diff --git a/bin/assets/ui/breeze.css b/bin/assets/ui/breeze.css index 024751261..1a0c2bc36 100644 --- a/bin/assets/ui/breeze.css +++ b/bin/assets/ui/breeze.css @@ -539,7 +539,7 @@ Tab { height: 24dp; transition: background-color 0.15s; foreground-image: linear-gradient( to top, var(--tab-line), var(--tab-back)); - foreground-size: 1dp 80%; + foreground-size: 1dprd 80%; foreground-position: right bottom; } @@ -586,9 +586,6 @@ Tab::close { width: 10dp; height: 10dp; border-radius: 5dp; - /*background-color: var(--tab-close); - foreground-image: poly(line, var(--icon-line-hover), "0dp 0dp, 5dp 5dp"), poly(line, var(--icon-line-hover), "5dp 0dp, 0dp 5dp"); - foreground-position: 2.5dp 2.5dp, 2.5dp 2.5dp;*/ foreground-image: url("data:image/svg,"); foreground-tint: var(--tab-close); foreground-size: 10dp 10dp; @@ -597,7 +594,6 @@ Tab::close { } Tab::close:hover { - /*background-color: var(--tab-close-hover);*/ foreground-tint: var(--tab-close-hover); } diff --git a/docs/articles/cssspecification.md b/docs/articles/cssspecification.md index 2ba7efdd6..4db92d92c 100644 --- a/docs/articles/cssspecification.md +++ b/docs/articles/cssspecification.md @@ -27,8 +27,7 @@ the CSS file. * eepp CSS supports alternative path methods besides paths (resource locator to previously loaded resources by the process). -* eepp CSS supports [Device-independent -pixel](https://en.wikipedia.org/wiki/Device-independent_pixel) unit `dp`. +* eepp CSS supports [Device-independent pixel](https://en.wikipedia.org/wiki/Device-independent_pixel) unit `dp`. * CSS files should be always UTF-8 encoded. @@ -2461,6 +2460,8 @@ Read [length](https://developer.mozilla.org/en-US/docs/Web/CSS/length) documenta * Supported lenghts: `em`, `rem`, `pt`, `pc`, `in`, `cm`, `mm`, `vw`, `vh`, `vmin`, `vmax`. +* Also adds: `dp` as [Device-independent pixel](https://en.wikipedia.org/wiki/Device-independent_pixel). Plus `dprd` (dp rounded down) and `dpru` (dp rounded up). + --- ### length-percentage (data-type) diff --git a/include/eepp/ui/css/stylesheetlength.hpp b/include/eepp/ui/css/stylesheetlength.hpp index 9b2011715..3976a998f 100644 --- a/include/eepp/ui/css/stylesheetlength.hpp +++ b/include/eepp/ui/css/stylesheetlength.hpp @@ -30,6 +30,8 @@ class EE_API StyleSheetLength { Vmin, Vmax, Rem, + Dprd, + Dpru, }; static Unit unitFromString( std::string unitStr ); @@ -64,7 +66,7 @@ class EE_API StyleSheetLength { StyleSheetLength& operator=( const Float& val ); - static StyleSheetLength fromString( std::string str, const Float& defaultValue = 0 ); + static StyleSheetLength fromString( const std::string& str, const Float& defaultValue = 0 ); std::string toString() const; diff --git a/include/eepp/ui/css/stylesheetselector.hpp b/include/eepp/ui/css/stylesheetselector.hpp index ca5c7b8bd..f70239221 100644 --- a/include/eepp/ui/css/stylesheetselector.hpp +++ b/include/eepp/ui/css/stylesheetselector.hpp @@ -21,14 +21,13 @@ class EE_API StyleSheetSelector { bool select( UIWidget* element, const bool& applyPseudo = true ) const; - const bool& isCacheable() const; + bool isCacheable() const; bool hasPseudoClasses() const; - std::vector getRelatedElements( UIWidget* element, - const bool& applyPseudo = true ) const; + std::vector getRelatedElements( UIWidget* element, bool applyPseudo = true ) const; - const bool& isStructurallyVolatile() const; + bool isStructurallyVolatile() const; const StyleSheetSelectorRule& getRule( const Uint32& index ); diff --git a/projects/linux/ee.creator.user b/projects/linux/ee.creator.user index e8eeb3ad6..8109aad79 100644 --- a/projects/linux/ee.creator.user +++ b/projects/linux/ee.creator.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -1215,6 +1215,7 @@ ecode-debug ProjectExplorer.CustomExecutableRunConfiguration + --css=/root/.config/ecode/style.css 0 false 1 diff --git a/src/eepp/ui/css/stylesheetlength.cpp b/src/eepp/ui/css/stylesheetlength.cpp index a38a42214..ddb9cfb4b 100644 --- a/src/eepp/ui/css/stylesheetlength.cpp +++ b/src/eepp/ui/css/stylesheetlength.cpp @@ -4,45 +4,115 @@ #include using namespace EE::Graphics; +using namespace std::literals; namespace EE { namespace UI { namespace CSS { +enum UnitHashes : String::HashType { + Percentage = String::hash( "%" ), + In = String::hash( "in" ), + Cm = String::hash( "cm" ), + Mm = String::hash( "mm" ), + Em = String::hash( "em" ), + Ex = String::hash( "ex" ), + Pt = String::hash( "pt" ), + Pc = String::hash( "pc" ), + Px = String::hash( "px" ), + Dpi = String::hash( "dpi" ), + Dp = String::hash( "dp" ), + Dpcm = String::hash( "dpcm" ), + Vw = String::hash( "vw" ), + Vh = String::hash( "vh" ), + Vmin = String::hash( "vmin" ), + Vmax = String::hash( "vmax" ), + Rem = String::hash( "rem" ), + Dprd = String::hash( "dprd" ), + Dpru = String::hash( "dpru" ), +}; + +enum PercentagePositions : String::HashType { + Center = String::hash( "center" ), + Left = String::hash( "left" ), + Right = String::hash( "right" ), + Top = String::hash( "top" ), + Bottom = String::hash( "bottom" ), + None = 0, +}; + +static std::string positionToPercentage( const PercentagePositions& pos ) { + switch ( pos ) { + case Center: + return "50%"; + case Left: + case Top: + return "0%"; + case Right: + case Bottom: + return "100%"; + default: + case None: + return ""; + } +} + +static PercentagePositions isPercentagePosition( const String::HashType& strHash ) { + switch ( strHash ) { + case PercentagePositions::Center: + return PercentagePositions::Center; + case PercentagePositions::Left: + return PercentagePositions::Left; + case PercentagePositions::Right: + return PercentagePositions::Right; + case PercentagePositions::Top: + return PercentagePositions::Top; + case PercentagePositions::Bottom: + return PercentagePositions::Bottom; + } + return PercentagePositions::None; +} + StyleSheetLength::Unit StyleSheetLength::unitFromString( std::string unitStr ) { String::toLowerInPlace( unitStr ); - if ( "%" == unitStr ) - return Unit::Percentage; - else if ( "dp" == unitStr ) - return Unit::Dp; - else if ( "px" == unitStr ) - return Unit::Px; - else if ( "in" == unitStr ) - return Unit::In; - else if ( "cm" == unitStr ) - return Unit::Cm; - else if ( "mm" == unitStr ) - return Unit::Mm; - else if ( "em" == unitStr ) - return Unit::Em; - else if ( "ex" == unitStr ) - return Unit::Ex; - else if ( "pt" == unitStr ) - return Unit::Pt; - else if ( "pc" == unitStr ) - return Unit::Pc; - else if ( "dpi" == unitStr ) - return Unit::Dpi; - else if ( "dpcm" == unitStr ) - return Unit::Dpcm; - else if ( "vw" == unitStr ) - return Unit::Vw; - else if ( "vh" == unitStr ) - return Unit::Vh; - else if ( "vmin" == unitStr ) - return Unit::Vmin; - else if ( "vmax" == unitStr ) - return Unit::Vmax; - else if ( "rem" == unitStr ) - return Unit::Rem; + switch ( String::hash( unitStr ) ) { + case UnitHashes::Percentage: + return Unit::Percentage; + case UnitHashes::Dp: + return Unit::Dp; + case UnitHashes::Px: + return Unit::Px; + case UnitHashes::In: + return Unit::In; + case UnitHashes::Cm: + return Unit::Cm; + case UnitHashes::Mm: + return Unit::Mm; + case UnitHashes::Em: + return Unit::Em; + case UnitHashes::Ex: + return Unit::Ex; + case UnitHashes::Pt: + return Unit::Pt; + case UnitHashes::Pc: + return Unit::Pc; + case UnitHashes::Dpi: + return Unit::Dpi; + case UnitHashes::Dpcm: + return Unit::Dpcm; + case UnitHashes::Vw: + return Unit::Vw; + case UnitHashes::Vh: + return Unit::Vh; + case UnitHashes::Vmin: + return Unit::Vmin; + case UnitHashes::Vmax: + return Unit::Vmax; + case UnitHashes::Rem: + return Unit::Rem; + case UnitHashes::Dprd: + return Unit::Dprd; + case UnitHashes::Dpru: + return Unit::Dpru; + } return Unit::Px; } @@ -82,6 +152,10 @@ std::string StyleSheetLength::unitToString( const StyleSheetLength::Unit& unit ) return "vmax"; case Unit::Rem: return "rem"; + case Unit::Dprd: + return "dprd"; + case Unit::Dpru: + return "dpru"; } return "px"; } @@ -123,6 +197,12 @@ Float StyleSheetLength::asPixels( const Float& parentSize, const Sizef& viewSize case Unit::Dp: ret = PixelDensity::dpToPx( mValue ); break; + case Unit::Dprd: + ret = roundDown( PixelDensity::dpToPx( mValue ) ); + break; + case Unit::Dpru: + ret = roundUp( PixelDensity::dpToPx( mValue ) ); + break; case Unit::Em: ret = Math::round( mValue * elFontSize ); break; @@ -190,22 +270,15 @@ StyleSheetLength& StyleSheetLength::operator=( const StyleSheetLength& val ) { return *this; } -static std::string positionToPercentage( const std::string& pos ) { - if ( pos == "center" ) - return "50%"; - if ( pos == "left" || pos == "top" ) - return "0%"; - if ( pos == "right" || pos == "bottom" ) - return "100%"; - return pos; -} +StyleSheetLength StyleSheetLength::fromString( const std::string& str, const Float& defaultValue ) { + PercentagePositions isPercentage = isPercentagePosition( String::hash( str ) ); + if ( PercentagePositions::None != isPercentage ) + return fromString( positionToPercentage( isPercentage ), defaultValue ); -StyleSheetLength StyleSheetLength::fromString( std::string str, const Float& defaultValue ) { StyleSheetLength length; length.setValue( defaultValue, Unit::Px ); std::string num; std::string unit; - str = positionToPercentage( str ); for ( std::size_t i = 0; i < str.size(); i++ ) { if ( String::isNumber( str[i], true ) || ( '-' == str[i] && i == 0 ) || @@ -219,11 +292,8 @@ StyleSheetLength StyleSheetLength::fromString( std::string str, const Float& def if ( !num.empty() ) { Float val = 0; - bool res = String::fromString( val, num ); - - if ( res ) { + if ( String::fromString( val, num ) ) length.setValue( val, unitFromString( unit ) ); - } } return length; @@ -233,7 +303,8 @@ std::string StyleSheetLength::toString() const { std::string res; if ( (Int64)mValue == mValue ) res = String::format( "%lld%s", (Int64)mValue, unitToString( mUnit ).c_str() ); - res = String::format( "%.2f%s", mValue, unitToString( mUnit ).c_str() ); + else + res = String::format( "%.2f%s", mValue, unitToString( mUnit ).c_str() ); String::replace( res, ",", "." ); return res; } diff --git a/src/eepp/ui/css/stylesheetselector.cpp b/src/eepp/ui/css/stylesheetselector.cpp index 035592232..abcd0e764 100644 --- a/src/eepp/ui/css/stylesheetselector.cpp +++ b/src/eepp/ui/css/stylesheetselector.cpp @@ -109,7 +109,7 @@ void StyleSheetSelector::parseSelector( std::string selector ) { } } -const bool& StyleSheetSelector::isCacheable() const { +bool StyleSheetSelector::isCacheable() const { return mCacheable; } @@ -210,7 +210,7 @@ bool StyleSheetSelector::select( UIWidget* element, const bool& applyPseudo ) co } std::vector StyleSheetSelector::getRelatedElements( UIWidget* element, - const bool& applyPseudo ) const { + bool applyPseudo ) const { static std::vector EMPTY_ELEMENTS; std::vector elements; if ( mSelectorRules.empty() ) @@ -331,7 +331,7 @@ std::vector StyleSheetSelector::getRelatedElements( UIWidget* element return elements; } -const bool& StyleSheetSelector::isStructurallyVolatile() const { +bool StyleSheetSelector::isStructurallyVolatile() const { return mStructurallyVolatile; } diff --git a/src/eepp/ui/uinodedrawable.cpp b/src/eepp/ui/uinodedrawable.cpp index d99ca49f9..fc43358a2 100644 --- a/src/eepp/ui/uinodedrawable.cpp +++ b/src/eepp/ui/uinodedrawable.cpp @@ -656,7 +656,7 @@ void UINodeDrawable::LayerDrawable::update() { setDrawable( mDrawableRef ); } - mDrawableSize = calcDrawableSize( mSizeEq ).roundDown(); + mDrawableSize = calcDrawableSize( mSizeEq ); mOffset = calcPosition( mPositionX + " " + mPositionY ); mNeedsUpdate = false; diff --git a/src/eepp/ui/uitabwidget.cpp b/src/eepp/ui/uitabwidget.cpp index 4b1120670..34e61048f 100644 --- a/src/eepp/ui/uitabwidget.cpp +++ b/src/eepp/ui/uitabwidget.cpp @@ -482,6 +482,7 @@ UITab* UITabWidget::createTab( const String& text, UINode* nodeOwned, Drawable* tab->setVisible( true ); tab->setEnabled( true ); tab->setOwnedWidget( nodeOwned ); + tab->reloadStyle( true, true, true ); if ( tab->getCloseButton() ) { tab->getCloseButton() ->setVisible( mStyleConfig.TabsClosable && mStyleConfig.TabCloseButtonVisible ) @@ -752,9 +753,7 @@ UITab* UITabWidget::setTabSelected( UITab* tab ) { if ( tab->getOwnedWidget() ) tab->getOwnedWidget()->setFocus(); return tab; - } - - if ( NULL != mTabSelected ) { + } else if ( NULL != mTabSelected ) { mTabSelected->unselect(); if ( NULL != mTabSelected->getOwnedWidget() ) { diff --git a/src/tools/ecode/applayout.xml.hpp b/src/tools/ecode/applayout.xml.hpp index 6a5fd3f3e..e4d7ae2c9 100644 --- a/src/tools/ecode/applayout.xml.hpp +++ b/src/tools/ecode/applayout.xml.hpp @@ -390,6 +390,13 @@ Anchor.error:hover { #code_container > TabWidget > TabWidget::TabBar > Tab > Tab::Text { text-overflow: ellipsis; } +#code_container > TabWidget > TabWidget::TabBar > Tab > Tab::close { + opacity: 0; +} +#code_container > TabWidget > TabWidget::TabBar > Tab:selected > Tab::close, +#code_container > TabWidget > TabWidget::TabBar > Tab:hover > Tab::close { + opacity: 1; +} diff --git a/src/tools/ecode/projectdirectorytree.cpp b/src/tools/ecode/projectdirectorytree.cpp index 92125625d..1336da534 100644 --- a/src/tools/ecode/projectdirectorytree.cpp +++ b/src/tools/ecode/projectdirectorytree.cpp @@ -15,12 +15,14 @@ ProjectDirectoryTree::ProjectDirectoryTree( const std::string& path, mRunning( false ), mIsReady( false ), mIgnoreHidden( true ), + mClosing( false ), mIgnoreMatcher( path ), mApp( app ) { FileSystem::dirAddSlashAtEnd( mPath ); } ProjectDirectoryTree::~ProjectDirectoryTree() { + mClosing = true; if ( mApp->getPluginManager() ) mApp->getPluginManager()->unsubscribeMessages( "ProjectDirectoryTree" ); Lock rl( mMatchingMutex ); @@ -28,6 +30,9 @@ ProjectDirectoryTree::~ProjectDirectoryTree() { mRunning = false; Lock l( mFilesMutex ); } + { + Lock l( mDoneMutex ); + } } void ProjectDirectoryTree::scan( const ProjectDirectoryTree::ScanCompleteEvent& scanComplete, @@ -76,7 +81,6 @@ void ProjectDirectoryTree::scan( const ProjectDirectoryTree::ScanCompleteEvent& mAllowedMatcher.get() ); } mIsReady = true; - mRunning = false; mApp->getPluginManager()->subscribeMessages( "ProjectDirectoryTree", [this]( const PluginMessage& msg ) -> PluginRequestHandle { return processMessage( msg ); @@ -88,8 +92,11 @@ void ProjectDirectoryTree::scan( const ProjectDirectoryTree::ScanCompleteEvent& #if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ ) }, [scanComplete, this]( const auto& ) { - if ( scanComplete ) + if ( !mClosing && scanComplete ) { + Lock l( mDoneMutex ); scanComplete( *this ); + } + mRunning = false; } ); #endif } @@ -324,7 +331,8 @@ void ProjectDirectoryTree::tryAddFile( const FileInfo& file ) { } if ( foundPattern ) { Lock l( mFilesMutex ); - auto exists = std::find( mFiles.begin(), mFiles.end(), file.getFilepath() ) != mFiles.end(); + auto exists = + std::find( mFiles.begin(), mFiles.end(), file.getFilepath() ) != mFiles.end(); if ( !exists ) { mFiles.emplace_back( file.getFilepath() ); mNames.emplace_back( file.getFileName() ); diff --git a/src/tools/ecode/projectdirectorytree.hpp b/src/tools/ecode/projectdirectorytree.hpp index c204f1de9..4e1526fbb 100644 --- a/src/tools/ecode/projectdirectorytree.hpp +++ b/src/tools/ecode/projectdirectorytree.hpp @@ -158,8 +158,10 @@ class ProjectDirectoryTree { bool mRunning; bool mIsReady; bool mIgnoreHidden; + bool mClosing; mutable Mutex mFilesMutex; mutable Mutex mMatchingMutex; + Mutex mDoneMutex; IgnoreMatcherManager mIgnoreMatcher; App* mApp{ nullptr };