Skip to content

Commit

Permalink
libview: Implement AtkHypertext interface
Browse files Browse the repository at this point in the history
  • Loading branch information
Carlos Garcia Campos committed Jan 20, 2013
1 parent b645f0f commit 6c1d1a2
Show file tree
Hide file tree
Showing 4 changed files with 449 additions and 8 deletions.
2 changes: 2 additions & 0 deletions libview/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ lib_LTLIBRARIES = libevview3.la

NOINST_H_SRC_FILES = \
ev-annotation-window.h \
ev-link-accessible.h \
ev-page-cache.h \
ev-pixbuf-cache.h \
ev-timeline.h \
Expand Down Expand Up @@ -34,6 +35,7 @@ libevview3_la_SOURCES = \
ev-document-model.c \
ev-jobs.c \
ev-job-scheduler.c \
ev-link-accessible.c \
ev-page-cache.c \
ev-pixbuf-cache.c \
ev-print-operation.c \
Expand Down
260 changes: 260 additions & 0 deletions libview/ev-link-accessible.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
/* -*- 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) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

#include <config.h>

#include "ev-link-accessible.h"
#include "ev-view-private.h"

typedef struct _EvHyperlink EvHyperlink;
typedef struct _EvHyperlinkClass EvHyperlinkClass;

struct _EvLinkAccessiblePrivate {
EvViewAccessible *view;
EvLink *link;
EvRectangle area;

EvHyperlink *hyperlink;
};

struct _EvHyperlink {
AtkHyperlink parent;

EvLinkAccessible *link_impl;
};

struct _EvHyperlinkClass {
AtkHyperlinkClass parent_class;
};

#define EV_TYPE_HYPERLINK (ev_hyperlink_get_type ())
#define EV_HYPERLINK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EV_TYPE_HYPERLINK, EvHyperlink))

static GType ev_hyperlink_get_type (void);

G_DEFINE_TYPE (EvHyperlink, ev_hyperlink, ATK_TYPE_HYPERLINK)

static gchar *
ev_hyperlink_get_uri (AtkHyperlink *atk_hyperlink,
gint i)
{
EvHyperlink *hyperlink = EV_HYPERLINK (atk_hyperlink);
EvLinkAccessiblePrivate *impl_priv;
EvLinkAction *action;

if (!hyperlink->link_impl)
return NULL;

impl_priv = hyperlink->link_impl->priv;
action = ev_link_get_action (impl_priv->link);

return action ? g_strdup (ev_link_action_get_uri (action)) : NULL;
}

static gint
ev_hyperlink_get_n_anchors (AtkHyperlink *atk_hyperlink)
{
return 1;
}

static gboolean
ev_hyperlink_is_valid (AtkHyperlink *atk_hyperlink)
{
return TRUE;
}

static AtkObject *
ev_hyperlink_get_object (AtkHyperlink *atk_hyperlink,
gint i)
{
EvHyperlink *hyperlink = EV_HYPERLINK (atk_hyperlink);

return hyperlink->link_impl ? ATK_OBJECT (hyperlink->link_impl) : NULL;
}

static gint
ev_hyperlink_get_start_index (AtkHyperlink *atk_hyperlink)
{
EvHyperlink *hyperlink = EV_HYPERLINK (atk_hyperlink);
EvLinkAccessiblePrivate *impl_priv;
GtkWidget *widget;
EvView *view;
EvRectangle *areas = NULL;
guint n_areas = 0;
guint i;

if (!hyperlink->link_impl)
return -1;

impl_priv = hyperlink->link_impl->priv;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (impl_priv->view));
if (widget == NULL)
/* State is defunct */
return -1;

view = EV_VIEW (widget);
if (!view->page_cache)
return -1;

ev_page_cache_get_text_layout (view->page_cache, view->current_page, &areas, &n_areas);
if (!areas)
return -1;

for (i = 0; i < n_areas; i++) {
EvRectangle *rect = areas + i;
gdouble c_x, c_y;

c_x = rect->x1 + (rect->x2 - rect->x1) / 2.;
c_y = rect->y1 + (rect->y2 - rect->y1) / 2.;
if (c_x >= impl_priv->area.x1 && c_x <= impl_priv->area.x2 &&
c_y >= impl_priv->area.y1 && c_y <= impl_priv->area.y2)
return i;
}

return -1;
}

static gint
ev_hyperlink_get_end_index (AtkHyperlink *atk_hyperlink)
{
EvHyperlink *hyperlink = EV_HYPERLINK (atk_hyperlink);
EvLinkAccessiblePrivate *impl_priv;
GtkWidget *widget;
EvView *view;
EvRectangle *areas = NULL;
guint n_areas = 0;
guint i;

if (!hyperlink->link_impl)
return -1;

impl_priv = hyperlink->link_impl->priv;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (impl_priv->view));
if (widget == NULL)
/* State is defunct */
return -1;

view = EV_VIEW (widget);
if (!view->page_cache)
return -1;

ev_page_cache_get_text_layout (view->page_cache, view->current_page, &areas, &n_areas);
if (!areas)
return -1;

