diff options
-rw-r--r-- | CMakeLists.txt | 4 | ||||
-rw-r--r-- | liblogdiag/ld-category-symbol-view.c | 22 | ||||
-rw-r--r-- | liblogdiag/ld-category-tree-view.c | 338 | ||||
-rw-r--r-- | liblogdiag/ld-category-tree-view.h | 58 | ||||
-rw-r--r-- | liblogdiag/ld-category-view-if.c | 99 | ||||
-rw-r--r-- | liblogdiag/ld-category-view-if.h | 58 | ||||
-rw-r--r-- | liblogdiag/ld-category-view.c | 364 | ||||
-rw-r--r-- | liblogdiag/ld-category-view.h | 32 | ||||
-rw-r--r-- | liblogdiag/liblogdiag.h | 4 | ||||
-rw-r--r-- | src/ld-window-main.c | 4 |
10 files changed, 492 insertions, 491 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 5fe91ea..cd8f514 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -124,8 +124,8 @@ set (liblogdiag_SOURCES liblogdiag/ld-diagram-connection.c liblogdiag/ld-diagram-view.c liblogdiag/ld-library.c - liblogdiag/ld-category-view-if.c liblogdiag/ld-category-view.c + liblogdiag/ld-category-tree-view.c liblogdiag/ld-category-symbol-view.c liblogdiag/ld-category.c liblogdiag/ld-symbol.c @@ -143,8 +143,8 @@ set (liblogdiag_HEADERS liblogdiag/ld-diagram-connection.h liblogdiag/ld-diagram-view.h liblogdiag/ld-library.h - liblogdiag/ld-category-view-if.h liblogdiag/ld-category-view.h + liblogdiag/ld-category-tree-view.h liblogdiag/ld-category-symbol-view.h liblogdiag/ld-category.h liblogdiag/ld-symbol.h diff --git a/liblogdiag/ld-category-symbol-view.c b/liblogdiag/ld-category-symbol-view.c index 3cf975f..aa3fe8c 100644 --- a/liblogdiag/ld-category-symbol-view.c +++ b/liblogdiag/ld-category-symbol-view.c @@ -71,9 +71,9 @@ static void ld_category_symbol_view_set_property (GObject *object, static void ld_category_symbol_view_finalize (GObject *gobject); static void ld_category_symbol_view_set_category - (LdCategoryViewIf *iface, LdCategory *category); + (LdCategoryView *iface, LdCategory *category); static LdCategory *ld_category_symbol_view_get_category - (LdCategoryViewIf *iface); + (LdCategoryView *iface); static void on_size_request (GtkWidget *widget, GtkRequisition *requisition, gpointer user_data); @@ -84,7 +84,7 @@ static gboolean on_expose_event (GtkWidget *widget, GdkEventExpose *event, static void -ld_category_view_if_init (LdCategoryViewIfInterface *iface) +ld_category_view_init (LdCategoryViewInterface *iface) { iface->set_category = ld_category_symbol_view_set_category; iface->get_category = ld_category_symbol_view_get_category; @@ -92,7 +92,7 @@ ld_category_view_if_init (LdCategoryViewIfInterface *iface) G_DEFINE_TYPE_WITH_CODE (LdCategorySymbolView, ld_category_symbol_view, GTK_TYPE_DRAWING_AREA, - G_IMPLEMENT_INTERFACE (LD_TYPE_CATEGORY_VIEW_IF, ld_category_view_if_init)); + G_IMPLEMENT_INTERFACE (LD_TYPE_CATEGORY_VIEW, ld_category_view_init)); static void ld_category_symbol_view_class_init (LdCategorySymbolViewClass *klass) @@ -128,7 +128,7 @@ symbol_deselect (LdCategorySymbolView *self) if (!preselected) return; - g_signal_emit (self, LD_CATEGORY_VIEW_IF_GET_INTERFACE (self)-> + g_signal_emit (self, LD_CATEGORY_VIEW_GET_INTERFACE (self)-> symbol_deselected_signal, 0, preselected->symbol, preselected->path); symbol_redraw (self, preselected); @@ -175,7 +175,7 @@ on_motion_notify (GtkWidget *widget, GdkEventMotion *event, gpointer user_data) gtk_drag_source_set (widget, GDK_BUTTON1_MASK, &target, 1, GDK_ACTION_COPY); - g_signal_emit (self, LD_CATEGORY_VIEW_IF_GET_INTERFACE (self)-> + g_signal_emit (self, LD_CATEGORY_VIEW_GET_INTERFACE (self)-> symbol_selected_signal, 0, data->symbol, data->path); } return FALSE; @@ -298,7 +298,7 @@ ld_category_symbol_view_get_property (GObject *object, guint property_id, { case PROP_CATEGORY: g_value_set_object (value, - ld_category_view_if_get_category (LD_CATEGORY_VIEW_IF (object))); + ld_category_view_get_category (LD_CATEGORY_VIEW (object))); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -312,7 +312,7 @@ ld_category_symbol_view_set_property (GObject *object, guint property_id, switch (property_id) { case PROP_CATEGORY: - ld_category_view_if_set_category (LD_CATEGORY_VIEW_IF (object), + ld_category_view_set_category (LD_CATEGORY_VIEW (object), LD_CATEGORY (g_value_get_object (value))); break; default: @@ -541,12 +541,12 @@ ld_category_symbol_view_new (LdCategory *category) LdCategorySymbolView *self; self = g_object_new (LD_TYPE_CATEGORY_SYMBOL_VIEW, NULL); - ld_category_view_if_set_category (LD_CATEGORY_VIEW_IF (self), category); + ld_category_view_set_category (LD_CATEGORY_VIEW (self), category); return GTK_WIDGET (self); } static void -ld_category_symbol_view_set_category (LdCategoryViewIf *iface, +ld_category_symbol_view_set_category (LdCategoryView *iface, LdCategory *category) { LdCategorySymbolView *self; @@ -575,7 +575,7 @@ ld_category_symbol_view_set_category (LdCategoryViewIf *iface, } static LdCategory * -ld_category_symbol_view_get_category (LdCategoryViewIf *iface) +ld_category_symbol_view_get_category (LdCategoryView *iface) { g_return_val_if_fail (LD_IS_CATEGORY_SYMBOL_VIEW (iface), NULL); return LD_CATEGORY_SYMBOL_VIEW (iface)->priv->category; diff --git a/liblogdiag/ld-category-tree-view.c b/liblogdiag/ld-category-tree-view.c new file mode 100644 index 0000000..674c308 --- /dev/null +++ b/liblogdiag/ld-category-tree-view.c @@ -0,0 +1,338 @@ +/* + * ld-category-tree-view.c + * + * This file is a part of logdiag. + * Copyright Přemysl Janouch 2011. All rights reserved. + * + * See the file LICENSE for licensing information. + * + */ + +#include "liblogdiag.h" +#include "config.h" + + +/** + * SECTION:ld-category-tree-view + * @short_description: A category tree view widget + * @see_also: #LdCategory + * + * #LdCategoryTreeView enables the user to drag symbols from #LdLibrary + * onto #LdDiagramView. + */ + +/* + * LdCategoryTreeViewPrivate: + * @category: a category object assigned as a model. + * @expander_prefix: a string to prepend to subcategory labels in expanders. + */ +struct _LdCategoryTreeViewPrivate +{ + LdCategory *category; + gchar *expander_prefix; +}; + +enum +{ + PROP_0, + PROP_CATEGORY +}; + +static void ld_category_tree_view_get_property (GObject *object, + guint property_id, GValue *value, GParamSpec *pspec); +static void ld_category_tree_view_set_property (GObject *object, + guint property_id, const GValue *value, GParamSpec *pspec); +static void ld_category_tree_view_dispose (GObject *gobject); + +static void ld_category_tree_view_set_category (LdCategoryView *iface, + LdCategory *category); +static LdCategory *ld_category_tree_view_get_category (LdCategoryView *iface); + +static void reload_category (LdCategoryTreeView *self); +static void load_category_cb (gpointer data, gpointer user_data); + + +static void +ld_category_view_init (LdCategoryViewInterface *iface) +{ + iface->set_category = ld_category_tree_view_set_category; + iface->get_category = ld_category_tree_view_get_category; +} + +G_DEFINE_TYPE_WITH_CODE (LdCategoryTreeView, + ld_category_tree_view, GTK_TYPE_VBOX, + G_IMPLEMENT_INTERFACE (LD_TYPE_CATEGORY_VIEW, ld_category_view_init)); + +static void +ld_category_tree_view_class_init (LdCategoryTreeViewClass *klass) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (klass); + object_class->get_property = ld_category_tree_view_get_property; + object_class->set_property = ld_category_tree_view_set_property; + object_class->dispose = ld_category_tree_view_dispose; + + g_object_class_override_property (object_class, PROP_CATEGORY, "category"); + + g_type_class_add_private (klass, sizeof (LdCategoryTreeViewPrivate)); +} + +static void +ld_category_tree_view_init (LdCategoryTreeView *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE + (self, LD_TYPE_CATEGORY_TREE_VIEW, LdCategoryTreeViewPrivate); +} + +static void +ld_category_tree_view_dispose (GObject *gobject) +{ + LdCategoryTreeView *self; + + self = LD_CATEGORY_TREE_VIEW (gobject); + ld_category_view_set_category (LD_CATEGORY_VIEW (self), NULL); + + g_free (self->priv->expander_prefix); + self->priv->expander_prefix = NULL; + + /* Chain up to the parent class. */ + G_OBJECT_CLASS (ld_category_tree_view_parent_class)->dispose (gobject); +} + +static void +ld_category_tree_view_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + switch (property_id) + { + case PROP_CATEGORY: + g_value_set_object (value, + ld_category_view_get_category (LD_CATEGORY_VIEW (object))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +ld_category_tree_view_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + switch (property_id) + { + case PROP_CATEGORY: + ld_category_view_set_category (LD_CATEGORY_VIEW (object), + LD_CATEGORY (g_value_get_object (value))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + + +/** + * ld_category_tree_view_new: + * @category: (allow-none): a category to be assigned to the widget. + * + * Create an instance. + */ +GtkWidget * +ld_category_tree_view_new (LdCategory *category) +{ + LdCategoryTreeView *self; + + self = g_object_new (LD_TYPE_CATEGORY_TREE_VIEW, NULL); + ld_category_view_set_category (LD_CATEGORY_VIEW (self), category); + return GTK_WIDGET (self); +} + +static void +ld_category_tree_view_set_category (LdCategoryView *iface, LdCategory *category) +{ + LdCategoryTreeView *self; + + g_return_if_fail (LD_IS_CATEGORY_TREE_VIEW (iface)); + g_return_if_fail (LD_IS_CATEGORY (category) || category == NULL); + + self = LD_CATEGORY_TREE_VIEW (iface); + if (self->priv->category) + { + g_signal_handlers_disconnect_by_func (self->priv->category, + reload_category, self); + g_object_unref (self->priv->category); + } + + self->priv->category = category; + + if (category) + { + g_signal_connect_data (category, "children-changed", + G_CALLBACK (reload_category), self, + NULL, G_CONNECT_AFTER | G_CONNECT_SWAPPED); + g_signal_connect_data (category, "notify::parent", + G_CALLBACK (reload_category), self, + NULL, G_CONNECT_AFTER | G_CONNECT_SWAPPED); + g_object_ref (category); + } + reload_category (self); + g_object_notify (G_OBJECT (self), "category"); +} + +static LdCategory * +ld_category_tree_view_get_category (LdCategoryView *iface) +{ + g_return_val_if_fail (LD_IS_CATEGORY_TREE_VIEW (iface), NULL); + return LD_CATEGORY_TREE_VIEW (iface)->priv->category; +} + +static GtkWidget * +create_empty_label (void) +{ + GtkWidget *label; + PangoAttrList *attr; + + label = gtk_label_new (_("Empty")); + gtk_widget_set_sensitive (label, FALSE); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + gtk_misc_set_padding (GTK_MISC (label), 5, 0); + + attr = pango_attr_list_new (); + pango_attr_list_change (attr, pango_attr_style_new (PANGO_STYLE_ITALIC)); + gtk_label_set_attributes (GTK_LABEL (label), attr); + pango_attr_list_unref (attr); + + return label; +} + +static void +reconstruct_prefix (LdCategoryTreeView *self) +{ + LdCategory *iter; + gchar *start, *end; + + start = g_strdup (""); + end = g_strdup (""); + + for (iter = self->priv->category; iter; + iter = ld_category_get_parent (iter)) + { + const gchar *name; + gchar *new_start, *new_end, *name_escaped; + + /* Stop at the root category. */ + if (!strcmp (ld_category_get_name (iter), + LD_LIBRARY_IDENTIFIER_SEPARATOR)) + break; + + name = ld_category_get_human_name (iter); + name_escaped = g_markup_escape_text (name, -1); + + new_start = g_strconcat (start, "<small>", NULL); + new_end = g_strconcat (name_escaped, ":</small> ", end, NULL); + + g_free (name_escaped); + g_free (start); + g_free (end); + + start = new_start; + end = new_end; + } + + g_free (self->priv->expander_prefix); + self->priv->expander_prefix = g_strconcat (start, end, NULL); + g_free (start); + g_free (end); +} + +static void +on_symbol_selected (GObject *source, + LdSymbol *symbol, const gchar *path, LdCategoryTreeView *self) +{ + g_signal_emit (self, LD_CATEGORY_VIEW_GET_INTERFACE (self)-> + symbol_selected_signal, 0, symbol, path); +} + +static void +on_symbol_deselected (GObject *source, + LdSymbol *symbol, const gchar *path, LdCategoryTreeView *self) +{ + g_signal_emit (self, LD_CATEGORY_VIEW_GET_INTERFACE (self)-> + symbol_deselected_signal, 0, symbol, path); +} + +static void +reload_category (LdCategoryTreeView *self) +{ + g_return_if_fail (LD_IS_CATEGORY_TREE_VIEW (self)); + + /* Clear the container first, if there is already something in it. */ + gtk_container_foreach (GTK_CONTAINER (self), + (GtkCallback) gtk_widget_destroy, NULL); + + /* XXX: We might want to disconnect signal handlers. */ + + if (self->priv->category) + { + GSList *symbols, *children; + + symbols = (GSList *) ld_category_get_symbols (self->priv->category); + children = (GSList *) ld_category_get_children (self->priv->category); + + if (symbols) + { + GtkWidget *symbol_view; + + symbol_view = ld_category_symbol_view_new (self->priv->category); + gtk_box_pack_start (GTK_BOX (self), symbol_view, FALSE, FALSE, 0); + + g_signal_connect_after (symbol_view, "symbol-selected", + G_CALLBACK (on_symbol_selected), self); + g_signal_connect_after (symbol_view, "symbol-deselected", + G_CALLBACK (on_symbol_deselected), self); + } + + if (children) + { + reconstruct_prefix (self); + g_slist_foreach (children, load_category_cb, self); + } + else if (!symbols) + gtk_box_pack_start (GTK_BOX (self), + create_empty_label (), FALSE, FALSE, 0); + } +} + +static void +load_category_cb (gpointer data, gpointer user_data) +{ + LdCategoryTreeView *self; + LdCategory *cat; + GtkWidget *expander, *child; + gchar *name, *label_markup; + + g_return_if_fail (LD_IS_CATEGORY_TREE_VIEW (user_data)); + g_return_if_fail (LD_IS_CATEGORY (data)); + + self = user_data; + cat = data; + + name = g_markup_escape_text (ld_category_get_human_name (cat), -1); + label_markup = g_strconcat (self->priv->expander_prefix, name, NULL); + g_free (name); + + expander = gtk_expander_new (label_markup); + gtk_expander_set_expanded (GTK_EXPANDER (expander), TRUE); + gtk_expander_set_use_markup (GTK_EXPANDER (expander), TRUE); + g_free (label_markup); + + child = ld_category_tree_view_new (cat); + gtk_container_add (GTK_CONTAINER (expander), child); + gtk_box_pack_start (GTK_BOX (self), expander, FALSE, FALSE, 0); + + g_signal_connect_after (child, "symbol-selected", + G_CALLBACK (on_symbol_selected), self); + g_signal_connect_after (child, "symbol-deselected", + G_CALLBACK (on_symbol_deselected), self); +} + diff --git a/liblogdiag/ld-category-tree-view.h b/liblogdiag/ld-category-tree-view.h new file mode 100644 index 0000000..f5456f2 --- /dev/null +++ b/liblogdiag/ld-category-tree-view.h @@ -0,0 +1,58 @@ +/* + * ld-category-tree-view.h + * + * This file is a part of logdiag. + * Copyright Přemysl Janouch 2011. All rights reserved. + * + * See the file LICENSE for licensing information. + * + */ + +#ifndef __LD_CATEGORY_TREE_VIEW_H__ +#define __LD_CATEGORY_TREE_VIEW_H__ + +G_BEGIN_DECLS + + +#define LD_TYPE_CATEGORY_TREE_VIEW (ld_category_tree_view_get_type ()) +#define LD_CATEGORY_TREE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), LD_TYPE_CATEGORY_TREE_VIEW, LdCategoryTreeView)) +#define LD_CATEGORY_TREE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST \ + ((klass), LD_TYPE_CATEGORY_TREE_VIEW, LdCategoryTreeViewClass)) +#define LD_IS_CATEGORY_TREE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), LD_TYPE_CATEGORY_TREE_VIEW)) +#define LD_IS_CATEGORY_TREE_VIEW_CLASS(klass) (G_TYPE_CHECK_INSTANCE_TYPE \ + ((klass), LD_TYPE_CATEGORY_TREE_VIEW)) +#define LD_CATEGORY_TREE_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), LD_CATEGORY_TREE_VIEW, LdCategoryTreeViewClass)) + +typedef struct _LdCategoryTreeView LdCategoryTreeView; +typedef struct _LdCategoryTreeViewPrivate LdCategoryTreeViewPrivate; +typedef struct _LdCategoryTreeViewClass LdCategoryTreeViewClass; + + +/** + * LdCategoryTreeView: + */ +struct _LdCategoryTreeView +{ +/*< private >*/ + GtkVBox parent_instance; + LdCategoryTreeViewPrivate *priv; +}; + +struct _LdCategoryTreeViewClass +{ +/*< private >*/ + GtkVBoxClass parent_class; +}; + + +GType ld_category_tree_view_get_type (void) G_GNUC_CONST; + +GtkWidget *ld_category_tree_view_new (LdCategory *category); + + +G_END_DECLS + +#endif /* ! __LD_CATEGORY_TREE_VIEW_H__ */ diff --git a/liblogdiag/ld-category-view-if.c b/liblogdiag/ld-category-view-if.c deleted file mode 100644 index 18a37e1..0000000 --- a/liblogdiag/ld-category-view-if.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * ld-category-view-if.c - * - * This file is a part of logdiag. - * Copyright Přemysl Janouch 2012. All rights reserved. - * - * See the file LICENSE for licensing information. - * - */ - -#include "liblogdiag.h" -#include "config.h" - - -/** - * SECTION:ld-category-view-if - * @short_description: Interface for objects displaying categories - * @see_also: #LdCategory - * - * #LdCategoryViewIf defines objects displaying contents of #LdCategory - * hierarchies. - */ - -G_DEFINE_INTERFACE (LdCategoryViewIf, ld_category_view_if, 0); - -static void -ld_category_view_if_default_init (LdCategoryViewIfInterface *iface) -{ - GParamSpec *pspec; - -/** - * LdCategoryViewIf::symbol-selected: - * @self: an #LdCategoryView object. - * @symbol: the selected #LdSymbol object. - * @path: location of the symbol within the library. - * - * A symbol has been selected. - */ - iface->symbol_selected_signal = g_signal_new - ("symbol-selected", G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, - ld_marshal_VOID__OBJECT_STRING, - G_TYPE_NONE, 2, LD_TYPE_SYMBOL, - G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE); - -/** - * LdCategoryViewIf::symbol-deselected: - * @self: an #LdCategoryView object. - * @symbol: the deselected #LdSymbol object. - * @path: location of the symbol within the library. - * - * A symbol has been deselected. - */ - iface->symbol_deselected_signal = g_signal_new - ("symbol-deselected", G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, - ld_marshal_VOID__OBJECT_STRING, - G_TYPE_NONE, 2, LD_TYPE_SYMBOL, - G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE); - -/** - * LdCategoryViewIf:category: - * - * The #LdCategory this object retrieves content from. - */ - pspec = g_param_spec_object ("category", "Category", - "The symbol category that is shown by this object.", - LD_TYPE_CATEGORY, G_PARAM_READWRITE); - g_object_interface_install_property (iface, pspec); -} - -/** - * ld_category_view_if_set_category: - * @self: an #LdCategorylViewIf object. - * @category: the #LdCategory to be assigned to the view. - * - * Assign an #LdCategory object to the view. - */ -void -ld_category_view_if_set_category (LdCategoryViewIf *self, - LdCategory *category) -{ - g_return_if_fail (LD_IS_CATEGORY_VIEW_IF (self)); - LD_CATEGORY_VIEW_IF_GET_INTERFACE (self)->set_category (self, category); -} - -/** - * ld_category_view_if_get_category: - * @self: an #LdCategoryViewIf object. - * - * Get the #LdCategory object assigned to this view. - * The reference count on the category is not incremented. - */ -LdCategory * -ld_category_view_if_get_category (LdCategoryViewIf *self) -{ - g_return_val_if_fail (LD_IS_CATEGORY_VIEW_IF (self), NULL); - return LD_CATEGORY_VIEW_IF_GET_INTERFACE (self)->get_category (self); -} diff --git a/liblogdiag/ld-category-view-if.h b/liblogdiag/ld-category-view-if.h deleted file mode 100644 index 7cdfa9d..0000000 --- a/liblogdiag/ld-category-view-if.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * ld-category-view-if.h - * - * This file is a part of logdiag. - * Copyright Přemysl Janouch 2012. All rights reserved. - * - * See the file LICENSE for licensing information. - * - */ - -#ifndef __LD_CATEGORY_VIEW_IF_H__ -#define __LD_CATEGORY_VIEW_IF_H__ - -G_BEGIN_DECLS - - -#define LD_TYPE_CATEGORY_VIEW_IF (ld_category_view_if_get_type ()) -#define LD_CATEGORY_VIEW_IF(obj) (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), LD_TYPE_CATEGORY_VIEW_IF, LdCategoryViewIf)) -#define LD_IS_CATEGORY_VIEW_IF(obj) (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), LD_TYPE_CATEGORY_VIEW_IF)) -#define LD_CATEGORY_VIEW_IF_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE \ - ((inst), LD_TYPE_CATEGORY_VIEW_IF, LdCategoryViewIfInterface)) - -typedef struct _LdCategoryViewIf LdCategoryViewIf; -typedef struct _LdCategoryViewIfInterface LdCategoryViewIfInterface; - -/** - * LdCategoryViewIf: - */ -struct _LdCategoryViewIf -{ - /* Just to remind gtk-doc that this really exists. */ -}; - -struct _LdCategoryViewIfInterface -{ -/*< private >*/ - GTypeInterface parent; - - guint symbol_selected_signal; - guint symbol_deselected_signal; - - void (*set_category) (LdCategoryViewIf *self, LdCategory *category); - LdCategory *(*get_category) (LdCategoryViewIf *self); -}; - - -GType ld_category_view_if_get_type (void) G_GNUC_CONST; - -void ld_category_view_if_set_category (LdCategoryViewIf *self, - LdCategory *category); -LdCategory *ld_category_view_if_get_category (LdCategoryViewIf *self); - - -G_END_DECLS - -#endif /* ! __LD_CATEGORY_VIEW_IF_H__ */ diff --git a/liblogdiag/ld-category-view.c b/liblogdiag/ld-category-view.c index 707627d..839b099 100644 --- a/liblogdiag/ld-category-view.c +++ b/liblogdiag/ld-category-view.c @@ -2,7 +2,7 @@ * ld-category-view.c * * This file is a part of logdiag. - * Copyright Přemysl Janouch 2011. All rights reserved. + * Copyright Přemysl Janouch 2012. All rights reserved. * * See the file LICENSE for licensing information. * @@ -14,324 +14,86 @@ /** * SECTION:ld-category-view - * @short_description: A category view widget + * @short_description: Interface for objects displaying categories * @see_also: #LdCategory * - * #LdCategoryView enables the user to drag symbols from #LdLibrary - * onto #LdDiagramView. + * #LdCategoryView defines objects displaying contents of #LdCategory + * hierarchies. */ -/* - * LdCategoryViewPrivate: - * @category: a category object assigned as a model. - * @expander_prefix: a string to prepend to subcategory labels in expanders. - */ -struct _LdCategoryViewPrivate -{ - LdCategory *category; - gchar *expander_prefix; -}; - -enum -{ - PROP_0, - PROP_CATEGORY -}; - -static void ld_category_view_get_property (GObject *object, guint property_id, - GValue *value, GParamSpec *pspec); -static void ld_category_view_set_property (GObject *object, guint property_id, - const GValue *value, GParamSpec *pspec); -static void ld_category_view_dispose (GObject *gobject); - -static void ld_category_view_set_category (LdCategoryViewIf *iface, - LdCategory *category); -static LdCategory *ld_category_view_get_category (LdCategoryViewIf *iface); - -static void reload_category (LdCategoryView *self); -static void load_category_cb (gpointer data, gpointer user_data); - - -static void -ld_category_view_if_init (LdCategoryViewIfInterface *iface) -{ - iface->set_category = ld_category_view_set_category; - iface->get_category = ld_category_view_get_category; -} - -G_DEFINE_TYPE_WITH_CODE (LdCategoryView, ld_category_view, GTK_TYPE_VBOX, - G_IMPLEMENT_INTERFACE (LD_TYPE_CATEGORY_VIEW_IF, ld_category_view_if_init)); - -static void -ld_category_view_class_init (LdCategoryViewClass *klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - object_class->get_property = ld_category_view_get_property; - object_class->set_property = ld_category_view_set_property; - object_class->dispose = ld_category_view_dispose; - - g_object_class_override_property (object_class, PROP_CATEGORY, "category"); - - g_type_class_add_private (klass, sizeof (LdCategoryViewPrivate)); -} - -static void -ld_category_view_init (LdCategoryView *self) -{ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE - (self, LD_TYPE_CATEGORY_VIEW, LdCategoryViewPrivate); -} - -static void -ld_category_view_dispose (GObject *gobject) -{ - LdCategoryView *self; - - self = LD_CATEGORY_VIEW (gobject); - ld_category_view_if_set_category (LD_CATEGORY_VIEW_IF (self), NULL); - - g_free (self->priv->expander_prefix); - self->priv->expander_prefix = NULL; - - /* Chain up to the parent class. */ - G_OBJECT_CLASS (ld_category_view_parent_class)->dispose (gobject); -} +G_DEFINE_INTERFACE (LdCategoryView, ld_category_view, 0); static void -ld_category_view_get_property (GObject *object, guint property_id, - GValue *value, GParamSpec *pspec) +ld_category_view_default_init (LdCategoryViewInterface *iface) { - switch (property_id) - { - case PROP_CATEGORY: - g_value_set_object (value, - ld_category_view_if_get_category (LD_CATEGORY_VIEW_IF (object))); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - -static void -ld_category_view_set_property (GObject *object, guint property_id, - const GValue *value, GParamSpec *pspec) -{ - switch (property_id) - { - case PROP_CATEGORY: - ld_category_view_if_set_category (LD_CATEGORY_VIEW_IF (object), - LD_CATEGORY (g_value_get_object (value))); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - + GParamSpec *pspec; /** - * ld_category_view_new: - * @category: (allow-none): a category to be assigned to the widget. + * LdCategoryView::symbol-selected: + * @self: an #LdCategoryView object. + * @symbol: the selected #LdSymbol object. + * @path: location of the symbol within the library. * - * Create an instance. + * A symbol has been selected. */ -GtkWidget * -ld_category_view_new (LdCategory *category) -{ - LdCategoryView *self; - - self = g_object_new (LD_TYPE_CATEGORY_VIEW, NULL); - ld_category_view_if_set_category (LD_CATEGORY_VIEW_IF (self), category); - return GTK_WIDGET (self); -} - -static void -ld_category_view_set_category (LdCategoryViewIf *iface, LdCategory *category) -{ - LdCategoryView *self; - - g_return_if_fail (LD_IS_CATEGORY_VIEW (iface)); - g_return_if_fail (LD_IS_CATEGORY (category) || category == NULL); - - self = LD_CATEGORY_VIEW (iface); - if (self->priv->category) - { - g_signal_handlers_disconnect_by_func (self->priv->category, - reload_category, self); - g_object_unref (self->priv->category); - } - - self->priv->category = category; - - if (category) - { - g_signal_connect_data (category, "children-changed", - G_CALLBACK (reload_category), self, - NULL, G_CONNECT_AFTER | G_CONNECT_SWAPPED); - g_signal_connect_data (category, "notify::parent", - G_CALLBACK (reload_category), self, - NULL, G_CONNECT_AFTER | G_CONNECT_SWAPPED); - g_object_ref (category); - } - reload_category (self); - g_object_notify (G_OBJECT (self), "category"); -} - -static LdCategory * -ld_category_view_get_category (LdCategoryViewIf *iface) -{ - g_return_val_if_fail (LD_IS_CATEGORY_VIEW (iface), NULL); - return LD_CATEGORY_VIEW (iface)->priv->category; -} + iface->symbol_selected_signal = g_signal_new + ("symbol-selected", G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, + ld_marshal_VOID__OBJECT_STRING, + G_TYPE_NONE, 2, LD_TYPE_SYMBOL, + G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE); -static GtkWidget * -create_empty_label (void) -{ - GtkWidget *label; - PangoAttrList *attr; - - label = gtk_label_new (_("Empty")); - gtk_widget_set_sensitive (label, FALSE); - gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); - gtk_misc_set_padding (GTK_MISC (label), 5, 0); - - attr = pango_attr_list_new (); - pango_attr_list_change (attr, pango_attr_style_new (PANGO_STYLE_ITALIC)); - gtk_label_set_attributes (GTK_LABEL (label), attr); - pango_attr_list_unref (attr); - - return label; -} - -static void -reconstruct_prefix (LdCategoryView *self) -{ - LdCategory *iter; - gchar *start, *end; - - start = g_strdup (""); - end = g_strdup (""); - - for (iter = self->priv->category; iter; - iter = ld_category_get_parent (iter)) - { - const gchar *name; - gchar *new_start, *new_end, *name_escaped; - - /* Stop at the root category. */ - if (!strcmp (ld_category_get_name (iter), - LD_LIBRARY_IDENTIFIER_SEPARATOR)) - break; - - name = ld_category_get_human_name (iter); - name_escaped = g_markup_escape_text (name, -1); - - new_start = g_strconcat (start, "<small>", NULL); - new_end = g_strconcat (name_escaped, ":</small> ", end, NULL); - - g_free (name_escaped); - g_free (start); - g_free (end); - - start = new_start; - end = new_end; - } - - g_free (self->priv->expander_prefix); - self->priv->expander_prefix = g_strconcat (start, end, NULL); - g_free (start); - g_free (end); -} - -static void -on_symbol_selected (GObject *source, - LdSymbol *symbol, const gchar *path, LdCategoryView *self) -{ - g_signal_emit (self, LD_CATEGORY_VIEW_IF_GET_INTERFACE (self)-> - symbol_selected_signal, 0, symbol, path); -} +/** + * LdCategoryView::symbol-deselected: + * @self: an #LdCategoryView object. + * @symbol: the deselected #LdSymbol object. + * @path: location of the symbol within the library. + * + * A symbol has been deselected. + */ + iface->symbol_deselected_signal = g_signal_new + ("symbol-deselected", G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, + ld_marshal_VOID__OBJECT_STRING, + G_TYPE_NONE, 2, LD_TYPE_SYMBOL, + G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE); -static void -on_symbol_deselected (GObject *source, - LdSymbol *symbol, const gchar *path, LdCategoryView *self) -{ - g_signal_emit (self, LD_CATEGORY_VIEW_IF_GET_INTERFACE (self)-> - symbol_deselected_signal, 0, symbol, path); +/** + * LdCategoryView:category: + * + * The #LdCategory this object retrieves content from. + */ + pspec = g_param_spec_object ("category", "Category", + "The symbol category that is shown by this object.", + LD_TYPE_CATEGORY, G_PARAM_READWRITE); + g_object_interface_install_property (iface, pspec); } -static void -reload_category (LdCategoryView *self) +/** + * ld_category_view_set_category: + * @self: an #LdCategorylView object. + * @category: the #LdCategory to be assigned to the view. + * + * Assign an #LdCategory object to the view. + */ +void +ld_category_view_set_category (LdCategoryView *self, + LdCategory *category) { g_return_if_fail (LD_IS_CATEGORY_VIEW (self)); - - /* Clear the container first, if there is already something in it. */ - gtk_container_foreach (GTK_CONTAINER (self), - (GtkCallback) gtk_widget_destroy, NULL); - - /* XXX: We might want to disconnect signal handlers. */ - - if (self->priv->category) - { - GSList *symbols, *children; - - symbols = (GSList *) ld_category_get_symbols (self->priv->category); - children = (GSList *) ld_category_get_children (self->priv->category); - - if (symbols) - { - GtkWidget *symbol_view; - - symbol_view = ld_category_symbol_view_new (self->priv->category); - gtk_box_pack_start (GTK_BOX (self), symbol_view, FALSE, FALSE, 0); - - g_signal_connect_after (symbol_view, "symbol-selected", - G_CALLBACK (on_symbol_selected), self); - g_signal_connect_after (symbol_view, "symbol-deselected", - G_CALLBACK (on_symbol_deselected), self); - } - - if (children) - { - reconstruct_prefix (self); - g_slist_foreach (children, load_category_cb, self); - } - else if (!symbols) - gtk_box_pack_start (GTK_BOX (self), - create_empty_label (), FALSE, FALSE, 0); - } + LD_CATEGORY_VIEW_GET_INTERFACE (self)->set_category (self, category); } -static void -load_category_cb (gpointer data, gpointer user_data) +/** + * ld_category_view_get_category: + * @self: an #LdCategoryView object. + * + * Get the #LdCategory object assigned to this view. + * The reference count on the category is not incremented. + */ +LdCategory * +ld_category_view_get_category (LdCategoryView *self) { - LdCategoryView *self; - LdCategory *cat; - GtkWidget *expander, *child; - gchar *name, *label_markup; - - g_return_if_fail (LD_IS_CATEGORY_VIEW (user_data)); - g_return_if_fail (LD_IS_CATEGORY (data)); - - self = user_data; - cat = data; - - name = g_markup_escape_text (ld_category_get_human_name (cat), -1); - label_markup = g_strconcat (self->priv->expander_prefix, name, NULL); - g_free (name); - - expander = gtk_expander_new (label_markup); - gtk_expander_set_expanded (GTK_EXPANDER (expander), TRUE); - gtk_expander_set_use_markup (GTK_EXPANDER (expander), TRUE); - g_free (label_markup); - - child = ld_category_view_new (cat); - gtk_container_add (GTK_CONTAINER (expander), child); - gtk_box_pack_start (GTK_BOX (self), expander, FALSE, FALSE, 0); - - g_signal_connect_after (child, "symbol-selected", - G_CALLBACK (on_symbol_selected), self); - g_signal_connect_after (child, "symbol-deselected", - G_CALLBACK (on_symbol_deselected), self); + g_return_val_if_fail (LD_IS_CATEGORY_VIEW (self), NULL); + return LD_CATEGORY_VIEW_GET_INTERFACE (self)->get_category (self); } - diff --git a/liblogdiag/ld-category-view.h b/liblogdiag/ld-category-view.h index b684448..723f78a 100644 --- a/liblogdiag/ld-category-view.h +++ b/liblogdiag/ld-category-view.h @@ -2,7 +2,7 @@ * ld-category-view.h * * This file is a part of logdiag. - * Copyright Přemysl Janouch 2011. All rights reserved. + * Copyright Přemysl Janouch 2012. All rights reserved. * * See the file LICENSE for licensing information. * @@ -17,40 +17,40 @@ G_BEGIN_DECLS #define LD_TYPE_CATEGORY_VIEW (ld_category_view_get_type ()) #define LD_CATEGORY_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST \ ((obj), LD_TYPE_CATEGORY_VIEW, LdCategoryView)) -#define LD_CATEGORY_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST \ - ((klass), LD_TYPE_CATEGORY_VIEW, LdCategoryViewClass)) #define LD_IS_CATEGORY_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE \ ((obj), LD_TYPE_CATEGORY_VIEW)) -#define LD_IS_CATEGORY_VIEW_CLASS(klass) (G_TYPE_CHECK_INSTANCE_TYPE \ - ((klass), LD_TYPE_CATEGORY_VIEW)) -#define LD_CATEGORY_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), LD_CATEGORY_VIEW, LdCategoryViewClass)) +#define LD_CATEGORY_VIEW_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE \ + ((inst), LD_TYPE_CATEGORY_VIEW, LdCategoryViewInterface)) typedef struct _LdCategoryView LdCategoryView; -typedef struct _LdCategoryViewPrivate LdCategoryViewPrivate; -typedef struct _LdCategoryViewClass LdCategoryViewClass; - +typedef struct _LdCategoryViewInterface LdCategoryViewInterface; /** * LdCategoryView: */ struct _LdCategoryView { -/*< private >*/ - GtkVBox parent_instance; - LdCategoryViewPrivate *priv; + /* Just to remind gtk-doc that this really exists. */ }; -struct _LdCategoryViewClass +struct _LdCategoryViewInterface { /*< private >*/ - GtkVBoxClass parent_class; + GTypeInterface parent; + + guint symbol_selected_signal; + guint symbol_deselected_signal; + + void (*set_category) (LdCategoryView *self, LdCategory *category); + LdCategory *(*get_category) (LdCategoryView *self); }; GType ld_category_view_get_type (void) G_GNUC_CONST; -GtkWidget *ld_category_view_new (LdCategory *category); +void ld_category_view_set_category (LdCategoryView *self, + LdCategory *category); +LdCategory *ld_category_view_get_category (LdCategoryView *self); G_END_DECLS diff --git a/liblogdiag/liblogdiag.h b/liblogdiag/liblogdiag.h index f3ec94b..aeac0a3 100644 --- a/liblogdiag/liblogdiag.h +++ b/liblogdiag/liblogdiag.h @@ -28,9 +28,9 @@ #include "ld-diagram.h" #include "ld-diagram-view.h" -#include "ld-category-view-if.h" -#include "ld-category-symbol-view.h" #include "ld-category-view.h" +#include "ld-category-symbol-view.h" +#include "ld-category-tree-view.h" #include "ld-lua.h" #include "ld-lua-symbol.h" diff --git a/src/ld-window-main.c b/src/ld-window-main.c index d23d78b..3fa3499 100644 --- a/src/ld-window-main.c +++ b/src/ld-window-main.c @@ -270,7 +270,7 @@ ld_window_main_init (LdWindowMain *self) priv->toolbar = gtk_ui_manager_get_widget (priv->ui_manager, "/Toolbar"); /* Create the remaining widgets. */ - priv->library_view = ld_category_view_new (NULL); + priv->library_view = ld_category_tree_view_new (NULL); priv->view = LD_DIAGRAM_VIEW (ld_diagram_view_new ()); priv->scrolled_window = gtk_scrolled_window_new (NULL, NULL); @@ -343,7 +343,7 @@ ld_window_main_init (LdWindowMain *self) g_signal_connect (priv->view, "notify::zoom", G_CALLBACK (on_view_zoom_changed), self); - ld_category_view_if_set_category (LD_CATEGORY_VIEW_IF (priv->library_view), + ld_category_view_set_category (LD_CATEGORY_VIEW (priv->library_view), ld_library_get_root (priv->library)); g_signal_connect_after (priv->library_view, "symbol-selected", |