• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/declarative_frontend/jsview/js_navigation.h"
17 
18 #include "core/components/navigation_bar/navigation_bar_component_v2.h"
19 #include "core/components/navigation_bar/navigation_container_component.h"
20 #include "core/components/option/option_component.h"
21 #include "frameworks/bridge/declarative_frontend/engine/functions/js_click_function.h"
22 #include "frameworks/bridge/declarative_frontend/view_stack_processor.h"
23 
24 namespace OHOS::Ace::Framework {
25 namespace {
26 
TitleModeChangeEventToJSValue(const NavigationTitleModeChangeEvent & eventInfo)27 JSRef<JSVal> TitleModeChangeEventToJSValue(const NavigationTitleModeChangeEvent& eventInfo)
28 {
29     return JSRef<JSVal>::Make(ToJSValue(eventInfo.IsMiniBar() ? static_cast<int32_t>(NavigationTitleMode::MINI)
30                                                               : static_cast<int32_t>(NavigationTitleMode::FULL)));
31 }
32 
ParseToolBarItems(const JSRef<JSArray> & jsArray,std::list<RefPtr<ToolBarItem>> & items)33 void ParseToolBarItems(const JSRef<JSArray>& jsArray, std::list<RefPtr<ToolBarItem>>& items)
34 {
35     auto length = jsArray->Length();
36     for (size_t i = 0; i < length; i++) {
37         auto item = jsArray->GetValueAt(i);
38         if (!item->IsObject()) {
39             LOGE("tool bar item is not object");
40             continue;
41         }
42 
43         auto itemObject = JSRef<JSObject>::Cast(item);
44         auto toolBarItem = AceType::MakeRefPtr<ToolBarItem>();
45         auto itemValueObject = itemObject->GetProperty("value");
46         if (itemValueObject->IsString()) {
47             toolBarItem->value = itemValueObject->ToString();
48         }
49 
50         auto itemIconObject = itemObject->GetProperty("icon");
51         if (itemIconObject->IsString()) {
52             toolBarItem->icon = itemIconObject->ToString();
53         }
54 
55         auto itemActionValue = itemObject->GetProperty("action");
56         if (itemActionValue->IsFunction()) {
57             auto onClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(itemActionValue));
58             toolBarItem->action = EventMarker(
59                 [func = std::move(onClickFunc)]() {
60                     ACE_SCORING_EVENT("Navigation.toolBarItemClick");
61                     func->Execute();
62                 });
63             auto onClickWithParamFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(itemActionValue));
64             toolBarItem->actionWithParam = EventMarker(
65                 [func = std::move(onClickWithParamFunc)](const BaseEventInfo* info) {
66                     ACE_SCORING_EVENT("Navigation.menuItemButtonClick");
67                     func->Execute();
68                 });
69         }
70         items.push_back(toolBarItem);
71     }
72 }
73 
74 } // namespace
75 
Create()76 void JSNavigation::Create()
77 {
78     auto navigationContainer = AceType::MakeRefPtr<NavigationContainerComponent>();
79     ViewStackProcessor::GetInstance()->Push(navigationContainer);
80 }
81 
JSBind(BindingTarget globalObj)82 void JSNavigation::JSBind(BindingTarget globalObj)
83 {
84     JSClass<JSNavigation>::Declare("Navigation");
85     MethodOptions opt = MethodOptions::NONE;
86     JSClass<JSNavigation>::StaticMethod("create", &JSNavigation::Create, opt);
87     JSClass<JSNavigation>::StaticMethod("title", &JSNavigation::SetTitle, opt);
88     JSClass<JSNavigation>::StaticMethod("subTitle", &JSNavigation::SetSubTitle, opt);
89     JSClass<JSNavigation>::StaticMethod("titleMode", &JSNavigation::SetTitleMode, opt);
90     JSClass<JSNavigation>::StaticMethod("hideTitleBar", &JSNavigation::SetHideTitleBar, opt);
91     JSClass<JSNavigation>::StaticMethod("hideBackButton", &JSNavigation::SetHideBackButton, opt);
92     JSClass<JSNavigation>::StaticMethod("hideToolBar", &JSNavigation::SetHideToolBar, opt);
93     JSClass<JSNavigation>::StaticMethod("toolBar", &JSNavigation::SetToolBar);
94     JSClass<JSNavigation>::StaticMethod("menus", &JSNavigation::SetMenus);
95     JSClass<JSNavigation>::StaticMethod("menuCount", &JSNavigation::SetMenuCount);
96     // keep compatible, need remove after
97     JSClass<JSNavigation>::StaticMethod("onTitleModeChanged", &JSNavigation::SetOnTitleModeChanged);
98     JSClass<JSNavigation>::StaticMethod("onTitleModeChange", &JSNavigation::SetOnTitleModeChanged);
99     JSClass<JSNavigation>::Inherit<JSContainerBase>();
100     JSClass<JSNavigation>::Inherit<JSViewAbstract>();
101     JSClass<JSNavigation>::Bind(globalObj);
102 }
103 
SetTitle(const JSCallbackInfo & info)104 void JSNavigation::SetTitle(const JSCallbackInfo& info)
105 {
106     if (info.Length() < 1) {
107         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
108         return;
109     }
110     auto component = ViewStackProcessor::GetInstance()->GetMainComponent();
111     auto navigationContainer = AceType::DynamicCast<OHOS::Ace::NavigationContainerComponent>(component);
112     if (!navigationContainer) {
113         LOGI("component is not navigationContainer.");
114         return;
115     }
116 
117     if (info[0]->IsString()) {
118         navigationContainer->GetDeclaration()->title = info[0]->ToString();
119     } else if (info[0]->IsObject()) {
120         auto builderObject = JSRef<JSObject>::Cast(info[0])->GetProperty("builder");
121         if (builderObject->IsFunction()) {
122             ScopedViewStackProcessor builderViewStackProcessor;
123             JsFunction jsBuilderFunc(info.This(), JSRef<JSObject>::Cast(builderObject));
124             ACE_SCORING_EVENT("Navigation.title.builder");
125             jsBuilderFunc.Execute();
126             auto customTile = ViewStackProcessor::GetInstance()->Finish();
127 #if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM)
128                     auto composedComponent =
129                         ViewStackProcessor::GetInstance()->CreateInspectorWrapper("NavigationTitle");
130                     composedComponent->SetChild(customTile);
131                     navigationContainer->GetDeclaration()->customTitle = composedComponent;
132 #else
133                     navigationContainer->GetDeclaration()->customTitle = customTile;
134 #endif
135         }
136     } else {
137         LOGE("arg is not [String|Function].");
138     }
139 }
140 
SetTitleMode(int32_t value)141 void JSNavigation::SetTitleMode(int32_t value)
142 {
143     if ((value == static_cast<int32_t>(NavigationTitleMode::FREE)) ||
144         (value == static_cast<int32_t>(NavigationTitleMode::FULL)) ||
145         (value == static_cast<int32_t>(NavigationTitleMode::MINI))) {
146         auto component = ViewStackProcessor::GetInstance()->GetMainComponent();
147         auto navigationContainer = AceType::DynamicCast<OHOS::Ace::NavigationContainerComponent>(component);
148         if (navigationContainer) {
149             navigationContainer->GetDeclaration()->titleMode = static_cast<NavigationTitleMode>(value);
150         }
151     } else {
152         LOGE("invalid value for titleMode");
153     }
154 }
155 
SetSubTitle(const std::string & subTitle)156 void JSNavigation::SetSubTitle(const std::string& subTitle)
157 {
158     auto component = ViewStackProcessor::GetInstance()->GetMainComponent();
159     auto navigationContainer = AceType::DynamicCast<OHOS::Ace::NavigationContainerComponent>(component);
160     if (navigationContainer) {
161         navigationContainer->GetDeclaration()->subTitle = subTitle;
162     }
163 }
164 
SetHideTitleBar(bool hide)165 void JSNavigation::SetHideTitleBar(bool hide)
166 {
167     auto component = ViewStackProcessor::GetInstance()->GetMainComponent();
168     auto navigationContainer = AceType::DynamicCast<OHOS::Ace::NavigationContainerComponent>(component);
169     if (navigationContainer) {
170         auto declaration = navigationContainer->GetDeclaration();
171         declaration->hideBar = hide;
172         declaration->animationOption = ViewStackProcessor::GetInstance()->GetImplicitAnimationOption();
173     }
174 }
175 
SetHideBackButton(bool hide)176 void JSNavigation::SetHideBackButton(bool hide)
177 {
178     auto component = ViewStackProcessor::GetInstance()->GetMainComponent();
179     auto navigationContainer = AceType::DynamicCast<OHOS::Ace::NavigationContainerComponent>(component);
180     if (navigationContainer) {
181         navigationContainer->GetDeclaration()->hideBarBackButton = hide;
182     }
183 }
184 
SetHideToolBar(bool hide)185 void JSNavigation::SetHideToolBar(bool hide)
186 {
187     auto component = ViewStackProcessor::GetInstance()->GetMainComponent();
188     auto navigationContainer = AceType::DynamicCast<OHOS::Ace::NavigationContainerComponent>(component);
189     if (navigationContainer) {
190         auto declaration = navigationContainer->GetDeclaration();
191         declaration->hideToolbar = hide;
192         declaration->animationOption = ViewStackProcessor::GetInstance()->GetImplicitAnimationOption();
193     }
194 }
195 
SetToolBar(const JSCallbackInfo & info)196 void JSNavigation::SetToolBar(const JSCallbackInfo& info)
197 {
198     if (info.Length() < 1) {
199         LOGE("The arg is wrong, it is supposed to have at least one argument");
200         return;
201     }
202     auto component = ViewStackProcessor::GetInstance()->GetMainComponent();
203     auto navigationContainer = AceType::DynamicCast<OHOS::Ace::NavigationContainerComponent>(component);
204     if (!navigationContainer) {
205         LOGI("component is not navigationContainer.");
206         return;
207     }
208 
209     if (!info[0]->IsObject()) {
210         LOGE("arg is not a object.");
211         return;
212     }
213     auto builderFuncParam = JSRef<JSObject>::Cast(info[0])->GetProperty("builder");
214     if (builderFuncParam->IsFunction()) {
215         ScopedViewStackProcessor builderViewStackProcessor;
216         JsFunction jsBuilderFunc(builderFuncParam);
217         jsBuilderFunc.Execute();
218         RefPtr<Component> builderGeneratedRootComponent = ViewStackProcessor::GetInstance()->Finish();
219         navigationContainer->GetDeclaration()->toolBarBuilder = builderGeneratedRootComponent;
220         return;
221     }
222 
223     auto itemsValue = JSRef<JSObject>::Cast(info[0])->GetProperty("items");
224     if (!itemsValue->IsObject() || !itemsValue->IsArray()) {
225         LOGE("arg format error: not find items");
226         return;
227     }
228     ParseToolBarItems(JSRef<JSArray>::Cast(itemsValue), navigationContainer->GetDeclaration()->toolbarItems);
229 }
230 
SetMenus(const JSCallbackInfo & info)231 void JSNavigation::SetMenus(const JSCallbackInfo& info)
232 {
233     if (info.Length() < 1) {
234         LOGE("The arg is wrong, it is supposed to have at least one argument");
235         return;
236     }
237     auto component = ViewStackProcessor::GetInstance()->GetMainComponent();
238     auto navigationContainer = AceType::DynamicCast<OHOS::Ace::NavigationContainerComponent>(component);
239     if (!navigationContainer) {
240         LOGI("component is not navigationContainer.");
241         return;
242     }
243 
244     if (info[0]->IsArray()) {
245         ParseToolBarItems(JSRef<JSArray>::Cast(info[0]), navigationContainer->GetDeclaration()->menuItems);
246     } else if (info[0]->IsObject()) {
247         auto builderObject = JSRef<JSObject>::Cast(info[0])->GetProperty("builder");
248         if (builderObject->IsFunction()) {
249             ScopedViewStackProcessor builderViewStackProcessor;
250             JsFunction jsBuilderFunc(info.This(), JSRef<JSObject>::Cast(builderObject));
251             {
252                 ACE_SCORING_EVENT("Navigation.menu.builder");
253                 jsBuilderFunc.Execute();
254             }
255             auto customMenus = ViewStackProcessor::GetInstance()->Finish();
256 #if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM)
257                 auto composedComponent = ViewStackProcessor::GetInstance()->CreateInspectorWrapper("NavigationMenus");
258                 composedComponent->SetChild(customMenus);
259                 navigationContainer->GetDeclaration()->customMenus = composedComponent;
260 #else
261                 navigationContainer->GetDeclaration()->customMenus = customMenus;
262 #endif
263         }
264     } else {
265         LOGE("arg is not [String|Function].");
266     }
267 }
268 
SetMenuCount(int32_t menuCount)269 void JSNavigation::SetMenuCount(int32_t menuCount)
270 {
271     auto component = ViewStackProcessor::GetInstance()->GetMainComponent();
272     auto navigationContainer = AceType::DynamicCast<OHOS::Ace::NavigationContainerComponent>(component);
273     if (navigationContainer) {
274         navigationContainer->SetMenuCount(menuCount);
275     }
276 }
277 
SetOnTitleModeChanged(const JSCallbackInfo & info)278 void JSNavigation::SetOnTitleModeChanged(const JSCallbackInfo& info)
279 {
280     if (info.Length() < 1) {
281         LOGE("The arg is wrong, it is supposed to have at least one argument");
282         return;
283     }
284     if (info[0]->IsFunction()) {
285         auto changeHandler = AceType::MakeRefPtr<JsEventFunction<NavigationTitleModeChangeEvent, 1>>(
286             JSRef<JSFunc>::Cast(info[0]), TitleModeChangeEventToJSValue);
287         auto eventMarker = EventMarker([executionContext = info.GetExecutionContext(), func = std::move(changeHandler)](
288                                            const BaseEventInfo* baseInfo) {
289             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext);
290             auto eventInfo = TypeInfoHelper::DynamicCast<NavigationTitleModeChangeEvent>(baseInfo);
291             if (!eventInfo) {
292                 LOGE("HandleChangeEvent eventInfo == nullptr");
293                 return;
294             }
295             ACE_SCORING_EVENT("Navigation.onTitleModeChanged");
296             func->Execute(*eventInfo);
297         });
298         auto component = ViewStackProcessor::GetInstance()->GetMainComponent();
299         auto navigationContainer = AceType::DynamicCast<OHOS::Ace::NavigationContainerComponent>(component);
300         if (navigationContainer) {
301             navigationContainer->GetDeclaration()->titleModeChangedEvent = eventMarker;
302         }
303     }
304     info.ReturnSelf();
305 }
306 
307 } // namespace OHOS::Ace::Framework
308