commit 807d82b79641b94c22f4861fc01b2214aab4d5a4
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Sat Apr 25 18:33:46 2020 +0100

    Add two new UI States: Ready and Done.

diff --git a/src/main/java/org/distorted/main/RubikPostRender.java b/src/main/java/org/distorted/main/RubikPostRender.java
index 78f52282..d2aeb580 100644
--- a/src/main/java/org/distorted/main/RubikPostRender.java
+++ b/src/main/java/org/distorted/main/RubikPostRender.java
@@ -153,7 +153,7 @@ public class RubikPostRender implements EffectListener
       if( RubikState.getCurrentState()==RubikState.SOLV )
         {
         RubikStateSolving solving = (RubikStateSolving)RubikState.SOLV.getStateClass();
-        mNewRecord = solving.stopCounting((RubikActivity)mView.getContext());
+        mNewRecord = solving.stopCounting();
 
         if( mNewRecord< 0 )
           {
@@ -519,15 +519,13 @@ public class RubikPostRender implements EffectListener
           if( i==BaseEffect.Type.SCRAMBLE.ordinal() )
             {
             final RubikActivity act = (RubikActivity)mView.getContext();
-            RubikStateSolving solving = (RubikStateSolving)RubikState.SOLV.getStateClass();
-            solving.resetUpperText();
 
             act.runOnUiThread(new Runnable()
               {
               @Override
               public void run()
                 {
-                RubikState.switchState( act, RubikState.SOLV);
+                RubikState.switchState( act, RubikState.READ);
                 }
               });
             }
@@ -552,6 +550,15 @@ public class RubikPostRender implements EffectListener
                 dialog.setArguments(bundle);
                 dialog.show( act.getSupportFragmentManager(), null);
                 }
+
+              act.runOnUiThread(new Runnable()
+                {
+                @Override
+                public void run()
+                  {
+                  RubikState.switchState( act, RubikState.DONE);
+                  }
+                });
               }
             }
 
diff --git a/src/main/java/org/distorted/main/RubikSurfaceView.java b/src/main/java/org/distorted/main/RubikSurfaceView.java
index 37e3b564..90b6b9d7 100644
--- a/src/main/java/org/distorted/main/RubikSurfaceView.java
+++ b/src/main/java/org/distorted/main/RubikSurfaceView.java
@@ -373,8 +373,19 @@ public class RubikSurfaceView extends GLSurfaceView
 
                                            object.beginNewRotation( mCurrentAxis, mCurrentRow );
 
-                                           if( RubikState.getCurrentState()==RubikState.SOLV )
+                                           if( RubikState.getCurrentState()==RubikState.READ )
                                              {
+                                             final RubikActivity act = (RubikActivity)getContext();
+
+                                             act.runOnUiThread(new Runnable()
+                                               {
+                                               @Override
+                                               public void run()
+                                                 {
+                                                 RubikState.switchState( act, RubikState.SOLV);
+                                                 }
+                                               });
+
                                              RubikStateSolving solving = (RubikStateSolving)RubikState.SOLV.getStateClass();
                                              solving.startCounting( (RubikActivity)getContext() );
                                              }
diff --git a/src/main/java/org/distorted/states/RubikState.java b/src/main/java/org/distorted/states/RubikState.java
index 47651158..978a0e90 100644
--- a/src/main/java/org/distorted/states/RubikState.java
+++ b/src/main/java/org/distorted/states/RubikState.java
@@ -33,6 +33,8 @@ public enum RubikState
   PATT ( MAIN , MODE_DRAG   , new RubikStatePattern()  ),
   SVER ( MAIN , MODE_REPLACE, new RubikStateSolver()   ),
   SOLU ( SVER , MODE_DRAG   , new RubikStateSolution() ),
+  READ ( PLAY , MODE_ROTATE , new RubikStateReady()    ),
+  DONE ( PLAY , MODE_DRAG   , new RubikStateDone()    ),
   ;
 
   public static final int LENGTH = values().length;
