From a3aeead861fd21efdb8bbb24751ead0a6b8bc730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Sun, 16 Dec 2018 04:45:52 -0300 Subject: [PATCH] Implemented padding for UIScrollBar, UISlider and UIWindow. --HG-- branch : dev-widget-padding --- bin/assets/layouts/test.xml | 6 ++- include/eepp/math/rect.hpp | 29 ++++++++---- include/eepp/ui/uiscrollbar.hpp | 2 + include/eepp/ui/uislider.hpp | 6 +++ include/eepp/ui/uiwindow.hpp | 4 +- src/eepp/ui/uiscrollbar.cpp | 79 ++++++++++++++++++++++++++------ src/eepp/ui/uislider.cpp | 81 +++++++++++++++++++++++---------- src/eepp/ui/uiwindow.cpp | 29 +++++------- 8 files changed, 169 insertions(+), 67 deletions(-) diff --git a/bin/assets/layouts/test.xml b/bin/assets/layouts/test.xml index bdbaf48c1..5e1c49404 100644 --- a/bin/assets/layouts/test.xml +++ b/bin/assets/layouts/test.xml @@ -21,7 +21,7 @@ - + @@ -32,6 +32,10 @@ --> + + + + diff --git a/include/eepp/math/rect.hpp b/include/eepp/math/rect.hpp index 13fec83b2..7f2b9caab 100755 --- a/include/eepp/math/rect.hpp +++ b/include/eepp/math/rect.hpp @@ -183,22 +183,35 @@ tRECT& operator /(tRECT& R, Y X) { } template -tRECT::tRECT(T left, T top, T right, T bottom) { - Left = left; Right = right; Top = top; Bottom = bottom; +Vector2 operator -(Vector2 X, const tRECT& R) { + return Vector2(X.x - R.Left - R.Right, X.y - R.Top - R.Bottom); } +template +Vector2 operator +(Vector2 X, const tRECT& R) { + return Vector2(X.x + R.Left + R.Right, X.y + R.Top + R.Bottom); +} + +template +tRECT::tRECT(T left, T top, T right, T bottom) : + Left(left), + Right(right), + Top(top), + Bottom(bottom) +{} + template tRECT tRECT::copy() { return tRECT( Left, Top, Right, Bottom ); } template -tRECT::tRECT( const Vector2& Pos, const tSize& Size ) { - Left = Pos.x; - Top = Pos.y; - Right = Left + Size.getWidth(); - Bottom = Top + Size.getHeight(); -} +tRECT::tRECT( const Vector2& Pos, const tSize& Size ) : + Left( Pos.x ), + Right( Pos.x + Size.getWidth() ), + Top( Pos.y ), + Bottom( Pos.y + Size.getHeight() ) +{} template tRECT::tRECT() : Left(0), Right(0), Top(0), Bottom(0) {} diff --git a/include/eepp/ui/uiscrollbar.hpp b/include/eepp/ui/uiscrollbar.hpp index abe6b66b3..f50bc1161 100644 --- a/include/eepp/ui/uiscrollbar.hpp +++ b/include/eepp/ui/uiscrollbar.hpp @@ -86,6 +86,8 @@ class EE_API UIScrollBar : public UIWidget { virtual Uint32 onMessage( const NodeMessage * Msg ); + virtual void onPaddingChange(); + void manageClick( const Uint32& flags ); }; diff --git a/include/eepp/ui/uislider.hpp b/include/eepp/ui/uislider.hpp index 11b2762f2..2799294ec 100644 --- a/include/eepp/ui/uislider.hpp +++ b/include/eepp/ui/uislider.hpp @@ -65,6 +65,8 @@ class EE_API UISlider : public UIWidget { void setPageStep( const Float & pageStep ); virtual bool setAttribute( const NodeAttribute& attribute ); + + Sizef getMinimumSize(); protected: friend class Private::UISliderButton; @@ -82,8 +84,12 @@ class EE_API UISlider : public UIWidget { Uint32 mLastTickMove; + virtual void onAutoSize(); + virtual void onSizeChange(); + virtual void onPaddingChange(); + void fixSliderPos(); virtual Uint32 onKeyDown( const KeyEvent &Event ); diff --git a/include/eepp/ui/uiwindow.hpp b/include/eepp/ui/uiwindow.hpp index b27ee9520..61ab5ff1e 100644 --- a/include/eepp/ui/uiwindow.hpp +++ b/include/eepp/ui/uiwindow.hpp @@ -189,8 +189,6 @@ class EE_API UIWindow : public UIWidget { virtual void matrixUnset(); - void onContainerPositionChange( const Event * Event ); - void fixChildsSize(); void doResize( const NodeMessage * Msg ); @@ -237,6 +235,8 @@ class EE_API UIWindow : public UIWidget { virtual void drawShadow(); + virtual void onPaddingChange(); + virtual void preDraw(); virtual void postDraw(); diff --git a/src/eepp/ui/uiscrollbar.cpp b/src/eepp/ui/uiscrollbar.cpp index 6cd3b53c4..c3cfc7df3 100644 --- a/src/eepp/ui/uiscrollbar.cpp +++ b/src/eepp/ui/uiscrollbar.cpp @@ -85,10 +85,11 @@ void UIScrollBar::setTheme( UITheme * Theme ) { } void UIScrollBar::onAutoSize() { + Sizef size; UISkin * tSkin = mSlider->getBackSlider()->getSkin(); if ( NULL != tSkin ) { - Sizef size = tSkin->getSize(); + size = tSkin->getSize(); mMinControlSize = PixelDensity::pxToDp( size ); @@ -105,7 +106,7 @@ void UIScrollBar::onAutoSize() { UISkin * tSkin = mSlider->getSliderButton()->getSkin(); if ( NULL != tSkin ) { - Sizef size = tSkin->getSize(); + size = tSkin->getSize(); if ( mFlags & UI_AUTO_SIZE ) { if ( mSlider->isVertical() ) { @@ -116,6 +117,26 @@ void UIScrollBar::onAutoSize() { } } } + + if ( mLayoutWidthRules == WRAP_CONTENT || mLayoutHeightRules == WRAP_CONTENT ) { + Sizef size = PixelDensity::dpToPx( mSlider->getMinimumSize() ) + mRealPadding; + + if ( mScrollBarType == TwoButtons ) { + if ( mSlider->isVertical() ) { + size.y += mBtnDown->getRealSize().getHeight() + mBtnUp->getRealSize().getHeight(); + } else { + size.x += mBtnDown->getRealSize().getWidth() + mBtnUp->getRealSize().getWidth(); + } + } + + if ( mLayoutWidthRules == WRAP_CONTENT ) { + setInternalPixelsWidth( size.getWidth() ); + } + + if ( mLayoutHeightRules == WRAP_CONTENT ) { + setInternalPixelsHeight( size.getHeight() ); + } + } } void UIScrollBar::onSizeChange() { @@ -138,9 +159,9 @@ void UIScrollBar::adjustChilds() { mBtnUp->setVisible( false )->setEnabled( false ); if ( !isVertical() ) { - mSlider->setSize( mDpSize )->setPosition( 0, 0 )->centerVertical(); + mSlider->setSize( mDpSize - mPadding )->setPosition( mPadding.Left, mPadding.Top )->centerVertical(); } else { - mSlider->setSize( mDpSize )->setPosition( 0, 0 )->centerHorizontal(); + mSlider->setSize( mDpSize - mPadding )->setPosition( mPadding.Left, mPadding.Top )->centerHorizontal(); } break; @@ -152,17 +173,19 @@ void UIScrollBar::adjustChilds() { mBtnUp->setVisible( true )->setEnabled( true ); if ( !isVertical() ) { - mBtnDown->setPosition( mDpSize.getWidth() - mBtnDown->getSize().getWidth(), 0 ); - mSlider->setSize( mDpSize.getWidth() - mBtnDown->getSize().getWidth() - mBtnUp->getSize().getWidth(), mDpSize.getHeight() ); - mSlider->setPosition( mBtnUp->getSize().getWidth(), 0 ); + mBtnUp->setPosition( mPadding.Left, mPadding.Top ); + mBtnDown->setPosition( mDpSize.getWidth() - mBtnDown->getSize().getWidth() - mPadding.Right, mPadding.Top ); + mSlider->setSize( mDpSize.getWidth() - mBtnDown->getSize().getWidth() - mBtnUp->getSize().getWidth() - mPadding.Left - mPadding.Bottom, mDpSize.getHeight() ); + mSlider->setPosition( mPadding.Left + mBtnUp->getSize().getWidth(), mPadding.Top ); mBtnDown->centerVertical(); mBtnUp->centerVertical(); mSlider->centerVertical(); } else { - mBtnDown->setPosition( 0, mDpSize.getHeight() - mBtnDown->getSize().getHeight() ); - mSlider->setSize( mDpSize.getWidth(), mDpSize.getHeight() - mBtnDown->getSize().getHeight() - mBtnUp->getSize().getHeight() ); - mSlider->setPosition( 0, mBtnUp->getSize().getHeight() ); + mBtnUp->setPosition( mPadding.Left, mPadding.Top ); + mBtnDown->setPosition( mPadding.Left, mDpSize.getHeight() - mBtnDown->getSize().getHeight() - mPadding.Bottom ); + mSlider->setSize( mDpSize.getWidth(), mDpSize.getHeight() - mBtnDown->getSize().getHeight() - mBtnUp->getSize().getHeight() - mPadding.Top - mPadding.Bottom ); + mSlider->setPosition( mPadding.Left, mBtnUp->getSize().getHeight() + mPadding.Top ); mBtnDown->centerHorizontal(); mBtnUp->centerHorizontal(); @@ -281,11 +304,36 @@ void UIScrollBar::setExpandBackground( bool expandBackground ) { } bool UIScrollBar::setAttribute(const NodeAttribute & attribute) { - bool attributeSet = UIScrollBar::setAttribute( attribute ); + const std::string& name = attribute.getName(); - mSlider->setAttribute( attribute ); + if ( "orientation" == name ) { + std::string val = attribute.asString(); + String::toLowerInPlace( val ); - return attributeSet; + if ( "horizontal" == val ) + setOrientation( UI_HORIZONTAL ); + else if ( "vertical" == val ) + setOrientation( UI_VERTICAL ); + } else if ( "minvalue" == name ) { + setMinValue( attribute.asFloat() ); + } else if ( "maxvalue" == name ) { + setMaxValue( attribute.asFloat() ); + } else if ( "value" == name ) { + setValue( attribute.asFloat() ); + } else if ( "clickstep" == name ) { + setClickStep( attribute.asFloat() ); + } else if ( "pagestep" == name ) { + setPageStep( attribute.asFloat() ); + } else if ( "scrollbartype" == name || "scrollbar_type" == name ) { + std::string val = attribute.asString(); + String::toLowerInPlace( val ); + + setScrollBarType( val == "nobuttons" || val == "mobile" || val == "simple" ? NoButtons : TwoButtons ); + } else { + return UIWidget::setAttribute( attribute ); + } + + return true; } UIScrollBar::ScrollBarType UIScrollBar::getScrollBarType() const { @@ -320,4 +368,9 @@ void UIScrollBar::onAlphaChange() { mBtnDown->setAlpha( mAlpha ); } +void UIScrollBar::onPaddingChange() { + adjustChilds(); + UIWidget::onPaddingChange(); +} + }} diff --git a/src/eepp/ui/uislider.cpp b/src/eepp/ui/uislider.cpp index 0798f139c..031c9bd9b 100644 --- a/src/eepp/ui/uislider.cpp +++ b/src/eepp/ui/uislider.cpp @@ -93,6 +93,11 @@ void UISlider::onSizeChange() { adjustChilds(); } +void UISlider::onPaddingChange() { + adjustChilds(); + UIWidget::onPaddingChange(); +} + void UISlider::adjustChilds() { UISkin * tSkin = NULL; @@ -129,24 +134,24 @@ void UISlider::adjustChilds() { Float Height; if ( mStyleConfig.ExpandBackground ) - Height = mDpSize.getHeight(); + Height = mDpSize.getHeight() - mPadding.Top - mPadding.Bottom; else Height = tSkin->getSize().getHeight(); if ( mStyleConfig.AllowHalfSliderOut ) - mBackSlider->setSize( Sizef( mDpSize.getWidth() - mSlider->getSize().getWidth(), Height ) ); + mBackSlider->setSize( Sizef( mDpSize.getWidth() - mSlider->getSize().getWidth() - mPadding.Left - mPadding.Right, Height ) ); else - mBackSlider->setSize( Sizef( mDpSize.getWidth(), Height ) ); + mBackSlider->setSize( Sizef( mDpSize.getWidth() - mPadding.Left - mPadding.Right, Height ) ); } else { Float Width; if ( mStyleConfig.ExpandBackground ) - Width = mDpSize.getWidth(); + Width = mDpSize.getWidth() - mPadding.Left - mPadding.Right; else Width = tSkin->getSize().getWidth(); if ( mStyleConfig.AllowHalfSliderOut ) - mBackSlider->setSize( Sizef( Width, mDpSize.getHeight() - mSlider->getSize().getHeight() ) ); + mBackSlider->setSize( Sizef( Width, mDpSize.getHeight() - mSlider->getSize().getHeight() - mPadding.Top - mPadding.Bottom ) ); else mBackSlider->setSize( Sizef( Width, mDpSize.getHeight() ) ); } @@ -164,44 +169,44 @@ void UISlider::fixSliderPos() { if ( UI_HORIZONTAL == mOrientation ) { mSlider->setPosition( mSlider->getPosition().x, 0 ); - if ( mSlider->getPosition().x < 0 ) - mSlider->setPosition( 0, 0 ); + if ( mSlider->getPosition().x < mPadding.Left ) + mSlider->setPosition( mPadding.Left, 0 ); if ( mStyleConfig.AllowHalfSliderOut ) { - if ( mSlider->getPosition().x > mBackSlider->getSize().getWidth() ) - mSlider->setPosition( mBackSlider->getSize().getWidth(), 0 ); + if ( mSlider->getPosition().x > mBackSlider->getSize().getWidth() + mPadding.Left ) + mSlider->setPosition( mBackSlider->getSize().getWidth() + mPadding.Left, 0 ); } else { - if ( mSlider->getPosition().x > mBackSlider->getSize().getWidth() - mSlider->getSize().getWidth() ) - mSlider->setPosition( mBackSlider->getSize().getWidth() - mSlider->getSize().getWidth(), 0 ); + if ( mSlider->getPosition().x > mBackSlider->getSize().getWidth() - mSlider->getSize().getWidth() + mPadding.Left ) + mSlider->setPosition( mBackSlider->getSize().getWidth() - mSlider->getSize().getWidth() + mPadding.Left, 0 ); } mSlider->centerVertical(); if ( mStyleConfig.AllowHalfSliderOut ) - setValue( mMinValue + (Float)mSlider->getPosition().x * ( mMaxValue - mMinValue ) / (Float)mBackSlider->getSize().getWidth() ); + setValue( mMinValue + ( mSlider->getPosition().x - mPadding.Left ) * ( mMaxValue - mMinValue ) / (Float)mBackSlider->getSize().getWidth() ); else - setValue( mMinValue + (Float)mSlider->getPosition().x * ( mMaxValue - mMinValue ) / ( (Float)mDpSize.getWidth() - mSlider->getSize().getWidth() ) ); + setValue( mMinValue + ( mSlider->getPosition().x - mPadding.Left ) * ( mMaxValue - mMinValue ) / ( (Float)mDpSize.getWidth() - mSlider->getSize().getWidth() ) ); } else { mSlider->setPosition( 0, mSlider->getPosition().y ); - if ( mSlider->getPosition().y < 0 ) - mSlider->setPosition( 0, 0 ); + if ( mSlider->getPosition().y < mPadding.Top ) + mSlider->setPosition( 0, mPadding.Top ); if ( mStyleConfig.AllowHalfSliderOut ) { - if ( mSlider->getPosition().y > mBackSlider->getSize().getHeight() ) - mSlider->setPosition( 0, mBackSlider->getSize().getHeight() ); + if ( mSlider->getPosition().y > mBackSlider->getSize().getHeight() + mPadding.Top ) + mSlider->setPosition( 0, mBackSlider->getSize().getHeight() + mPadding.Top ); } else { - if ( mSlider->getPosition().y > mBackSlider->getSize().getHeight() - mSlider->getSize().getHeight() ) { - mSlider->setPosition( 0, mBackSlider->getSize().getHeight() - mSlider->getSize().getHeight() ); + if ( mSlider->getPosition().y > mBackSlider->getSize().getHeight() - mSlider->getSize().getHeight() + mPadding.Top ) { + mSlider->setPosition( 0, mBackSlider->getSize().getHeight() - mSlider->getSize().getHeight() + mPadding.Top ); } } mSlider->centerHorizontal(); if ( mStyleConfig.AllowHalfSliderOut ) - setValue( mMinValue + (Float)mSlider->getPosition().y * ( mMaxValue - mMinValue ) / (Float)mBackSlider->getSize().getHeight() ); + setValue( mMinValue + ( mSlider->getPosition().y - mPadding.Top ) * ( mMaxValue - mMinValue ) / (Float)mBackSlider->getSize().getHeight() ); else - setValue( mMinValue + (Float)mSlider->getPosition().y * ( mMaxValue - mMinValue ) / ( (Float)mDpSize.getHeight() - mSlider->getSize().getHeight() ) ); + setValue( mMinValue + ( mSlider->getPosition().y - mPadding.Top ) * ( mMaxValue - mMinValue ) / ( (Float)mDpSize.getHeight() - mSlider->getSize().getHeight() ) ); } mOnPosChange = false; @@ -222,14 +227,14 @@ void UISlider::setValue( Float Val ) { if ( UI_HORIZONTAL == mOrientation ) { if ( mStyleConfig.AllowHalfSliderOut ) - mSlider->setPosition( (Int32)( (Float)mBackSlider->getSize().getWidth() * Percent ), mSlider->getPosition().y ); + mSlider->setPosition( mPadding.Left + (Int32)( (Float)mBackSlider->getSize().getWidth() * Percent ), mSlider->getPosition().y ); else - mSlider->setPosition( (Int32)( ( (Float)mDpSize.getWidth() - mSlider->getSize().getWidth() ) * Percent ), mSlider->getPosition().y ); + mSlider->setPosition( mPadding.Left + (Int32)( ( (Float)mDpSize.getWidth() - mPadding.Left - mPadding.Top - mSlider->getSize().getWidth() ) * Percent ), mSlider->getPosition().y ); } else { if ( mStyleConfig.AllowHalfSliderOut ) - mSlider->setPosition( mSlider->getPosition().x, (Int32)( (Float)mBackSlider->getSize().getHeight() * Percent ) ); + mSlider->setPosition( mSlider->getPosition().x, mPadding.Top + (Int32)( (Float)mBackSlider->getSize().getHeight() * Percent ) ); else - mSlider->setPosition( mSlider->getPosition().x, (Int32)( ( (Float)mDpSize.getHeight() - mSlider->getSize().getHeight() ) * Percent ) ); + mSlider->setPosition( mSlider->getPosition().x, mPadding.Top + (Int32)( ( (Float)mDpSize.getHeight() - mPadding.Top - mPadding.Bottom - mSlider->getSize().getHeight() ) * Percent ) ); } mOnPosChange = false; @@ -423,6 +428,8 @@ bool UISlider::setAttribute( const NodeAttribute& attribute ) { setClickStep( attribute.asFloat() ); } else if ( "pagestep" == name ) { setPageStep( attribute.asFloat() ); + } else if ( "halfslider" == name ) { + setAllowHalfSliderOut( attribute.asBool() ); } else { return UIWidget::setAttribute( attribute ); } @@ -430,4 +437,28 @@ bool UISlider::setAttribute( const NodeAttribute& attribute ) { return true; } +Sizef UISlider::getMinimumSize() { + Float w = eemax( mBackSlider->getSkinSize().getWidth(), mSlider->getSkinSize().getWidth() ); + Float h = eemax( mBackSlider->getSkinSize().getHeight(), mSlider->getSkinSize().getHeight() ); + return Sizef( w + ( mStyleConfig.AllowHalfSliderOut ? w : 0 ) + mPadding.Left + mPadding.Right, h + mPadding.Top + mPadding.Bottom ); +} + +void UISlider::onAutoSize() { + if ( mLayoutWidthRules == WRAP_CONTENT || mLayoutHeightRules == WRAP_CONTENT ) { + Sizef total( getMinimumSize() ); + + total = PixelDensity::dpToPx( total ); + + if ( mLayoutWidthRules == WRAP_CONTENT ) { + setInternalPixelsWidth( total.getWidth() ); + } + + if ( mLayoutHeightRules == WRAP_CONTENT ) { + setInternalPixelsHeight( total.getHeight() ); + } + + adjustChilds(); + } +} + }} diff --git a/src/eepp/ui/uiwindow.cpp b/src/eepp/ui/uiwindow.cpp index 873d64e23..bfee1476f 100644 --- a/src/eepp/ui/uiwindow.cpp +++ b/src/eepp/ui/uiwindow.cpp @@ -69,7 +69,6 @@ UIWindow::UIWindow( UIWindow::WindowBaseContainerType type, const UIWindowStyleC mContainer->clipEnable(); mContainer->enableReportSizeChangeToChilds(); mContainer->setSize( mDpSize ); - mContainer->addEventListener( Event::OnPositionChange, cb::Make1( this, &UIWindow::onContainerPositionChange ) ); updateWinFlags(); @@ -328,6 +327,12 @@ void UIWindow::drawShadow() { } } +void UIWindow::onPaddingChange() { + fixChildsSize(); + + UIWidget::onPaddingChange(); +} + Sizei UIWindow::getFrameBufferSize() { return isResizeable() && (Node*)this != mSceneNode ? Sizei( Math::nextPowOfTwo( (int)mSize.getWidth() ), Math::nextPowOfTwo( (int)mSize.getHeight() ) ) : mSize.ceil().asInt(); } @@ -405,19 +410,6 @@ bool UIWindow::isType( const Uint32& type ) const { return UIWindow::getType() == type ? true : UIWidget::isType( type ); } -void UIWindow::onContainerPositionChange( const Event * Event ) { - if ( NULL == mContainer ) - return; - - Vector2f PosDiff = mContainer->getPosition() - Vector2f( NULL != mBorderLeft ? mBorderLeft->getSize().getWidth() : 0, NULL != mWindowDecoration ? mWindowDecoration->getSize().getHeight() : 0 ); - - if ( PosDiff.x != 0 || PosDiff.y != 0 ) { - mContainer->setPosition( NULL != mBorderLeft ? mBorderLeft->getSize().getWidth() : 0, NULL != mWindowDecoration ? mWindowDecoration->getSize().getHeight() : 0 ); - - setPosition( mDpPos + PosDiff ); - } -} - void UIWindow::closeWindow() { if ( NULL != mButtonClose ) mButtonClose->setEnabled( false ); @@ -578,7 +570,8 @@ void UIWindow::fixChildsSize() { } if ( NULL == mWindowDecoration && NULL != mContainer ) { - mContainer->setPixelsSize( mSize ); + mContainer->setPixelsSize( mSize - mRealPadding ); + mContainer->setPosition( mRealPadding.Left, mRealPadding.Top ); return; } @@ -610,9 +603,9 @@ void UIWindow::fixChildsSize() { mBorderRight->setPixelsPosition( mSize.getWidth() - mBorderRight->getRealSize().getWidth(), mWindowDecoration->getRealSize().getHeight() ); mBorderBottom->setPixelsPosition( 0, mWindowDecoration->getRealSize().getHeight() + mBorderLeft->getRealSize().getHeight() ); - mContainer->setPixelsPosition( mBorderLeft->getRealSize().getWidth(), mWindowDecoration->getRealSize().getHeight() ); - mContainer->setPixelsSize( mSize.getWidth() - mBorderLeft->getRealSize().getWidth() - mBorderRight->getRealSize().getWidth(), - mSize.getHeight() - mWindowDecoration->getRealSize().getHeight() - mBorderBottom->getRealSize().getHeight() ); + mContainer->setPixelsPosition( mBorderLeft->getRealSize().getWidth() + mRealPadding.Left, mWindowDecoration->getRealSize().getHeight() + mRealPadding.Top ); + mContainer->setPixelsSize( mSize.getWidth() - mBorderLeft->getRealSize().getWidth() - mBorderRight->getRealSize().getWidth() - mRealPadding.Left - mRealPadding.Right, + mSize.getHeight() - mWindowDecoration->getRealSize().getHeight() - mBorderBottom->getRealSize().getHeight() - mRealPadding.Top - mRealPadding.Bottom ); Uint32 yPos; Vector2f posFix( PixelDensity::dpToPx( Vector2f( mStyleConfig.ButtonsPositionFixer.x, mStyleConfig.ButtonsPositionFixer.y ) ) );