diff options
author | Dave Davenport <DaveDavenport@users.noreply.github.com> | 2020-04-24 19:54:08 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-24 19:54:08 +0200 |
commit | 151547a99ed142168ec4a11e526102994f6736a9 (patch) | |
tree | 523506cae7120bc80c1234c94c1f0a4e1cd66bc6 /source | |
parent | f90ad971d9d334b26280fbf14dda700877f75d67 (diff) |
[Themes] add calc() support to distance in theme format. (#1105)
* Initial test to allow math in distances.
Support + and -
Needs spaces around + and -.
* [THEME] Fix printing theme with math in distance.
* [Theme] use calc() syntax.
* [Theme] Add * and / to calc().
* [Theme] Fix the precedense ordering in parsing. Also avoid making copies.
* [Theme] Don't print unneeded ().
* [Theme] Add modulo to calc.
Diffstat (limited to 'source')
-rw-r--r-- | source/theme.c | 211 | ||||
-rw-r--r-- | source/widgets/scrollbar.c | 2 | ||||
-rw-r--r-- | source/widgets/widget.c | 10 |
3 files changed, 188 insertions, 35 deletions
diff --git a/source/theme.c b/source/theme.c index 069b9ef3..85bf7c86 100644 --- a/source/theme.c +++ b/source/theme.c @@ -47,7 +47,8 @@ void yyerror ( YYLTYPE *yylloc, const char *, const char * ); static gboolean distance_compare ( RofiDistance d, RofiDistance e ) { - return d.type == e.type && d.distance == e.distance && d.style == e.style; + // TODO UPDATE + return d.base.type == e.base.type && d.base.distance == e.base.distance && d.style == e.style; } static gpointer rofi_g_list_strdup ( gconstpointer data, G_GNUC_UNUSED gpointer user_data ) @@ -80,6 +81,33 @@ Property *rofi_theme_property_create ( PropertyType type ) retv->type = type; return retv; } + +static RofiDistanceUnit *rofi_theme_property_copy_distance_unit ( RofiDistanceUnit *unit ) +{ + RofiDistanceUnit *retv = g_slice_new0( RofiDistanceUnit ); + *retv = *unit; + if ( unit->left ) { + retv->left = rofi_theme_property_copy_distance_unit ( unit->left ); + } + if ( unit->right ) { + retv->right = rofi_theme_property_copy_distance_unit ( unit->right ); + } + return retv; +} +RofiDistance rofi_theme_property_copy_distance ( RofiDistance const distance ) +{ + RofiDistance retv = distance; + if ( distance.base.left ) + { + retv.base.left = rofi_theme_property_copy_distance_unit ( distance.base.left ); + } + if ( distance.base.right ) + { + retv.base.right = rofi_theme_property_copy_distance_unit ( distance.base.right ); + } + return retv; +} + Property* rofi_theme_property_copy ( Property *p ) { Property *retv = rofi_theme_property_create ( p->type ); @@ -100,12 +128,45 @@ Property* rofi_theme_property_copy ( Property *p ) retv->value.link.def_value = rofi_theme_property_copy ( p->value.link.def_value ); } break; + case P_PADDING: + { + retv->value = p->value; + retv->value.padding.top = rofi_theme_property_copy_distance ( p->value.padding.top); + retv->value.padding.left = rofi_theme_property_copy_distance ( p->value.padding.left); + retv->value.padding.bottom = rofi_theme_property_copy_distance ( p->value.padding.bottom); + retv->value.padding.right = rofi_theme_property_copy_distance ( p->value.padding.right); + break; + } default: retv->value = p->value; } return retv; } +static void rofi_theme_distance_unit_property_free ( RofiDistanceUnit *unit ) +{ + if ( unit->left ) { + rofi_theme_distance_unit_property_free ( unit->left ); + unit->left = NULL; + } + if ( unit->right ) { + rofi_theme_distance_unit_property_free ( unit->right ); + unit->right = NULL; + } + g_slice_free ( RofiDistanceUnit, unit); +} +static void rofi_theme_distance_property_free ( RofiDistance *distance ) +{ + if ( distance->base.left ) { + rofi_theme_distance_unit_property_free ( distance->base.left ); + distance->base.left = NULL; + } + if ( distance->base.right ) { + rofi_theme_distance_unit_property_free ( distance->base.right ); + distance->base.right = NULL; + } +} + void rofi_theme_property_free ( Property *p ) { if ( p == NULL ) { @@ -121,6 +182,12 @@ void rofi_theme_property_free ( Property *p ) rofi_theme_property_free ( p->value.link.def_value ); } } + if ( p->type == P_PADDING) { + rofi_theme_distance_property_free( &(p->value.padding.top)); + rofi_theme_distance_property_free( &(p->value.padding.right)); + rofi_theme_distance_property_free( &(p->value.padding.bottom)); + rofi_theme_distance_property_free( &(p->value.padding.left)); + } g_slice_free ( Property, p ); } @@ -149,7 +216,7 @@ static void rofi_theme_insert_listview_backwards_fix ( void ) rofi_theme_widget_add_properties ( tt, table ); - RofiDistance dsize = (RofiDistance){ 1.2, ROFI_PU_CH, ROFI_HL_SOLID }; + RofiDistance dsize = (RofiDistance){ .base = {1.2, ROFI_PU_CH, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, .style = ROFI_HL_SOLID }; Property *pts = rofi_theme_property_create ( P_PADDING ); pts->value.padding.top = pts->value.padding.right = pts->value.padding.bottom = pts->value.padding.left = dsize; pts->name = g_strdup ( "size" ); @@ -162,7 +229,7 @@ static void rofi_theme_insert_listview_backwards_fix ( void ) table = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, (GDestroyNotify) rofi_theme_property_free ); Property *psp = rofi_theme_property_create ( P_PADDING ); psp->name = g_strdup ( "spacing" ); - RofiDistance d = (RofiDistance){ 5, ROFI_PU_PX, ROFI_HL_SOLID }; + RofiDistance d = (RofiDistance){ .base = {5, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, .style = ROFI_HL_SOLID }; psp->value.padding = (RofiPadding){ d, d, d, d }; g_hash_table_replace ( table, psp->name, psp ); rofi_theme_widget_add_properties ( t, table ); @@ -187,6 +254,9 @@ void rofi_theme_free ( ThemeWidget *widget ) g_hash_table_destroy ( widget->properties ); widget->properties = NULL; } + if ( widget->media ) { + g_slice_free ( ThemeMedia, widget->media ); + } for ( unsigned int i = 0; i < widget->num_widgets; i++ ) { rofi_theme_free ( widget->widgets[i] ); } @@ -204,22 +274,58 @@ inline static void printf_double ( double d ) g_ascii_formatd ( buf, G_ASCII_DTOSTR_BUF_SIZE, "%.4lf", d ); fputs ( buf, stdout ); } -static void rofi_theme_print_distance ( RofiDistance d ) + +static void rofi_theme_print_distance_unit ( RofiDistanceUnit *unit ) { - if ( d.type == ROFI_PU_PX ) { - printf ( "%upx ", (unsigned int) d.distance ); - } - else if ( d.type == ROFI_PU_PERCENT ) { - printf_double ( d.distance ); - fputs ( "%% ", stdout ); + if ( unit->modtype == ROFI_DISTANCE_MODIFIER_GROUP ) + fputs("( " , stdout); + if ( unit->left ) + rofi_theme_print_distance_unit ( unit->left ); + + if ( unit->modtype == ROFI_DISTANCE_MODIFIER_ADD ) { + fputs ( " + ", stdout ); + } else if ( unit->modtype == ROFI_DISTANCE_MODIFIER_SUBTRACT ) { + fputs ( " - ", stdout ); + } else if ( unit->modtype == ROFI_DISTANCE_MODIFIER_DIVIDE ) { + fputs ( " / ", stdout ); + } else if ( unit->modtype == ROFI_DISTANCE_MODIFIER_MULTIPLY) { + fputs ( " * ", stdout ); + } else if ( unit->modtype == ROFI_DISTANCE_MODIFIER_MODULO) { + fputs ( " % ", stdout ); + } + if ( unit->right ) + rofi_theme_print_distance_unit ( unit->right ); + + if ( unit->modtype == ROFI_DISTANCE_MODIFIER_NONE ) + { + if ( unit->type == ROFI_PU_PX ) { + printf ( "%upx ", (unsigned int) unit->distance ); + } + else if ( unit->type == ROFI_PU_PERCENT ) { + printf_double ( unit->distance ); + fputs ( "% ", stdout ); + } + else if ( unit->type == ROFI_PU_CH ) { + printf_double ( unit->distance ); + fputs ( "ch ", stdout ); + } + else { + printf_double ( unit->distance ); + fputs ( "em ", stdout ); + } } - else if ( d.type == ROFI_PU_CH ) { - printf_double ( d.distance ); - fputs ( "ch ", stdout ); + if ( unit->modtype == ROFI_DISTANCE_MODIFIER_GROUP ) + fputs(" )" , stdout); +} + +static void rofi_theme_print_distance ( RofiDistance d ) +{ + if ( d.base.modtype == ROFI_DISTANCE_MODIFIER_GROUP ){ + fputs( "calc( ", stdout ); } - else { - printf_double ( d.distance ); - fputs ( "em ", stdout ); + rofi_theme_print_distance_unit ( &(d.base) ); + if ( d.base.modtype == ROFI_DISTANCE_MODIFIER_GROUP ){ + fputs( ")", stdout ); } if ( d.style == ROFI_HL_DASH ) { printf ( "dash " ); @@ -636,17 +742,17 @@ RofiDistance rofi_theme_get_distance ( const widget *widget, const char *propert if ( widget->parent ) { return rofi_theme_get_distance ( widget->parent, property, def ); } - return (RofiDistance){ def, ROFI_PU_PX, ROFI_HL_SOLID }; + return (RofiDistance){ .base = {def, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, .style = ROFI_HL_SOLID }; } if ( p->type == P_INTEGER ) { - return (RofiDistance){ p->value.i, ROFI_PU_PX, ROFI_HL_SOLID }; + return (RofiDistance){ .base = { p->value.i, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, .style = ROFI_HL_SOLID }; } else { return p->value.padding.left; } } g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property ); - return (RofiDistance){ def, ROFI_PU_PX, ROFI_HL_SOLID }; + return (RofiDistance){ .base = {def, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, .style = ROFI_HL_SOLID }; } int rofi_theme_get_boolean ( const widget *widget, const char *property, int def ) @@ -762,7 +868,7 @@ RofiPadding rofi_theme_get_padding ( const widget *widget, const char *property, pad = p->value.padding; } else { - RofiDistance d = (RofiDistance){ p->value.i, ROFI_PU_PX, ROFI_HL_SOLID }; + RofiDistance d = (RofiDistance){ .base = {p->value.i, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, .style = ROFI_HL_SOLID }; return (RofiPadding){ d, d, d, d }; } } @@ -813,27 +919,74 @@ RofiHighlightColorStyle rofi_theme_get_highlight ( widget *widget, const char *p return th; } -int distance_get_pixel ( RofiDistance d, RofiOrientation ori ) +static int get_pixels ( RofiDistanceUnit *unit, RofiOrientation ori ) { - if ( d.type == ROFI_PU_EM ) { - return d.distance * textbox_get_estimated_char_height (); + int val = unit->distance; + + + if ( unit->type == ROFI_PU_EM ) { + val = unit->distance * textbox_get_estimated_char_height (); } - else if ( d.type == ROFI_PU_CH ) { - return d.distance * textbox_get_estimated_ch (); + else if ( unit->type == ROFI_PU_CH ) { + val = unit->distance * textbox_get_estimated_ch (); } - else if ( d.type == ROFI_PU_PERCENT ) { + else if ( unit->type == ROFI_PU_PERCENT ) { if ( ori == ROFI_ORIENTATION_VERTICAL ) { int height = 0; rofi_view_get_current_monitor ( NULL, &height ); - return ( d.distance * height ) / ( 100.0 ); + val = ( unit->distance * height ) / ( 100.0 ); } else { int width = 0; rofi_view_get_current_monitor ( &width, NULL ); - return ( d.distance * width ) / ( 100.0 ); + val = ( unit->distance * width ) / ( 100.0 ); } } - return d.distance; + return val; +} + + +static int distance_unit_get_pixel ( RofiDistanceUnit *unit, RofiOrientation ori ) +{ + switch ( unit->modtype) + { + case ROFI_DISTANCE_MODIFIER_GROUP: + return distance_unit_get_pixel ( unit->left, ori ); + break; + case ROFI_DISTANCE_MODIFIER_ADD: + return distance_unit_get_pixel ( unit->left, ori)+ distance_unit_get_pixel ( unit->right, ori); + case ROFI_DISTANCE_MODIFIER_SUBTRACT: + return distance_unit_get_pixel ( unit->left, ori)- distance_unit_get_pixel ( unit->right, ori); + case ROFI_DISTANCE_MODIFIER_MULTIPLY: + return distance_unit_get_pixel ( unit->left, ori)* distance_unit_get_pixel ( unit->right, ori); + case ROFI_DISTANCE_MODIFIER_DIVIDE: + { + int a = distance_unit_get_pixel ( unit->left, ori); + int b = distance_unit_get_pixel ( unit->right, ori); + if ( b != 0 ) { + return a/b; + } + return a; + } + case ROFI_DISTANCE_MODIFIER_MODULO: + { + int a = distance_unit_get_pixel ( unit->left, ori); + int b = distance_unit_get_pixel ( unit->right, ori); + if ( b != 0 ) { + return a%b; + } + return 0; + } + default: + break; + } + return get_pixels ( unit, ori ); +} + + +int distance_get_pixel ( RofiDistance d, RofiOrientation ori ) +{ + return distance_unit_get_pixel ( &(d.base), ori); } void distance_get_linestyle ( RofiDistance d, cairo_t *draw ) diff --git a/source/widgets/scrollbar.c b/source/widgets/scrollbar.c index dd057591..699ab07e 100644 --- a/source/widgets/scrollbar.c +++ b/source/widgets/scrollbar.c @@ -51,7 +51,7 @@ static int scrollbar_get_desired_height ( widget *wid ) // This should behave more like a real scrollbar. guint scrollbar_scroll_get_line ( const scrollbar *sb, int y ) { - y -= sb->widget.border.top.distance; + y -= sb->widget.border.top.base.distance; if ( y < 0 ) { return 0; } diff --git a/source/widgets/widget.c b/source/widgets/widget.c index 5dfd9437..c0e89859 100644 --- a/source/widgets/widget.c +++ b/source/widgets/widget.c @@ -40,11 +40,11 @@ void widget_init ( widget *wid, widget *parent, WidgetType type, const char *nam wid->parent = parent; wid->name = g_strdup ( name ); wid->def_padding = - (RofiPadding){ { WIDGET_DEFAULT_PADDING, ROFI_PU_PX, ROFI_HL_SOLID }, { WIDGET_DEFAULT_PADDING, ROFI_PU_PX, ROFI_HL_SOLID }, { WIDGET_DEFAULT_PADDING, ROFI_PU_PX, ROFI_HL_SOLID }, - { WIDGET_DEFAULT_PADDING, ROFI_PU_PX, ROFI_HL_SOLID } }; - wid->def_border = (RofiPadding){ { 0, ROFI_PU_PX, ROFI_HL_SOLID }, { 0, ROFI_PU_PX, ROFI_HL_SOLID }, { 0, ROFI_PU_PX, ROFI_HL_SOLID }, { 0, ROFI_PU_PX, ROFI_HL_SOLID } }; - wid->def_border_radius = (RofiPadding){ { 0, ROFI_PU_PX, ROFI_HL_SOLID }, { 0, ROFI_PU_PX, ROFI_HL_SOLID }, { 0, ROFI_PU_PX, ROFI_HL_SOLID }, { 0, ROFI_PU_PX, ROFI_HL_SOLID } }; - wid->def_margin = (RofiPadding){ { 0, ROFI_PU_PX, ROFI_HL_SOLID }, { 0, ROFI_PU_PX, ROFI_HL_SOLID }, { 0, ROFI_PU_PX, ROFI_HL_SOLID }, { 0, ROFI_PU_PX, ROFI_HL_SOLID } }; + (RofiPadding){ { {WIDGET_DEFAULT_PADDING, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID }, { {WIDGET_DEFAULT_PADDING, ROFI_PU_PX,ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID }, { {WIDGET_DEFAULT_PADDING, ROFI_PU_PX,ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID }, + { {WIDGET_DEFAULT_PADDING, ROFI_PU_PX,ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID } }; + wid->def_border = (RofiPadding){ { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL} , ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID } }; + wid->def_border_radius = (RofiPadding){ { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL} , ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID } }; + wid->def_margin = (RofiPadding){ { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL} , ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID } }; wid->padding = rofi_theme_get_padding ( wid, "padding", wid->def_padding ); wid->border = rofi_theme_get_padding ( wid, "border", wid->def_border ); |