express/src/bin/channel.c

496 lines
12 KiB
C

#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);
}