Merge "custom eail widget implementation" into tizen
[platform/core/uifw/eail.git] / 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 EailCheck 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_text_interface_init(AtkTextIface *iface);
32
33 /**
34  * @brief Define EailCheck GObject type
35  */
36 G_DEFINE_TYPE_WITH_CODE(EailCheck,
37                         eail_check,
38                         EAIL_TYPE_ACTION_WIDGET,
39                         G_IMPLEMENT_INTERFACE(ATK_TYPE_TEXT,
40                                               atk_text_interface_init));
41
42 /**
43  * @brief Gets text bounded by start_offset and end_offset
44  *
45  * Use g_free() to free the returned string.
46  *
47  * @param text AtkText instance
48  * @param start_offset start position
49  * @param end_offset end position, -1 for the end of the string
50  * @return string containing text from start_offset up to,
51  * but not including end_offset
52  */
53 static gchar*
54 eail_check_get_text(AtkText   *text,
55                      gint       start_offset,
56                      gint       end_offset)
57 {
58    gchar *string = NULL;
59    Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(text));
60
61    if (widget)
62      string = (gchar *)elm_object_text_get(widget);
63
64    return eail_get_substring(string, start_offset, end_offset);
65 }
66
67 /**
68  * @brief Gets the character at offset
69  *
70  * @param text AtkText instance
71  * @param offset character offset
72  * @return char representing the character at offset
73  */
74 static gunichar
75 eail_check_get_character_at_offset(AtkText    *text,
76                                     gint        offset)
77 {
78    gunichar character = '\0';
79    Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(text));
80
81    if (widget)
82      character = g_utf8_get_char(
83          g_utf8_offset_to_pointer(elm_object_text_get(widget), offset));
84
85    return character;
86 }
87
88 /**
89  * @brief Gets the text length
90  *
91  * @param text AtkText instance
92  * @return integer representing the text length
93  */
94 static gint
95 eail_check_get_character_count(AtkText *text)
96 {
97    gint count = 0;
98    const gchar *string_text = NULL;
99
100    Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(text));
101
102    if (!widget) return count;
103
104    string_text = elm_object_text_get(widget);
105    if (!string_text) return count;
106
107    count = g_utf8_strlen(string_text, -1);
108
109    return count;
110 }
111
112 /**
113  * @brief AtkText interface initializer
114  *
115  * Function called upon instance creation. It initializes AtkText interface
116  * implementation i.e hooks method pointers in the interface structure
117  * to the implementing class's implementation.
118  *
119  * @param iface AtkTextIface instance
120  */
121 static void
122 atk_text_interface_init(AtkTextIface *iface)
123 {
124    iface->get_text = eail_check_get_text;
125    iface->get_character_at_offset = eail_check_get_character_at_offset;
126    iface->get_character_count = eail_check_get_character_count;
127 }
128
129
130 /**
131  * @brief Callback for on_changed event
132  *
133  * Called to notify AtkObject about an object's state change.
134  *
135  * @param data callback data
136  * @param obj source object
137  * @param event_info event info
138  */
139 static void
140 eail_check_atk_notify_change(void *data, Evas_Object *obj, void *event_info)
141 {
142    Eina_Bool state = elm_check_state_get(obj);
143    atk_object_notify_state_change(ATK_OBJECT(data), ATK_STATE_CHECKED,
144                                   state == EINA_TRUE ? TRUE : FALSE);
145 }
146
147
148 /**
149  * @brief Action handler for 'click'
150  *
151  * @param action AtkAction instance (EailCheck)
152  * @param data additional data (unused here)
153  *
154  * @returns TRUE on success, FALSE otherwise
155  */
156 static gboolean
157 eail_check_action_click_cb(AtkAction *action, void *data)
158 {
159    Evas_Object *widget;
160    Eina_Bool state;
161
162    widget = eail_widget_get_widget(EAIL_WIDGET(action));
163    if (!widget) return FALSE;
164
165    if ((elm_object_disabled_get(widget)) || (!evas_object_visible_get(widget)))
166      return FALSE;
167
168    state = elm_check_state_get(widget);
169    elm_check_state_set(widget, !state);
170
171    evas_object_smart_callback_call(widget, "changed", NULL);
172    eail_check_atk_notify_change(action, widget, NULL);
173
174    return TRUE;
175 }
176
177 /**
178  * @brief Initializer for actions defined in EailCheck
179  *
180  * @param action_widget EailActionWidget implementation to be filled
181  */
182 static void
183 eail_check_actions_init(EailActionWidget *action_widget)
184 {
185    eail_action_widget_action_append(action_widget, "click", NULL,
186                                     eail_check_action_click_cb);
187 }
188
189 /**
190  * @brief Gets a reference to the state set of the accessible
191  *
192  * The caller must unreference it when it is no longer needed.
193  *
194  * Implementation of ref_state_set from AtkObject.
195  *
196  * @param obj AtkObject instance
197  *
198  * @returns AtkStateSet representing the state set
199  * of the accessible
200  */
201 static AtkStateSet*
202 eail_check_ref_state_set(AtkObject *obj)
203 {
204    Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(obj));
205    AtkStateSet *state_set =
206        ATK_OBJECT_CLASS(eail_check_parent_class)->ref_state_set(obj);
207
208    if (NULL == widget)
209      {
210         atk_state_set_add_state(state_set, ATK_STATE_DEFUNCT);
211         return state_set;
212      }
213    if (elm_check_state_get(widget))
214      {
215         atk_state_set_add_state(state_set, ATK_STATE_CHECKED);
216      }
217
218    return state_set;
219 }
220
221 /**
222  * @brief Gets the accessible name of obj
223  *
224  * @param obj AtkObject instance
225  *
226  * @returns string representing the accessible name of obj
227  */
228 static const gchar*
229 eail_check_get_name(AtkObject *obj)
230 {
231    Evas_Object *widget;
232    const char *atk_name;
233
234    g_return_val_if_fail(EAIL_IS_CHECK(obj), NULL);
235
236    atk_name = ATK_OBJECT_CLASS(eail_check_parent_class)->get_name(obj);
237    if (atk_name)
238      return atk_name;
239
240    widget = eail_widget_get_widget(EAIL_WIDGET(obj));
241    if (!widget) return NULL;
242
243    return elm_object_text_get(widget);
244 }
245
246 /**
247  * @brief Gets the list of widget's children
248  *
249  * @param widget EailWidget instance
250  *
251  * @return Eina_list representing the list of children
252  * or NULL if widget has no children
253  */
254 static Eina_List *
255 eail_check_get_widget_children(EailWidget *widget)
256 {
257    Eina_List *list = NULL;
258    Evas_Object *child, *obj;
259
260    obj = eail_widget_get_widget(EAIL_WIDGET(widget));
261    if (obj)
262      {
263         child = elm_object_part_content_get(obj, "icon");
264         if (child && elm_object_widget_check(child))
265           list = eina_list_append(list, child);
266      }
267
268    return list;
269 }
270
271 /**
272  * @brief EailCheck instance initialization
273  *
274  * @param check AtkObject instance
275  */
276 static void
277 eail_check_init(EailCheck *check)
278 {
279 }
280
281 /**
282  * @brief EailCheck object initialization
283  *
284  * @param obj EailCheck instance
285  * @param data user set addtional initailization data
286  */
287 static void
288 eail_check_initialize(AtkObject *obj, gpointer data)
289 {
290    ATK_OBJECT_CLASS(eail_check_parent_class)->initialize(obj, data);
291    obj->role = ATK_ROLE_CHECK_BOX;
292
293    evas_object_smart_callback_add((Evas_Object*) data, "changed",
294                                   eail_check_atk_notify_change,
295                                   obj);
296
297    eail_check_actions_init(EAIL_ACTION_WIDGET(obj));
298 }
299
300 /**
301  * @brief GObject type initialization function
302  *
303  * @param klass EailCheckClass instance
304  */
305 static void
306 eail_check_class_init(EailCheckClass *klass)
307 {
308    AtkObjectClass *atk_class = ATK_OBJECT_CLASS(klass);
309    EailWidgetClass *widget_class = EAIL_WIDGET_CLASS(klass);
310
311    atk_class->initialize = eail_check_initialize;
312    atk_class->ref_state_set = eail_check_ref_state_set;
313    atk_class->get_name = eail_check_get_name;
314    widget_class->get_widget_children = eail_check_get_widget_children;
315 }