source: trunk/sources/HeuristicLab.Scripting.Views/3.3/ScriptView.cs @ 11807

Last change on this file since 11807 was 11807, checked in by jkarder, 7 years ago

#2077: merged r11700:11806 back to trunk

File size: 8.6 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2014 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
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.CodeDom.Compiler;
24using System.Collections.Generic;
25using System.Drawing;
26using System.Globalization;
27using System.Linq;
28using System.Reflection;
29using System.Windows.Forms;
30using HeuristicLab.Common;
31using HeuristicLab.Common.Resources;
32using HeuristicLab.Core.Views;
33using HeuristicLab.MainForm;
34
35namespace HeuristicLab.Scripting.Views {
36
37  [View("Script View")]
38  [Content(typeof(Script), true)]
39  public partial class ScriptView : NamedItemView {
40    private const string AssembliesLoadingMessage = "Loading Assemblies";
41    private const string AssembliesUnloadingMessage = "Unloading Assemblies";
42    private const int SilentAssemblyLoadingOperationLimit = 10;
43
44    #region Properties
45    public new Script Content {
46      get { return (Script)base.Content; }
47      set { base.Content = value; }
48    }
49
50    public override bool ReadOnly {
51      get { return codeEditor.ReadOnly || base.ReadOnly; }
52      set { base.ReadOnly = codeEditor.ReadOnly = value; }
53    }
54
55    public override bool Locked {
56      get { return codeEditor.ReadOnly || base.Locked; }
57      set { base.Locked = codeEditor.ReadOnly = value; }
58    }
59    #endregion
60
61    public ScriptView() {
62      InitializeComponent();
63      errorListView.SmallImageList.Images.AddRange(new Image[] { VSImageLibrary.Warning, VSImageLibrary.Error });
64    }
65
66    protected override void RegisterContentEvents() {
67      base.RegisterContentEvents();
68      Content.CodeChanged += Content_CodeChanged;
69    }
70
71    protected override void DeregisterContentEvents() {
72      Content.CodeChanged -= Content_CodeChanged;
73      base.DeregisterContentEvents();
74    }
75
76    #region Overrides
77    protected override void OnContentChanged() {
78      base.OnContentChanged();
79      if (Content == null) {
80        codeEditor.UserCode = string.Empty;
81      } else {
82        codeEditor.UserCode = Content.Code;
83        codeEditor.AddAssembliesAsync(Content.GetAssemblies());
84        if (Content.CompileErrors == null) {
85          compilationLabel.ForeColor = SystemColors.ControlDarkDark;
86          compilationLabel.Text = "Not compiled";
87        } else if (Content.CompileErrors.HasErrors) {
88          compilationLabel.ForeColor = Color.DarkRed;
89          compilationLabel.Text = "Compilation failed";
90        } else {
91          compilationLabel.ForeColor = Color.DarkGreen;
92          compilationLabel.Text = "Compilation successful";
93        }
94      }
95    }
96
97    protected override void SetEnabledStateOfControls() {
98      base.SetEnabledStateOfControls();
99      compileButton.Enabled = Content != null && !Locked && !ReadOnly;
100      codeEditor.Enabled = Content != null;
101    }
102
103    protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
104      switch (keyData) {
105        case Keys.F6:
106          if (Content != null && !Locked)
107            Compile();
108          return true;
109      }
110      return base.ProcessCmdKey(ref msg, keyData);
111    }
112    #endregion
113
114    public virtual bool Compile() {
115      ReadOnly = true;
116      Locked = true;
117      errorListView.Items.Clear();
118      outputTextBox.Text = "Compiling ... ";
119      try {
120        Content.Compile();
121        outputTextBox.AppendText("Compilation succeeded.");
122        return true;
123      } catch (InvalidOperationException) {
124        if (Content.CompileErrors.HasErrors) {
125          outputTextBox.AppendText("Compilation failed.");
126          return false;
127        } else {
128          outputTextBox.AppendText("Compilation succeeded.");
129          return true;
130        }
131      } finally {
132        ShowCompilationResults();
133        if (Content.CompileErrors.Count > 0)
134          infoTabControl.SelectedTab = errorListTabPage;
135        ReadOnly = false;
136        Locked = false;
137        codeEditor.Focus();
138      }
139    }
140
141    #region Helpers
142    protected virtual void ShowCompilationResults() {
143      if (Content.CompileErrors.Count == 0) return;
144
145      var messages = Content.CompileErrors.OfType<CompilerError>()
146                                      .OrderBy(x => x.IsWarning)
147                                      .ThenBy(x => x.Line)
148                                      .ThenBy(x => x.Column);
149
150      foreach (var m in messages) {
151        var item = new ListViewItem { Tag = m };
152        item.SubItems.AddRange(new[] {
153          m.IsWarning ? "Warning" : "Error",
154          m.ErrorNumber,
155          m.Line.ToString(CultureInfo.InvariantCulture),
156          m.Column.ToString(CultureInfo.InvariantCulture),
157          m.ErrorText
158        });
159        item.ImageIndex = m.IsWarning ? 0 : 1;
160        errorListView.Items.Add(item);
161      }
162
163      codeEditor.ShowCompileErrors(Content.CompileErrors);
164
165      AdjustErrorListViewColumnSizes();
166    }
167
168    protected virtual void AdjustErrorListViewColumnSizes() {
169      foreach (ColumnHeader ch in errorListView.Columns)
170        // adjusts the column width to the width of the column header
171        ch.Width = -2;
172    }
173
174    #region ProgressView
175    private bool progressViewCreated;
176
177    private void AddProgressView(string progressMessage) {
178      var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
179      mainForm.AddOperationProgressToView(this, progressMessage);
180      progressViewCreated = true;
181    }
182
183    private void RemoveProgressView() {
184      if (!progressViewCreated) return;
185      var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
186      mainForm.RemoveOperationProgressFromView(this);
187      progressViewCreated = false;
188    }
189    #endregion
190    #endregion
191
192    #region Event Handlers
193    private void Content_CodeChanged(object sender, EventArgs e) {
194      if (InvokeRequired) Invoke((Action<object, EventArgs>)Content_CodeChanged, sender, e);
195      else {
196        codeEditor.UserCode = Content.Code;
197      }
198    }
199
200    private void compileButton_Click(object sender, EventArgs e) {
201      Compile();
202    }
203
204    private void codeEditor_TextEditorTextChanged(object sender, EventArgs e) {
205      if (Content == null) return;
206      Content.Code = codeEditor.UserCode;
207    }
208
209    private void errorListView_MouseDoubleClick(object sender, MouseEventArgs e) {
210      if (e.Button == MouseButtons.Left) {
211        var item = errorListView.SelectedItems[0];
212        var message = (CompilerError)item.Tag;
213        codeEditor.ScrollToPosition(message.Line, message.Column);
214        codeEditor.Focus();
215      }
216    }
217    #endregion
218
219    private void codeEditor_AssembliesLoading(object sender, EventArgs<IEnumerable<Assembly>> e) {
220      if (InvokeRequired) Invoke((Action<object, EventArgs<IEnumerable<Assembly>>>)codeEditor_AssembliesLoading, sender, e);
221      else {
222        int nrOfAssemblies = e.Value.Count();
223        if (nrOfAssemblies > SilentAssemblyLoadingOperationLimit)
224          AddProgressView(AssembliesLoadingMessage);
225      }
226    }
227
228    private void codeEditor_AssembliesLoaded(object sender, EventArgs<IEnumerable<Assembly>> e) {
229      if (InvokeRequired) Invoke((Action<object, EventArgs<IEnumerable<Assembly>>>)codeEditor_AssembliesLoaded, sender, e);
230      else {
231        RemoveProgressView();
232      }
233    }
234
235    private void codeEditor_AssembliesUnloading(object sender, EventArgs<IEnumerable<Assembly>> e) {
236      if (InvokeRequired) Invoke((Action<object, EventArgs<IEnumerable<Assembly>>>)codeEditor_AssembliesUnloading, sender, e);
237      else {
238        int nrOfAssemblies = e.Value.Count();
239        if (nrOfAssemblies > SilentAssemblyLoadingOperationLimit)
240          AddProgressView(AssembliesUnloadingMessage);
241      }
242    }
243
244    private void codeEditor_AssembliesUnloaded(object sender, EventArgs<IEnumerable<Assembly>> e) {
245      if (InvokeRequired) Invoke((Action<object, EventArgs<IEnumerable<Assembly>>>)codeEditor_AssembliesUnloaded, sender, e);
246      else {
247        RemoveProgressView();
248      }
249    }
250  }
251}
Note: See TracBrowser for help on using the repository browser.