diff options
| author | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2021-06-07 15:05:30 +0200 |
|---|---|---|
| committer | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2021-06-07 15:05:30 +0200 |
| commit | 263de03914a3de5d55c4508c322e32d36caf2a87 (patch) | |
| tree | c279464365fd7683744fa59d01b242e4b3ab17b9 /Samples/common/src/SampleBaseForEditor.cs | |
| parent | f738cf0f78c57750cce8fd5744825b0591f24bb8 (diff) | |
suggestion in IML editor, editor base classe for ShowCase and LogAnalyzerSimplifiedTabView
Diffstat (limited to 'Samples/common/src/SampleBaseForEditor.cs')
| -rw-r--r-- | Samples/common/src/SampleBaseForEditor.cs | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/Samples/common/src/SampleBaseForEditor.cs b/Samples/common/src/SampleBaseForEditor.cs new file mode 100644 index 00000000..4af718a2 --- /dev/null +++ b/Samples/common/src/SampleBaseForEditor.cs @@ -0,0 +1,312 @@ +// Copyright (c) 2013-2021 Bruyère Jean-Philippe <jp_bruyere@hotmail.com> +// +// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) + +using System; +using Crow; +using System.IO; +using System.Text; +using Crow.IML; +using System.Runtime.CompilerServices; +using Glfw; +using System.Diagnostics; +using Crow.Text; +using System.Collections.Generic; +using Encoding = System.Text.Encoding; + +namespace Samples +{ + public class SampleBaseForEditor : SampleBase + { + public static SampleBaseForEditor CurrentProgramInstance; + + protected override void OnInitialized () { + initCommands (); + + base.OnInitialized (); + + if (string.IsNullOrEmpty (CurrentDir)) + CurrentDir = Path.Combine (Directory.GetCurrentDirectory (), "Interfaces"); + + } + + protected const string _defaultFileName = "unnamed.txt"; + protected string source = "", origSource; + protected TextBox editor; + bool debugLogRecording; + + + public string CurrentDir { + get => Configuration.Global.Get<string> (nameof (CurrentDir)); + set { + if (CurrentDir == value) + return; + Configuration.Global.Set (nameof (CurrentDir), value); + NotifyValueChanged (CurrentDir); + } + } + public string CurrentFile { + get => Configuration.Global.Get<string> (nameof (CurrentFile)); + set { + if (CurrentFile == value) + return; + Configuration.Global.Set (nameof (CurrentFile), value); + NotifyValueChanged (CurrentFile); + } + } + public virtual string Source { + get => source; + set { + if (source == value) + return; + source = value; + CMDSave.CanExecute = IsDirty; + NotifyValueChanged (source); + NotifyValueChanged ("IsDirty", IsDirty); + } + } + public bool DebugLoggingEnabled => DbgLogger.IsEnabled; + + public DbgEvtType RecordedEvents { + get => Configuration.Global.Get<DbgEvtType> (nameof (RecordedEvents)); + set { + if (RecordedEvents == value) + return; + Configuration.Global.Set (nameof (RecordedEvents), value); + if (DebugLogRecording) + DbgLogger.IncludeEvents = RecordedEvents; + NotifyValueChanged(RecordedEvents); + } + } + public DbgEvtType DiscardedEvents { + get => Configuration.Global.Get<DbgEvtType> (nameof (DiscardedEvents)); + set { + if (DiscardedEvents == value) + return; + Configuration.Global.Set (nameof (DiscardedEvents), value); + if (DebugLogRecording) + DbgLogger.DiscardEvents = DiscardedEvents; + NotifyValueChanged(DiscardedEvents); + } + } + public bool DebugLogRecording { + get => debugLogRecording; + set { + if (debugLogRecording == value) + return; + debugLogRecording = value; + NotifyValueChanged(debugLogRecording); + } + } + + public new bool IsDirty => source != origSource; + + + public Command CMDNew, CMDOpen, CMDSave, CMDSaveAs, CMDQuit, CMDShowLeftPane, + CMDUndo, CMDRedo, CMDCut, CMDCopy, CMDPaste, CMDHelp, CMDAbout, CMDOptions; + public CommandGroup EditorCommands => new CommandGroup (CMDUndo, CMDRedo, CMDCut, CMDCopy, CMDPaste, CMDSave, CMDSaveAs); + protected virtual void initCommands () + { + CMDNew = new Command ("New", new Action (onNewFile), "#Icons.blank-file.svg"); + CMDSave = new Command ("Save", new Action (onSave), "#Icons.save.svg", false); + CMDSaveAs = new Command ("Save As...", new Action (onSaveAs), "#Icons.save.svg"); + CMDQuit = new Command ("Quit", new Action (() => base.Quit ()), "#Icons.exit.svg"); + CMDUndo = new Command ("Undo", new Action (undo),"#Icons.undo.svg", false); + CMDRedo = new Command ("Redo", new Action (redo),"#Icons.redo.svg", false); + CMDCut = new Command ("Cut", new Action (cut), "#Icons.scissors.svg", false); + CMDCopy = new Command ("Copy", new Action (copy), "#Icons.copy-file.svg", false); + CMDPaste= new Command ("Paste", new Action (paste), "#Icons.paste-on-document.svg", false); + } + + + protected Stack<TextChange> undoStack = new Stack<TextChange> (); + protected Stack<TextChange> redoStack = new Stack<TextChange> (); + protected TextSpan selection; + protected string SelectedText => + selection.IsEmpty ? "" : Source.AsSpan (selection.Start, selection.Length).ToString (); + + protected void undo () { + if (undoStack.TryPop (out TextChange tch)) { + redoStack.Push (tch.Inverse (source)); + CMDRedo.CanExecute = true; + apply (tch); + editor.SetCursorPosition (tch.End + tch.ChangedText.Length); + } + if (undoStack.Count == 0) + CMDUndo.CanExecute = false; + } + protected void redo () { + if (redoStack.TryPop (out TextChange tch)) { + undoStack.Push (tch.Inverse (source)); + CMDUndo.CanExecute = true; + apply (tch); + editor.SetCursorPosition (tch.End + tch.ChangedText.Length); + } + if (redoStack.Count == 0) + CMDRedo.CanExecute = false; + } + protected void resetUndoRedo () { + undoStack.Clear (); + redoStack.Clear (); + CMDUndo.CanExecute = false; + CMDRedo.CanExecute = false; + } + + protected void cut () { + copy (); + applyChange (new TextChange (selection.Start, selection.Length, "")); + } + protected void copy () { + Clipboard = SelectedText; + } + protected void paste () { + applyChange (new TextChange (selection.Start, selection.Length, Clipboard)); + } + protected void onNewFile () { + if (IsDirty) { + MessageBox.ShowModal (this, MessageBox.Type.YesNo, "Current file has unsaved changes, are you sure?").Yes += (sender, e) => newFile (); + } else + newFile (); + } + protected void onSave () + { + if (!File.Exists (CurrentFile)) { + onSaveAs (); + return; + } + save (); + } + protected void onSaveAs () + { + string dir = Path.GetDirectoryName (CurrentFile); + if (string.IsNullOrEmpty (dir)) + dir = Directory.GetCurrentDirectory (); + LoadIMLFragment (@"<FileDialog Width='60%' Height='50%' Caption='Save as ...' CurrentDirectory='" + + dir + "' SelectedFile='" + + Path.GetFileName(CurrentFile) + "' OkClicked='saveFileDialog_OkClicked'/>").DataSource = this; + } + protected void saveFileDialog_OkClicked (object sender, EventArgs e) + { + FileDialog fd = sender as FileDialog; + + if (string.IsNullOrEmpty (fd.SelectedFileFullPath)) + return; + + if (File.Exists(fd.SelectedFileFullPath)) { + MessageBox mb = MessageBox.ShowModal (this, MessageBox.Type.YesNo, "File exists, overwrite?"); + mb.Yes += (sender2, e2) => { + CurrentFile = fd.SelectedFileFullPath; + save (); + }; + return; + } + + CurrentFile = fd.SelectedFileFullPath; + save (); + } + + protected void newFile() + { + disableTextChangedEvent = true; + Source = @"<Label Text='Hello World' Background='MediumSeaGreen' Margin='10'/>"; + disableTextChangedEvent = false; + resetUndoRedo (); + if (!string.IsNullOrEmpty (CurrentFile)) + CurrentFile = Path.Combine (Path.GetDirectoryName (CurrentFile), "newfile.crow"); + else + CurrentFile = Path.Combine (CurrentDir, "newfile.crow"); + } + + protected void save () { + using (Stream s = new FileStream(CurrentFile, FileMode.Create)) { + s.WriteByte (0xEF); + s.WriteByte (0xBB); + s.WriteByte (0xBF); + byte [] buff = Encoding.UTF8.GetBytes (source); + s.Write (buff, 0, buff.Length); + } + origSource = source; + NotifyValueChanged ("IsDirty", IsDirty); + CMDSave.CanExecute = false; + } + + protected void reloadFromFile () { + disableTextChangedEvent = true; + if (File.Exists (CurrentFile)) { + using (Stream s = new FileStream (CurrentFile, FileMode.Open)) { + using (StreamReader sr = new StreamReader (s)) + Source = origSource = sr.ReadToEnd (); + } + } + disableTextChangedEvent = false; + resetUndoRedo (); + } + protected bool disableTextChangedEvent = false; + protected void apply (TextChange change) { + Span<char> tmp = stackalloc char[source.Length + (change.ChangedText.Length - change.Length)]; + ReadOnlySpan<char> src = source.AsSpan (); + src.Slice (0, change.Start).CopyTo (tmp); + if (!string.IsNullOrEmpty (change.ChangedText)) + change.ChangedText.AsSpan ().CopyTo (tmp.Slice (change.Start)); + src.Slice (change.End).CopyTo (tmp.Slice (change.Start + change.ChangedText.Length)); + disableTextChangedEvent = true; + Source = tmp.ToString (); + disableTextChangedEvent = false; + } + protected void applyChange (TextChange change) { + undoStack.Push (change.Inverse (source)); + redoStack.Clear (); + CMDUndo.CanExecute = true; + CMDRedo.CanExecute = false; + apply (change); + } + public void goUpDirClick (object sender, MouseButtonEventArgs e) + { + string root = Directory.GetDirectoryRoot (CurrentDir); + if (CurrentDir == root) + return; + CurrentDir = Directory.GetParent (CurrentDir).FullName; + } + + protected void Dv_SelectedItemChanged (object sender, SelectionChangeEventArgs e) + { + FileSystemInfo fi = e.NewValue as FileSystemInfo; + if (fi == null) + return; + if (fi is DirectoryInfo) + return; + + if (IsDirty) { + MessageBox mb = MessageBox.ShowModal (this, MessageBox.Type.YesNo, "Current file has unsaved changes, are you sure?"); + mb.Yes += (mbsender, mbe) => { CurrentFile = fi.FullName; reloadFromFile (); }; + return; + } + + CurrentFile = fi.FullName; + reloadFromFile (); + } + protected void onTextChanged (object sender, TextChangeEventArgs e) { + if (disableTextChangedEvent) + return; + applyChange (e.Change); + } + + protected void onSelectedTextChanged (object sender, EventArgs e) { + selection = (sender as Label).Selection; + Console.WriteLine($"selection:{selection.Start} length:{selection.Length}"); + CMDCut.CanExecute = CMDCopy.CanExecute = !selection.IsEmpty; + } + protected void textView_KeyDown (object sender, Crow.KeyEventArgs e) { + if (Ctrl) { + if (e.Key == Glfw.Key.W) { + if (Shift) + CMDRedo.Execute (); + else + CMDUndo.Execute (); + } else if (e.Key == Glfw.Key.S) { + onSave (); + } + } + } + } +}
\ No newline at end of file |