1 /*
2 * Copyright (c) 2022-2023 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_ng/pattern/search/search_layout_algorithm.h"
17 #include "core/components_ng/pattern/search/search_pattern.h"
18
19 #include <algorithm>
20
21 #include "base/utils/utils.h"
22 #include "core/common/ace_application_info.h"
23 #include "core/components/common/layout/constants.h"
24 #include "core/components_ng/layout/layout_algorithm.h"
25 #include "core/components_ng/pattern/button/button_layout_property.h"
26 #include "core/components_ng/pattern/button/button_pattern.h"
27 #include "core/components_ng/pattern/image/image_layout_property.h"
28 #include "core/components_ng/pattern/image/image_pattern.h"
29 #include "core/components_ng/pattern/text/text_layout_property.h"
30 #include "core/components_ng/pattern/text_field/text_field_layout_algorithm.h"
31 #include "core/components_ng/property/layout_constraint.h"
32 #include "core/components_ng/property/measure_utils.h"
33 #include "core/pipeline_ng/pipeline_context.h"
34
35 namespace OHOS::Ace::NG {
36 namespace {
37 constexpr int32_t TEXTFIELD_INDEX = 0;
38 constexpr int32_t IMAGE_INDEX = 1;
39 constexpr int32_t CANCEL_IMAGE_INDEX = 2;
40 constexpr int32_t CANCEL_BUTTON_INDEX = 3;
41 constexpr int32_t BUTTON_INDEX = 4;
42 constexpr int32_t DIVIDER_INDEX = 5;
43 constexpr int32_t MULTIPLE_2 = 2;
44 constexpr float MAX_SEARCH_BUTTON_RATE = 0.4f;
45 constexpr float AGING_MIN_SCALE = 1.75f;
46 constexpr float MAX_FONT_SCALE = 2.0f;
47 constexpr int TWO = 2;
48 } // namespace
49
IsFixedHeightMode(LayoutWrapper * layoutWrapper)50 bool SearchLayoutAlgorithm::IsFixedHeightMode(LayoutWrapper* layoutWrapper)
51 {
52 auto layoutProperty = AceType::DynamicCast<SearchLayoutProperty>(layoutWrapper->GetLayoutProperty());
53 CHECK_NULL_RETURN(layoutProperty, false);
54
55 auto constraint = layoutProperty->GetLayoutConstraint();
56 return constraint->selfIdealSize.Height().has_value();
57 }
58
CancelImageMeasure(LayoutWrapper * layoutWrapper)59 void SearchLayoutAlgorithm::CancelImageMeasure(LayoutWrapper* layoutWrapper)
60 {
61 auto layoutProperty = AceType::DynamicCast<SearchLayoutProperty>(layoutWrapper->GetLayoutProperty());
62 CHECK_NULL_VOID(layoutProperty);
63 auto cancelImageWrapper = layoutWrapper->GetOrCreateChildByIndex(CANCEL_IMAGE_INDEX);
64 CHECK_NULL_VOID(cancelImageWrapper);
65 auto cancelImageGeometryNode = cancelImageWrapper->GetGeometryNode();
66 CHECK_NULL_VOID(cancelImageGeometryNode);
67 auto imageLayoutProperty = cancelImageWrapper->GetLayoutProperty();
68 CHECK_NULL_VOID(imageLayoutProperty);
69 auto searchHost = layoutWrapper->GetHostNode();
70 CHECK_NULL_VOID(searchHost);
71 auto pipeline = searchHost->GetContext();
72 CHECK_NULL_VOID(pipeline);
73 auto searchTheme = pipeline->GetTheme<SearchTheme>();
74 CHECK_NULL_VOID(searchTheme);
75 auto constraint = layoutProperty->GetLayoutConstraint();
76 auto searchHeight = CalcSearchHeight(constraint.value(), layoutWrapper);
77 auto defaultImageHeight = static_cast<float>(searchTheme->GetIconSize().ConvertToPx());
78 auto imageHeight = static_cast<float>(std::min(layoutProperty->HasCancelButtonUDSize() ?
79 layoutProperty->GetCancelButtonUDSizeValue().ConvertToPx() : defaultImageHeight,
80 searchHeight));
81 if (cancelImageWrapper->GetHostTag() == V2::SYMBOL_ETS_TAG) {
82 imageHeight = CalcSymbolIconHeight(layoutWrapper, CANCEL_IMAGE_INDEX, defaultImageHeight);
83 }
84 CalcSize imageCalcSize;
85 imageCalcSize.SetWidth(CalcLength(imageHeight));
86 imageCalcSize.SetHeight(CalcLength(imageHeight));
87 imageLayoutProperty->UpdateUserDefinedIdealSize(imageCalcSize);
88 auto childLayoutConstraint = layoutProperty->CreateChildConstraint();
89 cancelImageWrapper->Measure(childLayoutConstraint);
90 cancelIconSizeMeasure_ = cancelImageGeometryNode->GetFrameSize();
91 }
92
CancelButtonMeasure(LayoutWrapper * layoutWrapper)93 void SearchLayoutAlgorithm::CancelButtonMeasure(LayoutWrapper* layoutWrapper)
94 {
95 auto cancelButtonWrapper = layoutWrapper->GetOrCreateChildByIndex(CANCEL_BUTTON_INDEX);
96 CHECK_NULL_VOID(cancelButtonWrapper);
97 auto layoutProperty = AceType::DynamicCast<SearchLayoutProperty>(layoutWrapper->GetLayoutProperty());
98 CHECK_NULL_VOID(layoutProperty);
99 auto cancelButtonLayoutProperty =
100 AceType::DynamicCast<ButtonLayoutProperty>(cancelButtonWrapper->GetLayoutProperty());
101 CHECK_NULL_VOID(cancelButtonLayoutProperty);
102 auto cancelButtonGeometryNode = cancelButtonWrapper->GetGeometryNode();
103 CHECK_NULL_VOID(cancelButtonGeometryNode);
104 auto searchHost = layoutWrapper->GetHostNode();
105 CHECK_NULL_VOID(searchHost);
106 auto pipeline = searchHost->GetContext();
107 CHECK_NULL_VOID(pipeline);
108 auto searchTheme = pipeline->GetTheme<SearchTheme>();
109 CHECK_NULL_VOID(searchTheme);
110
111 // calculate theme space from cancel button to cancel image
112 auto spaceHeight = searchTheme->GetHeight().ConvertToPx() - 2 * searchTheme->GetSearchButtonSpace().ConvertToPx() -
113 searchTheme->GetIconHeight().ConvertToPx();
114
115 // calculate cancel button height
116 auto cancelButtonHeight =
117 layoutProperty->GetCancelButtonUDSizeValue(Dimension(cancelIconSizeMeasure_.Height())).ConvertToPx() +
118 spaceHeight;
119
120 // cancel button height should be less than searchHeight
121 auto constraint = layoutProperty->GetLayoutConstraint();
122 CHECK_NULL_VOID(constraint);
123 auto searchHeight = CalcSearchHeight(constraint.value(), layoutWrapper);
124 cancelButtonHeight = std::min(cancelButtonHeight, searchHeight);
125
126 CalcSize cancelButtonCalcSize((CalcLength(cancelButtonHeight)), CalcLength(cancelButtonHeight));
127 cancelButtonLayoutProperty->UpdateUserDefinedIdealSize(cancelButtonCalcSize);
128
129 auto childLayoutConstraint = layoutProperty->CreateChildConstraint();
130 cancelButtonWrapper->Measure(childLayoutConstraint);
131 cancelBtnSizeMeasure_ = cancelButtonGeometryNode->GetFrameSize();
132 }
133
TextFieldMeasure(LayoutWrapper * layoutWrapper)134 void SearchLayoutAlgorithm::TextFieldMeasure(LayoutWrapper* layoutWrapper)
135 {
136 auto searchHost = layoutWrapper->GetHostNode();
137 CHECK_NULL_VOID(searchHost);
138 auto pipeline = searchHost->GetContext();
139 CHECK_NULL_VOID(pipeline);
140 auto searchTheme = pipeline->GetTheme<SearchTheme>();
141 auto layoutProperty = AceType::DynamicCast<SearchLayoutProperty>(layoutWrapper->GetLayoutProperty());
142 CHECK_NULL_VOID(layoutProperty);
143 auto textFieldWrapper = layoutWrapper->GetOrCreateChildByIndex(TEXTFIELD_INDEX);
144 CHECK_NULL_VOID(textFieldWrapper);
145 auto cancelButtonWrapper = layoutWrapper->GetOrCreateChildByIndex(CANCEL_BUTTON_INDEX);
146 CHECK_NULL_VOID(cancelButtonWrapper);
147 auto textFieldGeometryNode = textFieldWrapper->GetGeometryNode();
148 CHECK_NULL_VOID(textFieldGeometryNode);
149
150 UpdateFontFeature(layoutWrapper);
151 auto buttonWidth = searchButtonSizeMeasure_.Width();
152 auto cancelButtonWidth = cancelBtnSizeMeasure_.Width();
153 auto iconRenderWidth =
154 layoutProperty->GetSearchIconUDSizeValue(Dimension(searchIconSizeMeasure_.Width())).ConvertToPx();
155 auto constraint = layoutProperty->GetLayoutConstraint();
156 auto searchWidthMax = CalcSearchWidth(constraint.value(), layoutWrapper);
157
158 auto searchWrapper = layoutWrapper->GetOrCreateChildByIndex(BUTTON_INDEX);
159 auto searchButtonNode = searchWrapper->GetHostNode();
160 auto searchButtonEvent = searchButtonNode->GetEventHub<ButtonEventHub>();
161 auto padding = layoutProperty->CreatePaddingAndBorder();
162 float leftPadding = padding.left.value_or(0.0f);
163 float rightPadding = padding.right.value_or(0.0f);
164 auto textFieldWidth = searchWidthMax - searchTheme->GetSearchIconLeftSpace().ConvertToPx() - iconRenderWidth -
165 searchTheme->GetSearchIconRightSpace().ConvertToPx() - leftPadding - rightPadding;
166 if (!AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TEN)) {
167 textFieldWidth = searchWidthMax - searchTheme->GetSearchIconLeftSpace().ConvertToPx() - iconRenderWidth -
168 searchTheme->GetSearchIconRightSpace().ConvertToPx();
169 }
170 if (searchButtonEvent->IsEnabled()) {
171 textFieldWidth = textFieldWidth - buttonWidth - searchTheme->GetSearchDividerWidth().ConvertToPx() -
172 MULTIPLE_2 * searchTheme->GetDividerSideSpace().ConvertToPx();
173 }
174
175 auto style = layoutProperty->GetCancelButtonStyle().value_or(CancelButtonStyle::INPUT);
176 if (style != CancelButtonStyle::INVISIBLE) {
177 textFieldWidth = textFieldWidth - cancelButtonWidth;
178 }
179 auto textFieldHeight = CalcSearchHeight(constraint.value(), layoutWrapper);
180 auto childLayoutConstraint = layoutProperty->CreateChildConstraint();
181 childLayoutConstraint.selfIdealSize.SetWidth(textFieldWidth);
182 if (LessNotEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
183 SetTextFieldLayoutConstraintHeight(childLayoutConstraint, textFieldHeight, layoutWrapper);
184 }
185 textFieldWrapper->Measure(childLayoutConstraint);
186 textFieldSizeMeasure_ = textFieldGeometryNode->GetFrameSize();
187 }
188
UpdateFontFeature(LayoutWrapper * layoutWrapper)189 void SearchLayoutAlgorithm::UpdateFontFeature(LayoutWrapper* layoutWrapper)
190 {
191 auto layoutProperty = AceType::DynamicCast<SearchLayoutProperty>(layoutWrapper->GetLayoutProperty());
192 CHECK_NULL_VOID(layoutProperty);
193 auto textFieldWrapper = layoutWrapper->GetOrCreateChildByIndex(TEXTFIELD_INDEX);
194 CHECK_NULL_VOID(textFieldWrapper);
195
196 auto textFieldLayoutProperty = AceType::DynamicCast<TextFieldLayoutProperty>(textFieldWrapper->GetLayoutProperty());
197 CHECK_NULL_VOID(textFieldLayoutProperty);
198 if (layoutProperty->HasFontFeature()) {
199 textFieldLayoutProperty->UpdateFontFeature(layoutProperty->GetFontFeature().value());
200 }
201 }
SetTextFieldLayoutConstraintHeight(LayoutConstraintF & contentConstraint,double textFieldHeight,LayoutWrapper * layoutWrapper)202 void SearchLayoutAlgorithm::SetTextFieldLayoutConstraintHeight(LayoutConstraintF& contentConstraint,
203 double textFieldHeight, LayoutWrapper* layoutWrapper)
204 {
205 if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
206 auto textFieldWrapper = layoutWrapper->GetOrCreateChildByIndex(TEXTFIELD_INDEX);
207 auto textFieldLayoutProperty =
208 AceType::DynamicCast<TextFieldLayoutProperty>(textFieldWrapper->GetLayoutProperty());
209 if ((textFieldLayoutProperty == nullptr) || (!textFieldLayoutProperty->HasLineHeight())) {
210 contentConstraint.selfIdealSize.SetHeight(textFieldHeight);
211 }
212 return;
213 }
214 contentConstraint.selfIdealSize.SetHeight(textFieldHeight);
215 }
216
ImageMeasure(LayoutWrapper * layoutWrapper)217 void SearchLayoutAlgorithm::ImageMeasure(LayoutWrapper* layoutWrapper)
218 {
219 auto layoutProperty = AceType::DynamicCast<SearchLayoutProperty>(layoutWrapper->GetLayoutProperty());
220 CHECK_NULL_VOID(layoutProperty);
221 auto imageWrapper = layoutWrapper->GetOrCreateChildByIndex(IMAGE_INDEX);
222 CHECK_NULL_VOID(imageWrapper);
223 auto imageGeometryNode = imageWrapper->GetGeometryNode();
224 CHECK_NULL_VOID(imageGeometryNode);
225 auto imageLayoutProperty = imageWrapper->GetLayoutProperty();
226 CHECK_NULL_VOID(imageLayoutProperty);
227 auto searchHost = layoutWrapper->GetHostNode();
228 CHECK_NULL_VOID(searchHost);
229 auto pipeline = searchHost->GetContext();
230 CHECK_NULL_VOID(pipeline);
231 auto searchTheme = pipeline->GetTheme<SearchTheme>();
232 CHECK_NULL_VOID(searchTheme);
233 auto constraint = layoutProperty->GetLayoutConstraint();
234 auto searchHeight = CalcSearchHeight(constraint.value(), layoutWrapper);
235 auto defaultImageHeight = searchTheme->GetIconSize().ConvertToPx();
236 auto imageHeight = static_cast<float>(std::min(layoutProperty->HasSearchIconUDSize() ?
237 layoutProperty->GetSearchIconUDSizeValue().ConvertToPx() : defaultImageHeight,
238 searchHeight));
239 if (imageWrapper->GetHostTag() == V2::SYMBOL_ETS_TAG) {
240 imageHeight = CalcSymbolIconHeight(layoutWrapper, IMAGE_INDEX, defaultImageHeight);
241 }
242 CalcSize imageCalcSize;
243 imageCalcSize.SetWidth(CalcLength(imageHeight));
244 imageCalcSize.SetHeight(CalcLength(imageHeight));
245 imageLayoutProperty->UpdateUserDefinedIdealSize(imageCalcSize);
246
247 auto childLayoutConstraint = layoutProperty->CreateChildConstraint();
248 imageWrapper->Measure(childLayoutConstraint);
249 searchIconSizeMeasure_ = imageGeometryNode->GetFrameSize();
250 }
251
SearchButtonMeasure(LayoutWrapper * layoutWrapper)252 void SearchLayoutAlgorithm::SearchButtonMeasure(LayoutWrapper* layoutWrapper)
253 {
254 auto buttonWrapper = layoutWrapper->GetOrCreateChildByIndex(BUTTON_INDEX);
255 CHECK_NULL_VOID(buttonWrapper);
256 auto buttonLayoutProperty = AceType::DynamicCast<ButtonLayoutProperty>(buttonWrapper->GetLayoutProperty());
257 CHECK_NULL_VOID(buttonLayoutProperty);
258 auto layoutProperty = AceType::DynamicCast<SearchLayoutProperty>(layoutWrapper->GetLayoutProperty());
259 CHECK_NULL_VOID(layoutProperty);
260 auto buttonGeometryNode = buttonWrapper->GetGeometryNode();
261 CHECK_NULL_VOID(buttonGeometryNode);
262 auto searchHost = layoutWrapper->GetHostNode();
263 CHECK_NULL_VOID(searchHost);
264 auto pipeline = searchHost->GetContext();
265 CHECK_NULL_VOID(pipeline);
266 auto searchTheme = pipeline->GetTheme<SearchTheme>();
267 CHECK_NULL_VOID(searchTheme);
268
269 // calculate theme space from search button to font
270 auto spaceHeight = searchTheme->GetHeight().ConvertToPx() - 2 * searchTheme->GetSearchButtonSpace().ConvertToPx() -
271 searchTheme->GetFontSize().ConvertToPx();
272
273 // calculate search button height
274 auto defaultButtonHeight =
275 searchTheme->GetHeight().ConvertToPx() - 2 * searchTheme->GetSearchButtonSpace().ConvertToPx();
276 auto searchButtonHeight = std::max(defaultButtonHeight,
277 layoutProperty->GetSearchButtonFontSizeValue(searchTheme->GetFontSize()).ConvertToPx() + spaceHeight);
278 auto constraint = layoutProperty->GetLayoutConstraint();
279 auto searchHeight = CalcSearchHeight(constraint.value(), layoutWrapper);
280 searchButtonHeight = std::min(searchButtonHeight, searchHeight - 0.0f);
281 CalcSize searchButtonCalcSize;
282 searchButtonCalcSize.SetHeight(CalcLength(searchButtonHeight));
283 buttonLayoutProperty->UpdateUserDefinedIdealSize(searchButtonCalcSize);
284
285 auto textWrapper = buttonWrapper->GetChildByIndex(0);
286 if (textWrapper) {
287 auto textLayoutProperty = AceType::DynamicCast<TextLayoutProperty>(textWrapper->GetLayoutProperty());
288 CHECK_NULL_VOID(textLayoutProperty);
289 textLayoutProperty->UpdateMaxFontScale(MAX_FONT_SCALE);
290 }
291 if (GreatOrEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
292 buttonLayoutProperty->ClearUserDefinedIdealSize(false, true);
293 }
294
295 // searchButton Measure
296 auto buttonLayoutConstraint = layoutProperty->CreateChildConstraint();
297 buttonWrapper->Measure(buttonLayoutConstraint);
298
299 // deal with pixel round
300 auto pixelRound = static_cast<uint16_t>(PixelRoundPolicy::FORCE_FLOOR_TOP) |
301 static_cast<uint16_t>(PixelRoundPolicy::FORCE_CEIL_BOTTOM);
302 buttonLayoutProperty->UpdatePixelRound(pixelRound);
303
304 // compute searchButton width
305 auto searchWidthMax = CalcSearchWidth(constraint.value(), layoutWrapper);
306 double searchButtonWidth = searchWidthMax * MAX_SEARCH_BUTTON_RATE;
307 double curSearchButtonWidth = buttonGeometryNode->GetFrameSize().Width();
308 searchButtonWidth = std::min(searchButtonWidth, curSearchButtonWidth);
309 buttonLayoutConstraint.selfIdealSize.SetWidth(searchButtonWidth);
310 buttonWrapper->Measure(buttonLayoutConstraint);
311 searchButtonSizeMeasure_ = buttonGeometryNode->GetFrameSize();
312 }
313
DividerMeasure(LayoutWrapper * layoutWrapper)314 void SearchLayoutAlgorithm::DividerMeasure(LayoutWrapper* layoutWrapper)
315 {
316 auto layoutProperty = AceType::DynamicCast<SearchLayoutProperty>(layoutWrapper->GetLayoutProperty());
317 CHECK_NULL_VOID(layoutProperty);
318 auto dividerWrapper = layoutWrapper->GetOrCreateChildByIndex(DIVIDER_INDEX);
319 CHECK_NULL_VOID(dividerWrapper);
320 auto dividerGeometryNode = dividerWrapper->GetGeometryNode();
321 CHECK_NULL_VOID(dividerGeometryNode);
322 auto dividerLayoutProperty = dividerWrapper->GetLayoutProperty();
323 CHECK_NULL_VOID(dividerLayoutProperty);
324 auto host = layoutWrapper->GetHostNode();
325 CHECK_NULL_VOID(host);
326 auto pipeline = host->GetContext();
327 CHECK_NULL_VOID(pipeline);
328 auto searchTheme = pipeline->GetTheme<SearchTheme>();
329 CHECK_NULL_VOID(searchTheme);
330
331 auto constraint = layoutProperty->GetLayoutConstraint();
332 auto iconHeight = searchTheme->GetIconHeight().ConvertToPx();
333 auto searchHeight = CalcSearchHeight(constraint.value(), layoutWrapper);
334 auto dividerHeight = std::min(static_cast<float>(searchHeight), static_cast<float>(iconHeight));
335 auto dividerWidth = searchTheme->GetSearchDividerWidth();
336
337 CalcSize dividerSize;
338 dividerSize.SetWidth(CalcLength(dividerWidth));
339 dividerSize.SetHeight(CalcLength(dividerHeight));
340 dividerLayoutProperty->UpdateUserDefinedIdealSize(dividerSize);
341
342 auto childLayoutConstraint = layoutProperty->CreateChildConstraint();
343 dividerWrapper->Measure(childLayoutConstraint);
344 dividerSizeMeasure_ = dividerGeometryNode->GetFrameSize();
345 }
346
CalcSearchAdaptHeight(LayoutWrapper * layoutWrapper)347 double SearchLayoutAlgorithm::CalcSearchAdaptHeight(LayoutWrapper* layoutWrapper)
348 {
349 double searchHeightAdapt = 0;
350 auto host = layoutWrapper->GetHostNode();
351 CHECK_NULL_RETURN(host, 0);
352 auto pipeline = host->GetContext();
353 CHECK_NULL_RETURN(pipeline, 0);
354 auto searchTheme = pipeline->GetTheme<SearchTheme>();
355 CHECK_NULL_RETURN(searchTheme, 0);
356 auto layoutProperty = AceType::DynamicCast<SearchLayoutProperty>(layoutWrapper->GetLayoutProperty());
357 CHECK_NULL_RETURN(layoutProperty, 0);
358 auto searchBtnWrapper = layoutWrapper->GetOrCreateChildByIndex(BUTTON_INDEX);
359 CHECK_NULL_RETURN(searchBtnWrapper, 0);
360 auto cancelBtnLayoutWrapper = layoutWrapper->GetOrCreateChildByIndex(CANCEL_BUTTON_INDEX);
361 CHECK_NULL_RETURN(cancelBtnLayoutWrapper, 0);
362
363 // search button height
364 auto buttonNode = searchBtnWrapper->GetHostNode();
365 CHECK_NULL_RETURN(buttonNode, true);
366 auto searchButtonEvent = buttonNode->GetEventHub<ButtonEventHub>();
367 CHECK_NULL_RETURN(searchButtonEvent, true);
368 auto searchButtonHeight = searchButtonSizeMeasure_.Height() + 2 * searchTheme->GetSearchButtonSpace().ConvertToPx();
369 searchButtonHeight = (!searchButtonEvent->IsEnabled()) ? 0.0f : searchButtonHeight;
370
371 // search icon height
372 auto searchIconFrameHight = searchIconSizeMeasure_.Height();
373 auto searchIconHeight = layoutProperty->GetSearchIconUDSizeValue(Dimension(searchIconFrameHight)).ConvertToPx();
374 searchIconHeight += searchTheme->GetHeight().ConvertToPx() - searchTheme->GetIconHeight().ConvertToPx();
375
376 // cancel button height
377 auto cancelButtonNode = cancelBtnLayoutWrapper->GetHostNode();
378 CHECK_NULL_RETURN(cancelButtonNode, 0);
379 auto cancelButtonEvent = cancelButtonNode->GetEventHub<ButtonEventHub>();
380 CHECK_NULL_RETURN(cancelButtonEvent, 0);
381 auto cancelBtnHight = cancelBtnSizeMeasure_.Height() + 2 * searchTheme->GetSearchButtonSpace().ConvertToPx();
382 cancelBtnHight = (!cancelButtonEvent->IsEnabled()) ? 0.0f : cancelBtnHight;
383
384 // textfield height
385 auto padding = layoutProperty->CreatePaddingAndBorder();
386 auto verticalPadding = padding.top.value_or(0.0f) + padding.bottom.value_or(0.0f);
387 auto textfieldHeight = textFieldSizeMeasure_.Height() + verticalPadding;
388
389 // calculate the highest
390 searchHeightAdapt = std::max(searchIconHeight, searchButtonHeight);
391 searchHeightAdapt = std::max(searchHeightAdapt, cancelBtnHight);
392 searchHeightAdapt = std::max(searchHeightAdapt, static_cast<double>(textfieldHeight));
393
394 return searchHeightAdapt;
395 }
396
SelfMeasure(LayoutWrapper * layoutWrapper)397 void SearchLayoutAlgorithm::SelfMeasure(LayoutWrapper* layoutWrapper)
398 {
399 auto geometryNode = layoutWrapper->GetGeometryNode();
400 CHECK_NULL_VOID(geometryNode);
401 auto layoutProperty = AceType::DynamicCast<SearchLayoutProperty>(layoutWrapper->GetLayoutProperty());
402 CHECK_NULL_VOID(layoutProperty);
403 auto constraint = layoutProperty->GetLayoutConstraint();
404 auto searchHeight = CalcSearchHeight(constraint.value(), layoutWrapper);
405 UpdateClipBounds(layoutWrapper, searchHeight);
406 // update search height
407 constraint->selfIdealSize.SetHeight(searchHeight);
408 auto searchWidth = CalcSearchWidth(constraint.value(), layoutWrapper);
409 SizeF idealSize(searchWidth, searchHeight);
410 if (GreaterOrEqualToInfinity(idealSize.Width()) || GreaterOrEqualToInfinity(idealSize.Height())) {
411 geometryNode->SetFrameSize(SizeF());
412 return;
413 }
414
415 // update search height
416 geometryNode->SetFrameSize(idealSize);
417 geometryNode->SetContentSize(idealSize);
418 }
419
CalcSearchWidth(const LayoutConstraintF & contentConstraint,LayoutWrapper * layoutWrapper)420 double SearchLayoutAlgorithm::CalcSearchWidth(
421 const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper)
422 {
423 auto searchConstraint = contentConstraint;
424 auto idealWidth = contentConstraint.selfIdealSize.Width().value_or(contentConstraint.maxSize.Width());
425 auto idealHeight = contentConstraint.selfIdealSize.Height().value_or(contentConstraint.maxSize.Height());
426 auto maxIdealSize = SizeF { idealWidth, idealHeight };
427 if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
428 auto frameIdealSize = maxIdealSize;
429 auto finalSize = UpdateOptionSizeByCalcLayoutConstraint(static_cast<OptionalSize<float>>(frameIdealSize),
430 layoutWrapper->GetLayoutProperty()->GetCalcLayoutConstraint(),
431 layoutWrapper->GetLayoutProperty()->GetLayoutConstraint()->percentReference);
432 finalSize.SetWidth(finalSize.Width().value_or(frameIdealSize.Width()));
433 finalSize.SetHeight(finalSize.Height().value_or(frameIdealSize.Height()));
434 maxIdealSize.UpdateSizeWhenSmaller(finalSize.ConvertToSizeT());
435 }
436 searchConstraint.maxSize = maxIdealSize;
437 auto searchWidth = (searchConstraint.selfIdealSize.Width().has_value())
438 ? std::min(searchConstraint.selfIdealSize.Width().value(), searchConstraint.maxSize.Width())
439 : std::min(searchConstraint.percentReference.Width(), searchConstraint.maxSize.Width());
440
441 const auto& calcLayoutConstraint = layoutWrapper->GetLayoutProperty()->GetCalcLayoutConstraint();
442 CHECK_NULL_RETURN(calcLayoutConstraint, searchWidth);
443 auto hasMinSize = calcLayoutConstraint->minSize->Width().has_value();
444 auto hasMaxSize = calcLayoutConstraint->maxSize->Width().has_value();
445 auto hasWidth = calcLayoutConstraint->selfIdealSize->Width().has_value();
446 if (hasMinSize && ((hasMaxSize && searchConstraint.minSize.Width() >= searchConstraint.maxSize.Width())
447 || (!hasMaxSize && !hasWidth))) {
448 return searchConstraint.minSize.Width();
449 }
450 if (hasMinSize) {
451 searchWidth = std::max(searchConstraint.minSize.Width(), static_cast<float>(searchWidth));
452 }
453 if (hasMaxSize) {
454 searchWidth = std::min(searchConstraint.maxSize.Width(), static_cast<float>(searchWidth));
455 }
456 return searchWidth;
457 }
458
CalcSearchHeight(const LayoutConstraintF & constraint,LayoutWrapper * layoutWrapper)459 double SearchLayoutAlgorithm::CalcSearchHeight(
460 const LayoutConstraintF& constraint, LayoutWrapper* layoutWrapper)
461 {
462 auto layoutProperty = AceType::DynamicCast<SearchLayoutProperty>(layoutWrapper->GetLayoutProperty());
463 CHECK_NULL_RETURN(layoutProperty, 0.0);
464 auto host = layoutWrapper->GetHostNode();
465 CHECK_NULL_RETURN(host, 0.0);
466 auto pipeline = host->GetContext();
467 CHECK_NULL_RETURN(pipeline, 0.0);
468 auto renderContext = host->GetRenderContext();
469 CHECK_NULL_RETURN(renderContext, 0.0);
470 auto searchTheme = pipeline->GetTheme<SearchTheme>();
471 CHECK_NULL_RETURN(searchTheme, 0.0);
472 auto themeHeight = searchTheme->GetHeight().ConvertToPx();
473 auto searchHeight =
474 (constraint.selfIdealSize.Height().has_value()) ? constraint.selfIdealSize.Height().value() : themeHeight;
475 auto padding = layoutProperty->CreatePaddingAndBorder();
476 auto verticalPadding = padding.top.value_or(0.0f) + padding.bottom.value_or(0.0f);
477 searchHeight = std::max(verticalPadding, static_cast<float>(searchHeight));
478 auto searchHeightAdapt = searchHeight;
479 if (!IsFixedHeightMode(layoutWrapper)) {
480 searchHeightAdapt = std::max(searchHeightAdapt, CalcSearchAdaptHeight(layoutWrapper));
481 renderContext->SetClipToBounds(false);
482 } else {
483 renderContext->SetClipToBounds(true);
484 }
485
486 const auto& calcLayoutConstraint = layoutWrapper->GetLayoutProperty()->GetCalcLayoutConstraint();
487 CHECK_NULL_RETURN(calcLayoutConstraint, searchHeightAdapt);
488 auto hasMinSize = calcLayoutConstraint->minSize.has_value() &&
489 calcLayoutConstraint->minSize->Height().has_value();
490 auto hasMaxSize = calcLayoutConstraint->maxSize.has_value() &&
491 calcLayoutConstraint->maxSize->Height().has_value();
492 auto hasHeight = calcLayoutConstraint->selfIdealSize.has_value() &&
493 calcLayoutConstraint->selfIdealSize->Height().has_value();
494 if (hasMinSize && ((hasMaxSize && constraint.minSize.Height() >= constraint.maxSize.Height())
495 || (!hasMaxSize && !hasHeight))) {
496 return constraint.minSize.Height();
497 }
498 if (hasMinSize) {
499 searchHeightAdapt = std::max(constraint.minSize.Height(),
500 static_cast<float>(searchHeightAdapt));
501 }
502 if (hasMaxSize) {
503 searchHeightAdapt = std::min(constraint.maxSize.Height(),
504 static_cast<float>(searchHeightAdapt));
505 }
506 return searchHeightAdapt;
507 }
508
Measure(LayoutWrapper * layoutWrapper)509 void SearchLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper)
510 {
511 auto host = layoutWrapper->GetHostNode();
512 CHECK_NULL_VOID(host);
513 auto children = host->GetChildren();
514 if (children.empty()) {
515 return;
516 }
517
518 SearchButtonMeasure(layoutWrapper);
519 DividerMeasure(layoutWrapper);
520 ImageMeasure(layoutWrapper);
521 CancelImageMeasure(layoutWrapper);
522 CancelButtonMeasure(layoutWrapper);
523 TextFieldMeasure(layoutWrapper);
524 SelfMeasure(layoutWrapper);
525 }
526
CalcChildrenHotZone(LayoutWrapper * layoutWrapper)527 void SearchLayoutAlgorithm::CalcChildrenHotZone(LayoutWrapper* layoutWrapper)
528 {
529 // search info
530 auto searchGeometryNode = layoutWrapper->GetGeometryNode();
531 CHECK_NULL_VOID(searchGeometryNode);
532 auto searchHeight = searchGeometryNode->GetFrameSize().Height();
533
534 // cancel button info
535 auto cancelButtonWrapper = layoutWrapper->GetOrCreateChildByIndex(CANCEL_BUTTON_INDEX);
536 CHECK_NULL_VOID(cancelButtonWrapper);
537 auto cancelButtonFrameNode = cancelButtonWrapper->GetHostNode();
538 CHECK_NULL_VOID(cancelButtonFrameNode);
539 auto cancelButtonGeometryNode = cancelButtonWrapper->GetGeometryNode();
540 CHECK_NULL_VOID(cancelButtonGeometryNode);
541 auto cancelButtonFrameSize = cancelButtonGeometryNode->GetFrameSize();
542 auto cancelButtonWidth = cancelButtonFrameSize.Width();
543 auto cancelButtonHeight = cancelButtonFrameSize.Height();
544
545 // search button info
546 auto searchButtonWrapper = layoutWrapper->GetOrCreateChildByIndex(BUTTON_INDEX);
547 CHECK_NULL_VOID(searchButtonWrapper);
548 auto searchButtonFrameNode = searchButtonWrapper->GetHostNode();
549 CHECK_NULL_VOID(searchButtonFrameNode);
550 auto searchButtonGeometryNode = searchButtonWrapper->GetGeometryNode();
551 CHECK_NULL_VOID(searchButtonGeometryNode);
552 auto searchButtonFrameSize = searchButtonGeometryNode->GetFrameSize();
553 auto searchButtonWidth = searchButtonFrameSize.Width();
554 auto searchButtonHeight = searchButtonFrameSize.Height();
555
556 auto pipeline = searchButtonFrameNode->GetContext();
557 CHECK_NULL_VOID(pipeline);
558 auto searchTheme = pipeline->GetTheme<SearchTheme>();
559 auto buttonSpace = searchTheme->GetSearchButtonSpace().ConvertToPx();
560 // calculate cancel button hot zone
561 cancelButtonFrameNode->RemoveLastHotZoneRect();
562 DimensionRect cancelButtonHotZone;
563 if (cancelButtonHeight > searchHeight) {
564 cancelButtonHotZone.SetSize(DimensionSize(Dimension(cancelButtonWidth), Dimension(searchHeight)));
565 double hotZoneOffsetY = (cancelButtonHeight - searchHeight) / 2;
566 cancelButtonHotZone.SetOffset(DimensionOffset(Dimension(0), Dimension(hotZoneOffsetY)));
567 } else {
568 cancelButtonHotZone.SetSize(DimensionSize(
569 Dimension(cancelButtonWidth + 2 * buttonSpace), Dimension(cancelButtonHeight + 2 * buttonSpace)));
570 cancelButtonHotZone.SetOffset(
571 DimensionOffset(Offset(static_cast<float>(-buttonSpace), static_cast<float>(-buttonSpace))));
572 }
573 cancelButtonFrameNode->AddHotZoneRect(cancelButtonHotZone);
574
575 // calculate search button hot zone
576 searchButtonFrameNode->RemoveLastHotZoneRect();
577 DimensionRect searchButtonHotZone;
578 if (searchButtonHeight > searchHeight) {
579 searchButtonHotZone.SetSize(DimensionSize(Dimension(searchButtonWidth), Dimension(searchHeight)));
580 double hotZoneOffsetY = (searchButtonHeight - searchHeight) / 2;
581 searchButtonHotZone.SetOffset(DimensionOffset(Dimension(0), Dimension(hotZoneOffsetY)));
582 } else {
583 searchButtonHotZone.SetSize(DimensionSize(
584 Dimension(searchButtonWidth + 2 * buttonSpace), Dimension(searchButtonHeight + 2 * buttonSpace)));
585 searchButtonHotZone.SetOffset(
586 DimensionOffset(Offset(static_cast<float>(-buttonSpace), static_cast<float>(-buttonSpace))));
587 }
588 searchButtonFrameNode->AddHotZoneRect(searchButtonHotZone);
589 }
590
Layout(LayoutWrapper * layoutWrapper)591 void SearchLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper)
592 {
593 auto host = layoutWrapper->GetHostNode();
594 CHECK_NULL_VOID(host);
595 auto children = host->GetChildren();
596 if (children.empty()) {
597 return;
598 }
599
600 auto layoutProperty = DynamicCast<SearchLayoutProperty>(layoutWrapper->GetLayoutProperty());
601 CHECK_NULL_VOID(layoutProperty);
602 auto isRTL = layoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
603
604
605 auto pipeline = host->GetContext();
606 CHECK_NULL_VOID(pipeline);
607 auto searchTheme = pipeline->GetTheme<SearchTheme>();
608
609 auto geometryNode = layoutWrapper->GetGeometryNode();
610 CHECK_NULL_VOID(geometryNode);
611 auto searchSize = geometryNode->GetFrameSize();
612 auto searchFrameWidth = searchSize.Width();
613 auto searchFrameHeight = searchSize.Height();
614
615 LayoutSearchParams params = {
616 .layoutWrapper = layoutWrapper,
617 .layoutProperty = layoutProperty,
618 .searchTheme = searchTheme,
619 .searchFrameWidth = searchFrameWidth,
620 .searchFrameHeight = searchFrameHeight,
621 .isRTL = isRTL
622 };
623 LayoutSearchIcon(params);
624 LayoutSearchButton(params);
625 LayoutDivider(params);
626 LayoutCancelButton(params);
627 LayoutCancelImage(params);
628 LayoutTextField(params);
629
630 CalcChildrenHotZone(layoutWrapper);
631 }
632
LayoutSearchIcon(const LayoutSearchParams & params)633 void SearchLayoutAlgorithm::LayoutSearchIcon(const LayoutSearchParams& params)
634 {
635 auto searchIconLeftSpace = params.searchTheme->GetSearchIconLeftSpace().ConvertToPx();
636 auto imageWrapper = params.layoutWrapper->GetOrCreateChildByIndex(IMAGE_INDEX);
637 CHECK_NULL_VOID(imageWrapper);
638 auto imageGeometryNode = imageWrapper->GetGeometryNode();
639 CHECK_NULL_VOID(imageGeometryNode);
640 auto iconFrameWidth = searchIconSizeMeasure_.Width();
641 auto iconFrameHeight = searchIconSizeMeasure_.Height();
642 auto layoutProperty = params.layoutProperty;
643 auto iconRenderWidth = layoutProperty->GetSearchIconUDSizeValue(Dimension(iconFrameWidth)).ConvertToPx();
644
645 auto padding = layoutProperty->CreatePaddingAndBorder();
646 float topPadding = padding.top.value_or(0.0f);
647 auto bottomPadding = padding.bottom.value_or(0.0f);
648 auto leftOffset = padding.left.value_or(0.0f);
649 auto rightOffset = padding.right.value_or(0.0f);
650 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
651 leftOffset = 0.0f;
652 }
653 float iconHorizontalOffset = params.isRTL ?
654 params.searchFrameWidth - searchIconLeftSpace - iconRenderWidth - rightOffset :
655 leftOffset + searchIconLeftSpace + (iconRenderWidth - iconFrameWidth) / 2.0f;
656
657 auto searchIconConstraint = imageWrapper->GetLayoutProperty()->GetLayoutConstraint();
658 auto iconUserHeight =
659 searchIconConstraint->selfIdealSize.Height().value_or(params.searchTheme->GetIconHeight().ConvertToPx());
660 float imageVerticalOffset = topPadding;
661 if (NearEqual(iconUserHeight, iconFrameHeight)) {
662 float iconInterval = (params.searchFrameHeight - iconUserHeight) / 2;
663 if (topPadding <= iconInterval && bottomPadding <= iconInterval) {
664 imageVerticalOffset = iconInterval;
665 } else if (topPadding <= iconInterval && bottomPadding > iconInterval) {
666 imageVerticalOffset = params.searchFrameHeight - (bottomPadding + iconFrameHeight);
667 }
668 }
669 OffsetF imageOffset(iconHorizontalOffset, imageVerticalOffset);
670 imageGeometryNode->SetMarginFrameOffset(imageOffset);
671 imageWrapper->Layout();
672 }
673
LayoutSearchButton(const LayoutSearchParams & params)674 void SearchLayoutAlgorithm::LayoutSearchButton(const LayoutSearchParams& params)
675 {
676 auto searchButtonSpace = params.searchTheme->GetSearchButtonSpace().ConvertToPx();
677
678 auto searchButtonWrapper = params.layoutWrapper->GetOrCreateChildByIndex(BUTTON_INDEX);
679 CHECK_NULL_VOID(searchButtonWrapper);
680 auto searchButtonGeometryNode = searchButtonWrapper->GetGeometryNode();
681 CHECK_NULL_VOID(searchButtonGeometryNode);
682 auto searchButtonFrameSize = searchButtonGeometryNode->GetFrameSize();
683 float searchButtonVerticalOffset = (params.searchFrameHeight - searchButtonFrameSize.Height()) / TWO;
684
685 auto padding = params.layoutProperty->CreatePaddingAndBorder();
686 auto leftOffset = padding.left.value_or(0.0f);
687 auto rightOffset = padding.right.value_or(0.0f);
688 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
689 rightOffset = 0.0f;
690 }
691 float searchButtonHorizontalOffset = 0.0f;
692 if (params.isRTL) {
693 searchButtonHorizontalOffset = leftOffset + searchButtonSpace;
694 } else {
695 searchButtonHorizontalOffset =
696 params.searchFrameWidth - searchButtonFrameSize.Width() - searchButtonSpace - rightOffset;
697 searchButtonHorizontalOffset = std::max(searchButtonHorizontalOffset, 0.0f);
698 }
699 auto searchButtonOffset = OffsetF(searchButtonHorizontalOffset, searchButtonVerticalOffset);
700 searchButtonGeometryNode->SetMarginFrameOffset(searchButtonOffset);
701 searchButtonWrapper->Layout();
702 }
703
LayoutDivider(const LayoutSearchParams & params)704 void SearchLayoutAlgorithm::LayoutDivider(const LayoutSearchParams& params)
705 {
706 auto searchButtonSpace = params.searchTheme->GetSearchButtonSpace().ConvertToPx();
707 auto dividerSpace = params.searchTheme->GetDividerSideSpace().ConvertToPx();
708
709 auto dividerWrapper = params.layoutWrapper->GetOrCreateChildByIndex(DIVIDER_INDEX);
710 CHECK_NULL_VOID(dividerWrapper);
711 auto dividerGeometryNode = dividerWrapper->GetGeometryNode();
712 CHECK_NULL_VOID(dividerGeometryNode);
713 auto dividerFrameSize = dividerGeometryNode->GetFrameSize();
714
715 auto padding = params.layoutProperty->CreatePaddingAndBorder();
716 auto leftOffset = padding.left.value_or(0.0f);
717 auto rightOffset = padding.right.value_or(0.0f);
718 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
719 rightOffset = 0.0f;
720 }
721 auto buttonWidth = searchButtonSizeMeasure_.Width();
722
723 float dividerHorizontalOffset = 0.0f;
724 if (params.isRTL) {
725 dividerHorizontalOffset =
726 leftOffset + buttonWidth + dividerSpace + searchButtonSpace + dividerFrameSize.Width() / 2.0f;
727 } else {
728 dividerHorizontalOffset = params.searchFrameWidth - buttonWidth - dividerSpace - searchButtonSpace -
729 dividerFrameSize.Width() / 2.0f - rightOffset;
730 }
731 dividerHorizontalOffset = std::max(dividerHorizontalOffset, 0.0f);
732 auto dividerVerticalOffset = (params.searchFrameHeight - dividerFrameSize.Height()) / 2.0f;
733 auto dividerOffset = OffsetF(dividerHorizontalOffset, dividerVerticalOffset);
734 dividerGeometryNode->SetMarginFrameOffset(dividerOffset);
735 dividerWrapper->Layout();
736 }
737
738
LayoutCancelButton(const LayoutSearchParams & params)739 void SearchLayoutAlgorithm::LayoutCancelButton(const LayoutSearchParams& params)
740 {
741 auto dividerSideSpace = params.searchTheme->GetDividerSideSpace().ConvertToPx();
742 auto dividerWidth = params.searchTheme->GetSearchDividerWidth().ConvertToPx();
743
744 auto cancelButtonWrapper = params.layoutWrapper->GetOrCreateChildByIndex(CANCEL_BUTTON_INDEX);
745 CHECK_NULL_VOID(cancelButtonWrapper);
746 auto cancelButtonGeometryNode = cancelButtonWrapper->GetGeometryNode();
747 CHECK_NULL_VOID(cancelButtonGeometryNode);
748 auto cancelButtonFrameSize = cancelButtonGeometryNode->GetFrameSize();
749 auto cancelButtonFrameWidth = cancelButtonFrameSize.Width();
750 auto cancelButtonFrameHeight = cancelButtonFrameSize.Height();
751
752 auto searchButtonWrapper = params.layoutWrapper->GetOrCreateChildByIndex(BUTTON_INDEX);
753 CHECK_NULL_VOID(searchButtonWrapper);
754 auto searchButtonGeometryNode = searchButtonWrapper->GetGeometryNode();
755 CHECK_NULL_VOID(searchButtonGeometryNode);
756 auto searchButtonFrameSize = searchButtonGeometryNode->GetFrameSize();
757 auto searchButtonHorizontalOffset = searchButtonGeometryNode->GetMarginFrameOffset().GetX();
758
759 auto cancelButtonHorizontalOffset = 0;
760 auto cancelButtonVerticalOffset = (params.searchFrameHeight - cancelButtonFrameHeight) / 2;
761 auto searchButtonNode = searchButtonWrapper->GetHostNode();
762 auto searchButtonEvent = searchButtonNode->GetEventHub<ButtonEventHub>();
763 auto buttonSpace = params.searchTheme->GetSearchButtonSpace().ConvertToPx();
764 if (params.isRTL) {
765 if (searchButtonEvent->IsEnabled()) {
766 cancelButtonHorizontalOffset =
767 searchButtonHorizontalOffset + (searchButtonFrameSize.Width() + TWO * dividerSideSpace + dividerWidth);
768 } else {
769 cancelButtonHorizontalOffset = searchButtonHorizontalOffset;
770 }
771 } else {
772 if (searchButtonEvent->IsEnabled()) {
773 auto cancelButtonOffsetToSearchButton = cancelButtonFrameWidth + 2 * dividerSideSpace + dividerWidth;
774 cancelButtonHorizontalOffset =
775 std::max(searchButtonHorizontalOffset - cancelButtonOffsetToSearchButton, 0.0);
776 } else {
777 cancelButtonHorizontalOffset = params.searchFrameWidth - cancelButtonFrameWidth - buttonSpace;
778 }
779 }
780 auto cancelButtonOffset = OffsetF(cancelButtonHorizontalOffset, cancelButtonVerticalOffset);
781 cancelButtonGeometryNode->SetMarginFrameOffset(cancelButtonOffset);
782 cancelButtonWrapper->Layout();
783 }
784
LayoutCancelImage(const LayoutSearchParams & params)785 void SearchLayoutAlgorithm::LayoutCancelImage(const LayoutSearchParams& params)
786 {
787 auto cancelImageWrapper = params.layoutWrapper->GetOrCreateChildByIndex(CANCEL_IMAGE_INDEX);
788 CHECK_NULL_VOID(cancelImageWrapper);
789 auto cancelImageGeometryNode = cancelImageWrapper->GetGeometryNode();
790 CHECK_NULL_VOID(cancelImageGeometryNode);
791 auto cancelImageFrameSize = cancelImageGeometryNode->GetFrameSize();
792 auto cancelImageFrameWidth = cancelImageFrameSize.Width();
793 auto cancelImageFrameHeight = cancelImageFrameSize.Height();
794
795 auto cancelButtonWrapper = params.layoutWrapper->GetOrCreateChildByIndex(CANCEL_BUTTON_INDEX);
796 CHECK_NULL_VOID(cancelButtonWrapper);
797 auto cancelButtonGeometryNode = cancelButtonWrapper->GetGeometryNode();
798 CHECK_NULL_VOID(cancelButtonGeometryNode);
799 auto cancelButtonHorizontalOffset = cancelButtonGeometryNode->GetMarginFrameOffset().GetX();
800 auto cancelButtonFrameWidth = cancelButtonGeometryNode->GetFrameSize().Width();
801
802 auto cancelImageVerticalOffset = (params.searchFrameHeight - cancelImageFrameHeight) / 2;
803 auto cancelButtonImageCenterOffset = (cancelButtonFrameWidth - cancelImageFrameWidth) / 2;
804 auto cancelImageHorizontalOffset = cancelButtonHorizontalOffset + cancelButtonImageCenterOffset;
805 auto cancelImageOffset = OffsetF(cancelImageHorizontalOffset, cancelImageVerticalOffset);
806 cancelImageGeometryNode->SetMarginFrameOffset(cancelImageOffset);
807 cancelImageWrapper->Layout();
808 }
809
LayoutTextField(const LayoutSearchParams & params)810 void SearchLayoutAlgorithm::LayoutTextField(const LayoutSearchParams& params)
811 {
812 auto searchIconLeftSpace = params.searchTheme->GetSearchIconLeftSpace().ConvertToPx();
813 auto searchIconRightSpace = params.searchTheme->GetSearchIconRightSpace().ConvertToPx();
814 auto searchIconWidth = searchIconSizeMeasure_.Width();
815 auto layoutProperty = DynamicCast<SearchLayoutProperty>(params.layoutWrapper->GetLayoutProperty());
816 CHECK_NULL_VOID(layoutProperty);
817 auto padding = layoutProperty->CreatePaddingAndBorder();
818
819 auto textFieldWrapper = params.layoutWrapper->GetOrCreateChildByIndex(TEXTFIELD_INDEX);
820 CHECK_NULL_VOID(textFieldWrapper);
821 auto textFieldGeometryNode = textFieldWrapper->GetGeometryNode();
822 CHECK_NULL_VOID(textFieldGeometryNode);
823
824 auto hostGeometryNode = params.layoutWrapper->GetGeometryNode();
825 CHECK_NULL_VOID(hostGeometryNode);
826
827 auto textFieldHorizontalOffset = 0;
828 if (params.isRTL) {
829 auto rightOffset = searchIconWidth + searchIconLeftSpace
830 + searchIconRightSpace + padding.right.value_or(0.0f);
831 textFieldHorizontalOffset = hostGeometryNode->GetFrameSize().Width()
832 - rightOffset - textFieldGeometryNode->GetFrameSize().Width();
833 } else {
834 textFieldHorizontalOffset = searchIconWidth + searchIconLeftSpace
835 + searchIconRightSpace + padding.left.value_or(0.0f);
836 }
837
838 auto textFieldVerticalOffset = (params.searchFrameHeight - textFieldGeometryNode->GetFrameSize().Height()) / 2;
839 textFieldGeometryNode->SetMarginFrameOffset(OffsetF(textFieldHorizontalOffset, textFieldVerticalOffset));
840 textFieldWrapper->Layout();
841 }
842
UpdateClipBounds(LayoutWrapper * layoutWrapper,float height)843 void SearchLayoutAlgorithm::UpdateClipBounds(LayoutWrapper* layoutWrapper, float height)
844 {
845 if (!IsFixedHeightMode(layoutWrapper)) {
846 return;
847 }
848 auto host = layoutWrapper->GetHostNode();
849 CHECK_NULL_VOID(host);
850 auto renderContext = host->GetRenderContext();
851 CHECK_NULL_VOID(renderContext);
852 auto layoutProperty = AceType::DynamicCast<SearchLayoutProperty>(layoutWrapper->GetLayoutProperty());
853 CHECK_NULL_VOID(layoutProperty);
854 if (!layoutProperty->HasSearchIconUDSize() && !layoutProperty->HasCancelButtonUDSize()) {
855 auto pipeline = host->GetContext();
856 CHECK_NULL_VOID(pipeline);
857 auto searchTheme = pipeline->GetTheme<SearchTheme>();
858 CHECK_NULL_VOID(searchTheme);
859 auto defaultImageHeight = searchTheme->GetIconSize().ConvertToPx();
860 auto isClip = LessNotEqual(height, defaultImageHeight);
861 renderContext->SetClipToBounds(isClip);
862 return;
863 }
864 auto isClip = false;
865 if (layoutProperty->HasSearchIconUDSize()) {
866 isClip = isClip || LessNotEqual(height, layoutProperty->GetSearchIconUDSizeValue().ConvertToPx());
867 }
868 if (layoutProperty->HasCancelButtonUDSize()) {
869 isClip = isClip || LessNotEqual(height, layoutProperty->GetCancelButtonUDSizeValue().ConvertToPx());
870 }
871 renderContext->SetClipToBounds(isClip);
872 }
CalcSymbolIconHeight(LayoutWrapper * layoutWrapper,int32_t index,double defaultImageHeight)873 double SearchLayoutAlgorithm::CalcSymbolIconHeight(
874 LayoutWrapper* layoutWrapper, int32_t index, double defaultImageHeight)
875 {
876 auto hostNode = layoutWrapper->GetHostNode();
877 CHECK_NULL_RETURN(hostNode, defaultImageHeight);
878 auto pipeline = hostNode->GetContext();
879 CHECK_NULL_RETURN(pipeline, defaultImageHeight);
880 auto searchPattern = hostNode->GetPattern<SearchPattern>();
881 CHECK_NULL_RETURN(searchPattern, defaultImageHeight);
882 auto searchNode = searchPattern->GetSearchNode();
883 CHECK_NULL_RETURN(searchNode, defaultImageHeight);
884
885 auto iconNode = AceType::DynamicCast<FrameNode>(hostNode->GetChildAtIndex(index));
886 CHECK_NULL_RETURN(iconNode, defaultImageHeight);
887 auto symbolLayoutProperty = iconNode->GetLayoutProperty<TextLayoutProperty>();
888 CHECK_NULL_RETURN(symbolLayoutProperty, defaultImageHeight);
889
890 auto defaultSymbolIconSize =
891 (index == IMAGE_INDEX ? searchNode->GetSearchSymbolIconSize() : searchNode->GetCancelSymbolIconSize());
892 auto iconSize = symbolLayoutProperty->GetFontSize().value_or(defaultSymbolIconSize);
893 if (iconSize.Unit() == DimensionUnit::FP) {
894 float maxFontScale = std::min(pipeline->GetMaxAppFontScale(), MAX_FONT_SCALE);
895 return iconSize.ConvertToPxDistribute(0, maxFontScale);
896 }
897 return iconSize.ConvertToPx();
898 }
899 } // namespace OHOS::Ace::NG
900