summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Davenport <qball@gmpclient.org>2017-05-25 23:41:15 +0200
committerDave Davenport <qball@gmpclient.org>2017-05-25 23:41:15 +0200
commitc23df70aebf9d6926303b4ddb8d099a4d285949f (patch)
tree2eb4f57db7550584a032340d8f42a4492a634358
parente387105091fb9802de474d00035a640bf06dabc3 (diff)
Allow interface to be dynamically changed.
-rw-r--r--include/theme.h57
-rw-r--r--lexer/theme-lexer.l24
-rw-r--r--lexer/theme-parser.y21
-rw-r--r--source/theme.c22
-rw-r--r--source/view.c186
-rw-r--r--source/widgets/box.c2
6 files changed, 219 insertions, 93 deletions
diff --git a/include/theme.h b/include/theme.h
index 2ebd187c..bc200953 100644
--- a/include/theme.h
+++ b/include/theme.h
@@ -118,6 +118,8 @@ typedef enum
P_POSITION,
/** Highlight */
P_HIGHLIGHT,
+ /** List */
+ P_LIST,
} PropertyType;
/**
@@ -156,6 +158,34 @@ typedef struct
/** Color */
ThemeColor color;
} ThemeHighlight;
+
+typedef union {
+ /** integer */
+ int i;
+ /** Double */
+ double f;
+ /** String */
+ char *s;
+ /** boolean */
+ gboolean b;
+ /** Color */
+ ThemeColor color;
+ /** Padding */
+ Padding padding;
+ /** Reference */
+ struct
+ {
+ /** Name */
+ char *name;
+ /** Cached looked up ref */
+ struct Property *ref;
+ } link;
+ /** Highlight Style */
+ ThemeHighlight highlight;
+ /** List */
+ GList *list;
+} PropertyValue;
+
/**
* Property structure.
*/
@@ -166,31 +196,7 @@ typedef struct Property
/** Type of property. */
PropertyType type;
/** Value */
- union
- {
- /** integer */
- int i;
- /** Double */
- double f;
- /** String */
- char *s;
- /** boolean */
- gboolean b;
- /** Color */
- ThemeColor color;
- /** Padding */
- Padding padding;
- /** Reference */
- struct
- {
- /** Name */
- char *name;
- /** Cached looked up ref */
- struct Property *ref;
- } link;
- /** Highlight Style */
- ThemeHighlight highlight;
- } value;
+ PropertyValue value;
} Property;
/**
* ThemeWidget.
@@ -445,6 +451,7 @@ ThemeWidget *rofi_theme_find_widget ( const char *name, const char *state, gbool
*/
Property *rofi_theme_find_property ( ThemeWidget *widget, PropertyType type, const char *property, gboolean exact );
+GList *rofi_theme_get_list ( const widget *widget, const char * property, const char *defaults);
/**
* Checks if a theme is set, or is empty.
* @returns TRUE when empty.
diff --git a/lexer/theme-lexer.l b/lexer/theme-lexer.l
index 80ee6584..826fff85 100644
--- a/lexer/theme-lexer.l
+++ b/lexer/theme-lexer.l
@@ -211,6 +211,9 @@ S_T_PARENT_RIGHT \)
COMMA ,
FORWARD_SLASH \/
+LIST_OPEN \[
+LIST_CLOSE \]
+
LS_DASH "dash"
LS_SOLID "solid"
@@ -220,6 +223,7 @@ CONFIGURATION "configuration"
%x INCLUDE
%x PROPERTIES
+%x PROPERTIES_LIST
%x NAMESTR
%x SECTION
%x DEFAULTS
@@ -382,7 +386,7 @@ if ( queue == NULL ){
/* After Namestr/Classstr we want to go to state str, then to { */
<INITIAL,SECTION>{WHITESPACE}+ ; // ignore all whitespace
-<PROPERTIES>{WHITESPACE}+ ; // ignore all whitespace
+<PROPERTIES,PROPERTIES_LIST>{WHITESPACE}+ ; // ignore all whitespace
<SECTION>":" { g_queue_push_head ( queue, GINT_TO_POINTER (YY_START) ); BEGIN(PROPERTIES); return T_PSEP; }
<PROPERTIES>";" { BEGIN(GPOINTER_TO_INT ( g_queue_pop_head ( queue ))); return T_PCLOSE;}
@@ -448,7 +452,16 @@ if ( queue == NULL ){
/* Fluff */
<PROPERTIES>{S_T_PARENT_LEFT} { return T_PARENT_LEFT; }
<PROPERTIES>{S_T_PARENT_RIGHT} { return T_PARENT_RIGHT; }
-<PROPERTIES>{COMMA} { return T_COMMA; }
+<PROPERTIES,PROPERTIES_LIST>{COMMA} { return T_COMMA; }
+<PROPERTIES>{LIST_OPEN} {
+ g_queue_push_head ( queue, GINT_TO_POINTER (YY_START) );
+ BEGIN(PROPERTIES_LIST);
+ return T_LIST_OPEN;
+}
+<PROPERTIES_LIST>{LIST_CLOSE} {
+ BEGIN(GPOINTER_TO_INT(g_queue_pop_head ( queue )));
+ return T_LIST_CLOSE;
+}
<PROPERTIES>{FORWARD_SLASH} { return T_FORWARD_SLASH; }
/* Position */
<PROPERTIES>{CENTER} { return T_POS_CENTER; }
@@ -521,7 +534,12 @@ if ( queue == NULL ){
<SECTION>. {
return T_ERROR_SECTION;
}
-<PROPERTIES>. {
+<PROPERTIES_LIST>{WORD} {
+ yylval->sval = g_strdup(yytext);
+ return T_ELEMENT;
+}
+
+<PROPERTIES,PROPERTIES_LIST>. {
return T_ERROR_PROPERTY;
}
<NAMESTR>. {
diff --git a/lexer/theme-parser.y b/lexer/theme-parser.y
index d66b7cc4..fd290e85 100644
--- a/lexer/theme-parser.y
+++ b/lexer/theme-parser.y
@@ -141,7 +141,7 @@ static ThemeColor hwb_to_rgb ( double h, double w, double b)
WindowLocation wloc;
ThemeColor colorval;
ThemeWidget *theme;
- GList *name_path;
+ GList *list;
Property *property;
GHashTable *property_list;
Distance distance;
@@ -163,6 +163,7 @@ static ThemeColor hwb_to_rgb ( double h, double w, double b)
%token <bval> T_BOOLEAN "Boolean value (true or false)"
%token <colorval> T_COLOR "Hexidecimal color value"
%token <sval> T_LINK "Reference"
+%token <sval> T_ELEMENT "Name of element"
%token T_POS_CENTER "Center"
%token T_POS_EAST "East"
%token T_POS_WEST "West"
@@ -198,6 +199,8 @@ static ThemeColor hwb_to_rgb ( double h, double w, double b)
%token T_OPTIONAL_COMMA "Optional comma separator (',')"
%token T_FORWARD_SLASH "forward slash ('/')"
%token T_PERCENT "Percent sign ('%')"
+%token T_LIST_OPEN "List open ('[')"
+%token T_LIST_CLOSE "List close (']')"
%token T_BOPEN "bracket open ('{')"
%token T_BCLOSE "bracket close ('}')"
@@ -213,7 +216,7 @@ static ThemeColor hwb_to_rgb ( double h, double w, double b)
%type <sval> t_entry
%type <theme> t_entry_list
-%type <name_path> t_entry_name_path
+%type <list> t_entry_name_path
%type <property> t_property
%type <property_list> t_property_list
%type <property_list> t_property_list_optional
@@ -232,6 +235,7 @@ static ThemeColor hwb_to_rgb ( double h, double w, double b)
%type <ival> t_property_highlight_styles
%type <ival> t_property_highlight_style
%type <ival> t_property_line_style
+%type <list> t_property_element_list
%start t_entry_list
%%
@@ -363,6 +367,19 @@ t_property
$$->name = $1;
$$->value.color = $3;
}
+| t_property_name T_PSEP T_LIST_OPEN t_property_element_list T_LIST_CLOSE T_PCLOSE {
+ $$ = rofi_theme_property_create ( P_LIST );
+ $$->name = $1;
+ $$->value.list = $4;
+}
+;
+
+/** List of elements */
+t_property_element_list
+: T_ELEMENT { $$ = g_list_append ( NULL, $1); }
+| t_property_element_list T_COMMA T_ELEMENT {
+ $$ = g_list_append ( $1, $3 );
+}
;
/**
diff --git a/source/theme.c b/source/theme.c
index 468e1a8c..03837d59 100644
--- a/source/theme.c
+++ b/source/theme.c
@@ -591,6 +591,28 @@ Padding rofi_theme_get_padding ( const widget *widget, const char *property, Pad
g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
return pad;
}
+
+GList *rofi_theme_get_list ( const widget *widget, const char * property, const char *defaults )
+{
+ ThemeWidget *wid2 = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
+ Property *p = rofi_theme_find_property ( wid2, P_LIST, property, TRUE);
+ if ( p ) {
+ if ( p->type == P_LIST ){
+ return g_list_copy_deep ( p->value.list, g_strdup, NULL );
+ }
+ }
+ char **r = defaults?g_strsplit (defaults, ",",0):NULL;
+ if ( r ){
+ GList *l = NULL;
+ for ( int i =0; r[i] != NULL; i++){
+ l = g_list_append(l, r[i]);
+ }
+ g_free(r);
+ return l;
+ }
+ return NULL;
+}
+
ThemeHighlight rofi_theme_get_highlight ( widget *widget, const char *property, ThemeHighlight th )
{
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
diff --git a/source/view.c b/source/view.c
index 6c44c289..0e6375b8 100644
--- a/source/view.c
+++ b/source/view.c
@@ -1578,6 +1578,121 @@ static void rofi_view_listview_mouse_activated_cb ( listview *lv, xcb_button_pre
state->skip_absorb = TRUE;
}
+
+static void rofi_view_add_widget ( RofiViewState *state, widget *parent_widget, const char *parent, const char *name )
+{
+ char *defaults = NULL;
+ widget *wid = NULL;
+ char *str= g_strjoin ( "." , parent, name, NULL );
+ char *strbox= g_strjoin ( "." , str, "box",NULL );
+
+ /**
+ * MAINBOX
+ */
+ if ( strcmp ( name, "mainbox") == 0 ){
+ state->main_box = box_create ( strbox, BOX_VERTICAL );
+ container_add ( (container *)parent_widget, WIDGET ( state->main_box ) );
+ wid = WIDGET ( state->main_box );
+ defaults = "inputbar,message,listview";
+ }
+ /**
+ * INPUTBAR
+ */
+ else if ( strcmp ( name, "inputbar" ) == 0 ){
+ state->input_bar = box_create ( strbox, BOX_HORIZONTAL );
+ wid = WIDGET( state->input_bar );
+ defaults = "prompt,entry,case-indicator";
+
+ box_add ( (box *)parent_widget, WIDGET ( state->input_bar ), FALSE, 0 );
+ }
+ /**
+ * PROMPT
+ */
+ else if ( strcmp ( name, "prompt" ) == 0 ){
+ // Prompt box.
+ state->prompt = textbox_create ( str, TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "" );
+ rofi_view_update_prompt ( state );
+ box_add ( (box *)parent_widget, WIDGET ( state->prompt ), FALSE, 1 );
+ defaults = NULL;
+ }
+ /**
+ * CASE INDICATOR
+ */
+ else if ( strcmp ( name, "case-indicator") == 0 ){
+ state->case_indicator = textbox_create ( str, TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "*" );
+ // Add small separator between case indicator and text box.
+ box_add ( (box *)parent_widget, WIDGET ( state->case_indicator ), FALSE, 3 );
+ textbox_text ( state->case_indicator, get_matching_state () );
+ }
+ /**
+ * ENTRY BOX
+ */
+ else if ( strcmp ( name, "entry" ) == 0 ){
+ // Entry box
+ TextboxFlags tfl = TB_EDITABLE;
+ tfl |= ( ( state->menu_flags & MENU_PASSWORD ) == MENU_PASSWORD ) ? TB_PASSWORD : 0;
+ state->text = textbox_create ( str, tfl | TB_AUTOHEIGHT, NORMAL, NULL);
+ box_add ( (box*)parent_widget, WIDGET ( state->text ), TRUE, 2 );
+ }
+ /**
+ * MESSAGE
+ */
+ else if ( strcmp ( name, "message") == 0 ){
+ char *strmsg= g_strjoin ( "." , str, "textbox",NULL );
+ state->mesg_box = container_create ( strbox );
+ state->mesg_tb = textbox_create ( strmsg, TB_AUTOHEIGHT | TB_MARKUP | TB_WRAP, NORMAL, NULL );
+ container_add ( state->mesg_box, WIDGET ( state->mesg_tb ) );
+ rofi_view_reload_message_bar ( state );
+ box_add ( (box*)parent_widget, WIDGET ( state->mesg_box ), FALSE, 2 );
+ g_free(strmsg);
+ }
+ /**
+ * LISTVIEW
+ */
+ else if ( strcmp ( name, "listview" ) == 0 ) {
+ state->list_view = listview_create ( str, update_callback, state, config.element_height, 0);
+ box_add ( (box*)parent_widget, WIDGET ( state->list_view ), TRUE, 3 );
+ // Set configuration
+ listview_set_multi_select ( state->list_view, ( state->menu_flags & MENU_INDICATOR ) == MENU_INDICATOR );
+ listview_set_scroll_type ( state->list_view, config.scroll_method );
+ listview_set_mouse_activated_cb ( state->list_view, rofi_view_listview_mouse_activated_cb, state );
+
+ int lines = rofi_theme_get_integer ( WIDGET ( state->list_view ), "lines", config.menu_lines );
+ listview_set_num_lines ( state->list_view, lines );
+ listview_set_max_lines ( state->list_view, state->num_lines );
+ }
+ /**
+ * SIDEBAR
+ */
+ else if ( strcmp( name, "sidebar" ) == 0 ) {
+ state->sidebar_bar = box_create ( strbox, BOX_HORIZONTAL );
+ box_add ( (box*)parent_widget, WIDGET ( state->sidebar_bar ), FALSE, 10 );
+ state->num_modi = rofi_get_num_enabled_modi ();
+ state->modi = g_malloc0 ( state->num_modi * sizeof ( textbox * ) );
+ char *strbutton= g_strjoin ( "." , str, "button",NULL );
+ for ( unsigned int j = 0; j < state->num_modi; j++ ) {
+ const Mode * mode = rofi_get_mode ( j );
+ state->modi[j] = textbox_create ( strbutton, TB_CENTER | TB_AUTOHEIGHT, ( mode == state->sw ) ? HIGHLIGHT : NORMAL,
+ mode_get_display_name ( mode ) );
+ box_add ( state->sidebar_bar, WIDGET ( state->modi[j] ), TRUE, j );
+ widget_set_clicked_handler ( WIDGET ( state->modi[j] ), rofi_view_modi_clicked_cb, state );
+ }
+ g_free(strbutton);
+ }
+ else {
+ g_error("The widget %s does not exists. Invalid layout.", name);
+ }
+ if ( wid ) {
+ GList *list = rofi_theme_get_list ( wid, "children",defaults);
+ for ( const GList *iter = list; iter != NULL; iter = g_list_next ( iter )){
+ rofi_view_add_widget ( state, wid, str, (const char *)iter->data );
+ }
+ g_list_free_full ( list, g_free );
+ }
+ g_free(strbox);
+ g_free(str);
+}
+
RofiViewState *rofi_view_create ( Mode *sw,
const char *input,
MenuFlags menu_flags,
@@ -1605,77 +1720,24 @@ RofiViewState *rofi_view_create ( Mode *sw,
// Get active monitor size.
TICK_N ( "Get active monitor" );
- state->main_window = container_create ( "window.box" );
- state->main_box = box_create ( "window.mainbox.box", BOX_VERTICAL );
- container_add ( state->main_window, WIDGET ( state->main_box ) );
- state->input_bar = box_create ( "window.mainbox.inputbar.box", BOX_HORIZONTAL );
+ state->main_window = container_create ( "window.box" );
+ // Get children.
+ GList *list = rofi_theme_get_list ( WIDGET(state->main_window), "children", "mainbox");
+ for ( const GList *iter = list; iter != NULL; iter = g_list_next ( iter )){
+ rofi_view_add_widget ( state, WIDGET(state->main_window), "window", (const char *)iter->data );
- // Only enable widget when sidebar is enabled.
- if ( config.sidebar_mode ) {
- state->sidebar_bar = box_create ( "window.mainbox.sidebar.box", BOX_HORIZONTAL );
- box_add ( state->main_box, WIDGET ( state->sidebar_bar ), FALSE, 10 );
- state->num_modi = rofi_get_num_enabled_modi ();
- state->modi = g_malloc0 ( state->num_modi * sizeof ( textbox * ) );
- for ( unsigned int j = 0; j < state->num_modi; j++ ) {
- const Mode * mode = rofi_get_mode ( j );
- state->modi[j] = textbox_create ( "window.mainbox.sidebar.button", TB_CENTER | TB_AUTOHEIGHT, ( mode == state->sw ) ? HIGHLIGHT : NORMAL,
- mode_get_display_name ( mode ) );
- box_add ( state->sidebar_bar, WIDGET ( state->modi[j] ), TRUE, j );
- widget_set_clicked_handler ( WIDGET ( state->modi[j] ), rofi_view_modi_clicked_cb, state );
- }
}
+ g_list_free_full ( list, g_free );
- int location = rofi_theme_get_position ( WIDGET ( state->main_window ), "location", config.location );
- int end = ( location == WL_SOUTH_EAST || location == WL_SOUTH || location == WL_SOUTH_WEST );
- box_add ( state->main_box, WIDGET ( state->input_bar ), FALSE, end ? 9 : 0 );
-
- state->case_indicator = textbox_create ( "window.mainbox.inputbar.case-indicator", TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "*" );
- // Add small separator between case indicator and text box.
- box_add ( state->input_bar, WIDGET ( state->case_indicator ), FALSE, 3 );
-
- // Prompt box.
- state->prompt = textbox_create ( "window.mainbox.inputbar.prompt", TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "" );
- rofi_view_update_prompt ( state );
- box_add ( state->input_bar, WIDGET ( state->prompt ), FALSE, 1 );
-
- // Entry box
- TextboxFlags tfl = TB_EDITABLE;
- tfl |= ( ( menu_flags & MENU_PASSWORD ) == MENU_PASSWORD ) ? TB_PASSWORD : 0;
- state->text = textbox_create ( "window.mainbox.inputbar.entry", tfl | TB_AUTOHEIGHT, NORMAL, input );
-
- box_add ( state->input_bar, WIDGET ( state->text ), TRUE, 2 );
-
- textbox_text ( state->case_indicator, get_matching_state () );
- state->mesg_box = container_create ( "window.mainbox.message.box" );
- state->mesg_tb = textbox_create ( "window.mainbox.message.textbox", TB_AUTOHEIGHT | TB_MARKUP | TB_WRAP, NORMAL, NULL );
- container_add ( state->mesg_box, WIDGET ( state->mesg_tb ) );
- rofi_view_reload_message_bar ( state );
- box_add ( state->main_box, WIDGET ( state->mesg_box ), FALSE, end ? 8 : 2 );
+ if ( state->text && input) {
+ textbox_text ( state->text, input );
+ }
state->overlay = textbox_create ( "window.overlay", TB_AUTOWIDTH | TB_AUTOHEIGHT, URGENT, "blaat" );
state->overlay->widget.parent = WIDGET ( state->main_window );
widget_disable ( WIDGET ( state->overlay ) );
- state->list_view = listview_create ( "window.mainbox.listview", update_callback, state, config.element_height, end );
- // Set configuration
- listview_set_multi_select ( state->list_view, ( state->menu_flags & MENU_INDICATOR ) == MENU_INDICATOR );
- listview_set_scroll_type ( state->list_view, config.scroll_method );
- listview_set_mouse_activated_cb ( state->list_view, rofi_view_listview_mouse_activated_cb, state );
-
- int lines = rofi_theme_get_integer ( WIDGET ( state->list_view ), "lines", config.menu_lines );
- listview_set_num_lines ( state->list_view, lines );
- listview_set_max_lines ( state->list_view, state->num_lines );
-
- if ( rofi_theme_get_boolean ( WIDGET ( state->main_window ), "listview-in-inputbar", FALSE)){
- box_add ( state->input_bar, WIDGET ( state->list_view ), TRUE, 3 );
-
- Distance d = rofi_theme_get_distance_exact ( WIDGET ( state->text ) , "width", 150);
- state->text->widget.expand = FALSE;
- widget_resize ( WIDGET( state->text ), distance_get_pixel ( d, ORIENTATION_HORIZONTAL ), -1);
- } else {
- box_add ( state->main_box, WIDGET ( state->list_view ), TRUE, 3 );
- }
// filtered list
state->line_map = g_malloc0_n ( state->num_lines, sizeof ( unsigned int ) );
diff --git a/source/widgets/box.c b/source/widgets/box.c
index faeba226..409fa0b1 100644
--- a/source/widgets/box.c
+++ b/source/widgets/box.c
@@ -263,7 +263,7 @@ void box_add ( box *box, widget *child, gboolean expand, int index )
child->index = rofi_theme_get_integer_exact ( child, "index", index );
child->parent = WIDGET ( box );
box->children = g_list_append ( box->children, (void *) child );
- box->children = g_list_sort ( box->children, box_sort_children );
+ //box->children = g_list_sort ( box->children, box_sort_children );
widget_update ( WIDGET ( box ) );
}