mirror of
https://github.com/davatorium/rofi.git
synced 2024-11-25 13:55:34 -05:00
[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:
parent
0bbefbf257
commit
47d785758a
10 changed files with 171 additions and 24 deletions
|
@ -262,7 +262,7 @@ Go to the next column
|
||||||
Select previous entry
|
Select previous entry
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
\fBDefault\fP: Up,Control+p,ISO\_Left\_Tab
|
\fBDefault\fP: Up,Control+p
|
||||||
|
|
||||||
.SS \fBkb\-row\-down\fP
|
.SS \fBkb\-row\-down\fP
|
||||||
.PP
|
.PP
|
||||||
|
@ -275,9 +275,23 @@ Select next entry
|
||||||
.PP
|
.PP
|
||||||
Go to next row, if one left, accept it, if no left next mode.
|
Go to next row, if one left, accept it, if no left next mode.
|
||||||
|
|
||||||
|
.PP
|
||||||
|
\fBDefault\fP:
|
||||||
|
|
||||||
|
.SS \fBkb\-element\-next\fP
|
||||||
|
.PP
|
||||||
|
Go to next row.
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
\fBDefault\fP: Tab
|
\fBDefault\fP: Tab
|
||||||
|
|
||||||
|
.SS \fBkb\-element\-prev\fP
|
||||||
|
.PP
|
||||||
|
Go to previous row.
|
||||||
|
|
||||||
|
.PP
|
||||||
|
\fBDefault\fP: ISO\_Left\_Tab
|
||||||
|
|
||||||
.SS \fBkb\-page\-prev\fP
|
.SS \fBkb\-page\-prev\fP
|
||||||
.PP
|
.PP
|
||||||
Go to the previous page
|
Go to the previous page
|
||||||
|
|
|
@ -183,7 +183,7 @@ Go to the next column
|
||||||
### **kb-row-up**
|
### **kb-row-up**
|
||||||
Select previous entry
|
Select previous entry
|
||||||
|
|
||||||
**Default**: Up,Control+p,ISO_Left_Tab
|
**Default**: Up,Control+p
|
||||||
|
|
||||||
### **kb-row-down**
|
### **kb-row-down**
|
||||||
Select next entry
|
Select next entry
|
||||||
|
@ -193,8 +193,18 @@ Select next entry
|
||||||
### **kb-row-tab**
|
### **kb-row-tab**
|
||||||
Go to next row, if one left, accept it, if no left next mode.
|
Go to next row, if one left, accept it, if no left next mode.
|
||||||
|
|
||||||
|
**Default**:
|
||||||
|
|
||||||
|
### **kb-element-next**
|
||||||
|
Go to next row.
|
||||||
|
|
||||||
**Default**: Tab
|
**Default**: Tab
|
||||||
|
|
||||||
|
### **kb-element-prev**
|
||||||
|
Go to previous row.
|
||||||
|
|
||||||
|
**Default**: ISO_Left_Tab
|
||||||
|
|
||||||
### **kb-page-prev**
|
### **kb-page-prev**
|
||||||
Go to the previous page
|
Go to the previous page
|
||||||
|
|
||||||
|
|
|
@ -1278,6 +1278,9 @@ Indicate how elements are stacked. Horizontal implements the dmenu style.
|
||||||
\fBreverse\fP: boolean
|
\fBreverse\fP: boolean
|
||||||
Reverse the ordering (top down to bottom up).
|
Reverse the ordering (top down to bottom up).
|
||||||
.IP \(bu 2
|
.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
|
\fBfixed\-columns\fP: boolean
|
||||||
Do not reduce the number of columns shown when number of visible elements is not enough to fill them all.
|
Do not reduce the number of columns shown when number of visible elements is not enough to fill them all.
|
||||||
|
|
||||||
|
|
|
@ -794,6 +794,8 @@ The following properties are currently supported:
|
||||||
Indicate how elements are stacked. Horizontal implements the dmenu style.
|
Indicate how elements are stacked. Horizontal implements the dmenu style.
|
||||||
* **reverse**: boolean
|
* **reverse**: boolean
|
||||||
Reverse the ordering (top down to bottom up).
|
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
|
* **fixed-columns**: boolean
|
||||||
Do not reduce the number of columns shown when number of visible elements is not enough to fill them all.
|
Do not reduce the number of columns shown when number of visible elements is not enough to fill them all.
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,8 @@ typedef enum {
|
||||||
ROW_UP,
|
ROW_UP,
|
||||||
ROW_DOWN,
|
ROW_DOWN,
|
||||||
ROW_TAB,
|
ROW_TAB,
|
||||||
|
ELEMENT_NEXT,
|
||||||
|
ELEMENT_PREV,
|
||||||
PAGE_PREV,
|
PAGE_PREV,
|
||||||
PAGE_NEXT,
|
PAGE_NEXT,
|
||||||
ROW_FIRST,
|
ROW_FIRST,
|
||||||
|
|
|
@ -111,6 +111,21 @@ void listview_set_selected(listview *lv, unsigned int selected);
|
||||||
*/
|
*/
|
||||||
unsigned int listview_get_selected(listview *lv);
|
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
|
* @param lv The listview handle
|
||||||
*
|
*
|
||||||
|
|
|
@ -26,10 +26,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <string.h>
|
|
||||||
#include "nkutils-bindings.h"
|
#include "nkutils-bindings.h"
|
||||||
#include "rofi.h"
|
#include "rofi.h"
|
||||||
#include "xrmoptions.h"
|
#include "xrmoptions.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
guint id;
|
guint id;
|
||||||
|
@ -145,7 +145,7 @@ ActionBindingEntry rofi_bindings[] = {
|
||||||
.comment = "Go to the next column"},
|
.comment = "Go to the next column"},
|
||||||
{.id = ROW_UP,
|
{.id = ROW_UP,
|
||||||
.name = "kb-row-up",
|
.name = "kb-row-up",
|
||||||
.binding = "Up,Control+p,ISO_Left_Tab",
|
.binding = "Up,Control+p",
|
||||||
.comment = "Select previous entry"},
|
.comment = "Select previous entry"},
|
||||||
{.id = ROW_DOWN,
|
{.id = ROW_DOWN,
|
||||||
.name = "kb-row-down",
|
.name = "kb-row-down",
|
||||||
|
@ -153,9 +153,17 @@ ActionBindingEntry rofi_bindings[] = {
|
||||||
.comment = "Select next entry"},
|
.comment = "Select next entry"},
|
||||||
{.id = ROW_TAB,
|
{.id = ROW_TAB,
|
||||||
.name = "kb-row-tab",
|
.name = "kb-row-tab",
|
||||||
.binding = "Tab",
|
.binding = "",
|
||||||
.comment =
|
.comment =
|
||||||
"Go to next row, if one left, accept it, if no left next mode."},
|
"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,
|
{.id = PAGE_PREV,
|
||||||
.name = "kb-page-prev",
|
.name = "kb-page-prev",
|
||||||
.binding = "Page_Up",
|
.binding = "Page_Up",
|
||||||
|
|
|
@ -1362,6 +1362,12 @@ static void rofi_view_trigger_global_action(KeyBindingAction action) {
|
||||||
state->retv = MENU_CANCEL;
|
state->retv = MENU_CANCEL;
|
||||||
state->quit = TRUE;
|
state->quit = TRUE;
|
||||||
break;
|
break;
|
||||||
|
case ELEMENT_NEXT:
|
||||||
|
listview_nav_next(state->list_view);
|
||||||
|
break;
|
||||||
|
case ELEMENT_PREV:
|
||||||
|
listview_nav_prev(state->list_view);
|
||||||
|
break;
|
||||||
case ROW_UP:
|
case ROW_UP:
|
||||||
listview_nav_up(state->list_view);
|
listview_nav_up(state->list_view);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -71,6 +71,9 @@ struct _listview {
|
||||||
// RChanged
|
// RChanged
|
||||||
// Text needs to be repainted.
|
// Text needs to be repainted.
|
||||||
unsigned int rchanged;
|
unsigned int rchanged;
|
||||||
|
|
||||||
|
// The direction we pack the widgets.
|
||||||
|
RofiOrientation pack_direction;
|
||||||
// Administration
|
// Administration
|
||||||
|
|
||||||
unsigned int cur_page;
|
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++) {
|
for (unsigned int i = 0; i < max; i++) {
|
||||||
unsigned int ex =
|
if (lv->pack_direction == ROFI_ORIENTATION_HORIZONTAL) {
|
||||||
left_offset + ((i) / lv->max_rows) * (element_width + spacing_hori);
|
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->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 ex = left_offset + ((i) / lv->max_rows) *
|
||||||
|
(element_width + spacing_hori);
|
||||||
|
|
||||||
if ((i) / lv->max_rows == (lv->cur_columns - 1)) {
|
if ((i) / lv->max_rows == (lv->cur_columns - 1)) {
|
||||||
ex += d;
|
ex += d;
|
||||||
}
|
}
|
||||||
|
unsigned int ey = 0;
|
||||||
if (lv->reverse) {
|
if (lv->reverse) {
|
||||||
unsigned int ey =
|
ey = wid->h -
|
||||||
wid->h -
|
|
||||||
(widget_padding_get_bottom(wid) +
|
(widget_padding_get_bottom(wid) +
|
||||||
((i) % lv->max_rows) * (lv->element_height + spacing_vert)) -
|
((i) % lv->max_rows) * (lv->element_height + spacing_vert)) -
|
||||||
lv->element_height;
|
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 {
|
} else {
|
||||||
unsigned int ey =
|
ey = top_offset +
|
||||||
top_offset +
|
|
||||||
((i) % lv->max_rows) * (lv->element_height + spacing_vert);
|
((i) % lv->max_rows) * (lv->element_height + spacing_vert);
|
||||||
|
}
|
||||||
widget_move(WIDGET(lv->boxes[i].box), ex, ey);
|
widget_move(WIDGET(lv->boxes[i].box), ex, ey);
|
||||||
widget_resize(WIDGET(lv->boxes[i].box), element_width,
|
widget_resize(WIDGET(lv->boxes[i].box), element_width,
|
||||||
lv->element_height);
|
lv->element_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
update_element(lv, i, i + offset, TRUE);
|
update_element(lv, i, i + offset, TRUE);
|
||||||
widget_draw(WIDGET(lv->boxes[i].box), draw);
|
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) {
|
if (!(lv->fixed_columns) && lv->req_elements < lv->max_elements) {
|
||||||
newne = lv->req_elements;
|
newne = lv->req_elements;
|
||||||
|
if (lv->pack_direction == ROFI_ORIENTATION_VERTICAL) {
|
||||||
lv->cur_columns = (lv->req_elements + (lv->max_rows - 1)) / lv->max_rows;
|
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 {
|
} else {
|
||||||
newne = MIN(lv->req_elements, lv->max_elements);
|
newne = MIN(lv->req_elements, lv->max_elements);
|
||||||
lv->cur_columns = lv->menu_columns;
|
lv->cur_columns = lv->menu_columns;
|
||||||
|
@ -709,6 +742,8 @@ listview *listview_create(widget *parent, const char *name,
|
||||||
config.fixed_num_lines);
|
config.fixed_num_lines);
|
||||||
lv->dynamic = rofi_theme_get_boolean(WIDGET(lv), "dynamic", TRUE);
|
lv->dynamic = rofi_theme_get_boolean(WIDGET(lv), "dynamic", TRUE);
|
||||||
lv->reverse = rofi_theme_get_boolean(WIDGET(lv), "reverse", reverse);
|
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->cycle = rofi_theme_get_boolean(WIDGET(lv), "cycle", config.cycle);
|
||||||
lv->fixed_columns =
|
lv->fixed_columns =
|
||||||
rofi_theme_get_boolean(WIDGET(lv), "fixed-columns", FALSE);
|
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;
|
lv->barview.direction = LEFT_TO_RIGHT;
|
||||||
widget_queue_redraw(WIDGET(lv));
|
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) {
|
void listview_nav_up(listview *lv) {
|
||||||
if (lv == NULL) {
|
if (lv == NULL) {
|
||||||
return;
|
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) {
|
if (lv->reverse) {
|
||||||
listview_nav_down_int(lv);
|
listview_nav_down_int(lv);
|
||||||
} else {
|
} else {
|
||||||
|
@ -771,6 +839,14 @@ void listview_nav_down(listview *lv) {
|
||||||
if (lv == NULL) {
|
if (lv == NULL) {
|
||||||
return;
|
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) {
|
if (lv->reverse) {
|
||||||
listview_nav_up_int(lv);
|
listview_nav_up_int(lv);
|
||||||
} else {
|
} else {
|
||||||
|
@ -782,6 +858,13 @@ void listview_nav_left(listview *lv) {
|
||||||
if (lv == NULL) {
|
if (lv == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (lv->max_rows == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (lv->pack_direction == ROFI_ORIENTATION_HORIZONTAL) {
|
||||||
|
listview_nav_up_int(lv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (lv->type == BARVIEW) {
|
if (lv->type == BARVIEW) {
|
||||||
listview_nav_up_int(lv);
|
listview_nav_up_int(lv);
|
||||||
return;
|
return;
|
||||||
|
@ -798,6 +881,10 @@ void listview_nav_right(listview *lv) {
|
||||||
if (lv->max_rows == 0) {
|
if (lv->max_rows == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (lv->pack_direction == ROFI_ORIENTATION_HORIZONTAL) {
|
||||||
|
listview_nav_down_int(lv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (lv->type == BARVIEW) {
|
if (lv->type == BARVIEW) {
|
||||||
listview_nav_down_int(lv);
|
listview_nav_down_int(lv);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -117,7 +117,7 @@ END_TEST
|
||||||
|
|
||||||
START_TEST(test_mode_num_items) {
|
START_TEST(test_mode_num_items) {
|
||||||
unsigned int rows = mode_get_num_entries(&help_keys_mode);
|
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++) {
|
for (unsigned int i = 0; i < rows; i++) {
|
||||||
int state = 0;
|
int state = 0;
|
||||||
GList *list = NULL;
|
GList *list = NULL;
|
||||||
|
|
Loading…
Reference in a new issue