summaryrefslogtreecommitdiff
path: root/libnautilus-private
diff options
context:
space:
mode:
authorDarin Adler <darin@src.gnome.org>2000-02-16 19:43:10 +0000
committerDarin Adler <darin@src.gnome.org>2000-02-16 19:43:10 +0000
commit9b94323cc3a318fbf589846278beb4e85ffe6b9e (patch)
tree08391c28015a7bb5bdfd23eaa537201a9d1c5348 /libnautilus-private
parentd3d8e1d7a5e808882ede2c10b15e78e44eef4d7b (diff)
downloadnautilus-9b94323cc3a318fbf589846278beb4e85ffe6b9e.tar.gz
Added icon stretching and did some cleanups.
Stretched icons aren't yet persistent (the scale factor is not saved in metadata), but that's not much more work. * libnautilus/gnome-icon-container-private.h: * libnautilus/gnome-icon-container.h: * libnautilus/gnome-icon-container.c: (icon_new), (icon_position), (icon_set_position), (icon_get_size), (icon_set_size), (icon_toggle_selected), (icon_select), (icon_set_selected), (button_press_event), (gnome_icon_container_begin_stretch), (start_stretching), (gnome_icon_container_stretch), (continue_stretching), (gnome_icon_container_end_stretch), (end_stretching), (button_release_event), (motion_notify_event), (handle_icon_button_press), (gnome_icon_container_clear), (request_update_one), (update_icon), (get_first_selected_icon), (gnome_icon_container_show_stretch_handles), (gnome_icon_container_has_stretch_handles), (gnome_icon_container_is_stretched), (gnome_icon_container_unstretch), (compute_stretch), (nautilus_self_check_compute_stretch), (nautilus_self_check_gnome_icon_container): * libnautilus/nautilus-icons-view-icon-item.h: * libnautilus/nautilus-icons-view-icon-item.c: (nautilus_icons_view_icon_item_draw), (nautilus_icons_view_icon_item_point), (nautilus_icons_view_icon_item_set_show_stretch_handles), (nautilus_icons_view_icon_item_get_hit_stretch_handle): * libnautilus/nautilus-lib-self-check-functions.h: Added machinery for stretching icons. * src/file-manager/fm-directory-view.h: * src/file-manager/fm-directory-view.c: (append_item_context_menu_items), (fm_directory_view_real_append_item_context_menu_items), (fm_directory_view_initialize_class), (create_item_context_menu): Added machinery for views to have view-specific menu items for icons as well as for the window as a whole. * src/file-manager/fm-directory-view-icons.c: (fm_directory_view_icons_initialize_class), (fm_directory_view_icons_append_item_context_menu_items), (show_stretch_handles_cb), (unstretch_item_cb): Added menu items for stretching icons. * libnautilus/gnome-icon-container.c: (start_rubberbanding): Fixed bug that would result in two rubberband timeouts at once if you did rubberbanding quickly. * components/notes/.cvsignore: Andy's new component needs a .cvsignore file for its generated pieces. * libnautilus/nautilus-directory.c: (nautilus_directory_try_to_read_metafile), (nautilus_directory_read_metafile): Simplified logic in metafile-reading functions and fixed a bug where the vfs handle would be left open if certain categories of errors occurred. * libnautilus/nautilus-gtk-extensions.h: Added a missing gtk_marshal function. * libnautilus/nautilus-icon-factory.h: * libnautilus/nautilus-icon-factory.c: (nautilus_icon_size_for_zoom_level), (nautilus_get_icon_size_for_zoom_level), (nautilus_icon_factory_get_pixbuf_for_file), (nautilus_icon_factory_get_pixmap_and_mask_for_file): * src/nautilus-index-title.c: (nautilus_index_title_set_up_icon): * src/nautilus-zoom-control.c: (set_zoom_level): * src/file-manager/fm-directory-view-list.c: (fm_directory_view_list_bump_zoom_level), (install_icon): Made some API improvements for the icon factory. Added a missing get_ to the name nautilus_get_icon_size_for_zoom_level and added convenience functions for the most common uses of the factory. * libnautilus/ntl-content-view-frame.c: * libnautilus/ntl-meta-view-frame.c: * libnautilus/ntl-view-frame.c: Weaned all the files in libnautilus itself from using the libnautilus.h include file. They instead include the parts that they need. Also added some missing <config.h> includes.
Diffstat (limited to 'libnautilus-private')
-rw-r--r--libnautilus-private/gnome-icon-container-private.h40
-rw-r--r--libnautilus-private/gnome-icon-container.c497
-rw-r--r--libnautilus-private/gnome-icon-container.h16
-rw-r--r--libnautilus-private/nautilus-directory.c30
-rw-r--r--libnautilus-private/nautilus-gtk-extensions.h12
-rw-r--r--libnautilus-private/nautilus-icon-factory.c35
-rw-r--r--libnautilus-private/nautilus-icon-factory.h38
-rw-r--r--libnautilus-private/nautilus-icons-view-icon-item.c83
-rw-r--r--libnautilus-private/nautilus-icons-view-icon-item.h18
-rw-r--r--libnautilus-private/nautilus-lib-self-check-functions.h1
10 files changed, 599 insertions, 171 deletions
diff --git a/libnautilus-private/gnome-icon-container-private.h b/libnautilus-private/gnome-icon-container-private.h
index 3ee3f4240..3f923f765 100644
--- a/libnautilus-private/gnome-icon-container-private.h
+++ b/libnautilus-private/gnome-icon-container-private.h
@@ -36,11 +36,12 @@ typedef struct {
/* Canvas item for the icon. */
NautilusIconsViewIconItem *item;
- /* X/Y coordinates and size. We could use the GnomeCanvasItem
- * functions, but this is a lot faster
- */
+ /* X/Y coordinates. */
double x, y;
+ /* Scale factor (stretches icon). */
+ double scale;
+
/* Whether this item is selected for operation. */
gboolean is_selected : 1;
@@ -99,6 +100,20 @@ typedef struct {
guint prev_x2, prev_y2;
} GnomeIconContainerRubberbandInfo;
+typedef enum {
+ DRAG_ACTION_MOVE_OR_COPY,
+ DRAG_ACTION_STRETCH
+} DragAction;
+
+typedef struct {
+ /* Pointer position in canvas coordinates. */
+ int pointer_x, pointer_y;
+
+ /* Icon top, left, and size in canvas coordinates. */
+ int icon_x, icon_y;
+ guint icon_size;
+} StretchState;
+
struct _GnomeIconContainerDetails {
NautilusIconsController *controller;
@@ -123,6 +138,9 @@ struct _GnomeIconContainerDetails {
/* Current icon for keyboard navigation. */
GnomeIconContainerIcon *kbd_current;
+ /* Current icon with stretch handles, so we have only one. */
+ GnomeIconContainerIcon *stretch_icon;
+
/* Rubberbanding status. */
GnomeIconContainerRubberbandInfo rubberband_info;
@@ -132,20 +150,16 @@ struct _GnomeIconContainerDetails {
*/
guint kbd_icon_visibility_timer_id;
- /* the time the mouse button went down in milliseconds */
+ /* Remembered information about the start of the current event. */
guint32 button_down_time;
-
- /* Position of the pointer during the last click. */
- int drag_x, drag_y;
- /* Button currently pressed, possibly for dragging. */
+ /* Drag state. Valid only if drag_button is non-zero. */
guint drag_button;
-
- /* Icon on which the click happened. */
GnomeIconContainerIcon *drag_icon;
-
- /* Whether we are actually performing a dragging action. */
- gboolean doing_drag;
+ int drag_x, drag_y;
+ DragAction drag_action;
+ gboolean drag_started;
+ StretchState stretch_start;
/* Idle ID. */
guint idle_id;
diff --git a/libnautilus-private/gnome-icon-container.c b/libnautilus-private/gnome-icon-container.c
index d42943a86..118bd3d91 100644
--- a/libnautilus-private/gnome-icon-container.c
+++ b/libnautilus-private/gnome-icon-container.c
@@ -35,6 +35,7 @@
#include "nautilus-glib-extensions.h"
#include "nautilus-gtk-macros.h"
+#include "nautilus-lib-self-check-functions.h"
#include "gnome-icon-container-private.h"
@@ -63,13 +64,14 @@
/* Button assignments. */
#define DRAG_BUTTON 1
#define RUBBERBAND_BUTTON 1
-#define STRETCH_BUTTON 2
#define CONTEXTUAL_MENU_BUTTON 3
static void gnome_icon_container_initialize_class (GnomeIconContainerClass *class);
static void gnome_icon_container_initialize (GnomeIconContainer *container);
-static void request_update_one (GnomeIconContainer *container,
- GnomeIconContainerIcon *icon);
+static void update_icon (GnomeIconContainer *container,
+ GnomeIconContainerIcon *icon);
+static void compute_stretch (StretchState *start,
+ StretchState *current);
NAUTILUS_DEFINE_CLASS_BOILERPLATE (GnomeIconContainer, gnome_icon_container, GNOME_TYPE_CANVAS)
@@ -107,10 +109,11 @@ icon_new (GnomeIconContainer *container,
GnomeIconContainerIcon *new;
GnomeCanvas *canvas;
- canvas = GNOME_CANVAS(container);
+ canvas = GNOME_CANVAS (container);
new = g_new0 (GnomeIconContainerIcon, 1);
+ new->scale = 1.0;
new->layout_done = TRUE;
new->data = data;
@@ -120,14 +123,14 @@ icon_new (GnomeIconContainer *container,
nautilus_icons_view_icon_item_get_type (),
NULL));
- request_update_one (container, new);
+ update_icon (container, new);
return new;
}
static void
-icon_position (GnomeIconContainerIcon *icon,
- double x, double y)
+icon_set_position (GnomeIconContainerIcon *icon,
+ double x, double y)
{
if (icon->x == x && icon->y == y)
return;
@@ -140,6 +143,30 @@ icon_position (GnomeIconContainerIcon *icon,
icon->y = y;
}
+static guint
+icon_get_size (GnomeIconContainer *container,
+ GnomeIconContainerIcon *icon)
+{
+ return MAX (nautilus_get_icon_size_for_zoom_level (container->details->zoom_level)
+ * icon->scale,
+ NAUTILUS_ICON_SIZE_SMALLEST);
+}
+
+static void
+icon_set_size (GnomeIconContainer *container,
+ GnomeIconContainerIcon *icon,
+ guint icon_size)
+{
+ if (icon_size == icon_get_size (container, icon))
+ return;
+
+ icon->scale = (double) icon_size /
+ nautilus_get_icon_size_for_zoom_level
+ (container->details->zoom_level);
+
+ update_icon (container, icon);
+}
+
static void
icon_raise (GnomeIconContainerIcon *icon)
{
@@ -153,18 +180,28 @@ icon_show (GnomeIconContainerIcon *icon)
}
static void
-icon_toggle_selected (GnomeIconContainerIcon *icon)
+icon_toggle_selected (GnomeIconContainer *container,
+ GnomeIconContainerIcon *icon)
{
icon->is_selected = !icon->is_selected;
gnome_canvas_item_set (GNOME_CANVAS_ITEM (icon->item),
"highlighted_for_selection", (gboolean) icon->is_selected,
NULL);
+
+ /* If the icon is deselected, then get rid of the stretch handles.
+ * No harm in doing the same if the item is newly selected.
+ */
+ if (icon == container->details->stretch_icon) {
+ container->details->stretch_icon = NULL;
+ nautilus_icons_view_icon_item_set_show_stretch_handles (icon->item, FALSE);
+ }
}
/* Select an icon. Return TRUE if selection has changed. */
static gboolean
-icon_select (GnomeIconContainerIcon *icon,
- gboolean select)
+icon_set_selected (GnomeIconContainer *container,
+ GnomeIconContainerIcon *icon,
+ gboolean select)
{
/* Since is_selected is a bit field, we have to do the ! business
* to be sure we have either a 1 or a 0. Similarly, the caller
@@ -174,7 +211,7 @@ icon_select (GnomeIconContainerIcon *icon,
if (!select == !icon->is_selected)
return FALSE;
- icon_toggle_selected (icon);
+ icon_toggle_selected (container, icon);
g_assert (!select == !icon->is_selected);
return TRUE;
}
@@ -902,7 +939,7 @@ select_one_unselect_others (GnomeIconContainer *container,
GnomeIconContainerIcon *icon;
icon = p->data;
- selection_changed |= icon_select (icon, icon == icon_to_select);
+ selection_changed |= icon_set_selected (container, icon, icon == icon_to_select);
}
return selection_changed;
@@ -959,7 +996,7 @@ gnome_icon_container_move_icon (GnomeIconContainer *container,
if (new_x_offset > 0 && new_y_offset > 0)
icon_grid_add (details->grid, icon, new_grid_x + 1, new_grid_y + 1);
- icon_position (icon, x, y);
+ icon_set_position (icon, x, y);
if (raise)
icon_raise (icon);
@@ -1003,11 +1040,11 @@ rubberband_select_in_cell (GnomeIconContainer *container,
prev_x2, prev_y2);
if (in_curr_region && ! in_prev_region)
- selection_changed |= icon_select (icon,
- !icon->was_selected_before_rubberband);
+ selection_changed |= icon_set_selected (container, icon,
+ !icon->was_selected_before_rubberband);
else if (in_prev_region && ! in_curr_region)
- selection_changed |= icon_select (icon,
- icon->was_selected_before_rubberband);
+ selection_changed |= icon_set_selected (container, icon,
+ icon->was_selected_before_rubberband);
}
return selection_changed;
@@ -1197,9 +1234,10 @@ start_rubberbanding (GnomeIconContainer *container,
band_info->active = TRUE;
- band_info->timer_id = gtk_timeout_add (RUBBERBAND_TIMEOUT_INTERVAL,
- rubberband_timeout_cb,
- container);
+ if (band_info->timer_id == 0)
+ band_info->timer_id = gtk_timeout_add (RUBBERBAND_TIMEOUT_INTERVAL,
+ rubberband_timeout_cb,
+ container);
gnome_canvas_item_grab (band_info->selection_rectangle,
(GDK_POINTER_MOTION_MASK
@@ -1242,7 +1280,7 @@ kbd_move_to (GnomeIconContainer *container,
gboolean selection_changed;
selection_changed = unselect_all (container);
- selection_changed |= icon_select (icon, TRUE);
+ selection_changed |= icon_set_selected (container, icon, TRUE);
if (selection_changed)
gtk_signal_emit (GTK_OBJECT (container),
@@ -1529,7 +1567,7 @@ kbd_space (GnomeIconContainer *container,
GdkEventKey *event)
{
if (container->details->kbd_current != NULL) {
- if (icon_select (container->details->kbd_current, TRUE))
+ if (icon_set_selected (container, container->details->kbd_current, TRUE))
gtk_signal_emit (GTK_OBJECT (container),
signals[SELECTION_CHANGED]);
}
@@ -1637,9 +1675,10 @@ static gboolean
button_press_event (GtkWidget *widget,
GdkEventButton *event)
{
+ GnomeIconContainer *container;
gboolean return_value;
- GnomeIconContainer *container = GNOME_ICON_CONTAINER (widget);
-
+
+ container = GNOME_ICON_CONTAINER (widget);
container->details->button_down_time = event->time;
/* Invoke the canvas event handler and see if an item picks up the event. */
@@ -1698,13 +1737,16 @@ gnome_icon_container_almost_drag (GnomeIconContainer *container,
}
if (details->drag_icon != NULL) {
- int elapsed_time = event->time - details->button_down_time;
+ int elapsed_time;
+
set_kbd_current (container, details->drag_icon, TRUE);
/* If single-click mode, activate the icon, unless modifying
* the selection or pressing for a very long time.
*/
- if (details->single_click_mode && (elapsed_time < MAX_CLICK_TIME)
+ elapsed_time = event->time - details->button_down_time;
+ if (details->single_click_mode
+ && elapsed_time < MAX_CLICK_TIME
&& ! button_event_modifies_selection (event)) {
/* FIXME: This should activate all selected icons, not just one */
@@ -1712,28 +1754,76 @@ gnome_icon_container_almost_drag (GnomeIconContainer *container,
signals[ACTIVATE],
details->drag_icon->data);
}
-
- details->drag_icon = NULL;
}
}
-static void
-gnome_icon_container_begin_stretch (GnomeIconContainer *container)
+static gboolean
+start_stretching (GnomeIconContainer *container)
{
- g_message ("begin_stretch");
+ GnomeIconContainerDetails *details;
+ GnomeIconContainerIcon *icon;
+ int canvas_x, canvas_y;
+
+ details = container->details;
+ icon = details->stretch_icon;
+
+ gnome_canvas_w2c (GNOME_CANVAS (container),
+ details->drag_x, details->drag_y,
+ &canvas_x, &canvas_y);
+
+ /* Check if we hit the stretch handles. */
+ if (!nautilus_icons_view_icon_item_get_hit_stretch_handle
+ (icon->item, canvas_x, canvas_y))
+ return FALSE;
+
+ /* Set up the dragging. */
+ details->drag_action = DRAG_ACTION_STRETCH;
+ details->stretch_start.pointer_x = canvas_x;
+ details->stretch_start.pointer_y = canvas_y;
+ gnome_canvas_w2c (GNOME_CANVAS (container),
+ icon->x, icon->y,
+ &details->stretch_start.icon_x,
+ &details->stretch_start.icon_y);
+ details->stretch_start.icon_size = icon_get_size (container, icon);
+
+ return TRUE;
}
static void
-gnome_icon_container_stretch (GnomeIconContainer *container,
- GdkEventMotion *motion)
+continue_stretching (GnomeIconContainer *container,
+ int window_x, int window_y)
{
- g_message ("stretch");
+ GnomeIconContainerDetails *details;
+ GnomeIconContainerIcon *icon;
+ double world_x, world_y;
+ StretchState stretch_state;
+
+ details = container->details;
+ icon = details->stretch_icon;
+
+ gnome_canvas_window_to_world (GNOME_CANVAS (container),
+ window_x, window_y,
+ &world_x, &world_y);
+ gnome_canvas_w2c (GNOME_CANVAS (container),
+ world_x, world_y,
+ &stretch_state.pointer_x, &stretch_state.pointer_y);
+
+ compute_stretch (&details->stretch_start,
+ &stretch_state);
+
+ gnome_canvas_c2w (GNOME_CANVAS (container),
+ stretch_state.icon_x, stretch_state.icon_y,
+ &world_x, &world_y);
+
+ icon_set_position (icon, world_x, world_y);
+ icon_set_size (container, icon, stretch_state.icon_size);
}
static void
-gnome_icon_container_end_stretch (GnomeIconContainer *container)
+end_stretching (GnomeIconContainer *container,
+ int window_x, int window_y)
{
- g_message ("end_stretch");
+ continue_stretching (container, window_x, window_y);
}
static gboolean
@@ -1754,21 +1844,16 @@ button_release_event (GtkWidget *widget,
if (event->button == details->drag_button) {
details->drag_button = 0;
- if (!details->doing_drag)
- gnome_icon_container_almost_drag (container, event);
- else {
- details->doing_drag = FALSE;
-
- switch (event->button) {
- case DRAG_BUTTON:
+ switch (details->drag_action) {
+ case DRAG_ACTION_MOVE_OR_COPY:
+ if (!details->drag_started)
+ gnome_icon_container_almost_drag (container, event);
+ else
gnome_icon_container_dnd_end_drag (container);
- break;
- case STRETCH_BUTTON:
- gnome_icon_container_end_stretch (container);
- break;
- default:
- g_assert_not_reached ();
- }
+ break;
+ case DRAG_ACTION_STRETCH:
+ end_stretching (container, event->x, event->y);
+ break;
}
return TRUE;
@@ -1788,41 +1873,37 @@ motion_notify_event (GtkWidget *widget,
container = GNOME_ICON_CONTAINER (widget);
details = container->details;
- gnome_canvas_window_to_world (GNOME_CANVAS (container),
- motion->x, motion->y,
- &world_x, &world_y);
+ if (details->drag_button != 0) {
+ switch (details->drag_action) {
+ case DRAG_ACTION_MOVE_OR_COPY:
+ if (details->drag_started)
+ break;
- if (details->drag_button != 0 && (details->doing_drag
- || (abs (details->drag_x - world_x) >= SNAP_RESISTANCE
- && abs (details->drag_y - world_y) >= SNAP_RESISTANCE))) {
- switch (details->drag_button) {
- case DRAG_BUTTON:
- details->doing_drag = TRUE;
-
- /* KLUDGE ALERT: Poke the starting values into the motion
- * structure so that dragging behaves as expected.
- */
- motion->x = details->drag_x;
- motion->y = details->drag_y;
+ gnome_canvas_window_to_world (GNOME_CANVAS (container),
+ motion->x, motion->y,
+ &world_x, &world_y);
- gnome_icon_container_dnd_begin_drag (container,
- GDK_ACTION_MOVE,
- details->drag_button,
- motion);
+ if (abs (details->drag_x - world_x) >= SNAP_RESISTANCE
+ && abs (details->drag_y - world_y) >= SNAP_RESISTANCE) {
+
+ details->drag_started = TRUE;
+
+ /* KLUDGE ALERT: Poke the starting values into the motion
+ * structure so that dragging behaves as expected.
+ */
+ motion->x = details->drag_x;
+ motion->y = details->drag_y;
+
+ gnome_icon_container_dnd_begin_drag (container,
+ GDK_ACTION_MOVE,
+ details->drag_button,
+ motion);
+ }
break;
-
- case STRETCH_BUTTON:
- if (!details->doing_drag)
- gnome_icon_container_begin_stretch (container);
- details->doing_drag = TRUE;
- gnome_icon_container_stretch (container, motion);
+ case DRAG_ACTION_STRETCH:
+ continue_stretching (container, motion->x, motion->y);
break;
-
- default:
- g_assert_not_reached ();
}
-
- return TRUE;
}
return NAUTILUS_CALL_PARENT_CLASS (GTK_WIDGET_CLASS, motion_notify_event, (widget, motion));
@@ -1978,12 +2059,12 @@ gnome_icon_container_initialize (GnomeIconContainer *container)
/* font table - this isnt exactly proportional, but it looks better than computed */
/* FIXME: read font from metadata */
details->label_font[NAUTILUS_ZOOM_LEVEL_SMALLEST] = gdk_font_load("-bitstream-charter-medium-r-normal-*-8-*-*-*-*-*-*-*");
- details->label_font[NAUTILUS_ZOOM_LEVEL_SMALLER] = gdk_font_load("-bitstream-charter-medium-r-normal-*-8-*-*-*-*-*-*-*");
- details->label_font[NAUTILUS_ZOOM_LEVEL_SMALL] = gdk_font_load("-bitstream-charter-medium-r-normal-*-10-*-*-*-*-*-*-*");
- details->label_font[NAUTILUS_ZOOM_LEVEL_STANDARD] = gdk_font_load("-bitstream-charter-medium-r-normal-*-12-*-*-*-*-*-*-*");
- details->label_font[NAUTILUS_ZOOM_LEVEL_LARGE] = gdk_font_load("-bitstream-charter-medium-r-normal-*-14-*-*-*-*-*-*-*");
- details->label_font[NAUTILUS_ZOOM_LEVEL_LARGER] = gdk_font_load("-bitstream-charter-medium-r-normal-*-16-*-*-*-*-*-*-*");
- details->label_font[NAUTILUS_ZOOM_LEVEL_LARGEST] = gdk_font_load("-bitstream-charter-medium-r-normal-*-18-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_SMALLER] = gdk_font_load("-bitstream-charter-medium-r-normal-*-8-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_SMALL] = gdk_font_load("-bitstream-charter-medium-r-normal-*-10-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_STANDARD] = gdk_font_load("-bitstream-charter-medium-r-normal-*-12-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_LARGE] = gdk_font_load("-bitstream-charter-medium-r-normal-*-14-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_LARGER] = gdk_font_load("-bitstream-charter-medium-r-normal-*-16-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_LARGEST] = gdk_font_load("-bitstream-charter-medium-r-normal-*-18-*-*-*-*-*-*-*");
/* FIXME: Read these from preferences. */
details->linger_selection_mode = FALSE;
@@ -2017,7 +2098,7 @@ linger_select_timeout_cb (gpointer data)
icon = details->linger_selection_mode_icon;
selection_changed = unselect_all (container);
- selection_changed |= icon_select (icon, TRUE);
+ selection_changed |= icon_set_selected (container, icon, TRUE);
set_kbd_current (container, icon, FALSE);
make_icon_visible (container, icon);
@@ -2058,7 +2139,6 @@ handle_icon_button_press (GnomeIconContainer *container,
*/
details->drag_button = 0;
- details->drag_icon = NULL;
/* Context menu applies to single item (at least
* for now). Select item first to make this obvious.
@@ -2072,41 +2152,47 @@ handle_icon_button_press (GnomeIconContainer *container,
return TRUE;
}
- if (event->button != DRAG_BUTTON && event->button != STRETCH_BUTTON)
+ if (event->button != DRAG_BUTTON)
return FALSE;
+ details->drag_button = event->button;
+ details->drag_icon = icon;
+ details->drag_x = event->x;
+ details->drag_y = event->y;
+ details->drag_action = DRAG_ACTION_MOVE_OR_COPY;
+ details->drag_started = FALSE;
+
+ /* Check to see if this is a click on the stretch handles.
+ * If so, it won't modify the selection.
+ */
+ if (icon == container->details->stretch_icon) {
+ if (start_stretching (container)) {
+ return TRUE;
+ }
+ }
+
+ /* Select or deselect the icon */
if (button_event_modifies_selection (event)) {
- icon_toggle_selected (icon);
+ icon_toggle_selected (container, icon);
gtk_signal_emit (GTK_OBJECT (container),
signals[SELECTION_CHANGED]);
} else if (! icon->is_selected) {
unselect_all (container);
- icon_select (icon, TRUE);
+ icon_set_selected (container, icon, TRUE);
gtk_signal_emit (GTK_OBJECT (container),
signals[SELECTION_CHANGED]);
}
+ /* Double clicking does not trigger a D&D action. */
if (event->type == GDK_2BUTTON_PRESS) {
- /* Double clicking should *never* trigger a D&D action.
- * We must clear this out before emitting the signal, because
- * handling the activate signal might invalidate the drag_icon pointer.
- */
details->drag_button = 0;
- details->drag_icon = NULL;
/* FIXME: This should activate all selected icons, not just one */
gtk_signal_emit (GTK_OBJECT (container),
signals[ACTIVATE],
icon->data);
-
- return TRUE;
}
- details->drag_button = event->button;
- details->drag_icon = icon;
- details->drag_x = event->x;
- details->drag_y = event->y;
-
return TRUE;
}
@@ -2207,6 +2293,7 @@ gnome_icon_container_clear (GnomeIconContainer *container)
details = container->details;
set_kbd_current (container, NULL, FALSE);
+ details->stretch_icon = NULL;
for (p = details->icons; p != NULL; p = p->next)
icon_destroy (p->data);
@@ -2236,7 +2323,7 @@ setup_icon_in_container (GnomeIconContainer *container,
}
static void
-request_update_one (GnomeIconContainer *container, GnomeIconContainerIcon *icon)
+update_icon (GnomeIconContainer *container, GnomeIconContainerIcon *icon)
{
GnomeIconContainerDetails *details;
NautilusScalableIcon *scalable_icon;
@@ -2246,11 +2333,14 @@ request_update_one (GnomeIconContainer *container, GnomeIconContainerIcon *icon)
details = container->details;
- scalable_icon = nautilus_icons_controller_get_icon_image (details->controller, icon->data);
- pixbuf = nautilus_icon_factory_get_pixbuf_for_icon (scalable_icon, nautilus_icon_size_for_zoom_level (details->zoom_level));
+ scalable_icon = nautilus_icons_controller_get_icon_image
+ (details->controller, icon->data);
+ pixbuf = nautilus_icon_factory_get_pixbuf_for_icon
+ (scalable_icon, icon_get_size (container, icon));
nautilus_scalable_icon_unref (scalable_icon);
- label = nautilus_icons_controller_get_icon_text (details->controller, icon->data);
+ label = nautilus_icons_controller_get_icon_text
+ (details->controller, icon->data);
font = details->label_font[details->zoom_level];
@@ -2279,7 +2369,7 @@ gnome_icon_container_add (GnomeIconContainer *container,
details = container->details;
new_icon = icon_new (container, data);
- icon_position (new_icon, x, y);
+ icon_set_position (new_icon, x, y);
world_to_grid (container, x, y, &grid_x, &grid_y);
icon_grid_add (details->grid, new_icon, grid_x, grid_y);
@@ -2321,7 +2411,7 @@ gnome_icon_container_add_auto (GnomeIconContainer *container,
icon_grid_add_auto (container->details->grid, new_icon, &grid_x, &grid_y);
grid_to_world (container, grid_x, grid_y, &x, &y);
- icon_position (new_icon, x, y);
+ icon_set_position (new_icon, x, y);
setup_icon_in_container (container, new_icon);
@@ -2356,7 +2446,7 @@ gnome_icon_container_set_zoom_level(GnomeIconContainer *container, int new_level
details->zoom_level = pinned_level;
- pixels_per_unit = (double) nautilus_icon_size_for_zoom_level (pinned_level)
+ pixels_per_unit = (double) nautilus_get_icon_size_for_zoom_level (pinned_level)
/ NAUTILUS_ICON_SIZE_STANDARD;
gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (container), pixels_per_unit);
@@ -2376,7 +2466,7 @@ gnome_icon_container_request_update_all (GnomeIconContainer *container)
GList *p;
for (p = container->details->icons; p != NULL; p = p->next)
- request_update_one (container, p->data);
+ update_icon (container, p->data);
}
@@ -2456,7 +2546,7 @@ gnome_icon_container_relayout (GnomeIconContainer *container)
dp[cols] = g_list_alloc ();
dp[cols]->data = icon;
- icon_position (icon, dx, dy);
+ icon_set_position (icon, dx, dy);
icon->layout_done = TRUE;
@@ -2595,7 +2685,7 @@ gnome_icon_container_line_up (GnomeIconContainer *container)
|| (icon->y >= 0 && icon->y < y))
continue;
- icon_position (icon, dx, y);
+ icon_set_position (icon, dx, y);
icon->layout_done = TRUE;
q[k] = g_list_alloc ();
@@ -2698,7 +2788,7 @@ gnome_icon_container_select_all (GnomeIconContainer *container)
GnomeIconContainerIcon *icon;
icon = p->data;
- selection_changed |= icon_select (icon, TRUE);
+ selection_changed |= icon_set_selected (container, icon, TRUE);
}
if (selection_changed)
@@ -2731,8 +2821,8 @@ gnome_icon_container_select_list_unselect_others (GnomeIconContainer *container,
GnomeIconContainerIcon *icon;
icon = p->data;
- selection_changed |= icon_select
- (icon, g_list_find (icons, icon) != NULL);
+ selection_changed |= icon_set_selected
+ (container, icon, g_list_find (icons, icon) != NULL);
}
if (selection_changed)
@@ -2795,3 +2885,178 @@ gnome_icon_container_get_icon_by_uri (GnomeIconContainer *container,
return NULL;
}
+
+static GnomeIconContainerIcon *
+get_first_selected_icon (GnomeIconContainer *container)
+{
+ GList *p;
+ GnomeIconContainerIcon *icon;
+
+ /* Find the first selected icon. */
+ icon = NULL;
+ for (p = container->details->icons; p != NULL; p = p->next) {
+ icon = p->data;
+ if (icon->is_selected) {
+ return icon;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * gnome_icon_container_show_stretch_handles:
+ * @container: An icon container widget.
+ *
+ * Makes stretch handles visible on the first selected icon.
+ **/
+void
+gnome_icon_container_show_stretch_handles (GnomeIconContainer *container)
+{
+ GnomeIconContainerDetails *details;
+ GnomeIconContainerIcon *icon;
+
+ icon = get_first_selected_icon (container);
+ if (icon == NULL)
+ return;
+
+ /* Check if it already has stretch handles. */
+ details = container->details;
+ if (details->stretch_icon == icon)
+ return;
+
+ /* Get rid of the existing stretch handles and put them on the new icon. */
+ if (details->stretch_icon != NULL)
+ nautilus_icons_view_icon_item_set_show_stretch_handles
+ (details->stretch_icon->item, FALSE);
+ nautilus_icons_view_icon_item_set_show_stretch_handles (icon->item, TRUE);
+ details->stretch_icon = icon;
+}
+
+/**
+ * gnome_icon_container_has_stretch_handles
+ * @container: An icon container widget.
+ *
+ * Returns true if the first selected item has stretch handles.
+ **/
+gboolean
+gnome_icon_container_has_stretch_handles (GnomeIconContainer *container)
+{
+ GnomeIconContainerIcon *icon;
+
+ icon = get_first_selected_icon (container);
+ if (icon == NULL) {
+ return FALSE;
+ }
+
+ return icon == container->details->stretch_icon;
+}
+
+/**
+ * gnome_icon_container_is_stretched
+ * @container: An icon container widget.
+ *
+ * Returns true if the first selected item is stretched to a size other than 1.0.
+ **/
+gboolean
+gnome_icon_container_is_stretched (GnomeIconContainer *container)
+{
+ GnomeIconContainerIcon *icon;
+
+ icon = get_first_selected_icon (container);
+ if (icon == NULL) {
+ return FALSE;
+ }
+
+ return icon->scale != 1.0;
+}
+
+/**
+ * gnome_icon_container_unstretch
+ * @container: An icon container widget.
+ *
+ * Gets rid of any icon stretching.
+ **/
+void
+gnome_icon_container_unstretch (GnomeIconContainer *container)
+{
+ GnomeIconContainerIcon *icon;
+
+ icon = get_first_selected_icon (container);
+ if (icon == NULL) {
+ return;
+ }
+
+ icon->scale = 1.0;
+ update_icon (container, icon);
+}
+
+static void
+compute_stretch (StretchState *start,
+ StretchState *current)
+{
+ gboolean right, bottom;
+ int x_stretch, y_stretch;
+
+ /* Figure out which handle we are dragging. */
+ right = start->pointer_x > start->icon_x + start->icon_size / 2;
+ bottom = start->pointer_y > start->icon_y + start->icon_size / 2;
+
+ /* Figure out how big we should stretch. */
+ x_stretch = start->pointer_x - current->pointer_x;
+ y_stretch = start->pointer_y - current->pointer_y;
+ if (right) {
+ x_stretch = -x_stretch;
+ }
+ if (bottom) {
+ y_stretch = -y_stretch;
+ }
+ current->icon_size = MAX ((int)start->icon_size + MIN (x_stretch, y_stretch),
+ (int)NAUTILUS_ICON_SIZE_SMALLEST);
+
+ /* Figure out where the corner of the icon should be. */
+ current->icon_x = start->icon_x;
+ if (!right) {
+ current->icon_x += start->icon_size - current->icon_size;
+ }
+ current->icon_y = start->icon_y;
+ if (!bottom) {
+ current->icon_y += start->icon_size - current->icon_size;
+ }
+}
+
+
+#if ! defined (NAUTILUS_OMIT_SELF_CHECK)
+
+static char *
+nautilus_self_check_compute_stretch (int icon_x, int icon_y, int icon_size,
+ int start_pointer_x, int start_pointer_y,
+ int end_pointer_x, int end_pointer_y)
+{
+ StretchState start, current;
+
+ start.icon_x = icon_x;
+ start.icon_y = icon_y;
+ start.icon_size = icon_size;
+ start.pointer_x = start_pointer_x;
+ start.pointer_y = start_pointer_y;
+ current.pointer_x = end_pointer_x;
+ current.pointer_y = end_pointer_y;
+
+ compute_stretch (&start, &current);
+
+ return g_strdup_printf ("%d,%d:%d",
+ current.icon_x,
+ current.icon_y,
+ current.icon_size);
+}
+
+void
+nautilus_self_check_gnome_icon_container (void)
+{
+ NAUTILUS_CHECK_STRING_RESULT (nautilus_self_check_compute_stretch (0, 0, 12, 0, 0, 0, 0), "0,0:12");
+ NAUTILUS_CHECK_STRING_RESULT (nautilus_self_check_compute_stretch (0, 0, 12, 12, 12, 13, 13), "0,0:13");
+ NAUTILUS_CHECK_STRING_RESULT (nautilus_self_check_compute_stretch (0, 0, 12, 12, 12, 13, 12), "0,0:12");
+ NAUTILUS_CHECK_STRING_RESULT (nautilus_self_check_compute_stretch (100, 100, 64, 105, 105, 40, 40), "35,35:129");
+}
+
+#endif /* ! NAUTILUS_OMIT_SELF_CHECK */
diff --git a/libnautilus-private/gnome-icon-container.h b/libnautilus-private/gnome-icon-container.h
index 7d9b3859c..821a16178 100644
--- a/libnautilus-private/gnome-icon-container.h
+++ b/libnautilus-private/gnome-icon-container.h
@@ -66,6 +66,7 @@ struct _GnomeIconContainerClass {
};
+
guint gnome_icon_container_get_type (void);
GtkWidget *gnome_icon_container_new (NautilusIconsController *controller);
@@ -75,8 +76,8 @@ void gnome_icon_container_enable_linger_selection (GnomeIconContainer
void gnome_icon_container_clear (GnomeIconContainer *view);
void gnome_icon_container_add (GnomeIconContainer *view,
NautilusControllerIcon *icon,
- gint x,
- gint y);
+ int x,
+ int y);
void gnome_icon_container_add_auto (GnomeIconContainer *view,
NautilusControllerIcon *icon);
@@ -87,10 +88,17 @@ void gnome_icon_container_request_update_all (GnomeIconContainer *containe
GList * gnome_icon_container_get_selection (GnomeIconContainer *view);
-gint gnome_icon_container_get_zoom_level (GnomeIconContainer *view);
-void gnome_icon_container_set_zoom_level (GnomeIconContainer *view, gint new_zoom_level);
+int gnome_icon_container_get_zoom_level (GnomeIconContainer *view);
+void gnome_icon_container_set_zoom_level (GnomeIconContainer *view,
+ int new_zoom_level);
void gnome_icon_container_unselect_all (GnomeIconContainer *view);
void gnome_icon_container_select_all (GnomeIconContainer *view);
+/* The following all work on the selected icon. */
+gboolean gnome_icon_container_has_stretch_handles (GnomeIconContainer *container);
+gboolean gnome_icon_container_is_stretched (GnomeIconContainer *container);
+void gnome_icon_container_show_stretch_handles (GnomeIconContainer *container);
+void gnome_icon_container_unstretch (GnomeIconContainer *container);
+
#endif
diff --git a/libnautilus-private/nautilus-directory.c b/libnautilus-private/nautilus-directory.c
index 4ee20ab37..4909379dd 100644
--- a/libnautilus-private/nautilus-directory.c
+++ b/libnautilus-private/nautilus-directory.c
@@ -295,29 +295,33 @@ nautilus_directory_try_to_read_metafile (NautilusDirectory *directory, GnomeVFSU
NULL);
if (result == GNOME_VFS_OK) {
+ /* Check for the case where the info doesn't give the file size. */
+ if ((metafile_info.flags & GNOME_VFS_FILE_INFO_FIELDS_SIZE) == 0)
+ result = GNOME_VFS_ERROR_GENERIC;
+ }
+
+ if (result == GNOME_VFS_OK) {
/* Check for a size that won't fit into a size_t. */
- if(metafile_info.flags & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
- size = metafile_info.size;
- if (size != metafile_info.size)
- result = GNOME_VFS_ERROR_TOOBIG;
- } else
- size = 0;
+ size = metafile_info.size;
+ if (size != metafile_info.size)
+ result = GNOME_VFS_ERROR_TOOBIG;
}
metafile_handle = NULL;
+ if (result == GNOME_VFS_OK) {
result = gnome_vfs_open_uri (&metafile_handle,
metafile_uri,
GNOME_VFS_OPEN_READ);
+ }
- if (result == GNOME_VFS_OK && size) {
+ if (result == GNOME_VFS_OK) {
buffer = g_malloc (size);
result = gnome_vfs_read (metafile_handle, buffer, size, &actual_size);
directory->details->metafile_tree = xmlParseMemory (buffer, actual_size);
g_free (buffer);
- } else
- directory->details->metafile_tree = NULL;
+ }
- if (result == GNOME_VFS_OK)
+ if (metafile_handle != NULL)
gnome_vfs_close (metafile_handle);
return result;
@@ -339,12 +343,6 @@ nautilus_directory_read_metafile (NautilusDirectory *directory)
directory->details->use_alternate_metafile = TRUE;
else
result = nautilus_directory_try_to_read_metafile (directory, directory->details->metafile_uri);
-
- /* Check for errors. Later this must be reported to the user, not spit out as a warning. */
- if (result != GNOME_VFS_OK
- && result != GNOME_VFS_ERROR_NOTFOUND
- && result != GNOME_VFS_ERROR_NOTADIRECTORY)
- g_warning ("nautilus_directory_read_metafile failed to read metafile - we should report this to the user");
}
static void
diff --git a/libnautilus-private/nautilus-gtk-extensions.h b/libnautilus-private/nautilus-gtk-extensions.h
index 71ab3da7c..a3f04773f 100644
--- a/libnautilus-private/nautilus-gtk-extensions.h
+++ b/libnautilus-private/nautilus-gtk-extensions.h
@@ -25,11 +25,15 @@
*/
#ifndef NAUTILUS_GTK_EXTENSIONS_H
-#define NAUTILUS_GTK_EXTENSIONS_H 1
+#define NAUTILUS_GTK_EXTENSIONS_H
#include <gtk/gtkmenu.h>
#include <gtk/gtkwindow.h>
+#define gtk_marshal_NONE__BOXED_BOXED gtk_marshal_NONE__POINTER_POINTER
+
+#define NAUTILUS_DEFAULT_POPUP_MENU_DISPLACEMENT 2
+
guint nautilus_gtk_signal_connect_free_data (GtkObject *object,
const gchar *name,
GtkSignalFunc func,
@@ -40,10 +44,8 @@ void nautilus_gtk_window_present (GtkWindow
GtkSelectionData *nautilus_gtk_selection_data_copy_deep (const GtkSelectionData *selection_data);
void nautilus_gtk_selection_data_free_deep (GtkSelectionData *selection_data);
-#define NAUTILUS_DEFAULT_POPUP_MENU_DISPLACEMENT 2
-
void nautilus_pop_up_context_menu (GtkMenu *menu,
- gint16 offset_x,
- gint16 offset_y);
+ gint16 offset_x,
+ gint16 offset_y);
#endif /* NAUTILUS_GTK_EXTENSIONS_H */
diff --git a/libnautilus-private/nautilus-icon-factory.c b/libnautilus-private/nautilus-icon-factory.c
index 61e562c92..c9397f41e 100644
--- a/libnautilus-private/nautilus-icon-factory.c
+++ b/libnautilus-private/nautilus-icon-factory.c
@@ -746,7 +746,7 @@ nautilus_icon_factory_scale (GdkPixbuf *standard_sized_image,
* NAUTILUS_ICON_SIZE_LARGEST, inclusive.
*/
guint
-nautilus_icon_size_for_zoom_level (NautilusZoomLevel zoom_level)
+nautilus_get_icon_size_for_zoom_level (NautilusZoomLevel zoom_level)
{
switch (zoom_level) {
case NAUTILUS_ZOOM_LEVEL_SMALLEST:
@@ -768,3 +768,36 @@ nautilus_icon_size_for_zoom_level (NautilusZoomLevel zoom_level)
return NAUTILUS_ICON_SIZE_STANDARD;
}
}
+
+/* Convenience cover for nautilus_icon_factory_get_icon_for_file
+ * and nautilus_icon_factory_get_pixbuf_for_icon.
+ */
+GdkPixbuf *
+nautilus_icon_factory_get_pixbuf_for_file (NautilusFile *file,
+ guint size_in_pixels)
+{
+ NautilusScalableIcon *icon;
+ GdkPixbuf *pixbuf;
+
+ icon = nautilus_icon_factory_get_icon_for_file (file);
+ pixbuf = nautilus_icon_factory_get_pixbuf_for_icon (icon, size_in_pixels);
+ nautilus_scalable_icon_unref (icon);
+ return pixbuf;
+}
+
+/* Convenience cover for nautilus_icon_factory_get_icon_for_file,
+ * nautilus_icon_factory_get_pixbuf_for_icon,
+ * and gdk_pixbuf_render_pixmap_and_mask.
+ */
+void
+nautilus_icon_factory_get_pixmap_and_mask_for_file (NautilusFile *file,
+ guint size_in_pixels,
+ GdkPixmap **pixmap,
+ GdkBitmap **mask)
+{
+ GdkPixbuf *pixbuf;
+
+ pixbuf = nautilus_icon_factory_get_pixbuf_for_file (file, size_in_pixels);
+ gdk_pixbuf_render_pixmap_and_mask (pixbuf, pixmap, mask, 128);
+ gdk_pixbuf_unref (pixbuf);
+}
diff --git a/libnautilus-private/nautilus-icon-factory.h b/libnautilus-private/nautilus-icon-factory.h
index 7a98e3194..9ee1abbba 100644
--- a/libnautilus-private/nautilus-icon-factory.h
+++ b/libnautilus-private/nautilus-icon-factory.h
@@ -70,32 +70,52 @@ typedef enum {
typedef struct _NautilusScalableIcon NautilusScalableIcon;
/* Relationship between zoom levels and icons sizes. */
-guint nautilus_icon_size_for_zoom_level (NautilusZoomLevel zoom_level);
+guint nautilus_get_icon_size_for_zoom_level (NautilusZoomLevel zoom_level);
/* Switch themes. */
-void nautilus_icon_factory_set_theme (const char *theme_name);
+void nautilus_icon_factory_set_theme (const char *theme_name);
/* Choose the appropriate icon, but don't render it yet. */
-NautilusScalableIcon *nautilus_icon_factory_get_icon_for_file (NautilusFile *file);
-NautilusScalableIcon *nautilus_icon_factory_get_icon_by_name (const char *scalable_icon_name);
+NautilusScalableIcon *nautilus_icon_factory_get_icon_for_file (NautilusFile *file);
+NautilusScalableIcon *nautilus_icon_factory_get_icon_by_name (const char *icon_name);
/* Render an icon to a particular size.
* Ownership of a ref. count in this pixbuf comes with the deal.
*/
-GdkPixbuf * nautilus_icon_factory_get_pixbuf_for_icon (NautilusScalableIcon *scalable_icon,
- guint size_in_pixels);
+GdkPixbuf * nautilus_icon_factory_get_pixbuf_for_icon (NautilusScalableIcon *scalable_icon,
+ guint size_in_pixels);
+
+/* Convenience functions for the common case where you want to choose
+ * and render the icon into a pixbuf all at once.
+ */
+GdkPixbuf * nautilus_icon_factory_get_pixbuf_for_file (NautilusFile *file,
+ guint size_in_pixels);
+GdkPixbuf * nautilus_icon_factory_get_pixbuf_by_name (const char *icon_name,
+ guint size_in_pixels);
+
+/* Convenience functions for legacy interfaces that require a pixmap and
+ * bitmap. Maybe we can get rid of these one day.
+ */
+void nautilus_icon_factory_get_pixmap_and_mask_for_file (NautilusFile *file,
+ guint size_in_pixels,
+ GdkPixmap **pixmap,
+ GdkBitmap **mask);
+void nautilus_icon_factory_get_pixmap_and_mask_by_name (NautilusFile *file,
+ guint size_in_pixels,
+ GdkPixmap **pixmap,
+ GdkBitmap **mask);
/* Manage a scalable icon.
* Since the factory always passes out references to the same scalable
* icon, you can compare two scalable icons to see if they are the same
* with ==.
*/
-void nautilus_scalable_icon_ref (NautilusScalableIcon *scalable_icon);
-void nautilus_scalable_icon_unref (NautilusScalableIcon *scalable_icon);
+void nautilus_scalable_icon_ref (NautilusScalableIcon *scalable_icon);
+void nautilus_scalable_icon_unref (NautilusScalableIcon *scalable_icon);
/* The name of a scalable icon is suitable for storage in metadata.
* This is a quick way to record the result of getting an icon by name.
*/
-char * nautilus_scalable_icon_get_name (NautilusScalableIcon *scalable_icon);
+char * nautilus_scalable_icon_get_name (NautilusScalableIcon *scalable_icon);
#endif /* NAUTILUS_ICON_FACTORY_H */
diff --git a/libnautilus-private/nautilus-icons-view-icon-item.c b/libnautilus-private/nautilus-icons-view-icon-item.c
index 29c31d400..3b67af4e0 100644
--- a/libnautilus-private/nautilus-icons-view-icon-item.c
+++ b/libnautilus-private/nautilus-icons-view-icon-item.c
@@ -36,6 +36,8 @@
#include "nautilus-string.h"
#include "gdk-extensions.h"
+#define STRETCH_HANDLE_THICKNESS 6
+
/* Private part of the NautilusIconsViewIconItem structure */
struct _NautilusIconsViewIconItemDetails {
/* The image, text, font. */
@@ -51,6 +53,7 @@ struct _NautilusIconsViewIconItemDetails {
guint is_highlighted_for_selection : 1;
guint is_highlighted_for_keyboard_selection: 1;
guint is_highlighted_for_drop : 1;
+ guint show_stretch_handles : 1;
};
@@ -491,6 +494,7 @@ nautilus_icons_view_icon_item_draw (GnomeCanvasItem *item, GdkDrawable *drawable
NautilusIconsViewIconItem *icon_item;
NautilusIconsViewIconItemDetails *details;
ArtIRect pixbuf_rect, drawable_rect, draw_rect;
+ GdkGC *gc;
icon_item = NAUTILUS_ICONS_VIEW_ICON_ITEM (item);
details = icon_item->details;
@@ -516,6 +520,34 @@ nautilus_icons_view_icon_item_draw (GnomeCanvasItem *item, GdkDrawable *drawable
GDK_PIXBUF_ALPHA_BILEVEL, 128, GDK_RGB_DITHER_MAX,
draw_rect.x0, draw_rect.y0);
}
+
+ /* Draw stretching handles. */
+ if (details->show_stretch_handles) {
+ gc = gdk_gc_new (drawable);
+
+ gdk_draw_rectangle (drawable, gc, TRUE,
+ pixbuf_rect.x0 - x,
+ pixbuf_rect.y0 - y,
+ STRETCH_HANDLE_THICKNESS,
+ STRETCH_HANDLE_THICKNESS);
+ gdk_draw_rectangle (drawable, gc, TRUE,
+ pixbuf_rect.x1 - x - STRETCH_HANDLE_THICKNESS,
+ pixbuf_rect.y0 - y,
+ STRETCH_HANDLE_THICKNESS,
+ STRETCH_HANDLE_THICKNESS);
+ gdk_draw_rectangle (drawable, gc, TRUE,
+ pixbuf_rect.x0 - x,
+ pixbuf_rect.y1 - y - STRETCH_HANDLE_THICKNESS,
+ STRETCH_HANDLE_THICKNESS,
+ STRETCH_HANDLE_THICKNESS);
+ gdk_draw_rectangle (drawable, gc, TRUE,
+ pixbuf_rect.x1 - x - STRETCH_HANDLE_THICKNESS,
+ pixbuf_rect.y1 - y - STRETCH_HANDLE_THICKNESS,
+ STRETCH_HANDLE_THICKNESS,
+ STRETCH_HANDLE_THICKNESS);
+
+ gdk_gc_unref (gc);
+ }
/* Draw the text. */
nautilus_icons_view_draw_text_box
@@ -544,7 +576,9 @@ nautilus_icons_view_icon_item_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf
/* Point handler for the icon canvas item. */
-/* FIXME: This currently only reports a hit if the pixbuf is hit. */
+/* FIXME: This currently only reports a hit if the pixbuf or stretch handles are hit,
+ * and ignores hits on the text.
+ */
static double
nautilus_icons_view_icon_item_point (GnomeCanvasItem *item, double x, double y, int cx, int cy,
GnomeCanvasItem **actual_item)
@@ -564,9 +598,13 @@ nautilus_icons_view_icon_item_point (GnomeCanvasItem *item, double x, double y,
/* Check to see if it's within the item's rectangle at all. */
nautilus_icons_view_icon_item_get_icon_canvas_rectangle (icon_item, &rect);
- if (cx <= rect.x0 || cx >= rect.x1 || cy <= rect.y0 || cy >= rect.y1)
+ if (cx < rect.x0 || cx >= rect.x1 || cy < rect.y0 || cy >= rect.y1)
return no_hit;
+ /* Check for hits in the stretch handles. */
+ if (nautilus_icons_view_icon_item_get_hit_stretch_handle (icon_item, cx, cy))
+ return 0.0;
+
/* Can't get this far without a pixbuf. */
g_assert (details->pixbuf != NULL);
if (details->pixbuf == NULL)
@@ -724,3 +762,44 @@ nautilus_icons_view_icon_item_get_icon_window_rectangle (NautilusIconsViewIconIt
rect->x1 = rect->x0 + (pixbuf == NULL ? 0 : pixbuf->art_pixbuf->width);
rect->y1 = rect->y0 + (pixbuf == NULL ? 0 : pixbuf->art_pixbuf->height);
}
+
+void
+nautilus_icons_view_icon_item_set_show_stretch_handles (NautilusIconsViewIconItem *item,
+ gboolean show_stretch_handles)
+{
+ g_return_if_fail (NAUTILUS_IS_ICONS_VIEW_ICON_ITEM (item));
+ g_return_if_fail (show_stretch_handles == FALSE || show_stretch_handles == TRUE);
+
+ if (!item->details->show_stretch_handles == !show_stretch_handles)
+ return;
+
+ item->details->show_stretch_handles = show_stretch_handles;
+ gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (item));
+}
+
+/* Check if one of the stretch handles was hit. */
+gboolean
+nautilus_icons_view_icon_item_get_hit_stretch_handle (NautilusIconsViewIconItem *item,
+ int canvas_x, int canvas_y)
+{
+ ArtIRect rect;
+
+ g_return_val_if_fail (NAUTILUS_IS_ICONS_VIEW_ICON_ITEM (item), FALSE);
+
+ /* Make sure there are handles to hit. */
+ if (!item->details->show_stretch_handles)
+ return FALSE;
+
+ /* Get both the point and the icon rectangle in canvas coordinates. */
+ nautilus_icons_view_icon_item_get_icon_canvas_rectangle (item, &rect);
+
+ /* Handle the case where it's not in the rectangle at all. */
+ if (canvas_x < rect.x0 || canvas_x >= rect.x1 || canvas_y < rect.y0 || canvas_y >= rect.y1)
+ return FALSE;
+
+ /* Check for hits in the stretch handles. */
+ return (canvas_x < rect.x0 + STRETCH_HANDLE_THICKNESS
+ || canvas_x >= rect.x1 - STRETCH_HANDLE_THICKNESS)
+ && (canvas_y < rect.y0 + STRETCH_HANDLE_THICKNESS
+ || canvas_y >= rect.y1 - STRETCH_HANDLE_THICKNESS);
+}
diff --git a/libnautilus-private/nautilus-icons-view-icon-item.h b/libnautilus-private/nautilus-icons-view-icon-item.h
index 03ae11862..a9b3efad7 100644
--- a/libnautilus-private/nautilus-icons-view-icon-item.h
+++ b/libnautilus-private/nautilus-icons-view-icon-item.h
@@ -55,11 +55,19 @@ struct _NautilusIconsViewIconItemClass {
GnomeCanvasItemClass parent_class;
};
-GtkType nautilus_icons_view_icon_item_get_type (void);
-void nautilus_icons_view_icon_item_get_icon_world_rectangle (NautilusIconsViewIconItem *item,
- ArtDRect *world_rectangle);
-void nautilus_icons_view_icon_item_get_icon_window_rectangle (NautilusIconsViewIconItem *item,
- ArtIRect *window_rectangle);
+GtkType nautilus_icons_view_icon_item_get_type (void);
+
+void nautilus_icons_view_icon_item_get_icon_world_rectangle (NautilusIconsViewIconItem *item,
+ ArtDRect *world_rectangle);
+void nautilus_icons_view_icon_item_get_icon_window_rectangle (NautilusIconsViewIconItem *item,
+ ArtIRect *window_rectangle);
+
+void nautilus_icons_view_icon_item_set_show_stretch_handles (NautilusIconsViewIconItem *item,
+ gboolean show_stretch_handles);
+
+gboolean nautilus_icons_view_icon_item_get_hit_stretch_handle (NautilusIconsViewIconItem *item,
+ int canvas_x,
+ int canvas_y);
END_GNOME_DECLS
diff --git a/libnautilus-private/nautilus-lib-self-check-functions.h b/libnautilus-private/nautilus-lib-self-check-functions.h
index 93cb644f3..4a51d24df 100644
--- a/libnautilus-private/nautilus-lib-self-check-functions.h
+++ b/libnautilus-private/nautilus-lib-self-check-functions.h
@@ -43,6 +43,7 @@ void nautilus_run_lib_self_checks (void);
macro (nautilus_self_check_directory) \
macro (nautilus_self_check_gdk_extensions) \
macro (nautilus_self_check_glib_extensions) \
+ macro (nautilus_self_check_gnome_icon_container) \
macro (nautilus_self_check_string) \
/* Add new self-check functions to the list above this line. */