Fix #8097 - highlighting selected line from code navigation - partially workimg
authorAlan Knowles <alan@roojs.com>
Tue, 19 Mar 2024 15:43:00 +0000 (23:43 +0800)
committerAlan Knowles <alan@roojs.com>
Tue, 19 Mar 2024 15:43:00 +0000 (23:43 +0800)
resources/css/roobuilder.css
src/Builder4/Editor.bjs
src/Builder4/Editor.vala
src/Lsp.vala

index 592d2c6..f1fde7b 100644 (file)
        padding-top: 2px;
        padding-bottom: 2px;
 } 
+
+#editor-navigation .selected-row {
+    background-color:#88a3bc; 
+} 
+
 .lang-class-symbolic {
        color : #266b02;
        font-weight: bold;
index dd0a0c2..0db9e57 100644 (file)
                "    return ;",
                "}",
                ""
+              ],
+              "cursor_moved" : [
+               "( ) => {",
+               "",
+               "\tGtk.TextIter iter;",
+               "\tthis.el.get_iter_at_offset (",
+               "\t\t\tout iter, this.el.cursor_position);",
+               "\tvar line = iter.get_line();",
+               "\t_this.navigation.updateSelectedLine(",
+               "\t\t\t(uint)iter.get_line(),",
+               "\t\t\t(uint)iter.get_line_offset()",
+               "\t\t);",
+               "",
+               "",
+               "}",
+               ""
               ]
              },
              "| bool OLDhighlightErrorsJson" : [
        "id" : "navigationwindow",
        "items" : [
         {
+         "# int last_selected_line" : "-1",
+         "$ Gtk.Widget? selected_row" : "null",
          "$ xns" : "Gtk",
          "* prop" : "child",
          "id" : "navigation",
             {
              "$ xns" : "Gtk",
              "* prop" : "model",
+             "id" : "navigationsort",
              "items" : [
               {
                "$ Gtk.TreeListModelCreateModelFunc create_func" : [
                  "$ xns" : "GLib",
                  "* prop" : "root",
                  "id" : "navliststore",
-                 "xtype" : "ListStore"
+                 "xtype" : "ListStore",
+                 "| Lsp.DocumentSymbol? symbolAtLine" : [
+                  "(uint line, uint chr) {",
+                  " ",
+                  "\t",
+                  "\tfor(var i = 0; i < this.el.get_n_items();i++) {",
+                  "\t\tvar el = (Lsp.DocumentSymbol)this.el.get_item(i);",
+                  "\t\t//GLib.debug(\"Check sym %s : %d-%d\",",
+                  "\t\t//\tel.name , (int)el.range.start.line,",
+                  "\t\t//\t(int)el.range.end.line",
+                  "\t\t//);",
+                  "\t\tvar ret = el.containsLine(line,chr);",
+                  "\t\tif (ret != null) {",
+                  "\t\t\treturn ret;",
+                  "\t\t}",
+                  "\t\t",
+                  "\t}",
+                  "\t",
+                  "\treturn null;",
+                  "}"
+                 ]
                 }
                ],
                "xtype" : "TreeListModel"
                "xtype" : "TreeListRowSorter"
               }
              ],
-             "xtype" : "SortListModel"
+             "xtype" : "SortListModel",
+             "| Lsp.DocumentSymbol? getSymbolAt" : [
+              "(uint row) {",
+              "",
+              "   var tr = (Gtk.TreeListRow)this.el.get_item(row);",
+              "   ",
+              "   var a = tr.get_item();;   ",
+              "   GLib.debug(\"get_item (2) = %s\", a.get_type().name());",
+              "  \t",
+              "   ",
+              "   return (Lsp.DocumentSymbol)tr.get_item();",
+              "\t ",
+              "}"
+             ],
+             "| int getRowFromSymbol" : [
+              "(Lsp.DocumentSymbol sym) {",
+              "",
+              "\tfor (var i=0;i < this.el.get_n_items(); i++) {",
+              "\t\tvar tr = (Gtk.TreeListRow)this.el.get_item(i);",
+              "\t   ",
+              "\t\tif (sym.equals( (Lsp.DocumentSymbol)tr.get_item())) {",
+              "\t\t\treturn i;",
+              "\t\t}",
+              "\t}",
+              "   \treturn -1;",
+              "}"
+             ]
             }
            ],
            "xtype" : "NoSelection",
-           "| Lsp.DocumentSymbol? getSymoblAt" : [
+           "| Lsp.DocumentSymbol? getSymbollAtOLD" : [
             "(uint row) {",
             "",
             "   var tr = (Gtk.TreeListRow)this.el.get_item(row);",
             "   return (Lsp.DocumentSymbol)tr.get_item();",
             "\t ",
             "}"
+           ],
+           "| int getRowFromSymbolx" : [
+            "(Lsp.DocumentSymbol sym) {",
+            "",
+            "\tfor (var i=0;i < this.el.get_n_items(); i++) {",
+            "\t\tvar tr = (Gtk.TreeListRow)this.el.get_item(i);",
+            "\t   ",
+            "\t\tif (sym.equals( (Lsp.DocumentSymbol)tr.get_item())) {",
+            "\t\t\treturn i;",
+            "\t\t}",
+            "\t}",
+            "   \treturn -1;",
+            "}"
            ]
           },
           {
              "\t    return;",
              "    }",
              "    //Lsp.DocumentSymbol",
-             "    var sym =   _this.navigationselmodel.getSymoblAt(row);",
+             "    var sym =   _this.navigationsort.getSymbolAt(row);",
              "    if (sym == null) {",
              "    \treturn;",
              "\t}",
              "                \"character\" : 39",
              "              }",
              "            },",
-             "            */",
+             "        */",
+             "     GLib.debug(\"goto line %d\",   (int)sym.range.start.line); ",
              "    _this.scroll_to_line((int)sym.range.start.line);",
              "\t",
              "}"
          ],
          "string name" : "editor-navigation",
          "xtype" : "ColumnView",
+         "| Gtk.Widget? getWidgetAtRow" : [
+          "(uint row) {",
+          "/*",
+          "    \t",
+          "from    \thttps://discourse.gnome.org/t/gtk4-finding-a-row-data-on-gtkcolumnview/8465",
+          "    \tvar colview = gesture.widget;",
+          "    \tvar line_no = check_list_widget(colview, x,y);",
+          "         if (line_no > -1) {",
+          "    \t\tvar item = colview.model.get_item(line_no);",
+          "    \t\t ",
+          "    \t}",
+          "    \t*/",
+          "\t\t//GLib.debug(\"Get Widget At Row %d\", (int)row);",
+          "        var  child = this.el.get_first_child(); ",
+          "    \tvar line_no = -1; ",
+          "    \tvar reading_header = true;",
+          "\t ",
+          "    \twhile (child != null) {",
+          "\t\t\t//GLib.debug(\"Got %s\", child.get_type().name());",
+          "    \t   ",
+          "    \t   if (reading_header) {",
+          "\t\t\t\t",
+          "",
+          "\t\t\t\tif (child.get_type().name() != \"GtkColumnListView\") {",
+          "\t\t\t\t   ",
+          "\t\t\t\t\tchild = child.get_next_sibling();",
+          "\t\t\t\t\tcontinue;",
+          "\t\t\t\t}",
+          "\t\t\t\t// should be columnlistview",
+          "\t\t\t\tchild = child.get_first_child(); ",
+          "\t\t\t ",
+          "\t\t\t ",
+          "\t\t\t\t",
+          "\t\t\t\treading_header = false;",
+          "\t\t\t\tcontinue;",
+          "\t\t    }",
+          "\t\t    ",
+          "\t\t  ",
+          "    \t    ",
+          "\t\t    line_no++;",
+          "\t\t\tif (line_no == row) {",
+          "\t\t\t\t//GLib.debug(\"Returning widget %s\", child.get_type().name());",
+          "\t\t\t    return (Gtk.Widget)child;",
+          "\t\t    }",
+          "\t        child = child.get_next_sibling(); ",
+          "    \t}",
+          "\t\tGLib.debug(\"Failed to find row (max = %d)\", line_no);",
+          "        return null;",
+          "",
+          " }"
+         ],
          "| int getRowAt" : [
           "(double x,  double  y, out string pos) {",
           "",
           "\t",
           "",
           "}"
+         ],
+         "| void updateSelectedLine" : [
+          "(uint line, uint chr) {",
+          "\tif (line == this.last_selected_line) {",
+          "\t\treturn;",
+          "\t}",
+          "\tGLib.debug(\"select line %d\", (int)line);",
+          "\tthis.last_selected_line = (int)line;",
+          "\t",
+          "\t",
+          "\tvar new_row = -1;",
+          "\tvar sym = _this.navliststore.symbolAtLine(line, chr);",
+          "\tif (sym != null) {",
+          "\t \tnew_row = _this.navigationsort.getRowFromSymbol(sym);",
+          " \t\tGLib.debug(\"select line %d - row found %d\", (int)line, new_row);",
+          " \t} else {",
+          " \t\tGLib.debug(\" no symbol found at line %d\", (int)line);",
+          " \t}",
+          " \t",
+          "\tif (this.selected_row != null) { ",
+          "\t\tGLib.debug(\" remove selected row\");",
+          "\t\tthis.selected_row.remove_css_class(\"selected-row\");",
+          "\t}",
+          "\tthis.selected_row  = null;",
+          "\tif (new_row > -1) {",
+          "\t\tthis.el.scroll_to(new_row,null,Gtk.ListScrollFlags.NONE, null);",
+          "\t\tvar row = this.getWidgetAtRow(new_row);",
+          "\t\tif (row != null) {",
+          "\t\t\tGLib.debug(\" Add selected row\");",
+          " \t\t\t",
+          "\t\t\trow.add_css_class(\"selected-row\");",
+          "\t\t\tthis.selected_row = row;",
+          "",
+          "\t\t\t",
+          "\t\t} else {",
+          "\t\t\tGLib.debug(\"could not find widget on row %d\", new_row);",
+          "\t\t}",
+          "",
+          "\t}",
+          "",
+          "",
+          "}"
          ]
         }
        ],
