/* * Copyright (c) 2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "custom_input_method.h" #include #include "common/input_method_manager.h" #include "components/root_view.h" #include "components/ui_checkbox.h" #include "components/ui_edit_text.h" #include "components/ui_label.h" #include "font/ui_font.h" #include "ui_test.h" #include "graphic_timer.h" namespace OHOS { namespace { struct KeyInfo { uint8_t keyCount; uint8_t row1Count; uint8_t row2Count; uint8_t row3Count; uint8_t row4Count; const char* keyName[32]; // 32: max count of keys }; const KeyInfo LOW_CASE_KEY_IOFO = { 32, 10, 19, 28, 32, { "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", // 10 "a", "s", "d", "f", "g", "h", "j", "k", "l", // 9 "shift", "z", "x", "c", "v", "b", "n", "m", "del", // 9 "123", "space", ".", "return" // 4 } }; const KeyInfo UPPER_CASE_KEY_IOFO = { 32, 10, 19, 28, 32, { "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", // 10 "A", "S", "D", "F", "G", "H", "J", "K", "L", // 9 "shift", "Z", "X", "C", "V", "B", "N", "M", "del", // 9 "123", "space", ".", "return" // 4 } }; const KeyInfo NUM_KEY_IOFO = { 31, 10, 20, 27, 31, { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", // 10 "-", "/", ":", ";", "(", ")", "$", "&", "@", "\"", // 10 "#+=", ".", ",", "?", "!", "'", "del", // 7 "ABC", "space", ".", "return" // 4 } }; const KeyInfo SYMBOL_KEY_IOFO = { 31, 10, 20, 27, 31, { "[", "]", "{", "}", "#", "%", "^", "*", "+", "=", // 10 "_", "\\", "|", "~", "<", ">", "¥", "€", "£", "•", // 10 "123", ".", ",", "?", "!", "'", "del", // 7 "ABC", "space", ".", "return" // 4 } }; const int16_t KEYBOARD_WIDTH = 580; const int16_t KEYBOARD_HEIGHT = 320; const int16_t KEY_WIDTH = 50; const int16_t KEY_HEIGHT = 65; const int16_t FUNC_KEY_WIDTH = 65; const int16_t SPACE_KEY_WIDTH = 260; const int16_t RETURN_KEY_WIDTH = 120; const int16_t KEY_BORDER_RADIUS = 10; const int16_t KEY_MARGIN_LEFT = 7; KeyInfo GetKeyInfo(KeyboardType type) { KeyInfo keyInfo; switch (type) { case KeyboardType::LOW_CASE: keyInfo = LOW_CASE_KEY_IOFO; break; case KeyboardType::UPPER_CASE: keyInfo = UPPER_CASE_KEY_IOFO; break; case KeyboardType::NUMBER: keyInfo = NUM_KEY_IOFO; break; case KeyboardType::SYMBOL: keyInfo = SYMBOL_KEY_IOFO; break; default: keyInfo = LOW_CASE_KEY_IOFO; break; } return keyInfo; } } // namespace void CustomInputMethod::OnShow(InputMethodManager::InputMethodParam& param) { bool needFocus = editView_ == nullptr ? true : false; SetupView(keyboardType_); // update value editView_->SetText(param.text.c_str()); editView_->SetInputType(param.inputType); if (param.view != nullptr) { UIEditText* paramView = reinterpret_cast(param.view); editView_->SetPlaceholder(paramView->GetPlaceholder()); editView_->SetPlaceholderColor(paramView->GetPlaceholderColor()); editView_->SetCursorColor(paramView->GetCursorColor()); editView_->SetCursorIndex(paramView->GetCursorIndex()); editView_->SetTextColor(paramView->GetTextColor()); editView_->SetMaxLength(paramView->GetMaxLength()); } if (needFocus) { editView_->RequestFocus(); } container_->Invalidate(); // keyboard show callback InputMethodManager::GetInstance().OnKeyboardShow(); } void CustomInputMethod::OnHide() { editView_->Blur(); TearDownView(); // keyboard show callback InputMethodManager::GetInstance().OnKeyboardHide(); } void CustomInputMethod::SetupView(KeyboardType type) { if (container_ == nullptr) { container_ = new UIViewGroup(); container_->Resize(KEYBOARD_WIDTH, 650); // 650: height container_->SetPosition(350, 100); // 350: position x, 100: position y container_->SetStyle(STYLE_BORDER_COLOR, Color::White().full); // add on rootview RootView::GetInstance()->Add(container_); } if (editView_ != nullptr) { container_->Remove(editView_); delete editView_; } editView_ = new UIEditTextEx(); container_->Add(editView_); editView_->Resize(250, 40); // 250: width, 40: height editView_->SetPosition(0, 0); editView_->SetViewId("Input_edit_text_view"); if (inputTypeBtn_ == nullptr) { inputTypeBtn_ = new UILabelButton(); container_->Add(inputTypeBtn_); inputTypeBtn_->Resize(100, 40); // 100: width, 40: height inputTypeBtn_->SetText("toggle"); inputTypeBtn_->SetViewId(UI_TEST_KEY_INPUT); inputTypeBtn_->LayoutRightToSibling("Input_edit_text_view", 10); // 10: offset inputTypeBtn_->SetOnClickListener(this); inputTypeBtn_->SetStyleForState(STYLE_BACKGROUND_COLOR, BUTTON_STYLE_BACKGROUND_COLOR_VALUE, UIButton::RELEASED); inputTypeBtn_->SetStyleForState(STYLE_BACKGROUND_COLOR, BUTTON_STYLE_BACKGROUND_COLOR_VALUE, UIButton::PRESSED); } SetupKeyboard(type); } void CustomInputMethod::SetupKeyboard(KeyboardType type) { UIViewGroup* keyboard = new UIViewGroup(); int16_t rowHeight = KEYBOARD_HEIGHT / 4; // 4: row number keyboard->Resize(KEYBOARD_WIDTH, KEYBOARD_HEIGHT); keyboard->SetPosition(0, 45); // 45: position y keyboard->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); keyboard->SetViewId("keyboard"); container_->Add(keyboard); FlexLayout* row1 = SetupKeyRow("row1", KEYBOARD_WIDTH, rowHeight); row1->SetPosition(0, 0); keyboard->Add(row1); FlexLayout* row2 = SetupKeyRow("row2", KEYBOARD_WIDTH, rowHeight); keyboard->Add(row2); row2->LayoutBottomToSibling("row1"); FlexLayout* row3 = SetupKeyRow("row3", KEYBOARD_WIDTH, rowHeight); keyboard->Add(row3); row3->LayoutBottomToSibling("row2"); FlexLayout* row4 = SetupKeyRow("row4", KEYBOARD_WIDTH, rowHeight); keyboard->Add(row4); row4->LayoutBottomToSibling("row3"); KeyInfo keyInfo = GetKeyInfo(type); for (int16_t i = 0; i < keyInfo.keyCount; i++) { UILabelButton* key = SetupButton(keyInfo.keyName[i]); if (i < keyInfo.row1Count) { row1->Add(key); } else if (i < keyInfo.row2Count) { row2->Add(key); } else if (i < keyInfo.row3Count) { row3->Add(key); } else if (i < keyInfo.row4Count) { row4->Add(key); } } row1->LayoutChildren(); row2->LayoutChildren(); row3->LayoutChildren(); row4->LayoutChildren(); keyboard->Invalidate(); } FlexLayout* CustomInputMethod::SetupKeyRow(const char* name, int16_t width, int16_t height) { FlexLayout* row = new FlexLayout(); row->Resize(width, height); row->SetViewId(name); row->SetMajorAxisAlign(ALIGN_CENTER); row->SetStyle(STYLE_BACKGROUND_OPA, OPA_TRANSPARENT); return row; } UILabelButton* CustomInputMethod::SetupButton(const char* title) { UILabelButton* keyBtn = new UILabelButton(); keyBtn->SetText(title); keyBtn->SetViewId(title); keyBtn->SetFont(DEFAULT_VECTOR_FONT_FILENAME, BUTTON_LABEL_SIZE); keyBtn->SetStyle(STYLE_MARGIN_LEFT, KEY_MARGIN_LEFT); keyBtn->SetOnClickListener(this); int16_t radius = KEY_BORDER_RADIUS; keyBtn->SetStyleForState(STYLE_BORDER_RADIUS, radius, UIButton::RELEASED); keyBtn->SetStyleForState(STYLE_BORDER_RADIUS, radius, UIButton::PRESSED); keyBtn->SetStyleForState(STYLE_BORDER_RADIUS, radius, UIButton::INACTIVE); keyBtn->SetStyleForState(STYLE_BACKGROUND_COLOR, BUTTON_STYLE_BACKGROUND_COLOR_VALUE, UIButton::RELEASED); keyBtn->SetStyleForState(STYLE_BACKGROUND_COLOR, BUTTON_STYLE_BACKGROUND_COLOR_VALUE, UIButton::PRESSED); keyBtn->SetStyleForState(STYLE_BACKGROUND_COLOR, BUTTON_STYLE_BACKGROUND_COLOR_VALUE, UIButton::INACTIVE); keyBtn->Resize(KEY_WIDTH, KEY_HEIGHT); keyBtn->SetOnLongPressListener(this); keyBtn->SetOnTouchListener(this); if ((strcmp(title, "shift") == 0) || (strcmp(title, "del") == 0) || (strcmp(title, "123") == 0) || (strcmp(title, "ABC") == 0) || (strcmp(title, "#+=") == 0)) { keyBtn->Resize(FUNC_KEY_WIDTH, KEY_HEIGHT); } else if (strcmp(title, "space") == 0) { keyBtn->Resize(SPACE_KEY_WIDTH, KEY_HEIGHT); } else if (strcmp(title, "return") == 0) { keyBtn->Resize(RETURN_KEY_WIDTH, KEY_HEIGHT); } return keyBtn; } void CustomInputMethod::TearDownView() { UITest::DeleteChildren(container_); container_ = nullptr; editView_ = nullptr; } bool CustomInputMethod::OnClick(UIView& view, const ClickEvent& event) { if (inputTypeBtn_ == &view) { InputType type = editView_->GetInputType(); if (type == InputType::TEXT_TYPE) { editView_->SetInputType(InputType::PASSWORD_TYPE); InputMethodManager::GetInstance().SetInputType(InputType::PASSWORD_TYPE); } else { editView_->SetInputType(InputType::TEXT_TYPE); InputMethodManager::GetInstance().SetInputType(InputType::TEXT_TYPE); } } else { DealKeyEvent(view); } return true; } void CustomInputMethod::DealKeyEvent(UIView& view) { const char* key = reinterpret_cast(&view)->GetText(); if (key == nullptr) { return; } if (editView_ == nullptr) { return; } if (editView_->GetIsFocus()) { InputMethodManager::GetInstance().SetCursorIndex(editView_->GetCursorIndex()); } else { editView_->SetCursorIndex(InputMethodManager::GetInstance().GetCursorIndex()); } if (strcmp(key, "shift") == 0) { if (keyboardType_ == KeyboardType::LOW_CASE) { keyboardType_ = KeyboardType::UPPER_CASE; } else { keyboardType_ = KeyboardType::LOW_CASE; } ChangeKeyboard(keyboardType_); } else if (strcmp(key, "123") == 0) { keyboardType_ = KeyboardType::NUMBER; ChangeKeyboard(keyboardType_); } else if (strcmp(key, "ABC") == 0) { keyboardType_ = KeyboardType::LOW_CASE; ChangeKeyboard(keyboardType_); } else if (strcmp(key, "#+=") == 0) { keyboardType_ = KeyboardType::SYMBOL; ChangeKeyboard(keyboardType_); } else if (strcmp(key, "del") == 0) { InputMethodManager::GetInstance().DeleteBackward(1); editView_->DeleteBackward(1); } else if (strcmp(key, "space") == 0) { InputMethodManager::GetInstance().InsertText(" "); editView_->InsertText(" "); } else if (strcmp(key, "return") == 0) { // do nothing } else { InputMethodManager::GetInstance().InsertText(key); editView_->InsertText(key); } } bool CustomInputMethod::OnLongPress(UIView &view, const LongPressEvent &event) { longPressed_ = true; if (inputTypeBtn_ == &view) { InputType type = editView_->GetInputType(); if (type == InputType::TEXT_TYPE) { editView_->SetInputType(InputType::PASSWORD_TYPE); InputMethodManager::GetInstance().SetInputType(InputType::PASSWORD_TYPE); } else { editView_->SetInputType(InputType::TEXT_TYPE); InputMethodManager::GetInstance().SetInputType(InputType::TEXT_TYPE); } } else { key_ = reinterpret_cast(&view)->GetText(); timer_.Start(); } return true; } bool CustomInputMethod::OnRelease(UIView& view, const ReleaseEvent& event) { if (longPressed_) { longPressed_ = false; timer_.Stop(); } return true; } void CustomInputMethod::DealLongPressKeyEvent() { if (key_ == nullptr) { return; } if (strcmp(key_, "del") == 0) { InputMethodManager::GetInstance().DeleteBackward(1); editView_->DeleteBackward(1); } else if (strcmp(key_, "space") == 0) { InputMethodManager::GetInstance().InsertText(" "); editView_->InsertText(" "); } else if (strcmp(key_, "return") == 0 || strcmp(key_, "123") == 0 || strcmp(key_, "ABC") == 0 || strcmp(key_, "#+=") == 0 || strcmp(key_, "shift") == 0) { // do nothing } else { InputMethodManager::GetInstance().InsertText(key_); editView_->InsertText(key_); } if (!longPressed_) { timer_.Stop(); } else { timer_.Start(); } } void CustomInputMethod::ChangeKeyboard(KeyboardType type) { UIView* keyboardTmp = container_->GetChildById("keyboard"); SetupKeyboard(type); container_->Remove(keyboardTmp); UITest::DeleteChildren(keyboardTmp); } } // namespace OHOS