mirror of
https://github.com/dgis/emu48android
synced 2024-12-26 09:58:49 +01:00
Transform child activities with dialog fragments, and fix an issue with the numpad keys which send the arrow keys and the numbers at the same time.
This commit is contained in:
parent
6765cc7035
commit
2b2308d93f
26 changed files with 1172 additions and 998 deletions
|
@ -74,6 +74,8 @@ Version 1.8beta3 (2020-04-XX)
|
|||
- Fix: Overlapping window source position when Background/Offset is not (0,0).
|
||||
- Wrap the table of content in the former help documentation.
|
||||
- Save the settings at the end of the state file.
|
||||
- Transform all child activities with dialog fragments (to prevent unwanted state save).
|
||||
- Fix an issue with the numpad keys which send the arrow keys and the numbers at the same time.
|
||||
|
||||
|
||||
Version 1.7 (2019-12-12)
|
||||
|
@ -192,6 +194,8 @@ The Eric's Real scripts ("real*.kml" and "real*.bmp/png") are embedded in this a
|
|||
|
||||
TODO
|
||||
|
||||
- Add a settings to switch between dark and light theme.
|
||||
- Increase the loading speed (for Charlemagne faceplates) if possible.
|
||||
- Add the name of the file in the toast "State saved".
|
||||
- The clock seems unsynchronized sometimes.
|
||||
- Retain a key by right clicking if it is from a mouse.
|
||||
|
|
|
@ -28,11 +28,11 @@ if (keystorePropertiesFile.exists()) {
|
|||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
compileSdkVersion 29
|
||||
defaultConfig {
|
||||
applicationId "org.emulator.forty.eight"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 28
|
||||
targetSdkVersion 29
|
||||
versionCode 13
|
||||
versionName "1.8beta2"
|
||||
setProperty("archivesBaseName", "Emu48-v$versionName")
|
||||
|
@ -80,13 +80,12 @@ android {
|
|||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta3'
|
||||
implementation 'androidx.preference:preference:1.1.0'
|
||||
implementation 'com.google.android.material:material:1.2.0-alpha02'
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
implementation 'androidx.viewpager:viewpager:1.0.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0-beta01'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation 'androidx.preference:preference:1.1.1'
|
||||
implementation 'com.google.android.material:material:1.1.0'
|
||||
implementation 'androidx.documentfile:documentfile:1.0.1'
|
||||
testImplementation 'junit:junit:4.13-beta-3'
|
||||
androidTestImplementation 'androidx.test:runner:1.3.0-alpha02'
|
||||
androidTestImplementation 'androidx.test:runner:1.2.0'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0-alpha02'
|
||||
}
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
android:label="@string/app_name"
|
||||
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/AppTheme.NoActionBar">
|
||||
android:theme="@style/AppTheme.NoActionBar"
|
||||
>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
|
@ -44,31 +45,6 @@
|
|||
android:host="*"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".SettingsActivity"
|
||||
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
|
||||
android:label="@string/title_activity_settings"
|
||||
android:parentActivityName=".MainActivity">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="org.emulator.forty.eight.MainActivity"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name="org.emulator.calculator.InfoWebActivity"
|
||||
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
|
||||
android:label="@string/title_web_activity_info">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="org.emulator.forty.eight.MainActivity" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name="org.emulator.calculator.InfoActivity"
|
||||
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
|
||||
android:label="@string/title_activity_info">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="org.emulator.forty.eight.MainActivity" />
|
||||
</activity>
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.provider"
|
||||
|
|
|
@ -74,6 +74,8 @@ Version 1.8beta3 (2020-04-XX)
|
|||
- Fix: Overlapping window source position when Background/Offset is not (0,0).
|
||||
- Wrap the table of content in the former help documentation.
|
||||
- Save the settings at the end of the state file.
|
||||
- Transform all child activities with dialog fragments (to prevent unwanted state save).
|
||||
- Fix an issue with the numpad keys which send the arrow keys and the numbers at the same time.
|
||||
|
||||
|
||||
Version 1.7 (2019-12-12)
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
package org.emulator.calculator;
|
||||
|
||||
import android.app.Application;
|
||||
import android.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
public class EmuApplication extends Application {
|
||||
|
||||
|
|
|
@ -14,34 +14,65 @@
|
|||
|
||||
package org.emulator.calculator;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.text.method.ScrollingMovementMethod;
|
||||
import android.text.util.Linkify;
|
||||
import android.view.MenuItem;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatDialogFragment;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
public class InfoActivity extends AppCompatActivity {
|
||||
|
||||
private int homeId;
|
||||
public class InfoFragment extends AppCompatDialogFragment {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setStyle(AppCompatDialogFragment.STYLE_NO_FRAME, Utils.resId(this, "style", "AppTheme"));
|
||||
}
|
||||
|
||||
setContentView(Utils.resId(this, "layout", "activity_info"));
|
||||
String filepath = getString(Utils.resId(this, "string", "info_readme"));
|
||||
homeId = Utils.resId(this, "id", "home");
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
Dialog dialog = super.onCreateDialog(savedInstanceState);
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
|
||||
String title = getString(Utils.resId(this, "string", "title_fragment_info"));
|
||||
Dialog dialog = getDialog();
|
||||
if(dialog != null)
|
||||
dialog.setTitle(title);
|
||||
|
||||
View view = inflater.inflate(Utils.resId(this, "layout", "fragment_info"), container, false);
|
||||
|
||||
// Toolbar
|
||||
|
||||
Toolbar toolbar = view.findViewById(Utils.resId(this, "id", "my_toolbar"));
|
||||
toolbar.setTitle(title);
|
||||
Utils.colorizeDrawableWithColor(requireContext(), toolbar.getNavigationIcon(), android.R.attr.colorForeground);
|
||||
toolbar.setNavigationOnClickListener(v -> {
|
||||
dismiss();
|
||||
});
|
||||
|
||||
// Programmatically load text from an asset and place it into the
|
||||
// text view. Note that the text we are loading is ASCII, so we
|
||||
// need to convert it to UTF-16.
|
||||
try {
|
||||
InputStream is = getAssets().open(filepath);
|
||||
InputStream is = requireContext().getAssets().open(getString(Utils.resId(this, "string", "info_readme")));
|
||||
|
||||
// We guarantee that the available method returns the total
|
||||
// size of the asset... of course, this does mean that a single
|
||||
|
@ -58,23 +89,11 @@ public class InfoActivity extends AppCompatActivity {
|
|||
String text = new String(buffer);
|
||||
|
||||
// Finally stick the string into the text view.
|
||||
TextView textViewInfo = findViewById(Utils.resId(this, "id", "textViewInfo"));
|
||||
TextView textViewInfo = view.findViewById(Utils.resId(this, "id", "textViewInfo"));
|
||||
textViewInfo.setMovementMethod(new ScrollingMovementMethod());
|
||||
textViewInfo.setText(text);
|
||||
Linkify.addLinks(textViewInfo, Linkify.ALL);
|
||||
} catch (IOException e) {
|
||||
// Should never happen!
|
||||
//throw new RuntimeException(e);
|
||||
} catch (IOException ignored) { }
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if(item.getItemId() == homeId) {
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
// 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 2 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, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
package org.emulator.calculator;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Bundle;
|
||||
import android.view.MenuItem;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
public class InfoWebActivity extends AppCompatActivity {
|
||||
|
||||
private int homeId;
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(Utils.resId(this, "layout", "activity_web_info"));
|
||||
homeId = Utils.resId(this, "id", "home");
|
||||
|
||||
WebView webView = findViewById(Utils.resId(this, "id", "webViewInfo"));
|
||||
webView.getSettings().setJavaScriptEnabled(true);
|
||||
webView.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public void onPageFinished(WebView view, String url) {
|
||||
super.onPageFinished(view, url);
|
||||
|
||||
if(url != null)
|
||||
// Inject a CSS style to wrap the table of content if needed
|
||||
view.evaluateJavascript("javascript:(function(){var css=document.createElement(\"style\");css.type=\"text/css\";css.innerHTML=\".nav1{overflow-wrap:break-word;}\";document.head.appendChild(css);})();", null);
|
||||
}
|
||||
});
|
||||
webView.loadUrl(getString(Utils.resId(this, "string", "help_url")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if(item.getItemId() == homeId) {
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
// 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 2 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, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
package org.emulator.calculator;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Dialog;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatDialogFragment;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
||||
public class InfoWebFragment extends AppCompatDialogFragment {
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setStyle(AppCompatDialogFragment.STYLE_NO_FRAME, Utils.resId(this, "style", "AppTheme"));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
Dialog dialog = super.onCreateDialog(savedInstanceState);
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
|
||||
String title = getString(Utils.resId(this, "string", "title_web_fragment_info"));
|
||||
Dialog dialog = getDialog();
|
||||
if(dialog != null)
|
||||
dialog.setTitle(title);
|
||||
|
||||
View view = inflater.inflate(Utils.resId(this, "layout", "fragment_web_info"), container, false);
|
||||
|
||||
// Toolbar
|
||||
|
||||
Toolbar toolbar = view.findViewById(Utils.resId(this, "id", "my_toolbar"));
|
||||
toolbar.setTitle(title);
|
||||
Utils.colorizeDrawableWithColor(requireContext(), toolbar.getNavigationIcon(), android.R.attr.colorForeground);
|
||||
toolbar.setNavigationOnClickListener(v -> {
|
||||
dismiss();
|
||||
});
|
||||
|
||||
WebView webView = view.findViewById(Utils.resId(this, "id", "webViewInfo"));
|
||||
webView.getSettings().setJavaScriptEnabled(true);
|
||||
webView.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public void onPageFinished(WebView view, String url) {
|
||||
super.onPageFinished(view, url);
|
||||
|
||||
if(url != null)
|
||||
// Inject a CSS style to wrap the table of content if needed
|
||||
view.evaluateJavascript("javascript:(function(){var css=document.createElement(\"style\");css.type=\"text/css\";css.innerHTML=\".nav1{overflow-wrap:break-word;}\";document.head.appendChild(css);})();", null);
|
||||
}
|
||||
});
|
||||
webView.loadUrl(getString(Utils.resId(this, "string", "help_url")));
|
||||
|
||||
return view;
|
||||
}
|
||||
}
|
|
@ -30,14 +30,16 @@ import android.view.InputDevice;
|
|||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class MainScreenView extends PanAndScaleView {
|
||||
|
||||
protected static final String TAG = "MainScreenView";
|
||||
protected final boolean debug = false;
|
||||
protected final boolean debug = true;
|
||||
|
||||
private Paint paintFullCalc = new Paint();
|
||||
private Paint paintLCD = new Paint();
|
||||
|
@ -45,6 +47,7 @@ public class MainScreenView extends PanAndScaleView {
|
|||
private Rect srcBitmapCopy = new Rect();
|
||||
private SparseIntArray vkmap;
|
||||
private HashMap<Character, Integer> charmap;
|
||||
private List<Integer> numpadKey;
|
||||
private int kmlBackgroundColor = Color.BLACK;
|
||||
private boolean useKmlBackgroundColor = false;
|
||||
private int fallbackBackgroundColorType = 0;
|
||||
|
@ -102,6 +105,10 @@ public class MainScreenView extends PanAndScaleView {
|
|||
// vkmap.put(KeyEvent.KEYCODE_CTRL_RIGHT, 0x11); // VK_CONTROL
|
||||
vkmap.put(KeyEvent.KEYCODE_ESCAPE, 0x1B); // VK_ESCAPE
|
||||
vkmap.put(KeyEvent.KEYCODE_SPACE, 0x20); // VK_SPACE
|
||||
vkmap.put(KeyEvent.KEYCODE_PAGE_UP, 0x21); // VK_PRIOR
|
||||
vkmap.put(KeyEvent.KEYCODE_PAGE_DOWN, 0x22); // VK_NEXT
|
||||
vkmap.put(KeyEvent.KEYCODE_MOVE_END, 0x23); // VK_END
|
||||
vkmap.put(KeyEvent.KEYCODE_MOVE_HOME, 0x24); // VK_HOME
|
||||
vkmap.put(KeyEvent.KEYCODE_DPAD_LEFT, 0x25); // VK_LEFT
|
||||
vkmap.put(KeyEvent.KEYCODE_DPAD_UP, 0x26); // VK_UP
|
||||
vkmap.put(KeyEvent.KEYCODE_DPAD_RIGHT, 0x27); // VK_RIGHT
|
||||
|
@ -166,6 +173,21 @@ public class MainScreenView extends PanAndScaleView {
|
|||
vkmap.put(KeyEvent.KEYCODE_APOSTROPHE, 0xDE); // VK_OEM_7 (‘ »)
|
||||
vkmap.put(KeyEvent.KEYCODE_BACKSLASH, 0xDC); // VK_OEM_5 (\|)
|
||||
|
||||
numpadKey = Arrays.asList(
|
||||
KeyEvent.KEYCODE_NUMPAD_0,
|
||||
KeyEvent.KEYCODE_NUMPAD_1,
|
||||
KeyEvent.KEYCODE_NUMPAD_2,
|
||||
KeyEvent.KEYCODE_NUMPAD_3,
|
||||
KeyEvent.KEYCODE_NUMPAD_4,
|
||||
KeyEvent.KEYCODE_NUMPAD_5,
|
||||
KeyEvent.KEYCODE_NUMPAD_6,
|
||||
KeyEvent.KEYCODE_NUMPAD_7,
|
||||
KeyEvent.KEYCODE_NUMPAD_8,
|
||||
KeyEvent.KEYCODE_NUMPAD_9,
|
||||
KeyEvent.KEYCODE_NUMPAD_DOT,
|
||||
KeyEvent.KEYCODE_NUMPAD_COMMA
|
||||
);
|
||||
|
||||
this.setFocusable(true);
|
||||
this.setFocusableInTouchMode(true);
|
||||
}
|
||||
|
@ -213,6 +235,8 @@ public class MainScreenView extends PanAndScaleView {
|
|||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if((event.getFlags() & KeyEvent.FLAG_VIRTUAL_HARD_KEY) == 0
|
||||
&& (event.getSource() & InputDevice.SOURCE_KEYBOARD) == InputDevice.SOURCE_KEYBOARD) {
|
||||
if(!event.isNumLockOn() && numpadKey.indexOf(keyCode) != -1)
|
||||
return false;
|
||||
char pressedKey = (char) event.getUnicodeChar();
|
||||
Integer windowsKeycode = charmap.get(pressedKey);
|
||||
if(windowsKeycode == null)
|
||||
|
@ -232,6 +256,8 @@ public class MainScreenView extends PanAndScaleView {
|
|||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
if((event.getFlags() & KeyEvent.FLAG_VIRTUAL_HARD_KEY) == 0
|
||||
&& (event.getSource() & InputDevice.SOURCE_KEYBOARD) == InputDevice.SOURCE_KEYBOARD) {
|
||||
if(!event.isNumLockOn() && numpadKey.indexOf(keyCode) != -1)
|
||||
return false;
|
||||
char pressedKey = (char) event.getUnicodeChar();
|
||||
Integer windowsKeycode = charmap.get(pressedKey);
|
||||
if(windowsKeycode == null)
|
||||
|
|
|
@ -70,14 +70,6 @@ public class PrinterSimulator {
|
|||
m_bPrinter82240A = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* true to prevent the line wrapping for the textual printer when the character '\4' is sent by the calc.
|
||||
* @param preventLineWrap true to prevent the line wrapping; false otherwise.
|
||||
*/
|
||||
public void setPreventLineWrap(boolean preventLineWrap) {
|
||||
this.preventLineWrap = preventLineWrap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Change the paper, so we cleanup everything.
|
||||
|
@ -252,8 +244,6 @@ public class PrinterSimulator {
|
|||
|
||||
// Text Printer
|
||||
|
||||
private boolean preventLineWrap = false;
|
||||
|
||||
/**
|
||||
* ROMAN8 Unicode table
|
||||
*/
|
||||
|
@ -303,7 +293,7 @@ public class PrinterSimulator {
|
|||
private void addTextData(int byData) {
|
||||
do {
|
||||
// special LF and LF characters
|
||||
if (/*!preventLineWrap &&*/ byData == 0x04 || byData == 0x0A) {
|
||||
if (byData == 0x04 || byData == 0x0A) {
|
||||
textUpdate.append('\r');
|
||||
textUpdate.append('\n');
|
||||
if(debug) Log.d(TAG, "addTextData(" + byData + ")");
|
||||
|
|
|
@ -22,7 +22,9 @@ import android.graphics.Bitmap;
|
|||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
|
@ -70,9 +72,7 @@ public class PrinterSimulatorFragment extends AppCompatDialogFragment {
|
|||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
Dialog dialog = super.onCreateDialog(savedInstanceState);
|
||||
Window window = dialog.getWindow();
|
||||
if(window != null)
|
||||
window.requestFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,7 @@ public class PrinterSimulatorFragment extends AppCompatDialogFragment {
|
|||
|
||||
Toolbar toolbar = view.findViewById(Utils.resId(this, "id", "my_toolbar"));
|
||||
toolbar.setTitle(title);
|
||||
toolbar.setNavigationIcon(Utils.resId(this, "drawable", "ic_keyboard_backspace_white_24dp"));
|
||||
Utils.colorizeDrawableWithColor(requireContext(), toolbar.getNavigationIcon(), android.R.attr.colorForeground);
|
||||
toolbar.setNavigationOnClickListener(
|
||||
v -> dismiss()
|
||||
);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
package org.emulator.calculator;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
|
@ -33,226 +34,82 @@ import java.io.FileInputStream;
|
|||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class Settings extends PreferenceDataStore {
|
||||
|
||||
private static final String TAG = "Settings";
|
||||
protected final boolean debug = true;
|
||||
protected final boolean debug = false;
|
||||
|
||||
private final SharedPreferences defaultSettings;
|
||||
private final SharedPreferences androidSettings;
|
||||
private List<String> applicationSettingKeys = Arrays.asList("settings_kml_default", "settings_kml_folder", "lastDocument", "MRU");
|
||||
private final HashMap<String, Object> applicationSettings = new HashMap<>();
|
||||
private final HashMap<String, Object> commonSettings = new HashMap<>();
|
||||
private final HashMap<String, Object> embeddedStateSettings = new HashMap<>();
|
||||
private SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener;
|
||||
private boolean isCommonSettings = true;
|
||||
|
||||
public interface OnOneKeyChangedListener {
|
||||
void onOneKeyChanged(String keyChanged);
|
||||
}
|
||||
private OnOneKeyChangedListener oneKeyChangedListener;
|
||||
private static String magic = "MYHP";
|
||||
|
||||
|
||||
private boolean isDefaultSettings = true;
|
||||
|
||||
|
||||
public Settings(@NonNull SharedPreferences sharedPreferences) {
|
||||
if(debug) Log.d(TAG, "Settings()");
|
||||
this.defaultSettings = sharedPreferences;
|
||||
androidSettings = sharedPreferences;
|
||||
|
||||
loadApplicationSettings();
|
||||
}
|
||||
|
||||
public void registerOnSharedPreferenceChangeListener(SharedPreferences.OnSharedPreferenceChangeListener listener) {
|
||||
if(debug) Log.d(TAG, "registerOnSharedPreferenceChangeListener()");
|
||||
sharedPreferenceChangeListener = listener;
|
||||
public void registerOnOneKeyChangeListener(OnOneKeyChangedListener listener) {
|
||||
if(debug) Log.d(TAG, "registerOnOneKeyChangeListener()");
|
||||
oneKeyChangedListener = listener;
|
||||
}
|
||||
|
||||
public void unregisterOnSharedPreferenceChangeListener(SharedPreferences.OnSharedPreferenceChangeListener listener) {
|
||||
if(debug) Log.d(TAG, "unregisterOnSharedPreferenceChangeListener()");
|
||||
sharedPreferenceChangeListener = null;
|
||||
public void unregisterOnOneKeyChangeListener() {
|
||||
if(debug) Log.d(TAG, "unregisterOnOneKeyChangeListener()");
|
||||
oneKeyChangedListener = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putString(String key, @Nullable String value) {
|
||||
putString(key, value, false);
|
||||
}
|
||||
public void putString(String key, @Nullable String value, boolean forceDefault) {
|
||||
if(debug) Log.d(TAG, (isDefaultSettings ? "DEFAULT" : "LOCAL") + " putString(key: '" + key + "' value: '" + value + "')");
|
||||
if(isDefaultSettings || forceDefault) {
|
||||
defaultSettings.edit().putString(key, value).apply();
|
||||
if(sharedPreferenceChangeListener != null)
|
||||
sharedPreferenceChangeListener.onSharedPreferenceChanged(defaultSettings, key);
|
||||
} else {
|
||||
private void putValue(String key, @Nullable Object value) {
|
||||
if(applicationSettingKeys.indexOf(key) != -1)
|
||||
applicationSettings.put(key, value);
|
||||
else if(isCommonSettings)
|
||||
commonSettings.put(key, value);
|
||||
else
|
||||
embeddedStateSettings.put(key, value);
|
||||
if(sharedPreferenceChangeListener != null)
|
||||
sharedPreferenceChangeListener.onSharedPreferenceChanged(null, key);
|
||||
}
|
||||
if(oneKeyChangedListener != null)
|
||||
oneKeyChangedListener.onOneKeyChanged(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putStringSet(String key, @Nullable Set<String> value) {
|
||||
putStringSet(key, value, false);
|
||||
}
|
||||
public void putStringSet(String key, @Nullable Set<String> value, boolean forceDefault) {
|
||||
if(debug) Log.d(TAG, (isDefaultSettings ? "DEFAULT" : "LOCAL") + " putStringSet(key: '" + key + "' value: '" + "" + "')");
|
||||
if(isDefaultSettings || forceDefault) {
|
||||
defaultSettings.edit().putStringSet(key, value).apply();
|
||||
if(sharedPreferenceChangeListener != null)
|
||||
sharedPreferenceChangeListener.onSharedPreferenceChanged(defaultSettings, key);
|
||||
} else {
|
||||
embeddedStateSettings.put(key, value);
|
||||
if(sharedPreferenceChangeListener != null)
|
||||
sharedPreferenceChangeListener.onSharedPreferenceChanged(null, key);
|
||||
private Object getValue(String key) {
|
||||
Object value = null;
|
||||
if(!isCommonSettings)
|
||||
value = embeddedStateSettings.get(key);
|
||||
if(value == null) {
|
||||
if(applicationSettingKeys.indexOf(key) != -1)
|
||||
value = applicationSettings.get(key);
|
||||
else
|
||||
value = commonSettings.get(key);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putInt(String key, int value) {
|
||||
putInt(key, value, false);
|
||||
}
|
||||
public void putInt(String key, int value, boolean forceDefault) {
|
||||
if(debug) Log.d(TAG, (isDefaultSettings ? "DEFAULT" : "LOCAL") + " putInt(key: '" + key + "' value: '" + value + "')");
|
||||
if(isDefaultSettings || forceDefault) {
|
||||
defaultSettings.edit().putInt(key, value).apply();
|
||||
if(sharedPreferenceChangeListener != null)
|
||||
sharedPreferenceChangeListener.onSharedPreferenceChanged(defaultSettings, key);
|
||||
} else {
|
||||
embeddedStateSettings.put(key, value);
|
||||
if(sharedPreferenceChangeListener != null)
|
||||
sharedPreferenceChangeListener.onSharedPreferenceChanged(null, key);
|
||||
}
|
||||
public boolean getIsDefaultSettings() {
|
||||
return isCommonSettings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putLong(String key, long value){
|
||||
putLong(key,value,false);
|
||||
}
|
||||
public void putLong(String key, long value, boolean forceDefault) {
|
||||
if(debug) Log.d(TAG, (isDefaultSettings ? "DEFAULT" : "LOCAL") + " putLong(key: '" + key + "' value: '" + value + "')");
|
||||
if(isDefaultSettings || forceDefault) {
|
||||
defaultSettings.edit().putLong(key, value).apply();
|
||||
if(sharedPreferenceChangeListener != null)
|
||||
sharedPreferenceChangeListener.onSharedPreferenceChanged(defaultSettings, key);
|
||||
} else {
|
||||
embeddedStateSettings.put(key, value);
|
||||
if(sharedPreferenceChangeListener != null)
|
||||
sharedPreferenceChangeListener.onSharedPreferenceChanged(null, key);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putFloat(String key, float value){
|
||||
putFloat(key,value,false);
|
||||
}
|
||||
public void putFloat(String key, float value, boolean forceDefault) {
|
||||
if(debug) Log.d(TAG, (isDefaultSettings ? "DEFAULT" : "LOCAL") + " putFloat(key: '" + key + "' value: '" + value + "')");
|
||||
if(isDefaultSettings || forceDefault) {
|
||||
defaultSettings.edit().putFloat(key, value).apply();
|
||||
if(sharedPreferenceChangeListener != null)
|
||||
sharedPreferenceChangeListener.onSharedPreferenceChanged(defaultSettings, key);
|
||||
} else {
|
||||
embeddedStateSettings.put(key, value);
|
||||
if(sharedPreferenceChangeListener != null)
|
||||
sharedPreferenceChangeListener.onSharedPreferenceChanged(null, key);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putBoolean(String key, boolean value){
|
||||
putBoolean(key,value,false);
|
||||
}
|
||||
public void putBoolean(String key, boolean value, boolean forceDefault) {
|
||||
if(debug) Log.d(TAG, (isDefaultSettings ? "DEFAULT" : "LOCAL") + " putBoolean(key: '" + key + "' value: '" + value + "')");
|
||||
if(isDefaultSettings || forceDefault) {
|
||||
defaultSettings.edit().putBoolean(key, value).apply();
|
||||
if(sharedPreferenceChangeListener != null)
|
||||
sharedPreferenceChangeListener.onSharedPreferenceChanged(defaultSettings, key);
|
||||
} else {
|
||||
embeddedStateSettings.put(key, value);
|
||||
if(sharedPreferenceChangeListener != null)
|
||||
sharedPreferenceChangeListener.onSharedPreferenceChanged(null, key);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getString(String key, @Nullable String defValue) {
|
||||
if(debug) Log.d(TAG, "getString(key: '" + key + "')");
|
||||
if(!isDefaultSettings) {
|
||||
Object result = embeddedStateSettings.get(key);
|
||||
if(result instanceof String)
|
||||
return (String) result;
|
||||
}
|
||||
return defaultSettings.getString(key, defValue);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
@Override
|
||||
public Set<String> getStringSet(String key, @Nullable Set<String> defValues) {
|
||||
if(debug) Log.d(TAG, "getStringSet(key: '" + key + "')");
|
||||
if(!isDefaultSettings) {
|
||||
Object result = embeddedStateSettings.get(key);
|
||||
if(result instanceof Set<?>)
|
||||
try {
|
||||
return (Set<String>) result;
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
return defaultSettings.getStringSet(key, defValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(String key, int defValue) {
|
||||
if(debug) Log.d(TAG, "getInt(key: '" + key + "')");
|
||||
if(!isDefaultSettings) {
|
||||
Object result = embeddedStateSettings.get(key);
|
||||
if(result != null)
|
||||
try {
|
||||
return (Integer) result;
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
return defaultSettings.getInt(key, defValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(String key, long defValue) {
|
||||
if(debug) Log.d(TAG, "getLong(key: '" + key + "')");
|
||||
if(!isDefaultSettings) {
|
||||
Object result = embeddedStateSettings.get(key);
|
||||
if(result != null)
|
||||
try {
|
||||
return (Long) result;
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
return defaultSettings.getLong(key, defValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat(String key, float defValue) {
|
||||
if(debug) Log.d(TAG, "getFloat(key: '" + key + "')");
|
||||
if(!isDefaultSettings) {
|
||||
Object result = embeddedStateSettings.get(key);
|
||||
if(result != null)
|
||||
try {
|
||||
return (Float) result;
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
return defaultSettings.getFloat(key, defValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(String key, boolean defValue) {
|
||||
if(debug) Log.d(TAG, "getBoolean(key: '" + key + "')");
|
||||
if(!isDefaultSettings) {
|
||||
Object result = embeddedStateSettings.get(key);
|
||||
if(result != null)
|
||||
try {
|
||||
return (Boolean) result;
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
return defaultSettings.getBoolean(key, defValue);
|
||||
}
|
||||
|
||||
|
||||
public void setDefaultSettings(boolean defaultSettings) {
|
||||
isDefaultSettings = defaultSettings;
|
||||
public void setIsDefaultSettings(boolean isDefaultSettings) {
|
||||
this.isCommonSettings = isDefaultSettings;
|
||||
}
|
||||
|
||||
private static String toJSON(Collection<String> array) {
|
||||
|
@ -340,14 +197,23 @@ public class Settings extends PreferenceDataStore {
|
|||
|
||||
public void saveInStateFile(Context context, String url) {
|
||||
if(debug) Log.d(TAG, "saveInStateFile(url: '" + url + "')");
|
||||
|
||||
// Consolidate common and embedded settings but without the app only settings
|
||||
Map<String, Object> stateSettings = new HashMap<>();
|
||||
stateSettings.putAll(commonSettings);
|
||||
stateSettings.putAll(embeddedStateSettings);
|
||||
|
||||
String json = toJSON(stateSettings);
|
||||
byte[] jsonBytes = json.getBytes(StandardCharsets.UTF_8);
|
||||
int jsonLength = jsonBytes.length;
|
||||
|
||||
if(jsonLength < 65536) {
|
||||
Uri uri = Uri.parse(url);
|
||||
try {
|
||||
ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uri, "wa");
|
||||
if(pfd != null) {
|
||||
if (pfd != null) {
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(pfd.getFileDescriptor());
|
||||
String json = toJSON(embeddedStateSettings);
|
||||
byte[] jsonBytes = json.getBytes(StandardCharsets.UTF_8);
|
||||
int jsonLength = jsonBytes.length;
|
||||
|
||||
fileOutputStream.write(jsonBytes);
|
||||
// The JSON text should not be more than 64KB
|
||||
fileOutputStream.write((jsonLength >> 8) & 0xFF);
|
||||
|
@ -362,11 +228,18 @@ public class Settings extends PreferenceDataStore {
|
|||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clearEmbeddedStateSettings() {
|
||||
embeddedStateSettings.clear();
|
||||
}
|
||||
|
||||
@SuppressLint("ApplySharedPref")
|
||||
public void clearCommonDefaultSettings() {
|
||||
embeddedStateSettings.clear();
|
||||
commonSettings.clear();
|
||||
}
|
||||
|
||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||
public void loadFromStateFile(Context context, String url) {
|
||||
if(debug) Log.d(TAG, "loadFromStateFile(url: '" + url + "')");
|
||||
|
@ -383,7 +256,7 @@ public class Settings extends PreferenceDataStore {
|
|||
fileInputStream.read(lastChunk, 0, lastChunk.length);
|
||||
} else {
|
||||
int lastChunkOffset = lastChunk.length - (int)fileSize;
|
||||
fileInputStream.read(lastChunk, lastChunkOffset, lastChunk.length);
|
||||
fileInputStream.read(lastChunk, lastChunkOffset, (int)fileSize);
|
||||
}
|
||||
fileInputStream.close();
|
||||
|
||||
|
@ -408,4 +281,154 @@ public class Settings extends PreferenceDataStore {
|
|||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadApplicationSettings() {
|
||||
commonSettings.clear();
|
||||
Map<String, ?> keyValuePairs = androidSettings.getAll();
|
||||
for (String key : keyValuePairs.keySet()) {
|
||||
if (applicationSettingKeys.indexOf(key) != -1)
|
||||
applicationSettings.put(key, keyValuePairs.get(key));
|
||||
else
|
||||
commonSettings.put(key, keyValuePairs.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
public void saveApplicationSettings() {
|
||||
if(debug) Log.d(TAG, "saveApplicationSettings()");
|
||||
|
||||
SharedPreferences.Editor settingsEditor = androidSettings.edit();
|
||||
for (String key : commonSettings.keySet()) {
|
||||
Object value = commonSettings.get(key);
|
||||
putKeyValueInEditor(settingsEditor, key, value);
|
||||
}
|
||||
for (String key : applicationSettingKeys) {
|
||||
Object value = applicationSettings.get(key);
|
||||
putKeyValueInEditor(settingsEditor, key, value);
|
||||
}
|
||||
|
||||
settingsEditor.apply();
|
||||
}
|
||||
|
||||
private void putKeyValueInEditor(SharedPreferences.Editor settingsEditor, String key, Object value) {
|
||||
if (value instanceof Integer)
|
||||
settingsEditor.putInt(key, ((Number)value).intValue());
|
||||
else if (value instanceof Long)
|
||||
settingsEditor.putLong(key, ((Number)value).longValue());
|
||||
else if (value instanceof Boolean)
|
||||
settingsEditor.putBoolean(key, (Boolean) value);
|
||||
else if (value instanceof Float || value instanceof Double)
|
||||
settingsEditor.putFloat(key, ((Number)value).floatValue());
|
||||
else if (value instanceof String)
|
||||
settingsEditor.putString(key, (String) value);
|
||||
else if (value instanceof Set<?>)
|
||||
settingsEditor.putStringSet(key, (Set<String>) value);
|
||||
else
|
||||
settingsEditor.putString(key, null);
|
||||
}
|
||||
|
||||
|
||||
// PreferenceDataStore
|
||||
|
||||
@Override
|
||||
public void putString(String key, @Nullable String value) {
|
||||
if(debug) Log.d(TAG, (isCommonSettings ? "DEFAULT" : "LOCAL") + " putString(key: '" + key + "' value: '" + value + "')");
|
||||
putValue(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putStringSet(String key, @Nullable Set<String> value) {
|
||||
if(debug) Log.d(TAG, (isCommonSettings ? "DEFAULT" : "LOCAL") + " putStringSet(key: '" + key + "' value: '" + "" + "')");
|
||||
putValue(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putInt(String key, int value) {
|
||||
if(debug) Log.d(TAG, (isCommonSettings ? "DEFAULT" : "LOCAL") + " putInt(key: '" + key + "' value: '" + value + "')");
|
||||
putValue(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putLong(String key, long value){
|
||||
if(debug) Log.d(TAG, (isCommonSettings ? "DEFAULT" : "LOCAL") + " putLong(key: '" + key + "' value: '" + value + "')");
|
||||
putValue(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putFloat(String key, float value){
|
||||
if(debug) Log.d(TAG, (isCommonSettings ? "DEFAULT" : "LOCAL") + " putFloat(key: '" + key + "' value: '" + value + "')");
|
||||
putValue(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putBoolean(String key, boolean value){
|
||||
if(debug) Log.d(TAG, (isCommonSettings ? "DEFAULT" : "LOCAL") + " putBoolean(key: '" + key + "' value: '" + value + "')");
|
||||
putValue(key, value);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getString(String key, @Nullable String defValue) {
|
||||
if(debug) Log.d(TAG, "getString(key: '" + key + "')");
|
||||
Object result = getValue(key);
|
||||
if(result instanceof String)
|
||||
return (String) result;
|
||||
return defValue;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
@Override
|
||||
public Set<String> getStringSet(String key, @Nullable Set<String> defValues) {
|
||||
if(debug) Log.d(TAG, "getStringSet(key: '" + key + "')");
|
||||
Object result = getValue(key);
|
||||
if(result instanceof Set<?>)
|
||||
try {
|
||||
return (Set<String>) result;
|
||||
} catch (Exception ignored) {}
|
||||
return defValues;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(String key, int defValue) {
|
||||
if(debug) Log.d(TAG, "getInt(key: '" + key + "')");
|
||||
Object result = getValue(key);
|
||||
if(result != null)
|
||||
try {
|
||||
return ((Number) result).intValue();
|
||||
} catch (Exception ignored) {}
|
||||
return defValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(String key, long defValue) {
|
||||
if(debug) Log.d(TAG, "getLong(key: '" + key + "')");
|
||||
Object result = getValue(key);
|
||||
if(result != null)
|
||||
try {
|
||||
return ((Number) result).longValue();
|
||||
} catch (Exception ignored) {}
|
||||
return defValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat(String key, float defValue) {
|
||||
if(debug) Log.d(TAG, "getFloat(key: '" + key + "')");
|
||||
Object result = getValue(key);
|
||||
if(result != null)
|
||||
try {
|
||||
return ((Number) result).floatValue();
|
||||
} catch (Exception ignored) {}
|
||||
return defValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(String key, boolean defValue) {
|
||||
if(debug) Log.d(TAG, "getBoolean(key: '" + key + "')");
|
||||
Object result = getValue(key);
|
||||
if(result != null)
|
||||
try {
|
||||
return (Boolean) result;
|
||||
} catch (Exception ignored) {}
|
||||
return defValue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,17 +16,24 @@ package org.emulator.calculator;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.BlendMode;
|
||||
import android.graphics.BlendModeColorFilter;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.provider.OpenableColumns;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import javax.microedition.khronos.egl.EGL10;
|
||||
|
@ -43,28 +50,48 @@ public class Utils {
|
|||
toast.show();
|
||||
}
|
||||
|
||||
static int resId(Context context, String resourcename, String variableName)
|
||||
{
|
||||
static int resId(Context context, String resourceName, String variableName) {
|
||||
try {
|
||||
return context.getResources().getIdentifier(variableName, resourcename, context.getApplicationContext().getPackageName());
|
||||
return context.getResources().getIdentifier(variableName, resourceName, context.getApplicationContext().getPackageName());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int resId(Fragment fragment, String resourcename, String variableName)
|
||||
{
|
||||
public static int resId(Fragment fragment, String resourceName, String variableName) {
|
||||
try {
|
||||
Context context = fragment.getContext();
|
||||
if(context != null)
|
||||
return fragment.getResources().getIdentifier(variableName, resourcename, context.getApplicationContext().getPackageName());
|
||||
return fragment.getResources().getIdentifier(variableName, resourceName, context.getApplicationContext().getPackageName());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static int getThemedColor(Context context, int attr) {
|
||||
Resources.Theme theme = context.getTheme();
|
||||
if (theme != null) {
|
||||
TypedValue tv = new TypedValue();
|
||||
theme.resolveAttribute(attr, tv, true);
|
||||
Resources resources = context.getResources();
|
||||
if(resources != null)
|
||||
return ContextCompat.getColor(context, tv.resourceId);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static void colorizeDrawableWithColor(Context context, Drawable icon, int colorAttribute) {
|
||||
if(icon != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
|
||||
icon.setColorFilter(new BlendModeColorFilter(Utils.getThemedColor(context, colorAttribute), BlendMode.SRC_ATOP));
|
||||
else
|
||||
icon.setColorFilter(Utils.getThemedColor(context, colorAttribute), PorterDuff.Mode.SRC_ATOP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void makeUriPersistable(Context context, Intent data, Uri uri) {
|
||||
int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
|
||||
|
|
|
@ -21,7 +21,6 @@ import android.content.Context;
|
|||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.res.AssetManager;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
|
@ -32,7 +31,6 @@ import android.os.Bundle;
|
|||
import android.os.ParcelFileDescriptor;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.util.TypedValue;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
@ -47,10 +45,8 @@ import android.widget.Toast;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBarDrawerToggle;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.content.FileProvider;
|
||||
import androidx.core.view.GravityCompat;
|
||||
import androidx.documentfile.provider.DocumentFile;
|
||||
|
@ -59,8 +55,8 @@ import androidx.drawerlayout.widget.DrawerLayout;
|
|||
import com.google.android.material.navigation.NavigationView;
|
||||
|
||||
import org.emulator.calculator.EmuApplication;
|
||||
import org.emulator.calculator.InfoActivity;
|
||||
import org.emulator.calculator.InfoWebActivity;
|
||||
import org.emulator.calculator.InfoFragment;
|
||||
import org.emulator.calculator.InfoWebFragment;
|
||||
import org.emulator.calculator.LCDOverlappingView;
|
||||
import org.emulator.calculator.MainScreenView;
|
||||
import org.emulator.calculator.NativeLib;
|
||||
|
@ -96,6 +92,7 @@ import java.util.regex.Pattern;
|
|||
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
|
||||
|
||||
private static final String TAG = "MainActivity";
|
||||
private boolean debug = false;
|
||||
private Settings settings;
|
||||
private NavigationView navigationView;
|
||||
private DrawerLayout drawer;
|
||||
|
@ -107,7 +104,6 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
public static final int INTENT_GETSAVEFILENAME = 2;
|
||||
public static final int INTENT_OBJECT_LOAD = 3;
|
||||
public static final int INTENT_OBJECT_SAVE = 4;
|
||||
public static final int INTENT_SETTINGS = 5;
|
||||
public static final int INTENT_PORT2LOAD = 6;
|
||||
public static final int INTENT_PICK_KML_FOLDER_FOR_NEW_FILE = 7;
|
||||
public static final int INTENT_PICK_KML_FOLDER_FOR_CHANGING = 8;
|
||||
|
@ -144,20 +140,14 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
toolbar.setVisibility(View.GONE);
|
||||
|
||||
drawer = findViewById(R.id.drawer_layout);
|
||||
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
|
||||
drawer.addDrawerListener(toggle);
|
||||
toggle.syncState();
|
||||
|
||||
navigationView = findViewById(R.id.nav_view);
|
||||
navigationView.setNavigationItemSelectedListener(this);
|
||||
|
||||
settings = EmuApplication.getSettings();
|
||||
settings.setDefaultSettings(true);
|
||||
settings.setIsDefaultSettings(true);
|
||||
|
||||
|
||||
ViewGroup mainScreenContainer = findViewById(R.id.main_screen_container);
|
||||
|
@ -193,7 +183,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
}
|
||||
}
|
||||
updateMRU();
|
||||
updateFromPreferences(null);
|
||||
updateFromPreferences(null, false);
|
||||
|
||||
updateNavigationDrawerItems();
|
||||
|
||||
|
@ -240,7 +230,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
Utils.makeUriPersistable(this, intent, documentToOpenUri);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
if(debug) Log.e(TAG, e.getMessage());
|
||||
}
|
||||
else if(drawer != null)
|
||||
drawer.openDrawer(GravityCompat.START);
|
||||
|
@ -285,7 +275,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
protected void onStop() {
|
||||
//TODO We cannot make the difference between going to the settings or loading/saving a file and a real app stop/kill!
|
||||
// -> Maybe by settings some flags when loading/saving
|
||||
settings.putStringSet("MRU", mruLinkedHashMap.keySet(), true);
|
||||
settings.putStringSet("MRU", mruLinkedHashMap.keySet());
|
||||
if(lcdOverlappingView != null)
|
||||
lcdOverlappingView.saveViewLayout();
|
||||
|
||||
|
@ -295,6 +285,8 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
onFileSave();
|
||||
}
|
||||
|
||||
settings.saveApplicationSettings();
|
||||
|
||||
clearFolderCache();
|
||||
|
||||
super.onStop();
|
||||
|
@ -534,7 +526,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
String url = file.getUri().toString();
|
||||
String name = file.getName();
|
||||
String mime = file.getType();
|
||||
Log.d(TAG, "url: " + url + ", name: " + name + ", mime: " + mime);
|
||||
if(debug) Log.d(TAG, "url: " + url + ", name: " + name + ", mime: " + mime);
|
||||
if(kmlMimeType.equals(mime)) {
|
||||
calculatorsAssetFilenames.add(url);
|
||||
}
|
||||
|
@ -662,7 +654,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
private void newFileFromKML(String kmlScriptFilename) {
|
||||
int result = NativeLib.onFileNew(kmlScriptFilename);
|
||||
if(result > 0) {
|
||||
settings.setDefaultSettings(false);
|
||||
settings.setIsDefaultSettings(false);
|
||||
settings.clearEmbeddedStateSettings();
|
||||
showCalculatorView(true);
|
||||
displayFilename("");
|
||||
|
@ -731,7 +723,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
private void OnFileClose() {
|
||||
ensureDocumentSaved(() -> {
|
||||
NativeLib.onFileClose();
|
||||
settings.setDefaultSettings(true);
|
||||
settings.setIsDefaultSettings(true);
|
||||
settings.clearEmbeddedStateSettings();
|
||||
showCalculatorView(false);
|
||||
saveLastDocument("");
|
||||
|
@ -744,7 +736,32 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
}
|
||||
|
||||
private void OnSettings() {
|
||||
startActivityForResult(new Intent(this, SettingsActivity.class), INTENT_SETTINGS);
|
||||
SettingsFragment settingsFragment = new SettingsFragment();
|
||||
settingsFragment.registerOnSettingsKeyChangedListener(settingsKeyChanged -> {
|
||||
HashSet<String> changedKeysCleaned = new HashSet<>();
|
||||
for (String key : settingsKeyChanged) {
|
||||
if(debug) Log.d(TAG, "ChangedKey): " + key);
|
||||
switch (key) {
|
||||
case "settings_port1en":
|
||||
case "settings_port1wr":
|
||||
changedKeysCleaned.add("settings_port1");
|
||||
break;
|
||||
case "settings_port2en":
|
||||
case "settings_port2wr":
|
||||
case "settings_port2load":
|
||||
changedKeysCleaned.add("settings_port2");
|
||||
break;
|
||||
default:
|
||||
changedKeysCleaned.add(key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (String key : changedKeysCleaned) {
|
||||
updateFromPreferences(key, true);
|
||||
}
|
||||
settingsFragment.unregisterOnSettingsKeyChangedListener();
|
||||
});
|
||||
settingsFragment.show(getSupportFragmentManager(), "SettingsFragment");
|
||||
}
|
||||
|
||||
private void openDocument() {
|
||||
|
@ -911,7 +928,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
}
|
||||
} else if(which == lastIndex + 1) {
|
||||
// Reset to default KML folder
|
||||
settings.putBoolean("settings_kml_default", true, true);
|
||||
settings.putBoolean("settings_kml_default", true);
|
||||
updateFromPreferences("settings_kml", true);
|
||||
if(changeKML)
|
||||
OnViewScript();
|
||||
|
@ -1002,41 +1019,15 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
}
|
||||
|
||||
private void OnTopics() {
|
||||
startActivity(new Intent(this, InfoWebActivity.class));
|
||||
new InfoWebFragment().show(getSupportFragmentManager(), "InfoWebFragment");
|
||||
}
|
||||
private void OnAbout() {
|
||||
startActivity(new Intent(this, InfoActivity.class));
|
||||
new InfoFragment().show(getSupportFragmentManager(), "InfoFragment");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||
if(resultCode == Activity.RESULT_OK && data != null) {
|
||||
if(requestCode == INTENT_SETTINGS) {
|
||||
String[] changedKeys = data.getStringArrayExtra("changedKeys");
|
||||
if(changedKeys != null) {
|
||||
HashSet<String> changedKeysCleaned = new HashSet<>();
|
||||
for (String key : changedKeys) {
|
||||
//Log.d(TAG, "ChangedKey): " + key);
|
||||
switch (key) {
|
||||
case "settings_port1en":
|
||||
case "settings_port1wr":
|
||||
changedKeysCleaned.add("settings_port1");
|
||||
break;
|
||||
case "settings_port2en":
|
||||
case "settings_port2wr":
|
||||
case "settings_port2load":
|
||||
changedKeysCleaned.add("settings_port2");
|
||||
break;
|
||||
default:
|
||||
changedKeysCleaned.add(key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (String key : changedKeysCleaned) {
|
||||
updateFromPreferences(key, true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Uri uri = data.getData();
|
||||
String url = null;
|
||||
if (uri != null)
|
||||
|
@ -1044,7 +1035,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
if (url != null) {
|
||||
switch (requestCode) {
|
||||
case INTENT_GETOPENFILENAME: {
|
||||
//Log.d(TAG, "onActivityResult INTENT_GETOPENFILENAME " + url);
|
||||
if(debug) Log.d(TAG, "onActivityResult INTENT_GETOPENFILENAME " + url);
|
||||
int openResult = onFileOpen(url);
|
||||
if (openResult > 0) {
|
||||
saveLastDocument(url);
|
||||
|
@ -1062,7 +1053,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
break;
|
||||
}
|
||||
case INTENT_GETSAVEFILENAME: {
|
||||
//Log.d(TAG, "onActivityResult INTENT_GETSAVEFILENAME " + url);
|
||||
if(debug) Log.d(TAG, "onActivityResult INTENT_GETSAVEFILENAME " + url);
|
||||
if (NativeLib.onFileSaveAs(url) != 0) {
|
||||
showAlert(getString(R.string.message_state_saved));
|
||||
settings.saveInStateFile(this, url);
|
||||
|
@ -1075,12 +1066,12 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
break;
|
||||
}
|
||||
case INTENT_OBJECT_LOAD: {
|
||||
//Log.d(TAG, "onActivityResult INTENT_OBJECT_LOAD " + url);
|
||||
if(debug) Log.d(TAG, "onActivityResult INTENT_OBJECT_LOAD " + url);
|
||||
NativeLib.onObjectLoad(url);
|
||||
break;
|
||||
}
|
||||
case INTENT_OBJECT_SAVE: {
|
||||
//Log.d(TAG, "onActivityResult INTENT_OBJECT_SAVE " + url);
|
||||
if(debug) Log.d(TAG, "onActivityResult INTENT_OBJECT_SAVE " + url);
|
||||
NativeLib.onObjectSave(url, null);
|
||||
break;
|
||||
}
|
||||
|
@ -1088,9 +1079,9 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
case INTENT_PICK_KML_FOLDER_FOR_CHANGING:
|
||||
case INTENT_PICK_KML_FOLDER_FOR_SETTINGS:
|
||||
case INTENT_PICK_KML_FOLDER_FOR_SECURITY: {
|
||||
//Log.d(TAG, "onActivityResult INTENT_PICK_KML_FOLDER " + url);
|
||||
settings.putBoolean("settings_kml_default", false, true);
|
||||
settings.putString("settings_kml_folder", url, true);
|
||||
if(debug) Log.d(TAG, "onActivityResult INTENT_PICK_KML_FOLDER " + url);
|
||||
settings.putBoolean("settings_kml_default", false);
|
||||
settings.putString("settings_kml_folder", url);
|
||||
updateFromPreferences("settings_kml", true);
|
||||
Utils.makeUriPersistableReadOnly(this, data, uri);
|
||||
|
||||
|
@ -1114,7 +1105,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
break;
|
||||
}
|
||||
case INTENT_CREATE_RAM_CARD: {
|
||||
//Log.d(TAG, "onActivityResult INTENT_CREATE_RAM_CARD " + url);
|
||||
if(debug) Log.d(TAG, "onActivityResult INTENT_CREATE_RAM_CARD " + url);
|
||||
if(selectedRAMSize > 0) {
|
||||
int size = 2 * selectedRAMSize;
|
||||
FileOutputStream fileOutputStream;
|
||||
|
@ -1138,13 +1129,13 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
break;
|
||||
}
|
||||
case INTENT_MACRO_LOAD: {
|
||||
//Log.d(TAG, "onActivityResult INTENT_MACRO_LOAD " + url);
|
||||
if(debug) Log.d(TAG, "onActivityResult INTENT_MACRO_LOAD " + url);
|
||||
NativeLib.onToolMacroPlay(url);
|
||||
updateNavigationDrawerItems();
|
||||
break;
|
||||
}
|
||||
case INTENT_MACRO_SAVE: {
|
||||
//Log.d(TAG, "onActivityResult INTENT_MACRO_SAVE " + url);
|
||||
if(debug) Log.d(TAG, "onActivityResult INTENT_MACRO_SAVE " + url);
|
||||
NativeLib.onToolMacroNew(url);
|
||||
updateNavigationDrawerItems();
|
||||
break;
|
||||
|
@ -1154,13 +1145,12 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fileSaveAsCallback = null;
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
private void saveLastDocument(String url) {
|
||||
settings.putString("lastDocument", url, true);
|
||||
settings.putString("lastDocument", url);
|
||||
|
||||
if(url != null && !url.isEmpty())
|
||||
mruLinkedHashMap.put(url, null);
|
||||
|
@ -1177,14 +1167,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
} else {
|
||||
mainScreenView.setEnablePanAndScale(false);
|
||||
mainScreenView.setVisibility(View.GONE);
|
||||
|
||||
Resources.Theme theme = getTheme();
|
||||
if (theme != null) {
|
||||
TypedValue tv = new TypedValue();
|
||||
theme.resolveAttribute(android.R.attr.colorForeground, tv, true);
|
||||
int iconColor = getResources().getColor(tv.resourceId);
|
||||
imageButtonMenu.setColorFilter(iconColor);
|
||||
}
|
||||
imageButtonMenu.setColorFilter(Utils.getThemedColor(this, android.R.attr.colorForeground));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1192,18 +1175,18 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
|
||||
// Eventually, close the previous state file
|
||||
NativeLib.onFileClose();
|
||||
settings.setDefaultSettings(true);
|
||||
settings.setIsDefaultSettings(true);
|
||||
showCalculatorView(false);
|
||||
displayFilename("");
|
||||
|
||||
// Pre-Load the embedded settings from the end of the classic state file
|
||||
settings.setDefaultSettings(false);
|
||||
settings.setIsDefaultSettings(false);
|
||||
settings.clearEmbeddedStateSettings();
|
||||
settings.loadFromStateFile(this, url);
|
||||
|
||||
|
||||
// Update the Emu VM with the new settings
|
||||
updateFromPreferences(null);
|
||||
updateFromPreferences(null, false);
|
||||
|
||||
// Load the genuine state file
|
||||
int result = NativeLib.onFileOpen(url);
|
||||
|
@ -1214,7 +1197,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
showKMLLog();
|
||||
} else {
|
||||
// Because it failed to load the state file, we switch to the default settings
|
||||
settings.setDefaultSettings(true);
|
||||
settings.setIsDefaultSettings(true);
|
||||
settings.clearEmbeddedStateSettings();
|
||||
showKMLLogForce();
|
||||
}
|
||||
|
@ -1564,23 +1547,18 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
updateFromPreferences("settings_port1", true);
|
||||
}
|
||||
|
||||
private void updateFromPreferences(Set<String> keys) {
|
||||
if(keys != null) {
|
||||
for (String settingKey : keys)
|
||||
updateFromPreferences(settingKey, false);
|
||||
} else {
|
||||
private void updateFromPreferences(String key, boolean isDynamic) {
|
||||
int isDynamicValue = isDynamic ? 1 : 0;
|
||||
if(key == null) {
|
||||
String[] settingKeys = {
|
||||
"settings_realspeed", "settings_grayscale", "settings_rotation", "settings_auto_layout", "settings_allow_pinch_zoom", "settings_lcd_overlapping_mode", "settings_lcd_pixel_borders",
|
||||
"settings_hide_bar", "settings_hide_button_menu", "settings_sound_volume", "settings_haptic_feedback",
|
||||
"settings_background_kml_color", "settings_background_fallback_color",
|
||||
"settings_printer_model", "settings_printer_prevent_line_wrap", "settings_macro",
|
||||
"settings_printer_model", "settings_macro",
|
||||
"settings_kml", "settings_port1", "settings_port2" };
|
||||
for (String settingKey : settingKeys)
|
||||
updateFromPreferences(settingKey, false);
|
||||
}
|
||||
}
|
||||
private void updateFromPreferences(String key, boolean isDynamic) {
|
||||
int isDynamicValue = isDynamic ? 1 : 0;
|
||||
} else {
|
||||
switch (key) {
|
||||
case "settings_realspeed":
|
||||
NativeLib.setConfiguration(key, isDynamicValue, settings.getBoolean(key, false) ? 1 : 0, 0, null);
|
||||
|
@ -1627,7 +1605,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
case "settings_hide_bar":
|
||||
case "settings_hide_bar_status":
|
||||
case "settings_hide_bar_nav":
|
||||
if(settings.getBoolean("settings_hide_bar_status", false)
|
||||
if (settings.getBoolean("settings_hide_bar_status", false)
|
||||
|| settings.getBoolean("settings_hide_bar_nav", false))
|
||||
hideSystemUI();
|
||||
else
|
||||
|
@ -1663,15 +1641,12 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
// Catch bad number format
|
||||
}
|
||||
break;
|
||||
case "settings_printer_prevent_line_wrap":
|
||||
printerSimulator.setPreventLineWrap(settings.getBoolean("settings_printer_prevent_line_wrap", false));
|
||||
break;
|
||||
|
||||
case "settings_kml":
|
||||
case "settings_kml_default":
|
||||
case "settings_kml_folder":
|
||||
kmlFolderUseDefault = settings.getBoolean("settings_kml_default", true);
|
||||
if(!kmlFolderUseDefault) {
|
||||
if (!kmlFolderUseDefault) {
|
||||
kmlFolderURL = settings.getString("settings_kml_folder", "");
|
||||
// https://github.com/googlesamples/android-DirectorySelection
|
||||
// https://stackoverflow.com/questions/44185477/intent-action-open-document-tree-doesnt-seem-to-return-a-real-path-to-drive/44185706
|
||||
|
@ -1707,6 +1682,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
|
|
|
@ -1,281 +0,0 @@
|
|||
// 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 2 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, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
package org.emulator.forty.eight;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Configuration;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.InputType;
|
||||
import android.util.Log;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.EditText;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceDataStore;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.SeekBarPreference;
|
||||
|
||||
import org.emulator.calculator.EmuApplication;
|
||||
import org.emulator.calculator.NativeLib;
|
||||
import org.emulator.calculator.Settings;
|
||||
import org.emulator.calculator.Utils;
|
||||
|
||||
public class SettingsActivity extends AppCompatActivity {
|
||||
|
||||
private static final String TAG = "SettingsActivity";
|
||||
protected final boolean debug = false;
|
||||
|
||||
private static Settings settings;
|
||||
private HashSet<String> settingsKeyChanged = new HashSet<>();
|
||||
private SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = (sharedPreferences, key) -> settingsKeyChanged.add(key);
|
||||
private GeneralPreferenceFragment generalPreferenceFragment;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
settings = EmuApplication.getSettings();
|
||||
settings.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
|
||||
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
// Show the Up button in the action bar.
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
|
||||
generalPreferenceFragment = new GeneralPreferenceFragment();
|
||||
getSupportFragmentManager().beginTransaction().replace(android.R.id.content, generalPreferenceFragment).commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
settings.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
if (id == android.R.id.home) {
|
||||
onBackPressed();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
Intent resultIntent = new Intent();
|
||||
resultIntent.putExtra("changedKeys", settingsKeyChanged.toArray(new String[0]));
|
||||
setResult(Activity.RESULT_OK, resultIntent);
|
||||
finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* This fragment shows general preferences only. It is used when the
|
||||
* activity is showing a two-pane settings UI.
|
||||
*/
|
||||
public static class GeneralPreferenceFragment extends PreferenceFragmentCompat {
|
||||
|
||||
Preference preferencePort2load = null;
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
getPreferenceManager().setPreferenceDataStore(EmuApplication.getSettings());
|
||||
|
||||
// Load the preferences from an XML resource
|
||||
setPreferencesFromResource(R.xml.pref_general, rootKey);
|
||||
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
// Sound settings
|
||||
|
||||
SeekBarPreference preferenceSoundVolume = findPreference("settings_sound_volume");
|
||||
if(preferenceSoundVolume != null) {
|
||||
if(!NativeLib.getSoundEnabled()) {
|
||||
preferenceSoundVolume.setSummary("Cannot initialize the sound engine.");
|
||||
preferenceSoundVolume.setEnabled(false);
|
||||
} else {
|
||||
preferenceSoundVolume.setOnPreferenceClickListener(preference -> {
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(Objects.requireNonNull(getContext()));
|
||||
alert.setTitle(R.string.settings_sound_volume_dialog_title);
|
||||
final EditText input = new EditText(getContext());
|
||||
input.setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||
input.setRawInputType(Configuration.KEYBOARD_12KEY);
|
||||
input.setFocusable(true);
|
||||
input.setText(String.format(Locale.US,"%d", preferenceSoundVolume.getValue()));
|
||||
alert.setView(input);
|
||||
alert.setPositiveButton(R.string.message_ok, (dialog, whichButton) -> {
|
||||
String newValueText = input.getText().toString();
|
||||
try {
|
||||
int newValue = Integer.parseInt(newValueText);
|
||||
if(newValue >= preferenceSoundVolume.getMin() && newValue <= preferenceSoundVolume.getMax())
|
||||
preferenceSoundVolume.setValue(newValue);
|
||||
} catch (NumberFormatException ignored) {}
|
||||
});
|
||||
alert.setNegativeButton(R.string.message_cancel, (dialog, whichButton) -> {});
|
||||
alert.show();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Background color settings
|
||||
|
||||
Preference preferenceBackgroundFallbackColor = findPreference("settings_background_fallback_color");
|
||||
// final ColorPickerPreferenceCompat preferenceBackgroundCustomColor = (ColorPickerPreferenceCompat)findPreference("settings_background_custom_color");
|
||||
if(preferenceBackgroundFallbackColor != null /*&& preferenceBackgroundCustomColor != null*/) {
|
||||
final String[] stringArrayBackgroundFallbackColor = getResources().getStringArray(R.array.settings_background_fallback_color_item);
|
||||
Preference.OnPreferenceChangeListener onPreferenceChangeListenerBackgroundFallbackColor = (preference, value) -> {
|
||||
if(value != null) {
|
||||
String stringValue = value.toString();
|
||||
int backgroundFallbackColor = -1;
|
||||
try {
|
||||
backgroundFallbackColor = Integer.parseInt(stringValue);
|
||||
} catch (NumberFormatException ignored) {}
|
||||
if(backgroundFallbackColor >= 0 && backgroundFallbackColor < stringArrayBackgroundFallbackColor.length)
|
||||
preference.setSummary(stringArrayBackgroundFallbackColor[backgroundFallbackColor]);
|
||||
// preferenceBackgroundCustomColor.setEnabled(backgroundFallbackColor == 2);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
preferenceBackgroundFallbackColor.setOnPreferenceChangeListener(onPreferenceChangeListenerBackgroundFallbackColor);
|
||||
onPreferenceChangeListenerBackgroundFallbackColor.onPreferenceChange(preferenceBackgroundFallbackColor,
|
||||
settings.getString(preferenceBackgroundFallbackColor.getKey(), "0"));
|
||||
|
||||
|
||||
//preferenceBackgroundCustomColor.setColorValue(customColor);
|
||||
|
||||
// Preference.OnPreferenceChangeListener onPreferenceChangeListenerBackgroundCustomColor = new Preference.OnPreferenceChangeListener() {
|
||||
// @Override
|
||||
// public boolean onPreferenceChange(Preference preference, Object value) {
|
||||
// if(value != null) {
|
||||
// int customColor = (Integer)value;
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
// };
|
||||
// preferenceBackgroundCustomColor.setOnPreferenceChangeListener(onPreferenceChangeListenerBackgroundCustomColor);
|
||||
// onPreferenceChangeListenerBackgroundCustomColor.onPreferenceChange(preferenceBackgroundCustomColor, sharedPreferences.getBoolean(preferenceBackgroundCustomColor.getKey(), false));
|
||||
}
|
||||
|
||||
// Macro
|
||||
|
||||
Preference preferenceMacroRealSpeed = findPreference("settings_macro_real_speed");
|
||||
Preference preferenceMacroManualSpeed = findPreference("settings_macro_manual_speed");
|
||||
if(preferenceMacroRealSpeed != null && preferenceMacroManualSpeed != null) {
|
||||
Preference.OnPreferenceChangeListener onPreferenceChangeListenerMacroRealSpeed = (preference, value) -> {
|
||||
if(value != null)
|
||||
preferenceMacroManualSpeed.setEnabled(!(Boolean) value);
|
||||
return true;
|
||||
};
|
||||
preferenceMacroRealSpeed.setOnPreferenceChangeListener(onPreferenceChangeListenerMacroRealSpeed);
|
||||
onPreferenceChangeListenerMacroRealSpeed.onPreferenceChange(preferenceMacroRealSpeed, settings.getBoolean(preferenceMacroRealSpeed.getKey(), true));
|
||||
}
|
||||
|
||||
// Ports 1 & 2 settings
|
||||
|
||||
Preference preferencePort1en = findPreference("settings_port1en");
|
||||
Preference preferencePort1wr = findPreference("settings_port1wr");
|
||||
Preference preferencePort2en = findPreference("settings_port2en");
|
||||
Preference preferencePort2wr = findPreference("settings_port2wr");
|
||||
preferencePort2load = findPreference("settings_port2load");
|
||||
if(preferencePort1en != null && preferencePort1wr != null
|
||||
&& preferencePort2en != null && preferencePort2wr != null
|
||||
&& preferencePort2load != null) {
|
||||
boolean enablePortPreferences = NativeLib.isPortExtensionPossible();
|
||||
|
||||
Preference.OnPreferenceChangeListener onPreferenceChangeListenerPort1en = (preference, value) -> {
|
||||
preferencePort1en.setEnabled(enablePortPreferences);
|
||||
preferencePort1wr.setEnabled(enablePortPreferences);
|
||||
return true;
|
||||
};
|
||||
preferencePort1en.setOnPreferenceChangeListener(onPreferenceChangeListenerPort1en);
|
||||
onPreferenceChangeListenerPort1en.onPreferenceChange(preferencePort1en, settings.getBoolean(preferencePort1en.getKey(), false));
|
||||
|
||||
Preference.OnPreferenceChangeListener onPreferenceChangeListenerPort2en = (preference, value) -> {
|
||||
preferencePort2en.setEnabled(enablePortPreferences);
|
||||
preferencePort2wr.setEnabled(enablePortPreferences);
|
||||
preferencePort2load.setEnabled(enablePortPreferences);
|
||||
return true;
|
||||
};
|
||||
preferencePort2en.setOnPreferenceChangeListener(onPreferenceChangeListenerPort2en);
|
||||
onPreferenceChangeListenerPort2en.onPreferenceChange(preferencePort2en, settings.getBoolean(preferencePort2en.getKey(), false));
|
||||
|
||||
updatePort2LoadFilename(settings.getString(preferencePort2load.getKey(), ""));
|
||||
preferencePort2load.setOnPreferenceClickListener(preference -> {
|
||||
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
intent.setType("*/*");
|
||||
intent.putExtra(Intent.EXTRA_TITLE, "shared.bin");
|
||||
Activity activity = getActivity();
|
||||
if (activity != null)
|
||||
activity.startActivityForResult(intent, MainActivity.INTENT_PORT2LOAD);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void updatePort2LoadFilename(String port2Filename) {
|
||||
if(preferencePort2load != null) {
|
||||
String displayName = port2Filename;
|
||||
try {
|
||||
displayName = Utils.getFileName(getActivity(), port2Filename);
|
||||
} catch (Exception e) {
|
||||
// Do nothing
|
||||
}
|
||||
preferencePort2load.setSummary(displayName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||
if(resultCode == Activity.RESULT_OK && data != null) {
|
||||
if(requestCode == MainActivity.INTENT_PORT2LOAD) {
|
||||
Uri uri = data.getData();
|
||||
String url;
|
||||
if (uri != null) {
|
||||
if(debug) Log.d(TAG, "onActivityResult INTENT_PORT2LOAD " + uri.toString());
|
||||
url = uri.toString();
|
||||
settings.putString("settings_port2load", url);
|
||||
makeUriPersistable(data, uri);
|
||||
if(generalPreferenceFragment != null)
|
||||
generalPreferenceFragment.updatePort2LoadFilename(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
private void makeUriPersistable(Intent data, Uri uri) {
|
||||
int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
|
||||
getContentResolver().takePersistableUriPermission(uri, takeFlags);
|
||||
}
|
||||
}
|
343
app/src/main/java/org/emulator/forty/eight/SettingsFragment.java
Normal file
343
app/src/main/java/org/emulator/forty/eight/SettingsFragment.java
Normal file
|
@ -0,0 +1,343 @@
|
|||
// 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 2 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, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
package org.emulator.forty.eight;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.BlendMode;
|
||||
import android.graphics.BlendModeColorFilter;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.InputType;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.widget.EditText;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatDialog;
|
||||
import androidx.appcompat.app.AppCompatDialogFragment;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
import androidx.preference.SeekBarPreference;
|
||||
|
||||
import org.emulator.calculator.EmuApplication;
|
||||
import org.emulator.calculator.NativeLib;
|
||||
import org.emulator.calculator.Settings;
|
||||
import org.emulator.calculator.Utils;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
|
||||
public class SettingsFragment extends AppCompatDialogFragment {
|
||||
|
||||
private static final String TAG = "SettingsFragment";
|
||||
protected final boolean debug = false;
|
||||
|
||||
private static Settings settings;
|
||||
private HashSet<String> settingsKeyChanged = new HashSet<>();
|
||||
private Settings.OnOneKeyChangedListener sharedPreferenceChangeListener = (key) -> settingsKeyChanged.add(key);
|
||||
private GeneralPreferenceFragment generalPreferenceFragment;
|
||||
|
||||
public interface OnSettingsKeyChangedListener {
|
||||
void onSettingsKeyChanged(HashSet<String> settingsKeyChanged);
|
||||
}
|
||||
|
||||
private OnSettingsKeyChangedListener onSettingsKeyChangedListener;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
settings = EmuApplication.getSettings();
|
||||
settings.registerOnOneKeyChangeListener(sharedPreferenceChangeListener);
|
||||
|
||||
setStyle(AppCompatDialogFragment.STYLE_NO_FRAME, R.style.AppTheme);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
Dialog dialog = new AppCompatDialog(getContext(), getTheme()) {
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
dialogResult();
|
||||
dismiss();
|
||||
}
|
||||
};
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
|
||||
String title = getString(settings.getIsDefaultSettings() ? R.string.dialog_common_settings_title : R.string.dialog_state_settings_title);
|
||||
Dialog dialog = getDialog();
|
||||
if(dialog != null)
|
||||
dialog.setTitle(title);
|
||||
|
||||
View view = inflater.inflate(R.layout.fragment_settings, container, false);
|
||||
|
||||
// Configure the toolbar
|
||||
|
||||
Toolbar toolbar = view.findViewById(R.id.my_toolbar);
|
||||
toolbar.setTitle(title);
|
||||
Utils.colorizeDrawableWithColor(requireContext(), toolbar.getNavigationIcon(), android.R.attr.colorForeground);
|
||||
toolbar.setNavigationOnClickListener(v -> {
|
||||
dialogResult();
|
||||
dismiss();
|
||||
});
|
||||
toolbar.inflateMenu(R.menu.fragment_settings);
|
||||
Menu menu = toolbar.getMenu();
|
||||
menu.findItem(R.id.menu_settings_reset_to_default).setEnabled(settings.getIsDefaultSettings());
|
||||
menu.findItem(R.id.menu_settings_reset_to_common).setEnabled(!settings.getIsDefaultSettings());
|
||||
toolbar.setOnMenuItemClickListener(item -> {
|
||||
int id = item.getItemId();
|
||||
if(id == R.id.menu_settings_reset_to_default) {
|
||||
settings.clearCommonDefaultSettings();
|
||||
restartPreferenceFragment();
|
||||
} else if(id == R.id.menu_settings_reset_to_common) {
|
||||
settings.clearEmbeddedStateSettings();
|
||||
restartPreferenceFragment();
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
// Insert the Preference fragment
|
||||
restartPreferenceFragment();
|
||||
return view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start or restart the preference fragment to take into account the new settings.
|
||||
*/
|
||||
private void restartPreferenceFragment() {
|
||||
if(generalPreferenceFragment != null)
|
||||
getChildFragmentManager().beginTransaction().remove(generalPreferenceFragment).commit();
|
||||
generalPreferenceFragment = new GeneralPreferenceFragment();
|
||||
getChildFragmentManager().beginTransaction().replace(R.id.settingsContent, generalPreferenceFragment).commit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Common method to handle the result of the dialog.
|
||||
*/
|
||||
private void dialogResult() {
|
||||
if (onSettingsKeyChangedListener != null)
|
||||
onSettingsKeyChangedListener.onSettingsKeyChanged(settingsKeyChanged);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
settings.unregisterOnOneKeyChangeListener();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
void registerOnSettingsKeyChangedListener(OnSettingsKeyChangedListener listener) {
|
||||
if(debug) Log.d(TAG, "registerOnSettingsKeyChangedListener()");
|
||||
onSettingsKeyChangedListener = listener;
|
||||
}
|
||||
|
||||
void unregisterOnSettingsKeyChangedListener() {
|
||||
if(debug) Log.d(TAG, "unregisterOnSettingsKeyChangedListener()");
|
||||
onSettingsKeyChangedListener = null;
|
||||
}
|
||||
|
||||
public static class GeneralPreferenceFragment extends PreferenceFragmentCompat {
|
||||
|
||||
Preference preferencePort2load = null;
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
|
||||
// Register our own settings data store
|
||||
getPreferenceManager().setPreferenceDataStore(EmuApplication.getSettings());
|
||||
|
||||
// Load the preferences from an XML resource
|
||||
setPreferencesFromResource(R.xml.pref_general, rootKey);
|
||||
|
||||
|
||||
// Sound settings
|
||||
|
||||
SeekBarPreference preferenceSoundVolume = findPreference("settings_sound_volume");
|
||||
if(preferenceSoundVolume != null) {
|
||||
if(!NativeLib.getSoundEnabled()) {
|
||||
preferenceSoundVolume.setSummary("Cannot initialize the sound engine.");
|
||||
preferenceSoundVolume.setEnabled(false);
|
||||
} else {
|
||||
preferenceSoundVolume.setOnPreferenceClickListener(preference -> {
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(requireContext());
|
||||
alert.setTitle(R.string.settings_sound_volume_dialog_title);
|
||||
final EditText input = new EditText(getContext());
|
||||
input.setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||
input.setRawInputType(Configuration.KEYBOARD_12KEY);
|
||||
input.setFocusable(true);
|
||||
input.setText(String.format(Locale.US,"%d", preferenceSoundVolume.getValue()));
|
||||
alert.setView(input);
|
||||
alert.setPositiveButton(R.string.message_ok, (dialog, whichButton) -> {
|
||||
String newValueText = input.getText().toString();
|
||||
try {
|
||||
int newValue = Integer.parseInt(newValueText);
|
||||
if(newValue >= preferenceSoundVolume.getMin() && newValue <= preferenceSoundVolume.getMax())
|
||||
preferenceSoundVolume.setValue(newValue);
|
||||
} catch (NumberFormatException ignored) {}
|
||||
});
|
||||
alert.setNegativeButton(R.string.message_cancel, (dialog, whichButton) -> {});
|
||||
alert.show();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Background color settings
|
||||
|
||||
Preference preferenceBackgroundFallbackColor = findPreference("settings_background_fallback_color");
|
||||
// final ColorPickerPreferenceCompat preferenceBackgroundCustomColor = (ColorPickerPreferenceCompat)findPreference("settings_background_custom_color");
|
||||
if(preferenceBackgroundFallbackColor != null /*&& preferenceBackgroundCustomColor != null*/) {
|
||||
final String[] stringArrayBackgroundFallbackColor = getResources().getStringArray(R.array.settings_background_fallback_color_item);
|
||||
Preference.OnPreferenceChangeListener onPreferenceChangeListenerBackgroundFallbackColor = (preference, value) -> {
|
||||
if(value != null) {
|
||||
String stringValue = value.toString();
|
||||
int backgroundFallbackColor = -1;
|
||||
try {
|
||||
backgroundFallbackColor = Integer.parseInt(stringValue);
|
||||
} catch (NumberFormatException ignored) {}
|
||||
if(backgroundFallbackColor >= 0 && backgroundFallbackColor < stringArrayBackgroundFallbackColor.length)
|
||||
preference.setSummary(stringArrayBackgroundFallbackColor[backgroundFallbackColor]);
|
||||
// preferenceBackgroundCustomColor.setEnabled(backgroundFallbackColor == 2);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
preferenceBackgroundFallbackColor.setOnPreferenceChangeListener(onPreferenceChangeListenerBackgroundFallbackColor);
|
||||
onPreferenceChangeListenerBackgroundFallbackColor.onPreferenceChange(preferenceBackgroundFallbackColor,
|
||||
settings.getString(preferenceBackgroundFallbackColor.getKey(), "0"));
|
||||
|
||||
|
||||
//preferenceBackgroundCustomColor.setColorValue(customColor);
|
||||
|
||||
// Preference.OnPreferenceChangeListener onPreferenceChangeListenerBackgroundCustomColor = new Preference.OnPreferenceChangeListener() {
|
||||
// @Override
|
||||
// public boolean onPreferenceChange(Preference preference, Object value) {
|
||||
// if(value != null) {
|
||||
// int customColor = (Integer)value;
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
// };
|
||||
// preferenceBackgroundCustomColor.setOnPreferenceChangeListener(onPreferenceChangeListenerBackgroundCustomColor);
|
||||
// onPreferenceChangeListenerBackgroundCustomColor.onPreferenceChange(preferenceBackgroundCustomColor, sharedPreferences.getBoolean(preferenceBackgroundCustomColor.getKey(), false));
|
||||
}
|
||||
|
||||
// Macro
|
||||
|
||||
Preference preferenceMacroRealSpeed = findPreference("settings_macro_real_speed");
|
||||
Preference preferenceMacroManualSpeed = findPreference("settings_macro_manual_speed");
|
||||
if(preferenceMacroRealSpeed != null && preferenceMacroManualSpeed != null) {
|
||||
Preference.OnPreferenceChangeListener onPreferenceChangeListenerMacroRealSpeed = (preference, value) -> {
|
||||
if(value != null)
|
||||
preferenceMacroManualSpeed.setEnabled(!(Boolean) value);
|
||||
return true;
|
||||
};
|
||||
preferenceMacroRealSpeed.setOnPreferenceChangeListener(onPreferenceChangeListenerMacroRealSpeed);
|
||||
onPreferenceChangeListenerMacroRealSpeed.onPreferenceChange(preferenceMacroRealSpeed, settings.getBoolean(preferenceMacroRealSpeed.getKey(), true));
|
||||
}
|
||||
|
||||
// Ports 1 & 2 settings
|
||||
|
||||
Preference preferencePort1en = findPreference("settings_port1en");
|
||||
Preference preferencePort1wr = findPreference("settings_port1wr");
|
||||
Preference preferencePort2en = findPreference("settings_port2en");
|
||||
Preference preferencePort2wr = findPreference("settings_port2wr");
|
||||
preferencePort2load = findPreference("settings_port2load");
|
||||
if(preferencePort1en != null && preferencePort1wr != null
|
||||
&& preferencePort2en != null && preferencePort2wr != null
|
||||
&& preferencePort2load != null) {
|
||||
boolean enablePortPreferences = NativeLib.isPortExtensionPossible();
|
||||
|
||||
Preference.OnPreferenceChangeListener onPreferenceChangeListenerPort1en = (preference, value) -> {
|
||||
preferencePort1en.setEnabled(enablePortPreferences);
|
||||
preferencePort1wr.setEnabled(enablePortPreferences);
|
||||
return true;
|
||||
};
|
||||
preferencePort1en.setOnPreferenceChangeListener(onPreferenceChangeListenerPort1en);
|
||||
onPreferenceChangeListenerPort1en.onPreferenceChange(preferencePort1en, settings.getBoolean(preferencePort1en.getKey(), false));
|
||||
|
||||
Preference.OnPreferenceChangeListener onPreferenceChangeListenerPort2en = (preference, value) -> {
|
||||
preferencePort2en.setEnabled(enablePortPreferences);
|
||||
preferencePort2wr.setEnabled(enablePortPreferences);
|
||||
preferencePort2load.setEnabled(enablePortPreferences);
|
||||
return true;
|
||||
};
|
||||
preferencePort2en.setOnPreferenceChangeListener(onPreferenceChangeListenerPort2en);
|
||||
onPreferenceChangeListenerPort2en.onPreferenceChange(preferencePort2en, settings.getBoolean(preferencePort2en.getKey(), false));
|
||||
|
||||
updatePort2LoadFilename(settings.getString(preferencePort2load.getKey(), ""));
|
||||
preferencePort2load.setOnPreferenceClickListener(preference -> {
|
||||
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
intent.setType("*/*");
|
||||
intent.putExtra(Intent.EXTRA_TITLE, "shared.bin");
|
||||
Fragment parentFragment = getParentFragment();
|
||||
if (parentFragment != null)
|
||||
parentFragment.startActivityForResult(intent, MainActivity.INTENT_PORT2LOAD);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void updatePort2LoadFilename(String port2Filename) {
|
||||
if(preferencePort2load != null) {
|
||||
String displayName = port2Filename;
|
||||
try {
|
||||
displayName = Utils.getFileName(getActivity(), port2Filename);
|
||||
} catch (Exception e) {
|
||||
// Do nothing
|
||||
}
|
||||
preferencePort2load.setSummary(displayName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||
if(resultCode == Activity.RESULT_OK && data != null) {
|
||||
if(requestCode == MainActivity.INTENT_PORT2LOAD) {
|
||||
Uri uri = data.getData();
|
||||
String url;
|
||||
if (uri != null) {
|
||||
if(debug) Log.d(TAG, "onActivityResult INTENT_PORT2LOAD " + uri.toString());
|
||||
url = uri.toString();
|
||||
settings.putString("settings_port2load", url);
|
||||
Utils.makeUriPersistable(requireContext(), data, uri);
|
||||
if(generalPreferenceFragment != null)
|
||||
generalPreferenceFragment.updatePort2LoadFilename(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewInfo"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="5dp"
|
||||
android:textIsSelectable="true" />
|
||||
|
||||
</ScrollView>
|
|
@ -1,17 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" >
|
||||
|
||||
<WebView
|
||||
android:id="@+id/webViewInfo"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -5,17 +5,6 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?attr/colorPrimary" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<include layout="@layout/content_main" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
32
app/src/main/res/layout/fragment_info.xml
Normal file
32
app/src/main/res/layout/fragment_info.xml
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/frameLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/my_toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?attr/actionBarSize"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:navigationIcon="?android:attr/homeAsUpIndicator" />
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/my_toolbar" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewInfo"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="5dp"
|
||||
android:textIsSelectable="true" />
|
||||
|
||||
</ScrollView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
25
app/src/main/res/layout/fragment_settings.xml
Normal file
25
app/src/main/res/layout/fragment_settings.xml
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/frameLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/my_toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?attr/actionBarSize"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:navigationIcon="?android:attr/homeAsUpIndicator" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/settingsContent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/my_toolbar" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
24
app/src/main/res/layout/fragment_web_info.xml
Normal file
24
app/src/main/res/layout/fragment_web_info.xml
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/frameLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/my_toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?attr/actionBarSize"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:navigationIcon="?android:attr/homeAsUpIndicator" />
|
||||
|
||||
<WebView
|
||||
android:id="@+id/webViewInfo"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/my_toolbar" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
10
app/src/main/res/menu/fragment_settings.xml
Normal file
10
app/src/main/res/menu/fragment_settings.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/menu_settings_reset_to_default"
|
||||
android:title="@string/menu_settings_reset_to_default" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_settings_reset_to_common"
|
||||
android:title="@string/menu_settings_reset_to_common" />
|
||||
</menu>
|
|
@ -1,17 +1,21 @@
|
|||
<resources>
|
||||
|
||||
<!-- InfoActivity -->
|
||||
<!-- InfoFragment -->
|
||||
|
||||
<string name="title_activity_info">About</string>
|
||||
<string name="title_fragment_info">About</string>
|
||||
<string name="info_readme">ReadMe.txt</string>
|
||||
|
||||
<!-- InfoWebActivity -->
|
||||
<string name="title_web_activity_info">Help</string>
|
||||
<!-- InfoWebFragment -->
|
||||
<string name="title_web_fragment_info">Help</string>
|
||||
<string name="help_url">file:///android_asset/Emu48.htm</string>
|
||||
|
||||
<!-- SettingsActivity -->
|
||||
<!-- SettingsFragment -->
|
||||
|
||||
<string name="title_activity_settings">Settings</string>
|
||||
<string name="dialog_common_settings_title">Common Settings</string>
|
||||
<string name="dialog_state_settings_title">Settings (Saved in state file)</string>
|
||||
|
||||
<string name="menu_settings_reset_to_default">Reset to Default</string>
|
||||
<string name="menu_settings_reset_to_common">Reset to Common</string>
|
||||
|
||||
<!-- MainActivity -->
|
||||
|
||||
|
@ -129,7 +133,7 @@
|
|||
<string name="settings_lcd_overlapping_mode_item_2">Manual (Zoom or pan)</string>
|
||||
|
||||
<string name="settings_lcd_pixel_borders_title">Show the LCD pixel borders</string>
|
||||
<string name="settings_lcd_pixel_borders_summary">Experimental feature which show a more realistic pixel. Note: Due to the difference in screen resolution between Android and the calculator, the pixels are not necessarily uniform in size.</string>
|
||||
<string name="settings_lcd_pixel_borders_summary">Experimental feature which shows a more realistic pixel. Note: Due to the difference in screen resolution between Android and the calculator, the pixels are not necessarily uniform in size.</string>
|
||||
|
||||
<string name="settings_hide_bar_status">Hide the status bar</string>
|
||||
<string name="settings_hide_bar_nav">Hide the navigation bar</string>
|
||||
|
@ -162,8 +166,6 @@
|
|||
<string name="settings_printer_model_item_0">HP82240A</string>
|
||||
<string name="settings_printer_model_item_1">HP82240B (default)</string>
|
||||
<string name="settings_printer_model_item_2">Generic Serial</string>
|
||||
<string name="settings_printer_prevent_line_wrap">Prevent Line Wrapping</string>
|
||||
<string name="settings_printer_prevent_line_wrap_summary">Prevent the calc to wrap the line in the textual printer simulator</string>
|
||||
|
||||
<string name="settings_category_macro_title">Macro</string>
|
||||
<string name="settings_macro_real_speed_title">Use Real Replay Speed</string>
|
||||
|
|
|
@ -121,12 +121,6 @@
|
|||
android:entryValues="@array/settings_printer_model_value"
|
||||
android:defaultValue="1"
|
||||
/>
|
||||
<!--<SwitchPreference-->
|
||||
<!--android:defaultValue="false"-->
|
||||
<!--android:key="settings_printer_prevent_line_wrap"-->
|
||||
<!--android:summary="@string/settings_printer_prevent_line_wrap_summary"-->
|
||||
<!--android:title="@string/settings_printer_prevent_line_wrap"-->
|
||||
<!--/>-->
|
||||
</PreferenceCategory>
|
||||
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ buildscript {
|
|||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.6.2'
|
||||
classpath 'com.android.tools.build:gradle:3.6.3'
|
||||
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
|
Loading…
Reference in a new issue