From: Jean-Philippe Bruyère Date: Tue, 27 Feb 2018 17:18:42 +0000 (+0100) Subject: crowide wip, DesignIDS X-Git-Tag: 0.7.3~4^2~39 X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=508b53d725958e6a8c8be51db04033aeff1df0da;p=jp%2Fcrow.git crowide wip, DesignIDS --- diff --git a/CrowIDE/CrowIDE.csproj b/CrowIDE/CrowIDE.csproj index 322e9bee..b916d716 100644 --- a/CrowIDE/CrowIDE.csproj +++ b/CrowIDE/CrowIDE.csproj @@ -141,7 +141,6 @@ Crow.TreeExpandable.template - Crow.Coding.EditPane.template @@ -167,6 +166,8 @@ + + diff --git a/CrowIDE/src/EditPane.cs b/CrowIDE/src/EditPane.cs index d7ddba5a..780e86d5 100644 --- a/CrowIDE/src/EditPane.cs +++ b/CrowIDE/src/EditPane.cs @@ -31,9 +31,7 @@ namespace Crow.Coding { public class EditPane : TemplatedGroup { - public EditPane () : base() - { - } + public EditPane () {} object selectedItemElement = null; diff --git a/CrowIDE/src/ImlVisualEditor.cs b/CrowIDE/src/ImlVisualEditor.cs index 3d59e9be..7989936a 100644 --- a/CrowIDE/src/ImlVisualEditor.cs +++ b/CrowIDE/src/ImlVisualEditor.cs @@ -43,7 +43,7 @@ namespace Crow.Coding DesignInterface imlVE; GraphicObject selectedItem; - ImlProjectItem projectItem; + ImlProjectItem projFile; Exception imlError = null; bool drawGrid; @@ -97,35 +97,27 @@ namespace Crow.Coding [XmlIgnore]public List LQIs { get { return imlVE.LQIs; } } - - [XmlAttributeAttribute] + public ProjectNode ProjectNode { - get { return projectItem; } + get { return projFile; } set { - if (projectItem == value) + if (projFile == value) return; + if (projFile != null) + projFile.UnregisterEditor (this); + + projFile = value as ImlProjectItem; - if (projectItem != null) - projectItem.ValueChanged -= ProjectItem_ValueChanged; - - projectItem = value as ImlProjectItem; - - if (projectItem != null) - projectItem.ValueChanged += ProjectItem_ValueChanged; + imlVE.ProjFile = projFile; - NotifyValueChanged ("ProjectNode", projectItem); + if (projFile != null) + projFile.RegisterEditor (this); - reload (); + NotifyValueChanged ("ProjectNode", projFile); } } - void ProjectItem_ValueChanged (object sender, ValueChangeEventArgs e) - { - if (e.MemberName == "Source") - reload (); - } - [XmlIgnore]public Exception IMLError { get { return imlError; } set { @@ -140,24 +132,6 @@ namespace Crow.Coding get { return imlError != null; } } - void reload(){ - if (projectItem == null) - return; - - try { - imlVE.ProjFile = projectItem; - imlVE.Styling = projectItem.Project.solution.Styling; - imlVE.DefaultTemplates = projectItem.Project.solution.DefaultTemplates; - imlVE.Instantiators = new Dictionary(); - imlVE.ClearInterface(); - imlVE.LoadIMLFragment(projectItem.Source); - IMLError = null; - } catch (Exception ex) { - IMLError = ex.InnerException; - Console.WriteLine (ex.ToString ()); - } - } - public List GraphicTree { get { return imlVE.GraphicTree; } } @@ -166,9 +140,29 @@ namespace Crow.Coding { while (true) { try { + if (!projFile.RegisteredEditors[this]){ + string selItemDesignID = null; + if (SelectedItem!=null) + selItemDesignID = SelectedItem.design_id; + imlVE.ClearInterface(); + Instantiator.NextInstantiatorID = 0; + imlVE.Styling = projFile.Project.solution.Styling; + imlVE.DefaultTemplates = projFile.Project.solution.DefaultTemplates; + imlVE.Instantiators = new Dictionary(); + imlVE.LoadIMLFragment(projFile.Source); + projFile.Instance = imlVE.GraphicTree[0]; + GraphicObject go = null; + if (selItemDesignID!=null) + projFile.Instance.FindByDesignID(selItemDesignID,out go); + SelectedItem = go; + IMLError = null; + projFile.RegisteredEditors[this] = true; + }else if ((bool)projFile.Instance?.HasChanged){ + projFile.UpdateSource(this, projFile.Instance.GetIML()); + } imlVE.Update (); } catch (Exception ex) { - System.Diagnostics.Debug.WriteLine (ex.ToString ()); + IMLError = ex.InnerException; if (Monitor.IsEntered(imlVE.UpdateMutex)) Monitor.Exit (imlVE.UpdateMutex); } @@ -215,9 +209,9 @@ namespace Crow.Coding //base.onMouseDown (sender, e); SelectedItem = HoverWidget; - if (SelectedItem != null && projectItem != null) { - projectItem.CurrentLine = HoverWidget.design_line; - projectItem.CurrentColumn = HoverWidget.design_column; + if (SelectedItem != null && projFile != null) { + projFile.CurrentLine = SelectedItem.design_line; + projFile.CurrentColumn = SelectedItem.design_column; } } diff --git a/CrowIDE/src/MembersView.cs b/CrowIDE/src/MembersView.cs index 79bcf5c4..f0c3a13a 100644 --- a/CrowIDE/src/MembersView.cs +++ b/CrowIDE/src/MembersView.cs @@ -32,6 +32,12 @@ namespace Crow.Coding public class MembersView : ListBox { object instance; + ImlProjectItem projFile; + + public MembersView () : base() {} + + //cache property containers per type + Dictionary propContainersCache = new Dictionary(); [XmlAttributeAttribute][DefaultValue(null)] public virtual object Instance { @@ -39,36 +45,70 @@ namespace Crow.Coding set { if (instance == value) return; + object lastInst = instance; + instance = value; NotifyValueChanged ("Instance", instance); - if (Instance is GraphicObject) - NotifyValueChanged ("SelectedItemName", (Instance as GraphicObject).Name); - else + + if (Instance is GraphicObject) { + NotifyValueChanged ("SelectedItemName", Instance.GetType().Name + (Instance as GraphicObject).design_id + + ":" + (Instance as GraphicObject).design_imlPath ); + }else NotifyValueChanged ("SelectedItemName", ""); - if (instance == null) { + if (instance == null) { Data = null; return; + } + + Type it = instance.GetType (); + if (!propContainersCache.ContainsKey (it.FullName)) { + MemberInfo[] members = it.GetMembers (BindingFlags.Public | BindingFlags.Instance); + List props = new List (); + foreach (MemberInfo m in members) { + if (m.MemberType == MemberTypes.Property) { + PropertyInfo pi = m as PropertyInfo; + if (!pi.CanWrite) + continue; + if (pi.GetCustomAttribute (typeof(XmlIgnoreAttribute)) != null) + continue; + props.Add (new PropertyContainer (this, pi)); + } + } + propContainersCache.Add (it.FullName, props.OrderBy (p => p.Name).ToArray ()); } - MemberInfo[] members = instance.GetType ().GetMembers (BindingFlags.Public | BindingFlags.Instance); + Data = propContainersCache [it.FullName]; - List props = new List (); - foreach (MemberInfo m in members) { - if (m.MemberType == MemberTypes.Property) { - PropertyInfo pi = m as PropertyInfo; - if (!pi.CanWrite) - continue; - if (pi.GetCustomAttribute (typeof(XmlIgnoreAttribute)) != null) - continue; - props.Add (new PropertyContainer (pi, instance)); + if (lastInst != instance) { + foreach (PropertyContainer pc in propContainersCache [it.FullName]) { + pc.NotifyValueChanged ("Value", pc.Value); } } - Data = props.OrderBy(p=>p.Name).ToArray (); } } - public MembersView () : base() - { + public ImlProjectItem ProjectNode { + get { return projFile; } + set { + if (projFile == value) + return; + +// if (projFile != null) +// projFile.UnregisterEditor (this); + + projFile = value; + +// if (projFile != null) +// projFile.RegisterEditor (this); + + NotifyValueChanged ("ProjectNode", projFile); + } + } + + public void updateSource () { + if (projFile == null) + return; + projFile.UpdateSource (this, (Instance as GraphicObject).GetIML ()); } // public override void Paint (ref Context ctx) diff --git a/CrowIDE/src/ProjectNodes.cs b/CrowIDE/src/ProjectNodes.cs index c668cfd3..eb7d6506 100644 --- a/CrowIDE/src/ProjectNodes.cs +++ b/CrowIDE/src/ProjectNodes.cs @@ -29,6 +29,7 @@ using System.Linq; using System.Xml; using System.IO; using Crow; +using System.Threading; namespace Crow.Coding { @@ -61,17 +62,24 @@ namespace Crow.Coding public ProjectNode (Project project, ItemType _type, string _name) : this(project){ type = _type; name = _name; + initCommands (); } public ProjectNode (Project project){ Project = project; + initCommands (); } #endregion + void initCommands () { + Commands = new List (); + } + ItemType type; string name; List childNodes = new List(); public Project Project; + public List Commands;//list of command available for that node public virtual ItemType Type { get { return type; } @@ -143,21 +151,29 @@ namespace Crow.Coding } public class ProjectFile : ProjectItem { - bool isOpened = false; + protected bool isOpened = false; DateTime accessTime; string source; string origSource; object selectedItem; + int curLine, curColumn; + + internal ReaderWriterLockSlim srcEditMtx = new ReaderWriterLockSlim(); + + public Dictionary RegisteredEditors = new Dictionary(); + + Crow.Command cmdSave, cmdOpen; - public List Commands; + public ProjectFile (ProjectItem pi) + : base (pi.Project, pi.node) { - public ProjectFile (ProjectItem pi) : base (pi.Project, pi.node){ - Commands = new List (new Crow.Command[] { - new Crow.Command(new Action(() => Open())) - { Caption = "Open", Icon = new SvgPicture("#Crow.Coding.ui.icons.outbox.svg"), CanExecute = false}, - new Crow.Command(new Action(() => Save())) - { Caption = "Save", Icon = new SvgPicture("#Crow.Coding.ui.icons.inbox.svg"), CanExecute = false}, - }); + cmdSave = new Crow.Command (new Action (() => Save ())) + { Caption = "Save", Icon = new SvgPicture ("#Crow.Coding.ui.icons.inbox.svg"), CanExecute = false }; + cmdOpen = new Crow.Command (new Action (() => Open ())) + { Caption = "Open", Icon = new SvgPicture ("#Crow.Coding.ui.icons.outbox.svg"), CanExecute = false }; + + Commands.Insert (0, cmdOpen); + Commands.Insert (1, cmdSave); } public string ResourceID { @@ -173,6 +189,28 @@ namespace Crow.Coding return node.SelectSingleNode ("LogicalName")?.InnerText; } } + + public void UnregisterEditor (object editor){ + lock(RegisteredEditors){ + RegisteredEditors.Remove (editor); + } + } + public void RegisterEditor (object editor) { + lock(RegisteredEditors){ + RegisteredEditors.Add (editor, false); + } + } + public void UpdateSource (object sender, string newSrc){ + System.Diagnostics.Debug.WriteLine ("update source by {0}", sender); + Source = newSrc; + lock (RegisteredEditors) { + object[] keys = RegisteredEditors.Keys.ToArray (); + foreach (object editor in keys) { + if (editor != sender) + RegisteredEditors [editor] = false; + } + } + } public string Source { get { if (!isOpened) @@ -188,15 +226,19 @@ namespace Crow.Coding set { if (source == value) return; + + srcEditMtx.EnterWriteLock (); + source = value; NotifyValueChanged ("Source", source); NotifyValueChanged ("IsDirty", IsDirty); + + srcEditMtx.ExitWriteLock (); } } public bool IsDirty { get { return source != origSource; } } - int curLine, curColumn; public int CurrentColumn{ get { return curColumn; } set { @@ -215,15 +257,6 @@ namespace Crow.Coding NotifyValueChanged ("CurrentLine", curLine); } } -// public bool IsSelected { -// get { return isSelected; } -// set { -// if (isSelected == value) -// return; -// isSelected = value; -// NotifyValueChanged ("IsSelected", isSelected); -// } -// } public object SelectedItem { get { return selectedItem; } @@ -239,10 +272,6 @@ namespace Crow.Coding public CopyToOutputState CopyToOutputDirectory { get { XmlNode xn = node.SelectSingleNode ("CopyToOutputDirectory"); -// if (xn == null) -// return CopyToOutputState.Never; -// CopyToOutputState tmp = (CopyToOutputState)Enum.Parse (typeof(CopyToOutputState), xn.InnerText, true); -// return tmp; return xn == null ? CopyToOutputState.Never : (CopyToOutputState)Enum.Parse (typeof(CopyToOutputState), xn.InnerText, true); } @@ -266,6 +295,8 @@ namespace Crow.Coding } public void OnQueryClose (object sender, EventArgs e){ + if (IsDirty) + Console.WriteLine ("closing unsaved file"); Project.solution.CloseItem (this); } } @@ -276,6 +307,21 @@ namespace Crow.Coding } #endregion + GraphicObject instance; + + /// + /// instance created with an instantiator from the source by a DesignInterface, + /// for now, the one in ImlVisualEditor + /// + public GraphicObject Instance { + get { return instance; } + set { + if (instance == value) + return; + instance = value; + NotifyValueChanged ("Instance", instance); + } + } } } diff --git a/CrowIDE/src/PropertyContainer.cs b/CrowIDE/src/PropertyContainer.cs index feea6477..6caec9d4 100644 --- a/CrowIDE/src/PropertyContainer.cs +++ b/CrowIDE/src/PropertyContainer.cs @@ -26,6 +26,8 @@ using System; using System.Reflection; using System.Linq; +using System.Collections.Generic; +using System.Diagnostics; namespace Crow.Coding { @@ -39,44 +41,84 @@ namespace Crow.Coding } #endregion + public List Commands; PropertyInfo pi; - object instance; - GraphicObject go; + MembersView mview; +// object instance; +// GraphicObject go; + + public PropertyContainer(MembersView mv, PropertyInfo prop){ + mview = mv; + pi = prop; +// instance = _instance; +// go = instance as GraphicObject; + + Commands = new List (new Crow.Command[] { + new Crow.Command(new Action(() => Reset())) { Caption = "Reset to default"}, + }); + } public string Name { get { return pi.Name; }} public object Value { - get { return go.design_members.ContainsKey(Name) ? - go.design_members[Name] : pi.GetValue(instance); } + get { + return pi.GetValue(mview.ProjectNode.SelectedItem); +// GraphicObject inst = mview.ProjectNode.SelectedItem as GraphicObject; +// Debug.WriteLine("read {0}.{1}", inst.Name, Name); +// if (!inst.design_members.ContainsKey (Name)) +// return pi.GetValue (inst); +// +// if (inst.design_members [Name].StartsWith ("{")) +// return inst.design_members [Name]; +// else +// return pi.GetValue (inst); + } set { - if (go.design_members.ContainsKey (Name)) { - if (go.design_members [Name] == (string)value) - return; + try { + GraphicObject inst = mview.ProjectNode.SelectedItem as GraphicObject; + string valstr = null; + if (value != null) + valstr = value.ToString(); + if (inst.design_members.ContainsKey (Name)) { + if (inst.design_members [Name] == valstr) + return; + Debug.WriteLine("update {0} : {1} = {2}", inst.Name, Name, valstr); + inst.design_members [Name] = value.ToString(); + } else { + Debug.WriteLine("add {0} : {1} = {2}", inst.Name, Name, valstr); + inst.design_members.Add (Name, value.ToString()); + } + + if (!pi.PropertyType.IsAssignableFrom(value.GetType()) && pi.PropertyType != typeof(string)){ + if (pi.PropertyType.IsEnum) { + if (value is string) { + pi.SetValue (inst, Enum.Parse (pi.PropertyType, (string)value)); + }else + pi.SetValue (inst, value); + } else { + MethodInfo me = pi.PropertyType.GetMethod + ("Parse", BindingFlags.Static | BindingFlags.Public, + System.Type.DefaultBinder, new Type [] {typeof (string)},null); + pi.SetValue (inst, me.Invoke (null, new object[] { value }), null); + } + }else + pi.SetValue(inst, value); + + mview.ProjectNode.Instance.HasChanged = true; + NotifyValueChanged ("Value", value); + NotifyValueChanged ("LabForeground", LabForeground); + } catch (Exception ex) { + System.Diagnostics.Debug.WriteLine ("Error setting property:"+ ex.ToString()); } - go.design_members [Name] = (string)value; -// try { -// if (!pi.PropertyType.IsAssignableFrom(value.GetType()) && pi.PropertyType != typeof(string)){ -// if (pi.PropertyType.IsEnum) { -// if (value is string) { -// pi.SetValue (instance, Enum.Parse (pi.PropertyType, (string)value)); -// }else -// pi.SetValue (instance, value); -// } else { -// MethodInfo me = pi.PropertyType.GetMethod -// ("Parse", BindingFlags.Static | BindingFlags.Public, -// System.Type.DefaultBinder, new Type [] {typeof (string)},null); -// pi.SetValue (instance, me.Invoke (null, new object[] { value }), null); -// } -// }else -// pi.SetValue(instance, value); -// } catch (Exception ex) { -// System.Diagnostics.Debug.WriteLine ("Error setting property:"+ ex.ToString()); -// } - NotifyValueChanged ("Value", value); + // } } + /// + /// for style attribute which is a string, return Style as type + /// public string Type { get { return pi.PropertyType.IsEnum ? "System.Enum" - : pi.PropertyType.FullName; }} + : pi.Name == "Style" ? "Style" : pi.PropertyType.FullName; }} + public object[] Choices { get { return Enum.GetValues (pi.PropertyType).Cast().ToArray(); @@ -84,15 +126,24 @@ namespace Crow.Coding } public Fill LabForeground { - get { return go.design_members.ContainsKey(Name) ? Color.Black : Color.DimGray;} + get { return (mview.ProjectNode.SelectedItem as GraphicObject).design_members.ContainsKey(Name) ? Color.Black : Color.DimGray;} } - public PropertyContainer(PropertyInfo prop, object _instance){ - pi = prop; - instance = _instance; - go = instance as GraphicObject; + /// + /// reset to default value + /// + public void Reset () { + GraphicObject inst = mview.ProjectNode.SelectedItem as GraphicObject; + if (!inst.design_members.ContainsKey (Name)) + return; + inst.design_members.Remove (Name); + //NotifyValueChanged ("Value", Value); + mview.ProjectNode.Instance.HasChanged = true; + //should reinstantiate to get default } + + } } diff --git a/CrowIDE/src/SourceEditor/SourceEditor.cs b/CrowIDE/src/SourceEditor/SourceEditor.cs index db83b2ba..d594776e 100644 --- a/CrowIDE/src/SourceEditor/SourceEditor.cs +++ b/CrowIDE/src/SourceEditor/SourceEditor.cs @@ -86,10 +86,25 @@ namespace Crow.Coding string oldSource = ""; void updateSourceThreadFunc (){ while (true) { - if (projNode != null && buffer != null) { - string newSrc = buffer.FullText; - if (projNode.Source != newSrc) - projNode.Source = newSrc; + if (projFile != null && buffer != null) { + if (!projFile.RegisteredEditors [this]) { + loadSource (); + isDirty = false; + oldSource = projFile.Source; + projFile.RegisteredEditors [this] = true; + } + if (Monitor.TryEnter (buffer.EditMutex)) { + string newsrc = ""; + bool wasDirty = false; + if (isDirty) { + isDirty = false; + wasDirty = true; + newsrc = buffer.FullText; + } + Monitor.Exit (buffer.EditMutex); + if (wasDirty) + projFile.UpdateSource (this, newsrc); + } } Thread.Sleep (100); } @@ -99,7 +114,7 @@ namespace Crow.Coding #region private and protected fields bool foldingEnabled = true; - ProjectFile projNode = null; + ProjectFile projFile = null; int leftMargin = 0; //margin used to display line numbers, folding errors,etc... int visibleLines = 1; int visibleColumns = 1; @@ -203,6 +218,8 @@ namespace Crow.Coding buffer.ToogleFolding (line); } + volatile bool isDirty = false; + #region Buffer events handlers void Buffer_BufferCleared (object sender, EventArgs e) { @@ -213,6 +230,7 @@ namespace Crow.Coding PrintedLines = null; RegisterForGraphicUpdate (); notifyPositionChanged (); + isDirty = true; } void Buffer_LineAdditionEvent (object sender, CodeBufferEventArgs e) { @@ -237,6 +255,7 @@ namespace Crow.Coding updateMaxScrollY (); RegisterForGraphicUpdate (); notifyPositionChanged (); + isDirty = true; } void Buffer_LineRemoveEvent (object sender, CodeBufferEventArgs e) { @@ -254,6 +273,7 @@ namespace Crow.Coding updateMaxScrollY (); RegisterForGraphicUpdate (); notifyPositionChanged (); + isDirty = true; } void Buffer_LineUpadateEvent (object sender, CodeBufferEventArgs e) { @@ -273,6 +293,7 @@ namespace Crow.Coding RegisterForGraphicUpdate (); notifyPositionChanged (); + isDirty = true; } void Buffer_PositionChanged (object sender, EventArgs e) { @@ -356,39 +377,45 @@ namespace Crow.Coding public ProjectFile ProjectNode { get { - return projNode; + return projFile; } set { - if (projNode == value) + if (projFile == value) return; - projNode = value; + if (projFile != null) + projFile.UnregisterEditor (this); - NotifyValueChanged ("ProjectNode", projNode); + projFile = value; + NotifyValueChanged ("ProjectNode", projFile); - if (projNode == null) - return; - - if (!File.Exists (projNode.AbsolutePath)) + if (projFile == null) return; - parser = getParserFromExt (System.IO.Path.GetExtension (projNode.Extension)); + parser = getParserFromExt (System.IO.Path.GetExtension (projFile.Extension)); - try { - buffer.Load (projNode.Source); - oldSource = projNode.Source; - } catch (Exception ex) { - Debug.WriteLine (ex.ToString ()); - } - - updateMaxScrollY (); - MaxScrollX = Math.Max (0, buffer.longestLineCharCount - visibleColumns); - updatePrintedLines (); + projFile.RegisterEditor (this); - RegisterForGraphicUpdate (); } } + void loadSource () { + + try { + buffer.Load (projFile.Source); + } catch (Exception ex) { + Debug.WriteLine (ex.ToString ()); + } + + projFile.RegisteredEditors [this] = true; + + updateMaxScrollY (); + MaxScrollX = Math.Max (0, buffer.longestLineCharCount - visibleColumns); + updatePrintedLines (); + + RegisterForGraphicUpdate (); + } + [XmlAttributeAttribute][DefaultValue("BlueGray")] public virtual Color SelectionBackground { get { return selBackground; } diff --git a/CrowIDE/ui/CrowIDE.crow b/CrowIDE/ui/CrowIDE.crow index d2be368c..9e2694f9 100644 --- a/CrowIDE/ui/CrowIDE.crow +++ b/CrowIDE/ui/CrowIDE.crow @@ -42,7 +42,8 @@ Data="{Projects}" SelectedItemChanged="onSelectedItemChanged" ItemTemplate="#Crow.Coding.ui.ProjectTree.template"/> - diff --git a/CrowIDE/ui/EditPaneItems.template b/CrowIDE/ui/EditPaneItems.template index af7e7d10..e5e9b280 100644 --- a/CrowIDE/ui/EditPaneItems.template +++ b/CrowIDE/ui/EditPaneItems.template @@ -1,15 +1,15 @@ - + - + - - - - + + + + diff --git a/CrowIDE/ui/IDE.style b/CrowIDE/ui/IDE.style index 3dce97fa..d7212053 100644 --- a/CrowIDE/ui/IDE.style +++ b/CrowIDE/ui/IDE.style @@ -15,3 +15,11 @@ MemberViewHStack { MouseEnter={Background=UnitedNationsBlue}; MouseLeave={Background=Transparent}; } + +IcoBut { + Template = #Crow.Coding.ui.IcoBut.template; + MinimumSize = 10,10; + Width = 8; + Height = 14; + Background = White; +} \ No newline at end of file diff --git a/CrowIDE/ui/IcoBut.template b/CrowIDE/ui/IcoBut.template new file mode 100644 index 00000000..a9fc28a7 --- /dev/null +++ b/CrowIDE/ui/IcoBut.template @@ -0,0 +1,7 @@ + + + + diff --git a/CrowIDE/ui/MembersItem.template b/CrowIDE/ui/MembersItem.template old mode 100644 new mode 100755 index 5c564061..cc653ef8 --- a/CrowIDE/ui/MembersItem.template +++ b/CrowIDE/ui/MembersItem.template @@ -1,18 +1,18 @@ - + - + - - + + - + @@ -61,17 +61,17 @@ - +