]> O.S.I.I.S - jp/crowedit.git/commitdiff
toolbox, undo/redo keybindings, dirty state forcing in crow service, wip
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Mon, 21 Jul 2025 18:35:08 +0000 (20:35 +0200)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Mon, 21 Jul 2025 18:35:08 +0000 (20:35 +0200)
13 files changed:
CrowEditBase/src/Compiler/SourceDocument.cs
CrowEditBase/src/CrowEditBase.cs
CrowEditBase/src/CrowEditComponent.cs
CrowEditBase/src/Document.cs
CrowEditBase/src/Editor.cs
CrowEditBase/src/TextDocument.cs
CrowEditBase/ui/IconButton.template [new file with mode: 0644]
plugins/CECrowPlugin/src/CrowService.cs
plugins/CECrowPlugin/src/ForeignWidgetContainer.cs
plugins/CECrowPlugin/src/Parsing/IML/ImlDocument.cs
src/CrowEdit.cs
ui/main.crow
ui/windows/winLogs.crow

index 8ee2e1dd942d79add91e44b429af94e9cd8b2ca1..a0f35ae4b7334587b5d67976cc5126e16d438b4f 100644 (file)
@@ -170,10 +170,10 @@ namespace CrowEditBase
                        if (cancel.IsCancellationRequested)
                                return;
 
-                       NotifyValueChanged("Exceptions", Exceptions);
+                       /*NotifyValueChanged("Exceptions", Exceptions);
                        NotifyValueChanged ("SyntaxRootChildNodes", (object)null);
                        NotifyValueChanged ("SyntaxRootChildNodes", SyntaxRootChildNodes);
-                       Console.WriteLine("parse async finished");
+                       Console.WriteLine("parse async finished");*/
                }
        }
 }
\ No newline at end of file
index 58459aa171dd36ade94974d28fc7ea6d4f297177..b9b52b5a62ba6a246f5ead3b287666b1a8c9efa2 100644 (file)
@@ -42,7 +42,7 @@ namespace CrowEditBase
                Document currentDocument;
                Editor currentEditor;
                Project currentProject;
-               public CommandGroup CommandsRoot, FileCommands, EditCommands, ViewCommands;
+               public CommandGroup CommandsRoot, FileCommands, EditCommands, ViewCommands, ToolBox;
                public ObservableList<Document> OpenedDocuments = new ObservableList<Document> ();
                public ObservableList<Service> Services = new ObservableList<Service> ();
                public ObservableList<Plugin> Plugins = new ObservableList<Plugin> ();
index 79cbebc281e404ead499587967f7093bd2f04635..ad6df554db2bdfd441c965d0aeb899509c3176b8 100644 (file)
@@ -17,6 +17,11 @@ namespace CrowEditBase
                        //Debug.WriteLine ("Value changed: {0}->{1} = {2}", this, MemberName, _value);
                        ValueChanged.Raise (this, new ValueChangeEventArgs (MemberName, _value));
                }
