diff options
author | Dave Davenport <qball@gmpclient.org> | 2020-04-23 20:04:41 +0200 |
---|---|---|
committer | Dave Davenport <qball@gmpclient.org> | 2020-04-23 20:04:41 +0200 |
commit | 1cf9fd4b5e63d05bdbcda7b2ff7db1934dcfa8c2 (patch) | |
tree | 7b8c7e785a1478d71f81e430334331bc44c4de9c | |
parent | f90ad971d9d334b26280fbf14dda700877f75d67 (diff) |
Initial test to allow math in distances.
Support + and -
Needs spaces around + and -.
-rw-r--r-- | include/rofi-types.h | 22 | ||||
-rw-r--r-- | include/theme.h | 1 | ||||
-rw-r--r-- | lexer/theme-lexer.l | 5 | ||||
-rw-r--r-- | lexer/theme-parser.y | 79 | ||||
-rw-r--r-- | source/theme.c | 120 | ||||
-rw-r--r-- | source/widgets/scrollbar.c | 2 | ||||
-rw-r--r-- | source/widgets/widget.c | 10 |
7 files changed, 200 insertions, 39 deletions
diff --git a/include/rofi-types.h b/include/rofi-types.h index bb294dad..c546f6e6 100644 --- a/include/rofi-types.h +++ b/include/rofi-types.h @@ -89,12 +89,32 @@ typedef enum /** * Structure representing a distance. */ -typedef struct +typedef enum +{ + ROFI_DISTANCE_MODIFIER_NONE, + ROFI_DISTANCE_MODIFIER_ADD, + ROFI_DISTANCE_MODIFIER_SUBTRACT, +} RofiDistanceModifier; + +typedef struct RofiDistanceUnit { /** Distance */ double distance; /** Unit type of the distance */ RofiPixelUnit type; + + /** Type */ + RofiDistanceModifier modtype; + + /** Modifier */ + struct RofiDistanceUnit *modifier; + +} RofiDistanceUnit; + +typedef struct +{ + /** Base */ + RofiDistanceUnit base; /** Style of the line (optional)*/ RofiLineStyle style; } RofiDistance; diff --git a/include/theme.h b/include/theme.h index 0ed71460..055bea71 100644 --- a/include/theme.h +++ b/include/theme.h @@ -387,4 +387,5 @@ void rofi_theme_parse_merge_widgets ( ThemeWidget *parent, ThemeWidget *child ); * Returns the media type described by type. */ ThemeMediaType rofi_theme_parse_media_type ( const char *type ); +RofiDistance rofi_theme_property_copy_distance ( RofiDistance const distance ); #endif diff --git a/lexer/theme-lexer.l b/lexer/theme-lexer.l index 50a2c4e7..f0b68048 100644 --- a/lexer/theme-lexer.l +++ b/lexer/theme-lexer.l @@ -183,6 +183,9 @@ ASTERIX \* ENV $\{[[:alnum:]]*\} +MODIFIER_ADD \+ +MODIFIER_SUBTRACT - + /* Position */ CENTER (?i:center) NORTH (?i:north) @@ -450,6 +453,8 @@ if ( queue == NULL ){ <PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{LS_DASH} { return T_DASH; } <PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{INHERIT} { return T_INHERIT; } +<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{MODIFIER_ADD} { return T_MODIFIER_ADD; } +<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{MODIFIER_SUBTRACT} { return T_MODIFIER_SUBTRACT; } <PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{ENV} { yytext[yyleng-1] = '\0'; diff --git a/lexer/theme-parser.y b/lexer/theme-parser.y index c85a5bbe..50819098 100644 --- a/lexer/theme-parser.y +++ b/lexer/theme-parser.y @@ -146,6 +146,7 @@ static ThemeColor hwb_to_rgb ( double h, double w, double b) Property *property; GHashTable *property_list; RofiDistance distance; + RofiDistanceUnit *distance_unit; } %token <ival> T_END 0 "end of file" @@ -210,6 +211,9 @@ static ThemeColor hwb_to_rgb ( double h, double w, double b) %token T_LIST_OPEN "List open ('[')" %token T_LIST_CLOSE "List close (']')" +%token T_MODIFIER_ADD "Add ('+')" +%token T_MODIFIER_SUBTRACT "Subtract ('-')" + %token T_BOPEN "bracket open ('{')" %token T_BCLOSE "bracket close ('}')" %token T_PSEP "property separator (':')" @@ -251,6 +255,8 @@ static ThemeColor hwb_to_rgb ( double h, double w, double b) %type <sval> t_property_name %type <distance> t_property_distance %type <distance> t_property_distance_zero +%type <distance_unit> t_property_distance_unit +%type <ival> t_property_distance_modifier_type %type <ival> t_property_unit %type <wloc> t_property_position %type <wloc> t_property_position_ew @@ -503,15 +509,15 @@ t_property_element } | t_property_distance { $$ = rofi_theme_property_create ( P_PADDING ); - $$->value.padding = (RofiPadding){ $1, $1, $1, $1 }; + $$->value.padding = (RofiPadding){ $1, rofi_theme_property_copy_distance($1), rofi_theme_property_copy_distance($1), rofi_theme_property_copy_distance($1) }; } | t_property_distance_zero t_property_distance_zero { $$ = rofi_theme_property_create ( P_PADDING ); - $$->value.padding = (RofiPadding){ $1, $2, $1, $2 }; + $$->value.padding = (RofiPadding){ $1, $2, rofi_theme_property_copy_distance($1), rofi_theme_property_copy_distance($2) }; } | t_property_distance_zero t_property_distance_zero t_property_distance_zero { $$ = rofi_theme_property_create ( P_PADDING ); - $$->value.padding = (RofiPadding){ $1, $2, $3, $2 }; + $$->value.padding = (RofiPadding){ $1, $2, $3, rofi_theme_property_copy_distance($2) }; } | t_property_distance_zero t_property_distance_zero t_property_distance_zero t_property_distance_zero { $$ = rofi_theme_property_create ( P_PADDING ); @@ -599,25 +605,80 @@ t_property_highlight_style t_property_distance_zero : T_INT t_property_line_style { - $$.distance = (double) $1; - $$.type = ROFI_PU_PX; + $$.base.distance = (double) $1; + $$.base.type = ROFI_PU_PX; + $$.base.modifier = NULL; $$.style = $2; } | t_property_distance { $$ = $1;} ; + +t_property_distance_modifier_type +: T_MODIFIER_ADD { $$ = ROFI_DISTANCE_MODIFIER_ADD; } +| T_MODIFIER_SUBTRACT { $$ = ROFI_DISTANCE_MODIFIER_SUBTRACT; }; + + /** Distance. */ +t_property_distance_unit +: t_property_distance_modifier_type T_INT t_property_unit { + $$ = g_malloc0(sizeof(RofiDistanceUnit)); + $$->distance = (double)$2; + $$->type = $3; + $$->modifier = NULL; + $$->modtype = $1; +} +| t_property_distance_modifier_type T_DOUBLE t_property_unit { + $$ = g_malloc0(sizeof(RofiDistanceUnit)); + $$->distance = (double)$2; + $$->type = $3; + $$->modifier = NULL; + $$->modtype = $1; +} +| t_property_distance_modifier_type T_INT t_property_unit t_property_distance_unit { + $$ = g_malloc0(sizeof(RofiDistanceUnit)); + $$->distance = (double)$2; + $$->type = $3; + $$->modifier = $4; + $$->modtype = $1; +} +| t_property_distance_modifier_type T_DOUBLE t_property_unit t_property_distance_unit { + $$ = g_malloc0(sizeof(RofiDistanceUnit)); + $$->distance = (double)$2; + $$->type = $3; + $$->modifier = $4; + $$->modtype = $1; +}; + t_property_distance /** Integer unit and line style */ : T_INT t_property_unit t_property_line_style { - $$.distance = (double)$1; - $$.type = $2; + $$.base.distance = (double)$1; + $$.base.type = $2; + $$.base.modifier = NULL; + $$.base.modtype = ROFI_DISTANCE_MODIFIER_NONE; $$.style = $3; } /** Double unit and line style */ | T_DOUBLE t_property_unit t_property_line_style { - $$.distance = (double)$1; - $$.type = $2; + $$.base.distance = (double)$1; + $$.base.type = $2; + $$.base.modtype = ROFI_DISTANCE_MODIFIER_NONE; + $$.base.modifier = NULL; $$.style = $3; +} +| T_INT t_property_unit t_property_distance_unit t_property_line_style { + $$.base.distance = (double)$1; + $$.base.type = $2; + $$.base.modifier = $3; + $$.base.modtype = ROFI_DISTANCE_MODIFIER_NONE; + $$.style = $4; +} +| T_DOUBLE t_property_unit t_property_distance_unit t_property_line_style { + $$.base.distance = (double)$1; + $$.base.type = $2; + $$.base.modifier = $3; + $$.base.modtype = ROFI_DISTANCE_MODIFIER_NONE; + $$.style = $4; }; /** distance unit. px, em, % */ diff --git a/source/theme.c b/source/theme.c index 069b9ef3..c7489292 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,26 @@ 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_malloc0( sizeof(RofiDistanceUnit) ); + *retv = *unit; + if ( unit->modifier ) { + retv->modifier = rofi_theme_property_copy_distance_unit ( unit->modifier ); + } + return retv; +} +RofiDistance rofi_theme_property_copy_distance ( RofiDistance const distance ) +{ + RofiDistance retv = distance; + if ( distance.base.modifier ) + { + retv.base.modifier = rofi_theme_property_copy_distance_unit ( distance.base.modifier ); + } + return retv; +} + Property* rofi_theme_property_copy ( Property *p ) { Property *retv = rofi_theme_property_create ( p->type ); @@ -100,12 +121,37 @@ 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->modifier ) { + rofi_theme_distance_unit_property_free ( unit->modifier ); + unit->modifier = NULL; + } + g_free (unit); +} +static void rofi_theme_distance_property_free ( RofiDistance *distance ) +{ + if ( distance->base.modifier ) { + rofi_theme_distance_unit_property_free ( distance->base.modifier ); + distance->base.modifier = NULL; + } +} + void rofi_theme_property_free ( Property *p ) { if ( p == NULL ) { @@ -121,6 +167,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 +201,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}, .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 +214,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}, .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 ); @@ -206,19 +258,19 @@ inline static void printf_double ( double d ) } static void rofi_theme_print_distance ( RofiDistance d ) { - if ( d.type == ROFI_PU_PX ) { - printf ( "%upx ", (unsigned int) d.distance ); + if ( d.base.type == ROFI_PU_PX ) { + printf ( "%upx ", (unsigned int) d.base.distance ); } - else if ( d.type == ROFI_PU_PERCENT ) { - printf_double ( d.distance ); + else if ( d.base.type == ROFI_PU_PERCENT ) { + printf_double ( d.base.distance ); fputs ( "%% ", stdout ); } - else if ( d.type == ROFI_PU_CH ) { - printf_double ( d.distance ); + else if ( d.base.type == ROFI_PU_CH ) { + printf_double ( d.base.distance ); fputs ( "ch ", stdout ); } else { - printf_double ( d.distance ); + printf_double ( d.base.distance ); fputs ( "em ", stdout ); } if ( d.style == ROFI_HL_DASH ) { @@ -636,17 +688,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}, .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}, .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}, .style = ROFI_HL_SOLID }; } int rofi_theme_get_boolean ( const widget *widget, const char *property, int def ) @@ -762,7 +814,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}, .style = ROFI_HL_SOLID }; return (RofiPadding){ d, d, d, d }; } } @@ -813,27 +865,49 @@ RofiHighlightColorStyle rofi_theme_get_highlight ( widget *widget, const char *p return th; } -int distance_get_pixel ( RofiDistance d, RofiOrientation ori ) + +static int distance_unit_get_pixel ( 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 ); + } + } + if ( unit->modifier ) { + switch ( unit->modifier->modtype) + { + case ROFI_DISTANCE_MODIFIER_ADD: + val += distance_unit_get_pixel ( unit->modifier, ori); + break; + case ROFI_DISTANCE_MODIFIER_SUBTRACT: + val -= distance_unit_get_pixel ( unit->modifier, ori); + break; + default: + break; } } - return d.distance; + return val; +} + +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..d90ec297 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}, ROFI_HL_SOLID }, { {WIDGET_DEFAULT_PADDING, ROFI_PU_PX,ROFI_DISTANCE_MODIFIER_NONE, NULL}, ROFI_HL_SOLID }, { {WIDGET_DEFAULT_PADDING, ROFI_PU_PX,ROFI_DISTANCE_MODIFIER_NONE, NULL}, ROFI_HL_SOLID }, + { {WIDGET_DEFAULT_PADDING, ROFI_PU_PX,ROFI_DISTANCE_MODIFIER_NONE, NULL}, ROFI_HL_SOLID } }; + wid->def_border = (RofiPadding){ { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL} , ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL}, ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL}, ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL}, ROFI_HL_SOLID } }; + wid->def_border_radius = (RofiPadding){ { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL} , ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL}, ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL}, ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL}, ROFI_HL_SOLID } }; + wid->def_margin = (RofiPadding){ { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL} , ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL}, ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL}, ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, 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 ); |