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