From 652c23591e3f23c1d5c1b7c0c63630a9d342d07e Mon Sep 17 00:00:00 2001 From: Gustavo Sverzut Barbieri Date: Mon, 20 Aug 2012 23:58:10 -0300 Subject: [PATCH] gui: add editable entry support to simple popup. This refactors the internal popup to keep a context and store the entry and message, as well as a button. The logic is now changed to evaluate the context whenever there is at least a message or an entry. Dismiss button also uses the buttons_set() infra, which will delete previous buttons if any. --- data/themes/includes/popup.edc | 161 ++++++++++++++++++++++++- data/themes/includes/scroller.edc | 241 ++++++++++++++++++++++++++++++++++++++ dialer/gui.c | 216 ++++++++++++++++++++++++++++------ dialer/gui.h | 4 + 4 files changed, 583 insertions(+), 39 deletions(-) diff --git a/data/themes/includes/popup.edc b/data/themes/includes/popup.edc index 1a070e9..b88491e 100644 --- a/data/themes/includes/popup.edc +++ b/data/themes/includes/popup.edc @@ -371,8 +371,91 @@ group { } group { - name: "elm/entry/base/dialer-popup"; - alias: "elm/entry/base-noedit/dialer-popup"; + name: "elm/entry/cursor/dialer"; + parts { + part { + name: "cursor"; + type: RECT; + mouse_events: 0; + scale: 1; + description { + state: "default" 0.0; + color_class: "action"; + min: ITEM_PADDING (SEPARATOR_HEIGHT / 2); + align: 0.5 1.0; + rel1 { + relative: 0.0 1.0; + offset: 0 -1; + } + } + description { + state: "faded" 0.0; + inherit: "default" 0.0; + color: 255 255 255 128; + } + } + programs { + program { + name: "focus"; + signal: "elm,action,focus"; + source: "elm"; + action: ACTION_STOP; + target: "unfocus"; + target: "unfocus2"; + after: "focus2"; + } + program { + name: "focus2"; + action: STATE_SET "default" 0.0; + transition: ACCELERATE 0.3; + target: "cursor"; + after: "focus3"; + } + program { + name: "focus3"; + action: STATE_SET "faded" 0.0; + transition: ACCELERATE 0.3; + target: "cursor"; + after: "focus2"; + } + + program { + name: "unfocus"; + signal: "elm,action,unfocus"; + source: "elm"; + action: ACTION_STOP; + target: "focus"; + target: "focus2"; + target: "focus3"; + after: "unfocus2"; + } + program { + name: "unfocus2"; + action: STATE_SET "faded" 0.0; + transition: ACCELERATE 0.3; + target: "cursor"; + } + } + } +} + +group { + name: "elm/entry/selection/dialer"; + parts { + part { + name: "bg"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + color_class: "dark"; + } + } + } +} + +group { + name: "elm/entry/base-noedit/dialer-popup"; styles { style { @@ -388,6 +471,7 @@ group { tag: "br" "\n"; } } + parts { part { name: "elm.text"; @@ -395,6 +479,8 @@ group { mouse_events: 1; scale: 1; multiline: 1; + source: "elm/entry/selection/dialer"; + source4: "elm/entry/cursor/dialer"; description { state: "default" 0.0; text { @@ -435,3 +521,74 @@ group { } } } + +group { + name: "elm/entry/base/dialer-popup-editable"; + + styles { + style { + name: "entry_textblock_editable_style"; + base: "font="FONT_NORMAL" font_size="SIZE_MEDIUM" color="TEXTBLOCK_COLOR_ACTION" wrap=word valign=top align=auto"; + tag: "b" "+ font_weight=Bold"; + tag: "br" "\n"; + } + style { + name: "entry_textblock_editable_disabled_style"; + base: "font="FONT_NORMAL" font_size="SIZE_MEDIUM" color="TEXTBLOCK_COLOR_ACTION" wrap=word valign=top align=auto"; + tag: "b" "+ font_weight=Bold"; + tag: "br" "\n"; + } + } + + parts { + part { + name: "elm.text"; + type: TEXTBLOCK; + mouse_events: 1; + scale: 1; + entry_mode: EDITABLE; + select_mode: EXPLICIT; + source: "elm/entry/selection/dialer"; + source4: "elm/entry/cursor/dialer"; + multiline: 1; + description { + state: "default" 0.0; + align: 0.0 0.0; + text { + style: "entry_textblock_editable_style"; + min: 0 1; + max: 1 1; + align: -1.0 0.0; + } + } + description { + state: "disabled" 0.0; + inherit: "default" 0.0; + text { + style: "entry_textblock_editable_disabled_style"; + } + } + } + } + + programs { + program { + signal: "load"; + source: ""; + action: FOCUS_SET; + target: "elm.text"; + } + program { + signal: "elm,state,disabled"; + source: "elm"; + action: STATE_SET "disabled" 0.0; + target: "elm.text"; + } + program { + signal: "elm,state,enabled"; + source: "elm"; + action: STATE_SET "default" 0.0; + target: "elm.text"; + } + } +} diff --git a/data/themes/includes/scroller.edc b/data/themes/includes/scroller.edc index 6792afc..9237ba4 100644 --- a/data/themes/includes/scroller.edc +++ b/data/themes/includes/scroller.edc @@ -439,3 +439,244 @@ group { } } } + +group { + name: "elm/scroller/entry/dialer-popup-editable"; + + script { + public sbvis_v, sbalways_v, sbvis_timer; + public timer0(val) { + new v; + v = get_int(sbvis_v); + if (v) { + v = get_int(sbalways_v); + if (!v) { + emit("do-hide-vbar", ""); + set_int(sbvis_v, 0); + } + } + set_int(sbvis_timer, 0); + return 0; + } + } + + parts { + part { + name: "clipper"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + } + } + + part { + name: "bg-color"; + type: RECT; + clip_to: "clipper"; + description { + state: "default" 0.0; + color_class: "action"; + } + } + part { + name: "bg-nocolor"; + type: RECT; + clip_to: "clipper"; + description { + state: "default" 0.0; + color_class: "bg"; + rel1.offset: 1 1; + rel2.offset: -2 -2; + } + } + part { + name: "elm.swallow.content"; + clip_to: "clipper"; + type: SWALLOW; + description { + state: "default" 0.0; + rel1.offset: BORDER_PADDING 2; + rel2.offset: (-BORDER_PADDING - 1) -3; + } + } + + part { + name: "sb_vbar_clip_master"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + } + description { + state: "hidden" 0.0; + color: 255 255 255 0; + visible: 0; + } + } + + part { + name: "sb_vbar_clip"; + clip_to: "sb_vbar_clip_master"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + } + description { + state: "hidden" 0.0; + color: 255 255 255 0; + visible: 0; + } + } + + part { + name: "sb_vbar"; + type: RECT; + mouse_events: 0; + description { + state: "default" 0.0; + fixed: 1 1; + visible: 0; + min: SCROLLBAR_WIDTH SCROLLBAR_HEIGHT; + align: 1.0 0.0; + rel1 { + relative: 1.0 0.0; + offset: -3 2; + } + rel2 { + relative: 1.0 1.0; + offset: -3 -3; + } + } + } + + part { + name: "elm.dragable.vbar"; + type: RECT; + clip_to: "sb_vbar_clip"; + mouse_events: 0; + dragable { + x: 0 0 0; + y: 1 1 0; + confine: "sb_vbar"; + } + description { + state: "default" 0.0; + color: 255 255 255 255; + color_class: "light"; + fixed: 1 1; + min: SCROLLBAR_WIDTH SCROLLBAR_HEIGHT; + max: SCROLLBAR_WIDTH 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"; + } + } + } + } + + programs { + program { + signal: "load"; + source: ""; + script { + set_state(PART:"sb_vbar_clip", "hidden", 0.0); + set_int(sbvis_v, 0); + set_int(sbalways_v, 0); + set_int(sbvis_timer, 0); + } + } + + program { + name: "vbar_show"; + signal: "elm,action,show,vbar"; + source: "elm"; + action: STATE_SET "default" 0.0; + target: "sb_vbar_clip_master"; + } + + program { + name: "vbar_hide"; + signal: "elm,action,hide,vbar"; + 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"; + script { + new v; + v = get_int(sbvis_v); + v |= get_int(sbalways_v); + if (!v) { + set_int(sbalways_v, 1); + emit("do-show-vbar", ""); + set_int(sbvis_v, 1); + } + } + } + + program { + name: "vbar_show_notalways"; + signal: "elm,action,show_notalways,vbar"; + source: "elm"; + script { + new v; + v = get_int(sbalways_v); + if (v) { + set_int(sbalways_v, 0); + v = get_int(sbvis_v); + if (!v) { + emit("do-hide-vbar", ""); + set_int(sbvis_v, 0); + } + } + } + } + + program { + signal: "do-show-vbar"; + source: ""; + action: STATE_SET "default" 0.0; + transition: LINEAR 0.5; + target: "sb_vbar_clip"; + } + + program { + signal: "do-hide-vbar"; + source: ""; + action: STATE_SET "hidden" 0.0; + transition: LINEAR 0.5; + target: "sb_vbar_clip"; + } + + program { + name: "scroll"; + signal: "elm,action,scroll"; + source: "elm"; + script { + new v; + v = get_int(sbvis_v); + v |= get_int(sbalways_v); + if (!v) { + emit("do-show-vbar", ""); + set_int(sbvis_v, 1); + } + v = get_int(sbvis_timer); + if (v > 0) cancel_timer(v); + v = timer(1.0, "timer0", 0); + set_int(sbvis_timer, v); + } + } + } +} diff --git a/dialer/gui.c b/dialer/gui.c index 3f71e33..9f78262 100644 --- a/dialer/gui.c +++ b/dialer/gui.c @@ -52,6 +52,15 @@ static void _gui_show(Evas_Object *o) elm_object_focus_set(o, EINA_TRUE); } +typedef struct _Simple_Popup +{ + Evas_Object *popup; + Evas_Object *box; + Evas_Object *message; + Evas_Object *entry; + Ecore_Timer *recalc_timer; /* HACK */ +} Simple_Popup; + static void _popup_close(void *data, Evas_Object *bt __UNUSED__, void *event __UNUSED__) { Evas_Object *popup = data; @@ -70,65 +79,169 @@ void gui_simple_popup_title_set(Evas_Object *p, const char *title) } /* HACK: force recalc from an idler to fix elm_entry problem */ -static Eina_Bool _gui_simple_popup_message_reeval(void *data) +static Eina_Bool _gui_simple_popup_entries_reeval(void *data) { - Evas_Object *en = data; - elm_entry_calc_force(en); - evas_object_data_del(en, "reeval_timer"); + Simple_Popup *ctx = data; + if (ctx->message) + elm_entry_calc_force(ctx->message); + if (ctx->entry) + elm_entry_calc_force(ctx->entry); + ctx->recalc_timer = NULL; return EINA_FALSE; } -static void _gui_simple_popup_message_reeval_del(void *data __UNUSED__, - Evas *e __UNUSED__, - Evas_Object *en, - void *einfo __UNUSED__) +static void _gui_simple_popup_timer_cancel_if_needed(Simple_Popup *ctx) +{ + if (!ctx->recalc_timer) + return; + if (ctx->message || ctx->entry) + return; + ecore_timer_del(ctx->recalc_timer); + ctx->recalc_timer = NULL; +} + +static void _gui_simple_popup_message_del(void *data, Evas *e __UNUSED__, + Evas_Object *en __UNUSED__, + void *einfo __UNUSED__) +{ + Simple_Popup *ctx = data; + ctx->message = NULL; + _gui_simple_popup_timer_cancel_if_needed(ctx); +} + +static void _gui_simple_popup_entry_del(void *data, Evas *e __UNUSED__, + Evas_Object *en __UNUSED__, + void *einfo __UNUSED__) { - Ecore_Timer *timer = evas_object_data_del(en, "reeval_timer"); - if (timer) - ecore_timer_del(timer); + Simple_Popup *ctx = data; + ctx->entry = NULL; + _gui_simple_popup_timer_cancel_if_needed(ctx); +} + +static void _gui_simple_popup_reeval_content(Simple_Popup *ctx) +{ + if ((!ctx->message) && (!ctx->entry)) { + elm_object_part_content_unset(ctx->popup, + "elm.swallow.content"); + elm_object_signal_emit(ctx->popup, "hide,content", "gui"); + evas_object_hide(ctx->box); + return; + } + + elm_box_unpack_all(ctx->box); + if (ctx->message) { + elm_box_pack_end(ctx->box, ctx->message); + evas_object_show(ctx->message); + } + if (ctx->entry) { + elm_box_pack_end(ctx->box, ctx->entry); + evas_object_show(ctx->entry); + } + + elm_object_part_content_set(ctx->popup, "elm.swallow.content", + ctx->box); + elm_object_signal_emit(ctx->popup, "show,content", "gui"); + + /* HACK: elm_entry is not evaluating properly and the text is + * not centered as it should be. Then we must force a + * calculation from an timer. + */ + if (ctx->recalc_timer) + ecore_timer_del(ctx->recalc_timer); + ctx->recalc_timer = ecore_timer_add( + 0.02, _gui_simple_popup_entries_reeval, ctx); } void gui_simple_popup_message_set(Evas_Object *p, const char *msg) { + Simple_Popup *ctx = evas_object_data_get(p, "simple_popup"); Evas_Object *en; - Ecore_Timer *timer; + + EINA_SAFETY_ON_NULL_RETURN(ctx); if (!msg) { - elm_object_part_content_set(p, "elm.swallow.content", NULL); - elm_object_signal_emit(p, "hide,content", "gui"); + if (ctx->message) + evas_object_del(ctx->message); + _gui_simple_popup_reeval_content(ctx); return; } - en = elm_entry_add(p); - elm_object_style_set(en, "dialer-popup"); - elm_entry_editable_set(en, EINA_FALSE); + if (ctx->message) + en = ctx->message; + else { + en = ctx->message = elm_entry_add(p); + elm_object_style_set(en, "dialer-popup"); + elm_entry_editable_set(en, EINA_FALSE); + elm_entry_scrollable_set(en, EINA_TRUE); + elm_entry_scrollbar_policy_set(en, ELM_SCROLLER_POLICY_OFF, + ELM_SCROLLER_POLICY_AUTO); + + evas_object_event_callback_add(en, EVAS_CALLBACK_DEL, + _gui_simple_popup_message_del, + ctx); + evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(en, EVAS_HINT_FILL, + EVAS_HINT_FILL); + } + + elm_object_text_set(en, msg); + _gui_simple_popup_reeval_content(ctx); +} + +void gui_simple_popup_entry_enable(Evas_Object *p) +{ + Simple_Popup *ctx = evas_object_data_get(p, "simple_popup"); + Evas_Object *en; + + EINA_SAFETY_ON_NULL_RETURN(ctx); + + if (ctx->entry) + return; + en = ctx->entry = elm_entry_add(p); + elm_object_style_set(en, "dialer-popup-editable"); + elm_entry_editable_set(en, EINA_TRUE); elm_entry_scrollable_set(en, EINA_TRUE); elm_entry_scrollbar_policy_set(en, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO); - elm_object_text_set(en, msg); - elm_object_part_content_set(p, "elm.swallow.content", en); - elm_object_signal_emit(p, "show,content", "gui"); - /* HACK: elm_entry is not evaluating properly and the text is - * not centered as it should be. Then we must force a - * calculation from an timer. - */ - timer = ecore_timer_add(0.02, _gui_simple_popup_message_reeval, en); - evas_object_data_set(en, "reeval_timer", timer); + evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(en, EVAS_HINT_FILL, + EVAS_HINT_FILL); + evas_object_event_callback_add(en, EVAS_CALLBACK_DEL, - _gui_simple_popup_message_reeval_del, - NULL); + _gui_simple_popup_entry_del, + ctx); + _gui_simple_popup_reeval_content(ctx); } -void gui_simple_popup_button_dismiss_set(Evas_Object *p) +void gui_simple_popup_entry_disable(Evas_Object *p) +{ + Simple_Popup *ctx = evas_object_data_get(p, "simple_popup"); + EINA_SAFETY_ON_NULL_RETURN(ctx); + if (!ctx->entry) + return; + evas_object_del(ctx->entry); + _gui_simple_popup_reeval_content(ctx); +} + +const char *gui_simple_popup_entry_get(const Evas_Object *p) { - Evas_Object *bt = elm_button_add(p); - elm_object_style_set(bt, "dialer"); - elm_object_text_set(bt, "Dismiss"); + Simple_Popup *ctx = evas_object_data_get(p, "simple_popup"); + EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(ctx->entry, NULL); + return elm_object_text_get(ctx->entry); +} - elm_object_part_content_set(p, "elm.swallow.button1", bt); - elm_object_signal_emit(p, "buttons,1", "gui"); - evas_object_smart_callback_add(bt, "clicked", _popup_close, p); +void gui_simple_popup_button_dismiss_set(Evas_Object *p) +{ + gui_simple_popup_buttons_set(p, + "Dismiss", + "dialer", + _popup_close, + NULL, NULL, NULL, + p); } void gui_simple_popup_buttons_set(Evas_Object *p, @@ -170,19 +283,44 @@ void gui_simple_popup_buttons_set(Evas_Object *p, if (count == 2) elm_object_signal_emit(p, "buttons,2", "gui"); - else if (count == 1) + else if (count == 1) { elm_object_signal_emit(p, "buttons,1", "gui"); - else + elm_object_part_content_set(p, "elm.swallow.button2", NULL); + } else { elm_object_signal_emit(p, "buttons,0", "gui"); + elm_object_part_content_set(p, "elm.swallow.button1", NULL); + elm_object_part_content_set(p, "elm.swallow.button2", NULL); + } +} + +static void _gui_simple_popup_del(void *data, Evas *e __UNUSED__, + Evas_Object *o __UNUSED__, + void *event_info __UNUSED__) +{ + Simple_Popup *ctx = data; + free(ctx); } Evas_Object *gui_simple_popup(const char *title, const char *message) { Evas_Object *p = gui_layout_add(win, "popup"); + Simple_Popup *ctx; + + EINA_SAFETY_ON_NULL_RETURN_VAL(p, NULL); + + ctx = calloc(1, sizeof(Simple_Popup)); + EINA_SAFETY_ON_NULL_GOTO(ctx, failed_calloc); + + evas_object_data_set(p, "simple_popup", ctx); + ctx->popup = p; + evas_object_event_callback_add(p, EVAS_CALLBACK_DEL, + _gui_simple_popup_del, ctx); evas_object_size_hint_weight_set(p, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_win_resize_object_add(win, p); + ctx->box = elm_box_add(p); + gui_simple_popup_title_set(p, title); gui_simple_popup_message_set(p, message); gui_simple_popup_button_dismiss_set(p); @@ -190,6 +328,10 @@ Evas_Object *gui_simple_popup(const char *title, const char *message) evas_object_show(p); return p; + +failed_calloc: + evas_object_del(p); + return NULL; } void gui_activate(void) diff --git a/dialer/gui.h b/dialer/gui.h index 3281e8a..6c1c5bd 100644 --- a/dialer/gui.h +++ b/dialer/gui.h @@ -20,6 +20,10 @@ void gui_simple_popup_buttons_set(Evas_Object *p, Evas_Smart_Cb b2_cb, const void *data); +void gui_simple_popup_entry_enable(Evas_Object *p); +void gui_simple_popup_entry_disable(Evas_Object *p); +const char *gui_simple_popup_entry_get(const Evas_Object *p); + void gui_activate(void); void gui_number_set(const char *number, Eina_Bool auto_dial); -- 2.7.4