• 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 #include "components/ui_edit_text.h"
17 
18 #include <codecvt>
19 #include <locale>
20 
21 #include "font/ui_font.h"
22 #include "gfx_utils/graphic_log.h"
23 #include "securec.h"
24 #include "themes/theme_manager.h"
25 
26 namespace OHOS {
27 namespace {
28 constexpr char16_t PASSWORD_DOT = u'•'; // dot for password type
29 constexpr uint16_t DEFAULT_TEXT_OFFSET = 5;
30 constexpr uint16_t DEFAULT_CURSOR_OFFSET = 2;
31 constexpr uint16_t DEFAULT_CURSOR_WIDTH = 2;
32 } // namespace name
33 
34 class CursorAnimator : public Animator, public AnimatorCallback {
35 public:
CursorAnimator(UIEditText * view)36     explicit CursorAnimator(UIEditText* view) : Animator(this, view, 0, true), editText_(view) {}
37 
~CursorAnimator()38     virtual ~CursorAnimator() {}
39 
Callback(UIView * view)40     void Callback(UIView* view) override
41     {
42         if ((view == nullptr) || (editText_ == nullptr)) {
43             return;
44         }
45 
46         uint32_t curTime = GetRunTime();
47         if (curTime == preTime_) {
48             return;
49         }
50         uint32_t duration = (curTime > preTime_) ? (curTime - preTime_) : (UINT32_MAX - preTime_ + curTime);
51         if (duration < CURSOR_ANIMATOT_DURATION) {
52             return;
53         }
54         preTime_ = curTime;
55         editText_->drawCursor_ = !editText_->drawCursor_;
56         view->Invalidate();
57     }
58 
StartAnimator()59     void StartAnimator()
60     {
61         if (editText_ == nullptr) {
62             return;
63         }
64         Start();
65         preTime_ = GetRunTime();
66         editText_->drawCursor_ = false;
67     }
68 
StopAnimator()69     void StopAnimator()
70     {
71         if (editText_ == nullptr) {
72             return;
73         }
74         Stop();
75         editText_->drawCursor_ = false;
76         editText_->Invalidate();
77     }
78 
79 private:
80     uint32_t preTime_ = 0;
81     UIEditText* editText_ = nullptr;
82     static constexpr uint16_t CURSOR_ANIMATOT_DURATION = 650;
83 };
84 
UIEditText()85 UIEditText::UIEditText()
86     : inputText_(nullptr),
87       placeholderText_(nullptr),
88       needRefresh_(false),
89       useTextColor_(false),
90       isFocused_(false),
91       drawCursor_(false),
92       maxLength_(MAX_TEXT_LENGTH),
93       placeholderEllipsisIndex_(Text::TEXT_ELLIPSIS_END_INV),
94       offsetX_(DEFAULT_TEXT_OFFSET),
95       textColor_(Color::White()),
96       placeholderColor_(Color::Gray()),
97       cursorColor_(Color::White()),
98       onChangeListener_(nullptr),
99       cursorAnimator_(nullptr)
100 {
101     touchable_ = true;
102     focusable_ = true;
103     Theme* theme = ThemeManager::GetInstance().GetCurrent();
104     Style& style = (theme != nullptr) ? (theme->GetEditTextStyle()) : (StyleDefault::GetEditTextStyle());
105     UIView::SetStyle(style);
106 }
107 
~UIEditText()108 UIEditText::~UIEditText()
109 {
110     if (cursorAnimator_ != nullptr) {
111         delete cursorAnimator_;
112         cursorAnimator_ = nullptr;
113     }
114     if (inputText_ != nullptr) {
115         delete inputText_;
116         inputText_ = nullptr;
117     }
118     if (placeholderText_ != nullptr) {
119         delete placeholderText_;
120         placeholderText_ = nullptr;
121     }
122 }
123 
OnPressEvent(const PressEvent & event)124 bool UIEditText::OnPressEvent(const PressEvent& event)
125 {
126     if (touchable_) {
127         RequestFocus();
128     }
129     return UIView::OnPressEvent(event);
130 }
131 
Focus()132 void UIEditText::Focus()
133 {
134     if (focusable_) {
135         if (cursorAnimator_ == nullptr) {
136             cursorAnimator_ = new CursorAnimator(this);
137         }
138         static_cast<CursorAnimator*>(cursorAnimator_)->StartAnimator();
139         isFocused_ = true;
140     }
141     UpdateOffsetX();
142     Invalidate();
143     UIView::Focus();
144 }
145 
Blur()146 void UIEditText::Blur()
147 {
148     if (cursorAnimator_ != nullptr) {
149         static_cast<CursorAnimator*>(cursorAnimator_)->StopAnimator();
150     }
151     isFocused_ = false;
152     UpdateOffsetX();
153     Invalidate();
154     UIView::Blur();
155 }
156 
InitText()157 void UIEditText::InitText()
158 {
159     if (inputText_ == nullptr) {
160         inputText_ = new Text();
161         inputText_->SetAlign(TEXT_ALIGNMENT_LEFT, TEXT_ALIGNMENT_CENTER);
162         inputText_->SetExpandWidth(true);
163         inputText_->SetExpandHeight(false);
164     }
165 
166     if (placeholderText_ == nullptr) {
167         placeholderText_ = new Text();
168         placeholderText_->SetAlign(TEXT_ALIGNMENT_LEFT, TEXT_ALIGNMENT_CENTER);
169         placeholderText_->SetExpandWidth(false);
170         placeholderText_->SetExpandHeight(false);
171     }
172 }
173 
SetStyle(Style & style)174 void UIEditText::SetStyle(Style& style)
175 {
176     UIView::SetStyle(style);
177     RefreshText();
178 }
179 
SetStyle(uint8_t key,int64_t value)180 void UIEditText::SetStyle(uint8_t key, int64_t value)
181 {
182     UIView::SetStyle(key, value);
183     RefreshText();
184 }
185 
SetText(const char * text)186 void UIEditText::SetText(const char* text)
187 {
188     InitText();
189     if (text == nullptr) {
190         return;
191     }
192     SetText(std::string(text));
193 }
194 
SetText(std::string text)195 void UIEditText::SetText(std::string text)
196 {
197     UpdateTextString(text);
198     UpdateInnerText();
199 }
200 
GetText()201 const char* UIEditText::GetText()
202 {
203     return textStr_.c_str();
204 }
205 
UpdateTextString(std::string text)206 void UIEditText::UpdateTextString(std::string text)
207 {
208     std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert;
209     std::wstring wideText = convert.from_bytes(text);
210     uint32_t textLen = wideText.length();
211     uint16_t maxLength = GetMaxLength();
212     if (textLen > maxLength) {
213         textLen = maxLength;
214     }
215     std::wstring newWideText = wideText.substr(0, textLen);
216     std::string newText = convert.to_bytes(newWideText);
217     CheckValueChange(newText);
218     textStr_ = newText;
219 
220     std::wstring dotString = std::wstring(newWideText.length(), PASSWORD_DOT);
221     passwordStr_ = convert.to_bytes(dotString);
222 }
223 
GetInnerText()224 std::string UIEditText::GetInnerText()
225 {
226     return textStr_;
227 }
228 
GetInnerPassword()229 std::string UIEditText::GetInnerPassword()
230 {
231     return passwordStr_;
232 }
233 
SetPlaceholder(const char * text)234 void UIEditText::SetPlaceholder(const char* text)
235 {
236     InitText();
237     placeholderText_->SetText(text);
238     if (placeholderText_->IsNeedRefresh()) {
239         RefreshText();
240     }
241 }
242 
GetPlaceholder()243 const char* UIEditText::GetPlaceholder()
244 {
245     if ((placeholderText_ == nullptr) || placeholderText_->GetText() == nullptr) {
246         return "";
247     } else {
248         return placeholderText_->GetText();
249     }
250 }
251 
SetFontId(uint16_t fontId)252 void UIEditText::SetFontId(uint16_t fontId)
253 {
254     InitText();
255     inputText_->SetFontId(fontId);
256     placeholderText_->SetFontId(fontId);
257     if (inputText_->IsNeedRefresh()) {
258         RefreshText();
259     }
260 }
261 
SetFont(const char * name,uint8_t size)262 void UIEditText::SetFont(const char* name, uint8_t size)
263 {
264     InitText();
265     inputText_->SetFont(name, size);
266     placeholderText_->SetFont(name, size);
267     if (inputText_->IsNeedRefresh()) {
268         RefreshText();
269     }
270 }
271 
GetTextWidth()272 uint16_t UIEditText::GetTextWidth()
273 {
274     InitText();
275     if (inputText_->IsNeedRefresh()) {
276         ReMeasure();
277     }
278     return inputText_->GetTextSize().x;
279 }
280 
GetTextHeight()281 uint16_t UIEditText::GetTextHeight()
282 {
283     InitText();
284     if (inputText_->IsNeedRefresh()) {
285         ReMeasure();
286     }
287     return inputText_->GetTextSize().y;
288 }
289 
RefreshText()290 void UIEditText::RefreshText()
291 {
292     Invalidate();
293     placeholderEllipsisIndex_ = Text::TEXT_ELLIPSIS_END_INV;
294     if (!needRefresh_) {
295         needRefresh_ = true;
296     }
297 }
298 
ReMeasure()299 void UIEditText::ReMeasure()
300 {
301     if (!needRefresh_) {
302         return;
303     }
304     needRefresh_ = false;
305     InitText();
306     Style style = GetStyleConst();
307     style.textColor_ = GetTextColor();
308     Rect contentRect = GetContentRect();
309     int16_t width = contentRect.GetWidth() - DEFAULT_TEXT_OFFSET * 2; // 2: left and right space
310     contentRect.SetWidth(width > 0 ? width : 0);
311     inputText_->ReMeasureTextSize(contentRect, style);
312     placeholderText_->ReMeasureTextSize(contentRect, style);
313     placeholderEllipsisIndex_ = placeholderText_->GetEllipsisIndex(contentRect, style);
314     placeholderText_->ReMeasureTextWidthInEllipsisMode(contentRect, style, placeholderEllipsisIndex_);
315 
316     UpdateOffsetX();
317 }
318 
UpdateOffsetX()319 void UIEditText::UpdateOffsetX()
320 {
321     if (isFocused_) {
322         Point textSize = inputText_->GetTextSize();
323         Rect contentRect = GetContentRect();
324         int16_t curWidth = textSize.x + DEFAULT_TEXT_OFFSET * 2;
325         if (contentRect.GetWidth() > curWidth) {
326             offsetX_ = DEFAULT_TEXT_OFFSET;
327         } else {
328             offsetX_ = contentRect.GetWidth() - curWidth;
329         }
330     } else {
331         offsetX_ = DEFAULT_TEXT_OFFSET;
332     }
333 }
334 
OnDraw(BufferInfo & gfxDstBuffer,const Rect & invalidatedArea)335 void UIEditText::OnDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
336 {
337     InitText();
338     UIView::OnDraw(gfxDstBuffer, invalidatedArea);
339 
340     bool drawPlaceholder = false;
341     if (inputText_->GetText() != nullptr && strlen(inputText_->GetText()) > 0) {
342         Style style = GetStyleConst();
343         style.textColor_ = GetTextColor();
344         OpacityType opa = GetMixOpaScale();
345         inputText_->OnDraw(gfxDstBuffer, invalidatedArea, GetOrigRect(), GetContentRect(), offsetX_, style,
346                            Text::TEXT_ELLIPSIS_END_INV, opa);
347         drawPlaceholder = false;
348     } else {
349         Style style = GetStyleConst();
350         style.textColor_ = GetPlaceholderColor();
351         OpacityType opa = GetMixOpaScale();
352         placeholderText_->OnDraw(gfxDstBuffer, invalidatedArea, GetOrigRect(), GetContentRect(), DEFAULT_TEXT_OFFSET,
353                                  style, placeholderEllipsisIndex_, opa);
354         drawPlaceholder = true;
355     }
356 
357     DrawCursor(gfxDstBuffer, invalidatedArea, drawPlaceholder);
358 }
359 
DrawCursor(BufferInfo & gfxDstBuffer,const Rect & invalidatedArea,bool drawPlaceholder)360 void UIEditText::DrawCursor(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea, bool drawPlaceholder)
361 {
362     if (!(isFocused_ && drawCursor_)) {
363         return;
364     }
365 
366     Style* cursorStyle = new Style();
367     cursorStyle->SetStyle(STYLE_BACKGROUND_COLOR, cursorColor_.full);
368     cursorStyle->SetStyle(STYLE_BACKGROUND_OPA, OPA_OPAQUE);
369 
370     Rect viewRect;
371     int16_t cursorSpace = DEFAULT_CURSOR_OFFSET;
372     if (drawPlaceholder) {
373         viewRect.SetLeft(GetOrigRect().GetX() + cursorSpace + offsetX_);
374     } else {
375         int16_t width = inputText_->GetTextSize().x;
376         viewRect.SetLeft(GetOrigRect().GetX() + width + cursorSpace + offsetX_);
377     }
378     viewRect.SetTop(GetOrigRect().GetTop() + (GetRect().GetHeight() - inputText_->GetFontSize()) / 2); // 2: harf size
379     viewRect.SetHeight(inputText_->GetFontSize());
380     viewRect.SetWidth(DEFAULT_CURSOR_WIDTH);
381 
382     BaseGfxEngine::GetInstance()->DrawRect(gfxDstBuffer, viewRect, invalidatedArea, *cursorStyle, OPA_OPAQUE);
383     delete cursorStyle;
384 }
385 
InsertText(std::string text)386 void UIEditText::InsertText(std::string text)
387 {
388     SetText(textStr_ + text);
389     if (cursorAnimator_ != nullptr) {
390         static_cast<CursorAnimator*>(cursorAnimator_)->StartAnimator();
391     }
392 }
393 
DeleteBackward(uint32_t length)394 void UIEditText::DeleteBackward(uint32_t length)
395 {
396     if ((length == 0) || (textStr_.length() == 0)) {
397         return;
398     }
399     std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert;
400     std::wstring wideText = convert.from_bytes(textStr_);
401     uint32_t textLen = wideText.length();
402     if (length > textLen) {
403         textLen = 0;
404     } else {
405         textLen -= length;
406     }
407     std::wstring newWideText = std::wstring(wideText, 0, textLen);
408     std::string newText = convert.to_bytes(newWideText);
409 
410     SetText(newText);
411     if (cursorAnimator_ != nullptr) {
412         static_cast<CursorAnimator*>(cursorAnimator_)->StartAnimator();
413     }
414 }
415 
UpdateInnerText()416 void UIEditText::UpdateInnerText()
417 {
418     InitText();
419     if (inputType_ == InputType::TEXT_TYPE) {
420         inputText_->SetText(GetInnerText().c_str());
421     } else {
422         inputText_->SetText(GetInnerPassword().c_str());
423     }
424     RefreshText();
425 }
426 
SetMaxLength(uint16_t maxLength)427 void UIEditText::SetMaxLength(uint16_t maxLength)
428 {
429     InitText();
430     if (maxLength > MAX_TEXT_LENGTH) {
431         maxLength = MAX_TEXT_LENGTH;
432     }
433     maxLength_ = maxLength;
434     if (textStr_.length() > maxLength) {
435         SetText(textStr_.substr(0, maxLength));
436     }
437 }
438 
GetMaxLength()439 uint16_t UIEditText::GetMaxLength()
440 {
441     return maxLength_;
442 }
443 
SetInputType(InputType inputType)444 void UIEditText::SetInputType(InputType inputType)
445 {
446     if (inputType_ == inputType) {
447         return;
448     }
449     inputType_ = inputType;
450 
451     // update view
452     UpdateInnerText();
453 }
454 
CheckValueChange(std::string text)455 void UIEditText::CheckValueChange(std::string text)
456 {
457     if (onChangeListener_ == nullptr) {
458         return;
459     }
460 
461     if (textStr_.compare(text) != 0) {
462         onChangeListener_->OnChange(*this, text.c_str());
463     }
464 }
465 } // namespace OHOS
466