1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "custom_input_method.h"
17
18 #include <string>
19
20 #include "common/input_method_manager.h"
21 #include "components/root_view.h"
22 #include "components/ui_checkbox.h"
23 #include "components/ui_edit_text.h"
24 #include "components/ui_label.h"
25 #include "font/ui_font.h"
26 #include "ui_test.h"
27
28 namespace OHOS {
29 namespace {
30 struct KeyInfo {
31 uint8_t keyCount;
32 uint8_t row1Count;
33 uint8_t row2Count;
34 uint8_t row3Count;
35 uint8_t row4Count;
36 const char* keyName[32]; // 32: max count of keys
37 };
38
39 const KeyInfo LOW_CASE_KEY_IOFO = {
40 32, 10, 19, 28, 32,
41 {
42 "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", // 10
43 "a", "s", "d", "f", "g", "h", "j", "k", "l", // 9
44 "shift", "z", "x", "c", "v", "b", "n", "m", "del", // 9
45 "123", "space", ".", "return" // 4
46 }
47 };
48
49 const KeyInfo UPPER_CASE_KEY_IOFO = {
50 32, 10, 19, 28, 32,
51 {
52 "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", // 10
53 "A", "S", "D", "F", "G", "H", "J", "K", "L", // 9
54 "shift", "Z", "X", "C", "V", "B", "N", "M", "del", // 9
55 "123", "space", ".", "return" // 4
56 }
57 };
58
59 const KeyInfo NUM_KEY_IOFO = {
60 31, 10, 20, 27, 31,
61 {
62 "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", // 10
63 "-", "/", ":", ";", "(", ")", "$", "&", "@", "\"", // 10
64 "#+=", ".", ",", "?", "!", "'", "del", // 7
65 "ABC", "space", ".", "return" // 4
66 }
67 };
68
69 const KeyInfo SYMBOL_KEY_IOFO = {
70 31, 10, 20, 27, 31,
71 {
72 "[", "]", "{", "}", "#", "%", "^", "*", "+", "=", // 10
73 "_", "\\", "|", "~", "<", ">", "¥", "€", "£", "•", // 10
74 "123", ".", ",", "?", "!", "'", "del", // 7
75 "ABC", "space", ".", "return" // 4
76 }
77 };
78
79 const int16_t KEYBOARD_WIDTH = 580;
80 const int16_t KEYBOARD_HEIGHT = 320;
81 const int16_t KEY_WIDTH = 50;
82 const int16_t KEY_HEIGHT = 65;
83 const int16_t FUNC_KEY_WIDTH = 65;
84 const int16_t SPACE_KEY_WIDTH = 260;
85 const int16_t RETURN_KEY_WIDTH = 120;
86 const int16_t KEY_BORDER_RADIUS = 10;
87 const int16_t KEY_MARGIN_LEFT = 7;
88
GetKeyInfo(KeyboardType type)89 KeyInfo GetKeyInfo(KeyboardType type)
90 {
91 KeyInfo keyInfo;
92 switch (type) {
93 case KeyboardType::LOW_CASE:
94 keyInfo = LOW_CASE_KEY_IOFO;
95 break;
96 case KeyboardType::UPPER_CASE:
97 keyInfo = UPPER_CASE_KEY_IOFO;
98 break;
99 case KeyboardType::NUMBER:
100 keyInfo = NUM_KEY_IOFO;
101 break;
102 case KeyboardType::SYMBOL:
103 keyInfo = SYMBOL_KEY_IOFO;
104 break;
105 default:
106 keyInfo = LOW_CASE_KEY_IOFO;
107 break;
108 }
109
110 return keyInfo;
111 }
112 } // namespace
113
OnShow(InputMethodManager::InputMethodParam & param)114 void CustomInputMethod::OnShow(InputMethodManager::InputMethodParam& param)
115 {
116 // init method
117 SetupView(keyboardType_);
118
119 // update value
120 editView_->SetText(param.text.c_str());
121 editView_->SetInputType(param.inputType);
122 if (param.view != nullptr) {
123 UIEditText* paramView = reinterpret_cast<UIEditText*>(param.view);
124 editView_->SetPlaceholder(paramView->GetPlaceholder());
125 editView_->SetPlaceholderColor(paramView->GetPlaceholderColor());
126 editView_->SetCursorColor(paramView->GetCursorColor());
127 editView_->SetTextColor(paramView->GetTextColor());
128 editView_->SetMaxLength(paramView->GetMaxLength());
129 }
130 editView_->Focus();
131 container_->Invalidate();
132
133 // keyboard show callback
134 InputMethodManager::GetInstance().OnKeyboardShow();
135 }
136
OnHide()137 void CustomInputMethod::OnHide()
138 {
139 editView_->Blur();
140 TearDownView();
141
142 // keyboard show callback
143 InputMethodManager::GetInstance().OnKeyboardHide();
144 }
145
SetupView(KeyboardType type)146 void CustomInputMethod::SetupView(KeyboardType type)
147 {
148 if (container_ == nullptr) {
149 container_ = new UIViewGroup();
150 container_->Resize(KEYBOARD_WIDTH, 650); // 650: height
151 container_->SetPosition(350, 100); // 350: position x, 100: position y
152 container_->SetStyle(STYLE_BORDER_COLOR, Color::White().full);
153 // add on rootview
154 RootView::GetInstance()->Add(container_);
155 }
156
157 if (editView_ != nullptr) {
158 container_->Remove(editView_);
159 delete editView_;
160 }
161 editView_ = new UIEditTextEx();
162 container_->Add(editView_);
163 editView_->Resize(250, 40); // 250: width, 40: height
164 editView_->SetPosition(0, 0);
165 editView_->SetViewId("Input_edit_text_view");
166
167 if (inputTypeBtn_ == nullptr) {
168 inputTypeBtn_ = new UILabelButton();
169 container_->Add(inputTypeBtn_);
170 inputTypeBtn_->Resize(100, 40); // 100: width, 40: height
171 inputTypeBtn_->SetText("toggle");
172 inputTypeBtn_->LayoutRightToSibling("Input_edit_text_view", 10); // 10: offset
173 inputTypeBtn_->SetOnClickListener(this);
174 inputTypeBtn_->SetStyleForState(STYLE_BACKGROUND_COLOR, BUTTON_STYLE_BACKGROUND_COLOR_VALUE,
175 UIButton::RELEASED);
176 inputTypeBtn_->SetStyleForState(STYLE_BACKGROUND_COLOR, BUTTON_STYLE_BACKGROUND_COLOR_VALUE, UIButton::PRESSED);
177 }
178
179 SetupKeyboard(type);
180 }
181
SetupKeyboard(KeyboardType type)182 void CustomInputMethod::SetupKeyboard(KeyboardType type)
183 {
184 UIViewGroup* keyboard = new UIViewGroup();
185 int16_t rowHeight = KEYBOARD_HEIGHT / 4; // 4: row number
186 keyboard->Resize(KEYBOARD_WIDTH, KEYBOARD_HEIGHT);
187 keyboard->SetPosition(0, 45); // 45: position y
188 keyboard->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full);
189 keyboard->SetViewId("keyboard");
190 container_->Add(keyboard);
191 FlexLayout* row1 = SetupKeyRow("row1", KEYBOARD_WIDTH, rowHeight);
192 row1->SetPosition(0, 0);
193 keyboard->Add(row1);
194
195 FlexLayout* row2 = SetupKeyRow("row2", KEYBOARD_WIDTH, rowHeight);
196 keyboard->Add(row2);
197 row2->LayoutBottomToSibling("row1");
198
199 FlexLayout* row3 = SetupKeyRow("row3", KEYBOARD_WIDTH, rowHeight);
200 keyboard->Add(row3);
201 row3->LayoutBottomToSibling("row2");
202
203 FlexLayout* row4 = SetupKeyRow("row4", KEYBOARD_WIDTH, rowHeight);
204 keyboard->Add(row4);
205 row4->LayoutBottomToSibling("row3");
206
207 KeyInfo keyInfo = GetKeyInfo(type);
208 for (int16_t i = 0; i < keyInfo.keyCount; i++) {
209 UILabelButton* key = SetupButton(keyInfo.keyName[i]);
210 if (i < keyInfo.row1Count) {
211 row1->Add(key);
212 } else if (i < keyInfo.row2Count) {
213 row2->Add(key);
214 } else if (i < keyInfo.row3Count) {
215 row3->Add(key);
216 } else if (i < keyInfo.row4Count) {
217 row4->Add(key);
218 }
219 }
220
221 row1->LayoutChildren();
222 row2->LayoutChildren();
223 row3->LayoutChildren();
224 row4->LayoutChildren();
225 keyboard->Invalidate();
226 }
227
SetupKeyRow(const char * name,int16_t width,int16_t height)228 FlexLayout* CustomInputMethod::SetupKeyRow(const char* name, int16_t width, int16_t height)
229 {
230 FlexLayout* row = new FlexLayout();
231 row->Resize(width, height);
232 row->SetViewId(name);
233 row->SetMajorAxisAlign(ALIGN_CENTER);
234 row->SetStyle(STYLE_BACKGROUND_OPA, OPA_TRANSPARENT);
235 return row;
236 }
237
SetupButton(const char * title)238 UILabelButton* CustomInputMethod::SetupButton(const char* title)
239 {
240 UILabelButton* keyBtn = new UILabelButton();
241 keyBtn->SetText(title);
242 keyBtn->SetFont(DEFAULT_VECTOR_FONT_FILENAME, BUTTON_LABEL_SIZE);
243 keyBtn->SetStyle(STYLE_MARGIN_LEFT, KEY_MARGIN_LEFT);
244 keyBtn->SetOnClickListener(this);
245 int16_t radius = KEY_BORDER_RADIUS;
246 keyBtn->SetStyleForState(STYLE_BORDER_RADIUS, radius, UIButton::RELEASED);
247 keyBtn->SetStyleForState(STYLE_BORDER_RADIUS, radius, UIButton::PRESSED);
248 keyBtn->SetStyleForState(STYLE_BORDER_RADIUS, radius, UIButton::INACTIVE);
249 keyBtn->SetStyleForState(STYLE_BACKGROUND_COLOR, BUTTON_STYLE_BACKGROUND_COLOR_VALUE, UIButton::RELEASED);
250 keyBtn->SetStyleForState(STYLE_BACKGROUND_COLOR, BUTTON_STYLE_BACKGROUND_COLOR_VALUE, UIButton::PRESSED);
251 keyBtn->SetStyleForState(STYLE_BACKGROUND_COLOR, BUTTON_STYLE_BACKGROUND_COLOR_VALUE, UIButton::INACTIVE);
252 keyBtn->Resize(KEY_WIDTH, KEY_HEIGHT);
253
254 if ((strcmp(title, "shift") == 0) || (strcmp(title, "del") == 0) || (strcmp(title, "123") == 0) ||
255 (strcmp(title, "ABC") == 0) || (strcmp(title, "#+=") == 0)) {
256 keyBtn->Resize(FUNC_KEY_WIDTH, KEY_HEIGHT);
257 } else if (strcmp(title, "space") == 0) {
258 keyBtn->Resize(SPACE_KEY_WIDTH, KEY_HEIGHT);
259 } else if (strcmp(title, "return") == 0) {
260 keyBtn->Resize(RETURN_KEY_WIDTH, KEY_HEIGHT);
261 }
262 return keyBtn;
263 }
264
TearDownView()265 void CustomInputMethod::TearDownView()
266 {
267 UITest::DeleteChildren(container_);
268 container_ = nullptr;
269 editView_ = nullptr;
270 }
271
OnClick(UIView & view,const ClickEvent & event)272 bool CustomInputMethod::OnClick(UIView& view, const ClickEvent& event)
273 {
274 if (inputTypeBtn_ == &view) {
275 InputType type = editView_->GetInputType();
276 if (type == InputType::TEXT_TYPE) {
277 editView_->SetInputType(InputType::PASSWORD_TYPE);
278 InputMethodManager::GetInstance().SetInputType(InputType::PASSWORD_TYPE);
279 } else {
280 editView_->SetInputType(InputType::TEXT_TYPE);
281 InputMethodManager::GetInstance().SetInputType(InputType::TEXT_TYPE);
282 }
283 } else {
284 DealKeyEvent(view);
285 }
286
287 return true;
288 }
289
DealKeyEvent(UIView & view)290 void CustomInputMethod::DealKeyEvent(UIView& view)
291 {
292 const char* key = reinterpret_cast<UILabelButton*>(&view)->GetText();
293 if (key == nullptr) {
294 return;
295 }
296
297 if (strcmp(key, "shift") == 0) {
298 if (keyboardType_ == KeyboardType::LOW_CASE) {
299 keyboardType_ = KeyboardType::UPPER_CASE;
300 } else {
301 keyboardType_ = KeyboardType::LOW_CASE;
302 }
303 ChangeKeyboard(keyboardType_);
304 } else if (strcmp(key, "123") == 0) {
305 keyboardType_ = KeyboardType::NUMBER;
306 ChangeKeyboard(keyboardType_);
307 } else if (strcmp(key, "ABC") == 0) {
308 keyboardType_ = KeyboardType::LOW_CASE;
309 ChangeKeyboard(keyboardType_);
310 } else if (strcmp(key, "#+=") == 0) {
311 keyboardType_ = KeyboardType::SYMBOL;
312 ChangeKeyboard(keyboardType_);
313 } else if (strcmp(key, "del") == 0) {
314 InputMethodManager::GetInstance().DeleteBackward(1);
315 editView_->DeleteBackward(1);
316 } else if (strcmp(key, "space") == 0) {
317 InputMethodManager::GetInstance().InsertText(" ");
318 editView_->InsertText(" ");
319 } else if (strcmp(key, "return") == 0) {
320 // do nothing
321 } else {
322 InputMethodManager::GetInstance().InsertText(key);
323 editView_->InsertText(key);
324 }
325 }
326
ChangeKeyboard(KeyboardType type)327 void CustomInputMethod::ChangeKeyboard(KeyboardType type)
328 {
329 UIView* keyboardTmp = container_->GetChildById("keyboard");
330 SetupKeyboard(type);
331 container_->Remove(keyboardTmp);
332 UITest::DeleteChildren(keyboardTmp);
333 }
334 } // namespace OHOS
335