accessible/src/atk/nsMaiHyperlink.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/accessible/src/atk/nsMaiHyperlink.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,259 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* vim: set ts=2 et sw=2 tw=80: */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#include "nsIURI.h"
    1.11 +#include "nsMaiHyperlink.h"
    1.12 +
    1.13 +using namespace mozilla::a11y;
    1.14 +
    1.15 +/* MaiAtkHyperlink */
    1.16 +
    1.17 +#define MAI_TYPE_ATK_HYPERLINK      (mai_atk_hyperlink_get_type ())
    1.18 +#define MAI_ATK_HYPERLINK(obj)      (G_TYPE_CHECK_INSTANCE_CAST ((obj),\
    1.19 +                                     MAI_TYPE_ATK_HYPERLINK, MaiAtkHyperlink))
    1.20 +#define MAI_ATK_HYPERLINK_CLASS(klass)  (G_TYPE_CHECK_CLASS_CAST ((klass),\
    1.21 +                                 MAI_TYPE_ATK_HYPERLINK, MaiAtkHyperlinkClass))
    1.22 +#define MAI_IS_ATK_HYPERLINK(obj)      (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\
    1.23 +                                        MAI_TYPE_ATK_HYPERLINK))
    1.24 +#define MAI_IS_ATK_HYPERLINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),\
    1.25 +                                        MAI_TYPE_ATK_HYPERLINK))
    1.26 +#define MAI_ATK_HYPERLINK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),\
    1.27 +                                 MAI_TYPE_ATK_HYPERLINK, MaiAtkHyperlinkClass))
    1.28 +
    1.29 +/**
    1.30 + * This MaiAtkHyperlink is a thin wrapper, in the MAI namespace,
    1.31 + * for AtkHyperlink
    1.32 + */
    1.33 +
    1.34 +struct MaiAtkHyperlink
    1.35 +{
    1.36 +    AtkHyperlink parent;
    1.37 +
    1.38 +    /*
    1.39 +     * The MaiHyperlink whose properties and features are exported via this
    1.40 +     * hyperlink instance.
    1.41 +     */
    1.42 +    MaiHyperlink *maiHyperlink;
    1.43 +};
    1.44 +
    1.45 +struct MaiAtkHyperlinkClass
    1.46 +{
    1.47 +    AtkHyperlinkClass parent_class;
    1.48 +};
    1.49 +
    1.50 +GType mai_atk_hyperlink_get_type(void);
    1.51 +
    1.52 +G_BEGIN_DECLS
    1.53 +/* callbacks for AtkHyperlink */
    1.54 +static void classInitCB(AtkHyperlinkClass *aClass);
    1.55 +static void finalizeCB(GObject *aObj);
    1.56 +
    1.57 +/* callbacks for AtkHyperlink virtual functions */
    1.58 +static gchar *getUriCB(AtkHyperlink *aLink, gint aLinkIndex);
    1.59 +static AtkObject *getObjectCB(AtkHyperlink *aLink, gint aLinkIndex);
    1.60 +static gint getEndIndexCB(AtkHyperlink *aLink);
    1.61 +static gint getStartIndexCB(AtkHyperlink *aLink);
    1.62 +static gboolean isValidCB(AtkHyperlink *aLink);
    1.63 +static gint getAnchorCountCB(AtkHyperlink *aLink);
    1.64 +G_END_DECLS
    1.65 +
    1.66 +static gpointer parent_class = nullptr;
    1.67 +static Accessible*
    1.68 +get_accessible_hyperlink(AtkHyperlink *aHyperlink);
    1.69 +
    1.70 +GType
    1.71 +mai_atk_hyperlink_get_type(void)
    1.72 +{
    1.73 +    static GType type = 0;
    1.74 +
    1.75 +    if (!type) {
    1.76 +        static const GTypeInfo tinfo = {
    1.77 +            sizeof(MaiAtkHyperlinkClass),
    1.78 +            (GBaseInitFunc)nullptr,
    1.79 +            (GBaseFinalizeFunc)nullptr,
    1.80 +            (GClassInitFunc)classInitCB,
    1.81 +            (GClassFinalizeFunc)nullptr,
    1.82 +            nullptr, /* class data */
    1.83 +            sizeof(MaiAtkHyperlink), /* instance size */
    1.84 +            0, /* nb preallocs */
    1.85 +            (GInstanceInitFunc)nullptr,
    1.86 +            nullptr /* value table */
    1.87 +        };
    1.88 +
    1.89 +        type = g_type_register_static(ATK_TYPE_HYPERLINK,
    1.90 +                                      "MaiAtkHyperlink",
    1.91 +                                      &tinfo, GTypeFlags(0));
    1.92 +    }
    1.93 +    return type;
    1.94 +}
    1.95 +
    1.96 +MaiHyperlink::MaiHyperlink(Accessible* aHyperLink) :
    1.97 +    mHyperlink(aHyperLink),
    1.98 +    mMaiAtkHyperlink(nullptr)
    1.99 +{
   1.100 +}
   1.101 +
   1.102 +MaiHyperlink::~MaiHyperlink()
   1.103 +{
   1.104 +    if (mMaiAtkHyperlink) {
   1.105 +        MAI_ATK_HYPERLINK(mMaiAtkHyperlink)->maiHyperlink = nullptr;
   1.106 +        g_object_unref(mMaiAtkHyperlink);
   1.107 +    }
   1.108 +}
   1.109 +
   1.110 +AtkHyperlink*
   1.111 +MaiHyperlink::GetAtkHyperlink(void)
   1.112 +{
   1.113 +  NS_ENSURE_TRUE(mHyperlink, nullptr);
   1.114 +
   1.115 +  if (mMaiAtkHyperlink)
   1.116 +    return mMaiAtkHyperlink;
   1.117 +
   1.118 +  if (!mHyperlink->IsLink())
   1.119 +    return nullptr;
   1.120 +
   1.121 +    mMaiAtkHyperlink =
   1.122 +        reinterpret_cast<AtkHyperlink *>
   1.123 +                        (g_object_new(mai_atk_hyperlink_get_type(), nullptr));
   1.124 +    NS_ASSERTION(mMaiAtkHyperlink, "OUT OF MEMORY");
   1.125 +    NS_ENSURE_TRUE(mMaiAtkHyperlink, nullptr);
   1.126 +
   1.127 +    /* be sure to initialize it with "this" */
   1.128 +    MaiHyperlink::Initialize(mMaiAtkHyperlink, this);
   1.129 +
   1.130 +    return mMaiAtkHyperlink;
   1.131 +}
   1.132 +
   1.133 +/* static */
   1.134 +
   1.135 +/* remember to call this static function when a MaiAtkHyperlink
   1.136 + * is created
   1.137 + */
   1.138 +
   1.139 +nsresult
   1.140 +MaiHyperlink::Initialize(AtkHyperlink *aObj, MaiHyperlink *aHyperlink)
   1.141 +{
   1.142 +    NS_ENSURE_ARG(MAI_IS_ATK_HYPERLINK(aObj));
   1.143 +    NS_ENSURE_ARG(aHyperlink);
   1.144 +
   1.145 +    /* initialize hyperlink */
   1.146 +    MAI_ATK_HYPERLINK(aObj)->maiHyperlink = aHyperlink;
   1.147 +    return NS_OK;
   1.148 +}
   1.149 +
   1.150 +/* static functions for ATK callbacks */
   1.151 +
   1.152 +void
   1.153 +classInitCB(AtkHyperlinkClass *aClass)
   1.154 +{
   1.155 +    GObjectClass *gobject_class = G_OBJECT_CLASS(aClass);
   1.156 +
   1.157 +    parent_class = g_type_class_peek_parent(aClass);
   1.158 +
   1.159 +    aClass->get_uri = getUriCB;
   1.160 +    aClass->get_object = getObjectCB;
   1.161 +    aClass->get_end_index = getEndIndexCB;
   1.162 +    aClass->get_start_index = getStartIndexCB;
   1.163 +    aClass->is_valid = isValidCB;
   1.164 +    aClass->get_n_anchors = getAnchorCountCB;
   1.165 +
   1.166 +    gobject_class->finalize = finalizeCB;
   1.167 +}
   1.168 +
   1.169 +void
   1.170 +finalizeCB(GObject *aObj)
   1.171 +{
   1.172 +    NS_ASSERTION(MAI_IS_ATK_HYPERLINK(aObj), "Invalid MaiAtkHyperlink");
   1.173 +    if (!MAI_IS_ATK_HYPERLINK(aObj))
   1.174 +        return;
   1.175 +
   1.176 +    MaiAtkHyperlink *maiAtkHyperlink = MAI_ATK_HYPERLINK(aObj);
   1.177 +    maiAtkHyperlink->maiHyperlink = nullptr;
   1.178 +
   1.179 +    /* call parent finalize function */
   1.180 +    if (G_OBJECT_CLASS (parent_class)->finalize)
   1.181 +        G_OBJECT_CLASS (parent_class)->finalize(aObj);
   1.182 +}
   1.183 +
   1.184 +gchar *
   1.185 +getUriCB(AtkHyperlink *aLink, gint aLinkIndex)
   1.186 +{
   1.187 +    Accessible* hyperlink = get_accessible_hyperlink(aLink);
   1.188 +    NS_ENSURE_TRUE(hyperlink, nullptr);
   1.189 +
   1.190 +    nsCOMPtr<nsIURI> uri = hyperlink->AnchorURIAt(aLinkIndex);
   1.191 +    if (!uri)
   1.192 +        return nullptr;
   1.193 +
   1.194 +    nsAutoCString cautoStr;
   1.195 +    nsresult rv = uri->GetSpec(cautoStr);
   1.196 +    NS_ENSURE_SUCCESS(rv, nullptr);
   1.197 +
   1.198 +    return g_strdup(cautoStr.get());
   1.199 +}
   1.200 +
   1.201 +AtkObject *
   1.202 +getObjectCB(AtkHyperlink *aLink, gint aLinkIndex)
   1.203 +{
   1.204 +    Accessible* hyperlink = get_accessible_hyperlink(aLink);
   1.205 +    NS_ENSURE_TRUE(hyperlink, nullptr);
   1.206 +
   1.207 +    Accessible* anchor = hyperlink->AnchorAt(aLinkIndex);
   1.208 +    NS_ENSURE_TRUE(anchor, nullptr);
   1.209 +
   1.210 +    AtkObject* atkObj = AccessibleWrap::GetAtkObject(anchor);
   1.211 +    //no need to add ref it, because it is "get" not "ref"
   1.212 +    return atkObj;
   1.213 +}
   1.214 +
   1.215 +gint
   1.216 +getEndIndexCB(AtkHyperlink *aLink)
   1.217 +{
   1.218 +    Accessible* hyperlink = get_accessible_hyperlink(aLink);
   1.219 +    NS_ENSURE_TRUE(hyperlink, -1);
   1.220 +
   1.221 +    return static_cast<gint>(hyperlink->EndOffset());
   1.222 +}
   1.223 +
   1.224 +gint
   1.225 +getStartIndexCB(AtkHyperlink *aLink)
   1.226 +{
   1.227 +    Accessible* hyperlink = get_accessible_hyperlink(aLink);
   1.228 +    NS_ENSURE_TRUE(hyperlink, -1);
   1.229 +
   1.230 +    return static_cast<gint>(hyperlink->StartOffset());
   1.231 +}
   1.232 +
   1.233 +gboolean
   1.234 +isValidCB(AtkHyperlink *aLink)
   1.235 +{
   1.236 +    Accessible* hyperlink = get_accessible_hyperlink(aLink);
   1.237 +    NS_ENSURE_TRUE(hyperlink, FALSE);
   1.238 +
   1.239 +    return static_cast<gboolean>(hyperlink->IsLinkValid());
   1.240 +}
   1.241 +
   1.242 +gint
   1.243 +getAnchorCountCB(AtkHyperlink *aLink)
   1.244 +{
   1.245 +    Accessible* hyperlink = get_accessible_hyperlink(aLink);
   1.246 +    NS_ENSURE_TRUE(hyperlink, -1);
   1.247 +
   1.248 +    return static_cast<gint>(hyperlink->AnchorCount());
   1.249 +}
   1.250 +
   1.251 +// Check if aHyperlink is a valid MaiHyperlink, and return the
   1.252 +// HyperLinkAccessible related.
   1.253 +Accessible*
   1.254 +get_accessible_hyperlink(AtkHyperlink *aHyperlink)
   1.255 +{
   1.256 +    NS_ENSURE_TRUE(MAI_IS_ATK_HYPERLINK(aHyperlink), nullptr);
   1.257 +    MaiHyperlink * maiHyperlink =
   1.258 +        MAI_ATK_HYPERLINK(aHyperlink)->maiHyperlink;
   1.259 +    NS_ENSURE_TRUE(maiHyperlink != nullptr, nullptr);
   1.260 +    NS_ENSURE_TRUE(maiHyperlink->GetAtkHyperlink() == aHyperlink, nullptr);
   1.261 +    return maiHyperlink->GetAccHyperlink();
   1.262 +}

mercurial