1 /*
2  * Copyright (c) 2021-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_PICKER_PICKER_THEME_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_PICKER_PICKER_THEME_H
18 
19 #include "base/geometry/dimension.h"
20 #include "base/utils/system_properties.h"
21 #include "core/components/common/layout/constants.h"
22 #include "core/components/common/properties/border.h"
23 #include "core/components/common/properties/color.h"
24 #include "core/components/common/properties/decoration.h"
25 #include "core/components/common/properties/edge.h"
26 #include "core/components/common/properties/text_style.h"
27 #include "core/components/picker/picker_data.h"
28 #include "core/components/theme/theme.h"
29 #include "core/components/theme/theme_constants.h"
30 #include "core/components/theme/theme_constants_defines.h"
31 
32 namespace OHOS::Ace {
33 namespace {
34 constexpr Dimension DIVIDER_THICKNESS = 1.0_px;
35 } // namespace
36 
37 class PickerTheme final : public virtual Theme {
38     DECLARE_ACE_TYPE(PickerTheme, Theme);
39 
40 public:
41     class Builder final {
42     public:
43         Builder() = default;
44         ~Builder() = default;
45 
Build(const RefPtr<ThemeConstants> & themeConstants)46         RefPtr<PickerTheme> Build(const RefPtr<ThemeConstants>& themeConstants) const
47         {
48             RefPtr<PickerTheme> theme = AceType::Claim(new PickerTheme());
49             if (!themeConstants) {
50                 return theme;
51             }
52 
53             auto themeStyle = themeConstants->GetThemeStyle();
54             if (!themeStyle) {
55                 return theme;
56             }
57 
58             InitializeTextStyles(theme, themeStyle);
59             theme->optionSizeUnit_ = DimensionUnit::VP;
60             theme->lunarWidth_ =
61                 Dimension(36.0, DimensionUnit::VP); // 36.0: lunarWidth, this width do not need setting by outer.
62             theme->lunarHeight_ =
63                 Dimension(18.0, DimensionUnit::VP); // 18.0: lunarHeight, this height do not need setting by outer.
64             theme->rotateInterval_ = 15.0; // when rotate 15.0 angle handle scroll of picker column.
65             theme->dividerThickness_ = DIVIDER_THICKNESS;
66             Parse(themeStyle, theme);
67             return theme;
68         }
69 
70         void Parse(const RefPtr<ThemeStyle>& style, const RefPtr<PickerTheme>& theme) const;
71 
72     private:
InitializeButtonTextStyles(const RefPtr<PickerTheme> & theme,const RefPtr<ThemeStyle> & themeStyle)73         void InitializeButtonTextStyles(const RefPtr<PickerTheme>& theme, const RefPtr<ThemeStyle>& themeStyle) const
74         {
75             auto pattern = themeStyle->GetAttr<RefPtr<ThemeStyle>>("picker_pattern", nullptr);
76             if (pattern) {
77                 theme->buttonStyle_.SetFontSize(pattern->GetAttr<Dimension>("picker_button_font_size", 0.0_fp));
78                 theme->buttonStyle_.SetTextColor(pattern->GetAttr<Color>("picker_button_text_color", Color()));
79             }
80         }
81 
InitializeTitleTextStyles(const RefPtr<PickerTheme> & theme,const RefPtr<ThemeStyle> & themeStyle)82         void InitializeTitleTextStyles(const RefPtr<PickerTheme>& theme, const RefPtr<ThemeStyle>& themeStyle) const
83         {
84             auto pattern = themeStyle->GetAttr<RefPtr<ThemeStyle>>("picker_pattern", nullptr);
85             if (pattern) {
86                 theme->titleStyle_.SetFontSize(pattern->GetAttr<Dimension>("picker_title_font_size", 0.0_fp));
87                 theme->titleStyle_.SetTextColor(pattern->GetAttr<Color>("picker_title_text_color", Color()));
88             }
89             theme->titleStyle_.SetFontWeight(FontWeight::W500);
90             theme->titleStyle_.SetMaxLines(1);
91             theme->titleStyle_.SetTextOverflow(TextOverflow::ELLIPSIS);
92         }
93 
InitializeItemTextStyles(const RefPtr<PickerTheme> & theme,const RefPtr<ThemeStyle> & themeStyle)94         void InitializeItemTextStyles(const RefPtr<PickerTheme>& theme, const RefPtr<ThemeStyle>& themeStyle) const
95         {
96             auto pattern = themeStyle->GetAttr<RefPtr<ThemeStyle>>("picker_pattern", nullptr);
97             if (pattern) {
98                 theme->selectedOptionStyle_.SetTextColor(
99                     pattern->GetAttr<Color>("selected_text_color", Color(0x007DFF)));
100                 theme->selectedOptionStyle_.SetFontSize(
101                     pattern->GetAttr<Dimension>("selected_text_size", 20.0_vp));
102                 theme->selectedOptionStyle_.SetFontWeight(FontWeight::MEDIUM);
103                 theme->selectedOptionStyle_.SetAdaptTextSize(theme->selectedOptionStyle_.GetFontSize(),
104                     pattern->GetAttr<Dimension>("picker_select_option_min_font_size", 0.0_fp));
105                 theme->selectedOptionStyle_.SetMaxLines(1);
106                 theme->selectedOptionStyle_.SetTextOverflow(TextOverflow::ELLIPSIS);
107 
108                 theme->normalOptionStyle_.SetTextColor(
109                     pattern->GetAttr<Color>("text_color", Color(0xff182431)));
110                 theme->normalOptionStyle_.SetFontSize(
111                     pattern->GetAttr<Dimension>("text_size", 16.0_fp));
112                 theme->normalOptionStyle_.SetFontWeight(FontWeight::REGULAR);
113                 theme->normalOptionStyle_.SetAdaptTextSize(theme->normalOptionStyle_.GetFontSize(),
114                     pattern->GetAttr<Dimension>("picker_normal_option_min_font_size", 0.0_fp));
115                 theme->normalOptionStyle_.SetMaxLines(1);
116                 theme->normalOptionStyle_.SetTextOverflow(TextOverflow::ELLIPSIS);
117 
118                 theme->disappearOptionStyle_.SetTextColor(
119                     pattern->GetAttr<Color>("disappear_text_color", Color(0xff182431)));
120                 theme->disappearOptionStyle_.SetFontSize(
121                     pattern->GetAttr<Dimension>("disappear_text_size", 14.0_fp));
122                 theme->disappearOptionStyle_.SetFontWeight(FontWeight::REGULAR);
123                 theme->disappearOptionStyle_.SetAdaptTextSize(theme->disappearOptionStyle_.GetFontSize(),
124                     pattern->GetAttr<Dimension>("picker_normal_option_min_font_size", 0.0_fp));
125                 theme->disappearOptionStyle_.SetMaxLines(1);
126                 theme->disappearOptionStyle_.SetTextOverflow(TextOverflow::ELLIPSIS);
127                 theme->focusOptionStyle_.SetFontSize(
128                     pattern->GetAttr<Dimension>("picker_focus_option_font_size", 0.0_fp));
129                 theme->focusOptionStyle_.SetTextColor(
130                     pattern->GetAttr<Color>("picker_focus_option_text_color", Color()));
131                 theme->focusOptionStyle_.SetFontWeight(
132                     FontWeight(static_cast<int32_t>(pattern->GetAttr<double>("picker_focus_option_weight", 0.0))));
133                 theme->focusOptionStyle_.SetAdaptTextSize(theme->focusOptionStyle_.GetFontSize(),
134                     pattern->GetAttr<Dimension>("picker_select_option_min_font_size", 0.0_fp));
135             }
136             theme->focusOptionStyle_.SetMaxLines(1);
137             theme->focusOptionStyle_.SetTextOverflow(TextOverflow::ELLIPSIS);
138 
139             if (SystemProperties::GetDeviceType() == DeviceType::PHONE) {
140                 theme->focusOptionStyle_ = theme->selectedOptionStyle_; // focus style the same with selected on phone
141             }
142         }
143 
InitializeTextStyles(const RefPtr<PickerTheme> & theme,const RefPtr<ThemeStyle> & themeStyle)144         void InitializeTextStyles(const RefPtr<PickerTheme>& theme, const RefPtr<ThemeStyle>& themeStyle) const
145         {
146             InitializeItemTextStyles(theme, themeStyle);
147             InitializeTitleTextStyles(theme, themeStyle);
148             InitializeButtonTextStyles(theme, themeStyle);
149         }
150     };
151 
152     ~PickerTheme() override = default;
153 
clone()154     RefPtr<PickerTheme> clone() const
155     {
156         auto theme = AceType::Claim(new PickerTheme());
157         theme->selectedOptionSize_ = selectedOptionSize_;
158         theme->selectedOptionStyle_ = selectedOptionStyle_;
159         theme->normalOptionSize_ = normalOptionSize_;
160         theme->normalOptionStyle_ = normalOptionStyle_;
161         theme->disappearOptionStyle_ = disappearOptionStyle_;
162         theme->showOptionCount_ = showOptionCount_;
163         theme->optionSizeUnit_ = optionSizeUnit_;
164         theme->popupDecoration_ = popupDecoration_;
165         theme->focusColor_ = focusColor_;
166         theme->popupEdge_ = popupEdge_;
167         theme->focusOptionStyle_ = focusOptionStyle_;
168         theme->focusOptionDecoration_ = focusOptionDecoration_;
169         theme->selectedOptionDecoration_ = selectedOptionDecoration_;
170         theme->buttonStyle_ = buttonStyle_;
171         theme->showButtons_ = showButtons_;
172         theme->buttonWidth_ = buttonWidth_;
173         theme->buttonHeight_ = buttonHeight_;
174         theme->buttonTopPadding_ = buttonTopPadding_;
175         theme->jumpInterval_ = jumpInterval_;
176         theme->columnIntervalMargin_ = columnIntervalMargin_;
177         theme->focusRadius_ = focusRadius_;
178         theme->optionPadding_ = optionPadding_;
179         theme->titleStyle_ = titleStyle_;
180         theme->titleBottomPadding_ = titleBottomPadding_;
181         theme->popupOutDecoration_ = popupOutDecoration_;
182         theme->lunarWidth_ = lunarWidth_;
183         theme->lunarHeight_ = lunarHeight_;
184         theme->timeSplitter_ = timeSplitter_;
185         theme->rotateInterval_ = rotateInterval_;
186         theme->deviceHeightLimit_ = deviceHeightLimit_;
187         theme->dividerThickness_ = dividerThickness_;
188         theme->dividerSpacing_ = dividerSpacing_;
189         theme->dividerColor_ = dividerColor_;
190         theme->gradientHeight_ = gradientHeight_;
191         theme->columnFixedWidth_ = columnFixedWidth_;
192         theme->disappearOptionStyle_ = disappearOptionStyle_;
193         theme->pressColor_ = pressColor_;
194         theme->hoverColor_ = hoverColor_;
195         theme->lunarswitchTextColor_ = lunarswitchTextColor_;
196         theme->lunarswitchTextSize_ = lunarswitchTextSize_;
197         theme->defaultStartDate_ = defaultStartDate_;
198         theme->defaultEndDate_ = defaultEndDate_;
199         return theme;
200     }
201 
GetOptionStyle(bool selected,bool focus)202     const TextStyle& GetOptionStyle(bool selected, bool focus) const
203     {
204         if (!selected) {
205             return normalOptionStyle_;
206         }
207 
208         if (focus) {
209             return focusOptionStyle_;
210         }
211 
212         return selectedOptionStyle_;
213     }
SetOptionStyle(bool selected,bool focus,const TextStyle & value)214     void SetOptionStyle(bool selected, bool focus, const TextStyle& value)
215     {
216         if (!selected) {
217             normalOptionStyle_ = value;
218         } else if (focus) {
219             focusOptionStyle_ = value;
220         } else {
221             selectedOptionStyle_ = value;
222         }
223     }
224 
GetDisappearOptionStyle()225     const TextStyle& GetDisappearOptionStyle() const
226     {
227         return disappearOptionStyle_;
228     }
SetDisappearOptionStyle(const TextStyle & value)229     void SetDisappearOptionStyle(const TextStyle& value)
230     {
231         disappearOptionStyle_ = value;
232     }
233 
GetButtonStyle()234     const TextStyle& GetButtonStyle() const
235     {
236         return buttonStyle_;
237     }
238 
GetOptionDecoration(bool focus)239     const RefPtr<Decoration>& GetOptionDecoration(bool focus)
240     {
241         if (focus) {
242             return focusOptionDecoration_;
243         }
244 
245         return selectedOptionDecoration_;
246     }
SetOptionDecoration(bool focus,const RefPtr<Decoration> & value)247     void SetOptionDecoration(bool focus, const RefPtr<Decoration>& value)
248     {
249         if (focus) {
250             focusOptionDecoration_ = value;
251         } else {
252             selectedOptionDecoration_ = value;
253         }
254     }
255 
GetOptionSize(bool selected)256     const Size& GetOptionSize(bool selected) const
257     {
258         if (selected) {
259             return selectedOptionSize_;
260         }
261 
262         return normalOptionSize_;
263     }
264 
GetShowOptionCount()265     uint32_t GetShowOptionCount() const
266     {
267         return showOptionCount_;
268     }
269 
GetOptionSizeUnit()270     DimensionUnit GetOptionSizeUnit() const
271     {
272         return optionSizeUnit_;
273     }
274 
GetPopupDecoration(bool isOutBox)275     const RefPtr<Decoration>& GetPopupDecoration(bool isOutBox) const
276     {
277         if (!isOutBox) {
278             return popupDecoration_;
279         }
280         return popupOutDecoration_;
281     }
282 
GetFocusColor()283     const Color& GetFocusColor() const
284     {
285         return focusColor_;
286     }
287 
GetPopupEdge()288     const Edge& GetPopupEdge() const
289     {
290         return popupEdge_;
291     }
292 
GetShowButtons()293     bool GetShowButtons() const
294     {
295         return showButtons_;
296     }
297 
GetButtonWidth()298     const Dimension& GetButtonWidth() const
299     {
300         return buttonWidth_;
301     }
302 
GetButtonHeight()303     const Dimension& GetButtonHeight() const
304     {
305         return buttonHeight_;
306     }
307 
GetButtonTopPadding()308     const Dimension& GetButtonTopPadding() const
309     {
310         return buttonTopPadding_;
311     }
312 
GetJumpInterval()313     const Dimension& GetJumpInterval() const
314     {
315         return jumpInterval_;
316     }
317 
GetColumnIntervalMargin()318     const Dimension& GetColumnIntervalMargin() const
319     {
320         return columnIntervalMargin_;
321     }
322 
GetFocusRadius()323     const Radius& GetFocusRadius() const
324     {
325         return focusRadius_;
326     }
327 
GetOptionPadding()328     double GetOptionPadding() const
329     {
330         return optionPadding_;
331     }
SetOptionPadding(double value)332     void SetOptionPadding(double value)
333     {
334         optionPadding_ = value;
335     }
336 
GetTitleStyle()337     const TextStyle& GetTitleStyle() const
338     {
339         return titleStyle_;
340     }
341 
GetTitleBottomPadding()342     const Dimension& GetTitleBottomPadding() const
343     {
344         return titleBottomPadding_;
345     }
346 
GetLunarWidth()347     const Dimension& GetLunarWidth() const
348     {
349         return lunarWidth_;
350     }
351 
GetLunarHeight()352     const Dimension& GetLunarHeight() const
353     {
354         return lunarHeight_;
355     }
356 
HasTimeSplitter()357     bool HasTimeSplitter() const
358     {
359         return (timeSplitter_ > 0);
360     }
361 
GetRotateInterval()362     double GetRotateInterval() const
363     {
364         return rotateInterval_;
365     }
366 
GetDeviceHeightLimit()367     double GetDeviceHeightLimit() const
368     {
369         return deviceHeightLimit_;
370     }
371 
GetDividerThickness()372     const Dimension& GetDividerThickness() const
373     {
374         return dividerThickness_;
375     }
376 
GetDividerSpacing()377     const Dimension& GetDividerSpacing() const
378     {
379         return dividerSpacing_;
380     }
381 
GetDividerColor()382     const Color& GetDividerColor() const
383     {
384         return dividerColor_;
385     }
386 
GetGradientHeight()387     const Dimension& GetGradientHeight() const
388     {
389         return gradientHeight_;
390     }
391 
GetColumnFixedWidth()392     const Dimension& GetColumnFixedWidth() const
393     {
394         return columnFixedWidth_;
395     }
396 
GetColumnBottomTotalHeight(bool hasLunar)397     Dimension GetColumnBottomTotalHeight(bool hasLunar) const
398     {
399         if (hasLunar) {
400             return buttonHeight_ + lunarHeight_ + buttonTopPadding_ * 2 + popupEdge_.Bottom(); //2: double padding
401         } else {
402             return buttonHeight_ + buttonTopPadding_ + popupEdge_.Bottom();
403         }
404     }
405 
GetPressColor()406     const Color& GetPressColor() const
407     {
408         return pressColor_;
409     }
410 
GetHoverColor()411     const Color& GetHoverColor() const
412     {
413         return hoverColor_;
414     }
415 
GetPaddingHorizontal()416     const Dimension& GetPaddingHorizontal() const
417     {
418         return paddingHorizontal_;
419     }
420 
GetContentMarginVertical()421     const Dimension& GetContentMarginVertical() const
422     {
423         return contentMarginVertical_;
424     }
425 
GetLunarSwitchTextSize()426     const Dimension& GetLunarSwitchTextSize() const
427     {
428         return lunarswitchTextSize_;
429     }
430 
GetLunarSwitchTextColor()431     const Color& GetLunarSwitchTextColor() const
432     {
433         return lunarswitchTextColor_;
434     }
435 
GetDefaultStartDate()436     const PickerDate& GetDefaultStartDate() const
437     {
438         return defaultStartDate_;
439     }
440 
GetDefaultEndDate()441     const PickerDate& GetDefaultEndDate() const
442     {
443         return defaultEndDate_;
444     }
445 
GetShowCountLandscape()446     uint32_t GetShowCountLandscape() const
447     {
448         return showCountLandscape_;
449     }
450 
GetShowCountPortrait()451     uint32_t GetShowCountPortrait() const
452     {
453         return showCountPortrait_;
454     }
455 
GetTitleFontScaleLimit()456     double GetTitleFontScaleLimit()
457     {
458         return titleFontScaleLimit_;
459     }
460 
GetGradientHeightLimit()461     const Dimension& GetGradientHeightLimit() const
462     {
463         return gradientHeightLimit_;
464     }
465 
GetDividerSpacingLimit()466     const Dimension& GetDividerSpacingLimit() const
467     {
468         return dividerSpacingHeightLimit_;
469     }
470 
GetPickerDialogFontPadding()471     const Dimension& GetPickerDialogFontPadding() const
472     {
473         return pickerDialogFontPadding_;
474     }
475 
GetUseSetSelectedTextStyle()476     const Dimension& GetUseSetSelectedTextStyle() const
477     {
478         return selectedTextStyle_;
479     }
480 
GetUserSetNormalTextStyle()481     const Dimension& GetUserSetNormalTextStyle() const
482     {
483         return normalTextStyle_;
484     }
485 
GetUserSetDisappearTextStyle()486     const Dimension& GetUserSetDisappearTextStyle() const
487     {
488         return disappearTextStyle_;
489     }
490 
GetNormalFontScale()491     double GetNormalFontScale() const
492     {
493         return pickerDialogNormalFontScale_;
494     }
495 
GetMaxOneFontScale()496     double GetMaxOneFontScale() const
497     {
498         return pickerDialogMaxOneFontScale_;
499     }
500 
GetMaxTwoFontScale()501     double GetMaxTwoFontScale() const
502     {
503         return pickerDialogMaxTwoFontScale_;
504     }
505 
GetMaxThirdFontScale()506     double GetMaxThirdFontScale() const
507     {
508         return pickerDialogMaxThirdFontScale_;
509     }
510 private:
511     PickerTheme() = default;
512 
513     Color focusColor_;
514     Color hoverColor_;
515     Color pressColor_;
516     Color lunarswitchTextColor_;
517 
518     Radius focusRadius_;
519     uint32_t showOptionCount_ = 0;
520     bool showButtons_ = false;
521     Dimension jumpInterval_;
522 
523     // popup style
524     RefPtr<Decoration> popupDecoration_;
525     RefPtr<Decoration> popupOutDecoration_;
526     Edge popupEdge_;
527 
528     // column
529     Dimension columnIntervalMargin_;
530 
531     // text style
532     TextStyle focusOptionStyle_;
533     TextStyle selectedOptionStyle_;
534     TextStyle normalOptionStyle_;
535     TextStyle disappearOptionStyle_;
536     TextStyle buttonStyle_;
537     TextStyle titleStyle_;
538 
539     // text around decoration
540     RefPtr<Decoration> selectedOptionDecoration_;
541     RefPtr<Decoration> focusOptionDecoration_;
542 
543     // option size
544     Size selectedOptionSize_;
545     Size normalOptionSize_;
546     double optionPadding_ = 0.0;
547     DimensionUnit optionSizeUnit_ = DimensionUnit::PX;
548 
549     // buttons size
550     Dimension buttonWidth_;
551     Dimension buttonHeight_;
552     Dimension buttonTopPadding_;
553     Dimension titleBottomPadding_;
554 
555     // lunar size
556     Dimension lunarWidth_;
557     Dimension lunarHeight_;
558 
559     uint32_t timeSplitter_ = 0;
560 
561     double rotateInterval_ = 0.0;
562     Dimension dividerThickness_;
563     Dimension dividerSpacing_;
564     Color dividerColor_;
565     Dimension gradientHeight_;
566     Dimension columnFixedWidth_;
567 
568     Dimension paddingHorizontal_;
569     Dimension contentMarginVertical_;
570     Dimension lunarswitchTextSize_;
571 
572     PickerDate defaultStartDate_ = PickerDate(1970, 1, 1);
573     PickerDate defaultEndDate_ = PickerDate(2100, 12, 31);
574 
575     uint32_t showCountLandscape_ = 3;
576     uint32_t showCountPortrait_ = 5;
577     double deviceHeightLimit_ = 640.0;
578     Dimension gradientHeightLimit_ = 54.0_vp;
579     Dimension dividerSpacingHeightLimit_ = 64.0_vp;
580     Dimension pickerDialogFontPadding_ = 8.0_vp;
581     Dimension selectedTextStyle_ = 40.0_vp;
582     Dimension normalTextStyle_ = 32.0_vp;
583     Dimension disappearTextStyle_ = 28.0_vp;
584     double pickerDialogNormalFontScale_ = 1.0f;
585     double pickerDialogMaxOneFontScale_ = 1.75f;
586     double pickerDialogMaxTwoFontScale_ = 2.0f;
587     double pickerDialogMaxThirdFontScale_ = 3.2f;
588     double titleFontScaleLimit_ = 1.45f;
589 };
590 
591 } // namespace OHOS::Ace
592 
593 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_PICKER_PICKER_THEME_H
594