Home | History | Annotate | Download | only in openwnn
      1 /*
      2  * Copyright (C) 2008-2012  OMRON SOFTWARE Co., Ltd.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy 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,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package jp.co.omronsoft.openwnn;
     18 
     19 import android.app.Activity;
     20 import android.app.AlertDialog;
     21 import android.app.Dialog;
     22 import android.content.DialogInterface;
     23 import android.content.Intent;
     24 import android.content.res.Configuration;
     25 import android.graphics.Color;
     26 import android.graphics.Paint.FontMetricsInt;
     27 import android.os.Bundle;
     28 import android.text.TextPaint;
     29 import android.text.TextUtils;
     30 import android.util.Log;
     31 import android.view.Display;
     32 import android.view.Gravity;
     33 import android.view.Menu;
     34 import android.view.MenuItem;
     35 import android.view.MotionEvent;
     36 import android.view.KeyEvent;
     37 import android.view.View;
     38 import android.view.ViewGroup;
     39 import android.view.Window;
     40 import android.view.WindowManager;
     41 import android.view.View.OnFocusChangeListener;
     42 import android.view.View.OnTouchListener;
     43 import android.widget.TableLayout;
     44 import android.widget.TableRow;
     45 import android.widget.TextView;
     46 import android.widget.Toast;
     47 import android.widget.Button;
     48 
     49 import java.util.ArrayList;
     50 import java.util.Arrays;
     51 import java.util.Comparator;
     52 
     53 
     54 /**
     55  * The abstract class for user dictionary tool.
     56  *
     57  * @author Copyright (C) 2009, OMRON SOFTWARE CO., LTD.  All Rights Reserved.
     58  */
     59 public abstract class UserDictionaryToolsList extends Activity
     60     implements View.OnClickListener, OnTouchListener, OnFocusChangeListener {
     61 
     62     /** The class name of the user dictionary tool */
     63     protected String  mListViewName;
     64     /** The class name of the user dictionary editor */
     65     protected String  mEditViewName;
     66     /** The package name of the user dictionary editor */
     67     protected String  mPackageName;
     68 
     69     /** ID of the menu item (add) */
     70     private final int MENU_ITEM_ADD = 0;
     71     /** ID of the menu item (edit) */
     72     private final int MENU_ITEM_EDIT = 1;
     73     /** ID of the menu item (delete) */
     74     private final int MENU_ITEM_DELETE = 2;
     75     /** ID of the menu item (initialize) */
     76     private final int MENU_ITEM_INIT = 3;
     77 
     78     /** ID of the dialog control (confirm deletion) */
     79     private final int DIALOG_CONTROL_DELETE_CONFIRM = 0;
     80     /** ID of the dialog control (confirm initialize) */
     81     private final int DIALOG_CONTROL_INIT_CONFIRM = 1;
     82 
     83     /** The size of font*/
     84     private final int WORD_TEXT_SIZE = 16;
     85 
     86     /** The color of background (unfocused item) */
     87     private final int UNFOCUS_BACKGROUND_COLOR = 0xFF242424;
     88     /** The color of background (focused item) */
     89     private final int FOCUS_BACKGROUND_COLOR = 0xFFFF8500;
     90 
     91     /** The minimum count of registered words */
     92     private final int MIN_WORD_COUNT = 0;
     93     /** The maximum count of registered words */
     94     private final int MAX_WORD_COUNT = 100;
     95     /** Maximum word count to display */
     96     private final int MAX_LIST_WORD_COUNT = 100;
     97 
     98     /** The threshold time of the double tapping */
     99     private final int DOUBLE_TAP_TIME = 300;
    100 
    101     /** Widgets which constitute this screen of activity */
    102     private Menu mMenu;
    103     /** Table layout for the lists */
    104     private TableLayout mTableLayout;
    105     /** Focusing view */
    106     private static View sFocusingView = null;
    107     /** Focusing pair view */
    108     private static View sFocusingPairView = null;
    109 
    110     /** Objects which control state transitions */
    111     private Intent mIntent;
    112 
    113     /** The number of the registered words */
    114     private int mWordCount = 0;
    115 
    116     /** The state of "Add" menu item */
    117     private boolean mAddMenuEnabled;
    118     /** The state of "Edit" menu item */
    119     private boolean mEditMenuEnabled;
    120     /** The state of "Delete" menu item */
    121     private boolean mDeleteMenuEnabled;
    122     /** The state of "Initialize" menu item */
    123     private boolean mInitMenuEnabled;
    124 
    125     /** {@code true} if the menu option is initialized */
    126     private boolean mInitializedMenu = false;
    127     /** {@code true} if one of word is selected */
    128     private boolean mSelectedWords;
    129     /** The viewID which is selected */
    130     private int mSelectedViewID = -1;
    131     /** The viewID which was selected previously */
    132     private static int sBeforeSelectedViewID = -1;
    133     /** The time of previous action */
    134     private static long sJustBeforeActionTime = -1;
    135 
    136     /** List of the words in the user dictionary */
    137     private ArrayList<WnnWord> mWordList = null;
    138 
    139     /** Work area for sorting the word list */
    140     private WnnWord[] mSortData;
    141 
    142     /** Whether the view is initialized */
    143     private boolean mInit = false;
    144 
    145     /** Page left button */
    146     private Button mLeftButton = null;
    147 
    148     /** Page right button */
    149     private Button mRightButton = null;
    150 
    151     /** for isXLarge */
    152     private static boolean mIsXLarge = false;
    153 
    154     /**
    155      * Send the specified event to IME
    156      *
    157      * @param ev    The event object
    158      * @return      {@code true} if this event is processed
    159      */
    160     protected abstract boolean sendEventToIME(OpenWnnEvent ev);
    161     /** Get the comparator for sorting the list */
    162     protected abstract Comparator<WnnWord> getComparator();
    163 
    164     /** Show Dialog Num */
    165     private int mDialogShow = -1;
    166 
    167     /** @see android.app.Activity#onCreate */
    168     @Override protected void onCreate(Bundle savedInstanceState) {
    169 
    170 
    171         super.onCreate(savedInstanceState);
    172 
    173         /* create XML layout */
    174         setContentView(R.layout.user_dictionary_tools_list);
    175         mTableLayout = (TableLayout)findViewById(R.id.user_dictionary_tools_table);
    176 
    177         Button b = (Button)findViewById(R.id.user_dictionary_left_button);
    178         b.setOnClickListener(new View.OnClickListener() {
    179                 public void onClick(View v) {
    180                     int pos = mWordCount - MAX_LIST_WORD_COUNT;
    181                     if (0 <= pos) {
    182                         mWordCount = pos;
    183                         updateWordList();
    184                         mTableLayout.findViewById(1).requestFocus();
    185                     }
    186                 }
    187             });
    188         mLeftButton = b;
    189 
    190         b = (Button)findViewById(R.id.user_dictionary_right_button);
    191         b.setOnClickListener(new View.OnClickListener() {
    192                 public void onClick(View v) {
    193                     int pos = mWordCount + MAX_LIST_WORD_COUNT;
    194                     if (pos < mWordList.size()) {
    195                         mWordCount = pos;
    196                         updateWordList();
    197                         mTableLayout.findViewById(1).requestFocus();
    198                     }
    199                 }
    200             });
    201         mRightButton = b;
    202 
    203     }
    204 
    205     /** @see android.app.Activity#onStart */
    206     @Override protected void onStart() {
    207         super.onStart();
    208         mDialogShow = -1;
    209         sBeforeSelectedViewID = -1;
    210         sJustBeforeActionTime = -1;
    211         mWordList = getWords();
    212 
    213         final TextView leftText = (TextView) findViewById(R.id.user_dictionary_tools_list_title_words_count);
    214         leftText.setText(mWordList.size() + "/" + MAX_WORD_COUNT);
    215 
    216         mIsXLarge = ((getResources().getConfiguration().screenLayout &
    217                       Configuration.SCREENLAYOUT_SIZE_MASK)
    218                       == Configuration.SCREENLAYOUT_SIZE_XLARGE);
    219         updateWordList();
    220     }
    221 
    222     /**
    223      * Called when the system is about to start resuming a previous activity.
    224      *
    225      * @see android.app.Activity#onPause
    226      */
    227     @Override protected void onPause() {
    228 
    229         if (mDialogShow == DIALOG_CONTROL_DELETE_CONFIRM) {
    230             dismissDialog(DIALOG_CONTROL_DELETE_CONFIRM);
    231             mDialogShow = -1;
    232         } else if (mDialogShow == DIALOG_CONTROL_INIT_CONFIRM){
    233             dismissDialog(DIALOG_CONTROL_INIT_CONFIRM);
    234             mDialogShow = -1;
    235         }
    236 
    237         super.onPause();
    238     }
    239 
    240     /**
    241      * Set parameters of table
    242      *
    243      * @param  w        The width of the table
    244      * @param  h        The height of the table
    245      * @return          The information of the layout
    246      */
    247     private TableLayout.LayoutParams tableCreateParam(int w, int h) {
    248         return new TableLayout.LayoutParams(w, h);
    249     }
    250 
    251     /** @see android.app.Activity#onCreateOptionsMenu */
    252     @Override public boolean onCreateOptionsMenu(Menu menu) {
    253 
    254 
    255         /* initialize the menu */
    256         menu.clear();
    257         /* set the menu item enable/disable */
    258         setOptionsMenuEnabled();
    259         /* [menu] add a word */
    260         menu.add(0, MENU_ITEM_ADD, 0, R.string.user_dictionary_add)
    261             .setIcon(android.R.drawable.ic_menu_add)
    262             .setEnabled(mAddMenuEnabled);
    263         /* [menu] edit a word */
    264         menu.add(0, MENU_ITEM_EDIT, 0, R.string.user_dictionary_edit)
    265             .setIcon(android.R.drawable.ic_menu_edit)
    266             .setEnabled(mEditMenuEnabled);
    267         /* [menu] delete a word */
    268         menu.add(0, MENU_ITEM_DELETE, 0, R.string.user_dictionary_delete)
    269             .setIcon(android.R.drawable.ic_menu_delete)
    270             .setEnabled(mDeleteMenuEnabled);
    271         /* [menu] clear the dictionary */
    272         menu.add(1, MENU_ITEM_INIT, 0, R.string.user_dictionary_init)
    273             .setIcon(android.R.drawable.ic_menu_delete)
    274             .setEnabled(mInitMenuEnabled);
    275 
    276         mMenu = menu;
    277         mInitializedMenu = true;
    278 
    279 
    280         return super.onCreateOptionsMenu(menu);
    281     }
    282 
    283     /**
    284      * Change state of the option menus according to a current state of the list widget
    285      */
    286     private void setOptionsMenuEnabled() {
    287 
    288 
    289         /* [menu] add a word */
    290         if (mWordList.size() >= MAX_WORD_COUNT) {
    291             /* disable if the number of registered word exceeds MAX_WORD_COUNT */
    292             mAddMenuEnabled = false;
    293         } else {
    294             mAddMenuEnabled = true;
    295         }
    296 
    297         /* [menu] edit a word/delete a word */
    298         if (mWordList.size() <= MIN_WORD_COUNT) {
    299             /* disable if no word is registered or no word is selected */
    300             mEditMenuEnabled = false;
    301             mDeleteMenuEnabled = false;
    302         } else {
    303             mEditMenuEnabled = true;
    304             if (mSelectedWords) {
    305                 mDeleteMenuEnabled = true;
    306             } else {
    307                 mDeleteMenuEnabled = false;
    308             }
    309         }
    310 
    311         /* [menu] clear the dictionary (always enabled) */
    312         mInitMenuEnabled = true;
    313 
    314     }
    315 
    316     /** @see android.app.Activity#onOptionsItemSelected */
    317     @Override public boolean onOptionsItemSelected(MenuItem item) {
    318 
    319         boolean ret;
    320         switch (item.getItemId()) {
    321         case MENU_ITEM_ADD:
    322             /* add a word */
    323             wordAdd();
    324             ret = true;
    325             break;
    326 
    327         case MENU_ITEM_EDIT:
    328             /* edit the word (show dialog) */
    329             wordEdit(sFocusingView, sFocusingPairView);
    330             ret = true;
    331             break;
    332 
    333         case MENU_ITEM_DELETE:
    334             /* delete the word (show dialog) */
    335             showDialog(DIALOG_CONTROL_DELETE_CONFIRM);
    336             mDialogShow = DIALOG_CONTROL_DELETE_CONFIRM;
    337             ret = true;
    338             break;
    339 
    340         case MENU_ITEM_INIT:
    341             /* clear the dictionary (show dialog) */
    342             showDialog(DIALOG_CONTROL_INIT_CONFIRM);
    343             mDialogShow = DIALOG_CONTROL_INIT_CONFIRM;
    344             ret = true;
    345             break;
    346 
    347         default:
    348             ret = false;
    349         }
    350 
    351         return ret;
    352     }
    353 
    354     /** @see android.app.Activity#onKeyUp */
    355     @Override public boolean onKeyUp(int keyCode, KeyEvent event) {
    356         /* open the menu if KEYCODE_DPAD_CENTER is pressed */
    357         if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
    358             openOptionsMenu();
    359             return true;
    360         }
    361          return super.onKeyUp(keyCode, event);
    362     }
    363 
    364     /** @see android.app.Activity#onCreateDialog */
    365     @Override protected Dialog onCreateDialog(int id) {
    366         switch (id) {
    367         case DIALOG_CONTROL_DELETE_CONFIRM:
    368             return new AlertDialog.Builder(UserDictionaryToolsList.this)
    369                 .setMessage(R.string.user_dictionary_delete_confirm)
    370                 .setNegativeButton(android.R.string.cancel, null)
    371                 .setPositiveButton(android.R.string.ok, mDialogDeleteWords)
    372                 .setCancelable(true)
    373                 .create();
    374 
    375         case DIALOG_CONTROL_INIT_CONFIRM:
    376             return new AlertDialog.Builder(UserDictionaryToolsList.this)
    377                 .setMessage(R.string.dialog_clear_user_dictionary_message)
    378                 .setNegativeButton(android.R.string.cancel, null)
    379                 .setPositiveButton(android.R.string.ok, mDialogInitWords)
    380                 .setCancelable(true)
    381                 .create();
    382 
    383         default:
    384             Log.e("OpenWnn", "onCreateDialog : Invaled Get DialogID. ID=" + id);
    385             break;
    386         }
    387 
    388 
    389         return super.onCreateDialog(id);
    390     }
    391 
    392     /**
    393      * Process the event when the button on the "Delete word" dialog is pushed
    394      *
    395      * @param  dialog    The information of the dialog
    396      * @param  button    The button that is pushed
    397      */
    398     private DialogInterface.OnClickListener mDialogDeleteWords =
    399         new DialogInterface.OnClickListener() {
    400             public void onClick(DialogInterface dialog, int button) {
    401 
    402                 mDialogShow = -1;
    403                 CharSequence focusString = ((TextView)sFocusingView).getText();
    404                 CharSequence focusPairString = ((TextView)sFocusingPairView).getText();
    405                 WnnWord wnnWordSearch = new WnnWord();
    406 
    407                 if (mSelectedViewID > MAX_WORD_COUNT) {
    408                     wnnWordSearch.stroke = focusPairString.toString();
    409                     wnnWordSearch.candidate = focusString.toString();
    410                 } else {
    411                     wnnWordSearch.stroke = focusString.toString();
    412                     wnnWordSearch.candidate = focusPairString.toString();
    413                 }
    414                 boolean deleted = deleteWord(wnnWordSearch);
    415                 if (deleted) {
    416                     Toast.makeText(getApplicationContext(),
    417                                    R.string.user_dictionary_delete_complete,
    418                                    Toast.LENGTH_LONG).show();
    419                 } else {
    420                     Toast.makeText(getApplicationContext(),
    421                                    R.string.user_dictionary_delete_fail,
    422                                    Toast.LENGTH_LONG).show();
    423                     return;
    424                 }
    425 
    426                 mWordList = getWords();
    427                 int size = mWordList.size();
    428                 if (size <= mWordCount) {
    429                     int newPos = (mWordCount - MAX_LIST_WORD_COUNT);
    430                     mWordCount = (0 <= newPos) ? newPos : 0;
    431                 }
    432                 updateWordList();
    433 
    434                 TextView leftText = (TextView) findViewById(R.id.user_dictionary_tools_list_title_words_count);
    435                 leftText.setText(size + "/" + MAX_WORD_COUNT);
    436 
    437                 if (mInitializedMenu) {
    438                     onCreateOptionsMenu(mMenu);
    439                 }
    440             }
    441         };
    442 
    443     /**
    444      * Process the event when the button on the "Initialize" dialog is pushed
    445      *
    446      * @param  dialog    The information of the dialog
    447      * @param  button    The button that is pushed
    448      */
    449     private DialogInterface.OnClickListener mDialogInitWords =
    450         new DialogInterface.OnClickListener() {
    451             public void onClick(DialogInterface dialog, int button) {
    452 
    453                 mDialogShow = -1;
    454                 /* clear the user dictionary */
    455                 OpenWnnEvent ev = new OpenWnnEvent(OpenWnnEvent.INITIALIZE_USER_DICTIONARY, new WnnWord());
    456 
    457                 sendEventToIME(ev);
    458                 /* show the message */
    459                 Toast.makeText(getApplicationContext(), R.string.dialog_clear_user_dictionary_done,
    460                                Toast.LENGTH_LONG).show();
    461                 mWordList = new ArrayList<WnnWord>();
    462                 mWordCount = 0;
    463                 updateWordList();
    464                 TextView leftText = (TextView) findViewById(R.id.user_dictionary_tools_list_title_words_count);
    465                 leftText.setText(mWordList.size() + "/" + MAX_WORD_COUNT);
    466 
    467                 if (mInitializedMenu) {
    468                     onCreateOptionsMenu(mMenu);
    469                 }
    470             }
    471         };
    472 
    473 
    474     /** @see android.view.View.OnClickListener#onClick */
    475     public void onClick(View arg0) {
    476     }
    477 
    478     /** @see android.view.View.OnTouchListener#onTouch */
    479     public boolean onTouch(View v, MotionEvent e) {
    480 
    481 
    482         mSelectedViewID = ((TextView)v).getId();
    483         switch (e.getAction()) {
    484         case MotionEvent.ACTION_DOWN:
    485             /* double tap handling */
    486             if (sBeforeSelectedViewID != ((TextView)v).getId()) {
    487                 /* save the view id if the id is not same as previously selected one */
    488                 sBeforeSelectedViewID = ((TextView)v).getId();
    489             } else {
    490                 if ((e.getDownTime() - sJustBeforeActionTime) < DOUBLE_TAP_TIME) {
    491                     /* edit the word if double tapped */
    492                     sFocusingView = v;
    493                     sFocusingPairView = ((UserDictionaryToolsListFocus)v).getPairView();
    494                     wordEdit(sFocusingView, sFocusingPairView);
    495                 }
    496             }
    497             /* save the action time */
    498             sJustBeforeActionTime = e.getDownTime();
    499             break;
    500         }
    501 
    502         return false;
    503     }
    504 
    505     /** @see android.view.View.OnFocusChangeListener#onFocusChange */
    506     public void onFocusChange(View v, boolean hasFocus) {
    507 
    508         mSelectedViewID = ((TextView)v).getId();
    509         sFocusingView = v;
    510         sFocusingPairView = ((UserDictionaryToolsListFocus)v).getPairView();
    511         if (hasFocus) {
    512             ((TextView)v).setTextColor(Color.BLACK);
    513             v.setBackgroundColor(FOCUS_BACKGROUND_COLOR);
    514             ((TextView)sFocusingPairView).setTextColor(Color.BLACK);
    515             sFocusingPairView.setBackgroundColor(FOCUS_BACKGROUND_COLOR);
    516             mSelectedWords = true;
    517         } else {
    518             mSelectedWords = false;
    519             ((TextView)v).setTextColor(Color.LTGRAY);
    520             v.setBackgroundColor(UNFOCUS_BACKGROUND_COLOR);
    521             ((TextView)sFocusingPairView).setTextColor(Color.LTGRAY);
    522             sFocusingPairView.setBackgroundColor(UNFOCUS_BACKGROUND_COLOR);
    523         }
    524         if (mInitializedMenu) {
    525             onCreateOptionsMenu(mMenu);
    526         }
    527     }
    528 
    529     /**
    530      * Add the word
    531      */
    532     public void wordAdd() {
    533         /** change to the edit window */
    534         screenTransition(Intent.ACTION_INSERT, mEditViewName);
    535     }
    536 
    537     /**
    538      * Edit the specified word
    539      *
    540      * @param  focusView       The information of view
    541      * @param  focusPairView   The information of pair of view
    542      */
    543     public void wordEdit(View focusView, View focusPairView) {
    544         if (mSelectedViewID > MAX_WORD_COUNT) {
    545             createUserDictionaryToolsEdit(focusPairView, focusView);
    546         } else {
    547             createUserDictionaryToolsEdit(focusView, focusPairView);
    548         }
    549         screenTransition(Intent.ACTION_EDIT, mEditViewName);
    550     }
    551 
    552     /**
    553      * The internal process of editing the specified word
    554      *
    555      * @param  focusView        The information of view
    556      * @param  focusPairView    The information of pair of view
    557      */
    558     protected abstract UserDictionaryToolsEdit createUserDictionaryToolsEdit(View focusView, View focusPairView);
    559 
    560     /**
    561      * Delete the specified word
    562      *
    563      * @param  searchword   The information of searching
    564      * @return          {@code true} if success; {@code false} if fail.
    565      */
    566     public boolean deleteWord(WnnWord searchword) {
    567         OpenWnnEvent event = new OpenWnnEvent(OpenWnnEvent.LIST_WORDS_IN_USER_DICTIONARY,
    568                                               WnnEngine.DICTIONARY_TYPE_USER,
    569                                               searchword);
    570 
    571         boolean deleted = false;
    572         sendEventToIME(event);
    573         for( int i=0; i < MAX_WORD_COUNT; i++) {
    574             WnnWord getword = new WnnWord();
    575             event = new OpenWnnEvent(OpenWnnEvent.GET_WORD,
    576                                      getword);
    577             sendEventToIME(event);
    578             getword = event.word;
    579             int len = getword.candidate.length();
    580             if (len == 0) {
    581                 break;
    582             }
    583             if (searchword.candidate.equals(getword.candidate)) {
    584                 WnnWord delword = new WnnWord();
    585                 delword.stroke = searchword.stroke;
    586                 delword.candidate = searchword.candidate;
    587                 delword.id = i;
    588                 event = new OpenWnnEvent(OpenWnnEvent.DELETE_WORD,
    589                                          delword);
    590                 deleted = sendEventToIME(event);
    591                 break;
    592             }
    593         }
    594 
    595         if (mInitializedMenu) {
    596             onCreateOptionsMenu(mMenu);
    597         }
    598 
    599         return deleted;
    600     }
    601 
    602 
    603     /**
    604      * Processing the transition of screen
    605      *
    606      * @param  action       The string of action
    607      * @param  classname    The class name
    608      */
    609     private void screenTransition(String action, String classname) {
    610 
    611         if (action.equals("")) {
    612             mIntent = new Intent();
    613         } else {
    614             mIntent = new Intent(action);
    615         }
    616         mIntent.setClassName(mPackageName, classname);
    617         startActivity(mIntent);
    618         finish();
    619     }
    620 
    621     /**
    622      * Get the list of words in the user dictionary.
    623      * @return The list of words
    624      */
    625     private ArrayList<WnnWord> getWords() {
    626         WnnWord word = new WnnWord();
    627         OpenWnnEvent event = new OpenWnnEvent(OpenWnnEvent.LIST_WORDS_IN_USER_DICTIONARY,
    628                                               WnnEngine.DICTIONARY_TYPE_USER,
    629                                               word);
    630         sendEventToIME(event);
    631 
    632         ArrayList<WnnWord> list = new ArrayList<WnnWord>();
    633         for (int i = 0; i < MAX_WORD_COUNT; i++) {
    634             event = new OpenWnnEvent(OpenWnnEvent.GET_WORD, word);
    635             if (!sendEventToIME(event)) {
    636                 break;
    637             }
    638             list.add(event.word);
    639         }
    640 
    641         compareTo(list);
    642 
    643         return list;
    644     }
    645 
    646     /**
    647      * Sort the list of words
    648      * @param array The array list of the words
    649      */
    650     protected void compareTo(ArrayList<WnnWord> array) {
    651         mSortData = new WnnWord[array.size()];
    652         array.toArray(mSortData);
    653         Arrays.sort(mSortData, getComparator());
    654     }
    655 
    656 
    657     /**
    658      * Update the word list.
    659      */
    660     private void updateWordList() {
    661         if (!mInit) {
    662             mInit = true;
    663             mSelectedViewID = 1;
    664 
    665             Window window = getWindow();
    666             WindowManager windowManager = window.getWindowManager();
    667             Display display = windowManager.getDefaultDisplay();
    668             int system_width = display.getWidth();
    669 
    670             UserDictionaryToolsListFocus dummy = new UserDictionaryToolsListFocus(this);
    671             dummy.setTextSize(WORD_TEXT_SIZE);
    672             TextPaint paint = dummy.getPaint();
    673             FontMetricsInt fontMetrics = paint.getFontMetricsInt();
    674             int row_hight = (Math.abs(fontMetrics.top) + fontMetrics.bottom) * 2;
    675 
    676             for (int i = 1; i <= MAX_LIST_WORD_COUNT; i++) {
    677                 TableRow row = new TableRow(this);
    678                 UserDictionaryToolsListFocus stroke = new UserDictionaryToolsListFocus(this);
    679                 stroke.setId(i);
    680                 stroke.setWidth(system_width/2);
    681                 stroke.setTextSize(WORD_TEXT_SIZE);
    682                 stroke.setTextColor(Color.LTGRAY);
    683                 stroke.setBackgroundColor(UNFOCUS_BACKGROUND_COLOR);
    684                 stroke.setSingleLine();
    685                 stroke.setPadding(1,0,1,1);
    686                 stroke.setEllipsize(TextUtils.TruncateAt.END);
    687                 stroke.setClickable(true);
    688                 stroke.setFocusable(true);
    689                 stroke.setFocusableInTouchMode(true);
    690                 stroke.setOnTouchListener(this);
    691                 stroke.setOnFocusChangeListener(this);
    692                 if (isXLarge()) {
    693                     stroke.setHeight(row_hight);
    694                     stroke.setGravity(Gravity.CENTER_VERTICAL);
    695                 }
    696 
    697                 UserDictionaryToolsListFocus candidate = new UserDictionaryToolsListFocus(this);
    698                 candidate.setId(i+MAX_WORD_COUNT);
    699                 candidate.setWidth(system_width/2);
    700                 candidate.setTextSize(WORD_TEXT_SIZE);
    701                 candidate.setTextColor(Color.LTGRAY);
    702                 candidate.setBackgroundColor(UNFOCUS_BACKGROUND_COLOR);
    703                 candidate.setSingleLine();
    704                 candidate.setPadding(1,0,1,1);
    705                 candidate.setEllipsize(TextUtils.TruncateAt.END);
    706                 candidate.setClickable(true);
    707                 candidate.setFocusable(true);
    708                 candidate.setFocusableInTouchMode(true);
    709                 candidate.setOnTouchListener(this);
    710                 candidate.setOnFocusChangeListener(this);
    711 
    712                 if (isXLarge()) {
    713                     candidate.setHeight(row_hight);
    714                     candidate.setGravity(Gravity.CENTER_VERTICAL);
    715                 }
    716                 stroke.setPairView(candidate);
    717                 candidate.setPairView(stroke);
    718 
    719                 row.addView(stroke);
    720                 row.addView(candidate);
    721                 mTableLayout.addView(row, tableCreateParam(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
    722             }
    723         }
    724 
    725         int size = mWordList.size();
    726         int start = mWordCount;
    727 
    728         TextView t = (TextView)findViewById(R.id.user_dictionary_position_indicator);
    729         if (size <= MAX_LIST_WORD_COUNT) {
    730             ((View)mLeftButton.getParent()).setVisibility(View.GONE);
    731         } else {
    732             ((View)mLeftButton.getParent()).setVisibility(View.VISIBLE);
    733             int last = (start + MAX_LIST_WORD_COUNT);
    734             t.setText((start + 1) + " - " + Math.min(last, size));
    735 
    736             mLeftButton.setEnabled(start != 0);
    737             mRightButton.setEnabled(last < size);
    738         }
    739 
    740         int selectedId = mSelectedViewID - ((MAX_WORD_COUNT < mSelectedViewID) ? MAX_WORD_COUNT : 0);
    741 
    742         for (int i = 0; i < MAX_LIST_WORD_COUNT; i++) {
    743             if ((size - 1) < (start + i)) {
    744                 if ((0 < i) && (selectedId == (i + 1))) {
    745                     mTableLayout.findViewById(i).requestFocus();
    746                 }
    747 
    748                 ((View)(mTableLayout.findViewById(i + 1)).getParent()).setVisibility(View.GONE);
    749                 continue;
    750             }
    751 
    752             WnnWord wnnWordGet;
    753             wnnWordGet = mSortData[start + i];
    754             int len_stroke = wnnWordGet.stroke.length();
    755             int len_candidate = wnnWordGet.candidate.length();
    756             if (len_stroke == 0 || len_candidate == 0) {
    757                 break;
    758             }
    759 
    760             if (selectedId == i + 1) {
    761                 mTableLayout.findViewById(i + 1).requestFocus();
    762             }
    763 
    764             TextView text = (TextView)mTableLayout.findViewById(i + 1);
    765             text.setText(wnnWordGet.stroke);
    766             text = (TextView)mTableLayout.findViewById(i + 1 + MAX_WORD_COUNT);
    767             text.setText(wnnWordGet.candidate);
    768             ((View)text.getParent()).setVisibility(View.VISIBLE);
    769         }
    770         mTableLayout.requestLayout();
    771     }
    772 
    773     /**
    774      * Whether the x large mode.
    775      *
    776      * @return      {@code true} if x large; {@code false} if not x large.
    777      */
    778     public static boolean isXLarge() {
    779         return mIsXLarge;
    780     }
    781 
    782 }
    783