Initial import
This commit is contained in:
parent
0feee46e9e
commit
d18ecc7997
|
@ -0,0 +1,397 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <gtksourceview/gtksourceview.h>
|
||||
#include <gtksourceview/gtksourcelanguage.h>
|
||||
#include <gtksourceview/gtksourcelanguagesmanager.h>
|
||||
#include <gtksourceview/gtksourcetag.h>
|
||||
|
||||
#include "gm-editor-view.h"
|
||||
#include "../gm-pixbuf.h"
|
||||
#include "../gm-support.h"
|
||||
#include "../gm-debug.h"
|
||||
#include "../gm-options.h"
|
||||
#include "../gm-color-table.h"
|
||||
#include "../gm-app.h"
|
||||
|
||||
#define GM_EDITOR_VIEW_GET_PRIVATE(object)( \
|
||||
G_TYPE_INSTANCE_GET_PRIVATE((object), \
|
||||
GM_TYPE_EDITOR_VIEW, GmEditorViewPrivate))
|
||||
|
||||
struct _GmEditorViewPrivate {
|
||||
GmWorld *world;
|
||||
GmEditor *editor;
|
||||
|
||||
GtkSourceView *source_view;
|
||||
};
|
||||
|
||||
static GtkSourceLanguage *language = NULL;
|
||||
static GtkSourceLanguagesManager *language_manager = NULL;
|
||||
|
||||
/* Signals */
|
||||
|
||||
enum {
|
||||
MODIFIED_CHANGED,
|
||||
NUM_SIGNALS
|
||||
};
|
||||
|
||||
static guint gm_editor_view_signals[NUM_SIGNALS] = {0};
|
||||
|
||||
G_DEFINE_TYPE(GmEditorView, gm_editor_view, GTK_TYPE_VBOX)
|
||||
|
||||
void on_gm_editor_view_save_clicked(GtkToolButton *button,
|
||||
GmEditorView *view);
|
||||
void on_gm_editor_view_saveclose_clicked(GtkToolButton *button,
|
||||
GmEditorView *view);
|
||||
void on_gm_editor_view_close_clicked(GtkToolButton *button,
|
||||
GmEditorView *view);
|
||||
void on_gm_editor_view_editor_saved(GmEditor *editor, GmEditorView *view);
|
||||
|
||||
void on_gm_editor_view_app_option_changed(GmOptions *options, gchar const *key);
|
||||
void on_gm_editor_view_font_changed(GmColorTable *color_table,
|
||||
gchar const *desc, GmEditorView *view);
|
||||
void on_gm_editor_view_modified_changed(GtkTextBuffer *buffer,
|
||||
GmEditorView *view);
|
||||
|
||||
static void
|
||||
gm_editor_view_finalize(GObject *object) {
|
||||
//GmEditorView *obj = GM_EDITOR_VIEW(object);
|
||||
|
||||
G_OBJECT_CLASS(gm_editor_view_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
GtkSourceTag *
|
||||
gm_editor_view_find_tag(gchar const *name) {
|
||||
GSList *tags, *tag;
|
||||
gchar *tname;
|
||||
GtkSourceTag *st;
|
||||
|
||||
tags = gtk_source_language_get_tags(language);
|
||||
|
||||
for (tag = tags; tag; tag = tag->next) {
|
||||
st = GTK_SOURCE_TAG(tag->data);
|
||||
g_object_get(G_OBJECT(st), "name", &tname, NULL);
|
||||
|
||||
if (strcmp(name, tname) == 0) {
|
||||
g_slist_free(tags);
|
||||
g_free(tname);
|
||||
return st;
|
||||
}
|
||||
|
||||
g_free(tname);
|
||||
}
|
||||
|
||||
g_slist_free(tags);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
gm_editor_view_update_tag(GtkSourceTag *tag, gchar const *name,
|
||||
gchar const *value) {
|
||||
gchar **style;
|
||||
GtkSourceTagStyle *sty;
|
||||
gchar *id;
|
||||
|
||||
if (tag == NULL) {
|
||||
tag = gm_editor_view_find_tag(name);
|
||||
}
|
||||
|
||||
if (tag == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
g_object_get(G_OBJECT(tag), "id", &id, NULL);
|
||||
sty = gtk_source_tag_get_style(tag);
|
||||
style = g_strsplit(value, ",", 6);
|
||||
|
||||
if (g_strv_length(style) == 6) {
|
||||
/* Foreground color */
|
||||
if (strcmp(style[0], "0") == 0) {
|
||||
sty->mask = sty->mask &
|
||||
~GTK_SOURCE_TAG_STYLE_USE_FOREGROUND;
|
||||
} else {
|
||||
sty->mask = sty->mask | GTK_SOURCE_TAG_STYLE_USE_FOREGROUND;
|
||||
gdk_color_parse(style[0], &(sty->foreground));
|
||||
}
|
||||
|
||||
/* Background color */
|
||||
if (strcmp(style[1], "0") == 0) {
|
||||
sty->mask = sty->mask &
|
||||
~GTK_SOURCE_TAG_STYLE_USE_BACKGROUND;
|
||||
} else {
|
||||
sty->mask = sty->mask | GTK_SOURCE_TAG_STYLE_USE_BACKGROUND;
|
||||
gdk_color_parse(style[1], &(sty->background));
|
||||
}
|
||||
|
||||
sty->bold = atoi(style[2]);
|
||||
sty->italic = atoi(style[3]);
|
||||
sty->underline = atoi(style[4]);
|
||||
sty->strikethrough = atoi(style[5]);
|
||||
|
||||
gtk_source_language_set_tag_style(language, id, sty);
|
||||
}
|
||||
|
||||
g_free(id);
|
||||
g_strfreev(style);
|
||||
}
|
||||
|
||||
static void
|
||||
gm_editor_view_setup_tags() {
|
||||
GmOptions *options = gm_app_options(gm_app_instance());
|
||||
GSList *tags, *tag;
|
||||
gchar *name, *oname;
|
||||
gchar const *value;
|
||||
GtkSourceTag *st;
|
||||
|
||||
tags = gtk_source_language_get_tags(language);
|
||||
|
||||
for (tag = tags; tag; tag = tag->next) {
|
||||
st = GTK_SOURCE_TAG(tag->data);
|
||||
|
||||
g_object_get(G_OBJECT(st), "name", &name, NULL);
|
||||
oname = g_strconcat("editor_", name, NULL);
|
||||
|
||||
if ((value = gm_options_get(options, oname))) {
|
||||
gm_editor_view_update_tag(st, NULL, value);
|
||||
}
|
||||
|
||||
g_free(oname);
|
||||
g_free(name);
|
||||
}
|
||||
|
||||
g_slist_free(tags);
|
||||
}
|
||||
|
||||
static void
|
||||
gm_editor_view_class_init(GmEditorViewClass *klass) {
|
||||
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
object_class->finalize = gm_editor_view_finalize;
|
||||
|
||||
gm_editor_view_signals[MODIFIED_CHANGED] =
|
||||
g_signal_new("modified_changed",
|
||||
G_OBJECT_CLASS_TYPE(object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET(GmEditorViewClass, modified_changed),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__BOOLEAN,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
G_TYPE_BOOLEAN);
|
||||
|
||||
if (language_manager == NULL) {
|
||||
language_manager = gtk_source_languages_manager_new();
|
||||
language = gtk_source_languages_manager_get_language_from_mime_type(
|
||||
language_manager, "text/x-moo");
|
||||
|
||||
gm_editor_view_setup_tags();
|
||||
|
||||
g_signal_connect(gm_app_options(gm_app_instance()), "option_changed",
|
||||
G_CALLBACK(on_gm_editor_view_app_option_changed), NULL);
|
||||
|
||||
}
|
||||
|
||||
g_type_class_add_private(object_class, sizeof(GmEditorViewPrivate));
|
||||
}
|
||||
|
||||
GtkSourceView *
|
||||
gm_editor_create_source_view(GmEditorView *view) {
|
||||
GtkTextBuffer *buffer;
|
||||
GtkWidget *source_view;
|
||||
GtkTextIter iter;
|
||||
gchar *line;
|
||||
GList *lines;
|
||||
PangoFontDescription *f;
|
||||
|
||||
GtkSourceTagStyle *st;
|
||||
|
||||
source_view = gtk_source_view_new();
|
||||
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(source_view));
|
||||
|
||||
if (language) {
|
||||
gtk_source_buffer_set_language(GTK_SOURCE_BUFFER(buffer), language);
|
||||
}
|
||||
|
||||
gtk_text_buffer_get_end_iter(buffer, &iter);
|
||||
|
||||
for (lines = gm_editor_lines(view->priv->editor); lines;
|
||||
lines = lines->next) {
|
||||
line = (gchar *) (lines->data);
|
||||
gtk_text_buffer_insert(buffer, &iter, line, -1);
|
||||
|
||||
if (lines->next) {
|
||||
gtk_text_buffer_insert(buffer, &iter, "\r\n", 2);
|
||||
}
|
||||
}
|
||||
|
||||
gtk_text_buffer_set_modified(buffer, FALSE);
|
||||
|
||||
st = gtk_source_tag_style_new();
|
||||
st->mask = GTK_SOURCE_TAG_STYLE_USE_BACKGROUND;
|
||||
gdk_color_parse("#0000FF", &(st->background));
|
||||
gtk_source_buffer_set_bracket_match_style(GTK_SOURCE_BUFFER(buffer), st);
|
||||
|
||||
f = pango_font_description_from_string(gm_color_table_font_description(
|
||||
gm_app_color_table(gm_app_instance())));
|
||||
|
||||
if (f) {
|
||||
gtk_widget_modify_font(source_view, f);
|
||||
pango_font_description_free(f);
|
||||
}
|
||||
|
||||
gtk_source_view_set_insert_spaces_instead_of_tabs(GTK_SOURCE_VIEW(
|
||||
source_view), TRUE);
|
||||
gtk_source_view_set_auto_indent(GTK_SOURCE_VIEW(source_view), TRUE);
|
||||
gtk_source_view_set_show_line_numbers(GTK_SOURCE_VIEW(source_view), TRUE);
|
||||
gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(source_view), GTK_WRAP_WORD_CHAR);
|
||||
gtk_text_view_set_left_margin(GTK_TEXT_VIEW(source_view), 6);
|
||||
gtk_text_view_set_right_margin(GTK_TEXT_VIEW(source_view), 6);
|
||||
|
||||
if (gm_editor_is_code(view->priv->editor)) {
|
||||
gtk_source_buffer_set_highlight(GTK_SOURCE_BUFFER(buffer), TRUE);
|
||||
} else {
|
||||
gtk_source_buffer_set_highlight(GTK_SOURCE_BUFFER(buffer), FALSE);
|
||||
}
|
||||
|
||||
g_signal_connect(buffer, "modified_changed",
|
||||
G_CALLBACK(on_gm_editor_view_modified_changed), view);
|
||||
gtk_widget_show(source_view);
|
||||
|
||||
return GTK_SOURCE_VIEW(source_view);
|
||||
}
|
||||
|
||||
static void
|
||||
gm_editor_view_init(GmEditorView *obj) {
|
||||
GtkWidget *toolbar, *item;
|
||||
obj->priv = GM_EDITOR_VIEW_GET_PRIVATE(obj);
|
||||
|
||||
gtk_box_set_spacing(GTK_BOX(obj), 6);
|
||||
gtk_box_set_homogeneous(GTK_BOX(obj), FALSE);
|
||||
|
||||
toolbar = gtk_toolbar_new();
|
||||
|
||||
item = GTK_WIDGET(gtk_tool_button_new_from_stock(GTK_STOCK_SAVE));
|
||||
g_signal_connect(item, "clicked",
|
||||
G_CALLBACK(on_gm_editor_view_save_clicked), obj);
|
||||
gtk_container_add(GTK_CONTAINER(toolbar), item);
|
||||
|
||||
item = GTK_WIDGET(gtk_tool_button_new(gtk_image_new_from_pixbuf(
|
||||
gm_pixbuf_get("saveclose.xpm")), _("Save&close")));
|
||||
g_signal_connect(item, "clicked",
|
||||
G_CALLBACK(on_gm_editor_view_saveclose_clicked), obj);
|
||||
gtk_container_add(GTK_CONTAINER(toolbar), item);
|
||||
|
||||
item = GTK_WIDGET(gtk_tool_button_new_from_stock(GTK_STOCK_CLOSE));
|
||||
g_signal_connect(item, "clicked",
|
||||
G_CALLBACK(on_gm_editor_view_close_clicked), obj);
|
||||
gtk_container_add(GTK_CONTAINER(toolbar), item);
|
||||
|
||||
gtk_box_pack_start(GTK_BOX(obj), toolbar, FALSE, FALSE, 0);
|
||||
gtk_widget_show_all(toolbar);
|
||||
}
|
||||
|
||||
GmEditorView *
|
||||
gm_editor_view_new(GmWorld *world, GmEditor *editor) {
|
||||
GmEditorView *obj = GM_EDITOR_VIEW(g_object_new(GM_TYPE_EDITOR_VIEW, NULL));
|
||||
GtkWidget *srl;
|
||||
|
||||
obj->priv->editor = editor;
|
||||
obj->priv->world = world;
|
||||
obj->priv->source_view = gm_editor_create_source_view(obj);
|
||||
|
||||
srl = gtk_scrolled_window_new(NULL, NULL);
|
||||
gtk_widget_show(srl);
|
||||
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(srl),
|
||||
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(srl), GTK_WIDGET(obj->priv->source_view));
|
||||
gtk_box_pack_start(GTK_BOX(obj), srl, TRUE, TRUE, 0);
|
||||
|
||||
g_signal_connect(gm_app_color_table(gm_app_instance()), "font_changed",
|
||||
G_CALLBACK(on_gm_editor_view_font_changed), obj);
|
||||
g_signal_connect(editor, "saved",
|
||||
G_CALLBACK(on_gm_editor_view_editor_saved), obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
GmEditor *
|
||||
gm_editor_view_editor(GmEditorView *view) {
|
||||
return view->priv->editor;
|
||||
}
|
||||
|
||||
GtkTextView *
|
||||
gm_editor_view_text_view(GmEditorView *view) {
|
||||
return GTK_TEXT_VIEW(view->priv->source_view);
|
||||
}
|
||||
|
||||
void
|
||||
gm_editor_view_save(GmEditorView *view) {
|
||||
GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(
|
||||
view->priv->source_view));
|
||||
GtkTextIter start, end;
|
||||
gchar *text;
|
||||
|
||||
gtk_text_buffer_get_bounds(buffer, &start, &end);
|
||||
text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
|
||||
gm_editor_set_lines_from_string(view->priv->editor, text);
|
||||
|
||||
g_free(text);
|
||||
gm_editor_save(view->priv->editor);
|
||||
}
|
||||
|
||||
/* Callbacks */
|
||||
|
||||
void
|
||||
on_gm_editor_view_font_changed(GmColorTable *color_table, gchar const *desc,
|
||||
GmEditorView *view) {
|
||||
PangoFontDescription *f;
|
||||
|
||||
f = pango_font_description_from_string(gm_color_table_font_description(
|
||||
gm_app_color_table(gm_app_instance())));
|
||||
|
||||
if (f) {
|
||||
gtk_widget_modify_font(GTK_WIDGET(view->priv->source_view), f);
|
||||
pango_font_description_free(f);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
on_gm_editor_view_editor_saved(GmEditor *editor, GmEditorView *view) {
|
||||
gtk_text_buffer_set_modified(gtk_text_view_get_buffer(GTK_TEXT_VIEW(
|
||||
view->priv->source_view)), FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
on_gm_editor_view_save_clicked(GtkToolButton *button,
|
||||
GmEditorView *view) {
|
||||
gm_editor_view_save(view);
|
||||
}
|
||||
|
||||
void
|
||||
on_gm_editor_view_saveclose_clicked(GtkToolButton *button,
|
||||
GmEditorView *view) {
|
||||
gm_editor_save(view->priv->editor);
|
||||
gm_editor_close(view->priv->editor);
|
||||
}
|
||||
|
||||
void
|
||||
on_gm_editor_view_close_clicked(GtkToolButton *button,
|
||||
GmEditorView *view) {
|
||||
gm_editor_close(view->priv->editor);
|
||||
}
|
||||
|
||||
void
|
||||
on_gm_editor_view_app_option_changed(GmOptions *options, gchar const *key) {
|
||||
gchar const *value;
|
||||
|
||||
if (strncmp(key, "editor_", 7) == 0) {
|
||||
value = gm_options_get(options, key);
|
||||
gm_editor_view_update_tag(NULL, key + 7, value);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
on_gm_editor_view_modified_changed(GtkTextBuffer *buffer,
|
||||
GmEditorView *view) {
|
||||
g_signal_emit(view, gm_editor_view_signals[MODIFIED_CHANGED], 0,
|
||||
gtk_text_buffer_get_modified(buffer));
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
#ifndef __GM_EDITOR_VIEW_H__
|
||||
#define __GM_EDITOR_VIEW_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include "../gm-editor.h"
|
||||
#include "../gm-world.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Type checking and casting macros
|
||||
*/
|
||||
#define GM_TYPE_EDITOR_VIEW (gm_editor_view_get_type())
|
||||
#define GM_EDITOR_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
|
||||
GM_TYPE_EDITOR_VIEW, GmEditorView))
|
||||
#define GM_EDITOR_VIEW_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\
|
||||
GM_TYPE_EDITOR_VIEW, GmEditorView const))
|
||||
#define GM_EDITOR_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \
|
||||
GM_TYPE_EDITOR_VIEW, GmEditorViewClass))
|
||||
#define GM_IS_EDITOR_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \
|
||||
GM_TYPE_EDITOR_VIEW))
|
||||
#define GM_IS_EDITOR_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
|
||||
GM_TYPE_EDITOR_VIEW))
|
||||
#define GM_EDITOR_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \
|
||||
GM_TYPE_EDITOR_VIEW, GmEditorViewClass))
|
||||
|
||||
/* Private structure type */
|
||||
typedef struct _GmEditorViewPrivate GmEditorViewPrivate;
|
||||
|
||||
/*
|
||||
* Main object structure
|
||||
*/
|
||||
typedef struct _GmEditorView GmEditorView;
|
||||
|
||||
struct _GmEditorView {
|
||||
GtkVBox parent;
|
||||
|
||||
/*< private > */
|
||||
GmEditorViewPrivate *priv;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class definition
|
||||
*/
|
||||
typedef struct _GmEditorViewClass GmEditorViewClass;
|
||||
|
||||
struct _GmEditorViewClass {
|
||||
GtkVBoxClass parent_class;
|
||||
|
||||
/* Signals */
|
||||
void (* modified_changed) (GmEditorView *obj, gboolean modified);
|
||||
};
|
||||
|
||||
GType gm_editor_view_get_type(void) G_GNUC_CONST;
|
||||
GmEditorView *gm_editor_view_new(GmWorld *world, GmEditor *editor);
|
||||
GmEditor *gm_editor_view_editor(GmEditorView *view);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* __GM_EDITOR_VIEW_H__ */
|
Reference in New Issue