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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TEXT_PICKER_TEXT_PICKER_PATTERN_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TEXT_PICKER_TEXT_PICKER_PATTERN_H
18 
19 #include <optional>
20 
21 #include "core/components/picker/picker_theme.h"
22 #include "core/components/dialog/dialog_theme.h"
23 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
24 #include "core/components_ng/pattern/picker/picker_type_define.h"
25 #include "core/components_ng/pattern/text_picker/textpicker_row_accessibility_property.h"
26 #include "core/components_ng/pattern/text_picker/textpicker_event_hub.h"
27 #include "core/components_ng/pattern/text_picker/textpicker_layout_property.h"
28 #include "core/components_ng/pattern/text_picker/textpicker_paint_method.h"
29 #include "core/components_ng/pattern/text_picker/toss_animation_controller.h"
30 
31 namespace OHOS::Ace::NG {
32 class InspectorFilter;
33 using EventCallback = std::function<void(bool)>;
34 using ColumnChangeCallback = std::function<void(const RefPtr<FrameNode>&, bool, uint32_t, bool)>;
35 
36 namespace {
37 const Dimension TEXT_FOCUS_PAINT_WIDTH = 2.0_vp;
38 }
39 class TextPickerPattern : public LinearLayoutPattern {
40     DECLARE_ACE_TYPE(TextPickerPattern, LinearLayoutPattern);
41 
42 public:
TextPickerPattern()43     TextPickerPattern() : LinearLayoutPattern(false) {};
44 
45     ~TextPickerPattern() override = default;
46 
IsAtomicNode()47     bool IsAtomicNode() const override
48     {
49         return true;
50     }
51 
CreateEventHub()52     RefPtr<EventHub> CreateEventHub() override
53     {
54         return MakeRefPtr<TextPickerEventHub>();
55     }
56 
CreateLayoutProperty()57     RefPtr<LayoutProperty> CreateLayoutProperty() override
58     {
59         return MakeRefPtr<TextPickerLayoutProperty>();
60     }
61 
CreateAccessibilityProperty()62     RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override
63     {
64         return MakeRefPtr<TextPickerRowAccessibilityProperty>();
65     }
66 
CreateNodePaintMethod()67     RefPtr<NodePaintMethod> CreateNodePaintMethod() override
68     {
69         auto textPickerPaintMethod = MakeRefPtr<TextPickerPaintMethod>(WeakClaim(this));
70         textPickerPaintMethod->SetDefaultPickerItemHeight(CalculateHeight());
71         textPickerPaintMethod->SetEnabled(enabled_);
72         return textPickerPaintMethod;
73     }
74 
CreateLayoutAlgorithm()75     RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override
76     {
77         return MakeRefPtr<LinearLayoutAlgorithm>();
78     }
79 
80     void SetEventCallback(EventCallback&& value);
81 
82     void FireChangeEvent(bool refresh);
83 
84     void SetScrollStopEventCallback(EventCallback&& value);
85 
86     void FireScrollStopEvent(bool refresh);
87 
88     void OnColumnsBuilding();
89 
90     void FlushOptions();
91 
92     void SetDefaultPickerItemHeight();
93 
94     std::map<uint32_t, RefPtr<FrameNode>> GetColumnNodes();
95 
96     RefPtr<FrameNode> GetColumnNode();
97 
98     uint32_t GetShowOptionCount() const;
99 
SetSelected(uint32_t value)100     void SetSelected(uint32_t value)
101     {
102         selectedIndex_ = value;
103     }
104 
GetSelected()105     uint32_t GetSelected() const
106     {
107         return selectedIndex_;
108     }
109 
SetRange(const std::vector<NG::RangeContent> & value)110     void SetRange(const std::vector<NG::RangeContent>& value)
111     {
112         if (value.empty()) {
113             return;
114         }
115         range_.clear();
116         for (size_t i = 0; i < value.size(); i++) {
117             RangeContent content;
118             content.icon_ = value[i].icon_;
119             content.text_ = value[i].text_;
120             range_.emplace_back(content);
121         }
122     }
123 
GetRange()124     std::vector<NG::RangeContent> GetRange() const
125     {
126         return range_;
127     }
128 
GetMultiOptions()129     std::vector<NG::TextCascadePickerOptions> GetMultiOptions() const
130     {
131         return cascadeOriginptions_;
132     }
133 
SetColumnsKind(uint32_t columnKind)134     void SetColumnsKind(uint32_t columnKind)
135     {
136         columnsKind_ = columnKind;
137     }
138 
ClearOption()139     void ClearOption()
140     {
141         options_.clear();
142     }
143 
AppendOption(const NG::RangeContent & value)144     void AppendOption(const NG::RangeContent& value)
145     {
146         options_.emplace_back(value);
147     }
148 
GetOptionCount()149     uint32_t GetOptionCount() const
150     {
151         return options_.size();
152     }
153 
154     std::string GetSelectedObject(bool isColumnChange, int32_t status = 0) const;
155 
GetOption(uint32_t index)156     std::string GetOption(uint32_t index) const
157     {
158         if (index >= GetOptionCount()) {
159             return "";
160         }
161         return options_[index].text_;
162     }
163 
SetBackgroundColor(const Color & color)164     void SetBackgroundColor(const Color& color)
165     {
166         if (backgroundColor_ == color) {
167             return;
168         }
169         auto host = GetHost();
170         CHECK_NULL_VOID(host);
171         backgroundColor_ = color;
172         host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
173     }
174 
GetBackgroundColor()175     Color GetBackgroundColor()
176     {
177         return backgroundColor_;
178     }
179 
GetFocusPattern()180     FocusPattern GetFocusPattern() const override
181     {
182         auto pipeline = PipelineBase::GetCurrentContext();
183         CHECK_NULL_RETURN(pipeline, FocusPattern());
184         auto pickerTheme = pipeline->GetTheme<PickerTheme>();
185         CHECK_NULL_RETURN(pickerTheme, FocusPattern());
186         auto focusColor = pickerTheme->GetFocusColor();
187 
188         FocusPaintParam focusPaintParams;
189         focusPaintParams.SetPaintColor(focusColor);
190         focusPaintParams.SetPaintWidth(TEXT_FOCUS_PAINT_WIDTH);
191 
192         return { FocusType::NODE, true, FocusStyleType::CUSTOM_REGION, focusPaintParams };
193     }
194 
195     void ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const override;
196 
SetCascadeOptions(const std::vector<NG::TextCascadePickerOptions> & options,const std::vector<NG::TextCascadePickerOptions> & cascadeOptions)197     void SetCascadeOptions(const std::vector<NG::TextCascadePickerOptions>& options,
198         const std::vector<NG::TextCascadePickerOptions>& cascadeOptions)
199     {
200         cascadeOptions_.clear();
201         cascadeOriginptions_.clear();
202         for (auto& option : cascadeOptions) {
203             cascadeOptions_.emplace_back(std::move(option));
204         }
205         for (auto& option : options) {
206             cascadeOriginptions_.emplace_back(std::move(option));
207         }
208     }
209 
GetCascadeOptionCount()210     uint32_t GetCascadeOptionCount() const
211     {
212         return cascadeOptions_.size();
213     }
214 
GetOptionCount(const RefPtr<FrameNode> & frmeNode)215     uint32_t GetOptionCount(const RefPtr<FrameNode>& frmeNode)
216     {
217         uint32_t count = 0;
218         auto it = optionsWithNode_.find(frmeNode);
219         if (it != optionsWithNode_.end()) {
220             count = it->second.size();
221         }
222         return count;
223     }
224 
SetIsCascade(bool isCascade)225     void SetIsCascade(bool isCascade)
226     {
227         isCascade_ = isCascade;
228     }
229 
GetIsCascade()230     bool GetIsCascade() const
231     {
232         return isCascade_;
233     }
234 
SetConfirmNode(WeakPtr<FrameNode> buttonConfirmNode)235     void SetConfirmNode(WeakPtr<FrameNode> buttonConfirmNode)
236     {
237         weakButtonConfirm_ = buttonConfirmNode;
238     }
239 
SetCancelNode(WeakPtr<FrameNode> buttonCancelNode)240     void SetCancelNode(WeakPtr<FrameNode> buttonCancelNode)
241     {
242         weakButtonCancel_ = buttonCancelNode;
243     }
244 
SetForwardNode(WeakPtr<FrameNode> buttonForwardNode)245     void SetForwardNode(WeakPtr<FrameNode> buttonForwardNode)
246     {
247         weakButtonForward_ = buttonForwardNode;
248     }
249 
SetBackwardNode(WeakPtr<FrameNode> buttonBackwardNode)250     void SetBackwardNode(WeakPtr<FrameNode> buttonBackwardNode)
251     {
252         weakButtonBackward_ = buttonBackwardNode;
253     }
254 
255     void OnLanguageConfigurationUpdate() override;
256     void OnFontConfigurationUpdate() override;
257 
SetValues(const std::vector<std::string> & values)258     void SetValues(const std::vector<std::string>& values)
259     {
260         values_.clear();
261         for (auto& value : values) {
262             values_.emplace_back(value);
263         }
264     }
265 
GetValues()266     const std::vector<std::string>& GetValues()
267     {
268         return values_;
269     }
270 
GetSelecteds()271     const std::vector<uint32_t>& GetSelecteds()
272     {
273         return selecteds_;
274     }
275 
SetHasSelectAttr(bool value)276     void SetHasSelectAttr(bool value)
277     {
278         isHasSelectAttr_ = value;
279     }
280 
SetResizePickerItemHeight(double resizePickerItemHeight)281     void SetResizePickerItemHeight(double resizePickerItemHeight)
282     {
283         resizePickerItemHeight_ = resizePickerItemHeight;
284     }
285 
GetResizePickerItemHeight()286     double GetResizePickerItemHeight() const
287     {
288         return resizePickerItemHeight_;
289     }
290 
SetResizeFlag(bool resizeFlag)291     void SetResizeFlag(bool resizeFlag)
292     {
293         resizeFlag_ = resizeFlag;
294     }
295 
GetResizeFlag()296     bool GetResizeFlag() const
297     {
298         return resizeFlag_;
299     }
300 
SetIsShowInDialog(bool isShowInDialog)301     void SetIsShowInDialog(bool isShowInDialog)
302     {
303         isShowInDialog_ = isShowInDialog;
304     }
305 
GetIsShowInDialog()306     bool GetIsShowInDialog() const
307     {
308         return isShowInDialog_;
309     }
310 
GetDefaultPickerItemHeight()311     double GetDefaultPickerItemHeight() const
312     {
313         return defaultPickerItemHeight_;
314     }
315 
316     void SetSelecteds(const std::vector<uint32_t>& values);
317 
318     void HandleColumnChange(const RefPtr<FrameNode>& tag, bool isAdd, uint32_t index, bool needNotify);
319 
320     void SetChangeCallback(ColumnChangeCallback&& value);
321 
322     void ProcessCascadeOptions(const std::vector<NG::TextCascadePickerOptions>& options,
323         std::vector<NG::TextCascadePickerOptions>& reOptions, uint32_t index);
324 
325     size_t ProcessCascadeOptionDepth(const NG::TextCascadePickerOptions& option);
326 
327     void OnColorConfigurationUpdate() override;
328 
329     void OnDirectionConfigurationUpdate() override;
330 
SetContentRowNode(RefPtr<FrameNode> & contentRowNode)331     void SetContentRowNode(RefPtr<FrameNode>& contentRowNode)
332     {
333         contentRowNode_ = contentRowNode;
334     }
335 
SetPickerTag(bool isPicker)336     void SetPickerTag(bool isPicker)
337     {
338         isPicker_ = isPicker;
339     }
340 
341     void CheckAndUpdateColumnSize(SizeF& size, bool isNeedAdaptForAging = false);
342     bool NeedAdaptForAging();
343 
SetDivider(const ItemDivider & divider)344     void SetDivider(const ItemDivider& divider)
345     {
346         divider_ = divider;
347     }
348 
GetDivider()349     ItemDivider GetDivider()
350     {
351         return divider_;
352     }
353 
SetCustomDividerFlag(bool customDividerFlag)354     void SetCustomDividerFlag(bool customDividerFlag)
355     {
356         customDividerFlag_ = customDividerFlag;
357     }
358 
GetCustomDividerFlag()359     bool GetCustomDividerFlag()
360     {
361         return customDividerFlag_;
362     }
363 
SetGradientHeight(const Dimension & value)364     void SetGradientHeight(const Dimension& value)
365     {
366         value_ = value;
367     }
368 
GetGradientHeight()369     Dimension GetGradientHeight()
370     {
371         return value_;
372     }
373 
374     void SetCanLoop(bool isLoop);
375 
GetCanLoop()376     bool GetCanLoop()
377     {
378         return canloop_;
379     }
380 
SetRangeType(int32_t rangeType)381     void SetRangeType(int32_t rangeType)
382     {
383         rangeType_ = rangeType;
384     }
385 
GetRangeType()386     int32_t GetRangeType()
387     {
388         return rangeType_;
389     }
390 
HasUserDefinedDisappearFontFamily(bool isUserDefined)391     void HasUserDefinedDisappearFontFamily(bool isUserDefined)
392     {
393         hasUserDefinedDisappearFontFamily_ = isUserDefined;
394     }
395 
GetHasUserDefinedDisappearFontFamily()396     bool GetHasUserDefinedDisappearFontFamily()
397     {
398         return hasUserDefinedDisappearFontFamily_;
399     }
400 
HasUserDefinedNormalFontFamily(bool isUserDefined)401     void HasUserDefinedNormalFontFamily(bool isUserDefined)
402     {
403         hasUserDefinedNormalFontFamily_ = isUserDefined;
404     }
405 
GetHasUserDefinedNormalFontFamily()406     bool GetHasUserDefinedNormalFontFamily()
407     {
408         return hasUserDefinedNormalFontFamily_;
409     }
410 
HasUserDefinedSelectedFontFamily(bool isUserDefined)411     void HasUserDefinedSelectedFontFamily(bool isUserDefined)
412     {
413         hasUserDefinedSelectedFontFamily_ = isUserDefined;
414     }
415 
GetHasUserDefinedSelectedFontFamily()416     bool GetHasUserDefinedSelectedFontFamily()
417     {
418         return hasUserDefinedSelectedFontFamily_;
419     }
420 
updateFontConfigurationEvent(const std::function<void ()> & closeDialogEvent)421     void updateFontConfigurationEvent(const std::function<void()>& closeDialogEvent)
422     {
423         closeDialogEvent_ = closeDialogEvent;
424     }
425 
GetTextProperties()426     const PickerTextProperties& GetTextProperties() const
427     {
428         return textProperties_;
429     }
430 
SetTextProperties(const PickerTextProperties & properties)431     void SetTextProperties(const PickerTextProperties& properties)
432     {
433         textProperties_ = properties;
434         if (properties.disappearTextStyle_.fontSize.has_value() && properties.disappearTextStyle_.fontSize->IsValid()) {
435             isUserSetGradientFont_ = true;
436             gradientHeight_ = properties.disappearTextStyle_.fontSize.value();
437         }
438 
439         if (properties.normalTextStyle_.fontSize.has_value() && properties.normalTextStyle_.fontSize->IsValid()) {
440             isUserSetGradientFont_ = true;
441             gradientHeight_ = std::max(properties.normalTextStyle_.fontSize.value(), gradientHeight_);
442         }
443 
444         if (properties.selectedTextStyle_.fontSize.has_value() && properties.selectedTextStyle_.fontSize->IsValid()) {
445             isUserSetDividerSpacingFont_ = true;
446             dividerSpacing_ = properties.selectedTextStyle_.fontSize.value();
447         }
448     }
449 
GetIsUserSetDividerSpacingFont()450     bool GetIsUserSetDividerSpacingFont()
451     {
452         return isUserSetDividerSpacingFont_;
453     }
454 
GetIsUserSetGradientFont()455     bool GetIsUserSetGradientFont()
456     {
457         return isUserSetGradientFont_;
458     }
459 
GetDividerSpacing()460     Dimension GetDividerSpacing()
461     {
462         return dividerSpacing_;
463     }
464 
GetTextGradientHeight()465     Dimension GetTextGradientHeight()
466     {
467         return gradientHeight_;
468     }
469 
SetPaintDividerSpacing(float & value)470     void SetPaintDividerSpacing(float& value)
471     {
472         paintDividerSpacing_ = value;
473     }
474 
GetPaintDividerSpacing()475     float GetPaintDividerSpacing()
476     {
477         return paintDividerSpacing_;
478     }
479 
SetUserDefinedOpacity(double opacity)480     void SetUserDefinedOpacity(double opacity)
481     {
482         curOpacity_ = opacity;
483     }
484 
485 private:
486     void OnModifyDone() override;
487     void SetLayoutDirection(TextDirection textDirection);
488     void OnAttachToFrameNode() override;
489     bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override;
490 
491     void InitOnKeyEvent(const RefPtr<FocusHub>& focusHub);
492     bool OnKeyEvent(const KeyEvent& event);
493     bool HandleDirectionKey(KeyCode code);
494     double CalculateHeight();
495 
496     void InitDisabled();
497     void GetInnerFocusPaintRect(RoundRect& paintRect);
498     void PaintFocusState();
499     void SetButtonIdeaSize();
500     std::string GetRangeStr() const;
501     std::string GetOptionsMultiStr() const;
502     std::string GetOptionsMultiStrInternal() const;
503     std::string GetOptionsCascadeStr(
504         const std::vector<NG::TextCascadePickerOptions>& options) const;
505     bool ChangeCurrentOptionValue(NG::TextCascadePickerOptions& option,
506         uint32_t value, uint32_t curColumn, uint32_t replaceColumn);
507     void OnColumnsBuildingUnCascade();
508     void OnColumnsBuildingCascade();
509     std::string GetSelectedObjectMulti(const std::vector<std::string>& values,
510         const std::vector<uint32_t>& indexs, int32_t status) const;
511     void SupplementOption(const std::vector<NG::TextCascadePickerOptions>& reOptions,
512         std::vector<NG::RangeContent>& rangeContents, uint32_t patterIndex);
513     void ProcessCascadeOptionsValues(const std::vector<std::string>& rangeResultValue, uint32_t index);
514     void SetFocusCornerRadius(RoundRect& paintRect);
515     void UpdateConfirmButtonMargin(
516         const RefPtr<FrameNode>& buttonConfirmNode, const RefPtr<DialogTheme>& dialogTheme);
517     void UpdateCancelButtonMargin(
518         const RefPtr<FrameNode>& buttonCancelNode, const RefPtr<DialogTheme>& dialogTheme);
519     void CheckFocusID(int32_t childSize);
520     bool ParseDirectionKey(RefPtr<TextPickerColumnPattern>& textPickerColumnPattern, KeyCode& code, int32_t childSize);
521     RectF CalculatePaintRect(int32_t currentFocusIndex,
522         float centerX, float centerY, float piantRectWidth, float piantRectHeight, float columnWidth);
523 
524     bool enabled_ = true;
525     int32_t focusKeyID_ = 0;
526     double defaultPickerItemHeight_ = 0.0;
527     double resizePickerItemHeight_ = 0.0;
528     uint32_t selectedIndex_ = 0;
529     std::vector<NG::RangeContent> range_;
530     std::vector<NG::RangeContent> options_;
531     uint32_t columnsKind_ = 0;
532     std::vector<NG::TextCascadePickerOptions> cascadeOptions_;
533     std::map<WeakPtr<FrameNode>, std::vector<NG::RangeContent>> optionsWithNode_;
534     std::vector<NG::TextCascadePickerOptions> cascadeOriginptions_;
535     bool isCascade_ = false;
536     bool isHasSelectAttr_ = false;
537     WeakPtr<FrameNode> weakButtonConfirm_;
538     WeakPtr<FrameNode> weakButtonCancel_;
539     WeakPtr<FrameNode> weakButtonForward_;
540     WeakPtr<FrameNode> weakButtonBackward_;
541     std::vector<std::string> values_;
542     std::vector<uint32_t> selecteds_;
543     Color backgroundColor_ = Color::WHITE;
544     bool resizeFlag_ = false;
545     bool isShowInDialog_ = false;
546     bool canloop_ = true;
547 
548     // inner focus switch
549     bool operationOn_ = false;
550 
551     bool hasUserDefinedDisappearFontFamily_ = false;
552     bool hasUserDefinedNormalFontFamily_ = false;
553     bool hasUserDefinedSelectedFontFamily_ = false;
554 
555     double curOpacity_ = 1.0;
556 
557     ACE_DISALLOW_COPY_AND_MOVE(TextPickerPattern);
558 
559     WeakPtr<NG::FrameNode> contentRowNode_;
560     bool isPicker_ = true;
561     bool isFiredSelectsChange_ = false;
562     std::optional<std::string> firedSelectsStr_;
563 
564     ItemDivider divider_;
565     bool customDividerFlag_ = false;
566     Dimension value_;
567     int32_t rangeType_ = 0;
568     std::function<void()> closeDialogEvent_;
569     bool isUserSetDividerSpacingFont_ = false;
570     bool isUserSetGradientFont_ = false;
571     Dimension gradientHeight_;
572     Dimension dividerSpacing_;
573     float paintDividerSpacing_ = 1.0f;
574     bool isNeedUpdateSelectedIndex_ = true;
575     PickerTextProperties textProperties_;
576 };
577 } // namespace OHOS::Ace::NG
578 
579 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TEXT_PICKER_TEXT_PICKER_PATTERN_H
580