index 94dd0ca..9d501d7 100644 (file)
@@ -29,6 +29,7 @@ public class Editor : Object
        public Xcls_navigationwindow navigationwindow;
        public Xcls_navigation navigation;
        public Xcls_navigationselmodel navigationselmodel;
+       public Xcls_navigationsort navigationsort;
        public Xcls_navliststore navliststore;
 
                // my vars (def)
@@ -926,6 +927,19 @@ public class Editor : Object
                        buf.create_tag ("DEPR", "weight", Pango.Weight.BOLD, "background", "#EEA9FF");
 
                        //listeners
+                       this.el.cursor_moved.connect( ( ) => {
+                       
+                               Gtk.TextIter iter;
+                               this.el.get_iter_at_offset (
+                                               out iter, this.el.cursor_position);
+                               var line = iter.get_line();
+                               _this.navigation.updateSelectedLine(
+                                               (uint)iter.get_line(),
+                                               (uint)iter.get_line_offset()
+                                       );
+                       
+                       
+                       });
                        this.el.changed.connect( () => {
                            // check syntax??
                            // ??needed..??
@@ -1760,6 +1774,8 @@ public class Editor : Object
 
 
                        // my vars (def)
+               public int last_selected_line;
+               public Gtk.Widget? selected_row;
 
                // ctor
                public Xcls_navigation(Editor _owner )
@@ -1770,18 +1786,69 @@ public class Editor : Object
                        this.el = new Gtk.ColumnView( _this.navigationselmodel.el );
 
                        // my vars (dec)
+                       this.last_selected_line = -1;
+                       this.selected_row = null;
 
                        // set gobject values
                        this.el.name = "editor-navigation";
                        var child_2 = new Xcls_ColumnViewColumn29( _this );
                        child_2.ref();
                        this.el.append_column( child_2.el );
-                       var child_3 = new Xcls_GestureClick34( _this );
+                       var child_3 = new Xcls_GestureClick38( _this );
                        child_3.ref();
                        this.el.add_controller(  child_3.el );
                }
 
                // user defined functions
+               public Gtk.Widget? getWidgetAtRow (uint row) {
+               /*
+                       
+               from            https://discourse.gnome.org/t/gtk4-finding-a-row-data-on-gtkcolumnview/8465
+                       var colview = gesture.widget;
+                       var line_no = check_list_widget(colview, x,y);
+                        if (line_no > -1) {
+                               var item = colview.model.get_item(line_no);
+                                
+                       }
+                       */
+                               //GLib.debug("Get Widget At Row %d", (int)row);
+                       var  child = this.el.get_first_child(); 
+                       var line_no = -1; 
+                       var reading_header = true;
+                        
+                       while (child != null) {
+                                       //GLib.debug("Got %s", child.get_type().name());
+                          
+                          if (reading_header) {
+                                               
+               
+                                               if (child.get_type().name() != "GtkColumnListView") {
+                                                  
+                                                       child = child.get_next_sibling();
+                                                       continue;
+                                               }
+                                               // should be columnlistview
+                                               child = child.get_first_child(); 
+                                        
+                                        
+                                               
+                                               reading_header = false;
+                                               continue;
+                                   }
+                                   
+                                 
+                           
+                                   line_no++;
+                                       if (line_no == row) {
+                                               //GLib.debug("Returning widget %s", child.get_type().name());
+                                           return (Gtk.Widget)child;
+                                   }
+                               child = child.get_next_sibling(); 
+                       }
+                               GLib.debug("Failed to find row (max = %d)", line_no);
+                       return null;
+               
+                }
                public void show (Gee.ArrayList<Lsp.DocumentSymbol> syms) {
                        _this.navigationwindow.el.show();
                        _this.navliststore.el.remove_all();
@@ -1837,6 +1904,46 @@ public class Editor : Object
                        } 
                        return rn;
                 }
