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

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

#2077:

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