[access] support back gesture
[framework/uifw/elementary.git] / src / lib / elm_panes.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include "elm_widget_panes.h"
4
5 /**
6  * TODO
7  * Update the minimun height of the bar in the theme.
8  * No minimun should be set in the vertical theme
9  * Add events (move, start ...)
10  */
11
12 EAPI const char ELM_PANES_SMART_NAME[] = "elm_panes";
13
14 static const char SIG_CLICKED[] = "clicked";
15 static const char SIG_PRESS[] = "press";
16 static const char SIG_UNPRESS[] = "unpress";
17 static const char SIG_DOUBLE_CLICKED[] = "clicked,double";
18 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
19    {SIG_CLICKED, ""},
20    {SIG_PRESS, ""},
21    {SIG_UNPRESS, ""},
22    {SIG_DOUBLE_CLICKED, ""},
23    {NULL, NULL}
24 };
25
26 static const Elm_Layout_Part_Alias_Description _content_aliases[] =
27 {
28    {"left", "elm.swallow.left"},
29    {"right", "elm.swallow.right"},
30    {NULL, NULL}
31 };
32
33 EVAS_SMART_SUBCLASS_NEW
34   (ELM_PANES_SMART_NAME, _elm_panes, Elm_Panes_Smart_Class,
35   Elm_Layout_Smart_Class, elm_layout_smart_class_get, _smart_callbacks);
36
37 static Eina_Bool
38 _elm_panes_smart_theme(Evas_Object *obj)
39 {
40    double size;
41
42    ELM_PANES_DATA_GET(obj, sd);
43
44    if (sd->horizontal)
45      eina_stringshare_replace(&(ELM_LAYOUT_DATA(sd)->group), "horizontal");
46    else
47      eina_stringshare_replace(&(ELM_LAYOUT_DATA(sd)->group), "vertical");
48
49    if (!ELM_WIDGET_CLASS(_elm_panes_parent_sc)->theme(obj)) return EINA_FALSE;
50
51    size = elm_panes_content_left_size_get(obj);
52
53    if (sd->fixed) elm_layout_signal_emit(obj, "elm.panes.fixed", "elm");
54
55    elm_layout_sizing_eval(obj);
56
57    elm_panes_content_left_size_set(obj, size);
58
59    return EINA_TRUE;
60 }
61
62 static Eina_Bool
63 _elm_panes_smart_focus_next(const Evas_Object *obj,
64                             Elm_Focus_Direction dir,
65                             Evas_Object **next)
66 {
67    double w, h;
68    unsigned char i;
69    Evas_Object *to_focus;
70    Evas_Object *chain[2];
71    Evas_Object *left, *right;
72
73    ELM_PANES_DATA_GET(obj, sd);
74
75    edje_object_part_drag_value_get
76      (ELM_WIDGET_DATA(sd)->resize_obj, "elm.bar", &w, &h);
77
78    left = elm_layout_content_get(obj, "left");
79    right = elm_layout_content_get(obj, "right");
80
81    if (((sd->horizontal) && (h == 0.0)) || ((!sd->horizontal) && (w == 0.0)))
82      return elm_widget_focus_next_get(right, dir, next);
83
84    /* Direction */
85    if (dir == ELM_FOCUS_PREVIOUS)
86      {
87         chain[0] = right;
88         chain[1] = left;
89      }
90    else if (dir == ELM_FOCUS_NEXT)
91      {
92         chain[0] = left;
93         chain[1] = right;
94      }
95    else return EINA_FALSE;
96
97    i = elm_widget_focus_get(chain[1]);
98
99    if (elm_widget_focus_next_get(chain[i], dir, next)) return EINA_TRUE;
100
101    i = !i;
102
103    if (elm_widget_focus_next_get(chain[i], dir, &to_focus))
104      {
105         *next = to_focus;
106         return !!i;
107      }
108
109    return EINA_FALSE;
110 }
111
112 static void
113 _on_clicked(void *data,
114             Evas_Object *obj __UNUSED__,
115             const char *emission __UNUSED__,
116             const char *source __UNUSED__)
117 {
118    evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
119 }
120
121 static void
122 _double_clicked(void *data,
123                 Evas_Object *obj __UNUSED__,
124                 const char *emission __UNUSED__,
125                 const char *source __UNUSED__)
126 {
127    ELM_PANES_DATA_GET(data, sd);
128
129    sd->double_clicked = EINA_TRUE;
130 }
131
132 static void
133 _on_pressed(void *data,
134             Evas_Object *obj __UNUSED__,
135             const char *emission __UNUSED__,
136             const char *source __UNUSED__)
137 {
138    evas_object_smart_callback_call(data, SIG_PRESS, NULL);
139 }
140
141 static void
142 _on_unpressed(void *data,
143               Evas_Object *obj __UNUSED__,
144               const char *emission __UNUSED__,
145               const char *source __UNUSED__)
146 {
147    ELM_PANES_DATA_GET(data, sd);
148    evas_object_smart_callback_call(data, SIG_UNPRESS, NULL);
149
150    if (sd->double_clicked)
151      {
152         evas_object_smart_callback_call(data, SIG_DOUBLE_CLICKED, NULL);
153         sd->double_clicked = EINA_FALSE;
154      }
155 }
156
157 static void
158 _elm_panes_smart_add(Evas_Object *obj)
159 {
160    EVAS_SMART_DATA_ALLOC(obj, Elm_Panes_Smart_Data);
161
162    ELM_WIDGET_CLASS(_elm_panes_parent_sc)->base.add(obj);
163
164    elm_layout_theme_set(obj, "panes", "vertical", elm_widget_style_get(obj));
165
166    elm_panes_content_left_size_set(obj, 0.5);
167
168    edje_object_signal_callback_add
169      (ELM_WIDGET_DATA(priv)->resize_obj, "elm,action,click", "",
170      _on_clicked, obj);
171    edje_object_signal_callback_add
172      (ELM_WIDGET_DATA(priv)->resize_obj, "elm,action,click,double", "",
173      _double_clicked, obj);
174    edje_object_signal_callback_add
175      (ELM_WIDGET_DATA(priv)->resize_obj, "elm,action,press", "",
176      _on_pressed, obj);
177    edje_object_signal_callback_add
178      (ELM_WIDGET_DATA(priv)->resize_obj, "elm,action,unpress", "",
179      _on_unpressed, obj);
180
181    elm_widget_can_focus_set(obj, EINA_FALSE);
182
183    elm_layout_sizing_eval(obj);
184 }
185
186 static void
187 _elm_panes_smart_set_user(Elm_Panes_Smart_Class *sc)
188 {
189    ELM_WIDGET_CLASS(sc)->base.add = _elm_panes_smart_add;
190
191    ELM_WIDGET_CLASS(sc)->theme = _elm_panes_smart_theme;
192    ELM_WIDGET_CLASS(sc)->focus_next = _elm_panes_smart_focus_next;
193
194    ELM_LAYOUT_CLASS(sc)->content_aliases = _content_aliases;
195 }
196
197 EAPI const Elm_Panes_Smart_Class *
198 elm_panes_smart_class_get(void)
199 {
200    static Elm_Panes_Smart_Class _sc =
201      ELM_PANES_SMART_CLASS_INIT_NAME_VERSION(ELM_PANES_SMART_NAME);
202    static const Elm_Panes_Smart_Class *class = NULL;
203    Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
204
205    if (class)
206      return class;
207
208    _elm_panes_smart_set(&_sc);
209    esc->callbacks = _smart_callbacks;
210    class = &_sc;
211
212    return class;
213 }
214
215 EAPI Evas_Object *
216 elm_panes_add(Evas_Object *parent)
217 {
218    Evas_Object *obj;
219
220    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
221
222    obj = elm_widget_add(_elm_panes_smart_class_new(), parent);
223    if (!obj) return NULL;
224
225    if (!elm_widget_sub_object_add(parent, obj))
226      ERR("could not add %p as sub object of %p", obj, parent);
227
228    return obj;
229 }
230
231 EINA_DEPRECATED EAPI void
232 elm_panes_content_left_set(Evas_Object *obj,
233                            Evas_Object *content)
234 {
235    elm_layout_content_set(obj, "left", content);
236 }
237
238 EINA_DEPRECATED EAPI void
239 elm_panes_content_right_set(Evas_Object *obj,
240                             Evas_Object *content)
241 {
242    elm_layout_content_set(obj, "right", content);
243 }
244
245 EINA_DEPRECATED EAPI Evas_Object *
246 elm_panes_content_left_get(const Evas_Object *obj)
247 {
248    return elm_layout_content_get(obj, "left");
249 }
250
251 EINA_DEPRECATED EAPI Evas_Object *
252 elm_panes_content_right_get(const Evas_Object *obj)
253 {
254    return elm_layout_content_get(obj, "right");
255 }
256
257 EINA_DEPRECATED EAPI Evas_Object *
258 elm_panes_content_left_unset(Evas_Object *obj)
259 {
260    return elm_layout_content_unset(obj, "left");
261 }
262
263 EINA_DEPRECATED EAPI Evas_Object *
264 elm_panes_content_right_unset(Evas_Object *obj)
265 {
266    return elm_layout_content_unset(obj, "right");
267 }
268
269 EAPI double
270 elm_panes_content_left_size_get(const Evas_Object *obj)
271 {
272    double w, h;
273
274    ELM_PANES_CHECK(obj) 0.0;
275    ELM_PANES_DATA_GET(obj, sd);
276
277    edje_object_part_drag_value_get
278      (ELM_WIDGET_DATA(sd)->resize_obj, "elm.bar", &w, &h);
279
280    if (sd->horizontal) return h;
281    else return w;
282 }
283
284 EAPI void
285 elm_panes_content_left_size_set(Evas_Object *obj,
286                                 double size)
287 {
288    ELM_PANES_CHECK(obj);
289    ELM_PANES_DATA_GET(obj, sd);
290
291    if (size < 0.0) size = 0.0;
292    else if (size > 1.0)
293      size = 1.0;
294    if (sd->horizontal)
295      edje_object_part_drag_value_set
296        (ELM_WIDGET_DATA(sd)->resize_obj, "elm.bar", 0.0, size);
297    else
298      edje_object_part_drag_value_set
299        (ELM_WIDGET_DATA(sd)->resize_obj, "elm.bar", size, 0.0);
300 }
301
302 EAPI double
303 elm_panes_content_right_size_get(const Evas_Object *obj)
304 {
305    return 1.0 - elm_panes_content_left_size_get(obj);
306 }
307
308 EAPI void
309 elm_panes_content_right_size_set(Evas_Object *obj,
310                                  double size)
311 {
312    elm_panes_content_left_size_set(obj, (1.0 - size));
313 }
314
315 EAPI void
316 elm_panes_horizontal_set(Evas_Object *obj,
317                          Eina_Bool horizontal)
318 {
319    ELM_PANES_CHECK(obj);
320    ELM_PANES_DATA_GET(obj, sd);
321
322    sd->horizontal = horizontal;
323    _elm_panes_smart_theme(obj);
324
325    elm_panes_content_left_size_set(obj, 0.5);
326 }
327
328 EAPI Eina_Bool
329 elm_panes_horizontal_get(const Evas_Object *obj)
330 {
331    ELM_PANES_CHECK(obj) EINA_FALSE;
332    ELM_PANES_DATA_GET(obj, sd);
333
334    return sd->horizontal;
335 }
336
337 EAPI void
338 elm_panes_fixed_set(Evas_Object *obj, Eina_Bool fixed)
339 {
340    ELM_PANES_CHECK(obj);
341    ELM_PANES_DATA_GET(obj, sd);
342
343    sd->fixed = !!fixed;
344    if (sd->fixed == EINA_TRUE)
345      elm_layout_signal_emit(obj, "elm.panes.fixed", "elm");
346    else
347      elm_layout_signal_emit(obj, "elm.panes.unfixed", "elm");
348 }
349
350 EAPI Eina_Bool
351 elm_panes_fixed_get(const Evas_Object *obj)
352 {
353    ELM_PANES_CHECK(obj) EINA_FALSE;
354    ELM_PANES_DATA_GET(obj, sd);
355
356    return sd->fixed;
357 }