diff options
author | Ramiro Estrugo <ramiro@src.gnome.org> | 2001-02-01 10:24:58 +0000 |
---|---|---|
committer | Ramiro Estrugo <ramiro@src.gnome.org> | 2001-02-01 10:24:58 +0000 |
commit | 33f219c3e08f31fb1489af13247c25d1cb9b3e91 (patch) | |
tree | d068ba79078140299f7f6c374cbc01eab12fad62 | |
parent | 93ea1a9d6190670f9566001502d0d0fbb3a02ede (diff) | |
download | nautilus-33f219c3e08f31fb1489af13247c25d1cb9b3e91.tar.gz |
reviewed by: Pavel Cisler <pavel@eazel.com>
* libnautilus-extensions/Makefile.am:
New files.
* libnautilus-extensions/nautilus-art-extensions.c:
(nautilus_art_irect_align):
* libnautilus-extensions/nautilus-art-extensions.h:
Make the align function actually work. The previous version was
copied from GtkPixmap and i didnt realize it did not work. Remove
the padding parameters which are not really needed for alignment.
* libnautilus-extensions/nautilus-clickable-image.h:
* libnautilus-extensions/nautilus-clickable-image.c:
New class. A clickable image.
* libnautilus-extensions/nautilus-labeled-image.h:
* libnautilus-extensions/nautilus-labeled-image.c:
New class. A labeled image.
* libnautilus-extensions/nautilus-image.h:
* libnautilus-extensions/nautilus-image.c:
(nautilus_image_expose_event), (image_get_pixbuf_bounds),
(image_is_smooth), (nautilus_image_set_is_smooth),
(nautilus_image_get_is_smooth), (nautilus_image_new_solid),
(nautilus_image_set_never_smooth):
Add never smooth attribute to force behavior to match GTK+ for
cases when consistency is most important.
Update for alignment art extensions api change.
Some minor paramter name changes to lose abbreviations.
* libnautilus-extensions/nautilus-label.h:
* libnautilus-extensions/nautilus-label.c:
(nautilus_label_size_request), (nautilus_label_expose_event),
(label_get_text_bounds), (label_is_smooth),
(nautilus_label_set_is_smooth), (nautilus_label_get_is_smooth),
(nautilus_label_new_solid), (nautilus_label_set_never_smooth):
Add never smooth attribute to force behavior to match GTK+ for
cases when consistency is most important.
Update for alignment art extensions api change.
Update for alignment art extensions api change.
Some minor paramter name changes to lose abbreviations.
* libnautilus-extensions/nautilus-smooth-widget.c:
(smooth_widget_get_tile_origin_point),
(nautilus_smooth_widget_get_preferred_frame):
Add some comments explaining why using 0 for ancestor offsets
works.
Fix a really dumb bug, the paddings where multiplies by 2 twice
instead of once.
* test/.cvsignore:
* test/Makefile.am:
* test/test-nautilus-clickable-image.c: (clicked_callback),
(enter_callback), (leave_callback), (clickable_image_new), (main):
* test/test-nautilus-label-background.c:
* test/test-nautilus-label-scrolled.c: (label_window_new_scrolled),
(label_window_new_table):
* test/test-nautilus-label-simple.c: (main):
* test/test-nautilus-label.c: (main):
* test/test-nautilus-labeled-image.c: (labeled_image_new),
(labeled_image_window_new), (labeled_image_button_window_new),
(main):
* test/test-nautilus-pixbuf-tile.c:
(pixbuf_drawing_area_expose_event),
(drawable_drawing_area_expose_event), (main):
* test/test-nautilus-preferences-change.c: (main):
* test/test.c: (test_init):
New tests for clickable and labeled images. Many updates to other
tests.
Also, changed many instances of NautilusFooDetail to
NautilusFooDetails as well as the corresponding members.
36 files changed, 6515 insertions, 1030 deletions
@@ -1,3 +1,78 @@ +2001-02-01 Ramiro Estrugo <ramiro@eazel.com> + + reviewed by: Pavel Cisler <pavel@eazel.com> + + * libnautilus-extensions/Makefile.am: + New files. + * libnautilus-extensions/nautilus-art-extensions.c: + (nautilus_art_irect_align): + * libnautilus-extensions/nautilus-art-extensions.h: + Make the align function actually work. The previous version was + copied from GtkPixmap and i didnt realize it did not work. Remove + the padding parameters which are not really needed for alignment. + + * libnautilus-extensions/nautilus-clickable-image.h: + * libnautilus-extensions/nautilus-clickable-image.c: + New class. A clickable image. + + * libnautilus-extensions/nautilus-labeled-image.h: + * libnautilus-extensions/nautilus-labeled-image.c: + New class. A labeled image. + + * libnautilus-extensions/nautilus-image.h: + * libnautilus-extensions/nautilus-image.c: + (nautilus_image_expose_event), (image_get_pixbuf_bounds), + (image_is_smooth), (nautilus_image_set_is_smooth), + (nautilus_image_get_is_smooth), (nautilus_image_new_solid), + (nautilus_image_set_never_smooth): + Add never smooth attribute to force behavior to match GTK+ for + cases when consistency is most important. + Update for alignment art extensions api change. + Some minor paramter name changes to lose abbreviations. + + * libnautilus-extensions/nautilus-label.h: + * libnautilus-extensions/nautilus-label.c: + (nautilus_label_size_request), (nautilus_label_expose_event), + (label_get_text_bounds), (label_is_smooth), + (nautilus_label_set_is_smooth), (nautilus_label_get_is_smooth), + (nautilus_label_new_solid), (nautilus_label_set_never_smooth): + Add never smooth attribute to force behavior to match GTK+ for + cases when consistency is most important. + Update for alignment art extensions api change. + Update for alignment art extensions api change. + Some minor paramter name changes to lose abbreviations. + + * libnautilus-extensions/nautilus-smooth-widget.c: + (smooth_widget_get_tile_origin_point), + (nautilus_smooth_widget_get_preferred_frame): + Add some comments explaining why using 0 for ancestor offsets + works. + Fix a really dumb bug, the paddings where multiplies by 2 twice + instead of once. + + * test/.cvsignore: + * test/Makefile.am: + * test/test-nautilus-clickable-image.c: (clicked_callback), + (enter_callback), (leave_callback), (clickable_image_new), (main): + * test/test-nautilus-label-background.c: + * test/test-nautilus-label-scrolled.c: (label_window_new_scrolled), + (label_window_new_table): + * test/test-nautilus-label-simple.c: (main): + * test/test-nautilus-label.c: (main): + * test/test-nautilus-labeled-image.c: (labeled_image_new), + (labeled_image_window_new), (labeled_image_button_window_new), + (main): + * test/test-nautilus-pixbuf-tile.c: + (pixbuf_drawing_area_expose_event), + (drawable_drawing_area_expose_event), (main): + * test/test-nautilus-preferences-change.c: (main): + * test/test.c: (test_init): + New tests for clickable and labeled images. Many updates to other + tests. + + Also, changed many instances of NautilusFooDetail to + NautilusFooDetails as well as the corresponding members. + 2001-02-01 Gene Z. Ragan <gzr@eazel.com> Additional work on first time druid gmc to nautilus conversion routines. diff --git a/libnautilus-extensions/Makefile.am b/libnautilus-extensions/Makefile.am index 45f0f2922..342ff77de 100644 --- a/libnautilus-extensions/Makefile.am +++ b/libnautilus-extensions/Makefile.am @@ -49,8 +49,8 @@ libnautilus_extensions_la_LDFLAGS = \ libnautilus_extensions_la_SOURCES = \ bug-5712-pr3-workaround--gdk-pixbuf-drawable.c \ - bug-5712-pr3-workaround--gdkimage.c \ bug-5712-pr3-workaround--gdk-pixbuf-private.h \ + bug-5712-pr3-workaround--gdkimage.c \ nautilus-art-extensions.c \ nautilus-art-gtk-extensions.c \ nautilus-background-canvas-group.c \ @@ -59,6 +59,7 @@ libnautilus_extensions_la_SOURCES = \ nautilus-bookmark.c \ nautilus-caption-table.c \ nautilus-caption.c \ + nautilus-clickable-image.c \ nautilus-ctree.c \ nautilus-customization-data.c \ nautilus-dateedit-extensions.c \ @@ -73,8 +74,8 @@ libnautilus_extensions_la_SOURCES = \ nautilus-drag.c \ nautilus-druid-page-eazel.c \ nautilus-druid.c \ - nautilus-entry.c \ nautilus-ellipsizing-label.c \ + nautilus-entry.c \ nautilus-enumeration.c \ nautilus-file-changes-queue.c \ nautilus-file-operations-progress.c \ @@ -104,6 +105,7 @@ libnautilus_extensions_la_SOURCES = \ nautilus-keep-last-vertical-box.c \ nautilus-label-with-background.c \ nautilus-label.c \ + nautilus-labeled-image.c \ nautilus-lib-self-check-functions.c \ nautilus-link-set.c \ nautilus-link.c \ @@ -160,6 +162,7 @@ noinst_HEADERS = \ nautilus-caption-table.h \ nautilus-caption.h \ nautilus-cdrom-extensions.h \ + nautilus-clickable-image.h \ nautilus-ctree.h \ nautilus-customization-data.h \ nautilus-dateedit-extensions.h \ @@ -212,6 +215,7 @@ noinst_HEADERS = \ nautilus-keep-last-vertical-box.h \ nautilus-label-with-background.h \ nautilus-label.h \ + nautilus-labeled-image.h \ nautilus-lib-self-check-functions.h \ nautilus-link-set.h \ nautilus-link.h \ diff --git a/libnautilus-extensions/nautilus-art-extensions.c b/libnautilus-extensions/nautilus-art-extensions.c index 88d581888..9cec8a717 100644 --- a/libnautilus-extensions/nautilus-art-extensions.c +++ b/libnautilus-extensions/nautilus-art-extensions.c @@ -26,6 +26,7 @@ #include <config.h> #include "nautilus-art-extensions.h" +#include <math.h> ArtIRect NAUTILUS_ART_IRECT_EMPTY = { 0, 0, 0, 0 }; NautilusArtIPoint NAUTILUS_ART_IPOINT_ZERO = { 0, 0 }; @@ -172,8 +173,6 @@ nautilus_art_irect_get_height (const ArtIRect *rectangle) * @aligned_height: Height of rectangle being algined. * @x_alignment: X alignment. * @y_alignment: Y alignment. - * @x_padding: X padding. - * @y_padding: Y padding. * * Returns: A rectangle aligned within a container rectangle * using the given alignment parameters. @@ -183,11 +182,11 @@ nautilus_art_irect_align (const ArtIRect *container, int aligned_width, int aligned_height, float x_alignment, - float y_alignment, - int x_padding, - int y_padding) + float y_alignment) { ArtIRect aligned; + int available_width; + int available_height; g_return_val_if_fail (container != NULL, NAUTILUS_ART_IRECT_EMPTY); @@ -200,23 +199,16 @@ nautilus_art_irect_align (const ArtIRect *container, } /* Make sure the aligment parameters are within range */ - x_padding = MAX (0, x_padding); - y_padding = MAX (0, y_padding); x_alignment = MAX (0, x_alignment); x_alignment = MIN (1.0, x_alignment); y_alignment = MAX (0, y_alignment); y_alignment = MIN (1.0, y_alignment); - - aligned.x0 = (container->x0 * (1.0 - x_alignment) + - (container->x0 + nautilus_art_irect_get_width (container) - - (aligned_width - x_padding * 2)) * - x_alignment) + 0.5; - - aligned.y0 = (container->y0 * (1.0 - y_alignment) + - (container->y0 + nautilus_art_irect_get_height (container) - - (aligned_height - y_padding * 2)) * - y_alignment) + 0.5; - + + available_width = nautilus_art_irect_get_width (container) - aligned_width; + available_height = nautilus_art_irect_get_height (container) - aligned_height; + + aligned.x0 = floor (container->x0 + (available_width * x_alignment) + 0.5); + aligned.y0 = floor (container->y0 + (available_height * y_alignment) + 0.5); aligned.x1 = aligned.x0 + aligned_width; aligned.y1 = aligned.y0 + aligned_height; diff --git a/libnautilus-extensions/nautilus-art-extensions.h b/libnautilus-extensions/nautilus-art-extensions.h index 9b6b498c5..b47f2d7ed 100644 --- a/libnautilus-extensions/nautilus-art-extensions.h +++ b/libnautilus-extensions/nautilus-art-extensions.h @@ -66,9 +66,7 @@ ArtIRect nautilus_art_irect_align (const ArtIRect *container, int aligned_width, int aligned_height, float x_alignment, - float y_alignment, - int x_padding, - int y_padding); + float y_alignment); END_GNOME_DECLS #endif /* NAUTILUS_ART_EXTENSIONS_H */ diff --git a/libnautilus-extensions/nautilus-clickable-image.c b/libnautilus-extensions/nautilus-clickable-image.c new file mode 100644 index 000000000..f39a4c4d2 --- /dev/null +++ b/libnautilus-extensions/nautilus-clickable-image.c @@ -0,0 +1,551 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ + +/* nautilus-clickable-image.c - A clickable image widget. + + Copyright (C) 2000 Eazel, Inc. + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Authors: Ramiro Estrugo <ramiro@eazel.com> +*/ + +#include <config.h> + +#include "nautilus-clickable-image.h" + +#include "nautilus-gtk-macros.h" +#include "nautilus-gtk-extensions.h" +#include "nautilus-art-gtk-extensions.h" + +/* Arguments */ +enum +{ + ARG_0, + ARG_POINTER_INSIDE, +}; + +/* Signals */ +typedef enum +{ + CLICKED, + ENTER, + LEAVE, + LAST_SIGNAL +} ImageSignal; + +/* Signals */ +static guint clickable_image_signals[LAST_SIGNAL] = { 0 }; + +/* Detail member struct */ +struct _NautilusClickableImageDetails +{ + gboolean pointer_inside; +}; + +/* GtkObjectClass methods */ +static void nautilus_clickable_image_initialize_class (NautilusClickableImageClass *image_class); +static void nautilus_clickable_image_initialize (NautilusClickableImage *image); +static void nautilus_clickable_image_destroy (GtkObject *object); +static void nautilus_clickable_image_get_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); +/* GtkWidgetClass methods */ +static int nautilus_clickable_image_expose_event (GtkWidget *widget, + GdkEventExpose *event); +static void nautilus_clickable_image_realize (GtkWidget *widget); +static void nautilus_clickable_image_unrealize (GtkWidget *widget); + + +/* Ancestor callbacks */ +static int ancestor_enter_notify_event (GtkWidget *widget, + GdkEventCrossing *event, + gpointer event_data); +static int ancestor_leave_notify_event (GtkWidget *widget, + GdkEventCrossing *event, + gpointer event_data); +static int ancestor_motion_notify_event (GtkWidget *widget, + GdkEventMotion *event, + gpointer event_data); +static int ancestor_button_press_event (GtkWidget *widget, + GdkEventButton *event, + gpointer event_data); +static int ancestor_button_release_event (GtkWidget *widget, + GdkEventButton *event, + gpointer event_data); + +NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusClickableImage, nautilus_clickable_image, NAUTILUS_TYPE_LABELED_IMAGE) + +/* Class init methods */ +static void +nautilus_clickable_image_initialize_class (NautilusClickableImageClass *image_class) +{ + GtkObjectClass *object_class = GTK_OBJECT_CLASS (image_class); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (image_class); + + /* GtkObjectClass */ + object_class->destroy = nautilus_clickable_image_destroy; + object_class->get_arg = nautilus_clickable_image_get_arg; + + /* GtkWidgetClass */ + widget_class->expose_event = nautilus_clickable_image_expose_event; + widget_class->realize = nautilus_clickable_image_realize; + widget_class->unrealize = nautilus_clickable_image_unrealize; + + /* Signals */ + clickable_image_signals[CLICKED] = gtk_signal_new ("clicked", + GTK_RUN_LAST, + object_class->type, + 0, + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, + 0); + + clickable_image_signals[ENTER] = gtk_signal_new ("enter", + GTK_RUN_LAST, + object_class->type, + 0, + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, + 0); + + clickable_image_signals[LEAVE] = gtk_signal_new ("leave", + GTK_RUN_LAST, + object_class->type, + 0, + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, + 0); + + gtk_object_class_add_signals (object_class, clickable_image_signals, LAST_SIGNAL); + + /* Arguments */ + gtk_object_add_arg_type ("NautilusClickableImage::pointer_inside", + GTK_TYPE_BOOL, + GTK_ARG_READABLE, + ARG_POINTER_INSIDE); +} + +void +nautilus_clickable_image_initialize (NautilusClickableImage *image) +{ + image->details = g_new0 (NautilusClickableImageDetails, 1); +} + +/* GtkObjectClass methods */ +static void +nautilus_clickable_image_destroy (GtkObject *object) +{ + NautilusClickableImage *clickable_image; + + g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (object)); + + clickable_image = NAUTILUS_CLICKABLE_IMAGE (object); + + g_free (clickable_image->details); + + /* Chain destroy */ + NAUTILUS_CALL_PARENT_CLASS (GTK_OBJECT_CLASS, destroy, (object)); +} + +static void +nautilus_clickable_image_get_arg (GtkObject *object, + GtkArg *arg, + guint arg_id) +{ + NautilusClickableImage *clickable_image; + + g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (object)); + + clickable_image = NAUTILUS_CLICKABLE_IMAGE (object); + + switch (arg_id) + { + case ARG_POINTER_INSIDE: + GTK_VALUE_BOOL (*arg) = clickable_image->details->pointer_inside; + break; + + default: + g_assert_not_reached (); + } +} + +/* GtkWidgetClass methods */ +static void +nautilus_clickable_image_realize (GtkWidget *widget) +{ + NautilusClickableImage *clickable_image; + GtkWidget *windowed_ancestor; + + g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (widget)); + + clickable_image = NAUTILUS_CLICKABLE_IMAGE (widget); + + /* Chain realize */ + NAUTILUS_CALL_PARENT_CLASS (GTK_WIDGET_CLASS, realize, (widget)); + + windowed_ancestor = nautilus_gtk_widget_find_windowed_ancestor (widget); + g_assert (GTK_IS_WIDGET (windowed_ancestor)); + + gtk_widget_add_events (windowed_ancestor, + GDK_BUTTON_PRESS_MASK + | GDK_BUTTON_RELEASE_MASK + | GDK_ENTER_NOTIFY_MASK + | GDK_LEAVE_NOTIFY_MASK + | GDK_POINTER_MOTION_MASK); + + gtk_signal_connect_while_alive (GTK_OBJECT (windowed_ancestor), + "enter_notify_event", + GTK_SIGNAL_FUNC (ancestor_enter_notify_event), + widget, + GTK_OBJECT (widget)); + + gtk_signal_connect_while_alive (GTK_OBJECT (windowed_ancestor), + "leave_notify_event", + GTK_SIGNAL_FUNC (ancestor_leave_notify_event), + widget, + GTK_OBJECT (widget)); + + gtk_signal_connect_while_alive (GTK_OBJECT (windowed_ancestor), + "motion_notify_event", + GTK_SIGNAL_FUNC (ancestor_motion_notify_event), + widget, + GTK_OBJECT (widget)); + + gtk_signal_connect_while_alive (GTK_OBJECT (windowed_ancestor), + "button_press_event", + GTK_SIGNAL_FUNC (ancestor_button_press_event), + widget, + GTK_OBJECT (widget)); + + gtk_signal_connect_while_alive (GTK_OBJECT (windowed_ancestor), + "button_release_event", + GTK_SIGNAL_FUNC (ancestor_button_release_event), + widget, + GTK_OBJECT (widget)); +} + +static void +nautilus_clickable_image_unrealize (GtkWidget *widget) +{ + NautilusClickableImage *clickable_image; + GtkWidget *windowed_ancestor; + + g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (widget)); + + clickable_image = NAUTILUS_CLICKABLE_IMAGE (widget); + + windowed_ancestor = nautilus_gtk_widget_find_windowed_ancestor (widget); + g_assert (GTK_IS_WIDGET (windowed_ancestor)); + + gtk_signal_disconnect_by_func (GTK_OBJECT (windowed_ancestor), + GTK_SIGNAL_FUNC (ancestor_enter_notify_event), + widget); + + gtk_signal_disconnect_by_func (GTK_OBJECT (windowed_ancestor), + GTK_SIGNAL_FUNC (ancestor_leave_notify_event), + widget); + + gtk_signal_disconnect_by_func (GTK_OBJECT (windowed_ancestor), + GTK_SIGNAL_FUNC (ancestor_motion_notify_event), + widget); + + gtk_signal_disconnect_by_func (GTK_OBJECT (windowed_ancestor), + GTK_SIGNAL_FUNC (ancestor_button_press_event), + widget); + + gtk_signal_disconnect_by_func (GTK_OBJECT (windowed_ancestor), + GTK_SIGNAL_FUNC (ancestor_button_release_event), + widget); + + /* Chain unrealize */ + NAUTILUS_CALL_PARENT_CLASS (GTK_WIDGET_CLASS, unrealize, (widget)); +} + +static void +label_enter (NautilusClickableImage *clickable_image) +{ + g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (clickable_image)); + + clickable_image->details->pointer_inside = TRUE; + + gtk_widget_set_state (GTK_WIDGET (clickable_image), GTK_STATE_PRELIGHT); + gtk_widget_queue_draw (GTK_WIDGET (clickable_image)); + + gtk_signal_emit (GTK_OBJECT (clickable_image), + clickable_image_signals[ENTER], + clickable_image); + +} + +static void +label_leave (NautilusClickableImage *clickable_image) +{ + g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (clickable_image)); + + clickable_image->details->pointer_inside = FALSE; + + gtk_widget_set_state (GTK_WIDGET (clickable_image), GTK_STATE_NORMAL); + gtk_widget_queue_draw (GTK_WIDGET (clickable_image)); + + gtk_signal_emit (GTK_OBJECT (clickable_image), + clickable_image_signals[LEAVE], + clickable_image); +} + +static void +label_handle_motion (NautilusClickableImage *clickable_image, + int x, + int y) +{ + ArtIRect bounds; + + g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (clickable_image)); + + bounds = nautilus_irect_gtk_widget_get_bounds (GTK_WIDGET (clickable_image)); + + if (nautilus_art_irect_contains_point (&bounds, x, y)) { + /* Inside */ + if (!clickable_image->details->pointer_inside) { + label_enter (clickable_image); + } + } else { + /* Outside */ + if (clickable_image->details->pointer_inside) { + label_leave (clickable_image); + } + } +} + +static void +label_handle_button_press (NautilusClickableImage *clickable_image) +{ + g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (clickable_image)); + + gtk_widget_set_state (GTK_WIDGET (clickable_image), GTK_STATE_ACTIVE); + gtk_widget_queue_draw (GTK_WIDGET (clickable_image)); +} + +static void +label_handle_button_release (NautilusClickableImage *clickable_image) +{ + g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (clickable_image)); + + gtk_widget_set_state (GTK_WIDGET (clickable_image), GTK_STATE_PRELIGHT); + gtk_widget_queue_draw (GTK_WIDGET (clickable_image)); + + gtk_signal_emit (GTK_OBJECT (clickable_image), + clickable_image_signals[CLICKED], + clickable_image); +} + +static int +ancestor_enter_notify_event (GtkWidget *widget, + GdkEventCrossing *event, + gpointer event_data) +{ + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); + g_return_val_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (event_data), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + label_handle_motion (NAUTILUS_CLICKABLE_IMAGE (event_data), event->x, event->y); + + return FALSE; +} + +static int +ancestor_leave_notify_event (GtkWidget *widget, + GdkEventCrossing *event, + gpointer event_data) +{ + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); + g_return_val_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (event_data), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + label_handle_motion (NAUTILUS_CLICKABLE_IMAGE (event_data), event->x, event->y); + + return FALSE; +} + +static int +ancestor_motion_notify_event (GtkWidget *widget, + GdkEventMotion *event, + gpointer event_data) +{ + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); + g_return_val_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (event_data), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + label_handle_motion (NAUTILUS_CLICKABLE_IMAGE (event_data), event->x, event->y); + + return FALSE; +} + +static int +ancestor_button_press_event (GtkWidget *widget, + GdkEventButton *event, + gpointer event_data) +{ + NautilusClickableImage *clickable_image; + + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); + g_return_val_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (event_data), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + clickable_image = NAUTILUS_CLICKABLE_IMAGE (event_data); + + if (clickable_image->details->pointer_inside) { + label_handle_button_press (NAUTILUS_CLICKABLE_IMAGE (event_data)); + } + + return FALSE; +} + +static int +ancestor_button_release_event (GtkWidget *widget, + GdkEventButton *event, + gpointer event_data) +{ + NautilusClickableImage *clickable_image; + + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); + g_return_val_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (event_data), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + clickable_image = NAUTILUS_CLICKABLE_IMAGE (event_data); + + if (clickable_image->details->pointer_inside) { + label_handle_button_release (NAUTILUS_CLICKABLE_IMAGE (event_data)); + } + + return FALSE; +} + +static int +nautilus_clickable_image_expose_event (GtkWidget *widget, + GdkEventExpose *event) +{ + NautilusClickableImage *clickable_image; + + g_return_val_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (widget), TRUE); + g_return_val_if_fail (event != NULL, TRUE); + g_return_val_if_fail (event->window == widget->window, TRUE); + g_return_val_if_fail (GTK_WIDGET_REALIZED (widget), TRUE); + + clickable_image = NAUTILUS_CLICKABLE_IMAGE (widget); + + /* Chain expose */ + return NAUTILUS_CALL_PARENT_CLASS (GTK_WIDGET_CLASS, expose_event, (widget, event)); +} + +/* Public NautilusClickableImage methods */ + +/** + * nautilus_clickable_image_new: + * + * @text: Text for label or NULL. + * @pixbuf: A GdkPixbuf to or NULL. + + * Create a clickable image with a solid background. + * + * Return value: The newly allocated NautilusClickableImage with the + * given text and pixbuf. Either of these two can be NULL. + */ +GtkWidget* +nautilus_clickable_image_new (const char *text, + GdkPixbuf *pixbuf) +{ + NautilusClickableImage *clickable_image; + + clickable_image = NAUTILUS_CLICKABLE_IMAGE (gtk_widget_new (nautilus_clickable_image_get_type (), NULL)); + + if (pixbuf != NULL) { + nautilus_labeled_image_set_pixbuf (NAUTILUS_LABELED_IMAGE (clickable_image), pixbuf); + } + + if (text != NULL) { + nautilus_labeled_image_set_text (NAUTILUS_LABELED_IMAGE (clickable_image), text); + } + + return GTK_WIDGET (clickable_image); +} + +/** + * nautilus_clickable_image_new_solid: + * + * @text: Text for label or NULL. + * @pixbuf: A GdkPixbuf to or NULL. + * @drop_shadow_offset: Drop shadow offset. + * @drop_shadow_color: Drop shadow color. + * @text_color: Text color. + * @x_alignment: Horizontal alignment. + * @y_alignmtn: Vertical alignment. + * @x_padding: Horizontal padding. + * @y_padding: Vertical padding. + * @background_color: Background color. + * @tile_pixbuf: A GdkPixbuf or NULL. + * + * Create a clickable image with a solid background. + * + * Return value: The newly allocated NautilusClickableImage with the + * given attributes. + */ +GtkWidget * +nautilus_clickable_image_new_solid (const char *text, + GdkPixbuf *pixbuf, + guint drop_shadow_offset, + guint32 drop_shadow_color, + guint32 text_color, + float x_alignment, + float y_alignment, + int x_padding, + int y_padding, + guint32 background_color, + GdkPixbuf *tile_pixbuf) +{ + NautilusClickableImage *clickable_image; + NautilusLabeledImage *labeled_image; + + clickable_image = NAUTILUS_CLICKABLE_IMAGE (gtk_widget_new (nautilus_clickable_image_get_type (), NULL)); + + labeled_image = NAUTILUS_LABELED_IMAGE (clickable_image); + + if (pixbuf != NULL) { + nautilus_labeled_image_set_pixbuf (labeled_image, pixbuf); + } + + if (text != NULL) { + nautilus_labeled_image_set_text (labeled_image, text); + } + + nautilus_labeled_image_set_background_mode (labeled_image, NAUTILUS_SMOOTH_BACKGROUND_SOLID_COLOR); + nautilus_labeled_image_set_solid_background_color (labeled_image, background_color); + nautilus_labeled_image_set_smooth_drop_shadow_color (labeled_image, drop_shadow_color); + nautilus_labeled_image_set_smooth_drop_shadow_offset (labeled_image, drop_shadow_offset); + nautilus_labeled_image_set_text_color (labeled_image, text_color); + + if (tile_pixbuf != NULL) { + nautilus_labeled_image_set_tile_pixbuf (labeled_image, tile_pixbuf); + } + + nautilus_labeled_image_set_x_padding (labeled_image, x_padding); + nautilus_labeled_image_set_y_padding (labeled_image, y_padding); + nautilus_labeled_image_set_x_alignment (labeled_image, x_alignment); + nautilus_labeled_image_set_y_alignment (labeled_image, y_alignment); + + return GTK_WIDGET (clickable_image); +} + + diff --git a/libnautilus-extensions/nautilus-clickable-image.h b/libnautilus-extensions/nautilus-clickable-image.h new file mode 100644 index 000000000..387743073 --- /dev/null +++ b/libnautilus-extensions/nautilus-clickable-image.h @@ -0,0 +1,94 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ + +/* nautilus-clickable-image.h - A clickable image widget. + + Copyright (C) 2000 Eazel, Inc. + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Authors: Ramiro Estrugo <ramiro@eazel.com> +*/ + +/* NautilusClickableImage is a NautilusLabeledImage sublclass that can handle + * event useful for detect click events. + * + * The following signals are provided by NautilusClickableImage: + * + * "clicked" - Widget was clicked + * "enter" - Pointer entered widget. + * "leave" - Pointer left widget. + * + * NautilusClickableImage is a NO_WINDOW widget. It does it event detection + * by monitoring events on the first windowed ancestor in its widget hierarchy. + * + * Being a NO_WINDOW widget, it will work nicely with tile_pixbufs. + */ + +#ifndef NAUTILUS_CLICKABLE_IMAGE_H +#define NAUTILUS_CLICKABLE_IMAGE_H + +#include <libnautilus-extensions/nautilus-labeled-image.h> + +BEGIN_GNOME_DECLS + +#define NAUTILUS_TYPE_CLICKABLE_IMAGE (nautilus_clickable_image_get_type ()) +#define NAUTILUS_CLICKABLE_IMAGE(obj) (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_CLICKABLE_IMAGE, NautilusClickableImage)) +#define NAUTILUS_CLICKABLE_IMAGE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_CLICKABLE_IMAGE, NautilusClickableImageClass)) +#define NAUTILUS_IS_CLICKABLE_IMAGE(obj) (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_CLICKABLE_IMAGE)) +#define NAUTILUS_IS_CLICKABLE_IMAGE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_CLICKABLE_IMAGE)) + +typedef struct _NautilusClickableImage NautilusClickableImage; +typedef struct _NautilusClickableImageClass NautilusClickableImageClass; +typedef struct _NautilusClickableImageDetails NautilusClickableImageDetails; + +struct _NautilusClickableImage +{ + /* Superclass */ + NautilusLabeledImage labeled_image; + + /* Private things */ + NautilusClickableImageDetails *details; +}; + +struct _NautilusClickableImageClass +{ + NautilusLabeledImageClass parent_class; + + void (*clicked) (NautilusClickableImage *image); + void (*enter) (NautilusClickableImage *image); + void (*leave) (NautilusClickableImage *image); +}; + +GtkType nautilus_clickable_image_get_type (void); +GtkWidget *nautilus_clickable_image_new (const char *text, + GdkPixbuf *pixbuf); +GtkWidget *nautilus_clickable_image_new_solid (const char *text, + GdkPixbuf *pixbuf, + guint drop_shadow_offset, + guint32 drop_shadow_color, + guint32 text_color, + float x_alignment, + float y_alignment, + int x_padding, + int y_padding, + guint32 background_color, + GdkPixbuf *tile_pixbuf); + +END_GNOME_DECLS + +#endif /* NAUTILUS_CLICKABLE_IMAGE_H */ + + diff --git a/libnautilus-extensions/nautilus-image.c b/libnautilus-extensions/nautilus-image.c index c3b326d58..746046a36 100644 --- a/libnautilus-extensions/nautilus-image.c +++ b/libnautilus-extensions/nautilus-image.c @@ -63,7 +63,7 @@ typedef enum static guint image_signals[LAST_SIGNAL] = { 0 }; /* Detail member struct */ -struct _NautilusImageDetail +struct _NautilusImageDetails { gboolean is_smooth; @@ -82,6 +82,7 @@ struct _NautilusImageDetail /* Background */ NautilusSmoothBackgroundMode background_mode; guint32 solid_background_color; + gboolean never_smooth; }; /* GtkObjectClass methods */ @@ -108,6 +109,7 @@ static void nautilus_image_set_is_smooth_signal (GtkWidget *widget static ArtIRect image_get_pixbuf_frame (const NautilusImage *image); static ArtIRect image_get_pixbuf_bounds (const NautilusImage *image); static ArtIRect image_get_tile_frame (const NautilusImage *image); +static gboolean image_is_smooth (const NautilusImage *image); NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusImage, nautilus_image, GTK_TYPE_MISC) @@ -204,15 +206,15 @@ nautilus_image_initialize (NautilusImage *image) GTK_WIDGET_UNSET_FLAGS (image, GTK_CAN_FOCUS); GTK_WIDGET_SET_FLAGS (image, GTK_NO_WINDOW); - image->detail = g_new0 (NautilusImageDetail, 1); + image->details = g_new0 (NautilusImageDetails, 1); - image->detail->pixbuf_opacity = NAUTILUS_OPACITY_FULLY_OPAQUE; - image->detail->tile_opacity = NAUTILUS_OPACITY_FULLY_OPAQUE; - image->detail->tile_width = NAUTILUS_SMOOTH_TILE_EXTENT_FULL; - image->detail->tile_height = NAUTILUS_SMOOTH_TILE_EXTENT_FULL; - image->detail->tile_mode_vertical = NAUTILUS_SMOOTH_TILE_SELF; - image->detail->tile_mode_horizontal = NAUTILUS_SMOOTH_TILE_SELF; - image->detail->background_mode = NAUTILUS_SMOOTH_BACKGROUND_GTK; + image->details->pixbuf_opacity = NAUTILUS_OPACITY_FULLY_OPAQUE; + image->details->tile_opacity = NAUTILUS_OPACITY_FULLY_OPAQUE; + image->details->tile_width = NAUTILUS_SMOOTH_TILE_EXTENT_FULL; + image->details->tile_height = NAUTILUS_SMOOTH_TILE_EXTENT_FULL; + image->details->tile_mode_vertical = NAUTILUS_SMOOTH_TILE_SELF; + image->details->tile_mode_horizontal = NAUTILUS_SMOOTH_TILE_SELF; + image->details->background_mode = NAUTILUS_SMOOTH_BACKGROUND_GTK; nautilus_smooth_widget_register (GTK_WIDGET (image)); } @@ -227,10 +229,10 @@ nautilus_image_destroy (GtkObject *object) image = NAUTILUS_IMAGE (object); - nautilus_gdk_pixbuf_unref_if_not_null (image->detail->tile_pixbuf); - image->detail->tile_pixbuf = NULL; + nautilus_gdk_pixbuf_unref_if_not_null (image->details->tile_pixbuf); + image->details->tile_pixbuf = NULL; - g_free (image->detail); + g_free (image->details); /* Chain destroy */ NAUTILUS_CALL_PARENT_CLASS (GTK_OBJECT_CLASS, destroy, (object)); @@ -373,8 +375,8 @@ nautilus_image_size_request (GtkWidget *widget, preferred_frame = nautilus_smooth_widget_get_preferred_frame (widget, &pixbuf_frame, &tile_frame, - image->detail->tile_width, - image->detail->tile_height); + image->details->tile_width, + image->details->tile_height); requisition->width = preferred_frame.x1; requisition->height = preferred_frame.y1; } @@ -398,9 +400,9 @@ image_paint_pixbuf_callback (GtkWidget *widget, image = NAUTILUS_IMAGE (widget); - g_return_if_fail (nautilus_gdk_pixbuf_is_valid (image->detail->pixbuf)); + g_return_if_fail (nautilus_gdk_pixbuf_is_valid (image->details->pixbuf)); - nautilus_gdk_pixbuf_draw_to_drawable (image->detail->pixbuf, + nautilus_gdk_pixbuf_draw_to_drawable (image->details->pixbuf, destination_drawable, gc, source_x, @@ -429,9 +431,9 @@ image_composite_pixbuf_callback (GtkWidget *widget, image = NAUTILUS_IMAGE (widget); - g_return_if_fail (nautilus_gdk_pixbuf_is_valid (image->detail->pixbuf)); + g_return_if_fail (nautilus_gdk_pixbuf_is_valid (image->details->pixbuf)); - nautilus_gdk_pixbuf_draw_to_pixbuf_alpha (image->detail->pixbuf, + nautilus_gdk_pixbuf_draw_to_pixbuf_alpha (image->details->pixbuf, destination_pixbuf, source_x, source_y, @@ -460,12 +462,12 @@ nautilus_image_expose_event (GtkWidget *widget, pixbuf_bounds = image_get_pixbuf_bounds (image); tile_bounds = nautilus_smooth_widget_get_tile_bounds (widget, - image->detail->tile_pixbuf, - image->detail->tile_width, - image->detail->tile_height); + image->details->tile_pixbuf, + image->details->tile_width, + image->details->tile_height); /* Check for the dumb case when theres nothing to do */ - if (image->detail->pixbuf == NULL && image->detail->tile_pixbuf == NULL) { + if (image->details->pixbuf == NULL && image->details->tile_pixbuf == NULL) { return TRUE; } @@ -481,16 +483,16 @@ nautilus_image_expose_event (GtkWidget *widget, /* Paint ourselves */ nautilus_smooth_widget_paint (widget, widget->style->white_gc, - image->detail->is_smooth, - image->detail->background_mode, - image->detail->solid_background_color, - image->detail->tile_pixbuf, + image_is_smooth (image), + image->details->background_mode, + image->details->solid_background_color, + image->details->tile_pixbuf, &tile_bounds, - image->detail->tile_opacity, - image->detail->tile_mode_vertical, - image->detail->tile_mode_horizontal, + image->details->tile_opacity, + image->details->tile_mode_vertical, + image->details->tile_mode_horizontal, &pixbuf_bounds, - image->detail->pixbuf_opacity, + image->details->pixbuf_opacity, &screen_dirty_area, image_paint_pixbuf_callback, image_composite_pixbuf_callback, @@ -517,14 +519,14 @@ image_get_pixbuf_frame (const NautilusImage *image) g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), NAUTILUS_ART_IRECT_EMPTY); - if (!image->detail->pixbuf) { + if (!image->details->pixbuf) { return NAUTILUS_ART_IRECT_EMPTY; } pixbuf_frame.x0 = 0; pixbuf_frame.y0 = 0; - pixbuf_frame.x1 = gdk_pixbuf_get_width (image->detail->pixbuf); - pixbuf_frame.y1 = gdk_pixbuf_get_height (image->detail->pixbuf); + pixbuf_frame.x1 = gdk_pixbuf_get_width (image->details->pixbuf); + pixbuf_frame.y1 = gdk_pixbuf_get_height (image->details->pixbuf); return pixbuf_frame; } @@ -550,9 +552,7 @@ image_get_pixbuf_bounds (const NautilusImage *image) pixbuf_frame.x1, pixbuf_frame.y1, GTK_MISC (image)->xalign, - GTK_MISC (image)->yalign, - GTK_MISC (image)->xpad, - GTK_MISC (image)->ypad); + GTK_MISC (image)->yalign); return pixbuf_bounds; } @@ -564,18 +564,26 @@ image_get_tile_frame (const NautilusImage *image) g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), NAUTILUS_ART_IRECT_EMPTY); - if (!image->detail->tile_pixbuf) { + if (!image->details->tile_pixbuf) { return NAUTILUS_ART_IRECT_EMPTY; } tile_frame.x0 = 0; tile_frame.y0 = 0; - tile_frame.x1 = gdk_pixbuf_get_width (image->detail->tile_pixbuf); - tile_frame.y1 = gdk_pixbuf_get_height (image->detail->tile_pixbuf); + tile_frame.x1 = gdk_pixbuf_get_width (image->details->tile_pixbuf); + tile_frame.y1 = gdk_pixbuf_get_height (image->details->tile_pixbuf); return tile_frame; } +gboolean +image_is_smooth (const NautilusImage *image) +{ + g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), FALSE); + + return !image->details->never_smooth && image->details->is_smooth; +} + /* Public NautilusImage methods */ GtkWidget* nautilus_image_new (const char *file_name) @@ -597,11 +605,15 @@ nautilus_image_set_is_smooth (NautilusImage *image, { g_return_if_fail (NAUTILUS_IS_IMAGE (image)); - if (image->detail->is_smooth == is_smooth) { + if (image->details->never_smooth) { return; } - image->detail->is_smooth = is_smooth; + if (image->details->is_smooth == is_smooth) { + return; + } + + image->details->is_smooth = is_smooth; /* We call queue_resize() instead queue_draw() because * we want the widget's background to be cleared of @@ -616,7 +628,7 @@ nautilus_image_get_is_smooth (const NautilusImage *image) { g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), FALSE); - return image->detail->is_smooth; + return image_is_smooth (image); } /** @@ -634,11 +646,11 @@ nautilus_image_set_tile_pixbuf (NautilusImage *image, { g_return_if_fail (NAUTILUS_IS_IMAGE (image)); - if (pixbuf != image->detail->tile_pixbuf) { - nautilus_gdk_pixbuf_unref_if_not_null (image->detail->tile_pixbuf); + if (pixbuf != image->details->tile_pixbuf) { + nautilus_gdk_pixbuf_unref_if_not_null (image->details->tile_pixbuf); nautilus_gdk_pixbuf_ref_if_not_null (pixbuf); - image->detail->tile_pixbuf = pixbuf; + image->details->tile_pixbuf = pixbuf; gtk_widget_queue_draw (GTK_WIDGET (image)); } @@ -657,9 +669,9 @@ nautilus_image_get_tile_pixbuf (const NautilusImage *image) { g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), NULL); - nautilus_gdk_pixbuf_ref_if_not_null (image->detail->tile_pixbuf); + nautilus_gdk_pixbuf_ref_if_not_null (image->details->tile_pixbuf); - return image->detail->tile_pixbuf; + return image->details->tile_pixbuf; } void @@ -668,10 +680,10 @@ nautilus_image_set_pixbuf (NautilusImage *image, { g_return_if_fail (NAUTILUS_IS_IMAGE (image)); - if (pixbuf != image->detail->pixbuf) { - nautilus_gdk_pixbuf_unref_if_not_null (image->detail->pixbuf); + if (pixbuf != image->details->pixbuf) { + nautilus_gdk_pixbuf_unref_if_not_null (image->details->pixbuf); nautilus_gdk_pixbuf_ref_if_not_null (pixbuf); - image->detail->pixbuf = pixbuf; + image->details->pixbuf = pixbuf; gtk_widget_queue_resize (GTK_WIDGET (image)); } } @@ -698,9 +710,9 @@ nautilus_image_get_pixbuf (const NautilusImage *image) { g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), NULL); - nautilus_gdk_pixbuf_ref_if_not_null (image->detail->pixbuf); + nautilus_gdk_pixbuf_ref_if_not_null (image->details->pixbuf); - return image->detail->pixbuf; + return image->details->pixbuf; } void @@ -711,11 +723,11 @@ nautilus_image_set_pixbuf_opacity (NautilusImage *image, g_return_if_fail (pixbuf_opacity >= NAUTILUS_OPACITY_FULLY_TRANSPARENT); g_return_if_fail (pixbuf_opacity <= NAUTILUS_OPACITY_FULLY_OPAQUE); - if (image->detail->pixbuf_opacity == pixbuf_opacity) { + if (image->details->pixbuf_opacity == pixbuf_opacity) { return; } - image->detail->pixbuf_opacity = pixbuf_opacity; + image->details->pixbuf_opacity = pixbuf_opacity; gtk_widget_queue_draw (GTK_WIDGET (image)); } @@ -725,7 +737,7 @@ nautilus_image_get_pixbuf_opacity (const NautilusImage *image) { g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), NAUTILUS_OPACITY_FULLY_OPAQUE); - return image->detail->pixbuf_opacity; + return image->details->pixbuf_opacity; } void @@ -736,11 +748,11 @@ nautilus_image_set_tile_opacity (NautilusImage *image, g_return_if_fail (tile_opacity >= NAUTILUS_OPACITY_FULLY_TRANSPARENT); g_return_if_fail (tile_opacity <= NAUTILUS_OPACITY_FULLY_OPAQUE); - if (image->detail->tile_opacity == tile_opacity) { + if (image->details->tile_opacity == tile_opacity) { return; } - image->detail->tile_opacity = tile_opacity; + image->details->tile_opacity = tile_opacity; gtk_widget_queue_draw (GTK_WIDGET (image)); } @@ -750,7 +762,7 @@ nautilus_image_get_tile_opacity (const NautilusImage *image) { g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), NAUTILUS_OPACITY_FULLY_OPAQUE); - return image->detail->tile_opacity; + return image->details->tile_opacity; } void @@ -760,11 +772,11 @@ nautilus_image_set_tile_width (NautilusImage *image, g_return_if_fail (NAUTILUS_IS_IMAGE (image)); g_return_if_fail (tile_width >= NAUTILUS_SMOOTH_TILE_EXTENT_ONE_STEP); - if (image->detail->tile_width == tile_width) { + if (image->details->tile_width == tile_width) { return; } - image->detail->tile_width = tile_width; + image->details->tile_width = tile_width; gtk_widget_queue_resize (GTK_WIDGET (image)); } @@ -781,7 +793,7 @@ nautilus_image_get_tile_width (const NautilusImage *image) { g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), 0); - return image->detail->tile_width; + return image->details->tile_width; } void @@ -791,11 +803,11 @@ nautilus_image_set_tile_height (NautilusImage *image, g_return_if_fail (NAUTILUS_IS_IMAGE (image)); g_return_if_fail (tile_height >= NAUTILUS_SMOOTH_TILE_EXTENT_ONE_STEP); - if (image->detail->tile_height == tile_height) { + if (image->details->tile_height == tile_height) { return; } - image->detail->tile_height = tile_height; + image->details->tile_height = tile_height; gtk_widget_queue_resize (GTK_WIDGET (image)); } @@ -812,7 +824,7 @@ nautilus_image_get_tile_height (const NautilusImage *image) { g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), 0); - return image->detail->tile_height; + return image->details->tile_height; } void @@ -823,11 +835,11 @@ nautilus_image_set_tile_mode_vertical (NautilusImage *image, g_return_if_fail (tile_mode_vertical >= NAUTILUS_SMOOTH_TILE_SELF); g_return_if_fail (tile_mode_vertical <= NAUTILUS_SMOOTH_TILE_ANCESTOR); - if (image->detail->tile_mode_vertical == tile_mode_vertical) { + if (image->details->tile_mode_vertical == tile_mode_vertical) { return; } - image->detail->tile_mode_vertical = tile_mode_vertical; + image->details->tile_mode_vertical = tile_mode_vertical; gtk_widget_queue_draw (GTK_WIDGET (image)); } @@ -837,7 +849,7 @@ nautilus_image_get_tile_mode_vertical (const NautilusImage *image) { g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), 0); - return image->detail->tile_mode_vertical; + return image->details->tile_mode_vertical; } void @@ -848,11 +860,11 @@ nautilus_image_set_tile_mode_horizontal (NautilusImage *image, g_return_if_fail (tile_mode_horizontal >= NAUTILUS_SMOOTH_TILE_SELF); g_return_if_fail (tile_mode_horizontal <= NAUTILUS_SMOOTH_TILE_ANCESTOR); - if (image->detail->tile_mode_horizontal == tile_mode_horizontal) { + if (image->details->tile_mode_horizontal == tile_mode_horizontal) { return; } - image->detail->tile_mode_horizontal = tile_mode_horizontal; + image->details->tile_mode_horizontal = tile_mode_horizontal; gtk_widget_queue_draw (GTK_WIDGET (image)); } @@ -862,7 +874,7 @@ nautilus_image_get_tile_mode_horizontal (const NautilusImage *image) { g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), 0); - return image->detail->tile_mode_horizontal; + return image->details->tile_mode_horizontal; } void @@ -890,11 +902,11 @@ nautilus_image_set_background_mode (NautilusImage *image, g_return_if_fail (background_mode >= NAUTILUS_SMOOTH_BACKGROUND_GTK); g_return_if_fail (background_mode <= NAUTILUS_SMOOTH_BACKGROUND_SOLID_COLOR); - if (image->detail->background_mode == background_mode) { + if (image->details->background_mode == background_mode) { return; } - image->detail->background_mode = background_mode; + image->details->background_mode = background_mode; gtk_widget_queue_draw (GTK_WIDGET (image)); } @@ -904,7 +916,7 @@ nautilus_image_get_background_mode (const NautilusImage *image) { g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), 0); - return image->detail->background_mode; + return image->details->background_mode; } void @@ -913,11 +925,11 @@ nautilus_image_set_solid_background_color (NautilusImage *image, { g_return_if_fail (NAUTILUS_IS_IMAGE (image)); - if (image->detail->solid_background_color == solid_background_color) { + if (image->details->solid_background_color == solid_background_color) { return; } - image->detail->solid_background_color = solid_background_color; + image->details->solid_background_color = solid_background_color; gtk_widget_queue_draw (GTK_WIDGET (image)); } @@ -927,17 +939,17 @@ nautilus_image_get_solid_background_color (const NautilusImage *image) { g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), 0); - return image->detail->solid_background_color; + return image->details->solid_background_color; } /** * nautilus_image_new_solid: * * @pixbuf: A GdkPixbuf or NULL. - * @xalign: Horizontal alignment. - * @yalign: Vertical alignment. - * @xpadding: Horizontal padding. - * @ypadding: Vertical padding. + * @x_alignment: Horizontal alignment. + * @y_alignment: Vertical alignment. + * @x_padding: Horizontal padding. + * @y_padding: Vertical padding. * @background_color: Background color. * @tile_pixbuf: A GdkPixbuf or NULL. * @@ -948,10 +960,10 @@ nautilus_image_get_solid_background_color (const NautilusImage *image) */ GtkWidget * nautilus_image_new_solid (GdkPixbuf *pixbuf, - float xalign, - float yalign, - int xpadding, - int ypadding, + float x_alignment, + float y_alignment, + int x_padding, + int y_padding, guint32 background_color, GdkPixbuf *tile_pixbuf) { @@ -963,16 +975,36 @@ nautilus_image_new_solid (GdkPixbuf *pixbuf, nautilus_image_set_pixbuf (image, pixbuf); } - nautilus_image_set_background_mode (NAUTILUS_IMAGE (image), NAUTILUS_SMOOTH_BACKGROUND_SOLID_COLOR); - nautilus_image_set_solid_background_color (NAUTILUS_IMAGE (image), background_color); + nautilus_image_set_background_mode (image, NAUTILUS_SMOOTH_BACKGROUND_SOLID_COLOR); + nautilus_image_set_solid_background_color (image, background_color); - gtk_misc_set_padding (GTK_MISC (image), xpadding, ypadding); - gtk_misc_set_alignment (GTK_MISC (image), xalign, yalign); + gtk_misc_set_padding (GTK_MISC (image), x_padding, y_padding); + gtk_misc_set_alignment (GTK_MISC (image), x_alignment, y_alignment); if (tile_pixbuf != NULL) { - nautilus_image_set_tile_pixbuf (NAUTILUS_IMAGE (image), tile_pixbuf); + nautilus_image_set_tile_pixbuf (image, tile_pixbuf); } return GTK_WIDGET (image); } + +/** + * nautilus_image_set_never_smooth + * + * @image: A NautilusImage. + * @never_smooth: A boolean value indicating whether the image can NEVER be smooth. + * + * Force an image to never be smooth. Calls to nautilus_image_set_is_smooth () will + * thus be ignored. This is useful if you want to use a NautilusImage in a situation. + */ +void +nautilus_image_set_never_smooth (NautilusImage *image, + gboolean never_smooth) +{ + g_return_if_fail (NAUTILUS_IS_IMAGE (image)); + + image->details->never_smooth = never_smooth; + gtk_widget_queue_resize (GTK_WIDGET (image)); +} + diff --git a/libnautilus-extensions/nautilus-image.h b/libnautilus-extensions/nautilus-image.h index 05ce361c0..c5ffca43c 100644 --- a/libnautilus-extensions/nautilus-image.h +++ b/libnautilus-extensions/nautilus-image.h @@ -41,7 +41,7 @@ BEGIN_GNOME_DECLS typedef struct _NautilusImage NautilusImage; typedef struct _NautilusImageClass NautilusImageClass; -typedef struct _NautilusImageDetail NautilusImageDetail; +typedef struct _NautilusImageDetails NautilusImageDetails; struct _NautilusImage { @@ -49,7 +49,7 @@ struct _NautilusImage GtkMisc misc; /* Private things */ - NautilusImageDetail *detail; + NautilusImageDetails *details; }; struct _NautilusImageClass @@ -106,6 +106,8 @@ NautilusSmoothBackgroundMode nautilus_image_get_background_mode (cons void nautilus_image_set_solid_background_color (NautilusImage *image, guint32 solid_background_color); guint32 nautilus_image_get_solid_background_color (const NautilusImage *image); +void nautilus_image_set_never_smooth (NautilusImage *image, + gboolean never_smooth); END_GNOME_DECLS diff --git a/libnautilus-extensions/nautilus-label.c b/libnautilus-extensions/nautilus-label.c index 24cc443c8..c703b691d 100644 --- a/libnautilus-extensions/nautilus-label.c +++ b/libnautilus-extensions/nautilus-label.c @@ -88,7 +88,7 @@ typedef enum static guint label_signals[LAST_SIGNAL] = { 0 }; /* Detail member struct */ -struct _NautilusLabelDetail +struct _NautilusLabelDetails { gboolean is_smooth; @@ -126,6 +126,7 @@ struct _NautilusLabelDetail guint32 solid_background_color; GdkPixbuf *solid_cache_pixbuf; + gboolean never_smooth; }; /* GtkObjectClass methods */ @@ -166,6 +167,7 @@ static void label_draw_text_to_pixbuf (NautilusLabel static guint label_get_default_line_wrap_width (const NautilusLabel *label); static void label_solid_cache_pixbuf_clear (NautilusLabel *label); static gboolean label_can_cache_contents (const NautilusLabel *label); +static gboolean label_is_smooth (const NautilusLabel *label); NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusLabel, nautilus_label, GTK_TYPE_LABEL) @@ -294,21 +296,21 @@ nautilus_label_initialize (NautilusLabel *label) GTK_WIDGET_UNSET_FLAGS (label, GTK_CAN_FOCUS); GTK_WIDGET_SET_FLAGS (label, GTK_NO_WINDOW); - label->detail = g_new0 (NautilusLabelDetail, 1); + label->details = g_new0 (NautilusLabelDetails, 1); - label->detail->text_opacity = NAUTILUS_OPACITY_FULLY_OPAQUE; - label->detail->smooth_font = nautilus_scalable_font_get_default_font (); - label->detail->smooth_font_size = DEFAULT_FONT_SIZE; - label->detail->smooth_text_color = NAUTILUS_RGBA_COLOR_PACK (0, 0, 0, 255); - label->detail->smooth_drop_shadow_color = NAUTILUS_RGBA_COLOR_PACK (255, 255, 255, 255); - label->detail->smooth_line_wrap_width = label_get_default_line_wrap_width (label); + label->details->text_opacity = NAUTILUS_OPACITY_FULLY_OPAQUE; + label->details->smooth_font = nautilus_scalable_font_get_default_font (); + label->details->smooth_font_size = DEFAULT_FONT_SIZE; + label->details->smooth_text_color = NAUTILUS_RGBA_COLOR_PACK (0, 0, 0, 255); + label->details->smooth_drop_shadow_color = NAUTILUS_RGBA_COLOR_PACK (255, 255, 255, 255); + label->details->smooth_line_wrap_width = label_get_default_line_wrap_width (label); - label->detail->tile_opacity = NAUTILUS_OPACITY_FULLY_OPAQUE; - label->detail->tile_width = NAUTILUS_SMOOTH_TILE_EXTENT_FULL; - label->detail->tile_height = NAUTILUS_SMOOTH_TILE_EXTENT_FULL; - label->detail->tile_mode_vertical = NAUTILUS_SMOOTH_TILE_SELF; - label->detail->tile_mode_horizontal = NAUTILUS_SMOOTH_TILE_SELF; - label->detail->background_mode = NAUTILUS_SMOOTH_BACKGROUND_GTK; + label->details->tile_opacity = NAUTILUS_OPACITY_FULLY_OPAQUE; + label->details->tile_width = NAUTILUS_SMOOTH_TILE_EXTENT_FULL; + label->details->tile_height = NAUTILUS_SMOOTH_TILE_EXTENT_FULL; + label->details->tile_mode_vertical = NAUTILUS_SMOOTH_TILE_SELF; + label->details->tile_mode_horizontal = NAUTILUS_SMOOTH_TILE_SELF; + label->details->background_mode = NAUTILUS_SMOOTH_BACKGROUND_GTK; nautilus_smooth_widget_register (GTK_WIDGET (label)); } @@ -323,13 +325,13 @@ nautilus_label_destroy (GtkObject *object) label = NAUTILUS_LABEL (object); - nautilus_gdk_pixbuf_unref_if_not_null (label->detail->tile_pixbuf); - label->detail->tile_pixbuf = NULL; + nautilus_gdk_pixbuf_unref_if_not_null (label->details->tile_pixbuf); + label->details->tile_pixbuf = NULL; label_solid_cache_pixbuf_clear (label); label_line_geometries_clear (label); - g_free (label->detail); + g_free (label->details); /* Chain destroy */ NAUTILUS_CALL_PARENT_CLASS (GTK_OBJECT_CLASS, destroy, (object)); @@ -533,7 +535,7 @@ nautilus_label_size_request (GtkWidget *widget, label = NAUTILUS_LABEL (widget); - if (!label->detail->is_smooth) { + if (!label_is_smooth (label)) { NAUTILUS_CALL_PARENT_CLASS (GTK_WIDGET_CLASS, size_request, (widget, requisition)); return; } @@ -544,8 +546,8 @@ nautilus_label_size_request (GtkWidget *widget, preferred_frame = nautilus_smooth_widget_get_preferred_frame (widget, &text_frame, &tile_frame, - label->detail->tile_width, - label->detail->tile_height); + label->details->tile_width, + label->details->tile_height); requisition->width = preferred_frame.x1; requisition->height = preferred_frame.y1; } @@ -610,25 +612,25 @@ label_composite_pixbuf_callback (GtkWidget *widget, /* Optimize the case where the background is solid */ if (label_can_cache_contents (label)) { - if (label->detail->solid_cache_pixbuf == NULL) { - label->detail->solid_cache_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + if (label->details->solid_cache_pixbuf == NULL) { + label->details->solid_cache_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, text_frame.x1, text_frame.y1); - nautilus_gdk_pixbuf_fill_rectangle_with_color (label->detail->solid_cache_pixbuf, + nautilus_gdk_pixbuf_fill_rectangle_with_color (label->details->solid_cache_pixbuf, NULL, - label->detail->solid_background_color); + label->details->solid_background_color); label_draw_text_to_pixbuf (label, - label->detail->solid_cache_pixbuf, + label->details->solid_cache_pixbuf, &text_frame, 0, 0); } - nautilus_gdk_pixbuf_draw_to_pixbuf (label->detail->solid_cache_pixbuf, + nautilus_gdk_pixbuf_draw_to_pixbuf (label->details->solid_cache_pixbuf, destination_pixbuf, source_x, source_y, @@ -722,12 +724,12 @@ nautilus_label_expose_event (GtkWidget *widget, widget_bounds = nautilus_irect_gtk_widget_get_bounds (widget); smooth_text_bounds = label_get_text_bounds (label); tile_bounds = nautilus_smooth_widget_get_tile_bounds (widget, - label->detail->tile_pixbuf, - label->detail->tile_width, - label->detail->tile_height); + label->details->tile_pixbuf, + label->details->tile_width, + label->details->tile_height); /* Check for the dumb case when theres nothing to do */ - if (nautilus_strlen (label_peek_text (label)) == 0 && label->detail->tile_pixbuf == NULL) { + if (nautilus_strlen (label_peek_text (label)) == 0 && label->details->tile_pixbuf == NULL) { return TRUE; } @@ -735,20 +737,21 @@ nautilus_label_expose_event (GtkWidget *widget, dirty_area = nautilus_irect_assign_gdk_rectangle (&event->area); screen_dirty_area = nautilus_irect_gdk_window_clip_dirty_area_to_screen (event->window, &dirty_area); + /* Make sure the area is screen visible before painting */ if (!art_irect_empty (&screen_dirty_area)) { nautilus_smooth_widget_paint (widget, widget->style->white_gc, - label->detail->is_smooth, - label->detail->background_mode, - label->detail->solid_background_color, - label->detail->tile_pixbuf, + label_is_smooth (label), + label->details->background_mode, + label->details->solid_background_color, + label->details->tile_pixbuf, &tile_bounds, - label->detail->tile_opacity, - label->detail->tile_mode_vertical, - label->detail->tile_mode_horizontal, - label->detail->is_smooth ? &smooth_text_bounds : &widget_bounds, - label->detail->text_opacity, + label->details->tile_opacity, + label->details->tile_mode_vertical, + label->details->tile_mode_horizontal, + label_is_smooth (label) ? &smooth_text_bounds : &widget_bounds, + label->details->text_opacity, &screen_dirty_area, label_paint_pixbuf_callback, label_composite_pixbuf_callback, @@ -792,16 +795,16 @@ label_draw_text_to_pixbuf (NautilusLabel *label, if (nautilus_label_get_wrap (label)) { int i; - for (i = 0; i < label->detail->num_text_lines; i++) { - const NautilusTextLayout *text_layout = label->detail->text_layouts[i]; + for (i = 0; i < label->details->num_text_lines; i++) { + const NautilusTextLayout *text_layout = label->details->text_layouts[i]; - if (label->detail->smooth_drop_shadow_offset > 0) { + if (label->details->smooth_drop_shadow_offset > 0) { nautilus_text_layout_paint (text_layout, pixbuf, - x + label->detail->smooth_drop_shadow_offset, - y + label->detail->smooth_drop_shadow_offset, + x + label->details->smooth_drop_shadow_offset, + y + label->details->smooth_drop_shadow_offset, nautilus_label_get_text_justify (label), - label->detail->smooth_drop_shadow_color, + label->details->smooth_drop_shadow_color, FALSE); } @@ -810,7 +813,7 @@ label_draw_text_to_pixbuf (NautilusLabel *label, x, y, nautilus_label_get_text_justify (label), - label->detail->smooth_text_color, + label->details->smooth_text_color, FALSE); y += text_layout->height; @@ -818,43 +821,43 @@ label_draw_text_to_pixbuf (NautilusLabel *label, } /* No line wrapping */ else { - if (label->detail->smooth_drop_shadow_offset > 0) { + if (label->details->smooth_drop_shadow_offset > 0) { nautilus_scalable_font_draw_text_lines_with_dimensions ( - label->detail->smooth_font, + label->details->smooth_font, pixbuf, - x + label->detail->smooth_drop_shadow_offset, - x + label->detail->smooth_drop_shadow_offset, + x + label->details->smooth_drop_shadow_offset, + x + label->details->smooth_drop_shadow_offset, destination_area, - label->detail->smooth_font_size, - label->detail->smooth_font_size, + label->details->smooth_font_size, + label->details->smooth_font_size, label_peek_text (label), - label->detail->num_text_lines, - label->detail->text_line_widths, - label->detail->text_line_heights, + label->details->num_text_lines, + label->details->text_line_widths, + label->details->text_line_heights, nautilus_label_get_text_justify (label), LINE_OFFSET, label_get_empty_line_height (label), - label->detail->smooth_drop_shadow_color, - label->detail->text_opacity); + label->details->smooth_drop_shadow_color, + label->details->text_opacity); } nautilus_scalable_font_draw_text_lines_with_dimensions ( - label->detail->smooth_font, + label->details->smooth_font, pixbuf, x, y, destination_area, - label->detail->smooth_font_size, - label->detail->smooth_font_size, + label->details->smooth_font_size, + label->details->smooth_font_size, label_peek_text (label), - label->detail->num_text_lines, - label->detail->text_line_widths, - label->detail->text_line_heights, + label->details->num_text_lines, + label->details->text_line_widths, + label->details->text_line_heights, nautilus_label_get_text_justify (label), LINE_OFFSET, label_get_empty_line_height (label), - label->detail->smooth_text_color, - label->detail->text_opacity); + label->details->smooth_text_color, + label->details->text_opacity); } } @@ -866,9 +869,9 @@ label_get_default_line_wrap_width (const NautilusLabel *label) g_return_val_if_fail (NAUTILUS_IS_LABEL (label), 0); - nautilus_scalable_font_measure_text (label->detail->smooth_font, - label->detail->smooth_font_size, - label->detail->smooth_font_size, + nautilus_scalable_font_measure_text (label->details->smooth_font, + label->details->smooth_font_size, + label->details->smooth_font_size, DEFAULT_LINE_WRAP_WIDTH_TEXT, strlen (DEFAULT_LINE_WRAP_WIDTH_TEXT), &width, @@ -886,13 +889,13 @@ label_get_text_frame (const NautilusLabel *label) text_frame = NAUTILUS_ART_IRECT_EMPTY; - if (label->detail->num_text_lines > 0) { + if (label->details->num_text_lines > 0) { text_frame.x1 = - label->detail->max_text_line_width - + label->detail->smooth_drop_shadow_offset; + label->details->max_text_line_width + + label->details->smooth_drop_shadow_offset; text_frame.y1 = label_get_total_text_and_line_offset_height (label) - + label->detail->smooth_drop_shadow_offset; + + label->details->smooth_drop_shadow_offset; } return text_frame; @@ -919,9 +922,7 @@ label_get_text_bounds (const NautilusLabel *label) text_frame.x1, text_frame.y1, GTK_MISC (label)->xalign, - GTK_MISC (label)->yalign, - GTK_MISC (label)->xpad, - GTK_MISC (label)->ypad); + GTK_MISC (label)->yalign); return text_bounds; @@ -934,14 +935,14 @@ label_get_tile_frame (const NautilusLabel *label) g_return_val_if_fail (NAUTILUS_IS_LABEL (label), NAUTILUS_ART_IRECT_EMPTY); - if (!label->detail->tile_pixbuf) { + if (!label->details->tile_pixbuf) { return NAUTILUS_ART_IRECT_EMPTY; } tile_frame.x0 = 0; tile_frame.y0 = 0; - tile_frame.x1 = gdk_pixbuf_get_width (label->detail->tile_pixbuf); - tile_frame.y1 = gdk_pixbuf_get_height (label->detail->tile_pixbuf); + tile_frame.x1 = gdk_pixbuf_get_width (label->details->tile_pixbuf); + tile_frame.y1 = gdk_pixbuf_get_height (label->details->tile_pixbuf); return tile_frame; } @@ -951,8 +952,8 @@ label_solid_cache_pixbuf_clear (NautilusLabel *label) { g_return_if_fail (NAUTILUS_IS_LABEL (label)); - nautilus_gdk_pixbuf_unref_if_not_null (label->detail->solid_cache_pixbuf); - label->detail->solid_cache_pixbuf = NULL; + nautilus_gdk_pixbuf_unref_if_not_null (label->details->solid_cache_pixbuf); + label->details->solid_cache_pixbuf = NULL; } static gboolean @@ -960,8 +961,8 @@ label_can_cache_contents (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), FALSE); - return (label->detail->background_mode == NAUTILUS_SMOOTH_BACKGROUND_SOLID_COLOR) - && !label->detail->tile_pixbuf; + return (label->details->background_mode == NAUTILUS_SMOOTH_BACKGROUND_SOLID_COLOR) + && !label->details->tile_pixbuf; } const char * @@ -979,7 +980,7 @@ label_get_empty_line_height (const NautilusLabel *label) /* If we wanted to crunch lines together, we could add a divider * here. For now we just use the font size for empty lines. */ - return label->detail->smooth_font_size; + return label->details->smooth_font_size; } static guint @@ -989,10 +990,10 @@ label_get_total_text_and_line_offset_height (const NautilusLabel *label) g_return_val_if_fail (NAUTILUS_IS_LABEL (label), 0); - total_height = label->detail->total_text_line_height; + total_height = label->details->total_text_line_height; - if (label->detail->num_text_lines > 1) { - total_height += ((label->detail->num_text_lines - 1) * LINE_OFFSET); + if (label->details->num_text_lines > 1) { + total_height += ((label->details->num_text_lines - 1) * LINE_OFFSET); } return total_height; @@ -1003,27 +1004,27 @@ label_line_geometries_clear (NautilusLabel *label) { g_return_if_fail (NAUTILUS_IS_LABEL (label)); - g_free (label->detail->text_line_widths); - g_free (label->detail->text_line_heights); - label->detail->text_line_widths = NULL; - label->detail->text_line_heights = NULL; + g_free (label->details->text_line_widths); + g_free (label->details->text_line_heights); + label->details->text_line_widths = NULL; + label->details->text_line_heights = NULL; - if (label->detail->text_layouts != NULL) { + if (label->details->text_layouts != NULL) { int i; - for (i = 0; i < label->detail->num_text_lines; i++) { - g_assert (label->detail->text_layouts[i] != NULL); - nautilus_text_layout_free (label->detail->text_layouts[i]); + for (i = 0; i < label->details->num_text_lines; i++) { + g_assert (label->details->text_layouts[i] != NULL); + nautilus_text_layout_free (label->details->text_layouts[i]); } - g_free (label->detail->text_layouts); - label->detail->text_layouts = NULL; + g_free (label->details->text_layouts); + label->details->text_layouts = NULL; } - label->detail->num_text_lines = 0; + label->details->num_text_lines = 0; - label->detail->max_text_line_width = 0; - label->detail->total_text_line_height = 0; + label->details->max_text_line_width = 0; + label->details->total_text_line_height = 0; } static void @@ -1042,38 +1043,38 @@ label_line_geometries_recompute (NautilusLabel *label) return; } - label->detail->num_text_lines = nautilus_str_count_characters (text, '\n') + 1; + label->details->num_text_lines = nautilus_str_count_characters (text, '\n') + 1; /* Line wrapping */ if (nautilus_label_get_wrap (label)) { char **pieces; int i; - label->detail->text_layouts = g_new (NautilusTextLayout *, label->detail->num_text_lines); + label->details->text_layouts = g_new (NautilusTextLayout *, label->details->num_text_lines); pieces = g_strsplit (text, "\n", 0); for (i = 0; pieces[i] != NULL; i++) { char *text_piece = pieces[i]; - g_assert (i < label->detail->num_text_lines); + g_assert (i < label->details->num_text_lines); /* Make empty lines appear. A single '\n' for example. */ if (text_piece[0] == '\0') { text_piece = " "; } - label->detail->text_layouts[i] = nautilus_text_layout_new (label->detail->smooth_font, - label->detail->smooth_font_size, + label->details->text_layouts[i] = nautilus_text_layout_new (label->details->smooth_font, + label->details->smooth_font_size, text_piece, LINE_WRAP_SEPARATORS, - label->detail->smooth_line_wrap_width, + label->details->smooth_line_wrap_width, TRUE); - label->detail->total_text_line_height += label->detail->text_layouts[i]->height; + label->details->total_text_line_height += label->details->text_layouts[i]->height; - if (label->detail->text_layouts[i]->width > label->detail->max_text_line_width) { - label->detail->max_text_line_width = label->detail->text_layouts[i]->width; + if (label->details->text_layouts[i]->width > label->details->max_text_line_width) { + label->details->max_text_line_width = label->details->text_layouts[i]->width; } } @@ -1081,22 +1082,30 @@ label_line_geometries_recompute (NautilusLabel *label) } /* No line wrapping */ else { - label->detail->text_line_widths = g_new (guint, label->detail->num_text_lines); - label->detail->text_line_heights = g_new (guint, label->detail->num_text_lines); + label->details->text_line_widths = g_new (guint, label->details->num_text_lines); + label->details->text_line_heights = g_new (guint, label->details->num_text_lines); - nautilus_scalable_font_measure_text_lines (label->detail->smooth_font, - label->detail->smooth_font_size, - label->detail->smooth_font_size, + nautilus_scalable_font_measure_text_lines (label->details->smooth_font, + label->details->smooth_font_size, + label->details->smooth_font_size, text, - label->detail->num_text_lines, + label->details->num_text_lines, label_get_empty_line_height (label), - label->detail->text_line_widths, - label->detail->text_line_heights, - &label->detail->max_text_line_width, - &label->detail->total_text_line_height); + label->details->text_line_widths, + label->details->text_line_heights, + &label->details->max_text_line_width, + &label->details->total_text_line_height); } } +gboolean +label_is_smooth (const NautilusLabel *label) +{ + g_return_val_if_fail (NAUTILUS_IS_LABEL (label), FALSE); + + return !label->details->never_smooth && label->details->is_smooth; +} + /* Public NautilusLabel methods */ GtkWidget * nautilus_label_new (const char *text) @@ -1117,19 +1126,19 @@ nautilus_label_set_smooth_font (NautilusLabel *label, g_return_if_fail (NAUTILUS_IS_LABEL (label)); g_return_if_fail (NAUTILUS_IS_SCALABLE_FONT (smooth_font)); - if (label->detail->smooth_font == smooth_font) { + if (label->details->smooth_font == smooth_font) { return; } - if (label->detail->smooth_font != NULL) { - gtk_object_unref (GTK_OBJECT (label->detail->smooth_font)); + if (label->details->smooth_font != NULL) { + gtk_object_unref (GTK_OBJECT (label->details->smooth_font)); } gtk_object_ref (GTK_OBJECT (smooth_font)); - label->detail->smooth_font = smooth_font; + label->details->smooth_font = smooth_font; /* Update the line wrap width */ - label->detail->smooth_line_wrap_width = label_get_default_line_wrap_width (label); + label->details->smooth_line_wrap_width = label_get_default_line_wrap_width (label); label_line_geometries_recompute (label); @@ -1141,11 +1150,11 @@ nautilus_label_get_smooth_font (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), NULL); - if (label->detail->smooth_font != NULL) { - gtk_object_ref (GTK_OBJECT (label->detail->smooth_font)); + if (label->details->smooth_font != NULL) { + gtk_object_ref (GTK_OBJECT (label->details->smooth_font)); } - return label->detail->smooth_font; + return label->details->smooth_font; } void @@ -1155,14 +1164,14 @@ nautilus_label_set_smooth_font_size (NautilusLabel *label, g_return_if_fail (NAUTILUS_IS_LABEL (label)); g_return_if_fail (smooth_font_size > MIN_SMOOTH_FONT_SIZE); - if (label->detail->smooth_font_size == smooth_font_size) { + if (label->details->smooth_font_size == smooth_font_size) { return; } - label->detail->smooth_font_size = smooth_font_size; + label->details->smooth_font_size = smooth_font_size; /* Update the line wrap width */ - label->detail->smooth_line_wrap_width = label_get_default_line_wrap_width (label); + label->details->smooth_line_wrap_width = label_get_default_line_wrap_width (label); label_line_geometries_recompute (label); @@ -1174,7 +1183,7 @@ nautilus_label_get_smooth_font_size (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), 0); - return label->detail->smooth_font_size; + return label->details->smooth_font_size; } /* This function is an ugly hack. The issue is that we want @@ -1213,11 +1222,15 @@ nautilus_label_set_is_smooth (NautilusLabel *label, { g_return_if_fail (NAUTILUS_IS_LABEL (label)); - if (label->detail->is_smooth == is_smooth) { + if (label->details->never_smooth) { return; } - label->detail->is_smooth = is_smooth; + if (label->details->is_smooth == is_smooth) { + return; + } + + label->details->is_smooth = is_smooth; label_line_geometries_recompute (label); @@ -1237,7 +1250,7 @@ nautilus_label_get_is_smooth (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), FALSE); - return label->detail->is_smooth; + return label_is_smooth (label); } /** @@ -1255,11 +1268,11 @@ nautilus_label_set_tile_pixbuf (NautilusLabel *label, { g_return_if_fail (NAUTILUS_IS_LABEL (label)); - if (pixbuf != label->detail->tile_pixbuf) { - nautilus_gdk_pixbuf_unref_if_not_null (label->detail->tile_pixbuf); + if (pixbuf != label->details->tile_pixbuf) { + nautilus_gdk_pixbuf_unref_if_not_null (label->details->tile_pixbuf); nautilus_gdk_pixbuf_ref_if_not_null (pixbuf); - label->detail->tile_pixbuf = pixbuf; + label->details->tile_pixbuf = pixbuf; gtk_widget_queue_resize (GTK_WIDGET (label)); } @@ -1278,9 +1291,9 @@ nautilus_label_get_tile_pixbuf (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), NULL); - nautilus_gdk_pixbuf_ref_if_not_null (label->detail->tile_pixbuf); + nautilus_gdk_pixbuf_ref_if_not_null (label->details->tile_pixbuf); - return label->detail->tile_pixbuf; + return label->details->tile_pixbuf; } void @@ -1291,7 +1304,7 @@ nautilus_label_set_text_opacity (NautilusLabel *label, g_return_if_fail (opacity >= NAUTILUS_OPACITY_FULLY_TRANSPARENT); g_return_if_fail (opacity <= NAUTILUS_OPACITY_FULLY_OPAQUE); - label->detail->text_opacity = opacity; + label->details->text_opacity = opacity; gtk_widget_queue_draw (GTK_WIDGET (label)); } @@ -1301,7 +1314,7 @@ nautilus_label_get_text_opacity (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), NAUTILUS_OPACITY_FULLY_OPAQUE); - return label->detail->text_opacity; + return label->details->text_opacity; } void @@ -1312,11 +1325,11 @@ nautilus_label_set_tile_opacity (NautilusLabel *label, g_return_if_fail (tile_opacity >= NAUTILUS_OPACITY_FULLY_TRANSPARENT); g_return_if_fail (tile_opacity <= NAUTILUS_OPACITY_FULLY_OPAQUE); - if (label->detail->tile_opacity == tile_opacity) { + if (label->details->tile_opacity == tile_opacity) { return; } - label->detail->tile_opacity = tile_opacity; + label->details->tile_opacity = tile_opacity; gtk_widget_queue_draw (GTK_WIDGET (label)); } @@ -1326,7 +1339,7 @@ nautilus_label_get_tile_opacity (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), NAUTILUS_OPACITY_FULLY_OPAQUE); - return label->detail->tile_opacity; + return label->details->tile_opacity; } void @@ -1336,11 +1349,11 @@ nautilus_label_set_tile_width (NautilusLabel *label, g_return_if_fail (NAUTILUS_IS_LABEL (label)); g_return_if_fail (tile_width >= NAUTILUS_SMOOTH_TILE_EXTENT_ONE_STEP); - if (label->detail->tile_width == tile_width) { + if (label->details->tile_width == tile_width) { return; } - label->detail->tile_width = tile_width; + label->details->tile_width = tile_width; gtk_widget_queue_resize (GTK_WIDGET (label)); } @@ -1357,7 +1370,7 @@ nautilus_label_get_tile_width (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), 0); - return label->detail->tile_width; + return label->details->tile_width; } void @@ -1367,11 +1380,11 @@ nautilus_label_set_tile_height (NautilusLabel *label, g_return_if_fail (NAUTILUS_IS_LABEL (label)); g_return_if_fail (tile_height >= NAUTILUS_SMOOTH_TILE_EXTENT_ONE_STEP); - if (label->detail->tile_height == tile_height) { + if (label->details->tile_height == tile_height) { return; } - label->detail->tile_height = tile_height; + label->details->tile_height = tile_height; gtk_widget_queue_resize (GTK_WIDGET (label)); } @@ -1388,7 +1401,7 @@ nautilus_label_get_tile_height (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), 0); - return label->detail->tile_height; + return label->details->tile_height; } void @@ -1399,11 +1412,11 @@ nautilus_label_set_tile_mode_vertical (NautilusLabel *label, g_return_if_fail (tile_mode_vertical >= NAUTILUS_SMOOTH_TILE_SELF); g_return_if_fail (tile_mode_vertical <= NAUTILUS_SMOOTH_TILE_ANCESTOR); - if (label->detail->tile_mode_vertical == tile_mode_vertical) { + if (label->details->tile_mode_vertical == tile_mode_vertical) { return; } - label->detail->tile_mode_vertical = tile_mode_vertical; + label->details->tile_mode_vertical = tile_mode_vertical; gtk_widget_queue_draw (GTK_WIDGET (label)); } @@ -1413,7 +1426,7 @@ nautilus_label_get_tile_mode_vertical (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), 0); - return label->detail->tile_mode_vertical; + return label->details->tile_mode_vertical; } void @@ -1424,11 +1437,11 @@ nautilus_label_set_tile_mode_horizontal (NautilusLabel *label, g_return_if_fail (tile_mode_horizontal >= NAUTILUS_SMOOTH_TILE_SELF); g_return_if_fail (tile_mode_horizontal <= NAUTILUS_SMOOTH_TILE_ANCESTOR); - if (label->detail->tile_mode_horizontal == tile_mode_horizontal) { + if (label->details->tile_mode_horizontal == tile_mode_horizontal) { return; } - label->detail->tile_mode_horizontal = tile_mode_horizontal; + label->details->tile_mode_horizontal = tile_mode_horizontal; gtk_widget_queue_draw (GTK_WIDGET (label)); } @@ -1438,7 +1451,7 @@ nautilus_label_get_tile_mode_horizontal (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), 0); - return label->detail->tile_mode_horizontal; + return label->details->tile_mode_horizontal; } void @@ -1466,11 +1479,11 @@ nautilus_label_set_background_mode (NautilusLabel *label, g_return_if_fail (background_mode >= NAUTILUS_SMOOTH_BACKGROUND_GTK); g_return_if_fail (background_mode <= NAUTILUS_SMOOTH_BACKGROUND_SOLID_COLOR); - if (label->detail->background_mode == background_mode) { + if (label->details->background_mode == background_mode) { return; } - label->detail->background_mode = background_mode; + label->details->background_mode = background_mode; gtk_widget_queue_draw (GTK_WIDGET (label)); } @@ -1480,7 +1493,7 @@ nautilus_label_get_background_mode (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), 0); - return label->detail->background_mode; + return label->details->background_mode; } void @@ -1489,11 +1502,11 @@ nautilus_label_set_solid_background_color (NautilusLabel *label, { g_return_if_fail (NAUTILUS_IS_LABEL (label)); - if (label->detail->solid_background_color == solid_background_color) { + if (label->details->solid_background_color == solid_background_color) { return; } - label->detail->solid_background_color = solid_background_color; + label->details->solid_background_color = solid_background_color; gtk_widget_queue_draw (GTK_WIDGET (label)); } @@ -1503,7 +1516,7 @@ nautilus_label_get_solid_background_color (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), 0); - return label->detail->solid_background_color; + return label->details->solid_background_color; } /** @@ -1521,11 +1534,11 @@ nautilus_label_set_smooth_line_wrap_width (NautilusLabel *label, { g_return_if_fail (NAUTILUS_IS_LABEL (label)); - if (label->detail->smooth_line_wrap_width == line_wrap_width) { + if (label->details->smooth_line_wrap_width == line_wrap_width) { return; } - label->detail->smooth_line_wrap_width = line_wrap_width; + label->details->smooth_line_wrap_width = line_wrap_width; label_line_geometries_recompute (label); @@ -1545,7 +1558,7 @@ nautilus_label_get_smooth_line_wrap_width (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), FALSE); - return label->detail->smooth_line_wrap_width; + return label->details->smooth_line_wrap_width; } void @@ -1556,11 +1569,11 @@ nautilus_label_set_text_color (NautilusLabel *label, g_return_if_fail (NAUTILUS_IS_LABEL (label)); - if (label->detail->smooth_text_color == text_color) { + if (label->details->smooth_text_color == text_color) { return; } - label->detail->smooth_text_color = text_color; + label->details->smooth_text_color = text_color; color_spec = nautilus_gdk_rgb_to_color_spec (text_color); @@ -1576,7 +1589,7 @@ nautilus_label_get_text_color (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), 0); - return label->detail->smooth_text_color; + return label->details->smooth_text_color; } /** @@ -1595,11 +1608,11 @@ nautilus_label_set_smooth_drop_shadow_offset (NautilusLabel *label, { g_return_if_fail (NAUTILUS_IS_LABEL (label)); - if (label->detail->smooth_drop_shadow_offset == drop_shadow_offset) { + if (label->details->smooth_drop_shadow_offset == drop_shadow_offset) { return; } - label->detail->smooth_drop_shadow_offset = drop_shadow_offset; + label->details->smooth_drop_shadow_offset = drop_shadow_offset; gtk_widget_queue_resize (GTK_WIDGET (label)); } @@ -1616,7 +1629,7 @@ nautilus_label_get_smooth_drop_shadow_offset (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), 0); - return label->detail->smooth_drop_shadow_offset; + return label->details->smooth_drop_shadow_offset; } /** @@ -1633,11 +1646,11 @@ nautilus_label_set_smooth_drop_shadow_color (NautilusLabel *label, { g_return_if_fail (NAUTILUS_IS_LABEL (label)); - if (label->detail->smooth_drop_shadow_color == drop_shadow_color) { + if (label->details->smooth_drop_shadow_color == drop_shadow_color) { return; } - label->detail->smooth_drop_shadow_color = drop_shadow_color; + label->details->smooth_drop_shadow_color = drop_shadow_color; gtk_widget_queue_draw (GTK_WIDGET (label)); } @@ -1654,7 +1667,7 @@ nautilus_label_get_smooth_drop_shadow_color (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), 0); - return label->detail->smooth_drop_shadow_color; + return label->details->smooth_drop_shadow_color; } void @@ -1761,15 +1774,15 @@ nautilus_label_get_wrap (const NautilusLabel *label) * nautilus_label_new_solid: * * @text: Text or NULL - * @drop_shadow_offset: Drop shadow offset - * @drop_shadow_color: Drop shadow color - * @text_color: Text color - * @xalign: Horizontal alignment. - * @yalign: Vertical alignment. - * @xpadding: Amount to pad label in the x direction. - * @ypadding: Amount to pad label in the y direction. + * @drop_shadow_offset: Drop shadow offset. + * @drop_shadow_color: Drop shadow color. + * @text_color: Text color. + * @x_alignment: Horizontal alignment. + * @y_alignment: Vertical alignment. + * @x_padding: Amount to pad label in the x direction. + * @y_padding: Amount to pad label in the y direction. * @background_color: Background color. - * @tile_pixbuf: Pixbuf to use for tile or NULL + * @tile_pixbuf: Pixbuf to use for tile or NULL. * * Create a label with a solid background. * @@ -1780,10 +1793,10 @@ nautilus_label_new_solid (const char *text, guint drop_shadow_offset, guint32 drop_shadow_color, guint32 text_color, - float xalign, - float yalign, - int xpadding, - int ypadding, + float x_alignment, + float y_alignment, + int x_padding, + int y_padding, guint32 background_color, GdkPixbuf *tile_pixbuf) { @@ -1797,8 +1810,8 @@ nautilus_label_new_solid (const char *text, nautilus_label_set_text_color (label, text_color); nautilus_label_set_solid_background_color (NAUTILUS_LABEL (label), background_color); - gtk_misc_set_padding (GTK_MISC (label), xpadding, ypadding); - gtk_misc_set_alignment (GTK_MISC (label), xalign, yalign); + gtk_misc_set_padding (GTK_MISC (label), x_padding, y_padding); + gtk_misc_set_alignment (GTK_MISC (label), x_alignment, y_alignment); if (tile_pixbuf != NULL) { nautilus_label_set_tile_pixbuf (NAUTILUS_LABEL (label), tile_pixbuf); @@ -1822,7 +1835,7 @@ nautilus_label_make_bold (NautilusLabel *label) nautilus_gtk_label_make_bold (GTK_LABEL (label)); - bold_font = nautilus_scalable_font_make_bold (label->detail->smooth_font); + bold_font = nautilus_scalable_font_make_bold (label->details->smooth_font); if (bold_font != NULL) { nautilus_label_set_smooth_font (label, bold_font); @@ -1846,7 +1859,7 @@ nautilus_label_make_larger (NautilusLabel *label, { g_return_if_fail (NAUTILUS_IS_LABEL (label)); - label->detail->smooth_font_size += num_steps; + label->details->smooth_font_size += num_steps; nautilus_gtk_label_make_larger (GTK_LABEL (label), num_steps); @@ -1867,7 +1880,7 @@ nautilus_label_make_smaller (NautilusLabel *label, { g_return_if_fail (NAUTILUS_IS_LABEL (label)); - label->detail->smooth_font_size -= num_steps; + label->details->smooth_font_size -= num_steps; nautilus_gtk_label_make_smaller (GTK_LABEL (label), num_steps); @@ -1875,3 +1888,36 @@ nautilus_label_make_smaller (NautilusLabel *label, gtk_widget_queue_resize (GTK_WIDGET (label)); } + +/** + * nautilus_label_set_never_smooth + * + * @label: A NautilusLabel. + * @never_smooth: A boolean value indicating whether the label can NEVER be smooth. + * + * Force an label to never be smooth. Calls to nautilus_label_set_is_smooth () will + * thus be ignored. This is useful if you want to use a NautilusLabel in a situation + * wherre smoothness does not make sense - for example, in a dialog with other "normal" + * GtkLabel widgets for consistency. + */ +void +nautilus_label_set_never_smooth (NautilusLabel *label, + gboolean never_smooth) +{ + g_return_if_fail (NAUTILUS_IS_LABEL (label)); + + label->details->never_smooth = never_smooth; + + label_line_geometries_recompute (label); + + /* Force GtkLabel to flush its cached requisition dimensions. + * GtkLabel caches its requisition for efficiency. We need this + * dimensions to be flushed when our is_smooth attribute changes. + * The reason is that the geometry of the widget is dependent on + * whether it is_smooth or not. + */ + label_force_cached_requisition_flush (label); + + gtk_widget_queue_resize (GTK_WIDGET (label)); +} + diff --git a/libnautilus-extensions/nautilus-label.h b/libnautilus-extensions/nautilus-label.h index a435caf06..13c5d7fbb 100644 --- a/libnautilus-extensions/nautilus-label.h +++ b/libnautilus-extensions/nautilus-label.h @@ -39,7 +39,7 @@ BEGIN_GNOME_DECLS typedef struct _NautilusLabel NautilusLabel; typedef struct _NautilusLabelClass NautilusLabelClass; -typedef struct _NautilusLabelDetail NautilusLabelDetail; +typedef struct _NautilusLabelDetails NautilusLabelDetails; struct _NautilusLabel { @@ -47,7 +47,7 @@ struct _NautilusLabel GtkLabel gtk_label; /* Private things */ - NautilusLabelDetail *detail; + NautilusLabelDetails *details; }; struct _NautilusLabelClass @@ -134,6 +134,8 @@ NautilusSmoothTileMode nautilus_label_get_tile_mode_vertical (cons void nautilus_label_set_tile_mode_horizontal (NautilusLabel *label, NautilusSmoothTileMode horizontal_tile_mode); NautilusSmoothTileMode nautilus_label_get_tile_mode_horizontal (const NautilusLabel *label); +void nautilus_label_set_never_smooth (NautilusLabel *label, + gboolean never_smooth); END_GNOME_DECLS diff --git a/libnautilus-extensions/nautilus-labeled-image.c b/libnautilus-extensions/nautilus-labeled-image.c new file mode 100644 index 000000000..5a56fceaf --- /dev/null +++ b/libnautilus-extensions/nautilus-labeled-image.c @@ -0,0 +1,1845 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ + +/* nautilus-image.c - A labeled image. + + Copyright (C) 2000 Eazel, Inc. + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Authors: Ramiro Estrugo <ramiro@eazel.com> +*/ + +#include <config.h> + +#include "nautilus-labeled-image.h" + +#include "nautilus-gtk-macros.h" +#include "nautilus-gtk-extensions.h" +#include "nautilus-art-extensions.h" +#include "nautilus-art-gtk-extensions.h" +#include "nautilus-label.h" +#include "nautilus-image.h" + +#include <gtk/gtkbutton.h> +#include <gtk/gtktogglebutton.h> +#include <gtk/gtkcheckbutton.h> + +#include "nautilus-debug-drawing.h" + +#define DEFAULT_SPACING 0 +#define DEFAULT_X_PADDING 0 +#define DEFAULT_Y_PADDING 0 +#define DEFAULT_X_ALIGNMENT 0.5 +#define DEFAULT_Y_ALIGNMENT 0.5 + +/* Arguments */ +enum +{ + ARG_0, + ARG_FILL, + ARG_LABEL, + ARG_LABEL_POSITION, + ARG_PIXBUF, + ARG_SHOW_IMAGE, + ARG_SHOW_LABEL, + ARG_SPACING, + ARG_X_ALIGNMENT, + ARG_X_PADDING, + ARG_Y_ALIGNMENT, + ARG_Y_PADDING, +}; + +/* Detail member struct */ +struct _NautilusLabeledImageDetails +{ + GtkWidget *image; + GtkWidget *label; + GtkPositionType label_position; + gboolean show_label; + gboolean show_image; + guint spacing; + float x_alignment; + float y_alignment; + int x_padding; + int y_padding; + gboolean fill; +}; + +/* GtkObjectClass methods */ +static void nautilus_labeled_image_initialize_class (NautilusLabeledImageClass *labeled_image_class); +static void nautilus_labeled_image_initialize (NautilusLabeledImage *image); +static void nautilus_labeled_image_destroy (GtkObject *object); +static void nautilus_labeled_image_set_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); +static void nautilus_labeled_image_get_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); +/* GtkWidgetClass methods */ +static void nautilus_labeled_image_size_request (GtkWidget *widget, + GtkRequisition *requisition); +static int nautilus_labeled_image_expose_event (GtkWidget *widget, + GdkEventExpose *event); +static void nautilus_labeled_image_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); +static void nautilus_labeled_image_map (GtkWidget *widget); +static void nautilus_labeled_image_unmap (GtkWidget *widget); + +/* GtkContainerClass methods */ +static void nautilus_labeled_image_add (GtkContainer *container, + GtkWidget *widget); +static void nautilus_labeled_image_remove (GtkContainer *container, + GtkWidget *widget); +static void nautilus_labeled_image_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data); + +/* Private NautilusLabeledImage methods */ +static ArtIRect labeled_image_get_image_frame (const NautilusLabeledImage *labeled_image); +static ArtIRect labeled_image_get_label_frame (const NautilusLabeledImage *labeled_image); +static ArtIRect labeled_image_get_image_bounds (const NautilusLabeledImage *labeled_image); +static ArtIRect labeled_image_get_label_bounds (const NautilusLabeledImage *labeled_image); +static void labeled_image_ensure_label (NautilusLabeledImage *labeled_image); +static void labeled_image_ensure_image (NautilusLabeledImage *labeled_image); +static ArtIRect labeled_image_get_content_bounds (const NautilusLabeledImage *labeled_image); +static ArtIRect labeled_image_get_content_frame (const NautilusLabeledImage *labeled_image); +static void labeled_image_update_alignments (NautilusLabeledImage *labeled_image); +static gboolean labeled_image_show_label (const NautilusLabeledImage *labeled_image); +static gboolean labeled_image_show_image (const NautilusLabeledImage *labeled_image); + +NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusLabeledImage, nautilus_labeled_image, GTK_TYPE_CONTAINER) + +/* Class init methods */ +static void +nautilus_labeled_image_initialize_class (NautilusLabeledImageClass *labeled_image_class) +{ + GtkObjectClass *object_class = GTK_OBJECT_CLASS (labeled_image_class); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (labeled_image_class); + GtkContainerClass *container_class = GTK_CONTAINER_CLASS (labeled_image_class); + + /* GtkObjectClass */ + object_class->destroy = nautilus_labeled_image_destroy; + object_class->set_arg = nautilus_labeled_image_set_arg; + object_class->get_arg = nautilus_labeled_image_get_arg; + + /* GtkWidgetClass */ + widget_class->size_request = nautilus_labeled_image_size_request; + widget_class->size_allocate = nautilus_labeled_image_size_allocate; + widget_class->expose_event = nautilus_labeled_image_expose_event; + widget_class->map = nautilus_labeled_image_map; + widget_class->unmap = nautilus_labeled_image_unmap; + + /* GtkContainerClass */ + container_class->add = nautilus_labeled_image_add; + container_class->remove = nautilus_labeled_image_remove; + container_class->forall = nautilus_labeled_image_forall; + + /* Arguments */ + gtk_object_add_arg_type ("NautilusLabeledImage::pixbuf", + GTK_TYPE_POINTER, + GTK_ARG_READWRITE, + ARG_PIXBUF); + gtk_object_add_arg_type ("NautilusLabeledImage::label", + GTK_TYPE_STRING, + GTK_ARG_READWRITE, + ARG_LABEL); + gtk_object_add_arg_type ("NautilusLabeledImage::label_position", + GTK_TYPE_POSITION_TYPE, + GTK_ARG_READWRITE, + ARG_LABEL_POSITION); + gtk_object_add_arg_type ("NautilusLabeledImage::show_label", + GTK_TYPE_BOOL, + GTK_ARG_READWRITE, + ARG_SHOW_LABEL); + gtk_object_add_arg_type ("NautilusLabeledImage::show_image", + GTK_TYPE_BOOL, + GTK_ARG_READWRITE, + ARG_SHOW_IMAGE); + gtk_object_add_arg_type ("NautilusLabeledImage::spacing", + GTK_TYPE_UINT, + GTK_ARG_READWRITE, + ARG_SPACING); + gtk_object_add_arg_type ("NautilusLabeledImage::x_padding", + GTK_TYPE_INT, + GTK_ARG_READWRITE, + ARG_X_PADDING); + gtk_object_add_arg_type ("NautilusLabeledImage::y_padding", + GTK_TYPE_INT, + GTK_ARG_READWRITE, + ARG_Y_PADDING); + gtk_object_add_arg_type ("NautilusLabeledImage::x_alignment", + GTK_TYPE_FLOAT, + GTK_ARG_READWRITE, + ARG_X_ALIGNMENT); + gtk_object_add_arg_type ("NautilusLabeledImage::y_alignment", + GTK_TYPE_FLOAT, + GTK_ARG_READWRITE, + ARG_Y_ALIGNMENT); + gtk_object_add_arg_type ("NautilusLabeledImage::fill", + GTK_TYPE_BOOL, + GTK_ARG_READWRITE, + ARG_FILL); +} + +void +nautilus_labeled_image_initialize (NautilusLabeledImage *labeled_image) +{ + GTK_WIDGET_SET_FLAGS (labeled_image, GTK_NO_WINDOW); + + labeled_image->details = g_new0 (NautilusLabeledImageDetails, 1); + labeled_image->details->show_label = TRUE; + labeled_image->details->show_image = TRUE; + labeled_image->details->label_position = GTK_POS_BOTTOM; + labeled_image->details->spacing = DEFAULT_SPACING; + labeled_image->details->x_padding = DEFAULT_X_PADDING; + labeled_image->details->y_padding = DEFAULT_Y_PADDING; + labeled_image->details->x_alignment = DEFAULT_X_ALIGNMENT; + labeled_image->details->y_alignment = DEFAULT_Y_ALIGNMENT; + nautilus_labeled_image_set_fill (labeled_image, FALSE); +} + +/* GtkObjectClass methods */ +static void +nautilus_labeled_image_destroy (GtkObject *object) +{ + NautilusLabeledImage *labeled_image; + + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (object)); + + labeled_image = NAUTILUS_LABELED_IMAGE (object); + + g_free (labeled_image->details); + + /* Chain destroy */ + NAUTILUS_CALL_PARENT_CLASS (GTK_OBJECT_CLASS, destroy, (object)); +} + +static void +nautilus_labeled_image_set_arg (GtkObject *object, + GtkArg *arg, + guint arg_id) +{ + NautilusLabeledImage *labeled_image; + + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (object)); + + labeled_image = NAUTILUS_LABELED_IMAGE (object); + + switch (arg_id) + { + case ARG_PIXBUF: + nautilus_labeled_image_set_pixbuf (labeled_image, (GdkPixbuf *) GTK_VALUE_POINTER (*arg)); + break; + + case ARG_LABEL: + nautilus_labeled_image_set_text (labeled_image, GTK_VALUE_STRING (*arg)); + break; + + case ARG_LABEL_POSITION: + nautilus_labeled_image_set_label_position (labeled_image, GTK_VALUE_ENUM (*arg)); + break; + + case ARG_SHOW_LABEL: + nautilus_labeled_image_set_show_label (labeled_image, GTK_VALUE_BOOL (*arg)); + break; + + case ARG_SHOW_IMAGE: + nautilus_labeled_image_set_show_image (labeled_image, GTK_VALUE_BOOL (*arg)); + break; + + case ARG_SPACING: + nautilus_labeled_image_set_spacing (labeled_image, GTK_VALUE_UINT (*arg)); + break; + + case ARG_X_PADDING: + nautilus_labeled_image_set_x_padding (labeled_image, GTK_VALUE_INT (*arg)); + break; + + case ARG_Y_PADDING: + nautilus_labeled_image_set_y_padding (labeled_image, GTK_VALUE_INT (*arg)); + break; + + case ARG_X_ALIGNMENT: + nautilus_labeled_image_set_x_alignment (labeled_image, GTK_VALUE_FLOAT (*arg)); + break; + + case ARG_Y_ALIGNMENT: + nautilus_labeled_image_set_y_alignment (labeled_image, GTK_VALUE_FLOAT (*arg)); + break; + + case ARG_FILL: + nautilus_labeled_image_set_fill (labeled_image, GTK_VALUE_BOOL (*arg)); + break; + default: + g_assert_not_reached (); + } +} + +static void +nautilus_labeled_image_get_arg (GtkObject *object, + GtkArg *arg, + guint arg_id) +{ + NautilusLabeledImage *labeled_image; + + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (object)); + + labeled_image = NAUTILUS_LABELED_IMAGE (object); + + switch (arg_id) + { + case ARG_PIXBUF: + GTK_VALUE_POINTER (*arg) = nautilus_labeled_image_get_pixbuf (labeled_image); + break; + + case ARG_LABEL: + GTK_VALUE_STRING (*arg) = nautilus_labeled_image_get_text (labeled_image); + break; + + case ARG_LABEL_POSITION: + GTK_VALUE_ENUM (*arg) = nautilus_labeled_image_get_label_position (labeled_image); + break; + + case ARG_SHOW_LABEL: + GTK_VALUE_BOOL (*arg) = nautilus_labeled_image_get_show_label (labeled_image); + break; + + case ARG_SHOW_IMAGE: + GTK_VALUE_BOOL (*arg) = nautilus_labeled_image_get_show_image (labeled_image); + break; + + case ARG_SPACING: + GTK_VALUE_UINT (*arg) = nautilus_labeled_image_get_spacing (labeled_image); + break; + + case ARG_X_PADDING: + GTK_VALUE_INT (*arg) = nautilus_labeled_image_get_x_padding (labeled_image); + break; + + case ARG_Y_PADDING: + GTK_VALUE_INT (*arg) = nautilus_labeled_image_get_y_padding (labeled_image); + break; + + case ARG_X_ALIGNMENT: + GTK_VALUE_FLOAT (*arg) = nautilus_labeled_image_get_x_alignment (labeled_image); + break; + + case ARG_Y_ALIGNMENT: + GTK_VALUE_FLOAT (*arg) = nautilus_labeled_image_get_y_alignment (labeled_image); + break; + + case ARG_FILL: + GTK_VALUE_BOOL (*arg) = nautilus_labeled_image_get_fill (labeled_image); + break; + + default: + g_assert_not_reached (); + } +} + +/* GtkWidgetClass methods */ +static void +nautilus_labeled_image_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + NautilusLabeledImage *labeled_image; + ArtIRect content_frame; + + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (widget)); + g_return_if_fail (requisition != NULL); + + labeled_image = NAUTILUS_LABELED_IMAGE (widget); + + content_frame = labeled_image_get_content_frame (labeled_image); + + requisition->width = + MAX (1, content_frame.x1) + + 2 * labeled_image->details->x_padding; + + requisition->height = + MAX (1, content_frame.y1) + + 2 * labeled_image->details->y_padding; +} + +static void +nautilus_labeled_image_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + NautilusLabeledImage *labeled_image; + ArtIRect image_bounds; + ArtIRect label_bounds; + + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (widget)); + g_return_if_fail (allocation != NULL); + + labeled_image = NAUTILUS_LABELED_IMAGE (widget); + + widget->allocation = *allocation; + + label_bounds = labeled_image_get_label_bounds (labeled_image); + if (!art_irect_empty (&label_bounds)) { + GtkAllocation label_allocation; + + label_allocation.x = label_bounds.x0; + label_allocation.y = label_bounds.y0; + label_allocation.width = nautilus_art_irect_get_width (&label_bounds); + label_allocation.height = nautilus_art_irect_get_height (&label_bounds); + + gtk_widget_size_allocate (labeled_image->details->label, &label_allocation); + } + + image_bounds = labeled_image_get_image_bounds (labeled_image); + if (!art_irect_empty (&image_bounds)) { + GtkAllocation image_allocation; + + image_allocation.x = image_bounds.x0; + image_allocation.y = image_bounds.y0; + image_allocation.width = nautilus_art_irect_get_width (&image_bounds); + image_allocation.height = nautilus_art_irect_get_height (&image_bounds); + + gtk_widget_size_allocate (labeled_image->details->image, &image_allocation); + } +} + +static int +nautilus_labeled_image_expose_event (GtkWidget *widget, + GdkEventExpose *event) +{ + NautilusLabeledImage *labeled_image; + + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (widget), TRUE); + g_return_val_if_fail (GTK_WIDGET_REALIZED (widget), TRUE); + g_return_val_if_fail (event != NULL, TRUE); + + labeled_image = NAUTILUS_LABELED_IMAGE (widget); + + if (labeled_image_show_label (labeled_image)) { + GdkEventExpose label_event; + + label_event = *event; + + if (GTK_WIDGET_DRAWABLE (labeled_image->details->label) && + GTK_WIDGET_NO_WINDOW (labeled_image->details->label) && + gtk_widget_intersect (labeled_image->details->label, &event->area, &label_event.area)) { + gtk_widget_event (labeled_image->details->label, (GdkEvent *) &label_event); + } + } + + if (labeled_image_show_image (labeled_image)) { + GdkEventExpose image_event; + + image_event = *event; + + if (GTK_WIDGET_DRAWABLE (labeled_image->details->image) && + GTK_WIDGET_NO_WINDOW (labeled_image->details->image) && + gtk_widget_intersect (labeled_image->details->image, &event->area, &image_event.area)) { + gtk_widget_event (labeled_image->details->image, (GdkEvent *) &image_event); + } + } + + return FALSE; +} + +static void +nautilus_labeled_image_map (GtkWidget *widget) +{ + NautilusLabeledImage *labeled_image; + + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (widget)); + + labeled_image = NAUTILUS_LABELED_IMAGE (widget); + + GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED); + + if (labeled_image_show_label (labeled_image)) { + if (GTK_WIDGET_VISIBLE (labeled_image->details->label) && + !GTK_WIDGET_MAPPED (labeled_image->details->label)) { + gtk_widget_map (labeled_image->details->label); + } + } + + if (labeled_image_show_image (labeled_image)) { + if (GTK_WIDGET_VISIBLE (labeled_image->details->image) && + !GTK_WIDGET_MAPPED (labeled_image->details->image)) { + gtk_widget_map (labeled_image->details->image); + } + } +} + +static void +nautilus_labeled_image_unmap (GtkWidget *widget) +{ + NautilusLabeledImage *labeled_image; + + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (widget)); + + labeled_image = NAUTILUS_LABELED_IMAGE (widget); + + GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED); + + if (labeled_image->details->label != NULL) { + if (GTK_WIDGET_VISIBLE (labeled_image->details->label) && + GTK_WIDGET_MAPPED (labeled_image->details->label)) { + gtk_widget_unmap (labeled_image->details->label); + } + } + + if (labeled_image->details->image != NULL) { + if (GTK_WIDGET_VISIBLE (labeled_image->details->image) && + GTK_WIDGET_MAPPED (labeled_image->details->image)) { + gtk_widget_unmap (labeled_image->details->image); + } + } +} + +/* GtkContainerClass methods */ +static void +nautilus_labeled_image_add (GtkContainer *container, + GtkWidget *child) +{ + g_return_if_fail (container != NULL); + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (container)); + g_return_if_fail (NAUTILUS_IS_LABEL (child) || NAUTILUS_IS_IMAGE (child)); + + gtk_widget_set_parent (child, GTK_WIDGET (container)); + + if (GTK_WIDGET_REALIZED (container)) { + gtk_widget_realize (child); + } + + if (GTK_WIDGET_VISIBLE (container) && GTK_WIDGET_VISIBLE (child)) { + if (GTK_WIDGET_MAPPED (container)) { + gtk_widget_map (child); + } + + gtk_widget_queue_resize (child); + } +} + +static void +nautilus_labeled_image_remove (GtkContainer *container, + GtkWidget *child) +{ + NautilusLabeledImage *labeled_image; + gboolean child_was_visible; + + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (container)); + g_return_if_fail (NAUTILUS_IS_LABEL (child) || NAUTILUS_IS_IMAGE (child)); + + labeled_image = NAUTILUS_LABELED_IMAGE (container);; + + g_return_if_fail (child == labeled_image->details->image || child == labeled_image->details->label); + + child_was_visible = GTK_WIDGET_VISIBLE (child); + + gtk_widget_unparent (child); + + if (child_was_visible) { + gtk_widget_queue_resize (GTK_WIDGET (container)); + } + + if (labeled_image->details->image == child) { + labeled_image->details->image = NULL; + } + + if (labeled_image->details->label == child) { + labeled_image->details->label = NULL; + } +} + +static void +nautilus_labeled_image_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) +{ + NautilusLabeledImage *labeled_image; + + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (container)); + g_return_if_fail (callback != NULL); + + labeled_image = NAUTILUS_LABELED_IMAGE (container);; + + if (include_internals) { + if (labeled_image->details->image != NULL) { + (* callback) (labeled_image->details->image, callback_data); + } + + if (labeled_image->details->label != NULL) { + (* callback) (labeled_image->details->label, callback_data); + } + } +} + +static ArtIRect +labeled_image_get_image_frame (const NautilusLabeledImage *labeled_image) +{ + ArtIRect image_frame; + GtkRequisition image_requisition; + + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), NAUTILUS_ART_IRECT_EMPTY); + + if (!labeled_image_show_image (labeled_image)) { + return NAUTILUS_ART_IRECT_EMPTY; + } + + gtk_widget_size_request (labeled_image->details->image, &image_requisition); + + image_frame.x0 = 0; + image_frame.y0 = 0; + image_frame.x1 = (int) image_requisition.width; + image_frame.y1 = (int) image_requisition.height; + + return image_frame; +} + +static ArtIRect +labeled_image_get_label_frame (const NautilusLabeledImage *labeled_image) +{ + ArtIRect label_frame; + GtkRequisition label_requisition; + + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), NAUTILUS_ART_IRECT_EMPTY); + + if (!labeled_image_show_label (labeled_image)) { + return NAUTILUS_ART_IRECT_EMPTY; + } + + gtk_widget_size_request (labeled_image->details->label, &label_requisition); + + label_frame.x0 = 0; + label_frame.y0 = 0; + label_frame.x1 = (int) label_requisition.width; + label_frame.y1 = (int) label_requisition.height; + + return label_frame; +} + +static ArtIRect +labeled_image_get_image_bounds_fill (const NautilusLabeledImage *labeled_image) +{ + ArtIRect image_bounds; + ArtIRect image_frame; + ArtIRect content_bounds; + ArtIRect bounds; + + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), NAUTILUS_ART_IRECT_EMPTY); + + image_frame = labeled_image_get_image_frame (labeled_image); + + if (art_irect_empty (&image_frame)) { + return NAUTILUS_ART_IRECT_EMPTY; + } + + content_bounds = labeled_image_get_content_bounds (labeled_image); + bounds = nautilus_irect_gtk_widget_get_bounds (GTK_WIDGET (labeled_image)); + + if (!labeled_image_show_label (labeled_image)) { + image_bounds = bounds; + } else { + switch (labeled_image->details->label_position) { + case GTK_POS_LEFT: + image_bounds.y0 = bounds.y0; + image_bounds.x0 = content_bounds.x1 - image_frame.x1; + image_bounds.y1 = bounds.y1; + image_bounds.x1 = bounds.x1; + break; + + case GTK_POS_RIGHT: + image_bounds.y0 = bounds.y0; + image_bounds.x0 = bounds.x0; + image_bounds.y1 = bounds.y1; + image_bounds.x1 = content_bounds.x0 + image_frame.x1; + break; + + case GTK_POS_TOP: + image_bounds.x0 = bounds.x0; + image_bounds.y0 = content_bounds.y1 - image_frame.y1; + image_bounds.x1 = bounds.x1; + image_bounds.y1 = bounds.y1; + break; + + case GTK_POS_BOTTOM: + image_bounds.x0 = bounds.x0; + image_bounds.y0 = bounds.y0; + image_bounds.x1 = bounds.x1; + image_bounds.y1 = content_bounds.y0 + image_frame.y1; + break; + } + } + + return image_bounds; +} + +static ArtIRect +labeled_image_get_image_bounds (const NautilusLabeledImage *labeled_image) +{ + ArtIRect image_frame; + ArtIRect image_bounds; + ArtIRect content_bounds; + + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), NAUTILUS_ART_IRECT_EMPTY); + + if (labeled_image->details->fill) { + return labeled_image_get_image_bounds_fill (labeled_image); + } + + image_frame = labeled_image_get_image_frame (labeled_image); + + if (art_irect_empty (&image_frame)) { + return NAUTILUS_ART_IRECT_EMPTY; + } + + content_bounds = labeled_image_get_content_bounds (labeled_image); + + if (!labeled_image_show_label (labeled_image)) { + image_bounds.x0 = + content_bounds.x0 + + (nautilus_art_irect_get_width (&content_bounds) - image_frame.x1) / 2; + image_bounds.y0 = + content_bounds.y0 + + (nautilus_art_irect_get_height (&content_bounds) - image_frame.y1) / 2; + } else { + switch (labeled_image->details->label_position) { + case GTK_POS_LEFT: + image_bounds.x0 = content_bounds.x1 - image_frame.x1; + image_bounds.y0 = + content_bounds.y0 + + (nautilus_art_irect_get_height (&content_bounds) - image_frame.y1) / 2; + break; + + case GTK_POS_RIGHT: + image_bounds.x0 = content_bounds.x0; + image_bounds.y0 = + content_bounds.y0 + + (nautilus_art_irect_get_height (&content_bounds) - image_frame.y1) / 2; + break; + + case GTK_POS_TOP: + image_bounds.x0 = + content_bounds.x0 + + (nautilus_art_irect_get_width (&content_bounds) - image_frame.x1) / 2; + image_bounds.y0 = content_bounds.y1 - image_frame.y1; + break; + + case GTK_POS_BOTTOM: + image_bounds.x0 = + content_bounds.x0 + + (nautilus_art_irect_get_width (&content_bounds) - image_frame.x1) / 2; + image_bounds.y0 = content_bounds.y0; + break; + } + } + + image_bounds.x1 = image_bounds.x0 + image_frame.x1; + image_bounds.y1 = image_bounds.y0 + image_frame.y1; + + return image_bounds; +} + +static ArtIRect +labeled_image_get_label_bounds_fill (const NautilusLabeledImage *labeled_image) +{ + ArtIRect label_bounds; + ArtIRect label_frame; + ArtIRect content_bounds; + ArtIRect bounds; + + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), NAUTILUS_ART_IRECT_EMPTY); + + label_frame = labeled_image_get_label_frame (labeled_image); + + if (art_irect_empty (&label_frame)) { + return NAUTILUS_ART_IRECT_EMPTY; + } + + content_bounds = labeled_image_get_content_bounds (labeled_image); + bounds = nautilus_irect_gtk_widget_get_bounds (GTK_WIDGET (labeled_image)); + + /* Only the label is shown */ + if (!labeled_image_show_image (labeled_image)) { + label_bounds = bounds; + /* Both label and image are shown */ + } else { + switch (labeled_image->details->label_position) { + case GTK_POS_LEFT: + label_bounds.y0 = bounds.y0; + label_bounds.x0 = bounds.x0; + label_bounds.y1 = bounds.y1; + label_bounds.x1 = content_bounds.x0 + label_frame.x1; + break; + + case GTK_POS_RIGHT: + label_bounds.y0 = bounds.y0; + label_bounds.x0 = content_bounds.x1 - label_frame.x1; + label_bounds.y1 = bounds.y1; + label_bounds.x1 = bounds.x1; + break; + + case GTK_POS_TOP: + label_bounds.x0 = bounds.x0; + label_bounds.y0 = bounds.y0; + label_bounds.x1 = bounds.x1; + label_bounds.y1 = content_bounds.y0 + label_frame.y1; + break; + + case GTK_POS_BOTTOM: + label_bounds.x0 = bounds.x0; + label_bounds.y0 = content_bounds.y1 - label_frame.y1; + label_bounds.x1 = bounds.x1; + label_bounds.y1 = bounds.y1; + break; + } + } + + return label_bounds; +} + +static ArtIRect +labeled_image_get_label_bounds (const NautilusLabeledImage *labeled_image) +{ + ArtIRect label_bounds; + ArtIRect label_frame; + ArtIRect content_bounds; + + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), NAUTILUS_ART_IRECT_EMPTY); + + if (labeled_image->details->fill) { + return labeled_image_get_label_bounds_fill (labeled_image); + } + + label_frame = labeled_image_get_label_frame (labeled_image); + + if (art_irect_empty (&label_frame)) { + return NAUTILUS_ART_IRECT_EMPTY; + } + + content_bounds = labeled_image_get_content_bounds (labeled_image); + + /* Only the label is shown */ + if (!labeled_image_show_image (labeled_image)) { + label_bounds.x0 = + content_bounds.x0 + + (nautilus_art_irect_get_width (&content_bounds) - label_frame.x1) / 2; + label_bounds.y0 = + content_bounds.y0 + + (nautilus_art_irect_get_height (&content_bounds) - label_frame.y1) / 2; + /* Both label and image are shown */ + } else { + switch (labeled_image->details->label_position) { + case GTK_POS_LEFT: + label_bounds.x0 = content_bounds.x0; + label_bounds.y0 = + content_bounds.y0 + + (nautilus_art_irect_get_height (&content_bounds) - label_frame.y1) / 2; + break; + + case GTK_POS_RIGHT: + label_bounds.x0 = content_bounds.x1 - label_frame.x1; + label_bounds.y0 = + content_bounds.y0 + + (nautilus_art_irect_get_height (&content_bounds) - label_frame.y1) / 2; + break; + + case GTK_POS_TOP: + label_bounds.x0 = + content_bounds.x0 + + (nautilus_art_irect_get_width (&content_bounds) - label_frame.x1) / 2; + label_bounds.y0 = content_bounds.y0; + break; + + case GTK_POS_BOTTOM: + label_bounds.x0 = + content_bounds.x0 + + (nautilus_art_irect_get_width (&content_bounds) - label_frame.x1) / 2; + label_bounds.y0 = content_bounds.y1 - label_frame.y1; + break; + } + } + + label_bounds.x1 = label_bounds.x0 + label_frame.x1; + label_bounds.y1 = label_bounds.y0 + label_frame.y1; + + return label_bounds; +} + +static void +labeled_image_update_alignments (NautilusLabeledImage *labeled_image) +{ + + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->label != NULL) { + float x_alignment; + float y_alignment; + + if (labeled_image->details->fill) { + x_alignment = GTK_MISC (labeled_image->details->label)->xalign; + y_alignment = GTK_MISC (labeled_image->details->label)->yalign; + + /* Only the label is shown */ + if (!labeled_image_show_image (labeled_image)) { + x_alignment = 0.5; + y_alignment = 0.5; + /* Both label and image are shown */ + } else { + switch (labeled_image->details->label_position) { + case GTK_POS_LEFT: + x_alignment = 1.0; + y_alignment = 0.5; + break; + + case GTK_POS_RIGHT: + x_alignment = 0.0; + y_alignment = 0.5; + break; + + case GTK_POS_TOP: + x_alignment = 0.5; + y_alignment = 1.0; + break; + + case GTK_POS_BOTTOM: + x_alignment = 0.5; + y_alignment = 0.0; + break; + } + + } + + gtk_misc_set_alignment (GTK_MISC (labeled_image->details->label), + x_alignment, + y_alignment); + } + } + + if (labeled_image->details->image != NULL) { + float x_alignment; + float y_alignment; + + if (labeled_image->details->fill) { + x_alignment = GTK_MISC (labeled_image->details->image)->xalign; + y_alignment = GTK_MISC (labeled_image->details->image)->yalign; + + /* Only the image is shown */ + if (!labeled_image_show_label (labeled_image)) { + x_alignment = 0.5; + y_alignment = 0.5; + /* Both label and image are shown */ + } else { + switch (labeled_image->details->label_position) { + case GTK_POS_LEFT: + x_alignment = 0.0; + y_alignment = 0.5; + break; + + case GTK_POS_RIGHT: + x_alignment = 1.0; + y_alignment = 0.5; + break; + + case GTK_POS_TOP: + x_alignment = 0.5; + y_alignment = 0.0; + break; + + case GTK_POS_BOTTOM: + x_alignment = 0.5; + y_alignment = 1.0; + break; + } + } + + gtk_misc_set_alignment (GTK_MISC (labeled_image->details->image), + x_alignment, + y_alignment); + } + } +} + +static ArtIRect +labeled_image_get_content_frame (const NautilusLabeledImage *labeled_image) +{ + ArtIRect image_frame; + ArtIRect label_frame; + ArtIRect content_frame; + + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), NAUTILUS_ART_IRECT_EMPTY); + + image_frame = labeled_image_get_image_frame (labeled_image); + label_frame = labeled_image_get_label_frame (labeled_image); + + content_frame = NAUTILUS_ART_IRECT_EMPTY; + + /* Both shown */ + if (!art_irect_empty (&image_frame) && !art_irect_empty (&label_frame)) { + content_frame.x1 = image_frame.x1 + labeled_image->details->spacing + label_frame.x1; + switch (labeled_image->details->label_position) { + case GTK_POS_LEFT: + case GTK_POS_RIGHT: + content_frame.x1 = image_frame.x1 + labeled_image->details->spacing + label_frame.x1; + content_frame.y1 = MAX (image_frame.y1, label_frame.y1); + break; + + case GTK_POS_TOP: + case GTK_POS_BOTTOM: + content_frame.x1 = MAX (image_frame.x1, label_frame.x1); + content_frame.y1 = image_frame.y1 + labeled_image->details->spacing + label_frame.y1; + break; + } + /* Only image shown */ + } else if (!art_irect_empty (&image_frame)) { + content_frame.x1 = image_frame.x1; + content_frame.y1 = image_frame.y1; + /* Only label shown */ + } else { + content_frame.x1 = label_frame.x1; + content_frame.y1 = label_frame.y1; + } + + return content_frame; +} + +static ArtIRect +labeled_image_get_content_bounds (const NautilusLabeledImage *labeled_image) +{ + ArtIRect content_frame; + ArtIRect content_bounds; + ArtIRect bounds; + + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), NAUTILUS_ART_IRECT_EMPTY); + + bounds = nautilus_irect_gtk_widget_get_bounds (GTK_WIDGET (labeled_image)); + + content_frame = labeled_image_get_content_frame (labeled_image); + content_bounds = nautilus_art_irect_align (&bounds, + content_frame.x1, + content_frame.y1, + labeled_image->details->x_alignment, + labeled_image->details->y_alignment); + + return content_bounds; +} + +static void +labeled_image_ensure_label (NautilusLabeledImage *labeled_image) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->label != NULL) { + return; + } + + labeled_image->details->label = nautilus_label_new (NULL); + gtk_container_add (GTK_CONTAINER (labeled_image), labeled_image->details->label); + gtk_widget_show (labeled_image->details->label); +} + +static void +labeled_image_ensure_image (NautilusLabeledImage *labeled_image) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->image != NULL) { + return; + } + + labeled_image->details->image = nautilus_image_new (NULL); + gtk_container_add (GTK_CONTAINER (labeled_image), labeled_image->details->image); + gtk_widget_show (labeled_image->details->image); +} + +static gboolean +labeled_image_show_image (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), FALSE); + + return labeled_image->details->image != NULL && labeled_image->details->show_image; +} + +static gboolean +labeled_image_show_label (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), FALSE); + + return labeled_image->details->label != NULL && labeled_image->details->show_label; +} + +/** + * nautilus_labeled_image_new: + * @text: Text to use for label or NULL. + * @pixbuf: Pixbuf to use for image or NULL. + * + * Returns A newly allocated NautilusLabeledImage. If the &text parameter is not + * NULL then the LabeledImage will show a label. If the &pixbuf parameter is not + * NULL then the LabeledImage will show a pixbuf. Either of these can be NULL at + * creation time. + * + * Later in the lifetime of the widget you can invoke methods that affect the + * label and/or the image. If at creation time these were NULL, then they will + * be created as neeeded. + * + * Thus, using this widget in place of NautilusImage or NautilusLabel is "free" with + * only the GtkObject and function call overhead. + * + */ +GtkWidget* +nautilus_labeled_image_new (const char *text, + GdkPixbuf *pixbuf) +{ + NautilusLabeledImage *labeled_image; + + labeled_image = NAUTILUS_LABELED_IMAGE (gtk_widget_new (nautilus_labeled_image_get_type (), NULL)); + + if (text != NULL) { + nautilus_labeled_image_set_text (labeled_image, text); + } + + if (pixbuf != NULL) { + nautilus_labeled_image_set_pixbuf (labeled_image, pixbuf); + } + + labeled_image_update_alignments (labeled_image); + + return GTK_WIDGET (labeled_image); +} + +/** + * nautilus_labeled_image_set_label_position: + * @labeled_image: A NautilusLabeledImage. + * @label_position: The position of the label with respect to the image. + * + * Set the position of the label with respect to the image as follows: + * + * GTK_POS_LEFT: + * [ <label> <image> ] + * + * GTK_POS_RIGHT: + * [ <image> <label> ] + * + * GTK_POS_TOP: + * [ <label> ] + * [ <image> ] + * + * GTK_POS_BOTTOM: + * [ <image> ] + * [ <label> ] + * + */ +void +nautilus_labeled_image_set_label_position (NautilusLabeledImage *labeled_image, + GtkPositionType label_position) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + g_return_if_fail (label_position >= GTK_POS_LEFT); + g_return_if_fail (label_position <= GTK_POS_BOTTOM); + + if (labeled_image->details->label_position == label_position) { + return; + } + + labeled_image->details->label_position = label_position; + + labeled_image_update_alignments (labeled_image); + + gtk_widget_queue_resize (GTK_WIDGET (labeled_image)); +} + +/** + * nautilus_labeled_image_get_label_postiion: + * @labeled_image: A NautilusLabeledImage. + * + * Returns an enumeration indicating the position of the label with respect to the image. + */ +GtkPositionType +nautilus_labeled_image_get_label_position (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), 0); + + return labeled_image->details->label_position; +} + +/** + * nautilus_labeled_image_set_show_label: + * @labeled_image: A NautilusLabeledImage. + * @show_image: A boolean value indicating whether the label should be shown. + * + * Update the labeled image to either show or hide the internal label widget. + * This function doesnt have any effect if the LabeledImage doesnt already + * contain an label. + */ +void +nautilus_labeled_image_set_show_label (NautilusLabeledImage *labeled_image, + gboolean show_label) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->show_label == show_label) { + return; + } + + labeled_image->details->show_label = show_label; + + if (labeled_image->details->label != NULL) { + if (labeled_image->details->show_label) { + gtk_widget_show (labeled_image->details->label); + } else { + gtk_widget_hide (labeled_image->details->label); + } + } + + labeled_image_update_alignments (labeled_image); + + gtk_widget_queue_resize (GTK_WIDGET (labeled_image)); +} + +/** + * nautilus_labeled_image_get_show_label: + * @labeled_image: A NautilusLabeledImage. + * + * Returns a boolean value indicating whether the internal label is shown. + */ +gboolean +nautilus_labeled_image_get_show_label (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), 0); + + return labeled_image->details->show_label; +} + +/** + * nautilus_labeled_image_set_show_image: + * @labeled_image: A NautilusLabeledImage. + * @show_image: A boolean value indicating whether the image should be shown. + * + * Update the labeled image to either show or hide the internal image widget. + * This function doesnt have any effect if the LabeledImage doesnt already + * contain an image. + */ +void +nautilus_labeled_image_set_show_image (NautilusLabeledImage *labeled_image, + gboolean show_image) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->show_image == show_image) { + return; + } + + labeled_image->details->show_image = show_image; + + if (labeled_image->details->image != NULL) { + if (labeled_image->details->show_image) { + gtk_widget_show (labeled_image->details->image); + } else { + gtk_widget_hide (labeled_image->details->image); + } + } + + labeled_image_update_alignments (labeled_image); + + gtk_widget_queue_resize (GTK_WIDGET (labeled_image)); +} + +/** + * nautilus_labeled_image_get_show_image: + * @labeled_image: A NautilusLabeledImage. + * + * Returns a boolean value indicating whether the internal image is shown. + */ +gboolean +nautilus_labeled_image_get_show_image (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), 0); + + return labeled_image->details->show_image; +} + +/** + * nautilus_labeled_image_set_spacing: + * @labeled_image: A NautilusLabeledImage. + * @spacing: The new spacing between label and image. + * + * Set the spacing between label and image. This will only affect + * the geometry of the widget if both a label and image are currently + * visible. + * + */ +void +nautilus_labeled_image_set_spacing (NautilusLabeledImage *labeled_image, + guint spacing) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->spacing == spacing) { + return; + } + + labeled_image->details->spacing = spacing; + + labeled_image_update_alignments (labeled_image); + + gtk_widget_queue_resize (GTK_WIDGET (labeled_image)); +} + +/** + * nautilus_labeled_image_get_spacing: + * @labeled_image: A NautilusLabeledImage. + * + * Returns: The spacing between the label and image. + */ +guint +nautilus_labeled_image_get_spacing (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), 0); + + return labeled_image->details->spacing; +} + +/** + * nautilus_labeled_image_set_x_padding: + * @labeled_image: A NautilusLabeledImage. + * @x_padding: The new horizontal padding. + * + * Set horizontal padding for the NautilusLabeledImage. The padding + * attribute work just like that in GtkMisc. + */ +void +nautilus_labeled_image_set_x_padding (NautilusLabeledImage *labeled_image, + int x_padding) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + x_padding = MAX (0, x_padding); + + if (labeled_image->details->x_padding == x_padding) { + return; + } + + labeled_image->details->x_padding = x_padding; + labeled_image_update_alignments (labeled_image); + gtk_widget_queue_resize (GTK_WIDGET (labeled_image)); +} + +/** + * nautilus_labeled_image_get_x_padding: + * @labeled_image: A NautilusLabeledImage. + * + * Returns: The horizontal padding for the LabeledImage's content. + */ +int +nautilus_labeled_image_get_x_padding (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), 0); + + return labeled_image->details->x_padding; +} + +/** + * nautilus_labeled_image_set_y_padding: + * @labeled_image: A NautilusLabeledImage. + * @x_padding: The new vertical padding. + * + * Set vertical padding for the NautilusLabeledImage. The padding + * attribute work just like that in GtkMisc. + */ +void +nautilus_labeled_image_set_y_padding (NautilusLabeledImage *labeled_image, + int y_padding) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + y_padding = MAX (0, y_padding); + + if (labeled_image->details->y_padding == y_padding) { + return; + } + + labeled_image->details->y_padding = y_padding; + labeled_image_update_alignments (labeled_image); + gtk_widget_queue_resize (GTK_WIDGET (labeled_image)); +} + +/** + * nautilus_labeled_image_get_x_padding: + * @labeled_image: A NautilusLabeledImage. + * + * Returns: The vertical padding for the LabeledImage's content. + */ +int +nautilus_labeled_image_get_y_padding (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), 0); + + return labeled_image->details->y_padding; +} + +/** + * nautilus_labeled_image_set_x_alignment: + * @labeled_image: A NautilusLabeledImage. + * @x_alignment: The new horizontal alignment. + * + * Set horizontal alignment for the NautilusLabeledImage's content. + * The 'content' is the union of the image and label. The alignment + * attribute work just like that in GtkMisc. + */ +void +nautilus_labeled_image_set_x_alignment (NautilusLabeledImage *labeled_image, + float x_alignment) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + x_alignment = MAX (0, x_alignment); + x_alignment = MIN (1.0, x_alignment); + + if (labeled_image->details->x_alignment == x_alignment) { + return; + } + + labeled_image->details->x_alignment = x_alignment; + gtk_widget_queue_resize (GTK_WIDGET (labeled_image)); +} + +/** + * nautilus_labeled_image_get_x_alignment: + * @labeled_image: A NautilusLabeledImage. + * + * Returns: The horizontal alignment for the LabeledImage's content. + */ +float +nautilus_labeled_image_get_x_alignment (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), 0); + + return labeled_image->details->x_alignment; +} + +/** + * nautilus_labeled_image_set_y_alignment: + * @labeled_image: A NautilusLabeledImage. + * @y_alignment: The new vertical alignment. + * + * Set vertical alignment for the NautilusLabeledImage's content. + * The 'content' is the union of the image and label. The alignment + * attribute work just like that in GtkMisc. + */ +void +nautilus_labeled_image_set_y_alignment (NautilusLabeledImage *labeled_image, + float y_alignment) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + y_alignment = MAX (0, y_alignment); + y_alignment = MIN (1.0, y_alignment); + + if (labeled_image->details->y_alignment == y_alignment) { + return; + } + + labeled_image->details->y_alignment = y_alignment; + gtk_widget_queue_resize (GTK_WIDGET (labeled_image)); +} + +/** + * nautilus_labeled_image_get_y_alignment: + * @labeled_image: A NautilusLabeledImage. + * + * Returns: The vertical alignment for the LabeledImage's content. + */ +float +nautilus_labeled_image_get_y_alignment (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), 0); + + return labeled_image->details->y_alignment; +} + +/** + * nautilus_labeled_image_set_fill: + * @labeled_image: A NautilusLabeledImage. + * @fill: A boolean value indicating whether the internal image and label + * widgets should fill all the available allocation. + * + * By default the internal image and label wigets are sized to their natural + * preferred geometry. You can use the 'fill' attribute of LabeledImage + * to have the internal widgets fill as much of the LabeledImage allocation + * as is available. This is useful if you install a tile_pixbuf and want it + * to cover the whole widget, and not just the areas occupied by the internal + * widgets. + */ +void +nautilus_labeled_image_set_fill (NautilusLabeledImage *labeled_image, + gboolean fill) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->fill == fill) { + return; + } + + labeled_image->details->fill = fill; + + labeled_image_update_alignments (labeled_image); + + gtk_widget_queue_resize (GTK_WIDGET (labeled_image)); +} + +/** + * nautilus_labeled_image_get_fill: + * @labeled_image: A NautilusLabeledImage. + * + * Retruns a boolean value indicating whether the internal widgets fill + * all the available allocation. + */ +gboolean +nautilus_labeled_image_get_fill (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), 0); + + return labeled_image->details->fill; +} + +/** + * nautilus_labeled_image_button_new: + * @text: Text to use for label or NULL. + * @pixbuf: Pixbuf to use for image or NULL. + * + * Create a stock GtkButton with a NautilusLabeledImage child. + * + */ +GtkWidget * +nautilus_labeled_image_button_new (const char *text, + GdkPixbuf *pixbuf) +{ + GtkWidget *button; + GtkWidget *labeled_image; + + button = gtk_button_new (); + labeled_image = nautilus_labeled_image_new (text, pixbuf); + gtk_container_add (GTK_CONTAINER (button), labeled_image); + gtk_widget_show (labeled_image); + + return button; +} + +/** + * nautilus_labeled_image_toggle_button_new: + * @text: Text to use for label or NULL. + * @pixbuf: Pixbuf to use for image or NULL. + * + * Create a stock GtkToggleButton with a NautilusLabeledImage child. + * + */ +GtkWidget * +nautilus_labeled_image_toggle_button_new (const char *text, + GdkPixbuf *pixbuf) +{ + GtkWidget *toggle_button; + GtkWidget *labeled_image; + + toggle_button = gtk_toggle_button_new (); + labeled_image = nautilus_labeled_image_new (text, pixbuf); + gtk_container_add (GTK_CONTAINER (toggle_button), labeled_image); + gtk_widget_show (labeled_image); + + return toggle_button; +} + +/** + * nautilus_labeled_image_check_button_new: + * @text: Text to use for label or NULL. + * @pixbuf: Pixbuf to use for image or NULL. + * + * Create a stock GtkCheckButton with a NautilusLabeledImage child. + * + */ +GtkWidget * +nautilus_labeled_image_check_button_new (const char *text, + GdkPixbuf *pixbuf) +{ + GtkWidget *check_button; + GtkWidget *labeled_image; + + check_button = gtk_check_button_new (); + labeled_image = nautilus_labeled_image_new (text, pixbuf); + gtk_container_add (GTK_CONTAINER (check_button), labeled_image); + gtk_widget_show (labeled_image); + + return check_button; +} + +/* + * The rest of the methods are proxies for those in NautilusImage and + * NautilusLabel. We have all these so that we dont have to expose + * our internal widgets at all. Probably more of these will be added + * as they are needed. + */ +void +nautilus_labeled_image_set_pixbuf (NautilusLabeledImage *labeled_image, + GdkPixbuf *pixbuf) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (pixbuf == NULL) { + if (labeled_image->details->image != NULL) { + gtk_widget_destroy (labeled_image->details->image); + labeled_image->details->image = NULL; + } + + gtk_widget_queue_resize (GTK_WIDGET (labeled_image)); + } else { + labeled_image_ensure_image (labeled_image); + nautilus_image_set_pixbuf (NAUTILUS_IMAGE (labeled_image->details->image), pixbuf); + } +} + +void +nautilus_labeled_image_set_pixbuf_from_file_name (NautilusLabeledImage *labeled_image, + const char *file_name) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + labeled_image_ensure_image (labeled_image); + nautilus_image_set_pixbuf_from_file_name (NAUTILUS_IMAGE (labeled_image->details->image), file_name); +} + +void +nautilus_labeled_image_set_tile_pixbuf (NautilusLabeledImage *labeled_image, + GdkPixbuf *tile_pixbuf) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->image != NULL) { + nautilus_image_set_tile_pixbuf (NAUTILUS_IMAGE (labeled_image->details->image), tile_pixbuf); + nautilus_image_set_tile_mode_horizontal (NAUTILUS_IMAGE (labeled_image->details->image), + NAUTILUS_SMOOTH_TILE_ANCESTOR); + nautilus_image_set_tile_mode_vertical (NAUTILUS_IMAGE (labeled_image->details->image), + NAUTILUS_SMOOTH_TILE_ANCESTOR); + } + + if (labeled_image->details->label != NULL) { + nautilus_label_set_tile_pixbuf (NAUTILUS_LABEL (labeled_image->details->label), tile_pixbuf); + nautilus_label_set_tile_mode_horizontal (NAUTILUS_LABEL (labeled_image->details->label), + NAUTILUS_SMOOTH_TILE_ANCESTOR); + nautilus_label_set_tile_mode_vertical (NAUTILUS_LABEL (labeled_image->details->label), + NAUTILUS_SMOOTH_TILE_ANCESTOR); + } +} + +void +nautilus_labeled_image_set_tile_pixbuf_from_file_name (NautilusLabeledImage *labeled_image, + const char *file_name) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->image != NULL) { + nautilus_image_set_tile_pixbuf_from_file_name (NAUTILUS_IMAGE (labeled_image->details->image), + file_name); + nautilus_image_set_tile_mode_horizontal (NAUTILUS_IMAGE (labeled_image->details->image), + NAUTILUS_SMOOTH_TILE_ANCESTOR); + nautilus_image_set_tile_mode_vertical (NAUTILUS_IMAGE (labeled_image->details->image), + NAUTILUS_SMOOTH_TILE_ANCESTOR); + } + + if (labeled_image->details->label != NULL) { + nautilus_label_set_tile_pixbuf_from_file_name (NAUTILUS_LABEL (labeled_image->details->label), + file_name); + nautilus_label_set_tile_mode_horizontal (NAUTILUS_LABEL (labeled_image->details->label), + NAUTILUS_SMOOTH_TILE_ANCESTOR); + nautilus_label_set_tile_mode_vertical (NAUTILUS_LABEL (labeled_image->details->label), + NAUTILUS_SMOOTH_TILE_ANCESTOR); + } +} + +GdkPixbuf* +nautilus_labeled_image_get_pixbuf (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), NULL); + + if (labeled_image->details->image == NULL) { + return NULL; + } + + return nautilus_image_get_pixbuf (NAUTILUS_IMAGE (labeled_image->details->image)); +} + +void +nautilus_labeled_image_set_text (NautilusLabeledImage *labeled_image, + const char *text) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (text == NULL) { + if (labeled_image->details->label) { + gtk_widget_destroy (labeled_image->details->label); + labeled_image->details->label = NULL; + } + + gtk_widget_queue_resize (GTK_WIDGET (labeled_image)); + } else { + labeled_image_ensure_label (labeled_image); + nautilus_label_set_text (NAUTILUS_LABEL (labeled_image->details->label), text); + } +} + +char * +nautilus_labeled_image_get_text (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), NULL); + + if (labeled_image->details->label == NULL) { + return NULL; + } + + return nautilus_label_get_text (NAUTILUS_LABEL (labeled_image->details->label)); +} + +void +nautilus_labeled_image_make_bold (NautilusLabeledImage *labeled_image) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + labeled_image_ensure_label (labeled_image); + nautilus_label_make_bold (NAUTILUS_LABEL (labeled_image->details->label)); +} + +void +nautilus_labeled_image_make_larger (NautilusLabeledImage *labeled_image, + guint num_sizes) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + labeled_image_ensure_label (labeled_image); + nautilus_label_make_larger (NAUTILUS_LABEL (labeled_image->details->label), num_sizes); +} + +void +nautilus_labeled_image_make_smaller (NautilusLabeledImage *labeled_image, + guint num_sizes) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + labeled_image_ensure_label (labeled_image); + nautilus_label_make_smaller (NAUTILUS_LABEL (labeled_image->details->label), num_sizes); +} + +void +nautilus_labeled_image_set_tile_width (NautilusLabeledImage *labeled_image, + int tile_width) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->image != NULL) { + nautilus_image_set_tile_width (NAUTILUS_IMAGE (labeled_image->details->image), + tile_width); + } + + if (labeled_image->details->label != NULL) { + nautilus_label_set_tile_width (NAUTILUS_LABEL (labeled_image->details->label), + tile_width); + } +} + +void +nautilus_labeled_image_set_tile_height (NautilusLabeledImage *labeled_image, + int tile_height) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->image != NULL) { + nautilus_image_set_tile_height (NAUTILUS_IMAGE (labeled_image->details->image), + tile_height); + } + + if (labeled_image->details->label != NULL) { + nautilus_label_set_tile_height (NAUTILUS_LABEL (labeled_image->details->label), + tile_height); + } +} + +void +nautilus_labeled_image_set_background_mode (NautilusLabeledImage *labeled_image, + NautilusSmoothBackgroundMode background_mode) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + g_return_if_fail (background_mode >= NAUTILUS_SMOOTH_BACKGROUND_GTK); + g_return_if_fail (background_mode <= NAUTILUS_SMOOTH_BACKGROUND_SOLID_COLOR); + + if (labeled_image->details->image != NULL) { + nautilus_image_set_background_mode (NAUTILUS_IMAGE (labeled_image->details->image), + background_mode); + } + + if (labeled_image->details->label != NULL) { + nautilus_label_set_background_mode (NAUTILUS_LABEL (labeled_image->details->label), + background_mode); + } +} + +void +nautilus_labeled_image_set_solid_background_color (NautilusLabeledImage *labeled_image, + guint32 solid_background_color) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->image != NULL) { + nautilus_image_set_solid_background_color (NAUTILUS_IMAGE (labeled_image->details->image), + solid_background_color); + } + + if (labeled_image->details->label != NULL) { + nautilus_label_set_solid_background_color (NAUTILUS_LABEL (labeled_image->details->label), + solid_background_color); + } +} + +void +nautilus_labeled_image_set_smooth_drop_shadow_offset (NautilusLabeledImage *labeled_image, + guint drop_shadow_offset) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->label != NULL) { + nautilus_label_set_smooth_drop_shadow_offset (NAUTILUS_LABEL (labeled_image->details->label), + drop_shadow_offset); + } +} + +void +nautilus_labeled_image_set_smooth_drop_shadow_color (NautilusLabeledImage *labeled_image, + guint32 drop_shadow_color) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->label != NULL) { + nautilus_label_set_smooth_drop_shadow_color (NAUTILUS_LABEL (labeled_image->details->label), + drop_shadow_color); + } +} + +void +nautilus_labeled_image_set_text_color (NautilusLabeledImage *labeled_image, + guint32 text_color) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->label != NULL) { + nautilus_label_set_text_color (NAUTILUS_LABEL (labeled_image->details->label), + text_color); + } +} + diff --git a/libnautilus-extensions/nautilus-labeled-image.h b/libnautilus-extensions/nautilus-labeled-image.h new file mode 100644 index 000000000..e8c511966 --- /dev/null +++ b/libnautilus-extensions/nautilus-labeled-image.h @@ -0,0 +1,158 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ + +/* nautilus-labeled-image.h - A labeled image. + + Copyright (C) 2000 Eazel, Inc. + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Authors: Ramiro Estrugo <ramiro@eazel.com> +*/ + +/* NautilusLabeledImage is a container widget. It can only contain internal + * widgets. These internal widgets are can be a NautilusLabel and/or a + * NautilusImage. These internal widgets are create as needed. That means + * that NautilusLabeledImage can always be used for "free" instead of a + * NautilusLabel or NautilusImage. The only overhead is that of the GtkObject + * machinery. The label and image widgets themselves are only created as needed. + * + * The position of the label with respect to the image is controlled by the + * 'label_positon' attribute. + * + * By default the internal image and label wigets are sized to their natural + * preferred geometry. You can use the 'fill' attribute of LabeledImage + * to have the internal widgets fill as much of the LabeledImage allocation + * as is available. This is useful if you install a tile_pixbuf and want it + * to cover the whole widget, and not just the areas occupied by the internal + * widgets. + * + * LabeledImage also has x_padding/y_padding and x_alignment/y_alignment + * attributes that behave exaclty as those in the GtkMisc class. + * + * Note that the alignments are ignored if the fill attribute is TRUE. + */ + +#ifndef NAUTILUS_LABELED_IMAGE_H +#define NAUTILUS_LABELED_IMAGE_H + +#include <gtk/gtkcontainer.h> +#include <libnautilus-extensions/nautilus-label.h> +#include <libnautilus-extensions/nautilus-image.h> + +BEGIN_GNOME_DECLS + +#define NAUTILUS_TYPE_LABELED_IMAGE (nautilus_labeled_image_get_type ()) +#define NAUTILUS_LABELED_IMAGE(obj) (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_LABELED_IMAGE, NautilusLabeledImage)) +#define NAUTILUS_LABELED_IMAGE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_LABELED_IMAGE, NautilusLabeledImageClass)) +#define NAUTILUS_IS_LABELED_IMAGE(obj) (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_LABELED_IMAGE)) +#define NAUTILUS_IS_LABELED_IMAGE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_LABELED_IMAGE)) + +typedef struct _NautilusLabeledImage NautilusLabeledImage; +typedef struct _NautilusLabeledImageClass NautilusLabeledImageClass; +typedef struct _NautilusLabeledImageDetails NautilusLabeledImageDetails; + +struct _NautilusLabeledImage +{ + /* Superclass */ + GtkContainer container; + + /* Private things */ + NautilusLabeledImageDetails *details; +}; + +struct _NautilusLabeledImageClass +{ + GtkContainerClass parent_class; +}; + +/* Public GtkLabeledImage methods */ +GtkType nautilus_labeled_image_get_type (void); +GtkWidget * nautilus_labeled_image_new (const char *text, + GdkPixbuf *pixbuf); +void nautilus_labeled_image_set_label_position (NautilusLabeledImage *labeled_image, + GtkPositionType label_position); +GtkPositionType nautilus_labeled_image_get_label_position (const NautilusLabeledImage *labeled_image); +void nautilus_labeled_image_set_show_label (NautilusLabeledImage *labeled_image, + gboolean show_label); +gboolean nautilus_labeled_image_get_show_label (const NautilusLabeledImage *labeled_image); +void nautilus_labeled_image_set_show_image (NautilusLabeledImage *labeled_image, + gboolean show_image); +gboolean nautilus_labeled_image_get_show_image (const NautilusLabeledImage *labeled_image); +void nautilus_labeled_image_set_spacing (NautilusLabeledImage *labeled_image, + guint spacing); +guint nautilus_labeled_image_get_spacing (const NautilusLabeledImage *labeled_image); +int nautilus_labeled_image_get_x_padding (const NautilusLabeledImage *labeled_image); +void nautilus_labeled_image_set_x_padding (NautilusLabeledImage *labeled_image, + int x_padding); +int nautilus_labeled_image_get_y_padding (const NautilusLabeledImage *labeled_image); +void nautilus_labeled_image_set_y_padding (NautilusLabeledImage *labeled_image, + int y_padding); +float nautilus_labeled_image_get_x_alignment (const NautilusLabeledImage *labeled_image); +void nautilus_labeled_image_set_x_alignment (NautilusLabeledImage *labeled_image, + float x_alignment); +float nautilus_labeled_image_get_y_alignment (const NautilusLabeledImage *labeled_image); +void nautilus_labeled_image_set_y_alignment (NautilusLabeledImage *labeled_image, + float y_alignment); +void nautilus_labeled_image_set_fill (NautilusLabeledImage *labeled_image, + gboolean fill); +gboolean nautilus_labeled_image_get_fill (const NautilusLabeledImage *labeled_image); + +/* Functions for creating stock GtkButtons with a labeled image child */ +GtkWidget * nautilus_labeled_image_button_new (const char *text, + GdkPixbuf *pixbuf); +GtkWidget * nautilus_labeled_image_toggle_button_new (const char *text, + GdkPixbuf *pixbuf); +GtkWidget * nautilus_labeled_image_check_button_new (const char *text, + GdkPixbuf *pixbuf); + +/* These are proxies for methods in NautilusImage and NautilusLabel */ +void nautilus_labeled_image_set_pixbuf (NautilusLabeledImage *labeled_image, + GdkPixbuf *pixbuf); +void nautilus_labeled_image_set_pixbuf_from_file_name (NautilusLabeledImage *labeled_image, + const char *file_name); +GdkPixbuf* nautilus_labeled_image_get_pixbuf (const NautilusLabeledImage *labeled_image); +void nautilus_labeled_image_set_text (NautilusLabeledImage *labeled_image, + const char *text); +char* nautilus_labeled_image_get_text (const NautilusLabeledImage *labeled_image); +void nautilus_labeled_image_set_tile_pixbuf (NautilusLabeledImage *image, + GdkPixbuf *pixbuf); +void nautilus_labeled_image_set_tile_pixbuf_from_file_name (NautilusLabeledImage *image, + const char *tile_file_name); +void nautilus_labeled_image_make_bold (NautilusLabeledImage *labeled_image); +void nautilus_labeled_image_make_larger (NautilusLabeledImage *labeled_image, + guint num_sizes); +void nautilus_labeled_image_make_smaller (NautilusLabeledImage *labeled_image, + guint num_sizes); +void nautilus_labeled_image_set_tile_width (NautilusLabeledImage *labeled_image, + int tile_width); +void nautilus_labeled_image_set_tile_height (NautilusLabeledImage *labeled_image, + int tile_height); +void nautilus_labeled_image_set_background_mode (NautilusLabeledImage *labeled_image, + NautilusSmoothBackgroundMode background_mode); +void nautilus_labeled_image_set_solid_background_color (NautilusLabeledImage *labeled_image, + guint32 solid_background_color); +void nautilus_labeled_image_set_smooth_drop_shadow_offset (NautilusLabeledImage *labeled_image, + guint drop_shadow_offset); +void nautilus_labeled_image_set_smooth_drop_shadow_color (NautilusLabeledImage *labeled_image, + guint32 drop_shadow_color); +void nautilus_labeled_image_set_text_color (NautilusLabeledImage *labeled_image, + guint32 text_color); + +END_GNOME_DECLS + +#endif /* NAUTILUS_LABELED_IMAGE_H */ + + diff --git a/libnautilus-extensions/nautilus-smooth-widget.c b/libnautilus-extensions/nautilus-smooth-widget.c index ec82c692e..3b144263e 100644 --- a/libnautilus-extensions/nautilus-smooth-widget.c +++ b/libnautilus-extensions/nautilus-smooth-widget.c @@ -204,6 +204,13 @@ smooth_widget_get_tile_origin_point (const GtkWidget *widget, origin_point = NAUTILUS_ART_IPOINT_ZERO; + /* Using '0' for the ancestor origin works because our buddy GTK+ + * already makes our allocation.{x,y} the collected offsets of all + * our ancestors. + * + * It might be more correct to make this the allocation.{x,y} of the + * ancestor windowed widget - maybe. + */ switch (tile_mode_vertical) { case NAUTILUS_SMOOTH_TILE_SELF: origin_point.y = widget->allocation.y; @@ -960,8 +967,8 @@ nautilus_smooth_widget_get_preferred_frame (const GtkWidget *widget, nautilus_art_irect_assign (&preferred_frame, 0, 0, - MAX (content_frame->x1, tile_width) + (2 * GTK_MISC (widget)->xpad * 2), - MAX (content_frame->y1, tile_height) + (2 * GTK_MISC (widget)->ypad * 2)); + MAX (content_frame->x1, tile_width) + (2 * GTK_MISC (widget)->xpad), + MAX (content_frame->y1, tile_height) + (2 * GTK_MISC (widget)->ypad)); /* Make sure the frame is not zero. Gtk goes berserk with zero size widget */ preferred_frame.x1 = MAX (preferred_frame.x1, 2); diff --git a/libnautilus-private/Makefile.am b/libnautilus-private/Makefile.am index 45f0f2922..342ff77de 100644 --- a/libnautilus-private/Makefile.am +++ b/libnautilus-private/Makefile.am @@ -49,8 +49,8 @@ libnautilus_extensions_la_LDFLAGS = \ libnautilus_extensions_la_SOURCES = \ bug-5712-pr3-workaround--gdk-pixbuf-drawable.c \ - bug-5712-pr3-workaround--gdkimage.c \ bug-5712-pr3-workaround--gdk-pixbuf-private.h \ + bug-5712-pr3-workaround--gdkimage.c \ nautilus-art-extensions.c \ nautilus-art-gtk-extensions.c \ nautilus-background-canvas-group.c \ @@ -59,6 +59,7 @@ libnautilus_extensions_la_SOURCES = \ nautilus-bookmark.c \ nautilus-caption-table.c \ nautilus-caption.c \ + nautilus-clickable-image.c \ nautilus-ctree.c \ nautilus-customization-data.c \ nautilus-dateedit-extensions.c \ @@ -73,8 +74,8 @@ libnautilus_extensions_la_SOURCES = \ nautilus-drag.c \ nautilus-druid-page-eazel.c \ nautilus-druid.c \ - nautilus-entry.c \ nautilus-ellipsizing-label.c \ + nautilus-entry.c \ nautilus-enumeration.c \ nautilus-file-changes-queue.c \ nautilus-file-operations-progress.c \ @@ -104,6 +105,7 @@ libnautilus_extensions_la_SOURCES = \ nautilus-keep-last-vertical-box.c \ nautilus-label-with-background.c \ nautilus-label.c \ + nautilus-labeled-image.c \ nautilus-lib-self-check-functions.c \ nautilus-link-set.c \ nautilus-link.c \ @@ -160,6 +162,7 @@ noinst_HEADERS = \ nautilus-caption-table.h \ nautilus-caption.h \ nautilus-cdrom-extensions.h \ + nautilus-clickable-image.h \ nautilus-ctree.h \ nautilus-customization-data.h \ nautilus-dateedit-extensions.h \ @@ -212,6 +215,7 @@ noinst_HEADERS = \ nautilus-keep-last-vertical-box.h \ nautilus-label-with-background.h \ nautilus-label.h \ + nautilus-labeled-image.h \ nautilus-lib-self-check-functions.h \ nautilus-link-set.h \ nautilus-link.h \ diff --git a/libnautilus-private/nautilus-art-extensions.c b/libnautilus-private/nautilus-art-extensions.c index 88d581888..9cec8a717 100644 --- a/libnautilus-private/nautilus-art-extensions.c +++ b/libnautilus-private/nautilus-art-extensions.c @@ -26,6 +26,7 @@ #include <config.h> #include "nautilus-art-extensions.h" +#include <math.h> ArtIRect NAUTILUS_ART_IRECT_EMPTY = { 0, 0, 0, 0 }; NautilusArtIPoint NAUTILUS_ART_IPOINT_ZERO = { 0, 0 }; @@ -172,8 +173,6 @@ nautilus_art_irect_get_height (const ArtIRect *rectangle) * @aligned_height: Height of rectangle being algined. * @x_alignment: X alignment. * @y_alignment: Y alignment. - * @x_padding: X padding. - * @y_padding: Y padding. * * Returns: A rectangle aligned within a container rectangle * using the given alignment parameters. @@ -183,11 +182,11 @@ nautilus_art_irect_align (const ArtIRect *container, int aligned_width, int aligned_height, float x_alignment, - float y_alignment, - int x_padding, - int y_padding) + float y_alignment) { ArtIRect aligned; + int available_width; + int available_height; g_return_val_if_fail (container != NULL, NAUTILUS_ART_IRECT_EMPTY); @@ -200,23 +199,16 @@ nautilus_art_irect_align (const ArtIRect *container, } /* Make sure the aligment parameters are within range */ - x_padding = MAX (0, x_padding); - y_padding = MAX (0, y_padding); x_alignment = MAX (0, x_alignment); x_alignment = MIN (1.0, x_alignment); y_alignment = MAX (0, y_alignment); y_alignment = MIN (1.0, y_alignment); - - aligned.x0 = (container->x0 * (1.0 - x_alignment) + - (container->x0 + nautilus_art_irect_get_width (container) - - (aligned_width - x_padding * 2)) * - x_alignment) + 0.5; - - aligned.y0 = (container->y0 * (1.0 - y_alignment) + - (container->y0 + nautilus_art_irect_get_height (container) - - (aligned_height - y_padding * 2)) * - y_alignment) + 0.5; - + + available_width = nautilus_art_irect_get_width (container) - aligned_width; + available_height = nautilus_art_irect_get_height (container) - aligned_height; + + aligned.x0 = floor (container->x0 + (available_width * x_alignment) + 0.5); + aligned.y0 = floor (container->y0 + (available_height * y_alignment) + 0.5); aligned.x1 = aligned.x0 + aligned_width; aligned.y1 = aligned.y0 + aligned_height; diff --git a/libnautilus-private/nautilus-art-extensions.h b/libnautilus-private/nautilus-art-extensions.h index 9b6b498c5..b47f2d7ed 100644 --- a/libnautilus-private/nautilus-art-extensions.h +++ b/libnautilus-private/nautilus-art-extensions.h @@ -66,9 +66,7 @@ ArtIRect nautilus_art_irect_align (const ArtIRect *container, int aligned_width, int aligned_height, float x_alignment, - float y_alignment, - int x_padding, - int y_padding); + float y_alignment); END_GNOME_DECLS #endif /* NAUTILUS_ART_EXTENSIONS_H */ diff --git a/libnautilus-private/nautilus-clickable-image.c b/libnautilus-private/nautilus-clickable-image.c new file mode 100644 index 000000000..f39a4c4d2 --- /dev/null +++ b/libnautilus-private/nautilus-clickable-image.c @@ -0,0 +1,551 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ + +/* nautilus-clickable-image.c - A clickable image widget. + + Copyright (C) 2000 Eazel, Inc. + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Authors: Ramiro Estrugo <ramiro@eazel.com> +*/ + +#include <config.h> + +#include "nautilus-clickable-image.h" + +#include "nautilus-gtk-macros.h" +#include "nautilus-gtk-extensions.h" +#include "nautilus-art-gtk-extensions.h" + +/* Arguments */ +enum +{ + ARG_0, + ARG_POINTER_INSIDE, +}; + +/* Signals */ +typedef enum +{ + CLICKED, + ENTER, + LEAVE, + LAST_SIGNAL +} ImageSignal; + +/* Signals */ +static guint clickable_image_signals[LAST_SIGNAL] = { 0 }; + +/* Detail member struct */ +struct _NautilusClickableImageDetails +{ + gboolean pointer_inside; +}; + +/* GtkObjectClass methods */ +static void nautilus_clickable_image_initialize_class (NautilusClickableImageClass *image_class); +static void nautilus_clickable_image_initialize (NautilusClickableImage *image); +static void nautilus_clickable_image_destroy (GtkObject *object); +static void nautilus_clickable_image_get_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); +/* GtkWidgetClass methods */ +static int nautilus_clickable_image_expose_event (GtkWidget *widget, + GdkEventExpose *event); +static void nautilus_clickable_image_realize (GtkWidget *widget); +static void nautilus_clickable_image_unrealize (GtkWidget *widget); + + +/* Ancestor callbacks */ +static int ancestor_enter_notify_event (GtkWidget *widget, + GdkEventCrossing *event, + gpointer event_data); +static int ancestor_leave_notify_event (GtkWidget *widget, + GdkEventCrossing *event, + gpointer event_data); +static int ancestor_motion_notify_event (GtkWidget *widget, + GdkEventMotion *event, + gpointer event_data); +static int ancestor_button_press_event (GtkWidget *widget, + GdkEventButton *event, + gpointer event_data); +static int ancestor_button_release_event (GtkWidget *widget, + GdkEventButton *event, + gpointer event_data); + +NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusClickableImage, nautilus_clickable_image, NAUTILUS_TYPE_LABELED_IMAGE) + +/* Class init methods */ +static void +nautilus_clickable_image_initialize_class (NautilusClickableImageClass *image_class) +{ + GtkObjectClass *object_class = GTK_OBJECT_CLASS (image_class); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (image_class); + + /* GtkObjectClass */ + object_class->destroy = nautilus_clickable_image_destroy; + object_class->get_arg = nautilus_clickable_image_get_arg; + + /* GtkWidgetClass */ + widget_class->expose_event = nautilus_clickable_image_expose_event; + widget_class->realize = nautilus_clickable_image_realize; + widget_class->unrealize = nautilus_clickable_image_unrealize; + + /* Signals */ + clickable_image_signals[CLICKED] = gtk_signal_new ("clicked", + GTK_RUN_LAST, + object_class->type, + 0, + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, + 0); + + clickable_image_signals[ENTER] = gtk_signal_new ("enter", + GTK_RUN_LAST, + object_class->type, + 0, + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, + 0); + + clickable_image_signals[LEAVE] = gtk_signal_new ("leave", + GTK_RUN_LAST, + object_class->type, + 0, + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, + 0); + + gtk_object_class_add_signals (object_class, clickable_image_signals, LAST_SIGNAL); + + /* Arguments */ + gtk_object_add_arg_type ("NautilusClickableImage::pointer_inside", + GTK_TYPE_BOOL, + GTK_ARG_READABLE, + ARG_POINTER_INSIDE); +} + +void +nautilus_clickable_image_initialize (NautilusClickableImage *image) +{ + image->details = g_new0 (NautilusClickableImageDetails, 1); +} + +/* GtkObjectClass methods */ +static void +nautilus_clickable_image_destroy (GtkObject *object) +{ + NautilusClickableImage *clickable_image; + + g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (object)); + + clickable_image = NAUTILUS_CLICKABLE_IMAGE (object); + + g_free (clickable_image->details); + + /* Chain destroy */ + NAUTILUS_CALL_PARENT_CLASS (GTK_OBJECT_CLASS, destroy, (object)); +} + +static void +nautilus_clickable_image_get_arg (GtkObject *object, + GtkArg *arg, + guint arg_id) +{ + NautilusClickableImage *clickable_image; + + g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (object)); + + clickable_image = NAUTILUS_CLICKABLE_IMAGE (object); + + switch (arg_id) + { + case ARG_POINTER_INSIDE: + GTK_VALUE_BOOL (*arg) = clickable_image->details->pointer_inside; + break; + + default: + g_assert_not_reached (); + } +} + +/* GtkWidgetClass methods */ +static void +nautilus_clickable_image_realize (GtkWidget *widget) +{ + NautilusClickableImage *clickable_image; + GtkWidget *windowed_ancestor; + + g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (widget)); + + clickable_image = NAUTILUS_CLICKABLE_IMAGE (widget); + + /* Chain realize */ + NAUTILUS_CALL_PARENT_CLASS (GTK_WIDGET_CLASS, realize, (widget)); + + windowed_ancestor = nautilus_gtk_widget_find_windowed_ancestor (widget); + g_assert (GTK_IS_WIDGET (windowed_ancestor)); + + gtk_widget_add_events (windowed_ancestor, + GDK_BUTTON_PRESS_MASK + | GDK_BUTTON_RELEASE_MASK + | GDK_ENTER_NOTIFY_MASK + | GDK_LEAVE_NOTIFY_MASK + | GDK_POINTER_MOTION_MASK); + + gtk_signal_connect_while_alive (GTK_OBJECT (windowed_ancestor), + "enter_notify_event", + GTK_SIGNAL_FUNC (ancestor_enter_notify_event), + widget, + GTK_OBJECT (widget)); + + gtk_signal_connect_while_alive (GTK_OBJECT (windowed_ancestor), + "leave_notify_event", + GTK_SIGNAL_FUNC (ancestor_leave_notify_event), + widget, + GTK_OBJECT (widget)); + + gtk_signal_connect_while_alive (GTK_OBJECT (windowed_ancestor), + "motion_notify_event", + GTK_SIGNAL_FUNC (ancestor_motion_notify_event), + widget, + GTK_OBJECT (widget)); + + gtk_signal_connect_while_alive (GTK_OBJECT (windowed_ancestor), + "button_press_event", + GTK_SIGNAL_FUNC (ancestor_button_press_event), + widget, + GTK_OBJECT (widget)); + + gtk_signal_connect_while_alive (GTK_OBJECT (windowed_ancestor), + "button_release_event", + GTK_SIGNAL_FUNC (ancestor_button_release_event), + widget, + GTK_OBJECT (widget)); +} + +static void +nautilus_clickable_image_unrealize (GtkWidget *widget) +{ + NautilusClickableImage *clickable_image; + GtkWidget *windowed_ancestor; + + g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (widget)); + + clickable_image = NAUTILUS_CLICKABLE_IMAGE (widget); + + windowed_ancestor = nautilus_gtk_widget_find_windowed_ancestor (widget); + g_assert (GTK_IS_WIDGET (windowed_ancestor)); + + gtk_signal_disconnect_by_func (GTK_OBJECT (windowed_ancestor), + GTK_SIGNAL_FUNC (ancestor_enter_notify_event), + widget); + + gtk_signal_disconnect_by_func (GTK_OBJECT (windowed_ancestor), + GTK_SIGNAL_FUNC (ancestor_leave_notify_event), + widget); + + gtk_signal_disconnect_by_func (GTK_OBJECT (windowed_ancestor), + GTK_SIGNAL_FUNC (ancestor_motion_notify_event), + widget); + + gtk_signal_disconnect_by_func (GTK_OBJECT (windowed_ancestor), + GTK_SIGNAL_FUNC (ancestor_button_press_event), + widget); + + gtk_signal_disconnect_by_func (GTK_OBJECT (windowed_ancestor), + GTK_SIGNAL_FUNC (ancestor_button_release_event), + widget); + + /* Chain unrealize */ + NAUTILUS_CALL_PARENT_CLASS (GTK_WIDGET_CLASS, unrealize, (widget)); +} + +static void +label_enter (NautilusClickableImage *clickable_image) +{ + g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (clickable_image)); + + clickable_image->details->pointer_inside = TRUE; + + gtk_widget_set_state (GTK_WIDGET (clickable_image), GTK_STATE_PRELIGHT); + gtk_widget_queue_draw (GTK_WIDGET (clickable_image)); + + gtk_signal_emit (GTK_OBJECT (clickable_image), + clickable_image_signals[ENTER], + clickable_image); + +} + +static void +label_leave (NautilusClickableImage *clickable_image) +{ + g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (clickable_image)); + + clickable_image->details->pointer_inside = FALSE; + + gtk_widget_set_state (GTK_WIDGET (clickable_image), GTK_STATE_NORMAL); + gtk_widget_queue_draw (GTK_WIDGET (clickable_image)); + + gtk_signal_emit (GTK_OBJECT (clickable_image), + clickable_image_signals[LEAVE], + clickable_image); +} + +static void +label_handle_motion (NautilusClickableImage *clickable_image, + int x, + int y) +{ + ArtIRect bounds; + + g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (clickable_image)); + + bounds = nautilus_irect_gtk_widget_get_bounds (GTK_WIDGET (clickable_image)); + + if (nautilus_art_irect_contains_point (&bounds, x, y)) { + /* Inside */ + if (!clickable_image->details->pointer_inside) { + label_enter (clickable_image); + } + } else { + /* Outside */ + if (clickable_image->details->pointer_inside) { + label_leave (clickable_image); + } + } +} + +static void +label_handle_button_press (NautilusClickableImage *clickable_image) +{ + g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (clickable_image)); + + gtk_widget_set_state (GTK_WIDGET (clickable_image), GTK_STATE_ACTIVE); + gtk_widget_queue_draw (GTK_WIDGET (clickable_image)); +} + +static void +label_handle_button_release (NautilusClickableImage *clickable_image) +{ + g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (clickable_image)); + + gtk_widget_set_state (GTK_WIDGET (clickable_image), GTK_STATE_PRELIGHT); + gtk_widget_queue_draw (GTK_WIDGET (clickable_image)); + + gtk_signal_emit (GTK_OBJECT (clickable_image), + clickable_image_signals[CLICKED], + clickable_image); +} + +static int +ancestor_enter_notify_event (GtkWidget *widget, + GdkEventCrossing *event, + gpointer event_data) +{ + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); + g_return_val_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (event_data), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + label_handle_motion (NAUTILUS_CLICKABLE_IMAGE (event_data), event->x, event->y); + + return FALSE; +} + +static int +ancestor_leave_notify_event (GtkWidget *widget, + GdkEventCrossing *event, + gpointer event_data) +{ + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); + g_return_val_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (event_data), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + label_handle_motion (NAUTILUS_CLICKABLE_IMAGE (event_data), event->x, event->y); + + return FALSE; +} + +static int +ancestor_motion_notify_event (GtkWidget *widget, + GdkEventMotion *event, + gpointer event_data) +{ + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); + g_return_val_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (event_data), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + label_handle_motion (NAUTILUS_CLICKABLE_IMAGE (event_data), event->x, event->y); + + return FALSE; +} + +static int +ancestor_button_press_event (GtkWidget *widget, + GdkEventButton *event, + gpointer event_data) +{ + NautilusClickableImage *clickable_image; + + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); + g_return_val_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (event_data), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + clickable_image = NAUTILUS_CLICKABLE_IMAGE (event_data); + + if (clickable_image->details->pointer_inside) { + label_handle_button_press (NAUTILUS_CLICKABLE_IMAGE (event_data)); + } + + return FALSE; +} + +static int +ancestor_button_release_event (GtkWidget *widget, + GdkEventButton *event, + gpointer event_data) +{ + NautilusClickableImage *clickable_image; + + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); + g_return_val_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (event_data), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + clickable_image = NAUTILUS_CLICKABLE_IMAGE (event_data); + + if (clickable_image->details->pointer_inside) { + label_handle_button_release (NAUTILUS_CLICKABLE_IMAGE (event_data)); + } + + return FALSE; +} + +static int +nautilus_clickable_image_expose_event (GtkWidget *widget, + GdkEventExpose *event) +{ + NautilusClickableImage *clickable_image; + + g_return_val_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (widget), TRUE); + g_return_val_if_fail (event != NULL, TRUE); + g_return_val_if_fail (event->window == widget->window, TRUE); + g_return_val_if_fail (GTK_WIDGET_REALIZED (widget), TRUE); + + clickable_image = NAUTILUS_CLICKABLE_IMAGE (widget); + + /* Chain expose */ + return NAUTILUS_CALL_PARENT_CLASS (GTK_WIDGET_CLASS, expose_event, (widget, event)); +} + +/* Public NautilusClickableImage methods */ + +/** + * nautilus_clickable_image_new: + * + * @text: Text for label or NULL. + * @pixbuf: A GdkPixbuf to or NULL. + + * Create a clickable image with a solid background. + * + * Return value: The newly allocated NautilusClickableImage with the + * given text and pixbuf. Either of these two can be NULL. + */ +GtkWidget* +nautilus_clickable_image_new (const char *text, + GdkPixbuf *pixbuf) +{ + NautilusClickableImage *clickable_image; + + clickable_image = NAUTILUS_CLICKABLE_IMAGE (gtk_widget_new (nautilus_clickable_image_get_type (), NULL)); + + if (pixbuf != NULL) { + nautilus_labeled_image_set_pixbuf (NAUTILUS_LABELED_IMAGE (clickable_image), pixbuf); + } + + if (text != NULL) { + nautilus_labeled_image_set_text (NAUTILUS_LABELED_IMAGE (clickable_image), text); + } + + return GTK_WIDGET (clickable_image); +} + +/** + * nautilus_clickable_image_new_solid: + * + * @text: Text for label or NULL. + * @pixbuf: A GdkPixbuf to or NULL. + * @drop_shadow_offset: Drop shadow offset. + * @drop_shadow_color: Drop shadow color. + * @text_color: Text color. + * @x_alignment: Horizontal alignment. + * @y_alignmtn: Vertical alignment. + * @x_padding: Horizontal padding. + * @y_padding: Vertical padding. + * @background_color: Background color. + * @tile_pixbuf: A GdkPixbuf or NULL. + * + * Create a clickable image with a solid background. + * + * Return value: The newly allocated NautilusClickableImage with the + * given attributes. + */ +GtkWidget * +nautilus_clickable_image_new_solid (const char *text, + GdkPixbuf *pixbuf, + guint drop_shadow_offset, + guint32 drop_shadow_color, + guint32 text_color, + float x_alignment, + float y_alignment, + int x_padding, + int y_padding, + guint32 background_color, + GdkPixbuf *tile_pixbuf) +{ + NautilusClickableImage *clickable_image; + NautilusLabeledImage *labeled_image; + + clickable_image = NAUTILUS_CLICKABLE_IMAGE (gtk_widget_new (nautilus_clickable_image_get_type (), NULL)); + + labeled_image = NAUTILUS_LABELED_IMAGE (clickable_image); + + if (pixbuf != NULL) { + nautilus_labeled_image_set_pixbuf (labeled_image, pixbuf); + } + + if (text != NULL) { + nautilus_labeled_image_set_text (labeled_image, text); + } + + nautilus_labeled_image_set_background_mode (labeled_image, NAUTILUS_SMOOTH_BACKGROUND_SOLID_COLOR); + nautilus_labeled_image_set_solid_background_color (labeled_image, background_color); + nautilus_labeled_image_set_smooth_drop_shadow_color (labeled_image, drop_shadow_color); + nautilus_labeled_image_set_smooth_drop_shadow_offset (labeled_image, drop_shadow_offset); + nautilus_labeled_image_set_text_color (labeled_image, text_color); + + if (tile_pixbuf != NULL) { + nautilus_labeled_image_set_tile_pixbuf (labeled_image, tile_pixbuf); + } + + nautilus_labeled_image_set_x_padding (labeled_image, x_padding); + nautilus_labeled_image_set_y_padding (labeled_image, y_padding); + nautilus_labeled_image_set_x_alignment (labeled_image, x_alignment); + nautilus_labeled_image_set_y_alignment (labeled_image, y_alignment); + + return GTK_WIDGET (clickable_image); +} + + diff --git a/libnautilus-private/nautilus-clickable-image.h b/libnautilus-private/nautilus-clickable-image.h new file mode 100644 index 000000000..387743073 --- /dev/null +++ b/libnautilus-private/nautilus-clickable-image.h @@ -0,0 +1,94 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ + +/* nautilus-clickable-image.h - A clickable image widget. + + Copyright (C) 2000 Eazel, Inc. + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Authors: Ramiro Estrugo <ramiro@eazel.com> +*/ + +/* NautilusClickableImage is a NautilusLabeledImage sublclass that can handle + * event useful for detect click events. + * + * The following signals are provided by NautilusClickableImage: + * + * "clicked" - Widget was clicked + * "enter" - Pointer entered widget. + * "leave" - Pointer left widget. + * + * NautilusClickableImage is a NO_WINDOW widget. It does it event detection + * by monitoring events on the first windowed ancestor in its widget hierarchy. + * + * Being a NO_WINDOW widget, it will work nicely with tile_pixbufs. + */ + +#ifndef NAUTILUS_CLICKABLE_IMAGE_H +#define NAUTILUS_CLICKABLE_IMAGE_H + +#include <libnautilus-extensions/nautilus-labeled-image.h> + +BEGIN_GNOME_DECLS + +#define NAUTILUS_TYPE_CLICKABLE_IMAGE (nautilus_clickable_image_get_type ()) +#define NAUTILUS_CLICKABLE_IMAGE(obj) (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_CLICKABLE_IMAGE, NautilusClickableImage)) +#define NAUTILUS_CLICKABLE_IMAGE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_CLICKABLE_IMAGE, NautilusClickableImageClass)) +#define NAUTILUS_IS_CLICKABLE_IMAGE(obj) (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_CLICKABLE_IMAGE)) +#define NAUTILUS_IS_CLICKABLE_IMAGE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_CLICKABLE_IMAGE)) + +typedef struct _NautilusClickableImage NautilusClickableImage; +typedef struct _NautilusClickableImageClass NautilusClickableImageClass; +typedef struct _NautilusClickableImageDetails NautilusClickableImageDetails; + +struct _NautilusClickableImage +{ + /* Superclass */ + NautilusLabeledImage labeled_image; + + /* Private things */ + NautilusClickableImageDetails *details; +}; + +struct _NautilusClickableImageClass +{ + NautilusLabeledImageClass parent_class; + + void (*clicked) (NautilusClickableImage *image); + void (*enter) (NautilusClickableImage *image); + void (*leave) (NautilusClickableImage *image); +}; + +GtkType nautilus_clickable_image_get_type (void); +GtkWidget *nautilus_clickable_image_new (const char *text, + GdkPixbuf *pixbuf); +GtkWidget *nautilus_clickable_image_new_solid (const char *text, + GdkPixbuf *pixbuf, + guint drop_shadow_offset, + guint32 drop_shadow_color, + guint32 text_color, + float x_alignment, + float y_alignment, + int x_padding, + int y_padding, + guint32 background_color, + GdkPixbuf *tile_pixbuf); + +END_GNOME_DECLS + +#endif /* NAUTILUS_CLICKABLE_IMAGE_H */ + + diff --git a/libnautilus-private/nautilus-image.c b/libnautilus-private/nautilus-image.c index c3b326d58..746046a36 100644 --- a/libnautilus-private/nautilus-image.c +++ b/libnautilus-private/nautilus-image.c @@ -63,7 +63,7 @@ typedef enum static guint image_signals[LAST_SIGNAL] = { 0 }; /* Detail member struct */ -struct _NautilusImageDetail +struct _NautilusImageDetails { gboolean is_smooth; @@ -82,6 +82,7 @@ struct _NautilusImageDetail /* Background */ NautilusSmoothBackgroundMode background_mode; guint32 solid_background_color; + gboolean never_smooth; }; /* GtkObjectClass methods */ @@ -108,6 +109,7 @@ static void nautilus_image_set_is_smooth_signal (GtkWidget *widget static ArtIRect image_get_pixbuf_frame (const NautilusImage *image); static ArtIRect image_get_pixbuf_bounds (const NautilusImage *image); static ArtIRect image_get_tile_frame (const NautilusImage *image); +static gboolean image_is_smooth (const NautilusImage *image); NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusImage, nautilus_image, GTK_TYPE_MISC) @@ -204,15 +206,15 @@ nautilus_image_initialize (NautilusImage *image) GTK_WIDGET_UNSET_FLAGS (image, GTK_CAN_FOCUS); GTK_WIDGET_SET_FLAGS (image, GTK_NO_WINDOW); - image->detail = g_new0 (NautilusImageDetail, 1); + image->details = g_new0 (NautilusImageDetails, 1); - image->detail->pixbuf_opacity = NAUTILUS_OPACITY_FULLY_OPAQUE; - image->detail->tile_opacity = NAUTILUS_OPACITY_FULLY_OPAQUE; - image->detail->tile_width = NAUTILUS_SMOOTH_TILE_EXTENT_FULL; - image->detail->tile_height = NAUTILUS_SMOOTH_TILE_EXTENT_FULL; - image->detail->tile_mode_vertical = NAUTILUS_SMOOTH_TILE_SELF; - image->detail->tile_mode_horizontal = NAUTILUS_SMOOTH_TILE_SELF; - image->detail->background_mode = NAUTILUS_SMOOTH_BACKGROUND_GTK; + image->details->pixbuf_opacity = NAUTILUS_OPACITY_FULLY_OPAQUE; + image->details->tile_opacity = NAUTILUS_OPACITY_FULLY_OPAQUE; + image->details->tile_width = NAUTILUS_SMOOTH_TILE_EXTENT_FULL; + image->details->tile_height = NAUTILUS_SMOOTH_TILE_EXTENT_FULL; + image->details->tile_mode_vertical = NAUTILUS_SMOOTH_TILE_SELF; + image->details->tile_mode_horizontal = NAUTILUS_SMOOTH_TILE_SELF; + image->details->background_mode = NAUTILUS_SMOOTH_BACKGROUND_GTK; nautilus_smooth_widget_register (GTK_WIDGET (image)); } @@ -227,10 +229,10 @@ nautilus_image_destroy (GtkObject *object) image = NAUTILUS_IMAGE (object); - nautilus_gdk_pixbuf_unref_if_not_null (image->detail->tile_pixbuf); - image->detail->tile_pixbuf = NULL; + nautilus_gdk_pixbuf_unref_if_not_null (image->details->tile_pixbuf); + image->details->tile_pixbuf = NULL; - g_free (image->detail); + g_free (image->details); /* Chain destroy */ NAUTILUS_CALL_PARENT_CLASS (GTK_OBJECT_CLASS, destroy, (object)); @@ -373,8 +375,8 @@ nautilus_image_size_request (GtkWidget *widget, preferred_frame = nautilus_smooth_widget_get_preferred_frame (widget, &pixbuf_frame, &tile_frame, - image->detail->tile_width, - image->detail->tile_height); + image->details->tile_width, + image->details->tile_height); requisition->width = preferred_frame.x1; requisition->height = preferred_frame.y1; } @@ -398,9 +400,9 @@ image_paint_pixbuf_callback (GtkWidget *widget, image = NAUTILUS_IMAGE (widget); - g_return_if_fail (nautilus_gdk_pixbuf_is_valid (image->detail->pixbuf)); + g_return_if_fail (nautilus_gdk_pixbuf_is_valid (image->details->pixbuf)); - nautilus_gdk_pixbuf_draw_to_drawable (image->detail->pixbuf, + nautilus_gdk_pixbuf_draw_to_drawable (image->details->pixbuf, destination_drawable, gc, source_x, @@ -429,9 +431,9 @@ image_composite_pixbuf_callback (GtkWidget *widget, image = NAUTILUS_IMAGE (widget); - g_return_if_fail (nautilus_gdk_pixbuf_is_valid (image->detail->pixbuf)); + g_return_if_fail (nautilus_gdk_pixbuf_is_valid (image->details->pixbuf)); - nautilus_gdk_pixbuf_draw_to_pixbuf_alpha (image->detail->pixbuf, + nautilus_gdk_pixbuf_draw_to_pixbuf_alpha (image->details->pixbuf, destination_pixbuf, source_x, source_y, @@ -460,12 +462,12 @@ nautilus_image_expose_event (GtkWidget *widget, pixbuf_bounds = image_get_pixbuf_bounds (image); tile_bounds = nautilus_smooth_widget_get_tile_bounds (widget, - image->detail->tile_pixbuf, - image->detail->tile_width, - image->detail->tile_height); + image->details->tile_pixbuf, + image->details->tile_width, + image->details->tile_height); /* Check for the dumb case when theres nothing to do */ - if (image->detail->pixbuf == NULL && image->detail->tile_pixbuf == NULL) { + if (image->details->pixbuf == NULL && image->details->tile_pixbuf == NULL) { return TRUE; } @@ -481,16 +483,16 @@ nautilus_image_expose_event (GtkWidget *widget, /* Paint ourselves */ nautilus_smooth_widget_paint (widget, widget->style->white_gc, - image->detail->is_smooth, - image->detail->background_mode, - image->detail->solid_background_color, - image->detail->tile_pixbuf, + image_is_smooth (image), + image->details->background_mode, + image->details->solid_background_color, + image->details->tile_pixbuf, &tile_bounds, - image->detail->tile_opacity, - image->detail->tile_mode_vertical, - image->detail->tile_mode_horizontal, + image->details->tile_opacity, + image->details->tile_mode_vertical, + image->details->tile_mode_horizontal, &pixbuf_bounds, - image->detail->pixbuf_opacity, + image->details->pixbuf_opacity, &screen_dirty_area, image_paint_pixbuf_callback, image_composite_pixbuf_callback, @@ -517,14 +519,14 @@ image_get_pixbuf_frame (const NautilusImage *image) g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), NAUTILUS_ART_IRECT_EMPTY); - if (!image->detail->pixbuf) { + if (!image->details->pixbuf) { return NAUTILUS_ART_IRECT_EMPTY; } pixbuf_frame.x0 = 0; pixbuf_frame.y0 = 0; - pixbuf_frame.x1 = gdk_pixbuf_get_width (image->detail->pixbuf); - pixbuf_frame.y1 = gdk_pixbuf_get_height (image->detail->pixbuf); + pixbuf_frame.x1 = gdk_pixbuf_get_width (image->details->pixbuf); + pixbuf_frame.y1 = gdk_pixbuf_get_height (image->details->pixbuf); return pixbuf_frame; } @@ -550,9 +552,7 @@ image_get_pixbuf_bounds (const NautilusImage *image) pixbuf_frame.x1, pixbuf_frame.y1, GTK_MISC (image)->xalign, - GTK_MISC (image)->yalign, - GTK_MISC (image)->xpad, - GTK_MISC (image)->ypad); + GTK_MISC (image)->yalign); return pixbuf_bounds; } @@ -564,18 +564,26 @@ image_get_tile_frame (const NautilusImage *image) g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), NAUTILUS_ART_IRECT_EMPTY); - if (!image->detail->tile_pixbuf) { + if (!image->details->tile_pixbuf) { return NAUTILUS_ART_IRECT_EMPTY; } tile_frame.x0 = 0; tile_frame.y0 = 0; - tile_frame.x1 = gdk_pixbuf_get_width (image->detail->tile_pixbuf); - tile_frame.y1 = gdk_pixbuf_get_height (image->detail->tile_pixbuf); + tile_frame.x1 = gdk_pixbuf_get_width (image->details->tile_pixbuf); + tile_frame.y1 = gdk_pixbuf_get_height (image->details->tile_pixbuf); return tile_frame; } +gboolean +image_is_smooth (const NautilusImage *image) +{ + g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), FALSE); + + return !image->details->never_smooth && image->details->is_smooth; +} + /* Public NautilusImage methods */ GtkWidget* nautilus_image_new (const char *file_name) @@ -597,11 +605,15 @@ nautilus_image_set_is_smooth (NautilusImage *image, { g_return_if_fail (NAUTILUS_IS_IMAGE (image)); - if (image->detail->is_smooth == is_smooth) { + if (image->details->never_smooth) { return; } - image->detail->is_smooth = is_smooth; + if (image->details->is_smooth == is_smooth) { + return; + } + + image->details->is_smooth = is_smooth; /* We call queue_resize() instead queue_draw() because * we want the widget's background to be cleared of @@ -616,7 +628,7 @@ nautilus_image_get_is_smooth (const NautilusImage *image) { g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), FALSE); - return image->detail->is_smooth; + return image_is_smooth (image); } /** @@ -634,11 +646,11 @@ nautilus_image_set_tile_pixbuf (NautilusImage *image, { g_return_if_fail (NAUTILUS_IS_IMAGE (image)); - if (pixbuf != image->detail->tile_pixbuf) { - nautilus_gdk_pixbuf_unref_if_not_null (image->detail->tile_pixbuf); + if (pixbuf != image->details->tile_pixbuf) { + nautilus_gdk_pixbuf_unref_if_not_null (image->details->tile_pixbuf); nautilus_gdk_pixbuf_ref_if_not_null (pixbuf); - image->detail->tile_pixbuf = pixbuf; + image->details->tile_pixbuf = pixbuf; gtk_widget_queue_draw (GTK_WIDGET (image)); } @@ -657,9 +669,9 @@ nautilus_image_get_tile_pixbuf (const NautilusImage *image) { g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), NULL); - nautilus_gdk_pixbuf_ref_if_not_null (image->detail->tile_pixbuf); + nautilus_gdk_pixbuf_ref_if_not_null (image->details->tile_pixbuf); - return image->detail->tile_pixbuf; + return image->details->tile_pixbuf; } void @@ -668,10 +680,10 @@ nautilus_image_set_pixbuf (NautilusImage *image, { g_return_if_fail (NAUTILUS_IS_IMAGE (image)); - if (pixbuf != image->detail->pixbuf) { - nautilus_gdk_pixbuf_unref_if_not_null (image->detail->pixbuf); + if (pixbuf != image->details->pixbuf) { + nautilus_gdk_pixbuf_unref_if_not_null (image->details->pixbuf); nautilus_gdk_pixbuf_ref_if_not_null (pixbuf); - image->detail->pixbuf = pixbuf; + image->details->pixbuf = pixbuf; gtk_widget_queue_resize (GTK_WIDGET (image)); } } @@ -698,9 +710,9 @@ nautilus_image_get_pixbuf (const NautilusImage *image) { g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), NULL); - nautilus_gdk_pixbuf_ref_if_not_null (image->detail->pixbuf); + nautilus_gdk_pixbuf_ref_if_not_null (image->details->pixbuf); - return image->detail->pixbuf; + return image->details->pixbuf; } void @@ -711,11 +723,11 @@ nautilus_image_set_pixbuf_opacity (NautilusImage *image, g_return_if_fail (pixbuf_opacity >= NAUTILUS_OPACITY_FULLY_TRANSPARENT); g_return_if_fail (pixbuf_opacity <= NAUTILUS_OPACITY_FULLY_OPAQUE); - if (image->detail->pixbuf_opacity == pixbuf_opacity) { + if (image->details->pixbuf_opacity == pixbuf_opacity) { return; } - image->detail->pixbuf_opacity = pixbuf_opacity; + image->details->pixbuf_opacity = pixbuf_opacity; gtk_widget_queue_draw (GTK_WIDGET (image)); } @@ -725,7 +737,7 @@ nautilus_image_get_pixbuf_opacity (const NautilusImage *image) { g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), NAUTILUS_OPACITY_FULLY_OPAQUE); - return image->detail->pixbuf_opacity; + return image->details->pixbuf_opacity; } void @@ -736,11 +748,11 @@ nautilus_image_set_tile_opacity (NautilusImage *image, g_return_if_fail (tile_opacity >= NAUTILUS_OPACITY_FULLY_TRANSPARENT); g_return_if_fail (tile_opacity <= NAUTILUS_OPACITY_FULLY_OPAQUE); - if (image->detail->tile_opacity == tile_opacity) { + if (image->details->tile_opacity == tile_opacity) { return; } - image->detail->tile_opacity = tile_opacity; + image->details->tile_opacity = tile_opacity; gtk_widget_queue_draw (GTK_WIDGET (image)); } @@ -750,7 +762,7 @@ nautilus_image_get_tile_opacity (const NautilusImage *image) { g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), NAUTILUS_OPACITY_FULLY_OPAQUE); - return image->detail->tile_opacity; + return image->details->tile_opacity; } void @@ -760,11 +772,11 @@ nautilus_image_set_tile_width (NautilusImage *image, g_return_if_fail (NAUTILUS_IS_IMAGE (image)); g_return_if_fail (tile_width >= NAUTILUS_SMOOTH_TILE_EXTENT_ONE_STEP); - if (image->detail->tile_width == tile_width) { + if (image->details->tile_width == tile_width) { return; } - image->detail->tile_width = tile_width; + image->details->tile_width = tile_width; gtk_widget_queue_resize (GTK_WIDGET (image)); } @@ -781,7 +793,7 @@ nautilus_image_get_tile_width (const NautilusImage *image) { g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), 0); - return image->detail->tile_width; + return image->details->tile_width; } void @@ -791,11 +803,11 @@ nautilus_image_set_tile_height (NautilusImage *image, g_return_if_fail (NAUTILUS_IS_IMAGE (image)); g_return_if_fail (tile_height >= NAUTILUS_SMOOTH_TILE_EXTENT_ONE_STEP); - if (image->detail->tile_height == tile_height) { + if (image->details->tile_height == tile_height) { return; } - image->detail->tile_height = tile_height; + image->details->tile_height = tile_height; gtk_widget_queue_resize (GTK_WIDGET (image)); } @@ -812,7 +824,7 @@ nautilus_image_get_tile_height (const NautilusImage *image) { g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), 0); - return image->detail->tile_height; + return image->details->tile_height; } void @@ -823,11 +835,11 @@ nautilus_image_set_tile_mode_vertical (NautilusImage *image, g_return_if_fail (tile_mode_vertical >= NAUTILUS_SMOOTH_TILE_SELF); g_return_if_fail (tile_mode_vertical <= NAUTILUS_SMOOTH_TILE_ANCESTOR); - if (image->detail->tile_mode_vertical == tile_mode_vertical) { + if (image->details->tile_mode_vertical == tile_mode_vertical) { return; } - image->detail->tile_mode_vertical = tile_mode_vertical; + image->details->tile_mode_vertical = tile_mode_vertical; gtk_widget_queue_draw (GTK_WIDGET (image)); } @@ -837,7 +849,7 @@ nautilus_image_get_tile_mode_vertical (const NautilusImage *image) { g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), 0); - return image->detail->tile_mode_vertical; + return image->details->tile_mode_vertical; } void @@ -848,11 +860,11 @@ nautilus_image_set_tile_mode_horizontal (NautilusImage *image, g_return_if_fail (tile_mode_horizontal >= NAUTILUS_SMOOTH_TILE_SELF); g_return_if_fail (tile_mode_horizontal <= NAUTILUS_SMOOTH_TILE_ANCESTOR); - if (image->detail->tile_mode_horizontal == tile_mode_horizontal) { + if (image->details->tile_mode_horizontal == tile_mode_horizontal) { return; } - image->detail->tile_mode_horizontal = tile_mode_horizontal; + image->details->tile_mode_horizontal = tile_mode_horizontal; gtk_widget_queue_draw (GTK_WIDGET (image)); } @@ -862,7 +874,7 @@ nautilus_image_get_tile_mode_horizontal (const NautilusImage *image) { g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), 0); - return image->detail->tile_mode_horizontal; + return image->details->tile_mode_horizontal; } void @@ -890,11 +902,11 @@ nautilus_image_set_background_mode (NautilusImage *image, g_return_if_fail (background_mode >= NAUTILUS_SMOOTH_BACKGROUND_GTK); g_return_if_fail (background_mode <= NAUTILUS_SMOOTH_BACKGROUND_SOLID_COLOR); - if (image->detail->background_mode == background_mode) { + if (image->details->background_mode == background_mode) { return; } - image->detail->background_mode = background_mode; + image->details->background_mode = background_mode; gtk_widget_queue_draw (GTK_WIDGET (image)); } @@ -904,7 +916,7 @@ nautilus_image_get_background_mode (const NautilusImage *image) { g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), 0); - return image->detail->background_mode; + return image->details->background_mode; } void @@ -913,11 +925,11 @@ nautilus_image_set_solid_background_color (NautilusImage *image, { g_return_if_fail (NAUTILUS_IS_IMAGE (image)); - if (image->detail->solid_background_color == solid_background_color) { + if (image->details->solid_background_color == solid_background_color) { return; } - image->detail->solid_background_color = solid_background_color; + image->details->solid_background_color = solid_background_color; gtk_widget_queue_draw (GTK_WIDGET (image)); } @@ -927,17 +939,17 @@ nautilus_image_get_solid_background_color (const NautilusImage *image) { g_return_val_if_fail (NAUTILUS_IS_IMAGE (image), 0); - return image->detail->solid_background_color; + return image->details->solid_background_color; } /** * nautilus_image_new_solid: * * @pixbuf: A GdkPixbuf or NULL. - * @xalign: Horizontal alignment. - * @yalign: Vertical alignment. - * @xpadding: Horizontal padding. - * @ypadding: Vertical padding. + * @x_alignment: Horizontal alignment. + * @y_alignment: Vertical alignment. + * @x_padding: Horizontal padding. + * @y_padding: Vertical padding. * @background_color: Background color. * @tile_pixbuf: A GdkPixbuf or NULL. * @@ -948,10 +960,10 @@ nautilus_image_get_solid_background_color (const NautilusImage *image) */ GtkWidget * nautilus_image_new_solid (GdkPixbuf *pixbuf, - float xalign, - float yalign, - int xpadding, - int ypadding, + float x_alignment, + float y_alignment, + int x_padding, + int y_padding, guint32 background_color, GdkPixbuf *tile_pixbuf) { @@ -963,16 +975,36 @@ nautilus_image_new_solid (GdkPixbuf *pixbuf, nautilus_image_set_pixbuf (image, pixbuf); } - nautilus_image_set_background_mode (NAUTILUS_IMAGE (image), NAUTILUS_SMOOTH_BACKGROUND_SOLID_COLOR); - nautilus_image_set_solid_background_color (NAUTILUS_IMAGE (image), background_color); + nautilus_image_set_background_mode (image, NAUTILUS_SMOOTH_BACKGROUND_SOLID_COLOR); + nautilus_image_set_solid_background_color (image, background_color); - gtk_misc_set_padding (GTK_MISC (image), xpadding, ypadding); - gtk_misc_set_alignment (GTK_MISC (image), xalign, yalign); + gtk_misc_set_padding (GTK_MISC (image), x_padding, y_padding); + gtk_misc_set_alignment (GTK_MISC (image), x_alignment, y_alignment); if (tile_pixbuf != NULL) { - nautilus_image_set_tile_pixbuf (NAUTILUS_IMAGE (image), tile_pixbuf); + nautilus_image_set_tile_pixbuf (image, tile_pixbuf); } return GTK_WIDGET (image); } + +/** + * nautilus_image_set_never_smooth + * + * @image: A NautilusImage. + * @never_smooth: A boolean value indicating whether the image can NEVER be smooth. + * + * Force an image to never be smooth. Calls to nautilus_image_set_is_smooth () will + * thus be ignored. This is useful if you want to use a NautilusImage in a situation. + */ +void +nautilus_image_set_never_smooth (NautilusImage *image, + gboolean never_smooth) +{ + g_return_if_fail (NAUTILUS_IS_IMAGE (image)); + + image->details->never_smooth = never_smooth; + gtk_widget_queue_resize (GTK_WIDGET (image)); +} + diff --git a/libnautilus-private/nautilus-image.h b/libnautilus-private/nautilus-image.h index 05ce361c0..c5ffca43c 100644 --- a/libnautilus-private/nautilus-image.h +++ b/libnautilus-private/nautilus-image.h @@ -41,7 +41,7 @@ BEGIN_GNOME_DECLS typedef struct _NautilusImage NautilusImage; typedef struct _NautilusImageClass NautilusImageClass; -typedef struct _NautilusImageDetail NautilusImageDetail; +typedef struct _NautilusImageDetails NautilusImageDetails; struct _NautilusImage { @@ -49,7 +49,7 @@ struct _NautilusImage GtkMisc misc; /* Private things */ - NautilusImageDetail *detail; + NautilusImageDetails *details; }; struct _NautilusImageClass @@ -106,6 +106,8 @@ NautilusSmoothBackgroundMode nautilus_image_get_background_mode (cons void nautilus_image_set_solid_background_color (NautilusImage *image, guint32 solid_background_color); guint32 nautilus_image_get_solid_background_color (const NautilusImage *image); +void nautilus_image_set_never_smooth (NautilusImage *image, + gboolean never_smooth); END_GNOME_DECLS diff --git a/libnautilus-private/nautilus-label.c b/libnautilus-private/nautilus-label.c index 24cc443c8..c703b691d 100644 --- a/libnautilus-private/nautilus-label.c +++ b/libnautilus-private/nautilus-label.c @@ -88,7 +88,7 @@ typedef enum static guint label_signals[LAST_SIGNAL] = { 0 }; /* Detail member struct */ -struct _NautilusLabelDetail +struct _NautilusLabelDetails { gboolean is_smooth; @@ -126,6 +126,7 @@ struct _NautilusLabelDetail guint32 solid_background_color; GdkPixbuf *solid_cache_pixbuf; + gboolean never_smooth; }; /* GtkObjectClass methods */ @@ -166,6 +167,7 @@ static void label_draw_text_to_pixbuf (NautilusLabel static guint label_get_default_line_wrap_width (const NautilusLabel *label); static void label_solid_cache_pixbuf_clear (NautilusLabel *label); static gboolean label_can_cache_contents (const NautilusLabel *label); +static gboolean label_is_smooth (const NautilusLabel *label); NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusLabel, nautilus_label, GTK_TYPE_LABEL) @@ -294,21 +296,21 @@ nautilus_label_initialize (NautilusLabel *label) GTK_WIDGET_UNSET_FLAGS (label, GTK_CAN_FOCUS); GTK_WIDGET_SET_FLAGS (label, GTK_NO_WINDOW); - label->detail = g_new0 (NautilusLabelDetail, 1); + label->details = g_new0 (NautilusLabelDetails, 1); - label->detail->text_opacity = NAUTILUS_OPACITY_FULLY_OPAQUE; - label->detail->smooth_font = nautilus_scalable_font_get_default_font (); - label->detail->smooth_font_size = DEFAULT_FONT_SIZE; - label->detail->smooth_text_color = NAUTILUS_RGBA_COLOR_PACK (0, 0, 0, 255); - label->detail->smooth_drop_shadow_color = NAUTILUS_RGBA_COLOR_PACK (255, 255, 255, 255); - label->detail->smooth_line_wrap_width = label_get_default_line_wrap_width (label); + label->details->text_opacity = NAUTILUS_OPACITY_FULLY_OPAQUE; + label->details->smooth_font = nautilus_scalable_font_get_default_font (); + label->details->smooth_font_size = DEFAULT_FONT_SIZE; + label->details->smooth_text_color = NAUTILUS_RGBA_COLOR_PACK (0, 0, 0, 255); + label->details->smooth_drop_shadow_color = NAUTILUS_RGBA_COLOR_PACK (255, 255, 255, 255); + label->details->smooth_line_wrap_width = label_get_default_line_wrap_width (label); - label->detail->tile_opacity = NAUTILUS_OPACITY_FULLY_OPAQUE; - label->detail->tile_width = NAUTILUS_SMOOTH_TILE_EXTENT_FULL; - label->detail->tile_height = NAUTILUS_SMOOTH_TILE_EXTENT_FULL; - label->detail->tile_mode_vertical = NAUTILUS_SMOOTH_TILE_SELF; - label->detail->tile_mode_horizontal = NAUTILUS_SMOOTH_TILE_SELF; - label->detail->background_mode = NAUTILUS_SMOOTH_BACKGROUND_GTK; + label->details->tile_opacity = NAUTILUS_OPACITY_FULLY_OPAQUE; + label->details->tile_width = NAUTILUS_SMOOTH_TILE_EXTENT_FULL; + label->details->tile_height = NAUTILUS_SMOOTH_TILE_EXTENT_FULL; + label->details->tile_mode_vertical = NAUTILUS_SMOOTH_TILE_SELF; + label->details->tile_mode_horizontal = NAUTILUS_SMOOTH_TILE_SELF; + label->details->background_mode = NAUTILUS_SMOOTH_BACKGROUND_GTK; nautilus_smooth_widget_register (GTK_WIDGET (label)); } @@ -323,13 +325,13 @@ nautilus_label_destroy (GtkObject *object) label = NAUTILUS_LABEL (object); - nautilus_gdk_pixbuf_unref_if_not_null (label->detail->tile_pixbuf); - label->detail->tile_pixbuf = NULL; + nautilus_gdk_pixbuf_unref_if_not_null (label->details->tile_pixbuf); + label->details->tile_pixbuf = NULL; label_solid_cache_pixbuf_clear (label); label_line_geometries_clear (label); - g_free (label->detail); + g_free (label->details); /* Chain destroy */ NAUTILUS_CALL_PARENT_CLASS (GTK_OBJECT_CLASS, destroy, (object)); @@ -533,7 +535,7 @@ nautilus_label_size_request (GtkWidget *widget, label = NAUTILUS_LABEL (widget); - if (!label->detail->is_smooth) { + if (!label_is_smooth (label)) { NAUTILUS_CALL_PARENT_CLASS (GTK_WIDGET_CLASS, size_request, (widget, requisition)); return; } @@ -544,8 +546,8 @@ nautilus_label_size_request (GtkWidget *widget, preferred_frame = nautilus_smooth_widget_get_preferred_frame (widget, &text_frame, &tile_frame, - label->detail->tile_width, - label->detail->tile_height); + label->details->tile_width, + label->details->tile_height); requisition->width = preferred_frame.x1; requisition->height = preferred_frame.y1; } @@ -610,25 +612,25 @@ label_composite_pixbuf_callback (GtkWidget *widget, /* Optimize the case where the background is solid */ if (label_can_cache_contents (label)) { - if (label->detail->solid_cache_pixbuf == NULL) { - label->detail->solid_cache_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + if (label->details->solid_cache_pixbuf == NULL) { + label->details->solid_cache_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, text_frame.x1, text_frame.y1); - nautilus_gdk_pixbuf_fill_rectangle_with_color (label->detail->solid_cache_pixbuf, + nautilus_gdk_pixbuf_fill_rectangle_with_color (label->details->solid_cache_pixbuf, NULL, - label->detail->solid_background_color); + label->details->solid_background_color); label_draw_text_to_pixbuf (label, - label->detail->solid_cache_pixbuf, + label->details->solid_cache_pixbuf, &text_frame, 0, 0); } - nautilus_gdk_pixbuf_draw_to_pixbuf (label->detail->solid_cache_pixbuf, + nautilus_gdk_pixbuf_draw_to_pixbuf (label->details->solid_cache_pixbuf, destination_pixbuf, source_x, source_y, @@ -722,12 +724,12 @@ nautilus_label_expose_event (GtkWidget *widget, widget_bounds = nautilus_irect_gtk_widget_get_bounds (widget); smooth_text_bounds = label_get_text_bounds (label); tile_bounds = nautilus_smooth_widget_get_tile_bounds (widget, - label->detail->tile_pixbuf, - label->detail->tile_width, - label->detail->tile_height); + label->details->tile_pixbuf, + label->details->tile_width, + label->details->tile_height); /* Check for the dumb case when theres nothing to do */ - if (nautilus_strlen (label_peek_text (label)) == 0 && label->detail->tile_pixbuf == NULL) { + if (nautilus_strlen (label_peek_text (label)) == 0 && label->details->tile_pixbuf == NULL) { return TRUE; } @@ -735,20 +737,21 @@ nautilus_label_expose_event (GtkWidget *widget, dirty_area = nautilus_irect_assign_gdk_rectangle (&event->area); screen_dirty_area = nautilus_irect_gdk_window_clip_dirty_area_to_screen (event->window, &dirty_area); + /* Make sure the area is screen visible before painting */ if (!art_irect_empty (&screen_dirty_area)) { nautilus_smooth_widget_paint (widget, widget->style->white_gc, - label->detail->is_smooth, - label->detail->background_mode, - label->detail->solid_background_color, - label->detail->tile_pixbuf, + label_is_smooth (label), + label->details->background_mode, + label->details->solid_background_color, + label->details->tile_pixbuf, &tile_bounds, - label->detail->tile_opacity, - label->detail->tile_mode_vertical, - label->detail->tile_mode_horizontal, - label->detail->is_smooth ? &smooth_text_bounds : &widget_bounds, - label->detail->text_opacity, + label->details->tile_opacity, + label->details->tile_mode_vertical, + label->details->tile_mode_horizontal, + label_is_smooth (label) ? &smooth_text_bounds : &widget_bounds, + label->details->text_opacity, &screen_dirty_area, label_paint_pixbuf_callback, label_composite_pixbuf_callback, @@ -792,16 +795,16 @@ label_draw_text_to_pixbuf (NautilusLabel *label, if (nautilus_label_get_wrap (label)) { int i; - for (i = 0; i < label->detail->num_text_lines; i++) { - const NautilusTextLayout *text_layout = label->detail->text_layouts[i]; + for (i = 0; i < label->details->num_text_lines; i++) { + const NautilusTextLayout *text_layout = label->details->text_layouts[i]; - if (label->detail->smooth_drop_shadow_offset > 0) { + if (label->details->smooth_drop_shadow_offset > 0) { nautilus_text_layout_paint (text_layout, pixbuf, - x + label->detail->smooth_drop_shadow_offset, - y + label->detail->smooth_drop_shadow_offset, + x + label->details->smooth_drop_shadow_offset, + y + label->details->smooth_drop_shadow_offset, nautilus_label_get_text_justify (label), - label->detail->smooth_drop_shadow_color, + label->details->smooth_drop_shadow_color, FALSE); } @@ -810,7 +813,7 @@ label_draw_text_to_pixbuf (NautilusLabel *label, x, y, nautilus_label_get_text_justify (label), - label->detail->smooth_text_color, + label->details->smooth_text_color, FALSE); y += text_layout->height; @@ -818,43 +821,43 @@ label_draw_text_to_pixbuf (NautilusLabel *label, } /* No line wrapping */ else { - if (label->detail->smooth_drop_shadow_offset > 0) { + if (label->details->smooth_drop_shadow_offset > 0) { nautilus_scalable_font_draw_text_lines_with_dimensions ( - label->detail->smooth_font, + label->details->smooth_font, pixbuf, - x + label->detail->smooth_drop_shadow_offset, - x + label->detail->smooth_drop_shadow_offset, + x + label->details->smooth_drop_shadow_offset, + x + label->details->smooth_drop_shadow_offset, destination_area, - label->detail->smooth_font_size, - label->detail->smooth_font_size, + label->details->smooth_font_size, + label->details->smooth_font_size, label_peek_text (label), - label->detail->num_text_lines, - label->detail->text_line_widths, - label->detail->text_line_heights, + label->details->num_text_lines, + label->details->text_line_widths, + label->details->text_line_heights, nautilus_label_get_text_justify (label), LINE_OFFSET, label_get_empty_line_height (label), - label->detail->smooth_drop_shadow_color, - label->detail->text_opacity); + label->details->smooth_drop_shadow_color, + label->details->text_opacity); } nautilus_scalable_font_draw_text_lines_with_dimensions ( - label->detail->smooth_font, + label->details->smooth_font, pixbuf, x, y, destination_area, - label->detail->smooth_font_size, - label->detail->smooth_font_size, + label->details->smooth_font_size, + label->details->smooth_font_size, label_peek_text (label), - label->detail->num_text_lines, - label->detail->text_line_widths, - label->detail->text_line_heights, + label->details->num_text_lines, + label->details->text_line_widths, + label->details->text_line_heights, nautilus_label_get_text_justify (label), LINE_OFFSET, label_get_empty_line_height (label), - label->detail->smooth_text_color, - label->detail->text_opacity); + label->details->smooth_text_color, + label->details->text_opacity); } } @@ -866,9 +869,9 @@ label_get_default_line_wrap_width (const NautilusLabel *label) g_return_val_if_fail (NAUTILUS_IS_LABEL (label), 0); - nautilus_scalable_font_measure_text (label->detail->smooth_font, - label->detail->smooth_font_size, - label->detail->smooth_font_size, + nautilus_scalable_font_measure_text (label->details->smooth_font, + label->details->smooth_font_size, + label->details->smooth_font_size, DEFAULT_LINE_WRAP_WIDTH_TEXT, strlen (DEFAULT_LINE_WRAP_WIDTH_TEXT), &width, @@ -886,13 +889,13 @@ label_get_text_frame (const NautilusLabel *label) text_frame = NAUTILUS_ART_IRECT_EMPTY; - if (label->detail->num_text_lines > 0) { + if (label->details->num_text_lines > 0) { text_frame.x1 = - label->detail->max_text_line_width - + label->detail->smooth_drop_shadow_offset; + label->details->max_text_line_width + + label->details->smooth_drop_shadow_offset; text_frame.y1 = label_get_total_text_and_line_offset_height (label) - + label->detail->smooth_drop_shadow_offset; + + label->details->smooth_drop_shadow_offset; } return text_frame; @@ -919,9 +922,7 @@ label_get_text_bounds (const NautilusLabel *label) text_frame.x1, text_frame.y1, GTK_MISC (label)->xalign, - GTK_MISC (label)->yalign, - GTK_MISC (label)->xpad, - GTK_MISC (label)->ypad); + GTK_MISC (label)->yalign); return text_bounds; @@ -934,14 +935,14 @@ label_get_tile_frame (const NautilusLabel *label) g_return_val_if_fail (NAUTILUS_IS_LABEL (label), NAUTILUS_ART_IRECT_EMPTY); - if (!label->detail->tile_pixbuf) { + if (!label->details->tile_pixbuf) { return NAUTILUS_ART_IRECT_EMPTY; } tile_frame.x0 = 0; tile_frame.y0 = 0; - tile_frame.x1 = gdk_pixbuf_get_width (label->detail->tile_pixbuf); - tile_frame.y1 = gdk_pixbuf_get_height (label->detail->tile_pixbuf); + tile_frame.x1 = gdk_pixbuf_get_width (label->details->tile_pixbuf); + tile_frame.y1 = gdk_pixbuf_get_height (label->details->tile_pixbuf); return tile_frame; } @@ -951,8 +952,8 @@ label_solid_cache_pixbuf_clear (NautilusLabel *label) { g_return_if_fail (NAUTILUS_IS_LABEL (label)); - nautilus_gdk_pixbuf_unref_if_not_null (label->detail->solid_cache_pixbuf); - label->detail->solid_cache_pixbuf = NULL; + nautilus_gdk_pixbuf_unref_if_not_null (label->details->solid_cache_pixbuf); + label->details->solid_cache_pixbuf = NULL; } static gboolean @@ -960,8 +961,8 @@ label_can_cache_contents (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), FALSE); - return (label->detail->background_mode == NAUTILUS_SMOOTH_BACKGROUND_SOLID_COLOR) - && !label->detail->tile_pixbuf; + return (label->details->background_mode == NAUTILUS_SMOOTH_BACKGROUND_SOLID_COLOR) + && !label->details->tile_pixbuf; } const char * @@ -979,7 +980,7 @@ label_get_empty_line_height (const NautilusLabel *label) /* If we wanted to crunch lines together, we could add a divider * here. For now we just use the font size for empty lines. */ - return label->detail->smooth_font_size; + return label->details->smooth_font_size; } static guint @@ -989,10 +990,10 @@ label_get_total_text_and_line_offset_height (const NautilusLabel *label) g_return_val_if_fail (NAUTILUS_IS_LABEL (label), 0); - total_height = label->detail->total_text_line_height; + total_height = label->details->total_text_line_height; - if (label->detail->num_text_lines > 1) { - total_height += ((label->detail->num_text_lines - 1) * LINE_OFFSET); + if (label->details->num_text_lines > 1) { + total_height += ((label->details->num_text_lines - 1) * LINE_OFFSET); } return total_height; @@ -1003,27 +1004,27 @@ label_line_geometries_clear (NautilusLabel *label) { g_return_if_fail (NAUTILUS_IS_LABEL (label)); - g_free (label->detail->text_line_widths); - g_free (label->detail->text_line_heights); - label->detail->text_line_widths = NULL; - label->detail->text_line_heights = NULL; + g_free (label->details->text_line_widths); + g_free (label->details->text_line_heights); + label->details->text_line_widths = NULL; + label->details->text_line_heights = NULL; - if (label->detail->text_layouts != NULL) { + if (label->details->text_layouts != NULL) { int i; - for (i = 0; i < label->detail->num_text_lines; i++) { - g_assert (label->detail->text_layouts[i] != NULL); - nautilus_text_layout_free (label->detail->text_layouts[i]); + for (i = 0; i < label->details->num_text_lines; i++) { + g_assert (label->details->text_layouts[i] != NULL); + nautilus_text_layout_free (label->details->text_layouts[i]); } - g_free (label->detail->text_layouts); - label->detail->text_layouts = NULL; + g_free (label->details->text_layouts); + label->details->text_layouts = NULL; } - label->detail->num_text_lines = 0; + label->details->num_text_lines = 0; - label->detail->max_text_line_width = 0; - label->detail->total_text_line_height = 0; + label->details->max_text_line_width = 0; + label->details->total_text_line_height = 0; } static void @@ -1042,38 +1043,38 @@ label_line_geometries_recompute (NautilusLabel *label) return; } - label->detail->num_text_lines = nautilus_str_count_characters (text, '\n') + 1; + label->details->num_text_lines = nautilus_str_count_characters (text, '\n') + 1; /* Line wrapping */ if (nautilus_label_get_wrap (label)) { char **pieces; int i; - label->detail->text_layouts = g_new (NautilusTextLayout *, label->detail->num_text_lines); + label->details->text_layouts = g_new (NautilusTextLayout *, label->details->num_text_lines); pieces = g_strsplit (text, "\n", 0); for (i = 0; pieces[i] != NULL; i++) { char *text_piece = pieces[i]; - g_assert (i < label->detail->num_text_lines); + g_assert (i < label->details->num_text_lines); /* Make empty lines appear. A single '\n' for example. */ if (text_piece[0] == '\0') { text_piece = " "; } - label->detail->text_layouts[i] = nautilus_text_layout_new (label->detail->smooth_font, - label->detail->smooth_font_size, + label->details->text_layouts[i] = nautilus_text_layout_new (label->details->smooth_font, + label->details->smooth_font_size, text_piece, LINE_WRAP_SEPARATORS, - label->detail->smooth_line_wrap_width, + label->details->smooth_line_wrap_width, TRUE); - label->detail->total_text_line_height += label->detail->text_layouts[i]->height; + label->details->total_text_line_height += label->details->text_layouts[i]->height; - if (label->detail->text_layouts[i]->width > label->detail->max_text_line_width) { - label->detail->max_text_line_width = label->detail->text_layouts[i]->width; + if (label->details->text_layouts[i]->width > label->details->max_text_line_width) { + label->details->max_text_line_width = label->details->text_layouts[i]->width; } } @@ -1081,22 +1082,30 @@ label_line_geometries_recompute (NautilusLabel *label) } /* No line wrapping */ else { - label->detail->text_line_widths = g_new (guint, label->detail->num_text_lines); - label->detail->text_line_heights = g_new (guint, label->detail->num_text_lines); + label->details->text_line_widths = g_new (guint, label->details->num_text_lines); + label->details->text_line_heights = g_new (guint, label->details->num_text_lines); - nautilus_scalable_font_measure_text_lines (label->detail->smooth_font, - label->detail->smooth_font_size, - label->detail->smooth_font_size, + nautilus_scalable_font_measure_text_lines (label->details->smooth_font, + label->details->smooth_font_size, + label->details->smooth_font_size, text, - label->detail->num_text_lines, + label->details->num_text_lines, label_get_empty_line_height (label), - label->detail->text_line_widths, - label->detail->text_line_heights, - &label->detail->max_text_line_width, - &label->detail->total_text_line_height); + label->details->text_line_widths, + label->details->text_line_heights, + &label->details->max_text_line_width, + &label->details->total_text_line_height); } } +gboolean +label_is_smooth (const NautilusLabel *label) +{ + g_return_val_if_fail (NAUTILUS_IS_LABEL (label), FALSE); + + return !label->details->never_smooth && label->details->is_smooth; +} + /* Public NautilusLabel methods */ GtkWidget * nautilus_label_new (const char *text) @@ -1117,19 +1126,19 @@ nautilus_label_set_smooth_font (NautilusLabel *label, g_return_if_fail (NAUTILUS_IS_LABEL (label)); g_return_if_fail (NAUTILUS_IS_SCALABLE_FONT (smooth_font)); - if (label->detail->smooth_font == smooth_font) { + if (label->details->smooth_font == smooth_font) { return; } - if (label->detail->smooth_font != NULL) { - gtk_object_unref (GTK_OBJECT (label->detail->smooth_font)); + if (label->details->smooth_font != NULL) { + gtk_object_unref (GTK_OBJECT (label->details->smooth_font)); } gtk_object_ref (GTK_OBJECT (smooth_font)); - label->detail->smooth_font = smooth_font; + label->details->smooth_font = smooth_font; /* Update the line wrap width */ - label->detail->smooth_line_wrap_width = label_get_default_line_wrap_width (label); + label->details->smooth_line_wrap_width = label_get_default_line_wrap_width (label); label_line_geometries_recompute (label); @@ -1141,11 +1150,11 @@ nautilus_label_get_smooth_font (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), NULL); - if (label->detail->smooth_font != NULL) { - gtk_object_ref (GTK_OBJECT (label->detail->smooth_font)); + if (label->details->smooth_font != NULL) { + gtk_object_ref (GTK_OBJECT (label->details->smooth_font)); } - return label->detail->smooth_font; + return label->details->smooth_font; } void @@ -1155,14 +1164,14 @@ nautilus_label_set_smooth_font_size (NautilusLabel *label, g_return_if_fail (NAUTILUS_IS_LABEL (label)); g_return_if_fail (smooth_font_size > MIN_SMOOTH_FONT_SIZE); - if (label->detail->smooth_font_size == smooth_font_size) { + if (label->details->smooth_font_size == smooth_font_size) { return; } - label->detail->smooth_font_size = smooth_font_size; + label->details->smooth_font_size = smooth_font_size; /* Update the line wrap width */ - label->detail->smooth_line_wrap_width = label_get_default_line_wrap_width (label); + label->details->smooth_line_wrap_width = label_get_default_line_wrap_width (label); label_line_geometries_recompute (label); @@ -1174,7 +1183,7 @@ nautilus_label_get_smooth_font_size (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), 0); - return label->detail->smooth_font_size; + return label->details->smooth_font_size; } /* This function is an ugly hack. The issue is that we want @@ -1213,11 +1222,15 @@ nautilus_label_set_is_smooth (NautilusLabel *label, { g_return_if_fail (NAUTILUS_IS_LABEL (label)); - if (label->detail->is_smooth == is_smooth) { + if (label->details->never_smooth) { return; } - label->detail->is_smooth = is_smooth; + if (label->details->is_smooth == is_smooth) { + return; + } + + label->details->is_smooth = is_smooth; label_line_geometries_recompute (label); @@ -1237,7 +1250,7 @@ nautilus_label_get_is_smooth (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), FALSE); - return label->detail->is_smooth; + return label_is_smooth (label); } /** @@ -1255,11 +1268,11 @@ nautilus_label_set_tile_pixbuf (NautilusLabel *label, { g_return_if_fail (NAUTILUS_IS_LABEL (label)); - if (pixbuf != label->detail->tile_pixbuf) { - nautilus_gdk_pixbuf_unref_if_not_null (label->detail->tile_pixbuf); + if (pixbuf != label->details->tile_pixbuf) { + nautilus_gdk_pixbuf_unref_if_not_null (label->details->tile_pixbuf); nautilus_gdk_pixbuf_ref_if_not_null (pixbuf); - label->detail->tile_pixbuf = pixbuf; + label->details->tile_pixbuf = pixbuf; gtk_widget_queue_resize (GTK_WIDGET (label)); } @@ -1278,9 +1291,9 @@ nautilus_label_get_tile_pixbuf (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), NULL); - nautilus_gdk_pixbuf_ref_if_not_null (label->detail->tile_pixbuf); + nautilus_gdk_pixbuf_ref_if_not_null (label->details->tile_pixbuf); - return label->detail->tile_pixbuf; + return label->details->tile_pixbuf; } void @@ -1291,7 +1304,7 @@ nautilus_label_set_text_opacity (NautilusLabel *label, g_return_if_fail (opacity >= NAUTILUS_OPACITY_FULLY_TRANSPARENT); g_return_if_fail (opacity <= NAUTILUS_OPACITY_FULLY_OPAQUE); - label->detail->text_opacity = opacity; + label->details->text_opacity = opacity; gtk_widget_queue_draw (GTK_WIDGET (label)); } @@ -1301,7 +1314,7 @@ nautilus_label_get_text_opacity (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), NAUTILUS_OPACITY_FULLY_OPAQUE); - return label->detail->text_opacity; + return label->details->text_opacity; } void @@ -1312,11 +1325,11 @@ nautilus_label_set_tile_opacity (NautilusLabel *label, g_return_if_fail (tile_opacity >= NAUTILUS_OPACITY_FULLY_TRANSPARENT); g_return_if_fail (tile_opacity <= NAUTILUS_OPACITY_FULLY_OPAQUE); - if (label->detail->tile_opacity == tile_opacity) { + if (label->details->tile_opacity == tile_opacity) { return; } - label->detail->tile_opacity = tile_opacity; + label->details->tile_opacity = tile_opacity; gtk_widget_queue_draw (GTK_WIDGET (label)); } @@ -1326,7 +1339,7 @@ nautilus_label_get_tile_opacity (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), NAUTILUS_OPACITY_FULLY_OPAQUE); - return label->detail->tile_opacity; + return label->details->tile_opacity; } void @@ -1336,11 +1349,11 @@ nautilus_label_set_tile_width (NautilusLabel *label, g_return_if_fail (NAUTILUS_IS_LABEL (label)); g_return_if_fail (tile_width >= NAUTILUS_SMOOTH_TILE_EXTENT_ONE_STEP); - if (label->detail->tile_width == tile_width) { + if (label->details->tile_width == tile_width) { return; } - label->detail->tile_width = tile_width; + label->details->tile_width = tile_width; gtk_widget_queue_resize (GTK_WIDGET (label)); } @@ -1357,7 +1370,7 @@ nautilus_label_get_tile_width (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), 0); - return label->detail->tile_width; + return label->details->tile_width; } void @@ -1367,11 +1380,11 @@ nautilus_label_set_tile_height (NautilusLabel *label, g_return_if_fail (NAUTILUS_IS_LABEL (label)); g_return_if_fail (tile_height >= NAUTILUS_SMOOTH_TILE_EXTENT_ONE_STEP); - if (label->detail->tile_height == tile_height) { + if (label->details->tile_height == tile_height) { return; } - label->detail->tile_height = tile_height; + label->details->tile_height = tile_height; gtk_widget_queue_resize (GTK_WIDGET (label)); } @@ -1388,7 +1401,7 @@ nautilus_label_get_tile_height (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), 0); - return label->detail->tile_height; + return label->details->tile_height; } void @@ -1399,11 +1412,11 @@ nautilus_label_set_tile_mode_vertical (NautilusLabel *label, g_return_if_fail (tile_mode_vertical >= NAUTILUS_SMOOTH_TILE_SELF); g_return_if_fail (tile_mode_vertical <= NAUTILUS_SMOOTH_TILE_ANCESTOR); - if (label->detail->tile_mode_vertical == tile_mode_vertical) { + if (label->details->tile_mode_vertical == tile_mode_vertical) { return; } - label->detail->tile_mode_vertical = tile_mode_vertical; + label->details->tile_mode_vertical = tile_mode_vertical; gtk_widget_queue_draw (GTK_WIDGET (label)); } @@ -1413,7 +1426,7 @@ nautilus_label_get_tile_mode_vertical (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), 0); - return label->detail->tile_mode_vertical; + return label->details->tile_mode_vertical; } void @@ -1424,11 +1437,11 @@ nautilus_label_set_tile_mode_horizontal (NautilusLabel *label, g_return_if_fail (tile_mode_horizontal >= NAUTILUS_SMOOTH_TILE_SELF); g_return_if_fail (tile_mode_horizontal <= NAUTILUS_SMOOTH_TILE_ANCESTOR); - if (label->detail->tile_mode_horizontal == tile_mode_horizontal) { + if (label->details->tile_mode_horizontal == tile_mode_horizontal) { return; } - label->detail->tile_mode_horizontal = tile_mode_horizontal; + label->details->tile_mode_horizontal = tile_mode_horizontal; gtk_widget_queue_draw (GTK_WIDGET (label)); } @@ -1438,7 +1451,7 @@ nautilus_label_get_tile_mode_horizontal (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), 0); - return label->detail->tile_mode_horizontal; + return label->details->tile_mode_horizontal; } void @@ -1466,11 +1479,11 @@ nautilus_label_set_background_mode (NautilusLabel *label, g_return_if_fail (background_mode >= NAUTILUS_SMOOTH_BACKGROUND_GTK); g_return_if_fail (background_mode <= NAUTILUS_SMOOTH_BACKGROUND_SOLID_COLOR); - if (label->detail->background_mode == background_mode) { + if (label->details->background_mode == background_mode) { return; } - label->detail->background_mode = background_mode; + label->details->background_mode = background_mode; gtk_widget_queue_draw (GTK_WIDGET (label)); } @@ -1480,7 +1493,7 @@ nautilus_label_get_background_mode (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), 0); - return label->detail->background_mode; + return label->details->background_mode; } void @@ -1489,11 +1502,11 @@ nautilus_label_set_solid_background_color (NautilusLabel *label, { g_return_if_fail (NAUTILUS_IS_LABEL (label)); - if (label->detail->solid_background_color == solid_background_color) { + if (label->details->solid_background_color == solid_background_color) { return; } - label->detail->solid_background_color = solid_background_color; + label->details->solid_background_color = solid_background_color; gtk_widget_queue_draw (GTK_WIDGET (label)); } @@ -1503,7 +1516,7 @@ nautilus_label_get_solid_background_color (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), 0); - return label->detail->solid_background_color; + return label->details->solid_background_color; } /** @@ -1521,11 +1534,11 @@ nautilus_label_set_smooth_line_wrap_width (NautilusLabel *label, { g_return_if_fail (NAUTILUS_IS_LABEL (label)); - if (label->detail->smooth_line_wrap_width == line_wrap_width) { + if (label->details->smooth_line_wrap_width == line_wrap_width) { return; } - label->detail->smooth_line_wrap_width = line_wrap_width; + label->details->smooth_line_wrap_width = line_wrap_width; label_line_geometries_recompute (label); @@ -1545,7 +1558,7 @@ nautilus_label_get_smooth_line_wrap_width (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), FALSE); - return label->detail->smooth_line_wrap_width; + return label->details->smooth_line_wrap_width; } void @@ -1556,11 +1569,11 @@ nautilus_label_set_text_color (NautilusLabel *label, g_return_if_fail (NAUTILUS_IS_LABEL (label)); - if (label->detail->smooth_text_color == text_color) { + if (label->details->smooth_text_color == text_color) { return; } - label->detail->smooth_text_color = text_color; + label->details->smooth_text_color = text_color; color_spec = nautilus_gdk_rgb_to_color_spec (text_color); @@ -1576,7 +1589,7 @@ nautilus_label_get_text_color (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), 0); - return label->detail->smooth_text_color; + return label->details->smooth_text_color; } /** @@ -1595,11 +1608,11 @@ nautilus_label_set_smooth_drop_shadow_offset (NautilusLabel *label, { g_return_if_fail (NAUTILUS_IS_LABEL (label)); - if (label->detail->smooth_drop_shadow_offset == drop_shadow_offset) { + if (label->details->smooth_drop_shadow_offset == drop_shadow_offset) { return; } - label->detail->smooth_drop_shadow_offset = drop_shadow_offset; + label->details->smooth_drop_shadow_offset = drop_shadow_offset; gtk_widget_queue_resize (GTK_WIDGET (label)); } @@ -1616,7 +1629,7 @@ nautilus_label_get_smooth_drop_shadow_offset (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), 0); - return label->detail->smooth_drop_shadow_offset; + return label->details->smooth_drop_shadow_offset; } /** @@ -1633,11 +1646,11 @@ nautilus_label_set_smooth_drop_shadow_color (NautilusLabel *label, { g_return_if_fail (NAUTILUS_IS_LABEL (label)); - if (label->detail->smooth_drop_shadow_color == drop_shadow_color) { + if (label->details->smooth_drop_shadow_color == drop_shadow_color) { return; } - label->detail->smooth_drop_shadow_color = drop_shadow_color; + label->details->smooth_drop_shadow_color = drop_shadow_color; gtk_widget_queue_draw (GTK_WIDGET (label)); } @@ -1654,7 +1667,7 @@ nautilus_label_get_smooth_drop_shadow_color (const NautilusLabel *label) { g_return_val_if_fail (NAUTILUS_IS_LABEL (label), 0); - return label->detail->smooth_drop_shadow_color; + return label->details->smooth_drop_shadow_color; } void @@ -1761,15 +1774,15 @@ nautilus_label_get_wrap (const NautilusLabel *label) * nautilus_label_new_solid: * * @text: Text or NULL - * @drop_shadow_offset: Drop shadow offset - * @drop_shadow_color: Drop shadow color - * @text_color: Text color - * @xalign: Horizontal alignment. - * @yalign: Vertical alignment. - * @xpadding: Amount to pad label in the x direction. - * @ypadding: Amount to pad label in the y direction. + * @drop_shadow_offset: Drop shadow offset. + * @drop_shadow_color: Drop shadow color. + * @text_color: Text color. + * @x_alignment: Horizontal alignment. + * @y_alignment: Vertical alignment. + * @x_padding: Amount to pad label in the x direction. + * @y_padding: Amount to pad label in the y direction. * @background_color: Background color. - * @tile_pixbuf: Pixbuf to use for tile or NULL + * @tile_pixbuf: Pixbuf to use for tile or NULL. * * Create a label with a solid background. * @@ -1780,10 +1793,10 @@ nautilus_label_new_solid (const char *text, guint drop_shadow_offset, guint32 drop_shadow_color, guint32 text_color, - float xalign, - float yalign, - int xpadding, - int ypadding, + float x_alignment, + float y_alignment, + int x_padding, + int y_padding, guint32 background_color, GdkPixbuf *tile_pixbuf) { @@ -1797,8 +1810,8 @@ nautilus_label_new_solid (const char *text, nautilus_label_set_text_color (label, text_color); nautilus_label_set_solid_background_color (NAUTILUS_LABEL (label), background_color); - gtk_misc_set_padding (GTK_MISC (label), xpadding, ypadding); - gtk_misc_set_alignment (GTK_MISC (label), xalign, yalign); + gtk_misc_set_padding (GTK_MISC (label), x_padding, y_padding); + gtk_misc_set_alignment (GTK_MISC (label), x_alignment, y_alignment); if (tile_pixbuf != NULL) { nautilus_label_set_tile_pixbuf (NAUTILUS_LABEL (label), tile_pixbuf); @@ -1822,7 +1835,7 @@ nautilus_label_make_bold (NautilusLabel *label) nautilus_gtk_label_make_bold (GTK_LABEL (label)); - bold_font = nautilus_scalable_font_make_bold (label->detail->smooth_font); + bold_font = nautilus_scalable_font_make_bold (label->details->smooth_font); if (bold_font != NULL) { nautilus_label_set_smooth_font (label, bold_font); @@ -1846,7 +1859,7 @@ nautilus_label_make_larger (NautilusLabel *label, { g_return_if_fail (NAUTILUS_IS_LABEL (label)); - label->detail->smooth_font_size += num_steps; + label->details->smooth_font_size += num_steps; nautilus_gtk_label_make_larger (GTK_LABEL (label), num_steps); @@ -1867,7 +1880,7 @@ nautilus_label_make_smaller (NautilusLabel *label, { g_return_if_fail (NAUTILUS_IS_LABEL (label)); - label->detail->smooth_font_size -= num_steps; + label->details->smooth_font_size -= num_steps; nautilus_gtk_label_make_smaller (GTK_LABEL (label), num_steps); @@ -1875,3 +1888,36 @@ nautilus_label_make_smaller (NautilusLabel *label, gtk_widget_queue_resize (GTK_WIDGET (label)); } + +/** + * nautilus_label_set_never_smooth + * + * @label: A NautilusLabel. + * @never_smooth: A boolean value indicating whether the label can NEVER be smooth. + * + * Force an label to never be smooth. Calls to nautilus_label_set_is_smooth () will + * thus be ignored. This is useful if you want to use a NautilusLabel in a situation + * wherre smoothness does not make sense - for example, in a dialog with other "normal" + * GtkLabel widgets for consistency. + */ +void +nautilus_label_set_never_smooth (NautilusLabel *label, + gboolean never_smooth) +{ + g_return_if_fail (NAUTILUS_IS_LABEL (label)); + + label->details->never_smooth = never_smooth; + + label_line_geometries_recompute (label); + + /* Force GtkLabel to flush its cached requisition dimensions. + * GtkLabel caches its requisition for efficiency. We need this + * dimensions to be flushed when our is_smooth attribute changes. + * The reason is that the geometry of the widget is dependent on + * whether it is_smooth or not. + */ + label_force_cached_requisition_flush (label); + + gtk_widget_queue_resize (GTK_WIDGET (label)); +} + diff --git a/libnautilus-private/nautilus-label.h b/libnautilus-private/nautilus-label.h index a435caf06..13c5d7fbb 100644 --- a/libnautilus-private/nautilus-label.h +++ b/libnautilus-private/nautilus-label.h @@ -39,7 +39,7 @@ BEGIN_GNOME_DECLS typedef struct _NautilusLabel NautilusLabel; typedef struct _NautilusLabelClass NautilusLabelClass; -typedef struct _NautilusLabelDetail NautilusLabelDetail; +typedef struct _NautilusLabelDetails NautilusLabelDetails; struct _NautilusLabel { @@ -47,7 +47,7 @@ struct _NautilusLabel GtkLabel gtk_label; /* Private things */ - NautilusLabelDetail *detail; + NautilusLabelDetails *details; }; struct _NautilusLabelClass @@ -134,6 +134,8 @@ NautilusSmoothTileMode nautilus_label_get_tile_mode_vertical (cons void nautilus_label_set_tile_mode_horizontal (NautilusLabel *label, NautilusSmoothTileMode horizontal_tile_mode); NautilusSmoothTileMode nautilus_label_get_tile_mode_horizontal (const NautilusLabel *label); +void nautilus_label_set_never_smooth (NautilusLabel *label, + gboolean never_smooth); END_GNOME_DECLS diff --git a/libnautilus-private/nautilus-labeled-image.c b/libnautilus-private/nautilus-labeled-image.c new file mode 100644 index 000000000..5a56fceaf --- /dev/null +++ b/libnautilus-private/nautilus-labeled-image.c @@ -0,0 +1,1845 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ + +/* nautilus-image.c - A labeled image. + + Copyright (C) 2000 Eazel, Inc. + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Authors: Ramiro Estrugo <ramiro@eazel.com> +*/ + +#include <config.h> + +#include "nautilus-labeled-image.h" + +#include "nautilus-gtk-macros.h" +#include "nautilus-gtk-extensions.h" +#include "nautilus-art-extensions.h" +#include "nautilus-art-gtk-extensions.h" +#include "nautilus-label.h" +#include "nautilus-image.h" + +#include <gtk/gtkbutton.h> +#include <gtk/gtktogglebutton.h> +#include <gtk/gtkcheckbutton.h> + +#include "nautilus-debug-drawing.h" + +#define DEFAULT_SPACING 0 +#define DEFAULT_X_PADDING 0 +#define DEFAULT_Y_PADDING 0 +#define DEFAULT_X_ALIGNMENT 0.5 +#define DEFAULT_Y_ALIGNMENT 0.5 + +/* Arguments */ +enum +{ + ARG_0, + ARG_FILL, + ARG_LABEL, + ARG_LABEL_POSITION, + ARG_PIXBUF, + ARG_SHOW_IMAGE, + ARG_SHOW_LABEL, + ARG_SPACING, + ARG_X_ALIGNMENT, + ARG_X_PADDING, + ARG_Y_ALIGNMENT, + ARG_Y_PADDING, +}; + +/* Detail member struct */ +struct _NautilusLabeledImageDetails +{ + GtkWidget *image; + GtkWidget *label; + GtkPositionType label_position; + gboolean show_label; + gboolean show_image; + guint spacing; + float x_alignment; + float y_alignment; + int x_padding; + int y_padding; + gboolean fill; +}; + +/* GtkObjectClass methods */ +static void nautilus_labeled_image_initialize_class (NautilusLabeledImageClass *labeled_image_class); +static void nautilus_labeled_image_initialize (NautilusLabeledImage *image); +static void nautilus_labeled_image_destroy (GtkObject *object); +static void nautilus_labeled_image_set_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); +static void nautilus_labeled_image_get_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); +/* GtkWidgetClass methods */ +static void nautilus_labeled_image_size_request (GtkWidget *widget, + GtkRequisition *requisition); +static int nautilus_labeled_image_expose_event (GtkWidget *widget, + GdkEventExpose *event); +static void nautilus_labeled_image_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); +static void nautilus_labeled_image_map (GtkWidget *widget); +static void nautilus_labeled_image_unmap (GtkWidget *widget); + +/* GtkContainerClass methods */ +static void nautilus_labeled_image_add (GtkContainer *container, + GtkWidget *widget); +static void nautilus_labeled_image_remove (GtkContainer *container, + GtkWidget *widget); +static void nautilus_labeled_image_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data); + +/* Private NautilusLabeledImage methods */ +static ArtIRect labeled_image_get_image_frame (const NautilusLabeledImage *labeled_image); +static ArtIRect labeled_image_get_label_frame (const NautilusLabeledImage *labeled_image); +static ArtIRect labeled_image_get_image_bounds (const NautilusLabeledImage *labeled_image); +static ArtIRect labeled_image_get_label_bounds (const NautilusLabeledImage *labeled_image); +static void labeled_image_ensure_label (NautilusLabeledImage *labeled_image); +static void labeled_image_ensure_image (NautilusLabeledImage *labeled_image); +static ArtIRect labeled_image_get_content_bounds (const NautilusLabeledImage *labeled_image); +static ArtIRect labeled_image_get_content_frame (const NautilusLabeledImage *labeled_image); +static void labeled_image_update_alignments (NautilusLabeledImage *labeled_image); +static gboolean labeled_image_show_label (const NautilusLabeledImage *labeled_image); +static gboolean labeled_image_show_image (const NautilusLabeledImage *labeled_image); + +NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusLabeledImage, nautilus_labeled_image, GTK_TYPE_CONTAINER) + +/* Class init methods */ +static void +nautilus_labeled_image_initialize_class (NautilusLabeledImageClass *labeled_image_class) +{ + GtkObjectClass *object_class = GTK_OBJECT_CLASS (labeled_image_class); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (labeled_image_class); + GtkContainerClass *container_class = GTK_CONTAINER_CLASS (labeled_image_class); + + /* GtkObjectClass */ + object_class->destroy = nautilus_labeled_image_destroy; + object_class->set_arg = nautilus_labeled_image_set_arg; + object_class->get_arg = nautilus_labeled_image_get_arg; + + /* GtkWidgetClass */ + widget_class->size_request = nautilus_labeled_image_size_request; + widget_class->size_allocate = nautilus_labeled_image_size_allocate; + widget_class->expose_event = nautilus_labeled_image_expose_event; + widget_class->map = nautilus_labeled_image_map; + widget_class->unmap = nautilus_labeled_image_unmap; + + /* GtkContainerClass */ + container_class->add = nautilus_labeled_image_add; + container_class->remove = nautilus_labeled_image_remove; + container_class->forall = nautilus_labeled_image_forall; + + /* Arguments */ + gtk_object_add_arg_type ("NautilusLabeledImage::pixbuf", + GTK_TYPE_POINTER, + GTK_ARG_READWRITE, + ARG_PIXBUF); + gtk_object_add_arg_type ("NautilusLabeledImage::label", + GTK_TYPE_STRING, + GTK_ARG_READWRITE, + ARG_LABEL); + gtk_object_add_arg_type ("NautilusLabeledImage::label_position", + GTK_TYPE_POSITION_TYPE, + GTK_ARG_READWRITE, + ARG_LABEL_POSITION); + gtk_object_add_arg_type ("NautilusLabeledImage::show_label", + GTK_TYPE_BOOL, + GTK_ARG_READWRITE, + ARG_SHOW_LABEL); + gtk_object_add_arg_type ("NautilusLabeledImage::show_image", + GTK_TYPE_BOOL, + GTK_ARG_READWRITE, + ARG_SHOW_IMAGE); + gtk_object_add_arg_type ("NautilusLabeledImage::spacing", + GTK_TYPE_UINT, + GTK_ARG_READWRITE, + ARG_SPACING); + gtk_object_add_arg_type ("NautilusLabeledImage::x_padding", + GTK_TYPE_INT, + GTK_ARG_READWRITE, + ARG_X_PADDING); + gtk_object_add_arg_type ("NautilusLabeledImage::y_padding", + GTK_TYPE_INT, + GTK_ARG_READWRITE, + ARG_Y_PADDING); + gtk_object_add_arg_type ("NautilusLabeledImage::x_alignment", + GTK_TYPE_FLOAT, + GTK_ARG_READWRITE, + ARG_X_ALIGNMENT); + gtk_object_add_arg_type ("NautilusLabeledImage::y_alignment", + GTK_TYPE_FLOAT, + GTK_ARG_READWRITE, + ARG_Y_ALIGNMENT); + gtk_object_add_arg_type ("NautilusLabeledImage::fill", + GTK_TYPE_BOOL, + GTK_ARG_READWRITE, + ARG_FILL); +} + +void +nautilus_labeled_image_initialize (NautilusLabeledImage *labeled_image) +{ + GTK_WIDGET_SET_FLAGS (labeled_image, GTK_NO_WINDOW); + + labeled_image->details = g_new0 (NautilusLabeledImageDetails, 1); + labeled_image->details->show_label = TRUE; + labeled_image->details->show_image = TRUE; + labeled_image->details->label_position = GTK_POS_BOTTOM; + labeled_image->details->spacing = DEFAULT_SPACING; + labeled_image->details->x_padding = DEFAULT_X_PADDING; + labeled_image->details->y_padding = DEFAULT_Y_PADDING; + labeled_image->details->x_alignment = DEFAULT_X_ALIGNMENT; + labeled_image->details->y_alignment = DEFAULT_Y_ALIGNMENT; + nautilus_labeled_image_set_fill (labeled_image, FALSE); +} + +/* GtkObjectClass methods */ +static void +nautilus_labeled_image_destroy (GtkObject *object) +{ + NautilusLabeledImage *labeled_image; + + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (object)); + + labeled_image = NAUTILUS_LABELED_IMAGE (object); + + g_free (labeled_image->details); + + /* Chain destroy */ + NAUTILUS_CALL_PARENT_CLASS (GTK_OBJECT_CLASS, destroy, (object)); +} + +static void +nautilus_labeled_image_set_arg (GtkObject *object, + GtkArg *arg, + guint arg_id) +{ + NautilusLabeledImage *labeled_image; + + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (object)); + + labeled_image = NAUTILUS_LABELED_IMAGE (object); + + switch (arg_id) + { + case ARG_PIXBUF: + nautilus_labeled_image_set_pixbuf (labeled_image, (GdkPixbuf *) GTK_VALUE_POINTER (*arg)); + break; + + case ARG_LABEL: + nautilus_labeled_image_set_text (labeled_image, GTK_VALUE_STRING (*arg)); + break; + + case ARG_LABEL_POSITION: + nautilus_labeled_image_set_label_position (labeled_image, GTK_VALUE_ENUM (*arg)); + break; + + case ARG_SHOW_LABEL: + nautilus_labeled_image_set_show_label (labeled_image, GTK_VALUE_BOOL (*arg)); + break; + + case ARG_SHOW_IMAGE: + nautilus_labeled_image_set_show_image (labeled_image, GTK_VALUE_BOOL (*arg)); + break; + + case ARG_SPACING: + nautilus_labeled_image_set_spacing (labeled_image, GTK_VALUE_UINT (*arg)); + break; + + case ARG_X_PADDING: + nautilus_labeled_image_set_x_padding (labeled_image, GTK_VALUE_INT (*arg)); + break; + + case ARG_Y_PADDING: + nautilus_labeled_image_set_y_padding (labeled_image, GTK_VALUE_INT (*arg)); + break; + + case ARG_X_ALIGNMENT: + nautilus_labeled_image_set_x_alignment (labeled_image, GTK_VALUE_FLOAT (*arg)); + break; + + case ARG_Y_ALIGNMENT: + nautilus_labeled_image_set_y_alignment (labeled_image, GTK_VALUE_FLOAT (*arg)); + break; + + case ARG_FILL: + nautilus_labeled_image_set_fill (labeled_image, GTK_VALUE_BOOL (*arg)); + break; + default: + g_assert_not_reached (); + } +} + +static void +nautilus_labeled_image_get_arg (GtkObject *object, + GtkArg *arg, + guint arg_id) +{ + NautilusLabeledImage *labeled_image; + + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (object)); + + labeled_image = NAUTILUS_LABELED_IMAGE (object); + + switch (arg_id) + { + case ARG_PIXBUF: + GTK_VALUE_POINTER (*arg) = nautilus_labeled_image_get_pixbuf (labeled_image); + break; + + case ARG_LABEL: + GTK_VALUE_STRING (*arg) = nautilus_labeled_image_get_text (labeled_image); + break; + + case ARG_LABEL_POSITION: + GTK_VALUE_ENUM (*arg) = nautilus_labeled_image_get_label_position (labeled_image); + break; + + case ARG_SHOW_LABEL: + GTK_VALUE_BOOL (*arg) = nautilus_labeled_image_get_show_label (labeled_image); + break; + + case ARG_SHOW_IMAGE: + GTK_VALUE_BOOL (*arg) = nautilus_labeled_image_get_show_image (labeled_image); + break; + + case ARG_SPACING: + GTK_VALUE_UINT (*arg) = nautilus_labeled_image_get_spacing (labeled_image); + break; + + case ARG_X_PADDING: + GTK_VALUE_INT (*arg) = nautilus_labeled_image_get_x_padding (labeled_image); + break; + + case ARG_Y_PADDING: + GTK_VALUE_INT (*arg) = nautilus_labeled_image_get_y_padding (labeled_image); + break; + + case ARG_X_ALIGNMENT: + GTK_VALUE_FLOAT (*arg) = nautilus_labeled_image_get_x_alignment (labeled_image); + break; + + case ARG_Y_ALIGNMENT: + GTK_VALUE_FLOAT (*arg) = nautilus_labeled_image_get_y_alignment (labeled_image); + break; + + case ARG_FILL: + GTK_VALUE_BOOL (*arg) = nautilus_labeled_image_get_fill (labeled_image); + break; + + default: + g_assert_not_reached (); + } +} + +/* GtkWidgetClass methods */ +static void +nautilus_labeled_image_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + NautilusLabeledImage *labeled_image; + ArtIRect content_frame; + + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (widget)); + g_return_if_fail (requisition != NULL); + + labeled_image = NAUTILUS_LABELED_IMAGE (widget); + + content_frame = labeled_image_get_content_frame (labeled_image); + + requisition->width = + MAX (1, content_frame.x1) + + 2 * labeled_image->details->x_padding; + + requisition->height = + MAX (1, content_frame.y1) + + 2 * labeled_image->details->y_padding; +} + +static void +nautilus_labeled_image_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + NautilusLabeledImage *labeled_image; + ArtIRect image_bounds; + ArtIRect label_bounds; + + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (widget)); + g_return_if_fail (allocation != NULL); + + labeled_image = NAUTILUS_LABELED_IMAGE (widget); + + widget->allocation = *allocation; + + label_bounds = labeled_image_get_label_bounds (labeled_image); + if (!art_irect_empty (&label_bounds)) { + GtkAllocation label_allocation; + + label_allocation.x = label_bounds.x0; + label_allocation.y = label_bounds.y0; + label_allocation.width = nautilus_art_irect_get_width (&label_bounds); + label_allocation.height = nautilus_art_irect_get_height (&label_bounds); + + gtk_widget_size_allocate (labeled_image->details->label, &label_allocation); + } + + image_bounds = labeled_image_get_image_bounds (labeled_image); + if (!art_irect_empty (&image_bounds)) { + GtkAllocation image_allocation; + + image_allocation.x = image_bounds.x0; + image_allocation.y = image_bounds.y0; + image_allocation.width = nautilus_art_irect_get_width (&image_bounds); + image_allocation.height = nautilus_art_irect_get_height (&image_bounds); + + gtk_widget_size_allocate (labeled_image->details->image, &image_allocation); + } +} + +static int +nautilus_labeled_image_expose_event (GtkWidget *widget, + GdkEventExpose *event) +{ + NautilusLabeledImage *labeled_image; + + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (widget), TRUE); + g_return_val_if_fail (GTK_WIDGET_REALIZED (widget), TRUE); + g_return_val_if_fail (event != NULL, TRUE); + + labeled_image = NAUTILUS_LABELED_IMAGE (widget); + + if (labeled_image_show_label (labeled_image)) { + GdkEventExpose label_event; + + label_event = *event; + + if (GTK_WIDGET_DRAWABLE (labeled_image->details->label) && + GTK_WIDGET_NO_WINDOW (labeled_image->details->label) && + gtk_widget_intersect (labeled_image->details->label, &event->area, &label_event.area)) { + gtk_widget_event (labeled_image->details->label, (GdkEvent *) &label_event); + } + } + + if (labeled_image_show_image (labeled_image)) { + GdkEventExpose image_event; + + image_event = *event; + + if (GTK_WIDGET_DRAWABLE (labeled_image->details->image) && + GTK_WIDGET_NO_WINDOW (labeled_image->details->image) && + gtk_widget_intersect (labeled_image->details->image, &event->area, &image_event.area)) { + gtk_widget_event (labeled_image->details->image, (GdkEvent *) &image_event); + } + } + + return FALSE; +} + +static void +nautilus_labeled_image_map (GtkWidget *widget) +{ + NautilusLabeledImage *labeled_image; + + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (widget)); + + labeled_image = NAUTILUS_LABELED_IMAGE (widget); + + GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED); + + if (labeled_image_show_label (labeled_image)) { + if (GTK_WIDGET_VISIBLE (labeled_image->details->label) && + !GTK_WIDGET_MAPPED (labeled_image->details->label)) { + gtk_widget_map (labeled_image->details->label); + } + } + + if (labeled_image_show_image (labeled_image)) { + if (GTK_WIDGET_VISIBLE (labeled_image->details->image) && + !GTK_WIDGET_MAPPED (labeled_image->details->image)) { + gtk_widget_map (labeled_image->details->image); + } + } +} + +static void +nautilus_labeled_image_unmap (GtkWidget *widget) +{ + NautilusLabeledImage *labeled_image; + + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (widget)); + + labeled_image = NAUTILUS_LABELED_IMAGE (widget); + + GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED); + + if (labeled_image->details->label != NULL) { + if (GTK_WIDGET_VISIBLE (labeled_image->details->label) && + GTK_WIDGET_MAPPED (labeled_image->details->label)) { + gtk_widget_unmap (labeled_image->details->label); + } + } + + if (labeled_image->details->image != NULL) { + if (GTK_WIDGET_VISIBLE (labeled_image->details->image) && + GTK_WIDGET_MAPPED (labeled_image->details->image)) { + gtk_widget_unmap (labeled_image->details->image); + } + } +} + +/* GtkContainerClass methods */ +static void +nautilus_labeled_image_add (GtkContainer *container, + GtkWidget *child) +{ + g_return_if_fail (container != NULL); + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (container)); + g_return_if_fail (NAUTILUS_IS_LABEL (child) || NAUTILUS_IS_IMAGE (child)); + + gtk_widget_set_parent (child, GTK_WIDGET (container)); + + if (GTK_WIDGET_REALIZED (container)) { + gtk_widget_realize (child); + } + + if (GTK_WIDGET_VISIBLE (container) && GTK_WIDGET_VISIBLE (child)) { + if (GTK_WIDGET_MAPPED (container)) { + gtk_widget_map (child); + } + + gtk_widget_queue_resize (child); + } +} + +static void +nautilus_labeled_image_remove (GtkContainer *container, + GtkWidget *child) +{ + NautilusLabeledImage *labeled_image; + gboolean child_was_visible; + + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (container)); + g_return_if_fail (NAUTILUS_IS_LABEL (child) || NAUTILUS_IS_IMAGE (child)); + + labeled_image = NAUTILUS_LABELED_IMAGE (container);; + + g_return_if_fail (child == labeled_image->details->image || child == labeled_image->details->label); + + child_was_visible = GTK_WIDGET_VISIBLE (child); + + gtk_widget_unparent (child); + + if (child_was_visible) { + gtk_widget_queue_resize (GTK_WIDGET (container)); + } + + if (labeled_image->details->image == child) { + labeled_image->details->image = NULL; + } + + if (labeled_image->details->label == child) { + labeled_image->details->label = NULL; + } +} + +static void +nautilus_labeled_image_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) +{ + NautilusLabeledImage *labeled_image; + + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (container)); + g_return_if_fail (callback != NULL); + + labeled_image = NAUTILUS_LABELED_IMAGE (container);; + + if (include_internals) { + if (labeled_image->details->image != NULL) { + (* callback) (labeled_image->details->image, callback_data); + } + + if (labeled_image->details->label != NULL) { + (* callback) (labeled_image->details->label, callback_data); + } + } +} + +static ArtIRect +labeled_image_get_image_frame (const NautilusLabeledImage *labeled_image) +{ + ArtIRect image_frame; + GtkRequisition image_requisition; + + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), NAUTILUS_ART_IRECT_EMPTY); + + if (!labeled_image_show_image (labeled_image)) { + return NAUTILUS_ART_IRECT_EMPTY; + } + + gtk_widget_size_request (labeled_image->details->image, &image_requisition); + + image_frame.x0 = 0; + image_frame.y0 = 0; + image_frame.x1 = (int) image_requisition.width; + image_frame.y1 = (int) image_requisition.height; + + return image_frame; +} + +static ArtIRect +labeled_image_get_label_frame (const NautilusLabeledImage *labeled_image) +{ + ArtIRect label_frame; + GtkRequisition label_requisition; + + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), NAUTILUS_ART_IRECT_EMPTY); + + if (!labeled_image_show_label (labeled_image)) { + return NAUTILUS_ART_IRECT_EMPTY; + } + + gtk_widget_size_request (labeled_image->details->label, &label_requisition); + + label_frame.x0 = 0; + label_frame.y0 = 0; + label_frame.x1 = (int) label_requisition.width; + label_frame.y1 = (int) label_requisition.height; + + return label_frame; +} + +static ArtIRect +labeled_image_get_image_bounds_fill (const NautilusLabeledImage *labeled_image) +{ + ArtIRect image_bounds; + ArtIRect image_frame; + ArtIRect content_bounds; + ArtIRect bounds; + + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), NAUTILUS_ART_IRECT_EMPTY); + + image_frame = labeled_image_get_image_frame (labeled_image); + + if (art_irect_empty (&image_frame)) { + return NAUTILUS_ART_IRECT_EMPTY; + } + + content_bounds = labeled_image_get_content_bounds (labeled_image); + bounds = nautilus_irect_gtk_widget_get_bounds (GTK_WIDGET (labeled_image)); + + if (!labeled_image_show_label (labeled_image)) { + image_bounds = bounds; + } else { + switch (labeled_image->details->label_position) { + case GTK_POS_LEFT: + image_bounds.y0 = bounds.y0; + image_bounds.x0 = content_bounds.x1 - image_frame.x1; + image_bounds.y1 = bounds.y1; + image_bounds.x1 = bounds.x1; + break; + + case GTK_POS_RIGHT: + image_bounds.y0 = bounds.y0; + image_bounds.x0 = bounds.x0; + image_bounds.y1 = bounds.y1; + image_bounds.x1 = content_bounds.x0 + image_frame.x1; + break; + + case GTK_POS_TOP: + image_bounds.x0 = bounds.x0; + image_bounds.y0 = content_bounds.y1 - image_frame.y1; + image_bounds.x1 = bounds.x1; + image_bounds.y1 = bounds.y1; + break; + + case GTK_POS_BOTTOM: + image_bounds.x0 = bounds.x0; + image_bounds.y0 = bounds.y0; + image_bounds.x1 = bounds.x1; + image_bounds.y1 = content_bounds.y0 + image_frame.y1; + break; + } + } + + return image_bounds; +} + +static ArtIRect +labeled_image_get_image_bounds (const NautilusLabeledImage *labeled_image) +{ + ArtIRect image_frame; + ArtIRect image_bounds; + ArtIRect content_bounds; + + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), NAUTILUS_ART_IRECT_EMPTY); + + if (labeled_image->details->fill) { + return labeled_image_get_image_bounds_fill (labeled_image); + } + + image_frame = labeled_image_get_image_frame (labeled_image); + + if (art_irect_empty (&image_frame)) { + return NAUTILUS_ART_IRECT_EMPTY; + } + + content_bounds = labeled_image_get_content_bounds (labeled_image); + + if (!labeled_image_show_label (labeled_image)) { + image_bounds.x0 = + content_bounds.x0 + + (nautilus_art_irect_get_width (&content_bounds) - image_frame.x1) / 2; + image_bounds.y0 = + content_bounds.y0 + + (nautilus_art_irect_get_height (&content_bounds) - image_frame.y1) / 2; + } else { + switch (labeled_image->details->label_position) { + case GTK_POS_LEFT: + image_bounds.x0 = content_bounds.x1 - image_frame.x1; + image_bounds.y0 = + content_bounds.y0 + + (nautilus_art_irect_get_height (&content_bounds) - image_frame.y1) / 2; + break; + + case GTK_POS_RIGHT: + image_bounds.x0 = content_bounds.x0; + image_bounds.y0 = + content_bounds.y0 + + (nautilus_art_irect_get_height (&content_bounds) - image_frame.y1) / 2; + break; + + case GTK_POS_TOP: + image_bounds.x0 = + content_bounds.x0 + + (nautilus_art_irect_get_width (&content_bounds) - image_frame.x1) / 2; + image_bounds.y0 = content_bounds.y1 - image_frame.y1; + break; + + case GTK_POS_BOTTOM: + image_bounds.x0 = + content_bounds.x0 + + (nautilus_art_irect_get_width (&content_bounds) - image_frame.x1) / 2; + image_bounds.y0 = content_bounds.y0; + break; + } + } + + image_bounds.x1 = image_bounds.x0 + image_frame.x1; + image_bounds.y1 = image_bounds.y0 + image_frame.y1; + + return image_bounds; +} + +static ArtIRect +labeled_image_get_label_bounds_fill (const NautilusLabeledImage *labeled_image) +{ + ArtIRect label_bounds; + ArtIRect label_frame; + ArtIRect content_bounds; + ArtIRect bounds; + + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), NAUTILUS_ART_IRECT_EMPTY); + + label_frame = labeled_image_get_label_frame (labeled_image); + + if (art_irect_empty (&label_frame)) { + return NAUTILUS_ART_IRECT_EMPTY; + } + + content_bounds = labeled_image_get_content_bounds (labeled_image); + bounds = nautilus_irect_gtk_widget_get_bounds (GTK_WIDGET (labeled_image)); + + /* Only the label is shown */ + if (!labeled_image_show_image (labeled_image)) { + label_bounds = bounds; + /* Both label and image are shown */ + } else { + switch (labeled_image->details->label_position) { + case GTK_POS_LEFT: + label_bounds.y0 = bounds.y0; + label_bounds.x0 = bounds.x0; + label_bounds.y1 = bounds.y1; + label_bounds.x1 = content_bounds.x0 + label_frame.x1; + break; + + case GTK_POS_RIGHT: + label_bounds.y0 = bounds.y0; + label_bounds.x0 = content_bounds.x1 - label_frame.x1; + label_bounds.y1 = bounds.y1; + label_bounds.x1 = bounds.x1; + break; + + case GTK_POS_TOP: + label_bounds.x0 = bounds.x0; + label_bounds.y0 = bounds.y0; + label_bounds.x1 = bounds.x1; + label_bounds.y1 = content_bounds.y0 + label_frame.y1; + break; + + case GTK_POS_BOTTOM: + label_bounds.x0 = bounds.x0; + label_bounds.y0 = content_bounds.y1 - label_frame.y1; + label_bounds.x1 = bounds.x1; + label_bounds.y1 = bounds.y1; + break; + } + } + + return label_bounds; +} + +static ArtIRect +labeled_image_get_label_bounds (const NautilusLabeledImage *labeled_image) +{ + ArtIRect label_bounds; + ArtIRect label_frame; + ArtIRect content_bounds; + + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), NAUTILUS_ART_IRECT_EMPTY); + + if (labeled_image->details->fill) { + return labeled_image_get_label_bounds_fill (labeled_image); + } + + label_frame = labeled_image_get_label_frame (labeled_image); + + if (art_irect_empty (&label_frame)) { + return NAUTILUS_ART_IRECT_EMPTY; + } + + content_bounds = labeled_image_get_content_bounds (labeled_image); + + /* Only the label is shown */ + if (!labeled_image_show_image (labeled_image)) { + label_bounds.x0 = + content_bounds.x0 + + (nautilus_art_irect_get_width (&content_bounds) - label_frame.x1) / 2; + label_bounds.y0 = + content_bounds.y0 + + (nautilus_art_irect_get_height (&content_bounds) - label_frame.y1) / 2; + /* Both label and image are shown */ + } else { + switch (labeled_image->details->label_position) { + case GTK_POS_LEFT: + label_bounds.x0 = content_bounds.x0; + label_bounds.y0 = + content_bounds.y0 + + (nautilus_art_irect_get_height (&content_bounds) - label_frame.y1) / 2; + break; + + case GTK_POS_RIGHT: + label_bounds.x0 = content_bounds.x1 - label_frame.x1; + label_bounds.y0 = + content_bounds.y0 + + (nautilus_art_irect_get_height (&content_bounds) - label_frame.y1) / 2; + break; + + case GTK_POS_TOP: + label_bounds.x0 = + content_bounds.x0 + + (nautilus_art_irect_get_width (&content_bounds) - label_frame.x1) / 2; + label_bounds.y0 = content_bounds.y0; + break; + + case GTK_POS_BOTTOM: + label_bounds.x0 = + content_bounds.x0 + + (nautilus_art_irect_get_width (&content_bounds) - label_frame.x1) / 2; + label_bounds.y0 = content_bounds.y1 - label_frame.y1; + break; + } + } + + label_bounds.x1 = label_bounds.x0 + label_frame.x1; + label_bounds.y1 = label_bounds.y0 + label_frame.y1; + + return label_bounds; +} + +static void +labeled_image_update_alignments (NautilusLabeledImage *labeled_image) +{ + + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->label != NULL) { + float x_alignment; + float y_alignment; + + if (labeled_image->details->fill) { + x_alignment = GTK_MISC (labeled_image->details->label)->xalign; + y_alignment = GTK_MISC (labeled_image->details->label)->yalign; + + /* Only the label is shown */ + if (!labeled_image_show_image (labeled_image)) { + x_alignment = 0.5; + y_alignment = 0.5; + /* Both label and image are shown */ + } else { + switch (labeled_image->details->label_position) { + case GTK_POS_LEFT: + x_alignment = 1.0; + y_alignment = 0.5; + break; + + case GTK_POS_RIGHT: + x_alignment = 0.0; + y_alignment = 0.5; + break; + + case GTK_POS_TOP: + x_alignment = 0.5; + y_alignment = 1.0; + break; + + case GTK_POS_BOTTOM: + x_alignment = 0.5; + y_alignment = 0.0; + break; + } + + } + + gtk_misc_set_alignment (GTK_MISC (labeled_image->details->label), + x_alignment, + y_alignment); + } + } + + if (labeled_image->details->image != NULL) { + float x_alignment; + float y_alignment; + + if (labeled_image->details->fill) { + x_alignment = GTK_MISC (labeled_image->details->image)->xalign; + y_alignment = GTK_MISC (labeled_image->details->image)->yalign; + + /* Only the image is shown */ + if (!labeled_image_show_label (labeled_image)) { + x_alignment = 0.5; + y_alignment = 0.5; + /* Both label and image are shown */ + } else { + switch (labeled_image->details->label_position) { + case GTK_POS_LEFT: + x_alignment = 0.0; + y_alignment = 0.5; + break; + + case GTK_POS_RIGHT: + x_alignment = 1.0; + y_alignment = 0.5; + break; + + case GTK_POS_TOP: + x_alignment = 0.5; + y_alignment = 0.0; + break; + + case GTK_POS_BOTTOM: + x_alignment = 0.5; + y_alignment = 1.0; + break; + } + } + + gtk_misc_set_alignment (GTK_MISC (labeled_image->details->image), + x_alignment, + y_alignment); + } + } +} + +static ArtIRect +labeled_image_get_content_frame (const NautilusLabeledImage *labeled_image) +{ + ArtIRect image_frame; + ArtIRect label_frame; + ArtIRect content_frame; + + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), NAUTILUS_ART_IRECT_EMPTY); + + image_frame = labeled_image_get_image_frame (labeled_image); + label_frame = labeled_image_get_label_frame (labeled_image); + + content_frame = NAUTILUS_ART_IRECT_EMPTY; + + /* Both shown */ + if (!art_irect_empty (&image_frame) && !art_irect_empty (&label_frame)) { + content_frame.x1 = image_frame.x1 + labeled_image->details->spacing + label_frame.x1; + switch (labeled_image->details->label_position) { + case GTK_POS_LEFT: + case GTK_POS_RIGHT: + content_frame.x1 = image_frame.x1 + labeled_image->details->spacing + label_frame.x1; + content_frame.y1 = MAX (image_frame.y1, label_frame.y1); + break; + + case GTK_POS_TOP: + case GTK_POS_BOTTOM: + content_frame.x1 = MAX (image_frame.x1, label_frame.x1); + content_frame.y1 = image_frame.y1 + labeled_image->details->spacing + label_frame.y1; + break; + } + /* Only image shown */ + } else if (!art_irect_empty (&image_frame)) { + content_frame.x1 = image_frame.x1; + content_frame.y1 = image_frame.y1; + /* Only label shown */ + } else { + content_frame.x1 = label_frame.x1; + content_frame.y1 = label_frame.y1; + } + + return content_frame; +} + +static ArtIRect +labeled_image_get_content_bounds (const NautilusLabeledImage *labeled_image) +{ + ArtIRect content_frame; + ArtIRect content_bounds; + ArtIRect bounds; + + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), NAUTILUS_ART_IRECT_EMPTY); + + bounds = nautilus_irect_gtk_widget_get_bounds (GTK_WIDGET (labeled_image)); + + content_frame = labeled_image_get_content_frame (labeled_image); + content_bounds = nautilus_art_irect_align (&bounds, + content_frame.x1, + content_frame.y1, + labeled_image->details->x_alignment, + labeled_image->details->y_alignment); + + return content_bounds; +} + +static void +labeled_image_ensure_label (NautilusLabeledImage *labeled_image) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->label != NULL) { + return; + } + + labeled_image->details->label = nautilus_label_new (NULL); + gtk_container_add (GTK_CONTAINER (labeled_image), labeled_image->details->label); + gtk_widget_show (labeled_image->details->label); +} + +static void +labeled_image_ensure_image (NautilusLabeledImage *labeled_image) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->image != NULL) { + return; + } + + labeled_image->details->image = nautilus_image_new (NULL); + gtk_container_add (GTK_CONTAINER (labeled_image), labeled_image->details->image); + gtk_widget_show (labeled_image->details->image); +} + +static gboolean +labeled_image_show_image (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), FALSE); + + return labeled_image->details->image != NULL && labeled_image->details->show_image; +} + +static gboolean +labeled_image_show_label (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), FALSE); + + return labeled_image->details->label != NULL && labeled_image->details->show_label; +} + +/** + * nautilus_labeled_image_new: + * @text: Text to use for label or NULL. + * @pixbuf: Pixbuf to use for image or NULL. + * + * Returns A newly allocated NautilusLabeledImage. If the &text parameter is not + * NULL then the LabeledImage will show a label. If the &pixbuf parameter is not + * NULL then the LabeledImage will show a pixbuf. Either of these can be NULL at + * creation time. + * + * Later in the lifetime of the widget you can invoke methods that affect the + * label and/or the image. If at creation time these were NULL, then they will + * be created as neeeded. + * + * Thus, using this widget in place of NautilusImage or NautilusLabel is "free" with + * only the GtkObject and function call overhead. + * + */ +GtkWidget* +nautilus_labeled_image_new (const char *text, + GdkPixbuf *pixbuf) +{ + NautilusLabeledImage *labeled_image; + + labeled_image = NAUTILUS_LABELED_IMAGE (gtk_widget_new (nautilus_labeled_image_get_type (), NULL)); + + if (text != NULL) { + nautilus_labeled_image_set_text (labeled_image, text); + } + + if (pixbuf != NULL) { + nautilus_labeled_image_set_pixbuf (labeled_image, pixbuf); + } + + labeled_image_update_alignments (labeled_image); + + return GTK_WIDGET (labeled_image); +} + +/** + * nautilus_labeled_image_set_label_position: + * @labeled_image: A NautilusLabeledImage. + * @label_position: The position of the label with respect to the image. + * + * Set the position of the label with respect to the image as follows: + * + * GTK_POS_LEFT: + * [ <label> <image> ] + * + * GTK_POS_RIGHT: + * [ <image> <label> ] + * + * GTK_POS_TOP: + * [ <label> ] + * [ <image> ] + * + * GTK_POS_BOTTOM: + * [ <image> ] + * [ <label> ] + * + */ +void +nautilus_labeled_image_set_label_position (NautilusLabeledImage *labeled_image, + GtkPositionType label_position) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + g_return_if_fail (label_position >= GTK_POS_LEFT); + g_return_if_fail (label_position <= GTK_POS_BOTTOM); + + if (labeled_image->details->label_position == label_position) { + return; + } + + labeled_image->details->label_position = label_position; + + labeled_image_update_alignments (labeled_image); + + gtk_widget_queue_resize (GTK_WIDGET (labeled_image)); +} + +/** + * nautilus_labeled_image_get_label_postiion: + * @labeled_image: A NautilusLabeledImage. + * + * Returns an enumeration indicating the position of the label with respect to the image. + */ +GtkPositionType +nautilus_labeled_image_get_label_position (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), 0); + + return labeled_image->details->label_position; +} + +/** + * nautilus_labeled_image_set_show_label: + * @labeled_image: A NautilusLabeledImage. + * @show_image: A boolean value indicating whether the label should be shown. + * + * Update the labeled image to either show or hide the internal label widget. + * This function doesnt have any effect if the LabeledImage doesnt already + * contain an label. + */ +void +nautilus_labeled_image_set_show_label (NautilusLabeledImage *labeled_image, + gboolean show_label) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->show_label == show_label) { + return; + } + + labeled_image->details->show_label = show_label; + + if (labeled_image->details->label != NULL) { + if (labeled_image->details->show_label) { + gtk_widget_show (labeled_image->details->label); + } else { + gtk_widget_hide (labeled_image->details->label); + } + } + + labeled_image_update_alignments (labeled_image); + + gtk_widget_queue_resize (GTK_WIDGET (labeled_image)); +} + +/** + * nautilus_labeled_image_get_show_label: + * @labeled_image: A NautilusLabeledImage. + * + * Returns a boolean value indicating whether the internal label is shown. + */ +gboolean +nautilus_labeled_image_get_show_label (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), 0); + + return labeled_image->details->show_label; +} + +/** + * nautilus_labeled_image_set_show_image: + * @labeled_image: A NautilusLabeledImage. + * @show_image: A boolean value indicating whether the image should be shown. + * + * Update the labeled image to either show or hide the internal image widget. + * This function doesnt have any effect if the LabeledImage doesnt already + * contain an image. + */ +void +nautilus_labeled_image_set_show_image (NautilusLabeledImage *labeled_image, + gboolean show_image) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->show_image == show_image) { + return; + } + + labeled_image->details->show_image = show_image; + + if (labeled_image->details->image != NULL) { + if (labeled_image->details->show_image) { + gtk_widget_show (labeled_image->details->image); + } else { + gtk_widget_hide (labeled_image->details->image); + } + } + + labeled_image_update_alignments (labeled_image); + + gtk_widget_queue_resize (GTK_WIDGET (labeled_image)); +} + +/** + * nautilus_labeled_image_get_show_image: + * @labeled_image: A NautilusLabeledImage. + * + * Returns a boolean value indicating whether the internal image is shown. + */ +gboolean +nautilus_labeled_image_get_show_image (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), 0); + + return labeled_image->details->show_image; +} + +/** + * nautilus_labeled_image_set_spacing: + * @labeled_image: A NautilusLabeledImage. + * @spacing: The new spacing between label and image. + * + * Set the spacing between label and image. This will only affect + * the geometry of the widget if both a label and image are currently + * visible. + * + */ +void +nautilus_labeled_image_set_spacing (NautilusLabeledImage *labeled_image, + guint spacing) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->spacing == spacing) { + return; + } + + labeled_image->details->spacing = spacing; + + labeled_image_update_alignments (labeled_image); + + gtk_widget_queue_resize (GTK_WIDGET (labeled_image)); +} + +/** + * nautilus_labeled_image_get_spacing: + * @labeled_image: A NautilusLabeledImage. + * + * Returns: The spacing between the label and image. + */ +guint +nautilus_labeled_image_get_spacing (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), 0); + + return labeled_image->details->spacing; +} + +/** + * nautilus_labeled_image_set_x_padding: + * @labeled_image: A NautilusLabeledImage. + * @x_padding: The new horizontal padding. + * + * Set horizontal padding for the NautilusLabeledImage. The padding + * attribute work just like that in GtkMisc. + */ +void +nautilus_labeled_image_set_x_padding (NautilusLabeledImage *labeled_image, + int x_padding) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + x_padding = MAX (0, x_padding); + + if (labeled_image->details->x_padding == x_padding) { + return; + } + + labeled_image->details->x_padding = x_padding; + labeled_image_update_alignments (labeled_image); + gtk_widget_queue_resize (GTK_WIDGET (labeled_image)); +} + +/** + * nautilus_labeled_image_get_x_padding: + * @labeled_image: A NautilusLabeledImage. + * + * Returns: The horizontal padding for the LabeledImage's content. + */ +int +nautilus_labeled_image_get_x_padding (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), 0); + + return labeled_image->details->x_padding; +} + +/** + * nautilus_labeled_image_set_y_padding: + * @labeled_image: A NautilusLabeledImage. + * @x_padding: The new vertical padding. + * + * Set vertical padding for the NautilusLabeledImage. The padding + * attribute work just like that in GtkMisc. + */ +void +nautilus_labeled_image_set_y_padding (NautilusLabeledImage *labeled_image, + int y_padding) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + y_padding = MAX (0, y_padding); + + if (labeled_image->details->y_padding == y_padding) { + return; + } + + labeled_image->details->y_padding = y_padding; + labeled_image_update_alignments (labeled_image); + gtk_widget_queue_resize (GTK_WIDGET (labeled_image)); +} + +/** + * nautilus_labeled_image_get_x_padding: + * @labeled_image: A NautilusLabeledImage. + * + * Returns: The vertical padding for the LabeledImage's content. + */ +int +nautilus_labeled_image_get_y_padding (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), 0); + + return labeled_image->details->y_padding; +} + +/** + * nautilus_labeled_image_set_x_alignment: + * @labeled_image: A NautilusLabeledImage. + * @x_alignment: The new horizontal alignment. + * + * Set horizontal alignment for the NautilusLabeledImage's content. + * The 'content' is the union of the image and label. The alignment + * attribute work just like that in GtkMisc. + */ +void +nautilus_labeled_image_set_x_alignment (NautilusLabeledImage *labeled_image, + float x_alignment) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + x_alignment = MAX (0, x_alignment); + x_alignment = MIN (1.0, x_alignment); + + if (labeled_image->details->x_alignment == x_alignment) { + return; + } + + labeled_image->details->x_alignment = x_alignment; + gtk_widget_queue_resize (GTK_WIDGET (labeled_image)); +} + +/** + * nautilus_labeled_image_get_x_alignment: + * @labeled_image: A NautilusLabeledImage. + * + * Returns: The horizontal alignment for the LabeledImage's content. + */ +float +nautilus_labeled_image_get_x_alignment (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), 0); + + return labeled_image->details->x_alignment; +} + +/** + * nautilus_labeled_image_set_y_alignment: + * @labeled_image: A NautilusLabeledImage. + * @y_alignment: The new vertical alignment. + * + * Set vertical alignment for the NautilusLabeledImage's content. + * The 'content' is the union of the image and label. The alignment + * attribute work just like that in GtkMisc. + */ +void +nautilus_labeled_image_set_y_alignment (NautilusLabeledImage *labeled_image, + float y_alignment) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + y_alignment = MAX (0, y_alignment); + y_alignment = MIN (1.0, y_alignment); + + if (labeled_image->details->y_alignment == y_alignment) { + return; + } + + labeled_image->details->y_alignment = y_alignment; + gtk_widget_queue_resize (GTK_WIDGET (labeled_image)); +} + +/** + * nautilus_labeled_image_get_y_alignment: + * @labeled_image: A NautilusLabeledImage. + * + * Returns: The vertical alignment for the LabeledImage's content. + */ +float +nautilus_labeled_image_get_y_alignment (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), 0); + + return labeled_image->details->y_alignment; +} + +/** + * nautilus_labeled_image_set_fill: + * @labeled_image: A NautilusLabeledImage. + * @fill: A boolean value indicating whether the internal image and label + * widgets should fill all the available allocation. + * + * By default the internal image and label wigets are sized to their natural + * preferred geometry. You can use the 'fill' attribute of LabeledImage + * to have the internal widgets fill as much of the LabeledImage allocation + * as is available. This is useful if you install a tile_pixbuf and want it + * to cover the whole widget, and not just the areas occupied by the internal + * widgets. + */ +void +nautilus_labeled_image_set_fill (NautilusLabeledImage *labeled_image, + gboolean fill) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->fill == fill) { + return; + } + + labeled_image->details->fill = fill; + + labeled_image_update_alignments (labeled_image); + + gtk_widget_queue_resize (GTK_WIDGET (labeled_image)); +} + +/** + * nautilus_labeled_image_get_fill: + * @labeled_image: A NautilusLabeledImage. + * + * Retruns a boolean value indicating whether the internal widgets fill + * all the available allocation. + */ +gboolean +nautilus_labeled_image_get_fill (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), 0); + + return labeled_image->details->fill; +} + +/** + * nautilus_labeled_image_button_new: + * @text: Text to use for label or NULL. + * @pixbuf: Pixbuf to use for image or NULL. + * + * Create a stock GtkButton with a NautilusLabeledImage child. + * + */ +GtkWidget * +nautilus_labeled_image_button_new (const char *text, + GdkPixbuf *pixbuf) +{ + GtkWidget *button; + GtkWidget *labeled_image; + + button = gtk_button_new (); + labeled_image = nautilus_labeled_image_new (text, pixbuf); + gtk_container_add (GTK_CONTAINER (button), labeled_image); + gtk_widget_show (labeled_image); + + return button; +} + +/** + * nautilus_labeled_image_toggle_button_new: + * @text: Text to use for label or NULL. + * @pixbuf: Pixbuf to use for image or NULL. + * + * Create a stock GtkToggleButton with a NautilusLabeledImage child. + * + */ +GtkWidget * +nautilus_labeled_image_toggle_button_new (const char *text, + GdkPixbuf *pixbuf) +{ + GtkWidget *toggle_button; + GtkWidget *labeled_image; + + toggle_button = gtk_toggle_button_new (); + labeled_image = nautilus_labeled_image_new (text, pixbuf); + gtk_container_add (GTK_CONTAINER (toggle_button), labeled_image); + gtk_widget_show (labeled_image); + + return toggle_button; +} + +/** + * nautilus_labeled_image_check_button_new: + * @text: Text to use for label or NULL. + * @pixbuf: Pixbuf to use for image or NULL. + * + * Create a stock GtkCheckButton with a NautilusLabeledImage child. + * + */ +GtkWidget * +nautilus_labeled_image_check_button_new (const char *text, + GdkPixbuf *pixbuf) +{ + GtkWidget *check_button; + GtkWidget *labeled_image; + + check_button = gtk_check_button_new (); + labeled_image = nautilus_labeled_image_new (text, pixbuf); + gtk_container_add (GTK_CONTAINER (check_button), labeled_image); + gtk_widget_show (labeled_image); + + return check_button; +} + +/* + * The rest of the methods are proxies for those in NautilusImage and + * NautilusLabel. We have all these so that we dont have to expose + * our internal widgets at all. Probably more of these will be added + * as they are needed. + */ +void +nautilus_labeled_image_set_pixbuf (NautilusLabeledImage *labeled_image, + GdkPixbuf *pixbuf) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (pixbuf == NULL) { + if (labeled_image->details->image != NULL) { + gtk_widget_destroy (labeled_image->details->image); + labeled_image->details->image = NULL; + } + + gtk_widget_queue_resize (GTK_WIDGET (labeled_image)); + } else { + labeled_image_ensure_image (labeled_image); + nautilus_image_set_pixbuf (NAUTILUS_IMAGE (labeled_image->details->image), pixbuf); + } +} + +void +nautilus_labeled_image_set_pixbuf_from_file_name (NautilusLabeledImage *labeled_image, + const char *file_name) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + labeled_image_ensure_image (labeled_image); + nautilus_image_set_pixbuf_from_file_name (NAUTILUS_IMAGE (labeled_image->details->image), file_name); +} + +void +nautilus_labeled_image_set_tile_pixbuf (NautilusLabeledImage *labeled_image, + GdkPixbuf *tile_pixbuf) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->image != NULL) { + nautilus_image_set_tile_pixbuf (NAUTILUS_IMAGE (labeled_image->details->image), tile_pixbuf); + nautilus_image_set_tile_mode_horizontal (NAUTILUS_IMAGE (labeled_image->details->image), + NAUTILUS_SMOOTH_TILE_ANCESTOR); + nautilus_image_set_tile_mode_vertical (NAUTILUS_IMAGE (labeled_image->details->image), + NAUTILUS_SMOOTH_TILE_ANCESTOR); + } + + if (labeled_image->details->label != NULL) { + nautilus_label_set_tile_pixbuf (NAUTILUS_LABEL (labeled_image->details->label), tile_pixbuf); + nautilus_label_set_tile_mode_horizontal (NAUTILUS_LABEL (labeled_image->details->label), + NAUTILUS_SMOOTH_TILE_ANCESTOR); + nautilus_label_set_tile_mode_vertical (NAUTILUS_LABEL (labeled_image->details->label), + NAUTILUS_SMOOTH_TILE_ANCESTOR); + } +} + +void +nautilus_labeled_image_set_tile_pixbuf_from_file_name (NautilusLabeledImage *labeled_image, + const char *file_name) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->image != NULL) { + nautilus_image_set_tile_pixbuf_from_file_name (NAUTILUS_IMAGE (labeled_image->details->image), + file_name); + nautilus_image_set_tile_mode_horizontal (NAUTILUS_IMAGE (labeled_image->details->image), + NAUTILUS_SMOOTH_TILE_ANCESTOR); + nautilus_image_set_tile_mode_vertical (NAUTILUS_IMAGE (labeled_image->details->image), + NAUTILUS_SMOOTH_TILE_ANCESTOR); + } + + if (labeled_image->details->label != NULL) { + nautilus_label_set_tile_pixbuf_from_file_name (NAUTILUS_LABEL (labeled_image->details->label), + file_name); + nautilus_label_set_tile_mode_horizontal (NAUTILUS_LABEL (labeled_image->details->label), + NAUTILUS_SMOOTH_TILE_ANCESTOR); + nautilus_label_set_tile_mode_vertical (NAUTILUS_LABEL (labeled_image->details->label), + NAUTILUS_SMOOTH_TILE_ANCESTOR); + } +} + +GdkPixbuf* +nautilus_labeled_image_get_pixbuf (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), NULL); + + if (labeled_image->details->image == NULL) { + return NULL; + } + + return nautilus_image_get_pixbuf (NAUTILUS_IMAGE (labeled_image->details->image)); +} + +void +nautilus_labeled_image_set_text (NautilusLabeledImage *labeled_image, + const char *text) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (text == NULL) { + if (labeled_image->details->label) { + gtk_widget_destroy (labeled_image->details->label); + labeled_image->details->label = NULL; + } + + gtk_widget_queue_resize (GTK_WIDGET (labeled_image)); + } else { + labeled_image_ensure_label (labeled_image); + nautilus_label_set_text (NAUTILUS_LABEL (labeled_image->details->label), text); + } +} + +char * +nautilus_labeled_image_get_text (const NautilusLabeledImage *labeled_image) +{ + g_return_val_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image), NULL); + + if (labeled_image->details->label == NULL) { + return NULL; + } + + return nautilus_label_get_text (NAUTILUS_LABEL (labeled_image->details->label)); +} + +void +nautilus_labeled_image_make_bold (NautilusLabeledImage *labeled_image) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + labeled_image_ensure_label (labeled_image); + nautilus_label_make_bold (NAUTILUS_LABEL (labeled_image->details->label)); +} + +void +nautilus_labeled_image_make_larger (NautilusLabeledImage *labeled_image, + guint num_sizes) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + labeled_image_ensure_label (labeled_image); + nautilus_label_make_larger (NAUTILUS_LABEL (labeled_image->details->label), num_sizes); +} + +void +nautilus_labeled_image_make_smaller (NautilusLabeledImage *labeled_image, + guint num_sizes) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + labeled_image_ensure_label (labeled_image); + nautilus_label_make_smaller (NAUTILUS_LABEL (labeled_image->details->label), num_sizes); +} + +void +nautilus_labeled_image_set_tile_width (NautilusLabeledImage *labeled_image, + int tile_width) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->image != NULL) { + nautilus_image_set_tile_width (NAUTILUS_IMAGE (labeled_image->details->image), + tile_width); + } + + if (labeled_image->details->label != NULL) { + nautilus_label_set_tile_width (NAUTILUS_LABEL (labeled_image->details->label), + tile_width); + } +} + +void +nautilus_labeled_image_set_tile_height (NautilusLabeledImage *labeled_image, + int tile_height) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->image != NULL) { + nautilus_image_set_tile_height (NAUTILUS_IMAGE (labeled_image->details->image), + tile_height); + } + + if (labeled_image->details->label != NULL) { + nautilus_label_set_tile_height (NAUTILUS_LABEL (labeled_image->details->label), + tile_height); + } +} + +void +nautilus_labeled_image_set_background_mode (NautilusLabeledImage *labeled_image, + NautilusSmoothBackgroundMode background_mode) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + g_return_if_fail (background_mode >= NAUTILUS_SMOOTH_BACKGROUND_GTK); + g_return_if_fail (background_mode <= NAUTILUS_SMOOTH_BACKGROUND_SOLID_COLOR); + + if (labeled_image->details->image != NULL) { + nautilus_image_set_background_mode (NAUTILUS_IMAGE (labeled_image->details->image), + background_mode); + } + + if (labeled_image->details->label != NULL) { + nautilus_label_set_background_mode (NAUTILUS_LABEL (labeled_image->details->label), + background_mode); + } +} + +void +nautilus_labeled_image_set_solid_background_color (NautilusLabeledImage *labeled_image, + guint32 solid_background_color) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->image != NULL) { + nautilus_image_set_solid_background_color (NAUTILUS_IMAGE (labeled_image->details->image), + solid_background_color); + } + + if (labeled_image->details->label != NULL) { + nautilus_label_set_solid_background_color (NAUTILUS_LABEL (labeled_image->details->label), + solid_background_color); + } +} + +void +nautilus_labeled_image_set_smooth_drop_shadow_offset (NautilusLabeledImage *labeled_image, + guint drop_shadow_offset) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->label != NULL) { + nautilus_label_set_smooth_drop_shadow_offset (NAUTILUS_LABEL (labeled_image->details->label), + drop_shadow_offset); + } +} + +void +nautilus_labeled_image_set_smooth_drop_shadow_color (NautilusLabeledImage *labeled_image, + guint32 drop_shadow_color) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->label != NULL) { + nautilus_label_set_smooth_drop_shadow_color (NAUTILUS_LABEL (labeled_image->details->label), + drop_shadow_color); + } +} + +void +nautilus_labeled_image_set_text_color (NautilusLabeledImage *labeled_image, + guint32 text_color) +{ + g_return_if_fail (NAUTILUS_IS_LABELED_IMAGE (labeled_image)); + + if (labeled_image->details->label != NULL) { + nautilus_label_set_text_color (NAUTILUS_LABEL (labeled_image->details->label), + text_color); + } +} + diff --git a/libnautilus-private/nautilus-labeled-image.h b/libnautilus-private/nautilus-labeled-image.h new file mode 100644 index 000000000..e8c511966 --- /dev/null +++ b/libnautilus-private/nautilus-labeled-image.h @@ -0,0 +1,158 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ + +/* nautilus-labeled-image.h - A labeled image. + + Copyright (C) 2000 Eazel, Inc. + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Authors: Ramiro Estrugo <ramiro@eazel.com> +*/ + +/* NautilusLabeledImage is a container widget. It can only contain internal + * widgets. These internal widgets are can be a NautilusLabel and/or a + * NautilusImage. These internal widgets are create as needed. That means + * that NautilusLabeledImage can always be used for "free" instead of a + * NautilusLabel or NautilusImage. The only overhead is that of the GtkObject + * machinery. The label and image widgets themselves are only created as needed. + * + * The position of the label with respect to the image is controlled by the + * 'label_positon' attribute. + * + * By default the internal image and label wigets are sized to their natural + * preferred geometry. You can use the 'fill' attribute of LabeledImage + * to have the internal widgets fill as much of the LabeledImage allocation + * as is available. This is useful if you install a tile_pixbuf and want it + * to cover the whole widget, and not just the areas occupied by the internal + * widgets. + * + * LabeledImage also has x_padding/y_padding and x_alignment/y_alignment + * attributes that behave exaclty as those in the GtkMisc class. + * + * Note that the alignments are ignored if the fill attribute is TRUE. + */ + +#ifndef NAUTILUS_LABELED_IMAGE_H +#define NAUTILUS_LABELED_IMAGE_H + +#include <gtk/gtkcontainer.h> +#include <libnautilus-extensions/nautilus-label.h> +#include <libnautilus-extensions/nautilus-image.h> + +BEGIN_GNOME_DECLS + +#define NAUTILUS_TYPE_LABELED_IMAGE (nautilus_labeled_image_get_type ()) +#define NAUTILUS_LABELED_IMAGE(obj) (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_LABELED_IMAGE, NautilusLabeledImage)) +#define NAUTILUS_LABELED_IMAGE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_LABELED_IMAGE, NautilusLabeledImageClass)) +#define NAUTILUS_IS_LABELED_IMAGE(obj) (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_LABELED_IMAGE)) +#define NAUTILUS_IS_LABELED_IMAGE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_LABELED_IMAGE)) + +typedef struct _NautilusLabeledImage NautilusLabeledImage; +typedef struct _NautilusLabeledImageClass NautilusLabeledImageClass; +typedef struct _NautilusLabeledImageDetails NautilusLabeledImageDetails; + +struct _NautilusLabeledImage +{ + /* Superclass */ + GtkContainer container; + + /* Private things */ + NautilusLabeledImageDetails *details; +}; + +struct _NautilusLabeledImageClass +{ + GtkContainerClass parent_class; +}; + +/* Public GtkLabeledImage methods */ +GtkType nautilus_labeled_image_get_type (void); +GtkWidget * nautilus_labeled_image_new (const char *text, + GdkPixbuf *pixbuf); +void nautilus_labeled_image_set_label_position (NautilusLabeledImage *labeled_image, + GtkPositionType label_position); +GtkPositionType nautilus_labeled_image_get_label_position (const NautilusLabeledImage *labeled_image); +void nautilus_labeled_image_set_show_label (NautilusLabeledImage *labeled_image, + gboolean show_label); +gboolean nautilus_labeled_image_get_show_label (const NautilusLabeledImage *labeled_image); +void nautilus_labeled_image_set_show_image (NautilusLabeledImage *labeled_image, + gboolean show_image); +gboolean nautilus_labeled_image_get_show_image (const NautilusLabeledImage *labeled_image); +void nautilus_labeled_image_set_spacing (NautilusLabeledImage *labeled_image, + guint spacing); +guint nautilus_labeled_image_get_spacing (const NautilusLabeledImage *labeled_image); +int nautilus_labeled_image_get_x_padding (const NautilusLabeledImage *labeled_image); +void nautilus_labeled_image_set_x_padding (NautilusLabeledImage *labeled_image, + int x_padding); +int nautilus_labeled_image_get_y_padding (const NautilusLabeledImage *labeled_image); +void nautilus_labeled_image_set_y_padding (NautilusLabeledImage *labeled_image, + int y_padding); +float nautilus_labeled_image_get_x_alignment (const NautilusLabeledImage *labeled_image); +void nautilus_labeled_image_set_x_alignment (NautilusLabeledImage *labeled_image, + float x_alignment); +float nautilus_labeled_image_get_y_alignment (const NautilusLabeledImage *labeled_image); +void nautilus_labeled_image_set_y_alignment (NautilusLabeledImage *labeled_image, + float y_alignment); +void nautilus_labeled_image_set_fill (NautilusLabeledImage *labeled_image, + gboolean fill); +gboolean nautilus_labeled_image_get_fill (const NautilusLabeledImage *labeled_image); + +/* Functions for creating stock GtkButtons with a labeled image child */ +GtkWidget * nautilus_labeled_image_button_new (const char *text, + GdkPixbuf *pixbuf); +GtkWidget * nautilus_labeled_image_toggle_button_new (const char *text, + GdkPixbuf *pixbuf); +GtkWidget * nautilus_labeled_image_check_button_new (const char *text, + GdkPixbuf *pixbuf); + +/* These are proxies for methods in NautilusImage and NautilusLabel */ +void nautilus_labeled_image_set_pixbuf (NautilusLabeledImage *labeled_image, + GdkPixbuf *pixbuf); +void nautilus_labeled_image_set_pixbuf_from_file_name (NautilusLabeledImage *labeled_image, + const char *file_name); +GdkPixbuf* nautilus_labeled_image_get_pixbuf (const NautilusLabeledImage *labeled_image); +void nautilus_labeled_image_set_text (NautilusLabeledImage *labeled_image, + const char *text); +char* nautilus_labeled_image_get_text (const NautilusLabeledImage *labeled_image); +void nautilus_labeled_image_set_tile_pixbuf (NautilusLabeledImage *image, + GdkPixbuf *pixbuf); +void nautilus_labeled_image_set_tile_pixbuf_from_file_name (NautilusLabeledImage *image, + const char *tile_file_name); +void nautilus_labeled_image_make_bold (NautilusLabeledImage *labeled_image); +void nautilus_labeled_image_make_larger (NautilusLabeledImage *labeled_image, + guint num_sizes); +void nautilus_labeled_image_make_smaller (NautilusLabeledImage *labeled_image, + guint num_sizes); +void nautilus_labeled_image_set_tile_width (NautilusLabeledImage *labeled_image, + int tile_width); +void nautilus_labeled_image_set_tile_height (NautilusLabeledImage *labeled_image, + int tile_height); +void nautilus_labeled_image_set_background_mode (NautilusLabeledImage *labeled_image, + NautilusSmoothBackgroundMode background_mode); +void nautilus_labeled_image_set_solid_background_color (NautilusLabeledImage *labeled_image, + guint32 solid_background_color); +void nautilus_labeled_image_set_smooth_drop_shadow_offset (NautilusLabeledImage *labeled_image, + guint drop_shadow_offset); +void nautilus_labeled_image_set_smooth_drop_shadow_color (NautilusLabeledImage *labeled_image, + guint32 drop_shadow_color); +void nautilus_labeled_image_set_text_color (NautilusLabeledImage *labeled_image, + guint32 text_color); + +END_GNOME_DECLS + +#endif /* NAUTILUS_LABELED_IMAGE_H */ + + diff --git a/libnautilus-private/nautilus-smooth-widget.c b/libnautilus-private/nautilus-smooth-widget.c index ec82c692e..3b144263e 100644 --- a/libnautilus-private/nautilus-smooth-widget.c +++ b/libnautilus-private/nautilus-smooth-widget.c @@ -204,6 +204,13 @@ smooth_widget_get_tile_origin_point (const GtkWidget *widget, origin_point = NAUTILUS_ART_IPOINT_ZERO; + /* Using '0' for the ancestor origin works because our buddy GTK+ + * already makes our allocation.{x,y} the collected offsets of all + * our ancestors. + * + * It might be more correct to make this the allocation.{x,y} of the + * ancestor windowed widget - maybe. + */ switch (tile_mode_vertical) { case NAUTILUS_SMOOTH_TILE_SELF: origin_point.y = widget->allocation.y; @@ -960,8 +967,8 @@ nautilus_smooth_widget_get_preferred_frame (const GtkWidget *widget, nautilus_art_irect_assign (&preferred_frame, 0, 0, - MAX (content_frame->x1, tile_width) + (2 * GTK_MISC (widget)->xpad * 2), - MAX (content_frame->y1, tile_height) + (2 * GTK_MISC (widget)->ypad * 2)); + MAX (content_frame->x1, tile_width) + (2 * GTK_MISC (widget)->xpad), + MAX (content_frame->y1, tile_height) + (2 * GTK_MISC (widget)->ypad)); /* Make sure the frame is not zero. Gtk goes berserk with zero size widget */ preferred_frame.x1 = MAX (preferred_frame.x1, 2); diff --git a/test/.cvsignore b/test/.cvsignore index 8703d5a0e..617de9093 100644 --- a/test/.cvsignore +++ b/test/.cvsignore @@ -6,6 +6,7 @@ Makefile Makefile.in test-nautilus-async-activation test-nautilus-background +test-nautilus-clickable-image test-nautilus-font test-nautilus-font-picker test-nautilus-font-simple @@ -21,6 +22,7 @@ test-nautilus-label-offset test-nautilus-label-scrolled test-nautilus-label-simple test-nautilus-label-wrapped +test-nautilus-labeled-image test-nautilus-mime-actions test-nautilus-mime-actions-set test-nautilus-password-dialog diff --git a/test/Makefile.am b/test/Makefile.am index 782e1acfd..1eff0a8ff 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -28,35 +28,38 @@ LDADD =\ $(NULL) noinst_PROGRAMS =\ - test-nautilus-async-activation \ - test-nautilus-background \ - test-nautilus-font \ - test-nautilus-font-picker \ - test-nautilus-font-simple \ - test-nautilus-image \ - test-nautilus-image-background \ - test-nautilus-image-scrolled \ - test-nautilus-image-simple \ - test-nautilus-image-tile \ - test-nautilus-label \ - test-nautilus-label-background \ - test-nautilus-label-flavorful \ - test-nautilus-label-offset \ - test-nautilus-label-scrolled \ - test-nautilus-label-simple \ - test-nautilus-label-wrapped \ - test-nautilus-mime-actions \ - test-nautilus-mime-actions-set \ - test-nautilus-password-dialog \ - test-nautilus-pixbuf-tile \ - test-nautilus-smooth-graphics \ - test-nautilus-widgets \ - test-nautilus-preferences-display \ + test-nautilus-async-activation \ + test-nautilus-background \ + test-nautilus-font \ + test-nautilus-font-picker \ + test-nautilus-font-simple \ + test-nautilus-image \ + test-nautilus-image-background \ + test-nautilus-clickable-image \ + test-nautilus-image-scrolled \ + test-nautilus-image-simple \ + test-nautilus-image-tile \ + test-nautilus-label \ + test-nautilus-label-background \ + test-nautilus-label-flavorful \ + test-nautilus-label-offset \ + test-nautilus-label-scrolled \ + test-nautilus-label-simple \ + test-nautilus-label-wrapped \ + test-nautilus-labeled-image \ + test-nautilus-mime-actions \ + test-nautilus-mime-actions-set \ + test-nautilus-password-dialog \ + test-nautilus-pixbuf-tile \ test-nautilus-preferences-change \ + test-nautilus-preferences-display \ + test-nautilus-smooth-graphics \ + test-nautilus-widgets \ $(NULL) test_nautilus_async_activation_SOURCES = test-nautilus-async-activation.c test_nautilus_background_SOURCES = test-nautilus-background.c +test_nautilus_clickable_image_SOURCES = test-nautilus-clickable-image.c test.c test_nautilus_font_SOURCES = test-nautilus-font.c test.c test_nautilus_font_picker_SOURCES = test-nautilus-font-picker.c test_nautilus_font_simple_SOURCES = test-nautilus-font-simple.c test.c @@ -70,8 +73,9 @@ test_nautilus_label_background_SOURCES = test-nautilus-label-background.c test.c test_nautilus_label_flavorful_SOURCES = test-nautilus-label-flavorful.c test_nautilus_label_offset_SOURCES = test-nautilus-label-offset.c test.c test_nautilus_label_scrolled_SOURCES = test-nautilus-label-scrolled.c test.c -test_nautilus_label_simple_SOURCES = test-nautilus-label-simple.c +test_nautilus_label_simple_SOURCES = test-nautilus-label-simple.c test.c test_nautilus_label_wrapped_SOURCES = test-nautilus-label-wrapped.c +test_nautilus_labeled_image_SOURCES = test-nautilus-labeled-image.c test.c test_nautilus_mime_actions_SOURCES = test-nautilus-mime-actions.c test_nautilus_mime_actions_set_SOURCES = test-nautilus-mime-actions-set.c test_nautilus_password_dialog_SOURCES = test-nautilus-password-dialog.c diff --git a/test/test-nautilus-clickable-image.c b/test/test-nautilus-clickable-image.c new file mode 100644 index 000000000..742f30858 --- /dev/null +++ b/test/test-nautilus-clickable-image.c @@ -0,0 +1,76 @@ +#include "test.h" + +#include <libnautilus-extensions/nautilus-clickable-image.h> + +static void +clicked_callback (GtkWidget *widget, + gpointer callback_data) +{ + g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (widget)); + + g_print ("%s(%p)\n", __FUNCTION__, widget); +} + +static void +enter_callback (GtkWidget *widget, + gpointer callback_data) +{ + g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (widget)); + + g_print ("%s(%p)\n", __FUNCTION__, widget); +} + + +static void +leave_callback (GtkWidget *widget, + gpointer callback_data) +{ + g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (widget)); + + g_print ("%s(%p)\n", __FUNCTION__, widget); +} + +static GtkWidget * +clickable_image_new (const char *text, GdkPixbuf *pixbuf) +{ + GtkWidget *clickable_image; + + clickable_image = nautilus_clickable_image_new (text, pixbuf); + + gtk_signal_connect (GTK_OBJECT (clickable_image), "clicked", GTK_SIGNAL_FUNC (clicked_callback), NULL); + gtk_signal_connect (GTK_OBJECT (clickable_image), "enter", GTK_SIGNAL_FUNC (enter_callback), NULL); + gtk_signal_connect (GTK_OBJECT (clickable_image), "leave", GTK_SIGNAL_FUNC (leave_callback), NULL); + + return clickable_image; +} + +int +main (int argc, char* argv[]) +{ + GtkWidget *window; + GtkWidget *vbox; + GtkWidget *clickable_images[3]; + GdkPixbuf *pixbuf; + + test_init (&argc, &argv); + + window = test_window_new ("Simple Label Test", 20); + vbox = gtk_vbox_new (TRUE, 10); + gtk_container_add (GTK_CONTAINER (window), vbox); + + pixbuf = test_pixbuf_new_named ("/usr/share/pixmaps/gnome-globe.png", 1.0); + clickable_images[0] = clickable_image_new ("Clickable Image", pixbuf); + clickable_images[1] = clickable_image_new ("Clickable Image No pixbuf", NULL); + clickable_images[2] = clickable_image_new (NULL, pixbuf); + gdk_pixbuf_unref (pixbuf); + + gtk_box_pack_start (GTK_BOX (vbox), clickable_images[0], FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox), clickable_images[1], FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox), clickable_images[2], FALSE, FALSE, 0); + + gtk_widget_show_all (window); + + gtk_main (); + + return 0; +} diff --git a/test/test-nautilus-label-background.c b/test/test-nautilus-label-background.c index 935886fdb..4a7869ce1 100644 --- a/test/test-nautilus-label-background.c +++ b/test/test-nautilus-label-background.c @@ -4,6 +4,7 @@ #include <libnautilus-extensions/nautilus-label-with-background.h> static const char tile_name[] = "patterns/camouflage.png"; +//static const char *tile_name = NULL; static GtkWidget * window_new_with_nautilus_background_image (void) diff --git a/test/test-nautilus-label-scrolled.c b/test/test-nautilus-label-scrolled.c index 545e3ed35..2480c2853 100644 --- a/test/test-nautilus-label-scrolled.c +++ b/test/test-nautilus-label-scrolled.c @@ -86,7 +86,7 @@ label_window_new_scrolled (void) NULL); nautilus_label_set_wrap (NAUTILUS_LABEL (label), TRUE); nautilus_label_set_justify (NAUTILUS_LABEL (label), GTK_JUSTIFY_LEFT); - nautilus_label_make_larger (NAUTILUS_LABEL (label), 10); +// nautilus_label_make_larger (NAUTILUS_LABEL (label), 10); gtk_container_add (GTK_CONTAINER (viewport), label); @@ -161,7 +161,7 @@ label_window_new_table (void) 0, NAUTILUS_RGB_COLOR_WHITE, NULL); - nautilus_label_make_larger (NAUTILUS_LABEL (label[2]), 40); +// nautilus_label_make_larger (NAUTILUS_LABEL (label[2]), 40); gtk_table_attach (GTK_TABLE (table), label[0], 0, 1, 0, 1, GTK_FILL, GTK_FILL, 4, 4); gtk_table_attach (GTK_TABLE (table), label[1], 1, 2, 18, 19, GTK_FILL, GTK_FILL, 4, 4); diff --git a/test/test-nautilus-label-simple.c b/test/test-nautilus-label-simple.c index 46247f10d..9a8ce235a 100644 --- a/test/test-nautilus-label-simple.c +++ b/test/test-nautilus-label-simple.c @@ -1,153 +1,31 @@ -#include <config.h> +#include "test.h" -#include <gtk/gtk.h> - -#include <libnautilus-extensions/nautilus-label.h> -#include <libnautilus-extensions/nautilus-gtk-extensions.h> - -#include <libgnomevfs/gnome-vfs-init.h> - -typedef struct +int +main (int argc, char* argv[]) { GtkWidget *window; - GtkWidget *vbox; - GtkWidget *entry; - GtkWidget *hbox; - GtkWidget *smooth_toggle; - GtkWidget *frame; GtkWidget *label; -} Window; -static void -delete_event (GtkWidget *widget, GdkEvent *event, gpointer callback_data) -{ - gtk_main_quit (); -} + test_init (&argc, &argv); -#if 0 -static void -toggle_smooth_callback (GtkWidget *widget, gpointer callback_data) -{ - Window *window; - NautilusLabel *label; + window = test_window_new ("Simple Label Test", 20); - window = (Window *) callback_data; + if (0) { + GtkWidget *frame; + GtkWidget *main_vbox; - if (!NAUTILUS_IS_LABEL (window->label)) { - return; + main_vbox = gtk_vbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER (window), main_vbox); + frame = gtk_frame_new ("Foo"); + label = nautilus_label_new ("This is a very intersting label\nThat has more\nthan one line."); + gtk_container_add (GTK_CONTAINER (frame), label); + gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0); + } else { + label = nautilus_label_new ("This is a very intersting label\nThat has more\nthan one line."); + gtk_container_add (GTK_CONTAINER (window), label); } - label = NAUTILUS_LABEL (window->label); - - nautilus_label_set_is_smooth (label, !nautilus_label_get_is_smooth (label)); -} -#endif - -static Window * -window_new (const char *title, guint border_width) -{ - Window *window; - GtkWidget *main_vbox; - - window = g_new0 (Window, 1); - - window->window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - main_vbox = gtk_vbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (window->window), main_vbox); - - if (title != NULL) { - - gtk_window_set_title (GTK_WINDOW (window->window), title); - } - - gtk_signal_connect (GTK_OBJECT (window->window), - "delete_event", - GTK_SIGNAL_FUNC (delete_event), - NULL); - - gtk_window_set_policy (GTK_WINDOW (window->window), TRUE, TRUE, FALSE); - gtk_container_set_border_width (GTK_CONTAINER (window->window), border_width); - - window->vbox = gtk_vbox_new (FALSE, 0); - window->entry = gtk_entry_new (); - window->hbox = gtk_hbox_new (FALSE, 0); -// window->smooth_toggle = gtk_check_button_new_with_label ("Smooth"); - - gtk_box_pack_start (GTK_BOX (main_vbox), window->vbox, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (main_vbox), window->hbox, FALSE, FALSE, 0); - gtk_box_pack_end (GTK_BOX (main_vbox), window->entry, FALSE, FALSE, 0); - -// gtk_box_pack_start (GTK_BOX (window->hbox), window->smooth_toggle, FALSE, FALSE, 0); - - gtk_widget_show (main_vbox); - gtk_widget_show (window->vbox); - gtk_widget_show (window->hbox); - gtk_widget_show (window->entry); -// gtk_widget_show (window->smooth_toggle); - -#if 0 - gtk_signal_connect (GTK_OBJECT (window->smooth_toggle), - "toggled", - GTK_SIGNAL_FUNC (toggle_smooth_callback), - window); -#endif - - return window; -} - -static Window * -label_window_new (const char *title, - guint border_width, - const char *file_name, - const char *tile_file_name) -{ - Window *window; - - window = window_new (title, border_width); - - window->frame = gtk_frame_new ("Foo"); - window->label = nautilus_label_new (file_name); - - if (tile_file_name != NULL) { - nautilus_label_set_tile_pixbuf_from_file_name (NAUTILUS_LABEL (window->label), - tile_file_name); - } - - gtk_container_add (GTK_CONTAINER (window->frame), window->label); - - gtk_box_pack_start (GTK_BOX (window->vbox), window->frame, TRUE, TRUE, 0); - - gtk_widget_show (window->label); - gtk_widget_show (window->frame); - - //gtk_widget_set_sensitive (window->smooth_toggle, TRUE); -/* gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (window->smooth_toggle), */ -/* nautilus_label_get_is_smooth (NAUTILUS_LABEL (window->label))); */ - - return window; -} - -int -main (int argc, char* argv[]) -{ - Window *window; - - gtk_init (&argc, &argv); - gdk_rgb_init (); - gnome_vfs_init (); - - window = label_window_new ("Nautilus Label", - 100, - "This is a very intersting label\nThat has more\nthan one line.", - NULL); - //"/gnome/share/nautilus/patterns/pale_coins.png"); - //window = label_window_new ("Nautilus Label", 100, "eazel-logo-right-side-logo.png"); - //window = label_window_new ("Nautilus Label", 100, "foo.png"); - -// debug_widget_set_background_label (window->window, "pale_coins.png"); -// debug_widget_set_background_label (window->label, "pale_coins.png"); - - gtk_widget_show (window->window); + gtk_widget_show_all (window); gtk_main (); diff --git a/test/test-nautilus-label.c b/test/test-nautilus-label.c index 75283a6cf..2bbabd9c1 100644 --- a/test/test-nautilus-label.c +++ b/test/test-nautilus-label.c @@ -757,7 +757,7 @@ main (int argc, char* argv[]) main_box = gtk_vbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER (window), main_box); - label = nautilus_label_new ("Label that doesn't suck"); + label = nautilus_label_new ("Foo"); bottom_box = gtk_vbox_new (FALSE, 4); diff --git a/test/test-nautilus-labeled-image.c b/test/test-nautilus-labeled-image.c new file mode 100644 index 000000000..3eb2420bd --- /dev/null +++ b/test/test-nautilus-labeled-image.c @@ -0,0 +1,101 @@ +#include "test.h" + +#include <libnautilus-extensions/nautilus-labeled-image.h> + + +static const char pixbuf_name[] = "/usr/share/pixmaps/gnome-globe.png"; +static const char tile_name[] = "/gnome/share/nautilus/patterns/camouflage.png"; + +static GtkWidget * +labeled_image_new (const char *text, + GdkPixbuf *pixbuf, + const char *tile_file_name) +{ + GtkWidget *labeled_image; + + labeled_image = nautilus_labeled_image_new (text, pixbuf); + + if (tile_file_name != NULL) { + nautilus_labeled_image_set_tile_pixbuf_from_file_name (NAUTILUS_LABELED_IMAGE (labeled_image), + tile_file_name); + } + + return labeled_image; +} + +static GtkWidget * +labeled_image_window_new (const char *title, + GdkPixbuf *pixbuf, + const char *tile_file_name) +{ + GtkWidget *window; + GtkWidget *vbox; + GtkWidget *labeled_image; + GtkWidget *tiled_labeled_image; + + window = test_window_new (title, 20); + vbox = gtk_vbox_new (FALSE, 10); + gtk_container_add (GTK_CONTAINER (window), vbox); + + labeled_image = labeled_image_new ("Labeled Image", pixbuf, NULL); + tiled_labeled_image = labeled_image_new ("Labeled Image", pixbuf, tile_file_name); + if (tile_file_name != NULL) { + nautilus_labeled_image_set_fill (NAUTILUS_LABELED_IMAGE (tiled_labeled_image), TRUE); + } + if (labeled_image) gtk_box_pack_start (GTK_BOX (vbox), labeled_image, TRUE, TRUE, 0); + if (tiled_labeled_image) gtk_box_pack_start (GTK_BOX (vbox), tiled_labeled_image, TRUE, TRUE, 0); + + gtk_widget_show_all (vbox); + + return window; +} + +static GtkWidget * +labeled_image_button_window_new (const char *title, + GdkPixbuf *pixbuf) +{ + GtkWidget *window; + GtkWidget *vbox; + GtkWidget *button; + GtkWidget *toggle_button; + GtkWidget *check_button; + + window = test_window_new (title, 20); + vbox = gtk_vbox_new (FALSE, 10); + gtk_container_add (GTK_CONTAINER (window), vbox); + + if (1) button = nautilus_labeled_image_button_new ("GtkButton with LabeledImage", pixbuf); + if (1) toggle_button = nautilus_labeled_image_toggle_button_new ("GtkToggleButton with LabeledImage", pixbuf); + if (1) check_button = nautilus_labeled_image_check_button_new ("GtkCheckButton with LabeledImage", pixbuf); + + if (button) gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0); + if (toggle_button) gtk_box_pack_start (GTK_BOX (vbox), toggle_button, TRUE, TRUE, 0); + if (check_button) gtk_box_pack_start (GTK_BOX (vbox), check_button, TRUE, TRUE, 0); + + gtk_widget_show_all (vbox); + + return window; +} + +int +main (int argc, char* argv[]) +{ + GtkWidget *labeled_image_window = NULL; + GtkWidget *labeled_image_button_window = NULL; + GdkPixbuf *pixbuf = NULL; + + test_init (&argc, &argv); + + if (1) pixbuf = test_pixbuf_new_named (pixbuf_name, 1.0); + if (1) labeled_image_window = labeled_image_window_new ("LabeledImage Test", pixbuf, tile_name); + if (1) labeled_image_button_window = labeled_image_button_window_new ("LabeledImage in GtkButton Test", pixbuf); + + nautilus_gdk_pixbuf_unref_if_not_null (pixbuf); + + if (labeled_image_window) gtk_widget_show (labeled_image_window); + if (labeled_image_button_window) gtk_widget_show (labeled_image_button_window); + + gtk_main (); + + return 0; +} diff --git a/test/test-nautilus-pixbuf-tile.c b/test/test-nautilus-pixbuf-tile.c index 44ee5fb83..14fe33810 100644 --- a/test/test-nautilus-pixbuf-tile.c +++ b/test/test-nautilus-pixbuf-tile.c @@ -1,276 +1,144 @@ - -#include <config.h> - #include "test.h" -#if 0 -#include <libnautilus-extensions/nautilus-background.h> -#include <libnautilus-extensions/nautilus-file-utilities.h> -#include <libnautilus-extensions/nautilus-font-factory.h> -#include <libnautilus-extensions/nautilus-glib-extensions.h> -#include <libnautilus-extensions/nautilus-gdk-extensions.h> -#include <libnautilus-extensions/nautilus-gtk-extensions.h> -#include <libnautilus-extensions/nautilus-gdk-pixbuf-extensions.h> -#include <libnautilus-extensions/nautilus-icon-factory.h> -#include <libnautilus-extensions/nautilus-string-list.h> -#include <libnautilus-extensions/nautilus-string-picker.h> -#include <libnautilus-extensions/nautilus-font-picker.h> -#include <libnautilus-extensions/nautilus-text-caption.h> - -#include <libnautilus-extensions/nautilus-scalable-font.h> -#include <libnautilus-extensions/nautilus-string.h> - -#include <libnautilus-extensions/nautilus-debug-drawing.h> - -#include <libart_lgpl/art_vpath.h> -#include <libart_lgpl/art_svp.h> -#include <libart_lgpl/art_svp_vpath_stroke.h> -#include <libart_lgpl/art_rgb_svp.h> -#include <libart_lgpl/art_svp_vpath.h> -#include <libart_lgpl/art_rgb.h> - -#include <libgnomevfs/gnome-vfs-init.h> - -/* Danger! Many Gremlins live here. */ - -/* FIXME bugzilla.eazel.com 5031: Need to account for word endianess in these macros */ -#define ART_OPACITY_NONE 255 -#define ART_OPACITY_FULL 0 - -/* Pack RGBA values */ -#define ART_RGBA_COLOR_PACK(_r, _g, _b, _a) \ -( ((_a) << 0) | \ - ((_r) << 24) | \ - ((_g) << 16) | \ - ((_b) << 8) ) +#include <libnautilus-extensions/nautilus-labeled-image.h> -#define ART_RGB_COLOR_PACK(_r, _g, _b) \ -( (ART_OPACITY_NONE << 0) | \ - ((_r) << 24) | \ - ((_g) << 16) | \ - ((_b) << 8) ) -/* Access the individual RGBA components */ -#define ART_RGBA_GET_R(_color) (((_color) >> 24) & 0xff) -#define ART_RGBA_GET_G(_color) (((_color) >> 16) & 0xff) -#define ART_RGBA_GET_B(_color) (((_color) >> 8) & 0xff) -#define ART_RGBA_GET_A(_color) (((_color) >> 0) & 0xff) +static const char pixbuf_name[] = "/usr/share/pixmaps/gnome-globe.png"; +static const char tile_name[] = "/gnome/share/nautilus/patterns/camouflage.png"; -#define RED ART_RGB_COLOR_PACK (255, 0, 0) -#define GREEN ART_RGB_COLOR_PACK (0, 255, 0) -#define BLUE ART_RGB_COLOR_PACK (0, 0, 255) -#define WHITE ART_RGB_COLOR_PACK (255, 255, 255) -#define BLACK ART_RGB_COLOR_PACK (0, 0, 0) -#define TRANSPARENT ART_RGBA_COLOR_PACK (255, 255, 255, 0) - -static GdkPixbuf * -create_named_background (const char *name) +static int +pixbuf_drawing_area_expose_event (GtkWidget *widget, + GdkEventExpose *event, + gpointer callback_data) { - GdkPixbuf *pixbuf; - char *path; - - g_return_val_if_fail (name != NULL, NULL); - - path = nautilus_make_path (NAUTILUS_DATADIR "/patterns", name); - - if (path == NULL) { - return NULL; - } + static GdkPixbuf *tile = NULL; + GdkPixbuf *buffer; + ArtIRect dest; + ArtIRect tile_area; - pixbuf = gdk_pixbuf_new_from_file (path); - g_free (path); + buffer = nautilus_gdk_pixbuf_get_global_buffer (widget->allocation.width, widget->allocation.height); - return pixbuf; -} + if (tile == NULL) { + tile = gdk_pixbuf_new_from_file (tile_name); + g_assert (tile != NULL); + } -static void -rgba_run_alpha (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n) -{ - int i; - int v; + tile_area.x0 = 0; + tile_area.y0 = 0; + tile_area.x1 = widget->allocation.width; + tile_area.y1 = widget->allocation.height; - for (i = 0; i < n; i++) - { - v = *buf; - *buf++ = v + (((r - v) * alpha + 0x80) >> 8); - v = *buf; - *buf++ = v + (((g - v) * alpha + 0x80) >> 8); - v = *buf; - *buf++ = v + (((b - v) * alpha + 0x80) >> 8); + nautilus_gdk_pixbuf_draw_to_pixbuf_tiled (tile, + buffer, + &tile_area, + gdk_pixbuf_get_width (tile), + gdk_pixbuf_get_height (tile), + 0, + 0, + NAUTILUS_OPACITY_FULLY_OPAQUE, + GDK_INTERP_NEAREST); + + dest = nautilus_irect_gtk_widget_get_bounds (widget); + nautilus_gdk_pixbuf_draw_to_drawable (buffer, + widget->window, + widget->style->white_gc, + 0, + 0, + &dest, + GDK_RGB_DITHER_NONE, + GDK_PIXBUF_ALPHA_BILEVEL, + NAUTILUS_STANDARD_ALPHA_THRESHHOLD); + + nautilus_debug_draw_rectangle_and_cross (widget->window, &dest, 0xFF0000, TRUE); + { + ArtIRect one_tile; + one_tile.x0 = widget->allocation.x; + one_tile.y0 = widget->allocation.y; + one_tile.x1 = gdk_pixbuf_get_width (tile); + one_tile.y1 = gdk_pixbuf_get_height (tile); + + nautilus_debug_draw_rectangle_and_cross (widget->window, &one_tile, 0x0000FF, TRUE); + } - *buf++ = 255; - } + return TRUE; } -typedef void (*RunFunc) (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n); - -static void -pixbuf_draw_rectangle (GdkPixbuf *pixbuf, - const ArtIRect *rectangle, - guint32 color, - gboolean filled) +static int +drawable_drawing_area_expose_event (GtkWidget *widget, + GdkEventExpose *event, + gpointer callback_data) { - guchar red; - guchar green; - guchar blue; - guchar alpha; - - guint width; - guint height; - guchar *pixels; - guint rowstride; - int y; - gboolean has_alpha; - guint pixel_offset; - guchar *offset; - - guint rect_width; - guint rect_height; - - ArtIRect draw_area; - - RunFunc run_func; - - g_return_if_fail (pixbuf != NULL); - - width = gdk_pixbuf_get_width (pixbuf); - height = gdk_pixbuf_get_height (pixbuf); - pixels = gdk_pixbuf_get_pixels (pixbuf); - rowstride = gdk_pixbuf_get_rowstride (pixbuf); - has_alpha = gdk_pixbuf_get_has_alpha (pixbuf); - pixel_offset = has_alpha ? 4 : 3; - - red = ART_RGBA_GET_R (color); - green = ART_RGBA_GET_G (color); - blue = ART_RGBA_GET_B (color); - alpha = ART_RGBA_GET_A (color); - - run_func = has_alpha ? rgba_run_alpha : art_rgb_run_alpha; - - if (rectangle != NULL) { - g_return_if_fail (rectangle->x1 > rectangle->x0); - g_return_if_fail (rectangle->y1 > rectangle->y0); - - rect_width = rectangle->x1 - rectangle->x0; - rect_height = rectangle->y1 - rectangle->y0; - - draw_area = *rectangle; - } - else { - rect_width = width; - rect_height = height; + static GdkPixbuf *tile = NULL; + ArtIRect dest; - draw_area.x0 = 0; - draw_area.y0 = 0; - draw_area.x1 = width; - draw_area.y1 = height; + if (tile == NULL) { + tile = gdk_pixbuf_new_from_file (tile_name); + g_assert (tile != NULL); } - if (filled) { - offset = pixels + (draw_area.y0 * rowstride) + (draw_area.x0 * pixel_offset); - - for (y = draw_area.y0; y < draw_area.y1; y++) { - (*run_func) (offset, red, green, blue, 255, rect_width); - offset += rowstride; - } - } - else { - /* top */ - offset = pixels + (draw_area.y0 * rowstride) + (draw_area.x0 * pixel_offset); - (*run_func) (offset, red, green, blue, 255, rect_width); - - /* bottom */ - offset += ((rect_height - 1) * rowstride); - (*run_func) (offset, red, green, blue, 255, rect_width); + dest = nautilus_irect_gtk_widget_get_bounds (widget); + nautilus_gdk_pixbuf_draw_to_drawable_tiled (tile, + widget->window, + widget->style->white_gc, + &dest, + gdk_pixbuf_get_width (tile), + gdk_pixbuf_get_height (tile), + 0, + 0, + GDK_RGB_DITHER_NONE, + GDK_PIXBUF_ALPHA_BILEVEL, + NAUTILUS_STANDARD_ALPHA_THRESHHOLD); - for (y = draw_area.y0 + 1; y < (draw_area.y1 - 1); y++) { - /* left */ - offset = pixels + (y * rowstride) + (draw_area.x0 * pixel_offset); - (*run_func) (offset, red, green, blue, 255, 1); - - /* right */ - offset += (rect_width - 1) * pixel_offset; - (*run_func) (offset, red, green, blue, 255, 1); - } + nautilus_debug_draw_rectangle_and_cross (widget->window, &dest, 0xFF0000, TRUE); + { + ArtIRect one_tile; + one_tile.x0 = widget->allocation.x; + one_tile.y0 = widget->allocation.y; + one_tile.x1 = gdk_pixbuf_get_width (tile); + one_tile.y1 = gdk_pixbuf_get_height (tile); + + nautilus_debug_draw_rectangle_and_cross (widget->window, &one_tile, 0x0000FF, TRUE); } -} -static void -pixbuf_draw_rectangle_around (GdkPixbuf *pixbuf, - const ArtIRect *rectangle, - guint32 color) -{ - ArtIRect area; - - g_return_if_fail (pixbuf != NULL); - g_return_if_fail (rectangle != NULL); - g_return_if_fail (rectangle->x1 > rectangle->x0); - g_return_if_fail (rectangle->y1 > rectangle->y0); - - area = *rectangle; - - area.x0 -= 1; - area.y0 -= 1; - area.x1 += 1; - area.y1 += 1; - pixbuf_draw_rectangle (pixbuf, &area, color, FALSE); - area.x0 += 1; - area.y0 += 1; - area.x1 -= 1; - area.y1 -= 1; + return TRUE; } -#endif int main (int argc, char* argv[]) { - const guint pixbuf_width = 500; - const guint pixbuf_height = 700; - - GdkPixbuf *pixbuf; - GdkPixbuf *tile_pixbuf; - ArtIRect tile_area; - - test_init (&argc, &argv); - - pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, pixbuf_width, pixbuf_height); - g_assert (pixbuf != NULL); - - tile_pixbuf = test_pixbuf_new_named ("patterns/pale_coins.png", 1.0); - g_assert (tile_pixbuf != NULL); - - nautilus_art_irect_assign (&tile_area, 200, 50, 100, 100); - - nautilus_gdk_pixbuf_draw_to_pixbuf_tiled (tile_pixbuf, - pixbuf, - &tile_area, - gdk_pixbuf_get_width (tile_pixbuf), - gdk_pixbuf_get_height (tile_pixbuf), - 0, - 0, - NAUTILUS_OPACITY_FULLY_OPAQUE, - GDK_INTERP_BILINEAR); + GtkWidget *pixbuf_window; + GtkWidget *pixbuf_drawing_area; + GtkWidget *pixbuf_vbox; + GtkWidget *drawable_window; + GtkWidget *drawable_drawing_area; + GtkWidget *drawable_vbox; + test_init (&argc, &argv); - nautilus_art_irect_assign (&tile_area, 200, 150, 100, 100); - - nautilus_gdk_pixbuf_draw_to_pixbuf_tiled (tile_pixbuf, - pixbuf, - &tile_area, - gdk_pixbuf_get_width (tile_pixbuf), - gdk_pixbuf_get_height (tile_pixbuf), - 0, - 0, - NAUTILUS_OPACITY_FULLY_OPAQUE, - GDK_INTERP_BILINEAR); - - gdk_pixbuf_unref (tile_pixbuf); - - nautilus_debug_show_pixbuf_in_eog (pixbuf); - - gdk_pixbuf_unref (pixbuf); - - test_quit (0); + pixbuf_window = test_window_new ("Pixbuf To Pixbuf Tile Test", 0); + pixbuf_vbox = gtk_vbox_new (FALSE, 0); + pixbuf_drawing_area = gtk_drawing_area_new (); + gtk_signal_connect (GTK_OBJECT (pixbuf_drawing_area), + "expose_event", + GTK_SIGNAL_FUNC (pixbuf_drawing_area_expose_event), + NULL); + gtk_box_pack_start (GTK_BOX (pixbuf_vbox), pixbuf_drawing_area, TRUE, TRUE, 0); + gtk_container_add (GTK_CONTAINER (pixbuf_window), pixbuf_vbox); + gtk_widget_show_all (pixbuf_window); + + + drawable_window = test_window_new ("Pixbuf To Drawable Tile Test", 0); + drawable_vbox = gtk_vbox_new (FALSE, 0); + drawable_drawing_area = gtk_drawing_area_new (); + gtk_signal_connect (GTK_OBJECT (drawable_drawing_area), + "expose_event", + GTK_SIGNAL_FUNC (drawable_drawing_area_expose_event), + NULL); + gtk_box_pack_start (GTK_BOX (drawable_vbox), drawable_drawing_area, TRUE, TRUE, 0); + gtk_container_add (GTK_CONTAINER (drawable_window), drawable_vbox); + gtk_widget_show_all (drawable_window); + + gtk_main (); return 0; } diff --git a/test/test-nautilus-preferences-change.c b/test/test-nautilus-preferences-change.c index 9b269acdd..646abca93 100644 --- a/test/test-nautilus-preferences-change.c +++ b/test/test-nautilus-preferences-change.c @@ -4,6 +4,7 @@ #include <libnautilus-extensions/nautilus-image-with-background.h> #include <libnautilus-extensions/nautilus-string-picker.h> #include <libnautilus-extensions/nautilus-preferences.h> +#include <libnautilus-extensions/nautilus-global-preferences.h> #include <unistd.h> @@ -153,6 +154,8 @@ main (int argc, char *argv[]) test_init (&argc, &argv); + nautilus_global_preferences_initialize (); + user_level_entries = nautilus_string_list_new_from_tokens ("Beginner,Intermediate,Hacker", ",", TRUE); color_entries = nautilus_string_list_new_from_tokens ("0,1,2,3,4,5,6,7,8,9,10", ",", TRUE); fruits_entries = nautilus_string_list_new_from_tokens ("0,1,2,3", ",", TRUE); diff --git a/test/test.c b/test/test.c index 8ded85ad5..cc24a3ea4 100644 --- a/test/test.c +++ b/test/test.c @@ -10,6 +10,21 @@ test_init (int *argc, gtk_init (argc, argv); gdk_rgb_init (); gnome_vfs_init (); + + nautilus_make_warnings_and_criticals_stop_in_debugger + (G_LOG_DOMAIN, g_log_domain_glib, + "Bonobo", + "Gdk", + "GnomeUI", + "GnomeVFS", + "GnomeVFS-CORBA", + "GnomeVFS-pthread", + "Gtk", + "Nautilus", + "Nautilus-Authenticate", + "Nautilus-Tree", + "ORBit", + NULL); } void |