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