1 |
c820515c
|
leszek
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
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 |
881697b3
|
leszek
|
import android.content.res.Resources;
|
14 |
0a9adc31
|
leszek
|
import android.graphics.drawable.ColorDrawable;
|
15 |
c820515c
|
leszek
|
import android.os.Build;
|
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 |
|
|
|
25 |
def32b2c
|
leszek
|
import java.lang.ref.WeakReference;
|
26 |
c820515c
|
leszek
|
import java.lang.reflect.Field;
|
27 |
|
|
|
28 |
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
29 |
|
|
|
30 |
|
|
public class MainSettingsPopup implements AdapterView.OnItemSelectedListener
|
31 |
|
|
{
|
32 |
def32b2c
|
leszek
|
public static final int SORT_CLASSIC = 0;
|
33 |
881697b3
|
leszek
|
public static final int SORT_SHAPE = 1;
|
34 |
def32b2c
|
leszek
|
public static final int SORT_DIFFICULTY = 2;
|
35 |
|
|
public static final int SORT_AUTHOR = 3;
|
36 |
|
|
public static final int SORT_YEAR = 4;
|
37 |
|
|
|
38 |
97076b52
|
leszek
|
public static final int SORT_DEFAULT = SORT_SHAPE;
|
39 |
417d51b6
|
leszek
|
|
40 |
def32b2c
|
leszek
|
private static final int[] mLocation = new int[2];
|
41 |
c820515c
|
leszek
|
|
42 |
2eb70e4a
|
leszek
|
private final int mWidth, mHeight;
|
43 |
9881dc03
|
leszek
|
private PopupWindow mPopup;
|
44 |
|
|
private WeakReference<MainActivity> mAct;
|
45 |
c820515c
|
leszek
|
private int mCurrMethod;
|
46 |
881697b3
|
leszek
|
private String[] mSortNames;
|
47 |
9881dc03
|
leszek
|
private int mCurrTheme;
|
48 |
|
|
private String[] mThemeNames;
|
49 |
c820515c
|
leszek
|
|
50 |
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
51 |
|
|
// this is supposed to prevent showing the navigational bar when we show the drop down list,
|
52 |
|
|
// but it doesn't quite work... At least not in the emulator.
|
53 |
|
|
// see https://gist.github.com/kakajika/a236ba721a5c0ad3c1446e16a7423a63
|
54 |
|
|
//
|
55 |
|
|
// EDIT: the bar does not appear on API 34 without the need to call this method. Must have been
|
56 |
|
|
// fixed by Android developers.
|
57 |
|
|
|
58 |
|
|
public static void avoidSpinnerDropdownFocus(Spinner spinner)
|
59 |
|
|
{
|
60 |
|
|
try
|
61 |
|
|
{
|
62 |
|
|
Field listPopupField = Spinner.class.getDeclaredField("mPopup");
|
63 |
|
|
listPopupField.setAccessible(true);
|
64 |
|
|
Object listPopup = listPopupField.get(spinner);
|
65 |
|
|
|
66 |
|
|
if( listPopup instanceof ListPopupWindow )
|
67 |
|
|
{
|
68 |
|
|
Field popupField = ListPopupWindow.class.getDeclaredField("mPopup");
|
69 |
|
|
popupField.setAccessible(true);
|
70 |
|
|
Object popup = popupField.get((ListPopupWindow) listPopup);
|
71 |
|
|
|
72 |
|
|
if( popup instanceof PopupWindow )
|
73 |
|
|
{
|
74 |
|
|
((PopupWindow) popup).setFocusable(false);
|
75 |
|
|
}
|
76 |
|
|
}
|
77 |
|
|
}
|
78 |
|
|
catch (NoSuchFieldException | IllegalAccessException ignored)
|
79 |
|
|
{
|
80 |
|
|
|
81 |
|
|
}
|
82 |
|
|
}
|
83 |
|
|
|
84 |
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
85 |
|
|
|
86 |
9b6f8f18
|
leszek
|
MainSettingsPopup(MainActivity act, int sortMethod, int themeValue, int popupWidth, int popupHeight)
|
87 |
c820515c
|
leszek
|
{
|
88 |
def32b2c
|
leszek
|
mAct = new WeakReference<>(act);
|
89 |
|
|
|
90 |
2eb70e4a
|
leszek
|
mWidth = popupWidth;
|
91 |
|
|
mHeight= popupHeight;
|
92 |
|
|
|
93 |
c820515c
|
leszek
|
// due to bugs in Android API <=25, a Spinner inside a PopupWindow will crash once you click on it.
|
94 |
|
|
// solution: on those APIs, use a special Spinner in dialog mode (this does not crash)
|
95 |
|
|
int id = android.os.Build.VERSION.SDK_INT <= 25 ? R.layout.settings_popup_android25 : R.layout.settings_popup;
|
96 |
|
|
|
97 |
|
|
LayoutInflater layoutInflater = (LayoutInflater) act.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
98 |
|
|
final View layout = layoutInflater.inflate(id, null);
|
99 |
0a9adc31
|
leszek
|
final View title = layout.findViewById(R.id.settingsTitle);
|
100 |
c820515c
|
leszek
|
|
101 |
|
|
mPopup = new PopupWindow(act);
|
102 |
|
|
mPopup.setContentView(layout);
|
103 |
|
|
mPopup.setFocusable(true);
|
104 |
|
|
|
105 |
0a9adc31
|
leszek
|
Resources res = act.getResources();
|
106 |
|
|
int d = res.getColor(act.getDarkTrans());
|
107 |
|
|
int l = res.getColor(act.getLightTrans());
|
108 |
|
|
|
109 |
|
|
mPopup.setBackgroundDrawable(new ColorDrawable(l));
|
110 |
|
|
title.setBackground(new ColorDrawable(d));
|
111 |
|
|
mPopup.setElevation(100);
|
112 |
|
|
|
113 |
9881dc03
|
leszek
|
Spinner sortSpinner = layout.findViewById(R.id.sortMethod);
|
114 |
|
|
sortSpinner.setOnItemSelectedListener(this);
|
115 |
c820515c
|
leszek
|
|
116 |
acee3e3e
|
leszek
|
mCurrMethod = sortMethod;
|
117 |
881697b3
|
leszek
|
buildSortOptions(act);
|
118 |
c820515c
|
leszek
|
|
119 |
2eb70e4a
|
leszek
|
ArrayAdapter<String> sortAdapter = new ArrayAdapter<>(act, R.layout.settings_spinner_item, mSortNames);
|
120 |
236cc1c1
|
leszek
|
sortAdapter.setDropDownViewResource(R.layout.settings_spinner_item);
|
121 |
9881dc03
|
leszek
|
sortSpinner.setAdapter(sortAdapter);
|
122 |
acee3e3e
|
leszek
|
|
123 |
9881dc03
|
leszek
|
if( sortMethod>=0 && sortMethod<mSortNames.length ) sortSpinner.setSelection(sortMethod);
|
124 |
|
|
|
125 |
|
|
Spinner themeSpinner = layout.findViewById(R.id.themeValue);
|
126 |
|
|
themeSpinner.setOnItemSelectedListener(this);
|
127 |
|
|
|
128 |
|
|
mCurrTheme = themeValue;
|
129 |
|
|
buildThemeOptions(act);
|
130 |
|
|
|
131 |
2eb70e4a
|
leszek
|
ArrayAdapter<String> themeAdapter = new ArrayAdapter<>(act, R.layout.settings_spinner_item, mThemeNames);
|
132 |
236cc1c1
|
leszek
|
themeAdapter.setDropDownViewResource(R.layout.settings_spinner_item);
|
133 |
9881dc03
|
leszek
|
themeSpinner.setAdapter(themeAdapter);
|
134 |
|
|
|
135 |
|
|
if( themeValue>=0 && themeValue<mThemeNames.length ) themeSpinner.setSelection(themeValue);
|
136 |
c820515c
|
leszek
|
}
|
137 |
881697b3
|
leszek
|
|
138 |
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
139 |
|
|
|
140 |
|
|
private void buildSortOptions(MainActivity act)
|
141 |
|
|
{
|
142 |
|
|
Resources res = act.getResources();
|
143 |
|
|
mSortNames = new String[5];
|
144 |
|
|
|
145 |
|
|
mSortNames[0] = res.getString(R.string.sort_classic);
|
146 |
|
|
mSortNames[1] = res.getString(R.string.sort_shape);
|
147 |
|
|
mSortNames[2] = res.getString(R.string.sort_difficulty);
|
148 |
|
|
mSortNames[3] = res.getString(R.string.sort_author);
|
149 |
|
|
mSortNames[4] = res.getString(R.string.sort_year);
|
150 |
|
|
}
|
151 |
c820515c
|
leszek
|
|
152 |
9881dc03
|
leszek
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
153 |
|
|
|
154 |
|
|
private void buildThemeOptions(MainActivity act)
|
155 |
|
|
{
|
156 |
|
|
Resources res = act.getResources();
|
157 |
2456eaa0
|
leszek
|
mThemeNames = new String[5];
|
158 |
9881dc03
|
leszek
|
|
159 |
7214ddf1
|
leszek
|
mThemeNames[0] = res.getString(R.string.theme_green);
|
160 |
2456eaa0
|
leszek
|
mThemeNames[1] = res.getString(R.string.theme_blue);
|
161 |
7214ddf1
|
leszek
|
mThemeNames[2] = res.getString(R.string.theme_grey);
|
162 |
2456eaa0
|
leszek
|
mThemeNames[3] = res.getString(R.string.theme_pink);
|
163 |
|
|
mThemeNames[4] = res.getString(R.string.theme_orange);
|
164 |
9881dc03
|
leszek
|
}
|
165 |
|
|
|
166 |
c820515c
|
leszek
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
167 |
|
|
// work around lame bugs in Android's version <= 10 pop-up and split-screen modes
|
168 |
|
|
|
169 |
2eb70e4a
|
leszek
|
public void displayPopup(MainActivity act, View view, int xoff, int yoff)
|
170 |
c820515c
|
leszek
|
{
|
171 |
|
|
View v = mPopup.getContentView();
|
172 |
|
|
v.setSystemUiVisibility(MainActivity.FLAGS);
|
173 |
|
|
|
174 |
|
|
View topLayout = act.findViewById(R.id.relativeLayout);
|
175 |
|
|
|
176 |
|
|
boolean isFullScreen;
|
177 |
|
|
|
178 |
|
|
if( topLayout!=null )
|
179 |
|
|
{
|
180 |
|
|
topLayout.getLocationOnScreen(mLocation);
|
181 |
|
|
isFullScreen = (mLocation[1]==0);
|
182 |
|
|
}
|
183 |
|
|
else
|
184 |
|
|
{
|
185 |
|
|
isFullScreen = true;
|
186 |
|
|
}
|
187 |
|
|
|
188 |
|
|
try
|
189 |
|
|
{
|
190 |
|
|
// if on Android 11 or we are fullscreen
|
191 |
|
|
if (Build.VERSION_CODES.R<=Build.VERSION.SDK_INT || isFullScreen )
|
192 |
|
|
{
|
193 |
|
|
mPopup.showAsDropDown(view, xoff, yoff, Gravity.CENTER);
|
194 |
2eb70e4a
|
leszek
|
mPopup.update(view, mWidth, mHeight);
|
195 |
c820515c
|
leszek
|
}
|
196 |
|
|
else // Android 10 or below in pop-up mode or split-screen mode
|
197 |
|
|
{
|
198 |
|
|
view.getLocationOnScreen(mLocation);
|
199 |
|
|
int width = view.getWidth();
|
200 |
|
|
int height = view.getHeight();
|
201 |
2eb70e4a
|
leszek
|
int x = mLocation[0]+(width-mWidth)/2;
|
202 |
c820515c
|
leszek
|
int y = mLocation[1]+height+yoff;
|
203 |
|
|
mPopup.showAsDropDown(view);
|
204 |
2eb70e4a
|
leszek
|
mPopup.update(x,y,mWidth,mHeight);
|
205 |
c820515c
|
leszek
|
}
|
206 |
|
|
}
|
207 |
|
|
catch( IllegalArgumentException iae )
|
208 |
|
|
{
|
209 |
|
|
// ignore, this means window is 'not attached to window manager' -
|
210 |
|
|
// which most probably is because we are already exiting the app.
|
211 |
|
|
}
|
212 |
|
|
}
|
213 |
|
|
|
214 |
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
215 |
|
|
|
216 |
|
|
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id)
|
217 |
|
|
{
|
218 |
|
|
if( parent.getId()==R.id.sortMethod && mCurrMethod!=pos )
|
219 |
|
|
{
|
220 |
9881dc03
|
leszek
|
mPopup.dismiss();
|
221 |
c820515c
|
leszek
|
mCurrMethod = pos;
|
222 |
def32b2c
|
leszek
|
MainActivity act = mAct.get();
|
223 |
|
|
act.sortObjectsBy(pos);
|
224 |
9881dc03
|
leszek
|
}
|
225 |
|
|
if( parent.getId()==R.id.themeValue && mCurrTheme!=pos )
|
226 |
|
|
{
|
227 |
acee3e3e
|
leszek
|
mPopup.dismiss();
|
228 |
9881dc03
|
leszek
|
mPopup = null;
|
229 |
|
|
mCurrTheme = pos;
|
230 |
|
|
MainActivity act = mAct.get();
|
231 |
|
|
mAct = null;
|
232 |
|
|
act.changeThemeTo(pos);
|
233 |
c820515c
|
leszek
|
}
|
234 |
|
|
}
|
235 |
|
|
|
236 |
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
237 |
|
|
|
238 |
|
|
public void onNothingSelected(AdapterView<?> parent)
|
239 |
|
|
{
|
240 |
|
|
|
241 |
|
|
}
|
242 |
|
|
}
|