summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorDave Davenport <DaveDavenport@users.noreply.github.com>2020-04-24 19:54:08 +0200
committerGitHub <noreply@github.com>2020-04-24 19:54:08 +0200
commit151547a99ed142168ec4a11e526102994f6736a9 (patch)
tree523506cae7120bc80c1234c94c1f0a4e1cd66bc6 /source
parentf90ad971d9d334b26280fbf14dda700877f75d67 (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.c211
-rw-r--r--source/widgets/scrollbar.c2
-rw-r--r--source/widgets/widget.c10
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 );