diff --git a/DroidFishApp/src/main/java/org/petero/droidfish/DroidFish.java b/DroidFishApp/src/main/java/org/petero/droidfish/DroidFish.java
index 9dbfe92..37616db 100644
--- a/DroidFishApp/src/main/java/org/petero/droidfish/DroidFish.java
+++ b/DroidFishApp/src/main/java/org/petero/droidfish/DroidFish.java
@@ -2408,17 +2408,25 @@ public class DroidFish extends Activity
items[numFiles] = getString(R.string.internal_book);
items[numFiles + 1] = getString(R.string.eco_book);
items[numFiles + 2] = getString(R.string.no_book);
+
int defaultItem = numFiles;
if ("eco:".equals(bookOptions.filename))
defaultItem = numFiles + 1;
else if ("nobook:".equals(bookOptions.filename))
defaultItem = numFiles + 2;
+ String oldName = bookOptions.filename;
+ File extDir = Environment.getExternalStorageDirectory();
+ String sep = File.separator;
+ String defDir = extDir.getAbsolutePath() + sep + bookDir + sep;
+ if (oldName.startsWith(defDir))
+ oldName = oldName.substring(defDir.length());
for (int i = 0; i < numFiles; i++) {
- if (bookOptions.filename.equals(items[i])) {
+ if (oldName.equals(items[i])) {
defaultItem = i;
break;
}
}
+
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.select_opening_book_file);
builder.setSingleChoiceItems(items, defaultItem, (dialog, item) -> {
diff --git a/DroidFishApp/src/main/java/org/petero/droidfish/activities/EditFilePreference.java b/DroidFishApp/src/main/java/org/petero/droidfish/activities/EditFilePreference.java
new file mode 100644
index 0000000..7d07896
--- /dev/null
+++ b/DroidFishApp/src/main/java/org/petero/droidfish/activities/EditFilePreference.java
@@ -0,0 +1,151 @@
+/*
+ DroidFish - An Android chess program.
+ Copyright (C) 2020 Peter Österlund, peterosterlund2@gmail.com
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+package org.petero.droidfish.activities;
+
+import android.app.Activity;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Environment;
+import android.preference.EditTextPreference;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import org.petero.droidfish.FileUtil;
+import org.petero.droidfish.R;
+
+import java.io.File;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+
+/** A text preference representing a file or directory, with a corresponding browse button. */
+public class EditFilePreference extends EditTextPreference {
+ private boolean pickDirectory = false; // True to pick a directory, false to pick a file
+ private String defaultPath = ""; // Default path when current value does not define a path
+ private String ignorePattern = ""; // Regexp for values to be treated as non-paths
+ private View view;
+
+ public EditFilePreference(Context context) {
+ super(context);
+ init(null);
+ }
+
+ public EditFilePreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(attrs);
+ }
+
+ public EditFilePreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init(attrs);
+ }
+
+ private void init(AttributeSet attrs) {
+ if (attrs != null) {
+ pickDirectory = attrs.getAttributeBooleanValue(null, "pickDirectory", false);
+ defaultPath = getStringValue(attrs, "defaultPath");
+ ignorePattern = getStringValue(attrs, "ignorePattern");
+ }
+ }
+
+ private static String getStringValue(AttributeSet attrs, String name) {
+ String val = attrs.getAttributeValue(null, name);
+ return val == null ? "" : val;
+ }
+
+ @Override
+ protected void onBindView(View view) {
+ super.onBindView(view);
+ this.view = view;
+ addBrowseButton();
+ }
+
+ private void addBrowseButton() {
+ if (view == null)
+ return;
+
+ LinearLayout widgetFrameView = view.findViewById(android.R.id.widget_frame);
+ if (widgetFrameView == null)
+ return;
+ widgetFrameView.setVisibility(View.VISIBLE);
+ int count = widgetFrameView.getChildCount();
+ if (count > 0)
+ widgetFrameView.removeViews(0, count);
+
+ ImageView button = new ImageView(getContext());
+ widgetFrameView.addView(button);
+ widgetFrameView.setMinimumWidth(0);
+
+ boolean hasBrowser = FileBrowseUtil.hasBrowser(getContext().getPackageManager(),
+ pickDirectory);
+ FileBrowseUtil.setBrowseImage(getContext().getResources(), button, hasBrowser);
+ button.setOnClickListener(view -> browseFile());
+ }
+
+ private void browseFile() {
+ String currentPath = getText();
+ if (matchPattern(currentPath))
+ currentPath = "";
+ String sep = File.separator;
+ if (currentPath.isEmpty() || !currentPath.contains(sep)) {
+ String extDir = Environment.getExternalStorageDirectory().getAbsolutePath();
+ String newPath = extDir + sep + defaultPath;
+ if (!currentPath.isEmpty())
+ newPath += sep + currentPath;
+ currentPath = newPath;
+ }
+
+ final String action = FileBrowseUtil.getPickAction(pickDirectory);
+ final String title = getContext().getString(pickDirectory ? R.string.select_directory
+ : R.string.select_file);
+ Intent i = new Intent(action);
+ i.setData(Uri.fromFile(new File(currentPath)));
+ i.putExtra("org.openintents.extra.TITLE", title);
+ try {
+ Context context = getContext();
+ if (context instanceof Preferences) {
+ Preferences prefs = ((Preferences)context);
+ prefs.runActivity(i, (resultCode, data) -> {
+ if (resultCode == Activity.RESULT_OK) {
+ String pathName = FileUtil.getFilePathFromUri(data.getData());
+ if (pathName != null)
+ setText(pathName);
+ }
+ });
+ }
+ } catch (ActivityNotFoundException ignore) {
+ }
+ }
+
+ private boolean matchPattern(String s) {
+ if (ignorePattern.isEmpty())
+ return false;
+ Pattern p;
+ try {
+ p = Pattern.compile(ignorePattern);
+ return p.matcher(s).find();
+ } catch (PatternSyntaxException ex) {
+ return false;
+ }
+ }
+}
diff --git a/DroidFishApp/src/main/java/org/petero/droidfish/activities/EditOptions.java b/DroidFishApp/src/main/java/org/petero/droidfish/activities/EditOptions.java
index e5ace65..bf73b29 100644
--- a/DroidFishApp/src/main/java/org/petero/droidfish/activities/EditOptions.java
+++ b/DroidFishApp/src/main/java/org/petero/droidfish/activities/EditOptions.java
@@ -24,34 +24,23 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.drawable.StateListDrawable;
import android.net.Uri;
import android.os.Bundle;
-import android.os.Environment;
import android.preference.PreferenceManager;
import android.text.Editable;
import android.text.TextWatcher;
-import android.util.TypedValue;
import android.view.KeyEvent;
import android.view.View;
-import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.EditText;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-
-import com.caverock.androidsvg.SVG;
-import com.caverock.androidsvg.SVGParseException;
import androidx.databinding.DataBindingUtil;
import org.petero.droidfish.DroidFishApp;
import org.petero.droidfish.FileUtil;
import org.petero.droidfish.R;
-import org.petero.droidfish.SVGPictureDrawable;
import org.petero.droidfish.Util;
import org.petero.droidfish.databinding.EditoptionsBinding;
import org.petero.droidfish.databinding.UciOptionButtonBinding;
@@ -90,10 +79,8 @@ public class EditOptions extends Activity {
workDir = (String) i.getSerializableExtra("org.petero.droidfish.workDir");
hasBrowser = (Boolean) i.getSerializableExtra("org.petero.droidfish.localEngine");
if (uciOpts != null) {
- if (hasBrowser) {
- Intent browser = new Intent("org.openintents.action.PICK_FILE");
- hasBrowser = browser.resolveActivity(getPackageManager()) != null;
- }
+ if (hasBrowser)
+ hasBrowser = FileBrowseUtil.hasBrowser(getPackageManager(), false);
initUI();
} else {
setResult(RESULT_CANCELED);
@@ -267,10 +254,8 @@ public class EditOptions extends Activity {
});
boolean isFileOption = hasBrowser && (o.name.toLowerCase().contains("file") ||
o.name.toLowerCase().contains("path"));
- setBrowseImage(holder.eoBrowse, isFileOption);
- holder.eoBrowse.setOnClickListener(view -> {
- browseFile(so, holder.eoValue);
- });
+ FileBrowseUtil.setBrowseImage(getResources(), holder.eoBrowse, isFileOption);
+ holder.eoBrowse.setOnClickListener(view -> browseFile(so, holder.eoValue));
return holder.getRoot();
}
default:
@@ -278,42 +263,12 @@ public class EditOptions extends Activity {
}
}
- private void setBrowseImage(ImageButton button, boolean visible) {
- button.setVisibility(visible ? View.VISIBLE : View.GONE);
-
- Resources r = getResources();
- try {
- SVG svg = SVG.getFromResource(r, R.raw.open_last_file);
- button.setBackgroundDrawable(new SVGPictureDrawable(svg));
- } catch (SVGParseException ignore) {
- }
-
- try {
- SVG touched = SVG.getFromResource(r, R.raw.touch);
- StateListDrawable sld = new StateListDrawable();
- sld.addState(new int[]{android.R.attr.state_pressed}, new SVGPictureDrawable(touched));
- button.setImageDrawable(sld);
- } catch (SVGParseException ignore) {
- }
-
- int bWidth = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
- 36, r.getDisplayMetrics()));
- int bHeight = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
- 32, r.getDisplayMetrics()));
- ViewGroup.LayoutParams lp = button.getLayoutParams();
- lp.width = bWidth;
- lp.height = bHeight;
- button.setLayoutParams(lp);
- button.setPadding(0,0,0,0);
- button.setScaleType(ImageView.ScaleType.FIT_XY);
- }
-
private void browseFile(UCIOptions.StringOption so, EditText textField) {
String currentFile = so.getStringValue();
String sep = File.separator;
if (!currentFile.contains(sep))
currentFile = workDir + sep + currentFile;
- Intent i = new Intent("org.openintents.action.PICK_FILE");
+ Intent i = new Intent(FileBrowseUtil.getPickAction(false));
i.setData(Uri.fromFile(new File(currentFile)));
i.putExtra("org.openintents.extra.TITLE", getString(R.string.select_file));
try {
diff --git a/DroidFishApp/src/main/java/org/petero/droidfish/activities/FileBrowseUtil.java b/DroidFishApp/src/main/java/org/petero/droidfish/activities/FileBrowseUtil.java
new file mode 100644
index 0000000..bc0b568
--- /dev/null
+++ b/DroidFishApp/src/main/java/org/petero/droidfish/activities/FileBrowseUtil.java
@@ -0,0 +1,76 @@
+/*
+ DroidFish - An Android chess program.
+ Copyright (C) 2020 Peter Österlund, peterosterlund2@gmail.com
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+package org.petero.droidfish.activities;
+
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.graphics.drawable.StateListDrawable;
+import android.util.TypedValue;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+import com.caverock.androidsvg.SVG;
+import com.caverock.androidsvg.SVGParseException;
+
+import org.petero.droidfish.R;
+import org.petero.droidfish.SVGPictureDrawable;
+
+public class FileBrowseUtil {
+
+ public static String getPickAction(boolean pickDirectory) {
+ return pickDirectory ? "org.openintents.action.PICK_DIRECTORY"
+ : "org.openintents.action.PICK_FILE";
+ }
+
+ public static boolean hasBrowser(PackageManager pMan, boolean pickDirectory) {
+ Intent browser = new Intent(getPickAction(pickDirectory));
+ return browser.resolveActivity(pMan) != null;
+ }
+
+ public static void setBrowseImage(Resources r, ImageView button, boolean visible) {
+ button.setVisibility(visible ? View.VISIBLE : View.GONE);
+
+ try {
+ SVG svg = SVG.getFromResource(r, R.raw.open_last_file);
+ button.setBackgroundDrawable(new SVGPictureDrawable(svg));
+ } catch (SVGParseException ignore) {
+ }
+
+ try {
+ SVG touched = SVG.getFromResource(r, R.raw.touch);
+ StateListDrawable sld = new StateListDrawable();
+ sld.addState(new int[]{android.R.attr.state_pressed}, new SVGPictureDrawable(touched));
+ button.setImageDrawable(sld);
+ } catch (SVGParseException ignore) {
+ }
+
+ int bWidth = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+ 36, r.getDisplayMetrics()));
+ int bHeight = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+ 32, r.getDisplayMetrics()));
+ ViewGroup.LayoutParams lp = button.getLayoutParams();
+ lp.width = bWidth;
+ lp.height = bHeight;
+ button.setLayoutParams(lp);
+ button.setPadding(0,0,0,0);
+ button.setScaleType(ImageView.ScaleType.FIT_XY);
+ }
+}
diff --git a/DroidFishApp/src/main/java/org/petero/droidfish/activities/Preferences.java b/DroidFishApp/src/main/java/org/petero/droidfish/activities/Preferences.java
index 89984d3..c85dd91 100644
--- a/DroidFishApp/src/main/java/org/petero/droidfish/activities/Preferences.java
+++ b/DroidFishApp/src/main/java/org/petero/droidfish/activities/Preferences.java
@@ -1,6 +1,6 @@
/*
DroidFish - An Android chess program.
- Copyright (C) 2011 Peter Österlund, peterosterlund2@gmail.com
+ Copyright (C) 2011,2020 Peter Österlund, peterosterlund2@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -23,6 +23,7 @@ import org.petero.droidfish.R;
import org.petero.droidfish.Util;
import android.content.Context;
+import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
@@ -36,6 +37,9 @@ import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListView;
+import java.util.HashMap;
+import java.util.Map;
+
public class Preferences extends PreferenceActivity {
private static int currentItem = -1;
private static int initialItem = -1;
@@ -100,4 +104,28 @@ public class Preferences extends PreferenceActivity {
editor.putInt("prefsViewInitialItem", currentItem);
editor.apply();
}
+
+ public interface ActivityHandler {
+ void handleResult(int resultCode, Intent data);
+ }
+
+ private int nextRequestCode = 129866295;
+ private Map handlers = new HashMap<>();
+
+ /** Start an activity and invoke handler when the activity finishes. */
+ public void runActivity(Intent data, ActivityHandler handler) {
+ int requestCode = nextRequestCode++;
+ startActivityForResult(data, requestCode);
+ handlers.put(requestCode, handler);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ ActivityHandler handler = handlers.get(requestCode);
+ if (handler != null) {
+ handlers.remove(requestCode);
+ handler.handleResult(resultCode, data);
+ }
+ }
}
diff --git a/DroidFishApp/src/main/res/values/strings.xml b/DroidFishApp/src/main/res/values/strings.xml
index c08aaa5..53caa80 100644
--- a/DroidFishApp/src/main/res/values/strings.xml
+++ b/DroidFishApp/src/main/res/values/strings.xml
@@ -82,6 +82,7 @@ If you are running on battery power, it is recommended that you change settings
Save to PGN file
Open FEN/EPD file
Select file
+ Select directory
Load
Save
Reading PGN file…
diff --git a/DroidFishApp/src/main/res/xml/preferences.xml b/DroidFishApp/src/main/res/xml/preferences.xml
index b154930..9528158 100644
--- a/DroidFishApp/src/main/res/xml/preferences.xml
+++ b/DroidFishApp/src/main/res/xml/preferences.xml
@@ -609,12 +609,14 @@
android:defaultValue="500"
android:title="@string/prefs_bookRandom_title">
-
-
+
-
-
+
-
-
+