#include "private.h" #include "channel.h" #include "config.h" #include "theme.h" #include "window.h" #include "grid.h" #include "utils.h" #include "commands.h" struct _Channel { const char *name; const char *server; Evas *evas; Evas_Object *o_win; Evas_Object *o_base; Evas_Object *o_bg; Evas_Object *o_grid; Evas_Object *o_spacer; Evas_Object *o_tab_spacer; Evas_Object *o_tabregion_bg; Evas_Object *o_tabregion_base; Evas_Object *o_img; Evas_Object *o_entry; struct { Evas_Object *o_frame; Evas_Object *o_spacer; Evas_Object *o_box; Evas_Object *o_label; Evas_Object *o_list; Evas_Object *o_dismiss; Eina_Bool visible : 1; Eina_List *users; int opcount; } userlist; struct { Evas_Object *o_frame; Evas_Object *o_box; Evas_Object *o_list; Elm_Object_Item *group; Elm_Genlist_Item_Class *itc, *gitc; } treeview; struct { struct { Evas_Object *o_box; Eina_List *tabs; } l, r; } tabbar; int step_x, step_y; int min_w, min_h; int req_w, req_h; Eina_Bool active : 1; Eina_Bool size_done : 1; Eina_Bool translucent : 1; Eina_Bool focused : 1; Eina_Bool unswallowed : 1; Eina_Bool missed : 1; Express_Network *net; }; static void _cb_theme_reload(Channel *chl) { Edje_Message_Int msg; chl->translucent = _ex_cfg->gui.translucent; if (chl->translucent) msg.val = _ex_cfg->gui.opacity; else msg.val = 100; edje_object_message_send(chl->o_bg, EDJE_MESSAGE_INT, 1, &msg); edje_object_message_send(chl->o_base, EDJE_MESSAGE_INT, 1, &msg); } static void _cb_size_hint(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event EINA_UNUSED) { Channel *chl; Evas_Coord mw, mh, rw, rh, w = 0, h = 0; chl = data; evas_object_size_hint_min_get(obj, &mw, &mh); evas_object_size_hint_request_get(obj, &rw, &rh); edje_object_size_min_calc(chl->o_base, &w, &h); evas_object_size_hint_min_set(chl->o_base, w, h); edje_object_size_min_calc(chl->o_bg, &w, &h); evas_object_size_hint_min_set(chl->o_bg, w, h); chl->step_x = mw; chl->step_y = mh; chl->min_w = (w - mw); chl->min_h = (h - mh); chl->req_w = (w - mw + rw); chl->req_h = (h - mh + rh); if (chl->active) _window_size_update(); } static void _cb_prev(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) { Channel *chl, *pchl = NULL; chl = data; if (chl->active) { if ((pchl = _window_channel_previous_get(chl))) _window_channel_switch(chl, pchl); } } static void _cb_next(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) { Channel *chl, *nchl = NULL; chl = data; if (chl->active) { if ((nchl = _window_channel_next_get(chl))) _window_channel_switch(chl, nchl); } } static void _cb_count_go(void *data, Evas_Object *obj EINA_UNUSED, const char *sig EINA_UNUSED, const char *source EINA_UNUSED) { Channel *chl; chl = data; _window_channel_switch(chl, chl); } static void _cb_count_prev(void *data, Evas_Object *obj EINA_UNUSED, const char *sig EINA_UNUSED, const char *source EINA_UNUSED) { _cb_prev(data, NULL, NULL); } static void _cb_count_next(void *data, Evas_Object *obj EINA_UNUSED, const char *sig EINA_UNUSED, const char *source EINA_UNUSED) { _cb_next(data, NULL, NULL); } static void _cb_userlist_go(void *data, Evas_Object *obj EINA_UNUSED, const char *sig EINA_UNUSED, const char *source EINA_UNUSED) { Channel *chl; chl = data; if (!chl->userlist.visible) { edje_object_signal_emit(chl->o_base, "userlist,show", PACKAGE_NAME); chl->userlist.visible = EINA_TRUE; } else { edje_object_signal_emit(chl->o_base, "userlist,hide", PACKAGE_NAME); chl->userlist.visible = EINA_FALSE; } } static int _cb_userlist_compare(const void *data1, const void *data2) { const char *label1, *label2; const Elm_Object_Item *item1, *item2; char *item_data1, *item_data2; item1 = data1; item2 = data2; label1 = elm_object_item_text_get(item1); label2 = elm_object_item_text_get(item2); item_data1 = elm_object_item_data_get(item1); item_data2 = elm_object_item_data_get(item2); if ((item_data1) && (item_data2)) return strcasecmp(label1, label2); else if ((item_data1) && (!item_data2)) return -1; else if ((!item_data1) && (item_data2)) return 1; return strcasecmp(label1, label2); } static void _cb_userlist_dismiss_mouse_down(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) { _cb_userlist_go(data, NULL, NULL, NULL); } static void _cb_userlist_done(void *data, Evas_Object *obj EINA_UNUSED, const char *sig EINA_UNUSED, const char *source EINA_UNUSED) { Channel *chl; chl = data; chl->userlist.o_dismiss = NULL; } static void _cb_options_done(void *data) { Channel *chl; chl = data; if (chl->active) elm_object_focus_set(chl->o_entry, EINA_TRUE); } static void _cb_options(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) { Channel *chl; chl = data; _window_options_toggle(chl->o_grid, _cb_options_done, chl); } static void _cb_entry_go(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) { Channel *chl; char *txt; chl = data; if (!chl->net) return; if ((txt = (char *)elm_entry_entry_get(chl->o_entry))) { if (strlen(txt) < 1) return; if ((txt = elm_entry_markup_to_utf8(txt))) { char buff[PATH_MAX]; if (_cmd_txt_handle(chl->net, chl->name, txt, buff)) { const char *nick; nick = express_network_nickname_get(chl->net); _channel_text_append(chl, nick, buff, _row_color_simple_create(0)); } elm_entry_entry_set(chl->o_entry, ""); } } } static void _cb_entry_key_down(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event) { Evas_Event_Key_Down *ev; ev = event; if (!strcmp(ev->key, "Tab")) { Channel *chl; const char *usr, *str; Eina_List *l, *m = NULL; chl = data; str = elm_entry_entry_get(chl->o_entry); if ((!str) || (strlen(str) < 1)) return; EINA_LIST_FOREACH(chl->userlist.users, l, usr) { if (_util_str_has_prefix(usr, str)) m = eina_list_append(m, usr); } if (eina_list_count(m) > 1) { Eina_Strbuf *sb; char *s; sb = eina_strbuf_new(); EINA_LIST_FOREACH(m, l, usr) { eina_strbuf_append_length(sb, usr, strlen(usr)); eina_strbuf_append_char(sb, ' '); } if (eina_strbuf_length_get(sb) < 1) { eina_strbuf_free(sb); return; } eina_strbuf_append_char(sb, '\r'); eina_strbuf_append_char(sb, '\n'); s = eina_strbuf_string_steal(sb); eina_strbuf_free(sb); _channel_text_append(chl, "*", s, _row_color_simple_create(0)); } else { elm_entry_entry_set(chl->o_entry, eina_list_data_get(m)); elm_entry_entry_append(chl->o_entry, ": "); elm_entry_cursor_end_set(chl->o_entry); } } } static void _cb_tabregion_change(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event EINA_UNUSED) { Channel *chl; Evas_Coord w = 0, h = 0; chl = data; evas_object_geometry_get(obj, NULL, NULL, &w, &h); evas_object_size_hint_min_set(chl->o_tabregion_base, w, h); edje_object_part_swallow(chl->o_bg, "channel.tabregion", chl->o_tabregion_bg); edje_object_part_swallow(chl->o_base, "channel.tabregion", chl->o_tabregion_base); } static void _channel_userlist_create(Channel *chl) { if (!chl->userlist.o_frame) { Evas_Object *o; o = elm_frame_add(chl->o_win); WEIGHT_SET(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); ALIGN_SET(o, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_object_text_set(o, "Users"); elm_object_focus_allow_set(o, EINA_FALSE); chl->userlist.o_frame = o; edje_object_part_swallow(chl->o_base, "userlist.content", o); } if (!chl->userlist.o_box) { Evas_Object *o; o = elm_box_add(chl->o_win); WEIGHT_SET(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); ALIGN_SET(o, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_box_align_set(o, 0.5, 0.0); elm_box_padding_set(o, 2, 2); evas_object_show(o); chl->userlist.o_box = o; elm_object_content_set(chl->userlist.o_frame, o); } if (!chl->userlist.o_label) { Evas_Object *o; o = elm_label_add(chl->o_win); elm_label_line_wrap_set(o, ELM_WRAP_NONE); evas_object_show(o); chl->userlist.o_label = o; elm_box_pack_end(chl->userlist.o_box, o); } if (!chl->userlist.o_list) { Evas_Object *o; o = elm_list_add(chl->o_win); WEIGHT_SET(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); ALIGN_SET(o, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_object_focus_allow_set(o, EINA_FALSE); elm_scroller_content_min_limit(o, EINA_TRUE, EINA_FALSE); elm_scroller_bounce_set(o, EINA_FALSE, EINA_TRUE); elm_scroller_policy_set(o, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO); evas_object_show(o); chl->userlist.o_list = o; elm_box_pack_end(chl->userlist.o_box, o); } if (!chl->userlist.o_spacer) { Evas_Object *o; Evas_Coord w = 0, h = 0; o = elm_icon_add(chl->o_win); elm_icon_standard_set(o, "user-idle"); elm_coords_finger_size_adjust(1, &w, 1, &h); evas_object_size_hint_min_set(o, w, h); elm_object_focus_allow_set(o, EINA_FALSE); chl->userlist.o_spacer = o; edje_object_part_swallow(chl->o_bg, "userlist.control", o); } if (!chl->userlist.o_dismiss) { chl->userlist.o_dismiss = evas_object_rectangle_add(chl->evas); evas_object_color_set(chl->userlist.o_dismiss, 0, 0, 0, 0); evas_object_event_callback_add(chl->userlist.o_dismiss, EVAS_CALLBACK_MOUSE_DOWN, _cb_userlist_dismiss_mouse_down, chl); edje_object_signal_callback_add(chl->o_base, "userlist,hide,done", PACKAGE_NAME, _cb_userlist_done, chl); edje_object_part_swallow(chl->o_base, "userlist.dismiss", chl->userlist.o_dismiss); } } static char * _channel_treeview_group_name_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part EINA_UNUSED) { /* char buff[256]; */ const char *group; if (!(group = data)) return NULL; return strdup(group); /* snprintf(buff, sizeof(buff), "%s", express_network_name_get(net)); */ /* return strdup(buff); */ } static char * _channel_treeview_item_name_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part EINA_UNUSED) { Channel *chl; if (!(chl = data)) return NULL; return strdup(chl->name); } static void _channel_treeview_create(Channel *chl) { if (!chl->treeview.o_frame) { Evas_Object *o; o = elm_frame_add(chl->o_win); WEIGHT_SET(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); FILL_SET(o, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_object_text_set(o, "Channels"); elm_object_focus_allow_set(o, EINA_FALSE); evas_object_show(o); chl->treeview.o_frame = o; edje_object_part_swallow(chl->o_base, "treeview.content", o); } if (!chl->treeview.o_box) { Evas_Object *o; o = elm_box_add(chl->o_win); WEIGHT_SET(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); FILL_SET(o, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_box_align_set(o, 0.5, 0.0); elm_box_padding_set(o, 2, 2); evas_object_show(o); chl->treeview.o_box = o; elm_object_content_set(chl->treeview.o_frame, o); } if (!chl->treeview.o_list) { Evas_Object *o; chl->treeview.gitc = elm_genlist_item_class_new(); chl->treeview.gitc->item_style = "group_index"; chl->treeview.gitc->func.text_get = _channel_treeview_group_name_get; chl->treeview.itc = elm_genlist_item_class_new(); chl->treeview.itc->item_style = "default"; chl->treeview.itc->func.text_get = _channel_treeview_item_name_get; o = elm_genlist_add(chl->o_win); WEIGHT_SET(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); FILL_SET(o, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_genlist_focus_on_selection_set(o, EINA_FALSE); elm_scroller_content_min_limit(o, EINA_TRUE, EINA_FALSE); elm_scroller_bounce_set(o, EINA_FALSE, EINA_TRUE); elm_scroller_policy_set(o, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO); evas_object_show(o); chl->treeview.o_list = o; elm_box_pack_end(chl->treeview.o_box, o); } edje_object_signal_emit(chl->o_base, "treeview,on", PACKAGE_NAME); } static void _channel_treeview_destroy(Channel *chl) { edje_object_signal_emit(chl->o_base, "treeview,off", PACKAGE_NAME); if (chl->treeview.gitc) elm_genlist_item_class_free(chl->treeview.gitc); chl->treeview.gitc = NULL; if (chl->treeview.itc) elm_genlist_item_class_free(chl->treeview.itc); chl->treeview.itc = NULL; if (chl->treeview.o_list) evas_object_del(chl->treeview.o_list); chl->treeview.o_list = NULL; if (chl->treeview.o_box) evas_object_del(chl->treeview.o_box); chl->treeview.o_box = NULL; if (chl->treeview.o_frame) evas_object_del(chl->treeview.o_frame); chl->treeview.o_frame = NULL; } static void _cb_treeview_selected(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event) { Elm_Object_Item *item; Channel *chl, *pchl; if (!(item = event)) return; if (!(chl = elm_object_item_data_get(item))) return; if ((pchl = _window_channel_active_get())) { if (pchl != chl) _window_channel_unswallow(pchl); } _window_channel_activate(chl); _window_channel_swallow(chl); /* elm_genlist_item_selected_set(item, EINA_TRUE); */ } static void _channel_tabbar_create(Channel *chl) { if (!chl->o_tabregion_bg) { chl->o_tabregion_bg = evas_object_rectangle_add(chl->evas); evas_object_color_set(chl->o_tabregion_bg, 0, 0, 0, 0); evas_object_event_callback_add(chl->o_tabregion_bg, EVAS_CALLBACK_MOVE, _cb_tabregion_change, chl); evas_object_event_callback_add(chl->o_tabregion_bg, EVAS_CALLBACK_RESIZE, _cb_tabregion_change, chl); edje_object_part_swallow(chl->o_bg, "channel.tabregion", chl->o_tabregion_bg); } if (!chl->o_tabregion_base) { chl->o_tabregion_base = evas_object_rectangle_add(chl->evas); evas_object_color_set(chl->o_tabregion_base, 0, 0, 0, 0); edje_object_part_swallow(chl->o_base, "channel.tabregion", chl->o_tabregion_base); } _window_tabcount_update(); } static void _channel_tabbar_destroy(Channel *chl EINA_UNUSED) { /* NB: This function will already destroy tabbar */ _window_tabcount_update(); } /* external functions */ Channel * _channel_create(Evas *evas, Evas_Object *win, const char *name, const char *server) { Channel *chl; /* try to allocate space for channel structure */ if (!(chl = calloc(1, sizeof(Channel)))) return NULL; /* set channel to the opposite of config translucent * NB: This is done so that first time through the signals get sent */ chl->translucent = !_ex_cfg->gui.translucent; chl->evas = evas; chl->o_win = win; /* store channel name */ if (name) chl->name = eina_stringshare_add(name); /* store channel server */ if (server) chl->server = eina_stringshare_add(server); /* add base object */ chl->o_base = edje_object_add(evas); _theme_apply(chl->o_base, "express/channel"); _theme_reload_enable(chl->o_base); evas_object_data_set(chl->o_base, "theme_reload_func", _cb_theme_reload); evas_object_data_set(chl->o_base, "theme_reload_func_data", chl); /* add bg object */ chl->o_bg = edje_object_add(evas); WEIGHT_SET(chl->o_bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); FILL_SET(chl->o_bg, EVAS_HINT_FILL, EVAS_HINT_FILL); _theme_apply(chl->o_bg, "express/background"); _theme_reload_enable(chl->o_bg); evas_object_data_set(chl->o_bg, "theme_reload_func", _cb_theme_reload); evas_object_data_set(chl->o_bg, "theme_reload_func_data", chl); /* add tabregion */ if (_ex_cfg->gui.tabs) _channel_tabbar_create(chl); else _channel_treeview_create(chl); /* add grid */ chl->o_grid = _grid_add(evas); WEIGHT_SET(chl->o_grid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); FILL_SET(chl->o_grid, EVAS_HINT_FILL, EVAS_HINT_FILL); /* add userlist */ _channel_userlist_create(chl); evas_object_event_callback_add(chl->o_grid, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _cb_size_hint, chl); evas_object_smart_callback_add(chl->o_grid, "options", _cb_options, chl); evas_object_smart_callback_add(chl->o_grid, "prev", _cb_prev, chl); evas_object_smart_callback_add(chl->o_grid, "next", _cb_next, chl); /* swallow parts */ edje_object_part_swallow(chl->o_base, "channel.content", chl->o_grid); edje_object_part_swallow(chl->o_bg, "background.content", chl->o_base); /* add handlers for chlcount signals */ edje_object_signal_callback_add(chl->o_bg, "chlcount,go", PACKAGE_NAME, _cb_count_go, chl); edje_object_signal_callback_add(chl->o_bg, "chlcount,prev", PACKAGE_NAME, _cb_count_prev, chl); edje_object_signal_callback_add(chl->o_bg, "chlcount,next", PACKAGE_NAME, _cb_count_next, chl); /* add handlers for userlist signals */ edje_object_signal_callback_add(chl->o_bg, "userlist,go", PACKAGE_NAME, _cb_userlist_go, chl); return chl; } void _channel_destroy(Channel *chl) { const char *usr; /* delete tabregion stuff */ _channel_tabbar_destroy(chl); _channel_treeview_destroy(chl); /* delete channel userlist objects */ EINA_LIST_FREE(chl->userlist.users, usr) eina_stringshare_del(usr); if (chl->userlist.o_dismiss) evas_object_del(chl->userlist.o_dismiss); if (chl->userlist.o_list) evas_object_del(chl->userlist.o_list); if (chl->userlist.o_label) evas_object_del(chl->userlist.o_label); if (chl->userlist.o_box) evas_object_del(chl->userlist.o_box); if (chl->userlist.o_spacer) evas_object_del(chl->userlist.o_spacer); if (chl->userlist.o_frame) evas_object_del(chl->userlist.o_frame); /* delete channel objects */ if (chl->o_img) evas_object_del(chl->o_img); if (chl->o_spacer) evas_object_del(chl->o_spacer); if (chl->o_entry) evas_object_del(chl->o_entry); if (chl->o_grid) evas_object_del(chl->o_grid); if (chl->o_bg) evas_object_del(chl->o_bg); if (chl->o_base) evas_object_del(chl->o_base); /* delete channel name */ if (chl->name) eina_stringshare_del(chl->name); /* delete channel server name */ if (chl->server) eina_stringshare_del(chl->server); /* free allocated channel structure */ free(chl); } void _channel_update(Channel *chl) { chl->size_done = EINA_FALSE; /* update channel transparency */ _cb_theme_reload(chl); if (_ex_cfg->gui.tabs) { _channel_treeview_destroy(chl); _window_tabcount_update(); } else { _channel_tabbar_destroy(chl); _channel_treeview_create(chl); _window_treeview_update(); } /* update grid config */ _grid_update(chl->o_grid); edje_object_part_swallow(chl->o_base, "channel.content", chl->o_grid); edje_object_part_swallow(chl->o_bg, "background.content", chl->o_base); } void _channel_focused_set(Channel *chl, Eina_Bool focus) { chl->focused = focus; } Eina_Bool _channel_focused_get(Channel *chl) { return chl->focused; } void _channel_focus(Channel *chl) { if (chl->focused) return; edje_object_signal_emit(chl->o_bg, "focus,in", PACKAGE_NAME); edje_object_signal_emit(chl->o_base, "focus,in", PACKAGE_NAME); chl->focused = EINA_TRUE; } void _channel_unfocus(Channel *chl) { if (!chl->focused) return; edje_object_signal_emit(chl->o_bg, "focus,out", PACKAGE_NAME); edje_object_signal_emit(chl->o_base, "focus,out", PACKAGE_NAME); chl->focused = EINA_FALSE; } void _channel_active_set(Channel *chl, Eina_Bool active) { chl->active = active; elm_object_focus_allow_set(chl->o_entry, active); elm_object_focus_set(chl->o_entry, active); } Eina_Bool _channel_active_get(Channel *chl) { return chl->active; } const char * _channel_name_get(Channel *chl) { return chl->name; } const char * _channel_server_name_get(Channel *chl) { return chl->server; } void _channel_size_update(Channel *chl) { _cb_size_hint(chl, NULL, chl->o_grid, NULL); } void _channel_size_min_get(Channel *chl, int *w, int *h) { evas_object_size_hint_min_get(chl->o_bg, w, h); } void _channel_size_step_get(Channel *chl, int *w, int *h) { if (w) *w = chl->step_x; if (h) *h = chl->step_y; } void _channel_size_request_get(Channel *chl, int *w, int *h) { if (w) *w = chl->req_w; if (h) *h = chl->req_h; } void _channel_size_done_set(Channel *chl, Eina_Bool done) { chl->size_done = done; } Eina_Bool _channel_size_done_get(Channel *chl) { return chl->size_done; } Evas_Object * _channel_background_get(Channel *chl) { return chl->o_bg; } void _channel_background_hide(Channel *chl) { evas_object_hide(chl->o_bg); } void _channel_background_show(Channel *chl) { evas_object_show(chl->o_bg); } Evas_Object * _channel_base_get(Channel *chl) { return chl->o_base; } void _channel_base_unswallow(Channel *chl) { edje_object_part_unswallow(chl->o_bg, chl->o_base); evas_object_lower(chl->o_base); evas_object_move(chl->o_base, -9999, -9999); evas_object_show(chl->o_base); evas_object_clip_unset(chl->o_base); #if (EVAS_VERSION_MAJOR > 1) || (EVAS_VERSION_MINOR >= 8) evas_object_image_source_visible_set(chl->o_img, EINA_FALSE); #endif chl->unswallowed = EINA_TRUE; } Evas_Object * _channel_image_get(Channel *chl) { return chl->o_img; } void _channel_image_unset(Channel *chl) { #if (EVAS_VERSION_MAJOR > 1) || (EVAS_VERSION_MINOR >= 8) evas_object_image_source_visible_set(chl->o_img, EINA_TRUE); #endif chl->o_img = NULL; } void _channel_image_create(Channel *chl) { Evas_Coord w = 0, h = 0; chl->o_img = evas_object_image_filled_add(chl->evas); evas_object_image_source_set(chl->o_img, chl->o_base); evas_object_geometry_get(chl->o_base, NULL, NULL, &w, &h); evas_object_resize(chl->o_img, w, h); evas_object_data_set(chl->o_img, "grid", chl->o_grid); } Eina_Bool _channel_missed_get(Channel *chl) { return chl->missed; } void _channel_missed_set(Channel *chl, Eina_Bool missed) { chl->missed = missed; } void _channel_missed_count_set(Channel *chl, int count) { if (count > 0) { char buff[32]; snprintf(buff, sizeof(buff), "%i", count); edje_object_part_text_set(chl->o_bg, "chlmissed.label", buff); } else edje_object_part_text_set(chl->o_bg, "chlmissed.label", NULL); if (count > 0) edje_object_signal_emit(chl->o_bg, "chlmissed,on", PACKAGE_NAME); else edje_object_signal_emit(chl->o_bg, "chlmissed,off", PACKAGE_NAME); } void _channel_count_set(Channel *chl, int count, int total) { if (total > 1) { char buff[32]; snprintf(buff, sizeof(buff), "%i/%i", count, total); edje_object_part_text_set(chl->o_bg, "chlcount.label", buff); edje_object_signal_emit(chl->o_bg, "chlcount,on", PACKAGE_NAME); } else edje_object_signal_emit(chl->o_bg, "chlcount,off", PACKAGE_NAME); } void _channel_userlist_show(Channel *chl) { edje_object_signal_emit(chl->o_bg, "userlist,on", PACKAGE_NAME); } void _channel_userlist_hide(Channel *chl) { edje_object_signal_emit(chl->o_bg, "userlist,off", PACKAGE_NAME); } Eina_Bool _channel_unswallowed_get(Channel *chl) { return chl->unswallowed; } void _channel_unswallowed_set(Channel *chl, Eina_Bool swallowed) { chl->unswallowed = swallowed; if (!swallowed) { edje_object_part_swallow(chl->o_base, "channel.content", chl->o_grid); edje_object_part_swallow(chl->o_bg, "background.content", chl->o_base); } } void _channel_spacer_create(Channel *chl) { if (!chl->o_spacer) { Evas_Coord w = 0, h = 0; chl->o_spacer = evas_object_rectangle_add(chl->evas); evas_object_color_set(chl->o_spacer, 0, 0, 0, 0); elm_coords_finger_size_adjust(1, &w, 1, &h); evas_object_size_hint_min_set(chl->o_spacer, w, h); edje_object_part_swallow(chl->o_bg, "chlcount.control", chl->o_spacer); } } void _channel_text_append(Channel *chl, const char *user, const char *txt, Row_Color *color) { /* fprintf(stderr, "Channel %s Append: %s", chl->name, txt); */ /* write buff to grid */ if (user) { /* If user is * ie for messages use a different color */ Row_Color *ucolor; if (!strncmp(user, "*", strlen(user))) ucolor = _row_color_simple_create(78); else ucolor = _row_color_simple_create(31); _grid_text_append(chl->o_grid, user, strlen(user), ucolor); _grid_text_append(chl->o_grid, "\t", strlen("\t"), ucolor); if (ucolor) free(ucolor); } _grid_text_append(chl->o_grid, txt, strlen(txt), color); if (color) free(color); if (!chl->active) chl->missed = EINA_TRUE; else chl->missed = EINA_FALSE; _window_channel_count_update(); if (chl->missed) _window_tabbar_update(chl); } void _channel_window_set(Channel *chl, Evas_Object *win) { _grid_window_set(chl->o_grid, win); _grid_theme_set(chl->o_grid, chl->o_bg); if (chl->o_entry) return; chl->o_entry = elm_entry_add(win); WEIGHT_SET(chl->o_entry, EVAS_HINT_EXPAND, 0.0); ALIGN_SET(chl->o_entry, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_entry_single_line_set(chl->o_entry, EINA_TRUE); elm_entry_scrollable_set(chl->o_entry, EINA_TRUE); elm_entry_line_wrap_set(chl->o_entry, ELM_WRAP_NONE); elm_scroller_policy_set(chl->o_entry, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF); elm_entry_input_panel_layout_set(chl->o_entry, ELM_INPUT_PANEL_LAYOUT_TERMINAL); elm_entry_autocapital_type_set(chl->o_entry, ELM_AUTOCAPITAL_TYPE_NONE); elm_entry_input_panel_enabled_set(chl->o_entry, EINA_TRUE); elm_entry_input_panel_language_set(chl->o_entry, ELM_INPUT_PANEL_LANG_ALPHABET); elm_entry_input_panel_return_key_type_set(chl->o_entry, ELM_INPUT_PANEL_RETURN_KEY_TYPE_GO); elm_entry_prediction_allow_set(chl->o_entry, EINA_TRUE); elm_entry_cnp_mode_set(chl->o_entry, ELM_CNP_MODE_PLAINTEXT); evas_object_smart_callback_add(chl->o_entry, "activated", _cb_entry_go, chl); /* NB: This is messed up. Elm_Entry in single-line mode does not * generate a changed event when pressing the Tab key */ evas_object_event_callback_add(chl->o_entry, EVAS_CALLBACK_KEY_DOWN, _cb_entry_key_down, chl); edje_object_part_swallow(chl->o_base, "channel.entry", chl->o_entry); elm_entry_entry_set(chl->o_entry, ""); elm_object_focus_allow_set(chl->o_entry, EINA_FALSE); } void _channel_network_set(Channel *chl, Express_Network *net) { chl->net = net; _grid_nicklen_set(chl->o_grid, express_network_nickname_length_get(net)); } Express_Network * _channel_network_get(Channel *chl) { return chl->net; } void _channel_userlist_user_append(Channel *chl, const char *user, Eina_Bool op) { char users[PATH_MAX]; if ((!user) || (strlen(user) < 1)) return; /* append to list of users for autocomplete */ chl->userlist.users = eina_list_append(chl->userlist.users, eina_stringshare_add(user)); if (!op) elm_list_item_sorted_insert(chl->userlist.o_list, user, NULL, NULL, NULL, NULL, _cb_userlist_compare); else { Evas_Object *icon; char buff[PATH_MAX]; static char data[] = "1"; icon = elm_icon_add(chl->o_bg); elm_image_resizable_set(icon, EINA_TRUE, EINA_TRUE); WEIGHT_SET(icon, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); ALIGN_SET(icon, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_object_focus_allow_set(icon, EINA_FALSE); snprintf(buff, sizeof(buff), "%s/images/operator.png", elm_app_data_dir_get()); elm_image_file_set(icon, buff, NULL); evas_object_show(icon); elm_list_item_sorted_insert(chl->userlist.o_list, user, icon, NULL, NULL, &data, _cb_userlist_compare); chl->userlist.opcount++; } snprintf(users, sizeof(users), "(%d ops, %d total)", chl->userlist.opcount, eina_list_count(chl->userlist.users)); elm_object_text_set(chl->userlist.o_label, users); } void _channel_userlist_go(Channel *chl) { elm_list_go(chl->userlist.o_list); } void _channel_tabbar_lbox_create(Channel *chl, Evas_Object *win) { if (!chl->tabbar.l.o_box) { chl->tabbar.l.o_box = elm_box_add(win); elm_box_horizontal_set(chl->tabbar.l.o_box, EINA_TRUE); elm_box_homogeneous_set(chl->tabbar.l.o_box, EINA_TRUE); WEIGHT_SET(chl->tabbar.l.o_box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); FILL_SET(chl->tabbar.l.o_box, EVAS_HINT_FILL, EVAS_HINT_FILL); edje_object_part_swallow(chl->o_bg, "tabl.content", chl->tabbar.l.o_box); elm_object_focus_allow_set(chl->tabbar.l.o_box, EINA_FALSE); evas_object_show(chl->tabbar.l.o_box); } } void _channel_tabbar_rbox_create(Channel *chl, Evas_Object *win) { if (!chl->tabbar.r.o_box) { chl->tabbar.r.o_box = elm_box_add(win); elm_box_horizontal_set(chl->tabbar.r.o_box, EINA_TRUE); elm_box_homogeneous_set(chl->tabbar.r.o_box, EINA_TRUE); WEIGHT_SET(chl->tabbar.r.o_box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); FILL_SET(chl->tabbar.r.o_box, EVAS_HINT_FILL, EVAS_HINT_FILL); edje_object_part_swallow(chl->o_bg, "tabr.content", chl->tabbar.r.o_box); elm_object_focus_allow_set(chl->tabbar.r.o_box, EINA_FALSE); evas_object_show(chl->tabbar.r.o_box); } } void _channel_tabbar_lbox_append(Channel *chl, Evas_Object *o) { chl->tabbar.l.tabs = eina_list_append(chl->tabbar.l.tabs, o); elm_box_pack_end(chl->tabbar.l.o_box, o); } void _channel_tabbar_rbox_append(Channel *chl, Evas_Object *o) { chl->tabbar.r.tabs = eina_list_append(chl->tabbar.r.tabs, o); elm_box_pack_end(chl->tabbar.r.o_box, o); } void _channel_tabbar_clear(Channel *chl) { Evas_Object *o; if (chl->tabbar.l.o_box) { EINA_LIST_FREE(chl->tabbar.l.tabs, o) evas_object_del(o); evas_object_del(chl->tabbar.l.o_box); chl->tabbar.l.o_box = NULL; } if (chl->tabbar.r.o_box) { EINA_LIST_FREE(chl->tabbar.r.tabs, o) evas_object_del(o); evas_object_del(chl->tabbar.r.o_box); chl->tabbar.r.o_box = NULL; } } void _channel_tabbar_update(Channel *chl) { Eina_List *l; Evas_Object *o; Channel *pchl; EINA_LIST_FOREACH(chl->tabbar.l.tabs, l, o) { pchl = evas_object_data_get(o, "channel"); if ((pchl) && (pchl != chl)) { if (pchl->missed) edje_object_signal_emit(o, "tabmissed,on", PACKAGE_NAME); else edje_object_signal_emit(o, "tabmissed,off", PACKAGE_NAME); } } EINA_LIST_FOREACH(chl->tabbar.r.tabs, l, o) { pchl = evas_object_data_get(o, "channel"); if ((pchl) && (pchl != chl)) { if (pchl->missed) edje_object_signal_emit(o, "tabmissed,on", PACKAGE_NAME); else edje_object_signal_emit(o, "tabmissed,off", PACKAGE_NAME); } } } void _channel_tabspacer_create(Channel *chl, double v1, double v2) { if (!chl->o_tab_spacer) { Evas_Coord w = 0, h = 0; chl->o_tab_spacer = evas_object_rectangle_add(chl->evas); evas_object_color_set(chl->o_tab_spacer, 0, 0, 0, 0); elm_coords_finger_size_adjust(1, &w, 1, &h); evas_object_size_hint_min_set(chl->o_tab_spacer, w, h); edje_object_part_swallow(chl->o_bg, "tab", chl->o_tab_spacer); edje_object_part_drag_value_set(chl->o_bg, "tabl", v1, 0.0); edje_object_part_drag_value_set(chl->o_bg, "tabr", v2, 0.0); edje_object_part_text_set(chl->o_bg, "tab.title", chl->name); edje_object_signal_emit(chl->o_bg, "tabbar,on", PACKAGE_NAME); edje_object_signal_emit(chl->o_base, "tabbar,on", PACKAGE_NAME); edje_object_message_signal_process(chl->o_bg); } else { edje_object_part_drag_value_set(chl->o_bg, "tabl", v1, 0.0); edje_object_part_drag_value_set(chl->o_bg, "tabr", v2, 0.0); edje_object_message_signal_process(chl->o_bg); } } void _channel_tabspacer_destroy(Channel *chl) { if (chl->o_tab_spacer) { edje_object_signal_emit(chl->o_bg, "tabbar,off", PACKAGE_NAME); edje_object_signal_emit(chl->o_base, "tabbar,off", PACKAGE_NAME); evas_object_del(chl->o_tab_spacer); chl->o_tab_spacer = NULL; edje_object_message_signal_process(chl->o_bg); } } Eina_Bool _channel_user_find(Channel *chl, const char *user) { if ((!chl) || (!user)) return EINA_FALSE; if (eina_list_data_find(chl->userlist.users, user) == user) return EINA_TRUE; return EINA_FALSE; } void _channel_treeview_clear(Channel *chl) { elm_genlist_clear(chl->treeview.o_list); } void _channel_treeview_group_add(Channel *chl, const char *group) { Elm_Object_Item *it; it = elm_genlist_item_append(chl->treeview.o_list, chl->treeview.gitc, group, NULL, ELM_GENLIST_ITEM_GROUP, NULL, NULL); elm_genlist_item_expanded_set(it, EINA_FALSE); elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY); if (chl->net) { const char *netname; if ((netname = express_network_name_get(chl->net))) { if (!strcmp(netname, group)) chl->treeview.group = it; } } } void _channel_treeview_group_item_add(Channel *pchl, Channel *chl) { Elm_Object_Item *it; it = elm_genlist_item_append(pchl->treeview.o_list, pchl->treeview.itc, chl, pchl->treeview.group, ELM_GENLIST_ITEM_NONE, _cb_treeview_selected, NULL); if (chl->active) elm_genlist_item_selected_set(it, EINA_TRUE); } void _channel_treeview_item_add(Channel *pchl, Channel *chl) { Elm_Object_Item *it; it = elm_genlist_item_append(pchl->treeview.o_list, pchl->treeview.itc, chl, NULL, ELM_GENLIST_ITEM_NONE, _cb_treeview_selected, NULL); if (chl->active) elm_genlist_item_selected_set(it, EINA_TRUE); }