Project

General

Profile

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

magiccube / src / main / java / org / distorted / config / ConfigScreen.java @ 280dc794

1 1237d25d 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
package org.distorted.config;
21
22 97a4ae23 Leszek Koltunski
import android.content.res.Resources;
23
import android.graphics.drawable.BitmapDrawable;
24
import android.os.Build;
25
import android.util.TypedValue;
26
import android.view.Gravity;
27 1237d25d Leszek Koltunski
import android.view.View;
28 97a4ae23 Leszek Koltunski
import android.widget.GridLayout;
29
import android.widget.ImageButton;
30 1237d25d Leszek Koltunski
import android.widget.LinearLayout;
31 97a4ae23 Leszek Koltunski
import android.widget.PopupWindow;
32
import android.widget.ScrollView;
33
import android.widget.TextView;
34
35
import org.distorted.objectlib.main.ObjectControl;
36 1237d25d Leszek Koltunski
37
import org.distorted.helpers.TransparentImageButton;
38
import org.distorted.main.R;
39
import org.distorted.main.RubikActivity;
40 a7d8c3cd Leszek Koltunski
import org.distorted.objects.RubikObject;
41
import org.distorted.objects.RubikObjectList;
42 97a4ae23 Leszek Koltunski
43
import static android.view.View.inflate;
44 1237d25d Leszek Koltunski
45
///////////////////////////////////////////////////////////////////////////////////////////////////
46
47
public class ConfigScreen
48
{
49 97a4ae23 Leszek Koltunski
  private static final int NUM_COLUMNS = 4;
50
  private static final int[] mLocation = new int[2];
51
52
  private TransparentImageButton mBackButton, mObjectButton, mPrevButton, mNextButton;
53
  private TextView mMovesText;
54
  private PopupWindow mObjectPopup;
55 74d088c3 Leszek Koltunski
  private ConfigScreenPane mPane;
56 97a4ae23 Leszek Koltunski
  private int mObjectOrdinal;
57
  private int mColCount, mRowCount, mMaxRowCount;
58
  private int mObjectSize;
59
  private int mBarHeight;
60
  private float mButtonSize;
61
62
///////////////////////////////////////////////////////////////////////////////////////////////////
63
64
  private void setupObjectWindow(final ConfigActivity act, final float width, final float height)
65
    {
66
    int icon = RubikActivity.getDrawable(R.drawable.cube_2s,R.drawable.cube_2m, R.drawable.cube_2b, R.drawable.cube_2h);
67
68
    Resources res = act.getResources();
69
    BitmapDrawable bd = (BitmapDrawable)res.getDrawable(icon);
70
    int cubeWidth = bd.getIntrinsicWidth();
71
    int margin = (int)(width*RubikActivity.LARGE_MARGIN);
72
    mObjectSize = (int)(cubeWidth + 2*margin + 0.5f);
73
    mMaxRowCount = (int)((height-mBarHeight)/mObjectSize);
74
75
    ScrollView view = (ScrollView)inflate( act, R.layout.popup_object_simple, null);
76
    GridLayout objectGrid = view.findViewById(R.id.objectGrid);
77
78
    GridLayout.Spec[] rowSpecs = new GridLayout.Spec[mRowCount];
79
    GridLayout.Spec[] colSpecs = new GridLayout.Spec[mColCount];
80
81
    objectGrid.setColumnCount(mColCount);
82
    objectGrid.setRowCount(mRowCount);
83
84
    mObjectPopup = new PopupWindow(act);
85
    mObjectPopup.setFocusable(true);
86
    mObjectPopup.setContentView(view);
87
88
    int[] nextInRow = new int[mRowCount];
89
90
    for(int row=0; row<mRowCount; row++)
91
      {
92
      rowSpecs[row] = GridLayout.spec(row);
93
      nextInRow[row]= 0;
94
      }
95
    for(int col=0; col<mColCount; col++)
96
      {
97
      colSpecs[col] = GridLayout.spec(col);
98
      }
99
100 a7d8c3cd Leszek Koltunski
    int numObjects = RubikObjectList.getNumObjects();
101
102
    for(int object=0; object<numObjects; object++)
103 97a4ae23 Leszek Koltunski
      {
104
      final int ordinal = object;
105 a7d8c3cd Leszek Koltunski
      RubikObject rubikObject = RubikObjectList.getObject(ordinal);
106 97a4ae23 Leszek Koltunski
      int iconSize = RubikActivity.getDrawableSize();
107 a7d8c3cd Leszek Koltunski
      int icons = rubikObject.getIconID(iconSize);
108 97a4ae23 Leszek Koltunski
      int row = object/NUM_COLUMNS;
109
110
      ImageButton button = new ImageButton(act);
111
      button.setBackgroundResource(icons);
112
      button.setOnClickListener( new View.OnClickListener()
113
        {
114
        @Override
115
        public void onClick(View v)
116
          {
117
          if( act.getControl().isUINotBlocked() && mObjectOrdinal!=ordinal )
118
            {
119
            mObjectOrdinal = ordinal;
120 280dc794 Leszek Koltunski
            act.changeObject(mObjectOrdinal);
121 a7d8c3cd Leszek Koltunski
            mMovesText.setText(act.getString(R.string.mo_placeholder,mObjectOrdinal+1,numObjects));
122 74d088c3 Leszek Koltunski
            mPane.updatePane(act,mObjectOrdinal);
123 97a4ae23 Leszek Koltunski
            }
124
125
          mObjectPopup.dismiss();
126
          }
127
        });
128
129
      GridLayout.LayoutParams params = new GridLayout.LayoutParams(rowSpecs[row],colSpecs[nextInRow[row]]);
130
      params.bottomMargin = margin;
131
      params.topMargin    = margin;
132
      params.leftMargin   = margin;
133
      params.rightMargin  = margin;
134
135
      nextInRow[row]++;
136
137
      objectGrid.addView(button, params);
138
      }
139
    }
140 1237d25d Leszek Koltunski
141
///////////////////////////////////////////////////////////////////////////////////////////////////
142
143
  private void setupBackButton(final ConfigActivity act)
144
    {
145
    int icon = RubikActivity.getDrawable(R.drawable.ui_small_smallback,R.drawable.ui_medium_smallback, R.drawable.ui_big_smallback, R.drawable.ui_huge_smallback);
146 97a4ae23 Leszek Koltunski
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);
147 1237d25d Leszek Koltunski
    mBackButton = new TransparentImageButton(act, icon, TransparentImageButton.GRAVITY_MIDDLE, params);
148
149
    mBackButton.setOnClickListener( new View.OnClickListener()
150
      {
151
      @Override
152
      public void onClick(View v)
153
        {
154
        ObjectControl control = act.getControl();
155
        if( control!=null ) control.unblockEverything();
156
        act.finish();
157
        }
158
      });
159
    }
