[gtk/wip/baedert/nodeeditor-fuckery] node editor: Add a quick way to save a testcase



commit 3874f37395877f26802e1d84cbbb38a5a70c5943
Author: Timm Bäder <mail baedert org>
Date:   Wed May 29 20:30:21 2019 +0200

    node editor: Add a quick way to save a testcase

 demos/node-editor/meson.build           |   1 +
 demos/node-editor/node-editor-window.c  | 116 ++++++++++++++++++++++++++++++++
 demos/node-editor/node-editor-window.ui |  87 ++++++++++++++++++++++++
 3 files changed, 204 insertions(+)
---
diff --git a/demos/node-editor/meson.build b/demos/node-editor/meson.build
index 81f96a2fd8..c08fdd4bc9 100644
--- a/demos/node-editor/meson.build
+++ b/demos/node-editor/meson.build
@@ -13,6 +13,7 @@ executable('gtk4-node-editor',
            node_editor_sources, node_editor_resources,
            dependencies: libgtk_dep,
            include_directories: confinc,
+           c_args: 
['-DNODE_EDITOR_SOURCE_DIR="@0@/../../testsuite/gsk/compare/"'.format(meson.current_source_dir())],
            gui_app: true,
            link_args: extra_demo_ldflags,
            install: false)
diff --git a/demos/node-editor/node-editor-window.c b/demos/node-editor/node-editor-window.c
index c1a50c18ff..08559f167c 100644
--- a/demos/node-editor/node-editor-window.c
+++ b/demos/node-editor/node-editor-window.c
@@ -25,6 +25,10 @@
 
 #include "gsk/gskrendernodeparserprivate.h"
 
+#ifndef NODE_EDITOR_SOURCE_DIR
+#define NODE_EDITOR_SOURCE_DIR "." /* Fallback */
+#endif
+
 typedef struct
 {
   gsize  start_chars;
@@ -41,6 +45,12 @@ struct _NodeEditorWindow
   GtkTextBuffer *text_buffer;
   GtkTextTagTable *tag_table;
 
+  GtkWidget *testcase_popover;
+  GtkWidget *testcase_error_label;
+  GtkWidget *testcase_cairo_checkbutton;
+  GtkWidget *testcase_name_entry;
+  GtkWidget *testcase_save_button;
+
   GtkWidget *renderer_listbox;
   GListStore *renderers;
   GdkPaintable *paintable;
@@ -471,6 +481,39 @@ create_texture (NodeEditorWindow *self)
   return texture;
 }
 
+static GdkTexture *
+create_cairo_texture (NodeEditorWindow *self)
+{
+  GdkPaintable *paintable;
+  GtkSnapshot *snapshot;
+  GskRenderer *renderer;
+  GskRenderNode *node;
+  GdkTexture *texture;
+  GdkSurface *surface;
+
+  paintable = gtk_picture_get_paintable (GTK_PICTURE (self->picture));
+  if (paintable == NULL ||
+      gdk_paintable_get_intrinsic_width (paintable) <= 0 ||
+      gdk_paintable_get_intrinsic_height (paintable) <= 0)
+    return NULL;
+  snapshot = gtk_snapshot_new ();
+  gdk_paintable_snapshot (paintable, snapshot, gdk_paintable_get_intrinsic_width (paintable), 
gdk_paintable_get_intrinsic_height (paintable));
+  node = gtk_snapshot_free_to_node (snapshot);
+  if (node == NULL)
+    return NULL;
+
+  surface = gtk_native_get_surface (gtk_widget_get_native (GTK_WIDGET (self)));
+  renderer = gsk_cairo_renderer_new ();
+  gsk_renderer_realize (renderer, surface, NULL);
+
+  texture = gsk_renderer_render_texture (renderer, node, NULL);
+  gsk_render_node_unref (node);
+  gsk_renderer_unrealize (renderer);
+  g_object_unref (renderer);
+
+  return texture;
+}
+
 static void
 export_image_response_cb (GtkWidget  *dialog,
                           gint        response,
@@ -527,6 +570,72 @@ export_image_cb (GtkWidget        *button,
   gtk_widget_show (dialog);
 }
 
+static void
+testcase_name_entry_changed_cb (GtkWidget        *button,
+                                GParamSpec       *pspec,
+                                NodeEditorWindow *self)
+
+{
+  const char *text = gtk_editable_get_text (GTK_EDITABLE (self->testcase_name_entry));
+
+  if (strlen (text) > 0)
+    gtk_widget_set_sensitive (self->testcase_save_button, TRUE);
+  else
+    gtk_widget_set_sensitive (self->testcase_save_button, FALSE);
+}
+
+static void
+testcase_save_clicked_cb (GtkWidget        *button,
+                          NodeEditorWindow *self)
+{
+  const char *testcase_name = gtk_editable_get_text (GTK_EDITABLE (self->testcase_name_entry));
+  char *source_dir = g_canonicalize_filename (NODE_EDITOR_SOURCE_DIR, NULL);
+  char *node_file_name;
+  char *node_file;
+  char *png_file_name;
+  char *png_file;
+  char *text = NULL;
+  GdkTexture *texture;
+  GError *error = NULL;
+
+  node_file_name = g_strconcat (testcase_name, ".node", NULL);
+  node_file = g_build_filename (source_dir, node_file_name, NULL);
+  g_free (node_file_name);
+
+  png_file_name = g_strconcat (testcase_name, ".png", NULL);
+  png_file = g_build_filename (source_dir, png_file_name, NULL);
+  g_free (png_file_name);
+
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->testcase_cairo_checkbutton)))
+    texture = create_cairo_texture (self);
+  else
+    texture = create_texture (self);
+
+  if (!gdk_texture_save_to_png (texture, png_file))
+    {
+      gtk_label_set_label (GTK_LABEL (self->testcase_error_label),
+                           "Could not save texture file");
+      goto out;
+    }
+
+  text = get_current_text (self->text_buffer);
+  if (!g_file_set_contents (node_file, text, -1, &error))
+    {
+      gtk_label_set_label (GTK_LABEL (self->testcase_error_label), error->message);
+      /* TODO: Remove texture file again? */
+      goto out;
+    }
+
+  gtk_editable_set_text (GTK_EDITABLE (self->testcase_name_entry), "");
+  gtk_popover_popdown (GTK_POPOVER (self->testcase_popover));
+
+out:
+  g_free (text);
+  g_free (png_file);
+  g_free (node_file);
+  g_free (source_dir);
+}
+
 static void
 node_editor_window_finalize (GObject *object)
 {
@@ -621,11 +730,18 @@ node_editor_window_class_init (NodeEditorWindowClass *class)
   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);
