Removes gestures from ListView.

This commit is contained in:
Romain Guy
2009-06-08 22:36:10 -07:00
parent be19df0a4d
commit f642aa2a44
20 changed files with 0 additions and 1757 deletions

View File

@@ -1,279 +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 android.gesture;
import android.content.Context;
import android.content.res.Resources;
import android.util.Log;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import static android.gesture.GestureConstants.LOG_TAG;
public class LetterRecognizer {
static final String GESTURE_FILE_NAME = "letters.gestures";
private final static int ADJUST_RANGE = 3;
private SigmoidUnit[] mHiddenLayer;
private SigmoidUnit[] mOutputLayer;
private final String[] mClasses;
private final int mPatchSize;
private GestureLibrary mGestureStore;
private final Comparator<Prediction> mComparator = new PredictionComparator();
private static class SigmoidUnit {
final float[] mWeights;
SigmoidUnit(float[] weights) {
mWeights = weights;
}
private float compute(float[] inputs) {
float sum = 0;
final int count = inputs.length;
final float[] weights = mWeights;
for (int i = 0; i < count; i++) {
sum += inputs[i] * weights[i];
}
sum += weights[weights.length - 1];
return 1.0f / (float) (1 + Math.exp(-sum));
}
}
private LetterRecognizer(int numOfInput, int numOfHidden, String[] classes) {
mPatchSize = (int) Math.sqrt(numOfInput);
mHiddenLayer = new SigmoidUnit[numOfHidden];
mClasses = classes;
mOutputLayer = new SigmoidUnit[classes.length];
}
public ArrayList<Prediction> recognize(Gesture gesture) {
return recognize(gesture, null);
}
public ArrayList<Prediction> recognize(Gesture gesture, ArrayList<Prediction> predictions) {
float[] query = GestureUtilities.spatialSampling(gesture, mPatchSize);
predictions = classify(query, predictions);
adjustPrediction(gesture, predictions);
return predictions;
}
private ArrayList<Prediction> classify(float[] vector, ArrayList<Prediction> predictions) {
if (predictions == null) {
predictions = new ArrayList<Prediction>();
} else {
predictions.clear();
}
final float[] intermediateOutput = compute(mHiddenLayer, vector);
final float[] output = compute(mOutputLayer, intermediateOutput);
double sum = 0;
final String[] classes = mClasses;
final int count = classes.length;
for (int i = 0; i < count; i++) {
double score = output[i];
sum += score;
predictions.add(new Prediction(classes[i], score));
}
for (int i = 0; i < count; i++) {
predictions.get(i).score /= sum;
}
Collections.sort(predictions, mComparator);
return predictions;
}
private float[] compute(SigmoidUnit[] layer, float[] input) {
final float[] output = new float[layer.length];
final int count = layer.length;
for (int i = 0; i < count; i++) {
output[i] = layer[i].compute(input);
}
return output;
}
static LetterRecognizer createFromResource(Context context, int resourceID) {
final Resources resources = context.getResources();
final InputStream stream = resources.openRawResource(resourceID);
return createFromStream(stream);
}
static LetterRecognizer createFromStream(InputStream stream) {
DataInputStream in = null;
LetterRecognizer classifier = null;
try {
in = new DataInputStream(new BufferedInputStream(stream,
GestureConstants.IO_BUFFER_SIZE));
final int version = in.readShort();
switch (version) {
case 1:
classifier = readV1(in);
break;
default:
Log.d(LOG_TAG, "Couldn't load handwriting data: version " + version +
" not supported");
break;
}
} catch (IOException e) {
Log.d(LOG_TAG, "Failed to load handwriting data:", e);
} finally {
GestureUtilities.closeStream(in);
}
return classifier;
}
private static LetterRecognizer readV1(DataInputStream in) throws IOException {
final int iCount = in.readInt();
final int hCount = in.readInt();
final int oCount = in.readInt();
final String[] classes = new String[oCount];
for (int i = 0; i < classes.length; i++) {
classes[i] = in.readUTF();
}
final LetterRecognizer classifier = new LetterRecognizer(iCount, hCount, classes);
final SigmoidUnit[] hiddenLayer = new SigmoidUnit[hCount];
final SigmoidUnit[] outputLayer = new SigmoidUnit[oCount];
for (int i = 0; i < hCount; i++) {
final float[] weights = new float[iCount + 1];
for (int j = 0; j <= iCount; j++) {
weights[j] = in.readFloat();
}
hiddenLayer[i] = new SigmoidUnit(weights);
}
for (int i = 0; i < oCount; i++) {
final float[] weights = new float[hCount + 1];
for (int j = 0; j <= hCount; j++) {
weights[j] = in.readFloat();
}
outputLayer[i] = new SigmoidUnit(weights);
}
classifier.mHiddenLayer = hiddenLayer;
classifier.mOutputLayer = outputLayer;
return classifier;
}
/**
* TODO: Publish this API once we figure out where we should save the personalized
* gestures, and how to do so across all apps
*
* @hide
*/
public boolean save() {
if (mGestureStore != null) {
return mGestureStore.save();
}
return false;
}
/**
* TODO: Publish this API once we figure out where we should save the personalized
* gestures, and how to do so across all apps
*
* @hide
*/
public void setPersonalizationEnabled(boolean enabled) {
if (enabled) {
mGestureStore = GestureLibraries.fromFile(GESTURE_FILE_NAME);
mGestureStore.setSequenceType(GestureStore.SEQUENCE_INVARIANT);
mGestureStore.load();
} else {
mGestureStore = null;
}
}
/**
* TODO: Publish this API once we figure out where we should save the personalized
* gestures, and how to do so across all apps
*
* @hide
*/
public void addExample(String letter, Gesture example) {
if (mGestureStore != null) {
mGestureStore.addGesture(letter, example);
}
}
private void adjustPrediction(Gesture query, ArrayList<Prediction> predictions) {
if (mGestureStore != null) {
final ArrayList<Prediction> results = mGestureStore.recognize(query);
final HashMap<String, Prediction> topNList = new HashMap<String, Prediction>();
for (int j = 0; j < ADJUST_RANGE; j++) {
Prediction prediction = predictions.remove(0);
topNList.put(prediction.name, prediction);
}
final int count = results.size();
for (int j = count - 1; j >= 0 && !topNList.isEmpty(); j--) {
final Prediction item = results.get(j);
final Prediction original = topNList.get(item.name);
if (original != null) {
predictions.add(0, original);
topNList.remove(item.name);
}
}
}
}
private static class PredictionComparator implements Comparator<Prediction> {
public int compare(Prediction object1, Prediction object2) {
double score1 = object1.score;
double score2 = object2.score;
if (score1 > score2) {
return -1;
} else if (score1 < score2) {
return 1;
} else {
return 0;
}
}
}
}

