mirror of
https://github.com/peterosterlund2/droidfish.git
synced 2024-11-23 11:31:33 +01:00
Support regular expression search in game load/save activity
Standard Java regular expression syntax is supported. The search is case insensitive.
This commit is contained in:
parent
15b62e9bc2
commit
fbb2091d45
|
@ -72,6 +72,7 @@ public abstract class EditPGN extends AppCompatActivity {
|
|||
private String lastSearchString = "";
|
||||
private String lastFileName = "";
|
||||
private long lastModTime = -1;
|
||||
private boolean useRegExp = false;
|
||||
|
||||
private Thread workThread = null;
|
||||
private boolean canceled = false;
|
||||
|
@ -95,11 +96,13 @@ public abstract class EditPGN extends AppCompatActivity {
|
|||
lastFileName = savedInstanceState.getString("lastFileName");
|
||||
if (lastFileName == null) lastFileName = "";
|
||||
lastModTime = savedInstanceState.getLong("lastModTime");
|
||||
useRegExp = savedInstanceState.getBoolean("useRegExpSearch");
|
||||
} else {
|
||||
defaultFilePos = settings.getLong("defaultFilePos", 0);
|
||||
lastSearchString = settings.getString("lastSearchString", "");
|
||||
lastFileName = settings.getString("lastFileName", "");
|
||||
lastModTime = settings.getLong("lastModTime", 0);
|
||||
useRegExp = settings.getBoolean("useRegExpSearch", false);
|
||||
}
|
||||
|
||||
Intent i = getIntent();
|
||||
|
@ -131,14 +134,14 @@ public abstract class EditPGN extends AppCompatActivity {
|
|||
workThread = new Thread(() -> {
|
||||
if (!readFile())
|
||||
return;
|
||||
GameAdapter.ItemMatcher<GameInfo> m =
|
||||
GameAdapter.getItemMatcher(lastSearchString, useRegExp);
|
||||
int itemNo = getItemNo(gamesInFile, defaultFilePos) + (next ? 1 : -1);
|
||||
if (next) {
|
||||
while (itemNo < gamesInFile.size() &&
|
||||
!GameAdapter.matchItem(gamesInFile.get(itemNo), lastSearchString))
|
||||
while (itemNo < gamesInFile.size() && !m.matches(gamesInFile.get(itemNo)))
|
||||
itemNo++;
|
||||
} else {
|
||||
while (itemNo >= 0 &&
|
||||
!GameAdapter.matchItem(gamesInFile.get(itemNo), lastSearchString))
|
||||
while (itemNo >= 0 && !m.matches(gamesInFile.get(itemNo)))
|
||||
itemNo--;
|
||||
}
|
||||
final int loadItem = itemNo;
|
||||
|
@ -205,6 +208,7 @@ public abstract class EditPGN extends AppCompatActivity {
|
|||
outState.putString("lastSearchString", lastSearchString);
|
||||
outState.putString("lastFileName", lastFileName);
|
||||
outState.putLong("lastModTime", lastModTime);
|
||||
outState.putBoolean("useRegExpSearch", useRegExp);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -214,6 +218,7 @@ public abstract class EditPGN extends AppCompatActivity {
|
|||
editor.putString("lastSearchString", lastSearchString);
|
||||
editor.putString("lastFileName", lastFileName);
|
||||
editor.putLong("lastModTime", lastModTime);
|
||||
editor.putBoolean("useRegExpSearch", useRegExp);
|
||||
editor.apply();
|
||||
super.onPause();
|
||||
}
|
||||
|
@ -234,6 +239,8 @@ public abstract class EditPGN extends AppCompatActivity {
|
|||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.edit_file_options_menu, menu);
|
||||
MenuItem item = menu.findItem(R.id.regexp_search);
|
||||
item.setChecked(useRegExp);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -243,6 +250,14 @@ public abstract class EditPGN extends AppCompatActivity {
|
|||
case R.id.item_delete_file:
|
||||
reShowDialog(DELETE_PGN_FILE_DIALOG);
|
||||
break;
|
||||
case R.id.regexp_search:
|
||||
useRegExp = !useRegExp;
|
||||
item.setChecked(useRegExp);
|
||||
if (binding != null) {
|
||||
String s = binding.selectGameFilter.getText().toString();
|
||||
setFilterString(s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -480,17 +495,20 @@ public abstract class EditPGN extends AppCompatActivity {
|
|||
}
|
||||
|
||||
private void setFilterString(String s) {
|
||||
boolean regExp = useRegExp;
|
||||
Filter.FilterListener listener = (count) -> {
|
||||
ArrayList<GameInfo> arr = aa.getValues();
|
||||
int itemNo = getItemNo(arr, currentFilePos);
|
||||
if (itemNo < 0)
|
||||
itemNo = 0;
|
||||
while (itemNo < arr.size() &&
|
||||
!GameAdapter.matchItem(arr.get(itemNo), lastSearchString))
|
||||
GameAdapter.ItemMatcher<GameInfo> m =
|
||||
GameAdapter.getItemMatcher(lastSearchString, regExp);
|
||||
while (itemNo < arr.size() && !m.matches(arr.get(itemNo)))
|
||||
itemNo++;
|
||||
if (itemNo < arr.size())
|
||||
binding.listView.setSelectionFromTop(itemNo, 0);
|
||||
};
|
||||
aa.setUseRegExp(regExp);
|
||||
aa.getFilter().filter(s, listener);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,16 +28,19 @@ import android.widget.Filterable;
|
|||
import android.widget.TextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
/**
|
||||
* An adapter for displaying an ArrayList<GameInfo> in a ListView.
|
||||
*/
|
||||
public class GameAdapter<T> extends BaseAdapter implements Filterable {
|
||||
private ArrayList<T> origValues; // Unfiltered values
|
||||
private ArrayList<T> values; // Filtered values. Equal to origValues if no filter used
|
||||
private ArrayList<T> origValues; // Unfiltered values
|
||||
private ArrayList<T> values; // Filtered values. Equal to origValues if no filter used
|
||||
private final LayoutInflater inflater;
|
||||
private int resource;
|
||||
private GameFilter filter; // Initialized at first use
|
||||
private GameFilter filter; // Initialized at first use
|
||||
private boolean useRegExp = false; // If true, use regular expression in filter
|
||||
|
||||
public GameAdapter(Context context, int resource, ArrayList<T> objects) {
|
||||
origValues = objects;
|
||||
|
@ -83,6 +86,10 @@ public class GameAdapter<T> extends BaseAdapter implements Filterable {
|
|||
return filter;
|
||||
}
|
||||
|
||||
public void setUseRegExp(boolean regExp) {
|
||||
useRegExp = regExp;
|
||||
}
|
||||
|
||||
private class GameFilter extends Filter {
|
||||
@Override
|
||||
protected FilterResults performFiltering(CharSequence constraint) {
|
||||
|
@ -91,10 +98,10 @@ public class GameAdapter<T> extends BaseAdapter implements Filterable {
|
|||
res.values = origValues;
|
||||
res.count = origValues.size();
|
||||
} else {
|
||||
String s = constraint.toString().toLowerCase();
|
||||
ItemMatcher<T> m = getItemMatcher(constraint.toString(), useRegExp);
|
||||
ArrayList<T> newValues = new ArrayList<>();
|
||||
for (T item : origValues)
|
||||
if (matchItem(item, s))
|
||||
if (m.matches(item))
|
||||
newValues.add(item);
|
||||
res.values = newValues;
|
||||
res.count = newValues.size();
|
||||
|
@ -110,10 +117,27 @@ public class GameAdapter<T> extends BaseAdapter implements Filterable {
|
|||
}
|
||||
}
|
||||
|
||||
/** Return true if matchStr matches item.
|
||||
* @param item The item to check. The toString() value converted to lowercase is used.
|
||||
* @param matchStr The match string. Must be lowercase. */
|
||||
static <U> boolean matchItem(U item, String matchStr) {
|
||||
return item.toString().toLowerCase().contains(matchStr);
|
||||
interface ItemMatcher<U> {
|
||||
/** Return true if item matches the search criteria. */
|
||||
boolean matches(U item);
|
||||
}
|
||||
|
||||
/** Return an object that determines if an item matches given search criteria.
|
||||
* @param matchStr The match string.
|
||||
* @param useRegExp If true matchStr is interpreted as a regular expression. */
|
||||
static <U> ItemMatcher<U> getItemMatcher(String matchStr, boolean useRegExp) {
|
||||
if (useRegExp) {
|
||||
Pattern tmp;
|
||||
try {
|
||||
tmp = Pattern.compile(matchStr, Pattern.CASE_INSENSITIVE);
|
||||
} catch (PatternSyntaxException ex) {
|
||||
tmp = null;
|
||||
}
|
||||
Pattern p = tmp;
|
||||
return item -> p == null || p.matcher(item.toString()).find();
|
||||
} else {
|
||||
String s = matchStr.toLowerCase();
|
||||
return item -> item.toString().toLowerCase().contains(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/item_delete_file"
|
||||
android:title="@string/delete_file" />
|
||||
<item
|
||||
android:id="@+id/regexp_search"
|
||||
android:title="@string/regexp_search"
|
||||
android:checkable="true"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
||||
|
|
|
@ -196,6 +196,7 @@ If you are running on battery power, it is recommended that you change settings
|
|||
<string name="delete_file">Delete file</string>
|
||||
<string name="delete_file_question">Delete file?</string>
|
||||
<string name="delete_named_file">Delete file %s?</string>
|
||||
<string name="regexp_search">Regular Expression Search</string>
|
||||
<string name="game_saved">Game saved</string>
|
||||
<string name="failed_to_save_game">Failed to save game</string>
|
||||
<string name="failed_to_delete_game">Failed to delete game</string>
|
||||
|
|
Loading…
Reference in New Issue
Block a user