using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Linq; using System.Windows.Forms; using HeuristicLab.Optimization.Views; using HeuristicLab.Core.Views; using HeuristicLab.MainForm; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.PluginInfrastructure; using HeuristicLab.Optimization; using HeuristicLab.Common.Resources; using System.Collections.Specialized; using System.Threading; using HeuristicLab.BackgroundProcessing; using HeuristicLab.Collections; namespace HeuristicLab.OKB.AlgorithmHost { [View("OKB Algorithm Host View")] [Content(typeof(AlgorithmHost), true)] public partial class AlgorithmHostView : NamedItemView { protected WorkerMonitor workerMonitor; public new AlgorithmHost Content { get { return (AlgorithmHost)base.Content; } set { base.Content = value; } } public AlgorithmHostView() { InitializeComponent(); workerMonitor = new WorkerMonitor(); workerMonitor.BackgroundWorkerException += new ThreadExceptionEventHandler(workerMonitor_BackgroundWorkerException); workerMonitor.CollectionChanged += new NotifyCollectionChangedEventHandler(workerMonitor_CollectionChanged); } void workerMonitor_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { if (InvokeRequired) { Invoke(new NotifyCollectionChangedEventHandler(workerMonitor_CollectionChanged), sender, e); } else { switch (e.Action) { case NotifyCollectionChangedAction.Add: string name = ((ObservableBackgroundWorker)e.NewItems[0]).Name; statusStrip.Items.Add(new ToolStripStatusLabel(name) { Name = name, BorderSides = ToolStripStatusLabelBorderSides.Left, BorderStyle = Border3DStyle.Etched, }); break; case NotifyCollectionChangedAction.Remove: statusStrip.Items.RemoveByKey(((ObservableBackgroundWorker)e.OldItems[0]).Name); break; } progressBar.Visible = statusStrip.Items.Count > 0; if (statusStrip.Items.Count > 0) { okbTabPage.Text = "OKB*"; } else { okbTabPage.Text = "OKB"; } } } void workerMonitor_BackgroundWorkerException(object sender, ThreadExceptionEventArgs e) { if (InvokeRequired) { Invoke(new ThreadExceptionEventHandler(workerMonitor_BackgroundWorkerException), sender, e); } else { ErrorHandling.ShowErrorDialog(this, "Uncaught asynchronous exception", e.Exception); } } protected override void OnInitialized(EventArgs e) { // Set order of tab pages according to z order. // NOTE: This is required due to a bug in the VS designer. List tabPages = new List(); for (int i = 0; i < tabControl.Controls.Count; i++) { tabPages.Add(tabControl.Controls[i]); } tabControl.Controls.Clear(); foreach (Control control in tabPages) tabControl.Controls.Add(control); runsView.ItemsListView.SelectedIndexChanged += new EventHandler(ItemsListView_SelectedIndexChanged); base.OnInitialized(e); } void ItemsListView_SelectedIndexChanged(object sender, EventArgs e) { submitButton.Enabled = runsView.ItemsListView.SelectedIndices.Count > 0; } protected override void DeregisterContentEvents() { Content.ExceptionOccurred -= new EventHandler>(Content_ExceptionOccurred); Content.ExecutionStateChanged -= new EventHandler(Content_ExecutionStateChanged); Content.ExecutionTimeChanged -= new EventHandler(Content_ExecutionTimeChanged); Content.Prepared -= Content_Prepared; Content.AlgorithmChanged -= Content_AlgorithmChanged; Content.ProblemChanged -= Content_ProblemChanged; Content.Runs.ItemsAdded -= Runs_ItemsAdded; base.DeregisterContentEvents(); } protected override void RegisterContentEvents() { base.RegisterContentEvents(); Content.ExceptionOccurred += new EventHandler>(Content_ExceptionOccurred); Content.ExecutionStateChanged += new EventHandler(Content_ExecutionStateChanged); Content.ExecutionTimeChanged += new EventHandler(Content_ExecutionTimeChanged); Content.Prepared += Content_Prepared; Content.AlgorithmChanged += Content_AlgorithmChanged; Content.ProblemChanged += Content_ProblemChanged; Content.Runs.ItemsAdded += Runs_ItemsAdded; } void Runs_ItemsAdded(object sender, CollectionItemsChangedEventArgs e) { if (InvokeRequired) { Invoke(new CollectionItemsChangedEventHandler(Runs_ItemsAdded), sender, e); } else { if (autoSubmitCheckBox.Checked) { foreach (IRun run in e.Items) { SubmitRun(run, true); } } } } void Content_ProblemChanged(object sender, EventArgs e) { if (InvokeRequired) Invoke(new EventHandler(Content_ProblemChanged), sender, e); else { problemParameterCollectionView.Content = Content.ProblemParameters; SetEnableStateOfControls(); if (!Content.HasOKBProblem) MessageBox.Show(ParentForm, "Non-OKB problem selected: You will not be able to submit results with non-OKB problems", "Non-OKB Problem Selected.", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } void Content_AlgorithmChanged(object sender, EventArgs e) { if (InvokeRequired) Invoke(new EventHandler(Content_AlgorithmChanged), sender, e); else { algorithmParameterCollectionView.Content = Content.Algorithm.Parameters; resultsView.Content = Content.Algorithm.Results.AsReadOnly(); SetEnableStateOfControls(); } } protected override void OnContentChanged() { base.OnContentChanged(); if (Content == null) { algorithmParameterCollectionView.Content = null; problemParameterCollectionView.Content = null; resultsView.Content = null; runsView.Content = null; executionTimeTextBox.Text = "-"; } else { algorithmParameterCollectionView.Content = Content.Parameters; problemParameterCollectionView.Content = Content.ProblemParameters; runsView.Content = Content.Runs; executionTimeTextBox.Text = Content.ExecutionTime.ToString(); if (Content.StarterKit == null) DownloadStarterKit(); } SetEnableStateOfControls(); } private void DownloadStarterKit() { BackgroundWorker loader = new ObservableBackgroundWorker("Connecting...", workerMonitor); loader.DoWork += (s, a) => { var starterKit = Content.DownloadStarerKit(); Content.StarterKit = starterKit; }; connectButton.Enabled = false; SetEnableStateOfControls(); loader.RunWorkerCompleted += (s, a) => { connectButton.Enabled = true; SetEnableStateOfControls(); }; loader.RunWorkerAsync(); } protected override void OnReadOnlyChanged() { base.OnReadOnlyChanged(); SetEnableStateOfControls(); } private void SetEnableStateOfControls() { openAlgorithmButton.Enabled = Content != null && Content.StarterKit != null; openProblemButton.Enabled = Content != null && Content.StarterKit != null; algorithmParameterCollectionView.Enabled = Content != null && Content.Algorithm != null; problemParameterCollectionView.Enabled = Content != null && Content.Problem != null; resultsView.Enabled = Content != null; runsView.Enabled = Content != null; executionTimeTextBox.Enabled = Content != null; viewAlgorithmButton.Enabled = Content != null && Content.Algorithm != null; viewProblemButton.Enabled = Content != null && Content.Problem != null; SetEnabledStateOfExecutableButtons(); } protected override void OnClosed(FormClosedEventArgs e) { if ((Content != null) && (Content.ExecutionState == ExecutionState.Started)) Content.Stop(); base.OnClosed(e); } #region Content Events protected virtual void Content_Prepared(object sender, EventArgs e) { if (InvokeRequired) Invoke(new EventHandler(Content_Prepared), sender, e); else resultsView.Content = Content.Results.AsReadOnly(); } protected virtual void Content_ExecutionStateChanged(object sender, EventArgs e) { if (InvokeRequired) Invoke(new EventHandler(Content_ExecutionStateChanged), sender, e); else { ReadOnly = Content.ExecutionState == ExecutionState.Started; Locked = Content.ExecutionState == ExecutionState.Started; SetEnabledStateOfExecutableButtons(); } } protected virtual void Content_ExecutionTimeChanged(object sender, EventArgs e) { if (InvokeRequired) Invoke(new EventHandler(Content_ExecutionTimeChanged), sender, e); else executionTimeTextBox.Text = Content.ExecutionTime.ToString(); } protected virtual void Content_ExceptionOccurred(object sender, EventArgs e) { if (InvokeRequired) Invoke(new EventHandler>(Content_ExceptionOccurred), sender, e); else ErrorHandling.ShowErrorDialog(this, e.Value); } #endregion #region Control Events protected virtual void openAlgorithmButton_Click(object sender, EventArgs e) { SelectItemDialog d = new SelectItemDialog(); foreach (var ac in Content.StarterKit.AlgorithmClasses) { foreach (var a in ac.Algorithms) { d.AddItem(a.Name, a.Description, ac.Name, a, VS2008ImageLibrary.ExecutableStopped); } } if (d.ShowDialog(ParentForm) == DialogResult.OK) { var loader = new ObservableBackgroundWorker("loading algorithm...", workerMonitor); loader.DoWork += (s, a) => { Content.OKBAlgorithm = d.Item as OKBRunner.Algorithm; }; loader.RunWorkerAsync(); } } protected virtual void openProblemButton_Click(object sender, EventArgs e) { SelectItemDialog d = new SelectItemDialog(); foreach (var pc in Content.StarterKit.ProblemClasses) { foreach (var p in pc.Problems) { d.AddItem(p.Name, p.Description, pc.Name, p, VS2008ImageLibrary.Type); } } if (d.ShowDialog(ParentForm) == DialogResult.OK) { var loader = new ObservableBackgroundWorker("loading problem...", workerMonitor); loader.DoWork += (s, a) => { Content.OKBProblem = d.Item as OKBRunner.Problem; }; loader.RunWorkerAsync(); } } protected virtual void startButton_Click(object sender, EventArgs e) { Content.Start(); } protected virtual void pauseButton_Click(object sender, EventArgs e) { Content.Pause(); } protected virtual void stopButton_Click(object sender, EventArgs e) { Content.Stop(); } protected virtual void resetButton_Click(object sender, EventArgs e) { Content.Prepare(false); } protected virtual void connectButton_Click(object sender, EventArgs e) { DownloadStarterKit(); } #endregion #region Helpers private void SetEnabledStateOfExecutableButtons() { if (Content == null) { startButton.Enabled = pauseButton.Enabled = stopButton.Enabled = resetButton.Enabled = false; } else { startButton.Enabled = (Content.ExecutionState == ExecutionState.Prepared) || (Content.ExecutionState == ExecutionState.Paused); pauseButton.Enabled = Content.ExecutionState == ExecutionState.Started; stopButton.Enabled = (Content.ExecutionState == ExecutionState.Started) || (Content.ExecutionState == ExecutionState.Paused); resetButton.Enabled = Content.ExecutionState != ExecutionState.Started; } } #endregion private void submitButton_Click(object sender, EventArgs e) { foreach (ListViewItem item in runsView.ItemsListView.SelectedItems) { SubmitRun(item.Tag as IRun, false); } } private void SubmitRun(IRun run, bool skipConfirmation) { if (run == null) { MessageBox.Show(this, "selected item is not an IRun :`("); } else { var worker = new ObservableBackgroundWorker("Preparing submission: " + run.Name, workerMonitor); OKBRunner.ExperimentKit experimentKit = null; worker.DoWork += (s, a) => { experimentKit = Content.PrepareSubmission(run); }; worker.RunWorkerCompleted += (s, a) => { if (experimentKit == null) return; if (skipConfirmation || ConfirmSubmission(experimentKit)) { var submitter = new ObservableBackgroundWorker("Submitting Run: " + run.Name, workerMonitor); submitter.DoWork += (s1, a1) => { Content.SubmitRun(experimentKit); }; submitter.RunWorkerAsync(); } }; worker.RunWorkerAsync(); } } private bool ConfirmSubmission(OKBRunner.ExperimentKit experimentKit) { return MessageBox.Show(this, AlgorithmHost.FormatSubmission(experimentKit), "Submit Run?", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK; } private void viewAlgorithmButton_Click(object sender, EventArgs e) { if (Content.Algorithm == null) return; IContentView view = FindFirstView(Content.Algorithm); if (view == null && MessageBox.Show(ParentForm, @"The defintion of this algorithm has been fixed inside the OKB and should not be changed in a way that changes its behaviour Please be careful with modifications!", "Algorithm assumed fixed!", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation) == DialogResult.OK) view = MainFormManager.CreateDefaultView(Content.Algorithm.GetType()); if (view != null) { view.Content = Content.Algorithm; view.Show(); } } private void viewProblemButton_Click(object sender, EventArgs e) { if (Content.Problem == null) return; IContentView view = FindFirstView(Content.Problem); if (view == null && MessageBox.Show(ParentForm, @"The defintion of this problem has been fixed inside the OKB and should not be changed in a way that changes its behaviour. Please be careful with modifications!", "Problem assumed fixed!", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation) == DialogResult.OK) view = MainFormManager.CreateDefaultView(Content.Problem.GetType()); if (view != null) { view.Content = Content.Problem; view.Show(); } } private static IContentView FindFirstView(IContent content) { return MainFormManager.MainForm.Views .Where(v => v is IContentView) .Cast() .Where(v => v.Content == content) .FirstOrDefault(); } } }