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