From: Jean-Philippe Bruyère Date: Thu, 16 Sep 2021 19:29:17 +0000 (+0000) Subject: wip X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=1d0b26c321355210c84f853df425b750a3602a13;p=jp%2Fcrowedit.git wip --- 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/CrowEditBase/ui/DockWindow2.template b/CrowEditBase/ui/DockWindow2.template new file mode 100644 index 0000000..17c6eba --- /dev/null +++ b/CrowEditBase/ui/DockWindow2.template @@ -0,0 +1,42 @@ + + + + + + + + + diff --git a/CrowEditBase/ui/DockingTabView.template b/CrowEditBase/ui/DockingTabView.template new file mode 100644 index 0000000..908c6c4 --- /dev/null +++ b/CrowEditBase/ui/DockingTabView.template @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + 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/CrowEditBase/ui/MenuButton.template b/CrowEditBase/ui/MenuButton.template new file mode 100644 index 0000000..92414b2 --- /dev/null +++ b/CrowEditBase/ui/MenuButton.template @@ -0,0 +1,11 @@ + + diff --git a/CrowEditBase/ui/MenuItem.itmp b/CrowEditBase/ui/MenuItem.itmp new file mode 100644 index 0000000..705ee04 --- /dev/null +++ b/CrowEditBase/ui/MenuItem.itmp @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/CrowEditBase/ui/MenuItem.template b/CrowEditBase/ui/MenuItem.template new file mode 100644 index 0000000..df853bc --- /dev/null +++ b/CrowEditBase/ui/MenuItem.template @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/CrowEditBase/ui/Service.itmp b/CrowEditBase/ui/Service.itmp index aa1d3d6..9ef5292 100644 --- a/CrowEditBase/ui/Service.itmp +++ b/CrowEditBase/ui/Service.itmp @@ -5,7 +5,7 @@ - + diff --git a/CrowEditBase/ui/Suggestions.template b/CrowEditBase/ui/Suggestions.template new file mode 100644 index 0000000..2cfb74a --- /dev/null +++ b/CrowEditBase/ui/Suggestions.template @@ -0,0 +1,13 @@ + + + + + + + + + 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/CrowEditBase/ui/sourceEditor.itmp b/CrowEditBase/ui/sourceEditor.itmp new file mode 100644 index 0000000..527d5cf --- /dev/null +++ b/CrowEditBase/ui/sourceEditor.itmp @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + diff --git a/README.md b/README.md index 66a5dab..71ae2bd 100644 --- a/README.md +++ b/README.md @@ -1 +1,7 @@ # CrowEdit + +

+ + + +

