1 /* 2 * Copyright (c) 2021-2023 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_NG_PATTERN_TEXT_FIELD_TEXT_SELECTOR_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TEXT_FIELD_TEXT_SELECTOR_H 18 19 #include <cstdint> 20 #include <string> 21 #include <functional> 22 23 #include "base/geometry/ng/offset_t.h" 24 #include "base/geometry/ng/rect_t.h" 25 26 // avoid windows build error about macro defined in wincon.h 27 #ifdef DOUBLE_CLICK 28 #undef DOUBLE_CLICK 29 #endif 30 31 namespace OHOS::Ace::NG { 32 33 using OnAccessibilityCallback = std::function<void()>; 34 35 enum class CaretUpdateType { 36 PRESSED, 37 LONG_PRESSED, 38 ICON_PRESSED, 39 DEL, 40 EVENT, 41 HANDLE_MOVE, 42 HANDLE_MOVE_DONE, 43 INPUT, 44 NONE, 45 RIGHT_CLICK, 46 VISIBLE_PASSWORD_ICON, 47 DOUBLE_CLICK 48 }; 49 /** 50 * Stands for selection indexes 51 * We use base/destination to indicate the start/end position because of uncertain direction. 52 */ 53 struct HandleInfo { 54 int32_t index = 0; 55 RectF rect; 56 AddRectYHandleInfo57 void AddRectY(float deltaY) 58 { 59 auto newOffset = rect.GetOffset(); 60 newOffset.AddY(deltaY); 61 rect.SetOffset(newOffset); 62 } 63 AddRectXHandleInfo64 void AddRectX(float deltaX) 65 { 66 auto newOffset = rect.GetOffset(); 67 newOffset.AddX(deltaX); 68 rect.SetOffset(newOffset); 69 } 70 }; 71 struct TextSelector { 72 TextSelector() = default; TextSelectorTextSelector73 TextSelector(int32_t base, int32_t destination) : baseOffset(base), destinationOffset(destination) {} 74 SetOnAccessibilityTextSelector75 void SetOnAccessibility(OnAccessibilityCallback&& onAccessibilityCallback) 76 { 77 if (onAccessibilityCallback) { 78 onAccessibilityCallback_ = std::move(onAccessibilityCallback); 79 } 80 } 81 FireAccessibilityCallbackTextSelector82 void FireAccessibilityCallback() const 83 { 84 if (onAccessibilityCallback_) { 85 onAccessibilityCallback_(); 86 } 87 } 88 UpdateTextSelector89 void Update(int32_t base, int32_t destination) 90 { 91 if (base == baseOffset && destination == destinationOffset) { 92 return; 93 } 94 bool isChanged = baseOffset != destinationOffset || base != destination; 95 baseOffset = base; 96 destinationOffset = destination; 97 if (isChanged) { 98 FireAccessibilityCallback(); 99 } 100 } 101 102 // Usually called when none is selected. UpdateTextSelector103 void Update(int32_t both) 104 { 105 if ((baseOffset != both) || (destinationOffset != both)) { 106 if (baseOffset != destinationOffset) { 107 FireAccessibilityCallback(); 108 } 109 } 110 baseOffset = both; 111 destinationOffset = both; 112 } 113 ReverseTextSelectorTextSelector114 void ReverseTextSelector() 115 { 116 if (baseOffset > destinationOffset) { 117 Update(destinationOffset, baseOffset); 118 } 119 } 120 121 bool operator==(const TextSelector& other) const 122 { 123 return baseOffset == other.baseOffset && destinationOffset == other.destinationOffset; 124 } 125 126 bool operator!=(const TextSelector& other) const 127 { 128 return !operator==(other); 129 } 130 GetTextStartTextSelector131 inline int32_t GetTextStart() const 132 { 133 return std::min(baseOffset, destinationOffset); 134 } 135 GetTextEndTextSelector136 inline int32_t GetTextEnd() const 137 { 138 return std::max(baseOffset, destinationOffset); 139 } 140 GetStartTextSelector141 inline int32_t GetStart() const 142 { 143 return baseOffset; 144 } 145 GetEndTextSelector146 inline int32_t GetEnd() const 147 { 148 return destinationOffset; 149 } 150 IsValidTextSelector151 inline bool IsValid() const 152 { 153 return baseOffset > -1 && destinationOffset > -1; 154 } 155 SelectNothingTextSelector156 inline bool SelectNothing() const 157 { 158 return !IsValid() || baseOffset == destinationOffset; 159 } 160 MoveSelectionLeftTextSelector161 bool MoveSelectionLeft() 162 { 163 destinationOffset = std::max(0, destinationOffset - 1); 164 return destinationOffset == baseOffset; 165 } 166 MoveSelectionRightTextSelector167 bool MoveSelectionRight() 168 { 169 destinationOffset = std::min(charCount, destinationOffset + 1); 170 return destinationOffset == baseOffset; 171 } 172 GetSelectHeightTextSelector173 double GetSelectHeight() const 174 { 175 return std::max(firstHandle.Height(), secondHandle.Height()); 176 } 177 StartEqualToDestTextSelector178 bool StartEqualToDest() const 179 { 180 return baseOffset == destinationOffset; 181 } 182 StartGreaterDestTextSelector183 bool StartGreaterDest() const 184 { 185 return baseOffset > destinationOffset; 186 } 187 ToStringTextSelector188 std::string ToString() 189 { 190 std::string result; 191 result.append("baseOffset: "); 192 result.append(std::to_string(baseOffset)); 193 result.append(", selectionBaseOffset: "); 194 result.append(selectionBaseOffset.ToString()); 195 result.append(", destinationOffset: "); 196 result.append(std::to_string(destinationOffset)); 197 result.append(", selectionDestinationOffset: "); 198 result.append(selectionDestinationOffset.ToString()); 199 result.append(", firstHandle: "); 200 result.append(firstHandle.ToString()); 201 result.append(", secondHandle: "); 202 result.append(secondHandle.ToString()); 203 result.append(", firstHandleOffset_: "); 204 result.append(firstHandleOffset_.ToString()); 205 result.append(", secondHandleOffset_: "); 206 result.append(secondHandleOffset_.ToString()); 207 return result; 208 } 209 210 // May larger than, smaller than or equal to destinationOffset. 211 int32_t baseOffset = -1; 212 OffsetF selectionBaseOffset; 213 214 // When paints caret, this is where the caret position is. 215 int32_t destinationOffset = -1; 216 OffsetF selectionDestinationOffset; 217 218 int32_t charCount = 0; 219 RectF firstHandle; 220 RectF secondHandle; 221 OffsetF firstHandleOffset_; 222 OffsetF secondHandleOffset_; 223 OnAccessibilityCallback onAccessibilityCallback_; 224 }; 225 226 enum class TextSpanType : int32_t { 227 TEXT = 0, 228 IMAGE, 229 MIXED, 230 BUILDER, 231 NONE, 232 }; 233 234 enum class TextResponseType : int32_t { 235 RIGHT_CLICK = 0, 236 LONG_PRESS, 237 SELECTED_BY_MOUSE, 238 NONE, 239 }; 240 241 enum class SelectionMenuType : int32_t { 242 SELECTION_MENU = 0, 243 PREVIEW_MENU = 1, 244 }; 245 246 struct SelectMenuParam { 247 std::function<void(int32_t, int32_t)> onAppear; 248 std::function<void()> onDisappear; 249 }; 250 251 struct SelectionMenuParams { 252 TextSpanType type; 253 std::function<void()> buildFunc; 254 std::function<void(int32_t, int32_t)> onAppear; 255 std::function<void()> onDisappear; 256 TextResponseType responseType; 257 SelectionMenuParamsSelectionMenuParams258 SelectionMenuParams(TextSpanType _type, std::function<void()> _buildFunc, 259 std::function<void(int32_t, int32_t)> _onAppear, std::function<void()> _onDisappear, 260 TextResponseType _responseType) 261 : type(_type), buildFunc(_buildFunc), onAppear(_onAppear), onDisappear(_onDisappear), 262 responseType(_responseType) 263 {} 264 }; 265 266 } // namespace OHOS::Ace::NG 267 268 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TEXT_FIELD_TEXT_SELECTOR_H 269