diff --git a/.agent/rules/build-project.md b/.agent/rules/build-project.md index 1cb266a7d..e5d15561d 100644 --- a/.agent/rules/build-project.md +++ b/.agent/rules/build-project.md @@ -16,6 +16,16 @@ If you have **added, renamed, or deleted** any source files, you must regenerate *(If no files were added/removed, you may skip Step 1).* +## Step 1a: Format Changed Files +After editing any C or C++ source file (`.c`, `.cpp`, `.h`, `.hpp`), you **must** run `clang-format` on all modified files to ensure consistent formatting with the project's style (defined in `.clang-format` at the repository root). + +**Command (formats all currently modified tracked files at once):** +`git diff --name-only -- '*.c' '*.cpp' '*.h' '*.hpp' | xargs clang-format -i` + +Run this **after** all edits and **before** attempting to compile. + +--- + ## Step 2: Compile the Project To compile the project in debug mode, execute the `make` command, ensuring you point to the correct directory for your current Operating System. diff --git a/bin/unit_tests/assets/html/ensoft/ensoft.css b/bin/unit_tests/assets/html/ensoft/ensoft.css index 1db20d51f..b9d032425 100644 --- a/bin/unit_tests/assets/html/ensoft/ensoft.css +++ b/bin/unit_tests/assets/html/ensoft/ensoft.css @@ -5,11 +5,6 @@ a:focus { outline: none; } .no_selection { - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; user-select: none; } .blue_links a { @@ -45,11 +40,6 @@ textarea { width: 200px !important; } #bar { - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; user-select: none; position: fixed; top: 0px; @@ -71,16 +61,10 @@ textarea { width: 225px; background: url('fx.png') no-repeat center; opacity: 0; - -ms-filter: "alpha(opacity=0)"; - -khtml-opacity: 0; - -webkit-animation-name: contract; - -moz-animation-name: contract; - -webkit-animation-duration: 6s; - -moz-animation-duration: 6s; - -webkit-animation-iteration-count: infinite; - -moz-animation-iteration-count: infinite; - -webkit-animation-timing-function: linear; - -moz-animation-timing-function: linear; + animation-name: contract; + animation-duration: 6s; + animation-iteration-count: infinite; + animation-timing-function: linear; } #bar #links li { margin: 40px 30px 0px 0px; @@ -104,9 +88,6 @@ textarea { text-decoration: none; font-size: 12px; border-radius: 4px; - -khtml-border-radius: 4px; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; behavior: url('https://ensoft.dev/assets/js/PIE.php'); background-color: #d0d0d0; color: white; @@ -227,9 +208,6 @@ a img { cursor: pointer; background-color: black; border-radius: 5px; - -khtml-border-radius: 5px; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; behavior: url('https://ensoft.dev/assets/js/PIE.php'); font-size: 16px; color: white !important; @@ -280,9 +258,6 @@ a img { cursor: pointer; background-color: black; border-radius: 5px; - -khtml-border-radius: 5px; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; behavior: url('https://ensoft.dev/assets/js/PIE.php'); font-size: 16px; color: white !important; @@ -430,9 +405,6 @@ a img { border: 5px solid #f0f0f0; padding: 10px; border-radius: 10px; - -khtml-border-radius: 10px; - -webkit-border-radius: 10px; - -moz-border-radius: 10px; behavior: url('https://ensoft.dev/assets/js/PIE.php'); } .blog_post .markdown blockquote { @@ -512,9 +484,6 @@ a img { cursor: pointer; background-color: black; border-radius: 5px; - -khtml-border-radius: 5px; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; behavior: url('https://ensoft.dev/assets/js/PIE.php'); font-size: 16px; color: white !important; @@ -564,9 +533,6 @@ a img { font-weight: bold; background-color: red; border-radius: 5px; - -khtml-border-radius: 5px; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; behavior: url('https://ensoft.dev/assets/js/PIE.php'); } #minimap { @@ -609,10 +575,6 @@ a img { font-size: 12px; font-weight: bold; color: white; - -moz-border-radius-topleft: 4px; - -moz-border-radius-bottomleft: 4px; - -webkit-border-top-left-radius: 4px; - -webkit-border-bottom-left-radius: 4px; border-top-left-radius: 4px; border-bottom-left-radius: 4px; } diff --git a/docs/articles/cssspecification.md b/docs/articles/cssspecification.md index abd20f914..122086566 100644 --- a/docs/articles/cssspecification.md +++ b/docs/articles/cssspecification.md @@ -706,6 +706,18 @@ Multiple flags can be set, flags are separated by `|`. --- +### foreground-bottom-left-radius + +Same as [border-bottom-left-radius](#border-bottom-left-radius) but for the foreground of the node. + +--- + +### foreground-bottom-right-radius + +Same as [border-bottom-right-radius](#border-bottom-right-radius) but for the foreground of the node. + +--- + ### foreground-color Same as [background-color](#background-color) but for the foreground. @@ -756,6 +768,18 @@ Sets the tint color of the foreground image. --- +### foreground-top-left-radius + +Same as [border-top-left-radius](#border-top-left-radius) but for the foreground of the node. + +--- + +### foreground-top-right-radius + +Same as [border-top-right-radius](#border-top-right-radius) but for the foreground of the node. + +--- + ### gravity Sets the horizontal and vertical align of the inner elements/contents of a widget (for example the @@ -2487,6 +2511,8 @@ Same as the [background-position](#background-position) but for the foreground o Same as the [border-radius](#border-radius) but for the foreground of the node. +This is a shorthand for setting [foreground-top-left-radius](#foreground-top-left-radius), [foreground-top-right-radius](#foreground-top-right-radius), [foreground-bottom-right-radius](#foreground-bottom-right-radius), and [foreground-bottom-left-radius](#foreground-bottom-left-radius) in a single declaration. + --- ### hint-shadow diff --git a/include/eepp/ui/css/propertydefinition.hpp b/include/eepp/ui/css/propertydefinition.hpp index 8249ae92c..2cc840c5f 100644 --- a/include/eepp/ui/css/propertydefinition.hpp +++ b/include/eepp/ui/css/propertydefinition.hpp @@ -27,7 +27,10 @@ enum class PropertyId : Uint32 { ForegroundPositionY = String::hash( "foreground-position-y" ), ForegroundRepeat = String::hash( "foreground-repeat" ), ForegroundSize = String::hash( "foreground-size" ), - ForegroundRadius = String::hash( "foreground-radius" ), + ForegroundTopLeftRadius = String::hash( "foreground-top-left-radius" ), + ForegroundTopRightRadius = String::hash( "foreground-top-right-radius" ), + ForegroundBottomLeftRadius = String::hash( "foreground-bottom-left-radius" ), + ForegroundBottomRightRadius = String::hash( "foreground-bottom-right-radius" ), Visible = String::hash( "visible" ), Enabled = String::hash( "enabled" ), Theme = String::hash( "theme" ), diff --git a/include/eepp/ui/uinode.hpp b/include/eepp/ui/uinode.hpp index 801a1216f..30c8061cb 100644 --- a/include/eepp/ui/uinode.hpp +++ b/include/eepp/ui/uinode.hpp @@ -633,6 +633,74 @@ class EE_API UINode : public Node { */ Uint32 getForegroundRadius() const; + /** + * @brief Sets the top-left foreground border radius. + * + * Sets the top-left corner radius for the foreground content. + * + * @param radius The radius value as a string (e.g., "5px", "50%"). + * @return Pointer to this node for method chaining. + */ + UINode* setForegroundTopLeftRadius( const std::string& radius ); + + /** + * @brief Sets the top-right foreground border radius. + * + * Sets the top-right corner radius for the foreground content. + * + * @param radius The radius value as a string (e.g., "5px", "50%"). + * @return Pointer to this node for method chaining. + */ + UINode* setForegroundTopRightRadius( const std::string& radius ); + + /** + * @brief Sets the bottom-left foreground border radius. + * + * Sets the bottom-left corner radius for the foreground content. + * + * @param radius The radius value as a string (e.g., "5px", "50%"). + * @return Pointer to this node for method chaining. + */ + UINode* setForegroundBottomLeftRadius( const std::string& radius ); + + /** + * @brief Sets the bottom-right foreground border radius. + * + * Sets the bottom-right corner radius for the foreground content. + * + * @param radius The radius value as a string (e.g., "5px", "50%"). + * @return Pointer to this node for method chaining. + */ + UINode* setForegroundBottomRightRadius( const std::string& radius ); + + /** + * @brief Gets the top-left foreground border radius. + * + * @return The top-left foreground border radius. + */ + const Sizef& getForegroundTopLeftRadius() const; + + /** + * @brief Gets the top-right foreground border radius. + * + * @return The top-right foreground border radius. + */ + const Sizef& getForegroundTopRightRadius() const; + + /** + * @brief Gets the bottom-left foreground border radius. + * + * @return The bottom-left foreground border radius. + */ + const Sizef& getForegroundBottomLeftRadius() const; + + /** + * @brief Gets the bottom-right foreground border radius. + * + * @return The bottom-right foreground border radius. + */ + const Sizef& getForegroundBottomRightRadius() const; + /** * @brief Enables or disables the border and returns the border drawable. * diff --git a/src/eepp/ui/css/stylesheetspecification.cpp b/src/eepp/ui/css/stylesheetspecification.cpp index 5bc498b7e..620931f4c 100644 --- a/src/eepp/ui/css/stylesheetspecification.cpp +++ b/src/eepp/ui/css/stylesheetspecification.cpp @@ -126,7 +126,6 @@ void StyleSheetSpecification::registerDefaultProperties() { registerProperty( "foreground-size", "auto" ) .setType( PropertyType::ForegroundSize ) .setIndexed(); - registerProperty( "foreground-radius", "0px" ).setType( PropertyType::NumberLength ); registerProperty( "visible", "true" ).setType( PropertyType::Bool ); registerProperty( "enabled", "true" ).setType( PropertyType::Bool ); registerProperty( "theme", "" ); @@ -402,6 +401,11 @@ void StyleSheetSpecification::registerDefaultProperties() { registerProperty( "background-smooth", "false" ).setType( PropertyType::Bool ); registerProperty( "foreground-smooth", "false" ).setType( PropertyType::Bool ); + registerProperty( "foreground-top-left-radius", "0" ).setType( PropertyType::RadiusLength ); + registerProperty( "foreground-top-right-radius", "0" ).setType( PropertyType::RadiusLength ); + registerProperty( "foreground-bottom-left-radius", "0" ).setType( PropertyType::RadiusLength ); + registerProperty( "foreground-bottom-right-radius", "0" ).setType( PropertyType::RadiusLength ); + registerProperty( "tabbar-hide-on-single-tab", "false" ); registerProperty( "tabbar-allow-rearrange", "false" ); registerProperty( "tabbar-allow-drag-and-drop-tabs", "false" ); @@ -517,6 +521,10 @@ void StyleSheetSpecification::registerDefaultProperties() { { "border-top-left-radius", "border-top-right-radius", "border-bottom-right-radius", "border-bottom-left-radius" }, "radius" ); + registerShorthand( "foreground-radius", + { "foreground-top-left-radius", "foreground-top-right-radius", + "foreground-bottom-right-radius", "foreground-bottom-left-radius" }, + "radius" ); registerShorthand( "rotation-origin-point", { "rotation-origin-point-x", "rotation-origin-point-y" }, "vector2" ); registerShorthand( "rotate-origin-point", diff --git a/src/eepp/ui/uinode.cpp b/src/eepp/ui/uinode.cpp index d4f5a61ec..0d0059ff6 100644 --- a/src/eepp/ui/uinode.cpp +++ b/src/eepp/ui/uinode.cpp @@ -883,6 +883,54 @@ Uint32 UINode::getForegroundRadius() const { return NULL != mForeground ? mForeground->getBorderRadius() : 0; } +UINode* UINode::setForegroundTopLeftRadius( const std::string& radius ) { + setForegroundFillEnabled( true )->getBackgroundDrawable().setTopLeftRadius( radius ); + return this; +} + +UINode* UINode::setForegroundTopRightRadius( const std::string& radius ) { + setForegroundFillEnabled( true )->getBackgroundDrawable().setTopRightRadius( radius ); + return this; +} + +UINode* UINode::setForegroundBottomLeftRadius( const std::string& radius ) { + setForegroundFillEnabled( true )->getBackgroundDrawable().setBottomLeftRadius( radius ); + return this; +} + +UINode* UINode::setForegroundBottomRightRadius( const std::string& radius ) { + setForegroundFillEnabled( true )->getBackgroundDrawable().setBottomRightRadius( radius ); + return this; +} + +const Sizef& UINode::getForegroundTopLeftRadius() const { + static const Sizef zero; + if ( NULL != mForeground ) + return mForeground->getBackgroundDrawable().getRadiuses().topLeft; + return zero; +} + +const Sizef& UINode::getForegroundTopRightRadius() const { + static const Sizef zero; + if ( NULL != mForeground ) + return mForeground->getBackgroundDrawable().getRadiuses().topRight; + return zero; +} + +const Sizef& UINode::getForegroundBottomLeftRadius() const { + static const Sizef zero; + if ( NULL != mForeground ) + return mForeground->getBackgroundDrawable().getRadiuses().bottomLeft; + return zero; +} + +const Sizef& UINode::getForegroundBottomRightRadius() const { + static const Sizef zero; + if ( NULL != mForeground ) + return mForeground->getBackgroundDrawable().getRadiuses().bottomRight; + return zero; +} + UIBorderDrawable* UINode::setBorderEnabled( bool enabled ) const { const_cast( this )->writeFlag( UI_BORDER, enabled ? 1 : 0 ); diff --git a/src/eepp/ui/uiwidget.cpp b/src/eepp/ui/uiwidget.cpp index 570ab5edf..b461d148e 100644 --- a/src/eepp/ui/uiwidget.cpp +++ b/src/eepp/ui/uiwidget.cpp @@ -1609,7 +1609,10 @@ std::vector UIWidget::getPropertiesImplemented() const { PropertyId::BackgroundTint, PropertyId::ForegroundColor, PropertyId::ForegroundTint, - PropertyId::ForegroundRadius, + PropertyId::ForegroundTopLeftRadius, + PropertyId::ForegroundTopRightRadius, + PropertyId::ForegroundBottomLeftRadius, + PropertyId::ForegroundBottomRightRadius, PropertyId::BorderType, PropertyId::SkinColor, PropertyId::Rotation, @@ -1701,8 +1704,22 @@ std::string UIWidget::getPropertyString( const PropertyDefinition* propertyDef, return getForegroundColor().toHexString(); case PropertyId::ForegroundTint: return getForegroundTint( propertyIndex ).toHexString(); - case PropertyId::ForegroundRadius: - return String::toString( getForegroundRadius() ); + case PropertyId::ForegroundTopLeftRadius: + return String::format( "%s %s", + String::fromFloat( getForegroundTopLeftRadius().x, "px" ), + String::fromFloat( getForegroundTopLeftRadius().y, "px" ) ); + case PropertyId::ForegroundTopRightRadius: + return String::format( "%s %s", + String::fromFloat( getForegroundTopRightRadius().x, "px" ), + String::fromFloat( getForegroundTopRightRadius().y, "px" ) ); + case PropertyId::ForegroundBottomLeftRadius: + return String::format( "%s %s", + String::fromFloat( getForegroundBottomLeftRadius().x, "px" ), + String::fromFloat( getForegroundBottomLeftRadius().y, "px" ) ); + case PropertyId::ForegroundBottomRightRadius: + return String::format( "%s %s", + String::fromFloat( getForegroundBottomRightRadius().x, "px" ), + String::fromFloat( getForegroundBottomRightRadius().y, "px" ) ); case PropertyId::BorderType: return Borders::fromBorderType( setBorderEnabled( true )->getBorderType() ); case PropertyId::SkinColor: @@ -1964,8 +1981,17 @@ bool UIWidget::applyProperty( const StyleSheetProperty& attribute ) { case PropertyId::ForegroundImage: setForegroundDrawable( attribute.getValue(), attribute.getIndex() ); break; - case PropertyId::ForegroundRadius: - setForegroundRadius( lengthFromValue( attribute ) ); + case PropertyId::ForegroundTopLeftRadius: + setForegroundTopLeftRadius( attribute.value() ); + break; + case PropertyId::ForegroundTopRightRadius: + setForegroundTopRightRadius( attribute.value() ); + break; + case PropertyId::ForegroundBottomLeftRadius: + setForegroundBottomLeftRadius( attribute.value() ); + break; + case PropertyId::ForegroundBottomRightRadius: + setForegroundBottomRightRadius( attribute.value() ); break; case PropertyId::ForegroundSize: setForegroundSize( attribute.value(), attribute.getIndex() );