diff options
author | Darin Adler <darin@src.gnome.org> | 2000-02-16 19:43:10 +0000 |
---|---|---|
committer | Darin Adler <darin@src.gnome.org> | 2000-02-16 19:43:10 +0000 |
commit | 9b94323cc3a318fbf589846278beb4e85ffe6b9e (patch) | |
tree | 08391c28015a7bb5bdfd23eaa537201a9d1c5348 /libnautilus-private | |
parent | d3d8e1d7a5e808882ede2c10b15e78e44eef4d7b (diff) | |
download | nautilus-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.h | 40 | ||||
-rw-r--r-- | libnautilus-private/gnome-icon-container.c | 497 | ||||
-rw-r--r-- | libnautilus-private/gnome-icon-container.h | 16 | ||||
-rw-r--r-- | libnautilus-private/nautilus-directory.c | 30 | ||||
-rw-r--r-- | libnautilus-private/nautilus-gtk-extensions.h | 12 | ||||
-rw-r--r-- | libnautilus-private/nautilus-icon-factory.c | 35 | ||||
-rw-r--r-- | libnautilus-private/nautilus-icon-factory.h | 38 | ||||
-rw-r--r-- | libnautilus-private/nautilus-icons-view-icon-item.c | 83 | ||||
-rw-r--r-- | libnautilus-private/nautilus-icons-view-icon-item.h | 18 | ||||
-rw-r--r-- | libnautilus-private/nautilus-lib-self-check-functions.h | 1 |
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, ¤t); + + 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. */ |