void glw_layout0(glw_t *w, glw_rctx_t *rc) { glw_root_t *gr = w->glw_root; LIST_REMOVE(w, glw_active_link); LIST_INSERT_HEAD(&gr->gr_active_list, w, glw_active_link); if(!(w->glw_flags & GLW_ACTIVE)) { w->glw_flags |= GLW_ACTIVE; glw_signal0(w, GLW_SIGNAL_ACTIVE, NULL); } glw_signal0(w, GLW_SIGNAL_LAYOUT, rc); }
static void mod_flags1(glw_t *w, int set, int clr) { set &= ~w->glw_flags; // Mask out already set flags w->glw_flags |= set; if(set & GLW_HIDDEN) glw_signal0(w->glw_parent, GLW_SIGNAL_CHILD_HIDDEN, w); clr &= w->glw_flags; w->glw_flags &= ~clr; if(clr & GLW_HIDDEN) glw_signal0(w->glw_parent, GLW_SIGNAL_CHILD_UNHIDDEN, w); }
static int slider_bound_callback(glw_t *w, void *opaque, glw_signal_t signal, void *extra) { glw_slider_t *s = opaque; glw_slider_metrics_t *m = extra; switch(signal) { case GLW_SIGNAL_DESTROY: s->bound_widget = NULL; break; case GLW_SIGNAL_SLIDER_METRICS: s->fixed_knob_size = 1; s->value = m->position; s->interpolate = 0; s->knob_size_fixed = m->knob_size; if((s->knob_size_fixed != 1.0) == !(s->w.glw_flags & GLW_CAN_SCROLL)) { s->w.glw_flags ^= GLW_CAN_SCROLL; glw_signal0(&s->w, GLW_SIGNAL_CAN_SCROLL_CHANGED, NULL); } break; default: break; } return 0; }
static int glw_image_callback(glw_t *w, void *opaque, glw_signal_t signal, void *extra) { glw_t *c; switch(signal) { default: break; case GLW_SIGNAL_LAYOUT: glw_image_layout(w, extra); break; case GLW_SIGNAL_EVENT: TAILQ_FOREACH(c, &w->glw_childs, glw_parent_link) if(glw_signal0(c, GLW_SIGNAL_EVENT, extra)) return 1; break; case GLW_SIGNAL_CHILD_CONSTRAINTS_CHANGED: case GLW_SIGNAL_CHILD_CREATED: glw_image_update_constraints((glw_image_t *)w); return 1; case GLW_SIGNAL_CHILD_DESTROYED: glw_set_constraints(w, 0, 0, 0, 0); return 1; } return 0; }
int glw_navigate_move(glw_t *w, int steps) { glw_move_op_t mop = {0}; mop.steps = steps; glw_signal0(w, GLW_SIGNAL_MOVE, &mop); return mop.did_move; }
static void update_value_delta(glw_slider_t *s, float d) { if(s->p != NULL) prop_add_float(s->p, d * (s->max - s->min)); else { s->value = GLW_MAX(s->min, GLW_MIN(s->max, s->value + d)); if(s->bound_widget != NULL) { glw_scroll_t gs; gs.value = s->value; glw_signal0(s->bound_widget, GLW_SIGNAL_SCROLL, &gs); } } }
int glw_navigate_may_wrap(glw_t *w) { if(!(w->glw_flags2 & GLW2_NAV_WRAP)) { return 0; } if(!glw_settings.gs_wrap) { return 0; } int may_wrap = 1; glw_signal0(w, GLW_SIGNAL_WRAP_CHECK, &may_wrap); return may_wrap; }
void glw_scroll_update_metrics(glw_scroll_control_t *gsc, glw_t *w) { float v; int do_update = 0; w->glw_flags &= ~GLW_UPDATE_METRICS; v = GLW_MIN(1.0f, (float)gsc->page_size / gsc->total_size); if(v != gsc->metrics.knob_size) { do_update = 1; gsc->metrics.knob_size = v; } v = GLW_MAX(0, (float)gsc->target_pos / (gsc->total_size - gsc->page_size + gsc->scroll_threshold_post)); if(v != gsc->metrics.position) { do_update = 1; gsc->metrics.position = v; } if(!do_update) return; if(gsc->total_size > gsc->page_size && !(w->glw_flags & GLW_CAN_SCROLL)) { w->glw_flags |= GLW_CAN_SCROLL; glw_signal0(w, GLW_SIGNAL_CAN_SCROLL_CHANGED, NULL); } else if(gsc->total_size <= gsc->page_size && w->glw_flags & GLW_CAN_SCROLL) { w->glw_flags &= ~GLW_CAN_SCROLL; glw_signal0(w, GLW_SIGNAL_CAN_SCROLL_CHANGED, NULL); } glw_signal0(w, GLW_SIGNAL_SLIDER_METRICS, &gsc->metrics); }
static void update_value(glw_slider_t *s, float v, int how) { v = GLW_MAX(0, GLW_MIN(1.0, v)); if(s->p != NULL) prop_set_float_ex(s->p, NULL, v * (s->max - s->min) + s->min, how); else { s->value = v; if(s->bound_widget != NULL) { glw_scroll_t gs; gs.value = s->value; glw_signal0(s->bound_widget, GLW_SIGNAL_SCROLL, &gs); } } }
static void update_value_delta(glw_slider_t *s, float d) { if(s->p != NULL) { s->interpolate = 2; prop_add_float(s->p, d * (s->max - s->min)); } else { s->value = GLW_MAX(s->min, GLW_MIN(s->max, s->value + d)); s->interpolate = 1; if(s->bound_widget != NULL) { glw_scroll_t gs; gs.value = s->value; glw_signal0(s->bound_widget, GLW_SIGNAL_SCROLL, &gs); } glw_need_refresh(s->w.glw_root, 0); } }
void glw_scroll_suggest_focus(glw_scroll_control_t *gsc, glw_t *w, glw_t *c) { if(!glw_is_focused(w)) { w->glw_focused = c; glw_signal0(w, GLW_SIGNAL_FOCUS_CHILD_INTERACTIVE, c); gsc->scroll_to_me = c; return; } if(gsc->suggested == w->glw_focused || gsc->suggest_cnt > 0) { c = glw_focus_by_path(c); if(c != NULL) glw_focus_set(c->glw_root, c, GLW_FOCUS_SET_SUGGESTED, "Suggested"); gsc->suggest_cnt = 1; } gsc->suggested = c; gsc->suggest_cnt++; }
void glw_scroll_handle_scroll(glw_scroll_control_t *gsc, glw_t *w, glw_scroll_t *gs) { int top = GLW_MAX(gs->value * (gsc->total_size - gsc->page_size + gsc->scroll_threshold_post), 0); gsc->target_pos = top; glw_schedule_refresh(w->glw_root, 0); if(gsc->chase_focus == 0) return; glw_t *c = w->glw_class->gc_find_visible_child(w); if(c == NULL) return; if(glw_is_focused(w)) { glw_focus_set(w->glw_root, c, GLW_FOCUS_SET_SUGGESTED, "Scroll"); } else { w->glw_focused = c; glw_signal0(w, GLW_SIGNAL_FOCUS_CHILD_INTERACTIVE, c); } }
static void glw_image_layout(glw_t *w, glw_rctx_t *rc) { glw_image_t *gi = (void *)w; glw_root_t *gr = w->glw_root; glw_loadable_texture_t *glt; glw_rctx_t rc0; glw_t *c; int hq = (w->glw_class == &glw_icon || w->glw_class == &glw_image); if(gi->gi_pending_url != NULL) { // Request to load int xs = -1, ys = -1; int flags = 0; gi->gi_loading_new_url = 1; if(gi->gi_pending != NULL) { glw_tex_deref(w->glw_root, gi->gi_pending); gi->gi_pending = NULL; } if(rstr_get(gi->gi_pending_url)[0] == 0) { // Empty string, unload all if(gi->gi_current != NULL) { glw_tex_deref(w->glw_root, gi->gi_current); gi->gi_current = NULL; } gi->gi_update = 1; } else { if(w->glw_class == &glw_repeatedimage) flags |= GLW_TEX_REPEAT; if(hq) { if(rc->rc_width < rc->rc_height) { xs = rc->rc_width; } else { ys = rc->rc_height; } } if(xs && ys) { if(w->glw_flags & GLW_DEBUG) TRACE(TRACE_DEBUG, "IMG", "Loading texture: %s", rstr_get(gi->gi_pending_url)); gi->gi_pending = glw_tex_create(w->glw_root, gi->gi_pending_url, flags, xs, ys); rstr_release(gi->gi_pending_url); gi->gi_pending_url = NULL; } } } if((glt = gi->gi_pending) != NULL) { glw_tex_layout(gr, glt); if(glw_is_tex_inited(&glt->glt_texture) || glt->glt_state == GLT_STATE_ERROR) { // Pending texture completed, ok or error: transfer to current if(gi->gi_current != NULL) glw_tex_deref(w->glw_root, gi->gi_current); gi->gi_current = gi->gi_pending; gi->gi_pending = NULL; gi->gi_update = 1; gi->gi_loading_new_url = 0; } } if((glt = gi->gi_current) == NULL) return; if(gi->gi_loading_new_url) { gi->gi_autofade = GLW_LP(8, gi->gi_autofade, 0); } else { gi->gi_autofade = GLW_LP(8, gi->gi_autofade, 1); } glw_tex_layout(gr, glt); if(glt->glt_state == GLT_STATE_ERROR) { if(!gi->gi_is_ready) { gi->gi_is_ready = 1; glw_signal0(w, GLW_SIGNAL_READINESS, NULL); } } else if(glw_is_tex_inited(&glt->glt_texture)) { int r = !gi->gi_loading_new_url; if(gi->gi_is_ready != r) { gi->gi_is_ready = r; glw_signal0(w, GLW_SIGNAL_READINESS, NULL); } if(gi->gi_update) { gi->gi_update = 0; glw_renderer_free(&gi->gi_gr); switch(gi->gi_mode) { case GI_MODE_NORMAL: glw_renderer_init_quad(&gi->gi_gr); glw_image_layout_normal(gr, rc, gi, glt); break; case GI_MODE_BORDER_SCALING: glw_renderer_init(&gi->gi_gr, 16, 18, borderobject); glw_image_layout_tesselated(gr, rc, gi, glt); break; case GI_MODE_REPEATED_TEXTURE: glw_renderer_init_quad(&gi->gi_gr); glw_image_layout_repeated(gr, rc, gi, glt); break; case GI_MODE_ALPHA_EDGES: glw_renderer_init(&gi->gi_gr, 16, 18, borderobject); glw_image_layout_alpha_edges(gr, rc, gi, glt); break; case GI_MODE_BORDER_ONLY_SCALING: glw_renderer_init(&gi->gi_gr, 16, 16, borderonlyobject); glw_image_layout_tesselated(gr, rc, gi, glt); break; default: abort(); } } else if(gi->gi_last_width != rc->rc_width || gi->gi_last_height != rc->rc_height) { gi->gi_last_width = rc->rc_width; gi->gi_last_height = rc->rc_height; switch(gi->gi_mode) { case GI_MODE_NORMAL: break; case GI_MODE_BORDER_SCALING: case GI_MODE_BORDER_ONLY_SCALING: glw_image_layout_tesselated(gr, rc, gi, glt); break; case GI_MODE_REPEATED_TEXTURE: glw_image_layout_repeated(gr, rc, gi, glt); break; case GI_MODE_ALPHA_EDGES: glw_image_layout_alpha_edges(gr, rc, gi, glt); break; } gi->gi_need_reload = hq; } if(gi->gi_need_reload && gi->gi_pending == NULL && gi->gi_pending_url == NULL && rc->rc_width && rc->rc_height) { gi->gi_need_reload = 0; int xs = -1, ys = -1, rescale; if(rc->rc_width < rc->rc_height) { rescale = rc->rc_width != glt->glt_xs; xs = rc->rc_width; } else { rescale = rc->rc_height != glt->glt_ys; ys = rc->rc_height; } if(rescale) { int flags = 0; if(w->glw_class == &glw_repeatedimage) flags |= GLW_TEX_REPEAT; gi->gi_pending = glw_tex_create(w->glw_root, glt->glt_url, flags, xs, ys); } } } else { if(gi->gi_is_ready) { gi->gi_is_ready = 0; glw_signal0(w, GLW_SIGNAL_READINESS, NULL); } } glw_image_update_constraints(gi); if((c = TAILQ_FIRST(&w->glw_childs)) != NULL) { rc0 = *rc; rc0.rc_width -= gi->gi_box_left + gi->gi_box_right; rc0.rc_height -= gi->gi_box_top + gi->gi_box_bottom; if(rc0.rc_height >= 0 && rc0.rc_width >= 0) glw_layout0(c, &rc0); } }
static void glw_image_layout(glw_t *w, glw_rctx_t *rc) { glw_image_t *gi = (void *)w; glw_root_t *gr = w->glw_root; glw_loadable_texture_t *glt; glw_rctx_t rc0; glw_t *c; if(gi->gi_pending_filename != NULL) { // Request to load int xs = -1, ys = -1; int flags = 0; if(gi->gi_pending != NULL) glw_tex_deref(w->glw_root, gi->gi_pending); if(gi->gi_pending_filename[0] == 0) { gi->gi_pending = NULL; if(gi->gi_current != NULL) { glw_tex_deref(w->glw_root, gi->gi_current); gi->gi_current = NULL; } gi->gi_update = 1; } else { if(w->glw_class == &glw_repeatedimage) flags |= GLW_TEX_REPEAT; if(gi->gi_bitmap_flags & GLW_IMAGE_HQ_SCALING) { if(rc->rc_width < rc->rc_height) { xs = rc->rc_width; } else { ys = rc->rc_height; } } if(xs && ys) { gi->gi_pending = glw_tex_create(w->glw_root, gi->gi_pending_filename, flags, xs, ys); free(gi->gi_pending_filename); gi->gi_pending_filename = NULL; } else { gi->gi_pending = NULL; } } } if((glt = gi->gi_pending) != NULL) { glw_tex_layout(gr, glt); if(glt->glt_state == GLT_STATE_VALID || glt->glt_state == GLT_STATE_ERROR) { // Pending texture completed, ok or error: transfer to current if(gi->gi_current != NULL) glw_tex_deref(w->glw_root, gi->gi_current); gi->gi_current = gi->gi_pending; gi->gi_pending = NULL; gi->gi_update = 1; } } if((glt = gi->gi_current) == NULL) return; glw_tex_layout(gr, glt); if(glt->glt_state == GLT_STATE_ERROR) { if(!gi->gi_was_valid) { glw_signal0(w, GLW_SIGNAL_READY, NULL); gi->gi_was_valid = 1; } } else if(glt->glt_state == GLT_STATE_VALID) { if(!gi->gi_was_valid) { glw_signal0(w, GLW_SIGNAL_READY, NULL); gi->gi_was_valid = 1; } if(gi->gi_update) { gi->gi_update = 0; glw_renderer_free(&gi->gi_gr); switch(gi->gi_mode) { case GI_MODE_NORMAL: glw_renderer_init_quad(&gi->gi_gr); glw_image_layout_normal(gr, rc, gi, glt); break; case GI_MODE_BORDER_SCALING: glw_renderer_init(&gi->gi_gr, 16, 18, borderobject); glw_image_layout_tesselated(gr, rc, gi, glt); break; case GI_MODE_REPEATED_TEXTURE: glw_renderer_init_quad(&gi->gi_gr); glw_image_layout_repeated(gr, rc, gi, glt); break; case GI_MODE_ALPHA_EDGES: glw_renderer_init(&gi->gi_gr, 16, 18, borderobject); glw_image_layout_alpha_edges(gr, rc, gi, glt); break; case GI_MODE_BORDER_ONLY_SCALING: glw_renderer_init(&gi->gi_gr, 16, 16, borderonlyobject); glw_image_layout_tesselated(gr, rc, gi, glt); break; default: abort(); } } else if(gi->gi_last_width != rc->rc_width || gi->gi_last_height != rc->rc_height) { gi->gi_last_width = rc->rc_width; gi->gi_last_height = rc->rc_height; switch(gi->gi_mode) { case GI_MODE_NORMAL: break; case GI_MODE_BORDER_SCALING: case GI_MODE_BORDER_ONLY_SCALING: glw_image_layout_tesselated(gr, rc, gi, glt); break; case GI_MODE_REPEATED_TEXTURE: glw_image_layout_repeated(gr, rc, gi, glt); break; case GI_MODE_ALPHA_EDGES: glw_image_layout_alpha_edges(gr, rc, gi, glt); break; } if(gi->gi_bitmap_flags & GLW_IMAGE_HQ_SCALING && gi->gi_pending == NULL && gi->gi_pending_filename == NULL && rc->rc_width && rc->rc_height) { int xs = -1, ys = -1, rescale; if(rc->rc_width < rc->rc_height) { rescale = abs(rc->rc_width - glt->glt_xs) > glt->glt_xs / 10; xs = rc->rc_width; } else { rescale = abs(rc->rc_height - glt->glt_ys) > glt->glt_ys / 10; ys = rc->rc_height; } if(rescale) { int flags = 0; if(w->glw_class == &glw_repeatedimage) flags |= GLW_TEX_REPEAT; gi->gi_pending = glw_tex_create(w->glw_root, glt->glt_filename, flags, xs, ys); } } } } glw_image_update_constraints(gi); if((c = TAILQ_FIRST(&w->glw_childs)) != NULL) { rc0 = *rc; rc0.rc_width -= gi->gi_box_left + gi->gi_box_right; rc0.rc_height -= gi->gi_box_top + gi->gi_box_bottom; if(rc0.rc_height >= 0 && rc0.rc_width >= 0) glw_layout0(c, &rc0); } }