summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaeun Choi <jaeun12.choi@samsung.com>2014-07-07 15:08:45 +0900
committerJaeun Choi <jaeun12.choi@samsung.com>2014-07-07 15:08:45 +0900
commit25c01e026220f533080ceb459a567b772eb1cbcd (patch)
treed9d787285fb39437d923c100a5c879e63dbaefe6
parent2c142e6271025bc2a6b8cee953e29e094adf2507 (diff)
panel: add scrollable feature
This implements scrollable interface in elm_panel so that users can drag open/close panel. Tap & hold on the edge and panel handler will appear. Left scrollable panel is implemented in elementary_test > Panel Scrollable. @feature
-rw-r--r--data/themes/edc/elm/panel.edc381
-rw-r--r--src/bin/test.c2
-rw-r--r--src/bin/test_panel.c73
-rw-r--r--src/lib/elm_panel.c971
-rw-r--r--src/lib/elm_panel.eo29
-rw-r--r--src/lib/elm_panel.h3
-rw-r--r--src/lib/elm_panel_common.h6
-rw-r--r--src/lib/elm_widget_panel.h12
8 files changed, 1450 insertions, 27 deletions
diff --git a/data/themes/edc/elm/panel.edc b/data/themes/edc/elm/panel.edc
index 7dab212da..7a99dbb73 100644
--- a/data/themes/edc/elm/panel.edc
+++ b/data/themes/edc/elm/panel.edc
@@ -1,3 +1,384 @@
1group { name: "elm/scroller/panel/default";
2 data {
3 item: "handler_size" "30";
4 }
5 parts {
6 part { name: "elm.swallow.content";
7 type: SWALLOW;
8 description { state: "default" 0.0;
9 }
10 }
11 }
12}
13
14group { name: "elm/scroller/panel/left/default";
15 parts {
16 part { name: "panel_area";
17 type: SWALLOW;
18 description { state: "default" 0.0;
19 rel2.relative: 0.0 1.0;
20 align: 0.0 0.5;
21 fixed: 1 1;
22 visible: 0;
23 }
24 description { state: "visible" 0.0;
25 inherit: "default" 0.0;
26 visible: 1;
27 }
28 }
29 part { name: "event_area";
30 type: SWALLOW;
31 description { state: "default" 0.0;
32 rel1 {
33 relative: 1.0 0.0;
34 to: "panel_area";
35 }
36 rel2 {
37 relative: 1.0 1.0;
38 to: "panel_area";
39 }
40 align: 0.0 0.5;
41 fixed: 1 1;
42 visible: 0;
43 }
44 description { state: "visible" 0.0;
45 inherit: "default" 0.0;
46 visible: 1;
47 }
48 }
49 part { name: "access.outline";
50 type: RECT;
51 repeat_events: 1;
52 description { state: "default" 0.0;
53 rel1.to: "panel_area";
54 rel2.to: "panel_area";
55 color: 0 0 0 0;
56 }
57 }
58 part { name: "bg";
59 type: RECT;
60 description { state: "default" 0.0;
61 rel1.to: "panel_area";
62 rel2.to: "panel_area";
63 color: 64 64 64 255;
64 visible: 0;
65 }
66 description { state: "visible" 0.0;
67 inherit: "default" 0.0;
68 visible: 1;
69 }
70 }
71 part { name: "elm.swallow.content";
72 type: SWALLOW;
73 description { state: "default" 0.0;
74 rel1.to: "panel_area";
75 rel2.to: "panel_area";
76 visible: 0;
77 }
78 description { state: "visible" 0.0;
79 inherit: "default" 0.0;
80 visible: 1;
81 }
82 }
83 }
84 programs {
85 program { name: "active";
86 signal: "elm,state,content,visible";
87 source: "elm";
88 action: STATE_SET "visible" 0.0;
89 target: "panel_area";
90 target: "event_area";
91 target: "bg";
92 target: "elm.swallow.content";
93 }
94 program { name: "inactive";
95 signal: "elm,state,content,hidden";
96 source: "elm";
97 action: STATE_SET "default" 0.0;
98 target: "panel_area";
99 target: "event_area";
100 target: "bg";
101 target: "elm.swallow.content";
102 }
103 }
104}
105
106group { name: "elm/scroller/panel/right/default";
107 parts {
108 part { name: "event_area";
109 type: SWALLOW;
110 description { state: "default" 0.0;
111 rel2.relative: 0.0 1.0;
112 align: 0.0 0.5;
113 fixed: 1 1;
114 visible: 0;
115 }
116 description { state: "visible" 0.0;
117 inherit: "default" 0.0;
118 visible: 1;
119 }
120 }
121 part { name: "panel_area";
122 type: SWALLOW;
123 description { state: "default" 0.0;
124 rel1 {
125 relative: 1.0 0.0;
126 to: "event_area";
127 }
128 rel2 {
129 relative: 1.0 1.0;
130 to: "event_area";
131 }
132 align: 0.0 0.5;
133 fixed: 1 1;
134 visible: 0;
135 }
136 description { state: "visible" 0.0;
137 inherit: "default" 0.0;
138 visible: 1;
139 }
140 }
141 part { name: "access.outline";
142 type: RECT;
143 repeat_events: 1;
144 description { state: "default" 0.0;
145 rel1.to: "panel_area";
146 rel2.to: "panel_area";
147 color: 0 0 0 0;
148 }
149 }
150 part { name: "bg";
151 type: RECT;
152 description { state: "default" 0.0;
153 rel1.to: "panel_area";
154 rel2.to: "panel_area";
155 color: 64 64 64 255;
156 visible: 0;
157 }
158 description { state: "visible" 0.0;
159 inherit: "default" 0.0;
160 visible: 1;
161 }
162 }
163 part { name: "elm.swallow.content";
164 type: SWALLOW;
165 description { state: "default" 0.0;
166 rel1.to: "panel_area";
167 rel2.to: "panel_area";
168 visible: 0;
169 }
170 description { state: "visible" 0.0;
171 inherit: "default" 0.0;
172 visible: 1;
173 }
174 }
175 }
176 programs {
177 program { name: "active";
178 signal: "elm,state,content,visible";
179 source: "elm";
180 action: STATE_SET "visible" 0.0;
181 target: "panel_area";
182 target: "event_area";
183 target: "bg";
184 target: "elm.swallow.content";
185 }
186 program { name: "inactive";
187 signal: "elm,state,content,hidden";
188 source: "elm";
189 action: STATE_SET "default" 0.0;
190 target: "panel_area";
191 target: "event_area";
192 target: "bg";
193 target: "elm.swallow.content";
194 }
195 }
196}
197
198group { name: "elm/scroller/panel/top/default";
199 parts {
200 part { name: "panel_area";
201 type: SWALLOW;
202 description { state: "default" 0.0;
203 rel2.relative: 1.0 0.0;
204 align: 0.5 0.0;
205 fixed: 1 1;
206 visible: 0;
207 }
208 description { state: "visible" 0.0;
209 inherit: "default" 0.0;
210 visible: 1;
211 }
212 }
213 part { name: "event_area";
214 type: SWALLOW;
215 description { state: "default" 0.0;
216 rel1 {
217 relative: 0.0 1.0;
218 to: "panel_area";
219 }
220 rel2 {
221 relative: 1.0 1.0;
222 to: "panel_area";
223 }
224 align: 0.5 0.0;
225 fixed: 1 1;
226 visible: 0;
227 }
228 description { state: "visible" 0.0;
229 inherit: "default" 0.0;
230 visible: 1;
231 }
232 }
233 part { name: "access.outline";
234 type: RECT;
235 repeat_events: 1;
236 description { state: "default" 0.0;
237 rel1.to: "panel_area";
238 rel2.to: "panel_area";
239 color: 0 0 0 0;
240 }
241 }
242 part { name: "bg";
243 type: RECT;
244 description { state: "default" 0.0;
245 rel1.to: "panel_area";
246 rel2.to: "panel_area";
247 color: 64 64 64 255;
248 visible: 0;
249 }
250 description { state: "visible" 0.0;
251 inherit: "default" 0.0;
252 visible: 1;
253 }
254 }
255 part { name: "elm.swallow.content";
256 type: SWALLOW;
257 description { state: "default" 0.0;
258 rel1.to: "panel_area";
259 rel2.to: "panel_area";
260 visible: 0;
261 }
262 description { state: "visible" 0.0;
263 inherit: "default" 0.0;
264 visible: 1;
265 }
266 }
267 }
268 programs {
269 program { name: "active";
270 signal: "elm,state,content,visible";
271 source: "elm";
272 action: STATE_SET "visible" 0.0;
273 target: "panel_area";
274 target: "event_area";
275 target: "bg";
276 target: "elm.swallow.content";
277 }
278 program { name: "inactive";
279 signal: "elm,state,content,hidden";
280 source: "elm";
281 action: STATE_SET "default" 0.0;
282 target: "panel_area";
283 target: "event_area";
284 target: "bg";
285 target: "elm.swallow.content";
286 }
287 }
288}
289
290group { name: "elm/scroller/panel/bottom/default";
291 parts {
292 part { name: "event_area";
293 type: SWALLOW;
294 description { state: "default" 0.0;
295 rel2.relative: 1.0 0.0;
296 align: 0.5 0.0;
297 fixed: 1 1;
298 visible: 0;
299 }
300 description { state: "visible" 0.0;
301 inherit: "default" 0.0;
302 visible: 1;
303 }
304 }
305 part { name: "panel_area";
306 type: SWALLOW;
307 description { state: "default" 0.0;
308 rel1 {
309 relative: 0.0 1.0;
310 to: "event_area";
311 }
312 rel2 {
313 relative: 1.0 1.0;
314 to: "event_area";
315 }
316 align: 0.5 0.0;
317 fixed: 1 1;
318 visible: 0;
319 }
320 description { state: "visible" 0.0;
321 inherit: "default" 0.0;
322 visible: 1;
323 }
324 }
325 part { name: "access.outline";
326 type: RECT;
327 repeat_events: 1;
328 description { state: "default" 0.0;
329 rel1.to: "panel_area";
330 rel2.to: "panel_area";
331 color: 0 0 0 0;
332 }
333 }
334 part { name: "bg";
335 type: RECT;
336 description { state: "default" 0.0;
337 rel1.to: "panel_area";
338 rel2.to: "panel_area";
339 color: 64 64 64 255;
340 visible: 0;
341 }
342 description { state: "visible" 0.0;
343 inherit: "default" 0.0;
344 visible: 1;
345 }
346 }
347 part { name: "elm.swallow.content";
348 type: SWALLOW;
349 description { state: "default" 0.0;
350 rel1.to: "panel_area";
351 rel2.to: "panel_area";
352 visible: 0;
353 }
354 description { state: "visible" 0.0;
355 inherit: "default" 0.0;
356 visible: 1;
357 }
358 }
359 }
360 programs {
361 program { name: "active";
362 signal: "elm,state,content,visible";
363 source: "elm";
364 action: STATE_SET "visible" 0.0;
365 target: "panel_area";
366 target: "event_area";
367 target: "bg";
368 target: "elm.swallow.content";
369 }
370 program { name: "inactive";
371 signal: "elm,state,content,hidden";
372 source: "elm";
373 action: STATE_SET "default" 0.0;
374 target: "panel_area";
375 target: "event_area";
376 target: "bg";
377 target: "elm.swallow.content";
378 }
379 }
380}
381
1group { name: "elm/panel/left/default"; 382group { name: "elm/panel/left/default";
2 images.image: "bevel_out.png" COMP; 383 images.image: "bevel_out.png" COMP;
3 images.image: "shine.png" COMP; 384 images.image: "shine.png" COMP;
diff --git a/src/bin/test.c b/src/bin/test.c
index ada5c2516..ae3976c19 100644
--- a/src/bin/test.c
+++ b/src/bin/test.c
@@ -158,6 +158,7 @@ void test_slideshow(void *data, Evas_Object *obj, void *event_info);
158void test_menu(void *data, Evas_Object *obj, void *event_info); 158void test_menu(void *data, Evas_Object *obj, void *event_info);
159void test_menu2(void *data, Evas_Object *obj, void *event_info); 159void test_menu2(void *data, Evas_Object *obj, void *event_info);
160void test_panel(void *data, Evas_Object *obj, void *event_info); 160void test_panel(void *data, Evas_Object *obj, void *event_info);
161void test_panel2(void *data, Evas_Object *obj, void *event_info);
161void test_panes(void *data, Evas_Object *obj, void *event_info); 162void test_panes(void *data, Evas_Object *obj, void *event_info);
162void test_calendar(void *data, Evas_Object *obj, void *event_info); 163void test_calendar(void *data, Evas_Object *obj, void *event_info);
163void test_calendar2(void *data, Evas_Object *obj, void *event_info); 164void test_calendar2(void *data, Evas_Object *obj, void *event_info);
@@ -785,6 +786,7 @@ add_tests:
785 786
786 //------------------------------// 787 //------------------------------//
787 ADD_TEST(NULL, "Dividers", "Panel", test_panel); 788 ADD_TEST(NULL, "Dividers", "Panel", test_panel);
789 ADD_TEST(NULL, "Dividers", "Panel Scrollable", test_panel2);
788 ADD_TEST(NULL, "Dividers", "Panes", test_panes); 790 ADD_TEST(NULL, "Dividers", "Panes", test_panes);
789 791
790 //------------------------------// 792 //------------------------------//
diff --git a/src/bin/test_panel.c b/src/bin/test_panel.c
index d0b7f6b3f..7743174ce 100644
--- a/src/bin/test_panel.c
+++ b/src/bin/test_panel.c
@@ -270,3 +270,76 @@ test_panel(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_inf
270 evas_object_resize(win, 320, 400); 270 evas_object_resize(win, 320, 400);
271 evas_object_show(win); 271 evas_object_show(win);
272} 272}
273
274static void
275_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
276{
277 Evas_Object *panel = data;
278 elm_panel_toggle(panel);
279}
280
281void
282test_panel2(void *data EINA_UNUSED,
283 Evas_Object *obj EINA_UNUSED,
284 void *event_info EINA_UNUSED)
285{
286 Evas_Object *win, *box, *table, *panel, *list, *button;
287 int i;
288
289 // Left Panel
290 win = elm_win_util_standard_add("panel", "Left Panel");
291 elm_win_autodel_set(win, EINA_TRUE);
292 evas_object_resize(win, 320, 400);
293 evas_object_show(win);
294
295 // box for button and table
296 box = elm_box_add(win);
297 evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
298 evas_object_show(box);
299 elm_win_resize_object_add(win, box);
300
301 // toggle button
302 button = elm_button_add(box);
303 evas_object_size_hint_weight_set(button, EVAS_HINT_EXPAND, 0);
304 evas_object_size_hint_align_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL);
305 evas_object_show(button);
306 elm_object_text_set(button, "Toggle");
307 elm_box_pack_end(box, button);
308
309 // table for panel and center content
310 table = elm_table_add(win);
311 evas_object_size_hint_weight_set(table, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
312 evas_object_size_hint_align_set(table, EVAS_HINT_FILL, EVAS_HINT_FILL);
313 evas_object_show(table);
314 elm_box_pack_end(box, table);
315
316 // center content
317 list = elm_list_add(table);
318 evas_object_size_hint_weight_set(list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
319 evas_object_size_hint_align_set(list, EVAS_HINT_FILL, EVAS_HINT_FILL);
320 evas_object_show(list);
321 for (i = 0; i < 20; i++)
322 elm_list_item_append(list, "center list item", NULL, NULL, NULL, NULL);
323 elm_table_pack(table, list, 0, 0, 1, 1);
324
325 // panel
326 panel = elm_panel_add(table);
327 evas_object_size_hint_weight_set(panel, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
328 evas_object_size_hint_align_set(panel, EVAS_HINT_FILL, EVAS_HINT_FILL);
329 evas_object_show(panel);
330 elm_table_pack(table, panel, 0, 0, 1, 1);
331
332 elm_panel_scrollable_set(panel, EINA_TRUE);
333 elm_panel_orient_set(panel, ELM_PANEL_ORIENT_LEFT);
334 elm_panel_hidden_set(panel, EINA_TRUE);
335 elm_panel_scrollable_content_size_set(panel, 0.75);
336
337 list = elm_list_add(panel);
338 evas_object_size_hint_weight_set(list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
339 evas_object_size_hint_align_set(list, EVAS_HINT_FILL, EVAS_HINT_FILL);
340 for (i = 0; i < 7; i++)
341 elm_list_item_append(list, "panel list item", NULL, NULL, NULL, NULL);
342 elm_object_content_set(panel, list);
343
344 evas_object_smart_callback_add(button, "clicked", _clicked_cb, panel);
345}
diff --git a/src/lib/elm_panel.c b/src/lib/elm_panel.c
index 6da13f975..c3245a28d 100644
--- a/src/lib/elm_panel.c
+++ b/src/lib/elm_panel.c
@@ -18,7 +18,12 @@
18#define MY_CLASS_NAME "Elm_Panel" 18#define MY_CLASS_NAME "Elm_Panel"
19#define MY_CLASS_NAME_LEGACY "elm_panel" 19#define MY_CLASS_NAME_LEGACY "elm_panel"
20 20
21static const char ACCESS_OUTLINE_PART[] = "access.outline";
22
23static const char SIG_SCROLL[] = "scroll";
24
21static const Evas_Smart_Cb_Description _smart_callbacks[] = { 25static const Evas_Smart_Cb_Description _smart_callbacks[] = {
26 {SIG_SCROLL, ""},
22 {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */ 27 {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */
23 {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */ 28 {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */
24 {NULL, NULL} 29 {NULL, NULL}
@@ -68,6 +73,55 @@ _access_state_cb(void *data, Evas_Object *obj EINA_UNUSED)
68 return NULL; 73 return NULL;
69} 74}
70 75
76static Evas_Object *
77_access_object_get(const Evas_Object *obj, const char *part)
78{
79 Evas_Object *po, *ao;
80 ELM_PANEL_DATA_GET(obj, sd);
81
82 po = (Evas_Object *)edje_object_part_object_get
83 (elm_layout_edje_get(sd->scr_ly), part);
84 ao = evas_object_data_get(po, "_part_access_obj");
85
86 return ao;
87}
88
89static void
90_access_activate_cb(void *data,
91 Evas_Object *part_obj EINA_UNUSED,
92 Elm_Object_Item *item EINA_UNUSED)
93{
94 elm_panel_hidden_set(data, EINA_TRUE);
95}
96
97static void
98_access_obj_process(Evas_Object *obj, Eina_Bool is_access)
99{
100 Evas_Object *ao;
101 ELM_PANEL_DATA_GET(obj, sd);
102
103 if (is_access)
104 {
105 ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
106 if (!ao)
107 {
108 ao = _elm_access_edje_object_part_object_register
109 (obj, elm_layout_edje_get(sd->scr_ly), ACCESS_OUTLINE_PART);
110 _elm_access_text_set(_elm_access_info_get(ao),
111 ELM_ACCESS_TYPE, E_("A drawer is open"));
112 _elm_access_text_set(_elm_access_info_get(ao),
113 ELM_ACCESS_CONTEXT_INFO, E_("Double tap to close drawer menu"));
114 _elm_access_activate_callback_set
115 (_elm_access_info_get(ao), _access_activate_cb, obj);
116 }
117 }
118 else
119 {
120 _elm_access_edje_object_part_object_unregister
121 (obj, elm_layout_edje_get(sd->scr_ly), ACCESS_OUTLINE_PART);
122 }
123}
124
71static void 125static void
72_orient_set_do(Evas_Object *obj) 126_orient_set_do(Evas_Object *obj)
73{ 127{
@@ -132,6 +186,38 @@ _orient_set_do(Evas_Object *obj)
132 } 186 }
133} 187}
134 188
189static void
190_scrollable_layout_theme_set(Eo *obj, Elm_Panel_Data *sd)
191{
192 switch (sd->orient)
193 {
194 case ELM_PANEL_ORIENT_TOP:
195 if (!elm_layout_theme_set(sd->scr_ly, "scroller", "panel/top",
196 elm_widget_style_get(obj)))
197 CRI("Failed to set layout!");
198 break;
199 case ELM_PANEL_ORIENT_BOTTOM:
200 if (!elm_layout_theme_set(sd->scr_ly, "scroller", "panel/bottom",
201 elm_widget_style_get(obj)))
202 CRI("Failed to set layout!");
203 break;
204 case ELM_PANEL_ORIENT_LEFT:
205 if (!elm_layout_theme_set(sd->scr_ly, "scroller", "panel/left",
206 elm_widget_style_get(obj)))
207 CRI("Failed to set layout!");
208 break;
209 case ELM_PANEL_ORIENT_RIGHT:
210 if (!elm_layout_theme_set(sd->scr_ly, "scroller", "panel/right",
211 elm_widget_style_get(obj)))
212 CRI("Failed to set layout!");
213 break;
214 }
215
216 /* access */
217 if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
218 _access_obj_process(obj, EINA_TRUE);
219}
220
135EOLIAN static Eina_Bool 221EOLIAN static Eina_Bool
136_elm_panel_elm_widget_theme_apply(Eo *obj, Elm_Panel_Data *sd) 222_elm_panel_elm_widget_theme_apply(Eo *obj, Elm_Panel_Data *sd)
137{ 223{
@@ -147,22 +233,36 @@ _elm_panel_elm_widget_theme_apply(Eo *obj, Elm_Panel_Data *sd)
147 233
148 _mirrored_set(obj, elm_widget_mirrored_get(obj)); 234 _mirrored_set(obj, elm_widget_mirrored_get(obj));
149 235
150 str = edje_object_data_get 236 if (sd->scrollable)
151 (wd->resize_obj, "focus_highlight"); 237 {
152 if ((str) && (!strcmp(str, "on"))) 238 const char *handler_size;
153 elm_widget_highlight_in_theme_set(obj, EINA_TRUE); 239 elm_widget_theme_object_set(obj, sd->scr_edje, "scroller", "panel",
240 elm_widget_style_get(obj));
241 _scrollable_layout_theme_set(obj, sd);
242
243 handler_size = edje_object_data_get(sd->scr_edje, "handler_size");
244 if (handler_size)
245 sd->handler_size = (int) (elm_object_scale_get(obj)) * (atoi(handler_size));
246 }
154 else 247 else
155 elm_widget_highlight_in_theme_set(obj, EINA_FALSE); 248 {
249 str = edje_object_data_get
250 (wd->resize_obj, "focus_highlight");
251 if ((str) && (!strcmp(str, "on")))
252 elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
253 else
254 elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
156 255
157 _orient_set_do(obj); 256 _orient_set_do(obj);
158 257
159 evas_object_hide(sd->event); 258 evas_object_hide(sd->event);
160 elm_coords_finger_size_adjust(1, &minw, 1, &minh); 259 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
161 evas_object_size_hint_min_set(sd->event, minw, minh); 260 evas_object_size_hint_min_set(sd->event, minw, minh);
162 261
163 if (edje_object_part_exists 262 if (edje_object_part_exists
164 (wd->resize_obj, "elm.swallow.event")) 263 (wd->resize_obj, "elm.swallow.event"))
165 elm_layout_content_set(obj, "elm.swallow.event", sd->event); 264 elm_layout_content_set(obj, "elm.swallow.event", sd->event);
265 }
166 266
167 elm_layout_sizing_eval(obj); 267 elm_layout_sizing_eval(obj);
168 268
@@ -179,11 +279,33 @@ EOLIAN static Eina_Bool
179_elm_panel_elm_widget_focus_next(Eo *obj, Elm_Panel_Data *sd, Elm_Focus_Direction dir, Evas_Object **next) 279_elm_panel_elm_widget_focus_next(Eo *obj, Elm_Panel_Data *sd, Elm_Focus_Direction dir, Evas_Object **next)
180{ 280{
181 Evas_Object *cur; 281 Evas_Object *cur;
282 Eina_List *items = NULL;
283 Eina_Bool ret = EINA_FALSE;
182 284
183 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE); 285 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
184 286
185 if (!sd->content) return EINA_FALSE; 287 if (!sd->content) return EINA_FALSE;
186 288
289 if (sd->scrollable)
290 {
291 if (sd->hidden) return EINA_FALSE;
292
293 if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
294 {
295 Evas_Object *ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
296 if (ao) items = eina_list_append(items, ao);
297 items = eina_list_append(items, sd->content);
298
299 ret = elm_widget_focus_list_next_get
300 (obj, items, eina_list_data_get, dir, next);
301 eina_list_free(items);
302
303 return ret;
304 }
305
306 return elm_widget_focus_next_get(sd->content, dir, next);
307 }
308
187 cur = sd->content; 309 cur = sd->content;
188 310
189 /* Try to Focus cycle in subitem */ 311 /* Try to Focus cycle in subitem */
@@ -213,6 +335,124 @@ _box_layout_cb(Evas_Object *o,
213} 335}
214 336
215static void 337static void
338_handler_open(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
339{
340 ELM_PANEL_DATA_GET(obj, sd);
341
342 if (sd->handler_size == 0) return;
343
344 switch (sd->orient)
345 {
346 case ELM_PANEL_ORIENT_TOP:
347 eo_do(obj, elm_interface_scrollable_region_bring_in
348 (0, (h * sd->content_size_ratio) - sd->handler_size, w, h));
349 break;
350 case ELM_PANEL_ORIENT_BOTTOM:
351 eo_do(obj, elm_interface_scrollable_region_bring_in
352 (0, sd->handler_size, w, h));
353 break;
354 case ELM_PANEL_ORIENT_LEFT:
355 eo_do(obj, elm_interface_scrollable_region_bring_in
356 ((w * sd->content_size_ratio) - sd->handler_size, 0, w, h));
357 break;
358 case ELM_PANEL_ORIENT_RIGHT:
359 eo_do(obj, elm_interface_scrollable_region_bring_in
360 (sd->handler_size, 0, w, h));
361 break;
362 }
363}
364
365static void
366_drawer_open(Evas_Object *obj, Evas_Coord w, Evas_Coord h, Eina_Bool anim)
367{
368 ELM_PANEL_DATA_GET(obj, sd);
369 int x = 0, y = 0;
370
371 if (sd->freeze)
372 {
373 eo_do(obj, elm_interface_scrollable_movement_block_set
374 (ELM_SCROLLER_MOVEMENT_NO_BLOCK));
375 sd->freeze = EINA_FALSE;
376 elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
377 }
378
379 switch (sd->orient)
380 {
381 case ELM_PANEL_ORIENT_TOP:
382 case ELM_PANEL_ORIENT_LEFT:
383 break;
384
385 case ELM_PANEL_ORIENT_BOTTOM:
386 y = h * sd->content_size_ratio;
387 break;
388
389 case ELM_PANEL_ORIENT_RIGHT:
390 x = w * sd->content_size_ratio;
391 break;
392 }
393
394 if (anim)
395 eo_do(obj, elm_interface_scrollable_region_bring_in
396 (x, y, w, h));
397 else
398 eo_do(obj, elm_interface_scrollable_content_region_show
399 (x, y, w, h));
400}
401
402static void
403_drawer_close(Evas_Object *obj, Evas_Coord w, Evas_Coord h, Eina_Bool anim)
404{
405 ELM_PANEL_DATA_GET(obj, sd);
406 int x = 0, y = 0;
407 Eina_Bool horizontal = EINA_FALSE;
408
409 switch (sd->orient)
410 {
411 case ELM_PANEL_ORIENT_TOP:
412 y = h * sd->content_size_ratio;
413 break;
414
415 case ELM_PANEL_ORIENT_LEFT:
416 x = w * sd->content_size_ratio;
417 horizontal = EINA_TRUE;
418 break;
419
420 case ELM_PANEL_ORIENT_BOTTOM:
421 break;
422 case ELM_PANEL_ORIENT_RIGHT:
423 horizontal = EINA_TRUE;
424 break;
425 }
426
427 if (anim)
428 {
429 if (sd->freeze)
430 {
431 eo_do(obj, elm_interface_scrollable_movement_block_set
432 (ELM_SCROLLER_MOVEMENT_NO_BLOCK));
433 sd->freeze = EINA_FALSE;
434 elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
435 }
436 eo_do(obj, elm_interface_scrollable_region_bring_in(x, y, w, h));
437 }
438 else
439 {
440 eo_do(obj, elm_interface_scrollable_content_region_show(x, y, w, h));
441 if (!sd->freeze)
442 {
443 if (horizontal)
444 eo_do(obj, elm_interface_scrollable_movement_block_set
445 (ELM_SCROLLER_MOVEMENT_BLOCK_HORIZONTAL));
446 else
447 eo_do(obj, elm_interface_scrollable_movement_block_set
448 (ELM_SCROLLER_MOVEMENT_BLOCK_VERTICAL));
449 sd->freeze = EINA_TRUE;
450 elm_layout_signal_emit(sd->scr_ly, "elm,state,content,hidden", "elm");
451 }
452 }
453}
454
455static void
216_panel_toggle(void *data EINA_UNUSED, 456_panel_toggle(void *data EINA_UNUSED,
217 Evas_Object *obj, 457 Evas_Object *obj,
218 const char *emission EINA_UNUSED, 458 const char *emission EINA_UNUSED,
@@ -220,26 +460,382 @@ _panel_toggle(void *data EINA_UNUSED,
220{ 460{
221 ELM_PANEL_DATA_GET(obj, sd); 461 ELM_PANEL_DATA_GET(obj, sd);
222 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); 462 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
463 int w, h;
464
465 if (sd->scrollable)
466 {
467 if (elm_widget_disabled_get(obj)) return;
468
469 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
470 if (sd->hidden)
471 {
472 sd->hidden = EINA_FALSE;
473 _drawer_open(obj, w, h, EINA_TRUE);
474 }
475 else
476 {
477 sd->hidden = EINA_TRUE;
478 _drawer_close(obj, w, h, EINA_TRUE);
479 }
480 }
481 else
482 {
483 if (sd->hidden)
484 {
485 elm_layout_signal_emit(obj, "elm,action,show", "elm");
486 sd->hidden = EINA_FALSE;
487 evas_object_repeat_events_set(obj, EINA_FALSE);
488 }
489 else
490 {
491 elm_layout_signal_emit(obj, "elm,action,hide", "elm");
492 sd->hidden = EINA_TRUE;
493 evas_object_repeat_events_set(obj, EINA_TRUE);
494 if (sd->content && elm_widget_focus_get(sd->content))
495 {
496 elm_widget_focused_object_clear(obj);
497 elm_widget_focus_steal(obj);
498 }
499 }
500
501 edje_object_message_signal_process(wd->resize_obj);
502 }
503}
223 504
224 if (sd->hidden) 505static Eina_Bool
506_state_sync(Evas_Object *obj)
507{
508 ELM_PANEL_DATA_GET(obj, sd);
509 Evas_Object *ao;
510 Evas_Coord pos, panel_size, w, h;
511 Eina_Bool open = EINA_FALSE, horizontal = EINA_FALSE;
512 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
513
514 switch (sd->orient)
225 { 515 {
226 elm_layout_signal_emit(obj, "elm,action,show", "elm"); 516 case ELM_PANEL_ORIENT_TOP:
227 sd->hidden = EINA_FALSE; 517 panel_size = h * sd->content_size_ratio;
228 evas_object_repeat_events_set(obj, EINA_FALSE); 518 eo_do(obj, elm_interface_scrollable_content_pos_get(NULL, &pos));
519
520 if (pos == 0) open = EINA_TRUE;
521 else if (pos == panel_size) open = EINA_FALSE;
522 else return EINA_FALSE;
523 break;
524
525 case ELM_PANEL_ORIENT_BOTTOM:
526 panel_size = h * sd->content_size_ratio;
527 eo_do(obj, elm_interface_scrollable_content_pos_get(NULL, &pos));
528
529 if (pos == panel_size) open = EINA_TRUE;
530 else if (pos == 0) open = EINA_FALSE;
531 else return EINA_FALSE;
532 break;
533
534 case ELM_PANEL_ORIENT_LEFT:
535 panel_size = w * sd->content_size_ratio;
536 eo_do(obj, elm_interface_scrollable_content_pos_get(&pos, NULL));
537 horizontal = EINA_TRUE;
538
539 if (pos == 0) open = EINA_TRUE;
540 else if (pos == panel_size) open = EINA_FALSE;
541 else return EINA_FALSE;
542 break;
543
544 case ELM_PANEL_ORIENT_RIGHT:
545 panel_size = w * sd->content_size_ratio;
546 eo_do(obj, elm_interface_scrollable_content_pos_get(&pos, NULL));
547 horizontal = EINA_TRUE;
548
549 if (pos == panel_size) open = EINA_TRUE;
550 else if (pos == 0) open = EINA_FALSE;
551 else return EINA_FALSE;
552 break;
553 }
554
555 if (open)
556 {
557 if (sd->hidden) sd->hidden = EINA_FALSE;
558 eo_do(obj, elm_interface_scrollable_single_direction_set
559 (ELM_SCROLLER_SINGLE_DIRECTION_HARD));
560
561 //focus & access
562 elm_object_tree_focus_allow_set(obj, EINA_TRUE);
563 if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
564 {
565 ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
566 evas_object_show(ao);
567 _elm_access_highlight_set(ao);
568 }
569 else
570 elm_object_focus_set(obj, EINA_TRUE);
229 } 571 }
230 else 572 else
231 { 573 {
232 elm_layout_signal_emit(obj, "elm,action,hide", "elm"); 574 if (!sd->hidden) sd->hidden = EINA_TRUE;
233 sd->hidden = EINA_TRUE; 575
234 evas_object_repeat_events_set(obj, EINA_TRUE); 576 if (horizontal)
235 if (sd->content && elm_widget_focus_get(sd->content)) 577 eo_do(obj, elm_interface_scrollable_movement_block_set
578 (ELM_SCROLLER_MOVEMENT_BLOCK_HORIZONTAL));
579 else
580 eo_do(obj, elm_interface_scrollable_movement_block_set
581 (ELM_SCROLLER_MOVEMENT_BLOCK_VERTICAL));
582 sd->freeze = EINA_TRUE;
583 elm_layout_signal_emit(sd->scr_ly, "elm,state,content,hidden", "elm");
584
585 eo_do(obj, elm_interface_scrollable_single_direction_set
586 (ELM_SCROLLER_SINGLE_DIRECTION_NONE));
587
588 //focus & access
589 elm_object_tree_focus_allow_set(obj, EINA_FALSE);
590 if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
236 { 591 {
237 elm_widget_focused_object_clear(obj); 592 ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
238 elm_widget_focus_steal(obj); 593 evas_object_hide(ao);
239 } 594 }
240 } 595 }
241 596
242 edje_object_message_signal_process(wd->resize_obj); 597 return EINA_TRUE;
598}
599
600static Eina_Bool
601_timer_cb(void *data)
602{
603 ELM_PANEL_DATA_GET(data, sd);
604 Evas_Object *obj = data;
605 Evas_Coord w, h;
606
607 sd->timer = NULL;
608
609 if (sd->freeze)
610 {
611 eo_do(obj, elm_interface_scrollable_movement_block_set
612 (ELM_SCROLLER_MOVEMENT_NO_BLOCK));
613 sd->freeze = EINA_FALSE;
614 elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
615 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
616 _handler_open(obj, w, h);
617 }
618
619 return ECORE_CALLBACK_CANCEL;
620}
621
622static void
623_event_mouse_up(void *data,
624 Evas *e EINA_UNUSED,
625 Evas_Object *obj EINA_UNUSED,
626 void *event_info)
627{
628 ELM_PANEL_DATA_GET(data, sd);
629 Evas_Event_Mouse_Up *ev = event_info;
630 Evas_Coord x, y, up_x, up_y, minw = 0, minh = 0;
631 evas_object_geometry_get(data, &x, &y, NULL, NULL);
632
633 up_x = ev->output.x - x;
634 up_y = ev->output.y - y;
635
636 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
637
638 if ((!sd->hidden) && (up_x == sd->down_x) && (up_y == sd->down_y))
639 elm_panel_hidden_set(data, EINA_TRUE);
640}
641
642static void
643_on_mouse_down(void *data,
644 Evas *e EINA_UNUSED,
645 Evas_Object *obj,
646 void *event_info)
647{
648 Elm_Panel_Data *sd = data;
649 Evas_Event_Mouse_Down *ev = event_info;
650 Evas_Coord finger_size = elm_config_finger_size_get();
651 Evas_Coord x, y, w, h;
652 evas_object_geometry_get(obj, &x, &y, &w, &h);
653
654 sd->down_x = ev->output.x - x;
655 sd->down_y = ev->output.y - y;
656
657 // if freeze state & mouse down on the edge
658 // then set timer for un-freeze
659 switch (sd->orient)
660 {
661 case ELM_PANEL_ORIENT_TOP:
662 if ((sd->freeze) && (sd->down_y >= 0) && (sd->down_y < finger_size))
663 {
664 ecore_timer_del(sd->timer);
665 sd->timer = ecore_timer_add(0.2, _timer_cb, obj);
666 }
667 break;
668 case ELM_PANEL_ORIENT_BOTTOM:
669 if ((sd->freeze) && (sd->down_y <= h) && (sd->down_y > (h - finger_size)))
670 {
671 ecore_timer_del(sd->timer);
672 sd->timer = ecore_timer_add(0.2, _timer_cb, obj);
673 }
674 break;
675 case ELM_PANEL_ORIENT_LEFT:
676 if ((sd->freeze) && (sd->down_x >= 0) && (sd->down_x < finger_size))
677 {
678 ecore_timer_del(sd->timer);
679 sd->timer = ecore_timer_add(0.2, _timer_cb, obj);
680 }
681 break;
682 case ELM_PANEL_ORIENT_RIGHT:
683 if ((sd->freeze) && (sd->down_x <= w) && (sd->down_x > (w - finger_size)))
684 {
685 ecore_timer_del(sd->timer);
686 sd->timer = ecore_timer_add(0.2, _timer_cb, obj);
687 }
688 break;
689 }
690}
691
692static void
693_on_mouse_move(void *data,
694 Evas *e EINA_UNUSED,
695 Evas_Object *obj,
696 void *event_info)
697{
698 Elm_Panel_Data *sd = data;
699 Evas_Event_Mouse_Move *ev = event_info;
700 Evas_Coord x, y, w, h, cur_x, cur_y, finger_size;
701 evas_object_geometry_get(obj, &x, &y, &w, &h);
702 finger_size = elm_config_finger_size_get();
703
704 cur_x = ev->cur.canvas.x - x;
705 cur_y = ev->cur.canvas.y - y;
706
707 // if mouse down on the edge (it means sd->timer is not null)
708 // and move more than finger size
709 // then un-freeze
710 switch (sd->orient)
711 {
712 case ELM_PANEL_ORIENT_TOP:
713 if (sd->timer && ((cur_y - sd->down_y) > finger_size))
714 {
715 eo_do(obj, elm_interface_scrollable_freeze_set(EINA_FALSE));
716 sd->freeze = EINA_FALSE;
717 elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
718 }
719 break;
720 case ELM_PANEL_ORIENT_BOTTOM:
721 if (sd->timer && ((sd->down_y - cur_y) > finger_size))
722 {
723 eo_do(obj, elm_interface_scrollable_freeze_set(EINA_FALSE));
724 sd->freeze = EINA_FALSE;
725 elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
726 }
727 break;
728 case ELM_PANEL_ORIENT_LEFT:
729 if (sd->timer && ((cur_x - sd->down_x) > finger_size))
730 {
731 eo_do(obj, elm_interface_scrollable_freeze_set(EINA_FALSE));
732 sd->freeze = EINA_FALSE;
733 elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
734 }
735 break;
736 case ELM_PANEL_ORIENT_RIGHT:
737 if (sd->timer && ((sd->down_x - cur_x) > finger_size))
738 {
739 eo_do(obj, elm_interface_scrollable_freeze_set(EINA_FALSE));
740 sd->freeze = EINA_FALSE;
741 elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
742 }
743 break;
744 }
745
746 if (!sd->freeze && sd->hidden)
747 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
748}
749
750static void
751_on_mouse_up(void *data,
752 Evas *e EINA_UNUSED,
753 Evas_Object *obj,
754 void *event_info)
755{
756 Elm_Panel_Data *sd = data;
757 Evas_Event_Mouse_Up *ev = event_info;
758 Evas_Coord panel_size, threshold, pos, w, h;
759
760 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
761
762 ELM_SAFE_FREE(sd->timer, ecore_timer_del);
763
764 if (_state_sync(obj)) return;
765
766 switch (sd->orient)
767 {
768 case ELM_PANEL_ORIENT_TOP:
769 panel_size = h * sd->content_size_ratio;
770 threshold = panel_size / 4;
771 eo_do(obj, elm_interface_scrollable_content_pos_get(NULL, &pos));
772
773 if (sd->hidden)
774 {
775 if (pos < (panel_size - threshold)) _drawer_open(obj, w, h, EINA_TRUE);
776 else _drawer_close(obj, w, h, EINA_TRUE);
777 }
778 else
779 {
780 if (pos < threshold) _drawer_open(obj, w, h, EINA_TRUE);
781 else _drawer_close(obj, w, h, EINA_TRUE);
782 }
783 break;
784
785 case ELM_PANEL_ORIENT_BOTTOM:
786 panel_size = h * sd->content_size_ratio;
787 threshold = panel_size / 4;
788 eo_do(obj, elm_interface_scrollable_content_pos_get(NULL, &pos));
789
790 if (sd->hidden)
791 {
792 if (pos > threshold) _drawer_open(obj, w, h, EINA_TRUE);
793 else _drawer_close(obj, w, h, EINA_TRUE);
794 }
795 else
796 {
797 if (pos > (panel_size - threshold)) _drawer_open(obj, w, h, EINA_TRUE);
798 else _drawer_close(obj, w, h, EINA_TRUE);
799 }
800 break;
801
802 case ELM_PANEL_ORIENT_LEFT:
803 panel_size = w * sd->content_size_ratio;
804 threshold = panel_size / 4;
805 eo_do(obj, elm_interface_scrollable_content_pos_get(&pos, NULL));
806
807 if (sd->hidden)
808 {
809 if (pos < (panel_size - threshold)) _drawer_open(obj, w, h, EINA_TRUE);
810 else _drawer_close(obj, w, h, EINA_TRUE);
811 }
812 else
813 {
814 if (pos < threshold) _drawer_open(obj, w, h, EINA_TRUE);
815 else _drawer_close(obj, w, h, EINA_TRUE);
816 }
817 break;
818
819 case ELM_PANEL_ORIENT_RIGHT:
820 panel_size = w * sd->content_size_ratio;
821 threshold = panel_size / 4;
822 eo_do(obj, elm_interface_scrollable_content_pos_get(&pos, NULL));
823
824 if (sd->hidden)
825 {
826 if (pos > threshold) _drawer_open(obj, w, h, EINA_TRUE);
827 else _drawer_close(obj, w, h, EINA_TRUE);
828 }
829 else
830 {
831 if (pos > (panel_size - threshold)) _drawer_open(obj, w, h, EINA_TRUE);
832 else _drawer_close(obj, w, h, EINA_TRUE);
833 }
834 break;
835 }
836
837 if (!sd->freeze && sd->hidden)
838 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
243} 839}
244 840
245static Eina_Bool 841static Eina_Bool
@@ -330,6 +926,8 @@ _elm_panel_evas_object_smart_add(Eo *obj, Elm_Panel_Data *priv)
330 elm_widget_sub_object_parent_add(obj); 926 elm_widget_sub_object_parent_add(obj);
331 elm_widget_can_focus_set(obj, EINA_TRUE); 927 elm_widget_can_focus_set(obj, EINA_TRUE);
332 928
929 priv->panel_edje = wd->resize_obj;
930
333 eo_do(obj, elm_obj_widget_theme_apply()); 931 eo_do(obj, elm_obj_widget_theme_apply());
334 932
335 priv->bx = evas_object_box_add(evas_object_evas_get(obj)); 933 priv->bx = evas_object_box_add(evas_object_evas_get(obj));
@@ -378,6 +976,8 @@ _elm_panel_evas_object_smart_del(Eo *obj, Elm_Panel_Data *sd)
378 976
379 sd->delete_me = EINA_TRUE; 977 sd->delete_me = EINA_TRUE;
380 978
979 ELM_SAFE_FREE(sd->timer, ecore_timer_del);
980
381 /* let's make our box object the *last* to be processed, since it 981 /* let's make our box object the *last* to be processed, since it
382 * may (smart) parent other sub objects here */ 982 * may (smart) parent other sub objects here */
383 EINA_LIST_FOREACH(wd->subobjs, l, child) 983 EINA_LIST_FOREACH(wd->subobjs, l, child)
@@ -394,9 +994,77 @@ _elm_panel_evas_object_smart_del(Eo *obj, Elm_Panel_Data *sd)
394} 994}
395 995
396EOLIAN static void 996EOLIAN static void
397_elm_panel_elm_widget_access(Eo *obj, Elm_Panel_Data *_pd EINA_UNUSED, Eina_Bool is_access) 997_elm_panel_evas_object_smart_move(Eo *obj, Elm_Panel_Data *sd, Evas_Coord x, Evas_Coord y)
998{
999 eo_do_super(obj, MY_CLASS, evas_obj_smart_move(x, y));
1000
1001 evas_object_move(sd->hit_rect, x, y);
1002}
1003
1004static Eina_Bool
1005_elm_panel_anim_cb(void *data)
1006{
1007 Evas_Object *obj = data;
1008 ELM_PANEL_DATA_GET(obj, sd);
1009 int w, h;
1010
1011 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1012
1013 if (sd->hidden) _drawer_close(obj, w, h, EINA_FALSE);
1014 else _drawer_open(obj, w, h, EINA_FALSE);
1015
1016 return ECORE_CALLBACK_CANCEL;
1017}
1018
1019EOLIAN static void
1020_elm_panel_evas_object_smart_resize(Eo *obj, Elm_Panel_Data *sd, Evas_Coord w, Evas_Coord h)
1021{
1022 eo_do_super(obj, MY_CLASS, evas_obj_smart_resize(w, h));
1023
1024 if (!sd->scrollable) return;
1025
1026 evas_object_resize(sd->hit_rect, w, h);
1027
1028 switch (sd->orient)
1029 {
1030 case ELM_PANEL_ORIENT_TOP:
1031 case ELM_PANEL_ORIENT_BOTTOM:
1032 // vertical
1033 evas_object_resize(sd->scr_ly, w, (1 + sd->content_size_ratio) * h);
1034 evas_object_size_hint_min_set(sd->scr_panel, w, (sd->content_size_ratio * h));
1035 evas_object_size_hint_min_set(sd->scr_event, w, h);
1036 break;
1037 case ELM_PANEL_ORIENT_LEFT:
1038 case ELM_PANEL_ORIENT_RIGHT:
1039 // horizontal
1040 evas_object_resize(sd->scr_ly, (1 + sd->content_size_ratio) * w, h);
1041 evas_object_size_hint_min_set(sd->scr_panel, (sd->content_size_ratio * w), h);
1042 evas_object_size_hint_min_set(sd->scr_event, w, h);
1043 break;
1044 }
1045
1046 ecore_animator_add(_elm_panel_anim_cb, obj);
1047}
1048
1049EOLIAN static void
1050_elm_panel_evas_object_smart_member_add(Eo *obj, Elm_Panel_Data *sd, Evas_Object *member)
1051{
1052 eo_do_super(obj, MY_CLASS, evas_obj_smart_member_add(member));
1053
1054 if (sd->hit_rect) evas_object_raise(sd->hit_rect);
1055}
1056
1057EOLIAN static void
1058_elm_panel_elm_widget_access(Eo *obj, Elm_Panel_Data *_pd, Eina_Bool is_access)
398{ 1059{
399 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); 1060 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1061 Elm_Panel_Data *sd = _pd;
1062
1063 if (sd->scrollable)
1064 {
1065 _access_obj_process(obj, is_access);
1066 return;
1067 }
400 1068
401 if (is_access) 1069 if (is_access)
402 _elm_access_edje_object_part_object_register 1070 _elm_access_edje_object_part_object_register
@@ -412,6 +1080,10 @@ elm_panel_add(Evas_Object *parent)
412 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL); 1080 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
413 Evas_Object *obj = eo_add(MY_CLASS, parent); 1081 Evas_Object *obj = eo_add(MY_CLASS, parent);
414 eo_unref(obj); 1082 eo_unref(obj);
1083
1084 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
1085 wd->highlight_root = EINA_TRUE;
1086
415 return obj; 1087 return obj;
416} 1088}
417 1089
@@ -431,7 +1103,8 @@ _elm_panel_orient_set(Eo *obj, Elm_Panel_Data *sd, Elm_Panel_Orient orient)
431 if (sd->orient == orient) return; 1103 if (sd->orient == orient) return;
432 sd->orient = orient; 1104 sd->orient = orient;
433 1105
434 _orient_set_do(obj); 1106 if (sd->scrollable) _scrollable_layout_theme_set(obj, sd);
1107 else _orient_set_do(obj);
435 1108
436 elm_layout_sizing_eval(obj); 1109 elm_layout_sizing_eval(obj);
437} 1110}
@@ -445,7 +1118,16 @@ _elm_panel_orient_get(Eo *obj EINA_UNUSED, Elm_Panel_Data *sd)
445EOLIAN static void 1118EOLIAN static void
446_elm_panel_hidden_set(Eo *obj, Elm_Panel_Data *sd, Eina_Bool hidden) 1119_elm_panel_hidden_set(Eo *obj, Elm_Panel_Data *sd, Eina_Bool hidden)
447{ 1120{
448 if (sd->hidden == !!hidden) return; 1121 if (sd->hidden == !!hidden)
1122 {
1123 if (sd->scrollable && sd->hidden && !sd->freeze)
1124 {
1125 Evas_Coord w, h;
1126 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1127 _drawer_close(obj, w, h, EINA_TRUE);
1128 }
1129 return;
1130 }
449 1131
450 _panel_toggle(NULL, obj, NULL, NULL); 1132 _panel_toggle(NULL, obj, NULL, NULL);
451} 1133}
@@ -462,6 +1144,243 @@ _elm_panel_toggle(Eo *obj, Elm_Panel_Data *_pd EINA_UNUSED)
462 _panel_toggle(NULL, obj, NULL, NULL); 1144 _panel_toggle(NULL, obj, NULL, NULL);
463} 1145}
464 1146
1147EOLIAN static Eina_Bool
1148_elm_panel_elm_widget_on_focus_region(Eo *obj,
1149 Elm_Panel_Data *sd,
1150 Evas_Coord *x,
1151 Evas_Coord *y,
1152 Evas_Coord *w,
1153 Evas_Coord *h)
1154{
1155 eo_do(obj, elm_interface_scrollable_content_pos_get(x, y));
1156 evas_object_geometry_get(obj, NULL, NULL, w, h);
1157 switch (sd->orient)
1158 {
1159 case ELM_PANEL_ORIENT_TOP:
1160 case ELM_PANEL_ORIENT_BOTTOM:
1161 *h = *h * sd->content_size_ratio;
1162 break;
1163 case ELM_PANEL_ORIENT_LEFT:
1164 case ELM_PANEL_ORIENT_RIGHT:
1165 *w = *w * sd->content_size_ratio;
1166 break;
1167 }
1168 return EINA_TRUE;
1169}
1170
1171static void
1172_anim_stop_cb(Evas_Object *obj, void *data EINA_UNUSED)
1173{
1174 if (elm_widget_disabled_get(obj)) return;
1175 _state_sync(obj);
1176}
1177
1178static void
1179_scroll_cb(Evas_Object *obj, void *data EINA_UNUSED)
1180{
1181 ELM_PANEL_DATA_GET(obj, sd);
1182 Elm_Panel_Scroll_Info event;
1183 Evas_Coord x, y, w, h;
1184
1185 if (elm_widget_disabled_get(obj)) return;
1186 // in the case of
1187 // freeze_set(FALSE) -> mouse_up -> freeze_set(TRUE) -> scroll
1188 if (sd->freeze)
1189 {
1190 eo_do(obj, elm_interface_scrollable_movement_block_set
1191 (ELM_SCROLLER_MOVEMENT_NO_BLOCK));
1192 sd->freeze = EINA_FALSE;
1193 elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
1194 }
1195
1196 eo_do(obj, elm_interface_scrollable_content_pos_get(&x, &y));
1197 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1198
1199 switch (sd->orient)
1200 {
1201 case ELM_PANEL_ORIENT_TOP:
1202 event.rel_x = 1;
1203 event.rel_y = 1 - ((double) y / (double) ((sd->content_size_ratio) * h));
1204 break;
1205 case ELM_PANEL_ORIENT_BOTTOM:
1206 event.rel_x = 1;
1207 event.rel_y = (double) y / (double) ((sd->content_size_ratio) * h);
1208 break;
1209 case ELM_PANEL_ORIENT_LEFT:
1210 event.rel_x = 1 - ((double) x / (double) ((sd->content_size_ratio) * w));
1211 event.rel_y = 1;
1212 break;
1213 case ELM_PANEL_ORIENT_RIGHT:
1214 event.rel_x = (double) x / (double) ((sd->content_size_ratio) * w);
1215 event.rel_y = 1;
1216 break;
1217 }
1218 evas_object_smart_callback_call(obj, SIG_SCROLL, (void *) &event);
1219}
1220
1221EOLIAN static Eina_Bool
1222_elm_panel_elm_widget_disable(Eo *obj, Elm_Panel_Data *sd)
1223{
1224 Eina_Bool int_ret = EINA_FALSE;
1225 eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_disable());
1226 if (!int_ret) return EINA_FALSE;
1227
1228 if (sd->scrollable)
1229 {
1230 if (elm_widget_disabled_get(obj))
1231 {
1232 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_DOWN,
1233 _on_mouse_down);
1234 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_MOVE,
1235 _on_mouse_move);
1236 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_UP,
1237 _on_mouse_up);
1238 evas_object_event_callback_del(sd->scr_event, EVAS_CALLBACK_MOUSE_UP,
1239 _event_mouse_up);
1240 }
1241 else
1242 {
1243 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
1244 _on_mouse_down, sd);
1245 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
1246 _on_mouse_move, sd);
1247 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
1248 _on_mouse_up, sd);
1249 evas_object_event_callback_add(sd->scr_event, EVAS_CALLBACK_MOUSE_UP,
1250 _event_mouse_up, obj);
1251 }
1252 }
1253
1254 return EINA_TRUE;
1255}
1256
1257EOLIAN static void
1258_elm_panel_scrollable_content_size_set(Eo *obj EINA_UNUSED, Elm_Panel_Data *sd, double ratio)
1259{
1260 sd->content_size_ratio = ratio;
1261}
1262
1263EOLIAN static void
1264_elm_panel_scrollable_set(Eo *obj, Elm_Panel_Data *sd, Eina_Bool scrollable)
1265{
1266 scrollable = !!scrollable;
1267 if (sd->scrollable == scrollable) return;
1268 sd->scrollable = scrollable;
1269
1270 if (scrollable)
1271 {
1272 elm_layout_content_unset(obj, "elm.swallow.content");
1273
1274 elm_widget_resize_object_set(obj, NULL, EINA_TRUE);
1275 elm_widget_sub_object_add(obj, sd->panel_edje);
1276
1277 if (!sd->scr_edje)
1278 {
1279 const char *handler_size;
1280
1281 sd->scr_edje = edje_object_add(evas_object_evas_get(obj));
1282 elm_widget_theme_object_set(obj, sd->scr_edje, "scroller", "panel",
1283 elm_widget_style_get(obj));
1284 evas_object_size_hint_weight_set
1285 (sd->scr_edje, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1286 evas_object_size_hint_align_set
1287 (sd->scr_edje, EVAS_HINT_FILL, EVAS_HINT_FILL);
1288
1289 handler_size = edje_object_data_get(sd->scr_edje, "handler_size");
1290 if (handler_size)
1291 sd->handler_size = (int) (elm_object_scale_get(obj)) * (atoi(handler_size));
1292 }
1293
1294 elm_widget_resize_object_set(obj, sd->scr_edje, EINA_TRUE);
1295
1296 if (!sd->hit_rect)
1297 {
1298 sd->hit_rect = evas_object_rectangle_add(evas_object_evas_get(obj));
1299 evas_object_smart_member_add(sd->hit_rect, obj);
1300 elm_widget_sub_object_add(obj, sd->hit_rect);
1301 evas_object_color_set(sd->hit_rect, 0, 0, 0, 0);
1302 evas_object_show(sd->hit_rect);
1303 evas_object_repeat_events_set(sd->hit_rect, EINA_TRUE);
1304
1305 eo_do(obj,
1306 elm_interface_scrollable_objects_set(sd->scr_edje, sd->hit_rect),
1307 elm_interface_scrollable_animate_stop_cb_set(_anim_stop_cb),
1308 elm_interface_scrollable_scroll_cb_set(_scroll_cb));
1309 }
1310
1311 if (!sd->scr_ly)
1312 {
1313 sd->scr_ly = elm_layout_add(obj);
1314 evas_object_smart_member_add(sd->scr_ly, obj);
1315 elm_widget_sub_object_add(obj, sd->scr_ly);
1316 _scrollable_layout_theme_set(obj, sd);
1317
1318 sd->scr_panel = evas_object_rectangle_add(evas_object_evas_get(obj));
1319 evas_object_color_set(sd->scr_panel, 0, 0, 0, 0);
1320 elm_widget_sub_object_add(obj, sd->scr_panel);
1321 elm_layout_content_set(sd->scr_ly, "panel_area", sd->scr_panel);
1322
1323 sd->scr_event = evas_object_rectangle_add(evas_object_evas_get(obj));
1324 evas_object_color_set(sd->scr_event, 0, 0, 0, 0);
1325 elm_widget_sub_object_add(obj, sd->scr_event);
1326 elm_layout_content_set(sd->scr_ly, "event_area", sd->scr_event);
1327 }
1328
1329 eo_do(obj,
1330 elm_interface_scrollable_content_set(sd->scr_ly));
1331 sd->freeze = EINA_TRUE;
1332 elm_layout_content_set(sd->scr_ly, "elm.swallow.content", sd->bx);
1333
1334 switch (sd->orient)
1335 {
1336 case ELM_PANEL_ORIENT_TOP:
1337 case ELM_PANEL_ORIENT_BOTTOM:
1338 eo_do(obj, elm_interface_scrollable_movement_block_set
1339 (ELM_SCROLLER_MOVEMENT_BLOCK_VERTICAL));
1340 break;
1341 case ELM_PANEL_ORIENT_LEFT:
1342 case ELM_PANEL_ORIENT_RIGHT:
1343 eo_do(obj, elm_interface_scrollable_movement_block_set
1344 (ELM_SCROLLER_MOVEMENT_BLOCK_HORIZONTAL));
1345 break;
1346 }
1347
1348 eo_do(obj, elm_interface_scrollable_single_direction_set
1349 (ELM_SCROLLER_SINGLE_DIRECTION_NONE));
1350
1351 if (!elm_widget_disabled_get(obj))
1352 {
1353 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
1354 _on_mouse_down, sd);
1355 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
1356 _on_mouse_move, sd);
1357 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
1358 _on_mouse_up, sd);
1359 evas_object_event_callback_add(sd->scr_event, EVAS_CALLBACK_MOUSE_UP,
1360 _event_mouse_up, obj);
1361 }
1362
1363 }
1364 else
1365 {
1366 eo_do(obj, elm_interface_scrollable_content_set(NULL));
1367
1368 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_DOWN, _on_mouse_down);
1369 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_MOVE, _on_mouse_move);
1370 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_UP, _on_mouse_up);
1371 evas_object_event_callback_del(sd->scr_event, EVAS_CALLBACK_MOUSE_UP,
1372 _event_mouse_up);
1373
1374 elm_widget_resize_object_set(obj, NULL, EINA_TRUE);
1375 elm_widget_sub_object_add(obj, sd->scr_edje);
1376
1377 elm_widget_resize_object_set(obj, sd->panel_edje, EINA_TRUE);
1378
1379 elm_layout_content_unset(sd->scr_ly, "elm.swallow.content");
1380 elm_layout_content_set(obj, "elm.swallow.content", sd->bx);
1381 }
1382}
1383
465static void 1384static void
466_elm_panel_class_constructor(Eo_Class *klass) 1385_elm_panel_class_constructor(Eo_Class *klass)
467{ 1386{
diff --git a/src/lib/elm_panel.eo b/src/lib/elm_panel.eo
index ecc48fe9f..0924ebebb 100644
--- a/src/lib/elm_panel.eo
+++ b/src/lib/elm_panel.eo
@@ -1,4 +1,4 @@
1class Elm_Panel (Elm_Layout) 1class Elm_Panel (Elm_Layout, Elm_Interface_Scrollable)
2{ 2{
3 eo_prefix: elm_obj_panel; 3 eo_prefix: elm_obj_panel;
4 properties { 4 properties {
@@ -45,6 +45,28 @@ class Elm_Panel (Elm_Layout)
45 Eina_Bool hidden; /*@ If true, the panel will run the animation to disappear. */ 45 Eina_Bool hidden; /*@ If true, the panel will run the animation to disappear. */
46 } 46 }
47 } 47 }
48 scrollable {
49 set {
50 /*@
51 @brief Set the scrollability of the panel.
52
53 @ingroup Panel */
54 }
55 values {
56 Eina_Bool scrollable;
57 }
58 }
59 scrollable_content_size {
60 set {
61 /*@
62 @brief Set the size of the scrollable panel.
63
64 @ingroup Panel */
65 }
66 values {
67 double ratio;
68 }
69 }
48 } 70 }
49 methods { 71 methods {
50 toggle { 72 toggle {
@@ -59,12 +81,17 @@ class Elm_Panel (Elm_Layout)
59 class.constructor; 81 class.constructor;
60 Eo.Base.constructor; 82 Eo.Base.constructor;
61 Evas.Object_Smart.add; 83 Evas.Object_Smart.add;
84 Evas.Object_Smart.member_add;
62 Evas.Object_Smart.del; 85 Evas.Object_Smart.del;
86 Evas.Object_Smart.resize;
87 Evas.Object_Smart.move;
63 Elm_Widget.theme_apply; 88 Elm_Widget.theme_apply;
64 Elm_Widget.focus_next_manager_is; 89 Elm_Widget.focus_next_manager_is;
65 Elm_Widget.focus_next; 90 Elm_Widget.focus_next;
91 Elm_Widget.disable;
66 Elm_Widget.access; 92 Elm_Widget.access;
67 Elm_Widget.event; 93 Elm_Widget.event;
94 Elm_Widget.on_focus_region;
68 Elm_Container.content_get; 95 Elm_Container.content_get;
69 Elm_Container.content_unset; 96 Elm_Container.content_unset;
70 Elm_Container.content_set; 97 Elm_Container.content_set;
diff --git a/src/lib/elm_panel.h b/src/lib/elm_panel.h
index 6bf385390..0e957ee5c 100644
--- a/src/lib/elm_panel.h
+++ b/src/lib/elm_panel.h
@@ -23,6 +23,9 @@
23 * 23 *
24 * This widget emits the following signals, besides the ones sent from 24 * This widget emits the following signals, besides the ones sent from
25 * @ref Layout: 25 * @ref Layout:
26 * @li @c "scroll" : When the content has been scrolled (moved). (since 1.10)
27 * This signal is emitted only when the panel is scrollable.
28 * Elm_Panel_Scroll_Info will be passed by @c event_info argument.
26 * @li @c "focused" : When the panel has received focus. (since 1.8) 29 * @li @c "focused" : When the panel has received focus. (since 1.8)
27 * @li @c "unfocused" : When the panel has lost focus. (since 1.8) 30 * @li @c "unfocused" : When the panel has lost focus. (since 1.8)
28 * 31 *
diff --git a/src/lib/elm_panel_common.h b/src/lib/elm_panel_common.h
index 8c84d1ab1..9993b2208 100644
--- a/src/lib/elm_panel_common.h
+++ b/src/lib/elm_panel_common.h
@@ -6,3 +6,9 @@ typedef enum
6 ELM_PANEL_ORIENT_RIGHT, /**< Panel (dis)appears from the right */ 6 ELM_PANEL_ORIENT_RIGHT, /**< Panel (dis)appears from the right */
7} Elm_Panel_Orient; 7} Elm_Panel_Orient;
8 8
9typedef struct _Elm_Panel_Scroll_Info
10{
11 double rel_x; /**<content scrolled position (0.0 ~ 1.0) in the panel>*/
12 double rel_y; /**<content scrolled position (0.0 ~ 1.0) in the panel>*/
13
14} Elm_Panel_Scroll_Info;
diff --git a/src/lib/elm_widget_panel.h b/src/lib/elm_widget_panel.h
index 6982774d0..38740081b 100644
--- a/src/lib/elm_widget_panel.h
+++ b/src/lib/elm_widget_panel.h
@@ -1,6 +1,7 @@
1#ifndef ELM_WIDGET_PANEL_H 1#ifndef ELM_WIDGET_PANEL_H
2#define ELM_WIDGET_PANEL_H 2#define ELM_WIDGET_PANEL_H
3 3
4#include "elm_interface_scrollable.h"
4#include "elm_widget_layout.h" 5#include "elm_widget_layout.h"
5 6
6/** 7/**
@@ -22,11 +23,22 @@ struct _Elm_Panel_Data
22{ 23{
23 Evas_Object *bx, *content; 24 Evas_Object *bx, *content;
24 Evas_Object *event; 25 Evas_Object *event;
26 Evas_Object *scr_ly;
27 Evas_Object *hit_rect, *panel_edje, *scr_edje;
28 Evas_Object *scr_panel, *scr_event;
29
25 30
26 Elm_Panel_Orient orient; 31 Elm_Panel_Orient orient;
27 32
33 double content_size_ratio;
34 Evas_Coord down_x, down_y;
35 Evas_Coord handler_size;
36 Ecore_Timer *timer;
37
28 Eina_Bool hidden : 1; 38 Eina_Bool hidden : 1;
29 Eina_Bool delete_me : 1; 39 Eina_Bool delete_me : 1;
40 Eina_Bool scrollable : 1;
41 Eina_Bool freeze: 1;
30}; 42};
31 43
32/** 44/**