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 #include "core/components/indexer/indexer_item_component.h"
17 
18 #include "core/components/indexer/indexer_component.h"
19 #include "core/components/indexer/render_indexer_item.h"
20 #include "core/components/transform/transform_component.h"
21 
22 namespace OHOS::Ace {
23 
CreateRenderNode()24 RefPtr<RenderNode> IndexerItemComponent::CreateRenderNode()
25 {
26     return RenderIndexerItem::Create();
27 }
28 
BuildItem()29 void IndexerItemComponent::BuildItem()
30 {
31     box_ = AceType::MakeRefPtr<BoxComponent>();
32     RefPtr<Component> tail = box_;
33     if (rotate_) {
34         image_ = AceType::MakeRefPtr<ImageComponent>(InternalResource::ResourceId::INDEXER_ARROW_PNG);
35         image_->SetHeight(itemSize_);
36         image_->SetWidth(itemSize_);
37         box_->SetChild(image_);
38         tail = image_;
39     } else {
40         text_ = AceType::MakeRefPtr<TextComponent>(StringUtils::Str16ToStr8(strLabel_));
41         TextStyle textStyle;
42         textStyle.SetTextAlign(TextAlign::CENTER);
43         textStyle.SetFontWeight(FontWeight::W400);
44         text_->SetTextStyle(textStyle);
45         box_->SetChild(text_);
46         tail = text_;
47     }
48     box_->SetFlex(BoxFlex::FLEX_NO);
49     box_->SetWidth(itemSize_.Value(), itemSize_.Unit());
50     box_->SetHeight(itemSize_.Value(), itemSize_.Unit());
51     box_->SetAlignment(Alignment::CENTER);
52     // generate background
53     RefPtr<Decoration> background = AceType::MakeRefPtr<Decoration>();
54     background->SetBackgroundColor(Color::TRANSPARENT);
55     // generate circle
56     Radius radius = circleMode_ ? Radius(itemSize_ / 2.0) : Radius(Dimension(4.0, DimensionUnit::VP));
57     background->SetBorderRadius(radius);
58     box_->SetBackDecoration(background);
59     if (rotate_) {
60         RefPtr<TransformComponent> rotate = AceType::MakeRefPtr<TransformComponent>();
61         rotate->SetChild(box_);
62         Component::MergeRSNode(rotate, tail);
63         SetChild(rotate);
64     } else {
65         Component::MergeRSNode(box_, tail);
66         SetChild(box_);
67     }
68 }
69 
IsCorrectItem(const std::string & indexKey) const70 bool IndexerItemComponent::IsCorrectItem(const std::string& indexKey) const
71 {
72     // check whether the indexkey matched the section string
73     if (strSection_.empty()) {
74         LOGE("[indexer] IsCorrectItem invalid strSection_");
75         return false;
76     }
77 
78     if (strSection_ == INDEXER_STR_SHARP) {
79         return false;
80     }
81 
82     if (indexKey.empty()) {
83         LOGE("[indexer] IsCorrectItem NULL index key");
84         return false;
85     }
86 
87     std::u16string u16IndexKey = StringUtils::Str8ToStr16(indexKey);
88     for (size_t i = 0; i < strSection_.size(); ++i) {
89         if (u16IndexKey[0] == strSection_[i]) {
90             return true;
91         }
92     }
93 
94     return false;
95 }
96 
AddIndexKey(const std::string & indexKey)97 uint32_t IndexerItemComponent::AddIndexKey(const std::string& indexKey)
98 {
99     uint32_t itemIndex = 0;
100 
101     if (strSection_.empty()) {
102         LOGE("[indexer] AddIndexKey invalid strSection_");
103         return itemIndex;
104     }
105 
106     if (strSection_ == INDEXER_STR_SHARP) {
107         return AddIndexKeyForSharp(indexKey);
108     }
109 
110     if (indexKey.empty()) {
111         LOGE("[indexer] AddIndexKey NULL index key");
112         return itemIndex;
113     }
114 
115     if (!IsCorrectItem(indexKey)) {
116         LOGE("[indexer] AddIndexKey index key does not match section");
117         return itemIndex;
118     }
119 
120     auto it = indexKey_.begin();
121     for (; it != indexKey_.end(); ++it) {
122         if (indexKey.compare((*it)) < 0) {
123             itemIndex++;
124             indexKey_.insert(it, indexKey);
125             break;
126         } else {
127             itemIndex++;
128         }
129     }
130 
131     if (it == indexKey_.end()) {
132         indexKey_.emplace_back(indexKey);
133         itemIndex++;
134     }
135 
136     keyCount_++;
137     itemIndex += static_cast<uint32_t>(sectionIndex_);
138     if (circleMode_) {
139         itemIndex--;
140     }
141 
142     return itemIndex;
143 }
144 
AddIndexKeyForSharp(const std::string & indexKey)145 uint32_t IndexerItemComponent::AddIndexKeyForSharp(const std::string& indexKey)
146 {
147     uint32_t itemIndex = 0;
148     if (strSection_ != INDEXER_STR_SHARP) {
149         LOGE("[indexer] AddIndexKeyForSharp the section key is not #, section:%{public}s",
150             StringUtils::Str16ToStr8(strSection_).c_str());
151         return itemIndex;
152     }
153 
154     auto item = indexKey_.begin();
155     if (indexKey.empty()) {
156         // add NULL key
157         for (; item != indexKey_.end(); ++item) {
158             itemIndex++;
159             if (!item->empty()) {
160                 indexKey_.insert(item, indexKey);
161                 break;
162             }
163         }
164     } else {
165         // add number key
166         for (; item != indexKey_.end(); ++item) {
167             itemIndex++;
168             if (indexKey.compare((*item)) < 0) {
169                 indexKey_.insert(item, indexKey);
170                 break;
171             }
172         }
173     }
174 
175     if (item == indexKey_.end()) {
176         indexKey_.emplace_back(indexKey);
177         itemIndex++;
178     }
179 
180     keyCount_++;
181     itemIndex += static_cast<uint32_t>(sectionIndex_);
182     if (circleMode_) {
183         itemIndex--;
184     }
185 
186     return itemIndex;
187 }
188 
RemoveIndexKey(const std::string & indexKey)189 bool IndexerItemComponent::RemoveIndexKey(const std::string& indexKey)
190 {
191     bool ret = false;
192     if (strSection_.empty()) {
193         LOGE("[indexer] RemoveIndexKey invalid strSection_");
194         return ret;
195     }
196 
197     if (strSection_ == INDEXER_STR_SHARP) {
198         return RemoveIndexKeyForSharp(indexKey);
199     }
200 
201     if (indexKey.empty()) {
202         LOGE("[indexer] RemoveIndexKey NULL index key");
203         return ret;
204     }
205 
206     if (!IsCorrectItem(indexKey)) {
207         LOGE("[indexer] RemoveIndexKey  index key does not match section");
208         return ret;
209     }
210 
211     auto it = indexKey_.begin();
212     for (; it != indexKey_.end(); ++it) {
213         if (indexKey == *it) {
214             indexKey_.erase(it);
215             keyCount_--;
216             ret = true;
217             break;
218         }
219     }
220 
221     return ret;
222 }
223 
RemoveIndexKeyForSharp(const std::string & indexKey)224 bool IndexerItemComponent::RemoveIndexKeyForSharp(const std::string& indexKey)
225 {
226     bool ret = false;
227 
228     if (strSection_ != INDEXER_STR_SHARP) {
229         LOGE("[indexer] RemoveIndexKeyForSharp the section key is not #, section:%{public}s",
230             StringUtils::Str16ToStr8(strSection_).c_str());
231         return ret;
232     }
233 
234     auto item = indexKey_.begin();
235     if (indexKey.empty()) {
236         // remove NULL key
237         for (; item != indexKey_.end(); ++item) {
238             if (item->empty()) {
239                 indexKey_.erase(item);
240                 keyCount_--;
241                 ret = true;
242                 break;
243             }
244         }
245     } else {
246         // remove number key
247         for (; item != indexKey_.end(); ++item) {
248             if (indexKey == *item) {
249                 indexKey_.erase(item);
250                 keyCount_--;
251                 ret = true;
252                 break;
253             }
254         }
255     }
256 
257     return ret;
258 }
259 
PrintIndexerItem() const260 void IndexerItemComponent::PrintIndexerItem() const
261 {
262     int count = 1;
263     LOGI("[indexer] label:%{public}s section:%{public}s %{public}d",
264         StringUtils::Str16ToStr8(strLabel_).c_str(), StringUtils::Str16ToStr8(strSection_).c_str(), sectionIndex_);
265     for (auto it = indexKey_.begin(); it != indexKey_.end(); ++it) {
266         if (circleMode_) {
267             LOGI("[indexer] key:%{public}s %{public}d", it->c_str(), sectionIndex_ + count - 1);
268         } else {
269             LOGI("[indexer] key:%{public}s %{public}d", it->c_str(), sectionIndex_ + count);
270         }
271         count++;
272     }
273 }
274 
SetTextStyle(bool active)275 void IndexerItemComponent::SetTextStyle(bool active)
276 {
277     if (!text_) {
278         LOGE("[indexer] Get child text failed.");
279         return;
280     }
281     if (active) {
282         text_->SetTextStyle(activeStyle_);
283     } else {
284         text_->SetTextStyle(normalStyle_);
285     }
286 }
287 
288 } // namespace OHOS::Ace
289