aboutsummaryrefslogtreecommitdiffstatsci
path: root/CrowIDE/src/ProjectTree/ProjectFile.cs
diff options
context:
space:
mode:
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>2018-03-11 13:20:27 +0100
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>2018-03-11 13:20:27 +0100
commit1c2da8cc925b78687b87d3168322bc1088ae10cd (patch)
tree4e6a32f363e47f9f4596cb474ebe9ac80ec33d54 /CrowIDE/src/ProjectTree/ProjectFile.cs
parentce0ae6979394ea2274c9467bf84f5e5cf0177f11 (diff)
split ProjectNode classes in separate files
Diffstat (limited to 'CrowIDE/src/ProjectTree/ProjectFile.cs')
-rw-r--r--CrowIDE/src/ProjectTree/ProjectFile.cs290
1 files changed, 290 insertions, 0 deletions
diff --git a/CrowIDE/src/ProjectTree/ProjectFile.cs b/CrowIDE/src/ProjectTree/ProjectFile.cs
new file mode 100644
index 00000000..2c3dbbe4
--- /dev/null
+++ b/CrowIDE/src/ProjectTree/ProjectFile.cs
@@ -0,0 +1,290 @@
+//
+// ProjectNodes.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// 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.Linq;
+using System.Xml;
+using System.IO;
+using Crow;
+using System.Threading;
+
+namespace Crow.Coding
+{
+ public class ProjectFile : ProjectItem {
+ protected bool isOpened = false;
+ DateTime accessTime;
+ string source;
+ string origSource;
+ object selectedItem;
+ int curLine, curColumn;
+
+ internal ReaderWriterLockSlim srcEditMtx = new ReaderWriterLockSlim();
+
+ public Dictionary<object, bool> RegisteredEditors = new Dictionary<object, bool>();
+ List<String> undoStack = new List<string>();
+ List<String> redoStack = new List<string>();
+
+ public Crow.Command cmdSave, cmdSaveAs, cmdOpen, cmdUndo, cmdRedo;
+
+ void initCommands (){
+ cmdSave = new Crow.Command (new Action (() => Save ()))
+ { Caption = "Save", Icon = new SvgPicture ("#Crow.Coding.ui.icons.inbox.svg"), CanExecute = false };
+ cmdSaveAs = new Crow.Command (new Action (() => SaveAs ()))
+ { Caption = "Save As ..", Icon = new SvgPicture ("#Crow.Coding.ui.icons.inbox.svg"), CanExecute = false };
+ cmdOpen = new Crow.Command (new Action (() => Open ()))
+ { Caption = "Open", Icon = new SvgPicture ("#Crow.Coding.ui.icons.outbox.svg"), CanExecute = false };
+ cmdUndo = new Crow.Command (new Action (() => Undo (null)))
+ { Caption = "Undo", Icon = new SvgPicture ("#Crow.Coding.icons.undo.svg"), CanExecute = false };
+ cmdRedo = new Crow.Command (new Action (() => Redo (null)))
+ { Caption = "Redo", Icon = new SvgPicture ("#Crow.Coding.icons.redo.svg"), CanExecute = false };
+
+ Commands.Insert (0, cmdOpen);
+ Commands.Insert (1, cmdSave);
+ }
+ 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 void UnregisterEditor (object editor){
+ lock(RegisteredEditors){
+ RegisteredEditors.Remove (editor);
+ }
+ }
+ public void RegisterEditor (object editor) {
+ lock(RegisteredEditors){
+ RegisteredEditors.Add (editor, false);
+ }
+ }
+ public void UpdateSource (object sender, string newSrc){
+ System.Diagnostics.Debug.WriteLine ("update source by {0}", sender);
+ Source = newSrc;
+ signalOtherRegisteredEditors (sender);
+ }
+ 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)
+ Open ();
+ 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 void Open () {
+ accessTime = System.IO.File.GetLastWriteTime (AbsolutePath);
+ using (StreamReader sr = new StreamReader (AbsolutePath)) {
+ source = sr.ReadToEnd ();
+ }
+ isOpened = true;
+ origSource = source;
+ NotifyValueChanged ("IsDirty", false);
+ }
+ public void Save () {
+ if (!IsDirty)
+ return;
+ using (StreamWriter sw = new StreamWriter (AbsolutePath)) {
+ sw.Write (source);
+ }
+ origSource = source;
+ NotifyValueChanged ("IsDirty", false);
+ }
+ public void SaveAs () {
+ if (!IsDirty)
+ return;
+ using (StreamWriter sw = new StreamWriter (AbsolutePath)) {
+ sw.Write (source);
+ }
+ origSource = source;
+ NotifyValueChanged ("IsDirty", false);
+ }
+ public void Close () {
+ origSource = null;
+ isOpened = false;
+ Project.solution.CloseItem (this);
+ }
+ 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 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 += onClickSaveAndCloseNow;
+ mb.No += onClickCloseNow;
+ } else
+ Close ();
+ }
+
+ void onClickCloseNow (object sender, EventArgs e)
+ {
+ Close ();
+ }
+
+ void onClickSaveAndCloseNow (object sender, EventArgs e)
+ {
+ Save ();
+ Close ();
+ }
+ }
+}
+