Project

General

Profile

Download (24.7 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / screens / RubikScreenPlay.java @ 68191e7d

1 211b48f2 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19
20 fcd5b990 Leszek Koltunski
package org.distorted.screens;
21 211b48f2 Leszek Koltunski
22 179f7189 Leszek Koltunski
import java.lang.ref.WeakReference;
23
24
import android.app.Activity;
25 4c0cd600 Leszek Koltunski
import android.content.Context;
26 211b48f2 Leszek Koltunski
import android.content.SharedPreferences;
27 be65535e Leszek Koltunski
import android.content.res.ColorStateList;
28 8a47642f Leszek Koltunski
import android.content.res.Resources;
29 255492a0 Leszek Koltunski
import android.os.Build;
30 e03e0352 Leszek Koltunski
import android.os.Bundle;
31 e3c74c0f Leszek Koltunski
import android.util.TypedValue;
32 255492a0 Leszek Koltunski
import android.view.Gravity;
33 211b48f2 Leszek Koltunski
import android.view.LayoutInflater;
34
import android.view.View;
35
import android.widget.Button;
36 e07c48a2 Leszek Koltunski
import android.widget.GridLayout;
37 211b48f2 Leszek Koltunski
import android.widget.ImageButton;
38
import android.widget.LinearLayout;
39 4c0cd600 Leszek Koltunski
import android.widget.PopupWindow;
40 d6e7c7fb Leszek Koltunski
import android.widget.RelativeLayout;
41 10373dc7 Leszek Koltunski
import android.widget.TextView;
42 211b48f2 Leszek Koltunski
43 5f3801d3 Leszek Koltunski
import org.distorted.dialogs.RubikDialogUpdates;
44 acabdd83 Leszek Koltunski
import org.distorted.external.RubikNetwork;
45 1088a219 Leszek Koltunski
import org.distorted.external.RubikScores;
46 acabdd83 Leszek Koltunski
import org.distorted.external.RubikUpdates;
47 3f7a4363 Leszek Koltunski
48
import org.distorted.main.R;
49
import org.distorted.main.RubikActivity;
50 e03e0352 Leszek Koltunski
import org.distorted.dialogs.RubikDialogAbout;
51 a8576d91 Leszek Koltunski
import org.distorted.dialogs.RubikDialogPattern;
52 e03e0352 Leszek Koltunski
import org.distorted.dialogs.RubikDialogScores;
53 234a7582 Leszek Koltunski
import org.distorted.dialogs.RubikDialogTutorial;
54 55e6be1d Leszek Koltunski
import org.distorted.helpers.TransparentImageButton;
55 4f3e2d90 Leszek Koltunski
import org.distorted.objectlib.main.ObjectControl;
56 15adc102 Leszek Koltunski
import org.distorted.objects.MainEntry;
57
import org.distorted.objects.MainEntryList;
58 d433b50e Leszek Koltunski
import org.distorted.objects.RubikObject;
59
import org.distorted.objects.RubikObjectList;
60 211b48f2 Leszek Koltunski
61 b600ccd9 Leszek Koltunski
import static android.view.View.inflate;
62 88d28110 Leszek Koltunski
63 211b48f2 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
64
65 63dd19c4 Leszek Koltunski
public class RubikScreenPlay extends RubikScreenBase implements RubikNetwork.Updatee
66 211b48f2 Leszek Koltunski
  {
67 6e3fcb91 Leszek Koltunski
  public static final int NUM_COLUMNS  = 5;
68 adbd16d9 Leszek Koltunski
  public static final int LEVELS_SHOWN = 8;
69 0b458a90 Leszek Koltunski
  private static final int NUM_BUTTONS = 5;
70 dc78f395 Leszek Koltunski
  private static final int[] mLocation = new int[2];
71 e03e0352 Leszek Koltunski
72 756f152c Leszek Koltunski
  private TransparentImageButton mObjButton, mMenuButton, mSolveButton, mScrambleButton;
73 4f3e2d90 Leszek Koltunski
  private PopupWindow mObjectPopup, mMenuPopup;
74
  private WeakReference<RubikActivity> mWeakAct;
75 10373dc7 Leszek Koltunski
  private TextView mBubbleUpdates;
76 1088a219 Leszek Koltunski
  private Button[] mLevel;
77 369a0fce Leszek Koltunski
  private int mObjectSize, mMenuLayoutWidth, mMenuLayoutHeight, mMenuButtonHeight, mMenuTextSize;
78 85b09df4 Leszek Koltunski
  private int mLevelValue;
79 598de3ee Leszek Koltunski
  private int mColCount, mRowCount, mMaxRowCount;
80 255492a0 Leszek Koltunski
  private int mUpperBarHeight;
81 dd874ae8 Leszek Koltunski
  private boolean mShouldReactToEndOfScrambling;
82 9c39179e Leszek Koltunski
  private float mScreenWidth;
83 255492a0 Leszek Koltunski
84 211b48f2 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
85
86 f5da732a Leszek Koltunski
  void leaveScreen(RubikActivity act)
87 211b48f2 Leszek Koltunski
    {
88 85b09df4 Leszek Koltunski
89 211b48f2 Leszek Koltunski
    }
90
91
///////////////////////////////////////////////////////////////////////////////////////////////////
92
93 f5da732a Leszek Koltunski
  void enterScreen(final RubikActivity act)
94 211b48f2 Leszek Koltunski
    {
95 179f7189 Leszek Koltunski
    mWeakAct = new WeakReference<>(act);
96 9c39179e Leszek Koltunski
    mScreenWidth = act.getScreenWidthInPixels();
97 255492a0 Leszek Koltunski
    mUpperBarHeight = act.getHeightUpperBar();
98 a8576d91 Leszek Koltunski
99 0b458a90 Leszek Koltunski
    mMenuButtonHeight = (int)(mScreenWidth*RubikActivity.MENU_BUTTON_HEIGHT);
100 3c27ff9e Leszek Koltunski
    mMenuTextSize     = (int)(mScreenWidth*RubikActivity.MENU_MAIN_TEXT_SIZE);
101 e3c74c0f Leszek Koltunski
102 ac1900c3 Leszek Koltunski
    mObjectPopup = null;
103 e07c48a2 Leszek Koltunski
104 211b48f2 Leszek Koltunski
    // TOP ////////////////////////////
105 7289fd6c Leszek Koltunski
    LinearLayout layoutTop = act.findViewById(R.id.upperBar);
106 211b48f2 Leszek Koltunski
    layoutTop.removeAllViews();
107 85b09df4 Leszek Koltunski
108 c1df05fa Leszek Koltunski
    setupSolveButton(act);
109
    layoutTop.addView(mSolveButton);
110 9c39179e Leszek Koltunski
    setupMenuButton(act,mScreenWidth);
111 0254cfd7 Leszek Koltunski
    layoutTop.addView(mMenuButton);
112 756f152c Leszek Koltunski
    setupScrambleButton(act);
113 c1df05fa Leszek Koltunski
    layoutTop.addView(mScrambleButton);
114
115
    // BOTTOM /////////////////////////
116
    setupObjectButton(act,mScreenWidth);
117
    createBottomPane(act,mObjButton,null);
118 769d7b9f Leszek Koltunski
    }
119 211b48f2 Leszek Koltunski
120 8ab435b9 Leszek Koltunski
//////////////////////////////////////////////////////////////////////////////////////////////////
121 4c0cd600 Leszek Koltunski
122 ad0c8e0e Leszek Koltunski
  private void setupObjectButton(final RubikActivity act, final float width)
123 769d7b9f Leszek Koltunski
    {
124 c651024f Leszek Koltunski
    final int margin  = (int)(width*RubikActivity.SMALL_MARGIN);
125 e07c48a2 Leszek Koltunski
    final int icon = RubikActivity.getDrawable(R.drawable.ui_small_cube_menu,R.drawable.ui_medium_cube_menu, R.drawable.ui_big_cube_menu, R.drawable.ui_huge_cube_menu);
126 b600ccd9 Leszek Koltunski
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
127
    mObjButton = new TransparentImageButton(act, icon, TransparentImageButton.GRAVITY_MIDDLE, params);
128 769d7b9f Leszek Koltunski
129
    mObjButton.setOnClickListener( new View.OnClickListener()
130
      {
131
      @Override
132
      public void onClick(View view)
133 4c0cd600 Leszek Koltunski
        {
134 2da68298 Leszek Koltunski
        if( mObjectPopup==null )
135
          {
136
          float width = act.getScreenWidthInPixels();
137
          float height= act.getScreenHeightInPixels();
138
          setupObjectWindow(act,width,height);
139
          }
140
141
        if( act.getControl().isUINotBlocked())
142 a42e25a6 Leszek Koltunski
          {
143 598de3ee Leszek Koltunski
          int rowCount = Math.min(mMaxRowCount,mRowCount);
144 c5b4af4a Leszek Koltunski
          View popupView = mObjectPopup.getContentView();
145
          popupView.setSystemUiVisibility(RubikActivity.FLAGS);
146 c1df05fa Leszek Koltunski
          displayPopup(act,view,mObjectPopup,mObjectSize*mColCount,mObjectSize*rowCount+5*margin,margin,margin);
147 c5b4af4a Leszek Koltunski
          }
148 769d7b9f Leszek Koltunski
        }
149
      });
150
    }
151 4c0cd600 Leszek Koltunski
152 e31abc1e Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
153
154 ad0c8e0e Leszek Koltunski
  private void setupMenuButton(final RubikActivity act, final float width)
155 e31abc1e Leszek Koltunski
    {
156 0254cfd7 Leszek Koltunski
    final int icon = RubikActivity.getDrawable(R.drawable.ui_small_menu,R.drawable.ui_medium_menu, R.drawable.ui_big_menu, R.drawable.ui_huge_menu);
157 b600ccd9 Leszek Koltunski
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
158
    mMenuButton = new TransparentImageButton(act, icon, TransparentImageButton.GRAVITY_MIDDLE, params);
159 e31abc1e Leszek Koltunski
160 e03e0352 Leszek Koltunski
    mMenuButton.setOnClickListener( new View.OnClickListener()
161 e31abc1e Leszek Koltunski
      {
162
      @Override
163
      public void onClick(View view)
164
        {
165 2da68298 Leszek Koltunski
        if( mMenuPopup==null )
166
          {
167
          float width = act.getScreenWidthInPixels();
168
          setupMenuWindow(act,width);
169
          }
170
171
        if( act.getControl().isUINotBlocked())
172 e03e0352 Leszek Koltunski
          {
173 c5b4af4a Leszek Koltunski
          View popupView = mMenuPopup.getContentView();
174
          popupView.setSystemUiVisibility(RubikActivity.FLAGS);
175 8a47642f Leszek Koltunski
          setupLevelColors(act);
176 3c27ff9e Leszek Koltunski
          displayPopup(act,view,mMenuPopup,mMenuLayoutWidth,mMenuLayoutHeight,(int)(-mMenuLayoutWidth/2 + width/6),0);
177 6fad862b Leszek Koltunski
          }
178 e31abc1e Leszek Koltunski
        }
179
      });
180
    }
181
182 4c0cd600 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
183
184 598de3ee Leszek Koltunski
  private void setupObjectWindow(final RubikActivity act, final float width, final float height)
185 4c0cd600 Leszek Koltunski
    {
186 ac1900c3 Leszek Koltunski
    MainEntryList list = MainEntryList.getInstance();
187
    int numEntries = list.getNumOfEntries();
188
    mRowCount = (numEntries + NUM_COLUMNS-1) / NUM_COLUMNS;
189
    mColCount = NUM_COLUMNS;
190
191 adbd16d9 Leszek Koltunski
    int cubeSize = (int)(width/9);
192
    int margin   = (int)(width*RubikActivity.LARGE_MARGIN);
193
    mObjectSize  = (int)(cubeSize + 2*margin + 0.5f);
194 0b162619 Leszek Koltunski
    mMaxRowCount = (int)((height-1.8f*mUpperBarHeight)/mObjectSize);
195 598de3ee Leszek Koltunski
196 8d1da3f1 Leszek Koltunski
    LinearLayout view = (LinearLayout)inflate( act, R.layout.popup_object, null);
197 b600ccd9 Leszek Koltunski
    GridLayout objectGrid = view.findViewById(R.id.objectGrid);
198 e07c48a2 Leszek Koltunski
199
    GridLayout.Spec[] rowSpecs = new GridLayout.Spec[mRowCount];
200
    GridLayout.Spec[] colSpecs = new GridLayout.Spec[mColCount];
201
202 92843d3b Leszek Koltunski
    objectGrid.setColumnCount(mColCount);
203
    objectGrid.setRowCount(mRowCount);
204 e07c48a2 Leszek Koltunski
205 d6e7c7fb Leszek Koltunski
    RelativeLayout bottomLayout = view.findViewById(R.id.bottomLayout);
206
    setupBottomLayout(act,bottomLayout);
207 0b162619 Leszek Koltunski
208 b600ccd9 Leszek Koltunski
    mObjectPopup = new PopupWindow(act);
209
    mObjectPopup.setFocusable(true);
210
    mObjectPopup.setContentView(view);
211
212 0501a4b8 Leszek Koltunski
    int[] nextInRow = new int[mRowCount];
213 fa679111 Leszek Koltunski
214 e07c48a2 Leszek Koltunski
    for(int row=0; row<mRowCount; row++)
215
      {
216
      rowSpecs[row] = GridLayout.spec(row);
217 0501a4b8 Leszek Koltunski
      nextInRow[row]= 0;
218 e07c48a2 Leszek Koltunski
      }
219
    for(int col=0; col<mColCount; col++)
220
      {
221
      colSpecs[col] = GridLayout.spec(col);
222
      }
223 769d7b9f Leszek Koltunski
224 15adc102 Leszek Koltunski
    for(int entry=0; entry<numEntries; entry++)
225 769d7b9f Leszek Koltunski
      {
226 15adc102 Leszek Koltunski
      final MainEntry mainEntry = list.getEntry(entry);
227
      int row = entry/NUM_COLUMNS;
228 7ac0ee88 Leszek Koltunski
      ImageButton button = new ImageButton(act);
229 15adc102 Leszek Koltunski
      if( mainEntry!=null ) mainEntry.setIconTo(act,button);
230 314e9ff0 Leszek Koltunski
231 7ac0ee88 Leszek Koltunski
      button.setOnClickListener( new View.OnClickListener()
232 769d7b9f Leszek Koltunski
        {
233 7ac0ee88 Leszek Koltunski
        @Override
234
        public void onClick(View v)
235 769d7b9f Leszek Koltunski
          {
236 2afc6754 Leszek Koltunski
          if( act.getControl().isUINotBlocked() && ScreenList.getCurrentScreen()== ScreenList.PLAY )
237 769d7b9f Leszek Koltunski
            {
238 15adc102 Leszek Koltunski
            int type = mainEntry!=null ? mainEntry.getType() : -1;
239
240
            if( type==MainEntry.TYPE_OBJECT )
241
              {
242
              int ordinal = mainEntry.getOrdinal();
243 1088a219 Leszek Koltunski
              RubikObjectList.setCurrObject(ordinal);
244 15adc102 Leszek Koltunski
              act.changeObject(ordinal,true);
245 8a47642f Leszek Koltunski
              if( mMenuPopup!=null ) setupLevelColors(act);
246 15adc102 Leszek Koltunski
              mMovesController.clearMoves(act);
247
              }
248
            else if( type==MainEntry.TYPE_CREATOR )
249
              {
250
              act.switchToBandagedCreator();
251
              }
252 769d7b9f Leszek Koltunski
            }
253
254 1f3bc259 Leszek Koltunski
          if( mObjectPopup!=null ) mObjectPopup.dismiss();
255 7ac0ee88 Leszek Koltunski
          }
256
        });
257 e07c48a2 Leszek Koltunski
258 7ac0ee88 Leszek Koltunski
      GridLayout.LayoutParams params = new GridLayout.LayoutParams(rowSpecs[row],colSpecs[nextInRow[row]]);
259
      params.bottomMargin = margin;
260
      params.topMargin    = margin;
261
      params.leftMargin   = margin;
262
      params.rightMargin  = margin;
263 fa679111 Leszek Koltunski
264 adbd16d9 Leszek Koltunski
      params.width = cubeSize;
265
      params.height= cubeSize;
266 6e3fcb91 Leszek Koltunski
267 7ac0ee88 Leszek Koltunski
      nextInRow[row]++;
268
269
      objectGrid.addView(button, params);
270 769d7b9f Leszek Koltunski
      }
271 4c0cd600 Leszek Koltunski
    }
272
273 8d1da3f1 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
274
275 d6e7c7fb Leszek Koltunski
  private void setupBottomLayout(final RubikActivity act, final RelativeLayout layout)
276 8d1da3f1 Leszek Koltunski
    {
277
    int iconT = RubikActivity.getDrawable(R.drawable.ui_small_tutorial,R.drawable.ui_medium_tutorial, R.drawable.ui_big_tutorial, R.drawable.ui_huge_tutorial);
278 d6e7c7fb Leszek Koltunski
    int iconD = RubikActivity.getDrawable(R.drawable.ui_small_download,R.drawable.ui_medium_download, R.drawable.ui_big_download, R.drawable.ui_huge_download);
279
    int iconI = RubikActivity.getDrawable(R.drawable.ui_small_info,R.drawable.ui_medium_info, R.drawable.ui_big_info, R.drawable.ui_huge_info);
280 8d1da3f1 Leszek Koltunski
281
    ImageButton buttonTut = layout.findViewById(R.id.buttonTut);
282 d6e7c7fb Leszek Koltunski
    ImageButton buttonDow = layout.findViewById(R.id.buttonDow);
283
    ImageButton buttonInf = layout.findViewById(R.id.buttonInf);
284 8d1da3f1 Leszek Koltunski
285
    buttonTut.setImageResource(iconT);
286 d6e7c7fb Leszek Koltunski
    buttonDow.setImageResource(iconD);
287
    buttonInf.setImageResource(iconI);
288 8d1da3f1 Leszek Koltunski
289
    TypedValue outValue = new TypedValue();
290
    act.getTheme().resolveAttribute(android.R.attr.selectableItemBackgroundBorderless, outValue, true);
291
    buttonTut.setBackgroundResource(outValue.resourceId);
292 d6e7c7fb Leszek Koltunski
    buttonDow.setBackgroundResource(outValue.resourceId);
293
    buttonInf.setBackgroundResource(outValue.resourceId);
294 8d1da3f1 Leszek Koltunski
295
    buttonTut.setOnClickListener( new View.OnClickListener()
296
      {
297
      @Override
298
      public void onClick(View v)
299
        {
300
        if( mObjectPopup!=null ) mObjectPopup.dismiss();
301
        RubikDialogTutorial tDiag = new RubikDialogTutorial();
302
        tDiag.show( act.getSupportFragmentManager(), RubikDialogTutorial.getDialogTag() );
303
        }
304
      });
305
306 d6e7c7fb Leszek Koltunski
    buttonDow.setOnClickListener( new View.OnClickListener()
307
      {
308
      @Override
309
      public void onClick(View v)
310
        {
311 5f3801d3 Leszek Koltunski
        if( mObjectPopup!=null ) mObjectPopup.dismiss();
312
        RubikDialogUpdates uDiag = new RubikDialogUpdates();
313
        uDiag.show( act.getSupportFragmentManager(), RubikDialogUpdates.getDialogTag() );
314 d6e7c7fb Leszek Koltunski
        }
315
      });
316
317
    buttonInf.setOnClickListener( new View.OnClickListener()
318 8d1da3f1 Leszek Koltunski
      {
319
      @Override
320
      public void onClick(View v)
321
        {
322 f12e4de9 Leszek Koltunski
        if( mObjectPopup!=null ) mObjectPopup.dismiss();
323 400ff34d Leszek Koltunski
        int currObject = RubikObjectList.getCurrObject();
324
        act.switchConfig(currObject);
325 8d1da3f1 Leszek Koltunski
        }
326
      });
327 d6e7c7fb Leszek Koltunski
328 10373dc7 Leszek Koltunski
    mBubbleUpdates = layout.findViewById(R.id.bubbleUpdates);
329
    mBubbleUpdates.setVisibility(View.INVISIBLE);
330
331 d6e7c7fb Leszek Koltunski
    RubikNetwork network = RubikNetwork.getInstance();
332
    network.signUpForUpdates(this);
333 8d1da3f1 Leszek Koltunski
    }
334
335 c1df05fa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
336
337
  void setupSolveButton(final RubikActivity act)
338
    {
339
    int icon = RubikActivity.getDrawable(R.drawable.ui_small_cube_solve,R.drawable.ui_medium_cube_solve, R.drawable.ui_big_cube_solve, R.drawable.ui_huge_cube_solve);
340
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
341
    mSolveButton = new TransparentImageButton(act, icon, TransparentImageButton.GRAVITY_MIDDLE,params);
342
343
    mSolveButton.setOnClickListener( new View.OnClickListener()
344
      {
345
      @Override
346
      public void onClick(View v)
347
        {
348
        act.getControl().solveObject();
349
        mMovesController.clearMoves(act);
350
        }
351
      });
352
    }
353
354
///////////////////////////////////////////////////////////////////////////////////////////////////
355
356
  private void setupScrambleButton(final RubikActivity act)
357
    {
358
    int icon = RubikActivity.getDrawable(R.drawable.ui_small_cube_scramble,R.drawable.ui_medium_cube_scramble, R.drawable.ui_big_cube_scramble, R.drawable.ui_huge_cube_scramble);
359
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
360
    mScrambleButton = new TransparentImageButton(act, icon, TransparentImageButton.GRAVITY_MIDDLE, params);
361
362
    mScrambleButton.setOnClickListener( new View.OnClickListener()
363
      {
364
      @Override
365
      public void onClick(View v)
366
        {
367
        int currObject = RubikObjectList.getCurrObject();
368
        RubikObject object = RubikObjectList.getObject(currObject);
369 ca280c3f Leszek Koltunski
        int numScrambles = object==null ? 0 : 2*object.getNumScramble();
370 c1df05fa Leszek Koltunski
        mShouldReactToEndOfScrambling = false;
371
        act.getControl().fastScrambleObject(numScrambles);
372
        }
373
      });
374
    }
375
376 e03e0352 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
377
378 ad0c8e0e Leszek Koltunski
  private void setupMenuWindow(final RubikActivity act, final float width)
379 e03e0352 Leszek Koltunski
    {
380
    LayoutInflater layoutInflater = (LayoutInflater)act.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
381 e07c48a2 Leszek Koltunski
    final View layout = layoutInflater.inflate(R.layout.popup_menu, null);
382 e03e0352 Leszek Koltunski
383
    mMenuPopup = new PopupWindow(act);
384
    mMenuPopup.setContentView(layout);
385
    mMenuPopup.setFocusable(true);
386 0b458a90 Leszek Koltunski
    int padding = (int)(width*RubikActivity.MEDIUM_MARGIN);
387 0254cfd7 Leszek Koltunski
388 0b458a90 Leszek Koltunski
    mMenuLayoutWidth = (int)(width*0.6f);
389 369a0fce Leszek Koltunski
    mMenuLayoutHeight= (int)( padding + NUM_BUTTONS*(mMenuButtonHeight+padding) + 4*mMenuButtonHeight+6*padding);
390 e03e0352 Leszek Koltunski
391 0b458a90 Leszek Koltunski
    layout.setPadding(padding,0,padding,0);
392 e03e0352 Leszek Koltunski
393 0b458a90 Leszek Koltunski
    Button highScores = layout.findViewById(R.id.menuHighScores);
394 369a0fce Leszek Koltunski
    highScores.setTextSize(TypedValue.COMPLEX_UNIT_PX, mMenuTextSize);
395 0b458a90 Leszek Koltunski
    highScores.setOnClickListener( new View.OnClickListener()
396 e03e0352 Leszek Koltunski
        {
397
        @Override
398
        public void onClick(View v)
399
          {
400
          mMenuPopup.dismiss();
401 0b458a90 Leszek Koltunski
          Bundle sBundle = new Bundle();
402
          int currObject = RubikObjectList.getCurrObject();
403
          sBundle.putInt("tab", currObject );
404
          sBundle.putBoolean("submitting", false);
405
          RubikDialogScores scores = new RubikDialogScores();
406
          scores.setArguments(sBundle);
407
          scores.show(act.getSupportFragmentManager(), null);
408 e03e0352 Leszek Koltunski
          }
409
        });
410
411 0b458a90 Leszek Koltunski
    Button prettyPatterns = layout.findViewById(R.id.menuPrettyPatterns);
412 369a0fce Leszek Koltunski
    prettyPatterns.setTextSize(TypedValue.COMPLEX_UNIT_PX, mMenuTextSize);
413 0b458a90 Leszek Koltunski
    prettyPatterns.setOnClickListener( new View.OnClickListener()
414
        {
415
        @Override
416
        public void onClick(View v)
417
          {
418
          mMenuPopup.dismiss();
419
          RubikDialogPattern pDiag = new RubikDialogPattern();
420
          pDiag.show( act.getSupportFragmentManager(), RubikDialogPattern.getDialogTag() );
421
          }
422
        });
423 0254cfd7 Leszek Koltunski
424 0b458a90 Leszek Koltunski
    Button solver = layout.findViewById(R.id.menuSolver);
425 369a0fce Leszek Koltunski
    solver.setTextSize(TypedValue.COMPLEX_UNIT_PX, mMenuTextSize);
426 0b458a90 Leszek Koltunski
    solver.setOnClickListener( new View.OnClickListener()
427
        {
428
        @Override
429
        public void onClick(View v)
430
          {
431
          mMenuPopup.dismiss();
432
          ScreenList.switchScreen(act, ScreenList.SVER);
433
          }
434
        });
435 e03e0352 Leszek Koltunski
436 0b458a90 Leszek Koltunski
    Button tutorials = layout.findViewById(R.id.menuTutorials);
437 369a0fce Leszek Koltunski
    tutorials.setTextSize(TypedValue.COMPLEX_UNIT_PX, mMenuTextSize);
438 0b458a90 Leszek Koltunski
    tutorials.setOnClickListener( new View.OnClickListener()
439
        {
440
        @Override
441
        public void onClick(View v)
442
          {
443
          mMenuPopup.dismiss();
444
          RubikDialogTutorial tDiag = new RubikDialogTutorial();
445
          tDiag.show( act.getSupportFragmentManager(), RubikDialogTutorial.getDialogTag() );
446
          }
447
        });
448 e03e0352 Leszek Koltunski
449 0b458a90 Leszek Koltunski
    Button about = layout.findViewById(R.id.menuAbout);
450 369a0fce Leszek Koltunski
    about.setTextSize(TypedValue.COMPLEX_UNIT_PX, mMenuTextSize);
451 0b458a90 Leszek Koltunski
    about.setOnClickListener( new View.OnClickListener()
452
        {
453
        @Override
454
        public void onClick(View v)
455
          {
456
          mMenuPopup.dismiss();
457
          RubikDialogAbout aDiag = new RubikDialogAbout();
458
          aDiag.show(act.getSupportFragmentManager(), null);
459
          }
460
        });
461 4f3e2d90 Leszek Koltunski
462 369a0fce Leszek Koltunski
    TextView levels = layout.findViewById(R.id.menuLevels);
463
    levels.setTextSize(TypedValue.COMPLEX_UNIT_PX, mMenuTextSize);
464
465 4f3e2d90 Leszek Koltunski
    setupLevelButtons(act,layout,padding);
466
    }
467
468
///////////////////////////////////////////////////////////////////////////////////////////////////
469
470
  private void setupLevelButtons(RubikActivity act, View layout, int padding)
471
    {
472
    int sizeW = (mMenuLayoutWidth-4*padding)/3;
473 3c27ff9e Leszek Koltunski
    int sizeH = (int)(sizeW*0.8f);
474 4f3e2d90 Leszek Koltunski
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(sizeW,sizeH);
475
    params.setMargins(padding/2,0,padding/2,0);
476
477 1088a219 Leszek Koltunski
    mLevel = new Button[LEVELS_SHOWN+1];
478 4f3e2d90 Leszek Koltunski
479 1088a219 Leszek Koltunski
    mLevel[0] = layout.findViewById(R.id.level1);
480
    mLevel[1] = layout.findViewById(R.id.level2);
481
    mLevel[2] = layout.findViewById(R.id.level3);
482
    mLevel[3] = layout.findViewById(R.id.level4);
483
    mLevel[4] = layout.findViewById(R.id.level5);
484
    mLevel[5] = layout.findViewById(R.id.level6);
485
    mLevel[6] = layout.findViewById(R.id.level7);
486
    mLevel[7] = layout.findViewById(R.id.level8);
487
    mLevel[8] = layout.findViewById(R.id.levelM);
488 4f3e2d90 Leszek Koltunski
489 1088a219 Leszek Koltunski
    for(int i=0; i<=LEVELS_SHOWN; i++)
490
      {
491
      final int ii = i;
492
      mLevel[i].setTextSize(TypedValue.COMPLEX_UNIT_PX, mMenuTextSize);
493
      mLevel[i].setLayoutParams(params);
494
      mLevel[i].setOnClickListener( new View.OnClickListener()
495 4f3e2d90 Leszek Koltunski
        {
496
        @Override
497
        public void onClick(View v)
498
          {
499
          ObjectControl control = act.getControl();
500
501
          if(control.isUINotBlocked())
502
            {
503
            if( mMenuPopup!=null ) mMenuPopup.dismiss();
504
505
            int currObject = RubikObjectList.getCurrObject();
506
            RubikObject object = RubikObjectList.getObject(currObject);
507 1088a219 Leszek Koltunski
            final int scrambles = ii<LEVELS_SHOWN ? ii+1 : (object==null ? 0 : object.getNumScramble());
508
            mLevelValue = ii+1;
509 4f3e2d90 Leszek Koltunski
            mShouldReactToEndOfScrambling = true;
510
            control.scrambleObject(scrambles);
511
            }
512
          }
513
        });
514 1088a219 Leszek Koltunski
      }
515
    }
516
517
///////////////////////////////////////////////////////////////////////////////////////////////////
518
519 8a47642f Leszek Koltunski
  private void setupLevelColors(RubikActivity act)
520 1088a219 Leszek Koltunski
    {
521
    int currObject = RubikObjectList.getCurrObject();
522
    int dbLevel = RubikObjectList.getDBLevel(currObject);
523
    RubikScores scores = RubikScores.getInstance();
524 8a47642f Leszek Koltunski
    Resources res = act.getResources();
525 be65535e Leszek Koltunski
    ColorStateList colorG = ColorStateList.valueOf(res.getColor(R.color.green));
526
    ColorStateList colorD = ColorStateList.valueOf(res.getColor(R.color.dark_grey));
527 1088a219 Leszek Koltunski
528
    for(int i=0; i<=LEVELS_SHOWN; i++)
529
      {
530
      int level = i<LEVELS_SHOWN ? i : dbLevel;
531
      boolean isSolved = scores.isSolved(currObject,level);
532 be65535e Leszek Koltunski
      mLevel[i].setBackgroundTintList( isSolved ? colorG : colorD);
533 1088a219 Leszek Koltunski
      }
534 e03e0352 Leszek Koltunski
    }
535
536 211b48f2 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
537 3398a606 Leszek Koltunski
// This is necessary! Otherwise the ObjectPopup will not be re-created next time and we will still
538
// hold a reference to the old instance of the RubikActivity class (because setupObjectWindow is not
539
// going to be called)
540
// An reference to the old instance of RubikActivity will cause all sorts of strange issues.
541 211b48f2 Leszek Koltunski
542
  public void savePreferences(SharedPreferences.Editor editor)
543
    {
544 d38a302b Leszek Koltunski
    editor.putInt("play_LevelValue", mLevelValue );
545
546 3398a606 Leszek Koltunski
    if( mObjectPopup!=null )
547
      {
548
      mObjectPopup.dismiss();
549
      mObjectPopup = null;
550
      }
551 87d86e5f Leszek Koltunski
552 3398a606 Leszek Koltunski
    if( mMenuPopup!=null )
553
      {
554
      mMenuPopup.dismiss();
555
      mMenuPopup = null;
556
      }
557 69b66386 Leszek Koltunski
    }
558
559 211b48f2 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
560
561
  public void restorePreferences(SharedPreferences preferences)
562
    {
563 1088a219 Leszek Koltunski
    mLevelValue = preferences.getInt("play_LevelValue", 0);
564 7b7d65ce Leszek Koltunski
    }
565
566
///////////////////////////////////////////////////////////////////////////////////////////////////
567 255492a0 Leszek Koltunski
// work around lame bugs in Android's version <= 10 pop-up and split-screen modes
568
569
  private void displayPopup(RubikActivity act, View view, PopupWindow window, int w, int h, int xoff, int yoff)
570
    {
571
    View topLayout = act.findViewById(R.id.relativeLayout);
572 7ac0ee88 Leszek Koltunski
    boolean isFullScreen;
573 00aa398a Leszek Koltunski
574
    if( topLayout!=null )
575
      {
576
      topLayout.getLocationOnScreen(mLocation);
577 7ac0ee88 Leszek Koltunski
      isFullScreen = (mLocation[1]==0);
578 00aa398a Leszek Koltunski
      }
579
    else
580
      {
581 7ac0ee88 Leszek Koltunski
      isFullScreen = true;
582 00aa398a Leszek Koltunski
      }
583 255492a0 Leszek Koltunski
584 69a271f3 Leszek Koltunski
    try
585 255492a0 Leszek Koltunski
      {
586 69a271f3 Leszek Koltunski
      // if on Android 11 or we are fullscreen
587
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R || isFullScreen )
588
        {
589
        window.showAsDropDown(view, xoff, yoff, Gravity.CENTER);
590
        window.update(view, w, h);
591
        }
592
      else  // Android 10 or below in pop-up mode or split-screen mode
593
        {
594
        view.getLocationOnScreen(mLocation);
595
        int width  = view.getWidth();
596
        int height = view.getHeight();
597
        int x = mLocation[0]+(width-w)/2;
598
        int y = mLocation[1]+height+yoff;
599
600
        window.showAsDropDown(view);
601
        window.update(x,y,w,h);
602
        }
603 255492a0 Leszek Koltunski
      }
604 69a271f3 Leszek Koltunski
    catch( IllegalArgumentException iae )
605 255492a0 Leszek Koltunski
      {
606 69a271f3 Leszek Koltunski
      // ignore, this means window is 'not attached to window manager' -
607
      // which most probably is because we are already exiting the app.
608 255492a0 Leszek Koltunski
      }
609
    }
610
611 211b48f2 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
612
613 dca3888a Leszek Koltunski
  public int getLevel()
614 211b48f2 Leszek Koltunski
    {
615 85b09df4 Leszek Koltunski
    return mLevelValue;
616 211b48f2 Leszek Koltunski
    }
617
618 84d746d7 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
619
620
  public void recreatePopup()
621
    {
622
    mObjectPopup = null;
623
    }
624
625 dd874ae8 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
626
627
  public boolean shouldReactToEndOfScrambling()
628
    {
629
    return mShouldReactToEndOfScrambling;
630
    }
631 63dd19c4 Leszek Koltunski
632
///////////////////////////////////////////////////////////////////////////////////////////////////
633
634
  public void receiveUpdate(RubikUpdates updates)
635
    {
636 179f7189 Leszek Koltunski
    Activity act = mWeakAct.get();
637 10373dc7 Leszek Koltunski
638 179f7189 Leszek Koltunski
    if( act!=null )
639 903c7bbc Leszek Koltunski
      {
640 179f7189 Leszek Koltunski
      act.runOnUiThread(new Runnable()
641
        {
642
        @Override
643
        public void run()
644
          {
645 2c9ab085 Leszek Koltunski
          int num = updates.getCompletedNumber();
646 179f7189 Leszek Koltunski
647
          if( num>0 )
648
            {
649
            String shownNum = String.valueOf(num);
650
            mBubbleUpdates.setText(shownNum);
651
            mBubbleUpdates.setVisibility(View.VISIBLE);
652
            int height = (int)(0.05f*mScreenWidth);
653
            mBubbleUpdates.setTextSize(TypedValue.COMPLEX_UNIT_PX,height);
654
            }
655
         else
656
            {
657
            mBubbleUpdates.setVisibility(View.INVISIBLE);
658
            }
659
          }
660
        });
661 903c7bbc Leszek Koltunski
      }
662 63dd19c4 Leszek Koltunski
    }
663
664
///////////////////////////////////////////////////////////////////////////////////////////////////
665
666
  public void errorUpdate()
667
    {
668 c99db493 Leszek Koltunski
    android.util.Log.e("D", "Screen: Error receiving update");
669 63dd19c4 Leszek Koltunski
    }
670 211b48f2 Leszek Koltunski
  }