]> Pileus Git - ~andy/gtk/blobdiff - gtk/a11y/gtkmenuitemaccessible.c
a11y: fix private strict regression
[~andy/gtk] / gtk / a11y / gtkmenuitemaccessible.c
index ddea3528dc208da5a423e63486be2764164e6765..2e5a4369e599c67f354b88a5c82abcd9b31904a2 100644 (file)
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <string.h>
 #include <gtk/gtk.h>
 #include "gtkmenuitemaccessible.h"
-#include "gtksubmenuitemaccessible.h"
 #include "gtk/gtkmenuitemprivate.h"
 
+struct _GtkMenuItemAccessiblePrivate
+{
+  gchar *text;
+};
+
 #define KEYBINDING_SEPARATOR ";"
 
 static void menu_item_select   (GtkMenuItem *item);
@@ -31,11 +33,17 @@ static void menu_item_deselect (GtkMenuItem *item);
 static GtkWidget *get_label_from_container   (GtkWidget *container);
 static gchar     *get_text_from_label_widget (GtkWidget *widget);
 
+static gint menu_item_add_gtk    (GtkContainer   *container,
+                                  GtkWidget      *widget);
+static gint menu_item_remove_gtk (GtkContainer   *container,
+                                  GtkWidget      *widget);
 
-static void atk_action_interface_init (AtkActionIface *iface);
+static void atk_action_interface_init    (AtkActionIface *iface);
+static void atk_selection_interface_init (AtkSelectionIface *iface);
 
 G_DEFINE_TYPE_WITH_CODE (GtkMenuItemAccessible, _gtk_menu_item_accessible, GTK_TYPE_CONTAINER_ACCESSIBLE,
-                         G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init))
+                         G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init);
+                         G_IMPLEMENT_INTERFACE (ATK_TYPE_SELECTION, atk_selection_interface_init))
 
 static void
 gtk_menu_item_accessible_initialize (AtkObject *obj,
@@ -43,6 +51,7 @@ gtk_menu_item_accessible_initialize (AtkObject *obj,
 {
   GtkWidget *widget;
   GtkWidget *parent;
+  GtkWidget *menu;
 
   ATK_OBJECT_CLASS (_gtk_menu_item_accessible_parent_class)->initialize (obj, data);
 
@@ -63,12 +72,16 @@ gtk_menu_item_accessible_initialize (AtkObject *obj,
         atk_object_set_parent (obj, gtk_widget_get_accessible (parent_widget));
     }
 
-  GTK_WIDGET_ACCESSIBLE (obj)->layer = ATK_LAYER_POPUP;
+  _gtk_widget_accessible_set_layer (GTK_WIDGET_ACCESSIBLE (obj), ATK_LAYER_POPUP);
 
-  if (GTK_IS_TEAROFF_MENU_ITEM (data))
-    obj->role = ATK_ROLE_TEAR_OFF_MENU_ITEM;
-  else
-    obj->role = ATK_ROLE_MENU_ITEM;
+  obj->role = ATK_ROLE_MENU_ITEM;
+
+  menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (data));
+  if (menu)
+    {
+      g_signal_connect (menu, "add", G_CALLBACK (menu_item_add_gtk), NULL);
+      g_signal_connect (menu, "remove", G_CALLBACK (menu_item_remove_gtk), NULL);
+    }
 }
 
 static gint
@@ -185,10 +198,10 @@ gtk_menu_item_accessible_get_name (AtkObject *obj)
   accessible = GTK_MENU_ITEM_ACCESSIBLE (obj);
   label = get_label_from_container (widget);
 
-  g_free (accessible->text);
-  accessible->text = get_text_from_label_widget (label);
+  g_free (accessible->priv->text);
+  accessible->priv->text = get_text_from_label_widget (label);
 
-  return accessible->text;
+  return accessible->priv->text;
 }
 
 static void
