Fix #8049 - language server hover and editor hover (not supported for gtkview / rooview)
[roobuilder] / src / Builder4 / Editor.bjs
1 {
2  "build_module" : "builder",
3  "gen_extended" : false,
4  "items" : [
5   {
6    "# GtkSource.SearchContext searchcontext" : "null",
7    "# JsRender.JsRender? file" : "null",
8    "# JsRender.Node node" : "null",
9    "# JsRender.NodeProp? prop" : "null",
10    "# Xcls_MainWindow window" : "null",
11    "# bool dirty" : false,
12    "# bool pos" : false,
13    "# int last_error_counter" : 0,
14    "# int pos_root_x" : "",
15    "# int pos_root_y" : "",
16    "# string activeEditor" : "\"\"",
17    "$ homogeneous" : false,
18    "$ xns" : "Gtk",
19    "@ void save" : "()",
20    "Gtk.Orientation orientation" : "Gtk.Orientation.VERTICAL",
21    "bool hexpand" : true,
22    "bool vexpand" : true,
23    "int last_search_end" : 0,
24    "items" : [
25     {
26      "$ homogeneous" : false,
27      "$ xns" : "Gtk",
28      "Gtk.Orientation orientation" : "Gtk.Orientation.HORIZONTAL",
29      "bool hexpand" : true,
30      "items" : [
31       {
32        "$ xns" : "Gtk",
33        "id" : "save_button",
34        "label" : "Save",
35        "listeners" : {
36         "clicked" : [
37          " () => { ",
38          "    _this.saveContents();",
39          "}",
40          "  "
41         ]
42        },
43        "xtype" : "Button"
44       },
45       {
46        "$ xns" : "Gtk",
47        "bool hexpand" : true,
48        "xtype" : "Label"
49       },
50       {
51        "$ xns" : "Gtk",
52        "* ctor" : "new Gtk.Scale.with_range (Gtk.Orientation.HORIZONTAL,6, 30, 1)",
53        "* init" : [
54         "{",
55         "\t//this.el.set_range(6,30);",
56         " \tthis.el.set_value ( BuilderApplication.settings.editor_font_size);",
57         " \tBuilderApplication.settings.editor_font_size_updated.connect(",
58         " \t\t() => {",
59         " \t\t\tBuilderApplication.settings.editor_font_size_inchange = true;",
60         " \t\t//\tGLib.debug(\"update range\");",
61         " \t\t \tthis.el.set_value (BuilderApplication.settings.editor_font_size);",
62         " \t\t \tBuilderApplication.settings.editor_font_size_inchange = false;",
63         " \t\t}",
64         "\t);",
65         "\t",
66         " ",
67         "}",
68         ""
69        ],
70        "bool draw_value" : false,
71        "bool has_origin" : true,
72        "bool sensitive" : true,
73        "int digits" : 0,
74        "int width_request" : 200,
75        "listeners" : {
76         "change_value" : [
77          "(st, val ) => {",
78          "\tif (BuilderApplication.settings.editor_font_size_inchange) {",
79          "\t\treturn false;",
80          "\t}",
81          "  \tBuilderApplication.settings.editor_font_size = val;",
82          " \treturn false;",
83          "}"
84         ]
85        },
86        "xtype" : "Scale"
87       },
88       {
89        "$ xns" : "Gtk",
90        "id" : "close_btn",
91        "items" : [
92         {
93          "$ xns" : "Gtk",
94          "* prop" : "child",
95          "Gtk.IconSize icon_size" : "Gtk.IconSize.NORMAL",
96          "string icon_name" : "window-close",
97          "xtype" : "Image"
98         }
99        ],
100        "listeners" : {
101         "clicked" : [
102          " () => { ",
103          "    _this.saveContents();",
104          "    _this.window.windowstate.switchState(WindowState.State.PREVIEW);",
105          "}",
106          "  "
107         ]
108        },
109        "string icon_name" : "window-close",
110        "xtype" : "Button"
111       }
112      ],
113      "xtype" : "Box"
114     },
115     {
116      "$ xns" : "Gtk",
117      "Gtk.PolicyType hscrollbar_policy" : "Gtk.PolicyType.AUTOMATIC",
118      "Gtk.PolicyType vscrollbar_policy" : "Gtk.PolicyType.AUTOMATIC",
119      "bool overlay_scrolling" : false,
120      "bool vexpand" : true,
121      "id" : "RightEditor",
122      "items" : [
123       {
124        "# Gtk.CssProvider css" : "null",
125        "$ gboolean auto_indent" : true,
126        "$ xns" : "GtkSource",
127        "* init" : [
128         "",
129         " ",
130         "\t",
131         " ",
132         " ",
133         "this.el.completion.add_provider(",
134         "\tnew Palete.CompletionProvider(_this)",
135         ");",
136         " ",
137         "var hover = this.el.get_hover();",
138         "hover.add_provider(new Palete.HoverProvider(_this));",
139         "",
140         "//this.el.completion.unblock_interactive();",
141         "this.el.completion.select_on_show = true; // select",
142         "//this.el.completion.remember_info_visibility\t = true;",
143         "",
144         "",
145         "var attrs = new GtkSource.MarkAttributes();",
146         "",
147         "attrs.set_icon_name ( \"process-stop\");    ",
148         "attrs.query_tooltip_text.connect(( mark) => {",
149         "     GLib.debug(\"tooltip query? %s\", mark.name);",
150         "    return strdup( mark.name);",
151         "});",
152         " attrs.query_tooltip_markup.connect(( mark) => {",
153         "     GLib.debug(\"tooltip query? %s\", mark.name);",
154         "    return strdup( mark.name);",
155         "});",
156         "this.el.set_mark_attributes (\"ERR\", attrs, 1);",
157         "attrs.ref();",
158         "",
159         "",
160         "var wattrs = new GtkSource.MarkAttributes();",
161         "wattrs.set_icon_name ( \"process-stop\");    ",
162         "wattrs.query_tooltip_text.connect(( mark) => {",
163         "     GLib.debug(\"tooltip query? %s\", mark.name);",
164         "    return strdup(mark.name);",
165         "});",
166         "wattrs.query_tooltip_markup.connect(( mark) => {",
167         "     GLib.debug(\"tooltip query? %s\", mark.name);",
168         "    return strdup(mark.name);",
169         "});",
170         "this.el.set_mark_attributes (\"WARN\", wattrs, 1);",
171         "wattrs.ref();",
172         "",
173         " ",
174         "var dattrs = new GtkSource.MarkAttributes();",
175         " ",
176         "dattrs.set_icon_name ( \"process-stop\"); ",
177         "",
178         "dattrs.query_tooltip_text.connect(( mark) => {",
179         "\tGLib.debug(\"tooltip query? %s\", mark.name);",
180         "    return strdup(mark.name);",
181         "});",
182         "//dattrs.query_tooltip_markup.connect(( mark) => {",
183         "//\tGLib.debug(\"tooltip query? %s\", mark.name);",
184         " //   return strdup(mark.name);",
185         "//});",
186         "this.el.set_mark_attributes (\"DEPR\", dattrs, 1);",
187         "dattrs.ref();    ",
188         "",
189         " this.el.get_space_drawer().set_matrix(null);",
190         " this.el.get_space_drawer().set_types_for_locations( ",
191         "\tGtkSource.SpaceLocationFlags.ALL,",
192         "\tGtkSource.SpaceTypeFlags.ALL",
193         ");",
194         "this.el.get_space_drawer().set_enable_matrix(true);",
195         ""
196        ],
197        "* prop" : "child",
198        "bool has_tooltip" : true,
199        "bool hexpand" : true,
200        "bool insert_spaces_instead_of_tabs" : true,
201        "bool vexpand" : true,
202        "boolean show_line_marks" : true,
203        "boolean show_line_numbers" : true,
204        "css_classes" : "{ \"code-editor\" }",
205        "gboolean highlight_current_line" : true,
206        "id" : "view",
207        "indent_width" : 4,
208        "items" : [
209         {
210          "$ Gee.HashMap<int,string>? xmarks" : "null",
211          "$ xns" : "GtkSource",
212          "$ xtype" : "Buffer",
213          "* init" : [
214           "",
215           "var buf = this.el;",
216           "buf.create_tag (\"bold\", \"weight\", Pango.Weight.BOLD);",
217           "buf.create_tag (\"type\", \"weight\", Pango.Weight.BOLD, \"foreground\", \"#204a87\");",
218           "buf.create_tag (\"keyword\", \"weight\", Pango.Weight.BOLD, \"foreground\", \"#a40000\");",
219           "buf.create_tag (\"text\", \"weight\", Pango.Weight.NORMAL, \"foreground\", \"#729fcf\");",
220           "buf.create_tag (\"number\", \"weight\", Pango.Weight.BOLD, \"foreground\", \"#ad7fa8\");",
221           "buf.create_tag (\"method\", \"weight\", Pango.Weight.BOLD, \"foreground\", \"#729fcf\");",
222           "buf.create_tag (\"property\", \"weight\", Pango.Weight.BOLD, \"foreground\", \"#BC1F51\");",
223           "buf.create_tag (\"variable\", \"weight\", Pango.Weight.BOLD, \"foreground\", \"#A518B5\");",
224           "",
225           "",
226           "buf.create_tag (\"ERR\", \"weight\", Pango.Weight.BOLD, \"background\", \"pink\");",
227           "buf.create_tag (\"WARN\", \"weight\", Pango.Weight.BOLD, \"background\", \"#ABF4EB\");",
228           "buf.create_tag (\"DEPR\", \"weight\", Pango.Weight.BOLD, \"background\", \"#EEA9FF\");",
229           "",
230           "",
231           ""
232          ],
233          "* prop" : "buffer",
234          "bool check_queued" : false,
235          "bool enable_undo" : true,
236          "bool highlight_matching_brackets" : true,
237          "bool highlight_syntax" : true,
238          "id" : "buffer",
239          "int error_line" : "-1",
240          "listeners" : {
241           "changed" : [
242            " () => {",
243            "    // check syntax??",
244            "    // ??needed..??",
245            "    _this.save_button.el.sensitive = true;",
246            "    print(\"EDITOR CHANGED\");",
247            "    this.checkSyntax();",
248            "   ",
249            "    _this.dirty = true;",
250            "",
251            "    // this.get('/LeftPanel.model').changed(  str , false);",
252            "    return ;",
253            "}",
254            ""
255           ]
256          },
257          "| bool OLDhighlightErrorsJson" : [
258           "(string type, Json.Object obj) {",
259           "\tGtk.TextIter start;",
260           "\tGtk.TextIter end;     ",
261           "\tthis.el.get_bounds (out start, out end);",
262           "",
263           "\tthis.el.remove_source_marks (start, end, type);",
264           "\tGLib.debug(\"highlight errors\");\t\t ",
265           "",
266           "\t // we should highlight other types of errors..",
267           "",
268           "\tif (!obj.has_member(type)) {",
269           "\t\tGLib.debug(\"Return has no errors\\n\");",
270           "\t\treturn true;",
271           "\t}",
272           "",
273           "\tif (_this.window.windowstate.state != WindowState.State.CODEONLY ",
274           "\t\t&&",
275           "\t\t_this.window.windowstate.state != WindowState.State.CODE",
276           "\t\t) {",
277           "\t\tGLib.debug(\"windowstate != CODEONLY?\");",
278           "\t\t",
279           "\t\treturn true;",
280           "\t} ",
281           "",
282           "\t//this.marks = new Gee.HashMap<int,string>();",
283           "\tvar err = obj.get_object_member(type);",
284           " ",
285           "\tif (_this.file == null) {",
286           "\t\tGLib.debug(\"file is null?\");",
287           "\t\treturn true;",
288           "",
289           "\t}",
290           "\tvar valafn = _this.file.path;",
291           "",
292           "\tif (_this.file.xtype != \"PlainFile\") {",
293           "",
294           "\t\tvalafn = \"\";",
295           "\t\ttry {             ",
296           "\t\t\tvar  regex = new Regex(\"\\\\.bjs$\");",
297           "\t\t\t// should not happen",
298           "\t      \t\tvalafn = regex.replace(_this.file.path,_this.file.path.length , 0 , \".vala\");",
299           "\t\t} catch (GLib.RegexError e) {",
300           "\t\t\treturn true;",
301           "\t\t}   ",
302           "",
303           "",
304           "",
305           "\t}",
306           "\tif (!err.has_member(valafn)) {",
307           "\t\tGLib.debug(\"File path has no errors\");",
308           "\t\treturn  true;",
309           "\t}",
310           "",
311           "\tvar lines = err.get_object_member(valafn);",
312           "\t",
313           "\tvar offset = 1;",
314           "\tif (obj.has_member(\"line_offset\")) { // ?? why??",
315           "\t\toffset = (int)obj.get_int_member(\"line_offset\") + 1;",
316           "\t}",
317           "",
318           "",
319           "\tvar tlines = this.el.get_line_count () +1;",
320           "\t",
321           "\tif (_this.prop != null) {",
322           "\t",
323           "\t\ttlines = _this.prop.end_line + 1;",
324           "\t\toffset = _this.prop.start_line + 1;",
325           "\t",
326           "\t}",
327           "\t",
328           "",
329           "",
330           "\tlines.foreach_member((obj, line, node) => {",
331           "\t\t",
332           "\t     Gtk.TextIter iter;",
333           "//        print(\"get inter\\n\");",
334           "\t    var eline = int.parse(line) - offset;",
335           "\t    GLib.debug(\"GOT ERROR on line %s -- converted to %d  (offset = %d)\\n\", line,eline, offset);",
336           "\t    ",
337           "\t    ",
338           "\t    if (eline > tlines || eline < 0) {",
339           "\t        return;",
340           "\t    }",
341           "\t   ",
342           "\t    ",
343           "\t    this.el.get_iter_at_line( out iter, eline);",
344           "\t    //print(\"mark line\\n\");",
345           "\t    var msg  = \"\";",
346           "\t    var ar = lines.get_array_member(line);",
347           "\t    for (var i = 0 ; i < ar.get_length(); i++) {",
348           "\t    \tif (ar.get_string_element(i) == \"Success\") {",
349           "\t    \t\tcontinue;",
350           "    \t\t}",
351           "\t\t\tmsg += (msg.length > 0) ? \"\\n\" : \"\";",
352           "\t\t\tmsg += ar.get_string_element(i);",
353           "\t\t}",
354           "\t\tif (msg == \"\") {",
355           "\t\t\treturn;",
356           "\t\t}",
357           "\t\tmsg = \"Line: %d\".printf(eline+1) +  \" \" + msg;",
358           "\t    this.el.create_source_mark(msg, type, iter);",
359           "\t    GLib.debug(\"set line %d to %m\", eline, msg);",
360           "\t   // this.marks.set(eline, msg);",
361           "\t} );",
362           "\treturn false;",
363           "",
364           "",
365           "",
366           "",
367           "",
368           "\t}",
369           ""
370          ],
371          "| bool checkSyntax" : [
372           " () {",
373           " ",
374           "    ",
375           "    var str = this.toString();",
376           "    ",
377           "    // needed???",
378           "    if (this.error_line > 0) {",
379           "         Gtk.TextIter start;",
380           "         Gtk.TextIter end;     ",
381           "        this.el.get_bounds (out start, out end);",
382           "",
383           "        this.el.remove_source_marks (start, end, null);",
384           "    }",
385           "    if (str.length < 1) {",
386           "        print(\"checkSyntax - empty string?\\n\");",
387           "        return true;",
388           "    }",
389           "    ",
390           "    // bit presumptiona",
391           "    if (_this.file.xtype == \"PlainFile\") {",
392           "    ",
393           "        // assume it's gtk...",
394           "         var  oldcode =_this.file.toSource();",
395           "        _this.file.setSource(str);",
396           "\t    BuilderApplication.showSpinner(\"appointment soon\",\"document change pending\");",
397           "    \t_this.file.getLanguageServer().document_change(_this.file);",
398           "",
399           "        _this.file.setSource(oldcode);",
400           "        ",
401           "\t\t ",
402           "        return true;",
403           "    ",
404           "    }",
405           "   if (_this.file == null) {",
406           "       return true;",
407           "   }",
408           " ",
409           "    ",
410           "",
411           "      ",
412           "     ",
413           "    GLib.debug(\"calling validate\");    ",
414           "    // clear the buttons.",
415           " \tif (_this.prop.name == \"xns\" || _this.prop.name == \"xtype\") {",
416           "\t\treturn true ;",
417           "\t}",
418           "\tvar oldcode  = _this.prop.val;",
419           "\t",
420           "\t_this.prop.val = str;",
421           "\t_this.node.updated_count++;",
422           "    _this.file.getLanguageServer().document_change(_this.file);",
423           "    _this.node.updated_count++;",
424           "    _this.prop.val = oldcode;",
425           "    ",
426           "    ",
427           "    //print(\"done mark line\\n\");",
428           "     ",
429           "    return true; // at present allow saving - even if it's invalid..",
430           "}",
431           ""
432          ],
433          "| bool highlightErrors" : [
434           "( Gee.HashMap<int,string> validate_res) {",
435           "         ",
436           "\tthis.error_line = validate_res.size;",
437           "",
438           "\tif (this.error_line < 1) {",
439           "\t\treturn true;",
440           "\t}",
441           "\tvar tlines = this.el.get_line_count ();",
442           "\tGtk.TextIter iter;",
443           "\tvar valiter = validate_res.map_iterator();",
444           "\twhile (valiter.next()) {",
445           "",
446           "\t//        print(\"get inter\\n\");",
447           "\t\tvar eline = valiter.get_key();",
448           "\t\tif (eline > tlines) {",
449           "\t\t\tcontinue;",
450           "\t\t}",
451           "\t\tthis.el.get_iter_at_line( out iter, eline);",
452           "\t\t//print(\"mark line\\n\");",
453           "\t\tthis.el.create_source_mark(valiter.get_value(), \"ERR\", iter);",
454           "\t}   ",
455           "\treturn false;",
456           "}"
457          ],
458          "| string toString" : [
459           "  () {",
460           "    ",
461           "    Gtk.TextIter s;",
462           "    Gtk.TextIter e;",
463           "    this.el.get_start_iter(out s);",
464           "    this.el.get_end_iter(out e);",
465           "    var ret = this.el.get_text(s,e,true);",
466           "    //print(\"TO STRING? \" + ret);",
467           "    return ret;",
468           "}",
469           " "
470          ]
471         },
472         {
473          "# bool is_control" : false,
474          "$ xns" : "Gtk",
475          "id" : "keystate",
476          "listeners" : {
477           "key_pressed" : [
478            "(keyval, keycode, state) => {",
479            "",
480            " \tif (keyval == Gdk.Key.Control_L || keyval == Gdk.Key.Control_R) {",
481            " \t\tthis.is_control = true;",
482            "\t}",
483            "\treturn false;",
484            "}",
485            ""
486           ],
487           "key_released" : [
488            "(keyval, keycode, state) => {",
489            "",
490            " \t if (keyval == Gdk.Key.Control_L || keyval == Gdk.Key.Control_R) {",
491            " \t\tthis.is_control = false;",
492            "\t}",
493            "    if (keyval == Gdk.Key.s && (state & Gdk.ModifierType.CONTROL_MASK ) > 0 ) {",
494            "        GLib.debug(\"SAVE: ctrl-S  pressed\");",
495            "        _this.saveContents();",
496            "        return;",
497            "    }",
498            "    ",
499            "    if (keyval == Gdk.Key.g && (state & Gdk.ModifierType.CONTROL_MASK ) > 0 ) {",
500            "\t    GLib.debug(\"SAVE: ctrl-g  pressed\");",
501            "\t\t_this.forwardSearch(true);",
502            "\t    return;",
503            "\t}",
504            "\tif (keyval == Gdk.Key.f && (state & Gdk.ModifierType.CONTROL_MASK ) > 0 ) {",
505            "\t    GLib.debug(\"SAVE: ctrl-f  pressed\");",
506            "\t\t_this.search_entry.el.grab_focus();",
507            "\t\t_this.search_entry.el.select_region(0,-1);",
508            "\t    return;",
509            "\t}",
510            "\tif (keyval == Gdk.Key.space && (state & Gdk.ModifierType.CONTROL_MASK ) > 0 ) {",
511            "\t\t_this.view.el.show_completion();",
512            "\t}",
513            "\t",
514            "\tGtk.TextIter iter;",
515            "\t_this.buffer.el.get_iter_at_offset( out iter, _this.buffer.el.cursor_position);  ",
516            "\tvar line  = iter.get_line();",
517            "\tvar offset = iter.get_line_offset();",
518            "\tGLib.debug(\"line  %d  off %d\", line ,offset);",
519            "\tif (_this.prop != null) {",
520            "\t\tline += _this.prop.start_line + 1; // i think..",
521            "\t\toffset += 12; // should probably be 8 without namespaced ",
522            "\t\tGLib.debug(\"guess line  %d  off %d\", line ,offset);",
523            "\t} ",
524            "    //_this.view.el.show_completion();",
525            "   // print(event.key.keyval)",
526            "   ",
527            "   ",
528            "   ",
529            "    ",
530            "    return;",
531            " ",
532            " ",
533            "}",
534            ""
535           ]
536          },
537          "xtype" : "EventControllerKey"
538         },
539         {
540          "# double distance" : "0.0f",
541          "$ xns" : "Gtk",
542          "Gtk.EventControllerScrollFlags flags" : "Gtk.EventControllerScrollFlags.VERTICAL",
543          "listeners" : {
544           "scroll" : [
545            "(dx, dy) => {",
546            "\tif (!_this.keystate.is_control) {",
547            "\t\treturn false;",
548            "\t}",
549            "\t //GLib.debug(\"scroll %f\",  dy);",
550            "\t",
551            "\tthis.distance += dy;",
552            "\t",
553            "\t//GLib.debug(\"scroll %f / %f\",  dy, this.distance);",
554            " ",
555            "\t if (this.distance < -1) {",
556            " ",
557            "\t\tBuilderApplication.settings.editor_font_size ++;",
558            "\t\tthis.distance = 0;",
559            "\t}",
560            "\tif (this.distance > 1) {",
561            "\t\tBuilderApplication.settings.editor_font_size --;",
562            "\t\tthis.distance = 0;",
563            "\t}",
564            "\t ",
565            "\treturn true;",
566            "}",
567            ""
568           ]
569          },
570          "xtype" : "EventControllerScroll"
571         }
572        ],
573        "listeners" : {
574         "query_tooltip" : [
575          "(x, y, keyboard_tooltip, tooltip) => {",
576          "\t",
577          "\t//GLib.debug(\"query tooltip\");",
578          "\tGtk.TextIter iter;",
579          "\tint trailing;",
580          "\t",
581          "\tvar yoff = (int) _this.RightEditor.el.vadjustment.value;",
582          "\t",
583          "\t// I think this is problematic - if it's compliing  / updating at same time as query.",
584          "\t",
585          "\t//if (_this.window.statusbar_compile_spinner.el.spinning) {",
586          "\t//\treturn false;",
587          "\t//}",
588          "\t",
589          "\tthis.el.get_iter_at_position (out iter, out trailing,  x,  y + yoff);",
590          "\t ",
591          "\tvar l = iter.get_line();",
592          "",
593          "\t",
594          "\t ",
595          "\t// GLib.debug(\"query tooltip line %d\", (int) l);",
596          "\tif (l < 0) {",
597          "",
598          "\t\treturn false;",
599          "\t}",
600          "\t/*",
601          "\tif (_this.buffer.marks != null && _this.buffer.marks.has_key(l)) {",
602          "\t\tGLib.debug(\"line %d setting tip to %s\", l,  _this.buffer.marks.get(l));",
603          "\t\ttooltip.set_text(_this.buffer.marks.get(l).dup());",
604          "\t\treturn true;",
605          "\t}",
606          " ",
607          "\treturn false;",
608          "\t*/",
609          "\t",
610          "\t  ",
611          "\t// this crashes?? - not sure why.",
612          "\tvar marks = _this.buffer.el.get_source_marks_at_line(l, \"ERR\");",
613          "\tif (marks.is_empty()) {",
614          "\t\tmarks = _this.buffer.el.get_source_marks_at_line(l, \"WARN\");",
615          "\t}",
616          "\tif (marks.is_empty()) {",
617          "\t\tmarks = _this.buffer.el.get_source_marks_at_line(l, \"DEPR\");",
618          "\t}",
619          "\t",
620          "\t// GLib.debug(\"query tooltip line %d marks %d\", (int)l, (int) marks.length());",
621          "\tvar str = \"\";",
622          "\tmarks.@foreach((m) => { ",
623          "\t\t//GLib.debug(\"got mark %s\", m.name);",
624          "\t\tstr += (str.length > 0 ? \"\\n\" : \"\") + m.category + \": \" + m.name;",
625          "\t});",
626          "\t// true if there is a mark..",
627          "\tif (str.length > 0 ) {",
628          "\t\ttooltip.set_text( str );",
629          "\t}",
630          "\treturn str.length > 0 ? true : false;",
631          "\t ",
632          "}",
633          ""
634         ]
635        },
636        "string name" : "editor-view",
637        "uint tab_width" : 4,
638        "xtype" : "View",
639        "| void load" : [
640         " (string str) {",
641         "",
642         "// show the help page for the active node..",
643         "   //this.get('/Help').show();",
644         " ",
645         "  // this.get('/BottomPane').el.set_current_page(0);",
646         "  \tGLib.debug(\"load called - Reset undo buffer\");",
647         "  \t",
648         "    var buf = (GtkSource.Buffer)this.el.get_buffer();",
649         "    buf.begin_irreversible_action();",
650         "    buf.set_text(str, str.length);",
651         "    buf.end_irreversible_action();",
652         "    ",
653         "    var lm = GtkSource.LanguageManager.get_default();",
654         "    var lang = \"vala\";",
655         "    if (_this.file != null) {",
656         "         lang = _this.file.language;",
657         "    }",
658         "    print(\"lang=%s, content_type = %s\\n\", lang, _this.file.content_type);",
659         "    var lg = _this.file.content_type.length > 0  ?",
660         "            lm.guess_language(_this.file.path, _this.file.content_type) :",
661         "            lm.get_language(lang);",
662         "     ",
663         "   ",
664         "    ((GtkSource.Buffer)(this.el.get_buffer())) .set_language(lg); ",
665         "",
666         "    this.el.insert_spaces_instead_of_tabs = true;",
667         "    if (lg != null) {",
668         "\t\tprint(\"sourcelanguage  = %s\\n\", lg.name);",
669         "\t\tif (lg.name == \"Vala\") {",
670         "\t\t    this.el.insert_spaces_instead_of_tabs = false;",
671         "\t\t}",
672         "     }",
673         "    _this.dirty = false;",
674         "    this.el.grab_focus();",
675         "    _this.save_button.el.sensitive = false;",
676         "    _this.last_error_counter = -1;",
677         "}"
678        ]
679       }
680      ],
681      "xtype" : "ScrolledWindow"
682     },
683     {
684      "$ xns" : "Gtk",
685      "* pack" : "append",
686      "Gtk.Orientation orientation" : "Gtk.Orientation.HORIZONTAL",
687      "bool homogeneous" : false,
688      "bool vexpand" : false,
689      "int spacing" : 0,
690      "items" : [
691       {
692        "$ xns" : "Gtk",
693        "Gtk.CssProvider css" : "",
694        "bool hexpand" : true,
695        "id" : "search_entry",
696        "items" : [
697         {
698          "$ xns" : "Gtk",
699          "listeners" : {
700           "key_pressed" : [
701            "(keyval, keycode, state) => {",
702            "",
703            "\tif (keyval == Gdk.Key.g && (state & Gdk.ModifierType.CONTROL_MASK ) > 0 ) {",
704            "\t    GLib.debug(\"SAVE: ctrl-g  pressed\");",
705            "\t\t_this.forwardSearch(true);",
706            "\t    return true;",
707            "\t}",
708            "    ",
709            "  ",
710            " \tif (keyval == Gdk.Key.Return && _this.search_entry.el.text.length > 0) {",
711            "\t\t_this.forwardSearch(true);",
712            "\t\t",
713            "\t\t",
714            "\t    return true;",
715            "",
716            "\t}    ",
717            "   // print(event.key.keyval)",
718            "   ",
719            "    return false;",
720            "}",
721            ""
722           ]
723          },
724          "xtype" : "EventControllerKey"
725         }
726        ],
727        "listeners" : {
728         "search_changed" : [
729          "( ) => {",
730          "",
731          "_this.search(_this.search_entry.el.text);",
732          "\t _this.search_results.updateResults();",
733          "",
734          "\tGLib.Timeout.add_seconds(1,() => {",
735          "\t\t _this.search_results.updateResults();",
736          "\t\t return false;",
737          "\t });",
738          "}",
739          ""
740         ]
741        },
742        "string name" : "editor-search-entry",
743        "string placeholder_text" : "Press enter to search",
744        "uint search_delay" : 3,
745        "xtype" : "SearchEntry",
746        "| void forwardSearch" : [
747         "(bool change_focus) {",
748         "",
749         "",
750         "\t_this.forwardSearch(change_focus);",
751         "",
752         "/*",
753         "",
754         "\tswitch(_this.windowstate.state) {",
755         "\t\tcase WindowState.State.CODEONLY:",
756         "\t\t//case WindowState.State.CODE:",
757         "\t\t\t// search the code being edited..",
758         "\t\t\t_this.windowstate.code_editor_tab.forwardSearch(change_focus);",
759         "\t\t\t ",
760         "\t\t\tbreak;",
761         "\t\tcase WindowState.State.PREVIEW:",
762         "\t\t\tif (_this.windowstate.file.xtype == \"Gtk\") {",
763         "\t\t\t\t_this.windowstate.window_gladeview.forwardSearch(change_focus);",
764         "\t\t\t} else { ",
765         "\t\t\t\t _this.windowstate.window_rooview.forwardSearch(change_focus);",
766         "\t\t\t}",
767         "\t\t",
768         "\t\t\tbreak;",
769         "\t}",
770         "\t*/",
771         "\t",
772         "}",
773         ""
774        ]
775       },
776       {
777        "$ xns" : "Gtk",
778        "id" : "search_results",
779        "int margin_end" : 4,
780        "int margin_start" : 4,
781        "string label" : "No Results",
782        "xtype" : "Label",
783        "| void updateResults" : [
784         "() {",
785         "\tthis.el.visible = true;",
786         "\t",
787         "\tvar res = _this.searchcontext.get_occurrences_count();",
788         "\tif (res < 0) {",
789         "\t\t_this.search_results.el.label = \"??? Matches\";\t\t",
790         "\t\treturn;",
791         "\t}",
792         "",
793         "\t_this.nextBtn.el.sensitive = false;",
794         "\t_this.backBtn.el.sensitive = false;\t",
795         "",
796         "\tif (res > 0) {",
797         "\t\t_this.search_results.el.label = \"%d Matches\".printf(res);",
798         "\t\t_this.nextBtn.el.sensitive = true;",
799         "\t\t_this.backBtn.el.sensitive = true;",
800         "\t\treturn;",
801         "\t} ",
802         "\t_this.search_results.el.label = \"No Matches\";",
803         "\t",
804         "}"
805        ]
806       },
807       {
808        "$ xns" : "Gtk",
809        "bool always_show_image" : true,
810        "bool sensitive" : false,
811        "id" : "nextBtn",
812        "listeners" : {
813         "clicked" : [
814          "(event) => {",
815          "",
816          "\t_this.forwardSearch(true);",
817          "\t",
818          "\t ",
819          "}",
820          ""
821         ]
822        },
823        "string icon_name" : "go-down",
824        "xtype" : "Button"
825       },
826       {
827        "$ xns" : "Gtk",
828        "bool always_show_image" : true,
829        "bool sensitive" : false,
830        "id" : "backBtn",
831        "listeners" : {
832         "clicked" : [
833          "(event) => {",
834          "",
835          "\t_this.backSearch(true);",
836          "\t ",
837          "}",
838          ""
839         ]
840        },
841        "string icon_name" : "go-up",
842        "xtype" : "Button"
843       },
844       {
845        "$ xns" : "Gtk",
846        "bool always_show_arrow" : true,
847        "bool always_show_image" : true,
848        "items" : [
849         {
850          "$ xns" : "Gtk",
851          "* prop" : "popover",
852          "id" : "search_settings",
853          "items" : [
854           {
855            "$ xns" : "Gtk",
856            "* prop" : "child",
857            "Gtk.Orientation orientation" : "Gtk.Orientation.VERTICAL",
858            "int spacing" : 0,
859            "items" : [
860             {
861              "$ xns" : "Gtk",
862              "* init" : [
863               "{",
864               "\tthis.el.show();",
865               "}",
866               ""
867              ],
868              "id" : "case_sensitive",
869              "string label" : "Case Sensitive",
870              "xtype" : "CheckButton"
871             },
872             {
873              "$ xns" : "Gtk",
874              "* init" : [
875               "{",
876               "\tthis.el.show();",
877               "}",
878               ""
879              ],
880              "id" : "regex",
881              "string label" : "Regex",
882              "xtype" : "CheckButton"
883             },
884             {
885              "$ xns" : "Gtk",
886              "id" : "multiline",
887              "string label" : "Multi-line (add \\n)",
888              "xtype" : "CheckButton"
889             }
890            ],
891            "xtype" : "Box"
892           }
893          ],
894          "xtype" : "Popover"
895         }
896        ],
897        "string icon_name" : "emblem-system",
898        "xtype" : "MenuButton"
899       }
900      ],
901      "xtype" : "Box"
902     }
903    ],
904    "xtype" : "Box",
905    "| bool saveContents" : [
906     "  ()  {",
907     "    ",
908     "    ",
909     "    if (_this.file == null) {",
910     "        return true;",
911     "    }",
912     "    ",
913     "     ",
914     "     ",
915     "     var str = _this.buffer.toString();",
916     "     ",
917     "     _this.buffer.checkSyntax();",
918     "     ",
919     "     ",
920     "     ",
921     "     // LeftPanel.model.changed(  str , false);",
922     "     _this.dirty = false;",
923     "     _this.save_button.el.sensitive = false;",
924     "     ",
925     "    // find the text for the node..",
926     "    if (_this.file.xtype != \"PlainFile\") {",
927     "       // in theory these properties have to exist!?!",
928     "    \tthis.prop.val = str;",
929     "        //this.window.windowstate.left_props.reload();",
930     "    } else {",
931     "        _this.file.setSource(  str );",
932     "     }",
933     "    ",
934     "    // call the signal..",
935     "    this.save();",
936     "    ",
937     "    return true;",
938     "",
939     "} "
940    ],
941    "| int search" : [
942     "(string in_txt) {",
943     "",
944     "\tvar s = new GtkSource.SearchSettings();",
945     "\ts.case_sensitive = _this.case_sensitive.el.active;",
946     "\ts.regex_enabled = _this.regex.el.active;\t",
947     "\ts.wrap_around = false;",
948     "\t",
949     "\tthis.searchcontext = new GtkSource.SearchContext(this.buffer.el,s);",
950     "\tthis.searchcontext.set_highlight(true);",
951     "\tvar txt = in_txt;",
952     "\t",
953     "\tif (_this.multiline.el.active) {",
954     "\t\ttxt = in_txt.replace(\"\\\\n\", \"\\n\");",
955     "\t}",
956     "\t",
957     "\ts.set_search_text(txt);",
958     "\tGtk.TextIter beg, st,en;",
959     "\t ",
960     "\tthis.buffer.el.get_start_iter(out beg);",
961     "\tbool has_wrapped_around;",
962     "\tthis.searchcontext.forward(beg, out st, out en, out has_wrapped_around);",
963     "\tthis.last_search_end = 0;",
964     "\t",
965     "\treturn this.searchcontext.get_occurrences_count();",
966     "",
967     " ",
968     "   ",
969     "",
970     "}",
971     ""
972    ],
973    "| string tempFileContents" : [
974     "() {",
975     "   ",
976     "   ",
977     "   if (_this.file == null) {",
978     "       return \"\";",
979     "   }",
980     "\tvar str= this.buffer.toString();",
981     "\tif (_this.file.xtype == \"PlainFile\") {",
982     "    ",
983     "     \treturn str;",
984     "    ",
985     "    }",
986     "  ",
987     "      ",
988     "     ",
989     "    GLib.debug(\"calling validate\");    ",
990     "    // clear the buttons.",
991     " \tif (_this.prop.name == \"xns\" || _this.prop.name == \"xtype\") {",
992     "\t\treturn this.file.toSource(); ;",
993     "\t}",
994     "\t",
995     "\tvar oldcode  = _this.prop.val;",
996     "\t_this.prop.val = str;",
997     "    var ret = _this.file.toSource();",
998     "    _this.prop.val = oldcode;",
999     "    return ret;",
1000     "    ",
1001     "}"
1002    ],
1003    "| void backSearch" : [
1004     "(bool change_focus) {",
1005     "",
1006     "\tif (this.searchcontext == null) {",
1007     "\t\treturn;",
1008     "\t}",
1009     "\t",
1010     "\tGtk.TextIter beg, st,en;",
1011     "\tbool has_wrapped_around;",
1012     "\tthis.buffer.el.get_iter_at_offset(out beg, this.last_search_end -1 );",
1013     "\t",
1014     "\tif (!this.searchcontext.backward(beg, out st, out en, out has_wrapped_around)) {",
1015     "\t\tthis.last_search_end = 0;",
1016     "\t} else {",
1017     "\t\tthis.last_search_end = en.get_offset();",
1018     "\t\tif (change_focus) {",
1019     "\t\t\tthis.view.el.grab_focus();",
1020     "\t\t}",
1021     "\t\tthis.buffer.el.place_cursor(st);",
1022     "\t\tthis.view.el.scroll_to_iter(st,  0.1f, true, 0.0f, 0.5f);",
1023     "\t}",
1024     "",
1025     "}",
1026     ""
1027    ],
1028    "| void forwardSearch" : [
1029     "(bool change_focus) {",
1030     "",
1031     "\tif (this.searchcontext == null) {",
1032     "\t\treturn;",
1033     "\t} ",
1034     "",
1035     "\tGtk.TextIter beg, st,en;",
1036     "\t bool has_wrapped_around;",
1037     "\tthis.buffer.el.get_iter_at_offset(out beg, this.last_search_end);",
1038     "\tif (!this.searchcontext.forward(beg, out st, out en, out has_wrapped_around)) {",
1039     "\t",
1040     "\t\tthis.last_search_end = 0; // not sure if this should happen",
1041     "\t} else {",
1042     "\t\tif (has_wrapped_around) {",
1043     "\t\t\treturn;",
1044     "\t\t}",
1045     "\t",
1046     "\t\tthis.last_search_end = en.get_offset();",
1047     "\t\tif (change_focus) {",
1048     "\t\t\tthis.view.el.grab_focus();",
1049     "\t\t}",
1050     "\t\tthis.buffer.el.place_cursor(st);",
1051     "\t\tthis.view.el.scroll_to_iter(st,  0.1f, true, 0.0f, 0.5f);",
1052     "\t}",
1053     " ",
1054     "}",
1055     ""
1056    ],
1057    "| void reset" : [
1058     "() {",
1059     "\t this.file = null;    ",
1060     "     ",
1061     "    this.node = null;",
1062     "    this.prop = null;",
1063     "\tthis.searchcontext = null;",
1064     "  ",
1065     "}",
1066     ""
1067    ],
1068    "| void scroll_to_line" : [
1069     "(int line) {",
1070     "",
1071     "\tGLib.Timeout.add(500, () => {",
1072     "   ",
1073     "\t\tvar buf = this.view.el.get_buffer();",
1074     "",
1075     "\t\tvar sbuf = (GtkSource.Buffer) buf;",
1076     "",
1077     "",
1078     "\t\tGtk.TextIter iter;   ",
1079     "\t\tsbuf.get_iter_at_line(out iter,  line);",
1080     "\t\tthis.view.el.scroll_to_iter(iter,  0.1f, true, 0.0f, 0.5f);",
1081     "\t\treturn false;",
1082     "\t});   ",
1083     "}",
1084     ""
1085    ],
1086    "| void show" : [
1087     "(JsRender.JsRender file, JsRender.Node? node, JsRender.NodeProp? prop)",
1088     "{",
1089     "    this.reset();",
1090     "    this.file = file;    ",
1091     "    ",
1092     "    if (file.xtype != \"PlainFile\") {",
1093     "    \tthis.prop = prop;",
1094     "        this.node = node;",
1095     "",
1096     "        // find the text for the node..",
1097     "        this.view.load( prop.val );",
1098     "        this.updateErrorMarks();",
1099     "        ",
1100     "        this.close_btn.el.show();       ",
1101     "    ",
1102     "    } else {",
1103     "        this.view.load(        file.toSource() );",
1104     "         this.updateErrorMarks();",
1105     "        this.close_btn.el.hide();",
1106     "        ",
1107     "    }",
1108     " ",
1109     "}"
1110    ],
1111    "| void updateErrorMarks" : [
1112     "() {",
1113     "\t",
1114     " ",
1115     "",
1116     "\tvar buf = _this.buffer.el;",
1117     "\tGtk.TextIter start;",
1118     "\tGtk.TextIter end;     ",
1119     "\tbuf.get_bounds (out start, out end);",
1120     "",
1121     "\t",
1122     "",
1123     " ",
1124     "\t//GLib.debug(\"highlight errors\");\t\t ",
1125     "",
1126     "\t // we should highlight other types of errors..",
1127     "",
1128     "\tif (_this.window.windowstate.state != WindowState.State.CODEONLY ",
1129     "\t\t&&",
1130     "\t\t_this.window.windowstate.state != WindowState.State.CODE",
1131     "\t\t) {",
1132     "\t\t//GLib.debug(\"windowstate != CODEONLY?\");",
1133     "\t\t",
1134     "\t\treturn;",
1135     "\t} ",
1136     "",
1137     "\t ",
1138     "\tif (_this.file == null) {",
1139     "\t\tGLib.debug(\"file is null?\");",
1140     "\t\treturn;",
1141     "",
1142     "\t}",
1143     "\tvar ar = this.file.getErrors();",
1144     "\tif (ar.size < 1) {",
1145     "\t\tbuf.remove_source_marks (start, end, \"ERR\");",
1146     "\t\tbuf.remove_source_marks (start, end, \"WARN\");",
1147     "\t\tbuf.remove_source_marks (start, end, \"DEPR\");",
1148     "\t\tbuf.remove_tag_by_name (\"ERR\", start, end);",
1149     "\t\tbuf.remove_tag_by_name (\"WARN\", start, end);",
1150     "\t\tbuf.remove_tag_by_name (\"DEPR\", start, end);",
1151     "\t\tthis.last_error_counter = file.error_counter ;",
1152     "\t\t//GLib.debug(\"highlight %s :  %s has no errors\", this.file.relpath, category);",
1153     "\t\treturn;",
1154     "\t}",
1155     "\t",
1156     "",
1157     " // basicaly check if there is no change, then we do not do any update..",
1158     " // we can do this by just using an error counter?",
1159     " // if that's changed then we will do an update, otherwise dont bother.",
1160     "\t  ",
1161     "\t",
1162     "\tvar offset = 0;",
1163     "\tvar hoffset = 0;",
1164     "",
1165     "\tvar tlines = buf.get_line_count () +1;",
1166     "\t",
1167     "\tif (_this.prop != null) {",
1168     "\t\t// this still seems flaky...",
1169     "",
1170     "\t\ttlines = _this.prop.end_line;",
1171     "\t\toffset = _this.prop.start_line;",
1172     "\t\thoffset = _this.node.node_pad.length + 2; //shift it left  by 2 ? ..",
1173     "\t\t",
1174     "\t\t ",
1175     "\t} else {",
1176     "\t\t// no update...",
1177     "\t\tif (this.last_error_counter == file.error_counter) {",
1178     "\t\t",
1179     "\t\t\treturn;",
1180     "\t\t}",
1181     "\t",
1182     "\t}",
1183     "\tbuf.remove_source_marks (start, end, \"ERR\");",
1184     "\tbuf.remove_source_marks (start, end, \"WARN\");",
1185     "\tbuf.remove_source_marks (start, end, \"DEPR\");",
1186     "\tbuf.remove_tag_by_name (\"ERR\", start, end);",
1187     "\tbuf.remove_tag_by_name (\"WARN\", start, end);",
1188     "\tbuf.remove_tag_by_name (\"DEPR\", start, end);",
1189     "\t",
1190     "\tforeach(var diag in ar) { ",
1191     "\t     Gtk.TextIter iter;",
1192     "//        print(\"get inter\\n\");",
1193     "\t    var eline = (int)diag.range.start.line - offset;",
1194     "\t    var eline_to = (int)diag.range.end.line - offset;",
1195     "\t    //var eline =  diag.range.end_line - offset;",
1196     "\t    //GLib.debug(\"GOT ERROR on line %d -- converted to %d  (offset = %d)\",",
1197     "\t    //\terr.line ,eline, offset);",
1198     "\t    ",
1199     "\t    ",
1200     "\t    if (eline > tlines || eline < 0) {",
1201     "\t        continue;",
1202     "\t    }",
1203     "\t    ",
1204     "\t    buf.get_iter_at_line( out iter, eline);",
1205     "\t   \tvar msg = \"Line: %d %s : %s\".printf(eline+1, diag.category, diag.message);",
1206     "\t    buf.create_source_mark( msg, diag.category, iter);",
1207     "\t    ",
1208     " \t    var spos = (int)diag.range.start.character - hoffset;",
1209     " \t    if (spos < 0) { spos =0 ; }",
1210     " \t    if (spos > iter.get_chars_in_line()) {",
1211     " \t    \tspos = iter.get_chars_in_line();",
1212     "    \t}",
1213     "\t\tbuf.get_iter_at_line( out iter, eline_to);",
1214     "\t\tvar epos = (int)diag.range.end.character - hoffset;",
1215     " \t    if (epos < 0) { epos =0 ; }",
1216     " \t    if (epos > iter.get_chars_in_line()) {",
1217     " \t    \tepos = iter.get_chars_in_line();",
1218     "    \t}",
1219     " \t     ",
1220     " \t    ",
1221     " \t    buf.get_iter_at_line_offset( out start, eline, spos); ",
1222     " \t   ",
1223     " \t    buf.get_iter_at_line_offset( out end, eline_to,epos); ",
1224     " \t    \t",
1225     "\t    buf.apply_tag_by_name(diag.category, start, end);",
1226     "\t    ",
1227     "\t   // GLib.debug(\"set line %d to %s\", eline, msg);",
1228     "\t    //this.marks.set(eline, msg);",
1229     "\t}",
1230     "\tthis.last_error_counter = file.error_counter ;",
1231     "",
1232     "",
1233     "",
1234     " ",
1235     "",
1236     "}"
1237    ]
1238   }
1239  ],
1240  "name" : "Editor"
1241 }