/* * Copyright (C) 2007 OpenedHand Ltd * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) any later * version. * * This program 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 General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "taku-icon-tile.h" G_DEFINE_TYPE (TakuIconTile, taku_icon_tile, TAKU_TYPE_TILE); #define GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), TAKU_TYPE_ICON_TILE, TakuIconTilePrivate)) struct _TakuIconTilePrivate { GtkWidget *icon; GtkWidget *primary; GtkWidget *secondary; gchar *collation_key; GtkOrientation orientation; }; enum { PROP_0, PROP_PIXBUF, PROP_PRIMARY, PROP_SECONDARY, }; static void tile_arrange (TakuIconTile *tile) { GtkOrientation orientation = GTK_ORIENTATION_HORIZONTAL; gboolean show_secondary = TRUE; gtk_widget_style_get (GTK_WIDGET (tile), "show-secondary-text", &show_secondary, "orientation", &orientation, NULL); if (orientation != tile->priv->orientation) { GtkWidget *box, *vbox; if (tile->priv->orientation != -1) { gtk_widget_destroy (gtk_bin_get_child (GTK_BIN (tile))); } tile->priv->orientation = orientation; gtk_widget_show (tile->priv->icon); gtk_widget_show (tile->priv->primary); switch (orientation) { case GTK_ORIENTATION_VERTICAL : gtk_misc_set_alignment (GTK_MISC (tile->priv->primary), 0.5, 0.5); gtk_misc_set_alignment (GTK_MISC (tile->priv->secondary), 0.5, 0.5); box = gtk_vbox_new (FALSE, 6); break; default: case GTK_ORIENTATION_HORIZONTAL : gtk_misc_set_alignment (GTK_MISC (tile->priv->primary), 0.0, 0.5); gtk_misc_set_alignment (GTK_MISC (tile->priv->secondary), 0.0, 0.5); box = gtk_hbox_new (FALSE, 6); break; } gtk_widget_show (box); gtk_box_pack_start (GTK_BOX (box), tile->priv->icon, FALSE, FALSE, 0); vbox = gtk_vbox_new (FALSE, 6); gtk_widget_show (vbox); gtk_box_pack_start (GTK_BOX (vbox), tile->priv->primary, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (vbox), tile->priv->secondary, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (box), vbox, TRUE, TRUE, 0); gtk_container_add (GTK_CONTAINER (tile), box); } if (show_secondary) { gtk_widget_show (tile->priv->secondary); } else { gtk_widget_hide (tile->priv->secondary); } } static void taku_icon_tile_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { switch (property_id) { case PROP_PIXBUF: { TakuIconTilePrivate *priv = GET_PRIVATE (object); g_value_set_object (value, gtk_image_get_pixbuf (GTK_IMAGE (priv->icon))); } break; case PROP_PRIMARY: g_value_set_string (value, taku_icon_tile_get_primary (TAKU_ICON_TILE (object))); break; case PROP_SECONDARY: g_value_set_string (value, taku_icon_tile_get_secondary (TAKU_ICON_TILE (object))); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void taku_icon_tile_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { switch (property_id) { case PROP_PIXBUF: taku_icon_tile_set_pixbuf (TAKU_ICON_TILE (object), g_value_get_object (value)); break; case PROP_PRIMARY: taku_icon_tile_set_primary (TAKU_ICON_TILE (object), g_value_get_string (value)); break; case PROP_SECONDARY: taku_icon_tile_set_secondary (TAKU_ICON_TILE (object), g_value_get_string (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void taku_icon_tile_finalize (GObject *object) { g_free (TAKU_ICON_TILE (object)->priv->collation_key); G_OBJECT_CLASS (taku_icon_tile_parent_class)->finalize (object); } static void taku_icon_tile_style_set (GtkWidget *widget, GtkStyle *previous) { GTK_WIDGET_CLASS (taku_icon_tile_parent_class)->style_set (widget, previous); tile_arrange (TAKU_ICON_TILE (widget)); } static const char * taku_icon_tile_get_sort_key (TakuTile *tile) { return TAKU_ICON_TILE (tile)->priv->collation_key; } static const char * taku_icon_tile_get_search_key (TakuTile *tile) { return taku_icon_tile_get_primary (TAKU_ICON_TILE (tile)); } static void taku_icon_tile_dispose (GObject *object) { TakuIconTilePrivate *priv = GET_PRIVATE (object); if (priv->icon) { g_object_unref (priv->icon); priv->icon = NULL; } if (priv->primary) { g_object_unref (priv->primary); priv->primary = NULL; } if (priv->secondary) { g_object_unref (priv->secondary); priv->secondary = NULL; } G_OBJECT_CLASS (taku_icon_tile_parent_class)->dispose (object); } static void taku_icon_tile_class_init (TakuIconTileClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); TakuTileClass *tile_class = TAKU_TILE_CLASS (klass); g_type_class_add_private (klass, sizeof (TakuIconTilePrivate)); object_class->get_property = taku_icon_tile_get_property; object_class->set_property = taku_icon_tile_set_property; object_class->dispose = taku_icon_tile_dispose; object_class->finalize = taku_icon_tile_finalize; widget_class->style_set = taku_icon_tile_style_set; tile_class->get_sort_key = taku_icon_tile_get_sort_key; tile_class->get_search_key = taku_icon_tile_get_search_key; g_object_class_install_property (object_class, PROP_PIXBUF, g_param_spec_object ("pixbuf", "pixbuf", "The pixbuf", GDK_TYPE_PIXBUF, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_PRIMARY, g_param_spec_string ("primary", "primary", "The primary string", "", G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_SECONDARY, g_param_spec_string ("secondary", "secondary", "The secondary string", "", G_PARAM_READWRITE)); gtk_widget_class_install_style_property (widget_class, g_param_spec_boolean ("show-secondary-text", "show secondary text", "show secondary text", TRUE, G_PARAM_READABLE)); gtk_widget_class_install_style_property (widget_class, g_param_spec_enum ("orientation", "orientation", "The orientation of the tile layout", GTK_TYPE_ORIENTATION, GTK_ORIENTATION_HORIZONTAL, G_PARAM_READABLE)); } static void make_bold (GtkLabel *label) { static PangoAttrList *list = NULL; if (list == NULL) { PangoAttribute *attr; list = pango_attr_list_new (); attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD); attr->start_index = 0; attr->end_index = G_MAXUINT; pango_attr_list_insert (list, attr); attr = pango_attr_scale_new (1.2); attr->start_index = 0; attr->end_index = G_MAXUINT; pango_attr_list_insert (list, attr); } gtk_label_set_attributes (label, list); } static void taku_icon_tile_init (TakuIconTile *self) { self->priv = GET_PRIVATE (self); self->priv->icon = gtk_image_new (); gtk_widget_show (self->priv->icon); g_object_ref (self->priv->icon); self->priv->primary = gtk_label_new (NULL); gtk_label_set_ellipsize (GTK_LABEL (self->priv->primary), PANGO_ELLIPSIZE_END); make_bold (GTK_LABEL (self->priv->primary)); gtk_widget_show (self->priv->primary); g_object_ref (self->priv->primary); self->priv->secondary = gtk_label_new (NULL); gtk_label_set_ellipsize (GTK_LABEL (self->priv->secondary), PANGO_ELLIPSIZE_END); gtk_widget_show (self->priv->secondary); g_object_ref (self->priv->secondary); self->priv->orientation = -1; } GtkWidget * taku_icon_tile_new (void) { return g_object_new (TAKU_TYPE_ICON_TILE, NULL); } void taku_icon_tile_set_pixbuf (TakuIconTile *tile, GdkPixbuf *pixbuf) { g_return_if_fail (TAKU_IS_ICON_TILE (tile)); gtk_image_set_from_pixbuf (GTK_IMAGE (tile->priv->icon), pixbuf); g_object_notify (G_OBJECT (tile), "pixbuf"); } void taku_icon_tile_set_icon_name (TakuIconTile *tile, const char *name) { g_return_if_fail (TAKU_IS_ICON_TILE (tile)); gtk_image_set_from_icon_name (GTK_IMAGE (tile->priv->icon), name, gtk_icon_size_from_name ("taku-icon")); } void taku_icon_tile_set_primary (TakuIconTile *tile, const char *text) { g_return_if_fail (TAKU_IS_ICON_TILE (tile)); gtk_label_set_text (GTK_LABEL (tile->priv->primary), text); if (tile->priv->collation_key) g_free (tile->priv->collation_key); if (text) { gchar *text_casefold = g_utf8_casefold (text, -1); tile->priv->collation_key = g_utf8_collate_key (text_casefold, -1); g_free (text_casefold); } else { tile->priv->collation_key = NULL; } atk_object_set_name (gtk_widget_get_accessible (GTK_WIDGET (tile)), text ?: ""); g_object_notify (G_OBJECT (tile), "primary"); } const char * taku_icon_tile_get_primary (TakuIconTile *tile) { return gtk_label_get_text (GTK_LABEL (tile->priv->primary)); } void taku_icon_tile_set_secondary (TakuIconTile *tile, const char *text) { g_return_if_fail (TAKU_IS_ICON_TILE (tile)); gtk_label_set_text (GTK_LABEL (tile->priv->secondary), text); g_object_notify (G_OBJECT (tile), "secondary"); } const char * taku_icon_tile_get_secondary (TakuIconTile *tile) { return gtk_label_get_text (GTK_LABEL (tile->priv->secondary)); }