diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index 4975d6540..cced45d9f 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -131,6 +131,12 @@
+
+
+
+
+
+
diff --git a/java/res/values/config.xml b/java/res/values/config.xml
index 54a6687a3..8477df054 100644
--- a/java/res/values/config.xml
+++ b/java/res/values/config.xml
@@ -50,6 +50,9 @@
-->
70
200
+ 100
+ 1000
+ 20
diff --git a/java/res/values/styles.xml b/java/res/values/styles.xml
index ae67c4369..e5e7fed80 100644
--- a/java/res/values/styles.xml
+++ b/java/res/values/styles.xml
@@ -78,6 +78,9 @@
- @android:color/white
- @dimen/gesture_floating_preview_text_connector_width
- @integer/config_gesture_floating_preview_text_linger_timeout
+ - @integer/config_gesture_preview_trail_fadeout_start_delay
+ - @integer/config_gesture_preview_trail_fadeout_duration
+ - @integer/config_gesture_preview_trail_update_interval
- @android:color/holo_blue_light
- @dimen/gesture_preview_trail_width
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 67f37a7e7..b5b3ef65f 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -17,14 +17,13 @@
package com.android.inputmethod.keyboard;
import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Paint;
import android.os.SystemClock;
import android.util.Log;
import android.view.MotionEvent;
import com.android.inputmethod.accessibility.AccessibilityUtils;
import com.android.inputmethod.keyboard.internal.GestureStroke;
+import com.android.inputmethod.keyboard.internal.GestureStrokeWithPreviewTrail;
import com.android.inputmethod.keyboard.internal.PointerTrackerQueue;
import com.android.inputmethod.latin.CollectionUtils;
import com.android.inputmethod.latin.InputPointers;
@@ -211,7 +210,7 @@ public class PointerTracker implements PointerTrackerQueue.Element {
private static final KeyboardActionListener EMPTY_LISTENER =
new KeyboardActionListener.Adapter();
- private final GestureStroke mGestureStroke;
+ private final GestureStrokeWithPreviewTrail mGestureStrokeWithPreviewTrail;
public static void init(boolean hasDistinctMultitouch,
boolean needsPhantomSuddenMoveEventHack) {
@@ -297,7 +296,8 @@ public class PointerTracker implements PointerTrackerQueue.Element {
final int trackersSize = sTrackers.size();
for (int i = 0; i < trackersSize; ++i) {
final PointerTracker tracker = sTrackers.get(i);
- tracker.mGestureStroke.appendIncrementalBatchPoints(sAggregratedPointers);
+ tracker.mGestureStrokeWithPreviewTrail.appendIncrementalBatchPoints(
+ sAggregratedPointers);
}
return sAggregratedPointers;
}
@@ -308,7 +308,7 @@ public class PointerTracker implements PointerTrackerQueue.Element {
final int trackersSize = sTrackers.size();
for (int i = 0; i < trackersSize; ++i) {
final PointerTracker tracker = sTrackers.get(i);
- tracker.mGestureStroke.appendAllBatchPoints(sAggregratedPointers);
+ tracker.mGestureStrokeWithPreviewTrail.appendAllBatchPoints(sAggregratedPointers);
}
return sAggregratedPointers;
}
@@ -319,7 +319,7 @@ public class PointerTracker implements PointerTrackerQueue.Element {
final int trackersSize = sTrackers.size();
for (int i = 0; i < trackersSize; ++i) {
final PointerTracker tracker = sTrackers.get(i);
- tracker.mGestureStroke.reset();
+ tracker.mGestureStrokeWithPreviewTrail.reset();
}
sAggregratedPointers.reset();
}
@@ -329,7 +329,7 @@ public class PointerTracker implements PointerTrackerQueue.Element {
throw new NullPointerException();
}
mPointerId = id;
- mGestureStroke = new GestureStroke(id);
+ mGestureStrokeWithPreviewTrail = new GestureStrokeWithPreviewTrail(id);
setKeyDetectorInner(handler.getKeyDetector());
mListener = handler.getKeyboardActionListener();
mDrawingProxy = handler.getDrawingProxy();
@@ -429,7 +429,7 @@ public class PointerTracker implements PointerTrackerQueue.Element {
mKeyDetector = keyDetector;
mKeyboard = keyDetector.getKeyboard();
mIsAlphabetKeyboard = mKeyboard.mId.isAlphabetKeyboard();
- mGestureStroke.setGestureSampleLength(mKeyboard.mMostCommonKeyWidth);
+ mGestureStrokeWithPreviewTrail.setGestureSampleLength(mKeyboard.mMostCommonKeyWidth);
final Key newKey = mKeyDetector.detectHitKey(mKeyX, mKeyY);
if (newKey != mCurrentKey) {
if (mDrawingProxy != null) {
@@ -539,10 +539,8 @@ public class PointerTracker implements PointerTrackerQueue.Element {
mDrawingProxy.invalidateKey(key);
}
- public void drawGestureTrail(final Canvas canvas, final Paint paint) {
- if (mInGesture) {
- mGestureStroke.drawGestureTrail(canvas, paint);
- }
+ public GestureStrokeWithPreviewTrail getGestureStrokeWithPreviewTrail() {
+ return mGestureStrokeWithPreviewTrail;
}
public int getLastX() {
@@ -692,7 +690,7 @@ public class PointerTracker implements PointerTrackerQueue.Element {
mIsPossibleGesture = true;
// TODO: pointer times should be relative to first down even in entire batch input
// instead of resetting to 0 for each new down event.
- mGestureStroke.addPoint(x, y, 0, false);
+ mGestureStrokeWithPreviewTrail.addPoint(x, y, 0, false);
}
}
}
@@ -733,7 +731,7 @@ public class PointerTracker implements PointerTrackerQueue.Element {
final long eventTime, final boolean isHistorical, final Key key) {
final int gestureTime = (int)(eventTime - tracker.getDownTime());
if (sShouldHandleGesture && mIsPossibleGesture) {
- final GestureStroke stroke = mGestureStroke;
+ final GestureStroke stroke = mGestureStrokeWithPreviewTrail;
stroke.addPoint(x, y, gestureTime, isHistorical);
if (!mInGesture && stroke.isStartOfAGesture()) {
startBatchInput();
diff --git a/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java b/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java
new file mode 100644
index 000000000..edc20998f
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package com.android.inputmethod.keyboard.internal;
+
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.os.SystemClock;
+
+import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.ResizableIntArray;
+
+class GesturePreviewTrail {
+ private static final int DEFAULT_CAPACITY = GestureStrokeWithPreviewTrail.PREVIEW_CAPACITY;
+
+ private final GesturePreviewTrailParams mPreviewParams;
+ private final ResizableIntArray mXCoordinates = new ResizableIntArray(DEFAULT_CAPACITY);
+ private final ResizableIntArray mYCoordinates = new ResizableIntArray(DEFAULT_CAPACITY);
+ private final ResizableIntArray mEventTimes = new ResizableIntArray(DEFAULT_CAPACITY);
+ private int mCurrentStrokeId;
+ private long mCurrentDownTime;
+
+ // Use this value as imaginary zero because x-coordinates may be zero.
+ private static final int DOWN_EVENT_MARKER = -128;
+
+ static class GesturePreviewTrailParams {
+ public final int mFadeoutStartDelay;
+ public final int mFadeoutDuration;
+ public final int mUpdateInterval;
+
+ public GesturePreviewTrailParams(final TypedArray keyboardViewAttr) {
+ mFadeoutStartDelay = keyboardViewAttr.getInt(
+ R.styleable.KeyboardView_gesturePreviewTrailFadeoutStartDelay, 0);
+ mFadeoutDuration = keyboardViewAttr.getInt(
+ R.styleable.KeyboardView_gesturePreviewTrailFadeoutDuration, 0);
+ mUpdateInterval = keyboardViewAttr.getInt(
+ R.styleable.KeyboardView_gesturePreviewTrailUpdateInterval, 0);
+ }
+ }
+
+ public GesturePreviewTrail(final GesturePreviewTrailParams params) {
+ mPreviewParams = params;
+ }
+
+ private static int markAsDownEvent(final int xCoord) {
+ return DOWN_EVENT_MARKER - xCoord;
+ }
+
+ private static boolean isDownEventXCoord(final int xCoordOrMark) {
+ return xCoordOrMark <= DOWN_EVENT_MARKER;
+ }
+
+ private static int getXCoordValue(final int xCoordOrMark) {
+ return isDownEventXCoord(xCoordOrMark)
+ ? DOWN_EVENT_MARKER - xCoordOrMark : xCoordOrMark;
+ }
+
+ public void addStroke(final GestureStrokeWithPreviewTrail stroke, final long downTime) {
+ final int strokeId = stroke.getGestureStrokeId();
+ final boolean isNewStroke = strokeId != mCurrentStrokeId;
+ final int trailSize = mEventTimes.getLength();
+ stroke.appendPreviewStroke(mEventTimes, mXCoordinates, mYCoordinates);
+ final int newTrailSize = mEventTimes.getLength();
+ if (stroke.getGestureStrokePreviewSize() == 0) {
+ return;
+ }
+ if (isNewStroke) {
+ final int elapsedTime = (int)(downTime - mCurrentDownTime);
+ final int[] eventTimes = mEventTimes.getPrimitiveArray();
+ for (int i = 0; i < trailSize; i++) {
+ eventTimes[i] -= elapsedTime;
+ }
+
+ if (newTrailSize > trailSize) {
+ final int[] xCoords = mXCoordinates.getPrimitiveArray();
+ xCoords[trailSize] = markAsDownEvent(xCoords[trailSize]);
+ }
+ mCurrentDownTime = downTime;
+ mCurrentStrokeId = strokeId;
+ }
+ }
+
+ private int getAlpha(final int elapsedTime) {
+ if (elapsedTime < mPreviewParams.mFadeoutStartDelay) {
+ return Constants.Color.ALPHA_OPAQUE;
+ }
+ final int decreasingAlpha = Constants.Color.ALPHA_OPAQUE
+ * (elapsedTime - mPreviewParams.mFadeoutStartDelay)
+ / mPreviewParams.mFadeoutDuration;
+ return Constants.Color.ALPHA_OPAQUE - decreasingAlpha;
+ }
+
+ /**
+ * Draw gesture preview trail
+ * @param canvas The canvas to draw the gesture preview trail
+ * @param paint The paint object to be used to draw the gesture preview trail
+ * @return true if some gesture preview trails remain to be drawn
+ */
+ public boolean drawGestureTrail(final Canvas canvas, final Paint paint) {
+ final int trailSize = mEventTimes.getLength();
+ if (trailSize == 0) {
+ return false;
+ }
+
+ final int[] eventTimes = mEventTimes.getPrimitiveArray();
+ final int[] xCoords = mXCoordinates.getPrimitiveArray();
+ final int[] yCoords = mYCoordinates.getPrimitiveArray();
+ final int sinceDown = (int)(SystemClock.uptimeMillis() - mCurrentDownTime);
+ final int lingeringDuration = mPreviewParams.mFadeoutStartDelay
+ + mPreviewParams.mFadeoutDuration;
+ int startIndex;
+ for (startIndex = 0; startIndex < trailSize; startIndex++) {
+ final int elapsedTime = sinceDown - eventTimes[startIndex];
+ // Skip too old trail points.
+ if (elapsedTime < lingeringDuration) {
+ break;
+ }
+ }
+
+ if (startIndex < trailSize) {
+ int lastX = getXCoordValue(xCoords[startIndex]);
+ int lastY = yCoords[startIndex];
+ for (int i = startIndex + 1; i < trailSize - 1; i++) {
+ final int x = xCoords[i];
+ final int y = yCoords[i];
+ final int elapsedTime = sinceDown - eventTimes[i];
+ // Draw trail line only when the current point isn't a down point.
+ if (!isDownEventXCoord(x)) {
+ paint.setAlpha(getAlpha(elapsedTime));
+ canvas.drawLine(lastX, lastY, x, y, paint);
+ }
+ lastX = getXCoordValue(x);
+ lastY = y;
+ }
+ }
+
+ // TODO: Implement ring buffer to avoid moving points.
+ // Discard faded out points.
+ final int newSize = trailSize - startIndex;
+ System.arraycopy(eventTimes, startIndex, eventTimes, 0, newSize);
+ System.arraycopy(xCoords, startIndex, xCoords, 0, newSize);
+ System.arraycopy(yCoords, startIndex, yCoords, 0, newSize);
+ mEventTimes.setLength(newSize);
+ mXCoordinates.setLength(newSize);
+ mYCoordinates.setLength(newSize);
+ return newSize > 0;
+ }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java b/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java
index 79e977a40..292842d22 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java
@@ -14,10 +14,6 @@
package com.android.inputmethod.keyboard.internal;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-
-import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.InputPointers;
import com.android.inputmethod.latin.ResizableIntArray;
@@ -48,13 +44,8 @@ public class GestureStroke {
private static final float DOUBLE_PI = (float)(2.0f * Math.PI);
- // Fade based on number of gesture samples, see MIN_GESTURE_SAMPLING_RATIO_TO_KEY_HEIGHT
- private static final int DRAWING_GESTURE_FADE_START = 10;
- private static final int DRAWING_GESTURE_FADE_RATE = 6;
-
- public GestureStroke(int pointerId) {
+ public GestureStroke(final int pointerId) {
mPointerId = pointerId;
- reset();
}
public void setGestureSampleLength(final int keyWidth) {
@@ -158,7 +149,7 @@ public class GestureStroke {
if (dx == 0 && dy == 0) return 0;
// Would it be faster to call atan2f() directly via JNI? Not sure about what the JIT
// does with Math.atan2().
- return (float)Math.atan2((double)dy, (double)dx);
+ return (float)Math.atan2(dy, dx);
}
private static float getAngleDiff(final float a1, final float a2) {
@@ -168,20 +159,4 @@ public class GestureStroke {
}
return diff;
}
-
- public void drawGestureTrail(final Canvas canvas, final Paint paint) {
- // TODO: These paint parameter interpolation should be tunable, possibly introduce an object
- // that implements an interface such as Paint getPaint(int step, int strokePoints)
- final int size = mXCoordinates.getLength();
- final int[] xCoords = mXCoordinates.getPrimitiveArray();
- final int[] yCoords = mYCoordinates.getPrimitiveArray();
- int alpha = Constants.Color.ALPHA_OPAQUE;
- for (int i = size - 1; i > 0 && alpha > 0; i--) {
- paint.setAlpha(alpha);
- if (size - i > DRAWING_GESTURE_FADE_START) {
- alpha -= DRAWING_GESTURE_FADE_RATE;
- }
- canvas.drawLine(xCoords[i - 1], yCoords[i - 1], xCoords[i], yCoords[i], paint);
- }
- }
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewTrail.java b/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewTrail.java
new file mode 100644
index 000000000..6c1a9bc01
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewTrail.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package com.android.inputmethod.keyboard.internal;
+
+import com.android.inputmethod.latin.ResizableIntArray;
+
+public class GestureStrokeWithPreviewTrail extends GestureStroke {
+ public static final int PREVIEW_CAPACITY = 256;
+
+ private final ResizableIntArray mPreviewEventTimes = new ResizableIntArray(PREVIEW_CAPACITY);
+ private final ResizableIntArray mPreviewXCoordinates = new ResizableIntArray(PREVIEW_CAPACITY);
+ private final ResizableIntArray mPreviewYCoordinates = new ResizableIntArray(PREVIEW_CAPACITY);
+
+ private int mStrokeId;
+ private int mLastPreviewSize;
+
+ public GestureStrokeWithPreviewTrail(final int pointerId) {
+ super(pointerId);
+ }
+
+ @Override
+ public void reset() {
+ super.reset();
+ mStrokeId++;
+ mLastPreviewSize = 0;
+ mPreviewEventTimes.setLength(0);
+ mPreviewXCoordinates.setLength(0);
+ mPreviewYCoordinates.setLength(0);
+ }
+
+ public int getGestureStrokeId() {
+ return mStrokeId;
+ }
+
+ public int getGestureStrokePreviewSize() {
+ return mPreviewEventTimes.getLength();
+ }
+
+ @Override
+ public void addPoint(final int x, final int y, final int time, final boolean isHistorical) {
+ super.addPoint(x, y, time, isHistorical);
+ mPreviewEventTimes.add(time);
+ mPreviewXCoordinates.add(x);
+ mPreviewYCoordinates.add(y);
+ }
+
+ public void appendPreviewStroke(final ResizableIntArray eventTimes,
+ final ResizableIntArray xCoords, final ResizableIntArray yCoords) {
+ final int length = mPreviewEventTimes.getLength() - mLastPreviewSize;
+ if (length <= 0) {
+ return;
+ }
+ eventTimes.append(mPreviewEventTimes, mLastPreviewSize, length);
+ xCoords.append(mPreviewXCoordinates, mLastPreviewSize, length);
+ yCoords.append(mPreviewYCoordinates, mLastPreviewSize, length);
+ mLastPreviewSize = mPreviewEventTimes.getLength();
+ }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java b/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java
index 3f33aee5a..269b202b5 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java
@@ -28,6 +28,7 @@ import android.util.SparseArray;
import android.widget.RelativeLayout;
import com.android.inputmethod.keyboard.PointerTracker;
+import com.android.inputmethod.keyboard.internal.GesturePreviewTrail.GesturePreviewTrailParams;
import com.android.inputmethod.latin.CollectionUtils;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
@@ -48,7 +49,9 @@ public class PreviewPlacerView extends RelativeLayout {
private int mXOrigin;
private int mYOrigin;
- private final SparseArray mPointers = CollectionUtils.newSparseArray();
+ private final SparseArray mGesturePreviewTrails =
+ CollectionUtils.newSparseArray();
+ private final GesturePreviewTrailParams mGesturePreviewTrailParams;
private String mGestureFloatingPreviewText;
private int mLastPointerX;
@@ -57,23 +60,31 @@ public class PreviewPlacerView extends RelativeLayout {
private boolean mDrawsGesturePreviewTrail;
private boolean mDrawsGestureFloatingPreviewText;
- private final DrawingHandler mDrawingHandler = new DrawingHandler(this);
+ private final DrawingHandler mDrawingHandler;
private static class DrawingHandler extends StaticInnerHandlerWrapper {
private static final int MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 0;
+ private static final int MSG_UPDATE_GESTURE_PREVIEW_TRAIL = 1;
- public DrawingHandler(PreviewPlacerView outerInstance) {
+ private final GesturePreviewTrailParams mGesturePreviewTrailParams;
+
+ public DrawingHandler(final PreviewPlacerView outerInstance,
+ final GesturePreviewTrailParams gesturePreviewTrailParams) {
super(outerInstance);
+ mGesturePreviewTrailParams = gesturePreviewTrailParams;
}
@Override
- public void handleMessage(Message msg) {
+ public void handleMessage(final Message msg) {
final PreviewPlacerView placerView = getOuterInstance();
if (placerView == null) return;
switch (msg.what) {
case MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT:
placerView.setGestureFloatingPreviewText(null);
break;
+ case MSG_UPDATE_GESTURE_PREVIEW_TRAIL:
+ placerView.invalidate();
+ break;
}
}
@@ -89,16 +100,27 @@ public class PreviewPlacerView extends RelativeLayout {
placerView.mGestureFloatingPreviewTextLingerTimeout);
}
+ private void cancelUpdateGestureTrailPreview() {
+ removeMessages(MSG_UPDATE_GESTURE_PREVIEW_TRAIL);
+ }
+
+ public void postUpdateGestureTrailPreview() {
+ cancelUpdateGestureTrailPreview();
+ sendMessageDelayed(obtainMessage(MSG_UPDATE_GESTURE_PREVIEW_TRAIL),
+ mGesturePreviewTrailParams.mUpdateInterval);
+ }
+
public void cancelAllMessages() {
cancelDismissGestureFloatingPreviewText();
+ cancelUpdateGestureTrailPreview();
}
}
- public PreviewPlacerView(Context context, AttributeSet attrs) {
+ public PreviewPlacerView(final Context context, final AttributeSet attrs) {
this(context, attrs, R.attr.keyboardViewStyle);
}
- public PreviewPlacerView(Context context, AttributeSet attrs, int defStyle) {
+ public PreviewPlacerView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context);
setWillNotDraw(false);
@@ -128,8 +150,11 @@ public class PreviewPlacerView extends RelativeLayout {
R.styleable.KeyboardView_gesturePreviewTrailColor, 0);
final int gesturePreviewTrailWidth = keyboardViewAttr.getDimensionPixelSize(
R.styleable.KeyboardView_gesturePreviewTrailWidth, 0);
+ mGesturePreviewTrailParams = new GesturePreviewTrailParams(keyboardViewAttr);
keyboardViewAttr.recycle();
+ mDrawingHandler = new DrawingHandler(this, mGesturePreviewTrailParams);
+
mGesturePaint = new Paint();
mGesturePaint.setAntiAlias(true);
mGesturePaint.setStyle(Paint.Style.STROKE);
@@ -144,21 +169,28 @@ public class PreviewPlacerView extends RelativeLayout {
mTextPaint.setTextSize(gestureFloatingPreviewTextSize);
}
- public void setOrigin(int x, int y) {
+ public void setOrigin(final int x, final int y) {
mXOrigin = x;
mYOrigin = y;
}
- public void setGesturePreviewMode(boolean drawsGesturePreviewTrail,
- boolean drawsGestureFloatingPreviewText) {
+ public void setGesturePreviewMode(final boolean drawsGesturePreviewTrail,
+ final boolean drawsGestureFloatingPreviewText) {
mDrawsGesturePreviewTrail = drawsGesturePreviewTrail;
mDrawsGestureFloatingPreviewText = drawsGestureFloatingPreviewText;
}
- public void invalidatePointer(PointerTracker tracker) {
- synchronized (mPointers) {
- mPointers.put(tracker.mPointerId, tracker);
+ public void invalidatePointer(final PointerTracker tracker) {
+ GesturePreviewTrail trail;
+ synchronized (mGesturePreviewTrails) {
+ trail = mGesturePreviewTrails.get(tracker.mPointerId);
+ if (trail == null) {
+ trail = new GesturePreviewTrail(mGesturePreviewTrailParams);
+ mGesturePreviewTrails.put(tracker.mPointerId, trail);
+ }
}
+ trail.addStroke(tracker.getGestureStrokeWithPreviewTrail(), tracker.getDownTime());
+
mLastPointerX = tracker.getLastX();
mLastPointerY = tracker.getLastY();
// TODO: Should narrow the invalidate region.
@@ -166,17 +198,23 @@ public class PreviewPlacerView extends RelativeLayout {
}
@Override
- public void onDraw(Canvas canvas) {
+ public void onDraw(final Canvas canvas) {
super.onDraw(canvas);
canvas.translate(mXOrigin, mYOrigin);
if (mDrawsGesturePreviewTrail) {
- synchronized (mPointers) {
- final int trackerCount = mPointers.size();
- for (int index = 0; index < trackerCount; index++) {
- final PointerTracker tracker = mPointers.valueAt(index);
- tracker.drawGestureTrail(canvas, mGesturePaint);
+ boolean needsUpdatingGesturePreviewTrail = false;
+ synchronized (mGesturePreviewTrails) {
+ // Trails count == fingers count that have ever been active.
+ final int trailsCount = mGesturePreviewTrails.size();
+ for (int index = 0; index < trailsCount; index++) {
+ final GesturePreviewTrail trail = mGesturePreviewTrails.valueAt(index);
+ needsUpdatingGesturePreviewTrail |=
+ trail.drawGestureTrail(canvas, mGesturePaint);
}
}
+ if (needsUpdatingGesturePreviewTrail) {
+ mDrawingHandler.postUpdateGestureTrailPreview();
+ }
}
if (mDrawsGestureFloatingPreviewText) {
drawGestureFloatingPreviewText(canvas, mGestureFloatingPreviewText);
@@ -184,7 +222,7 @@ public class PreviewPlacerView extends RelativeLayout {
canvas.translate(-mXOrigin, -mYOrigin);
}
- public void setGestureFloatingPreviewText(String gestureFloatingPreviewText) {
+ public void setGestureFloatingPreviewText(final String gestureFloatingPreviewText) {
mGestureFloatingPreviewText = gestureFloatingPreviewText;
invalidate();
}
@@ -197,7 +235,8 @@ public class PreviewPlacerView extends RelativeLayout {
mDrawingHandler.cancelAllMessages();
}
- private void drawGestureFloatingPreviewText(Canvas canvas, String gestureFloatingPreviewText) {
+ private void drawGestureFloatingPreviewText(final Canvas canvas,
+ final String gestureFloatingPreviewText) {
if (TextUtils.isEmpty(gestureFloatingPreviewText)) {
return;
}