demo: Clean up GtkFishbowl widget
authorBenjamin Otte <otte@redhat.com>
Tue, 24 Apr 2018 18:32:57 +0000 (20:32 +0200)
committerBenjamin Otte <otte@redhat.com>
Tue, 24 Apr 2018 19:55:37 +0000 (21:55 +0200)
1. Remove set_icons property
2. Make it a GtkWidget subclass
3. Add gtk_fishbowl_set_creation_func()
4. Make the widgetbowl use the new benchmarking infrastructure of the
   fishbowl

demos/gtk-demo/fishbowl.c
demos/gtk-demo/gtkfishbowl.c
demos/gtk-demo/gtkfishbowl.h
demos/gtk-demo/widgetbowl.c

index bc4650a5dd2903df72f592adaec1f5cc4a426da0..fc410494156b800f010efafd1bcff09f4a40a2f9 100644 (file)
@@ -9,6 +9,56 @@
 
 #include "gtkfishbowl.h"
 
+char **icon_names = NULL;
+gsize n_icon_names = 0;
+
+static void
+init_icon_names (GtkIconTheme *theme)
+{
+  GPtrArray *icons;
+  GList *l, *icon_list;
+
+  if (icon_names)
+    return;
+
+  icon_list = gtk_icon_theme_list_icons (theme, NULL);
+  icons = g_ptr_array_new ();
+
+  for (l = icon_list; l; l = l->next)
+    {
+      if (g_str_has_suffix (l->data, "symbolic"))
+        continue;
+
+      g_ptr_array_add (icons, g_strdup (l->data));
+    }
+
+  n_icon_names = icons->len;
+  g_ptr_array_add (icons, NULL); /* NULL-terminate the array */
+  icon_names = (char **) g_ptr_array_free (icons, FALSE);
+
+  /* don't free strings, we assigned them to the array */
+  g_list_free_full (icon_list, g_free);
+}
+
+static const char *
+get_random_icon_name (GtkIconTheme *theme)
+{
+  init_icon_names (theme);
+
+  return icon_names[g_random_int_range(0, n_icon_names)];
+}
+
+GtkWidget *
+create_icon (void)
+{
+  GtkWidget *image;
+
+  image = gtk_image_new_from_icon_name (get_random_icon_name (gtk_icon_theme_get_default ()));
+  gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
+
+  return image;
+}
+
 GtkWidget *
 do_fishbowl (GtkWidget *do_widget)
 {
@@ -25,7 +75,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);
+      gtk_fishbowl_set_creation_func (GTK_FISHBOWL (bowl), create_icon);
       gtk_window_set_display (GTK_WINDOW (window),
                               gtk_widget_get_display (do_widget));
       g_signal_connect (window, "destroy",
index a15f1e9470d07a87ac1d0f1c631ce0e304c61167..9477f7e4e5de1956e5cd1d44cb7aa232e6ab3e97 100644 (file)
@@ -24,6 +24,7 @@ typedef struct _GtkFishbowlChild         GtkFishbowlChild;
 
 struct _GtkFishbowlPrivate
 {
+  GtkFishCreationFunc creation_func;
   GList *children;
   guint count;
 
@@ -34,7 +35,6 @@ struct _GtkFishbowlPrivate
   double framerate;
   int last_benchmark_change;
 
-  guint use_icons : 1;
   guint benchmark : 1;
 };
 
@@ -59,7 +59,7 @@ enum {
 
 static GParamSpec *props[NUM_PROPERTIES] = { NULL, };
 
-G_DEFINE_TYPE_WITH_PRIVATE (GtkFishbowl, gtk_fishbowl, GTK_TYPE_CONTAINER)
+G_DEFINE_TYPE_WITH_PRIVATE (GtkFishbowl, gtk_fishbowl, GTK_TYPE_WIDGET)
 
 static void
 gtk_fishbowl_init (GtkFishbowl *fishbowl)
@@ -84,15 +84,6 @@ 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,
@@ -173,10 +164,9 @@ new_speed (void)
 }
 
 static void
-gtk_fishbowl_add (GtkContainer *container,
-                  GtkWidget    *widget)
+gtk_fishbowl_add (GtkFishbowl *fishbowl,
+                  GtkWidget   *widget)
 {
-  GtkFishbowl *fishbowl = GTK_FISHBOWL (container);
   GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
   GtkFishbowlChild *child_info;
 
@@ -198,13 +188,12 @@ gtk_fishbowl_add (GtkContainer *container,
 }
 
 static void
-gtk_fishbowl_remove (GtkContainer *container,
-                     GtkWidget    *widget)
+gtk_fishbowl_remove (GtkFishbowl *fishbowl,
+                     GtkWidget   *widget)
 {
-  GtkFishbowl *fishbowl = GTK_FISHBOWL (container);
   GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
   GtkFishbowlChild *child;
-  GtkWidget *widget_container = GTK_WIDGET (container);
+  GtkWidget *widget_bowl = GTK_WIDGET (fishbowl);
   GList *children;
 
   for (children = priv->children; children; children = children->next)
@@ -221,8 +210,8 @@ gtk_fishbowl_remove (GtkContainer *container,
           g_list_free (children);
           g_free (child);
 
-          if (was_visible && gtk_widget_get_visible (widget_container))
-            gtk_widget_queue_resize (widget_container);
+          if (was_visible && gtk_widget_get_visible (widget_bowl))
+            gtk_widget_queue_resize (widget_bowl);
 
           priv->count--;
           g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_COUNT]);
@@ -231,26 +220,6 @@ gtk_fishbowl_remove (GtkContainer *container,
     }
 }
 
-static void
-gtk_fishbowl_forall (GtkContainer *container,
-                     GtkCallback   callback,
-                     gpointer      callback_data)
-{
-  GtkFishbowl *fishbowl = GTK_FISHBOWL (container);
-  GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
-  GtkFishbowlChild *child;
-  GList *children;
-
-  children = priv->children;
-  while (children)
-    {
-      child = children->data;
-      children = children->next;
-
-      (* callback) (child->widget, callback_data);
-    }
-}
-
 static void
 gtk_fishbowl_dispose (GObject *object)
 {
@@ -335,7 +304,6 @@ gtk_fishbowl_class_init (GtkFishbowlClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
-  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
 
   object_class->dispose = gtk_fishbowl_dispose;
   object_class->set_property = gtk_fishbowl_set_property;
@@ -344,10 +312,6 @@ gtk_fishbowl_class_init (GtkFishbowlClass *klass)
   widget_class->measure = gtk_fishbowl_measure;
   widget_class->size_allocate = gtk_fishbowl_size_allocate;
 
-  container_class->add = gtk_fishbowl_add;
-  container_class->remove = gtk_fishbowl_remove;
-  container_class->forall = gtk_fishbowl_forall;
-
   props[PROP_ANIMATING] =
       g_param_spec_boolean ("animating",
                             "animating",
@@ -397,91 +361,29 @@ gtk_fishbowl_get_count (GtkFishbowl *fishbowl)
   return priv->count;
 }
 
-char **icon_names = NULL;
-gsize n_icon_names = 0;
-
-static void
-init_icon_names (GtkIconTheme *theme)
-{
-  GPtrArray *icons;
-  GList *l, *icon_list;
-
-  if (icon_names)
-    return;
-
-  icon_list = gtk_icon_theme_list_icons (theme, NULL);
-  icons = g_ptr_array_new ();
-
-  for (l = icon_list; l; l = l->next)
-    {
-      if (g_str_has_suffix (l->data, "symbolic"))
-        continue;
-
-      g_ptr_array_add (icons, g_strdup (l->data));
-    }
-
-  n_icon_names = icons->len;
-  g_ptr_array_add (icons, NULL); /* NULL-terminate the array */
-  icon_names = (char **) g_ptr_array_free (icons, FALSE);
-
-  /* don't free strings, we assigned them to the array */
-  g_list_free_full (icon_list, g_free);
-}
-
-static const char *
-get_random_icon_name (GtkIconTheme *theme)
-{
-  init_icon_names (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)
 {
   GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
 
+  if (priv->count == count)
+    return;
+
   g_object_freeze_notify (G_OBJECT (fishbowl));
 
   while (priv->count > count)
     {
-      gtk_container_remove (GTK_CONTAINER (fishbowl),
-                            ((GtkFishbowlChild *) priv->children->data)->widget);
+      gtk_fishbowl_remove (fishbowl, gtk_widget_get_first_child (GTK_WIDGET (fishbowl)));
     }
 
   while (priv->count < count)
     {
       GtkWidget *new_widget;
 
-      if (priv->use_icons)
-        {
-          new_widget = gtk_image_new_from_icon_name (get_random_icon_name (gtk_icon_theme_get_default ()));
-          gtk_image_set_icon_size (GTK_IMAGE (new_widget), GTK_ICON_SIZE_LARGE);
-        }
-      else
-        new_widget = g_object_new (get_random_widget_type (), NULL);
+      new_widget = priv->creation_func ();
 
-      gtk_container_add (GTK_CONTAINER (fishbowl), new_widget);
+      gtk_fishbowl_add (fishbowl, new_widget);
     }
 
   g_object_thaw_notify (G_OBJECT (fishbowl));
@@ -741,3 +643,17 @@ gtk_fishbowl_set_update_delay (GtkFishbowl *fishbowl,
   g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_UPDATE_DELAY]);
 }
 
+void
+gtk_fishbowl_set_creation_func (GtkFishbowl         *fishbowl,
+                                GtkFishCreationFunc  creation_func)
+{
+  GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
+
+  g_object_freeze_notify (G_OBJECT (fishbowl));
+
+  gtk_fishbowl_set_count (fishbowl, 0);
+
+  priv->creation_func = creation_func;
+
+  g_object_thaw_notify (G_OBJECT (fishbowl));
+}
index 83f2c249d781c0d362ae500a5e22bbf748f98574..34ea83b40a88de7702f0ce633aa9cb28a70ca226 100644 (file)
@@ -32,23 +32,22 @@ G_BEGIN_DECLS
 typedef struct _GtkFishbowl              GtkFishbowl;
 typedef struct _GtkFishbowlClass         GtkFishbowlClass;
 
+typedef GtkWidget * (* GtkFishCreationFunc) (void);
+
 struct _GtkFishbowl
 {
-  GtkContainer container;
+  GtkWidget parent;
 };
 
 struct _GtkFishbowlClass
 {
-  GtkContainerClass parent_class;
+  GtkWidgetClass parent_class;
 };
 
 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);
@@ -62,6 +61,8 @@ double     gtk_fishbowl_get_framerate     (GtkFishbowl       *fishbowl);
 gint64     gtk_fishbowl_get_update_delay  (GtkFishbowl       *fishbowl);
 void       gtk_fishbowl_set_update_delay  (GtkFishbowl       *fishbowl,
                                            gint64             update_delay);
+void       gtk_fishbowl_set_creation_func (GtkFishbowl       *fishbowl,
+                                           GtkFishCreationFunc creation_func);
 
 G_END_DECLS
 
index 565c036d6bbb2004fc07cf673614fb54e7bd4f5d..63369efbd660519af2eafd00591e716fa36dab8d 100644 (file)
@@ -140,177 +140,15 @@ static void
 set_widget_type (GtkWidget *headerbar,
                  int        widget_type_index)
 {
-  GList *children, *l;
-
   if (widget_type_index == selected_widget_type)
     return;
 
-  /* Remove everything */
-  children = gtk_container_get_children (GTK_CONTAINER (fishbowl));
-  for (l = children; l; l = l->next)
-    {
-      gtk_container_remove (GTK_CONTAINER (fishbowl), (GtkWidget*)l->data);
-    }
-
-  g_list_free (children);
-
   selected_widget_type = widget_type_index;
 
   gtk_header_bar_set_title (GTK_HEADER_BAR (headerbar),
                             widget_types[selected_widget_type].name);
-}
-
-
-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 ("widgets - %.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, &suggested_change);
-
-  if (suggested_change > 0)
-    {
-      int i;
-
-      for (i = 0; i < suggested_change; i ++)
-        {
-          GtkWidget *new_widget = widget_types[selected_widget_type].create_func ();
-
-          gtk_container_add (GTK_CONTAINER (fishbowl), new_widget);
-
-        }
-    }
-  else if (suggested_change < 0)
-    {
-      GList *children, *l;
-      int n_removed = 0;
-
-      children = gtk_container_get_children (GTK_CONTAINER (fishbowl));
-      for (l = children; l; l = l->next)
-        {
-          gtk_container_remove (GTK_CONTAINER (fishbowl), (GtkWidget *)l->data);
-          n_removed ++;
-
-          if (n_removed >= (-suggested_change))
-            break;
-        }
-
-      g_list_free (children);
-    }
-
-  stats_update (bowl);
-
-  return G_SOURCE_CONTINUE;
+  gtk_fishbowl_set_creation_func (GTK_FISHBOWL (fishbowl),
+                                  widget_types[selected_widget_type].create_func);
 }
 
 static void
@@ -386,6 +224,7 @@ do_widgetbowl (GtkWidget *do_widget)
       g_signal_connect (prev_button, "clicked", G_CALLBACK (prev_button_clicked_cb), titlebar);
 
       gtk_fishbowl_set_animating (GTK_FISHBOWL (fishbowl), TRUE);
+      gtk_fishbowl_set_benchmark (GTK_FISHBOWL (fishbowl), TRUE);
 
       gtk_widget_set_hexpand (title_box, TRUE);
       gtk_widget_set_halign (title_box, GTK_ALIGN_END);
@@ -408,7 +247,6 @@ do_widgetbowl (GtkWidget *do_widget)
                         G_CALLBACK (gtk_widget_destroyed), &window);
 
       gtk_widget_realize (window);
-      gtk_widget_add_tick_callback (fishbowl, move_fish, info_label, NULL);
 
       set_widget_type (titlebar, 0);
     }