4
Copyright (c) 2014 Tuur Dutoit
6
Permission is hereby granted, free of charge, to any person obtaining a copy
7
of this software and associated documentation files (the "Software"), to deal
8
in the Software without restriction, including without limitation the rights
9
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
copies of the Software, and to permit persons to whom the Software is
11
furnished to do so, subject to the following conditions:
13
The above copyright notice and this permission notice shall be included in all
14
copies or substantial portions of the Software.
16
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32
public class TextEditor : TextBuffer {
34
public TextView text_view;
36
public signal void cursor_moved ();
37
public signal void text_inserted ();
39
public TextEditor () {
40
setup_tagtable (this);
41
text_view = new TextView.with_buffer (this);
43
this.notify["cursor-position"].connect (cursor_moved_callback);
44
this.insert_text.connect_after (text_inserted_callback);
46
text_view.key_press_event.connect (key_press_callback);
47
text_view.pixels_below_lines = 20;
50
// Get a TextTagTable with all the default tags
51
private void setup_tagtable (TextBuffer buffer) {
53
buffer.create_tag ("bold", "weight", 700);
54
buffer.create_tag ("italic", "style", Pango.Style.ITALIC);
55
buffer.create_tag ("underline", "underline", Pango.Underline.SINGLE);
56
buffer.create_tag ("strikethrough", "strikethrough", true);
58
buffer.create_tag ("align-left", "justification", Gtk.Justification.LEFT);
59
buffer.create_tag ("align-center", "justification", Gtk.Justification.CENTER);
60
buffer.create_tag ("align-right", "justification", Gtk.Justification.RIGHT);
61
buffer.create_tag ("align-fill", "justification", Gtk.Justification.FILL);
67
* Styles (apply, remove, check)
70
public void apply_style (string name) {
72
get_selection_range ().apply_style (name);
75
public void remove_style (string name) {
77
get_selection_range ().remove_style (name);
80
public void toggle_style (string name) {
82
get_selection_range ().toggle_style (name);
85
public bool has_style (string name) {
87
return get_selection_range ().has_style (name);
89
return iter_has_style (get_cursor (), name);
93
public Gtk.Justification get_justification () {
95
return get_selection_range ().get_justification ();
97
return get_justification_at_iter (get_cursor ());
100
public Gtk.Justification get_justification_at_iter (TextIter iter) {
101
if (iter_has_style (iter, "align-center"))
102
return Gtk.Justification.CENTER;
103
else if (iter_has_style (iter, "align-right"))
104
return Gtk.Justification.RIGHT;
105
else if (iter_has_style (iter, "align-fill"))
106
return Gtk.Justification.FILL;
108
return Gtk.Justification.LEFT;
111
public int get_justification_as_int () {
113
return get_selection_range ().get_justification_as_int ();
115
return get_justification_as_int_at_iter (get_cursor ());
118
public int get_justification_as_int_at_iter (TextIter iter) {
119
if (iter_has_style (iter, "align-center"))
121
else if (iter_has_style (iter, "align-right"))
123
else if (iter_has_style (iter, "align-fill"))
129
public void set_justification (string align) {
130
get_paragraph (get_cursor ()).set_justification (align);
134
public void set_font (FontDescription font) {
135
get_selection_range ().set_font (font);
138
public void set_font_from_string (string font) {
139
get_selection_range ().set_font_from_string (font);
143
public void set_font_color (Gdk.Color color) {
144
get_selection_range ().set_font_color (color);
147
public void set_font_color_from_string (string color) {
148
get_selection_range ().set_font_color_from_string (color);
157
public void insert_comment () {
158
print ("Insert Comment\n");
161
public void insert_image () {
162
print ("Insert Image\n");
165
public void insert_link () {
166
print ("Insert Link\n");
169
public void insert_table (int cols, int rows) {
170
print ("Insert Table of %d columns by %d rows\n", cols, rows);
174
public void insert_line () {
175
TextIter insert_cursor = get_cursor ();
176
insert_line_at_iter (insert_cursor);
179
public void insert_paragraph () {
180
TextIter cursor = get_cursor ();
181
insert_paragraph_at_iter (cursor);
184
public void insert_line_at_iter (TextIter iter) {
186
// Cursor does not move to next line
187
// Only happens when inserting at the end of the buffer
188
// Bug reported in GTK+
190
insert (ref iter, "\u2028", -1);
193
public void insert_paragraph_at_iter (TextIter iter) {
194
insert (ref iter, "\n", -1);
204
// Moves iter to the start of the paragraph it is located in
205
public TextIter get_paragraph_start (TextIter iter) {
206
iter.backward_find_char ((char) => {
207
if (char.to_string () == "\n")
215
// Moves iter to the end of the paragraph it is located in
216
public TextIter get_paragraph_end (TextIter iter) {
217
iter.forward_find_char ((char) => {
218
if (char.to_string () == "\n")
226
public TextRange get_paragraph (TextIter iter) {
227
TextIter start = get_paragraph_start (iter);
228
TextIter end = get_paragraph_end (iter);
230
return new TextRange (this, start, end);
240
public void search (string text) {
242
search_string (text);
247
public void search_string (string text) {
248
print ("Searching for: %s\n", text);
251
public void clear_search () {
252
print ("Clearing search");
261
public TextIter get_cursor () {
263
get_iter_at_mark (out iter, get_insert ());
267
public TextRange get_cursor_as_range () {
268
var cursor = get_cursor ();
269
return new TextRange (this, cursor, cursor);
272
public TextRange get_selection_range () {
273
TextIter start; TextIter end;
274
get_selection_bounds (out start, out end);
275
return new TextRange (this, start, end);
278
public bool iter_has_tag (TextIter iter, TextTag tag) {
279
return iter.has_tag (tag) || iter.begins_tag (tag) || iter.ends_tag (tag);
282
public bool iter_has_style (TextIter iter, string name) {
283
var tag = tag_table.lookup (name);
284
return iter_has_tag (iter, tag);
287
public TextIter copy_iter (TextIter iter) {
289
get_iter_at_offset (out copy, iter.get_offset ());
301
private void cursor_moved_callback () {
302
// Emit 'cursor_moved' signal
306
private void text_inserted_callback (TextIter cursor, string new_text, int length) {
308
get_iter_at_offset (out previous, cursor.get_offset () - length);
310
if (iter_has_style (previous, "bold"))
311
apply_tag_by_name ("bold", previous, cursor);
312
if (iter_has_style (previous, "italic"))
313
apply_tag_by_name ("italic", previous, cursor);
314
if (iter_has_style (previous, "underline"))
315
apply_tag_by_name ("underline", previous, cursor);
316
if (iter_has_style (previous, "strikethrough"))
317
apply_tag_by_name ("strikethrough", previous, cursor);
325
private bool key_press_callback (EventKey event) {
326
if (Gdk.keyval_name (event.keyval) == "Return") {
327
ModifierType modifiers = Gtk.accelerator_get_default_mod_mask ();
329
if ((event.state & modifiers) == Gdk.ModifierType.SHIFT_MASK)
b'\\ No newline at end of file'