Skip to content
Snippets Groups Projects
Commit b7ccf78b authored by Yorhel's avatar Yorhel
Browse files

More intuitive multi-page browsing

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

It may look very easy, but getting this to work right wasn't,
unfortunately.
parent c68a229e
No related branches found
No related tags found
No related merge requests found
...@@ -4,6 +4,7 @@ git - ? ...@@ -4,6 +4,7 @@ git - ?
- Fixed crash on browsing dirs with a small window size (#2991787) - Fixed crash on browsing dirs with a small window size (#2991787)
- Fixed buffer overflow when some directories can't be scanned (#2981704) - Fixed buffer overflow when some directories can't be scanned (#2981704)
- Improved browsing performance - Improved browsing performance
- More intuitive multi-page browsing
- Various minor fixes - Various minor fixes
1.6 - 2009-10-23 1.6 - 2009-10-23
......
...@@ -205,12 +205,10 @@ void browse_draw() { ...@@ -205,12 +205,10 @@ void browse_draw() {
return; return;
/* get start position */ /* get start position */
t = dirlist_get(-1*((winrows)/2)); t = dirlist_top(0);
if(t == dirlist_next(NULL))
t = NULL;
/* print the list to the screen */ /* 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); browse_draw_item(t, 2+i);
/* save the selected row number for later */ /* save the selected row number for later */
if(t->flags & FF_BSEL) if(t->flags & FF_BSEL)
...@@ -284,28 +282,34 @@ int browse_key(int ch) { ...@@ -284,28 +282,34 @@ int browse_key(int ch) {
case KEY_UP: case KEY_UP:
case 'k': case 'k':
dirlist_select(dirlist_get(-1)); dirlist_select(dirlist_get(-1));
dirlist_top(-1);
info_start = 0; info_start = 0;
break; break;
case KEY_DOWN: case KEY_DOWN:
case 'j': case 'j':
dirlist_select(dirlist_get(1)); dirlist_select(dirlist_get(1));
dirlist_top(1);
info_start = 0; info_start = 0;
break; break;
case KEY_HOME: case KEY_HOME:
dirlist_select(dirlist_next(NULL)); dirlist_select(dirlist_next(NULL));
dirlist_top(2);
info_start = 0; info_start = 0;
break; break;
case KEY_LL: case KEY_LL:
case KEY_END: case KEY_END:
dirlist_select(dirlist_get(1<<30)); dirlist_select(dirlist_get(1<<30));
dirlist_top(1);
info_start = 0; info_start = 0;
break; break;
case KEY_PPAGE: case KEY_PPAGE:
dirlist_select(dirlist_get(-1*(winrows-3))); dirlist_select(dirlist_get(-1*(winrows-3)));
dirlist_top(-1);
info_start = 0; info_start = 0;
break; break;
case KEY_NPAGE: case KEY_NPAGE:
dirlist_select(dirlist_get(winrows-3)); dirlist_select(dirlist_get(winrows-3));
dirlist_top(1);
info_start = 0; info_start = 0;
break; break;
...@@ -338,15 +342,19 @@ int browse_key(int ch) { ...@@ -338,15 +342,19 @@ int browse_key(int ch) {
case 10: case 10:
case KEY_RIGHT: case KEY_RIGHT:
case 'l': case 'l':
if(sel != NULL && sel->sub != NULL) if(sel != NULL && sel->sub != NULL) {
dirlist_open(sel->sub); dirlist_open(sel->sub);
dirlist_top(-3);
}
info_show = 0; info_show = 0;
break; break;
case KEY_LEFT: case KEY_LEFT:
case 'h': case 'h':
case '<': case '<':
if(sel != NULL && sel->parent->parent != NULL) if(sel != NULL && sel->parent->parent != NULL) {
dirlist_open(sel->parent); dirlist_open(sel->parent);
dirlist_top(-3);
}
info_show = 0; info_show = 0;
break; break;
......
...@@ -509,6 +509,7 @@ int calc_process() { ...@@ -509,6 +509,7 @@ int calc_process() {
freedir(orig); freedir(orig);
} }
browse_init(root->sub); browse_init(root->sub);
dirlist_top(-3);
return 0; return 0;
} }
......
...@@ -236,6 +236,7 @@ void delete_process() { ...@@ -236,6 +236,7 @@ void delete_process() {
else { else {
nextsel->flags |= FF_BSEL; nextsel->flags |= FF_BSEL;
browse_init(nextsel); browse_init(nextsel);
dirlist_top(-4);
} }
} }
......
...@@ -40,7 +40,7 @@ int dirlist_sort_desc = 1, ...@@ -40,7 +40,7 @@ int dirlist_sort_desc = 1,
/* private state vars */ /* private state vars */
struct dir dirlist_parent_alloc; 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) { ...@@ -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) { void dirlist_set_sort(int col, int desc, int df) {
/* update config */ /* update config */
if(col != DL_NOCHANGE) if(col != DL_NOCHANGE)
...@@ -297,11 +358,13 @@ void dirlist_set_sort(int col, int desc, int df) { ...@@ -297,11 +358,13 @@ void dirlist_set_sort(int col, int desc, int df) {
dirlist_parent->next = head_real; dirlist_parent->next = head_real;
else else
head = head_real; head = head_real;
dirlist_top(-3);
} }
void dirlist_set_hidden(int hidden) { void dirlist_set_hidden(int hidden) {
dirlist_hidden = hidden; dirlist_hidden = hidden;
dirlist_fixup(); dirlist_fixup();
dirlist_top(-5);
} }
...@@ -49,6 +49,9 @@ struct dir *dirlist_next(struct dir *); ...@@ -49,6 +49,9 @@ struct dir *dirlist_next(struct dir *);
* hidden items aren't considered */ * hidden items aren't considered */
struct dir *dirlist_get(int i); 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) */ /* Set selected dir (must be in the currently opened directory, obviously) */
void dirlist_select(struct dir *); void dirlist_select(struct dir *);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment