From 1d0b26c321355210c84f853df425b750a3602a13 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jean-Philippe=20Bruy=C3=A8re?= Date: Thu, 16 Sep 2021 19:29:17 +0000 Subject: [PATCH] wip --- CrowEdit.csproj | 1 - CrowEdit.style | 47 ---- CrowEditBase/CrowEditBase.csproj | 10 +- CrowEditBase/src/Compiler/SourceDocument.cs | 47 ++-- CrowEditBase/src/Compiler/Token.cs | 5 + CrowEditBase/src/CrowEditBase.cs | 18 +- CrowEditBase/src/Debug/Debugger.cs | 12 +- CrowEditBase/src/Debug/Watch.cs | 4 +- CrowEditBase/src/Document.cs | 22 +- CrowEditBase/src/Editor.cs | 108 +++---- CrowEditBase/src/LogViewerWidget.cs | 264 +++++++++++++++--- CrowEditBase/src/Plugin.cs | 22 +- CrowEditBase/src/Project.cs | 18 +- CrowEditBase/src/Service.cs | 12 +- CrowEditBase/src/TextDocument.cs | 18 +- CrowEditBase/src/TreeNode.cs | 2 +- CrowEditBase/ui/CategoryExp.template | 2 +- CrowEditBase/ui/CrowEdit.style | 131 +++++++++ .../ui/DockWinTitleBarIconMenu.template | 2 + CrowEditBase/ui/DockWinTitleBarMenu.itemp | 10 + CrowEditBase/ui/DockWindow.template | 22 ++ .../ui/DockWindow2.template | 18 +- .../ui}/DockingTabView.template | 10 +- CrowEditBase/ui/EnumSelector.template | 12 + CrowEditBase/ui/IDE.style | 43 --- {ui => CrowEditBase/ui}/MenuButton.template | 2 +- {ui => CrowEditBase/ui}/MenuItem.itmp | 2 +- {ui => CrowEditBase/ui}/MenuItem.template | 0 CrowEditBase/ui/Service.itmp | 2 +- {ui => CrowEditBase/ui}/Suggestions.template | 2 +- CrowEditBase/ui/TreeExpandable.template | 6 +- {ui => CrowEditBase/ui}/sourceEditor.itmp | 16 +- README.md | 6 + clean.sh | 2 - plugins/CECrowPlugin/src/CrowService.cs | 175 +++++++----- plugins/CECrowPlugin/src/DbgLogViewer.cs | 50 ++-- plugins/CECrowPlugin/src/DebugInterface.cs | 72 +++-- .../CECrowPlugin/src/DebugInterfaceWidget.cs | 59 ++-- plugins/CECrowPlugin/src/ImlDocument.cs | 36 ++- plugins/CECrowPlugin/ui/Button.template | 2 +- plugins/CECrowPlugin/ui/winConfiguration.crow | 16 +- plugins/CECrowPlugin/ui/winDebugLog.crow | 2 +- plugins/CERoslynPlugin/src/CELogger.cs | 37 ++- plugins/CERoslynPlugin/src/CETaskLogHook.cs | 64 +++++ plugins/CERoslynPlugin/src/CSDocument.cs | 19 +- plugins/CERoslynPlugin/src/CSTokenizer.cs | 142 ++++++++++ plugins/CERoslynPlugin/src/MSBuildProject.cs | 82 ++++-- .../src/ProjectTree/ProjectItemNodes.cs | 35 ++- plugins/CERoslynPlugin/src/RoslynService.cs | 28 +- plugins/CERoslynPlugin/src/SolutionProject.cs | 37 +-- .../ui/MSBuildProjectNode.template | 8 +- .../CERoslynPlugin/ui/winConfiguration.crow | 21 +- .../src/ImlParsing/XmlTokenizer.cs | 40 +-- screenshot.png | Bin 0 -> 237900 bytes src/CrowEdit.cs | 90 +++--- src/Extensions.cs | 14 +- ui/main.crow | 4 +- ui/windows/winEditor.crow | 22 +- ui/windows/winLogs.crow | 29 +- ui/windows/winPlugins.crow | 2 +- ui/windows/winProjects.crow | 15 +- ui/windows/winServices.crow | 2 +- 62 files changed, 1343 insertions(+), 658 deletions(-) delete mode 100644 CrowEdit.style create mode 100644 CrowEditBase/ui/CrowEdit.style create mode 100644 CrowEditBase/ui/DockWinTitleBarIconMenu.template create mode 100644 CrowEditBase/ui/DockWinTitleBarMenu.itemp create mode 100644 CrowEditBase/ui/DockWindow.template rename ui/DockWindow.template => CrowEditBase/ui/DockWindow2.template (75%) rename {ui => CrowEditBase/ui}/DockingTabView.template (86%) create mode 100644 CrowEditBase/ui/EnumSelector.template delete mode 100644 CrowEditBase/ui/IDE.style rename {ui => CrowEditBase/ui}/MenuButton.template (95%) rename {ui => CrowEditBase/ui}/MenuItem.itmp (88%) rename {ui => CrowEditBase/ui}/MenuItem.template (100%) rename {ui => CrowEditBase/ui}/Suggestions.template (99%) rename {ui => CrowEditBase/ui}/sourceEditor.itmp (60%) delete mode 100755 clean.sh create mode 100644 plugins/CERoslynPlugin/src/CETaskLogHook.cs create mode 100644 plugins/CERoslynPlugin/src/CSTokenizer.cs create mode 100644 screenshot.png diff --git a/CrowEdit.csproj b/CrowEdit.csproj index b97f8bd..0bae253 100644 --- a/CrowEdit.csproj +++ b/CrowEdit.csproj @@ -9,7 +9,6 @@ - diff --git a/CrowEdit.style b/CrowEdit.style deleted file mode 100644 index 5bfdb06..0000000 --- a/CrowEdit.style +++ /dev/null @@ -1,47 +0,0 @@ -SmallUIFont = "sans, 10"; -SmallFont = "consolas, 10"; -InactiveTabBackground = "DarkGrey"; -SelectedTabBackground = "Onyx"; -InactiveTabForeground = "Grey"; -SelectedTabForeground = "White"; -MenuIconSize = "16"; - -ControlHighlight = "RoyalBlue"; - -Splitter { - Thickness="1"; - Background="Transparent"; - Hover="{Background=White}"; - Unhover="{Background=Transparent}"; -} -DockStack { - Margin="0"; - Spacing="0"; -} -DockWindow { - Template = "#CrowEdit.ui.DockWindow.template"; - Background = "DarkGrey"; - Margin="0"; -} -DockingTabView { - Template = "#CrowEdit.ui.DockingTabView.template"; -} -MenuItem { - Template = "#CrowEdit.ui.MenuItem.template"; -} - -MenuIcon { - Margin = "1"; - Width = "${MenuIconSize}"; - Height = "${MenuIconSize}"; -} - -suggestionsListBox { - Template = "#CrowEdit.ui.Suggestions.template"; - Width = "Fit"; - Height = "Fit"; - MaximumSize = "300, 120"; - Background = "Jet"; - UseLoadingThread = "false"; -} - diff --git a/CrowEditBase/CrowEditBase.csproj b/CrowEditBase/CrowEditBase.csproj index b255137..f9fd2fa 100644 --- a/CrowEditBase/CrowEditBase.csproj +++ b/CrowEditBase/CrowEditBase.csproj @@ -4,16 +4,18 @@ netcoreapp3.1 false - + - + + ui.%(Filename)%(Extension) + icons.%(Filename)%(Extension) - + - + diff --git a/CrowEditBase/src/Compiler/SourceDocument.cs b/CrowEditBase/src/Compiler/SourceDocument.cs index 52164c9..bb4ba3e 100644 --- a/CrowEditBase/src/Compiler/SourceDocument.cs +++ b/CrowEditBase/src/Compiler/SourceDocument.cs @@ -3,9 +3,6 @@ // This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) using System; -using System.Linq; -using System.Collections.Generic; -using System.IO; using Crow; using Crow.Text; using System.Diagnostics; @@ -19,6 +16,9 @@ namespace CrowEditBase } protected Token[] tokens; protected SyntaxNode RootNode; + protected Token currentToken; + protected SyntaxNode currentNode; + public Token[] Tokens => tokens; public Token FindTokenIncludingPosition (int pos) { if (pos == 0 || tokens == null || tokens.Length == 0) @@ -51,8 +51,27 @@ namespace CrowEditBase parse (); } + public virtual Crow.Color GetColorForToken (TokenType tokType) { + if (tokType.HasFlag (TokenType.Punctuation)) + return Colors.DarkGrey; + if (tokType.HasFlag (TokenType.Trivia)) + return Colors.DimGrey; + if (tokType == TokenType.Keyword) + return Colors.DarkSlateBlue; + return Colors.Red; + } protected abstract Tokenizer CreateTokenizer (); protected abstract SyntaxAnalyser CreateSyntaxAnalyser (); + public abstract IList GetSuggestions (int pos); + + /// + /// complete current token with selected item from the suggestion overlay. + /// It may set a new position or a new selection. + /// + /// selected object of suggestion overlay + /// new position or selection, null if normal position after text changes + /// the TextChange to apply to the source + public abstract TextChange? GetCompletionForCurrentToken (object suggestion, out TextSpan? newSelection); void parse () { Tokenizer tokenizer = CreateTokenizer (); tokens = tokenizer.Tokenize (Source); @@ -71,26 +90,6 @@ namespace CrowEditBase Console.WriteLine ($"{t,-40} {Source.AsSpan(t.Start, t.Length).ToString()}"); syntaxAnalyser.Root.Dump();*/ } - public virtual Crow.Color GetColorForToken (TokenType tokType) { - if (tokType.HasFlag (TokenType.Punctuation)) - return Colors.DarkGrey; - if (tokType.HasFlag (TokenType.Trivia)) - return Colors.DimGrey; - if (tokType == TokenType.Keyword) - return Colors.DarkSlateBlue; - return Colors.Red; - } - protected Token currentToken; - protected SyntaxNode currentNode; - public abstract IList GetSuggestions (int pos); - - /// - /// complete current token with selected item from the suggestion overlay. - /// It may set a new position or a new selection. - /// - /// selected object of suggestion overlay - /// new position or selection, null if normal position after text changes - /// the TextChange to apply to the source - public abstract TextChange? GetCompletionForCurrentToken (object suggestion, out TextSpan? newSelection); + } } \ No newline at end of file diff --git a/CrowEditBase/src/Compiler/Token.cs b/CrowEditBase/src/Compiler/Token.cs index 86354ac..26fd21c 100644 --- a/CrowEditBase/src/Compiler/Token.cs +++ b/CrowEditBase/src/Compiler/Token.cs @@ -26,6 +26,11 @@ namespace CrowEditBase Type = type; Start = start; Length = end - start; + } + public Token (int start, int length, TokenType type) { + Type = type; + Start = start; + Length = length; } public int CompareTo([AllowNull] Token other) diff --git a/CrowEditBase/src/CrowEditBase.cs b/CrowEditBase/src/CrowEditBase.cs index f79a532..b40fa18 100644 --- a/CrowEditBase/src/CrowEditBase.cs +++ b/CrowEditBase/src/CrowEditBase.cs @@ -11,7 +11,7 @@ using System.Collections.Generic; using System.Runtime.Loader; namespace CrowEditBase -{ +{ public abstract class CrowEditBase : Interface { protected class DocumentClientClassList : List { string defaultClass; @@ -34,7 +34,7 @@ namespace CrowEditBase FileAssociations.Add (extension, new DocumentClientClassList ()); if (!FileAssociations[extension].Contains (clientClass)) FileAssociations[extension].Add (clientClass); - + } public void RemoveFileAssociationByType (Type clientClass) { @@ -110,7 +110,7 @@ namespace CrowEditBase currentDocument?.UnselectDocument (); - currentDocument = value; + currentDocument = value; NotifyValueChanged (currentDocument); if (currentDocument == null) @@ -121,7 +121,7 @@ namespace CrowEditBase FileCommands[3] = currentDocument.CMDSaveAs; EditCommands[0] = currentDocument.CMDUndo; EditCommands[1] = currentDocument.CMDRedo; - + } } public Project CurrentProject { @@ -195,7 +195,7 @@ namespace CrowEditBase public void CloseFile (string filePath) => CloseDocument (OpenedDocuments.FirstOrDefault (d => d.FullPath == filePath)); public void CloseOthers (string filePath) { - foreach (Document doc in OpenedDocuments.Where (d => d.FullPath != filePath)) + foreach (Document doc in OpenedDocuments.Where (d => d.FullPath != filePath)) CloseDocument (doc); } public void CloseOthers (Document document) { @@ -207,8 +207,8 @@ namespace CrowEditBase } public void createNewFile(){ - openOrCreateFile (Path.Combine (CurFileDir, _defaultFileName)); - } + openOrCreateFile (Path.Combine (CurFileDir, _defaultFileName)); + } protected abstract Document openOrCreateFile (string filePath); public void CloseDocument (Document doc) { @@ -260,7 +260,7 @@ namespace CrowEditBase protected void loadPlugins () { - if (string.IsNullOrEmpty (PluginsDirecory)) + if (string.IsNullOrEmpty (PluginsDirecory)) PluginsDirecory = Path.Combine ( Environment.GetFolderPath (Environment.SpecialFolder.UserProfile), ".config", "CrowEdit", "plugins"); @@ -269,7 +269,7 @@ namespace CrowEditBase Plugins.Add (plugin); plugin.Load (); } - } + } } } \ No newline at end of file diff --git a/CrowEditBase/src/Debug/Debugger.cs b/CrowEditBase/src/Debug/Debugger.cs index a6eadc8..3fe227a 100644 --- a/CrowEditBase/src/Debug/Debugger.cs +++ b/CrowEditBase/src/Debug/Debugger.cs @@ -28,12 +28,12 @@ namespace CrowEditBase public virtual CommandGroup Commands => new CommandGroup ( CMDDebugStart, CMDDebugPause, CMDDebugStop, CMDDebugStepIn, CMDDebugStepOver, CMDDebugStepOut); protected virtual void initCommands () { - CMDDebugStart = new Command ("Start", Start, "#Icons.debug-play.svg"); - CMDDebugPause = new Command ("Pause", Pause, "#Icons.debug-pause.svg", false); - CMDDebugStop = new Command ("Stop", Stop, "#Icons.debug-stop.svg", false); - CMDDebugStepIn = new Command ("Step in", StepIn, "#Icons.debug-step-into.svg", false); - CMDDebugStepOut = new Command ("Step out", StepOut, "#Icons.debug-step-out.svg", false); - CMDDebugStepOver = new Command ("Step over", StepOver, "#Icons.debug-step-over.svg", false); + CMDDebugStart = new ActionCommand ("Start", Start, "#Icons.debug-play.svg"); + CMDDebugPause = new ActionCommand ("Pause", Pause, "#Icons.debug-pause.svg", false); + CMDDebugStop = new ActionCommand ("Stop", Stop, "#Icons.debug-stop.svg", false); + CMDDebugStepIn = new ActionCommand ("Step in", StepIn, "#Icons.debug-step-into.svg", false); + CMDDebugStepOut = new ActionCommand ("Step out", StepOut, "#Icons.debug-step-out.svg", false); + CMDDebugStepOver = new ActionCommand ("Step over", StepOver, "#Icons.debug-step-over.svg", false); } diff --git a/CrowEditBase/src/Debug/Watch.cs b/CrowEditBase/src/Debug/Watch.cs index cf33260..497e0d1 100644 --- a/CrowEditBase/src/Debug/Watch.cs +++ b/CrowEditBase/src/Debug/Watch.cs @@ -23,8 +23,8 @@ namespace CrowEditBase ObservableList children = new ObservableList(); public CommandGroup Commands => new CommandGroup ( - new Command ("Update Value", () => UpdateValue()), - new Command ("Delete", () => Delete()) + new ActionCommand ("Update Value", () => UpdateValue()), + new ActionCommand ("Delete", () => Delete()) ); public bool HasChildren => NumChild > 0; diff --git a/CrowEditBase/src/Document.cs b/CrowEditBase/src/Document.cs index 1c3646e..472cbd7 100644 --- a/CrowEditBase/src/Document.cs +++ b/CrowEditBase/src/Document.cs @@ -32,7 +32,7 @@ namespace CrowEditBase public abstract void UnregisterClient (object client); DateTime accessTime; - string fullPath; + string fullPath; public string FullPath { get => fullPath; @@ -41,7 +41,7 @@ namespace CrowEditBase return; fullPath = value; - + NotifyValueChanged (fullPath); NotifyValueChanged ("FileName", (object)FileName); NotifyValueChanged ("FileDirectory", (object)Extension); @@ -65,7 +65,7 @@ namespace CrowEditBase if (File.Exists (FullPath)) writeToDisk (); else - SaveAs (); + SaveAs (); } public Command CMDUndo, CMDRedo, CMDSave, CMDSaveAs; @@ -74,14 +74,14 @@ namespace CrowEditBase public CommandGroup TabCommands => new CommandGroup ( CMDClose, CMDCloseOther ); - + protected virtual void initCommands () { - CMDUndo = new Command ("Undo", undo, "#icons.reply.svg", false); - CMDRedo = new Command ("Redo", redo, "#icons.share-arrow.svg", false); - CMDSave = new Command ("save", Save, "#icons.inbox.svg", false); - CMDSaveAs = new Command ("Save As...", SaveAs, "#icons.inbox.svg"); - CMDClose = new Command ("Close", () => App.CloseDocument (this), "#icons.sign-out.svg"); - CMDCloseOther = new Command ("Close Others", () => App.CloseOthers (this), "#icons.inbox.svg"); + CMDUndo = new ActionCommand ("Undo", undo, "#icons.reply.svg", false); + CMDRedo = new ActionCommand ("Redo", redo, "#icons.share-arrow.svg", false); + CMDSave = new ActionCommand ("save", Save, "#icons.inbox.svg", false); + CMDSaveAs = new ActionCommand ("Save As...", SaveAs, "#icons.inbox.svg"); + CMDClose = new ActionCommand ("Close", () => App.CloseDocument (this), "#icons.sign-out.svg"); + CMDCloseOther = new ActionCommand ("Close Others", () => App.CloseOthers (this), "#icons.inbox.svg"); } protected abstract void undo(); protected abstract void redo(); @@ -94,7 +94,7 @@ namespace CrowEditBase if (File.Exists (FullPath)) readFromDisk (); else - initNewFile (); + initNewFile (); } finally { editorRWLock.ExitWriteLock (); } diff --git a/CrowEditBase/src/Editor.cs b/CrowEditBase/src/Editor.cs index a0ad516..92eb65b 100644 --- a/CrowEditBase/src/Editor.cs +++ b/CrowEditBase/src/Editor.cs @@ -34,15 +34,15 @@ namespace Crow t.IsBackground = true; t.Start (); } - #endregion + #endregion TextDocument document; protected bool disableTextChangedEvent; public Command CMDCut, CMDCopy, CMDPaste; void initCommands () { - CMDCut = new Command ("Cut", Cut, "#icons.scissors.svg", false); - CMDCopy = new Command ("Copy", Copy, "#icons.copy-file.svg", false); - CMDPaste = new Command ("Paste", Paste, "#icons.paste-on-document.svg", true); + CMDCut = new ActionCommand ("Cut", Cut, "#icons.scissors.svg", false); + CMDCopy = new ActionCommand ("Copy", Copy, "#icons.copy-file.svg", false); + CMDPaste = new ActionCommand ("Paste", Paste, "#icons.paste-on-document.svg", true); ContextCommands = new CommandGroup (CMDCut, CMDCopy, CMDPaste); } @@ -76,24 +76,24 @@ namespace Crow public virtual void OnTextChanged(object sender, TextChangeEventArgs e) { if (disableTextChangedEvent) - return; + return; TextChanged.Raise (this, e); - } + } protected void backgroundThreadFunc () { - while (true) { - if (Document != null && document.TryGetState (this, out List changes)) { - disableTextChangedEvent = true; + while (true) { + if (Document != null && document.TryGetState (this, out List changes)) { + disableTextChangedEvent = true; foreach (TextChange tc in changes) update (tc); disableTextChangedEvent = false; } - Thread.Sleep (200); - } - } + Thread.Sleep (200); + } + } #region Label protected string _text = ""; - int targetColumn = -1;//handle line changes with long->short->long line length sequence. + int targetColumn = -1;//handle line changes with long->short->long line length sequence. protected CharLocation? hoverLoc = null; protected CharLocation? currentLoc = null; @@ -152,7 +152,7 @@ namespace Crow protected bool mixedLineBreak = false; protected FontExtents fe; - protected TextExtents te; + protected TextExtents te; /// @@ -188,7 +188,7 @@ namespace Crow /// /// Moves cursor one char to the left. /// - /// true if move succeed + /// true if move succeed public bool MoveLeft(){ //targetColumn = -1; CharLocation loc = CurrentLoc.Value; @@ -210,7 +210,7 @@ namespace Crow } else CurrentLoc = new CharLocation (loc.Line, loc.Column + 1); return true; - } + } public bool LineMove (int lineDiff) { CharLocation loc = CurrentLoc.Value; int newLine = Math.Min (Math.Max (0, loc.Line + lineDiff), lines.Count - 1); @@ -233,7 +233,7 @@ namespace Crow } protected int visibleLines => (int)((double)ClientRectangle.Height / (fe.Ascent + fe.Descent)); public void GotoWordStart(){ - int pos = lines.GetAbsolutePosition (CurrentLoc.Value); + int pos = lines.GetAbsolutePosition (CurrentLoc.Value); //skip white spaces while (pos > 0 && !char.IsLetterOrDigit (_text[pos-1])) pos--; @@ -249,7 +249,7 @@ namespace Crow while (pos < _text.Length - 1 && char.IsLetterOrDigit (_text[pos])) pos++; CurrentLoc = lines.GetLocation (pos); - } + } protected void detectLineBreak () { mixedLineBreak = false; @@ -268,8 +268,8 @@ namespace Crow } } } - - protected void getLines () { + + protected void getLines () { if (lines == null) lines = new LineCollection (10); else @@ -429,7 +429,7 @@ namespace Crow if (HasFocus && selectionNotEmpty) { RectangleD selRect = lineRect; - + if (i >= selStart.Line && i <= selEnd.Line) { if (selStart.Line == selEnd.Line) { selRect.X = selStart.VisualCharXPosition + cb.X; @@ -446,7 +446,7 @@ namespace Crow y += lineHeight; continue; } - + gr.SetSource (selBackground); gr.Rectangle (selRect); if (encodedBytes < 0) @@ -470,7 +470,15 @@ namespace Crow gr.Translate (ScrollX, ScrollY); } protected virtual void updateHoverLocation (Point mouseLocalPos) { - int hoverLine = (int)Math.Min (Math.Max (0, Math.Floor (mouseLocalPos.Y / (fe.Ascent + fe.Descent))), lines.Count - 1); + int hoverLine = (int)Math.Min (Math.Max (0, Math.Floor ((mouseLocalPos.Y + ScrollY)/ (fe.Ascent + fe.Descent))), lines.Count - 1); + int scrollLine = (int)Math.Ceiling((double)ScrollY / (fe.Ascent + fe.Descent)); + if (hoverLine > scrollLine + visibleLines) + ScrollY = (int)((double)(hoverLine - visibleLines) * (fe.Ascent + fe.Descent)); + NotifyValueChanged("MouseY", mouseLocalPos.Y + ScrollY); + NotifyValueChanged("ScrollY", ScrollY); + NotifyValueChanged("VisibleLines", visibleLines); + NotifyValueChanged("HoverLine", hoverLine); + NotifyValueChanged("ScrollLine", hoverLine); hoverLoc = new CharLocation (hoverLine, -1, mouseLocalPos.X); using (Context gr = new Context (IFace.surf)) { setFontForContext (gr); @@ -486,7 +494,7 @@ namespace Crow } if (!CurrentLoc.Value.HasVisualX) { setFontForContext (ctx); - lock (linesMutex) { + lock (linesMutex) { if (currentLoc?.Column < 0) { updateLocation (ctx, ClientRectangle.Width, ref currentLoc); NotifyValueChanged ("CurrentColumn", CurrentColumn); @@ -507,7 +515,7 @@ namespace Crow //} Rectangle c = ScreenCoordinates (textCursor.Value + Slot.Position + ClientRectangle.Position); ctx.ResetClip (); - Foreground.SetAsSource (IFace, ctx, c); + Foreground.SetAsSource (IFace, ctx, c); ctx.LineWidth = 1.0; ctx.MoveTo (0.5 + c.X, c.Y); ctx.LineTo (0.5 + c.X, c.Bottom); @@ -582,7 +590,7 @@ namespace Crow return false; } try { - bool result = base.UpdateLayout (layoutType); + bool result = base.UpdateLayout (layoutType); return result; } finally { System.Threading.Monitor.Exit (linesMutex); @@ -604,18 +612,18 @@ namespace Crow DbgLogger.EndEvent(DbgEvtType.GOMeasure); return Margin * 2 + (lt == LayoutingType.Height ? cachedTextSize.Height : cachedTextSize.Width); } - + protected override void onDraw (Context gr) { base.onDraw (gr); setFontForContext (gr); - + if (!textMeasureIsUpToDate) { lock (linesMutex) measureTextBounds (gr); } - + if (ClipToClientRect) { gr.Save (); CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius); @@ -624,7 +632,7 @@ namespace Crow lock (linesMutex) drawContent (gr); - + if (ClipToClientRect) gr.Restore (); } @@ -636,7 +644,7 @@ namespace Crow base.onFocused (sender, e); if (CurrentLoc == null) { - selectionStart = new CharLocation (0, 0); + selectionStart = new CharLocation (0, 0); CurrentLoc = new CharLocation (lines.Count - 1, lines[lines.Count - 1].Length); } @@ -652,7 +660,7 @@ namespace Crow public override void onMouseEnter (object sender, MouseMoveEventArgs e) { base.onMouseEnter (sender, e); if (Focusable) - IFace.MouseCursor = MouseCursor.ibeam; + IFace.MouseCursor = MouseCursor.ibeam; } public override void onMouseMove (object sender, MouseMoveEventArgs e) { @@ -661,16 +669,16 @@ namespace Crow updateHoverLocation (ScreenPointToLocal (e.Position)); if (HasFocus && IFace.IsDown (MouseButton.Left)) { - CurrentLoc = hoverLoc; - RegisterForRedraw (); + CurrentLoc = hoverLoc; + RegisterForRedraw (); } - } + } public override void onMouseDown (object sender, MouseButtonEventArgs e) { if (e.Button == Glfw.MouseButton.Left) { targetColumn = -1; - if (HasFocus) { - if (!IFace.Shift) + if (HasFocus) { + if (!IFace.Shift) selectionStart = hoverLoc; else if (!selectionStart.HasValue) selectionStart = CurrentLoc; @@ -678,7 +686,7 @@ namespace Crow IFace.forceTextCursor = true; RegisterForRedraw (); e.Handled = true; - } + } } base.onMouseDown (sender, e); @@ -688,7 +696,7 @@ namespace Crow { base.onMouseUp (sender, e); if (e.Button != MouseButton.Left || !HasFocus || !selectionStart.HasValue) - return; + return; if (selectionStart.Value == CurrentLoc.Value) selectionStart = null; } @@ -699,7 +707,7 @@ namespace Crow return; GotoWordStart (); - selectionStart = CurrentLoc; + selectionStart = CurrentLoc; GotoWordEnd (); RegisterForRedraw (); } @@ -726,8 +734,8 @@ namespace Crow if (selection.IsEmpty) { if (selection.Start == _text.Length) return; - if (CurrentLoc.Value.Column >= lines[CurrentLoc.Value.Line].Length) - update (new TextChange (selection.Start, lines[CurrentLoc.Value.Line].LineBreakLength, "")); + if (CurrentLoc.Value.Column >= lines[CurrentLoc.Value.Line].Length) + update (new TextChange (selection.Start, lines[CurrentLoc.Value.Line].LineBreakLength, "")); else update (new TextChange (selection.Start, 1, "")); } else { @@ -813,7 +821,7 @@ namespace Crow } autoAdjustScroll = true; IFace.forceTextCursor = true; - e.Handled = true; + e.Handled = true; } #endregion #endregion @@ -846,8 +854,8 @@ namespace Crow return null; } else if (cursor.Right < 0 || cursor.X > cb.Width || cursor.Y < 0 || cursor.Bottom > cb.Height) return null; - - return cursor; + + return cursor; } void updateMaxScrolls (LayoutingType layout) { @@ -875,7 +883,7 @@ namespace Crow TextSpan selection = Selection; if (selection.IsEmpty) return; - IFace.Clipboard = SelectedText; + IFace.Clipboard = SelectedText; } public virtual void Paste () { TextSpan selection = Selection; @@ -906,7 +914,7 @@ namespace Crow src.Slice (0, change.Start).CopyTo (tmp); change.ChangedText.AsSpan ().CopyTo (tmp.Slice (change.Start)); src.Slice (change.End).CopyTo (tmp.Slice (change.Start + change.ChangedText.Length)); - + _text = tmp.ToString (); lines.Update (change); //lines.Update (_text); @@ -916,12 +924,12 @@ namespace Crow textMeasureIsUpToDate = false; IFace.forceTextCursor = true; } - + OnTextChanged (this, new TextChangeEventArgs (change)); - + RegisterForGraphicUpdate (); } - + #endregion } diff --git a/CrowEditBase/src/LogViewerWidget.cs b/CrowEditBase/src/LogViewerWidget.cs index ee2f4a1..3cab786 100644 --- a/CrowEditBase/src/LogViewerWidget.cs +++ b/CrowEditBase/src/LogViewerWidget.cs @@ -7,6 +7,8 @@ using System.Xml.Serialization; using System.ComponentModel; using System.Collections; using Crow.Drawing; +using System.Threading.Tasks; +using System.Linq; namespace Crow { @@ -14,16 +16,22 @@ namespace Crow { Minimal, Normal, Full, Debug } + [Flags] public enum LogType { - Low, - Normal, - High, - Debug, - Warning, - Error, - Custom1, - Custom2, - Custom3, + None = 0, + Low = 0x0001, + Normal = 0x0002, + High = 0x0004, + Message = Low | Normal | High, + Debug = 0x0008, + Warning = 0x0010, + Error = 0x0020, + WarnErr = Warning | Error, + Custom1 = 0x0040, + Custom2 = 0x0080, + Custom3 = 0x0100, + Custom = Custom1 | Custom2 | Custom3, + all = Message | WarnErr | Custom | Debug, } public class LogEntry { public LogType Type; @@ -37,48 +45,188 @@ namespace Crow public class LogViewerWidget : ScrollingObject { ObservableList lines; - bool scrollOnOutput; + LogEntry[] filteredLines; + object filteredLinesMutex = new object (); + bool scrollOnOutput, caseSensitiveSearch, allWordSearch; int visibleLines = 1; FontExtents fe; + int hoverEntryIdx = -1, curEntryIdx; + string searchString; + LogType filter; + public CommandGroup SearchCommands => new CommandGroup( + new ActionCommand("Prev", () => performSearch(searchString, true, true)), + new ActionCommand("Next", () => performSearch(searchString, true)) + ); + [DefaultValue(true)] public virtual bool ScrollOnOutput { - get { return scrollOnOutput; } + get => scrollOnOutput; set { if (scrollOnOutput == value) return; scrollOnOutput = value; NotifyValueChanged ("ScrollOnOutput", scrollOnOutput); - } } + [DefaultValue(LogType.all)] + public LogType Filter { + get => filter; + set { + if (filter == value) + return; + filter = value; + NotifyValueChangedAuto (filter); + updateFilteredLines (); + RegisterForRedraw (); + } + } + bool updateFilteredLinesRequest = true; + void updateFilteredLines () { + if (Lines != null) { + lock (filteredLinesMutex) + lock (lines) + filteredLines = Lines.Where (l=>((int)l.Type & (int)filter) > 0).ToArray(); + MaxScrollY = filteredLines.Length - visibleLines; + if (scrollOnOutput) + ScrollY = MaxScrollY; + } + updateFilteredLinesRequest = false; + } public virtual ObservableList Lines { - get { return lines; } + get => lines; set { if (lines == value) return; if (lines != null) { lines.ListAdd -= Lines_ListAdd; lines.ListRemove -= Lines_ListRemove; + lines.ListClear -= Lines_ListClear; } lines = value; if (lines != null) { lines.ListAdd += Lines_ListAdd; lines.ListRemove += Lines_ListRemove; + lines.ListClear += Lines_ListClear; + updateFilteredLinesRequest = true; } NotifyValueChanged ("Lines", lines); RegisterForGraphicUpdate (); } } + public int CurrentEntryIndex { + get => curEntryIdx; + set { + if (curEntryIdx == value) + return; + curEntryIdx = value; + NotifyValueChangedAuto (curEntryIdx); + if (curEntryIdx >= 0) { + if (curEntryIdx < ScrollY || (curEntryIdx > ScrollY + visibleLines)) + ScrollY = curEntryIdx - visibleLines / 2; + } + RegisterForRedraw(); + } + } + [DefaultValue (true)] + public virtual bool CaseSensitiveSearch { + get { return caseSensitiveSearch; } + set { + if (caseSensitiveSearch == value) + return; + caseSensitiveSearch = value; + NotifyValueChanged ("CaseSensitiveSearch", caseSensitiveSearch); + + } + } + [DefaultValue (false)] + public virtual bool AllWordSearch { + get { return allWordSearch; } + set { + if (allWordSearch == value) + return; + allWordSearch = value; + NotifyValueChangedAuto (allWordSearch); + } + } + public string SearchString { + get => searchString; + set { + if (searchString == value) + return; + searchString = value; + NotifyValueChanged ("SearchString", searchString); + + Task.Run (() => performSearch (searchString)); + } + } + private void onSearch (object sender, KeyEventArgs e) { + if (e.Key == Glfw.Key.Enter) + performSearch (SearchString, true); + } + void performSearchBackward (LogEntry[] entries, string str, bool next = false) { + int idx = CurrentEntryIndex < 0 ? entries.Length - 1 : next ? CurrentEntryIndex - 1 : CurrentEntryIndex; + while (idx >= 0) { + if (entries[idx].msg.Contains (str, CaseSensitiveSearch ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase)) { + CurrentEntryIndex = idx; + return; + } + idx--; + } + if (CurrentEntryIndex <= 0)//all the list has been searched + return; + idx = entries.Length - 1; + while (idx > CurrentEntryIndex) { + if (entries[idx].msg.Contains (str, CaseSensitiveSearch ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase)) { + CurrentEntryIndex = idx; + return; + } + idx--; + } + } + void performSearchForward (LogEntry[] entries, string str, bool next = false) { + int idx = CurrentEntryIndex < 0 ? 0 : next ? CurrentEntryIndex + 1 : CurrentEntryIndex; + while (idx < entries.Length) { + if (entries[idx].msg.Contains (str, CaseSensitiveSearch ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase)) { + CurrentEntryIndex = idx; + return; + } + idx++; + } + if (CurrentEntryIndex <= 0)//all the list has been searched + return; + idx = 0; + while (idx < CurrentEntryIndex) { + if (entries[idx].msg.Contains (str, CaseSensitiveSearch ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase)) { + CurrentEntryIndex = idx; + return; + } + idx++; + } + } + void performSearch (string str, bool next = false, bool backward = false) { + if (string.IsNullOrEmpty (str) || filteredLines == null) + return; + LogEntry[] entries = filteredLines.ToArray (); + if (entries.Length == 0) { + CurrentEntryIndex = -1; + return; + } + if (backward) + performSearchBackward (entries, str, next); + else + performSearchForward (entries, str, next); + } + void Lines_ListAdd (object sender, ListChangedEventArg e) { + updateFilteredLinesRequest = true; + RegisterForRedraw(); // try // { - MaxScrollY = lines.Count - visibleLines; - if (scrollOnOutput) - ScrollY = MaxScrollY; - + //updateFilteredLines(); + // } // catch (System.Exception ex) // { @@ -88,7 +236,16 @@ namespace Crow void Lines_ListRemove (object sender, ListChangedEventArg e) { - MaxScrollY = lines.Count - visibleLines; + /*updateFilteredLines(); + MaxScrollY = filteredLines.Length - visibleLines;*/ + updateFilteredLinesRequest = true; + RegisterForRedraw (); + } + void Lines_ListClear (object sender, ListClearEventArg e) { + lock (filteredLinesMutex) + filteredLines = null; + MaxScrollX = ScrollY = 0; + RegisterForRedraw (); } @@ -107,15 +264,20 @@ namespace Crow fe = gr.FontExtents; } } + if (updateFilteredLinesRequest) + updateFilteredLines (); visibleLines = (int)Math.Floor ((double)ClientRectangle.Height / fe.Height); - MaxScrollY = lines == null ? 0 : lines.Count - visibleLines; + MaxScrollY = filteredLines == null ? 0 : filteredLines.Length - visibleLines; } } protected override void onDraw (Context gr) { base.onDraw (gr); - if (lines == null) + if (updateFilteredLinesRequest) + updateFilteredLines (); + + if (filteredLines == null) return; gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight); @@ -127,17 +289,23 @@ namespace Crow double y = ClientRectangle.Y; double x = ClientRectangle.X - ScrollX; - lock (lines) { + lock (filteredLinesMutex) { for (int i = 0; i < visibleLines; i++) { - if (i + ScrollY >= Lines.Count) + int idx = i + ScrollY; + if (idx >= filteredLines.Length) break; - //if ((lines [i + Scroll] as string).StartsWith ("error", StringComparison.OrdinalIgnoreCase)) { - // errorFill.SetAsSource (gr); - // gr.Rectangle (x, y, (double)r.Width, fe.Height); - // gr.Fill (); - // Foreground.SetAsSource (gr); - //} - LogEntry le = lines[i+ScrollY]; + LogEntry le = filteredLines[idx]; + + if (idx == curEntryIdx) { + gr.Rectangle (x, y, r.Width, fe.Height); + gr.SetSource (Color.Parse ("#5555ff55")); + gr.Fill (); + } else if (idx == hoverEntryIdx) { + gr.Rectangle (x, y, r.Width, fe.Height); + gr.SetSource (Color.Parse ("#8B451355")); + gr.Fill (); + } + switch (le.Type) { case LogType.Low: gr.SetSource (Colors.DimGrey); @@ -161,7 +329,7 @@ namespace Crow gr.SetSource (Colors.Cyan); break; case LogType.Custom2: - gr.SetSource (Colors.Green); + gr.SetSource (Colors.Lime); break; case LogType.Custom3: gr.SetSource (Colors.LightPink); @@ -170,11 +338,43 @@ namespace Crow gr.MoveTo (x, y + fe.Ascent); gr.ShowText (le.msg); y += fe.Height; - gr.Fill (); } } } - + public override void onMouseLeave(object sender, MouseMoveEventArgs e) + { + hoverEntryIdx = -1; + base.onMouseLeave(sender, e); + } + public override void onMouseDown(object sender, MouseButtonEventArgs e) + { + if (e.Button == Glfw.MouseButton.Left) { + CurrentEntryIndex = hoverEntryIdx; + e.Handled = true; + } + base.onMouseDown(sender, e); + } + public override void onMouseMove(object sender, MouseMoveEventArgs e) + { + base.onMouseMove(sender, e); + updateHoverEntryIdx (e.Position); + } + public override void onMouseWheel(object sender, MouseWheelEventArgs e) + { + base.onMouseWheel(sender, e); + updateHoverEntryIdx (IFace.MousePosition); + } + void updateHoverEntryIdx (Point mpos) { + PointD mouseLocalPos = ScreenPointToLocal (mpos); + lock (filteredLinesMutex) { + if (filteredLines == null) { + hoverEntryIdx = -1; + return; + } + hoverEntryIdx = ScrollY + (int)Math.Min (Math.Max (0, Math.Floor (mouseLocalPos.Y / fe.Height)), filteredLines.Length - 1); + } + RegisterForRedraw (); + } } } diff --git a/CrowEditBase/src/Plugin.cs b/CrowEditBase/src/Plugin.cs index 8639a95..44356df 100644 --- a/CrowEditBase/src/Plugin.cs +++ b/CrowEditBase/src/Plugin.cs @@ -21,7 +21,7 @@ namespace CrowEditBase public Assembly Load (AssemblyName assemblyName) => loadContext.LoadFromAssemblyName (assemblyName); - + public bool TryGet (AssemblyName assemblyName, out Assembly assembly) { assembly = loadContext.Assemblies.FirstOrDefault (a=>a.GetName().Name == assemblyName.Name); return assembly != null; @@ -42,18 +42,18 @@ namespace CrowEditBase } public readonly string Name; public Plugin (string fullPath) { - initCommands (); + initCommands (); FullPath = fullPath; Name = Path.GetFileNameWithoutExtension (FullPath); } public Command CMDLoad, CMDUnload, CMDReload; public CommandGroup Commands => new CommandGroup ( CMDLoad, CMDUnload, CMDReload); - + protected virtual void initCommands () { - CMDLoad = new Command ("Load", Load, "#icons.reply.svg", false); - CMDUnload = new Command ("Unload", Unload, "#icons.share-arrow.svg", false); - CMDReload = new Command ("Reload", () => { Unload(); Load();}, "#icons.refresh.svg", false); + CMDLoad = new ActionCommand ("Load", Load, "#icons.reply.svg", false); + CMDUnload = new ActionCommand ("Unload", Unload, "#icons.share-arrow.svg", false); + CMDReload = new ActionCommand ("Reload", () => { Unload(); Load();}, "#icons.refresh.svg", false); } public void Load () { @@ -62,10 +62,10 @@ namespace CrowEditBase if (loadContext == null) loadContext = new PluginsLoadContext(FullPath); - + App.AddCrowAssembly (loadContext.MainAssembly); - string defaultConfigName = loadContext.MainAssembly.GetManifestResourceNames ().FirstOrDefault(c=>c.EndsWith ("default.conf")); + string defaultConfigName = loadContext.MainAssembly.GetManifestResourceNames ().FirstOrDefault(c=>c.EndsWith ("default.conf")); if (!string.IsNullOrEmpty (defaultConfigName)) { Configuration config = new Configuration (loadContext.MainAssembly.GetManifestResourceStream (defaultConfigName)); string fileAssociations = config.Get ("FileAssociations"); @@ -75,11 +75,11 @@ namespace CrowEditBase foreach (string associations in fileAssociations.Split (';')) { string[] typeExts = associations.Split (':'); Type clientClass = loadContext.MainAssembly.GetType (typeExts[0]); - foreach (string ext in typeExts[1].Split (',')) - App.AddFileAssociation (ext, clientClass); + foreach (string ext in typeExts[1].Split (',')) + App.AddFileAssociation (ext, clientClass); } } - catch (System.Exception ex) { + catch (System.Exception ex) { throw; } } diff --git a/CrowEditBase/src/Project.cs b/CrowEditBase/src/Project.cs index 847b629..1c9bb93 100644 --- a/CrowEditBase/src/Project.cs +++ b/CrowEditBase/src/Project.cs @@ -14,7 +14,7 @@ using static CrowEditBase.CrowEditBase; namespace CrowEditBase { - public abstract class Project : CrowEditComponent { + public abstract class Project : CrowEditComponent { bool isLoaded; protected Project parent; protected IList subProjects; @@ -37,7 +37,7 @@ namespace CrowEditBase public abstract string Name { get; } public string Caption => Name; public bool IsLoaded { - get { return isLoaded; } + get => isLoaded; set { if (value == isLoaded) return; @@ -49,20 +49,20 @@ namespace CrowEditBase CMDLoad.CanExecute = !IsLoaded; CMDReload.CanExecute = CMDUnload.CanExecute = IsLoaded; } - } + } public Project (string fullPath) { initCommands (); - FullPath = fullPath; + FullPath = fullPath; } public Command CMDLoad, CMDUnload, CMDReload, CMDClose; public virtual CommandGroup Commands => new CommandGroup ( CMDLoad, CMDUnload, CMDReload, CMDClose); - + void initCommands () { - CMDLoad = new Command ("Load", Load, "#icons.reply.svg", false); - CMDUnload = new Command ("Unload", Unload, "#icons.share-arrow.svg", false); - CMDReload = new Command ("Reload", () => { Unload(); Load();}, "#icons.refresh.svg", false); - CMDClose = new Command ("Close", Close, "#icons.share-arrow.svg", true); + CMDLoad = new ActionCommand ("Load", Load, "#icons.reply.svg", false); + CMDUnload = new ActionCommand ("Unload", Unload, "#icons.share-arrow.svg", false); + CMDReload = new ActionCommand ("Reload", () => { Unload(); Load();}, "#icons.refresh.svg", false); + CMDClose = new ActionCommand ("Close", Close, "#icons.share-arrow.svg", true); } public abstract void Load (); diff --git a/CrowEditBase/src/Service.cs b/CrowEditBase/src/Service.cs index eb53143..fa33fd1 100644 --- a/CrowEditBase/src/Service.cs +++ b/CrowEditBase/src/Service.cs @@ -19,15 +19,15 @@ namespace CrowEditBase Stopped } protected Service () { - CMDStart = new Command ("Start", Start, "#icons.play-button.svg", true); - CMDStop = new Command ("Stop", Stop, "#icons.stop.svg", false); - CMDPause = new Command ("Pause", Pause, "#icons.pause-symbol.svg", false); - CMDOpenConfig = new Command ("Service configuration", + CMDStart = new ActionCommand ("Start", Start, "#icons.play-button.svg", true); + CMDStop = new ActionCommand ("Stop", Stop, "#icons.stop.svg", false); + CMDPause = new ActionCommand ("Pause", Pause, "#icons.pause-symbol.svg", false); + CMDOpenConfig = new ActionCommand ("Service configuration", () => CrowEditBase.App.LoadWindow (ConfigurationWindowPath, this), "#icons.cogwheel.svg", true); Commands = new CommandGroup (CMDStart, CMDPause, CMDStop, CMDOpenConfig); if (CrowEditBase.App.TryGetWindow (ConfigurationWindowPath, out Window win)) - win.DataSource = this; + win.DataSource = this; } public Command CMDStart, CMDStop, CMDPause, CMDOpenConfig; public CommandGroup Commands; @@ -55,7 +55,7 @@ namespace CrowEditBase public abstract void Start (); public abstract void Stop (); public abstract void Pause (); - public virtual string ConfigurationWindowPath => "#CrowEditBase.ui.winServiceConfig.crow"; + public virtual string ConfigurationWindowPath => "#ui.winServiceConfig.crow"; public virtual Document OpenDocument (string fullPath) => null; } diff --git a/CrowEditBase/src/TextDocument.cs b/CrowEditBase/src/TextDocument.cs index cfbf41a..ada9c1b 100644 --- a/CrowEditBase/src/TextDocument.cs +++ b/CrowEditBase/src/TextDocument.cs @@ -14,7 +14,7 @@ namespace CrowEditBase { public class TextDocument : Document { public TextDocument (string fullPath) - : base (fullPath) { + : base (fullPath) { reloadFromFile (); } @@ -38,11 +38,11 @@ namespace CrowEditBase Dictionary> registeredClients = new Dictionary>(); public override bool TryGetState(object client, out T state) { state = default; - if (editorRWLock.TryEnterReadLock (10)) { + if (editorRWLock.TryEnterReadLock (10)) { try { state = (T)(object)registeredClients[client]; registeredClients[client] = null; - } finally { + } finally { editorRWLock.ExitReadLock (); } } @@ -64,7 +64,7 @@ namespace CrowEditBase void notifyClients (TextChange tc, object triggeringClient = null) { object[] clients = registeredClients.Keys.ToArray (); for (int i = 0; i < clients.Length; i++) { - if (clients[i] != triggeringClient) + if (clients[i] != triggeringClient) notifyClient (clients[i], tc); } } @@ -73,7 +73,7 @@ namespace CrowEditBase registeredClients[client] = new List (); registeredClients[client].Add (tc); } - + protected override void writeToDisk () { @@ -86,7 +86,7 @@ namespace CrowEditBase } protected override void readFromDisk() { - using (Stream s = new FileStream (FullPath, FileMode.Open)) { + using (Stream s = new FileStream (FullPath, FileMode.Open)) { using (StreamReader sr = new StreamReader (s)) { Source = origSource = sr.ReadToEnd (); encoding = sr.CurrentEncoding; @@ -103,7 +103,7 @@ namespace CrowEditBase if (File.Exists (FullPath)) readFromDisk (); else - initNewFile (); + initNewFile (); resetUndoRedo (); } finally { editorRWLock.ExitWriteLock (); @@ -113,7 +113,7 @@ namespace CrowEditBase protected Stack redoStack = new Stack (); - + protected void saveFileDialog_OkClicked (object sender, EventArgs e) { FileDialog fd = sender as FileDialog; @@ -170,7 +170,7 @@ namespace CrowEditBase undoStack.Clear (); redoStack.Clear (); CMDUndo.CanExecute = false; - CMDRedo.CanExecute = false; + CMDRedo.CanExecute = false; } protected bool disableTextChangedEvent = false; protected virtual void apply (TextChange change) { diff --git a/CrowEditBase/src/TreeNode.cs b/CrowEditBase/src/TreeNode.cs index 77ab2b7..7de3c53 100644 --- a/CrowEditBase/src/TreeNode.cs +++ b/CrowEditBase/src/TreeNode.cs @@ -89,7 +89,7 @@ namespace CrowEditBase } public bool HasChildren => children?.Count > 0; public abstract string Icon { get; } - public virtual string IconSub => null; + public virtual string IconSub => null; public IEnumerable Flatten { get { diff --git a/CrowEditBase/ui/CategoryExp.template b/CrowEditBase/ui/CategoryExp.template index f546492..d1b0da4 100755 --- a/CrowEditBase/ui/CategoryExp.template +++ b/CrowEditBase/ui/CategoryExp.template @@ -18,4 +18,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/CrowEditBase/ui/CrowEdit.style b/CrowEditBase/ui/CrowEdit.style new file mode 100644 index 0000000..8bdd96d --- /dev/null +++ b/CrowEditBase/ui/CrowEdit.style @@ -0,0 +1,131 @@ +SmallUIFont = "sans, 10"; +SmallFont = "consolas, 10"; +InactiveTabBackground = "DarkGrey"; +SelectedTabBackground = "Onyx"; +InactiveTabForeground = "Grey"; +SelectedTabForeground = "White"; +MenuIconSize = "16"; + +ControlForeground = "LightGrey"; +ControlCaptionHoverColor = "White"; + +ControlHighlight = "RoyalBlue"; +ControlIdle = "Jet"; + +DockWindowBackground = "DarkGrey"; + +Editor { + Background="White"; + Foreground="Black"; + MouseWheelSpeed = "20"; + BubbleMouseEvent ="None"; +} + +icon { + Width="14"; + Height="14"; +} +MemberViewLabel { + Margin="1"; + Height="Fit"; + Width="50%"; + Background="White"; +} +MemberViewHStack { + Focusable="true"; + Height="Fit"; + Spacing="1"; + MouseEnter="{Background=SteelBlue}"; + MouseLeave="{Background=Transparent}"; +} + +IcoBut { + Template = "#Crow.Coding.ui.IcoBut.template"; + MinimumSize = "10,10"; + Width = "8"; + Height = "14"; + Background = "White"; +} +Spinner { + Template = "#ui.spinner.template"; +} +TreeIcon { + Width="18"; + Height="18"; +} +TreeIconSmall { + Width="12"; + Height="12"; +} +TreeLabel { + Foreground="White"; + Margin = "1"; +} +Splitter { + Thickness="1"; + Background="Transparent"; + Hover="{Background=White}"; + Unhover="{Background=Transparent}"; +} +DockStack { + Margin="0"; + Spacing="0"; +} +DockWindow { + Template = "#ui.DockWindow.template"; + Background = "${DockWindowBackground}"; + Margin="0"; + RootDataLevel = "true"; +} +DockWindow2 { + Template = "#ui.DockWindow2.template"; + Background = "${DockWindowBackground}"; + Margin="0"; + RootDataLevel = "true"; +} +DockWinTitleBarMenu { + ItemTemplate = "#ui.DockWinTitleBarMenu.itemp"; +} +DockWinTitleBarIconMenu { + Template = "#ui.DockWinTitleBarIconMenu.template"; + ItemTemplate = "#Crow.WindowButton.template"; + Width = "Fit"; + Height = "Fit"; +} +DockingTabView { + Template = "#ui.DockingTabView.template"; +} +MenuItem { + Template = "#ui.MenuItem.template"; +} + +MenuIcon { + Margin = "1"; + Width = "${MenuIconSize}"; + Height = "${MenuIconSize}"; +} + +suggestionsListBox { + Template = "#ui.Suggestions.template"; + Width = "Fit"; + Height = "Fit"; + MaximumSize = "300, 120"; + Background = "Jet"; + UseLoadingThread = "false"; +} +EnumSelector { + Template = "#ui.EnumSelector.template"; + //ItemStyle = "CheckBox"; +} +CheckBox { + Template= "#Crow.CheckBox2.template"; + Width = "Stretched"; + Height = "Fit"; + CornerRadius = "3"; + Background = "${ControlIdle}"; + Foreground = "${ControlForeground}"; + Checked = "{Background=${ControlHighlight}}"; + Unchecked = "{Background=${ControlIdle}}"; + MouseEnter = "{Foreground=${ControlCaptionHoverColor}}"; + MouseLeave = "{Foreground=${ControlForeground}}"; +} \ No newline at end of file diff --git a/CrowEditBase/ui/DockWinTitleBarIconMenu.template b/CrowEditBase/ui/DockWinTitleBarIconMenu.template new file mode 100644 index 0000000..29864d4 --- /dev/null +++ b/CrowEditBase/ui/DockWinTitleBarIconMenu.template @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/CrowEditBase/ui/DockWinTitleBarMenu.itemp b/CrowEditBase/ui/DockWinTitleBarMenu.itemp new file mode 100644 index 0000000..9ecd788 --- /dev/null +++ b/CrowEditBase/ui/DockWinTitleBarMenu.itemp @@ -0,0 +1,10 @@ + + + + diff --git a/CrowEditBase/ui/DockWindow.template b/CrowEditBase/ui/DockWindow.template new file mode 100644 index 0000000..3540140 --- /dev/null +++ b/CrowEditBase/ui/DockWindow.template @@ -0,0 +1,22 @@ + + + + + + + + + + + + + diff --git a/ui/DockWindow.template b/CrowEditBase/ui/DockWindow2.template similarity index 75% rename from ui/DockWindow.template rename to CrowEditBase/ui/DockWindow2.template index 2c23fa0..17c6eba 100644 --- a/ui/DockWindow.template +++ b/CrowEditBase/ui/DockWindow2.template @@ -2,9 +2,9 @@ - - - + diff --git a/ui/DockingTabView.template b/CrowEditBase/ui/DockingTabView.template similarity index 86% rename from ui/DockingTabView.template rename to CrowEditBase/ui/DockingTabView.template index 7f6e661..908c6c4 100644 --- a/ui/DockingTabView.template +++ b/CrowEditBase/ui/DockingTabView.template @@ -1,15 +1,15 @@  - + + SelectedItem="{²./SelectedItem}"> - + Unselected="{.DataSource.IsVisible='false'};{Background=${InactiveTabBackground}};{Foreground=${InactiveTabForeground}}"> + - + diff --git a/CrowEditBase/ui/EnumSelector.template b/CrowEditBase/ui/EnumSelector.template new file mode 100644 index 0000000..c33c32f --- /dev/null +++ b/CrowEditBase/ui/EnumSelector.template @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/CrowEditBase/ui/IDE.style b/CrowEditBase/ui/IDE.style deleted file mode 100644 index e5ec8d4..0000000 --- a/CrowEditBase/ui/IDE.style +++ /dev/null @@ -1,43 +0,0 @@ -Editor { - Background="White"; - Foreground="Black"; - MouseWheelSpeed = "20"; - BubbleMouseEvent ="None"; -} - -icon { - Width="14"; - Height="14"; -} -MemberViewLabel { - Margin="1"; - Height="Fit"; - Width="50%"; - Background="White"; -} -MemberViewHStack { - Focusable="true"; - Height="Fit"; - Spacing="1"; - MouseEnter="{Background=SteelBlue}"; - MouseLeave="{Background=Transparent}"; -} - -IcoBut { - Template = "#Crow.Coding.ui.IcoBut.template"; - MinimumSize = "10,10"; - Width = "8"; - Height = "14"; - Background = "White"; -} -Spinner { - Template = "#CrowEditBase.ui.spinner.template"; -} -TreeIcon { - Width="18"; - Height="18"; -} -TreeLabel { - Foreground="White"; - Margin = "1"; -} \ No newline at end of file diff --git a/ui/MenuButton.template b/CrowEditBase/ui/MenuButton.template similarity index 95% rename from ui/MenuButton.template rename to CrowEditBase/ui/MenuButton.template index 38ce0f9..92414b2 100644 --- a/ui/MenuButton.template +++ b/CrowEditBase/ui/MenuButton.template @@ -6,6 +6,6 @@ MouseLeave="{Background=Transparent}"> + diff --git a/ui/MenuItem.itmp b/CrowEditBase/ui/MenuItem.itmp similarity index 88% rename from ui/MenuItem.itmp rename to CrowEditBase/ui/MenuItem.itmp index 67a67c3..705ee04 100644 --- a/ui/MenuItem.itmp +++ b/CrowEditBase/ui/MenuItem.itmp @@ -1,5 +1,5 @@  - + - + diff --git a/ui/Suggestions.template b/CrowEditBase/ui/Suggestions.template similarity index 99% rename from ui/Suggestions.template rename to CrowEditBase/ui/Suggestions.template index 8bc5574..2cfb74a 100644 --- a/ui/Suggestions.template +++ b/CrowEditBase/ui/Suggestions.template @@ -7,7 +7,7 @@ diff --git a/CrowEditBase/ui/TreeExpandable.template b/CrowEditBase/ui/TreeExpandable.template index 8838166..488f879 100644 --- a/CrowEditBase/ui/TreeExpandable.template +++ b/CrowEditBase/ui/TreeExpandable.template @@ -1,5 +1,5 @@  - + @@ -11,7 +11,7 @@ Selected="{Background=RoyalBlue}" Unselected="{Background=Transparent}"> - - + diff --git a/ui/sourceEditor.itmp b/CrowEditBase/ui/sourceEditor.itmp similarity index 60% rename from ui/sourceEditor.itmp rename to CrowEditBase/ui/sourceEditor.itmp index 91ac4c8..527d5cf 100644 --- a/ui/sourceEditor.itmp +++ b/CrowEditBase/ui/sourceEditor.itmp @@ -14,10 +14,20 @@ + +