LCOV - code coverage report
Current view: top level - xenolith/renderer/material2d/components/input - MaterialInputTextContainer.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 128 308 41.6 %
Date: 2024-05-12 00:16:13 Functions: 17 28 60.7 %

          Line data    Source code
       1             : /**
       2             :  Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
       3             : 
       4             :  Permission is hereby granted, free of charge, to any person obtaining a copy
       5             :  of this software and associated documentation files (the "Software"), to deal
       6             :  in the Software without restriction, including without limitation the rights
       7             :  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       8             :  copies of the Software, and to permit persons to whom the Software is
       9             :  furnished to do so, subject to the following conditions:
      10             : 
      11             :  The above copyright notice and this permission notice shall be included in
      12             :  all copies or substantial portions of the Software.
      13             : 
      14             :  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15             :  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             :  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      17             :  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      18             :  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      19             :  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      20             :  THE SOFTWARE.
      21             :  **/
      22             : 
      23             : #include "MaterialInputTextContainer.h"
      24             : #include "MaterialSurfaceInterior.h"
      25             : #include "MaterialStyleContainer.h"
      26             : #include "MaterialEasing.h"
      27             : #include "XLFrameInfo.h"
      28             : #include "XL2dLayer.h"
      29             : #include "XLAction.h"
      30             : #include "XL2dVectorSprite.h"
      31             : 
      32             : namespace STAPPLER_VERSIONIZED stappler::xenolith::material2d {
      33             : 
      34          20 : InputTextContainer::~InputTextContainer() { }
      35             : 
      36          10 : bool InputTextContainer::init() {
      37          10 :         if (!DynamicStateNode::init()) {
      38           0 :                 return false;
      39             :         }
      40             : 
      41          10 :         _label = addChild(Rc<TypescaleLabel>::create(TypescaleRole::BodyLarge), ZOrder(-1));
      42          10 :         _label->setAnchorPoint(Anchor::BottomLeft);
      43             : 
      44          10 :         _label->setOnTransformDirtyCallback([this] (const Mat4 &) {
      45          80 :                 updateCursorPointers();
      46          80 :         });
      47             : 
      48          10 :         _caret = _label->addChild(Rc<Layer>::create());
      49          10 :         _caret->setAnchorPoint(Anchor::BottomLeft);
      50          10 :         _caret->setOpacity(0.0f);
      51             : 
      52          10 :         _cursorPointer = addChild(Rc<IconSprite>::create(IconName::Stappler_CursorIcon), ZOrder(1));
      53          10 :         _cursorPointer->setContentSize(Size2(24.0f, 24.0f));
      54          10 :         _cursorPointer->setAnchorPoint(Vec2(0.5f, _cursorAnchor));
      55          10 :         _cursorPointer->setBlendColor(ColorRole::Primary, 1.0f);
      56          10 :         _cursorPointer->setVisible(false);
      57             : 
      58          10 :         _selectionPointerStart = addChild(Rc<IconSprite>::create(IconName::Stappler_SelectioinStartIcon), ZOrder(1));
      59          10 :         _selectionPointerStart->setContentSize(Size2(24.0f, 24.0f));
      60          10 :         _selectionPointerStart->setAnchorPoint(Vec2(1.0f, _cursorAnchor));
      61          10 :         _selectionPointerStart->setBlendColor(ColorRole::Primary, 1.0f);
      62          10 :         _selectionPointerStart->setVisible(false);
      63             : 
      64          10 :         _selectionPointerEnd = addChild(Rc<IconSprite>::create(IconName::Stappler_SelectioinEndIcon), ZOrder(1));
      65          10 :         _selectionPointerEnd->setContentSize(Size2(24.0f, 24.0f));
      66          10 :         _selectionPointerEnd->setAnchorPoint(Vec2(0.0f, _cursorAnchor));
      67          10 :         _selectionPointerEnd->setBlendColor(ColorRole::Primary, 1.0f);
      68          10 :         _selectionPointerEnd->setVisible(false);
      69             : 
      70          10 :         setStateApplyMode(StateApplyMode::ApplyForNodesBelow);
      71          10 :         enableScissor(Padding(0.0f, 2.0f));
      72             : 
      73          10 :         return true;
      74             : }
      75             : 
      76           0 : void InputTextContainer::update(const UpdateTime &time) {
      77           0 :         DynamicStateNode::update(time);
      78             : 
      79           0 :         if (_selectedPointer) {
      80           0 :                 if (hasHorizontalOverflow()) {
      81           0 :                         const auto width = _contentSize.width;
      82           0 :                         const auto offset = std::min(48.0f, width / 3.0f);
      83           0 :                         const auto xPos = _selectedPointer->getPosition().x;
      84           0 :                         const auto labelWidth = _label->getContentSize().width;
      85           0 :                         const auto labelPos = _label->getPosition().x;
      86           0 :                         const auto minPos = width - labelWidth;
      87           0 :                         const auto maxPos = 0.0f;
      88             : 
      89           0 :                         const auto maxv = 300.0f;
      90             : 
      91           0 :                         if (xPos < offset) {
      92           0 :                                 const float relPos = 1.0f - math::clamp(xPos / offset, 0.0f, 1.0f);
      93           0 :                                 _label->setPositionX(std::min(maxPos, labelPos + relPos * maxv * time.dt));
      94           0 :                         } else if (xPos > width - offset) {
      95           0 :                                 const float relPos = 1.0f - math::clamp((width - xPos) / offset, 0.0f, 1.0f);
      96           0 :                                 _label->setPositionX(std::max(minPos, labelPos - relPos * maxv * time.dt));
      97             :                         }
      98             :                 }
      99             :         }
     100           0 : }
     101             : 
     102          10 : void InputTextContainer::onContentSizeDirty() {
     103          10 :         DynamicStateNode::onContentSizeDirty();
     104             : 
     105          10 :         _label->setPosition(Vec2(0.0f, 0.0f) + Vec2(_label->getContentSize() - _contentSize) * _adjustment);
     106          10 :         _caret->setContentSize(Size2(1.5f, _label->getFontHeight()));
     107          10 : }
     108             : 
     109         370 : bool InputTextContainer::visitDraw(FrameInfo &frame, NodeFlags parentFlags) {
     110         370 :         if (!_visible) {
     111           0 :                 return false;
     112             :         }
     113             : 
     114         370 :         if (_cursorDirty) {
     115          80 :                 updateCursorPosition();
     116          80 :                 _cursorDirty = false;
     117             :         }
     118             : 
     119         370 :         auto style = frame.getComponent<SurfaceInterior>(SurfaceInterior::ComponentFrameTag);
     120         370 :         auto styleContainer = frame.getComponent<StyleContainer>(StyleContainer::ComponentFrameTag);
     121         370 :         if (style && styleContainer) {
     122         370 :                 if (auto scheme = styleContainer->getScheme(style->getStyle().schemeTag)) {
     123         370 :                         auto c = scheme->get(ColorRole::Primary);
     124         370 :                         auto currentColor = _caret->getColor();
     125         370 :                         currentColor.a = 1.0f;
     126         370 :                         if (currentColor != c) {
     127          10 :                                 _caret->setColor(c, false);
     128             :                         }
     129             :                 }
     130             :         }
     131             : 
     132         370 :         return DynamicStateNode::visitDraw(frame, parentFlags);
     133         370 : }
     134             : 
     135          20 : void InputTextContainer::setEnabled(bool value) {
     136          20 :         if (value != _enabled) {
     137          20 :                 _enabled = value;
     138          20 :                 _caret->stopAllActions();
     139          20 :                 _caret->runAction(makeEasing(Rc<FadeTo>::create(0.2f, _enabled ? 1.0f : 0.0f)));
     140             : 
     141          20 :                 if (!_enabled) {
     142          10 :                         unscheduleCursorPointer();
     143          10 :                         stopActionByTag("RenderContinuously"_tag);
     144          10 :                         setPointerEnabled(false);
     145             :                 }
     146             :         }
     147          20 : }
     148             : 
     149         340 : void InputTextContainer::setCursor(TextCursor cursor) {
     150         340 :         if (_cursor != cursor) {
     151         340 :                 _cursor = cursor;
     152         340 :                 _cursorDirty = true;
     153         340 :                 _caret->setVisible(_cursor.length == 0);
     154         340 :                 if (_cursor.length > 0) {
     155          10 :                         _label->setSelectionCursor(_cursor);
     156             :                 } else {
     157         330 :                         _label->setSelectionCursor(TextCursor::InvalidCursor);
     158             :                 }
     159             :         }
     160         340 : }
     161             : 
     162         330 : void InputTextContainer::handleLabelChanged() {
     163         330 :         _cursorDirty = true;
     164         330 :         unscheduleCursorPointer();
     165         330 :         setPointerEnabled(false);
     166         330 : }
     167             : 
     168          10 : TextCursor InputTextContainer::getCursorForPosition(const Vec2 &loc) {
     169          10 :         if (_label->isTouched(loc, 4)) {
     170           0 :                 auto chIdx = _label->getCharIndex(_label->convertToNodeSpace(loc));
     171           0 :                 if (chIdx.first != maxOf<uint32_t>()) {
     172           0 :                         if (chIdx.second) {
     173           0 :                                 return TextCursor(chIdx.first + 1);
     174             :                         } else {
     175           0 :                                 return TextCursor(chIdx.first);
     176             :                         }
     177             :                 }
     178             :         }
     179          10 :         return TextCursor::InvalidCursor;
     180             : }
     181             : 
     182           0 : bool InputTextContainer::hasHorizontalOverflow() const {
     183           0 :         return _label->getContentSize().width > _contentSize.width;
     184             : }
     185             : 
     186           0 : void InputTextContainer::moveHorizontalOverflow(float d) {
     187           0 :         _label->stopAllActionsByTag("InputTextContainerAdjust"_tag);
     188             : 
     189           0 :         const auto labelWidth = _label->getContentSize().width;
     190           0 :         const auto width = _contentSize.width;
     191           0 :         const auto minPos = width - labelWidth;
     192           0 :         const auto maxPos = 0.0f;
     193             : 
     194           0 :         auto newpos = _label->getPosition().x + d;
     195           0 :         if (newpos < minPos) {
     196           0 :                 newpos = minPos;
     197           0 :         } else if (newpos > maxPos) {
     198           0 :                 newpos = maxPos;
     199             :         }
     200             : 
     201           0 :         _label->setPositionX(newpos);
     202           0 : }
     203             : 
     204           0 : IconSprite *InputTextContainer::getTouchedCursor(const Vec2 &vec, float padding) {
     205           0 :         if (_cursorPointer->isVisible() && _cursorPointer->isTouched(vec, padding)) {
     206           0 :                 return _cursorPointer;
     207             :         }
     208           0 :         if (_selectionPointerStart->isVisible() && _selectionPointerStart->isTouched(vec, padding)) {
     209           0 :                 return _selectionPointerStart;
     210             :         }
     211           0 :         if (_selectionPointerEnd->isVisible() && _selectionPointerEnd->isTouched(vec, padding)) {
     212           0 :                 return _selectionPointerEnd;
     213             :         }
     214           0 :         return nullptr;
     215             : }
     216             : 
     217           0 : bool InputTextContainer::handleLongPress(const Vec2 &pt, uint32_t tickCount) {
     218           0 :         if (tickCount == 1) {
     219           0 :                 if (_selectedPointer
     220           0 :                                 || (_cursorPointer->isVisible() && _cursorPointer->getOpacity() > 0.0f && _cursorPointer->isTouched(pt))
     221           0 :                                 || (_selectionPointerStart->isVisible() && _selectionPointerStart->getOpacity() > 0.0f && _selectionPointerStart->isTouched(pt))
     222           0 :                                 || (_selectionPointerEnd->isVisible() && _selectionPointerEnd->getOpacity() > 0.0f && _selectionPointerEnd->isTouched(pt))) {
     223           0 :                         return false;
     224             :                 }
     225             : 
     226           0 :                 auto pos = _label->convertToNodeSpace(pt);
     227             : 
     228           0 :                 auto chIdx = _label->getCharIndex(pos, font::CharSelectMode::Center);
     229           0 :                 if (chIdx.first != maxOf<uint32_t>()) {
     230           0 :                         auto word = _label->selectWord(chIdx.first);
     231           0 :                         setCursor(word);
     232           0 :                         if (_cursorCallback) {
     233           0 :                                 _cursorCallback(_cursor);
     234             :                         }
     235           0 :                         scheduleCursorPointer();
     236           0 :                         return true;
     237             :                 }
     238             : 
     239           0 :         } else if (tickCount == 3) {
     240           0 :                 setCursor(TextCursor(0, uint32_t(_label->getCharsCount())));
     241           0 :                 if (_cursorCallback) {
     242           0 :                         _cursorCallback(_cursor);
     243             :                 }
     244           0 :                 scheduleCursorPointer();
     245             :         }
     246           0 :         return false;
     247             : }
     248             : 
     249           0 : bool InputTextContainer::handleSwipeBegin(const Vec2 &pt) {
     250           0 :         auto c = getTouchedCursor(pt);
     251           0 :         if (c != nullptr) {
     252           0 :                 unscheduleCursorPointer();
     253           0 :                 _selectedPointer = c;
     254           0 :                 scheduleUpdate();
     255           0 :                 runAction(Rc<RenderContinuously>::create(), "RenderContinuously"_tag);
     256           0 :                 return true;
     257             :         }
     258           0 :         return false;
     259             : }
     260             : 
     261           0 : bool InputTextContainer::handleSwipe(const Vec2 &pt, const Vec2 &delta) {
     262           0 :         if (_selectedPointer) {
     263           0 :                 unscheduleCursorPointer();
     264           0 :                 auto size = _selectedPointer->getContentSize();
     265           0 :                 auto anchor = _selectedPointer->getAnchorPoint();
     266           0 :                 auto offset = Vec2(anchor.x * size.width - size.width / 2.0f, (anchor.y + 1.0f) * size.height);
     267             : 
     268           0 :                 auto locInLabel = _label->convertToNodeSpace(pt) + offset;
     269             : 
     270           0 :                 if (_selectedPointer == _cursorPointer) {
     271           0 :                         auto chIdx = _label->getCharIndex(locInLabel);
     272           0 :                         if (chIdx.first != maxOf<uint32_t>()) {
     273           0 :                                 auto cursorIdx = chIdx.first;
     274           0 :                                 if (chIdx.second) {
     275           0 :                                         ++ cursorIdx;
     276             :                                 }
     277             : 
     278           0 :                                 if (_cursor.start != cursorIdx) {
     279           0 :                                         setCursor(TextCursor(cursorIdx));
     280           0 :                                         if (_cursorCallback) {
     281           0 :                                                 _cursorCallback(_cursor);
     282             :                                         }
     283             :                                 }
     284             :                         }
     285           0 :                 } else if (_selectedPointer == _selectionPointerStart) {
     286           0 :                         auto charNumber = _label->getCharIndex(locInLabel, font::CharSelectMode::Prefix).first;
     287           0 :                         if (charNumber != maxOf<uint32_t>()) {
     288           0 :                                 if (charNumber != _cursor.start && charNumber < _cursor.start + _cursor.length) {
     289           0 :                                         setCursor(TextCursor(charNumber, (_cursor.start + _cursor.length) - charNumber));
     290             :                                 }
     291             :                         }
     292           0 :                 } else if (_selectedPointer == _selectionPointerEnd) {
     293           0 :                         auto charNumber = _label->getCharIndex(locInLabel, font::CharSelectMode::Suffix).first;
     294           0 :                         if (charNumber != maxOf<uint32_t>()) {
     295           0 :                                 if (charNumber != _cursor.start + _cursor.length - 1 && charNumber >= _cursor.start) {
     296           0 :                                         setCursor(TextCursor(_cursor.start, charNumber - _cursor.start + 1));
     297             :                                 }
     298             :                         }
     299             :                 }
     300           0 :                 return true;
     301             :         }
     302           0 :         return false;
     303             : }
     304             : 
     305           0 : bool InputTextContainer::handleSwipeEnd(const Vec2 &pt) {
     306           0 :         if (_selectedPointer) {
     307           0 :                 _selectedPointer = nullptr;
     308           0 :                 if (_scheduled && _running) {
     309           0 :                         stopActionByTag("RenderContinuously"_tag);
     310           0 :                         unscheduleUpdate();
     311             :                 }
     312           0 :                 scheduleCursorPointer();
     313           0 :                 return true;
     314             :         }
     315           0 :         return false;
     316             : }
     317             : 
     318          10 : void InputTextContainer::touchPointers() {
     319          10 :         if (!_label->empty()) {
     320           0 :                 scheduleCursorPointer();
     321             :         }
     322          10 : }
     323             : 
     324          30 : void InputTextContainer::setCursorCallback(Function<void(TextCursor)> &&cb) {
     325          30 :         _cursorCallback = move(cb);
     326          30 : }
     327             : 
     328           0 : const Function<void(TextCursor)> &InputTextContainer::getCursorCallback() const {
     329           0 :         return _cursorCallback;
     330             : }
     331             : 
     332          80 : void InputTextContainer::updateCursorPosition() {
     333          80 :         Vec2 cpos;
     334          80 :         if (_label->empty()) {
     335          10 :                 cpos = Vec2(0.0f, 0.0f);
     336             :         } else {
     337          70 :                 cpos = _label->getCursorPosition(_cursor.start);
     338             :         }
     339          80 :         _caret->setPosition(cpos);
     340             : 
     341          80 :         const auto labelWidth = _label->getContentSize().width;
     342          80 :         const auto width = _contentSize.width;
     343          80 :         const auto minPos = width - std::max(labelWidth, cpos.x);
     344          80 :         const auto maxPos = 0.0f;
     345             : 
     346          80 :         if (labelWidth <= width) {
     347          80 :                 runAdjustLabel(0.0f);
     348             :         } else {
     349           0 :                 auto maxWidth = std::min(width / 4.0f, 60.0f);
     350           0 :                 auto containerPos = _label->getNodeToParentTransform().transformPoint(cpos);
     351           0 :                 if (containerPos.x < maxWidth || containerPos.x > width - maxWidth) {
     352           0 :                         auto newpos = width / 2.0f - cpos.x;
     353           0 :                         if (newpos < minPos) {
     354           0 :                                 newpos = minPos;
     355           0 :                         } else if (newpos > maxPos) {
     356           0 :                                 newpos = maxPos;
     357             :                         }
     358             : 
     359           0 :                         runAdjustLabel(newpos);
     360             :                 }
     361             :         }
     362             : 
     363          80 :         updateCursorPointers();
     364          80 : }
     365             : 
     366         160 : void InputTextContainer::updateCursorPointers() {
     367         160 :         const auto width = _contentSize.width;
     368             : 
     369         160 :         auto &t = _label->getNodeToParentTransform();
     370             : 
     371         160 :         if (_cursor.length > 0) {
     372          20 :                 auto endPos = t.transformPoint(_label->getCursorPosition(_cursor.start + _cursor.length - 1, false));
     373          20 :                 _selectionPointerEnd->setPosition(endPos + Vec2(_caret->getContentSize().width / 2.0f, 0.0f));
     374             : 
     375          20 :                 if (endPos.x >= 0.0f && endPos.x <= width) {
     376          20 :                         _selectionPointerEnd->setOpacity(1.0f);
     377           0 :                 } else if (endPos.x < 0.0f) {
     378           0 :                         auto op = math::clamp((endPos.x + 10.0f) / 10.0f, 0.0f, 1.0f);
     379           0 :                         _selectionPointerEnd->setOpacity(op);
     380           0 :                 } else if (endPos.x > width) {
     381           0 :                         auto op = math::clamp((width - endPos.x + 10.0f) / 10.0f, 0.0f, 1.0f);
     382           0 :                         _selectionPointerEnd->setOpacity(op);
     383             :                 }
     384             :         }
     385             : 
     386         160 :         auto cursorPos = t.transformPoint(_label->getCursorPosition(_cursor.start, true));
     387             : 
     388         160 :         _cursorPointer->setPosition(cursorPos + Vec2(_caret->getContentSize().width / 2.0f, 0.0f));
     389         160 :         _selectionPointerStart->setPosition(cursorPos + Vec2(_caret->getContentSize().width / 2.0f, 0.0f));
     390             : 
     391         160 :         if (cursorPos.x >= 0.0f && cursorPos.x <= width) {
     392         160 :                 _cursorPointer->setOpacity(1.0f);
     393         160 :                 _selectionPointerStart->setOpacity(1.0f);
     394           0 :         } else if (cursorPos.x < 0.0f) {
     395           0 :                 auto op = math::clamp((cursorPos.x + 10.0f) / 10.0f, 0.0f, 1.0f);
     396           0 :                 _cursorPointer->setOpacity(op);
     397           0 :                 _selectionPointerStart->setOpacity(op);
     398           0 :         } else if (cursorPos.x > width) {
     399           0 :                 auto op = math::clamp((width - cursorPos.x + 10.0f) / 10.0f, 0.0f, 1.0f);
     400           0 :                 _cursorPointer->setOpacity(op);
     401           0 :                 _selectionPointerStart->setOpacity(op);
     402             :         }
     403             : 
     404         160 :         if (_pointerEnabled && !_label->empty()) {
     405           0 :                 if (_cursor.length == 0) {
     406           0 :                         _cursorPointer->setVisible(true);
     407           0 :                         _selectionPointerStart->setVisible(false);
     408           0 :                         _selectionPointerEnd->setVisible(false);
     409             :                 } else {
     410           0 :                         _cursorPointer->setVisible(false);
     411           0 :                         _selectionPointerStart->setVisible(true);
     412           0 :                         _selectionPointerEnd->setVisible(true);
     413             :                 }
     414             :         } else {
     415         160 :                 _cursorPointer->setVisible(false);
     416         160 :                 _selectionPointerStart->setVisible(false);
     417         160 :                 _selectionPointerEnd->setVisible(false);
     418             :         }
     419         160 : }
     420             : 
     421          80 : void InputTextContainer::runAdjustLabel(float pos) {
     422          80 :         if (_selectedPointer) {
     423          80 :                 return;
     424             :         }
     425             : 
     426          80 :         if (_label->getPosition().x == pos) {
     427          80 :                 _label->stopAllActionsByTag("InputTextContainerAdjust"_tag);
     428          80 :                 return;
     429             :         }
     430             : 
     431           0 :         _label->stopAllActionsByTag("InputTextContainerAdjust"_tag);
     432             : 
     433           0 :         const float minT = 0.05f;
     434           0 :         const float maxT = 0.35f;
     435           0 :         const float labelPos = _label->getPosition().x;
     436             : 
     437           0 :         auto dist = std::fabs(labelPos - pos);
     438             : 
     439           0 :         if (_enabled) {
     440           0 :                 if (dist > _contentSize.width * 0.5f) {
     441           0 :                         auto targetPos = labelPos - std::copysign(dist - _contentSize.width * 0.25f, labelPos - pos);
     442           0 :                         _label->setPositionX(targetPos);
     443           0 :                         dist = _contentSize.width * 0.5f;
     444             :                 }
     445             :         }
     446             : 
     447           0 :         auto t = minT;
     448           0 :         if (dist < 16.0f) {
     449           0 :                 t = minT;
     450           0 :         } else if (dist > 80.0f) {
     451           0 :                 t = maxT;
     452             :         } else {
     453           0 :                 t = progress(minT, maxT, (dist - 16.0f) / 80.0f);
     454             :         }
     455             : 
     456           0 :         auto a = makeEasing(Rc<MoveTo>::create(t, Vec2(pos, _label->getPosition().y)));
     457           0 :         _label->runAction(a, "InputTextContainerAdjust"_tag);
     458           0 : }
     459             : 
     460           0 : void InputTextContainer::scheduleCursorPointer() {
     461           0 :         stopAllActionsByTag("TextFieldCursorPointer"_tag);
     462           0 :         setPointerEnabled(true);
     463           0 :         if (_cursor.length == 0) {
     464           0 :                 runAction(Rc<Sequence>::create(3.5f, [this] {
     465           0 :                         setPointerEnabled(false);
     466           0 :                 }), "TextFieldCursorPointer"_tag);
     467             :         }
     468           0 : }
     469             : 
     470         340 : void InputTextContainer::unscheduleCursorPointer() {
     471         340 :         stopAllActionsByTag("TextFieldCursorPointer"_tag);
     472         340 : }
     473             : 
     474         340 : void InputTextContainer::setPointerEnabled(bool value) {
     475         340 :         if (_pointerEnabled != value) {
     476           0 :                 _pointerEnabled = value;
     477           0 :                 updateCursorPointers();
     478             :         }
     479         340 : }
     480             : 
     481             : }

Generated by: LCOV version 1.14