32
32
public class TextEditor : TextBuffer {
34
34
public TextView text_view;
35
public bool style_bold;
36
public bool style_italic;
37
public bool style_underline;
38
public bool style_strikethrough;
36
40
public signal void cursor_moved ();
37
41
public signal void text_inserted ();
39
43
public TextEditor () {
40
44
setup_tagtable (this);
41
45
text_view = new TextView.with_buffer (this);
43
this.notify["cursor-position"].connect (cursor_moved_callback);
49
style_underline = false;
50
style_strikethrough = false;
52
text_view.move_cursor.connect (cursor_moved_callback);
53
text_view.button_release_event.connect (editor_clicked_callback);
44
54
this.insert_text.connect_after (text_inserted_callback);
46
56
text_view.key_press_event.connect (key_press_callback);
47
57
text_view.pixels_below_lines = 20;
50
60
// Get a TextTagTable with all the default tags
51
61
private void setup_tagtable (TextBuffer buffer) {
53
63
buffer.create_tag ("bold", "weight", 700);
54
64
buffer.create_tag ("italic", "style", Pango.Style.ITALIC);
55
65
buffer.create_tag ("underline", "underline", Pango.Underline.SINGLE);
56
66
buffer.create_tag ("strikethrough", "strikethrough", true);
58
68
buffer.create_tag ("align-left", "justification", Gtk.Justification.LEFT);
59
69
buffer.create_tag ("align-center", "justification", Gtk.Justification.CENTER);
60
70
buffer.create_tag ("align-right", "justification", Gtk.Justification.RIGHT);
61
71
buffer.create_tag ("align-fill", "justification", Gtk.Justification.FILL);
67
77
* Styles (apply, remove, check)
70
80
public void apply_style (string name) {
72
82
get_selection_range ().apply_style (name);
86
else if (name == "italic")
88
else if (name == "underline")
89
style_underline = true;
90
else if (name == "strikethrough")
91
style_strikethrough = true;
75
94
public void remove_style (string name) {
77
96
get_selection_range ().remove_style (name);
100
else if (name == "italic")
101
style_italic = false;
102
else if (name == "underline")
103
style_underline = false;
104
else if (name == "strikethrough")
105
style_strikethrough = false;
80
108
public void toggle_style (string name) {
81
109
if (has_selection)
82
110
get_selection_range ().toggle_style (name);
113
style_bold = !style_bold;
114
else if (name == "italic")
115
style_italic = !style_italic;
116
else if (name == "underline")
117
style_underline = !style_underline;
118
else if (name == "strikethrough")
119
style_strikethrough = !style_strikethrough;
85
122
public bool has_style (string name) {
86
123
if (has_selection)
87
124
return get_selection_range ().has_style (name);
89
126
return iter_has_style (get_cursor (), name);
93
130
public Gtk.Justification get_justification () {
94
131
if (has_selection)
95
132
return get_selection_range ().get_justification ();
97
134
return get_justification_at_iter (get_cursor ());
100
137
public Gtk.Justification get_justification_at_iter (TextIter iter) {
101
138
if (iter_has_style (iter, "align-center"))
102
139
return Gtk.Justification.CENTER;
129
166
public void set_justification (string align) {
130
167
get_paragraph (get_cursor ()).set_justification (align);
134
171
public void set_font (FontDescription font) {
135
172
get_selection_range ().set_font (font);
138
175
public void set_font_from_string (string font) {
139
176
get_selection_range ().set_font_from_string (font);
143
180
public void set_font_color (Gdk.Color color) {
144
181
get_selection_range ().set_font_color (color);
147
184
public void set_font_color_from_string (string color) {
148
185
get_selection_range ().set_font_color_from_string (color);
157
194
public void insert_comment () {
158
195
print ("Insert Comment\n");
161
198
public void insert_image () {
162
199
print ("Insert Image\n");
165
202
public void insert_link () {
166
203
print ("Insert Link\n");
169
206
public void insert_table (int cols, int rows) {
170
207
print ("Insert Table of %d columns by %d rows\n", cols, rows);
174
211
public void insert_line () {
175
212
TextIter insert_cursor = get_cursor ();
176
213
insert_line_at_iter (insert_cursor);
179
216
public void insert_paragraph () {
180
217
TextIter cursor = get_cursor ();
181
218
insert_paragraph_at_iter (cursor);
184
221
public void insert_line_at_iter (TextIter iter) {
186
223
// Cursor does not move to next line
187
224
// Only happens when inserting at the end of the buffer
188
225
// Bug reported in GTK+
190
227
insert (ref iter, "\u2028", -1);
193
230
public void insert_paragraph_at_iter (TextIter iter) {
194
231
insert (ref iter, "\n", -1);
204
241
// Moves iter to the start of the paragraph it is located in
205
242
public TextIter get_paragraph_start (TextIter iter) {
206
243
iter.backward_find_char ((char) => {
226
263
public TextRange get_paragraph (TextIter iter) {
227
264
TextIter start = get_paragraph_start (iter);
228
265
TextIter end = get_paragraph_end (iter);
230
267
return new TextRange (this, start, end);
240
277
public void search (string text) {
241
278
if (text.length > 0)
242
279
search_string (text);
247
284
public void search_string (string text) {
248
285
print ("Searching for: %s\n", text);
251
288
public void clear_search () {
252
289
print ("Clearing search");
261
298
public TextIter get_cursor () {
263
300
get_iter_at_mark (out iter, get_insert ());
267
304
public TextRange get_cursor_as_range () {
268
305
var cursor = get_cursor ();
269
306
return new TextRange (this, cursor, cursor);
272
309
public TextRange get_selection_range () {
273
310
TextIter start; TextIter end;
274
311
get_selection_bounds (out start, out end);
275
312
return new TextRange (this, start, end);
278
315
public bool iter_has_tag (TextIter iter, TextTag tag) {
279
316
return iter.has_tag (tag) || iter.begins_tag (tag) || iter.ends_tag (tag);
282
319
public bool iter_has_style (TextIter iter, string name) {
283
320
var tag = tag_table.lookup (name);
284
321
return iter_has_tag (iter, tag);
287
324
public TextIter copy_iter (TextIter iter) {
289
326
get_iter_at_offset (out copy, iter.get_offset ());
332
private void update_styles () {
333
var iter = get_cursor();
335
style_bold = iter_has_style (iter, "bold");
336
style_italic = iter_has_style (iter, "italic");
337
style_underline = iter_has_style (iter, "underline");
338
style_strikethrough = iter_has_style (iter, "strikethrough");
298
342
* Signal callbacks
301
345
private void cursor_moved_callback () {
302
346
// Emit 'cursor_moved' signal
306
351
private void text_inserted_callback (TextIter cursor, string new_text, int length) {
307
352
TextIter previous;
308
353
get_iter_at_offset (out previous, cursor.get_offset () - length);
310
if (iter_has_style (previous, "bold"))
311
356
apply_tag_by_name ("bold", previous, cursor);
312
if (iter_has_style (previous, "italic"))
313
358
apply_tag_by_name ("italic", previous, cursor);
314
if (iter_has_style (previous, "underline"))
315
360
apply_tag_by_name ("underline", previous, cursor);
316
if (iter_has_style (previous, "strikethrough"))
361
if (style_strikethrough)
317
362
apply_tag_by_name ("strikethrough", previous, cursor);
321
366
text_inserted ();
325
370
private bool key_press_callback (EventKey event) {
326
371
if (Gdk.keyval_name (event.keyval) == "Return") {
327
372
ModifierType modifiers = Gtk.accelerator_get_default_mod_mask ();
329
374
if ((event.state & modifiers) == Gdk.ModifierType.SHIFT_MASK)
332
377
insert_paragraph ();
386
private bool editor_clicked_callback (EventButton event) {
b'\\ No newline at end of file'