diff options
author | Dave Davenport <DaveDavenport@users.noreply.github.com> | 2019-08-08 20:02:20 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-08-08 20:02:20 +0200 |
commit | 618d1396eefea6ea26d954e44015c1fa422801f3 (patch) | |
tree | bd52799b1024ef97edcbbef6153108a1f44a95af | |
parent | d9eb9f25a16b3e95cfc32c3c1076caae58c0ceb1 (diff) |
Issue949 (#999)
* [Issue 949] Add initial split of listview row into widget tree.
Allowing better themeing.
* Remove unneeded code from textbox. allow dis. icons.
* Fix typo.
* Fix wrong widget offset in textbox.
* Fix mouse handling
* [ListView] Add 'fixed-columns' boolean option.
* [Listview] Fix inversion of option.
* [ListView] remove commented old code.
* [Textbox] Handle null pointer on desired width.
* [Listview] Fix crasher with fixed_columns and more max elements requested items.
* Add hack to get backwards compatibility for new listview structure.
* Fix the scrollbar test.
* Fix tests for theme update..
-rw-r--r-- | doc/default_theme.rasi | 95 | ||||
-rw-r--r-- | doc/old-theme-convert-output.rasi | 97 | ||||
-rw-r--r-- | include/view-internal.h | 2 | ||||
-rw-r--r-- | include/widgets/listview.h | 2 | ||||
-rw-r--r-- | include/widgets/textbox.h | 21 | ||||
-rw-r--r-- | include/widgets/widget.h | 9 | ||||
-rw-r--r-- | source/theme.c | 43 | ||||
-rw-r--r-- | source/view.c | 21 | ||||
-rw-r--r-- | source/widgets/box.c | 4 | ||||
-rw-r--r-- | source/widgets/listview.c | 144 | ||||
-rw-r--r-- | source/widgets/scrollbar.c | 1 | ||||
-rw-r--r-- | source/widgets/textbox.c | 50 | ||||
-rw-r--r-- | source/widgets/widget.c | 7 | ||||
-rw-r--r-- | test/scrollbar-test.c | 1 | ||||
-rw-r--r-- | test/theme-parser-test.c | 22 |
15 files changed, 299 insertions, 220 deletions
diff --git a/doc/default_theme.rasi b/doc/default_theme.rasi index 4a1a382c..0b6940ab 100644 --- a/doc/default_theme.rasi +++ b/doc/default_theme.rasi @@ -2,63 +2,39 @@ * rofi -dump-theme output. **/ * { - selected-normal-foreground: var(lightbg); - foreground: rgba ( 0, 43, 54, 100 % ); - normal-foreground: var(foreground); - alternate-normal-background: var(lightbg); red: rgba ( 220, 50, 47, 100 % ); - selected-urgent-foreground: var(background); - blue: rgba ( 38, 139, 210, 100 % ); + selected-active-foreground: var(background); + lightfg: rgba ( 88, 104, 117, 100 % ); + separatorcolor: var(foreground); urgent-foreground: var(red); alternate-urgent-background: var(lightbg); - active-foreground: var(blue); lightbg: rgba ( 238, 232, 213, 100 % ); - selected-active-foreground: var(background); - alternate-active-background: var(lightbg); - background: rgba ( 253, 246, 227, 100 % ); - alternate-normal-foreground: var(foreground); - normal-background: var(background); - lightfg: rgba ( 88, 104, 117, 100 % ); - selected-normal-background: var(lightfg); + background-color: rgba ( 0, 0, 0, 0 % ); border-color: var(foreground); + normal-background: var(background); + selected-urgent-background: var(red); + alternate-active-background: var(lightbg); spacing: 2; - separatorcolor: var(foreground); + blue: rgba ( 38, 139, 210, 100 % ); + alternate-normal-foreground: var(foreground); urgent-background: var(background); - selected-urgent-background: var(red); + selected-normal-foreground: var(lightbg); + active-foreground: var(blue); + background: rgba ( 253, 246, 227, 100 % ); + selected-active-background: var(blue); + active-background: var(background); + selected-normal-background: var(lightfg); + alternate-normal-background: var(lightbg); + foreground: rgba ( 0, 43, 54, 100 % ); + selected-urgent-foreground: var(background); + normal-foreground: var(foreground); alternate-urgent-foreground: var(red); - background-color: rgba ( 0, 0, 0, 0 % ); alternate-active-foreground: var(blue); - active-background: var(background); - selected-active-background: var(blue); -} -window { - background-color: var(background); - border: 1; - padding: 5; -} -mainbox { - border: 0; - padding: 0; -} -message { - border: 2px dash 0px 0px ; - border-color: var(separatorcolor); - padding: 1px ; -} -textbox { - text-color: var(foreground); -} -listview { - fixed-height: 0; - border: 2px dash 0px 0px ; - border-color: var(separatorcolor); - spacing: 2px ; - scrollbar: true; - padding: 2px 0px 0px ; } element { - border: 0; padding: 1px ; + spacing: 5px ; + border: 0; } element normal.normal { background-color: var(normal-background); @@ -96,16 +72,24 @@ element alternate.active { background-color: var(alternate-active-background); text-color: var(alternate-active-foreground); } +element-text { + background-color: rgba ( 0, 0, 0, 0 % ); + text-color: inherit; +} +element-icon { + background-color: rgba ( 0, 0, 0, 0 % ); + text-color: inherit; +} scrollbar { width: 4px ; + padding: 0; + handle-width: 8px ; border: 0; handle-color: var(normal-foreground); - handle-width: 8px ; - padding: 0; } mode-switcher { - border: 2px dash 0px 0px ; border-color: var(separatorcolor); + border: 2px dash 0px 0px ; } button { spacing: 0; @@ -116,9 +100,9 @@ button selected { text-color: var(selected-normal-foreground); } inputbar { + padding: 1px ; spacing: 0px ; text-color: var(normal-foreground); - padding: 1px ; children: [ prompt,textbox-prompt-colon,entry,overlay,case-indicator ]; } case-indicator { @@ -134,12 +118,23 @@ prompt { text-color: var(normal-foreground); } textbox-prompt-colon { + margin: 0px 0.3000em 0.0000em 0.0000em ; expand: false; str: ":"; - margin: 0px 0.3000em 0.0000em 0.0000em ; text-color: inherit; } error-message { background-color: rgba ( 0, 0, 0, 0 % ); text-color: var(normal-foreground); } +window { + padding: 5; + border: 1; +} +listview { + scrollbar: true; + spacing: 2px ; +} +message { + padding: 1px ; +} diff --git a/doc/old-theme-convert-output.rasi b/doc/old-theme-convert-output.rasi index 169f07e4..60ad5dd7 100644 --- a/doc/old-theme-convert-output.rasi +++ b/doc/old-theme-convert-output.rasi @@ -2,63 +2,39 @@ * rofi -dump-theme output. **/ * { - selected-normal-foreground: rgba ( 2, 20, 63, 100 % ); - foreground: rgba ( 219, 223, 188, 100 % ); - normal-foreground: var(foreground); - alternate-normal-background: rgba ( 0, 0, 0, 0 % ); red: rgba ( 220, 50, 47, 100 % ); - selected-urgent-foreground: rgba ( 2, 20, 63, 100 % ); - blue: rgba ( 38, 139, 210, 100 % ); + selected-active-foreground: rgba ( 2, 20, 63, 100 % ); + lightfg: rgba ( 88, 104, 117, 100 % ); + separatorcolor: rgba ( 219, 223, 188, 100 % ); urgent-foreground: rgba ( 255, 129, 255, 100 % ); alternate-urgent-background: rgba ( 0, 0, 0, 0 % ); - active-foreground: rgba ( 138, 196, 255, 100 % ); lightbg: rgba ( 238, 232, 213, 100 % ); - selected-active-foreground: rgba ( 2, 20, 63, 100 % ); - alternate-active-background: rgba ( 0, 0, 0, 0 % ); - background: rgba ( 0, 0, 33, 87 % ); - alternate-normal-foreground: var(foreground); - normal-background: rgba ( 0, 0, 0, 0 % ); - lightfg: rgba ( 88, 104, 117, 100 % ); - selected-normal-background: rgba ( 219, 223, 188, 100 % ); + background-color: rgba ( 0, 0, 0, 0 % ); border-color: rgba ( 219, 223, 188, 100 % ); + normal-background: rgba ( 0, 0, 0, 0 % ); + selected-urgent-background: rgba ( 255, 129, 127, 100 % ); + alternate-active-background: rgba ( 0, 0, 0, 0 % ); spacing: 2; - separatorcolor: rgba ( 219, 223, 188, 100 % ); + blue: rgba ( 38, 139, 210, 100 % ); + alternate-normal-foreground: var(foreground); urgent-background: rgba ( 0, 0, 0, 0 % ); - selected-urgent-background: rgba ( 255, 129, 127, 100 % ); + selected-normal-foreground: rgba ( 2, 20, 63, 100 % ); + active-foreground: rgba ( 138, 196, 255, 100 % ); + background: rgba ( 0, 0, 33, 87 % ); + selected-active-background: rgba ( 138, 196, 255, 100 % ); + active-background: rgba ( 0, 0, 0, 0 % ); + selected-normal-background: rgba ( 219, 223, 188, 100 % ); + alternate-normal-background: rgba ( 0, 0, 0, 0 % ); + foreground: rgba ( 219, 223, 188, 100 % ); + selected-urgent-foreground: rgba ( 2, 20, 63, 100 % ); + normal-foreground: var(foreground); alternate-urgent-foreground: var(urgent-foreground); - background-color: rgba ( 0, 0, 0, 0 % ); alternate-active-foreground: var(active-foreground); - active-background: rgba ( 0, 0, 0, 0 % ); - selected-active-background: rgba ( 138, 196, 255, 100 % ); -} -window { - background-color: var(background); - border: 1; - padding: 5; -} -mainbox { - border: 0; - padding: 0; -} -message { - border: 2px 0px 0px ; - border-color: var(separatorcolor); - padding: 1px ; -} -textbox { - text-color: var(foreground); -} -listview { - fixed-height: 0; - border: 2px 0px 0px ; - border-color: var(separatorcolor); - spacing: 2px ; - scrollbar: true; - padding: 2px 0px 0px ; } element { - border: 0; padding: 1px ; + spacing: 5px ; + border: 0; } element normal.normal { background-color: var(normal-background); @@ -96,16 +72,24 @@ element alternate.active { background-color: var(alternate-active-background); text-color: var(alternate-active-foreground); } +element-text { + background-color: rgba ( 0, 0, 0, 0 % ); + text-color: inherit; +} +element-icon { + background-color: rgba ( 0, 0, 0, 0 % ); + text-color: inherit; +} scrollbar { width: 4px ; + padding: 0; + handle-width: 8px ; border: 0; handle-color: var(normal-foreground); - handle-width: 8px ; - padding: 0; } mode-switcher { - border: 2px 0px 0px ; border-color: var(separatorcolor); + border: 2px 0px 0px ; } button { spacing: 0; @@ -116,9 +100,9 @@ button selected { text-color: var(selected-normal-foreground); } inputbar { + padding: 1px ; spacing: 0px ; text-color: var(normal-foreground); - padding: 1px ; children: [ prompt,textbox-prompt-colon,entry,overlay,case-indicator ]; } case-indicator { @@ -134,12 +118,25 @@ prompt { text-color: var(normal-foreground); } textbox-prompt-colon { + margin: 0px 0.3000em 0.0000em 0.0000em ; expand: false; str: ":"; - margin: 0px 0.3000em 0.0000em 0.0000em ; text-color: inherit; } error-message { background-color: rgba ( 0, 0, 0, 0 % ); text-color: var(normal-foreground); } +window { + padding: 5; + border: 1; +} +listview { + scrollbar: true; + spacing: 2px ; + border: 2px 0px 0px ; +} +message { + padding: 1px ; + border: 2px 0px 0px ; +} diff --git a/include/view-internal.h b/include/view-internal.h index a00bd147..7ebee79d 100644 --- a/include/view-internal.h +++ b/include/view-internal.h @@ -30,9 +30,9 @@ #include "widgets/container.h" #include "widgets/widget.h" #include "widgets/textbox.h" -#include "widgets/listview.h" #include "widgets/box.h" #include "widgets/icon.h" +#include "widgets/listview.h" #include "keyb.h" #include "xcb.h" #include "theme.h" diff --git a/include/widgets/listview.h b/include/widgets/listview.h index ec5861e1..c10e1831 100644 --- a/include/widgets/listview.h +++ b/include/widgets/listview.h @@ -61,7 +61,7 @@ typedef enum * * Update callback, this is called to set the value of each (visible) element. */ -typedef void ( *listview_update_callback )( textbox *tb, unsigned int entry, void *udata, TextBoxFontType type, gboolean full ); +typedef void ( *listview_update_callback )( textbox *tb,icon *ico, unsigned int entry, void *udata, TextBoxFontType *type, gboolean full ); /** * Callback when a element is activated. diff --git a/include/widgets/textbox.h b/include/widgets/textbox.h index 6d666ff0..83831bfe 100644 --- a/include/widgets/textbox.h +++ b/include/widgets/textbox.h @@ -58,9 +58,6 @@ typedef struct int markup; int changed; - cairo_surface_t *icon; // AA TODO - pass in icons for a textbox line if needed - int icon_index; - int blink; guint blink_timeout; @@ -69,7 +66,6 @@ typedef struct PangoFontMetrics *metrics; PangoEllipsizeMode emode; - int left_offset; // const char *theme_name; } textbox; @@ -86,7 +82,6 @@ typedef enum TB_WRAP = 1 << 21, TB_PASSWORD = 1 << 22, TB_INDICATOR = 1 << 23, - TB_ICON = 1 << 24, } TextboxFlags; /** * Flags indicating current state of the textbox. @@ -148,14 +143,6 @@ void textbox_font ( textbox *tb, TextBoxFontType tbft ); void textbox_text ( textbox *tb, const char *text ); /** - * @param tb Handle to the textbox - * @param icon The icon to show on the textbox - * - * Set the text to show. Cursor is moved to end (if visible) - */ -void textbox_icon ( textbox *tb, cairo_surface_t *icon ); - -/** * @param tb Handle to the textbox * @param action the #KeyBindingAction to execute on textbox * @@ -299,14 +286,6 @@ void textbox_set_pango_attributes ( textbox *tb, PangoAttrList *list ); /** * @param tb Handle to the textbox - * @param index character index to draw the icon at. -1 for no icon - * - * Sets the character index where the icon should be drawn - */ -void textbox_set_icon_index ( textbox *tb, int index ); - -/** - * @param tb Handle to the textbox * * Get the list of currently active pango attributes. * diff --git a/include/widgets/widget.h b/include/widgets/widget.h index 9370a49b..abe0c4f6 100644 --- a/include/widgets/widget.h +++ b/include/widgets/widget.h @@ -142,6 +142,15 @@ void widget_move ( widget *widget, short x, short y ); */ WidgetType widget_type ( widget *widget ); + +/** + * @param widget Handle to widget + * @param type The widget type. + * + * Set the widget type. + */ +void widget_set_type ( widget *widget, WidgetType type ); + /** * @param widget Handle to widget * diff --git a/source/theme.c b/source/theme.c index bf91879f..b031a8a8 100644 --- a/source/theme.c +++ b/source/theme.c @@ -124,11 +124,54 @@ void rofi_theme_property_free ( Property *p ) g_slice_free ( Property, p ); } +/** + * This function is a hack to insert backward support for older theme with the updated listvie structure. + */ +static void rofi_theme_insert_listview_backwards_fix ( void ) +{ + GHashTable *table= g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, (GDestroyNotify) rofi_theme_property_free ); + ThemeWidget *t = rofi_theme_find_or_create_name ( rofi_theme, "element" ); + ThemeWidget *tt = rofi_theme_find_or_create_name ( rofi_theme, "element-text" ); + ThemeWidget *ti = rofi_theme_find_or_create_name ( rofi_theme, "element-icon" ); + + // Inherit text color + Property *ptc = rofi_theme_property_create ( P_INHERIT ); + ptc->name = g_strdup("text-color"); + g_hash_table_replace ( table, ptc->name, ptc ); + // Transparent background + Property *ptb = rofi_theme_property_create ( P_COLOR ); + ptb->name = g_strdup("background-color"); + ptb->value.color.red = 0.0; + ptb->value.color.green = 0.0; + ptb->value.color.blue = 0.0; + ptb->value.color.alpha = 0.0; + g_hash_table_replace ( table, ptb->name, ptb ); + + + rofi_theme_widget_add_properties ( tt, table); + rofi_theme_widget_add_properties ( ti, table); + + /** Add spacing between icon and text. */ + g_hash_table_destroy ( table ); + 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 }; + psp->value.padding = (RofiPadding){d,d,d,d}; + g_hash_table_replace ( table, psp->name, psp ); + rofi_theme_widget_add_properties ( t, table); + g_hash_table_destroy ( table ); + + +} + void rofi_theme_reset ( void ) { rofi_theme_free ( rofi_theme ); rofi_theme = g_slice_new0 ( ThemeWidget ); rofi_theme->name = g_strdup ( "Root" ); + // Hack to fix backwards compatibility. + rofi_theme_insert_listview_backwards_fix ( ); } void rofi_theme_free ( ThemeWidget *widget ) diff --git a/source/view.c b/source/view.c index e9b4d8d8..2f6ce5f0 100644 --- a/source/view.c +++ b/source/view.c @@ -928,15 +928,16 @@ inline static void rofi_view_nav_last ( RofiViewState * state ) listview_set_selected ( state->list_view, -1 ); } -static void update_callback ( textbox *t, unsigned int index, void *udata, TextBoxFontType type, gboolean full ) +static void update_callback ( textbox *t,icon *ico, unsigned int index, void *udata, TextBoxFontType *type, gboolean full ) { RofiViewState *state = (RofiViewState *) udata; if ( full ) { GList *add_list = NULL; int fstate = 0; char *text = mode_get_display_value ( state->sw, state->line_map[index], &fstate, &add_list, TRUE ); - type |= fstate; - textbox_font ( t, type ); + (*type) |= fstate; + // TODO needed for markup. + textbox_font ( t, *type ); // Move into list view. textbox_text ( t, text ); PangoAttrList *list = textbox_get_pango_attributes ( t ); @@ -946,10 +947,11 @@ static void update_callback ( textbox *t, unsigned int index, void *udata, TextB else{ list = pango_attr_list_new (); } - int icon_height = textbox_get_font_height ( t ); - - cairo_surface_t *icon = mode_get_icon ( state->sw, state->line_map[index], icon_height ); - textbox_icon ( t, icon ); + if( ico ) { + int icon_height = widget_get_desired_height( WIDGET(ico) ); + cairo_surface_t *icon = mode_get_icon ( state->sw, state->line_map[index], icon_height ); + icon_set_surface ( ico, icon ); + } if ( state->tokens && config.show_match ) { RofiHighlightColorStyle th = { ROFI_HL_BOLD | ROFI_HL_UNDERLINE, { 0.0, 0.0, 0.0, 0.0 } }; @@ -967,8 +969,9 @@ static void update_callback ( textbox *t, unsigned int index, void *udata, TextB else { int fstate = 0; mode_get_display_value ( state->sw, state->line_map[index], &fstate, NULL, FALSE ); - type |= fstate; - textbox_font ( t, type ); + (*type) |= fstate; + // TODO needed for markup. + textbox_font ( t, *type ); } } diff --git a/source/widgets/box.c b/source/widgets/box.c index 11733a6f..874760c6 100644 --- a/source/widgets/box.c +++ b/source/widgets/box.c @@ -107,10 +107,6 @@ static int box_get_desired_height ( widget *wid ) continue; } active_widgets++; - if ( child->expand == TRUE ) { - height += widget_get_desired_height ( child ); - continue; - } height += widget_get_desired_height ( child ); } if ( active_widgets > 0 ) { diff --git a/source/widgets/listview.c b/source/widgets/listview.c index cb7f0628..79367cdb 100644 --- a/source/widgets/listview.c +++ b/source/widgets/listview.c @@ -29,8 +29,10 @@ #include <glib.h> #include <widgets/widget.h> #include <widgets/textbox.h> -#include <widgets/listview.h> #include <widgets/scrollbar.h> +#include <widgets/icon.h> +#include <widgets/box.h> +#include <widgets/listview.h> #include "settings.h" #include "theme.h" @@ -58,6 +60,12 @@ typedef enum RIGHT_TO_LEFT = 1 } MoveDirection; +typedef struct { + box *box; + textbox *textbox; + icon *icon; +} _listview_row; + struct _listview { widget widget; @@ -78,6 +86,7 @@ struct _listview unsigned int max_elements; // + gboolean fixed_columns; unsigned int cur_columns; unsigned int req_elements; unsigned int cur_elements; @@ -95,7 +104,7 @@ struct _listview ScrollType scroll_type; - textbox **boxes; + _listview_row * boxes; scrollbar *scrollbar; listview_update_callback callback; @@ -119,13 +128,79 @@ struct _listview } barview; }; +const char *const listview_theme_prop_names[][3] = { + /** Normal row */ + { "normal.normal", "selected.normal", "alternate.normal" }, + /** Urgent row */ + { "normal.urgent", "selected.urgent", "alternate.urgent" }, + /** Active row */ + { "normal.active", "selected.active", "alternate.active" }, +}; + +static void listview_set_style ( widget *w, TextBoxFontType tbft ) +{ + TextBoxFontType t = tbft & STATE_MASK; + if ( w == NULL ) { + return; + } + // ACTIVE has priority over URGENT if both set. + if ( t == ( URGENT | ACTIVE ) ) { + t = ACTIVE; + } + switch ( ( tbft & FMOD_MASK ) ) + { + case HIGHLIGHT: + widget_set_state ( w, listview_theme_prop_names[t][1] ); + break; + case ALT: + widget_set_state ( w, listview_theme_prop_names[t][2] ); + break; + default: + widget_set_state ( w, listview_theme_prop_names[t][0] ); + break; + } +} +static void listview_create_row ( listview *lv, _listview_row *row ) +{ + TextboxFlags flags = ( lv->multi_select ) ? TB_INDICATOR : 0; + row->box = box_create ( WIDGET ( lv ), "element",ROFI_ORIENTATION_HORIZONTAL ); + widget_set_type ( WIDGET(row->box), WIDGET_TYPE_LISTVIEW_ELEMENT); + GList *list = rofi_theme_get_list ( WIDGET(row->box), "children", "element-icon,element-text"); + + row->textbox = NULL; + row->icon = NULL; + + for ( GList *iter = g_list_first(list); iter != NULL;iter = g_list_next(iter)){ + if ( strcasecmp((char *)iter->data, "element-icon") == 0 ) { + if ( config.show_icons ) { + row->icon = icon_create ( WIDGET ( row->box ), "element-icon" ); + box_add ( row->box, WIDGET ( row->icon ), FALSE); + } + } else if ( strcasecmp ((char *)iter->data, "element-text") == 0 ){ + row->textbox= textbox_create ( WIDGET ( row->box ), WIDGET_TYPE_TEXTBOX_TEXT, "element-text", TB_AUTOHEIGHT|flags, NORMAL, "DDD", 0, 0 ); + box_add ( row->box, WIDGET ( row->textbox ), TRUE); + } + } + g_list_free_full ( list, g_free ); +} + + +static void listview_set_state ( _listview_row r, TextBoxFontType type ) +{ + listview_set_style ( WIDGET(r.box), type); + listview_set_style ( WIDGET(r.textbox), type); + if ( r.icon ) { + listview_set_style ( WIDGET(r.icon), type); + } + widget_queue_redraw ( WIDGET( r.box ) ); +} static int listview_get_desired_height ( widget *wid ); static void listview_free ( widget *wid ) { listview *lv = (listview *) wid; for ( unsigned int i = 0; i < lv->cur_elements; i++ ) { - widget_free ( WIDGET ( lv->boxes [i] ) ); + widget_free ( WIDGET ( lv->boxes [i].box ) ); } g_free ( lv->boxes ); @@ -200,7 +275,8 @@ static void update_element ( listview *lv, unsigned int tb, unsigned int index, type = ( index ) == lv->selected ? HIGHLIGHT : type; if ( lv->callback ) { - lv->callback ( lv->boxes[tb], index, lv->udata, type, full ); + lv->callback ( lv->boxes[tb].textbox, lv->boxes[tb].icon, index, lv->udata, &type, full ); + listview_set_state ( lv->boxes[tb], type); } } @@ -226,16 +302,17 @@ static void barview_draw ( widget *wid, cairo_t *draw ) if ( lv->barview.direction == LEFT_TO_RIGHT ) { for ( unsigned int i = 0; i < max && width > 0; i++ ) { update_element ( lv, i, i + offset, TRUE ); - int twidth = textbox_get_desired_width ( WIDGET ( lv->boxes[i] ) ); + int twidth = textbox_get_desired_width ( WIDGET ( lv->boxes[i].textbox ) ); if ( twidth >= width ) { if ( !first ) { break; } twidth = width; } - textbox_moveresize ( lv->boxes[i], left_offset, top_offset, twidth, lv->element_height ); + widget_move ( WIDGET(lv->boxes[i].box), left_offset, top_offset); + widget_resize ( WIDGET (lv->boxes[i].box), twidth, lv->element_height); - widget_draw ( WIDGET ( lv->boxes[i] ), draw ); + widget_draw ( WIDGET ( lv->boxes[i].box ), draw ); width -= twidth + spacing_hori; left_offset += twidth + spacing_hori; first = FALSE; @@ -245,7 +322,7 @@ static void barview_draw ( widget *wid, cairo_t *draw ) else { for ( unsigned int i = 0; i < lv->cur_elements && width > 0 && i <= offset; i++ ) { update_element ( lv, i, offset - i, TRUE ); - int twidth = textbox_get_desired_width ( WIDGET ( lv->boxes[i] ) ); + int twidth = textbox_get_desired_width ( WIDGET ( lv->boxes[i].textbox ) ); if ( twidth >= width ) { if ( !first ) { break; @@ -253,9 +330,10 @@ static void barview_draw ( widget *wid, cairo_t *draw ) twidth = width; } right_offset -= twidth; - textbox_moveresize ( lv->boxes[i], right_offset, top_offset, twidth, lv->element_height ); + widget_move ( WIDGET(lv->boxes[i].box), left_offset, top_offset); + widget_resize ( WIDGET (lv->boxes[i].box), twidth, lv->element_height); - widget_draw ( WIDGET ( lv->boxes[i] ), draw ); + widget_draw ( WIDGET ( lv->boxes[i].box ), draw ); width -= twidth + spacing_hori; right_offset -= spacing_hori; first = FALSE; @@ -264,7 +342,7 @@ static void barview_draw ( widget *wid, cairo_t *draw ) offset -= lv->barview.cur_visible - 1; lv->last_offset = offset; for ( unsigned int i = 0; i < ( lv->barview.cur_visible / 2 ); i++ ) { - void * temp = lv->boxes[i]; + _listview_row temp = lv->boxes[i]; int sw = lv->barview.cur_visible - i - 1; lv->boxes[i] = lv->boxes[sw]; lv->boxes[sw] = temp; @@ -275,7 +353,7 @@ static void barview_draw ( widget *wid, cairo_t *draw ) else { for ( unsigned int i = 0; i < lv->barview.cur_visible; i++ ) { update_element ( lv, i, i + offset, FALSE ); - widget_draw ( WIDGET ( lv->boxes[i] ), draw ); + widget_draw ( WIDGET ( lv->boxes[i].box ), draw ); } } } @@ -326,22 +404,24 @@ static void listview_draw ( widget *wid, cairo_t *draw ) unsigned int ex = left_offset + ( ( i ) / lv->max_rows ) * ( element_width + spacing_hori ); if ( lv->reverse ) { unsigned int ey = wid->h - ( widget_padding_get_bottom ( wid ) + ( ( i ) % lv->max_rows ) * ( lv->element_height + spacing_vert ) ) - lv->element_height; - textbox_moveresize ( lv->boxes[i], ex, ey, element_width, lv->element_height ); + widget_move ( WIDGET(lv->boxes[i].box), ex, ey); + widget_resize ( WIDGET (lv->boxes[i].box), element_width, lv->element_height); } else { unsigned int ey = top_offset + ( ( i ) % lv->max_rows ) * ( lv->element_height + spacing_vert ); - textbox_moveresize ( lv->boxes[i], ex, ey, element_width, lv->element_height ); + widget_move ( WIDGET(lv->boxes[i].box), ex, ey); + widget_resize ( WIDGET (lv->boxes[i].box), element_width, lv->element_height); } update_element ( lv, i, i + offset, TRUE ); - widget_draw ( WIDGET ( lv->boxes[i] ), draw ); + widget_draw ( WIDGET ( lv->boxes[i].box ), draw ); } lv->rchanged = FALSE; } else { for ( unsigned int i = 0; i < max; i++ ) { update_element ( lv, i, i + offset, FALSE ); - widget_draw ( WIDGET ( lv->boxes[i] ), draw ); + widget_draw ( WIDGET ( lv->boxes[i].box ), draw ); } } } @@ -359,30 +439,32 @@ static void _listview_draw ( widget *wid, cairo_t *draw ) barview_draw ( wid, draw ); } } +/** + * State names used for theming. + */ static void listview_recompute_elements ( listview *lv ) { unsigned int newne = 0; if ( lv->max_rows == 0 ) { return; } - if ( lv->req_elements < lv->max_elements ) { + if ( !(lv->fixed_columns) && lv->req_elements < lv->max_elements ) { newne = lv->req_elements; lv->cur_columns = ( lv->req_elements + ( lv->max_rows - 1 ) ) / lv->max_rows; } else { - newne = lv->max_elements; + newne = MIN( lv->req_elements, lv->max_elements); lv->cur_columns = lv->menu_columns; } for ( unsigned int i = newne; i < lv->cur_elements; i++ ) { - widget_free ( WIDGET ( lv->boxes[i] ) ); + widget_free ( WIDGET ( lv->boxes[i].box ) ); } - lv->boxes = g_realloc ( lv->boxes, newne * sizeof ( textbox* ) ); + lv->boxes = g_realloc ( lv->boxes, newne * sizeof ( _listview_row ) ); if ( newne > 0 ) { for ( unsigned int i = lv->cur_elements; i < newne; i++ ) { - TextboxFlags flags = ( lv->multi_select ) ? TB_INDICATOR : 0; - flags |= ( ( config.show_icons ) ? TB_ICON : 0 ); - lv->boxes[i] = textbox_create ( WIDGET ( lv ), WIDGET_TYPE_LISTVIEW_ELEMENT, "element", flags, NORMAL, "", 0, 0 ); - widget_set_trigger_action_handler ( WIDGET ( lv->boxes[i] ), listview_element_trigger_action, lv ); + listview_create_row ( lv, &(lv->boxes[i]) ); + widget_set_trigger_action_handler ( WIDGET ( lv->boxes[i].box ), listview_element_trigger_action, lv ); + listview_set_state ( lv->boxes[i], NORMAL); } } lv->rchanged = TRUE; @@ -461,7 +543,7 @@ static widget *listview_find_mouse_target ( widget *wid, WidgetType type, gint x unsigned int max = MIN ( lv->cur_elements, lv->req_elements - lv->last_offset ); unsigned int i; for ( i = 0; i < max && target == NULL; i++ ) { - widget *w = WIDGET ( lv->boxes[i] |