View File

@@ -1,65 +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 android.gesture;
import android.content.Context;
import android.util.Log;
import static android.gesture.GestureConstants.LOG_TAG;
import static android.gesture.LetterRecognizer.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
public final class LetterRecognizers {
public final static int RECOGNIZER_LATIN_LOWERCASE = 0;
private LetterRecognizers() {
}
public static LetterRecognizer fromType(Context context, int type) {
switch (type) {
case RECOGNIZER_LATIN_LOWERCASE: {
return createFromResource(context, com.android.internal.R.raw.latin_lowercase);
}
}
return null;
}
public static LetterRecognizer fromResource(Context context, int resourceId) {
return createFromResource(context, resourceId);
}
public static LetterRecognizer fromFile(String path) {
return fromFile(new File(path));
}
public static LetterRecognizer fromFile(File file) {
try {
return createFromStream(new FileInputStream(file));
} catch (FileNotFoundException e) {
Log.d(LOG_TAG, "Failed to load handwriting data from file " + file, e);
}
return null;
}
public static LetterRecognizer fromStream(InputStream stream) {
return createFromStream(stream);
}
}

View File

@@ -41,18 +41,12 @@ import android.view.ViewConfiguration;
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.KeyCharacterMap;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputConnectionWrapper;
import android.view.inputmethod.InputMethodManager;
import android.view.ContextMenu.ContextMenuInfo;
import android.gesture.GestureOverlayView;
import android.gesture.Gesture;
import android.gesture.LetterRecognizer;
import android.gesture.Prediction;
import android.gesture.LetterRecognizers;
import com.android.internal.R;
@@ -73,7 +67,6 @@ import java.util.List;
* @attr ref android.R.styleable#AbsListView_cacheColorHint
* @attr ref android.R.styleable#AbsListView_fastScrollEnabled
* @attr ref android.R.styleable#AbsListView_smoothScrollbar
* @attr ref android.R.styleable#AbsListView_gestures
*/
public abstract class AbsListView extends AdapterView<ListAdapter> implements TextWatcher,
ViewTreeObserver.OnGlobalLayoutListener, Filter.FilterListener,
@@ -101,31 +94,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
*/
public static final int TRANSCRIPT_MODE_ALWAYS_SCROLL = 2;
/**
* Disables gestures.
*
* @see #setGestures(int)
* @see #GESTURES_JUMP
* @see #GESTURES_FILTER
*/
public static final int GESTURES_NONE = 0;
/**
* When a letter gesture is recognized the list jumps to a matching position.
*
* @see #setGestures(int)
* @see #GESTURES_NONE
* @see #GESTURES_FILTER
*/
public static final int GESTURES_JUMP = 1;
/**
* When a letter gesture is recognized the letter is added to the filter.
*
* @see #setGestures(int)
* @see #GESTURES_NONE
* @see #GESTURES_JUMP
*/
public static final int GESTURES_FILTER = 2;
/**
* Indicates that we are not in the middle of a touch gesture
*/
@@ -461,18 +429,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
*/
private FastScroller mFastScroller;
/**
* Indicates the type of gestures to use: GESTURES_NONE, GESTURES_FILTER or GESTURES_NONE
*/
private int mGestures;
// Used to implement the gestures overlay
private GestureOverlayView mGesturesOverlay;
private PopupWindow mGesturesPopup;
private ViewTreeObserver.OnGlobalLayoutListener mGesturesLayoutListener;
private boolean mGlobalLayoutListenerAddedGestures;
private boolean mInstallGesturesOverlay;
private boolean mGlobalLayoutListenerAddedFilter;
private int mTouchSlop;
@@ -583,9 +539,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
boolean smoothScrollbar = a.getBoolean(R.styleable.AbsListView_smoothScrollbar, true);
setSmoothScrollbarEnabled(smoothScrollbar);
int gestures = a.getInt(R.styleable.AbsListView_gestures, GESTURES_NONE);
setGestures(gestures);
a.recycle();
}
@@ -600,160 +553,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mDensityScale = getContext().getResources().getDisplayMetrics().density;
}
/**
* <p>Sets the type of gestures to use with this list. When gestures are enabled,
* that is if the <code>gestures</code> parameter is not {@link #GESTURES_NONE},
* the user can draw characters on top of this view. When a character is
* recognized and matches a known character, the list will either:</p>
* <ul>
* <li>Jump to the appropriate position ({@link #GESTURES_JUMP})</li>
* <li>Add the character to the current filter ({@link #GESTURES_FILTER})</li>
* </ul>
* <p>Using {@link #GESTURES_JUMP} requires {@link #isFastScrollEnabled()} to
* be true. Using {@link #GESTURES_FILTER} requires {@link #isTextFilterEnabled()}
* to be true.</p>
*
* @param gestures The type of gestures to enable for this list:
* {@link #GESTURES_NONE}, {@link #GESTURES_JUMP} or {@link #GESTURES_FILTER}
*
* @see #GESTURES_NONE
* @see #GESTURES_JUMP
* @see #GESTURES_FILTER
* @see #getGestures()
*/
public void setGestures(int gestures) {
switch (gestures) {
case GESTURES_JUMP:
if (!mFastScrollEnabled) {
throw new IllegalStateException("Jump gestures can only be used with "
+ "fast scroll enabled");
}
break;
case GESTURES_FILTER:
if (!mTextFilterEnabled) {
throw new IllegalStateException("Filter gestures can only be used with "
+ "text filtering enabled");
}
break;
}
final int oldGestures = mGestures;
mGestures = gestures;
// Install overlay later
if (oldGestures == GESTURES_NONE && gestures != GESTURES_NONE) {
mInstallGesturesOverlay = true;
// Uninstall overlay
} else if (oldGestures != GESTURES_NONE && gestures == GESTURES_NONE) {
uninstallGesturesOverlay();
}
}
/**
* Indicates what gestures are enabled on this view.
*
* @return {@link #GESTURES_NONE}, {@link #GESTURES_JUMP} or {@link #GESTURES_FILTER}
*
* @see #GESTURES_NONE
* @see #GESTURES_JUMP
* @see #GESTURES_FILTER
* @see #setGestures(int)
*/
@ViewDebug.ExportedProperty(mapping = {
@ViewDebug.IntToString(from = GESTURES_NONE, to = "NONE"),
@ViewDebug.IntToString(from = GESTURES_JUMP, to = "JUMP"),
@ViewDebug.IntToString(from = GESTURES_FILTER, to = "FILTER")
})
public int getGestures() {
return mGestures;
}
private void dismissGesturesPopup() {
if (mGesturesPopup != null) {
mGesturesPopup.dismiss();
}
}
private void showGesturesPopup() {
// Make sure we have a window before showing the popup
if (getWindowVisibility() == View.VISIBLE) {
installGesturesOverlay();
positionGesturesPopup();
}
}
private void positionGesturesPopup() {
final int[] xy = new int[2];
getLocationOnScreen(xy);
if (!mGesturesPopup.isShowing()) {
mGesturesPopup.showAtLocation(this, Gravity.LEFT | Gravity.TOP, xy[0], xy[1]);
} else {
mGesturesPopup.update(xy[0], xy[1], -1, -1);
}
}
private void installGesturesOverlay() {
mInstallGesturesOverlay = false;
if (mGesturesPopup == null) {
final Context c = getContext();
final LayoutInflater layoutInflater = (LayoutInflater)
c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mGesturesOverlay = (GestureOverlayView)
layoutInflater.inflate(R.layout.list_gestures_overlay, null);
final PopupWindow p = new PopupWindow(c);
p.setFocusable(false);
p.setTouchable(false);
p.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
p.setContentView(mGesturesOverlay);
p.setWidth(getWidth());
p.setHeight(getHeight());
p.setBackgroundDrawable(null);
if (mGesturesLayoutListener == null) {
mGesturesLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
if (isShown()) {
showGesturesPopup();
} else if (mGesturesPopup.isShowing()) {
dismissGesturesPopup();
}
}
};
}
getViewTreeObserver().addOnGlobalLayoutListener(mGesturesLayoutListener);
mGlobalLayoutListenerAddedGestures = true;
mGesturesPopup = p;
mGesturesOverlay.removeAllOnGestureListeners();
mGesturesOverlay.setGestureStrokeType(GestureOverlayView.GESTURE_STROKE_TYPE_MULTIPLE);
mGesturesOverlay.addOnGesturePerformedListener(new GesturesProcessor());
}
}
private void uninstallGesturesOverlay() {
dismissGesturesPopup();
mGesturesPopup = null;
if (mGesturesLayoutListener != null) {
getViewTreeObserver().removeGlobalOnLayoutListener(mGesturesLayoutListener);
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (mGestures != GESTURES_NONE) {
if ((ev.getAction() != MotionEvent.ACTION_DOWN || mFastScroller == null ||
!mFastScroller.isPointInside(ev.getX(), ev.getY())) &&
mGesturesPopup.isShowing()) {
mGesturesOverlay.dispatchTouchEvent(ev);
}
}
return super.dispatchTouchEvent(ev);
}
/**
* Enables fast scrolling by letting the user quickly scroll through lists by
* dragging the fast scroll thumb. The adapter attached to the list may want
@@ -1037,7 +836,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
* about having leaked the window.
*/
dismissPopup();
dismissGesturesPopup();
Parcelable superState = super.onSaveInstanceState();
@@ -1325,11 +1123,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
if (mFiltered && visible && mPopup != null && mPopup.isShowing()) {
positionPopup();
}
if (mGestures != GESTURES_NONE && visible && mGesturesPopup != null &&
mGesturesPopup.isShowing()) {
positionGesturesPopup();
}
}
return changed;
@@ -1544,13 +1337,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
if (mFastScroller != null) {
mFastScroller.onSizeChanged(w, h, oldw, oldh);
}
if (mInstallGesturesOverlay) {
installGesturesOverlay();
positionGesturesPopup();
} else if (mGesturesPopup != null && mGesturesPopup.isShowing()) {
mGesturesPopup.update(w, h);
}
}
/**
@@ -1737,10 +1523,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
if (mTextFilterEnabled && mPopup != null && !mGlobalLayoutListenerAddedFilter) {
treeObserver.addOnGlobalLayoutListener(this);
}
if (mGestures != GESTURES_NONE && mGesturesPopup != null &&
!mGlobalLayoutListenerAddedGestures) {
treeObserver.addOnGlobalLayoutListener(mGesturesLayoutListener);
}
}
}
@@ -1755,10 +1537,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
treeObserver.removeGlobalOnLayoutListener(this);
mGlobalLayoutListenerAddedFilter = false;
}
if (mGesturesLayoutListener != null && mGesturesPopup != null) {
mGlobalLayoutListenerAddedGestures = false;
treeObserver.removeGlobalOnLayoutListener(mGesturesLayoutListener);
}
}
}
@@ -1773,7 +1551,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
removeCallbacks(mFlingRunnable);
// Always hide the type filter
dismissPopup();
dismissGesturesPopup();
if (touchMode == TOUCH_MODE_OFF) {
// Remember the last selected element
@@ -1784,9 +1561,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
// Show the type filter only if a filter is in effect
showPopup();
}
if (mGestures != GESTURES_NONE) {
showGesturesPopup();
}
// If we changed touch mode since the last time we had focus
if (touchMode != mLastTouchMode && mLastTouchMode != TOUCH_MODE_UNKNOWN) {
@@ -1907,8 +1681,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
final int longPressPosition, final long longPressId) {
boolean handled = false;
dismissGesturesPopup();
if (mOnItemLongClickListener != null) {
handled = mOnItemLongClickListener.onItemLongClick(AbsListView.this, child,
longPressPosition, longPressId);
@@ -3829,79 +3601,4 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
}
}
private class GesturesProcessor implements GestureOverlayView.OnGesturePerformedListener {
private static final double SCORE_THRESHOLD = 0.1;
private LetterRecognizer mRecognizer;
private ArrayList<Prediction> mPredictions;
private final KeyCharacterMap mKeyMap;
private final char[] mHolder;
GesturesProcessor() {
mRecognizer = LetterRecognizers.fromType(getContext(),
LetterRecognizers.RECOGNIZER_LATIN_LOWERCASE);
if (mRecognizer == null) {
setGestures(GESTURES_NONE);
}
if (mGestures == GESTURES_FILTER) {
mKeyMap = KeyCharacterMap.load(KeyCharacterMap.BUILT_IN_KEYBOARD);
mHolder = new char[1];
} else {
mKeyMap = null;
mHolder = null;
}
}
public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
mPredictions = mRecognizer.recognize(gesture, mPredictions);
if (!mPredictions.isEmpty()) {
final Prediction prediction = mPredictions.get(0);
if (prediction.score > SCORE_THRESHOLD) {
switch (mGestures) {
case GESTURES_JUMP:
processJump(prediction);
break;
case GESTURES_FILTER:
processFilter(prediction);
break;
}
}
}
}
private void processJump(Prediction prediction) {
final Object[] sections = mFastScroller.getSections();
if (sections != null) {
final String name = prediction.name;
final int count = sections.length;
int index = -1;
for (int i = 0; i < count; i++) {
if (name.equalsIgnoreCase((String) sections[i])) {
index = i;
break;
}
}
if (index != -1) {
final SectionIndexer indexer = mFastScroller.getSectionIndexer();
final int position = indexer.getPositionForSection(index);
setSelection(position);
}
}
}
private void processFilter(Prediction prediction) {
mHolder[0] = prediction.name.charAt(0);
final KeyEvent[] events = mKeyMap.getEvents(mHolder);
if (events != null) {
for (KeyEvent event : events) {
sendToTextFilter(event.getKeyCode(), event.getRepeatCount(),
event);
}
}
}
}
}

Binary file not shown.

View File

@@ -1381,16 +1381,6 @@
will use only the number of items in the adapter and the number of items visible
on screen to determine the scrollbar's properties. -->
<attr name="smoothScrollbar" format="boolean" />
<!-- Defines the type of gesture to enable for the widget. -->
<attr name="gestures">
<!-- No gesture -->
<enum name="none" value="0" />
<!-- Gestures jump to a specific position in the content. This requires
fast scroll to be enabled. -->
<enum name="jump" value="1" />
<!-- Gestures filter the content. This requires text filtering to be enabled. -->
<enum name="filter" value="2" />
</attr>
</declare-styleable>
<declare-styleable name="AbsSpinner">
<!-- Reference to an array resource that will populate the Spinner. For static content,

View File

@@ -1106,7 +1106,6 @@
<public type="attr" name="uncertainGestureColor" />
<public type="attr" name="fadeOffset" />
<public type="attr" name="fadeDuration" />
<public type="attr" name="gestures" />
<public type="attr" name="gestureStrokeType" />
<public type="attr" name="gestureStrokeLengthThreshold" />
<public type="attr" name="gestureStrokeSquarenessThreshold" />

View File

@@ -1,8 +0,0 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := Sketch
include $(BUILD_PACKAGE)

View File

@@ -1,45 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.gesture.example">
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity
android:name="com.android.gesture.example.GestureEntry"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -1,35 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Spinner
android:id="@+id/spinner"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:drawSelectorOnTop="true"
android:prompt="@string/recognition_result"/>
<android.gesture.GestureOverlayView
android:id="@+id/drawingpad"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>

View File

@@ -1,59 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Spinner
android:id="@+id/spinner"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:drawSelectorOnTop="true"
android:prompt="@string/recognition_result"/>
<android.gesture.GestureOverlayView
android:id="@+id/drawingpad"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/previous"
android:text="@string/previous"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<Button
android:id="@+id/remove"
android:text="@string/remove"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<Button
android:id="@+id/next"
android:text="@string/next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"/>
</LinearLayout>
</LinearLayout>

View File

@@ -1,34 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<EditText
android:id="@+id/gesturename_edit"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:scrollHorizontally="true"
android:autoText="false"
android:capitalize="none"
android:gravity="fill_horizontal"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>

View File

@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<android.gesture.GestureOverlayView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/overlay"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView
android:id="@+id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</android.gesture.GestureOverlayView>

View File

@@ -1,29 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<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>
<string name="viewgesture">View</string>
<string name="newgesture_dialog_ok">OK</string>
<string name="newgesture_dialog_cancel">Cancel</string>
<string name="newgesture_text_entry">Gesture Name</string>
<string name="previous">Previous</string>
<string name="remove">Remove</string>
<string name="next">Next</string>
</resources>

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}

View File

@@ -1,108 +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.provider.Contacts.People;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.ListView;
import android.gesture.Gesture;
import android.gesture.GestureOverlayView;
import android.gesture.LetterRecognizer;
import android.gesture.Prediction;
import android.gesture.LetterRecognizers;
import java.util.ArrayList;
public class ContactListGestureOverlay extends Activity {
private static final String LOG_TAG = "ContactListGestureOverlay";
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 ContactAdapter mContactAdapter;
private ListView mContactList;
private LetterRecognizer mRecognizer;
private GestureOverlayView mOverlay;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.overlaydemo);
// create a letter recognizer
mRecognizer = LetterRecognizers.fromType(this,
LetterRecognizers.RECOGNIZER_LATIN_LOWERCASE);
mOverlay = (GestureOverlayView) findViewById(R.id.overlay);
// load the contact list
mContactList = (ListView) findViewById(R.id.list);
registerForContextMenu(mContactList);
mContactList.setTextFilterEnabled(true);
mContactList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
if (!mOverlay.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);
mOverlay.setGestureStrokeType(GestureOverlayView.GESTURE_STROKE_TYPE_MULTIPLE);
mOverlay.addOnGesturePerformedListener(new GestureOverlayView.OnGesturePerformedListener() {
public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
ArrayList<Prediction> predictions = mRecognizer.recognize(gesture);
if (!predictions.isEmpty()) {
Log.v(LOG_TAG, "1st Prediction : " + predictions.get(0).name +
" @" + predictions.get(0).score);
Log.v(LOG_TAG, "2nd Prediction : " + predictions.get(1).name +
" @" + predictions.get(1).score);
Log.v(LOG_TAG, "3rd Prediction : " + predictions.get(2).name +
" @" + predictions.get(2).score);
int index = mContactAdapter.search(predictions.get(0).name);
if (index != -1) {
mContactList.setSelection(index);
}
}
}
});
}
}

View File

@@ -1,211 +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.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.AdapterView.OnItemSelectedListener;
import android.gesture.Gesture;
import android.gesture.GestureOverlayView;
import android.gesture.Prediction;
import android.gesture.GestureLibraries;
import android.gesture.GestureLibrary;
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 +
"demo_library.gestures";
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 GestureOverlayView mGesturePad;
private Spinner mRecognitionResult;
private GestureLibrary mGestureStore;
private boolean mChangedByRecognizer = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.demo);
// init the gesture library
mGestureStore = GestureLibraries.fromFile(GESTURE_FILE_NAME);
mGestureStore.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) {
mGestureStore.addGesture(parent.getSelectedItem().toString(), mGesturePad
.getGesture());
} else {
mChangedByRecognizer = false;
}
}
public void onNothingSelected(AdapterView<?> parent) {
}
});
// create the area for drawing a gesture
mGesturePad = (GestureOverlayView) findViewById(R.id.drawingpad);
mGesturePad.setBackgroundColor(Color.BLACK);
mGesturePad.addOnGestureListener(new GestureOverlayView.OnGestureListener() {
public void onGestureEnded(GestureOverlayView overlay, MotionEvent event) {
recognize(overlay.getGesture());
}
public void onGesture(GestureOverlayView overlay, MotionEvent event) {
}
public void onGestureStarted(GestureOverlayView overlay, MotionEvent event) {
overlay.clear(false);
}
public void onGestureCancelled(GestureOverlayView overlay, MotionEvent event) {
}
});
if (savedInstanceState != null) {
Gesture gesture = (Gesture) savedInstanceState.getParcelable(PARCEL_KEY);
if (gesture != null) {
mGesturePad.setGesture(gesture);
}
}
}
@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) {
mGestureStore.addGesture(text, mGesturePad.getGesture());
}
}
}).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.getGesture() != 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) {
mGestureStore.load();
mGesturePad.clear(false);
}
@Override
protected void onPause() {
super.onPause();
mGestureStore.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.getGesture();
if (gesture != null) {
outState.putParcelable(PARCEL_KEY, gesture);
}
mGestureStore.save();
}
private void recognize(Gesture gesture) {
mChangedByRecognizer = true;
ArrayList<Prediction> predictions = mGestureStore.recognize(gesture);
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);
}
}

View File

@@ -1,184 +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.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.AdapterView.OnItemSelectedListener;
import android.gesture.Gesture;
import android.gesture.GestureOverlayView;
import android.gesture.GestureLibraries;
import android.gesture.GestureLibrary;
import java.util.ArrayList;
import java.util.Collections;
/**
* GestureLibViewer gives an example on how to browse existing gestures and
* removing unwanted gestures.
*/
public class GestureLibViewer extends Activity {
private GestureOverlayView mGesturePad;
private Spinner mGestureCategory;
private GestureLibrary mGesureStore;
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);
mGesureStore.removeGesture(name, gesture);
mGestures = mGesureStore.getGestures(name);
if (mGestures == null) {
// delete the entire entry
mCurrentGestureIndex = 0;
ArrayList<String> list = new ArrayList<String>();
list.addAll(mGesureStore.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.setGesture(gesture);
mGesturePad.invalidate();
}
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gestureviewer);
// create the area for drawing a gesture
mGesturePad = (GestureOverlayView) findViewById(R.id.drawingpad);
mGesturePad.setEnabled(false);
// init the gesture library
mGesureStore = GestureLibraries.fromFile(GestureEntry.GESTURE_FILE_NAME);
mGesureStore.load();
mGestureCategory = (Spinner) findViewById(R.id.spinner);
ArrayList<String> list = new ArrayList<String>();
if (!mGesureStore.getGestureEntries().isEmpty()) {
list.addAll(mGesureStore.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 = mGesureStore.getGestures(list.get(0));
mCurrentGestureIndex = 0;
Gesture gesture = mGestures.get(mCurrentGestureIndex);
mGesturePad.setGesture(gesture);
}
mGestureCategory.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
mGestures = mGesureStore.getGestures((String) mGestureCategory.getSelectedItem());
if (!mGestures.isEmpty()) {
mCurrentGestureIndex = 0;
Gesture gesture = mGestures.get(mCurrentGestureIndex);
mGesturePad.setGesture(gesture);
}
mGesturePad.invalidate();
}
public void onNothingSelected(AdapterView<?> parent) {
}
});
Button remove = (Button) findViewById(R.id.remove);
remove.setOnClickListener(new RemoveGestureListener());
Button next = (Button) findViewById(R.id.next);
next.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (mCurrentGestureIndex >= mGestures.size() - 1) {
return;
}
mCurrentGestureIndex++;
Gesture gesture = mGestures.get(mCurrentGestureIndex);
mGesturePad.setGesture(gesture);
mGesturePad.invalidate();
}
});
Button previous = (Button) findViewById(R.id.previous);
previous.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (mCurrentGestureIndex >= 1 && !mGestures.isEmpty()) {
mCurrentGestureIndex--;
Gesture gesture = mGestures.get(mCurrentGestureIndex);
mGesturePad.setGesture(gesture);
mGesturePad.invalidate();
}
}
});
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
mGesureStore.save();
setResult(RESULT_OK);
finish();
return true;
} else {
return false;
}
}
@Override
protected void onPause() {
super.onPause();
mGesureStore.save();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mGesureStore.save();
}
}

