From: Marco Pesenti Gritti Date: Wed, 7 Sep 2005 12:36:54 +0000 (+0000) Subject: Implement xyz links, still not functional. Links are a total mess, will X-Git-Tag: EVINCE_0_5_0~178 X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=commitdiff_plain;h=9f8ec2d921de1c31da212c8486ab2bda85d51bf9;p=evince.git Implement xyz links, still not functional. Links are a total mess, will 2005-09-07 Marco Pesenti Gritti * backend/ev-document.h: * backend/ev-link.c: (ev_link_type_get_type), (ev_link_get_top), (ev_link_get_left), (ev_link_get_zoom), (ev_link_get_property), (ev_link_set_property), (ev_window_dispose), (ev_link_class_init), (ev_link_new_page), (ev_link_new_page_xyz): * backend/ev-link.h: * pdf/ev-poppler.cc: * shell/ev-view.c: (doc_point_to_view_point), (scroll_to_xyz_link), (go_to_link), (tip_from_link): Implement xyz links, still not functional. Links are a total mess, will need to refactor and bugfix a lot :( --- diff --git a/ChangeLog b/ChangeLog index bf36d1d7..d1765274 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2005-09-07 Marco Pesenti Gritti + + * backend/ev-document.h: + * backend/ev-link.c: (ev_link_type_get_type), (ev_link_get_top), + (ev_link_get_left), (ev_link_get_zoom), (ev_link_get_property), + (ev_link_set_property), (ev_window_dispose), (ev_link_class_init), + (ev_link_new_page), (ev_link_new_page_xyz): + * backend/ev-link.h: + * pdf/ev-poppler.cc: + * shell/ev-view.c: (doc_point_to_view_point), (scroll_to_xyz_link), + (go_to_link), (tip_from_link): + + Implement xyz links, still not functional. Links are a total + mess, will need to refactor and bugfix a lot :( + 2005-09-05 Alessio Frusciante * configure.ac: Added "it" (Italian) to ALL_LINGUAS. diff --git a/backend/ev-document.h b/backend/ev-document.h index 2629a47f..2cea42f3 100644 --- a/backend/ev-document.h +++ b/backend/ev-document.h @@ -56,6 +56,11 @@ typedef enum EV_DOCUMENT_ERROR_ENCRYPTED } EvDocumentError; +typedef struct { + double x; + double y; +} EvPoint; + typedef struct { double x1; double y1; diff --git a/backend/ev-link.c b/backend/ev-link.c index ee54b285..9016ec0d 100644 --- a/backend/ev-link.c +++ b/backend/ev-link.c @@ -29,7 +29,10 @@ enum { PROP_TITLE, PROP_TYPE, PROP_PAGE, - PROP_URI + PROP_URI, + PROP_LEFT, + PROP_TOP, + PROP_ZOOM }; @@ -47,6 +50,9 @@ struct _EvLinkPrivate { char *uri; EvLinkType type; int page; + double top; + double left; + double zoom; }; G_DEFINE_TYPE (EvLink, ev_link, G_TYPE_OBJECT) @@ -63,6 +69,7 @@ ev_link_type_get_type (void) static const GEnumValue values[] = { { EV_LINK_TYPE_TITLE, "EV_LINK_TYPE_TITLE", "title" }, { EV_LINK_TYPE_PAGE, "EV_LINK_TYPE_PAGE", "page" }, + { EV_LINK_TYPE_PAGE_XYZ, "EV_LINK_TYPE_PAGE_XYZ", "page-xyz" }, { EV_LINK_TYPE_EXTERNAL_URI, "EV_LINK_TYPE_EXTERNAL_URI", "external" }, { 0, NULL, NULL } }; @@ -81,22 +88,6 @@ ev_link_get_title (EvLink *self) return self->priv->title; } -void -ev_link_set_title (EvLink* self, const char *title) -{ - g_assert (EV_IS_LINK (self)); - - if (self->priv->title != NULL) { - g_free (self->priv->title); - } - if (title) - self->priv->title = g_strdup (title); - else - self->priv->title = NULL; - - g_object_notify (G_OBJECT (self), "title"); -} - const char * ev_link_get_uri (EvLink *self) { @@ -105,21 +96,6 @@ ev_link_get_uri (EvLink *self) return self->priv->uri; } -void -ev_link_set_uri (EvLink* self, const char *uri) -{ - g_assert (EV_IS_LINK (self)); - g_assert (uri != NULL); - - if (self->priv->uri != NULL) { - g_free (self->priv->uri); - } - - self->priv->uri = g_strdup (uri); - - g_object_notify (G_OBJECT (self), "uri"); -} - EvLinkType ev_link_get_link_type (EvLink *self) { @@ -128,16 +104,6 @@ ev_link_get_link_type (EvLink *self) return self->priv->type; } -void -ev_link_set_link_type (EvLink* self, EvLinkType type) -{ - g_assert (EV_IS_LINK (self)); - - self->priv->type = type; - - g_object_notify (G_OBJECT (self), "type"); -} - int ev_link_get_page (EvLink *self) { @@ -146,14 +112,28 @@ ev_link_get_page (EvLink *self) return self->priv->page; } -void -ev_link_set_page (EvLink* self, int page) +double +ev_link_get_top (EvLink *self) { - g_assert (EV_IS_LINK (self)); + g_return_val_if_fail (EV_IS_LINK (self), 0); + + return self->priv->top; +} - self->priv->page = page; +double +ev_link_get_left (EvLink *self) +{ + g_return_val_if_fail (EV_IS_LINK (self), 0); + + return self->priv->left; +} - g_object_notify (G_OBJECT (self), "page"); +double +ev_link_get_zoom (EvLink *self) +{ + g_return_val_if_fail (EV_IS_LINK (self), 0); + + return self->priv->zoom; } static void @@ -177,6 +157,15 @@ ev_link_get_property (GObject *object, guint prop_id, GValue *value, case PROP_PAGE: g_value_set_int (value, self->priv->page); break; + case PROP_TOP: + g_value_set_double (value, self->priv->top); + break; + case PROP_LEFT: + g_value_set_double (value, self->priv->left); + break; + case PROP_ZOOM: + g_value_set_double (value, self->priv->zoom); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, @@ -189,23 +178,31 @@ static void ev_link_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *param_spec) { - EvLink *self; - - self = EV_LINK (object); + EvLink *link = EV_LINK (object); switch (prop_id) { case PROP_TITLE: - ev_link_set_title (self, g_value_get_string (value)); + link->priv->title = g_strdup (g_value_get_string (value)); break; case PROP_URI: - ev_link_set_uri (self, g_value_get_string (value)); + link->priv->uri = g_strdup (g_value_get_string (value)); break; case PROP_TYPE: - ev_link_set_link_type (self, g_value_get_enum (value)); + link->priv->type = g_value_get_enum (value); break; case PROP_PAGE: - ev_link_set_page (self, g_value_get_int (value)); + link->priv->page = g_value_get_int (value); + break; + case PROP_TOP: + link->priv->top = g_value_get_double (value); + break; + case PROP_LEFT: + link->priv->left = g_value_get_double (value); + break; + case PROP_ZOOM: + link->priv->zoom = g_value_get_double (value); break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, @@ -228,6 +225,11 @@ ev_window_dispose (GObject *object) priv->title = NULL; } + if (priv->uri) { + g_free (priv->uri); + priv->uri = NULL; + } + G_OBJECT_CLASS (ev_link_parent_class)->dispose (object); } @@ -257,16 +259,16 @@ ev_link_class_init (EvLinkClass *ev_window_class) "Link Title", "The link title", NULL, - G_PARAM_READWRITE)); - + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (g_object_class, PROP_URI, g_param_spec_string ("uri", "Link URI", "The link URI", NULL, - G_PARAM_READWRITE)); - + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (g_object_class, PROP_TYPE, g_param_spec_enum ("type", @@ -274,8 +276,8 @@ ev_link_class_init (EvLinkClass *ev_window_class) "The link type", EV_TYPE_LINK_TYPE, EV_LINK_TYPE_TITLE, - G_PARAM_READWRITE)); - + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (g_object_class, PROP_PAGE, g_param_spec_int ("page", @@ -284,7 +286,38 @@ ev_link_class_init (EvLinkClass *ev_window_class) -1, G_MAXINT, 0, - G_PARAM_READWRITE)); + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (g_object_class, + PROP_LEFT, + g_param_spec_double ("left", + "Left coordinate", + "The left coordinate", + 0, + G_MAXDOUBLE, + 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (g_object_class, + PROP_TOP, + g_param_spec_double ("top", + "Top coordinate", + "The top coordinate", + 0, + G_MAXDOUBLE, + 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (g_object_class, + PROP_ZOOM, + g_param_spec_double ("zoom", + "Zoom", + "Zoom", + 0, + G_MAXDOUBLE, + 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); } EvLink * @@ -306,6 +339,23 @@ ev_link_new_page (const char *title, int page) NULL)); } +EvLink * +ev_link_new_page_xyz (const char *title, + int page, + double top, + double left, + double zoom) +{ + return EV_LINK (g_object_new (EV_TYPE_LINK, + "title", title, + "page", page, + "type", EV_LINK_TYPE_PAGE_XYZ, + "left", left, + "top", top, + "zoom", zoom, + NULL)); +} + EvLink * ev_link_new_external (const char *title, const char *uri) { diff --git a/backend/ev-link.h b/backend/ev-link.h index b79e2fa4..8ee84294 100644 --- a/backend/ev-link.h +++ b/backend/ev-link.h @@ -43,6 +43,7 @@ typedef enum { EV_LINK_TYPE_TITLE, EV_LINK_TYPE_PAGE, + EV_LINK_TYPE_PAGE_XYZ, EV_LINK_TYPE_EXTERNAL_URI, /* We'll probably fill this in more as we support the other types of * links */ @@ -54,20 +55,21 @@ GType ev_link_get_type (void); EvLink *ev_link_new_title (const char *title); EvLink *ev_link_new_page (const char *title, int page); +EvLink *ev_link_new_page_xyz (const char *title, + int page, + double top, + double left, + double zoom); EvLink *ev_link_new_external (const char *title, const char *uri); + const char *ev_link_get_title (EvLink *link); -void ev_link_set_title (EvLink *link, - const char *title); const char *ev_link_get_uri (EvLink *link); -void ev_link_set_uri (EvLink *link, - const char *uri); EvLinkType ev_link_get_link_type (EvLink *link); -void ev_link_set_link_type (EvLink *link, - EvLinkType type); int ev_link_get_page (EvLink *link); -void ev_link_set_page (EvLink *link, - int page); +double ev_link_get_top (EvLink *link); +double ev_link_get_left (EvLink *link); +double ev_link_get_zoom (EvLink *link); /* Link Mapping stuff */ diff --git a/pdf/ev-poppler.cc b/pdf/ev-poppler.cc index bbcb9781..769c78a7 100644 --- a/pdf/ev-poppler.cc +++ b/pdf/ev-poppler.cc @@ -703,18 +703,94 @@ pdf_document_links_has_document_links (EvDocumentLinks *document_links) } static EvLink * -ev_link_from_action (PopplerAction *action) +ev_link_from_dest (PopplerAction *action) { EvLink *link; + const char *unimplemented_dest = NULL; + + switch (action->goto_dest.dest->type) { + case POPPLER_DEST_UNKNOWN: + unimplemented_dest = "POPPLER_DEST_UNKNOWN"; + break; + case POPPLER_DEST_XYZ: + link = ev_link_new_page_xyz (action->any.title, + action->goto_dest.dest->page_num - 1, + action->goto_dest.dest->left, + action->goto_dest.dest->top, + action->goto_dest.dest->zoom); + break; + case POPPLER_DEST_FIT: + unimplemented_dest = "POPPLER_DEST_FIT"; + break; + case POPPLER_DEST_FITH: + unimplemented_dest = "POPPLER_DEST_FITH"; + break; + case POPPLER_DEST_FITV: + unimplemented_dest = "POPPLER_DEST_FITV"; + break; + case POPPLER_DEST_FITR: + unimplemented_dest = "POPPLER_DEST_FITR"; + break; + case POPPLER_DEST_FITB: + unimplemented_dest = "POPPLER_DEST_FITB"; + break; + case POPPLER_DEST_FITBH: + unimplemented_dest = "POPPLER_DEST_FITBH"; + break; + case POPPLER_DEST_FITBV: + unimplemented_dest = "POPPLER_DEST_FITBV"; + break; + } + + if (unimplemented_dest) { + g_warning ("Unimplemented destination: %s, please post a bug report with a testcase.", + unimplemented_dest); + } + + link = ev_link_new_page (action->any.title, action->goto_dest.dest->page_num - 1); + + return link; +} + +static EvLink * +ev_link_from_action (PopplerAction *action) +{ + EvLink *link = NULL; const char *title; + const char *unimplemented_action = NULL; title = action->any.title; - - if (action->type == POPPLER_ACTION_GOTO_DEST) { - link = ev_link_new_page (title, action->goto_dest.dest->page_num - 1); - } else if (action->type == POPPLER_ACTION_URI) { + + switch (action->type) { + case POPPLER_ACTION_UNKNOWN: + g_warning ("Unknown action"); + break; + case POPPLER_ACTION_GOTO_DEST: + link = ev_link_from_dest (action); + break; + case POPPLER_ACTION_GOTO_REMOTE: + unimplemented_action = "POPPLER_ACTION_GOTO_REMOTE"; + break; + case POPPLER_ACTION_LAUNCH: + unimplemented_action = "POPPLER_ACTION_LAUNCH"; + break; + case POPPLER_ACTION_URI: link = ev_link_new_external (title, action->uri.uri); - } else { + break; + case POPPLER_ACTION_NAMED: + unimplemented_action = "POPPLER_ACTION_NAMED"; + break; + case POPPLER_ACTION_MOVIE: + unimplemented_action = "POPPLER_ACTION_MOVIE"; + break; + } + + if (unimplemented_action) { + g_warning ("Unimplemented action: %s, please post a bug report with a testcase.", + unimplemented_action); + } + + if (link == NULL) { link = ev_link_new_title (title); } diff --git a/shell/ev-view.c b/shell/ev-view.c index 2edcd858..052529eb 100644 --- a/shell/ev-view.c +++ b/shell/ev-view.c @@ -922,6 +922,44 @@ view_rect_to_doc_rect (EvView *view, doc_rect->y2 = doc_rect->y1 + (double) view_rect->height / view->scale; } +static void +doc_point_to_view_point (EvView *view, + int page, + EvPoint *doc_point, + GdkPoint *view_point) +{ + GdkRectangle page_area; + GtkBorder border; + double x, y; + int width, height; + + ev_page_cache_get_size (view->page_cache, page, + view->rotation, + 1.0, + &width, &height); + + if (view->rotation == 0) { + x = doc_point->x; + y = doc_point->y; + } else if (view->rotation == 90) { + x = width - doc_point->y; + y = doc_point->x; + } else if (view->rotation == 180) { + x = width - doc_point->x; + y = height - doc_point->y; + } else if (view->rotation == 270) { + x = doc_point->y; + y = height - doc_point->x; + } else { + g_assert_not_reached (); + } + + get_page_extents (view, page, &page_area, &border); + + view_point->x = x * view->scale + page_area.x; + view_point->y = y * view->scale + page_area.y; +} + static void doc_rect_to_view_rect (EvView *view, int page, @@ -1053,7 +1091,22 @@ get_link_at_location (EvView *view, return NULL; } -/* FIXME: standardize this sometime */ +static void +scroll_to_xyz_link (EvView *view, EvLink *link) +{ + GdkPoint view_point; + EvPoint doc_point; + + doc_point.x = ev_link_get_left (link); + doc_point.y = ev_link_get_top (link); + + doc_point_to_view_point (view, ev_link_get_page (link), + &doc_point, &view_point); + + gtk_adjustment_set_value (view->hadjustment, view_point.x); + gtk_adjustment_set_value (view->vadjustment, view_point.y); +} + static void go_to_link (EvView *view, EvLink *link) { @@ -1070,6 +1123,9 @@ go_to_link (EvView *view, EvLink *link) page = ev_link_get_page (link); ev_page_cache_set_current_page (view->page_cache, page); break; + case EV_LINK_TYPE_PAGE_XYZ: + scroll_to_xyz_link (view, link); + break; case EV_LINK_TYPE_EXTERNAL_URI: uri = ev_link_get_uri (link); gnome_vfs_url_show (uri); @@ -1092,6 +1148,7 @@ tip_from_link (EvView *view, EvLink *link) msg = g_strdup (ev_link_get_title (link)); break; case EV_LINK_TYPE_PAGE: + case EV_LINK_TYPE_PAGE_XYZ: page_label = ev_page_cache_get_page_label (view->page_cache, ev_link_get_page (link)); msg = g_strdup_printf (_("Go to page %s"), page_label); g_free (page_label);