+               public void NotifyValueChanged (string MemberName, string _value)
+               {
+                       //Debug.WriteLine ("Value changed: {0}->{1} = {2}", this, MemberName, _value);
+                       ValueChanged.Raise (this, new ValueChangeEventArgs (MemberName, _value));
+               }
                public void NotifyValueChanged (object _value, [CallerMemberName] string caller = null)
                {
                        NotifyValueChanged (caller, _value);
index f91fdba0229e30ee5176cab2f076eead8b84c002..19e60ceecde0cad6cb3763152595cb60485e05e0 100644 (file)
@@ -6,11 +6,12 @@ using System;
 using System.IO;
 using System.Threading;
 using Crow;
+using Glfw;
 using static CrowEditBase.CrowEditBase;
 
 namespace CrowEditBase
 {
-       public abstract class Document : CrowEditComponent {
+       public abstract class Document : CrowEditComponent, ICommandHost {
                #region CTOR
                public Document (string fullPath, string editorPath) {
                        initCommands ();
@@ -31,8 +32,17 @@ namespace CrowEditBase
                /// <value></value>
                public string EditorPath { get; private set; }//the ressource path is used as an id for editor template selection.
                public event EventHandler CloseEvent;
+        public event EventHandler<KeyEventArgs> KeyDown;
 
-               protected ReaderWriterLockSlim documentRWLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
+               public bool OnKeyDown(object sender, KeyEventArgs e) {
+                       if (KeyDown != null) {
+                               KeyDown.Invoke (sender, e);
+                       }
+                       
+                       return e.Handled;
+               }
+
+        protected ReaderWriterLockSlim documentRWLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
                public void EnterReadLock () => documentRWLock.EnterReadLock ();
                public void ExitReadLock () => documentRWLock.ExitReadLock ();
                public void EnterWriteLock () => documentRWLock.EnterWriteLock ();
@@ -47,9 +57,9 @@ namespace CrowEditBase
                                fullPath = value;
 
                                NotifyValueChanged (fullPath);
-                               NotifyValueChanged ("FileName", (object)FileName);
-                               NotifyValueChanged ("FileDirectory", (object)Extension);
-                               NotifyValueChanged ("Extension", (object)Extension);
+                               NotifyValueChanged ("FileName", FileName);
+                               NotifyValueChanged ("FileDirectory", FileDirectory);
+                               NotifyValueChanged ("Extension", Extension);
                        }
                }
                public string FileDirectory => System.IO.Path.GetDirectoryName (FullPath);
@@ -59,17 +69,19 @@ namespace CrowEditBase
                        (DateTime.Compare (accessTime, System.IO.File.GetLastWriteTime (FullPath)) < 0) : false;
 
                #region commands
-               public Command CMDUndo, CMDRedo, CMDSave, CMDSaveAs;
                Command CMDClose, CMDCloseOther;
+               public Command CMDUndo, CMDRedo, CMDSave, CMDSaveAs;
                public CommandGroup TabCommands => new CommandGroup (
                        CMDClose, CMDCloseOther
                );
 
                protected virtual void initCommands () {
-                       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);
+                       CMDUndo = new ActionCommand (this, "Undo", Undo, "#icons.reply.svg",  new KeyBinding(Key.Z, Modifier.Control), false);
+                       CMDRedo = new ActionCommand (this, "Redo", Redo, "#icons.share-arrow.svg", new KeyBinding(Key.Z, Modifier.Control | Modifier.Shift), false);
+
+                       CMDSave = new ActionCommand (this, "save", Save, "#icons.inbox.svg", new KeyBinding(Key.S, Modifier.Control), 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");
                }
@@ -79,8 +91,8 @@ namespace CrowEditBase
                public abstract void RegisterClient (object client, bool initialState = false);
                public abstract void UnregisterClient (object client);
                protected abstract void saveFileDialog_OkClicked (object sender, EventArgs e);
-               protected abstract void undo();
-               protected abstract void redo();
+               public abstract void Undo();
+               public abstract void Redo();
                protected abstract void writeToDisk ();
                protected abstract void readFromDisk ();
                protected abstract void initNewFile ();
index 4eebf3ed6d14e64d45a8ddf94856a8d8de6132e7..b8c468925c628fd59a75508a6a64c7f42c8caa49 100644 (file)
@@ -35,7 +35,6 @@ namespace CrowEditBase
                        CMDCut = new ActionCommand (this, "Cut", Cut, "#icons.scissors.svg", new KeyBinding(Key.X, Modifier.Control), false);
                        CMDCopy = new ActionCommand (this, "Copy", Copy, "#icons.copy-file.svg",  new KeyBinding(Key.C, Modifier.Control), false);
                        CMDPaste = new ActionCommand (this, "Paste", Paste, "#icons.paste-on-document.svg",  new KeyBinding(Key.P, Modifier.Control), true);
-
                        ContextCommands = new CommandGroup (CMDCut, CMDCopy, CMDPaste);
                }
 
@@ -701,8 +700,6 @@ namespace CrowEditBase
                }
                protected override void onDraw (IContext gr)
                {
-                       //base.onDraw (gr);
-
                        gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
                        gr.SetFontSize (Font.Size);
 
@@ -814,23 +811,17 @@ namespace CrowEditBase
                        if (!e.Handled) {
                                TextSpan selection = Selection;
                                update (new TextChange (selection.Start, selection.Length, e.KeyChar.ToString ()));
-
                                e.Handled = true;
                        }
-                       /*Insert (e.KeyChar.ToString());
-
-                       SelRelease = -1;
-                       SelBegin = new Point(CurrentColumn, SelBegin.Y);
-
-                       RegisterForGraphicUpdate();*/
                }
                public override void onKeyDown (object sender, KeyEventArgs e) {
                        Key key = e.Key;
                        TextSpan selection = Selection;
 
-                       /*document.EnterReadLock();
-                       try {*/
-                               switch (key) {
+                       if (document != null && document.OnKeyDown(sender, e))
+                               return;
+
+                       switch (key) {
                                case Key.Backspace:
                                        if (selection.IsEmpty) {
                                                if (selection.Start == 0)
@@ -935,13 +926,10 @@ namespace CrowEditBase
                                default:
                                        base.onKeyDown (sender, e);
                                        return;
-                               }
-                               autoAdjustScroll = true;
-                               IFace.forceTextCursor();
-                               e.Handled = true;
-                       /*} finally {
-                               document.ExitReadLock ();
-                       }*/
+                       }
+                       autoAdjustScroll = true;
+                       IFace.forceTextCursor();
+                       e.Handled = true;
                }
                #endregion
                #endregion
@@ -1010,6 +998,8 @@ namespace CrowEditBase
                        update (new TextChange (selection.Start, selection.Length, IFace.Clipboard));
                }
 
+
+
                protected virtual void update (TextChange change) {
                        if (!disableTextChangedEvent)
                                OnTextChanged (this, new TextChangeEventArgs (change));
index e4b5cb70e7e84767d8ac5adcf7929f9490223942..d399ec534e26917f2b4303b526a61284747bdd6f 100644 (file)
@@ -114,7 +114,7 @@ namespace CrowEditBase
                        writeToDisk ();
                }
 
-               protected override void undo () {
+               public override void Undo () {
                        documentRWLock.EnterWriteLock ();
                        try {
                                if (undoStack.TryPop (out TextChange tc)) {
@@ -130,7 +130,7 @@ namespace CrowEditBase
                                documentRWLock.ExitWriteLock ();
                        }
                }
-               protected override void redo () {
+               public override void Redo () {
                        documentRWLock.EnterWriteLock ();
                        try {
                                if (redoStack.TryPop (out TextChange tc)) {
diff --git a/CrowEditBase/ui/IconButton.template b/CrowEditBase/ui/IconButton.template
new file mode 100644 (file)
index 0000000..b49e482
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<Button Command="{}" Width="Fit" BubbleEvents="All" MinimumSize="0,0">
+       <Template>
+               <Border Style="ButtonBorder" Width="Stretched" Height="Stretched" Margin="4" Background="{./Background}" CornerRadius="{../CornerRadius}">
+                       <Image Path="{./Icon}" Tooltip="{./Caption}" Scaled="true" KeepProportions="true" Margin="0"/>
+               </Border>
+       </Template>
+</Button>
index 80a9865449bd7f8ff75b62bb28a800a68fe5ebf4..d06bf00c6fee83de8b5353c92ba4d87c02db0113 100644 (file)
@@ -321,6 +321,7 @@ namespace CECrowPlugin
                                CMDEditMode.CanExecute = !value;
                                CMDRun.CanExecute = value;
                                NotifyValueChanged(value);
+                               ForceDirtyState();
                        }
                }               
                public double ZoomFactor {
@@ -363,7 +364,21 @@ namespace CECrowPlugin
                        if (IsRunning)
                                delUnlockRenderMutex();
                }
-               public bool GetDirtyState => IsRunning ? (bool)fiDbgIFace_IsDirty.GetValue (dbgIFace) : false;
+               
+               bool dirtyState = false;
+               bool DirtyState {
+                       get {
+                               if (dirtyState) {
+                                       dirtyState = false;
+                                       return true;
+                               } else
+                                       return false;
+                       }
+               }
+               // force repaint of preview widget without debug interface update.
+               bool ForceDirtyState() => dirtyState = true;
+
+               public bool GetDirtyState => IsRunning ? (bool)fiDbgIFace_IsDirty.GetValue (dbgIFace) | DirtyState : false;
                public bool DesignModeEnabled => IsRunning && ForeignWidgetContainer.fiWidget_design_id != null ? true : false;
                public Type GetWidgetTypeFromeName(string typeName) {
                        if (!IsRunning)
index 2cae562a20ba7a03e21589f99223c2dc1c736c11..fca86187776ec525c27cf16fdeb60a6db0929660 100644 (file)
@@ -44,7 +44,7 @@ namespace CECrowPlugin
                        designColumn = (int)fiWidget_design_column?.GetValue(instance);
                        designImlPath = (string)fiWidget_design_imlPath?.GetValue(instance);
 
-                       Console.WriteLine($"new ForeignWidgetContainer: {this} {parent}");
+                       //Console.WriteLine($"new ForeignWidgetContainer: {this} {parent}");
                }
 
 
index 44060536a3e29293dad603359077302ddc1a1aba..23b32c702d4e1ca6e270afea1bba26366452f1ac 100644 (file)
@@ -61,7 +61,7 @@ namespace CECrowPlugin
                        }
                }
                public string TemplateContainerSource {
-                       get => conf.Get (nameof(TemplateContainerSource), "<Button/>");
+                       get => conf.Get (nameof(TemplateContainerSource), "<Button>");
                        set {
                                if (TemplateContainerSource == value)
                                        return;
index 444d2c0acbae5e1791b21de32ab7ffb4993e920c..2876b519cda94b2263c8c8823ac5e1d8d9ad3e84 100644 (file)
@@ -92,14 +92,17 @@ namespace CrowEdit
                        saveWinConfigs ();
                }
                
-               public Command CMDSave, CMDSaveAs, CMDQuit, CMDHelp, CMDAbout, CMDOptions;
+               public Command CMDNew, CMDOpen, CMDSave, CMDSaveAs, CMDQuit, CMDHelp, CMDAbout, CMDOptions;
                public Command CMDSyntaxTheme_Reload, CMDSyntaxTheme_Save, CMDSyntaxTheme_SaveAs;
 
                void initCommands (){
+                       CMDNew = new ActionCommand("New", createNewFile, "#icons.blank-file.svg");
+                       CMDOpen = new ActionCommand("Open...", openFileDialog, "#icons.outbox.svg");
+                       CMDSave = new ActionCommand ("save", default(Action), "#icons.inbox.svg", false);
                        FileCommands = new CommandGroup ("File",
-                               new ActionCommand("New", createNewFile, "#icons.blank-file.svg"),
-                               new ActionCommand("Open...", openFileDialog, "#icons.outbox.svg"),
-                               new ActionCommand ("save", default(Action), "#icons.inbox.svg", false),
+                               CMDNew,
+                               CMDOpen,
+                               CMDSave,
                                new ActionCommand ("Save As...", default(Action), "#icons.inbox.svg", false),
                                new ActionCommand("Options", openOptionsDialog, "#icons.tools.svg"),
                                new ActionCommand("Quit", base.Quit, "#icons.sign-out.svg")
@@ -137,6 +140,8 @@ namespace CrowEdit
                                new CommandGroup ("Help", CMDHelp)
                        );
 
+                       ToolBox = new CommandGroup (CMDNew, CMDOpen, EditCommands);
+
                        CMDSyntaxTheme_Reload = new ActionCommand ("Reload", () => reloadSyntaxTheme ());
                        CMDSyntaxTheme_Save   = new ActionCommand ("Save", () => saveSyntaxTheme ());
                        CMDSyntaxTheme_SaveAs = new ActionCommand ("Save As...", () => saveSyntaxThemeAs ());
index caa59caf7bab1e1ea393d57293dd22c284026b39..832d0f38872e2f8758c0be0892d0e441a391c53f 100755 (executable)
                        </MenuItem>
                </ItemTemplate>
        </Menu>
+       <Menu Data="{ToolBox}" IsVisible="{CMDShowToolBox}" Margin="1">
+               <ItemTemplate DataType="Crow.Command" Path="#ui.IconButton.template"/>
+               <ItemTemplate DataType="Crow.CommandGroup">
+                       <MenuItem Data="{Commands}" Width="Fit" IsEnabled="{CanExecute}"
+                               ItemTemplate="#ui.IconButton.template">
+                               <Template>
+                                       <HorizontalStack Name="ItemsContainer" Margin="0"/>
+                               </Template>
+                       </MenuItem>
+               </ItemTemplate>
+       </Menu>
        <DockStack Name="mainDock"  RootDataLevel="true" Background="DarkGrey"/>
 </VerticalStack>
index edae52362da9ebeacded7991850b31af1515daf5..7abd92b10c8d3d0abfc5c28443fff81f43df6b13 100644 (file)
                                                <HorizontalStack Height="Fit" Spacing="5" Margin="0">
                                                        <Widget Width="Stretched"/>
                                                        <EnumSelector Caption="Filter:" EnumValue="{²../../log.Filter}" />
-                                                       <TextBox Background="Grey" Foreground="Black" Text="{²../../log.SearchString}" Width="200" KeyDown="../../log.onSearch" Font="${SmallUIFont}"/>
-                                                       <CheckBox Fit="true" Caption="Case Sensitive" IsChecked="{²../../log.CaseSensitiveSearch}" Font="${SmallUIFont}"/>
-                                                       <CheckBox Fit="true" Caption="All Word" IsChecked="{²../../log.AllWordSearch}" Font="${SmallUIFont}"/>
-                                                       <Menu Style="DockWinTitleBarMenu" Data="{../../log.SearchCommands}" Fit="true" Background="Transparent"/>
+                                                       <HorizontalStack Height="Fit" Spacing="3" Margin="0" Background="Grey">
+                                                       <TextBox Background="Transparent" Foreground="Black" Text="{²../../../log.SearchString}" Width="200" KeyDown="../../../log.onSearch" Font="${SmallUIFont}"/>
+                                                               <CheckBox Fit="true" Caption="Case Sensitive" IsChecked="{²../../../log.CaseSensitiveSearch}" Font="${SmallUIFont}"/>
+                                                               <CheckBox Fit="true" Caption="All Word" IsChecked="{²../../../log.AllWordSearch}" Font="${SmallUIFont}"/>
+                                                               <Menu Style="DockWinTitleBarMenu" Data="{../../../log.SearchCommands}" Fit="true" Background="Transparent"/>
+                                                       </HorizontalStack>
                                                </HorizontalStack>
                                                <HorizontalStack Spacing="0">
                                                        <LogViewerWidget Name="log" Logger="{}" Font="${SmallFont}" MaxScrollX="6000" ContextCommands="{Commands}" CurrentEntryIndex="{²SelectedIndex}"/>