From 11ec774ac808cb171a1975c0c0aed03e1bd90fa4 Mon Sep 17 00:00:00 2001 From: ChunEon Park Date: Mon, 10 Jan 2011 08:59:40 +0000 Subject: [PATCH] From: ChunEon Park Subject: [PATCH] elc_ctxpopup Here code is for the ctxpopup. Since the functionalities of ctxpopup are somewhat different, I'm trying to overwrite the ctxpopup code entirely first. The main reason is, Original ctxpopup could determine it's size and position by itself. Of course, upstreamed version supports this. But it can not be reduced it's size And it supposes the arrow position to center of box edje. Basically, This version calculates it's box size first then find available space from the it's position. The origin position of the box is not expected, it finds the available positions. But if there is not enough space to be shown, then it finds a best direction to be shown again. In this case, it reduces it's size also as to be shown entirely. Since the ctxpopup supports scroller, the reduced box could show the all items also. (The point is ctxpopup should know the size of total items...) I'm not sure the upstreamed version could cover the above scenario, If then, I need to modify it first. (fixed some minor formatting issue too) SVN revision: 56021 --- data/themes/default.edc | 1024 ++++++++++++-------------------- src/bin/test_ctxpopup.c | 203 ++++--- src/lib/Elementary.h.in | 43 +- src/lib/elc_ctxpopup.c | 1482 +++++++++++++++++++++++++++++++++++------------ 4 files changed, 1638 insertions(+), 1114 deletions(-) diff --git a/data/themes/default.edc b/data/themes/default.edc index 893476e..e457e5d 100644 --- a/data/themes/default.edc +++ b/data/themes/default.edc @@ -7406,575 +7406,8 @@ collections { } } } - /////////////////////////////////////////////////////////////////////////////// - group { name: "elm/hover/base/ctxpopup/default"; - images { - image: "bt_base2.png" COMP; - image: "bt_hilight.png" COMP; - image: "bt_shine.png" COMP; - image: "icon_arrow_left.png" COMP; - image: "icon_arrow_up_left.png" COMP; - image: "icon_arrow_up.png" COMP; - image: "icon_arrow_up_right.png" COMP; - image: "icon_arrow_right.png" COMP; - image: "icon_arrow_down_right.png" COMP; - image: "icon_arrow_down.png" COMP; - image: "icon_arrow_down_left.png" COMP; - } - parts { - part { name: "elm.swallow.offset"; - type: SWALLOW; - description { state: "default" 0.0; - align: 0.0 0.0; - rel1.relative: 0.0 0.0; - rel2.relative: 0.0 0.0; - } - } - part { name: "elm.swallow.size"; - type: SWALLOW; - description { state: "default" 0.0; - align: 0.0 0.0; - rel1.to: "elm.swallow.offset"; - rel1.relative: 1.0 1.0; - rel2.to: "elm.swallow.offset"; - rel2.relative: 1.0 1.0; - } - } - part { name: "button_image"; - mouse_events: 1; - description { state: "default" 0.0; - image { - normal: "bt_base2.png"; - border: 7 7 7 7; - } - image.middle: SOLID; - } - description { state: "top-left" 0.0; - inherit: "default" 0.0; - visible: 1; - rel1.to: "elm.swallow.slot.top-left"; - rel1.offset: -2 -6; - rel2.to: "elm.swallow.slot.top-left"; - rel2.offset: 1 7; - } - description { state: "top" 0.0; - inherit: "default" 0.0; - visible: 1; - rel1.to: "elm.swallow.slot.top"; - rel1.offset: -2 -6; - rel2.to: "elm.swallow.slot.top"; - rel2.offset: 1 7; - } - description { state: "top-right" 0.0; - inherit: "default" 0.0; - visible: 1; - rel1.to: "elm.swallow.slot.top-right"; - rel1.offset: -2 -6; - rel2.to: "elm.swallow.slot.top-right"; - rel2.offset: 1 7; - } - description { state: "right" 0.0; - inherit: "default" 0.0; - visible: 1; - rel1.to: "elm.swallow.slot.right"; - rel1.offset: -2 -6; - rel2.to: "elm.swallow.slot.right"; - rel2.offset: 1 7; - } - description { state: "bottom-right" 0.0; - inherit: "default" 0.0; - visible: 1; - rel1.to: "elm.swallow.slot.bottom-right"; - rel1.offset: -2 -6; - rel2.to: "elm.swallow.slot.bottom-right"; - rel2.offset: 1 7; - } - description { state: "bottom" 0.0; - inherit: "default" 0.0; - visible: 1; - rel1.to: "elm.swallow.slot.bottom"; - rel1.offset: -2 -6; - rel2.to: "elm.swallow.slot.bottom"; - rel2.offset: 1 7; - } - description { state: "bottom-left" 0.0; - inherit: "default" 0.0; - visible: 1; - rel1.to: "elm.swallow.slot.bottom-left"; - rel1.offset: -2 -6; - rel2.to: "elm.swallow.slot.bottom-left"; - rel2.offset: 1 7; - } - description { state: "left" 0.0; - inherit: "default" 0.0; - visible: 1; - rel1.to: "elm.swallow.slot.left"; - rel1.offset: -2 -6; - rel2.to: "elm.swallow.slot.left"; - rel2.offset: 1 7; - } - } - part { name: "base"; - type: RECT; - mouse_events: 1; - description { state: "default" 0.0; - color: 0 0 0 0; - } - description { state: "visible" 0.0; - inherit: "default" 1.0; - color: 0 0 0 64; - } - } - part { name: "elm.swallow.slot.left"; - type: SWALLOW; - description { state: "default" 0.0; - align: 1.0 0.5; - rel1.to: "elm.swallow.slot.middle"; - rel1.relative: 0.0 0.0; - rel1.offset: -1 0; - rel2.to: "elm.swallow.slot.middle"; - rel2.relative: 0.0 1.0; - rel2.offset: -1 -1; - } - } - part { name: "elm.swallow.slot.top-left"; - type: SWALLOW; - description { state: "default" 0.0; - align: 1.0 1.0; - rel1.to: "elm.swallow.slot.middle"; - rel1.relative: 0.0 0.0; - rel1.offset: 0 0; - rel2.to: "elm.swallow.slot.middle"; - rel2.relative: 0.0 0.0; - rel2.offset: -1 -1; - } - } - part { name: "elm.swallow.slot.top"; - type: SWALLOW; - description { state: "default" 0.0; - align: 0.5 1.0; - rel1.to: "elm.swallow.slot.middle"; - rel1.relative: 0.0 0.0; - rel1.offset: 0 -1; - rel2.to: "elm.swallow.slot.middle"; - rel2.relative: 1.0 0.0; - rel2.offset: -1 -1; - } - } - part { name: "elm.swallow.slot.top-right"; - type: SWALLOW; - description { state: "default" 0.0; - align: 0.0 1.0; - rel1.to: "elm.swallow.slot.middle"; - rel1.relative: 1.0 0.0; - rel1.offset: 0 0; - rel2.to: "elm.swallow.slot.middle"; - rel2.relative: 1.0 0.0; - rel2.offset: -1 -1; - } - } - part { name: "elm.swallow.slot.right"; - type: SWALLOW; - description { state: "default" 0.0; - align: 0.0 0.5; - rel1.to: "elm.swallow.slot.middle"; - rel1.relative: 1.0 0.0; - rel1.offset: 0 0; - rel2.to: "elm.swallow.slot.middle"; - rel2.relative: 1.0 1.0; - rel2.offset: 0 -1; - } - } - part { name: "elm.swallow.slot.bottom-right"; - type: SWALLOW; - description { state: "default" 0.0; - align: 0.0 0.0; - rel1.to: "elm.swallow.slot.middle"; - rel1.relative: 1.0 1.0; - rel1.offset: 0 0; - rel2.to: "elm.swallow.slot.middle"; - rel2.relative: 1.0 1.0; - rel2.offset: -1 -1; - } - } - part { name: "elm.swallow.slot.bottom"; - type: SWALLOW; - description { state: "default" 0.0; - align: 0.5 0.0; - rel1.to: "elm.swallow.slot.middle"; - rel1.relative: 0.0 1.0; - rel1.offset: 0 0; - rel2.to: "elm.swallow.slot.middle"; - rel2.relative: 1.0 1.0; - rel2.offset: -1 0; - } - } - part { name: "elm.swallow.slot.bottom-left"; - type: SWALLOW; - description { state: "default" 0.0; - align: 1.0 0.0; - rel1.to: "elm.swallow.slot.middle"; - rel1.relative: 0.0 1.0; - rel1.offset: 0 0; - rel2.to: "elm.swallow.slot.middle"; - rel2.relative: 0.0 1.0; - rel2.offset: -1 0; - } - } - part { name: "over1"; - mouse_events: 0; - description { state: "default" 0.0; - rel1.to: "button_image"; - rel2.to: "button_image"; - rel2.relative: 1.0 0.5; - image { - normal: "bt_hilight.png"; - border: 7 7 7 0; - } - } - } - part { name: "over2"; - mouse_events: 1; - repeat_events: 1; - ignore_flags: ON_HOLD; - description { state: "default" 0.0; - rel1.to: "button_image"; - rel2.to: "button_image"; - image { - normal: "bt_shine.png"; - border: 7 7 7 7; - } - } - } - part { name: "elm.swallow.slot.middle"; - type: SWALLOW; - description { state: "default" 0.0; - rel1.to: "elm.swallow.size"; - rel2.to: "elm.swallow.size"; - } - } - part { name: "arrow"; - mouse_events: 0; - description { state: "default" 0.0; - visible: 0; - min: 40 40; - max: 40 40; - } - description { state: "left" 0.0; - inherit: "default" 0.0; - visible: 1; - align: 0.0 0.5; - rel1.to: "elm.swallow.slot.left"; - rel1.relative: 1.0 0.0; - rel1.offset: 0 0; - rel2.to: "elm.swallow.slot.left"; - rel2.relative: 1.0 1.0; - rel2.offset: 0 -1; - image.normal: "icon_arrow_right.png"; - } - description { state: "top-left" 0.0; - inherit: "default" 0.0; - visible: 1; - align: 0.0 0.0; - rel1.to: "elm.swallow.slot.top-left"; - rel1.relative: 1.0 1.0; - rel1.offset: -5 5; - rel2.to: "elm.swallow.slot.top-left"; - rel2.relative: 1.0 1.0; - rel2.offset: -4 4; - image.normal: "icon_arrow_down_right.png"; - } - description { state: "top" 0.0; - inherit: "default" 0.0; - visible: 1; - align: 0.5 0.0; - rel1.to: "elm.swallow.slot.top"; - rel1.relative: 0.0 1.0; - rel1.offset: 0 0; - rel2.to: "elm.swallow.slot.top"; - rel2.relative: 1.0 1.0; - rel2.offset: -1 0; - image.normal: "icon_arrow_down.png"; - } - description { state: "top-right" 0.0; - inherit: "default" 0.0; - visible: 1; - align: 1.0 0.0; - rel1.to: "elm.swallow.slot.top-right"; - rel1.relative: 0.0 1.0; - rel1.offset: 5 5; - rel2.to: "elm.swallow.slot.top-right"; - rel2.relative: 0.0 1.0; - rel2.offset: 4 4; - image.normal: "icon_arrow_down_left.png"; - } - description { state: "right" 0.0; - inherit: "default" 0.0; - visible: 1; - align: 1.0 0.5; - rel1.to: "elm.swallow.slot.right"; - rel1.relative: 0.0 0.0; - rel1.offset: 0 0; - rel2.to: "elm.swallow.slot.right"; - rel2.relative: 0.0 1.0; - rel2.offset: 0 -1; - image.normal: "icon_arrow_left.png"; - } - description { state: "bottom-right" 0.0; - inherit: "default" 0.0; - visible: 1; - align: 1.0 1.0; - rel1.to: "elm.swallow.slot.bottom-right"; - rel1.relative: 0.0 0.0; - rel1.offset: 5 5; - rel2.to: "elm.swallow.slot.bottom-right"; - rel2.relative: 0.0 0.0; - rel2.offset: 4 4; - image.normal: "icon_arrow_up_left.png"; - } - description { state: "bottom" 0.0; - inherit: "default" 0.0; - visible: 1; - align: 0.5 1.0; - rel1.to: "elm.swallow.slot.bottom"; - rel1.relative: 0.0 0.0; - rel1.offset: 0 -1; - rel2.to: "elm.swallow.slot.bottom"; - rel2.relative: 1.0 0.0; - rel2.offset: -1 -1; - image.normal: "icon_arrow_up.png"; - } - description { state: "bottom-left" 0.0; - inherit: "default" 0.0; - visible: 1; - align: 0.0 1.0; - rel1.to: "elm.swallow.slot.bottom-left"; - rel1.relative: 1.0 0.0; - rel1.offset: -5 5; - rel2.to: "elm.swallow.slot.bottom-left"; - rel2.relative: 1.0 0.0; - rel2.offset: -4 4; - image.normal: "icon_arrow_up_right.png"; - } - } - } - programs { - program { name: "end"; - signal: "mouse,up,1"; - source: "base"; - action: SIGNAL_EMIT "elm,action,dismiss" ""; - } - program { name: "show"; - signal: "elm,action,show"; - source: "elm"; - action: STATE_SET "visible" 0.0; - target: "base"; - } - program { name: "hide"; - signal: "elm,action,hide"; - source: "elm"; - action: STATE_SET "default" 0.0; - target: "base"; - } - program { name: "all-hide"; - action: STATE_SET "default" 0.0; - target: "button_image"; - } - program { name: "top-left-show"; - signal: "elm,action,slot,top-left,show"; - source: "elm"; - action: STATE_SET "top-left" 0.0; - target: "arrow"; - target: "button_image"; - } - program { name: "top-show"; - signal: "elm,action,slot,top,show"; - source: "elm"; - action: STATE_SET "top" 0.0; - target: "arrow"; - target: "button_image"; - } - program { name: "top-right-show"; - signal: "elm,action,slot,top-right,show"; - source: "elm"; - action: STATE_SET "top-right" 0.0; - target: "arrow"; - target: "button_image"; - } - program { name: "right-show"; - signal: "elm,action,slot,right,show"; - source: "elm"; - action: STATE_SET "right" 0.0; - target: "arrow"; - target: "button_image"; - } - program { name: "bottom-right-show"; - signal: "elm,action,slot,bottom-right,show"; - source: "elm"; - action: STATE_SET "bottom-right" 0.0; - target: "arrow"; - target: "button_image"; - } - program { name: "bottom-show"; - signal: "elm,action,slot,bottom,show"; - source: "elm"; - action: STATE_SET "bottom" 0.0; - target: "arrow"; - target: "button_image"; - } - program { name: "bottom-left-show"; - signal: "elm,action,slot,bottom-left,show"; - source: "elm"; - action: STATE_SET "bottom-left" 0.0; - target: "arrow"; - target: "button_image"; - } - program { name: "left-show"; - signal: "elm,action,slot,left,show"; - source: "elm"; - action: STATE_SET "left" 0.0; - target: "arrow"; - target: "button_image"; - } - } - } - -/////////////////////////////////////////////////////////////////////////////// - group { name: "elm/list/item/ctxpopup"; - alias: "elm/list/item_odd/ctxpopup"; - alias: "elm/list/h_item/ctxpopup"; - alias: "elm/list/h_item_odd/ctxpopup"; - parts { - part { name: "button_image"; - mouse_events: 1; - clip_to: "disclip"; - description { state: "default" 0.0; - color: 255 255 255 0; - image.normal: "hoversel_entry_bg.png"; - image.border: 0 0 2 2; - fill.smooth: 0; - } - description { state: "selected" 0.0; - inherit: "default" 0.0; - color: 255 255 255 255; - } - } - part { name: "elm.swallow.icon"; - type: SWALLOW; - clip_to: "disclip"; - description { state: "default" 0.0; - fixed: 1 0; - align: 0.0 0.5; - rel1 { - relative: 0.0 0.0; - offset: 4 4; - } - rel2 { - relative: 0.0 1.0; - offset: 4 -5; - } - } - } - part { name: "elm.text"; - type: TEXT; - effect: SOFT_SHADOW; - mouse_events: 0; - scale: 1; - clip_to: "disclip"; - description { - state: "default" 0.0; - rel1 { - to_x: "elm.swallow.icon"; - relative: 1.0 0.0; - offset: 4 4; - } - rel2 { - offset: -5 -5; - } - color: 224 224 224 255; - color3: 0 0 0 64; - text { - font: "Sans,Edje-Vera"; - size: 10; - min: 1 1; - align: 0.0 0.5; - text_class: "list_item"; - } - } - description { state: "selected" 0.0; - inherit: "default" 0.0; - text.min: 1 1; - color: 0 0 0 255; - color3: 0 0 0 0; - } - } - part { name: "event"; - type: RECT; - repeat_events: 1; - description { - state: "default" 0.0; - color: 0 0 0 0; - } - } - part { name: "disclip"; - type: RECT; - repeat_events: 1; - description { state: "default" 0.0; - rel1.to: "event"; - rel2.to: "event"; - } - description { state: "disabled" 0.0; - inherit: "default" 0.0; - color: 255 255 255 64; - } - } - } - programs { - program { - name: "go_active"; - signal: "elm,state,selected"; - source: "elm"; - action: STATE_SET "selected" 0.0; - target: "elm.text"; - target: "button_image"; - } - program { - name: "item_unclick"; - signal: "mouse,up,1"; - source: "event"; - action: STATE_SET "default" 0.0; - target: "button_image"; - target: "elm.text"; - } - program { - name: "go_passive"; - signal: "elm,state,unselected"; - source: "elm"; - action: STATE_SET "default" 0.0; - target: "elm.text"; - target: "button_image"; - transition: LINEAR 0.1; - } - program { - name: "go_disabled"; - signal: "elm,state,disabled"; - source: "elm"; - action: STATE_SET "disabled" 0.0; - target: "disclip"; - } - program { - name: "go_enabled"; - signal: "elm,state,enabled"; - source: "elm"; - action: STATE_SET "default" 0.0; - target: "disclip"; - } - } - } - -/////////////////////////////////////////////////////////////////////////////// - group { name: "elm/list/base/ctxpopup"; + group { name: "elm/scroller/base/ctxpopup"; data { item: "focus_highlight" "on"; } @@ -7985,7 +7418,7 @@ collections { v = get_int(sbvis_v); if (v) { v = get_int(sbalways_v); - if (!v) { + if(!v) { emit("do-hide-vbar", ""); set_int(sbvis_v, 0); } @@ -7993,7 +7426,7 @@ collections { v = get_int(sbvis_h); if (v) { v = get_int(sbalways_h); - if (!v) { + if(!v) { emit("do-hide-hbar", ""); set_int(sbvis_h, 0); } @@ -8009,32 +7442,19 @@ collections { image: "sl_bt2_2.png" COMP; } parts { - part { name: "bg"; - type: RECT; - description { state: "default" 0.0; - rel1.offset: 2 2; - rel2.offset: -3 -3; - color: 255 255 255 0; - } - } part { name: "clipper"; type: RECT; mouse_events: 0; + scale: 1; description { state: "default" 0.0; - rel1.to: "bg"; - rel2.to: "bg"; - rel1.offset: 2 2; - rel2.offset: -3 -3; } } part { name: "elm.swallow.content"; clip_to: "clipper"; type: SWALLOW; + scale: 1; description { state: "default" 0.0; - rel1.to: "bg"; - rel2.to: "bg"; - rel1.offset: 2 2; - rel2.offset: -3 -3; + align: 0.5 0.5; } } part { name: "focus_highlight"; @@ -8042,8 +7462,7 @@ collections { description { state: "default" 0.0; rel1.offset: -1 -1; rel2.offset: 0 0; - image { - normal: "sl_bt2_2.png"; + image { normal: "sl_bt2_2.png"; border: 7 7 7 7; middle: 0; } @@ -8064,12 +7483,15 @@ collections { visible: 0; color: 255 255 255 0; } - } + } part { name: "sb_vbar_clip"; - clip_to: "sb_vbar_clip_master"; + clip_to:"sb_vbar_clip_master"; type: RECT; mouse_events: 0; + scale: 1; description { state: "default" 0.0; + align: 0.0 0.0; + rel2{ to:"clipper"; relative: 1.0 1.0;} } description { state: "hidden" 0.0; visible: 0; @@ -8079,28 +7501,19 @@ collections { part { name: "sb_vbar"; type: RECT; mouse_events: 0; + scale: 1; description { state: "default" 0.0; fixed: 1 1; visible: 0; - min: 10 17; align: 1.0 0.0; - rel1 { - relative: 1.0 0.0; - offset: 0 2; - to_y: "elm.swallow.content"; - to_x: "elm.swallow.content"; - } - rel2 { - relative: 1.0 0.0; - offset: -1 -1; - to_y: "sb_hbar"; - to_x: "elm.swallow.content"; - } + rel1{ to:"clipper"; relative: 1.0 0.0; } + rel2{ to:"clipper"; relative: 1.0 1.0; } } } part { name: "elm.dragable.vbar"; clip_to: "sb_vbar_clip"; - mouse_events: 0; + mouse_events: 0; + scale: 1; dragable { x: 0 0 0; y: 1 1 0; @@ -8110,18 +7523,9 @@ collections { fixed: 1 1; min: 10 17; max: 10 99999; - rel1 { - relative: 0.5 0.5; - offset: 0 0; - to: "sb_vbar"; - } - rel2 { - relative: 0.5 0.5; - offset: 0 0; - to: "sb_vbar"; - } - image { - normal: "bt_sm_base2.png"; + rel1 { relative: 0.5 0.5; to: "sb_vbar"; } + rel2 { relative: 0.5 0.5; to: "sb_vbar"; } + image { normal: "bt_sm_base2.png"; border: 6 6 6 6; middle: SOLID; } @@ -8134,8 +7538,7 @@ collections { rel1.to: "elm.dragable.vbar"; rel2.relative: 1.0 0.5; rel2.to: "elm.dragable.vbar"; - image { - normal: "bt_sm_hilight.png"; + image { normal: "bt_sm_hilight.png"; border: 6 6 6 0; } } @@ -8146,8 +7549,7 @@ collections { description { state: "default" 0.0; rel1.to: "elm.dragable.vbar"; rel2.to: "elm.dragable.vbar"; - image { - normal: "bt_sm_shine.png"; + image { normal: "bt_sm_shine.png"; border: 6 6 6 0; } } @@ -8161,12 +7563,15 @@ collections { visible: 0; color: 255 255 255 0; } - } + } part { name: "sb_hbar_clip"; clip_to: "sb_hbar_clip_master"; type: RECT; mouse_events: 0; + scale: 1; description { state: "default" 0.0; + align: 0.0 0.0; + rel2{ to:"clipper"; relative: 1.0 1.0;} } description { state: "hidden" 0.0; visible: 0; @@ -8176,49 +7581,31 @@ collections { part { name: "sb_hbar"; type: RECT; mouse_events: 0; - description { state: "default" 0.0; + scale: 1; + description { state: "default" 0.0; fixed: 1 1; visible: 0; - min: 17 10; align: 0.0 1.0; - rel1 { - relative: 0.0 1.0; - offset: 2 0; - to_x: "elm.swallow.content"; - to_y: "elm.swallow.content"; - } - rel2 { - relative: 0.0 1.0; - offset: -1 -1; - to_x: "sb_vbar"; - to_y: "elm.swallow.content"; - } + rel1 { to:"clipper"; relative: 0.0 1.0; } + rel2 { to:"clipper"; relative: 1.0 1.0; } } } part { name: "elm.dragable.hbar"; clip_to: "sb_hbar_clip"; - mouse_events: 0; + mouse_events: 0; + scale: 1; dragable { x: 1 1 0; y: 0 0 0; confine: "sb_hbar"; } description { state: "default" 0.0; - fixed: 1 1; min: 17 10; max: 99999 10; - rel1 { - relative: 0.5 0.5; - offset: 0 0; - to: "sb_hbar"; - } - rel2 { - relative: 0.5 0.5; - offset: 0 0; - to: "sb_hbar"; - } - image { - normal: "bt_sm_base2.png"; + fixed: 1 1; + rel1 { relative: 0.5 0.5; to: "sb_hbar"; } + rel2 { relative: 0.5 0.5; to: "sb_hbar"; } + image { normal: "bt_sm_base2.png"; border: 4 4 4 4; middle: SOLID; } @@ -8231,8 +7618,7 @@ collections { rel1.to: "elm.dragable.hbar"; rel2.relative: 1.0 0.5; rel2.to: "elm.dragable.hbar"; - image { - normal: "bt_sm_hilight.png"; + image { normal: "bt_sm_hilight.png"; border: 6 6 6 0; } } @@ -8243,31 +7629,30 @@ collections { description { state: "default" 0.0; rel1.to: "elm.dragable.hbar"; rel2.to: "elm.dragable.hbar"; - image { - normal: "bt_sm_shine.png"; + image { normal: "bt_sm_shine.png"; border: 6 6 6 0; } } } - } + } programs { program { name: "load"; signal: "load"; source: ""; script { - set_state(PART:"sb_hbar_clip", "hidden", 0.0); set_state(PART:"sb_vbar_clip", "hidden", 0.0); - set_int(sbvis_h, 0); + set_state(PART:"sb_hbar_clip", "hidden", 0.0); set_int(sbvis_v, 0); + set_int(sbvis_h, 0); set_int(sbalways_v, 0); - set_int(sbalways_h, 0); + set_int(sbalways_h, 0); set_int(sbvis_timer, 0); } - } + } program { name: "vbar_show"; signal: "elm,action,show,vbar"; source: "elm"; - action: STATE_SET "default" 0.0; + action: STATE_SET "default" 0.0; target: "sb_vbar_clip_master"; } program { name: "vbar_hide"; @@ -8275,7 +7660,7 @@ collections { source: "elm"; action: STATE_SET "hidden" 0.0; target: "sb_vbar_clip_master"; - } + } program { name: "vbar_show_always"; signal: "elm,action,show_always,vbar"; source: "elm"; @@ -8305,19 +7690,19 @@ collections { } } } - } + } program { name: "sb_vbar_show"; signal: "do-show-vbar"; source: ""; action: STATE_SET "default" 0.0; - transition: LINEAR 0.5; + transition: LINEAR 1.0; target: "sb_vbar_clip"; } program { name: "sb_vbar_hide"; signal: "do-hide-vbar"; source: ""; action: STATE_SET "hidden" 0.0; - transition: LINEAR 0.5; + transition: LINEAR 1.0; target: "sb_vbar_clip"; } program { name: "hbar_show"; @@ -8366,16 +7751,16 @@ collections { signal: "do-show-hbar"; source: ""; action: STATE_SET "default" 0.0; - transition: LINEAR 0.5; + transition: LINEAR 1.0; target: "sb_hbar_clip"; } program { name: "sb_hbar_hide"; signal: "do-hide-hbar"; source: ""; action: STATE_SET "hidden" 0.0; - transition: LINEAR 0.5; + transition: LINEAR 1.0; target: "sb_hbar_clip"; - } + } program { name: "scroll"; signal: "elm,action,scroll"; source: "elm"; @@ -8384,7 +7769,7 @@ collections { v = get_int(sbvis_v); v |= get_int(sbalways_v); if (!v) { - emit("do-show-vbar", ""); + emit("do-show-vbar", "") set_int(sbvis_v, 1); } v = get_int(sbvis_h); @@ -8405,7 +7790,7 @@ collections { action: STATE_SET "enabled" 0.0; transition: ACCELERATE 0.3; target: "focus_highlight"; - } + } program { name: "highlight_hide"; signal: "elm,action,focus_highlight,hide"; source: "elm"; @@ -8413,9 +7798,306 @@ collections { transition: DECELERATE 0.3; target: "focus_highlight"; } + } + } +/////////////////////////////////////////////////////////////////////////////// + group { name: "elm/ctxpopup/bg/default"; + parts { + part { name: "ctxpopup_bg"; + type: RECT; + mouse_events: 1; + description { state: "default" 0.0; + color: 0 0 0 0; + } + description { state: "visible" 0.0; + inherit: "default" 0.0; + color: 0 0 0 64; + } + } + } + programs { + program { name: "clicked_event"; + signal: "mouse,clicked,1"; + source: "ctxpopup_bg"; + action: SIGNAL_EMIT "elm,action,click" ""; + } + program { name: "show"; + signal: "elm,state,show"; + source: "elm"; + action: STATE_SET "visible" 0.0; + target: "ctxpopup_bg"; + } + program { name: "hide"; + signal: "elm,state,hide"; + source: "elm"; + action: STATE_SET "default" 0.0; + target: "ctxpopup_bg"; + } } } - +/////////////////////////////////////////////////////////////////////////////// + group { name: "elm/ctxpopup/base/default"; + images { + image: "bt_base2.png" COMP; + image: "bt_hilight.png" COMP; + image: "bt_shine.png" COMP; + } + parts { + part { name: "base"; + scale: 1; + description { state: "default" 0.0; + rel1.offset: -3 -3; + rel2.offset: 3 3; + image { normal: "bt_base2.png"; + border: 7 7 7 7; + } + } + } + part { name: "over1"; + scale: 1; + description { state: "default" 0.0; + rel1.to: "base"; + rel2.to: "base"; + rel2.relative: 1.0 0.5; + image { normal: "bt_hilight.png"; + border: 7 7 7 0; + } + } + } + part { name: "over2"; + scale: 1; + description { state: "default" 0.0; + rel1.to: "base"; + rel2.to: "base"; + image { normal: "bt_shine.png"; + border: 7 7 7 7; + } + } + } + part { name: "elm.swallow.content"; + type: SWALLOW; + description { state: "default" 0.0; + rel1 { to:"base"; offset: 4 4; }; + rel2 { to:"base"; offset: -5 -5; }; + } + } + } + } +/////////////////////////////////////////////////////////////////////////////// + group { name: "elm/ctxpopup/arrow/default"; + images { + image: "icon_arrow_left.png" COMP; + image: "icon_arrow_right.png" COMP; + image: "icon_arrow_up.png" COMP; + image: "icon_arrow_down.png" COMP; + } + parts { + part { name: "ctxpopup_arrow"; + type: IMAGE; + scale: 1; + description { + state: "default" 0.0; + min: 40 40; + fixed: 1 1; + visible: 0; + align: 0.5 0.5; + } + description { + state: "left" 0.0; + min: 40 40; + fixed: 1 1; + align: 0.0 0.5; + image { normal: "icon_arrow_left.png"; + } + } + description { state: "right" 0.0; + min: 40 40; + fixed: 1 1; + align: 1.0 0.5; + image { normal: "icon_arrow_right.png"; + } + } + description { state: "top" 0.0; + min: 40 40; + fixed: 1 1; + align: 0.5 0.0; + image { normal: "icon_arrow_up.png"; + } + } + description { state: "bottom" 0.0; + min: 40 40; + fixed: 1 1; + align: 0.5 1.0; + image { normal: "icon_arrow_down.png"; + } + } + } + } + programs { + program { name: "enable_left_arrow"; + signal: "elm,state,left"; + source: "elm"; + action: STATE_SET "left" 0.0; + target: "ctxpopup_arrow"; + } + program { name: "enable_right_arrow"; + signal: "elm,state,right"; + source: "elm"; + action: STATE_SET "right" 0.0; + target: "ctxpopup_arrow"; + } + program { name: "enable_top_arrow"; + signal: "elm,state,top"; + source: "elm"; + action: STATE_SET "top" 0.0; + target: "ctxpopup_arrow"; + } + program { name: "enable_bottom_arrow"; + signal: "elm,state,bottom"; + source: "elm"; + action: STATE_SET "bottom" 0.0; + target: "ctxpopup_arrow"; + } + } + } +/////////////////////////////////////////////////////////////////////////////// + group { + name: "elm/ctxpopup/icon_text_style_item/default"; + alias: "elm/ctxpopup/text_style_item/default"; + alias: "elm/ctxpopup/icon_style_item/default"; + images { + image: "hoversel_entry_bg.png" COMP; + } + parts { + part { name: "event"; + mouse_events: 1; + description { state: "default" 0.0; + } + } + part { name: "bg"; + mouse_events: 0; + description { state: "default" 0.0; + rel1.offset: 2 2; + rel2.offset: -3 -3; + image { normal:"hoversel_entry_bg.png"; + border: 0 0 2 2; + } + fill.smooth: 0; + color: 255 255 255 0; + } + description { state: "clicked" 0.0; + inherit: "default" 0.0; + color: 255 255 255 255; + } + } + part { name: "elm.swallow.icon"; + type: SWALLOW; + scale: 1; + description { state: "default" 0.0; + min: 25 25; + max: 25 25; + align: 0 0.5; + aspect: 1.0 1.0; + rel1 { offset: 10 10; } + rel2 { offset: 0 -10; } + } + } + part { name: "elm.text"; + type: TEXT; + mouse_events: 0; + scale: 1; + description { state: "default" 0.0; + min: 1 40; + fixed: 0 1; + align: 0.5 0.5; + rel1 { relative: 1.0 0.0; to: "elm.swallow.icon"; offset: 10 0; } + rel2 { relative: 1.0 1.0; offset: -11 -1; } + color: 255 255 255 255; + text { + font: "Sans"; + size: 10; + align: 0.0 0.5; + min: 1 1; + } + } + description { state: "clicked" 0.0; + inherit: "default" 0.0; + color: 0 0 0 255; + } + } + part { name: "over1"; + mouse_events: 1; + repeat_events: 1; + ignore_flags: ON_HOLD; + description { state: "default" 0.0; + color: 255 255 255 0; + } + description { state: "clicked" 0.0; + inherit: "default" 0.0; + color: 255 255 255 255; + } + } + part { name: "over2"; + mouse_events: 1; + repeat_events: 1; + description { state: "default" 0.0; + color: 255 255 255 0; + } + description { state: "clicked" 0.0; + inherit: "default" 0.0; + color: 255 255 255 255; + } + } + part { name: "disclip"; + type: RECT; + description { state: "default" 0.0; + visible: 0; + } + description { state: "enabled" 0.0; + visible: 1; + color: 50 50 50 127; + rel1.offset: 4 4; + rel2.offset: -5 -5; + } + } + } + programs { + program { + name: "item_unclick"; + signal: "mouse,up,1"; + source: "over1"; + action: SIGNAL_EMIT "elm,action,click" ""; + } + program { name: "disable"; + signal: "elm,state,disabled"; + source: "elm"; + action: STATE_SET "enabled" 0.0; + target: "disclip"; + } + program { name: "enable"; + signal: "elm,state,enabled"; + source: "elm"; + action: STATE_SET "default" 0.0; + target: "disclip"; + } + program { name: "item_click2"; + signal: "mouse,down,1"; + source: "over2"; + script { + set_state(PART:"elm.text", "clicked", 0.0); + set_state(PART:"bg", "clicked", 0.0); + } + } + program { name: "item_unclick2"; + signal: "mouse,up,1"; + source: "over2"; + script { + set_state(PART:"elm.text", "default", 0.0); + set_state(PART:"bg", "default", 0.0); + } + } + } + } /////////////////////////////////////////////////////////////////////////////// // emoticon images from: // Tanya - Latvia @@ -36422,3 +36104,7 @@ collections { } } } + + + + diff --git a/src/bin/test_ctxpopup.c b/src/bin/test_ctxpopup.c index 718d317..f4397a3 100644 --- a/src/bin/test_ctxpopup.c +++ b/src/bin/test_ctxpopup.c @@ -5,18 +5,136 @@ #ifndef ELM_LIB_QUICKLAUNCH static void +_ctxpopup_item_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) +{ + printf("ctxpopup item selected: %s\n", + elm_ctxpopup_item_label_get(event_info)); +} + +#define ITEM_NEW(_hov, _label, _icon) \ + if(_icon) \ + { \ + ic = elm_icon_add(obj); \ + elm_icon_standard_set(ic, _icon); \ + elm_icon_scale_set(ic, EINA_FALSE, EINA_FALSE); \ + } \ + else \ + ic = NULL; \ + it = elm_ctxpopup_item_append(_hov, _label, ic, _ctxpopup_item_cb, NULL); \ + +static void _list_item_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { - evas_object_show(data); + Evas_Object *ctxpopup, *ic; + Elm_Ctxpopup_Item *it; + Evas_Coord x,y; + + ctxpopup = elm_ctxpopup_add(obj); + + ITEM_NEW(ctxpopup, "Go to home folder", "home"); + ITEM_NEW(ctxpopup, "Save file", "file"); + ITEM_NEW(ctxpopup, "Delete file", "delete"); + ITEM_NEW(ctxpopup, "Navigate to folder", "folder"); + elm_ctxpopup_item_disabled_set(it, EINA_TRUE); + ITEM_NEW(ctxpopup, "Edit entry", "edit"); + ITEM_NEW(ctxpopup, "Set date and time", "clock"); + elm_ctxpopup_item_disabled_set(it, EINA_TRUE); + + evas_pointer_output_xy_get(evas_object_evas_get(obj), &x, &y); + evas_object_size_hint_max_set(ctxpopup, 240, 240); + evas_object_move(ctxpopup, x, y); + evas_object_show(ctxpopup); +} + +static void +_list_item_cb2(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Evas_Object *ctxpopup, *ic; + Elm_Ctxpopup_Item *it; + Evas_Coord x,y; + + ctxpopup = elm_ctxpopup_add(obj); + + ITEM_NEW(ctxpopup, NULL, "home"); + ITEM_NEW(ctxpopup, NULL, "file"); + ITEM_NEW(ctxpopup, NULL, "delete"); + ITEM_NEW(ctxpopup, NULL, "folder"); + ITEM_NEW(ctxpopup, NULL, "edit"); + elm_ctxpopup_item_disabled_set(it, EINA_TRUE); + ITEM_NEW(ctxpopup, NULL, "clock"); + + evas_pointer_output_xy_get(evas_object_evas_get(obj), &x, &y); + evas_object_size_hint_max_set(ctxpopup, 240, 240); + evas_object_move(ctxpopup, x, y); + evas_object_show(ctxpopup); } static void -_ctxpopup_item_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) +_list_item_cb3(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { - printf("ctxpopup item selected: %s\n", - elm_ctxpopup_item_label_get(event_info)); + Evas_Object *ctxpopup, *ic; + Elm_Ctxpopup_Item *it; + Evas_Coord x,y; + + ctxpopup = elm_ctxpopup_add(obj); + + ITEM_NEW(ctxpopup, "Eina", NULL); + ITEM_NEW(ctxpopup, "Eet", NULL); + ITEM_NEW(ctxpopup, "Evas", NULL); + ITEM_NEW(ctxpopup, "Ecore", NULL); + elm_ctxpopup_item_disabled_set(it, EINA_TRUE); + ITEM_NEW(ctxpopup, "Embryo", NULL); + ITEM_NEW(ctxpopup, "Edje", NULL); + + evas_pointer_output_xy_get(evas_object_evas_get(obj), &x, &y); + evas_object_move(ctxpopup, x, y); + evas_object_show(ctxpopup); +} + +static void +_list_item_cb4(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Evas_Object *ctxpopup, *ic; + Elm_Ctxpopup_Item *it; + Evas_Coord x,y; + + ctxpopup = elm_ctxpopup_add(obj); + elm_ctxpopup_horizontal_set(ctxpopup, EINA_TRUE); + + ITEM_NEW(ctxpopup, NULL, "home"); + ITEM_NEW(ctxpopup, NULL, "file"); + ITEM_NEW(ctxpopup, NULL, "delete"); + ITEM_NEW(ctxpopup, NULL, "folder"); + ITEM_NEW(ctxpopup, NULL, "edit"); + ITEM_NEW(ctxpopup, NULL, "clock"); + + evas_pointer_output_xy_get(evas_object_evas_get(obj), &x, &y); + evas_object_size_hint_max_set(ctxpopup, 240, 240); + evas_object_move(ctxpopup, x, y); + evas_object_show(ctxpopup); +} + + +static void +_list_item_cb5(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Evas_Object *ctxpopup, *btn; + Evas_Coord x,y; + char buf[PATH_MAX]; + + btn = elm_button_add(obj); + elm_button_label_set(btn, "Enlightenment"); + evas_object_size_hint_min_set(btn, 150, 150); + + ctxpopup = elm_ctxpopup_add(obj); + elm_ctxpopup_content_set(ctxpopup, btn); + + evas_pointer_output_xy_get(evas_object_evas_get(obj), &x, &y); + evas_object_move(ctxpopup, x, y); + evas_object_show(ctxpopup); } + static void _list_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) { elm_list_item_selected_set(event_info, EINA_FALSE); @@ -25,11 +143,10 @@ static void _list_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__, vo void test_ctxpopup(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { - Evas_Object *win, *bg, *list, *hov1, *hov2, *hov3, *hov4, *ic; - Elm_Ctxpopup_Item *it; + Evas_Object *win, *bg, *list, *ic; - win = elm_win_add(NULL, "Contexual Popup 2", ELM_WIN_BASIC); - elm_win_title_set(win, "Contextual Popup 2"); + win = elm_win_add(NULL, "Contexual Popup", ELM_WIN_BASIC); + elm_win_title_set(win, "Contextual Popup"); elm_win_autodel_set(win, EINA_TRUE); bg = elm_bg_add(win); @@ -42,75 +159,21 @@ test_ctxpopup(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_in elm_list_mode_set(list, ELM_LIST_COMPRESS); evas_object_smart_callback_add(list, "selected", _list_clicked, NULL); -#define ITEM_NEW(_hov, _icon, _label) \ - ic = elm_icon_add(win); \ - elm_icon_standard_set(ic, _icon); \ - elm_icon_scale_set(ic, EINA_FALSE, EINA_FALSE); \ - it = elm_ctxpopup_item_append(_hov, _label, ic, _ctxpopup_item_cb, NULL); - - hov1 = elm_ctxpopup_add(win); - - ITEM_NEW(hov1, "home", "Go to home folder"); - ITEM_NEW(hov1, "file", "Save file"); - ITEM_NEW(hov1, "delete", "Delete file"); - ITEM_NEW(hov1, "folder", "Navigate to folder"); - elm_ctxpopup_item_disabled_set(it, EINA_TRUE); - ITEM_NEW(hov1, "edit", "Edit entry"); - ITEM_NEW(hov1, "clock", "Set date and time"); - ITEM_NEW(hov1, "arrow_up", "Go up"); - ITEM_NEW(hov1, "arrow_down", "Go down"); - ITEM_NEW(hov1, "arrow_left", "Go left"); - elm_ctxpopup_item_disabled_set(it, EINA_TRUE); - ITEM_NEW(hov1, "arrow_right", "Go right"); - - hov2 = elm_ctxpopup_add(win); - - ITEM_NEW(hov2, "home", NULL); - ITEM_NEW(hov2, "file", NULL); - ITEM_NEW(hov2, "delete", NULL); - ITEM_NEW(hov2, "folder", NULL); - ITEM_NEW(hov2, "edit", NULL); - elm_ctxpopup_item_disabled_set(it, EINA_TRUE); - ITEM_NEW(hov2, "clock", NULL); - ITEM_NEW(hov2, "arrow_up", NULL); - ITEM_NEW(hov2, "arrow_down", NULL); - ITEM_NEW(hov2, "arrow_left", NULL); - ITEM_NEW(hov2, "arrow_right", NULL); - - hov3 = elm_ctxpopup_add(win); - elm_ctxpopup_horizontal_set(hov3, EINA_TRUE); - - ITEM_NEW(hov3, "home", "Zero"); - ITEM_NEW(hov3, "file", "Um"); - ITEM_NEW(hov3, "delete", "Dos"); - ITEM_NEW(hov3, "folder", "Tri"); - ITEM_NEW(hov3, "edit", "Vier"); - ITEM_NEW(hov3, "clock", "五"); - - hov4 = elm_ctxpopup_add(win); - - ITEM_NEW(hov4, NULL, "Eina"); - ITEM_NEW(hov4, NULL, "Eet"); - ITEM_NEW(hov4, NULL, "Evas"); - ITEM_NEW(hov4, NULL, "Ecore"); - elm_ctxpopup_item_disabled_set(it, EINA_TRUE); - ITEM_NEW(hov4, NULL, "Embryo"); - ITEM_NEW(hov4, NULL, "Edje"); - #undef ITEM_NEW - elm_list_item_append(list, "Ctxpopup with icons and labels", NULL, NULL, - _list_item_cb, hov1); + _list_item_cb, NULL); elm_list_item_append(list, "Ctxpopup with icons only", NULL, NULL, - _list_item_cb, hov2); + _list_item_cb2, NULL); + elm_list_item_append(list, "Ctxpopup with labels only", NULL, NULL, + _list_item_cb3, NULL); elm_list_item_append(list, "Ctxpopup at horizontal mode", NULL, NULL, - _list_item_cb, hov3); - elm_list_item_append(list, "Ctxpopup with no icons", NULL, NULL, - _list_item_cb, hov4); + _list_item_cb4, NULL); + elm_list_item_append(list, "Ctxpopup with user content", NULL, NULL, + _list_item_cb5, NULL); evas_object_show(list); elm_list_go(list); - evas_object_resize(win, 300, 300); + evas_object_resize(win, 400, 400); evas_object_show(win); } #endif diff --git a/src/lib/Elementary.h.in b/src/lib/Elementary.h.in index 1b00ff2..f7de3b5 100644 --- a/src/lib/Elementary.h.in +++ b/src/lib/Elementary.h.in @@ -2420,24 +2420,35 @@ extern "C" { * "changed" - when the color value changes */ - /* ctxpopup */ + /* Contextual Popup */ typedef struct _Elm_Ctxpopup_Item Elm_Ctxpopup_Item; - EAPI Evas_Object *elm_ctxpopup_add(Evas_Object* parent) EINA_ARG_NONNULL(1); - EAPI void elm_ctxpopup_hover_end(Evas_Object *obj) EINA_ARG_NONNULL(1); - EAPI Evas_Object *elm_ctxpopup_item_icon_get(const Elm_Ctxpopup_Item *item) EINA_ARG_NONNULL(1); - EAPI void elm_ctxpopup_item_icon_set(Elm_Ctxpopup_Item *item, Evas_Object *icon) EINA_ARG_NONNULL(1); - EAPI const char *elm_ctxpopup_item_label_get(const Elm_Ctxpopup_Item *item) EINA_ARG_NONNULL(1); - EAPI void elm_ctxpopup_item_label_set(Elm_Ctxpopup_Item *item, const char *label) EINA_ARG_NONNULL(1); - EAPI void elm_ctxpopup_hover_parent_set(Evas_Object *obj, Evas_Object *parent) EINA_ARG_NONNULL(1, 2); - EAPI Evas_Object *elm_ctxpopup_hover_parent_get(const Evas_Object *obj) EINA_ARG_NONNULL(1); - EAPI void elm_ctxpopup_clear(Evas_Object* obj) EINA_ARG_NONNULL(1); - EAPI void elm_ctxpopup_horizontal_set(Evas_Object* obj, Eina_Bool horizontal) EINA_ARG_NONNULL(1); - EAPI Eina_Bool elm_ctxpopup_horizontal_get(const Evas_Object *obj) EINA_ARG_NONNULL(1); - EAPI Elm_Ctxpopup_Item *elm_ctxpopup_item_append(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Smart_Cb func, const void *data) EINA_ARG_NONNULL(1); - EAPI void elm_ctxpopup_item_del(Elm_Ctxpopup_Item *item) EINA_ARG_NONNULL(1); - EAPI void elm_ctxpopup_item_disabled_set(Elm_Ctxpopup_Item *item, Eina_Bool disabled) EINA_ARG_NONNULL(1); - EAPI Eina_Bool elm_ctxpopup_item_disabled_get(const Elm_Ctxpopup_Item *item) EINA_ARG_NONNULL(1); + typedef enum _Elm_Ctxpopup_Direction + { + ELM_CTXPOPUP_DIRECTION_DOWN, + ELM_CTXPOPUP_DIRECTION_RIGHT, + ELM_CTXPOPUP_DIRECTION_LEFT, + ELM_CTXPOPUP_DIRECTION_UP, + } Elm_Ctxpopup_Direction; + + EAPI Evas_Object *elm_ctxpopup_add(Evas_Object *parent) EINA_ARG_NONNULL(1); + EAPI Evas_Object *elm_ctxpopup_item_icon_get(const Elm_Ctxpopup_Item *item) EINA_ARG_NONNULL(1); + EAPI void elm_ctxpopup_item_icon_set(Elm_Ctxpopup_Item *item, Evas_Object *icon) EINA_ARG_NONNULL(1); + EAPI const char *elm_ctxpopup_item_label_get(const Elm_Ctxpopup_Item *item) EINA_ARG_NONNULL(1); + EAPI void elm_ctxpopup_item_label_set(Elm_Ctxpopup_Item *item, const char *label) EINA_ARG_NONNULL(1); + EAPI void elm_ctxpopup_hover_parent_set(Evas_Object *obj, Evas_Object *parent) EINA_ARG_NONNULL(1, 2); + EAPI Evas_Object *elm_ctxpopup_hover_parent_get(const Evas_Object *obj) EINA_ARG_NONNULL(1); + EAPI void elm_ctxpopup_clear(Evas_Object *obj) EINA_ARG_NONNULL(1); + EAPI void elm_ctxpopup_horizontal_set(Evas_Object *obj, Eina_Bool horizontal) EINA_ARG_NONNULL(1); + EAPI Eina_Bool elm_ctxpopup_horizontal_get(const Evas_Object *obj) EINA_ARG_NONNULL(1); + Elm_Ctxpopup_Item *elm_ctxpopup_item_append(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Smart_Cb func, const void *data) EINA_ARG_NONNULL(1); + EAPI void elm_ctxpopup_item_del(Elm_Ctxpopup_Item *item) EINA_ARG_NONNULL(1); + EAPI void elm_ctxpopup_item_disabled_set(Elm_Ctxpopup_Item *item, Eina_Bool disabled) EINA_ARG_NONNULL(1); + EAPI Eina_Bool elm_ctxpopup_item_disabled_get(const Elm_Ctxpopup_Item *item) EINA_ARG_NONNULL(1); + EAPI void elm_ctxpopup_content_set(Evas_Object *obj, Evas_Object *content) EINA_ARG_NONNULL(1, 2); + EAPI Evas_Object *elm_ctxpopup_content_unset(Evas_Object *obj) EINA_ARG_NONNULL(1); + EAPI void elm_ctxpopup_direction_priority_set(Evas_Object *obj, Elm_Ctxpopup_Direction first, Elm_Ctxpopup_Direction second, Elm_Ctxpopup_Direction third, Elm_Ctxpopup_Direction fourth) EINA_ARG_NONNULL(1); + EAPI void elm_ctxpopup_direction_priority_get(Evas_Object *obj, Elm_Ctxpopup_Direction *first, Elm_Ctxpopup_Direction *second, Elm_Ctxpopup_Direction *third, Elm_Ctxpopup_Direction *fourth) EINA_ARG_NONNULL(1); /* smart callbacks called: * "dismissed" - the ctxpopup was dismissed */ diff --git a/src/lib/elc_ctxpopup.c b/src/lib/elc_ctxpopup.c index 8395c43..df84de9 100644 --- a/src/lib/elc_ctxpopup.c +++ b/src/lib/elc_ctxpopup.c @@ -14,7 +14,7 @@ * * Signals that you can add callbacks for are: * - * dismissed - the hover was dismissed + * dismissed - the ctxpopup was dismissed */ typedef struct _Widget_Data Widget_Data; @@ -22,53 +22,97 @@ typedef struct _Widget_Data Widget_Data; struct _Elm_Ctxpopup_Item { Elm_Widget_Item base; - - Elm_List_Item *lptr; - - const char *label; - Evas_Object *icon; - - Evas_Smart_Cb func; - const void *data; - - Eina_Bool disabled : 1; + const char *label; + Evas_Object *icon; + Evas_Smart_Cb func; + Eina_Bool disabled:1; }; struct _Widget_Data { + Evas_Object *parent; + Evas_Object *base; + Evas_Object *content; + Evas_Object *box; + Evas_Object *arrow; + Evas_Object *scr; + Evas_Object *bg; Evas_Object *hover_parent; - Evas_Object *list; - Evas_Object *target; - Evas_Object *hover; - Evas *evas; - - Eina_List *items; - - Eina_Bool scroller_disabled : 1; - Eina_Bool horizontal : 1; + Eina_List *items; + Elm_Ctxpopup_Direction dir; + Elm_Ctxpopup_Direction dir_priority[4]; + Evas_Coord max_sc_w, max_sc_h; + Eina_Bool horizontal:1; + Eina_Bool visible:1; + Eina_Bool finished:1; }; static const char *widtype = NULL; + static void _del_hook(Evas_Object *obj); static void _del_pre_hook(Evas_Object *obj); static void _theme_hook(Evas_Object *obj); -static void _hover_clicked_cb(void *data, - Evas_Object *obj, - void *event_info); -static void _parent_resize_cb(void *data, - Evas *evas, - Evas_Object *obj, - void *event_info); -static void _ctxpopup_show(void *data, - Evas *evas, - Evas_Object *obj, - void *event_info); -static void _ctxpopup_hide(void *data, - Evas *evas, - Evas_Object *obj, - void *event_info); +static void _sizing_eval(Evas_Object *obj); +static void _hover_parent_resize(void *data, Evas *e __UNUSED__, + Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__); +static void _hover_parent_move(void *data, Evas *e __UNUSED__, + Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__); +static void _hover_parent_del(void *data, Evas *e __UNUSED__, + Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__); +static void _hover_parent_callbacks_del(Evas_Object *obj); +static void _bg_clicked_cb(void *data, Evas_Object *obj __UNUSED__, + const char *emission __UNUSED__, + const char *source __UNUSED__); +static void _parent_resize(void *data, Evas *e, Evas_Object *obj, + void *event_info __UNUSED__); +static void _ctxpopup_show(void *data __UNUSED__, Evas *e __UNUSED__, + Evas_Object *obj, void *event_info __UNUSED__); +static void _ctxpopup_hide(void *data __UNUSED__, Evas *e __UNUSED__, + Evas_Object *obj, void *event_info __UNUSED__); +static void _ctxpopup_move(void *data __UNUSED__, Evas *e __UNUSED__, + Evas_Object *obj, void *event_info __UNUSED__); +static void _scroller_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__); +static void _ctxpopup_changed_size_hints(void *data __UNUSED__, + Evas *e __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__); +static void _item_new(Elm_Ctxpopup_Item *item, char *group_name); +static void _list_new(Evas_Object *obj); +static void _item_sizing_eval(Elm_Ctxpopup_Item *item); +static void _item_select_cb(void *data, Evas_Object *obj __UNUSED__, + const char *emission __UNUSED__, + const char *source __UNUSED__); +static Elm_Ctxpopup_Direction _calc_base_geometry(Evas_Object *obj, + Evas_Coord_Rectangle *rect); +static void _update_arrow(Evas_Object *obj, Elm_Ctxpopup_Direction dir); +static void _shift_base_by_arrow(Evas_Object *arrow, + Elm_Ctxpopup_Direction dir, + Evas_Coord_Rectangle *rect); +static void _adjust_pos_x(Evas_Coord_Point *pos, Evas_Coord_Point *base_size, + Evas_Coord_Rectangle *hover_area); +static void _adjust_pos_y(Evas_Coord_Point *pos, Evas_Coord_Point *base_size, + Evas_Coord_Rectangle *hover_area); +static void _scroller_size_reset(Widget_Data *wd); +static void _hide(Evas_Object *obj); +static void _content_del(void *data, Evas *e, Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__); +static void _freeze_on(void *data __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__); +static void _freeze_off(void *data __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__); +static void _hold_on(void *data __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__); +static void _hold_off(void *data __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__); +static void _item_icon_set(Elm_Ctxpopup_Item *item, Evas_Object *icon); +static void _item_label_set(Elm_Ctxpopup_Item *item, const char *label); +static void _remove_items(Widget_Data * wd); static const char SIG_DISMISSED[] = "dismissed"; + static const Evas_Smart_Cb_Description _signals[] = { {SIG_DISMISSED, ""}, {NULL, NULL} @@ -78,270 +122,814 @@ static const Evas_Smart_Cb_Description _signals[] = { ELM_WIDGET_ITEM_CHECK_OR_RETURN((Elm_Widget_Item *)it, __VA_ARGS__); \ ELM_CHECK_WIDTYPE(item->base.widget, widtype) __VA_ARGS__; -static Elm_Ctxpopup_Item * -_item_new(Evas_Object *obj, - const char *label, - Evas_Object *icon, - Evas_Smart_Cb func, - const void *data) +static void +_freeze_on(void *data __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__) { - Elm_Ctxpopup_Item *it; + Widget_Data *wd = elm_widget_data_get(obj); - it = elm_widget_item_new(obj, Elm_Ctxpopup_Item); - if (!it) - return NULL; + if (!wd) + return; + elm_object_scroll_freeze_push(wd->scr); +} - it->label = eina_stringshare_add(label); - it->icon = icon; - it->func = func; - it->base.data = data; +static void +_freeze_off(void *data __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__) +{ + Widget_Data *wd = elm_widget_data_get(obj); - return it; + if (!wd) + return; + elm_object_scroll_freeze_pop(wd->scr); } -static inline void -_item_free(Elm_Ctxpopup_Item *it) +static void +_hold_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) { - eina_stringshare_del(it->label); - elm_widget_item_del(it); + Widget_Data *wd = elm_widget_data_get(obj); + + if (!wd) + return; + elm_object_scroll_hold_push(wd->scr); } static void -_del_pre_hook(Evas_Object *obj) +_hold_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) { Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) - return; + return; + elm_object_scroll_hold_pop(wd->scr); +} + +static void +_scroller_size_reset(Widget_Data *wd) +{ + wd->finished = EINA_FALSE; + wd->max_sc_h = -1; + wd->max_sc_w = -1; +} + +static void +_hover_parent_callbacks_del(Evas_Object *obj) +{ + Widget_Data *wd = elm_widget_data_get(obj); + + if ((!wd) || (!wd->hover_parent)) + return; + + evas_object_event_callback_del_full(wd->hover_parent, EVAS_CALLBACK_DEL, + _hover_parent_del, obj); + evas_object_event_callback_del_full(wd->hover_parent, EVAS_CALLBACK_MOVE, + _hover_parent_move, obj); evas_object_event_callback_del_full(wd->hover_parent, EVAS_CALLBACK_RESIZE, - _parent_resize_cb, obj); + _hover_parent_resize, obj); } static void -_del_hook(Evas_Object *obj) +_hover_parent_resize(void *data, Evas *e __UNUSED__, + Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { - Elm_Ctxpopup_Item *it; - Widget_Data *wd; + Widget_Data *wd = elm_widget_data_get(data); - wd = elm_widget_data_get(obj); if (!wd) - return; + return; - EINA_LIST_FREE(wd->items, it) - _item_free(it); - - free(wd); + if (wd->visible) + { + _scroller_size_reset(wd); + _sizing_eval(data); + } } -static Eina_Bool -_event_hook(Evas_Object *obj, - Evas_Object *src __UNUSED__, - Evas_Callback_Type type, - void *event_info) +static void +_hover_parent_move(void *data, Evas *e __UNUSED__, + Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { - if (type != EVAS_CALLBACK_KEY_DOWN) - return EINA_FALSE; + Widget_Data *wd = elm_widget_data_get(data); - Evas_Event_Key_Down *ev = event_info; + if (!wd) + return; + + if (wd->visible) + { + _scroller_size_reset(wd); + _sizing_eval(obj); + } +} + +static void +_hover_parent_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__) +{ + Widget_Data *wd = elm_widget_data_get(data); - Widget_Data *wd = elm_widget_data_get(obj); if (!wd) - return EINA_FALSE; + return; - if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) - return EINA_FALSE; + wd->hover_parent = NULL; +} - if (strcmp(ev->keyname, "Escape")) - return EINA_FALSE; +static void +_item_sizing_eval(Elm_Ctxpopup_Item *item) +{ + Evas_Coord min_w = -1, min_h = -1, max_w = -1, max_h = -1; + + Evas_Coord x, y, w, h; + + if (!item) + return; - evas_object_hide(obj); - ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; - return EINA_TRUE; + evas_object_geometry_get(item->base.view, &x, &y, &w, &h); + edje_object_size_min_restricted_calc(item->base.view, &min_w, &min_h, min_w, + min_h); + evas_object_size_hint_min_set(item->base.view, min_w, min_h); + evas_object_size_hint_max_set(item->base.view, max_w, max_h); } static void -_on_focus_hook(void *data __UNUSED__, - Evas_Object *obj) +_adjust_pos_x(Evas_Coord_Point *pos, Evas_Coord_Point *base_size, + Evas_Coord_Rectangle *hover_area) { - Widget_Data *wd = elm_widget_data_get(obj); + pos->x -= (base_size->x / 2); + + if (pos->x < hover_area->x) + pos->x = hover_area->x; + else if ((pos->x + base_size->x) > (hover_area->x + hover_area->w)) + pos->x = (hover_area->x + hover_area->w) - base_size->x; + + if (base_size->x > hover_area->w) + base_size->x -= (base_size->x - hover_area->w); + + if (pos->x < hover_area->x) + pos->x = hover_area->x; +} + +static void +_adjust_pos_y(Evas_Coord_Point *pos, Evas_Coord_Point *base_size, + Evas_Coord_Rectangle *hover_area) +{ + pos->y -= (base_size->y / 2); + + if (pos->y < hover_area->y) + pos->y = hover_area->y; + else if ((pos->y + base_size->y) > (hover_area->y + hover_area->h)) + pos->y = hover_area->y + hover_area->h - base_size->y; + + if (base_size->y > hover_area->h) + base_size->y -= (base_size->y - hover_area->h); + + if (pos->y < hover_area->y) + pos->y = hover_area->y; +} + +static void +_ctxpopup_changed_size_hints(void *data __UNUSED__, Evas *e __UNUSED__, + Evas_Object *obj, void *event_info __UNUSED__) +{ + Widget_Data *wd; + + wd = elm_widget_data_get(obj); if (!wd) - return; + return; + + if (wd->visible) + _sizing_eval(obj); +} + +static Elm_Ctxpopup_Direction +_calc_base_geometry(Evas_Object *obj, Evas_Coord_Rectangle *rect) +{ + Widget_Data *wd; + Evas_Coord_Point pos; + Evas_Coord_Point base_size; + Evas_Coord_Point max_size; + Evas_Coord_Point min_size; + Evas_Coord_Rectangle hover_area; + Evas_Coord_Rectangle parent_size; + Evas_Coord_Point arrow_size; + Elm_Ctxpopup_Direction arrow; + Evas_Coord finger_size; + Evas_Coord_Point temp; + int idx; + + wd = elm_widget_data_get(obj); + + if ((!wd) || (!rect)) + return ELM_CTXPOPUP_DIRECTION_DOWN; + + finger_size = elm_finger_size_get(); + + edje_object_part_geometry_get(wd->arrow, "ctxpopup_arrow", NULL, NULL, + &arrow_size.x, &arrow_size.y); + evas_object_resize(wd->arrow, arrow_size.x, arrow_size.y); - if (elm_widget_focus_get(obj)) + //Initialize Area Rectangle. + if (wd->hover_parent) + evas_object_geometry_get(wd->hover_parent, &hover_area.x, &hover_area.y, + &hover_area.w, &hover_area.h); + else { - elm_object_signal_emit(wd->list, "elm,action,focus", "elm"); - evas_object_focus_set(wd->list, EINA_TRUE); + evas_object_geometry_get(wd->parent, &parent_size.x, &parent_size.y, + &parent_size.w, &parent_size.h); + hover_area.x = parent_size.x; + hover_area.y = parent_size.y; + hover_area.w = parent_size.w; + hover_area.h = parent_size.h; } - else + + evas_object_geometry_get(obj, &pos.x, &pos.y, NULL, NULL); + + //recalc the edje + edje_object_size_min_calc(wd->base, &base_size.x, &base_size.y); + evas_object_smart_calculate(wd->base); + + //Limit to Max Size + evas_object_size_hint_max_get(obj, &max_size.x, &max_size.y); + + if ((max_size.y > 0) && (base_size.y > max_size.y)) + base_size.y = max_size.y; + + if ((max_size.x > 0) && (base_size.x > max_size.x)) + base_size.x = max_size.x; + + //Limit to Min Size + evas_object_size_hint_min_get(obj, &min_size.x, &min_size.y); + + if ((min_size.y > 0) && (base_size.y < min_size.y)) + base_size.y = min_size.y; + + if ((min_size.x > 0) && (base_size.x < min_size.x)) + base_size.x = min_size.x; + + //Check the Which direction is available. + //If find a avaialble direction, it adjusts position and size. + for (idx = 0; idx < 4; idx++) { - elm_object_signal_emit(wd->list, "elm,action,unfocus", "elm"); - evas_object_focus_set(wd->list, EINA_FALSE); + switch (wd->dir_priority[idx]) + { + case ELM_CTXPOPUP_DIRECTION_UP: + temp.y = pos.y - base_size.y; + if ((temp.y - arrow_size.y - finger_size) < hover_area.y) + continue; + _adjust_pos_x(&pos, &base_size, &hover_area); + pos.y -= (base_size.y + finger_size); + arrow = ELM_CTXPOPUP_DIRECTION_DOWN; + break; + case ELM_CTXPOPUP_DIRECTION_LEFT: + temp.x = (pos.x - base_size.x); + if ((temp.x - arrow_size.x - finger_size) < hover_area.x) + continue; + _adjust_pos_y(&pos, &base_size, &hover_area); + pos.x -= (base_size.x + finger_size); + arrow = ELM_CTXPOPUP_DIRECTION_RIGHT; + break; + case ELM_CTXPOPUP_DIRECTION_RIGHT: + temp.x = (pos.x + base_size.x); + if ((temp.x + arrow_size.x + finger_size) > + (hover_area.x + hover_area.w)) + continue; + _adjust_pos_y(&pos, &base_size, &hover_area); + pos.x += finger_size; + arrow = ELM_CTXPOPUP_DIRECTION_LEFT; + break; + case ELM_CTXPOPUP_DIRECTION_DOWN: + temp.y = (pos.y + base_size.y); + if ((temp.y + arrow_size.y + finger_size) > + (hover_area.y + hover_area.h)) + continue; + _adjust_pos_x(&pos, &base_size, &hover_area); + pos.y += finger_size; + arrow = ELM_CTXPOPUP_DIRECTION_UP; + break; + default: + break; + } + break; } + + //In this case, all directions are invalid because of lack of space. + if (idx == 4) + { + //TODO 1: Find the largest space direction. + Evas_Coord length[2]; + + length[0] = pos.y - hover_area.y; + length[1] = (hover_area.y + hover_area.h) - pos.y; + + if (length[0] > length[1]) + idx = ELM_CTXPOPUP_DIRECTION_DOWN; + else + idx = ELM_CTXPOPUP_DIRECTION_UP; + + //TODO 2: determine x , y + switch (idx) + { + case ELM_CTXPOPUP_DIRECTION_UP: + _adjust_pos_x(&pos, &base_size, &hover_area); + pos.y -= (base_size.y + finger_size); + arrow = ELM_CTXPOPUP_DIRECTION_DOWN; + if (pos.y < hover_area.y + arrow_size.y) + { + base_size.y -= ((hover_area.y + arrow_size.y) - pos.y); + pos.y = hover_area.y + arrow_size.y; + } + break; + case ELM_CTXPOPUP_DIRECTION_LEFT: + _adjust_pos_y(&pos, &base_size, &hover_area); + pos.x -= (base_size.x + finger_size); + arrow = ELM_CTXPOPUP_DIRECTION_RIGHT; + if (pos.x < hover_area.x + arrow_size.x) + { + base_size.x -= ((hover_area.x + arrow_size.x) - pos.x); + pos.x = hover_area.x + arrow_size.x; + } + break; + case ELM_CTXPOPUP_DIRECTION_RIGHT: + _adjust_pos_y(&pos, &base_size, &hover_area); + pos.x += finger_size; + arrow = ELM_CTXPOPUP_DIRECTION_LEFT; + if (pos.x + arrow_size.x + base_size.x > + hover_area.x + hover_area.w) + base_size.x -= + ((pos.x + arrow_size.x + base_size.x) - + (hover_area.x + hover_area.w)); + break; + case ELM_CTXPOPUP_DIRECTION_DOWN: + _adjust_pos_x(&pos, &base_size, &hover_area); + pos.y += finger_size; + arrow = ELM_CTXPOPUP_DIRECTION_UP; + if (pos.y + arrow_size.y + base_size.y > + hover_area.y + hover_area.h) + base_size.y -= + ((pos.y + arrow_size.y + base_size.y) - + (hover_area.y + hover_area.h)); + break; + default: + break; + } + } + + //Final position and size. + rect->x = pos.x; + rect->y = pos.y; + rect->w = base_size.x; + rect->h = base_size.y; + + return arrow; } static void -_theme_hook(Evas_Object *obj) +_update_arrow(Evas_Object *obj, Elm_Ctxpopup_Direction dir) { + Evas_Coord x, y; + Evas_Coord_Rectangle arrow_size; Widget_Data *wd; - char buf[1024]; wd = elm_widget_data_get(obj); if (!wd) - return; + return; - elm_widget_style_set(wd->list, "ctxpopup"); + evas_object_geometry_get(obj, &x, &y, NULL, NULL); + evas_object_geometry_get(wd->arrow, NULL, NULL, &arrow_size.w, + &arrow_size.h); - snprintf(buf, sizeof(buf), "ctxpopup/%s", elm_widget_style_get(obj)); - elm_object_style_set(wd->hover, buf); + switch (dir) + { + case ELM_CTXPOPUP_DIRECTION_LEFT: + edje_object_signal_emit(wd->arrow, "elm,state,left", "elm"); + arrow_size.y = (y - (arrow_size.h * 0.5)); + arrow_size.x = (x + elm_finger_size_get()); + break; + case ELM_CTXPOPUP_DIRECTION_RIGHT: + edje_object_signal_emit(wd->arrow, "elm,state,right", "elm"); + arrow_size.y = (y - (arrow_size.h * 0.5)); + arrow_size.x = (x - elm_finger_size_get() - arrow_size.w); + break; + case ELM_CTXPOPUP_DIRECTION_UP: + edje_object_signal_emit(wd->arrow, "elm,state,top", "elm"); + arrow_size.x = (x - (arrow_size.w * 0.5)); + arrow_size.y = (y + elm_finger_size_get()); + break; + case ELM_CTXPOPUP_DIRECTION_DOWN: + edje_object_signal_emit(wd->arrow, "elm,state,bottom", "elm"); + arrow_size.x = (x - (arrow_size.w * 0.5)); + arrow_size.y = (y - elm_finger_size_get() - arrow_size.h); + break; + default: + break; + } + + evas_object_move(wd->arrow, arrow_size.x, arrow_size.y); } static void -_signal_emit_hook(Evas_Object *obj, - const char *emission, - const char *source) +_sizing_eval(Evas_Object *obj) { - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return; - elm_object_signal_emit(wd->list, emission, source); - elm_object_signal_emit(wd->hover, emission, source); + Widget_Data *wd; + Eina_List *elist; + Elm_Ctxpopup_Item *item; + Evas_Coord_Rectangle rect = { 0, 0, 1, 1 }; + Evas_Coord_Point box_size = { 0, 0 }; + Evas_Coord_Point _box_size = { 0, 0 }; + + wd = elm_widget_data_get(obj); + if ((!wd) || (!wd->parent)) + return; + + //Box, Scroller + EINA_LIST_FOREACH(wd->items, elist, item) + { + _item_sizing_eval(item); + evas_object_size_hint_min_get(item->base.view, &_box_size.x, &_box_size.y); + if (!wd->horizontal) + { + if (_box_size.x > box_size.x) + box_size.x = _box_size.x; + if (_box_size.y != -1) + box_size.y += _box_size.y; + } + else + { + if (_box_size.x != -1) + box_size.x += _box_size.x; + if (_box_size.y > box_size.y) + box_size.y = _box_size.y; + } + } + + if (!wd->content) + { + evas_object_size_hint_min_set(wd->box, box_size.x, box_size.y); + evas_object_size_hint_min_set(wd->scr, box_size.x, box_size.y); + } + + //Base + wd->dir = _calc_base_geometry(obj, &rect); + if (wd->dir != -1) + { + _update_arrow(obj, wd->dir); + _shift_base_by_arrow(wd->arrow, wd->dir, &rect); + } + + //resize scroller according to final size. + if (!wd->content) + evas_object_smart_calculate(wd->scr); + + evas_object_move(wd->base, rect.x, rect.y); + evas_object_resize(wd->base, rect.w, rect.h); } static void -_signal_callback_add_hook(Evas_Object *obj, - const char *emission, - const char *source, - void (*func_cb)(void *data, - Evas_Object *o, - const char *emission, - const char *source), - void *data) +_shift_base_by_arrow(Evas_Object *arrow, Elm_Ctxpopup_Direction dir, + Evas_Coord_Rectangle *rect) { - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return; - elm_object_signal_callback_add(wd->list, emission, source, func_cb, data); - elm_object_signal_callback_add(wd->hover, emission, source, func_cb, data); + Evas_Coord arrow_w, arrow_h; + + evas_object_geometry_get(arrow, NULL, NULL, &arrow_w, &arrow_h); + + switch (dir) + { + case ELM_CTXPOPUP_DIRECTION_LEFT: + rect->x += arrow_w; + break; + case ELM_CTXPOPUP_DIRECTION_RIGHT: + rect->x -= arrow_w; + break; + case ELM_CTXPOPUP_DIRECTION_UP: + rect->y += arrow_h; + break; + case ELM_CTXPOPUP_DIRECTION_DOWN: + rect->y -= arrow_h; + break; + default: + break; + } } static void -_signal_callback_del_hook(Evas_Object *obj, - const char *emission, - const char *source, - void (*func_cb)(void *data, - Evas_Object *o, - const char *emission, - const char *source), - void *data __UNUSED__) +_del_pre_hook(Evas_Object *obj) { - Widget_Data *wd = elm_widget_data_get(obj); - elm_object_signal_callback_del(wd->list, emission, source, func_cb); - elm_object_signal_callback_del(wd->hover, emission, source, func_cb); + Widget_Data *wd; + + wd = elm_widget_data_get(obj); + if (!wd) + return; + + evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_RESIZE, + _parent_resize, obj); + + _hover_parent_callbacks_del(obj); } static void -_item_func_cb(void *data, - Evas_Object *obj __UNUSED__, - void *event_info) +_del_hook(Evas_Object *obj) { - Elm_Ctxpopup_Item *it; + Widget_Data *wd; - elm_list_item_selected_set(event_info, EINA_FALSE); + wd = elm_widget_data_get(obj); + if (!wd) + return; - it = data; - if (it->func) - it->func((void *)it->base.data, it->base.widget, it); + elm_ctxpopup_clear(obj); + evas_object_del(wd->arrow); + evas_object_del(wd->base); + free(wd); } static void -_hover_clicked_cb(void *data, - Evas_Object *obj __UNUSED__, - void *event_info __UNUSED__) +_theme_hook(Evas_Object *obj) +{ + Widget_Data *wd; + Eina_List *elist; + Elm_Ctxpopup_Item *item; + + wd = elm_widget_data_get(obj); + if (!wd) + return; + + //Items + EINA_LIST_FOREACH(wd->items, elist, item) + { + if (item->label && item->icon) + _elm_theme_object_set(obj, item->base.view, "ctxpopup", + "icon_text_style_item", + elm_widget_style_get(obj)); + else if (item->label) + _elm_theme_object_set(obj, item->base.view, "ctxpopup", "text_style_item", + elm_widget_style_get(obj)); + else if (item->icon) + _elm_theme_object_set(obj, item->base.view, "ctxpopup", "icon_style_item", + elm_widget_style_get(obj)); + if (item->label) + edje_object_part_text_set(item->base.view, "elm.text", item->label); + + if (item->disabled) + edje_object_signal_emit(item->base.view, "elm,state,disabled", "elm"); + + edje_object_message_signal_process(item->base.view); + } + + _elm_theme_object_set(obj, wd->bg, "ctxpopup", "bg", + elm_widget_style_get(obj)); + _elm_theme_object_set(obj, wd->base, "ctxpopup", "base", + elm_widget_style_get(obj)); + _elm_theme_object_set(obj, wd->arrow, "ctxpopup", "arrow", + elm_widget_style_get(obj)); + + if(!strncmp(elm_object_style_get(obj), "default", strlen("default") + * sizeof(char))) + elm_object_style_set(wd->scr, "ctxpopup"); + else + elm_object_style_set(wd->scr, elm_object_style_get(obj)); + + if (wd->visible) + { + _scroller_size_reset(wd); + _sizing_eval(obj); + } +} + +static void +_bg_clicked_cb(void *data, Evas_Object *obj __UNUSED__, + const char *emission __UNUSED__, const char *source __UNUSED__) { evas_object_hide(data); } -void -_content_placement_changed_cb(void *data, - Evas_Object *obj __UNUSED__, - void *event_info) +static void +_parent_resize(void *data, Evas *e, Evas_Object *obj, + void *event_info __UNUSED__) { - const char *new_slot; + Evas_Coord w, h; Widget_Data *wd; - char buf[1024]; wd = elm_widget_data_get(data); - new_slot = event_info; + if (!wd) + return; + + evas_object_geometry_get(obj, NULL, NULL, &w, &h); + evas_object_resize(wd->bg, w, h); + + if (!wd->visible) + return; - snprintf(buf, sizeof(buf), "elm,action,slot,%s,show", new_slot); - elm_widget_signal_emit(wd->hover, buf, "elm"); + _hide(data); } static void -_ctxpopup_show(void *data __UNUSED__, - Evas *evas __UNUSED__, - Evas_Object *obj, +_ctxpopup_show(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) { Widget_Data *wd; - int px, py; - int w, h; wd = elm_widget_data_get(obj); - if (eina_list_count(wd->items) < 1) - return; + if (!wd) + return; + + if ((!wd->items) && (!wd->content)) + return; - elm_widget_focus_steal(obj); + wd->visible = EINA_TRUE; - evas_pointer_canvas_xy_get(wd->evas, &px, &py); - evas_object_geometry_get(wd->target, NULL, NULL, &w, &h); - evas_object_move(wd->target, px - (w / 2), py - (h / 2)); + evas_object_show(wd->bg); + evas_object_show(wd->base); + evas_object_show(wd->arrow); - /* reset list */ - elm_list_item_show(eina_list_data_get(elm_list_items_get(wd->list))); + edje_object_signal_emit(wd->bg, "elm,state,show", "elm"); - evas_object_show(wd->hover); + _sizing_eval(obj); } static void -_ctxpopup_hide(void *data __UNUSED__, - Evas *evas __UNUSED__, - Evas_Object *obj, - void *event_info __UNUSED__) +_hide(Evas_Object *obj) { Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) - return; + return; + + evas_object_hide(wd->bg); + evas_object_hide(wd->arrow); + evas_object_hide(wd->base); + + _scroller_size_reset(wd); - evas_object_hide(wd->hover); evas_object_smart_callback_call(obj, SIG_DISMISSED, NULL); + wd->visible = EINA_FALSE; } static void -_parent_del(void *data, - Evas *e __UNUSED__, - Evas_Object *obj __UNUSED__, - void *event_info __UNUSED__) +_ctxpopup_hide(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__) { - Widget_Data *wd = elm_widget_data_get(data); + Widget_Data *wd; + + wd = elm_widget_data_get(obj); if (!wd) - return; + return; - wd->hover_parent = NULL; + if (!wd->visible) + return; + + _hide(obj); } static void -_parent_resize_cb(void *data, - Evas *e __UNUSED__, - Evas_Object *obj __UNUSED__, - void *event_info __UNUSED__) +_scroller_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__) { Widget_Data *wd; - int w, h; + Evas_Coord w, h; wd = elm_widget_data_get(data); if (!wd) - return; + return; + + if (!wd->visible) + return; + if (wd->finished) + return; + + evas_object_geometry_get(obj, 0, 0, &w, &h); + + if (w != 0 && h != 0) + { + if ((w <= wd->max_sc_w) && (h <= wd->max_sc_h)) + { + _sizing_eval(data); + wd->finished = EINA_TRUE; + return; + } + } + + if (wd->max_sc_w < w) + wd->max_sc_w = w; + if (wd->max_sc_h < h) + wd->max_sc_h = h; + + _sizing_eval(data); +} + +static void +_ctxpopup_move(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__) +{ + Widget_Data *wd; + + wd = elm_widget_data_get(obj); + + if (!wd) + return; + + if (wd->visible) + evas_object_show(wd->arrow); + + _scroller_size_reset(wd); + _sizing_eval(obj); +} + +static void +_item_select_cb(void *data, Evas_Object *obj __UNUSED__, + const char *emission __UNUSED__, const char *source __UNUSED__) +{ + Elm_Ctxpopup_Item *item = data; + + if (!item) + return; + if (item->disabled) + return; + + if (item->func) + item->func((void*) item->base.data, item->base.widget, data); +} + +static void +_item_icon_set(Elm_Ctxpopup_Item *item, Evas_Object *icon) +{ + if (item->icon) + { + elm_widget_sub_object_del(item->base.view, item->icon); + evas_object_del(item->icon); + } + + item->icon = icon; + edje_object_part_swallow(item->base.view, "elm.swallow.icon", item->icon); + edje_object_message_signal_process(item->base.view); +} + +static void +_item_label_set(Elm_Ctxpopup_Item *item, const char *label) +{ + if (!eina_stringshare_replace(&item->label, label)) + return; + + edje_object_part_text_set(item->base.view, "elm.text", label); + edje_object_message_signal_process(item->base.view); +} + +static void +_item_new(Elm_Ctxpopup_Item *item, char *group_name) +{ + Widget_Data *wd; + + wd = elm_widget_data_get(item->base.widget); + if (!wd) + return; + + item->base.view = edje_object_add(evas_object_evas_get(wd->base)); + _elm_theme_object_set(item->base.widget, item->base.view, "ctxpopup", group_name, + elm_widget_style_get(item->base.widget)); + edje_object_signal_callback_add(item->base.view, "elm,action,click", "", + _item_select_cb, item); + evas_object_size_hint_align_set(item->base.view, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_show(item->base.view); +} + +static void +_content_del(void *data, Evas *e, Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__) +{ + elm_ctxpopup_content_unset(data); +} + +static void +_list_del(Widget_Data *wd) +{ + if (!wd->scr) + return; - evas_object_geometry_get(wd->hover_parent, NULL, NULL, &w, &h); - evas_object_size_hint_max_set(wd->list, w * 0.666667, h / 2); + edje_object_part_unswallow(wd->base, wd->scr); + evas_object_del(wd->scr); + wd->scr = NULL; + wd->box = NULL; +} + +static void +_list_new(Evas_Object *obj) +{ + Widget_Data *wd; + wd = elm_widget_data_get(obj); + if (!wd) + return; + + //scroller + wd->scr = elm_scroller_add(obj); + elm_object_style_set(wd->scr, "ctxpopup"); + evas_object_size_hint_align_set(wd->scr, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_RESIZE, + _scroller_resize, obj); + edje_object_part_swallow(wd->base, "elm.swallow.content", wd->scr); + + //box + wd->box = elm_box_add(obj); + evas_object_size_hint_weight_set(wd->box, EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + + elm_scroller_content_set(wd->scr, wd->box); + elm_ctxpopup_horizontal_set(obj, wd->horizontal); } /** @@ -356,98 +944,77 @@ EAPI Evas_Object * elm_ctxpopup_add(Evas_Object *parent) { Evas_Object *obj; + Evas *e; Widget_Data *wd; - char buf[1024]; + Evas_Coord x, y, w, h; EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL); wd = ELM_NEW(Widget_Data); - wd->evas = evas_object_evas_get(parent); - if (!wd->evas) return NULL; - obj = elm_widget_add(wd->evas); + e = evas_object_evas_get(parent); + if (!e) + return NULL; + obj = elm_widget_add(e); ELM_SET_WIDTYPE(widtype, "ctxpopup"); elm_widget_type_set(obj, "ctxpopup"); elm_widget_sub_object_add(parent, obj); elm_widget_data_set(obj, wd); - elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL); - elm_widget_can_focus_set(obj, EINA_TRUE); elm_widget_del_pre_hook_set(obj, _del_pre_hook); elm_widget_del_hook_set(obj, _del_hook); elm_widget_theme_hook_set(obj, _theme_hook); - elm_widget_event_hook_set(obj, _event_hook); - elm_widget_signal_emit_hook_set(obj, _signal_emit_hook); - elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook); - elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook); - - wd->list = elm_list_add(obj); - elm_widget_style_set(wd->list, "ctxpopup"); - - elm_list_mode_set(wd->list, ELM_LIST_EXPAND); - evas_object_show(wd->list); - - wd->target = elm_icon_add(obj); /* has to be an elm_widget (dummy, - in this case) because we gotta - make it work with - elm_widget_hover_object_set() */ - evas_object_resize(wd->target, elm_finger_size_get(), - elm_finger_size_get()); - evas_object_show(wd->target); - evas_object_layer_set(wd->target, EVAS_LAYER_MIN); - - wd->hover = elm_hover_add(obj); - - snprintf(buf, sizeof(buf), "ctxpopup/%s", elm_widget_style_get(obj)); - elm_object_style_set(wd->hover, buf); - - evas_object_smart_callback_add(wd->hover, "smart,changed", - _content_placement_changed_cb, obj); - - elm_ctxpopup_hover_parent_set(obj, parent); - elm_hover_target_set(wd->hover, wd->target); - - evas_object_smart_callback_add(wd->hover, "clicked", _hover_clicked_cb, obj); - elm_hover_content_set(wd->hover, "smart", wd->list); + wd->parent = parent; + + //Background + wd->bg = edje_object_add(e); + elm_widget_sub_object_add(obj, wd->bg); + _elm_theme_object_set(obj, wd->bg, "ctxpopup", "bg", "default"); + evas_object_geometry_get(parent, &x, &y, &w, &h); + evas_object_move(wd->bg, x, y); + evas_object_resize(wd->bg, w, h); + edje_object_signal_callback_add(wd->bg, "elm,action,click", "", + _bg_clicked_cb, obj); + + //Base + wd->base = edje_object_add(e); + elm_widget_sub_object_add(obj, wd->base); + _elm_theme_object_set(obj, wd->base, "ctxpopup", "base", "default"); + + //Arrow + wd->arrow = edje_object_add(e); + elm_widget_sub_object_add(obj, wd->arrow); + _elm_theme_object_set(obj, wd->arrow, "ctxpopup", "arrow", "default"); + + wd->dir_priority[0] = ELM_CTXPOPUP_DIRECTION_UP; + wd->dir_priority[1] = ELM_CTXPOPUP_DIRECTION_LEFT; + wd->dir_priority[2] = ELM_CTXPOPUP_DIRECTION_RIGHT; + wd->dir_priority[3] = ELM_CTXPOPUP_DIRECTION_DOWN; + + evas_object_event_callback_add(parent, EVAS_CALLBACK_RESIZE, _parent_resize, + obj); evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _ctxpopup_show, NULL); evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _ctxpopup_hide, NULL); + evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _ctxpopup_move, + NULL); + evas_object_event_callback_add(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, + _ctxpopup_changed_size_hints, NULL); + evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj); + evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj); + evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj); + evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj); - elm_widget_sub_object_add(obj, wd->hover); - elm_widget_sub_object_add(obj, wd->target); evas_object_smart_callbacks_descriptions_set(obj, _signals); - return obj; -} - -/** - * This ends the Ctxpopup's popup as if the user had clicked - * outside the hover. - * - * @param obj The ctxpopup object - * - * @ingroup Ctxpopup - */ -EAPI void -elm_ctxpopup_hover_end(Evas_Object *obj) -{ - ELM_CHECK_WIDTYPE(obj, widtype); - - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) - return; - - if (!wd->hover) - return; - evas_object_hide(wd->hover); + return obj; } /** * Get the icon object for the given ctxpopup item. * * @param item Ctxpopup item - * @return icon object or @c NULL, if the item does not have icon or - * an error occurred + * @return icon object or @c NULL, if the item does not have icon or an error occurred * * @ingroup Ctxpopup */ @@ -459,21 +1026,20 @@ elm_ctxpopup_item_icon_get(const Elm_Ctxpopup_Item *item) } /** - * Sets the side icon associated with the ctxpopup item. + * Sets the side icon associated with the ctxpopup item * * Once the icon object is set, a previously set one will be deleted. * You probably don't want, then, to have the same icon object * set for more than one item of the list (when replacing one of its * instances). - * + * * @param item Ctxpopup item - * @param icon Icon object to be set + * @param icon Icon object to be set * * @ingroup Ctxpopup */ EAPI void -elm_ctxpopup_item_icon_set(Elm_Ctxpopup_Item *item, - Evas_Object *icon) +elm_ctxpopup_item_icon_set(Elm_Ctxpopup_Item *item, Evas_Object *icon) { ELM_CTXPOPUP_ITEM_CHECK_RETURN(item); @@ -481,27 +1047,25 @@ elm_ctxpopup_item_icon_set(Elm_Ctxpopup_Item *item, wd = elm_widget_data_get(item->base.widget); if (!wd) - return; + return; - if (item->icon) + _item_icon_set(item, icon); + + if (wd->visible) { - evas_object_del(item->icon); - item->icon = NULL; + _scroller_size_reset(wd); + _sizing_eval(item->base.widget); } - - item->icon = icon; - elm_list_item_icon_set(item->lptr, icon); - elm_list_go(wd->list); } /** * Get the label object for the given ctxpopup item. * * @param item Ctxpopup item - * @return label object or @c NULL, if the item does not have label or - * an error occur-ed + * @return label object or @c NULL, if the item does not have label or an error occured * * @ingroup Ctxpopup + * */ EAPI const char * elm_ctxpopup_item_label_get(const Elm_Ctxpopup_Item *item) @@ -513,14 +1077,13 @@ elm_ctxpopup_item_label_get(const Elm_Ctxpopup_Item *item) /** * (Re)set the label on the given ctxpopup item. * - * @param obj Ctxpopup item + * @param item Ctxpopup item * @param label String to set as label - * + * * @ingroup Ctxpopup */ EAPI void -elm_ctxpopup_item_label_set(Elm_Ctxpopup_Item *item, - const char *label) +elm_ctxpopup_item_label_set(Elm_Ctxpopup_Item *item, const char *label) { ELM_CTXPOPUP_ITEM_CHECK_RETURN(item); @@ -528,24 +1091,24 @@ elm_ctxpopup_item_label_set(Elm_Ctxpopup_Item *item, wd = elm_widget_data_get(item->base.widget); if (!wd) - return; + return; - if (!eina_stringshare_replace(&item->label, label)) - return; + _item_label_set(item, label); - elm_list_item_label_set(item->lptr, label); - elm_list_go(wd->list); + if (wd->visible) + { + _scroller_size_reset(wd); + _sizing_eval(item->base.widget); + } } /** - * Set the Ctxpopup's parent. - * - * Sets the hover's parent object (it would much probably be the - * window that the ctxpopup is in). See Hover objects for more - * information. + * Set the Ctxpopup's parent + * Set the parent object (it would much probably be the + * window that the ctxpopup is in). * * @param obj The ctxpopup object - * @param parent The parent to use + * @param area The parent to use * * @note elm_ctxpopup_add() will automatically call this function * with its @c parent argument. @@ -553,8 +1116,7 @@ elm_ctxpopup_item_label_set(Elm_Ctxpopup_Item *item, * @ingroup Ctxpopup */ EAPI void -elm_ctxpopup_hover_parent_set(Evas_Object *obj, - Evas_Object *parent) +elm_ctxpopup_hover_parent_set(Evas_Object *obj, Evas_Object *hover_parent) { ELM_CHECK_WIDTYPE(obj, widtype); @@ -562,37 +1124,29 @@ elm_ctxpopup_hover_parent_set(Evas_Object *obj, wd = elm_widget_data_get(obj); if (!wd) - return; - - EINA_SAFETY_ON_NULL_RETURN(parent); + return; - elm_hover_parent_set(wd->hover, parent); + _hover_parent_callbacks_del(obj); - if (wd->hover_parent) + if (hover_parent) { - evas_object_event_callback_del_full(wd->hover_parent, EVAS_CALLBACK_DEL, - _parent_del, obj); - evas_object_event_callback_del_full(wd->hover_parent, - EVAS_CALLBACK_RESIZE, - _parent_resize_cb, obj); + evas_object_event_callback_add(hover_parent, EVAS_CALLBACK_DEL, + _hover_parent_del, obj); + evas_object_event_callback_add(hover_parent, EVAS_CALLBACK_MOVE, + _hover_parent_move, obj); + evas_object_event_callback_add(hover_parent, EVAS_CALLBACK_RESIZE, + _hover_parent_resize, obj); } - wd->hover_parent = parent; - evas_object_event_callback_add(wd->hover_parent, EVAS_CALLBACK_DEL, - _parent_del, obj); - evas_object_event_callback_add(wd->hover_parent, EVAS_CALLBACK_RESIZE, - _parent_resize_cb, obj); - - _parent_resize_cb(obj, NULL, NULL, NULL); + wd->hover_parent = hover_parent; } /** - * Get the Ctxpopup's parent object. + * Get the Ctxpopup's parent * * @param obj The ctxpopup object - * @param parent The parent to use * - * See elm_ctxpopup_hover_parent_set() for more information. + * @see elm_ctxpopup_hover_parent_set() for more information * * @ingroup Ctxpopup */ @@ -605,11 +1159,33 @@ elm_ctxpopup_hover_parent_get(const Evas_Object *obj) wd = elm_widget_data_get(obj); if (!wd) - return NULL; + return NULL; return wd->hover_parent; } +static void +_remove_items(Widget_Data *wd) +{ + Eina_List *elist; + Elm_Ctxpopup_Item *item; + + if (!wd->items) + return; + + EINA_LIST_FOREACH(wd->items, elist, item) + { + if (item->label) + eina_stringshare_del(item->label); + if (item->icon) + evas_object_del(item->icon); + wd->items = eina_list_remove(wd->items, item); + free(item); + } + + wd->items = NULL; +} + /** * Clear all items in the given ctxpopup object. * @@ -618,38 +1194,29 @@ elm_ctxpopup_hover_parent_get(const Evas_Object *obj) * @ingroup Ctxpopup */ EAPI void -elm_ctxpopup_clear(Evas_Object *obj) +elm_ctxpopup_clear(Evas_Object * obj) { ELM_CHECK_WIDTYPE(obj, widtype); - Elm_Ctxpopup_Item *item; - Widget_Data *wd; - - wd = elm_widget_data_get(obj); - if ((!wd) || (!wd->items)) - return; + Widget_Data *wd = elm_widget_data_get(obj); - EINA_LIST_FREE(wd->items, item) - { - elm_list_item_del(item->lptr); - _item_free(item); - } + if (!wd) + return; - evas_object_hide(wd->hover); + _remove_items(wd); + _list_del(wd); } /** * Change the ctxpopup's orientation to horizontal or vertical. * * @param obj Ctxpopup object - * @param horizontal @c EINA_TRUE for horizontal mode, @c EINA_FALSE - * for vertical + * @param horizontal @c EINA_TRUE for horizontal mode, @c EINA_FALSE for vertical * * @ingroup Ctxpopup */ EAPI void -elm_ctxpopup_horizontal_set(Evas_Object *obj, - Eina_Bool horizontal) +elm_ctxpopup_horizontal_set(Evas_Object *obj, Eina_Bool horizontal) { ELM_CHECK_WIDTYPE(obj, widtype); @@ -657,21 +1224,33 @@ elm_ctxpopup_horizontal_set(Evas_Object *obj, wd = elm_widget_data_get(obj); if (!wd) - return; + return; - if (wd->horizontal == horizontal) - return; + wd->horizontal = !!horizontal; - wd->horizontal = horizontal; - elm_list_horizontal_set(wd->list, horizontal); + if ((!wd->scr) && (!wd->box)) + return; + + if (!horizontal) + { + elm_box_horizontal_set(wd->box, EINA_FALSE); + elm_scroller_bounce_set(wd->scr, EINA_FALSE, EINA_TRUE); + } + else + { + elm_box_horizontal_set(wd->box, EINA_TRUE); + elm_scroller_bounce_set(wd->scr, EINA_TRUE, EINA_FALSE); + } + + if (wd->visible) + _sizing_eval(obj); } /** * Get the value of current ctxpopup object's orientation. * * @param obj Ctxpopup object - * @return @c EINA_TRUE for horizontal mode, @c EINA_FALSE for - * vertical mode (or errors) + * @return @c EINA_TRUE for horizontal mode, @c EINA_FALSE for vertical mode (or errors) * * @ingroup Ctxpopup */ @@ -684,47 +1263,72 @@ elm_ctxpopup_horizontal_get(const Evas_Object *obj) wd = elm_widget_data_get(obj); if (!wd) - return EINA_FALSE; + return EINA_FALSE; return wd->horizontal; } /** - * Append a new item to a ctxpopup object. + * Add a new item to a ctxpopup object. + * + * Both a item list and a content could not be set at the same time! + * once you set add a item, the previous content will be removed. * * @param obj Ctxpopup object - * @param label The label of the new item - * @param icon Icon to be set on new item + * @param icon Icon to be set on new item + * @param label The Label of the new item * @param func Convenience function called when item selected * @param data Data passed to @p func above * @return A handle to the item added or @c NULL, on errors - * + * * @ingroup Ctxpopup */ EAPI Elm_Ctxpopup_Item * -elm_ctxpopup_item_append(Evas_Object *obj, - const char *label, - Evas_Object *icon, - Evas_Smart_Cb func, - const void *data) +elm_ctxpopup_item_append(Evas_Object *obj, const char *label, + Evas_Object *icon, Evas_Smart_Cb func, + const void *data) { ELM_CHECK_WIDTYPE(obj, widtype) NULL; - Elm_Ctxpopup_Item *item; Widget_Data *wd; + Elm_Ctxpopup_Item *item; wd = elm_widget_data_get(obj); if (!wd) - return NULL; + return NULL; - item = _item_new(obj, label, icon, func, data); + item = elm_widget_item_new(obj, Elm_Ctxpopup_Item); if (!item) - return NULL; + return NULL; + + //The first item is appended. + if (wd->content) + evas_object_del(elm_ctxpopup_content_unset(obj)); + + if (!wd->items) + _list_new(obj); + item->func = func; + item->base.data = data; + + if (icon && label) + _item_new(item, "icon_text_style_item"); + else if (label) + _item_new(item, "text_style_item"); + else + _item_new(item, "icon_style_item"); + + _item_icon_set(item, icon); + _item_label_set(item, label); + elm_box_pack_end(wd->box, item->base.view); wd->items = eina_list_append(wd->items, item); - item->lptr = elm_list_item_append(wd->list, label, icon, NULL, - _item_func_cb, item); - elm_list_go(wd->list); + + if (wd->visible) + { + _scroller_size_reset(wd); + _sizing_eval(obj); + } + return item; } @@ -744,30 +1348,36 @@ elm_ctxpopup_item_del(Elm_Ctxpopup_Item *item) wd = elm_widget_data_get(item->base.widget); if (!wd) - return; + return; - wd->items = eina_list_remove(wd->items, item); + if (item->icon) + evas_object_del(item->icon); + if (item->base.view) + evas_object_del(item->base.view); - elm_list_item_del(item->lptr); - item->lptr = NULL; + eina_stringshare_del(item->label); + + wd->items = eina_list_remove(wd->items, item); if (eina_list_count(wd->items) < 1) - evas_object_hide(wd->hover); + wd->items = NULL; + + if (wd->visible) + _sizing_eval(item->base.widget); - _item_free(item); + free(item); } /** - * Set the ctxpopup item's state as disabled or enabled + * Set the ctxpopup item's state as disabled or enabled. * * @param item Ctxpopup item to be enabled/disabled - * @param disabled @c EINA_TRUE to disable it, @c EINA_FALSE to enable + * @param disabled @c EINA_TRUE to disable it, @c EINA_FALSE to enable it * * @ingroup Ctxpopup */ EAPI void -elm_ctxpopup_item_disabled_set(Elm_Ctxpopup_Item *item, - Eina_Bool disabled) +elm_ctxpopup_item_disabled_set(Elm_Ctxpopup_Item *item, Eina_Bool disabled) { ELM_CTXPOPUP_ITEM_CHECK_RETURN(item); @@ -775,20 +1385,24 @@ elm_ctxpopup_item_disabled_set(Elm_Ctxpopup_Item *item, wd = elm_widget_data_get(item->base.widget); if (!wd) - return; + return; if (disabled == item->disabled) - return; + return; + + if (disabled) + edje_object_signal_emit(item->base.view, "elm,state,disabled", "elm"); + else + edje_object_signal_emit(item->base.view, "elm,state,enabled", "elm"); - item->disabled = disabled; - elm_list_item_disabled_set(item->lptr, disabled); + item->disabled = !!disabled; } /** * Get the ctxpopup item's disabled/enabled state. * * @param item Ctxpopup item to be enabled/disabled - * @return @c EINA_TRUE, if disabled, @c EINA_FALSE otherwise + * @return disabled @c EINA_TRUE, if disabled, @c EINA_FALSE otherwise * * @ingroup Ctxpopup */ @@ -800,3 +1414,153 @@ elm_ctxpopup_item_disabled_get(const Elm_Ctxpopup_Item *item) return item->disabled; } +/** + * Once the content object is set, a previously set one will be deleted. + * If you want to keep that old content object, use the + * elm_ctxpopup_content_unset() function + * + * Both a item list and a content could not be set at the same time! + * once you set a content, the previous list items will be removed. + * + * @param obj Ctxpopup object + * @param content Content to be swallowed + * + * @ingroup Ctxpopup + */ +EAPI void +elm_ctxpopup_content_set(Evas_Object *obj, Evas_Object *content) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + + Widget_Data *wd; + + wd = elm_widget_data_get(obj); + if ((!wd) || (!content)) + return; + + if (wd->items) + elm_ctxpopup_clear(obj); + + if (wd->content) + evas_object_del(wd->content); + + evas_object_event_callback_add(content, EVAS_CALLBACK_DEL, _content_del, + obj); + + elm_widget_sub_object_add(obj, content); + edje_object_part_swallow(wd->base, "elm.swallow.content", content); + edje_object_message_signal_process(wd->base); + + wd->content = content; + + if (wd->visible) + _sizing_eval(obj); +} + +/** + * Unset the ctxpopup content + * + * Unparent and return the content object which was set for this widget + * + * @param obj Ctxpopup object + * @return The content that was being used + * + * @ingroup Ctxpopup + */ +EAPI Evas_Object * +elm_ctxpopup_content_unset(Evas_Object *obj) +{ + ELM_CHECK_WIDTYPE(obj, widtype) NULL; + + Widget_Data *wd; + Evas_Object *content; + + wd = elm_widget_data_get(obj); + if (!wd) + return NULL; + + content = wd->content; + if (!content) + return NULL; + + edje_object_part_unswallow(wd->base, content); + elm_widget_sub_object_del(obj, content); + evas_object_event_callback_del(content, EVAS_CALLBACK_DEL, _content_del); + edje_object_signal_emit(wd->base, "elm,state,content,disable", "elm"); + + wd->content = NULL; + + return content; +} + +/** + * Set the direction priority of a ctxpopup. + * This functions gives a chance to user to set the priority of ctxpopup showing direction. + * + * @param obj Ctxpopup object + * @param first 1st priority of direction + * @param second 2nd priority of direction + * @param third 3th priority of direction + * @param fourth 4th priority of direction + * + * @ingroup Ctxpopup + */ +EAPI void +elm_ctxpopup_direction_priority_set(Evas_Object *obj, + Elm_Ctxpopup_Direction first, + Elm_Ctxpopup_Direction second, + Elm_Ctxpopup_Direction third, + Elm_Ctxpopup_Direction fourth) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd; + + wd = elm_widget_data_get(obj); + if (!wd) + return; + + wd->dir_priority[0] = first; + wd->dir_priority[1] = second; + wd->dir_priority[2] = third; + wd->dir_priority[3] = fourth; + + if (wd->visible) + _sizing_eval(obj); +} + +/** + * Get the direction priority of a ctxpopup. + * + * @param obj Ctxpopup object + * @param first 1st priority of direction to be returned + * @param second 2nd priority of direction to be returned + * @param third 3th priority of direction to be returned + * @param fourth 4th priority of direction to be returned + * + * @see elm_ctxpopup_direction_priority_set for more information. + * + * @ingroup Ctxpopup + */ +EAPI void +elm_ctxpopup_direction_priority_get(Evas_Object *obj, + Elm_Ctxpopup_Direction *first, + Elm_Ctxpopup_Direction *second, + Elm_Ctxpopup_Direction *third, + Elm_Ctxpopup_Direction *fourth) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd; + + wd = elm_widget_data_get(obj); + if (!wd) + return; + + if (first) + *first = wd->dir_priority[0]; + if (second) + *second = wd->dir_priority[1]; + if (third) + *third = wd->dir_priority[2]; + if (fourth) + *fourth = wd->dir_priority[3]; +} -- 2.7.4