preliminary guild view in the side bar
This commit is contained in:
parent
b879151e07
commit
af49931b49
@ -21,27 +21,27 @@ typedef enum {
|
|||||||
|
|
||||||
/* A direct message channel for 1:1 communication
|
/* A direct message channel for 1:1 communication
|
||||||
*/
|
*/
|
||||||
CHANNEL_TYPE_DM,
|
CHANNEL_TYPE_DM = 1,
|
||||||
|
|
||||||
/* A guild voice channel
|
/* A guild voice channel
|
||||||
*/
|
*/
|
||||||
CHANNEL_TYPE_GUILD_VOICE,
|
CHANNEL_TYPE_GUILD_VOICE = 2,
|
||||||
|
|
||||||
/* Group direct message channel 1:N communication
|
/* Group direct message channel 1:N communication
|
||||||
*/
|
*/
|
||||||
CHANNEL_TYPE_GROUP_DM,
|
CHANNEL_TYPE_GROUP_DM = 3,
|
||||||
|
|
||||||
/* Category within a GUILD
|
/* Category within a GUILD
|
||||||
*/
|
*/
|
||||||
CHANNEL_TYPE_GUILD_CATEGORY,
|
CHANNEL_TYPE_GUILD_CATEGORY = 4,
|
||||||
|
|
||||||
/* News channel
|
/* News channel
|
||||||
*/
|
*/
|
||||||
CHANNEL_TYPE_GUILD_NEWS,
|
CHANNEL_TYPE_GUILD_NEWS = 5,
|
||||||
|
|
||||||
/* Guild store, no idea what this is
|
/* Guild store, no idea what this is
|
||||||
*/
|
*/
|
||||||
CHANNEL_TYPE_GUILD_STORE,
|
CHANNEL_TYPE_GUILD_STORE = 6,
|
||||||
} dc_channel_type_t;
|
} dc_channel_type_t;
|
||||||
|
|
||||||
struct dc_channel_;
|
struct dc_channel_;
|
||||||
@ -51,6 +51,7 @@ dc_channel_t dc_channel_new(void);
|
|||||||
dc_channel_t dc_channel_from_json(json_t *j);
|
dc_channel_t dc_channel_from_json(json_t *j);
|
||||||
|
|
||||||
char const *dc_channel_id(dc_channel_t c);
|
char const *dc_channel_id(dc_channel_t c);
|
||||||
|
char const *dc_channel_name(dc_channel_t c);
|
||||||
|
|
||||||
dc_channel_type_t dc_channel_type(dc_channel_t c);
|
dc_channel_type_t dc_channel_type(dc_channel_t c);
|
||||||
bool dc_channel_is_dm(dc_channel_t c);
|
bool dc_channel_is_dm(dc_channel_t c);
|
||||||
|
@ -1,12 +1,21 @@
|
|||||||
#ifndef DC_GUILD_H
|
#ifndef DC_GUILD_H
|
||||||
#define DC_GUILD_H
|
#define DC_GUILD_H
|
||||||
|
|
||||||
|
#include <dc/channel.h>
|
||||||
|
|
||||||
|
#include <jansson.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
/* Discords version of groups or chat servers
|
/* Discords version of groups or chat servers
|
||||||
*/
|
*/
|
||||||
struct dc_guild_;
|
struct dc_guild_;
|
||||||
typedef struct dc_guild_ *dc_guild_t;
|
typedef struct dc_guild_ *dc_guild_t;
|
||||||
|
|
||||||
dc_guild_t dc_guild_new(void);
|
dc_guild_t dc_guild_new(void);
|
||||||
|
dc_guild_t dc_guild_from_json(json_t *j);
|
||||||
|
|
||||||
|
size_t dc_guild_channels(dc_guild_t d);
|
||||||
|
dc_channel_t dc_guild_nth_channel(dc_guild_t d, size_t idx);
|
||||||
|
|
||||||
char const *dc_guild_name(dc_guild_t d);
|
char const *dc_guild_name(dc_guild_t d);
|
||||||
void dc_guild_set_name(dc_guild_t d, char const *val);
|
void dc_guild_set_name(dc_guild_t d, char const *val);
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <dc/account.h>
|
#include <dc/account.h>
|
||||||
#include <dc/channel.h>
|
#include <dc/channel.h>
|
||||||
#include <dc/gateway.h>
|
#include <dc/gateway.h>
|
||||||
|
#include <dc/guild.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A session object will contain all information gathered after a user
|
* A session object will contain all information gathered after a user
|
||||||
@ -86,6 +87,12 @@ dc_channel_t dc_session_make_channel(dc_session_t s, dc_account_t *r,
|
|||||||
dc_channel_t dc_session_channel_recipients(dc_session_t s,
|
dc_channel_t dc_session_channel_recipients(dc_session_t s,
|
||||||
dc_account_t *r, size_t sz);
|
dc_account_t *r, size_t sz);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a guild to be managed by this session.
|
||||||
|
*/
|
||||||
|
void dc_session_add_guild(dc_session_t s, dc_guild_t g);
|
||||||
|
GHashTable *dc_session_guilds(dc_session_t s);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* comparision functions for sorting, and finding
|
* comparision functions for sorting, and finding
|
||||||
*/
|
*/
|
||||||
|
@ -124,7 +124,7 @@ dc_channel_t dc_channel_from_json(json_t *j)
|
|||||||
}
|
}
|
||||||
|
|
||||||
v = json_object_get(j, "name");
|
v = json_object_get(j, "name");
|
||||||
if (v == NULL && json_is_string(v)) {
|
if (v != NULL && json_is_string(v)) {
|
||||||
c->name = strdup(json_string_value(v));
|
c->name = strdup(json_string_value(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,6 +237,12 @@ json_t *dc_channel_to_json(dc_channel_t c)
|
|||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char const *dc_channel_name(dc_channel_t c)
|
||||||
|
{
|
||||||
|
return_if_true(c == NULL, NULL);
|
||||||
|
return c->name;
|
||||||
|
}
|
||||||
|
|
||||||
char const *dc_channel_id(dc_channel_t c)
|
char const *dc_channel_id(dc_channel_t c)
|
||||||
{
|
{
|
||||||
return_if_true(c == NULL, NULL);
|
return_if_true(c == NULL, NULL);
|
||||||
|
@ -9,6 +9,8 @@ struct dc_guild_
|
|||||||
|
|
||||||
char *name;
|
char *name;
|
||||||
char *id;
|
char *id;
|
||||||
|
|
||||||
|
GPtrArray *channels;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void dc_guild_free(dc_guild_t ptr)
|
static void dc_guild_free(dc_guild_t ptr)
|
||||||
@ -16,6 +18,11 @@ static void dc_guild_free(dc_guild_t ptr)
|
|||||||
free(ptr->name);
|
free(ptr->name);
|
||||||
free(ptr->id);
|
free(ptr->id);
|
||||||
|
|
||||||
|
if (ptr->channels != NULL) {
|
||||||
|
g_ptr_array_unref(ptr->channels);
|
||||||
|
ptr->channels = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
free(ptr);
|
free(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,9 +33,64 @@ dc_guild_t dc_guild_new(void)
|
|||||||
|
|
||||||
p->ref.cleanup = (dc_cleanup_t)dc_guild_free;
|
p->ref.cleanup = (dc_cleanup_t)dc_guild_free;
|
||||||
|
|
||||||
|
p->channels = g_ptr_array_new_with_free_func((GDestroyNotify)dc_unref);
|
||||||
|
if (p->channels == NULL) {
|
||||||
|
free(p);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return dc_ref(p);
|
return dc_ref(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dc_guild_t dc_guild_from_json(json_t *j)
|
||||||
|
{
|
||||||
|
dc_guild_t g = dc_guild_new();
|
||||||
|
json_t *val = NULL;
|
||||||
|
json_t *c = NULL;
|
||||||
|
size_t idx = 0;
|
||||||
|
|
||||||
|
val = json_object_get(j, "name");
|
||||||
|
goto_if_true(val == NULL || !json_is_string(val), error);
|
||||||
|
g->name = strdup(json_string_value(val));
|
||||||
|
|
||||||
|
val = json_object_get(j, "id");
|
||||||
|
goto_if_true(val == NULL || !json_is_string(val), error);
|
||||||
|
g->id = strdup(json_string_value(val));
|
||||||
|
|
||||||
|
/* there is a ton of more information here, that we should look
|
||||||
|
* add, including "member_count", "owner_id", but for channels
|
||||||
|
* will do nicely
|
||||||
|
*/
|
||||||
|
val = json_object_get(j, "channels");
|
||||||
|
goto_if_true(val == NULL || !json_is_array(val), error);
|
||||||
|
|
||||||
|
json_array_foreach(val, idx, c) {
|
||||||
|
dc_channel_t chan = dc_channel_from_json(c);
|
||||||
|
continue_if_true(chan == NULL);
|
||||||
|
g_ptr_array_add(g->channels, chan);
|
||||||
|
}
|
||||||
|
|
||||||
|
return g;
|
||||||
|
|
||||||
|
error:
|
||||||
|
|
||||||
|
dc_unref(g);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t dc_guild_channels(dc_guild_t d)
|
||||||
|
{
|
||||||
|
return_if_true(d == NULL || d->channels == NULL, 0);
|
||||||
|
return d->channels->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
dc_channel_t dc_guild_nth_channel(dc_guild_t d, size_t idx)
|
||||||
|
{
|
||||||
|
return_if_true(d == NULL || d->channels == NULL, NULL);
|
||||||
|
return_if_true(idx >= d->channels->len, NULL);
|
||||||
|
return g_ptr_array_index(d->channels, idx);
|
||||||
|
}
|
||||||
|
|
||||||
char const *dc_guild_name(dc_guild_t d)
|
char const *dc_guild_name(dc_guild_t d)
|
||||||
{
|
{
|
||||||
return_if_true(d == NULL, NULL);
|
return_if_true(d == NULL, NULL);
|
||||||
|
@ -12,6 +12,7 @@ struct dc_session_
|
|||||||
|
|
||||||
GHashTable *accounts;
|
GHashTable *accounts;
|
||||||
GHashTable *channels;
|
GHashTable *channels;
|
||||||
|
GHashTable *guilds;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* event handlers
|
/* event handlers
|
||||||
@ -40,6 +41,11 @@ static void dc_session_free(dc_session_t s)
|
|||||||
s->channels = NULL;
|
s->channels = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s->guilds != NULL) {
|
||||||
|
g_hash_table_unref(s->guilds);
|
||||||
|
s->guilds = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
dc_session_logout(s);
|
dc_session_logout(s);
|
||||||
|
|
||||||
dc_unref(s->api);
|
dc_unref(s->api);
|
||||||
@ -79,6 +85,7 @@ static void dc_session_handle_ready(dc_session_t s, dc_event_t e)
|
|||||||
size_t idx = 0;
|
size_t idx = 0;
|
||||||
json_t *c = NULL;
|
json_t *c = NULL;
|
||||||
json_t *channels = NULL;
|
json_t *channels = NULL;
|
||||||
|
json_t *guilds = NULL;
|
||||||
|
|
||||||
/* retrieve user information about ourselves, including snowflake,
|
/* retrieve user information about ourselves, including snowflake,
|
||||||
* discriminator, and other things
|
* discriminator, and other things
|
||||||
@ -127,6 +134,17 @@ static void dc_session_handle_ready(dc_session_t s, dc_event_t e)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* load guilds
|
||||||
|
*/
|
||||||
|
guilds = json_object_get(r, "guilds");
|
||||||
|
if (guilds != NULL && json_is_array(guilds)) {
|
||||||
|
json_array_foreach(guilds, idx, c) {
|
||||||
|
dc_guild_t guild = dc_guild_from_json(c);
|
||||||
|
continue_if_true(guild == NULL);
|
||||||
|
dc_session_add_guild(s, guild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* load channels
|
/* load channels
|
||||||
*/
|
*/
|
||||||
channels = json_object_get(r, "private_channels");
|
channels = json_object_get(r, "private_channels");
|
||||||
@ -181,6 +199,11 @@ dc_session_t dc_session_new(dc_loop_t loop)
|
|||||||
);
|
);
|
||||||
goto_if_true(s->channels == NULL, error);
|
goto_if_true(s->channels == NULL, error);
|
||||||
|
|
||||||
|
s->guilds = g_hash_table_new_full(g_str_hash, g_str_equal,
|
||||||
|
free, dc_unref
|
||||||
|
);
|
||||||
|
goto_if_true(s->channels == NULL, error);
|
||||||
|
|
||||||
s->loop = dc_ref(loop);
|
s->loop = dc_ref(loop);
|
||||||
|
|
||||||
s->api = dc_api_new();
|
s->api = dc_api_new();
|
||||||
@ -394,3 +417,23 @@ dc_channel_t dc_session_channel_recipients(dc_session_t s,
|
|||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GHashTable *dc_session_guilds(dc_session_t s)
|
||||||
|
{
|
||||||
|
return_if_true(s == NULL, NULL);
|
||||||
|
return s->guilds;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dc_session_add_guild(dc_session_t s, dc_guild_t g)
|
||||||
|
{
|
||||||
|
return_if_true(s == NULL || g == NULL,);
|
||||||
|
return_if_true(dc_guild_id(g) == NULL,);
|
||||||
|
|
||||||
|
char const *id = dc_guild_id(g);
|
||||||
|
|
||||||
|
if (!g_hash_table_contains(s->guilds, id)) {
|
||||||
|
g_hash_table_insert(s->guilds, strdup(id), dc_ref(g));
|
||||||
|
/* TODO: dedup for saving storage
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -13,6 +13,7 @@ SET(SOURCES
|
|||||||
"include/ncdc/mainwindow.h"
|
"include/ncdc/mainwindow.h"
|
||||||
"include/ncdc/ncdc.h"
|
"include/ncdc/ncdc.h"
|
||||||
"include/ncdc/textview.h"
|
"include/ncdc/textview.h"
|
||||||
|
"include/ncdc/treeview.h"
|
||||||
"src/ack.c"
|
"src/ack.c"
|
||||||
"src/cmds.c"
|
"src/cmds.c"
|
||||||
"src/config.c"
|
"src/config.c"
|
||||||
@ -26,6 +27,7 @@ SET(SOURCES
|
|||||||
"src/ncdc.c"
|
"src/ncdc.c"
|
||||||
"src/post.c"
|
"src/post.c"
|
||||||
"src/textview.c"
|
"src/textview.c"
|
||||||
|
"src/treeview.c"
|
||||||
"src/util.c"
|
"src/util.c"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -24,4 +24,6 @@ void ncdc_mainwindow_input_ready(ncdc_mainwindow_t n);
|
|||||||
void ncdc_mainwindow_rightview(ncdc_mainwindow_t n);
|
void ncdc_mainwindow_rightview(ncdc_mainwindow_t n);
|
||||||
void ncdc_mainwindow_leftview(ncdc_mainwindow_t n);
|
void ncdc_mainwindow_leftview(ncdc_mainwindow_t n);
|
||||||
|
|
||||||
|
void ncdc_mainwindow_update_guilds(ncdc_mainwindow_t n);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
31
ncdc/include/ncdc/treeview.h
Normal file
31
ncdc/include/ncdc/treeview.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef NCDC_TREEVIEW_H
|
||||||
|
#define NCDC_TREEVIEW_H
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ncdc/ncdc.h>
|
||||||
|
|
||||||
|
struct ncdc_treeitem_;
|
||||||
|
typedef struct ncdc_treeitem_ *ncdc_treeitem_t;
|
||||||
|
|
||||||
|
ncdc_treeitem_t ncdc_treeitem_new(void);
|
||||||
|
ncdc_treeitem_t ncdc_treeitem_new_string(wchar_t const *s);
|
||||||
|
|
||||||
|
wchar_t const *ncdc_treeitem_label(ncdc_treeitem_t i);
|
||||||
|
void ncdc_treeitem_set_label(ncdc_treeitem_t i, wchar_t const *s);
|
||||||
|
|
||||||
|
void *ncdc_treeitem_tag(ncdc_treeitem_t i);
|
||||||
|
void ncdc_treeitem_set_tag(ncdc_treeitem_t i, void *t);
|
||||||
|
|
||||||
|
void ncdc_treeitem_clear(ncdc_treeitem_t i);
|
||||||
|
void ncdc_treeitem_add(ncdc_treeitem_t i, ncdc_treeitem_t c);
|
||||||
|
void ncdc_treeitem_remove(ncdc_treeitem_t i, ncdc_treeitem_t c);
|
||||||
|
|
||||||
|
struct ncdc_treeview_;
|
||||||
|
typedef struct ncdc_treeview_ *ncdc_treeview_t;
|
||||||
|
|
||||||
|
ncdc_treeview_t ncdc_treeview_new(void);
|
||||||
|
ncdc_treeitem_t ncdc_treeview_root(ncdc_treeview_t t);
|
||||||
|
void ncdc_treeview_render(ncdc_treeview_t t, WINDOW *w, int lines, int cols);
|
||||||
|
|
||||||
|
#endif
|
@ -1,6 +1,7 @@
|
|||||||
#include <ncdc/mainwindow.h>
|
#include <ncdc/mainwindow.h>
|
||||||
#include <ncdc/input.h>
|
#include <ncdc/input.h>
|
||||||
#include <ncdc/textview.h>
|
#include <ncdc/textview.h>
|
||||||
|
#include <ncdc/treeview.h>
|
||||||
#include <ncdc/cmds.h>
|
#include <ncdc/cmds.h>
|
||||||
#include <ncdc/ncdc.h>
|
#include <ncdc/ncdc.h>
|
||||||
|
|
||||||
@ -37,6 +38,8 @@ struct ncdc_mainwindow_
|
|||||||
WINDOW *sep2;
|
WINDOW *sep2;
|
||||||
|
|
||||||
ncdc_input_t in;
|
ncdc_input_t in;
|
||||||
|
ncdc_treeview_t guildview;
|
||||||
|
ncdc_treeitem_t root;
|
||||||
|
|
||||||
GPtrArray *views;
|
GPtrArray *views;
|
||||||
int curview;
|
int curview;
|
||||||
@ -62,6 +65,7 @@ static void ncdc_mainwindow_free(ncdc_mainwindow_t n)
|
|||||||
delwin(n->sep2);
|
delwin(n->sep2);
|
||||||
|
|
||||||
dc_unref(n->in);
|
dc_unref(n->in);
|
||||||
|
dc_unref(n->guildview);
|
||||||
|
|
||||||
if (n->views != NULL) {
|
if (n->views != NULL) {
|
||||||
g_ptr_array_unref(n->views);
|
g_ptr_array_unref(n->views);
|
||||||
@ -81,6 +85,9 @@ ncdc_mainwindow_t ncdc_mainwindow_new(void)
|
|||||||
ptr->in = ncdc_input_new();
|
ptr->in = ncdc_input_new();
|
||||||
ncdc_input_set_callback(ptr->in, ncdc_mainwindow_callback, ptr);
|
ncdc_input_set_callback(ptr->in, ncdc_mainwindow_callback, ptr);
|
||||||
|
|
||||||
|
ptr->guildview = ncdc_treeview_new();
|
||||||
|
ptr->root = ncdc_treeview_root(ptr->guildview);
|
||||||
|
|
||||||
ptr->views = g_ptr_array_new_with_free_func(
|
ptr->views = g_ptr_array_new_with_free_func(
|
||||||
(GDestroyNotify)dc_unref
|
(GDestroyNotify)dc_unref
|
||||||
);
|
);
|
||||||
@ -134,7 +141,7 @@ ncdc_mainwindow_callback(ncdc_input_t i, wchar_t const *s,
|
|||||||
static void ncdc_mainwindow_resize(ncdc_mainwindow_t n)
|
static void ncdc_mainwindow_resize(ncdc_mainwindow_t n)
|
||||||
{
|
{
|
||||||
n->guilds_h = LINES - 2;
|
n->guilds_h = LINES - 2;
|
||||||
n->guilds_w = (COLS / 5);
|
n->guilds_w = (COLS / 4);
|
||||||
n->guilds_y = 0;
|
n->guilds_y = 0;
|
||||||
n->guilds_x = 0;
|
n->guilds_x = 0;
|
||||||
|
|
||||||
@ -239,6 +246,85 @@ static void ncdc_mainwindow_render_status(ncdc_mainwindow_t n)
|
|||||||
free(status);
|
free(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ncdc_mainwindow_update_guilds(ncdc_mainwindow_t n)
|
||||||
|
{
|
||||||
|
GHashTableIter iter;
|
||||||
|
gpointer key = NULL, value = NULL;
|
||||||
|
size_t idx = 0;
|
||||||
|
|
||||||
|
ncdc_treeitem_clear(n->root);
|
||||||
|
|
||||||
|
if (!is_logged_in()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_iter_init(&iter, dc_session_guilds(current_session));
|
||||||
|
while (g_hash_table_iter_next(&iter, &key, &value)) {
|
||||||
|
dc_guild_t g = (dc_guild_t)value;
|
||||||
|
ncdc_treeitem_t i = ncdc_treeitem_new();
|
||||||
|
wchar_t *name = NULL;
|
||||||
|
|
||||||
|
if (i == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
name = s_convert(dc_guild_name(g));
|
||||||
|
if (name == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ncdc_treeitem_set_label(i, name);
|
||||||
|
|
||||||
|
free(name);
|
||||||
|
name = NULL;
|
||||||
|
|
||||||
|
ncdc_treeitem_set_tag(i, g);
|
||||||
|
|
||||||
|
/* add subchannels
|
||||||
|
*/
|
||||||
|
for (idx = 0; idx < dc_guild_channels(g); idx++) {
|
||||||
|
dc_channel_t c = dc_guild_nth_channel(g, idx);
|
||||||
|
ncdc_treeitem_t ci = NULL;
|
||||||
|
|
||||||
|
if (dc_channel_name(c) == NULL ||
|
||||||
|
dc_channel_id(c) == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skip categories, and shop channels
|
||||||
|
*/
|
||||||
|
if (dc_channel_type(c) == CHANNEL_TYPE_GUILD_CATEGORY ||
|
||||||
|
dc_channel_type(c) == CHANNEL_TYPE_GUILD_NEWS ||
|
||||||
|
dc_channel_type(c) == CHANNEL_TYPE_GUILD_STORE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ci = ncdc_treeitem_new();
|
||||||
|
if (ci == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
aswprintf(&name, L"[%s] %s",
|
||||||
|
(dc_channel_type(c) == CHANNEL_TYPE_GUILD_VOICE ?
|
||||||
|
"<" : "#"),
|
||||||
|
dc_channel_name(c)
|
||||||
|
);
|
||||||
|
if (name == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ncdc_treeitem_set_label(ci, name);
|
||||||
|
free(name);
|
||||||
|
name = NULL;
|
||||||
|
|
||||||
|
ncdc_treeitem_set_tag(ci, c);
|
||||||
|
ncdc_treeitem_add(i, ci);
|
||||||
|
}
|
||||||
|
|
||||||
|
ncdc_treeitem_add(n->root, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ncdc_mainwindow_input_ready(ncdc_mainwindow_t n)
|
void ncdc_mainwindow_input_ready(ncdc_mainwindow_t n)
|
||||||
{
|
{
|
||||||
wint_t i = 0;
|
wint_t i = 0;
|
||||||
@ -311,6 +397,8 @@ void ncdc_mainwindow_refresh(ncdc_mainwindow_t n)
|
|||||||
{
|
{
|
||||||
ncdc_textview_t v = 0;
|
ncdc_textview_t v = 0;
|
||||||
|
|
||||||
|
ncdc_mainwindow_update_guilds(n);
|
||||||
|
ncdc_treeview_render(n->guildview, n->guilds, n->guilds_h, n->guilds_w);
|
||||||
wnoutrefresh(n->guilds);
|
wnoutrefresh(n->guilds);
|
||||||
|
|
||||||
/* render active text view
|
/* render active text view
|
||||||
|
181
ncdc/src/treeview.c
Normal file
181
ncdc/src/treeview.c
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
#include <ncdc/treeview.h>
|
||||||
|
#include <ncdc/ncdc.h>
|
||||||
|
|
||||||
|
struct ncdc_treeitem_
|
||||||
|
{
|
||||||
|
dc_refable_t ref;
|
||||||
|
|
||||||
|
/* content
|
||||||
|
*/
|
||||||
|
wchar_t *content;
|
||||||
|
|
||||||
|
/* collapsed?
|
||||||
|
*/
|
||||||
|
bool collapsed;
|
||||||
|
|
||||||
|
/* children
|
||||||
|
*/
|
||||||
|
GPtrArray *children;
|
||||||
|
|
||||||
|
/* user defined data
|
||||||
|
*/
|
||||||
|
void *tag;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void ncdc_treeitem_free(ncdc_treeitem_t t)
|
||||||
|
{
|
||||||
|
return_if_true(t == NULL,);
|
||||||
|
|
||||||
|
free(t->content);
|
||||||
|
t->content = NULL;
|
||||||
|
|
||||||
|
if (t->children != NULL) {
|
||||||
|
g_ptr_array_unref(t->children);
|
||||||
|
t->children = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
ncdc_treeitem_t ncdc_treeitem_new(void)
|
||||||
|
{
|
||||||
|
ncdc_treeitem_t t = calloc(1, sizeof(struct ncdc_treeitem_));
|
||||||
|
return_if_true(t == NULL, NULL);
|
||||||
|
|
||||||
|
t->ref.cleanup = (dc_cleanup_t)ncdc_treeitem_free;
|
||||||
|
|
||||||
|
t->children = g_ptr_array_new_with_free_func((GDestroyNotify)dc_unref);
|
||||||
|
if (t->children == NULL) {
|
||||||
|
free(t);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dc_ref(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
ncdc_treeitem_t ncdc_treeitem_new_string(wchar_t const *s)
|
||||||
|
{
|
||||||
|
ncdc_treeitem_t t = ncdc_treeitem_new();
|
||||||
|
return_if_true(t == NULL, NULL);
|
||||||
|
|
||||||
|
t->content = wcsdup(s);
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ncdc_treeitem_add(ncdc_treeitem_t i, ncdc_treeitem_t c)
|
||||||
|
{
|
||||||
|
return_if_true(i == NULL || c == NULL,);
|
||||||
|
g_ptr_array_add(i->children, dc_ref(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ncdc_treeitem_remove(ncdc_treeitem_t i, ncdc_treeitem_t c)
|
||||||
|
{
|
||||||
|
return_if_true(i == NULL || c == NULL,);
|
||||||
|
g_ptr_array_remove(i->children, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ncdc_treeitem_clear(ncdc_treeitem_t i)
|
||||||
|
{
|
||||||
|
return_if_true(i == NULL || i->children == NULL,);
|
||||||
|
return_if_true(i->children->len == 0,);
|
||||||
|
g_ptr_array_remove_range(i->children, 0, i->children->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ncdc_treeitem_tag(ncdc_treeitem_t i)
|
||||||
|
{
|
||||||
|
return_if_true(i == NULL, NULL);
|
||||||
|
return i->tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ncdc_treeitem_set_tag(ncdc_treeitem_t i, void *t)
|
||||||
|
{
|
||||||
|
return_if_true(i == NULL,);
|
||||||
|
i->tag = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t const *ncdc_treeitem_label(ncdc_treeitem_t i)
|
||||||
|
{
|
||||||
|
return_if_true(i == NULL, NULL);
|
||||||
|
return i->content;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ncdc_treeitem_set_label(ncdc_treeitem_t i, wchar_t const *s)
|
||||||
|
{
|
||||||
|
return_if_true(i == NULL || s == NULL,);
|
||||||
|
free(i->content);
|
||||||
|
i->content = wcsdup(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ncdc_treeitem_render(ncdc_treeitem_t t, WINDOW *win,
|
||||||
|
int lines, int cols, int l, int c)
|
||||||
|
{
|
||||||
|
size_t i = 0, off = 0;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (t->content != NULL) {
|
||||||
|
size_t len = wcslen(t->content);
|
||||||
|
|
||||||
|
mvwaddwstr(win, l, c, t->content);
|
||||||
|
off = ((len + c) / cols) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < t->children->len; i++) {
|
||||||
|
ncdc_treeitem_t child = g_ptr_array_index(t->children, i);
|
||||||
|
ret = ncdc_treeitem_render(child, win, lines, cols,
|
||||||
|
l + off, c + 1
|
||||||
|
);
|
||||||
|
off += ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return off;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ncdc_treeview_
|
||||||
|
{
|
||||||
|
dc_refable_t ref;
|
||||||
|
|
||||||
|
ncdc_treeitem_t root;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void ncdc_treeview_free(ncdc_treeview_t t)
|
||||||
|
{
|
||||||
|
return_if_true(t == NULL,);
|
||||||
|
|
||||||
|
dc_unref(t->root);
|
||||||
|
t->root = NULL;
|
||||||
|
|
||||||
|
free(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
ncdc_treeview_t ncdc_treeview_new(void)
|
||||||
|
{
|
||||||
|
ncdc_treeview_t t = calloc(1, sizeof(struct ncdc_treeview_));
|
||||||
|
return_if_true(t == NULL, NULL);
|
||||||
|
|
||||||
|
t->ref.cleanup = (dc_cleanup_t)ncdc_treeview_free;
|
||||||
|
|
||||||
|
t->root = ncdc_treeitem_new();
|
||||||
|
goto_if_true(t->root == NULL, error);
|
||||||
|
|
||||||
|
return dc_ref(t);
|
||||||
|
|
||||||
|
error:
|
||||||
|
|
||||||
|
dc_unref(t);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ncdc_treeview_render(ncdc_treeview_t t, WINDOW *w, int lines, int cols)
|
||||||
|
{
|
||||||
|
werase(w);
|
||||||
|
wmove(w, 0, 0);
|
||||||
|
ncdc_treeitem_render(t->root, w, lines, cols, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ncdc_treeitem_t ncdc_treeview_root(ncdc_treeview_t t)
|
||||||
|
{
|
||||||
|
return_if_true(t == NULL, NULL);
|
||||||
|
return t->root;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user