[listview] Allow settings of flow direction of elements (#1605)

* [Listview] Initial implementation for left to right packing.
* [Listview] fix movement in pack-left-to-right.
* Add element-next/prev keybinding and remap tab.
* [Listview] Change option name to 'flow' and use rofi orientation type.
* [Listview] Make listview work with reverse property.
* Update test for 2 new keybindings.

fixes: #1058
This commit is contained in:
Dave Davenport 2022-03-07 20:37:58 +01:00 committed by GitHub
parent 0bbefbf257
commit 47d785758a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 171 additions and 24 deletions

View File

@ -262,7 +262,7 @@ Go to the next column
Select previous entry
.PP
\fBDefault\fP: Up,Control+p,ISO\_Left\_Tab
\fBDefault\fP: Up,Control+p
.SS \fBkb\-row\-down\fP
.PP
@ -276,7 +276,21 @@ Select next entry
Go to next row, if one left, accept it, if no left next mode.
.PP
\fBDefault\fP: Tab
\fBDefault\fP:
.SS \fBkb\-element\-next\fP
.PP
Go to next row.
.PP
\fBDefault\fP: Tab
.SS \fBkb\-element\-prev\fP
.PP
Go to previous row.
.PP
\fBDefault\fP: ISO\_Left\_Tab
.SS \fBkb\-page\-prev\fP
.PP

View File

@ -183,7 +183,7 @@ Go to the next column
### **kb-row-up**
Select previous entry
**Default**: Up,Control+p,ISO_Left_Tab
**Default**: Up,Control+p
### **kb-row-down**
Select next entry
@ -193,7 +193,17 @@ Select next entry
### **kb-row-tab**
Go to next row, if one left, accept it, if no left next mode.
**Default**: Tab
**Default**:
### **kb-element-next**
Go to next row.
**Default**: Tab
### **kb-element-prev**
Go to previous row.
**Default**: ISO_Left_Tab
### **kb-page-prev**
Go to the previous page

View File

@ -1278,6 +1278,9 @@ Indicate how elements are stacked. Horizontal implements the dmenu style.
\fBreverse\fP: boolean
Reverse the ordering (top down to bottom up).
.IP \(bu 2
\fBflow\fP: orientation
The order the elements are layed out. Vertical is the original 'column' view.
.IP \(bu 2
\fBfixed\-columns\fP: boolean
Do not reduce the number of columns shown when number of visible elements is not enough to fill them all.

View File

@ -794,6 +794,8 @@ The following properties are currently supported:
Indicate how elements are stacked. Horizontal implements the dmenu style.
* **reverse**: boolean
Reverse the ordering (top down to bottom up).
* **flow**: orientation
The order the elements are layed out. Vertical is the original 'column' view.
* **fixed-columns**: boolean
Do not reduce the number of columns shown when number of visible elements is not enough to fill them all.

View File

@ -101,6 +101,8 @@ typedef enum {
ROW_UP,
ROW_DOWN,
ROW_TAB,
ELEMENT_NEXT,
ELEMENT_PREV,
PAGE_PREV,
PAGE_NEXT,
ROW_FIRST,

View File

@ -111,6 +111,21 @@ void listview_set_selected(listview *lv, unsigned int selected);
*/
unsigned int listview_get_selected(listview *lv);
/**
* @param lv The listview handle
*
* Move the selection next element.
* - Wrap around.
*/
void listview_nav_next(listview *lv);
/**
* @param lv The listview handle
*
* Move the selection previous element.
* - Wrap around.
*/
void listview_nav_prev(listview *lv);
/**
* @param lv The listview handle
*

View File

@ -26,10 +26,10 @@
*/
#include <glib.h>
#include <string.h>
#include "nkutils-bindings.h"
#include "rofi.h"
#include "xrmoptions.h"
#include <string.h>
typedef struct {
guint id;
@ -145,7 +145,7 @@ ActionBindingEntry rofi_bindings[] = {
.comment = "Go to the next column"},
{.id = ROW_UP,
.name = "kb-row-up",
.binding = "Up,Control+p,ISO_Left_Tab",
.binding = "Up,Control+p",
.comment = "Select previous entry"},
{.id = ROW_DOWN,
.name = "kb-row-down",
@ -153,9 +153,17 @@ ActionBindingEntry rofi_bindings[] = {
.comment = "Select next entry"},
{.id = ROW_TAB,
.name = "kb-row-tab",
.binding = "Tab",
.binding = "",
.comment =
"Go to next row, if one left, accept it, if no left next mode."},
{.id = ELEMENT_NEXT,
.name = "kb-element-next",
.binding = "Tab",
.comment = "Go to next element (in logical order)."},
{.id = ELEMENT_PREV,
.name = "kb-element-prev",
.binding = "ISO_Left_Tab",
.comment = "Go to next previous element (in logical order)."},
{.id = PAGE_PREV,
.name = "kb-page-prev",
.binding = "Page_Up",

View File

@ -1362,6 +1362,12 @@ static void rofi_view_trigger_global_action(KeyBindingAction action) {
state->retv = MENU_CANCEL;
state->quit = TRUE;
break;
case ELEMENT_NEXT:
listview_nav_next(state->list_view);
break;
case ELEMENT_PREV:
listview_nav_prev(state->list_view);
break;
case ROW_UP:
listview_nav_up(state->list_view);
break;

View File

@ -71,6 +71,9 @@ struct _listview {
// RChanged
// Text needs to be repainted.
unsigned int rchanged;
// The direction we pack the widgets.
RofiOrientation pack_direction;
// Administration
unsigned int cur_page;
@ -433,30 +436,53 @@ static void listview_draw(widget *wid, cairo_t *draw) {
}
}
for (unsigned int i = 0; i < max; i++) {
unsigned int ex =
left_offset + ((i) / lv->max_rows) * (element_width + spacing_hori);
if (lv->pack_direction == ROFI_ORIENTATION_HORIZONTAL) {
unsigned int ex = left_offset + ((i) % lv->cur_columns) *
(element_width + spacing_hori);
unsigned int ey = 0;
if (lv->reverse) {
ey = wid->h -
(widget_padding_get_bottom(wid) +
((i) / lv->cur_columns) *
(lv->element_height + spacing_vert)) -
lv->element_height;
if ((i) / lv->max_rows == (lv->cur_columns - 1)) {
ex += d;
}
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;
if ((i) / lv->cur_columns == (lv->cur_columns - 1)) {
ex += d;
}
} else {
ey = top_offset +
((i) / lv->cur_columns) * (lv->element_height + spacing_vert);
if ((i) / lv->cur_columns == (lv->cur_columns - 1)) {
ex += d;
}
}
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);
unsigned int ex = left_offset + ((i) / lv->max_rows) *
(element_width + spacing_hori);
if ((i) / lv->max_rows == (lv->cur_columns - 1)) {
ex += d;
}
unsigned int ey = 0;
if (lv->reverse) {
ey = wid->h -
(widget_padding_get_bottom(wid) +
((i) % lv->max_rows) * (lv->element_height + spacing_vert)) -
lv->element_height;
} else {
ey = top_offset +
((i) % lv->max_rows) * (lv->element_height + spacing_vert);
}
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].box), draw);
}
@ -494,7 +520,14 @@ static void listview_recompute_elements(listview *lv) {
}
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;
if (lv->pack_direction == ROFI_ORIENTATION_VERTICAL) {
lv->cur_columns = (lv->req_elements + (lv->max_rows - 1)) / lv->max_rows;
} else {
lv->cur_columns = lv->menu_columns;
if (lv->req_elements < lv->menu_columns) {
lv->cur_columns = lv->req_elements;
}
}
} else {
newne = MIN(lv->req_elements, lv->max_elements);
lv->cur_columns = lv->menu_columns;
@ -709,6 +742,8 @@ listview *listview_create(widget *parent, const char *name,
config.fixed_num_lines);
lv->dynamic = rofi_theme_get_boolean(WIDGET(lv), "dynamic", TRUE);
lv->reverse = rofi_theme_get_boolean(WIDGET(lv), "reverse", reverse);
lv->pack_direction =
rofi_theme_get_orientation(WIDGET(lv), "flow", ROFI_ORIENTATION_VERTICAL);
lv->cycle = rofi_theme_get_boolean(WIDGET(lv), "cycle", config.cycle);
lv->fixed_columns =
rofi_theme_get_boolean(WIDGET(lv), "fixed-columns", FALSE);
@ -756,11 +791,44 @@ static void listview_nav_down_int(listview *lv) {
lv->barview.direction = LEFT_TO_RIGHT;
widget_queue_redraw(WIDGET(lv));
}
void listview_nav_next(listview *lv) {
if (lv == NULL) {
return;
}
listview_nav_down_int(lv);
}
void listview_nav_prev(listview *lv) {
if (lv == NULL) {
return;
}
listview_nav_up_int(lv);
}
static void listview_nav_column_left_int(listview *lv) {
if (lv->selected >= lv->cur_columns) {
lv->selected -= lv->cur_columns;
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;
widget_queue_redraw(WIDGET(lv));
}
}
void listview_nav_up(listview *lv) {
if (lv == NULL) {
return;
}
if (lv->pack_direction == ROFI_ORIENTATION_HORIZONTAL) {
if (lv->reverse) {
listview_nav_column_right_int(lv);
} else {
listview_nav_column_left_int(lv);
}
return;
}
if (lv->reverse) {
listview_nav_down_int(lv);
} else {
@ -771,6 +839,14 @@ void listview_nav_down(listview *lv) {
if (lv == NULL) {
return;
}
if (lv->pack_direction == ROFI_ORIENTATION_HORIZONTAL) {
if (lv->reverse) {
listview_nav_column_left_int(lv);
} else {
listview_nav_column_right_int(lv);
}
return;
}
if (lv->reverse) {
listview_nav_up_int(lv);
} else {
@ -782,6 +858,13 @@ void listview_nav_left(listview *lv) {
if (lv == NULL) {
return;
}
if (lv->max_rows == 0) {
return;
}
if (lv->pack_direction == ROFI_ORIENTATION_HORIZONTAL) {
listview_nav_up_int(lv);
return;
}
if (lv->type == BARVIEW) {
listview_nav_up_int(lv);
return;
@ -798,6 +881,10 @@ void listview_nav_right(listview *lv) {
if (lv->max_rows == 0) {
return;
}
if (lv->pack_direction == ROFI_ORIENTATION_HORIZONTAL) {
listview_nav_down_int(lv);
return;
}
if (lv->type == BARVIEW) {
listview_nav_down_int(lv);
return;

View File

@ -117,7 +117,7 @@ END_TEST
START_TEST(test_mode_num_items) {
unsigned int rows = mode_get_num_entries(&help_keys_mode);
ck_assert_int_eq(rows, 74);
ck_assert_int_eq(rows, 76);
for (unsigned int i = 0; i < rows; i++) {
int state = 0;
GList *list = NULL;