160
161
///////////////////////////////////////////////////////////////////////////////////////////////////
162
163 97a4ae23 Leszek Koltunski
  private void setupObjectButton(final ConfigActivity act, final int width)
164 1237d25d Leszek Koltunski
    {
165 97a4ae23 Leszek Koltunski
    final int margin= (int)(width*RubikActivity.MARGIN);
166
    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);
167
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);
168
    mObjectButton = new TransparentImageButton(act, icon, TransparentImageButton.GRAVITY_MIDDLE, params);
169
170
    mObjectButton.setOnClickListener( new View.OnClickListener()
171
      {
172
      @Override
173
      public void onClick(View view)
174
        {
175
        if( mObjectPopup==null )
176
          {
177
          float height= act.getScreenHeightInPixels();
178
          setupObjectWindow(act,width,height);
179
          }
180
181
        if( act.getControl().isUINotBlocked())
182
          {
183
          int rowCount = Math.min(mMaxRowCount,mRowCount);
184
          View popupView = mObjectPopup.getContentView();
185
          popupView.setSystemUiVisibility(RubikActivity.FLAGS);
186
          displayPopup(act,view,mObjectPopup,mObjectSize*mColCount,mObjectSize*rowCount,margin,margin);
187
          }
188
        }
189
      });
190
    }
191
192
///////////////////////////////////////////////////////////////////////////////////////////////////
193
// work around lame bugs in Android's version <= 10 pop-up and split-screen modes
194
195
  private void displayPopup(ConfigActivity act, View view, PopupWindow window, int w, int h, int xoff, int yoff)
