Skip to content

Commit acd2481

Browse files
committed
Search, Sort of UiPager & Bug fixes
1 parent 6c2920a commit acd2481

File tree

21 files changed

+632
-63
lines changed

21 files changed

+632
-63
lines changed

.idea/dictionaries/twisted.xml

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/inspectionProfiles/Project_Default.xml

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

SuperiorPlugin/build.gradle

+8-4
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,12 @@ dependencies {
3434
testImplementation 'junit:junit:4.13.2'
3535
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
3636
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
37-
implementation "org.jmonkeyengine:jme3-core:3.4.0-beta1"
38-
implementation "org.jmonkeyengine:jme3-effects:3.4.0-beta1"
39-
implementation "org.jmonkeyengine:jme3-android-native:3.4.0-beta1"
40-
implementation 'com.github.stephengold:Minie:4.0.0'
37+
implementation "org.jmonkeyengine:jme3-core:3.4.0-beta4"
38+
implementation "org.jmonkeyengine:jme3-effects:3.4.0-beta4"
39+
implementation "org.jmonkeyengine:jme3-android-native:3.4.0-beta4"
40+
//noinspection GradleDynamicVersion
41+
implementation 'com.github.stephengold:Minie:4.1.0+for33'
42+
implementation "androidx.work:work-runtime:2.5.0"
43+
implementation "androidx.concurrent:concurrent-futures:1.1.0"
44+
4145
}

SuperiorPlugin/src/main/java/com/scrappers/superiorExtendedEngine/gamePad/Speedometer.java

-3
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,13 @@
99
import android.widget.ProgressBar;
1010
import android.widget.RelativeLayout;
1111
import android.widget.TextView;
12-
1312
import com.jme3.app.Application;
1413
import com.jme3.app.SimpleApplication;
1514
import com.jme3.app.state.BaseAppState;
1615
import com.jme3.bullet.control.VehicleControl;
1716
import com.jme3.math.FastMath;
1817
import com.scrappers.GamePad.R;
19-
2018
import java.util.ArrayList;
21-
2219
import androidx.appcompat.app.AppCompatActivity;
2320
import androidx.cardview.widget.CardView;
2421
import androidx.core.content.ContextCompat;

