From 523d7278ae482d18bf4b6d1eb053f1fbd5ab9c2f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jean-Philippe=20Bruy=C3=A8re?= Date: Fri, 2 Mar 2018 07:53:54 +0100 Subject: [PATCH] CrowIDE wip, removed key repeat already handled by otk --- CrowIDE/src/EditPane.cs | 8 ++ CrowIDE/src/ImlVisualEditor.cs | 1 + CrowIDE/src/Project.cs | 9 +- CrowIDE/src/ProjectNodes.cs | 6 +- CrowIDE/src/PropertyContainer.cs | 28 ++++- CrowIDE/src/Solution.cs | 41 ++++++- CrowIDE/src/SourceEditor/CSharpParser.cs | 2 +- CrowIDE/src/SourceEditor/CodeBuffer.cs | 143 ++++++++++++----------- CrowIDE/src/SourceEditor/SourceEditor.cs | 102 ++++++++-------- CrowIDE/src/SourceEditor/StyleParser.cs | 2 +- CrowIDE/src/SourceEditor/XMLParser.cs | 2 +- CrowIDE/ui/CrowIDE.crow | 2 +- src/Configuration.cs | 3 +- src/GraphicObjects/GraphicObject.cs | 117 ++++++++++--------- src/GraphicObjects/TemplatedGroup.cs | 2 +- src/Interface.cs | 26 ++--- src/ParsingException.cs | 8 +- src/Style.cs | 21 +++- src/StyleReader.cs | 32 +++-- 19 files changed, 318 insertions(+), 237 deletions(-) diff --git a/CrowIDE/src/EditPane.cs b/CrowIDE/src/EditPane.cs index 780e86d5..a75522f0 100644 --- a/CrowIDE/src/EditPane.cs +++ b/CrowIDE/src/EditPane.cs @@ -35,6 +35,14 @@ namespace Crow.Coding object selectedItemElement = null; + public override int SelectedIndex { + get { + return base.SelectedIndex; + } + set { + base.SelectedIndex = value; + } + } public object SelectedItemElement { get { return selectedItemElement; } set { diff --git a/CrowIDE/src/ImlVisualEditor.cs b/CrowIDE/src/ImlVisualEditor.cs index 7989936a..69ae5515 100644 --- a/CrowIDE/src/ImlVisualEditor.cs +++ b/CrowIDE/src/ImlVisualEditor.cs @@ -147,6 +147,7 @@ namespace Crow.Coding imlVE.ClearInterface(); Instantiator.NextInstantiatorID = 0; imlVE.Styling = projFile.Project.solution.Styling; + imlVE.DefaultValuesLoader.Clear(); imlVE.DefaultTemplates = projFile.Project.solution.DefaultTemplates; imlVE.Instantiators = new Dictionary(); imlVE.LoadIMLFragment(projFile.Source); diff --git a/CrowIDE/src/Project.cs b/CrowIDE/src/Project.cs index 0da5dc19..ff3469de 100644 --- a/CrowIDE/src/Project.cs +++ b/CrowIDE/src/Project.cs @@ -377,7 +377,12 @@ namespace Crow.Coding return parameters.OutputAssembly; } - public bool GetProjectFileFromPath (string path, out ProjectFile pi){ + public bool TryGetProjectFileFromAbsolutePath (string absolutePath, out ProjectFile pi){ + pi = flattenNodes.OfType ().FirstOrDefault + (pp => pp.AbsolutePath == absolutePath); + return pi != null; + } + public bool TryGetProjectFileFromPath (string path, out ProjectFile pi){ if (path.StartsWith ("#")) pi = flattenNodes.OfType ().FirstOrDefault (pp => pp.Type == ItemType.EmbeddedResource && pp.ResourceID == path.Substring (1)); @@ -391,7 +396,7 @@ namespace Crow.Coding Project p = solution.Projects.FirstOrDefault (pp => pp.ProjectGuid == pr.ProjectGUID); if (p == null) throw new Exception ("referenced project not found"); - if (p.GetProjectFileFromPath (path, out pi)) + if (p.TryGetProjectFileFromPath (path, out pi)) return true; } //TODO: search referenced assemblies diff --git a/CrowIDE/src/ProjectNodes.cs b/CrowIDE/src/ProjectNodes.cs index 4f24060f..c3348266 100644 --- a/CrowIDE/src/ProjectNodes.cs +++ b/CrowIDE/src/ProjectNodes.cs @@ -95,7 +95,11 @@ namespace Crow.Coding foreach (ProjectNode pn in childNodes) pn.SortChilds (); childNodes = childNodes.OrderBy(c=>c.Type).ThenBy(cn=>cn.DisplayName).ToList(); - } + } + public override string ToString () + { + return DisplayName; + } } public class ProjectItem : ProjectNode { #region CTOR diff --git a/CrowIDE/src/PropertyContainer.cs b/CrowIDE/src/PropertyContainer.cs index 298dcd15..c89273cc 100644 --- a/CrowIDE/src/PropertyContainer.cs +++ b/CrowIDE/src/PropertyContainer.cs @@ -42,6 +42,7 @@ namespace Crow.Coding #endregion public List Commands; + Command cmdReset, cmdGoToStyle; PropertyInfo pi; MembersView mview; // object instance; @@ -53,9 +54,10 @@ namespace Crow.Coding // instance = _instance; // go = instance as GraphicObject; - Commands = new List (new Crow.Command[] { - new Crow.Command(new Action(() => Reset())) { Caption = "Reset to default"}, - }); + 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 }); } public string Name { get { return pi.Name; }} @@ -128,7 +130,10 @@ namespace Crow.Coding } public Fill LabForeground { - get { return (mview.ProjectNode.SelectedItem as GraphicObject).design_members.ContainsKey(Name) ? Color.Black : Color.DimGray;} + 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;} } /// @@ -143,7 +148,20 @@ namespace Crow.Coding mview.ProjectNode.Instance.HasChanged = true; //should reinstantiate to get default } - + public void GotoStyle(){ + GraphicObject inst = mview.ProjectNode.SelectedItem as GraphicObject; + if (!inst.design_defaults.ContainsKey (Name)) + return; + FileLocation fl = inst.design_defaults [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; + } } diff --git a/CrowIDE/src/Solution.cs b/CrowIDE/src/Solution.cs index 9874fd4a..7ed6b780 100644 --- a/CrowIDE/src/Solution.cs +++ b/CrowIDE/src/Solution.cs @@ -66,10 +66,9 @@ namespace Crow.Coding{ public bool GetProjectFileFromPath (string path, out ProjectFile pi){ pi = null; return StartupProject == null ? false : - StartupProject.GetProjectFileFromPath (path, out pi); + StartupProject.TryGetProjectFileFromPath (path, out pi); } - public ObservableList OpenedItems { get { return openedItems; } set { @@ -139,20 +138,49 @@ namespace Crow.Coding{ NotifyValueChanged ("CompilerErrors", CompilerErrors); } + void saveOpenedItemsInUserConfig (){ + UserConfig.Set ("OpenedItems", openedItems.Select(o => o.AbsolutePath).Aggregate((a,b)=>a + ";" + b)); + } + void reopenItemsSavedInUserConfig () { + string tmp = UserConfig.Get ("OpenedItems"); + string sel = UserConfig.Get ("SelectedProjItems"); + ProjectFile selItem = null; + if (string.IsNullOrEmpty (tmp)) + return; + foreach (string f in tmp.Split(';')) { + foreach (Project p in Projects) { + ProjectFile pi; + if (p.TryGetProjectFileFromAbsolutePath (f, out pi)) { + OpenedItems.Add (pi); + if (pi.AbsolutePath == sel) + selItem = pi; + break; + } + } + } + SelectedItem = selItem;//BUG: loading in another thread focused last loaded pf + } + void onSelectedItemChanged (object sender, SelectionChangeEventArgs e){ ProjectItem pi = e.NewValue as ProjectItem; if (pi != null) { - if (!openedItems.Contains (pi)) + if (!openedItems.Contains (pi)) { openedItems.AddElement (pi); + saveOpenedItemsInUserConfig (); + } } this.SelectedItem = pi; + UserConfig.Set ("SelectedProjItems", SelectedItem?.AbsolutePath); } public void OnCloseTab (object sender, MouseButtonEventArgs e){ - + Console.WriteLine ("OnCloseTab"); openedItems.RemoveElement ((sender as GraphicObject).DataSource as ProjectItem); + saveOpenedItemsInUserConfig (); } public void CloseItem (ProjectItem pi) { + Console.WriteLine ("CloseItem"); openedItems.RemoveElement (pi); + saveOpenedItemsInUserConfig (); } /// @@ -243,7 +271,9 @@ namespace Crow.Coding{ /// /// Creates new solution. /// - public Solution() { } + public Solution() { + } + #endregion @@ -412,6 +442,7 @@ 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/CSharpParser.cs b/CrowIDE/src/SourceEditor/CSharpParser.cs index 23aef43e..d7f15a7a 100644 --- a/CrowIDE/src/SourceEditor/CSharpParser.cs +++ b/CrowIDE/src/SourceEditor/CSharpParser.cs @@ -150,7 +150,7 @@ namespace Crow.Coding public override void ParseCurrentLine () { - Debug.WriteLine (string.Format("parsing line:{0}", currentLine)); + //Debug.WriteLine (string.Format("parsing line:{0}", currentLine)); CodeLine cl = buffer [currentLine]; cl.Tokens = new List (); diff --git a/CrowIDE/src/SourceEditor/CodeBuffer.cs b/CrowIDE/src/SourceEditor/CodeBuffer.cs index 55d88978..66c24857 100644 --- a/CrowIDE/src/SourceEditor/CodeBuffer.cs +++ b/CrowIDE/src/SourceEditor/CodeBuffer.cs @@ -23,6 +23,7 @@ using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using System.Diagnostics; +using System.Threading; namespace Crow.Coding { @@ -31,7 +32,8 @@ namespace Crow.Coding /// public class CodeBuffer { - public object EditMutex = new object(); + public ReaderWriterLockSlim editMutex = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); + //those events are handled in SourceEditor to help keeping sync between textbuffer,parser and editor. //modified lines are marked for reparse #region Events @@ -65,72 +67,72 @@ namespace Crow.Coding set { if (lines [i] == value) return; - lock (EditMutex) { - lines [i] = value; - LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i)); - } + editMutex.EnterWriteLock (); + lines [i] = value; + LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i)); + editMutex.ExitWriteLock (); } } public void RemoveAt(int i){ - lock (EditMutex) { - lines.RemoveAt (i); - LineRemoveEvent.Raise (this, new CodeBufferEventArgs (i)); - } + editMutex.EnterWriteLock (); + lines.RemoveAt (i); + LineRemoveEvent.Raise (this, new CodeBufferEventArgs (i)); + editMutex.ExitWriteLock (); } public void Insert(int i, string item){ - lock (EditMutex) { - lines.Insert (i, item); - LineAdditionEvent.Raise (this, new CodeBufferEventArgs (i)); - } + editMutex.EnterWriteLock (); + lines.Insert (i, item); + LineAdditionEvent.Raise (this, new CodeBufferEventArgs (i)); + editMutex.ExitWriteLock (); } public void Add(CodeLine item){ - lock (EditMutex) { - lines.Add (item); - LineAdditionEvent.Raise (this, new CodeBufferEventArgs (lines.Count - 1)); - } + editMutex.EnterWriteLock (); + lines.Add (item); + LineAdditionEvent.Raise (this, new CodeBufferEventArgs (lines.Count - 1)); + editMutex.ExitWriteLock (); } public void AddRange (string[] items){ int start = lines.Count; - lock (EditMutex) { - for (int i = 0; i < items.Length; i++) - lines.Add (items [i]); - LineAdditionEvent.Raise (this, new CodeBufferEventArgs (start, items.Length)); - } + editMutex.EnterWriteLock (); + for (int i = 0; i < items.Length; i++) + lines.Add (items [i]); + LineAdditionEvent.Raise (this, new CodeBufferEventArgs (start, items.Length)); + editMutex.ExitWriteLock (); } public void AddRange (CodeLine[] items){ int start = lines.Count; - lock (EditMutex) { - lines.AddRange (items); - LineAdditionEvent.Raise (this, new CodeBufferEventArgs (start, items.Length)); - } + editMutex.EnterWriteLock (); + lines.AddRange (items); + LineAdditionEvent.Raise (this, new CodeBufferEventArgs (start, items.Length)); + editMutex.ExitWriteLock (); } public void Clear () { - lock (EditMutex) { - longestLineCharCount = 0; - lines.Clear (); - BufferCleared.Raise (this, null); - } + editMutex.EnterWriteLock (); + longestLineCharCount = 0; + lines.Clear (); + BufferCleared.Raise (this, null); + editMutex.ExitWriteLock (); } public void UpdateLine(int i, string newContent){ - lock (EditMutex) { - this [i].Content = newContent; - LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i)); - } + editMutex.EnterWriteLock (); + this [i].Content = newContent; + LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i)); + editMutex.ExitWriteLock (); } public void AppenedLine(int i, string newContent){ - lock (EditMutex) { - this [i].Content += newContent; - LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i)); - } + editMutex.EnterWriteLock (); + this [i].Content += newContent; + LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i)); + editMutex.ExitWriteLock (); } public void ToogleFolding (int line) { if (!this [line].IsFoldable) return; - lock (EditMutex) { - this [line].IsFolded = !this [line].IsFolded; - FoldingEvent.Raise (this, new CodeBufferEventArgs (line)); - } + editMutex.EnterWriteLock (); + this [line].IsFolded = !this [line].IsFolded; + FoldingEvent.Raise (this, new CodeBufferEventArgs (line)); + editMutex.ExitWriteLock (); } public void Load(string rawSource, string lineBrkRegex = @"\r\n|\r|\n|\\\n") { this.Clear(); @@ -410,37 +412,40 @@ namespace Crow.Coding } public void DeleteChar() { - lock (EditMutex) { - if (SelectionIsEmpty) { - if (CurrentColumn == 0) { - if (CurrentLine == 0) - return; - CurrentLine--; - CurrentColumn = this [CurrentLine].Length; - AppenedLine (CurrentLine, this [CurrentLine + 1].Content); - RemoveAt (CurrentLine + 1); + editMutex.EnterWriteLock (); + if (SelectionIsEmpty) { + if (CurrentColumn == 0) { + if (CurrentLine == 0) { + editMutex.ExitWriteLock (); return; } - CurrentColumn--; - UpdateLine (CurrentLine, this [CurrentLine].Content.Remove (CurrentColumn, 1)); - } else { - int linesToRemove = SelectionEnd.Y - SelectionStart.Y + 1; - int l = SelectionStart.Y; + CurrentLine--; + CurrentColumn = this [CurrentLine].Length; + AppenedLine (CurrentLine, this [CurrentLine + 1].Content); + RemoveAt (CurrentLine + 1); + editMutex.ExitWriteLock (); + return; + } + CurrentColumn--; + UpdateLine (CurrentLine, this [CurrentLine].Content.Remove (CurrentColumn, 1)); + } else { + int linesToRemove = SelectionEnd.Y - SelectionStart.Y + 1; + int l = SelectionStart.Y; - if (linesToRemove > 0) { - UpdateLine (l, this [l].Content.Remove (SelectionStart.X, this [l].Length - SelectionStart.X) + - this [SelectionEnd.Y].Content.Substring (SelectionEnd.X, this [SelectionEnd.Y].Length - SelectionEnd.X)); - l++; - for (int c = 0; c < linesToRemove - 1; c++) - RemoveAt (l); - CurrentLine = SelectionStart.Y; - CurrentColumn = SelectionStart.X; - } else - UpdateLine (l, this [l].Content.Remove (SelectionStart.X, SelectionEnd.X - SelectionStart.X)); + if (linesToRemove > 0) { + UpdateLine (l, this [l].Content.Remove (SelectionStart.X, this [l].Length - SelectionStart.X) + + this [SelectionEnd.Y].Content.Substring (SelectionEnd.X, this [SelectionEnd.Y].Length - SelectionEnd.X)); + l++; + for (int c = 0; c < linesToRemove - 1; c++) + RemoveAt (l); + CurrentLine = SelectionStart.Y; CurrentColumn = SelectionStart.X; - ResetSelection (); - } + } else + UpdateLine (l, this [l].Content.Remove (SelectionStart.X, SelectionEnd.X - SelectionStart.X)); + CurrentColumn = SelectionStart.X; + ResetSelection (); } + editMutex.ExitWriteLock (); } /// /// Insert new string at caret position, should be sure no line break is inside. diff --git a/CrowIDE/src/SourceEditor/SourceEditor.cs b/CrowIDE/src/SourceEditor/SourceEditor.cs index 6480af18..b0e8a35f 100644 --- a/CrowIDE/src/SourceEditor/SourceEditor.cs +++ b/CrowIDE/src/SourceEditor/SourceEditor.cs @@ -93,18 +93,18 @@ namespace Crow.Coding 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); + buffer.editMutex.EnterWriteLock (); + string newsrc = ""; + bool wasDirty = false; + if (isDirty) { + isDirty = false; + wasDirty = true; + newsrc = buffer.FullText; } + buffer.editMutex.ExitWriteLock (); + if (wasDirty) + projFile.UpdateSource (this, newsrc); + } Thread.Sleep (100); } @@ -187,30 +187,30 @@ namespace Crow.Coding } } void updatePrintedLines () { - lock (buffer.EditMutex) { - PrintedLines = new List (); - int curL = 0; - int i = 0; - - while (curL < buffer.LineCount && i < ScrollY) { - if (buffer [curL].IsFolded) - curL = buffer.GetEndNodeIndex (curL); - curL++; - i++; - } + buffer.editMutex.EnterReadLock (); + PrintedLines = new List (); + int curL = 0; + int i = 0; - firstPrintedLine = curL; - i = 0; - while (i < visibleLines && curL < buffer.LineCount) { - PrintedLines.Add (buffer [curL]); + while (curL < buffer.LineCount && i < ScrollY) { + if (buffer [curL].IsFolded) + curL = buffer.GetEndNodeIndex (curL); + curL++; + i++; + } - if (buffer [curL].IsFolded) - curL = buffer.GetEndNodeIndex (curL); + firstPrintedLine = curL; + i = 0; + while (i < visibleLines && curL < buffer.LineCount) { + PrintedLines.Add (buffer [curL]); - curL++; - i++; - } + if (buffer [curL].IsFolded) + curL = buffer.GetEndNodeIndex (curL); + + curL++; + i++; } + buffer.editMutex.ExitReadLock (); } void toogleFolding (int line) { if (parser == null || !foldingEnabled) @@ -786,29 +786,29 @@ namespace Crow.Coding Foreground.SetAsSource (gr); - lock (buffer.EditMutex) { - #region draw text cursor - if (buffer.SelectionInProgress){ - selStartCol = getTabulatedColumn (buffer.SelectionStart); - selEndCol = getTabulatedColumn (buffer.SelectionEnd); - }else if (HasFocus && printedCurrentLine >= 0){ - gr.LineWidth = 1.0; - double cursorX = cb.X + (getTabulatedColumn(buffer.CurrentPosition) - ScrollX) * fe.MaxXAdvance + leftMargin; - gr.MoveTo (0.5 + cursorX, cb.Y + (printedCurrentLine) * (fe.Ascent+fe.Descent)); - gr.LineTo (0.5 + cursorX, cb.Y + (printedCurrentLine + 1) * (fe.Ascent+fe.Descent)); - gr.Stroke(); - } - #endregion + buffer.editMutex.EnterReadLock (); + #region draw text cursor + if (buffer.SelectionInProgress){ + selStartCol = getTabulatedColumn (buffer.SelectionStart); + selEndCol = getTabulatedColumn (buffer.SelectionEnd); + }else if (HasFocus && printedCurrentLine >= 0){ + gr.LineWidth = 1.0; + double cursorX = cb.X + (getTabulatedColumn(buffer.CurrentPosition) - ScrollX) * fe.MaxXAdvance + leftMargin; + gr.MoveTo (0.5 + cursorX, cb.Y + (printedCurrentLine) * (fe.Ascent+fe.Descent)); + gr.LineTo (0.5 + cursorX, cb.Y + (printedCurrentLine + 1) * (fe.Ascent+fe.Descent)); + gr.Stroke(); + } + #endregion - if (PrintedLines != null) { - for (int i = 0; i < visibleLines; i++) { - if (i + ScrollY >= buffer.UnfoldedLines)//TODO:need optimize - break; - drawLine (gr, cb, i); - } + if (PrintedLines != null) { + for (int i = 0; i < visibleLines; i++) { + if (i + ScrollY >= buffer.UnfoldedLines)//TODO:need optimize + break; + drawLine (gr, cb, i); } } - //System.Threading.Monitor.Exit (buffer.EditMutex); + buffer.editMutex.ExitReadLock (); + } #endregion diff --git a/CrowIDE/src/SourceEditor/StyleParser.cs b/CrowIDE/src/SourceEditor/StyleParser.cs index 13c94d90..2aba6848 100644 --- a/CrowIDE/src/SourceEditor/StyleParser.cs +++ b/CrowIDE/src/SourceEditor/StyleParser.cs @@ -36,7 +36,7 @@ namespace Crow.Coding public override void ParseCurrentLine () { - Debug.WriteLine (string.Format("parsing line:{0}", currentLine)); + //Debug.WriteLine (string.Format("parsing line:{0}", currentLine)); CodeLine cl = buffer [currentLine]; cl.Tokens = new List (); diff --git a/CrowIDE/src/SourceEditor/XMLParser.cs b/CrowIDE/src/SourceEditor/XMLParser.cs index ada05512..6f001587 100644 --- a/CrowIDE/src/SourceEditor/XMLParser.cs +++ b/CrowIDE/src/SourceEditor/XMLParser.cs @@ -90,7 +90,7 @@ namespace Crow.Coding public override void ParseCurrentLine () { - Debug.WriteLine (string.Format("parsing line:{0}", currentLine)); + //Debug.WriteLine (string.Format("parsing line:{0}", currentLine)); CodeLine cl = buffer [currentLine]; cl.Tokens = new List (); diff --git a/CrowIDE/ui/CrowIDE.crow b/CrowIDE/ui/CrowIDE.crow index 9e2694f9..395503f5 100644 --- a/CrowIDE/ui/CrowIDE.crow +++ b/CrowIDE/ui/CrowIDE.crow @@ -34,7 +34,7 @@