\ No newline at end of file diff --git a/clean.sh b/clean.sh deleted file mode 100755 index 08b3c61..0000000 --- a/clean.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -rm -fr build && find . -iname bin -o -iname obj -o -iname packages -o -iname build | xargs rm -rf diff --git a/plugins/CECrowPlugin/src/CrowService.cs b/plugins/CECrowPlugin/src/CrowService.cs index 8af2687..71bacd4 100644 --- a/plugins/CECrowPlugin/src/CrowService.cs +++ b/plugins/CECrowPlugin/src/CrowService.cs @@ -20,7 +20,7 @@ using System.Runtime.CompilerServices; using static CrowEditBase.CrowEditBase; namespace Crow -{ +{ public class CrowService : Service { public CrowService () : base () { @@ -28,7 +28,7 @@ namespace Crow //resolve other plugins dependencies //AssemblyLoadContext.GetLoadContext (Assembly.GetExecutingAssembly ()).Resolving += resolvePluginRefs; - + if (CrowEditBase.CrowEditBase.App.TryGetWindow ("#CECrowPlugin.ui.winLogGraph.crow", out Window win)) win.DataSource = this; } @@ -52,18 +52,19 @@ namespace Crow void updateCrowApp () { if (App.CurrentProject is CERoslynPlugin.SolutionProject sol) { - CERoslynPlugin.SolutionProject project = App.CurrentProject as CERoslynPlugin.SolutionProject; - Console.WriteLine (project.Name); + if (sol.StartupProject is CERoslynPlugin.MSBuildProject csprj) { + + } }else if (App.CurrentProject is CERoslynPlugin.MSBuildProject csprj){ CERoslynPlugin.MSBuildProject project = App.CurrentProject as CERoslynPlugin.MSBuildProject; Console.WriteLine ($"{project.Name}: {project.IsCrowProject}"); - + } - - + + } - - + + public Command CMDStartRecording, CMDStopRecording, CMDRefresh; public Command CMDGotoParentEvent, CMDEventHistoryForward, CMDEventHistoryBackward; public CommandGroup LoggerCommands => new CommandGroup (CMDRefresh, CMDStartRecording, CMDStopRecording); @@ -72,19 +73,19 @@ namespace Crow void initCommands () { App.ViewCommands.Add ( - new Command("Crow Preview", () => App.LoadWindow ("#CECrowPlugin.ui.winCrowPreview.crow", App))); - CMDRefresh = new Command ("Refresh", refresh, "#icons.refresh.svg", IsRunning); - CMDStartRecording = new Command ("Start Recording", () => Recording = true, "#icons.circle.svg", false); - CMDStopRecording = new Command ("Stop Recording", stopRecording, "#icons.circle-red.svg", false); + new ActionCommand("Crow Preview", () => App.LoadWindow ("#CECrowPlugin.ui.winCrowPreview.crow", App))); + CMDRefresh = new ActionCommand ("Refresh", refresh, "#icons.refresh.svg", IsRunning); + CMDStartRecording = new ActionCommand ("Start Recording", () => Recording = true, "#icons.circle.svg", false); + CMDStopRecording = new ActionCommand ("Stop Recording", stopRecording, "#icons.circle-red.svg", false); - CMDGotoParentEvent = new Command("parent", ()=> { CurrentEvent = CurrentEvent?.parentEvent; }, "#icons.level-up.svg", false); - CMDEventHistoryBackward = new Command("back.", currentEventHistoryGoBack, "#icons.previous.svg", false); - CMDEventHistoryForward = new Command("forw.", currentEventHistoryGoForward, "#icons.forward-arrow.svg", false); + CMDGotoParentEvent = new ActionCommand("parent", ()=> { CurrentEvent = CurrentEvent?.parentEvent; }, "#icons.level-up.svg", false); + CMDEventHistoryBackward = new ActionCommand("back.", currentEventHistoryGoBack, "#icons.previous.svg", false); + CMDEventHistoryForward = new ActionCommand("forw.", currentEventHistoryGoForward, "#icons.forward-arrow.svg", false); } public void LoadIML (string imlSource) { if (CurrentState == Status.Running) - delSetSource (imlSource); - } + delSetSource (imlSource); + } Exception currentException; object dbgIFace; AssemblyLoadContext crowLoadCtx; @@ -97,10 +98,10 @@ namespace Crow Func delMouseWheelChanged; Func delMouseDown, delMouseUp; Func delKeyPress; - Func delKeyDown, delKeyUp; + Func delKeyDown, delKeyUp; FieldInfo fiDbgIFace_IsDirty; Action delResetDebugger; - Action delSaveDebugLog; + Action delSaveDebugLog; Func delGetSurfacePointer; Action delSetSource; Action delReloadIml; @@ -117,8 +118,8 @@ namespace Crow if (RefreshRate == value) return; Configuration.Global.Set ("RefreshRate", value); - NotifyValueChanged(value); - } + NotifyValueChanged(value); + } } public int MaxLayoutingTries { get => Configuration.Global.Get ("MaxLayoutingTries", 30); @@ -128,7 +129,7 @@ namespace Crow Configuration.Global.Set ("MaxLayoutingTries", value); NotifyValueChanged(value); fiDbgIFace_MaxLayoutingTries.SetValue (null, value); - } + } } public int MaxDiscardCount { get => Configuration.Global.Get ("MaxDiscardCount", 5); @@ -136,30 +137,30 @@ namespace Crow if (MaxDiscardCount == value) return; Configuration.Global.Set ("MaxDiscardCount", value); - NotifyValueChanged(value); - fiDbgIFace_MaxDiscardCount.SetValue (null, value); - } - } + NotifyValueChanged(value); + fiDbgIFace_MaxDiscardCount.SetValue (null, value); + } + } public bool PreviewHasError => currentException != null; public Exception CurrentException { get => currentException; set { if (currentException == value) return; - currentException = value; + currentException = value; NotifyValueChanged (currentException); NotifyValueChanged ("PreviewHasError", PreviewHasError); } - } + } public string CrowDbgAssemblyLocation { get => Configuration.Global.Get ("CrowDbgAssemblyLocation"); set { if (CrowDbgAssemblyLocation == value) return; Configuration.Global.Set ("CrowDbgAssemblyLocation", value); - NotifyValueChanged(value); + NotifyValueChanged(value); } - } + } public bool DebugLogIsEnabled { get => debugLogIsEnabled; set { @@ -170,7 +171,7 @@ namespace Crow CMDStopRecording.CanExecute = debugLogIsEnabled & Recording; NotifyValueChanged (debugLogIsEnabled); } - } + } public bool Recording { get => recording; set { @@ -180,12 +181,12 @@ namespace Crow if (recording) { fiDbg_DiscardEvents.SetValue (dbgIFace, DiscardedEvents); fiDbg_IncludeEvents.SetValue (dbgIFace, RecordedEvents); - CMDStartRecording.CanExecute = false; + CMDStartRecording.CanExecute = false; CMDStopRecording.CanExecute = true; } else { fiDbg_DiscardEvents.SetValue (dbgIFace, DbgEvtType.All); fiDbg_IncludeEvents.SetValue (dbgIFace, DbgEvtType.None); - CMDStartRecording.CanExecute = debugLogIsEnabled; + CMDStartRecording.CanExecute = debugLogIsEnabled; CMDStopRecording.CanExecute = false; } NotifyValueChanged(recording); @@ -206,7 +207,7 @@ namespace Crow get => discardedEvents; set { if (discardedEvents == value) - return; + return; discardedEvents = value; if (Recording) fiDbg_DiscardEvents.SetValue (dbgIFace, value); @@ -230,18 +231,22 @@ namespace Crow NotifyValueChanged ("ServiceErrorMessage", (object)ErrorMessage); NotifyValueChanged ("ServiceIsInError", ServiceIsInError); } + public void GetMouseScreenCoordinates (out int x, out int y) { + x = mouseScreenPos.X; + y = mouseScreenPos.Y; + } public override void Start() { if (CurrentState == Status.Running) return; - + if (!File.Exists (CrowDbgAssemblyLocation)) { DebugLogIsEnabled = false; updateCrowDebuggerState($"Crow.dll for debugging file not found"); return; - } - + } + crowLoadCtx = new AssemblyLoadContext("CrowDebuggerLoadContext"); crowLoadCtx.ResolvingUnmanagedDll += resolveUnmanaged; crowLoadCtx.Resolving += (context, assemblyName) => { @@ -250,16 +255,16 @@ namespace Crow System.IO.Path.GetDirectoryName(CrowDbgAssemblyLocation), assemblyName.Name + ".dll")); }; //crowLoadCtx.Resolving += (ctx,name) => AssemblyLoadContext.Default.LoadFromAssemblyName (name); - + //using (crowLoadCtx.EnterContextualReflection()) { crowAssembly = crowLoadCtx.LoadFromAssemblyPath (CrowDbgAssemblyLocation); - thisAssembly = crowLoadCtx.LoadFromAssemblyPath (new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath); + thisAssembly = crowLoadCtx.LoadFromAssemblyPath (new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath); Type debuggerType = crowAssembly.GetType("Crow.DbgLogger"); DebugLogIsEnabled = (bool)debuggerType.GetField("IsEnabled").GetValue(null); dbgIfaceType = thisAssembly.GetType("CECrowPlugin.DebugInterface"); - + dbgIFace = Activator.CreateInstance (dbgIfaceType, new object[] {CrowEditBase.CrowEditBase.App.WindowHandle}); delResize = (Action)Delegate.CreateDelegate(typeof(Action), @@ -278,10 +283,10 @@ namespace Crow delMouseUp = (Func)Delegate.CreateDelegate(typeof(Func), dbgIFace, dbgIfaceType.GetMethod("OnMouseButtonUp")); - delKeyDown = (Func)Delegate.CreateDelegate(typeof(Func), - dbgIFace, dbgIfaceType.GetMethod("OnKeyDown")); - delKeyUp = (Func)Delegate.CreateDelegate(typeof(Func), - dbgIFace, dbgIfaceType.GetMethod("OnKeyUp")); + delKeyDown = (Func)Delegate.CreateDelegate(typeof(Func), + dbgIFace, dbgIfaceType.GetMethod("OnKeyDown", new Type[] { typeof(Key), typeof(int), typeof (Modifier)})); + delKeyUp = (Func)Delegate.CreateDelegate(typeof(Func), + dbgIFace, dbgIfaceType.GetMethod("OnKeyUp", new Type[] { typeof(Key), typeof(int), typeof (Modifier)})); delKeyPress = (Func)Delegate.CreateDelegate(typeof(Func), dbgIFace, dbgIfaceType.GetMethod("OnKeyPress")); @@ -303,7 +308,7 @@ namespace Crow /*delSaveDebugLog = (Action)Delegate.CreateDelegate(typeof(Action), null, debuggerType.GetMethod("Save", new Type[] {dbgIfaceType, typeof(string)}));*/ HasVkvgBackend = (bool)dbgIfaceType.GetField ("HaveVkvgBackend", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy).GetValue (null); - dbgIfaceType.GetMethod("RegisterDebugInterfaceCallback").Invoke (dbgIFace, new object[] {this} ); + dbgIfaceType.GetMethod("RegisterDebugInterfaceCallback").Invoke (dbgIFace, new object[] {this} ); dbgIfaceType.GetMethod("Run").Invoke (dbgIFace, null); fiDbgIFace_MaxLayoutingTries.SetValue (null, MaxLayoutingTries); @@ -325,7 +330,7 @@ namespace Crow CurrentState = Status.Paused; } public override string ConfigurationWindowPath => "#CECrowPlugin.ui.winConfiguration.crow"; - public Command CMDOptions_SelectCrowAssemblyLocation => new Command ("...", + public ActionCommand CMDOptions_SelectCrowAssemblyLocation => new ActionCommand ("...", () => { FileDialog dlg = App.LoadIMLFragment (@" IsRunning ? delGetSurfacePointer() : IntPtr.Zero; public void Resize (int width, int height) { if (IsRunning) @@ -442,8 +450,26 @@ namespace Crow fiDbgIFace_IsDirty.SetValue (dbgIFace, false); } public bool GetDirtyState => IsRunning ? (bool)fiDbgIFace_IsDirty.GetValue (dbgIFace) : false; + public IEnumerable GetStyling () { + if (App.CurrentProject is CERoslynPlugin.SolutionProject sol) { + if (sol.StartupProject is CERoslynPlugin.MSBuildProject csprj) { + foreach (var style in csprj.RootNode.Flatten.OfType() + .Where (pin=>pin.NodeType == NodeType.EmbeddedResource && pin.FullPath.EndsWith (".style", StringComparison.OrdinalIgnoreCase))) + yield return style.FullPath; + } + } + yield return crowAssembly; + } + public Stream GetStreamFromPath (string path) { + if (App.CurrentProject is CERoslynPlugin.SolutionProject sol) { + if (sol.StartupProject is CERoslynPlugin.MSBuildProject csprj) { + return csprj.GetStreamFromTargetPath (path); + } + } + return null; + } - + #region Debug log IList events; IList widgets; public IList Events { @@ -465,9 +491,11 @@ namespace Crow } } void refresh () { + if (!IsRunning) + Start (); if (IsRunning) delReloadIml (); - updateCrowApp(); + //updateCrowApp(); } void stopRecording () { if (!Recording) @@ -509,7 +537,7 @@ namespace Crow } Events = events; Widgets = widgets; - firstWidgetIndexToGet += widgets.Count; + firstWidgetIndexToGet += widgets.Count; /*if (widgets.Count > 0 && firstWidgetIndexToGet != widgets.Last().InstanceIndex + 1) Debugger.Break ();*/ } @@ -519,8 +547,8 @@ namespace Crow widgets.FirstOrDefault (w => w.InstanceIndex == we.InstanceIndex)?.Events.Add (we); if (evt.Events == null) return; - foreach (DbgEvent e in evt.Events) - updateWidgetEvents (widgets, e); + foreach (DbgEvent e in evt.Events) + updateWidgetEvents (widgets, e); } void saveLogToDebugLogFilePath () { @@ -529,7 +557,6 @@ namespace Crow } - //public virtual object GetScreenCoordinates () => ScreenCoordinates(Slot).TopLeft; DbgEvent curEvent; bool disableCurrentEventHistory; Stack CurrentEventHistoryForward = new Stack(); @@ -570,8 +597,8 @@ namespace Crow CurrentEventHistoryBackward.Push (curEvent); CMDEventHistoryBackward.CanExecute = true; } - } - + } + curEvent = value; NotifyValueChanged (nameof (CurrentEvent), curEvent); @@ -581,7 +608,7 @@ namespace Crow if (CurrentEvent != null && CurrentEvent.parentEvent != null) CMDGotoParentEvent.CanExecute = true; else - CMDGotoParentEvent.CanExecute = false; + CMDGotoParentEvent.CanExecute = false; } } void currentEventHistoryGoBack () { @@ -636,6 +663,6 @@ namespace Crow return result; } } - + #endregion } } \ No newline at end of file diff --git a/plugins/CECrowPlugin/src/DbgLogViewer.cs b/plugins/CECrowPlugin/src/DbgLogViewer.cs index 67ca7cc..fd0f18e 100644 --- a/plugins/CECrowPlugin/src/DbgLogViewer.cs +++ b/plugins/CECrowPlugin/src/DbgLogViewer.cs @@ -32,14 +32,14 @@ namespace Crow IList events = new List (); IList widgets = new List (); - + public DbgEvtType Filter { get => Configuration.Global.Get ("DbgLogViewFilter"); set { if (Filter == value) - return; - Configuration.Global.Set ("DbgLogViewFilter", value); + return; + Configuration.Global.Set ("DbgLogViewFilter", value); NotifyValueChangedAuto(Filter); RegisterForGraphicUpdate(); } @@ -53,7 +53,7 @@ namespace Crow NotifyValueChanged (nameof (Events), events); maxTicks = minTicks = 0; - if (events != null && events.Count > 0) { + if (events != null && events.Count > 0) { minTicks = long.MaxValue; foreach (DbgEvent e in events) { if (e.begin < minTicks) @@ -67,7 +67,7 @@ namespace Crow ScrollY = 0; } else { maxTicks = 1; - XScale = 1.0/1024.0; + XScale = 1.0/1024.0; } @@ -97,7 +97,7 @@ namespace Crow return; if (CurrentWidget.listIndex < scrollY || CurrentWidget.listIndex > scrollY + visibleLines) ScrollY = CurrentWidget.listIndex - (visibleLines / 2); - + currentLine = CurrentWidget.listIndex; RegisterForRedraw(); } @@ -118,8 +118,8 @@ namespace Crow } currentTick = curEvent.begin; if (curEvent.begin > minTicks + ScrollX + visibleTicks || - curEvent.end < minTicks + ScrollX) - ScrollX = curEvent.begin - minTicks - visibleTicks / 2; + curEvent.end < minTicks + ScrollX) + ScrollX = curEvent.begin - minTicks - visibleTicks / 2; } NotifyValueChanged (nameof (CurrentEvent), curEvent); RegisterForRedraw (); @@ -216,9 +216,9 @@ namespace Crow DbgWidgetEvent eW = evt as DbgWidgetEvent; int lIdx = eW.InstanceIndex - ScrollY; if (lIdx >= 0 && lIdx <= visibleLines) { - - penY += (lIdx) * fe.Height; - + + penY += (lIdx) * fe.Height; + ctx.SetSource (evt.Color); ctx.Rectangle (getWidgetEvtBounds (evt, ref cb, penY)); ctx.Fill (); @@ -233,8 +233,8 @@ namespace Crow x += leftMargin + cb.Left; double rightDiff = x + w - cb.Right; if (rightDiff > 0) - w -= rightDiff; - //ctx.SetSource (0.9,0.9,0.0,0.1); + w -= rightDiff; + //ctx.SetSource (0.9,0.9,0.0,0.1); ctx.SetSource (evt.Color.AdjustAlpha(0.15)); ctx.Rectangle (x, cb.Top + topMargin, w, cb.Height); ctx.Fill (); @@ -310,7 +310,7 @@ namespace Crow double x = (double)gg * xScale + leftMargin + cb.Left; gr.MoveTo (x, penY - 0.5); - if (curGrad % largeGrad == 0) { + if (curGrad % largeGrad == 0) { gr.LineTo (x, penY - 8.5); string str = ticksToMS(curGrad); TextExtents te = gr.TextExtents (str); @@ -344,7 +344,7 @@ namespace Crow else x = Math.Truncate (x) - 0.5; ctx.MoveTo (x, cb.Top + topMargin - 4.0); - ctx.LineTo (x, cb.Bottom); + ctx.LineTo (x, cb.Bottom); ctx.SetSource (0.7,0.7,0.7,0.5); ctx.Stroke(); } @@ -356,7 +356,7 @@ namespace Crow else x = Math.Truncate (x) - 0.5; ctx.MoveTo (x, cb.Top); - ctx.LineTo (x, cb.Bottom); + ctx.LineTo (x, cb.Bottom); ctx.SetSource (0.2,0.7,1.0,0.6); ctx.Stroke(); } @@ -450,7 +450,7 @@ namespace Crow hoverTick = 0; } public override void onMouseMove (object sender, MouseMoveEventArgs e) - { + { long lastTick = hoverTick; int lastLine = hoverLine; updateMouseLocalPos (e.Position); @@ -472,14 +472,14 @@ namespace Crow } RegisterForRepaint(); - + e.Handled = true; base.onMouseMove (sender, e); - } + } void findHoverEvent (DbgWidgetRecord widget, long tick, long precision = 0) { DbgEvent tmp = widget?.Events.FirstOrDefault (ev => ev.begin - precision <= tick && ev.end + precision >= tick); if (tmp == null) { - tmp = Events.Where(e=>e.type.HasFlag(DbgEvtType.IFace)).Where (ev => ev.begin - precision <= tick && ev.end + precision >= tick).FirstOrDefault(); + tmp = Events.Where(e=>e.type.HasFlag(DbgEvtType.IFace)).Where (ev => ev.begin - precision <= tick && ev.end + precision >= tick).FirstOrDefault(); while(tmp != null) { DbgEvent che = tmp.Events?.Where(e=>e.type.HasFlag(DbgEvtType.IFace)).Where (ev => ev.begin - precision <= tick && ev.end + precision >= tick).FirstOrDefault(); if (che == null) @@ -546,7 +546,7 @@ namespace Crow /// Process scrolling vertically, or if shift is down, vertically public override void onMouseWheel (object sender, MouseWheelEventArgs e) - { + { //base.onMouseWheel (sender, e); if (IFace.Shift) @@ -620,7 +620,7 @@ namespace Crow void updateMaxScrollX () { if (widgets == null) { - MaxScrollX = 0; + MaxScrollX = 0; } else { long tot = maxTicks - minTicks; MaxScrollX = Math.Max (0L, tot - visibleTicks); @@ -664,7 +664,7 @@ namespace Crow hoverTick = (long)((double)(mousePos.X - cb.X) / xScale) + minTicks + ScrollX; RegisterForRedraw (); } - void zoom (long start, long end) { + void zoom (long start, long end) { //Rectangle cb = ClientRectangle; //cb.X += (int)leftMargin; XScale = ((double)ClientRectangle.Width - leftMargin)/(end - start); @@ -739,7 +739,7 @@ namespace Crow else hoverLine = (int)((double)(mousePos.Y - cb.Top) / fe.Height) + ScrollY; - NotifyValueChanged ("CurrentLine", hoverLine); + NotifyValueChanged ("CurrentLine", hoverLine); } } /// Horizontal Scrolling maximum value @@ -783,7 +783,7 @@ namespace Crow set { if (mouseWheelSpeed == value) return; - + mouseWheelSpeed = value; NotifyValueChangedAuto (mouseWheelSpeed); diff --git a/plugins/CECrowPlugin/src/DebugInterface.cs b/plugins/CECrowPlugin/src/DebugInterface.cs index ec3bed9..dd2d49c 100644 --- a/plugins/CECrowPlugin/src/DebugInterface.cs +++ b/plugins/CECrowPlugin/src/DebugInterface.cs @@ -3,7 +3,9 @@ // This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) using System; - +using System.Collections.Generic; +using System.IO; +using System.Reflection; using System.Threading; using Crow; using Crow.Drawing; @@ -21,7 +23,7 @@ namespace CECrowPlugin { SolidBackground = false; initBackend (true); - + clientRectangle = new Rectangle (0, 0, 100, 100); CreateMainSurface (ref clientRectangle); } @@ -39,13 +41,17 @@ namespace CECrowPlugin string source; Action delRegisterForRepaint;//call RegisterForRepaint in the container widget (DebugInterfaceWidget) Action delSetCurrentException; - //Func delGetScreenCoordinate; + + delegate void GetScreenCoordinateDelegateType(out int x, out int y); + GetScreenCoordinateDelegateType delGetScreenCoordinate; + Func> delGetStyling; + Func delGetStreamFromPath; void interfaceThread () { while (!Terminate) { try { - Update(); + Update(); } catch (System.Exception ex) { @@ -72,12 +78,12 @@ namespace CECrowPlugin delSetCurrentException (ex); Console.WriteLine ($"[DbgIFace] {ex}"); ClearInterface(); - Thread.Sleep(1000); + Thread.Sleep(1000); } - + /*if (IsDirty) delRegisterForRepaint(); */ - + Thread.Sleep (UPDATE_INTERVAL); } } @@ -91,7 +97,9 @@ namespace CECrowPlugin Type t = w.GetType(); //delRegisterForRepaint = (Action)Delegate.CreateDelegate(typeof(Action), w, t.GetMethod("RegisterForRepaint")); delSetCurrentException = (Action)Delegate.CreateDelegate(typeof(Action), w, t.GetProperty("CurrentException").GetSetMethod()); - //delGetScreenCoordinate = (Func)Delegate.CreateDelegate(typeof(Func), w, t.GetMethod("GetScreenCoordinates")); + delGetScreenCoordinate = (GetScreenCoordinateDelegateType)Delegate.CreateDelegate(typeof(GetScreenCoordinateDelegateType), w, t.GetMethod("GetMouseScreenCoordinates")); + delGetStyling = (Func>)Delegate.CreateDelegate (typeof (Func>), w, t.GetMethod ("GetStyling")); + delGetStreamFromPath = (Func)Delegate.CreateDelegate (typeof (Func), w, t.GetMethod ("GetStreamFromPath")); } /*public void ResetDirtyState () { IsDirty = false; @@ -101,17 +109,17 @@ namespace CECrowPlugin if (source == value) return; source = value; - if (string.IsNullOrEmpty(source)) - return; delSetCurrentException(null); try { lock (UpdateMutex) { + resetInterface (); + if (string.IsNullOrEmpty(source)) + return; Widget tmp = CreateITorFromIMLFragment (source).CreateInstance(); - ClearInterface(); AddWidget (tmp); tmp.DataSource = this; - } + } } catch (IML.InstantiatorException iTorEx) { @@ -123,6 +131,16 @@ namespace CECrowPlugin } } } + void resetInterface () { + ClearInterface(); + initDictionaries(); + foreach (object style in delGetStyling ()) { + if (style is string stylePath) + LoadStyle (stylePath); + else if (style is Assembly styleAssembly) + loadStylingFromAssembly (styleAssembly); + } + } public void ReloadIml () { if (string.IsNullOrEmpty (source)) return; @@ -137,19 +155,35 @@ namespace CECrowPlugin public override void ProcessResize(Rectangle bounds) { lock (UpdateMutex) { clientRectangle = bounds.Size; - + CreateMainSurface (ref clientRectangle); foreach (Widget g in GraphicTree) g.RegisterForLayouting (LayoutingType.All); RegisterClip (clientRectangle); - } - } - /*public override void ForceMousePosition() + } + } + public override void ForceMousePosition() { - Point p = (Point)delGetScreenCoordinate(); - Glfw.Glfw3.SetCursorPosition (WindowHandle, p.X + MousePosition.X, p.Y + MousePosition.Y); - }*/ + delGetScreenCoordinate(out int x, out int y); + Glfw.Glfw3.SetCursorPosition (WindowHandle, x, y); + } + + public bool OnKeyDown (Glfw.Key key, int scancode, Glfw.Modifier modifiers) { + return base.OnKeyDown (new KeyEventArgs (key, scancode, modifiers)); + } + public bool OnKeyUp (Glfw.Key key, int scancode, Glfw.Modifier modifiers) { + return base.OnKeyDown (new KeyEventArgs (key, scancode, modifiers)); + } + + + public override Stream GetStreamFromPath(string path) + { + Stream result = delGetStreamFromPath (path); + if (result != null) + return result; + return base.GetStreamFromPath (path); + } } } \ No newline at end of file diff --git a/plugins/CECrowPlugin/src/DebugInterfaceWidget.cs b/plugins/CECrowPlugin/src/DebugInterfaceWidget.cs index 738b549..20b2705 100644 --- a/plugins/CECrowPlugin/src/DebugInterfaceWidget.cs +++ b/plugins/CECrowPlugin/src/DebugInterfaceWidget.cs @@ -21,7 +21,7 @@ using static CrowEditBase.CrowEditBase; using CECrowPlugin; namespace Crow -{ +{ public class DebugInterfaceWidget : Widget { CrowService crowIFaceService; public CrowService CrowIFaceService { @@ -33,7 +33,17 @@ namespace Crow NotifyValueChangedAuto (crowIFaceService); } } + Command CMDRefresh; public DebugInterfaceWidget () : base () { + CMDRefresh = new ActionCommand (this, "Refresh", + () => { + crowIFaceService?.LoadIML (""); + crowIFaceService?.LoadIML (imlSource); + RegisterForGraphicUpdate (); + }, + "#icons.refresh.svg", + new KeyBinding (Key.F3)); + Thread t = new Thread (backgroundThreadFunc); t.IsBackground = true; t.Start (); @@ -42,8 +52,8 @@ namespace Crow Stopwatch sw = Stopwatch.StartNew (); int refreshRate = crowIFaceService == null ? 10 : crowIFaceService.RefreshRate; while (true) { - if (sw.ElapsedMilliseconds > 200) { - if (Document != null && document.TryGetState (this, out List changes)) { + if (sw.ElapsedMilliseconds > 200) { + if (Document != null && document.TryGetState (this, out List changes)) { foreach (TextChange tc in changes) updateIMLSource (tc); } @@ -53,22 +63,22 @@ namespace Crow if (crowIFaceService != null && crowIFaceService.GetDirtyState) RegisterForRepaint (); Thread.Sleep (refreshRate); - } - } - void updateIMLSource (TextChange change) { + } + } + void updateIMLSource (TextChange change) { ReadOnlySpan src = imlSource.AsSpan (); Span tmp = stackalloc char[src.Length + (change.ChangedText.Length - change.Length)]; //Console.WriteLine ($"{Text.Length,-4} {change.Start,-4} {change.Length,-4} {change.ChangedText.Length,-4} tmp:{tmp.Length,-4}"); 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)); - + imlSource = tmp.ToString (); - + crowIFaceService?.LoadIML (imlSource); RegisterForRedraw (); - } + } string imlSource; ImlDocument document; @@ -77,7 +87,7 @@ namespace Crow set { if (document == value) return; - + if (value is ImlDocument imlDoc) { document?.UnregisterClient (this); imlSource = ""; @@ -89,13 +99,13 @@ namespace Crow } } } - + protected override void onInitialized(object sender, EventArgs e) { base.onInitialized(sender, e); - - CrowIFaceService = App.GetService (); + + CrowIFaceService = App.GetService (); crowIFaceService?.Start (); } /*public CommandGroup LoggerCommands => @@ -106,7 +116,7 @@ namespace Crow new Command("Load from file", () => loadLogFromDebugLogFilePath ()) );*/ public CommandGroup WindowCommands => new CommandGroup ( - crowIFaceService.CMDRefresh, + CMDRefresh, crowIFaceService.CMDStartRecording, crowIFaceService.CMDStopRecording, crowIFaceService.CMDOpenConfig, @@ -127,7 +137,7 @@ namespace Crow public override void onKeyPress(object sender, KeyPressEventArgs e) => crowIFaceService?.onKeyPress(e); public override void onMouseMove(object sender, MouseMoveEventArgs e) { Point m = ScreenPointToLocal (e.Position); - crowIFaceService?.onMouseMove(new MouseMoveEventArgs(m.X,m.Y, e.XDelta, e.YDelta)); + crowIFaceService?.onMouseMove(e.Position, new MouseMoveEventArgs(m.X,m.Y, e.XDelta, e.YDelta)); } public override void onMouseDown(object sender, MouseButtonEventArgs e) => crowIFaceService?.onMouseDown(e); public override void onMouseUp(object sender, MouseButtonEventArgs e) => crowIFaceService?.onMouseUp(e); @@ -135,33 +145,34 @@ namespace Crow protected override void RecreateCache() { - bmp?.Dispose (); - + bmp?.Dispose (); + if (crowIFaceService != null && crowIFaceService.IsRunning) { crowIFaceService.Resize (Slot.Width, Slot.Height); if (crowIFaceService.HasVkvgBackend) bmp = IFace.CreateSurfaceForData (crowIFaceService.SurfacePointer, Slot.Width, Slot.Height); else bmp = IFace.CreateSurface (crowIFaceService.SurfacePointer); - bmp = Crow.Drawing.Surface.Lookup (crowIFaceService.SurfacePointer, false); - } + bmp = Crow.Drawing.Surface.Lookup (crowIFaceService.SurfacePointer, false); + } else + base.RecreateCache (); - IsDirty = false; + IsDirty = false; } protected override void UpdateCache(Context ctx) { - if (bmp != null) { + if (bmp != null) { paintCache (ctx, Slot + Parent.ClientRectangle.Position); - crowIFaceService?.ResetDirtyState (); + crowIFaceService?.ResetDirtyState (); } } protected override void Dispose(bool disposing) { + CMDRefresh?.Dispose (); crowIFaceService?.Stop (); - base.Dispose(disposing); + base.Dispose(disposing); } - } } \ No newline at end of file diff --git a/plugins/CECrowPlugin/src/ImlDocument.cs b/plugins/CECrowPlugin/src/ImlDocument.cs index 0b6aef1..a00de9b 100644 --- a/plugins/CECrowPlugin/src/ImlDocument.cs +++ b/plugins/CECrowPlugin/src/ImlDocument.cs @@ -15,13 +15,19 @@ using CrowEditBase; using static CrowEditBase.CrowEditBase; using CrowEdit.Xml; +using CERoslynPlugin; namespace CECrowPlugin { public class ImlDocument : XmlDocument { + public ImlDocument (string fullPath) : base (fullPath) { App.GetService ()?.Start (); + + /*if (project is MSBuildProject msbp) { + if (msbp.IsCrowProject) + }*/ } string[] allWidgetNames = typeof (Widget).Assembly.GetExportedTypes ().Where(t=>typeof(Widget).IsAssignableFrom (t)) @@ -35,12 +41,12 @@ namespace CECrowPlugin m.GetCustomAttribute() == null); } MemberInfo getCrowTypeMember (string crowTypeName, string memberName) { - Type crowType = IML.Instantiator.GetWidgetTypeFromName (crowTypeName); + Type crowType = IML.Instantiator.GetWidgetTypeFromName (crowTypeName); return crowType.GetMember (memberName, BindingFlags.Public | BindingFlags.Instance).FirstOrDefault (); } - public override IList GetSuggestions (int pos) { + public override IList GetSuggestions (int pos) { base.GetSuggestions (pos); -#if DEBUG +#if DEBUG Console.WriteLine ($"Current Token: {currentToken} Current Node: {currentNode}"); #endif @@ -71,7 +77,7 @@ namespace CECrowPlugin if (pi.PropertyType == typeof (Measure)) return (new string[] {"Stretched", "Fit"}). Where (s => s.StartsWith (currentToken.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList (); - if (pi.PropertyType == typeof (Fill)) + if (pi.PropertyType == typeof (Fill)) return EnumsNET.Enums.GetValues () .Where (s => s.ToString().StartsWith (currentToken.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList (); } @@ -85,7 +91,7 @@ namespace CECrowPlugin return Enum.GetNames (pi.PropertyType).ToList (); if (pi.PropertyType == typeof(bool)) return new List (new string[] {"true", "false"}); - if (pi.PropertyType == typeof (Fill)) + if (pi.PropertyType == typeof (Fill)) return EnumsNET.Enums.GetValues ().ToList (); if (pi.PropertyType == typeof (Measure)) return new List (new string[] {"Stretched", "Fit"}); @@ -93,10 +99,10 @@ namespace CECrowPlugin } } } - } - } else if (currentToken.GetTokenType() != XmlTokenType.AttributeValueClose && - currentToken.GetTokenType() != XmlTokenType.EmptyElementClosing && - currentToken.GetTokenType() != XmlTokenType.ClosingSign && + } + } else if (currentToken.GetTokenType() != XmlTokenType.AttributeValueClose && + currentToken.GetTokenType() != XmlTokenType.EmptyElementClosing && + currentToken.GetTokenType() != XmlTokenType.ClosingSign && currentNode is ElementStartTagSyntax eltStartTag) { if (currentToken.GetTokenType() == XmlTokenType.AttributeName) return getAllCrowTypeMembers (eltStartTag.NameToken.Value.AsString (Source)) @@ -110,8 +116,8 @@ namespace CECrowPlugin (currentToken.Type != TokenType.ClosingSign && currentToken.Type != TokenType.EmptyElementClosing && currentToken.Type != TokenType.Unknown)) { Suggestions = getAllCrowTypeMembers (eltStartTag.NameToken.Value.AsString (Source)).ToList (); } else*/ - - } + + } return null; } public override TextChange? GetCompletionForCurrentToken (object suggestion, out TextSpan? newSelection) { @@ -129,7 +135,7 @@ namespace CECrowPlugin if (currentToken.GetTokenType() == XmlTokenType.AttributeName && currentNode is AttributeSyntax attrib) { if (attrib.ValueToken.HasValue) { - TextChange tc = new TextChange (currentToken.Start, currentToken.Length, selectedSugg); + TextChange tc = new TextChange (currentToken.Start, currentToken.Length, selectedSugg); newSelection = new TextSpan( attrib.ValueToken.Value.Start + tc.CharDiff + 1, attrib.ValueToken.Value.End + tc.CharDiff - 1 @@ -137,8 +143,8 @@ namespace CECrowPlugin return tc; } else { newSelection = TextSpan.FromStartAndLength (currentToken.Start + selectedSugg.Length + 2); - return new TextChange (currentToken.Start, currentToken.Length, selectedSugg + "=\"\""); - } + return new TextChange (currentToken.Start, currentToken.Length, selectedSugg + "=\"\""); + } } return new TextChange (currentToken.Start, currentToken.Length, selectedSugg); @@ -148,5 +154,5 @@ namespace CECrowPlugin { return base.GetColorForToken (tokType); } - } + } } \ No newline at end of file diff --git a/plugins/CECrowPlugin/ui/Button.template b/plugins/CECrowPlugin/ui/Button.template index c7e2fa0..f45d890 100644 --- a/plugins/CECrowPlugin/ui/Button.template +++ b/plugins/CECrowPlugin/ui/Button.template @@ -1,5 +1,5 @@ - - + @@ -17,25 +17,25 @@ diff --git a/ui/MenuItem.itmp b/ui/MenuItem.itmp deleted file mode 100644 index 67a67c3..0000000 --- a/ui/MenuItem.itmp +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - diff --git a/ui/MenuItem.template b/ui/MenuItem.template deleted file mode 100644 index df853bc..0000000 --- a/ui/MenuItem.template +++ /dev/null @@ -1,13 +0,0 @@ - - - - - \ No newline at end of file diff --git a/ui/Suggestions.template b/ui/Suggestions.template deleted file mode 100644 index 8bc5574..0000000 --- a/ui/Suggestions.template +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - diff --git a/ui/main.crow b/ui/main.crow index 4c12c86..cbc0924 100755 --- a/ui/main.crow +++ b/ui/main.crow @@ -1,10 +1,10 @@  - + + ItemTemplate="#ui.MenuItem.itmp"> @@ -39,19 +39,19 @@ + CursorRatio="{../tb.ChildWidthRatio}" Maximum="{../tb.MaxScrollX}" /> + - + diff --git a/ui/windows/winLogs.crow b/ui/windows/winLogs.crow index e32813d..f547e52 100644 --- a/ui/windows/winLogs.crow +++ b/ui/windows/winLogs.crow @@ -1,8 +1,33 @@  - + + +