From 260519c1c68311ad4bc4897757b78744b8873a27 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Sat, 11 Apr 2015 21:11:21 -0400 Subject: [PATCH] express: Add initial support for treeview NB: Not entirely complete yet, but sort of functional ;) Signed-off-by: Chris Michael --- src/bin/channel.c | 177 ++++++++++++++++++++++++++++++++++++++++++++++ src/bin/channel.h | 6 ++ src/bin/window.c | 78 ++++++++++++++++---- 3 files changed, 249 insertions(+), 12 deletions(-) diff --git a/src/bin/channel.c b/src/bin/channel.c index 3914592..ca921da 100644 --- a/src/bin/channel.c +++ b/src/bin/channel.c @@ -36,6 +36,15 @@ struct _Channel 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 @@ -416,6 +425,110 @@ _channel_userlist_create(Channel *chl) } } +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); + ALIGN_SET(o, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_object_text_set(o, "Channels"); + elm_object_focus_allow_set(o, EINA_FALSE); + + 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); + 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->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";//"tree_effect"; + 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); + ALIGN_SET(o, EVAS_HINT_FILL, EVAS_HINT_FILL); + /* elm_genlist_tree_effect_enabled_set(o, EINA_TRUE); */ + 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->treeview.o_list = o; + elm_box_pack_end(chl->treeview.o_box, o); + } +} + +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; + + DBG("Channel Selected: %s", chl->name); + + 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); */ +} + /* external functions */ Channel * _channel_create(Evas *evas, Evas_Object *win, const char *name, const char *server) @@ -477,6 +590,8 @@ _channel_create(Evas *evas, Evas_Object *win, const char *name, const char *serv /* add userlist */ _channel_userlist_create(chl); + _channel_treeview_create(chl); + evas_object_event_callback_add(chl->o_grid, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _cb_size_hint, chl); @@ -519,6 +634,12 @@ _channel_destroy(Channel *chl) EINA_LIST_FREE(chl->userlist.users, usr) eina_stringshare_del(usr); + if (chl->treeview.gitc) elm_genlist_item_class_free(chl->treeview.gitc); + if (chl->treeview.itc) elm_genlist_item_class_free(chl->treeview.itc); + if (chl->treeview.o_list) evas_object_del(chl->treeview.o_list); + if (chl->treeview.o_box) evas_object_del(chl->treeview.o_box); + if (chl->treeview.o_frame) evas_object_del(chl->treeview.o_frame); + 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); @@ -554,6 +675,11 @@ _channel_update(Channel *chl) /* update grid config */ _grid_update(chl->o_grid); + + if (!_ex_cfg->gui.tabs) + edje_object_signal_emit(chl->o_base, "treeview,on", PACKAGE_NAME); + else + edje_object_signal_emit(chl->o_base, "treeview,off", PACKAGE_NAME); } void @@ -879,6 +1005,12 @@ _channel_network_set(Channel *chl, Express_Network *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) { @@ -1075,3 +1207,48 @@ _channel_user_find(Channel *chl, const char *user) 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_genlist_item_append(pchl->treeview.o_list, pchl->treeview.itc, + chl, pchl->treeview.group, ELM_GENLIST_ITEM_NONE, + _cb_treeview_selected, NULL); +} + +void +_channel_treeview_item_add(Channel *pchl, Channel *chl) +{ + elm_genlist_item_append(pchl->treeview.o_list, pchl->treeview.itc, + chl, NULL, ELM_GENLIST_ITEM_NONE, + _cb_treeview_selected, NULL); +} diff --git a/src/bin/channel.h b/src/bin/channel.h index 11fc647..4dec169 100644 --- a/src/bin/channel.h +++ b/src/bin/channel.h @@ -47,6 +47,7 @@ void _channel_text_append(Channel *chl, const char *user, const char *txt); void _channel_window_set(Channel *chl, Evas_Object *win); void _channel_network_set(Channel *chl, Express_Network *net); +Express_Network *_channel_network_get(Channel *chl); void _channel_userlist_show(Channel *chl); void _channel_userlist_hide(Channel *chl); @@ -62,6 +63,11 @@ void _channel_tabbar_update(Channel *chl); void _channel_tabspacer_create(Channel *chl, double v1, double v2); void _channel_tabspacer_destroy(Channel *chl); +void _channel_treeview_clear(Channel *chl); +void _channel_treeview_group_add(Channel *chl, const char *group); +void _channel_treeview_group_item_add(Channel *pchl, Channel *chl); +void _channel_treeview_item_add(Channel *pchl, Channel *chl); + Eina_Bool _channel_user_find(Channel *chl, const char *user); #endif diff --git a/src/bin/window.c b/src/bin/window.c index 3843b3c..d0b59cc 100644 --- a/src/bin/window.c +++ b/src/bin/window.c @@ -294,7 +294,6 @@ _cb_tab_activate(void *data, Evas_Object *obj EINA_UNUSED, const char *sig EINA_ } _window_channel_activate(chl); - _window_channel_swallow(chl); _window_tabcount_update(); @@ -333,6 +332,68 @@ _window_new(void) return win; } +static int +_cb_groups_sort(const void *d1, const void *d2) +{ + return strcasecmp(d1, d2); +} + +static void +_window_treeview_update(void) +{ + Eina_List *l, *groups = NULL; + Eina_List *ll, *channels = NULL; + Channel *chl; + const char *name; + /* char *group; */ + + channels = eina_list_clone(_win->channels); + + EINA_LIST_FOREACH(_win->channels, l, chl) + { + Express_Network *net; + + if ((net = _channel_network_get(chl))) + { + name = express_network_name_get(net); + + if (!eina_list_data_find(groups, name)) + groups = eina_list_append(groups, name); + } + } + + groups = eina_list_sort(groups, eina_list_count(groups), _cb_groups_sort); + + EINA_LIST_FREE(groups, name) + { + EINA_LIST_FOREACH(_win->channels, l, chl) + { + Channel *lchl; + + EINA_LIST_FOREACH(channels, ll, lchl) + { + if (!_channel_network_get(lchl)) + _channel_treeview_item_add(chl, lchl); + } + + _channel_treeview_group_add(chl, name); + + EINA_LIST_FOREACH(channels, ll, lchl) + { + Express_Network *net; + + if ((net = _channel_network_get(lchl))) + { + if (!strcmp(name, express_network_name_get(net))) + _channel_treeview_group_item_add(chl, lchl); + } + } + } + } + + eina_list_free(channels); +} + /* external functions */ Eina_Bool _window_create(void) @@ -878,22 +939,13 @@ _window_network_channels_create(Express_Network *net) } _channel_network_set(chl, net); - - /* if (i < 0) */ - /* { */ - /* if this is the first channel, swallow it */ - /* _window_channel_swallow(chl); */ - - /* focus this channel */ - /* _window_channel_focus(chl); */ - /* } */ - - /* i++; */ } break; } + _window_treeview_update(); + /* if (i >= 0) */ /* { */ /* remove the default channel window @@ -950,6 +1002,8 @@ _window_network_channels_destroy(Express_Network *net) _window_channel_focus(chl); } } + + _window_treeview_update(); } void