From af8fdac00135012651be549bed9fa95d38295715 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 20 May 2014 21:44:48 -0400 Subject: [PATCH] inspector: Show size groups Add a tab that shows size groups of a widget. The properties of the size group are available here, as well as the widgets that are part of the size group. We highlight the widgets in the application when their row in the inspector is hovered. --- gtk/inspector/Makefile.am | 2 + gtk/inspector/init.c | 2 + gtk/inspector/size-groups.c | 278 ++++++++++++++++++++++++++++++++++++ gtk/inspector/size-groups.h | 51 +++++++ gtk/inspector/window.c | 3 + gtk/inspector/window.ui | 14 ++ 6 files changed, 350 insertions(+) create mode 100644 gtk/inspector/size-groups.c create mode 100644 gtk/inspector/size-groups.h diff --git a/gtk/inspector/Makefile.am b/gtk/inspector/Makefile.am index 3a604233c8..faa5670842 100644 --- a/gtk/inspector/Makefile.am +++ b/gtk/inspector/Makefile.am @@ -46,6 +46,8 @@ libgtkinspector_la_SOURCES = \ resources.c \ signals-list.h \ signals-list.c \ + size-groups.h \ + size-groups.c \ visual.h \ visual.c \ widget-tree.h \ diff --git a/gtk/inspector/init.c b/gtk/inspector/init.c index a82b6f2759..35b63f8462 100644 --- a/gtk/inspector/init.c +++ b/gtk/inspector/init.c @@ -35,6 +35,7 @@ #include "resource-list.h" #include "resources.h" #include "signals-list.h" +#include "size-groups.h" #include "visual.h" #include "widget-tree.h" #include "window.h" @@ -59,6 +60,7 @@ gtk_inspector_init (void) g_type_ensure (GTK_TYPE_INSPECTOR_PYTHON_SHELL); g_type_ensure (GTK_TYPE_INSPECTOR_RESOURCE_LIST); g_type_ensure (GTK_TYPE_INSPECTOR_SIGNALS_LIST); + g_type_ensure (GTK_TYPE_INSPECTOR_SIZE_GROUPS); g_type_ensure (GTK_TYPE_INSPECTOR_VISUAL); g_type_ensure (GTK_TYPE_INSPECTOR_WIDGET_TREE); g_type_ensure (GTK_TYPE_INSPECTOR_WINDOW); diff --git a/gtk/inspector/size-groups.c b/gtk/inspector/size-groups.c new file mode 100644 index 0000000000..d4b27d1295 --- /dev/null +++ b/gtk/inspector/size-groups.c @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2014 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "config.h" +#include +#include "size-groups.h" +#include "window.h" +#include "gtkwidgetprivate.h" + + +typedef struct { + GtkListBoxRow parent; + GtkWidget *widget; +} SizeGroupRow; + +typedef struct { + GtkListBoxRowClass parent; +} SizeGroupRowClass; + +enum { + PROP_WIDGET = 1, + LAST_PROPERTY +}; + +GParamSpec *properties[LAST_PROPERTY] = { NULL }; + +G_DEFINE_TYPE (SizeGroupRow, size_group_row, GTK_TYPE_LIST_BOX_ROW) + +static void +size_group_row_init (SizeGroupRow *row) +{ +} + +static void +size_group_row_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + SizeGroupRow *row = (SizeGroupRow*)object; + + switch (property_id) + { + case PROP_WIDGET: + g_value_set_pointer (value, row->widget); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +size_group_row_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + SizeGroupRow *row = (SizeGroupRow*)object; + + switch (property_id) + { + case PROP_WIDGET: + if (row->widget) + g_object_remove_weak_pointer (G_OBJECT (row->widget), (gpointer *)&row->widget); + row->widget = g_value_get_pointer (value); + if (row->widget) + g_object_add_weak_pointer (G_OBJECT (row->widget), (gpointer *)&row->widget); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} +static void +size_group_row_finalize (GObject *object) +{ + SizeGroupRow *row = (SizeGroupRow *)object; + + if (row->widget) + g_object_remove_weak_pointer (G_OBJECT (row->widget), (gpointer *)&row->widget); + + G_OBJECT_CLASS (size_group_row_parent_class)->finalize (object); +} + +static void +size_group_state_flags_changed (GtkWidget *widget, + GtkStateFlags old_state) +{ + SizeGroupRow *row = (SizeGroupRow*)widget; + GtkStateFlags state; + + if (!row->widget) + return; + + state = gtk_widget_get_state_flags (widget); + if ((state & GTK_STATE_FLAG_PRELIGHT) != (old_state & GTK_STATE_FLAG_PRELIGHT)) + { + if (state & GTK_STATE_FLAG_PRELIGHT) + gtk_inspector_start_highlight (row->widget); + else + gtk_inspector_stop_highlight (row->widget); + } +} + +static void +size_group_row_class_init (SizeGroupRowClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); + + object_class->finalize = size_group_row_finalize; + object_class->get_property = size_group_row_get_property; + object_class->set_property = size_group_row_set_property; + + widget_class->state_flags_changed = size_group_state_flags_changed; + + properties[PROP_WIDGET] = + g_param_spec_pointer ("widget", "Widget", "Widget", G_PARAM_READWRITE); + + g_object_class_install_properties (object_class, LAST_PROPERTY, properties); + +} + +G_DEFINE_TYPE (GtkInspectorSizeGroups, gtk_inspector_size_groups, GTK_TYPE_BOX) + +static void +clear_view (GtkInspectorSizeGroups *sl) +{ + GList *children, *l; + GtkWidget *child; + + children = gtk_container_get_children (GTK_CONTAINER (sl)); + for (l = children; l; l = l->next) + { + child = l->data; + gtk_container_remove (GTK_CONTAINER (sl), child); + } + g_list_free (children); +} + +static void +add_widget (GtkInspectorSizeGroups *sl, + GtkListBox *listbox, + GtkWidget *widget) +{ + GtkWidget *row; + GtkWidget *label; + gchar *text; + + row = g_object_new (size_group_row_get_type (), "widget", widget, NULL); + text = g_strdup_printf ("%p (%s)", widget, g_type_name_from_instance ((GTypeInstance*)widget)); + label = gtk_label_new (text); + g_free (text); + g_object_set (label, "margin", 10, NULL); + gtk_widget_set_halign (label, GTK_ALIGN_START); + gtk_widget_set_valign (label, GTK_ALIGN_BASELINE); + gtk_widget_show (label); + gtk_container_add (GTK_CONTAINER (row), label); + gtk_container_add (GTK_CONTAINER (listbox), row); +} + +static void +add_size_group (GtkInspectorSizeGroups *sl, + GtkSizeGroup *group) +{ + GtkWidget *frame, *box, *box2; + GtkWidget *label, *sw, *combo; + GSList *widgets, *l; + GtkWidget *listbox; + + frame = gtk_frame_new (NULL); + gtk_container_add (GTK_CONTAINER (sl), frame); + box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + gtk_container_add (GTK_CONTAINER (frame), box); + + box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10); + gtk_container_add (GTK_CONTAINER (box), box2); + + label = gtk_label_new (_("Ignore hidden")); + g_object_set (label, "margin", 10, NULL); + gtk_widget_set_halign (label, GTK_ALIGN_START); + gtk_widget_set_valign (label, GTK_ALIGN_BASELINE); + gtk_box_pack_start (GTK_BOX (box2), label, TRUE, TRUE, 0); + + sw = gtk_switch_new (); + g_object_set (sw, "margin", 10, NULL); + gtk_widget_set_halign (sw, GTK_ALIGN_END); + gtk_widget_set_valign (sw, GTK_ALIGN_BASELINE); + g_object_bind_property (group, "ignore-hidden", + sw, "active", + G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); + gtk_box_pack_start (GTK_BOX (box2), sw, FALSE, FALSE, 0); + + box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10); + gtk_container_add (GTK_CONTAINER (box), box2); + + label = gtk_label_new (_("Mode")); + g_object_set (label, "margin", 10, NULL); + gtk_widget_set_halign (label, GTK_ALIGN_START); + gtk_widget_set_valign (label, GTK_ALIGN_BASELINE); + gtk_box_pack_start (GTK_BOX (box2), label, TRUE, TRUE, 0); + + combo = gtk_combo_box_text_new (); + g_object_set (combo, "margin", 10, NULL); + gtk_widget_set_halign (combo, GTK_ALIGN_END); + gtk_widget_set_valign (combo, GTK_ALIGN_BASELINE); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), _("None")); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), _("Horizontal")); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), _("Vertical")); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), _("Both")); + g_object_bind_property (group, "mode", + combo, "active", + G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); + gtk_box_pack_start (GTK_BOX (box2), combo, FALSE, FALSE, 0); + + listbox = gtk_list_box_new (); + gtk_container_add (GTK_CONTAINER (box), listbox); + gtk_list_box_set_selection_mode (GTK_LIST_BOX (listbox), GTK_SELECTION_NONE); + + widgets = gtk_size_group_get_widgets (group); + for (l = widgets; l; l = l->next) + add_widget (sl, GTK_LIST_BOX (listbox), GTK_WIDGET (l->data)); + + gtk_widget_show_all (frame); +} + +void +gtk_inspector_size_groups_set_object (GtkInspectorSizeGroups *sl, + GObject *object) +{ + clear_view (sl); + gtk_widget_hide (GTK_WIDGET (sl)); + + if (GTK_IS_WIDGET (object)) + { + GSList *groups, *l; + + gtk_widget_show (GTK_WIDGET (sl)); + groups = _gtk_widget_get_sizegroups (GTK_WIDGET (object)); + for (l = groups; l; l = l->next) + { + GtkSizeGroup *group = l->data; + add_size_group (sl, group); + } + } +} + +static void +gtk_inspector_size_groups_init (GtkInspectorSizeGroups *sl) +{ + g_object_set (sl, + "orientation", GTK_ORIENTATION_VERTICAL, + "margin", 40, + "spacing", 20, + NULL); +} + +static void +gtk_inspector_size_groups_class_init (GtkInspectorSizeGroupsClass *klass) +{ +} + +// vim: set et sw=2 ts=2: diff --git a/gtk/inspector/size-groups.h b/gtk/inspector/size-groups.h new file mode 100644 index 0000000000..2d4ccaa904 --- /dev/null +++ b/gtk/inspector/size-groups.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2014 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef _GTK_INSPECTOR_SIZE_GROUPS_H_ +#define _GTK_INSPECTOR_SIZE_GROUPS_H_ + +#include + +#define GTK_TYPE_INSPECTOR_SIZE_GROUPS (gtk_inspector_size_groups_get_type()) +#define GTK_INSPECTOR_SIZE_GROUPS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_INSPECTOR_SIZE_GROUPS, GtkInspectorSizeGroups)) +#define GTK_INSPECTOR_SIZE_GROUPS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_INSPECTOR_SIZE_GROUPS, GtkInspectorSizeGroupsClass)) +#define GTK_INSPECTOR_IS_SIZE_GROUPS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_INSPECTOR_SIZE_GROUPS)) +#define GTK_INSPECTOR_IS_SIZE_GROUPS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_INSPECTOR_SIZE_GROUPS)) +#define GTK_INSPECTOR_SIZE_GROUPS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_INSPECTOR_SIZE_GROUPS, GtkInspectorSizeGroupsClass)) + + +typedef struct _GtkInspectorSizeGroups +{ + GtkBox parent; +} GtkInspectorSizeGroups; + +typedef struct _GtkInspectorSizeGroupsClass +{ + GtkBoxClass parent; +} GtkInspectorSizeGroupsClass; + +G_BEGIN_DECLS + +GType gtk_inspector_size_groups_get_type (void); +void gtk_inspector_size_groups_set_object (GtkInspectorSizeGroups *sl, + GObject *object); + +G_END_DECLS + +#endif // _GTK_INSPECTOR_SIZE_GROUPS_H_ + +// vim: set et sw=2 ts=2: diff --git a/gtk/inspector/window.c b/gtk/inspector/window.c index 4d8b27f02e..25290ef472 100644 --- a/gtk/inspector/window.c +++ b/gtk/inspector/window.c @@ -34,6 +34,7 @@ #include "python-hooks.h" #include "python-shell.h" #include "button-path.h" +#include "size-groups.h" #include "data-list.h" #include "signals-list.h" #include "actions.h" @@ -70,6 +71,7 @@ on_widget_tree_selection_changed (GtkInspectorWidgetTree *wt, gtk_inspector_button_path_set_object (GTK_INSPECTOR_BUTTON_PATH (iw->button_path), selected); gtk_inspector_classes_list_set_object (GTK_INSPECTOR_CLASSES_LIST (iw->classes_list), selected); gtk_inspector_css_editor_set_object (GTK_INSPECTOR_CSS_EDITOR (iw->widget_css_editor), selected); + gtk_inspector_size_groups_set_object (GTK_INSPECTOR_SIZE_GROUPS (iw->size_groups), selected); gtk_inspector_data_list_set_object (GTK_INSPECTOR_DATA_LIST (iw->data_list), selected); gtk_inspector_actions_set_object (GTK_INSPECTOR_ACTIONS (iw->actions), selected); if (GTK_IS_WIDGET (selected)) @@ -168,6 +170,7 @@ gtk_inspector_window_class_init (GtkInspectorWindowClass *klass) gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, object_hierarchy); gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, python_shell); gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, widget_popup); + gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, size_groups); gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, data_list); gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, actions); diff --git a/gtk/inspector/window.ui b/gtk/inspector/window.ui index 6b29a6d0ce..4ee58ec9a2 100644 --- a/gtk/inspector/window.ui +++ b/gtk/inspector/window.ui @@ -197,6 +197,20 @@ Custom CSS + + + + + True + True + + + + + True + Sizegroups + +