source: trunk/third/nautilus/src/nautilus-window-toolbars.c @ 18663

Revision 18663, 11.5 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18662, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3/*
4 * Nautilus
5 *
6 * Copyright (C) 2000, 2001 Eazel, Inc.
7 *
8 * Nautilus is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
12 *
13 * Nautilus 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 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 * Author: John Sullivan <sullivan@eazel.com>
23 */
24
25/* nautilus-window-toolbars.c - implementation of nautilus window toolbar operations,
26 * split into separate file just for convenience.
27 */
28
29#include <config.h>
30
31#include <unistd.h>
32#include "nautilus-application.h"
33#include "nautilus-window-manage-views.h"
34#include "nautilus-window-private.h"
35#include "nautilus-window.h"
36#include <bonobo/bonobo-control.h>
37#include <bonobo/bonobo-property-bag.h>
38#include <bonobo/bonobo-property-bag-client.h>
39#include <bonobo/bonobo-exception.h>
40#include <bonobo/bonobo-moniker-util.h>
41#include <bonobo/bonobo-ui-util.h>
42#include <eel/eel-gnome-extensions.h>
43#include <eel/eel-gtk-extensions.h>
44#include <eel/eel-string.h>
45#include <gtk/gtkframe.h>
46#include <gtk/gtktogglebutton.h>
47#include <gdk/gdkkeysyms.h>
48#include <libgnome/gnome-i18n.h>
49#include <libgnomeui/gnome-popup-menu.h>
50#include <libnautilus-private/nautilus-bonobo-extensions.h>
51#include <libnautilus-private/nautilus-bookmark.h>
52#include <libnautilus-private/nautilus-file-utilities.h>
53#include <libnautilus-private/nautilus-global-preferences.h>
54#include <libnautilus-private/nautilus-theme.h>
55
56/* FIXME bugzilla.gnome.org 41243:
57 * We should use inheritance instead of these special cases
58 * for the desktop window.
59 */
60#include "nautilus-desktop-window.h"
61
62enum {
63        TOOLBAR_ITEM_STYLE_PROP,
64        TOOLBAR_ITEM_ORIENTATION_PROP
65};
66
67static void
68activate_back_or_forward_menu_item (GtkMenuItem *menu_item,
69                                    NautilusWindow *window,
70                                    gboolean back)
71{
72        int index;
73       
74        g_assert (GTK_IS_MENU_ITEM (menu_item));
75        g_assert (NAUTILUS_IS_WINDOW (window));
76
77        index = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menu_item), "user_data"));
78        nautilus_window_back_or_forward (window, back, index);
79}
80
81static void
82activate_back_menu_item_callback (GtkMenuItem *menu_item, NautilusWindow *window)
83{
84        activate_back_or_forward_menu_item (menu_item, window, TRUE);
85}
86
87static void
88activate_forward_menu_item_callback (GtkMenuItem *menu_item, NautilusWindow *window)
89{
90        activate_back_or_forward_menu_item (menu_item, window, FALSE);
91}
92
93static GtkMenu *
94create_back_or_forward_menu (NautilusWindow *window, gboolean back)
95{
96        GtkMenu *menu;
97        GtkWidget *menu_item;
98        GList *list_link;
99        int index;
100
101        g_assert (NAUTILUS_IS_WINDOW (window));
102       
103        menu = GTK_MENU (gtk_menu_new ());
104
105        list_link = back ? window->back_list : window->forward_list;
106        index = 0;
107        while (list_link != NULL)
108        {
109                menu_item = nautilus_bookmark_menu_item_new (NAUTILUS_BOOKMARK (list_link->data));             
110                g_object_set_data (G_OBJECT (menu_item), "user_data", GINT_TO_POINTER (index));
111                gtk_widget_show (GTK_WIDGET (menu_item));
112                g_signal_connect_object (menu_item, "activate",
113                                         back
114                                         ? G_CALLBACK (activate_back_menu_item_callback)
115                                         : G_CALLBACK (activate_forward_menu_item_callback),
116                                         window, 0);
117               
118                gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
119                list_link = g_list_next (list_link);
120                ++index;
121        }
122
123        return menu;
124}
125
126static GtkWidget *
127get_back_button (NautilusWindow *window)
128{
129        return GTK_WIDGET (GTK_BIN
130                (window->details->back_button_item)->child);
131}
132
133static GtkWidget *
134get_forward_button (NautilusWindow *window)
135{
136        return GTK_WIDGET (GTK_BIN
137                (window->details->forward_button_item)->child);
138}
139
140static void
141menu_position_under_widget (GtkMenu *menu, int *x, int *y,
142                            gboolean *push_in, gpointer user_data)
143{
144        GtkWidget *w;
145        int width, height;
146        int screen_width, screen_height;
147        GtkRequisition requisition;
148
149        w = GTK_WIDGET (user_data);
150       
151        gdk_drawable_get_size (w->window, &width, &height);
152        gdk_window_get_origin (w->window, x, y);
153        *y = *y + height;
154
155        gtk_widget_size_request (GTK_WIDGET (menu), &requisition);
156
157        screen_width = gdk_screen_width ();
158        screen_height = gdk_screen_height ();
159
160        *x = CLAMP (*x, 0, MAX (0, screen_width - requisition.width));
161        *y = CLAMP (*y, 0, MAX (0, screen_height - requisition.height));
162}
163
164static gboolean
165back_or_forward_button_pressed_callback (GtkWidget *widget,
166                                         GdkEventButton *event,
167                                         gpointer *user_data)
168{
169        NautilusWindow *window;
170        gboolean back;
171
172        g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
173        g_return_val_if_fail (NAUTILUS_IS_WINDOW (user_data), FALSE);
174
175        window = NAUTILUS_WINDOW (user_data);
176
177        back = widget == get_back_button (window);
178        g_assert (back || widget == get_forward_button (window));
179
180        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
181
182        gnome_popup_menu_do_popup_modal (GTK_WIDGET (create_back_or_forward_menu (NAUTILUS_WINDOW (user_data), back)),
183                                         menu_position_under_widget, widget, event, widget, widget);
184       
185        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
186       
187        return TRUE;
188}
189
190static gboolean
191back_or_forward_key_pressed_callback (GtkWidget *widget,
192                                      GdkEventKey *event,
193                                      gpointer *user_data)
194{
195        if (event->keyval == GDK_space ||
196            event->keyval == GDK_KP_Space ||
197            event->keyval == GDK_Return ||
198            event->keyval == GDK_KP_Enter) {
199                back_or_forward_button_pressed_callback (widget, NULL, user_data);
200        }
201
202        return FALSE;
203}
204
205static void
206back_or_forward_toolbar_item_property_set_cb (BonoboPropertyBag *bag,
207                                              const BonoboArg   *arg,
208                                              guint              arg_id,
209                                              CORBA_Environment *ev,
210                                              gpointer           user_data)
211{
212        BonoboControl *control;
213        BonoboUIToolbarItem *item;
214        GtkOrientation orientation;
215        BonoboUIToolbarItemStyle style;
216
217        control = BONOBO_CONTROL (user_data);
218        item = BONOBO_UI_TOOLBAR_ITEM (bonobo_control_get_widget (control));
219
220        switch (arg_id) {
221        case TOOLBAR_ITEM_ORIENTATION_PROP:
222                orientation = BONOBO_ARG_GET_INT (arg);
223                bonobo_ui_toolbar_item_set_orientation (item, orientation);
224
225                if (GTK_WIDGET (item)->parent) {
226                        gtk_widget_queue_resize (GTK_WIDGET (item)->parent);
227                }
228                break;
229        case TOOLBAR_ITEM_STYLE_PROP:
230                style = BONOBO_ARG_GET_INT (arg);
231                bonobo_ui_toolbar_item_set_style (item, style);
232                break;
233        }
234}
235
236static BonoboUIToolbarItem *
237create_back_or_forward_toolbar_item (NautilusWindow *window,
238                                     const char     *tooltip,
239                                     const char     *control_path)
240{
241        BonoboUIToolbarItem *item;
242        BonoboPropertyBag *pb;
243        BonoboControl *wrapper;
244        GtkWidget *button;
245
246        item = BONOBO_UI_TOOLBAR_ITEM (bonobo_ui_toolbar_item_new ());
247
248        button = gtk_toggle_button_new ();
249        gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
250
251        gtk_container_add (GTK_CONTAINER (button),
252                           gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT));
253
254        gtk_container_add (GTK_CONTAINER (item), button);
255
256        gtk_widget_show_all (GTK_WIDGET (item));
257
258        gtk_tooltips_set_tip (window->details->tooltips,
259                              GTK_WIDGET (button),
260                              tooltip, NULL);
261        g_signal_connect_object (button, "key_press_event",
262                                 G_CALLBACK (back_or_forward_key_pressed_callback),
263                                 window, 0);
264        g_signal_connect_object (button, "button_press_event",
265                                 G_CALLBACK (back_or_forward_button_pressed_callback),
266                                 window, 0);
267
268        wrapper = bonobo_control_new (GTK_WIDGET (item));
269        pb = bonobo_property_bag_new
270                (NULL, back_or_forward_toolbar_item_property_set_cb, wrapper);
271        bonobo_property_bag_add (pb, "style",
272                                 TOOLBAR_ITEM_STYLE_PROP,
273                                 BONOBO_ARG_INT, NULL, NULL,
274                                 Bonobo_PROPERTY_WRITEABLE);
275        bonobo_property_bag_add (pb, "orientation",
276                                 TOOLBAR_ITEM_ORIENTATION_PROP,
277                                 BONOBO_ARG_INT, NULL, NULL,
278                                 Bonobo_PROPERTY_WRITEABLE);
279        bonobo_control_set_properties (wrapper, BONOBO_OBJREF (pb), NULL);
280        bonobo_object_unref (pb);
281
282        bonobo_ui_component_object_set (window->details->shell_ui,
283                                        control_path,
284                                        BONOBO_OBJREF (wrapper),
285                                        NULL);
286
287        bonobo_object_unref (wrapper);
288
289        return item;
290}
291
292static void
293throbber_set_throbbing (NautilusWindow *window,
294                        gboolean        throbbing)
295{
296        CORBA_boolean b;
297        CORBA_any     val;
298
299        val._type = TC_CORBA_boolean;
300        val._value = &b;
301        b = throbbing;
302
303        bonobo_pbclient_set_value_async (
304                window->details->throbber_property_bag,
305                "throbbing", &val, NULL);
306}
307
308static void
309throbber_created_callback (Bonobo_Unknown     throbber,
310                           CORBA_Environment *ev,
311                           gpointer           user_data)
312{
313        char *exception_as_text;
314        NautilusWindow *window;
315
316        if (BONOBO_EX (ev)) {
317                exception_as_text = bonobo_exception_get_text (ev);
318                g_warning ("Throbber activation exception '%s'", exception_as_text);
319                g_free (exception_as_text);
320                return;
321        }
322
323        g_return_if_fail (NAUTILUS_IS_WINDOW (user_data));
324
325        window = NAUTILUS_WINDOW (user_data);
326
327        window->details->throbber_activating = FALSE;
328
329        bonobo_ui_component_object_set (window->details->shell_ui,
330                                        "/Toolbar/ThrobberWrapper",
331                                        throbber, ev);
332        CORBA_exception_free (ev);
333
334        window->details->throbber_property_bag =
335                Bonobo_Control_getProperties (throbber, ev);
336
337        if (BONOBO_EX (ev)) {
338                window->details->throbber_property_bag = CORBA_OBJECT_NIL;
339                CORBA_exception_free (ev);
340        } else {
341                throbber_set_throbbing (window, window->details->throbber_active);
342        }
343
344        bonobo_object_release_unref (throbber, ev);
345
346        g_object_unref (window);
347}
348
349void
350nautilus_window_allow_stop (NautilusWindow *window, gboolean allow)
351{
352        if (( window->details->throbber_active &&  allow) ||
353            (!window->details->throbber_active && !allow)) {
354                return;
355        }
356
357        if (allow)
358                access ("nautilus-throbber: start", 0);
359        else
360                access ("nautilus-throbber: stop", 0);
361
362        window->details->throbber_active = allow;
363
364        nautilus_window_ui_freeze (window);
365
366        nautilus_bonobo_set_sensitive (window->details->shell_ui,
367                                       NAUTILUS_COMMAND_STOP, allow);
368
369        if (window->details->throbber_property_bag != CORBA_OBJECT_NIL) {
370                throbber_set_throbbing (window, allow);
371        }
372
373        nautilus_window_ui_thaw (window);
374}
375
376
377void
378nautilus_window_activate_throbber (NautilusWindow *window)
379{
380        CORBA_Environment ev;
381        char *exception_as_text;
382
383        if (window->details->throbber_activating ||
384            window->details->throbber_property_bag != CORBA_OBJECT_NIL) {
385                return;
386        }
387
388        /* FIXME bugzilla.gnome.org 41243:
389         * We should use inheritance instead of these special cases
390         * for the desktop window.
391         */
392        if (!NAUTILUS_IS_DESKTOP_WINDOW (window)) {
393                CORBA_exception_init (&ev);
394
395                g_object_ref (window);
396                bonobo_get_object_async ("OAFIID:Nautilus_Throbber",
397                                         "IDL:Bonobo/Control:1.0",
398                                         &ev,
399                                         throbber_created_callback,
400                                         window);
401
402                if (BONOBO_EX (&ev)) {
403                        exception_as_text = bonobo_exception_get_text (&ev);
404                        g_warning ("Throbber activation exception '%s'", exception_as_text);
405                        g_free (exception_as_text);
406                }
407                CORBA_exception_free (&ev);
408                window->details->throbber_activating = TRUE;           
409        }
410}
411
412void
413nautilus_window_initialize_toolbars (NautilusWindow *window)
414{
415        nautilus_window_ui_freeze (window);
416
417        if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_START_WITH_TOOLBAR)) {
418                nautilus_window_activate_throbber (window);
419        }
420
421        window->details->back_button_item = create_back_or_forward_toolbar_item
422                (window, _("Go back a few pages"),
423                 "/Toolbar/BackMenu");
424        window->details->forward_button_item = create_back_or_forward_toolbar_item
425                (window, _("Go forward a number of pages"),
426                 "/Toolbar/ForwardMenu");
427
428        nautilus_window_ui_thaw (window);
429}
Note: See TracBrowser for help on using the repository browser.