Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarlos Garcia Campos <carlosgc@gnome.org>2007-07-08 20:09:36 (GMT)
committer Carlos Garcia Campos <carlosgc@src.gnome.org>2007-07-08 20:09:36 (GMT)
commit6426ce3672bf190ab39d9c49c841232c127d174f (patch)
tree74ae4a68b2a5d1cd559b2c7c77a58f9820fa6abf
parent080921f46c2e66ee230dd5781794638219557349 (diff)
Merge evince-forms branch.
2007-07-08 Carlos Garcia Campos <carlosgc@gnome.org> * configure.ac: * backend/pdf/ev-poppler.cc: (pdf_document_get_crop_box), (ev_form_field_from_poppler_field), (pdf_document_forms_get_form_fields), (pdf_document_forms_form_field_text_get_text), (pdf_document_forms_form_field_text_set_text), (pdf_document_forms_form_field_button_set_state), (pdf_document_forms_form_field_button_get_state), (pdf_document_forms_form_field_choice_get_item), (pdf_document_forms_form_field_choice_get_n_items), (pdf_document_forms_form_field_choice_is_item_selected), (pdf_document_forms_form_field_choice_select_item), (pdf_document_forms_form_field_choice_toggle_item), (pdf_document_forms_form_field_choice_unselect_all), (pdf_document_forms_form_field_choice_set_text), (pdf_document_forms_form_field_choice_get_text), (pdf_document_document_forms_iface_init): * libdocument/Makefile.am: * libdocument/ev-form-field.[ch]: * libdocument/ev-document-forms.[ch]: * shell/ev-pixbuf-cache.[ch]: (dispose_cache_job_info), (move_one_job), (copy_job_to_job_info), (add_job_if_needed), (add_job), (ev_pixbuf_cache_reload_page), (ev_pixbuf_cache_get_form_field_mapping): * shell/ev-jobs.[ch]: (ev_job_render_new), (ev_job_render_run): * shell/ev-view-private.h: * shell/ev-view.[ch]: (ev_view_set_scroll_adjustments), (ev_view_handle_cursor_over_xy), (ev_view_get_form_field_at_location), (ev_view_forms_remove_widgets), (ev_view_form_field_destroy), (ev_view_form_field_button_create_widget), (ev_view_form_field_text_save), (ev_view_form_field_text_changed), (ev_view_form_field_text_create_widget), (ev_view_form_field_choice_save), (ev_view_form_field_choice_changed), (ev_view_form_field_choice_create_widget), (ev_view_handle_form_field), (ev_view_size_allocate), (ev_view_realize), (draw_end_presentation_page), (ev_view_button_press_event), (ev_view_remove_all), (ev_view_motion_notify_event), (ev_view_key_press_event), (ev_view_enter_notify_event), (highlight_find_results), (draw_loading_text), (draw_one_page), (ev_view_destroy), (ev_view_class_init), (page_changed_cb), (on_adjustment_value_changed), (ev_view_set_presentation), (merge_selection_region), (ev_view_set_cursor), (ev_view_reset_presentation_state): Merge evince-forms branch. svn path=/trunk/; revision=2560
-rw-r--r--ChangeLog53
-rw-r--r--backend/pdf/ev-poppler.cc400
-rw-r--r--configure.ac3
-rw-r--r--libdocument/Makefile.am4
-rw-r--r--libdocument/ev-document-forms.c165
-rw-r--r--libdocument/ev-document-forms.h121
-rw-r--r--libdocument/ev-document.c3
-rw-r--r--libdocument/ev-document.h2
-rw-r--r--libdocument/ev-form-field.c269
-rw-r--r--libdocument/ev-form-field.h230
-rw-r--r--shell/ev-jobs.c8
-rw-r--r--shell/ev-jobs.h3
-rw-r--r--shell/ev-pixbuf-cache.c115
-rw-r--r--shell/ev-pixbuf-cache.h7
-rw-r--r--shell/ev-view-private.h8
-rw-r--r--shell/ev-view.c649
-rw-r--r--shell/ev-view.h1
17 files changed, 1957 insertions, 84 deletions
diff --git a/ChangeLog b/ChangeLog
index 7fd60bd..9fc7297 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,54 @@
+2007-07-08 Carlos Garcia Campos <carlosgc@gnome.org>
+
+ * configure.ac:
+ * backend/pdf/ev-poppler.cc: (pdf_document_get_crop_box),
+ (ev_form_field_from_poppler_field),
+ (pdf_document_forms_get_form_fields),
+ (pdf_document_forms_form_field_text_get_text),
+ (pdf_document_forms_form_field_text_set_text),
+ (pdf_document_forms_form_field_button_set_state),
+ (pdf_document_forms_form_field_button_get_state),
+ (pdf_document_forms_form_field_choice_get_item),
+ (pdf_document_forms_form_field_choice_get_n_items),
+ (pdf_document_forms_form_field_choice_is_item_selected),
+ (pdf_document_forms_form_field_choice_select_item),
+ (pdf_document_forms_form_field_choice_toggle_item),
+ (pdf_document_forms_form_field_choice_unselect_all),
+ (pdf_document_forms_form_field_choice_set_text),
+ (pdf_document_forms_form_field_choice_get_text),
+ (pdf_document_document_forms_iface_init):
+ * libdocument/Makefile.am:
+ * libdocument/ev-form-field.[ch]:
+ * libdocument/ev-document-forms.[ch]:
+ * shell/ev-pixbuf-cache.[ch]: (dispose_cache_job_info),
+ (move_one_job), (copy_job_to_job_info), (add_job_if_needed),
+ (add_job), (ev_pixbuf_cache_reload_page),
+ (ev_pixbuf_cache_get_form_field_mapping):
+ * shell/ev-jobs.[ch]: (ev_job_render_new), (ev_job_render_run):
+ * shell/ev-view-private.h:
+ * shell/ev-view.[ch]: (ev_view_set_scroll_adjustments),
+ (ev_view_handle_cursor_over_xy),
+ (ev_view_get_form_field_at_location),
+ (ev_view_forms_remove_widgets), (ev_view_form_field_destroy),
+ (ev_view_form_field_button_create_widget),
+ (ev_view_form_field_text_save), (ev_view_form_field_text_changed),
+ (ev_view_form_field_text_create_widget),
+ (ev_view_form_field_choice_save),
+ (ev_view_form_field_choice_changed),
+ (ev_view_form_field_choice_create_widget),
+ (ev_view_handle_form_field), (ev_view_size_allocate),
+ (ev_view_realize), (draw_end_presentation_page),
+ (ev_view_button_press_event), (ev_view_remove_all),
+ (ev_view_motion_notify_event), (ev_view_key_press_event),
+ (ev_view_enter_notify_event), (highlight_find_results),
+ (draw_loading_text), (draw_one_page), (ev_view_destroy),
+ (ev_view_class_init), (page_changed_cb),
+ (on_adjustment_value_changed), (ev_view_set_presentation),
+ (merge_selection_region), (ev_view_set_cursor),
+ (ev_view_reset_presentation_state):
+
+ Merge evince-forms branch.
+
2007-07-03 Jaap Haitsma <jaap@haitsma.org>
* cut-n-paste/toolbar-editor/update-toolbareditor-from-libegg: removed
@@ -16,7 +67,7 @@
Adds a nice icon to page action during toolbar editing.
See bug #452872.
-2007-07-02 Nickolay V. Shmyrev <nshmyrev@yandex.ru
+2007-07-02 Nickolay V. Shmyrev <nshmyrev@yandex.ru>
* data/evince-toolbar.xml:
* shell/ev-window.c:
diff --git a/backend/pdf/ev-poppler.cc b/backend/pdf/ev-poppler.cc
index 5cdedde..3b3fe2b 100644
--- a/backend/pdf/ev-poppler.cc
+++ b/backend/pdf/ev-poppler.cc
@@ -19,6 +19,10 @@
#include "config.h"
+#ifdef HAVE_POPPLER_FORM_FIELD_BUTTON_GET_BUTTON_TYPE
+#define HAVE_FORMS
+#endif
+
#include <math.h>
#include <string.h>
#include <gtk/gtk.h>
@@ -40,6 +44,7 @@
#include "ev-document-security.h"
#include "ev-document-thumbnails.h"
#include "ev-document-transition.h"
+#include "ev-document-forms.h"
#include "ev-selection.h"
#include "ev-attachment.h"
#include "ev-image.h"
@@ -86,6 +91,7 @@ static void pdf_document_security_iface_init (EvDocumentSecurityIface
static void pdf_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface);
static void pdf_document_document_links_iface_init (EvDocumentLinksIface *iface);
static void pdf_document_document_images_iface_init (EvDocumentImagesIface *iface);
+static void pdf_document_document_forms_iface_init (EvDocumentFormsIface *iface);
static void pdf_document_document_fonts_iface_init (EvDocumentFontsIface *iface);
static void pdf_document_find_iface_init (EvDocumentFindIface *iface);
static void pdf_document_file_exporter_iface_init (EvFileExporterIface *iface);
@@ -104,7 +110,6 @@ static EvLink *ev_link_from_action (PdfDocument *pdf_document,
static void pdf_document_search_free (PdfDocumentSearch *search);
static void pdf_print_context_free (PdfPrintContext *ctx);
-
G_DEFINE_TYPE_WITH_CODE (PdfDocument, pdf_document, G_TYPE_OBJECT,
{
G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT,
@@ -117,6 +122,10 @@ G_DEFINE_TYPE_WITH_CODE (PdfDocument, pdf_document, G_TYPE_OBJECT,
pdf_document_document_links_iface_init);
G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_IMAGES,
pdf_document_document_images_iface_init);
+#ifdef HAVE_FORMS
+ G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FORMS,
+ pdf_document_document_forms_iface_init);
+#endif /* HAVE_FORMS */
G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FONTS,
pdf_document_document_fonts_iface_init);
G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FIND,
@@ -1775,3 +1784,392 @@ pdf_document_new (void)
{
return PDF_DOCUMENT (g_object_new (PDF_TYPE_DOCUMENT, NULL));
}
+
+/* Forms */
+static void
+pdf_document_get_crop_box (EvDocument *document,
+ int page,
+ EvRectangle *rect)
+{
+ PdfDocument *pdf_document;
+ PopplerPage *poppler_page;
+ PopplerRectangle poppler_rect;
+
+ pdf_document = PDF_DOCUMENT (document);
+ poppler_page = poppler_document_get_page (pdf_document->document, page);
+ poppler_page_get_crop_box (poppler_page, &poppler_rect);
+ rect->x1 = poppler_rect.x1;
+ rect->x2 = poppler_rect.x2;
+ rect->y1 = poppler_rect.y1;
+ rect->y2 = poppler_rect.y2;
+}
+
+#ifdef HAVE_FORMS
+static EvFormField *
+ev_form_field_from_poppler_field (PopplerFormField *poppler_field)
+{
+ EvFormField *ev_field = NULL;
+ gint id;
+ gdouble font_size;
+ gboolean is_read_only;
+
+ id = poppler_form_field_get_id (poppler_field);
+ font_size = poppler_form_field_get_font_size (poppler_field);
+ is_read_only = poppler_form_field_is_read_only (poppler_field);
+
+ switch (poppler_form_field_get_field_type (poppler_field)) {
+ case POPPLER_FORM_FIELD_TEXT: {
+ EvFormFieldText *field_text;
+ EvFormFieldTextType ev_text_type = EV_FORM_FIELD_TEXT_NORMAL;
+
+ switch (poppler_form_field_text_get_text_type (poppler_field)) {
+ case POPPLER_FORM_TEXT_NORMAL:
+ ev_text_type = EV_FORM_FIELD_TEXT_NORMAL;
+ break;
+ case POPPLER_FORM_TEXT_MULTILINE:
+ ev_text_type = EV_FORM_FIELD_TEXT_MULTILINE;
+ break;
+ case POPPLER_FORM_TEXT_PASSWORD:
+ ev_text_type = EV_FORM_FIELD_TEXT_PASSWORD;
+ break;
+ case POPPLER_FORM_TEXT_FILE_SELECT:
+ ev_text_type = EV_FORM_FIELD_TEXT_FILE_SELECT;
+ break;
+ }
+
+ ev_field = ev_form_field_text_new (id, ev_text_type);
+ field_text = EV_FORM_FIELD_TEXT (ev_field);
+
+ field_text->do_spell_check = poppler_form_field_text_do_spell_check (poppler_field);
+ field_text->do_scroll = poppler_form_field_text_do_scroll (poppler_field);
+ field_text->is_rich_text = poppler_form_field_text_is_rich_text (poppler_field);
+
+ field_text->text = poppler_form_field_text_get_text (poppler_field);
+
+ }
+ break;
+ case POPPLER_FORM_FIELD_BUTTON: {
+ EvFormFieldButton *field_button;
+ EvFormFieldButtonType ev_button_type = EV_FORM_FIELD_BUTTON_PUSH;
+
+ switch (poppler_form_field_button_get_button_type (poppler_field)) {
+ case POPPLER_FORM_BUTTON_PUSH:
+ ev_button_type = EV_FORM_FIELD_BUTTON_PUSH;
+ break;
+ case POPPLER_FORM_BUTTON_CHECK:
+ ev_button_type = EV_FORM_FIELD_BUTTON_CHECK;
+ break;
+ case POPPLER_FORM_BUTTON_RADIO:
+ ev_button_type = EV_FORM_FIELD_BUTTON_RADIO;
+ break;
+ }
+
+ ev_field = ev_form_field_button_new (id, ev_button_type);
+ field_button = EV_FORM_FIELD_BUTTON (ev_field);
+
+ field_button->state = poppler_form_field_button_get_state (poppler_field);
+ }
+ break;
+ case POPPLER_FORM_FIELD_CHOICE: {
+ EvFormFieldChoice *field_choice;
+ EvFormFieldChoiceType ev_choice_type = EV_FORM_FIELD_CHOICE_COMBO;
+
+ switch (poppler_form_field_choice_get_choice_type (poppler_field)) {
+ case POPPLER_FORM_CHOICE_COMBO:
+ ev_choice_type = EV_FORM_FIELD_CHOICE_COMBO;
+ break;
+ case EV_FORM_FIELD_CHOICE_LIST:
+ ev_choice_type = EV_FORM_FIELD_CHOICE_LIST;
+ break;
+ }
+
+ ev_field = ev_form_field_choice_new (id, ev_choice_type);
+ field_choice = EV_FORM_FIELD_CHOICE (ev_field);
+
+ field_choice->is_editable = poppler_form_field_choice_is_editable (poppler_field);
+ field_choice->multi_select = poppler_form_field_choice_can_select_multiple (poppler_field);
+ field_choice->do_spell_check = poppler_form_field_choice_do_spell_check (poppler_field);
+ field_choice->commit_on_sel_change = poppler_form_field_choice_commit_on_change (poppler_field);
+
+ /* TODO: we need poppler_form_field_choice_get_selected_items in poppler
+ field_choice->selected_items = poppler_form_field_choice_get_selected_items (poppler_field);*/
+ if (field_choice->is_editable)
+ field_choice->text = poppler_form_field_choice_get_text (poppler_field);
+ }
+ break;
+ case POPPLER_FORM_FIELD_SIGNATURE:
+ /* TODO */
+ ev_field = ev_form_field_signature_new (id);
+ break;
+ case POPPLER_FORM_FIELD_UNKNOWN:
+ break;
+ }
+
+ ev_field->font_size = font_size;
+ ev_field->is_read_only = is_read_only;
+
+ return ev_field;
+}
+
+static GList *
+pdf_document_forms_get_form_fields (EvDocumentForms *document,
+ gint page)
+{
+ PdfDocument *pdf_document;
+ PopplerPage *poppler_page;
+ GList *retval = NULL;
+ GList *fields;
+ GList *list;
+ double height;
+
+
+ pdf_document = PDF_DOCUMENT (document);
+ poppler_page = poppler_document_get_page (pdf_document->document, page);
+ fields = poppler_page_get_form_field_mapping (poppler_page);
+ poppler_page_get_size (poppler_page, NULL, &height);
+
+ for (list = fields; list; list = list->next) {
+ PopplerFormFieldMapping *mapping;
+ EvFormFieldMapping *field_mapping;
+
+ mapping = (PopplerFormFieldMapping *)list->data;
+
+ field_mapping = g_new0 (EvFormFieldMapping, 1);
+ field_mapping->x1 = mapping->area.x1;
+ field_mapping->x2 = mapping->area.x2;
+ field_mapping->y1 = height - mapping->area.y2;
+ field_mapping->y2 = height - mapping->area.y1;
+ field_mapping->field = ev_form_field_from_poppler_field (mapping->field);
+ field_mapping->field->page = page;
+
+ retval = g_list_prepend (retval, field_mapping);
+ }
+ poppler_page_free_form_field_mapping (fields);
+ g_object_unref (poppler_page);
+
+ return g_list_reverse (retval);
+}
+
+static gchar *
+pdf_document_forms_form_field_text_get_text (EvDocumentForms *document,
+ EvFormField *field)
+
+{
+ PdfDocument *pdf_document = PDF_DOCUMENT (document);
+ PopplerFormField *poppler_field;
+ gchar *text;
+
+ poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
+ if (!poppler_field)
+ return NULL;
+
+ text = poppler_form_field_text_get_text (poppler_field);
+ g_object_unref (poppler_field);
+
+ return text;
+}
+
+static void
+pdf_document_forms_form_field_text_set_text (EvDocumentForms *document,
+ EvFormField *field,
+ const gchar *text)
+{
+ PdfDocument *pdf_document = PDF_DOCUMENT (document);
+ PopplerFormField *poppler_field;
+
+ poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
+ if (!poppler_field)
+ return;
+ poppler_form_field_text_set_text (poppler_field, text);
+ g_object_unref (poppler_field);
+}
+
+static void
+pdf_document_forms_form_field_button_set_state (EvDocumentForms *document,
+ EvFormField *field,
+ gboolean state)
+{
+ PdfDocument *pdf_document = PDF_DOCUMENT (document);
+ PopplerFormField *poppler_field;
+
+ poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
+ if (!poppler_field)
+ return;
+
+ poppler_form_field_button_set_state (poppler_field, state);
+ g_object_unref (poppler_field);
+}
+
+static gboolean
+pdf_document_forms_form_field_button_get_state (EvDocumentForms *document,
+ EvFormField *field)
+{
+ PdfDocument *pdf_document = PDF_DOCUMENT (document);
+ PopplerFormField *poppler_field;
+ gboolean state;
+
+ poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
+ if (!poppler_field)
+ return FALSE;
+
+ state = poppler_form_field_button_get_state (poppler_field);
+ g_object_unref (poppler_field);
+
+ return state;
+}
+
+static gchar *
+pdf_document_forms_form_field_choice_get_item (EvDocumentForms *document,
+ EvFormField *field,
+ gint index)
+{
+ PdfDocument *pdf_document = PDF_DOCUMENT (document);
+ PopplerFormField *poppler_field;
+ gchar *text;
+
+ poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
+ if (!poppler_field)
+ return NULL;
+
+ text = poppler_form_field_choice_get_item (poppler_field, index);
+ g_object_unref (poppler_field);
+
+ return text;
+}
+
+static int
+pdf_document_forms_form_field_choice_get_n_items (EvDocumentForms *document,
+ EvFormField *field)
+{
+ PdfDocument *pdf_document = PDF_DOCUMENT (document);
+ PopplerFormField *poppler_field;
+ gint n_items;
+
+ poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
+ if (!poppler_field)
+ return -1;
+
+ n_items = poppler_form_field_choice_get_n_items (poppler_field);
+ g_object_unref (poppler_field);
+
+ return n_items;
+}
+
+static gboolean
+pdf_document_forms_form_field_choice_is_item_selected (EvDocumentForms *document,
+ EvFormField *field,
+ gint index)
+{
+ PdfDocument *pdf_document = PDF_DOCUMENT (document);
+ PopplerFormField *poppler_field;
+ gboolean selected;
+
+ poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
+ if (!poppler_field)
+ return FALSE;
+
+ selected = poppler_form_field_choice_is_item_selected (poppler_field, index);
+ g_object_unref (poppler_field);
+
+ return selected;
+}
+
+static void
+pdf_document_forms_form_field_choice_select_item (EvDocumentForms *document,
+ EvFormField *field,
+ gint index)
+{
+ PdfDocument *pdf_document = PDF_DOCUMENT (document);
+ PopplerFormField *poppler_field;
+
+ poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
+ if (!poppler_field)
+ return;
+
+ poppler_form_field_choice_select_item (poppler_field, index);
+ g_object_unref (poppler_field);
+}
+
+static void
+pdf_document_forms_form_field_choice_toggle_item (EvDocumentForms *document,
+ EvFormField *field,
+ gint index)
+{
+ PdfDocument *pdf_document = PDF_DOCUMENT (document);
+ PopplerFormField *poppler_field;
+
+ poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
+ if (!poppler_field)
+ return;
+
+ poppler_form_field_choice_toggle_item (poppler_field, index);
+ g_object_unref (poppler_field);
+}
+
+static void
+pdf_document_forms_form_field_choice_unselect_all (EvDocumentForms *document,
+ EvFormField *field)
+{
+ PdfDocument *pdf_document = PDF_DOCUMENT (document);
+ PopplerFormField *poppler_field;
+
+ poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
+ if (!poppler_field)
+ return;
+
+ poppler_form_field_choice_unselect_all (poppler_field);
+ g_object_unref (poppler_field);
+}
+
+static void
+pdf_document_forms_form_field_choice_set_text (EvDocumentForms *document,
+ EvFormField *field,
+ const gchar *text)
+{
+ PdfDocument *pdf_document = PDF_DOCUMENT (document);
+ PopplerFormField *poppler_field;
+
+ poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
+ if (!poppler_field)
+ return;
+
+ poppler_form_field_choice_set_text (poppler_field, text);
+ g_object_unref (poppler_field);
+}
+
+static gchar *
+pdf_document_forms_form_field_choice_get_text (EvDocumentForms *document,
+ EvFormField *field)
+{
+ PdfDocument *pdf_document = PDF_DOCUMENT (document);
+ PopplerFormField *poppler_field;
+ gchar *text;
+
+ poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
+ if (!poppler_field)
+ return NULL;
+
+ text = poppler_form_field_choice_get_text (poppler_field);
+ g_object_unref (poppler_field);
+
+ return text;
+}
+
+static void
+pdf_document_document_forms_iface_init (EvDocumentFormsIface *iface)
+{
+ iface->get_form_fields = pdf_document_forms_get_form_fields;
+ iface->form_field_text_get_text = pdf_document_forms_form_field_text_get_text;
+ iface->form_field_text_set_text = pdf_document_forms_form_field_text_set_text;
+ iface->form_field_button_set_state = pdf_document_forms_form_field_button_set_state;
+ iface->form_field_button_get_state = pdf_document_forms_form_field_button_get_state;
+ iface->form_field_choice_get_item = pdf_document_forms_form_field_choice_get_item;
+ iface->form_field_choice_get_n_items = pdf_document_forms_form_field_choice_get_n_items;
+ iface->form_field_choice_is_item_selected = pdf_document_forms_form_field_choice_is_item_selected;
+ iface->form_field_choice_select_item = pdf_document_forms_form_field_choice_select_item;
+ iface->form_field_choice_toggle_item = pdf_document_forms_form_field_choice_toggle_item;
+ iface->form_field_choice_unselect_all = pdf_document_forms_form_field_choice_unselect_all;
+ iface->form_field_choice_set_text = pdf_document_forms_form_field_choice_set_text;
+ iface->form_field_choice_get_text = pdf_document_forms_form_field_choice_get_text;
+}
+#endif /* HAVE_FORMS */
diff --git a/configure.ac b/configure.ac
index 0846107..0a0e97a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -247,6 +247,9 @@ if test "x$enable_pdf" = "xyes"; then
evince_save_LIBS=$LIBS
LIBS="$LIBS $FRONTEND_LIBS"
AC_CHECK_FUNCS(poppler_page_render)
+ dnl we need latest poppler cvs head,
+ dnl this function was the last to be added
+ AC_CHECK_FUNCS(poppler_form_field_button_get_button_type)
LIBS=$evince_save_LIBS
PKG_CHECK_MODULES(CAIRO_PDF, cairo-pdf, enable_cairo_pdf=yes, enable_cairo_pdf=no)
diff --git a/libdocument/Makefile.am b/libdocument/Makefile.am
index 73340ff..f96d019 100644
--- a/libdocument/Makefile.am
+++ b/libdocument/Makefile.am
@@ -48,6 +48,10 @@ libevbackend_la_SOURCES= \
ev-document-info.h \
ev-document-transition.h \
ev-document-transition.c \
+ ev-document-forms.h \
+ ev-document-forms.c \
+ ev-form-field.h \
+ ev-form-field.c \
ev-file-exporter.c \
ev-file-exporter.h \
ev-file-helpers.c \
diff --git a/libdocument/ev-document-forms.c b/libdocument/ev-document-forms.c
new file mode 100644
index 0000000..cdefb46
--- /dev/null
+++ b/libdocument/ev-document-forms.c
@@ -0,0 +1,165 @@
+/* ev-document-forms.c
+ * this file is part of evince, a gnome document viewer
+ *
+ * Copyright (C) 2007 Carlos Garcia Campos <carlosgc@gnome.org>
+ *
+ * Evince is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Evince is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "ev-document-forms.h"
+
+GType
+ev_document_forms_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ const GTypeInfo our_info = {
+ sizeof (EvDocumentFormsIface),
+ NULL,
+ NULL,
+ };
+
+ type = g_type_register_static (G_TYPE_INTERFACE,
+ "EvDocumentForms",
+ &our_info, (GTypeFlags)0);
+ }
+
+ return type;
+}
+
+GList *
+ev_document_forms_get_form_fields (EvDocumentForms *document_forms,
+ gint page)
+{
+ EvDocumentFormsIface *iface = EV_DOCUMENT_FORMS_GET_IFACE (document_forms);
+
+ return iface->get_form_fields (document_forms, page);
+}
+
+gchar *
+ev_document_forms_form_field_text_get_text (EvDocumentForms *document_forms,
+ EvFormField *field)
+{
+ EvDocumentFormsIface *iface = EV_DOCUMENT_FORMS_GET_IFACE (document_forms);
+
+ return iface->form_field_text_get_text (document_forms, field);
+}
+
+void
+ev_document_forms_form_field_text_set_text (EvDocumentForms *document_forms,
+ EvFormField *field,
+ const gchar *text)
+{
+ EvDocumentFormsIface *iface = EV_DOCUMENT_FORMS_GET_IFACE (document_forms);
+
+ iface->form_field_text_set_text (document_forms, field, text);
+}
+
+gboolean
+ev_document_forms_form_field_button_get_state (EvDocumentForms *document_forms,
+ EvFormField *field)
+{
+ EvDocumentFormsIface *iface = EV_DOCUMENT_FORMS_GET_IFACE (document_forms);
+
+ return iface->form_field_button_get_state (document_forms, field);
+}
+
+void
+ev_document_forms_form_field_button_set_state (EvDocumentForms *document_forms,
+ EvFormField *field,
+ gboolean state)
+{
+ EvDocumentFormsIface *iface = EV_DOCUMENT_FORMS_GET_IFACE (document_forms);
+
+ iface->form_field_button_set_state (document_forms, field, state);
+}
+
+gchar *
+ev_document_forms_form_field_choice_get_item (EvDocumentForms *document_forms,
+ EvFormField *field,
+ gint index)
+{
+ EvDocumentFormsIface *iface = EV_DOCUMENT_FORMS_GET_IFACE (document_forms);
+
+ return iface->form_field_choice_get_item (document_forms, field, index);
+}
+
+gint
+ev_document_forms_form_field_choice_get_n_items (EvDocumentForms *document_forms,
+ EvFormField *field)
+{
+ EvDocumentFormsIface *iface = EV_DOCUMENT_FORMS_GET_IFACE (document_forms);
+
+ return iface->form_field_choice_get_n_items (document_forms, field);
+}
+
+gboolean
+ev_document_forms_form_field_choice_is_item_selected (EvDocumentForms *document_forms,
+ EvFormField *field,
+ gint index)
+{
+ EvDocumentFormsIface *iface = EV_DOCUMENT_FORMS_GET_IFACE (document_forms);
+
+ return iface->form_field_choice_is_item_selected (document_forms, field, index);
+}
+
+void
+ev_document_forms_form_field_choice_select_item (EvDocumentForms *document_forms,
+ EvFormField *field,
+ gint index)
+{
+ EvDocumentFormsIface *iface = EV_DOCUMENT_FORMS_GET_IFACE (document_forms);
+
+ iface->form_field_choice_select_item (document_forms, field, index);
+}
+
+void
+ev_document_forms_form_field_choice_toggle_item (EvDocumentForms *document_forms,
+ EvFormField *field,
+ gint index)
+{
+ EvDocumentFormsIface *iface = EV_DOCUMENT_FORMS_GET_IFACE (document_forms);
+
+ iface->form_field_choice_toggle_item (document_forms, field, index);
+}
+
+void
+ev_document_forms_form_field_choice_unselect_all (EvDocumentForms *document_forms,
+ EvFormField *field)
+{
+ EvDocumentFormsIface *iface = EV_DOCUMENT_FORMS_GET_IFACE (document_forms);
+
+ iface->form_field_choice_unselect_all (document_forms, field);
+}
+
+void
+ev_document_forms_form_field_choice_set_text (EvDocumentForms *document_forms,
+ EvFormField *field,
+ const gchar *text)
+{
+ EvDocumentFormsIface *iface = EV_DOCUMENT_FORMS_GET_IFACE (document_forms);
+
+ iface->form_field_choice_set_text (document_forms, field, text);
+}
+
+gchar *
+ev_document_forms_form_field_choice_get_text (EvDocumentForms *document_forms,
+ EvFormField *field)
+{
+ EvDocumentFormsIface *iface = EV_DOCUMENT_FORMS_GET_IFACE (document_forms);
+
+ return iface->form_field_choice_get_text (document_forms, field);
+}
diff --git a/libdocument/ev-document-forms.h b/libdocument/ev-document-forms.h
new file mode 100644
index 0000000..a1b192d
--- /dev/null
+++ b/libdocument/ev-document-forms.h
@@ -0,0 +1,121 @@
+/* ev-document-forms.h
+ * this file is part of evince, a gnome document viewer
+ *
+ * Copyright (C) 2007 Carlos Garcia Campos <carlosgc@gnome.org>
+ *
+ * Evince is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Evince is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef EV_DOCUMENT_FORMS_H
+#define EV_DOCUMENT_FORMS_H
+
+#include <glib-object.h>
+
+#include "ev-document.h"
+#include "ev-form-field.h"
+
+G_BEGIN_DECLS
+
+#define EV_TYPE_DOCUMENT_FORMS (ev_document_forms_get_type ())
+#define EV_DOCUMENT_FORMS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EV_TYPE_DOCUMENT_FORMS, EvDocumentForms))
+#define EV_DOCUMENT_FORMS_IFACE(k) (G_TYPE_CHECK_CLASS_CAST((k), EV_TYPE_DOCUMENT_FORMS, EvDocumentFormsIface))
+#define EV_IS_DOCUMENT_FORMS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EV_TYPE_DOCUMENT_FORMS))
+#define EV_IS_DOCUMENT_FORMS_IFACE(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EV_TYPE_DOCUMENT_FORMS))
+#define EV_DOCUMENT_FORMS_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), EV_TYPE_DOCUMENT_FORMS, EvDocumentFormsIface))
+
+typedef struct _EvDocumentForms EvDocumentForms;
+typedef struct _EvDocumentFormsIface EvDocumentFormsIface;
+
+struct _EvDocumentFormsIface
+{
+ GTypeInterface base_iface;
+
+ /* Methods */
+ GList *(* get_form_fields) (EvDocumentForms *document_forms,
+ gint page);
+ gchar *(* form_field_text_get_text) (EvDocumentForms *document_forms,
+ EvFormField *field);
+ void (* form_field_text_set_text) (EvDocumentForms *document_forms,
+ EvFormField *field,
+ const gchar *text);
+ gboolean (* form_field_button_get_state) (EvDocumentForms *document_forms,
+ EvFormField *field);
+ void (* form_field_button_set_state) (EvDocumentForms *document_forms,
+ EvFormField *field,
+ gboolean state);
+ gchar *(* form_field_choice_get_item) (EvDocumentForms *document_forms,
+ EvFormField *field,
+ gint index);
+ gint (* form_field_choice_get_n_items) (EvDocumentForms *document_forms,
+ EvFormField *field);
+ gboolean (* form_field_choice_is_item_selected) (EvDocumentForms *document_forms,
+ EvFormField *field,
+ gint index);
+ void (* form_field_choice_select_item) (EvDocumentForms *document_forms,
+ EvFormField *field,
+ gint index);
+ void (* form_field_choice_toggle_item) (EvDocumentForms *document_forms,
+ EvFormField *field,
+ gint index);
+ void (* form_field_choice_unselect_all) (EvDocumentForms *document_forms,
+ EvFormField *field);
+ void (* form_field_choice_set_text) (EvDocumentForms *document_forms,
+ EvFormField *field,
+ const gchar *text);
+ gchar *(* form_field_choice_get_text) (EvDocumentForms *document_forms,
+ EvFormField *field);
+};
+
+GType ev_document_forms_get_type (void) G_GNUC_CONST;
+GList *ev_document_forms_get_form_fields (EvDocumentForms *document_forms,
+ gint page);
+
+gchar *ev_document_forms_form_field_text_get_text (EvDocumentForms *document_forms,
+ EvFormField *field);
+void ev_document_forms_form_field_text_set_text (EvDocumentForms *document_forms,
+ EvFormField *field,
+ const gchar *text);
+
+gboolean ev_document_forms_form_field_button_get_state (EvDocumentForms *document_forms,
+ EvFormField *field);
+void ev_document_forms_form_field_button_set_state (EvDocumentForms *document_forms,
+ EvFormField *field,
+ gboolean state);
+
+gchar *ev_document_forms_form_field_choice_get_item (EvDocumentForms *document_forms,
+ EvFormField *field,
+ gint index);
+gint ev_document_forms_form_field_choice_get_n_items (EvDocumentForms *document_forms,
+ EvFormField *field);
+gboolean ev_document_forms_form_field_choice_is_item_selected (EvDocumentForms *document_forms,
+ EvFormField *field,
+ gint index);
+void ev_document_forms_form_field_choice_select_item (EvDocumentForms *document_forms,
+ EvFormField *field,
+ gint index);
+void ev_document_forms_form_field_choice_toggle_item (EvDocumentForms *document_forms,
+ EvFormField *field,
+ gint index);
+void ev_document_forms_form_field_choice_unselect_all (EvDocumentForms *document_forms,
+ EvFormField *field);
+void ev_document_forms_form_field_choice_set_text (EvDocumentForms *document_forms,
+ EvFormField *field,
+ const gchar *text);
+gchar *ev_document_forms_form_field_choice_get_text (EvDocumentForms *document_forms,
+ EvFormField *field);
+
+G_END_DECLS
+
+#endif /* EV_DOCUMENT_FORMS_H */
diff --git a/libdocument/ev-document.c b/libdocument/ev-document.c
index f22f55f..e0ce69f 100644
--- a/libdocument/ev-document.c
+++ b/libdocument/ev-document.c
@@ -283,3 +283,6 @@ ev_rect_cmp (EvRectangle *a,
(ABS (a->x2 - b->x2) < EPSILON) &&
(ABS (a->y2 - b->y2) < EPSILON));
}
+
+
+
diff --git a/libdocument/ev-document.h b/libdocument/ev-document.h
index ce887fc..e83295f 100644
--- a/libdocument/ev-document.h
+++ b/libdocument/ev-document.h
@@ -134,8 +134,6 @@ cairo_surface_t *ev_document_render (EvDocument *document,
gint ev_rect_cmp (EvRectangle *a,
EvRectangle *b);
-
-
G_END_DECLS
#endif /* EV_DOCUMENT_H */
diff --git a/libdocument/ev-form-field.c b/libdocument/ev-form-field.c
new file mode 100644
index 0000000..b3cc791
--- /dev/null
+++ b/libdocument/ev-form-field.c
@@ -0,0 +1,269 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
+/* this file is part of evince, a gnome document viewer
+ *
+ * Copyright (C) 2007 Carlos Garcia Campos <carlosgc@gnome.org>
+ * Copyright (C) 2006 Julien Rebetez
+ *
+ * Evince is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Evince is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "ev-form-field.h"
+
+static void ev_form_field_init (EvFormField *field);
+static void ev_form_field_class_init (EvFormFieldClass *klass);
+static void ev_form_field_text_init (EvFormFieldText *field_text);
+static void ev_form_field_text_class_init (EvFormFieldTextClass *klass);
+static void ev_form_field_button_init (EvFormFieldButton *field_button);
+static void ev_form_field_button_class_init (EvFormFieldButtonClass *klass);
+static void ev_form_field_choice_init (EvFormFieldChoice *field_choice);
+static void ev_form_field_choice_class_init (EvFormFieldChoiceClass *klass);
+static void ev_form_field_signature_init (EvFormFieldSignature *field_choice);
+static void ev_form_field_signature_class_init (EvFormFieldSignatureClass *klass);
+
+G_DEFINE_ABSTRACT_TYPE (EvFormField, ev_form_field, G_TYPE_OBJECT)
+G_DEFINE_TYPE (EvFormFieldText, ev_form_field_text, EV_TYPE_FORM_FIELD)
+G_DEFINE_TYPE (EvFormFieldButton, ev_form_field_button, EV_TYPE_FORM_FIELD)
+G_DEFINE_TYPE (EvFormFieldChoice, ev_form_field_choice, EV_TYPE_FORM_FIELD)
+G_DEFINE_TYPE (EvFormFieldSignature, ev_form_field_signature, EV_TYPE_FORM_FIELD)
+
+static void
+ev_form_field_init (EvFormField *field)
+{
+ field->page = -1;
+ field->changed = FALSE;
+ field->is_read_only = FALSE;
+}
+
+static void
+ev_form_field_class_init (EvFormFieldClass *klass)
+{
+}
+
+static void
+ev_form_field_text_finalize (GObject *object)
+{
+ EvFormFieldText *field_text = EV_FORM_FIELD_TEXT (object);
+
+ if (field_text->text) {
+ g_free (field_text->text);
+ field_text->text = NULL;
+ }
+
+ (* G_OBJECT_CLASS (ev_form_field_text_parent_class)->finalize) (object);
+}
+
+static void
+ev_form_field_text_init (EvFormFieldText *field_text)
+{
+}
+
+static void
+ev_form_field_text_class_init (EvFormFieldTextClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = ev_form_field_text_finalize;
+}
+
+static void
+ev_form_field_button_init (EvFormFieldButton *field_button)
+{
+}
+
+static void
+ev_form_field_button_class_init (EvFormFieldButtonClass *klass)
+{
+}
+
+static void
+ev_form_field_choice_finalize (GObject *object)
+{
+ EvFormFieldChoice *field_choice = EV_FORM_FIELD_CHOICE (object);
+
+ if (field_choice->selected_items) {
+ g_list_free (field_choice->selected_items);
+ field_choice->selected_items = NULL;
+ }
+
+ if (field_choice->text) {
+ g_free (field_choice->text);
+ field_choice->text = NULL;
+ }
+
+ (* G_OBJECT_CLASS (ev_form_field_choice_parent_class)->finalize) (object);
+}
+
+static void
+ev_form_field_choice_init (EvFormFieldChoice *field_choice)
+{
+}
+
+static void
+ev_form_field_choice_class_init (EvFormFieldChoiceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = ev_form_field_choice_finalize;
+}
+
+static void
+ev_form_field_signature_init (EvFormFieldSignature *field_signature)
+{
+}
+
+static void
+ev_form_field_signature_class_init (EvFormFieldSignatureClass *klass)
+{
+}
+
+EvFormField *
+ev_form_field_text_new (gint id,
+ EvFormFieldTextType type)
+{
+ EvFormField *field;
+
+ g_return_val_if_fail (id >= 0, NULL);
+ g_return_val_if_fail (type >= EV_FORM_FIELD_TEXT_NORMAL &&
+ type <= EV_FORM_FIELD_TEXT_FILE_SELECT, NULL);
+
+ field = EV_FORM_FIELD (g_object_new (EV_TYPE_FORM_FIELD_TEXT, NULL));
+ field->id = id;
+ EV_FORM_FIELD_TEXT (field)->type = type;
+
+ return field;
+}
+
+EvFormField *
+ev_form_field_button_new (gint id,
+ EvFormFieldButtonType type)
+{
+ EvFormField *field;
+
+ g_return_val_if_fail (id >= 0, NULL);
+ g_return_val_if_fail (type >= EV_FORM_FIELD_BUTTON_PUSH &&
+ type <= EV_FORM_FIELD_BUTTON_RADIO, NULL);
+
+ field = EV_FORM_FIELD (g_object_new (EV_TYPE_FORM_FIELD_BUTTON, NULL));
+ field->id = id;
+ EV_FORM_FIELD_BUTTON (field)->type = type;
+
+ return field;
+}
+
+EvFormField *
+ev_form_field_choice_new (gint id,
+ EvFormFieldChoiceType type)
+{
+ EvFormField *field;
+
+ g_return_val_if_fail (id >= 0, NULL);
+ g_return_val_if_fail (type >= EV_FORM_FIELD_CHOICE_COMBO &&
+ type <= EV_FORM_FIELD_CHOICE_LIST, NULL);
+
+ field = EV_FORM_FIELD (g_object_new (EV_TYPE_FORM_FIELD_CHOICE, NULL));
+ field->id = id;
+ EV_FORM_FIELD_CHOICE (field)->type = type;
+
+ return field;
+}
+
+EvFormField *
+ev_form_field_signature_new (gint id)
+{
+ EvFormField *field;
+
+ g_return_val_if_fail (id >= 0, NULL);
+
+ field = EV_FORM_FIELD (g_object_new (EV_TYPE_FORM_FIELD_SIGNATURE, NULL));
+ field->id = id;
+
+ return field;
+}
+
+/* EvFormFieldMapping */
+static void
+ev_form_field_mapping_free_foreach (EvFormFieldMapping *mapping)
+{
+ g_object_unref (mapping->field);
+ g_free (mapping);
+}
+
+void
+ev_form_field_mapping_free (GList *field_mapping)
+{
+ if (!field_mapping)
+ return;
+
+ g_list_foreach (field_mapping, (GFunc)ev_form_field_mapping_free_foreach, NULL);
+ g_list_free (field_mapping);
+}
+
+EvFormField *
+ev_form_field_mapping_find (GList *field_mapping,
+ gdouble x,
+ gdouble y)
+{
+ GList *list;
+
+ for (list = field_mapping; list; list = list->next) {
+ EvFormFieldMapping *mapping = list->data;
+
+ if ((x >= mapping->x1) &&
+ (y >= mapping->y1) &&
+ (x <= mapping->x2) &&
+ (y <= mapping->y2)) {
+ return mapping->field;
+ }
+ }
+
+ return NULL;
+}
+
+void
+ev_form_field_mapping_get_area (GList *field_mapping,
+ EvFormField *field,
+ EvRectangle *area)
+{
+ GList *list;
+
+ for (list = field_mapping; list; list = list->next) {
+ EvFormFieldMapping *mapping = list->data;
+
+ if (mapping->field->id == field->id) {
+ area->x1 = mapping->x1;
+ area->y1 = mapping->y1;
+ area->x2 = mapping->x2;
+ area->y2 = mapping->y2;
+
+ break;
+ }
+ }
+}
+
+EvFormField *
+ev_form_field_mapping_find_by_id (GList *field_mapping,
+ gint id)
+{
+ GList *list;
+
+ for (list = field_mapping; list; list = list->next) {
+ EvFormFieldMapping *mapping = list->data;
+
+ if (id == mapping->field->id)
+ return mapping->field;
+ }
+
+ return NULL;
+}
diff --git a/libdocument/ev-form-field.h b/libdocument/ev-form-field.h
new file mode 100644
index 0000000..1405999
--- /dev/null
+++ b/libdocument/ev-form-field.h
@@ -0,0 +1,230 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
+/* this file is part of evince, a gnome document viewer
+ *
+ * Copyright (C) 2006 Julien Rebetez
+ *
+ * Evince is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Evince is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef EV_FORM_FIELD_H
+#define EV_FORM_FIELD_H
+
+#include <glib-object.h>
+
+#include "ev-document.h"
+
+G_BEGIN_DECLS
+
+#define EV_TYPE_FORM_FIELD (ev_form_field_get_type())
+#define EV_FORM_FIELD(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_FORM_FIELD, EvFormField))
+#define EV_FORM_FIELD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_FORM_FIELD, EvFormFieldClass))
+#define EV_IS_FORM_FIELD(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_FORM_FIELD))
+#define EV_IS_FORM_FIELD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EV_TYPE_FORM_FIELD))
+#define EV_FORM_FIELD_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), EV_TYPE_FORM_FIELD, EvFormFieldClass))
+
+#define EV_TYPE_FORM_FIELD_TEXT (ev_form_field_text_get_type())
+#define EV_FORM_FIELD_TEXT(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_FORM_FIELD_TEXT, EvFormFieldText))
+#define EV_FORM_FIELD_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_FORM_FIELD_TEXT, EvFormFieldTextClass))
+#define EV_IS_FORM_FIELD_TEXT(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_FORM_FIELD_TEXT))
+#define EV_IS_FORM_FIELD_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EV_TYPE_FORM_FIELD_TEXT))
+#define EV_FORM_FIELD_TEXT_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), EV_TYPE_FORM_FIELD_TEXT, EvFormFieldTextClass))
+
+#define EV_TYPE_FORM_FIELD_BUTTON (ev_form_field_button_get_type())
+#define EV_FORM_FIELD_BUTTON(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_FORM_FIELD_BUTTON, EvFormFieldButton))
+#define EV_FORM_FIELD_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_FORM_FIELD_BUTTON, EvFormFieldButtonClass))
+#define EV_IS_FORM_FIELD_BUTTON(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_FORM_FIELD_BUTTON))
+#define EV_IS_FORM_FIELD_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EV_TYPE_FORM_FIELD_BUTTON))
+#define EV_FORM_FIELD_BUTTON_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), EV_TYPE_FORM_FIELD_BUTTON, EvFormFieldButtonClass))
+
+#define EV_TYPE_FORM_FIELD_CHOICE (ev_form_field_choice_get_type())
+#define EV_FORM_FIELD_CHOICE(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_FORM_FIELD_CHOICE, EvFormFieldChoice))
+#define EV_FORM_FIELD_CHOICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_FORM_FIELD_CHOICE, EvFormFieldChoiceClass))
+#define EV_IS_FORM_FIELD_CHOICE(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_FORM_FIELD_CHOICE))
+#define EV_IS_FORM_FIELD_CHOICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EV_TYPE_FORM_FIELD_CHOICE))
+#define EV_FORM_FIELD_CHOICE_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), EV_TYPE_FORM_FIELD_CHOICE, EvFormFieldChoiceClass))
+
+#define EV_TYPE_FORM_FIELD_SIGNATURE (ev_form_field_signature_get_type())
+#define EV_FORM_FIELD_SIGNATURE(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_FORM_FIELD_SIGNATURE, EvFormFieldSignature))
+#define EV_FORM_FIELD_SIGNATURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_FORM_FIELD_SIGNATURE, EvFormFieldSignatureClass))
+#define EV_IS_FORM_FIELD_SIGNATURE(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_FORM_FIELD_SIGNATURE))
+#define EV_IS_FORM_FIELD_SIGNATURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EV_TYPE_FORM_FIELD_SIGNATURE))
+#define EV_FORM_FIELD_SIGNATURE_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), EV_TYPE_FORM_FIELD_SIGNATURE, EvFormFieldSignatureClass))
+
+typedef struct _EvFormField EvFormField;
+typedef struct _EvFormFieldClass EvFormFieldClass;
+
+typedef struct _EvFormFieldText EvFormFieldText;
+typedef struct _EvFormFieldTextClass EvFormFieldTextClass;
+
+typedef struct _EvFormFieldButton EvFormFieldButton;
+typedef struct _EvFormFieldButtonClass EvFormFieldButtonClass;
+
+typedef struct _EvFormFieldChoice EvFormFieldChoice;
+typedef struct _EvFormFieldChoiceClass EvFormFieldChoiceClass;
+
+typedef struct _EvFormFieldSignature EvFormFieldSignature;
+typedef struct _EvFormFieldSignatureClass EvFormFieldSignatureClass;
+
+typedef enum
+{
+ EV_FORM_FIELD_TEXT_NORMAL,
+ EV_FORM_FIELD_TEXT_MULTILINE,
+ EV_FORM_FIELD_TEXT_PASSWORD,
+ EV_FORM_FIELD_TEXT_FILE_SELECT
+} EvFormFieldTextType;
+
+typedef enum
+{
+ EV_FORM_FIELD_BUTTON_PUSH,
+ EV_FORM_FIELD_BUTTON_CHECK,
+ EV_FORM_FIELD_BUTTON_RADIO
+} EvFormFieldButtonType;
+
+typedef enum
+{
+ EV_FORM_FIELD_CHOICE_COMBO,
+ EV_FORM_FIELD_CHOICE_LIST
+} EvFormFieldChoiceType;
+
+struct _EvFormField
+{
+ GObject parent;
+
+ gint id;
+ gboolean is_read_only;
+ gdouble font_size;
+
+ gint page;
+ gboolean changed;
+};
+
+struct _EvFormFieldClass
+{
+ GObjectClass parent_class;
+};
+
+struct _EvFormFieldText
+{
+ EvFormField partent;
+
+ EvFormFieldTextType type;
+
+ gboolean do_spell_check : 1;
+ gboolean do_scroll : 1;
+ gboolean comb : 1;
+ gboolean is_rich_text : 1;
+
+ gint max_len;
+ gchar *text;
+};
+
+struct _EvFormFieldTextClass
+{
+ EvFormFieldClass partent_class;
+};
+
+struct _EvFormFieldButton
+{
+ EvFormField partent;
+
+ EvFormFieldButtonType type;
+
+ gboolean state;
+};
+
+struct _EvFormFieldButtonClass
+{
+ EvFormFieldClass partent_class;
+};
+
+struct _EvFormFieldChoice
+{
+ EvFormField partent;
+
+ EvFormFieldChoiceType type;
+
+ gboolean multi_select : 1;
+ gboolean is_editable : 1;
+ gboolean do_spell_check : 1;
+ gboolean commit_on_sel_change : 1;
+
+ GList *selected_items;
+ gchar *text;
+};
+
+struct _EvFormFieldChoiceClass
+{
+ EvFormFieldClass partent_class;
+};
+
+struct _EvFormFieldSignature
+{
+ EvFormField partent;
+
+ /* TODO */
+};
+
+struct _EvFormFieldSignatureClass
+{
+ EvFormFieldClass partent_class;
+};
+
+/* EvFormField base class */
+GType ev_form_field_get_type (void) G_GNUC_CONST;
+
+/* EvFormFieldText */
+GType ev_form_field_text_get_type (void) G_GNUC_CONST;
+EvFormField *ev_form_field_text_new (gint id,
+ EvFormFieldTextType type);
+
+/* EvFormFieldButton */
+GType ev_form_field_button_get_type (void) G_GNUC_CONST;
+EvFormField *ev_form_field_button_new (gint id,
+ EvFormFieldButtonType type);
+
+/* EvFormFieldChoice */
+GType ev_form_field_choice_get_type (void) G_GNUC_CONST;
+EvFormField *ev_form_field_choice_new (gint id,
+ EvFormFieldChoiceType type);
+
+/* EvFormFieldSignature */
+GType ev_form_field_signature_get_type (void) G_GNUC_CONST;
+EvFormField *ev_form_field_signature_new (gint id);
+
+
+/* FormField Mapping stuff */
+typedef struct _EvFormFieldMapping EvFormFieldMapping;
+struct _EvFormFieldMapping {
+ EvFormField *field;
+ gdouble x1;
+ gdouble y1;
+ gdouble x2;
+ gdouble y2;
+};
+
+void ev_form_field_mapping_free (GList *field_mapping);
+EvFormField *ev_form_field_mapping_find (GList *field_mapping,
+ gdouble x,
+ gdouble y);
+void ev_form_field_mapping_get_area (GList *field_mapping,
+ EvFormField *field,
+ EvRectangle *area);
+EvFormField *ev_form_field_mapping_find_by_id (GList *form_field_mapping,
+ gint id);
+
+G_END_DECLS
+
+#endif /* !EV_FORM_FIELD_H */
+
diff --git a/shell/ev-jobs.c b/shell/ev-jobs.c
index d9cdac8..0f0a0da 100644
--- a/shell/ev-jobs.c
+++ b/shell/ev-jobs.c
@@ -3,6 +3,7 @@
#include "ev-document-thumbnails.h"
#include "ev-document-links.h"
#include "ev-document-images.h"
+#include "ev-document-forms.h"
#include "ev-document-factory.h"
#include "ev-document-misc.h"
#include "ev-file-helpers.h"
@@ -265,6 +266,7 @@ ev_job_render_new (EvDocument *document,
EvRectangle *selection_points,
GdkColor *text,
GdkColor *base,
+ gboolean include_forms,
gboolean include_links,
gboolean include_images,
gboolean include_text,
@@ -284,6 +286,7 @@ ev_job_render_new (EvDocument *document,
job->target_height = height;
job->text = *text;
job->base = *base;
+ job->include_forms = include_forms;
job->include_links = include_links;
job->include_images = include_images;
job->include_text = include_text;
@@ -330,6 +333,7 @@ ev_job_render_run (EvJobRender *job)
ev_document_fc_mutex_lock ();
job->surface = ev_document_render (EV_JOB (job)->document, job->rc);
+
if (job->include_links && EV_IS_DOCUMENT_LINKS (EV_JOB (job)->document))
job->link_mapping =
ev_document_links_get_links (EV_DOCUMENT_LINKS (EV_JOB (job)->document),
@@ -338,6 +342,10 @@ ev_job_render_run (EvJobRender *job)
job->image_mapping =
ev_document_images_get_images (EV_DOCUMENT_IMAGES (EV_JOB (job)->document),
job->rc->page);
+ if (job->include_forms && EV_IS_DOCUMENT_FORMS (EV_JOB (job)->document))
+ job->form_field_mapping =
+ ev_document_forms_get_form_fields (EV_DOCUMENT_FORMS (EV_JOB(job)->document),
+ job->rc->page);
if (job->include_text && EV_IS_SELECTION (EV_JOB (job)->document))
job->text_mapping =
ev_selection_get_selection_map (EV_SELECTION (EV_JOB (job)->document),
diff --git a/shell/ev-jobs.h b/shell/ev-jobs.h
index fc681d3..0523198 100644
--- a/shell/ev-jobs.h
+++ b/shell/ev-jobs.h
@@ -126,6 +126,7 @@ struct _EvJobRender
GList *link_mapping;
GdkRegion *text_mapping;
GList *image_mapping;
+ GList *form_field_mapping;
cairo_surface_t *selection;
GdkRegion *selection_region;
@@ -133,6 +134,7 @@ struct _EvJobRender
GdkColor base;
GdkColor text;
+ gint include_forms : 1;
gint include_links : 1;
gint include_text : 1;
gint include_selection : 1;
@@ -223,6 +225,7 @@ EvJob *ev_job_render_new (EvDocument *document,
EvRectangle *selection_points,
GdkColor *text,
GdkColor *base,
+ gboolean include_forms,
gboolean include_links,
gboolean include_images,
gboolean include_text,
diff --git a/shell/ev-pixbuf-cache.c b/shell/ev-pixbuf-cache.c
index 20446b1..6cc0580 100644
--- a/shell/ev-pixbuf-cache.c
+++ b/shell/ev-pixbuf-cache.c
@@ -4,6 +4,7 @@
#include "ev-selection.h"
#include "ev-document-images.h"
#include "ev-image.h"
+#include "ev-form-field.h"
typedef struct _CacheJobInfo
{
@@ -14,6 +15,7 @@ typedef struct _CacheJobInfo
cairo_surface_t *surface;
GList *link_mapping;
GList *image_mapping;
+ GList *form_field_mapping;
GdkRegion *text_mapping;
/* Selection data.
@@ -161,6 +163,10 @@ dispose_cache_job_info (CacheJobInfo *job_info,
ev_image_mapping_free (job_info->image_mapping);
job_info->image_mapping = NULL;
}
+ if (job_info->form_field_mapping) {
+ ev_form_field_mapping_free (job_info->form_field_mapping);
+ job_info->form_field_mapping = NULL;
+ }
if (job_info->text_mapping) {
gdk_region_destroy (job_info->text_mapping);
job_info->text_mapping = NULL;
@@ -323,6 +329,7 @@ move_one_job (CacheJobInfo *job_info,
job_info->surface = NULL;
job_info->link_mapping = NULL;
job_info->image_mapping = NULL;
+ job_info->form_field_mapping = NULL;
if (new_priority != priority && target_page->job) {
ev_job_queue_update_job (target_page->job, new_priority);
@@ -432,6 +439,12 @@ copy_job_to_job_info (EvJobRender *job_render,
job_info->image_mapping = job_render->image_mapping;
}
+ if (job_render->include_forms) {
+ if (job_info->form_field_mapping)
+ ev_form_field_mapping_free (job_info->form_field_mapping);
+ job_info->form_field_mapping = job_render->form_field_mapping;
+ }
+
if (job_render->include_text) {
if (job_info->text_mapping)
gdk_region_destroy (job_info->text_mapping);
@@ -540,6 +553,7 @@ add_job_if_needed (EvPixbufCache *pixbuf_cache,
gfloat scale,
EvJobPriority priority)
{
+ gboolean include_forms = FALSE;
gboolean include_links = FALSE;
gboolean include_text = FALSE;
gboolean include_selection = FALSE;
@@ -572,6 +586,8 @@ add_job_if_needed (EvPixbufCache *pixbuf_cache,
include_links = TRUE;
if (job_info->image_mapping == NULL)
include_images = TRUE;
+ if (job_info->form_field_mapping == NULL)
+ include_forms = TRUE;
if (job_info->text_mapping == NULL)
include_text = TRUE;
if (new_selection_surface_needed (pixbuf_cache, job_info, page, scale)) {
@@ -587,6 +603,7 @@ add_job_if_needed (EvPixbufCache *pixbuf_cache,
width, height,
&(job_info->target_points),
text, base,
+ include_forms,
include_links,
include_images,
include_text,
@@ -1102,3 +1119,101 @@ ev_pixbuf_cache_get_selection_list (EvPixbufCache *pixbuf_cache)
return retval;
}
+static void add_job (EvPixbufCache *pixbuf_cache,
+ CacheJobInfo *job_info,
+ EvPageCache *page_cache,
+ gint page,
+ gint rotation,
+ gfloat scale,
+ EvJobPriority priority,
+ int width,
+ int height)
+{
+ gboolean include_links = FALSE;
+ gboolean include_text = FALSE;
+ gboolean include_selection = FALSE;
+ gboolean include_images = TRUE;
+ gboolean include_forms = FALSE;
+ GdkColor *text, *base;
+
+
+ if (job_info->rc == NULL) {
+ job_info->rc = ev_render_context_new (rotation, page, scale);
+ } else {
+ ev_render_context_set_rotation (job_info->rc, rotation);
+ ev_render_context_set_page (job_info->rc, page);
+ ev_render_context_set_scale (job_info->rc, scale);
+ }
+
+ /* Figure out what else we need for this job */
+ if (job_info->link_mapping == NULL)
+ include_links = TRUE;
+ if (job_info->image_mapping == NULL)
+ include_images = TRUE;
+ if (job_info->form_field_mapping == NULL)
+ include_forms = TRUE;
+ if (job_info->text_mapping == NULL)
+ include_text = TRUE;
+ if (new_selection_surface_needed (pixbuf_cache, job_info, page, scale)) {
+ include_selection = TRUE;
+ }
+
+ gtk_widget_ensure_style (pixbuf_cache->view);
+
+ get_selection_colors (pixbuf_cache->view, &text, &base);
+
+ job_info->job = ev_job_render_new (pixbuf_cache->document,
+ job_info->rc,
+ width, height,
+ &(job_info->target_points),
+ text, base,
+ include_forms,
+ include_links,
+ include_images,
+ include_text,
+ include_selection);
+ ev_job_queue_add_job (job_info->job, priority);
+ g_signal_connect (job_info->job, "finished", G_CALLBACK (job_finished_cb), pixbuf_cache);
+
+}
+
+void
+ev_pixbuf_cache_reload_page (EvPixbufCache *pixbuf_cache,
+ gint page,
+ gint rotation,
+ gfloat scale)
+{
+ CacheJobInfo *job_info;
+ EvPageCache *page_cache;
+ int width, height;
+
+ if(page < pixbuf_cache->start_page || page > pixbuf_cache->end_page)
+ return;
+ page_cache = ev_page_cache_get (pixbuf_cache->document);
+ ev_page_cache_get_size (page_cache, page, rotation, scale, &width, &height);
+ job_info = pixbuf_cache->job_list + (page - pixbuf_cache->start_page);
+
+ //dispose_cache_job_info (job_info, pixbuf_cache);
+
+ add_job(pixbuf_cache, job_info, page_cache, page, rotation, scale, EV_JOB_PRIORITY_HIGH, width, height);
+
+
+}
+
+GList *
+ev_pixbuf_cache_get_form_field_mapping (EvPixbufCache *pixbuf_cache,
+ gint page)
+{
+ CacheJobInfo *job_info;
+
+ job_info = find_job_cache (pixbuf_cache, page);
+ if(job_info == NULL)
+ return NULL;
+
+ if(job_info->job &&
+ EV_JOB(job_info->job)->finished) {
+ copy_job_to_job_info (EV_JOB_RENDER(job_info->job), job_info, pixbuf_cache);
+ }
+ return job_info->form_field_mapping;
+}
+
diff --git a/shell/ev-pixbuf-cache.h b/shell/ev-pixbuf-cache.h
index 79e0810..a8ff30a 100644
--- a/shell/ev-pixbuf-cache.h
+++ b/shell/ev-pixbuf-cache.h
@@ -65,9 +65,14 @@ GList *ev_pixbuf_cache_get_image_mapping (EvPixbufCache *pixbuf_cache
gint page);
GdkRegion *ev_pixbuf_cache_get_text_mapping (EvPixbufCache *pixbuf_cache,
gint page);
+GList *ev_pixbuf_cache_get_form_field_mapping (EvPixbufCache *pixbuf_cache,
+ gint page);
void ev_pixbuf_cache_clear (EvPixbufCache *pixbuf_cache);
void ev_pixbuf_cache_style_changed (EvPixbufCache *pixbuf_cache);
-
+void ev_pixbuf_cache_reload_page (EvPixbufCache *pixbuf_cache,
+ gint page,
+ gint rotation,
+ gfloat scale);
/* Selection */
cairo_surface_t *ev_pixbuf_cache_get_selection_surface (EvPixbufCache *pixbuf_cache,
gint page,
diff --git a/shell/ev-view-private.h b/shell/ev-view-private.h
index cab0941..4908711 100644
--- a/shell/ev-view-private.h
+++ b/shell/ev-view-private.h
@@ -25,6 +25,7 @@
#include "ev-pixbuf-cache.h"
#include "ev-page-cache.h"
#include "ev-image.h"
+#include "ev-form-field.h"
/* Information for middle clicking and moving around the doc */
typedef struct {
@@ -73,7 +74,7 @@ typedef enum {
} EvPresentationState;
struct _EvView {
- GtkWidget parent_instance;
+ GtkLayout layout;
EvDocument *document;
@@ -152,11 +153,8 @@ struct _EvView {
};
struct _EvViewClass {
- GtkWidgetClass parent_class;
+ GtkLayoutClass parent_class;
- void (*set_scroll_adjustments) (EvView *view,
- GtkAdjustment *hadjustment,
- GtkAdjustment *vadjustment);
void (*binding_activated) (EvView *view,
EvScrollType scroll,
gboolean horizontal);
diff --git a/shell/ev-view.c b/shell/ev-view.c
index 0869472..468a894 100644
--- a/shell/ev-view.c
+++ b/shell/ev-view.c
@@ -37,6 +37,7 @@
#include "ev-document-images.h"
#include "ev-document-find.h"
#include "ev-document-transition.h"
+#include "ev-document-forms.h"
#include "ev-document-misc.h"
#include "ev-job-queue.h"
#include "ev-page-cache.h"
@@ -115,7 +116,7 @@ typedef enum {
/*** Scrolling ***/
static void scroll_to_current_page (EvView *view,
GtkOrientation orientation);
-static void ev_view_set_scroll_adjustments (EvView *view,
+static void ev_view_set_scroll_adjustments (GtkLayout *layout,
GtkAdjustment *hadjustment,
GtkAdjustment *vadjustment);
static void view_update_range_and_current_page (EvView *view);
@@ -157,19 +158,21 @@ static void find_page_at_location (EvView
gint *page,
gint *x_offset,
gint *y_offset);
-static gboolean doc_point_to_view_point (EvView *view,
- int page,
- EvPoint *doc_point,
- GdkPoint *view_point);
+static gboolean doc_point_to_view_point (EvView *view,
+ int page,
+ EvPoint *doc_point,
+ GdkPoint *view_point);
/*** Hyperrefs ***/
-static EvLink * ev_view_get_link_at_location (EvView *view,
- gdouble x,
- gdouble y);
+static EvLink * ev_view_get_link_at_location (EvView *view,
+ gdouble x,
+ gdouble y);
static char* tip_from_link (EvView *view,
EvLink *link);
-static void handle_link_over_xy (EvView *view,
- gint x,
- gint y);
+/*** Forms ***/
+static EvFormField *ev_view_get_form_field_at_location (EvView *view,
+ gdouble x,
+ gdouble y);
+
/*** GtkWidget implementation ***/
static void ev_view_size_request_continuous_dual_page (EvView *view,
GtkRequisition *requisition);
@@ -201,6 +204,7 @@ static gboolean ev_view_leave_notify_event (GtkWidget
GdkEventCrossing *event);
static void ev_view_style_set (GtkWidget *widget,
GtkStyle *old_style);
+static void ev_view_remove_all (EvView *view);
static AtkObject *ev_view_get_accessible (GtkWidget *widget);
@@ -292,6 +296,9 @@ static void ev_view_zoom_for_size_single_page (EvView *view,
static GdkCursor* ev_view_create_invisible_cursor (void);
static void ev_view_set_cursor (EvView *view,
EvViewCursor new_cursor);
+static void ev_view_handle_cursor_over_xy (EvView *view,
+ gint x,
+ gint y);
/*** Status messages ***/
static void ev_view_set_status (EvView *view,
@@ -326,7 +333,7 @@ static void ev_view_presentation_transition_start (EvView
static void ev_view_presentation_transition_stop (EvView *ev_view);
-G_DEFINE_TYPE (EvView, ev_view, GTK_TYPE_WIDGET)
+G_DEFINE_TYPE (EvView, ev_view, GTK_TYPE_LAYOUT)
static void
scroll_to_current_page (EvView *view, GtkOrientation orientation)
@@ -554,13 +561,15 @@ set_scroll_adjustment (EvView *view,
}
static void
-ev_view_set_scroll_adjustments (EvView *view,
+ev_view_set_scroll_adjustments (GtkLayout *layout,
GtkAdjustment *hadjustment,
GtkAdjustment *vadjustment)
{
+ EvView *view = EV_VIEW (layout);
+
set_scroll_adjustment (view, GTK_ORIENTATION_HORIZONTAL, hadjustment);
set_scroll_adjustment (view, GTK_ORIENTATION_VERTICAL, vadjustment);
-
+
on_adjustment_value_changed (NULL, view);
}
@@ -1481,7 +1490,7 @@ tip_from_link (EvView *view, EvLink *link)
}
static void
-handle_link_over_xy (EvView *view, gint x, gint y)
+ev_view_handle_cursor_over_xy (EvView *view, gint x, gint y)
{
EvLink *link;
@@ -1511,6 +1520,8 @@ handle_link_over_xy (EvView *view, gint x, gint y)
ev_view_set_cursor (view, EV_VIEW_CURSOR_LINK);
} else if (location_in_text (view, x + view->scroll_x, y + view->scroll_y)) {
ev_view_set_cursor (view, EV_VIEW_CURSOR_IBEAM);
+ } else if (ev_view_get_form_field_at_location (view, x, y)) {
+ ev_view_set_cursor (view, EV_VIEW_CURSOR_LINK);
} else {
ev_view_set_status (view, NULL);
if (view->cursor == EV_VIEW_CURSOR_LINK ||
@@ -1553,6 +1564,440 @@ ev_view_get_image_at_location (EvView *view,
return NULL;
}
+/*** Forms ***/
+static EvFormField *
+ev_view_get_form_field_at_location (EvView *view,
+ gdouble x,
+ gdouble y)
+{
+ gint page = -1;
+ gint x_offset = 0, y_offset = 0;
+ gint x_new = 0, y_new = 0;
+ GList *forms_mapping;
+
+ if (!EV_IS_DOCUMENT_FORMS (view->document))
+ return NULL;
+
+ x += view->scroll_x;
+ y += view->scroll_y;
+
+ find_page_at_location (view, x, y, &page, &x_offset, &y_offset);
+
+ if (page == -1)
+ return NULL;
+
+ if (get_doc_point_from_offset (view, page, x_offset,
+ y_offset, &x_new, &y_new) == FALSE)
+ return NULL;
+
+ forms_mapping = ev_pixbuf_cache_get_form_field_mapping (view->pixbuf_cache, page);
+
+ if (forms_mapping)
+ return ev_form_field_mapping_find (forms_mapping, x_new, y_new);
+ else
+ return NULL;
+}
+
+static gboolean
+ev_view_forms_remove_widgets (EvView *view)
+{
+ ev_view_remove_all (view);
+
+ return FALSE;
+}
+
+static void
+ev_view_form_field_destroy (GtkWidget *widget,
+ EvView *view)
+{
+ g_idle_add ((GSourceFunc)ev_view_forms_remove_widgets, view);
+}
+
+static GtkWidget *
+ev_view_form_field_button_create_widget (EvView *view,
+ EvFormField *field)
+{
+ EvFormFieldButton *field_button = EV_FORM_FIELD_BUTTON (field);
+
+ switch (field_button->type) {
+ case EV_FORM_FIELD_BUTTON_PUSH:
+ break;
+ case EV_FORM_FIELD_BUTTON_CHECK:
+ case EV_FORM_FIELD_BUTTON_RADIO: {
+ gboolean state;
+
+ state = ev_document_forms_form_field_button_get_state (EV_DOCUMENT_FORMS (view->document),
+ field);
+ ev_document_forms_form_field_button_set_state (EV_DOCUMENT_FORMS (view->document),
+ field, !state);
+ ev_pixbuf_cache_reload_page (view->pixbuf_cache,
+ field->page,
+ view->rotation,
+ view->scale);
+ }
+ break;
+ }
+
+ return NULL;
+}
+
+static void
+ev_view_form_field_text_save (EvView *view,
+ GtkWidget *widget)
+{
+ EvFormField *field;
+
+ field = g_object_get_data (G_OBJECT (widget), "form-field");
+
+ if (field->changed) {
+ EvFormFieldText *field_text = EV_FORM_FIELD_TEXT (field);
+
+ ev_document_forms_form_field_text_set_text (EV_DOCUMENT_FORMS (view->document),
+ field, field_text->text);
+ field->changed = FALSE;
+ ev_pixbuf_cache_reload_page (view->pixbuf_cache,
+ field->page,
+ view->rotation,
+ view->scale);
+ }
+}
+
+static void
+ev_view_form_field_text_changed (GtkWidget *widget,
+ EvFormField *field)
+{
+ EvFormFieldText *field_text = EV_FORM_FIELD_TEXT (field);
+ gchar *text = NULL;
+
+ if (GTK_IS_ENTRY (widget)) {
+ text = g_strdup (gtk_entry_get_text (GTK_ENTRY (widget)));
+ } else if (GTK_IS_TEXT_BUFFER (widget)) {
+ GtkTextIter start, end;
+
+ gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (widget), &start, &end);
+ text = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (widget),
+ &start, &end, FALSE);
+ }
+
+ if (!field_text->text ||
+ (field_text->text && g_ascii_strcasecmp (field_text->text, text) != 0)) {
+ g_free (field_text->text);
+ field_text->text = text;
+ field->changed = TRUE;
+ }
+}
+
+static GtkWidget *
+ev_view_form_field_text_create_widget (EvView *view,
+ EvFormField *field)
+{
+ EvFormFieldText *field_text = EV_FORM_FIELD_TEXT (field);
+ GtkWidget *text = NULL;
+ gchar *txt;
+
+ txt = ev_document_forms_form_field_text_get_text (EV_DOCUMENT_FORMS (view->document),
+ field);
+
+ switch (field_text->type) {
+ case EV_FORM_FIELD_TEXT_FILE_SELECT:
+ /* TODO */
+ case EV_FORM_FIELD_TEXT_NORMAL:
+ case EV_FORM_FIELD_TEXT_PASSWORD:
+ text = gtk_entry_new ();
+ gtk_entry_set_has_frame (GTK_ENTRY (text), FALSE);
+ gtk_entry_set_max_length (GTK_ENTRY (text), field_text->max_len);
+ gtk_entry_set_visibility (GTK_ENTRY (text),
+ !(field_text->type == EV_FORM_FIELD_TEXT_PASSWORD));
+
+ if (txt) {
+ gtk_entry_set_text (GTK_ENTRY (text), txt);
+ g_free (txt);
+ }
+
+ g_signal_connect (G_OBJECT (text), "changed",
+ G_CALLBACK (ev_view_form_field_text_changed),
+ field);
+ g_signal_connect_after (G_OBJECT (text), "activate",
+ G_CALLBACK (ev_view_form_field_destroy),
+ view);
+ break;
+ case EV_FORM_FIELD_TEXT_MULTILINE: {
+ GtkTextBuffer *buffer;
+
+ text = gtk_text_view_new ();
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text));
+
+ if (txt) {
+ gtk_text_buffer_set_text (buffer, txt, -1);
+ g_free (txt);
+ }
+
+ g_signal_connect (G_OBJECT (buffer), "changed",
+ G_CALLBACK (ev_view_form_field_text_changed),
+ field);
+ }
+ break;
+ }
+
+ g_object_weak_ref (G_OBJECT (text),
+ (GWeakNotify)ev_view_form_field_text_save,
+ view);
+
+ return text;
+}
+
+static void
+ev_view_form_field_choice_save (EvView *view,
+ GtkWidget *widget)
+{
+ EvFormField *field;
+
+ field = g_object_get_data (G_OBJECT (widget), "form-field");
+
+ if (field->changed) {
+ GList *l;
+ EvFormFieldChoice *field_choice = EV_FORM_FIELD_CHOICE (field);
+
+ if (field_choice->is_editable) {
+ ev_document_forms_form_field_choice_set_text (EV_DOCUMENT_FORMS (view->document),
+ field, field_choice->text);
+ }
+
+ ev_document_forms_form_field_choice_unselect_all (EV_DOCUMENT_FORMS (view->document), field);
+ for (l = field_choice->selected_items; l && l->data; l = g_list_next (l)) {
+ ev_document_forms_form_field_choice_select_item (EV_DOCUMENT_FORMS (view->document),
+ field,
+ GPOINTER_TO_INT (l->data));
+ }
+ field->changed = FALSE;
+ ev_pixbuf_cache_reload_page (view->pixbuf_cache,
+ field->page,
+ view->rotation,
+ view->scale);
+ }
+}
+
+static void
+ev_view_form_field_choice_changed (GtkWidget *widget,
+ EvFormField *field)
+{
+ EvFormFieldChoice *field_choice = EV_FORM_FIELD_CHOICE (field);
+
+ if (GTK_IS_COMBO_BOX (widget)) {
+ gint item;
+
+ item = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
+ if (GPOINTER_TO_INT (field_choice->selected_items->data) != item) {
+ g_list_free (field_choice->selected_items);
+ field_choice->selected_items = NULL;
+ field_choice->selected_items = g_list_prepend (field_choice->selected_items,
+ GINT_TO_POINTER (item));
+ field->changed = TRUE;
+ }
+
+ if (GTK_IS_COMBO_BOX_ENTRY (widget)) {
+ gchar *text;
+
+ text = gtk_combo_box_get_active_text (GTK_COMBO_BOX (widget));
+ if (!field_choice->text ||
+ (field_choice->text && g_ascii_strcasecmp (field_choice->text, text) != 0)) {
+ g_free (field_choice->text);
+ field_choice->text = text;
+ field->changed = TRUE;
+ }
+ }
+ } else if (GTK_IS_TREE_SELECTION (widget)) {
+ GtkTreeSelection *selection = GTK_TREE_SELECTION (widget);
+ GtkTreeModel *model;
+ GList *items, *l;
+
+ items = gtk_tree_selection_get_selected_rows (selection, &model);
+ g_list_free (field_choice->selected_items);
+ field_choice->selected_items = NULL;
+
+ for (l = items; l && l->data; l = g_list_next (l)) {
+ GtkTreeIter iter;
+ GtkTreePath *path = (GtkTreePath *)l->data;
+ gint item;
+
+ gtk_tree_model_get_iter (model, &iter, path);
+ gtk_tree_model_get (model, &iter, 1, &item, -1);
+
+ field_choice->selected_items = g_list_prepend (field_choice->selected_items,
+ GINT_TO_POINTER (item));
+
+ gtk_tree_path_free (path);
+ }
+
+ g_list_free (items);
+
+ field->changed = TRUE;
+ }
+}
+
+static GtkWidget *
+ev_view_form_field_choice_create_widget (EvView *view,
+ EvFormField *field)
+{
+ EvFormFieldChoice *field_choice = EV_FORM_FIELD_CHOICE (field);
+ GtkWidget *choice;
+ GtkTreeModel *model;
+ gint n_items, i;
+ gint selected_item = 0;
+
+ n_items = ev_document_forms_form_field_choice_get_n_items (EV_DOCUMENT_FORMS (view->document),
+ field);
+ model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT));
+ for (i = 0; i < n_items; i++) {
+ GtkTreeIter iter;
+ gchar *item;
+
+ item = ev_document_forms_form_field_choice_get_item (EV_DOCUMENT_FORMS (view->document),
+ field, i);
+ if (ev_document_forms_form_field_choice_is_item_selected (
+ EV_DOCUMENT_FORMS (view->document), field, i)) {
+ selected_item = i;
+ /* FIXME: we need a get_selected_items function in poppler */
+ field_choice->selected_items = g_list_prepend (field_choice->selected_items,
+ GINT_TO_POINTER (i));
+ }
+
+ if (item) {
+ gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+ gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+ 0, item,
+ 1, i,
+ -1);
+ g_free (item);
+ }
+ }
+
+ if (field_choice->type == EV_FORM_FIELD_CHOICE_LIST) {
+ GtkCellRenderer *renderer;
+ GtkWidget *tree_view;
+ GtkTreeSelection *selection;
+
+ tree_view = gtk_tree_view_new_with_model (model);
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tree_view), FALSE);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+ if (field_choice->multi_select) {
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
+ }
+
+ /* TODO: set selected items */
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view),
+ 0,
+ "choix", renderer,
+ "text", 0,
+ NULL);
+
+ choice = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (choice),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_container_add (GTK_CONTAINER (choice), tree_view);
+ gtk_widget_show (tree_view);
+
+ g_signal_connect (G_OBJECT (selection), "changed",
+ G_CALLBACK (ev_view_form_field_choice_changed),
+ field);
+ g_signal_connect_after (G_OBJECT (selection), "changed",
+ G_CALLBACK (ev_view_form_field_destroy),
+ view);
+ } else if (field_choice->is_editable) { /* ComboBoxEntry */
+ gchar *text;
+
+ choice = gtk_combo_box_entry_new_with_model (model, 0);
+ text = ev_document_forms_form_field_choice_get_text (EV_DOCUMENT_FORMS (view->document), field);
+ if (text) {
+ gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (choice))), text);
+ g_free (text);
+ }
+
+ g_signal_connect (G_OBJECT (choice), "changed",
+ G_CALLBACK (ev_view_form_field_choice_changed),
+ field);
+ g_signal_connect_after (G_OBJECT (GTK_BIN (choice)->child), "activate",
+ G_CALLBACK (ev_view_form_field_destroy),
+ view);
+ } else { /* ComboBoxText */
+ GtkCellRenderer *renderer;
+
+ choice = gtk_combo_box_new_with_model (model);
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (choice),
+ renderer, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (choice),
+ renderer,
+ "text", 0,
+ NULL);
+ gtk_combo_box_set_active (GTK_COMBO_BOX (choice), selected_item);
+ gtk_combo_box_popup (GTK_COMBO_BOX (choice));
+
+ g_signal_connect (G_OBJECT (choice), "changed",
+ G_CALLBACK (ev_view_form_field_choice_changed),
+ field);
+ g_signal_connect_after (G_OBJECT (choice), "changed",
+ G_CALLBACK (ev_view_form_field_destroy),
+ view);
+ }
+
+ g_object_unref (model);
+
+ g_object_weak_ref (G_OBJECT (choice),
+ (GWeakNotify)ev_view_form_field_choice_save,
+ view);
+
+ return choice;
+}
+
+static void
+ev_view_handle_form_field (EvView *view,
+ EvFormField *field,
+ gdouble x,
+ gdouble y)
+{
+ GtkWidget *field_widget = NULL;
+ GList *form_field_mapping;
+ EvRectangle field_area;
+ GdkRectangle view_area;
+
+ if (field->is_read_only)
+ return;
+
+ if (EV_IS_FORM_FIELD_BUTTON (field)) {
+ field_widget = ev_view_form_field_button_create_widget (view, field);
+ } else if (EV_IS_FORM_FIELD_TEXT (field)) {
+ field_widget = ev_view_form_field_text_create_widget (view, field);
+ } else if (EV_IS_FORM_FIELD_CHOICE (field)) {
+ field_widget = ev_view_form_field_choice_create_widget (view, field);
+ } else if (EV_IS_FORM_FIELD_SIGNATURE (field)) {
+ /* TODO */
+ }
+
+ /* Form field doesn't require a widget */
+ if (!field_widget)
+ return;
+
+ g_object_set_data_full (G_OBJECT (field_widget), "form-field",
+ g_object_ref (field),
+ (GDestroyNotify)g_object_unref);
+
+ form_field_mapping = ev_pixbuf_cache_get_form_field_mapping (view->pixbuf_cache, field->page);
+ ev_form_field_mapping_get_area (form_field_mapping, field, &field_area);
+
+ doc_rect_to_view_rect (view, field->page, &field_area, &view_area);
+ view_area.x -= view->scroll_x;
+ view_area.y -= view->scroll_y;
+
+ gtk_layout_put (GTK_LAYOUT (view), field_widget, view_area.x, view_area.y);
+ gtk_widget_show (field_widget);
+ gtk_widget_grab_focus (field_widget);
+}
+
/*** GtkWidget implementation ***/
static void
@@ -1680,7 +2125,7 @@ ev_view_size_request (GtkWidget *widget,
GtkRequisition *requisition)
{
EvView *view = EV_VIEW (widget);
-
+
if (view->document == NULL) {
requisition->width = 1;
requisition->height = 1;
@@ -1708,6 +2153,7 @@ ev_view_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
EvView *view = EV_VIEW (widget);
+ GList *children, *l;
GTK_WIDGET_CLASS (ev_view_parent_class)->size_allocate (widget, allocation);
@@ -1718,7 +2164,7 @@ ev_view_size_allocate (GtkWidget *widget,
ev_view_size_request (widget, &widget->requisition);
}
-
+
view_set_adjustment_values (view, GTK_ORIENTATION_HORIZONTAL);
view_set_adjustment_values (view, GTK_ORIENTATION_VERTICAL);
@@ -1727,47 +2173,71 @@ ev_view_size_allocate (GtkWidget *widget,
view->pending_scroll = SCROLL_TO_KEEP_POSITION;
view->pending_resize = FALSE;
+
+ children = gtk_container_get_children (GTK_CONTAINER (widget));
+ for (l = children; l && l->data; l = g_list_next (l)) {
+ EvFormField *field;
+ EvRectangle field_area;
+ GdkRectangle view_area;
+ GList *form_field_mapping;
+ GtkAllocation child_allocation;
+ GtkRequisition child_requisition;
+ GtkWidget *child = (GtkWidget *)l->data;
+
+ field = g_object_get_data (G_OBJECT (child), "form-field");
+ if (!field)
+ continue;
+
+ form_field_mapping = ev_pixbuf_cache_get_form_field_mapping (view->pixbuf_cache,
+ field->page);
+ ev_form_field_mapping_get_area (form_field_mapping, field, &field_area);
+
+ doc_rect_to_view_rect (view, field->page, &field_area, &view_area);
+ view_area.x -= view->scroll_x;
+ view_area.y -= view->scroll_y;
+
+ gtk_widget_size_request (child, &child_requisition);
+ if (child_requisition.width != view_area.width ||
+ child_requisition.height != view_area.height)
+ gtk_widget_set_size_request (child, view_area.width, view_area.height);
+
+ gtk_container_child_get (GTK_CONTAINER (widget),
+ child,
+ "x", &child_allocation.x,
+ "y", &child_allocation.y,
+ NULL);
+ if (child_allocation.x != view_area.x ||
+ child_allocation.y != view_area.y) {
+ gtk_layout_move (GTK_LAYOUT (widget), child, view_area.x, view_area.y);
+ }
+ }
+ g_list_free (children);
}
static void
ev_view_realize (GtkWidget *widget)
{
EvView *view = EV_VIEW (widget);
- GdkWindowAttr attributes;
-
- GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
- attributes.window_type = GDK_WINDOW_CHILD;
- attributes.wclass = GDK_INPUT_OUTPUT;
- attributes.visual = gtk_widget_get_visual (widget);
- attributes.colormap = gtk_widget_get_colormap (widget);
+ if (GTK_WIDGET_CLASS (ev_view_parent_class)->realize)
+ (* GTK_WIDGET_CLASS (ev_view_parent_class)->realize) (widget);
- attributes.x = widget->allocation.x;
- attributes.y = widget->allocation.y;
- attributes.width = widget->allocation.width;
- attributes.height = widget->allocation.height;
- attributes.event_mask = GDK_EXPOSURE_MASK |
+ gdk_window_set_events (view->layout.bin_window,
+ (gdk_window_get_events (view->layout.bin_window) |
+ GDK_EXPOSURE_MASK |
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_SCROLL_MASK |
GDK_KEY_PRESS_MASK |
GDK_POINTER_MOTION_MASK |
GDK_POINTER_MOTION_HINT_MASK |
- GDK_ENTER_NOTIFY_MASK |
- GDK_LEAVE_NOTIFY_MASK;
-
- widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
- &attributes,
- GDK_WA_X | GDK_WA_Y |
- GDK_WA_COLORMAP |
- GDK_WA_VISUAL);
- gdk_window_set_user_data (widget->window, widget);
- widget->style = gtk_style_attach (widget->style, widget->window);
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK));
if (view->presentation)
- gdk_window_set_background (widget->window, &widget->style->black);
+ gdk_window_set_background (view->layout.bin_window, &widget->style->black);
else
- gdk_window_set_background (widget->window, &widget->style->mid [GTK_STATE_NORMAL]);
+ gdk_window_set_background (view->layout.bin_window, &widget->style->mid [GTK_STATE_NORMAL]);
}
static gboolean
@@ -1869,7 +2339,7 @@ draw_end_presentation_page (EvView *view,
pango_layout_set_font_description (layout, font_desc);
gtk_paint_layout (GTK_WIDGET (view)->style,
- GTK_WIDGET (view)->window,
+ view->layout.bin_window,
GTK_WIDGET_STATE (view),
FALSE,
page_area,
@@ -1939,6 +2409,9 @@ ev_view_expose_event (GtkWidget *widget,
highlight_find_results (view, i);
}
+ if (GTK_WIDGET_CLASS (ev_view_parent_class)->expose_event)
+ (* GTK_WIDGET_CLASS (ev_view_parent_class)->expose_event) (widget, event);
+
return FALSE;
}
@@ -1995,6 +2468,7 @@ ev_view_button_press_event (GtkWidget *widget,
switch (event->button) {
case 1: {
EvImage *image;
+ EvFormField *field;
if (view->selection_info.selections) {
if (location_in_selected_text (view,
@@ -2018,7 +2492,11 @@ ev_view_button_press_event (GtkWidget *widget,
view->image_dnd_info.start.x = event->x + view->scroll_x;
view->image_dnd_info.start.y = event->y + view->scroll_y;
+ } else if ((field = ev_view_get_form_field_at_location (view, event->x, event->y))) {
+ ev_view_remove_all (view);
+ ev_view_handle_form_field (view, field, event->x, event->y);
} else {
+ ev_view_remove_all (view);
view->selection_info.start.x = event->x + view->scroll_x;
view->selection_info.start.y = event->y + view->scroll_y;
}
@@ -2042,6 +2520,19 @@ ev_view_button_press_event (GtkWidget *widget,
return FALSE;
}
+static void
+ev_view_remove_all (EvView *view)
+{
+ GList *children, *child;
+
+ children = gtk_container_get_children (GTK_CONTAINER (view));
+ for (child = children; child && child->data; child = g_list_next (child)) {
+ gtk_container_remove (GTK_CONTAINER (view),
+ GTK_WIDGET (child->data));
+ }
+ g_list_free (children);
+}
+
/*** Drag and Drop ***/
static void
ev_view_drag_data_get (GtkWidget *widget,
@@ -2196,7 +2687,7 @@ ev_view_motion_notify_event (GtkWidget *widget,
if (!view->document)
return FALSE;
- if (event->is_hint || event->window != widget->window) {
+ if (event->is_hint || event->window != view->layout.bin_window) {
gtk_widget_get_pointer (widget, &x, &y);
} else {
x = event->x;
@@ -2306,7 +2797,7 @@ ev_view_motion_notify_event (GtkWidget *widget,
return TRUE;
}
} else if (view->pressed_button <= 0) {
- handle_link_over_xy (view, x, y);
+ ev_view_handle_cursor_over_xy (view, x, y);
return TRUE;
}
@@ -2642,11 +3133,11 @@ ev_view_key_press_event (GtkWidget *widget,
switch (view->presentation_state) {
case EV_PRESENTATION_NORMAL:
case EV_PRESENTATION_BLACK:
- gdk_window_set_background (widget->window,
+ gdk_window_set_background (view->layout.bin_window,
&widget->style->black);
break;
case EV_PRESENTATION_WHITE:
- gdk_window_set_background (widget->window,
+ gdk_window_set_background (view->layout.bin_window,
&widget->style->white);
break;
default:
@@ -2706,7 +3197,7 @@ ev_view_enter_notify_event (GtkWidget *widget, GdkEventCrossing *event)
{
EvView *view = EV_VIEW (widget);
- handle_link_over_xy (view, event->x, event->y);
+ ev_view_handle_cursor_over_xy (view, event->x, event->y);
return FALSE;
}
@@ -2793,7 +3284,7 @@ highlight_find_results (EvView *view, int page)
ev_document_find_get_result (find, page, i, &rectangle);
doc_rect_to_view_rect (view, page, &rectangle, &view_rectangle);
- draw_rubberband (GTK_WIDGET (view), GTK_WIDGET(view)->window,
+ draw_rubberband (GTK_WIDGET (view), view->layout.bin_window,
&view_rectangle, alpha);
}
}
@@ -2857,7 +3348,7 @@ draw_loading_text (EvView *view,
width = (page_area->width - cairo_image_surface_get_width (view->loading_text)) / 2;
height = (page_area->height - cairo_image_surface_get_height (view->loading_text)) / 2;
- cr = gdk_cairo_create (GTK_WIDGET (view)->window);
+ cr = gdk_cairo_create (view->layout.bin_window);
cairo_translate (cr,
page_area->x + width,
page_area->y + height);
@@ -2893,9 +3384,9 @@ draw_one_page (EvView *view,
if (!view->presentation) {
gint current_page;
-
+
current_page = ev_page_cache_get_current_page (view->page_cache);
- ev_document_misc_paint_one_page (GTK_WIDGET (view)->window,
+ ev_document_misc_paint_one_page (view->layout.bin_window,
GTK_WIDGET (view),
page_area, border,
page == current_page);
@@ -2925,7 +3416,7 @@ draw_one_page (EvView *view,
view->scale,
&width, &height);
- cr = gdk_cairo_create (GTK_WIDGET (view)->window);
+ cr = gdk_cairo_create (view->layout.bin_window);
cairo_save (cr);
@@ -3057,7 +3548,7 @@ ev_view_destroy (GtkObject *object)
ev_view_presentation_transition_stop (view);
- ev_view_set_scroll_adjustments (view, NULL, NULL);
+ ev_view_set_scroll_adjustments (GTK_LAYOUT (view), NULL, NULL);
GTK_OBJECT_CLASS (ev_view_parent_class)->destroy (object);
}
@@ -3179,6 +3670,7 @@ ev_view_class_init (EvViewClass *class)
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+ GtkLayoutClass *layout_class = GTK_LAYOUT_CLASS (class);
GtkBindingSet *binding_set;
object_class->finalize = ev_view_finalize;
@@ -3204,22 +3696,13 @@ ev_view_class_init (EvViewClass *class)
widget_class->drag_motion = ev_view_drag_motion;
widget_class->drag_data_received = ev_view_drag_data_received;
widget_class->popup_menu = ev_view_popup_menu;
+
gtk_object_class->destroy = ev_view_destroy;
- class->set_scroll_adjustments = ev_view_set_scroll_adjustments;
+ layout_class->set_scroll_adjustments = ev_view_set_scroll_adjustments;
+
class->binding_activated = ev_view_scroll;
- widget_class->set_scroll_adjustments_signal =
- g_signal_new ("set-scroll-adjustments",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (EvViewClass, set_scroll_adjustments),
- NULL, NULL,
- ev_marshal_VOID__OBJECT_OBJECT,
- G_TYPE_NONE, 2,
- GTK_TYPE_ADJUSTMENT,
- GTK_TYPE_ADJUSTMENT);
-
signals[SIGNAL_BINDING_ACTIVATED] = g_signal_new ("binding_activated",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
@@ -3379,6 +3862,9 @@ ev_view_init (EvView *view)
view->pending_scroll = SCROLL_TO_KEEP_POSITION;
view->jump_to_find_result = TRUE;
+ gtk_layout_set_hadjustment (GTK_LAYOUT (view), NULL);
+ gtk_layout_set_vadjustment (GTK_LAYOUT (view), NULL);
+
gtk_drag_dest_set (GTK_WIDGET (view),
GTK_DEST_DEFAULT_ALL,
view_drop_targets,
@@ -3429,7 +3915,7 @@ page_changed_cb (EvPageCache *page_cache,
ev_view_presentation_transition_start (view);
gtk_widget_get_pointer (GTK_WIDGET (view), &x, &y);
- handle_link_over_xy (view, x, y);
+ ev_view_handle_cursor_over_xy (view, x, y);
gtk_widget_queue_resize (GTK_WIDGET (view));
} else {
@@ -3448,6 +3934,7 @@ on_adjustment_value_changed (GtkAdjustment *adjustment,
{
int dx = 0, dy = 0;
gint x, y;
+ GList *children, *l;
if (! GTK_WIDGET_REALIZED (view))
return;
@@ -3466,13 +3953,27 @@ on_adjustment_value_changed (GtkAdjustment *adjustment,
view->scroll_y = 0;
}
+ children = gtk_container_get_children (GTK_CONTAINER (view));
+ for (l = children; l && l->data; l = g_list_next (l)) {
+ gint child_x, child_y;
+ GtkWidget *child = (GtkWidget *)l->data;
+
+ gtk_container_child_get (GTK_CONTAINER (view),
+ child,
+ "x", &child_x,
+ "y", &child_y,
+ NULL);
+ gtk_layout_move (GTK_LAYOUT (view), child, child_x + dx, child_y + dy);
+ }
+ g_list_free (children);
+
if (view->pending_resize)
gtk_widget_queue_draw (GTK_WIDGET (view));
else
- gdk_window_scroll (GTK_WIDGET (view)->window, dx, dy);
+ gdk_window_scroll (view->layout.bin_window, dx, dy);
gtk_widget_get_pointer (GTK_WIDGET (view), &x, &y);
- handle_link_over_xy (view, x, y);
+ ev_view_handle_cursor_over_xy (view, x, y);
if (view->document)
view_update_range_and_current_page (view);
@@ -3725,10 +4226,10 @@ ev_view_set_presentation (EvView *view,
if (GTK_WIDGET_REALIZED (view)) {
if (view->presentation)
- gdk_window_set_background (GTK_WIDGET(view)->window,
+ gdk_window_set_background (view->layout.bin_window,
&GTK_WIDGET (view)->style->black);
else
- gdk_window_set_background (GTK_WIDGET(view)->window,
+ gdk_window_set_background (view->layout.bin_window,
&GTK_WIDGET (view)->style->mid [GTK_STATE_NORMAL]);
}
@@ -4629,7 +5130,7 @@ merge_selection_region (EvView *view,
gdk_region_offset (region,
page_area.x + border.left - view->scroll_x,
page_area.y + border.top - view->scroll_y);
- gdk_window_invalidate_region (GTK_WIDGET (view)->window, region, TRUE);
+ gdk_window_invalidate_region (view->layout.bin_window, region, TRUE);
gdk_region_destroy (region);
}
}
@@ -4843,7 +5344,7 @@ ev_view_set_cursor (EvView *view, EvViewCursor new_cursor)
switch (new_cursor) {
case EV_VIEW_CURSOR_NORMAL:
- gdk_window_set_cursor (widget->window, NULL);
+ gdk_window_set_cursor (view->layout.bin_window, NULL);
break;
case EV_VIEW_CURSOR_IBEAM:
cursor = gdk_cursor_new_for_display (display, GDK_XTERM);
@@ -4863,7 +5364,7 @@ ev_view_set_cursor (EvView *view, EvViewCursor new_cursor)
}
if (cursor) {
- gdk_window_set_cursor (widget->window, cursor);
+ gdk_window_set_cursor (view->layout.bin_window, cursor);
gdk_cursor_unref (cursor);
gdk_flush();
}
@@ -4889,7 +5390,7 @@ ev_view_reset_presentation_state (EvView *view)
return;
view->presentation_state = EV_PRESENTATION_NORMAL;
- gdk_window_set_background (GTK_WIDGET (view)->window,
+ gdk_window_set_background (view->layout.bin_window,
&GTK_WIDGET (view)->style->black);
gtk_widget_queue_draw (GTK_WIDGET (view));
}
diff --git a/shell/ev-view.h b/shell/ev-view.h
index e9b8afa..78fc659 100644
--- a/shell/ev-view.h
+++ b/shell/ev-view.h
@@ -21,6 +21,7 @@
#define __EV_VIEW_H__
#include <gtk/gtkwidget.h>
+#include <gtk/gtklayout.h>
#include "ev-document.h"
#include "ev-link.h"