[gtk+/wip/baedert/drawing: 100/102] gtk4-demo: Add widgetbowl demo



commit 848a5083b13ba1c8f1b2d209d913f5cf19dce1e2
Author: Timm Bäder <mail baedert org>
Date:   Thu Jun 29 12:18:40 2017 +0200

    gtk4-demo: Add widgetbowl demo
    
    Same as fishbowl, but with widgets

 demos/gtk-demo/Makefile.am   |    1 +
 demos/gtk-demo/fishbowl.c    |    1 +
 demos/gtk-demo/gtkfishbowl.c |   63 +++++++++------
 demos/gtk-demo/gtkfishbowl.h |    3 +
 demos/gtk-demo/widgetbowl.c  |  179 ++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 221 insertions(+), 26 deletions(-)
---
diff --git a/demos/gtk-demo/Makefile.am b/demos/gtk-demo/Makefile.am
index b3bcd7d..ea20c49 100644
--- a/demos/gtk-demo/Makefile.am
+++ b/demos/gtk-demo/Makefile.am
@@ -28,6 +28,7 @@ demos_base =                                  \
        expander.c                              \
         filtermodel.c                          \
        fishbowl.c                              \
+       widgetbowl.c                            \
        foreigndrawing.c                        \
        gestures.c                              \
        glarea.c                                \
diff --git a/demos/gtk-demo/fishbowl.c b/demos/gtk-demo/fishbowl.c
index db49822..4d87655 100644
--- a/demos/gtk-demo/fishbowl.c
+++ b/demos/gtk-demo/fishbowl.c
@@ -157,6 +157,7 @@ do_fishbowl (GtkWidget *do_widget)
       gtk_builder_connect_signals (builder, NULL);
       window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
       bowl = GTK_WIDGET (gtk_builder_get_object (builder, "bowl"));
+      gtk_fishbowl_set_use_icons (GTK_FISHBOWL (bowl), TRUE);
       info_label = GTK_WIDGET (gtk_builder_get_object (builder, "info_label"));
       allow_changes = GTK_WIDGET (gtk_builder_get_object (builder, "changes_allow"));
       gtk_window_set_screen (GTK_WINDOW (window),
diff --git a/demos/gtk-demo/gtkfishbowl.c b/demos/gtk-demo/gtkfishbowl.c
index 447610c..d3343eb 100644
--- a/demos/gtk-demo/gtkfishbowl.c
+++ b/demos/gtk-demo/gtkfishbowl.c
@@ -29,6 +29,8 @@ struct _GtkFishbowlPrivate
 
   gint64 last_frame_time;
   guint tick_id;
+
+  guint use_icons: 1;
 };
 
 struct _GtkFishbowlChild
@@ -70,6 +72,15 @@ gtk_fishbowl_new (void)
   return g_object_new (GTK_TYPE_FISHBOWL, NULL);
 }
 
+void
+gtk_fishbowl_set_use_icons (GtkFishbowl *fishbowl,
+                            gboolean     use_icons)
+{
+  GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
+
+  priv->use_icons = use_icons;
+}
+
 static void
 gtk_fishbowl_measure (GtkWidget      *widget,
                       GtkOrientation  orientation,
@@ -218,27 +229,6 @@ gtk_fishbowl_forall (GtkContainer *container,
     }
 }
 
-static void 
-gtk_fishbowl_snapshot (GtkWidget   *widget,
-                       GtkSnapshot *snapshot)
-{
-  GtkFishbowl *fishbowl = GTK_FISHBOWL (widget);
-  GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
-  GtkFishbowlChild *child;
-  GList *list;
-
-  for (list = priv->children;
-       list;
-       list = list->next)
-    {
-      child = list->data;
-
-      gtk_widget_snapshot_child (widget,
-                                 child->widget,
-                                 snapshot);
-    }
-}
-
 static void
 gtk_fishbowl_dispose (GObject *object)
 {
@@ -311,7 +301,6 @@ gtk_fishbowl_class_init (GtkFishbowlClass *klass)
 
   widget_class->measure = gtk_fishbowl_measure;
   widget_class->size_allocate = gtk_fishbowl_size_allocate;
-  widget_class->snapshot = gtk_fishbowl_snapshot;
 
   container_class->add = gtk_fishbowl_add;
   container_class->remove = gtk_fishbowl_remove;
@@ -382,6 +371,25 @@ get_random_icon_name (GtkIconTheme *theme)
   return icon_names[g_random_int_range(0, n_icon_names)];
 }
 
