1 /*
2  * Copyright (c) 2021 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_INDEXER_INDEXER_COMPONENT_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_INDEXER_INDEXER_COMPONENT_H
18 
19 #include "base/i18n/localization.h"
20 #include "base/utils/string_utils.h"
21 #include "base/utils/system_properties.h"
22 #include "core/components/indexer/indexer_item_component.h"
23 #include "core/components/list/list_component.h"
24 #include "core/pipeline/base/component_group.h"
25 
26 namespace OHOS::Ace {
27 
28 // common data
29 inline constexpr int32_t INDEXER_INVALID_INDEX = -1;
30 inline constexpr int32_t INDEXER_ITEM_MAX_COUNT = 29; // [indexer], default max count
31 inline constexpr uint8_t DEFAULT_OPACITY = 255;
32 inline constexpr uint8_t ZERO_OPACITY = 0;
33 inline const std::u16string INDEXER_STR_COLLECT = StringUtils::Str8ToStr16("*");
34 inline const std::u16string INDEXER_STR_DOT = StringUtils::Str8ToStr16("•");
35 inline const std::u16string INDEXER_STR_DOT_EX = StringUtils::Str8ToStr16(".");
36 inline const std::u16string INDEXER_STR_SHARP = StringUtils::Str8ToStr16("#");
37 inline const std::u16string INDEXER_STR_COLLAPSE = StringUtils::Str8ToStr16(">");
38 inline const std::u16string INDEXER_STR_SPACE = StringUtils::Str8ToStr16(" ");
39 inline constexpr float KEYFRAME_BEGIN = 0.0;
40 inline constexpr float KEYFRAME_HALF = 0.5;
41 inline constexpr float KEYFRAME_END = 1.0;
42 inline constexpr double DEFAULT_OPACITY_IN_PERCENT = 1.0;
43 inline constexpr double NINETY_OPACITY_IN_PERCENT = 0.9;
44 inline constexpr double ZERO_OPACITY_IN_PERCENT = 0.0;
45 // data for list mode
46 inline constexpr double INDEXER_LIST_ITEM_TEXT_SIZE = 12.0; // list mode, font size (FP)
47 inline constexpr uint32_t INDEXER_LIST_COLOR = 0x99000000;
48 inline constexpr uint32_t INDEXER_LIST_ACTIVE_COLOR = 0xFF0A59F7;
49 inline constexpr double INDEXER_DEFAULT_PADDING_X = 10.0;
50 inline constexpr double INDEXER_DEFAULT_PADDING_Y = 16.0;
51 inline constexpr double BUBBLE_BOX_SIZE = 56.0;
52 inline constexpr double BUBBLE_BOX_RADIUS = 16.0;
53 inline constexpr double BUBBLE_FONT_SIZE = 24.0;
54 inline constexpr Dimension BUBBLE_POSITION_X = Dimension(-84.0, DimensionUnit::VP);
55 inline constexpr Dimension BUBBLE_POSITION_Y = 48.0_vp;
56 inline constexpr uint32_t BUBBLE_FONT_COLOR = 0xFF254FF7;
57 inline constexpr uint32_t BUBBLE_BG_COLOR = 0xFFF1F3F5;
58 inline constexpr double INDEXER_ITEM_SIZE = 16.0;      // circle mode, item size (VP)
59 inline constexpr double INDEXER_ITEM_TEXT_SIZE = 12.0; // circle, mode font size (VP)
60 // data for circle mode
61 inline constexpr int32_t INDEXER_COLLAPSE_ITEM_COUNT = 4;
62 inline constexpr double INDEXER_CIRCLE_ITEM_SIZE = 24.0;          // circle mode, item size (VP)
63 inline constexpr double INDEXER_CIRCLE_ITEM_TEXT_SIZE = 13.0;     // circle, mode font size (VP)
64 inline constexpr double INDEXER_CIRCLE_ITEM_SHADOW_RADIUS = 27.0; // circle mode, shadow radius (VP)
65 inline constexpr double INDEXER_ANGLE_TO_RADIAN = 180.0;
66 inline constexpr double INDEXER_ARC_BEGIN = -0.4488; // default angle
67 inline constexpr double INDEXER_ARC_LENGTH = 2.0 * M_PI;
68 inline constexpr double BUBBLE_BOX_SIZE_CIRCLE = 46.0;
69 inline constexpr double BUBBLE_FONT_SIZE_CIRCLE = 19.0;
70 inline constexpr uint32_t BUBBLE_BG_COLOR_CIRCLE = 0xFF404040;
71 inline constexpr uint32_t INDEXER_CIRCLE_ARC_COLOR = 0xFF212121;
72 inline constexpr uint32_t INDEXER_CIRCLE_ACTIVE_BG_COLOR = 0xFF007DFF;
73 inline constexpr uint32_t INDEXER_ACTIVE_BG_COLOR = 0x1F0A59F7;
74 
75 class IndexerComponent : public ComponentGroup {
76     DECLARE_ACE_TYPE(IndexerComponent, ComponentGroup);
77 
78 public:
79     IndexerComponent(const RefPtr<ListComponent>& list, bool circleMode, bool bubble = true, bool multiLanguage = false)
80         : indexerLabel_(Localization::GetInstance()->GetIndexLetter()), list_(list), circleMode_(circleMode),
81           bubbleEnabled_(bubble), multiLanguageEnabled_(multiLanguage)
82     {
83         if (indexerLabel_.empty()) {
84             indexerLabel_ = GetU16StrVector(alphabetDefault_);
85         }
86         if (circleMode_) {
87             itemSize_ = Dimension(INDEXER_CIRCLE_ITEM_SIZE, DimensionUnit::VP);
88         } else {
89             itemSize_ = Dimension(INDEXER_ITEM_SIZE, DimensionUnit::VP);
90         }
91         BuildIndexerAlphabet();
92         InitIndexerItemStyle();
93         BuildIndexerItems();
94     }
95 
96     IndexerComponent(const RefPtr<ListComponent>& list, bool circleMode, const std::vector<std::string>& label,
97         bool bubble = true, bool multiLanguage = false)
98         : list_(list), circleMode_(circleMode), bubbleEnabled_(bubble), multiLanguageEnabled_(multiLanguage)
99     {
100         indexerLabel_ = GetU16StrVector(label);
101         userDefineList_ = true;
102         if (indexerLabel_.empty()) {
103             indexerLabel_ = Localization::GetInstance()->GetIndexLetter();
104             userDefineList_ = false;
105         }
106         if (circleMode_) {
107             itemSize_ = Dimension(INDEXER_CIRCLE_ITEM_SIZE, DimensionUnit::VP);
108         } else {
109             itemSize_ = Dimension(INDEXER_ITEM_SIZE, DimensionUnit::VP);
110         }
111         BuildIndexerAlphabet();
112         InitIndexerItemStyle();
113         BuildIndexerItems();
114     }
115 
116     ~IndexerComponent() override = default;
117     RefPtr<Element> CreateElement() override;
118     RefPtr<RenderNode> CreateRenderNode() override;
119 
GetController()120     const RefPtr<ScrollPositionController>& GetController() const
121     {
122         return controller_;
123     }
124 
SetController(const RefPtr<ScrollPositionController> & controller)125     void SetController(const RefPtr<ScrollPositionController>& controller)
126     {
127         controller_ = controller;
128     }
129 
130     // init data
131     void FormatLabelAlphabet();
132     void BuildIndexerAlphabet();
133     void BuildDefaultAlphabet();
134     void InitIndexerItemStyle();
135     void BuildIndexerItems();
136     void BuildArcItem();
137     void BuildIndicatorBox();
138     void BuildBubbleBox();
139     void BuildTextItem(const std::u16string& strSection, const std::u16string& strLabel, int32_t itemType = 0);
140     void BuildCollapseItem();
141 
IsBubbleEnabled()142     bool IsBubbleEnabled() const
143     {
144         return bubbleEnabled_;
145     }
146 
SetBubbleEnabled(bool enable)147     void SetBubbleEnabled(bool enable)
148     {
149         bubbleEnabled_ = enable;
150     }
151 
HasCollapseItem()152     bool HasCollapseItem() const
153     {
154         return hasCollapseItem_;
155     }
156 
157     // add item
158     int32_t AddItemIndexKey(const std::string& indexKey, const std::string& headStyle);
159 
160     // remove item
161     bool RemoveItemIndexKey(const std::string& indexKey);
162 
163     RefPtr<IndexerItemComponent> GetIndexerItem(const std::string& indexKey);
164     int32_t GetSectionIndexInList(const std::string& indexKey);
165     int32_t GetSectionIndexInIndexer(int32_t index);
166 
167     // for debug
168     void PrintItemInfo() const;
169 
GetBubbleTextComponent()170     const RefPtr<TextComponent>& GetBubbleTextComponent() const
171     {
172         return bubbleText_;
173     }
174 
GetNonItemCount()175     int32_t GetNonItemCount() const
176     {
177         return nonItemCount_;
178     }
179 
GetMaxShowCount()180     int32_t GetMaxShowCount() const
181     {
182         return maxShowCount_;
183     }
184 
GetCircleMode()185     bool GetCircleMode() const
186     {
187         return circleMode_;
188     }
189 
SetCircleMode(bool circleMode)190     void SetCircleMode(bool circleMode)
191     {
192         circleMode_ = circleMode;
193     }
194 
GetItemSize()195     const Dimension& GetItemSize() const
196     {
197         return itemSize_;
198     }
199 
SetItemSize(const Dimension & size)200     void SetItemSize(const Dimension& size)
201     {
202         itemSize_ = size;
203     }
204 
GetItemCount()205     int32_t GetItemCount() const
206     {
207         return itemCount_;
208     }
209 
GetNormalTextStyle()210     const TextStyle& GetNormalTextStyle() const
211     {
212         return normalStyle_;
213     }
214 
SetNormalTextStyle(const TextStyle & textStyle)215     void SetNormalTextStyle(const TextStyle& textStyle)
216     {
217         normalStyle_ = textStyle;
218     }
219 
GetActiveTextStyle()220     const TextStyle& GetActiveTextStyle() const
221     {
222         return activeStyle_;
223     }
224 
SetActiveTextStyle(const TextStyle & textStyle)225     void SetActiveTextStyle(const TextStyle& textStyle)
226     {
227         activeStyle_ = textStyle;
228     }
229 
GetU16StrVector(const std::vector<std::string> & str)230     std::vector<std::u16string> GetU16StrVector(const std::vector<std::string>& str)
231     {
232         std::vector<std::u16string> alphabet;
233         for (const auto& item : str) {
234             alphabet.emplace_back(StringUtils::Str8ToStr16(item));
235         }
236         return alphabet;
237     }
GetIndexerItemsComponents()238     std::list<RefPtr<IndexerItemComponent>> GetIndexerItemsComponents()
239     {
240         return listItem_;
241     }
242 
SetIndexerChange(const EventMarker & indexChange)243     void SetIndexerChange(const EventMarker& indexChange)
244     {
245         indexChange_ = indexChange;
246     }
247 
GetIndexerChange()248     const EventMarker& GetIndexerChange() const
249     {
250         return indexChange_;
251     }
252 
253 protected:
254     void UpdateSectionIndex();
255     // add
256     int32_t AddSectionHead(const RefPtr<IndexerItemComponent>& indexerItem, const std::string& headStyleStr);
257     int32_t AddItemToSharp(const std::string& indexKey, const std::string& headStyle);
258     // remove
259     bool RemoveSectionHead(int32_t index);
260     bool RemoveItemFromSharp(const std::string& indexKey);
261 
262     std::vector<std::string> alphabetDefault_ = { "#", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
263         "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
264 
265     std::vector<std::string> alphabetIndexer_ = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
266         "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
267 
268     std::vector<std::u16string> indexerLabel_;  // user input sections
269     std::vector<std::u16string> sectionsLocal_; // actual sections, exclude dot
270     std::vector<std::u16string> labelLocal_;    // sections shown on the screen with dot inside
271     std::vector<std::u16string> defaultAlphaLocal_;
272     TextStyle normalStyle_;
273     TextStyle activeStyle_;
274 
275     std::list<RefPtr<IndexerItemComponent>> listItem_;
276     RefPtr<ListComponent> list_;
277     RefPtr<ScrollPositionController> controller_;
278     RefPtr<TextComponent> bubbleText_;
279 
280     int32_t itemCount_ = INDEXER_ITEM_MAX_COUNT;    // actual indexer item
281     int32_t maxShowCount_ = INDEXER_ITEM_MAX_COUNT; // max item shown on screen
282     int32_t nonItemCount_ = 0;                      // not indexer item count such as arc and bubbleBox
283     // item size
284     Dimension itemSize_;
285     double startPosition_ = INDEXER_ARC_BEGIN; // arc start angle
286     double arcLength_ = INDEXER_ARC_LENGTH;    // arc length
287     bool circleMode_ = false;                  // list mode or circle mode
288     bool userDefineList_ = false;              // user define alphabet list
289     bool isFirstItem_ = false;
290     bool hasCollapseItem_ = false;
291     bool bubbleEnabled_ = true;
292     bool multiLanguageEnabled_ = false; // support multi language or not
293 
294 private:
295     EventMarker indexChange_;
296 };
297 
298 } // namespace OHOS::Ace
299 
300 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_INDEXER_INDEXER_COMPONENT_H
301