project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MapFragment.java
changeset 10017 de822cd3df3a
parent 7584 7831c84cc644
equal deleted inserted replaced
10015:4feced261c68 10017:de822cd3df3a
    48 import android.widget.TableRow;
    48 import android.widget.TableRow;
    49 import android.widget.Toast;
    49 import android.widget.Toast;
    50 
    50 
    51 /**
    51 /**
    52  * Display a map preview, and configuration options for the map.
    52  * Display a map preview, and configuration options for the map.
    53  * 
    53  *
    54  * Mostly for layout reasons, this does not include the theme setting, which
    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.
    55  * (arguably) is more a map setting than a general game setting.
    56  */
    56  */
    57 public class MapFragment extends Fragment {
    57 public class MapFragment extends Fragment {
    58 	private Spinner mapTypeSpinner, mapNameSpinner, templateSpinner, mazeSizeSpinner;
    58     private Spinner mapTypeSpinner, mapNameSpinner, templateSpinner, mazeSizeSpinner;
    59 	private TableRow nameRow, templateRow, mazeSizeRow;
    59     private TableRow nameRow, templateRow, mazeSizeRow;
    60 	private ImageView mapPreview;
    60     private ImageView mapPreview;
    61 	
    61 
    62 	private List<MapFile> mapFiles;
    62     private List<MapFile> mapFiles;
    63 	private RoomStateManager stateManager;
    63     private RoomStateManager stateManager;
    64 	private Random random = new Random();
    64     private Random random = new Random();
    65 	private CalmDownHandler mapPreviewHandler;
    65     private CalmDownHandler mapPreviewHandler;
    66 	
    66 
    67 	/*
    67     /*
    68 	 * Rendering the preview can take a few seconds on Android, so we want to prevent preview
    68      * Rendering the preview can take a few seconds on Android, so we want to prevent preview
    69 	 * requests from queueing up if maps are changed quickly. So if there is already a preview
    69      * requests from queueing up if maps are changed quickly. So if there is already a preview
    70 	 * being generated, we store our latest request in the newPreviewRequest variable instead.
    70      * being generated, we store our latest request in the newPreviewRequest variable instead.
    71 	 * Once the current preview is finished generating it will start on that one.
    71      * Once the current preview is finished generating it will start on that one.
    72 	 */
    72      */
    73 	private boolean previewGenerationInProgress;
    73     private boolean previewGenerationInProgress;
    74 	private MapRecipe newPreviewRequest;
    74     private MapRecipe newPreviewRequest;
    75 	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
    76 	
    76 
    77 	@Override
    77     @Override
    78 	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    78     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    79 		View v = inflater.inflate(R.layout.fragment_map, container, false);
    79         View v = inflater.inflate(R.layout.fragment_map, container, false);
    80 		final Context appContext = getActivity().getApplicationContext();
    80         final Context appContext = getActivity().getApplicationContext();
    81 
    81 
    82 		/*
    82         /*
    83 		 * This handler will start the map preview after none of the map settings
    83          * This handler will start the map preview after none of the map settings
    84 		 * have been updated for a short time.
    84          * have been updated for a short time.
    85 		 */
    85          */
    86 		mapPreviewHandler = new CalmDownHandler(getActivity().getMainLooper(), new Runnable() {
    86         mapPreviewHandler = new CalmDownHandler(getActivity().getMainLooper(), new Runnable() {
    87 			public void run() {
    87             public void run() {
    88 				if(!previewGenerationInProgress) {
    88                 if(!previewGenerationInProgress) {
    89 					mapPreview.setImageResource(R.drawable.roomlist_preparing);
    89                     mapPreview.setImageResource(R.drawable.roomlist_preparing);
    90 					MapPreviewGenerator.startPreviewGeneration(appContext, stateManager.getMapRecipe(), mapPreviewListener);
    90                     MapPreviewGenerator.startPreviewGeneration(appContext, stateManager.getMapRecipe(), mapPreviewListener);
    91 					previewGenerationInProgress = true;
    91                     previewGenerationInProgress = true;
    92 				} else {
    92                 } else {
    93 					newPreviewRequest = stateManager.getMapRecipe();
    93                     newPreviewRequest = stateManager.getMapRecipe();
    94 				}
    94                 }
    95 			}
    95             }
    96 		}, 250);
    96         }, 250);
    97 		
    97 
    98 		nameRow = (TableRow) v.findViewById(R.id.rowMapName);
    98         nameRow = (TableRow) v.findViewById(R.id.rowMapName);
    99 		templateRow = (TableRow) v.findViewById(R.id.rowTemplateFilter);
    99         templateRow = (TableRow) v.findViewById(R.id.rowTemplateFilter);
   100 		mazeSizeRow = (TableRow) v.findViewById(R.id.rowMazeSize);
   100         mazeSizeRow = (TableRow) v.findViewById(R.id.rowMazeSize);
   101 		mapPreview = (ImageView) v.findViewById(R.id.mapPreview);
   101         mapPreview = (ImageView) v.findViewById(R.id.mapPreview);
   102 		mapPreview.setImageDrawable(null);;
   102         mapPreview.setImageDrawable(null);;
   103 		mapPreview.setOnClickListener(mapClickListener);
   103         mapPreview.setOnClickListener(mapClickListener);
   104 		
   104 
   105 		try {
   105         try {
   106 			mapFiles = FrontendDataUtils.getMaps(getActivity());
   106             mapFiles = FrontendDataUtils.getMaps(getActivity());
   107 		} catch (IOException e) {
   107         } catch (IOException e) {
   108 			Toast.makeText(getActivity().getApplicationContext(), R.string.error_missing_sdcard_or_files, Toast.LENGTH_LONG).show();
   108             Toast.makeText(getActivity().getApplicationContext(), R.string.error_missing_sdcard_or_files, Toast.LENGTH_LONG).show();
   109 			getActivity().finish();
   109             getActivity().finish();
   110 			return null;
   110             return null;
   111 		}
   111         }
   112 		Collections.sort(mapFiles, MapFile.MISSIONS_FIRST_NAME_ORDER);
   112         Collections.sort(mapFiles, MapFile.MISSIONS_FIRST_NAME_ORDER);
   113 		
   113 
   114 		List<String> mapNames = MapFile.toDisplayNameList(mapFiles, getResources());
   114         List<String> mapNames = MapFile.toDisplayNameList(mapFiles, getResources());
   115 		mapTypeSpinner = prepareSpinner(v, R.id.spinMapType, Arrays.asList(getResources().getStringArray(R.array.map_types)), mapTypeSelectedListener);
   115         mapTypeSpinner = prepareSpinner(v, R.id.spinMapType, Arrays.asList(getResources().getStringArray(R.array.map_types)), mapTypeSelectedListener);
   116 		mapNameSpinner = prepareSpinner(v, R.id.spinMapName, mapNames, mapNameSelectedListener);
   116         mapNameSpinner = prepareSpinner(v, R.id.spinMapName, mapNames, mapNameSelectedListener);
   117 		templateSpinner = prepareSpinner(v, R.id.spinTemplateFilter, Arrays.asList(getResources().getStringArray(R.array.map_templates)), mapTemplateSelectedListener);
   117         templateSpinner = prepareSpinner(v, R.id.spinTemplateFilter, Arrays.asList(getResources().getStringArray(R.array.map_templates)), mapTemplateSelectedListener);
   118 		mazeSizeSpinner = prepareSpinner(v, R.id.spinMazeSize, Arrays.asList(getResources().getStringArray(R.array.map_maze_sizes)), mazeSizeSelectedListener);
   118         mazeSizeSpinner = prepareSpinner(v, R.id.spinMazeSize, Arrays.asList(getResources().getStringArray(R.array.map_maze_sizes)), mazeSizeSelectedListener);
   119 
   119 
   120 		stateManager.addListener(roomStateChangeListener);
   120         stateManager.addListener(roomStateChangeListener);
   121 		currentMap = stateManager.getMapRecipe();
   121         currentMap = stateManager.getMapRecipe();
   122 		if(currentMap != null) {
   122         if(currentMap != null) {
   123 			updateDisplay(currentMap);
   123             updateDisplay(currentMap);
   124 		}
   124         }
   125 		setChiefState(stateManager.getChiefStatus());
   125         setChiefState(stateManager.getChiefStatus());
   126 		mapPreviewHandler.activity();
   126         mapPreviewHandler.activity();
   127 		return v;
   127         return v;
   128 	}
   128     }
   129 	
   129 
   130 	private static Spinner prepareSpinner(View v, int id, List<String> items, OnItemSelectedListener itemSelectedListener) {
   130     private static Spinner prepareSpinner(View v, int id, List<String> items, OnItemSelectedListener itemSelectedListener) {
   131 		Spinner spinner = (Spinner)v.findViewById(id);
   131         Spinner spinner = (Spinner)v.findViewById(id);
   132 		ArrayAdapter<String> adapter = new ArrayAdapter<String>(v.getContext(), R.layout.listview_item, items);
   132         ArrayAdapter<String> adapter = new ArrayAdapter<String>(v.getContext(), R.layout.listview_item, items);
   133 		adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
   133         adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
   134 		spinner.setAdapter(adapter);
   134         spinner.setAdapter(adapter);
   135 		spinner.setOnItemSelectedListener(itemSelectedListener);
   135         spinner.setOnItemSelectedListener(itemSelectedListener);
   136 		return spinner;
   136         return spinner;
   137 	}
   137     }
   138 	
   138 
   139 	@Override
   139     @Override
   140 	public void onCreate(Bundle savedInstanceState) {
   140     public void onCreate(Bundle savedInstanceState) {
   141 		super.onCreate(savedInstanceState);
   141         super.onCreate(savedInstanceState);
   142 		try {
   142         try {
   143 			stateManager = ((RoomStateManager.Provider)getActivity()).getRoomStateManager();
   143             stateManager = ((RoomStateManager.Provider)getActivity()).getRoomStateManager();
   144 		} catch(ClassCastException e) {
   144         } catch(ClassCastException e) {
   145 			throw new RuntimeException("Hosting activity must implement RoomStateManager.Provider.", e);
   145             throw new RuntimeException("Hosting activity must implement RoomStateManager.Provider.", e);
   146 		}
   146         }
   147 	}
   147     }
   148 	
   148 
   149 	@Override
   149     @Override
   150 	public void onDestroy() {
   150     public void onDestroy() {
   151 		super.onDestroy();
   151         super.onDestroy();
   152 		mapPreviewHandler.stop();
   152         mapPreviewHandler.stop();
   153 		newPreviewRequest = null;
   153         newPreviewRequest = null;
   154 		
   154 
   155 		stateManager.removeListener(roomStateChangeListener);
   155         stateManager.removeListener(roomStateChangeListener);
   156 	}
   156     }
   157 	
   157 
   158 	private void setChiefState(boolean chiefState) {
   158     private void setChiefState(boolean chiefState) {
   159 		mapTypeSpinner.setEnabled(chiefState);
   159         mapTypeSpinner.setEnabled(chiefState);
   160 		mapNameSpinner.setEnabled(chiefState);
   160         mapNameSpinner.setEnabled(chiefState);
   161 		templateSpinner.setEnabled(chiefState);
   161         templateSpinner.setEnabled(chiefState);
   162 		mazeSizeSpinner.setEnabled(chiefState);
   162         mazeSizeSpinner.setEnabled(chiefState);
   163 		mapPreview.setEnabled(chiefState);
   163         mapPreview.setEnabled(chiefState);
   164 		
   164 
   165 		if(chiefState) {
   165         if(chiefState) {
   166 			sendMapnameAndGenerator();
   166             sendMapnameAndGenerator();
   167 			stateManager.changeMapTemplate(templateSpinner.getSelectedItemPosition());
   167             stateManager.changeMapTemplate(templateSpinner.getSelectedItemPosition());
   168 			stateManager.changeMazeSize(mazeSizeSpinner.getSelectedItemPosition());
   168             stateManager.changeMazeSize(mazeSizeSpinner.getSelectedItemPosition());
   169 		}
   169         }
   170 	}
   170     }
   171 	
   171 
   172 	private void updateDisplay(MapRecipe map) {
   172     private void updateDisplay(MapRecipe map) {
   173 		nameRow.setVisibility(map.mapgen == Frontlib.MAPGEN_NAMED ? View.VISIBLE : View.GONE);
   173         nameRow.setVisibility(map.mapgen == Frontlib.MAPGEN_NAMED ? View.VISIBLE : View.GONE);
   174 		templateRow.setVisibility(map.mapgen == Frontlib.MAPGEN_REGULAR ? View.VISIBLE : View.GONE);
   174         templateRow.setVisibility(map.mapgen == Frontlib.MAPGEN_REGULAR ? View.VISIBLE : View.GONE);
   175 		mazeSizeRow.setVisibility(map.mapgen == Frontlib.MAPGEN_MAZE ? View.VISIBLE : View.GONE);
   175         mazeSizeRow.setVisibility(map.mapgen == Frontlib.MAPGEN_MAZE ? View.VISIBLE : View.GONE);
   176 		
   176 
   177 		mapTypeSpinner.setSelection(map.mapgen);
   177         mapTypeSpinner.setSelection(map.mapgen);
   178 		int mapPosition = findMapPosition(mapFiles, map.name);
   178         int mapPosition = findMapPosition(mapFiles, map.name);
   179 		if(mapPosition >= 0) {
   179         if(mapPosition >= 0) {
   180 			mapNameSpinner.setSelection(mapPosition);
   180             mapNameSpinner.setSelection(mapPosition);
   181 		}
   181         }
   182 		templateSpinner.setSelection(map.templateFilter);
   182         templateSpinner.setSelection(map.templateFilter);
   183 		mazeSizeSpinner.setSelection(map.mazeSize);
   183         mazeSizeSpinner.setSelection(map.mazeSize);
   184 	}
   184     }
   185 	
   185 
   186 	private static int findMapPosition(List<MapFile> mapFiles, String mapName) {
   186     private static int findMapPosition(List<MapFile> mapFiles, String mapName) {
   187 		for(int i=0; i<mapFiles.size(); i++) {
   187         for(int i=0; i<mapFiles.size(); i++) {
   188 			if(mapName.equals(mapFiles.get(i).name)) {
   188             if(mapName.equals(mapFiles.get(i).name)) {
   189 				return i;
   189                 return i;
   190 			}
   190             }
   191 		}
   191         }
   192 		return -1;
   192         return -1;
   193 	}
   193     }
   194 	
   194 
   195 	private void sendMapnameAndGenerator() {
   195     private void sendMapnameAndGenerator() {
   196 		int mapType = mapTypeSpinner.getSelectedItemPosition();
   196         int mapType = mapTypeSpinner.getSelectedItemPosition();
   197 		String mapName = mapFiles.get(mapNameSpinner.getSelectedItemPosition()).name;
   197         String mapName = mapFiles.get(mapNameSpinner.getSelectedItemPosition()).name;
   198 		stateManager.changeMapNameAndGenerator(MapRecipe.mapnameForGenerator(mapType, mapName));
   198         stateManager.changeMapNameAndGenerator(MapRecipe.mapnameForGenerator(mapType, mapName));
   199 	}
   199     }
   200 	
   200 
   201 	private final OnItemSelectedListener mapTypeSelectedListener = new OnItemSelectedListener() {
   201     private final OnItemSelectedListener mapTypeSelectedListener = new OnItemSelectedListener() {
   202 		public void onItemSelected(AdapterView<?> adapter, View v, int position, long arg3) {
   202         public void onItemSelected(AdapterView<?> adapter, View v, int position, long arg3) {
   203 			sendMapnameAndGenerator();
   203             sendMapnameAndGenerator();
   204 		}
   204         }
   205 		public void onNothingSelected(AdapterView<?> arg0) {}
   205         public void onNothingSelected(AdapterView<?> arg0) {}
   206 	};
   206     };
   207 	
   207 
   208 	private final OnItemSelectedListener mapNameSelectedListener = new OnItemSelectedListener() {
   208     private final OnItemSelectedListener mapNameSelectedListener = new OnItemSelectedListener() {
   209 		public void onItemSelected(AdapterView<?> adapter, View v, int position, long arg3) {
   209         public void onItemSelected(AdapterView<?> adapter, View v, int position, long arg3) {
   210 			sendMapnameAndGenerator();
   210             sendMapnameAndGenerator();
   211 		}
   211         }
   212 		public void onNothingSelected(AdapterView<?> arg0) {}
   212         public void onNothingSelected(AdapterView<?> arg0) {}
   213 	};
   213     };
   214 	
   214 
   215 	private final OnItemSelectedListener mapTemplateSelectedListener = new OnItemSelectedListener() {
   215     private final OnItemSelectedListener mapTemplateSelectedListener = new OnItemSelectedListener() {
   216 		public void onItemSelected(AdapterView<?> adapter, View v, int position, long arg3) {
   216         public void onItemSelected(AdapterView<?> adapter, View v, int position, long arg3) {
   217 			stateManager.changeMapTemplate(position);
   217             stateManager.changeMapTemplate(position);
   218 		}
   218         }
   219 		public void onNothingSelected(AdapterView<?> arg0) {}
   219         public void onNothingSelected(AdapterView<?> arg0) {}
   220 	};
   220     };
   221 	
   221 
   222 	private final OnItemSelectedListener mazeSizeSelectedListener = new OnItemSelectedListener() {
   222     private final OnItemSelectedListener mazeSizeSelectedListener = new OnItemSelectedListener() {
   223 		public void onItemSelected(AdapterView<?> adapter, View v, int position, long arg3) {
   223         public void onItemSelected(AdapterView<?> adapter, View v, int position, long arg3) {
   224 			stateManager.changeMazeSize(position);
   224             stateManager.changeMazeSize(position);
   225 		}
   225         }
   226 		public void onNothingSelected(AdapterView<?> arg0) {}
   226         public void onNothingSelected(AdapterView<?> arg0) {}
   227 	};
   227     };
   228 	
   228 
   229 	private final OnClickListener mapClickListener = new OnClickListener() {
   229     private final OnClickListener mapClickListener = new OnClickListener() {
   230 		public void onClick(View v) {
   230         public void onClick(View v) {
   231 			stateManager.changeMapSeed(MapRecipe.makeRandomSeed());
   231             stateManager.changeMapSeed(MapRecipe.makeRandomSeed());
   232 			if(mapTypeSpinner.getSelectedItemPosition() == Frontlib.MAPGEN_NAMED) {
   232             if(mapTypeSpinner.getSelectedItemPosition() == Frontlib.MAPGEN_NAMED) {
   233 				mapNameSpinner.setSelection(random.nextInt(mapNameSpinner.getCount()));
   233                 mapNameSpinner.setSelection(random.nextInt(mapNameSpinner.getCount()));
   234 			}
   234             }
   235 		}
   235         }
   236 	};
   236     };
   237 	
   237 
   238 	private final RoomStateManager.Listener roomStateChangeListener = new RoomStateManager.ListenerAdapter() {
   238     private final RoomStateManager.Listener roomStateChangeListener = new RoomStateManager.ListenerAdapter() {
   239 		@Override
   239         @Override
   240 		public void onChiefStatusChanged(boolean isChief) {
   240         public void onChiefStatusChanged(boolean isChief) {
   241 			setChiefState(isChief);
   241             setChiefState(isChief);
   242 		};
   242         };
   243 		
   243 
   244 		@Override
   244         @Override
   245 		public void onMapChanged(MapRecipe recipe) {
   245         public void onMapChanged(MapRecipe recipe) {
   246 			// Only trigger a preview update if a relevant field changed (not theme)
   246             // Only trigger a preview update if a relevant field changed (not theme)
   247 			if(currentMap==null
   247             if(currentMap==null
   248 					|| currentMap.mapgen != recipe.mapgen
   248                     || currentMap.mapgen != recipe.mapgen
   249 					|| currentMap.mazeSize != recipe.mazeSize
   249                     || currentMap.mazeSize != recipe.mazeSize
   250 					|| !currentMap.name.equals(recipe.name)
   250                     || !currentMap.name.equals(recipe.name)
   251 					|| !currentMap.seed.equals(recipe.seed)
   251                     || !currentMap.seed.equals(recipe.seed)
   252 					|| currentMap.templateFilter != recipe.templateFilter
   252                     || currentMap.templateFilter != recipe.templateFilter
   253 					|| !Arrays.equals(currentMap.getDrawData(), recipe.getDrawData())) {
   253                     || !Arrays.equals(currentMap.getDrawData(), recipe.getDrawData())) {
   254 				mapPreviewHandler.activity();
   254                 mapPreviewHandler.activity();
   255 			}
   255             }
   256 			updateDisplay(recipe);
   256             updateDisplay(recipe);
   257 			currentMap = recipe;
   257             currentMap = recipe;
   258 		};
   258         };
   259 	};
   259     };
   260 	
   260 
   261 	private MapPreviewGenerator.Listener mapPreviewListener = new MapPreviewGenerator.Listener() {
   261     private MapPreviewGenerator.Listener mapPreviewListener = new MapPreviewGenerator.Listener() {
   262 		public void onMapPreviewResult(Drawable preview) {
   262         public void onMapPreviewResult(Drawable preview) {
   263 			if(newPreviewRequest != null) {
   263             if(newPreviewRequest != null) {
   264 				MapPreviewGenerator.startPreviewGeneration(getActivity().getApplicationContext(), newPreviewRequest, mapPreviewListener);
   264                 MapPreviewGenerator.startPreviewGeneration(getActivity().getApplicationContext(), newPreviewRequest, mapPreviewListener);
   265 				newPreviewRequest = null;
   265                 newPreviewRequest = null;
   266 			} else {
   266             } else {
   267 				if(mapPreview != null) {
   267                 if(mapPreview != null) {
   268 					mapPreview.setImageDrawable(preview);
   268                     mapPreview.setImageDrawable(preview);
   269 				}
   269                 }
   270 				previewGenerationInProgress = false;
   270                 previewGenerationInProgress = false;
   271 			}
   271             }
   272 		}
   272         }
   273 	};
   273     };
   274 }
   274 }