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.os.Bundle; 25 import android.text.Editable; 26 import android.text.TextWatcher; 27 import android.util.Log; 28 import android.view.KeyEvent; 29 import android.view.View; 30 import android.view.Window; 31 import android.widget.Button; 32 import android.widget.EditText; 33 import android.widget.TextView; 34 import 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 */ 41 public 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