source: trunk/third/gail/gail/gailexpander.c @ 20902

Revision 20902, 26.5 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20901, which included commits to RCS files with non-trunk default branches.
Line 
1/* GAIL - The GNOME Accessibility Implementation Library
2 * Copyright 2003 Sun Microsystems Inc.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
20#include <string.h>
21#include <gtk/gtk.h>
22#include <gdk/gdkkeysyms.h>
23#include "gailexpander.h"
24#include <libgail-util/gailmisc.h>
25
26static void                  gail_expander_class_init       (GailExpanderClass *klass);
27static void                  gail_expander_object_init      (GailExpander      *expander);
28
29static G_CONST_RETURN gchar* gail_expander_get_name         (AtkObject         *obj);
30static gint                  gail_expander_get_n_children   (AtkObject         *obj)
31;
32static AtkObject*            gail_expander_ref_child        (AtkObject         *obj,
33                                                             gint              i);
34
35static AtkStateSet*          gail_expander_ref_state_set    (AtkObject         *obj);
36static void                  gail_expander_real_notify_gtk  (GObject           *obj,
37                                                             GParamSpec        *pspec);
38static void                  gail_expander_map_gtk          (GtkWidget         *widget,
39                                                             gpointer          data);
40
41static void                  gail_expander_real_initialize  (AtkObject         *obj,
42                                                             gpointer          data);
43static void                  gail_expander_finalize         (GObject           *object);
44static void                  gail_expander_init_textutil    (GailExpander      *expander,
45                                                             GtkExpander       *widget);
46
47static void                  atk_action_interface_init  (AtkActionIface *iface);
48static gboolean              gail_expander_do_action    (AtkAction      *action,
49                                                         gint           i);
50static gboolean              idle_do_action             (gpointer       data);
51static gint                  gail_expander_get_n_actions(AtkAction      *action);
52static G_CONST_RETURN gchar* gail_expander_get_description
53                                                        (AtkAction      *action,
54                                                         gint           i);
55static G_CONST_RETURN gchar* gail_expander_get_keybinding
56                                                        (AtkAction      *action,
57                                                         gint           i);
58static G_CONST_RETURN gchar* gail_expander_action_get_name
59                                                        (AtkAction      *action,
60                                                         gint           i);
61static gboolean              gail_expander_set_description
62                                                        (AtkAction      *action,
63                                                         gint           i,
64                                                         const gchar    *desc);
65
66/* atktext.h */
67static void       atk_text_interface_init          (AtkTextIface        *iface);
68
69static gchar*     gail_expander_get_text           (AtkText           *text,
70                                                    gint              start_pos,
71                                                    gint              end_pos);
72static gunichar   gail_expander_get_character_at_offset
73                                                   (AtkText           *text,
74                                                    gint              offset);
75static gchar*     gail_expander_get_text_before_offset
76                                                   (AtkText           *text,
77                                                    gint              offset,
78                                                    AtkTextBoundary   boundary_type,
79                                                    gint              *start_offset,
80                                                    gint              *end_offset);
81static gchar*     gail_expander_get_text_at_offset (AtkText           *text,
82                                                    gint              offset,
83                                                    AtkTextBoundary   boundary_type,
84                                                    gint              *start_offset,
85                                                    gint              *end_offset);
86static gchar*     gail_expander_get_text_after_offset
87                                                   (AtkText           *text,
88                                                    gint              offset,
89                                                    AtkTextBoundary   boundary_type,
90                                                    gint              *start_offset,
91                                                    gint              *end_offset);
92static gint       gail_expander_get_character_count(AtkText           *text);
93static void gail_expander_get_character_extents    (AtkText           *text,
94                                                    gint              offset,
95                                                    gint              *x,
96                                                    gint              *y,
97                                                    gint              *width,
98                                                    gint              *height,
99                                                    AtkCoordType      coords);
100static gint gail_expander_get_offset_at_point      (AtkText           *text,
101                                                    gint              x,
102                                                    gint              y,
103                                                    AtkCoordType      coords);
104static AtkAttributeSet* gail_expander_get_run_attributes
105                                                   (AtkText           *text,
106                                                    gint              offset,
107                                                    gint              *start_offset,
108                                                    gint              *end_offset);
109static AtkAttributeSet* gail_expander_get_default_attributes
110                                                   (AtkText           *text);
111
112static GailContainer* parent_class = NULL;
113
114GType
115gail_expander_get_type (void)
116{
117  static GType type = 0;
118
119  if (!type)
120    {
121      static const GTypeInfo tinfo =
122      {
123        sizeof (GailExpanderClass),
124        (GBaseInitFunc) NULL, /* base init */
125        (GBaseFinalizeFunc) NULL, /* base finalize */
126        (GClassInitFunc) gail_expander_class_init, /* class init */
127        (GClassFinalizeFunc) NULL, /* class finalize */
128        NULL, /* class data */
129        sizeof (GailExpander), /* instance size */
130        0, /* nb preallocs */
131        (GInstanceInitFunc) gail_expander_object_init, /* instance init */
132        NULL /* value table */
133      };
134
135      static const GInterfaceInfo atk_action_info =
136      {
137        (GInterfaceInitFunc) atk_action_interface_init,
138        (GInterfaceFinalizeFunc) NULL,
139        NULL
140      };
141
142      static const GInterfaceInfo atk_text_info =
143      {
144        (GInterfaceInitFunc) atk_text_interface_init,
145        (GInterfaceFinalizeFunc) NULL,
146        NULL
147      };
148
149      type = g_type_register_static (GAIL_TYPE_CONTAINER,
150                                     "GailExpander", &tinfo, 0);
151
152      g_type_add_interface_static (type, ATK_TYPE_ACTION,
153                                   &atk_action_info);
154      g_type_add_interface_static (type, ATK_TYPE_TEXT,
155                                   &atk_text_info);
156
157    }
158
159  return type;
160}
161
162static void
163gail_expander_class_init (GailExpanderClass *klass)
164{
165  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
166  AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
167  GailWidgetClass *widget_class;
168
169  widget_class = (GailWidgetClass*)klass;
170  widget_class->notify_gtk = gail_expander_real_notify_gtk;
171
172  gobject_class->finalize = gail_expander_finalize;
173
174  parent_class = g_type_class_peek_parent (klass);
175
176  class->get_name = gail_expander_get_name;
177  class->get_n_children = gail_expander_get_n_children;
178  class->ref_child = gail_expander_ref_child;
179  class->ref_state_set = gail_expander_ref_state_set;
180
181  class->initialize = gail_expander_real_initialize;
182}
183
184static void
185gail_expander_object_init (GailExpander *expander)
186{
187  expander->activate_description = NULL;
188  expander->activate_keybinding = NULL;
189  expander->action_idle_handler = 0;
190  expander->textutil = NULL;
191}
192
193AtkObject*
194gail_expander_new (GtkWidget *widget)
195{
196  GObject *object;
197  AtkObject *accessible;
198
199  g_return_val_if_fail (GTK_IS_EXPANDER (widget), NULL);
200
201  object = g_object_new (GAIL_TYPE_EXPANDER, NULL);
202
203  accessible = ATK_OBJECT (object);
204  atk_object_initialize (accessible, widget);
205
206  return accessible;
207}
208
209static G_CONST_RETURN gchar*
210gail_expander_get_name (AtkObject *obj)
211{
212  G_CONST_RETURN gchar *name;
213  g_return_val_if_fail (GAIL_IS_EXPANDER (obj), NULL);
214
215  name = ATK_OBJECT_CLASS (parent_class)->get_name (obj);
216  if (name != NULL)
217    return name;
218  else
219    {
220      /*
221       * Get the text on the label
222       */
223      GtkWidget *widget;
224
225      widget = GTK_ACCESSIBLE (obj)->widget;
226      if (widget == NULL)
227        /*
228         * State is defunct
229         */
230        return NULL;
231
232      g_return_val_if_fail (GTK_IS_EXPANDER (widget), NULL);
233
234      return gtk_expander_get_label (GTK_EXPANDER (widget));
235    }
236}
237
238static gint
239gail_expander_get_n_children (AtkObject* obj)
240{
241  GtkWidget *widget;
242  GtkWidget *child;
243
244  widget = GTK_ACCESSIBLE (obj)->widget;
245
246  if (widget == NULL)
247    return 0;
248
249  child = GTK_BIN (widget)->child;
250  if (child && !GTK_IS_LABEL (child))
251    return 1;
252
253  return 0;
254}
255
256static AtkObject*
257gail_expander_ref_child (AtkObject *obj,
258                         gint      i)
259{
260  GtkWidget *widget;
261  GtkWidget *child;
262  AtkObject *child_obj;
263
264  widget = GTK_ACCESSIBLE (obj)->widget;
265
266  if (widget == NULL)
267    return NULL;
268
269  if (i != 0)
270    return NULL;
271   
272  child = GTK_BIN (widget)->child;
273  if (child && !GTK_IS_LABEL (child))
274    {
275      child_obj = gtk_widget_get_accessible (child);
276      return g_object_ref (child_obj);
277    }
278
279  return NULL;
280}
281
282static void
283gail_expander_real_initialize (AtkObject *obj,
284                               gpointer   data)
285{
286  GailExpander *gail_expander = GAIL_EXPANDER (obj);
287  GtkWidget  *expander;
288
289  ATK_OBJECT_CLASS (parent_class)->initialize (obj, data);
290
291  expander = GTK_WIDGET (data);
292  if (GTK_WIDGET_MAPPED (expander))
293    gail_expander_init_textutil (gail_expander, GTK_EXPANDER (expander));
294  else
295    g_signal_connect (expander,
296                      "map",
297                      G_CALLBACK (gail_expander_map_gtk),
298                      gail_expander);
299 
300  obj->role = ATK_ROLE_TOGGLE_BUTTON;
301}
302
303static void
304gail_expander_map_gtk (GtkWidget *widget,
305                       gpointer data)
306{
307  GailExpander *expander;
308
309  expander = GAIL_EXPANDER (data);
310  gail_expander_init_textutil (expander, GTK_EXPANDER (widget));
311}
312
313static void
314gail_expander_real_notify_gtk (GObject    *obj,
315                               GParamSpec *pspec)
316{
317  AtkObject* atk_obj;
318  GtkExpander *expander;
319  GailExpander *gail_expander;
320
321  expander = GTK_EXPANDER (obj);
322  atk_obj = gtk_widget_get_accessible (GTK_WIDGET (expander));
323;
324  if (strcmp (pspec->name, "label") == 0)
325    {
326      const gchar* label_text;
327
328
329      label_text = gtk_expander_get_label (expander);
330
331      gail_expander = GAIL_EXPANDER (atk_obj);
332      if (gail_expander->textutil)
333        gail_text_util_text_setup (gail_expander->textutil, label_text);
334
335      if (atk_obj->name == NULL)
336      {
337        /*
338         * The label has changed so notify a change in accessible-name
339         */
340        g_object_notify (G_OBJECT (atk_obj), "accessible-name");
341      }
342      /*
343       * The label is the only property which can be changed
344       */
345      g_signal_emit_by_name (atk_obj, "visible_data_changed");
346    }
347  else if (strcmp (pspec->name, "expanded") == 0)
348    {
349      atk_object_notify_state_change (atk_obj, ATK_STATE_CHECKED,
350                                      gtk_expander_get_expanded (expander));
351      g_signal_emit_by_name (atk_obj, "visible_data_changed");
352    }
353  else
354    GAIL_WIDGET_CLASS (parent_class)->notify_gtk (obj, pspec);
355}
356
357static void
358gail_expander_init_textutil (GailExpander *expander,
359                             GtkExpander  *widget)
360{
361  const gchar *label_text;
362
363  expander->textutil = gail_text_util_new ();
364  label_text = gtk_expander_get_label (widget);
365  gail_text_util_text_setup (expander->textutil, label_text);
366}
367
368static void
369atk_action_interface_init (AtkActionIface *iface)
370{
371  g_return_if_fail (iface != NULL);
372
373  iface->do_action = gail_expander_do_action;
374  iface->get_n_actions = gail_expander_get_n_actions;
375  iface->get_description = gail_expander_get_description;
376  iface->get_keybinding = gail_expander_get_keybinding;
377  iface->get_name = gail_expander_action_get_name;
378  iface->set_description = gail_expander_set_description;
379}
380
381static gboolean
382gail_expander_do_action (AtkAction *action,
383                         gint      i)
384{
385  GtkWidget *widget;
386  GailExpander *expander;
387  gboolean return_value = TRUE;
388
389  widget = GTK_ACCESSIBLE (action)->widget;
390  if (widget == NULL)
391    /*
392     * State is defunct
393     */
394    return FALSE;
395
396  if (!GTK_WIDGET_IS_SENSITIVE (widget) || !GTK_WIDGET_VISIBLE (widget))
397    return FALSE;
398
399  expander = GAIL_EXPANDER (action);
400  switch (i)
401    {
402    case 0:
403      if (expander->action_idle_handler)
404        return_value = FALSE;
405      else
406        expander->action_idle_handler = g_idle_add (idle_do_action, expander);
407      break;
408    default:
409      return_value = FALSE;
410      break;
411    }
412  return return_value;
413}
414
415static gboolean
416idle_do_action (gpointer data)
417{
418  GtkWidget *widget;
419  GailExpander *gail_expander;
420
421  gail_expander = GAIL_EXPANDER (data);
422  gail_expander->action_idle_handler = 0;
423
424  widget = GTK_ACCESSIBLE (gail_expander)->widget;
425  if (widget == NULL)
426    /*
427     * State is defunct
428     */
429    return FALSE;
430
431  if (!GTK_WIDGET_IS_SENSITIVE (widget) || !GTK_WIDGET_VISIBLE (widget))
432    return FALSE;
433
434  gtk_widget_activate (widget);
435  return FALSE;
436}
437
438static gint
439gail_expander_get_n_actions (AtkAction *action)
440{
441  return 1;
442}
443
444static G_CONST_RETURN gchar*
445gail_expander_get_description (AtkAction *action,
446                               gint      i)
447{
448  GailExpander *expander;
449  G_CONST_RETURN gchar *return_value;
450
451  expander = GAIL_EXPANDER (action);
452
453  switch (i)
454    {
455    case 0:
456      return_value = expander->activate_description;
457      break;
458    default:
459      return_value = NULL;
460      break;
461    }
462  return return_value;
463}
464
465static G_CONST_RETURN gchar*
466gail_expander_get_keybinding (AtkAction *action,
467                              gint      i)
468{
469  GailExpander *expander;
470  gchar *return_value = NULL;
471
472  switch (i)
473    {
474    case 0:
475      {
476        /*
477         * We look for a mnemonic on the label
478         */
479        GtkWidget *widget;
480        GtkWidget *label;
481
482        expander = GAIL_EXPANDER (action);
483        widget = GTK_ACCESSIBLE (expander)->widget;
484        if (widget == NULL)
485          /*
486           * State is defunct
487           */
488          return NULL;
489
490        g_return_val_if_fail (GTK_IS_EXPANDER (widget), NULL);
491
492        label = gtk_expander_get_label_widget (GTK_EXPANDER (widget));
493        if (GTK_IS_LABEL (label))
494          {
495            guint key_val;
496
497            key_val = gtk_label_get_mnemonic_keyval (GTK_LABEL (label));
498            if (key_val != GDK_VoidSymbol)
499              return_value = gtk_accelerator_name (key_val, GDK_MOD1_MASK);
500            g_free (expander->activate_keybinding);
501            expander->activate_keybinding = return_value;
502          }
503        break;
504      }
505    default:
506      break;
507    }
508  return return_value;
509}
510
511static G_CONST_RETURN gchar*
512gail_expander_action_get_name (AtkAction *action,
513                               gint      i)
514{
515  G_CONST_RETURN gchar *return_value;
516
517  switch (i)
518    {
519    case 0:
520      return_value = "activate";
521      break;
522    default:
523      return_value = NULL;
524      break;
525    }
526  return return_value;
527}
528
529static gboolean
530gail_expander_set_description (AtkAction      *action,
531                               gint           i,
532                               const gchar    *desc)
533{
534  GailExpander *expander;
535  gchar **value;
536
537  expander = GAIL_EXPANDER (action);
538
539  switch (i)
540    {
541    case 0:
542      value = &expander->activate_description;
543      break;
544    default:
545      value = NULL;
546      break;
547    }
548  if (value)
549    {
550      g_free (*value);
551      *value = g_strdup (desc);
552      return TRUE;
553    }
554  else
555    return FALSE;
556}
557
558static AtkStateSet*
559gail_expander_ref_state_set (AtkObject *obj)
560{
561  AtkStateSet *state_set;
562  GtkWidget *widget;
563  GtkExpander *expander;
564
565  state_set = ATK_OBJECT_CLASS (parent_class)->ref_state_set (obj);
566  widget = GTK_ACCESSIBLE (obj)->widget;
567
568  if (widget == NULL)
569    return state_set;
570
571  expander = GTK_EXPANDER (widget);
572
573  if (gtk_expander_get_expanded (expander))
574    atk_state_set_add_state (state_set, ATK_STATE_CHECKED);
575
576  return state_set;
577}
578
579/* atktext.h */
580
581static void
582atk_text_interface_init (AtkTextIface *iface)
583{
584  g_return_if_fail (iface != NULL);
585  iface->get_text = gail_expander_get_text;
586  iface->get_character_at_offset = gail_expander_get_character_at_offset;
587  iface->get_text_before_offset = gail_expander_get_text_before_offset;
588  iface->get_text_at_offset = gail_expander_get_text_at_offset;
589  iface->get_text_after_offset = gail_expander_get_text_after_offset;
590  iface->get_character_count = gail_expander_get_character_count;
591  iface->get_character_extents = gail_expander_get_character_extents;
592  iface->get_offset_at_point = gail_expander_get_offset_at_point;
593  iface->get_run_attributes = gail_expander_get_run_attributes;
594  iface->get_default_attributes = gail_expander_get_default_attributes;
595}
596
597static gchar*
598gail_expander_get_text (AtkText *text,
599                        gint    start_pos,
600                        gint    end_pos)
601{
602  GtkWidget *widget;
603  GailExpander *expander;
604  const gchar *label_text;
605
606  widget = GTK_ACCESSIBLE (text)->widget;
607  if (widget == NULL)
608    /* State is defunct */
609    return NULL;
610
611  expander = GAIL_EXPANDER (text);
612  if (!expander->textutil)
613    gail_expander_init_textutil (expander, GTK_EXPANDER (widget));
614
615  label_text = gtk_expander_get_label (GTK_EXPANDER (widget));
616
617  if (label_text == NULL)
618    return NULL;
619  else
620    return gail_text_util_get_substring (expander->textutil,
621                                         start_pos, end_pos);
622}
623
624static gchar*
625gail_expander_get_text_before_offset (AtkText         *text,
626                                      gint            offset,
627                                      AtkTextBoundary boundary_type,
628                                      gint            *start_offset,
629                                      gint            *end_offset)
630{
631  GtkWidget *widget;
632  GailExpander *expander;
633  GtkWidget *label;
634
635  widget = GTK_ACCESSIBLE (text)->widget;
636  if (widget == NULL)
637    /* State is defunct */
638    return NULL;
639
640  expander = GAIL_EXPANDER (text);
641  if (!expander->textutil)
642    gail_expander_init_textutil (expander, GTK_EXPANDER (widget));
643
644  label = gtk_expander_get_label_widget (GTK_EXPANDER (widget));
645  if (!GTK_IS_LABEL(label))
646    return NULL;
647  return gail_text_util_get_text (expander->textutil,
648                           gtk_label_get_layout (GTK_LABEL (label)),
649                           GAIL_BEFORE_OFFSET,
650                           boundary_type, offset, start_offset, end_offset);
651}
652
653static gchar*
654gail_expander_get_text_at_offset (AtkText         *text,
655                                  gint            offset,
656                                  AtkTextBoundary boundary_type,
657                                  gint            *start_offset,
658                                  gint            *end_offset)
659{
660  GtkWidget *widget;
661  GailExpander *expander;
662  GtkWidget *label;
663
664  widget = GTK_ACCESSIBLE (text)->widget;
665  if (widget == NULL)
666    /* State is defunct */
667    return NULL;
668
669  expander = GAIL_EXPANDER (text);
670  if (!expander->textutil)
671    gail_expander_init_textutil (expander, GTK_EXPANDER (widget));
672
673  label = gtk_expander_get_label_widget (GTK_EXPANDER (widget));
674  if (!GTK_IS_LABEL(label))
675    return NULL;
676  return gail_text_util_get_text (expander->textutil,
677                           gtk_label_get_layout (GTK_LABEL (label)),
678                           GAIL_AT_OFFSET,
679                           boundary_type, offset, start_offset, end_offset);
680}
681
682static gchar*
683gail_expander_get_text_after_offset (AtkText         *text,
684                                     gint            offset,
685                                     AtkTextBoundary boundary_type,
686                                     gint            *start_offset,
687                                     gint            *end_offset)
688{
689  GtkWidget *widget;
690  GailExpander *expander;
691  GtkWidget *label;
692
693  widget = GTK_ACCESSIBLE (text)->widget;
694  if (widget == NULL)
695    /* State is defunct */
696    return NULL;
697
698  expander = GAIL_EXPANDER (text);
699  if (!expander->textutil)
700    gail_expander_init_textutil (expander, GTK_EXPANDER (widget));
701
702  label = gtk_expander_get_label_widget (GTK_EXPANDER (widget));
703  if (!GTK_IS_LABEL(label))
704    return NULL;
705  return gail_text_util_get_text (expander->textutil,
706                           gtk_label_get_layout (GTK_LABEL (label)),
707                           GAIL_AFTER_OFFSET,
708                           boundary_type, offset, start_offset, end_offset);
709}
710
711static gint
712gail_expander_get_character_count (AtkText *text)
713{
714  GtkWidget *widget;
715  GtkWidget *label;
716
717  widget = GTK_ACCESSIBLE (text)->widget;
718  if (widget == NULL)
719    /* State is defunct */
720    return 0;
721
722  label = gtk_expander_get_label_widget (GTK_EXPANDER (widget));
723  if (!GTK_IS_LABEL(label))
724    return 0;
725
726  return g_utf8_strlen (gtk_label_get_text (GTK_LABEL (label)), -1);
727}
728
729static void
730gail_expander_get_character_extents (AtkText      *text,
731                                     gint         offset,
732                                     gint         *x,
733                                     gint       *y,
734                                     gint       *width,
735                                     gint       *height,
736                                     AtkCoordType coords)
737{
738  GtkWidget *widget;
739  GtkWidget *label;
740  PangoRectangle char_rect;
741  gint index, x_layout, y_layout;
742  const gchar *label_text;
743 
744  widget = GTK_ACCESSIBLE (text)->widget;
745
746  if (widget == NULL)
747    /* State is defunct */
748    return;
749
750  label = gtk_expander_get_label_widget (GTK_EXPANDER (widget));
751  if (!GTK_IS_LABEL(label))
752    return;
753 
754  gtk_label_get_layout_offsets (GTK_LABEL (label), &x_layout, &y_layout);
755  label_text = gtk_label_get_text (GTK_LABEL (label));
756  index = g_utf8_offset_to_pointer (label_text, offset) - label_text;
757  pango_layout_index_to_pos (gtk_label_get_layout (GTK_LABEL (label)), index, &char_rect);
758 
759  gail_misc_get_extents_from_pango_rectangle (label, &char_rect,
760                    x_layout, y_layout, x, y, width, height, coords);
761}
762
763static gint
764gail_expander_get_offset_at_point (AtkText      *text,
765                                   gint         x,
766                                   gint         y,
767                                   AtkCoordType coords)
768{
769  GtkWidget *widget;
770  GtkWidget *label;
771  gint index, x_layout, y_layout;
772  const gchar *label_text;
773
774  widget = GTK_ACCESSIBLE (text)->widget;
775  if (widget == NULL)
776    /* State is defunct */
777    return -1;
778  label = gtk_expander_get_label_widget (GTK_EXPANDER (widget));
779
780  if (!GTK_IS_LABEL(label))
781    return -1;
782 
783  gtk_label_get_layout_offsets (GTK_LABEL (label), &x_layout, &y_layout);
784 
785  index = gail_misc_get_index_at_point_in_layout (label,
786                                              gtk_label_get_layout (GTK_LABEL (label)),
787                                              x_layout, y_layout, x, y, coords);
788  label_text = gtk_label_get_text (GTK_LABEL (label));
789  if (index == -1)
790    {
791      if (coords == ATK_XY_WINDOW || coords == ATK_XY_SCREEN)
792        return g_utf8_strlen (label_text, -1);
793
794      return index; 
795    }
796  else
797    return g_utf8_pointer_to_offset (label_text, label_text + index); 
798}
799
800static AtkAttributeSet*
801gail_expander_get_run_attributes (AtkText *text,
802                                  gint    offset,
803                                  gint    *start_offset,
804                                  gint    *end_offset)
805{
806  GtkWidget *widget;
807  GtkWidget *label;
808  AtkAttributeSet *at_set = NULL;
809  GtkJustification justify;
810  GtkTextDirection dir;
811
812  widget = GTK_ACCESSIBLE (text)->widget;
813  if (widget == NULL)
814    /* State is defunct */
815    return NULL;
816
817  label = gtk_expander_get_label_widget (GTK_EXPANDER (widget));
818
819  if (!GTK_IS_LABEL(label))
820    return NULL;
821 
822  /* Get values set for entire label, if any */
823  justify = gtk_label_get_justify (GTK_LABEL (label));
824  if (justify != GTK_JUSTIFY_CENTER)
825    {
826      at_set = gail_misc_add_attribute (at_set,
827                                        ATK_TEXT_ATTR_JUSTIFICATION,
828     g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_JUSTIFICATION, justify)));
829    }
830  dir = gtk_widget_get_direction (label);
831  if (dir == GTK_TEXT_DIR_RTL)
832    {
833      at_set = gail_misc_add_attribute (at_set,
834                                        ATK_TEXT_ATTR_DIRECTION,
835     g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_DIRECTION, dir)));
836    }
837
838  at_set = gail_misc_layout_get_run_attributes (at_set,
839                                                gtk_label_get_layout (GTK_LABEL (label)),
840                                                (gchar *) gtk_label_get_text (GTK_LABEL (label)),
841                                                offset,
842                                                start_offset,
843                                                end_offset);
844  return at_set;
845}
846
847static AtkAttributeSet*
848gail_expander_get_default_attributes (AtkText *text)
849{
850  GtkWidget *widget;
851  GtkWidget *label;
852  AtkAttributeSet *at_set = NULL;
853
854  widget = GTK_ACCESSIBLE (text)->widget;
855  if (widget == NULL)
856    /* State is defunct */
857    return NULL;
858
859  label = gtk_expander_get_label_widget (GTK_EXPANDER (widget));
860
861  if (!GTK_IS_LABEL(label))
862    return NULL;
863
864  at_set = gail_misc_get_default_attributes (at_set,
865                                             gtk_label_get_layout (GTK_LABEL (label)),
866                                             widget);
867  return at_set;
868}
869
870static gunichar
871gail_expander_get_character_at_offset (AtkText *text,
872                                       gint    offset)
873{
874  GtkWidget *widget;
875  GtkWidget *label;
876  const gchar *string;
877  gchar *index;
878
879  widget = GTK_ACCESSIBLE (text)->widget;
880  if (widget == NULL)
881    /* State is defunct */
882    return '\0';
883
884  label = gtk_expander_get_label_widget (GTK_EXPANDER (widget));
885
886  if (!GTK_IS_LABEL(label))
887    return '\0';
888  string = gtk_label_get_text (GTK_LABEL (label));
889  if (offset >= g_utf8_strlen (string, -1))
890    return '\0';
891  index = g_utf8_offset_to_pointer (string, offset);
892
893  return g_utf8_get_char (index);
894}
895
896static void
897gail_expander_finalize (GObject *object)
898{
899  GailExpander *expander = GAIL_EXPANDER (object);
900
901  g_free (expander->activate_description);
902  g_free (expander->activate_keybinding);
903  if (expander->action_idle_handler)
904    {
905      g_source_remove (expander->action_idle_handler);
906      expander->action_idle_handler = 0;
907    }
908  if (expander->textutil)
909    g_object_unref (expander->textutil);
910
911  G_OBJECT_CLASS (parent_class)->finalize (object);
912}
Note: See TracBrowser for help on using the repository browser.