From: Benjamin Otte Date: Tue, 24 Apr 2018 18:32:57 +0000 (+0200) Subject: demo: Clean up GtkFishbowl widget X-Git-Tag: archive/raspbian/4.4.1+ds1-2+rpi1^2~18^2~22^2~406 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=aa2f41528303812c9ef0255017e450bbdcd76766;p=gtk4.git demo: Clean up GtkFishbowl widget 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 --- diff --git a/demos/gtk-demo/fishbowl.c b/demos/gtk-demo/fishbowl.c index bc4650a5dd..fc41049415 100644 --- a/demos/gtk-demo/fishbowl.c +++ b/demos/gtk-demo/fishbowl.c @@ -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", diff --git a/demos/gtk-demo/gtkfishbowl.c b/demos/gtk-demo/gtkfishbowl.c index a15f1e9470..9477f7e4e5 100644 --- a/demos/gtk-demo/gtkfishbowl.c +++ b/demos/gtk-demo/gtkfishbowl.c @@ -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)); +} diff --git a/demos/gtk-demo/gtkfishbowl.h b/demos/gtk-demo/gtkfishbowl.h index 83f2c249d7..34ea83b40a 100644 --- a/demos/gtk-demo/gtkfishbowl.h +++ b/demos/gtk-demo/gtkfishbowl.h @@ -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 diff --git a/demos/gtk-demo/widgetbowl.c b/demos/gtk-demo/widgetbowl.c index 565c036d6b..63369efbd6 100644 --- a/demos/gtk-demo/widgetbowl.c +++ b/demos/gtk-demo/widgetbowl.c @@ -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); }