Initialize Tizen 2.3
[framework/uifw/elementary.git] / mobile / src / lib / elm_panel.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include "elm_widget_panel.h"
4
5 EAPI const char ELM_PANEL_SMART_NAME[] = "elm_panel";
6
7 EVAS_SMART_SUBCLASS_NEW
8   (ELM_PANEL_SMART_NAME, _elm_panel, Elm_Panel_Smart_Class,
9   Elm_Layout_Smart_Class, elm_layout_smart_class_get, NULL);
10
11 static void
12 _mirrored_set(Evas_Object *obj,
13               Eina_Bool rtl)
14 {
15    ELM_PANEL_DATA_GET(obj, sd);
16
17    elm_widget_mirrored_set(sd->bx, rtl);
18    elm_panel_orient_set(obj, elm_panel_orient_get(obj));
19 }
20
21 static void
22 _elm_panel_smart_sizing_eval(Evas_Object *obj)
23 {
24    Evas_Coord mw = -1, mh = -1;
25
26    ELM_PANEL_DATA_GET(obj, sd);
27
28    if (sd->on_deletion) return;
29
30    evas_object_smart_calculate(sd->bx);
31    edje_object_size_min_calc(ELM_WIDGET_DATA(sd)->resize_obj, &mw, &mh);
32    evas_object_size_hint_min_set(obj, mw, mh);
33    evas_object_size_hint_max_set(obj, -1, -1);
34 }
35
36 static char *
37 _access_state_cb(void *data, Evas_Object *obj __UNUSED__)
38 {
39    ELM_PANEL_DATA_GET(data, sd);
40
41    if (!sd->hidden) return strdup(E_("state: opened"));
42    else return strdup(E_("state: closed"));
43
44    return NULL;
45 }
46
47 static void
48 _orient_set_do(Evas_Object *obj)
49 {
50    ELM_PANEL_DATA_GET(obj, sd);
51
52    switch (sd->orient)
53      {
54       case ELM_PANEL_ORIENT_TOP:
55         elm_layout_theme_set(obj, "panel", "top", elm_widget_style_get(obj));
56         break;
57
58       case ELM_PANEL_ORIENT_BOTTOM:
59         elm_layout_theme_set
60           (obj, "panel", "bottom", elm_widget_style_get(obj));
61         break;
62
63       case ELM_PANEL_ORIENT_LEFT:
64         if (!elm_widget_mirrored_get(obj))
65           elm_layout_theme_set
66             (obj, "panel", "left", elm_widget_style_get(obj));
67         else
68           elm_layout_theme_set
69             (obj, "panel", "right", elm_widget_style_get(obj));
70         break;
71
72       case ELM_PANEL_ORIENT_RIGHT:
73         if (!elm_widget_mirrored_get(obj))
74           elm_layout_theme_set
75             (obj, "panel", "right", elm_widget_style_get(obj));
76         else
77           elm_layout_theme_set
78             (obj, "panel", "left", elm_widget_style_get(obj));
79         break;
80      }
81
82    /* access */
83    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
84      {
85         Evas_Object *ao;
86         ao = _elm_access_edje_object_part_object_register
87                (obj, ELM_WIDGET_DATA(sd)->resize_obj, "btn_icon");
88         _elm_access_text_set(_elm_access_object_get(ao),
89                              ELM_ACCESS_TYPE, E_("panel button"));
90         _elm_access_callback_set
91           (_elm_access_object_get(ao), ELM_ACCESS_STATE, _access_state_cb, obj);
92      }
93 }
94
95 static Eina_Bool
96 _elm_panel_smart_theme(Evas_Object *obj)
97 {
98    const char *str;
99
100    ELM_PANEL_DATA_GET(obj, sd);
101
102    if (!ELM_WIDGET_CLASS(_elm_panel_parent_sc)->theme(obj))
103      return EINA_FALSE;
104
105    _mirrored_set(obj, elm_widget_mirrored_get(obj));
106
107    str = edje_object_data_get
108        (ELM_WIDGET_DATA(sd)->resize_obj, "focus_highlight");
109    if ((str) && (!strcmp(str, "on")))
110      elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
111    else
112      elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
113
114    _orient_set_do(obj);
115
116    elm_layout_sizing_eval(obj);
117
118    return EINA_TRUE;
119 }
120
121 static Eina_Bool
122 _elm_panel_smart_focus_next(const Evas_Object *obj,
123                             Elm_Focus_Direction dir,
124                             Evas_Object **next)
125 {
126    Evas_Object *cur;
127
128    ELM_PANEL_DATA_GET(obj, sd);
129
130    if (!sd->content)
131      return EINA_FALSE;
132
133    cur = sd->content;
134
135    /* Try to Focus cycle in subitem */
136    if (!sd->hidden)
137      return elm_widget_focus_next_get(cur, dir, next);
138
139    /* access */
140    if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
141      {
142         Evas_Object *ao, *po;
143         po = (Evas_Object *)edje_object_part_object_get
144                (ELM_WIDGET_DATA(sd)->resize_obj, "btn_icon");
145         ao = evas_object_data_get(po, "_part_access_obj");
146         _elm_access_highlight_set(ao, EINA_FALSE);
147      }
148
149    /* Return */
150    *next = (Evas_Object *)obj;
151    return !elm_widget_focus_get(obj);
152 }
153
154 static void
155 _box_layout_cb(Evas_Object *o,
156                Evas_Object_Box_Data *priv,
157                void *data __UNUSED__)
158 {
159    _els_box_layout(o, priv, EINA_TRUE, EINA_FALSE, EINA_FALSE);
160 }
161
162 static void
163 _panel_toggle(void *data __UNUSED__,
164               Evas_Object *obj,
165               const char *emission __UNUSED__,
166               const char *source __UNUSED__)
167 {
168    ELM_PANEL_DATA_GET(obj, sd);
169
170    if (sd->hidden)
171      {
172         elm_layout_signal_emit(obj, "elm,action,show", "elm");
173         sd->hidden = EINA_FALSE;
174         evas_object_repeat_events_set(obj, EINA_FALSE);
175      }
176    else
177      {
178         elm_layout_signal_emit(obj, "elm,action,hide", "elm");
179         sd->hidden = EINA_TRUE;
180         evas_object_repeat_events_set(obj, EINA_TRUE);
181         if (elm_widget_focus_get(sd->content))
182           {
183              elm_widget_focused_object_clear(obj);
184              elm_widget_focus_steal(obj);
185           }
186      }
187
188    edje_object_message_signal_process(ELM_WIDGET_DATA(sd)->resize_obj);
189 }
190
191 static Eina_Bool
192 _elm_panel_smart_event(Evas_Object *obj,
193                        Evas_Object *src,
194                        Evas_Callback_Type type,
195                        void *event_info)
196 {
197    Evas_Event_Key_Down *ev = event_info;
198
199    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
200    if ((src != obj) || (type != EVAS_CALLBACK_KEY_DOWN)) return EINA_FALSE;
201    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
202
203    if ((strcmp(ev->keyname, "Return")) &&
204        (strcmp(ev->keyname, "KP_Enter")) &&
205        (strcmp(ev->keyname, "space")))
206      return EINA_FALSE;
207
208    _panel_toggle(NULL, obj, NULL, NULL);
209
210    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
211    return EINA_TRUE;
212 }
213
214 static Eina_Bool
215 _elm_panel_smart_content_set(Evas_Object *obj,
216                              const char *part,
217                              Evas_Object *content)
218 {
219    ELM_PANEL_DATA_GET(obj, sd);
220
221    if (part && strcmp(part, "default"))
222      return ELM_CONTAINER_CLASS(_elm_panel_parent_sc)->content_set
223               (obj, part, content);
224
225    if (sd->content == content) return EINA_TRUE;
226    if (sd->content)
227      evas_object_box_remove_all(sd->bx, EINA_TRUE);
228    sd->content = content;
229    if (content)
230      {
231         evas_object_box_append(sd->bx, sd->content);
232         evas_object_show(sd->content);
233      }
234
235    elm_layout_sizing_eval(obj);
236
237    return EINA_TRUE;
238 }
239
240 static Evas_Object *
241 _elm_panel_smart_content_get(const Evas_Object *obj,
242                              const char *part)
243 {
244    ELM_PANEL_DATA_GET(obj, sd);
245
246    if (part && strcmp(part, "default"))
247      return ELM_CONTAINER_CLASS(_elm_panel_parent_sc)->content_get(obj, part);
248
249    return sd->content;
250 }
251
252 static Evas_Object *
253 _elm_panel_smart_content_unset(Evas_Object *obj,
254                                const char *part)
255 {
256    Evas_Object *content;
257
258    ELM_PANEL_DATA_GET(obj, sd);
259
260    if (part && strcmp(part, "default"))
261      return ELM_CONTAINER_CLASS
262               (_elm_panel_parent_sc)->content_unset(obj, part);
263
264    if (!sd->content) return NULL;
265    content = sd->content;
266
267    evas_object_box_remove_all(sd->bx, EINA_FALSE);
268    sd->content = NULL;
269
270    return content;
271 }
272
273 static void
274 _elm_panel_smart_add(Evas_Object *obj)
275 {
276    EVAS_SMART_DATA_ALLOC(obj, Elm_Panel_Smart_Data);
277
278    ELM_WIDGET_CLASS(_elm_panel_parent_sc)->base.add(obj);
279
280    elm_widget_can_focus_set(obj, EINA_TRUE);
281
282    /* just to bootstrap and have theme hook to work */
283    elm_layout_theme_set(obj, "panel", "top", elm_widget_style_get(obj));
284
285    _elm_panel_smart_theme(obj);
286
287    elm_widget_can_focus_set(obj, EINA_TRUE);
288
289    priv->hidden = EINA_FALSE;
290
291    priv->bx = evas_object_box_add(evas_object_evas_get(obj));
292    evas_object_size_hint_align_set(priv->bx, 0.5, 0.5);
293    evas_object_box_layout_set(priv->bx, _box_layout_cb, priv, NULL);
294    elm_layout_content_set(obj, "elm.swallow.content", priv->bx);
295    evas_object_show(priv->bx);
296
297    elm_layout_signal_callback_add
298      (obj, "elm,action,panel,toggle", "*", _panel_toggle, obj);
299
300    _mirrored_set(obj, elm_widget_mirrored_get(obj));
301
302    elm_layout_sizing_eval(obj);
303 }
304
305 static void
306 _elm_panel_smart_del(Evas_Object *obj)
307 {
308    Evas_Object *child;
309    Eina_List *l;
310
311    ELM_PANEL_DATA_GET(obj, sd);
312
313    sd->on_deletion = EINA_TRUE;
314
315    /* let's make our box object the *last* to be processed, since it
316     * may (smart) parent other sub objects here */
317    EINA_LIST_FOREACH(ELM_WIDGET_DATA(sd)->subobjs, l, child)
318      {
319         if (child == sd->bx)
320           {
321              ELM_WIDGET_DATA(sd)->subobjs =
322                eina_list_demote_list(ELM_WIDGET_DATA(sd)->subobjs, l);
323              break;
324           }
325      }
326
327    ELM_WIDGET_CLASS(_elm_panel_parent_sc)->base.del(obj);
328 }
329
330 static void
331 _elm_panel_smart_access(Evas_Object *obj, Eina_Bool is_access)
332 {
333    ELM_PANEL_CHECK(obj);
334    ELM_PANEL_DATA_GET(obj, sd);
335
336    if (is_access)
337      _elm_access_edje_object_part_object_register
338        (obj, ELM_WIDGET_DATA(sd)->resize_obj, "btn_icon");
339    else
340      _elm_access_edje_object_part_object_unregister
341        (obj, ELM_WIDGET_DATA(sd)->resize_obj, "btn_icon");
342 }
343
344 static void
345 _elm_panel_smart_set_user(Elm_Panel_Smart_Class *sc)
346 {
347    ELM_WIDGET_CLASS(sc)->base.add = _elm_panel_smart_add;
348    ELM_WIDGET_CLASS(sc)->base.del = _elm_panel_smart_del;
349
350    ELM_WIDGET_CLASS(sc)->focus_next = _elm_panel_smart_focus_next;
351    ELM_WIDGET_CLASS(sc)->theme = _elm_panel_smart_theme;
352    ELM_WIDGET_CLASS(sc)->event = _elm_panel_smart_event;
353    ELM_WIDGET_CLASS(sc)->access = _elm_panel_smart_access;
354
355    ELM_CONTAINER_CLASS(sc)->content_set = _elm_panel_smart_content_set;
356    ELM_CONTAINER_CLASS(sc)->content_get = _elm_panel_smart_content_get;
357    ELM_CONTAINER_CLASS(sc)->content_unset = _elm_panel_smart_content_unset;
358
359    ELM_LAYOUT_CLASS(sc)->sizing_eval = _elm_panel_smart_sizing_eval;
360 }
361
362 EAPI const Elm_Panel_Smart_Class *
363 elm_panel_smart_class_get(void)
364 {
365    static Elm_Panel_Smart_Class _sc =
366      ELM_PANEL_SMART_CLASS_INIT_NAME_VERSION(ELM_PANEL_SMART_NAME);
367    static const Elm_Panel_Smart_Class *class = NULL;
368
369    if (class) return class;
370
371    _elm_panel_smart_set(&_sc);
372    class = &_sc;
373
374    return class;
375 }
376
377 EAPI Evas_Object *
378 elm_panel_add(Evas_Object *parent)
379 {
380    Evas_Object *obj;
381
382    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
383
384    obj = elm_widget_add(_elm_panel_smart_class_new(), parent);
385    if (!obj) return NULL;
386
387    if (!elm_widget_sub_object_add(parent, obj))
388      ERR("could not add %p as sub object of %p", obj, parent);
389
390    return obj;
391 }
392
393 EAPI void
394 elm_panel_orient_set(Evas_Object *obj,
395                      Elm_Panel_Orient orient)
396 {
397    ELM_PANEL_CHECK(obj);
398    ELM_PANEL_DATA_GET(obj, sd);
399
400    if (sd->orient == orient) return;
401    sd->orient = orient;
402
403    _orient_set_do(obj);
404
405    elm_layout_sizing_eval(obj);
406 }
407
408 EAPI Elm_Panel_Orient
409 elm_panel_orient_get(const Evas_Object *obj)
410 {
411    ELM_PANEL_CHECK(obj) ELM_PANEL_ORIENT_LEFT;
412    ELM_PANEL_DATA_GET(obj, sd);
413
414    return sd->orient;
415 }
416
417 EAPI void
418 elm_panel_hidden_set(Evas_Object *obj,
419                      Eina_Bool hidden)
420 {
421    ELM_PANEL_CHECK(obj);
422    ELM_PANEL_DATA_GET(obj, sd);
423
424    if (sd->hidden == hidden) return;
425
426    _panel_toggle(NULL, obj, NULL, NULL);
427 }
428
429 EAPI Eina_Bool
430 elm_panel_hidden_get(const Evas_Object *obj)
431 {
432    ELM_PANEL_CHECK(obj) EINA_FALSE;
433    ELM_PANEL_DATA_GET(obj, sd);
434
435    return sd->hidden;
436 }
437
438 EAPI void
439 elm_panel_toggle(Evas_Object *obj)
440 {
441    ELM_PANEL_CHECK(obj);
442
443    _panel_toggle(NULL, obj, NULL, NULL);
444 }