From 99b6c65ce3fc1e37c995676db7a0892d6358d2f7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Maty=C3=A1=C5=A1=20Latner?= <matyas.latner@nic.cz>
Date: Wed, 18 Mar 2015 14:42:48 +0100
Subject: [PATCH] #19 Saving and restoring last screen

 * save last screen
 * restore last screen after start
 * reset saved screen on Android for app shutdown from task manager
---
 .../nic/tablexia/android/AndroidLauncher.java |  2 +-
 core/src/cz/nic/tablexia/Tablexia.java        | 35 +++++++++-------
 .../cz/nic/tablexia/TablexiaApplication.java  |  7 +++-
 .../src/cz/nic/tablexia/TablexiaSettings.java | 42 ++++++++++++++++---
 .../screen/AbstractTablexiaScreen.java        | 11 +++--
 .../nic/tablexia/screen/ScreenDefinition.java |  8 +++-
 .../tablexia/screen/loader/LoaderScreen.java  |  2 +-
 core/src/cz/nic/tablexia/util/Utility.java    | 19 +++++++++
 .../nic/tablexia/desktop/DesktopLauncher.java |  2 +-
 ios/src/cz/nic/tablexia/IOSLauncher.java      |  2 +-
 10 files changed, 99 insertions(+), 31 deletions(-)
 create mode 100644 core/src/cz/nic/tablexia/util/Utility.java

diff --git a/android/src/cz/nic/tablexia/android/AndroidLauncher.java b/android/src/cz/nic/tablexia/android/AndroidLauncher.java
index 5627f27c1..018e4669b 100644
--- a/android/src/cz/nic/tablexia/android/AndroidLauncher.java
+++ b/android/src/cz/nic/tablexia/android/AndroidLauncher.java
@@ -13,6 +13,6 @@ public class AndroidLauncher extends AndroidApplication {
 	protected void onCreate (Bundle savedInstanceState) {
 		super.onCreate(savedInstanceState);
 		AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
-		initialize(new Tablexia(BuildConfig.DEBUG, getResources().getConfiguration().locale, BuildConfig.VERSION_NAME, BuildConfig.APPLICATION_ID), config);
+        initialize(new Tablexia(BuildConfig.DEBUG, getResources().getConfiguration().locale, BuildConfig.VERSION_NAME, BuildConfig.APPLICATION_ID, savedInstanceState == null), config);
 	}
 }
diff --git a/core/src/cz/nic/tablexia/Tablexia.java b/core/src/cz/nic/tablexia/Tablexia.java
index 8f2a38dae..f8a58a9c1 100644
--- a/core/src/cz/nic/tablexia/Tablexia.java
+++ b/core/src/cz/nic/tablexia/Tablexia.java
@@ -2,8 +2,6 @@ package cz.nic.tablexia;
 
 import com.badlogic.gdx.Application;
 import com.badlogic.gdx.Gdx;
-import com.badlogic.gdx.utils.reflect.ClassReflection;
-import com.badlogic.gdx.utils.reflect.ReflectionException;
 
 import net.engio.mbassy.listener.Handler;
 
@@ -20,33 +18,45 @@ import cz.nic.tablexia.loader.zip.ZipAssetLoader;
 import cz.nic.tablexia.menu.MainMenuContainer;
 import cz.nic.tablexia.screen.AbstractTablexiaScreen;
 import cz.nic.tablexia.screen.ScreenDefinition;
-import cz.nic.tablexia.screen.gamemenu.GameMenuScreen;
 import cz.nic.tablexia.screen.loader.LoaderScreen;
 import cz.nic.tablexia.util.Log;
