+extern "C" {
+ static gboolean
+ open_pdf (Container *container, const char *name)
+ {
+ GnomeObjectClient *object;
+ GnomeStream *stream;
+ GNOME_PersistStream persist;
+ Component *comp;
+ CORBA_Environment ev;
+
+ g_return_val_if_fail (container != NULL, FALSE);
+ g_return_val_if_fail (container->view_widget == NULL, FALSE);
+
+ comp = container_activate_component (container, "bonobo-object:image-x-pdf");
+ if (!comp || !(object = comp->server)) {
+ gnome_error_dialog (_("Could not launch bonobo object."));
+ return FALSE;
+ }
+
+ CORBA_exception_init (&ev);
+ persist = GNOME_Unknown_query_interface (
+ gnome_object_corba_objref (GNOME_OBJECT (object)),
+ "IDL:GNOME/PersistStream:1.0", &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION ||
+ persist == CORBA_OBJECT_NIL) {
+ gnome_error_dialog ("Panic: component is well broken.");
+ return FALSE;
+ }
+
+ stream = gnome_stream_fs_open (name, GNOME_Storage_READ);
+
+ if (stream == NULL) {
+ char *err = g_strconcat (_("Could not open "), name, NULL);
+ gnome_error_dialog_parented (err, GTK_WINDOW(container->app));
+ g_free (err);
+ return FALSE;
+ }
+
+ GNOME_PersistStream_load (persist,
+ (GNOME_Stream) gnome_object_corba_objref (GNOME_OBJECT (stream)), &ev);
+
+
+
+ GNOME_Unknown_unref (persist, &ev);
+ CORBA_Object_release (persist, &ev);
+ CORBA_exception_free (&ev);
+ return TRUE;
+ }
+
+ static void
+ set_ok (GtkWidget *widget, gboolean *dialog_result)
+ {
+ *dialog_result = TRUE;
+ gtk_main_quit ();
+ }
+
+ static guint
+ file_dialog_delete_event (GtkWidget *widget, GdkEventAny *event)
+ {
+ gtk_main_quit ();
+ return TRUE;
+ }
+
+ static void
+ container_open_cmd (GtkWidget *widget, Container *container)
+ {
+ GtkFileSelection *fsel;
+ gboolean accepted = FALSE;
+
+ fsel = GTK_FILE_SELECTION (gtk_file_selection_new (_("Load file")));
+ gtk_window_set_modal (GTK_WINDOW (fsel), TRUE);
+
+ gtk_window_set_transient_for (GTK_WINDOW (fsel),
+ GTK_WINDOW (container->app));
+
+ /* Connect the signals for Ok and Cancel */
+ gtk_signal_connect (GTK_OBJECT (fsel->ok_button), "clicked",
+ GTK_SIGNAL_FUNC (set_ok), &accepted);
+ gtk_signal_connect (GTK_OBJECT (fsel->cancel_button), "clicked",
+ GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
+ gtk_window_set_position (GTK_WINDOW (fsel), GTK_WIN_POS_MOUSE);
+
+ /*
+ * Make sure that we quit the main loop if the window is destroyed
+ */
+ gtk_signal_connect (GTK_OBJECT (fsel), "delete_event",
+ GTK_SIGNAL_FUNC (file_dialog_delete_event), NULL);
+
+ /* Run the dialog */
+ gtk_widget_show (GTK_WIDGET (fsel));
+ gtk_grab_add (GTK_WIDGET (fsel));
+ gtk_main ();
+
+ if (accepted) {
+ char *name = gtk_file_selection_get_filename (fsel);
+
+ if (name [strlen (name)-1] != '/') {
+ char *fname = g_strdup (name);
+ if (container->view_widget) /* any sort of MDI sucks :-] */
+ container = container_new (fname);
+ else
+ open_pdf (container, fname);
+ g_free (fname);
+ } else {
+ GtkWidget *dialog;
+ dialog = gnome_message_box_new ("Can't open a directory",
+ GNOME_MESSAGE_BOX_ERROR,
+ GNOME_STOCK_BUTTON_OK, NULL);
+ gnome_dialog_set_parent (GNOME_DIALOG (dialog),
+ GTK_WINDOW (container->app));
+ gnome_dialog_run (GNOME_DIALOG (dialog));
+ }
+ }
+
+ gtk_widget_destroy (GTK_WIDGET (fsel));
+ }
+
+ static void
+ container_destroy (Container *cont)
+ {
+ containers = g_list_remove (containers, cont);
+ gtk_widget_destroy (cont->app);
+ g_free (cont);
+ if (!containers)
+ gtk_main_quit ();
+ }
+
+ static void
+ container_close_cmd (GtkWidget *widget, Container *cont)
+ {
+ container_destroy (cont);
+ }
+
+ static void
+ container_exit_cmd (void)
+ {
+ while (containers)
+ container_destroy ((Container *)containers->data);
+ }
+
+ /*
+ * Enforces the containers zoom factor.
+ */
+ static void
+ zoom_set (Container *container)
+ {
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (container->component != NULL);
+
+ gnome_view_frame_set_zoom_factor (container->component->view_frame,
+ container->zoom);
+ }
+
+ static void
+ zoom_in_cmd (GtkWidget *widget, Container *container)
+ {
+ g_return_if_fail (container != NULL);
+ container->zoom *= 1.4;
+ zoom_set (container);
+ }
+
+ static void
+ zoom_out_cmd (GtkWidget *widget, Container *container)
+ {
+ g_return_if_fail (container != NULL);
+ container->zoom /= 1.4;
+ zoom_set (container);
+ }
+
+ static void
+ component_user_activate_request_cb (GnomeViewFrame *view_frame, gpointer data)
+ {
+ Component *component = (Component *) data;
+ Container *container = component->container;
+
+ /*
+ * If there is a
+ * If there is already an active View, deactivate it.
+ */
+ if (container->active_view_frame != NULL) {
+ /*
+ * This just sends a notice to the embedded View that
+ * it is being deactivated. We will also forcibly
+ * cover it so that it does not receive any Gtk
+ * events.
+ */
+ gnome_view_frame_view_deactivate (container->active_view_frame);
+
+ /*
+ * Here we manually cover it if it hasn't acquiesced.
+ * If it has consented to be deactivated, then it will
+ * already have notified us that it is inactive, and
+ * we will have covered it and set active_view_frame
+ * to NULL. Which is why this check is here.
+ */
+ if (container->active_view_frame != NULL)
+ gnome_view_frame_set_covered (container->active_view_frame, TRUE);
+
+ container->active_view_frame = NULL;
+ }
+
+ /*
+ * Activate the View which the user clicked on. This just
+ * sends a request to the embedded View to activate itself.
+ * When it agrees to be activated, it will notify its
+ * ViewFrame, and our view_activated_cb callback will be
+ * called.
+ *
+ * We do not uncover the View here, because it may not wish to
+ * be activated, and so we wait until it notifies us that it
+ * has been activated to uncover it.
+ */
+ gnome_view_frame_view_activate (view_frame);
+ }
+
+ static void
+ component_view_activated_cb (GnomeViewFrame *view_frame, gboolean activated, gpointer data)
+ {
+ Component *component = (Component *) data;
+ Container *container = component->container;
+
+ if (activated) {
+ /*
+ * If the View is requesting to be activated, then we
+ * check whether or not there is already an active
+ * View.
+ */
+ if (container->active_view_frame != NULL) {
+ g_warning ("View requested to be activated but there is already "
+ "an active View!\n");
+ return;
+ }
+
+ /*
+ * Otherwise, uncover it so that it can receive
+ * events, and set it as the active View.
+ */
+ gnome_view_frame_set_covered (view_frame, FALSE);
+ container->active_view_frame = view_frame;
+ } else {
+ /*
+ * If the View is asking to be deactivated, always
+ * oblige. We may have already deactivated it (see
+ * user_activation_request_cb), but there's no harm in
+ * doing it again. There is always the possibility
+ * that a View will ask to be deactivated when we have
+ * not told it to deactivate itself, and that is
+ * why we cover the view here.
+ */
+ gnome_view_frame_set_covered (view_frame, TRUE);
+
+ if (view_frame == container->active_view_frame)
+ container->active_view_frame = NULL;
+ }
+ }
+
+ static void
+ component_user_context_cb (GnomeViewFrame *view_frame, gpointer data)
+ {
+ Component *component = (Component *) data;
+ char *executed_verb;
+ GList *l;
+
+ /*
+ * See if the remote GnomeEmbeddable supports any verbs at
+ * all.
+ */
+ l = gnome_client_site_get_verbs (component->client_site);
+ if (l == NULL)
+ return;
+ gnome_client_site_free_verbs (l);
+
+ /*
+ * Popup the verb popup and execute the chosen verb. This
+ * function saves us the work of creating the menu, connecting
+ * the callback, and executing the verb on the remove
+ * GnomeView. We could implement all this functionality
+ * ourselves if we wanted.
+ */
+ executed_verb = gnome_view_frame_popup_verbs (view_frame);
+
+ g_free (executed_verb);
+ }