Back to index

unity  6.0.0
unity-rvgrid-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-rvgrid-accessible.h"
00034 #include "unity-result-accessible.h"
00035 #include "unity-places-group-accessible.h"
00036 
00037 #include "unitya11y.h"
00038 #include "ResultViewGrid.h"
00039 #include "PlacesGroup.h"
00040 
00041 using namespace unity::dash;
00042 
00043 /* GObject */
00044 static void unity_rvgrid_accessible_class_init(UnityRvgridAccessibleClass* klass);
00045 static void unity_rvgrid_accessible_init(UnityRvgridAccessible* self);
00046 static void unity_rvgrid_accessible_finalize(GObject* object);
00047 
00048 /* AtkObject.h */
00049 static void       unity_rvgrid_accessible_initialize(AtkObject* accessible,
00050                                                      gpointer   data);
00051 static AtkStateSet*  unity_rvgrid_accessible_ref_state_set(AtkObject* obj);
00052 static gint       unity_rvgrid_accessible_get_n_children(AtkObject* obj);
00053 static AtkObject* unity_rvgrid_accessible_ref_child(AtkObject* obj,
00054                                                     gint i);
00055 
00056 /* AtkSelection */
00057 static void       atk_selection_interface_init(AtkSelectionIface* iface);
00058 static AtkObject* unity_rvgrid_accessible_ref_selection(AtkSelection* selection,
00059                                                         gint i);
00060 static gint       unity_rvgrid_accessible_get_selection_count(AtkSelection* selection);
00061 static gboolean   unity_rvgrid_accessible_is_child_selected(AtkSelection* selection,
00062                                                             gint i);
00063 
00064 /* private */
00065 
00066 G_DEFINE_TYPE_WITH_CODE(UnityRvgridAccessible, unity_rvgrid_accessible,  NUX_TYPE_VIEW_ACCESSIBLE,
00067                         G_IMPLEMENT_INTERFACE(ATK_TYPE_SELECTION, atk_selection_interface_init))
00068 
00069 #define UNITY_RVGRID_ACCESSIBLE_GET_PRIVATE(obj)                        \
00070   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), UNITY_TYPE_RVGRID_ACCESSIBLE,    \
00071                                 UnityRvgridAccessiblePrivate))
00072 
00073 struct _UnityRvgridAccessiblePrivate
00074 {
00075   sigc::connection on_selection_change_connection;
00076 
00077   /* dummy selected result object */
00078   UnityResultAccessible* result;
00079   gboolean has_selection;
00080   gboolean focused;
00081 };
00082 
00083 
00084 static void
00085 unity_rvgrid_accessible_class_init(UnityRvgridAccessibleClass* klass)
00086 {
00087   GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
00088   AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
00089 
00090   /* GObject */
00091   gobject_class->finalize = unity_rvgrid_accessible_finalize;
00092 
00093   /* AtkObject */
00094   atk_class->get_n_children = unity_rvgrid_accessible_get_n_children;
00095   atk_class->ref_child = unity_rvgrid_accessible_ref_child;
00096   atk_class->initialize = unity_rvgrid_accessible_initialize;
00097   atk_class->ref_state_set = unity_rvgrid_accessible_ref_state_set;
00098 
00099   g_type_class_add_private(gobject_class, sizeof(UnityRvgridAccessiblePrivate));
00100 }
00101 
00102 static void
00103 unity_rvgrid_accessible_init(UnityRvgridAccessible* self)
00104 {
00105   UnityRvgridAccessiblePrivate* priv =
00106     UNITY_RVGRID_ACCESSIBLE_GET_PRIVATE(self);
00107 
00108   self->priv = priv;
00109 }
00110 
00111 static void
00112 unity_rvgrid_accessible_finalize(GObject* object)
00113 {
00114   UnityRvgridAccessible* self = UNITY_RVGRID_ACCESSIBLE(object);
00115 
00116   self->priv->on_selection_change_connection.disconnect();
00117 
00118   if (self->priv->result != NULL)
00119   {
00120     g_object_unref(self->priv->result);
00121     self->priv->result = NULL;
00122   }
00123 
00124   self->priv->on_selection_change_connection.disconnect();
00125 
00126   G_OBJECT_CLASS(unity_rvgrid_accessible_parent_class)->finalize(object);
00127 }
00128 
00129 AtkObject*
00130 unity_rvgrid_accessible_new(nux::Object* object)
00131 {
00132   AtkObject* accessible = NULL;
00133 
00134   g_return_val_if_fail(dynamic_cast<ResultViewGrid*>(object), NULL);
00135 
00136   accessible = ATK_OBJECT(g_object_new(UNITY_TYPE_RVGRID_ACCESSIBLE, NULL));
00137 
00138   atk_object_initialize(accessible, object);
00139 
00140   return accessible;
00141 }
00142 
00143 /* AtkObject.h */
00144 static void
00145 check_selection(UnityRvgridAccessible* self)
00146 {
00147   AtkObject* child = NULL;
00148   gint index = 0;
00149   ResultView::ResultList result_list;
00150   Result* result;
00151   nux::Object* object = NULL;
00152   ResultViewGrid* rvgrid = NULL;
00153   std::string name;
00154 
00155   /* we don't notify until the grid is focused */
00156   if (self->priv->focused == FALSE)
00157     return;
00158 
00159   object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(self));
00160   if (!object) /* state is defunct */
00161     return;
00162 
00163   rvgrid = dynamic_cast<ResultViewGrid*>(object);
00164 
00165   result_list = rvgrid->GetResultList();
00166   index = rvgrid->GetSelectedIndex();
00167 
00168   if (index >= 0)
00169   {
00170     result = &result_list[index];
00171     name = result->name;
00172 
00173     child = ATK_OBJECT(self->priv->result);
00174     self->priv->has_selection = TRUE;
00175     atk_object_set_name(child, name.c_str());
00176   }
00177   else
00178   {
00179     child = NULL;
00180     self->priv->has_selection = FALSE;
00181   }
00182 
00183   g_signal_emit_by_name(self, "active-descendant-changed", child);
00184   g_signal_emit_by_name(self, "selection-changed");
00185 }
00186 
00187 static void
00188 on_selection_change_cb(UnityRvgridAccessible* self)
00189 {
00190   check_selection(self);
00191 }
00192 
00193 static void
00194 search_for_label(UnityRvgridAccessible* self)
00195 {
00196   AtkObject* label_accessible = NULL;
00197   nux::Object* nux_object = NULL;
00198   unity::PlacesGroup* group = NULL;
00199   AtkObject* iter = NULL;
00200   nux::StaticCairoText* label = NULL;
00201 
00202   /* Search for the places group */
00203   for (iter = atk_object_get_parent(ATK_OBJECT(self)); iter != NULL;
00204        iter = atk_object_get_parent(iter))
00205   {
00206     if (UNITY_IS_PLACES_GROUP_ACCESSIBLE(iter))
00207       break;
00208   }
00209   if (iter == NULL)
00210     return;
00211 
00212   nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(iter));
00213   group = dynamic_cast<unity::PlacesGroup*>(nux_object);
00214 
00215   if (group == NULL)
00216     return;
00217 
00218   label = group->GetLabel();
00219 
00220   label_accessible = unity_a11y_get_accessible(label);
00221 
00222   if (label_accessible == NULL)
00223     return;
00224 
00225   /* FIXME: I had a froze using relations, require further
00226      investigation, meanwhile setting directly the name can do the
00227      work*/
00228   atk_object_set_name(ATK_OBJECT(self), atk_object_get_name(label_accessible));
00229 }
00230 
00231 static gboolean
00232 check_selection_on_idle(gpointer data)
00233 {
00234   check_selection(UNITY_RVGRID_ACCESSIBLE(data));
00235 
00236   return FALSE;
00237 }
00238 
00239 static void
00240 on_focus_event_cb(AtkObject* object,
00241                   gboolean in,
00242                   gpointer data)
00243 {
00244   UnityRvgridAccessible* self = NULL;
00245 
00246   g_return_if_fail(UNITY_IS_RVGRID_ACCESSIBLE(data));
00247 
00248   self = UNITY_RVGRID_ACCESSIBLE(data);
00249   self->priv->focused = in;
00250 
00251   /* we check the selection stuff again, to report the selection
00252      change now */
00253   g_idle_add(check_selection_on_idle, self);
00254 }
00255 
00256 static void
00257 unity_rvgrid_accessible_initialize(AtkObject* accessible,
00258                                    gpointer data)
00259 {
00260   UnityRvgridAccessible* self = NULL;
00261   ResultViewGrid* rvgrid = NULL;
00262   nux::Object* nux_object = NULL;
00263 
00264   ATK_OBJECT_CLASS(unity_rvgrid_accessible_parent_class)->initialize(accessible, data);
00265 
00266   atk_object_set_role(accessible, ATK_ROLE_TOOL_BAR);
00267 
00268   self = UNITY_RVGRID_ACCESSIBLE(accessible);
00269   nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
00270 
00271   rvgrid = dynamic_cast<ResultViewGrid*>(nux_object);
00272 
00273   if (rvgrid == NULL)
00274     return;
00275 
00276   self->priv->on_selection_change_connection =
00277     rvgrid->selection_change.connect(sigc::bind(sigc::ptr_fun(on_selection_change_cb), self));
00278 
00279   g_signal_connect(self, "focus-event",
00280                    G_CALLBACK(on_focus_event_cb), self);
00281 
00282   self->priv->result = UNITY_RESULT_ACCESSIBLE(unity_result_accessible_new());
00283   atk_object_set_parent(ATK_OBJECT(self->priv->result), ATK_OBJECT(self));
00284 
00285   search_for_label(self);
00286 }
00287 
00288 static gint
00289 unity_rvgrid_accessible_get_n_children(AtkObject* obj)
00290 {
00291   g_return_val_if_fail(UNITY_IS_RVGRID_ACCESSIBLE(obj), 0);
00292 
00293   /* we have the state MANAGES_DESCENDANT, clients should not ask for
00294      the children, and just taking care of the relevant signals. So we
00295      just don't expose the children */
00296   return 0;
00297 }
00298 
00299 static AtkObject*
00300 unity_rvgrid_accessible_ref_child(AtkObject* obj,
00301                                   gint i)
00302 {
00303   g_return_val_if_fail(UNITY_IS_RVGRID_ACCESSIBLE(obj), NULL);
00304 
00305   /* we have the state MANAGES_DESCENDANT, clients should not ask for
00306      the children, and just taking care of the relevant signals. So we
00307      just don't expose the children */
00308   return NULL;
00309 }
00310 
00311 static AtkStateSet*
00312 unity_rvgrid_accessible_ref_state_set(AtkObject* obj)
00313 {
00314   AtkStateSet* state_set = NULL;
00315   nux::Object* nux_object = NULL;
00316 
00317   g_return_val_if_fail(UNITY_IS_RVGRID_ACCESSIBLE(obj), NULL);
00318 
00319   state_set = ATK_OBJECT_CLASS(unity_rvgrid_accessible_parent_class)->ref_state_set(obj);
00320 
00321   nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
00322 
00323   if (nux_object == NULL) /* defunct */
00324     return state_set;
00325 
00326   atk_state_set_add_state(state_set, ATK_STATE_MANAGES_DESCENDANTS);
00327 
00328   return state_set;
00329 }
00330 
00331 
00332 /* AtkSelection */
00333 static void
00334 atk_selection_interface_init(AtkSelectionIface* iface)
00335 {
00336   iface->ref_selection = unity_rvgrid_accessible_ref_selection;
00337   iface->get_selection_count = unity_rvgrid_accessible_get_selection_count;
00338   iface->is_child_selected = unity_rvgrid_accessible_is_child_selected;
00339 
00340   /* NOTE: for the moment we don't provide the implementation for the
00341      "interactable" methods, it is, the methods that allow to change
00342      the selected icon. The Rvgrid doesn't provide that API, and
00343      right now  we are focusing on a normal user input.*/
00344   /* iface->add_selection = unity_rvgrid_accessible_add_selection; */
00345   /* iface->clear_selection = unity_rvgrid_accessible_clear_selection; */
00346   /* iface->remove_selection = unity_rvgrid_accessible_remove_selection; */
00347 
00348   /* This method will never be implemented, as select all the rvgrid
00349      icons makes no sense */
00350   /* iface->select_all = unity_rvgrid_accessible_select_all_selection; */
00351 }
00352 
00353 static AtkObject*
00354 unity_rvgrid_accessible_ref_selection(AtkSelection* selection,
00355                                       gint i)
00356 {
00357   UnityRvgridAccessible* self = NULL;
00358 
00359   g_return_val_if_fail(UNITY_IS_RVGRID_ACCESSIBLE(selection), NULL);
00360 
00361   self = UNITY_RVGRID_ACCESSIBLE(selection);
00362 
00363   if (self->priv->has_selection)
00364     return ATK_OBJECT(g_object_ref(self->priv->result));
00365   else
00366     return NULL;
00367 }
00368 
00369 static gint
00370 unity_rvgrid_accessible_get_selection_count(AtkSelection* selection)
00371 {
00372   UnityRvgridAccessible* self = NULL;
00373 
00374   g_return_val_if_fail(UNITY_IS_RVGRID_ACCESSIBLE(selection), 0);
00375 
00376   self = UNITY_RVGRID_ACCESSIBLE(selection);
00377 
00378   if (self->priv->has_selection)
00379     return 0;
00380   else
00381     return 1;
00382 }
00383 
00384 static gboolean
00385 unity_rvgrid_accessible_is_child_selected(AtkSelection* selection,
00386                                           gint i)
00387 {
00388   UnityRvgridAccessible* self = NULL;
00389 
00390   g_return_val_if_fail(UNITY_IS_RVGRID_ACCESSIBLE(selection), FALSE);
00391 
00392   self = UNITY_RVGRID_ACCESSIBLE(selection);
00393 
00394   if (self->priv->has_selection && i == 0)
00395     return TRUE;
00396   else
00397     return FALSE;
00398 }