View File

@@ -1,225 +0,0 @@
import java.io.File;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Closeable;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.BufferedInputStream;
/**
* Converts text-based letter stores to binary-based stores.
*/
public class Converter {
private final File mFile;
private static final short VERSION_NUMBER = 1;
Converter(File file) {
mFile = file;
}
private void convert() {
boolean read = false;
String[] classes = null;
int iCount = 0;
int hCount = 0;
int oCount = 0;
float[][] iWeights = null;
float[][] oWeights = null;
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(mFile));
long start = System.nanoTime();
String line = reader.readLine();
int startIndex = 0;
int endIndex;
endIndex = line.indexOf(" ", startIndex);
iCount = Integer.parseInt(line.substring(startIndex, endIndex));
startIndex = endIndex + 1;
endIndex = line.indexOf(" ", startIndex);
hCount = Integer.parseInt(line.substring(startIndex, endIndex));
startIndex = endIndex + 1;
endIndex = line.length();
oCount = Integer.parseInt(line.substring(startIndex, endIndex));
classes = new String[oCount];
line = reader.readLine();
startIndex = 0;
for (int i = 0; i < oCount; i++) {
endIndex = line.indexOf(" ", startIndex);
classes[i] = line.substring(startIndex, endIndex);
startIndex = endIndex + 1;
}
iWeights = new float[hCount][];
for (int i = 0; i < hCount; i++) {
iWeights[i] = new float[iCount + 1];
line = reader.readLine();
startIndex = 0;
for (int j = 0; j <= iCount; j++) {
endIndex = line.indexOf(" ", startIndex);
iWeights[i][j] = Float.parseFloat(line.substring(startIndex, endIndex));
startIndex = endIndex + 1;
}
}
oWeights = new float[oCount][];
for (int i = 0; i < oCount; i++) {
oWeights[i] = new float[hCount + 1];
line = reader.readLine();
startIndex = 0;
for (int j = 0; j <= hCount; j++) {
endIndex = line.indexOf(" ", startIndex);
oWeights[i][j] = Float.parseFloat(line.substring(startIndex, endIndex));
startIndex = endIndex + 1;
}
}
long end = System.nanoTime();
System.out.println("time to read text file = " +
((end - start) / 1000.0f / 1000.0f) + " ms");
read = true;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
close(reader);
}
if (read) {
boolean wrote = false;
DataOutputStream out = null;
try {
out = new DataOutputStream(new FileOutputStream(mFile));
out.writeShort(VERSION_NUMBER);
out.writeInt(iCount);
out.writeInt(hCount);
out.writeInt(oCount);
for (String aClass : classes) {
out.writeUTF(aClass);
}
for (float[] weights : iWeights) {
for (float weight : weights) {
out.writeFloat(weight);
}
}
for (float[] weights : oWeights) {
for (float weight : weights) {
out.writeFloat(weight);
}
}
out.flush();
wrote = true;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
close(out);
}
if (wrote) {
DataInputStream in = null;
try {
in = new DataInputStream(new BufferedInputStream(new FileInputStream(mFile)));
long start = System.nanoTime();
in.readShort();
iCount = in.readInt();
hCount = in.readInt();
oCount = in.readInt();
classes = new String[oCount];
for (int i = 0; i < classes.length; i++) {
classes[i] = in.readUTF();
}
iWeights = new float[hCount][];
for (int i = 0; i < iWeights.length; i++) {
iWeights[i] = new float[iCount];
for (int j = 0; j < iCount; j++) {
iWeights[i][j] = in.readFloat();
}
}
oWeights = new float[oCount][];
for (int i = 0; i < oWeights.length; i++) {
oWeights[i] = new float[hCount];
for (int j = 0; j < hCount; j++) {
oWeights[i][j] = in.readFloat();
}
}
long end = System.nanoTime();
System.out.println("time to read binary file = " +
((end - start) / 1000.0f / 1000.0f) + " ms");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
close(in);
}
}
}
}
private static void close(Closeable reader) {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
String fileName = args[0];
if (fileName != null) {
File file = new File(fileName);
if (!file.exists()) {
printHelp(fileName);
} else {
new Converter(file).convert();
}
} else {
printHelp(null);
}
}
private static void printHelp(String name) {
if (name == null) {
System.out.println("You must specify the name of the file to convert:");
} else {
System.out.println("The specified file does not exist: " + name);
}
System.out.println("java Converter [filename]");
System.out.println("");
System.out.println("\t[filename]\tPath to the file to convert. The file is replaced by "
+ "the conversion result.");
}
}