Compare commits

...

3 Commits

5 changed files with 47 additions and 18 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

@ -55,7 +55,11 @@ void jfkeys_set(jfkeys *f, char const *labels)
static char const *get_level(char const *labels, int level)
{
/* Navigate to level */
while(level > 0) labels = strchrnul(labels, '|');
while(level > 0) {
labels = strchrnul(labels, '|');
labels += (*labels == '|');
level--;
}
return (*labels == 0) ? NULL : labels;
}

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

@ -117,7 +117,9 @@ void jlist_update_model(jlist *l, int item_count)
if(l->item_count != item_count) {
l->items = realloc(l->items, item_count * sizeof *l->items);
if(!l->items) {
item_count = 0;
l->item_count = 0;
l->cursor = -1;
l->widget.dirty = 1;
return;
}
}

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,
};