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 EailWidget implementation
26 #include <Ecore_Evas.h>
27 #include <Elementary.h>
29 #include "eail_widget.h"
30 #include "eail_factory.h"
31 #include "eail_utils.h"
32 #include "eail_priv.h"
34 static void atk_component_interface_init(AtkComponentIface *iface);
37 * @brief EailWidget type definition
39 G_DEFINE_TYPE_WITH_CODE(EailWidget, eail_widget, ATK_TYPE_OBJECT,
40 G_IMPLEMENT_INTERFACE(ATK_TYPE_COMPONENT,
41 atk_component_interface_init));
44 * @brief Add custom widget to given parent object
46 * @param parent parent object instance
47 * @param custom_widget parent object instance
48 * @return Eina_Bool result of the operation
52 eail_widget_add_custom_widget_child(AtkObject *parent, AtkObject *custom_widget)
54 if (!custom_widget || !parent)
57 EailWidget *widget = EAIL_WIDGET(parent);
62 widget->custom_children = eina_list_append(widget->custom_children, custom_widget);
64 atk_object_set_parent(custom_widget, parent);
65 eail_emit_children_changed_obj(TRUE, parent, custom_widget);
71 * @brief deletes all cutom widgets from given parent widget
73 * @param widget parent widget instance
74 * @return Eina_Bool result of the operation
78 eail_widget_del_custom_widgets(AtkObject *parent) {
83 EailWidget *widget = EAIL_WIDGET(parent);
88 const Eina_List *l = NULL;
92 EINA_LIST_FOREACH(widget->custom_children, l, cw)
94 eail_emit_children_changed(FALSE, parent, i);
95 atk_object_set_parent(cw, NULL);
100 eina_list_free(widget->custom_children);
105 * @brief gets evas_object from eailwidget
107 * @param widget eailwidget instance
108 * @return evas_object widget representing the eailwidget
111 eail_widget_get_widget(EailWidget *widget)
113 g_return_val_if_fail(EAIL_IS_WIDGET(widget), NULL);
115 return widget->widget;
119 * @brief Gets EailWidget's custom children
121 * @param widget EailWidget instance
122 * @return Eina_List representing the EailWidget's custom children list
125 eail_widget_get_widget_custom_children(EailWidget *widget)
127 return widget->custom_children;
131 * @brief Gets EailWidget's children
133 * @param widget EailWidget instance
134 * @return Eina_List representing the EailWidget's children list
137 eail_widget_get_widget_children(EailWidget *widget)
139 EailWidgetClass *klass;
141 g_return_val_if_fail(EAIL_IS_WIDGET(widget), NULL);
143 klass = EAIL_WIDGET_GET_CLASS(widget);
144 return klass->get_widget_children(widget);
148 * @brief Callback used for tracking focus-in changes for widgets
150 * @param data data passed to callback
151 * @param e Evas instance that has been focused in
152 * @param obj Evas_Object instance that has been focused in
153 * @param event_info additional event info
156 eail_widget_on_focused_in(void *data, Evas *e, Evas_Object *obj, void *event_info)
158 g_return_if_fail(ATK_IS_OBJECT(data));
160 atk_object_notify_state_change(ATK_OBJECT(data), ATK_STATE_FOCUSED, TRUE);
161 atk_focus_tracker_notify(ATK_OBJECT(data));
165 * @brief Callback used for tracking show-changes for widgets
167 * @param data data passed to callback
168 * @param e Evas instance that has been shown
169 * @param obj Evas_Object instance that has been shown
170 * @param event_info additional event info
173 eail_widget_on_show(void *data, Evas *e, Evas_Object *obj, void *event_info)
175 g_return_if_fail(ATK_IS_OBJECT(data));
177 atk_object_notify_state_change(ATK_OBJECT(data), ATK_STATE_SHOWING, TRUE);
178 atk_object_notify_state_change(ATK_OBJECT(data), ATK_STATE_VISIBLE, TRUE);
182 * @brief Callback used for tracking hide-changes for widgets
184 * @param data data passed to callback
185 * @param e Evas instance that has been shown
186 * @param obj Evas_Object instance that has been shown
187 * @param event_info additional event info
190 eail_widget_on_hide(void *data, Evas *e, Evas_Object *obj, void *event_info)
192 g_return_if_fail(ATK_IS_OBJECT(data));
194 atk_object_notify_state_change(ATK_OBJECT(data), ATK_STATE_SHOWING, FALSE);
195 atk_object_notify_state_change(ATK_OBJECT(data), ATK_STATE_VISIBLE, FALSE);
199 * @brief Callback used for tracking focus-out changes for widgets
201 * @param data data passed to callback
202 * @param e Evas instance that has been focused out
203 * @param obj Evas_Object instance that has been focused out
204 * @param event_info additional event info
207 eail_widget_on_focused_out(void *data, Evas *e, Evas_Object *obj, void *event_info)
209 g_return_if_fail(ATK_IS_OBJECT(data));
212 atk_object_notify_state_change(ATK_OBJECT(data), ATK_STATE_FOCUSED, FALSE);
213 atk_focus_tracker_notify(ATK_OBJECT(data));
214 eail_notify_child_focus_changes();
218 * @brief Callback used to tracking bounds-change changes for widgets
220 * @param data data passed to callback
221 * @param e an Evas that has been focused out
222 * @param obj an Evas_Object that has been focused out
223 * @param event_info additional event info
226 eail_widget_on_bounds_change(void *data, Evas *e, Evas_Object *obj, void *event_info)
228 g_return_if_fail(ATK_IS_COMPONENT(data));
231 evas_object_geometry_get(obj, &rect.x, &rect.y, &rect.width, &rect.height);
232 g_signal_emit_by_name (ATK_OBJECT(data), "bounds_changed", &rect);
237 * @brief Default callback for on_focused used for tracking focus changes of
240 * @param data data passed to callback
241 * @param obj Evas_Object instance that has been shown
242 * @param event_info additional event info
244 void eail_widget_on_focused_smart(void *data,
248 g_return_if_fail(ATK_IS_OBJECT(data));
251 atk_object_notify_state_change(ATK_OBJECT(data), ATK_STATE_FOCUSED, TRUE);
252 atk_focus_tracker_notify(ATK_OBJECT(data));
253 eail_notify_child_focus_changes();
257 * @brief on_focused default callback used to tracking focus changes of
260 * @param data data passed to callback
261 * @param obj an Evas_Object that has been shown
262 * @param event_info additional event info
264 void eail_widget_on_focused_out_smart(void *data,
268 g_return_if_fail(ATK_IS_OBJECT(data));
271 /* Not propagating further, using only for internal eail focus changes*/
272 eail_notify_child_focus_changes();
276 * @brief EailWidget initializer
278 * @param obj AtkObject instance
279 * @param data initialization data
282 eail_widget_initialize(AtkObject *obj, gpointer data)
284 EailWidget *widget = EAIL_WIDGET(obj);
286 ATK_OBJECT_CLASS(eail_widget_parent_class)->initialize(obj, data);
288 widget->widget = (Evas_Object *)data;
289 widget->layer = ATK_LAYER_WIDGET;
291 obj->name = g_strdup(evas_object_name_get(widget->widget));
292 obj->role = ATK_ROLE_UNKNOWN;
294 if (!widget->widget) {
295 ERR("No evas object inside EailWidget was found");
299 evas_object_event_callback_add(widget->widget, EVAS_CALLBACK_FOCUS_IN,
300 eail_widget_on_focused_in, widget);
301 evas_object_event_callback_add(widget->widget, EVAS_CALLBACK_FOCUS_OUT,
302 eail_widget_on_focused_out, widget);
304 evas_object_event_callback_add(widget->widget, EVAS_CALLBACK_SHOW,
305 eail_widget_on_show, widget);
306 evas_object_event_callback_add(widget->widget, EVAS_CALLBACK_HIDE,
307 eail_widget_on_hide, widget);
309 evas_object_event_callback_add(widget->widget, EVAS_CALLBACK_RESIZE,
310 eail_widget_on_bounds_change, widget);
311 evas_object_event_callback_add(widget->widget, EVAS_CALLBACK_MOVE,
312 eail_widget_on_bounds_change, widget);
314 if (elm_object_widget_check(widget->widget)) {
316 /* for window don't need that event, it would result double generating
318 if (!ATK_IS_WINDOW(obj))
319 evas_object_smart_callback_add
320 (widget->widget, "focused", eail_widget_on_focused_smart, widget);
322 evas_object_smart_callback_add
323 (widget->widget, "unfocused", eail_widget_on_focused_out_smart, widget);
328 * @brief Default get_widget_children callback
330 * @param widget EailWidget instance
334 eail_widget_get_real_widget_children(EailWidget *widget)
340 * @brief Gets the number of children of obj
342 * @param obj AtkObject instance
344 * @returns integer representing the number of widget's children
347 eail_widget_get_n_children(AtkObject *obj)
349 gint n_children, c_n_children;
352 children = eail_widget_get_widget_children(EAIL_WIDGET(obj));
353 n_children = eina_list_count(children);
355 EailWidget *c = EAIL_WIDGET(obj);
356 c_n_children = eina_list_count(c->custom_children);
358 eina_list_free(children);
360 return n_children+c_n_children;
364 * @brief Gets reference to specified child of obj
366 * The caller must unreference it when it is no longer needed.
368 * @param obj AtkObject instance
369 * @param i child index
370 * @return AtkObject representing the specified child of obj
373 eail_widget_ref_child(AtkObject *obj, gint i)
376 AtkObject *child = NULL;
377 EailWidget *c = EAIL_WIDGET(obj);
378 g_return_val_if_fail(EAIL_IS_WIDGET(c), NULL);
380 children = eail_widget_get_widget_children(EAIL_WIDGET(obj));
381 unsigned int schild = eina_list_count(children);
383 if (eina_list_count(children) > i) {
384 child = eail_factory_get_accessible(eina_list_nth(children, i));
388 eina_list_free(children);
390 if (eina_list_count(c->custom_children) > 0) {
391 child = eina_list_nth(c->custom_children, i-schild);
401 * @brief Gets the parent of obj
403 * @param obj AtkObject instance
404 * @return AtkObject representing the parent of obj
407 eail_widget_get_parent(AtkObject *obj)
409 Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(obj));
415 if (obj->accessible_parent) {
416 return obj->accessible_parent;
419 return eail_factory_get_accessible(elm_object_parent_widget_get(widget));
423 * @brief Gets the 0-based index of this accessible in its parent
425 * Returns -1 if the accessible does not have an accessible parent.
427 * @param obj AtkObject instance
428 * @return integer representing obj's index in its parent
431 eail_widget_get_index_in_parent(AtkObject *obj)
434 Eina_List *l, *children, *custom_c;
435 Evas_Object *child = NULL;
436 AtkObject *cchild = NULL;
437 AtkObject *parent = NULL;
438 Evas_Object *widget = NULL;
440 if (obj->accessible_parent)
441 parent = obj->accessible_parent;
443 parent = atk_object_get_parent(obj);
445 g_return_val_if_fail(parent, -1);
447 children = eail_widget_get_widget_children(EAIL_WIDGET(parent));
448 custom_c = eail_widget_get_widget_custom_children(EAIL_WIDGET(parent));
449 unsigned int schild = eina_list_count(children);
451 child = eail_widget_get_widget(EAIL_WIDGET(obj));
452 if (elm_object_widget_check(child)) {
453 EINA_LIST_FOREACH(children, l, widget) {
461 EINA_LIST_FOREACH(custom_c, l, cchild) {
470 * @brief Gets the state set of obj
472 * @param obj AtkObject instance
473 * @return AtkState representing the state set of obj
476 eail_widget_ref_state_set(AtkObject *obj)
478 AtkStateSet *state_set;
479 Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(obj));
481 state_set = ATK_OBJECT_CLASS(eail_widget_parent_class)->ref_state_set(obj);
483 return eail_evas_obj_ref_state_set(widget, state_set);
487 * @brief Gets the attribute set of obj
489 * @param obj AtkObject instance
490 * @return AtkAttributeSet representing obj's attribute set
492 static AtkAttributeSet *
493 eail_widget_get_attributes(AtkObject *obj)
496 AtkAttributeSet *attributes;
497 Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(obj));
503 attr = g_new(AtkAttribute, 1);
504 attr->name = g_strdup("type");
505 attr->value = g_strdup(elm_object_widget_type_get(widget));
507 attributes = g_slist_append(NULL, attr);
513 * @brief EailWidget instance initializer
515 * @param widget EailWidget instance
518 eail_widget_init(EailWidget *widget)
523 * @brief EailWidget finalizer
525 * Frees memory assigned to object.
527 * @param obj GObject instance
530 eail_widget_class_finalize(GObject *obj)
532 EailWidget *eail_widget = EAIL_WIDGET(obj);
533 Evas_Object *evas_widget = eail_widget_get_widget(eail_widget);
536 eail_factory_unregister_wdgt_from_cache(evas_widget);
538 G_OBJECT_CLASS(eail_widget_parent_class)->finalize(obj);
542 * @brief EailWidget class initializer
544 * Function called upon instance creation. It initializes AtkObject class
545 * callbacks for EailWidget.
547 * @param klass EailWidgetClass instance
550 eail_widget_class_init(EailWidgetClass *klass)
552 AtkObjectClass *atk_class = ATK_OBJECT_CLASS(klass);
553 GObjectClass *g_object_class = G_OBJECT_CLASS(klass);
555 klass->get_widget_children = eail_widget_get_real_widget_children;
557 atk_class->initialize = eail_widget_initialize;
558 atk_class->get_n_children = eail_widget_get_n_children;
559 atk_class->ref_child = eail_widget_ref_child;
560 atk_class->get_parent = eail_widget_get_parent;
561 atk_class->get_index_in_parent = eail_widget_get_index_in_parent;
562 atk_class->ref_state_set = eail_widget_ref_state_set;
563 atk_class->get_attributes = eail_widget_get_attributes;
565 g_object_class->finalize = eail_widget_class_finalize;
569 * @brief Grabs focus of a component
571 * @param component AtkComponent instance
572 * @return TRUE on success, FALSE otherwise
575 eail_widget_grab_focus(AtkComponent *component)
577 Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(component));
579 return eail_evas_obj_grab_focus(widget);
583 * @brief Gets component's layer
585 * @param component AtkComponent instance
586 * @return AtkLayer representing the component's layer
589 eail_widget_get_layer(AtkComponent *component)
591 return EAIL_WIDGET(component)->layer;
595 * @brief Gets the rectangle which gives the extent of the component
597 * @param component AtkComponent instance
598 * @param [out] x upper left x coordinate of the rectangle
599 * @param [out] y upper left y coordinate of the rectangle
600 * @param [out] width width of the rectangle
601 * @param [out] height height of the rectangle
602 * @param coord_type coordinates type
605 eail_widget_get_extents(AtkComponent *component,
610 AtkCoordType coord_type)
612 Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(component));
615 *width = *height = -1;
620 evas_object_geometry_get(widget, x, y, width, height);
622 if (coord_type == ATK_XY_SCREEN) {
624 Ecore_Evas *ee= ecore_evas_ecore_evas_get(evas_object_evas_get(widget));
626 ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
633 * @brief Sets component position
635 * @param component AtkComponent instance
636 * @param x upper left x coordinate
637 * @param y upper left y coordinate
638 * @param coord_type coordinates type
639 * @return TRUE on success, FALSE otherwise
642 eail_widget_set_position(AtkComponent *component,
645 AtkCoordType coord_type)
647 Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(component));
649 if (!widget) return FALSE;
651 if (x < 0 || y < 0) return FALSE;
653 if (coord_type == ATK_XY_SCREEN) {
655 Ecore_Evas *ee= ecore_evas_ecore_evas_get(evas_object_evas_get(widget));
657 ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
662 evas_object_move(widget, x, y);
668 * @brief Sets component size
670 * @param component AtkComponent instance
671 * @param width new width of component
672 * @param height new height of component
673 * @return TRUE on success, FALSE otherwise
676 eail_widget_set_size(AtkComponent *component,
680 Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(component));
682 if (!widget) return FALSE;
684 if (width <= 0 || height <= 0) return FALSE;
686 evas_object_resize(widget, width, height);
692 * @brief Sets component extents
694 * @param component AtkComponent instance
695 * @param x new upper left x coordinate
696 * @param y new upper left y coordinate
697 * @param width new width of component
698 * @param height new height of component
699 * @param coord_type coordinates type
700 * @return TRUE on success, FALSE otherwise
703 eail_widget_set_extents(AtkComponent *component,
708 AtkCoordType coord_type)
710 Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(component));
716 if (coord_type == ATK_XY_SCREEN) {
718 Ecore_Evas *ee= ecore_evas_ecore_evas_get(evas_object_evas_get(widget));
720 ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
725 if (x < 0 || y < 0) {
729 evas_object_move(widget, x, y);
730 evas_object_resize(widget, width, height);
736 * @brief Sets function to execute whenever component gets focus
738 * @param component AtkComponent instance
739 * @param handler AtkFocusHandler instance
740 * @returns integer representing the handler's id
743 eail_widget_add_focus_handler(AtkComponent *component,
744 AtkFocusHandler handler)
746 GSignalMatchType match_type;
750 match_type = G_SIGNAL_MATCH_ID;
751 signal_id = g_signal_lookup("focus-event", ATK_TYPE_OBJECT);
753 ret = g_signal_handler_find(component, match_type, signal_id, 0, NULL,
754 (gpointer)handler, NULL);
757 return g_signal_connect_closure_by_id(component,
760 G_CALLBACK(handler), NULL,
761 (GClosureNotify)NULL),
771 * @brief Gets alpha value
773 * @param component an AtkComponent
774 * @return alpha value
777 eail_widget_get_alpha(AtkComponent *component)
779 Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(component));
782 evas_object_color_get(widget, NULL, NULL, NULL, &alpha);
784 return (gdouble)alpha/255.0;
788 * @brief AtkComponent interface initialization
790 * @param iface EailNaviframPage instance
793 atk_component_interface_init(AtkComponentIface *iface)
795 iface->grab_focus = eail_widget_grab_focus;
796 iface->get_layer = eail_widget_get_layer;
797 iface->get_extents = eail_widget_get_extents;
798 iface->set_position = eail_widget_set_position;
799 iface->set_size = eail_widget_set_size;
800 iface->set_extents = eail_widget_set_extents;
801 iface->add_focus_handler = eail_widget_add_focus_handler;
802 iface->get_alpha = eail_widget_get_alpha;