1 /*
2 * Copyright (c) 2021 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 "core/components/declaration/input/input_declaration.h"
17
18 #include "base/utils/string_utils.h"
19 #include "core/components/declaration/common/declaration_constants.h"
20 #include "core/components/declaration/textfield/textfield_declaration.h"
21 #include "frameworks/bridge/common/utils/utils.h"
22 #include "frameworks/core/components/text_field/textfield_theme.h"
23
24 namespace OHOS::Ace {
25 namespace {
26
27 // input type
28 constexpr char INPUT_TYPE_BUTTON[] = "button";
29 constexpr char INPUT_TYPE_CHECKBOX[] = "checkbox";
30 constexpr char INPUT_TYPE_RADIO[] = "radio";
31 constexpr char INPUT_TYPE_TEXT[] = "text";
32 constexpr char INPUT_TYPE_EMAIL[] = "email";
33 constexpr char INPUT_TYPE_DATE[] = "date";
34 constexpr char INPUT_TYPE_TIME[] = "time";
35 constexpr char INPUT_TYPE_NUMBER[] = "number";
36 constexpr char INPUT_TYPE_PASSWORD[] = "password";
37
38 std::set<std::string> g_textCategory;
39
40 // If type is changed between g_textCategory, there is no need to recreate components.
ShouldCreateNewComponent(const std::string & oldType,const std::string & newType)41 bool ShouldCreateNewComponent(const std::string& oldType, const std::string& newType)
42 {
43 if (g_textCategory.empty()) {
44 g_textCategory = std::set<std::string>({ INPUT_TYPE_TEXT, INPUT_TYPE_EMAIL, INPUT_TYPE_DATE, INPUT_TYPE_TIME,
45 INPUT_TYPE_NUMBER, INPUT_TYPE_PASSWORD });
46 }
47 return g_textCategory.find(oldType) == g_textCategory.end() || g_textCategory.find(newType) == g_textCategory.end();
48 }
49
50 } // namespace
51
52 using namespace Framework;
53
InitSpecialized()54 void InputDeclaration::InitSpecialized()
55 {
56 AddSpecializedAttribute(DeclarationConstants::DEFAULT_INPUT_ATTR);
57 }
58
InitializeStyle()59 void InputDeclaration::InitializeStyle()
60 {
61 if (specializedDeclaration_) {
62 specializedDeclaration_->InitializeStyle();
63 }
64 }
65
SetSpecializedAttr(const std::pair<std::string,std::string> & attr)66 bool InputDeclaration::SetSpecializedAttr(const std::pair<std::string, std::string>& attr)
67 {
68 static const std::set<std::string> inputCategory { INPUT_TYPE_BUTTON, INPUT_TYPE_CHECKBOX, INPUT_TYPE_RADIO,
69 INPUT_TYPE_TEXT, INPUT_TYPE_EMAIL, INPUT_TYPE_DATE, INPUT_TYPE_TIME, INPUT_TYPE_NUMBER, INPUT_TYPE_PASSWORD };
70 if (attr.first == DOM_INPUT_TYPE) {
71 auto& specializedAttr = MaybeResetAttribute<InputAttribute>(AttributeTag::SPECIALIZED_ATTR);
72 if (specializedAttr.IsValid()) {
73 std::string typeName = attr.second;
74 if (typeName.empty() || inputCategory.find(typeName) == inputCategory.end()) {
75 typeName = INPUT_TYPE_TEXT;
76 }
77 specializedAttr.type.second = ShouldCreateNewComponent(specializedAttr.type.first, typeName);
78 specializedAttr.type.first = typeName;
79 }
80 return true;
81 }
82 inputAttrs_[attr.first] = attr.second;
83 return false;
84 }
85
SetSpecializedStyle(const std::pair<std::string,std::string> & style)86 bool InputDeclaration::SetSpecializedStyle(const std::pair<std::string, std::string>& style)
87 {
88 inputStyles_[style.first] = style.second;
89 return false;
90 }
91
SetSpecializedEvent(int32_t pageId,const std::string & eventId,const std::string & event)92 bool InputDeclaration::SetSpecializedEvent(int32_t pageId, const std::string& eventId, const std::string& event)
93 {
94 inputEvents_[event] = eventId;
95 pageId_ = pageId;
96 return false;
97 }
98
CallSpecializedMethod(const std::string & method,const std::string & args)99 void InputDeclaration::CallSpecializedMethod(const std::string& method, const std::string& args)
100 {
101 if (g_textCategory.find(GetType()) != g_textCategory.end()) {
102 auto declaration = AceType::DynamicCast<TextFieldDeclaration>(specializedDeclaration_);
103 if (declaration) {
104 declaration->CallSpecializedMethod(method, args);
105 }
106 }
107 }
108
OnRequestFocus(bool shouldFocus)109 void InputDeclaration::OnRequestFocus(bool shouldFocus)
110 {
111 if (g_textCategory.find(GetType()) != g_textCategory.end()) {
112 auto declaration = AceType::DynamicCast<TextFieldDeclaration>(specializedDeclaration_);
113 if (declaration) {
114 declaration->OnRequestFocus(shouldFocus);
115 }
116 }
117 }
118
PrepareSpecializedDeclaration()119 void InputDeclaration::PrepareSpecializedDeclaration()
120 {
121 CreateSpecializedDeclaration();
122 auto declaration = AceType::DynamicCast<TextFieldDeclaration>(specializedDeclaration_);
123 if (declaration) {
124 for (const auto& attr : inputAttrs_) {
125 declaration->SetSpecializedAttr(attr);
126 }
127 for (const auto& style : inputStyles_) {
128 declaration->SetSpecializedStyle(style);
129 }
130 for (const auto& event : inputEvents_) {
131 declaration->SetSpecializedEvent(pageId_, event.second, event.first);
132 }
133 }
134
135 PrepareTextField();
136 }
137
CreateSpecializedDeclaration()138 void InputDeclaration::CreateSpecializedDeclaration()
139 {
140 std::pair<std::string, bool> type = { INPUT_TYPE_TEXT, true };
141 auto& specializedAttr = static_cast<InputAttribute&>(GetAttribute(AttributeTag::SPECIALIZED_ATTR));
142 if (specializedAttr.IsValid()) {
143 type = specializedAttr.type;
144 if (!type.second) {
145 LOGD("type of input is not changed.");
146 return;
147 }
148 specializedAttr.type.second = true;
149 }
150
151 if (specializedAttr.type.first == INPUT_TYPE_BUTTON) {
152 } else if (specializedAttr.type.first == INPUT_TYPE_CHECKBOX) {
153 } else if (specializedAttr.type.first == INPUT_TYPE_RADIO) {
154 } else {
155 specializedDeclaration_ = AceType::MakeRefPtr<TextFieldDeclaration>();
156 }
157 if (specializedDeclaration_) {
158 specializedDeclaration_->BindPipelineContext(pipelineContext_);
159 specializedDeclaration_->Init();
160 specializedDeclaration_->InitializeStyle();
161 }
162 }
163
PrepareTextField()164 void InputDeclaration::PrepareTextField()
165 {
166 auto textFieldDeclaration = AceType::DynamicCast<TextFieldDeclaration>(specializedDeclaration_);
167 if (!textFieldDeclaration) {
168 return;
169 }
170
171 // Init disable style.
172 if (!textFieldDeclaration->IsEnabled()) {
173 auto theme = GetTheme<TextFieldTheme>();
174 textFieldDeclaration->SetTextColor(theme->GetDisableTextColor());
175 textFieldDeclaration->SetPlaceholderColor(theme->GetDisableTextColor());
176 }
177
178 // Set height with height of box.
179 auto& sizeStyle = static_cast<CommonSizeStyle&>(GetStyle(StyleTag::COMMON_SIZE_STYLE));
180 if (sizeStyle.IsValid() && GreatOrEqual(sizeStyle.height.Value(), 0.0)) {
181 textFieldDeclaration->SetHeight(sizeStyle.height);
182 }
183 }
184
185 } // namespace OHOS::Ace
186