Back to index

unity  6.0.0
unity-quicklist-menu-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 
00054 #include <glib/gi18n.h>
00055 
00056 #include "unity-quicklist-menu-accessible.h"
00057 
00058 #include "unitya11y.h"
00059 #include "Launcher.h" /*without this I get a error with the following include*/
00060 #include "QuicklistView.h"
00061 
00062 /* GObject */
00063 static void unity_quicklist_menu_accessible_class_init(UnityQuicklistMenuAccessibleClass* klass);
00064 static void unity_quicklist_menu_accessible_init(UnityQuicklistMenuAccessible* self);
00065 static void unity_quicklist_menu_accessible_finalize(GObject* object);
00066 
00067 /* AtkObject.h */
00068 static void         unity_quicklist_menu_accessible_initialize(AtkObject* accessible,
00069                                                                gpointer   data);
00070 static gint         unity_quicklist_menu_accessible_get_n_children(AtkObject* obj);
00071 static AtkObject*   unity_quicklist_menu_accessible_ref_child(AtkObject* obj,
00072                                                               gint i);
00073 
00074 /* AtkSelection */
00075 static void       atk_selection_interface_init(AtkSelectionIface* iface);
00076 static AtkObject* unity_quicklist_menu_accessible_ref_selection(AtkSelection* selection,
00077                                                                 gint i);
00078 static gint       unity_quicklist_menu_accessible_get_selection_count(AtkSelection* selection);
00079 static gboolean   unity_quicklist_menu_accessible_is_child_selected(AtkSelection* selection,
00080                                                                     gint i);
00081 /* private */
00082 static void on_selection_change_cb(UnityQuicklistMenuAccessible* self);
00083 static void on_parent_activate_change_cb(AtkObject* parent_window,
00084                                          UnityQuicklistMenuAccessible* self);
00085 static void on_parent_change_cb(gchar* property,
00086                                 GValue* value,
00087                                 gpointer data);
00088 
00089 G_DEFINE_TYPE_WITH_CODE(UnityQuicklistMenuAccessible,
00090                         unity_quicklist_menu_accessible,  NUX_TYPE_OBJECT_ACCESSIBLE,
00091                         G_IMPLEMENT_INTERFACE(ATK_TYPE_SELECTION, atk_selection_interface_init));
00092 
00093 
00094 #define UNITY_QUICKLIST_MENU_ACCESSIBLE_GET_PRIVATE(obj)                      \
00095   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), UNITY_TYPE_QUICKLIST_MENU_ACCESSIBLE,  \
00096                                 UnityQuicklistMenuAccessiblePrivate))
00097 
00098 struct _UnityQuicklistMenuAccessiblePrivate
00099 {
00100   sigc::connection on_selection_change_connection;
00101   guint on_parent_change_id;
00102   guint on_parent_activate_change_id;
00103 };
00104 
00105 using unity::QuicklistView;
00106 using unity::QuicklistMenuItem;
00107 
00108 static void
00109 unity_quicklist_menu_accessible_class_init(UnityQuicklistMenuAccessibleClass* klass)
00110 {
00111   GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
00112   AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
00113 
00114   gobject_class->finalize = unity_quicklist_menu_accessible_finalize;
00115 
00116   /* AtkObject */
00117   atk_class->initialize = unity_quicklist_menu_accessible_initialize;
00118   atk_class->get_n_children = unity_quicklist_menu_accessible_get_n_children;
00119   atk_class->ref_child = unity_quicklist_menu_accessible_ref_child;
00120 
00121   g_type_class_add_private(gobject_class, sizeof(UnityQuicklistMenuAccessiblePrivate));
00122 }
00123 
00124 static void
00125 unity_quicklist_menu_accessible_init(UnityQuicklistMenuAccessible* self)
00126 {
00127   UnityQuicklistMenuAccessiblePrivate* priv =
00128     UNITY_QUICKLIST_MENU_ACCESSIBLE_GET_PRIVATE(self);
00129 
00130   self->priv = priv;
00131 }
00132 
00133 static void
00134 unity_quicklist_menu_accessible_finalize(GObject* object)
00135 {
00136   UnityQuicklistMenuAccessible* self = UNITY_QUICKLIST_MENU_ACCESSIBLE(object);
00137 
00138   self->priv->on_selection_change_connection.disconnect();
00139 
00140   if (self->priv->on_parent_change_id != 0)
00141     g_signal_handler_disconnect(object, self->priv->on_parent_change_id);
00142 
00143   G_OBJECT_CLASS(unity_quicklist_menu_accessible_parent_class)->finalize(object);
00144 }
00145 
00146 AtkObject*
00147 unity_quicklist_menu_accessible_new(nux::Object* object)
00148 {
00149   AtkObject* accessible = NULL;
00150 
00151   g_return_val_if_fail(dynamic_cast<QuicklistView*>(object), NULL);
00152 
00153   accessible = ATK_OBJECT(g_object_new(UNITY_TYPE_QUICKLIST_MENU_ACCESSIBLE, NULL));
00154 
00155   atk_object_initialize(accessible, object);
00156 
00157   return accessible;
00158 }
00159 
00160 /* AtkObject.h */
00161 static void
00162 unity_quicklist_menu_accessible_initialize(AtkObject* accessible,
00163                                            gpointer data)
00164 {
00165   nux::Object* nux_object = NULL;
00166   QuicklistView* quicklist = NULL;
00167   UnityQuicklistMenuAccessible* self = NULL;
00168 
00169   ATK_OBJECT_CLASS(unity_quicklist_menu_accessible_parent_class)->initialize(accessible, data);
00170   self = UNITY_QUICKLIST_MENU_ACCESSIBLE(accessible);
00171 
00172   nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
00173   quicklist = dynamic_cast<QuicklistView*>(nux_object);
00174 
00175   if (quicklist == NULL) /* status defunct */
00176     return;
00177 
00178   atk_object_set_role(accessible, ATK_ROLE_MENU);
00179   atk_object_set_name(accessible, _("Quicklist"));
00180 
00181   self->priv->on_selection_change_connection =
00182     quicklist->selection_change.connect(sigc::bind(sigc::ptr_fun(on_selection_change_cb), self));
00183 
00184   self->priv->on_parent_change_id =
00185     g_signal_connect(accessible, "notify::accessible-parent",
00186                      G_CALLBACK(on_parent_change_cb), self);
00187 }
00188 
00189 static gint
00190 unity_quicklist_menu_accessible_get_n_children(AtkObject* obj)
00191 {
00192   QuicklistView* quicklist = NULL;
00193   nux::Object* nux_object = NULL;
00194 
00195   g_return_val_if_fail(UNITY_IS_QUICKLIST_MENU_ACCESSIBLE(obj), 0);
00196 
00197   nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
00198   quicklist = dynamic_cast<QuicklistView*>(nux_object);
00199 
00200   if (quicklist == NULL)
00201     return 0;
00202 
00203   return quicklist->GetNumItems();
00204 }
00205 
00206 static AtkObject*
00207 unity_quicklist_menu_accessible_ref_child(AtkObject* obj,
00208                                           gint i)
00209 {
00210   QuicklistView* quicklist = NULL;
00211   QuicklistMenuItem* child = NULL;
00212   AtkObject* child_accessible = NULL;
00213   AtkObject* parent = NULL;
00214   nux::Object* nux_object = NULL;
00215 
00216   g_return_val_if_fail(UNITY_IS_QUICKLIST_MENU_ACCESSIBLE(obj), NULL);
00217 
00218   nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
00219   quicklist = dynamic_cast<QuicklistView*>(nux_object);
00220 
00221   if (quicklist == NULL)
00222     return NULL;
00223 
00224   child = quicklist->GetNthItems(i);
00225   child_accessible = unity_a11y_get_accessible(child);
00226 
00227   if (child_accessible != NULL)
00228   {
00229     g_object_ref(child_accessible);
00230     parent = atk_object_get_parent(child_accessible);
00231     if (parent != obj)
00232       atk_object_set_parent(child_accessible, obj);
00233   }
00234 
00235   return child_accessible;
00236 }
00237 
00238 /* AtkSelection */
00239 static void
00240 atk_selection_interface_init(AtkSelectionIface* iface)
00241 {
00242   iface->ref_selection = unity_quicklist_menu_accessible_ref_selection;
00243   iface->get_selection_count = unity_quicklist_menu_accessible_get_selection_count;
00244   iface->is_child_selected = unity_quicklist_menu_accessible_is_child_selected;
00245 
00246   /* NOTE: for the moment we don't provide the implementation for the
00247      "interactable" methods, it is, the methods that allow to change
00248      the selected icon. The QuicklistView doesn't provide that API, and
00249      right now  we are focusing on a normal user input.*/
00250 }
00251 
00252 static AtkObject*
00253 unity_quicklist_menu_accessible_ref_selection(AtkSelection* selection,
00254                                               gint i)
00255 {
00256   QuicklistView* quicklist = NULL;
00257   QuicklistMenuItem* child = NULL;
00258   AtkObject* child_accessible = NULL;
00259   nux::Object* nux_object = NULL;
00260 
00261   g_return_val_if_fail(UNITY_IS_QUICKLIST_MENU_ACCESSIBLE(selection), NULL);
00262   /* there can be only one item selected */
00263   g_return_val_if_fail(i == 0, NULL);
00264 
00265   nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(selection));
00266   quicklist = dynamic_cast<QuicklistView*>(nux_object);
00267 
00268   if (quicklist == NULL) /*state is defunct */
00269     return NULL;
00270 
00271   child = quicklist->GetSelectedMenuItem();
00272   child_accessible = unity_a11y_get_accessible(child);
00273 
00274   if (child_accessible != NULL)
00275     g_object_ref(child_accessible);
00276 
00277   return child_accessible;
00278 }
00279 
00280 static gint
00281 unity_quicklist_menu_accessible_get_selection_count(AtkSelection* selection)
00282 {
00283   QuicklistView* quicklist = NULL;
00284   nux::Object* nux_object = NULL;
00285 
00286   g_return_val_if_fail(UNITY_IS_QUICKLIST_MENU_ACCESSIBLE(selection), 0);
00287 
00288   /*
00289    * Looking at QuicklistView code, there is always one item selected,
00290    * anyway we check that there is at least one item
00291    */
00292   nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(selection));
00293   quicklist = dynamic_cast<QuicklistView*>(nux_object);
00294 
00295   if (quicklist == NULL) /*state is defunct */
00296     return 0;
00297 
00298   if (quicklist->GetNumItems() > 0)
00299     return 1;
00300   else
00301     return 0;
00302 }
00303 
00304 static gboolean
00305 unity_quicklist_menu_accessible_is_child_selected(AtkSelection* selection,
00306                                                   gint i)
00307 {
00308   QuicklistView* quicklist = NULL;
00309   QuicklistMenuItem* selected = NULL;
00310   QuicklistMenuItem* ith_item = NULL;
00311   nux::Object* nux_object = NULL;
00312 
00313   g_return_val_if_fail(UNITY_IS_QUICKLIST_MENU_ACCESSIBLE(selection), FALSE);
00314 
00315   nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(selection));
00316   quicklist = dynamic_cast<QuicklistView*>(nux_object);
00317 
00318   if (quicklist == NULL) /*state is defunct */
00319     return FALSE;
00320 
00321   selected = quicklist->GetSelectedMenuItem();
00322   ith_item = quicklist->GetNthItems(i);
00323 
00324   if (selected == ith_item)
00325     return TRUE;
00326   else
00327     return FALSE;
00328 }
00329 
00330 /* private */
00331 static void
00332 on_selection_change_cb(UnityQuicklistMenuAccessible* self)
00333 {
00334   g_signal_emit_by_name(ATK_OBJECT(self), "selection-changed");
00335 }
00336 
00337 static void
00338 on_parent_activate_change_cb(AtkObject* parent_window,
00339                              UnityQuicklistMenuAccessible* self)
00340 {
00341   /* We consider that when our parent window is activated, the focus
00342      should be on the menu, specifically on one of the menu-item. So
00343      we emit a selection-change in order to notify that a selection
00344      was made */
00345   g_signal_emit_by_name(ATK_OBJECT(self), "selection-changed");
00346 }
00347 
00348 
00349 static void
00350 on_parent_change_cb(gchar* property,
00351                     GValue* value,
00352                     gpointer data)
00353 {
00354   AtkObject* parent = NULL;
00355   UnityQuicklistMenuAccessible* self = NULL;
00356 
00357   g_return_if_fail(UNITY_IS_QUICKLIST_MENU_ACCESSIBLE(data));
00358   self = UNITY_QUICKLIST_MENU_ACCESSIBLE(data);
00359 
00360   parent = atk_object_get_parent(ATK_OBJECT(self));
00361 
00362   if (parent == NULL)
00363     return;
00364 
00365   self->priv->on_parent_activate_change_id =
00366     g_signal_connect(parent, "activate",
00367                      G_CALLBACK(on_parent_activate_change_cb), self);
00368 }
00369