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
17package jp.co.omronsoft.openwnn;
18
19import android.app.Activity;
20import android.app.AlertDialog;
21import android.app.Dialog;
22import android.content.DialogInterface;
23import android.content.Intent;
24import android.os.Bundle;
25import android.text.Editable;
26import android.text.TextWatcher;
27import android.util.Log;
28import android.view.KeyEvent;
29import android.view.View;
30import android.view.Window;
31import android.widget.Button;
32import android.widget.EditText;
33import android.widget.TextView;
34import android.widget.Toast;
35
36/**
37 * The abstract class for user dictionary's word editor.
38 *
39 * @author Copyright (C) 2009, OMRON SOFTWARE CO., LTD.  All Rights Reserved.
40 */
41public abstract class UserDictionaryToolsEdit extends Activity implements View.OnClickListener {
42    /** The class information for intent(Set this informations in the extend class) */
43    protected String  mListViewName;
44    /** The class information for intent(Set this informations in the extend class) */
45    protected String  mPackageName;
46
47    /** The operation mode (Unknown) */
48    private static final int STATE_UNKNOWN = 0;
49    /** The operation mode (Add the word) */
50    private static final int STATE_INSERT = 1;
51    /** The operation mode (Edit the word) */
52    private static final int STATE_EDIT = 2;
53
54    /** Maximum length of a word's string */
55    private static final int MAX_TEXT_SIZE = 20;
56
57    /** The error code (Already registered the same word) */
58    private static final int RETURN_SAME_WORD = -11;
59
60    /** The focus view and pair view */
61    private static View sFocusingView = null;
62    private static View sFocusingPairView = null;
63
64    /** Widgets which constitute this screen of activity */
65    private EditText mReadEditText;
66    private EditText mCandidateEditText;
67    private Button mEntryButton;
68    private Button mCancelButton;
69
70    /** The word information which contains the previous information */
71    private WnnWord mBeforeEditWnnWord;
72    /** The instance of word list activity */
73    private UserDictionaryToolsList mListInstance;
74
75    /** The constant for notifying dialog (Already exists the specified word) */
76    private static final int DIALOG_CONTROL_WORDS_DUPLICATE = 0;
77    /** The constant for notifying dialog (The length of specified stroke or candidate exceeds the limit) */
78    private static final int DIALOG_CONTROL_OVER_MAX_TEXT_SIZE = 1;
79
80    /** The operation mode of this activity */
81    private int mRequestState;
82
83    /**
84     * Constructor
85     */
86    public UserDictionaryToolsEdit() {
87        super();
88    }
89
90    /**
91     * Constructor
92     *
93     * @param  focusView      The information of view
94     * @param  focusPairView  The information of pair of view
95     */
96    public UserDictionaryToolsEdit(View focusView, View focusPairView) {
97        super();
98        sFocusingView = focusView;
99        sFocusingPairView = focusPairView;
100    }
101
102    /**
103     * Send the specified event to IME
104     *
105     * @param ev    The event object
106     * @return      {@code true} if this event is processed.
107     */
108    protected abstract boolean sendEventToIME(OpenWnnEvent ev);
109
110    /** @see android.app.Activity#onCreate */
111    @Override protected void onCreate(Bundle savedInstanceState) {
112
113        super.onCreate(savedInstanceState);
114
115        /* create view from XML layout */
116        setContentView(R.layout.user_dictionary_tools_edit);
117
118        /* get widgets */
119        mEntryButton = (Button)findViewById(R.id.addButton);
120        mCancelButton = (Button)findViewById(R.id.cancelButton);
121        mReadEditText = (EditText)findViewById(R.id.editRead);
122        mCandidateEditText = (EditText)findViewById(R.id.editCandidate);
123
124        /* set the listener */
125        mEntryButton.setOnClickListener(this);
126        mCancelButton.setOnClickListener(this);
127
128        /* initialize */
129        mRequestState = STATE_UNKNOWN;
130        mReadEditText.setSingleLine();
131        mCandidateEditText.setSingleLine();
132
133        /* get the request and do it */
134        Intent intent = getIntent();
135        String action = intent.getAction();
136        if (action.equals(Intent.ACTION_INSERT)) {
137            /* add a word */
138            mEntryButton.setEnabled(false);
139            mRequestState = STATE_INSERT;
140        } else if (action.equals(Intent.ACTION_EDIT)) {
141            /* edit a word */
142            mEntryButton.setEnabled(true);
143            mReadEditText.setText(((TextView)sFocusingView).getText());
144            mCandidateEditText.setText(((TextView)sFocusingPairView).getText());
145            mRequestState = STATE_EDIT;
146
147            /* save the word's information before this edit */
148            mBeforeEditWnnWord = new WnnWord();
149            mBeforeEditWnnWord.stroke = ((TextView)sFocusingView).getText().toString();
150            mBeforeEditWnnWord.candidate = ((TextView)sFocusingPairView).getText().toString();
151        } else {
152            /* finish if it is unknown request */
153            Log.e("OpenWnn", "onCreate() : Invaled Get Intent. ID=" + intent);
154            finish();
155            return;
156        }
157
158        getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,
159                                  R.layout.user_dictionary_tools_edit_header);
160
161        /* set control buttons */
162        setAddButtonControl();
163
164    }
165
166    /** @see android.app.Activity#onKeyDown */
167    @Override public boolean onKeyDown(int keyCode, KeyEvent event) {
168        if (keyCode == KeyEvent.KEYCODE_BACK) {
169            /* go back to the word list view */
170            screenTransition();
171            return true;
172        }
173        return super.onKeyDown(keyCode, event);
174    }
175
176    /**
177     * Change the state of the "Add" button into the depending state of input area.
178     */
179    public void setAddButtonControl() {
180
181        /* Text changed listener for the reading text */
182        mReadEditText.addTextChangedListener(new TextWatcher() {
183            public void afterTextChanged(Editable s) {
184            }
185            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
186            }
187            public void onTextChanged(CharSequence s, int start, int before, int count) {
188                /* Enable/disable the "Add" button */
189                if ((mReadEditText.getText().toString().length() != 0) &&
190                    (mCandidateEditText.getText().toString().length() != 0)) {
191                    mEntryButton.setEnabled(true);
192                } else {
193                    mEntryButton.setEnabled(false);
194                }
195            }
196        });
197        /* Text changed listener for the candidate text */
198        mCandidateEditText.addTextChangedListener(new TextWatcher() {
199            public void afterTextChanged(Editable s) {
200            }
201            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
202            }
203            public void onTextChanged(CharSequence s, int start, int before, int count) {
204            	/* Enable/disable the "Add" button */
205                if ((mReadEditText.getText().toString().length() != 0) &&
206                    (mCandidateEditText.getText().toString().length() != 0)) {
207                    mEntryButton.setEnabled(true);
208                } else {
209                    mEntryButton.setEnabled(false);
210                }
211            }
212        });
213
214    }
215
216    /** @see android.view.View.OnClickListener */
217    public void onClick(View v) {
218
219        mEntryButton.setEnabled(false);
220        mCancelButton.setEnabled(false);
221
222        switch (v.getId()) {
223            case R.id.addButton:
224                /* save the word */
225                doSaveAction();
226                break;
227
228            case R.id.cancelButton:
229                /* cancel the edit */
230                doRevertAction();
231                break;
232
233            default:
234                Log.e("OpenWnn", "onClick: Get Invalid ButtonID. ID=" + v.getId());
235                finish();
236                return;
237        }
238    }
239
240    /**
241     * Process the adding or editing action
242     */
243    private void doSaveAction() {
244
245        switch (mRequestState) {
246        case STATE_INSERT:
247            /* register a word */
248            if (inputDataCheck(mReadEditText) && inputDataCheck(mCandidateEditText)) {
249                    String stroke = mReadEditText.getText().toString();
250                    String candidate = mCandidateEditText.getText().toString();
251                    if (addDictionary(stroke, candidate)) {
252                        screenTransition();
253                    }
254                }
255            break;
256
257        case STATE_EDIT:
258            /* edit a word (=delete the word selected & add the word edited) */
259            if (inputDataCheck(mReadEditText) && inputDataCheck(mCandidateEditText)) {
260                deleteDictionary(mBeforeEditWnnWord);
261                    String stroke = mReadEditText.getText().toString();
262                    String candidate = mCandidateEditText.getText().toString();
263                    if (addDictionary(stroke, candidate)) {
264                        screenTransition();
265                    } else {
266                        addDictionary(mBeforeEditWnnWord.stroke, mBeforeEditWnnWord.candidate);
267                    }
268                }
269            break;
270
271        default:
272            Log.e("OpenWnn", "doSaveAction: Invalid Add Status. Status=" + mRequestState);
273            break;
274        }
275    }
276
277    /**
278     * Process the cancel action
279     */
280    private void doRevertAction() {
281        /* go back to the words list */
282        screenTransition();
283    }
284
285    /**
286     * Create the alert dialog for notifying the error
287     *
288     * @param  id        The dialog ID
289     * @return           The information of the dialog
290     */
291    @Override protected Dialog onCreateDialog(int id) {
292        switch (id) {
293            case DIALOG_CONTROL_WORDS_DUPLICATE:
294                /* there is the same word in the dictionary */
295                return new AlertDialog.Builder(UserDictionaryToolsEdit.this)
296                        .setIcon(android.R.drawable.ic_dialog_alert)
297                        .setMessage(R.string.user_dictionary_words_duplication_message)
298                        .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
299                            public void onClick(DialogInterface dialog, int whichButton) {
300                                mEntryButton.setEnabled(true);
301                                mCancelButton.setEnabled(true);
302                            }
303                        })
304                        .setCancelable(true)
305                        .setOnCancelListener(new DialogInterface.OnCancelListener() {
306                            public void onCancel(DialogInterface dialog) {
307                                mEntryButton.setEnabled(true);
308                                mCancelButton.setEnabled(true);
309                            }
310                        })
311                        .create();
312
313            case DIALOG_CONTROL_OVER_MAX_TEXT_SIZE:
314                /* the length of the word exceeds the limit */
315                return new AlertDialog.Builder(UserDictionaryToolsEdit.this)
316                        .setIcon(android.R.drawable.ic_dialog_alert)
317                        .setMessage(R.string.user_dictionary_over_max_text_size_message)
318                        .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
319                            public void onClick(DialogInterface dialog, int witchButton) {
320                                mEntryButton.setEnabled(true);
321                                mCancelButton.setEnabled(true);
322                            }
323                        })
324                        .setCancelable(true)
325                        .create();
326        }
327        return super.onCreateDialog(id);
328    }
329
330    /**
331     * Add the word
332     *
333     * @param  stroke       The stroke of the word
334     * @param  candidate    The string of the word
335     * @return              {@code true} if success; {@code false} if fail.
336     */
337    private boolean addDictionary(String stroke, String candidate) {
338        boolean ret;
339
340        /* create WnnWord from the strings */
341        WnnWord wnnWordAdd = new WnnWord();
342        wnnWordAdd.stroke = stroke;
343        wnnWordAdd.candidate = candidate;
344        /* add word event */
345        OpenWnnEvent event = new OpenWnnEvent(OpenWnnEvent.ADD_WORD,
346                                  WnnEngine.DICTIONARY_TYPE_USER,
347                                  wnnWordAdd);
348        /* notify the event to IME */
349        ret = sendEventToIME(event);
350        if (ret == false) {
351            /* get error code if the process in IME is failed */
352            int ret_code = event.errorCode;
353            if (ret_code == RETURN_SAME_WORD) {
354                showDialog(DIALOG_CONTROL_WORDS_DUPLICATE);
355            }
356        } else {
357            /* update the dictionary */
358            mListInstance = createUserDictionaryToolsList();
359        }
360        return ret;
361    }
362
363    /**
364     * Delete the word
365     *
366     * @param  word     The information of word
367     */
368    private void deleteDictionary(WnnWord word) {
369        /* delete the word from the dictionary */
370        mListInstance = createUserDictionaryToolsList();
371        boolean deleted = mListInstance.deleteWord(word);
372        if (!deleted) {
373            Toast.makeText(getApplicationContext(),
374                           R.string.user_dictionary_delete_fail,
375                           Toast.LENGTH_LONG).show();
376        }
377    }
378
379    /**
380     * Create the instance of UserDictionaryToolList object
381     */
382    protected abstract UserDictionaryToolsList createUserDictionaryToolsList();
383
384    /**
385     * Check the input string
386     *
387     * @param   v       The information of view
388     * @return          {@code true} if success; {@code false} if fail.
389     */
390    private boolean inputDataCheck(View v) {
391
392        /* return false if the length of the string exceeds the limit. */
393        if ((((TextView)v).getText().length()) > MAX_TEXT_SIZE) {
394            showDialog(DIALOG_CONTROL_OVER_MAX_TEXT_SIZE);
395            Log.e("OpenWnn", "inputDataCheck() : over max string length.");
396            return false;
397        }
398
399        return true;
400    }
401
402    /**
403     * Transit the new state
404     */
405    private void screenTransition() {
406        finish();
407
408        /* change to the word listing window */
409        Intent intent = new Intent();
410        intent.setClassName(mPackageName, mListViewName);
411        startActivity(intent);
412
413    }
414
415}
416