diff --git a/android-app-core/res/values-ru/text_strings.xml b/android-app-core/res/values-ru/text_strings.xml index bfe4ba48..4564c6f1 100644 --- a/android-app-core/res/values-ru/text_strings.xml +++ b/android-app-core/res/values-ru/text_strings.xml @@ -276,4 +276,7 @@ Запуск после загрузки устройства Если включено, то кнопка Калькулятора++ будет доступна в панели уведомлений после загрузки устройства + Показывать отдельную иконку (может потребовать перезагрузки) + Если включено, то вторая иконка будет добавлена в список приложений + \ No newline at end of file diff --git a/android-app-core/res/values/text_strings.xml b/android-app-core/res/values/text_strings.xml index 60b8bfc9..7ab7b1bb 100644 --- a/android-app-core/res/values/text_strings.xml +++ b/android-app-core/res/values/text_strings.xml @@ -272,8 +272,11 @@ Calculator++ Widget (4x5) Click to open calculator in window mode - Calculator (window mode) settings + Calculator (in separate window) settings Start on boot If turned on Calculator++ will appear in notification bar after device boot + Show separate icon (require reboot) + If turned on second icon will be shown in applications\' list + \ No newline at end of file diff --git a/android-app-core/src/main/java/org/solovyev/android/calculator/CalculatorPreferences.java b/android-app-core/src/main/java/org/solovyev/android/calculator/CalculatorPreferences.java index 806201a3..4bf5f8d8 100644 --- a/android-app-core/src/main/java/org/solovyev/android/calculator/CalculatorPreferences.java +++ b/android-app-core/src/main/java/org/solovyev/android/calculator/CalculatorPreferences.java @@ -30,6 +30,7 @@ public final class CalculatorPreferences { public static class OnscreenCalculator { public static final Preference startOnBoot = new BooleanPreference("onscreen_start_on_boot", false); + public static final Preference showAppIcon = new BooleanPreference("onscreen_show_app_icon", true); } public static class Calculations { @@ -188,6 +189,9 @@ public final class CalculatorPreferences { applyDefaultPreference(preferences, Calculations.preferredAngleUnits); applyDefaultPreference(preferences, Calculations.preferredNumeralBase); + applyDefaultPreference(preferences, OnscreenCalculator.showAppIcon); + applyDefaultPreference(preferences, OnscreenCalculator.startOnBoot); + // renew value after each application start Calculations.showCalculationMessagesDialog.putDefault(preferences); diff --git a/android-app-onscreen/src/main/java/org/solovyev/android/calculator/onscreen/CalculatorOnscreenService.java b/android-app-onscreen/src/main/java/org/solovyev/android/calculator/onscreen/CalculatorOnscreenService.java index 315793b2..4afc605f 100644 --- a/android-app-onscreen/src/main/java/org/solovyev/android/calculator/onscreen/CalculatorOnscreenService.java +++ b/android-app-onscreen/src/main/java/org/solovyev/android/calculator/onscreen/CalculatorOnscreenService.java @@ -69,7 +69,7 @@ public class CalculatorOnscreenService extends Service implements ExternalCalcul final int width = Math.min(width0, height0); final int height = Math.max(width0, height0); - view = CalculatorOnscreenView.newInstance(this, CalculatorOnscreenViewDef.newInstance(width, height, -1, -1), getCursorColor(this), this); + view = CalculatorOnscreenView.newInstance(this, CalculatorOnscreenViewState.newInstance(width, height, -1, -1), getCursorColor(this), this); view.show(); startCalculatorListening(); diff --git a/android-app-onscreen/src/main/java/org/solovyev/android/calculator/onscreen/CalculatorOnscreenView.java b/android-app-onscreen/src/main/java/org/solovyev/android/calculator/onscreen/CalculatorOnscreenView.java index c7bcd933..713f646e 100644 --- a/android-app-onscreen/src/main/java/org/solovyev/android/calculator/onscreen/CalculatorOnscreenView.java +++ b/android-app-onscreen/src/main/java/org/solovyev/android/calculator/onscreen/CalculatorOnscreenView.java @@ -1,7 +1,9 @@ package org.solovyev.android.calculator.onscreen; import android.content.Context; +import android.content.SharedPreferences; import android.graphics.PixelFormat; +import android.preference.PreferenceManager; import android.util.DisplayMetrics; import android.util.Log; import android.view.Gravity; @@ -12,6 +14,7 @@ import android.widget.ImageView; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.solovyev.android.calculator.*; +import org.solovyev.android.prefs.Preference; /** * User: serso @@ -29,6 +32,16 @@ public class CalculatorOnscreenView { private static final String TAG = CalculatorOnscreenView.class.getSimpleName(); + /* + ********************************************************************** + * + * STATIC + * + ********************************************************************** + */ + + private static final Preference viewStatePreference = new CalculatorOnscreenViewState.Preference("calculator_onscreen_view_state", CalculatorOnscreenViewState.newDefaultState()); + /* ********************************************************************** * @@ -55,11 +68,8 @@ public class CalculatorOnscreenView { @NotNull private Context context; - private int width; - - private int height; - - private int unfoldedHeight; + @NotNull + private CalculatorOnscreenViewState state = CalculatorOnscreenViewState.newDefaultState(); @NotNull private String cursorColor; @@ -98,18 +108,23 @@ public class CalculatorOnscreenView { } public static CalculatorOnscreenView newInstance(@NotNull Context context, - @NotNull CalculatorOnscreenViewDef def, + @NotNull CalculatorOnscreenViewState state, @NotNull String cursorColor, @Nullable OnscreenViewListener viewListener) { final CalculatorOnscreenView result = new CalculatorOnscreenView(); result.root = View.inflate(context, R.layout.onscreen_layout, null); result.context = context; - result.width = def.getWidth(); - result.height = def.getHeight(); result.cursorColor = cursorColor; result.viewListener = viewListener; + final CalculatorOnscreenViewState persistedState = readState(context); + if (persistedState != null) { + result.state = persistedState; + } else { + result.state = state; + } + return result; } @@ -134,8 +149,6 @@ public class CalculatorOnscreenView { private void setHeight(int height) { checkInit(); - this.height = height; - final WindowManager.LayoutParams params = (WindowManager.LayoutParams) root.getLayoutParams(); params.height = height; @@ -243,8 +256,10 @@ public class CalculatorOnscreenView { final WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); if (!attached) { final WindowManager.LayoutParams params = new WindowManager.LayoutParams( - width, - height, + state.getWidth(), + state.getHeight(), + state.getX(), + state.getY(), WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, PixelFormat.TRANSLUCENT); @@ -258,8 +273,6 @@ public class CalculatorOnscreenView { private void fold() { if (!folded) { - final WindowManager.LayoutParams params = (WindowManager.LayoutParams) root.getLayoutParams(); - unfoldedHeight = params.height; int newHeight = header.getHeight(); content.setVisibility(View.GONE); setHeight(newHeight); @@ -270,7 +283,7 @@ public class CalculatorOnscreenView { private void unfold() { if (folded) { content.setVisibility(View.VISIBLE); - setHeight(unfoldedHeight); + setHeight(state.getHeight()); folded = false; } } @@ -287,6 +300,8 @@ public class CalculatorOnscreenView { public void minimize() { checkInit(); if (!minimized) { + persistState(context, getCurrentState(!folded)); + detach(); if (viewListener != null) { @@ -297,11 +312,28 @@ public class CalculatorOnscreenView { } } + public static void persistState(@NotNull Context context, @NotNull CalculatorOnscreenViewState state) { + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + viewStatePreference.putPreference(preferences, state); + } + + @Nullable + public static CalculatorOnscreenViewState readState(@NotNull Context context) { + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + if (viewStatePreference.isSet(preferences)) { + return viewStatePreference.getPreference(preferences); + } else { + return null; + } + } + public void hide() { checkInit(); if (!hidden) { + persistState(context, getCurrentState(!folded)); + detach(); if (viewListener != null) { @@ -318,9 +350,13 @@ public class CalculatorOnscreenView { } @NotNull - public CalculatorOnscreenViewDef getCalculatorOnscreenViewDef() { + public CalculatorOnscreenViewState getCurrentState(boolean useRealSize) { final WindowManager.LayoutParams params = (WindowManager.LayoutParams) root.getLayoutParams(); - return CalculatorOnscreenViewDef.newInstance(width, height, params.x, params.y); + if (useRealSize) { + return CalculatorOnscreenViewState.newInstance(params.width, params.height, params.x, params.y); + } else { + return CalculatorOnscreenViewState.newInstance(state.getWidth(), state.getHeight(), params.x, params.y); + } } /* diff --git a/android-app-onscreen/src/main/java/org/solovyev/android/calculator/onscreen/CalculatorOnscreenViewDef.java b/android-app-onscreen/src/main/java/org/solovyev/android/calculator/onscreen/CalculatorOnscreenViewDef.java deleted file mode 100644 index accffb33..00000000 --- a/android-app-onscreen/src/main/java/org/solovyev/android/calculator/onscreen/CalculatorOnscreenViewDef.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.solovyev.android.calculator.onscreen; - -import org.jetbrains.annotations.NotNull; - -/** - * User: serso - * Date: 11/21/12 - * Time: 10:55 PM - */ -public class CalculatorOnscreenViewDef { - - private int width; - private int height; - private int x; - private int y; - - private CalculatorOnscreenViewDef() { - } - - @NotNull - public static CalculatorOnscreenViewDef newInstance(int width, int height, int x, int y) { - final CalculatorOnscreenViewDef result = new CalculatorOnscreenViewDef(); - result.width = width; - result.height = height; - result.x = x; - result.y = y; - return result; - } - - public int getWidth() { - return width; - } - - public void setWidth(int width) { - this.width = width; - } - - public int getHeight() { - return height; - } - - public void setHeight(int height) { - this.height = height; - } - - public int getX() { - return x; - } - - public void setX(int x) { - this.x = x; - } - - public int getY() { - return y; - } - - public void setY(int y) { - this.y = y; - } -} diff --git a/android-app-onscreen/src/main/java/org/solovyev/android/calculator/onscreen/CalculatorOnscreenViewState.java b/android-app-onscreen/src/main/java/org/solovyev/android/calculator/onscreen/CalculatorOnscreenViewState.java new file mode 100644 index 00000000..43d3aebd --- /dev/null +++ b/android-app-onscreen/src/main/java/org/solovyev/android/calculator/onscreen/CalculatorOnscreenViewState.java @@ -0,0 +1,166 @@ +package org.solovyev.android.calculator.onscreen; + +import android.content.SharedPreferences; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.json.JSONException; +import org.json.JSONObject; +import org.solovyev.android.prefs.AbstractPreference; + +import java.util.HashMap; +import java.util.Map; + +/** + * User: serso + * Date: 11/21/12 + * Time: 10:55 PM + */ +public class CalculatorOnscreenViewState implements Parcelable { + + private static final String TAG = CalculatorOnscreenViewState.class.getSimpleName(); + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public CalculatorOnscreenViewState createFromParcel(@NotNull Parcel in) { + return CalculatorOnscreenViewState.fromParcel(in); + } + + public CalculatorOnscreenViewState[] newArray(int size) { + return new CalculatorOnscreenViewState[size]; + } + }; + + private int width; + + private int height; + + private int x; + + private int y; + + private CalculatorOnscreenViewState() { + } + + @NotNull + private static CalculatorOnscreenViewState fromParcel(@NotNull Parcel in) { + final CalculatorOnscreenViewState result = new CalculatorOnscreenViewState(); + result.width = in.readInt(); + result.height = in.readInt(); + result.x = in.readInt(); + result.y = in.readInt(); + return result; + } + + @NotNull + public static CalculatorOnscreenViewState newDefaultState() { + return newInstance(200, 400, 0, 0); + } + + @NotNull + public static CalculatorOnscreenViewState newInstance(int width, int height, int x, int y) { + final CalculatorOnscreenViewState result = new CalculatorOnscreenViewState(); + result.width = width; + result.height = height; + result.x = x; + result.y = y; + return result; + } + + public int getWidth() { + return width; + } + + public void setWidth(int width) { + this.width = width; + } + + public int getHeight() { + return height; + } + + public void setHeight(int height) { + this.height = height; + } + + public int getX() { + return x; + } + + public void setX(int x) { + this.x = x; + } + + public int getY() { + return y; + } + + public void setY(int y) { + this.y = y; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NotNull Parcel out, int flags) { + out.writeInt(width); + out.writeInt(height); + out.writeInt(x); + out.writeInt(y); + } + + @Override + public String toString() { + return "CalculatorOnscreenViewState{" + + "y=" + y + + ", x=" + x + + ", height=" + height + + ", width=" + width + + '}'; + } + + public static class Preference extends AbstractPreference { + + public Preference(@NotNull String key, @Nullable CalculatorOnscreenViewState defaultValue) { + super(key, defaultValue); + } + + @Nullable + @Override + protected CalculatorOnscreenViewState getPersistedValue(@NotNull SharedPreferences preferences) { + try { + final CalculatorOnscreenViewState result = new CalculatorOnscreenViewState(); + final JSONObject jsonObject = new JSONObject(preferences.getString(getKey(), "{}")); + result.width = jsonObject.getInt("width"); + result.height = jsonObject.getInt("height"); + result.x = jsonObject.getInt("x"); + result.y = jsonObject.getInt("y"); + + Log.d(TAG, "Reading onscreen view state: " + result); + + return result; + } catch (JSONException e) { + return getDefaultValue(); + } + } + + @Override + protected void putPersistedValue(@NotNull SharedPreferences.Editor editor, @NotNull CalculatorOnscreenViewState value) { + final Map properties = new HashMap(); + properties.put("width", value.getWidth()); + properties.put("height", value.getHeight()); + properties.put("x", value.getX()); + properties.put("y", value.getY()); + + final JSONObject jsonObject = new JSONObject(properties); + + final String json = jsonObject.toString(); + Log.d(TAG, "Persisting onscreen view state: " + json); + editor.putString(getKey(), json); + } + } +} diff --git a/android-app/res/xml/preferences_onscreen.xml b/android-app/res/xml/preferences_onscreen.xml index 475e84cf..0bb38360 100644 --- a/android-app/res/xml/preferences_onscreen.xml +++ b/android-app/res/xml/preferences_onscreen.xml @@ -11,6 +11,11 @@ a:title="@string/prefs_onscreen_start_on_boot_title" a:summary="@string/prefs_onscreen_start_on_boot_summary"/> + + \ No newline at end of file diff --git a/android-app/src/main/java/org/solovyev/android/AndroidUtils2.java b/android-app/src/main/java/org/solovyev/android/AndroidUtils2.java index 2f507bd4..ab0a2727 100644 --- a/android-app/src/main/java/org/solovyev/android/AndroidUtils2.java +++ b/android-app/src/main/java/org/solovyev/android/AndroidUtils2.java @@ -1,8 +1,10 @@ package org.solovyev.android; import android.app.Activity; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; import org.jetbrains.annotations.NotNull; /** @@ -30,4 +32,19 @@ public final class AndroidUtils2 { intent.setFlags(flags); } + + public static void toggleComponent(@NotNull Context context, + @NotNull Class componentClass, + boolean enable) { + final PackageManager pm = context.getPackageManager(); + + final int componentState; + if (enable) { + componentState = PackageManager.COMPONENT_ENABLED_STATE_ENABLED; + } else { + componentState = PackageManager.COMPONENT_ENABLED_STATE_DISABLED; + } + + pm.setComponentEnabledSetting(new ComponentName(context, componentClass), componentState, PackageManager.DONT_KILL_APP); + } } diff --git a/android-app/src/main/java/org/solovyev/android/calculator/CalculatorApplication.java b/android-app/src/main/java/org/solovyev/android/calculator/CalculatorApplication.java index 09996999..0151aba0 100644 --- a/android-app/src/main/java/org/solovyev/android/calculator/CalculatorApplication.java +++ b/android-app/src/main/java/org/solovyev/android/calculator/CalculatorApplication.java @@ -12,10 +12,12 @@ import org.acra.ACRA; import org.acra.ReportingInteractionMode; import org.acra.annotation.ReportsCrashes; import org.jetbrains.annotations.NotNull; +import org.solovyev.android.AndroidUtils2; import org.solovyev.android.ads.AdsController; import org.solovyev.android.calculator.external.AndroidExternalListenersContainer; import org.solovyev.android.calculator.history.AndroidCalculatorHistory; import org.solovyev.android.calculator.model.AndroidCalculatorEngine; +import org.solovyev.android.calculator.onscreen.CalculatorOnscreenStartActivity; import java.util.ArrayList; import java.util.List; @@ -33,7 +35,7 @@ import java.util.List; resToastText = R.string.crashed, resDialogTitle = R.string.crash_dialog_title, resDialogText = R.string.crash_dialog_text) -public class CalculatorApplication extends android.app.Application { +public class CalculatorApplication extends android.app.Application implements SharedPreferences.OnSharedPreferenceChangeListener { /* ********************************************************************** @@ -94,6 +96,8 @@ public class CalculatorApplication extends android.app.Application { final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); CalculatorPreferences.setDefaultValues(preferences); + preferences.registerOnSharedPreferenceChangeListener(this); + setTheme(preferences); super.onCreate(); @@ -198,4 +202,12 @@ public class CalculatorApplication extends android.app.Application { // NOTE: this code is only for monkeyrunner return context.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) == PackageManager.PERMISSION_GRANTED; } + + @Override + public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { + if (CalculatorPreferences.OnscreenCalculator.showAppIcon.getKey().equals(key)) { + boolean showAppIcon = CalculatorPreferences.OnscreenCalculator.showAppIcon.getPreference(prefs); + AndroidUtils2.toggleComponent(this, CalculatorOnscreenStartActivity.class, showAppIcon); + } + } }