Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2839_HiveProjectManagement/HeuristicLab.Data.Views/3.3/Path Views/TextFileView.cs @ 16057

Last change on this file since 16057 was 16057, checked in by jkarder, 6 years ago

#2839:

File size: 9.2 KB
RevLine 
[9671]1#region License Information
2/* HeuristicLab
[16057]3 * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[9671]4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Drawing;
24using System.IO;
25using System.Windows.Forms;
26using HeuristicLab.MainForm;
[9850]27using HeuristicLab.PluginInfrastructure;
[9671]28
[9680]29namespace HeuristicLab.Data.Views {
[9671]30  [View("TextFileView")]
[9714]31  [Content(typeof(TextFileValue), true)]
[9833]32  public sealed partial class TextFileView : FileValueView {
33    private bool fileContentChanged;
34    private bool FileContentChanged {
35      get { return fileContentChanged; }
[9671]36      set {
[9833]37        if (fileContentChanged != value) {
38          fileContentChanged = value;
39          OnFileContentChanged();
[9671]40        }
41      }
42    }
43
[9714]44    public new TextFileValue Content {
45      get { return (TextFileValue)base.Content; }
[9671]46      set { base.Content = value; }
47    }
48
49    public TextFileView() {
50      InitializeComponent();
[9833]51      fileContentChanged = false;
[9671]52    }
53
54    protected override void RegisterContentEvents() {
55      base.RegisterContentEvents();
[9833]56      Content.StringValue.ValueChanged += Content_FilePathChanged;
[9671]57    }
58    protected override void DeregisterContentEvents() {
[9833]59      Content.StringValue.ValueChanged -= Content_FilePathChanged;
[9671]60      fileSystemWatcher.EnableRaisingEvents = false;
61      base.DeregisterContentEvents();
62    }
63    protected override void SetEnabledStateOfControls() {
64      base.SetEnabledStateOfControls();
65      textBox.ReadOnly = Locked || ReadOnly || Content == null;
[9833]66      saveButton.Enabled = !Locked && !ReadOnly && Content != null && FileContentChanged;
[9671]67
[9697]68      if (Content != null && Content.Exists()) {
[9671]69        fileSystemWatcher.Filter = Path.GetFileName(Content.Value);
[11034]70        var path = Path.GetDirectoryName(Content.Value);
71        if (string.IsNullOrEmpty(path)) path = Environment.CurrentDirectory;
72        fileSystemWatcher.Path = path;
[9671]73      }
74      fileSystemWatcher.EnableRaisingEvents = Content != null && File.Exists(Content.Value) && Visible;
75    }
76
77    protected override void OnVisibleChanged(EventArgs e) {
78      //mkommend: necessary to update the textbox to detect intermediate file changes.
[9697]79      if (Visible && Content != null) UpdateTextBox();
[9671]80      base.OnVisibleChanged(e);
81    }
82
83    protected override void OnContentChanged() {
84      base.OnContentChanged();
[9833]85      FileContentChanged = false;
[9671]86      if (Content == null) {
87        textBox.Text = string.Empty;
[9705]88        //mkommend: other properties of the file system watcher cannot be cleared (e.g., path) as this leads to an ArgumentException
89        fileSystemWatcher.EnableRaisingEvents = false;
[9671]90        return;
91      }
92      saveFileDialog.Filter = Content.FileDialogFilter;
93      UpdateTextBox();
94    }
95
[9714]96    private void Content_FilePathChanged(object sender, EventArgs e) {
[9671]97      UpdateTextBox();
98      SetEnabledStateOfControls();
99    }
100
[9714]101    private void textBox_TextChanged(object sender, EventArgs e) {
[9833]102      FileContentChanged = fileText != textBox.Text;
[9671]103    }
104
[9833]105    private void OnFileContentChanged() {
[9671]106      SetEnabledStateOfControls();
[9833]107      textBox.ForeColor = FileContentChanged ? Color.Red : Color.Black;
[9671]108    }
109
[9714]110    private bool fileSystemWatcherChangedFired = false;
111    private void fileSystemWatcher_Changed(object sender, FileSystemEventArgs e) {
[9671]112      //mkommend: cannot react on visible changed, because this event is not fired when the parent control gets visible set to false
113      if (!Visible) return;
114      //FileSystemWatcher may fire multiple events depending on how file changes are implemented in the modifying program
115      //see: http://stackoverflow.com/questions/1764809/filesystemwatcher-changed-event-is-raised-twice
116      if (fileSystemWatcherChangedFired) return;
117      fileSystemWatcherChangedFired = true;
118
119      string newContent = ReadFile(Content.Value);
120      if (newContent == textBox.Text) {
121        fileSystemWatcherChangedFired = false;
122        return;
123      }
124
125      //File created
126      if (e.ChangeType == WatcherChangeTypes.Created) {
127        UpdateTextBox();
128      }
129
130      //File changed
131      else if (e.ChangeType == WatcherChangeTypes.Changed) {
132        string msg = string.Format("The content of the file \"{0}\" has changed.\nDo you want to reload the file?", Content.Value);
133        var result = MessageBox.Show(this, msg, "Reload the file?", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
134        if (result == DialogResult.Yes) {
135          UpdateTextBox();
136        } else {
137          fileText = newContent;
[9833]138          FileContentChanged = true;
[9671]139        }
140      }
141
142      //File deleted
143      else if (e.ChangeType == WatcherChangeTypes.Deleted) {
144        string msg = string.Format("The file \"{0}\" is not present anymore. Do you want to restore the file from the given content?", Content.Value);
145        var result = MessageBox.Show(this, msg, "Restore file?", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
146        if (result == DialogResult.Yes) {
147          SaveFile();
148        }
149        UpdateTextBox();
150      }
151      fileSystemWatcherChangedFired = false;
152    }
153
[9714]154    private void fileSystemWatcher_Renamed(object sender, RenamedEventArgs e) {
[9671]155      //mkommend: cannot react on visible changed, because this event is not fired when the parent control gets visible set to false
156      if (!Visible) return;
157      string msg = string.Format("The file \"{0}\" got renamed to \"{1}\". Do you want to update the file path?", e.OldName, e.Name);
158      var result = MessageBox.Show(this, msg, "Update file path?", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
159      if (result == DialogResult.Yes) {
160        Content.Value = e.FullPath;
161        fileSystemWatcher.Filter = e.Name;
162      }
163      UpdateTextBox();
164    }
165
[9714]166    private void SaveFile() {
[9671]167      //omit circular events by changing the file from HL
168      fileSystemWatcher.EnableRaisingEvents = false;
169      string path = Content.Value;
170      if (string.IsNullOrEmpty(path)) {
171        if (saveFileDialog.ShowDialog(this) != DialogResult.OK) return;
172        path = saveFileDialog.FileName;
173      }
174
175      WriteFile(path, textBox.Text);
176      Content.Value = path;
[9833]177      FileContentChanged = false;
[9671]178      fileSystemWatcher.EnableRaisingEvents = true;
179    }
180
[9714]181    private void saveButton_Click(object sender, EventArgs e) {
[9671]182      SaveFile();
183    }
184
[9714]185    private string fileText;
186    private void UpdateTextBox() {
[9671]187      if (string.IsNullOrEmpty(Content.Value)) {
188        textBox.Enabled = false;
189        textBox.Text = string.Format("No file path is specified.");
190        return;
191      }
192
[9714]193      fileText = ReadFile(Content.Value);
194      if (fileText == null) {
[9671]195        textBox.Enabled = false;
196        textBox.Text = string.Format("The specified file \"{0}\" cannot be found.", Content.Value);
197        return;
198      }
199
200      textBox.Enabled = true;
201      textBox.Text = fileText;
202    }
[9714]203    private void textBox_Validated(object sender, EventArgs e) {
[9833]204      if (!FileContentChanged) return;
[9671]205      string msg = string.Format("You have not saved the changes in the file \"{0}\" yet. Do you want to save the changes?", Content.Value);
206      var result = MessageBox.Show(this, msg, "Save changes?", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
207      if (result == DialogResult.Yes) SaveFile();
208    }
209
210    protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
211      if (keyData == (Keys.Control | Keys.S)) {
212        SaveFile();
213        return true;
214      }
215      return base.ProcessCmdKey(ref msg, keyData);
216    }
217
[9714]218    private static string ReadFile(string path) {
[9671]219      if (!File.Exists(path)) return null;
[9714]220      string fileContent = string.Empty;
[9850]221      try {
222        using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) {
223          using (StreamReader streamReader = new StreamReader(fileStream)) {
224            fileContent = streamReader.ReadToEnd();
225          }
[9671]226        }
227      }
[9850]228      catch (Exception e) {
229        ErrorHandling.ShowErrorDialog(e);
230      }
[9671]231      return fileContent;
232    }
233
[9714]234    private static void WriteFile(string path, string fileContent) {
[9850]235      try {
236        using (FileStream fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) {
237          using (StreamWriter streamWriter = new StreamWriter(fileStream)) {
238            streamWriter.Write(fileContent);
239          }
[9671]240        }
241      }
[9850]242      catch (Exception e) {
243        ErrorHandling.ShowErrorDialog(e);
244      }
[9671]245    }
246  }
247}
Note: See TracBrowser for help on using the repository browser.