@@ -196,7 +209,7 @@ gtk_menu_item_accessible_finalize (GObject *object)
 {
   GtkMenuItemAccessible *accessible = GTK_MENU_ITEM_ACCESSIBLE (object);
 
-  g_free (accessible->text);
+  g_free (accessible->priv->text);
 
   G_OBJECT_CLASS (_gtk_menu_item_accessible_parent_class)->finalize (object);
 }
@@ -236,11 +249,16 @@ _gtk_menu_item_accessible_class_init (GtkMenuItemAccessibleClass *klass)
   class->initialize = gtk_menu_item_accessible_initialize;
   class->get_name = gtk_menu_item_accessible_get_name;
   class->get_role = gtk_menu_item_accessible_get_role;
+
+  g_type_class_add_private (klass, sizeof (GtkMenuItemAccessiblePrivate));
 }
 
 static void
 _gtk_menu_item_accessible_init (GtkMenuItemAccessible *menu_item)
 {
+  menu_item->priv = G_TYPE_INSTANCE_GET_PRIVATE (menu_item,
+                                                 GTK_TYPE_MENU_ITEM_ACCESSIBLE,
+                                                 GtkMenuItemAccessiblePrivate);
 }
 
 static GtkWidget *
@@ -615,6 +633,221 @@ menu_item_selection (GtkMenuItem  *item,
   g_signal_emit_by_name (parent, "selection-changed");
 }
 
