[access][gengrid] add activate callback
[framework/uifw/elementary.git] / src / lib / elm_frame.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include "elm_widget_frame.h"
4
5 EAPI const char ELM_FRAME_SMART_NAME[] = "elm_frame";
6
7 static const char SIG_CLICKED[] = "clicked";
8
9 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
10    {SIG_CLICKED, ""},
11    {NULL, NULL}
12 };
13 static const Elm_Layout_Part_Alias_Description _content_aliases[] =
14 {
15    {"default", "elm.swallow.content"},
16    {NULL, NULL}
17 };
18
19 static const Elm_Layout_Part_Alias_Description _text_aliases[] =
20 {
21    {"default", "elm.text"},
22    {NULL, NULL}
23 };
24
25 EVAS_SMART_SUBCLASS_NEW
26   (ELM_FRAME_SMART_NAME, _elm_frame, Elm_Frame_Smart_Class,
27   Elm_Layout_Smart_Class, elm_layout_smart_class_get, _smart_callbacks);
28
29 static void
30 _sizing_eval(Evas_Object *obj,
31              Elm_Frame_Smart_Data *sd)
32 {
33    Evas_Coord minw = -1, minh = -1;
34    Evas_Coord cminw = -1, cminh = -1;
35
36    edje_object_size_min_calc(ELM_WIDGET_DATA(sd)->resize_obj, &minw, &minh);
37    evas_object_size_hint_min_get(obj, &cminw, &cminh);
38    if ((minw == cminw) && (minh == cminh)) return;
39
40    evas_object_size_hint_min_set(obj, minw, minh);
41    evas_object_size_hint_max_set(obj, -1, -1);
42 }
43
44 static Eina_Bool
45 _elm_frame_smart_focus_next(const Evas_Object *obj,
46                             Elm_Focus_Direction dir,
47                             Evas_Object **next)
48 {
49    Evas_Object *content;
50
51    content = elm_layout_content_get(obj, NULL);
52
53    if (!content) return EINA_FALSE;
54
55    /* attempt to follow focus cycle into sub-object */
56    return elm_widget_focus_next_get(content, dir, next);
57 }
58
59 static Eina_Bool
60 _elm_frame_smart_focus_direction(const Evas_Object *obj,
61                                  const Evas_Object *base,
62                                  double degree,
63                                  Evas_Object **direction,
64                                  double *weight)
65 {
66    Evas_Object *content;
67
68    content = elm_layout_content_get(obj, NULL);
69
70    if (!content) return EINA_FALSE;
71
72    /* Try to cycle focus on content */
73    return elm_widget_focus_direction_get
74             (content, base, degree, direction, weight);
75 }
76
77 static void
78 _recalc(void *data,
79         Evas_Object *obj __UNUSED__,
80         void *event_info __UNUSED__)
81 {
82    elm_layout_sizing_eval(data);
83 }
84
85 static void
86 _on_recalc_done(void *data,
87                 Evas_Object *obj __UNUSED__,
88                 const char *sig __UNUSED__,
89                 const char *src __UNUSED__)
90 {
91    ELM_FRAME_DATA_GET(data, sd);
92
93    evas_object_smart_callback_del
94      (ELM_WIDGET_DATA(sd)->resize_obj, "recalc", _recalc);
95    sd->anim = EINA_FALSE;
96
97    elm_layout_sizing_eval(data);
98 }
99
100 static void
101 _on_frame_clicked(void *data,
102                   Evas_Object *obj __UNUSED__,
103                   const char *sig __UNUSED__,
104                   const char *src __UNUSED__)
105 {
106    ELM_FRAME_DATA_GET(data, sd);
107
108    if (sd->anim) return;
109
110    if (sd->collapsible)
111      {
112         evas_object_smart_callback_add
113           (ELM_WIDGET_DATA(sd)->resize_obj, "recalc", _recalc, data);
114         elm_layout_signal_emit(data, "elm,action,toggle", "elm");
115         sd->collapsed++;
116         sd->anim = EINA_TRUE;
117      }
118    evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
119 }
120
121 /* using deferred sizing evaluation, just like the parent */
122 static void
123 _elm_frame_smart_calculate(Evas_Object *obj)
124 {
125    ELM_FRAME_DATA_GET(obj, sd);
126
127    if (ELM_LAYOUT_DATA(sd)->needs_size_calc)
128      {
129         /* calling OWN sizing evaluate code here */
130         _sizing_eval(obj, sd);
131         ELM_LAYOUT_DATA(sd)->needs_size_calc = EINA_FALSE;
132      }
133 }
134
135 static void
136 _elm_frame_smart_add(Evas_Object *obj)
137 {
138    EVAS_SMART_DATA_ALLOC(obj, Elm_Frame_Smart_Data);
139
140    ELM_WIDGET_CLASS(_elm_frame_parent_sc)->base.add(obj);
141
142    edje_object_signal_callback_add
143      (ELM_WIDGET_DATA(priv)->resize_obj, "elm,anim,done", "elm",
144      _on_recalc_done, obj);
145    edje_object_signal_callback_add
146      (ELM_WIDGET_DATA(priv)->resize_obj, "elm,action,click", "elm",
147      _on_frame_clicked, obj);
148
149    elm_widget_can_focus_set(obj, EINA_FALSE);
150
151    elm_layout_theme_set(obj, "frame", "base", elm_widget_style_get(obj));
152
153    elm_layout_sizing_eval(obj);
154 }
155
156 static void
157 _elm_frame_smart_set_user(Elm_Frame_Smart_Class *sc)
158 {
159    ELM_WIDGET_CLASS(sc)->base.add = _elm_frame_smart_add;
160    ELM_WIDGET_CLASS(sc)->base.calculate = _elm_frame_smart_calculate;
161
162    ELM_WIDGET_CLASS(sc)->focus_next = _elm_frame_smart_focus_next;
163    ELM_WIDGET_CLASS(sc)->focus_direction = _elm_frame_smart_focus_direction;
164
165    ELM_LAYOUT_CLASS(sc)->content_aliases = _content_aliases;
166    ELM_LAYOUT_CLASS(sc)->text_aliases = _text_aliases;
167 }
168
169 EAPI const Elm_Frame_Smart_Class *
170 elm_frame_smart_class_get(void)
171 {
172    static Elm_Frame_Smart_Class _sc =
173      ELM_FRAME_SMART_CLASS_INIT_NAME_VERSION(ELM_FRAME_SMART_NAME);
174    static const Elm_Frame_Smart_Class *class = NULL;
175    Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
176
177    if (class)
178      return class;
179
180    _elm_frame_smart_set(&_sc);
181    esc->callbacks = _smart_callbacks;
182    class = &_sc;
183
184    return class;
185 }
186
187 EAPI Evas_Object *
188 elm_frame_add(Evas_Object *parent)
189 {
190    Evas_Object *obj;
191
192    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
193
194    obj = elm_widget_add(_elm_frame_smart_class_new(), parent);
195    if (!obj) return NULL;
196
197    if (!elm_widget_sub_object_add(parent, obj))
198      ERR("could not add %p as sub object of %p", obj, parent);
199
200    return obj;
201 }
202
203 EAPI void
204 elm_frame_autocollapse_set(Evas_Object *obj,
205                            Eina_Bool autocollapse)
206 {
207    ELM_FRAME_CHECK(obj);
208    ELM_FRAME_DATA_GET_OR_RETURN(obj, sd);
209
210    sd->collapsible = !!autocollapse;
211 }
212
213 EAPI Eina_Bool
214 elm_frame_autocollapse_get(const Evas_Object *obj)
215 {
216    ELM_FRAME_CHECK(obj) EINA_FALSE;
217    ELM_FRAME_DATA_GET_OR_RETURN_VAL(obj, sd, EINA_FALSE);
218
219    return sd->collapsible;
220 }
221
222 EAPI void
223 elm_frame_collapse_set(Evas_Object *obj,
224                        Eina_Bool collapse)
225 {
226    ELM_FRAME_CHECK(obj);
227    ELM_FRAME_DATA_GET_OR_RETURN(obj, sd);
228
229    collapse = !!collapse;
230    if (sd->collapsed == collapse) return;
231
232    elm_layout_signal_emit(obj, "elm,action,switch", "elm");
233    edje_object_message_signal_process(ELM_WIDGET_DATA(sd)->resize_obj);
234    sd->collapsed = !!collapse;
235    sd->anim = EINA_FALSE;
236
237    _sizing_eval(obj, sd);
238 }
239
240 EAPI void
241 elm_frame_collapse_go(Evas_Object *obj,
242                       Eina_Bool collapse)
243 {
244    ELM_FRAME_CHECK(obj);
245    ELM_FRAME_DATA_GET_OR_RETURN(obj, sd);
246
247    collapse = !!collapse;
248    if (sd->collapsed == collapse) return;
249
250    elm_layout_signal_emit(obj, "elm,action,toggle", "elm");
251    evas_object_smart_callback_add
252      (ELM_WIDGET_DATA(sd)->resize_obj, "recalc", _recalc, obj);
253    sd->collapsed = collapse;
254    sd->anim = EINA_TRUE;
255 }
256
257 EAPI Eina_Bool
258 elm_frame_collapse_get(const Evas_Object *obj)
259 {
260    ELM_FRAME_CHECK(obj) EINA_FALSE;
261    ELM_FRAME_DATA_GET_OR_RETURN_VAL(obj, sd, EINA_FALSE);
262
263    return sd->collapsed;
264 }