+               public void updateSelectedLine (uint line, uint chr) {
+                       if (line == this.last_selected_line) {
+                               return;
+                       }
+                       GLib.debug("select line %d", (int)line);
+                       this.last_selected_line = (int)line;
+                       
+                       
+                       var new_row = -1;
+                       var sym = _this.navliststore.symbolAtLine(line, chr);
+                       if (sym != null) {
+                               new_row = _this.navigationsort.getRowFromSymbol(sym);
+                               GLib.debug("select line %d - row found %d", (int)line, new_row);
+                       } else {
+                               GLib.debug(" no symbol found at line %d", (int)line);
+                       }
+                       
+                       if (this.selected_row != null) { 
+                               GLib.debug(" remove selected row");
+                               this.selected_row.remove_css_class("selected-row");
+                       }
+                       this.selected_row  = null;
+                       if (new_row > -1) {
+                               this.el.scroll_to(new_row,null,Gtk.ListScrollFlags.NONE, null);
+                               var row = this.getWidgetAtRow(new_row);
+                               if (row != null) {
+                                       GLib.debug(" Add selected row");
+                                       
+                                       row.add_css_class("selected-row");
+                                       this.selected_row = row;
+               
+                                       
+                               } else {
+                                       GLib.debug("could not find widget on row %d", new_row);
+                               }
+               
+                       }
+               
+               
+               }
        }
        public class Xcls_ColumnViewColumn29 : Object
        {
@@ -1961,9 +2068,8 @@ public class Editor : Object
                {
                        _this = _owner;
                        _this.navigationselmodel = this;
-                       var child_1 = new Xcls_SortListModel60( _this );
-                       child_1.ref();
-                       this.el = new Gtk.NoSelection( child_1.el );
+                       new Xcls_navigationsort( _this );
+                       this.el = new Gtk.NoSelection( _this.navigationsort.el );
 
                        // my vars (dec)
 
@@ -1971,7 +2077,18 @@ public class Editor : Object
                }
 
                // user defined functions
-               public Lsp.DocumentSymbol? getSymoblAt (uint row) {
+               public int getRowFromSymbolx (Lsp.DocumentSymbol sym) {
+               
+                       for (var i=0;i < this.el.get_n_items(); i++) {
+                               var tr = (Gtk.TreeListRow)this.el.get_item(i);
+                          
+                               if (sym.equals( (Lsp.DocumentSymbol)tr.get_item())) {
+                                       return i;
+                               }
+                       }
+                       return -1;
+               }
+               public Lsp.DocumentSymbol? getSymbollAtOLD (uint row) {
                
                   var tr = (Gtk.TreeListRow)this.el.get_item(row);
                   
@@ -1983,7 +2100,7 @@ public class Editor : Object
                         
                }
        }
-       public class Xcls_SortListModel60 : Object
+       public class Xcls_navigationsort : Object
        {
                public Gtk.SortListModel el;
                private Editor  _this;
@@ -1992,12 +2109,13 @@ public class Editor : Object
                        // my vars (def)
 
                // ctor
-               public Xcls_SortListModel60(Editor _owner )
+               public Xcls_navigationsort(Editor _owner )
                {
                        _this = _owner;
-                       var child_1 = new Xcls_TreeListModel171( _this );
+                       _this.navigationsort = this;
+                       var child_1 = new Xcls_TreeListModel33( _this );
                        child_1.ref();
-                       var child_2 = new Xcls_TreeListRowSorter209( _this );
+                       var child_2 = new Xcls_TreeListRowSorter35( _this );
                        child_2.ref();
                        this.el = new Gtk.SortListModel( child_1.el, child_2.el );
 
@@ -2007,8 +2125,30 @@ public class Editor : Object
                }
 
                // user defined functions
+               public int getRowFromSymbol (Lsp.DocumentSymbol sym) {
+               
+                       for (var i=0;i < this.el.get_n_items(); i++) {
+                               var tr = (Gtk.TreeListRow)this.el.get_item(i);
+                          
+                               if (sym.equals( (Lsp.DocumentSymbol)tr.get_item())) {
+                                       return i;
+                               }
+                       }
+                       return -1;
+               }
+               public Lsp.DocumentSymbol? getSymbolAt (uint row) {
+               
+                  var tr = (Gtk.TreeListRow)this.el.get_item(row);
+                  
+                  var a = tr.get_item();;   
+                  GLib.debug("get_item (2) = %s", a.get_type().name());
+                       
+                  
+                  return (Lsp.DocumentSymbol)tr.get_item();
+                        
+               }
        }
-       public class Xcls_TreeListModel171 : Object
+       public class Xcls_TreeListModel33 : Object
        {
                public Gtk.TreeListModel el;
                private Editor  _this;
@@ -2017,7 +2157,7 @@ public class Editor : Object
                        // my vars (def)
 
                // ctor
-               public Xcls_TreeListModel171(Editor _owner )
+               public Xcls_TreeListModel33(Editor _owner )
                {
                        _this = _owner;
                        new Xcls_navliststore( _this );
@@ -2055,10 +2195,28 @@ public class Editor : Object
                }
 
                // user defined functions
+               public Lsp.DocumentSymbol? symbolAtLine (uint line, uint chr) {
+                
+                       
+                       for(var i = 0; i < this.el.get_n_items();i++) {
+                               var el = (Lsp.DocumentSymbol)this.el.get_item(i);
+                               //GLib.debug("Check sym %s : %d-%d",
+                               //      el.name , (int)el.range.start.line,
+                               //      (int)el.range.end.line
+                               //);
+                               var ret = el.containsLine(line,chr);
+                               if (ret != null) {
+                                       return ret;
+                               }
+                               
+                       }
+                       
+                       return null;
+               }
        }
 
 
-       public class Xcls_TreeListRowSorter209 : Object
+       public class Xcls_TreeListRowSorter35 : Object
        {
                public Gtk.TreeListRowSorter el;
                private Editor  _this;
@@ -2067,10 +2225,10 @@ public class Editor : Object
                        // my vars (def)
 
                // ctor
-               public Xcls_TreeListRowSorter209(Editor _owner )
+               public Xcls_TreeListRowSorter35(Editor _owner )
                {
                        _this = _owner;
-                       var child_1 = new Xcls_StringSorter217( _this );
+                       var child_1 = new Xcls_StringSorter36( _this );
                        child_1.ref();
                        this.el = new Gtk.TreeListRowSorter( child_1.el );
 
@@ -2081,7 +2239,7 @@ public class Editor : Object
 
                // user defined functions
        }
-       public class Xcls_StringSorter217 : Object
+       public class Xcls_StringSorter36 : Object
        {
                public Gtk.StringSorter el;
                private Editor  _this;
@@ -2090,10 +2248,10 @@ public class Editor : Object
                        // my vars (def)
 
                // ctor
-               public Xcls_StringSorter217(Editor _owner )
+               public Xcls_StringSorter36(Editor _owner )
                {
                        _this = _owner;
-                       var child_1 = new Xcls_PropertyExpression224( _this );
+                       var child_1 = new Xcls_PropertyExpression37( _this );
                        child_1.ref();
                        this.el = new Gtk.StringSorter( child_1.el );
 
@@ -2104,7 +2262,7 @@ public class Editor : Object
 
                // user defined functions
        }
-       public class Xcls_PropertyExpression224 : Object
+       public class Xcls_PropertyExpression37 : Object
        {
                public Gtk.PropertyExpression el;
                private Editor  _this;
@@ -2113,7 +2271,7 @@ public class Editor : Object
                        // my vars (def)
 
                // ctor
-               public Xcls_PropertyExpression224(Editor _owner )
+               public Xcls_PropertyExpression37(Editor _owner )
                {
                        _this = _owner;
                        this.el = new Gtk.PropertyExpression( typeof(Lsp.DocumentSymbol), null, "sort_key" );
@@ -2130,7 +2288,7 @@ public class Editor : Object
 
 
 
-       public class Xcls_GestureClick34 : Object
+       public class Xcls_GestureClick38 : Object
        {
                public Gtk.GestureClick el;
                private Editor  _this;
@@ -2139,7 +2297,7 @@ public class Editor : Object
                        // my vars (def)
 
                // ctor
-               public Xcls_GestureClick34(Editor _owner )
+               public Xcls_GestureClick38(Editor _owner )
                {
                        _this = _owner;
                        this.el = new Gtk.GestureClick();
@@ -2157,7 +2315,7 @@ public class Editor : Object
                                    return;
                            }
                            //Lsp.DocumentSymbol
-                           var sym =   _this.navigationselmodel.getSymoblAt(row);
+                           var sym =   _this.navigationsort.getSymbolAt(row);
                            if (sym == null) {
                                return;
                                }
@@ -2172,7 +2330,8 @@ public class Editor : Object
                                        "character" : 39
                                      }
                                    },
-                                   */
+                               */
+                            GLib.debug("goto line %d",   (int)sym.range.start.line); 
                            _this.scroll_to_line((int)sym.range.start.line);
                                
                        });
index ec896ec..1f3a428 100644 (file)
@@ -62,6 +62,12 @@ namespace Lsp {
     }
 
     public  class Position : Object, Gee.Comparable<Position> {
+        
+        public Position(uint line, uint chr)
+        {
+               this.line = line;
+               this.character = chr;
+        }
         /**
          * Line position in a document (zero-based).
          */
@@ -78,6 +84,7 @@ namespace Lsp {
         public uint character { get; set; default = -1; }
 
         public int compare_to (Position other) {
+             
             return line > other.line ? 1 :
                 (line == other.line ?
                  (character > other.character ? 1 :
@@ -101,20 +108,14 @@ namespace Lsp {
         }
 
         public Position translate (int dl = 0, int dc = 0) {
-            return new Position () {
-                line = this.line + dl,
-                character = this.character + dc
-            };
+            return new Position (this.character + dc, this.character + dc) ;
         }
     }
 
     public class Range : Object, Gee.Hashable<Range>, Gee.Comparable<Range> {
         
         public Range.simple(uint line, uint pos) {
-               var p =  new Position () {
-                line = line,
-                character = pos
-            };
+               var p =  new Position (line,pos);
                this.start = p;
                this.end = p;
                
@@ -172,7 +173,10 @@ namespace Lsp {
         }
 
         public bool contains (Position pos) {
-            return start.compare_to (pos) <= 0 && pos.compare_to (end) <= 0;
+               
+            var ret =  start.compare_to (pos) <= 0 && pos.compare_to (end) <= 0;
+           // GLib.debug( "range contains %d  (%d-%d) %s", (int)pos.line, (int)start.line, (int)end.line, ret ? "Y" : "N");
+            return ret;
         }
        
     }
@@ -444,6 +448,26 @@ namespace Lsp {
                                return this.kind.sort_key().to_string() + "=" + this.name;
                        }
                }
+               
+               public DocumentSymbol? containsLine(uint line, uint chr)
+               {
+                       if (!this.range.contains(new Position(line, chr))) {
+                               return null;
+                       }
+
+                       for(var i = 0; i < this.children.get_n_items();i++) {
+                               var el = (DocumentSymbol)this.children.get_item(i);
+                               var ret = el.containsLine(line,chr);
+                               if (ret != null) {
+                                       return ret;
+                               }
+                       }
+                       return this;
+                       
+               }
+               public bool equals(DocumentSymbol sym) {
+                       return this.name == sym.name && this.kind == sym.kind &&  sym.range.equals(this.range);
+               }
           
           
     }