Initial import
This commit is contained in:
parent
98a61810e4
commit
7accf8e78f
|
@ -0,0 +1,282 @@
|
|||
#include <gtk/gtk.h>
|
||||
#include <string.h>
|
||||
#include "gm-app.h"
|
||||
#include "gm-pixbuf.h"
|
||||
#include "gm-worlds-view.h"
|
||||
#include "gm-world.h"
|
||||
#include "gm-options.h"
|
||||
#include "gm-support.h"
|
||||
|
||||
#define GM_WORLDS_VIEW_GET_PRIVATE(object)( \
|
||||
G_TYPE_INSTANCE_GET_PRIVATE((object), \
|
||||
GM_TYPE_WORLDS_VIEW, GmWorldsViewPrivate))
|
||||
|
||||
static void on_gm_worlds_view_world_option_changed(GmOptions *options,
|
||||
gchar const *key, GmWorldsView *view);
|
||||
static void on_gm_worlds_view_app_world_added(GmApp *app, GmWorld *world,
|
||||
GmWorldsView *view);
|
||||
static void on_gm_worlds_view_app_world_removed(GmApp *app, GmWorld *world,
|
||||
GmWorldsView *view);
|
||||
|
||||
struct _GmWorldsViewPrivate {
|
||||
GtkTreeModel *model;
|
||||
};
|
||||
|
||||
/* Signals
|
||||
|
||||
enum {
|
||||
PROTO
|
||||
NUM_SIGNALS
|
||||
};
|
||||
|
||||
static guint gm_worlds_view_signals[NUM_SIGNALS] = {0};*/
|
||||
|
||||
G_DEFINE_TYPE(GmWorldsView, gm_worlds_view, GTK_TYPE_TREE_VIEW)
|
||||
|
||||
static void
|
||||
gm_worlds_view_finalize(GObject *object) {
|
||||
GmWorldsView *obj = GM_WORLDS_VIEW(object);
|
||||
GtkTreeModel *model = obj->priv->model;
|
||||
GmWorld *list_world;
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (gtk_tree_model_get_iter_first(model, &iter)) {
|
||||
do {
|
||||
gtk_tree_model_get(model, &iter, GM_WORLDS_VIEW_WORLD_COLUMN,
|
||||
&list_world, -1);
|
||||
g_signal_handlers_disconnect_by_func(gm_world_options(list_world),
|
||||
G_CALLBACK(on_gm_worlds_view_world_option_changed),
|
||||
obj);
|
||||
} while (gtk_tree_model_iter_next(model, &iter));
|
||||
}
|
||||
|
||||
g_signal_handlers_disconnect_by_func(gm_app_instance(),
|
||||
G_CALLBACK(on_gm_worlds_view_app_world_added), obj);
|
||||
g_signal_handlers_disconnect_by_func(gm_app_instance(),
|
||||
G_CALLBACK(on_gm_worlds_view_app_world_removed), obj);
|
||||
|
||||
G_OBJECT_CLASS(gm_worlds_view_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static void
|
||||
gm_worlds_view_class_init(GmWorldsViewClass *klass) {
|
||||
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
object_class->finalize = gm_worlds_view_finalize;
|
||||
|
||||
/*gm_worlds_view_signals[PROTO] =
|
||||
g_signal_new("proto",
|
||||
G_OBJECT_CLASS_TYPE(object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET(GmWorldsViewClass, proto),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE,
|
||||
0);*/
|
||||
|
||||
g_type_class_add_private(object_class, sizeof(GmWorldsViewPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
gm_worlds_view_init(GmWorldsView *obj) {
|
||||
obj->priv = GM_WORLDS_VIEW_GET_PRIVATE(obj);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
gm_worlds_view_world_text(GmWorldsView *view, GmWorld *world) {
|
||||
gchar *text;
|
||||
gchar const *player, *server;
|
||||
GmOptions *options = gm_world_options(world);
|
||||
|
||||
player = gm_options_get(options, "player_name");
|
||||
server = gm_options_get(options, "host");
|
||||
|
||||
text = g_strconcat("<b>", gm_options_get(options, "name"),
|
||||
_("</b>\n<small>Server: "),
|
||||
((server && *server != '\0') ? server : _("<i>unspecified</i>")),
|
||||
_("\nPlayer: "),
|
||||
((player && *player != '\0') ? player : _("<i>unspecified</i>")),
|
||||
"</small>",
|
||||
NULL);
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
static void
|
||||
gm_worlds_view_populate_worlds(GmWorldsView *view) {
|
||||
GmApp *app = gm_app_instance();
|
||||
GList *worlds = gm_app_worlds(app);
|
||||
GList *item;
|
||||
GmWorld *world;
|
||||
|
||||
for (item = worlds; item; item = item->next) {
|
||||
world = (GmWorld *)(item->data);
|
||||
gm_worlds_view_add_world(view, world);
|
||||
}
|
||||
|
||||
g_list_free(worlds);
|
||||
}
|
||||
|
||||
static void
|
||||
gm_worlds_view_build(GmWorldsView *view) {
|
||||
GtkCellRenderer *renderer;
|
||||
GtkTreeViewColumn *column;
|
||||
GtkTreeView *tree_view = GTK_TREE_VIEW(view);
|
||||
|
||||
view->priv->model = GTK_TREE_MODEL(gtk_list_store_new(
|
||||
GM_WORLDS_VIEW_N_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING,
|
||||
G_TYPE_POINTER, G_TYPE_STRING));
|
||||
|
||||
gtk_tree_view_set_model(tree_view, view->priv->model);
|
||||
gtk_tree_selection_set_mode(gtk_tree_view_get_selection(tree_view),
|
||||
GTK_SELECTION_MULTIPLE);
|
||||
|
||||
renderer = gtk_cell_renderer_pixbuf_new();
|
||||
column = gtk_tree_view_column_new_with_attributes(_("Logo"), renderer,
|
||||
"pixbuf", GM_WORLDS_VIEW_LOGO_COLUMN, NULL);
|
||||
gtk_tree_view_column_set_min_width(column, 40);
|
||||
gtk_tree_view_append_column(tree_view, column);
|
||||
|
||||
renderer = gtk_cell_renderer_text_new();
|
||||
column = gtk_tree_view_column_new_with_attributes(_("Name"), renderer,
|
||||
"markup", GM_WORLDS_VIEW_NAME_COLUMN, NULL);
|
||||
gtk_tree_view_append_column(tree_view, column);
|
||||
|
||||
gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(view->priv->model),
|
||||
GM_WORLDS_VIEW_SORT_COLUMN, GTK_SORT_ASCENDING);
|
||||
|
||||
gm_worlds_view_populate_worlds(view);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gm_worlds_view_find_by_options(GmWorldsView *view, GmOptions *options,
|
||||
GtkTreeIter *iter, GmWorld **world) {
|
||||
GtkTreeModel *model = view->priv->model;
|
||||
GmWorld *list_world;
|
||||
|
||||
if (gtk_tree_model_get_iter_first(model, iter)) {
|
||||
do {
|
||||
gtk_tree_model_get(model, iter, GM_WORLDS_VIEW_WORLD_COLUMN,
|
||||
&list_world, -1);
|
||||
|
||||
if (options == gm_world_options(list_world)) {
|
||||
if (world != NULL) {
|
||||
*world = list_world;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
} while (gtk_tree_model_iter_next(model, iter));
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gm_worlds_view_find(GmWorldsView *view, GmWorld *world, GtkTreeIter *iter) {
|
||||
return gm_worlds_view_find_by_options(view, gm_world_options(world), iter,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* Public */
|
||||
GtkWidget *
|
||||
gm_worlds_view_new() {
|
||||
GmWorldsView *obj = GM_WORLDS_VIEW(g_object_new(GM_TYPE_WORLDS_VIEW, NULL));
|
||||
|
||||
gm_worlds_view_build(obj);
|
||||
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(obj), FALSE);
|
||||
|
||||
g_signal_connect(gm_app_instance(), "world_added",
|
||||
G_CALLBACK(on_gm_worlds_view_app_world_added), obj);
|
||||
g_signal_connect(gm_app_instance(), "world_removed",
|
||||
G_CALLBACK(on_gm_worlds_view_app_world_removed), obj);
|
||||
|
||||
return GTK_WIDGET(obj);
|
||||
}
|
||||
|
||||
void
|
||||
gm_worlds_view_add_world(GmWorldsView *view, GmWorld *world) {
|
||||
GtkTreeIter iter;
|
||||
GdkPixbuf *pix_logo = NULL;
|
||||
gchar *name = gm_worlds_view_world_text(view, world);
|
||||
gchar const *logo = gm_options_get(gm_world_options(world), "logo");
|
||||
GtkListStore *store = GTK_LIST_STORE(view->priv->model);
|
||||
|
||||
if (logo) {
|
||||
pix_logo = gm_pixbuf_get_at_size(logo, 32, 32);
|
||||
}
|
||||
|
||||
if (!pix_logo) {
|
||||
pix_logo = gm_pixbuf_get_at_size("world.svg", 32, 32);
|
||||
}
|
||||
|
||||
gtk_list_store_append(store, &iter);
|
||||
gtk_list_store_set(store, &iter,
|
||||
GM_WORLDS_VIEW_LOGO_COLUMN, pix_logo,
|
||||
GM_WORLDS_VIEW_NAME_COLUMN, name,
|
||||
GM_WORLDS_VIEW_WORLD_COLUMN, world,
|
||||
GM_WORLDS_VIEW_SORT_COLUMN, gm_world_name(world),
|
||||
-1);
|
||||
|
||||
g_signal_connect(gm_world_options(world), "option_changed",
|
||||
G_CALLBACK(on_gm_worlds_view_world_option_changed), view);
|
||||
|
||||
g_free(name);
|
||||
}
|
||||
|
||||
GtkTreeModel *
|
||||
gm_worlds_view_model(GmWorldsView *view) {
|
||||
return view->priv->model;
|
||||
}
|
||||
|
||||
/* Callbacks */
|
||||
|
||||
static void
|
||||
on_gm_worlds_view_world_option_changed(GmOptions *options,
|
||||
gchar const *key, GmWorldsView *view) {
|
||||
GtkTreeIter iter;
|
||||
GtkListStore *store = GTK_LIST_STORE(view->priv->model);
|
||||
gchar *text;
|
||||
gchar const *logo;
|
||||
GdkPixbuf *pix_logo;
|
||||
GmWorld *world;
|
||||
|
||||
if (!gm_worlds_view_find_by_options(view, options, &iter, &world)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(key, "name") == 0 ||
|
||||
strcmp(key, "player_name") == 0 ||
|
||||
strcmp(key, "host") == 0) {
|
||||
text = gm_worlds_view_world_text(view, world);
|
||||
gtk_list_store_set(store, &iter, GM_WORLDS_VIEW_NAME_COLUMN, text, -1);
|
||||
g_free(text);
|
||||
} else if (strcmp(key, "logo")) {
|
||||
logo = gm_options_get(options, "logo");
|
||||
|
||||
if (logo) {
|
||||
pix_logo = gm_pixbuf_get_at_size(logo, 32, 32);
|
||||
} else {
|
||||
pix_logo = gm_pixbuf_get_at_size("world.svg", 32, 32);
|
||||
}
|
||||
|
||||
gtk_list_store_set(store, &iter, GM_WORLDS_VIEW_LOGO_COLUMN,
|
||||
pix_logo, -1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_gm_worlds_view_app_world_added(GmApp *app, GmWorld *world,
|
||||
GmWorldsView *view) {
|
||||
gm_worlds_view_add_world(view, world);
|
||||
}
|
||||
|
||||
static void
|
||||
on_gm_worlds_view_app_world_removed(GmApp *app, GmWorld *world,
|
||||
GmWorldsView *view) {
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (gm_worlds_view_find(view, world, &iter)) {
|
||||
gtk_list_store_remove(GTK_LIST_STORE(view->priv->model), &iter);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
#ifndef __GM_WORLDS_VIEW_H__
|
||||
#define __GM_WORLDS_VIEW_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Type checking and casting macros
|
||||
*/
|
||||
#define GM_TYPE_WORLDS_VIEW (gm_worlds_view_get_type())
|
||||
#define GM_WORLDS_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
|
||||
GM_TYPE_WORLDS_VIEW, GmWorldsView))
|
||||
#define GM_WORLDS_VIEW_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
|
||||
GM_TYPE_WORLDS_VIEW, GmWorldsView const))
|
||||
#define GM_WORLDS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \
|
||||
GM_TYPE_WORLDS_VIEW, GmWorldsViewClass))
|
||||
#define GM_IS_WORLDS_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \
|
||||
GM_TYPE_WORLDS_VIEW))
|
||||
#define GM_IS_WORLDS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
|
||||
GM_TYPE_WORLDS_VIEW))
|
||||
#define GM_WORLDS_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \
|
||||
GM_TYPE_WORLDS_VIEW, GmWorldsViewClass))
|
||||
|
||||
enum {
|
||||
GM_WORLDS_VIEW_LOGO_COLUMN,
|
||||
GM_WORLDS_VIEW_NAME_COLUMN,
|
||||
GM_WORLDS_VIEW_WORLD_COLUMN,
|
||||
GM_WORLDS_VIEW_SORT_COLUMN,
|
||||
GM_WORLDS_VIEW_N_COLUMNS
|
||||
};
|
||||
|
||||
/* Private structure type */
|
||||
typedef struct _GmWorldsViewPrivate GmWorldsViewPrivate;
|
||||
|
||||
/*
|
||||
* Main object structure
|
||||
*/
|
||||
typedef struct _GmWorldsView GmWorldsView;
|
||||
|
||||
struct _GmWorldsView {
|
||||
GtkTreeView parent;
|
||||
|
||||
/*< private > */
|
||||
GmWorldsViewPrivate *priv;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class definition
|
||||
*/
|
||||
typedef struct _GmWorldsViewClass GmWorldsViewClass;
|
||||
|
||||
struct _GmWorldsViewClass {
|
||||
GtkTreeViewClass parent_class;
|
||||
|
||||
/* Signals
|
||||
void (* proto) (GmWorldsView *obj); */
|
||||
};
|
||||
|
||||
GType gm_worlds_view_get_type(void) G_GNUC_CONST;
|
||||
GtkWidget *gm_worlds_view_new();
|
||||
|
||||
void gm_worlds_view_add_world(GmWorldsView *view, GmWorld *world);
|
||||
GtkTreeModel *gm_worlds_view_model(GmWorldsView *view);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* __GM_WORLDS_VIEW_H__ */
|
Reference in New Issue