diff --git a/gtk/inspector/Makefile.am b/gtk/inspector/Makefile.am index 49d843e8de..9e14945142 100644 --- a/gtk/inspector/Makefile.am +++ b/gtk/inspector/Makefile.am @@ -37,6 +37,8 @@ libgtkinspector_la_SOURCES = \ inspect-button.c \ menu.h \ menu.c \ + misc-info.h \ + misc-info.c \ object-hierarchy.h \ object-hierarchy.c \ prop-editor.h \ @@ -100,6 +102,7 @@ templates = \ data-list.ui \ general.ui \ menu.ui \ + misc-info.ui \ object-hierarchy.ui \ prop-list.ui \ resource-list.ui \ diff --git a/gtk/inspector/init.c b/gtk/inspector/init.c index 35abb3f876..ada924a2ad 100644 --- a/gtk/inspector/init.c +++ b/gtk/inspector/init.c @@ -30,6 +30,7 @@ #include "general.h" #include "gestures.h" #include "menu.h" +#include "misc-info.h" #include "object-hierarchy.h" #include "prop-list.h" #include "python-hooks.h" @@ -60,6 +61,7 @@ gtk_inspector_init (void) g_type_ensure (GTK_TYPE_INSPECTOR_GENERAL); g_type_ensure (GTK_TYPE_INSPECTOR_GESTURES); g_type_ensure (GTK_TYPE_INSPECTOR_MENU); + g_type_ensure (GTK_TYPE_INSPECTOR_MISC_INFO); g_type_ensure (GTK_TYPE_INSPECTOR_OBJECT_HIERARCHY); g_type_ensure (GTK_TYPE_INSPECTOR_PROP_LIST); g_type_ensure (GTK_TYPE_INSPECTOR_PYTHON_SHELL); diff --git a/gtk/inspector/inspector.gresource.xml b/gtk/inspector/inspector.gresource.xml index 6f6c3ab680..ef57d5eb19 100644 --- a/gtk/inspector/inspector.gresource.xml +++ b/gtk/inspector/inspector.gresource.xml @@ -8,6 +8,7 @@ data-list.ui general.ui menu.ui + misc-info.ui object-hierarchy.ui prop-list.ui style-prop-list.ui diff --git a/gtk/inspector/misc-info.c b/gtk/inspector/misc-info.c new file mode 100644 index 0000000000..07c5bb4f4d --- /dev/null +++ b/gtk/inspector/misc-info.c @@ -0,0 +1,317 @@ +/* + * 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 "misc-info.h" +#include "window.h" +#include "widget-tree.h" + +#include "gtktypebuiltins.h" +#include "gtktreeview.h" +#include "gtklabel.h" +#include "gtkframe.h" + +struct _GtkInspectorMiscInfoPrivate { + GtkInspectorWidgetTree *widget_tree; + + GtkWidget *widget; + + GtkWidget *state; + GtkWidget *default_widget_row; + GtkWidget *default_widget; + GtkWidget *default_widget_button; + GtkWidget *focus_widget_row; + GtkWidget *focus_widget; + GtkWidget *focus_widget_button; +}; + +enum +{ + PROP_0, + PROP_WIDGET_TREE +}; + +G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorMiscInfo, gtk_inspector_misc_info, GTK_TYPE_BOX) + +static gchar * +format_state_flags (GtkStateFlags state) +{ + GFlagsClass *fclass; + GString *str; + gint i; + + str = g_string_new (""); + + if (state) + { + fclass = g_type_class_ref (GTK_TYPE_STATE_FLAGS); + for (i = 0; i < fclass->n_values; i++) + { + if (state & fclass->values[i].value) + { + if (str->len) + g_string_append (str, " | "); + g_string_append (str, fclass->values[i].value_nick); + } + } + g_type_class_unref (fclass); + } + else + g_string_append (str, "normal"); + + return g_string_free (str, FALSE); +} + +static void +state_flags_changed (GtkWidget *w, GtkStateFlags old_flags, GtkInspectorMiscInfo *sl) +{ + gchar *s; + + s = format_state_flags (gtk_widget_get_state_flags (w)); + gtk_label_set_label (GTK_LABEL (sl->priv->state), s); + g_free (s); +} + +static void +disconnect_each_other (gpointer still_alive, + GObject *for_science) +{ + if (GTK_INSPECTOR_IS_MISC_INFO (still_alive)) + { + GtkInspectorMiscInfo *self = GTK_INSPECTOR_MISC_INFO (still_alive); + self->priv->widget = NULL; + } + + g_signal_handlers_disconnect_matched (still_alive, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, for_science); + g_object_weak_unref (still_alive, disconnect_each_other, for_science); +} + +static void +show_widget (GtkInspectorMiscInfo *sl, + GtkWidget *widget, + const gchar *name, + const gchar *tab) +{ + GtkTreeIter iter; + + g_object_set_data (G_OBJECT (sl->priv->widget_tree), "next-tab", (gpointer)tab); + if (gtk_inspector_widget_tree_find_object (sl->priv->widget_tree, G_OBJECT (widget), &iter)) + { + gtk_inspector_widget_tree_select_object (sl->priv->widget_tree, G_OBJECT (widget)); + } + else if (gtk_inspector_widget_tree_find_object (sl->priv->widget_tree, G_OBJECT (gtk_widget_get_parent (widget)), &iter)) + + { + gtk_inspector_widget_tree_append_object (sl->priv->widget_tree, G_OBJECT (widget), &iter, name); + gtk_inspector_widget_tree_select_object (sl->priv->widget_tree, G_OBJECT (widget)); + } + else + { + g_warning ("GtkInspector: couldn't find the widget in the tree"); + } +} + +static void +update_default_widget (GtkInspectorMiscInfo *sl) +{ + GtkWidget *widget; + + widget = gtk_window_get_default_widget (GTK_WINDOW (sl->priv->widget)); + if (widget) + { + gchar *tmp; + tmp = g_strdup_printf ("%p", widget); + gtk_label_set_label (GTK_LABEL (sl->priv->default_widget), tmp); + g_free (tmp); + gtk_widget_set_sensitive (sl->priv->default_widget_button, TRUE); + } + else + { + gtk_label_set_label (GTK_LABEL (sl->priv->default_widget), "NULL"); + gtk_widget_set_sensitive (sl->priv->default_widget_button, FALSE); + } +} + +static void +show_default_widget (GtkWidget *button, GtkInspectorMiscInfo *sl) +{ + GtkWidget *widget; + + update_default_widget (sl); + widget = gtk_window_get_default_widget (GTK_WINDOW (sl->priv->widget)); + if (widget) + show_widget (sl, widget, NULL, "properties"); +} + +static void +update_focus_widget (GtkInspectorMiscInfo *sl) +{ + GtkWidget *widget; + + widget = gtk_window_get_focus (GTK_WINDOW (sl->priv->widget)); + if (widget) + { + gchar *tmp; + tmp = g_strdup_printf ("%p", widget); + gtk_label_set_label (GTK_LABEL (sl->priv->focus_widget), tmp); + g_free (tmp); + gtk_widget_set_sensitive (sl->priv->focus_widget_button, TRUE); + } + else + { + gtk_label_set_label (GTK_LABEL (sl->priv->focus_widget), "NULL"); + gtk_widget_set_sensitive (sl->priv->focus_widget_button, FALSE); + } +} + +static void +set_focus_cb (GtkWindow *window, GtkWidget *focus, GtkInspectorMiscInfo *sl) +{ + update_focus_widget (sl); +} + +static void +show_focus_widget (GtkWidget *button, GtkInspectorMiscInfo *sl) +{ + GtkWidget *widget; + + widget = gtk_window_get_focus (GTK_WINDOW (sl->priv->widget)); + if (widget) + show_widget (sl, widget, NULL, "properties"); +} + +void +gtk_inspector_misc_info_set_object (GtkInspectorMiscInfo *sl, + GObject *object) +{ + if (sl->priv->widget) + { + g_signal_handlers_disconnect_by_func (sl->priv->widget, state_flags_changed, sl); + g_signal_handlers_disconnect_by_func (sl->priv->widget, set_focus_cb, sl); + disconnect_each_other (sl->priv->widget, G_OBJECT (sl)); + disconnect_each_other (sl, G_OBJECT (sl->priv->widget)); + sl->priv->widget = NULL; + } + + if (!GTK_IS_WIDGET (object)) + { + gtk_widget_hide (GTK_WIDGET (sl)); + return; + } + + gtk_widget_show (GTK_WIDGET (sl)); + + sl->priv->widget = GTK_WIDGET (object); + g_object_weak_ref (G_OBJECT (sl), disconnect_each_other, object); + g_object_weak_ref (G_OBJECT (object), disconnect_each_other, sl); + + g_signal_connect_object (object, "state-flags-changed", G_CALLBACK (state_flags_changed), sl, 0); + state_flags_changed (sl->priv->widget, 0, sl); + + if (GTK_IS_WINDOW (object)) + { + gtk_widget_show (sl->priv->default_widget_row); + gtk_widget_show (sl->priv->focus_widget_row); + + update_default_widget (sl); + update_focus_widget (sl); + + g_signal_connect_object (object, "set-focus", G_CALLBACK (set_focus_cb), sl, G_CONNECT_AFTER); + } + else + { + gtk_widget_hide (sl->priv->default_widget_row); + gtk_widget_hide (sl->priv->focus_widget_row); + } +} + +static void +gtk_inspector_misc_info_init (GtkInspectorMiscInfo *sl) +{ + sl->priv = gtk_inspector_misc_info_get_instance_private (sl); + gtk_widget_init_template (GTK_WIDGET (sl)); +} + +static void +get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + GtkInspectorMiscInfo *sl = GTK_INSPECTOR_MISC_INFO (object); + + switch (param_id) + { + case PROP_WIDGET_TREE: + g_value_take_object (value, sl->priv->widget_tree); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + GtkInspectorMiscInfo *sl = GTK_INSPECTOR_MISC_INFO (object); + + switch (param_id) + { + case PROP_WIDGET_TREE: + sl->priv->widget_tree = g_value_get_object (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +gtk_inspector_misc_info_class_init (GtkInspectorMiscInfoClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + object_class->get_property = get_property; + object_class->set_property = set_property; + + g_object_class_install_property (object_class, PROP_WIDGET_TREE, + g_param_spec_object ("widget-tree", "Widget Tree", "Widget tree", + GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/inspector/misc-info.ui"); + gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, state); + gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, default_widget_row); + gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, default_widget); + gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, default_widget_button); + gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, focus_widget_row); + gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, focus_widget); + gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMiscInfo, focus_widget_button); + + gtk_widget_class_bind_template_callback (widget_class, show_default_widget); + gtk_widget_class_bind_template_callback (widget_class, show_focus_widget); +} + +// vim: set et sw=2 ts=2: diff --git a/gtk/inspector/misc-info.h b/gtk/inspector/misc-info.h new file mode 100644 index 0000000000..537e946fbf --- /dev/null +++ b/gtk/inspector/misc-info.h @@ -0,0 +1,54 @@ +/* + * 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_MISC_INFO_H_ +#define _GTK_INSPECTOR_MISC_INFO_H_ + +#include + +#define GTK_TYPE_INSPECTOR_MISC_INFO (gtk_inspector_misc_info_get_type()) +#define GTK_INSPECTOR_MISC_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_INSPECTOR_MISC_INFO, GtkInspectorMiscInfo)) +#define GTK_INSPECTOR_MISC_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_INSPECTOR_MISC_INFO, GtkInspectorMiscInfoClass)) +#define GTK_INSPECTOR_IS_MISC_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_INSPECTOR_MISC_INFO)) +#define GTK_INSPECTOR_IS_MISC_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_INSPECTOR_MISC_INFO)) +#define GTK_INSPECTOR_MISC_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_INSPECTOR_MISC_INFO, GtkInspectorMiscInfoClass)) + + +typedef struct _GtkInspectorMiscInfoPrivate GtkInspectorMiscInfoPrivate; + +typedef struct _GtkInspectorMiscInfo +{ + GtkBox parent; + GtkInspectorMiscInfoPrivate *priv; +} GtkInspectorMiscInfo; + +typedef struct _GtkInspectorMiscInfoClass +{ + GtkBoxClass parent; +} GtkInspectorMiscInfoClass; + +G_BEGIN_DECLS + +GType gtk_inspector_misc_info_get_type (void); +void gtk_inspector_misc_info_set_object (GtkInspectorMiscInfo *sl, + GObject *object); + +G_END_DECLS + +#endif // _GTK_INSPECTOR_MISC_INFO_H_ + +// vim: set et sw=2 ts=2: diff --git a/gtk/inspector/misc-info.ui b/gtk/inspector/misc-info.ui new file mode 100644 index 0000000000..ee02fd507a --- /dev/null +++ b/gtk/inspector/misc-info.ui @@ -0,0 +1,147 @@ + + + + + horizontal + + + + + + + diff --git a/gtk/inspector/window.c b/gtk/inspector/window.c index ba110accd5..efd510d310 100644 --- a/gtk/inspector/window.c +++ b/gtk/inspector/window.c @@ -42,6 +42,7 @@ #include "signals-list.h" #include "actions.h" #include "menu.h" +#include "misc-info.h" #include "gestures.h" #include "gtknotebook.h" @@ -79,6 +80,7 @@ on_widget_tree_selection_changed (GtkInspectorWidgetTree *wt, gtk_inspector_style_prop_list_set_object (GTK_INSPECTOR_STYLE_PROP_LIST (iw->style_prop_list), selected); gtk_inspector_signals_list_set_object (GTK_INSPECTOR_SIGNALS_LIST (iw->signals_list), selected); gtk_inspector_object_hierarchy_set_object (GTK_INSPECTOR_OBJECT_HIERARCHY (iw->object_hierarchy), selected); + gtk_inspector_misc_info_set_object (GTK_INSPECTOR_MISC_INFO (iw->misc_info), selected); 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); @@ -210,6 +212,7 @@ gtk_inspector_window_class_init (GtkInspectorWindowClass *klass) gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, data_list); gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, actions); gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, menu); + gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, misc_info); gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, gestures); gtk_widget_class_bind_template_callback (widget_class, on_inspect); diff --git a/gtk/inspector/window.h b/gtk/inspector/window.h index a04fb0ff0f..b8f8b71e2d 100644 --- a/gtk/inspector/window.h +++ b/gtk/inspector/window.h @@ -56,6 +56,7 @@ typedef struct GtkWidget *data_list; GtkWidget *actions; GtkWidget *menu; + GtkWidget *misc_info; GtkWidget *gestures; GtkWidget *widget_popup; diff --git a/gtk/inspector/window.ui b/gtk/inspector/window.ui index c6317dae1b..63671b343e 100644 --- a/gtk/inspector/window.ui +++ b/gtk/inspector/window.ui @@ -105,6 +105,22 @@ True False True + + + True + widget_tree + + + True + True + + + + + True + Miscellaneous + + True diff --git a/po/POTFILES.in b/po/POTFILES.in index 0e7c3d384f..326b1045b0 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -285,6 +285,8 @@ gtk/inspector/gestures.c gtk/inspector/inspect-button.c gtk/inspector/menu.c gtk/inspector/menu.ui.h +gtk/inspector/misc-info.c +gtk/inspector/misc-info.ui.h gtk/inspector/object-hierarchy.ui.h gtk/inspector/prop-editor.c gtk/inspector/prop-list.ui.h