diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 01d26edd..05de47c6 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -5,6 +5,8 @@
a:versionCode="5"
a:versionName="1.1.3">
+
+
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index aa7fe8e8..52702a9e 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -12,6 +12,8 @@
Основные настройки
+ Настроцки вычислений
+ Настройки внешнего вида
Настройки кнопок
@@ -97,4 +99,7 @@
Калькулятор
Устанавливает раскладку кнопок
+ Тактильный ввод
+ Включает/выключает вибрацию по нажатию клавиши
+
diff --git a/res/values/default_values.xml b/res/values/default_values.xml
index 649f8d77..0e269f30 100644
--- a/res/values/default_values.xml
+++ b/res/values/default_values.xml
@@ -19,13 +19,16 @@
org.solovyev.android.calculator.CalculatorModel_color_display
true
+ org.solovyev.android.calculator.CalculatorModel_haptic_feedback
+ false
+
org.solovyev.android.calculator.CalculatorModel_vars
org.solovyev.android.calculator.CalculatorActivity_calc_theme
default_theme
org.solovyev.android.calculator.CalculatorActivity_calc_layout
- main_cellphone
+ main_calculator
org.solovyev.android.calculator.CalculatorActivity_calc_grouping_separator
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 8e29e53d..ff9dc258 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -11,6 +11,8 @@
Variables And Constants
Main settings
+ Calculation settings
+ Appearance settings
Drag buttons settings
@@ -81,7 +83,7 @@
Violet
Light Blue
Precision of result value (all calculations are done with maximum precision regardless of the value of this option)
- Enables/disables colouring and styling in calculator editor
+ Toggles colouring and styling in calculator editor
Sets the theme for calculator
Clear history
Next constants are undefined: {0}!
@@ -97,4 +99,7 @@
Calculator
Sets layout of buttons
+ Haptic feedback
+ Toggles vibration on button click
+
diff --git a/res/xml/main_preferences.xml b/res/xml/main_preferences.xml
index 2812e567..e29b6125 100644
--- a/res/xml/main_preferences.xml
+++ b/res/xml/main_preferences.xml
@@ -2,7 +2,7 @@
-
+
+
+
+
+
+
+
+
-
+
-->
-
\ No newline at end of file
diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java b/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java
index 37b5d2d1..d0defba6 100644
--- a/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java
+++ b/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java
@@ -12,12 +12,14 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
+import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.text.ClipboardManager;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.util.TypedValue;
import android.view.*;
+import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import bsh.EvalError;
@@ -41,6 +43,8 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
private static final int HVGA_WIDTH_PIXELS = 320;
+ private static final long ON_CLICK_VIBRATION_TIME = 100;
+
@NotNull
private final Announcer dpclRegister = new Announcer(DragPreferencesChangeListener.class);
@@ -61,6 +65,12 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
// ids of drag buttons in R.class
private List dragButtonIds = null;
+ // ids of buttons in R.class
+ private List buttonIds = null;
+
+ @Nullable
+ private Vibrator vibrator;
+
/**
* Called when the activity is first created.
*/
@@ -78,28 +88,27 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
firstTimeInit(preferences);
+ vibrator = (Vibrator) this.getSystemService(VIBRATOR_SERVICE);
+
calculatorModel = CalculatorModel.instance.init(this, preferences, CalculatorEngine.instance);
dpclRegister.clear();
final SimpleOnDragListener.Preferences dragPreferences = SimpleOnDragListener.getPreferences(preferences, this);
- setOnDragListeners(dragPreferences);
+ setOnDragListeners(dragPreferences, preferences);
- final SimpleOnDragListener historyOnDragListener = new SimpleOnDragListener(new HistoryDragProcessor(this.calculatorModel), dragPreferences);
+ final OnDragListener historyOnDragListener = new OnDragListenerVibrator(newOnDragListener(new HistoryDragProcessor(this.calculatorModel), dragPreferences), vibrator, preferences);
((DragButton) findViewById(R.id.historyButton)).setOnDragListener(historyOnDragListener);
- dpclRegister.addListener(historyOnDragListener);
- final SimpleOnDragListener toPositionOnDragListener = new SimpleOnDragListener(new CursorDragProcessor(calculatorModel), dragPreferences);
+ final OnDragListener toPositionOnDragListener = new OnDragListenerVibrator(new SimpleOnDragListener(new CursorDragProcessor(calculatorModel), dragPreferences), vibrator, preferences);
((DragButton) findViewById(R.id.rightButton)).setOnDragListener(toPositionOnDragListener);
((DragButton) findViewById(R.id.leftButton)).setOnDragListener(toPositionOnDragListener);
- dpclRegister.addListener(toPositionOnDragListener);
final DragButton equalsButton = (DragButton) findViewById(R.id.equalsButton);
if (equalsButton != null) {
- final SimpleOnDragListener evalOnDragListener = new SimpleOnDragListener(new EvalDragProcessor(calculatorModel), dragPreferences);
+ final OnDragListener evalOnDragListener = new OnDragListenerVibrator(newOnDragListener(new EvalDragProcessor(calculatorModel), dragPreferences), vibrator, preferences);
equalsButton.setOnDragListener(evalOnDragListener);
- dpclRegister.addListener(evalOnDragListener);
}
CalculatorEngine.instance.reset(this, preferences);
@@ -108,13 +117,13 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
}
private void setDefaultValues(@NotNull SharedPreferences preferences) {
- if ( !preferences.contains(CalculatorEngine.GROUPING_SEPARATOR_P_KEY) ) {
+ if (!preferences.contains(CalculatorEngine.GROUPING_SEPARATOR_P_KEY)) {
final Locale locale = Locale.getDefault();
- if ( locale != null ) {
+ if (locale != null) {
final DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols(locale);
int index = MathType.grouping_separator.getTokens().indexOf(String.valueOf(decimalFormatSymbols.getGroupingSeparator()));
final String groupingSeparator;
- if ( index >= 0 ) {
+ if (index >= 0) {
groupingSeparator = MathType.grouping_separator.getTokens().get(index);
} else {
groupingSeparator = " ";
@@ -126,34 +135,48 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
}
}
- private synchronized void setOnDragListeners(@NotNull SimpleOnDragListener.Preferences dragPreferences) {
- final SimpleOnDragListener onDragListener = new SimpleOnDragListener(new DigitButtonDragProcessor(calculatorModel), dragPreferences);
- dpclRegister.addListener(onDragListener);
-
- if (dragButtonIds == null) {
- dragButtonIds = new ArrayList();
-
- for (Field field : R.id.class.getDeclaredFields()) {
- int modifiers = field.getModifiers();
- if (Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers)) {
- try {
- int dragButtonId = field.getInt(R.id.class);
- final View view = findViewById(dragButtonId);
- if (view instanceof DragButton) {
- dragButtonIds.add(dragButtonId);
- }
- } catch (IllegalAccessException e) {
- Log.e(CalculatorActivity.class.getName(), e.getMessage());
- }
- }
- }
- }
+ private synchronized void setOnDragListeners(@NotNull SimpleOnDragListener.Preferences dragPreferences, @NotNull SharedPreferences preferences) {
+ final OnDragListener onDragListener = new OnDragListenerVibrator(newOnDragListener(new DigitButtonDragProcessor(calculatorModel), dragPreferences), vibrator, preferences);
for (Integer dragButtonId : dragButtonIds) {
((DragButton) findViewById(dragButtonId)).setOnDragListener(onDragListener);
}
}
+ @NotNull
+ private SimpleOnDragListener newOnDragListener(@NotNull SimpleOnDragListener.DragProcessor dragProcessor,
+ @NotNull SimpleOnDragListener.Preferences dragPreferences) {
+ final SimpleOnDragListener onDragListener = new SimpleOnDragListener(dragProcessor, dragPreferences);
+ dpclRegister.addListener(onDragListener);
+ return onDragListener;
+ }
+
+ private class OnDragListenerVibrator extends OnDragListenerWrapper {
+
+ private static final long VIBRATION_TIME = 50;
+
+ @NotNull
+ private final VibratorContainer vibrator;
+
+ public OnDragListenerVibrator(@NotNull OnDragListener onDragListener,
+ @Nullable Vibrator vibrator,
+ @NotNull SharedPreferences preferences) {
+ super(onDragListener);
+ this.vibrator = new VibratorContainer(vibrator, preferences, VIBRATION_TIME);
+ }
+
+ @Override
+ public boolean onDrag(@NotNull DragButton dragButton, @NotNull DragEvent event) {
+ boolean result = super.onDrag(dragButton, event);
+
+ if (result) {
+ vibrator.vibrate();
+ }
+
+ return result;
+ }
+ }
+
private synchronized void setLayout(@NotNull SharedPreferences preferences) {
final Map layouts = getCache(R.layout.class);
@@ -162,8 +185,8 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
Integer layoutId = layouts.get(layoutName);
if (layoutId == null) {
- Log.d(this.getClass().getName(), "No saved layout found => applying default layout: " + R.layout.main_cellphone);
- layoutId = R.layout.main_cellphone;
+ Log.d(this.getClass().getName(), "No saved layout found => applying default layout: " + R.layout.main_calculator);
+ layoutId = R.layout.main_calculator;
} else {
Log.d(this.getClass().getName(), "Saved layout found: " + layoutId);
}
@@ -213,6 +236,27 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
private synchronized void firstTimeInit(@NotNull SharedPreferences preferences) {
if (!initialized) {
+ dragButtonIds = new ArrayList();
+ buttonIds = new ArrayList();
+
+ for (Field field : R.id.class.getDeclaredFields()) {
+ int modifiers = field.getModifiers();
+ if (Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers)) {
+ try {
+ int viewId = field.getInt(R.id.class);
+ final View view = findViewById(viewId);
+ if (view instanceof DragButton) {
+ dragButtonIds.add(viewId);
+ }
+ if (view instanceof Button) {
+ buttonIds.add(viewId);
+ }
+ } catch (IllegalAccessException e) {
+ Log.e(CalculatorActivity.class.getName(), e.getMessage());
+ }
+ }
+ }
+
try {
CalculatorEngine.instance.init(this, preferences);
} catch (EvalError evalError) {
diff --git a/src/main/java/org/solovyev/android/view/widgets/ColorButton.java b/src/main/java/org/solovyev/android/view/widgets/ColorButton.java
index caa10219..92b54b51 100644
--- a/src/main/java/org/solovyev/android/view/widgets/ColorButton.java
+++ b/src/main/java/org/solovyev/android/view/widgets/ColorButton.java
@@ -27,6 +27,8 @@ import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.drawable.Drawable;
+import android.os.Vibrator;
+import android.preference.PreferenceManager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.Button;
@@ -54,15 +56,21 @@ public class ColorButton extends Button {
private long animationStart;
private Paint feedbackPaint;
+ @NotNull
+ private final OnClickListenerVibrator onClickListener;
+
public ColorButton(Context context, AttributeSet attrs) {
this(context, attrs, true);
}
public ColorButton(Context context, AttributeSet attrs, boolean init) {
super(context, attrs);
+
if (init) {
init(context);
}
+
+ this.onClickListener = new OnClickListenerVibrator((Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE), PreferenceManager.getDefaultSharedPreferences(context));
}
protected void init(Context context) {
@@ -179,6 +187,22 @@ public class ColorButton extends Button {
invalidate();
}
+ @Override
+ public boolean performClick() {
+ vibrate();
+ return super.performClick();
+ }
+
+ @Override
+ public boolean performLongClick() {
+ vibrate();
+ return super.performLongClick();
+ }
+
+ private void vibrate() {
+ this.onClickListener.onClick(this);
+ }
+
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean result = super.onTouchEvent(event);
diff --git a/src/main/java/org/solovyev/android/view/widgets/OnClickListenerVibrator.java b/src/main/java/org/solovyev/android/view/widgets/OnClickListenerVibrator.java
new file mode 100644
index 00000000..39c30103
--- /dev/null
+++ b/src/main/java/org/solovyev/android/view/widgets/OnClickListenerVibrator.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2009-2011. Created by serso aka se.solovyev.
+ * For more information, please, contact se.solovyev@gmail.com
+ * or visit http://se.solovyev.org
+ */
+
+package org.solovyev.android.view.widgets;
+
+import android.content.SharedPreferences;
+import android.os.Vibrator;
+import android.view.View;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+* User: serso
+* Date: 10/26/11
+* Time: 11:25 PM
+*/
+public class OnClickListenerVibrator implements View.OnClickListener {
+
+ private static final long VIBRATION_TIME = 100;
+
+ @NotNull
+ private VibratorContainer vibrator;
+
+ public OnClickListenerVibrator(@Nullable Vibrator vibrator,
+ @NotNull SharedPreferences preferences) {
+ this.vibrator = new VibratorContainer(vibrator, preferences, VIBRATION_TIME);
+ }
+
+ @Override
+ public void onClick(View v) {
+ vibrator.vibrate();
+ }
+}
diff --git a/src/main/java/org/solovyev/android/view/widgets/OnClickListenerWrapper.java b/src/main/java/org/solovyev/android/view/widgets/OnClickListenerWrapper.java
new file mode 100644
index 00000000..e68243f9
--- /dev/null
+++ b/src/main/java/org/solovyev/android/view/widgets/OnClickListenerWrapper.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2009-2011. Created by serso aka se.solovyev.
+ * For more information, please, contact se.solovyev@gmail.com
+ * or visit http://se.solovyev.org
+ */
+
+package org.solovyev.android.view.widgets;
+
+import android.view.View;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * User: serso
+ * Date: 10/26/11
+ * Time: 10:55 PM
+ */
+public class OnClickListenerWrapper implements View.OnClickListener{
+
+ @NotNull
+ private final View.OnClickListener onClickListener;
+
+ public OnClickListenerWrapper(@NotNull View.OnClickListener onClickListener) {
+ this.onClickListener = onClickListener;
+ }
+
+ @Override
+ public void onClick(View v) {
+ this.onClick(v);
+ }
+}
diff --git a/src/main/java/org/solovyev/android/view/widgets/OnDragListenerWrapper.java b/src/main/java/org/solovyev/android/view/widgets/OnDragListenerWrapper.java
new file mode 100644
index 00000000..f88c8220
--- /dev/null
+++ b/src/main/java/org/solovyev/android/view/widgets/OnDragListenerWrapper.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2009-2011. Created by serso aka se.solovyev.
+ * For more information, please, contact se.solovyev@gmail.com
+ * or visit http://se.solovyev.org
+ */
+
+package org.solovyev.android.view.widgets;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+* User: serso
+* Date: 10/26/11
+* Time: 10:37 PM
+*/
+public class OnDragListenerWrapper implements OnDragListener {
+
+ @NotNull
+ private final OnDragListener onDragListener;
+
+ public OnDragListenerWrapper(@NotNull OnDragListener onDragListener) {
+ this.onDragListener = onDragListener;
+ }
+
+ @Override
+ public boolean isSuppressOnClickEvent() {
+ return this.onDragListener.isSuppressOnClickEvent();
+ }
+
+ @Override
+ public boolean onDrag(@NotNull DragButton dragButton, @NotNull DragEvent event) {
+ return this.onDragListener.onDrag(dragButton, event);
+ }
+}
diff --git a/src/main/java/org/solovyev/android/view/widgets/VibratorContainer.java b/src/main/java/org/solovyev/android/view/widgets/VibratorContainer.java
new file mode 100644
index 00000000..09999560
--- /dev/null
+++ b/src/main/java/org/solovyev/android/view/widgets/VibratorContainer.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2009-2011. Created by serso aka se.solovyev.
+ * For more information, please, contact se.solovyev@gmail.com
+ * or visit http://se.solovyev.org
+ */
+
+package org.solovyev.android.view.widgets;
+
+import android.content.SharedPreferences;
+import android.os.Vibrator;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * User: serso
+ * Date: 10/26/11
+ * Time: 11:40 PM
+ */
+public class VibratorContainer implements SharedPreferences.OnSharedPreferenceChangeListener {
+
+ private static final String HAPTIC_FEEDBACK_PREFERENCE = "org.solovyev.android.calculator.CalculatorModel_haptic_feedback";
+
+ private final long defaultVibrationTime;
+
+ @Nullable
+ private final Vibrator vibrator;
+
+ private long time = 0;
+
+ public VibratorContainer(@Nullable Vibrator vibrator, @NotNull SharedPreferences preferences, long defaultVibrationTime) {
+ this.vibrator = vibrator;
+ this.defaultVibrationTime = defaultVibrationTime;
+
+ preferences.registerOnSharedPreferenceChangeListener(this);
+ onSharedPreferenceChanged(preferences, null);
+
+ }
+
+ public void vibrate() {
+ if (time > 0 && vibrator != null) {
+ vibrator.vibrate(time);
+ }
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences preferences, @Nullable String key) {
+ if (preferences.getBoolean(HAPTIC_FEEDBACK_PREFERENCE, false)) {
+ this.time = defaultVibrationTime;
+ } else {
+ this.time = 0;
+ }
+ }
+}