From b88fa1ecf7537492ff7c3090caf95e0f3e9c3113 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Bruyère Date: Sat, 3 Aug 2019 19:49:15 +0200 Subject: sample directory --- Samples/CrowIDE/src/ProjectTree/ProjectFile.cs | 323 +++++++++++++++++++++++++ 1 file changed, 323 insertions(+) create mode 100644 Samples/CrowIDE/src/ProjectTree/ProjectFile.cs (limited to 'Samples/CrowIDE/src/ProjectTree/ProjectFile.cs') diff --git a/Samples/CrowIDE/src/ProjectTree/ProjectFile.cs b/Samples/CrowIDE/src/ProjectTree/ProjectFile.cs new file mode 100644 index 00000000..294a28f5 --- /dev/null +++ b/Samples/CrowIDE/src/ProjectTree/ProjectFile.cs @@ -0,0 +1,323 @@ +// +// ProjectNodes.cs +// +// Author: +// Jean-Philippe Bruyère +// +// Copyright (c) 2013-2017 Jean-Philippe Bruyère +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Xml; + +namespace Crow.Coding { + public class ProjectFile : ProjectItem { + bool isOpened = false; + DateTime accessTime; + string source; + string origSource; + object selectedItem; + int curLine, curColumn; + + internal ReaderWriterLockSlim srcEditMtx = new ReaderWriterLockSlim(); + + public Dictionary RegisteredEditors = new Dictionary(); + List undoStack = new List(); + List redoStack = new List(); + + public Crow.Command cmdSave, cmdSaveAs, cmdOpen, cmdClose, cmdUndo, cmdRedo; + + void initCommands (){ + cmdSave = new Crow.Command (new Action (() => Save ())) + { Caption = "Save", Icon = new SvgPicture ("#CrowIDE.icons.save.svg"), CanExecute = false }; + cmdSaveAs = new Crow.Command (new Action (() => SaveAs ())) + { Caption = "Save As ..", Icon = new SvgPicture ("#CrowIDE.icons.save.svg"), CanExecute = false }; + cmdOpen = new Crow.Command (new Action (() => Open ())) + { Caption = "Open", Icon = new SvgPicture ("#CrowIDE.icons.open.svg"), CanExecute = true }; + cmdClose = new Crow.Command (new Action (() => OnQueryClose (this,null))) + { Caption = "Close", Icon = new SvgPicture ("#CrowIDE.icons.open.svg"), CanExecute = false }; + cmdUndo = new Crow.Command (new Action (() => Undo (null))) + { Caption = "Undo", Icon = new SvgPicture ("#CrowIDE.icons.undo.svg"), CanExecute = false }; + cmdRedo = new Crow.Command (new Action (() => Redo (null))) + { Caption = "Redo", Icon = new SvgPicture ("#CrowIDE.icons.redo.svg"), CanExecute = false }; + + Commands.Insert (0, cmdOpen); + Commands.Insert (1, cmdSave); + Commands.Insert (2, cmdSaveAs); + Commands.Insert (3, cmdUndo); + Commands.Insert (4, cmdRedo); + Commands.Add (cmdClose); + } + public ProjectFile () { + initCommands(); + } + public ProjectFile (ProjectItem pi) + : base (pi.Project, pi.node) { + initCommands (); + } + + public string ResourceID { + get { + return Type != ItemType.EmbeddedResource ? null : + node.SelectSingleNode ("LogicalName") == null ? + Project.Name + "." + Path.Replace ('/', '.') : + LogicalName; + } + } + public string LogicalName { + get { + return node.SelectSingleNode ("LogicalName")?.InnerText; + } + } + public bool IsOpened { + get { return isOpened; } + set { + if (isOpened == value) + return; + isOpened = value; + + cmdOpen.CanExecute = !isOpened; + cmdClose.CanExecute = isOpened; + cmdSave.CanExecute = isOpened && IsDirty; + + if (isOpened) + Project.solution.OpenItem (this); + else + Project.solution.CloseItem (this); + + NotifyValueChanged ("IsOpened", isOpened); + } + } + + public void UnregisterEditor (object editor){ + lock(RegisteredEditors){ + RegisteredEditors.Remove (editor); + } + } + public void RegisterEditor (object editor) { + lock(RegisteredEditors){ + RegisteredEditors.Add (editor, false); + } + } + public virtual void UpdateSource (object sender, string newSrc){ + System.Diagnostics.Debug.WriteLine ("update source by {0}", sender); + Source = newSrc; + signalOtherRegisteredEditors (sender); + } + public void SignalEditorOfType (){ + lock (RegisteredEditors) { + object[] keys = RegisteredEditors.Keys.ToArray (); + foreach (object ed in keys) { + T editor = (T)ed; + if (editor == null) + continue; + RegisteredEditors [editor] = false; + break; + } + } + } + protected void signalOtherRegisteredEditors (object sender) { + lock (RegisteredEditors) { + object[] keys = RegisteredEditors.Keys.ToArray (); + foreach (object editor in keys) { + if (editor != sender) + RegisteredEditors [editor] = false; + } + } + } + public string Source { + get { + if (!IsOpened) { + using (StreamReader sr = new StreamReader (AbsolutePath)) + source = sr.ReadToEnd (); + + } else { + if (DateTime.Compare ( + accessTime, + System.IO.File.GetLastWriteTime (AbsolutePath)) < 0) + Console.WriteLine ("File has been modified outside CrowIDE"); + } + return source; + } + set { + if (source == value) + return; + + srcEditMtx.EnterWriteLock (); + + undoStack.Add (source); + cmdUndo.CanExecute = true; + redoStack.Clear (); + cmdRedo.CanExecute = false; + source = value; + + NotifyValueChanged ("Source", source); + NotifyValueChanged ("IsDirty", IsDirty); + + cmdSave.CanExecute = cmdSaveAs.CanExecute = IsDirty; + + srcEditMtx.ExitWriteLock (); + } + } + public bool IsDirty { + get { return source != origSource; } + } + public int CurrentColumn{ + get { return curColumn; } + set { + if (curColumn == value) + return; + curColumn = value; + NotifyValueChanged ("CurrentColumn", curColumn); + } + } + public int CurrentLine{ + get { return curLine; } + set { + if (curLine == value) + return; + curLine = value; + NotifyValueChanged ("CurrentLine", curLine); + } + } + + public object SelectedItem { + get { return selectedItem; } + set { + if (selectedItem == value) + return; + selectedItem= value; + Project.solution.SelectedItemElement = value; + NotifyValueChanged ("SelectedItem", selectedItem); + } + } + + public CopyToOutputState CopyToOutputDirectory { + get { + XmlNode xn = node.SelectSingleNode ("CopyToOutputDirectory"); + return xn == null ? CopyToOutputState.Never : + (CopyToOutputState)Enum.Parse (typeof(CopyToOutputState), xn.InnerText, true); + } + } + + public virtual void Open () { + accessTime = System.IO.File.GetLastWriteTime (AbsolutePath); + using (StreamReader sr = new StreamReader (AbsolutePath)) { + source = sr.ReadToEnd (); + } + origSource = source; + IsOpened = true; + NotifyValueChanged ("IsDirty", false); + } + public virtual void Save () { + if (!IsDirty) + return; + using (StreamWriter sw = new StreamWriter (AbsolutePath)) { + sw.Write (source); + } + origSource = source; + NotifyValueChanged ("IsDirty", false); + } + public virtual void SaveAs () { + if (!IsDirty) + return; + using (StreamWriter sw = new StreamWriter (AbsolutePath)) { + sw.Write (source); + } + origSource = source; + NotifyValueChanged ("IsDirty", false); + } + public void Close () { + origSource = source = null; + IsOpened = false; + } + public void Undo(object sender){ + undo(); + signalOtherRegisteredEditors (sender); + } + public void Redo(object sender){ + redo(); + signalOtherRegisteredEditors (sender); + } + + void undo () { + if (undoStack.Count == 0) + return; + + srcEditMtx.EnterWriteLock (); + string step = undoStack [undoStack.Count -1]; + redoStack.Add (source); + cmdRedo.CanExecute = true; + undoStack.RemoveAt(undoStack.Count -1); + + source = step; + + NotifyValueChanged ("Source", source); + NotifyValueChanged ("IsDirty", IsDirty); + cmdSave.CanExecute = IsDirty; + + if (undoStack.Count == 0) + cmdUndo.CanExecute = false; + srcEditMtx.ExitWriteLock (); + } + + void redo () { + if (redoStack.Count == 0) + return; + srcEditMtx.EnterWriteLock (); + string step = redoStack [redoStack.Count -1]; + undoStack.Add (source); + cmdUndo.CanExecute = true; + redoStack.RemoveAt(redoStack.Count -1); + source = step; + NotifyValueChanged ("Source", source); + NotifyValueChanged ("IsDirty", IsDirty); + cmdSave.CanExecute = IsDirty; + + if (redoStack.Count == 0) + cmdRedo.CanExecute = false; + srcEditMtx.ExitWriteLock (); + + } + + public void onDoubleClick (object sender, MouseButtonEventArgs e){ + if (IsOpened) + return; + Open (); + } + + public void onClick (object sender, MouseButtonEventArgs e){ + IsSelected = true; + } + public void OnQueryClose (object sender, EventArgs e){ + if (IsDirty) { + MessageBox mb = MessageBox.ShowModal (CrowIDE.MainIFace, + MessageBox.Type.YesNoCancel, $"{DisplayName} has unsaved changes.\nSave it now?"); + mb.Yes += (object _sender, EventArgs _e) => { Save (); Close (); }; + mb.No += (object _sender, EventArgs _e) => Close(); + } else + Close (); + } + } +} + -- cgit v1.3.1-4-g156e