diff options
Diffstat (limited to 'libraries/elementary/src/lib/elm_panel.c')
-rw-r--r-- | libraries/elementary/src/lib/elm_panel.c | 399 |
1 files changed, 399 insertions, 0 deletions
diff --git a/libraries/elementary/src/lib/elm_panel.c b/libraries/elementary/src/lib/elm_panel.c new file mode 100644 index 0000000..a93a7e0 --- /dev/null +++ b/libraries/elementary/src/lib/elm_panel.c | |||
@@ -0,0 +1,399 @@ | |||
1 | #include <Elementary.h> | ||
2 | #include "elm_priv.h" | ||
3 | #include "els_scroller.h" | ||
4 | #include "els_box.h" | ||
5 | |||
6 | typedef struct _Widget_Data Widget_Data; | ||
7 | struct _Widget_Data | ||
8 | { | ||
9 | Evas_Object *scr, *bx, *content; | ||
10 | Elm_Panel_Orient orient; | ||
11 | Eina_Bool hidden : 1; | ||
12 | }; | ||
13 | |||
14 | static const char *widtype = NULL; | ||
15 | static void _del_hook(Evas_Object *obj); | ||
16 | static void _theme_hook(Evas_Object *obj); | ||
17 | static void _on_focus_hook(void *data, Evas_Object *obj); | ||
18 | static void _sizing_eval(Evas_Object *obj); | ||
19 | static void _resize(void *data, Evas *evas, Evas_Object *obj, void *event); | ||
20 | static void _layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data); | ||
21 | static void _toggle_panel(void *data, Evas_Object *obj, const char *emission, const char *source); | ||
22 | |||
23 | static void | ||
24 | _del_hook(Evas_Object *obj) | ||
25 | { | ||
26 | Widget_Data *wd = elm_widget_data_get(obj); | ||
27 | if (!wd) return; | ||
28 | free(wd); | ||
29 | } | ||
30 | |||
31 | static void | ||
32 | _mirrored_set(Evas_Object *obj, Eina_Bool rtl) | ||
33 | { | ||
34 | Widget_Data *wd = elm_widget_data_get(obj); | ||
35 | if (!wd) return; | ||
36 | |||
37 | if (wd->scr) | ||
38 | { | ||
39 | elm_widget_mirrored_set(wd->bx, rtl); | ||
40 | elm_panel_orient_set(obj, elm_panel_orient_get(obj)); | ||
41 | } | ||
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_widget_mirrored_reload(obj); | ||
50 | if (wd->scr) | ||
51 | { | ||
52 | Evas_Object *edj; | ||
53 | const char *str; | ||
54 | |||
55 | _mirrored_set(obj, elm_widget_mirrored_get(obj)); | ||
56 | elm_smart_scroller_object_theme_set(obj, wd->scr, "panel", "base", | ||
57 | elm_widget_style_get(obj)); | ||
58 | // scale = (elm_widget_scale_get(obj) * _elm_config->scale); | ||
59 | // edje_object_scale_set(wd->scr, scale); | ||
60 | edj = elm_smart_scroller_edje_object_get(wd->scr); | ||
61 | str = edje_object_data_get(edj, "focus_highlight"); | ||
62 | if ((str) && (!strcmp(str, "on"))) | ||
63 | elm_widget_highlight_in_theme_set(obj, EINA_TRUE); | ||
64 | else | ||
65 | elm_widget_highlight_in_theme_set(obj, EINA_FALSE); | ||
66 | } | ||
67 | |||
68 | _sizing_eval(obj); | ||
69 | } | ||
70 | |||
71 | static void | ||
72 | _on_focus_hook(void *data __UNUSED__, Evas_Object *obj) | ||
73 | { | ||
74 | Widget_Data *wd = elm_widget_data_get(obj); | ||
75 | if (!wd) return; | ||
76 | if (elm_widget_focus_get(obj)) | ||
77 | evas_object_focus_set(obj, EINA_TRUE); | ||
78 | else | ||
79 | evas_object_focus_set(obj, EINA_FALSE); | ||
80 | } | ||
81 | |||
82 | static Eina_Bool | ||
83 | _elm_panel_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next) | ||
84 | { | ||
85 | Widget_Data *wd = elm_widget_data_get(obj); | ||
86 | Evas_Object *cur; | ||
87 | |||
88 | if ((!wd) || (!wd->content)) | ||
89 | return EINA_FALSE; | ||
90 | |||
91 | cur = wd->content; | ||
92 | |||
93 | /* Try Focus cycle in subitem */ | ||
94 | if (!wd->hidden) | ||
95 | return elm_widget_focus_next_get(cur, dir, next); | ||
96 | |||
97 | /* Return */ | ||
98 | *next = (Evas_Object *)obj; | ||
99 | return !elm_widget_focus_get(obj); | ||
100 | } | ||
101 | |||
102 | static void | ||
103 | _signal_emit_hook(Evas_Object *obj, const char *emission, const char *source) | ||
104 | { | ||
105 | Widget_Data *wd = elm_widget_data_get(obj); | ||
106 | if (!wd) return; | ||
107 | edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), | ||
108 | emission, source); | ||
109 | } | ||
110 | |||
111 | static void | ||
112 | _signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data) | ||
113 | { | ||
114 | Widget_Data *wd = elm_widget_data_get(obj); | ||
115 | if (!wd) return; | ||
116 | edje_object_signal_callback_add(elm_smart_scroller_edje_object_get(wd->scr), | ||
117 | emission, source, func_cb, data); | ||
118 | } | ||
119 | |||
120 | static void | ||
121 | _signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data) | ||
122 | { | ||
123 | Widget_Data *wd = elm_widget_data_get(obj); | ||
124 | edje_object_signal_callback_del_full( | ||
125 | elm_smart_scroller_edje_object_get(wd->scr), emission, source, | ||
126 | func_cb, data); | ||
127 | } | ||
128 | |||
129 | static void | ||
130 | _sizing_eval(Evas_Object *obj) | ||
131 | { | ||
132 | Widget_Data *wd = elm_widget_data_get(obj); | ||
133 | Evas_Coord mw = -1, mh = -1; | ||
134 | Evas_Coord vw = 0, vh = 0; | ||
135 | Evas_Coord w, h; | ||
136 | if (!wd) return; | ||
137 | evas_object_smart_calculate(wd->bx); | ||
138 | edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr), | ||
139 | &mw, &mh); | ||
140 | evas_object_geometry_get(obj, NULL, NULL, &w, &h); | ||
141 | if (w < mw) w = mw; | ||
142 | if (h < mh) h = mh; | ||
143 | evas_object_resize(wd->scr, w, h); | ||
144 | |||
145 | evas_object_size_hint_min_get(wd->bx, &mw, &mh); | ||
146 | if (w > mw) mw = w; | ||
147 | if (h > mh) mh = h; | ||
148 | evas_object_resize(wd->bx, mw, mh); | ||
149 | |||
150 | elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh); | ||
151 | mw = mw + (w - vw); | ||
152 | mh = mh + (h - vh); | ||
153 | evas_object_size_hint_min_set(obj, mw, mh); | ||
154 | evas_object_size_hint_max_set(obj, -1, -1); | ||
155 | } | ||
156 | |||
157 | static void | ||
158 | _resize(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event __UNUSED__) | ||
159 | { | ||
160 | Widget_Data *wd = elm_widget_data_get(data); | ||
161 | Evas_Coord mw, mh, vw, vh, w, h; | ||
162 | if (!wd) return; | ||
163 | elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh); | ||
164 | evas_object_size_hint_min_get(wd->bx, &mw, &mh); | ||
165 | evas_object_geometry_get(wd->bx, NULL, NULL, &w, &h); | ||
166 | if ((vw >= mw) || (vh >= mh)) | ||
167 | { | ||
168 | if ((w != vw) || (h != vh)) evas_object_resize(wd->bx, vw, vh); | ||
169 | } | ||
170 | } | ||
171 | |||
172 | static void | ||
173 | _layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data) | ||
174 | { | ||
175 | Widget_Data *wd = data; | ||
176 | if (!wd) return; | ||
177 | _els_box_layout(o, priv, EINA_TRUE, EINA_FALSE, EINA_FALSE); | ||
178 | } | ||
179 | |||
180 | static void | ||
181 | _toggle_panel(void *data, Evas_Object *obj, const char *emission __UNUSED__, const char *source __UNUSED__) | ||
182 | { | ||
183 | Widget_Data *wd = elm_widget_data_get(data); | ||
184 | if (!wd) return; | ||
185 | if (wd->hidden) | ||
186 | { | ||
187 | edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), | ||
188 | "elm,action,show", "elm"); | ||
189 | wd->hidden = EINA_FALSE; | ||
190 | evas_object_repeat_events_set(obj, EINA_FALSE); | ||
191 | } | ||
192 | else | ||
193 | { | ||
194 | edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), | ||
195 | "elm,action,hide", "elm"); | ||
196 | wd->hidden = EINA_TRUE; | ||
197 | evas_object_repeat_events_set(obj, EINA_TRUE); | ||
198 | if (elm_widget_focus_get(wd->content)) | ||
199 | { | ||
200 | elm_widget_focused_object_clear(obj); | ||
201 | elm_widget_focus_steal(obj); | ||
202 | } | ||
203 | } | ||
204 | } | ||
205 | |||
206 | static Eina_Bool | ||
207 | _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info) | ||
208 | { | ||
209 | if ((src != obj) || (type != EVAS_CALLBACK_KEY_DOWN)) return EINA_FALSE; | ||
210 | |||
211 | Evas_Event_Key_Down *ev = event_info; | ||
212 | Widget_Data *wd = elm_widget_data_get(obj); | ||
213 | if (!wd) return EINA_FALSE; | ||
214 | |||
215 | if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE; | ||
216 | |||
217 | if ((strcmp(ev->keyname, "Return")) && | ||
218 | (strcmp(ev->keyname, "KP_Enter")) && | ||
219 | (strcmp(ev->keyname, "space"))) | ||
220 | return EINA_FALSE; | ||
221 | |||
222 | _toggle_panel(obj, NULL, "elm,action,panel,toggle", "*"); | ||
223 | |||
224 | ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; | ||
225 | return EINA_TRUE; | ||
226 | } | ||
227 | |||
228 | static void | ||
229 | _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content) | ||
230 | { | ||
231 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
232 | Widget_Data *wd; | ||
233 | |||
234 | if (part && strcmp(part, "default")) return; | ||
235 | wd = elm_widget_data_get(obj); | ||
236 | if (!wd) return; | ||
237 | if (wd->content == content) return; | ||
238 | if (wd->content) | ||
239 | evas_object_box_remove_all(wd->bx, EINA_TRUE); | ||
240 | wd->content = content; | ||
241 | if (content) | ||
242 | { | ||
243 | evas_object_box_append(wd->bx, wd->content); | ||
244 | evas_object_show(wd->content); | ||
245 | } | ||
246 | _sizing_eval(obj); | ||
247 | } | ||
248 | |||
249 | static Evas_Object * | ||
250 | _content_get_hook(const Evas_Object *obj, const char *part) | ||
251 | { | ||
252 | ELM_CHECK_WIDTYPE(obj, widtype) NULL; | ||
253 | Widget_Data *wd; | ||
254 | |||
255 | if (part && strcmp(part, "default")) return NULL; | ||
256 | wd = elm_widget_data_get(obj); | ||
257 | if (!wd) return NULL; | ||
258 | return wd->content; | ||
259 | } | ||
260 | |||
261 | static Evas_Object * | ||
262 | _content_unset_hook(Evas_Object *obj, const char *part) | ||
263 | { | ||
264 | ELM_CHECK_WIDTYPE(obj, widtype) NULL; | ||
265 | Widget_Data *wd; | ||
266 | Evas_Object *content; | ||
267 | if (part && strcmp(part, "default")) return NULL; | ||
268 | wd = elm_widget_data_get(obj); | ||
269 | if (!wd) return NULL; | ||
270 | if (!wd->content) return NULL; | ||
271 | content = wd->content; | ||
272 | evas_object_box_remove_all(wd->bx, EINA_FALSE); | ||
273 | wd->content = NULL; | ||
274 | return content; | ||
275 | } | ||
276 | |||
277 | EAPI Evas_Object * | ||
278 | elm_panel_add(Evas_Object *parent) | ||
279 | { | ||
280 | Evas_Object *obj; | ||
281 | Evas *e; | ||
282 | Widget_Data *wd; | ||
283 | |||
284 | ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL); | ||
285 | |||
286 | ELM_SET_WIDTYPE(widtype, "panel"); | ||
287 | elm_widget_type_set(obj, "panel"); | ||
288 | elm_widget_sub_object_add(parent, obj); | ||
289 | elm_widget_data_set(obj, wd); | ||
290 | elm_widget_del_hook_set(obj, _del_hook); | ||
291 | elm_widget_theme_hook_set(obj, _theme_hook); | ||
292 | elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL); | ||
293 | elm_widget_signal_emit_hook_set(obj, _signal_emit_hook); | ||
294 | elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook); | ||
295 | elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook); | ||
296 | elm_widget_focus_next_hook_set(obj, _elm_panel_focus_next_hook); | ||
297 | elm_widget_can_focus_set(obj, EINA_TRUE); | ||
298 | elm_widget_event_hook_set(obj, _event_hook); | ||
299 | elm_widget_content_set_hook_set(obj, _content_set_hook); | ||
300 | elm_widget_content_get_hook_set(obj, _content_get_hook); | ||
301 | elm_widget_content_unset_hook_set(obj, _content_unset_hook); | ||
302 | |||
303 | wd->scr = elm_smart_scroller_add(e); | ||
304 | elm_smart_scroller_widget_set(wd->scr, obj); | ||
305 | _theme_hook(obj); | ||
306 | elm_smart_scroller_bounce_allow_set(wd->scr, EINA_FALSE, EINA_FALSE); | ||
307 | elm_widget_resize_object_set(obj, wd->scr); | ||
308 | elm_smart_scroller_policy_set(wd->scr, ELM_SMART_SCROLLER_POLICY_OFF, | ||
309 | ELM_SMART_SCROLLER_POLICY_OFF); | ||
310 | |||
311 | wd->hidden = EINA_FALSE; | ||
312 | wd->orient = ELM_PANEL_ORIENT_LEFT; | ||
313 | |||
314 | wd->bx = evas_object_box_add(e); | ||
315 | evas_object_size_hint_align_set(wd->bx, 0.5, 0.5); | ||
316 | evas_object_box_layout_set(wd->bx, _layout, wd, NULL); | ||
317 | elm_widget_sub_object_add(obj, wd->bx); | ||
318 | elm_smart_scroller_child_set(wd->scr, wd->bx); | ||
319 | evas_object_show(wd->bx); | ||
320 | |||
321 | edje_object_signal_callback_add(elm_smart_scroller_edje_object_get(wd->scr), | ||
322 | "elm,action,panel,toggle", "*", | ||
323 | _toggle_panel, obj); | ||
324 | |||
325 | evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_RESIZE, _resize, obj); | ||
326 | |||
327 | _mirrored_set(obj, elm_widget_mirrored_get(obj)); | ||
328 | _sizing_eval(obj); | ||
329 | return obj; | ||
330 | } | ||
331 | |||
332 | EAPI void | ||
333 | elm_panel_orient_set(Evas_Object *obj, Elm_Panel_Orient orient) | ||
334 | { | ||
335 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
336 | Widget_Data *wd = elm_widget_data_get(obj); | ||
337 | if (!wd) return; | ||
338 | wd->orient = orient; | ||
339 | switch (orient) | ||
340 | { | ||
341 | case ELM_PANEL_ORIENT_TOP: | ||
342 | elm_smart_scroller_object_theme_set(obj, wd->scr, "panel", "base", "top"); | ||
343 | break; | ||
344 | case ELM_PANEL_ORIENT_BOTTOM: | ||
345 | elm_smart_scroller_object_theme_set(obj, wd->scr, "panel", "base", "bottom"); | ||
346 | break; | ||
347 | case ELM_PANEL_ORIENT_LEFT: | ||
348 | if (!elm_widget_mirrored_get(obj)) | ||
349 | elm_smart_scroller_object_theme_set(obj, wd->scr, "panel", "base", "left"); | ||
350 | else | ||
351 | elm_smart_scroller_object_theme_set(obj, wd->scr, "panel", "base", "right"); | ||
352 | break; | ||
353 | case ELM_PANEL_ORIENT_RIGHT: | ||
354 | if (!elm_widget_mirrored_get(obj)) | ||
355 | elm_smart_scroller_object_theme_set(obj, wd->scr, "panel", "base", "right"); | ||
356 | else | ||
357 | elm_smart_scroller_object_theme_set(obj, wd->scr, "panel", "base", "left"); | ||
358 | break; | ||
359 | } | ||
360 | |||
361 | _sizing_eval(obj); | ||
362 | } | ||
363 | |||
364 | EAPI Elm_Panel_Orient | ||
365 | elm_panel_orient_get(const Evas_Object *obj) | ||
366 | { | ||
367 | ELM_CHECK_WIDTYPE(obj, widtype) ELM_PANEL_ORIENT_LEFT; | ||
368 | Widget_Data *wd = elm_widget_data_get(obj); | ||
369 | if (!wd) return ELM_PANEL_ORIENT_LEFT; | ||
370 | return wd->orient; | ||
371 | } | ||
372 | |||
373 | EAPI void | ||
374 | elm_panel_hidden_set(Evas_Object *obj, Eina_Bool hidden) | ||
375 | { | ||
376 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
377 | Widget_Data *wd = elm_widget_data_get(obj); | ||
378 | if (!wd) return; | ||
379 | if (wd->hidden == hidden) return; | ||
380 | _toggle_panel(obj, NULL, "elm,action,panel,toggle", "*"); | ||
381 | } | ||
382 | |||
383 | EAPI Eina_Bool | ||
384 | elm_panel_hidden_get(const Evas_Object *obj) | ||
385 | { | ||
386 | ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; | ||
387 | Widget_Data *wd = elm_widget_data_get(obj); | ||
388 | if (!wd) return EINA_FALSE; | ||
389 | return wd->hidden; | ||
390 | } | ||
391 | |||
392 | EAPI void | ||
393 | elm_panel_toggle(Evas_Object *obj) | ||
394 | { | ||
395 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
396 | Widget_Data *wd = elm_widget_data_get(obj); | ||
397 | if (!wd) return; | ||
398 | _toggle_panel(obj, NULL, "elm,action,panel,toggle", "*"); | ||
399 | } | ||