+static GType
+get_random_widget_type ()
+{
+  GType types[] = {
+    GTK_TYPE_SWITCH,
+    GTK_TYPE_BUTTON,
+    GTK_TYPE_ENTRY,
+    GTK_TYPE_SPIN_BUTTON,
+    GTK_TYPE_FONT_BUTTON,
+    GTK_TYPE_SCROLLBAR,
+    GTK_TYPE_SCALE,
+    GTK_TYPE_LEVEL_BAR,
+    GTK_TYPE_PROGRESS_BAR,
+    GTK_TYPE_RADIO_BUTTON,
+    GTK_TYPE_CHECK_BUTTON
+  };
+  return types[g_random_int_range (0, G_N_ELEMENTS (types))];
+}
+
 void
 gtk_fishbowl_set_count (GtkFishbowl *fishbowl,
                         guint        count)
@@ -399,10 +407,13 @@ gtk_fishbowl_set_count (GtkFishbowl *fishbowl,
   while (priv->count < count)
     {
       GtkWidget *new_widget;
-        
-      new_widget = gtk_image_new_from_icon_name (get_random_icon_name (gtk_icon_theme_get_default ()),
-                                                 GTK_ICON_SIZE_DIALOG);
-      gtk_widget_show (new_widget);
+
+      if (priv->use_icons)
+        new_widget = gtk_image_new_from_icon_name (get_random_icon_name (gtk_icon_theme_get_default ()),
+                                                   GTK_ICON_SIZE_DIALOG);
+      else
+        new_widget = g_object_new (get_random_widget_type (), NULL);
+
       gtk_container_add (GTK_CONTAINER (fishbowl), new_widget);
     }
 
diff --git a/demos/gtk-demo/gtkfishbowl.h b/demos/gtk-demo/gtkfishbowl.h
index 2ac1ad1..b1559d0 100644
--- a/demos/gtk-demo/gtkfishbowl.h
+++ b/demos/gtk-demo/gtkfishbowl.h
@@ -46,6 +46,9 @@ GType      gtk_fishbowl_get_type          (void) G_GNUC_CONST;
 
 GtkWidget* gtk_fishbowl_new               (void);
 
+void       gtk_fishbowl_set_use_icons     (GtkFishbowl       *fishbowl,
+                                           gboolean           use_icons);
+
 guint      gtk_fishbowl_get_count         (GtkFishbowl       *fishbowl);
 void       gtk_fishbowl_set_count         (GtkFishbowl       *fishbowl,
                                            guint              count);
diff --git a/demos/gtk-demo/widgetbowl.c b/demos/gtk-demo/widgetbowl.c
new file mode 100644
index 0000000..b64d2c4
--- /dev/null
+++ b/demos/gtk-demo/widgetbowl.c
@@ -0,0 +1,179 @@
+/* Benchmark/Widgetbowl
+ *
+ * This demo models the fishbowl demos seen on the web in a GTK way.
+ * It's also a neat little tool to see how fast your computer (or
+ * your GTK version) is.
+ */
+
+#include <gtk/gtk.h>
+
+#include "gtkfishbowl.h"
+
+GtkWidget *allow_changes;
+
+#define N_STATS 5
+
+#define STATS_UPDATE_TIME G_USEC_PER_SEC
+
+typedef struct _Stats Stats;
+struct _Stats {
+  gint64 last_stats;
+  gint64 last_frame;
+  gint last_suggestion;
+  guint frame_counter_max;
+
+  guint stats_index;
+  guint frame_counter[N_STATS];
+  guint item_counter[N_STATS];
+};
+
+static Stats *
+get_stats (GtkWidget *widget)
+{
+  static GQuark stats_quark = 0;
+  Stats *stats;
+
+  if (G_UNLIKELY (stats_quark == 0))
+    stats_quark = g_quark_from_static_string ("stats");
+
+  stats = g_object_get_qdata (G_OBJECT (widget), stats_quark);
+  if (stats == NULL)
+    {
+      stats = g_new0 (Stats, 1);
+      g_object_set_qdata_full (G_OBJECT (widget), stats_quark, stats, g_free);
+      stats->last_frame = gdk_frame_clock_get_frame_time (gtk_widget_get_frame_clock (widget));
+      stats->last_stats = stats->last_frame;
+    }
+
+  return stats;
+}
+
+static void
+do_stats (GtkWidget *widget,
+          GtkWidget *info_label,
+          gint      *suggested_change)
+{
+  Stats *stats;
+  gint64 frame_time;
+
+  stats = get_stats (widget);
+  frame_time = gdk_frame_clock_get_frame_time (gtk_widget_get_frame_clock (widget));
+
+  if (stats->last_stats + STATS_UPDATE_TIME < frame_time)
+    {
+      char *new_label;
+      guint i, n_frames;
+
+      n_frames = 0;
+      for (i = 0; i < N_STATS; i++)
+        {
+          n_frames += stats->frame_counter[i];
+        }
+      
+      new_label = g_strdup_printf ("icons - %.1f fps",
+                                   (double) G_USEC_PER_SEC * n_frames
+                                       / (N_STATS * STATS_UPDATE_TIME));
+      gtk_label_set_label (GTK_LABEL (info_label), new_label);
+      g_free (new_label);
+
+      if (stats->frame_counter[stats->stats_index] >= 19 * stats->frame_counter_max / 20)
+        {
+          if (stats->last_suggestion > 0)
+            stats->last_suggestion *= 2;
+          else
+            stats->last_suggestion = 1;
+        }
+      else
+        {
+          if (stats->last_suggestion < 0)
+            stats->last_suggestion--;
+          else
+            stats->last_suggestion = -1;
+          stats->last_suggestion = MAX (stats->last_suggestion, 1 - (int) 
stats->item_counter[stats->stats_index]);
+        }
+
+      stats->stats_index = (stats->stats_index + 1) % N_STATS;
+      stats->frame_counter[stats->stats_index] = 0;
+      stats->item_counter[stats->stats_index] = stats->item_counter[(stats->stats_index + N_STATS - 1) % 
N_STATS];
+      stats->last_stats = frame_time;
+      
+      if (suggested_change)
+        *suggested_change = stats->last_suggestion;
+      else
+        stats->last_suggestion = 0;
+    }
+  else
+    {
+      if (suggested_change)
+        *suggested_change = 0;
+    }
+
+  stats->last_frame = frame_time;
+  stats->frame_counter[stats->stats_index]++;
+  stats->frame_counter_max = MAX (stats->frame_counter_max, stats->frame_counter[stats->stats_index]);
+}
+
+static void
+stats_update (GtkWidget *widget)
+{
+  Stats *stats;
+
+  stats = get_stats (widget);
+
+  stats->item_counter[stats->stats_index] = gtk_fishbowl_get_count (GTK_FISHBOWL (widget));
+}
+
+static gboolean
+move_fish (GtkWidget     *bowl,
+           GdkFrameClock *frame_clock,
+           gpointer       info_label)
+{
+  gint suggested_change = 0;
+  
+  do_stats (bowl,
+            info_label,
+            !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (allow_changes)) ? &suggested_change : NULL);
+
+  gtk_fishbowl_set_count (GTK_FISHBOWL (bowl),
+                          gtk_fishbowl_get_count (GTK_FISHBOWL (bowl)) + suggested_change);
+  stats_update (bowl);
+
+  return G_SOURCE_CONTINUE;
+}
+
+GtkWidget *
+do_widgetbowl (GtkWidget *do_widget)
+{
+  static GtkWidget *window = NULL;
+
+  if (!window)
+    {
+      GtkBuilder *builder;
+      GtkWidget *bowl, *info_label;
+
+      g_type_ensure (GTK_TYPE_FISHBOWL);
+
+      builder = gtk_builder_new_from_resource ("/fishbowl/fishbowl.ui");
+      gtk_builder_connect_signals (builder, NULL);
+      window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
+      bowl = GTK_WIDGET (gtk_builder_get_object (builder, "bowl"));
+      gtk_fishbowl_set_use_icons (GTK_FISHBOWL (bowl), FALSE);
+      info_label = GTK_WIDGET (gtk_builder_get_object (builder, "info_label"));
+      allow_changes = GTK_WIDGET (gtk_builder_get_object (builder, "changes_allow"));
+      gtk_window_set_screen (GTK_WINDOW (window),
+                             gtk_widget_get_screen (do_widget));
+      g_signal_connect (window, "destroy",
+                        G_CALLBACK (gtk_widget_destroyed), &window);
+
+      gtk_widget_realize (window);
+      gtk_widget_add_tick_callback (bowl, move_fish, info_label, NULL);
+    }
+
+  if (!gtk_widget_get_visible (window))
+    gtk_widget_show (window);
+  else
+    gtk_widget_destroy (window);
+
+
+  return window;
+}


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