196
    {
197
    View topLayout = act.findViewById(R.id.mainLayout);
198
    boolean isFullScreen;
199
200
    if( topLayout!=null )
201
      {
202
      topLayout.getLocationOnScreen(mLocation);
203
      isFullScreen = (mLocation[1]==0);
204
      }
205
    else
206
      {
207
      isFullScreen = true;
208
      }
209
210
    try
211
      {
212
      // if on Android 11 or we are fullscreen
213
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R || isFullScreen )
214
        {
215
        window.showAsDropDown(view, xoff, yoff, Gravity.CENTER);
216
        window.update(view, w, h);
217
        }
218
      else  // Android 10 or below in pop-up mode or split-screen mode
219
        {
220
        view.getLocationOnScreen(mLocation);
221
        int width  = view.getWidth();
222
        int height = view.getHeight();
223
        int x = mLocation[0]+(width-w)/2;
224
        int y = mLocation[1]+height+yoff;
225
226
        window.showAsDropDown(view);
227
        window.update(x,y,w,h);
228
        }
229
      }
230
    catch( IllegalArgumentException iae )
231
      {
232
      // ignore, this means window is 'not attached to window manager' -
233
      // which most probably is because we are already exiting the app.
234
      }
235 1237d25d Leszek Koltunski
    }
236
237
///////////////////////////////////////////////////////////////////////////////////////////////////
238
239 a7d8c3cd Leszek Koltunski
  private void prevObject(ConfigActivity act, int numObjects)
240 1237d25d Leszek Koltunski
    {
241 97a4ae23 Leszek Koltunski
    mObjectOrdinal--;
242 a7d8c3cd Leszek Koltunski
    if( mObjectOrdinal<0 ) mObjectOrdinal=numObjects-1;
243 97a4ae23 Leszek Koltunski
244 280dc794 Leszek Koltunski
    act.changeObject(mObjectOrdinal);
245 74d088c3 Leszek Koltunski
    mPane.updatePane(act,mObjectOrdinal);
246 97a4ae23 Leszek Koltunski
    }
247
248
///////////////////////////////////////////////////////////////////////////////////////////////////
249
250 a7d8c3cd Leszek Koltunski
  private void nextObject(ConfigActivity act, int numObjects)
251 97a4ae23 Leszek Koltunski
    {
252
    mObjectOrdinal++;
253 a7d8c3cd Leszek Koltunski
    if( mObjectOrdinal>=numObjects ) mObjectOrdinal=0;
254 97a4ae23 Leszek Koltunski
255 280dc794 Leszek Koltunski
    act.changeObject(mObjectOrdinal);
256 74d088c3 Leszek Koltunski
    mPane.updatePane(act,mObjectOrdinal);
257 97a4ae23 Leszek Koltunski
    }
258
259
///////////////////////////////////////////////////////////////////////////////////////////////////
260
261
  private void setupPrevButton(final ConfigActivity act)
262
    {
263
    int icon = RubikActivity.getDrawable(R.drawable.ui_small_left,R.drawable.ui_medium_left, R.drawable.ui_big_left, R.drawable.ui_huge_left);
264
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
265
    mPrevButton = new TransparentImageButton(act,icon,TransparentImageButton.GRAVITY_MIDDLE,params);
266
267
    mPrevButton.setOnClickListener( new View.OnClickListener()
268
      {
269
      @Override
270
      public void onClick(View v)
271
        {
272 a7d8c3cd Leszek Koltunski
        int numObjects = RubikObjectList.getNumObjects();
273
        prevObject(act,numObjects);
274
        mMovesText.setText(act.getString(R.string.mo_placeholder,mObjectOrdinal+1,numObjects));
275 97a4ae23 Leszek Koltunski
        }
276
      });
277
    }
278
279
///////////////////////////////////////////////////////////////////////////////////////////////////
280
281
  private void setupNextButton(final ConfigActivity act)
282
    {
283
    int icon = RubikActivity.getDrawable(R.drawable.ui_small_right,R.drawable.ui_medium_right, R.drawable.ui_big_right, R.drawable.ui_huge_right);
284
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
285
    mNextButton = new TransparentImageButton(act,icon,TransparentImageButton.GRAVITY_MIDDLE,params);
286
287
    mNextButton.setOnClickListener( new View.OnClickListener()
288
      {
289
      @Override
290
      public void onClick(View v)
291
        {
292 a7d8c3cd Leszek Koltunski
        int numObjects = RubikObjectList.getNumObjects();
293
        nextObject(act,numObjects);
294
        mMovesText.setText(act.getString(R.string.mo_placeholder,mObjectOrdinal+1,numObjects));
295 97a4ae23 Leszek Koltunski
        }
296
      });
297
    }
