From 27232cfa68a07db1286331ca93fe9067a46fda9b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jean-Philippe=20Bruy=C3=A8re?= Date: Sun, 4 Mar 2018 11:28:09 +0100 Subject: [PATCH] crowIde wip, docker wip, stack remove child debug --- Crow.csproj | 2 + CrowIDE/CrowIDE.csproj | 6 +- CrowIDE/src/CrowIDE.cs | 7 +- CrowIDE/src/ImlVisualEditor.cs | 2 +- CrowIDE/src/MemberView/CategoryContainer.cs | 65 ++++ CrowIDE/src/{ => MemberView}/MembersView.cs | 9 +- .../src/{ => MemberView}/PropertyContainer.cs | 135 +++++--- CrowIDE/src/Project.cs | 22 +- CrowIDE/src/ProjectNodes.cs | 28 +- CrowIDE/src/Solution.cs | 18 +- CrowIDE/src/SourceEditor/CodeBuffer.cs | 42 ++- CrowIDE/src/SourceEditor/SourceEditor.cs | 45 ++- CrowIDE/ui/MembersItem.template | 22 ++ CrowIDE/ui/ProjectTree.template | 8 +- CrowIDE/ui/SrcEdit.itemp | 9 +- Default.style | 23 +- Templates/DockWindow.template | 32 +- Tests/Interfaces/Experimental/testDock.crow | 25 +- Tests/Interfaces/Experimental/testStack.crow | 32 ++ Tests/Tests.csproj | 3 + src/CompilerServices/CompilerServices.cs | 5 + src/GraphicObjects/ColorPicker.cs | 6 +- src/GraphicObjects/DockStack.cs | 299 ++++++++++++++++++ src/GraphicObjects/DockWindow.cs | 195 ++++-------- src/GraphicObjects/Docker.cs | 191 +++++------ src/GraphicObjects/Expandable.cs | 2 +- src/GraphicObjects/GenericStack.cs | 97 +++--- src/GraphicObjects/GraphicObject.cs | 186 +++++++---- src/GraphicObjects/Group.cs | 15 +- src/GraphicObjects/PrivateContainer.cs | 8 +- src/GraphicObjects/TemplatedGroup.cs | 5 +- src/GraphicObjects/Wrapper.cs | 14 +- src/IMLAttributes.cs | 40 +++ src/Instantiator.cs | 33 +- src/Interface.cs | 19 +- src/Measure.cs | 1 + src/StyleReader.cs | 2 +- 37 files changed, 1169 insertions(+), 484 deletions(-) create mode 100644 CrowIDE/src/MemberView/CategoryContainer.cs rename CrowIDE/src/{ => MemberView}/MembersView.cs (89%) rename CrowIDE/src/{ => MemberView}/PropertyContainer.cs (58%) create mode 100644 Tests/Interfaces/Experimental/testStack.crow create mode 100644 src/GraphicObjects/DockStack.cs create mode 100644 src/IMLAttributes.cs diff --git a/Crow.csproj b/Crow.csproj index 91b16e31..7a0ffada 100644 --- a/Crow.csproj +++ b/Crow.csproj @@ -223,6 +223,8 @@ + + diff --git a/CrowIDE/CrowIDE.csproj b/CrowIDE/CrowIDE.csproj index 9a9a222f..0a8150e4 100644 --- a/CrowIDE/CrowIDE.csproj +++ b/CrowIDE/CrowIDE.csproj @@ -77,7 +77,6 @@ - @@ -115,8 +114,10 @@ - + + + @@ -124,6 +125,7 @@ + diff --git a/CrowIDE/src/CrowIDE.cs b/CrowIDE/src/CrowIDE.cs index c08dd663..6f6e376b 100644 --- a/CrowIDE/src/CrowIDE.cs +++ b/CrowIDE/src/CrowIDE.cs @@ -103,13 +103,16 @@ namespace Crow.Coding //this.CrowInterface.LoadInterface ("#Crow.Coding.ui.imlEditor.crow").DataSource = this; //GraphicObject go = this.CrowInterface.LoadInterface (@"ui/test.crow"); GraphicObject go = AddWidget (@"#Crow.Coding.ui.CrowIDE.crow"); + go.DataSource = this; MainIFace = ifaceControl[0].CrowInterface; - if (ReopenLastSolution && !string.IsNullOrEmpty(LastOpenSolution)) + if (ReopenLastSolution && !string.IsNullOrEmpty (LastOpenSolution)) { CurrentSolution = Solution.LoadSolution (LastOpenSolution); + //lock(MainIFace.UpdateMutex) + CurrentSolution.ReopenItemsSavedInUserConfig (); + } - go.DataSource = this; instFileDlg = Instantiator.CreateFromImlFragment (MainIFace, ""); diff --git a/CrowIDE/src/ImlVisualEditor.cs b/CrowIDE/src/ImlVisualEditor.cs index 69ae5515..c9e5484e 100644 --- a/CrowIDE/src/ImlVisualEditor.cs +++ b/CrowIDE/src/ImlVisualEditor.cs @@ -158,7 +158,7 @@ namespace Crow.Coding SelectedItem = go; IMLError = null; projFile.RegisteredEditors[this] = true; - }else if ((bool)projFile.Instance?.HasChanged){ + }else if ((bool)projFile.Instance?.design_HasChanged){ projFile.UpdateSource(this, projFile.Instance.GetIML()); } imlVE.Update (); diff --git a/CrowIDE/src/MemberView/CategoryContainer.cs b/CrowIDE/src/MemberView/CategoryContainer.cs new file mode 100644 index 00000000..fbf3fe2c --- /dev/null +++ b/CrowIDE/src/MemberView/CategoryContainer.cs @@ -0,0 +1,65 @@ +// +// CategoryContainer.cs +// +// Author: +// Jean-Philippe Bruyère +// +// Copyright (c) 2013-2017 Jean-Philippe Bruyère +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace Crow.Coding +{ + public class CategoryContainer : IValueChange + { + #region IValueChange implementation + public event EventHandler ValueChanged; + public virtual void NotifyValueChanged(string MemberName, object _value) + { + ValueChanged.Raise(this, new ValueChangeEventArgs(MemberName, _value)); + } + #endregion + + bool _isExpanded = true; + + public PropertyContainer[] Properties; + public string Name; + + public bool IsExpanded + { + get { return _isExpanded; } + set + { + if (value == _isExpanded) + return; + + _isExpanded = value; + + NotifyValueChanged ("IsExpanded", _isExpanded); + } + } + + public CategoryContainer (string categoryName, PropertyContainer[] properties){ + Name = categoryName; + Properties = properties; + } + } +} + diff --git a/CrowIDE/src/MembersView.cs b/CrowIDE/src/MemberView/MembersView.cs similarity index 89% rename from CrowIDE/src/MembersView.cs rename to CrowIDE/src/MemberView/MembersView.cs index f0c3a13a..65dc9595 100644 --- a/CrowIDE/src/MembersView.cs +++ b/CrowIDE/src/MemberView/MembersView.cs @@ -38,6 +38,7 @@ namespace Crow.Coding //cache property containers per type Dictionary propContainersCache = new Dictionary(); + Dictionary> categoryContainersCache = new Dictionary> (); [XmlAttributeAttribute][DefaultValue(null)] public virtual object Instance { @@ -78,7 +79,13 @@ namespace Crow.Coding propContainersCache.Add (it.FullName, props.OrderBy (p => p.Name).ToArray ()); } - Data = propContainersCache [it.FullName]; + List categories = new List (); + + foreach (IGrouping ig in propContainersCache[it.FullName].GroupBy(pc=>pc.DesignCategory)) { + categories.Add(new CategoryContainer(ig.Key, ig.ToArray())); + } + + Data = categories; if (lastInst != instance) { foreach (PropertyContainer pc in propContainersCache [it.FullName]) { diff --git a/CrowIDE/src/PropertyContainer.cs b/CrowIDE/src/MemberView/PropertyContainer.cs similarity index 58% rename from CrowIDE/src/PropertyContainer.cs rename to CrowIDE/src/MemberView/PropertyContainer.cs index c89273cc..46cbbd74 100644 --- a/CrowIDE/src/PropertyContainer.cs +++ b/CrowIDE/src/MemberView/PropertyContainer.cs @@ -28,9 +28,10 @@ using System.Reflection; using System.Linq; using System.Collections.Generic; using System.Diagnostics; +using System.ComponentModel; namespace Crow.Coding -{ +{ public class PropertyContainer : IValueChange { #region IValueChange implementation @@ -41,71 +42,82 @@ namespace Crow.Coding } #endregion - public List Commands; - Command cmdReset, cmdGoToStyle; PropertyInfo pi; MembersView mview; -// object instance; -// GraphicObject go; + Command cmdReset, cmdGoToStyle; + + public List Commands; + #region CTOR public PropertyContainer(MembersView mv, PropertyInfo prop){ mview = mv; pi = prop; -// instance = _instance; -// go = instance as GraphicObject; cmdReset = new Crow.Command (new Action (() => Reset ())) { Caption = "Reset to default" }; cmdGoToStyle = new Crow.Command (new Action (() => GotoStyle ())) { Caption = "Goto style" }; Commands = new List (new Crow.Command[] { cmdReset, cmdGoToStyle }); } + #endregion + public string DesignCategory { + get { + DesignCategory dca = (DesignCategory)pi.GetCustomAttribute (typeof(DesignCategory)); + return dca == null ? "Divers" : dca.Name; + } + } public string Name { get { return pi.Name; }} public object Value { 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); + return mview.ProjectNode.SelectedItem == null ? null : pi.GetValue(mview.ProjectNode.SelectedItem); } set { try { - GraphicObject inst = mview.ProjectNode.SelectedItem as GraphicObject; - string valstr = null; + GraphicObject g = Instance; + string valstr = null, oldval = null; + if (value != null) valstr = value.ToString(); - if (inst.design_members.ContainsKey (Name)) { - if (inst.design_members [Name] == valstr) + + if (HasStyling) + oldval = g.design_style_values[Name]; + else if (HasDefaultValue) + oldval = DefaultValue?.ToString(); + else if (IsSetByIML) + oldval = g.design_iml_values [Name]; + + if (valstr == oldval){ + if (IsSetByIML){ + g.design_iml_values.Remove(Name); + Debug.WriteLine("iml attrib removed {0}.{1}", g.Name, Name); + }else 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()); - } + }else{ + if (IsSetByIML){ + g.design_iml_values [Name] = valstr; + Debug.WriteLine("iml update {0}.{1} = {2}", g.Name, Name, valstr); + }else{ + g.design_iml_values.Add(Name,valstr); + Debug.WriteLine("iml add {0}.{1} = {2}", g.Name, Name, valstr); + } + } 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)); + pi.SetValue (g, Enum.Parse (pi.PropertyType, (string)value)); }else - pi.SetValue (inst, value); + pi.SetValue (g, 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); + pi.SetValue (g, me.Invoke (null, new object[] { value }), null); } }else - pi.SetValue(inst, value); + pi.SetValue(g, value); - mview.ProjectNode.Instance.HasChanged = true; + mview.ProjectNode.Instance.design_HasChanged = true; NotifyValueChanged ("Value", value); NotifyValueChanged ("LabForeground", LabForeground); } catch (Exception ex) { @@ -128,12 +140,40 @@ namespace Crow.Coding mview.ProjectNode.Project.solution.AvailaibleStyles; } } + /// + /// Current graphicobject instance + /// + public GraphicObject Instance { + get { return mview.ProjectNode.SelectedItem as GraphicObject; } + } + public object DefaultValue { + get { return ((DefaultValueAttribute)(pi.GetCustomAttribute (typeof (DefaultValueAttribute)))).Value; } + } + public bool HasDefaultValue { + get { return pi.GetCustomAttribute (typeof(DefaultValueAttribute))!=null; } + } + /// + /// return true if current value comes from IML attributes + /// + public bool IsSetByIML { + get { return Instance.design_iml_values.ContainsKey (Name); } + } + /// + /// return true if member default value comes from style + /// + public bool HasStyling { + get { return Instance.design_style_locations.ContainsKey(Name); } + } + /// + /// Return true if current value comes from styling + /// + public bool IsSetByStyling { + get { return IsSetByIML ? false : HasStyling; } + } + public Fill LabForeground { - get { - GraphicObject go = mview.ProjectNode.SelectedItem as GraphicObject; - return go.design_members.ContainsKey (Name) ? Color.Black : - go.design_defaults.ContainsKey(Name) ? Color.DarkBlue : Color.DimGray;} + get { return IsSetByIML ? Color.DarkBlue : HasStyling ? Color.Black : Color.DimGray;} } /// @@ -141,29 +181,32 @@ namespace Crow.Coding /// public void Reset () { GraphicObject inst = mview.ProjectNode.SelectedItem as GraphicObject; - if (!inst.design_members.ContainsKey (Name)) + if (!inst.design_iml_values.ContainsKey (Name)) return; - inst.design_members.Remove (Name); + inst.design_iml_values.Remove (Name); //NotifyValueChanged ("Value", Value); - mview.ProjectNode.Instance.HasChanged = true; + mview.ProjectNode.Instance.design_HasChanged = true; //should reinstantiate to get default } public void GotoStyle(){ - GraphicObject inst = mview.ProjectNode.SelectedItem as GraphicObject; - if (!inst.design_defaults.ContainsKey (Name)) + GraphicObject g = Instance; + if (!g.design_style_locations.ContainsKey (Name)) return; - FileLocation fl = inst.design_defaults [Name]; + FileLocation fl = g.design_style_locations [Name]; ProjectFile pf; if (!mview.ProjectNode.Project.TryGetProjectFileFromPath ("#" + fl.FilePath, out pf)) return; Solution s = mview.ProjectNode.Project.solution; if (!s.OpenedItems.Contains (pf)) - s.OpenedItems.Add (pf); - //pf.CurrentLine = fl.Line; - //pf.CurrentColumn = fl.Column; + s.OpenedItems.AddElement (pf); + pf.CurrentLine = fl.Line; + pf.CurrentColumn = fl.Column; } - + public override string ToString () + { + return string.Format ("{0} = {1}", Name, Value); + } } } diff --git a/CrowIDE/src/Project.cs b/CrowIDE/src/Project.cs index ff3469de..5e6c98d9 100644 --- a/CrowIDE/src/Project.cs +++ b/CrowIDE/src/Project.cs @@ -46,6 +46,7 @@ namespace Crow.Coding #endregion bool isLoaded = false; + bool isExpanded; XmlDocument xmlDoc; XmlNode nodeProject; XmlNode nodeProps; @@ -72,6 +73,17 @@ namespace Crow.Coding NotifyValueChanged ("IsLoaded", isLoaded); } } + public bool IsExpanded + { + get { return isExpanded; } + set + { + if (value == isExpanded) + return; + isExpanded = value; + NotifyValueChanged ("IsExpanded", isExpanded); + } + } public bool IsStartupProject { get { return solution.StartupProject == this; } } @@ -100,17 +112,17 @@ namespace Crow.Coding flattenNodes = new List (); ProjectNode refs = new ProjectNode (this, ItemType.ReferenceGroup, "References"); - root.ChildNodes.Add (refs); + root.AddChild (refs); foreach (ProjectItem pn in items) { switch (pn.Type) { case ItemType.Reference: - refs.ChildNodes.Add (pn); + refs.AddChild (pn); flattenNodes.Add (pn); break; case ItemType.ProjectReference: ProjectReference pr = new ProjectReference (pn); - refs.ChildNodes.Add (pr); + refs.AddChild (pr); flattenNodes.Add (pr); break; case ItemType.Compile: @@ -122,7 +134,7 @@ namespace Crow.Coding ProjectNode nextNode = curNode.ChildNodes.FirstOrDefault (n => n.DisplayName == folds [i] && n.Type == ItemType.VirtualGroup); if (nextNode == null) { nextNode = new ProjectNode (this, ItemType.VirtualGroup, folds [i]); - curNode.ChildNodes.Add (nextNode); + curNode.AddChild (nextNode); } curNode = nextNode; } @@ -136,7 +148,7 @@ namespace Crow.Coding f = new ProjectFile (pn); break; } - curNode.ChildNodes.Add (f); + curNode.AddChild (f); flattenNodes.Add (f); break; } diff --git a/CrowIDE/src/ProjectNodes.cs b/CrowIDE/src/ProjectNodes.cs index c3348266..bf213c27 100644 --- a/CrowIDE/src/ProjectNodes.cs +++ b/CrowIDE/src/ProjectNodes.cs @@ -74,6 +74,8 @@ namespace Crow.Coding Commands = new List (); } + ProjectNode parent; + bool isExpanded; ItemType type; string name; List childNodes = new List(); @@ -81,6 +83,10 @@ namespace Crow.Coding public Project Project; public List Commands;//list of command available for that node + public ProjectNode Parent { + get { return parent; } + set { parent = value; } + } public virtual ItemType Type { get { return type; } } @@ -90,12 +96,32 @@ namespace Crow.Coding public List ChildNodes { get { return childNodes; } } - + public void AddChild (ProjectNode pn) { + childNodes.Add(pn); + pn.Parent = this; + } + public void RemoveChild (ProjectNode pn){ + pn.Parent = null; + childNodes.Remove (pn); + } public void SortChilds () { foreach (ProjectNode pn in childNodes) pn.SortChilds (); childNodes = childNodes.OrderBy(c=>c.Type).ThenBy(cn=>cn.DisplayName).ToList(); } + + public bool IsExpanded + { + get { return isExpanded; } + set + { + if (value == isExpanded) + return; + isExpanded = value; + NotifyValueChanged ("IsExpanded", isExpanded); + } + } + public override string ToString () { return DisplayName; diff --git a/CrowIDE/src/Solution.cs b/CrowIDE/src/Solution.cs index 7ed6b780..b1ccedca 100644 --- a/CrowIDE/src/Solution.cs +++ b/CrowIDE/src/Solution.cs @@ -138,10 +138,13 @@ namespace Crow.Coding{ NotifyValueChanged ("CompilerErrors", CompilerErrors); } - void saveOpenedItemsInUserConfig (){ - UserConfig.Set ("OpenedItems", openedItems.Select(o => o.AbsolutePath).Aggregate((a,b)=>a + ";" + b)); + void saveOpenedItemsInUserConfig (){ + if (openedItems.Count == 0) + UserConfig.Set ("OpenedItems", ""); + else + UserConfig.Set ("OpenedItems", openedItems.Select(o => o.AbsolutePath).Aggregate((a,b)=>a + ";" + b)); } - void reopenItemsSavedInUserConfig () { + public void ReopenItemsSavedInUserConfig () { string tmp = UserConfig.Get ("OpenedItems"); string sel = UserConfig.Get ("SelectedProjItems"); ProjectFile selItem = null; @@ -151,7 +154,13 @@ namespace Crow.Coding{ foreach (Project p in Projects) { ProjectFile pi; if (p.TryGetProjectFileFromAbsolutePath (f, out pi)) { - OpenedItems.Add (pi); + OpenedItems.AddElement (pi); + pi.Project.IsExpanded = true; + ProjectNode pn = pi.Parent; + while (pn != null) { + pn.IsExpanded = true; + pn = pn.Parent; + } if (pi.AbsolutePath == sel) selItem = pi; break; @@ -442,7 +451,6 @@ namespace Crow.Coding{ s.UserConfig = new Configuration (s.path + ".user"); s.ReloadStyling (); s.ReloadDefaultTemplates (); - s.reopenItemsSavedInUserConfig (); return s; } //LoadSolution #endregion diff --git a/CrowIDE/src/SourceEditor/CodeBuffer.cs b/CrowIDE/src/SourceEditor/CodeBuffer.cs index 66c24857..ec9bbc3e 100644 --- a/CrowIDE/src/SourceEditor/CodeBuffer.cs +++ b/CrowIDE/src/SourceEditor/CodeBuffer.cs @@ -69,70 +69,70 @@ namespace Crow.Coding return; editMutex.EnterWriteLock (); lines [i] = value; - LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i)); editMutex.ExitWriteLock (); + LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i)); } } public void RemoveAt(int i){ editMutex.EnterWriteLock (); lines.RemoveAt (i); - LineRemoveEvent.Raise (this, new CodeBufferEventArgs (i)); editMutex.ExitWriteLock (); + LineRemoveEvent.Raise (this, new CodeBufferEventArgs (i)); } public void Insert(int i, string item){ editMutex.EnterWriteLock (); lines.Insert (i, item); - LineAdditionEvent.Raise (this, new CodeBufferEventArgs (i)); editMutex.ExitWriteLock (); + LineAdditionEvent.Raise (this, new CodeBufferEventArgs (i)); } public void Add(CodeLine item){ editMutex.EnterWriteLock (); lines.Add (item); - LineAdditionEvent.Raise (this, new CodeBufferEventArgs (lines.Count - 1)); editMutex.ExitWriteLock (); + LineAdditionEvent.Raise (this, new CodeBufferEventArgs (lines.Count - 1)); } public void AddRange (string[] items){ int start = lines.Count; editMutex.EnterWriteLock (); for (int i = 0; i < items.Length; i++) lines.Add (items [i]); - LineAdditionEvent.Raise (this, new CodeBufferEventArgs (start, items.Length)); editMutex.ExitWriteLock (); + LineAdditionEvent.Raise (this, new CodeBufferEventArgs (start, items.Length)); } public void AddRange (CodeLine[] items){ int start = lines.Count; editMutex.EnterWriteLock (); lines.AddRange (items); - LineAdditionEvent.Raise (this, new CodeBufferEventArgs (start, items.Length)); editMutex.ExitWriteLock (); + LineAdditionEvent.Raise (this, new CodeBufferEventArgs (start, items.Length)); } public void Clear () { editMutex.EnterWriteLock (); longestLineCharCount = 0; lines.Clear (); - BufferCleared.Raise (this, null); editMutex.ExitWriteLock (); + BufferCleared.Raise (this, null); } public void UpdateLine(int i, string newContent){ editMutex.EnterWriteLock (); this [i].Content = newContent; - LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i)); editMutex.ExitWriteLock (); + LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i)); } public void AppenedLine(int i, string newContent){ editMutex.EnterWriteLock (); this [i].Content += newContent; - LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i)); editMutex.ExitWriteLock (); + LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i)); } public void ToogleFolding (int line) { if (!this [line].IsFoldable) return; editMutex.EnterWriteLock (); this [line].IsFolded = !this [line].IsFolded; - FoldingEvent.Raise (this, new CodeBufferEventArgs (line)); editMutex.ExitWriteLock (); + FoldingEvent.Raise (this, new CodeBufferEventArgs (line)); } public void Load(string rawSource, string lineBrkRegex = @"\r\n|\r|\n|\\\n") { this.Clear(); @@ -150,13 +150,15 @@ namespace Crow.Coding /// public void FindLongestVisualLine(){ longestLineCharCount = 0; + editMutex.EnterReadLock (); for (int i = 0; i < this.LineCount; i++) { if (lines[i].PrintableLength > longestLineCharCount) { longestLineCharCount = lines[i].PrintableLength; longestLineIdx = i; } } - Debug.WriteLine ("Longest line: {0}->{1}", longestLineIdx, longestLineCharCount); + editMutex.ExitReadLock (); + //Debug.WriteLine ("Longest line: {0}->{1}", longestLineIdx, longestLineCharCount); } /// line break could be '\r' or '\n' or '\r\n' static string detectLineBreakKind(string buffer){ @@ -190,9 +192,11 @@ namespace Crow.Coding if (lines.Count == 0) return ""; string tmp = ""; + editMutex.EnterReadLock (); for (int i = 0; i < lines.Count -1; i++) tmp += lines [i].Content + this.lineBreak; tmp += lines [lines.Count - 1].Content; + editMutex.ExitReadLock (); return tmp; } } @@ -203,12 +207,14 @@ namespace Crow.Coding public int UnfoldedLines { get { int i = 0, vl = 0; + editMutex.EnterReadLock (); while (i < LineCount) { if (this [i].IsFolded) i = GetEndNodeIndex (i); i++; vl++; } + editMutex.ExitReadLock (); //Debug.WriteLine ("unfolded lines: " + vl); return vl; } @@ -249,7 +255,7 @@ namespace Crow.Coding return i; } - int CurrentTabulatedColumn { + public int CurrentTabulatedColumn { get { return lines [_currentLine].Content.Substring (0, _currentCol). Replace ("\t", new String (' ', Interface.TabSize)).Length; @@ -330,6 +336,9 @@ namespace Crow.Coding set { if (value == _currentCol) return; + + editMutex.EnterReadLock (); + if (value < 0) _currentCol = 0; else if (value > lines [_currentLine].Length) @@ -338,7 +347,8 @@ namespace Crow.Coding _currentCol = value; requestedColumn = CurrentTabulatedColumn; - //requestedColumn = _currentCol; + + editMutex.ExitReadLock (); PositionChanged.Raise (this, null); } @@ -351,6 +361,9 @@ namespace Crow.Coding set { if (value == _currentLine) return; + + editMutex.EnterReadLock (); + if (value >= lines.Count) _currentLine = lines.Count-1; else if (value < 0) @@ -366,6 +379,9 @@ namespace Crow.Coding //_currentCol = requestedColumn; _currentCol = tabulatedRequestedCol; //Debug.WriteLine ("buff cur line: " + _currentLine); + + editMutex.ExitReadLock(); + PositionChanged.Raise (this, null); } } diff --git a/CrowIDE/src/SourceEditor/SourceEditor.cs b/CrowIDE/src/SourceEditor/SourceEditor.cs index b0e8a35f..1264f4a1 100644 --- a/CrowIDE/src/SourceEditor/SourceEditor.cs +++ b/CrowIDE/src/SourceEditor/SourceEditor.cs @@ -44,6 +44,8 @@ namespace Crow.Coding /// public class SourceEditor : ScrollingObject { + public ReaderWriterLockSlim seMutex = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); + #region CTOR public SourceEditor (): base() { @@ -91,6 +93,8 @@ namespace Crow.Coding loadSource (); isDirty = false; oldSource = projFile.Source; + CurrentLine = requestedLine; + CurrentColumn = requestedCol; projFile.RegisteredEditors [this] = true; } buffer.editMutex.EnterWriteLock (); @@ -153,7 +157,7 @@ namespace Crow.Coding } void findLongestLineAndUpdateMaxScrollX() { buffer.FindLongestVisualLine (); - MaxScrollX = Math.Max (0, buffer.longestLineCharCount - visibleColumns); + updateMaxScrollX (); // Debug.WriteLine ("SourceEditor: Find Longest line and update maxscrollx: {0} visible cols:{1}", MaxScrollX, visibleColumns); } /// @@ -170,11 +174,16 @@ namespace Crow.Coding } void updateVisibleColumns(){ visibleColumns = (int)Math.Floor ((double)(ClientRectangle.Width - leftMargin)/ fe.MaxXAdvance); - MaxScrollX = Math.Max (0, buffer.longestLineCharCount - visibleColumns); - + NotifyValueChanged ("VisibleColumns", visibleColumns); + updateMaxScrollX (); // System.Diagnostics.Debug.WriteLine ("update visible columns: {0} leftMargin:{1}",visibleColumns, leftMargin); // System.Diagnostics.Debug.WriteLine ("update MaxScrollX: " + MaxScrollX); } + void updateMaxScrollX () { + MaxScrollX = Math.Max (0, buffer.longestLineCharCount - visibleColumns); + if (buffer.longestLineCharCount > 0) + NotifyValueChanged ("ChildWidthRatio", Slot.Width * visibleColumns / buffer.longestLineCharCount); + } void updateMaxScrollY () { if (parser == null || !foldingEnabled) { MaxScrollY = Math.Max (0, buffer.LineCount - visibleLines); @@ -188,6 +197,8 @@ namespace Crow.Coding } void updatePrintedLines () { buffer.editMutex.EnterReadLock (); + seMutex.EnterWriteLock (); + PrintedLines = new List (); int curL = 0; int i = 0; @@ -210,7 +221,9 @@ namespace Crow.Coding curL++; i++; } + buffer.editMutex.ExitReadLock (); + seMutex.ExitWriteLock (); } void toogleFolding (int line) { if (parser == null || !foldingEnabled) @@ -223,6 +236,8 @@ namespace Crow.Coding #region Buffer events handlers void Buffer_BufferCleared (object sender, EventArgs e) { + seMutex.EnterWriteLock (); + buffer.longestLineCharCount = 0; buffer.longestLineIdx = 0; measureLeftMargin (); @@ -231,6 +246,8 @@ namespace Crow.Coding RegisterForGraphicUpdate (); notifyPositionChanged (); isDirty = true; + + seMutex.ExitWriteLock (); } void Buffer_LineAdditionEvent (object sender, CodeBufferEventArgs e) { @@ -297,6 +314,14 @@ namespace Crow.Coding } void Buffer_PositionChanged (object sender, EventArgs e) { + Console.WriteLine ("Position changes: ({0},{1})", buffer.CurrentLine, buffer.CurrentColumn); + int cc = buffer.CurrentTabulatedColumn; + + if (cc > visibleColumns + ScrollX) { + ScrollX = cc - visibleColumns; + } else if (cc < ScrollX) + ScrollX = cc; + RegisterForGraphicUpdate (); updateOnScreenCurLineFromBuffCurLine (); notifyPositionChanged (); @@ -318,22 +343,29 @@ namespace Crow.Coding public int CurrentColumn{ get { return buffer == null ? 0 : buffer.CurrentColumn+1; } set { - try { + try { + if (value - 1 == buffer.CurrentColumn) + return; buffer.CurrentColumn = value - 1; } catch (Exception ex) { + requestedCol = value - 1; Console.WriteLine ("Error cur column: " + ex.ToString ()); } } } + int requestedLine = 0, requestedCol = 0; public int CurrentLine{ get { return buffer == null ? 0 : buffer.CurrentLine+1; } set { try { int l = value - 1; + if (l == buffer.CurrentLine) + return; buffer.CurrentLine = l; if (buffer [l].IsFolded) buffer.ToogleFolding (l); } catch (Exception ex) { + requestedLine = value - 1; Console.WriteLine ("Error cur column: " + ex.ToString ()); } } @@ -800,6 +832,8 @@ namespace Crow.Coding } #endregion + seMutex.EnterReadLock (); + if (PrintedLines != null) { for (int i = 0; i < visibleLines; i++) { if (i + ScrollY >= buffer.UnfoldedLines)//TODO:need optimize @@ -807,6 +841,9 @@ namespace Crow.Coding drawLine (gr, cb, i); } } + + seMutex.ExitReadLock (); + buffer.editMutex.ExitReadLock (); } diff --git a/CrowIDE/ui/MembersItem.template b/CrowIDE/ui/MembersItem.template index 812d7884..3a977490 100755 --- a/CrowIDE/ui/MembersItem.template +++ b/CrowIDE/ui/MembersItem.template @@ -5,6 +5,28 @@ + + + + + + - +