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