Skip to content

Commit

Permalink
Search, Sort of UiPager & Bug fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
pavly-gerges committed Jul 1, 2021
1 parent 6c2920a commit acd2481
Show file tree
Hide file tree
Showing 21 changed files with 632 additions and 63 deletions.
1 change: 1 addition & 0 deletions .idea/dictionaries/twisted.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 8 additions & 4 deletions SuperiorPlugin/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,12 @@ dependencies {
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation "org.jmonkeyengine:jme3-core:3.4.0-beta1"
implementation "org.jmonkeyengine:jme3-effects:3.4.0-beta1"
implementation "org.jmonkeyengine:jme3-android-native:3.4.0-beta1"
implementation 'com.github.stephengold:Minie:4.0.0'
implementation "org.jmonkeyengine:jme3-core:3.4.0-beta4"
implementation "org.jmonkeyengine:jme3-effects:3.4.0-beta4"
implementation "org.jmonkeyengine:jme3-android-native:3.4.0-beta4"
//noinspection GradleDynamicVersion
implementation 'com.github.stephengold:Minie:4.1.0+for33'
implementation "androidx.work:work-runtime:2.5.0"
implementation "androidx.concurrent:concurrent-futures:1.1.0"

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,13 @@
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.jme3.app.Application;
import com.jme3.app.SimpleApplication;
import com.jme3.app.state.BaseAppState;
import com.jme3.bullet.control.VehicleControl;
import com.jme3.math.FastMath;
import com.scrappers.GamePad.R;

import java.util.ArrayList;

import androidx.appcompat.app.AppCompatActivity;
import androidx.cardview.widget.CardView;
import androidx.core.content.ContextCompat;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public SplashScreen(AppCompatActivity appCompatActivity, JmeSurfaceView jmESurfa
public void displayProgressedSplash(){
DisplayMetrics displayMetrics=new DisplayMetrics();
appCompatActivity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
splashScreen.setLayoutParams(new RelativeLayout.LayoutParams(displayMetrics.widthPixels*2,displayMetrics.heightPixels));
splashScreen.setLayoutParams(jmESurfaceView.getLayoutParams());
progressBar.setLayoutParams(new RelativeLayout.LayoutParams(displayMetrics.widthPixels/4,displayMetrics.widthPixels/4));

progressBar.setX((float) (displayMetrics.widthPixels/2 - progressBar.getLayoutParams().width/2));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.scrappers.superiorExtendedEngine.menuStates.uiPager;

import android.view.View;

public interface ActionInjector {
void execute(View uiState, int position);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@
import android.widget.ScrollView;
import com.scrappers.superiorExtendedEngine.menuStates.UiStateManager;
import com.scrappers.superiorExtendedEngine.menuStates.UiStatesLooper;
import java.util.ArrayList;
import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.Executors;
import androidx.annotation.IdRes;
import androidx.annotation.Nullable;

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

Expand Down Expand Up @@ -168,6 +175,112 @@ public void forEachUiState(UiStatesLooper.Modifiable.Looper uiStatesLooper){
uiStatesLooper.applyUpdate(getChildUiStateByIndex(position), position);
}
}

/**
* Runs an anonymous asynchronous searching task function for some items inside a searchList based on a list of searchKeyWords.
* @param searchList the search list you want to traverse through, it should be parallel to the UiStates you want to update.
* @param searchKeyWords the keywords you want to look for inside this search list.
* @param injector injects what you want to do when an item is returned by the search engine.
* @return a list of the founded strings from the searchList based on the search keywords.
* @throws Exception throws an exception if the search custom thread fails.
* @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.
*/
public String[] search(String[] searchList, String[] searchKeyWords, ActionInjector injector) throws Exception {
synchronized(this) {
final String[] resultList = new String[searchList.length];
return Executors.callable(() -> {
//format the list
removeAllViews();
for (int pos = 0; pos < searchList.length; pos++) {
for (String keyword : searchKeyWords) {
if (searchList[pos].replaceAll(" ","").trim().toLowerCase().contains(keyword.replaceAll(" ","").trim().toLowerCase())) {
resultList[pos] = searchList[pos];
View uiState = getChildUiStateByIndex(pos);
addView(uiState);
if(injector != null){
injector.execute(uiState, pos);
}
break;
}
}
}
}, resultList).call();
}
}

/**
* 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.
* @param actionInjector injects actions to execute accompanied by the reversion.
* @throws Exception throws an exception if the revert custom thread fails.
* @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.
*/
public void revertSearchEngine(@Nullable ActionInjector actionInjector) throws Exception {
synchronized(this){
//format the states
removeAllViews();
Executors.callable(() -> forEachUiState((UiStatesLooper.Modifiable.Looper) (currentView, position) -> {
if (actionInjector != null) {
actionInjector.execute(currentView, position);
}
addView(currentView, position);
})).call();
}
}

/**
* 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.
* @param list the list to order sort for.
* @param sortAlgorithm the sort algorithm either {@link UiPager#A_Z} or {@link UiPager#Z_A}.
* @return the new sorted String in the shape of Collection List.
* @throws Exception if process is interrupted or -1 is returned.
* @apiNote you will need to loop over this list to provide the uiStates with new update.
*/
public String[] sort(String[] list, int sortAlgorithm) throws Exception {
synchronized(this) {
return Executors.callable(() -> {
String tempPointer = "";
//main String List looping
for (int i = 0; i < list.length; i++) {
//looping over the String again to compare each one String member var with the sequence of the String member vars after that item
for(int j = i+1; j < list.length; j++ ){
//loop over chars inside the 2 strings & compare those suckers
for(int k = 0; k < Math.min(list[i].length(), list[j].length()); k++){
//sort from A-Z ascendingly
if(sortAlgorithm == A_Z){
if ( list[i].toLowerCase().charAt(k) > list[j].toLowerCase().charAt(k) ){
//format the pointer
tempPointer = "";
//then swap list[i] & list[j] because list[i] is after the list[k]
//store the list[i] inside the tempPointer for later access
tempPointer = list[i];
//get the list[i] after
list[i] = list[j];
//get the list[j] before
list[j] = tempPointer;
//terminate the comparison when goal is reached; for a new round
break;
}
}else if(sortAlgorithm == Z_A){
if ( list[i].toLowerCase().charAt(k) < list[j].toLowerCase().charAt(k) ){
//format the pointer
tempPointer = "";
//then swap list[i] & list[j] because list[i] is before the list[k]
//store the list[j] inside the tempPointer for later access
tempPointer = list[j];
//get the list[j] before
list[j] = list[i];
//get the list[i] after
list[i] = tempPointer;
//terminate the comparison when goal is reached; for a new round
break;
}
}
}
}
}
}, list).call();
}
}
/**
* gets the index of the Last UI-State attached to the UI-State-Manager.
* @return the index of the last UI state.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package com.scrappers.superiorExtendedEngine.tasksUtil.backgroundTask;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Build;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.RemoteViews;

import androidx.annotation.LayoutRes;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;

/**
* <b>Code design</b>
* <ol>
*<li> <s> BackgroundNotifier does have a builder class to build notification UI & handle the click listeners inside it </s></li>
*<li> BackgroundNotifier register a notifier to the system with some delay inputs, some data constraints(Binders), System flags</li>
*<li> Another class for Nominations stacks </li>
* </ol>
* @author pavl_g
*/
public class BackgroundNotifier {

/**
* A subclass that would inflate notifications with UI-Layouts
*/
public static class NotificationInflater{
private final Context context;
public NotificationInflater(final Context context){
this.context = context;
}
public View inflateNotification(@LayoutRes int resId){
return LayoutInflater.from(context).inflate(resId, null);
}
}

public static class Builder{
private final Context context;
public Builder(final Context context){
this.context = context;
}

/**
* Build a notiification using custom design
* @param inflatedView
* @param constraints
* @param systemFlags
* @return
*/
public NotificationCompat.Builder buildNotification(@Nullable View inflatedView){
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ){
NotificationChannel channel = new NotificationChannel(String.valueOf(inflatedView.getId()), String.valueOf(inflatedView.getId()), NotificationManager.IMPORTANCE_HIGH);
channel.enableLights(true);
channel.enableVibration(true);
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q ){
channel.setAllowBubbles(true);
}
notificationManager.createNotificationChannel(channel);
}
assert inflatedView != null;
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, String.valueOf(inflatedView.getId()));
if(inflatedView != null){
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), inflatedView.getId());
builder.setCustomContentView(remoteViews);
}
builder.setPriority(NotificationCompat.PRIORITY_HIGH);
builder.setAutoCancel(false);
return builder;
}

