Back to index

unity  6.0.0
unity-quicklist-menu-item-accessible.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2011 Canonical Ltd
00003  *
00004  * This program is free software: you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License version 3 as
00006  * published by the Free Software Foundation.
00007  *
00008  * This program is distributed in the hope that it will be useful,
00009  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00010  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011  * GNU General Public License for more details.
00012  *
00013  * You should have received a copy of the GNU General Public License
00014  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00015  *
00016  * Authored by: Alejandro PiƱeiro Iglesias <apinheiro@igalia.com>
00017  */
00018 
00031 #include <glib/gi18n.h>
00032 
00033 #include "unity-quicklist-menu-item-accessible.h"
00034 
00035 #include "unitya11y.h"
00036 #include "QuicklistMenuItem.h"
00037 #include "QuicklistMenuItemLabel.h"
00038 #include "QuicklistMenuItemSeparator.h"
00039 
00040 /* GObject */
00041 static void unity_quicklist_menu_item_accessible_class_init(UnityQuicklistMenuItemAccessibleClass* klass);
00042 static void unity_quicklist_menu_item_accessible_init(UnityQuicklistMenuItemAccessible* self);
00043 static void unity_quicklist_menu_item_accessible_dispose(GObject* object);
00044 
00045 /* AtkObject.h */
00046 static void         unity_quicklist_menu_item_accessible_initialize(AtkObject* accessible,
00047                                                                     gpointer   data);
00048 static const gchar* unity_quicklist_menu_item_accessible_get_name(AtkObject* obj);
00049 static AtkStateSet* unity_quicklist_menu_item_accessible_ref_state_set(AtkObject* obj);
00050 
00051 /* private */
00052 static void on_parent_selection_change_cb(AtkSelection* selection,
00053                                           gpointer data);
00054 
00055 G_DEFINE_TYPE(UnityQuicklistMenuItemAccessible, unity_quicklist_menu_item_accessible,  NUX_TYPE_VIEW_ACCESSIBLE);
00056 
00057 
00058 #define UNITY_QUICKLIST_MENU_ITEM_ACCESSIBLE_GET_PRIVATE(obj)           \
00059   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), UNITY_TYPE_QUICKLIST_MENU_ITEM_ACCESSIBLE, \
00060                                 UnityQuicklistMenuItemAccessiblePrivate))
00061 
00062 struct _UnityQuicklistMenuItemAccessiblePrivate
00063 {
00064   gboolean selected;
00065 
00066   guint on_parent_selection_change_id;
00067   guint on_parent_change_id;
00068 };
00069 
00070 using unity::QuicklistMenuItem;
00071 using unity::QuicklistMenuItemLabel;
00072 using unity::QuicklistMenuItemSeparator;
00073 
00074 static void
00075 unity_quicklist_menu_item_accessible_class_init(UnityQuicklistMenuItemAccessibleClass* klass)
00076 {
00077   GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
00078   AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
00079 
00080   gobject_class->dispose = unity_quicklist_menu_item_accessible_dispose;
00081 
00082   /* AtkObject */
00083   atk_class->get_name = unity_quicklist_menu_item_accessible_get_name;
00084   atk_class->initialize = unity_quicklist_menu_item_accessible_initialize;
00085   atk_class->ref_state_set = unity_quicklist_menu_item_accessible_ref_state_set;
00086 
00087   g_type_class_add_private(gobject_class, sizeof(UnityQuicklistMenuItemAccessiblePrivate));
00088 }
00089 
00090 static void
00091 unity_quicklist_menu_item_accessible_init(UnityQuicklistMenuItemAccessible* self)
00092 {
00093   UnityQuicklistMenuItemAccessiblePrivate* priv =
00094     UNITY_QUICKLIST_MENU_ITEM_ACCESSIBLE_GET_PRIVATE(self);
00095 
00096   self->priv = priv;
00097 }
00098 
00099 static void
00100 unity_quicklist_menu_item_accessible_dispose(GObject* object)
00101 {
00102   UnityQuicklistMenuItemAccessible* self = UNITY_QUICKLIST_MENU_ITEM_ACCESSIBLE(object);
00103   AtkObject* parent = NULL;
00104 
00105   parent = atk_object_get_parent(ATK_OBJECT(object));
00106 
00107   if (UNITY_IS_QUICKLIST_MENU_ITEM_ACCESSIBLE(parent))
00108   {
00109     if (self->priv->on_parent_selection_change_id != 0)
00110       g_signal_handler_disconnect(parent, self->priv->on_parent_selection_change_id);
00111   }
00112 
00113   if (self->priv->on_parent_change_id != 0)
00114     g_signal_handler_disconnect(object, self->priv->on_parent_change_id);
00115 
00116   G_OBJECT_CLASS(unity_quicklist_menu_item_accessible_parent_class)->dispose(object);
00117 }
00118 
00119 AtkObject*
00120 unity_quicklist_menu_item_accessible_new(nux::Object* object)
00121 {
00122   AtkObject* accessible = NULL;
00123 
00124   g_return_val_if_fail(dynamic_cast<QuicklistMenuItem*>(object), NULL);
00125 
00126   accessible = ATK_OBJECT(g_object_new(UNITY_TYPE_QUICKLIST_MENU_ITEM_ACCESSIBLE, NULL));
00127 
00128   atk_object_initialize(accessible, object);
00129 
00130   return accessible;
00131 }
00132 
00133 /* AtkObject.h */
00134 static gboolean
00135 menu_item_is_a_separator(QuicklistMenuItem* menu_item)
00136 {
00137   QuicklistMenuItemSeparator* separator = NULL;
00138 
00139   separator = dynamic_cast<QuicklistMenuItemSeparator*>(menu_item);
00140 
00141   if (separator != NULL)
00142     return TRUE;
00143   else
00144     return FALSE;
00145 }
00146 
00147 static void
00148 on_parent_change_cb(gchar* property,
00149                     GValue* value,
00150                     gpointer data)
00151 {
00152   AtkObject* parent = NULL;
00153   UnityQuicklistMenuItemAccessible* self = NULL;
00154 
00155   g_return_if_fail(UNITY_IS_QUICKLIST_MENU_ITEM_ACCESSIBLE(data));
00156   self = UNITY_QUICKLIST_MENU_ITEM_ACCESSIBLE(data);
00157 
00158   parent = atk_object_get_parent(ATK_OBJECT(self));
00159 
00160   if (parent == NULL)
00161     return;
00162 
00163   self->priv->on_parent_selection_change_id =
00164     g_signal_connect(parent, "selection-changed",
00165                      G_CALLBACK(on_parent_selection_change_cb), self);
00166 }
00167 
00168 static void
00169 unity_quicklist_menu_item_accessible_initialize(AtkObject* accessible,
00170                                                 gpointer data)
00171 {
00172   nux::Object* nux_object = NULL;
00173   QuicklistMenuItem* menu_item = NULL;
00174   UnityQuicklistMenuItemAccessible* self = NULL;
00175 
00176   ATK_OBJECT_CLASS(unity_quicklist_menu_item_accessible_parent_class)->initialize(accessible, data);
00177   self = UNITY_QUICKLIST_MENU_ITEM_ACCESSIBLE(accessible);
00178 
00179   nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
00180   menu_item = dynamic_cast<QuicklistMenuItem*>(nux_object);
00181 
00182   if (menu_item == NULL)
00183     return;
00184 
00185   if (menu_item_is_a_separator(menu_item))
00186     atk_object_set_role(accessible, ATK_ROLE_SEPARATOR);
00187   else
00188     atk_object_set_role(accessible, ATK_ROLE_MENU_ITEM);
00189 
00190   /* we could do that by redefining ->set_parent */
00191   self->priv->on_parent_change_id =
00192     g_signal_connect(accessible, "notify::accessible-parent",
00193                      G_CALLBACK(on_parent_change_cb), self);
00194 }
00195 
00196 
00197 
00198 static const gchar*
00199 unity_quicklist_menu_item_accessible_get_name(AtkObject* obj)
00200 {
00201   const gchar* name = NULL;
00202 
00203   g_return_val_if_fail(UNITY_IS_QUICKLIST_MENU_ITEM_ACCESSIBLE(obj), NULL);
00204 
00205   name = ATK_OBJECT_CLASS(unity_quicklist_menu_item_accessible_parent_class)->get_name(obj);
00206   if (name == NULL)
00207   {
00208     QuicklistMenuItem* menu_item = NULL;
00209 
00210     menu_item = dynamic_cast<QuicklistMenuItem*>(nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj)));
00211     if (menu_item != NULL)
00212     {
00213       name = menu_item->GetLabel();
00214     }
00215   }
00216 
00217   return name;
00218 }
00219 
00220 static AtkStateSet*
00221 unity_quicklist_menu_item_accessible_ref_state_set(AtkObject* obj)
00222 {
00223   AtkStateSet* state_set = NULL;
00224   UnityQuicklistMenuItemAccessible* self = NULL;
00225   nux::Object* nux_object = NULL;
00226 
00227   g_return_val_if_fail(UNITY_IS_QUICKLIST_MENU_ITEM_ACCESSIBLE(obj), NULL);
00228   self = UNITY_QUICKLIST_MENU_ITEM_ACCESSIBLE(obj);
00229 
00230   state_set = ATK_OBJECT_CLASS(unity_quicklist_menu_item_accessible_parent_class)->ref_state_set(obj);
00231 
00232   nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
00233 
00234   if (nux_object == NULL) /* defunct */
00235     return state_set;
00236 
00237   /* by default */
00238   atk_state_set_add_state(state_set, ATK_STATE_FOCUSABLE);
00239   atk_state_set_add_state(state_set, ATK_STATE_ENABLED);
00240   atk_state_set_add_state(state_set, ATK_STATE_SENSITIVE);
00241 
00242   if (self->priv->selected)
00243   {
00244     atk_state_set_add_state(state_set, ATK_STATE_FOCUSED);
00245     atk_state_set_add_state(state_set, ATK_STATE_SELECTED);
00246     atk_state_set_add_state(state_set, ATK_STATE_ACTIVE);
00247   }
00248   else
00249   {
00250     /* we clean the states that could come from NuxAreaAccessible */
00251     atk_state_set_remove_state(state_set, ATK_STATE_FOCUSED);
00252   }
00253 
00254   return state_set;
00255 }
00256 
00257 /* private */
00258 static void
00259 check_selected(UnityQuicklistMenuItemAccessible* self)
00260 {
00261   AtkObject* selected_item = NULL;
00262   AtkObject* parent = NULL;
00263   nux::Object* nux_object = NULL;
00264   gboolean found = FALSE;
00265 
00266   nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(self));
00267   if (nux_object == NULL) /* state is defunct */
00268     return;
00269 
00270   parent = atk_object_get_parent(ATK_OBJECT(self));
00271   if (parent == NULL)
00272     return;
00273 
00274   selected_item = atk_selection_ref_selection(ATK_SELECTION(parent), 0);
00275 
00276   if (ATK_OBJECT(self) == selected_item)
00277     found = TRUE;
00278 
00279   if (found != self->priv->selected)
00280   {
00281     gboolean return_val = FALSE;
00282 
00283     self->priv->selected = found;
00284     atk_object_notify_state_change(ATK_OBJECT(self),
00285                                    ATK_STATE_FOCUSED,
00286                                    found);
00287     atk_object_notify_state_change(ATK_OBJECT(self),
00288                                    ATK_STATE_SELECTED,
00289                                    found);
00290     atk_object_notify_state_change(ATK_OBJECT(self),
00291                                    ATK_STATE_ACTIVE,
00292                                    found);
00293 
00294     g_signal_emit_by_name(self, "focus-event", self->priv->selected, &return_val);
00295   }
00296 }
00297 
00298 static void
00299 on_parent_selection_change_cb(AtkSelection* selection,
00300                               gpointer data)
00301 {
00302   g_return_if_fail(UNITY_IS_QUICKLIST_MENU_ITEM_ACCESSIBLE(data));
00303 
00304   check_selected(UNITY_QUICKLIST_MENU_ITEM_ACCESSIBLE(data));
00305 }