Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.PluginInfrastructure/Advanced/EditProductsView.cs @ 3627

Last change on this file since 3627 was 3627, checked in by gkronber, 14 years ago

Refactored class names and fixed a dependency-selection bug. #994 (Clean up plugin infrastructure project)

File size: 18.0 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 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.Collections.Generic;
24using System.ComponentModel;
25using System.Drawing;
26using System.Data;
27using System.Linq;
28using System.Text;
29using System.Windows.Forms;
30using System.ServiceModel;
31using HeuristicLab.PluginInfrastructure;
32
33namespace HeuristicLab.PluginInfrastructure.Advanced {
34  internal partial class EditProductsView : InstallationManagerControl {
35    private const string RefreshMessage = "Downloading product and plugin information...";
36    private const string UploadMessage = "Uploading product and plugin information...";
37    private const string DeleteProductMessage = "Deleting product...";
38
39    private BackgroundWorker refreshProductsWorker;
40    private BackgroundWorker uploadChangedProductsWorker;
41    private BackgroundWorker deleteProductWorker;
42
43    private List<DeploymentService.ProductDescription> products;
44    private List<DeploymentService.PluginDescription> plugins;
45    private HashSet<DeploymentService.ProductDescription> dirtyProducts;
46
47    public EditProductsView() {
48      InitializeComponent();
49
50      productImageList.Images.Add(HeuristicLab.PluginInfrastructure.Resources.Resources.Setup_Install);
51      productImageList.Images.Add(HeuristicLab.PluginInfrastructure.Resources.Resources.ArrowUp);
52      pluginImageList.Images.Add(HeuristicLab.PluginInfrastructure.Resources.Resources.plugin_16);
53
54      dirtyProducts = new HashSet<DeploymentService.ProductDescription>();
55      refreshProductsWorker = new BackgroundWorker();
56      refreshProductsWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(refreshProductsWorker_RunWorkerCompleted);
57      refreshProductsWorker.DoWork += new DoWorkEventHandler(refreshProductsWorker_DoWork);
58
59      uploadChangedProductsWorker = new BackgroundWorker();
60      uploadChangedProductsWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(uploadChangedProductsWorker_RunWorkerCompleted);
61      uploadChangedProductsWorker.DoWork += new DoWorkEventHandler(uploadChangedProductsWorker_DoWork);
62
63      deleteProductWorker = new BackgroundWorker();
64      deleteProductWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(deleteProductWorker_RunWorkerCompleted);
65      deleteProductWorker.DoWork += new DoWorkEventHandler(deleteProductWorker_DoWork);
66    }
67
68    #region event handlers for delete product background worker
69    void deleteProductWorker_DoWork(object sender, DoWorkEventArgs e) {
70      var products = (IEnumerable<DeploymentService.ProductDescription>)e.Argument;
71      var adminClient = DeploymentService.AdminClientFactory.CreateClient();
72      // upload
73      try {
74        foreach (var product in products) {
75          adminClient.DeleteProduct(product);
76        }
77        adminClient.Close();
78      }
79      catch (TimeoutException) {
80        adminClient.Abort();
81        throw;
82      }
83      catch (FaultException) {
84        adminClient.Abort();
85        throw;
86      }
87      catch (CommunicationException) {
88        adminClient.Abort();
89        throw;
90      }
91      // refresh     
92      var updateClient = DeploymentService.UpdateClientFactory.CreateClient();
93      try {
94        e.Result = new object[] { updateClient.GetProducts(), updateClient.GetPlugins() };
95        updateClient.Close();
96      }
97      catch (TimeoutException) {
98        updateClient.Abort();
99        throw;
100      }
101      catch (FaultException) {
102        updateClient.Abort();
103        throw;
104      }
105      catch (CommunicationException) {
106        updateClient.Abort();
107        throw;
108      }
109    }
110
111    void deleteProductWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
112      if (e.Error != null) {
113        StatusView.ShowError("Connection Error",
114        "There was an error while connecting to the server." + Environment.NewLine +
115           "Please check your connection settings and user credentials.");
116        this.products.Clear();
117        this.plugins.Clear();
118      } else {
119        this.products = new List<DeploymentService.ProductDescription>(
120  (DeploymentService.ProductDescription[])((object[])e.Result)[0]);
121        this.plugins = new List<DeploymentService.PluginDescription>(
122          (DeploymentService.PluginDescription[])((object[])e.Result)[1]);
123
124        EnableControls();
125      }
126      UpdateProductsList();
127      dirtyProducts.Clear();
128      StatusView.HideProgressIndicator();
129      StatusView.RemoveMessage(DeleteProductMessage);
130      StatusView.UnlockUI();
131    }
132    #endregion
133
134    #region event handlers for upload products background worker
135    private void uploadChangedProductsWorker_DoWork(object sender, DoWorkEventArgs e) {
136      var products = (IEnumerable<DeploymentService.ProductDescription>)e.Argument;
137      var adminClient = DeploymentService.AdminClientFactory.CreateClient();
138      // upload
139      try {
140        foreach (var product in products) {
141          adminClient.DeployProduct(product);
142        }
143        adminClient.Close();
144      }
145      catch (TimeoutException) {
146        adminClient.Abort();
147        throw;
148      }
149      catch (FaultException) {
150        adminClient.Abort();
151        throw;
152      }
153      catch (CommunicationException) {
154        adminClient.Abort();
155        throw;
156      }
157      // refresh     
158      var updateClient = DeploymentService.UpdateClientFactory.CreateClient();
159      try {
160        e.Result = new object[] { updateClient.GetProducts(), updateClient.GetPlugins() };
161        updateClient.Close();
162      }
163      catch (TimeoutException) {
164        updateClient.Abort();
165        throw;
166      }
167      catch (FaultException) {
168        updateClient.Abort();
169        throw;
170      }
171      catch (CommunicationException) {
172        updateClient.Abort();
173        throw;
174      }
175    }
176
177    private void uploadChangedProductsWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
178      if (e.Error != null) {
179        StatusView.ShowError("Connection Error",
180        "There was an error while connecting to the server." + Environment.NewLine +
181           "Please check your connection settings and user credentials.");
182        this.products.Clear();
183        this.plugins.Clear();
184      } else {
185        this.products = new List<DeploymentService.ProductDescription>(
186  (DeploymentService.ProductDescription[])((object[])e.Result)[0]);
187        this.plugins = new List<DeploymentService.PluginDescription>(
188          (DeploymentService.PluginDescription[])((object[])e.Result)[1]);
189
190      }
191      UpdateProductsList();
192      dirtyProducts.Clear();
193      EnableControls();
194      StatusView.HideProgressIndicator();
195      StatusView.RemoveMessage(UploadMessage);
196      StatusView.UnlockUI();
197    }
198    #endregion
199
200    #region event handlers for refresh products background worker
201    private void refreshProductsWorker_DoWork(object sender, DoWorkEventArgs e) {
202      var updateClient = DeploymentService.UpdateClientFactory.CreateClient();
203      try {
204        e.Result = new object[] { updateClient.GetProducts(), updateClient.GetPlugins() };
205        updateClient.Close();
206      }
207      catch (TimeoutException) {
208        updateClient.Abort();
209        throw;
210      }
211      catch (FaultException) {
212        updateClient.Abort();
213        throw;
214      }
215      catch (CommunicationException) {
216        updateClient.Abort();
217        throw;
218      }
219    }
220
221    private void refreshProductsWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
222      if (e.Error != null) {
223        StatusView.ShowError("Connection Error",
224          "There was an error while connecting to the server." + Environment.NewLine +
225                   "Please check your connection settings and user credentials.");
226        this.products.Clear();
227        this.plugins.Clear();
228
229      } else {
230        this.products = new List<DeploymentService.ProductDescription>(
231          (DeploymentService.ProductDescription[])((object[])e.Result)[0]);
232        this.plugins = new List<DeploymentService.PluginDescription>(
233          (DeploymentService.PluginDescription[])((object[])e.Result)[1]);
234      }
235      UpdateProductsList();
236      dirtyProducts.Clear();
237      EnableControls();
238      StatusView.HideProgressIndicator();
239      StatusView.RemoveMessage(RefreshMessage);
240      StatusView.UnlockUI();
241    }
242    #endregion
243
244    private void UpdateProductsList() {
245      productsListView.SelectedItems.Clear();
246      productsListView.Items.Clear();
247      foreach (var prodDesc in products) {
248        productsListView.Items.Add(CreateListViewItem(prodDesc));
249      }
250      Util.ResizeColumns(productsListView.Columns.OfType<ColumnHeader>());
251    }
252
253    private void productsListBox_SelectedIndexChanged(object sender, EventArgs e) {
254      bool productSelected = productsListView.SelectedItems.Count > 0;
255      detailsGroupBox.Enabled = productSelected;
256      UpdateProductButtons();
257      if (productSelected) {
258        DeploymentService.ProductDescription activeProduct = (DeploymentService.ProductDescription)((ListViewItem)productsListView.SelectedItems[0]).Tag;
259        nameTextBox.Text = activeProduct.Name;
260        versionTextBox.Text = activeProduct.Version.ToString();
261
262        // populate plugins list view
263        ListViewItem activeItem = (ListViewItem)productsListView.SelectedItems[0];
264        pluginListView.SuppressItemCheckedEvents = true;
265        foreach (var plugin in plugins.OfType<IPluginDescription>()) {
266          pluginListView.Items.Add(CreateListViewItem(plugin));
267        }
268        pluginListView.SuppressItemCheckedEvents = false;
269        foreach (var plugin in activeProduct.Plugins) {
270          pluginListView.CheckItems(FindItemsForPlugin(plugin));
271        }
272      } else {
273        nameTextBox.Text = string.Empty;
274        versionTextBox.Text = string.Empty;
275        pluginListView.Items.Clear();
276      }
277      Util.ResizeColumns(pluginListView.Columns.OfType<ColumnHeader>());
278    }
279
280    private void UpdateProductButtons() {
281      uploadButton.Enabled = dirtyProducts.Count > 0;
282      if (productsListView.SelectedItems.Count > 0) {
283        var selectedProduct = (DeploymentService.ProductDescription)productsListView.SelectedItems[0].Tag;
284        deleteProductButton.Enabled = !dirtyProducts.Contains(selectedProduct);
285      } else {
286        deleteProductButton.Enabled = false;
287      }
288    }
289
290
291    #region button event handlers
292    private void newProductButton_Click(object sender, EventArgs e) {
293      var newProduct = new DeploymentService.ProductDescription("New product", new Version("0.0.0.0"));
294      products.Add(newProduct);
295      UpdateProductsList();
296      MarkProductDirty(newProduct);
297    }
298
299    private void saveButton_Click(object sender, EventArgs e) {
300      StatusView.LockUI();
301      StatusView.ShowProgressIndicator();
302      StatusView.ShowMessage(UploadMessage);
303      uploadChangedProductsWorker.RunWorkerAsync(dirtyProducts);
304    }
305    private void refreshButton_Click(object sender, EventArgs e) {
306      StatusView.LockUI();
307      StatusView.ShowProgressIndicator();
308      StatusView.ShowMessage(RefreshMessage);
309      refreshProductsWorker.RunWorkerAsync();
310    }
311    private void deleteProductButton_Click(object sender, EventArgs e) {
312      StatusView.LockUI();
313      StatusView.ShowProgressIndicator();
314      StatusView.ShowMessage(DeleteProductMessage);
315      var selectedProducts = from item in productsListView.SelectedItems.OfType<ListViewItem>()
316                             select (DeploymentService.ProductDescription)item.Tag;
317      deleteProductWorker.RunWorkerAsync(selectedProducts.ToList());
318    }
319
320    #endregion
321
322    #region textbox changed event handlers
323    private void nameTextBox_TextChanged(object sender, EventArgs e) {
324      if (productsListView.SelectedItems.Count > 0) {
325        ListViewItem activeItem = (ListViewItem)productsListView.SelectedItems[0];
326        DeploymentService.ProductDescription activeProduct = (DeploymentService.ProductDescription)activeItem.Tag;
327        if (string.IsNullOrEmpty(nameTextBox.Name)) {
328          errorProvider.SetError(nameTextBox, "Invalid value");
329        } else {
330          if (activeProduct.Name != nameTextBox.Text) {
331            activeProduct.Name = nameTextBox.Text;
332            activeItem.SubItems[0].Text = activeProduct.Name;
333            errorProvider.SetError(nameTextBox, string.Empty);
334            MarkProductDirty(activeProduct);
335          }
336        }
337      }
338    }
339
340
341    private void versionTextBox_TextChanged(object sender, EventArgs e) {
342      if (productsListView.SelectedItems.Count > 0) {
343        ListViewItem activeItem = (ListViewItem)productsListView.SelectedItems[0];
344        DeploymentService.ProductDescription activeProduct = (DeploymentService.ProductDescription)activeItem.Tag;
345        try {
346          var newVersion = new Version(versionTextBox.Text);
347          if (activeProduct.Version != newVersion) {
348            activeProduct.Version = newVersion;
349            activeItem.SubItems[1].Text = versionTextBox.Text;
350            errorProvider.SetError(versionTextBox, string.Empty);
351            MarkProductDirty(activeProduct);
352          }
353        }
354        catch (OverflowException) {
355          errorProvider.SetError(versionTextBox, "Invalid value");
356        }
357
358        catch (ArgumentException) {
359          errorProvider.SetError(versionTextBox, "Invalid value");
360        }
361        catch (FormatException) {
362          errorProvider.SetError(versionTextBox, "Invalid value");
363        }
364      }
365    }
366    #endregion
367
368
369    #region plugin list view
370    private void OnItemChecked(ItemCheckedEventArgs e) {
371      ListViewItem activeItem = (ListViewItem)productsListView.SelectedItems[0];
372      DeploymentService.ProductDescription activeProduct = (DeploymentService.ProductDescription)activeItem.Tag;
373      activeProduct.Plugins = (from item in pluginListView.CheckedItems.OfType<ListViewItem>()
374                               select (DeploymentService.PluginDescription)item.Tag).ToArray();
375      MarkProductDirty(activeProduct);
376    }
377
378    private void listView_ItemChecked(object sender, ItemCheckedEventArgs e) {
379      List<IPluginDescription> modifiedPlugins = new List<IPluginDescription>();
380      if (e.Item.Checked) {
381        foreach (ListViewItem item in pluginListView.SelectedItems) {
382          var plugin = (IPluginDescription)item.Tag;
383          // also check all dependencies
384          if (!modifiedPlugins.Contains(plugin))
385            modifiedPlugins.Add(plugin);
386          foreach (var dep in Util.GetAllDependencies(plugin)) {
387            if (!modifiedPlugins.Contains(dep))
388              modifiedPlugins.Add(dep);
389          }
390        }
391        pluginListView.CheckItems(modifiedPlugins.Select(x => FindItemsForPlugin(x).Single()));
392        OnItemChecked(e);
393      } else {
394        foreach (ListViewItem item in pluginListView.SelectedItems) {
395          var plugin = (IPluginDescription)item.Tag;
396          // also uncheck all dependent plugins
397          if (!modifiedPlugins.Contains(plugin))
398            modifiedPlugins.Add(plugin);
399          foreach (var dep in Util.GetAllDependents(plugin, plugins.Cast<IPluginDescription>())) {
400            if (!modifiedPlugins.Contains(dep))
401              modifiedPlugins.Add(dep);
402          }
403
404        }
405        pluginListView.UncheckItems(modifiedPlugins.Select(x => FindItemsForPlugin(x).Single()));
406        OnItemChecked(e);
407      }
408    }
409
410
411    #endregion
412
413    #region helper
414    private void MarkProductDirty(HeuristicLab.PluginInfrastructure.Advanced.DeploymentService.ProductDescription activeProduct) {
415      if (!dirtyProducts.Contains(activeProduct)) {
416        dirtyProducts.Add(activeProduct);
417        var item = FindItemForProduct(activeProduct);
418        item.ImageIndex = 1;
419        UpdateProductButtons();
420      }
421    }
422    private ListViewItem CreateListViewItem(DeploymentService.ProductDescription productDescription) {
423      ListViewItem item = new ListViewItem(new string[] { productDescription.Name, productDescription.Version.ToString() });
424      item.Tag = productDescription;
425      item.ImageIndex = 0;
426      return item;
427    }
428
429    private ListViewItem CreateListViewItem(IPluginDescription plugin) {
430      ListViewItem item = new ListViewItem(new string[] { plugin.Name, plugin.Version.ToString(),
431          string.Empty, plugin.Description });
432      item.Tag = plugin;
433      item.ImageIndex = 0;
434      item.Checked = false;
435      return item;
436    }
437
438    private ListViewItem FindItemForProduct(HeuristicLab.PluginInfrastructure.Advanced.DeploymentService.ProductDescription activeProduct) {
439      return (from item in productsListView.Items.OfType<ListViewItem>()
440              let product = item.Tag as DeploymentService.ProductDescription
441              where product != null
442              where product == activeProduct
443              select item).Single();
444    }
445    private IEnumerable<ListViewItem> FindItemsForPlugin(IPluginDescription plugin) {
446      return from item in pluginListView.Items.OfType<ListViewItem>()
447             let p = item.Tag as IPluginDescription
448             where p.Name == plugin.Name
449             where p.Version == plugin.Version
450             select item;
451    }
452
453    private void EnableControls() {
454      newProductButton.Enabled = true;
455      productsListView.Enabled = true;
456    }
457    #endregion
458
459  }
460}
Note: See TracBrowser for help on using the repository browser.