LongClickEraser generalized
This commit is contained in:
parent
a18f3210c3
commit
bbaedc71c9
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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() {
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user