// Copyright (c) 2013-2021 Bruyère Jean-Philippe // // 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; using System.Linq; namespace Samples { public class SampleBaseForEditor : SampleBase { static SampleBaseForEditor() { //DbgLogger.ConsoleOutput = !Configuration.Global.Get (nameof (DebugLogToFile)); //RecordedEvents = Configuration.Global.Get> ("RecordedEvents"); } 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 Editor editor; public string CurrentDir { get => Configuration.Global.Get (nameof (CurrentDir)); set { if (CurrentDir == value) return; Configuration.Global.Set (nameof (CurrentDir), value); NotifyValueChanged (CurrentDir); } } public string CurrentFile { get => Configuration.Global.Get (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); } } #region DebugLog bool debugLogRecording; public bool DebugLoggingEnabled => DbgLogger.IsEnabled; static ObservableList RecordedEvents; public bool DebugLogRecording { get => debugLogRecording; set { if (debugLogRecording == value) return; debugLogRecording = value; if (debugLogRecording) { DbgLogger.IncludedEvents = new List(RecordedEvents); } else { DbgLogger.IncludedEvents = null; } NotifyValueChanged(debugLogRecording); } } public bool DebugLogToFile { get => Configuration.Global.Get (nameof(DebugLogToFile)); set { if (DebugLogToFile == value) return; Configuration.Global.Set (nameof(DebugLogToFile), value); NotifyValueChanged(DebugLogToFile); DbgLogger.ConsoleOutput = !value; } } public string DebugLogFilePath { get => Configuration.Global.Get (nameof (DebugLogFilePath)); set { if (CurrentFile == value) return; Configuration.Global.Set (nameof (DebugLogFilePath), value); NotifyValueChanged (DebugLogFilePath); } } #endregion public new bool IsDirty => source != origSource; public ActionCommand CMDNew, CMDOpen, CMDSave, CMDSaveAs, CMDQuit, CMDShowLeftPane, CMDUndo, CMDRedo, CMDCut, CMDCopy, CMDPaste, CMDHelp, CMDAbout, CMDOptions; public CommandGroup EditorFileCommands, EditorEditCommands, EditorAllCommands; protected virtual void initCommands () { CMDNew = new ActionCommand ("New", new Action (onNewFile), "#Icons.blank-file.svg"); CMDSave = new ActionCommand ("Save", new Action (onSave), "#Icons.save.svg", false); CMDSaveAs = new ActionCommand ("Save As...", new Action (onSaveAs), "#Icons.save.svg"); CMDQuit = new ActionCommand ("Quit", new Action (() => base.Quit ()), "#Icons.exit.svg"); CMDUndo = new ActionCommand ("Undo", new Action (undo),"#Icons.undo.svg", false); CMDRedo = new ActionCommand ("Redo", new Action (redo),"#Icons.redo.svg", false); CMDCut = new ActionCommand ("Cut", new Action (cut), "#Icons.scissors.svg", false); CMDCopy = new ActionCommand ("Copy", new Action (copy), "#Icons.copy-file.svg", false); CMDPaste= new ActionCommand ("Paste", new Action (paste), "#Icons.paste-on-document.svg", false); EditorFileCommands = new CommandGroup ("File", CMDSave, CMDSaveAs, CMDQuit); EditorEditCommands = new CommandGroup ("Edit", CMDUndo, CMDRedo, CMDCut, CMDCopy, CMDPaste); EditorAllCommands = new CommandGroup (EditorFileCommands, EditorEditCommands); } protected Stack undoStack = new Stack (); protected Stack redoStack = new Stack (); protected TextSpan selection; protected string SelectedText => selection.IsEmpty ? "" : Source.AsSpan (selection.Start, selection.Length).ToString (); public void onEditorSelectionChanged(Object sender, TextSelectionChangeEventArgs e) { selection = e.Selection; CMDCut.CanExecute = CMDCopy.CanExecute = !selection.IsEmpty; } 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; CMDPaste.CanExecute = !string.IsNullOrEmpty (Clipboard); } 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 (@"").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 = @"