diff options
author | Matthias Clasen <mclasen@redhat.com> | 2021-01-21 18:15:57 +0000 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2021-01-21 18:15:57 +0000 |
commit | 5a3c3d821020f5a6527816c507a64c5599a6d7b8 (patch) | |
tree | d9f0879665576dfa971f37ea7c259a7ea233abb6 | |
parent | 40446201ff8f756a7a838ee9e1c3709298bd032f (diff) | |
parent | ccd9827b639ce8e1593787510f9071b658e3bc7e (diff) | |
download | gtk+-5a3c3d821020f5a6527816c507a64c5599a6d7b8.tar.gz |
Merge branch 'inspector-controllers' into 'master'
Inspector controllers
See merge request GNOME/gtk!3101
-rw-r--r-- | gtk/inspector/action-editor.c | 276 | ||||
-rw-r--r-- | gtk/inspector/action-editor.h | 9 | ||||
-rw-r--r-- | gtk/inspector/actions.c | 73 | ||||
-rw-r--r-- | gtk/inspector/actions.ui | 2 | ||||
-rw-r--r-- | gtk/inspector/controllers.c | 248 | ||||
-rw-r--r-- | gtk/inspector/meson.build | 7 | ||||
-rw-r--r-- | gtk/inspector/shortcuts.c | 178 | ||||
-rw-r--r-- | gtk/inspector/variant-editor.c | 238 | ||||
-rw-r--r-- | gtk/inspector/variant-editor.h | 54 |
9 files changed, 648 insertions, 437 deletions
diff --git a/gtk/inspector/action-editor.c b/gtk/inspector/action-editor.c index b4c04fdd0e..980b31ab1a 100644 --- a/gtk/inspector/action-editor.c +++ b/gtk/inspector/action-editor.c @@ -19,8 +19,8 @@ #include <glib/gi18n-lib.h> #include "action-editor.h" +#include "variant-editor.h" -#include "gtksizegroup.h" #include "gtktogglebutton.h" #include "gtkentry.h" #include "gtklabel.h" @@ -41,7 +41,7 @@ struct _GtkInspectorActionEditor GtkWidget *activate_button; GtkWidget *parameter_entry; GtkWidget *state_entry; - GtkSizeGroup *sg; + GtkWidget *state_editor; }; typedef struct @@ -59,147 +59,7 @@ enum G_DEFINE_TYPE (GtkInspectorActionEditor, gtk_inspector_action_editor, GTK_TYPE_WIDGET) -static void -gtk_inspector_action_editor_init (GtkInspectorActionEditor *editor) -{ - GtkBoxLayout *layout; - - layout = GTK_BOX_LAYOUT (gtk_widget_get_layout_manager (GTK_WIDGET (editor))); - gtk_orientable_set_orientation (GTK_ORIENTABLE (layout), GTK_ORIENTATION_HORIZONTAL); - gtk_box_layout_set_spacing (layout, 10); -} - -typedef void (*VariantEditorChanged) (GtkWidget *editor, gpointer data); - -typedef struct -{ - GtkWidget *editor; - VariantEditorChanged callback; - gpointer data; -} VariantEditorData; - -static void -variant_editor_changed_cb (GObject *obj, - GParamSpec *pspec, - VariantEditorData *data) -{ - data->callback (data->editor, data->data); -} - -static GtkWidget * -variant_editor_new (const GVariantType *type, - VariantEditorChanged callback, - gpointer data) -{ - GtkWidget *editor; - GtkWidget *label; - GtkWidget *entry; - VariantEditorData *d; - - d = g_new (VariantEditorData, 1); - d->callback = callback; - d->data = data; - - if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN)) - { - editor = gtk_toggle_button_new_with_label ("FALSE"); - g_signal_connect (editor, "notify::active", G_CALLBACK (variant_editor_changed_cb), d); - } - else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING)) - { - editor = gtk_entry_new (); - gtk_editable_set_width_chars (GTK_EDITABLE (editor), 10); - g_signal_connect (editor, "notify::text", G_CALLBACK (variant_editor_changed_cb), d); - } - else - { - editor = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10); - entry = gtk_entry_new (); - gtk_editable_set_width_chars (GTK_EDITABLE (entry), 10); - gtk_box_append (GTK_BOX (editor), entry); - label = gtk_label_new (g_variant_type_peek_string (type)); - gtk_box_append (GTK_BOX (editor), label); - g_signal_connect (entry, "notify::text", G_CALLBACK (variant_editor_changed_cb), d); - } - - g_object_set_data (G_OBJECT (editor), "type", (gpointer)type); - d->editor = editor; - g_object_set_data_full (G_OBJECT (editor), "callback", d, g_free); - - return editor; -} - -static void -variant_editor_set_value (GtkWidget *editor, - GVariant *value) -{ - const GVariantType *type; - gpointer data; - - data = g_object_get_data (G_OBJECT (editor), "callback"); - g_signal_handlers_block_by_func (editor, variant_editor_changed_cb, data); - - type = g_variant_get_type (value); - if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN)) - { - GtkToggleButton *tb = GTK_TOGGLE_BUTTON (editor); - GtkWidget *child; - - gtk_toggle_button_set_active (tb, g_variant_get_boolean (value)); - child = gtk_button_get_child (GTK_BUTTON (tb)); - gtk_label_set_text (GTK_LABEL (child), - g_variant_get_boolean (value) ? "TRUE" : "FALSE"); - } - else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING)) - { - GtkEntry *entry = GTK_ENTRY (editor); - gtk_editable_set_text (GTK_EDITABLE (entry), g_variant_get_string (value, NULL)); - } - else - { - GtkWidget *entry; - char *text; - - entry = gtk_widget_get_first_child (editor); - - text = g_variant_print (value, FALSE); - gtk_editable_set_text (GTK_EDITABLE (entry), text); - g_free (text); - } - - g_signal_handlers_unblock_by_func (editor, variant_editor_changed_cb, data); -} - -static GVariant * -variant_editor_get_value (GtkWidget *editor) -{ - const GVariantType *type; - GVariant *value; - - type = (const GVariantType *) g_object_get_data (G_OBJECT (editor), "type"); - if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN)) - { - GtkToggleButton *tb = GTK_TOGGLE_BUTTON (editor); - value = g_variant_new_boolean (gtk_toggle_button_get_active (tb)); - } - else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING)) - { - GtkEntry *entry = GTK_ENTRY (editor); - value = g_variant_new_string (gtk_editable_get_text (GTK_EDITABLE (entry))); - } - else - { - GtkWidget *entry; - const char *text; - - entry = gtk_widget_get_first_child (editor); - text = gtk_editable_get_text (GTK_EDITABLE (entry)); - - value = g_variant_parse (type, text, NULL, NULL, NULL); - } - - return value; -} +static void update_widgets (GtkInspectorActionEditor *r); static void activate_action (GtkWidget *button, @@ -208,11 +68,12 @@ activate_action (GtkWidget *button, GVariant *parameter = NULL; if (r->parameter_entry) - parameter = variant_editor_get_value (r->parameter_entry); + parameter = gtk_inspector_variant_editor_get_value (r->parameter_entry); if (G_IS_ACTION_GROUP (r->owner)) g_action_group_activate_action (G_ACTION_GROUP (r->owner), r->name, parameter); else if (GTK_IS_ACTION_MUXER (r->owner)) gtk_action_muxer_activate_action (GTK_ACTION_MUXER (r->owner), r->name, parameter); + update_widgets (r); } static void @@ -222,7 +83,7 @@ parameter_changed (GtkWidget *editor, GtkInspectorActionEditor *r = data; GVariant *value; - value = variant_editor_get_value (editor); + value = gtk_inspector_variant_editor_get_value (editor); gtk_widget_set_sensitive (r->activate_button, r->enabled && value != NULL); if (value) g_variant_unref (value); @@ -235,7 +96,7 @@ state_changed (GtkWidget *editor, GtkInspectorActionEditor *r = data; GVariant *value; - value = variant_editor_get_value (editor); + value = gtk_inspector_variant_editor_get_value (editor); if (value) { if (G_IS_ACTION_GROUP (r->owner)) @@ -246,6 +107,40 @@ state_changed (GtkWidget *editor, } static void +gtk_inspector_action_editor_init (GtkInspectorActionEditor *r) +{ + GtkBoxLayout *layout; + GtkWidget *row, *activate, *label; + + layout = GTK_BOX_LAYOUT (gtk_widget_get_layout_manager (GTK_WIDGET (r))); + gtk_orientable_set_orientation (GTK_ORIENTABLE (layout), GTK_ORIENTATION_HORIZONTAL); + gtk_box_layout_set_spacing (layout, 10); + + row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10); + activate = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10); + gtk_box_append (GTK_BOX (row), activate); + + r->activate_button = gtk_button_new_with_label (_("Activate")); + g_signal_connect (r->activate_button, "clicked", G_CALLBACK (activate_action), r); + + gtk_box_append (GTK_BOX (activate), r->activate_button); + + r->parameter_entry = gtk_inspector_variant_editor_new (NULL, parameter_changed, r); + gtk_widget_hide (r->parameter_entry); + gtk_box_append (GTK_BOX (activate), r->parameter_entry); + + gtk_widget_set_parent (row, GTK_WIDGET (r)); + + r->state_editor = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10); + label = gtk_label_new (_("Set State")); + gtk_box_append (GTK_BOX (r->state_editor), label); + r->state_entry = gtk_inspector_variant_editor_new (NULL, state_changed, r); + gtk_box_append (GTK_BOX (r->state_editor), r->state_entry); + gtk_widget_set_parent (r->state_editor, GTK_WIDGET (r)); + gtk_widget_hide (r->state_editor); +} + +static void update_enabled (GtkInspectorActionEditor *r, gboolean enabled) { @@ -274,7 +169,7 @@ update_state (GtkInspectorActionEditor *r, GVariant *state) { if (r->state_entry) - variant_editor_set_value (r->state_entry, state); + gtk_inspector_variant_editor_set_value (r->state_entry, state); } static void @@ -288,13 +183,9 @@ action_state_changed_cb (GActionGroup *group, } static void -constructed (GObject *object) +update_widgets (GtkInspectorActionEditor *r) { - GtkInspectorActionEditor *r = GTK_INSPECTOR_ACTION_EDITOR (object); GVariant *state; - GtkWidget *row; - GtkWidget *activate; - GtkWidget *label; if (G_IS_ACTION_GROUP (r->owner)) g_action_group_query_action (G_ACTION_GROUP (r->owner), r->name, @@ -307,40 +198,27 @@ constructed (GObject *object) else state = NULL; - row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10); - activate = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10); - gtk_box_append (GTK_BOX (row), activate); - if (r->sg) - gtk_size_group_add_widget (r->sg, activate); - - r->activate_button = gtk_button_new_with_label (_("Activate")); - g_signal_connect (r->activate_button, "clicked", G_CALLBACK (activate_action), r); - gtk_widget_set_sensitive (r->activate_button, r->enabled); - gtk_box_append (GTK_BOX (activate), r->activate_button); if (r->parameter_type) { - r->parameter_entry = variant_editor_new (r->parameter_type, parameter_changed, r); + gtk_inspector_variant_editor_set_type (r->parameter_entry, r->parameter_type); + gtk_widget_show (r->parameter_entry); gtk_widget_set_sensitive (r->parameter_entry, r->enabled); - gtk_box_append (GTK_BOX (activate), r->parameter_entry); } - - gtk_widget_set_parent (row, GTK_WIDGET (r)); + else + gtk_widget_hide (r->parameter_entry); if (state) { + if (r->state_type) + g_variant_type_free (r->state_type); r->state_type = g_variant_type_copy (g_variant_get_type (state)); - row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10); - label = gtk_label_new (_("Set State")); - if (r->sg) - gtk_size_group_add_widget (r->sg, label); - gtk_box_append (GTK_BOX (row), label); - r->state_entry = variant_editor_new (r->state_type, state_changed, r); - variant_editor_set_value (r->state_entry, state); - gtk_box_append (GTK_BOX (row), r->state_entry); - gtk_widget_set_parent (row, GTK_WIDGET (r)); + gtk_inspector_variant_editor_set_value (r->state_entry, state); + gtk_widget_show (r->state_editor); } + else + gtk_widget_hide (r->state_editor); if (G_IS_ACTION_GROUP (r->owner)) { @@ -358,11 +236,13 @@ dispose (GObject *object) GtkWidget *child; g_free (r->name); - g_clear_object (&r->sg); if (r->state_type) g_variant_type_free (r->state_type); - g_signal_handlers_disconnect_by_func (r->owner, action_enabled_changed_cb, r); - g_signal_handlers_disconnect_by_func (r->owner, action_state_changed_cb, r); + if (r->owner) + { + g_signal_handlers_disconnect_by_func (r->owner, action_enabled_changed_cb, r); + g_signal_handlers_disconnect_by_func (r->owner, action_state_changed_cb, r); + } while ((child = gtk_widget_get_first_child (GTK_WIDGET (r)))) gtk_widget_unparent (child); @@ -388,10 +268,6 @@ get_property (GObject *object, g_value_set_string (value, r->name); break; - case PROP_SIZEGROUP: - g_value_set_object (value, r->sg); - break; - default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; @@ -409,6 +285,11 @@ set_property (GObject *object, switch (param_id) { case PROP_OWNER: + if (r->owner) + { + g_signal_handlers_disconnect_by_func (r->owner, action_enabled_changed_cb, r); + g_signal_handlers_disconnect_by_func (r->owner, action_state_changed_cb, r); + } r->owner = g_value_get_object (value); break; @@ -417,10 +298,6 @@ set_property (GObject *object, r->name = g_value_dup_string (value); break; - case PROP_SIZEGROUP: - r->sg = g_value_dup_object (value); - break; - default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); break; @@ -433,35 +310,34 @@ gtk_inspector_action_editor_class_init (GtkInspectorActionEditorClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - object_class->constructed = constructed; object_class->dispose = dispose; object_class->get_property = get_property; object_class->set_property = set_property; g_object_class_install_property (object_class, PROP_OWNER, g_param_spec_object ("owner", "Owner", "The owner of the action", - G_TYPE_OBJECT, G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); + G_TYPE_OBJECT, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_NAME, g_param_spec_string ("name", "Name", "The action name", - NULL, G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); - g_object_class_install_property (object_class, PROP_SIZEGROUP, - g_param_spec_object ("sizegroup", "Size Group", "The Size Group for activate", - GTK_TYPE_SIZE_GROUP, G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); + NULL, G_PARAM_READWRITE)); gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT); } GtkWidget * -gtk_inspector_action_editor_new (GObject *owner, - const char *name, - GtkSizeGroup *activate) +gtk_inspector_action_editor_new (void) +{ + return g_object_new (GTK_TYPE_INSPECTOR_ACTION_EDITOR, NULL); +} + +void +gtk_inspector_action_editor_set (GtkInspectorActionEditor *self, + GObject *owner, + const char *name) { - return g_object_new (GTK_TYPE_INSPECTOR_ACTION_EDITOR, - "owner", owner, - "name", name, - "sizegroup", activate, - NULL); + g_object_set (self, "owner", owner, "name", name, NULL); + update_widgets (self); } void diff --git a/gtk/inspector/action-editor.h b/gtk/inspector/action-editor.h index db13c6c447..c918a9a55c 100644 --- a/gtk/inspector/action-editor.h +++ b/gtk/inspector/action-editor.h @@ -33,10 +33,11 @@ typedef struct _GtkInspectorActionEditor GtkInspectorActionEditor; G_BEGIN_DECLS GType gtk_inspector_action_editor_get_type (void); -GtkWidget *gtk_inspector_action_editor_new (GObject *owner, - const char *name, - GtkSizeGroup *activate); -void gtk_inspector_action_editor_update (GtkInspectorActionEditor *r, +GtkWidget *gtk_inspector_action_editor_new (void); +void gtk_inspector_action_editor_set (GtkInspectorActionEditor *self, + GObject *owner, + const char *name); +void gtk_inspector_action_editor_update (GtkInspectorActionEditor *self, gboolean enabled, GVariant *state); diff --git a/gtk/inspector/actions.c b/gtk/inspector/actions.c index 9c01e7475b..1f8a46ca5a 100644 --- a/gtk/inspector/actions.c +++ b/gtk/inspector/actions.c @@ -46,6 +46,7 @@ struct _GtkInspectorActions GObject *object; GListStore *actions; + GtkSortListModel *sorted; GtkColumnViewColumn *name; }; @@ -90,6 +91,7 @@ setup_name_cb (GtkSignalListItemFactory *factory, label = gtk_label_new (NULL); gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_widget_add_css_class (label, "cell"); gtk_list_item_set_child (list_item, label); } @@ -114,6 +116,7 @@ setup_enabled_cb (GtkSignalListItemFactory *factory, label = gtk_label_new (NULL); gtk_label_set_xalign (GTK_LABEL (label), 0.5); + gtk_widget_add_css_class (label, "cell"); gtk_list_item_set_child (list_item, label); } @@ -149,8 +152,8 @@ setup_parameter_cb (GtkSignalListItemFactory *factory, label = gtk_label_new (NULL); gtk_label_set_xalign (GTK_LABEL (label), 0.5); - gtk_list_item_set_child (list_item, label); gtk_widget_add_css_class (label, "cell"); + gtk_list_item_set_child (list_item, label); } static void @@ -189,8 +192,8 @@ setup_state_cb (GtkSignalListItemFactory *factory, gtk_widget_set_margin_start (label, 5); gtk_widget_set_margin_end (label, 5); gtk_label_set_xalign (GTK_LABEL (label), 0.0); - gtk_list_item_set_child (list_item, label); gtk_widget_add_css_class (label, "cell"); + gtk_list_item_set_child (list_item, label); } static void @@ -202,7 +205,6 @@ bind_state_cb (GtkSignalListItemFactory *factory, GObject *owner; const char *name; GVariant *state; - char *state_string; item = gtk_list_item_get_item (list_item); label = gtk_list_item_get_child (list_item); @@ -218,15 +220,27 @@ bind_state_cb (GtkSignalListItemFactory *factory, state = NULL; if (state) - state_string = g_variant_print (state, FALSE); + { + char *state_string; + + state_string = g_variant_print (state, FALSE); + gtk_label_set_label (GTK_LABEL (label), state_string); + g_free (state_string); + g_variant_unref (state); + } else - state_string = g_strdup (""); + gtk_label_set_label (GTK_LABEL (label), ""); +} - gtk_label_set_label (GTK_LABEL (label), state_string); +static void +setup_changes_cb (GtkSignalListItemFactory *factory, + GtkListItem *list_item) +{ + GtkWidget *editor; - g_free (state_string); - if (state) - g_variant_unref (state); + editor = gtk_inspector_action_editor_new (); + gtk_widget_add_css_class (editor, "cell"); + gtk_list_item_set_child (list_item, editor); } static void @@ -239,20 +253,14 @@ bind_changes_cb (GtkSignalListItemFactory *factory, GtkWidget *editor; item = gtk_list_item_get_item (list_item); + editor = gtk_list_item_get_child (list_item); owner = action_holder_get_owner (ACTION_HOLDER (item)); name = action_holder_get_name (ACTION_HOLDER (item)); - editor = gtk_inspector_action_editor_new (owner, name, NULL); - gtk_widget_add_css_class (editor, "cell"); - gtk_list_item_set_child (list_item, editor); -} - -static void -unbind_changes_cb (GtkSignalListItemFactory *factory, - GtkListItem *list_item) -{ - gtk_list_item_set_child (list_item, NULL); + gtk_inspector_action_editor_set (GTK_INSPECTOR_ACTION_EDITOR (editor), + owner, + name); } static void @@ -284,12 +292,15 @@ add_muxer (GtkInspectorActions *sl, static gboolean reload (GtkInspectorActions *sl) { - g_list_store_remove_all (sl->actions); + gboolean loaded = FALSE; + + g_object_unref (sl->actions); + sl->actions = g_list_store_new (ACTION_TYPE_HOLDER); if (GTK_IS_APPLICATION (sl->object)) { add_group (sl, G_ACTION_GROUP (sl->object)); - return TRUE; + loaded = TRUE; } else if (GTK_IS_WIDGET (sl->object)) { @@ -299,11 +310,13 @@ reload (GtkInspectorActions *sl) if (muxer) { add_muxer (sl, muxer); - return TRUE; + loaded = TRUE; } } - return FALSE; + gtk_sort_list_model_set_model (sl->sorted, G_LIST_MODEL (sl->actions)); + + return loaded; } static void @@ -325,10 +338,10 @@ gtk_inspector_actions_set_object (GtkInspectorActions *sl, gtk_stack_page_set_visible (page, FALSE); g_set_object (&sl->object, object); - loaded = reload (sl); - gtk_stack_page_set_visible (page, loaded); gtk_column_view_sort_by_column (GTK_COLUMN_VIEW (sl->list), sl->name, GTK_SORT_ASCENDING); + loaded = reload (sl); + gtk_stack_page_set_visible (page, loaded); } static void @@ -382,7 +395,6 @@ constructed (GObject *object) { GtkInspectorActions *sl = GTK_INSPECTOR_ACTIONS (object); GtkSorter *sorter; - GListModel *sorted; GListModel *model; g_signal_connect_swapped (sl->button, "clicked", @@ -397,9 +409,9 @@ constructed (GObject *object) g_object_unref (sorter); sl->actions = g_list_store_new (ACTION_TYPE_HOLDER); - sorted = G_LIST_MODEL (gtk_sort_list_model_new (g_object_ref (G_LIST_MODEL (sl->actions)), - g_object_ref (gtk_column_view_get_sorter (GTK_COLUMN_VIEW (sl->list))))); - model = G_LIST_MODEL (gtk_no_selection_new (sorted)); + sl->sorted = gtk_sort_list_model_new (g_object_ref (G_LIST_MODEL (sl->actions)), + g_object_ref (gtk_column_view_get_sorter (GTK_COLUMN_VIEW (sl->list)))); + model = G_LIST_MODEL (gtk_no_selection_new (g_object_ref (G_LIST_MODEL (sl->sorted)))); gtk_column_view_set_model (GTK_COLUMN_VIEW (sl->list), GTK_SELECTION_MODEL (model)); g_object_unref (model); } @@ -410,6 +422,7 @@ dispose (GObject *object) GtkInspectorActions *sl = GTK_INSPECTOR_ACTIONS (object); GtkWidget *child; + g_clear_object (&sl->sorted); g_clear_object (&sl->actions); g_clear_object (&sl->object); @@ -445,8 +458,8 @@ gtk_inspector_actions_class_init (GtkInspectorActionsClass *klass) gtk_widget_class_bind_template_callback (widget_class, bind_parameter_cb); gtk_widget_class_bind_template_callback (widget_class, setup_state_cb); gtk_widget_class_bind_template_callback (widget_class, bind_state_cb); + gtk_widget_class_bind_template_callback (widget_class, setup_changes_cb); gtk_widget_class_bind_template_callback (widget_class, bind_changes_cb); - gtk_widget_class_bind_template_callback (widget_class, unbind_changes_cb); gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT); } diff --git a/gtk/inspector/actions.ui b/gtk/inspector/actions.ui index f48320ceff..6b5982555b 100644 --- a/gtk/inspector/actions.ui +++ b/gtk/inspector/actions.ui @@ -64,8 +64,8 @@ <property name="expand">1</property> <property name="factory"> <object class="GtkSignalListItemFactory"> + <signal name="setup" handler="setup_changes_cb"/> <signal name="bind" handler="bind_changes_cb"/> - <signal name="unbind" handler="unbind_changes_cb"/> </object> </property> </object> diff --git a/gtk/inspector/controllers.c b/gtk/inspector/controllers.c index 83b35c6134..08144f1e10 100644 --- a/gtk/inspector/controllers.c +++ b/gtk/inspector/controllers.c @@ -24,27 +24,24 @@ #include "gtkdropdown.h" #include "gtkbox.h" #include "gtkcustomsorter.h" -#include "gtkflattenlistmodel.h" -#include "gtkframe.h" #include "gtkgesture.h" #include "gtklabel.h" -#include "gtklistbox.h" -#include "gtkmaplistmodel.h" -#include "gtkpropertylookuplistmodelprivate.h" #include "gtkscrolledwindow.h" -#include "gtksizegroup.h" #include "gtksortlistmodel.h" #include "gtkstack.h" #include "gtkwidgetprivate.h" #include "window.h" +#include "gtksignallistitemfactory.h" +#include "gtkcolumnview.h" +#include "gtkcolumnviewcolumn.h" +#include "gtklistitem.h" +#include "gtknoselection.h" struct _GtkInspectorControllers { GtkWidget parent_instance; - GtkWidget *listbox; - GtkPropertyLookupListModel *model; - GtkSizeGroup *sizegroup; + GtkWidget *view; }; struct _GtkInspectorControllersClass @@ -55,117 +52,160 @@ struct _GtkInspectorControllersClass G_DEFINE_TYPE (GtkInspectorControllers, gtk_inspector_controllers, GTK_TYPE_WIDGET) static void -row_activated (GtkListBox *box, - GtkListBoxRow *row, +row_activated (GtkColumnView *view, + guint position, GtkInspectorControllers *self) { GtkInspectorWindow *iw; + GListModel *model; GObject *controller; iw = GTK_INSPECTOR_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_INSPECTOR_WINDOW)); - controller = G_OBJECT (g_object_get_data (G_OBJECT (row), "controller")); - + model = G_LIST_MODEL (gtk_column_view_get_model (view)); + controller = g_list_model_get_item (model, position); gtk_inspector_window_push_object (iw, controller, CHILD_KIND_CONTROLLER, 0); + g_object_unref (controller); } static void -gtk_inspector_controllers_init (GtkInspectorControllers *self) +setup_row (GtkSignalListItemFactory *factory, + GtkListItem *list_item, + gpointer data) { - GtkWidget *sw, *box; + GtkWidget *label; - self->sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + label = gtk_label_new (""); + gtk_label_set_xalign (GTK_LABEL (label), 0); + gtk_list_item_set_child (list_item, label); +} - sw = gtk_scrolled_window_new (); +static void +bind_type (GtkSignalListItemFactory *factory, + GtkListItem *list_item, + gpointer data) +{ + GtkWidget *label; + GtkEventController *controller; - box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10); - g_object_set (box, - "margin-start", 60, - "margin-end", 60, - "margin-top", 60, - "margin-bottom", 30, - NULL); - gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), box); - gtk_widget_set_hexpand (box, TRUE); - gtk_widget_set_vexpand (box, TRUE); - - self->listbox = gtk_list_box_new (); - gtk_widget_add_css_class (self->listbox, "frame"); - gtk_widget_set_halign (self->listbox, GTK_ALIGN_CENTER); - g_signal_connect (self->listbox, "row-activated", G_CALLBACK (row_activated), self); - gtk_list_box_set_selection_mode (GTK_LIST_BOX (self->listbox), GTK_SELECTION_NONE); - gtk_box_append (GTK_BOX (box), self->listbox); + label = gtk_list_item_get_child (list_item); + controller = gtk_list_item_get_item (list_item); - gtk_widget_set_parent (sw, GTK_WIDGET (self)); + gtk_label_set_label (GTK_LABEL (label), G_OBJECT_TYPE_NAME (controller)); } static void -phase_changed_cb (GtkDropDown *dropdown, - GParamSpec *pspec, - GtkInspectorControllers *self) +bind_name (GtkSignalListItemFactory *factory, + GtkListItem *list_item, + gpointer data) { - GtkWidget *row; - GtkPropagationPhase phase; + GtkWidget *label; GtkEventController *controller; - phase = gtk_drop_down_get_selected (dropdown); - row = gtk_widget_get_ancestor (GTK_WIDGET (dropdown), GTK_TYPE_LIST_BOX_ROW); - controller = GTK_EVENT_CONTROLLER (g_object_get_data (G_OBJECT (row), "controller")); - gtk_event_controller_set_propagation_phase (controller, phase); + label = gtk_list_item_get_child (list_item); + controller = gtk_list_item_get_item (list_item); + + gtk_label_set_label (GTK_LABEL (label), gtk_event_controller_get_name (controller)); } -static GtkWidget * -create_controller_widget (gpointer item, - gpointer user_data) +static void +bind_phase (GtkSignalListItemFactory *factory, + GtkListItem *list_item, + gpointer data) { - GtkInspectorControllers *self = user_data; - GtkEventController *controller = item; - GtkWidget *row; - GtkWidget *box; GtkWidget *label; - GtkWidget *dropdown; - const char *phases[5]; - - row = gtk_list_box_row_new (); - gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), TRUE); - box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 40); - gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), box); - gtk_widget_set_margin_start (box, 10); - gtk_widget_set_margin_end (box, 10); - gtk_widget_set_margin_top (box, 10); - gtk_widget_set_margin_bottom (box, 10); - label = gtk_label_new (G_OBJECT_TYPE_NAME (controller)); - g_object_set (label, "xalign", 0.0, NULL); - gtk_box_append (GTK_BOX (box), label); - gtk_size_group_add_widget (self->sizegroup, label); - gtk_widget_set_halign (label, GTK_ALIGN_START); - gtk_widget_set_valign (label, GTK_ALIGN_BASELINE); - - phases[0] = C_("event phase", "None"); - phases[1] = C_("event phase", "Capture"); - phases[2] = C_("event phase", "Bubble"); - phases[3] = C_("event phase", "Target"); - phases[4] = NULL; - - dropdown = gtk_drop_down_new_from_strings (phases); - gtk_drop_down_set_selected (GTK_DROP_DOWN (dropdown), gtk_event_controller_get_propagation_phase (controller)); - gtk_box_append (GTK_BOX (box), dropdown); - gtk_widget_set_halign (label, GTK_ALIGN_END); - gtk_widget_set_valign (label, GTK_ALIGN_BASELINE); - - g_object_set_data (G_OBJECT (row), "controller", controller); - g_signal_connect (dropdown, "notify::selected", G_CALLBACK (phase_changed_cb), self); - - return row; + GtkEventController *controller; + const char *name; + + label = gtk_list_item_get_child (list_item); + controller = gtk_list_item_get_item (list_item); + + switch (gtk_event_controller_get_propagation_phase (controller)) + { + case GTK_PHASE_NONE: + name = C_("event phase", "None"); + break; + case GTK_PHASE_CAPTURE: + name = C_("event phase", "Capture"); + break; + case GTK_PHASE_BUBBLE: + name = C_("event phase", "Bubble"); + break; + case GTK_PHASE_TARGET: + name = C_("event phase", "Target"); + break; + default: + g_assert_not_reached (); + } + + gtk_label_set_label (GTK_LABEL (label), name); } -static gpointer -map_to_controllers (gpointer widget, - gpointer unused) +static void +bind_limit (GtkSignalListItemFactory *factory, + GtkListItem *list_item, + gpointer data) { - gpointer result = gtk_widget_observe_controllers (widget); - g_object_unref (widget); - return result; + GtkWidget *label; + GtkEventController *controller; + + label = gtk_list_item_get_child (list_item); + controller = gtk_list_item_get_item (list_item); + + if (gtk_event_controller_get_propagation_limit (controller) == GTK_LIMIT_SAME_NATIVE) + gtk_label_set_label (GTK_LABEL (label), C_("propagation limit", "Native")); + else + gtk_label_set_label (GTK_LABEL (label), ""); +} + +static void +gtk_inspector_controllers_init (GtkInspectorControllers *self) +{ + GtkWidget *sw; + GtkListItemFactory *factory; + GtkColumnViewColumn *column; + + sw = gtk_scrolled_window_new (); + + self->view = gtk_column_view_new (NULL); + + factory = gtk_signal_list_item_factory_new (); + g_signal_connect (factory, "setup", G_CALLBACK (setup_row), NULL); + g_signal_connect (factory, "bind", G_CALLBACK (bind_type), NULL); + + column = gtk_column_view_column_new ("Type", factory); + gtk_column_view_append_column (GTK_COLUMN_VIEW (self->view), column); + g_object_unref (column); + + factory = gtk_signal_list_item_factory_new (); + g_signal_connect (factory, "setup", G_CALLBACK (setup_row), NULL); + g_signal_connect (factory, "bind", G_CALLBACK (bind_name), NULL); + + column = gtk_column_view_column_new ("Name", factory); + gtk_column_view_append_column (GTK_COLUMN_VIEW (self->view), column); + g_object_unref (column); + + factory = gtk_signal_list_item_factory_new (); + g_signal_connect (factory, "setup", G_CALLBACK (setup_row), NULL); + g_signal_connect (factory, "bind", G_CALLBACK (bind_phase), NULL); + + column = gtk_column_view_column_new ("Phase", factory); + gtk_column_view_append_column (GTK_COLUMN_VIEW (self->view), column); + g_object_unref (column); + + factory = gtk_signal_list_item_factory_new (); + g_signal_connect (factory, "setup", G_CALLBACK (setup_row), NULL); + g_signal_connect (factory, "bind", G_CALLBACK (bind_limit), NULL); + + column = gtk_column_view_column_new ("Limit", factory); + gtk_column_view_append_column (GTK_COLUMN_VIEW (self->view), column); + g_object_unref (column); + + g_signal_connect (self->view, "activate", G_CALLBACK (row_activated), self); + + gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), self->view); + + gtk_widget_set_parent (sw, GTK_WIDGET (self)); } static int @@ -222,39 +262,31 @@ gtk_inspector_controllers_set_object (GtkInspectorControllers *self, { GtkWidget *stack; GtkStackPage *page; - GtkMapListModel *map_model; - GtkFlattenListModel *flatten_model; + GListModel *model; GtkSortListModel *sort_model; GtkSorter *sorter; + GtkNoSelection *no_selection; stack = gtk_widget_get_parent (GTK_WIDGET (self)); page = gtk_stack_get_page (GTK_STACK (stack), GTK_WIDGET (self)); if (!GTK_IS_WIDGET (object)) { + gtk_column_view_set_model (GTK_COLUMN_VIEW (self->view), NULL); g_object_set (page, "visible", FALSE, NULL); return; } g_object_set (page, "visible", TRUE, NULL); - self->model = gtk_property_lookup_list_model_new (GTK_TYPE_WIDGET, "parent"); - gtk_property_lookup_list_model_set_object (self->model, object); - - map_model = gtk_map_list_model_new (G_LIST_MODEL (self->model), map_to_controllers, NULL, NULL); - - flatten_model = gtk_flatten_list_model_new (G_LIST_MODEL (map_model)); - + model = gtk_widget_observe_controllers (GTK_WIDGET (object)); sorter = GTK_SORTER (gtk_custom_sorter_new (compare_controllers, NULL, NULL)); - sort_model = gtk_sort_list_model_new (G_LIST_MODEL (flatten_model), sorter); + sort_model = gtk_sort_list_model_new (model, sorter); + no_selection = gtk_no_selection_new (G_LIST_MODEL (sort_model)); - gtk_list_box_bind_model (GTK_LIST_BOX (self->listbox), - G_LIST_MODEL (sort_model), - create_controller_widget, - self, - NULL); + gtk_column_view_set_model (GTK_COLUMN_VIEW (self->view), GTK_SELECTION_MODEL (no_selection)); - g_object_unref (sort_model); + g_object_unref (no_selection); } static void @@ -264,8 +296,6 @@ gtk_inspector_controllers_dispose (GObject *object) gtk_widget_unparent (gtk_widget_get_first_child (GTK_WIDGET (self))); - g_clear_object (&self->sizegroup); - G_OBJECT_CLASS (gtk_inspector_controllers_parent_class)->dispose (object); } diff --git a/gtk/inspector/meson.build b/gtk/inspector/meson.build index 8ccc41340b..0ae9927011 100644 --- a/gtk/inspector/meson.build +++ b/gtk/inspector/meson.build @@ -1,6 +1,7 @@ inspector_sources = files( 'a11y.c', 'action-editor.c', + 'action-holder.c', 'actions.c', 'baselineoverlay.c', 'cellrenderergraph.c', @@ -24,10 +25,12 @@ inspector_sources = files( 'misc-info.c', 'object-tree.c', 'prop-editor.c', + 'prop-holder.c', 'prop-list.c', 'recorder.c', 'recording.c', 'renderrecording.c', + 'resource-holder.c', 'resource-list.c', 'shortcuts.c', 'size-groups.c', @@ -38,9 +41,7 @@ inspector_sources = files( 'treewalk.c', 'type-info.c', 'updatesoverlay.c', + 'variant-editor.c', 'visual.c', 'window.c', - 'prop-holder.c', - 'resource-holder.c', - 'action-holder.c' ) diff --git a/gtk/inspector/shortcuts.c b/gtk/inspector/shortcuts.c index c5627ff892..08a1a419c2 100644 --- a/gtk/inspector/shortcuts.c +++ b/gtk/inspector/shortcuts.c @@ -20,135 +20,140 @@ #include "shortcuts.h" #include "gtklabel.h" -#include "gtklistbox.h" #include "gtksizegroup.h" #include "gtkstack.h" #include "gtkshortcut.h" #include "gtkshortcuttrigger.h" #include "gtkshortcutcontroller.h" +#include "gtksignallistitemfactory.h" +#include "gtklistitem.h" +#include "gtkcolumnview.h" +#include "gtkcolumnviewcolumn.h" +#include "gtkscrolledwindow.h" +#include "gtknoselection.h" +#include "gtkbinlayout.h" + struct _GtkInspectorShortcuts { GtkWidget parent; - GtkWidget *box; - GtkWidget *list; - - GtkSizeGroup *trigger; - GtkSizeGroup *action; + GtkWidget *view; }; G_DEFINE_TYPE (GtkInspectorShortcuts, gtk_inspector_shortcuts, GTK_TYPE_WIDGET) static void -gtk_inspector_shortcuts_init (GtkInspectorShortcuts *sl) +setup_row (GtkSignalListItemFactory *factory, + GtkListItem *list_item, + gpointer data) { - gtk_widget_init_template (GTK_WIDGET (sl)); + GtkWidget *label; + + label = gtk_label_new (""); + gtk_label_set_xalign (GTK_LABEL (label), 0); + gtk_list_item_set_child (list_item, label); } -static GtkWidget * -create_row (gpointer item, - gpointer user_data) +static void +bind_trigger (GtkSignalListItemFactory *factory, + GtkListItem *list_item, + gpointer data) { - GtkShortcut *shortcut = GTK_SHORTCUT (item); - GtkInspectorShortcuts *sl = GTK_INSPECTOR_SHORTCUTS (user_data); - GtkShortcutTrigger *trigger; - GtkShortcutAction *action; - char *s; - GtkWidget *row; GtkWidget *label; + GtkShortcut *shortcut; + GtkShortcutTrigger *trigger; + char *str; + label = gtk_list_item_get_child (list_item); + shortcut = gtk_list_item_get_item (list_item); trigger = gtk_shortcut_get_trigger (shortcut); + str = gtk_shortcut_trigger_to_label (trigger, gtk_widget_get_display (label)); + gtk_label_set_label (GTK_LABEL (label), str); + g_free (str); +} + +static void +bind_action (GtkSignalListItemFactory *factory, + GtkListItem *list_item, + gpointer data) +{ + GtkWidget *label; + GtkShortcut *shortcut; + GtkShortcutAction *action; + char *str; + + label = gtk_list_item_get_child (list_item); + shortcut = gtk_list_item_get_item (list_item); action = gtk_shortcut_get_action (shortcut); + str = gtk_shortcut_action_to_string (action); + gtk_label_set_label (GTK_LABEL (label), str); + g_free (str); +} + +static void +gtk_inspector_shortcuts_init (GtkInspectorShortcuts *self) +{ + GtkWidget *sw; + GtkListItemFactory *factory; + GtkColumnViewColumn *column; + + sw = gtk_scrolled_window_new (); + + self->view = gtk_column_view_new (NULL); + + factory = gtk_signal_list_item_factory_new (); + g_signal_connect (factory, "setup", G_CALLBACK (setup_row), NULL); + g_signal_connect (factory, "bind", G_CALLBACK (bind_trigger), NULL); - row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10); + column = gtk_column_view_column_new ("Trigger", factory); + gtk_column_view_append_column (GTK_COLUMN_VIEW (self->view), column); + g_object_unref (column); - s = gtk_shortcut_trigger_to_string (trigger); - label = gtk_label_new (s); - gtk_label_set_xalign (GTK_LABEL (label), 0.0); - g_free (s); - gtk_box_append (GTK_BOX (row), label); - gtk_size_group_add_widget (sl->trigger, label); + factory = gtk_signal_list_item_factory_new (); + g_signal_connect (factory, "setup", G_CALLBACK (setup_row), NULL); + g_signal_connect (factory, "bind", G_CALLBACK (bind_action), NULL); - s = gtk_shortcut_action_to_string (action); - label = gtk_label_new (s); - gtk_label_set_xalign (GTK_LABEL (label), 0.0); - g_free (s); - gtk_box_append (GTK_BOX (row), label); - gtk_size_group_add_widget (sl->action, label); + column = gtk_column_view_column_new ("Action", factory); + gtk_column_view_append_column (GTK_COLUMN_VIEW (self->view), column); + g_object_unref (column); - return row; + gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), self->view); + + gtk_widget_set_parent (sw, GTK_WIDGET (self)); } void -gtk_inspector_shortcuts_set_object (GtkInspectorShortcuts *sl, +gtk_inspector_shortcuts_set_object (GtkInspectorShortcuts *self, GObject *object) { GtkWidget *stack; GtkStackPage *page; + GtkNoSelection *no_selection; - stack = gtk_widget_get_parent (GTK_WIDGET (sl)); - page = gtk_stack_get_page (GTK_STACK (stack), GTK_WIDGET (sl)); + stack = gtk_widget_get_parent (GTK_WIDGET (self)); + page = gtk_stack_get_page (GTK_STACK (stack), GTK_WIDGET (self)); - if (GTK_IS_SHORTCUT_CONTROLLER (object)) - { - g_object_set (page, "visible", TRUE, NULL); - gtk_list_box_bind_model (GTK_LIST_BOX (sl->list), - G_LIST_MODEL (object), - create_row, - sl, - NULL); - } - else + if (!GTK_IS_SHORTCUT_CONTROLLER (object)) { + gtk_column_view_set_model (GTK_COLUMN_VIEW (self->view), NULL); g_object_set (page, "visible", FALSE, NULL); - gtk_list_box_bind_model (GTK_LIST_BOX (sl->list), - NULL, - NULL, - NULL, - NULL); + return; } -} -static void -gtk_inspector_shortcuts_measure (GtkWidget *widget, - GtkOrientation orientation, - int for_size, - int *minimum, - int *natural, - int *minimum_baseline, - int *natural_baseline) -{ - GtkInspectorShortcuts *shortcuts = GTK_INSPECTOR_SHORTCUTS (widget); - - gtk_widget_measure (shortcuts->box, - orientation, - for_size, - minimum, natural, - minimum_baseline, natural_baseline); -} + g_object_set (page, "visible", TRUE, NULL); -static void -gtk_inspector_shortcuts_size_allocate (GtkWidget *widget, - int width, - int height, - int baseline) -{ - GtkInspectorShortcuts *shortcuts = GTK_INSPECTOR_SHORTCUTS (widget); - - gtk_widget_size_allocate (shortcuts->box, - &(GtkAllocation) { 0, 0, width, height }, - baseline); + no_selection = gtk_no_selection_new (g_object_ref (G_LIST_MODEL (object))); + gtk_column_view_set_model (GTK_COLUMN_VIEW (self->view), GTK_SELECTION_MODEL (no_selection)); + g_object_unref (no_selection); } static void dispose (GObject *object) { - GtkInspectorShortcuts *shortcuts = GTK_INSPECTOR_SHORTCUTS (object); - GtkWidget *child; + GtkInspectorShortcuts *self = GTK_INSPECTOR_SHORTCUTS (object); - while ((child = gtk_widget_get_first_child (GTK_WIDGET (shortcuts)))) - gtk_widget_unparent (child); + gtk_widget_unparent (gtk_widget_get_first_child (GTK_WIDGET (self))); G_OBJECT_CLASS (gtk_inspector_shortcuts_parent_class)->dispose (object); } @@ -161,12 +166,5 @@ gtk_inspector_shortcuts_class_init (GtkInspectorShortcutsClass *klass) object_class->dispose = dispose; - widget_class->measure = gtk_inspector_shortcuts_measure; - widget_class->size_allocate = gtk_inspector_shortcuts_size_allocate; - - gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/inspector/shortcuts.ui"); - gtk_widget_class_bind_template_child (widget_class, GtkInspectorShortcuts, box); - gtk_widget_class_bind_template_child (widget_class, GtkInspectorShortcuts, list); - gtk_widget_class_bind_template_child (widget_class, GtkInspectorShortcuts, trigger); - gtk_widget_class_bind_template_child (widget_class, GtkInspectorShortcuts, action); + gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT); } diff --git a/gtk/inspector/variant-editor.c b/gtk/inspector/variant-editor.c new file mode 100644 index 0000000000..cf8a16a3fc --- /dev/null +++ b/gtk/inspector/variant-editor.c @@ -0,0 +1,238 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + */ + +#include "config.h" +#include <glib/gi18n-lib.h> + +#include "variant-editor.h" + +#include "gtksizegroup.h" +#include "gtktogglebutton.h" +#include "gtkentry.h" +#include "gtklabel.h" +#include "gtkbox.h" +#include "gtkbinlayout.h" + + +struct _GtkInspectorVariantEditor +{ + GtkWidget parent; + + const GVariantType *type; + + GtkWidget *editor; + GtkInspectorVariantEditorChanged callback; + gpointer data; +}; + +typedef struct +{ + GtkWidgetClass parent; +} GtkInspectorVariantEditorClass; + +static void +variant_editor_changed_cb (GObject *obj, + GParamSpec *pspec, + GtkInspectorVariantEditor *self) +{ + self->callback (GTK_WIDGET (self), self->data); +} + +G_DEFINE_TYPE (GtkInspectorVariantEditor, gtk_inspector_variant_editor, GTK_TYPE_WIDGET) + +static void +gtk_inspector_variant_editor_init (GtkInspectorVariantEditor *editor) +{ +} + + +static void +dispose (GObject *object) +{ + GtkInspectorVariantEditor *self = GTK_INSPECTOR_VARIANT_EDITOR (object); + + if (self->editor) + { + g_signal_handlers_disconnect_by_func (self->editor, variant_editor_changed_cb, self->data); + + gtk_widget_unparent (self->editor); + } + + G_OBJECT_CLASS (gtk_inspector_variant_editor_parent_class)->dispose (object); +} + +static void +gtk_inspector_variant_editor_class_init (GtkInspectorVariantEditorClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + object_class->dispose = dispose; + + gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT); +} + +static void +ensure_editor (GtkInspectorVariantEditor *self, + const GVariantType *type) +{ + if (self->type && + g_variant_type_equal (self->type, type)) + return; + + if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN)) + { + if (self->editor) + gtk_widget_unparent (self->editor); + + self->editor = gtk_toggle_button_new_with_label ("FALSE"); + g_signal_connect (self->editor, "notify::active", + G_CALLBACK (variant_editor_changed_cb), self); + } + else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING)) + { + if (self->editor) + gtk_widget_unparent (self->editor); + + self->editor = gtk_entry_new (); + gtk_editable_set_width_chars (GTK_EDITABLE (self->editor), 10); + g_signal_connect (self->editor, "notify::text", + G_CALLBACK (variant_editor_changed_cb), self); + } + else if (!GTK_IS_BOX (self->editor)) + { + GtkWidget *entry, *label; + + if (self->editor) + gtk_widget_unparent (self->editor); + + self->editor = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10); + entry = gtk_entry_new (); + gtk_editable_set_width_chars (GTK_EDITABLE (entry), 10); + gtk_box_append (GTK_BOX (self->editor), entry); + label = gtk_label_new (g_variant_type_peek_string (type)); + gtk_box_append (GTK_BOX (self->editor), label); + g_signal_connect (entry, "notify::text", + G_CALLBACK (variant_editor_changed_cb), self); + } + + self->type = type; + gtk_widget_set_parent (self->editor, GTK_WIDGET (self)); +} + +GtkWidget * +gtk_inspector_variant_editor_new (const GVariantType *type, + GtkInspectorVariantEditorChanged callback, + gpointer data) +{ + GtkInspectorVariantEditor *self; + + self = g_object_new (GTK_TYPE_INSPECTOR_VARIANT_EDITOR, NULL); + + self->callback = callback; + self->data = data; + + if (type) + ensure_editor (self, type); + + return GTK_WIDGET (self); +} + +void +gtk_inspector_variant_editor_set_type (GtkWidget *editor, + const GVariantType *type) +{ + GtkInspectorVariantEditor *self = GTK_INSPECTOR_VARIANT_EDITOR (editor); + + ensure_editor (self, type); +} + +void +gtk_inspector_variant_editor_set_value (GtkWidget *editor, + GVariant *value) +{ + GtkInspectorVariantEditor *self = GTK_INSPECTOR_VARIANT_EDITOR (editor); + + ensure_editor (self, g_variant_get_type (value)); + + g_signal_handlers_block_by_func (self->editor, variant_editor_changed_cb, self->data); + + if (g_variant_type_equal (self->type, G_VARIANT_TYPE_BOOLEAN)) + { + GtkToggleButton *tb = GTK_TOGGLE_BUTTON (self->editor); + + if (gtk_toggle_button_get_active (tb) != g_variant_get_boolean (value)) + { + gtk_toggle_button_set_active (tb, g_variant_get_boolean (value)); + gtk_button_set_label (GTK_BUTTON (tb), + g_variant_get_boolean (value) ? "TRUE" : "FALSE"); + } + } + else if (g_variant_type_equal (self->type, G_VARIANT_TYPE_STRING)) + { + GtkEntry *entry = GTK_ENTRY (self->editor); + + gtk_editable_set_text (GTK_EDITABLE (entry), + g_variant_get_string (value, NULL)); + } + else + { + GtkWidget *entry; + char *text; + + entry = gtk_widget_get_first_child (self->editor); + + text = g_variant_print (value, FALSE); + gtk_editable_set_text (GTK_EDITABLE (entry), text); + g_free (text); + } + + g_signal_handlers_unblock_by_func (self->editor, variant_editor_changed_cb, self->data); +} + +GVariant * +gtk_inspector_variant_editor_get_value (GtkWidget *editor) +{ + GtkInspectorVariantEditor *self = GTK_INSPECTOR_VARIANT_EDITOR (editor); + GVariant *value; + + if (self->type == NULL) + return NULL; + + if (g_variant_type_equal (self->type, G_VARIANT_TYPE_BOOLEAN)) + { + GtkToggleButton *tb = GTK_TOGGLE_BUTTON (self->editor); + value = g_variant_new_boolean (gtk_toggle_button_get_active (tb)); + } + else if (g_variant_type_equal (self->type, G_VARIANT_TYPE_STRING)) + { + GtkEntry *entry = GTK_ENTRY (self->editor); + value = g_variant_new_string (gtk_editable_get_text (GTK_EDITABLE (entry))); + } + else + { + GtkWidget *entry; + const char *text; + + entry = gtk_widget_get_first_child (self->editor); + text = gtk_editable_get_text (GTK_EDITABLE (entry)); + + value = g_variant_parse (self->type, text, NULL, NULL, NULL); + } + + return value; +} diff --git a/gtk/inspector/variant-editor.h b/gtk/inspector/variant-editor.h new file mode 100644 index 0000000000..88a9ae2e2e --- /dev/null +++ b/gtk/inspector/variant-editor.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 <http://www.gnu.org/licenses/>. + */ + +#ifndef _GTK_INSPECTOR_VARIANT_EDITOR_H_ +#define _GTK_INSPECTOR_VARIANT_EDITOR_H_ + + +#include <gtk/gtkwidget.h> +#include <gtk/gtksizegroup.h> + + +#define GTK_TYPE_INSPECTOR_VARIANT_EDITOR (gtk_inspector_variant_editor_get_type()) +#define GTK_INSPECTOR_VARIANT_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_INSPECTOR_VARIANT_EDITOR, GtkInspectorVariantEditor)) +#define GTK_INSPECTOR_IS_VARIANT_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_INSPECTOR_VARIANT_EDITOR)) + + +typedef struct _GtkInspectorVariantEditor GtkInspectorVariantEditor; + +G_BEGIN_DECLS + +typedef void (* GtkInspectorVariantEditorChanged) (GtkWidget *editor, + gpointer data); + +GType gtk_inspector_variant_editor_get_type (void); +GtkWidget *gtk_inspector_variant_editor_new (const GVariantType *type, + GtkInspectorVariantEditorChanged callback, + gpointer data); +void gtk_inspector_variant_editor_set_type (GtkWidget *editor, + const GVariantType *type); +void gtk_inspector_variant_editor_set_value (GtkWidget *editor, + GVariant *value); +GVariant * gtk_inspector_variant_editor_get_value (GtkWidget *editor); + + +G_END_DECLS + + +#endif // _GTK_INSPECTOR_VARIANT_EDITOR_H_ + +// vim: set et: |