Index: INSTALL =================================================================== RCS file: /cvs/gnome/evince/INSTALL,v retrieving revision 1.1.1.1 diff -u -8 -p -r1.1.1.1 INSTALL --- INSTALL 21 Dec 2004 17:40:58 -0000 1.1.1.1 +++ INSTALL 12 Jun 2006 21:24:02 -0000 @@ -1,18 +1,21 @@ -Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software -Foundation, Inc. +Installation Instructions +************************* - This file is free documentation; the Free Software Foundation gives +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free +Software Foundation, Inc. + +This file is free documentation; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. Basic Installation ================== - These are generic installation instructions. +These are generic installation instructions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for @@ -62,143 +65,147 @@ The simplest way to compile this package also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. Compilers and Options ===================== - Some systems require unusual options for compilation or linking that -the `configure' script does not know about. Run `./configure --help' -for details on some of the pertinent environment variables. +Some systems require unusual options for compilation or linking that the +`configure' script does not know about. Run `./configure --help' for +details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== - You can compile the package for more than one kind of computer at the +You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you must use a version of `make' that supports the `VPATH' variable, such as GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. If you have to use a `make' that does not support the `VPATH' variable, you have to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. Installation Names ================== - By default, `make install' will install the package's files in -`/usr/local/bin', `/usr/local/man', etc. You can specify an -installation prefix other than `/usr/local' by giving `configure' the -option `--prefix=PATH'. +By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you -give `configure' the option `--exec-prefix=PATH', the package will use -PATH as the prefix for installing programs and libraries. -Documentation and other data files will still use the regular prefix. +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give -options like `--bindir=PATH' to specify different values for particular +options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= - Some packages pay attention to `--enable-FEATURE' options to +Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Specifying the System Type ========================== - There may be some features `configure' cannot figure out -automatically, but needs to determine by the type of machine the package -will run on. Usually, assuming the package is built to be run on the -_same_ architectures, `configure' can figure that out, but if it prints -a message saying it cannot guess the machine type, give it the +There may be some features `configure' cannot figure out automatically, +but needs to determine by the type of machine the package will run on. +Usually, assuming the package is built to be run on the _same_ +architectures, `configure' can figure that out, but if it prints a +message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should -use the `--target=TYPE' option to select the type of system they will +use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ - If you want to set default values for `configure' scripts to share, -you can create a site shell script called `config.site' that gives -default values for variables like `CC', `cache_file', and `prefix'. +If you want to set default values for `configure' scripts to share, you +can create a site shell script called `config.site' that gives default +values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== - Variables not defined in a site shell script can be set in the +Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc -will cause the specified gcc to be used as the C compiler (unless it is -overridden in the site shell script). +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). Here is a another example: + + /bin/bash ./configure CONFIG_SHELL=/bin/bash + +Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent +configuration-related scripts to be executed by `/bin/bash'. `configure' Invocation ====================== - `configure' recognizes the following options to control how it -operates. +`configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of the options to `configure', and exit. `--version' `-V' Print the version of Autoconf used to generate the `configure' Index: backend/Makefile.am =================================================================== RCS file: /cvs/gnome/evince/backend/Makefile.am,v retrieving revision 1.27 diff -u -8 -p -r1.27 Makefile.am --- backend/Makefile.am 2 May 2006 19:02:45 -0000 1.27 +++ backend/Makefile.am 12 Jun 2006 21:24:02 -0000 @@ -36,16 +36,18 @@ libevbackend_la_SOURCES= \ ev-document-fonts.h \ ev-document-links.c \ ev-document-links.h \ ev-document-security.c \ ev-document-security.h \ ev-document-find.c \ ev-document-find.h \ ev-document-info.h \ + ev-form-field.h \ + ev-form-field.c \ ev-ps-exporter.c \ ev-ps-exporter.h \ ev-render-context.h \ ev-render-context.c \ ev-selection.h \ ev-selection.c \ ev-document-misc.h \ ev-document-misc.c Index: backend/ev-document.c =================================================================== RCS file: /cvs/gnome/evince/backend/ev-document.c,v retrieving revision 1.35 diff -u -8 -p -r1.35 ev-document.c --- backend/ev-document.c 2 May 2006 19:02:45 -0000 1.35 +++ backend/ev-document.c 12 Jun 2006 21:24:02 -0000 @@ -254,8 +254,35 @@ ev_rect_cmp (EvRectangle *a, if (a == NULL || b == NULL) return 1; return ! ((ABS (a->x1 - b->x1) < EPSILON) && (ABS (a->y1 - b->y1) < EPSILON) && (ABS (a->x2 - b->x2) < EPSILON) && (ABS (a->y2 - b->y2) < EPSILON)); } + +GList* +ev_document_get_form_field_mapping (EvDocument *document, + int page) +{ + EvDocumentIface *iface = EV_DOCUMENT_GET_IFACE (document); + GList *retval; + + LOG ("ev_document_get_form_fields"); + if (iface->get_form_field_mapping == NULL) + return NULL; + retval = iface->get_form_field_mapping (document, page); + return retval; +} + +gboolean +ev_document_get_crop_box (EvDocument *document, + int page, + EvRectangle *rect) +{ + EvDocumentIface *iface = EV_DOCUMENT_GET_IFACE (document); + LOG("ev_document_get_crop_box"); + if (iface->get_crop_box == NULL) + return FALSE; + iface->get_crop_box(document, page, rect); + return TRUE; +} Index: backend/ev-document.h =================================================================== RCS file: /cvs/gnome/evince/backend/ev-document.h,v retrieving revision 1.34 diff -u -8 -p -r1.34 ev-document.h --- backend/ev-document.h 2 May 2006 19:02:45 -0000 1.34 +++ backend/ev-document.h 12 Jun 2006 21:24:03 -0000 @@ -22,16 +22,17 @@ #ifndef EV_DOCUMENT_H #define EV_DOCUMENT_H #include #include #include #include "ev-link.h" +#include "ev-form-field.h" #include "ev-document-info.h" #include "ev-render-context.h" G_BEGIN_DECLS #define EV_TYPE_DOCUMENT (ev_document_get_type ()) #define EV_DOCUMENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EV_TYPE_DOCUMENT, EvDocument)) #define EV_DOCUMENT_IFACE(k) (G_TYPE_CHECK_CLASS_CAST((k), EV_TYPE_DOCUMENT, EvDocumentIface)) @@ -83,21 +84,26 @@ struct _EvDocumentIface double *width, double *height); char * (* get_page_label) (EvDocument *document, int page); gboolean (* can_get_text) (EvDocument *document); char * (* get_text) (EvDocument *document, int page, EvRectangle *rect); + GList * (* get_form_field_mapping) (EvDocument *document, + int page); gboolean (* has_attachments) (EvDocument *document); GList * (* get_attachments) (EvDocument *document); GdkPixbuf * (* render_pixbuf) (EvDocument *document, EvRenderContext *rc); EvDocumentInfo * (* get_info) (EvDocument *document); + void (* get_crop_box) (EvDocument *document, + int page, + EvRectangle *rect); }; GType ev_document_get_type (void); GQuark ev_document_error_quark (void); GMutex *ev_document_get_doc_mutex (void); void ev_document_doc_mutex_lock (void); void ev_document_doc_mutex_unlock (void); @@ -121,13 +127,21 @@ char *ev_document_get_text EvRectangle *rect); gboolean ev_document_has_attachments (EvDocument *document); GList *ev_document_get_attachments (EvDocument *document); GdkPixbuf *ev_document_render_pixbuf (EvDocument *document, EvRenderContext *rc); gint ev_rect_cmp (EvRectangle *a, EvRectangle *b); + +GList *ev_document_get_form_field_mapping (EvDocument *document, + int page); + +gboolean ev_document_get_crop_box (EvDocument *document, + int page, + EvRectangle *rect); + G_END_DECLS #endif Index: backend/ev-form-field-mapping.c =================================================================== RCS file: backend/ev-form-field-mapping.c diff -N backend/ev-form-field-mapping.c Index: backend/ev-form-field-mapping.h =================================================================== RCS file: backend/ev-form-field-mapping.h diff -N backend/ev-form-field-mapping.h Index: backend/ev-form-field.c =================================================================== RCS file: backend/ev-form-field.c diff -N backend/ev-form-field.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ backend/ev-form-field.c 12 Jun 2006 21:24:03 -0000 @@ -0,0 +1,82 @@ +/* -*- 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) 2005 Red Hat, Inc. + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "ev-form-field.h" + +EvFormField * +ev_form_field_new () +{ + EvFormField *field = g_new (EvFormField, 1); + field->id = -1; + field->content = NULL; + +} + +void +ev_form_field_mapping_free (GList *form_field_mapping) +{ + if (form_field_mapping == NULL) + return; + + g_list_foreach (form_field_mapping, (GFunc) (g_free), NULL); + g_list_free (form_field_mapping); +} + + +EvFormField * +ev_form_field_mapping_find (GList *form_field_mapping, + gdouble x, + gdouble y) +{ + GList *list; + + for (list = form_field_mapping; list; list = list->next) { + EvFormField *field = list->data; + + if ((x >= field->x1) && + (y >= field->y1) && + (x <= field->x2) && + (y <= field->y2)) { + return field; + } + } + return NULL; +} + +EvFormField * +ev_form_field_mapping_find_by_id (GList *form_field_mapping, + int id) +{ + GList *list; + for (list = form_field_mapping; list; list = list->next) { + EvFormField *field = list->data; + + if (id == field->id) + return field; + } + return NULL; +} + + Index: backend/ev-form-field.h =================================================================== RCS file: backend/ev-form-field.h diff -N backend/ev-form-field.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ backend/ev-form-field.h 12 Jun 2006 21:24:03 -0000 @@ -0,0 +1,57 @@ +/* this file is part of evince, a gnome document viewer + * + * Copyright (C) 2005 Red Hat, Inc. + * 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 + +/*MUST be in the same order as poppler/glib/poppler.h PopplerFormFieldType !*/ +typedef enum +{ + EV_FORM_FIELD_TYPE_BUTTON, + EV_FORM_FIELD_TYPE_TEXT, + EV_FORM_FIELD_TYPE_CHOICE, + EV_FORM_FIELD_TYPE_SIGNATURE +} EvFormFieldType; + + +typedef struct _EvFormField EvFormField; +struct _EvFormField +{ + EvFormFieldType type; + int id; + gchar *content; + gdouble x1; + gdouble y1; + gdouble x2; + gdouble y2; +}; + +EvFormField *ev_form_field_new (); +void ev_form_field_mapping_free (GList *form_field_mapping); +EvFormField *ev_form_field_mapping_find (GList *form_field_mapping, + gdouble x, + gdouble y); +EvFormField *ev_form_field_mapping_find_by_id (GList *form_field_mapping, + int id); + +#endif /* !EV_FORM_H */ + Index: pdf/Makefile.am =================================================================== RCS file: /cvs/gnome/evince/pdf/Makefile.am,v retrieving revision 1.6 diff -u -8 -p -r1.6 Makefile.am --- pdf/Makefile.am 7 Jul 2005 12:11:24 -0000 1.6 +++ pdf/Makefile.am 12 Jun 2006 21:24:03 -0000 @@ -3,11 +3,12 @@ INCLUDES = \ -I$(top_srcdir)/backend \ $(BACKEND_CFLAGS) \ $(POPPLER_CFLAGS) \ $(WARN_CXXFLAGS) \ $(DISABLE_DEPRECATED) noinst_LTLIBRARIES = libpdfdocument.la + libpdfdocument_la_SOURCES = \ ev-poppler.cc \ ev-poppler.h Index: pdf/ev-poppler.cc =================================================================== RCS file: /cvs/gnome/evince/pdf/ev-poppler.cc,v retrieving revision 1.69 diff -u -8 -p -r1.69 ev-poppler.cc --- pdf/ev-poppler.cc 9 May 2006 18:00:47 -0000 1.69 +++ pdf/ev-poppler.cc 12 Jun 2006 21:24:05 -0000 @@ -79,16 +79,21 @@ static void pdf_document_thumbnails_get_ gint *width, gint *height); static int pdf_document_get_n_pages (EvDocument *document); static EvLinkDest *ev_link_dest_from_dest (PopplerDest *dest); static EvLink *ev_link_from_action (PopplerAction *action); static void pdf_document_search_free (PdfDocumentSearch *search); +static void pdf_document_get_crop_box (EvDocument *document, int page, EvRectangle *rect); +static GList *pdf_document_get_form_field_mapping (EvDocument *document, int page); + + + G_DEFINE_TYPE_WITH_CODE (PdfDocument, pdf_document, G_TYPE_OBJECT, { G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT, pdf_document_document_iface_init); G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_SECURITY, pdf_document_security_iface_init); G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS, @@ -627,16 +632,18 @@ pdf_document_document_iface_init (EvDocu iface->load = pdf_document_load; iface->get_n_pages = pdf_document_get_n_pages; iface->get_page_size = pdf_document_get_page_size; iface->get_page_label = pdf_document_get_page_label; iface->has_attachments = pdf_document_has_attachments; iface->get_attachments = pdf_document_get_attachments; iface->render_pixbuf = pdf_document_render_pixbuf; iface->get_text = pdf_document_get_text; + iface->get_form_field_mapping = pdf_document_get_form_field_mapping; + iface->get_crop_box = pdf_document_get_crop_box; iface->can_get_text = pdf_document_can_get_text; iface->get_info = pdf_document_get_info; }; static void pdf_document_security_iface_init (EvDocumentSecurityIface *iface) { iface->has_document_security = pdf_document_has_document_security; @@ -1496,8 +1503,91 @@ pdf_selection_iface_init (EvSelectionIfa iface->get_selection_map = pdf_selection_get_selection_map; } PdfDocument * pdf_document_new (void) { return PDF_DOCUMENT (g_object_new (PDF_TYPE_DOCUMENT, NULL)); } + +//FIXME: duplicated from backend/ev-form-field.c to quickly fix linking problems (yeah, this really sucks) +EvFormField * +ev_form_field_new () +{ + EvFormField *field = g_new (EvFormField, 1); + field->id = -1; + field->content = NULL; + +} + + +static GList * +pdf_document_get_form_field_mapping (EvDocument *document, + int page) +{ + PdfDocument *pdf_document; + PopplerPage *poppler_page; + GList *retval = NULL; + GList *fields; + GList *list; + double height; + EvRectangle crop_box; + + pdf_document = PDF_DOCUMENT (document); + poppler_page = poppler_document_get_page (pdf_document->document, + page); + fields = poppler_page_get_form_fields (poppler_page); + poppler_page_get_size (poppler_page, NULL, &height); + + pdf_document_get_crop_box(document, page, &crop_box); + + for (list = fields; list; list = list->next) { + PopplerFormField *field; + EvFormField *field_mapping; + double rect[4]; + + field = (PopplerFormField *)list->data; + /* Invert y for X-style coordinates */ + rect[0] = field->area.x1; rect[1] = height - field->area.y2; + rect[2] = field->area.x2; rect[3] = height - field->area.y1; + + field_mapping = ev_form_field_new(); + field_mapping->type = (EvFormFieldType)field->type; + field_mapping->id = field->id; + field_mapping->x1 = rect[0]; + field_mapping->x2 = rect[2]; + field_mapping->y1 = rect[1]; + field_mapping->y2 = rect[3]; + /* Add crop box to form area */ + field_mapping->x1 -= crop_box.x1; + field_mapping->y1 += crop_box.y1; + field_mapping->x2 -= crop_box.x1; + field_mapping->y2 += crop_box.y1; + + + retval = g_list_prepend(retval, field_mapping); + } + poppler_page_free_form_fields(fields); + g_object_unref (poppler_page); + + return g_list_reverse(retval); +} + +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; +} + + Index: shell/ev-jobs.c =================================================================== RCS file: /cvs/gnome/evince/shell/ev-jobs.c,v retrieving revision 1.17 diff -u -8 -p -r1.17 ev-jobs.c --- shell/ev-jobs.c 29 May 2006 15:35:29 -0000 1.17 +++ shell/ev-jobs.c 12 Jun 2006 21:24:06 -0000 @@ -208,16 +208,17 @@ ev_job_links_run (EvJobLinks *job) EvJob * ev_job_render_new (EvDocument *document, EvRenderContext *rc, gint width, gint height, EvRectangle *selection_points, GdkColor *text, GdkColor *base, + gboolean include_form, gboolean include_links, gboolean include_text, gboolean include_selection) { EvJobRender *job; g_return_val_if_fail (EV_IS_RENDER_CONTEXT (rc), NULL); if (include_selection) @@ -226,16 +227,17 @@ ev_job_render_new (EvDocument *docu job = g_object_new (EV_TYPE_JOB_RENDER, NULL); EV_JOB (job)->document = g_object_ref (document); job->rc = g_object_ref (rc); job->target_width = width; job->target_height = height; job->text = *text; job->base = *base; + job->include_form = include_form; job->include_links = include_links; job->include_text = include_text; job->include_selection = include_selection; if (include_selection) job->selection_points = *selection_points; if (EV_IS_ASYNC_RENDERER (document)) { @@ -266,16 +268,18 @@ ev_job_render_run (EvJobRender *job) if (EV_JOB (job)->async) { EvAsyncRenderer *renderer = EV_ASYNC_RENDERER (EV_JOB (job)->document); ev_async_renderer_render_pixbuf (renderer, job->rc->page, job->rc->scale, job->rc->rotation); g_signal_connect (EV_JOB (job)->document, "render_finished", G_CALLBACK (render_finished_cb), job); } else { job->pixbuf = ev_document_render_pixbuf (EV_JOB (job)->document, job->rc); + if (job->include_form) + job->form_field_mapping = ev_document_get_form_field_mapping(EV_JOB(job)->document, job->rc->page); 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), 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), job->rc); Index: shell/ev-jobs.h =================================================================== RCS file: /cvs/gnome/evince/shell/ev-jobs.h,v retrieving revision 1.12 diff -u -8 -p -r1.12 ev-jobs.h --- shell/ev-jobs.h 29 May 2006 15:35:29 -0000 1.12 +++ shell/ev-jobs.h 12 Jun 2006 21:24:07 -0000 @@ -111,23 +111,25 @@ struct _EvJobRender EvRenderContext *rc; gint target_width; gint target_height; GdkPixbuf *pixbuf; GList *link_mapping; GdkRegion *text_mapping; + GList *form_field_mapping; GdkPixbuf *selection; GdkRegion *selection_region; EvRectangle selection_points; GdkColor base; GdkColor text; + gint include_form : 1; gint include_links : 1; gint include_text : 1; gint include_selection : 1; }; struct _EvJobRenderClass { EvJobClass parent_class; @@ -186,16 +188,17 @@ void ev_job_links_run GType ev_job_render_get_type (void); EvJob *ev_job_render_new (EvDocument *document, EvRenderContext *rc, gint width, gint height, EvRectangle *selection_points, GdkColor *text, GdkColor *base, + gboolean include_form, gboolean include_links, gboolean include_text, gboolean include_selection); void ev_job_render_run (EvJobRender *thumbnail); /* EvJobThumbnail */ GType ev_job_thumbnail_get_type (void); EvJob *ev_job_thumbnail_new (EvDocument *document, Index: shell/ev-pixbuf-cache.c =================================================================== RCS file: /cvs/gnome/evince/shell/ev-pixbuf-cache.c,v retrieving revision 1.22 diff -u -8 -p -r1.22 ev-pixbuf-cache.c --- shell/ev-pixbuf-cache.c 7 Jan 2006 13:18:28 -0000 1.22 +++ shell/ev-pixbuf-cache.c 12 Jun 2006 21:24:09 -0000 @@ -7,16 +7,17 @@ typedef struct _CacheJobInfo { EvJob *job; EvRenderContext *rc; /* Data we get from rendering */ GdkPixbuf *pixbuf; GList *link_mapping; GdkRegion *text_mapping; + GList *form_field_mapping; /* Selection data. * Selection_points are the coordinates encapsulated in selection. * target_points is the target selection size. */ EvRectangle selection_points; EvRectangle target_points; gboolean points_set; @@ -143,16 +144,20 @@ dispose_cache_job_info (CacheJobInfo *jo ev_job_queue_remove_job (job_info->job); g_object_unref (G_OBJECT (job_info->job)); job_info->job = NULL; } if (job_info->pixbuf) { g_object_unref (G_OBJECT (job_info->pixbuf)); job_info->pixbuf = 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->link_mapping) { ev_link_mapping_free (job_info->link_mapping); job_info->link_mapping = NULL; } if (job_info->text_mapping) { gdk_region_destroy (job_info->text_mapping); job_info->text_mapping = NULL; } @@ -304,16 +309,17 @@ move_one_job (CacheJobInfo *job_info, page_offset = page - start_page; g_assert (page_offset >= 0 && page_offset <= ((end_page - start_page) + 1)); new_priority = EV_JOB_PRIORITY_HIGH; target_page = new_job_list + page_offset; } *target_page = *job_info; + job_info->form_field_mapping = NULL; job_info->job = NULL; job_info->pixbuf = NULL; job_info->link_mapping = NULL; if (new_priority != priority && target_page->job) { ev_job_queue_update_job (target_page->job, new_priority); } } @@ -405,17 +411,19 @@ copy_job_to_job_info (EvJobRender *job dispose_cache_job_info (job_info, pixbuf_cache); job_info->pixbuf = pixbuf; job_info->rc = rc; if (job_render->link_mapping) job_info->link_mapping = job_render->link_mapping; if (job_render->text_mapping) - job_info->text_mapping = job_render->text_mapping; + job_info->text_mapping = job_render->text_mapping; + if (job_render->form_field_mapping) + job_info->form_field_mapping = job_render->form_field_mapping; if (job_render->include_selection) { pixbuf = g_object_ref (job_render->selection); job_info->selection_points = job_render->selection_points; job_info->selection_region = gdk_region_copy (job_render->selection_region); job_info->selection = pixbuf; g_assert (job_info->selection_points.x1 >= 0); } @@ -492,16 +500,17 @@ static void add_job_if_needed (EvPixbufCache *pixbuf_cache, CacheJobInfo *job_info, EvPageCache *page_cache, gint page, gint rotation, gfloat scale, EvJobPriority priority) { + gboolean include_form = FALSE; gboolean include_links = FALSE; gboolean include_text = FALSE; gboolean include_selection = FALSE; int width, height; GdkColor *text, *base; if (job_info->job) return; @@ -519,16 +528,20 @@ add_job_if_needed (EvPixbufCache *pixbuf 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 we don't set include_form to TRUE, sometimes the render job's form_field_mapping is NULL + although the page has some fields + if (job_info->form_field_mappings == NULL)*/ + include_form = TRUE; if (job_info->link_mapping == NULL) include_links = TRUE; if (job_info->text_mapping == NULL) include_text = TRUE; if (new_selection_pixbuf_needed (pixbuf_cache, job_info, page, scale)) { include_selection = TRUE; } @@ -536,16 +549,17 @@ add_job_if_needed (EvPixbufCache *pixbuf 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_form, include_links, 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); } @@ -1016,9 +1030,27 @@ ev_pixbuf_cache_get_selection_list (EvPi retval = g_list_append (retval, selection); } page ++; } return retval; } + +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; +} + Index: shell/ev-pixbuf-cache.h =================================================================== RCS file: /cvs/gnome/evince/shell/ev-pixbuf-cache.h,v retrieving revision 1.9 diff -u -8 -p -r1.9 ev-pixbuf-cache.h --- shell/ev-pixbuf-cache.h 6 Aug 2005 05:13:20 -0000 1.9 +++ shell/ev-pixbuf-cache.h 12 Jun 2006 21:24:10 -0000 @@ -58,16 +58,19 @@ void ev_pixbuf_cache_set_page_ gfloat scale, GList *selection_list); GdkPixbuf *ev_pixbuf_cache_get_pixbuf (EvPixbufCache *pixbuf_cache, gint page); GList *ev_pixbuf_cache_get_link_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); /* Selection */ GdkPixbuf *ev_pixbuf_cache_get_selection_pixbuf (EvPixbufCache *pixbuf_cache, gint page, gfloat scale, GdkRegion **region); Index: shell/ev-view-private.h =================================================================== RCS file: /cvs/gnome/evince/shell/ev-view-private.h,v retrieving revision 1.9 diff -u -8 -p -r1.9 ev-view-private.h --- shell/ev-view-private.h 4 May 2006 08:24:19 -0000 1.9 +++ shell/ev-view-private.h 12 Jun 2006 21:24:10 -0000 @@ -36,33 +36,44 @@ typedef struct { /* Information for handling selection */ typedef struct { gboolean in_drag; GdkPoint start; gboolean in_selection; GList *selections; } SelectionInfo; +/* Info for form fields/container */ +typedef struct { + GtkWidget *widget; + gint x; + gint y; + EvPoint p[2]; + gint page; + int field_id; //id of the field represented by this child +} EvViewChild; + + typedef enum { SCROLL_TO_KEEP_POSITION, SCROLL_TO_PAGE_POSITION, SCROLL_TO_CENTER, } PendingScroll; typedef enum { EV_VIEW_CURSOR_NORMAL, EV_VIEW_CURSOR_IBEAM, EV_VIEW_CURSOR_LINK, EV_VIEW_CURSOR_WAIT, EV_VIEW_CURSOR_HIDDEN, EV_VIEW_CURSOR_DRAG } EvViewCursor; struct _EvView { - GtkWidget parent_instance; + GtkContainer parent_instance; EvDocument *document; char *status; char *find_status; int find_result; gboolean jump_to_find_result; @@ -111,20 +122,25 @@ struct _EvView { guint selection_scroll_id; EvViewSelectionMode selection_mode; SelectionInfo selection_info; /* Links */ GtkWidget *link_tooltip; EvLink *hovered_link; + + /* Container */ + gint current_width; + gint current_height; + EvViewChild *child; }; struct _EvViewClass { - GtkWidgetClass parent_class; + GtkContainerClass parent_class; void (*set_scroll_adjustments) (EvView *view, GtkAdjustment *hadjustment, GtkAdjustment *vadjustment); void (*binding_activated) (EvView *view, EvScrollType scroll, gboolean horizontal); void (*zoom_invalid) (EvView *view); Index: shell/ev-view.c =================================================================== RCS file: /cvs/gnome/evince/shell/ev-view.c,v retrieving revision 1.207 diff -u -8 -p -r1.207 ev-view.c --- shell/ev-view.c 27 May 2006 13:00:31 -0000 1.207 +++ shell/ev-view.c 12 Jun 2006 21:24:21 -0000 @@ -86,16 +86,17 @@ static const GtkTargetEntry targets[] = static guint signals[N_SIGNALS]; typedef enum { EV_VIEW_FIND_NEXT, EV_VIEW_FIND_PREV } EvViewFindDirection; + #define ZOOM_IN_FACTOR 1.2 #define ZOOM_OUT_FACTOR (1.0/ZOOM_IN_FACTOR) #define MIN_SCALE 0.05409 #define MAX_SCALE 4.0 #define SCROLL_TIME 150 @@ -306,18 +307,60 @@ static char* get_selected_text static void ev_view_primary_get_cb (GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, gpointer data); static void ev_view_primary_clear_cb (GtkClipboard *clipboard, gpointer data); static void ev_view_update_primary_selection (EvView *ev_view); +/*** Forms ***/ +static EvFormField* ev_view_get_form_field_at_location (EvView *view, + gdouble x, + gdouble y); +static void handle_form_field_over_xy (EvView *view, + gint x, + gint y); +static void form_field_widgets_resize (EvView *view); +static void handle_click_at_location (EvView *view, + gdouble x, + gdouble y); + +/*** Container ***/ +static void ev_view_map (GtkWidget *widget); +static void ev_view_add (GtkContainer *cont, + GtkWidget *widget); +static void ev_view_remove (GtkContainer *cont, + GtkWidget *widget); +static void ev_view_remove_all (GtkContainer *cont); +static void ev_view_put (EvView *view, + GtkWidget *widget, + gint x, + gint y, + double x1, + double y1, + double x2, + double y2, + gint page, + gint id); +static void ev_view_forall (GtkContainer *cont, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data); +static void ev_view_allocate_child (EvView *view, + EvViewChild *child); +static void ev_view_move_internal (EvView *view, + GtkWidget *widget, + gboolean change_x, + gint x, + gboolean change_y, + gint y); + -G_DEFINE_TYPE (EvView, ev_view, GTK_TYPE_WIDGET) +G_DEFINE_TYPE (EvView, ev_view, GTK_TYPE_CONTAINER) static void scroll_to_current_page (EvView *view, GtkOrientation orientation) { GdkPoint view_point; if (view->document == NULL) { return; @@ -1580,16 +1623,29 @@ ev_view_size_request (GtkWidget *wi return; } if (view->presentation) { requisition->width = 1; requisition->height = 1; return; } + if (view->child) { + GtkRequisition child_requisition; + gtk_widget_size_request (view->child->widget, &child_requisition); + } + if(!(requisition->width == view->current_width && requisition->height == view->current_height)) { + /* FIXME: In the case we have a sizing mode other than EV_SIZING_FIT_*, since the + rendered page 'move' (it is centered) when we resize, we need to move + the child widgets too, like what we do in 'on_adjustment_value_changed'*/ + + form_field_widgets_resize(view); + } + view->current_width = requisition->width; + view->current_height = requisition->height; if (view->continuous && view->dual_page) ev_view_size_request_continuous_dual_page (view, requisition); else if (view->continuous) ev_view_size_request_continuous (view, requisition); else if (view->dual_page) ev_view_size_request_dual_page (view, requisition); else @@ -1597,16 +1653,20 @@ ev_view_size_request (GtkWidget *wi } static void ev_view_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { EvView *view = EV_VIEW (widget); + if (view->child) { + ev_view_allocate_child(view, view->child); + } + if (view->sizing_mode == EV_SIZING_FIT_WIDTH || view->sizing_mode == EV_SIZING_BEST_FIT) { g_signal_emit (view, signals[SIGNAL_ZOOM_INVALID], 0); ev_view_size_request (widget, &widget->requisition); } @@ -1657,16 +1717,22 @@ ev_view_realize (GtkWidget *widget) GDK_WA_VISUAL); gdk_window_set_user_data (widget->window, widget); widget->style = gtk_style_attach (widget->style, widget->window); if (view->presentation) gdk_window_set_background (widget->window, &widget->style->black); else gdk_window_set_background (widget->window, &widget->style->mid [GTK_STATE_NORMAL]); + + if (view->child) { + gtk_widget_set_parent_window(view->child->widget, GTK_WIDGET(view)->window); + ev_view_allocate_child(view, view->child); + } + } static gboolean ev_view_scroll_event (GtkWidget *widget, GdkEventScroll *event) { EvView *view = EV_VIEW (widget); guint state; @@ -1773,16 +1839,17 @@ ev_view_expose_event (GtkWidget *wi page_area.x -= view->scroll_x; page_area.y -= view->scroll_y; draw_one_page (view, i, &page_area, &border, &(event->area), &page_ready); if (page_ready && EV_IS_DOCUMENT_FIND (view->document)) highlight_find_results (view, i); } + (* GTK_WIDGET_CLASS (ev_view_parent_class)->expose_event) (widget, event); return FALSE; } static gboolean ev_view_popup_menu (GtkWidget *widget) { gint x, y; @@ -1821,16 +1888,17 @@ ev_view_button_press_event (GtkWidget } gtk_widget_queue_draw (widget); } view->selection_info.start.x = event->x + view->scroll_x; view->selection_info.start.y = event->y + view->scroll_y; + handle_click_at_location (view, event->x, event->y); return TRUE; case 2: /* use root coordinates as reference point because * scrolling changes window relative coordinates */ view->drag_info.start.x = event->x_root; view->drag_info.start.y = event->y_root; view->drag_info.hadj = gtk_adjustment_get_value (view->hadjustment); view->drag_info.vadj = gtk_adjustment_get_value (view->vadjustment); @@ -2014,16 +2082,17 @@ ev_view_motion_notify_event (GtkWidget return TRUE; } /* For the Evince 0.4.x release, we limit links to un-rotated documents * only. */ } else if (view->pressed_button <= 0 && view->rotation == 0) { handle_link_over_xy (view, x, y); + handle_form_field_over_xy (view, x, y); return TRUE; } return FALSE; } static gboolean ev_view_button_release_event (GtkWidget *widget, @@ -2299,16 +2368,19 @@ draw_one_page (EvView *view, real_page_area.height -= (border->top + border->bottom); *page_ready = TRUE; ev_document_misc_paint_one_page (GTK_WIDGET(view)->window, GTK_WIDGET (view), page_area, border, page == current_page); + + + if (gdk_rectangle_intersect (&real_page_area, expose_area, &overlap)) { GdkPixbuf *selection_pixbuf = NULL; GdkPixbuf *scaled_image; GdkPixbuf *scaled_selection; current_pixbuf = ev_pixbuf_cache_get_pixbuf (view->pixbuf_cache, page); /* Get the selection pixbuf iff we have something to draw */ @@ -2368,16 +2440,32 @@ draw_one_page (EvView *view, overlap.y - real_page_area.y, overlap.x, overlap.y, overlap.width, overlap.height, GDK_RGB_DITHER_NORMAL, 0, 0); g_object_unref (scaled_selection); } } + + { + int text_height, text_width; + PangoLayout* playout = gtk_widget_create_pango_layout(GTK_WIDGET(view), "Hello"); + PangoFontDescription* pfontdesc = pango_font_description_from_string("Sans 16"); + pango_layout_set_font_description(playout, pfontdesc); + pango_layout_get_pixel_size(playout, &text_width, &text_height); + + gdk_draw_layout(GTK_WIDGET(view)->window, + GTK_WIDGET (view)->style->fg_gc[GTK_STATE_NORMAL], + (gint)view->scroll_x+40, + (gint)view->scroll_y+40, + playout); + + } + } /*** GObject functions ***/ static void ev_view_finalize (GObject *object) { EvView *view = EV_VIEW (object); @@ -2537,23 +2625,25 @@ ev_view_get_property (GObject *object, } } static void ev_view_class_init (EvViewClass *class) { GObjectClass *object_class = G_OBJECT_CLASS (class); GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (class); + GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); GtkBindingSet *binding_set; object_class->finalize = ev_view_finalize; object_class->set_property = ev_view_set_property; object_class->get_property = ev_view_get_property; + widget_class->map = ev_view_map; widget_class->expose_event = ev_view_expose_event; widget_class->button_press_event = ev_view_button_press_event; widget_class->motion_notify_event = ev_view_motion_notify_event; widget_class->button_release_event = ev_view_button_release_event; widget_class->focus_in_event = ev_view_focus_in; widget_class->focus_out_event = ev_view_focus_out; widget_class->get_accessible = ev_view_get_accessible; widget_class->size_request = ev_view_size_request; @@ -2562,16 +2652,20 @@ ev_view_class_init (EvViewClass *class) widget_class->scroll_event = ev_view_scroll_event; widget_class->enter_notify_event = ev_view_enter_notify_event; widget_class->leave_notify_event = ev_view_leave_notify_event; widget_class->style_set = ev_view_style_set; widget_class->drag_data_get = ev_view_drag_data_get; widget_class->popup_menu = ev_view_popup_menu; gtk_object_class->destroy = ev_view_destroy; + container_class->add = ev_view_add; + container_class->remove = ev_view_remove; + container_class->forall = ev_view_forall; + 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), @@ -2708,16 +2802,19 @@ ev_view_class_init (EvViewClass *class) add_scroll_binding_keypad (binding_set, GDK_Down, GDK_MOD1_MASK, EV_SCROLL_STEP_UP, FALSE); } static void ev_view_init (EvView *view) { GTK_WIDGET_SET_FLAGS (view, GTK_CAN_FOCUS); + view->current_width = 0; + view->current_height = 0; + view->child = NULL; view->spacing = 5; view->scale = 1.0; view->current_page = 0; view->pressed_button = -1; view->cursor = EV_VIEW_CURSOR_NORMAL; view->drag_info.in_drag = FALSE; view->selection_info.selections = NULL; view->selection_info.in_selection = FALSE; @@ -2795,17 +2892,22 @@ static void on_adjustment_value_changed } if (view->vadjustment) { dy = view->scroll_y - (int) view->vadjustment->value; view->scroll_y = (int) view->vadjustment->value; } else { view->scroll_y = 0; } - + + /* move the childs widgets (form fields) in order they follow the window scrolling */ + if (view->child) { + ev_view_move_internal(view, view->child->widget, TRUE, view->child->x + dx, TRUE, view->child->y + dy); + } + if (view->pending_resize) gtk_widget_queue_draw (GTK_WIDGET (view)); else gdk_window_scroll (GTK_WIDGET (view)->window, dx, dy); if (view->document) @@ -4213,8 +4315,294 @@ ev_scroll_type_get_type (void) { EV_SCROLL_STEP_UP, "EV_SCROLL_STEP_UP", "scroll-step-up" }, { EV_SCROLL_STEP_DOWN, "EV_SCROLL_STEP_DOWN", "scroll-step-down" }, { 0, NULL, NULL } }; etype = g_enum_register_static ("EvScrollType", values); } return etype; } + +/*** 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; + GList *form_field_mapping; + 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; + + form_field_mapping = ev_pixbuf_cache_get_form_field_mapping (view->pixbuf_cache, page); + + if (form_field_mapping) + return ev_form_field_mapping_find (form_field_mapping, x_offset / view->scale, y_offset / view->scale); + else + return NULL; +} + +static void +handle_click_at_location (EvView *view, + gdouble x, + gdouble y) +{ + gint page = -1; + gint x_offset = 0, y_offset = 0; + GList *form_field_mapping; + EvFormField *new_field; + GtkWidget *wid; + EvPoint p[2]; + GdkPoint d[2]; + gint v[4]; + + + x += view->scroll_x; + y += view->scroll_y; + + find_page_at_location (view, x, y, &page, &x_offset, &y_offset); + + if (page == -1) + return; + + form_field_mapping = ev_pixbuf_cache_get_form_field_mapping (view->pixbuf_cache, page); + + if (!form_field_mapping) + return; + + new_field = ev_form_field_mapping_find (form_field_mapping, x_offset/view->scale, y_offset/view->scale); + + if (!new_field) + return; + + //store current entry text + if (view->child) { + if (GTK_IS_ENTRY(view->child->widget)) { + EvFormField *current_field = ev_form_field_mapping_find_by_id(form_field_mapping, view->child->field_id); + if(!current_field) { + g_warning ("unable to retriev field by id stored in child : %i", view->child->field_id); + } else { + current_field->content = g_strdup(gtk_entry_get_text(GTK_ENTRY(view->child->widget))); + } + } + } + + //clean current view widgets + ev_view_remove_all(GTK_CONTAINER(view)); + + + p[0].x = new_field->x1; + p[0].y = new_field->y1; + p[1].x = new_field->x2; + p[1].y = new_field->y2; + + doc_point_to_view_point (view, page, &p[0], &d[0]); + doc_point_to_view_point (view, page, &p[1], &d[1]); + + v[0] = d[0].x - view->scroll_x; v[1] = d[0].y - view->scroll_y; + v[2] = d[1].x - view->scroll_x; v[3] = d[1].y - view->scroll_y; + + switch (new_field->type) { + case EV_FORM_FIELD_TYPE_BUTTON: + wid = gtk_button_new_with_label("Button"); + break; + case EV_FORM_FIELD_TYPE_TEXT: + wid = gtk_entry_new(); + //check if we have content stored for this field + if (new_field->content != NULL) + gtk_entry_set_text(GTK_ENTRY(wid), new_field->content); + break; + case EV_FORM_FIELD_TYPE_CHOICE: + wid = gtk_label_new ("choice"); + break; + case EV_FORM_FIELD_TYPE_SIGNATURE: + wid = gtk_label_new ("signature"); + break; + default: + g_warning("Unknow field type %i, please fill a bug report with a test case.", new_field->type); + break; + } + + gtk_widget_set_usize(wid, v[2]-v[0], v[3]-v[1]); + ev_view_put(view, wid,v[0],v[1],p[0].x,p[0].y,p[1].x,p[1].y,page, new_field->id); + gtk_widget_show(wid); + + + +} + +static void +handle_form_field_over_xy (EvView *view, gint x, gint y) +{ + EvFormField *field; + + field = ev_view_get_form_field_at_location (view, x, y); + if(field) { + ev_view_set_cursor (view, EV_VIEW_CURSOR_LINK); + } else { + ev_view_set_cursor(view, EV_VIEW_CURSOR_NORMAL); + } +} + +static void +form_field_widgets_resize (EvView *view) +{ + GdkPoint d[2]; + gint v[4]; + EvViewChild *child = view->child; + + if(!child) + return; + + doc_point_to_view_point(view, child->page, &child->p[0], &d[0]); + doc_point_to_view_point(view, child->page, &child->p[1], &d[1]); + + v[0] = d[0].x - view->scroll_x; v[1] = d[0].y - view->scroll_y; + v[2] = d[1].x - view->scroll_x; v[3] = d[1].y - view->scroll_y; + + gtk_widget_set_usize(child->widget, v[2]-v[0], v[3]-v[1]); + ev_view_move_internal(view, child->widget, TRUE, v[0], TRUE, v[1]); + +} + +/*** Container ***/ +static void +ev_view_map (GtkWidget *widget) +{ + EvView *view = EV_VIEW(widget); + + GTK_WIDGET_SET_FLAGS(widget, GTK_MAPPED); + + if (view->child) { + if (GTK_WIDGET_VISIBLE(view->child->widget)) { + if (!GTK_WIDGET_MAPPED(view->child->widget)) { + gtk_widget_map(view->child->widget); + } + } + } + + gdk_window_show(GTK_WIDGET(view)->window); +} + +static void +ev_view_add (GtkContainer *cont, GtkWidget *widget) +{ + g_warning("Use ev_view_put instead of ev_view_add"); +} + +static void +ev_view_remove (GtkContainer *cont, GtkWidget *widget) +{ + EvView *view = EV_VIEW(cont); + if (view->child) { + if (view->child->widget == widget) { + gtk_widget_unparent(widget); + g_free(view->child); + view->child = NULL; + } + } +} + +static void +ev_view_remove_all (GtkContainer *cont) +{ + EvView *view = EV_VIEW(cont); + if (view->child) { + gtk_widget_unparent(view->child->widget); + g_free(view->child); + view->child = NULL; + } + +} + +static void +ev_view_put (EvView *view, GtkWidget *widget, gint x, gint y, double x1, double y1, double x2, double y2, gint page, int id) +{ + EvViewChild *child; + + if (view->child != NULL) { + g_warning("ev_view_put, a child already exists"); + } + + child = g_new(EvViewChild, 1); + child->widget = widget; + child->x = x; + child->y = y; + child->p[0].x = x1; + child->p[0].y = y1; + child->p[1].x = x2; + child->p[1].y = y2; + child->page = page; + child->field_id = id; + + view->child = child; + + if (GTK_WIDGET_REALIZED(view)) + gtk_widget_set_parent_window (widget, GTK_WIDGET(view)->window); + gtk_widget_set_parent(widget, GTK_WIDGET(view)); +} + +static void +ev_view_forall (GtkContainer *cont, gboolean include_internals, GtkCallback callback, gpointer callback_data) +{ + EvView *view = EV_VIEW(cont); + if(view->child) { + (*callback)(view->child->widget, callback_data); + } +} + +static EvViewChild* +get_child (EvView *view, GtkWidget *widget) +{ + if(view->child) { + if(view->child->widget == widget) { + return view->child; + } + } + return NULL; +} + +static void +ev_view_move_internal (EvView *view, GtkWidget *widget, gboolean change_x, gint x, gboolean change_y, gint y) +{ + EvViewChild *child; + child = get_child(view, widget); + + g_assert(child); + + gtk_widget_freeze_child_notify(widget); + + if(change_x) { + child->x = x; + gtk_widget_child_notify(widget, "x"); + } + if(change_y) { + child->y = y; + gtk_widget_child_notify(widget, "y"); + } + gtk_widget_thaw_child_notify(widget); + + if (GTK_WIDGET_VISIBLE(widget) && GTK_WIDGET_VISIBLE(view)) + gtk_widget_queue_resize (GTK_WIDGET(widget)); +} + +static void +ev_view_allocate_child (EvView *view, EvViewChild *child) +{ + GtkAllocation allocation; + GtkRequisition requisition; + allocation.x = child->x; + allocation.y = child->y; + gtk_widget_get_child_requisition (child->widget, &requisition); + allocation.width = requisition.width; + allocation.height = requisition.height; + + gtk_widget_size_allocate (child->widget, &allocation); +} + + Index: shell/ev-view.h =================================================================== RCS file: /cvs/gnome/evince/shell/ev-view.h,v retrieving revision 1.50 diff -u -8 -p -r1.50 ev-view.h --- shell/ev-view.h 2 May 2006 19:02:46 -0000 1.50 +++ shell/ev-view.h 12 Jun 2006 21:24:21 -0000 @@ -16,16 +16,17 @@ * 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_VIEW_H__ #define __EV_VIEW_H__ #include +#include #include "ev-document.h" #include "ev-link.h" #include "ev-view-accessible.h" G_BEGIN_DECLS #define EV_TYPE_VIEW (ev_view_get_type ())