* BonoboObject data
*/
typedef struct {
- GnomeEmbeddable *embed_obj;
+ GnomeEmbeddable *embeddable;
PDFDoc *pdf;
GNOME_Stream stream; /* To free it later */
double scale;
GtkWidget *drawing_area;
GdkPixmap *pixmap;
+ GdkWindow *win;
GOutputDev *out;
GdkColor paper;
gint w, h;
gint page;
} view_data_t;
-static void realize_drawing_areas (bed_t *bed);
+extern "C" {
+ static void realize_drawing_areas (bed_t *bed);
+}
static void
redraw_view (view_data_t *view_data, GdkRectangle *rect)
static void
configure_size (view_data_t *view_data, GdkRectangle *rect)
{
-/* ArtPixBuf *pixbuf;
-
- if (view_data->scaled)
- pixbuf = view_data->scaled;
- else
- pixbuf = view_data->bed->image;
-*/
gtk_widget_set_usize (
view_data->drawing_area,
view_data->w,
rect->y = 0;
rect->width = view_data->w;
rect->height = view_data->h;
+ printf ("Set size to %d, %d\n", view_data->w, view_data->h);
}
static void
CORBA_Object_duplicate (stream, &ev);
g_return_val_if_fail (ev._major == CORBA_NO_EXCEPTION, 0);
-/* buffer = GNOME_Stream_iobuf__alloc ();
- length = GNOME_Stream_length (stream, &ev);
-
- name = tempnam (NULL, "xpdf-hack");
- if (!name)
- return -1;
- hack = fopen (name, "wb+");
- if (!hack)
- return -1;
-
- while (length > 0) {
- guint getlen;
- if (length > 128)
- getlen = 128;
- else
- getlen = length;
- GNOME_Stream_read (stream, getlen, &buffer, &ev);
- fwrite (buffer->_buffer, 1, buffer->_length, hack);
- length -= buffer->_length;
- }
-
- fclose (hack);
-
- CORBA_free (buffer);*/
-
printf ("Loading PDF from persiststream\n");
bed->stream = stream;
BonoboStream *bs = new BonoboStream (stream);
return pixmap;
}
+extern "C" {
+ static void
+ view_color_select_cb (GnomeUIHandler *uih, void *data, char *path)
+ {
+ view_data_t *view_data = (view_data_t *) data;
+
+ printf ("path '%s'\n", path);
+ }
+}
+
+static void
+view_create_menus (view_data_t *view_data)
+{
+ GNOME_UIHandler remote_uih;
+ GnomeView *view = view_data->view;
+ GnomeUIHandler *uih;
+
+ uih = gnome_view_get_ui_handler (view);
+ remote_uih = gnome_view_get_remote_ui_handler (view);
+
+ if (remote_uih == CORBA_OBJECT_NIL) {
+ g_warning ("server has no UI hander");
+ return;
+ }
+
+ gnome_ui_handler_set_container (uih, remote_uih);
+
+ gnome_ui_handler_menu_new_subtree (uih, "/Colors",
+ N_("Select drawing color..."),
+ N_("Set the current drawing color"),
+ 1,
+ GNOME_UI_HANDLER_PIXMAP_NONE, NULL,
+ 0, 0);
+ gnome_ui_handler_menu_new_radiogroup (uih, "/Colors/color radiogroup");
+
+ gnome_ui_handler_menu_new_radioitem (uih, "/Colors/color radiogroup/White",
+ N_("White"),
+ N_("Set the current drawing color to white"),
+ -1,
+ 0, (GdkModifierType) 0,
+ view_color_select_cb, (gpointer) view_data);
+
+ gnome_ui_handler_menu_new_radioitem (uih, "/Colors/color radiogroup/Red",
+ N_("Red"),
+ N_("Set the current drawing color to red"),
+ -1,
+ 0, (GdkModifierType) 0,
+ view_color_select_cb, (gpointer) view_data);
+
+ gnome_ui_handler_menu_new_radioitem (uih, "/Colors/color radiogroup/Green",
+ N_("Green"),
+ N_("Set the current drawing color to green"),
+ -1,
+ 0, (GdkModifierType) 0,
+ view_color_select_cb, (gpointer) view_data);
+}
+
+/*
+ * When this view is deactivated, we must remove our menu items.
+ */
+static void
+view_remove_menus (view_data_t *view_data)
+{
+ GnomeView *view = view_data->view;
+ GnomeUIHandler *uih;
+
+ uih = gnome_view_get_ui_handler (view);
+
+ gnome_ui_handler_unset_container (uih);
+}
+
extern "C" {
static void
{
g_return_if_fail (view_data != NULL);
g_return_if_fail (view_data->bed != NULL);
- g_return_if_fail (view_data->bed->pdf != NULL);
-
- if (!view_data->pixmap) {
- GdkWindow *win = gtk_widget_get_parent_window (drawing_area);
- GdkRectangle tmp;
-
- g_return_if_fail (win);
-
- view_data->pixmap = setup_pixmap (view_data->bed, view_data, win);
- view_data->bed->pdf->displayPage(view_data->out, view_data->page, view_data->zoom, 0, gTrue);
-
- configure_size (view_data, &tmp);
+
+ view_data->win = gtk_widget_get_parent_window (drawing_area);
+ if (!view_data->bed->pdf ||
+ !view_data->pixmap) {
+ g_warning ("Failed to setup pixmap");
+ return;
}
}
!view_data->bed->pdf)
return TRUE;
-/* Hoisted from view_factory: ugly */
redraw_view (view_data, &event->area);
return TRUE;
}
-}
-static void
-realize_drawing_areas (bed_t *bed)
-{
- GList *l;
-
- for (l = bed->views; l; l = l->next){
- GdkRectangle rect;
- view_data_t *view_data = (view_data_t *)l->data;
+ static void
+ view_activate (GnomeView *view, gboolean activate, gpointer data)
+ {
+ view_data_t *view_data = (view_data_t *) data;
+
+ gnome_view_activate_notify (view, activate);
+
+ /*
+ * If we were just activated, we merge in our menu entries.
+ * If we were just deactivated, we remove them.
+ */
+ if (activate)
+ view_create_menus (view_data);
+ else
+ view_remove_menus (view_data);
+ }
- drawing_area_realize (view_data->drawing_area, view_data);
- }
+ static void
+ view_size_query (GnomeView *view, int *desired_width, int *desired_height,
+ gpointer data)
+ {
+ view_data_t *view_data = (view_data_t *) data;
+
+ *desired_width = view_data->w;
+ *desired_height = view_data->h;
+ }
+
+ static void
+ render_page (view_data_t *view_data)
+ {
+ view_data->pixmap = setup_pixmap (view_data->bed, view_data,
+ view_data->win);
+ view_data->bed->pdf->displayPage(view_data->out,
+ view_data->page, view_data->zoom,
+ 0, gTrue);
+ }
+
+ static void
+ realize_drawing_areas (bed_t *bed)
+ {
+ GList *l;
+
+ for (l = bed->views; l; l = l->next) {
+ GdkRectangle rect;
+ view_data_t *view_data = (view_data_t *)l->data;
+ g_return_if_fail (view_data->win);
+ render_page (view_data);
+ configure_size (view_data, &rect);
+ }
+ }
+
+ static void
+ view_switch_page (GnomeView *view, const char *verb_name, void *user_data)
+ {
+ view_data_t *view_data = (view_data_t *) user_data;
+ GdkRectangle rect;
+ gboolean changed = FALSE;
+
+ if (!g_strcasecmp (verb_name, "nextpage")) {
+ printf ("next page\n");
+ if (view_data->page < view_data->bed->pdf->getNumPages()) {
+ view_data->page++;
+ changed = TRUE;
+ }
+ } else if (!g_strcasecmp (verb_name, "prevpage")) {
+ printf ("previous page\n");
+ if (view_data->page > 1) {
+ view_data->page--;
+ changed = TRUE;
+ }
+ } else
+ g_warning ("Unknown verb");
+
+ if (changed) {
+ render_page (view_data);
+ redraw_view (view_data, &rect);
+ gtk_widget_queue_draw (GTK_WIDGET (view_data->drawing_area));
+ }
+ }
}
static GnomeView *
-view_factory (GnomeEmbeddable *embed_obj,
+view_factory (GnomeEmbeddable *embeddable,
const GNOME_ViewFrame view_frame,
void *data)
{
GnomeView *view;
+ GnomeUIHandler *uih;
bed_t *bed = (bed_t *)data;
view_data_t *view_data = g_new (view_data_t, 1);
view_data->bed = bed;
view_data->drawing_area = gtk_drawing_area_new ();
view_data->pixmap = NULL;
+ view_data->win = NULL;
view_data->out = NULL;
view_data->w = 320;
view_data->h = 320;
GTK_OBJECT (view), "destroy",
GTK_SIGNAL_FUNC (destroy_view), view_data);
+ /* UI handling */
+ uih = gnome_ui_handler_new ();
+ gnome_view_set_ui_handler (view, uih);
+
+ gtk_signal_connect (GTK_OBJECT (view), "view_activate",
+ GTK_SIGNAL_FUNC (view_activate), view_data);
+
+ gtk_signal_connect (GTK_OBJECT (view), "size_query",
+ GTK_SIGNAL_FUNC (view_size_query), view_data);
+
bed->views = g_list_prepend (bed->views, view_data);
+ /* Verb handling */
+ gnome_view_register_verb (view, "NextPage",
+ view_switch_page, view_data);
+ gnome_view_register_verb (view, "PrevPage",
+ view_switch_page, view_data);
+
return view;
}
static GnomeObject *
-embed_obj_factory (GnomeEmbeddableFactory *This, void *data)
+embeddable_factory (GnomeEmbeddableFactory *This, void *data)
{
- GnomeEmbeddable *embed_obj;
+ GnomeEmbeddable *embeddable;
GnomePersistStream *stream;
bed_t *bed = (bed_t *)data;
/*
* Creates the BonoboObject server
*/
- embed_obj = gnome_embeddable_new (view_factory, bed);
- if (embed_obj == NULL){
+ embeddable = gnome_embeddable_new (view_factory, bed);
+ if (embeddable == NULL){
g_free (bed);
return NULL;
}
load_image_from_stream,
save_image,
bed);
- if (stream == NULL){
- gtk_object_unref (GTK_OBJECT (embed_obj));
+ if (stream == NULL) {
+ gtk_object_unref (GTK_OBJECT (embeddable));
g_free (bed);
return NULL;
}
- bed->embed_obj = embed_obj;
+ bed->embeddable = embeddable;
/*
* Bind the interfaces
*/
- gnome_object_add_interface (GNOME_OBJECT (embed_obj),
+ gnome_object_add_interface (GNOME_OBJECT (embeddable),
GNOME_OBJECT (stream));
gtk_signal_connect (
- GTK_OBJECT (embed_obj), "destroy",
+ GTK_OBJECT (embeddable), "destroy",
GTK_SIGNAL_FUNC (destroy_embed), bed);
- return (GnomeObject *) embed_obj;
+
+
+ /* Setup some verbs */
+ gnome_embeddable_add_verb (embeddable,
+ "NextPage",
+ _("_Next page"),
+ _("goto the next page"));
+ gnome_embeddable_add_verb (embeddable,
+ "PrevPage",
+ _("_Previous page"),
+ _("goto the previous page"));
+
+ return (GnomeObject *) embeddable;
}
static void
factory = gnome_embeddable_factory_new (
"bonobo-object-factory:image-x-pdf",
- embed_obj_factory, NULL);
+ embeddable_factory, NULL);
}
static void
int
main (int argc, char *argv [])
{
- CORBA_exception_init (&ev);
-
- init_server_factory (argc, argv);
- init_bonobo_image_x_png_factory ();
-
- errorInit();
-
- initParams (xpdfConfigFile); /* Init font path */
-
- gtk_widget_set_default_colormap (gdk_rgb_get_cmap ());
- gtk_widget_set_default_visual (gdk_rgb_get_visual ());
- gtk_main ();
-
- CORBA_exception_free (&ev);
-
- return 0;
+ CORBA_exception_init (&ev);
+
+ init_server_factory (argc, argv);
+ init_bonobo_image_x_png_factory ();
+
+ errorInit();
+
+ initParams (xpdfConfigFile); /* Init font path */
+
+ gtk_widget_set_default_colormap (gdk_rgb_get_cmap ());
+ gtk_widget_set_default_visual (gdk_rgb_get_visual ());
+ gtk_main ();
+
+ CORBA_exception_free (&ev);
+
+ return 0;
}
-
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * test-container.c
+ * PDF viewer Bonobo container.
*
- * A simple program to act as a test container for embeddable
- * components.
+ * Author:
+ * Michael Meeks <michael@imaginator.com>
*
- * Authors:
- * Nat Friedman (nat@gnome-support.com)
- * Miguel de Icaza (miguel@gnu.org)
*/
-
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include "Error.h"
#include "config.h"
-CORBA_Environment ev;
-CORBA_ORB orb;
poptContext ctx;
gint gpdf_debug=1;
{ NULL, '\0', 0, NULL, 0 }
};
-/*
- * A handle to some Embeddables and their ClientSites so we can add
- * views to existing components.
- */
-GnomeObjectClient *text_obj;
-GnomeClientSite *text_client_site;
+typedef struct {
+ GnomeContainer *container;
+ GnomeUIHandler *uih;
-GnomeObjectClient *image_png_obj;
-GnomeClientSite *image_client_site;
+ GnomeViewFrame *active_view_frame;
-/*
- * The currently active view. We keep track of this
- * so we can deactivate it when a new view is activated.
- */
-GnomeViewFrame *active_view_frame;
-
-char *server_goadid = "gnome_xpdf_viewer";
+ GtkWidget *app;
+ GtkWidget *vbox;
+} Container;
typedef struct {
- GtkWidget *app;
- GnomeContainer *container;
- GtkWidget *box;
- GnomeUIHandler *uih;
- gboolean contains_pdf;
-} Application;
-
-/* List of applications */
-GList *apps = NULL;
+ Container *container;
-static Application * application_new (void);
+ GnomeClientSite *client_site;
+ GnomeViewFrame *view_frame;
+ GnomeObjectClient *server;
-static void
-application_destroy (Application *app)
-{
- apps = g_list_remove (apps, app);
- gtk_widget_destroy (app->app);
- g_free (app);
- if (!apps)
- gtk_main_quit ();
-}
+ GtkWidget *views_hbox;
+} Component;
-static void
-applications_destroy ()
-{
- while (apps)
- application_destroy ((Application *)apps->data);
+GList *containers = NULL;
+/*
+ * Static prototypes.
+ */
+extern "C" {
+ static Container *container_new (void);
+ static void container_destroy (Container *cont);
+ static void container_open_cmd (GtkWidget *widget, Container *container);
+ static void container_close_cmd (GtkWidget *widget, Container *container);
+ static void container_exit_cmd (void);
+ static Component *container_activate_component (Container *container, char *component_goad_id);
}
-static GnomeObjectClient *
-launch_server (GnomeClientSite *client_site, GnomeContainer *container, char *goadid)
-{
- GnomeObjectClient *object_server;
-
- gnome_container_add (container, GNOME_OBJECT (client_site));
-
- printf ("Launching...\n");
- object_server = gnome_object_activate_with_goad_id (NULL, goadid, GOAD_ACTIVATE_SHLIB, NULL);
- printf ("Return: %p\n", object_server);
- if (!object_server){
- g_warning (_("Can not activate object_server\n"));
- return NULL;
- }
+/*
+ * The menus.
+ */
+static GnomeUIInfo container_file_menu [] = {
+ GNOMEUIINFO_MENU_OPEN_ITEM (container_open_cmd, NULL),
+ GNOMEUIINFO_SEPARATOR,
+ GNOMEUIINFO_MENU_CLOSE_ITEM(container_close_cmd, NULL),
+ GNOMEUIINFO_SEPARATOR,
+ GNOMEUIINFO_MENU_EXIT_ITEM (container_exit_cmd, NULL),
+ GNOMEUIINFO_END
+};
- if (!gnome_client_site_bind_embeddable (client_site, object_server)){
- g_warning (_("Can not bind object server to client_site\n"));
- return NULL;
- }
+static GnomeUIInfo container_main_menu [] = {
+ GNOMEUIINFO_MENU_FILE_TREE (container_file_menu),
+ GNOMEUIINFO_END
+};
- return object_server;
+extern "C" {
+ static void
+ open_pdf (Container *container, const char *name)
+ {
+ GnomeObjectClient *object;
+ GnomeStream *stream;
+ GNOME_PersistStream persist;
+ Component *comp;
+ CORBA_Environment ev;
+
+ comp = container_activate_component (container, "bonobo-object:image-x-pdf");
+ if (!comp || !(object = comp->server)) {
+ gnome_error_dialog (_("Could not launch bonobo object."));
+ return;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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);
+/* app->contains_pdf = 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 *app)
+ {
+ 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 (app->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] != '/') {
+/* if (app->contains_pdf)
+ app = application_new ();*/
+ char *fname = g_strdup (name);
+ open_pdf (app, 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 (app->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);
+ }
+
+ 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);
+ }
}
-static GnomeObjectClient *
-launch_server_moniker (GnomeClientSite *client_site, GnomeContainer *container, char *moniker)
+static void
+component_add_view (Component *component)
{
- GnomeObjectClient *object_server;
-
- gnome_container_add (container, GNOME_OBJECT (client_site));
+ GnomeViewFrame *view_frame;
+ GtkWidget *view_widget;
- printf ("Launching moniker %s...\n", moniker);
- object_server = gnome_object_activate (moniker, GOAD_ACTIVATE_SHLIB);
- printf ("Return: %p\n", object_server);
- if (!object_server){
- g_warning (_("Can not activate object_server\n"));
- return NULL;
- }
+ /*
+ * Create the remote view and the local ViewFrame.
+ */
+ view_frame = gnome_client_site_embeddable_new_view (component->client_site);
+ component->view_frame = view_frame;
- if (!gnome_client_site_bind_embeddable (client_site, object_server)){
- g_warning (_("Can not bind object server to client_site\n"));
- return NULL;
- }
+ /*
+ * Set the GnomeUIHandler for this ViewFrame. That way, the
+ * embedded component can get access to our UIHandler server
+ * so that it can merge menu and toolbar items when it gets
+ * activated.
+ */
+ gnome_view_frame_set_ui_handler (view_frame, component->container->uih);
- return object_server;
-}
+ /*
+ * Embed the view frame into the application.
+ */
+ view_widget = gnome_view_frame_get_wrapper (view_frame);
+ gtk_box_pack_start (GTK_BOX (component->views_hbox), view_widget,
+ FALSE, FALSE, 5);
-/*
- * This function is called when the user double clicks on a View in
- * order to activate it.
- */
-static gint
-user_activation_request_cb (GnomeViewFrame *view_frame)
-{
/*
- * If there is already an active View, deactivate it.
+ * The "user_activate" signal will be emitted when the user
+ * double clicks on the "cover". The cover is a transparent
+ * window which sits on top of the component and keeps any
+ * events (mouse, keyboard) from reaching it. When the user
+ * double clicks on the cover, the container (that's us)
+ * can choose to activate the component.
*/
- if (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 (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 (active_view_frame != NULL)
- gnome_view_frame_set_covered (active_view_frame, TRUE);
-
- active_view_frame = NULL;
- }
+ gtk_signal_connect (GTK_OBJECT (view_frame), "user_activate",
+ GTK_SIGNAL_FUNC (component_user_activate_request_cb), component);
- /*
- * 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.
+ /*
+ * In-place activation of a component is a two-step process.
+ * After the user double clicks on the component, our signal
+ * callback (compoennt_user_activate_request_cb()) asks the
+ * component to activate itself (see
+ * gnome_view_frame_view_activate()). The component can then
+ * choose to either accept or refuse activation. When an
+ * embedded component notifies us of its decision to change
+ * its activation state, the "view_activated" signal is
+ * emitted from the view frame. It is at that point that we
+ * actually remove the cover so that events can get through.
*/
- gnome_view_frame_view_activate (view_frame);
+ gtk_signal_connect (GTK_OBJECT (view_frame), "view_activated",
+ GTK_SIGNAL_FUNC (component_view_activated_cb), component);
- return FALSE;
-}
+ /*
+ * The "user_context" signal is emitted when the user right
+ * clicks on the wrapper. We use it to pop up a verb menu.
+ */
+ gtk_signal_connect (GTK_OBJECT (view_frame), "user_context",
+ GTK_SIGNAL_FUNC (component_user_context_cb), component);
-/*
- * Gets called when the View notifies the ViewFrame that it would like
- * to be activated or deactivated.
- */
-static gint
-view_activated_cb (GnomeViewFrame *view_frame, gboolean activated)
-{
+ /*
+ * Show the component.
+ */
+ gtk_widget_show_all (view_widget);
+}
- if (activated) {
- /*
- * If the View is requesting to be activated, then we
- * check whether or not there is already an active
- * View.
- */
- if (active_view_frame != NULL) {
- g_warning ("View requested to be activated but there is already "
- "an active View!\n");
- return FALSE;
- }
-
- /*
- * Otherwise, uncover it so that it can receive
- * events, and set it as the active View.
- */
- gnome_view_frame_set_covered (view_frame, FALSE);
- 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 == active_view_frame)
- active_view_frame = NULL;
- }
-
- return FALSE;
-}
-
-static GnomeViewFrame *
-add_view (Application *app,
- GnomeClientSite *client_site, GnomeObjectClient *server)
+static void
+component_new_view_cb (GtkWidget *button, gpointer data)
{
- GnomeViewFrame *view_frame;
- GtkWidget *view_widget;
-
- view_frame = gnome_client_site_embeddable_new_view (client_site);
-
- gtk_signal_connect (GTK_OBJECT (view_frame), "user_activate",
- GTK_SIGNAL_FUNC (user_activation_request_cb), NULL);
- gtk_signal_connect (GTK_OBJECT (view_frame), "view_activated",
- GTK_SIGNAL_FUNC (view_activated_cb), NULL);
+ Component *component = (Component *) data;
- gnome_view_frame_set_ui_handler (view_frame, app->uih);
+ component_add_view (component);
+}
- view_widget = gnome_view_frame_get_wrapper (view_frame);
+static void
+component_load_pf_cb (GtkWidget *button, gpointer data)
+{
+}
- gtk_box_pack_start (GTK_BOX (app->box), view_widget, TRUE, TRUE, 0);
- gtk_widget_show_all (app->box);
+static void
+component_load_ps_cb (GtkWidget *button, gpointer data)
+{
+}
- return view_frame;
-} /* add_view */
+static void
+component_destroy_cb (GtkWidget *button, gpointer data)
+{
+}
static GnomeObjectClient *
-add_cmd (Application *app, char *server_goadid,
- GnomeClientSite **client_site)
+container_launch_component (GnomeClientSite *client_site,
+ GnomeContainer *container,
+ char *component_goad_id)
{
- GnomeObjectClient *server;
-
- *client_site = gnome_client_site_new (app->container);
+ GnomeObjectClient *object_server;
+
+ /*
+ * Launch the component.
+ */
+ object_server = gnome_object_activate_with_goad_id (
+ NULL, component_goad_id, 0, NULL);
+
+ if (object_server == NULL)
+ return NULL;
- server = launch_server (*client_site, app->container, server_goadid);
- if (server == NULL)
+ /*
+ * Bind it to the local ClientSite. Every embedded component
+ * has a local GnomeClientSite object which serves as a
+ * container-side point of contact for the embeddable. The
+ * container talks to the embeddable through its ClientSite
+ */
+ if (!gnome_client_site_bind_embeddable (client_site, object_server)) {
+ gnome_object_unref (GNOME_OBJECT (object_server));
return NULL;
+ }
+
+ /*
+ * The GnomeContainer object maintains a list of the
+ * ClientSites which it manages. Here we add the new
+ * ClientSite to that list.
+ */
+ gnome_container_add (container, GNOME_OBJECT (client_site));
- add_view (app, *client_site, server);
- return server;
+ return object_server;
}
-static void
-open_pdf (Application *app, const char *name)
+/*
+ * Use query_interface to see if `obj' has `interface'.
+ */
+static gboolean
+gnome_object_has_interface (GnomeObject *obj, char *interface)
{
- GnomeObjectClient *object;
- GnomeStream *stream;
- GNOME_PersistStream persist;
-
- object = add_cmd (app, "bonobo-object:image-x-pdf", &image_client_site);
- if (object == NULL) {
- gnome_error_dialog (_("Could not launch bonobo object."));
- return;
- }
+ CORBA_Environment ev;
+ CORBA_Object requested_interface;
- image_png_obj = object;
+ CORBA_exception_init (&ev);
- persist = GNOME_Unknown_query_interface (
- gnome_object_corba_objref (GNOME_OBJECT (object)),
- "IDL:GNOME/PersistStream:1.0", &ev);
+ requested_interface = GNOME_Unknown_query_interface (
+ gnome_object_corba_objref (obj), interface, &ev);
- if (ev._major != CORBA_NO_EXCEPTION ||
- persist == CORBA_OBJECT_NIL) {
- gnome_error_dialog ("Panic: component is well broken.");
- return;
- }
-
- stream = gnome_stream_fs_open (name, GNOME_Storage_READ);
+ CORBA_exception_free (&ev);
- if (stream == NULL) {
- char *err = g_strconcat (_("Could not open "), name, NULL);
- gnome_error_dialog_parented (err, GTK_WINDOW(app->app));
- g_free (err);
- return;
+ if (!CORBA_Object_is_nil(requested_interface, &ev) &&
+ ev._major == CORBA_NO_EXCEPTION)
+ {
+ /* Get rid of the interface we've been passed */
+ CORBA_Object_release (requested_interface, &ev);
+ return TRUE;
}
-
- GNOME_PersistStream_load (persist,
- (GNOME_Stream) gnome_object_corba_objref (GNOME_OBJECT (stream)), &ev);
- GNOME_Unknown_unref (persist, &ev);
- CORBA_Object_release (persist, &ev);
- app->contains_pdf = TRUE;
+ return FALSE;
}
static void
-set_ok (GtkWidget *widget, gboolean *dialog_result)
+container_create_component_frame (Container *container, Component *component, char *name)
{
- *dialog_result = TRUE;
- gtk_main_quit ();
+ /*
+ * This hbox will store all the views of the component.
+ */
+ component->views_hbox = gtk_hbox_new (FALSE, 2);
+
+ gtk_box_pack_start (GTK_BOX (container->vbox), component->views_hbox,
+ TRUE, FALSE, 5);
+ gtk_widget_show_all (component->views_hbox);
}
-static guint
-file_dialog_delete_event (GtkWidget *widget, GdkEventAny *event)
-{
- gtk_main_quit ();
- return TRUE;
+extern "C" {
+ static Component *
+ container_activate_component (Container *container, char *component_goad_id)
+ {
+ Component *component;
+ GnomeClientSite *client_site;
+ GnomeObjectClient *server;
+
+ /*
+ * The ClientSite is the container-side point of contact for
+ * the Embeddable. So there is a one-to-one correspondence
+ * between GnomeClientSites and GnomeEmbeddables. */
+ client_site = gnome_client_site_new (container->container);
+
+ /*
+ * A GnomeObjectClient is a simple wrapper for a remote
+ * GnomeObject (a server supporting GNOME::Unknown).
+ */
+ server = container_launch_component (client_site, container->container,
+ component_goad_id);
+ if (server == NULL) {
+ char *error_msg;
+
+ error_msg = g_strdup_printf (_("Could not launch Embeddable %s!"),
+ component_goad_id);
+ gnome_warning_dialog (error_msg);
+ g_free (error_msg);
+
+ return NULL;
+ }
+
+ /*
+ * Create the internal data structure which we will use to
+ * keep track of this component.
+ */
+ component = g_new0 (Component, 1);
+ component->container = container;
+ component->client_site = client_site;
+ component->server = server;
+
+ /*
+ * Now we have a GnomeEmbeddable bound to our local
+ * ClientSite. Here we create a little on-screen box to store
+ * the embeddable in, when the user adds views for it.
+ */
+ container_create_component_frame (container, component, component_goad_id);
+
+ component_add_view (component);
+
+ return component;
+ }
}
static void
-file_open_cmd (GtkWidget *widget, Application *app)
+container_create_menus (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 (app->app));
+ GnomeUIHandlerMenuItem *menu_list;
- /* 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);
+ gnome_ui_handler_create_menubar (container->uih);
/*
- * Make sure that we quit the main loop if the window is destroyed
+ * Create the basic menus out of UIInfo structures.
*/
- 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] != '/') {
- if (app->contains_pdf)
- app = application_new ();
- char *fname = g_strdup (name);
- open_pdf (app, 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 (app->app));
- gnome_dialog_run (GNOME_DIALOG (dialog));
- }
- }
-
- gtk_widget_destroy (GTK_WIDGET (fsel));
+ menu_list = gnome_ui_handler_menu_parse_uiinfo_list_with_data (container_main_menu, container);
+ gnome_ui_handler_menu_add_list (container->uih, "/", menu_list);
+ gnome_ui_handler_menu_free_list (menu_list);
}
static void
-close_cmd (GtkWidget *widget, Application *app)
+container_create (void)
{
- application_destroy (app);
-}
+ Container *container;
-static void
-exit_cmd (void)
-{
- applications_destroy ();
-}
+ container = g_new0 (Container, 1);
-static GnomeUIInfo container_file_menu [] = {
- GNOMEUIINFO_MENU_OPEN_ITEM (file_open_cmd, NULL),
- GNOMEUIINFO_SEPARATOR,
- GNOMEUIINFO_MENU_CLOSE_ITEM(close_cmd, NULL),
- GNOMEUIINFO_SEPARATOR,
- GNOMEUIINFO_MENU_EXIT_ITEM (exit_cmd, NULL),
- GNOMEUIINFO_END
-};
+ container->app = gnome_app_new ("sample-container",
+ "Sample Bonobo Container");
-static GnomeUIInfo container_main_menu [] = {
- GNOMEUIINFO_MENU_FILE_TREE (container_file_menu),
- GNOMEUIINFO_END
-};
+ gtk_window_set_default_size (GTK_WINDOW (container->app), 400, 400);
+ gtk_window_set_policy (GTK_WINDOW (container->app), TRUE, TRUE, FALSE);
-static Application *
-application_new (void)
-{
- Application *app;
- GnomeUIHandlerMenuItem *menu_list;
+ container->container = gnome_container_new ();
- app = g_new0 (Application, 1);
- app->app = gnome_app_new ("gpdf",
- "GNOME PDF viewer");
- app->container = GNOME_CONTAINER (gnome_container_new ());
- app->contains_pdf = FALSE;
+ /*
+ * This is the VBox we will stuff embedded components into.
+ */
+ container->vbox = gtk_vbox_new (FALSE, 0);
+ gnome_app_set_contents (GNOME_APP (container->app), container->vbox);
- app->box = gtk_vbox_new (FALSE, 0);
- gtk_widget_show (app->box);
- gnome_app_set_contents (GNOME_APP (app->app), app->box);
+ /*
+ * Create the GnomeUIHandler object which will be used to
+ * create the container's menus and toolbars. The UIHandler
+ * also creates a CORBA server which embedded components use
+ * to do menu/toolbar merging.
+ */
+ container->uih = gnome_ui_handler_new ();
+ gnome_ui_handler_set_app (container->uih, GNOME_APP (container->app));
/*
* Create the menus.
*/
- app->uih = gnome_ui_handler_new ();
-
- gnome_ui_handler_set_app (app->uih, GNOME_APP (app->app));
- gnome_ui_handler_create_menubar (app->uih);
-
- menu_list = gnome_ui_handler_menu_parse_uiinfo_list_with_data (container_main_menu, app);
- gnome_ui_handler_menu_add_list (app->uih, "/", menu_list);
- gnome_ui_handler_menu_free_list (menu_list);
-
-/* gnome_ui_handler_create_toolbar (app->uih, "Common");
- gnome_ui_handler_toolbar_new_item (app->uih,
- "/Common/item 1",
- "Container-added Item 1", "I am the container. Hear me roar.",
- 0, GNOME_UI_HANDLER_PIXMAP_NONE, NULL, 0, 0,
- NULL, NULL);*/
-
- gtk_widget_show (app->app);
-
- apps = g_list_append (apps, app);
- return app;
+ container_create_menus (container);
+
+ gtk_widget_show_all (container->app);
}
int
-main (int argc, char *argv [])
+main (int argc, char **argv)
{
- Application *app;
- char **view_files = NULL;
+ CORBA_Environment ev;
+ CORBA_ORB orb;
- if (argc != 1){
- server_goadid = argv [1];
- }
-
CORBA_exception_init (&ev);
-
- gnome_CORBA_init_with_popt_table ("PDFViewer", "0.0.1",
- &argc, argv,
- gpdf_popt_options, 0, &ctx,
- GNORBA_INIT_SERVER_FUNC, &ev);
- orb = gnome_CORBA_ORB ();
-
- if (bonobo_init (orb, NULL, NULL) == FALSE)
- g_error (_("Can not bonobo_init\n"));
- app = application_new ();
+ gnome_CORBA_init ("gnome_xpdf_viewer", "0.1", &argc, argv, 0, &ev);
- view_files = poptGetArgs (ctx);
+ CORBA_exception_free (&ev);
- /* Load files */
- if (view_files) {
- int i;
- for (i = 0; view_files[i]; i++) {
- if (app->contains_pdf)
- app = application_new ();
- open_pdf (app, view_files[i]);
- }
- }
+ orb = gnome_CORBA_ORB ();
+
+ if (bonobo_init (orb, NULL, NULL) == FALSE)
+ g_error (_("Could not initialize Bonobo!\n"));
- poptFreeContext (ctx);
+ container_create ();
gtk_main ();
- CORBA_exception_free (&ev);
-
return 0;
}