david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

[settings] Enable jump scroll in config UI

Implement jump scrolling with "..." displayed where the settings list
continues off-screen, because there are now too many settings to fit
on screen in the "config ..." text user interface.

Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Glenn Brown 2010-06-23 13:18:34 -07:00 committed by Michael Brown
parent 9908587ca2
commit f9bcb928f5
1 changed files with 77 additions and 38 deletions

View File

@ -45,6 +45,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define TITLE_ROW 1 #define TITLE_ROW 1
#define SETTINGS_LIST_ROW 3 #define SETTINGS_LIST_ROW 3
#define SETTINGS_LIST_COL 1 #define SETTINGS_LIST_COL 1
#define SETTINGS_LIST_ROWS 16
#define INFO_ROW 20 #define INFO_ROW 20
#define ALERT_ROW 20 #define ALERT_ROW 20
#define INSTRUCTION_ROW 22 #define INSTRUCTION_ROW 22
@ -65,6 +66,8 @@ struct setting_row {
struct setting_widget { struct setting_widget {
/** Settings block */ /** Settings block */
struct settings *settings; struct settings *settings;
/** Index of the first visible setting, for scrolling. */
unsigned int first_visible;
/** Configuration setting */ /** Configuration setting */
struct setting *setting; struct setting *setting;
/** Screen row */ /** Screen row */
@ -84,15 +87,13 @@ struct setting_widget {
static void load_setting ( struct setting_widget *widget ) __nonnull; static void load_setting ( struct setting_widget *widget ) __nonnull;
static int save_setting ( struct setting_widget *widget ) __nonnull; static int save_setting ( struct setting_widget *widget ) __nonnull;
static void init_setting ( struct setting_widget *widget, static void init_widget ( struct setting_widget *widget,
struct settings *settings, struct settings *settings ) __nonnull;
struct setting *setting,
unsigned int row, unsigned int col ) __nonnull;
static void draw_setting ( struct setting_widget *widget ) __nonnull; static void draw_setting ( struct setting_widget *widget ) __nonnull;
static int edit_setting ( struct setting_widget *widget, int key ) __nonnull; static int edit_setting ( struct setting_widget *widget, int key ) __nonnull;
static void init_setting_index ( struct setting_widget *widget, static void select_setting ( struct setting_widget *widget,
struct settings *settings, unsigned int index ) __nonnull;
unsigned int index ) __nonnull; static void reveal ( struct setting_widget *widget, unsigned int n) __nonnull;
static void vmsg ( unsigned int row, const char *fmt, va_list args ) __nonnull; static void vmsg ( unsigned int row, const char *fmt, va_list args ) __nonnull;
static void msg ( unsigned int row, const char *fmt, ... ) __nonnull; static void msg ( unsigned int row, const char *fmt, ... ) __nonnull;
static void valert ( const char *fmt, va_list args ) __nonnull; static void valert ( const char *fmt, va_list args ) __nonnull;
@ -135,28 +136,17 @@ static int save_setting ( struct setting_widget *widget ) {
} }
/** /**
* Initialise setting widget * Initialise the scrolling setting widget, drawing initial display.
* *
* @v widget Setting widget * @v widget Setting widget
* @v settings Settings block * @v settings Settings block
* @v setting Configuration setting
* @v row Screen row
* @v col Screen column
*/ */
static void init_setting ( struct setting_widget *widget, static void init_widget ( struct setting_widget *widget,
struct settings *settings, struct settings *settings ) {
struct setting *setting,
unsigned int row, unsigned int col ) {
/* Initialise widget structure */
memset ( widget, 0, sizeof ( *widget ) ); memset ( widget, 0, sizeof ( *widget ) );
widget->settings = settings; widget->settings = settings;
widget->setting = setting; widget->first_visible = SETTINGS_LIST_ROWS;
widget->row = row; reveal ( widget, 0 );
widget->col = col;
/* Read current setting value */
load_setting ( widget );
} }
/** /**
@ -212,19 +202,25 @@ static int edit_setting ( struct setting_widget *widget, int key ) {
} }
/** /**
* Initialise setting widget by index * Select a setting for display updates, by index.
* *
* @v widget Setting widget * @v widget Setting widget
* @v settings Settings block * @v settings Settings block
* @v index Index of setting with settings list * @v index Index of setting with settings list
*/ */
static void init_setting_index ( struct setting_widget *widget, static void select_setting ( struct setting_widget *widget,
struct settings *settings, unsigned int index ) {
unsigned int index ) {
struct setting *all_settings = table_start ( SETTINGS ); struct setting *all_settings = table_start ( SETTINGS );
unsigned int skip = offsetof ( struct setting_widget, setting );
init_setting ( widget, settings, &all_settings[index], /* Reset the widget, preserving static state. */
( SETTINGS_LIST_ROW + index ), SETTINGS_LIST_COL ); memset ( ( char * ) widget + skip, 0, sizeof ( *widget ) - skip );
widget->setting = &all_settings[index];
widget->row = SETTINGS_LIST_ROW + index - widget->first_visible;
widget->col = SETTINGS_LIST_COL;
/* Read current setting value */
load_setting ( widget );
} }
/** /**
@ -334,22 +330,65 @@ static void draw_instruction_row ( int editing ) {
} }
} }
/**
* Reveal a setting by index: Scroll the setting list to reveal the
* specified setting.
*
* @widget The main loop's display widget.
* @n The index of the setting to reveal.
*/
static void reveal ( struct setting_widget *widget, unsigned int n)
{
unsigned int i;
/* Simply return if setting N is already on-screen. */
if ( n - widget->first_visible < SETTINGS_LIST_ROWS )
return;
/* Jump scroll to make the specified setting visible. */
while ( widget->first_visible < n )
widget->first_visible += SETTINGS_LIST_ROWS;
while ( widget->first_visible > n )
widget->first_visible -= SETTINGS_LIST_ROWS;
/* Draw elipses before and/or after the settings list to
represent any invisible settings. */
mvaddstr ( SETTINGS_LIST_ROW - 1,
SETTINGS_LIST_COL + 1,
widget->first_visible > 0 ? "..." : " " );
mvaddstr ( SETTINGS_LIST_ROW + SETTINGS_LIST_ROWS,
SETTINGS_LIST_COL + 1,
( widget->first_visible + SETTINGS_LIST_ROWS < NUM_SETTINGS
? "..."
: " " ) );
/* Draw visible settings. */
for ( i = 0; i < SETTINGS_LIST_ROWS; i++ ) {
if ( widget->first_visible + i < NUM_SETTINGS ) {
select_setting ( widget, widget->first_visible + i );
draw_setting ( widget );
} else {
clearmsg ( SETTINGS_LIST_ROW + i );
}
}
/* Set the widget to the current row, which will be redrawn
appropriately by the main loop. */
select_setting ( widget, n );
}
static int main_loop ( struct settings *settings ) { static int main_loop ( struct settings *settings ) {
struct setting_widget widget; struct setting_widget widget;
unsigned int current = 0; unsigned int current = 0;
unsigned int next; unsigned int next;
int i;
int key; int key;
int rc; int rc;
/* Print initial screen content */ /* Print initial screen content */
draw_title_row(); draw_title_row();
color_set ( CPAIR_NORMAL, NULL ); color_set ( CPAIR_NORMAL, NULL );
for ( i = ( NUM_SETTINGS - 1 ) ; i >= 0 ; i-- ) { init_widget ( &widget, settings );
init_setting_index ( &widget, settings, i );
draw_setting ( &widget );
}
while ( 1 ) { while ( 1 ) {
/* Redraw information and instruction rows */ /* Redraw information and instruction rows */
draw_info_row ( widget.setting ); draw_info_row ( widget.setting );
@ -385,11 +424,11 @@ static int main_loop ( struct settings *settings ) {
switch ( key ) { switch ( key ) {
case KEY_DOWN: case KEY_DOWN:
if ( next < ( NUM_SETTINGS - 1 ) ) if ( next < ( NUM_SETTINGS - 1 ) )
next++; reveal ( &widget, ++next );
break; break;
case KEY_UP: case KEY_UP:
if ( next > 0 ) if ( next > 0 )
next--; reveal ( &widget, --next ) ;
break; break;
case CTRL_X: case CTRL_X:
return 0; return 0;
@ -399,7 +438,7 @@ static int main_loop ( struct settings *settings ) {
} }
if ( next != current ) { if ( next != current ) {
draw_setting ( &widget ); draw_setting ( &widget );
init_setting_index ( &widget, settings, next ); select_setting ( &widget, next );
current = next; current = next;
} }
} }