ee7b84457817da41ded951e6f630114dfc3ef2a5
[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;
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  * @param obj The panel object
239  * @param content The panel content
240  *
241  * @ingroup Panel
242  */
243 EAPI void 
244 elm_panel_content_set(Evas_Object *obj, Evas_Object *content) 
245 {
246    ELM_CHECK_WIDTYPE(obj, widtype);
247    Widget_Data *wd = elm_widget_data_get(obj);
248    if (!wd) return;
249    evas_object_box_remove_all(wd->bx, EINA_TRUE);
250    if (!content) return;
251    evas_object_box_append(wd->bx, content);
252    evas_object_show(content);
253    _sizing_eval(obj);
254 }
255
256 /**
257  * Set the state of the panel.
258  *
259  * @param obj The panel object
260  * @param hidden If true, the panel will run the edje animation to contract
261  *
262  * @ingroup Panel
263  */
264 EAPI void
265 elm_panel_hidden_set(Evas_Object *obj, Eina_Bool hidden)
266 {
267    ELM_CHECK_WIDTYPE(obj, widtype);
268    Widget_Data *wd = elm_widget_data_get(obj);
269    if (!wd) return;
270    if (wd->hidden == hidden) return;
271    wd->hidden = hidden;
272    _toggle_panel(obj, NULL, "elm,action,panel,toggle", "*");
273 }
274
275 /**
276  * Get the state of the panel.
277  *
278  * @param obj The panel object
279  * @param hidden If true, the panel is in the "hide" state
280  *
281  * @ingroup Panel
282  */
283 EAPI Eina_Bool
284 elm_panel_hidden_get(Evas_Object *obj)
285 {
286    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
287    Widget_Data *wd = elm_widget_data_get(obj);
288    if (!wd) return EINA_FALSE;
289    return wd->hidden;
290 }
291
292 /**
293  * Toggle the state of the panel from code
294  *
295  * @param obj The panel object
296  *
297  * @ingroup Panel
298  */
299 EAPI void
300 elm_panel_toggle(Evas_Object *obj)
301 {
302    ELM_CHECK_WIDTYPE(obj, widtype);
303    Widget_Data *wd = elm_widget_data_get(obj);
304    if (!wd) return;
305    wd->hidden = !(wd->hidden);
306    _toggle_panel(obj, NULL, "elm,action,panel,toggle", "*");
307 }