Free cookie consent management tool by TermsFeed Policy Generator

source: branches/EnhancedProgress/HeuristicLab.MainForm.WindowsForms/3.3/Controls/ProgressView.cs @ 15415

Last change on this file since 15415 was 15415, checked in by pfleck, 7 years ago

#2845

  • Fixed/Added Progress Cancellation/Stopping
  • Added Visible property to progress and ProgressBarMode.
File size: 8.4 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2016 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.Runtime.InteropServices;
24using System.Windows.Forms;
25
26namespace HeuristicLab.MainForm.WindowsForms {
27  internal sealed partial class ProgressView : UserControl {
28    private const int defaultControlHeight = 88;
29    private const int collapsedControlHeight = 55;
30
31    private readonly Control control;
32    public Control Control {
33      get { return control; }
34    }
35
36    private readonly IProgress content;
37    public IProgress Content {
38      get { return content; }
39    }
40
41    public ProgressView(Control control, IProgress content)
42      : base() {
43      if (control == null) throw new ArgumentNullException("control");
44      if (content == null) throw new ArgumentNullException("content");
45      InitializeComponent();
46
47      this.control = control;
48      this.content = content;
49
50      UpdateButtonsState();
51      if (content.Visible) ShowProgress();
52      RegisterContentEvents();
53    }
54
55    /// <summary>
56    /// Clean up any resources being used.
57    /// </summary>
58    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
59    protected override void Dispose(bool disposing) {
60      DeregisterContentEvents();
61      HideProgress();
62
63      if (disposing && (components != null)) {
64        components.Dispose();
65      }
66      base.Dispose(disposing);
67    }
68
69    private void RegisterContentEvents() {
70      content.ProgressStateChanged += new EventHandler(Content_ProgressStateChanged);
71      content.MessageChanged += new EventHandler(Content_MessageChanged);
72      content.ProgressBarModeChanged += new EventHandler(Content_ProgressBarModeChanged);
73      content.ProgressValueChanged += new EventHandler(Content_ProgressValueChanged);
74      content.VisibleChanged += new EventHandler(Content_VisibleChanged);
75      content.CanBeStoppedChanged += new EventHandler(Content_CanBeStoppedChanged);
76      content.CanBeCanceledChanged += new EventHandler(Content_CanBeCanceledChanged);
77    }
78    private void DeregisterContentEvents() {
79      content.ProgressStateChanged -= new EventHandler(Content_ProgressStateChanged);
80      content.MessageChanged -= new EventHandler(Content_MessageChanged);
81      content.ProgressBarModeChanged -= new EventHandler(Content_ProgressBarModeChanged);
82      content.ProgressValueChanged -= new EventHandler(Content_ProgressValueChanged);
83      content.VisibleChanged -= new EventHandler(Content_VisibleChanged);
84      content.CanBeStoppedChanged -= new EventHandler(Content_CanBeStoppedChanged);
85      content.CanBeCanceledChanged -= new EventHandler(Content_CanBeCanceledChanged);
86    }
87
88    private void Content_ProgressStateChanged(object sender, EventArgs e) {
89      UpdateProgressState();
90      UpdateButtonsState();
91    }
92
93    private void Content_MessageChanged(object sender, EventArgs e) {
94      UpdateProgressMessage();
95    }
96
97    private void Content_ProgressBarModeChanged(object sender, EventArgs e) {
98      UpdateProgressValue();
99    }
100    private void Content_ProgressValueChanged(object sender, EventArgs e) {
101      UpdateProgressValue();
102    }
103
104    private void Content_VisibleChanged(object sender, EventArgs e) {
105      if (content.Visible)
106        ShowProgress();
107      else
108        HideProgress();
109    }
110
111    private void Content_CanBeStoppedChanged(object sender, EventArgs e) {
112      UpdateButtonsState();
113    }
114    private void Content_CanBeCanceledChanged(object sender, EventArgs e) {
115      UpdateButtonsState();
116    }
117
118    private void ShowProgress() {
119      if (control.InvokeRequired) {
120        control.Invoke((Action)ShowProgress);
121        return;
122      }
123
124      int height = (content.CanBeStopped || content.CanBeCanceled) ? Height : collapsedControlHeight;
125
126      Left = (control.ClientRectangle.Width / 2) - (Width / 2);
127      Top = (control.ClientRectangle.Height / 2) - (height / 2);
128      Anchor = AnchorStyles.None;
129
130      control.Enabled = false;
131      Parent = control.Parent;
132      BringToFront();
133
134      UpdateProgressValue();
135      UpdateProgressMessage();
136      UpdateButtonsState();
137      Visible = true;
138    }
139
140    private void HideProgress() {
141      if (control.InvokeRequired) {
142        control.Invoke((Action)HideProgress);
143        return;
144      }
145
146      control.Enabled = true;
147      Parent = null;
148      Visible = false;
149    }
150
151    private void UpdateProgressState() {
152      if (control.InvokeRequired) {
153        control.Invoke((Action)UpdateProgressState);
154        return;
155      }
156
157      switch (content.ProgressState) {
158        case ProgressState.Started:
159          progressBar.SetState(ProgressBarState.Normal);
160          break;
161        case ProgressState.Finished:
162          HideProgress();
163          progressBar.SetState(ProgressBarState.Normal);
164          break;
165        case ProgressState.Stopped:
166          progressBar.SetState(ProgressBarState.Warning);
167          break;
168        case ProgressState.Canceled:
169          progressBar.SetState(ProgressBarState.Error);
170          break;
171        default: throw new NotSupportedException("The progress state " + content.ProgressState + " is not supported by the ProgressView.");
172      }
173    }
174
175    private void UpdateProgressMessage() {
176      if (control.InvokeRequired) {
177        control.Invoke((Action)UpdateProgressMessage);
178        return;
179      }
180
181      messageLabel.Text = content.Message;
182    }
183
184
185    private void UpdateProgressValue() {
186      // prevent problems with object disposal and invoke as suggested by http://stackoverflow.com/a/18647091
187      if (!IsHandleCreated) return;
188      if (InvokeRequired) {
189        try {
190          Invoke((Action)UpdateProgressValue);
191        } catch (InvalidOperationException) {
192          // swallow ObjectDisposedException
193          // which might occur if the invoke call is executed after or while the control is disposing
194        }
195        return;
196      }
197
198      if (content.ProgressBarMode == ProgressBarMode.Continuous) {
199        progressBar.Style = ProgressBarStyle.Continuous;
200        progressBar.Value = (int)Math.Round(progressBar.Minimum + content.ProgressValue * (progressBar.Maximum - progressBar.Minimum));
201      } else {
202        progressBar.Style = ProgressBarStyle.Marquee;
203      }
204    }
205
206    private void UpdateButtonsState() {
207      if (control.InvokeRequired) {
208        control.Invoke((Action)UpdateButtonsState);
209        return;
210      }
211
212      stopButton.Visible = content.CanBeStopped;
213      stopButton.Enabled = content.ProgressState == ProgressState.Started && content.CanBeStopped;
214
215      cancelButton.Visible = content.CanBeCanceled;
216      cancelButton.Enabled = content.ProgressState == ProgressState.Started && content.CanBeCanceled;
217
218      if (content.CanBeStopped || content.CanBeCanceled) {
219        Height = defaultControlHeight;
220      } else {
221        Height = collapsedControlHeight;
222      }
223    }
224
225    private void stopButton_Click(object sender, EventArgs e) {
226      content.Stop();
227    }
228    private void cancelButton_Click(object sender, EventArgs e) {
229      content.Cancel();
230    }
231  }
232
233  // https://stackoverflow.com/a/9753302
234  internal enum ProgressBarState {
235    Normal = 1, Error = 2, Warning = 3
236  }
237  internal static class ProgressBarStateExtension {
238    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
239    private static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr w, IntPtr l);
240    public static void SetState(this ProgressBar pBar, ProgressBarState state) {
241      SendMessage(pBar.Handle, 1040, (IntPtr)state, IntPtr.Zero);
242    }
243  }
244}
Note: See TracBrowser for help on using the repository browser.