+import cz.nic.tablexia.util.Utility;
 
 public class Tablexia extends TablexiaApplication {
 	
 	private boolean					loadingComplete         = false;
     private MainMenuContainer       mainMenuContainer;
     private ZipAssetLoader          zipAssetLoader;
+    private boolean                 resetState;
 
-    public Tablexia(boolean debug, Locale systemLocale, String versionName, String applicationId) {
+    public Tablexia(boolean debug, Locale systemLocale, String versionName, String applicationId, boolean resetState) {
         TablexiaSettings.init(debug, systemLocale, versionName, applicationId);
+        this.resetState = resetState;
     }
 
-    public Tablexia(String buildTypeKey, Locale systemLocale, String versionName, String applicationId) {
+    public Tablexia(String buildTypeKey, Locale systemLocale, String versionName, String applicationId, boolean resetState) {
         TablexiaSettings.init(buildTypeKey, systemLocale, versionName, applicationId);
+        this.resetState = resetState;
     }
 	
 	private void loadingComplete() {
 		if (!loadingComplete) {
 			loadingComplete = true;
-			setScreenIfIsDifferent(new GameMenuScreen(), ScreenTransaction.MOVE_LEFT);
+			showLastOrInitialScreen();
 			ApplicationBus.getInstance().publishAsync(new ApplicationLoadingCompleteEvent());
 		}
 	}
-	
-	private void prepareMainMenu() {
+
+    private void showLastOrInitialScreen() {
+        AbstractTablexiaScreen<?> lastScreen = TablexiaSettings.getInstance().getCurrentScreen();
+        if (lastScreen != null) {
+            setScreenIfIsDifferent(lastScreen, ScreenTransaction.FADE);
+        } else {
+            setScreenIfIsDifferent(Utility.getScreenForScreenClass(TablexiaSettings.INITIAL_SCREEN.getScreenClass()), ScreenTransaction.MOVE_LEFT);
+        }
+    }
+
+    private void prepareMainMenu() {
         mainMenuContainer = new MainMenuContainer(getStage().getWidth(), getStage().getHeight());
         getStage().addActor(mainMenuContainer);
 	}
@@ -105,7 +115,7 @@ public class Tablexia extends TablexiaApplication {
 	public void create () {
 		super.create();
 
-        TablexiaSettings.getInstance().loadPreferences();
+        TablexiaSettings.getInstance().loadPreferences(resetState);
         Log.setLoglevel(TablexiaSettings.getInstance().getLogLevel());
 		
 		// init event bus handlers
@@ -194,12 +204,7 @@ public class Tablexia extends TablexiaApplication {
 			
 			@Override
 			public void run() {
-				try {
-					AbstractTablexiaScreen<?> screen = (AbstractTablexiaScreen<?>) ClassReflection.getConstructors(screenClass)[0].newInstance(new Object[]{});
-					setScreenIfIsDifferent(screen, changeScreenEvent.getScreenTransaction());
-				} catch (ReflectionException e) {
-					Log.err(getClass(), "Cannot change screen! (Do you have only one parameter less constructor in screen?)", e);
-				}
+                setScreenIfIsDifferent(Utility.getScreenForScreenClass(screenClass), changeScreenEvent.getScreenTransaction());
 			}
 		});
 	}
diff --git a/core/src/cz/nic/tablexia/TablexiaApplication.java b/core/src/cz/nic/tablexia/TablexiaApplication.java
index 272246154..f3abd297c 100644
--- a/core/src/cz/nic/tablexia/TablexiaApplication.java
+++ b/core/src/cz/nic/tablexia/TablexiaApplication.java
@@ -167,8 +167,10 @@ public abstract class TablexiaApplication implements ApplicationListener {
      * @param screenTransaction screen transaction type
      */
     public void setScreenIfIsDifferent(AbstractTablexiaScreen<?> newScreen, ScreenTransaction screenTransaction) {
-        if (getScreen() == null || getScreen().getClass() != newScreen.getClass()) {
-            setScreen(newScreen, screenTransaction);
+        if (newScreen != null) {
+            if (getScreen() == null || getScreen().getClass() != newScreen.getClass()) {
+                setScreen(newScreen, screenTransaction);
+            }
         }
     }
 
@@ -223,6 +225,7 @@ public abstract class TablexiaApplication implements ApplicationListener {
     @SuppressWarnings("unchecked")
     private void processNewScreen(AbstractTablexiaScreen<?> newScreen) {
         if (newScreen != null) {
+            TablexiaSettings.getInstance().setCurrentScreen(newScreen);
             inputMultiplexer.addProcessor(newScreen.getInputProcessor());
             newScreen.show();
             newScreen.resize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
diff --git a/core/src/cz/nic/tablexia/TablexiaSettings.java b/core/src/cz/nic/tablexia/TablexiaSettings.java
index d0c83227b..328fa67de 100644
--- a/core/src/cz/nic/tablexia/TablexiaSettings.java
+++ b/core/src/cz/nic/tablexia/TablexiaSettings.java
@@ -2,21 +2,30 @@ package cz.nic.tablexia;
 
 import com.badlogic.gdx.Gdx;
 import com.badlogic.gdx.Preferences;
+import com.badlogic.gdx.utils.reflect.ClassReflection;
+import com.badlogic.gdx.utils.reflect.ReflectionException;
 
 import java.util.Locale;
 
 import cz.nic.tablexia.bus.ApplicationBus;
 import cz.nic.tablexia.bus.event.LocaleChangedEvent;
 import cz.nic.tablexia.loader.application.ApplicationTextManager;
+import cz.nic.tablexia.screen.AbstractTablexiaScreen;
+import cz.nic.tablexia.screen.ScreenDefinition;
 import cz.nic.tablexia.util.Log;
+import cz.nic.tablexia.util.Utility;
 
 public class TablexiaSettings {
 
-    private static final    int         DEFAULT_SCREEN_WIDTH        = 1000;
-    private static final    double      MAXIMUM_RATIO               = 9.0 / 16.0;
-    private static final    int         MIN_SCREEN_HEIGHT           = (int) (DEFAULT_SCREEN_WIDTH * MAXIMUM_RATIO);
-    private static final    boolean 	DEBUG_SHOW_BOUNDING_BOXES   = true;
+    private static final    int                 DEFAULT_SCREEN_WIDTH        = 1000;
+    private static final    double              MAXIMUM_RATIO               = 9.0 / 16.0;
+    private static final    int                 MIN_SCREEN_HEIGHT           = (int) (DEFAULT_SCREEN_WIDTH * MAXIMUM_RATIO);
+    private static final    boolean 	        DEBUG_SHOW_BOUNDING_BOXES   = true;
+
+    public  static final    ScreenDefinition 	INITIAL_SCREEN              = ScreenDefinition.GAME_MENU;
+
     public static final     String      LOCALE_KEY                  = "locale";
+    public static final     String      CURRENT_SCREEN_KEY          = "current_screen";
 
     private static final    String      IDE_BUILD_APPLICATION_ID    = "cz.nic.tablexia.debug";
     private static final    String      IDE_BUILD_VERSION_NAME      = "IDE-BUILD";
@@ -162,9 +171,13 @@ public class TablexiaSettings {
 
 //////////////////////////// LIBGDX PREFERENCES
 
-    public void loadPreferences() {
+    public void loadPreferences(boolean resetState) {
         preferences     = Gdx.app.getPreferences(getApplicationId());
         selectedLocale  = LocaleDefinition.getLocaleDefinitionForKey(preferences.getString(LOCALE_KEY));
+        if (resetState) {
+            preferences.remove(CURRENT_SCREEN_KEY);
+            preferences.flush();
+        }
     }
 
 
@@ -208,6 +221,25 @@ public class TablexiaSettings {
         return selectedLocale.getLocale();
     }
 
+    public void setCurrentScreen(AbstractTablexiaScreen screen) {
+        if (screen.hasState()) {
+            preferences.putString(CURRENT_SCREEN_KEY, screen.getClass().getName());
+            preferences.flush();
+        }
+    }
+
+    public AbstractTablexiaScreen<?> getCurrentScreen() {
+        String screenClassName = preferences.getString(CURRENT_SCREEN_KEY, null);
+        if (screenClassName != null) {
+            try {
+                return Utility.getScreenForScreenClass(ClassReflection.forName(screenClassName));
+            } catch (ReflectionException e) {
+                Log.err(getClass(), "Cannot load screen class: " + screenClassName, e);
+            }
+        }
+        return null;
+    }
+
 
 //////////////////////////// SCREEN SIZE
 
diff --git a/core/src/cz/nic/tablexia/screen/AbstractTablexiaScreen.java b/core/src/cz/nic/tablexia/screen/AbstractTablexiaScreen.java
index 31f3aec1f..b3727089c 100644
--- a/core/src/cz/nic/tablexia/screen/AbstractTablexiaScreen.java
+++ b/core/src/cz/nic/tablexia/screen/AbstractTablexiaScreen.java
@@ -44,6 +44,7 @@ public abstract class AbstractTablexiaScreen<T> extends ScreenAdapter {
     private boolean					loadingStarted;
     private boolean                 loadAsync;
     private boolean                 paused;
+    private boolean                 hasState;
 
     private static class TextManager extends TablexiaDataManager<I18NBundle> {
 
@@ -111,21 +112,25 @@ public abstract class AbstractTablexiaScreen<T> extends ScreenAdapter {
 
 
     public AbstractTablexiaScreen() {
-        this(true, TablexiaAssetManager.StorageType.EXTERNAL);
+        this(true, true, TablexiaAssetManager.StorageType.EXTERNAL);
     }
 	
-	public AbstractTablexiaScreen(boolean loadAsync, TablexiaAssetManager.StorageType storageType) {
+	public AbstractTablexiaScreen(boolean hasState, boolean loadAsync, TablexiaAssetManager.StorageType storageType) {
         stage = prepareStage();
+        this.hasState   = hasState;
         this.loadAsync  = loadAsync;
 		textureManager 	= new TablexiaTextureManager(storageType);
 		soundManager 	= new TablexiaSoundManager(storageType);
 		textManager 	= new TextManager();
 		dataManager 	= new DataManager();
-		
+
 		loadingComplete = false;
 		loadingStarted = false;
 	}
 
+    public boolean hasState() {
+        return hasState;
+    }
 
 //////////////////////////// LOADING LISTENER
 
diff --git a/core/src/cz/nic/tablexia/screen/ScreenDefinition.java b/core/src/cz/nic/tablexia/screen/ScreenDefinition.java
index aedb41973..02bc7075f 100644
--- a/core/src/cz/nic/tablexia/screen/ScreenDefinition.java
+++ b/core/src/cz/nic/tablexia/screen/ScreenDefinition.java
@@ -29,8 +29,12 @@ public enum ScreenDefinition {
 		this.screenClass = screenClass;
 		this.mainMenuDefinition = mainMenuDefinition;
 	}
-	
-	public MainMenuDefinition getMainMenuDefinition() {
+
+    public Class<? extends AbstractTablexiaScreen<?>> getScreenClass() {
+        return screenClass;
+    }
+
+    public MainMenuDefinition getMainMenuDefinition() {
 		return mainMenuDefinition;
 	}
 
diff --git a/core/src/cz/nic/tablexia/screen/loader/LoaderScreen.java b/core/src/cz/nic/tablexia/screen/loader/LoaderScreen.java
index 2902da42a..e4d29a8d6 100644
--- a/core/src/cz/nic/tablexia/screen/loader/LoaderScreen.java
+++ b/core/src/cz/nic/tablexia/screen/loader/LoaderScreen.java
@@ -35,7 +35,7 @@ public class LoaderScreen extends AbstractTablexiaScreen<Void> {
     }
 
     public LoaderScreen() {
-        super(false, TablexiaAssetManager.StorageType.INTERNAL);
+        super(false, false, TablexiaAssetManager.StorageType.INTERNAL);
     }
 
     @Override
diff --git a/core/src/cz/nic/tablexia/util/Utility.java b/core/src/cz/nic/tablexia/util/Utility.java
new file mode 100644
index 000000000..e95fc1306
--- /dev/null
+++ b/core/src/cz/nic/tablexia/util/Utility.java
@@ -0,0 +1,19 @@
+package cz.nic.tablexia.util;
+
+import com.badlogic.gdx.utils.reflect.ClassReflection;
+import com.badlogic.gdx.utils.reflect.ReflectionException;
+
+import cz.nic.tablexia.screen.AbstractTablexiaScreen;
+
+public class Utility {
+
+    public static AbstractTablexiaScreen<?> getScreenForScreenClass(Class<? extends AbstractTablexiaScreen<?>> screenClass) {
+        try {
+            return (AbstractTablexiaScreen<?>) ClassReflection.getConstructors(screenClass)[0].newInstance(new Object[]{});
+        } catch (ReflectionException e) {
+            Log.err(Utility.class, "Cannot instantiate screen class: " + screenClass + " ! (Do you have only one parameter less constructor in screen class?)", e);
+        }
+        return null;
+    }
+
+}
diff --git a/desktop/src/cz/nic/tablexia/desktop/DesktopLauncher.java b/desktop/src/cz/nic/tablexia/desktop/DesktopLauncher.java
index d2fdb15fd..53926e574 100644
--- a/desktop/src/cz/nic/tablexia/desktop/DesktopLauncher.java
+++ b/desktop/src/cz/nic/tablexia/desktop/DesktopLauncher.java
@@ -44,7 +44,7 @@ public class DesktopLauncher {
             config.addIcon(DESKTOP_ICON_128, Files.FileType.Internal);
         }
 
-	    new LwjglApplication(new Tablexia(buildType, Locale.getDefault(), versionName, applicationId), config);
+	    new LwjglApplication(new Tablexia(buildType, Locale.getDefault(), versionName, applicationId, false), config);
     }
 
     private static String loadAttributeFromManifest(String attributeName) {
diff --git a/ios/src/cz/nic/tablexia/IOSLauncher.java b/ios/src/cz/nic/tablexia/IOSLauncher.java
index 0626c283d..9554705b9 100644
--- a/ios/src/cz/nic/tablexia/IOSLauncher.java
+++ b/ios/src/cz/nic/tablexia/IOSLauncher.java
@@ -14,7 +14,7 @@ public class IOSLauncher extends IOSApplication.Delegate {
     @Override
     protected IOSApplication createApplication() {
         IOSApplicationConfiguration config = new IOSApplicationConfiguration();
-        return new IOSApplication(new Tablexia(null, Locale.getDefault(), null, null), config);
+        return new IOSApplication(new Tablexia(null, Locale.getDefault(), null, null, false), config);
     }
 
     public static void main(String[] argv) {
-- 
GitLab