/**
* Build regular notification
*/
public NotificationCompat.Builder buildNotification(String channelID){
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ){
NotificationChannel channel = new NotificationChannel(channelID, channelID, NotificationManager.IMPORTANCE_HIGH);
channel.enableLights(true);
channel.enableVibration(true);
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q ){
channel.setAllowBubbles(true);
}
notificationManager.createNotificationChannel(channel);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelID);
builder.setPriority(NotificationCompat.PRIORITY_HIGH);
builder.setAutoCancel(false);
return builder;
}

public Context getContext() {
return context;
}

}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.scrappers.superiorExtendedEngine.tasksUtil.backgroundTask;

import android.annotation.SuppressLint;
import android.app.job.JobParameters;
import android.app.job.JobService;
import android.content.Intent;
import android.os.Build;
import android.os.Handler;

import androidx.annotation.RequiresApi;

@SuppressLint("SpecifyJobSchedulerIdRange")
@RequiresApi(api = Build.VERSION_CODES.M)
public abstract class BackgroundService extends JobService {
private final Task task = new Task();
private final Handler handler = new Handler();
@Override
public boolean onStartJob(JobParameters params) {
synchronized(task){
handler.post(task);
}
return true;
}

@Override
public boolean onStopJob(JobParameters params) {
synchronized(task){
handler.removeCallbacks(task);
}
return true;
}
public class Task implements Runnable{
@SuppressLint("SpecifyJobSchedulerIdRange")
@Override
public void run() {
listen(null);
}
}
public abstract void listen(Intent intent);
}
Loading

0 comments on commit acd2481

Please sign in to comment.