diff options
| author | Přemysl Eric Janouch <p@janouch.name> | 2023-06-15 11:42:29 +0200 | 
|---|---|---|
| committer | Přemysl Eric Janouch <p@janouch.name> | 2023-06-15 12:35:43 +0200 | 
| commit | 5d5f73f22f4802ff1cc3a6895d1e6009337b9ffe (patch) | |
| tree | f231c7e9f4095e35b847cf064e023b98a8439ee7 | |
| parent | 4a9e621d923290c8f5f62ed237427cee83de8b5d (diff) | |
| download | nncmpp-5d5f73f22f4802ff1cc3a6895d1e6009337b9ffe.tar.gz nncmpp-5d5f73f22f4802ff1cc3a6895d1e6009337b9ffe.tar.xz nncmpp-5d5f73f22f4802ff1cc3a6895d1e6009337b9ffe.zip | |
Don't layout during rendering
| -rw-r--r-- | nncmpp.c | 101 | 
1 files changed, 46 insertions, 55 deletions
| @@ -1182,9 +1182,6 @@ struct widget;  /// Draw a widget on the window  typedef void (*widget_render_fn) (struct widget *self); -/// Extract the contents of container widgets -typedef struct widget *(*widget_sublayout_fn) (struct widget *self); -  /// A minimal abstraction appropriate for both TUI and GUI widgets.  /// Units for the widget's region are frontend-specific.  /// Having this as a linked list simplifies layouting and memory management. @@ -1198,7 +1195,7 @@ struct widget  	int height;                         ///< Height, initialized by UI methods  	widget_render_fn on_render;         ///< Render callback -	widget_sublayout_fn on_sublayout;   ///< Optional sublayout callback +	struct widget *children;            ///< Child widgets of containers  	chtype attrs;                       ///< Rendition, in Curses terms  	short id;                           ///< Post-layouting identification @@ -1231,6 +1228,23 @@ struct ui  	bool have_icons;  }; +static void +widget_destroy (struct widget *self) +{ +	LIST_FOR_EACH (struct widget, w, self->children) +		widget_destroy (w); +	free (self); +} + +static void +widget_move (struct widget *w, int dx, int dy) +{ +	w->x += dx; +	w->y += dy; +	LIST_FOR_EACH (struct widget, child, w->children) +		widget_move (child, dx, dy); +} +  /// Replaces negative widths amongst widgets in the sublist by redistributing  /// any width remaining after all positive claims are satisfied from "width".  /// Also unifies heights to the maximum value of the run, and returns it. @@ -1265,7 +1279,7 @@ widget_redistribute (struct widget *head, int width)  	int x = 0;  	LIST_FOR_EACH (struct widget, w, head)  	{ -		w->x = x; +		widget_move (w, x - w->x, 0);  		x += w->width;  	}  	return max_height; @@ -1801,7 +1815,7 @@ app_append_layout (struct layout *l, struct layout *dest)  	{  		// Assuming there is no unclaimed vertical space.  		LIST_FOR_EACH (struct widget, w, l->head) -			w->y = last->y + last->height; +			widget_move (w, 0, last->y + last->height - w->y);  		last->next = l->head;  		l->head->prev = last; @@ -2176,44 +2190,35 @@ app_layout_row (struct tab *tab, int item_index)  	return l;  } -// XXX: This isn't a very clean design, in that part of layouting -//   is done during the rendering stage. -static struct widget * -app_sublayout_list (struct widget *list) +static void +app_layout_view (struct layout *out, int height)  { +	struct layout l = {}; +	struct widget *list = app_push_fill (&l, g.ui->list ()); +	list->id = WIDGET_LIST; +	list->height = height; +	list->width = g.ui_width; +  	struct tab *tab = g.active_tab; +	if ((int) tab->item_count * g.ui_vunit > list->height) +	{ +		struct widget *scrollbar = g.ui->scrollbar (APP_ATTR (SCROLLBAR)); +		list->width -= scrollbar->width; +		app_push (&l, scrollbar)->id = WIDGET_SCROLLBAR; +	} +  	int to_show = MIN ((int) tab->item_count - tab->item_top,  		ceil ((double) list->height / g.ui_vunit)); -	struct layout l = {}; +	struct layout children = {};  	for (int row = 0; row < to_show; row++)  	{  		int item_index = tab->item_top + row;  		struct layout subl = app_layout_row (tab, item_index); -		app_flush_layout_full (&subl, list->width, &l); -	} -	LIST_FOR_EACH (struct widget, w, l.head) -	{ -		w->x += list->x; -		w->y += list->y; -	} -	return l.head; -} - -static void -app_layout_view (struct layout *out, int height) -{ -	struct layout l = {}; -	struct widget *w = app_push_fill (&l, g.ui->list ()); -	w->id = WIDGET_LIST; -	w->height = height; - -	struct tab *tab = g.active_tab; -	if ((int) tab->item_count * g.ui_vunit > w->height) -	{ -		app_push (&l, g.ui->scrollbar (APP_ATTR (SCROLLBAR))) -			->id = WIDGET_SCROLLBAR; +		// TODO: Change layouting so that we don't need to know list->width. +		app_flush_layout_full (&subl, list->width, &children);  	} +	list->children = children.head;  	app_flush_layout (&l, out);  } @@ -2407,7 +2412,7 @@ app_on_refresh (void *user_data)  		available_height -= bottom.tail->y + bottom.tail->height;  	LIST_FOR_EACH (struct widget, w, g.widgets.head) -		free (w); +		widget_destroy (w);  	g.widgets = (struct layout) {};  	app_append_layout (&top, &g.widgets); @@ -2645,7 +2650,7 @@ incremental_search_on_changed (void)  		LIST_FOR_EACH (struct widget, w, tab->on_item_layout (index).head)  		{  			str_append (&s, w->text); -			free (w); +			widget_destroy (w);  		}  		size_t len; @@ -5706,11 +5711,8 @@ tui_make_scrollbar (chtype attrs)  static void  tui_render_list (struct widget *self)  { -	LIST_FOR_EACH (struct widget, w, self->on_sublayout (self)) -	{ +	LIST_FOR_EACH (struct widget, w, self->children)  		w->on_render (w); -		free (w); -	}  }  static struct widget * @@ -5720,7 +5722,6 @@ tui_make_list (void)  	w->width = -1;  	w->height = g.active_tab->item_count;  	w->on_render = tui_render_list; -	w->on_sublayout = app_sublayout_list;  	return w;  } @@ -6490,11 +6491,8 @@ x11_render_list (struct widget *self)  		&(XRectangle) { self->x, self->y, self->width, self->height }, 1);  	x11_render_padding (self); -	LIST_FOR_EACH (struct widget, w, self->on_sublayout (self)) -	{ +	LIST_FOR_EACH (struct widget, w, self->children)  		w->on_render (w); -		free (w); -	}  	XftDrawSetClip (g.xft_draw, None);  } @@ -6504,7 +6502,6 @@ x11_make_list (void)  {  	struct widget *w = xcalloc (1, sizeof *w + 1);  	w->on_render = x11_render_list; -	w->on_sublayout = app_sublayout_list;  	return w;  } @@ -6782,15 +6779,9 @@ x11_find_text (struct widget *list, int x, int y)  	if (!target)  		return NULL; -	if (target->on_sublayout) -	{ -		struct widget *sublist = target->on_sublayout (target); -		char *result = x11_find_text (sublist, x, y); -		LIST_FOR_EACH (struct widget, w, sublist) -			free (w); -		if (result) -			return result; -	} +	char *result = x11_find_text (target->children, x, y); +	if (result) +		return result;  	return xstrdup (target->text);  } | 
