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 "frameworks/bridge/common/dom/dom_calendar.h"
17
18 #include "base/utils/string_utils.h"
19 #include "frameworks/bridge/common/utils/utils.h"
20
21 namespace OHOS::Ace::Framework {
22 namespace {
23
24 constexpr uint32_t METHOD_GO_TO_ARGS_SIZE = 1;
25 const char GO_TO_ARG_KEY_YEAR[] = "year";
26 const char GO_TO_ARG_KEY_MONTH[] = "month";
27 const char GO_TO_ARG_KEY_DAY[] = "day";
28
29 } // namespace
30
DomCalendar(NodeId nodeId,const std::string & nodeName)31 DomCalendar::DomCalendar(NodeId nodeId, const std::string& nodeName)
32 : DOMNode(nodeId, nodeName),
33 calendarComponent_(AceType::MakeRefPtr<CalendarComponent>(std::to_string(nodeId), nodeName))
34 {
35 if (IsRightToLeft()) {
36 calendarComponent_->SetTextDirection(TextDirection::RTL);
37 }
38 }
39
SetSpecializedAttr(const std::pair<std::string,std::string> & attr)40 bool DomCalendar::SetSpecializedAttr(const std::pair<std::string, std::string>& attr)
41 {
42 static const LinearMapNode<bool (*)(const std::string&, DomCalendar&)> calendarAttrOperators[] = {
43 { DOM_CALENDAR_DATA,
44 [](const std::string& value, DomCalendar& calendar) {
45 calendar.calendarComponent_->SetCalendarData(value);
46 return true;
47 } },
48 { DOM_CALENDAR_CARD_CALENDAR,
49 [](const std::string& value, DomCalendar& calendar) {
50 calendar.calendarComponent_->SetCardCalendar(StringToBool(value));
51 return true;
52 } },
53 { DOM_CALENDAR_DATE,
54 [](const std::string& value, DomCalendar& calendar) {
55 CalendarDay day;
56 auto isLegal = StringUtils::StringToCalendarDay(value, day);
57 if (isLegal) {
58 calendar.calendarComponent_->SetCalendarDate(day);
59 return true;
60 }
61 return false;
62 } },
63 { DOM_CALENDAR_DATE_ADAPTER,
64 [](const std::string& value, DomCalendar& calendar) { return calendar.ParseDataAdapter(value); } },
65 { DOM_CALENDAR_DIRECTION,
66 [](const std::string& value, DomCalendar& calendar) {
67 if (value == "vertical") {
68 calendar.calendarComponent_->SetAxis(Axis::VERTICAL);
69 } else if (value == "horizontal") {
70 calendar.calendarComponent_->SetAxis(Axis::HORIZONTAL);
71 } else {
72 LOGE("input do not match any direction");
73 }
74 return true;
75 } },
76 { DOM_CALENDAR_HOLIDAYS,
77 [](const std::string& value, DomCalendar& calendar) {
78 calendar.calendarComponent_->SetHolidays(value);
79 return true;
80 } },
81 { DOM_CALENDAR_OFF_DAYS,
82 [](const std::string& value, DomCalendar& calendar) {
83 calendar.calendarComponent_->SetOffDays(value);
84 return true;
85 } },
86 { DOM_CALENDAR_SHOW_HOLIDAY,
87 [](const std::string& value, DomCalendar& calendar) {
88 calendar.calendarComponent_->SetShowHoliday(StringToBool(value));
89 return true;
90 } },
91 { DOM_CALENDAR_SHOW_LUNAR,
92 [](const std::string& value, DomCalendar& calendar) {
93 calendar.calendarComponent_->SetShowLunar(StringToBool(value));
94 return true;
95 } },
96 { DOM_CALENDAR_START_DAY_OF_WEEK,
97 [](const std::string& value, DomCalendar& calendar) {
98 auto indexOfWeek = StringToInt(value);
99 if (0 <= indexOfWeek && indexOfWeek < 7) {
100 calendar.calendarComponent_->SetStartDayOfWeek(indexOfWeek);
101 return true;
102 }
103 return false;
104 } },
105 { DOM_CALENDAR_TYPE,
106 [](const std::string& value, DomCalendar& calendar) {
107 if (value == "normal") {
108 calendar.calendarComponent_->SetCalendarType(CalendarType::NORMAL);
109 } else if (value == "simple") {
110 calendar.calendarComponent_->SetCalendarType(CalendarType::SIMPLE);
111 }
112 return true;
113 } },
114 { DOM_CALENDAR_WORK_DAYS,
115 [](const std::string& value, DomCalendar& calendar) {
116 calendar.calendarComponent_->SetWorkDays(value);
117 return true;
118 } },
119 };
120 auto operatorIter =
121 BinarySearchFindIndex(calendarAttrOperators, ArraySize(calendarAttrOperators), attr.first.c_str());
122 if (operatorIter != -1) {
123 return calendarAttrOperators[operatorIter].value(attr.second, *this);
124 }
125 return false;
126 }
127
CallSpecializedMethod(const std::string & method,const std::string & args)128 void DomCalendar::CallSpecializedMethod(const std::string& method, const std::string& args)
129 {
130 if (method == DOM_CALENDAR_METHOD_GO_TO) {
131 HandleGoTo(args);
132 }
133 }
134
AddSpecializedEvent(int32_t pageId,const std::string & event)135 bool DomCalendar::AddSpecializedEvent(int32_t pageId, const std::string& event)
136 {
137 if (event == DOM_CALENDAR_EVENT_SELECTED_CHANGE) {
138 selectedChangeEvent_ = EventMarker(GetNodeIdForEvent(), event, pageId);
139 calendarComponent_->SetSelectedChangeEvent(selectedChangeEvent_);
140 return true;
141 } else if (event == DOM_CALENDAR_EVENT_REQUEST_DATA) {
142 requestDataEvent_ = EventMarker(GetNodeIdForEvent(), event, pageId);
143 calendarComponent_->SetRequestDataEvent(requestDataEvent_);
144 return true;
145 }
146 return false;
147 }
148
ParseDataAdapter(const std::string & value)149 bool DomCalendar::ParseDataAdapter(const std::string& value)
150 {
151 std::unique_ptr<JsonValue> dataAdapterValue = JsonUtil::ParseJsonString(value);
152 if (!dataAdapterValue) {
153 LOGE("data adapter format is error");
154 return false;
155 }
156 std::unique_ptr<JsonValue> bundleNameValue = dataAdapterValue->GetValue("bundleName");
157 if (!bundleNameValue || !bundleNameValue->IsString()) {
158 LOGE("get bundleName failed");
159 return false;
160 }
161 std::unique_ptr<JsonValue> abilityNameValue = dataAdapterValue->GetValue("abilityName");
162 if (!abilityNameValue || !abilityNameValue->IsString()) {
163 LOGE("get abilityName failed");
164 return false;
165 }
166 std::unique_ptr<JsonValue> messageCodeValue = dataAdapterValue->GetValue("messageCode");
167 if (!messageCodeValue || !messageCodeValue->IsNumber()) {
168 LOGE("get messageCode failed");
169 return false;
170 }
171 std::string bundleName = bundleNameValue->GetString();
172 std::string abilityName = abilityNameValue->GetString();
173 int32_t messageCode = messageCodeValue->GetInt();
174 CalendarDataAdapterAction dataAdapterAction {
175 { .bundleName = bundleName, .abilityName = abilityName, .messageCode = messageCode }
176 };
177 calendarComponent_->SetDataAdapterAction(dataAdapterAction);
178 return true;
179 }
180
HandleGoTo(const std::string & args)181 void DomCalendar::HandleGoTo(const std::string& args)
182 {
183 std::unique_ptr<JsonValue> argsValue = JsonUtil::ParseJsonString(args);
184 if (!argsValue || !argsValue->IsArray() || argsValue->GetArraySize() != METHOD_GO_TO_ARGS_SIZE) {
185 LOGE("parse args error: %{private}s", args.c_str());
186 return;
187 }
188 auto gotoArg = argsValue->GetArrayItem(0);
189 if (!gotoArg || !gotoArg->Contains(GO_TO_ARG_KEY_YEAR) || !gotoArg->Contains(GO_TO_ARG_KEY_MONTH)) {
190 LOGE("calendar goto arg no year or month");
191 return;
192 }
193
194 std::unique_ptr<JsonValue> yearValue = gotoArg->GetValue(GO_TO_ARG_KEY_YEAR);
195 if (!yearValue || !yearValue->IsNumber()) {
196 LOGE("get year failed");
197 return;
198 }
199
200 std::unique_ptr<JsonValue> monthValue = gotoArg->GetValue(GO_TO_ARG_KEY_MONTH);
201 if (!monthValue || !monthValue->IsNumber()) {
202 LOGE("get month failed");
203 return;
204 }
205 int32_t year = yearValue->GetInt();
206 int32_t month = monthValue->GetInt();
207 // default selected first day of month
208 int32_t day = -1;
209
210 std::unique_ptr<JsonValue> dayValue = gotoArg->GetValue(GO_TO_ARG_KEY_DAY);
211 if (dayValue && dayValue->IsNumber()) {
212 day = dayValue->GetInt();
213 }
214 calendarComponent_->GoTo(year, month, day);
215 }
216
SetSpecializedStyle(const std::pair<std::string,std::string> & style)217 bool DomCalendar::SetSpecializedStyle(const std::pair<std::string, std::string>& style)
218 {
219 static const LinearMapNode<void (*)(const std::string&, CalendarThemeStructure&, const DomCalendar&)>
220 calendarStyleOperators[] = {
221 { "boundaryColumnOffset",
222 [](const std::string& value, CalendarThemeStructure& theme, const DomCalendar& node) {
223 theme.boundaryColOffset = node.ParseDimension(value);
224 } },
225 { "boundaryRowOffset",
226 [](const std::string& value, CalendarThemeStructure& theme, const DomCalendar& node) {
227 theme.boundaryRowOffset = node.ParseDimension(value);
228 } },
229 { "columnSpace", [](const std::string& value, CalendarThemeStructure& theme,
230 const DomCalendar& node) { theme.colSpace = node.ParseDimension(value); } },
231 { "dailyFiveRowSpace",
232 [](const std::string& value, CalendarThemeStructure& theme, const DomCalendar& node) {
233 theme.dailyFiveRowSpace = node.ParseDimension(value);
234 } },
235 { "dailySixRowSpace",
236 [](const std::string& value, CalendarThemeStructure& theme, const DomCalendar& node) {
237 theme.dailySixRowSpace = node.ParseDimension(value);
238 } },
239 { "dayColor", [](const std::string& value, CalendarThemeStructure& theme,
240 const DomCalendar& node) { theme.dayColor = node.ParseColor(value); } },
241 { "dayFontSize", [](const std::string& value, CalendarThemeStructure& theme,
242 const DomCalendar& node) { theme.dayFontSize = node.ParseDimension(value); } },
243 { "dayHeight", [](const std::string& value, CalendarThemeStructure& theme,
244 const DomCalendar& node) { theme.dayHeight = node.ParseDimension(value); } },
245 { "dayWidth", [](const std::string& value, CalendarThemeStructure& theme,
246 const DomCalendar& node) { theme.dayWidth = node.ParseDimension(value); } },
247 { "dayYAxisOffset", [](const std::string& value, CalendarThemeStructure& theme,
248 const DomCalendar& node) { theme.dayYAxisOffset = node.ParseDimension(value); } },
249 { "focusedAreaBackgroundColor",
250 [](const std::string& value, CalendarThemeStructure& theme, const DomCalendar& node) {
251 theme.focusedAreaBackgroundColor = node.ParseColor(value);
252 } },
253 { "focusedAreaRadius",
254 [](const std::string& value, CalendarThemeStructure& theme, const DomCalendar& node) {
255 theme.focusedAreaRadius = node.ParseDimension(value);
256 } },
257 { "focusedDayColor", [](const std::string& value, CalendarThemeStructure& theme,
258 const DomCalendar& node) { theme.focusedDayColor = node.ParseColor(value); } },
259 { "focusedLunarColor", [](const std::string& value, CalendarThemeStructure& theme,
260 const DomCalendar& node) { theme.focusedLunarColor = node.ParseColor(value); } },
261 { "gregorianCalendarHeight",
262 [](const std::string& value, CalendarThemeStructure& theme, const DomCalendar& node) {
263 theme.gregorianCalendarHeight = node.ParseDimension(value);
264 } },
265 { "lunarColor", [](const std::string& value, CalendarThemeStructure& theme,
266 const DomCalendar& node) { theme.lunarColor = node.ParseColor(value); } },
267 { "lunarDayFontSize",
268 [](const std::string& value, CalendarThemeStructure& theme, const DomCalendar& node) {
269 theme.lunarDayFontSize = node.ParseDimension(value);
270 } },
271 { "lunarDayYAxisOffset",
272 [](const std::string& value, CalendarThemeStructure& theme, const DomCalendar& node) {
273 theme.lunarDayYAxisOffset = node.ParseDimension(value);
274 } },
275 { "lunarHeight", [](const std::string& value, CalendarThemeStructure& theme,
276 const DomCalendar& node) { theme.lunarHeight = node.ParseDimension(value); } },
277 { "markLunarColor", [](const std::string& value, CalendarThemeStructure& theme,
278 const DomCalendar& node) { theme.markLunarColor = node.ParseColor(value); } },
279 { "nonCurrentMonthDayColor",
280 [](const std::string& value, CalendarThemeStructure& theme, const DomCalendar& node) {
281 theme.nonCurrentMonthDayColor = node.ParseColor(value);
282 } },
283 { "nonCurrentMonthLunarColor",
284 [](const std::string& value, CalendarThemeStructure& theme, const DomCalendar& node) {
285 theme.nonCurrentMonthLunarColor = node.ParseColor(value);
286 } },
287 { "nonCurrentMonthOffDayMarkColor",
288 [](const std::string& value, CalendarThemeStructure& theme, const DomCalendar& node) {
289 theme.nonCurrentMonthOffDayMarkColor = node.ParseColor(value);
290 } },
291 { "nonCurrentMonthWorkDayMarkColor",
292 [](const std::string& value, CalendarThemeStructure& theme, const DomCalendar& node) {
293 theme.nonCurrentMonthWorkDayMarkColor = node.ParseColor(value);
294 } },
295 { "offDayMarkColor", [](const std::string& value, CalendarThemeStructure& theme,
296 const DomCalendar& node) { theme.offDayMarkColor = node.ParseColor(value); } },
297 { "offDayMarkSize", [](const std::string& value, CalendarThemeStructure& theme,
298 const DomCalendar& node) { theme.offDayMarkSize = node.ParseDimension(value); } },
299 { "scheduleMarkerRadius",
300 [](const std::string& value, CalendarThemeStructure& theme, const DomCalendar& node) {
301 theme.scheduleMarkerRadius = node.ParseDimension(value);
302 } },
303 { "scheduleMarkerXAxisOffset",
304 [](const std::string& value, CalendarThemeStructure& theme, const DomCalendar& node) {
305 theme.scheduleMarkerXAxisOffset = node.ParseDimension(value);
306 } },
307 { "scheduleMarkerYAxisOffset",
308 [](const std::string& value, CalendarThemeStructure& theme, const DomCalendar& node) {
309 theme.scheduleMarkerYAxisOffset = node.ParseDimension(value);
310 } },
311 { "simpleOffTextColor",
312 [](const std::string& value, CalendarThemeStructure& theme, const DomCalendar& node) {
313 theme.simpleOffTextColor = node.ParseColor(value);
314 } },
315 { "simpleWorkTextColor",
316 [](const std::string& value, CalendarThemeStructure& theme, const DomCalendar& node) {
317 theme.simpleWorkTextColor = node.ParseColor(value);
318 } },
319 { "underscoreLength",
320 [](const std::string& value, CalendarThemeStructure& theme, const DomCalendar& node) {
321 theme.underscoreLength = node.ParseDimension(value);
322 } },
323 { "underscoreWidth", [](const std::string& value, CalendarThemeStructure& theme,
324 const DomCalendar& node) { theme.underscoreWidth = node.ParseDimension(value); } },
325 { "underscoreXAxisOffset",
326 [](const std::string& value, CalendarThemeStructure& theme, const DomCalendar& node) {
327 theme.underscoreXAxisOffset = node.ParseDimension(value);
328 } },
329 { "underscoreYAxisOffset",
330 [](const std::string& value, CalendarThemeStructure& theme, const DomCalendar& node) {
331 theme.underscoreYAxisOffset = node.ParseDimension(value);
332 } },
333 { "weekAndDayRowSpace",
334 [](const std::string& value, CalendarThemeStructure& theme, const DomCalendar& node) {
335 theme.weekAndDayRowSpace = node.ParseDimension(value);
336 } },
337 { "weekColor", [](const std::string& value, CalendarThemeStructure& theme,
338 const DomCalendar& node) { theme.weekColor = node.ParseColor(value); } },
339 { "weekFontSize", [](const std::string& value, CalendarThemeStructure& theme,
340 const DomCalendar& node) { theme.weekFontSize = node.ParseDimension(value); } },
341 { "weekHeight", [](const std::string& value, CalendarThemeStructure& theme,
342 const DomCalendar& node) { theme.weekHeight = node.ParseDimension(value); } },
343 { "weekWidth", [](const std::string& value, CalendarThemeStructure& theme,
344 const DomCalendar& node) { theme.weekWidth = node.ParseDimension(value); } },
345 { "weekendDayColor", [](const std::string& value, CalendarThemeStructure& theme,
346 const DomCalendar& node) { theme.weekendDayColor = node.ParseColor(value); } },
347 { "weekendLunarColor", [](const std::string& value, CalendarThemeStructure& theme,
348 const DomCalendar& node) { theme.weekendLunarColor = node.ParseColor(value); } },
349 { "workDayMarkColor", [](const std::string& value, CalendarThemeStructure& theme,
350 const DomCalendar& node) { theme.workDayMarkColor = node.ParseColor(value); } },
351 { "workDayMarkSize", [](const std::string& value, CalendarThemeStructure& theme,
352 const DomCalendar& node) { theme.workDayMarkSize = node.ParseDimension(value); } },
353 { "workStateHorizontalMovingDistance",
354 [](const std::string& value, CalendarThemeStructure& theme, const DomCalendar& node) {
355 theme.workStateHorizontalMovingDistance = node.ParseDimension(value);
356 } },
357 { "workStateOffset", [](const std::string& value, CalendarThemeStructure& theme,
358 const DomCalendar& node) { theme.workStateOffset = node.ParseDimension(value); } },
359 { "workStateVerticalMovingDistance",
360 [](const std::string& value, CalendarThemeStructure& theme, const DomCalendar& node) {
361 theme.workStateVerticalMovingDistance = node.ParseDimension(value);
362 } },
363 { "workStateWidth", [](const std::string& value, CalendarThemeStructure& theme,
364 const DomCalendar& node) { theme.workStateWidth = node.ParseDimension(value); } },
365 };
366 auto context = GetPipelineContext().Upgrade();
367 if (!context) {
368 return false;
369 }
370 auto theme = calendarComponent_->GetCalendarTheme();
371 if (!theme) {
372 theme = GetTheme<CalendarTheme>();
373 calendarComponent_->SetCalendarTheme(theme);
374 }
375 auto operatorIter =
376 BinarySearchFindIndex(calendarStyleOperators, ArraySize(calendarStyleOperators), style.first.c_str());
377 if (operatorIter != -1) {
378 auto& calendarTheme = context->IsJsCard() ? theme->GetCardCalendarTheme() : theme->GetCalendarTheme();
379 calendarStyleOperators[operatorIter].value(style.second, calendarTheme, *this);
380 return true;
381 }
382 return false;
383 }
384
385 } // namespace OHOS::Ace::Framework
386