source: trunk/third/gnome-panel/gnome-panel/panel-applet-frame.c @ 18631

Revision 18631, 26.1 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18630, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * panel-applet-frame.c:
3 *
4 * Copyright (C) 2001 Sun Microsystems, Inc.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 *
21 * Authors:
22 *      Mark McLoughlin <mark@skynet.ie>
23 */
24
25#include <config.h>
26#include <string.h>
27
28#include <libbonoboui.h>
29#include <gconf/gconf.h>
30#include <libgnome/libgnome.h>
31#include <gdk/gdk.h>
32#include <gdk/gdkx.h>
33
34#include "panel-applet-frame.h"
35#include "panel-gconf.h"
36#include "panel-util.h"
37#include "panel.h"
38#include "session.h"
39#include "applet.h"
40#include "panel-marshal.h"
41#include "panel-background.h"
42
43#define HANDLE_SIZE 10
44
45#define PANEL_STOCK_DONT_DELETE "panel-dont-delete"
46
47#undef PANEL_APPLET_FRAME_DEBUG
48
49struct _PanelAppletFramePrivate {
50        GNOME_Vertigo_PanelAppletShell  applet_shell;
51        Bonobo_PropertyBag              property_bag;
52        BonoboUIComponent              *ui_component;
53
54        PanelWidget                    *panel;
55        AppletInfo                     *applet_info;
56        PanelOrient                     orient;
57
58        gchar                          *iid;
59        gboolean                        moving_focus_out;
60
61        GtkAllocation                   child_allocation;
62        GdkRectangle                    handle_rect;
63};
64
65static GObjectClass *parent_class;
66
67/* Keep in sync with panel-applet.h. Uggh.
68 */     
69typedef enum {
70        APPLET_FLAGS_NONE   = 0,
71        APPLET_EXPAND_MAJOR = 1 << 0,
72        APPLET_EXPAND_MINOR = 1 << 1,
73        APPLET_HAS_HANDLE   = 1 << 2,
74} PanelAppletFlags;
75
76void
77panel_applet_frame_save_to_gconf (PanelAppletFrame *frame,
78                                  const char       *gconf_key)
79{
80        GConfClient *client;
81        const char  *profile;
82        const char  *temp_key;
83
84        client  = panel_gconf_get_client ();
85        profile = panel_gconf_get_profile ();
86
87        temp_key = panel_gconf_full_key (PANEL_GCONF_APPLETS, profile, gconf_key, "bonobo_iid");
88        gconf_client_set_string (client, temp_key, frame->priv->iid, NULL);
89}
90
91void
92panel_applet_frame_load_from_gconf (PanelWidget *panel_widget,
93                                    gint         position,
94                                    const char  *gconf_key)
95{
96        GConfClient *client;
97        const char  *profile;
98        const char  *temp_key;
99        char        *applet_iid;
100
101        g_return_if_fail (panel_widget != NULL);
102        g_return_if_fail (gconf_key != NULL);
103
104        client  = panel_gconf_get_client ();
105        profile = panel_gconf_get_profile ();
106
107        temp_key = panel_gconf_full_key (PANEL_GCONF_APPLETS, profile, gconf_key, "bonobo_iid");
108        applet_iid = gconf_client_get_string (client, temp_key, NULL);
109
110        panel_applet_frame_load (applet_iid, panel_widget, position, TRUE, gconf_key);
111
112        g_free (applet_iid);
113}
114
115static void
116popup_handle_remove (BonoboUIComponent *uic,
117                     PanelAppletFrame  *frame,
118                     const gchar       *verbname)
119{
120        AppletInfo *info;
121
122        info = frame->priv->applet_info;
123        frame->priv->applet_info = NULL;
124
125        panel_applet_clean (info, TRUE);
126}
127
128static void
129popup_handle_move (BonoboUIComponent *uic,
130                   PanelAppletFrame  *frame,
131                   const gchar       *verbname)
132{
133        GtkWidget *widget;
134
135        g_return_if_fail (GTK_IS_WIDGET (frame));
136        g_return_if_fail (PANEL_IS_WIDGET (frame->priv->panel));
137
138        widget = GTK_WIDGET (frame);
139
140        g_return_if_fail (PANEL_IS_WIDGET (widget->parent));
141
142        panel_widget_applet_drag_start (
143                frame->priv->panel, widget, PW_DRAG_OFF_CENTER);
144}
145
146static BonoboUIVerb popup_verbs [] = {
147        BONOBO_UI_UNSAFE_VERB ("RemoveAppletFromPanel", popup_handle_remove),
148        BONOBO_UI_UNSAFE_VERB ("MoveApplet",            popup_handle_move),
149
150        BONOBO_UI_VERB_END
151};
152
153void
154panel_applet_frame_load (const gchar *iid,
155                         PanelWidget *panel,
156                         int          position,
157                         gboolean     exactpos,
158                         const char  *gconf_key)
159{
160        GtkWidget  *frame = NULL;
161        AppletInfo *info;
162        char       *real_key;
163
164        g_return_if_fail (iid != NULL);
165        g_return_if_fail (panel != NULL);
166
167        if (gconf_key)
168                real_key = g_strdup (gconf_key);
169        else
170                real_key = gconf_unique_key ();
171
172        frame = panel_applet_frame_new (panel, iid, real_key);
173
174        if (!frame) {
175                g_free (real_key);
176                return;
177        }
178       
179        gtk_widget_show_all (frame);
180
181        info = panel_applet_register (frame, frame, NULL, panel, position,
182                                      exactpos, APPLET_BONOBO, real_key);
183
184        if (!info)
185                g_warning (_("Cannot register control widget\n"));
186
187        g_free (real_key);
188
189        panel_applet_frame_set_info (PANEL_APPLET_FRAME (frame), info);
190}
191
192static int
193panel_applet_frame_get_flags (PanelAppletFrame *frame)
194{
195        return bonobo_pbclient_get_short (
196                        frame->priv->property_bag, "panel-applet-flags", NULL);
197}
198
199void
200panel_applet_frame_get_expand_flags (PanelAppletFrame *frame,
201                                     gboolean         *expand_major,
202                                     gboolean         *expand_minor)
203{
204        int flags;
205
206        flags = panel_applet_frame_get_flags (frame);
207
208        *expand_major = flags & APPLET_EXPAND_MAJOR;
209        *expand_minor = flags & APPLET_EXPAND_MINOR;
210}
211
212int
213panel_applet_frame_get_size_hints (PanelAppletFrame  *frame,
214                                   int              **size_hints)
215{
216        CORBA_sequence_CORBA_long *seq;
217        CORBA_any                 *value;
218        int                        retval = 0;
219        int                        extra_size = 0;
220        int                        i;
221
222
223        g_return_val_if_fail (PANEL_IS_APPLET_FRAME (frame), 0);
224        g_return_val_if_fail (size_hints != NULL, 0);
225
226        *size_hints = NULL;
227
228        value = bonobo_pbclient_get_value (frame->priv->property_bag,
229                                           "panel-applet-size-hints",
230                                           TC_CORBA_sequence_CORBA_long,
231                                           NULL);
232       
233        if (value == NULL)
234                return retval;
235
236        seq = value->_value;
237
238        retval = seq->_length;
239        *size_hints = g_new (int, seq->_length);
240
241        extra_size = 0;
242        if (panel_applet_frame_get_flags (frame) & APPLET_HAS_HANDLE)
243                extra_size = HANDLE_SIZE + 1;
244       
245        for (i = 0; i < seq->_length; i++)
246                (*size_hints) [i] = seq->_buffer [i] + extra_size;
247       
248        CORBA_free (value);
249       
250        return retval;
251}
252
253void
254panel_applet_frame_change_orient (PanelAppletFrame *frame,
255                                  PanelOrient       orient)
256{
257        if (orient == frame->priv->orient)
258                return;
259
260        frame->priv->orient = orient;
261        bonobo_pbclient_set_short (frame->priv->property_bag,
262                                   "panel-applet-orient",
263                                   orient,
264                                   NULL);
265
266        gtk_widget_queue_resize (GTK_WIDGET (frame));
267}
268
269void
270panel_applet_frame_change_size (PanelAppletFrame *frame,
271                                PanelSize         size)
272{
273        bonobo_pbclient_set_short (frame->priv->property_bag,
274                                   "panel-applet-size",
275                                   size,
276                                   NULL);
277}
278
279static char *
280panel_applet_frame_get_background_string (PanelAppletFrame    *frame,
281                                          PanelWidget         *panel,
282                                          PanelBackgroundType  type)
283{
284        return panel_background_make_string (
285                        &panel->background,
286                        GTK_WIDGET (frame)->allocation.x,
287                        GTK_WIDGET (frame)->allocation.y);
288}
289
290void
291panel_applet_frame_change_background (PanelAppletFrame    *frame,
292                                      PanelBackgroundType  type)
293{
294        char *bg_str;
295
296        g_return_if_fail (PANEL_IS_APPLET_FRAME (frame));
297        g_return_if_fail (PANEL_IS_WIDGET (GTK_WIDGET (frame)->parent));
298
299        bg_str = panel_applet_frame_get_background_string (
300                        frame, PANEL_WIDGET (GTK_WIDGET (frame)->parent), type);
301
302        bonobo_pbclient_set_string (frame->priv->property_bag,
303                                    "panel-applet-background",
304                                    bg_str, NULL);
305
306        g_free (bg_str);
307}
308
309void
310panel_applet_frame_set_info (PanelAppletFrame *frame,
311                             AppletInfo       *info)
312{
313        frame->priv->applet_info = info;
314}
315
316static void
317panel_applet_frame_finalize (GObject *object)
318{
319        PanelAppletFrame *frame = PANEL_APPLET_FRAME (object);
320
321        if (frame->priv->property_bag)
322                bonobo_object_release_unref (
323                        frame->priv->property_bag, NULL);
324
325        if (frame->priv->applet_shell)
326                bonobo_object_release_unref (
327                        frame->priv->applet_shell, NULL);
328
329        if (frame->priv->ui_component)
330                bonobo_object_unref (
331                        BONOBO_OBJECT (frame->priv->ui_component));
332
333        g_free (frame->priv->iid);
334        frame->priv->iid = NULL;
335
336        g_free (frame->priv);
337        frame->priv = NULL;
338
339        parent_class->finalize (object);
340}
341
342static void
343panel_applet_frame_paint (GtkWidget    *widget,
344                          GdkRectangle *area)
345{
346        PanelAppletFrame *frame;
347
348        frame = PANEL_APPLET_FRAME (widget);
349
350        if (!(panel_applet_frame_get_flags (frame) & APPLET_HAS_HANDLE))
351                return;
352 
353        if (GTK_WIDGET_DRAWABLE (widget)) {
354                GtkOrientation orient = 0;
355
356                switch (frame->priv->orient) {
357                case PANEL_ORIENT_UP:
358                case PANEL_ORIENT_DOWN:
359                        orient = GTK_ORIENTATION_HORIZONTAL;
360                        break;
361                case PANEL_ORIENT_LEFT:
362                case PANEL_ORIENT_RIGHT:
363                        orient = GTK_ORIENTATION_VERTICAL;
364                        break;
365                default:
366                        g_assert_not_reached ();
367                        break;
368                }
369
370                gtk_paint_handle (
371                        widget->style, widget->window,
372                        GTK_WIDGET_STATE (widget),
373                        GTK_SHADOW_OUT,
374                        area, widget, "handlebox",
375                        frame->priv->handle_rect.x,
376                        frame->priv->handle_rect.y,
377                        frame->priv->handle_rect.width,
378                        frame->priv->handle_rect.height,
379                        orient);
380        }
381}
382
383static gboolean
384panel_applet_frame_expose (GtkWidget      *widget,
385                           GdkEventExpose *event)
386{
387        if (GTK_WIDGET_DRAWABLE (widget)) {
388                GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
389
390                panel_applet_frame_paint (widget, &event->area);
391
392        }
393
394        return FALSE;
395}
396
397static void
398panel_applet_frame_constrain_size (PanelAppletFrame *frame,
399                                   GtkRequisition   *requisition)
400{
401        PanelWidget *panel;
402
403        g_return_if_fail (PANEL_IS_WIDGET (frame->priv->panel));
404
405        panel = frame->priv->panel;
406
407        switch (frame->priv->orient) {
408        case PANEL_ORIENT_UP:
409        case PANEL_ORIENT_DOWN:
410                if (requisition->height > panel->sz)
411                        requisition->height = panel->sz;
412                break;
413        case PANEL_ORIENT_LEFT:
414        case PANEL_ORIENT_RIGHT:
415                if (requisition->width > panel->sz)
416                        requisition->width = panel->sz;
417                break;
418        default:
419                g_assert_not_reached ();
420                break;
421        }
422}
423
424static void
425panel_applet_frame_size_request (GtkWidget      *widget,
426                                 GtkRequisition *requisition)
427{
428        PanelAppletFrame *frame;
429        GtkBin           *bin;
430        GtkRequisition    child_requisition; 
431
432        frame = PANEL_APPLET_FRAME (widget);
433        bin = GTK_BIN (widget);
434
435        if (!(panel_applet_frame_get_flags (frame) & APPLET_HAS_HANDLE)) {
436                GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition);
437                panel_applet_frame_constrain_size (frame, requisition);
438                return;
439        }
440 
441        requisition->width = 0;
442        requisition->height = 0;
443 
444        if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) {
445                gtk_widget_size_request (bin->child, &child_requisition);
446
447                requisition->width  = child_requisition.width;
448                requisition->height = child_requisition.height;
449        }
450
451        requisition->width += GTK_CONTAINER (widget)->border_width;
452        requisition->height += GTK_CONTAINER (widget)->border_width;
453
454        switch (frame->priv->orient) {
455        case PANEL_ORIENT_UP:
456        case PANEL_ORIENT_DOWN:
457                requisition->width += HANDLE_SIZE;
458                break;
459        case PANEL_ORIENT_LEFT:
460        case PANEL_ORIENT_RIGHT:
461                requisition->height += HANDLE_SIZE;
462                break;
463        default:
464                g_assert_not_reached ();
465                break;
466        }
467
468        panel_applet_frame_constrain_size (frame, requisition);
469}
470
471static void
472panel_applet_frame_size_allocate (GtkWidget     *widget,
473                                  GtkAllocation *allocation)
474{
475        PanelAppletFrame *frame;
476        GtkBin           *bin;
477        GtkAllocation     new_allocation;
478
479        frame = PANEL_APPLET_FRAME (widget);
480        bin = GTK_BIN (widget);
481
482        if (!(panel_applet_frame_get_flags (frame) & APPLET_HAS_HANDLE)) {
483                GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
484                return;
485        }
486
487        widget->allocation = *allocation;
488
489        frame->priv->handle_rect.x = 0;
490        frame->priv->handle_rect.y = 0;
491
492        switch (frame->priv->orient) {
493        case PANEL_ORIENT_UP:
494        case PANEL_ORIENT_DOWN:
495                frame->priv->handle_rect.width  = HANDLE_SIZE;
496                frame->priv->handle_rect.height = allocation->height;
497
498                new_allocation.x      = HANDLE_SIZE;
499                new_allocation.y      = 0;
500                new_allocation.width  = allocation->width - HANDLE_SIZE;
501                new_allocation.height = allocation->height;
502                break;
503        case PANEL_ORIENT_LEFT:
504        case PANEL_ORIENT_RIGHT:
505                frame->priv->handle_rect.width  = allocation->width;
506                frame->priv->handle_rect.height = HANDLE_SIZE;
507
508                new_allocation.x      = 0;
509                new_allocation.y      = HANDLE_SIZE;
510                new_allocation.width  = allocation->width;
511                new_allocation.height = allocation->height - HANDLE_SIZE;
512                break;
513        default:
514                g_assert_not_reached ();
515                break;
516        }
517
518        new_allocation.width  = MAX (1, new_allocation.width);
519        new_allocation.height = MAX (1, new_allocation.height);
520
521        /* If the child allocation changed, that means that the frame is drawn
522         * in a new place, so we must redraw the entire widget.
523         */
524        if (GTK_WIDGET_MAPPED (widget) &&
525            (new_allocation.x != frame->priv->child_allocation.x ||
526             new_allocation.y != frame->priv->child_allocation.y ||
527             new_allocation.width != frame->priv->child_allocation.width ||
528             new_allocation.height != frame->priv->child_allocation.height))
529                gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
530
531        if (GTK_WIDGET_REALIZED (widget)) {
532                gdk_window_move_resize (widget->window,
533                        allocation->x + GTK_CONTAINER (widget)->border_width,
534                        allocation->y + GTK_CONTAINER (widget)->border_width,
535                        MAX (allocation->width - GTK_CONTAINER (widget)->border_width * 2, 0),
536                        MAX (allocation->height - GTK_CONTAINER (widget)->border_width * 2, 0));
537        }
538
539        if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
540                gtk_widget_size_allocate (bin->child, &new_allocation);
541 
542        frame->priv->child_allocation = new_allocation;
543}
544
545static inline gboolean
546button_event_in_rect (GdkEventButton *event,
547                      GdkRectangle   *rect)
548{
549        if (event->x >= rect->x &&
550            event->x <= (rect->x + rect->width) &&
551            event->y >= rect->y &&
552            event->y <= (rect->y + rect->height))
553                return TRUE;
554
555        return FALSE;
556}
557
558static gboolean
559panel_applet_frame_button_changed (GtkWidget      *widget,
560                                   GdkEventButton *event)
561{
562        PanelAppletFrame *frame;
563        gboolean          handled = FALSE;
564
565        frame = PANEL_APPLET_FRAME (widget);
566
567        if (!(panel_applet_frame_get_flags (frame) & APPLET_HAS_HANDLE))
568                return handled;
569
570        if (event->window != widget->window)
571                return FALSE;
572
573        switch (event->button) {
574        case 1:
575        case 2:
576                if (button_event_in_rect (event, &frame->priv->handle_rect)) {
577                        if (event->type == GDK_BUTTON_PRESS ||
578                            event->type == GDK_2BUTTON_PRESS) {
579                                panel_widget_applet_drag_start (
580                                        frame->priv->panel, GTK_WIDGET (frame), PW_DRAG_OFF_CURSOR);
581                                handled = TRUE;
582                        } else if (event->type == GDK_BUTTON_RELEASE) {
583                                panel_widget_applet_drag_end (frame->priv->panel);
584                                handled = TRUE;
585                        }
586                }
587                break;
588        case 3:
589                if (event->type == GDK_BUTTON_PRESS ||
590                    event->type == GDK_2BUTTON_PRESS) {
591                        CORBA_Environment env;
592
593                        CORBA_exception_init (&env);
594
595                        gdk_pointer_ungrab (GDK_CURRENT_TIME);
596
597                        GNOME_Vertigo_PanelAppletShell_popup_menu (
598                                        frame->priv->applet_shell,
599                                        event->button,
600                                        event->time, &env);
601                        if (BONOBO_EX (&env))
602                                g_warning (_("Exception from popup_menu '%s'\n"), env._id);
603
604                        CORBA_exception_free (&env);
605
606                        handled = TRUE;
607
608                } else if (event->type == GDK_BUTTON_RELEASE)
609                        handled = TRUE;
610                break;
611        default:
612                break;
613        }
614
615        return handled;
616}
617
618static void
619panel_applet_frame_reload_response (GtkWidget        *dialog,
620                                    int               response,
621                                    PanelAppletFrame *frame)
622{
623        AppletInfo *info;
624
625        g_return_if_fail (PANEL_IS_APPLET_FRAME (frame));
626
627        if (!frame->priv->iid || !frame->priv->panel)
628                return;
629
630        info = frame->priv->applet_info;
631
632        if (response == GTK_RESPONSE_YES) {
633                PanelWidget *panel;
634                char        *iid;
635                char        *gconf_key = NULL;
636                int          position = -1;
637
638                panel = frame->priv->panel;
639                iid   = g_strdup (frame->priv->iid);
640
641                if (info) {
642                        gconf_key = g_strdup (info->gconf_key);
643                        position  = panel_applet_get_position (info);
644                        panel_applet_clean (info, FALSE);
645                }
646
647                panel_applet_frame_load (iid, panel, position, TRUE, gconf_key);
648
649                g_free (iid);
650                g_free (gconf_key);
651
652        } else if (info)
653                panel_applet_clean (info, TRUE);
654
655        g_object_unref (frame);
656        gtk_widget_destroy (dialog);
657}
658
659static char *
660panel_applet_frame_get_name (char *iid)
661{
662        Bonobo_ServerInfoList *list;
663        char                  *query;
664        char                  *retval = NULL;
665       
666        query = g_strdup_printf ("iid == '%s'", iid);
667
668        list = bonobo_activation_query (query, NULL, NULL);
669        if (list && list->_length > 0 && list->_buffer) {
670                Bonobo_ServerInfo *info = &list->_buffer [0];
671                const GList       *langs_glist;
672                GSList            *langs_gslist;
673
674                /* Evil evil evil evil, we need to convert to
675                 * a GSList from a GList */
676                langs_glist = gnome_i18n_get_language_list ("LC_MESSAGES");
677                langs_gslist = NULL;
678                while (langs_glist) {
679                        langs_gslist = g_slist_append (langs_gslist, langs_glist->data);
680                        langs_glist = langs_glist->next;
681                }
682
683                retval = g_strdup (bonobo_server_info_prop_lookup (
684                                                info, "name", langs_gslist));
685
686                g_slist_free (langs_gslist);
687        }
688
689        g_free (query);
690        CORBA_free (list);
691
692        return retval;
693}
694
695static void
696panel_applet_frame_cnx_broken (PanelAppletFrame *frame)
697{
698        GtkWidget *dialog;
699        GdkScreen *screen;
700        char      *applet_name = NULL;
701        char      *txt;
702
703        g_return_if_fail (PANEL_IS_APPLET_FRAME (frame));
704
705        screen = gtk_widget_get_screen (GTK_WIDGET (frame));
706
707        if (frame->priv->iid)
708                applet_name = panel_applet_frame_get_name (frame->priv->iid);
709
710        txt = g_strdup_printf (
711                        _("The %s applet appears to have died "
712                          "unexpectedly\n\n"
713                          "Reload this applet?\n\n"
714                          "(If you choose not to reload it at this time"
715                          " you can always add it by right clicking on "
716                          "the panel and clicking on the \"Add to Panel\""
717                          " submenu)"), applet_name ? applet_name : "");
718
719        dialog = gtk_message_dialog_new (
720                                NULL,
721                                GTK_DIALOG_DESTROY_WITH_PARENT,
722                                GTK_MESSAGE_QUESTION,
723                                GTK_BUTTONS_YES_NO,
724                                txt);
725        gtk_window_set_screen (GTK_WINDOW (dialog), screen);
726
727        g_signal_connect (dialog, "response",
728                          G_CALLBACK (panel_applet_frame_reload_response),
729                          g_object_ref (frame));
730
731        gtk_widget_show (dialog);
732        g_free (applet_name);
733        g_free (txt);
734}
735
736static inline void
737register_stock_item (void)
738{
739        static gboolean registered = FALSE;
740
741        if (!registered) {
742                GtkIconFactory      *factory;
743                GtkIconSet          *cancel_icons;
744
745                static GtkStockItem  dont_delete_item [] = {
746                        { PANEL_STOCK_DONT_DELETE, N_("D_on't Delete"), 0, 0, GETTEXT_PACKAGE },
747                };
748
749                cancel_icons = gtk_icon_factory_lookup_default (GTK_STOCK_CANCEL);
750
751                factory = gtk_icon_factory_new ();
752
753                gtk_icon_factory_add (factory, PANEL_STOCK_DONT_DELETE, cancel_icons);
754
755                gtk_icon_factory_add_default (factory);
756
757                gtk_stock_add_static (dont_delete_item, 1);
758
759                registered = TRUE;
760        }
761}
762
763static void
764panel_applet_frame_loading_failed (PanelAppletFrame  *frame,
765                                   CORBA_Environment *ev,
766                                   const char        *iid,
767                                   const char        *gconf_key,
768                                   GtkWindow         *panel)
769{
770        GtkWidget *dialog;
771        char      *error;
772        int        response;
773
774        error = bonobo_exception_get_text (ev);
775
776        dialog = gtk_message_dialog_new (
777                                NULL, 0,
778                                GTK_MESSAGE_QUESTION,
779                                GTK_BUTTONS_NONE,
780                                _("The panel encountered a problem while loading \"%s\"\n"
781                                  "Details: %s\n\n"
782                                  "Do you want to delete the applet from your configuration?"),
783                                iid, error);
784
785        g_free (error);
786
787        register_stock_item ();
788
789        gtk_dialog_add_buttons (GTK_DIALOG (dialog),
790                                PANEL_STOCK_DONT_DELETE, GTK_RESPONSE_CANCEL,
791                                GTK_STOCK_DELETE, GTK_RESPONSE_OK,
792                                NULL);
793        gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
794
795        gtk_window_set_screen (GTK_WINDOW (dialog),
796                               gtk_window_get_screen (panel));
797
798        response = gtk_dialog_run (GTK_DIALOG (dialog));
799
800        gtk_widget_destroy (dialog);
801
802        if (response == GTK_RESPONSE_OK)
803                panel_applet_clean_gconf (APPLET_BONOBO, gconf_key, TRUE);
804}
805
806static void
807panel_applet_frame_class_init (PanelAppletFrameClass *klass,
808                               gpointer               dummy)
809{
810        GObjectClass   *gobject_class = (GObjectClass *) klass;
811        GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
812
813        parent_class = g_type_class_peek_parent (klass);
814
815        gobject_class->finalize = panel_applet_frame_finalize;
816
817        widget_class->expose_event         = panel_applet_frame_expose;
818        widget_class->size_request         = panel_applet_frame_size_request;
819        widget_class->size_allocate        = panel_applet_frame_size_allocate;
820        widget_class->button_press_event   = panel_applet_frame_button_changed;
821        widget_class->button_release_event = panel_applet_frame_button_changed;
822}
823
824static void
825panel_applet_frame_instance_init (PanelAppletFrame      *frame,
826                                  PanelAppletFrameClass *klass)
827{
828        frame->priv = g_new0 (PanelAppletFramePrivate, 1);
829
830        frame->priv->applet_shell     = CORBA_OBJECT_NIL;
831        frame->priv->property_bag     = CORBA_OBJECT_NIL;
832        frame->priv->ui_component     = NULL;
833        frame->priv->panel            = NULL;
834        frame->priv->orient           = PANEL_ORIENT_UP;
835        frame->priv->applet_info      = NULL;
836        frame->priv->moving_focus_out = FALSE;
837}
838
839GType
840panel_applet_frame_get_type (void)
841{
842        static GType type = 0;
843
844        if (!type) {
845                static const GTypeInfo info = {
846                        sizeof (PanelAppletFrameClass),
847                        NULL,
848                        NULL,
849                        (GClassInitFunc) panel_applet_frame_class_init,
850                        NULL,
851                        NULL,
852                        sizeof (PanelAppletFrame),
853                        0,
854                        (GInstanceInitFunc) panel_applet_frame_instance_init,
855                        NULL
856                };
857
858                type = g_type_register_static (GTK_TYPE_EVENT_BOX,
859                                               "PanelAppletFrame",
860                                               &info, 0);
861        }
862
863        return type;
864}
865
866static GNOME_Vertigo_PanelAppletShell
867panel_applet_frame_get_applet_shell (Bonobo_Control control)
868{
869        CORBA_Environment              env;
870        GNOME_Vertigo_PanelAppletShell retval;
871
872        CORBA_exception_init (&env);
873
874        retval = Bonobo_Unknown_queryInterface (control,
875                                                "IDL:GNOME/Vertigo/PanelAppletShell:1.0",
876                                                &env);
877        if (BONOBO_EX (&env)) {
878                g_warning (_("Unable to obtain AppletShell interface from control\n"));
879
880                retval = CORBA_OBJECT_NIL;
881        }
882
883        CORBA_exception_free (&env);
884
885        return retval;
886}
887
888static G_CONST_RETURN char *
889panel_applet_frame_get_orient_string (PanelAppletFrame *frame,
890                                      PanelWidget      *panel)
891{
892        PanelOrient  orient;
893        const char  *retval = NULL;
894
895        orient = panel_widget_get_applet_orient (panel);
896
897        switch (orient) {
898        case PANEL_ORIENT_UP:
899                retval = "up";
900                break;
901        case PANEL_ORIENT_DOWN:
902                retval = "down";
903                break;
904        case PANEL_ORIENT_LEFT:
905                retval = "left";
906                break;
907        case PANEL_ORIENT_RIGHT:
908                retval = "right";
909                break;
910        default:
911                g_assert_not_reached ();
912                break;
913        }
914
915        return retval;
916}
917
918static G_CONST_RETURN char *
919panel_applet_frame_get_size_string (PanelAppletFrame *frame,
920                                    PanelWidget      *panel)
921{
922        const char *retval = NULL;
923
924        switch (panel->sz) {
925        case PANEL_SIZE_XX_SMALL:
926                retval = "xx-small";
927                break;
928        case PANEL_SIZE_X_SMALL:
929                retval = "x-small";
930                break;
931        case PANEL_SIZE_SMALL:
932                retval = "small";
933                break;
934        case PANEL_SIZE_MEDIUM:
935                retval = "medium";
936                break;
937        case PANEL_SIZE_LARGE:
938                retval = "large";
939                break;
940        case PANEL_SIZE_X_LARGE:
941                retval = "x-large";
942                break;
943        case PANEL_SIZE_XX_LARGE:
944                retval = "xx-large";
945                break;
946        default:
947                g_assert_not_reached ();
948                break;
949        }
950
951        return retval;
952}
953
954static char *
955panel_applet_frame_construct_moniker (PanelAppletFrame *frame,
956                                      PanelWidget      *panel,
957                                      const char       *iid,
958                                      const char       *gconf_key)
959{
960        char *retval;
961        char *bg_str;
962
963        bg_str = panel_applet_frame_get_background_string (
964                                frame, panel, panel->background.type);
965
966        retval = g_strdup_printf (
967                        "%s!prefs_key=/apps/panel/profiles/%s/applets/%s/prefs;"
968                        "background=%s;orient=%s;size=%s",
969                        iid, panel_gconf_get_profile (), gconf_key, bg_str,
970                        panel_applet_frame_get_orient_string (frame, panel),
971                        panel_applet_frame_get_size_string (frame, panel));
972
973        g_free (bg_str);
974
975        return retval;
976}
977
978GtkWidget *
979panel_applet_frame_construct (PanelAppletFrame *frame,
980                              PanelWidget      *panel,
981                              const char       *iid,
982                              const char       *gconf_key)
983{
984        BonoboControlFrame    *control_frame;
985        Bonobo_Control         control;
986        CORBA_Environment      ev;
987        ORBitConnectionStatus  cnx_status;
988        GtkWidget             *widget;
989        char                  *moniker;
990
991        frame->priv->panel = panel;
992
993        moniker = panel_applet_frame_construct_moniker (frame, panel, iid, gconf_key);
994
995        /* FIXME: this should really use bonobo_get_object_async */
996        CORBA_exception_init (&ev);
997
998        control = bonobo_get_object (
999                moniker, "IDL:Bonobo/Control:1.0", &ev);
1000
1001        g_free (moniker);
1002
1003        if (BONOBO_EX (&ev)) {
1004                panel_applet_frame_loading_failed (
1005                        frame, &ev, iid, gconf_key, GTK_WINDOW (panel->panel_parent));
1006                CORBA_exception_free (&ev);
1007                return NULL;
1008        }
1009
1010        frame->priv->iid = g_strdup (iid);
1011
1012        cnx_status = ORBit_small_get_connection_status (control);
1013        if (cnx_status != ORBIT_CONNECTION_IN_PROC)
1014                g_signal_connect_object (
1015                        ORBit_small_get_connection (control),
1016                        "broken",
1017                        G_CALLBACK (panel_applet_frame_cnx_broken),
1018                        frame,
1019                        G_CONNECT_SWAPPED);
1020       
1021        CORBA_exception_free (&ev);
1022
1023        widget = bonobo_widget_new_control_from_objref (control, CORBA_OBJECT_NIL);
1024
1025        bonobo_object_release_unref (control, NULL);
1026
1027        if (!widget) {
1028                g_warning (G_STRLOC ": failed to load applet %s", iid);
1029                return NULL;
1030        }
1031
1032        control_frame = bonobo_widget_get_control_frame (BONOBO_WIDGET (widget));
1033
1034        frame->priv->property_bag =
1035                bonobo_control_frame_get_control_property_bag (control_frame, NULL);
1036
1037        frame->priv->ui_component =
1038                bonobo_control_frame_get_popup_component (control_frame, NULL);
1039        if (!frame->priv->ui_component)
1040                return NULL;
1041
1042        bonobo_ui_util_set_ui (frame->priv->ui_component, DATADIR,
1043                               "GNOME_Panel_Popup.xml", "panel", NULL);
1044
1045        bonobo_ui_component_add_verb_list_with_data (
1046                frame->priv->ui_component, popup_verbs, frame);
1047
1048        control = bonobo_control_frame_get_control (control_frame);
1049        if (!control)
1050                return NULL;
1051
1052        frame->priv->applet_shell = panel_applet_frame_get_applet_shell (control);
1053
1054        gtk_container_add (GTK_CONTAINER (frame), widget);
1055
1056        return widget;
1057}
1058
1059GtkWidget *
1060panel_applet_frame_new (PanelWidget *panel,
1061                        const char  *iid,
1062                        const char  *gconf_key)
1063{
1064        PanelAppletFrame *frame;
1065
1066        g_return_val_if_fail (iid != NULL && gconf_key != NULL, NULL);
1067
1068        frame = g_object_new (PANEL_TYPE_APPLET_FRAME, NULL);
1069
1070        if (!panel_applet_frame_construct (frame, panel, iid, gconf_key)) {
1071                gtk_object_sink (GTK_OBJECT (frame));
1072                return NULL;
1073        }
1074
1075        return GTK_WIDGET (frame);
1076}
Note: See TracBrowser for help on using the repository browser.