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