1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
3 /* nautilus-undo.c - public interface for objects that implement
4 * undoable actions -- works across components
6 * Copyright (C) 2000 Eazel, Inc.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
23 * Author: Darin Adler <darin@bentspoon.com>
27 #include "nautilus-undo.h"
29 #include "nautilus-undo-private.h"
30 #include "nautilus-undo-transaction.h"
31 #include <gtk/gtksignal.h>
32 #include <gtk/gtkwindow.h>
33 #include <libgnomecanvas/gnome-canvas.h>
35 #define NAUTILUS_UNDO_MANAGER_DATA "Nautilus undo manager"
37 /* Register a simple undo action by calling nautilus_undo_register_full. */
39 nautilus_undo_register (GObject
*target
,
40 NautilusUndoCallback callback
,
41 gpointer callback_data
,
42 GDestroyNotify callback_data_destroy_notify
,
43 const char *operation_name
,
44 const char *undo_menu_item_label
,
45 const char *undo_menu_item_hint
,
46 const char *redo_menu_item_label
,
47 const char *redo_menu_item_hint
)
49 NautilusUndoAtom atom
;
50 GList single_atom_list
;
52 g_return_if_fail (G_IS_OBJECT (target
));
53 g_return_if_fail (callback
!= NULL
);
57 atom
.callback
= callback
;
58 atom
.callback_data
= callback_data
;
59 atom
.callback_data_destroy_notify
= callback_data_destroy_notify
;
61 /* Make a single-atom list. */
62 single_atom_list
.data
= &atom
;
63 single_atom_list
.next
= NULL
;
64 single_atom_list
.prev
= NULL
;
66 /* Call the full version of the registration function,
67 * using the undo target as the place to search for the
70 nautilus_undo_register_full (&single_atom_list
,
79 /* Register an undo action. */
81 nautilus_undo_register_full (GList
*atoms
,
82 GObject
*undo_manager_search_start_object
,
83 const char *operation_name
,
84 const char *undo_menu_item_label
,
85 const char *undo_menu_item_hint
,
86 const char *redo_menu_item_label
,
87 const char *redo_menu_item_hint
)
89 NautilusUndoTransaction
*transaction
;
92 g_return_if_fail (atoms
!= NULL
);
93 g_return_if_fail (G_IS_OBJECT (undo_manager_search_start_object
));
95 /* Create an undo transaction */
96 transaction
= nautilus_undo_transaction_new (operation_name
,
100 redo_menu_item_hint
);
101 for (p
= atoms
; p
!= NULL
; p
= p
->next
) {
102 nautilus_undo_transaction_add_atom (transaction
, p
->data
);
104 nautilus_undo_transaction_add_to_undo_manager
106 nautilus_undo_get_undo_manager (undo_manager_search_start_object
));
108 /* Now we are done with the transaction.
109 * If the undo manager is holding it, then this will not destroy it.
111 g_object_unref (transaction
);
114 /* Cover for forgetting about all undo relating to a particular target. */
116 nautilus_undo_unregister (GObject
*target
)
118 /* Perhaps this should also unregister all children if called on a
119 * GtkContainer? That might be handy.
121 nautilus_undo_transaction_unregister_object (target
);
125 nautilus_undo (GObject
*undo_manager_search_start_object
)
127 NautilusUndoManager
*manager
;
129 g_return_if_fail (G_IS_OBJECT (undo_manager_search_start_object
));
131 manager
= nautilus_undo_get_undo_manager (undo_manager_search_start_object
);
132 if (manager
!= NULL
) {
133 nautilus_undo_manager_undo (manager
);
137 NautilusUndoManager
*
138 nautilus_undo_get_undo_manager (GObject
*start_object
)
140 NautilusUndoManager
*manager
;
142 GtkWindow
*transient_parent
;
144 if (start_object
== NULL
) {
145 return CORBA_OBJECT_NIL
;
148 g_return_val_if_fail (G_IS_OBJECT (start_object
), NULL
);
150 /* Check for an undo manager right here. */
151 manager
= g_object_get_data (start_object
, NAUTILUS_UNDO_MANAGER_DATA
);
152 if (manager
!= NULL
) {
156 /* Check for undo manager up the parent chain. */
157 if (GTK_IS_WIDGET (start_object
)) {
158 parent
= GTK_WIDGET (start_object
)->parent
;
159 if (parent
!= NULL
) {
160 manager
= nautilus_undo_get_undo_manager (G_OBJECT (parent
));
161 if (manager
!= NULL
) {
166 /* Check for undo manager in our window's parent. */
167 if (GTK_IS_WINDOW (start_object
)) {
168 transient_parent
= GTK_WINDOW (start_object
)->transient_parent
;
169 if (transient_parent
!= NULL
) {
170 manager
= nautilus_undo_get_undo_manager (G_OBJECT (transient_parent
));
171 if (manager
!= NULL
) {
178 /* In the case of a canvas item, try the canvas. */
179 if (GNOME_IS_CANVAS_ITEM (start_object
)) {
180 manager
= nautilus_undo_get_undo_manager (G_OBJECT (GNOME_CANVAS_ITEM (start_object
)->canvas
));
181 if (manager
!= NULL
) {
186 /* Found nothing. I can live with that. */
191 nautilus_undo_attach_undo_manager (GObject
*object
,
192 NautilusUndoManager
*manager
)
194 g_return_if_fail (G_IS_OBJECT (object
));
196 if (manager
== NULL
) {
197 g_object_set_data (object
, NAUTILUS_UNDO_MANAGER_DATA
, NULL
);
199 g_object_ref (manager
);
200 g_object_set_data_full
201 (object
, NAUTILUS_UNDO_MANAGER_DATA
,
202 manager
, g_object_unref
);
206 /* Copy a reference to the undo manager fromone object to another. */
208 nautilus_undo_share_undo_manager (GObject
*destination_object
,
209 GObject
*source_object
)
211 NautilusUndoManager
*manager
;
213 manager
= nautilus_undo_get_undo_manager (source_object
);
214 nautilus_undo_attach_undo_manager (destination_object
, manager
);