298
299
///////////////////////////////////////////////////////////////////////////////////////////////////
300
301 a7d8c3cd Leszek Koltunski
  private void setupTextView(final ConfigActivity act, final float width, int numObjects)
302 97a4ae23 Leszek Koltunski
    {
303
    int padding = (int)(width*RubikActivity.PADDING);
304
    int margin  = (int)(width*RubikActivity.MARGIN);
305
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0,LinearLayout.LayoutParams.MATCH_PARENT,2.0f);
306
    params.topMargin    = margin;
307
    params.bottomMargin = margin;
308
    params.leftMargin   = margin;
309
    params.rightMargin  = margin;
310
311
    mMovesText = new TextView(act);
312
    mMovesText.setTextSize(20);
313
    mMovesText.setLayoutParams(params);
314
    mMovesText.setPadding(padding,0,padding,0);
315
    mMovesText.setGravity(Gravity.CENTER);
316
    mMovesText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mButtonSize);
317 a7d8c3cd Leszek Koltunski
    mMovesText.setText(act.getString(R.string.mo_placeholder,mObjectOrdinal+1,numObjects));
318 97a4ae23 Leszek Koltunski
    }
319
320 8bf8fe70 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
321
322 74d088c3 Leszek Koltunski
  void onAttachedToWindow(final ConfigActivity act, final int objectOrdinal)
323 97a4ae23 Leszek Koltunski
    {
324 a7d8c3cd Leszek Koltunski
    int numObjects = RubikObjectList.getNumObjects();
325 97a4ae23 Leszek Koltunski
    int width = act.getScreenWidthInPixels();
326
    mBarHeight = act.getHeightBar();
327
    mButtonSize = width*RubikActivity.BUTTON_TEXT_SIZE;
328
329 a7d8c3cd Leszek Koltunski
    mRowCount = (numObjects + NUM_COLUMNS-1) / NUM_COLUMNS;
330 97a4ae23 Leszek Koltunski
    mColCount = NUM_COLUMNS;
331
332
    mObjectOrdinal = objectOrdinal;
333
334 74d088c3 Leszek Koltunski
    LinearLayout.LayoutParams paramsL = new LinearLayout.LayoutParams(width/4, LinearLayout.LayoutParams.MATCH_PARENT);
335
    LinearLayout.LayoutParams paramsM = new LinearLayout.LayoutParams(width/2, LinearLayout.LayoutParams.MATCH_PARENT);
336
    LinearLayout.LayoutParams paramsR = new LinearLayout.LayoutParams(width/4, LinearLayout.LayoutParams.MATCH_PARENT);
337 97a4ae23 Leszek Koltunski
338
    LinearLayout layoutLeft = new LinearLayout(act);
339
    layoutLeft.setLayoutParams(paramsL);
340
    LinearLayout layoutMid  = new LinearLayout(act);
341
    layoutMid.setLayoutParams(paramsM);
342
    LinearLayout layoutRight= new LinearLayout(act);
343
    layoutRight.setLayoutParams(paramsR);
344
345
    setupObjectButton(act,width);
346
    setupPrevButton(act);
347
    setupNextButton(act);
348 a7d8c3cd Leszek Koltunski
    setupTextView(act,width,numObjects);
349 97a4ae23 Leszek Koltunski
    setupBackButton(act);
350
351
    layoutLeft.addView(mObjectButton);
352
    layoutMid.addView(mPrevButton);
353
    layoutMid.addView(mMovesText);
354
    layoutMid.addView(mNextButton);
355
    layoutRight.addView(mBackButton);
356
357
    LinearLayout layout = act.findViewById(R.id.lowerBar);
358
    layout.removeAllViews();
359
    layout.addView(layoutLeft);
360
    layout.addView(layoutMid);
361
    layout.addView(layoutRight);
362 1237d25d Leszek Koltunski
363 74d088c3 Leszek Koltunski
    mPane = new ConfigScreenPane(act,mObjectOrdinal);
364 1237d25d Leszek Koltunski
    }
365
}