1 #include <Elementary.h>
3 #include "elm_widget_radio.h"
5 EAPI const char ELM_RADIO_SMART_NAME[] = "elm_radio";
7 static const Elm_Layout_Part_Alias_Description _content_aliases[] =
9 {"icon", "elm.swallow.content"},
13 static const Elm_Layout_Part_Alias_Description _text_aliases[] =
15 {"default", "elm.text"},
19 static const char SIG_CHANGED[] = "changed";
20 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
25 EVAS_SMART_SUBCLASS_NEW
26 (ELM_RADIO_SMART_NAME, _elm_radio, Elm_Radio_Smart_Class,
27 Elm_Layout_Smart_Class, elm_layout_smart_class_get, _smart_callbacks);
30 _state_set(Evas_Object *obj, Eina_Bool state)
32 ELM_RADIO_DATA_GET(obj, sd);
34 if ((state != sd->state) && (!elm_widget_disabled_get(obj)))
38 elm_layout_signal_emit(obj, "elm,state,radio,on", "elm");
40 elm_layout_signal_emit(obj, "elm,state,radio,off", "elm");
45 _state_set_all(Elm_Radio_Smart_Data *sd)
48 Eina_Bool disabled = EINA_FALSE;
49 Evas_Object *child, *selected = NULL;
51 EINA_LIST_FOREACH(sd->group->radios, l, child)
53 ELM_RADIO_DATA_GET(child, sdc);
55 if (sdc->state) selected = child;
56 if (sdc->value == sd->group->value)
58 _state_set(child, EINA_TRUE);
59 if (!sdc->state) disabled = EINA_TRUE;
61 else _state_set(child, EINA_FALSE);
64 if ((disabled) && (selected)) _state_set(selected, 1);
68 _activate(Evas_Object *obj)
70 ELM_RADIO_DATA_GET(obj, sd);
72 if (sd->group->value == sd->value) return;
74 if ((!_elm_config->access_mode) ||
75 (_elm_access_2nd_click_timeout(obj)))
77 sd->group->value = sd->value;
78 if (sd->group->valuep) *(sd->group->valuep) = sd->group->value;
82 if (_elm_config->access_mode)
83 _elm_access_say(E_("State: On"));
84 evas_object_smart_callback_call(obj, SIG_CHANGED, NULL);
88 /* FIXME: replicated from elm_layout just because radio's icon spot
89 * is elm.swallow.content, not elm.swallow.icon. Fix that whenever we
90 * can changed the theme API */
92 _icon_signal_emit(Evas_Object *obj)
96 snprintf(buf, sizeof(buf), "elm,state,icon,%s",
97 elm_layout_content_get(obj, "icon") ? "visible" : "hidden");
99 elm_layout_signal_emit(obj, buf, "elm");
102 /* FIXME: replicated from elm_layout just because radio's icon spot
103 * is elm.swallow.content, not elm.swallow.icon. Fix that whenever we
104 * can changed the theme API */
106 _elm_radio_smart_sub_object_del(Evas_Object *obj,
109 if (!ELM_WIDGET_CLASS(_elm_radio_parent_sc)->sub_object_del(obj, sobj))
112 _icon_signal_emit(obj);
117 /* FIXME: replicated from elm_layout just because radio's icon spot
118 * is elm.swallow.content, not elm.swallow.icon. Fix that whenever we
119 * can changed the theme API */
121 _elm_radio_smart_content_set(Evas_Object *obj,
123 Evas_Object *content)
125 if (!ELM_CONTAINER_CLASS(_elm_radio_parent_sc)->content_set
126 (obj, part, content))
129 _icon_signal_emit(obj);
135 _elm_radio_smart_event(Evas_Object *obj,
136 Evas_Object *src __UNUSED__,
137 Evas_Callback_Type type,
140 Evas_Event_Key_Down *ev;
142 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
144 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
147 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
149 if ((strcmp(ev->keyname, "Return")) &&
150 (strcmp(ev->keyname, "KP_Enter")) &&
151 (strcmp(ev->keyname, "space")))
155 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
161 _elm_radio_smart_theme(Evas_Object *obj)
163 ELM_RADIO_DATA_GET(obj, sd);
165 if (!ELM_WIDGET_CLASS(_elm_radio_parent_sc)->theme(obj)) return EINA_FALSE;
167 if (sd->state) elm_layout_signal_emit(obj, "elm,state,radio,on", "elm");
168 else elm_layout_signal_emit(obj, "elm,state,radio,off", "elm");
170 if (elm_widget_disabled_get(obj) && sd->state) _state_set(obj, EINA_FALSE);
172 edje_object_message_signal_process(ELM_WIDGET_DATA(sd)->resize_obj);
174 /* FIXME: replicated from elm_layout just because radio's icon
175 * spot is elm.swallow.content, not elm.swallow.icon. Fix that
176 * whenever we can changed the theme API */
177 _icon_signal_emit(obj);
179 elm_layout_sizing_eval(obj);
185 _elm_radio_smart_disable(Evas_Object *obj)
187 ELM_RADIO_DATA_GET(obj, sd);
189 if (!ELM_WIDGET_CLASS(_elm_radio_parent_sc)->disable(obj))
192 if (elm_widget_disabled_get(obj) && sd->state) _state_set(obj, EINA_FALSE);
198 _elm_radio_smart_sizing_eval(Evas_Object *obj)
200 Evas_Coord minw = -1, minh = -1;
202 ELM_RADIO_DATA_GET(obj, sd);
204 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
205 edje_object_size_min_restricted_calc
206 (ELM_WIDGET_DATA(sd)->resize_obj, &minw, &minh, minw, minh);
207 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
208 evas_object_size_hint_min_set(obj, minw, minh);
209 evas_object_size_hint_max_set(obj, -1, -1);
213 _radio_on_cb(void *data,
214 Evas_Object *obj __UNUSED__,
215 const char *emission __UNUSED__,
216 const char *source __UNUSED__)
222 _access_info_cb(void *data __UNUSED__, Evas_Object *obj)
224 const char *txt = elm_widget_access_info_get(obj);
226 if (!txt) txt = elm_layout_text_get(obj, NULL);
227 if (txt) return strdup(txt);
233 _access_state_cb(void *data __UNUSED__, Evas_Object *obj)
235 ELM_RADIO_DATA_GET(obj, sd);
237 if (elm_widget_disabled_get(obj)) return strdup(E_("State: Disabled"));
238 if (sd->state) return strdup(E_("State: On"));
240 return strdup(E_("State: Off"));
244 _elm_radio_smart_add(Evas_Object *obj)
246 EVAS_SMART_DATA_ALLOC(obj, Elm_Radio_Smart_Data);
248 ELM_WIDGET_CLASS(_elm_radio_parent_sc)->base.add(obj);
250 elm_layout_theme_set(obj, "radio", "base", elm_widget_style_get(obj));
252 elm_layout_signal_callback_add
253 (obj, "elm,action,radio,on", "", _radio_on_cb, obj);
254 elm_layout_signal_callback_add
255 (obj, "elm,action,radio,toggle", "", _radio_on_cb, obj);
257 priv->group = calloc(1, sizeof(Group));
258 priv->group->radios = eina_list_append(priv->group->radios, obj);
259 priv->state = EINA_FALSE;
261 elm_widget_can_focus_set(obj, EINA_TRUE);
263 elm_layout_sizing_eval(obj);
265 _elm_access_object_register(obj, ELM_WIDGET_DATA(priv)->resize_obj);
267 (_elm_access_object_get(obj), ELM_ACCESS_TYPE, E_("Radio"));
268 _elm_access_callback_set
269 (_elm_access_object_get(obj), ELM_ACCESS_INFO, _access_info_cb, obj);
270 _elm_access_callback_set
271 (_elm_access_object_get(obj), ELM_ACCESS_STATE, _access_state_cb, obj);
275 _elm_radio_smart_del(Evas_Object *obj)
277 ELM_RADIO_DATA_GET(obj, sd);
279 sd->group->radios = eina_list_remove(sd->group->radios, obj);
280 if (!sd->group->radios) free(sd->group);
282 ELM_WIDGET_CLASS(_elm_radio_parent_sc)->base.del(obj);
286 _elm_radio_smart_activate(Evas_Object *obj, Elm_Activate act)
288 if (act != ELM_ACTIVATE_DEFAULT) return EINA_FALSE;
296 _elm_radio_smart_set_user(Elm_Radio_Smart_Class *sc)
298 ELM_WIDGET_CLASS(sc)->base.add = _elm_radio_smart_add;
299 ELM_WIDGET_CLASS(sc)->base.del = _elm_radio_smart_del;
301 ELM_WIDGET_CLASS(sc)->disable = _elm_radio_smart_disable;
302 ELM_WIDGET_CLASS(sc)->theme = _elm_radio_smart_theme;
303 ELM_WIDGET_CLASS(sc)->sub_object_del = _elm_radio_smart_sub_object_del;
304 ELM_WIDGET_CLASS(sc)->event = _elm_radio_smart_event;
306 /* not a 'focus chain manager' */
307 ELM_WIDGET_CLASS(sc)->focus_next = NULL;
308 ELM_WIDGET_CLASS(sc)->focus_direction = NULL;
309 ELM_WIDGET_CLASS(sc)->activate = _elm_radio_smart_activate;
311 ELM_CONTAINER_CLASS(sc)->content_set = _elm_radio_smart_content_set;
313 ELM_LAYOUT_CLASS(sc)->sizing_eval = _elm_radio_smart_sizing_eval;
315 ELM_LAYOUT_CLASS(sc)->content_aliases = _content_aliases;
316 ELM_LAYOUT_CLASS(sc)->text_aliases = _text_aliases;
319 EAPI const Elm_Radio_Smart_Class *
320 elm_radio_smart_class_get(void)
322 static Elm_Radio_Smart_Class _sc =
323 ELM_RADIO_SMART_CLASS_INIT_NAME_VERSION(ELM_RADIO_SMART_NAME);
324 static const Elm_Radio_Smart_Class *class = NULL;
325 Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
330 _elm_radio_smart_set(&_sc);
331 esc->callbacks = _smart_callbacks;
338 elm_radio_add(Evas_Object *parent)
342 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
344 obj = elm_widget_add(_elm_radio_smart_class_new(), parent);
345 if (!obj) return NULL;
347 if (!elm_widget_sub_object_add(parent, obj))
348 ERR("could not add %p as sub object of %p", obj, parent);
354 elm_radio_group_add(Evas_Object *obj,
357 ELM_RADIO_CHECK(obj);
358 ELM_RADIO_DATA_GET(obj, sd);
359 ELM_RADIO_DATA_GET(group, sdg);
363 if (eina_list_count(sd->group->radios) == 1) return;
364 sd->group->radios = eina_list_remove(sd->group->radios, obj);
365 sd->group = calloc(1, sizeof(Group));
366 sd->group->radios = eina_list_append(sd->group->radios, obj);
368 else if (sd->group == sdg->group)
372 sd->group->radios = eina_list_remove(sd->group->radios, obj);
373 if (!sd->group->radios) free(sd->group);
374 sd->group = sdg->group;
375 sd->group->radios = eina_list_append(sd->group->radios, obj);
377 if (sd->value == sd->group->value) _state_set(obj, EINA_TRUE);
378 else _state_set(obj, EINA_FALSE);
382 elm_radio_state_value_set(Evas_Object *obj,
385 ELM_RADIO_CHECK(obj);
386 ELM_RADIO_DATA_GET(obj, sd);
389 if (sd->value == sd->group->value) _state_set(obj, EINA_TRUE);
390 else _state_set(obj, EINA_FALSE);
394 elm_radio_state_value_get(const Evas_Object *obj)
396 ELM_RADIO_CHECK(obj) 0;
397 ELM_RADIO_DATA_GET(obj, sd);
403 elm_radio_value_set(Evas_Object *obj,
406 ELM_RADIO_CHECK(obj);
407 ELM_RADIO_DATA_GET(obj, sd);
409 if (value == sd->group->value) return;
410 sd->group->value = value;
411 if (sd->group->valuep) *(sd->group->valuep) = sd->group->value;
416 elm_radio_value_get(const Evas_Object *obj)
418 ELM_RADIO_CHECK(obj) 0;
419 ELM_RADIO_DATA_GET(obj, sd);
421 return sd->group->value;
425 elm_radio_value_pointer_set(Evas_Object *obj,
428 ELM_RADIO_CHECK(obj);
429 ELM_RADIO_DATA_GET(obj, sd);
433 sd->group->valuep = valuep;
434 if (*(sd->group->valuep) != sd->group->value)
436 sd->group->value = *(sd->group->valuep);
440 else sd->group->valuep = NULL;
444 elm_radio_selected_object_get(Evas_Object *obj)
449 ELM_RADIO_CHECK(obj) NULL;
450 ELM_RADIO_DATA_GET(obj, sd);
452 EINA_LIST_FOREACH(sd->group->radios, l, child)
454 ELM_RADIO_DATA_GET(child, sdc);
456 if (sdc->value == sd->group->value) return child;