From 911730493decadef194853bcc54eb141b2d2cb69 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 14 Jan 2024 13:21:36 -0500 Subject: [PATCH] node-editor: Add an auto-reload property This is not exposed anywhere yet. --- demos/node-editor/node-editor-window.c | 218 +++++++++++++++++-------- 1 file changed, 148 insertions(+), 70 deletions(-) diff --git a/demos/node-editor/node-editor-window.c b/demos/node-editor/node-editor-window.c index 69ffe26697..8c40181ff3 100644 --- a/demos/node-editor/node-editor-window.c +++ b/demos/node-editor/node-editor-window.c @@ -68,6 +68,7 @@ struct _NodeEditorWindow GArray *errors; guint update_timeout; + gboolean auto_reload; }; struct _NodeEditorWindowClass @@ -75,6 +76,13 @@ struct _NodeEditorWindowClass GtkApplicationWindowClass parent_class; }; +enum { + PROP_AUTO_RELOAD = 1, + NUM_PROPERTIES +}; + +static GParamSpec *properties[NUM_PROPERTIES] = { NULL, }; + G_DEFINE_TYPE(NodeEditorWindow, node_editor_window, GTK_TYPE_APPLICATION_WINDOW); static void @@ -167,19 +175,84 @@ text_iter_skip_whitespace_backward (GtkTextIter *iter) } static void -text_changed (GtkTextBuffer *buffer, - NodeEditorWindow *self) +highlight_text (NodeEditorWindow *self) +{ + GtkTextIter iter; + GtkTextIter start, end; + + gtk_text_buffer_get_start_iter (self->text_buffer, &iter); + + while (!gtk_text_iter_is_end (&iter)) + { + gunichar c = gtk_text_iter_get_char (&iter); + + if (c == '{') + { + GtkTextIter word_end = iter; + GtkTextIter word_start; + + gtk_text_iter_backward_char (&word_end); + text_iter_skip_whitespace_backward (&word_end); + + word_start = word_end; + gtk_text_iter_backward_word_start (&word_start); + text_iter_skip_alpha_backward (&word_start); + + gtk_text_buffer_apply_tag_by_name (self->text_buffer, "nodename", &word_start, &word_end); + } + else if (c == ':') + { + GtkTextIter word_end = iter; + GtkTextIter word_start; + + gtk_text_iter_backward_char (&word_end); + text_iter_skip_whitespace_backward (&word_end); + + word_start = word_end; + gtk_text_iter_backward_word_start (&word_start); + text_iter_skip_alpha_backward (&word_start); + + gtk_text_buffer_apply_tag_by_name (self->text_buffer, "propname", &word_start, &word_end); + } + else if (c == '"') + { + GtkTextIter string_start = iter; + GtkTextIter string_end = iter; + + gtk_text_iter_forward_char (&iter); + while (!gtk_text_iter_is_end (&iter)) + { + c = gtk_text_iter_get_char (&iter); + + if (c == '"') + { + gtk_text_iter_forward_char (&iter); + string_end = iter; + break; + } + + gtk_text_iter_forward_char (&iter); + } + + gtk_text_buffer_apply_tag_by_name (self->text_buffer, "string", &string_start, &string_end); + } + + gtk_text_iter_forward_char (&iter); + } + + gtk_text_buffer_get_bounds (self->text_buffer, &start, &end); + gtk_text_buffer_apply_tag_by_name (self->text_buffer, "no-hyphens", &start, &end); +} + +static void +reload (NodeEditorWindow *self) { char *text; GBytes *bytes; - GtkTextIter iter; - GtkTextIter start, end; float scale; GskRenderNode *big_node; - g_array_remove_range (self->errors, 0, self->errors->len); text = get_current_text (self->text_buffer); - text_buffer_remove_all_tags (self->text_buffer); bytes = g_bytes_new_take (text, strlen (text)); g_clear_pointer (&self->node, gsk_render_node_unref); @@ -240,73 +313,19 @@ text_changed (GtkTextBuffer *buffer, } g_clear_pointer (&big_node, gsk_render_node_unref); +} - gtk_text_buffer_get_start_iter (self->text_buffer, &iter); +static void +text_changed (GtkTextBuffer *buffer, + NodeEditorWindow *self) +{ + g_array_remove_range (self->errors, 0, self->errors->len); + text_buffer_remove_all_tags (self->text_buffer); - while (!gtk_text_iter_is_end (&iter)) - { - gunichar c = gtk_text_iter_get_char (&iter); + if (self->auto_reload) + reload (self); - if (c == '{') - { - GtkTextIter word_end = iter; - GtkTextIter word_start; - - gtk_text_iter_backward_char (&word_end); - text_iter_skip_whitespace_backward (&word_end); - - word_start = word_end; - gtk_text_iter_backward_word_start (&word_start); - text_iter_skip_alpha_backward (&word_start); - - gtk_text_buffer_apply_tag_by_name (self->text_buffer, "nodename", - &word_start, &word_end); - } - else if (c == ':') - { - GtkTextIter word_end = iter; - GtkTextIter word_start; - - gtk_text_iter_backward_char (&word_end); - text_iter_skip_whitespace_backward (&word_end); - - word_start = word_end; - gtk_text_iter_backward_word_start (&word_start); - text_iter_skip_alpha_backward (&word_start); - - gtk_text_buffer_apply_tag_by_name (self->text_buffer, "propname", - &word_start, &word_end); - } - else if (c == '"') - { - GtkTextIter string_start = iter; - GtkTextIter string_end = iter; - - gtk_text_iter_forward_char (&iter); - while (!gtk_text_iter_is_end (&iter)) - { - c = gtk_text_iter_get_char (&iter); - - if (c == '"') - { - gtk_text_iter_forward_char (&iter); - string_end = iter; - break; - } - - gtk_text_iter_forward_char (&iter); - } - - gtk_text_buffer_apply_tag_by_name (self->text_buffer, "string", - &string_start, &string_end); - } - - gtk_text_iter_forward_char (&iter); - } - - gtk_text_buffer_get_bounds (self->text_buffer, &start, &end); - gtk_text_buffer_apply_tag_by_name (self->text_buffer, "no-hyphens", - &start, &end); + highlight_text (self); } static void @@ -1613,6 +1632,55 @@ G_GNUC_END_IGNORE_DEPRECATIONS g_free (path); } +static void +node_editor_window_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + NodeEditorWindow *self = NODE_EDITOR_WINDOW (object); + + switch (prop_id) + { + case PROP_AUTO_RELOAD: + { + gboolean auto_reload = g_value_get_boolean (value); + if (self->auto_reload != auto_reload) + { + self->auto_reload = auto_reload; + + if (self->auto_reload) + reload (self); + } + } + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +node_editor_window_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NodeEditorWindow *self = NODE_EDITOR_WINDOW (object); + + switch (prop_id) + { + case PROP_AUTO_RELOAD: + g_value_set_boolean (value, self->auto_reload); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + static void node_editor_window_class_init (NodeEditorWindowClass *class) { @@ -1624,6 +1692,8 @@ node_editor_window_class_init (NodeEditorWindowClass *class) object_class->dispose = node_editor_window_dispose; object_class->finalize = node_editor_window_finalize; + object_class->set_property = node_editor_window_set_property; + object_class->get_property = node_editor_window_get_property; gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/gtk4/node-editor/node-editor-window.ui"); @@ -1633,6 +1703,12 @@ node_editor_window_class_init (NodeEditorWindowClass *class) widget_class->map = node_editor_window_map; + properties[PROP_AUTO_RELOAD] = g_param_spec_boolean ("auto-reload", NULL, NULL, + TRUE, + G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME); + + g_object_class_install_properties (object_class, NUM_PROPERTIES, properties); + gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, text_view); gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, picture); gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, renderer_listbox); @@ -1818,6 +1894,8 @@ node_editor_window_init (NodeEditorWindow *self) { gtk_widget_init_template (GTK_WIDGET (self)); + self->auto_reload = TRUE; + self->renderers = g_list_store_new (GDK_TYPE_PAINTABLE); gtk_list_box_bind_model (GTK_LIST_BOX (self->renderer_listbox), G_LIST_MODEL (self->renderers),