• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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_ng/pattern/container_modal/enhance/container_modal_view_enhance.h"
17 
18 #include "core/components/theme/advanced_pattern_theme.h"
19 #include "core/components_ng/base/view_stack_processor.h"
20 #include "core/components_ng/pattern/container_modal/container_modal_utils.h"
21 #include "core/components_ng/pattern/container_modal/enhance/container_modal_pattern_enhance.h"
22 #include "core/components_ng/pattern/image/image_pattern.h"
23 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
24 #include "core/components_ng/pattern/stack/stack_pattern.h"
25 #include "core/components_v2/inspector/inspector_constants.h"
26 
27 namespace OHOS::Ace::NG {
28 namespace {
29 constexpr int32_t INVALID_LISTENER_ID = -1;
30 }
31 
32 /**
33  * The structure of container_modal enhanced is designed as follows :
34  * |--container_modal(stack)
35  *   |--column
36  *      |--container_modal_custom_title(row)
37  *          |--custom_node(js)
38  *      |--stack
39  *          |--container_modal_content(stage)
40  *              |--page
41  *          |--dialog(when show)
42  *      |--gesture_row(row)
43  *   |--container_modal_custom_floating_title(row)
44  *          |--custom_node(js)
45  *   |--container_modal_control_buttons(row)
46  *          |--[maxRecover, minimize, close](button)
47  */
48 
OnContainerModalEvent(RefPtr<PipelineContext> pipelineContext,const std::string & name,const std::string & value)49 void ContainerModalViewEnhance::OnContainerModalEvent(
50     RefPtr<PipelineContext> pipelineContext, const std::string& name, const std::string& value)
51 {
52     CHECK_NULL_VOID(pipelineContext);
53     auto rootNode = pipelineContext->GetRootElement();
54     CHECK_NULL_VOID(rootNode);
55     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode->GetFirstChild());
56     CHECK_NULL_VOID(containerNode);
57     auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
58     CHECK_NULL_VOID(containerPattern);
59     containerPattern->OnContainerModalEvent(name, value);
60 }
61 
Create(RefPtr<FrameNode> & content)62 RefPtr<FrameNode> ContainerModalViewEnhance::Create(RefPtr<FrameNode>& content)
63 {
64     auto containerModalNode = FrameNode::CreateFrameNode("ContainerModal",
65         ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ContainerModalPatternEnhance>());
66     auto stack = FrameNode::CreateFrameNode(
67         V2::STACK_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<StackPattern>());
68     auto column = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
69         AceType::MakeRefPtr<LinearLayoutPattern>(true));
70     auto controlButtonsRow = FrameNode::CreateFrameNode(
71         V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<LinearLayoutPattern>(false));
72 
73     column->AddChild(BuildTitle(containerModalNode));
74     stack->AddChild(content);
75     column->AddChild(stack);
76     column->AddChild(BuildGestureRow(containerModalNode));
77     auto containerPattern = containerModalNode->GetPattern<ContainerModalPatternEnhance>();
78     CHECK_NULL_RETURN(containerPattern, nullptr);
79     containerModalNode->AddChild(column);
80     containerModalNode->AddChild(BuildTitle(containerModalNode, true));
81 
82     // Confirm that if it is a pure Cangjie application, the node construction is completed on the C side
83     if (customControlButtonBuilder_) {
84         WeakPtr<ContainerModalPatternEnhance> weakPattern =
85             controlButtonsRow->GetPattern<ContainerModalPatternEnhance>();
86         containerModalNode->AddChild(customControlButtonBuilder_(weakPattern, controlButtonsRow));
87     } else {
88         containerModalNode->AddChild(BuildCustomButtonRow(controlButtonsRow));
89     }
90     containerPattern->Init();
91     return containerModalNode;
92 }
93 
BuildCustomButtonRow(RefPtr<FrameNode> & containerRow)94 RefPtr<FrameNode> ContainerModalViewEnhance::BuildCustomButtonRow(RefPtr<FrameNode>& containerRow)
95 {
96     TAG_LOGI(AceLogTag::ACE_APPBAR, "ContainerModalViewEnhance BuildCustomButtonRow called");
97     CHECK_NULL_RETURN(containerRow, nullptr);
98     auto isSucc = ExecuteCustomTitleAbc();
99     if (!isSucc) {
100         return nullptr;
101     }
102     auto customNode = NG::ViewStackProcessor::GetInstance()->GetCustomButtonNode();
103     containerRow->AddChild(customNode);
104     return containerRow;
105 }
106 
BuildTitle(RefPtr<FrameNode> & containerNode,bool isFloatingTitle)107 RefPtr<FrameNode> ContainerModalViewEnhance::BuildTitle(RefPtr<FrameNode>& containerNode, bool isFloatingTitle)
108 {
109     TAG_LOGI(AceLogTag::ACE_APPBAR, "ContainerModalViewEnhance BuildTitle called");
110     auto titleRow = BuildTitleContainer(containerNode, isFloatingTitle);
111     CHECK_NULL_RETURN(titleRow, nullptr);
112     return titleRow;
113 }
114 
AddControlButtons(RefPtr<FrameNode> & containerNode,RefPtr<FrameNode> & containerTitleRow)115 RefPtr<FrameNode> ContainerModalViewEnhance::AddControlButtons(
116     RefPtr<FrameNode>& containerNode, RefPtr<FrameNode>& containerTitleRow)
117 {
118     WeakPtr<ContainerModalPatternEnhance> weakPattern = containerNode->GetPattern<ContainerModalPatternEnhance>();
119     RefPtr<FrameNode> maximizeBtn = BuildControlButton(
120         InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_MAXIMIZE, [weakPattern](GestureEvent& info) {
121             auto pattern = weakPattern.Upgrade();
122             CHECK_NULL_VOID(pattern);
123             pattern->OnMaxButtonClick(info);
124         });
125     maximizeBtn->UpdateInspectorId("EnhanceMaximizeBtn");
126 
127     // add long press event
128     WeakPtr<FrameNode> weakMaximizeBtn = maximizeBtn;
129     auto longPressCallback = [weakPattern, weakMaximizeBtn](GestureEvent& info) {
130         auto pattern = weakPattern.Upgrade();
131         CHECK_NULL_VOID(pattern);
132         auto maximizeBtn = weakMaximizeBtn.Upgrade();
133         CHECK_NULL_VOID(maximizeBtn);
134         pattern->ShowMaxMenu(maximizeBtn);
135     };
136     // diable mouse left!
137     auto hub = maximizeBtn->GetOrCreateGestureEventHub();
138     auto longPressEvent = AceType::MakeRefPtr<LongPressEvent>(longPressCallback);
139     hub->SetLongPressEvent(longPressEvent, false, true);
140 
141     auto eventHub = maximizeBtn->GetOrCreateInputEventHub();
142     auto hoverMoveFuc = [weakPattern](MouseInfo& info) {
143         auto pattern = weakPattern.Upgrade();
144         CHECK_NULL_VOID(pattern);
145         pattern->OnMaxBtnInputEvent(info);
146     };
147     eventHub->AddOnMouseEvent(AceType::MakeRefPtr<InputEvent>(std::move(hoverMoveFuc)));
148 
149     // add hover in out event
150     auto hoverEventFuc = [weakPattern, weakMaximizeBtn](bool hover) mutable {
151         auto pattern = weakPattern.Upgrade();
152         CHECK_NULL_VOID(pattern);
153         pattern->OnMaxBtnHoverEvent(hover, weakMaximizeBtn);
154     };
155     eventHub->AddOnHoverEvent(AceType::MakeRefPtr<InputEvent>(std::move(hoverEventFuc)));
156     containerTitleRow->AddChild(maximizeBtn);
157 
158     RefPtr<FrameNode> minimizeBtn = BuildControlButton(
159         InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_MINIMIZE, [weakPattern](GestureEvent& info) {
160             auto pattern = weakPattern.Upgrade();
161             CHECK_NULL_VOID(pattern);
162             pattern->OnMinButtonClick(info);
163         });
164     // minimizeBtn add empty panEvent to over fater container event
165     minimizeBtn->UpdateInspectorId("EnhanceMinimizeBtn");
166     containerTitleRow->AddChild(minimizeBtn);
167 
168     RefPtr<FrameNode> closeBtn = BuildControlButton(
169         InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_CLOSE,
170         [weakPattern](GestureEvent& info) {
171             auto pattern = weakPattern.Upgrade();
172             CHECK_NULL_VOID(pattern);
173             pattern->OnCloseButtonClick(info);
174         },
175         true);
176     // closeBtn add empty panEvent to over fater container event
177     closeBtn->UpdateInspectorId("EnhanceCloseBtn");
178     containerTitleRow->AddChild(closeBtn);
179 
180     return containerTitleRow;
181 }
182 
BuildMenuItemIcon(InternalResource::ResourceId resourceId)183 RefPtr<FrameNode> ContainerModalViewEnhance::BuildMenuItemIcon(InternalResource::ResourceId resourceId)
184 {
185     auto icon = FrameNode::CreateFrameNode(
186         V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ImagePattern>());
187     auto iconLayoutProperty = icon->GetLayoutProperty<ImageLayoutProperty>();
188     ImageSourceInfo sourceInfo;
189     sourceInfo.SetResourceId(resourceId);
190     auto theme = PipelineContext::GetCurrentContextSafelyWithCheck()->GetTheme<AdvancedPatternTheme>();
191     if (theme) {
192         sourceInfo.SetFillColor(theme->GetPrimaryColor());
193     } else {
194         TAG_LOGI(AceLogTag::ACE_APPBAR, "BuildMenuItemIcon AdvancedPatternTheme is null");
195     }
196     iconLayoutProperty->UpdateImageSourceInfo(sourceInfo);
197     iconLayoutProperty->UpdateUserDefinedIdealSize(
198         CalcSize(CalcLength(TITLE_BUTTON_SIZE), CalcLength(TITLE_BUTTON_SIZE)));
199     icon->MarkModifyDone();
200     return icon;
201 }
202 
BuildGestureRow(RefPtr<FrameNode> & containerNode)203 RefPtr<FrameNode> ContainerModalViewEnhance::BuildGestureRow(RefPtr<FrameNode>& containerNode)
204 {
205     auto pattern = containerNode->GetPattern<ContainerModalPatternEnhance>();
206     auto gestureRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
207         AceType::MakeRefPtr<LinearLayoutPattern>(false));
208     auto renderContext = gestureRow->GetRenderContext();
209     renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
210     renderContext->UpdatePosition(OffsetT<Dimension>());
211     auto layoutProp = gestureRow->GetLayoutProperty();
212     layoutProp->UpdateUserDefinedIdealSize(
213         CalcSize(CalcLength(1.0, DimensionUnit::PERCENT), CalcLength(CONTAINER_TITLE_HEIGHT)));
214     return gestureRow;
215 }
216 
GetContainerModalComponentRect(PipelineContext * pipelineContext,RectF & floatContainerModal,RectF & floatButtons)217 bool ContainerModalViewEnhance::GetContainerModalComponentRect(
218     PipelineContext* pipelineContext, RectF& floatContainerModal, RectF& floatButtons)
219 {
220     CHECK_NULL_RETURN(pipelineContext, false);
221     auto rootNode = pipelineContext->GetRootElement();
222     CHECK_NULL_RETURN(rootNode, false);
223     auto containerMode = AceType::DynamicCast<NG::FrameNode>(rootNode->GetChildren().front());
224     CHECK_NULL_RETURN(containerMode, false);
225     auto pattern = containerMode->GetPattern<NG::ContainerModalPatternEnhance>();
226     CHECK_NULL_RETURN(pattern, false);
227     return pattern->GetContainerModalComponentRect(floatContainerModal, floatButtons);
228 }
229 
SetContainerButtonStyle(RefPtr<PipelineContext> pipeline,const Ace::DecorButtonStyle & buttonStyle)230 void ContainerModalViewEnhance::SetContainerButtonStyle(RefPtr<PipelineContext> pipeline,
231     const Ace::DecorButtonStyle& buttonStyle)
232 {
233     CHECK_NULL_VOID(pipeline);
234     if (!pipeline || pipeline->GetWindowModal() != WindowModal::CONTAINER_MODAL) {
235         return;
236     }
237     auto rootNode = pipeline->GetRootElement();
238     CHECK_NULL_VOID(rootNode);
239     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode->GetChildren().front());
240     CHECK_NULL_VOID(containerNode);
241     auto containerPattern = containerNode->GetPattern<ContainerModalPatternEnhance>();
242     CHECK_NULL_VOID(containerPattern);
243     auto controlButtonsNode = containerPattern->GetCustomButtonNode();
244     CHECK_NULL_VOID(controlButtonsNode);
245     controlButtonsNode->FireCustomCallback(EVENT_NAME_BUTTON_SPACING_CHANGE,
246         std::to_string(buttonStyle.spacingBetweenButtons));
247     controlButtonsNode->FireCustomCallback(EVENT_NAME_BUTTON_SIZE_CHANGE,
248         std::to_string(buttonStyle.buttonBackgroundSize));
249     controlButtonsNode->FireCustomCallback(EVENT_NAME_COLOR_CONFIGURATION_LOCKED,
250         std::to_string(buttonStyle.colorMode));
251     if (buttonStyle.colorMode != static_cast<int32_t>(ColorMode::DARK) &&
252         buttonStyle.colorMode != static_cast<int32_t>(ColorMode::LIGHT)) {
253         containerPattern->OnColorConfigurationUpdate();
254     }
255     controlButtonsNode->FireCustomCallback(
256         EVENT_NAME_BUTTON_RIGHT_OFFSET_CHANGE, std::to_string(buttonStyle.closeButtonRightMargin));
257     controlButtonsNode->FireCustomCallback(EVENT_NAME_BUTTON_ICON_SIZE_CHANGE,
258         std::to_string(buttonStyle.buttonIconSize));
259     controlButtonsNode->FireCustomCallback(EVENT_NAME_BUTTON_BACKGROUND_CORNER_RADIUS_CHANGE,
260         std::to_string(buttonStyle.buttonBackgroundCornerRadius));
261     containerPattern->CallButtonsRectChange();
262 }
263 
AddButtonsRectChangeListener(PipelineContext * context,ButtonsRectChangeListener && listener)264 int32_t ContainerModalViewEnhance::AddButtonsRectChangeListener(
265     PipelineContext* context, ButtonsRectChangeListener&& listener)
266 {
267     CHECK_NULL_RETURN(context, INVALID_LISTENER_ID);
268     auto rootNode = context->GetRootElement();
269     CHECK_NULL_RETURN(rootNode, INVALID_LISTENER_ID);
270     auto children = rootNode->GetChildren();
271     if (children.empty()) {
272         return INVALID_LISTENER_ID;
273     }
274     auto containerNode = AceType::DynamicCast<FrameNode>(children.front());
275     CHECK_NULL_RETURN(containerNode, INVALID_LISTENER_ID);
276     auto pattern = containerNode->GetPattern<ContainerModalPatternEnhance>();
277     CHECK_NULL_RETURN(pattern, INVALID_LISTENER_ID);
278     return pattern->AddButtonsRectChangeListener(std::move(listener));
279 }
280 
RemoveButtonsRectChangeListener(PipelineContext * context,int32_t id)281 void ContainerModalViewEnhance::RemoveButtonsRectChangeListener(PipelineContext* context, int32_t id)
282 {
283     CHECK_NULL_VOID(context);
284     auto rootNode = context->GetRootElement();
285     CHECK_NULL_VOID(rootNode);
286     auto children = rootNode->GetChildren();
287     if (children.empty()) {
288         return;
289     }
290     auto containerNode = AceType::DynamicCast<FrameNode>(children.front());
291     CHECK_NULL_VOID(containerNode);
292     auto pattern = containerNode->GetPattern<ContainerModalPatternEnhance>();
293     CHECK_NULL_VOID(pattern);
294     pattern->RemoveButtonsRectChangeListener(id);
295 }
296 
GetContainerModalTitleVisible(RefPtr<PipelineContext> pipeline,bool isImmersive)297 bool ContainerModalViewEnhance::GetContainerModalTitleVisible(RefPtr<PipelineContext> pipeline, bool isImmersive)
298 {
299     if (pipeline->GetWindowModal() != WindowModal::CONTAINER_MODAL) {
300         return false;
301     }
302     auto rootNode = pipeline->GetRootElement();
303     CHECK_NULL_RETURN(rootNode, false);
304     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode->GetFirstChild());
305     CHECK_NULL_RETURN(containerNode, false);
306     auto containerModalPattern = containerNode->GetPattern<ContainerModalPattern>();
307     CHECK_NULL_RETURN(containerModalPattern, false);
308     return containerModalPattern->GetContainerModalTitleVisible(isImmersive);
309 }
310 } // namespace OHOS::Ace::NG
311