diff --git a/app/misc/libs/drag-button-1.1.aar b/app/misc/libs/drag-button-1.1.aar index 7f27c42e..64d1d5cd 100644 Binary files a/app/misc/libs/drag-button-1.1.aar and b/app/misc/libs/drag-button-1.1.aar differ diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fdc6a626..c8360100 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -7,6 +7,7 @@ + @@ -48,7 +49,7 @@ diff --git a/app/src/main/java/org/solovyev/android/calculator/AppComponent.java b/app/src/main/java/org/solovyev/android/calculator/AppComponent.java index 4d27605c..10f0e3c0 100644 --- a/app/src/main/java/org/solovyev/android/calculator/AppComponent.java +++ b/app/src/main/java/org/solovyev/android/calculator/AppComponent.java @@ -39,7 +39,7 @@ public interface AppComponent { void inject(ConverterFragment fragment); void inject(CalculatorActivity activity); void inject(FixableErrorsActivity activity); - void inject(CalculatorReceiver receiver); + void inject(WidgetReceiver receiver); void inject(DisplayFragment fragment); void inject(KeyboardFragment fragment); void inject(PurchaseDialogActivity activity); diff --git a/app/src/main/java/org/solovyev/android/calculator/CalculatorApplication.java b/app/src/main/java/org/solovyev/android/calculator/CalculatorApplication.java index 607d3de9..aecc589a 100644 --- a/app/src/main/java/org/solovyev/android/calculator/CalculatorApplication.java +++ b/app/src/main/java/org/solovyev/android/calculator/CalculatorApplication.java @@ -182,7 +182,7 @@ public class CalculatorApplication extends android.app.Application implements Sh } // then we should set default preferences - Preferences.setDefaultValues(preferences); + Preferences.setDefaultValues(this, preferences); // and change application's theme/language is needed final Preferences.Gui.Theme theme = Preferences.Gui.getTheme(preferences); diff --git a/app/src/main/java/org/solovyev/android/calculator/FloatingCalculatorKeyboard.java b/app/src/main/java/org/solovyev/android/calculator/FloatingCalculatorKeyboard.java index a247b890..80b8be1a 100644 --- a/app/src/main/java/org/solovyev/android/calculator/FloatingCalculatorKeyboard.java +++ b/app/src/main/java/org/solovyev/android/calculator/FloatingCalculatorKeyboard.java @@ -4,7 +4,6 @@ import android.graphics.PointF; import android.support.annotation.IdRes; import android.support.annotation.NonNull; import android.text.TextUtils; -import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import android.view.View; import android.widget.Button; @@ -19,6 +18,7 @@ import org.solovyev.android.views.dragbutton.SimpleDragListener; import java.util.List; +import static android.view.HapticFeedbackConstants.*; import static org.solovyev.android.views.dragbutton.DirectionDragButton.Direction.down; import static org.solovyev.android.views.dragbutton.DirectionDragButton.Direction.up; @@ -89,7 +89,7 @@ public class FloatingCalculatorKeyboard extends BaseFloatingKeyboard { addOperationButton(row, R.id.cpp_kb_button_divide, "/").setText("%", up).setText("sqrt", down); addOperationButton(row, R.id.cpp_kb_button_minus, "−"); final View backspace = addImageButton(row, R.id.cpp_kb_button_backspace, R.drawable.ic_backspace_grey300_24dp); - EditTextLongClickEraser.attachTo(backspace, user.getEditor()); + EditTextLongClickEraser.attachTo(backspace, user.getEditor(), user.isVibrateOnKeypress()); row = makeRow(); addButton(row, R.id.cpp_kb_button_functions_constants, "f/π"); @@ -116,7 +116,7 @@ public class FloatingCalculatorKeyboard extends BaseFloatingKeyboard { addButton(row, 0, "6"); addOperationButton(row, R.id.cpp_kb_button_divide, "/").setText("%", up).setText("sqrt", down); final View backspace = addImageButton(row, R.id.cpp_kb_button_backspace, R.drawable.ic_backspace_grey300_24dp); - EditTextLongClickEraser.attachTo(backspace, user.getEditor()); + EditTextLongClickEraser.attachTo(backspace, user.getEditor(), user.isVibrateOnKeypress()); row = makeRow(); addButton(row, 0, "1"); @@ -172,7 +172,9 @@ public class FloatingCalculatorKeyboard extends BaseFloatingKeyboard { @Override public void onClick(@NonNull View v) { - v.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); + if (user.isVibrateOnKeypress()) { + v.performHapticFeedback(KEYBOARD_TAP, FLAG_IGNORE_GLOBAL_SETTING | FLAG_IGNORE_VIEW_SETTING); + } switch (v.getId()) { case R.id.cpp_kb_button_divide: user.insertOperator('/'); @@ -260,7 +262,6 @@ public class FloatingCalculatorKeyboard extends BaseFloatingKeyboard { user.insertText(text, 0); break; } - button.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); return true; } } diff --git a/app/src/main/java/org/solovyev/android/calculator/Keyboard.java b/app/src/main/java/org/solovyev/android/calculator/Keyboard.java index eca096f7..9324b68f 100644 --- a/app/src/main/java/org/solovyev/android/calculator/Keyboard.java +++ b/app/src/main/java/org/solovyev/android/calculator/Keyboard.java @@ -22,11 +22,11 @@ package org.solovyev.android.calculator; +import android.content.SharedPreferences; import android.support.annotation.NonNull; import android.text.TextUtils; - import com.squareup.otto.Bus; - +import dagger.Lazy; import org.solovyev.android.Check; import org.solovyev.android.calculator.buttons.CppSpecialButton; import org.solovyev.android.calculator.math.MathType; @@ -36,10 +36,8 @@ import javax.annotation.Nullable; import javax.inject.Inject; import javax.inject.Singleton; -import dagger.Lazy; - @Singleton -public class Keyboard { +public class Keyboard implements SharedPreferences.OnSharedPreferenceChangeListener { @Nonnull private final MathType.Result mathType = new MathType.Result(); @@ -56,9 +54,16 @@ public class Keyboard { Lazy bus; @Inject ActivityLauncher launcher; + private boolean vibrateOnKeypress; @Inject - public Keyboard() { + public Keyboard(@Nonnull SharedPreferences preferences) { + preferences.registerOnSharedPreferenceChangeListener(this); + vibrateOnKeypress = Preferences.Gui.vibrateOnKeypress.getPreference(preferences); + } + + public boolean isVibrateOnKeypress() { + return vibrateOnKeypress; } public boolean buttonPressed(@Nullable final String text) { @@ -215,4 +220,11 @@ public class Keyboard { public void moveCursorRight() { editor.moveCursorRight(); } + + @Override + public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { + if (Preferences.Gui.vibrateOnKeypress.isSameKey(key)) { + vibrateOnKeypress = Preferences.Gui.vibrateOnKeypress.getPreference(preferences); + } + } } diff --git a/app/src/main/java/org/solovyev/android/calculator/Preferences.java b/app/src/main/java/org/solovyev/android/calculator/Preferences.java index a834db2e..212fd527 100644 --- a/app/src/main/java/org/solovyev/android/calculator/Preferences.java +++ b/app/src/main/java/org/solovyev/android/calculator/Preferences.java @@ -22,10 +22,13 @@ package org.solovyev.android.calculator; +import android.app.Application; +import android.content.ContentResolver; import android.content.Context; import android.content.SharedPreferences; import android.content.res.TypedArray; import android.graphics.Color; +import android.provider.Settings; import android.support.annotation.ColorRes; import android.support.annotation.LayoutRes; import android.support.annotation.StyleRes; @@ -50,29 +53,35 @@ import java.util.Map; import static org.solovyev.android.Android.isPhoneModel; import static org.solovyev.android.DeviceModel.samsung_galaxy_s; import static org.solovyev.android.DeviceModel.samsung_galaxy_s_2; +import static org.solovyev.android.prefs.IntegerPreference.DEF_VALUE; public final class Preferences { - public static final Preference appVersion = IntegerPreference.of("application.version", -1); + public static final Preference appVersion = IntegerPreference.of("application.version", DEF_VALUE); public static final Preference appOpenedCounter = IntegerPreference.of("app_opened_counter", 0); private Preferences() { throw new AssertionError(); } - static void setDefaultValues(@Nonnull SharedPreferences preferences) { + static void setDefaultValues(@Nonnull Application application, @Nonnull SharedPreferences preferences) { SharedPreferences.Editor editor = preferences.edit(); // renew value after each application start Gui.showFixableErrorDialog.putDefault(editor); Gui.lastPreferredPreferencesCheck.putDefault(editor); - final Integer version = Preferences.appVersion.getPreference(preferences); - if (version == null) { - setInitialDefaultValues(preferences, editor); + final int version = Preferences.appVersion.getPreference(preferences); + if (version == DEF_VALUE) { + setInitialDefaultValues(application, preferences, editor); + } else if (version > 143) { + if (!Gui.vibrateOnKeypress.isSet(preferences)) { + //noinspection deprecation + Gui.vibrateOnKeypress.putPreference(editor, Gui.hapticFeedback.getPreference(preferences) > 0); + } } editor.apply(); } - private static void setInitialDefaultValues(@Nonnull SharedPreferences preferences, @Nonnull SharedPreferences.Editor editor) { + private static void setInitialDefaultValues(@Nonnull Application application, @Nonnull SharedPreferences preferences, @Nonnull SharedPreferences.Editor editor) { if (!Engine.Preferences.groupingSeparator.isSet(preferences)) { final Locale locale = Locale.getDefault(); if (locale != null) { @@ -101,6 +110,7 @@ public final class Preferences { Gui.theme.tryPutDefault(preferences, editor); Gui.layout.tryPutDefault(preferences, editor); + //noinspection deprecation if (Gui.layout.getPreference(preferences) == Gui.Layout.main_cellphone) { Gui.layout.putDefault(editor); } @@ -123,6 +133,12 @@ public final class Preferences { Onscreen.theme.tryPutDefault(preferences, editor); Widget.theme.tryPutDefault(preferences, editor); + + final ContentResolver cr = application.getContentResolver(); + if (cr != null) { + final boolean vibrateOnKeyPress = Settings.System.getInt(cr, Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) != 0; + Gui.vibrateOnKeypress.putPreference(editor, vibrateOnKeyPress); + } } public enum SimpleTheme { @@ -254,9 +270,11 @@ public final class Preferences { public static final Preference hideNumeralBaseDigits = BooleanPreference.of("hideNumeralBaseDigits", true); public static final Preference preventScreenFromFading = BooleanPreference.of("preventScreenFromFading", true); public static final Preference colorDisplay = BooleanPreference.of("org.solovyev.android.calculator.CalculatorModel_color_display", true); - public static final Preference hapticFeedback = NumberToStringPreference.of("hapticFeedback", 60L, Long.class); + public static final Preference vibrateOnKeypress = BooleanPreference.of("gui.vibrateOnKeypress", true); public static final Preference showFixableErrorDialog = BooleanPreference.of("gui.showFixableErrorDialog", true); public static final Preference lastPreferredPreferencesCheck = LongPreference.of("gui.lastPreferredPreferencesCheck", 0L); + @Deprecated + public static final Preference hapticFeedback = NumberToStringPreference.of("hapticFeedback", 60L, Long.class); @Nonnull public static Theme getTheme(@Nonnull SharedPreferences preferences) { diff --git a/app/src/main/java/org/solovyev/android/calculator/CalculatorReceiver.java b/app/src/main/java/org/solovyev/android/calculator/WidgetReceiver.java similarity index 71% rename from app/src/main/java/org/solovyev/android/calculator/CalculatorReceiver.java rename to app/src/main/java/org/solovyev/android/calculator/WidgetReceiver.java index 1f670384..46c275c6 100644 --- a/app/src/main/java/org/solovyev/android/calculator/CalculatorReceiver.java +++ b/app/src/main/java/org/solovyev/android/calculator/WidgetReceiver.java @@ -3,8 +3,8 @@ package org.solovyev.android.calculator; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.os.Vibrator; import android.text.TextUtils; - import org.solovyev.android.calculator.buttons.CppButton; import javax.annotation.Nonnull; @@ -12,7 +12,7 @@ import javax.inject.Inject; import static org.solovyev.android.calculator.App.cast; -public final class CalculatorReceiver extends BroadcastReceiver { +public final class WidgetReceiver extends BroadcastReceiver { public static final String ACTION_BUTTON_ID_EXTRA = "buttonId"; public static final String ACTION_BUTTON_PRESSED = "org.solovyev.android.calculator.BUTTON_PRESSED"; @@ -22,7 +22,7 @@ public final class CalculatorReceiver extends BroadcastReceiver { @Nonnull public static Intent newButtonClickedIntent(@Nonnull Context context, @Nonnull CppButton button) { - final Intent intent = new Intent(context, CalculatorReceiver.class); + final Intent intent = new Intent(context, WidgetReceiver.class); intent.setAction(ACTION_BUTTON_PRESSED); intent.putExtra(ACTION_BUTTON_ID_EXTRA, button.id); return intent; @@ -43,6 +43,16 @@ public final class CalculatorReceiver extends BroadcastReceiver { return; } - keyboard.buttonPressed(button.action); + if (!keyboard.buttonPressed(button.action)) { + return; + } + if (!keyboard.isVibrateOnKeypress()) { + return; + } + final Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); + if (vibrator == null) { + return; + } + vibrator.vibrate(10); } } diff --git a/app/src/main/java/org/solovyev/android/calculator/functions/EditFunctionFragment.java b/app/src/main/java/org/solovyev/android/calculator/functions/EditFunctionFragment.java index 5029ce29..ee0602b5 100644 --- a/app/src/main/java/org/solovyev/android/calculator/functions/EditFunctionFragment.java +++ b/app/src/main/java/org/solovyev/android/calculator/functions/EditFunctionFragment.java @@ -22,8 +22,6 @@ package org.solovyev.android.calculator.functions; -import static org.solovyev.android.calculator.functions.CppFunction.NO_ID; - import android.annotation.SuppressLint; import android.content.Context; import android.content.DialogInterface; @@ -37,46 +35,26 @@ import android.support.v4.app.FragmentManager; import android.support.v7.app.AlertDialog; import android.text.Editable; import android.text.TextUtils; -import android.view.ContextMenu; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewParent; +import android.view.*; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; - +import butterknife.Bind; +import butterknife.ButterKnife; +import jscl.math.function.Function; import org.solovyev.android.Activities; import org.solovyev.android.Check; -import org.solovyev.android.calculator.App; -import org.solovyev.android.calculator.AppComponent; -import org.solovyev.android.calculator.BaseDialogFragment; -import org.solovyev.android.calculator.Calculator; -import org.solovyev.android.calculator.Engine; -import org.solovyev.android.calculator.FloatingCalculatorKeyboard; -import org.solovyev.android.calculator.ParseException; -import org.solovyev.android.calculator.R; -import org.solovyev.android.calculator.VariablesRegistry; +import org.solovyev.android.calculator.*; import org.solovyev.android.calculator.entities.EntityRemovalDialog; import org.solovyev.android.calculator.keyboard.FloatingKeyboardWindow; import org.solovyev.android.calculator.view.EditTextCompat; import org.solovyev.common.math.MathRegistry; -import butterknife.Bind; -import butterknife.ButterKnife; -import jscl.math.function.Function; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.inject.Inject; +import java.util.*; + +import static org.solovyev.android.calculator.functions.CppFunction.NO_ID; public class EditFunctionFragment extends BaseDialogFragment implements View.OnClickListener, View.OnFocusChangeListener, View.OnKeyListener { @@ -104,6 +82,8 @@ public class EditFunctionFragment extends BaseDialogFragment implements View.OnC @Inject Calculator calculator; @Inject + Keyboard keyboard; + @Inject FunctionsRegistry functionsRegistry; @Inject VariablesRegistry variablesRegistry; @@ -551,6 +531,11 @@ public class EditFunctionFragment extends BaseDialogFragment implements View.OnC } } + @Override + public boolean isVibrateOnKeypress() { + return keyboard.isVibrateOnKeypress(); + } + @Override public void done() { keyboardWindow.hide(); diff --git a/app/src/main/java/org/solovyev/android/calculator/keyboard/BaseFloatingKeyboard.java b/app/src/main/java/org/solovyev/android/calculator/keyboard/BaseFloatingKeyboard.java index 61bc8e18..0ed731a1 100644 --- a/app/src/main/java/org/solovyev/android/calculator/keyboard/BaseFloatingKeyboard.java +++ b/app/src/main/java/org/solovyev/android/calculator/keyboard/BaseFloatingKeyboard.java @@ -64,6 +64,7 @@ public abstract class BaseFloatingKeyboard implements FloatingKeyboard { button.setTextColor(textColor); button.setDirectionTextColor(textColorSecondary); button.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 24); + button.setVibrateOnDrag(user.isVibrateOnKeypress()); if (TextUtils.isEmpty(text)) { button.setEnabled(false); } @@ -74,6 +75,7 @@ public abstract class BaseFloatingKeyboard implements FloatingKeyboard { button.setId(id); button.setBackgroundResource(buttonBackground); button.setPadding(sidePadding, 1, sidePadding, 1); + button.setHapticFeedbackEnabled(false); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { button.setStateListAnimator(null); } diff --git a/app/src/main/java/org/solovyev/android/calculator/keyboard/BaseKeyboardUi.java b/app/src/main/java/org/solovyev/android/calculator/keyboard/BaseKeyboardUi.java index 1ccbea93..d608698e 100644 --- a/app/src/main/java/org/solovyev/android/calculator/keyboard/BaseKeyboardUi.java +++ b/app/src/main/java/org/solovyev/android/calculator/keyboard/BaseKeyboardUi.java @@ -8,7 +8,6 @@ import android.graphics.Typeface; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.TypedValue; -import android.view.HapticFeedbackConstants; import android.view.View; import android.widget.ImageView; import org.solovyev.android.Views; @@ -17,12 +16,16 @@ import org.solovyev.android.calculator.buttons.CppSpecialButton; import org.solovyev.android.calculator.view.ScreenMetrics; import org.solovyev.android.views.Adjuster; import org.solovyev.android.views.dragbutton.DirectionDragButton; +import org.solovyev.android.views.dragbutton.DragButton; import org.solovyev.android.views.dragbutton.DragDirection; import org.solovyev.android.views.dragbutton.SimpleDragListener; import javax.annotation.Nonnull; import javax.inject.Inject; +import java.util.ArrayList; +import java.util.List; +import static android.view.HapticFeedbackConstants.*; import static org.solovyev.android.calculator.App.cast; import static org.solovyev.android.calculator.App.getScreenMetrics; import static org.solovyev.android.calculator.Preferences.Gui.Layout.simple; @@ -33,6 +36,8 @@ public abstract class BaseKeyboardUi implements SharedPreferences.OnSharedPrefer protected static final float TEXT_SCALE = 0.6f; protected static final float IMAGE_SCALE = 0.6f; + @NonNull + private final List dragButtons = new ArrayList<>(); @NonNull protected final SimpleDragListener listener; @Inject @@ -80,6 +85,8 @@ public abstract class BaseKeyboardUi implements SharedPreferences.OnSharedPrefer if (button == null) { return; } + // we call android.view.View.performHapticFeedback(int, int) from #onClick + button.setHapticFeedbackEnabled(false); button.setOnClickListener(this); } @@ -87,6 +94,8 @@ public abstract class BaseKeyboardUi implements SharedPreferences.OnSharedPrefer if (button == null) { return; } + dragButtons.add(button); + button.setVibrateOnDrag(keyboard.isVibrateOnKeypress()); prepareButton((View) button); button.setOnDragListener(listener); BaseUi.setFont(button, typeface); @@ -113,6 +122,7 @@ public abstract class BaseKeyboardUi implements SharedPreferences.OnSharedPrefer } public void onDestroyView() { + dragButtons.clear(); preferences.unregisterOnSharedPreferenceChangeListener(this); } @@ -125,14 +135,28 @@ public abstract class BaseKeyboardUi implements SharedPreferences.OnSharedPrefer return 5 * buttonSize / 12; } + @Override + public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { + if (Preferences.Gui.vibrateOnKeypress.isSameKey(key)) { + final boolean vibrate = Preferences.Gui.vibrateOnKeypress.getPreference(preferences); + for (DragButton dragButton : dragButtons) { + dragButton.setVibrateOnDrag(vibrate); + } + } + } + protected boolean isSimpleLayout() { return layout == simple || layout == simple_mobile; } protected final void onClick(@Nonnull View v, @Nonnull String s) { - if (keyboard.buttonPressed(s)) { - v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); + if (!keyboard.buttonPressed(s)) { + return; } + if (!keyboard.isVibrateOnKeypress()) { + return; + } + v.performHapticFeedback(KEYBOARD_TAP, FLAG_IGNORE_GLOBAL_SETTING | FLAG_IGNORE_VIEW_SETTING); } protected final void onClick(@Nonnull View v, @Nonnull CppSpecialButton b) { diff --git a/app/src/main/java/org/solovyev/android/calculator/keyboard/FloatingKeyboard.java b/app/src/main/java/org/solovyev/android/calculator/keyboard/FloatingKeyboard.java index 528d2a45..1fd61543 100644 --- a/app/src/main/java/org/solovyev/android/calculator/keyboard/FloatingKeyboard.java +++ b/app/src/main/java/org/solovyev/android/calculator/keyboard/FloatingKeyboard.java @@ -32,5 +32,8 @@ public interface FloatingKeyboard { void done(); void showIme(); + + boolean isVibrateOnKeypress(); + } } diff --git a/app/src/main/java/org/solovyev/android/calculator/keyboard/KeyboardUi.java b/app/src/main/java/org/solovyev/android/calculator/keyboard/KeyboardUi.java index 9285c63f..ee4a2fe3 100644 --- a/app/src/main/java/org/solovyev/android/calculator/keyboard/KeyboardUi.java +++ b/app/src/main/java/org/solovyev/android/calculator/keyboard/KeyboardUi.java @@ -1,14 +1,5 @@ package org.solovyev.android.calculator.keyboard; -import static jscl.NumeralBase.hex; -import static org.solovyev.android.calculator.Engine.Preferences.angleUnit; -import static org.solovyev.android.calculator.Engine.Preferences.multiplicationSign; -import static org.solovyev.android.calculator.Engine.Preferences.numeralBase; -import static org.solovyev.android.calculator.Preferences.Gui.hideNumeralBaseDigits; -import static org.solovyev.android.views.dragbutton.DragDirection.down; -import static org.solovyev.android.views.dragbutton.DragDirection.left; -import static org.solovyev.android.views.dragbutton.DragDirection.up; - import android.app.Activity; import android.app.Application; import android.content.SharedPreferences; @@ -20,12 +11,11 @@ import android.view.MotionEvent; import android.view.View; import android.widget.Button; import android.widget.ImageButton; - -import org.solovyev.android.calculator.ActivityLauncher; -import org.solovyev.android.calculator.CalculatorEventType; -import org.solovyev.android.calculator.CppNumeralBase; -import org.solovyev.android.calculator.Engine; -import org.solovyev.android.calculator.R; +import butterknife.Bind; +import butterknife.ButterKnife; +import jscl.AngleUnit; +import jscl.NumeralBase; +import org.solovyev.android.calculator.*; import org.solovyev.android.calculator.buttons.CppSpecialButton; import org.solovyev.android.calculator.history.History; import org.solovyev.android.calculator.view.AngleUnitsButton; @@ -33,14 +23,14 @@ import org.solovyev.android.views.dragbutton.DirectionDragButton; import org.solovyev.android.views.dragbutton.DragButton; import org.solovyev.android.views.dragbutton.DragDirection; -import butterknife.Bind; -import butterknife.ButterKnife; -import jscl.AngleUnit; -import jscl.NumeralBase; - import javax.annotation.Nonnull; import javax.inject.Inject; +import static jscl.NumeralBase.hex; +import static org.solovyev.android.calculator.Engine.Preferences.*; +import static org.solovyev.android.calculator.Preferences.Gui.hideNumeralBaseDigits; +import static org.solovyev.android.views.dragbutton.DragDirection.*; + public class KeyboardUi extends BaseKeyboardUi { @Bind(R.id.cpp_button_0) @@ -182,6 +172,7 @@ public class KeyboardUi extends BaseKeyboardUi { @Override public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { + super.onSharedPreferenceChanged(preferences, key); if (angleUnit.isSameKey(key)) { button6.setAngleUnit(angleUnit.getPreference(preferences)); } diff --git a/app/src/main/java/org/solovyev/android/calculator/keyboard/PartialKeyboardUi.java b/app/src/main/java/org/solovyev/android/calculator/keyboard/PartialKeyboardUi.java index 6b20c892..2b99705b 100644 --- a/app/src/main/java/org/solovyev/android/calculator/keyboard/PartialKeyboardUi.java +++ b/app/src/main/java/org/solovyev/android/calculator/keyboard/PartialKeyboardUi.java @@ -30,6 +30,7 @@ import javax.inject.Inject; import static org.solovyev.android.calculator.Engine.Preferences.numeralBase; import static org.solovyev.android.calculator.Preferences.Gui.showEqualsButton; +import static org.solovyev.android.calculator.Preferences.Gui.vibrateOnKeypress; import static org.solovyev.android.views.dragbutton.DragDirection.*; public class PartialKeyboardUi extends BaseKeyboardUi { @@ -49,6 +50,8 @@ public class PartialKeyboardUi extends BaseKeyboardUi { @Nullable @Bind(R.id.cpp_button_equals) DirectionDragButton equalsButton; + @Nullable + EditorLongClickEraser longClickEraser; @Inject public PartialKeyboardUi(@NonNull Application application) { @@ -67,7 +70,7 @@ public class PartialKeyboardUi extends BaseKeyboardUi { Check.isTrue(IMAGE_SCALE == 0.6f); // backspace button is too big, scale it more prepareButton(eraseButton, 0.5f); - EditorLongClickEraser.attachTo(eraseButton); + longClickEraser = EditorLongClickEraser.attachTo(eraseButton, keyboard.isVibrateOnKeypress()); } if (isSimpleLayout()) { hideText(clearButton, left, up, down); @@ -96,12 +99,16 @@ public class PartialKeyboardUi extends BaseKeyboardUi { @Override public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { + super.onSharedPreferenceChanged(preferences, key); if (clearButton != null && numeralBase.isSameKey(key)) { clearButton.setNumeralBase(numeralBase.getPreference(preferences)); } if (equalsButton != null && showEqualsButton.isSameKey(key)) { toggleEqualsButton(); } + if (longClickEraser != null && vibrateOnKeypress.isSameKey(key)) { + longClickEraser.setVibrateOnKeypress(vibrateOnKeypress.getPreference(preferences)); + } } @Override diff --git a/app/src/main/java/org/solovyev/android/calculator/onscreen/CalculatorOnscreenView.java b/app/src/main/java/org/solovyev/android/calculator/onscreen/CalculatorOnscreenView.java index 40f5646f..1973a261 100644 --- a/app/src/main/java/org/solovyev/android/calculator/onscreen/CalculatorOnscreenView.java +++ b/app/src/main/java/org/solovyev/android/calculator/onscreen/CalculatorOnscreenView.java @@ -42,6 +42,7 @@ import javax.annotation.Nullable; import javax.inject.Inject; import java.util.Locale; +import static android.view.HapticFeedbackConstants.*; import static org.solovyev.android.calculator.App.cast; public class CalculatorOnscreenView { @@ -145,7 +146,9 @@ public class CalculatorOnscreenView { @Override public void onClick(View v) { if (keyboard.buttonPressed(widgetButton.action)) { - v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); + if (keyboard.isVibrateOnKeypress()) { + v.performHapticFeedback(KEYBOARD_TAP, FLAG_IGNORE_GLOBAL_SETTING | FLAG_IGNORE_VIEW_SETTING); + } } if (widgetButton == CppButton.app) { minimize(); @@ -156,7 +159,9 @@ public class CalculatorOnscreenView { @Override public boolean onLongClick(View v) { if (keyboard.buttonPressed(widgetButton.actionLong)) { - v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + if (keyboard.isVibrateOnKeypress()) { + v.performHapticFeedback(LONG_PRESS, FLAG_IGNORE_GLOBAL_SETTING | FLAG_IGNORE_VIEW_SETTING); + } } return true; } diff --git a/app/src/main/java/org/solovyev/android/calculator/variables/EditVariableFragment.java b/app/src/main/java/org/solovyev/android/calculator/variables/EditVariableFragment.java index 9b935f5b..14014b2e 100644 --- a/app/src/main/java/org/solovyev/android/calculator/variables/EditVariableFragment.java +++ b/app/src/main/java/org/solovyev/android/calculator/variables/EditVariableFragment.java @@ -22,8 +22,6 @@ package org.solovyev.android.calculator.variables; -import static org.solovyev.android.calculator.variables.CppVariable.NO_ID; - import android.annotation.SuppressLint; import android.content.Context; import android.content.DialogInterface; @@ -43,16 +41,12 @@ import android.view.inputmethod.InputMethodManager; import android.widget.Button; import android.widget.EditText; import android.widget.PopupWindow; - +import butterknife.Bind; +import butterknife.ButterKnife; +import jscl.math.function.IConstant; import org.solovyev.android.Activities; import org.solovyev.android.Check; -import org.solovyev.android.calculator.App; -import org.solovyev.android.calculator.AppComponent; -import org.solovyev.android.calculator.BaseDialogFragment; -import org.solovyev.android.calculator.Calculator; -import org.solovyev.android.calculator.Engine; -import org.solovyev.android.calculator.R; -import org.solovyev.android.calculator.VariablesRegistry; +import org.solovyev.android.calculator.*; import org.solovyev.android.calculator.entities.EntityRemovalDialog; import org.solovyev.android.calculator.functions.FunctionsRegistry; import org.solovyev.android.calculator.keyboard.FloatingKeyboard; @@ -61,16 +55,13 @@ import org.solovyev.android.calculator.math.MathType; import org.solovyev.android.calculator.view.EditTextCompat; import org.solovyev.common.text.Strings; -import butterknife.Bind; -import butterknife.ButterKnife; -import jscl.math.function.IConstant; - -import java.util.Arrays; -import java.util.List; - import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.inject.Inject; +import java.util.Arrays; +import java.util.List; + +import static org.solovyev.android.calculator.variables.CppVariable.NO_ID; public class EditVariableFragment extends BaseDialogFragment implements View.OnFocusChangeListener, View.OnKeyListener, View.OnClickListener { @@ -100,6 +91,8 @@ public class EditVariableFragment extends BaseDialogFragment implements View.OnF @Inject Calculator calculator; @Inject + Keyboard keyboard; + @Inject FunctionsRegistry functionsRegistry; @Inject VariablesRegistry variablesRegistry; @@ -410,5 +403,10 @@ public class EditVariableFragment extends BaseDialogFragment implements View.OnF keyboard.showSoftInput(getEditor(), InputMethodManager.SHOW_FORCED); keyboardWindow.hide(); } + + @Override + public boolean isVibrateOnKeypress() { + return keyboard.isVibrateOnKeypress(); + } } } diff --git a/app/src/main/java/org/solovyev/android/calculator/variables/GreekFloatingKeyboard.java b/app/src/main/java/org/solovyev/android/calculator/variables/GreekFloatingKeyboard.java index 543844f8..a84eae6e 100644 --- a/app/src/main/java/org/solovyev/android/calculator/variables/GreekFloatingKeyboard.java +++ b/app/src/main/java/org/solovyev/android/calculator/variables/GreekFloatingKeyboard.java @@ -4,7 +4,6 @@ import android.annotation.TargetApi; import android.os.Build; import android.support.annotation.IdRes; import android.support.annotation.NonNull; -import android.view.HapticFeedbackConstants; import android.view.View; import android.widget.Button; import android.widget.LinearLayout; @@ -17,6 +16,8 @@ import org.solovyev.android.calculator.view.EditTextLongClickEraser; import javax.annotation.Nonnull; import java.util.Locale; +import static android.view.HapticFeedbackConstants.*; + public class GreekFloatingKeyboard extends BaseFloatingKeyboard implements View.OnClickListener { final static String ALPHABET = "αβγδεζηθικλμνξοπρστυφχψω"; @@ -57,7 +58,7 @@ public class GreekFloatingKeyboard extends BaseFloatingKeyboard implements View. switch (row) { case 0: final View backspace = addImageButton(rowView, R.id.cpp_kb_button_backspace, R.drawable.ic_backspace_grey300_24dp); - EditTextLongClickEraser.attachTo(backspace, user.getEditor()); + EditTextLongClickEraser.attachTo(backspace, user.getEditor(), user.isVibrateOnKeypress()); break; case 1: addButton(rowView, R.id.cpp_kb_button_change_case, "↑"); @@ -81,7 +82,7 @@ public class GreekFloatingKeyboard extends BaseFloatingKeyboard implements View. break; case 1: final View backspace = addImageButton(rowView, R.id.cpp_kb_button_backspace, R.drawable.ic_backspace_grey300_24dp); - EditTextLongClickEraser.attachTo(backspace, user.getEditor()); + EditTextLongClickEraser.attachTo(backspace, user.getEditor(), user.isVibrateOnKeypress()); break; case 2: addButton(rowView, R.id.cpp_kb_button_change_case, "↑"); @@ -118,7 +119,9 @@ public class GreekFloatingKeyboard extends BaseFloatingKeyboard implements View. @Override public void onClick(View v) { - v.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); + if (user.isVibrateOnKeypress()) { + v.performHapticFeedback(KEYBOARD_TAP, FLAG_IGNORE_GLOBAL_SETTING | FLAG_IGNORE_VIEW_SETTING); + } switch (v.getId()) { case R.id.cpp_kb_button_close: user.done(); diff --git a/app/src/main/java/org/solovyev/android/calculator/view/BaseLongClickEraser.java b/app/src/main/java/org/solovyev/android/calculator/view/BaseLongClickEraser.java index c5a9fe66..fc95adb8 100644 --- a/app/src/main/java/org/solovyev/android/calculator/view/BaseLongClickEraser.java +++ b/app/src/main/java/org/solovyev/android/calculator/view/BaseLongClickEraser.java @@ -1,25 +1,26 @@ package org.solovyev.android.calculator.view; import android.view.GestureDetector; -import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import android.view.View; import javax.annotation.Nonnull; +import static android.view.HapticFeedbackConstants.*; + public abstract class BaseLongClickEraser implements View.OnTouchListener { @Nonnull private final View view; - @Nonnull private final GestureDetector gestureDetector; - @Nonnull private final Eraser eraser = new Eraser(); + protected boolean vibrateOnKeypress; - protected BaseLongClickEraser(@Nonnull final View view) { + protected BaseLongClickEraser(@Nonnull final View view, boolean vibrateOnKeypress) { this.view = view; + this.vibrateOnKeypress = vibrateOnKeypress; this.gestureDetector = new GestureDetector(view.getContext(), new GestureDetector.SimpleOnGestureListener() { public void onLongPress(MotionEvent e) { if (eraser.isTracking()) { @@ -30,6 +31,10 @@ public abstract class BaseLongClickEraser implements View.OnTouchListener { this.view.setOnTouchListener(this); } + public void setVibrateOnKeypress(boolean vibrateOnKeypress) { + this.vibrateOnKeypress = vibrateOnKeypress; + } + @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { @@ -74,7 +79,9 @@ public abstract class BaseLongClickEraser implements View.OnTouchListener { erasing = true; delay = DELAY; view.removeCallbacks(this); - view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); + if (vibrateOnKeypress) { + view.performHapticFeedback(KEYBOARD_TAP, FLAG_IGNORE_GLOBAL_SETTING | FLAG_IGNORE_VIEW_SETTING); + } onStartErase(); run(); } diff --git a/app/src/main/java/org/solovyev/android/calculator/view/EditTextLongClickEraser.java b/app/src/main/java/org/solovyev/android/calculator/view/EditTextLongClickEraser.java index 4b03fee1..2082172c 100644 --- a/app/src/main/java/org/solovyev/android/calculator/view/EditTextLongClickEraser.java +++ b/app/src/main/java/org/solovyev/android/calculator/view/EditTextLongClickEraser.java @@ -1,34 +1,33 @@ package org.solovyev.android.calculator.view; import android.text.Editable; -import android.view.HapticFeedbackConstants; import android.view.View; import android.widget.EditText; import javax.annotation.Nonnull; +import static android.view.HapticFeedbackConstants.*; + public class EditTextLongClickEraser extends BaseLongClickEraser implements View.OnClickListener { @Nonnull private final EditText editView; - private EditTextLongClickEraser(@Nonnull View view, @Nonnull EditText editView) { - super(view); + private EditTextLongClickEraser(@Nonnull View view, @Nonnull EditText editView, boolean vibrateOnKeypress) { + super(view, vibrateOnKeypress); this.editView = editView; view.setOnClickListener(this); } - public static void attachTo(@Nonnull View view, @Nonnull EditText editView) { - new EditTextLongClickEraser(view, editView); + public static void attachTo(@Nonnull View view, @Nonnull EditText editView, boolean vibrateOnKeypress) { + new EditTextLongClickEraser(view, editView, vibrateOnKeypress); } @Override protected void onStopErase() { - } @Override protected void onStartErase() { - } @Override @@ -49,6 +48,8 @@ public class EditTextLongClickEraser extends BaseLongClickEraser implements View @Override public void onClick(View v) { erase(); - v.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); + if (vibrateOnKeypress) { + v.performHapticFeedback(KEYBOARD_TAP, FLAG_IGNORE_GLOBAL_SETTING | FLAG_IGNORE_VIEW_SETTING); + } } } diff --git a/app/src/main/java/org/solovyev/android/calculator/view/EditorLongClickEraser.java b/app/src/main/java/org/solovyev/android/calculator/view/EditorLongClickEraser.java index 8e9d489f..3da45939 100644 --- a/app/src/main/java/org/solovyev/android/calculator/view/EditorLongClickEraser.java +++ b/app/src/main/java/org/solovyev/android/calculator/view/EditorLongClickEraser.java @@ -17,12 +17,13 @@ public class EditorLongClickEraser extends BaseLongClickEraser { private boolean wasCalculatingOnFly; - private EditorLongClickEraser(@Nonnull View view) { - super(view); + private EditorLongClickEraser(@Nonnull View view, boolean vibrateOnKeypress) { + super(view, vibrateOnKeypress); } - public static void attachTo(@Nonnull View view) { - new EditorLongClickEraser(view); + @Nonnull + public static EditorLongClickEraser attachTo(@Nonnull View view, boolean vibrateOnKeypress) { + return new EditorLongClickEraser(view, vibrateOnKeypress); } protected boolean erase() { diff --git a/app/src/main/java/org/solovyev/android/calculator/widget/CalculatorWidget.java b/app/src/main/java/org/solovyev/android/calculator/widget/CalculatorWidget.java index 294f4896..aacbc566 100644 --- a/app/src/main/java/org/solovyev/android/calculator/widget/CalculatorWidget.java +++ b/app/src/main/java/org/solovyev/android/calculator/widget/CalculatorWidget.java @@ -40,37 +40,26 @@ import android.text.SpannedString; import android.text.TextUtils; import android.text.style.StyleSpan; import android.widget.RemoteViews; - import org.solovyev.android.Check; import org.solovyev.android.Views; -import org.solovyev.android.calculator.App; -import org.solovyev.android.calculator.buttons.CppButton; -import org.solovyev.android.calculator.DisplayState; -import org.solovyev.android.calculator.EditorState; -import org.solovyev.android.calculator.Locator; +import org.solovyev.android.calculator.*; import org.solovyev.android.calculator.Preferences.SimpleTheme; -import org.solovyev.android.calculator.R; - -import java.util.EnumMap; +import org.solovyev.android.calculator.buttons.CppButton; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.EnumMap; import static android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT; import static android.content.Intent.ACTION_CONFIGURATION_CHANGED; import static android.os.Build.VERSION_CODES.JELLY_BEAN; -import static org.solovyev.android.calculator.Broadcaster.ACTION_DISPLAY_STATE_CHANGED; -import static org.solovyev.android.calculator.Broadcaster.ACTION_EDITOR_STATE_CHANGED; -import static org.solovyev.android.calculator.Broadcaster.ACTION_INIT; -import static org.solovyev.android.calculator.Broadcaster.ACTION_THEME_CHANGED; -import static org.solovyev.android.calculator.CalculatorReceiver.newButtonClickedIntent; +import static org.solovyev.android.calculator.Broadcaster.*; +import static org.solovyev.android.calculator.WidgetReceiver.newButtonClickedIntent; public class CalculatorWidget extends AppWidgetProvider { - private static final String TAG = App.subTag("Widget"); private static final int WIDGET_CATEGORY_KEYGUARD = 2; private static final String OPTION_APPWIDGET_HOST_CATEGORY = "appWidgetCategory"; - private static final String ACTION_APPWIDGET_OPTIONS_CHANGED = "android.appwidget.action.APPWIDGET_UPDATE_OPTIONS"; @Nonnull private static final Intents intents = new Intents(); @Nullable @@ -209,9 +198,10 @@ public class CalculatorWidget extends AppWidgetProvider { updateWidget(context, true); break; case ACTION_CONFIGURATION_CHANGED: - case ACTION_APPWIDGET_OPTIONS_CHANGED: case ACTION_THEME_CHANGED: case ACTION_INIT: + case AppWidgetManager.ACTION_APPWIDGET_UPDATE: + case AppWidgetManager.ACTION_APPWIDGET_OPTIONS_CHANGED: updateWidget(context, false); break; } diff --git a/app/src/main/java/org/solovyev/android/prefs/IntegerPreference.java b/app/src/main/java/org/solovyev/android/prefs/IntegerPreference.java index 0cf317a9..58254ce3 100644 --- a/app/src/main/java/org/solovyev/android/prefs/IntegerPreference.java +++ b/app/src/main/java/org/solovyev/android/prefs/IntegerPreference.java @@ -29,6 +29,8 @@ import javax.annotation.Nullable; public class IntegerPreference extends AbstractPreference { + public static final int DEF_VALUE = -1; + private IntegerPreference(@Nonnull String key, @Nullable Integer defaultValue) { super(key, defaultValue); } @@ -40,7 +42,7 @@ public class IntegerPreference extends AbstractPreference { @Override protected Integer getPersistedValue(@Nonnull SharedPreferences preferences) { - return preferences.getInt(getKey(), -1); + return preferences.getInt(getKey(), DEF_VALUE); } @Override diff --git a/app/src/main/res/values/text_preferences.xml b/app/src/main/res/values/text_preferences.xml index 1a31fa36..6dd91173 100644 --- a/app/src/main/res/values/text_preferences.xml +++ b/app/src/main/res/values/text_preferences.xml @@ -18,4 +18,5 @@ If turned on screen will not fade while using the app Language + Vibrate on keypress diff --git a/app/src/main/res/xml/preferences_appearance.xml b/app/src/main/res/xml/preferences_appearance.xml index db24655b..82592cb0 100644 --- a/app/src/main/res/xml/preferences_appearance.xml +++ b/app/src/main/res/xml/preferences_appearance.xml @@ -36,6 +36,10 @@ a:summary="@string/c_calc_color_display_summary" a:title="@string/c_calc_color_display_title" /> + +