Home | History | Annotate | Download | only in settings
      1 /**
      2  * Copyright (C) 2009 Google Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
      5  * use this file except in compliance with the License. You may obtain a copy
      6  * of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
     12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
     13  * License for the specific language governing permissions and limitations
     14  * under the License.
     15  */
     16 
     17 package com.android.settings;
     18 
     19 import android.app.AlertDialog;
     20 import android.app.Dialog;
     21 import android.app.ListActivity;
     22 import android.content.Context;
     23 import android.content.DialogInterface;
     24 import android.database.Cursor;
     25 import android.os.Bundle;
     26 import android.provider.UserDictionary;
     27 import android.text.InputType;
     28 import android.view.ContextMenu;
     29 import android.view.Menu;
     30 import android.view.MenuItem;
     31 import android.view.View;
     32 import android.view.WindowManager;
     33 import android.view.ContextMenu.ContextMenuInfo;
     34 import android.widget.AlphabetIndexer;
     35 import android.widget.EditText;
     36 import android.widget.ListAdapter;
     37 import android.widget.ListView;
     38 import android.widget.SectionIndexer;
     39 import android.widget.SimpleCursorAdapter;
     40 import android.widget.TextView;
     41 import android.widget.AdapterView.AdapterContextMenuInfo;
     42 
     43 import java.util.Locale;
     44 
     45 public class UserDictionarySettings extends ListActivity {
     46 
     47     private static final String INSTANCE_KEY_DIALOG_EDITING_WORD = "DIALOG_EDITING_WORD";
     48     private static final String INSTANCE_KEY_ADDED_WORD = "DIALOG_ADDED_WORD";
     49 
     50     private static final String[] QUERY_PROJECTION = {
     51         UserDictionary.Words._ID, UserDictionary.Words.WORD
     52     };
     53 
     54     // Either the locale is empty (means the word is applicable to all locales)
     55     // or the word equals our current locale
     56     private static final String QUERY_SELECTION = UserDictionary.Words.LOCALE + "=? OR "
     57             + UserDictionary.Words.LOCALE + " is null";
     58 
     59     private static final String DELETE_SELECTION = UserDictionary.Words.WORD + "=?";
     60 
     61     private static final String EXTRA_WORD = "word";
     62 
     63     private static final int CONTEXT_MENU_EDIT = Menu.FIRST;
     64     private static final int CONTEXT_MENU_DELETE = Menu.FIRST + 1;
     65 
     66     private static final int OPTIONS_MENU_ADD = Menu.FIRST;
     67 
     68     private static final int DIALOG_ADD_OR_EDIT = 0;
     69 
     70     /** The word being edited in the dialog (null means the user is adding a word). */
     71     private String mDialogEditingWord;
     72 
     73     private Cursor mCursor;
     74 
     75     private boolean mAddedWordAlready;
     76     private boolean mAutoReturn;
     77 
     78     @Override
     79     protected void onCreate(Bundle savedInstanceState) {
     80         super.onCreate(savedInstanceState);
     81 
     82         setContentView(R.layout.list_content_with_empty_view);
     83 
     84         mCursor = createCursor();
     85         setListAdapter(createAdapter());
     86 
     87         TextView emptyView = (TextView) findViewById(R.id.empty);
     88         emptyView.setText(R.string.user_dict_settings_empty_text);
     89 
     90         ListView listView = getListView();
     91         listView.setFastScrollEnabled(true);
     92         listView.setEmptyView(emptyView);
     93 
     94         registerForContextMenu(listView);
     95     }
     96 
     97     @Override
     98     protected void onResume() {
     99         super.onResume();
    100         if (!mAddedWordAlready
    101                 && getIntent().getAction().equals("com.android.settings.USER_DICTIONARY_INSERT")) {
    102             String word = getIntent().getStringExtra(EXTRA_WORD);
    103             mAutoReturn = true;
    104             if (word != null) {
    105                 showAddOrEditDialog(word);
    106             }
    107         }
    108     }
    109     @Override
    110     protected void onRestoreInstanceState(Bundle state) {
    111         super.onRestoreInstanceState(state);
    112         mDialogEditingWord = state.getString(INSTANCE_KEY_DIALOG_EDITING_WORD);
    113         mAddedWordAlready = state.getBoolean(INSTANCE_KEY_ADDED_WORD, false);
    114     }
    115 
    116     @Override
    117     protected void onSaveInstanceState(Bundle outState) {
    118         super.onSaveInstanceState(outState);
    119         outState.putString(INSTANCE_KEY_DIALOG_EDITING_WORD, mDialogEditingWord);
    120         outState.putBoolean(INSTANCE_KEY_ADDED_WORD, mAddedWordAlready);
    121     }
    122 
    123     private Cursor createCursor() {
    124         String currentLocale = Locale.getDefault().toString();
    125         // Case-insensitive sort
    126         return managedQuery(UserDictionary.Words.CONTENT_URI, QUERY_PROJECTION,
    127                 QUERY_SELECTION, new String[] { currentLocale },
    128                 "UPPER(" + UserDictionary.Words.WORD + ")");
    129     }
    130 
    131     private ListAdapter createAdapter() {
    132         return new MyAdapter(this,
    133                 android.R.layout.simple_list_item_1, mCursor,
    134                 new String[] { UserDictionary.Words.WORD },
    135                 new int[] { android.R.id.text1 });
    136     }
    137 
    138     @Override
    139     protected void onListItemClick(ListView l, View v, int position, long id) {
    140         openContextMenu(v);
    141     }
    142 
    143     @Override
    144     public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
    145         if (!(menuInfo instanceof AdapterContextMenuInfo)) return;
    146 
    147         AdapterContextMenuInfo adapterMenuInfo = (AdapterContextMenuInfo) menuInfo;
    148         menu.setHeaderTitle(getWord(adapterMenuInfo.position));
    149         menu.add(0, CONTEXT_MENU_EDIT, 0,
    150                 R.string.user_dict_settings_context_menu_edit_title);
    151         menu.add(0, CONTEXT_MENU_DELETE, 0,
    152                 R.string.user_dict_settings_context_menu_delete_title);
    153     }
    154 
    155     @Override
    156     public boolean onContextItemSelected(MenuItem item) {
    157         ContextMenuInfo menuInfo = item.getMenuInfo();
    158         if (!(menuInfo instanceof AdapterContextMenuInfo)) return false;
    159 
    160         AdapterContextMenuInfo adapterMenuInfo = (AdapterContextMenuInfo) menuInfo;
    161         String word = getWord(adapterMenuInfo.position);
    162         if (word == null) return true;
    163 
    164         switch (item.getItemId()) {
    165             case CONTEXT_MENU_DELETE:
    166                 deleteWord(word);
    167                 return true;
    168 
    169             case CONTEXT_MENU_EDIT:
    170                 showAddOrEditDialog(word);
    171                 return true;
    172         }
    173 
    174         return false;
    175     }
    176 
    177     @Override
    178     public boolean onCreateOptionsMenu(Menu menu) {
    179         menu.add(0, OPTIONS_MENU_ADD, 0, R.string.user_dict_settings_add_menu_title)
    180                 .setIcon(R.drawable.ic_menu_add);
    181         return true;
    182     }
    183 
    184     @Override
    185     public boolean onOptionsItemSelected(MenuItem item) {
    186         showAddOrEditDialog(null);
    187         return true;
    188     }
    189 
    190     private void showAddOrEditDialog(String editingWord) {
    191         mDialogEditingWord = editingWord;
    192         showDialog(DIALOG_ADD_OR_EDIT);
    193     }
    194 
    195     private String getWord(int position) {
    196         mCursor.moveToPosition(position);
    197         // Handle a possible race-condition
    198         if (mCursor.isAfterLast()) return null;
    199 
    200         return mCursor.getString(
    201                 mCursor.getColumnIndexOrThrow(UserDictionary.Words.WORD));
    202     }
    203 
    204     @Override
    205     protected Dialog onCreateDialog(int id) {
    206         View content = getLayoutInflater().inflate(R.layout.dialog_edittext, null);
    207         final EditText editText = (EditText) content.findViewById(R.id.edittext);
    208         // No prediction in soft keyboard mode. TODO: Create a better way to disable prediction
    209         editText.setInputType(InputType.TYPE_CLASS_TEXT
    210                 | InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE);
    211 
    212         AlertDialog dialog =  new AlertDialog.Builder(this)
    213                 .setTitle(mDialogEditingWord != null
    214                         ? R.string.user_dict_settings_edit_dialog_title
    215                         : R.string.user_dict_settings_add_dialog_title)
    216                 .setView(content)
    217                 .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
    218                     public void onClick(DialogInterface dialog, int which) {
    219                         onAddOrEditFinished(editText.getText().toString());
    220                         if (mAutoReturn) finish();
    221                     }})
    222                 .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
    223                     public void onClick(DialogInterface dialog, int which) {
    224                         if (mAutoReturn) finish();
    225                     }})
    226                 .create();
    227         dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE |
    228                 WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
    229         return dialog;
    230     }
    231 
    232     @Override
    233     protected void onPrepareDialog(int id, Dialog d) {
    234         AlertDialog dialog = (AlertDialog) d;
    235         d.setTitle(mDialogEditingWord != null
    236                         ? R.string.user_dict_settings_edit_dialog_title
    237                         : R.string.user_dict_settings_add_dialog_title);
    238         EditText editText = (EditText) dialog.findViewById(R.id.edittext);
    239         editText.setText(mDialogEditingWord);
    240     }
    241 
    242     private void onAddOrEditFinished(String word) {
    243         if (mDialogEditingWord != null) {
    244             // The user was editing a word, so do a delete/add
    245             deleteWord(mDialogEditingWord);
    246         }
    247 
    248         // Disallow duplicates
    249         deleteWord(word);
    250 
    251         // TODO: present UI for picking whether to add word to all locales, or current.
    252         UserDictionary.Words.addWord(this, word.toString(),
    253                 250, UserDictionary.Words.LOCALE_TYPE_ALL);
    254         mCursor.requery();
    255         mAddedWordAlready = true;
    256     }
    257 
    258     private void deleteWord(String word) {
    259         getContentResolver().delete(UserDictionary.Words.CONTENT_URI, DELETE_SELECTION,
    260                 new String[] { word });
    261     }
    262 
    263     private static class MyAdapter extends SimpleCursorAdapter implements SectionIndexer {
    264         private AlphabetIndexer mIndexer;
    265 
    266         public MyAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
    267             super(context, layout, c, from, to);
    268 
    269             int wordColIndex = c.getColumnIndexOrThrow(UserDictionary.Words.WORD);
    270             String alphabet = context.getString(com.android.internal.R.string.fast_scroll_alphabet);
    271             mIndexer = new AlphabetIndexer(c, wordColIndex, alphabet);
    272         }
    273 
    274         public int getPositionForSection(int section) {
    275             return mIndexer.getPositionForSection(section);
    276         }
    277 
    278         public int getSectionForPosition(int position) {
    279             return mIndexer.getSectionForPosition(position);
    280         }
    281 
    282         public Object[] getSections() {
    283             return mIndexer.getSections();
    284         }
    285     }
    286 }
    287