1ecdde2463e6dac23dd10f01bc5c3e07e08011ec
[platform/core/uifw/eail.git] / eail / eail / eail_check.c
1 /*
2  * Copyright (c) 2013 Samsung Electronics Co., Ltd.
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 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.
18  */
19
20 /**
21  * @file eail_check.c
22  * @brief EailChceck implementation
23  */
24
25 #include <Elementary.h>
26
27 #include "eail_check.h"
28 #include "eail_utils.h"
29 #include "eail_factory.h"
30
31 static void atk_image_interface_init(AtkImageIface *iface);
32 static void atk_text_interface_init(AtkTextIface *iface);
33
34 /**
35  * @brief Define EailCheck GObject type
36  */
37 G_DEFINE_TYPE_WITH_CODE(EailCheck,
38                         eail_check,
39                         EAIL_TYPE_ACTION_WIDGET,
40                         G_IMPLEMENT_INTERFACE(ATK_TYPE_IMAGE,
41                                               atk_image_interface_init)
42                         G_IMPLEMENT_INTERFACE(ATK_TYPE_TEXT,
43                                               atk_text_interface_init));
44
45 /**
46  * @brief Implementation of get_image_position from AtkImage interface
47  *
48  * @param image Eailcheck instance
49  * @param [out] x horizontal coordinate
50  * @param [out] y vertical coordinate
51  * @param coord_type coord type
52  */
53 static void
54 eail_check_get_image_position(AtkImage     *image,
55                                gint         *x,
56                                gint         *y,
57                                AtkCoordType  coord_type)
58 {
59    Evas_Object *check_image;
60    Evas_Object *widget;
61    AtkObject *obj;
62
63    widget = eail_widget_get_widget(EAIL_WIDGET(image));
64    if (!widget)
65      {
66         *x = G_MININT;
67         *y = G_MININT;
68         return;
69      }
70
71    check_image = elm_object_part_content_get(widget, "icon");
72    if (check_image)
73      {
74         obj = eail_factory_get_accessible(check_image);
75         atk_image_get_image_position(ATK_IMAGE(obj), x, y, coord_type);
76      }
77    else
78      {
79         *x = G_MININT;
80         *y = G_MININT;
81      }
82 }
83
84 /**
85  * @brief Implementation of get_image_size from AtkImage interface
86  *
87  * @param image Eailcheck instance
88  * @param [out] width width image
89  * @param [out] height height image
90  */
91 static void
92 eail_check_get_image_size(AtkImage *image,
93                            gint     *width,
94                            gint     *height)
95 {
96    Evas_Object *widget;
97    Evas_Object *check_image;
98    AtkObject *obj;
99
100    widget = eail_widget_get_widget(EAIL_WIDGET(image));
101    if (!widget)
102      {
103         *width = -1;
104         *height = -1;
105         return;
106      }
107
108    check_image = elm_object_part_content_get(widget, "icon");
109    if (check_image)
110      {
111         obj = eail_factory_get_accessible(check_image);
112         atk_image_get_image_size(ATK_IMAGE(obj), width, height);
113      }
114    else
115      {
116         *width = -1;
117         *height = -1;
118      }
119 }
120
121 /**
122  * @brief AtkImage iterface initializer
123  *
124  * @param iface an AtkImageIface
125  */
126 static void
127 atk_image_interface_init(AtkImageIface *iface)
128 {
129    iface->get_image_position = eail_check_get_image_position;
130    iface->get_image_size     = eail_check_get_image_size;
131 }
132
133 /**
134  * @brief Gets text bounded by start_offset and end_offset
135  *
136  * Use g_free() to free the returned string
137  *
138  * @param text an AtkText
139  * @param start_offset start position
140  * @param end_offset end position, -1 for the end of the string
141  * @return string containing text from start_offset up to, but not including
142  * end_offset
143  */
144 static gchar*
145 eail_check_get_text(AtkText   *text,
146                      gint       start_offset,
147                      gint       end_offset)
148 {
149    gchar *string = NULL;
150    Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(text));
151
152    if (widget)
153      string = (gchar *)elm_object_text_get(widget);
154
155    return eail_get_substring(string, start_offset, end_offset);
156 }
157
158 /**
159  * @brief Gets character at offset
160  *
161  * @param text an AtkText
162  * @param offset character offset
163  * @return character at offset
164  */
165 static gunichar
166 eail_check_get_character_at_offset(AtkText    *text,
167                                     gint        offset)
168 {
169    gunichar character = '\0';
170    Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(text));
171
172    if (widget)
173      character = g_utf8_get_char(
174          g_utf8_offset_to_pointer(elm_object_text_get(widget), offset));
175
176    return character;
177 }
178
179 /**
180  * @brief Gets text length
181  *
182  * @param text an AtkText
183  * @return text length
184  */
185 static gint
186 eail_check_get_character_count(AtkText *text)
187 {
188    gint count = 0;
189    const gchar *string_text = NULL;
190
191    Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(text));
192
193    if (!widget) return count;
194
195    string_text = elm_object_text_get(widget);
196    if (!string_text) return count;
197
198    count = g_utf8_strlen(string_text, -1);
199
200    return count;
201 }
202
203 /**
204  * @brief AtkText interface initializer
205  *
206  * Function called upon instance creation. It initializes AtkText interface
207  * implementation i.e hooks method pointers in the interface structure
208  * to the implementing class's implementation.
209  *
210  * @param iface an AtkTextIface
211  */
212 static void
213 atk_text_interface_init(AtkTextIface *iface)
214 {
215    iface->get_text = eail_check_get_text;
216    iface->get_character_at_offset = eail_check_get_character_at_offset;
217    iface->get_character_count = eail_check_get_character_count;
218 }
219
220
221 /**
222  * @brief Callback for on_changed event
223  * This will be called to notify AtkObject about object state change
224  *
225  * @param data callback data
226  * @param obj object source
227  * @param event_info event info
228  */
229 static void
230 eail_check_atk_notify_change(void *data, Evas_Object *obj, void *event_info)
231 {
232    Eina_Bool state = elm_check_state_get(obj);
233    atk_object_notify_state_change(ATK_OBJECT(data), ATK_STATE_CHECKED,
234                                   state == EINA_TRUE ? TRUE : FALSE);
235 }
236
237
238 /**
239  * @brief Action handler for 'click'
240  *
241  * @param action an AtkAction object (EailCheck)
242  * @param data additional data (unused here)
243  *
244  * @returns TRUE on success, FALSE otherwise
245  */
246 static gboolean
247 eail_check_action_click_cb(AtkAction *action, void *data)
248 {
249    Evas_Object *widget;
250    Eina_Bool state;
251
252    widget = eail_widget_get_widget(EAIL_WIDGET(action));
253    if (!widget) return FALSE;
254
255    if ((elm_object_disabled_get(widget)) || (!evas_object_visible_get(widget)))
256      return FALSE;
257
258    state = elm_check_state_get(widget);
259    elm_check_state_set(widget, !state);
260
261    evas_object_smart_callback_call(widget, "changed", NULL);
262    eail_check_atk_notify_change(action, widget, NULL);
263
264    return TRUE;
265 }
266
267 /**
268  * @brief Initializer for actions defined in EailCheck
269  *
270  * @param action_widget an EailActionWidget implementation to be filled
271  */
272 static void
273 eail_check_actions_init(EailActionWidget *action_widget)
274 {
275    eail_action_widget_action_append(action_widget, "click", NULL,
276                                     eail_check_action_click_cb);
277 }
278
279 /**
280  * @brief Implementation of ref_state_set from AtkObject
281  *
282  * @param obj EailCheck instance
283  *
284  * @returns AtkStateSet for EailCheck instance
285  */
286 static AtkStateSet*
287 eail_check_ref_state_set(AtkObject *obj)
288 {
289    Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(obj));
290    AtkStateSet *state_set =
291        ATK_OBJECT_CLASS(eail_check_parent_class)->ref_state_set(obj);
292
293    if (NULL == widget)
294      {
295         atk_state_set_add_state(state_set, ATK_STATE_DEFUNCT);
296         return state_set;
297      }
298    if (elm_check_state_get(widget))
299      {
300         atk_state_set_add_state(state_set, ATK_STATE_CHECKED);
301      }
302
303    return state_set;
304 }
305
306 /**
307  * @brief Gets obj accessible name
308  *
309  * @param obj an AtkObject
310  *
311  * @returns obj name
312  */
313 static const gchar*
314 eail_check_get_name(AtkObject *obj)
315 {
316    Evas_Object *widget;
317    const char *atk_name;
318
319    g_return_val_if_fail(EAIL_IS_CHECK(obj), NULL);
320
321    atk_name = ATK_OBJECT_CLASS(eail_check_parent_class)->get_name(obj);
322    if (atk_name)
323      return atk_name;
324
325    widget = eail_widget_get_widget(EAIL_WIDGET(obj));
326    if (!widget) return NULL;
327
328    return elm_object_text_get(widget);
329 }
330
331 /**
332  * @brief Gets list of child widget
333  *
334  * @param widget EailWidget object
335  *
336  * @return list of children, NULL if no children
337  */
338 static Eina_List *
339 eail_check_get_widget_children(EailWidget *widget)
340 {
341    Eina_List *list = NULL;
342    Evas_Object *child, *obj;
343
344    obj = eail_widget_get_widget(EAIL_WIDGET(widget));
345    if (obj)
346      {
347         child = elm_object_part_content_get(obj, "icon");
348         if (child && elm_object_widget_check(child))
349           list = eina_list_append(list, child);
350      }
351
352    return list;
353 }
354
355 /**
356  * @brief EailCheck instance initialization
357  *
358  * @param check Eailheck instance
359  */
360 static void
361 eail_check_init(EailCheck *check)
362 {
363 }
364
365 /**
366  * @brief EailCheck object initializiation
367  *
368  * @param obj EailCheck object
369  * @param data user set addtional initailization data
370  */
371 static void
372 eail_check_initialize(AtkObject *obj, gpointer data)
373 {
374    ATK_OBJECT_CLASS(eail_check_parent_class)->initialize(obj, data);
375    obj->role = ATK_ROLE_CHECK_BOX;
376
377    evas_object_smart_callback_add((Evas_Object*) data, "changed",
378                                   eail_check_atk_notify_change,
379                                   obj);
380
381    eail_check_actions_init(EAIL_ACTION_WIDGET(obj));
382 }
383
384 /**
385  * @brief GObject type initialization function
386  *
387  * @param klass EailCheck class
388  */
389 static void
390 eail_check_class_init(EailCheckClass *klass)
391 {
392    AtkObjectClass *class = ATK_OBJECT_CLASS(klass);
393    EailWidgetClass *widget_class = EAIL_WIDGET_CLASS(klass);
394
395    class->initialize = eail_check_initialize;
396    class->ref_state_set = eail_check_ref_state_set;
397    class->get_name = eail_check_get_name;
398    widget_class->get_widget_children = eail_check_get_widget_children;
399 }