1 #include <Elementary.h>
3 #include "elm_widget_panel.h"
5 EAPI const char ELM_PANEL_SMART_NAME[] = "elm_panel";
7 static const char ACCESS_OUTLINE_PART[] = "access.outline";
9 static const char SIG_SCROLL[] = "scroll";
11 static const Evas_Smart_Cb_Description _smart_callbacks[] =
16 static const Evas_Smart_Interface *_smart_interfaces[] =
18 (Evas_Smart_Interface *)&ELM_SCROLLABLE_IFACE, NULL
21 EVAS_SMART_SUBCLASS_IFACE_NEW
22 (ELM_PANEL_SMART_NAME, _elm_panel, Elm_Panel_Smart_Class,
23 Elm_Layout_Smart_Class, elm_layout_smart_class_get, _smart_callbacks,
27 _mirrored_set(Evas_Object *obj,
30 ELM_PANEL_DATA_GET(obj, sd);
32 elm_widget_mirrored_set(sd->bx, rtl);
33 elm_panel_orient_set(obj, elm_panel_orient_get(obj));
37 _elm_panel_smart_sizing_eval(Evas_Object *obj)
39 Evas_Coord mw = -1, mh = -1;
41 ELM_PANEL_DATA_GET(obj, sd);
43 if (sd->on_deletion) return;
45 evas_object_smart_calculate(sd->bx);
46 edje_object_size_min_calc(ELM_WIDGET_DATA(sd)->resize_obj, &mw, &mh);
47 evas_object_size_hint_min_set(obj, mw, mh);
48 evas_object_size_hint_max_set(obj, -1, -1);
52 _access_state_cb(void *data, Evas_Object *obj __UNUSED__)
54 ELM_PANEL_DATA_GET(data, sd);
56 if (!sd->hidden) return strdup(E_("state: opened"));
57 else return strdup(E_("state: closed"));
63 _access_object_get(const Evas_Object *obj, const char *part)
66 ELM_PANEL_DATA_GET(obj, sd);
68 po = (Evas_Object *)edje_object_part_object_get
69 (elm_layout_edje_get(sd->scr_ly), part);
70 ao = evas_object_data_get(po, "_part_access_obj");
76 _access_activate_cb(void *data,
77 Evas_Object *part_obj __UNUSED__,
78 Elm_Object_Item *item __UNUSED__)
80 elm_panel_hidden_set(data, EINA_TRUE);
84 _access_obj_process(Evas_Object *obj, Eina_Bool is_access)
87 ELM_PANEL_DATA_GET(obj, sd);
91 ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
94 ao = _elm_access_edje_object_part_object_register
95 (obj, elm_layout_edje_get(sd->scr_ly), ACCESS_OUTLINE_PART);
96 _elm_access_text_set(_elm_access_object_get(ao),
97 ELM_ACCESS_TYPE, E_("A drawer is open"));
98 _elm_access_text_set(_elm_access_object_get(ao),
99 ELM_ACCESS_CONTEXT_INFO, E_("Double tap to close drawer menu"));
100 _elm_access_activate_callback_set
101 (_elm_access_object_get(ao), _access_activate_cb, obj);
106 _elm_access_edje_object_part_object_unregister
107 (obj, elm_layout_edje_get(sd->scr_ly), ACCESS_OUTLINE_PART);
112 _orient_set_do(Evas_Object *obj)
114 ELM_PANEL_DATA_GET(obj, sd);
118 case ELM_PANEL_ORIENT_TOP:
119 elm_layout_theme_set(obj, "panel", "top", elm_widget_style_get(obj));
122 case ELM_PANEL_ORIENT_BOTTOM:
124 (obj, "panel", "bottom", elm_widget_style_get(obj));
127 case ELM_PANEL_ORIENT_LEFT:
128 if (!elm_widget_mirrored_get(obj))
130 (obj, "panel", "left", elm_widget_style_get(obj));
133 (obj, "panel", "right", elm_widget_style_get(obj));
136 case ELM_PANEL_ORIENT_RIGHT:
137 if (!elm_widget_mirrored_get(obj))
139 (obj, "panel", "right", elm_widget_style_get(obj));
142 (obj, "panel", "left", elm_widget_style_get(obj));
147 if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
150 ao = _elm_access_edje_object_part_object_register
151 (obj, ELM_WIDGET_DATA(sd)->resize_obj, "btn_icon");
152 _elm_access_text_set(_elm_access_object_get(ao),
153 ELM_ACCESS_TYPE, E_("panel button"));
154 _elm_access_callback_set
155 (_elm_access_object_get(ao), ELM_ACCESS_STATE, _access_state_cb, obj);
160 _scrollable_layout_theme_set(Evas_Object *obj, Elm_Panel_Smart_Data *sd)
164 case ELM_PANEL_ORIENT_TOP:
165 if (!elm_layout_theme_set(sd->scr_ly, "scroller", "panel/top",
166 elm_widget_style_get(obj)))
167 CRITICAL("Failed to set layout!");
169 case ELM_PANEL_ORIENT_BOTTOM:
170 if (!elm_layout_theme_set(sd->scr_ly, "scroller", "panel/bottom",
171 elm_widget_style_get(obj)))
172 CRITICAL("Failed to set layout!");
174 case ELM_PANEL_ORIENT_LEFT:
175 if (!elm_layout_theme_set(sd->scr_ly, "scroller", "panel/left",
176 elm_widget_style_get(obj)))
177 CRITICAL("Failed to set layout!");
179 case ELM_PANEL_ORIENT_RIGHT:
180 if (!elm_layout_theme_set(sd->scr_ly, "scroller", "panel/right",
181 elm_widget_style_get(obj)))
182 CRITICAL("Failed to set layout!");
187 if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
188 _access_obj_process(obj, EINA_TRUE);
192 _elm_panel_smart_theme(Evas_Object *obj)
196 ELM_PANEL_DATA_GET(obj, sd);
198 if (!ELM_WIDGET_CLASS(_elm_panel_parent_sc)->theme(obj))
201 _mirrored_set(obj, elm_widget_mirrored_get(obj));
205 const char *handler_size;
206 elm_widget_theme_object_set(obj, sd->scr_edje, "scroller", "panel",
207 elm_widget_style_get(obj));
208 _scrollable_layout_theme_set(obj, sd);
210 handler_size = edje_object_data_get(sd->scr_edje, "handler_size");
212 sd->handler_size = (Evas_Coord) (elm_object_scale_get(obj)) * (atoi(handler_size));
216 str = edje_object_data_get
217 (ELM_WIDGET_DATA(sd)->resize_obj, "focus_highlight");
218 if ((str) && (!strcmp(str, "on")))
219 elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
221 elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
226 elm_layout_sizing_eval(obj);
232 _elm_panel_smart_focus_next(const Evas_Object *obj,
233 Elm_Focus_Direction dir,
237 Eina_List *items = NULL;
238 Eina_Bool ret = EINA_FALSE;
240 ELM_PANEL_DATA_GET(obj, sd);
247 if (sd->hidden) return EINA_FALSE;
249 if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
251 Evas_Object *ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
252 if (ao) items = eina_list_append(items, ao);
253 items = eina_list_append(items, sd->content);
255 ret = elm_widget_focus_list_next_get
256 (obj, items, eina_list_data_get, dir, next);
257 eina_list_free(items);
262 return elm_widget_focus_next_get(sd->content, dir, next);
267 /* Try to Focus cycle in subitem */
269 return elm_widget_focus_next_get(cur, dir, next);
272 if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
274 Evas_Object *ao, *po;
275 po = (Evas_Object *)edje_object_part_object_get
276 (ELM_WIDGET_DATA(sd)->resize_obj, "btn_icon");
277 ao = evas_object_data_get(po, "_part_access_obj");
278 _elm_access_highlight_set(ao, EINA_FALSE);
282 *next = (Evas_Object *)obj;
283 return !elm_widget_focus_get(obj);
287 _box_layout_cb(Evas_Object *o,
288 Evas_Object_Box_Data *priv,
289 void *data __UNUSED__)
291 _els_box_layout(o, priv, EINA_TRUE, EINA_FALSE, EINA_FALSE);
295 _handler_open(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
297 ELM_PANEL_DATA_GET(obj, sd);
299 if (sd->handler_size == 0) return;
303 case ELM_PANEL_ORIENT_TOP:
304 sd->s_iface->region_bring_in
305 (obj, 0, (h * sd->content_size_ratio) - sd->handler_size, w, h);
307 case ELM_PANEL_ORIENT_BOTTOM:
308 sd->s_iface->region_bring_in
309 (obj, 0, sd->handler_size, w, h);
311 case ELM_PANEL_ORIENT_LEFT:
312 sd->s_iface->region_bring_in
313 (obj, (w * sd->content_size_ratio) - sd->handler_size, 0, w, h);
315 case ELM_PANEL_ORIENT_RIGHT:
316 sd->s_iface->region_bring_in
317 (obj, sd->handler_size, 0, w, h);
323 _drawer_open(Evas_Object *obj, Evas_Coord w, Evas_Coord h, Eina_Bool anim)
325 ELM_PANEL_DATA_GET(obj, sd);
326 Evas_Coord x = 0, y = 0;
330 sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_NO_BLOCK);
331 sd->freeze = EINA_FALSE;
332 elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
333 elm_object_signal_emit(obj, "elm,state,unhold", "elm");
338 case ELM_PANEL_ORIENT_TOP:
339 case ELM_PANEL_ORIENT_LEFT:
342 case ELM_PANEL_ORIENT_BOTTOM:
343 y = h * sd->content_size_ratio;
346 case ELM_PANEL_ORIENT_RIGHT:
347 x = w * sd->content_size_ratio;
351 if (anim) sd->s_iface->region_bring_in(obj, x, y, w, h);
352 else sd->s_iface->content_region_show(obj, x, y, w, h);
356 _drawer_close(Evas_Object *obj, Evas_Coord w, Evas_Coord h, Eina_Bool anim)
358 ELM_PANEL_DATA_GET(obj, sd);
359 Evas_Coord x = 0, y = 0;
360 Eina_Bool horizontal = EINA_FALSE;
364 case ELM_PANEL_ORIENT_TOP:
365 y = h * sd->content_size_ratio;
368 case ELM_PANEL_ORIENT_LEFT:
369 x = w * sd->content_size_ratio;
370 horizontal = EINA_TRUE;
373 case ELM_PANEL_ORIENT_BOTTOM:
375 case ELM_PANEL_ORIENT_RIGHT:
376 horizontal = EINA_TRUE;
384 sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_NO_BLOCK);
385 sd->freeze = EINA_FALSE;
386 elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
387 elm_object_signal_emit(obj, "elm,state,unhold", "elm");
389 sd->s_iface->region_bring_in(obj, x, y, w, h);
393 sd->s_iface->content_region_show(obj, x, y, w, h);
397 sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_BLOCK_HORIZONTAL);
399 sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_BLOCK_VERTICAL);
400 sd->freeze = EINA_TRUE;
401 elm_layout_signal_emit(sd->scr_ly, "elm,state,content,hidden", "elm");
402 elm_object_signal_emit(obj, "elm,state,hold", "elm");
408 _panel_toggle(void *data __UNUSED__,
410 const char *emission __UNUSED__,
411 const char *source __UNUSED__)
413 ELM_PANEL_DATA_GET(obj, sd);
419 if (elm_widget_disabled_get(obj)) return;
421 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
424 sd->hidden = EINA_FALSE;
425 _drawer_open(obj, w, h, EINA_TRUE);
426 elm_object_signal_emit(obj, "elm,state,active", "elm");
430 sd->hidden = EINA_TRUE;
431 _drawer_close(obj, w, h, EINA_TRUE);
432 elm_object_signal_emit(obj, "elm,state,inactive", "elm");
439 elm_layout_signal_emit(obj, "elm,action,show", "elm");
440 sd->hidden = EINA_FALSE;
441 evas_object_repeat_events_set(obj, EINA_FALSE);
445 elm_layout_signal_emit(obj, "elm,action,hide", "elm");
446 sd->hidden = EINA_TRUE;
447 evas_object_repeat_events_set(obj, EINA_TRUE);
448 if (elm_widget_focus_get(sd->content))
450 elm_widget_focused_object_clear(obj);
451 elm_widget_focus_steal(obj);
455 edje_object_message_signal_process(ELM_WIDGET_DATA(sd)->resize_obj);
460 _state_sync(Evas_Object *obj)
462 ELM_PANEL_DATA_GET(obj, sd);
464 Evas_Coord pos, panel_size, w, h;
465 Eina_Bool open = EINA_FALSE, horizontal = EINA_FALSE;
466 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
470 case ELM_PANEL_ORIENT_TOP:
471 panel_size = h * sd->content_size_ratio;
472 sd->s_iface->content_pos_get(obj, NULL, &pos);
474 if (pos == 0) open = EINA_TRUE;
475 else if (pos == panel_size) open = EINA_FALSE;
476 else return EINA_FALSE;
479 case ELM_PANEL_ORIENT_BOTTOM:
480 panel_size = h * sd->content_size_ratio;
481 sd->s_iface->content_pos_get(obj, NULL, &pos);
483 if (pos == panel_size) open = EINA_TRUE;
484 else if (pos == 0) open = EINA_FALSE;
485 else return EINA_FALSE;
488 case ELM_PANEL_ORIENT_LEFT:
489 panel_size = w * sd->content_size_ratio;
490 sd->s_iface->content_pos_get(obj, &pos, NULL);
491 horizontal = EINA_TRUE;
493 if (pos == 0) open = EINA_TRUE;
494 else if (pos == panel_size) open = EINA_FALSE;
495 else return EINA_FALSE;
498 case ELM_PANEL_ORIENT_RIGHT:
499 panel_size = w * sd->content_size_ratio;
500 sd->s_iface->content_pos_get(obj, &pos, NULL);
501 horizontal = EINA_TRUE;
503 if (pos == panel_size) open = EINA_TRUE;
504 else if (pos == 0) open = EINA_FALSE;
505 else return EINA_FALSE;
513 sd->hidden = EINA_FALSE;
514 elm_object_signal_emit(obj, "elm,state,active", "elm");
516 sd->s_iface->single_direction_set(obj, ELM_SCROLLER_SINGLE_DIRECTION_HARD);
519 elm_object_tree_focus_allow_set(obj, EINA_TRUE);
520 if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
522 ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
523 evas_object_show(ao);
524 _elm_access_highlight_set(ao, EINA_FALSE);
527 elm_object_focus_set(obj, EINA_TRUE);
533 sd->hidden = EINA_TRUE;
534 elm_object_signal_emit(obj, "elm,state,inactive", "elm");
537 sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_BLOCK_HORIZONTAL);
539 sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_BLOCK_VERTICAL);
540 sd->freeze = EINA_TRUE;
541 elm_layout_signal_emit(sd->scr_ly, "elm,state,content,hidden", "elm");
542 elm_object_signal_emit(obj, "elm,state,hold", "elm");
544 sd->s_iface->single_direction_set(obj, ELM_SCROLLER_SINGLE_DIRECTION_NONE);
547 elm_object_tree_focus_allow_set(obj, EINA_FALSE);
548 if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
550 ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
551 evas_object_hide(ao);
559 _timer_cb(void *data)
561 ELM_PANEL_DATA_GET(data, sd);
562 Evas_Object *obj = data;
569 sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_NO_BLOCK);
570 sd->freeze = EINA_FALSE;
571 elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
572 elm_object_signal_emit(obj, "elm,state,unhold", "elm");
573 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
574 _handler_open(obj, w, h);
577 return ECORE_CALLBACK_CANCEL;
581 _event_mouse_up(void *data,
583 Evas_Object *obj EINA_UNUSED,
586 ELM_PANEL_DATA_GET(data, sd);
587 Evas_Event_Mouse_Up *ev = event_info;
588 Evas_Coord x, y, up_x, up_y, minw = 0, minh = 0;
589 evas_object_geometry_get(data, &x, &y, NULL, NULL);
591 up_x = ev->output.x - x;
592 up_y = ev->output.y - y;
594 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
596 if ((!sd->hidden) && (up_x == sd->down_x) && (up_y == sd->down_y))
597 elm_panel_hidden_set(data, EINA_TRUE);
601 _on_mouse_down(void *data,
606 Elm_Panel_Smart_Data *sd = data;
607 Evas_Event_Mouse_Down *ev = event_info;
608 Evas_Coord finger_size = elm_config_finger_size_get();
609 Evas_Coord x, y, w, h;
610 evas_object_geometry_get(obj, &x, &y, &w, &h);
611 const char *timer_duration;
612 double timer_duration_num;
614 sd->down_x = ev->output.x - x;
615 sd->down_y = ev->output.y - y;
617 // if freeze state & mouse down on the edge
618 // then set timer for un-freeze
619 timer_duration = edje_object_data_get(sd->scr_edje, "timer_duration");
620 if (timer_duration) timer_duration_num = atof(timer_duration);
621 else timer_duration_num = 0.2;
625 case ELM_PANEL_ORIENT_TOP:
626 if ((sd->freeze) && (sd->down_y >= 0) && (sd->down_y < finger_size))
628 if (sd->timer) ecore_timer_del(sd->timer);
629 sd->timer = ecore_timer_add(timer_duration_num, _timer_cb, obj);
632 case ELM_PANEL_ORIENT_BOTTOM:
633 if ((sd->freeze) && (sd->down_y <= h) && (sd->down_y > (h - finger_size)))
635 if (sd->timer) ecore_timer_del(sd->timer);
636 sd->timer = ecore_timer_add(timer_duration_num, _timer_cb, obj);
639 case ELM_PANEL_ORIENT_LEFT:
640 if ((sd->freeze) && (sd->down_x >= 0) && (sd->down_x < finger_size))
642 if (sd->timer) ecore_timer_del(sd->timer);
643 sd->timer = ecore_timer_add(timer_duration_num, _timer_cb, obj);
646 case ELM_PANEL_ORIENT_RIGHT:
647 if ((sd->freeze) && (sd->down_x <= w) && (sd->down_x > (w - finger_size)))
649 if (sd->timer) ecore_timer_del(sd->timer);
650 sd->timer = ecore_timer_add(timer_duration_num, _timer_cb, obj);
657 _on_mouse_move(void *data,
662 Elm_Panel_Smart_Data *sd = data;
663 Evas_Event_Mouse_Move *ev = event_info;
664 Evas_Coord x, y, w, h, cur_x, cur_y, finger_size;
665 evas_object_geometry_get(obj, &x, &y, &w, &h);
666 finger_size = elm_config_finger_size_get();
668 cur_x = ev->cur.canvas.x - x;
669 cur_y = ev->cur.canvas.y - y;
671 // if mouse down on the edge (it means sd->timer is not null)
672 // and move more than finger size
676 case ELM_PANEL_ORIENT_TOP:
677 if (sd->timer && ((cur_y - sd->down_y) > finger_size))
679 sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_NO_BLOCK);
680 sd->freeze = EINA_FALSE;
681 elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
682 elm_object_signal_emit(obj, "elm,state,unhold", "elm");
685 case ELM_PANEL_ORIENT_BOTTOM:
686 if (sd->timer && ((sd->down_y - cur_y) > finger_size))
688 sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_NO_BLOCK);
689 sd->freeze = EINA_FALSE;
690 elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
691 elm_object_signal_emit(obj, "elm,state,unhold", "elm");
694 case ELM_PANEL_ORIENT_LEFT:
695 if (sd->timer && ((cur_x - sd->down_x) > finger_size))
697 sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_NO_BLOCK);
698 sd->freeze = EINA_FALSE;
699 elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
700 elm_object_signal_emit(obj, "elm,state,unhold", "elm");
703 case ELM_PANEL_ORIENT_RIGHT:
704 if (sd->timer && ((sd->down_x - cur_x) > finger_size))
706 sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_NO_BLOCK);
707 sd->freeze = EINA_FALSE;
708 elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
709 elm_object_signal_emit(obj, "elm,state,unhold", "elm");
714 if (!sd->freeze && sd->hidden)
715 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
719 _on_mouse_up(void *data,
724 Elm_Panel_Smart_Data *sd = data;
725 Evas_Event_Mouse_Up *ev = event_info;
726 Evas_Coord panel_size, threshold, pos, w, h;
728 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
730 ELM_SAFE_FREE(sd->timer, ecore_timer_del);
732 if (_state_sync(obj)) return;
736 case ELM_PANEL_ORIENT_TOP:
737 panel_size = h * sd->content_size_ratio;
738 threshold = panel_size / 4;
739 sd->s_iface->content_pos_get(obj, NULL, &pos);
743 if (pos < (panel_size - threshold)) _drawer_open(obj, w, h, EINA_TRUE);
744 else _drawer_close(obj, w, h, EINA_TRUE);
748 if (pos < threshold) _drawer_open(obj, w, h, EINA_TRUE);
749 else _drawer_close(obj, w, h, EINA_TRUE);
753 case ELM_PANEL_ORIENT_BOTTOM:
754 panel_size = h * sd->content_size_ratio;
755 threshold = panel_size / 4;
756 sd->s_iface->content_pos_get(obj, NULL, &pos);
760 if (pos > threshold) _drawer_open(obj, w, h, EINA_TRUE);
761 else _drawer_close(obj, w, h, EINA_TRUE);
765 if (pos > (panel_size - threshold)) _drawer_open(obj, w, h, EINA_TRUE);
766 else _drawer_close(obj, w, h, EINA_TRUE);
770 case ELM_PANEL_ORIENT_LEFT:
771 panel_size = w * sd->content_size_ratio;
772 threshold = panel_size / 4;
773 sd->s_iface->content_pos_get(obj, &pos, NULL);
777 if (pos < (panel_size - threshold)) _drawer_open(obj, w, h, EINA_TRUE);
778 else _drawer_close(obj, w, h, EINA_TRUE);
782 if (pos < threshold) _drawer_open(obj, w, h, EINA_TRUE);
783 else _drawer_close(obj, w, h, EINA_TRUE);
787 case ELM_PANEL_ORIENT_RIGHT:
788 panel_size = w * sd->content_size_ratio;
789 threshold = panel_size / 4;
790 sd->s_iface->content_pos_get(obj, &pos, NULL);
794 if (pos > threshold) _drawer_open(obj, w, h, EINA_TRUE);
795 else _drawer_close(obj, w, h, EINA_TRUE);
799 if (pos > (panel_size - threshold)) _drawer_open(obj, w, h, EINA_TRUE);
800 else _drawer_close(obj, w, h, EINA_TRUE);
805 if (!sd->freeze && sd->hidden)
806 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
810 _elm_panel_smart_event(Evas_Object *obj,
812 Evas_Callback_Type type,
815 // TIZEN ONLY (2013.11.27): when panel is scrollable, ignore smart event
816 ELM_PANEL_DATA_GET(obj, sd);
817 if (sd->scrollable) return EINA_FALSE;
820 Evas_Event_Key_Down *ev = event_info;
822 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
823 if ((src != obj) || (type != EVAS_CALLBACK_KEY_DOWN)) return EINA_FALSE;
824 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
826 if ((strcmp(ev->keyname, "Return")) &&
827 (strcmp(ev->keyname, "KP_Enter")) &&
828 (strcmp(ev->keyname, "space")))
831 _panel_toggle(NULL, obj, NULL, NULL);
833 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
838 _elm_panel_smart_content_set(Evas_Object *obj,
840 Evas_Object *content)
842 ELM_PANEL_DATA_GET(obj, sd);
844 if (part && strcmp(part, "default"))
845 return ELM_CONTAINER_CLASS(_elm_panel_parent_sc)->content_set
846 (obj, part, content);
848 if (sd->content == content) return EINA_TRUE;
850 evas_object_box_remove_all(sd->bx, EINA_TRUE);
851 sd->content = content;
854 evas_object_box_append(sd->bx, sd->content);
855 evas_object_show(sd->content);
858 elm_layout_sizing_eval(obj);
864 _elm_panel_smart_content_get(const Evas_Object *obj,
867 ELM_PANEL_DATA_GET(obj, sd);
869 if (part && strcmp(part, "default"))
870 return ELM_CONTAINER_CLASS(_elm_panel_parent_sc)->content_get(obj, part);
876 _elm_panel_smart_content_unset(Evas_Object *obj,
879 Evas_Object *content;
881 ELM_PANEL_DATA_GET(obj, sd);
883 if (part && strcmp(part, "default"))
884 return ELM_CONTAINER_CLASS
885 (_elm_panel_parent_sc)->content_unset(obj, part);
887 if (!sd->content) return NULL;
888 content = sd->content;
890 evas_object_box_remove_all(sd->bx, EINA_FALSE);
897 _elm_panel_smart_add(Evas_Object *obj)
899 EVAS_SMART_DATA_ALLOC(obj, Elm_Panel_Smart_Data);
901 ELM_WIDGET_CLASS(_elm_panel_parent_sc)->base.add(obj);
905 _elm_panel_smart_del(Evas_Object *obj)
910 ELM_PANEL_DATA_GET(obj, sd);
912 sd->on_deletion = EINA_TRUE;
914 ELM_SAFE_FREE(sd->timer, ecore_timer_del);
915 ELM_SAFE_FREE(sd->animator, ecore_animator_del);
917 /* let's make our box object the *last* to be processed, since it
918 * may (smart) parent other sub objects here */
919 EINA_LIST_FOREACH(ELM_WIDGET_DATA(sd)->subobjs, l, child)
923 ELM_WIDGET_DATA(sd)->subobjs =
924 eina_list_demote_list(ELM_WIDGET_DATA(sd)->subobjs, l);
929 ELM_WIDGET_CLASS(_elm_panel_parent_sc)->base.del(obj);
933 _elm_panel_smart_orientation_set(Evas_Object *obj, int rotation)
935 ELM_PANEL_DATA_GET(obj, sd);
937 if(rotation == 90 || rotation == 270)
938 sd->content_size_ratio = 0.45;
940 sd->content_size_ratio = 0.80;
944 _elm_panel_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
946 ELM_PANEL_DATA_GET(obj, sd);
948 ELM_WIDGET_CLASS(_elm_panel_parent_sc)->base.move(obj, x, y);
950 evas_object_move(sd->hit_rect, x, y);
954 _elm_panel_anim_cb(void *data)
956 Evas_Object *obj = data;
957 ELM_PANEL_DATA_GET(obj, sd);
960 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
962 if (sd->hidden) _drawer_close(obj, w, h, EINA_FALSE);
963 else _drawer_open(obj, w, h, EINA_FALSE);
967 return ECORE_CALLBACK_CANCEL;
971 _elm_panel_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
973 ELM_PANEL_DATA_GET(obj, sd);
974 ELM_WIDGET_CLASS(_elm_panel_parent_sc)->base.resize(obj, w, h);
976 if (!sd->scrollable) return;
978 evas_object_resize(sd->hit_rect, w, h);
981 case ELM_PANEL_ORIENT_TOP:
982 case ELM_PANEL_ORIENT_BOTTOM:
984 evas_object_resize(sd->scr_ly, w, (1 + sd->content_size_ratio) * h);
985 evas_object_size_hint_min_set(sd->scr_panel, w, (sd->content_size_ratio * h));
986 evas_object_size_hint_min_set(sd->scr_event, w, h);
988 case ELM_PANEL_ORIENT_LEFT:
989 case ELM_PANEL_ORIENT_RIGHT:
991 evas_object_resize(sd->scr_ly, (1 + sd->content_size_ratio) * w, h);
992 evas_object_size_hint_min_set(sd->scr_panel, (sd->content_size_ratio * w), h);
993 evas_object_size_hint_min_set(sd->scr_event, w, h);
997 //Close/Open the drawer after sizing calculation is finished.
998 if (sd->animator) ecore_animator_del(sd->animator);
999 sd->animator = ecore_animator_add(_elm_panel_anim_cb, obj);
1003 _elm_panel_smart_member_add(Evas_Object *obj, Evas_Object *member)
1005 ELM_PANEL_DATA_GET(obj, sd);
1006 ELM_WIDGET_CLASS(_elm_panel_parent_sc)->base.member_add(obj, member);
1008 if (sd->hit_rect) evas_object_raise(sd->hit_rect);
1012 _elm_panel_smart_access(Evas_Object *obj, Eina_Bool is_access)
1014 ELM_PANEL_CHECK(obj);
1015 ELM_PANEL_DATA_GET(obj, sd);
1020 _access_obj_process(obj, is_access);
1025 _elm_access_edje_object_part_object_register
1026 (obj, ELM_WIDGET_DATA(sd)->resize_obj, "btn_icon");
1028 _elm_access_edje_object_part_object_unregister
1029 (obj, ELM_WIDGET_DATA(sd)->resize_obj, "btn_icon");
1032 static Evas_Object *
1033 _elm_panel_smart_access_object_get(Evas_Object *obj, char *part)
1035 ELM_PANEL_CHECK(obj) NULL;
1036 ELM_PANEL_DATA_GET(obj, sd);
1038 if (sd->scrollable && sd->scr_ly)
1039 return _access_object_get(obj, part);
1045 _elm_panel_smart_disable(Evas_Object *obj)
1047 ELM_PANEL_DATA_GET(obj, sd);
1051 if (elm_widget_disabled_get(obj))
1053 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_DOWN,
1055 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_MOVE,
1057 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_UP,
1059 evas_object_event_callback_del(sd->scr_event, EVAS_CALLBACK_MOUSE_UP,
1064 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
1065 _on_mouse_down, sd);
1066 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
1067 _on_mouse_move, sd);
1068 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
1070 evas_object_event_callback_add(sd->scr_event, EVAS_CALLBACK_MOUSE_UP,
1071 _event_mouse_up, obj);
1079 _elm_panel_smart_set_user(Elm_Panel_Smart_Class *sc)
1081 ELM_WIDGET_CLASS(sc)->base.add = _elm_panel_smart_add;
1082 ELM_WIDGET_CLASS(sc)->base.del = _elm_panel_smart_del;
1083 ELM_WIDGET_CLASS(sc)->base.move = _elm_panel_smart_move;
1084 ELM_WIDGET_CLASS(sc)->base.resize = _elm_panel_smart_resize;
1085 ELM_WIDGET_CLASS(sc)->base.member_add = _elm_panel_smart_member_add;
1087 ELM_WIDGET_CLASS(sc)->focus_next = _elm_panel_smart_focus_next;
1088 ELM_WIDGET_CLASS(sc)->theme = _elm_panel_smart_theme;
1089 ELM_WIDGET_CLASS(sc)->event = _elm_panel_smart_event;
1090 ELM_WIDGET_CLASS(sc)->access = _elm_panel_smart_access;
1091 ELM_WIDGET_CLASS(sc)->access_object_get = _elm_panel_smart_access_object_get;
1092 ELM_WIDGET_CLASS(sc)->disable = _elm_panel_smart_disable;
1093 ELM_WIDGET_CLASS(sc)->orientation_set = _elm_panel_smart_orientation_set;
1095 ELM_CONTAINER_CLASS(sc)->content_set = _elm_panel_smart_content_set;
1096 ELM_CONTAINER_CLASS(sc)->content_get = _elm_panel_smart_content_get;
1097 ELM_CONTAINER_CLASS(sc)->content_unset = _elm_panel_smart_content_unset;
1099 ELM_LAYOUT_CLASS(sc)->sizing_eval = _elm_panel_smart_sizing_eval;
1103 _anim_stop_cb(Evas_Object *obj, void *data EINA_UNUSED)
1105 if (elm_widget_disabled_get(obj)) return;
1110 _scroll_cb(Evas_Object *obj, void *data EINA_UNUSED)
1112 ELM_PANEL_DATA_GET(obj, sd);
1113 Elm_Panel_Scroll_Info event;
1114 Evas_Coord x, y, w, h;
1116 if (elm_widget_disabled_get(obj)) return;
1118 // freeze_set(FALSE) -> mouse_up -> freeze_set(TRUE) -> scroll
1121 sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_NO_BLOCK);
1122 sd->freeze = EINA_FALSE;
1123 elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
1124 elm_object_signal_emit(obj, "elm,state,unhold", "elm");
1127 sd->s_iface->content_pos_get(obj, &x, &y);
1128 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1132 case ELM_PANEL_ORIENT_TOP:
1134 event.rel_y = 1 - ((double) y / (double) ((sd->content_size_ratio) * h));
1136 case ELM_PANEL_ORIENT_BOTTOM:
1138 event.rel_y = (double) y / (double) ((sd->content_size_ratio) * h);
1140 case ELM_PANEL_ORIENT_LEFT:
1141 event.rel_x = 1 - ((double) x / (double) ((sd->content_size_ratio) * w));
1144 case ELM_PANEL_ORIENT_RIGHT:
1145 event.rel_x = (double) x / (double) ((sd->content_size_ratio) * w);
1149 evas_object_smart_callback_call(obj, SIG_SCROLL, (void *) &event);
1152 EAPI const Elm_Panel_Smart_Class *
1153 elm_panel_smart_class_get(void)
1155 static Elm_Panel_Smart_Class _sc =
1156 ELM_PANEL_SMART_CLASS_INIT_NAME_VERSION(ELM_PANEL_SMART_NAME);
1157 static const Elm_Panel_Smart_Class *class = NULL;
1159 if (class) return class;
1161 _elm_panel_smart_set(&_sc);
1168 elm_panel_add(Evas_Object *parent)
1172 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1174 obj = elm_widget_add(_elm_panel_smart_class_new(), parent);
1175 if (!obj) return NULL;
1177 if (!elm_widget_sub_object_add(parent, obj))
1178 ERR("could not add %p as sub object of %p", obj, parent);
1180 ELM_PANEL_DATA_GET(obj, sd);
1182 elm_widget_can_focus_set(obj, EINA_TRUE);
1184 /* just to bootstrap and have theme hook to work */
1185 elm_layout_theme_set(obj, "panel", "top", elm_widget_style_get(obj));
1187 _elm_panel_smart_theme(obj);
1189 elm_widget_can_focus_set(obj, EINA_TRUE);
1191 sd->hidden = EINA_FALSE;
1193 sd->bx = evas_object_box_add(evas_object_evas_get(obj));
1194 evas_object_size_hint_align_set(sd->bx, 0.5, 0.5);
1195 evas_object_box_layout_set(sd->bx, _box_layout_cb, sd, NULL);
1196 elm_layout_content_set(obj, "elm.swallow.content", sd->bx);
1197 evas_object_show(sd->bx);
1199 elm_layout_signal_callback_add
1200 (obj, "elm,action,panel,toggle", "*", _panel_toggle, obj);
1202 _mirrored_set(obj, elm_widget_mirrored_get(obj));
1204 elm_layout_sizing_eval(obj);
1206 //Tizen Only: This should be removed when eo is applied.
1207 ELM_WIDGET_DATA_GET(obj, wsd);
1208 wsd->on_create = EINA_FALSE;
1209 wsd->highlight_root = EINA_TRUE;
1211 sd->panel_edje = wsd->resize_obj;
1217 elm_panel_orient_set(Evas_Object *obj,
1218 Elm_Panel_Orient orient)
1220 ELM_PANEL_CHECK(obj);
1221 ELM_PANEL_DATA_GET(obj, sd);
1223 if (sd->orient == orient) return;
1224 sd->orient = orient;
1226 if (sd->scrollable) _scrollable_layout_theme_set(obj, sd);
1227 else _orient_set_do(obj);
1229 elm_layout_sizing_eval(obj);
1232 EAPI Elm_Panel_Orient
1233 elm_panel_orient_get(const Evas_Object *obj)
1235 ELM_PANEL_CHECK(obj) ELM_PANEL_ORIENT_LEFT;
1236 ELM_PANEL_DATA_GET(obj, sd);
1242 elm_panel_hidden_set(Evas_Object *obj,
1245 ELM_PANEL_CHECK(obj);
1246 ELM_PANEL_DATA_GET(obj, sd);
1248 if (sd->hidden == hidden)
1250 if (sd->hidden && !sd->freeze)
1253 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1254 _drawer_close(obj, w, h, EINA_TRUE);
1259 _panel_toggle(NULL, obj, NULL, NULL);
1263 elm_panel_hidden_get(const Evas_Object *obj)
1265 ELM_PANEL_CHECK(obj) EINA_FALSE;
1266 ELM_PANEL_DATA_GET(obj, sd);
1272 elm_panel_toggle(Evas_Object *obj)
1274 ELM_PANEL_CHECK(obj);
1276 _panel_toggle(NULL, obj, NULL, NULL);
1280 elm_panel_scrollable_set(Evas_Object *obj, Eina_Bool scrollable)
1282 ELM_PANEL_DATA_GET(obj, sd);
1284 scrollable = !!scrollable;
1285 if (sd->scrollable == scrollable) return;
1286 sd->scrollable = scrollable;
1290 elm_layout_content_unset(obj, "elm.swallow.content");
1292 elm_widget_resize_object_set(obj, NULL, EINA_TRUE);
1293 elm_widget_sub_object_add(obj, sd->panel_edje);
1297 const char *handler_size;
1299 sd->scr_edje = edje_object_add(evas_object_evas_get(obj));
1300 elm_widget_theme_object_set(obj, sd->scr_edje, "scroller", "panel",
1301 elm_widget_style_get(obj));
1302 evas_object_size_hint_weight_set
1303 (sd->scr_edje, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1304 evas_object_size_hint_align_set
1305 (sd->scr_edje, EVAS_HINT_FILL, EVAS_HINT_FILL);
1307 handler_size = edje_object_data_get(sd->scr_edje, "handler_size");
1309 sd->handler_size = (Evas_Coord) (elm_object_scale_get(obj)) * (atoi(handler_size));
1312 elm_widget_resize_object_set(obj, sd->scr_edje, EINA_TRUE);
1314 //Temporary code: will be removed after elm_panel_scrollable_content_size_set is applied
1315 if (elm_win_rotation_get(elm_widget_top_get(obj)) == 90 || elm_win_rotation_get(elm_widget_top_get(obj)) == 270)
1316 sd->content_size_ratio = 0.45;
1318 sd->content_size_ratio = 0.80;
1322 sd->s_iface = evas_object_smart_interface_get
1323 (obj, ELM_SCROLLABLE_IFACE_NAME);
1325 sd->hit_rect = evas_object_rectangle_add(evas_object_evas_get(obj));
1326 evas_object_smart_member_add(sd->hit_rect, obj);
1327 elm_widget_sub_object_add(obj, sd->hit_rect);
1328 evas_object_color_set(sd->hit_rect, 0, 0, 0, 0);
1329 evas_object_show(sd->hit_rect);
1330 evas_object_repeat_events_set(sd->hit_rect, EINA_TRUE);
1332 sd->s_iface->objects_set(obj, sd->scr_edje, sd->hit_rect);
1333 sd->s_iface->animate_stop_cb_set(obj, _anim_stop_cb);
1334 sd->s_iface->scroll_cb_set(obj, _scroll_cb);
1339 sd->scr_ly = elm_layout_add(obj);
1340 evas_object_smart_member_add(sd->scr_ly, obj);
1341 elm_widget_sub_object_add(obj, sd->scr_ly);
1342 _scrollable_layout_theme_set(obj, sd);
1344 sd->scr_panel = evas_object_rectangle_add(evas_object_evas_get(obj));
1345 evas_object_color_set(sd->scr_panel, 0, 0, 0, 0);
1346 elm_widget_sub_object_add(obj, sd->scr_panel);
1347 elm_layout_content_set(sd->scr_ly, "panel_area", sd->scr_panel);
1349 sd->scr_event = evas_object_rectangle_add(evas_object_evas_get(obj));
1350 evas_object_color_set(sd->scr_event, 0, 0, 0, 0);
1351 elm_widget_sub_object_add(obj, sd->scr_event);
1352 elm_layout_content_set(sd->scr_ly, "event_area", sd->scr_event);
1355 sd->s_iface->content_set(obj, sd->scr_ly);
1356 sd->freeze = EINA_TRUE;
1357 elm_layout_content_set(sd->scr_ly, "elm.swallow.content", sd->bx);
1361 case ELM_PANEL_ORIENT_TOP:
1362 case ELM_PANEL_ORIENT_BOTTOM:
1363 sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_BLOCK_VERTICAL);
1365 case ELM_PANEL_ORIENT_LEFT:
1366 case ELM_PANEL_ORIENT_RIGHT:
1367 sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_BLOCK_HORIZONTAL);
1371 sd->s_iface->single_direction_set(obj, ELM_SCROLLER_SINGLE_DIRECTION_NONE);
1373 if (!elm_widget_disabled_get(obj))
1375 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
1376 _on_mouse_down, sd);
1377 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
1378 _on_mouse_move, sd);
1379 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
1381 evas_object_event_callback_add(sd->scr_event, EVAS_CALLBACK_MOUSE_UP,
1382 _event_mouse_up, obj);
1387 sd->s_iface->content_set(obj, NULL);
1389 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_DOWN, _on_mouse_down);
1390 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_MOVE, _on_mouse_move);
1391 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_UP, _on_mouse_up);
1392 evas_object_event_callback_del(sd->scr_event, EVAS_CALLBACK_MOUSE_UP,
1395 elm_widget_resize_object_set(obj, NULL, EINA_TRUE);
1396 elm_widget_sub_object_add(obj, sd->scr_edje);
1398 elm_widget_resize_object_set(obj, sd->panel_edje, EINA_TRUE);
1400 elm_layout_content_unset(sd->scr_ly, "elm.swallow.content");
1401 elm_layout_content_set(obj, "elm.swallow.content", sd->bx);
1406 elm_panel_scrollable_get(const Evas_Object *obj)
1408 ELM_PANEL_DATA_GET(obj, sd);
1410 return sd->scrollable;
1414 elm_panel_scrollable_content_size_set(Evas_Object *obj, double ratio)
1417 ELM_PANEL_DATA_GET(obj, sd);
1419 sd->content_size_ratio = ratio;
1420 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1424 case ELM_PANEL_ORIENT_TOP:
1425 case ELM_PANEL_ORIENT_BOTTOM:
1427 evas_object_resize(sd->scr_ly, w, (1 + sd->content_size_ratio) * h);
1428 evas_object_size_hint_min_set(sd->scr_panel, w, (sd->content_size_ratio * h));
1429 evas_object_size_hint_min_set(sd->scr_event, w, h);
1431 case ELM_PANEL_ORIENT_LEFT:
1432 case ELM_PANEL_ORIENT_RIGHT:
1434 evas_object_resize(sd->scr_ly, (1 + sd->content_size_ratio) * w, h);
1435 evas_object_size_hint_min_set(sd->scr_panel, (sd->content_size_ratio * w), h);
1436 evas_object_size_hint_min_set(sd->scr_event, w, h);
1440 if (sd->animator) ecore_animator_del(sd->animator);
1441 sd->animator = ecore_animator_add(_elm_panel_anim_cb, obj);