Browse Source

[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>
tags/v1.20.1
Glenn Brown 14 years ago
parent
commit
f9bcb928f5
1 changed files with 77 additions and 38 deletions
  1. 77
    38
      src/hci/tui/settings_ui.c

+ 77
- 38
src/hci/tui/settings_ui.c View File

@@ -45,6 +45,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
45 45
 #define TITLE_ROW		1
46 46
 #define SETTINGS_LIST_ROW	3
47 47
 #define SETTINGS_LIST_COL	1
48
+#define SETTINGS_LIST_ROWS	16
48 49
 #define INFO_ROW		20
49 50
 #define ALERT_ROW		20
50 51
 #define INSTRUCTION_ROW		22
@@ -65,6 +66,8 @@ struct setting_row {
65 66
 struct setting_widget {
66 67
 	/** Settings block */
67 68
 	struct settings *settings;
69
+        /** Index of the first visible setting, for scrolling. */
70
+	unsigned int first_visible;
68 71
 	/** Configuration setting */
69 72
 	struct setting *setting;
70 73
 	/** Screen row */
@@ -84,15 +87,13 @@ struct setting_widget {
84 87
 
85 88
 static void load_setting ( struct setting_widget *widget ) __nonnull;
86 89
 static int save_setting ( struct setting_widget *widget ) __nonnull;
87
-static void init_setting ( struct setting_widget *widget,
88
-                           struct settings *settings,
89
-                           struct setting *setting,
90
-                           unsigned int row, unsigned int col ) __nonnull;
90
+static void init_widget ( struct setting_widget *widget,
91
+                           struct settings *settings ) __nonnull;
91 92
 static void draw_setting ( struct setting_widget *widget ) __nonnull;
92 93
 static int edit_setting ( struct setting_widget *widget, int key ) __nonnull;
93
-static void init_setting_index ( struct setting_widget *widget,
94
-                                 struct settings *settings,
95
-                                 unsigned int index ) __nonnull;
94
+static void select_setting ( struct setting_widget *widget,
95
+			     unsigned int index ) __nonnull;
96
+static void reveal ( struct setting_widget *widget, unsigned int n) __nonnull;
96 97
 static void vmsg ( unsigned int row, const char *fmt, va_list args ) __nonnull;
97 98
 static void msg ( unsigned int row, const char *fmt, ... ) __nonnull;
98 99
 static void valert ( const char *fmt, va_list args ) __nonnull;
@@ -135,28 +136,17 @@ static int save_setting ( struct setting_widget *widget ) {
135 136
 }
136 137
 
137 138
 /**
138
- * Initialise setting widget
139
+ * Initialise the scrolling setting widget, drawing initial display.
139 140
  *
140 141
  * @v widget		Setting widget
141 142
  * @v settings		Settings block
142
- * @v setting		Configuration setting
143
- * @v row		Screen row
144
- * @v col		Screen column
145 143
  */
146
-static void init_setting ( struct setting_widget *widget,
147
-			   struct settings *settings,
148
-			   struct setting *setting,
149
-			   unsigned int row, unsigned int col ) {
150
-
151
-	/* Initialise widget structure */
144
+static void init_widget ( struct setting_widget *widget,
145
+			  struct settings *settings ) {
152 146
 	memset ( widget, 0, sizeof ( *widget ) );
153 147
 	widget->settings = settings;
154
-	widget->setting = setting;
155
-	widget->row = row;
156
-	widget->col = col;
157
-
158
-	/* Read current setting value */
159
-	load_setting ( widget );
148
+	widget->first_visible = SETTINGS_LIST_ROWS;
149
+	reveal ( widget, 0 );
160 150
 }
161 151
 
162 152
 /**
@@ -212,19 +202,25 @@ static int edit_setting ( struct setting_widget *widget, int key ) {
212 202
 }
213 203
 
214 204
 /**
215
- * Initialise setting widget by index
205
+ * Select a setting for display updates, by index.
216 206
  *
217 207
  * @v widget		Setting widget
218 208
  * @v settings		Settings block
219 209
  * @v index		Index of setting with settings list
220 210
  */
221
-static void init_setting_index ( struct setting_widget *widget,
222
-				 struct settings *settings,
223
-				 unsigned int index ) {
211
+static void select_setting ( struct setting_widget *widget,
212
+			     unsigned int index ) {
224 213
 	struct setting *all_settings = table_start ( SETTINGS );
214
+	unsigned int skip = offsetof ( struct setting_widget, setting );
215
+
216
+	/* Reset the widget, preserving static state. */
217
+	memset ( ( char * ) widget + skip, 0, sizeof ( *widget ) - skip );
218
+	widget->setting = &all_settings[index];
219
+	widget->row = SETTINGS_LIST_ROW + index - widget->first_visible;
220
+	widget->col = SETTINGS_LIST_COL;
225 221
 
226
-	init_setting ( widget, settings, &all_settings[index],
227
-		       ( SETTINGS_LIST_ROW + index ), SETTINGS_LIST_COL );
222
+	/* Read current setting value */
223
+	load_setting ( widget );
228 224
 }
229 225
 
230 226
 /**
@@ -334,22 +330,65 @@ static void draw_instruction_row ( int editing ) {
334 330
 	}
335 331
 }
336 332
 
333
+/**
334
+ * Reveal a setting by index: Scroll the setting list to reveal the
335
+ * specified setting.
336
+ *
337
+ * @widget	The main loop's display widget.
338
+ * @n		The index of the setting to reveal.
339
+ */
340
+static void reveal ( struct setting_widget *widget, unsigned int n)
341
+{
342
+	unsigned int i;
343
+
344
+	/* Simply return if setting N is already on-screen. */
345
+	if ( n - widget->first_visible < SETTINGS_LIST_ROWS )
346
+		return;
347
+	
348
+	/* Jump scroll to make the specified setting visible. */
349
+	while ( widget->first_visible < n )
350
+		widget->first_visible += SETTINGS_LIST_ROWS;
351
+	while ( widget->first_visible > n )
352
+		widget->first_visible -= SETTINGS_LIST_ROWS;
353
+	
354
+	/* Draw elipses before and/or after the settings list to
355
+	   represent any invisible settings. */
356
+	mvaddstr ( SETTINGS_LIST_ROW - 1,
357
+		   SETTINGS_LIST_COL + 1,
358
+		   widget->first_visible > 0 ? "..." : "   " );
359
+	mvaddstr ( SETTINGS_LIST_ROW + SETTINGS_LIST_ROWS,
360
+		   SETTINGS_LIST_COL + 1,
361
+		   ( widget->first_visible + SETTINGS_LIST_ROWS < NUM_SETTINGS
362
+		     ? "..."
363
+		     : "   " ) );
364
+	
365
+	/* Draw visible settings. */
366
+	for ( i = 0; i < SETTINGS_LIST_ROWS; i++ ) {
367
+		if ( widget->first_visible + i < NUM_SETTINGS ) {
368
+			select_setting ( widget, widget->first_visible + i );
369
+			draw_setting ( widget );
370
+		} else {
371
+			clearmsg ( SETTINGS_LIST_ROW + i );
372
+		}
373
+	}
374
+
375
+	/* Set the widget to the current row, which will be redrawn
376
+	   appropriately by the main loop. */
377
+	select_setting ( widget, n );
378
+}
379
+
337 380
 static int main_loop ( struct settings *settings ) {
338 381
 	struct setting_widget widget;
339 382
 	unsigned int current = 0;
340 383
 	unsigned int next;
341
-	int i;
342 384
 	int key;
343 385
 	int rc;
344 386
 
345 387
 	/* Print initial screen content */
346 388
 	draw_title_row();
347 389
 	color_set ( CPAIR_NORMAL, NULL );
348
-	for ( i = ( NUM_SETTINGS - 1 ) ; i >= 0 ; i-- ) {
349
-		init_setting_index ( &widget, settings, i );
350
-		draw_setting ( &widget );
351
-	}
352
-
390
+	init_widget ( &widget, settings );
391
+	
353 392
 	while ( 1 ) {
354 393
 		/* Redraw information and instruction rows */
355 394
 		draw_info_row ( widget.setting );
@@ -385,11 +424,11 @@ static int main_loop ( struct settings *settings ) {
385 424
 			switch ( key ) {
386 425
 			case KEY_DOWN:
387 426
 				if ( next < ( NUM_SETTINGS - 1 ) )
388
-					next++;
427
+					reveal ( &widget, ++next );
389 428
 				break;
390 429
 			case KEY_UP:
391 430
 				if ( next > 0 )
392
-					next--;
431
+					reveal ( &widget, --next ) ;
393 432
 				break;
394 433
 			case CTRL_X:
395 434
 				return 0;
@@ -399,7 +438,7 @@ static int main_loop ( struct settings *settings ) {
399 438
 			}	
400 439
 			if ( next != current ) {
401 440
 				draw_setting ( &widget );
402
-				init_setting_index ( &widget, settings, next );
441
+				select_setting ( &widget, next );
403 442
 				current = next;
404 443
 			}
405 444
 		}

Loading…
Cancel
Save