Project

General

Profile

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

magiccube / src / main / java / org / distorted / main / MainSettingsPopup.java @ 2eb70e4a

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2023 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9

    
10
package org.distorted.main;
11

    
12
import android.content.Context;
13
import android.content.res.Resources;
14
import android.os.Build;
15
import android.util.TypedValue;
16
import android.view.Gravity;
17
import android.view.LayoutInflater;
18
import android.view.View;
19
import android.widget.AdapterView;
20
import android.widget.ArrayAdapter;
21
import android.widget.ListPopupWindow;
22
import android.widget.PopupWindow;
23
import android.widget.Spinner;
24
import android.widget.TextView;
25

    
26
import java.lang.ref.WeakReference;
27
import java.lang.reflect.Field;
28

    
29
///////////////////////////////////////////////////////////////////////////////////////////////////
30

    
31
public class MainSettingsPopup implements AdapterView.OnItemSelectedListener
32
  {
33
  public static final int SORT_CLASSIC    = 0;
34
  public static final int SORT_SHAPE      = 1;
35
  public static final int SORT_DIFFICULTY = 2;
36
  public static final int SORT_AUTHOR     = 3;
37
  public static final int SORT_YEAR       = 4;
38

    
39
  public static final int SORT_DEFAULT    = SORT_SHAPE;
40

    
41
  private static final float MENU_TITLE_SIZE= 0.070f;
42
  private static final float MENU_TEXT_SIZE = 0.060f;
43
  private static final int[] mLocation = new int[2];
44

    
45
  private final int mWidth, mHeight;
46
  private PopupWindow mPopup;
47
  private WeakReference<MainActivity> mAct;
48
  private int mCurrMethod;
49
  private String[] mSortNames;
50
  private int mCurrTheme;
51
  private String[] mThemeNames;
52

    
53
///////////////////////////////////////////////////////////////////////////////////////////////////
54
// this is supposed to prevent showing the navigational bar when we show the drop down list,
55
// but it doesn't quite work... At least not in the emulator.
56
// see https://gist.github.com/kakajika/a236ba721a5c0ad3c1446e16a7423a63
57
//
58
// EDIT: the bar does not appear on API 34 without the need to call this method. Must have been
59
// fixed by Android developers.
60

    
61
  public static void avoidSpinnerDropdownFocus(Spinner spinner)
62
    {
63
    try
64
      {
65
      Field listPopupField = Spinner.class.getDeclaredField("mPopup");
66
      listPopupField.setAccessible(true);
67
      Object listPopup = listPopupField.get(spinner);
68

    
69
      if( listPopup instanceof ListPopupWindow )
70
        {
71
        Field popupField = ListPopupWindow.class.getDeclaredField("mPopup");
72
        popupField.setAccessible(true);
73
        Object popup = popupField.get((ListPopupWindow) listPopup);
74

    
75
        if( popup instanceof PopupWindow )
76
          {
77
          ((PopupWindow) popup).setFocusable(false);
78
          }
79
        }
80
      }
81
    catch (NoSuchFieldException | IllegalAccessException ignored)
82
      {
83

    
84
      }
85
    }
86

    
87
///////////////////////////////////////////////////////////////////////////////////////////////////
88

    
89
  MainSettingsPopup(MainActivity act, int sortMethod, int themeValue,
90
                    int scrWidth, int popupWidth, int popupHeight)
91
    {
92
    mAct = new WeakReference<>(act);
93

    
94
    mWidth = popupWidth;
95
    mHeight= popupHeight;
96

    
97
    // due to bugs in Android API <=25, a Spinner inside a PopupWindow will crash once you click on it.
98
    // solution: on those APIs, use a special Spinner in dialog mode (this does not crash)
99
    int id = android.os.Build.VERSION.SDK_INT <= 25 ? R.layout.settings_popup_android25 : R.layout.settings_popup;
100

    
101
    LayoutInflater layoutInflater = (LayoutInflater) act.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
102
    final View layout = layoutInflater.inflate(id, null);
103

    
104
    mPopup = new PopupWindow(act);
105
    mPopup.setContentView(layout);
106
    mPopup.setFocusable(true);
107

    
108
    int titleSize = (int)(0.26f*popupHeight);
109
    int textSize  = (int)(0.19f*popupHeight);
110

    
111
    TextView title = layout.findViewById(R.id.settingsTitle);
112
    //title.setTextSize(TypedValue.COMPLEX_UNIT_PX, titleSize);
113
    TextView sortText = layout.findViewById(R.id.sortText);
114
    //sortText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
115
    TextView themeTitle = layout.findViewById(R.id.themeText);
116
   // themeTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
117

    
118
    Spinner sortSpinner  = layout.findViewById(R.id.sortMethod);
119
    sortSpinner.setOnItemSelectedListener(this);
120

    
121
    mCurrMethod = sortMethod;
122
    buildSortOptions(act);
123

    
124
    ArrayAdapter<String> sortAdapter = new ArrayAdapter<>(act, R.layout.settings_spinner_item, mSortNames);
125
    sortAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
126
    sortSpinner.setAdapter(sortAdapter);
127

    
128
    if( sortMethod>=0 && sortMethod<mSortNames.length ) sortSpinner.setSelection(sortMethod);
129

    
130
    Spinner themeSpinner  = layout.findViewById(R.id.themeValue);
131
    themeSpinner.setOnItemSelectedListener(this);
132

    
133
    mCurrTheme = themeValue;
134
    buildThemeOptions(act);
135

    
136
    ArrayAdapter<String> themeAdapter = new ArrayAdapter<>(act, R.layout.settings_spinner_item, mThemeNames);
137
    themeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
138
    themeSpinner.setAdapter(themeAdapter);
139

    
140
    if( themeValue>=0 && themeValue<mThemeNames.length ) themeSpinner.setSelection(themeValue);
141
    }
142

    
143
///////////////////////////////////////////////////////////////////////////////////////////////////
144

    
145
  private void buildSortOptions(MainActivity act)
146
    {
147
    Resources res = act.getResources();
148
    mSortNames = new String[5];
149

    
150
    mSortNames[0] = res.getString(R.string.sort_classic);
151
    mSortNames[1] = res.getString(R.string.sort_shape);
152
    mSortNames[2] = res.getString(R.string.sort_difficulty);
153
    mSortNames[3] = res.getString(R.string.sort_author);
154
    mSortNames[4] = res.getString(R.string.sort_year);
155
    }
156

    
157
///////////////////////////////////////////////////////////////////////////////////////////////////
158

    
159
  private void buildThemeOptions(MainActivity act)
160
    {
161
    Resources res = act.getResources();
162
    mThemeNames = new String[3];
163

    
164
    mThemeNames[0] = res.getString(R.string.theme_grey);
165
    mThemeNames[1] = res.getString(R.string.theme_white);
166
    mThemeNames[2] = res.getString(R.string.theme_green);
167
    }
168

    
169
///////////////////////////////////////////////////////////////////////////////////////////////////
170
// work around lame bugs in Android's version <= 10 pop-up and split-screen modes
171

    
172
  public void displayPopup(MainActivity act, View view, int xoff, int yoff)
173
    {
174
    View v = mPopup.getContentView();
175
    v.setSystemUiVisibility(MainActivity.FLAGS);
176

    
177
    View topLayout = act.findViewById(R.id.relativeLayout);
178

    
179
    boolean isFullScreen;
180

    
181
    if( topLayout!=null )
182
      {
183
      topLayout.getLocationOnScreen(mLocation);
184
      isFullScreen = (mLocation[1]==0);
185
      }
186
    else
187
      {
188
      isFullScreen = true;
189
      }
190

    
191
    try
192
      {
193
      // if on Android 11 or we are fullscreen
194
      if (Build.VERSION_CODES.R<=Build.VERSION.SDK_INT || isFullScreen )
195
        {
196
        mPopup.showAsDropDown(view, xoff, yoff, Gravity.CENTER);
197
        mPopup.update(view, mWidth, mHeight);
198
        }
199
      else  // Android 10 or below in pop-up mode or split-screen mode
200
        {
201
        view.getLocationOnScreen(mLocation);
202
        int width  = view.getWidth();
203
        int height = view.getHeight();
204
        int x = mLocation[0]+(width-mWidth)/2;
205
        int y = mLocation[1]+height+yoff;
206
        mPopup.showAsDropDown(view);
207
        mPopup.update(x,y,mWidth,mHeight);
208
        }
209
      }
210
    catch( IllegalArgumentException iae )
211
      {
212
      // ignore, this means window is 'not attached to window manager' -
213
      // which most probably is because we are already exiting the app.
214
      }
215
    }
216

    
217
///////////////////////////////////////////////////////////////////////////////////////////////////
218

    
219
  public void onItemSelected(AdapterView<?> parent, View view, int pos, long id)
220
    {
221
    if( parent.getId()==R.id.sortMethod && mCurrMethod!=pos )
222
      {
223
      mPopup.dismiss();
224
      mCurrMethod = pos;
225
      MainActivity act = mAct.get();
226
      act.sortObjectsBy(pos);
227
      }
228
    if( parent.getId()==R.id.themeValue && mCurrTheme!=pos )
229
      {
230
      mPopup.dismiss();
231
      mPopup = null;
232
      mCurrTheme = pos;
233
      MainActivity act = mAct.get();
234
      mAct = null;
235
      act.changeThemeTo(pos);
236
      }
237
    }
238

    
239
///////////////////////////////////////////////////////////////////////////////////////////////////
240

    
241
  public void onNothingSelected(AdapterView<?> parent)
242
    {
243

    
244
    }
245
  }
246

    
(4-4/4)