2 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
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 License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
22 * @brief EailLabel implementation.
25 #include <Elementary.h>
27 #include "eail_label.h"
28 #include "eail_utils.h"
30 static void atk_text_interface_init(AtkTextIface *iface);
33 * @brief EailLabel type definition
35 G_DEFINE_TYPE_WITH_CODE(EailLabel,
38 G_IMPLEMENT_INTERFACE(ATK_TYPE_TEXT,
39 atk_text_interface_init));
42 * @brief EailLabel initializer.
44 * @param obj EailLabel instance
45 * @param data initialization data
48 eail_label_initialize(AtkObject *obj, gpointer data)
50 ATK_OBJECT_CLASS(eail_label_parent_class)->initialize(obj, data);
51 obj->role = ATK_ROLE_LABEL;
55 * @brief EailLabel interface intializer.
57 * @param label EailLabel instance
60 eail_label_init(EailLabel *label)
65 * @brief Gets the state set of the accessible.
67 * The caller must unreference it when it is no longer needed.
69 * @param accessible AtkObject instance
70 * @return AtkStateSet containing the state set of the accessible
73 eail_label_ref_state_set(AtkObject *accessible)
75 AtkStateSet *state_set;
79 ATK_OBJECT_CLASS(eail_label_parent_class)->ref_state_set(accessible);
81 widget = eail_widget_get_widget(EAIL_WIDGET(accessible));
82 if (!widget) return state_set;
84 atk_state_set_add_state(state_set, ATK_STATE_MULTI_LINE);
90 * @brief Gets obj's name
92 * @param obj AtkObject instance
93 * @returns string containing obj's name or its text content if the name is not set
96 eail_label_get_name(AtkObject *obj)
101 name = ATK_OBJECT_CLASS(eail_label_parent_class)->get_name(obj);
105 widget = eail_widget_get_widget(EAIL_WIDGET(obj));
106 if (!widget) return NULL;
108 name = (const gchar*)elm_object_text_get(widget);
109 if (!name) return NULL;
115 * @brief EailLabel class initializer.
117 * @param klass EailLabelClass instance
120 eail_label_class_init(EailLabelClass *klass)
122 AtkObjectClass *atk_class = ATK_OBJECT_CLASS(klass);
124 atk_class->initialize = eail_label_initialize;
125 atk_class->ref_state_set = eail_label_ref_state_set;
126 atk_class->get_name = eail_label_get_name;
130 * @brief Gets text bounded by start_offset and end_offset
132 * Use g_free() to free the returned string
134 * @param text an AtkText
135 * @param start_offset start position
136 * @param end_offset end position, -1 for the end of the string
137 * @return string containing text from start_offset up to, but not including
141 eail_label_get_text(AtkText *text,
145 gchar *string = NULL;
146 Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(text));
149 string = (gchar *)elm_object_text_get(widget);
154 return eail_get_substring(string, start_offset, end_offset);
158 * @brief Gets the character at offset
160 * @param text AtkText instance
161 * @param offset character offset
162 * @return char located at the given offset
165 eail_label_get_character_at_offset(AtkText *text,
168 gunichar character = '\0';
169 Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(text));
172 character = g_utf8_get_char(
173 g_utf8_offset_to_pointer(elm_object_text_get(widget), offset));
179 * @brief Gets the length of text
181 * @param text AtkText instance
182 * @return integer representing the length of text
185 eail_label_get_character_count(AtkText *text)
190 widget = eail_widget_get_widget(EAIL_WIDGET(text));
194 str = elm_object_text_get(widget);
197 return g_utf8_strlen(str, -1);
201 * @brief Creates an AtkAttributeSet which consists of the default values of
202 * attributes for the text.
204 * This AtkAttributeSet should be freed by a call to
205 * atk_attribute_set_free()
207 * @param text AtkText instance
209 * @returns AtkAttributeSet containing default values of attributes
212 static AtkAttributeSet *
213 eail_label_get_default_attributes(AtkText *text)
215 AtkAttributeSet *at_set = NULL;
217 at_set = eail_utils_text_add_attribute
218 (at_set, ATK_TEXT_ATTR_WRAP_MODE,
219 atk_text_attribute_get_value(ATK_TEXT_ATTR_WRAP_MODE, 0));
221 at_set = eail_utils_text_add_attribute
222 (at_set, ATK_TEXT_ATTR_EDITABLE,
223 atk_text_attribute_get_value
224 (ATK_TEXT_ATTR_EDITABLE, FALSE));
230 * @brief Creates an AtkAttributeSet which consists of the attributes
231 * explicitly set at the position offset in the text.
233 * start_offset and end_offset are set to the start and end of the range around offset
234 * where the attributes are invariant.
236 * Note that end_offset is the offset of the first character after the range.
238 * This AtkAttributeSet should be freed by a call to
239 * atk_attribute_set_free()
241 * @param text AtkText instance
242 * @param offset the offset at which to get the attributes
243 * @param [out] start_offset start offset of the range
244 * @param [out] end_offset end offset of the range
246 * @returns an AtkAttributeSet which contains the attributes explicitly set at
249 static AtkAttributeSet *
250 eail_label_get_run_attributes(AtkText *text,
255 AtkAttributeSet *at_set = NULL;
256 Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(text));
257 gint len = eail_label_get_character_count(ATK_TEXT(text));
259 if (!widget || offset >= len)
270 /* NOTE: Elm_Wrap_Type value is in 100% compatible with ATK wrap modes, so
271 * no additional conversion is needed*/
272 Elm_Wrap_Type wrap_type = elm_label_line_wrap_get(widget);
273 at_set = eail_utils_text_add_attribute
274 (at_set, ATK_TEXT_ATTR_WRAP_MODE,
275 atk_text_attribute_get_value
276 (ATK_TEXT_ATTR_WRAP_MODE, wrap_type));
278 at_set = eail_utils_text_add_attribute
279 (at_set, ATK_TEXT_ATTR_EDITABLE,
280 atk_text_attribute_get_value
281 (ATK_TEXT_ATTR_EDITABLE, FALSE));
287 * @brief Gets the specified text after offset
289 * Use g_free() to free the returned string.
291 * @param text AtkText instance
292 * @param offset character offset
293 * @param boundary_type AtkTextBoundary instance
294 * @param [out] start_offset start offset of the returned string
295 * @param [out] end_offset offset of the first character after the returned
297 * @returns newly allocated string containing the text after offset bounded
298 * by the specified boundary_type
301 eail_label_get_text_after_offset(AtkText *text,
303 AtkTextBoundary boundary_type,
308 const Evas_Object *textblock;
309 Evas_Object *label_edje_layer;
311 widget = eail_widget_get_widget(EAIL_WIDGET(text));
312 if (!widget) return NULL;
314 label_edje_layer = elm_layout_edje_get(widget);
315 textblock = edje_object_part_object_get(label_edje_layer, "elm.text");
317 return eail_get_text_after(textblock, offset, boundary_type, start_offset,
323 * @brief Gets the specified text at offset
325 * Use g_free() to free the returned string.
327 * @param text AtkText instance
328 * @param offset character offset
329 * @param boundary_type AtkTextBoundary instance
330 * @param [out] start_offset start offset of the returned string
331 * @param [out] end_offset offset of the first character after the returned
333 * @returns newly allocated string containing the text after offset bounded
334 * by the specified boundary_type
337 eail_label_get_text_at_offset(AtkText *text,
339 AtkTextBoundary boundary_type,
344 const Evas_Object *textblock;
345 Evas_Object *label_edje_layer;
347 widget = eail_widget_get_widget(EAIL_WIDGET(text));
348 if (!widget) return NULL;
350 label_edje_layer = elm_layout_edje_get(widget);
351 textblock = edje_object_part_object_get(label_edje_layer, "elm.text");
353 return eail_get_text_at(textblock, offset, boundary_type, start_offset,
358 * @brief Gets the specified text before offset
360 * Use g_free() to free the returned string.
362 * @param text AtkText instance
363 * @param offset character offset
364 * @param boundary_type AtkTextBoundary instance
365 * @param [out] start_offset start offset of the returned string
366 * @param [out] end_offset offset of the first character after the returned
368 * @returns newly allocated string containing the text after offset bounded
369 * by the specified boundary_type
372 eail_label_get_text_before_offset(AtkText *text,
374 AtkTextBoundary boundary_type,
379 const Evas_Object *textblock;
380 Evas_Object *label_edje_layer;
382 widget = eail_widget_get_widget(EAIL_WIDGET(text));
383 if (!widget) return NULL;
385 label_edje_layer = elm_layout_edje_get(widget);
386 textblock = edje_object_part_object_get(label_edje_layer, "elm.text");
388 return eail_get_text_before(textblock, offset, boundary_type, start_offset,
393 * @brief Gets the offset of the character located at coordinates x and y.
394 * x and y are interpreted as being relative to the screen or this widget's window depending on coords.
396 * @param text AtkText instance
397 * @param screen x-position of character
398 * @param screen y-position of character
399 * @param specify whether coordinates are relative to the screen or widget window
401 * @returns the offset to the character which is located at the specified x and y coordinates.
404 eail_label_get_offset_at_point(AtkText *text,
410 const Evas_Object *textblock = NULL;
411 Evas_Textblock_Cursor *cur = NULL;
412 Evas_Object *label_edje_layer = NULL;
414 Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(text));
416 if (!widget) return -1;
418 label_edje_layer = elm_layout_edje_get(widget);
420 if (!label_edje_layer) return-1 ;
422 textblock = edje_object_part_object_get(label_edje_layer, "elm.text");
423 cur = evas_object_textblock_cursor_new(textblock);
425 if (coords == ATK_XY_SCREEN)
428 Ecore_Evas *ee= ecore_evas_ecore_evas_get(evas_object_evas_get(widget));
429 ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
434 evas_textblock_cursor_char_coord_set( cur, x, y);
435 result = evas_textblock_cursor_pos_get( cur );
436 evas_textblock_cursor_free(cur);
442 * @brief Get the bounding box containing the glyph
443 * representing the character at a particular text offset.
445 * @param text AtkText instance
446 * @param offset The offset of the text character for which
447 * bounding information is required.
448 * @param x Pointer for the x cordinate of the bounding box
449 * @param y Pointer for the y cordinate of the bounding box
450 * @param width Pointer for the width of the bounding box
451 * @param height Pointer for the height of the bounding box
452 * @param coords specify whether coordinates are relative to the
453 * screen or widget window
457 eail_label_get_character_extents(AtkText *text,
466 const Evas_Object *textblock = NULL;
467 Evas_Textblock_Cursor *cur = NULL;
468 Evas_Object *label_edje_layer = NULL;
470 Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(text));
474 label_edje_layer = elm_layout_edje_get(widget);
476 if (!label_edje_layer) return;
478 textblock = edje_object_part_object_get(label_edje_layer, "elm.text");
480 cur = evas_object_textblock_cursor_new(textblock);
481 evas_textblock_cursor_pos_set(cur, offset);
483 result = evas_textblock_cursor_char_geometry_get(cur, x, y, width, height);
485 evas_textblock_cursor_free(cur);
487 if (-1 == result) return;
489 if (coords == ATK_XY_SCREEN)
492 Ecore_Evas *ee= ecore_evas_ecore_evas_get(evas_object_evas_get(widget));
494 ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
501 * @brief Sum all rectangles on list
503 * (function for internal use ony)
505 * @param list list with Evas_Textblock_Rectangle
507 * @return an Evas_Textblock_Rectangle encloses all rectanges from list
509 Evas_Textblock_Rectangle _internal_sum_rects_on_list(Eina_List *list)
511 Evas_Textblock_Rectangle result;
513 Evas_Coord min_x = 0;
514 Evas_Coord min_y = 0;
515 Evas_Coord max_x = 0;
516 Evas_Coord max_y = 0;
520 Evas_Textblock_Rectangle *rectT = NULL;
521 EINA_LIST_FOREACH(list, l, rectT)
527 max_x = rectT->x + rectT->w;
528 max_y = rectT->y + rectT->h;
533 Evas_Coord t_min_x = rectT->x;
534 Evas_Coord t_min_y = rectT->y;
535 Evas_Coord t_max_x = rectT->x + rectT->w;
536 Evas_Coord t_max_y = rectT->y + rectT->h;
539 if ( t_min_x < min_x )
541 if ( t_min_y < min_y )
543 if ( t_max_x > max_x )
545 if ( t_max_y > max_y )
552 result.w = max_x - min_x;
553 result.h = max_y - min_y;
559 * Get the bounding box for text within the specified range.
561 * @param text an AtkText
562 * @param start_offset The offset of the first text character for which boundary information is required.
563 * @param end_offset The offset of the text character after the last character for which boundary information is required.
564 * @param coord_type Specify whether coordinates are relative to the screen or widget window.
565 * @param [out] rect A pointer to a AtkTextRectangle which is filled in by this function.
567 void eail_label_get_range_extents(AtkText *text,
570 AtkCoordType coord_type,
571 AtkTextRectangle *rect)
573 if (start_offset >= end_offset)
576 Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(text));
577 Evas_Textblock_Cursor *cur1 = NULL;
578 Evas_Textblock_Cursor *cur2 = NULL;
579 Evas_Object *label_edje_layer = NULL;
580 const Evas_Object *textblock = NULL;
582 label_edje_layer = elm_layout_edje_get(widget);
583 textblock = edje_object_part_object_get(label_edje_layer, "elm.text");
584 cur1 = evas_object_textblock_cursor_new(textblock);
585 cur2 = evas_object_textblock_cursor_new(textblock);
587 evas_textblock_cursor_pos_set(cur1, start_offset);
588 evas_textblock_cursor_pos_set(cur2, end_offset);
590 Eina_List *list = NULL;
591 list = evas_textblock_cursor_range_geometry_get(cur1, cur2);
595 Evas_Textblock_Rectangle rect_list = _internal_sum_rects_on_list(list);
596 rect->x = rect_list.x;
597 rect->y = rect_list.y;
598 rect->width = rect_list.w;
599 rect->height = rect_list.h;
601 if (coord_type == ATK_XY_SCREEN)
604 Ecore_Evas *ee= ecore_evas_ecore_evas_get(evas_object_evas_get(widget));
606 ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
613 evas_textblock_cursor_free(cur1);
615 evas_textblock_cursor_free(cur2);
619 * @brief Initializes AtkTextIface interface
621 * @param iface AtkTextIface instance
624 atk_text_interface_init(AtkTextIface *iface)
626 iface->get_character_count = eail_label_get_character_count;
627 iface->get_character_at_offset = eail_label_get_character_at_offset;
628 iface->get_text = eail_label_get_text;
629 iface->get_run_attributes = eail_label_get_run_attributes;
630 iface->get_default_attributes = eail_label_get_default_attributes;
631 iface->get_text_after_offset = eail_label_get_text_after_offset;
632 iface->get_text_at_offset = eail_label_get_text_at_offset;
633 iface->get_text_before_offset = eail_label_get_text_before_offset;
634 iface->get_offset_at_point = eail_label_get_offset_at_point;
635 iface->get_character_extents = eail_label_get_character_extents;
636 iface->get_range_extents = eail_label_get_range_extents;