From 4e01a99b0b49b03a4aa3405e4048f0562c19268b Mon Sep 17 00:00:00 2001 From: Lephenixnoir Date: Sun, 19 Jun 2022 22:45:05 +0100 Subject: [PATCH] jscene: add a stronger focus function --- include/justui/jscene.h | 8 ++++++++ include/justui/jwidget.h | 3 +++ src/jscene.c | 29 +++++++++++++++++++++++++++++ src/jwidget.c | 12 ++++++++++++ 4 files changed, 52 insertions(+) diff --git a/include/justui/jscene.h b/include/justui/jscene.h index 885460c..69a804a 100644 --- a/include/justui/jscene.h +++ b/include/justui/jscene.h @@ -87,6 +87,14 @@ void *jscene_focused_widget(jscene *scene); The selected widget, obviously, must be a descendant of the scene. */ void jscene_set_focused_widget(jscene *scene, void *widget); +/* jscene_show_and_focus(): Make a widget visible and focus it + This function does three things: + 1. Set the visibility of the target widget to [true] + 2. Configure any parent with a stacked layout to show the child that + contains the target widget + 3. Focus the target widget */ +void jscene_show_and_focus(jscene *scene, void *widget); + /* jscene_process_key_event(): Send a key event to the focused widget Returns true if the event was accepted, false if it was ignored. */ bool jscene_process_key_event(jscene *scene, key_event_t event); diff --git a/include/justui/jwidget.h b/include/justui/jwidget.h index d784d03..882fd44 100644 --- a/include/justui/jwidget.h +++ b/include/justui/jwidget.h @@ -204,6 +204,9 @@ void jwidget_insert_child(void *w, void *child, int position); (w) must be the parent of (child). The child is left without a parent. */ void jwidget_remove_child(void *w, void *child); +/* jwidget_child_position(): Find the position of a widget in the child list */ +int jwidget_child_position(void *w, void *child); + //--- // Sizing and stretching //--- diff --git a/src/jscene.c b/src/jscene.c index 17bb5de..8b5c1d2 100644 --- a/src/jscene.c +++ b/src/jscene.c @@ -138,6 +138,35 @@ void jscene_set_focused_widget(jscene *s, void *w0) (jevent){ .type = JWIDGET_FOCUS_IN, .source = w }); } +void jscene_show_and_focus(jscene *scene, void *w0) +{ + J_CAST(w) + + /* Ensure the widget is visible */ + jwidget_set_visible(w, true); + + /* Force stacked layouts all the wat up to [scene] to show [w] */ + jwidget *current = w; + jwidget *parent = w->parent; + + while(parent != (jwidget *)scene) { + jlayout_stack *stack = jlayout_get_stack(parent); + if(stack) { + int pos = jwidget_child_position(parent, current); + if(stack->active != pos) { + stack->active = pos; + parent->update = true; + } + } + + current = parent; + parent = current->parent; + } + + /* Give the widget focus */ + jscene_set_focused_widget(scene, w); +} + bool jscene_process_key_event(jscene *scene, key_event_t event) { jwidget *candidate = scene->focus; diff --git a/src/jwidget.c b/src/jwidget.c index 73ef8a8..c7b1973 100644 --- a/src/jwidget.c +++ b/src/jwidget.c @@ -249,6 +249,18 @@ void jwidget_remove_child(void *w0, void *child0) w->dirty = 1; } +int jwidget_child_position(void *w0, void *child0) +{ + J_CAST(w, child) + + for(int i = 0; i < w->child_count; i++) { + if(w->children[i] == child) + return i; + } + + return -1; +} + //--- // Sizing and stretching //---