1 /* GAIL - The GNOME Accessibility Implementation Library
2 * Copyright 2001, 2002, 2003 Sun Microsystems Inc.
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.
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.
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.
22 #include "gailstatusbar.h"
23 #include <libgail-util/gailmisc.h>
25 static void gail_statusbar_class_init (GailStatusbarClass *klass);
26 static void gail_statusbar_init (GailStatusbar *bar);
27 static G_CONST_RETURN gchar* gail_statusbar_get_name (AtkObject *obj);
28 static gint gail_statusbar_get_n_children (AtkObject *obj);
29 static AtkObject* gail_statusbar_ref_child (AtkObject *obj,
31 static void gail_statusbar_real_initialize (AtkObject *obj,
34 static gint gail_statusbar_notify (GObject *obj,
37 static void gail_statusbar_finalize (GObject *object);
38 static void gail_statusbar_init_textutil (GailStatusbar *statusbar,
42 static void atk_text_interface_init (AtkTextIface *iface);
44 static gchar* gail_statusbar_get_text (AtkText *text,
47 static gunichar gail_statusbar_get_character_at_offset
50 static gchar* gail_statusbar_get_text_before_offset
53 AtkTextBoundary boundary_type,
56 static gchar* gail_statusbar_get_text_at_offset(AtkText *text,
58 AtkTextBoundary boundary_type,
61 static gchar* gail_statusbar_get_text_after_offset
64 AtkTextBoundary boundary_type,
67 static gint gail_statusbar_get_character_count (AtkText *text);
68 static void gail_statusbar_get_character_extents
76 static gint gail_statusbar_get_offset_at_point(AtkText *text,
80 static AtkAttributeSet* gail_statusbar_get_run_attributes
85 static AtkAttributeSet* gail_statusbar_get_default_attributes
87 static GtkWidget* get_label_from_statusbar (GtkWidget *statusbar);
89 G_DEFINE_TYPE_WITH_CODE (GailStatusbar, gail_statusbar, GAIL_TYPE_CONTAINER,
90 G_IMPLEMENT_INTERFACE (ATK_TYPE_TEXT, atk_text_interface_init))
93 gail_statusbar_class_init (GailStatusbarClass *klass)
95 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
96 AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
97 GailContainerClass *container_class;
99 container_class = (GailContainerClass*)klass;
101 gobject_class->finalize = gail_statusbar_finalize;
103 class->get_name = gail_statusbar_get_name;
104 class->get_n_children = gail_statusbar_get_n_children;
105 class->ref_child = gail_statusbar_ref_child;
106 class->initialize = gail_statusbar_real_initialize;
108 * As we report the statusbar as having no children we are not interested
109 * in add and remove signals
111 container_class->add_gtk = NULL;
112 container_class->remove_gtk = NULL;
116 gail_statusbar_init (GailStatusbar *bar)
121 gail_statusbar_new (GtkWidget *widget)
124 AtkObject *accessible;
126 g_return_val_if_fail (GTK_IS_STATUSBAR (widget), NULL);
128 object = g_object_new (GAIL_TYPE_STATUSBAR, NULL);
130 accessible = ATK_OBJECT (object);
131 atk_object_initialize (accessible, widget);
136 static G_CONST_RETURN gchar*
137 gail_statusbar_get_name (AtkObject *obj)
139 G_CONST_RETURN gchar* name;
141 g_return_val_if_fail (GAIL_IS_STATUSBAR (obj), NULL);
143 name = ATK_OBJECT_CLASS (gail_statusbar_parent_class)->get_name (obj);
149 * Get the text on the label
154 widget = GTK_ACCESSIBLE (obj)->widget;
161 g_return_val_if_fail (GTK_IS_STATUSBAR (widget), NULL);
162 label = get_label_from_statusbar (widget);
163 if (GTK_IS_LABEL (label))
164 return gtk_label_get_label (GTK_LABEL (label));
171 gail_statusbar_get_n_children (AtkObject *obj)
177 widget = GTK_ACCESSIBLE (obj)->widget;
181 children = gtk_container_get_children (GTK_CONTAINER (widget));
182 if (children != NULL)
184 count = g_list_length (children);
185 g_list_free (children);
192 gail_statusbar_ref_child (AtkObject *obj,
195 GList *children, *tmp_list;
196 AtkObject *accessible;
199 g_return_val_if_fail ((i >= 0), NULL);
200 widget = GTK_ACCESSIBLE (obj)->widget;
204 children = gtk_container_get_children (GTK_CONTAINER (widget));
205 if (children == NULL)
208 tmp_list = g_list_nth (children, i);
211 g_list_free (children);
214 accessible = gtk_widget_get_accessible (GTK_WIDGET (tmp_list->data));
216 g_list_free (children);
217 g_object_ref (accessible);
222 gail_statusbar_real_initialize (AtkObject *obj,
225 GailStatusbar *statusbar = GAIL_STATUSBAR (obj);
228 ATK_OBJECT_CLASS (gail_statusbar_parent_class)->initialize (obj, data);
231 * We get notified of changes to the label
233 label = get_label_from_statusbar (GTK_WIDGET (data));
234 if (GTK_IS_LABEL (label))
236 gail_statusbar_init_textutil (statusbar, label);
239 obj->role = ATK_ROLE_STATUSBAR;
244 gail_statusbar_notify (GObject *obj,
248 AtkObject *atk_obj = ATK_OBJECT (user_data);
250 GailStatusbar *statusbar;
252 if (strcmp (pspec->name, "label") == 0)
254 const gchar* label_text;
256 label = GTK_LABEL (obj);
258 label_text = gtk_label_get_text (label);
260 statusbar = GAIL_STATUSBAR (atk_obj);
261 gail_text_util_text_setup (statusbar->textutil, label_text);
263 if (atk_obj->name == NULL)
266 * The label has changed so notify a change in accessible-name
268 g_object_notify (G_OBJECT (atk_obj), "accessible-name");
271 * The label is the only property which can be changed
273 g_signal_emit_by_name (atk_obj, "visible_data_changed");
279 gail_statusbar_init_textutil (GailStatusbar *statusbar,
282 const gchar *label_text;
284 statusbar->textutil = gail_text_util_new ();
285 label_text = gtk_label_get_text (GTK_LABEL (label));
286 gail_text_util_text_setup (statusbar->textutil, label_text);
287 g_signal_connect (label,
289 (GCallback) gail_statusbar_notify,
294 gail_statusbar_finalize (GObject *object)
296 GailStatusbar *statusbar = GAIL_STATUSBAR (object);
298 if (statusbar->textutil)
300 g_object_unref (statusbar->textutil);
302 G_OBJECT_CLASS (gail_statusbar_parent_class)->finalize (object);
308 atk_text_interface_init (AtkTextIface *iface)
310 iface->get_text = gail_statusbar_get_text;
311 iface->get_character_at_offset = gail_statusbar_get_character_at_offset;
312 iface->get_text_before_offset = gail_statusbar_get_text_before_offset;
313 iface->get_text_at_offset = gail_statusbar_get_text_at_offset;
314 iface->get_text_after_offset = gail_statusbar_get_text_after_offset;
315 iface->get_character_count = gail_statusbar_get_character_count;
316 iface->get_character_extents = gail_statusbar_get_character_extents;
317 iface->get_offset_at_point = gail_statusbar_get_offset_at_point;
318 iface->get_run_attributes = gail_statusbar_get_run_attributes;
319 iface->get_default_attributes = gail_statusbar_get_default_attributes;
323 gail_statusbar_get_text (AtkText *text,
329 GailStatusbar *statusbar;
330 const gchar *label_text;
332 widget = GTK_ACCESSIBLE (text)->widget;
334 /* State is defunct */
337 label = get_label_from_statusbar (widget);
339 if (!GTK_IS_LABEL (label))
342 statusbar = GAIL_STATUSBAR (text);
343 if (!statusbar->textutil)
344 gail_statusbar_init_textutil (statusbar, label);
346 label_text = gtk_label_get_text (GTK_LABEL (label));
348 if (label_text == NULL)
352 return gail_text_util_get_substring (statusbar->textutil,
358 gail_statusbar_get_text_before_offset (AtkText *text,
360 AtkTextBoundary boundary_type,
366 GailStatusbar *statusbar;
368 widget = GTK_ACCESSIBLE (text)->widget;
371 /* State is defunct */
375 label = get_label_from_statusbar (widget);
377 if (!GTK_IS_LABEL(label))
380 statusbar = GAIL_STATUSBAR (text);
381 if (!statusbar->textutil)
382 gail_statusbar_init_textutil (statusbar, label);
384 return gail_text_util_get_text (statusbar->textutil,
385 gtk_label_get_layout (GTK_LABEL (label)), GAIL_BEFORE_OFFSET,
386 boundary_type, offset, start_offset, end_offset);
390 gail_statusbar_get_text_at_offset (AtkText *text,
392 AtkTextBoundary boundary_type,
398 GailStatusbar *statusbar;
400 widget = GTK_ACCESSIBLE (text)->widget;
403 /* State is defunct */
407 label = get_label_from_statusbar (widget);
409 if (!GTK_IS_LABEL(label))
412 statusbar = GAIL_STATUSBAR (text);
413 if (!statusbar->textutil)
414 gail_statusbar_init_textutil (statusbar, label);
416 return gail_text_util_get_text (statusbar->textutil,
417 gtk_label_get_layout (GTK_LABEL (label)), GAIL_AT_OFFSET,
418 boundary_type, offset, start_offset, end_offset);
422 gail_statusbar_get_text_after_offset (AtkText *text,
424 AtkTextBoundary boundary_type,
430 GailStatusbar *statusbar;
432 widget = GTK_ACCESSIBLE (text)->widget;
436 /* State is defunct */
441 label = get_label_from_statusbar (widget);
443 if (!GTK_IS_LABEL(label))
446 statusbar = GAIL_STATUSBAR (text);
447 if (!statusbar->textutil)
448 gail_statusbar_init_textutil (statusbar, label);
450 return gail_text_util_get_text (statusbar->textutil,
451 gtk_label_get_layout (GTK_LABEL (label)), GAIL_AFTER_OFFSET,
452 boundary_type, offset, start_offset, end_offset);
456 gail_statusbar_get_character_count (AtkText *text)
461 widget = GTK_ACCESSIBLE (text)->widget;
463 /* State is defunct */
466 label = get_label_from_statusbar (widget);
468 if (!GTK_IS_LABEL(label))
471 return g_utf8_strlen (gtk_label_get_text (GTK_LABEL (label)), -1);
475 gail_statusbar_get_character_extents (AtkText *text,
485 PangoRectangle char_rect;
486 gint index, x_layout, y_layout;
487 const gchar *label_text;
489 widget = GTK_ACCESSIBLE (text)->widget;
492 /* State is defunct */
495 label = get_label_from_statusbar (widget);
497 if (!GTK_IS_LABEL(label))
500 gtk_label_get_layout_offsets (GTK_LABEL (label), &x_layout, &y_layout);
501 label_text = gtk_label_get_text (GTK_LABEL (label));
502 index = g_utf8_offset_to_pointer (label_text, offset) - label_text;
503 pango_layout_index_to_pos (gtk_label_get_layout (GTK_LABEL (label)), index, &char_rect);
505 gail_misc_get_extents_from_pango_rectangle (label, &char_rect,
506 x_layout, y_layout, x, y, width, height, coords);
510 gail_statusbar_get_offset_at_point (AtkText *text,
517 gint index, x_layout, y_layout;
518 const gchar *label_text;
520 widget = GTK_ACCESSIBLE (text)->widget;
522 /* State is defunct */
525 label = get_label_from_statusbar (widget);
527 if (!GTK_IS_LABEL(label))
530 gtk_label_get_layout_offsets (GTK_LABEL (label), &x_layout, &y_layout);
532 index = gail_misc_get_index_at_point_in_layout (label,
533 gtk_label_get_layout (GTK_LABEL (label)),
534 x_layout, y_layout, x, y, coords);
535 label_text = gtk_label_get_text (GTK_LABEL (label));
538 if (coords == ATK_XY_WINDOW || coords == ATK_XY_SCREEN)
539 return g_utf8_strlen (label_text, -1);
544 return g_utf8_pointer_to_offset (label_text, label_text + index);
547 static AtkAttributeSet*
548 gail_statusbar_get_run_attributes (AtkText *text,
555 AtkAttributeSet *at_set = NULL;
556 GtkJustification justify;
557 GtkTextDirection dir;
559 widget = GTK_ACCESSIBLE (text)->widget;
561 /* State is defunct */
564 label = get_label_from_statusbar (widget);
566 if (!GTK_IS_LABEL(label))
569 /* Get values set for entire label, if any */
570 justify = gtk_label_get_justify (GTK_LABEL (label));
571 if (justify != GTK_JUSTIFY_CENTER)
573 at_set = gail_misc_add_attribute (at_set,
574 ATK_TEXT_ATTR_JUSTIFICATION,
575 g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_JUSTIFICATION, justify)));
577 dir = gtk_widget_get_direction (label);
578 if (dir == GTK_TEXT_DIR_RTL)
580 at_set = gail_misc_add_attribute (at_set,
581 ATK_TEXT_ATTR_DIRECTION,
582 g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_DIRECTION, dir)));
585 at_set = gail_misc_layout_get_run_attributes (at_set,
586 gtk_label_get_layout (GTK_LABEL (label)),
587 (gchar *) gtk_label_get_text (GTK_LABEL (label)),
594 static AtkAttributeSet*
595 gail_statusbar_get_default_attributes (AtkText *text)
599 AtkAttributeSet *at_set = NULL;
601 widget = GTK_ACCESSIBLE (text)->widget;
603 /* State is defunct */
606 label = get_label_from_statusbar (widget);
608 if (!GTK_IS_LABEL(label))
611 at_set = gail_misc_get_default_attributes (at_set,
612 gtk_label_get_layout (GTK_LABEL (label)),
618 gail_statusbar_get_character_at_offset (AtkText *text,
626 widget = GTK_ACCESSIBLE (text)->widget;
628 /* State is defunct */
631 label = get_label_from_statusbar (widget);
633 if (!GTK_IS_LABEL(label))
635 string = gtk_label_get_text (GTK_LABEL (label));
636 if (offset >= g_utf8_strlen (string, -1))
638 index = g_utf8_offset_to_pointer (string, offset);
640 return g_utf8_get_char (index);
644 get_label_from_statusbar (GtkWidget *statusbar)
646 return GTK_STATUSBAR (statusbar)->label;