From 651039b0e857eae8a4dcadf92ddaae45e089ce58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Mon, 15 Jun 2020 01:44:29 -0300 Subject: [PATCH] Redesigning UITextInput and all the derivatives to use TextDocument. --- bin/assets/layouts/test_widgets.xml | 2 +- docs/articles/cssspecification.md | 22 +- include/eepp/core/string.hpp | 5 +- include/eepp/graphics/text.hpp | 3 + include/eepp/ui/css/propertydefinition.hpp | 1 - include/eepp/ui/uicombobox.hpp | 2 - include/eepp/ui/uispinbox.hpp | 30 +- include/eepp/ui/uitextinput.hpp | 64 +++-- projects/linux/ee.creator.user | 4 +- src/eepp/core/string.cpp | 5 + src/eepp/graphics/text.cpp | 6 +- src/eepp/maps/mapeditor/mapeditor.cpp | 2 +- src/eepp/maps/mapeditor/uimapnew.cpp | 10 +- src/eepp/ui/css/stylesheetspecification.cpp | 1 - src/eepp/ui/uicombobox.cpp | 7 - src/eepp/ui/uidropdownlist.cpp | 3 +- src/eepp/ui/uispinbox.cpp | 115 ++++---- src/eepp/ui/uitextedit.cpp | 11 +- src/eepp/ui/uitextinput.cpp | 303 ++++++++++++-------- src/eepp/ui/uitextinputpassword.cpp | 38 +-- src/eepp/ui/uitextview.cpp | 1 - src/tests/test_all/test.cpp | 2 +- src/tools/codeeditor/codeeditor.cpp | 30 +- 23 files changed, 370 insertions(+), 297 deletions(-) diff --git a/bin/assets/layouts/test_widgets.xml b/bin/assets/layouts/test_widgets.xml index b880290ab..1f0085326 100644 --- a/bin/assets/layouts/test_widgets.xml +++ b/bin/assets/layouts/test_widgets.xml @@ -55,7 +55,7 @@ - + diff --git a/docs/articles/cssspecification.md b/docs/articles/cssspecification.md index 933a4ac7b..9362f9522 100644 --- a/docs/articles/cssspecification.md +++ b/docs/articles/cssspecification.md @@ -158,10 +158,10 @@ properties. * All properties can be used as attributes of the XML node. * XML attributes are treated as inline CSS styling. * For example: - * Something like: - * `LinearLayout { layout-width: match_parent; layout_height: match_parent; orientation: vertical; }` - * is similar to (but not equivalent, since specificity of inline CSS is higher): - * `` + * Something like: + * `LinearLayout { layout-width: match_parent; layout_height: match_parent; orientation: vertical; }` + * is similar to (but not equivalent, since specificity of inline CSS is higher): + * `` * CSS standard properties directly linked to the Mozilla docs are fully supported, otherwise a clarification will appear. * _Applicable to_ will link to the EE::UI::UIWidget that can use that property, and betweeen parenthesis is the CSS element name. @@ -611,16 +611,6 @@ Same as [background-size](#background-size) but for the foreground. --- -### free-editing - -Allows the cursor to move freely in an input. - -* Applicable to: EE::UI::UITextInput (TextInput) -* Data Type: [boolean](#boolean-data-type) -* Default value: `true` - ---- - ### gravity Sets the horizontal and vertical align of the inner elements/contents of a widget (for example the @@ -1401,9 +1391,9 @@ Defines how the scrollbar should fit inside an scrollable element. * Data Type: [string-list](#string-list-data-type) * Value List: * `inclusive`: The scrollbar is part of the scrollable element container, this means that it will - be on top of the content (scrollbars on mobile usually behave like this). + be on top of the content (scrollbars on mobile usually behave like this). * `exclusive`: The scrollbar is outside the scrollable element container, this means that it will not - be on top of the content (scrollbars on desktop usually behave like this). + be on top of the content (scrollbars on desktop usually behave like this). * Default value: `exclusive` --- diff --git a/include/eepp/core/string.hpp b/include/eepp/core/string.hpp index 75f6c446d..3aed9ca48 100644 --- a/include/eepp/core/string.hpp +++ b/include/eepp/core/string.hpp @@ -238,13 +238,16 @@ class EE_API String { /** Converts from any basic type to std::string */ template static std::string toStr( const T& i ) { std::ostringstream ss; - ss << i; + ss << std::fixed << i; return ss.str(); } static std::string fromFloat( const Float& value, const std::string& append = "", const std::string& prepend = "" ); + static std::string fromDouble( const double& value, const std::string& append = "", + const std::string& prepend = "" ); + /** Converts from a string to type */ template static bool fromString( T& t, const std::string& s, diff --git a/include/eepp/graphics/text.hpp b/include/eepp/graphics/text.hpp index fef407a3f..0480b62e0 100644 --- a/include/eepp/graphics/text.hpp +++ b/include/eepp/graphics/text.hpp @@ -91,6 +91,9 @@ class EE_API Text { /** @return The cached text height */ Float getTextHeight(); + /** @return The line espacing */ + Float getLineSpacing(); + /** Draw the cached text on screen */ void draw( const Float& X, const Float& Y, const Vector2f& Scale = Vector2f::One, const Float& Rotation = 0, BlendMode Effect = BlendAlpha, diff --git a/include/eepp/ui/css/propertydefinition.hpp b/include/eepp/ui/css/propertydefinition.hpp index e5f6c11e7..824aa4e8c 100644 --- a/include/eepp/ui/css/propertydefinition.hpp +++ b/include/eepp/ui/css/propertydefinition.hpp @@ -133,7 +133,6 @@ enum class PropertyId : Uint32 { AllowEditing = String::hash( "allow-editing" ), Locked = String::hash( "locked" ), MaxLength = String::hash( "max-length" ), - FreeEditing = String::hash( "free-editing" ), Numeric = String::hash( "numeric" ), AllowFloat = String::hash( "allow-float" ), TouchDrag = String::hash( "touch-drag" ), diff --git a/include/eepp/ui/uicombobox.hpp b/include/eepp/ui/uicombobox.hpp index 99d9d4080..9e208842f 100644 --- a/include/eepp/ui/uicombobox.hpp +++ b/include/eepp/ui/uicombobox.hpp @@ -25,8 +25,6 @@ class EE_API UIComboBox : public UIWidget { UINode* getButton() const { return mButton; } - InputTextBuffer* getInputTextBuffer(); - const String& getText(); virtual bool applyProperty( const StyleSheetProperty& attribute ); diff --git a/include/eepp/ui/uispinbox.hpp b/include/eepp/ui/uispinbox.hpp index 14de3782c..3e5d4e591 100644 --- a/include/eepp/ui/uispinbox.hpp +++ b/include/eepp/ui/uispinbox.hpp @@ -24,25 +24,25 @@ class EE_API UISpinBox : public UIWidget { const Rectf& getPadding() const; - virtual void setClickStep( const Float& step ); + virtual void setClickStep( const double& step ); - const Float& getClickStep() const; + const double& getClickStep() const; virtual Uint32 onMessage( const NodeMessage* Msg ); - void addValue( const Float& value ); + void addValue( const double& value ); - virtual UISpinBox* setMinValue( const Float& MinVal ); + virtual UISpinBox* setMinValue( const double& minVal ); - const Float& getMinValue() const; + const double& getMinValue() const; - virtual UISpinBox* setMaxValue( const Float& MaxVal ); + virtual UISpinBox* setMaxValue( const double& maxVal ); - const Float& getMaxValue() const; + const double& getMaxValue() const; - virtual UISpinBox* setValue( const Float& Val ); + virtual UISpinBox* setValue( const double& val ); - const Float& getValue() const; + const double& getValue() const; UINode* getButtonPushUp() const; @@ -50,7 +50,7 @@ class EE_API UISpinBox : public UIWidget { UITextInput* getTextInput() const; - UISpinBox* setAllowOnlyNumbers( bool allow ); + UISpinBox* allowFloatingPoint( bool allow ); bool dotsInNumbersAllowed(); @@ -63,15 +63,13 @@ class EE_API UISpinBox : public UIWidget { UITextInput* mInput; UIWidget* mPushUp; UIWidget* mPushDown; - Float mMinValue; - Float mMaxValue; - Float mValue; - Float mClickStep; + double mMinValue; + double mMaxValue; + double mValue; + double mClickStep; void adjustChilds(); - void internalValue( const Float& Val, const bool& Force = false ); - virtual void onSizeChange(); virtual void onPositionChange(); diff --git a/include/eepp/ui/uitextinput.hpp b/include/eepp/ui/uitextinput.hpp index 5308e5afe..640b45f0f 100644 --- a/include/eepp/ui/uitextinput.hpp +++ b/include/eepp/ui/uitextinput.hpp @@ -1,13 +1,17 @@ #ifndef EE_UICUITEXTINPUT_H #define EE_UICUITEXTINPUT_H +#include +#include #include #include #include +using namespace EE::UI::Doc; + namespace EE { namespace UI { -class EE_API UITextInput : public UITextView { +class EE_API UITextInput : public UITextView, public TextDocument::Client { public: static UITextInput* New(); @@ -27,12 +31,8 @@ class EE_API UITextInput : public UITextView { virtual void draw(); - void pushIgnoredChar( const Uint32& ch ); - virtual void setTheme( UITheme* Theme ); - InputTextBuffer* getInputTextBuffer(); - UITextInput* setAllowEditing( const bool& allow ); const bool& isEditingAllowed() const; @@ -43,13 +43,9 @@ class EE_API UITextInput : public UITextView { virtual void shrinkText( const Uint32& MaxWidth ); - UITextInput* setMaxLength( Uint32 maxLength ); + UITextInput* setMaxLength( const Uint32& maxLength ); - Uint32 getMaxLength(); - - UITextInput* setFreeEditing( bool support ); - - bool isFreeEditingEnabled(); + const Uint32& getMaxLength(); virtual bool applyProperty( const StyleSheetProperty& attribute ); @@ -90,8 +86,21 @@ class EE_API UITextInput : public UITextView { UITextView* setHintOutlineColor( const Color& outlineColor ); + /** Block all the inserts, allow only numeric characters. */ + void setAllowOnlyNumbers( const bool& onlyNumbers, const bool& allowFloat = false ); + + /** @return If is only allowing numbers */ + bool onlyNumbersAllowed(); + + /** @return If is only allowing numbers, it allow floating point numbers? */ + bool floatingPointAllowed(); + + TextDocument& getDocument(); + + KeyBindings& getKeyBindings(); + protected: - InputTextBuffer mTextBuffer; + TextDocument mDoc; Float mWaitCursorTime; Vector2f mCurPos; Text* mHintCache; @@ -99,6 +108,11 @@ class EE_API UITextInput : public UITextView { int mCursorPos; bool mAllowEditing; bool mShowingWait; + bool mOnlyNumbers; + bool mAllowFloat; + Uint32 mMaxLength{0}; + KeyBindings mKeyBindings; + void resetWaitCursor(); virtual void alignFix(); @@ -107,8 +121,6 @@ class EE_API UITextInput : public UITextView { virtual void onSizeChange(); - void privOnPressEnter(); - void autoPadding(); virtual Uint32 onMouseDown( const Vector2i& position, const Uint32& flags ); @@ -145,11 +157,29 @@ class EE_API UITextInput : public UITextView { virtual Int32 selCurEnd(); - void onCursorPositionChange(); + virtual void onDocumentTextChanged(); - void onBufferChange(); + virtual void onDocumentCursorChange( const TextPosition& ); - void onInputSelectionChange(); + virtual void onDocumentSelectionChange( const TextRange& ); + + virtual void onDocumentLineCountChange( const size_t& lastCount, const size_t& newCount ); + + virtual void onDocumentLineChanged( const Int64& lineIndex ); + + void registerKeybindings(); + + void registerCommands(); + + void copy(); + + void cut(); + + void paste(); + + virtual Uint32 onKeyDown( const KeyEvent& event ); + + virtual Uint32 onTextInput( const TextInputEvent& event ); }; }} // namespace EE::UI diff --git a/projects/linux/ee.creator.user b/projects/linux/ee.creator.user index 92920fea1..1fed8afda 100644 --- a/projects/linux/ee.creator.user +++ b/projects/linux/ee.creator.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -89,7 +89,7 @@ {6d057187-158a-4883-8d5b-d470a6b6b025} 10 0 - 19 + 15 ../../make/linux diff --git a/src/eepp/core/string.cpp b/src/eepp/core/string.cpp index ad0f3474b..288568d6d 100644 --- a/src/eepp/core/string.cpp +++ b/src/eepp/core/string.cpp @@ -424,6 +424,11 @@ std::string String::fromFloat( const Float& value, const std::string& append, return prepend + toStr( value ) + append; } +std::string String::fromDouble( const double& value, const std::string& append, + const std::string& prepend ) { + return prepend + toStr( value ) + append; +} + void String::insertChar( String& str, const unsigned int& pos, const StringBaseType& tchar ) { str.insert( str.begin() + pos, tchar ); } diff --git a/src/eepp/graphics/text.cpp b/src/eepp/graphics/text.cpp index 53febd07b..4dd1c1af0 100644 --- a/src/eepp/graphics/text.cpp +++ b/src/eepp/graphics/text.cpp @@ -272,7 +272,7 @@ Float Text::getOutlineThickness() const { Vector2f Text::findCharacterPos( std::size_t index ) { // Make sure that we have a valid font - if ( !mFont ) + if ( !mFont || mString.empty() ) return Vector2f(); // Adjust the index if it's out of range @@ -535,6 +535,10 @@ Float Text::getTextHeight() { : 0; } +Float Text::getLineSpacing() { + return NULL != mFont ? mFont->getLineSpacing( mRealFontSize ) : 0; +} + void Text::draw( const Float& X, const Float& Y, const Vector2f& Scale, const Float& Rotation, BlendMode Effect, const OriginPoint& rotationCenter, const OriginPoint& scaleCenter ) { diff --git a/src/eepp/maps/mapeditor/mapeditor.cpp b/src/eepp/maps/mapeditor/mapeditor.cpp index 25ed769f3..904dbb2d5 100644 --- a/src/eepp/maps/mapeditor/mapeditor.cpp +++ b/src/eepp/maps/mapeditor/mapeditor.cpp @@ -581,7 +581,7 @@ void MapEditor::createLighContainer() { mUIBlueTxt->getSize().getHeight() + 16 ), UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); - mLightRadius = UISpinBox::New()->setAllowOnlyNumbers( false )->setValue( 100 ); + mLightRadius = UISpinBox::New()->setValue( 100 ); mLightRadius->setParent( mLightCont ) ->setSize( 100, 0 ) ->setPosition( Txt->getPosition().x, diff --git a/src/eepp/maps/mapeditor/uimapnew.cpp b/src/eepp/maps/mapeditor/uimapnew.cpp index 8a04af74b..151c6600e 100644 --- a/src/eepp/maps/mapeditor/uimapnew.cpp +++ b/src/eepp/maps/mapeditor/uimapnew.cpp @@ -62,7 +62,7 @@ UIMapNew::UIMapNew( UIMap* Map, std::function NewMapCb, bool ResizeMap ) Vector2f( Txt->getPosition().x + DistFromTitle, Txt->getPosition().y + DistFromTitle ), UI_NODE_DEFAULT_FLAGS, Text::Shadow ); - mUIMapWidth = UISpinBox::New()->setAllowOnlyNumbers( false )->setValue( 100 ); + mUIMapWidth = UISpinBox::New()->setValue( 100 ); mUIMapWidth->setParent( mUIWindow->getContainer() ) ->setSize( 53, 0 ) ->setPosition( Txt->getPosition().x + Txt->getSize().getWidth(), Txt->getPosition().y ); @@ -77,7 +77,7 @@ UIMapNew::UIMapNew( UIMap* Map, std::function NewMapCb, bool ResizeMap ) Vector2f( Txt->getPosition().x, Txt->getPosition().y + Txt->getSize().getHeight() + 8 ), UI_NODE_DEFAULT_FLAGS, Text::Shadow ); - mUIMapHeight = UISpinBox::New()->setAllowOnlyNumbers( false )->setValue( 100 ); + mUIMapHeight = UISpinBox::New()->setValue( 100 ); mUIMapHeight->setParent( mUIWindow->getContainer() ) ->setSize( 53, 0 ) ->setPosition( Txt->getPosition().x + Txt->getSize().getWidth(), Txt->getPosition().y ); @@ -96,7 +96,7 @@ UIMapNew::UIMapNew( UIMap* Map, std::function NewMapCb, bool ResizeMap ) Vector2f( Txt->getPosition().x + DistFromTitle, Txt->getPosition().y + DistFromTitle ), UI_NODE_DEFAULT_FLAGS, Text::Shadow ); - mUIMapTWidth = UISpinBox::New()->setAllowOnlyNumbers( false )->setValue( 32 ); + mUIMapTWidth = UISpinBox::New()->setValue( 32 ); mUIMapTWidth->setParent( mUIWindow->getContainer() ) ->setSize( 53, 0 ) ->setPosition( Txt->getPosition().x + Txt->getSize().getWidth(), Txt->getPosition().y ); @@ -111,7 +111,7 @@ UIMapNew::UIMapNew( UIMap* Map, std::function NewMapCb, bool ResizeMap ) Vector2f( Txt->getPosition().x, Txt->getPosition().y + Txt->getSize().getHeight() + 8 ), UI_NODE_DEFAULT_FLAGS, Text::Shadow ); - mUIMapTHeight = UISpinBox::New()->setAllowOnlyNumbers( false )->setValue( 32 ); + mUIMapTHeight = UISpinBox::New()->setValue( 32 ); mUIMapTHeight->setParent( mUIWindow->getContainer() ) ->setSize( 53, 0 ) ->setPosition( Txt->getPosition().x + Txt->getSize().getWidth(), Txt->getPosition().y ); @@ -126,7 +126,7 @@ UIMapNew::UIMapNew( UIMap* Map, std::function NewMapCb, bool ResizeMap ) Vector2f( 16, mUIMapTHeight->getPosition().y + mUIMapTHeight->getSize().getHeight() + 8 ), UI_NODE_DEFAULT_FLAGS | UI_AUTO_SIZE, Text::Shadow ); - mUIMapMaxLayers = UISpinBox::New()->setAllowOnlyNumbers( false )->setValue( 8 ); + mUIMapMaxLayers = UISpinBox::New()->setValue( 8 ); mUIMapMaxLayers->setParent( mUIWindow->getContainer() ) ->setSize( 53, 0 ) ->setPosition( Txt->getPosition().x + DistFromTitle, Txt->getPosition().y + DistFromTitle ); diff --git a/src/eepp/ui/css/stylesheetspecification.cpp b/src/eepp/ui/css/stylesheetspecification.cpp index 7c3a74b2a..97231fb8e 100644 --- a/src/eepp/ui/css/stylesheetspecification.cpp +++ b/src/eepp/ui/css/stylesheetspecification.cpp @@ -276,7 +276,6 @@ void StyleSheetSpecification::registerDefaultProperties() { registerProperty( "allow-editing", "" ).setType( PropertyType::Bool ); registerProperty( "locked", "" ).setType( PropertyType::Bool ); registerProperty( "max-length", "" ).setType( PropertyType::NumberInt ); - registerProperty( "free-editing", "" ).setType( PropertyType::Bool ); registerProperty( "numeric", "" ).setType( PropertyType::Bool ); registerProperty( "allow-float", "" ).setType( PropertyType::Bool ); registerProperty( "touch-drag", "" ).setType( PropertyType::Bool ); diff --git a/src/eepp/ui/uicombobox.cpp b/src/eepp/ui/uicombobox.cpp index 2d0077401..dd55b699d 100644 --- a/src/eepp/ui/uicombobox.cpp +++ b/src/eepp/ui/uicombobox.cpp @@ -14,7 +14,6 @@ UIComboBox::UIComboBox() : UIWidget( "combobox" ), mDropDownList( NULL ), mButto mDropDownList->setVisible( true ); mDropDownList->setEnabled( true ); mDropDownList->setAllowEditing( true ); - mDropDownList->setFreeEditing( true ); mDropDownList->setTextSelection( true ); mDropDownList->addEventListener( Event::OnPaddingChange, [this]( const Event* ) { onPaddingChange(); } ); @@ -64,10 +63,6 @@ UIListBox* UIComboBox::getListBox() { return mDropDownList->getListBox(); } -InputTextBuffer* UIComboBox::getInputTextBuffer() { - return mDropDownList->getInputTextBuffer(); -} - const String& UIComboBox::getText() { return mDropDownList->getText(); } @@ -159,7 +154,6 @@ bool UIComboBox::applyProperty( const StyleSheetProperty& attribute ) { case PropertyId::Text: case PropertyId::AllowEditing: case PropertyId::MaxLength: - case PropertyId::FreeEditing: case PropertyId::Numeric: case PropertyId::AllowFloat: case PropertyId::Hint: @@ -207,7 +201,6 @@ std::string UIComboBox::getPropertyString( const PropertyDefinition* propertyDef case PropertyId::Text: case PropertyId::AllowEditing: case PropertyId::MaxLength: - case PropertyId::FreeEditing: case PropertyId::Numeric: case PropertyId::AllowFloat: case PropertyId::Hint: diff --git a/src/eepp/ui/uidropdownlist.cpp b/src/eepp/ui/uidropdownlist.cpp index 89cdbde9b..a8c2a6851 100644 --- a/src/eepp/ui/uidropdownlist.cpp +++ b/src/eepp/ui/uidropdownlist.cpp @@ -85,7 +85,8 @@ void UIDropDownList::setFriendControl( UINode* friendCtrl ) { } void UIDropDownList::onAutoSize() { - Float max = eemax( PixelDensity::dpToPxI( getSkinSize().getHeight() ), getTextHeight() ); + Float max = eemax( PixelDensity::dpToPxI( getSkinSize().getHeight() ), + mTextCache->getLineSpacing() ); if ( mHeightPolicy == SizePolicy::WrapContent ) { setInternalPixelsHeight( eeceil( max + mRealPadding.Top + mRealPadding.Bottom ) ); diff --git a/src/eepp/ui/uispinbox.cpp b/src/eepp/ui/uispinbox.cpp index ff4f5b9ee..313d40284 100644 --- a/src/eepp/ui/uispinbox.cpp +++ b/src/eepp/ui/uispinbox.cpp @@ -13,7 +13,7 @@ UISpinBox* UISpinBox::New() { UISpinBox::UISpinBox() : UIWidget( "spinbox" ), mMinValue( 0.f ), - mMaxValue( std::numeric_limits::max() ), + mMaxValue( std::numeric_limits::max() ), mValue( 0 ), mClickStep( 1.f ) { mInput = UITextInput::NewWithTag( "spinbox::input" ); @@ -37,11 +37,12 @@ UISpinBox::UISpinBox() : mPushDown->setSize( 8, 8 ); mPushDown->addEventListener( Event::OnSizeChange, cb ); - mInput->getInputTextBuffer()->setAllowOnlyNumbers( true, false ); + mInput->setAllowOnlyNumbers( true, false ); mInput->addEventListener( Event::OnBufferChange, cb::Make1( this, &UISpinBox::onBufferChange ) ); - - internalValue( mValue, true ); + double val = mValue; + mValue += 1; + setValue( val ); applyDefaultTheme(); } @@ -117,11 +118,11 @@ const Rectf& UISpinBox::getPadding() const { return mInput->getPadding(); } -void UISpinBox::setClickStep( const Float& step ) { +void UISpinBox::setClickStep( const double& step ) { mClickStep = step; } -const Float& UISpinBox::getClickStep() const { +const double& UISpinBox::getClickStep() const { return mClickStep; } @@ -148,30 +149,54 @@ Uint32 UISpinBox::onMessage( const NodeMessage* Msg ) { return 0; } -void UISpinBox::addValue( const Float& value ) { +void UISpinBox::addValue( const double& value ) { if ( !mInput->getText().size() ) mInput->setText( String::toStr( static_cast( mMinValue ) ) ); - this->setValue( mValue + value ); + setValue( mValue + value ); } -void UISpinBox::internalValue( const Float& Val, const bool& Force ) { - if ( Force || Val != mValue ) { - if ( Val >= mMinValue && Val <= mMaxValue ) { - Float iValN = ( Float )(Int32)Val; - Float fValN = (Float)iValN; +UISpinBox* UISpinBox::setValue( const double& val ) { + if ( val != mValue ) { + if ( val >= mMinValue && val <= mMaxValue ) { + double iValN = (double)(Int64)val; + double fValN = (double)iValN; - if ( fValN == Val ) { - mInput->setText( String::toStr( iValN ) ); + mValue = val; + + if ( fValN == val ) { + mInput->setText( String::toStr( (Int64)iValN ) ); } else { - mInput->setText( String::toStr( Val ) ); + mInput->setText( String::toStr( val ) ); } - mValue = Val; - onValueChange(); } } + return this; +} + +void UISpinBox::onBufferChange( const Event* ) { + if ( !mInput->getText().size() ) { + setValue( 0 ); + } else { + double val = mValue; + + if ( '.' == mInput->getText()[mInput->getText().size() - 1] ) { + Uint32 pos = (Uint32)mInput->getText().find_first_of( "." ); + + if ( pos != mInput->getText().size() - 1 ) + mInput->setText( mInput->getText().substr( 0, mInput->getText().size() - 1 ) ); + } else { + bool res = String::fromString( val, mInput->getText() ); + + if ( res && val != mValue && val >= mMinValue && val <= mMaxValue ) { + mValue = val; + + onValueChange(); + } + } + } } void UISpinBox::onSizeChange() { @@ -186,17 +211,12 @@ void UISpinBox::onPositionChange() { adjustChilds(); } -UISpinBox* UISpinBox::setValue( const Float& Val ) { - internalValue( Val, false ); - return this; -} - -const Float& UISpinBox::getValue() const { +const double& UISpinBox::getValue() const { return mValue; } -UISpinBox* UISpinBox::setMinValue( const Float& MinVal ) { - mMinValue = MinVal; +UISpinBox* UISpinBox::setMinValue( const double& minVal ) { + mMinValue = minVal; if ( mValue < mMinValue ) mValue = mMinValue; @@ -204,12 +224,12 @@ UISpinBox* UISpinBox::setMinValue( const Float& MinVal ) { return this; } -const Float& UISpinBox::getMinValue() const { +const double& UISpinBox::getMinValue() const { return mMinValue; } -UISpinBox* UISpinBox::setMaxValue( const Float& MaxVal ) { - mMaxValue = MaxVal; +UISpinBox* UISpinBox::setMaxValue( const double& maxVal ) { + mMaxValue = maxVal; if ( mValue > mMaxValue ) mValue = mMaxValue; @@ -217,30 +237,10 @@ UISpinBox* UISpinBox::setMaxValue( const Float& MaxVal ) { return this; } -const Float& UISpinBox::getMaxValue() const { +const double& UISpinBox::getMaxValue() const { return mMaxValue; } -void UISpinBox::onBufferChange( const Event* ) { - if ( !mInput->getText().size() ) { - setValue( 0 ); - } else { - Float Val = mValue; - - if ( '.' == mInput->getText()[mInput->getText().size() - 1] ) { - Uint32 pos = (Uint32)mInput->getText().find_first_of( "." ); - - if ( pos != mInput->getText().size() - 1 ) - mInput->setText( mInput->getText().substr( 0, mInput->getText().size() - 1 ) ); - } else { - bool Res = String::fromString( Val, mInput->getText() ); - - if ( Res ) - setValue( Val ); - } - } -} - UINode* UISpinBox::getButtonPushUp() const { return mPushUp; } @@ -253,14 +253,14 @@ UITextInput* UISpinBox::getTextInput() const { return mInput; } -UISpinBox* UISpinBox::setAllowOnlyNumbers( bool allow ) { - mInput->getInputTextBuffer()->setAllowOnlyNumbers( true, allow ); +UISpinBox* UISpinBox::allowFloatingPoint( bool allow ) { + mInput->setAllowOnlyNumbers( true, allow ); return this; } bool UISpinBox::dotsInNumbersAllowed() { - return mInput->getInputTextBuffer()->dotsInNumbersAllowed(); + return mInput->floatingPointAllowed(); } void UISpinBox::onAlphaChange() { @@ -283,13 +283,13 @@ std::string UISpinBox::getPropertyString( const PropertyDefinition* propertyDef, switch ( propertyDef->getPropertyId() ) { case PropertyId::MinValue: - return String::fromFloat( getMinValue() ); + return String::fromDouble( getMinValue() ); case PropertyId::MaxValue: - return String::fromFloat( getMaxValue() ); + return String::fromDouble( getMaxValue() ); case PropertyId::Value: - return String::fromFloat( getValue() ); + return String::fromDouble( getValue() ); case PropertyId::ClickStep: - return String::fromFloat( getClickStep() ); + return String::fromDouble( getClickStep() ); default: return UIWidget::getPropertyString( propertyDef, propertyIndex ); } @@ -317,7 +317,6 @@ bool UISpinBox::applyProperty( const StyleSheetProperty& attribute ) { case PropertyId::Text: case PropertyId::AllowEditing: case PropertyId::MaxLength: - case PropertyId::FreeEditing: case PropertyId::Numeric: case PropertyId::AllowFloat: case PropertyId::Hint: diff --git a/src/eepp/ui/uitextedit.cpp b/src/eepp/ui/uitextedit.cpp index 532c837bf..2db642d83 100644 --- a/src/eepp/ui/uitextedit.cpp +++ b/src/eepp/ui/uitextedit.cpp @@ -28,7 +28,7 @@ UITextEdit::UITextEdit() : mTextInput->setFlags( UI_TEXT_SELECTION_ENABLED | UI_VALIGN_TOP ); mTextInput->unsetFlags( UI_VALIGN_CENTER | UI_AUTO_SIZE ); mTextInput->clipDisable(); - mTextInput->getInputTextBuffer()->isNewLineEnabled( true ); + //mTextInput->getInputTextBuffer()->isNewLineEnabled( true ); mTextInput->setVisible( true ); mTextInput->setEnabled( true ); mTextInput->setSize( getSize() ); @@ -288,7 +288,7 @@ void UITextEdit::onInputSizeChange( const Event* Event ) { if ( mHScrollBar->isVisible() ) aSize.y -= mHScrollBar->getPixelsSize().getHeight(); - String text( mTextInput->getInputTextBuffer()->getBuffer() ); + /*String text( mTextInput->getInputTextBuffer()->getBuffer() ); shrinkText( aSize.getWidth() ); @@ -298,7 +298,7 @@ void UITextEdit::onInputSizeChange( const Event* Event ) { mTextInput->getInputTextBuffer()->setBuffer( text ); shrinkText( aSize.getWidth() ); - } + }*/ textInputTryResize( aSize, iSize ); @@ -393,7 +393,7 @@ void UITextEdit::fixScroll() { } void UITextEdit::fixScrollToCursor() { - if ( Font::getHorizontalAlign( mTextInput->getFlags() ) == UI_HALIGN_LEFT ) { + /*if ( Font::getHorizontalAlign( mTextInput->getFlags() ) == UI_HALIGN_LEFT ) { Sizef aSize( getAvailableSize() ); if ( mVScrollBar->isVisible() ) @@ -449,7 +449,7 @@ void UITextEdit::fixScrollToCursor() { fixScroll(); mSkipValueChange = false; - } + }*/ invalidateDraw(); } @@ -576,7 +576,6 @@ bool UITextEdit::applyProperty( const StyleSheetProperty& attribute ) { break; } case PropertyId::MaxLength: - case PropertyId::FreeEditing: case PropertyId::Numeric: case PropertyId::AllowFloat: case PropertyId::Hint: diff --git a/src/eepp/ui/uitextinput.cpp b/src/eepp/ui/uitextinput.cpp index 6bc84317e..af9e159d8 100644 --- a/src/eepp/ui/uitextinput.cpp +++ b/src/eepp/ui/uitextinput.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -22,7 +23,13 @@ UITextInput* UITextInput::NewWithTag( const std::string& tag ) { } UITextInput::UITextInput( const std::string& tag ) : - UITextView( tag ), mCursorPos( 0 ), mAllowEditing( true ), mShowingWait( true ) { + UITextView( tag ), + mCursorPos( 0 ), + mAllowEditing( true ), + mShowingWait( true ), + mOnlyNumbers( false ), + mAllowFloat( false ), + mKeyBindings( getUISceneNode()->getWindow()->getInput() ) { mHintCache = Text::New(); UITheme* theme = getUISceneNode()->getUIThemeManager()->getDefaultTheme(); @@ -50,16 +57,9 @@ UITextInput::UITextInput( const std::string& tag ) : setFlags( UI_AUTO_PADDING | UI_AUTO_SIZE | UI_TEXT_SELECTION_ENABLED ); clipEnable(); - mTextBuffer.start(); - mTextBuffer.setActive( false ); - mTextBuffer.setFreeEditing( true ); - mTextBuffer.setTextSelectionEnabled( isTextSelectionEnabled() ); - mTextBuffer.setReturnCallback( cb::Make0( this, &UITextInput::privOnPressEnter ) ); - mTextBuffer.setCursorPositionChangeCallback( - cb::Make0( this, &UITextInput::onCursorPositionChange ) ); - mTextBuffer.setBufferChangeCallback( cb::Make0( this, &UITextInput::onBufferChange ) ); - mTextBuffer.setSelectionChangeCallback( - cb::Make0( this, &UITextInput::onInputSelectionChange ) ); + mDoc.registerClient( this ); + registerCommands(); + registerKeybindings(); applyDefaultTheme(); } @@ -88,8 +88,7 @@ void UITextInput::onCursorPosChange() { } void UITextInput::drawWaitingCursor() { - if ( mVisible && mTextBuffer.isActive() && mTextBuffer.isFreeEditingEnabled() && - mShowingWait ) { + if ( mVisible && hasFocus() && mShowingWait ) { bool disableSmooth = mShowingWait && GLi->isLineSmooth(); if ( disableSmooth ) @@ -116,7 +115,7 @@ void UITextInput::drawWaitingCursor() { } void UITextInput::updateWaitingCursor( const Time& time ) { - if ( mVisible && mTextBuffer.isActive() && mTextBuffer.isFreeEditingEnabled() ) { + if ( mVisible && hasFocus() ) { mWaitCursorTime += time.asMilliseconds(); if ( mWaitCursorTime >= 500.f ) { @@ -150,7 +149,7 @@ void UITextInput::draw() { if ( isClipped() ) { clipSmartDisable(); } - } else if ( !mHintCache->getString().empty() && !mTextBuffer.isActive() ) { + } else if ( !mHintCache->getString().empty() ) { if ( isClipped() ) { clipSmartEnable( mScreenPos.x + mRealPadding.Left, mScreenPos.y + mRealPadding.Top, mSize.getWidth() - mRealPadding.Left - mRealPadding.Right, @@ -176,8 +175,6 @@ Uint32 UITextInput::onFocus() { UINode::onFocus(); if ( mAllowEditing ) { - mTextBuffer.setActive( true ); - resetWaitCursor(); getSceneNode()->getWindow()->startTextInput(); @@ -187,7 +184,6 @@ Uint32 UITextInput::onFocus() { } Uint32 UITextInput::onFocusLoss() { - mTextBuffer.setActive( false ); getSceneNode()->getWindow()->stopTextInput(); return UITextView::onFocusLoss(); } @@ -197,14 +193,6 @@ Uint32 UITextInput::onPressEnter() { return 0; } -void UITextInput::privOnPressEnter() { - onPressEnter(); -} - -void UITextInput::pushIgnoredChar( const Uint32& ch ) { - mTextBuffer.pushIgnoredChar( ch ); -} - void UITextInput::resetWaitCursor() { mShowingWait = true; mWaitCursorTime = 0.f; @@ -214,21 +202,28 @@ void UITextInput::alignFix() { Vector2f rOffset( mRealAlignOffset ); UITextView::alignFix(); + switch ( Font::getVerticalAlign( getFlags() ) ) { + case UI_VALIGN_CENTER: + mRealAlignOffset.y = + ( Float )( ( Int32 )( ( mSize.y - mRealPadding.Top - mRealPadding.Bottom ) / 2 - + mTextCache->getLineSpacing() / 2 ) ) - + 1; + break; + case UI_VALIGN_BOTTOM: + mRealAlignOffset.y = + mSize.y - mRealPadding.Top - mRealPadding.Bottom - mTextCache->getLineSpacing(); + break; + case UI_VALIGN_TOP: + mRealAlignOffset.y = 0; + break; + } + if ( Font::getHorizontalAlign( getFlags() ) == UI_HALIGN_LEFT ) { - Uint32 NLPos = 0; - Uint32 LineNum = mTextBuffer.getCurPosLinePos( NLPos ); - - Text textCache( mTextCache->getFont(), mTextCache->getCharacterSize() ); - - textCache.setString( - mTextBuffer.getBuffer().substr( NLPos, mTextBuffer.getCursorPosition() - NLPos ) ); - - Float tW = textCache.getTextWidth(); + Float tW = mTextCache->findCharacterPos( selCurEnd() ).x; mCurPos.x = tW; - mCurPos.y = (Float)LineNum * (Float)mTextCache->getFont()->getLineSpacing( - mTextCache->getCharacterSizePx() ); + mCurPos.y = 0; - if ( !mTextBuffer.setSupportNewLine() && mSize.getWidth() > 0 ) { + if ( mSize.getWidth() > 0 ) { mRealAlignOffset.x = rOffset.x; Float tX = mRealAlignOffset.x + tW; @@ -263,7 +258,7 @@ void UITextInput::onThemeLoaded() { void UITextInput::onAutoSize() { if ( mHeightPolicy == SizePolicy::WrapContent ) { - int minHeight = eemax( mTextCache->getTextHeight(), + int minHeight = eemax( mTextCache->getLineSpacing(), PixelDensity::dpToPxI( getSkinSize().getHeight() ) ); setInternalPixelsHeight( minHeight + mRealPadding.Top + mRealPadding.Bottom ); } else if ( ( mFlags & UI_AUTO_SIZE ) && 0 == getSize().getHeight() ) { @@ -283,16 +278,8 @@ void UITextInput::autoPadding() { } } -InputTextBuffer* UITextInput::getInputTextBuffer() { - return &mTextBuffer; -} - UITextInput* UITextInput::setAllowEditing( const bool& allow ) { mAllowEditing = allow; - - if ( !mAllowEditing && mTextBuffer.isActive() ) - mTextBuffer.setActive( false ); - return this; } @@ -303,9 +290,8 @@ const bool& UITextInput::isEditingAllowed() const { UITextView* UITextInput::setText( const String& text ) { UITextView::setText( text ); - mTextBuffer.setBuffer( text ); - - mTextBuffer.cursorToEnd(); + mDoc.reset(); + mDoc.textInput( text ); return this; } @@ -314,15 +300,7 @@ const String& UITextInput::getText() { return UITextView::getText(); } -void UITextInput::shrinkText( const Uint32& MaxWidth ) { - mTextCache->setString( mTextBuffer.getBuffer() ); - - UITextView::shrinkText( MaxWidth ); - - mTextBuffer.setBuffer( mTextCache->getString() ); - - alignFix(); -} +void UITextInput::shrinkText( const Uint32& ) {} void UITextInput::updateText() {} @@ -332,8 +310,6 @@ Uint32 UITextInput::onMouseDown( const Vector2i& position, const Uint32& flags ) UITextView::onMouseDown( position, flags ); if ( endPos != selCurEnd() && -1 != selCurEnd() ) { - mTextBuffer.setCursorPosition( selCurEnd() ); - onCursorPositionChange(); resetWaitCursor(); } @@ -344,8 +320,6 @@ Uint32 UITextInput::onMouseDoubleClick( const Vector2i& Pos, const Uint32& Flags UITextView::onMouseDoubleClick( Pos, Flags ); if ( isTextSelectionEnabled() && ( Flags & EE_BUTTON_LMASK ) && selCurEnd() != -1 ) { - mTextBuffer.setCursorPosition( selCurEnd() ); - onCursorPositionChange(); resetWaitCursor(); } @@ -369,46 +343,33 @@ Uint32 UITextInput::onMouseLeave( const Vector2i& Pos, const Uint32& Flags ) { } void UITextInput::selCurInit( const Int32& init ) { - if ( mTextBuffer.selCurInit() != init ) { - mTextBuffer.selCurInit( init ); - invalidateDraw(); + if ( mDoc.getSelection().start().column() != init && -1 != init ) { + mDoc.setSelection( {{0, init}, mDoc.getSelection().end()} ); } } void UITextInput::selCurEnd( const Int32& end ) { - if ( mTextBuffer.selCurEnd() != end ) { - mTextBuffer.selCurEnd( end ); - invalidateDraw(); - - if ( mTextBuffer.selCurEnd() != mTextBuffer.selCurInit() ) { - mTextBuffer.setCursorPosition( end ); - onCursorPosChange(); - } + if ( mDoc.getSelection().end().column() != end && -1 != end ) { + mDoc.setSelection( {mDoc.getSelection().start(), {0, end}} ); + } else if ( -1 == end ) { + mDoc.setSelection( mDoc.getSelection().end() ); } } Int32 UITextInput::selCurInit() { - return mTextBuffer.selCurInit(); + return mDoc.getSelection().start().column(); } Int32 UITextInput::selCurEnd() { - return mTextBuffer.selCurEnd(); + return mDoc.getSelection().end().column(); } -void UITextInput::onCursorPositionChange() { - if ( mCursorPos != mTextBuffer.getCursorPosition() ) { - alignFix(); - mCursorPos = mTextBuffer.getCursorPosition(); - mWaitCursorTime = 0.f; - mShowingWait = true; - onCursorPosChange(); - } -} - -void UITextInput::onBufferChange() { +void UITextInput::onDocumentTextChanged() { Vector2f offSet = mRealAlignOffset; - UITextView::setText( mTextBuffer.getBuffer() ); + const String& text = mDoc.line( 0 ).getText(); + + UITextView::setText( !text.empty() ? text.substr( 0, text.size() - 1 ) : "" ); updateText(); @@ -418,35 +379,33 @@ void UITextInput::onBufferChange() { alignFix(); - mCursorPos = mTextBuffer.getCursorPosition(); - - mTextBuffer.setChangedSinceLastUpdate( false ); - invalidateDraw(); sendCommonEvent( Event::OnBufferChange ); } -void UITextInput::onInputSelectionChange() { +void UITextInput::onDocumentCursorChange( const TextPosition& ) { + alignFix(); + mWaitCursorTime = 0.f; + mShowingWait = true; + onCursorPosChange(); +} + +void UITextInput::onDocumentSelectionChange( const TextRange& ) { onSelectionChange(); } -UITextInput* UITextInput::setMaxLength( Uint32 maxLength ) { - mTextBuffer.setMaxLength( maxLength ); +void UITextInput::onDocumentLineCountChange( const size_t&, const size_t& ) {} + +void UITextInput::onDocumentLineChanged( const Int64& ) {} + +UITextInput* UITextInput::setMaxLength( const Uint32& maxLength ) { + mMaxLength = maxLength; return this; } -Uint32 UITextInput::getMaxLength() { - return mTextBuffer.getMaxLength(); -} - -UITextInput* UITextInput::setFreeEditing( bool support ) { - mTextBuffer.setFreeEditing( support ); - return this; -} - -bool UITextInput::isFreeEditingEnabled() { - return mTextBuffer.isFreeEditingEnabled(); +const Uint32& UITextInput::getMaxLength() { + return mMaxLength; } std::string UITextInput::getPropertyString( const PropertyDefinition* propertyDef, @@ -461,12 +420,10 @@ std::string UITextInput::getPropertyString( const PropertyDefinition* propertyDe return isEditingAllowed() ? "true" : "false"; case PropertyId::MaxLength: return String::toStr( getMaxLength() ); - case PropertyId::FreeEditing: - return isFreeEditingEnabled() ? "true" : "false"; case PropertyId::Numeric: - return getInputTextBuffer()->onlyNumbersAllowed() ? "true" : "false"; + return onlyNumbersAllowed() ? "true" : "false"; case PropertyId::AllowFloat: - return getInputTextBuffer()->dotsInNumbersAllowed() ? "true" : "false"; + return floatingPointAllowed() ? "true" : "false"; case PropertyId::Hint: return getHint().toUtf8(); case PropertyId::HintColor: @@ -503,16 +460,11 @@ bool UITextInput::applyProperty( const StyleSheetProperty& attribute ) { case PropertyId::MaxLength: setMaxLength( attribute.asUint() ); break; - case PropertyId::FreeEditing: - setFreeEditing( attribute.asBool() ); - break; case PropertyId::Numeric: - getInputTextBuffer()->setAllowOnlyNumbers( - attribute.asBool(), getInputTextBuffer()->dotsInNumbersAllowed() ); + setAllowOnlyNumbers( attribute.asBool(), floatingPointAllowed() ); break; case PropertyId::AllowFloat: - getInputTextBuffer()->setAllowOnlyNumbers( getInputTextBuffer()->onlyNumbersAllowed(), - attribute.asBool() ); + setAllowOnlyNumbers( onlyNumbersAllowed(), attribute.asBool() ); break; case PropertyId::Hint: if ( NULL != getUISceneNode() ) @@ -677,4 +629,121 @@ UITextView* UITextInput::setHintFontStyle( const Uint32& fontStyle ) { return this; } +void UITextInput::copy() { + getUISceneNode()->getWindow()->getClipboard()->setText( mDoc.getSelectedText() ); +} + +void UITextInput::cut() { + getUISceneNode()->getWindow()->getClipboard()->setText( mDoc.getSelectedText() ); + mDoc.deleteSelection(); +} + +void UITextInput::paste() { + String pasted( getUISceneNode()->getWindow()->getClipboard()->getText() ); + String::replaceAll( pasted, "\n", "" ); + mDoc.textInput( pasted ); +} + +void UITextInput::registerCommands() { + mDoc.setCommand( "copy", [&] { copy(); } ); + mDoc.setCommand( "cut", [&] { cut(); } ); + mDoc.setCommand( "paste", [&] { paste(); } ); + mDoc.setCommand( "press-enter", [&] { onPressEnter(); } ); +} + +void UITextInput::registerKeybindings() { + mKeyBindings.addKeybinds( { + {{KEY_BACKSPACE, KEYMOD_CTRL}, "delete-to-previous-word"}, + {{KEY_BACKSPACE, KEYMOD_SHIFT}, "delete-to-previous-char"}, + {{KEY_BACKSPACE, 0}, "delete-to-previous-char"}, + {{KEY_DELETE, KEYMOD_CTRL}, "delete-to-next-word"}, + {{KEY_DELETE, 0}, "delete-to-next-char"}, + {{KEY_KP_ENTER, 0}, "press-enter"}, + {{KEY_RETURN, 0}, "press-enter"}, + {{KEY_LEFT, KEYMOD_CTRL | KEYMOD_SHIFT}, "select-to-previous-word"}, + {{KEY_LEFT, KEYMOD_CTRL}, "move-to-previous-word"}, + {{KEY_LEFT, KEYMOD_SHIFT}, "select-to-previous-char"}, + {{KEY_LEFT, 0}, "move-to-previous-char"}, + {{KEY_RIGHT, KEYMOD_CTRL | KEYMOD_SHIFT}, "select-to-next-word"}, + {{KEY_RIGHT, KEYMOD_CTRL}, "move-to-next-word"}, + {{KEY_RIGHT, KEYMOD_SHIFT}, "select-to-next-char"}, + {{KEY_RIGHT, 0}, "move-to-next-char"}, + {{KEY_Z, KEYMOD_CTRL | KEYMOD_SHIFT}, "redo"}, + {{KEY_HOME, KEYMOD_CTRL | KEYMOD_SHIFT}, "select-to-start-of-doc"}, + {{KEY_HOME, KEYMOD_SHIFT}, "select-to-start-of-content"}, + {{KEY_HOME, KEYMOD_CTRL}, "move-to-start-of-doc"}, + {{KEY_HOME, 0}, "move-to-start-of-content"}, + {{KEY_END, KEYMOD_CTRL | KEYMOD_SHIFT}, "select-to-end-of-doc"}, + {{KEY_END, KEYMOD_SHIFT}, "select-to-end-of-line"}, + {{KEY_END, KEYMOD_CTRL}, "move-to-end-of-doc"}, + {{KEY_END, 0}, "move-to-end-of-line"}, + {{KEY_Y, KEYMOD_CTRL}, "redo"}, + {{KEY_Z, KEYMOD_CTRL}, "undo"}, + {{KEY_C, KEYMOD_CTRL}, "copy"}, + {{KEY_X, KEYMOD_CTRL}, "cut"}, + {{KEY_V, KEYMOD_CTRL}, "paste"}, + {{KEY_A, KEYMOD_CTRL}, "select-all"}, + } ); +} + +Uint32 UITextInput::onKeyDown( const KeyEvent& event ) { + std::string cmd = mKeyBindings.getCommandFromKeyBind( {event.getKeyCode(), event.getMod()} ); + if ( !cmd.empty() ) { + // Allow copy selection on locked mode + if ( mAllowEditing ) { + mDoc.execute( cmd ); + return 1; + } + } + return 0; +} + +Uint32 UITextInput::onTextInput( const TextInputEvent& event ) { + if ( !mAllowEditing ) + return 0; + Input* input = getUISceneNode()->getWindow()->getInput(); + + if ( !input->isControlPressed() && !( input->isAltPressed() && input->isShiftPressed() ) ) { + if ( input->isAltPressed() && !event.getText().empty() && event.getText()[0] == '\t' ) + return 0; + + const String& text = event.getText(); + + for ( size_t i = 0; i < text.size(); i++ ) { + if ( text[i] == '\n' ) + return 0; + if ( mOnlyNumbers && + ( ( mAllowFloat && text[i] == '.' && mDoc.find( "." ).isValid() ) || + !String::isNumber( text[i], mAllowFloat ) ) ) { + return 0; + } + } + + mDoc.textInput( text ); + return 1; + } + return 0; +} + +void UITextInput::setAllowOnlyNumbers( const bool& onlyNumbers, const bool& allowFloat ) { + mOnlyNumbers = onlyNumbers; + mAllowFloat = allowFloat; +} + +bool UITextInput::onlyNumbersAllowed() { + return mOnlyNumbers; +} + +bool UITextInput::floatingPointAllowed() { + return mAllowFloat; +} + +TextDocument& UITextInput::getDocument() { + return mDoc; +} + +KeyBindings& UITextInput::getKeyBindings() { + return mKeyBindings; +} + }} // namespace EE::UI diff --git a/src/eepp/ui/uitextinputpassword.cpp b/src/eepp/ui/uitextinputpassword.cpp index 09d3ea514..f672a676c 100644 --- a/src/eepp/ui/uitextinputpassword.cpp +++ b/src/eepp/ui/uitextinputpassword.cpp @@ -44,7 +44,7 @@ void UITextInputPassword::draw() { if ( isClipped() ) { clipSmartDisable(); } - } else if ( !mHintCache->getString().empty() && !mTextBuffer.isActive() ) { + } else if ( !mHintCache->getString().empty() ) { if ( isClipped() ) { clipSmartEnable( mScreenPos.x + mRealPadding.Left, mScreenPos.y + mRealPadding.Top, mSize.getWidth() - mRealPadding.Left - mRealPadding.Right, @@ -106,31 +106,17 @@ void UITextInputPassword::alignFix() { } if ( Font::getHorizontalAlign( getFlags() ) == UI_HALIGN_LEFT ) { - Uint32 NLPos = 0; - Uint32 LineNum = mTextBuffer.getCurPosLinePos( NLPos ); - - String curStr( - mTextBuffer.getBuffer().substr( NLPos, mTextBuffer.getCursorPosition() - NLPos ) ); - String pasStr; - - for ( size_t i = 0; i < curStr.size(); i++ ) - pasStr += mBulletCharacter; - - mPassCache->setString( pasStr ); - - Float tW = mPassCache->getTextWidth(); + Float tW = mPassCache->findCharacterPos( selCurEnd() ).x; Float tX = mRealAlignOffset.x + tW; mCurPos.x = tW; - mCurPos.y = (Float)LineNum * (Float)mPassCache->getFont()->getLineSpacing( - mPassCache->getCharacterSizePx() ); + mCurPos.y = 0; - if ( !mTextBuffer.setSupportNewLine() ) { - if ( tX < 0.f ) - mRealAlignOffset.x = -( mRealAlignOffset.x + ( tW - mRealAlignOffset.x ) ); - else if ( tX > mSize.getWidth() - mRealPadding.Left - mRealPadding.Right ) - mRealAlignOffset.x = mSize.getWidth() - mRealPadding.Left - mRealPadding.Right - - ( mRealAlignOffset.x + ( tW - mRealAlignOffset.x ) ); + if ( tX < 0.f ) { + mRealAlignOffset.x = -( mRealAlignOffset.x + ( tW - mRealAlignOffset.x ) ); + } else if ( tX > mSize.getWidth() - mRealPadding.Left - mRealPadding.Right ) { + mRealAlignOffset.x = mSize.getWidth() - mRealPadding.Left - mRealPadding.Right - + ( mRealAlignOffset.x + ( tW - mRealAlignOffset.x ) ); } } } @@ -141,10 +127,10 @@ void UITextInputPassword::updateText() { void UITextInputPassword::updatePass( const String& pass ) { String newTxt; - - for ( size_t i = 0; i < pass.size(); i++ ) - newTxt += mBulletCharacter; - + if ( !pass.empty() ) { + for ( size_t i = 0; i < pass.size() - 1; i++ ) + newTxt += mBulletCharacter; + } mPassCache->setString( newTxt ); } diff --git a/src/eepp/ui/uitextview.cpp b/src/eepp/ui/uitextview.cpp index 1fcda661b..215938ca1 100644 --- a/src/eepp/ui/uitextview.cpp +++ b/src/eepp/ui/uitextview.cpp @@ -590,7 +590,6 @@ void UITextView::recalculate() { void UITextView::resetSelCache() { mLastSelCurInit = mLastSelCurEnd = -1; - invalidateDraw(); onSelectionChange(); } diff --git a/src/tests/test_all/test.cpp b/src/tests/test_all/test.cpp index ce9f64bd1..17b49ca81 100644 --- a/src/tests/test_all/test.cpp +++ b/src/tests/test_all/test.cpp @@ -428,7 +428,7 @@ void EETest::createBaseUI() { ->setPosition( 60, 110 ) ->setSize( 80, 24 ); - UISpinBox::New()->setAllowOnlyNumbers( true )->setParent( C )->setPosition( 80, 150 )->setSize( + UISpinBox::New()->allowFloatingPoint( true )->setParent( C )->setPosition( 80, 150 )->setSize( 80, 24 ); mScrollBar = UIScrollBar::New(); diff --git a/src/tools/codeeditor/codeeditor.cpp b/src/tools/codeeditor/codeeditor.cpp index f8c424e14..16831f7bf 100644 --- a/src/tools/codeeditor/codeeditor.cpp +++ b/src/tools/codeeditor/codeeditor.cpp @@ -656,25 +656,22 @@ void App::initSearchBar() { } ); }; auto addReturnListener = [&]( UIWidget* widget, std::string cmd ) { - widget->addEventListener( Event::KeyDown, [this, cmd]( const Event* event ) { - const KeyEvent* keyEvent = static_cast( event ); - if ( keyEvent->getKeyCode() == KEY_RETURN ) - mSearchBarLayout->execute( cmd ); + widget->addEventListener( Event::OnPressEnter, [this, cmd]( const Event* ) { + mSearchBarLayout->execute( cmd ); } ); }; UITextInput* findInput = mSearchBarLayout->find( "search_find" ); UITextInput* replaceInput = mSearchBarLayout->find( "search_replace" ); UICheckBox* caseSensitiveChk = mSearchBarLayout->find( "case_sensitive" ); - findInput->getInputTextBuffer()->pushIgnoredChar( '\t' ); - replaceInput->getInputTextBuffer()->pushIgnoredChar( '\t' ); - findInput->addEventListener( Event::OnTextChanged, [&, findInput]( const Event* ) { - if ( !findInput->getText().empty() ) { - findNextText( findInput->getText(), caseSensitiveChk->isChecked() ); - } else if ( mCurEditor ) { - mCurEditor->getDocument().setSelection( - mCurEditor->getDocument().getSelection().start() ); - } - } ); + findInput->addEventListener( + Event::OnTextChanged, [&, findInput, caseSensitiveChk]( const Event* ) { + if ( !findInput->getText().empty() ) { + findNextText( findInput->getText(), caseSensitiveChk->isChecked() ); + } else if ( mCurEditor ) { + mCurEditor->getDocument().setSelection( + mCurEditor->getDocument().getSelection().start() ); + } + } ); mSearchBarLayout->addCommand( "close-searchbar", [&] { mSearchBarLayout->setEnabled( false )->setVisible( false ); mCurEditor->setFocus(); @@ -727,7 +724,7 @@ void App::showFindView() { String text = mCurEditor->getDocument().getSelectedText(); if ( !text.empty() ) { findInput->setText( text ); - findInput->getInputTextBuffer()->selectAll(); + findInput->getDocument().selectAll(); } } @@ -947,7 +944,8 @@ void App::init( const std::string& file, const Float& pidelDensity ) { mTheme = UITheme::load( "uitheme", "uitheme", "", font, resPath + "assets/ui/breeze.css" ); mUISceneNode->setStyleSheet( mTheme->getStyleSheet() ); - mUISceneNode->getUIThemeManager() + mUISceneNode + ->getUIThemeManager() //->setDefaultEffectsEnabled( true ) ->setDefaultTheme( mTheme ) ->setDefaultFont( font )