+  gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, testcase_popover);
+  gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, testcase_error_label);
+  gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, testcase_cairo_checkbutton);
+  gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, testcase_name_entry);
+  gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, testcase_save_button);
 
   gtk_widget_class_bind_template_callback (widget_class, text_view_query_tooltip_cb);
   gtk_widget_class_bind_template_callback (widget_class, open_cb);
   gtk_widget_class_bind_template_callback (widget_class, save_cb);
   gtk_widget_class_bind_template_callback (widget_class, export_image_cb);
+  gtk_widget_class_bind_template_callback (widget_class, testcase_save_clicked_cb);
+  gtk_widget_class_bind_template_callback (widget_class, testcase_name_entry_changed_cb);
 }
 
 static GtkWidget *
diff --git a/demos/node-editor/node-editor-window.ui b/demos/node-editor/node-editor-window.ui
index d254d992b3..337ef5995c 100644
--- a/demos/node-editor/node-editor-window.ui
+++ b/demos/node-editor/node-editor-window.ui
@@ -1,5 +1,81 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
+  <object class="GtkPopover" id="testcase_popover">
+    <child>
+      <object class="GtkGrid">
+        <property name="column-spacing">12</property>
+        <property name="row-spacing">12</property>
+        <child>
+          <object class="GtkLabel">
+            <property name="label">Testcase Name:</property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkEntry" id="testcase_name_entry">
+            <property name="hexpand">1</property>
+            <property name="activates-default">1</property>
+            <signal name="notify::text" handler="testcase_name_entry_changed_cb" />
+          </object>
+        </child>
+        <child>
+          <object class="GtkCheckButton" id="testcase_cairo_checkbutton">
+            <property name="label">Render using Cairo renderer</property>
+            <layout>
+              <property name="top-attach">1</property>
+              <property name="left-attach">0</property>
+              <property name="column-span">2</property>
+            </layout>
+          </object>
+        </child>
+
+        <child>
+          <object class="GtkLabel">
+            <property name="wrap">1</property>
+            <property name="label">&lt;i&gt;There will be a .node and a .png file placed in the 
testsuite/gsk/compare directory. &lt;b&gt;You need to add it to the meson.build 
yourself.&lt;/b&gt;&lt;/i&gt;</property>
+            <property name="use-markup">1</property>
+            <property name="max-width-chars">50</property>
+            <layout>
+              <property name="top-attach">2</property>
+              <property name="left-attach">0</property>
+              <property name="column-span">2</property>
+            </layout>
+          </object>
+        </child>
+
+        <child>
+          <object class="GtkLabel" id="testcase_error_label">
+            <property name="wrap">1</property>
+            <property name="xalign">0</property>
+            <layout>
+              <property name="top-attach">3</property>
+              <property name="left-attach">0</property>
+              <property name="column-span">2</property>
+            </layout>
+          </object>
+        </child>
+
+        <child>
+          <object class="GtkButton" id="testcase_save_button">
+            <property name="label">Save</property>
+            <property name="hexpand">1</property>
+            <property name="halign">end</property>
+            <property name="receives-default">1</property>
+            <property name="sensitive">0</property>
+            <signal name="clicked" handler="testcase_save_clicked_cb" />
+            <style>
+              <class name="suggested-action" />
+            </style>
+            <layout>
+              <property name="top-attach">4</property>
+              <property name="left-attach">0</property>
+              <property name="column-span">2</property>
+            </layout>
+          </object>
+        </child>
+      </object>
+    </child>
+  </object>
+
   <template class="NodeEditorWindow" parent="GtkApplicationWindow">
     <style>
       <class name="devel"/>
@@ -32,6 +108,17 @@
             <signal name="clicked" handler="export_image_cb"/>
           </object>
         </child>
+        <child type="start">
+          <object class="GtkSeparator">
+            <property name="orientation">vertical</property>
+          </object>
+        </child>
+        <child type="start">
+          <object class="GtkMenuButton">
+            <property name="label">Save Testcase</property>
+            <property name="popover">testcase_popover</property>
+          </object>
+        </child>
         <child type="title">
           <object class="GtkLabel">
             <property name="label" translatable="yes">GTK Node Editor</property>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]