Merge branch 'master' of 165.213.180.234:/git/slp/pkgs/elementary
[framework/uifw/elementary.git] / src / lib / elm_panel.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include "els_scroller.h"
4
5 /**
6  * @defgroup Panel Panel
7  * @ingroup Elementary
8  *
9  * A panel is a type of animated container that contains subobjects.  It
10  * can be expanded or contracted.
11  *
12  * Orientations are as follows:
13  * ELM_PANEL_ORIENT_TOP
14  * ELM_PANEL_ORIENT_BOTTOM
15  * ELM_PANEL_ORIENT_LEFT
16  * ELM_PANEL_ORIENT_RIGHT
17  * NOTE: Only LEFT and RIGHT orientations are implemented.
18  *
19  * THIS WIDGET IS UNDER CONSTRUCTION!
20  */
21
22 typedef struct _Widget_Data Widget_Data;
23 struct _Widget_Data 
24 {
25    Evas_Object *scr, *bx, *content;
26    Elm_Panel_Orient orient;
27    Eina_Bool hidden : 1;
28 };
29
30 static const char *widtype = NULL;
31 static void _del_hook(Evas_Object *obj);
32 static void _theme_hook(Evas_Object *obj);
33 static void _sizing_eval(Evas_Object *obj);
34 static void _resize(void *data, Evas *evas, Evas_Object *obj, void *event);
35 static void _layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data);
36 static void _toggle_panel(void *data, Evas_Object *obj, const char *emission, const char *source);
37
38 static void 
39 _del_hook(Evas_Object *obj) 
40 {
41    Widget_Data *wd = elm_widget_data_get(obj);
42    if (!wd) return;
43    free(wd);
44 }
45
46 static void 
47 _theme_hook(Evas_Object *obj) 
48 {
49    Widget_Data *wd = elm_widget_data_get(obj);
50    if (!wd) return;
51    elm_smart_scroller_object_theme_set(obj, wd->scr, "panel", "base", elm_widget_style_get(obj));
52 //   scale = (elm_widget_scale_get(obj) * _elm_config->scale);
53 //   edje_object_scale_set(wd->scr, scale);
54    _sizing_eval(obj);
55 }
56
57 static void 
58 _sizing_eval(Evas_Object *obj) 
59 {
60    Widget_Data *wd = elm_widget_data_get(obj);
61    Evas_Coord mw = -1, mh = -1;
62    Evas_Coord vw = 0, vh = 0;
63    Evas_Coord w, h;
64    if (!wd) return;
65    evas_object_smart_calculate(wd->bx);
66    edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr), 
67                              &mw, &mh);
68    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
69    if (w < mw) w = mw;
70    if (h < mh) h = mh;
71    evas_object_resize(wd->scr, w, h);
72
73    evas_object_size_hint_min_get(wd->bx, &mw, &mh);
74    if (w > mw) mw = w;
75    if (h > mh) mh = h;
76    evas_object_resize(wd->bx, mw, mh);
77
78    elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
79    mw = mw + (w - vw);
80    mh = mh + (h - vh);
81    evas_object_size_hint_min_set(obj, mw, mh);
82    evas_object_size_hint_max_set(obj, -1, -1);
83 }
84
85 static void 
86 _resize(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
87 {
88    Widget_Data *wd = elm_widget_data_get(data);
89    Evas_Coord mw, mh, vw, vh, w, h;
90    if (!wd) return;
91    elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
92    evas_object_size_hint_min_get(wd->bx, &mw, &mh);
93    evas_object_geometry_get(wd->bx, NULL, NULL, &w, &h);
94    if ((vw >= mw) || (vh >= mh))
95      {
96         if ((w != vw) || (h != vh)) evas_object_resize(wd->bx, vw, vh);
97      }
98 }
99
100 static void 
101 _layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data) 
102 {
103    Widget_Data *wd = data;
104    if (!wd) return;
105    _els_box_layout(o, priv, EINA_TRUE, EINA_FALSE);
106 }
107
108 static void 
109 _toggle_panel(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__) 
110 {
111    Widget_Data *wd = elm_widget_data_get(data);
112    if (!wd) return;
113    if (wd->hidden) 
114      {
115         edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), 
116                                 "elm,action,show", "elm");
117         wd->hidden = EINA_FALSE;
118      }
119    else
120      {
121         edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), 
122                                 "elm,action,hide", "elm");
123         wd->hidden = EINA_TRUE;
124      }
125 }
126
127 /**
128  * Adds a panel object
129  *
130  * @param parent The parent object
131  *
132  * @return The panel object, or NULL on failure
133  *
134  * @ingroup Panel
135  */
136 EAPI Evas_Object *
137 elm_panel_add(Evas_Object *parent) 
138 {
139    Evas_Object *obj;
140    Evas *evas;
141    Widget_Data *wd;
142
143    wd = ELM_NEW(Widget_Data);
144    evas = evas_object_evas_get(parent);
145    obj = elm_widget_add(evas);
146    ELM_SET_WIDTYPE(widtype, "panel");
147    elm_widget_type_set(obj, "panel");
148    elm_widget_sub_object_add(parent, obj);
149    elm_widget_data_set(obj, wd);
150    elm_widget_del_hook_set(obj, _del_hook);
151    elm_widget_theme_hook_set(obj, _theme_hook);
152    elm_widget_can_focus_set(obj, 0);
153
154    wd->scr = elm_smart_scroller_add(evas);
155    elm_smart_scroller_widget_set(wd->scr, obj);
156    elm_smart_scroller_object_theme_set(obj, wd->scr, "panel", "base", "left");
157    elm_smart_scroller_bounce_allow_set(wd->scr, 0, 0);
158    elm_widget_resize_object_set(obj, wd->scr);
159    elm_smart_scroller_policy_set(wd->scr, ELM_SMART_SCROLLER_POLICY_OFF, 
160                                  ELM_SMART_SCROLLER_POLICY_OFF);
161
162    wd->hidden = EINA_FALSE;
163    wd->orient = ELM_PANEL_ORIENT_LEFT;
164
165    wd->bx = evas_object_box_add(evas);
166    evas_object_size_hint_align_set(wd->bx, 0.5, 0.5);
167    evas_object_box_layout_set(wd->bx, _layout, wd, NULL);
168    elm_widget_sub_object_add(obj, wd->bx);
169    elm_smart_scroller_child_set(wd->scr, wd->bx);
170    evas_object_show(wd->bx);
171
172    edje_object_signal_callback_add(elm_smart_scroller_edje_object_get(wd->scr), 
173                                    "elm,action,panel,toggle", "*", 
174                                    _toggle_panel, obj);
175
176    evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_RESIZE, _resize, obj);
177
178    _sizing_eval(obj);
179    return obj;
180 }
181
182 /**
183  * Sets the orientation of the panel
184  *
185  * @param parent The parent object
186  * @param orient The panel orientation.  Can be one of the following:
187  * ELM_PANEL_ORIENT_TOP
188  * ELM_PANEL_ORIENT_BOTTOM
189  * ELM_PANEL_ORIENT_LEFT
190  * ELM_PANEL_ORIENT_RIGHT
191  *
192  * NOTE: Only LEFT and RIGHT orientations are implemented.
193  *
194  * @ingroup Panel
195  */
196 EAPI void 
197 elm_panel_orient_set(Evas_Object *obj, Elm_Panel_Orient orient) 
198 {
199    ELM_CHECK_WIDTYPE(obj, widtype);
200    Widget_Data *wd = elm_widget_data_get(obj);
201    if (!wd) return;
202    wd->orient = orient;
203    switch (orient) 
204      {
205      case ELM_PANEL_ORIENT_TOP:
206      case ELM_PANEL_ORIENT_BOTTOM:
207         break;
208      case ELM_PANEL_ORIENT_LEFT:
209         elm_smart_scroller_object_theme_set(obj, wd->scr, "panel", "base", "left");
210         break;
211      case ELM_PANEL_ORIENT_RIGHT:
212         elm_smart_scroller_object_theme_set(obj, wd->scr, "panel", "base", "right");
213         break;
214      default:
215         break;
216      }
217    _sizing_eval(obj);
218 }
219
220 /**
221  * Get the orientation of the panel.
222  *
223  * @param obj The panel object
224  * @return The Elm_Panel_Orient, or ELM_PANEL_ORIENT_LEFT on failure.
225  *
226  * @ingroup Panel
227  */
228 EAPI Elm_Panel_Orient
229 elm_panel_orient_get(Evas_Object *obj)
230 {
231    ELM_CHECK_WIDTYPE(obj, widtype) ELM_PANEL_ORIENT_LEFT;
232    Widget_Data *wd = elm_widget_data_get(obj);
233    if (!wd) return ELM_PANEL_ORIENT_LEFT;
234    return wd->orient;   
235 }
236
237 /**
238  * Set the content of the panel.
239  *
240  * Once the content object is set, a previously set one will be deleted.
241  * If you want to keep that old content object, use the
242  * elm_panel_content_unset() function.
243  *
244  * @param obj The panel object
245  * @param content The panel content
246  *
247  * @ingroup Panel
248  */
249 EAPI void
250 elm_panel_content_set(Evas_Object *obj, Evas_Object *content)
251 {
252    ELM_CHECK_WIDTYPE(obj, widtype);
253    Widget_Data *wd = elm_widget_data_get(obj);
254    if (!wd) return;
255    if (wd->content == content) return;
256    if (wd->content)
257      evas_object_box_remove_all(wd->bx, EINA_TRUE);
258    wd->content = content;
259    if (content)
260      {
261         evas_object_box_append(wd->bx, wd->content);
262         evas_object_show(wd->content);
263      }
264    _sizing_eval(obj);
265 }
266
267 /**
268  * Unset the content of the panel.
269  *
270  * Unparent and return the content object which was set for this widget.
271  *
272  * @param obj The panel object
273  * @return The content that was being used
274  *
275  * @ingroup Panel
276  */
277 EAPI Evas_Object *
278 elm_panel_content_unset(Evas_Object *obj)
279 {
280    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
281    Widget_Data *wd = elm_widget_data_get(obj);
282    Evas_Object *content;
283    if (!wd) return NULL;
284    if (!wd->content) return NULL;
285    content = wd->content;
286    evas_object_box_remove_all(wd->bx, EINA_FALSE);
287    wd->content = NULL;
288    return content;
289 }
290
291 /**
292  * Set the state of the panel.
293  *
294  * @param obj The panel object
295  * @param hidden If true, the panel will run the edje animation to contract
296  *
297  * @ingroup Panel
298  */
299 EAPI void
300 elm_panel_hidden_set(Evas_Object *obj, Eina_Bool hidden)
301 {
302    ELM_CHECK_WIDTYPE(obj, widtype);
303    Widget_Data *wd = elm_widget_data_get(obj);
304    if (!wd) return;
305    if (wd->hidden == hidden) return;
306    wd->hidden = hidden;
307    _toggle_panel(obj, NULL, "elm,action,panel,toggle", "*");
308 }
309
310 /**
311  * Get the state of the panel.
312  *
313  * @param obj The panel object
314  * @param hidden If true, the panel is in the "hide" state
315  *
316  * @ingroup Panel
317  */
318 EAPI Eina_Bool
319 elm_panel_hidden_get(Evas_Object *obj)
320 {
321    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
322    Widget_Data *wd = elm_widget_data_get(obj);
323    if (!wd) return EINA_FALSE;
324    return wd->hidden;
325 }
326
327 /**
328  * Toggle the state of the panel from code
329  *
330  * @param obj The panel object
331  *
332  * @ingroup Panel
333  */
334 EAPI void
335 elm_panel_toggle(Evas_Object *obj)
336 {
337    ELM_CHECK_WIDTYPE(obj, widtype);
338    Widget_Data *wd = elm_widget_data_get(obj);
339    if (!wd) return;
340    wd->hidden = !(wd->hidden);
341    _toggle_panel(obj, NULL, "elm,action,panel,toggle", "*");
342 }