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      */
sendEventToIME(OpenWnnEvent ev)160     protected abstract boolean sendEventToIME(OpenWnnEvent ev);
161     /** Get the comparator for sorting the list */
getComparator()162     protected abstract Comparator<WnnWord> getComparator();
163 
164     /** Show Dialog Num */
165     private int mDialogShow = -1;
166 
167     /** @see android.app.Activity#onCreate */
onCreate(Bundle savedInstanceState)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 */
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      */
onPause()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      */
tableCreateParam(int w, int h)247     private TableLayout.LayoutParams tableCreateParam(int w, int h) {
248         return new TableLayout.LayoutParams(w, h);
249     }
250 
251     /** @see android.app.Activity#onCreateOptionsMenu */
onCreateOptionsMenu(Menu menu)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      */
setOptionsMenuEnabled()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 */
onOptionsItemSelected(MenuItem item)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 */
onKeyUp(int keyCode, KeyEvent event)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 */
onCreateDialog(int id)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 */
onClick(View arg0)475     public void onClick(View arg0) {
476     }
477 
478     /** @see android.view.View.OnTouchListener#onTouch */
onTouch(View v, MotionEvent e)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 */
onFocusChange(View v, boolean hasFocus)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      */
wordAdd()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      */
wordEdit(View focusView, View focusPairView)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      */
createUserDictionaryToolsEdit(View focusView, View focusPairView)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      */
deleteWord(WnnWord searchword)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      */
screenTransition(String action, String classname)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      */
getWords()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      */
compareTo(ArrayList<WnnWord> array)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      */
updateWordList()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