1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.replica.replicaisland; 18 19 import android.app.ListActivity; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.media.AudioManager; 23 import android.os.Bundle; 24 import android.view.KeyEvent; 25 import android.view.LayoutInflater; 26 import android.view.Menu; 27 import android.view.MenuItem; 28 import android.view.View; 29 import android.view.ViewGroup; 30 import android.view.animation.Animation; 31 import android.view.animation.AnimationUtils; 32 import android.widget.ArrayAdapter; 33 import android.widget.ListView; 34 import android.widget.TextView; 35 36 import java.lang.reflect.InvocationTargetException; 37 import java.util.ArrayList; 38 import java.util.Comparator; 39 import java.util.List; 40 41 public class LevelSelectActivity extends ListActivity { 42 private final static int UNLOCK_ALL_LEVELS_ID = 0; 43 private final static int UNLOCK_NEXT_LEVEL_ID = 1; 44 private final static LevelDataComparator sLevelComparator = new LevelDataComparator(); 45 private ArrayList<LevelMetaData> mLevelData; 46 private Animation mButtonFlickerAnimation; 47 private boolean mLevelSelected; 48 49 private class LevelMetaData { 50 public LevelTree.Level level; 51 public int x; 52 public int y; 53 boolean enabled; 54 55 @Override toString()56 public String toString() { 57 return level.name; 58 } 59 } 60 61 private class DisableItemArrayAdapter<T> extends ArrayAdapter<T> { 62 private static final int TYPE_ENABLED = 0; 63 private static final int TYPE_DISABLED = 1; 64 private static final int TYPE_COMPLETED = 2; 65 private static final int TYPE_COUNT = 3; 66 67 private int mRowResource; 68 private int mDisabledRowResource; 69 private int mCompletedRowResource; 70 private Context mContext; 71 private int mTextViewResource; 72 private int mTextViewResource2; 73 DisableItemArrayAdapter(Context context, int resource, int disabledResource, int completedResource, int textViewResourceId, int textViewResourceId2, List<T> objects)74 public DisableItemArrayAdapter(Context context, int resource, int disabledResource, int completedResource, 75 int textViewResourceId, int textViewResourceId2, List<T> objects) { 76 super(context, resource, textViewResourceId, objects); 77 mRowResource = resource; 78 mDisabledRowResource = disabledResource; 79 mCompletedRowResource = completedResource; 80 mContext = context; 81 mTextViewResource = textViewResourceId; 82 mTextViewResource2 = textViewResourceId2; 83 } 84 85 @Override isEnabled(int position)86 public boolean isEnabled(int position) { 87 // TODO: do we have separators in this list? 88 return mLevelData.get(position).enabled; 89 } 90 91 92 @Override areAllItemsEnabled()93 public boolean areAllItemsEnabled() { 94 return false; 95 } 96 97 @Override getItemViewType(int position)98 public int getItemViewType(int position) { 99 int type = TYPE_ENABLED; 100 LevelMetaData level = mLevelData.get(position); 101 if (level != null) { 102 if (!level.enabled) { 103 if (level.level.completed) { 104 type = TYPE_COMPLETED; 105 } else { 106 type = TYPE_DISABLED; 107 } 108 } 109 } 110 return type; 111 } 112 113 @Override getViewTypeCount()114 public int getViewTypeCount() { 115 return TYPE_COUNT; 116 } 117 118 @Override hasStableIds()119 public boolean hasStableIds() { 120 return true; 121 } 122 123 @Override isEmpty()124 public boolean isEmpty() { 125 return mLevelData.size() > 0; 126 } 127 128 @Override getView(int position, View convertView, ViewGroup parent)129 public View getView (int position, View convertView, ViewGroup parent) { 130 View sourceView = null; 131 if (mLevelData.get(position).enabled) { 132 if (convertView != null && convertView.getId() == mRowResource) { 133 sourceView = convertView; 134 } else { 135 sourceView = LayoutInflater.from(mContext).inflate( 136 mRowResource, parent, false); 137 } 138 } else if (mLevelData.get(position).level.completed) { 139 if (convertView != null && convertView.getId() == mCompletedRowResource) { 140 sourceView = convertView; 141 } else { 142 sourceView = LayoutInflater.from(mContext).inflate( 143 mCompletedRowResource, parent, false); 144 } 145 } else { 146 if (convertView != null && convertView.getId() == mDisabledRowResource) { 147 sourceView = convertView; 148 } else { 149 sourceView = LayoutInflater.from(mContext).inflate( 150 mDisabledRowResource, parent, false); 151 } 152 } 153 TextView view = (TextView)sourceView.findViewById(mTextViewResource); 154 if (view != null) { 155 view.setText(mLevelData.get(position).level.name); 156 } 157 158 TextView view2 = (TextView)sourceView.findViewById(mTextViewResource2); 159 if (view2 != null) { 160 view2.setText(mLevelData.get(position).level.timeStamp); 161 } 162 return sourceView; 163 } 164 165 } 166 167 /** Called when the activity is first created. */ 168 @Override onCreate(Bundle savedInstanceState)169 public void onCreate(Bundle savedInstanceState) { 170 super.onCreate(savedInstanceState); 171 setContentView(R.layout.level_select); 172 mLevelData = new ArrayList<LevelMetaData>(); 173 174 if (getIntent().getBooleanExtra("unlockAll", false)) { 175 generateLevelList(false); 176 for (LevelMetaData level : mLevelData) { 177 level.enabled = true; 178 } 179 } else { 180 generateLevelList(true); 181 } 182 183 184 DisableItemArrayAdapter<LevelMetaData> adapter = new DisableItemArrayAdapter<LevelMetaData>( 185 this, R.layout.level_select_row, R.layout.level_select_disabled_row, R.layout.level_select_completed_row, 186 R.id.title, R.id.time, mLevelData); 187 188 adapter.sort(sLevelComparator); 189 190 setListAdapter(adapter); 191 192 mButtonFlickerAnimation = AnimationUtils.loadAnimation(this, R.anim.button_flicker); 193 194 mLevelSelected = false; 195 196 // Keep the volume control type consistent across all activities. 197 setVolumeControlStream(AudioManager.STREAM_MUSIC); 198 } 199 generateLevelList(boolean onlyAllowThePast)200 protected void generateLevelList(boolean onlyAllowThePast) { 201 final int count = LevelTree.levels.size(); 202 boolean oneBranchUnlocked = false; 203 for (int x = 0; x < count; x++) { 204 boolean anyUnlocksThisBranch = false; 205 final LevelTree.LevelGroup group = LevelTree.levels.get(x); 206 for (int y = 0; y < group.levels.size(); y++) { 207 LevelTree.Level level = group.levels.get(y); 208 boolean enabled = false; 209 if (!level.completed && !oneBranchUnlocked) { 210 enabled = true; 211 anyUnlocksThisBranch = true; 212 } 213 if (enabled || level.completed || !onlyAllowThePast || (onlyAllowThePast && level.inThePast)) { 214 addItem(level, x, y, enabled); 215 } 216 } 217 if (anyUnlocksThisBranch) { 218 oneBranchUnlocked = true; 219 } 220 } 221 } 222 unlockNext()223 protected void unlockNext() { 224 final int count = LevelTree.levels.size(); 225 for (int x = 0; x < count; x++) { 226 final LevelTree.LevelGroup group = LevelTree.levels.get(x); 227 for (int y = 0; y < group.levels.size(); y++) { 228 LevelTree.Level level = group.levels.get(y); 229 if (!level.completed) { 230 level.completed = true; 231 return; 232 } 233 } 234 235 } 236 } 237 238 239 @Override onListItemClick(ListView l, View v, int position, long id)240 protected void onListItemClick(ListView l, View v, int position, long id) { 241 if (!mLevelSelected) { 242 super.onListItemClick(l, v, position, id); 243 LevelMetaData selectedLevel = mLevelData.get(position); 244 if (selectedLevel.enabled) { 245 mLevelSelected = true; 246 Intent intent = new Intent(); 247 248 intent.putExtra("resource", selectedLevel.level.resource); 249 intent.putExtra("row", selectedLevel.x); 250 intent.putExtra("index", selectedLevel.y); 251 TextView text = (TextView)v.findViewById(R.id.title); 252 if (text != null) { 253 text.startAnimation(mButtonFlickerAnimation); 254 mButtonFlickerAnimation.setAnimationListener(new EndActivityAfterAnimation(intent)); 255 } else { 256 setResult(RESULT_OK, intent); 257 finish(); 258 if (UIConstants.mOverridePendingTransition != null) { 259 try { 260 UIConstants.mOverridePendingTransition.invoke(LevelSelectActivity.this, R.anim.activity_fade_in, R.anim.activity_fade_out); 261 } catch (InvocationTargetException ite) { 262 DebugLog.d("Activity Transition", "Invocation Target Exception"); 263 } catch (IllegalAccessException ie) { 264 DebugLog.d("Activity Transition", "Illegal Access Exception"); 265 } 266 } 267 } 268 } 269 } 270 } 271 addItem(LevelTree.Level level, int x, int y, boolean enabled)272 private void addItem(LevelTree.Level level, int x, int y, boolean enabled) { 273 LevelMetaData data = new LevelMetaData(); 274 data.level = level; 275 data.x = x; 276 data.y = y; 277 data.enabled = enabled; 278 mLevelData.add(data); 279 } 280 281 @Override onCreateOptionsMenu(Menu menu)282 public boolean onCreateOptionsMenu(Menu menu) { 283 super.onCreateOptionsMenu(menu); 284 boolean handled = false; 285 if (AndouKun.VERSION < 0) { 286 menu.add(0, UNLOCK_NEXT_LEVEL_ID, 0, R.string.unlock_next_level); 287 menu.add(0, UNLOCK_ALL_LEVELS_ID, 0, R.string.unlock_levels); 288 289 handled = true; 290 } 291 return handled; 292 } 293 294 @Override onMenuItemSelected(int featureId, MenuItem item)295 public boolean onMenuItemSelected(int featureId, MenuItem item) { 296 switch(item.getItemId()) { 297 case UNLOCK_NEXT_LEVEL_ID: 298 unlockNext(); 299 mLevelData.clear(); 300 generateLevelList(false); 301 ((ArrayAdapter)getListAdapter()).sort(sLevelComparator); 302 ((ArrayAdapter)getListAdapter()).notifyDataSetChanged(); 303 304 return true; 305 306 case UNLOCK_ALL_LEVELS_ID: 307 // Regenerate the level list to remove the past-only filter. 308 mLevelData.clear(); 309 generateLevelList(false); 310 for (LevelMetaData level : mLevelData) { 311 level.enabled = true; 312 } 313 314 ((ArrayAdapter)getListAdapter()).sort(sLevelComparator); 315 ((ArrayAdapter)getListAdapter()).notifyDataSetChanged(); 316 return true; 317 } 318 319 return super.onMenuItemSelected(featureId, item); 320 } 321 322 323 @Override onKeyDown(int keyCode, KeyEvent event)324 public boolean onKeyDown(int keyCode, KeyEvent event) { 325 boolean result = false; 326 if (keyCode == KeyEvent.KEYCODE_BACK) { 327 result = true; 328 } 329 return result; 330 } 331 332 @Override onKeyUp(int keyCode, KeyEvent event)333 public boolean onKeyUp(int keyCode, KeyEvent event) { 334 boolean result = false; 335 if (keyCode == KeyEvent.KEYCODE_BACK) { 336 result = true; 337 } 338 return result; 339 } 340 341 342 /** Comparator for level meta data. */ 343 private final static class LevelDataComparator implements Comparator<LevelMetaData> { compare(final LevelMetaData object1, final LevelMetaData object2)344 public int compare(final LevelMetaData object1, final LevelMetaData object2) { 345 int result = 0; 346 if (object1 == null && object2 != null) { 347 result = 1; 348 } else if (object1 != null && object2 == null) { 349 result = -1; 350 } else if (object1 != null && object2 != null) { 351 result = object1.level.timeStamp.compareTo(object2.level.timeStamp); 352 } 353 return result; 354 } 355 } 356 357 protected class EndActivityAfterAnimation implements Animation.AnimationListener { 358 private Intent mIntent; 359 EndActivityAfterAnimation(Intent intent)360 EndActivityAfterAnimation(Intent intent) { 361 mIntent = intent; 362 } 363 364 onAnimationEnd(Animation animation)365 public void onAnimationEnd(Animation animation) { 366 setResult(RESULT_OK, mIntent); 367 finish(); 368 } 369 onAnimationRepeat(Animation animation)370 public void onAnimationRepeat(Animation animation) { 371 // TODO Auto-generated method stub 372 373 } 374 onAnimationStart(Animation animation)375 public void onAnimationStart(Animation animation) { 376 // TODO Auto-generated method stub 377 378 } 379 380 } 381 } 382 383