parasite: Use template for widget tree

This commit is contained in:
Matthias Clasen 2014-05-04 19:53:04 -04:00
parent 6f1a786413
commit ead05d0954
4 changed files with 199 additions and 251 deletions

View File

@ -5,5 +5,6 @@
<file>object-hierarchy.ui</file>
<file>css-editor.ui</file>
<file>classes-list.ui</file>
<file>widget-tree.ui</file>
</gresource>
</gresources>

View File

@ -35,8 +35,7 @@ enum
WIDGET_VISIBLE,
WIDGET_MAPPED,
OBJECT_ADDRESS,
SENSITIVE,
NUM_COLUMNS
SENSITIVE
};
@ -58,138 +57,47 @@ static guint widget_tree_signals[LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE_WITH_PRIVATE (ParasiteWidgetTree, parasite_widget_tree, GTK_TYPE_TREE_VIEW)
static void
parasite_widget_tree_on_widget_selected(GtkTreeSelection *selection,
ParasiteWidgetTree *widget_tree)
on_widget_selected (GtkTreeSelection *selection,
ParasiteWidgetTree *wt)
{
g_signal_emit(widget_tree, widget_tree_signals[WIDGET_CHANGED], 0);
g_signal_emit (wt, widget_tree_signals[WIDGET_CHANGED], 0);
}
static void
parasite_widget_tree_init (ParasiteWidgetTree *widget_tree)
parasite_widget_tree_init (ParasiteWidgetTree *wt)
{
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
GtkTreeSelection *selection;
wt->priv = parasite_widget_tree_get_instance_private (wt);
wt->priv->iters = g_hash_table_new_full (g_direct_hash,
g_direct_equal,
NULL,
(GDestroyNotify) gtk_tree_iter_free);
gtk_widget_init_template (GTK_WIDGET (wt));
widget_tree->priv = parasite_widget_tree_get_instance_private (widget_tree);
widget_tree->priv->iters = g_hash_table_new_full (g_direct_hash,
g_direct_equal,
NULL,
(GDestroyNotify) gtk_tree_iter_free);
widget_tree->priv->model = gtk_tree_store_new(
NUM_COLUMNS,
G_TYPE_POINTER, // OBJECT
G_TYPE_STRING, // OBJECT_TYPE
G_TYPE_STRING, // OBJECT_NAME
G_TYPE_BOOLEAN, // WIDGET_REALIZED
G_TYPE_BOOLEAN, // WIDGET_VISIBLE
G_TYPE_BOOLEAN, // WIDGET_MAPPED
G_TYPE_STRING, // OBJECT_ADDRESS
G_TYPE_BOOLEAN);// SENSITIVE
gtk_tree_view_set_model(GTK_TREE_VIEW(widget_tree),
GTK_TREE_MODEL(widget_tree->priv->model));
gtk_tree_view_set_enable_search(GTK_TREE_VIEW(widget_tree), TRUE);
gtk_tree_view_set_search_column(GTK_TREE_VIEW(widget_tree), OBJECT_NAME);
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget_tree));
g_signal_connect(G_OBJECT(selection), "changed",
G_CALLBACK(parasite_widget_tree_on_widget_selected),
widget_tree);
// Widget column
renderer = gtk_cell_renderer_text_new();
g_object_set(G_OBJECT(renderer), "scale", TREE_TEXT_SCALE, NULL);
column = gtk_tree_view_column_new_with_attributes("Widget", renderer,
"text", OBJECT_TYPE,
"sensitive", SENSITIVE,
NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(widget_tree), column);
gtk_tree_view_column_set_resizable(column, TRUE);
// Name column
renderer = gtk_cell_renderer_text_new();
g_object_set(G_OBJECT(renderer), "scale", TREE_TEXT_SCALE, NULL);
column = gtk_tree_view_column_new_with_attributes("Name", renderer,
"text", OBJECT_NAME,
"sensitive", SENSITIVE,
NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(widget_tree), column);
gtk_tree_view_column_set_resizable(column, TRUE);
// Realized column
renderer = gtk_cell_renderer_toggle_new();
g_object_set(G_OBJECT(renderer),
"activatable", TRUE,
"indicator-size", TREE_CHECKBOX_SIZE,
NULL);
column = gtk_tree_view_column_new_with_attributes("Realized",
renderer,
"active", WIDGET_REALIZED,
NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(widget_tree), column);
// Mapped column
renderer = gtk_cell_renderer_toggle_new();
g_object_set(G_OBJECT(renderer),
"activatable", TRUE,
"indicator-size", TREE_CHECKBOX_SIZE,
NULL);
column = gtk_tree_view_column_new_with_attributes("Mapped",
renderer,
"active", WIDGET_MAPPED,
NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(widget_tree), column);
// Visible column
renderer = gtk_cell_renderer_toggle_new();
g_object_set(G_OBJECT(renderer),
"activatable", TRUE,
"indicator-size", TREE_CHECKBOX_SIZE,
NULL);
column = gtk_tree_view_column_new_with_attributes("Visible",
renderer,
"active", WIDGET_VISIBLE,
NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(widget_tree), column);
// Poinder Address column
renderer = gtk_cell_renderer_text_new();
g_object_set(G_OBJECT(renderer),
"scale", TREE_TEXT_SCALE,
"family", "monospace",
NULL);
column = gtk_tree_view_column_new_with_attributes("Pointer Address",
renderer,
"text", OBJECT_ADDRESS,
"sensitive", SENSITIVE,
NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(widget_tree), column);
gtk_tree_view_column_set_resizable(column, TRUE);
parasite_widget_tree_append_object (widget_tree, G_OBJECT (gtk_settings_get_default ()), NULL);
parasite_widget_tree_append_object (wt, G_OBJECT (gtk_settings_get_default ()), NULL);
}
static void
parasite_widget_tree_class_init(ParasiteWidgetTreeClass *klass)
parasite_widget_tree_class_init (ParasiteWidgetTreeClass *klass)
{
klass->widget_changed = NULL;
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
widget_tree_signals[WIDGET_CHANGED] =
g_signal_new("widget-changed",
G_OBJECT_CLASS_TYPE(klass),
G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
G_STRUCT_OFFSET(ParasiteWidgetTreeClass, widget_changed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
klass->widget_changed = NULL;
widget_tree_signals[WIDGET_CHANGED] =
g_signal_new ("widget-changed",
G_OBJECT_CLASS_TYPE(klass),
G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
G_STRUCT_OFFSET(ParasiteWidgetTreeClass, widget_changed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/parasite/widget-tree.ui");
gtk_widget_class_bind_template_child_private (widget_class, ParasiteWidgetTree, model);
gtk_widget_class_bind_template_callback (widget_class, on_widget_selected);
}
GtkWidget *
parasite_widget_tree_new ()
{
@ -198,13 +106,13 @@ parasite_widget_tree_new ()
GObject *
parasite_widget_tree_get_selected_object (ParasiteWidgetTree *widget_tree)
parasite_widget_tree_get_selected_object (ParasiteWidgetTree *wt)
{
GtkTreeIter iter;
GtkTreeSelection *sel;
GtkTreeModel *model;
sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget_tree));
sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (wt));
if (gtk_tree_selection_get_selected (sel, &model, &iter))
{
@ -218,28 +126,33 @@ parasite_widget_tree_get_selected_object (ParasiteWidgetTree *widget_tree)
return NULL;
}
static void
on_container_forall(GtkWidget *widget, gpointer data)
typedef struct
{
GList **list = (GList **)data;
ParasiteWidgetTree *wt;
GtkTreeIter *iter;
} FindAllData;
*list = g_list_append(*list, widget);
static void
on_container_forall (GtkWidget *widget,
gpointer data)
{
FindAllData *d = data;
parasite_widget_tree_append_object (d->wt, G_OBJECT (widget), d->iter);
}
void
parasite_widget_tree_append_object (ParasiteWidgetTree *widget_tree,
parasite_widget_tree_append_object (ParasiteWidgetTree *wt,
GObject *object,
GtkTreeIter *parent_iter)
{
GtkTreeIter iter;
const char *class_name = G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS (object));
const char *name = NULL;
char *address;
const gchar *class_name = G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS (object));
const gchar *name = NULL;
gchar *address;
gboolean realized;
gboolean mapped;
gboolean visible;
gboolean is_widget;
GList *l;
realized = mapped = visible = FALSE;
@ -248,7 +161,6 @@ parasite_widget_tree_append_object (ParasiteWidgetTree *widget_tree,
{
GtkWidget *widget = GTK_WIDGET (object);
name = gtk_widget_get_name (GTK_WIDGET (object));
realized = gtk_widget_get_realized (widget);
mapped = gtk_widget_get_mapped (widget);
visible = gtk_widget_get_visible (widget);
@ -257,27 +169,19 @@ parasite_widget_tree_append_object (ParasiteWidgetTree *widget_tree,
if (name == NULL || g_strcmp0 (name, class_name) == 0)
{
if (GTK_IS_LABEL (object))
{
name = gtk_label_get_text (GTK_LABEL (object));
}
name = gtk_label_get_text (GTK_LABEL (object));
else if (GTK_IS_BUTTON (object))
{
name = gtk_button_get_label (GTK_BUTTON (object));
}
name = gtk_button_get_label (GTK_BUTTON (object));
else if (GTK_IS_WINDOW (object))
{
name = gtk_window_get_title (GTK_WINDOW (object));
}
name = gtk_window_get_title (GTK_WINDOW (object));
else
{
name = "";
}
name = "";
}
address = g_strdup_printf ("%p", object);
gtk_tree_store_append (widget_tree->priv->model, &iter, parent_iter);
gtk_tree_store_set (widget_tree->priv->model, &iter,
gtk_tree_store_append (wt->priv->model, &iter, parent_iter);
gtk_tree_store_set (wt->priv->model, &iter,
OBJECT, object,
OBJECT_TYPE, class_name,
OBJECT_NAME, name,
@ -287,106 +191,39 @@ parasite_widget_tree_append_object (ParasiteWidgetTree *widget_tree,
OBJECT_ADDRESS, address,
SENSITIVE, !is_widget || (realized && mapped && visible),
-1);
g_hash_table_insert (widget_tree->priv->iters, object, gtk_tree_iter_copy (&iter));
g_hash_table_insert (wt->priv->iters, object, gtk_tree_iter_copy (&iter));
g_free(address);
if (GTK_IS_CONTAINER (object))
{
GList* children = NULL;
FindAllData data;
/* Pick up all children, including those that are internal. */
gtk_container_forall (GTK_CONTAINER (object),
on_container_forall, &children);
data.wt = wt;
data.iter = &iter;
for (l = children; l != NULL; l = l->next)
{
parasite_widget_tree_append_object (widget_tree, l->data, &iter);
}
g_list_free(children);
gtk_container_forall (GTK_CONTAINER (object), on_container_forall, &data);
}
}
void
parasite_widget_tree_scan (ParasiteWidgetTree *widget_tree,
parasite_widget_tree_scan (ParasiteWidgetTree *wt,
GtkWidget *window)
{
gtk_tree_store_clear (widget_tree->priv->model);
g_hash_table_remove_all (widget_tree->priv->iters);
parasite_widget_tree_append_object (widget_tree, G_OBJECT (gtk_settings_get_default ()), NULL);
parasite_widget_tree_append_object (widget_tree, G_OBJECT (window), NULL);
gtk_tree_store_clear (wt->priv->model);
g_hash_table_remove_all (wt->priv->iters);
parasite_widget_tree_append_object (wt, G_OBJECT (gtk_settings_get_default ()), NULL);
parasite_widget_tree_append_object (wt, G_OBJECT (window), NULL);
gtk_tree_view_columns_autosize (GTK_TREE_VIEW (widget_tree));
}
/*
static GList *
get_parents(GtkWidget *widget,
GList *parents)
{
GtkWidget *parent = gtk_widget_get_parent(widget);
parents = g_list_prepend(parents, widget);
if (parent != NULL)
return get_parents(parent, parents);
return parents;
gtk_tree_view_columns_autosize (GTK_TREE_VIEW (wt));
}
gboolean
parasite_widget_tree_find_widget (ParasiteWidgetTree *widget_tree,
GtkWidget *widget,
GtkTreeIter *iter)
{
GList *parents = get_parents (widget, NULL);
GList *l;
GtkTreeIter inner_iter, parent_iter = {0};
gboolean found = FALSE;
gboolean in_root = TRUE;
for (l = parents; l != NULL; l = l->next)
{
GtkWidget *cur_widget = GTK_WIDGET (l->data);
gboolean valid;
found = FALSE;
for (valid = gtk_tree_model_iter_children (widget_tree->priv->model,
&inner_iter,
in_root ? NULL : &parent_iter);
valid;
valid = gtk_tree_model_iter_next (widget_tree->priv->model, &inner_iter))
{
GtkWidget *iter_widget;
gtk_tree_model_get (widget_tree->priv->model,
&inner_iter,
WIDGET, &iter_widget,
-1);
if (iter_widget == cur_widget)
{
parent_iter = inner_iter;
in_root = FALSE;
found = TRUE;
break;
}
}
}
g_list_free(parents);
*iter = inner_iter;
return found;
}
*/
gboolean
parasite_widget_tree_find_object (ParasiteWidgetTree *widget_tree,
parasite_widget_tree_find_object (ParasiteWidgetTree *wt,
GObject *object,
GtkTreeIter *iter)
{
GtkTreeIter *internal_iter = g_hash_table_lookup (widget_tree->priv->iters, object);
GtkTreeIter *internal_iter = g_hash_table_lookup (wt->priv->iters, object);
if (internal_iter)
{
*iter = *internal_iter;
@ -397,22 +234,19 @@ parasite_widget_tree_find_object (ParasiteWidgetTree *widget_tree,
}
void
parasite_widget_tree_select_object (ParasiteWidgetTree *widget_tree,
parasite_widget_tree_select_object (ParasiteWidgetTree *wt,
GObject *object)
{
GtkTreeIter iter;
if (parasite_widget_tree_find_object (widget_tree, object, &iter))
if (parasite_widget_tree_find_object (wt, object, &iter))
{
GtkTreePath *path = gtk_tree_model_get_path (GTK_TREE_MODEL (widget_tree->priv->model), &iter);
gtk_tree_view_expand_to_path(GTK_TREE_VIEW(widget_tree), path);
gtk_tree_selection_select_iter(
gtk_tree_view_get_selection(GTK_TREE_VIEW(widget_tree)),
&iter);
gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (widget_tree), path, NULL, FALSE, 0, 0);
GtkTreePath *path = gtk_tree_model_get_path (GTK_TREE_MODEL (wt->priv->model), &iter);
gtk_tree_view_expand_to_path (GTK_TREE_VIEW (wt), path);
gtk_tree_selection_select_iter (gtk_tree_view_get_selection (GTK_TREE_VIEW (wt)), &iter);
gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (wt), path, NULL, FALSE, 0, 0);
}
}
// vim: set et sw=4 ts=4:
// vim: set et sw=2 ts=2:

View File

@ -37,17 +37,17 @@
typedef struct _ParasiteWidgetTreePrivate ParasiteWidgetTreePrivate;
typedef struct _ParasiteWidgetTree {
GtkTreeView parent;
// Private
ParasiteWidgetTreePrivate *priv;
typedef struct _ParasiteWidgetTree
{
GtkTreeView parent;
ParasiteWidgetTreePrivate *priv;
} ParasiteWidgetTree;
typedef struct _ParasiteWidgetTreeClass {
GtkTreeViewClass parent;
typedef struct _ParasiteWidgetTreeClass
{
GtkTreeViewClass parent;
void (*widget_changed)(ParasiteWidgetTree *tree);
void (*widget_changed) (ParasiteWidgetTree *tree);
} ParasiteWidgetTreeClass;
@ -57,16 +57,16 @@ G_BEGIN_DECLS
GType parasite_widget_tree_get_type (void);
GtkWidget *parasite_widget_tree_new (void);
GObject *parasite_widget_tree_get_selected_object (ParasiteWidgetTree *widget_tree);
GObject *parasite_widget_tree_get_selected_object (ParasiteWidgetTree *wt);
void parasite_widget_tree_scan (ParasiteWidgetTree *widget_tree,
GtkWidget *window);
void parasite_widget_tree_select_object (ParasiteWidgetTree *widget_tree,
void parasite_widget_tree_scan (ParasiteWidgetTree *wt,
GtkWidget *window);
void parasite_widget_tree_select_object (ParasiteWidgetTree *wt,
GObject *object);
void parasite_widget_tree_append_object (ParasiteWidgetTree *widget_tree,
void parasite_widget_tree_append_object (ParasiteWidgetTree *wt,
GObject *object,
GtkTreeIter *parent_iter);
gboolean parasite_widget_tree_find_object (ParasiteWidgetTree *widget_tree,
gboolean parasite_widget_tree_find_object (ParasiteWidgetTree *wt,
GObject *object,
GtkTreeIter *iter);
@ -75,4 +75,4 @@ G_END_DECLS
#endif // _GTKPARASITE_WIDGETTREE_H_
// vim: set et sw=4 ts=4:
// vim: set et sw=2 ts=2:

View File

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkTreeStore" id="model">
<columns>
<column type="gpointer"/>
<column type="gchararray"/>
<column type="gchararray"/>
<column type="gboolean"/>
<column type="gboolean"/>
<column type="gboolean"/>
<column type="gchararray"/>
<column type="gboolean"/>
</columns>
</object>
<template class="ParasiteWidgetTree" parent="GtkTreeView">
<property name="model">model</property>
<property name="enable-search">True</property>
<property name="search-column">2</property>
<child internal-child="selection">
<object class="GtkTreeSelection">
<signal name="changed" handler="on_widget_selected"/>
</object>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title">Widget</property>
<property name="resizable">True</property>
<child>
<object class="GtkCellRendererText">
<property name="scale">0.8</property>
</object>
<attributes>
<attribute name="text">1</attribute>
<attribute name="sensitive">7</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title">Name</property>
<property name="resizable">True</property>
<child>
<object class="GtkCellRendererText">
<property name="scale">0.8</property>
</object>
<attributes>
<attribute name="text">2</attribute>
<attribute name="sensitive">7</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title">Realized</property>
<child>
<object class="GtkCellRendererToggle">
<property name="activatable">True</property>
<property name="indicator-size">10</property>
</object>
<attributes>
<attribute name="active">3</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title">Mapped</property>
<child>
<object class="GtkCellRendererToggle">
<property name="activatable">True</property>
<property name="indicator-size">10</property>
</object>
<attributes>
<attribute name="active">4</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title">Visible</property>
<child>
<object class="GtkCellRendererToggle">
<property name="activatable">True</property>
<property name="indicator-size">10</property>
</object>
<attributes>
<attribute name="active">5</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title">Address</property>
<property name="resizable">True</property>
<child>
<object class="GtkCellRendererText">
<property name="scale">0.8</property>
<property name="family">monospace</property>
</object>
<attributes>
<attribute name="text">6</attribute>
<attribute name="sensitive">7</attribute>
</attributes>
</child>
</object>
</child>
</template>
</interface>