jscrolledlist: hack to allow scroll before re-layout

This commit is contained in:
Lephenixnoir 2022-12-01 23:59:31 +01:00
parent 40ffe54250
commit f5d6fb2e87
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
3 changed files with 39 additions and 16 deletions

View File

@ -81,7 +81,11 @@ void jframe_set_visibility_margin(jframe *f, int margin_x, int margin_y);
If either dimension of the provided region is larger than the content size
of the frame minus the visibility margin, the center of the region will be
shown at the center of the view along that direciton. Otherwise, the view
will scroll the minimum amount possible to bring the region into view. */
void jframe_scroll_to_region(jframe *f, jrect region);
will scroll the minimum amount possible to bring the region into view.
If clamp is set to false, the frame will allow scrolling beyond current
boundaries, which is helpful as a hack when calling this function while a
layout is occuring. */
void jframe_scroll_to_region(jframe *f, jrect region, bool clamp);
#endif /* _J_JFRAME */

View File

@ -140,7 +140,7 @@ void jframe_set_visibility_margin(jframe *f, int margin_x, int margin_y)
// Scrolling
//---
void jframe_scroll_to_region(jframe *f, jrect region)
void jframe_scroll_to_region(jframe *f, jrect region, bool do_clamp)
{
jwidget *child = frame_child(f);
if(!child)
@ -180,8 +180,10 @@ void jframe_scroll_to_region(jframe *f, jrect region)
f->scroll_y = clamp(f->scroll_y, y2 - vp_y2, y1 - vp_y1);
/* Safety clamp */
f->scroll_x = clamp(f->scroll_x, 0, f->max_scroll_x);
f->scroll_y = clamp(f->scroll_y, 0, f->max_scroll_y);
if(do_clamp) {
f->scroll_x = clamp(f->scroll_x, 0, f->max_scroll_x);
f->scroll_y = clamp(f->scroll_y, 0, f->max_scroll_y);
}
f->widget.update = 1;
}

View File

@ -21,7 +21,6 @@ jscrolledlist *jscrolledlist_create(void *parent,
jwidget_init(&l->widget, jscrolledlist_type_id, parent);
jwidget_set_stretch(l, 1, 1, false);
jlayout_set_vbox(l);
l->frame = jframe_create(l);
jwidget_set_stretch(l->frame, 1, 1, false);
@ -33,31 +32,49 @@ jscrolledlist *jscrolledlist_create(void *parent,
return l;
}
static void shake_scroll(jscrolledlist *l, bool clamp)
{
int cursor = jlist_selected_item(l->list);
if(cursor >= 0) {
jrect r = jlist_selected_region(l->list);
jframe_scroll_to_region(l->frame, r, clamp);
}
}
//---
// Polymorphic widget operations
//---
static void jscrolledlist_poly_layout(void *l0)
{
jscrolledlist *l = l0;
l->frame->widget.x = 0;
l->frame->widget.y = 0;
l->frame->widget.w = jwidget_content_width(l);
l->frame->widget.h = jwidget_content_height(l);
shake_scroll(l, false);
}
static bool jscrolledlist_poly_event(void *l0, jevent e)
{
jscrolledlist *l = l0;
if((e.type == JLIST_SELECTION_MOVED || e.type == JLIST_MODEL_UPDATED)
&& e.source == l->list) {
int cursor = jlist_selected_item(l->list);
if(cursor >= 0) {
jrect r = jlist_selected_region(l->list);
jframe_scroll_to_region(l->frame, r);
/* Allow the event to propagate up */
return false;
}
}
if(e.type == JLIST_SELECTION_MOVED && e.source == l->list)
shake_scroll(l, true);
if(e.type == JLIST_MODEL_UPDATED && e.source == l->list)
shake_scroll(l, true);
/* Allow the evnts to bubble up */
return false;
}
/* jscrolledlist type definition */
static jwidget_poly type_jscrolledlist = {
.name = "jscrolledlist",
.layout = jscrolledlist_poly_layout,
.event = jscrolledlist_poly_event,
};