From 0207180e0e32d84a440bc979f67d78204caed4c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Wed, 29 Apr 2020 03:37:05 -0300 Subject: [PATCH] Fixes in UITextEdit. Some minor performance improvements in the PropertyDefinition class. Breeze theme improvements. And some other minor changes. --- bin/assets/layouts/test_widgets.xml | 6 +- bin/assets/ui/breeze.css | 54 +++-- bin/assets/ui/uitheme.css | 2 +- include/eepp/system/resourcemanager.hpp | 11 +- include/eepp/ui/css/propertyspecification.hpp | 10 +- .../eepp/ui/css/stylesheetspecification.hpp | 5 +- include/eepp/ui/uitextedit.hpp | 8 +- include/eepp/ui/uiwidget.hpp | 2 + include/eepp/ui/uiwindow.hpp | 6 +- src/eepp/ui/css/propertydefinition.cpp | 21 +- src/eepp/ui/css/propertyspecification.cpp | 72 +++--- src/eepp/ui/css/stylesheetparser.cpp | 14 +- src/eepp/ui/css/stylesheetspecification.cpp | 27 ++- src/eepp/ui/tools/textureatlasnew.cpp | 3 +- src/eepp/ui/uiscenenode.cpp | 16 +- src/eepp/ui/uitextedit.cpp | 207 +++++++++++------- src/eepp/ui/uiwidget.cpp | 4 + src/eepp/ui/uiwindow.cpp | 11 +- src/test/eetest.cpp | 4 +- 19 files changed, 311 insertions(+), 172 deletions(-) diff --git a/bin/assets/layouts/test_widgets.xml b/bin/assets/layouts/test_widgets.xml index eaca435c5..d623cc3a6 100644 --- a/bin/assets/layouts/test_widgets.xml +++ b/bin/assets/layouts/test_widgets.xml @@ -32,7 +32,7 @@ - + @@ -57,7 +57,7 @@ - + @@ -70,7 +70,7 @@ - + diff --git a/bin/assets/ui/breeze.css b/bin/assets/ui/breeze.css index 263663651..62e3d825c 100644 --- a/bin/assets/ui/breeze.css +++ b/bin/assets/ui/breeze.css @@ -30,6 +30,10 @@ --menu-font: #eff0f1; --menu-border: #616569; --menu-font-active: white; + --icon-back-hover: #eff0f1; + --icon-line-hover: #3d4246; + --icon-back-alert: #d9727c; + --win-icon: #dbdbdd; } * { @@ -219,20 +223,23 @@ SpinBox::btndown { height: 13dp; } -TextEdit::input { +TextEdit { background-color: var(--list-back); border-color: var(--button-border); border-radius: var(--button-radius); border-width: var(--border-width); + transition: all 0.15; +} + +TextEdit::input { padding-left: var(--base-horizontal-padding); padding-right: var(--base-horizontal-padding); padding-top: var(--base-vertical-padding); padding-bottom: var(--base-vertical-padding); - transition: all 0.15; } -TextEdit::input:focus, -TextEdit::input:hover { +TextEdit:focus, +TextEdit:hover { border-color: var(--primary); } @@ -418,42 +425,53 @@ Loader { Window::close { width: 12dp; height: 12dp; - foreground-image: poly(line, var(--icon), "0dp 0dp, 8dp 8dp"), poly(line, var(--icon), "8dp 0dp, 0dp 8dp"); - foreground-position: 2dp 2dp, 2dp 2dp; + border-radius: 6dp; + background-color: var(--icon-back-hover); + foreground-image: poly(line, var(--icon-line-hover), "0dp 0dp, 6dp 6dp"), poly(line, var(--icon-line-hover), "6dp 0dp, 0dp 6dp"); + foreground-position: 3dp 3dp, 3dp 3dp; + transition: all 0.15s; } Window::close:hover { - foreground-image: poly(line, var(--icon-active), "0dp 0dp, 8dp 8dp"), poly(line, var(--icon-active), "8dp 0dp, 0dp 8dp"); + background-color: var(--icon-back-alert); } Window::maximize { width: 12dp; height: 12dp; - foreground-image: rectangle(line, var(--icon)), rectangle(solid, var(--icon)); - foreground-size: 8dp 8dp, 8dp 2dp; - foreground-position: 2dp 2dp, 2dp 2dp; + border-radius: 6dp; + background-color: transparent; + foreground-image: poly(line, var(--win-icon), "0dp 4dp, 4dp 0dp"), poly(line, var(--win-icon), "4dp 0dp, 8dp 4dp"); + foreground-position: 2dp 4dp, 2dp 4dp; + transition: all 0.15s; } Window::maximize:hover { - foreground-image: rectangle(line, var(--icon-active)), rectangle(solid, var(--icon-active)); + background-color: var(--icon-back-hover); + foreground-image: poly(line, var(--icon-line-hover), "0dp 4dp, 4dp 0dp"), poly(line, var(--icon-line-hover), "4dp 0dp, 8dp 4dp"); } Window::minimize { width: 12dp; height: 12dp; - foreground-image: rectangle(solid, var(--icon)); - foreground-size: 8dp 2dp; - foreground-position: 2dp 8dp; + border-radius: 6dp; + background-color: transparent; + foreground-image: poly(line, var(--win-icon), "0dp 0dp, 4dp 4dp"), poly(line, var(--win-icon), "4dp 4dp, 8dp 0dp"); + foreground-position: 2dp 4dp, 2dp 4dp; + transition: all 0.15s; } Window::minimize:hover { - foreground-image: rectangle(solid, var(--icon-active)); + background-color: var(--icon-back-hover); + foreground-image: poly(line, var(--icon-line-hover), "0dp 0dp, 4dp 4dp"), poly(line, var(--icon-line-hover), "4dp 4dp, 8dp 0dp"); } Window { background-color: var(--back); window-border-size: 2dp 2dp; window-titlebar-size: 24dp 24dp; + window-buttons-offset: -6dp 0dp; + window-buttons-separation: 8dp; window-flags: shadow; } @@ -614,6 +632,12 @@ Menu::CheckBox::icon:selected { background-position: center; } +ListBox > ScrollBar, +TextEdit > ScrollBar, +Table > ScrollBar { + background-color: var(--list-back); +} + .appbackground { background-color: var(--back); } diff --git a/bin/assets/ui/uitheme.css b/bin/assets/ui/uitheme.css index 490bf1294..52b22b4a6 100644 --- a/bin/assets/ui/uitheme.css +++ b/bin/assets/ui/uitheme.css @@ -36,7 +36,7 @@ Menu, PopUpMenu { color: #E6E6E6FF; min-width: 100dp; - min-icon-size: 16dp 16dp; + min-icon-size: 24dp 24dp; } Menu::Item, diff --git a/include/eepp/system/resourcemanager.hpp b/include/eepp/system/resourcemanager.hpp index f12360140..a89ae41cc 100644 --- a/include/eepp/system/resourcemanager.hpp +++ b/include/eepp/system/resourcemanager.hpp @@ -8,14 +8,15 @@ namespace EE { namespace System { /** @brief A simple resource manager. It keeps a list of the resources, and free the instances of -*the resources when the manager is closed. -** Resources must have Id() and Name() properties. Id() is the string hash of Name(). */ + * the resources when the manager is closed. Resources must have getId() and getName() properties. + * getId() is the string hash of getName(). + */ template class ResourceManager { public: /** @param UniqueId Indicates if the resources id must be unique */ ResourceManager( bool UniqueId = true ); - /** @brief The destructor will call Destroy() and destroy all the resources added to the manager + /** @brief The destructor will call destroy() and destroy all the resources added to the manager */ virtual ~ResourceManager(); @@ -30,11 +31,11 @@ template class ResourceManager { bool remove( T* Resource, bool Delete = true ); /** @brief Removes the resource by its id - ** @see Remove */ + ** @see remove */ bool removeById( const Uint32& Id, bool Delete = true ); /** @brief Removes the resource by its name - ** @see Remove */ + ** @see remove */ bool removeByName( const std::string& Name, bool Delete = true ); /** @returns A resource by its name. If not found returns NULL. */ diff --git a/include/eepp/ui/css/propertyspecification.hpp b/include/eepp/ui/css/propertyspecification.hpp index b010fcc68..e371ef603 100644 --- a/include/eepp/ui/css/propertyspecification.hpp +++ b/include/eepp/ui/css/propertyspecification.hpp @@ -1,13 +1,16 @@ #ifndef EE_UI_CSS_PROPERTYSPECIFICATION_HPP #define EE_UI_CSS_PROPERTYSPECIFICATION_HPP +#include #include #include #include +#include namespace EE { namespace UI { namespace CSS { class EE_API PropertySpecification { + SINGLETON_DECLARE_HEADERS( PropertySpecification ) public: ~PropertySpecification(); @@ -31,8 +34,11 @@ class EE_API PropertySpecification { bool isShorthand( const Uint32& id ) const; protected: - std::vector mProperties; - std::vector mShorthands; + friend class PropertyDefinition; + std::unordered_map> mProperties; + std::unordered_map> mShorthands; + + const PropertyDefinition* addPropertyAlias( Uint32 aliasId, const PropertyDefinition* propDef ); }; }}} // namespace EE::UI::CSS diff --git a/include/eepp/ui/css/stylesheetspecification.hpp b/include/eepp/ui/css/stylesheetspecification.hpp index 5717c14a8..c1e55ceac 100644 --- a/include/eepp/ui/css/stylesheetspecification.hpp +++ b/include/eepp/ui/css/stylesheetspecification.hpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include @@ -15,6 +14,8 @@ class UIWidget; namespace EE { namespace UI { namespace CSS { +class PropertySpecification; + typedef std::function StyleSheetNodeSelector; @@ -66,7 +67,7 @@ class EE_API StyleSheetSpecification { DrawableImageParser& getDrawableImageParser(); protected: - PropertySpecification mPropertySpecification; + PropertySpecification* mPropertySpecification; DrawableImageParser mDrawableImageParser; std::map mShorthandParsers; std::map mNodeSelectors; diff --git a/include/eepp/ui/uitextedit.hpp b/include/eepp/ui/uitextedit.hpp index 5f537aa76..3414d5194 100644 --- a/include/eepp/ui/uitextedit.hpp +++ b/include/eepp/ui/uitextedit.hpp @@ -85,7 +85,13 @@ class EE_API UITextEdit : public UIWidget { void fixScrollToCursor(); - void shrinkText( const Uint32& Width ); + void shrinkText( const Float& width ); + + void textInputTryResize(); + + Sizef getAvailableSize(); + + Sizef getInputSize(); }; }} // namespace EE::UI diff --git a/include/eepp/ui/uiwidget.hpp b/include/eepp/ui/uiwidget.hpp index 453b93165..1d0201107 100644 --- a/include/eepp/ui/uiwidget.hpp +++ b/include/eepp/ui/uiwidget.hpp @@ -116,6 +116,8 @@ class EE_API UIWidget : public UINode { const Rectf& getPadding() const; + const Rectf& getPixelsPadding() const; + UIWidget* setPadding( const Rectf& padding ); UIWidget* setPaddingLeft( const Float& paddingLeft ); diff --git a/include/eepp/ui/uiwindow.hpp b/include/eepp/ui/uiwindow.hpp index 5381ad294..db9442af3 100644 --- a/include/eepp/ui/uiwindow.hpp +++ b/include/eepp/ui/uiwindow.hpp @@ -160,6 +160,10 @@ class EE_API UIWindow : public UIWidget { std::string getWindowFlagsString(); + Sizef getMinWindowSizeWithDecoration(); + + Sizef getSizeWithoutDecoration(); + protected: enum UI_RESIZE_TYPE { RESIZE_NONE, @@ -262,8 +266,6 @@ class EE_API UIWindow : public UIWidget { virtual void onWindowReady(); - Sizef getMinWindowSizeWithDecoration(); - void onContainerPositionChange( const Event* Event ); void setupModal(); diff --git a/src/eepp/ui/css/propertydefinition.cpp b/src/eepp/ui/css/propertydefinition.cpp index 30f0ecbf2..c261fb220 100644 --- a/src/eepp/ui/css/propertydefinition.cpp +++ b/src/eepp/ui/css/propertydefinition.cpp @@ -1,6 +1,7 @@ #include #include #include +#include namespace EE { namespace UI { namespace CSS { @@ -18,16 +19,7 @@ PropertyDefinition::PropertyDefinition( const std::string& name, const std::stri mInherited( inherited ), mIndexed( false ), mRelativeTarget( PropertyRelativeTarget::None ), - mPropertyType( PropertyType::Undefined ) { - - for ( auto& sep : {"-", "_"} ) { - if ( mName.find( sep ) != std::string::npos ) { - std::string alias( name ); - String::replaceAll( alias, sep, "" ); - addAlias( alias ); - } - } -} + mPropertyType( PropertyType::Undefined ) {} const std::string& PropertyDefinition::getName() const { return mName; @@ -69,8 +61,10 @@ const PropertyType& PropertyDefinition::getType() const { } PropertyDefinition& PropertyDefinition::addAlias( const std::string& alias ) { + Uint32 aliasId = String::hash( alias ); mAliases.push_back( alias ); - mAliasesHash.push_back( String::hash( alias ) ); + mAliasesHash.push_back( aliasId ); + PropertySpecification::instance()->addPropertyAlias( aliasId, this ); return *this; } @@ -79,8 +73,9 @@ bool PropertyDefinition::isAlias( const std::string& alias ) const { } bool PropertyDefinition::isAlias( const Uint32& id ) const { - for ( auto& tid : mAliasesHash ) { - if ( tid == id ) + size_t size = mAliasesHash.size(); + for ( size_t i = 0; i < size; i++ ) { + if ( mAliasesHash[i] == id ) return true; } return false; diff --git a/src/eepp/ui/css/propertyspecification.cpp b/src/eepp/ui/css/propertyspecification.cpp index b4dc0bb61..ce73c7469 100644 --- a/src/eepp/ui/css/propertyspecification.cpp +++ b/src/eepp/ui/css/propertyspecification.cpp @@ -3,39 +3,42 @@ namespace EE { namespace UI { namespace CSS { -PropertySpecification::~PropertySpecification() { - for ( std::size_t i = 0; i < mProperties.size(); i++ ) { - eeSAFE_DELETE( mProperties[i] ); - } +SINGLETON_DECLARE_IMPLEMENTATION( PropertySpecification ) - for ( std::size_t i = 0; i < mShorthands.size(); i++ ) { - eeSAFE_DELETE( mShorthands[i] ); - } -} +PropertySpecification::~PropertySpecification() {} PropertyDefinition& PropertySpecification::registerProperty( const std::string& propertyVame, const std::string& defaultValue, bool inherited ) { PropertyDefinition* property = const_cast( getProperty( propertyVame ) ); - if ( NULL != property ) { + if ( nullptr != property ) { eePRINTL( "Property %s already registered.", propertyVame.c_str() ); return *property; } - mProperties.emplace_back( PropertyDefinition::New( propertyVame, defaultValue, inherited ) ); + PropertyDefinition* propDef = new PropertyDefinition( propertyVame, defaultValue, inherited ); - return *mProperties.back(); -} + mProperties[propDef->getId()] = std::shared_ptr( propDef ); -const PropertyDefinition* PropertySpecification::getProperty( const Uint32& id ) const { - for ( auto& property : mProperties ) { - if ( property->isDefinition( id ) ) { - return property; + for ( auto& sep : {"-", "_"} ) { + if ( propDef->getName().find( sep ) != std::string::npos ) { + std::string alias( propDef->getName() ); + String::replaceAll( alias, sep, "" ); + propDef->addAlias( alias ); } } - return NULL; + return *propDef; +} + +const PropertyDefinition* PropertySpecification::getProperty( const Uint32& id ) const { + auto it = mProperties.find( id ); + + if ( it != mProperties.end() ) + return it->second.get(); + + return nullptr; } const PropertyDefinition* PropertySpecification::getProperty( const std::string& name ) const { @@ -48,24 +51,26 @@ PropertySpecification::registerShorthand( const std::string& name, const std::string& shorthandParserName ) { ShorthandDefinition* shorthand = const_cast( getShorthand( name ) ); - if ( NULL != shorthand ) { + if ( nullptr != shorthand ) { eePRINTL( "Shorthand %s already registered.", name.c_str() ); return *shorthand; } - mShorthands.emplace_back( ShorthandDefinition::New( name, properties, shorthandParserName ) ); + ShorthandDefinition* shorthandDef = + new ShorthandDefinition( name, properties, shorthandParserName ); - return *mShorthands.back(); + mShorthands[shorthandDef->getId()] = std::shared_ptr( shorthandDef ); + + return *shorthandDef; } const ShorthandDefinition* PropertySpecification::getShorthand( const Uint32& id ) const { - for ( auto& shorthand : mShorthands ) { - if ( shorthand->isDefinition( id ) ) { - return shorthand; - } - } + auto it = mShorthands.find( id ); - return NULL; + if ( it != mShorthands.end() ) + return it->second.get(); + + return nullptr; } const ShorthandDefinition* PropertySpecification::getShorthand( const std::string& name ) const { @@ -73,11 +78,22 @@ const ShorthandDefinition* PropertySpecification::getShorthand( const std::strin } bool PropertySpecification::isShorthand( const std::string& name ) const { - return getShorthand( name ) != NULL; + return getShorthand( name ) != nullptr; } bool PropertySpecification::isShorthand( const Uint32& id ) const { - return getShorthand( id ) != NULL; + return getShorthand( id ) != nullptr; +} + +const PropertyDefinition* +PropertySpecification::addPropertyAlias( Uint32 aliasId, const PropertyDefinition* propDef ) { + if ( getProperty( aliasId ) == nullptr ) { + auto it = mProperties.find( propDef->getId() ); + if ( it != mProperties.end() ) { + mProperties[aliasId] = it->second; + } + } + return propDef; } }}} // namespace EE::UI::CSS diff --git a/src/eepp/ui/css/stylesheetparser.cpp b/src/eepp/ui/css/stylesheetparser.cpp index 784861996..1044b30cd 100644 --- a/src/eepp/ui/css/stylesheetparser.cpp +++ b/src/eepp/ui/css/stylesheetparser.cpp @@ -104,12 +104,14 @@ bool StyleSheetParser::parse( std::string& css, std::vector& import case ReadingSelector: { pos = readSelector( css, rs, pos, buffer ); - if ( String::startsWith( buffer, "@media" ) ) { - mediaParse( css, rs, pos, buffer, importedList ); - } else if ( String::startsWith( buffer, "@import" ) ) { - importParse( css, pos, buffer, importedList ); - } else if ( String::startsWith( buffer, "@keyframes" ) ) { - keyframesParse( css, rs, pos, buffer, importedList ); + if ( buffer[0] == '@' ) { + if ( String::startsWith( buffer, "@media" ) ) { + mediaParse( css, rs, pos, buffer, importedList ); + } else if ( String::startsWith( buffer, "@import" ) ) { + importParse( css, pos, buffer, importedList ); + } else if ( String::startsWith( buffer, "@keyframes" ) ) { + keyframesParse( css, rs, pos, buffer, importedList ); + } } break; diff --git a/src/eepp/ui/css/stylesheetspecification.cpp b/src/eepp/ui/css/stylesheetspecification.cpp index cc520aa1e..9aad607cd 100644 --- a/src/eepp/ui/css/stylesheetspecification.cpp +++ b/src/eepp/ui/css/stylesheetspecification.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -5,33 +6,36 @@ namespace EE { namespace UI { namespace CSS { SINGLETON_DECLARE_IMPLEMENTATION( StyleSheetSpecification ) -StyleSheetSpecification::StyleSheetSpecification() { +StyleSheetSpecification::StyleSheetSpecification() : + mPropertySpecification( PropertySpecification::createSingleton() ) { registerDefaultShorthandParsers(); registerDefaultProperties(); registerDefaultNodeSelectors(); } -StyleSheetSpecification::~StyleSheetSpecification() {} +StyleSheetSpecification::~StyleSheetSpecification() { + PropertySpecification::destroySingleton(); +} PropertyDefinition& StyleSheetSpecification::registerProperty( const std::string& propertyVame, const std::string& defaultValue, bool inherited ) { - return mPropertySpecification.registerProperty( propertyVame, defaultValue, inherited ); + return mPropertySpecification->registerProperty( propertyVame, defaultValue, inherited ); } const PropertyDefinition* StyleSheetSpecification::getProperty( const Uint32& id ) const { - return mPropertySpecification.getProperty( id ); + return mPropertySpecification->getProperty( id ); } const PropertyDefinition* StyleSheetSpecification::getProperty( const std::string& name ) const { - return mPropertySpecification.getProperty( name ); + return mPropertySpecification->getProperty( name ); } ShorthandDefinition& StyleSheetSpecification::registerShorthand( const std::string& name, const std::vector& properties, const std::string& shorthandFuncName ) { - return mPropertySpecification.registerShorthand( name, properties, shorthandFuncName ); + return mPropertySpecification->registerShorthand( name, properties, shorthandFuncName ); } void StyleSheetSpecification::registerShorthandParser( const std::string& name, @@ -57,19 +61,19 @@ DrawableImageParser& StyleSheetSpecification::getDrawableImageParser() { } const ShorthandDefinition* StyleSheetSpecification::getShorthand( const Uint32& id ) const { - return mPropertySpecification.getShorthand( id ); + return mPropertySpecification->getShorthand( id ); } const ShorthandDefinition* StyleSheetSpecification::getShorthand( const std::string& name ) const { - return mPropertySpecification.getShorthand( name ); + return mPropertySpecification->getShorthand( name ); } bool StyleSheetSpecification::isShorthand( const Uint32& id ) const { - return mPropertySpecification.isShorthand( id ); + return mPropertySpecification->isShorthand( id ); } bool StyleSheetSpecification::isShorthand( const std::string& name ) const { - return mPropertySpecification.isShorthand( name ); + return mPropertySpecification->isShorthand( name ); } void StyleSheetSpecification::registerDefaultProperties() { @@ -304,8 +308,7 @@ void StyleSheetSpecification::registerDefaultProperties() { registerProperty( "transition", "" ).setIndexed(); registerProperty( "transition-duration", "" ); - registerProperty( "transition-delay", "0s" ) - .setType( PropertyType::Time ); + registerProperty( "transition-delay", "0s" ).setType( PropertyType::Time ); registerProperty( "transition-timing-function", "linear" ); registerProperty( "transition-property", "" ); diff --git a/src/eepp/ui/tools/textureatlasnew.cpp b/src/eepp/ui/tools/textureatlasnew.cpp index 3de48f652..5d62716b1 100644 --- a/src/eepp/ui/tools/textureatlasnew.cpp +++ b/src/eepp/ui/tools/textureatlasnew.cpp @@ -115,8 +115,7 @@ TextureAtlasNew::TextureAtlasNew( TGCreateCb NewTGCb ) : mUIWindow( NULL ), mNew mUIWindow->find( "cancelButton" ) ->addEventListener( Event::MouseClick, cb::Make1( this, &TextureAtlasNew::cancelClick ) ); - mUIWindow->setMinWindowSize( - Sizef( container->getSize().getWidth(), container->getSize().getHeight() ) ); + mUIWindow->setMinWindowSize( container->getSize() ); mUIWindow->center(); mUIWindow->show(); } diff --git a/src/eepp/ui/uiscenenode.cpp b/src/eepp/ui/uiscenenode.cpp index 1ce2fb08d..716ceba27 100644 --- a/src/eepp/ui/uiscenenode.cpp +++ b/src/eepp/ui/uiscenenode.cpp @@ -162,8 +162,22 @@ std::vector UISceneNode::loadNode( pugi::xml_node node, Node* parent uiwidget->loadFromXmlNode( widget ); if ( mVerbose ) { + std::string name( widget.name() ); + pugi::xml_attribute idAttr( widget.attribute( "id" ) ); + pugi::xml_attribute classAttr( widget.attribute( "class" ) ); + + if ( !idAttr.empty() ) { + name += "#" + std::string( idAttr.as_string() ); + } + + if ( !classAttr.empty() ) { + std::string classes( String::trim( std::string( classAttr.as_string() ) ) ); + String::replaceAll( classes, " ", "." ); + name += "." + classes; + } + mTimes.push_back( std::make_pair( - clock.getElapsedTime().asMilliseconds(), widget.name() ) ); + clock.getElapsedTime().asMilliseconds(), std::string( name ) ) ); } if ( widget.first_child() ) { diff --git a/src/eepp/ui/uitextedit.cpp b/src/eepp/ui/uitextedit.cpp index 3424805b1..660575090 100644 --- a/src/eepp/ui/uitextedit.cpp +++ b/src/eepp/ui/uitextedit.cpp @@ -31,30 +31,26 @@ UITextEdit::UITextEdit() : mTextInput->getInputTextBuffer()->isNewLineEnabled( true ); mTextInput->setVisible( true ); mTextInput->setEnabled( true ); - mTextInput->setMinHeight( getSize().getHeight() ); mTextInput->setSize( getSize() ); - auto cb = [&]( const Event* event ) { - mNodeFlags |= NODE_FLAG_FREE_USE; - onInputSizeChange( event ); - mNodeFlags &= ~NODE_FLAG_FREE_USE; - }; + auto cb = [&]( const Event* event ) { onInputSizeChange( event ); }; mTextInput->addEventListener( Event::OnSizeChange, cb ); mTextInput->addEventListener( Event::OnTextChanged, cb ); mTextInput->addEventListener( Event::OnPressEnter, cb ); mTextInput->addEventListener( Event::OnCursorPosChange, cb::Make1( this, &UITextEdit::onCursorPosChange ) ); + mTextInput->addEventListener( Event::OnFocus, [&]( const Event* event ) { onFocus(); } ); + mTextInput->addEventListener( Event::OnFocusLoss, + [&]( const Event* event ) { onFocusLoss(); } ); - mVScrollBar = UIScrollBar::New(); - mVScrollBar->setOrientation( UIOrientation::Vertical ); + mVScrollBar = UIScrollBar::NewVertical(); mVScrollBar->setParent( this ); mVScrollBar->setSize( 0, getSize().getHeight() ); mVScrollBar->setPosition( getSize().getWidth() - mVScrollBar->getSize().getWidth(), 0 ); mVScrollBar->setValue( 1 ); - mHScrollBar = UIScrollBar::New(); - mHScrollBar->setOrientation( UIOrientation::Horizontal ); + mHScrollBar = UIScrollBar::NewHorizontal(); mHScrollBar->setParent( this ); mHScrollBar->setSize( getSize().getWidth() - mVScrollBar->getSize().getWidth(), 0 ); mHScrollBar->setPosition( 0, getSize().getHeight() - mHScrollBar->getSize().getHeight() ); @@ -99,9 +95,7 @@ void UITextEdit::onSizeChange() { mHScrollBar->setSize( getSize().getWidth(), mHScrollBar->getSize().getHeight() ); mVScrollBar->setSize( mVScrollBar->getSize().getWidth(), getSize().getHeight() ); - mTextInput->setPixelsPosition( mContainerPadding.Left, mContainerPadding.Top ); - mTextInput->setMinHeight( getSize().getHeight() ); - mTextInput->setSize( getSize() ); + mTextInput->setPosition( mContainerPadding.Left, mContainerPadding.Top ); onInputSizeChange( NULL ); @@ -199,9 +193,9 @@ void UITextEdit::scrollbarsSet() { if ( ScrollBarMode::Auto == mHScrollBarMode && mVScrollBar->isVisible() && !mHScrollBar->isVisible() ) { - if ( mTextInput->getTextWidth() > mSize.getWidth() - mContainerPadding.Left - - mContainerPadding.Right - - mVScrollBar->getPixelsSize().getWidth() ) { + if ( mTextInput->getPixelsSize().getWidth() > + mSize.getWidth() - mContainerPadding.Left - mContainerPadding.Right - + mVScrollBar->getPixelsSize().getWidth() ) { mHScrollBar->setVisible( true ); mHScrollBar->setEnabled( true ); } @@ -210,12 +204,9 @@ void UITextEdit::scrollbarsSet() { mSkipValueChange = true; if ( mVScrollBar->isVisible() ) { - int extraH = 0; - - if ( mHScrollBar->isVisible() ) - extraH = mHScrollBar->getPixelsSize().getHeight(); - - Int32 totH = mSize.getHeight() - mContainerPadding.Top - mContainerPadding.Bottom - extraH; + Float extraH = mHScrollBar->isVisible() ? mHScrollBar->getPixelsSize().getHeight() : 0; + Float totH = eefloor( mSize.getHeight() - mContainerPadding.Top - mContainerPadding.Bottom - + extraH ); if ( mTextInput->getTextHeight() > totH ) { mVScrollBar->setPageStep( (Float)totH / (Float)mTextInput->getTextHeight() ); @@ -223,11 +214,13 @@ void UITextEdit::scrollbarsSet() { } if ( mHScrollBar->isVisible() ) { - Int32 totW = mSize.getWidth() - mContainerPadding.Left - mContainerPadding.Right - - mVScrollBar->getPixelsSize().getWidth(); + Float extraW = mVScrollBar->isVisible() ? mVScrollBar->getPixelsSize().getWidth() : 0; + Float totW = + eefloor( mSize.getWidth() - mContainerPadding.Left - mContainerPadding.Right - extraW ); - if ( mTextInput->getTextWidth() > totW && 0 != mTextInput->getTextWidth() ) { - mHScrollBar->setPageStep( (Float)totW / (Float)mTextInput->getTextWidth() ); + if ( mTextInput->getPixelsSize().getWidth() > totW && + 0 != mTextInput->getPixelsSize().getWidth() ) { + mHScrollBar->setPageStep( (Float)totW / mTextInput->getPixelsSize().getWidth() ); } } @@ -282,8 +275,10 @@ void UITextEdit::onInputSizeChange( const Event* Event ) { if ( mNodeFlags & NODE_FLAG_FREE_USE ) return; - int Width = mSize.getWidth() - mContainerPadding.Left - mContainerPadding.Right; - int Height = mSize.getHeight() - mContainerPadding.Top - mContainerPadding.Bottom; + mNodeFlags |= NODE_FLAG_FREE_USE; + + Sizef aSize( getAvailableSize() ); + Sizef iSize( getInputSize() ); if ( NULL != Event ) { if ( Event->getType() == Event::OnPressEnter ) { @@ -292,57 +287,80 @@ void UITextEdit::onInputSizeChange( const Event* Event ) { } if ( mHScrollBar->isVisible() ) - Height -= mHScrollBar->getPixelsSize().getHeight(); + aSize.y -= mHScrollBar->getPixelsSize().getHeight(); String text( mTextInput->getInputTextBuffer()->getBuffer() ); - shrinkText( Width ); + shrinkText( aSize.getWidth() ); - if ( mTextInput->getTextHeight() > Height ) { - Width -= mVScrollBar->getPixelsSize().getWidth(); + if ( iSize.getHeight() > aSize.getHeight() ) { + aSize.x -= mVScrollBar->getPixelsSize().getWidth(); mTextInput->getInputTextBuffer()->setBuffer( text ); - shrinkText( Width ); - - scrollbarsSet(); + shrinkText( aSize.getWidth() ); } - if ( ( mFlags & UI_WORD_WRAP ) && mTextInput->getTextHeight() < Height ) { + textInputTryResize(); + + fixScroll(); + fixScrollToCursor(); + + mNodeFlags &= ~NODE_FLAG_FREE_USE; +} + +void UITextEdit::textInputTryResize() { + Sizef aSize( getAvailableSize() ); + Sizef iSize( getInputSize() ); + + if ( ( mFlags & UI_WORD_WRAP ) && iSize.getHeight() < aSize.getHeight() ) { mVScrollBar->setVisible( false ); mVScrollBar->setEnabled( false ); } - if ( mTextInput->getPixelsSize().getWidth() < Width || - mTextInput->getPixelsSize().getHeight() < Height ) { - if ( mTextInput->getPixelsSize().getWidth() < Width && - mTextInput->getPixelsSize().getHeight() < Height ) { - mTextInput->setPixelsSize( Width, Height ); + if ( mTextInput->getPixelsSize().getWidth() < aSize.getWidth() || + mTextInput->getPixelsSize().getHeight() < aSize.getHeight() ) { + if ( mTextInput->getPixelsSize().getWidth() < aSize.getWidth() && + mTextInput->getPixelsSize().getHeight() < aSize.getHeight() ) { + mTextInput->setPixelsSize( aSize ); } else { - if ( mTextInput->getPixelsSize().getWidth() < Width ) { - mTextInput->setPixelsSize( Width, mTextInput->getPixelsSize().getHeight() ); + if ( mTextInput->getPixelsSize().getWidth() < aSize.getWidth() ) { + mTextInput->setPixelsSize( aSize.getWidth(), + mTextInput->getPixelsSize().getHeight() ); } else { - mTextInput->setPixelsSize( mTextInput->getPixelsSize().getWidth(), Height ); + mTextInput->setPixelsSize( mTextInput->getPixelsSize().getWidth(), + aSize.getHeight() ); } } } - if ( mTextInput->getTextWidth() > Width || mTextInput->getTextHeight() > Height ) { - if ( mTextInput->getTextWidth() > Width && mTextInput->getTextHeight() > Height ) { - mTextInput->setPixelsSize( mTextInput->getTextWidth(), mTextInput->getTextHeight() ); + if ( iSize.getWidth() > aSize.getWidth() || iSize.getHeight() > aSize.getHeight() ) { + if ( iSize.getWidth() > aSize.getWidth() && iSize.getHeight() > aSize.getHeight() ) { + mTextInput->setPixelsSize( iSize ); } else { - if ( mTextInput->getTextWidth() > Width ) { - mTextInput->setPixelsSize( mTextInput->getTextWidth(), Height ); + if ( iSize.getWidth() > aSize.getWidth() ) { + mTextInput->setPixelsSize( iSize.getWidth(), aSize.getHeight() ); } else { - mTextInput->setPixelsSize( Width, mTextInput->getTextHeight() ); + mTextInput->setPixelsSize( aSize.getWidth(), iSize.getHeight() ); } } } else { - mTextInput->setPixelsSize( Width, Height ); + mTextInput->setPixelsSize( aSize ); } +} - fixScroll(); - fixScrollToCursor(); +Sizef UITextEdit::getAvailableSize() { + Float width = mSize.getWidth() - mContainerPadding.Left - mContainerPadding.Right; + Float height = mSize.getHeight() - mContainerPadding.Top - mContainerPadding.Bottom; + return Sizef( width, height ); +} + +Sizef UITextEdit::getInputSize() { + Float width = mTextInput->getTextWidth() + mTextInput->getPixelsPadding().Left + + mTextInput->getPixelsPadding().Right; + Float height = mTextInput->getTextHeight() + mTextInput->getPixelsPadding().Top + + mTextInput->getPixelsPadding().Bottom; + return Sizef( width, height ); } void UITextEdit::onCursorPosChange( const Event* ) { @@ -350,19 +368,18 @@ void UITextEdit::onCursorPosChange( const Event* ) { } void UITextEdit::fixScroll() { - int Width = mSize.getWidth() - mContainerPadding.Left - mContainerPadding.Right; - int Height = mSize.getHeight() - mContainerPadding.Top - mContainerPadding.Bottom; + Sizef aSize( getAvailableSize() ); if ( mVScrollBar->isVisible() ) - Width -= mVScrollBar->getPixelsSize().getWidth(); + aSize.x -= mVScrollBar->getPixelsSize().getWidth(); if ( mHScrollBar->isVisible() ) - Height -= mHScrollBar->getPixelsSize().getHeight(); + aSize.y -= mHScrollBar->getPixelsSize().getHeight(); - int diff; + Float diff; Float pos; - diff = mTextInput->getPixelsSize().getHeight() - Height; + diff = mTextInput->getPixelsSize().getHeight() - aSize.getHeight(); if ( diff >= 0 ) { pos = diff * mVScrollBar->getValue(); @@ -370,27 +387,24 @@ void UITextEdit::fixScroll() { mContainerPadding.Top - pos ); } - diff = mTextInput->getPixelsSize().getWidth() - Width; + diff = mTextInput->getPixelsSize().getWidth() - aSize.getWidth(); if ( diff >= 0 ) { pos = diff * mHScrollBar->getValue(); mTextInput->setPixelsPosition( mContainerPadding.Left - pos, mTextInput->getPixelsPosition().y ); } - - invalidateDraw(); } void UITextEdit::fixScrollToCursor() { if ( Font::getHorizontalAlign( mTextInput->getFlags() ) == UI_HALIGN_LEFT ) { - int Width = mSize.getWidth() - mContainerPadding.Left - mContainerPadding.Right; - int Height = mSize.getHeight() - mContainerPadding.Top - mContainerPadding.Bottom; + Sizef aSize( getAvailableSize() ); if ( mVScrollBar->isVisible() ) - Width -= mVScrollBar->getPixelsSize().getWidth(); + aSize.x -= mVScrollBar->getPixelsSize().getWidth(); if ( mHScrollBar->isVisible() ) - Height -= mHScrollBar->getPixelsSize().getHeight(); + aSize.y -= mHScrollBar->getPixelsSize().getHeight(); Uint32 NLPos = 0; Uint32 LineNum = mTextInput->getInputTextBuffer()->getCurPosLinePos( NLPos ); @@ -405,18 +419,36 @@ void UITextEdit::fixScrollToCursor() { Float lineHeight = (Float)textCache.getFont()->getLineSpacing( textCache.getCharacterSizePx() ); Float currentLineY = LineNum * lineHeight; - Float visibleLines = eefloor( Height / lineHeight ); + Float visibleLines = eefloor( aSize.getHeight() / lineHeight ); Float scrollLines = (Float)mTextInput->getNumLines() - visibleLines; if ( mTextInput->getNumLines() > 0 ) { if ( mTextInput->getPixelsPosition().y + currentLineY < 0 ) { mVScrollBar->setValue( LineNum / scrollLines ); - } else if ( mTextInput->getPixelsPosition().y + currentLineY + lineHeight > Height ) { + } else if ( mTextInput->getPixelsPosition().y + currentLineY + lineHeight > + aSize.getHeight() ) { mVScrollBar->setValue( ( LineNum + 1 - visibleLines ) / scrollLines ); } } - mHScrollBar->setValue( textCache.getTextWidth() / mTextInput->getPixelsSize().getWidth() ); + Vector2f cursorPos( mTextInput->getPixelsPadding().Left + textCache.getTextWidth(), + mTextInput->getPixelsPadding().Top + currentLineY ); + + Float tW = mTextInput->getPixelsPosition().x + cursorPos.x; + Float contDiff = mTextInput->getPixelsSize().getWidth() - aSize.getWidth(); + + if ( contDiff != 0 ) { + if ( tW <= 0.f ) { + if ( mTextInput->getInputTextBuffer()->getCursorPosition() - NLPos == 0 ) { + mHScrollBar->setValue( 0 ); + } else { + mHScrollBar->setValue( ( cursorPos.x - mTextInput->getPixelsPadding().Left ) / + contDiff ); + } + } else if ( tW >= aSize.getWidth() ) { + mHScrollBar->setValue( ( cursorPos.x - aSize.getWidth() ) / contDiff ); + } + } fixScroll(); @@ -426,9 +458,11 @@ void UITextEdit::fixScrollToCursor() { invalidateDraw(); } -void UITextEdit::shrinkText( const Uint32& Width ) { - if ( getFlags() & UI_WORD_WRAP ) { - mTextInput->shrinkText( Width ); +void UITextEdit::shrinkText( const Float& width ) { + if ( ( getFlags() & UI_WORD_WRAP ) && width > 0 ) { + mTextInput->shrinkText( width ); + textInputTryResize(); + scrollbarsSet(); } } @@ -545,14 +579,35 @@ bool UITextEdit::applyProperty( const StyleSheetProperty& attribute ) { setHorizontalScrollMode( ScrollBarMode::AlwaysOff ); break; } + case PropertyId::MaxLength: + case PropertyId::FreeEditing: + case PropertyId::Numeric: + case PropertyId::AllowFloat: + case PropertyId::Hint: + case PropertyId::HintColor: + case PropertyId::HintShadowColor: + case PropertyId::HintFontSize: + case PropertyId::HintFontFamily: + case PropertyId::HintFontStyle: + case PropertyId::HintStrokeWidth: + case PropertyId::HintStrokeColor: + case PropertyId::Color: + case PropertyId::ShadowColor: + case PropertyId::SelectionColor: + case PropertyId::SelectionBackColor: + case PropertyId::FontFamily: + case PropertyId::FontSize: + case PropertyId::FontStyle: + case PropertyId::TextStrokeWidth: + case PropertyId::TextStrokeColor: + case PropertyId::Wordwrap: + case PropertyId::TextSelection: + case PropertyId::TextAlign: + return mTextInput->applyProperty( attribute ); default: attributeSet = UIWidget::applyProperty( attribute ); } - if ( !attributeSet && ( String::startsWith( attribute.getName(), "text" ) || - String::startsWith( attribute.getName(), "font" ) ) ) - mTextInput->applyProperty( attribute ); - return attributeSet; } diff --git a/src/eepp/ui/uiwidget.cpp b/src/eepp/ui/uiwidget.cpp index b5c2e4ad2..484b7a44c 100644 --- a/src/eepp/ui/uiwidget.cpp +++ b/src/eepp/ui/uiwidget.cpp @@ -688,6 +688,10 @@ const Rectf& UIWidget::getPadding() const { return mPadding; } +const Rectf& UIWidget::getPixelsPadding() const { + return mRealPadding; +} + UIWidget* UIWidget::setPadding( const Rectf& padding ) { if ( padding != mPadding ) { mPadding = padding; diff --git a/src/eepp/ui/uiwindow.cpp b/src/eepp/ui/uiwindow.cpp index bba76810a..fcc722461 100644 --- a/src/eepp/ui/uiwindow.cpp +++ b/src/eepp/ui/uiwindow.cpp @@ -1194,7 +1194,7 @@ void UIWindow::maximize() { mNonMaxSize = mSize; setPosition( 0, 0 ); - internalSize( Ctrl->getPixelsSize() ); + setSizeWithDecoration( Ctrl->getSize() ); } } @@ -1422,6 +1422,15 @@ Sizef UIWindow::getMinWindowSizeWithDecoration() { return size; } +Sizef UIWindow::getSizeWithoutDecoration() { + Sizef size( getSize() ); + if ( NULL != mWindowDecoration ) { + size.x -= mBorderLeft->getSize().getWidth() + mBorderRight->getSize().getWidth(); + size.y -= mWindowDecoration->getSize().getHeight() + mBorderBottom->getSize().getHeight(); + } + return size; +} + const Sizef& UIWindow::getMinWindowSize() { return mStyleConfig.MinWindowSize; } diff --git a/src/test/eetest.cpp b/src/test/eetest.cpp index a7d04ec58..fa93f2a5b 100644 --- a/src/test/eetest.cpp +++ b/src/test/eetest.cpp @@ -1001,7 +1001,7 @@ void EETest::createMapEditor() { UIWindow::StyleConfig windowStyleConfig = tWin->getStyleConfig(); windowStyleConfig.WinFlags = UI_WIN_DEFAULT_FLAGS | UI_WIN_MAXIMIZE_BUTTON | UI_WIN_DRAGABLE_CONTAINER | UI_WIN_SHADOW | UI_WIN_FRAME_BUFFER; - windowStyleConfig.MinWindowSize = Sizef( 1024, 768 ); + windowStyleConfig.MinWindowSize = tWin->getSizeWithoutDecoration(); tWin->setStyleConfig( windowStyleConfig ); Clock mapEditorTime; @@ -1021,7 +1021,7 @@ void EETest::createETGEditor() { UIWindow::StyleConfig windowStyleConfig = tWin->getStyleConfig(); windowStyleConfig.WinFlags = UI_WIN_DEFAULT_FLAGS | UI_WIN_MAXIMIZE_BUTTON | UI_WIN_DRAGABLE_CONTAINER | UI_WIN_SHADOW | UI_WIN_FRAME_BUFFER; - windowStyleConfig.MinWindowSize = Sizef( 1024, 768 ); + windowStyleConfig.MinWindowSize = tWin->getSizeWithoutDecoration(); tWin->setStyleConfig( windowStyleConfig ); mETGEditor = Tools::TextureAtlasEditor::New( tWin, [&] { mETGEditor = NULL; } );