• 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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_TEXT_OVERLAY_TEXT_OVERLAY_MANAGER_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_TEXT_OVERLAY_TEXT_OVERLAY_MANAGER_H
18 
19 #ifdef USE_ROSEN_DRAWING
20 #include "core/components_ng/render/drawing_forward.h"
21 #endif
22 #include "core/components/common/layout/constants.h"
23 #include "core/components/common/properties/color.h"
24 #include "frameworks/base/geometry/offset.h"
25 #include "frameworks/base/geometry/rect.h"
26 #include "frameworks/base/memory/ace_type.h"
27 #include "frameworks/core/common/ime/text_editing_value.h"
28 #include "frameworks/core/pipeline/base/overlay_show_option.h"
29 
30 namespace OHOS::Rosen {
31 class Typography;
32 }
33 
34 #ifndef USE_ROSEN_DRAWING
35 class SkCanvas;
36 #endif
37 
38 namespace OHOS::Ace {
39 
40 class RenderNode;
41 class Animator;
42 class StackElement;
43 class PipelineContext;
44 class TextOverlayComponent;
45 class TextOverlayManager;
46 
47 enum class CursorPositionType {
48     NONE = 0,
49     END,      // end of paragraph
50     BOUNDARY, // boundary of LTR and RTL
51     NORMAL,
52 };
53 
54 enum class DirectionStatus : uint8_t {
55     LEFT_LEFT = 0, // System direction is LTR, text direction is LTR.
56     LEFT_RIGHT,
57     RIGHT_LEFT,
58     RIGHT_RIGHT,
59 };
60 
61 // Describe where caret is and how tall visually.
62 struct CaretMetrics {
ResetCaretMetrics63     void Reset()
64     {
65         offset.Reset();
66         height = 0.0;
67     }
68 
69     Offset offset;
70     // When caret is close to different glyphs, the height will be different.
71     double height = 0.0;
ToStringCaretMetrics72     std::string ToString() const
73     {
74         std::string result = "Offset: ";
75         result += offset.ToString();
76         result += ", height: ";
77         result += std::to_string(height);
78         return result;
79     }
80 };
81 
82 class TextOverlayBase : public virtual AceType {
83     DECLARE_ACE_TYPE(TextOverlayBase, AceType);
84 
85 public:
86     TextOverlayBase() = default;
87     ~TextOverlayBase() override;
88 
SetUpdateHandlePosition(const std::function<void (const OverlayShowOption &)> & updateHandlePosition)89     void SetUpdateHandlePosition(const std::function<void(const OverlayShowOption&)>& updateHandlePosition)
90     {
91         updateHandlePosition_ = updateHandlePosition;
92     }
93 
SetUpdateHandleDiameter(const std::function<void (const double &)> & updateHandleDiameter)94     void SetUpdateHandleDiameter(const std::function<void(const double&)>& updateHandleDiameter)
95     {
96         updateHandleDiameter_ = updateHandleDiameter;
97     }
98 
SetUpdateHandleDiameterInner(const std::function<void (const double &)> & updateHandleDiameterInner)99     void SetUpdateHandleDiameterInner(const std::function<void(const double&)>& updateHandleDiameterInner)
100     {
101         updateHandleDiameterInner_ = updateHandleDiameterInner;
102     }
103 
SetOnClipRectChanged(const std::function<void (const Rect &)> & onClipRectChanged)104     void SetOnClipRectChanged(const std::function<void(const Rect&)>& onClipRectChanged)
105     {
106         onClipRectChanged_ = onClipRectChanged;
107     }
108 
IsSelectiveDevice()109     static bool IsSelectiveDevice()
110     {
111         return (SystemProperties::GetDeviceType() != DeviceType::TV &&
112                 SystemProperties::GetDeviceType() != DeviceType::WATCH);
113     }
114 
MarkIsOverlayShowed(bool isOverlayShowed)115     void MarkIsOverlayShowed(bool isOverlayShowed)
116     {
117         isOverlayShowed_ = isOverlayShowed;
118     }
119 
IsOverlayShowed()120     bool IsOverlayShowed() const
121     {
122         return isOverlayShowed_;
123     }
124 
GetSelectedRect()125     const std::vector<Rect>& GetSelectedRect() const
126     {
127         return selectedRect_;
128     }
129 
GetSelectHeight()130     double GetSelectHeight() const
131     {
132         return selectHeight_;
133     }
134 
135     void ChangeSelection(int32_t start, int32_t end);
136     void InitAnimation(const WeakPtr<PipelineContext>& pipelineContext);
137     bool GetCaretRect(int32_t extent, Rect& caretRect, double caretHeightOffset = 0.0) const;
138 #ifndef USE_ROSEN_DRAWING
139     void PaintSelection(SkCanvas* canvas, const Offset& globalOffset);
140 #else
141     void PaintSelection(RSCanvas* canvas, const Offset& globalOffset);
142 #endif
143     virtual void InitSelection(const Offset& pos, const Offset& globalOffset);
144     virtual void UpdateStartSelection(int32_t end, const Offset& pos, const Offset& globalOffset);
145     virtual void UpdateEndSelection(int32_t start, const Offset& pos, const Offset& globalOffset);
146     virtual void ShowTextOverlay(const Offset& showOffset) = 0;
147     virtual void RegisterCallbacksToOverlay() = 0;
148     virtual Offset GetHandleOffset(int32_t extend) = 0;
149     virtual std::string GetSelectedContent() const = 0;
150     RefPtr<TextOverlayManager> GetTextOverlayManager(const WeakPtr<PipelineContext>& pipelineContext);
151     bool IsSelectedText(const Offset& pos, const Offset& globalOffset);
152 
153 protected:
154     std::shared_ptr<Rosen::Typography> paragraph_;
155     CursorPositionType cursorPositionType_ = CursorPositionType::NORMAL;
156     DirectionStatus directionStatus_ = DirectionStatus::LEFT_LEFT;
157     Offset clickOffset_;
158     // For ensuring caret is visible on screen, we take a strategy that move the whole text painting area.
159     // It maybe seems rough, and doesn't support scrolling smoothly.
160     Offset textOffsetForShowCaret_;
161     // An outline for caret. It is used by default when the actual size cannot be retrieved.
162     Rect caretProto_;
163     Rect textOverlayPaintRect_;
164     Color selectedColor_ = Color(0x330a59f7);
165     double selectHeight_ = 0.0;
166     // Default to the start of text (according to RTL/LTR).
167     TextAlign textAlign_ = TextAlign::START;
168     // RTL/LTR is inherit from parent.
169     TextDirection defaultTextDirection_ = TextDirection::INHERIT;
170     TextDirection realTextDirection_ = TextDirection::INHERIT;
171     TextAffinity textAffinity_ = TextAffinity::DOWNSTREAM;
172     TextEditingValue textValue_;
173     std::string textForDisplay_;
174     int32_t cursorPositionForShow_ = 0;
175     double cursorWidth_ = 0.0;     // The unit is px.
176     bool isOverlayShowed_ = false; // Whether overlay has showed.
177     RefPtr<Animator> animator_;
178     std::function<void(const OverlayShowOption&)> updateHandlePosition_;
179     std::function<void(const double&)> updateHandleDiameter_;
180     std::function<void(const double&)> updateHandleDiameterInner_;
181     std::function<void(const Rect&)> onClipRectChanged_;
182     RefPtr<TextOverlayComponent> textOverlay_;
183     std::vector<Rect> selectedRect_;
184 
185 private:
186     Offset MakeEmptyOffset() const;
187     double GetBoundaryOfParagraph(bool isLeftBoundary) const;
188     bool ComputeOffsetForCaretUpstream(int32_t extent, CaretMetrics& result) const;
189     bool ComputeOffsetForCaretDownstream(int32_t extent, CaretMetrics& result) const;
190     bool ComputeOffsetForCaretCloserToClick(int32_t extent, CaretMetrics& result) const;
191     DirectionStatus GetDirectionStatusOfPosition(int32_t position) const;
192     int32_t GetCursorPositionForClick(const Offset& offset, const Offset& globalOffset);
193     int32_t GetGraphemeClusterLength(int32_t extend, bool isPrefix) const;
194 };
195 
196 class PipelineContext;
197 class TextOverlayManager : public virtual AceType {
198     DECLARE_ACE_TYPE(TextOverlayManager, AceType);
199 
200 public:
201     explicit TextOverlayManager(const WeakPtr<PipelineContext>& context);
202     ~TextOverlayManager() override;
203 
SetTextOverlayBase(const WeakPtr<TextOverlayBase> & textOverlayBase)204     void SetTextOverlayBase(const WeakPtr<TextOverlayBase>& textOverlayBase)
205     {
206         textOverlayBase_ = textOverlayBase;
207     }
208 
GetTextOverlayBase()209     const RefPtr<TextOverlayBase> GetTextOverlayBase() const
210     {
211         auto textOverlayBase = textOverlayBase_.Upgrade();
212         if (!textOverlayBase) {
213             return nullptr;
214         }
215         return textOverlayBase;
216     }
217 
GetTextOverlayRect()218     const std::vector<Rect>& GetTextOverlayRect() const
219     {
220         return textOverlayRect_;
221     }
222 
AddTextOverlayRect(const Rect & textOverlayRect)223     void AddTextOverlayRect(const Rect& textOverlayRect)
224     {
225         textOverlayRect_.emplace_back(textOverlayRect);
226     }
227 
ClearTextOverlayRect()228     void ClearTextOverlayRect()
229     {
230         textOverlayRect_.clear();
231     }
232 
233     // Coordinate offset is used to calculate the local location of the touch point in the event manager.
SetCoordinateOffset(const Offset & coordinateOffset)234     void SetCoordinateOffset(const Offset& coordinateOffset)
235     {
236         coordinateOffset_ = coordinateOffset;
237     }
238 
239     // Gets the coordinate offset to calculate the local location of the touch point by manually.
GetCoordinateOffset()240     const Offset& GetCoordinateOffset() const
241     {
242         return coordinateOffset_;
243     }
244 
245     const RefPtr<RenderNode> GetTargetNode() const;
246     void PopTextOverlay();
247     void PushTextOverlayToStack(
248         const RefPtr<TextOverlayComponent>& textOverlay, const WeakPtr<PipelineContext>& context);
249 
250     void HandleCtrlC() const;
251 
252 private:
253     WeakPtr<TextOverlayBase> textOverlayBase_;
254     WeakPtr<StackElement> stackElement_;
255     WeakPtr<PipelineContext> context_;
256     std::vector<Rect> textOverlayRect_;
257     Offset coordinateOffset_;
258 };
259 
260 } // namespace OHOS::Ace
261 
262 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_TEXT_OVERLAY_TEXT_OVERLAY_MANAGER_H
263