• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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/container_modal/container_modal_component.h"
17 
18 #include "base/utils/system_properties.h"
19 #include "core/components/box/box_component.h"
20 #include "core/components/button/button_component.h"
21 #include "core/components/clip/clip_component.h"
22 #include "core/components/container_modal/container_modal_constants.h"
23 #include "core/components/container_modal/container_modal_element.h"
24 #include "core/components/container_modal/render_container_modal.h"
25 #include "core/components/image/image_component.h"
26 #include "core/components/padding/padding_component.h"
27 #include "core/components/text/text_component.h"
28 #include "core/components/tween/tween_component.h"
29 #include "core/components_v2/inspector/inspector_composed_component.h"
30 #include "core/components_v2/inspector/inspector_constants.h"
31 #include "core/gestures/pan_gesture.h"
32 
33 namespace OHOS::Ace {
34 namespace {
35 constexpr int32_t ROOT_DECOR_BASE = 3100000;
36 constexpr int32_t TITLE_ROW = ROOT_DECOR_BASE;
37 constexpr int32_t FLOATING_TITLE_ROW = ROOT_DECOR_BASE + 1;
38 constexpr int32_t TITLE_LABEL = ROOT_DECOR_BASE + 2;
39 constexpr int32_t FLOATING_TITLE_LABEL = ROOT_DECOR_BASE + 3;
40 constexpr int32_t WINDOW_SPLIT_BUTTON = ROOT_DECOR_BASE + 4;
41 constexpr int32_t WINDOW_MAX_RECOVER_BUTTON = ROOT_DECOR_BASE + 6;
42 constexpr int32_t WINDOW_MINIMIZE_BUTTON = ROOT_DECOR_BASE + 8;
43 constexpr int32_t WINDOW_CLOSE_BUTTON = ROOT_DECOR_BASE + 10;
44 constexpr int32_t WINDOW_BUTTON_INVALID = ROOT_DECOR_BASE + 12;
45 
46 const std::string SPLIT_LEFT_KEY = "container_modal_split_left_button";
47 const std::string MAXIMIZE_KEY = "container_modal_maximize_button";
48 const std::string MINIMIZE_KEY = "container_modal_minimize_button";
49 const std::string CLOSE_KEY = "container_modal_close_button";
50 }  // namespace
51 
Create(const WeakPtr<PipelineContext> & context,const RefPtr<Component> & child)52 RefPtr<Component> ContainerModalComponent::Create(
53     const WeakPtr<PipelineContext>& context, const RefPtr<Component>& child)
54 {
55     auto component = AceType::MakeRefPtr<ContainerModalComponent>(context);
56     component->SetChild(child);
57     component->BuildInnerChild();
58     return component;
59 }
60 
CreateElement()61 RefPtr<Element> ContainerModalComponent::CreateElement()
62 {
63     return AceType::MakeRefPtr<ContainerModalElement>();
64 }
65 
CreateRenderNode()66 RefPtr<RenderNode> ContainerModalComponent::CreateRenderNode()
67 {
68     return RenderContainerModal::Create();
69 }
70 
BuildTitle()71 RefPtr<Component> ContainerModalComponent::BuildTitle()
72 {
73     // build title box
74     auto titleBox = AceType::MakeRefPtr<BoxComponent>();
75     titleBox->SetHeight(CONTAINER_TITLE_HEIGHT);
76 
77     // BuildTitleChildren need this
78     CreateAccessibilityNode(DOM_FLEX_ROW, TITLE_ROW, -1);
79 
80     auto titleChildrenRow =
81         AceType::MakeRefPtr<RowComponent>(FlexAlign::FLEX_START, FlexAlign::CENTER, BuildTitleChildren(false));
82 
83     // handle touch move and mouse move
84     PanDirection panDirection;
85     panDirection.type = PanDirection::ALL;
86     auto panGesture =
87         AceType::MakeRefPtr<PanGesture>(DEFAULT_PAN_FINGER, panDirection, DEFAULT_PAN_DISTANCE.ConvertToPx());
88     panGesture->SetOnActionStartId([contextWptr = context_](const GestureEvent&) {
89         auto context = contextWptr.Upgrade();
90         if (context) {
91             LOGI("container window start move.");
92             context->GetWindowManager()->WindowStartMove();
93         }
94     });
95     titleBox->AddGesture(GesturePriority::Low, panGesture);
96     titleBox->SetChild(titleChildrenRow);
97 
98     if (isDeclarative_) {
99         return AceType::MakeRefPtr<DisplayComponent>(AceType::MakeRefPtr<V2::InspectorComposedComponent>(
100             V2::InspectorComposedComponent::GenerateId(), V2::ROW_COMPONENT_TAG, titleBox));
101     } else {
102         return AceType::MakeRefPtr<DisplayComponent>(
103             AceType::MakeRefPtr<ComposedComponent>(std::to_string(TITLE_ROW), DOM_FLEX_ROW, titleBox));
104     }
105 }
106 
BuildFloatingTitle()107 RefPtr<Component> ContainerModalComponent::BuildFloatingTitle()
108 {
109     // build floating title box
110     auto titleDecoration = AceType::MakeRefPtr<Decoration>();
111     titleDecoration->SetBackgroundColor(CONTAINER_BACKGROUND_COLOR);
112 
113     auto titleBox = AceType::MakeRefPtr<BoxComponent>();
114     titleBox->SetHeight(CONTAINER_TITLE_HEIGHT);
115     titleBox->SetBackDecoration(titleDecoration);
116 
117     CreateAccessibilityNode(DOM_FLEX_ROW, FLOATING_TITLE_ROW, -1);
118 
119     auto floatingTitleChildrenRow =
120         AceType::MakeRefPtr<RowComponent>(FlexAlign::FLEX_START, FlexAlign::CENTER, BuildTitleChildren(true));
121     titleBox->SetChild(floatingTitleChildrenRow);
122     if (isDeclarative_) {
123         return AceType::MakeRefPtr<TweenComponent>(
124             "ContainerModal", AceType::MakeRefPtr<V2::InspectorComposedComponent>(
125                                   V2::InspectorComposedComponent::GenerateId(), V2::ROW_COMPONENT_TAG, titleBox));
126     } else {
127         return AceType::MakeRefPtr<TweenComponent>("ContainerModal",
128             AceType::MakeRefPtr<ComposedComponent>(std::to_string(FLOATING_TITLE_ROW), DOM_FLEX_ROW, titleBox));
129     }
130 }
131 
BuildContent()132 RefPtr<Component> ContainerModalComponent::BuildContent()
133 {
134     auto contentBox = AceType::MakeRefPtr<BoxComponent>();
135     contentBox->SetChild(GetChild());
136     auto contentDecoration = AceType::MakeRefPtr<Decoration>();
137     auto context = context_.Upgrade();
138     if (context) {
139         contentDecoration->SetBackgroundColor(context->GetAppBgColor());
140     }
141     contentBox->SetBackDecoration(contentDecoration);
142 
143     auto clip = AceType::MakeRefPtr<ClipComponent>(contentBox);
144     clip->SetClipRadius(Radius(CONTAINER_INNER_RADIUS));
145     clip->SetFlexWeight(1.0);
146     return clip;
147 }
148 
BuildControlButton(InternalResource::ResourceId icon,std::function<void ()> && clickCallback,bool isFocus,bool isFloating)149 RefPtr<Component> ContainerModalComponent::BuildControlButton(
150     InternalResource::ResourceId icon, std::function<void()>&& clickCallback, bool isFocus, bool isFloating)
151 {
152     static std::unordered_map<InternalResource::ResourceId, std::pair<int32_t, std::string>> controlButtonIdMap = {
153         { InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_SPLIT_LEFT, { WINDOW_SPLIT_BUTTON, SPLIT_LEFT_KEY } },
154         { InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_DEFOCUS_SPLIT_LEFT,
155             { WINDOW_SPLIT_BUTTON, SPLIT_LEFT_KEY } },
156         { InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_RECOVER, { WINDOW_MAX_RECOVER_BUTTON, MAXIMIZE_KEY } },
157         { InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_MAXIMIZE, { WINDOW_MAX_RECOVER_BUTTON, MAXIMIZE_KEY } },
158         { InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_DEFOCUS_RECOVER,
159             { WINDOW_MAX_RECOVER_BUTTON, MAXIMIZE_KEY } },
160         { InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_DEFOCUS_MAXIMIZE,
161             { WINDOW_MAX_RECOVER_BUTTON, MAXIMIZE_KEY } },
162         { InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_MINIMIZE, { WINDOW_MINIMIZE_BUTTON, MINIMIZE_KEY } },
163         { InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_DEFOCUS_MINIMIZE,
164             { WINDOW_MINIMIZE_BUTTON, MINIMIZE_KEY } },
165         { InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_CLOSE, { WINDOW_CLOSE_BUTTON, CLOSE_KEY } },
166         { InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_DEFOCUS_CLOSE, { WINDOW_CLOSE_BUTTON, CLOSE_KEY } },
167     };
168 
169     auto image = AceType::MakeRefPtr<ImageComponent>(icon);
170     image->SetWidth(TITLE_ICON_SIZE);
171     image->SetHeight(TITLE_ICON_SIZE);
172     image->SetFocusable(false);
173     std::list<RefPtr<Component>> btnChildren;
174     btnChildren.emplace_back(image);
175 
176     auto button = AceType::MakeRefPtr<ButtonComponent>(btnChildren);
177     button->SetWidth(TITLE_BUTTON_SIZE);
178     button->SetHeight(TITLE_BUTTON_SIZE);
179     button->SetType(ButtonType::CIRCLE);
180     button->SetBackgroundColor(isFocus ? TITLE_BUTTON_BACKGROUND_COLOR : TITLE_BUTTON_BACKGROUND_COLOR_LOST_FOCUS);
181     button->SetClickedColor(TITLE_BUTTON_CLICKED_COLOR);
182     button->SetClickFunction(std::move(clickCallback));
183     button->SetFocusable(false);
184     std::string buttonKey = "";
185     auto iter = controlButtonIdMap.find(icon);
186     if (iter != controlButtonIdMap.end()) {
187         buttonKey = (iter->second).second;
188     }
189     button->SetInspectorKey(buttonKey.c_str());
190     if (!isDeclarative_) {
191         auto buttonId = WINDOW_BUTTON_INVALID;
192         auto iter = controlButtonIdMap.find(icon);
193         if (iter != controlButtonIdMap.end()) {
194             buttonId = isFloating ? (iter->second).first + 1 : (iter->second).first;
195         }
196         CreateAccessibilityNode(DOM_NODE_TAG_BUTTON, buttonId, isFloating ? FLOATING_TITLE_ROW : TITLE_ROW);
197         return AceType::MakeRefPtr<ComposedComponent>(std::to_string(buttonId), DOM_NODE_TAG_BUTTON, button);
198     } else {
199         return AceType::MakeRefPtr<V2::InspectorComposedComponent>(
200             V2::InspectorComposedComponent::GenerateId(), V2::BUTTON_COMPONENT_TAG, button);
201     }
202 }
203 
SetPadding(const RefPtr<Component> & component,const Dimension & leftPadding,const Dimension & rightPadding)204 RefPtr<Component> ContainerModalComponent::SetPadding(
205     const RefPtr<Component>& component, const Dimension& leftPadding, const Dimension& rightPadding)
206 {
207     auto paddingComponent = AceType::MakeRefPtr<PaddingComponent>();
208     paddingComponent->SetPaddingLeft(leftPadding);
209     paddingComponent->SetPaddingRight(rightPadding);
210     paddingComponent->SetPaddingTop((CONTAINER_TITLE_HEIGHT - TITLE_BUTTON_SIZE) / 2);
211     paddingComponent->SetPaddingBottom((CONTAINER_TITLE_HEIGHT - TITLE_BUTTON_SIZE) / 2);
212     paddingComponent->SetChild(component);
213     return paddingComponent;
214 }
215 
216 // Build ContainerModal FA structure
BuildInnerChild()217 void ContainerModalComponent::BuildInnerChild()
218 {
219     Border outerBorder;
220     outerBorder.SetBorderRadius(Radius(CONTAINER_OUTER_RADIUS));
221     outerBorder.SetColor(CONTAINER_BORDER_COLOR);
222     outerBorder.SetWidth(CONTAINER_BORDER_WIDTH);
223     auto containerDecoration = AceType::MakeRefPtr<Decoration>();
224     containerDecoration->SetBackgroundColor(CONTAINER_BACKGROUND_COLOR);
225     containerDecoration->SetBorder(outerBorder);
226 
227     auto column =
228         AceType::MakeRefPtr<ColumnComponent>(FlexAlign::FLEX_START, FlexAlign::CENTER, std::list<RefPtr<Component>>());
229     column->AppendChild(BuildTitle());
230     column->AppendChild(BuildContent());
231     std::list<RefPtr<Component>> stackChildren;
232     stackChildren.emplace_back(column);
233     stackChildren.emplace_back(BuildFloatingTitle());
234     auto stackComponent = AceType::MakeRefPtr<StackComponent>(
235         Alignment::TOP_LEFT, StackFit::INHERIT, Overflow::OBSERVABLE, stackChildren);
236 
237     auto containerBox = AceType::MakeRefPtr<BoxComponent>();
238     containerBox->SetBackDecoration(containerDecoration);
239     containerBox->SetFlex(BoxFlex::FLEX_X);
240     containerBox->SetAlignment(Alignment::CENTER);
241 
242     Edge padding = Edge(CONTENT_PADDING, Dimension(0.0), CONTENT_PADDING, CONTENT_PADDING);
243     containerBox->SetPadding(padding);
244     containerBox->SetChild(stackComponent);
245     SetChild(containerBox);
246 }
247 
BuildTitleChildren(bool isFloating,bool isFocus,bool isFullWindow)248 std::list<RefPtr<Component>> ContainerModalComponent::BuildTitleChildren(bool isFloating, bool isFocus,
249     bool isFullWindow)
250 {
251     // title icon
252     if (!titleIcon_) {
253         titleIcon_ = AceType::MakeRefPtr<ImageComponent>();
254         titleIcon_->SetWidth(TITLE_ICON_SIZE);
255         titleIcon_->SetHeight(TITLE_ICON_SIZE);
256         titleIcon_->SetFocusable(false);
257     }
258 
259     // title text
260     if (!titleLabel_) {
261         titleLabel_ = AceType::MakeRefPtr<TextComponent>("");
262     }
263     TextStyle style;
264     style.SetFontSize(TITLE_TEXT_FONT_SIZE);
265     style.SetMaxLines(1);
266     style.SetTextColor(isFocus ? TITLE_TEXT_COLOR : TITLE_TEXT_COLOR_LOST_FOCUS);
267     style.SetFontWeight(FontWeight::W500);
268     style.SetAllowScale(false);
269     style.SetTextOverflow(TextOverflow::ELLIPSIS);
270     titleLabel_->SetTextStyle(style);
271     titleLabel_->SetFlexWeight(1.0);
272 
273     CreateAccessibilityNode(DOM_NODE_TAG_TEXT, isFloating ? FLOATING_TITLE_LABEL : TITLE_LABEL,
274         isFloating ? FLOATING_TITLE_ROW : TITLE_ROW);
275 
276     // title control button
277     auto windowManager = context_.Upgrade()->GetWindowManager();
278     auto leftSplitButton = isFocus ? InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_SPLIT_LEFT
279                                    : InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_DEFOCUS_SPLIT_LEFT;
280     auto titleLeftSplitButton = BuildControlButton(leftSplitButton, [windowManager]() {
281             if (windowManager) {
282                 LOGI("left split button clicked");
283                 windowManager->FireWindowSplitCallBack();
284             }
285         }, isFocus, isFloating);
286     auto maxRecoverButton = isFloating && isFullWindow ? InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_RECOVER
287                                                        : InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_MAXIMIZE;
288     if (!isFocus) {
289         maxRecoverButton = isFloating && isFullWindow ?
290             InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_DEFOCUS_RECOVER :
291             InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_DEFOCUS_MAXIMIZE;
292     }
293     auto titleMaximizeRecoverButton = BuildControlButton(maxRecoverButton, [windowManager]() {
294             if (windowManager) {
295                 auto mode = windowManager->GetWindowMode();
296                 if (mode == WindowMode::WINDOW_MODE_FULLSCREEN) {
297                     LOGI("recover button clicked");
298                     windowManager->WindowRecover();
299                 } else {
300                     LOGI("maximize button clicked");
301                     windowManager->WindowMaximize();
302                 }
303             }
304         }, isFocus, isFloating);
305     auto minimizeButton = isFocus ? InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_MINIMIZE
306                                   : InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_DEFOCUS_MINIMIZE;
307     auto titleMinimizeButton = BuildControlButton(minimizeButton, [windowManager]() {
308             if (windowManager) {
309                 LOGI("minimize button clicked");
310                 windowManager->WindowMinimize();
311             }
312         }, isFocus, isFloating);
313     auto closeButton = isFocus ? InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_CLOSE
314                                : InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_DEFOCUS_CLOSE;
315     auto titleCloseButton = BuildControlButton(closeButton, [windowManager]() {
316             if (windowManager) {
317                 LOGI("close button clicked");
318                 windowManager->WindowClose();
319             }
320         }, isFocus, isFloating);
321     std::list<RefPtr<Component>> titleChildren;
322     titleChildren.emplace_back(SetPadding(titleIcon_, TITLE_PADDING_START, TITLE_ELEMENT_MARGIN_HORIZONTAL));
323     if (isDeclarative_) {
324         auto inspectorTitle = AceType::MakeRefPtr<V2::InspectorComposedComponent>(
325             V2::InspectorComposedComponent::GenerateId(), V2::TEXT_COMPONENT_TAG, titleLabel_);
326         inspectorTitle->MarkNeedUpdate();
327         titleChildren.emplace_back(inspectorTitle);
328     } else {
329         titleChildren.emplace_back(AceType::MakeRefPtr<ComposedComponent>(
330             isFloating ? std::to_string(FLOATING_TITLE_LABEL) : std::to_string(TITLE_LABEL), DOM_NODE_TAG_TEXT,
331             titleLabel_));
332     }
333     auto rightPadding = SystemProperties::GetDeviceAccess() ? TITLE_ELEMENT_MARGIN_HORIZONTAL_ACCESS_DEVICE
334                                                             : TITLE_ELEMENT_MARGIN_HORIZONTAL;
335     if (!hideSplit_) {
336         titleChildren.emplace_back(SetPadding(titleLeftSplitButton, ZERO_PADDING, rightPadding));
337     }
338     if (!hideMaximize_) {
339         titleChildren.emplace_back(
340             SetPadding(titleMaximizeRecoverButton, ZERO_PADDING, rightPadding));
341     }
342     if (!hideMinimize_) {
343         titleChildren.emplace_back(SetPadding(titleMinimizeButton, ZERO_PADDING, rightPadding));
344     }
345     titleChildren.emplace_back(SetPadding(titleCloseButton, ZERO_PADDING, TITLE_PADDING_END));
346     return titleChildren;
347 }
348 
CreateAccessibilityNode(const std::string & tag,int32_t nodeId,int32_t parentNodeId)349 void ContainerModalComponent::CreateAccessibilityNode(const std::string& tag, int32_t nodeId, int32_t parentNodeId)
350 {
351     auto context = context_.Upgrade();
352     if (context != nullptr && !isDeclarative_) {
353         auto accessibilityManager = context->GetAccessibilityManager();
354         if (accessibilityManager) {
355             accessibilityManager->CreateAccessibilityNode(tag, nodeId, parentNodeId, -1);
356         }
357     }
358 }
359 
360 } // namespace OHOS::Ace