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 
17 #include "core/components/box/drag_drop_event.h"
18 
19 #include "core/components/container_modal/container_modal_constants.h"
20 #include "core/gestures/long_press_recognizer.h"
21 #include "core/gestures/pan_recognizer.h"
22 #include "core/gestures/sequenced_recognizer.h"
23 #include "core/pipeline/base/render_node.h"
24 
25 namespace OHOS::Ace {
26 
27 namespace {
28 
29 constexpr int32_t DEFAULT_FINGERS = 1;
30 constexpr int32_t DEFAULT_DURATION = 450;
31 constexpr int32_t DEFAULT_DISTANCE = 5;
32 
33 }; // namespace
34 
CreateDragDropRecognizer(const WeakPtr<PipelineContext> & pipelineContext)35 void DragDropEvent::CreateDragDropRecognizer(const WeakPtr<PipelineContext>& pipelineContext)
36 {
37     if (dragDropGesture_) {
38         return;
39     }
40 
41     auto context = pipelineContext.Upgrade();
42     if (!context) {
43         return;
44     }
45 
46     auto longPressRecognizer = AceType::MakeRefPtr<OHOS::Ace::LongPressRecognizer>(
47         context, DEFAULT_DURATION, DEFAULT_FINGERS, false, true, false);
48     longPressRecognizer->SetOnAction(std::bind(&DragDropEvent::LongPressOnAction, this, std::placeholders::_1));
49     PanDirection panDirection;
50     auto panRecognizer =
51         AceType::MakeRefPtr<OHOS::Ace::PanRecognizer>(context, DEFAULT_FINGERS, panDirection, DEFAULT_DISTANCE);
52     panRecognizer->SetOnActionStart(std::bind(&DragDropEvent::PanOnActionStart, this, std::placeholders::_1));
53     panRecognizer->SetOnActionUpdate(std::bind(&DragDropEvent::PanOnActionUpdate, this, std::placeholders::_1));
54     panRecognizer->SetOnActionEnd(std::bind(&DragDropEvent::PanOnActionEnd, this, std::placeholders::_1));
55     panRecognizer->SetOnActionCancel(std::bind(&DragDropEvent::PanOnActionCancel, this));
56 
57     std::vector<RefPtr<GestureRecognizer>> recognizers { longPressRecognizer, panRecognizer };
58     dragDropGesture_ = AceType::MakeRefPtr<OHOS::Ace::SequencedRecognizer>(pipelineContext, recognizers);
59     dragDropGesture_->SetIsExternalGesture(true);
60 }
61 
LongPressOnAction(const GestureEvent & info)62 void DragDropEvent::LongPressOnAction(const GestureEvent& info)
63 {
64     startPoint_ = info.GetGlobalPoint();
65 }
66 
FindDragDropNode(const RefPtr<PipelineContext> & context,const GestureEvent & info)67 RefPtr<DragDropEvent> DragDropEvent::FindDragDropNode(const RefPtr<PipelineContext>& context, const GestureEvent& info)
68 {
69     if (!context) {
70         return nullptr;
71     }
72 
73     auto pageRenderNode = context->GetLastPageRender();
74     if (!pageRenderNode) {
75         return nullptr;
76     }
77     auto offset = context->GetStageRect().GetOffset();
78     auto targetRenderNode = pageRenderNode->FindDropChild(info.GetGlobalPoint(), info.GetGlobalPoint() - offset);
79     if (!targetRenderNode) {
80         return nullptr;
81     }
82     return AceType::DynamicCast<DragDropEvent>(targetRenderNode);
83 }
84 
AddDataToClipboard(const RefPtr<PipelineContext> & context,const std::string & extraInfo,const std::string & selectedText,const std::string & imageSrc)85 void DragDropEvent::AddDataToClipboard(const RefPtr<PipelineContext>& context, const std::string& extraInfo,
86     const std::string& selectedText, const std::string& imageSrc)
87 {
88     auto seleItemSizeStr = JsonUtil::Create(true);
89     seleItemSizeStr->Put("width", selectedItemSize_.Width());
90     seleItemSizeStr->Put("height", selectedItemSize_.Height());
91     seleItemSizeStr->Put("customDragInfo", extraInfo.c_str());
92     seleItemSizeStr->Put("selectedText", selectedText.c_str());
93     seleItemSizeStr->Put("imageSrc", imageSrc.c_str());
94     MergeClipboardData(context, seleItemSizeStr->ToString());
95 }
96 
MergeClipboardData(const RefPtr<PipelineContext> & context,const std::string & newData)97 void DragDropEvent::MergeClipboardData(const RefPtr<PipelineContext>& context, const std::string& newData)
98 {
99     if (!clipboard_) {
100         clipboard_ = ClipboardProxy::GetInstance()->GetClipboard(context->GetTaskExecutor());
101     }
102     if (!clipboardCallback_) {
103         auto callback = [weakDragDropNode = WeakClaim(this), addData = newData](const std::string& data) {
104             auto dragDropNode = weakDragDropNode.Upgrade();
105             if (dragDropNode) {
106                 auto clipboardAllData = JsonUtil::Create(true);
107                 clipboardAllData->Put("preData", data.c_str());
108                 clipboardAllData->Put("newData", addData.c_str());
109                 dragDropNode->clipboard_->SetData(clipboardAllData->ToString(), CopyOptions::Local, true);
110             }
111         };
112         clipboardCallback_ = callback;
113     }
114     clipboard_->GetData(clipboardCallback_);
115 }
116 
RestoreCilpboardData(const RefPtr<PipelineContext> & context)117 void DragDropEvent::RestoreCilpboardData(const RefPtr<PipelineContext>& context)
118 {
119     if (!clipboard_) {
120         clipboard_ = ClipboardProxy::GetInstance()->GetClipboard(context->GetTaskExecutor());
121     }
122 
123     if (!deleteDataCallback_) {
124         auto callback = [weakDragDropNode = WeakClaim(this)](const std::string& data) {
125             auto dragDropNode = weakDragDropNode.Upgrade();
126             if (dragDropNode) {
127                 auto json = JsonUtil::ParseJsonString(data);
128                 dragDropNode->clipboard_->SetData(json->GetString("preData"));
129             }
130         };
131         deleteDataCallback_ = callback;
132     }
133     clipboard_->GetData(deleteDataCallback_);
134 }
135 
UpdatePoint(const RefPtr<PipelineContext> & context,const Point & prePoint)136 Point DragDropEvent::UpdatePoint(const RefPtr<PipelineContext>& context, const Point& prePoint)
137 {
138     if (!context) {
139         return prePoint;
140     }
141 
142     auto isContainerModal = context->GetWindowModal() == WindowModal::CONTAINER_MODAL &&
143         context->GetWindowManager()->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING;
144     Point newPoint;
145     if (isContainerModal) {
146         newPoint.SetX(prePoint.GetX() - CONTAINER_BORDER_WIDTH.ConvertToPx() - CONTENT_PADDING.ConvertToPx());
147         newPoint.SetY(prePoint.GetY() - CONTAINER_TITLE_HEIGHT.ConvertToPx());
148     } else {
149         newPoint = prePoint;
150     }
151     return newPoint;
152 }
153 
154 } // namespace OHOS::Ace
155