1 /*
2 * Copyright (c) 2024 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_container_modal_view.h"
17 #include <cstdint>
18
19 #include "base/memory/ace_type.h"
20 #include "base/utils/utils.h"
21 #include "bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_common_bridge.h"
22 #include "core/common/ace_engine.h"
23 #include "core/components_ng/base/frame_node.h"
24 #include "core/components_ng/pattern/container_modal/enhance/container_modal_pattern_enhance.h"
25 #include "core/pipeline_ng/pipeline_context.h"
26
27 namespace OHOS::Ace::Framework {
28 namespace {
29 const std::string EVENT_NAME_CUSTOM_MAX_CLICK = "arkui_custom_max_click";
30 const std::string EVENT_NAME_MIN_CLICK = "arkui_custom_min_click";
31 const std::string EVENT_NAME_CLOSE_CLICK = "arkui_custom_close_click";
32 const std::string EVENT_NAME_PAN_EVENT = "arkui_custom_pan_event";
33 const std::string EVENT_NAME_LEFT_SPLIT_CLICK = "arkui_custom_left_split_click";
34 const std::string EVENT_NAME_RIGHT_SPLIT_CLICK = "arkui_custom_right_split_click";
35 const std::string EVENT_NAME_BUTTON_POINT_LIGHT_ANIM = "arkui_custom_button_point_light_anim";
36 const std::string EVENT_NAME_BUTTON_RECT_CHANGE = "arkui_custom_button_rect_change";
37 const std::string EVENT_NAME_MENU_WIDTH_CHANGE = "arkui_custom_menu_width_change";
38
39 const int32_t EVENT_NAME_MENU_WIDTH_CHANGE_PARAM_COUNT = 2;
40
41 static std::map<std::string, std::function<void(const JSCallbackInfo& info)>> g_nativeFuncMap;
42 } // namespace
43
OnMaxBtnClick(const JSCallbackInfo & info)44 void JSContainerModal::OnMaxBtnClick(const JSCallbackInfo& info)
45 {
46 TAG_LOGI(AceLogTag::ACE_APPBAR, "OnMaxBtnClick");
47 auto pattern = GetContainerModalPattern();
48 CHECK_NULL_VOID(pattern);
49 pattern->OnMaxButtonClick();
50 }
51
OnMinBtnClick(const JSCallbackInfo & info)52 void JSContainerModal::OnMinBtnClick(const JSCallbackInfo& info)
53 {
54 TAG_LOGI(AceLogTag::ACE_APPBAR, "OnMinBtnClick");
55 auto pattern = GetContainerModalPattern();
56 CHECK_NULL_VOID(pattern);
57 pattern->OnMinButtonClick();
58 }
59
OnCloseBtnClick(const JSCallbackInfo & info)60 void JSContainerModal::OnCloseBtnClick(const JSCallbackInfo& info)
61 {
62 TAG_LOGI(AceLogTag::ACE_APPBAR, "OnCloseBtnClick");
63 auto pattern = GetContainerModalPattern();
64 CHECK_NULL_VOID(pattern);
65 pattern->OnCloseButtonClick();
66 }
67
OnLeftSplitClick(const JSCallbackInfo & info)68 void JSContainerModal::OnLeftSplitClick(const JSCallbackInfo& info)
69 {
70 TAG_LOGI(AceLogTag::ACE_APPBAR, "OnLeftSplitClick");
71 auto pipelineContext = NG::PipelineContext::GetMainPipelineContext();
72 CHECK_NULL_VOID(pipelineContext);
73 auto rootNode = pipelineContext->GetRootElement();
74 CHECK_NULL_VOID(rootNode);
75 auto containerMode = AceType::DynamicCast<NG::FrameNode>(rootNode->GetChildren().front());
76 CHECK_NULL_VOID(containerMode);
77 auto pattern = containerMode->GetPattern<NG::ContainerModalPatternEnhance>();
78 CHECK_NULL_VOID(pattern);
79 pattern->OnMenuItemClickGesture(true);
80 }
81
OnRightSplitClick(const JSCallbackInfo & info)82 void JSContainerModal::OnRightSplitClick(const JSCallbackInfo& info)
83 {
84 TAG_LOGI(AceLogTag::ACE_APPBAR, "OnRightSplitClick");
85 auto pipelineContext = NG::PipelineContext::GetMainPipelineContext();
86 CHECK_NULL_VOID(pipelineContext);
87 auto rootNode = pipelineContext->GetRootElement();
88 CHECK_NULL_VOID(rootNode);
89 auto containerMode = AceType::DynamicCast<NG::FrameNode>(rootNode->GetChildren().front());
90 CHECK_NULL_VOID(containerMode);
91 auto pattern = containerMode->GetPattern<NG::ContainerModalPatternEnhance>();
92 CHECK_NULL_VOID(pattern);
93 pattern->OnMenuItemClickGesture(false);
94 }
95
AddButtonPointLightAnim(const JSCallbackInfo & info)96 void JSContainerModal::AddButtonPointLightAnim(const JSCallbackInfo& info)
97 {
98 TAG_LOGI(AceLogTag::ACE_APPBAR, "AddButtonPointLightAnim");
99 auto pattern = GetContainerModalPattern();
100 CHECK_NULL_VOID(pattern);
101 }
102
CallButtonsRectChange(const JSCallbackInfo & info)103 void JSContainerModal::CallButtonsRectChange(const JSCallbackInfo& info)
104 {
105 TAG_LOGI(AceLogTag::ACE_APPBAR, "CallButtonsRectChange");
106 auto pattern = GetContainerModalPattern();
107 CHECK_NULL_VOID(pattern);
108 pattern->CallButtonsRectChange();
109 pattern->InitAllTitleRowLayoutProperty();
110 }
111
CallMenuWidthChange(const JSCallbackInfo & info)112 void JSContainerModal::CallMenuWidthChange(const JSCallbackInfo& info)
113 {
114 TAG_LOGI(AceLogTag::ACE_APPBAR, "CallMenuWidthChange");
115 // second param is resource id
116 if (info.Length() < EVENT_NAME_MENU_WIDTH_CHANGE_PARAM_COUNT || !info[1]->IsString()) {
117 TAG_LOGI(AceLogTag::ACE_APPBAR, "CallMenuWidthChange param error");
118 return;
119 }
120 int32_t resId;
121 ConvertFromJSValue(info[1], resId);
122 auto pattern = GetContainerModalPattern();
123 CHECK_NULL_VOID(pattern);
124 pattern->CallMenuWidthChange(resId);
125 }
126
GetContainerModalPattern()127 RefPtr<NG::ContainerModalPatternEnhance> JSContainerModal::GetContainerModalPattern()
128 {
129 auto pipelineContext = NG::PipelineContext::GetCurrentContextPtrSafely();
130 CHECK_NULL_RETURN(pipelineContext, nullptr);
131 auto rootNode = pipelineContext->GetRootElement();
132 CHECK_NULL_RETURN(rootNode, nullptr);
133 auto containerMode = AceType::DynamicCast<NG::FrameNode>(rootNode->GetChildren().front());
134 CHECK_NULL_RETURN(containerMode, nullptr);
135 return containerMode->GetPattern<NG::ContainerModalPatternEnhance>();
136 }
137
CallWindowNative(const JSCallbackInfo & info)138 void JSContainerModal::CallWindowNative(const JSCallbackInfo& info)
139 {
140 if (info.Length() < EVENT_NAME_MENU_WIDTH_CHANGE_PARAM_COUNT) {
141 TAG_LOGI(AceLogTag::ACE_APPBAR, "CallWindowNative param error");
142 return;
143 }
144
145 if (!info[0]->IsString()) {
146 TAG_LOGI(AceLogTag::ACE_APPBAR, "CallWindowNative first param is not string");
147 return;
148 }
149
150 if (!info[1]->IsString()) {
151 TAG_LOGI(AceLogTag::ACE_APPBAR, "CallWindowNative value is error");
152 return;
153 }
154
155 TAG_LOGI(AceLogTag::ACE_APPBAR, "CallWindowNative");
156 auto pipelineContext = NG::PipelineContext::GetMainPipelineContext();
157 CHECK_NULL_VOID(pipelineContext);
158 auto rootNode = pipelineContext->GetRootElement();
159 CHECK_NULL_VOID(rootNode);
160 auto containerMode = AceType::DynamicCast<NG::FrameNode>(rootNode->GetChildren().front());
161 CHECK_NULL_VOID(containerMode);
162 auto pattern = containerMode->GetPattern<NG::ContainerModalPatternEnhance>();
163 CHECK_NULL_VOID(pattern);
164 std::string eventName = info[0]->ToString();
165 std::string value = info[1]->ToString();
166 pattern->CallContainerModalNative(eventName, value);
167 }
168
CallNative(const JSCallbackInfo & info)169 void JSContainerModal::CallNative(const JSCallbackInfo& info)
170 {
171 g_nativeFuncMap = {
172 { EVENT_NAME_CUSTOM_MAX_CLICK, JSContainerModal::OnMaxBtnClick },
173 { EVENT_NAME_MIN_CLICK, JSContainerModal::OnMinBtnClick },
174 { EVENT_NAME_CLOSE_CLICK, JSContainerModal::OnCloseBtnClick },
175 { EVENT_NAME_LEFT_SPLIT_CLICK, JSContainerModal::OnLeftSplitClick },
176 { EVENT_NAME_RIGHT_SPLIT_CLICK, JSContainerModal::OnRightSplitClick },
177 { EVENT_NAME_BUTTON_POINT_LIGHT_ANIM, JSContainerModal::AddButtonPointLightAnim },
178 { EVENT_NAME_BUTTON_RECT_CHANGE, JSContainerModal::CallButtonsRectChange },
179 { EVENT_NAME_MENU_WIDTH_CHANGE, JSContainerModal::CallMenuWidthChange },
180 };
181
182 TAG_LOGI(AceLogTag::ACE_APPBAR, "callNative");
183 if (info.Length() < 1) {
184 TAG_LOGI(AceLogTag::ACE_APPBAR, "callNative param erro");
185 return;
186 }
187 if (!info[0]->IsString()) {
188 TAG_LOGI(AceLogTag::ACE_APPBAR, "callNative first param erro");
189 return;
190 }
191 std::string eventName = info[0]->ToString();
192 if (eventName.rfind("arkui", 0) == 0) {
193 auto it = g_nativeFuncMap.find(eventName);
194 if (it == g_nativeFuncMap.end()) {
195 TAG_LOGI(AceLogTag::ACE_APPBAR, "Event not found: %{public}s", eventName.c_str());
196 return;
197 }
198 it->second(info);
199 } else {
200 CallWindowNative(info);
201 }
202 }
203
JSBind(BindingTarget globalObj)204 void JSContainerModal::JSBind(BindingTarget globalObj)
205 {
206 JSClass<JSContainerModal>::Declare("ContainerModal");
207 JSClass<JSContainerModal>::StaticMethod("callNative", &JSContainerModal::CallNative);
208 JSClass<JSContainerModal>::InheritAndBind<JSContainerBase>(globalObj);
209 }
210 } // namespace OHOS::Ace::Framework
211