diff --git a/src/main/java/org/distorted/states/RubikStateDone.java b/src/main/java/org/distorted/states/RubikStateDone.java
new file mode 100644
index 00000000..c47205fd
--- /dev/null
+++ b/src/main/java/org/distorted/states/RubikStateDone.java
@@ -0,0 +1,97 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Copyright 2020 Leszek Koltunski                                                               //
+//                                                                                               //
+// This file is part of Magic Cube.                                                              //
+//                                                                                               //
+// Magic Cube is free software: you can redistribute it and/or modify                            //
+// it under the terms of the GNU General Public License as published by                          //
+// the Free Software Foundation, either version 2 of the License, or                             //
+// (at your option) any later version.                                                           //
+//                                                                                               //
+// Magic Cube is distributed in the hope that it will be useful,                                 //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
+// GNU General Public License for more details.                                                  //
+//                                                                                               //
+// You should have received a copy of the GNU General Public License                             //
+// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+package org.distorted.states;
+
+import android.content.SharedPreferences;
+import android.util.DisplayMetrics;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import org.distorted.main.R;
+import org.distorted.main.RubikActivity;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class RubikStateDone extends RubikStateAbstract
+  {
+  void leaveState(RubikActivity act)
+    {
+
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  void enterState(final RubikActivity act)
+    {
+    LayoutInflater inflater = act.getLayoutInflater();
+    DisplayMetrics metrics = act.getResources().getDisplayMetrics();
+    float scale = metrics.density;
+
+    // TOP ////////////////////////////
+    LinearLayout layoutTop = act.findViewById(R.id.upperBar);
+    layoutTop.removeAllViews();
+    TextView label = (TextView)inflater.inflate(R.layout.upper_text, null);
+    label.setText(R.string.solved);
+    layoutTop.addView(label);
+
+    // BOT ////////////////////////////
+    LinearLayout layoutLeft = act.findViewById(R.id.mainBarLeft);
+    layoutLeft.removeAllViews();
+
+    LinearLayout layoutRight = act.findViewById(R.id.mainBarRight);
+    layoutRight.removeAllViews();
+
+    int padding = (int)(5*scale + 0.5f);
+    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);
+
+    Button back = new Button(act);
+    back.setLayoutParams(params);
+    back.setPadding(padding,0,padding,0);
+    back.setText(R.string.back);
+
+    back.setOnClickListener( new View.OnClickListener()
+      {
+      @Override
+      public void onClick(View v)
+        {
+        RubikState.goBack(act);
+        }
+      });
+
+    layoutRight.addView(back);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void savePreferences(SharedPreferences.Editor editor)
+    {
+
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void restorePreferences(SharedPreferences preferences)
+    {
+
+    }
+  }
diff --git a/src/main/java/org/distorted/states/RubikStateReady.java b/src/main/java/org/distorted/states/RubikStateReady.java
new file mode 100644
index 00000000..a628fc94
--- /dev/null
+++ b/src/main/java/org/distorted/states/RubikStateReady.java
@@ -0,0 +1,97 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Copyright 2020 Leszek Koltunski                                                               //
+//                                                                                               //
+// This file is part of Magic Cube.                                                              //
+//                                                                                               //
+// Magic Cube is free software: you can redistribute it and/or modify                            //
+// it under the terms of the GNU General Public License as published by                          //
+// the Free Software Foundation, either version 2 of the License, or                             //
+// (at your option) any later version.                                                           //
+//                                                                                               //
+// Magic Cube is distributed in the hope that it will be useful,                                 //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
+// GNU General Public License for more details.                                                  //
+//                                                                                               //
+// You should have received a copy of the GNU General Public License                             //
+// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+package org.distorted.states;
+
+import android.content.SharedPreferences;
+import android.util.DisplayMetrics;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import org.distorted.main.R;
+import org.distorted.main.RubikActivity;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class RubikStateReady extends RubikStateAbstract
+  {
+  void leaveState(RubikActivity act)
+    {
+
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  void enterState(final RubikActivity act)
+    {
+    LayoutInflater inflater = act.getLayoutInflater();
+    DisplayMetrics metrics = act.getResources().getDisplayMetrics();
+    float scale = metrics.density;
+
+    // TOP ////////////////////////////
+    LinearLayout layoutTop = act.findViewById(R.id.upperBar);
+    layoutTop.removeAllViews();
+    TextView label = (TextView)inflater.inflate(R.layout.upper_text, null);
+    label.setText(R.string.ready);
+    layoutTop.addView(label);
+
+    // BOT ////////////////////////////
+    LinearLayout layoutLeft = act.findViewById(R.id.mainBarLeft);
+    layoutLeft.removeAllViews();
+
+    LinearLayout layoutRight = act.findViewById(R.id.mainBarRight);
+    layoutRight.removeAllViews();
+
+    int padding = (int)(5*scale + 0.5f);
+    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);
+
+    Button back = new Button(act);
+    back.setLayoutParams(params);
+    back.setPadding(padding,0,padding,0);
+    back.setText(R.string.back);
+
+    back.setOnClickListener( new View.OnClickListener()
+      {
+      @Override
+      public void onClick(View v)
+        {
+        RubikState.goBack(act);
+        }
+      });
+
+    layoutRight.addView(back);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void savePreferences(SharedPreferences.Editor editor)
+    {
+
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void restorePreferences(SharedPreferences preferences)
+    {
+
+    }
+  }
diff --git a/src/main/java/org/distorted/states/RubikStateSolving.java b/src/main/java/org/distorted/states/RubikStateSolving.java
index 2918122b..ffaab1e8 100644
--- a/src/main/java/org/distorted/states/RubikStateSolving.java
+++ b/src/main/java/org/distorted/states/RubikStateSolving.java
@@ -45,13 +45,11 @@ public class RubikStateSolving extends RubikStateAbstract implements RubikPostRe
   {
   private static final int DURATION_MILLIS = 750;
 
-  private int mUpperText;
   private TextView mTime;
   private Timer mTimer;
   private long mStartTime;
   private boolean mRunning;
   private RubikScores mScores;
-  private Button mBack;
   private ImageButton mPrevButton;
   private boolean mCanPrevMove;
   private ArrayList<Move> mMoves;
@@ -79,7 +77,7 @@ public class RubikStateSolving extends RubikStateAbstract implements RubikPostRe
 
   void leaveState(RubikActivity act)
     {
-    stopCounting(act);
+    stopCounting();
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -88,8 +86,6 @@ public class RubikStateSolving extends RubikStateAbstract implements RubikPostRe
     {
     mCanPrevMove = true;
 
-    if( mUpperText==0 ) resetUpperText();
-
     if( mMoves==null ) mMoves = new ArrayList<>();
     else               mMoves.clear();
 
@@ -101,7 +97,7 @@ public class RubikStateSolving extends RubikStateAbstract implements RubikPostRe
     LinearLayout layoutTop = act.findViewById(R.id.upperBar);
     layoutTop.removeAllViews();
     mTime = (TextView)inflater.inflate(R.layout.upper_text, null);
-    mTime.setText(mUpperText);
+    mTime.setText(act.getString(R.string.tm_placeholder,0,0));
     layoutTop.addView(mTime);
 
     // BOT ////////////////////////////
@@ -117,12 +113,12 @@ public class RubikStateSolving extends RubikStateAbstract implements RubikPostRe
     int padding = (int)(5*scale + 0.5f);
     LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);
 
-    mBack = new Button(act);
-    mBack.setLayoutParams(params);
-    mBack.setPadding(padding,0,padding,0);
-    mBack.setText(R.string.back);
+    Button back = new Button(act);
+    back.setLayoutParams(params);
+    back.setPadding(padding,0,padding,0);
+    back.setText(R.string.back);
 
-    mBack.setOnClickListener( new View.OnClickListener()
+    back.setOnClickListener( new View.OnClickListener()
       {
       @Override
       public void onClick(View v)
@@ -131,7 +127,7 @@ public class RubikStateSolving extends RubikStateAbstract implements RubikPostRe
         }
       });
 
-    layoutRight.addView(mBack);
+    layoutRight.addView(back);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -216,6 +212,7 @@ public class RubikStateSolving extends RubikStateAbstract implements RubikPostRe
     {
     mPrevButton = null;
 
+    editor.putLong("stateSolving_startTime" , mStartTime);
     mScores.savePreferences(editor);
     }
 
@@ -223,6 +220,7 @@ public class RubikStateSolving extends RubikStateAbstract implements RubikPostRe
 
   public void restorePreferences(SharedPreferences preferences)
     {
+    mStartTime = preferences.getLong("stateSolving_startTime" , 0 );
     mScores.restorePreferences(preferences);
     }
 
@@ -257,22 +255,10 @@ public class RubikStateSolving extends RubikStateAbstract implements RubikPostRe
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public long stopCounting(RubikActivity act)
+  public long stopCounting()
     {
     if( mRunning )
       {
-      act.runOnUiThread(new Runnable()
-        {
-        @Override
-        public void run()
-          {
-          mUpperText = R.string.solved;
-          mTime.setText(mUpperText);
-          mBack.setClickable(false);
-          mPrevButton.setVisibility(View.INVISIBLE);
-          }
-        });
-
       if( mTimer!=null )
         {
         mTimer.cancel();
@@ -296,13 +282,6 @@ public class RubikStateSolving extends RubikStateAbstract implements RubikPostRe
     return 0;
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void resetUpperText()
-    {
-    mUpperText = R.string.ready;
-    }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public void onActionFinished(final long effectID)
