This repository has been archived on 2020-04-11. You can view files and clone it, but cannot push or open issues or pull requests.
gnoemoe/gnoemoe/widgets/gm-source-style-scheme.c

302 lines
8.3 KiB
C

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include "gm-source-style-scheme.h"
#include "gm-color-table.h"
#include "gm-app.h"
#include "gm-support.h"
#include "gm-debug.h"
#define GM_TYPE_SOURCE_STYLE_SCHEME (gm_source_style_scheme_get_type ())
#define GM_SOURCE_STYLE_SCHEME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GM_TYPE_SOURCE_STYLE_SCHEME, GmSourceStyleScheme))
#define GM_SOURCE_STYLE_SCHEME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GM_TYPE_SOURCE_STYLE_SCHEME, GmSourceStyleSchemeClass))
#define GM_IS_SOURCE_STYLE_SCHEME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GM_TYPE_SOURCE_STYLE_SCHEME))
#define GM_IS_SOURCE_STYLE_SCHEME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GM_TYPE_SOURCE_STYLE_SCHEME))
#define GM_SOURCE_STYLE_SCHEME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GM_TYPE_SOURCE_STYLE_SCHEME, GmSourceStyleSchemeClass))
typedef struct _GmSourceStyleScheme GmSourceStyleScheme;
typedef struct _GmSourceStyleSchemeClass GmSourceStyleSchemeClass;
struct _GmSourceStyleScheme {
GObject parent_instance;
GHashTable *mapping;
GHashTable *styles;
};
struct _GmSourceStyleSchemeClass {
GObjectClass parent_class;
};
static GObjectClass *parent_class = NULL;
static GType gm_source_style_scheme_get_type (void);
static void gm_source_style_scheme_class_init(GmSourceStyleSchemeClass *klass);
static void gm_source_style_scheme_IFace_init(GtkSourceStyleSchemeClass *iface);
static void gm_source_style_scheme_init(GmSourceStyleScheme *scheme);
static void gm_source_style_scheme_finalize(GObject *object);
static GtkSourceTagStyle *gm_source_style_scheme_get_tag_style(
GtkSourceStyleScheme *scheme, const gchar *style_name);
static const gchar *gm_source_style_scheme_get_name(GtkSourceStyleScheme *scheme);
static GSList *gm_source_style_scheme_get_style_names(GtkSourceStyleScheme *scheme);
static GType
gm_source_style_scheme_get_type (void)
{
static GType type = 0;
if (!type)
{
static const GTypeInfo info =
{
sizeof (GmSourceStyleSchemeClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gm_source_style_scheme_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GmSourceStyleScheme),
0, /* n_preallocs */
(GInstanceInitFunc) gm_source_style_scheme_init,
};
static const GInterfaceInfo iface_info =
{
(GInterfaceInitFunc) gm_source_style_scheme_IFace_init, /* interface_init */
NULL, /* interface_finalize */
NULL /* interface_data */
};
type = g_type_register_static (G_TYPE_OBJECT,
"GmSourceStyleScheme",
&info,
0);
g_type_add_interface_static (type,
GTK_TYPE_SOURCE_STYLE_SCHEME,
&iface_info);
}
return type;
}
static void
gm_source_style_scheme_class_init(GmSourceStyleSchemeClass *klass) {
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
parent_class = g_type_class_peek_parent(klass);
gobject_class->finalize = gm_source_style_scheme_finalize;
}
static void
gm_source_style_scheme_IFace_init(GtkSourceStyleSchemeClass *iface) {
iface->get_tag_style = gm_source_style_scheme_get_tag_style;
iface->get_name = gm_source_style_scheme_get_name;
iface->get_style_names = gm_source_style_scheme_get_style_names;
}
static GtkSourceTagStyle *
new_tag_style(gchar const * foreground, gchar const * background, gboolean bold,
gboolean italic) {
GtkSourceTagStyle *ts;
ts = gtk_source_tag_style_new();
gdk_color_parse(foreground, &ts->foreground);
ts->mask |= GTK_SOURCE_TAG_STYLE_USE_FOREGROUND;
if (background != NULL) {
gdk_color_parse (background, &ts->background);
ts->mask |= GTK_SOURCE_TAG_STYLE_USE_BACKGROUND;
}
ts->italic = italic;
ts->bold = bold;
ts->is_default = TRUE;
return ts;
}
typedef struct _GmSourceStyleEntry {
gchar const *name;
gchar const *color_name;
gboolean bold;
gboolean italic;
} GmSourceStyleEntry;
static GmSourceStyleEntry entries[] = {
{"Base-N Integer", "fg_purple_h"},
{"Character", "fg_purple_h"},
{"Comment", "fg_blue_h"},
{"Data Type", "fg_cyan", TRUE},
{"Function", "fg_green"},
{"Decimal", "fg_purple_h"},
{"Floating Point", "fg_purple_h"},
{"Keyword", "fg_red", TRUE},
{"String", "fg_purple_h"},
{NULL, NULL}
};
static GmKeyValuePair mapping[] = {
{"fg_purple_h", "Object@32@Number String"},
{"fg_cyan", "Builtin@32@Variables Types S-Ref Error"},
{"fg_green", "Builtin@32@Functions"},
{"fg_blue_h", "Line@32@Comment"},
{"fg_red", "Keywords"},
{NULL, NULL}
};
static void
gm_source_style_scheme_init_mapping(GmSourceStyleScheme *scheme) {
GmKeyValuePair *entry;
scheme->mapping = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
(GDestroyNotify)g_strfreev);
for (entry = mapping; entry->key; ++entry) {
g_hash_table_insert(scheme->mapping, g_strdup(entry->key),
g_strsplit(entry->value, " ", 0));
}
}
static void
gm_source_style_scheme_init(GmSourceStyleScheme *scheme) {
GtkSourceTagStyle *ts;
GmColorTable *table = gm_app_color_table(gm_app_instance());
GmSourceStyleEntry *entry;
scheme->styles = g_hash_table_new_full((GHashFunc)g_str_hash,
(GEqualFunc)g_str_equal, (GDestroyNotify)g_free,
(GDestroyNotify)gtk_source_tag_style_free);
for (entry = entries; entry->name; ++entry) {
ts = new_tag_style(gm_color_table_get_hex(table, entry->color_name),
NULL, entry->bold, entry->italic);
g_hash_table_insert(scheme->styles, g_strdup(entry->name), ts);
}
gm_source_style_scheme_init_mapping(scheme);
}
static void
gm_source_style_scheme_finalize(GObject *object) {
GmSourceStyleScheme *scheme = GM_SOURCE_STYLE_SCHEME(object);
g_hash_table_destroy(scheme->styles);
g_hash_table_destroy(scheme->mapping);
G_OBJECT_CLASS(parent_class)->finalize (object);
}
static GtkSourceTagStyle *
gm_source_style_scheme_get_tag_style(GtkSourceStyleScheme *scheme,
const gchar *style_name) {
GmSourceStyleScheme *ds;
const gpointer *style;
g_return_val_if_fail(GM_IS_SOURCE_STYLE_SCHEME(scheme), NULL);
g_return_val_if_fail(style_name != NULL, NULL);
ds = GM_SOURCE_STYLE_SCHEME(scheme);
style = g_hash_table_lookup(ds->styles, style_name);
return (style != NULL) ? gtk_source_tag_style_copy((GtkSourceTagStyle *)style) : NULL;
}
static const gchar *
gm_source_style_scheme_get_name(GtkSourceStyleScheme *scheme) {
g_return_val_if_fail(GTK_IS_SOURCE_STYLE_SCHEME(scheme), NULL);
return _("Gnoemoe");
}
static void
add_style_name(gpointer key, gpointer value, gpointer user_data) {
GSList **l = user_data;
*l = g_slist_append(*l, g_strdup(key));
}
static GSList *
gm_source_style_scheme_get_style_names(GtkSourceStyleScheme *scheme) {
GmSourceStyleScheme *ds;
GSList *l = NULL;
g_return_val_if_fail(GTK_IS_SOURCE_STYLE_SCHEME(scheme), NULL);
ds = GM_SOURCE_STYLE_SCHEME(scheme);
g_hash_table_foreach(ds->styles, add_style_name, &l);
return l;
}
/* Default style scheme */
static GtkSourceStyleScheme *gm_style_scheme = NULL;
static void
on_gm_source_style_scheme_color_changed(GmColorTable *table,
gchar const *color) {
gchar **ids;
gchar const *hex = gm_color_table_get_hex(table, color);
GmSourceStyleEntry *entry;
GtkSourceTagStyle *style;
for (entry = entries; entry->name; ++entry) {
if (strcmp(entry->color_name, color) == 0) {
style = g_hash_table_lookup(
GM_SOURCE_STYLE_SCHEME(gm_style_scheme)->styles,
entry->name);
if (style != NULL) {
gdk_color_parse(hex, &(style->foreground));
}
}
}
ids = g_hash_table_lookup(GM_SOURCE_STYLE_SCHEME(gm_style_scheme)->mapping,
color);
if (ids) {
for (; *ids; ++ids) {
g_signal_emit_by_name(gm_style_scheme, "style_changed",
*ids);
}
}
}
void
gm_source_style_weak_destroy(gpointer data, GObject *object) {
g_signal_handlers_disconnect_by_func(gm_app_color_table(gm_app_instance()),
on_gm_source_style_scheme_color_changed, NULL);
gm_style_scheme = NULL;
}
GtkSourceStyleScheme *
gm_source_style_scheme_get_default(void) {
if (gm_style_scheme == NULL) {
gm_style_scheme = g_object_new(GM_TYPE_SOURCE_STYLE_SCHEME,
NULL);
g_object_weak_ref(G_OBJECT(gm_style_scheme),
gm_source_style_weak_destroy, NULL);
g_signal_connect(gm_app_color_table(gm_app_instance()),
"color-changed",
G_CALLBACK(on_gm_source_style_scheme_color_changed), NULL);
} else {
g_object_ref(gm_style_scheme);
}
return gm_style_scheme;
}