#include "config.h"
poptContext ctx;
-gint gpdf_debug=1;
+gint gpdf_debug=0;
const struct poptOption gpdf_popt_options [] = {
{ "debug", '\0', POPT_ARG_INT, &gpdf_debug, 0,
{ NULL, '\0', 0, NULL, 0 }
};
-typedef struct {
- GnomeContainer *container;
- GnomeUIHandler *uih;
-
- GnomeViewFrame *active_view_frame;
-
- GtkWidget *app;
- GtkWidget *vbox;
-} Container;
+typedef struct _Component Component;
+typedef struct _Container Container;
+/* NB. there is a 1 to 1 Container -> Component mapping, this
+ is due to how much MDI sucks; unutterably */
+struct _Container {
+ GnomeContainer *container;
+ GnomeUIHandler *uih;
+
+ GnomeViewFrame *active_view_frame;
+
+ GtkWidget *app;
+ GtkScrolledWindow *scroll;
+ GtkWidget *view_widget;
+ Component *component;
+ gdouble zoom;
+};
-typedef struct {
+struct _Component {
Container *container;
GnomeClientSite *client_site;
GnomeViewFrame *view_frame;
GnomeObjectClient *server;
-
- GtkWidget *views_hbox;
-} Component;
+};
GList *containers = NULL;
/*
* Static prototypes.
*/
extern "C" {
- static Container *container_new (void);
+ static Container *container_new (const char *fname);
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 void container_about_cmd (GtkWidget *widget, Container *container);
static Component *container_activate_component (Container *container, char *component_goad_id);
+ static void zoom_in_cmd (GtkWidget *widget, Container *container);
+ static void zoom_out_cmd (GtkWidget *widget, Container *container);
+ static void zoom_set (Container *container);
}
/*
GNOMEUIINFO_END
};
+static GnomeUIInfo container_menu_zoom [] = {
+ { GNOME_APP_UI_ITEM, N_("_Zoom in"),
+ N_("Increase the size of objects in the PDF"),
+ zoom_in_cmd },
+ { GNOME_APP_UI_ITEM, N_("_Zoom out"),
+ N_("Decrease the size of objects in the PDF"),
+ zoom_out_cmd },
+ GNOMEUIINFO_END
+};
+
+static GnomeUIInfo container_help_menu [] = {
+ GNOMEUIINFO_MENU_ABOUT_ITEM(container_about_cmd, NULL),
+ GNOMEUIINFO_END
+};
+
static GnomeUIInfo container_main_menu [] = {
GNOMEUIINFO_MENU_FILE_TREE (container_file_menu),
+ { GNOME_APP_UI_SUBTREE, N_("_Zoom"), NULL, container_menu_zoom },
+ GNOMEUIINFO_MENU_HELP_TREE (container_help_menu),
+ GNOMEUIINFO_END
+};
+
+static GnomeUIInfo container_toolbar [] = {
+ GNOMEUIINFO_ITEM_STOCK (
+ N_("Open"), N_("Opens an existing workbook"),
+ container_open_cmd, GNOME_STOCK_PIXMAP_OPEN),
+
+ GNOMEUIINFO_SEPARATOR,
GNOMEUIINFO_END
};
extern "C" {
- static void
+ static gboolean
open_pdf (Container *container, const char *name)
{
GnomeObjectClient *object;
Component *comp;
CORBA_Environment ev;
- comp = container_activate_component (container, "bonobo-object:image-x-pdf");
+ 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:application-x-pdf");
if (!comp || !(object = comp->server)) {
gnome_error_dialog (_("Could not launch bonobo object."));
- return;
+ return FALSE;
}
CORBA_exception_init (&ev);
if (ev._major != CORBA_NO_EXCEPTION ||
persist == CORBA_OBJECT_NIL) {
gnome_error_dialog ("Panic: component is well broken.");
- return;
+ return FALSE;
}
stream = gnome_stream_fs_open (name, GNOME_Storage_READ);
char *err = g_strconcat (_("Could not open "), name, NULL);
gnome_error_dialog_parented (err, GTK_WINDOW(container->app));
g_free (err);
- return;
+ return FALSE;
}
GNOME_PersistStream_load (persist,
(GNOME_Stream) gnome_object_corba_objref (GNOME_OBJECT (stream)), &ev);
-
+
+ zoom_set (container);
+
GNOME_Unknown_unref (persist, &ev);
CORBA_Object_release (persist, &ev);
CORBA_exception_free (&ev);
-/* app->contains_pdf = TRUE; */
+ return TRUE;
}
static void
}
static void
- container_open_cmd (GtkWidget *widget, Container *app)
+ container_open_cmd (GtkWidget *widget, Container *container)
{
GtkFileSelection *fsel;
gboolean accepted = FALSE;
gtk_window_set_modal (GTK_WINDOW (fsel), TRUE);
gtk_window_set_transient_for (GTK_WINDOW (fsel),
- GTK_WINDOW (app->app));
+ GTK_WINDOW (container->app));
/* Connect the signals for Ok and Cancel */
gtk_signal_connect (GTK_OBJECT (fsel->ok_button), "clicked",
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);
+ if (container->view_widget) /* any sort of MDI sucks :-] */
+ container = container_new (fname);
+ else {
+ if (!open_pdf (container, fname))
+ container_destroy (container);
+ }
g_free (fname);
} else {
GtkWidget *dialog;
GNOME_MESSAGE_BOX_ERROR,
GNOME_STOCK_BUTTON_OK, NULL);
gnome_dialog_set_parent (GNOME_DIALOG (dialog),
- GTK_WINDOW (app->app));
+ GTK_WINDOW (container->app));
gnome_dialog_run (GNOME_DIALOG (dialog));
}
}
container_destroy (Container *cont)
{
containers = g_list_remove (containers, cont);
- gtk_widget_destroy (cont->app);
+ if (cont->app)
+ gtk_widget_destroy (cont->app);
+ cont->app = NULL;
+ /* FIXME: Some serious resource freeing needs to be here */
+
g_free (cont);
if (!containers)
gtk_main_quit ();
container_destroy ((Container *)containers->data);
}
+
+static void
+container_about_cmd (GtkWidget *widget, Container *container)
+{
+ GtkWidget *about;
+ int i;
+
+ const gchar *authors[] = {
+ N_("Michael Meeks, GNOME port maintainer."),
+ N_("Miguel de Icaza."),
+ N_("Nat Friedman."),
+ NULL
+ };
+
+#ifdef ENABLE_NLS
+ for (i = 0; authors[i] != NULL; i++)
+ authors [i] = _(authors [i]);
+#endif
+
+ about = gnome_about_new (_("GPDF"), VERSION,
+ _("(C) 1996-1999 Derek B. Noonburg."),
+ authors, NULL, NULL);
+
+ gnome_dialog_set_parent (GNOME_DIALOG (about), GTK_WINDOW (container->app));
+ gnome_dialog_set_close (GNOME_DIALOG (about), TRUE);
+ gtk_widget_show (about);
+}
+
+ /*
+ * Enforces the containers zoom factor.
+ */
static void
- component_user_activate_request_cb (GnomeViewFrame *view_frame, gpointer data)
+ zoom_set (Container *container)
{
- 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);
+ 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
- component_view_activated_cb (GnomeViewFrame *view_frame, gboolean activated, gpointer data)
+ zoom_in_cmd (GtkWidget *widget, Container *container)
{
- 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;
- }
+ g_return_if_fail (container != NULL);
+ if (container->zoom < 180.0) {
+ container->zoom *= 1.4;
+ zoom_set (container);
+ }
}
-
+
static void
- component_user_context_cb (GnomeViewFrame *view_frame, gpointer data)
+ zoom_out_cmd (GtkWidget *widget, Container *container)
{
- 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);
+ g_return_if_fail (container != NULL);
+ if (container->zoom > 10.0) {
+ container->zoom /= 1.4;
+ zoom_set (container);
+ }
}
}
static void
-component_add_view (Component *component)
+container_set_view (Container *container, Component *component)
{
GnomeViewFrame *view_frame;
GtkWidget *view_widget;
/*
* Create the remote view and the local ViewFrame.
*/
- view_frame = gnome_client_site_embeddable_new_view (component->client_site);
+ view_frame = gnome_client_site_new_view (component->client_site);
component->view_frame = view_frame;
/*
* so that it can merge menu and toolbar items when it gets
* activated.
*/
- gnome_view_frame_set_ui_handler (view_frame, component->container->uih);
+ gnome_view_frame_set_ui_handler (view_frame, container->uih);
/*
* 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);
-
- /*
- * 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.
- */
- gtk_signal_connect (GTK_OBJECT (view_frame), "user_activate",
- GTK_SIGNAL_FUNC (component_user_activate_request_cb), component);
+ container->view_widget = view_widget;
+ container->component = component;
/*
- * 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.
- */
- gtk_signal_connect (GTK_OBJECT (view_frame), "view_activated",
- GTK_SIGNAL_FUNC (component_view_activated_cb), component);
-
- /*
- * The "user_context" signal is emitted when the user right
- * clicks on the wrapper. We use it to pop up a verb menu.
+ * Show the component.
*/
- gtk_signal_connect (GTK_OBJECT (view_frame), "user_context",
- GTK_SIGNAL_FUNC (component_user_context_cb), component);
+ gtk_scrolled_window_add_with_viewport (container->scroll, view_widget);
/*
- * Show the component.
+ * Activate it ( get it to merge menus etc. )
*/
- gtk_widget_show_all (view_widget);
-}
-
-static void
-component_new_view_cb (GtkWidget *button, gpointer data)
-{
- Component *component = (Component *) data;
+ gnome_view_frame_view_activate (view_frame);
- component_add_view (component);
-}
-
-static void
-component_load_pf_cb (GtkWidget *button, gpointer data)
-{
-}
-
-static void
-component_load_ps_cb (GtkWidget *button, gpointer data)
-{
-}
-
-static void
-component_destroy_cb (GtkWidget *button, gpointer data)
-{
+ gtk_widget_show_all (GTK_WIDGET (container->scroll));
}
static GnomeObjectClient *
* Launch the component.
*/
object_server = gnome_object_activate_with_goad_id (
- NULL, component_goad_id, 0, NULL);
+ NULL, component_goad_id, GOAD_ACTIVATE_SHLIB, NULL);
if (object_server == NULL)
return NULL;
return FALSE;
}
-static void
-container_create_component_frame (Container *container, Component *component, char *name)
-{
- /*
- * 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);
-}
-
extern "C" {
static Component *
container_activate_component (Container *container, char *component_goad_id)
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);
+ container_set_view (container, component);
return component;
}
+
+ static void
+ filenames_dropped (GtkWidget * widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time,
+ Container *container)
+ {
+ GList *names, *tmp_list;
+
+ names = gnome_uri_list_extract_filenames ((char *)selection_data->data);
+ tmp_list = names;
+
+ while (tmp_list) {
+ const char *fname = (const char *)tmp_list->data;
+
+ if (fname) {
+ if (container->view_widget)
+ container = container_new (fname);
+ else
+ open_pdf (container, fname);
+ }
+
+ tmp_list = g_list_next (tmp_list);
+ }
+ }
}
static void
}
static void
-container_create (void)
+container_create_toolbar (Container *container)
{
- Container *container;
+ GnomeUIHandlerToolbarItem *toolbar;
+
+ gnome_ui_handler_create_toolbar (container->uih, "pdf");
+ toolbar = gnome_ui_handler_toolbar_parse_uiinfo_list_with_data (container_toolbar, container);
+ gnome_ui_handler_toolbar_add_list (container->uih, "/", toolbar);
+ gnome_ui_handler_toolbar_free_list (toolbar);
+}
+static Container *
+container_new (const char *fname)
+{
+ Container *container;
+ static GtkTargetEntry drag_types[] =
+ {
+ { "text/uri-list", 0, 0 },
+ };
+ static gint n_drag_types = sizeof (drag_types) / sizeof (drag_types [0]);
+
container = g_new0 (Container, 1);
- container->app = gnome_app_new ("sample-container",
- "Sample Bonobo Container");
+ container->app = gnome_app_new ("pdf-viewer",
+ "GNOME PDF viewer");
+ container->zoom = 86.0;
- gtk_window_set_default_size (GTK_WINDOW (container->app), 400, 400);
- gtk_window_set_policy (GTK_WINDOW (container->app), TRUE, TRUE, FALSE);
+ gtk_drag_dest_set (container->app,
+ GTK_DEST_DEFAULT_ALL,
+ drag_types, n_drag_types,
+ GDK_ACTION_COPY);
- container->container = gnome_container_new ();
+ gtk_signal_connect (GTK_OBJECT(container->app),
+ "drag_data_received",
+ GTK_SIGNAL_FUNC(filenames_dropped), (gpointer)container);
- /*
- * 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);
+ gtk_window_set_default_size (GTK_WINDOW (container->app), 600, 600);
+ gtk_window_set_policy (GTK_WINDOW (container->app), TRUE, TRUE, FALSE);
+
+ container->container = gnome_container_new ();
+ container->view_widget = NULL;
+ container->scroll = GTK_SCROLLED_WINDOW (gtk_scrolled_window_new (NULL, NULL));
+ gtk_scrolled_window_set_policy (container->scroll, GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gnome_app_set_contents (GNOME_APP (container->app), GTK_WIDGET (container->scroll));
/*
* Create the GnomeUIHandler object which will be used to
container->uih = gnome_ui_handler_new ();
gnome_ui_handler_set_app (container->uih, GNOME_APP (container->app));
- /*
- * Create the menus.
- */
- container_create_menus (container);
-
+ container_create_menus (container);
+ container_create_toolbar (container);
+
+ gtk_widget_show_all (container->app);
+
+ if (fname)
+ if (!open_pdf (container, fname)) {
+ container_destroy (container);
+ return NULL;
+ }
+
+ containers = g_list_append (containers, container);
+
gtk_widget_show_all (container->app);
+
+ return container;
}
int
main (int argc, char **argv)
{
- CORBA_Environment ev;
- CORBA_ORB orb;
-
- CORBA_exception_init (&ev);
-
- gnome_CORBA_init ("gnome_xpdf_viewer", "0.1", &argc, argv, 0, &ev);
+ CORBA_Environment ev;
+ CORBA_ORB orb;
+ char **view_files = NULL;
+ gboolean loaded;
+ int i;
+
+ 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);
- CORBA_exception_free (&ev);
+ CORBA_exception_free (&ev);
- orb = gnome_CORBA_ORB ();
+ orb = gnome_CORBA_ORB ();
- if (bonobo_init (orb, NULL, NULL) == FALSE)
- g_error (_("Could not initialize Bonobo!\n"));
+ if (bonobo_init (orb, NULL, NULL) == FALSE)
+ g_error (_("Could not initialize Bonobo!\n"));
+ bonobo_activate ();
- container_create ();
+ view_files = poptGetArgs (ctx);
- gtk_main ();
+ /* Load files */
+ i = 0;
+ loaded = FALSE;
+ if (view_files) {
+ for (i = 0; view_files[i]; i++)
+ if (container_new (view_files[i]))
+ loaded = TRUE;
+ }
+ if ((i == 0) || !loaded)
+ container_new (NULL);
+
+ poptFreeContext (ctx);
- return 0;
+ gtk_main ();
+
+ return 0;
}