#include "private.h" #include "channel.h" #include "config.h" #include "theme.h" #include "window.h" #include "grid.h" struct _Channel { const char *name; const char *server; Evas *evas; Evas_Object *o_base; Evas_Object *o_bg; Evas_Object *o_grid; Evas_Object *o_spacer; Evas_Object *o_img; int step_x, step_y; int min_w, min_h; int req_w, req_h; Eina_Bool size_done : 1; Eina_Bool translucent : 1; Eina_Bool focused : 1; Eina_Bool unswallowed : 1; Eina_Bool missed : 1; }; 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->focused) _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->focused) { 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->focused) { 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_options_done(void *data) { Channel *chl; chl = data; if (chl->focused) elm_object_focus_set(chl->o_grid, 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); } /* external functions */ Channel * _channel_create(Evas *evas, 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; /* 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 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); 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); return chl; } void _channel_destroy(Channel *chl) { /* 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_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); /* update grid config */ _grid_update(chl->o_grid); } 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); elm_object_focus_set(chl->o_grid, EINA_TRUE); chl->focused = EINA_TRUE; chl->missed = EINA_FALSE; } void _channel_unfocus(Channel *chl) { if (!chl->focused) return; elm_object_focus_set(chl->o_grid, EINA_FALSE); 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; } 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); } 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) { /* fprintf(stderr, "Channel %s Append: %s", chl->name, txt); */ /* write buff to grid */ if (user) { /* FIXME: If the user has a short nickname, and another user has a * longer nickname, then things don't line up on the grid. We need to * deal with this somehow */ _grid_text_append(chl->o_grid, user, strlen(user)); _grid_text_append(chl->o_grid, "\t", strlen("\t")); } _grid_text_append(chl->o_grid, txt, strlen(txt)); if (!chl->focused) chl->missed = EINA_TRUE; else chl->missed = EINA_FALSE; _window_channel_count_update(); } 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); }