+static gboolean
+gtk_menu_item_accessible_add_selection (AtkSelection *selection,
+                                           gint          i)
+{
+  GtkMenuShell *shell;
+  GList *kids;
+  guint length;
+  GtkWidget *widget;
+  GtkWidget *menu;
+  GtkWidget *child;
+
+  widget =  gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
+  if (widget == NULL)
+    return FALSE;
+
+  menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
+  if (menu == NULL)
+    return FALSE;
+
+  shell = GTK_MENU_SHELL (menu);
+  kids = gtk_container_get_children (GTK_CONTAINER (shell));
+  length = g_list_length (kids);
+  if (i < 0 || i > length)
+    {
+      g_list_free (kids);
+      return FALSE;
+    }
+
+  child = g_list_nth_data (kids, i);
+  g_list_free (kids);
+  g_return_val_if_fail (GTK_IS_MENU_ITEM (child), FALSE);
+  gtk_menu_shell_select_item (shell, GTK_WIDGET (child));
+  return TRUE;
+}
+
+static gboolean
+gtk_menu_item_accessible_clear_selection (AtkSelection *selection)
+{
+  GtkWidget *widget;
+  GtkWidget *menu;
+
+  widget =  gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
+  if (widget == NULL)
+    return FALSE;
+
+  menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
+  if (menu == NULL)
+    return FALSE;
+
+  gtk_menu_shell_deselect (GTK_MENU_SHELL (menu));
+
+  return TRUE;
+}
+
+static AtkObject *
+gtk_menu_item_accessible_ref_selection (AtkSelection *selection,
+                                           gint          i)
+{
+  GtkMenuShell *shell;
+  AtkObject *obj;
+  GtkWidget *widget;
+  GtkWidget *menu;
+  GtkWidget *item;
+
+  if (i != 0)
+    return NULL;
+
+  widget =  gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
+  if (widget == NULL)
+    return NULL;
+
+  menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
+  if (menu == NULL)
+    return NULL;
+
+  shell = GTK_MENU_SHELL (menu);
+
+  item = gtk_menu_shell_get_selected_item (shell);
+  if (item != NULL)
+    {
+      obj = gtk_widget_get_accessible (item);
+      g_object_ref (obj);
+      return obj;
+    }
+
+  return NULL;
+}
+
+static gint
+gtk_menu_item_accessible_get_selection_count (AtkSelection *selection)
+{
+  GtkMenuShell *shell;
+  GtkWidget *widget;
+  GtkWidget *menu;
+
+  widget =  gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
+  if (widget == NULL)
+    return 0;
+
+  menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
+  if (menu == NULL)
+    return 0;
+
+  shell = GTK_MENU_SHELL (menu);
+
+  if (gtk_menu_shell_get_selected_item (shell) != NULL)
+    return 1;
+
+  return 0;
+}
+
+static gboolean
+gtk_menu_item_accessible_is_child_selected (AtkSelection *selection,
+                                               gint          i)
+{
+  GtkMenuShell *shell;
+  gint j;
+  GtkWidget *widget;
+  GtkWidget *menu;
+  GtkWidget *item;
+  GList *kids;
+
+  widget =  gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
+  if (widget == NULL)
+    return FALSE;
+
+  menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
+  if (menu == NULL)
+    return FALSE;
+
+  shell = GTK_MENU_SHELL (menu);
+
+  item = gtk_menu_shell_get_selected_item (shell);
+  if (item == NULL)
+    return FALSE;
+
+  kids = gtk_container_get_children (GTK_CONTAINER (shell));
+  j = g_list_index (kids, item);
+  g_list_free (kids);
+
+  return j==i;
+}
+
+static gboolean
+gtk_menu_item_accessible_remove_selection (AtkSelection *selection,
+                                              gint          i)
+{
+  GtkMenuShell *shell;
+  GtkWidget *widget;
+  GtkWidget *menu;
+  GtkWidget *item;
+
+  if (i != 0)
+    return FALSE;
+
+  widget =  gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
+  if (widget == NULL)
+    return FALSE;
+
+  menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
+  if (menu == NULL)
+    return FALSE;
+
+  shell = GTK_MENU_SHELL (menu);
+
+  item = gtk_menu_shell_get_selected_item (shell);
+  if (item && gtk_menu_item_get_submenu (GTK_MENU_ITEM (item)))
+    gtk_menu_shell_deselect (shell);
+
+  return TRUE;
+}
+
+static void
+atk_selection_interface_init (AtkSelectionIface *iface)
+{
+  iface->add_selection = gtk_menu_item_accessible_add_selection;
+  iface->clear_selection = gtk_menu_item_accessible_clear_selection;
+  iface->ref_selection = gtk_menu_item_accessible_ref_selection;
+  iface->get_selection_count = gtk_menu_item_accessible_get_selection_count;
+  iface->is_child_selected = gtk_menu_item_accessible_is_child_selected;
+  iface->remove_selection = gtk_menu_item_accessible_remove_selection;
+}
+
+static gint
+menu_item_add_gtk (GtkContainer *container,
+                   GtkWidget    *widget)
+{
+  GtkWidget *parent_widget;
+
+  g_return_val_if_fail (GTK_IS_MENU (container), 1);
+
+  parent_widget = gtk_menu_get_attach_widget (GTK_MENU (container));
+  if (GTK_IS_MENU_ITEM (parent_widget))
+    {
+      GTK_CONTAINER_ACCESSIBLE_CLASS (_gtk_menu_item_accessible_parent_class)->add_gtk (container, widget, gtk_widget_get_accessible (parent_widget));
+
+    }
+  return 1;
+}
+
+static gint
+menu_item_remove_gtk (GtkContainer *container,
+                      GtkWidget    *widget)
+{
+  GtkWidget *parent_widget;
+
+  g_return_val_if_fail (GTK_IS_MENU (container), 1);
+
+  parent_widget = gtk_menu_get_attach_widget (GTK_MENU (container));
+  if (GTK_IS_MENU_ITEM (parent_widget))
+    {
+      GTK_CONTAINER_ACCESSIBLE_CLASS (_gtk_menu_item_accessible_parent_class)->remove_gtk (container, widget, gtk_widget_get_accessible (parent_widget));
+    }
+  return 1;
+}
 static void
 menu_item_select (GtkMenuItem *item)
 {