svn update: 48945 (latest:48959)
[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 orientation is 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;
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: Currently all orientations but LEFT are unimplemented.
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      case ELM_PANEL_ORIENT_RIGHT:
209         break;
210      default:
211         break;
212      }
213    _sizing_eval(obj);
214 }
215
216 /**
217  * Get the orientation of the panel.
218  *
219  * @param obj The panel object
220  * @return The Elm_Panel_Orient, or ELM_PANEL_ORIENT_LEFT on failure.
221  *
222  * @ingroup Panel
223  */
224 EAPI Elm_Panel_Orient
225 elm_panel_orient_get(Evas_Object *obj)
226 {
227    ELM_CHECK_WIDTYPE(obj, widtype) ELM_PANEL_ORIENT_LEFT;
228    Widget_Data *wd = elm_widget_data_get(obj);
229    if (!wd) return ELM_PANEL_ORIENT_LEFT;
230    return wd->orient;   
231 }
232
233 /**
234  * Set the content of the panel.
235  *
236  * @param obj The panel object
237  * @param content The panel content
238  *
239  * @ingroup Panel
240  */
241 EAPI void 
242 elm_panel_content_set(Evas_Object *obj, Evas_Object *content) 
243 {
244    ELM_CHECK_WIDTYPE(obj, widtype);
245    Widget_Data *wd = elm_widget_data_get(obj);
246    if (!wd) return;
247    evas_object_box_remove_all(wd->bx, EINA_TRUE);
248    if (!content) return;
249    evas_object_box_append(wd->bx, content);
250    evas_object_show(content);
251    _sizing_eval(obj);
252 }
253
254 /**
255  * Set the state of the panel.
256  *
257  * @param obj The panel object
258  * @param hidden If true, the panel will run the edje animation to contract
259  *
260  * @ingroup Panel
261  */
262 EAPI void
263 elm_panel_hidden_set(Evas_Object *obj, Eina_Bool hidden)
264 {
265    ELM_CHECK_WIDTYPE(obj, widtype);
266    Widget_Data *wd = elm_widget_data_get(obj);
267    if (!wd) return;
268    if (wd->hidden == hidden) return;
269    wd->hidden = hidden;
270    _toggle_panel(obj, NULL, "elm,action,panel,toggle", "*");
271 }
272
273 /**
274  * Get the state of the panel.
275  *
276  * @param obj The panel object
277  * @param hidden If true, the panel is in the "hide" state
278  *
279  * @ingroup Panel
280  */
281 EAPI Eina_Bool
282 elm_panel_hidden_get(Evas_Object *obj)
283 {
284    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
285    Widget_Data *wd = elm_widget_data_get(obj);
286    if (!wd) return EINA_FALSE;
287    return wd->hidden;
288 }
289
290 /**
291  * Toggle the state of the panel from code
292  *
293  * @param obj The panel object
294  *
295  * @ingroup Panel
296  */
297 EAPI void
298 elm_panel_toggle(Evas_Object *obj)
299 {
300    ELM_CHECK_WIDTYPE(obj, widtype);
301    Widget_Data *wd = elm_widget_data_get(obj);
302    if (!wd) return;
303    wd->hidden = !(wd->hidden);
304    _toggle_panel(obj, NULL, "elm,action,panel,toggle", "*");
305 }