/* * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include "i18n.h" #include "bar.h" #include "engine.h" #include "defs.h" #include "dbg.h" #define XBAR_W 647 #define XBAR_H 31 #define BTN_MAX 3 #define TITLE_MAX 128 #define MESSAGE_MAX 256 #define POPUP_DUR 3.0 #define TITLE_DELETE "Clear" #define TITLE_BANNER "All items are deleted" #define TITLE_NOTIFICATION "Notification" #define TITLE_HISTORY "History" #define MESSAGE_DELETE "Are you sure you want to clear your" #define MESSAGE_BANNER "is deleted" #define MESSAGE_NOTIFICATION "notification" #define MESSAGE_HISTORY "history" enum _xbar_state { XBAR_STATE_HIDE, XBAR_STATE_XBAR, XBAR_STATE_POPUP }; struct _xbar_data { Evas_Object *base; Evas_Object *ly; Evas_Object *bg; Evas_Object *popup; Evas_Object *btn[BTN_MAX]; struct bar_cb focus_cb; struct engine *eng; struct engine_dbar_item *it; struct bar_info *xbar; enum _xbar_state state; }; struct _btn_info { const char *part; const char *text; void (*click_cb)(void *, Evas *, Evas_Object *, void *e); }; static void _release(struct bar_info *info) { struct _xbar_data *bar; if (!info || !info->data) { _ERR("Invalid argument"); return; } bar = info->data; if (bar) { evas_object_del(bar->ly); free(bar); bar = NULL; } free(info); info = NULL; } static void _mouse_over(void *data, Evas *e, Evas_Object *obj, void *ei) { struct _xbar_data *bar; if (!data) { _ERR("Invalid argument"); return; } bar = data; if (elm_object_focus_get(bar->ly)) return; elm_object_focus_set(bar->ly, EINA_TRUE); } static Eina_Bool _add_popup(struct bar_info *info); static void _clicked(void *data, Evas *e, Evas_Object *obj, void *ei) { struct _xbar_data *bar; if (!data || !ei) return; bar = data; if (bar->state == XBAR_STATE_POPUP) { _ERR("popup already created"); return; } if (!elm_object_focus_get(bar->ly)) { _ERR("eo isn't focused"); return; } _add_popup(bar->xbar); } static void _focused(void *data, Evas_Object *obj, void *ei) { struct _xbar_data *bar; if (!data) { _ERR("Invalid argument"); return; } bar = data; bar->focus_cb.func(bar->focus_cb.data, bar->ly); bar->state = XBAR_STATE_XBAR; } static void _free_popup(struct _xbar_data *bar) { if (!bar) { _ERR("Invalid argument"); return; } if (!bar->popup) return; evas_object_del(bar->popup); bar->popup = NULL; bar->state = XBAR_STATE_XBAR; } static enum engine_dbar_content_type _get_ctnt_type(struct engine_dbar_item *it) { struct engine_dbar_item_content *ctnt; const Eina_List *ctnts; if (!it) { _ERR("Invalid argument"); return -1; } ctnts = engine_dbar_item_get_contents(it); if (!ctnts) return -1; ctnt = eina_list_data_get(ctnts); if (!ctnt) return -1; return engine_dbar_item_get_content_type(ctnt); } static void _add_banner(struct _xbar_data *bar, char *message) { Evas_Object *banner, *win; if (!bar || !message) { _ERR("Invalid argument"); return; } win = elm_object_top_widget_get(bar->base); if (!win) { _ERR("failed to get win eo"); return; } banner = elm_popup_add(win); if (!banner) { _ERR("failed to create popup"); return; } elm_object_style_set(banner, STYLE_POPUP_BOTTOM_1LINE); elm_popup_orient_set(banner, ELM_POPUP_ORIENT_BOTTOM); elm_object_text_set(banner, message); elm_popup_timeout_set(banner, POPUP_DUR); elm_object_focus_allow_set(banner, EINA_FALSE); evas_object_show(banner); } static void _del_item(struct _xbar_data *bar) { enum engine_dbar_content_type type; char message[MESSAGE_MAX]; if (!bar) { _ERR("Invalid argument"); return; } type = _get_ctnt_type(bar->it); if (type < 0) { _ERR("failed to get ctnt type"); return; } snprintf(message, sizeof(message), "'%s' %s", engine_dbar_item_get_name(bar->it), MESSAGE_BANNER); _free_popup(bar); _add_banner(bar, message); } static void _del_all_item(struct _xbar_data *bar) { enum engine_dbar_content_type type; if (!bar) { _ERR("Invalid argument"); return; } type = _get_ctnt_type(bar->it); if (type < 0) { _ERR("failed to get ctnt type"); return; } _free_popup(bar); _add_banner(bar, TITLE_BANNER); } static void _del_clicked(void *data, Evas *e, Evas_Object *obj, void *ei) { _del_item(data); } static void _del_all_clicked(void *data, Evas *e, Evas_Object *obj, void *ei) { _del_all_item(data); } static void _cancel_clicked(void *data, Evas *e, Evas_Object *obj, void *ei) { struct _xbar_data *bar; if (!data) { _ERR("Invalid argument"); return; } bar = data; _free_popup(bar); elm_object_signal_emit(bar->ly, SIG_CANCEL_CLICKED, SRC_PROG); } static void _btn_mouse_over(void *data, Evas *e, Evas_Object *obj, void *ei) { elm_object_focus_set(obj, EINA_TRUE); } static int _add_btn(struct _xbar_data *bar, Evas_Object *popup) { Evas_Object *btn; struct _btn_info btn_info[] = { { "button1", "Delete", _del_clicked }, { "button2", "Delete All", _del_all_clicked }, { "button3", "Cancel", _cancel_clicked } }; int i; if (!bar || !popup) { _ERR("Invalid argument"); return -1; } for (i = 0; i < sizeof(btn_info) / sizeof(*btn_info); i++) { btn = elm_button_add(popup); if (!btn) { _ERR("failed to create button"); memset(bar->btn, 0x00, sizeof(bar->btn)); return -1; } elm_object_part_content_set(popup, btn_info[i].part, btn); elm_object_text_set(btn, btn_info[i].text); evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_show(btn); bar->btn[i] = btn; evas_object_event_callback_add(btn, EVAS_CALLBACK_MOUSE_DOWN, btn_info[i].click_cb, bar); evas_object_event_callback_add(btn, EVAS_CALLBACK_MOUSE_MOVE, _btn_mouse_over, bar); if (i == 0) elm_object_focus_set(btn, EINA_TRUE); } return 0; } static Evas_Object *_load_popup(Evas_Object *base, enum engine_dbar_content_type type) { Evas_Object *popup; char title[TITLE_MAX]; char message[MESSAGE_MAX]; if (!base || type < 0) { _ERR("Invalid argument"); return NULL; } popup = elm_popup_add(base); if (!popup) { _ERR("failed to create popup"); return NULL; } elm_object_style_set(popup, STYLE_POPUP_1LINE_2BUTTON); elm_object_part_text_set(popup, PART_POPUP_TEXT, TITLE_DELETE); elm_object_focus_allow_set(popup, EINA_FALSE); evas_object_show(popup); switch (type) { case ENGINE_DBAR_CONTENT_TYPE_NOTIFICATION_NOTI: snprintf(title, sizeof(title), "%s %s", TITLE_DELETE, TITLE_NOTIFICATION); snprintf(message, sizeof(message), "%s %s?", MESSAGE_DELETE, MESSAGE_NOTIFICATION); break; case ENGINE_DBAR_CONTENT_TYPE_HISTORY: snprintf(title, sizeof(title), "%s %s", TITLE_DELETE, TITLE_HISTORY); snprintf(message, sizeof(message), "%s %s?", MESSAGE_DELETE, MESSAGE_HISTORY); break; default: _ERR("Invalid Type"); evas_object_del(popup); return NULL; } elm_object_text_set(popup, message); elm_object_part_text_set(popup, PART_POPUP_TEXT, title); return popup; } static Eina_Bool _add_popup(struct bar_info *info) { struct _xbar_data *bar; Evas_Object *popup, *win; enum engine_dbar_content_type type; int r; if (!info) { _ERR("Invalid argument"); return EINA_FALSE; } bar = info->data; if (bar->popup) { _ERR("Already popup created"); evas_object_del(bar->popup); bar->popup = NULL; return EINA_FALSE; } win = elm_object_top_widget_get(bar->base); if (!win) { _ERR("failed to get win eo"); return EINA_FALSE; } type = _get_ctnt_type(bar->it); if (type < 0) { _ERR("failed to get ctnt type"); return EINA_FALSE; } popup = _load_popup(win, type); if (!popup) { _ERR("failed to add popup"); return EINA_FALSE; } r = _add_btn(bar, popup); if (r < 0) { _ERR("failed to add btn"); evas_object_del(popup); return EINA_FALSE; } bar->popup = popup; bar->state = XBAR_STATE_POPUP; return EINA_TRUE; } static enum bar_event _enter(struct bar_info *info) { struct _xbar_data *bar; Eina_Bool r; if (!info) { _ERR("Invalid argument"); return BAR_EVENT_ERROR; } bar = info->data; r = EINA_FALSE; switch (bar->state) { case XBAR_STATE_XBAR: r = _add_popup(info); break; case XBAR_STATE_POPUP: if (!bar->popup) return BAR_EVENT_ERROR; if (elm_object_focus_get(bar->btn[0])) { _del_item(bar); r = EINA_TRUE; } else if (elm_object_focus_get(bar->btn[1])) { _del_all_item(bar); r = EINA_TRUE; } else if (elm_object_focus_get(bar->btn[2])) { _free_popup(bar); return BAR_EVENT_MOVE; } break; default: return BAR_EVENT_ERROR; } return r ? BAR_EVENT_DONE : BAR_EVENT_PASS; } static Eina_Bool _is_move(struct bar_info *info, int dir) { if (!info) { _ERR("Invalid argument"); return EINA_FALSE; } return EINA_TRUE; } static enum bar_event _back(struct bar_info *info) { struct _xbar_data *bar; if (!info) { _ERR("Invalid argument"); return BAR_EVENT_ERROR; } bar = info->data; switch (bar->state) { case XBAR_STATE_XBAR: return BAR_EVENT_MOVE; case XBAR_STATE_POPUP: if (!bar->popup) break; _free_popup(bar); return BAR_EVENT_MOVE; default: break; } return BAR_EVENT_ERROR; } static enum bar_event _key_down(struct bar_info *info, void *ei) { struct _xbar_data *bar; Ecore_Event_Key *ev; enum bar_event r; if (!info || !ei) return BAR_EVENT_ERROR; ev = ei; bar = info->data; if (!strcmp(ev->keyname, KEY_ENTER)) { r = _enter(info); } else if (!strcmp(ev->keyname, KEY_RIGHT)) { r = BAR_EVENT_PASS; } else if (!strcmp(ev->keyname, KEY_LEFT)) { if (bar->state == XBAR_STATE_XBAR) r = BAR_EVENT_MOVE; else r = BAR_EVENT_PASS; } else if (!strcmp(ev->keyname, KEY_BACK)) { r = _back(info); } else r = BAR_EVENT_DONE; return r; } static inline Evas_Object *_add_item_bg(Evas_Object *base, struct engine_dbar_item *it) { Evas_Object *bg; int r, g, b; if (!base || !it) { _ERR("Invalid argument"); return NULL; } bg = evas_object_rectangle_add(evas_object_evas_get(base)); if (!bg) { _ERR("bg add failed"); return NULL; } r = ITEM_DEFAULT_BG_R; g = ITEM_DEFAULT_BG_G; b = ITEM_DEFAULT_BG_B; engine_dbar_item_get_color(it, &r, &g, &b); evas_object_color_set(bg, r, g, b, 255); return bg; } static Eina_Bool _move(struct bar_info *info) { struct _xbar_data *bar; if (!info || !info->data) { _ERR("Invalid argument"); return EINA_FALSE; } bar = info->data; elm_object_focus_allow_set(bar->ly, EINA_TRUE); elm_object_focus_set(bar->ly, EINA_TRUE); return EINA_TRUE; } static Evas_Object *_get_object(struct bar_info *info) { struct _xbar_data *bar; if (!info || !info->data) { _ERR("Invalid argument"); return NULL; } bar = info->data; return bar->ly; } static int _update(struct bar_info *info, void *eng, void *data) { struct _xbar_data *bar; Evas_Object *bg1, *bg2, *eo; Evas_Coord x, y; if (!info || !info->data || !eng || !data) { _ERR("Invalid argument"); return -1; } bar = info->data; eo = data; if (!bar->bg) { bg1 = _add_item_bg(bar->ly, eng); if (!bg1) { _ERR("bg add failed"); return -1; } elm_object_part_content_set(bar->ly, PART_BG, bg1); bg2 = _add_item_bg(bar->ly, eng); if (!bg2) { _ERR("bg add failed"); evas_object_del(bg1); return -1; } elm_object_part_content_set(bar->ly, PART_BG2, bg2); evas_object_color_set(bg2, 0, 0, 0, 216); bar->bg = bg1; } elm_object_focus_allow_set(bar->ly, EINA_TRUE); evas_object_show(bar->ly); evas_object_geometry_get(eo, &x, &y, NULL, NULL); evas_object_move(bar->ly, (x + XBAR_W) * elm_config_scale_get(), (y + XBAR_H) * elm_config_scale_get()); bar->it = eng; bar->state = XBAR_STATE_XBAR; return 0; } static int _add_bar(struct bar_info *info, Evas_Object *base) { Evas_Object *ly; struct _xbar_data *bar; if (!base || !info || !info->data) { _ERR("Invalid argument"); return -1; } bar = info->data; ly = elm_layout_add(base); if (!ly) { _ERR("layout add failed"); return -1; } elm_layout_file_set(ly, EDJEFILE, GRP_CBAR_X); evas_object_smart_callback_add(ly, "focused", _focused, bar); evas_object_event_callback_add(ly, EVAS_CALLBACK_MOUSE_UP, _clicked, bar); evas_object_event_callback_add(ly, EVAS_CALLBACK_MOUSE_MOVE, _mouse_over, bar); bar->base = base; bar->ly = ly; bar->xbar = info; return 0; } static void _hide(struct bar_info *info) { struct _xbar_data *bar; if (!info) { _ERR("Invalid argument"); return; } bar = info->data; elm_object_signal_emit(bar->ly, SIG_HIDE, SRC_PROG); elm_object_signal_emit(bar->ly, SIG_HIDE_TO_HBAR, SRC_PROG); elm_object_focus_set(bar->ly, EINA_FALSE); elm_object_focus_allow_set(bar->ly, EINA_FALSE); bar->state = XBAR_STATE_HIDE; } static void _show(struct bar_info *info) { struct _xbar_data *bar; if (!info) { _ERR("Invalid argument"); return; } bar = info->data; elm_object_focus_allow_set(bar->ly, EINA_TRUE); elm_object_focus_set(bar->ly, EINA_TRUE); } static struct bar_ops xbar_ops = { .add_bar = _add_bar, .update = _update, .get_object = _get_object, .is_move = _is_move, .move = _move, .show = _show, .hide = _hide, .key_down = _key_down, .release = _release, }; int init_delete_bar(struct bar_info *info) { struct _xbar_data *bar; if (!info) return -1; bar = calloc(1, sizeof(*bar)); if (!bar) { _ERR("calloc failed"); return -1; } info->data = bar; info->ops = &xbar_ops; if (!info->cb.func) { _ERR("invalid callback function"); free(bar); return -1; } bar->focus_cb = info->cb; bar->state = XBAR_STATE_HIDE; return 0; }