1
1

More intuitive multi-page browsing

Here is the new multi-page listing functionality I promised in
5db9c2aea1.

It may look very easy, but getting this to work right wasn't,
unfortunately.
Этот коммит содержится в:
Yorhel 2010-04-28 13:32:30 +02:00
родитель c68a229e09
Коммит b7ccf78b90
6 изменённых файлов: 84 добавлений и 7 удалений

Просмотреть файл

@ -4,6 +4,7 @@ git - ?
- Fixed crash on browsing dirs with a small window size (#2991787)
- Fixed buffer overflow when some directories can't be scanned (#2981704)
- Improved browsing performance
- More intuitive multi-page browsing
- Various minor fixes
1.6 - 2009-10-23

Просмотреть файл

@ -205,12 +205,10 @@ void browse_draw() {
return;
/* get start position */
t = dirlist_get(-1*((winrows)/2));
if(t == dirlist_next(NULL))
t = NULL;
t = dirlist_top(0);
/* print the list to the screen */
for(i=0; (t=dirlist_next(t)) && i<winrows-3; i++) {
for(i=0; t && i<winrows-3; t=dirlist_next(t),i++) {
browse_draw_item(t, 2+i);
/* save the selected row number for later */
if(t->flags & FF_BSEL)
@ -284,28 +282,34 @@ int browse_key(int ch) {
case KEY_UP:
case 'k':
dirlist_select(dirlist_get(-1));
dirlist_top(-1);
info_start = 0;
break;
case KEY_DOWN:
case 'j':
dirlist_select(dirlist_get(1));
dirlist_top(1);
info_start = 0;
break;
case KEY_HOME:
dirlist_select(dirlist_next(NULL));
dirlist_top(2);
info_start = 0;
break;
case KEY_LL:
case KEY_END:
dirlist_select(dirlist_get(1<<30));
dirlist_top(1);
info_start = 0;
break;
case KEY_PPAGE:
dirlist_select(dirlist_get(-1*(winrows-3)));
dirlist_top(-1);
info_start = 0;
break;
case KEY_NPAGE:
dirlist_select(dirlist_get(winrows-3));
dirlist_top(1);
info_start = 0;
break;
@ -338,15 +342,19 @@ int browse_key(int ch) {
case 10:
case KEY_RIGHT:
case 'l':
if(sel != NULL && sel->sub != NULL)
if(sel != NULL && sel->sub != NULL) {
dirlist_open(sel->sub);
dirlist_top(-3);
}
info_show = 0;
break;
case KEY_LEFT:
case 'h':
case '<':
if(sel != NULL && sel->parent->parent != NULL)
if(sel != NULL && sel->parent->parent != NULL) {
dirlist_open(sel->parent);
dirlist_top(-3);
}
info_show = 0;
break;

Просмотреть файл

@ -509,6 +509,7 @@ int calc_process() {
freedir(orig);
}
browse_init(root->sub);
dirlist_top(-3);
return 0;
}

Просмотреть файл

@ -236,6 +236,7 @@ void delete_process() {
else {
nextsel->flags |= FF_BSEL;
browse_init(nextsel);
dirlist_top(-4);
}
}

Просмотреть файл

@ -40,7 +40,7 @@ int dirlist_sort_desc = 1,
/* private state vars */
struct dir dirlist_parent_alloc;
struct dir *head, *head_real, *selected;
struct dir *head, *head_real, *selected, *top = NULL;
@ -282,6 +282,67 @@ void dirlist_select(struct dir *d) {
}
/* We need a hint in order to figure out which item should be on top:
* 0 = only get the current top, don't set anything
* 1 = selected has moved down
* -1 = selected has moved up
* -2 = selected = first item in the list (faster version of '1')
* -3 = top should be considered as invalid (after sorting or opening an other dir)
* -4 = an item has been deleted
* -5 = hidden flag has been changed
*
* Actions:
* hint = -1 or -4 -> top = selected_is_visible ? top : selected
* hint = -2 or -3 -> top = selected-(winrows-3)/2
* hint = 1 -> top = selected_is_visible ? top : selected-(winrows-4)
* hint = 0 or -5 -> top = selected_is_visible ? top : selected-(winrows-3)/2
*
* Regardless of the hint, the returned top will always be chosen such that the
* selected item is visible.
*/
struct dir *dirlist_top(int hint) {
struct dir *t;
int i = winrows-3, visible = 0;
if(hint == -2 || hint == -3)
top = NULL;
/* check whether the current selected item is within the visible window */
if(top) {
i = winrows-3;
t = dirlist_get(0);
while(t && i--) {
if(t == top) {
visible++;
break;
}
t = dirlist_prev(t);
}
}
/* otherwise, get a new top */
if(!visible)
top = hint == -1 || hint == -4 ? dirlist_get(0) :
hint == 1 ? dirlist_get(-1*(winrows-4)) :
dirlist_get(-1*(winrows-3)/2);
/* also make sure that if the list is longer than the window and the last
* item is visible, that this last item is also the last on the window */
t = top;
i = winrows-3;
while(t && i--)
t = dirlist_next(t);
t = top;
do {
top = t;
t = dirlist_prev(t);
} while(t && i-- > 0);
return top;
}
void dirlist_set_sort(int col, int desc, int df) {
/* update config */
if(col != DL_NOCHANGE)
@ -297,11 +358,13 @@ void dirlist_set_sort(int col, int desc, int df) {
dirlist_parent->next = head_real;
else
head = head_real;
dirlist_top(-3);
}
void dirlist_set_hidden(int hidden) {
dirlist_hidden = hidden;
dirlist_fixup();
dirlist_top(-5);
}

Просмотреть файл

@ -49,6 +49,9 @@ struct dir *dirlist_next(struct dir *);
* hidden items aren't considered */
struct dir *dirlist_get(int i);
/* Get/set the first visible item in the list on the screen */
struct dir *dirlist_top(int hint);
/* Set selected dir (must be in the currently opened directory, obviously) */
void dirlist_select(struct dir *);