for (i = n_areas - 1; i >= 0; i--) {
EvRectangle *rect = areas + i;
gdouble c_x, c_y;

c_x = rect->x1 + (rect->x2 - rect->x1) / 2.;
c_y = rect->y1 + (rect->y2 - rect->y1) / 2.;
if (c_x >= impl_priv->area.x1 && c_x <= impl_priv->area.x2 &&
c_y >= impl_priv->area.y1 && c_y <= impl_priv->area.y2)
return i;
}

return -1;
}

static void
ev_hyperlink_class_init (EvHyperlinkClass *klass)
{
AtkHyperlinkClass *atk_link_class = ATK_HYPERLINK_CLASS (klass);

atk_link_class->get_uri = ev_hyperlink_get_uri;
atk_link_class->get_n_anchors = ev_hyperlink_get_n_anchors;
atk_link_class->is_valid = ev_hyperlink_is_valid;
atk_link_class->get_object = ev_hyperlink_get_object;
atk_link_class->get_start_index = ev_hyperlink_get_start_index;
atk_link_class->get_end_index = ev_hyperlink_get_end_index;
}

static void
ev_hyperlink_init (EvHyperlink *link)
{
}

static void ev_link_accessible_hyperlink_impl_iface_init (AtkHyperlinkImplIface *iface);

G_DEFINE_TYPE_WITH_CODE (EvLinkAccessible, ev_link_accessible, ATK_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (ATK_TYPE_HYPERLINK_IMPL, ev_link_accessible_hyperlink_impl_iface_init))

static void
ev_link_accessible_finalize (GObject *object)
{
EvLinkAccessible *link = EV_LINK_ACCESSIBLE (object);

g_clear_object (&link->priv->hyperlink);

G_OBJECT_CLASS (ev_link_accessible_parent_class)->finalize (object);
}

static void
ev_link_accessible_class_init (EvLinkAccessibleClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);

object_class->finalize = ev_link_accessible_finalize;

g_type_class_add_private (klass, sizeof (EvLinkAccessiblePrivate));
}

static void
ev_link_accessible_init (EvLinkAccessible *link)
{
link->priv = G_TYPE_INSTANCE_GET_PRIVATE (link, EV_TYPE_LINK_ACCESSIBLE, EvLinkAccessiblePrivate);
}

static AtkHyperlink *
ev_link_accessible_get_hyperlink (AtkHyperlinkImpl *hyperlink_impl)
{
EvLinkAccessible *link = EV_LINK_ACCESSIBLE (hyperlink_impl);

if (link->priv->hyperlink)
return ATK_HYPERLINK (link->priv->hyperlink);

link->priv->hyperlink = g_object_new (EV_TYPE_HYPERLINK, NULL);

link->priv->hyperlink->link_impl = link;
g_object_add_weak_pointer (G_OBJECT (link), (gpointer *)&link->priv->hyperlink->link_impl);

return ATK_HYPERLINK (link->priv->hyperlink);
}

static void
ev_link_accessible_hyperlink_impl_iface_init (AtkHyperlinkImplIface *iface)
{
iface->get_hyperlink = ev_link_accessible_get_hyperlink;
}

EvLinkAccessible *
ev_link_accessible_new (EvViewAccessible *view,
EvLink *link,
EvRectangle *area)
{
EvLinkAccessible *atk_link;

atk_link = g_object_new (EV_TYPE_LINK_ACCESSIBLE, NULL);
atk_link->priv->view = view;
atk_link->priv->link = g_object_ref (link);
atk_link->priv->area = *area;

return EV_LINK_ACCESSIBLE (atk_link);
}
56 changes: 56 additions & 0 deletions libview/ev-link-accessible.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/* -*- 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) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

#if !defined (EVINCE_COMPILATION)
#error "This is a private header."
#endif

#ifndef __EV_LINK_ACCESSIBLE_H__
#define __EV_LINK_ACCESSIBLE_H__

#include <gtk/gtk-a11y.h>
#include "ev-view-accessible.h"
#include "ev-link.h"

#define EV_TYPE_LINK_ACCESSIBLE (ev_link_accessible_get_type ())
#define EV_LINK_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EV_TYPE_LINK_ACCESSIBLE, EvLinkAccessible))
#define EV_IS_LINK_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EV_TYPE_LINK_ACCESSIBLE))

typedef struct _EvLinkAccessible EvLinkAccessible;
typedef struct _EvLinkAccessibleClass EvLinkAccessibleClass;
typedef struct _EvLinkAccessiblePrivate EvLinkAccessiblePrivate;

struct _EvLinkAccessible {
AtkObject parent;

EvLinkAccessiblePrivate *priv;
};

struct _EvLinkAccessibleClass {
AtkObjectClass parent_class;
};

GType ev_link_accessible_get_type (void);
EvLinkAccessible *ev_link_accessible_new (EvViewAccessible *view,
EvLink *link,
EvRectangle *area);

#endif /* __EV_LINK_ACCESSIBLE_H__ */

Loading

0 comments on commit 6c1d1a2

Please sign in to comment.