source: trunk/third/gnome-core/panel/drawer.c @ 17152

Revision 17152, 13.3 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r17151, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * GNOME panel drawer module.
3 * (C) 1997 The Free Software Foundation
4 *
5 * Authors: Miguel de Icaza
6 *          Federico Mena
7 *          George Lebl
8 */
9
10#include <config.h>
11#include <stdio.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <unistd.h>
15#include <dirent.h>
16#include <string.h>
17#include <gnome.h>
18
19#include "panel-include.h"
20#include "icon-entry-hack.h"
21
22#include "xstuff.h"
23
24extern GSList *applets;
25extern GSList *applets_last;
26extern int applet_count;
27extern GlobalConfig global_config;
28extern gboolean commie_mode;
29
30extern int applets_to_sync;
31extern int panels_to_sync;
32extern int need_complete_save;
33
34extern GtkTooltips *panel_tooltips;
35
36extern GSList *panel_list;
37
38static void
39properties_apply_callback(gpointer data)
40{
41        Drawer       *drawer = data;
42
43        GtkWidget    *pixentry = gtk_object_get_data(GTK_OBJECT(drawer->properties),
44                                                     "pixmap");
45        GtkWidget    *tipentry = gtk_object_get_data(GTK_OBJECT(drawer->properties),
46                                                     "tooltip");
47        char         *s;
48
49        g_free (drawer->pixmap);
50        drawer->pixmap = NULL;
51        g_free (drawer->tooltip);
52        drawer->tooltip = NULL;
53        s = hack_icon_entry_get_icon (GNOME_ICON_ENTRY (pixentry));
54        if (string_empty (s)) {
55                drawer->pixmap = gnome_pixmap_file ("panel-drawer.png");
56                button_widget_set_pixmap (BUTTON_WIDGET(drawer->button),
57                                          drawer->pixmap,-1);
58        } else {
59                if(button_widget_set_pixmap(BUTTON_WIDGET(drawer->button), s, -1))
60                        drawer->pixmap = g_strdup(s);
61                else {
62                        drawer->pixmap = gnome_pixmap_file ("panel-drawer.png");
63                        button_widget_set_pixmap(BUTTON_WIDGET(drawer->button),
64                                                 drawer->pixmap, -1);
65                }
66        }
67        g_free(s);
68        s = gtk_entry_get_text(GTK_ENTRY(gnome_entry_gtk_entry(GNOME_ENTRY(tipentry))));
69        if (string_empty (s))
70                drawer->tooltip = NULL;
71        else
72                drawer->tooltip = g_strdup(s);
73
74        gtk_tooltips_set_tip (panel_tooltips, drawer->button,
75                              drawer->tooltip, NULL);
76}
77
78static void
79properties_close_callback(GtkWidget *widget, gpointer data)
80{
81        Drawer *drawer = data;
82        drawer->properties = NULL;
83}
84
85static void
86set_toggle (GtkWidget *widget, gpointer data)
87{
88        PerPanelConfig *ppc = gtk_object_get_user_data(GTK_OBJECT(widget));
89        int *the_toggle = data;
90
91        *the_toggle = GTK_TOGGLE_BUTTON(widget)->active;
92
93        panel_config_register_changes (ppc);
94}
95
96static void
97set_sensitive_toggle (GtkWidget *widget, GtkWidget *widget2)
98{
99        gtk_widget_set_sensitive(widget2,GTK_TOGGLE_BUTTON(widget)->active);
100}
101
102void
103add_drawer_properties_page (PerPanelConfig *ppc, GtkNotebook *prop_nbook, Drawer *drawer)
104{
105        GtkWidget *dialog;
106        GtkWidget *table;
107        GtkWidget *f;
108        GtkWidget *box, *box_in;
109        GtkWidget *w;
110        GtkWidget *button;
111
112        g_return_if_fail (ppc != NULL);
113
114        dialog = ppc->config_window;
115
116        box = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
117        gtk_container_set_border_width (GTK_CONTAINER (box), GNOME_PAD_SMALL);
118
119        box_in = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
120        gtk_container_set_border_width (GTK_CONTAINER (box_in), GNOME_PAD_SMALL);
121
122        w = make_size_widget (ppc);
123        gtk_box_pack_start (GTK_BOX (box_in), w, FALSE, FALSE, 0);
124
125        w = make_level_widget (ppc);
126        gtk_box_pack_start (GTK_BOX (box_in), w, FALSE, FALSE, 0);
127
128        f = gtk_frame_new (_("Size and Position"));
129        gtk_container_add (GTK_CONTAINER (f), box_in);
130        gtk_box_pack_start (GTK_BOX (box), f, FALSE, FALSE, 0);
131
132       
133        table = gtk_table_new (3, 2, FALSE);
134        gtk_container_set_border_width (GTK_CONTAINER (table), GNOME_PAD_SMALL);
135
136        w = create_text_entry(table, "drawer_name", 0, _("Tooltip/Name"),
137                              drawer->tooltip,
138                              (UpdateFunction)panel_config_register_changes,
139                              ppc);
140        gtk_object_set_data(GTK_OBJECT(dialog),"tooltip",w);
141       
142        w = create_icon_entry(table, "icon", 0, 2, _("Icon"),
143                              NULL, drawer->pixmap,
144                              (UpdateFunction)panel_config_register_changes,
145                              ppc);
146        gtk_object_set_data(GTK_OBJECT(dialog), "pixmap", w);
147
148        f = gtk_frame_new(_("Applet appearance"));
149        gtk_container_add(GTK_CONTAINER(f),table);
150
151        gtk_box_pack_start(GTK_BOX(box),f,FALSE,FALSE,0);
152
153        f = gtk_frame_new(_("Drawer handle"));
154        box_in = gtk_vbox_new(FALSE,GNOME_PAD_SMALL);
155        gtk_container_set_border_width(GTK_CONTAINER(box_in), GNOME_PAD_SMALL);
156        /*we store this in w for later use!, so don't use w as temp from now
157          on*/
158        w = button = gtk_check_button_new_with_label (_("Enable hidebutton"));
159        gtk_object_set_user_data(GTK_OBJECT(button),ppc);
160        if (ppc->hidebuttons)
161                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
162        gtk_signal_connect (GTK_OBJECT (button), "toggled",
163                            GTK_SIGNAL_FUNC (set_toggle),
164                            &ppc->hidebuttons);
165        gtk_box_pack_start (GTK_BOX (box_in), button, TRUE, FALSE, 0);
166
167        button = gtk_check_button_new_with_label (_("Enable hidebutton arrow"));
168        gtk_signal_connect (GTK_OBJECT (w), "toggled",
169                            GTK_SIGNAL_FUNC (set_sensitive_toggle),
170                            button);
171        if (!ppc->hidebuttons)
172                gtk_widget_set_sensitive(button,FALSE);
173        gtk_object_set_user_data(GTK_OBJECT(button),ppc);
174        if (ppc->hidebutton_pixmaps)
175                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
176        gtk_signal_connect (GTK_OBJECT (button), "toggled",
177                            GTK_SIGNAL_FUNC (set_toggle),
178                            &ppc->hidebutton_pixmaps);
179        gtk_box_pack_start (GTK_BOX (box_in), button, TRUE, TRUE, 0);
180        gtk_container_add(GTK_CONTAINER(f),box_in);
181        gtk_box_pack_start (GTK_BOX (box),f,FALSE,FALSE,0);
182
183       
184        gtk_notebook_append_page (GTK_NOTEBOOK(prop_nbook),
185                                  box, gtk_label_new (_("Drawer")));
186       
187        gtk_signal_connect(GTK_OBJECT(dialog), "destroy",
188                           (GtkSignalFunc) properties_close_callback,
189                           drawer);
190
191        ppc->update_function = properties_apply_callback;
192        ppc->update_data = drawer;
193
194        drawer->properties = dialog;
195}
196
197static void
198drawer_click(GtkWidget *w, Drawer *drawer)
199{
200        DrawerWidget *drawerw = DRAWER_WIDGET(drawer->drawer);
201        PanelWidget *parent = PANEL_WIDGET(drawer->button->parent);
202        GtkWidget *panelw = parent->panel_parent;
203       
204        switch (BASEP_WIDGET (drawerw)->state) {
205        case BASEP_SHOWN:
206        case BASEP_AUTO_HIDDEN:
207                drawer_widget_close_drawer (drawerw, panelw);
208                break;
209        case BASEP_HIDDEN_LEFT:
210        case BASEP_HIDDEN_RIGHT:
211                drawer_widget_open_drawer (drawerw, panelw);
212                break;
213        case BASEP_MOVING:
214                g_assert_not_reached ();
215                break;
216        }
217}
218
219static void
220destroy_drawer(GtkWidget *widget, gpointer data)
221{
222        Drawer *drawer = data;
223        GtkWidget *prop_dialog = drawer->properties;
224
225        drawer->properties = NULL;
226
227        if(prop_dialog)
228                gtk_widget_destroy(prop_dialog);
229}
230
231static int
232enter_notify_drawer(GtkWidget *widget, GdkEventCrossing *event, gpointer data)
233{
234        Drawer *drawer = data;
235        BasePWidget *basep = BASEP_WIDGET (drawer->drawer);
236
237        if (!xstuff_is_compliant_wm() || global_config.autoraise)
238                gdk_window_raise(drawer->drawer->window);
239
240        if (basep->state == BASEP_MOVING)
241                return FALSE;
242       
243        if ((basep->state != BASEP_AUTO_HIDDEN) ||
244            (event->detail == GDK_NOTIFY_INFERIOR) ||
245            (basep->mode != BASEP_AUTO_HIDE))
246                return FALSE;
247
248        if (basep->leave_notify_timer_tag != 0) {
249                gtk_timeout_remove (basep->leave_notify_timer_tag);
250                basep->leave_notify_timer_tag = 0;
251        }
252
253        basep_widget_autoshow (basep);
254
255        return FALSE;
256}
257
258static int
259leave_notify_drawer (GtkWidget *widget, GdkEventCrossing *event, gpointer data)
260{
261        Drawer *drawer = data;
262        BasePWidget *basep = BASEP_WIDGET (drawer->drawer);
263
264        if (event->detail == GDK_NOTIFY_INFERIOR)
265                return FALSE;
266
267        basep_widget_queue_autohide (basep);
268
269        return FALSE;
270       
271}
272
273static void 
274drag_data_get_cb (GtkWidget          *widget,
275                  GdkDragContext     *context,
276                  GtkSelectionData   *selection_data,
277                  guint               info,
278                  guint               time,
279                  gpointer            data)
280{
281        char *foo;
282
283        foo = g_strdup_printf ("DRAWER:%d", find_applet (widget));
284
285        gtk_selection_data_set (selection_data,
286                                selection_data->target, 8, (guchar *)foo,
287                                strlen (foo));
288
289        g_free (foo);
290}
291
292static Drawer *
293create_drawer_applet(GtkWidget * drawer_panel,
294                     const char *tooltip, const char *pixmap,
295                     PanelOrientType orient)
296{
297        static GtkTargetEntry dnd_targets[] = {
298                { "application/x-panel-applet-internal", 0, 0 }
299        };
300        Drawer *drawer;
301       
302        drawer = g_new0 (Drawer, 1);
303       
304        drawer->properties = NULL;
305
306        if (string_empty (tooltip))
307                drawer->tooltip = NULL;
308        else
309                drawer->tooltip = g_strdup (tooltip);
310
311        if (string_empty (pixmap)) {
312                drawer->pixmap = gnome_pixmap_file ("panel-drawer.png");
313        } else {
314                drawer->pixmap = g_strdup (pixmap);
315        }
316        drawer->button = button_widget_new (drawer->pixmap, -1,
317                                            DRAWER_TILE,
318                                            TRUE, orient,
319                                            _("Drawer"));
320
321        /*A hack since this function only pretends to work on window
322          widgets (which we actually kind of are) this will select
323          some (already selected) events on the panel instead of
324          the button window (where they are also selected) but
325          we don't mind*/
326        GTK_WIDGET_UNSET_FLAGS (drawer->button, GTK_NO_WINDOW);
327        gtk_drag_source_set (drawer->button,
328                             GDK_BUTTON1_MASK,
329                             dnd_targets, 1,
330                             GDK_ACTION_MOVE);
331        GTK_WIDGET_SET_FLAGS (drawer->button, GTK_NO_WINDOW);
332
333        gtk_signal_connect (GTK_OBJECT (drawer->button), "drag_data_get",
334                            GTK_SIGNAL_FUNC (drag_data_get_cb),
335                            NULL);
336
337        gtk_widget_show(drawer->button);
338
339        drawer->drawer = drawer_panel;
340
341        gtk_signal_connect (GTK_OBJECT (drawer->button), "clicked",
342                            GTK_SIGNAL_FUNC (drawer_click), drawer);
343        gtk_signal_connect (GTK_OBJECT (drawer->button), "destroy",
344                            GTK_SIGNAL_FUNC (destroy_drawer), drawer);
345        gtk_signal_connect (GTK_OBJECT (drawer->button), "enter_notify_event",
346                            GTK_SIGNAL_FUNC (enter_notify_drawer), drawer);
347        gtk_signal_connect (GTK_OBJECT (drawer->button), "leave_notify_event",
348                            GTK_SIGNAL_FUNC (leave_notify_drawer), drawer);
349
350        gtk_object_set_user_data (GTK_OBJECT (drawer->button), drawer);
351        gtk_object_set_data (GTK_OBJECT (drawer_panel), DRAWER_PANEL_KEY, drawer);
352        gtk_widget_queue_resize (GTK_WIDGET (drawer_panel));
353
354        return drawer;
355}
356
357static Drawer *
358create_empty_drawer_applet(const char *tooltip, const char *pixmap,
359                           PanelOrientType orient)
360{
361        GtkWidget *dw = drawer_widget_new (orient,
362                                           BASEP_EXPLICIT_HIDE,
363                                           BASEP_SHOWN,
364                                           BASEP_LEVEL_DEFAULT,
365                                           FALSE,
366                                           SIZE_STANDARD,
367                                           TRUE, TRUE,
368                                           PANEL_BACK_NONE, NULL,
369                                           TRUE, FALSE, TRUE, NULL);
370        return create_drawer_applet (dw, tooltip, pixmap, orient);
371}
372
373void
374set_drawer_applet_orient(Drawer *drawer, PanelOrientType orient)
375{
376        g_return_if_fail(drawer!=NULL);
377
378        button_widget_set_params(BUTTON_WIDGET(drawer->button),
379                                 DRAWER_TILE,TRUE,orient);
380       
381        /*ignore orient events until we are realized, this will only
382          be the initial one and we have already set the orientation*/
383        if(!GTK_WIDGET_REALIZED(drawer->drawer))
384                return;
385       
386        drawer_widget_change_orient(DRAWER_WIDGET(drawer->drawer), orient);
387}
388
389static void
390drawer_setup(Drawer *drawer)
391{
392        gtk_widget_queue_resize(drawer->drawer);
393        if(BASEP_WIDGET(drawer->drawer)->state != BASEP_SHOWN) {
394                GtkRequisition chreq;
395                gtk_widget_size_request(drawer->drawer, &chreq);
396                gtk_widget_set_uposition(drawer->drawer,
397                                         -chreq.width - 1, -chreq.height - 1);
398        }
399        gtk_widget_show(drawer->drawer);
400}
401
402static void
403button_size_alloc(GtkWidget *widget, GtkAllocation *alloc, Drawer *drawer)
404{
405        if(!GTK_WIDGET_REALIZED(widget))
406                return;
407
408        gtk_widget_queue_resize(drawer->drawer);
409
410        gtk_object_set_data(GTK_OBJECT(widget),"allocated",GINT_TO_POINTER(1));
411}
412
413gboolean
414load_drawer_applet (int mypanel_id, const char *pixmap, const char *tooltip,
415                    PanelWidget *panel, int pos, gboolean exactpos)
416{
417        Drawer *drawer;
418        PanelOrientType orient = get_applet_orient (panel);
419
420        if (mypanel_id < 0) {
421                drawer = create_empty_drawer_applet (tooltip, pixmap, orient);
422                if (drawer != NULL)
423                        panel_setup (drawer->drawer);
424                panels_to_sync = TRUE;
425        } else {
426                PanelData *dr_pd;
427
428                dr_pd = panel_data_by_id (mypanel_id);
429
430                if (dr_pd == NULL) {
431                        g_warning ("Can't find the panel for drawer, making a new panel");
432                        drawer = create_empty_drawer_applet(tooltip, pixmap, orient);
433                        if(drawer) panel_setup(drawer->drawer);
434                        panels_to_sync = TRUE;
435                } else if ( ! IS_DRAWER_WIDGET (dr_pd->panel)) {
436                        g_warning ("I found a bogus panel for a drawer, making a new one");
437                        drawer = create_empty_drawer_applet(tooltip, pixmap, orient);
438                        if(drawer) panel_setup(drawer->drawer);
439                        panels_to_sync = TRUE;
440                } else {
441                        drawer = create_drawer_applet (dr_pd->panel, tooltip,
442                                                       pixmap, orient);
443
444                        drawer_widget_change_orient
445                                (DRAWER_WIDGET(dr_pd->panel), orient);
446                }
447        }
448
449        if(!drawer)
450                return FALSE;
451
452        {
453                GtkWidget *dw = drawer->drawer;
454
455                if(!register_toy(drawer->button,
456                                 drawer, (GDestroyNotify)g_free,
457                                 panel, pos, exactpos, APPLET_DRAWER)) {
458                        /* by this time drawer has been freed as register_toy
459                           has destroyed drawer->button */
460                        gtk_widget_destroy(dw);
461                        return FALSE;
462                }
463        }
464
465        gtk_signal_connect_after(GTK_OBJECT(drawer->button),
466                                 "size_allocate",
467                                 GTK_SIGNAL_FUNC(button_size_alloc),
468                                 drawer);
469
470        /* this doesn't make sense anymore */
471        if((BASEP_WIDGET(drawer->drawer)->state == BASEP_SHOWN) &&
472           (IS_BASEP_WIDGET (panel->panel_parent))) {
473                /*pop up, if popped down, if it's not an autohidden
474                  widget then it will just ignore this next call */
475                basep_widget_autoshow(BASEP_WIDGET(panel->panel_parent));
476        }
477
478        panel_widget_add_forbidden(PANEL_WIDGET(BASEP_WIDGET(drawer->drawer)->panel));
479
480        gtk_tooltips_set_tip (panel_tooltips,drawer->button,
481                              drawer->tooltip,NULL);
482        drawer_setup (drawer);
483
484        g_assert (applets_last != NULL);
485
486        if ( ! commie_mode)
487                applet_add_callback(applets_last->data,"properties",
488                                    GNOME_STOCK_MENU_PROP,
489                                    _("Properties..."));
490        applet_add_callback(applets_last->data, "help",
491                            GNOME_STOCK_PIXMAP_HELP,
492                            _("Help"));
493        return TRUE;
494}
495
Note: See TracBrowser for help on using the repository browser.