project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MapFragment.java
changeset 7584 7831c84cc644
parent 7582 714310efad8f
child 10017 de822cd3df3a
equal deleted inserted replaced
7582:714310efad8f 7584:7831c84cc644
       
     1 /*
       
     2  * Hedgewars for Android. An Android port of Hedgewars, a free turn based strategy game
       
     3  * Copyright (C) 2012 Simeon Maxein <smaxein@googlemail.com>
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or
       
     6  * modify it under the terms of the GNU General Public License
       
     7  * as published by the Free Software Foundation; either version 2
       
     8  * of the License, or (at your option) any later version.
       
     9  *
       
    10  * This program is distributed in the hope that it will be useful,
       
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    13  * GNU General Public License for more details.
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License
       
    16  * along with this program; if not, write to the Free Software
       
    17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
       
    18  */
       
    19 
     1 package org.hedgewars.hedgeroid;
    20 package org.hedgewars.hedgeroid;
     2 
    21 
     3 import java.io.IOException;
    22 import java.io.IOException;
     4 import java.util.Arrays;
    23 import java.util.Arrays;
     5 import java.util.Collections;
    24 import java.util.Collections;
     9 import org.hedgewars.hedgeroid.R;
    28 import org.hedgewars.hedgeroid.R;
    10 import org.hedgewars.hedgeroid.Datastructures.FrontendDataUtils;
    29 import org.hedgewars.hedgeroid.Datastructures.FrontendDataUtils;
    11 import org.hedgewars.hedgeroid.Datastructures.MapFile;
    30 import org.hedgewars.hedgeroid.Datastructures.MapFile;
    12 import org.hedgewars.hedgeroid.Datastructures.MapRecipe;
    31 import org.hedgewars.hedgeroid.Datastructures.MapRecipe;
    13 import org.hedgewars.hedgeroid.frontlib.Frontlib;
    32 import org.hedgewars.hedgeroid.frontlib.Frontlib;
       
    33 import org.hedgewars.hedgeroid.util.CalmDownHandler;
    14 
    34 
    15 import android.content.Context;
    35 import android.content.Context;
    16 import android.graphics.drawable.Drawable;
    36 import android.graphics.drawable.Drawable;
    17 import android.os.Bundle;
    37 import android.os.Bundle;
    18 import android.os.Handler;
       
    19 import android.os.Looper;
       
    20 import android.os.Message;
       
    21 import android.support.v4.app.Fragment;
    38 import android.support.v4.app.Fragment;
    22 import android.view.LayoutInflater;
    39 import android.view.LayoutInflater;
    23 import android.view.View;
    40 import android.view.View;
    24 import android.view.View.OnClickListener;
    41 import android.view.View.OnClickListener;
    25 import android.view.ViewGroup;
    42 import android.view.ViewGroup;
    29 import android.widget.ImageView;
    46 import android.widget.ImageView;
    30 import android.widget.Spinner;
    47 import android.widget.Spinner;
    31 import android.widget.TableRow;
    48 import android.widget.TableRow;
    32 import android.widget.Toast;
    49 import android.widget.Toast;
    33 
    50 
       
    51 /**
       
    52  * Display a map preview, and configuration options for the map.
       
    53  * 
       
    54  * Mostly for layout reasons, this does not include the theme setting, which
       
    55  * (arguably) is more a map setting than a general game setting.
       
    56  */
    34 public class MapFragment extends Fragment {
    57 public class MapFragment extends Fragment {
    35 	private Spinner mapTypeSpinner, mapNameSpinner, templateSpinner, mazeSizeSpinner;
    58 	private Spinner mapTypeSpinner, mapNameSpinner, templateSpinner, mazeSizeSpinner;
    36 	private TableRow nameRow, templateRow, mazeSizeRow;
    59 	private TableRow nameRow, templateRow, mazeSizeRow;
    37 	private ImageView mapPreview;
    60 	private ImageView mapPreview;
       
    61 	
    38 	private List<MapFile> mapFiles;
    62 	private List<MapFile> mapFiles;
    39 	private RoomStateManager stateManager;
    63 	private RoomStateManager stateManager;
    40 	private Random random = new Random();
    64 	private Random random = new Random();
    41 	private CalmDownHandler mapPreviewHandler;
    65 	private CalmDownHandler mapPreviewHandler;
    42 	
    66 	
    51 	private MapRecipe currentMap; // kept for reference on every change to find out what changed
    75 	private MapRecipe currentMap; // kept for reference on every change to find out what changed
    52 	
    76 	
    53 	@Override
    77 	@Override
    54 	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    78 	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    55 		View v = inflater.inflate(R.layout.fragment_map, container, false);
    79 		View v = inflater.inflate(R.layout.fragment_map, container, false);
    56 
       
    57 		final Context appContext = getActivity().getApplicationContext();
    80 		final Context appContext = getActivity().getApplicationContext();
       
    81 
       
    82 		/*
       
    83 		 * This handler will start the map preview after none of the map settings
       
    84 		 * have been updated for a short time.
       
    85 		 */
    58 		mapPreviewHandler = new CalmDownHandler(getActivity().getMainLooper(), new Runnable() {
    86 		mapPreviewHandler = new CalmDownHandler(getActivity().getMainLooper(), new Runnable() {
    59 			public void run() {
    87 			public void run() {
    60 				if(!previewGenerationInProgress) {
    88 				if(!previewGenerationInProgress) {
    61 					mapPreview.setImageResource(R.drawable.roomlist_preparing);
    89 					mapPreview.setImageResource(R.drawable.roomlist_preparing);
    62 					MapPreviewGenerator.startPreviewGeneration(appContext, stateManager.getMapRecipe(), mapPreviewListener);
    90 					MapPreviewGenerator.startPreviewGeneration(appContext, stateManager.getMapRecipe(), mapPreviewListener);
   120 	
   148 	
   121 	@Override
   149 	@Override
   122 	public void onDestroy() {
   150 	public void onDestroy() {
   123 		super.onDestroy();
   151 		super.onDestroy();
   124 		mapPreviewHandler.stop();
   152 		mapPreviewHandler.stop();
       
   153 		newPreviewRequest = null;
       
   154 		
   125 		stateManager.removeListener(roomStateChangeListener);
   155 		stateManager.removeListener(roomStateChangeListener);
   126 	}
   156 	}
   127 	
   157 	
   128 	private void setChiefState(boolean chiefState) {
   158 	private void setChiefState(boolean chiefState) {
   129 		mapTypeSpinner.setEnabled(chiefState);
   159 		mapTypeSpinner.setEnabled(chiefState);
   211 			setChiefState(isChief);
   241 			setChiefState(isChief);
   212 		};
   242 		};
   213 		
   243 		
   214 		@Override
   244 		@Override
   215 		public void onMapChanged(MapRecipe recipe) {
   245 		public void onMapChanged(MapRecipe recipe) {
       
   246 			// Only trigger a preview update if a relevant field changed (not theme)
   216 			if(currentMap==null
   247 			if(currentMap==null
   217 					|| currentMap.mapgen != recipe.mapgen
   248 					|| currentMap.mapgen != recipe.mapgen
   218 					|| currentMap.mazeSize != recipe.mazeSize
   249 					|| currentMap.mazeSize != recipe.mazeSize
   219 					|| !currentMap.name.equals(recipe.name)
   250 					|| !currentMap.name.equals(recipe.name)
   220 					|| !currentMap.seed.equals(recipe.seed)
   251 					|| !currentMap.seed.equals(recipe.seed)
   238 				}
   269 				}
   239 				previewGenerationInProgress = false;
   270 				previewGenerationInProgress = false;
   240 			}
   271 			}
   241 		}
   272 		}
   242 	};
   273 	};
   243 	
       
   244 	/**
       
   245 	 * This class allows you to define a runnable that is called when there has been no activity
       
   246 	 * for a set amount of time, where activity is determined by calls to the activity() method
       
   247 	 * of the handler. It is used here to update the map preview when there have been no updates
       
   248 	 * to the relevant map information for a time, to prevent triggering several updates at once
       
   249 	 * when different parts of the information change.
       
   250 	 */
       
   251 	private static final class CalmDownHandler extends Handler {
       
   252 		int runningMessagesCounter = 0;
       
   253 		final Runnable inactivityRunnable;
       
   254 		final long inactivityMs;
       
   255 		boolean stopped;
       
   256 
       
   257 		public CalmDownHandler(Looper looper, Runnable runnable, long inactivityMs) {
       
   258 			super(looper);
       
   259 			this.inactivityRunnable = runnable;
       
   260 			this.inactivityMs = inactivityMs;
       
   261 		}
       
   262 		
       
   263 		public void activity() {
       
   264 			runningMessagesCounter++;
       
   265 			sendMessageDelayed(obtainMessage(), inactivityMs);
       
   266 		}
       
   267 		
       
   268 		@Override
       
   269 		public void handleMessage(Message msg) {
       
   270 			runningMessagesCounter--;
       
   271 			if(runningMessagesCounter==0 && !stopped) {
       
   272 				inactivityRunnable.run();
       
   273 			}
       
   274 		}
       
   275 		
       
   276 		public void stop() {
       
   277 			stopped = true;
       
   278 		}
       
   279 	}
       
   280 }
   274 }