// 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; 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 (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); } } public bool DebugLoggingEnabled => DbgLogger.IsEnabled; public DbgEvtType RecordedEvents { get => Configuration.Global.Get (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 (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 bool DebugLogToFile { get => Configuration.Global.Get (nameof(DebugLogToFile)); set { if (DebugLogToFile != value) return; Configuration.Global.Set (nameof(DebugLogToFile), value); NotifyValueChanged(DebugLogToFile); DbgLogger.ConsoleOutput = !value; } } protected static void initDebugLog () { DbgLogger.IncludeEvents = DbgEvtType.None; DbgLogger.DiscardEvents = DbgEvtType.All; //DbgLogger.DiscardEvents = DbgEvtType.All; DbgLogger.ConsoleOutput = !Configuration.Global.Get (nameof (DebugLogToFile)); } 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 undoStack = new Stack (); protected Stack redoStack = new Stack (); 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 (@"").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 = @"