From bbaedc71c9966be4c68cda55294f0172c94a4760 Mon Sep 17 00:00:00 2001 From: serso Date: Fri, 22 Jan 2016 23:15:03 +0100 Subject: [PATCH] LongClickEraser generalized --- .../solovyev/android/calculator/BaseUi.java | 7 +- .../android/calculator/KeyboardUi.java | 126 +----------------- ...ckEraser.java => BaseLongClickEraser.java} | 43 ++---- .../calculator/view/DragListenerVibrator.java | 66 --------- .../view/EditTextLongClickEraser.java | 54 ++++++++ .../view/EditorLongClickEraser.java | 47 +++++++ 6 files changed, 117 insertions(+), 226 deletions(-) rename app/src/main/java/org/solovyev/android/calculator/view/{LongClickEraser.java => BaseLongClickEraser.java} (66%) delete mode 100644 app/src/main/java/org/solovyev/android/calculator/view/DragListenerVibrator.java create mode 100644 app/src/main/java/org/solovyev/android/calculator/view/EditTextLongClickEraser.java create mode 100644 app/src/main/java/org/solovyev/android/calculator/view/EditorLongClickEraser.java diff --git a/app/src/main/java/org/solovyev/android/calculator/BaseUi.java b/app/src/main/java/org/solovyev/android/calculator/BaseUi.java index 71c1e324..0515c4bb 100644 --- a/app/src/main/java/org/solovyev/android/calculator/BaseUi.java +++ b/app/src/main/java/org/solovyev/android/calculator/BaseUi.java @@ -37,10 +37,7 @@ import android.widget.TextView; import org.solovyev.android.Views; import org.solovyev.android.calculator.history.History; import org.solovyev.android.calculator.history.HistoryDragProcessor; -import org.solovyev.android.calculator.view.AngleUnitsButton; -import org.solovyev.android.calculator.view.LongClickEraser; -import org.solovyev.android.calculator.view.NumeralBasesButton; -import org.solovyev.android.calculator.view.ViewsCache; +import org.solovyev.android.calculator.view.*; import org.solovyev.android.views.dragbutton.DirectionDragButton; import org.solovyev.android.views.dragbutton.DragButton; import org.solovyev.android.views.dragbutton.DragDirection; @@ -216,7 +213,7 @@ public abstract class BaseUi implements SharedPreferences.OnSharedPreferenceChan final View eraseButton = getButton(views, R.id.cpp_button_erase); if (eraseButton != null) { - LongClickEraser.createAndAttach(eraseButton); + EditorLongClickEraser.attachTo(eraseButton); } clearButton = getButton(views, R.id.cpp_button_clear); diff --git a/app/src/main/java/org/solovyev/android/calculator/KeyboardUi.java b/app/src/main/java/org/solovyev/android/calculator/KeyboardUi.java index 7f872aef..95057a13 100644 --- a/app/src/main/java/org/solovyev/android/calculator/KeyboardUi.java +++ b/app/src/main/java/org/solovyev/android/calculator/KeyboardUi.java @@ -1,6 +1,5 @@ package org.solovyev.android.calculator; -import android.annotation.SuppressLint; import android.content.Context; import android.content.res.Resources; import android.graphics.Color; @@ -12,7 +11,6 @@ import android.support.annotation.IdRes; import android.support.annotation.NonNull; import android.text.TextUtils; import android.util.TypedValue; -import android.view.GestureDetector; import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import android.view.View; @@ -23,6 +21,7 @@ import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; +import org.solovyev.android.calculator.view.EditTextLongClickEraser; import org.solovyev.android.views.dragbutton.DirectionDragButton; import org.solovyev.android.views.dragbutton.DragButton; import org.solovyev.android.views.dragbutton.DragDirection; @@ -77,7 +76,7 @@ public class KeyboardUi { 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_white_24dp); - LongClickEraser.createAndAttach(backspace, user.getEditor()); + EditTextLongClickEraser.attachTo(backspace, user.getEditor()); row = makeRow(); addButton(row, 0, "1"); @@ -290,125 +289,4 @@ public class KeyboardUi { return true; } } - - public static final class LongClickEraser implements View.OnTouchListener, View.OnClickListener { - - @NonNull - private final View view; - - @NonNull - private final EditText editText; - - @NonNull - private final GestureDetector gestureDetector; - - @NonNull - private final Eraser eraser = new Eraser(); - - private LongClickEraser(@NonNull final View view, @NonNull EditText editText) { - this.view = view; - this.editText = editText; - this.gestureDetector = new GestureDetector(view.getContext(), new GestureDetector.SimpleOnGestureListener() { - public void onLongPress(MotionEvent e) { - if (eraser.isTracking()) { - eraser.start(); - } - } - }); - } - - public static void createAndAttach(@NonNull View view, @NonNull EditText editText) { - final LongClickEraser l = new LongClickEraser(view, editText); - view.setOnClickListener(l); - view.setOnTouchListener(l); - } - - private static void erase(@NonNull EditText editText) { - final int start = clampSelection(editText.getSelectionStart()); - final int end = clampSelection(editText.getSelectionEnd()); - if (start != end) { - editText.getText().delete(Math.min(start, end), Math.max(start, end)); - } else if (start > 0) { - editText.getText().delete(start - 1, start); - } - } - - public static int clampSelection(int selection) { - return selection < 0 ? 0 : selection; - } - - @SuppressLint("ClickableViewAccessibility") - @Override - public boolean onTouch(View v, MotionEvent event) { - switch (event.getAction()) { - case MotionEvent.ACTION_CANCEL: - case MotionEvent.ACTION_UP: - eraser.stopTracking(); - break; - default: - eraser.startTracking(); - gestureDetector.onTouchEvent(event); - break; - } - return false; - } - - @Override - public void onClick(View v) { - erase(editText); - v.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); - } - - private class Eraser implements Runnable { - private static final int DELAY = 300; - private long delay; - private boolean erasing; - private boolean tracking = true; - - @Override - public void run() { - erase(editText); - if (editText.length() == 0 || clampSelection(editText.getSelectionStart()) == 0) { - stop(); - return; - } - delay = Math.max(50, 2 * delay / 3); - view.postDelayed(this, delay); - } - - void start() { - if (erasing) { - stop(); - } - erasing = true; - delay = DELAY; - view.removeCallbacks(this); - view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); - run(); - } - - void stop() { - view.removeCallbacks(this); - if (!erasing) { - return; - } - - erasing = false; - } - - public void stopTracking() { - stop(); - tracking = false; - } - - public boolean isTracking() { - return tracking; - } - - public void startTracking() { - tracking = true; - } - } - } - } \ No newline at end of file diff --git a/app/src/main/java/org/solovyev/android/calculator/view/LongClickEraser.java b/app/src/main/java/org/solovyev/android/calculator/view/BaseLongClickEraser.java similarity index 66% rename from app/src/main/java/org/solovyev/android/calculator/view/LongClickEraser.java rename to app/src/main/java/org/solovyev/android/calculator/view/BaseLongClickEraser.java index 6c82d1b2..c5a9fe66 100644 --- a/app/src/main/java/org/solovyev/android/calculator/view/LongClickEraser.java +++ b/app/src/main/java/org/solovyev/android/calculator/view/BaseLongClickEraser.java @@ -5,17 +5,9 @@ import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import android.view.View; -import org.solovyev.android.calculator.App; -import org.solovyev.android.calculator.Calculator; -import org.solovyev.android.calculator.Editor; -import org.solovyev.android.calculator.EditorState; -import org.solovyev.android.calculator.Locator; - import javax.annotation.Nonnull; -import static android.text.TextUtils.isEmpty; - -public final class LongClickEraser implements View.OnTouchListener { +public abstract class BaseLongClickEraser implements View.OnTouchListener { @Nonnull private final View view; @@ -23,16 +15,10 @@ public final class LongClickEraser implements View.OnTouchListener { @Nonnull private final GestureDetector gestureDetector; - @Nonnull - private final Editor editor = App.getEditor(); - - @Nonnull - private final Calculator calculator = Locator.getInstance().getCalculator(); - @Nonnull private final Eraser eraser = new Eraser(); - private LongClickEraser(@Nonnull final View view) { + protected BaseLongClickEraser(@Nonnull final View view) { this.view = view; this.gestureDetector = new GestureDetector(view.getContext(), new GestureDetector.SimpleOnGestureListener() { public void onLongPress(MotionEvent e) { @@ -41,11 +27,7 @@ public final class LongClickEraser implements View.OnTouchListener { } } }); - } - - public static void createAndAttach(@Nonnull View view) { - final LongClickEraser l = new LongClickEraser(view); - view.setOnTouchListener(l); + this.view.setOnTouchListener(this); } @Override @@ -63,17 +45,21 @@ public final class LongClickEraser implements View.OnTouchListener { return false; } + protected abstract void onStopErase(); + + protected abstract void onStartErase(); + + protected abstract boolean erase(); + private class Eraser implements Runnable { private static final int DELAY = 300; private long delay; private boolean erasing; private boolean tracking = true; - private boolean wasCalculatingOnFly; @Override public void run() { - final EditorState state = editor.erase(); - if (isEmpty(state.text)) { + if (!erase()) { stop(); return; } @@ -89,10 +75,7 @@ public final class LongClickEraser implements View.OnTouchListener { delay = DELAY; view.removeCallbacks(this); view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); - wasCalculatingOnFly = calculator.isCalculateOnFly(); - if (wasCalculatingOnFly) { - calculator.setCalculateOnFly(false); - } + onStartErase(); run(); } @@ -103,9 +86,7 @@ public final class LongClickEraser implements View.OnTouchListener { } erasing = false; - if (wasCalculatingOnFly) { - calculator.setCalculateOnFly(true); - } + onStopErase(); } public void stopTracking() { diff --git a/app/src/main/java/org/solovyev/android/calculator/view/DragListenerVibrator.java b/app/src/main/java/org/solovyev/android/calculator/view/DragListenerVibrator.java deleted file mode 100644 index 0058b981..00000000 --- a/app/src/main/java/org/solovyev/android/calculator/view/DragListenerVibrator.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2013 serso aka se.solovyev - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * Contact details - * - * Email: se.solovyev@gmail.com - * Site: http://se.solovyev.org - */ - -package org.solovyev.android.calculator.view; - -import android.content.SharedPreferences; -import android.os.Vibrator; - -import org.solovyev.android.views.dragbutton.DragButton; -import org.solovyev.android.views.dragbutton.DragEvent; -import org.solovyev.android.views.dragbutton.DragListener; -import org.solovyev.android.views.dragbutton.DragListenerWrapper; -import org.solovyev.android.view.VibratorContainer; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * User: serso - * Date: 4/20/12 - * Time: 3:27 PM - */ -public class DragListenerVibrator extends DragListenerWrapper { - - private static final float VIBRATION_TIME_SCALE = 0.5f; - - @Nonnull - private final VibratorContainer vibrator; - - public DragListenerVibrator(@Nonnull DragListener dragListener, - @Nullable Vibrator vibrator, - @Nonnull SharedPreferences preferences) { - super(dragListener); - this.vibrator = new VibratorContainer(vibrator, preferences, VIBRATION_TIME_SCALE); - } - - @Override - public boolean onDrag(@Nonnull DragButton dragButton, @Nonnull DragEvent event) { - boolean consumed = super.onDrag(dragButton, event); - - if (consumed) { - vibrator.vibrate(); - } - - return consumed; - } -} 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 new file mode 100644 index 00000000..4b03fee1 --- /dev/null +++ b/app/src/main/java/org/solovyev/android/calculator/view/EditTextLongClickEraser.java @@ -0,0 +1,54 @@ +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; + +public class EditTextLongClickEraser extends BaseLongClickEraser implements View.OnClickListener { + @Nonnull + private final EditText editView; + + private EditTextLongClickEraser(@Nonnull View view, @Nonnull EditText editView) { + super(view); + this.editView = editView; + view.setOnClickListener(this); + } + + public static void attachTo(@Nonnull View view, @Nonnull EditText editView) { + new EditTextLongClickEraser(view, editView); + } + + @Override + protected void onStopErase() { + + } + + @Override + protected void onStartErase() { + + } + + @Override + protected boolean erase() { + final int start = editView.getSelectionStart(); + final int end = editView.getSelectionEnd(); + if (start < 0 || end < 0) { + return false; + } + final Editable text = editView.getText(); + if (start != end) { + text.delete(Math.min(start, end), Math.max(start, end)); + } else if (start > 0) { + text.delete(start - 1, start); + } + return text.length() != 0; + } + @Override + public void onClick(View v) { + erase(); + v.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); + } +} 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 new file mode 100644 index 00000000..8e9d489f --- /dev/null +++ b/app/src/main/java/org/solovyev/android/calculator/view/EditorLongClickEraser.java @@ -0,0 +1,47 @@ +package org.solovyev.android.calculator.view; + +import android.view.View; +import org.solovyev.android.calculator.*; + +import javax.annotation.Nonnull; + +import static android.text.TextUtils.isEmpty; + +public class EditorLongClickEraser extends BaseLongClickEraser { + + @Nonnull + private final Editor editor = App.getEditor(); + + @Nonnull + private final Calculator calculator = Locator.getInstance().getCalculator(); + + private boolean wasCalculatingOnFly; + + private EditorLongClickEraser(@Nonnull View view) { + super(view); + } + + public static void attachTo(@Nonnull View view) { + new EditorLongClickEraser(view); + } + + protected boolean erase() { + final EditorState state = editor.erase(); + return !isEmpty(state.text); + } + + @Override + protected void onStartErase() { + wasCalculatingOnFly = calculator.isCalculateOnFly(); + if (wasCalculatingOnFly) { + calculator.setCalculateOnFly(false); + } + } + + @Override + protected void onStopErase() { + if (wasCalculatingOnFly) { + calculator.setCalculateOnFly(true); + } + } +}