Merge change 1831 into donut
* changes:
Tear down data, if a disconnect request is pending.
diff --git a/tests/sketch/AndroidManifest.xml b/tests/sketch/AndroidManifest.xml
index 1f4333c..c44b54e 100755
--- a/tests/sketch/AndroidManifest.xml
+++ b/tests/sketch/AndroidManifest.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008-2009 The Android Open Source Project
+<!-- Copyright (C) 2008 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.
@@ -14,12 +14,11 @@
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.gesture.example"
+ package="com.android.gesture"
android:versionCode="1"
android:versionName="1.0.0">
- <uses-permission android:name="android.permission.READ_CONTACTS" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
- <activity android:name="com.android.gesture.example.GestureEntry"
+ <activity android:name="com.android.gesture.example.GestureEntryDemo"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -27,12 +26,5 @@
</intent-filter>
</activity>
<activity android:name="com.android.gesture.example.GestureLibViewer"/>
- <activity android:name="com.android.gesture.example.ContactListGestureOverlay"
- android:label="@string/overlay_name">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
</application>
</manifest>
diff --git a/tests/sketch/res/layout/demo.xml b/tests/sketch/res/layout/demo.xml
old mode 100644
new mode 100755
index 8c9161a..e516229
--- a/tests/sketch/res/layout/demo.xml
+++ b/tests/sketch/res/layout/demo.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2008 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.
@@ -13,7 +13,6 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
@@ -25,7 +24,7 @@
android:drawSelectorOnTop="true"
android:prompt="@string/recognition_result"/>
- <com.android.gesture.GestureOverlay
+ <com.android.gesture.GesturePad
android:id="@+id/drawingpad"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
diff --git a/tests/sketch/res/layout/gestureviewer.xml b/tests/sketch/res/layout/gestureviewer.xml
old mode 100644
new mode 100755
index 73d6a35..5302d34
--- a/tests/sketch/res/layout/gestureviewer.xml
+++ b/tests/sketch/res/layout/gestureviewer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2008 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.
@@ -13,7 +13,6 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
@@ -26,7 +25,7 @@
android:drawSelectorOnTop="true"
android:prompt="@string/recognition_result"/>
- <com.android.gesture.GestureOverlay
+ <com.android.gesture.GesturePad
android:id="@+id/drawingpad"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
diff --git a/tests/sketch/res/layout/newgesture_dialog.xml b/tests/sketch/res/layout/newgesture_dialog.xml
old mode 100644
new mode 100755
index 91e7645..6e45d81
--- a/tests/sketch/res/layout/newgesture_dialog.xml
+++ b/tests/sketch/res/layout/newgesture_dialog.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2008 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.
diff --git a/tests/sketch/res/layout/overlaydemo.xml b/tests/sketch/res/layout/overlaydemo.xml
deleted file mode 100644
index b6bbab3..0000000
--- a/tests/sketch/res/layout/overlaydemo.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- >
- <ListView
- android:id="@+id/list"
- android:layout_width="fill_parent"
- android:layout_height="0dip"
- android:layout_weight="1"/>
-</LinearLayout>
diff --git a/tests/sketch/res/values/strings.xml b/tests/sketch/res/values/strings.xml
index 42f14da..4c6aa20 100755
--- a/tests/sketch/res/values/strings.xml
+++ b/tests/sketch/res/values/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2008 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.
@@ -15,7 +15,6 @@
-->
<resources>
<string name="app_name">Gesture Demo</string>
- <string name="overlay_name">Overlay Demo</string>
<string name="recognition_result">Recognition Result</string>
<string name="clear">Clear</string>
<string name="newgesture">Add</string>
diff --git a/tests/sketch/src/com/android/gesture/Gesture.java b/tests/sketch/src/com/android/gesture/Gesture.java
index a5e7a25..29c07ad 100755
--- a/tests/sketch/src/com/android/gesture/Gesture.java
+++ b/tests/sketch/src/com/android/gesture/Gesture.java
@@ -18,290 +18,343 @@
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
+import android.graphics.PointF;
import android.graphics.RectF;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.gesture.recognizer.RecognitionUtil;
+
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.StringTokenizer;
/**
- * A gesture can have a single or multiple strokes
+ * A single stroke gesture.
*/
public class Gesture implements Parcelable {
- private static final long GESTURE_ID_BASE = System.currentTimeMillis();
-
- private static final int BITMAP_RENDERING_WIDTH = 2;
-
- private static final boolean BITMAP_RENDERING_ANTIALIAS = true;
-
- private static final boolean BITMAP_RENDERING_DITHER = true;
-
- private static int sGestureCount = 0;
-
- private RectF mBoundingBox;
-
- // the same as its instance ID
- private long mGestureID;
-
- private ArrayList<GestureStroke> mStrokes = new ArrayList<GestureStroke>();
+ private RectF mBBX;
+ private float mLength = 0;
+ private int mColor;
+ private float mWidth;
+ private ArrayList<PointF> mPtsBuffer = new ArrayList<PointF>();
+ private long mTimestamp = 0;
+ private long mID;
+
+ private static final long systemStartupTime = System.currentTimeMillis();
+ private static int instanceCount = 0;
public Gesture() {
- mGestureID = GESTURE_ID_BASE + sGestureCount++;
+ mID = systemStartupTime + instanceCount++;
}
- /**
- * @return all the strokes of the gesture
- */
- public ArrayList<GestureStroke> getStrokes() {
- return mStrokes;
+ public void setColor(int c) {
+ mColor = c;
+ }
+
+ public void setStrokeWidth(float w) {
+ mWidth = w;
+ }
+
+ public int getColor() {
+ return mColor;
+ }
+
+ public float getStrokeWidth() {
+ return mWidth;
+ }
+
+ public ArrayList<PointF> getPoints() {
+ return this.mPtsBuffer;
+ }
+
+ public int numOfPoints() {
+ return this.mPtsBuffer.size();
}
- /**
- * @return the number of strokes included by this gesture
- */
- public int getStrokesCount() {
- return mStrokes.size();
- }
-
- /**
- * Add a stroke to the gesture
- *
- * @param stroke
- */
- public void addStroke(GestureStroke stroke) {
- mStrokes.add(stroke);
-
- if (mBoundingBox == null) {
- mBoundingBox = new RectF(stroke.boundingBox);
- } else {
- mBoundingBox.union(stroke.boundingBox);
+ public void addPoint(float x, float y) {
+ mPtsBuffer.add(new PointF(x, y));
+ if (mBBX == null) {
+ mBBX = new RectF();
+ mBBX.top = y;
+ mBBX.left = x;
+ mBBX.right = x;
+ mBBX.bottom = y;
+ mLength = 0;
}
+ else {
+ PointF lst = mPtsBuffer.get(mPtsBuffer.size()-2);
+ mLength += Math.sqrt(Math.pow(x-lst.x, 2)+Math.pow(y-lst.y, 2));
+ mBBX.union(x, y);
+ }
+ mTimestamp = System.currentTimeMillis();
}
/**
- * Get the total length of the gesture. When there are multiple strokes in
- * the gesture, this returns the sum of the lengths of all the strokes
- *
* @return the length of the gesture
*/
public float getLength() {
- int len = 0;
- ArrayList<GestureStroke> strokes = mStrokes;
- int count = strokes.size();
- for (int i = 0; i < count; i++) {
- GestureStroke stroke = strokes.get(i);
- len += stroke.length;
- }
- return len;
+ return this.mLength;
}
-
- /**
- * @return the bounding box of the gesture
- */
- public RectF getBoundingBox() {
- return mBoundingBox;
+
+ public RectF getBBX() {
+ return mBBX;
}
-
- /**
- * Set the id of the gesture
- *
- * @param id
- */
- void setID(long id) {
- mGestureID = id;
+
+ public void setID(long id) {
+ mID = id;
}
-
- /**
- * @return the id of the gesture
- */
+
public long getID() {
- return mGestureID;
+ return mID;
}
-
+
+ public long getTimeStamp() {
+ return mTimestamp;
+ }
+
+ public void setTimestamp(long t) {
+ this.mTimestamp = t;
+ }
+
/**
* draw the gesture
- *
* @param canvas
*/
- void draw(Canvas canvas, Paint paint) {
- ArrayList<GestureStroke> strokes = mStrokes;
- int count = strokes.size();
- for (int i = 0; i < count; i++) {
- GestureStroke stroke = strokes.get(i);
- stroke.draw(canvas, paint);
- }
- }
-
- /**
- * Create a bitmap of the gesture with a transparent background
- *
- * @param width width of the target bitmap
- * @param height height of the target bitmap
- * @param edge the edge
- * @param numSample
- * @param color
- * @return the bitmap
- */
- public Bitmap toBitmap(int width, int height, int edge, int numSample, int color) {
- RectF bbx = getBoundingBox();
- Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- canvas.translate(edge, edge);
+ public void draw(Canvas canvas) {
Paint paint = new Paint();
- paint.setAntiAlias(BITMAP_RENDERING_ANTIALIAS);
- paint.setDither(BITMAP_RENDERING_DITHER);
- paint.setColor(color);
+ paint.setAntiAlias(true);
+ paint.setDither(true);
+ paint.setColor(mColor);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
- paint.setStrokeWidth(BITMAP_RENDERING_WIDTH);
- ArrayList<GestureStroke> strokes = mStrokes;
- int count = strokes.size();
- for (int i = 0; i < count; i++) {
- GestureStroke stroke = strokes.get(i);
- Path path = stroke.toPath(width - 2 * edge, height - 2 * edge, numSample);
- canvas.drawPath(path, paint);
+ paint.setStrokeWidth(mWidth);
+
+ Path path = null;
+ float mX = 0, mY = 0;
+ Iterator<PointF> it = mPtsBuffer.iterator();
+ while (it.hasNext()) {
+ PointF p = it.next();
+ float x = p.x;
+ float y = p.y;
+ if (path == null) {
+ path = new Path();
+ path.moveTo(x, y);
+ mX = x;
+ mY = y;
+ } else {
+ float dx = Math.abs(x - mX);
+ float dy = Math.abs(y - mY);
+ if (dx >= 3 || dy >= 3) {
+ path.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
+ mX = x;
+ mY = y;
+ }
+ }
}
-
- return bitmap;
+
+ canvas.drawPath(path, paint);
}
-
+
/**
- * Create a bitmap of the gesture with a transparent background
- *
- * @param width
- * @param height
+ * convert the gesture to a Path
+ * @param width the width of the bounding box of the target path
+ * @param height the height of the bounding box of the target path
+ * @param numSample the num of points needed
+ * @return the path
+ */
+ public Path toPath(float width, float height, int numSample) {
+ float[] pts = RecognitionUtil.resample(this, numSample);
+ RectF rect = this.getBBX();
+ float scale = height / rect.height();
+ Matrix matrix = new Matrix();
+ matrix.setTranslate(-rect.left, -rect.top);
+ Matrix scalem = new Matrix();
+ scalem.setScale(scale, scale);
+ matrix.postConcat(scalem);
+ Matrix translate = new Matrix();
+ matrix.postConcat(translate);
+ matrix.mapPoints(pts);
+
+ Path path = null;
+ float mX = 0, mY = 0;
+ for (int i=0; i<pts.length-1; i+=2) {
+ float x = pts[i];
+ float y = pts[i+1];
+ if (path == null) {
+ path = new Path();
+ path.moveTo(x, y);
+ mX = x;
+ mY = y;
+ } else {
+ float dx = Math.abs(x - mX);
+ float dy = Math.abs(y - mY);
+ if (dx >= 3 || dy >= 3) {
+ path.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
+ mX = x;
+ mY = y;
+ }
+ }
+ }
+ return path;
+ }
+
+ /**
+ * get a bitmap thumbnail of the gesture with a transparent background
+ * @param w
+ * @param h
* @param edge
- * @param color
- * @return the bitmap
+ * @param numSample
+ * @param foreground
+ * @return
*/
- public Bitmap toBitmap(int width, int height, int edge, int color) {
- RectF bbx = getBoundingBox();
- Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- canvas.translate(edge, edge);
+ public Bitmap toBitmap(int w, int h,
+ int edge, int numSample) {
+ RectF bbx = this.getBBX();
+ Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+ Path path = this.toPath(w - 2 * edge, h - 2 * edge, numSample);
+ Canvas c = new Canvas(bitmap);
+ //c.drawColor(background);
+ c.translate(edge, edge);
Paint paint = new Paint();
- paint.setAntiAlias(BITMAP_RENDERING_ANTIALIAS);
- paint.setDither(BITMAP_RENDERING_DITHER);
- paint.setColor(color);
+ paint.setAntiAlias(true);
+ paint.setDither(true);
+ paint.setColor(mColor);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
- paint.setStrokeWidth(BITMAP_RENDERING_WIDTH);
- ArrayList<GestureStroke> strokes = mStrokes;
- int count = strokes.size();
- for (int i = 0; i < count; i++) {
- GestureStroke stroke = strokes.get(i);
- stroke.draw(canvas, paint);
- }
-
+ paint.setStrokeWidth(2);
+ c.drawPath(path, paint);
return bitmap;
}
-
+
/**
- * Save the gesture as XML
- *
+ * save the gesture as XML
* @param namespace
* @param serializer
* @throws IOException
*/
- void toXML(String namespace, XmlSerializer serializer) throws IOException {
- serializer.startTag(namespace, GestureConstants.XML_TAG_GESTURE);
- serializer.attribute(namespace, GestureConstants.XML_TAG_ID, Long.toString(mGestureID));
- ArrayList<GestureStroke> strokes = mStrokes;
- int count = strokes.size();
- for (int i = 0; i < count; i++) {
- GestureStroke stroke = strokes.get(i);
- stroke.toXML(namespace, serializer);
+ public void toXML(String namespace, XmlSerializer serializer) throws IOException {
+ serializer.startTag(namespace, "stroke");
+ serializer.attribute(namespace, "timestamp", Long.toString(mTimestamp));
+ serializer.attribute(namespace, "id", Long.toString(mID));
+ serializer.attribute(namespace, "color", Integer.toString(mColor));
+ serializer.attribute(namespace, "width", Float.toString(mWidth));
+ Iterator it = this.mPtsBuffer.iterator();
+ String pts = "";
+ while (it.hasNext()) {
+ PointF fp = (PointF)it.next();
+ if (pts.length() > 0)
+ pts += ",";
+ pts += fp.x + "," + fp.y;
}
- serializer.endTag(namespace, GestureConstants.XML_TAG_GESTURE);
+ serializer.text(pts);
+ serializer.endTag(namespace, "stroke");
}
-
- /**
- * Create the gesture from a string
- *
- * @param str
- */
+
+
public void createFromString(String str) {
- int startIndex = 0;
- int endIndex;
- while ((endIndex = str.indexOf(GestureConstants.STRING_GESTURE_DELIIMITER, startIndex + 1)) != -1) {
- String token = str.substring(startIndex, endIndex);
- if (startIndex > 0) { // stroke tokens
- addStroke(GestureStroke.createFromString(token));
- } else { // id token
- mGestureID = Long.parseLong(token);
- }
- startIndex = endIndex + 1;
+ StringTokenizer st = new StringTokenizer(str, "#");
+
+ String para = st.nextToken();
+ StringTokenizer innerst = new StringTokenizer(para, ",");
+ this.mBBX = new RectF();
+ this.mBBX.left = Float.parseFloat(innerst.nextToken());
+ this.mBBX.top = Float.parseFloat(innerst.nextToken());
+ this.mBBX.right = Float.parseFloat(innerst.nextToken());
+ this.mBBX.bottom = Float.parseFloat(innerst.nextToken());
+
+ para = st.nextToken();
+ innerst = new StringTokenizer(para, ",");
+ while (innerst.hasMoreTokens()) {
+ String s = innerst.nextToken().trim();
+ if (s.length()==0)
+ break;
+ float x = Float.parseFloat(s);
+ float y = Float.parseFloat(innerst.nextToken());
+ this.mPtsBuffer.add(new PointF(x, y));
}
+
+ para = st.nextToken();
+ this.mColor = Integer.parseInt(para);
+
+ para = st.nextToken();
+ this.mWidth = Float.parseFloat(para);
+
+ para = st.nextToken();
+ this.mLength = Float.parseFloat(para);
+
+ para = st.nextToken();
+ this.mTimestamp = Long.parseLong(para);
}
-
- /**
- * Convert the gesture to string
- */
+
@Override
public String toString() {
- StringBuilder str = new StringBuilder();
- str.append(mGestureID);
- ArrayList<GestureStroke> strokes = mStrokes;
- int count = strokes.size();
- for (int i = 0; i < count; i++) {
- GestureStroke stroke = strokes.get(i);
- str.append(GestureConstants.STRING_GESTURE_DELIIMITER);
- str.append(stroke.toString());
+ String str = "";
+
+ str += "#" + this.mBBX.left + "," + this.mBBX.top + "," +
+ this.mBBX.right + "," + this.mBBX.bottom;
+
+ str += "#";
+ Iterator<PointF> it = this.mPtsBuffer.iterator();
+ while (it.hasNext()) {
+ PointF fp = it.next();
+ str += fp.x + "," + fp.y + ",";
}
- return str.toString();
+ str += "#";
+ str += this.mColor;
+
+ str += "#";
+ str += this.mWidth;
+
+ str += "#";
+ str += this.mLength;
+
+ str += "#";
+ str += this.mTimestamp;
+
+ return str;
}
-
- public static final Parcelable.Creator<Gesture> CREATOR = new Parcelable.Creator<Gesture>() {
+
+ public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public Gesture createFromParcel(Parcel in) {
String str = in.readString();
- Gesture gesture = new Gesture();
- gesture.createFromString(str);
- return gesture;
+ Gesture stk = new Gesture();
+ stk.createFromString(str);
+ return stk;
}
-
+
public Gesture[] newArray(int size) {
return new Gesture[size];
}
};
-
- /**
- * Build a gesture from a byte array
- *
- * @param bytes
- * @return the gesture
- */
- static Gesture buildFromArray(byte[] bytes) {
+
+ public static Gesture buildFromArray(byte[] bytes) {
String str = new String(bytes);
- Gesture gesture = new Gesture();
- gesture.createFromString(str);
- return gesture;
+ Gesture stk = new Gesture();
+ stk.createFromString(str);
+ return stk;
}
-
- /**
- * Save a gesture to a byte array
- *
- * @param stroke
- * @return the byte array
- */
- static byte[] saveToArray(Gesture stroke) {
- String str = stroke.toString();
+
+ public static byte[] saveToArray(Gesture stk) {
+ String str = stk.toString();
return str.getBytes();
}
-
+
public void writeToParcel(Parcel out, int flags) {
- out.writeString(toString());
+ out.writeString(this.toString());
}
-
+
public int describeContents() {
return CONTENTS_FILE_DESCRIPTOR;
}
diff --git a/tests/sketch/src/com/android/gesture/GestureActionListener.java b/tests/sketch/src/com/android/gesture/GestureActionListener.java
deleted file mode 100644
index 130ac19..0000000
--- a/tests/sketch/src/com/android/gesture/GestureActionListener.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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.gesture;
-
-
-public interface GestureActionListener {
- public void onGesturePerformed(GestureOverlay overlay, Gesture gesture);
-}
diff --git a/tests/sketch/src/com/android/gesture/GestureAdapter.java b/tests/sketch/src/com/android/gesture/GestureAdapter.java
deleted file mode 100644
index 3cf9b4c..0000000
--- a/tests/sketch/src/com/android/gesture/GestureAdapter.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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.gesture;
-
-import android.graphics.Color;
-import android.view.MotionEvent;
-import android.view.View;
-
-import java.util.ArrayList;
-
-public class GestureAdapter implements GestureListener {
-
- public static final int SINGLE_STROKE = 0;
-
- public static final int MULTIPLE_STROKE = 1;
-
- private static final float STROKE_LENGTH_THRESHOLD = 100;
-
- private static final float SQUARENESS_THRESHOLD = 0.24f;
-
- private static final int UNCERTAIN_GESTURE_COLOR = Color.argb(60, 255, 255, 0);
-
- private boolean mIsGesturing = false;
-
- private float mTotalLength;
-
- private float mX, mY;
-
- private View mModel;
-
- private int mGestureType = SINGLE_STROKE;
-
- private ArrayList<GestureActionListener> mActionListeners = new ArrayList<GestureActionListener>();
-
- public GestureAdapter(View model) {
- mModel = model;
- }
-
- public void setGestureType(int type) {
- mGestureType = type;
- }
-
- public void onStartGesture(GestureOverlay overlay, MotionEvent event) {
- if (mGestureType == MULTIPLE_STROKE) {
- overlay.cancelFadingOut();
- }
- mX = event.getX();
- mY = event.getY();
- mTotalLength = 0;
- mIsGesturing = false;
- if (mGestureType == SINGLE_STROKE || overlay.getCurrentGesture() == null
- || overlay.getCurrentGesture().getStrokesCount() == 0) {
- overlay.setGestureColor(UNCERTAIN_GESTURE_COLOR);
- }
- mModel.dispatchTouchEvent(event);
- }
-
- public void onGesture(GestureOverlay overlay, MotionEvent event) {
- if (mIsGesturing) {
- return;
- }
- float x = event.getX();
- float y = event.getY();
- float dx = x - mX;
- float dy = y - mY;
- mTotalLength += (float)Math.sqrt(dx * dx + dy * dy);
- mX = x;
- mY = y;
-
- if (mTotalLength > STROKE_LENGTH_THRESHOLD) {
- OrientedBoundingBox bbx = GestureUtils.computeOrientedBBX(overlay.getCurrentStroke());
- if (bbx.squareness > SQUARENESS_THRESHOLD) {
- mIsGesturing = true;
- overlay.setGestureColor(GestureOverlay.DEFAULT_GESTURE_COLOR);
- event = MotionEvent.obtain(event.getDownTime(), System.currentTimeMillis(),
- MotionEvent.ACTION_UP, x, y, event.getPressure(), event.getSize(), event
- .getMetaState(), event.getXPrecision(), event.getYPrecision(),
- event.getDeviceId(), event.getEdgeFlags());
- }
- }
- mModel.dispatchTouchEvent(event);
- }
-
- public void onFinishGesture(GestureOverlay overlay, MotionEvent event) {
- if (mIsGesturing) {
- overlay.clear(true);
- ArrayList<GestureActionListener> listeners = mActionListeners;
- int count = listeners.size();
- for (int i = 0; i < count; i++) {
- GestureActionListener listener = listeners.get(i);
- listener.onGesturePerformed(overlay, overlay.getCurrentGesture());
- }
- } else {
- mModel.dispatchTouchEvent(event);
- overlay.clear(false);
- }
- }
-
- public void addGestureActionListener(GestureActionListener listener) {
- mActionListeners.add(listener);
- }
-
- public void removeGestureActionListener(GestureActionListener listener) {
- mActionListeners.remove(listener);
- }
-
- public boolean isGesturing() {
- return mIsGesturing;
- }
-}
diff --git a/tests/sketch/src/com/android/gesture/GestureConstants.java b/tests/sketch/src/com/android/gesture/GestureConstants.java
deleted file mode 100644
index 0e17c8a..0000000
--- a/tests/sketch/src/com/android/gesture/GestureConstants.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2009 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.gesture;
-
-interface GestureConstants {
- static final String XML_TAG_LIBRARY = "library";
- static final String XML_TAG_ENTRY = "entry";
- static final String XML_TAG_GESTURE = "gesture";
- static final String XML_TAG_STROKE = "stroke";
- static final String XML_TAG_ID = "id";
- static final String XML_TAG_NAME = "name";
- static final String STRING_GESTURE_DELIIMITER = "#";
- static final String STRING_STROKE_DELIIMITER = ",";
- static final int STROKE_STRING_BUFFER_SIZE = 1024;
- static final int STROKE_POINT_BUFFER_SIZE = 100; // number of points
- static final int IO_BUFFER_SIZE = 8 * 1024; // 8K
-}
diff --git a/tests/sketch/src/com/android/gesture/GestureLibrary.java b/tests/sketch/src/com/android/gesture/GestureLibrary.java
deleted file mode 100644
index 32c1ac4..0000000
--- a/tests/sketch/src/com/android/gesture/GestureLibrary.java
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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.gesture;
-
-import android.util.Config;
-import android.util.Log;
-import android.util.Xml;
-import android.util.Xml.Encoding;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.Locator;
-import org.xml.sax.SAXException;
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Set;
-
-/**
- * GestureLibrary maintains gesture examples and makes predictions on a new
- * gesture
- */
-public class GestureLibrary {
-
- public static final int SEQUENCE_INVARIANT = 1;
-
- public static final int SEQUENCE_SENSITIVE = 2;
-
- private int mSequenceType = SEQUENCE_SENSITIVE;
-
- public static final int ORIENTATION_INVARIANT = 1;
-
- public static final int ORIENTATION_SENSITIVE = 2;
-
- private int mOrientationStyle = ORIENTATION_SENSITIVE;
-
- private static final String LOGTAG = "GestureLibrary";
-
- private static final String NAMESPACE = "";
-
- private final String mGestureFileName;
-
- private HashMap<String, ArrayList<Gesture>> mEntryName2gestures = new HashMap<String, ArrayList<Gesture>>();
-
- private Learner mClassifier;
-
- private boolean mChanged = false;
-
- /**
- * @param path where gesture data is stored
- */
- public GestureLibrary(String path) {
- mGestureFileName = path;
- mClassifier = new InstanceLearner();
- }
-
- /**
- * Specify whether the gesture library will handle orientation sensitive
- * gestures. Use ORIENTATION_INVARIANT or ORIENTATION_SENSITIVE
- *
- * @param style
- */
- public void setOrientationStyle(int style) {
- mOrientationStyle = style;
- }
-
- public int getOrientationStyle() {
- return mOrientationStyle;
- }
-
- public void setGestureType(int type) {
- mSequenceType = type;
- }
-
- public int getGestureType() {
- return mSequenceType;
- }
-
- /**
- * Get all the gesture entry names in the library
- *
- * @return a set of strings
- */
- public Set<String> getGestureEntries() {
- return mEntryName2gestures.keySet();
- }
-
- /**
- * Recognize a gesture
- *
- * @param gesture the query
- * @return a list of predictions of possible entries for a given gesture
- */
- public ArrayList<Prediction> recognize(Gesture gesture) {
- Instance instance = Instance.createInstance(this, gesture, null);
- return mClassifier.classify(this, instance);
- }
-
- /**
- * Add a gesture for the entry
- *
- * @param entryName entry name
- * @param gesture
- */
- public void addGesture(String entryName, Gesture gesture) {
- if (Config.DEBUG) {
- Log.v(LOGTAG, "Add an example for gesture: " + entryName);
- }
- ArrayList<Gesture> gestures = mEntryName2gestures.get(entryName);
- if (gestures == null) {
- gestures = new ArrayList<Gesture>();
- mEntryName2gestures.put(entryName, gestures);
- }
- gestures.add(gesture);
- mClassifier.addInstance(Instance.createInstance(this, gesture, entryName));
- mChanged = true;
- }
-
- /**
- * Remove a gesture from the library. If there are no more gestures for the
- * given entry, the gesture entry will be removed.
- *
- * @param entryName entry name
- * @param gesture
- */
- public void removeGesture(String entryName, Gesture gesture) {
- ArrayList<Gesture> gestures = mEntryName2gestures.get(entryName);
- if (gestures == null) {
- return;
- }
-
- gestures.remove(gesture);
-
- // if there are no more samples, remove the entry automatically
- if (gestures.isEmpty()) {
- mEntryName2gestures.remove(entryName);
- }
-
- mClassifier.removeInstance(gesture.getID());
-
- mChanged = true;
- }
-
- /**
- * Remove a entry of gestures
- *
- * @param entryName the entry name
- */
- public void removeEntireEntry(String entryName) {
- mEntryName2gestures.remove(entryName);
- mClassifier.removeInstances(entryName);
- mChanged = true;
- }
-
- /**
- * Get all the gestures of an entry
- *
- * @param entryName
- * @return the list of gestures that is under this name
- */
- @SuppressWarnings("unchecked")
- public ArrayList<Gesture> getGestures(String entryName) {
- ArrayList<Gesture> gestures = mEntryName2gestures.get(entryName);
- if (gestures != null) {
- return (ArrayList<Gesture>)gestures.clone();
- } else {
- return null;
- }
- }
-
- /**
- * Save the gesture library
- */
- public void save() {
- if (!mChanged)
- return;
-
- try {
- File file = new File(mGestureFileName);
- if (!file.getParentFile().exists()) {
- file.getParentFile().mkdirs();
- }
- if (Config.DEBUG) {
- Log.v(LOGTAG, "Save to " + mGestureFileName);
- }
- BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(
- mGestureFileName), GestureConstants.IO_BUFFER_SIZE);
-
- PrintWriter writer = new PrintWriter(outputStream);
- XmlSerializer serializer = Xml.newSerializer();
- serializer.setOutput(writer);
- serializer.startDocument(Encoding.ISO_8859_1.name(), null);
- serializer.startTag(NAMESPACE, GestureConstants.XML_TAG_LIBRARY);
- HashMap<String, ArrayList<Gesture>> maps = mEntryName2gestures;
- Iterator<String> it = maps.keySet().iterator();
- while (it.hasNext()) {
- String key = it.next();
- ArrayList<Gesture> examples = maps.get(key);
- // save an entry
- serializer.startTag(NAMESPACE, GestureConstants.XML_TAG_ENTRY);
- serializer.attribute(NAMESPACE, GestureConstants.XML_TAG_NAME, key);
- int count = examples.size();
- for (int i = 0; i < count; i++) {
- Gesture gesture = examples.get(i);
- // save each gesture in the entry
- gesture.toXML(NAMESPACE, serializer);
- }
- serializer.endTag(NAMESPACE, GestureConstants.XML_TAG_ENTRY);
- }
- serializer.endTag(NAMESPACE, GestureConstants.XML_TAG_LIBRARY);
- serializer.endDocument();
- serializer.flush();
- writer.close();
- outputStream.close();
- mChanged = false;
- } catch (IOException ex) {
- Log.d(LOGTAG, "Failed to save gestures:", ex);
- }
- }
-
- /**
- * Load the gesture library
- */
- public void load() {
- File file = new File(mGestureFileName);
- if (file.exists()) {
- try {
- if (Config.DEBUG) {
- Log.v(LOGTAG, "Load from " + mGestureFileName);
- }
- BufferedInputStream in = new BufferedInputStream(new FileInputStream(
- mGestureFileName), GestureConstants.IO_BUFFER_SIZE);
- Xml.parse(in, Encoding.ISO_8859_1, new CompactInkHandler());
- in.close();
- } catch (SAXException ex) {
- Log.d(LOGTAG, "Failed to load gestures:", ex);
- } catch (IOException ex) {
- Log.d(LOGTAG, "Failed to load gestures:", ex);
- }
- }
- }
-
- private class CompactInkHandler implements ContentHandler {
- Gesture currentGesture = null;
-
- StringBuilder buffer = new StringBuilder(GestureConstants.STROKE_STRING_BUFFER_SIZE);
-
- String entryName;
-
- ArrayList<Gesture> gestures;
-
- CompactInkHandler() {
- }
-
- public void characters(char[] ch, int start, int length) {
- buffer.append(ch, start, length);
- }
-
- public void endDocument() {
- }
-
- public void endElement(String uri, String localName, String qName) {
- if (localName.equals(GestureConstants.XML_TAG_ENTRY)) {
- mEntryName2gestures.put(entryName, gestures);
- gestures = null;
- } else if (localName.equals(GestureConstants.XML_TAG_GESTURE)) {
- gestures.add(currentGesture);
- mClassifier.addInstance(Instance.createInstance(GestureLibrary.this,
- currentGesture, entryName));
- currentGesture = null;
- } else if (localName.equals(GestureConstants.XML_TAG_STROKE)) {
- currentGesture.addStroke(GestureStroke.createFromString(buffer.toString()));
- buffer.setLength(0);
- }
- }
-
- public void endPrefixMapping(String prefix) {
- }
-
- public void ignorableWhitespace(char[] ch, int start, int length) {
- }
-
- public void processingInstruction(String target, String data) {
- }
-
- public void setDocumentLocator(Locator locator) {
- }
-
- public void skippedEntity(String name) {
- }
-
- public void startDocument() {
- }
-
- public void startElement(String uri, String localName, String qName, Attributes attributes) {
- if (localName.equals(GestureConstants.XML_TAG_ENTRY)) {
- gestures = new ArrayList<Gesture>();
- entryName = attributes.getValue(NAMESPACE, GestureConstants.XML_TAG_NAME);
- } else if (localName.equals(GestureConstants.XML_TAG_GESTURE)) {
- currentGesture = new Gesture();
- currentGesture.setID(Long.parseLong(attributes.getValue(NAMESPACE,
- GestureConstants.XML_TAG_ID)));
- }
- }
-
- public void startPrefixMapping(String prefix, String uri) {
- }
- }
-}
diff --git a/tests/sketch/src/com/android/gesture/GestureListener.java b/tests/sketch/src/com/android/gesture/GestureListener.java
index 9b50714..ebb4149 100755
--- a/tests/sketch/src/com/android/gesture/GestureListener.java
+++ b/tests/sketch/src/com/android/gesture/GestureListener.java
@@ -18,13 +18,8 @@
import android.view.MotionEvent;
-/**
- * An interface for processing gesture events
- */
public interface GestureListener {
- public void onStartGesture(GestureOverlay overlay, MotionEvent event);
-
- public void onGesture(GestureOverlay overlay, MotionEvent event);
-
- public void onFinishGesture(GestureOverlay overlay, MotionEvent event);
+ public void onStartGesture(GesturePad pad, MotionEvent event);
+ public void onGesture(GesturePad pad, MotionEvent event);
+ public void onFinishGesture(GesturePad pad, MotionEvent event);
}
diff --git a/tests/sketch/src/com/android/gesture/GestureOverlay.java b/tests/sketch/src/com/android/gesture/GestureOverlay.java
deleted file mode 100755
index 5cef8c8..0000000
--- a/tests/sketch/src/com/android/gesture/GestureOverlay.java
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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.gesture;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BlurMaskFilter;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.os.Handler;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.View;
-import java.util.ArrayList;
-
-/**
- * A (transparent) overlay for gesture input that can be placed on top of other
- * widgets. The view can also be opaque.
- */
-
-public class GestureOverlay extends View {
-
- static final float TOUCH_TOLERANCE = 3;
-
- private static final int TRANSPARENT_BACKGROUND = Color.argb(0, 0, 0, 0);
-
- private static final float FADING_ALPHA_CHANGE = 0.03f;
-
- private static final long FADING_REFRESHING_RATE = 100;
-
- private static final int GESTURE_STROKE_WIDTH = 12;
-
- private static final boolean GESTURE_RENDERING_ANTIALIAS = true;
-
- private static final int BLUR_MASK_RADIUS = 1;
-
- public static final int DEFAULT_GESTURE_COLOR = Color.argb(255, 255, 255, 0);
-
- // double buffering
- private Paint mGesturePaint;
-
- private Bitmap mBitmap; // with transparent background
-
- private Canvas mBitmapCanvas;
-
- // for rendering immediate ink feedback
- private Path mPath;
-
- private float mX;
-
- private float mY;
-
- // current gesture
- private Gesture mCurrentGesture = null;
-
- // gesture event handlers
- ArrayList<GestureListener> mGestureListeners = new ArrayList<GestureListener>();
-
- private ArrayList<GesturePoint> mPointBuffer = null;
-
- // fading out effect
- private boolean mIsFadingOut = false;
-
- private float mFadingAlpha = 1;
-
- private Handler mHandler = new Handler();
-
- private Paint mBitmapPaint = new Paint(Paint.DITHER_FLAG);
-
- private Runnable mFadingOut = new Runnable() {
- public void run() {
- if (mIsFadingOut) {
- mFadingAlpha -= FADING_ALPHA_CHANGE;
- if (mFadingAlpha <= 0) {
- mIsFadingOut = false;
- mPath = null;
- mCurrentGesture = null;
- mBitmap.eraseColor(TRANSPARENT_BACKGROUND);
- } else {
- mHandler.postDelayed(this, FADING_REFRESHING_RATE);
- }
- invalidate();
- }
- }
- };
-
- public GestureOverlay(Context context) {
- super(context);
- init();
- }
-
- public GestureOverlay(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
- }
-
- public ArrayList<GesturePoint> getCurrentStroke() {
- return mPointBuffer;
- }
-
- public Gesture getCurrentGesture() {
- return mCurrentGesture;
- }
-
- /**
- * Set Gesture color
- *
- * @param color
- */
- public void setGestureColor(int color) {
- mGesturePaint.setColor(color);
- if (mCurrentGesture != null) {
- mBitmap.eraseColor(TRANSPARENT_BACKGROUND);
- mCurrentGesture.draw(mBitmapCanvas, mGesturePaint);
- }
- }
-
- /**
- * Set the gesture to be shown in the view
- *
- * @param gesture
- */
- public void setCurrentGesture(Gesture gesture) {
- if (mCurrentGesture != null) {
- clear(false);
- }
-
- mCurrentGesture = gesture;
-
- if (gesture != null) {
- if (mBitmapCanvas != null) {
- gesture.draw(mBitmapCanvas, mGesturePaint);
- invalidate();
- }
- }
- }
-
- private void init() {
- mGesturePaint = new Paint();
- mGesturePaint.setAntiAlias(GESTURE_RENDERING_ANTIALIAS);
- mGesturePaint.setColor(DEFAULT_GESTURE_COLOR);
- mGesturePaint.setStyle(Paint.Style.STROKE);
- mGesturePaint.setStrokeJoin(Paint.Join.ROUND);
- mGesturePaint.setStrokeCap(Paint.Cap.ROUND);
- mGesturePaint.setStrokeWidth(GESTURE_STROKE_WIDTH);
- mGesturePaint
- .setMaskFilter(new BlurMaskFilter(BLUR_MASK_RADIUS, BlurMaskFilter.Blur.NORMAL));
-
- mPath = null;
- }
-
- @Override
- protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
- super.onSizeChanged(width, height, oldWidth, oldHeight);
- if (width <= 0 || height <= 0) {
- return;
- }
- int targetWidth = width > oldWidth ? width : oldWidth;
- int targetHeight = height > oldHeight ? height : oldHeight;
- mBitmap = Bitmap.createBitmap(targetWidth, targetHeight, Bitmap.Config.ARGB_8888);
- mBitmapCanvas = new Canvas(mBitmap);
- mBitmapCanvas.drawColor(TRANSPARENT_BACKGROUND);
- if (mCurrentGesture != null) {
- mCurrentGesture.draw(mBitmapCanvas, mGesturePaint);
- }
- }
-
- public void addGestureListener(GestureListener listener) {
- mGestureListeners.add(listener);
- }
-
- public void removeGestureListener(GestureListener listener) {
- mGestureListeners.remove(listener);
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- // draw double buffer
- if (mIsFadingOut) {
- mBitmapPaint.setAlpha((int) (255 * mFadingAlpha));
- canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
- } else {
- mBitmapPaint.setAlpha(255);
- canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
- }
-
- // draw the current stroke
- if (mPath != null) {
- canvas.drawPath(mPath, mGesturePaint);
- }
- }
-
- /**
- * Clear up the overlay
- *
- * @param fadeOut whether the gesture on the overlay should fade out
- * gradually or disappear immediately
- */
- public void clear(boolean fadeOut) {
- if (fadeOut) {
- mFadingAlpha = 1;
- mIsFadingOut = true;
- mHandler.removeCallbacks(mFadingOut);
- mHandler.postDelayed(mFadingOut, FADING_REFRESHING_RATE);
- } else {
- mPath = null;
- mCurrentGesture = null;
- if (mBitmap != null) {
- mBitmap.eraseColor(TRANSPARENT_BACKGROUND);
- invalidate();
- }
- }
- }
-
- public void cancelFadingOut() {
- mIsFadingOut = false;
- mHandler.removeCallbacks(mFadingOut);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
-
- if (!isEnabled()) {
- return true;
- }
-
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- touch_start(event);
- invalidate();
- break;
- case MotionEvent.ACTION_MOVE:
- touch_move(event);
- invalidate();
- break;
- case MotionEvent.ACTION_UP:
- touch_up(event);
- invalidate();
- break;
- }
-
- return true;
- }
-
- private void touch_start(MotionEvent event) {
- // pass the event to handlers
- ArrayList<GestureListener> listeners = mGestureListeners;
- int count = listeners.size();
- for (int i = 0; i < count; i++) {
- GestureListener listener = listeners.get(i);
- listener.onStartGesture(this, event);
- }
-
- // if there is fading out going on, stop it.
- if (mIsFadingOut) {
- mIsFadingOut = false;
- mHandler.removeCallbacks(mFadingOut);
- mBitmap.eraseColor(TRANSPARENT_BACKGROUND);
- mCurrentGesture = null;
- }
-
- float x = event.getX();
- float y = event.getY();
-
- mX = x;
- mY = y;
-
- if (mCurrentGesture == null) {
- mCurrentGesture = new Gesture();
- }
-
- mPointBuffer = new ArrayList<GesturePoint>();
- mPointBuffer.add(new GesturePoint(x, y, event.getEventTime()));
-
- mPath = new Path();
- mPath.moveTo(x, y);
- }
-
- private void touch_move(MotionEvent event) {
- float x = event.getX();
- float y = event.getY();
-
- float dx = Math.abs(x - mX);
- float dy = Math.abs(y - mY);
- if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
- mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
- mX = x;
- mY = y;
- }
-
- mPointBuffer.add(new GesturePoint(x, y, event.getEventTime()));
-
- // pass the event to handlers
- ArrayList<GestureListener> listeners = mGestureListeners;
- int count = listeners.size();
- for (int i = 0; i < count; i++) {
- GestureListener listener = listeners.get(i);
- listener.onGesture(this, event);
- }
- }
-
- private void touch_up(MotionEvent event) {
- // add the stroke to the current gesture
- mCurrentGesture.addStroke(new GestureStroke(mPointBuffer));
- mPointBuffer = null;
-
- // add the stroke to the double buffer
- mGesturePaint.setDither(true);
- mBitmapCanvas.drawPath(mPath, mGesturePaint);
- mGesturePaint.setDither(false);
- mPath = null;
-
- // pass the event to handlers
- ArrayList<GestureListener> listeners = mGestureListeners;
- int count = listeners.size();
- for (int i = 0; i < count; i++) {
- GestureListener listener = listeners.get(i);
- listener.onFinishGesture(this, event);
- }
- }
-
-}
diff --git a/tests/sketch/src/com/android/gesture/GesturePad.java b/tests/sketch/src/com/android/gesture/GesturePad.java
index 04dbe3a..45a09e6 100755
--- a/tests/sketch/src/com/android/gesture/GesturePad.java
+++ b/tests/sketch/src/com/android/gesture/GesturePad.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2009 Google Inc.
+ * Copyright (C) 2008 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.
@@ -18,67 +18,64 @@
import android.content.Context;
import android.graphics.Bitmap;
-import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
+import android.graphics.PointF;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
-
+import java.util.Iterator;
/**
- * A (transparent) view for gesture input that can be placed on top of other
- * widgets. The background of the view is customizable.
- *
- * @author liyang@google.com (Yang Li)
- *
+ * A view for rendering and processing gestures
*/
public class GesturePad extends View {
- private static final float TOUCH_TOLERANCE = 4;
- public static final int DEFAULT_GESTURE_COLOR = Color.argb(255, 255, 255, 0);
+ public static final float TOUCH_TOLERANCE = 4;
+ public static final int default_foreground = Color.argb(255, 255, 255, 0);
+ private int background = Color.argb(0, 0, 0, 0);
+ private int foreground = default_foreground;
+ private int uncertain_foreground = Color.argb(55, 255, 255, 0);
+ private Bitmap mBitmap;
+ private Canvas mCanvas;
+ private Path mPath;
+ private Paint mBitmapPaint;
+ private Paint mPaint;
+ private Paint mDebugPaint;
+ private float mX, mY;
+ private boolean mEnableInput = true;
+ private boolean mEnableRendering = true;
+ private boolean mCacheGesture = true;
+ private Gesture mCurrentGesture = null;
+ ArrayList<GestureListener> mGestureListeners = new ArrayList<GestureListener>();
+
+ private boolean mShouldFadingOut = true;
+ private boolean mIsFadingOut = false;
+ private float mFadingAlpha = 1;
- // double buffering
- private Paint mGesturePaint;
- private Bitmap mBitmap; // with transparent background
- private Canvas mBitmapCanvas;
-
- // for rendering immediate ink feedback
- private Path mPath;
- private float mX;
- private float mY;
-
- // current gesture
- private Gesture mCurrentGesture = null;
+ private boolean reconstruct = false;
- // gesture event handlers
- ArrayList<GestureListener> mGestureListeners =
- new ArrayList<GestureListener>();
- private ArrayList<GesturePoint> mPointBuffer = null;
-
- // fading out effect
- private boolean mIsFadingOut = false;
- private float mFadingAlpha = 1;
+ private ArrayList<Path> debug = new ArrayList<Path>();
private Handler mHandler = new Handler();
+
private Runnable mFadingOut = new Runnable() {
- public void run() {
- mFadingAlpha -= 0.03f;
- if (mFadingAlpha <= 0) {
- mIsFadingOut = false;
- mPath = null;
- mCurrentGesture = null;
- mBitmap.eraseColor(Color.argb(0, 0, 0, 0));
- } else {
- mHandler.postDelayed(this, 100);
- }
- invalidate();
- }
- };
+ public void run() {
+ mFadingAlpha -= 0.03f;
+ if (mFadingAlpha <= 0) {
+ mIsFadingOut = false;
+ mPath.reset();
+ } else {
+ mHandler.postDelayed(this, 100);
+ }
+ invalidate();
+ }
+ };
public GesturePad(Context context) {
super(context);
@@ -90,76 +87,82 @@
init();
}
- public ArrayList<GesturePoint> getCurrentStroke() {
- return this.mPointBuffer;
+ public boolean isEnableRendering() {
+ return this.mEnableRendering;
}
public Gesture getCurrentGesture() {
return mCurrentGesture;
}
- /**
- * Set Gesture color
- * @param c
- */
- public void setGestureColor(int c) {
- this.mGesturePaint.setColor(c);
- if (mCurrentGesture != null) {
- mBitmap.eraseColor(Color.argb(0, 0, 0, 0));
- mCurrentGesture.draw(mBitmapCanvas, mGesturePaint);
- }
+ public Paint getPaint() {
+ return mPaint;
}
- /**
- * Set the gesture to be shown in the view
- * @param gesture
- */
- public void setCurrentGesture(Gesture gesture) {
- if (this.mCurrentGesture != null) {
- clear(false);
- }
-
- this.mCurrentGesture = gesture;
-
- if (this.mCurrentGesture != null) {
- if (mBitmapCanvas != null) {
- this.mCurrentGesture.draw(mBitmapCanvas, mGesturePaint);
- this.invalidate();
- }
- }
+ public void setColor(int c) {
+ this.foreground = c;
+ }
+
+ public void setFadingAlpha(float f) {
+ mFadingAlpha = f;
+ }
+
+ public void setCurrentGesture(Gesture stk) {
+ this.mCurrentGesture = stk;
+ reconstruct = true;
}
private void init() {
- mGesturePaint = new Paint();
- mGesturePaint.setAntiAlias(true);
- mGesturePaint.setDither(true);
- mGesturePaint.setColor(DEFAULT_GESTURE_COLOR);
- mGesturePaint.setStyle(Paint.Style.STROKE);
- mGesturePaint.setStrokeJoin(Paint.Join.ROUND);
- mGesturePaint.setStrokeCap(Paint.Cap.ROUND);
- mGesturePaint.setStrokeWidth(12);
- mGesturePaint.setMaskFilter(
- new BlurMaskFilter(1, BlurMaskFilter.Blur.NORMAL));
+ mDebugPaint = new Paint();
+ mDebugPaint.setColor(Color.WHITE);
+ mDebugPaint.setStrokeWidth(4);
+ mDebugPaint.setAntiAlias(true);
+ mDebugPaint.setStyle(Paint.Style.STROKE);
- mPath = null;
+ mPaint = new Paint();
+ mPaint.setAntiAlias(true);
+ mPaint.setDither(true);
+ mPaint.setColor(foreground);
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setStrokeJoin(Paint.Join.ROUND);
+ mPaint.setStrokeCap(Paint.Cap.ROUND);
+ mPaint.setStrokeWidth(12);
+
+ mBitmapPaint = new Paint(Paint.DITHER_FLAG);
+ mPath = new Path();
+
+ reconstruct = false;
}
+
+ public void cacheGesture(boolean b) {
+ mCacheGesture = b;
+ }
+
+ public void enableRendering(boolean b) {
+ mEnableRendering = b;
+ }
+
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// TODO Auto-generated method stub
super.onSizeChanged(w, h, oldw, oldh);
- if (w <= 0 || h <= 0) {
+
+ if (w <=0 || h <=0)
return;
+
+ int width = w>oldw? w : oldw;
+ int height = h>oldh? h : oldh;
+ Bitmap newBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ mCanvas = new Canvas(newBitmap);
+
+ if (mBitmap != null) {
+ mCanvas.drawColor(background);
+ mCanvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
+ mCanvas.drawPath(mPath, mPaint);
}
- int width = w > oldw? w : oldw;
- int height = h > oldh? h : oldh;
- mBitmap = Bitmap.createBitmap(
- width, height, Bitmap.Config.ARGB_8888);
- mBitmapCanvas = new Canvas(mBitmap);
- mBitmapCanvas.drawColor(Color.argb(0, 0, 0, 0));
- if (mCurrentGesture != null) {
- mCurrentGesture.draw(mBitmapCanvas, mGesturePaint);
- }
+
+ mBitmap = newBitmap;
}
public void addGestureListener(GestureListener l) {
@@ -172,50 +175,111 @@
@Override
protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- // draw double buffer
- Paint paint = new Paint(Paint.DITHER_FLAG);
+ canvas.drawColor(background);
+
+ if (mCacheGesture)
+ canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
+
if (mIsFadingOut) {
- paint.setAlpha((int)(255 * mFadingAlpha));
- canvas.drawBitmap(mBitmap, 0, 0, paint);
+ int color = foreground;
+ int alpha = (int)(Color.alpha(color) * mFadingAlpha);
+ mPaint.setColor(Color.argb(alpha,
+ Color.red(color),
+ Color.green(color),
+ Color.blue(color)));
+ } else if (mEnableRendering == false) {
+ mPaint.setColor(uncertain_foreground);
} else {
- canvas.drawBitmap(mBitmap, 0, 0, paint);
+ mPaint.setColor(foreground);
}
- // draw the current stroke
- if (mPath != null) {
- canvas.drawPath(mPath, mGesturePaint);
+ if (reconstruct) {
+
+ if (this.mCurrentGesture != null) {
+ float xedge = 30;
+ float yedge = 30;
+ float w = this.getWidth() - 2 * xedge;
+ float h = this.getHeight() - 2 * yedge;
+ float sx = w / this.mCurrentGesture.getBBX().width();
+ float sy = h / mCurrentGesture.getBBX().height();
+ float scale = sx>sy?sy:sx;
+ convertFromStroke(mCurrentGesture);
+ Matrix matrix = new Matrix();
+ matrix.preTranslate(-mCurrentGesture.getBBX().centerX(), -mCurrentGesture.getBBX().centerY());
+ matrix.postScale(scale, scale);
+ matrix.postTranslate(this.getWidth()/2, this.getHeight()/2);
+ this.mPath.transform(matrix);
+ } else {
+ mPath.reset();
+ }
+
+ reconstruct = false;
+ }
+
+ canvas.drawPath(mPath, mPaint);
+
+ Iterator<Path> it = debug.iterator();
+ while (it.hasNext()) {
+ Path path = it.next();
+ canvas.drawPath(path, mDebugPaint);
}
}
-
- /**
- * Clear up the gesture pad
- * @param fadeOut whether the gesture on the pad should fade out gradually
- * or disappear immediately
- */
- public void clear(boolean fadeOut) {
- if (fadeOut) {
- mFadingAlpha = 1;
- mIsFadingOut = true;
- mHandler.removeCallbacks(mFadingOut);
- mHandler.postDelayed(mFadingOut, 100);
- } else {
- mPath = null;
- this.mCurrentGesture = null;
- if (mBitmap != null) {
- mBitmap.eraseColor(Color.argb(0, 0, 0, 0));
- this.invalidate();
+
+ public void clearDebugPath() {
+ debug.clear();
+ }
+
+ public void addDebugPath(Path path) {
+ debug.add(path);
+ }
+
+ public void addDebugPath(ArrayList<Path> paths) {
+ debug.addAll(paths);
+ }
+
+ public void clear() {
+ mPath = new Path();
+ this.mCurrentGesture = null;
+ mCanvas.drawColor(background);
+ this.invalidate();
+ }
+
+ private void convertFromStroke(Gesture stk) {
+ mPath = null;
+ Iterator it = stk.getPoints().iterator();
+ while (it.hasNext()) {
+ PointF p = (PointF) it.next();
+ if (mPath == null) {
+ mPath = new Path();
+ mPath.moveTo(p.x, p.y);
+ mX = p.x;
+ mY = p.y;
+ } else {
+ float dx = Math.abs(p.x - mX);
+ float dy = Math.abs(p.y - mY);
+ if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
+ mPath.quadTo(mX, mY, (p.x + mX)/2, (p.y + mY)/2);
+ mX = p.x;
+ mY = p.y;
+ }
}
}
+ mPath.lineTo(mX, mY);
+ }
+
+ public void setEnableInput(boolean b) {
+ mEnableInput = b;
+ }
+
+ public boolean isEnableInput() {
+ return mEnableInput;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
- if(this.isEnabled() == false) {
+ if(mEnableInput == false)
return true;
- }
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
@@ -231,41 +295,28 @@
invalidate();
break;
}
-
return true;
}
private void touch_start(MotionEvent event) {
- // if there is fading-out effect, stop it.
- if (mIsFadingOut) {
- mIsFadingOut = false;
- mHandler.removeCallbacks(mFadingOut);
- mBitmap.eraseColor(Color.argb(0, 0, 0, 0));
- this.mCurrentGesture = null;
- }
+ mIsFadingOut = false;
+ mHandler.removeCallbacks(mFadingOut);
float x = event.getX();
float y = event.getY();
+ mCurrentGesture = new Gesture();
+ mCurrentGesture.addPoint(x, y);
+
+ mPath.reset();
+ mPath.moveTo(x, y);
mX = x;
mY = y;
- // pass the event to handlers
- int count = mGestureListeners.size();
- for (int i = 0; i < count; i++) {
- GestureListener listener = mGestureListeners.get(i);
- listener.onStartGesture(this, event);
+ Iterator<GestureListener> it = mGestureListeners.iterator();
+ while (it.hasNext()) {
+ it.next().onStartGesture(this, event);
}
-
- if (mCurrentGesture == null) {
- mCurrentGesture = new Gesture();
- }
-
- mPointBuffer = new ArrayList<GesturePoint>();
- mPointBuffer.add(new GesturePoint(x, y, event.getEventTime()));
-
- mPath = new Path();
- mPath.moveTo(x, y);
}
private void touch_move(MotionEvent event) {
@@ -280,32 +331,41 @@
mY = y;
}
- mPointBuffer.add(new GesturePoint(x, y, event.getEventTime()));
-
- // pass the event to handlers
- int count = mGestureListeners.size();
- for (int i = 0; i < count; i++) {
- GestureListener listener = mGestureListeners.get(i);
- listener.onGesture(this, event);
+ mCurrentGesture.addPoint(x, y);
+
+ Iterator<GestureListener> it = mGestureListeners.iterator();
+ while (it.hasNext()) {
+ it.next().onGesture(this, event);
}
}
-
+
+ public void setFadingOut(boolean b) {
+ mShouldFadingOut = b;
+ mIsFadingOut = false;
+ }
+
+ public boolean shouldFadingOut() {
+ return mShouldFadingOut;
+ }
private void touch_up(MotionEvent event) {
- // add the stroke to the current gesture
- mCurrentGesture.addStroke(new GestureStroke(mPointBuffer));
- mPointBuffer = null;
-
- // add the stroke to the double buffer
- mBitmapCanvas.drawPath(mPath, mGesturePaint);
- mPath = null;
+ mPath.lineTo(mX, mY);
- // pass the event to handlers
- int count = mGestureListeners.size();
- for (int i = 0; i < count; i++) {
- GestureListener listener = mGestureListeners.get(i);
- listener.onFinishGesture(this, event);
+ if (mCacheGesture)
+ mCanvas.drawPath(mPath, mPaint);
+
+ // kill this so we don't double draw
+ if (shouldFadingOut()) {
+ mFadingAlpha = 1;
+ mIsFadingOut = true;
+ mHandler.removeCallbacks(mFadingOut);
+ mHandler.postDelayed(mFadingOut, 100);
+ }
+
+ Iterator<GestureListener> it = mGestureListeners.iterator();
+ while (it.hasNext()) {
+ it.next().onFinishGesture(this, event);
}
}
-
+
}
diff --git a/tests/sketch/src/com/android/gesture/GesturePoint.java b/tests/sketch/src/com/android/gesture/GesturePoint.java
deleted file mode 100644
index d06eff47..0000000
--- a/tests/sketch/src/com/android/gesture/GesturePoint.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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.gesture;
-
-/**
- * A timed point of a gesture stroke
- */
-
-public class GesturePoint {
- public final float xpos;
-
- public final float ypos;
-
- public final long timestamp;
-
- public GesturePoint(float x, float y, long t) {
- xpos = x;
- ypos = y;
- timestamp = t;
- }
-}
diff --git a/tests/sketch/src/com/android/gesture/GestureProcessor.java b/tests/sketch/src/com/android/gesture/GestureProcessor.java
deleted file mode 100644
index feddead..0000000
--- a/tests/sketch/src/com/android/gesture/GestureProcessor.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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.gesture;
-
-import android.graphics.Color;
-import android.view.MotionEvent;
-import android.view.View;
-
-import java.util.ArrayList;
-
-public class GestureProcessor implements GestureListener {
-
- public static final int SINGLE_STROKE = 0;
-
- public static final int MULTIPLE_STROKE = 1;
-
- private static final float STROKE_LENGTH_THRESHOLD = 100;
-
- private static final float SQUARENESS_THRESHOLD = 0.24f;
-
- private static final int UNCERTAIN_GESTURE_COLOR = Color.argb(60, 255, 255, 0);
-
- private boolean mIsGesturing = false;
-
- private float mTotalLength;
-
- private float mX, mY;
-
- private View mModel;
-
- private int mGestureType = SINGLE_STROKE;
-
- private ArrayList<GestureActionListener> mActionListeners = new ArrayList<GestureActionListener>();
-
- public GestureProcessor(View model) {
- mModel = model;
- }
-
- /**
- *
- * @param type SINGLE_STROKE or MULTIPLE_STROKE
- */
- public void setGestureType(int type) {
- mGestureType = type;
- }
-
- public void onStartGesture(GestureOverlay overlay, MotionEvent event) {
- if (mGestureType == MULTIPLE_STROKE) {
- overlay.cancelFadingOut();
- }
- mX = event.getX();
- mY = event.getY();
- mTotalLength = 0;
- mIsGesturing = false;
- if (mGestureType == SINGLE_STROKE || overlay.getCurrentGesture() == null
- || overlay.getCurrentGesture().getStrokesCount() == 0) {
- overlay.setGestureColor(UNCERTAIN_GESTURE_COLOR);
- }
- mModel.dispatchTouchEvent(event);
- }
-
- public void onGesture(GestureOverlay overlay, MotionEvent event) {
- if (mIsGesturing) {
- return;
- }
- float x = event.getX();
- float y = event.getY();
- float dx = x - mX;
- float dy = y - mY;
- mTotalLength += (float)Math.sqrt(dx * dx + dy * dy);
- mX = x;
- mY = y;
-
- if (mTotalLength > STROKE_LENGTH_THRESHOLD) {
- OrientedBoundingBox bbx = GestureUtils.computeOrientedBBX(overlay.getCurrentStroke());
- if (bbx.squareness > SQUARENESS_THRESHOLD) {
- mIsGesturing = true;
- overlay.setGestureColor(GestureOverlay.DEFAULT_GESTURE_COLOR);
- event = MotionEvent.obtain(event.getDownTime(), System.currentTimeMillis(),
- MotionEvent.ACTION_UP, x, y, event.getPressure(), event.getSize(), event
- .getMetaState(), event.getXPrecision(), event.getYPrecision(),
- event.getDeviceId(), event.getEdgeFlags());
- }
- }
- mModel.dispatchTouchEvent(event);
- }
-
- public void onFinishGesture(GestureOverlay overlay, MotionEvent event) {
- if (mIsGesturing) {
- overlay.clear(true);
- ArrayList<GestureActionListener> listeners = mActionListeners;
- int count = listeners.size();
- for (int i = 0; i < count; i++) {
- GestureActionListener listener = listeners.get(i);
- listener.onGesturePerformed(overlay, overlay.getCurrentGesture());
- }
- } else {
- mModel.dispatchTouchEvent(event);
- overlay.clear(false);
- }
- }
-
- public void addGestureActionListener(GestureActionListener listener) {
- mActionListeners.add(listener);
- }
-
- public void removeGestureActionListener(GestureActionListener listener) {
- mActionListeners.remove(listener);
- }
-
- public boolean isGesturing() {
- return mIsGesturing;
- }
-}
diff --git a/tests/sketch/src/com/android/gesture/GestureStroke.java b/tests/sketch/src/com/android/gesture/GestureStroke.java
deleted file mode 100644
index b1081e5..0000000
--- a/tests/sketch/src/com/android/gesture/GestureStroke.java
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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.gesture;
-
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.RectF;
-
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.IOException;
-import java.util.ArrayList;
-
-/**
- * A gesture stroke started on a touch down and ended on a touch up.
- */
-public class GestureStroke {
- public final RectF boundingBox;
-
- public final float length;
-
- public final float[] xPoints;
-
- public final float[] yPoints;
-
- public final long[] timestamps;
-
- private Path mCachedPath;
-
- /**
- * Construct a gesture stroke from a list of gesture points
- *
- * @param pts
- */
- public GestureStroke(ArrayList<GesturePoint> pts) {
- xPoints = new float[pts.size()];
- yPoints = new float[pts.size()];
- timestamps = new long[pts.size()];
-
- RectF bx = null;
- float len = 0;
- int index = 0;
- int count = pts.size();
- float[] xpts = xPoints;
- float[] ypts = yPoints;
- long[] times = timestamps;
-
- for (int i = 0; i < count; i++) {
- GesturePoint p = pts.get(i);
- xpts[index] = p.xpos;
- ypts[index] = p.ypos;
- times[index] = p.timestamp;
-
- if (bx == null) {
- bx = new RectF();
- bx.top = p.ypos;
- bx.left = p.xpos;
- bx.right = p.xpos;
- bx.bottom = p.ypos;
- len = 0;
- } else {
- len += Math.sqrt(Math.pow(p.xpos - xpts[index - 1], 2)
- + Math.pow(p.ypos - ypts[index - 1], 2));
- bx.union(p.xpos, p.ypos);
- }
- index++;
- }
-
- boundingBox = bx;
- length = len;
- }
-
- /**
- * Draw the gesture with a given canvas and paint
- *
- * @param canvas
- */
- void draw(Canvas canvas, Paint paint) {
- if (mCachedPath == null) {
- float[] xpts = xPoints;
- float[] ypts = yPoints;
- int count = xpts.length;
- Path path = null;
- float mX = 0, mY = 0;
- for (int i = 0; i < count; i++) {
- float x = xpts[i];
- float y = ypts[i];
- if (path == null) {
- path = new Path();
- path.moveTo(x, y);
- mX = x;
- mY = y;
- } else {
- float dx = Math.abs(x - mX);
- float dy = Math.abs(y - mY);
- if (dx >= 3 || dy >= 3) {
- path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
- mX = x;
- mY = y;
- }
- }
- }
-
- mCachedPath = path;
- }
-
- canvas.drawPath(mCachedPath, paint);
- }
-
- /**
- * Convert the stroke to a Path based on the number of points
- *
- * @param width the width of the bounding box of the target path
- * @param height the height of the bounding box of the target path
- * @param numSample the number of points needed
- * @return the path
- */
- public Path toPath(float width, float height, int numSample) {
- float[] pts = GestureUtils.sequentialFeaturize(this, numSample);
- RectF rect = boundingBox;
- float scale = height / rect.height();
- Matrix matrix = new Matrix();
- matrix.setTranslate(-rect.left, -rect.top);
- Matrix scaleMatrix = new Matrix();
- scaleMatrix.setScale(scale, scale);
- matrix.postConcat(scaleMatrix);
- Matrix translate = new Matrix();
- matrix.postConcat(translate);
- matrix.mapPoints(pts);
-
- Path path = null;
- float mX = 0;
- float mY = 0;
- int count = pts.length;
- for (int i = 0; i < count; i += 2) {
- float x = pts[i];
- float y = pts[i + 1];
- if (path == null) {
- path = new Path();
- path.moveTo(x, y);
- mX = x;
- mY = y;
- } else {
- float dx = Math.abs(x - mX);
- float dy = Math.abs(y - mY);
- if (dx >= GestureOverlay.TOUCH_TOLERANCE || dy >= GestureOverlay.TOUCH_TOLERANCE) {
- path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
- mX = x;
- mY = y;
- }
- }
- }
- return path;
- }
-
- /**
- * Save the gesture stroke as XML
- *
- * @param namespace
- * @param serializer
- * @throws IOException
- */
- void toXML(String namespace, XmlSerializer serializer) throws IOException {
- serializer.startTag(namespace, GestureConstants.XML_TAG_STROKE);
- serializer.text(toString());
- serializer.endTag(namespace, GestureConstants.XML_TAG_STROKE);
- }
-
- /**
- * Create a gesture stroke from a string
- *
- * @param str
- * @return the gesture stroke
- */
- public static GestureStroke createFromString(String str) {
- ArrayList<GesturePoint> points = new ArrayList<GesturePoint>(
- GestureConstants.STROKE_POINT_BUFFER_SIZE);
- int endIndex;
- int startIndex = 0;
- while ((endIndex = str.indexOf(GestureConstants.STRING_STROKE_DELIIMITER, startIndex + 1)) != -1) {
-
- // parse x
- String token = str.substring(startIndex, endIndex);
- float x = Float.parseFloat(token);
- startIndex = endIndex + 1;
-
- // parse y
- endIndex = str.indexOf(GestureConstants.STRING_STROKE_DELIIMITER, startIndex + 1);
- token = str.substring(startIndex, endIndex);
- float y = Float.parseFloat(token);
- startIndex = endIndex + 1;
-
- // parse t
- endIndex = str.indexOf(GestureConstants.STRING_STROKE_DELIIMITER, startIndex + 1);
- token = str.substring(startIndex, endIndex);
- long time = Long.parseLong(token);
- startIndex = endIndex + 1;
-
- points.add(new GesturePoint(x, y, time));
- }
- return new GestureStroke(points);
- }
-
- /**
- * Convert the stroke to string
- */
- @Override
- public String toString() {
- StringBuilder str = new StringBuilder(GestureConstants.STROKE_STRING_BUFFER_SIZE);
- float[] xpts = xPoints;
- float[] ypts = yPoints;
- long[] times = timestamps;
- int count = xpts.length;
- for (int i = 0; i < count; i++) {
- str.append(xpts[i] + GestureConstants.STRING_STROKE_DELIIMITER + ypts[i]
- + GestureConstants.STRING_STROKE_DELIIMITER + times[i]
- + GestureConstants.STRING_STROKE_DELIIMITER);
- }
- return str.toString();
- }
-
- /**
- * Invalidate the cached path that is used for rendering the stroke
- */
- public void invalidate() {
- mCachedPath = null;
- }
-}
diff --git a/tests/sketch/src/com/android/gesture/GestureUtils.java b/tests/sketch/src/com/android/gesture/GestureUtils.java
deleted file mode 100755
index 7c3237a..0000000
--- a/tests/sketch/src/com/android/gesture/GestureUtils.java
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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.gesture;
-
-import android.graphics.RectF;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-
-public class GestureUtils {
-
- private static final int SEQUENCE_SAMPLE_SIZE = 16;
-
- protected static float[] spatialFeaturize(Gesture gesture, int sampleSize) {
- float[] sample = new float[sampleSize * sampleSize];
- Arrays.fill(sample, 0);
-
- RectF rect = gesture.getBoundingBox();
- float sx = sampleSize / rect.width();
- float sy = sampleSize / rect.height();
- float scale = sx < sy ? sx : sy;
- android.graphics.Matrix trans = new android.graphics.Matrix();
- trans.setScale(scale, scale);
- android.graphics.Matrix translate1 = new android.graphics.Matrix();
- translate1.setTranslate(-rect.centerX(), -rect.centerY());
- trans.preConcat(translate1);
- android.graphics.Matrix translate2 = new android.graphics.Matrix();
- translate2.setTranslate(sampleSize / 2, sampleSize / 2);
- trans.postConcat(translate2);
-
- ArrayList<GestureStroke> strokes = gesture.getStrokes();
- int count = strokes.size();
- int size;
- for (int index = 0; index < count; index++) {
- GestureStroke stroke = strokes.get(index);
- float[] pts = sequentialFeaturize(stroke, SEQUENCE_SAMPLE_SIZE);
- trans.mapPoints(pts);
-
- size = pts.length;
- for (int i = 0; i < size; i += 2) {
- float x = pts[i];
- int xFloor = (int) Math.floor(x);
- int xCeiling = (int) Math.ceil(x);
- float y = pts[i + 1];
- int yFloor = (int) Math.floor(y);
- int yCeiling = (int) Math.ceil(y);
-
- if (yFloor >= 0 && yFloor < sampleSize && xFloor >= 0 && xFloor < sampleSize) {
- int pos = yFloor * sampleSize + xFloor;
- float value = (1 - x + xFloor) * (1 - y + yFloor);
- if (sample[pos] < value) {
- sample[pos] = value;
- }
- }
-
- if (yFloor >= 0 && yFloor < sampleSize && xCeiling >= 0 && xCeiling < sampleSize) {
- int pos = yFloor * sampleSize + xCeiling;
- float value = (1 - xCeiling + x) * (1 - y + yFloor);
- if (sample[pos] < value) {
- sample[pos] = value;
- }
- }
-
- if (yCeiling >= 0 && yCeiling < sampleSize && xFloor >= 0 && xFloor < sampleSize) {
- int pos = yCeiling * sampleSize + xFloor;
- float value = (1 - x + xFloor) * (1 - yCeiling + y);
- if (sample[pos] < value) {
- sample[pos] = value;
- }
-
- }
-
- if (yCeiling >= 0 && yCeiling < sampleSize && xCeiling >= 0
- && xCeiling < sampleSize) {
- int pos = yCeiling * sampleSize + xCeiling;
- float value = (1 - xCeiling + x) * (1 - yCeiling + y);
- if (sample[pos] < value) {
- sample[pos] = value;
- }
- }
- }
- }
-
- return sample;
- }
-
- /**
- * Featurize a stroke into a vector of a given number of elements
- *
- * @param stroke
- * @param sampleSize
- * @return a float array
- */
- protected static float[] sequentialFeaturize(GestureStroke stroke, int sampleSize) {
- final float increment = stroke.length / (sampleSize - 1);
- int vectorLength = sampleSize * 2;
- float[] vector = new float[vectorLength];
- float distanceSoFar = 0;
- float[] xpts = stroke.xPoints;
- float[] ypts = stroke.yPoints;
- float lstPointX = xpts[0];
- float lstPointY = ypts[0];
- int index = 0;
- float currentPointX = Float.MIN_VALUE;
- float currentPointY = Float.MIN_VALUE;
- vector[index] = lstPointX;
- index++;
- vector[index] = lstPointY;
- index++;
- int i = 0;
- int count = xpts.length;
- while (i < count) {
- if (currentPointX == Float.MIN_VALUE) {
- i++;
- if (i >= count) {
- break;
- }
- currentPointX = xpts[i];
- currentPointY = ypts[i];
- }
- float deltaX = currentPointX - lstPointX;
- float deltaY = currentPointY - lstPointY;
- float distance = (float) Math.sqrt(deltaX * deltaX + deltaY * deltaY);
- if (distanceSoFar + distance >= increment) {
- float ratio = (increment - distanceSoFar) / distance;
- float nx = lstPointX + ratio * deltaX;
- float ny = lstPointY + ratio * deltaY;
- vector[index] = nx;
- index++;
- vector[index] = ny;
- index++;
- lstPointX = nx;
- lstPointY = ny;
- distanceSoFar = 0;
- } else {
- lstPointX = currentPointX;
- lstPointY = currentPointY;
- currentPointX = Float.MIN_VALUE;
- currentPointY = Float.MIN_VALUE;
- distanceSoFar += distance;
- }
- }
-
- for (i = index; i < vectorLength; i += 2) {
- vector[i] = lstPointX;
- vector[i + 1] = lstPointY;
- }
- return vector;
- }
-
- /**
- * Calculate the centroid
- *
- * @param points
- * @return the centroid
- */
- public static float[] computeCentroid(float[] points) {
- float centerX = 0;
- float centerY = 0;
- int count = points.length;
- for (int i = 0; i < count; i++) {
- centerX += points[i];
- i++;
- centerY += points[i];
- }
- float[] center = new float[2];
- center[0] = 2 * centerX / count;
- center[1] = 2 * centerY / count;
-
- return center;
- }
-
- /**
- * calculate the variance-covariance matrix, treat each point as a sample
- *
- * @param points
- * @return the covariance matrix
- */
- protected static double[][] computeCoVariance(float[] points) {
- double[][] array = new double[2][2];
- array[0][0] = 0;
- array[0][1] = 0;
- array[1][0] = 0;
- array[1][1] = 0;
- int count = points.length;
- for (int i = 0; i < count; i++) {
- float x = points[i];
- i++;
- float y = points[i];
- array[0][0] += x * x;
- array[0][1] += x * y;
- array[1][0] = array[0][1];
- array[1][1] += y * y;
- }
- array[0][0] /= (count / 2);
- array[0][1] /= (count / 2);
- array[1][0] /= (count / 2);
- array[1][1] /= (count / 2);
-
- return array;
- }
-
- public static float computeTotalLength(float[] points) {
- float sum = 0;
- int count = points.length - 4;
- for (int i = 0; i < count; i += 2) {
- float dx = points[i + 2] - points[i];
- float dy = points[i + 3] - points[i + 1];
- sum += Math.sqrt(dx * dx + dy * dy);
- }
- return sum;
- }
-
- public static double computeStraightness(float[] points) {
- float totalLen = computeTotalLength(points);
- float dx = points[2] - points[0];
- float dy = points[3] - points[1];
- return Math.sqrt(dx * dx + dy * dy) / totalLen;
- }
-
- public static double computeStraightness(float[] points, float totalLen) {
- float dx = points[2] - points[0];
- float dy = points[3] - points[1];
- return Math.sqrt(dx * dx + dy * dy) / totalLen;
- }
-
- /**
- * Calculate the squared Euclidean distance between two vectors
- *
- * @param vector1
- * @param vector2
- * @return the distance
- */
- protected static double euclideanDistance(float[] vector1, float[] vector2) {
- double squaredDistance = 0;
- int size = vector1.length;
- for (int i = 0; i < size; i++) {
- float difference = vector1[i] - vector2[i];
- squaredDistance += difference * difference;
- }
- return squaredDistance / size;
- }
-
- /**
- * Calculate the cosine distance between two instances
- *
- * @param in1
- * @param in2
- * @return the distance between 0 and Math.PI
- */
- protected static double cosineDistance(Instance in1, Instance in2) {
- float sum = 0;
- float[] vector1 = in1.vector;
- float[] vector2 = in2.vector;
- int len = vector1.length;
- for (int i = 0; i < len; i++) {
- sum += vector1[i] * vector2[i];
- }
- return Math.acos(sum / (in1.magnitude * in2.magnitude));
- }
-
- public static OrientedBoundingBox computeOrientedBBX(ArrayList<GesturePoint> pts) {
- GestureStroke stroke = new GestureStroke(pts);
- float[] points = sequentialFeaturize(stroke, SEQUENCE_SAMPLE_SIZE);
- return computeOrientedBBX(points);
- }
-
- public static OrientedBoundingBox computeOrientedBBX(float[] points) {
- float[] meanVector = computeCentroid(points);
- return computeOrientedBBX(points, meanVector);
- }
-
- public static OrientedBoundingBox computeOrientedBBX(float[] points, float[] centroid) {
-
- android.graphics.Matrix tr = new android.graphics.Matrix();
- tr.setTranslate(-centroid[0], -centroid[1]);
- tr.mapPoints(points);
-
- double[][] array = computeCoVariance(points);
- double[] targetVector = computeOrientation(array);
-
- float angle;
- if (targetVector[0] == 0 && targetVector[1] == 0) {
- angle = -90;
- } else { // -PI<alpha<PI
- angle = (float) Math.atan2(targetVector[1], targetVector[0]);
- angle = (float) (180 * angle / Math.PI);
- android.graphics.Matrix trans = new android.graphics.Matrix();
- trans.setRotate(-angle);
- trans.mapPoints(points);
- }
-
- float minx = Float.MAX_VALUE;
- float miny = Float.MAX_VALUE;
- float maxx = Float.MIN_VALUE;
- float maxy = Float.MIN_VALUE;
- int count = points.length;
- for (int i = 0; i < count; i++) {
- if (points[i] < minx) {
- minx = points[i];
- }
- if (points[i] > maxx) {
- maxx = points[i];
- }
- i++;
- if (points[i] < miny) {
- miny = points[i];
- }
- if (points[i] > maxy) {
- maxy = points[i];
- }
- }
-
- OrientedBoundingBox bbx = new OrientedBoundingBox(angle, centroid[0], centroid[1], maxx
- - minx, maxy - miny);
- return bbx;
- }
-
- private static double[] computeOrientation(double[][] covarianceMatrix) {
- double[] targetVector = new double[2];
- if (covarianceMatrix[0][1] == 0 || covarianceMatrix[1][0] == 0) {
- targetVector[0] = 1;
- targetVector[1] = 0;
- }
-
- // lamda^2 + a * lamda + b = 0
- double a = -covarianceMatrix[0][0] - covarianceMatrix[1][1];
- double b = covarianceMatrix[0][0] * covarianceMatrix[1][1] - covarianceMatrix[0][1]
- * covarianceMatrix[1][0];
- double value = a / 2;
- double rightside = Math.sqrt(Math.pow(value, 2) - b);
- double lambda1 = -value + rightside;
- double lambda2 = -value - rightside;
- if (lambda1 == lambda2) {
- targetVector[0] = 0;
- targetVector[1] = 0;
- } else {
- double lambda = lambda1 > lambda2 ? lambda1 : lambda2;
- targetVector[0] = 1;
- targetVector[1] = (lambda - covarianceMatrix[0][0]) / covarianceMatrix[0][1];
- }
- return targetVector;
- }
-}
diff --git a/tests/sketch/src/com/android/gesture/Instance.java b/tests/sketch/src/com/android/gesture/Instance.java
deleted file mode 100755
index 4eb10f9..0000000
--- a/tests/sketch/src/com/android/gesture/Instance.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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.gesture;
-
-/**
- * An instance represents a sample if the label is available or a query if the
- * label is null.
- */
-public class Instance {
-
- private static final int SEQUENCE_SAMPLE_SIZE = 16;
-
- private static final int PATCH_SAMPLE_SIZE = 8;
-
- private final static float[] ORIENTATIONS = {
- 0, 45, 90, 135, 180, -0, -45, -90, -135, -180
- };
-
- // the feature vector
- public final float[] vector;
-
- // the label can be null
- public final String label;
-
- // the length of the vector
- public final float magnitude;
-
- // the id of the instance
- public final long instanceID;
-
- private Instance(long id, float[] sample, String sampleName) {
- instanceID = id;
- vector = sample;
- label = sampleName;
- float sum = 0;
- int size = sample.length;
- for (int i = 0; i < size; i++) {
- sum += sample[i] * sample[i];
- }
- magnitude = (float) Math.sqrt(sum);
- }
-
- /**
- * create a learning instance for a single stroke gesture
- *
- * @param gesture
- * @param label
- * @return the instance
- */
- public static Instance createInstance(GestureLibrary gesturelib, Gesture gesture, String label) {
- float[] pts;
- if (gesturelib.getGestureType() == GestureLibrary.SEQUENCE_SENSITIVE) {
- pts = sequenceSampler(gesturelib, gesture);
- } else {
- pts = spatialSampler(gesture);
- }
- return new Instance(gesture.getID(), pts, label);
- }
-
- private static float[] spatialSampler(Gesture gesture) {
- float[] pts = GestureUtils.spatialFeaturize(gesture, PATCH_SAMPLE_SIZE);
- return pts;
- }
-
- private static float[] sequenceSampler(GestureLibrary gesturelib, Gesture gesture) {
- float[] pts = GestureUtils.sequentialFeaturize(gesture.getStrokes().get(0),
- SEQUENCE_SAMPLE_SIZE);
- float[] center = GestureUtils.computeCentroid(pts);
- float orientation = (float) Math.atan2(pts[1] - center[1], pts[0] - center[0]);
- orientation *= 180 / Math.PI;
-
- float adjustment = -orientation;
- if (gesturelib.getOrientationStyle() == GestureLibrary.ORIENTATION_SENSITIVE) {
- int count = ORIENTATIONS.length;
- for (int i = 0; i < count; i++) {
- float delta = ORIENTATIONS[i] - orientation;
- if (Math.abs(delta) < Math.abs(adjustment)) {
- adjustment = delta;
- }
- }
- }
-
- android.graphics.Matrix m = new android.graphics.Matrix();
- m.setTranslate(-center[0], -center[1]);
- android.graphics.Matrix rotation = new android.graphics.Matrix();
- rotation.setRotate(adjustment);
- m.postConcat(rotation);
- m.mapPoints(pts);
- return pts;
- }
-
-}
diff --git a/tests/sketch/src/com/android/gesture/InstanceLearner.java b/tests/sketch/src/com/android/gesture/InstanceLearner.java
deleted file mode 100644
index 3bd875b..0000000
--- a/tests/sketch/src/com/android/gesture/InstanceLearner.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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.gesture;
-
-import android.util.Config;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.TreeMap;
-
-/**
- * An implementation of an instance-based learner
- */
-
-class InstanceLearner extends Learner {
-
- private static final String LOGTAG = "InstanceLearner";
-
- @Override
- ArrayList<Prediction> classify(GestureLibrary lib, Instance instance) {
- ArrayList<Prediction> predictions = new ArrayList<Prediction>();
- ArrayList<Instance> instances = getInstances();
- int count = instances.size();
- TreeMap<String, Double> label2score = new TreeMap<String, Double>();
- for (int i = 0; i < count; i++) {
- Instance sample = instances.get(i);
- if (sample.vector.length != instance.vector.length) {
- continue;
- }
- double distance;
- if (lib.getGestureType() == GestureLibrary.SEQUENCE_SENSITIVE) {
- distance = GestureUtils.cosineDistance(sample, instance);
- } else {
- distance = GestureUtils.euclideanDistance(sample.vector, instance.vector);
- }
- double weight;
- if (distance == 0) {
- weight = Double.MAX_VALUE;
- } else {
- weight = 1 / distance;
- }
- Double score = label2score.get(sample.label);
- if (score == null || weight > score) {
- label2score.put(sample.label, weight);
- }
- }
-
- double sum = 0;
- Iterator<String> lableIterator = label2score.keySet().iterator();
- while (lableIterator.hasNext()) {
- String name = lableIterator.next();
- double score = label2score.get(name);
- sum += score;
- predictions.add(new Prediction(name, score));
- }
-
- // normalize
- Iterator<Prediction> predictionIterator = predictions.iterator();
- while (predictionIterator.hasNext()) {
- Prediction name = predictionIterator.next();
- name.predictionScore /= sum;
- }
-
- Collections.sort(predictions, new Comparator<Prediction>() {
- public int compare(Prediction object1, Prediction object2) {
- double score1 = object1.predictionScore;
- double score2 = object2.predictionScore;
- if (score1 > score2) {
- return -1;
- } else if (score1 < score2) {
- return 1;
- } else {
- return 0;
- }
- }
- });
-
- if (Config.DEBUG) {
- predictionIterator = predictions.iterator();
- while (predictionIterator.hasNext()) {
- Prediction name = predictionIterator.next();
- Log.v(LOGTAG, "prediction [" + name.gestureName + " = " + name.predictionScore + "]");
- }
- }
-
- return predictions;
- }
-}
diff --git a/tests/sketch/src/com/android/gesture/Learner.java b/tests/sketch/src/com/android/gesture/Learner.java
deleted file mode 100755
index 63f3156..0000000
--- a/tests/sketch/src/com/android/gesture/Learner.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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.gesture;
-
-import java.util.ArrayList;
-
-/**
- * The abstract class of a gesture learner
- */
-abstract class Learner {
-
- private final ArrayList<Instance> mInstances = new ArrayList<Instance>();
-
- /**
- * Add an instance to the learner
- *
- * @param instance
- */
- void addInstance(Instance instance) {
- mInstances.add(instance);
- }
-
- /**
- * Retrieve all the instances
- *
- * @return instances
- */
- ArrayList<Instance> getInstances() {
- return mInstances;
- }
-
- /**
- * Remove an instance based on its id
- *
- * @param id
- */
- void removeInstance(long id) {
- ArrayList<Instance> instances = mInstances;
- int count = instances.size();
- for (int i = 0; i < count; i++) {
- Instance instance = instances.get(i);
- if (id == instance.instanceID) {
- instances.remove(instance);
- return;
- }
- }
- }
-
- /**
- * Remove all the instances of a category
- *
- * @param name the category name
- */
- void removeInstances(String name) {
- ArrayList<Instance> toDelete = new ArrayList<Instance>();
- ArrayList<Instance> instances = mInstances;
- int count = instances.size();
- for (int i = 0; i < count; i++) {
- Instance instance = instances.get(i);
- if (instance.label.equals(name)) {
- toDelete.add(instance);
- }
- }
- mInstances.removeAll(toDelete);
- }
-
- abstract ArrayList<Prediction> classify(GestureLibrary library, Instance instance);
-}
diff --git a/tests/sketch/src/com/android/gesture/OrientedBoundingBox.java b/tests/sketch/src/com/android/gesture/OrientedBoundingBox.java
deleted file mode 100644
index fe1984c..0000000
--- a/tests/sketch/src/com/android/gesture/OrientedBoundingBox.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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.gesture;
-
-import android.graphics.Matrix;
-import android.graphics.Path;
-
-/**
- * An oriented bounding box
- */
-public class OrientedBoundingBox {
-
- public final float squareness;
-
- public final float width;
- public final float height;
-
- public final float orientation; // -PI<alpha<PI
-
- public final float centerX;
- public final float centerY;
-
- OrientedBoundingBox(float angle, float cx, float cy, float w, float h) {
- orientation = angle;
- width = w;
- height = h;
- centerX = cx;
- centerY = cy;
- float ratio = w / h;
- if (ratio > 1) {
- squareness = 1 / ratio;
- } else {
- squareness = ratio;
- }
- }
-
- public Path toPath() {
- Path path = new Path();
- float[] point = new float[2];
- point[0] = -width / 2;
- point[1] = height / 2;
- Matrix matrix = new Matrix();
- matrix.setRotate(orientation);
- matrix.postTranslate(centerX, centerY);
- matrix.mapPoints(point);
- path.moveTo(point[0], point[1]);
-
- point[0] = -width / 2;
- point[1] = -height / 2;
- matrix.mapPoints(point);
- path.lineTo(point[0], point[1]);
-
- point[0] = width / 2;
- point[1] = -height / 2;
- matrix.mapPoints(point);
- path.lineTo(point[0], point[1]);
-
- point[0] = width / 2;
- point[1] = height / 2;
- matrix.mapPoints(point);
- path.lineTo(point[0], point[1]);
-
- path.close();
-
- return path;
- }
-}
diff --git a/tests/sketch/src/com/android/gesture/Prediction.java b/tests/sketch/src/com/android/gesture/Prediction.java
deleted file mode 100755
index 60cca8b..0000000
--- a/tests/sketch/src/com/android/gesture/Prediction.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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.gesture;
-
-public class Prediction {
- public final String gestureName;
-
- public double predictionScore;
-
- Prediction(String label, double score) {
- gestureName = label;
- predictionScore = score;
- }
-
- @Override
- public String toString() {
- return gestureName;
- }
-}
diff --git a/tests/sketch/src/com/android/gesture/example/ContactAdapter.java b/tests/sketch/src/com/android/gesture/example/ContactAdapter.java
deleted file mode 100644
index 008a972..0000000
--- a/tests/sketch/src/com/android/gesture/example/ContactAdapter.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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.gesture.example;
-
-import android.app.Activity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-
-class ContactAdapter extends ArrayAdapter<ContactItem> {
-
- private LayoutInflater mInflater;
-
- public ContactAdapter(Activity activity, ArrayList<ContactItem> contacts) {
- super(activity, 0, contacts);
- mInflater = activity.getLayoutInflater();
- }
-
- @Override
- public ContactItem getItem(int position) {
- return super.getItem(position);
- }
-
- @Override
- public long getItemId(int position) {
- return getItem(position).itemID;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- final ContactItem info = getItem(position);
-
- View view = convertView;
- if (view == null) {
- view = mInflater.inflate(android.R.layout.simple_list_item_1, parent, false);
- view.setTag(view.findViewById(android.R.id.text1));
- }
-
- final TextView textView = (TextView)view.getTag();
- textView.setText(info.toString());
-
- return view;
- }
-
- public int search(String query) {
- if (query != null && query.length() > 0) {
- int start = 0;
- int end = getCount() - 1;
- int index = binarySearch(query, start, end);
- for (index = index - 1; index >= 0; index--) {
- String str = getItem(index).toString().toLowerCase();
- if (!str.startsWith(query)) {
- return index + 1;
- }
- if (index == 0) {
- return 0;
- }
- }
- return -1;
- } else {
- return -1;
- }
- }
-
- private int binarySearch(String prefix, int start, int end) {
- if (start > end) {
- return -1;
- }
- int mid = (start + end) / 2;
- String str = getItem(mid).toString().toLowerCase();
- if (prefix.compareTo(str) <= 0) {
- if (str.startsWith(prefix)) {
- return mid;
- } else {
- return binarySearch(prefix, start, mid - 1);
- }
- } else {
- return binarySearch(prefix, mid + 1, end);
- }
- }
-
-}
diff --git a/tests/sketch/src/com/android/gesture/example/ContactItem.java b/tests/sketch/src/com/android/gesture/example/ContactItem.java
deleted file mode 100644
index 557c4d9..0000000
--- a/tests/sketch/src/com/android/gesture/example/ContactItem.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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.gesture.example;
-
-
-class ContactItem {
- final String itemName;
-
- final long itemID;
-
- public ContactItem(long id, String name) {
- itemID = id;
- itemName = name;
- }
-
- @Override
- public String toString() {
- return itemName;
- }
-}
diff --git a/tests/sketch/src/com/android/gesture/example/ContactListGestureOverlay.java b/tests/sketch/src/com/android/gesture/example/ContactListGestureOverlay.java
deleted file mode 100644
index 50d349a..0000000
--- a/tests/sketch/src/com/android/gesture/example/ContactListGestureOverlay.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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.gesture.example;
-
-import android.app.Activity;
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.Intent;
-import android.database.Cursor;
-import android.os.Bundle;
-import android.os.Environment;
-import android.provider.Contacts.People;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.widget.AdapterView;
-import android.widget.ListView;
-
-import com.android.gesture.Gesture;
-import com.android.gesture.GestureActionListener;
-import com.android.gesture.GestureProcessor;
-import com.android.gesture.GestureLibrary;
-import com.android.gesture.GestureOverlay;
-import com.android.gesture.Prediction;
-
-import java.io.File;
-import java.util.ArrayList;
-
-public class ContactListGestureOverlay extends Activity {
-
- static final String GESTURE_FILE_NAME = Environment.getExternalStorageDirectory().getAbsolutePath()
- + File.separator + "gestureOverlay.xml";
-
- private static final String SORT_ORDER = People.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
-
- private static final String[] CONTACTS_PROJECTION = new String[] {
- People._ID, // 0
- People.DISPLAY_NAME, // 1
- };
-
- private GestureOverlay mOverlay;
-
- private ContactAdapter mContactAdapter;
-
- private GestureProcessor mGestureProcessor;
-
- private GestureLibrary mLibrary;
-
- private ListView mContactList;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
- setContentView(R.layout.overlaydemo);
-
- setProgressBarIndeterminateVisibility(true);
-
- // load the gesture library
- mLibrary = new GestureLibrary(GESTURE_FILE_NAME);
- mLibrary.load();
-
- // load the contact list
- mContactList = (ListView)this.findViewById(R.id.list);
- registerForContextMenu(mContactList);
- mContactList.setTextFilterEnabled(true);
- mContactList.setVerticalScrollBarEnabled(true);
- mContactList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
- if (!mGestureProcessor.isGesturing()) {
- Intent intent = new Intent(Intent.ACTION_VIEW, ContentUris.withAppendedId(
- People.CONTENT_URI, id));
- startActivity(intent);
- }
- }
- });
- ContentResolver resolver = getContentResolver();
- Cursor cursor = resolver.query(People.CONTENT_URI, CONTACTS_PROJECTION, null, null,
- SORT_ORDER);
- ArrayList<ContactItem> list = new ArrayList<ContactItem>();
- while (cursor.moveToNext()) {
- list.add(new ContactItem(cursor.getLong(0), cursor.getString(1)));
- }
- mContactAdapter = new ContactAdapter(this, list);
- mContactList.setAdapter(mContactAdapter);
-
- setProgressBarIndeterminateVisibility(false);
-
- // add a gesture overlay on top of the ListView
- mOverlay = new GestureOverlay(this);
- mGestureProcessor = new GestureProcessor(mContactList);
- mGestureProcessor.addGestureActionListener(new GestureActionListener() {
- public void onGesturePerformed(GestureOverlay overlay, Gesture gesture) {
- ArrayList<Prediction> predictions = mLibrary.recognize(gesture);
- if (!predictions.isEmpty()) {
- int index = mContactAdapter.search(predictions.get(0).gestureName);
- if (index != -1) {
- mContactList.setSelection(index);
- }
- }
- }
- });
- mOverlay.addGestureListener(mGestureProcessor);
- ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT);
- this.addContentView(mOverlay, params);
- }
-}
diff --git a/tests/sketch/src/com/android/gesture/example/GestureEntry.java b/tests/sketch/src/com/android/gesture/example/GestureEntry.java
deleted file mode 100644
index 6a54b49..0000000
--- a/tests/sketch/src/com/android/gesture/example/GestureEntry.java
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (C) 2008-2009 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.gesture.example;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.graphics.Color;
-import android.os.Bundle;
-import android.os.Environment;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.Spinner;
-import android.widget.AdapterView.OnItemSelectedListener;
-
-import com.android.gesture.Gesture;
-import com.android.gesture.GestureLibrary;
-import com.android.gesture.GestureListener;
-import com.android.gesture.GestureOverlay;
-import com.android.gesture.Prediction;
-
-import java.io.File;
-import java.util.ArrayList;
-
-public class GestureEntry extends Activity {
-
- private static final String PARCEL_KEY = "gesture";
-
- static final String GESTURE_FILE_NAME = Environment.getExternalStorageDirectory().getAbsolutePath()
- + File.separator + "gestureEntry.xml";
-
- private static final int DIALOG_NEW_ENTRY = 1;
-
- private static final int NEW_ID = Menu.FIRST;
-
- private static final int VIEW_ID = Menu.FIRST + 1;
-
- private GestureOverlay mGesturePad;
-
- private Spinner mRecognitionResult;
-
- private GestureLibrary mGestureLibrary;
-
- private boolean mChangedByRecognizer = false;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.demo);
-
- // init the gesture library
- mGestureLibrary = new GestureLibrary(GESTURE_FILE_NAME);
- mGestureLibrary.load();
-
- // create the spinner for showing the recognition results
- // the spinner also allows a user to correct a prediction
- mRecognitionResult = (Spinner) findViewById(R.id.spinner);
- mRecognitionResult.setOnItemSelectedListener(new OnItemSelectedListener() {
-
- public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- // correct the recognition result by adding the new example
- if (!mChangedByRecognizer) {
- mGestureLibrary.addGesture(parent.getSelectedItem().toString(), mGesturePad
- .getCurrentGesture());
- } else {
- mChangedByRecognizer = false;
- }
- }
-
- public void onNothingSelected(AdapterView<?> parent) {
-
- }
-
- });
-
- // create the area for drawing a gesture
- mGesturePad = (GestureOverlay) findViewById(R.id.drawingpad);
- mGesturePad.setBackgroundColor(Color.BLACK);
- mGesturePad.addGestureListener(new GestureListener() {
- public void onFinishGesture(GestureOverlay pad, MotionEvent event) {
- recognize(pad.getCurrentGesture());
- pad.clear(true);
- }
-
- public void onGesture(GestureOverlay pad, MotionEvent event) {
- }
-
- public void onStartGesture(GestureOverlay pad, MotionEvent event) {
- }
- });
-
- if (savedInstanceState != null) {
- Gesture g = (Gesture) savedInstanceState.getParcelable(PARCEL_KEY);
- if (g != null) {
- mGesturePad.setCurrentGesture(g);
- }
- }
- }
-
- @Override
- protected Dialog onCreateDialog(int id) {
- LayoutInflater factory = LayoutInflater.from(this);
- final View textEntryView = factory.inflate(R.layout.newgesture_dialog, null);
- return new AlertDialog.Builder(GestureEntry.this).setTitle(
- R.string.newgesture_text_entry).setView(textEntryView).setPositiveButton(
- R.string.newgesture_dialog_ok, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton) {
- EditText edittext = (EditText) ((AlertDialog) dialog)
- .findViewById(R.id.gesturename_edit);
- String text = edittext.getText().toString().trim();
- if (text.length() > 0) {
- mGestureLibrary.addGesture(text, mGesturePad.getCurrentGesture());
- }
- }
- }).setNegativeButton(R.string.newgesture_dialog_cancel,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton) {
- }
- }).create();
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- menu.add(0, NEW_ID, 0, R.string.newgesture).setShortcut('0', 'n').setIcon(
- android.R.drawable.ic_menu_add);
- menu.add(0, VIEW_ID, 0, R.string.viewgesture).setShortcut('1', 'v').setIcon(
- android.R.drawable.ic_menu_view);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case NEW_ID:
- if (mGesturePad.getCurrentGesture() != null) {
- showDialog(DIALOG_NEW_ENTRY);
- }
- break;
-
- case VIEW_ID:
- startActivityForResult(new Intent(this, GestureLibViewer.class), VIEW_ID);
- break;
- }
-
- return super.onOptionsItemSelected(item);
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- mGestureLibrary.load();
- mGesturePad.clear(false);
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- mGestureLibrary.save();
- }
-
- @Override
- protected void onPrepareDialog(int id, Dialog dialog) {
- super.onPrepareDialog(id, dialog);
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- Gesture gesture = mGesturePad.getCurrentGesture();
- if (gesture != null) {
- outState.putParcelable(PARCEL_KEY, gesture);
- }
- mGestureLibrary.save();
- }
-
- private void recognize(Gesture ink) {
- mChangedByRecognizer = true;
- ArrayList<Prediction> predictions = mGestureLibrary.recognize(ink);
- ArrayAdapter<Prediction> adapter = new ArrayAdapter<Prediction>(this,
- android.R.layout.simple_spinner_item, predictions);
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- mRecognitionResult.setAdapter(adapter);
- }
-
-}
diff --git a/tests/sketch/src/com/android/gesture/example/GestureEntryDemo.java b/tests/sketch/src/com/android/gesture/example/GestureEntryDemo.java
old mode 100644
new mode 100755
index 52a2ba8..8fee21a
--- a/tests/sketch/src/com/android/gesture/example/GestureEntryDemo.java
+++ b/tests/sketch/src/com/android/gesture/example/GestureEntryDemo.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Google Inc.
+ * Copyright (C) 2008 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.
@@ -21,34 +21,29 @@
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
-import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
-import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
-import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.AdapterView.OnItemSelectedListener;
import com.android.gesture.Gesture;
-import com.android.gesture.GestureLibrary;
+import com.android.gesture.GestureLib;
import com.android.gesture.GestureListener;
import com.android.gesture.GesturePad;
-import com.android.gesture.Prediction;
+import com.android.gesture.R;
+import com.android.gesture.recognizer.Prediction;
import java.util.ArrayList;
/**
* The demo shows how to construct a gesture-based user interface on Android.
- *
- * @author liyang@google.com (Yang Li)
- *
*/
public class GestureEntryDemo extends Activity {
@@ -57,35 +52,31 @@
private static final int NEW_ID = Menu.FIRST;
private static final int VIEW_ID = Menu.FIRST + 1;
- private GesturePad mGesturePad;
- private Spinner mRecognitionResult;
- private GestureLibrary mGestureLibrary;
- private boolean mChangedByRecognizer = false;
+ GesturePad mView;
+ Spinner mResult;
+ GestureLib mRecognizer;
+ boolean mChangedByRecognizer = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.demo);
- // init the gesture library
- mGestureLibrary = new GestureLibrary(
- "/sdcard/gestureentry/gestures.xml");
- mGestureLibrary.load();
+ // init the recognizer
+ mRecognizer = new GestureLib("/sdcard/gestureentry");
+ mRecognizer.load();
// create the spinner for showing the recognition results
// the spinner also allows a user to correct a prediction
- mRecognitionResult = (Spinner) findViewById(R.id.spinner);
- mRecognitionResult.setOnItemSelectedListener(
- new OnItemSelectedListener() {
+ mResult = (Spinner) findViewById(R.id.spinner);
+ mResult.setOnItemSelectedListener(new OnItemSelectedListener() {
- public void onItemSelected(
- AdapterView<?> parent, View view, int position, long id) {
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
// TODO Auto-generated method stub
// correct the recognition result by adding the new example
if (mChangedByRecognizer == false) {
- mGestureLibrary.addGesture(
- parent.getSelectedItem().toString(),
- mGesturePad.getCurrentGesture());
+ mRecognizer.addGesture(parent.getSelectedItem().toString(),
+ mView.getCurrentGesture());
} else {
mChangedByRecognizer = false;
}
@@ -99,35 +90,28 @@
});
// create the area for drawing a gesture
- mGesturePad = (GesturePad)this.findViewById(R.id.drawingpad);
- mGesturePad.setBackgroundColor(Color.BLACK);
- mGesturePad.addGestureListener(new GestureListener() {
- public void onFinishGesture(GesturePad pad, MotionEvent event) {
+ mView = (GesturePad)this.findViewById(R.id.drawingpad);
+ mView.cacheGesture(false);
+ mView.setFadingOut(false);
+ mView.addGestureListener(new GestureListener() {
+ public void onFinishGesture(GesturePad patch, MotionEvent event) {
// TODO Auto-generated method stub
- recognize(pad.getCurrentGesture());
+ recognize(patch.getCurrentGesture());
}
- public void onGesture(GesturePad pad, MotionEvent event) {
+ public void onGesture(GesturePad patch, MotionEvent event) {
// TODO Auto-generated method stub
+
}
- public void onStartGesture(GesturePad pad, MotionEvent event) {
- // TODO Auto-generated method stub
+ public void onStartGesture(GesturePad patch, MotionEvent event) {
+ // TODO Auto-generated method stub
+
}
});
- Button clear = (Button)this.findViewById(R.id.clear);
- clear.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- // TODO Auto-generated method stub
- mGesturePad.clear(false);
- mGesturePad.invalidate();
- }
- });
if (savedInstanceState != null) {
- Gesture g = (Gesture)savedInstanceState.getParcelable("gesture");
- if (g != null) {
- mGesturePad.setCurrentGesture(g);
- }
+ mView.setCurrentGesture(
+ (Gesture)savedInstanceState.getParcelable("gesture"));
}
}
@@ -145,12 +129,10 @@
public void onClick(DialogInterface dialog, int whichButton) {
/* User clicked OK so do some stuff */
EditText edittext =
- (EditText)((AlertDialog)dialog).findViewById(
- R.id.gesturename_edit);
+ (EditText)((AlertDialog)dialog).findViewById(R.id.gesturename_edit);
String text = edittext.getText().toString().trim();
if (text.length() > 0) {
- mGestureLibrary.addGesture(
- text, mGesturePad.getCurrentGesture());
+ mRecognizer.addGesture(text, mView.getCurrentGesture());
}
}
})
@@ -182,7 +164,7 @@
switch (item.getItemId()) {
case NEW_ID:
// if there has been a gesture on the canvas
- if (mGesturePad.getCurrentGesture() != null) {
+ if (mView.getCurrentGesture() != null) {
showDialog(DIALOG_NEW_ENTRY);
}
break;
@@ -198,17 +180,16 @@
@Override
- protected void onActivityResult(
- int requestCode, int resultCode, Intent data) {
- mGestureLibrary.load();
- mGesturePad.clear(false);
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ mRecognizer.load();
+ mView.clear();
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
- mGestureLibrary.save();
+ mRecognizer.save();
}
@@ -222,20 +203,18 @@
protected void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub
super.onSaveInstanceState(outState);
- Gesture gesture = mGesturePad.getCurrentGesture();
- if (gesture != null)
- outState.putParcelable("gesture", gesture);
- mGestureLibrary.save();
+ outState.putParcelable("gesture", mView.getCurrentGesture());
+ mRecognizer.save();
}
public void recognize(Gesture ink) {
mChangedByRecognizer = true;
- ArrayList<Prediction> predictions = mGestureLibrary.recognize(ink);
- ArrayAdapter<Prediction> adapter = new ArrayAdapter<Prediction>(this,
+ ArrayList<Prediction> predictions = mRecognizer.recognize(ink);
+ ArrayAdapter adapter = new ArrayAdapter(this,
android.R.layout.simple_spinner_item, predictions);
adapter.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_item);
- mRecognitionResult.setAdapter(adapter);
+ mResult.setAdapter(adapter);
}
}
diff --git a/tests/sketch/src/com/android/gesture/example/GestureLibViewer.java b/tests/sketch/src/com/android/gesture/example/GestureLibViewer.java
old mode 100644
new mode 100755
index ca54110..7ae7fc5
--- a/tests/sketch/src/com/android/gesture/example/GestureLibViewer.java
+++ b/tests/sketch/src/com/android/gesture/example/GestureLibViewer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2009 The Android Open Source Project
+ * Copyright (C) 2008 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.
@@ -17,6 +17,8 @@
package com.android.gesture.example;
import android.app.Activity;
+import android.graphics.Matrix;
+import android.graphics.Path;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
@@ -28,156 +30,228 @@
import android.widget.AdapterView.OnItemSelectedListener;
import com.android.gesture.Gesture;
-import com.android.gesture.GestureLibrary;
-import com.android.gesture.GestureOverlay;
+import com.android.gesture.GestureLib;
+import com.android.gesture.GesturePad;
+import com.android.gesture.R;
+import com.android.gesture.recognizer.Instance;
import java.util.ArrayList;
import java.util.Collections;
/**
- * GestureLibViewer gives an example on how to browse existing gestures and
+ * GestureLibViewer is for viewing existing gestures and
* removing unwanted gestures.
*/
-public class GestureLibViewer extends Activity {
-
- private GestureOverlay mGesturePad;
-
- private Spinner mGestureCategory;
-
- private GestureLibrary mGesureLibrary;
-
- private ArrayList<Gesture> mGestures;
-
- private int mCurrentGestureIndex;
-
- private class RemoveGestureListener implements OnClickListener {
- public void onClick(View v) {
- if (mGestures.isEmpty()) {
- return;
- }
-
- String name = (String) mGestureCategory.getSelectedItem();
- Gesture gesture = mGestures.get(mCurrentGestureIndex);
- mGesureLibrary.removeGesture(name, gesture);
-
- mGestures = mGesureLibrary.getGestures(name);
-
- if (mGestures == null) {
- // delete the entire entry
- mCurrentGestureIndex = 0;
- ArrayList<String> list = new ArrayList<String>();
- list.addAll(mGesureLibrary.getGestureEntries());
- Collections.sort(list);
- ArrayAdapter<String> adapter = new ArrayAdapter<String>(GestureLibViewer.this,
- android.R.layout.simple_spinner_item, list);
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- mGestureCategory.setAdapter(adapter);
- } else {
- if (mCurrentGestureIndex > mGestures.size() - 1) {
- mCurrentGestureIndex--;
- }
- gesture = mGestures.get(mCurrentGestureIndex);
- mGesturePad.setCurrentGesture(gesture);
- mGesturePad.invalidate();
- }
- }
- }
+public class GestureLibViewer extends Activity {
+
+ GesturePad mView;
+ Spinner mResult;
+ GestureLib mRecognizer;
+ ArrayList<Gesture> mSamples;
+ int mCurrentGestureIndex;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gestureviewer);
+
+ // create the area for drawing a glyph
+ mView = (GesturePad)this.findViewById(R.id.drawingpad);
+ mView.cacheGesture(false);
+ mView.setFadingOut(false);
+ mView.setEnableInput(false);
+
+ // init the recognizer
+ mRecognizer = new GestureLib("/sdcard/gestureentry");
+ mRecognizer.load();
- // create the area for drawing a gesture
- mGesturePad = (GestureOverlay) findViewById(R.id.drawingpad);
- mGesturePad.setEnabled(false);
-
- // init the gesture library
- mGesureLibrary = new GestureLibrary(GestureEntry.GESTURE_FILE_NAME);
- mGesureLibrary.load();
-
- mGestureCategory = (Spinner) findViewById(R.id.spinner);
+ mResult = (Spinner) findViewById(R.id.spinner);
ArrayList<String> list = new ArrayList<String>();
- if (!mGesureLibrary.getGestureEntries().isEmpty()) {
- list.addAll(mGesureLibrary.getGestureEntries());
- Collections.sort(list);
- ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
- android.R.layout.simple_spinner_item, list);
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- mGestureCategory.setAdapter(adapter);
- mGestures = mGesureLibrary.getGestures(list.get(0));
+ list.addAll(mRecognizer.getLabels());
+ Collections.sort(list);
+ ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
+ android.R.layout.simple_spinner_item,
+ list);
+ adapter.setDropDownViewResource(
+ android.R.layout.simple_spinner_dropdown_item);
+ mResult.setAdapter(adapter);
+ mSamples = mRecognizer.getGestures(list.get(0));
+ if (mSamples.isEmpty() == false) {
mCurrentGestureIndex = 0;
- Gesture gesture = mGestures.get(mCurrentGestureIndex);
- mGesturePad.setCurrentGesture(gesture);
+ Gesture gesture = mSamples.get(mCurrentGestureIndex);
+ mView.setCurrentGesture(gesture);
+ mView.clearDebugPath();
+ mView.addDebugPath(
+ toPath(mRecognizer.getClassifier().getInstance(gesture.getID())));
}
-
- mGestureCategory.setOnItemSelectedListener(new OnItemSelectedListener() {
+
+ mResult.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- mGestures = mGesureLibrary.getGestures((String) mGestureCategory.getSelectedItem());
- if (!mGestures.isEmpty()) {
+ // TODO Auto-generated method stub
+ mSamples = mRecognizer.getGestures(
+ (String)mResult.getSelectedItem());
+ if (mSamples.isEmpty() == false) {
mCurrentGestureIndex = 0;
- Gesture gesture = mGestures.get(mCurrentGestureIndex);
- mGesturePad.setCurrentGesture(gesture);
+ Gesture gesture = mSamples.get(mCurrentGestureIndex);
+ mView.setCurrentGesture(gesture);
+ mView.clearDebugPath();
+ mView.addDebugPath(
+ toPath(mRecognizer.getClassifier().getInstance(gesture.getID())));
}
- mGesturePad.invalidate();
+ mView.invalidate();
}
-
+
public void onNothingSelected(AdapterView<?> parent) {
+ // TODO Auto-generated method stub
+
}
-
+
});
-
- Button remove = (Button) findViewById(R.id.remove);
- remove.setOnClickListener(new RemoveGestureListener());
-
- Button next = (Button) findViewById(R.id.next);
+
+ Button remove = (Button)this.findViewById(R.id.remove);
+ remove.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ // TODO Auto-generated method stub
+ if (mSamples.isEmpty())
+ return;
+
+ String name = (String)mResult.getSelectedItem();
+ Gesture gesture = mSamples.get(mCurrentGestureIndex);
+ mRecognizer.removeGesture(name, gesture);
+
+ mSamples = mRecognizer.getGestures(name);
+
+ if (mSamples == null) {
+ // delete the entire entry
+ mCurrentGestureIndex = 0;
+ ArrayList<String> list = new ArrayList<String>();
+ list.addAll(mRecognizer.getLabels());
+ Collections.sort(list);
+ ArrayAdapter<String> adapter = new ArrayAdapter<String>(
+ GestureLibViewer.this,
+ android.R.layout.simple_spinner_item,
+ list);
+ adapter.setDropDownViewResource(
+ android.R.layout.simple_spinner_dropdown_item);
+ mResult.setAdapter(adapter);
+ } else {
+ if (mCurrentGestureIndex > mSamples.size()-1) {
+ mCurrentGestureIndex--;
+ }
+ gesture = mSamples.get(mCurrentGestureIndex);
+ mView.setCurrentGesture(gesture);
+ mView.clearDebugPath();
+ mView.addDebugPath(
+ toPath(mRecognizer.getClassifier().getInstance(gesture.getID())));
+ mView.invalidate();
+ }
+ }
+ });
+
+ Button next = (Button)this.findViewById(R.id.next);
next.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
- if (mCurrentGestureIndex >= mGestures.size() - 1) {
+ // TODO Auto-generated method stub
+ if (mCurrentGestureIndex >= mSamples.size()-1)
return;
- }
+
mCurrentGestureIndex++;
- Gesture gesture = mGestures.get(mCurrentGestureIndex);
- mGesturePad.setCurrentGesture(gesture);
- mGesturePad.invalidate();
+ Gesture gesture = mSamples.get(mCurrentGestureIndex);
+ mView.setCurrentGesture(gesture);
+ mView.clearDebugPath();
+ mView.addDebugPath(
+ toPath(mRecognizer.getClassifier().getInstance(gesture.getID())));
+ mView.invalidate();
}
});
- Button previous = (Button) findViewById(R.id.previous);
+ Button previous = (Button)this.findViewById(R.id.previous);
previous.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
- if (mCurrentGestureIndex >= 1 && !mGestures.isEmpty()) {
+ // TODO Auto-generated method stub
+ if (mCurrentGestureIndex >= 1 &&
+ mSamples.isEmpty() == false) {
mCurrentGestureIndex--;
- Gesture gesture = mGestures.get(mCurrentGestureIndex);
- mGesturePad.setCurrentGesture(gesture);
- mGesturePad.invalidate();
+ Gesture gesture = mSamples.get(mCurrentGestureIndex);
+ mView.setCurrentGesture(gesture);
+ mView.clearDebugPath();
+ mView.addDebugPath(
+ toPath(mRecognizer.getClassifier().getInstance(gesture.getID())));
+ mView.invalidate();
}
}
});
}
-
+
+ public static ArrayList<Path> toPath(Instance instance) {
+ ArrayList<Path> paths = new ArrayList();
+ Path path = null;
+ float minx = 0, miny = 0;
+ float mX = 0, mY = 0;
+ for (int i=0; i<instance.vector.length; i+=2) {
+ float x = instance.vector[i];
+ float y = instance.vector[i+1];
+ if (x < minx)
+ minx = x;
+ if (y < miny)
+ miny = y;
+ if (path == null) {
+ path = new Path();
+ path.moveTo(x, y);
+ mX = x;
+ mY = y;
+ } else {
+ float dx = Math.abs(x - mX);
+ float dy = Math.abs(y - mY);
+ if (dx >= 3 || dy >= 3) {
+ path.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
+ mX = x;
+ mY = y;
+ }
+ }
+ }
+ Matrix matrix = new Matrix();
+ matrix.setTranslate(-minx + 10, -miny + 10);
+ path.transform(matrix);
+ paths.add(path);
+
+ path = new Path();
+ path.moveTo(instance.vector[0]-5, instance.vector[1]-5);
+ path.lineTo(instance.vector[0]-5, instance.vector[1]+5);
+ path.lineTo(instance.vector[0]+5, instance.vector[1]+5);
+ path.lineTo(instance.vector[0]+5, instance.vector[1]-5);
+ path.close();
+ path.transform(matrix);
+ paths.add(path);
+
+ return paths;
+ }
+
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK) {
- mGesureLibrary.save();
- setResult(RESULT_OK);
- finish();
- return true;
- } else {
- return false;
- }
+ // TODO Auto-generated method stub
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ mRecognizer.save();
+ this.setResult(RESULT_OK);
+ finish();
+ return true;
+ }
+ else
+ return false;
}
-
+
@Override
protected void onPause() {
+ // TODO Auto-generated method stub
super.onPause();
- mGesureLibrary.save();
+ mRecognizer.save();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
+ // TODO Auto-generated method stub
super.onSaveInstanceState(outState);
- mGesureLibrary.save();
+ mRecognizer.save();
}
}