diff --git a/Makefile.am b/Makefile.am index 667e6273..75a6270a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -223,6 +223,7 @@ theme_DATA=\ themes/paper-float.rasi\ themes/purple.rasi\ themes/sidebar.rasi\ + themes/sidebar-v2.rasi\ themes/solarized.rasi\ themes/solarized_alternate.rasi\ themes/fancy.rasi\ diff --git a/doc/rofi-theme.5 b/doc/rofi-theme.5 index 78a3dd02..360a74dd 100644 --- a/doc/rofi-theme.5 +++ b/doc/rofi-theme.5 @@ -1244,6 +1244,8 @@ The current widgets available in \fBrofi\fP: \fB\fCnum-rows\fR: Shows the total number of rows. .IP \(bu 2 \fB\fCnum-filtered-rows\fR: Shows the total number of rows after filtering. +.IP \(bu 2 +\fB\fCtextbox-current-entry\fR: Shows the text of the currently selected entry. .RE diff --git a/doc/rofi-theme.5.markdown b/doc/rofi-theme.5.markdown index a108a870..48125bf5 100644 --- a/doc/rofi-theme.5.markdown +++ b/doc/rofi-theme.5.markdown @@ -773,6 +773,7 @@ The current widgets available in **rofi**: * `entry`: the main entry @textbox * `num-rows`: Shows the total number of rows. * `num-filtered-rows`: Shows the total number of rows after filtering. + * `textbox-current-entry`: Shows the text of the currently selected entry. * `listview`: The listview. * `scrollbar`: the listview scrollbar * `element`: a box in the listview holding the entries diff --git a/include/view-internal.h b/include/view-internal.h index 44bf2bcb..b942e4e1 100644 --- a/include/view-internal.h +++ b/include/view-internal.h @@ -107,6 +107,8 @@ struct RofiViewState { /** filtered rows */ textbox *tb_filtered_rows; + textbox *tb_current_entry; + /** Settings of the menu */ MenuFlags menu_flags; /** If mouse was within view previously */ diff --git a/include/widgets/listview.h b/include/widgets/listview.h index 3a10436e..a2e95675 100644 --- a/include/widgets/listview.h +++ b/include/widgets/listview.h @@ -67,6 +67,16 @@ typedef void (*listview_update_callback)(textbox *tb, icon *ico, unsigned int entry, void *udata, TextBoxFontType *type, gboolean full); +/** + * @param lv The listview + * @param index the selected row + * @param udata user data + * + * Selection changed callback. + */ +typedef void (*listview_selection_changed_callback)(listview *lv, + unsigned int index, + void *udata); /** * Callback when a element is activated. */ @@ -86,6 +96,12 @@ listview *listview_create(widget *parent, const char *name, listview_update_callback cb, void *udata, unsigned int eh, gboolean reverse); +/** + * Set the selection changed callback. + */ +void listview_set_selection_changed_callback( + listview *lv, listview_selection_changed_callback cb, void *udata); + /** * @param lv The listview handle * @param rows Number of elements @@ -273,7 +289,7 @@ void listview_set_ellipsize_start(listview *lv); * @param filtered boolean indicating if list is filtered. * */ -void listview_set_filtered ( listview *lv, gboolean filtered ); +void listview_set_filtered(listview *lv, gboolean filtered); /** @} */ #endif // ROFI_LISTVIEW_H diff --git a/meson.build b/meson.build index dc7c7b9e..987c021e 100644 --- a/meson.build +++ b/meson.build @@ -277,6 +277,7 @@ install_data( 'themes/paper-float.rasi', 'themes/purple.rasi', 'themes/sidebar.rasi', + 'themes/sidebar-v2.rasi', 'themes/solarized.rasi', 'themes/solarized_alternate.rasi', 'themes/fancy.rasi', diff --git a/source/view.c b/source/view.c index 3d7b03aa..122010b6 100644 --- a/source/view.c +++ b/source/view.c @@ -1007,7 +1007,23 @@ inline static void rofi_view_nav_last(RofiViewState *state) { // state->selected = state->filtered_lines - 1; listview_set_selected(state->list_view, -1); } +static void selection_changed_callback(listview *lv, unsigned int index, + void *udata) { + RofiViewState *state = (RofiViewState *)udata; + if (state->tb_current_entry == NULL) { + return; + } + if (index < state->filtered_lines) { + int fstate = 0; + char *text = mode_get_display_value(state->sw, state->line_map[index], + &fstate, NULL, TRUE); + textbox_text(state->tb_current_entry, text); + g_free(text); + } else { + textbox_text(state->tb_current_entry, ""); + } +} static void update_callback(textbox *t, icon *ico, unsigned int index, void *udata, TextBoxFontType *type, gboolean full) { RofiViewState *state = (RofiViewState *)udata; @@ -1876,6 +1892,12 @@ static void rofi_view_add_widget(RofiViewState *state, widget *parent_widget, TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "", 0, 0); box_add((box *)parent_widget, WIDGET(state->tb_filtered_rows), FALSE); defaults = NULL; + } else if (strcmp(name, "textbox-current-entry") == 0) { + state->tb_current_entry = + textbox_create(parent_widget, WIDGET_TYPE_TEXTBOX_TEXT, name, + TB_MARKUP | TB_AUTOHEIGHT, NORMAL, "", 0, 0); + box_add((box *)parent_widget, WIDGET(state->tb_current_entry), FALSE); + defaults = NULL; } /** * CASE INDICATOR @@ -1934,6 +1956,8 @@ static void rofi_view_add_widget(RofiViewState *state, widget *parent_widget, } state->list_view = listview_create(parent_widget, name, update_callback, state, config.element_height, 0); + listview_set_selection_changed_callback( + state->list_view, selection_changed_callback, (void *)state); box_add((box *)parent_widget, WIDGET(state->list_view), TRUE); // Set configuration listview_set_multi_select(state->list_view, diff --git a/source/widgets/listview.c b/source/widgets/listview.c index ef57972a..acf8eeca 100644 --- a/source/widgets/listview.c +++ b/source/widgets/listview.c @@ -112,6 +112,9 @@ struct _listview { listview_update_callback callback; void *udata; + listview_selection_changed_callback sc_callback; + void *sc_udata; + gboolean scrollbar_scroll; xcb_timestamp_t last_click; @@ -562,7 +565,7 @@ void listview_set_num_elements(listview *lv, unsigned int rows) { } TICK_N("listview_set_num_elements"); lv->req_elements = rows; - if ( lv->require_input && !lv->filtered ) { + if (lv->require_input && !lv->filtered) { lv->req_elements = 0; } listview_set_selected(lv, lv->selected); @@ -585,6 +588,9 @@ void listview_set_selected(listview *lv, unsigned int selected) { lv->selected = MIN(selected, lv->req_elements - 1); lv->barview.direction = LEFT_TO_RIGHT; widget_queue_redraw(WIDGET(lv)); + lv->sc_callback(lv, lv->selected, lv->sc_udata); + } else if (lv->req_elements == 0) { + lv->sc_callback(lv, UINT32_MAX, lv->sc_udata); } } @@ -783,6 +789,8 @@ static void listview_nav_up_int(listview *lv) { } lv->selected--; lv->barview.direction = RIGHT_TO_LEFT; + + lv->sc_callback(lv, lv->selected, lv->sc_udata); widget_queue_redraw(WIDGET(lv)); } static void listview_nav_down_int(listview *lv) { @@ -797,6 +805,7 @@ static void listview_nav_down_int(listview *lv) { ? MIN(lv->req_elements - 1, lv->selected + 1) : 0; lv->barview.direction = LEFT_TO_RIGHT; + lv->sc_callback(lv, lv->selected, lv->sc_udata); widget_queue_redraw(WIDGET(lv)); } void listview_nav_next(listview *lv) { @@ -815,12 +824,14 @@ void listview_nav_prev(listview *lv) { static void listview_nav_column_left_int(listview *lv) { if (lv->selected >= lv->cur_columns) { lv->selected -= lv->cur_columns; + lv->sc_callback(lv, lv->selected, lv->sc_udata); widget_queue_redraw(WIDGET(lv)); } } static void listview_nav_column_right_int(listview *lv) { if ((lv->selected + lv->cur_columns) < lv->req_elements) { lv->selected += lv->cur_columns; + lv->sc_callback(lv, lv->selected, lv->sc_udata); widget_queue_redraw(WIDGET(lv)); } } @@ -879,6 +890,7 @@ void listview_nav_left(listview *lv) { } if (lv->selected >= lv->max_rows) { lv->selected -= lv->max_rows; + lv->sc_callback(lv, lv->selected, lv->sc_udata); widget_queue_redraw(WIDGET(lv)); } } @@ -899,6 +911,7 @@ void listview_nav_right(listview *lv) { } if ((lv->selected + lv->max_rows) < lv->req_elements) { lv->selected += lv->max_rows; + lv->sc_callback(lv, lv->selected, lv->sc_udata); widget_queue_redraw(WIDGET(lv)); } else if (lv->selected < (lv->req_elements - 1)) { // We do not want to move to last item, UNLESS the last column is only @@ -910,6 +923,7 @@ void listview_nav_right(listview *lv) { // If there is an extra column, move. if (col != ncol) { lv->selected = lv->req_elements - 1; + lv->sc_callback(lv, lv->selected, lv->sc_udata); widget_queue_redraw(WIDGET(lv)); } } @@ -935,6 +949,7 @@ static void listview_nav_page_prev_int(listview *lv) { } else { lv->selected -= (lv->max_elements); } + lv->sc_callback(lv, lv->selected, lv->sc_udata); widget_queue_redraw(WIDGET(lv)); } static void listview_nav_page_next_int(listview *lv) { @@ -949,6 +964,7 @@ static void listview_nav_page_next_int(listview *lv) { lv->selected = MIN(new, lv->req_elements - 1); lv->barview.direction = LEFT_TO_RIGHT; + lv->sc_callback(lv, lv->selected, lv->sc_udata); widget_queue_redraw(WIDGET(lv)); return; } @@ -956,6 +972,7 @@ static void listview_nav_page_next_int(listview *lv) { if (lv->selected >= lv->req_elements) { lv->selected = lv->req_elements - 1; } + lv->sc_callback(lv, lv->selected, lv->sc_udata); widget_queue_redraw(WIDGET(lv)); } @@ -1090,9 +1107,14 @@ void listview_toggle_ellipsizing(listview *lv) { } } -void listview_set_filtered ( listview *lv, gboolean filtered ) -{ - if ( lv ) { +void listview_set_filtered(listview *lv, gboolean filtered) { + if (lv) { lv->filtered = filtered; } } + +void listview_set_selection_changed_callback( + listview *lv, listview_selection_changed_callback cb, void *udata) { + lv->sc_callback = cb; + lv->sc_udata = udata; +} diff --git a/themes/sidebar-v2.rasi b/themes/sidebar-v2.rasi new file mode 100644 index 00000000..05894d26 --- /dev/null +++ b/themes/sidebar-v2.rasi @@ -0,0 +1,117 @@ +/** + * ROFI Color theme + * User: Qball + * Copyright: Dave Davenport + */ + +* { + background-color: transparent; + // Bold, Italic, Underline + highlight: bold #ffffff; +} +window { + background-color: black / 80%; + border-color: white; + border-radius: 0 15mm 15mm 0; + + padding: 10mm; + + height: 100%; + width: 150mm; + border: 1mm 1mm 1mm 0px; + text-color: white; + + + location: west; + anchor: west; +} +inputbar { + background-color: transparent; + text-color: black; + children: [prompt, entry, textbox-end]; + spacing: 1mm; +} +prompt { + border-radius: 5mm 0mm 0mm 5mm; + width: 15mm; +} +textbox-end { + border-radius: 0mm 5mm 5mm 0mm; + width: 15mm; + expand: false; +} +entry { + background-color: grey; +} +prompt, entry, textbox-end, num-filtered-rows { + background-color: white; + text-color: inherit; + padding: 2mm; + vertical-align: 0.5; +} +element { + border-radius: 5mm; + children: [element-icon]; +} +textbox-current-entry { + border-radius: 5mm; + background-color: lightgreen; + text-color: black; + placeholder: "n/a"; + padding: 2mm; + horizontal-align: 0.5; + } +element-icon { + expand: true; + size: 20mm; + vertial-align: 0.5; + horizontal-align: 0.5; + padding: 2mm; +} + + +mainbox { + expand: true; + background-color: transparent; + spacing: 5mm; + children: [ inputbar,textbox-current-entry, listview ]; +} +listview { + padding: 0em; + dynamic: false; + lines: 0; + columns: 5; + flow: horizontal; +} +element selected normal { + background-color: MediumSlateBlue; +} +element normal active { + text-color: MediumTurquoise; +} +element normal urgent { + text-color: red; +} +element alternate normal { +} +element alternate active { + text-color: MediumTurquoise; +} +element alternate urgent { + text-color: MediumVioletRed; +} +element selected active { + background-color: MediumTurquoise; + text-color: black; +} +element selected urgent { + background-color: MediumVioletRed; + text-color: black; +} +error-message { + expand: true; + background-color: red; + border-color: darkred; + border: 2px; + padding: 1em; +}