SuperiorPlugin/src/main/java/com/scrappers/superiorExtendedEngine/jmeSurfaceView/splashScreen/SplashScreen.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public SplashScreen(AppCompatActivity appCompatActivity, JmeSurfaceView jmESurfa
3838
public void displayProgressedSplash(){
3939
DisplayMetrics displayMetrics=new DisplayMetrics();
4040
appCompatActivity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
41-
splashScreen.setLayoutParams(new RelativeLayout.LayoutParams(displayMetrics.widthPixels*2,displayMetrics.heightPixels));
41+
splashScreen.setLayoutParams(jmESurfaceView.getLayoutParams());
4242
progressBar.setLayoutParams(new RelativeLayout.LayoutParams(displayMetrics.widthPixels/4,displayMetrics.widthPixels/4));
4343

4444
progressBar.setX((float) (displayMetrics.widthPixels/2 - progressBar.getLayoutParams().width/2));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.scrappers.superiorExtendedEngine.menuStates.uiPager;
2+
3+
import android.view.View;
4+
5+
public interface ActionInjector {
6+
void execute(View uiState, int position);
7+
}

SuperiorPlugin/src/main/java/com/scrappers/superiorExtendedEngine/menuStates/uiPager/UiPager.java

+113
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,14 @@
99
import android.widget.ScrollView;
1010
import com.scrappers.superiorExtendedEngine.menuStates.UiStateManager;
1111
import com.scrappers.superiorExtendedEngine.menuStates.UiStatesLooper;
12+
import java.util.ArrayList;
13+
import java.util.Collections;
1214
import java.util.ConcurrentModificationException;
1315
import java.util.HashMap;
16+
import java.util.List;
17+
import java.util.concurrent.Executors;
1418
import androidx.annotation.IdRes;
19+
import androidx.annotation.Nullable;
1520

1621
/**
1722
* A UiState Class that could hold multiple UiStates in a list/grid form.
@@ -20,6 +25,8 @@
2025
*/
2126
public class UiPager extends GridLayout {
2227
public static final int SEQUENTIAL_ADD = -1;
28+
public static final int A_Z = 200;
29+
public static final int Z_A = 300;
2330
private final HashMap<Integer, View> uiStates = new HashMap<>();
2431
private int stateIndex=0;
2532

@@ -168,6 +175,112 @@ public void forEachUiState(UiStatesLooper.Modifiable.Looper uiStatesLooper){
168175
uiStatesLooper.applyUpdate(getChildUiStateByIndex(position), position);
169176
}
170177
}
178+
179+
/**
180+
* Runs an anonymous asynchronous searching task function for some items inside a searchList based on a list of searchKeyWords.
181+
* @param searchList the search list you want to traverse through, it should be parallel to the UiStates you want to update.
182+
* @param searchKeyWords the keywords you want to look for inside this search list.
183+
* @param injector injects what you want to do when an item is returned by the search engine.
184+
* @return a list of the founded strings from the searchList based on the search keywords.
185+
* @throws Exception throws an exception if the search custom thread fails.
186+
* @apiNote <b> <T extends Object> synchronized(T)</b> marks a thread-safe function by the dead locking other threads synchronized on the same object scheduled or started by the thread factory.
187+
*/
188+
public String[] search(String[] searchList, String[] searchKeyWords, ActionInjector injector) throws Exception {
189+
synchronized(this) {
190+
final String[] resultList = new String[searchList.length];
191+
return Executors.callable(() -> {
192+
//format the list
193+
removeAllViews();
194+
for (int pos = 0; pos < searchList.length; pos++) {
195+
for (String keyword : searchKeyWords) {
196+
if (searchList[pos].replaceAll(" ","").trim().toLowerCase().contains(keyword.replaceAll(" ","").trim().toLowerCase())) {
197+
resultList[pos] = searchList[pos];
198+
View uiState = getChildUiStateByIndex(pos);
199+
addView(uiState);
200+
if(injector != null){
201+
injector.execute(uiState, pos);
202+
}
203+
break;
204+
}
205+
}
206+
}
207+
}, resultList).call();
208+
}
209+
}
210+
211+
/**
212+
* Revert the search results executed by the search function, to the full length of UiStates, this doesn't stop the searching thread though, it rather waits until it finishes searching.
213+
* @param actionInjector injects actions to execute accompanied by the reversion.
214+
* @throws Exception throws an exception if the revert custom thread fails.
215+
* @apiNote <b> <T extends Object> synchronized(T)</b> marks a thread-safe function by the dead locking other threads synchronized on the same object scheduled or started by the thread factory.
216+
*/
217+
public void revertSearchEngine(@Nullable ActionInjector actionInjector) throws Exception {
218+
synchronized(this){
219+
//format the states
220+
removeAllViews();
221+
Executors.callable(() -> forEachUiState((UiStatesLooper.Modifiable.Looper) (currentView, position) -> {
222+
if (actionInjector != null) {
223+
actionInjector.execute(currentView, position);
224+
}
225+
addView(currentView, position);
226+
})).call();
227+
}
228+
}
229+
230+
/**
231+
* Sort a String list either by A_Z or Z_A swapping algorithm, the sort runs in an async task in the same called thread.
232+
* @param list the list to order sort for.
233+
* @param sortAlgorithm the sort algorithm either {@link UiPager#A_Z} or {@link UiPager#Z_A}.
234+
* @return the new sorted String in the shape of Collection List.
235+
* @throws Exception if process is interrupted or -1 is returned.
236+
* @apiNote you will need to loop over this list to provide the uiStates with new update.
237+
*/
238+
public String[] sort(String[] list, int sortAlgorithm) throws Exception {
239+
synchronized(this) {
240+
return Executors.callable(() -> {
241+
String tempPointer = "";
242+
//main String List looping
243+
for (int i = 0; i < list.length; i++) {
244+
//looping over the String again to compare each one String member var with the sequence of the String member vars after that item
245+
for(int j = i+1; j < list.length; j++ ){
246+
//loop over chars inside the 2 strings & compare those suckers
247+
for(int k = 0; k < Math.min(list[i].length(), list[j].length()); k++){
248+
//sort from A-Z ascendingly
249+
if(sortAlgorithm == A_Z){
250+
if ( list[i].toLowerCase().charAt(k) > list[j].toLowerCase().charAt(k) ){
251+
//format the pointer
252+
tempPointer = "";
253+
//then swap list[i] & list[j] because list[i] is after the list[k]
254+
//store the list[i] inside the tempPointer for later access
255+
tempPointer = list[i];
256+
//get the list[i] after
257+
list[i] = list[j];
258+
//get the list[j] before
259+
list[j] = tempPointer;
260+
//terminate the comparison when goal is reached; for a new round
261+
break;
262+
}
263+
}else if(sortAlgorithm == Z_A){
264+
if ( list[i].toLowerCase().charAt(k) < list[j].toLowerCase().charAt(k) ){
265+
//format the pointer
266+
tempPointer = "";
267+
//then swap list[i] & list[j] because list[i] is before the list[k]
268+
//store the list[j] inside the tempPointer for later access
269+
tempPointer = list[j];
270+
//get the list[j] before
271+
list[j] = list[i];
272+
//get the list[i] after
273+
list[i] = tempPointer;
274+
//terminate the comparison when goal is reached; for a new round
275+
break;
276+
}
277+
}
278+
}
279+
}
280+
}
281+
}, list).call();
282+
}
283+
}
171284
/**
172285
* gets the index of the Last UI-State attached to the UI-State-Manager.
173286
* @return the index of the last UI state.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package com.scrappers.superiorExtendedEngine.tasksUtil.backgroundTask;
2+
3+
import android.app.Notification;
4+
import android.app.NotificationChannel;
5+
import android.app.NotificationManager;
6+
import android.content.Context;
7+
import android.os.Build;
8+
import android.view.LayoutInflater;
9+
import android.view.View;
10+
import android.widget.RemoteViews;
11+
12+
import androidx.annotation.LayoutRes;
13+
import androidx.annotation.Nullable;
14+
import androidx.core.app.NotificationCompat;
15+
16+
/**
17+
* <b>Code design</b>
18+
* <ol>
19+
*<li> <s> BackgroundNotifier does have a builder class to build notification UI & handle the click listeners inside it </s></li>
20+
*<li> BackgroundNotifier register a notifier to the system with some delay inputs, some data constraints(Binders), System flags</li>
21+
*<li> Another class for Nominations stacks </li>
22+
* </ol>
23+
* @author pavl_g
24+
*/
25+
public class BackgroundNotifier {
26+
27+
/**
28+
* A subclass that would inflate notifications with UI-Layouts
29+
*/
30+
public static class NotificationInflater{
31+
private final Context context;
32+
public NotificationInflater(final Context context){
33+
this.context = context;
34+
}
35+
public View inflateNotification(@LayoutRes int resId){
36+
return LayoutInflater.from(context).inflate(resId, null);
37+
}
38+
}
39+
40+
public static class Builder{
41+
private final Context context;
42+
public Builder(final Context context){
43+
this.context = context;
44+
}
45+
46+
/**
47+
* Build a notiification using custom design
48+
* @param inflatedView
49+
* @param constraints
50+
* @param systemFlags
51+
* @return
52+
*/
53+
public NotificationCompat.Builder buildNotification(@Nullable View inflatedView){
54+
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
55+
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ){
56+
NotificationChannel channel = new NotificationChannel(String.valueOf(inflatedView.getId()), String.valueOf(inflatedView.getId()), NotificationManager.IMPORTANCE_HIGH);
57+
channel.enableLights(true);
58+
channel.enableVibration(true);
59+
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
60+
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q ){
61+
channel.setAllowBubbles(true);
62+
}
63+
notificationManager.createNotificationChannel(channel);
64+
}
65+
assert inflatedView != null;
66+
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, String.valueOf(inflatedView.getId()));
67+
if(inflatedView != null){
68+
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), inflatedView.getId());
69+
builder.setCustomContentView(remoteViews);
70+
}
71+
builder.setPriority(NotificationCompat.PRIORITY_HIGH);
72+
builder.setAutoCancel(false);
73+
return builder;
74+
}
75+
76+
/**
77+
* Build regular notification
78+
*/
79+
public NotificationCompat.Builder buildNotification(String channelID){
80+
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
81+
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ){
82+
NotificationChannel channel = new NotificationChannel(channelID, channelID, NotificationManager.IMPORTANCE_HIGH);
83+
channel.enableLights(true);
84+
channel.enableVibration(true);
85+
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
86+
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q ){
87+
channel.setAllowBubbles(true);
88+
}
89+
notificationManager.createNotificationChannel(channel);
90+
}
91+
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelID);
92+
builder.setPriority(NotificationCompat.PRIORITY_HIGH);
93+
builder.setAutoCancel(false);
94+
return builder;
95+
}
96+
97+
public Context getContext() {
98+
return context;
99+
}
100+
101+
}
102+
103+
104+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.scrappers.superiorExtendedEngine.tasksUtil.backgroundTask;
2+
3+
import android.annotation.SuppressLint;
4+
import android.app.job.JobParameters;
5+
import android.app.job.JobService;
6+
import android.content.Intent;
7+
import android.os.Build;
8+
import android.os.Handler;
9+
10+
import androidx.annotation.RequiresApi;
11+
12+
@SuppressLint("SpecifyJobSchedulerIdRange")
13+
@RequiresApi(api = Build.VERSION_CODES.M)
14+
public abstract class BackgroundService extends JobService {
15+
private final Task task = new Task();
16+
private final Handler handler = new Handler();
17+
@Override
18+
public boolean onStartJob(JobParameters params) {
19+
synchronized(task){
20+
handler.post(task);
21+
}
22+
return true;
23+
}
24+
25+
@Override
26+
public boolean onStopJob(JobParameters params) {
27+
synchronized(task){
28+
handler.removeCallbacks(task);
29+
}
30+
return true;
31+
}
32+
public class Task implements Runnable{
33+
@SuppressLint("SpecifyJobSchedulerIdRange")
34+
@Override
35+
public void run() {
36+
listen(null);
37+
}
38+
}
39+
public abstract void listen(Intent intent);
40+
}

0 commit comments

Comments
 (0)