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