diff options
author | Sara Ting <sarating@google.com> | 2012-08-14 12:47:17 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-08-14 12:47:18 -0700 |
commit | 4ddc6b9ff31660bf3d1377c6f527609fd8f1947e (patch) | |
tree | db32d652bf12b2b5d5ca6294473f122c99cfb6f7 /src | |
parent | 487d52c2789114e0ee3e7ce85694611b8d59dd70 (diff) | |
parent | 601ef6e0e7b921141cfeaf849238e444a10b9687 (diff) | |
download | android_packages_apps_Calendar-4ddc6b9ff31660bf3d1377c6f527609fd8f1947e.tar.gz android_packages_apps_Calendar-4ddc6b9ff31660bf3d1377c6f527609fd8f1947e.tar.bz2 android_packages_apps_Calendar-4ddc6b9ff31660bf3d1377c6f527609fd8f1947e.zip |
Merge "Add autocompletion for title in edit-event." into ics-ub-calendar-burgundy
Diffstat (limited to 'src')
-rw-r--r-- | src/com/android/calendar/event/EditEventView.java | 134 |
1 files changed, 132 insertions, 2 deletions
diff --git a/src/com/android/calendar/event/EditEventView.java b/src/com/android/calendar/event/EditEventView.java index 57d56b14..1fbc8d5e 100644 --- a/src/com/android/calendar/event/EditEventView.java +++ b/src/com/android/calendar/event/EditEventView.java @@ -24,12 +24,14 @@ import android.app.ProgressDialog; import android.app.Service; import android.app.TimePickerDialog; import android.app.TimePickerDialog.OnTimeSetListener; +import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Resources; import android.database.Cursor; +import android.database.MatrixCursor; import android.graphics.drawable.Drawable; import android.provider.CalendarContract.Attendees; import android.provider.CalendarContract.Calendars; @@ -43,14 +45,17 @@ import android.text.format.DateUtils; import android.text.format.Time; import android.text.util.Rfc822Tokenizer; import android.util.Log; +import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; +import android.view.inputmethod.EditorInfo; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ArrayAdapter; +import android.widget.AutoCompleteTextView; import android.widget.Button; import android.widget.CalendarView; import android.widget.CheckBox; @@ -64,6 +69,7 @@ import android.widget.ResourceCursorAdapter; import android.widget.ScrollView; import android.widget.Spinner; import android.widget.TextView; +import android.widget.TextView.OnEditorActionListener; import android.widget.TimePicker; import com.android.calendar.CalendarEventModel; @@ -93,6 +99,7 @@ import java.util.Formatter; import java.util.HashMap; import java.util.Locale; import java.util.TimeZone; +import java.util.TreeMap; public class EditEventView implements View.OnClickListener, DialogInterface.OnCancelListener, DialogInterface.OnClickListener, OnItemSelectedListener { @@ -100,6 +107,16 @@ public class EditEventView implements View.OnClickListener, DialogInterface.OnCa private static final String GOOGLE_SECONDARY_CALENDAR = "calendar.google.com"; private static final String PERIOD_SPACE = ". "; + // Constants used for title autocompletion. + private static final String[] EVENT_PROJECTION = new String[] { + Events._ID, + Events.TITLE, + }; + private static final int EVENT_INDEX_ID = 0; + private static final int EVENT_INDEX_TITLE = 1; + private static final String TITLE_WHERE = Events.TITLE + " LIKE ?"; + private static final int MAX_TITLE_SUGGESTIONS = 4; + ArrayList<View> mEditOnlyList = new ArrayList<View>(); ArrayList<View> mEditViewList = new ArrayList<View>(); ArrayList<View> mViewOnlyList = new ArrayList<View>(); @@ -121,7 +138,7 @@ public class EditEventView implements View.OnClickListener, DialogInterface.OnCa Spinner mAvailabilitySpinner; Spinner mAccessLevelSpinner; RadioGroup mResponseRadioGroup; - TextView mTitleTextView; + AutoCompleteTextView mTitleTextView; TextView mLocationTextView; TextView mDescriptionTextView; TextView mWhenView; @@ -627,6 +644,106 @@ public class EditEventView implements View.OnClickListener, DialogInterface.OnCa } /** + * Adapter for title auto completion. + */ + private static class TitleAdapter extends ResourceCursorAdapter { + private final ContentResolver mContentResolver; + + public TitleAdapter(Context context) { + super(context, android.R.layout.simple_dropdown_item_1line, null, 0); + mContentResolver = context.getContentResolver(); + } + + @Override + public int getCount() { + return Math.min(MAX_TITLE_SUGGESTIONS, super.getCount()); + } + + private static String getTitleAtCursor(Cursor cursor) { + return cursor.getString(EVENT_INDEX_TITLE); + } + + @Override + public final String convertToString(Cursor cursor) { + return getTitleAtCursor(cursor); + } + + @Override + public void bindView(View view, Context context, Cursor cursor) { + TextView textView = (TextView) view; + textView.setText(getTitleAtCursor(cursor)); + } + + @Override + public Cursor runQueryOnBackgroundThread(CharSequence constraint) { + String filter = constraint == null ? "" : constraint.toString() + "%"; + if (filter.isEmpty()) { + return null; + } + long startTime = System.currentTimeMillis(); + + // Query all titles prefixed with the constraint. There is no way to insert + // 'DISTINCT' or 'GROUP BY' to get rid of dupes, so use post-processing to + // remove dupes. We will order query results by descending event ID to show + // results that were most recently inputted. + Cursor tempCursor = mContentResolver.query(Events.CONTENT_URI, EVENT_PROJECTION, + TITLE_WHERE, new String[] { filter }, Events._ID + " DESC"); + if (tempCursor != null) { + try { + // Post process query results. + Cursor c = uniqueTitlesCursor(tempCursor); + + // Log the processing duration. + long duration = System.currentTimeMillis() - startTime; + StringBuilder msg = new StringBuilder(); + msg.append("Autocomplete of "); + msg.append(constraint); + msg.append(": title query match took "); + msg.append(duration); + msg.append("ms."); + Log.d(TAG, msg.toString()); + return c; + } finally { + tempCursor.close(); + } + } else { + return null; + } + } + + /** + * Post-process the query results to return the first MAX_TITLE_SUGGESTIONS + * unique titles in alphabetical order. + */ + private Cursor uniqueTitlesCursor(Cursor cursor) { + TreeMap<String, String[]> titleToQueryResults = + new TreeMap<String, String[]>(String.CASE_INSENSITIVE_ORDER); + int numColumns = cursor.getColumnCount(); + cursor.moveToPosition(-1); + + // Remove dupes. + while ((titleToQueryResults.size() < MAX_TITLE_SUGGESTIONS) && cursor.moveToNext()) { + String title = getTitleAtCursor(cursor).trim(); + String data[] = new String[numColumns]; + if (!titleToQueryResults.containsKey(title)) { + for (int i = 0; i < numColumns; i++) { + data[i] = cursor.getString(i); + } + titleToQueryResults.put(title, data); + } + } + + // Copy the sorted results to a new cursor. + MatrixCursor newCursor = new MatrixCursor(EVENT_PROJECTION); + for (String[] result : titleToQueryResults.values()) { + newCursor.addRow(result); + } + newCursor.moveToFirst(); + return newCursor; + } + } + + /** * Does prep steps for saving a calendar event. * * This triggers a parse of the attendees list and checks if the event is @@ -829,7 +946,7 @@ public class EditEventView implements View.OnClickListener, DialogInterface.OnCa // cache all the widgets mCalendarsSpinner = (Spinner) view.findViewById(R.id.calendars_spinner); - mTitleTextView = (TextView) view.findViewById(R.id.title); + mTitleTextView = (AutoCompleteTextView) view.findViewById(R.id.title); mLocationTextView = (TextView) view.findViewById(R.id.location); mDescriptionTextView = (TextView) view.findViewById(R.id.description); mTimezoneLabel = (TextView) view.findViewById(R.id.timezone_label); @@ -863,6 +980,19 @@ public class EditEventView implements View.OnClickListener, DialogInterface.OnCa mAttendeesList = (MultiAutoCompleteTextView) view.findViewById(R.id.attendees); mTitleTextView.setTag(mTitleTextView.getBackground()); + mTitleTextView.setAdapter(new TitleAdapter(activity)); + mTitleTextView.setOnEditorActionListener(new OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_DONE) { + // Dismiss the suggestions dropdown. Return false so the other + // side effects still occur (soft keyboard going away, etc.). + mTitleTextView.dismissDropDown(); + } + return false; + } + }); + mLocationTextView.setTag(mLocationTextView.getBackground()); mDescriptionTextView.setTag(mDescriptionTextView.getBackground()); mRepeatsSpinner.setTag(mRepeatsSpinner.getBackground()); |