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#include "common/typed_text.h"
26
27namespace OHOS {
28class CursorAnimator : public Animator, public AnimatorCallback {
29public:
30    explicit CursorAnimator(UIEditText* view) : Animator(this, view, 0, true), editText_(view) {}
31
32    virtual ~CursorAnimator() {}
33
34    void Callback(UIView* view) override
35    {
36        if ((view == nullptr) || (editText_ == nullptr)) {
37            return;
38        }
39
40        uint32_t curTime = GetRunTime();
41        if (curTime == preTime_) {
42            return;
43        }
44        uint32_t duration = (curTime > preTime_) ? (curTime - preTime_) : (UINT32_MAX - preTime_ + curTime);
45        if (duration < CURSOR_ANIMATOT_DURATION) {
46            return;
47        }
48        preTime_ = curTime;
49        editText_->drawCursor_ = !editText_->drawCursor_;
50        view->Invalidate();
51    }
52
53    void StartAnimator()
54    {
55        if (editText_ == nullptr) {
56            return;
57        }
58        Start();
59        preTime_ = GetRunTime();
60        editText_->drawCursor_ = false;
61    }
62
63    void StopAnimator()
64    {
65        if (editText_ == nullptr) {
66            return;
67        }
68        Stop();
69        editText_->drawCursor_ = false;
70        editText_->Invalidate();
71    }
72
73private:
74    uint32_t preTime_ = 0;
75    UIEditText* editText_ = nullptr;
76    static constexpr uint16_t CURSOR_ANIMATOT_DURATION = 650;
77};
78
79UIEditText::UIEditText()
80    : inputText_(nullptr),
81      placeholderText_(nullptr),
82      offsetX_(DEFAULT_TEXT_OFFSET),
83      cursorIndex_(0),
84      deleteTextWidth_(0),
85      insertTextWidth_(0),
86      offsetState_(UPDATE_OFFSET_UNKNOW),
87      needRefresh_(false),
88      useTextColor_(false),
89      isFocused_(false),
90      drawCursor_(false),
91      maxLength_(MAX_TEXT_LENGTH),
92      placeholderEllipsisIndex_(Text::TEXT_ELLIPSIS_END_INV),
93      cursorPosX_(0),
94      textColor_(Color::White()),
95      placeholderColor_(Color::Gray()),
96      cursorColor_(Color::White()),
97      onChangeListener_(nullptr),
98      cursorAnimator_(nullptr)
99{
100    touchable_ = true;
101    focusable_ = true;
102    Theme* theme = ThemeManager::GetInstance().GetCurrent();
103    Style& style = (theme != nullptr) ? (theme->GetEditTextStyle()) : (StyleDefault::GetEditTextStyle());
104    UIView::SetStyle(style);
105    SetDraggable(true);
106}
107
108UIEditText::~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
124bool UIEditText::OnPressEvent(const PressEvent& event)
125{
126    DealPressEvents(false, event);
127    return UIView::OnPressEvent(event);
128}
129
130bool UIEditText::OnLongPressEvent(const LongPressEvent &event)
131{
132    DealPressEvents(true, event);
133    return UIView::OnLongPressEvent(event);
134}
135
136void UIEditText::DealPressEvents(bool longPressEvent, const Event &event)
137{
138    if (touchable_) {
139        if (!longPressEvent) {
140            Point pressPos = event.GetCurrentPos();
141            pressPos.x = pressPos.x - GetOrigRect().GetX();
142            pressPos.y = pressPos.y - GetOrigRect().GetY();
143            Style style = GetStyleConst();
144            cursorIndex_ = inputText_->GetLetterIndexByLinePosition(style,
145                GetContentRect().GetWidth(), pressPos.x, offsetX_);
146            offsetState_ = UPDATE_OFFSET_PRESS_EVENT;
147            UpdateOffsetX();
148        }
149        RequestFocus();
150        Invalidate();
151    }
152}
153
154bool UIEditText::OnDragEvent(const DragEvent& event)
155{
156    DealPressEvents(false, event);
157    return UIView::OnDragEvent(event);
158}
159
160void UIEditText::Focus()
161{
162    if (focusable_) {
163        if (cursorAnimator_ == nullptr) {
164            cursorAnimator_ = new CursorAnimator(this);
165        }
166        static_cast<CursorAnimator*>(cursorAnimator_)->StartAnimator();
167        isFocused_ = true;
168    }
169    Invalidate();
170    UIView::Focus();
171}
172
173void UIEditText::Blur()
174{
175    if (cursorAnimator_ != nullptr) {
176        static_cast<CursorAnimator*>(cursorAnimator_)->StopAnimator();
177    }
178    isFocused_ = false;
179    Invalidate();
180    UIView::Blur();
181}
182
183void UIEditText::InitText()
184{
185    if (inputText_ == nullptr) {
186        inputText_ = new Text();
187        inputText_->SetAlign(TEXT_ALIGNMENT_LEFT, TEXT_ALIGNMENT_CENTER);
188        inputText_->SetExpandWidth(true);
189        inputText_->SetExpandHeight(false);
190    }
191
192    if (placeholderText_ == nullptr) {
193        placeholderText_ = new Text();
194        placeholderText_->SetAlign(TEXT_ALIGNMENT_LEFT, TEXT_ALIGNMENT_CENTER);
195        placeholderText_->SetExpandWidth(false);
196        placeholderText_->SetExpandHeight(false);
197    }
198}
199
200void UIEditText::SetStyle(Style& style)
201{
202    UIView::SetStyle(style);
203    RefreshText();
204}
205
206void UIEditText::SetStyle(uint8_t key, int64_t value)
207{
208    UIView::SetStyle(key, value);
209    RefreshText();
210}
211
212void UIEditText::SetText(const char* text)
213{
214    InitText();
215    if (text == nullptr) {
216        return;
217    }
218
219    std::string inputText = std::string(text);
220    SetText(inputText);
221    cursorIndex_ = TypedText::GetUTF8CharacterSize(text, inputText.length());
222    offsetState_ = UPDATE_OFFSET_INTERFACE;
223}
224
225void UIEditText::SetText(std::string text)
226{
227    UpdateTextString(text);
228    UpdateInnerText();
229}
230
231const char* UIEditText::GetText()
232{
233    return textStr_.c_str();
234}
235
236void UIEditText::UpdateTextString(std::string text)
237{
238    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert;
239    std::wstring wideText = convert.from_bytes(text);
240    uint32_t textLen = wideText.length();
241    uint16_t maxLength = GetMaxLength();
242    if (textLen > maxLength) {
243        textLen = maxLength;
244    }
245    std::wstring newWideText = wideText.substr(0, textLen);
246    std::string newText = convert.to_bytes(newWideText);
247    CheckValueChange(newText);
248    textStr_ = newText;
249    passwordStr_ = std::string(newWideText.length(), *PASSWORD_DOT.c_str());
250}
251
252std::string UIEditText::GetInnerText()
253{
254    return textStr_;
255}
256
257std::string UIEditText::GetInnerPassword()
258{
259    return passwordStr_;
260}
261
262void UIEditText::SetPlaceholder(const char* text)
263{
264    InitText();
265    placeholderText_->SetText(text);
266    if (placeholderText_->IsNeedRefresh()) {
267        RefreshText();
268    }
269}
270
271const char* UIEditText::GetPlaceholder()
272{
273    if ((placeholderText_ == nullptr) || placeholderText_->GetText() == nullptr) {
274        return "";
275    } else {
276        return placeholderText_->GetText();
277    }
278}
279
280void UIEditText::SetFontId(uint16_t fontId)
281{
282    InitText();
283    inputText_->SetFontId(fontId);
284    placeholderText_->SetFontId(fontId);
285    if (inputText_->IsNeedRefresh()) {
286        RefreshText();
287    }
288}
289
290void UIEditText::SetFont(const char* name, uint8_t size)
291{
292    InitText();
293    inputText_->SetFont(name, size);
294    placeholderText_->SetFont(name, size);
295    if (inputText_->IsNeedRefresh()) {
296        RefreshText();
297    }
298}
299
300uint16_t UIEditText::GetTextWidth()
301{
302    InitText();
303    if (inputText_->IsNeedRefresh()) {
304        ReMeasure();
305    }
306    return inputText_->GetTextSize().x;
307}
308
309uint16_t UIEditText::GetTextHeight()
310{
311    InitText();
312    if (inputText_->IsNeedRefresh()) {
313        ReMeasure();
314    }
315    return inputText_->GetTextSize().y;
316}
317
318void UIEditText::RefreshText()
319{
320    Invalidate();
321    placeholderEllipsisIndex_ = Text::TEXT_ELLIPSIS_END_INV;
322    if (!needRefresh_) {
323        needRefresh_ = true;
324    }
325}
326
327void UIEditText::ReMeasure()
328{
329    if (!needRefresh_) {
330        return;
331    }
332    needRefresh_ = false;
333    InitText();
334    Style style = GetStyleConst();
335    style.textColor_ = GetTextColor();
336    Rect contentRect = GetContentRect();
337    int16_t width = contentRect.GetWidth() - BOTH_SIDE_TEXT_OFFSET;
338    contentRect.SetWidth(width > 0 ? width : 0);
339    inputText_->ReMeasureTextSize(contentRect, style);
340    placeholderText_->ReMeasureTextSize(contentRect, style);
341    placeholderEllipsisIndex_ = placeholderText_->GetEllipsisIndex(contentRect, style);
342    placeholderText_->ReMeasureTextWidthInEllipsisMode(contentRect, style, placeholderEllipsisIndex_);
343
344    UpdateOffsetX();
345}
346
347void UIEditText::UpdateOffsetX()
348{
349    if (!inputText_) {
350        return;
351    }
352
353    Rect contentRect = GetContentRect();
354    Style style = GetStyleConst();
355
356    uint16_t textLength = GetTextLength();
357    uint16_t firstVisibleIndex = GetFirstVisibleIndex();
358    uint16_t lastVisibleIndex = GetLastVisibleIndex();
359    if (textLength == 0 || (firstVisibleIndex == 0 && lastVisibleIndex == textLength)) {
360        offsetX_ = DEFAULT_TEXT_OFFSET;
361        offsetState_ = UPDATE_OFFSET_UNKNOW;
362        deleteTextWidth_ = 0;
363        insertTextWidth_ = 0;
364        return;
365    }
366
367    switch (offsetState_) {
368        case UPDATE_OFFSET_INTERFACE:
369            offsetX_ = DEFAULT_TEXT_OFFSET;
370            break;
371        case UPDATE_OFFSET_PRESS_EVENT:
372            UpdateExtraOffsetX(firstVisibleIndex, lastVisibleIndex);
373            break;
374        case UPDATE_OFFSET_DELETE:
375        case UPDATE_OFFSET_INSERT:
376            UpdateInsertDeletedOffset();
377            break;
378        case UPDATE_OFFSET_SET_CURSOR:
379            UpdateOffsetBySetCursorIndex();
380            break;
381        case UPDATE_OFFSET_INPUT_TYPE:
382            UpdateOffsetByInputType();
383            break;
384        default:
385            break;
386    }
387    offsetState_ = UPDATE_OFFSET_UNKNOW;
388    deleteTextWidth_ = 0;
389    insertTextWidth_ = 0;
390}
391
392uint16_t UIEditText::GetFirstVisibleIndex()
393{
394    if (!inputText_) {
395        return 0;
396    }
397    Rect contentRect = GetContentRect();
398    Style style = GetStyleConst();
399    uint16_t firstVisibleIndex = 0;
400    if (inputText_->GetDirect() == UITextLanguageDirect::TEXT_DIRECT_LTR) {
401        if (offsetX_ > 0) {
402            return 0;
403        }
404        // Returns the number of characters that can be skipped by the offset.
405        firstVisibleIndex = inputText_->GetLetterIndexByLinePosition(style, contentRect.GetWidth(),
406            0, offsetX_) + 1;
407    }
408    return firstVisibleIndex;
409}
410
411uint16_t UIEditText::GetLastVisibleIndex()
412{
413    if (!inputText_) {
414        return 0;
415    }
416    Rect contentRect = GetContentRect();
417    Style style = GetStyleConst();
418    uint16_t lastVisibleIndex = 0;
419    if (inputText_->GetDirect() == UITextLanguageDirect::TEXT_DIRECT_LTR) {
420        lastVisibleIndex = inputText_->GetLetterIndexByLinePosition(style, contentRect.GetWidth(),
421            contentRect.GetWidth(), offsetX_);
422    }
423    return lastVisibleIndex;
424}
425
426void UIEditText::UpdateExtraOffsetX(const uint16_t firstVisibleIndex,
427                                    const uint16_t lastVisibleIndex)
428{
429    if (!inputText_) {
430        return;
431    }
432    Rect contentRect = GetContentRect();
433    Style style = GetStyleConst();
434    uint16_t characterSize = 0;
435    uint16_t textLength = GetTextLength();
436    if (cursorIndex_ - firstVisibleIndex < 1 && firstVisibleIndex != 0) {
437        characterSize = inputText_->GetNextCharacterFullDispalyOffset(contentRect, style, firstVisibleIndex - 1, 1);
438        offsetX_ += characterSize + DEFAULT_TEXT_OFFSET;
439        if (GetFirstVisibleIndex() == 0) {
440            offsetX_ = DEFAULT_TEXT_OFFSET;
441        }
442    } else if (lastVisibleIndex - cursorIndex_ < 1 && lastVisibleIndex != textLength) {
443        characterSize = inputText_->GetNextCharacterFullDispalyOffset(contentRect, style, lastVisibleIndex, 1);
444        offsetX_ -= characterSize + DEFAULT_TEXT_OFFSET;
445        if (GetLastVisibleIndex() == textLength) {
446            offsetX_ = -(GetTextWidth() - GetRect().GetWidth() + BOTH_SIDE_TEXT_OFFSET);
447        }
448    }
449}
450
451uint16_t UIEditText::GetTextWidthByCursorIndex(const uint16_t cursorIndex)
452{
453    if (!inputText_ || cursorIndex == 0) {
454        return 0;
455    }
456
457    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert;
458    std::wstring wideText = convert.from_bytes(textStr_);
459    wideText = wideText.substr(0, cursorIndex);
460    std::string clipText = convert.to_bytes(wideText);
461
462    return TypedText::GetTextWidth(clipText.c_str(), GetFontId(), inputText_->GetFontSize(),
463        clipText.length(), GetStyleConst().letterSpace_);
464}
465
466void UIEditText::UpdateInsertDeletedOffset()
467{
468    if (deleteTextWidth_ > 0) {
469        if (offsetX_ + DEFAULT_TEXT_OFFSET < 0) {
470            offsetX_ += deleteTextWidth_;
471            if (GetFirstVisibleIndex() == 0 && GetLastVisibleIndex() == GetTextLength()) {
472                offsetX_ = DEFAULT_TEXT_OFFSET;
473            }
474        } else {
475            offsetX_ = DEFAULT_TEXT_OFFSET;
476        }
477    } else if (insertTextWidth_ > 0) {
478        if (cursorIndex_ == GetTextLength()) {
479            offsetX_ = -(GetTextWidth() - GetRect().GetWidth() + BOTH_SIDE_TEXT_OFFSET);
480        } else {
481            offsetX_ -= insertTextWidth_;
482        }
483    }
484}
485
486void UIEditText::OnDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
487{
488    InitText();
489    UIView::OnDraw(gfxDstBuffer, invalidatedArea);
490
491    bool drawPlaceholder = false;
492    if (inputText_->GetText() != nullptr && strlen(inputText_->GetText()) > 0) {
493        Style style = GetStyleConst();
494        style.textColor_ = GetTextColor();
495        OpacityType opa = GetMixOpaScale();
496        inputText_->OnDraw(gfxDstBuffer, invalidatedArea, GetOrigRect(), GetContentRect(), offsetX_, style,
497                           Text::TEXT_ELLIPSIS_END_INV, opa);
498        drawPlaceholder = false;
499    } else {
500        Style style = GetStyleConst();
501        style.textColor_ = GetPlaceholderColor();
502        OpacityType opa = GetMixOpaScale();
503        placeholderText_->OnDraw(gfxDstBuffer, invalidatedArea, GetOrigRect(), GetContentRect(), DEFAULT_TEXT_OFFSET,
504                                 style, placeholderEllipsisIndex_, opa);
505        drawPlaceholder = true;
506    }
507
508    DrawCursor(gfxDstBuffer, invalidatedArea, drawPlaceholder);
509}
510
511void UIEditText::DrawCursor(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea, bool drawPlaceholder)
512{
513    if (!(isFocused_ && drawCursor_)) {
514        return;
515    }
516
517    CalculatedCursorPos(drawPlaceholder);
518
519    Style* cursorStyle = new Style();
520    cursorStyle->SetStyle(STYLE_BACKGROUND_COLOR, cursorColor_.full);
521    cursorStyle->SetStyle(STYLE_BACKGROUND_OPA, OPA_OPAQUE);
522
523    int16_t left = 0;
524    UITextLanguageDirect direct = drawPlaceholder ? placeholderText_->GetDirect() : inputText_->GetDirect();
525    if (direct == UITextLanguageDirect::TEXT_DIRECT_LTR) {
526        left = cursorPosX_ - DEFAULT_CURSOR_OFFSET;
527    } else if (direct == UITextLanguageDirect::TEXT_DIRECT_RTL) {
528        left = cursorPosX_ + DEFAULT_CURSOR_OFFSET;
529    }
530
531    Rect viewRect;
532    viewRect.SetLeft(left);
533    viewRect.SetTop(GetOrigRect().GetTop() + (GetRect().GetHeight() - inputText_->GetFontSize()) / 2); // 2: harf size
534    viewRect.SetHeight(inputText_->GetFontSize());
535    viewRect.SetWidth(DEFAULT_CURSOR_WIDTH);
536
537    BaseGfxEngine::GetInstance()->DrawRect(gfxDstBuffer, viewRect, invalidatedArea, *cursorStyle, OPA_OPAQUE);
538    delete cursorStyle;
539}
540
541void UIEditText::InsertText(std::string text)
542{
543    InitText();
544    InsertTextByCursorIndex(text);
545}
546
547void UIEditText::InsertTextByCursorIndex(std::string text)
548{
549    if (!inputText_) {
550        return;
551    }
552    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert;
553    std::wstring wideText = convert.from_bytes(textStr_);
554    std::wstring insertWText = convert.from_bytes(text);
555    uint32_t textLen = wideText.length();
556    uint32_t insertWTextLen = insertWText.length();
557    if (cursorIndex_ > textLen || insertWTextLen + textLen > maxLength_) {
558        return;
559    }
560
561    std::wstring newWideText = wideText.insert(cursorIndex_, insertWText);
562    std::string newText = convert.to_bytes(newWideText);
563    cursorIndex_ += insertWTextLen;
564    SetText(newText);
565
566    Style style = GetStyleConst();
567    Rect contentRect = GetContentRect();
568    cursorPosX_ = inputText_->GetPosXByLetterIndex(contentRect, style, 0, cursorIndex_);
569    if (cursorPosX_ >= contentRect.GetWidth() - DEFAULT_TEXT_OFFSET) {
570        insertTextWidth_ = inputText_->GetNextCharacterFullDispalyOffset(contentRect,
571            style, cursorIndex_ - insertWTextLen, insertWTextLen) + style.letterSpace_;
572        offsetState_ = UPDATE_OFFSET_INSERT;
573    }
574
575    if (isFocused_) {
576        if (cursorAnimator_ != nullptr) {
577            static_cast<CursorAnimator*>(cursorAnimator_)->StartAnimator();
578        }
579    }
580}
581
582void UIEditText::CalculatedCursorPos(bool drawPlaceholder)
583{
584    if (!inputText_ || !placeholderText_) {
585        return;
586    }
587
588    Style style = GetStyleConst();
589    Rect contentRect = GetContentRect();
590    UITextLanguageDirect direct = drawPlaceholder ? placeholderText_->GetDirect() : inputText_->GetDirect();
591    if (direct == UITextLanguageDirect::TEXT_DIRECT_LTR) {
592        cursorPosX_ = contentRect.GetX() + inputText_->GetPosXByLetterIndex(contentRect,
593            style, 0, cursorIndex_) + offsetX_;
594    } else if (direct == UITextLanguageDirect::TEXT_DIRECT_RTL) {
595        cursorPosX_ = GetRect().GetRight() - style.borderWidth_ - style.paddingRight_
596            - inputText_->GetPosXByLetterIndex(contentRect, style, 0, cursorIndex_)
597            - offsetX_;
598    }
599}
600
601uint16_t UIEditText::GetCursorIndex()
602{
603    return cursorIndex_;
604}
605
606void UIEditText::SetCursorIndex(uint16_t cursorIndex)
607{
608    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert;
609    std::wstring wideText = convert.from_bytes(textStr_);
610    if (cursorIndex > wideText.length()) {
611        cursorIndex_ = wideText.length();
612    } else {
613        cursorIndex_ = cursorIndex;
614    }
615
616    offsetState_ = UPDATE_OFFSET_SET_CURSOR;
617    RefreshText();
618    if (cursorAnimator_ != nullptr) {
619        static_cast<CursorAnimator*>(cursorAnimator_)->StartAnimator();
620    }
621}
622
623void UIEditText::UpdateOffsetBySetCursorIndex()
624{
625    if (!inputText_) {
626        return;
627    }
628
629    uint16_t textWidth = GetTextWidthByCursorIndex(cursorIndex_);
630    Rect contentRect = GetContentRect();
631    int16_t newPosX = 0;
632    if (inputText_->GetDirect() == UITextLanguageDirect::TEXT_DIRECT_LTR) {
633        newPosX = contentRect.GetX() + textWidth + offsetX_;
634        if (newPosX <= contentRect.GetX()) {
635            offsetX_ = -(textWidth - DEFAULT_TEXT_OFFSET);
636        } else if (newPosX >= GetRect().GetRight()) {
637            offsetX_ = -(textWidth - GetRect().GetWidth() + BOTH_SIDE_TEXT_OFFSET);
638        }
639    }
640}
641
642void UIEditText::DeleteBackward(uint32_t length)
643{
644    if ((length == 0) || (textStr_.length() == 0) || (cursorIndex_ == 0)) {
645        return;
646    }
647    if (!inputText_) {
648        return;
649    }
650
651    std::string newText;
652    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert;
653    std::wstring wideText = convert.from_bytes(textStr_);
654    if (length > wideText.size()) {
655        cursorIndex_ = 0;
656    } else {
657        uint32_t deleteLength = cursorIndex_ >= length ? length : length - cursorIndex_;
658        if (wideText.size() >= cursorIndex_) {
659            wideText.erase(cursorIndex_ - deleteLength, deleteLength);
660        }
661        newText = convert.to_bytes(wideText);
662        cursorIndex_ -= deleteLength;
663        deleteTextWidth_ = inputText_->GetNextCharacterFullDispalyOffset(GetContentRect(),
664            GetStyleConst(), cursorIndex_, deleteLength);
665        offsetState_ = UPDATE_OFFSET_DELETE;
666    }
667
668    SetText(newText);
669    if (cursorAnimator_ != nullptr) {
670        static_cast<CursorAnimator*>(cursorAnimator_)->StartAnimator();
671    }
672}
673
674void UIEditText::UpdateInnerText()
675{
676    InitText();
677    if (inputType_ == InputType::TEXT_TYPE) {
678        inputText_->SetText(GetInnerText().c_str());
679    } else {
680        inputText_->SetText(GetInnerPassword().c_str());
681    }
682    RefreshText();
683}
684
685void UIEditText::SetMaxLength(uint16_t maxLength)
686{
687    InitText();
688    if (maxLength > MAX_TEXT_LENGTH) {
689        maxLength = MAX_TEXT_LENGTH;
690    }
691    maxLength_ = maxLength;
692    if (textStr_.length() > maxLength) {
693        SetText(textStr_.substr(0, maxLength));
694    }
695}
696
697uint16_t UIEditText::GetMaxLength()
698{
699    return maxLength_;
700}
701
702void UIEditText::SetInputType(InputType inputType)
703{
704    if (inputType_ == inputType) {
705        return;
706    }
707    inputType_ = inputType;
708
709    // update view
710    UpdateInnerText();
711
712    offsetState_ = UPDATE_OFFSET_INPUT_TYPE;
713}
714
715void UIEditText::UpdateOffsetByInputType()
716{
717    if (!inputText_) {
718        return;
719    }
720
721    Rect contentRect = GetContentRect();
722    if (GetTextWidth() <= contentRect.GetWidth() - DEFAULT_TEXT_OFFSET) {
723        offsetX_ = DEFAULT_TEXT_OFFSET;
724        return;
725    }
726
727    if (cursorIndex_ == GetTextLength()) {
728        offsetX_ = -(GetTextWidth() - GetRect().GetWidth() + BOTH_SIDE_TEXT_OFFSET);
729        return;
730    }
731
732    if (offsetX_ + GetTextWidth() < contentRect.GetWidth() - DEFAULT_TEXT_OFFSET) {
733        offsetX_ = contentRect.GetWidth() - DEFAULT_TEXT_OFFSET - GetTextWidth();
734        return;
735    }
736
737    UpdateOffsetBySetCursorIndex();
738}
739
740void UIEditText::CheckValueChange(std::string text)
741{
742    if (onChangeListener_ == nullptr) {
743        return;
744    }
745
746    if (textStr_.compare(text) != 0) {
747        onChangeListener_->OnChange(*this, text.c_str());
748    }
749}
750
751uint16_t UIEditText::GetTextLength()
752{
753    if (inputText_ == nullptr) {
754        return 0;
755    }
756    return TypedText::GetUTF8CharacterSize(inputText_->GetText(),
757        std::string(inputText_->GetText()).length());
758}
759} // namespace OHOS
760