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