Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.PluginInfrastructure/Advanced/ProductEditor.cs @ 3612

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

Implemented change requests of reviewers. #989 (Implement review comments in plugin infrastructure)

File size: 16.7 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 ProductEditor : 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 ProductEditor() {
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        DisableControls();
117      } else {
118        this.products = new List<DeploymentService.ProductDescription>(
119  (DeploymentService.ProductDescription[])((object[])e.Result)[0]);
120        this.plugins = new List<DeploymentService.PluginDescription>(
121          (DeploymentService.PluginDescription[])((object[])e.Result)[1]);
122
123        UpdateProductsList();
124        dirtyProducts.Clear();
125        EnableControls();
126      }
127      StatusView.HideProgressIndicator();
128      StatusView.RemoveMessage(DeleteProductMessage);
129      StatusView.UnlockUI();
130    }
131    #endregion
132
133    #region event handlers for upload products background worker
134    private void uploadChangedProductsWorker_DoWork(object sender, DoWorkEventArgs e) {
135      var products = (IEnumerable<DeploymentService.ProductDescription>)e.Argument;
136      var adminClient = DeploymentService.AdminClientFactory.CreateClient();
137      // upload
138      try {
139        foreach (var product in products) {
140          adminClient.DeployProduct(product);
141        }
142        adminClient.Close();
143      }
144      catch (TimeoutException) {
145        adminClient.Abort();
146        throw;
147      }
148      catch (FaultException) {
149        adminClient.Abort();
150        throw;
151      }
152      catch (CommunicationException) {
153        adminClient.Abort();
154        throw;
155      }
156      // refresh     
157      var updateClient = DeploymentService.UpdateClientFactory.CreateClient();
158      try {
159        e.Result = new object[] { updateClient.GetProducts(), updateClient.GetPlugins() };
160        updateClient.Close();
161      }
162      catch (TimeoutException) {
163        updateClient.Abort();
164        throw;
165      }
166      catch (FaultException) {
167        updateClient.Abort();
168        throw;
169      }
170      catch (CommunicationException) {
171        updateClient.Abort();
172        throw;
173      }
174    }
175
176    private void uploadChangedProductsWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
177      if (e.Error != null) {
178        StatusView.ShowError("Connection Error",
179        "There was an error while connecting to the server." + Environment.NewLine +
180           "Please check your connection settings and user credentials.");
181        DisableControls();
182      } else {
183        this.products = new List<DeploymentService.ProductDescription>(
184  (DeploymentService.ProductDescription[])((object[])e.Result)[0]);
185        this.plugins = new List<DeploymentService.PluginDescription>(
186          (DeploymentService.PluginDescription[])((object[])e.Result)[1]);
187
188        UpdateProductsList();
189        dirtyProducts.Clear();
190        EnableControls();
191      }
192      StatusView.HideProgressIndicator();
193      StatusView.RemoveMessage(UploadMessage);
194      StatusView.UnlockUI();
195    }
196    #endregion
197
198    #region event handlers for refresh products background worker
199    private void refreshProductsWorker_DoWork(object sender, DoWorkEventArgs e) {
200      var updateClient = DeploymentService.UpdateClientFactory.CreateClient();
201      try {
202        e.Result = new object[] { updateClient.GetProducts(), updateClient.GetPlugins() };
203        updateClient.Close();
204      }
205      catch (TimeoutException) {
206        updateClient.Abort();
207        throw;
208      }
209      catch (FaultException) {
210        updateClient.Abort();
211        throw;
212      }
213      catch (CommunicationException) {
214        updateClient.Abort();
215        throw;
216      }
217    }
218
219    private void refreshProductsWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
220      if (e.Error != null) {
221        StatusView.ShowError("Connection Error",
222          "There was an error while connecting to the server." + Environment.NewLine +
223                   "Please check your connection settings and user credentials.");
224        DisableControls();
225      } else {
226        this.products = new List<DeploymentService.ProductDescription>(
227          (DeploymentService.ProductDescription[])((object[])e.Result)[0]);
228        this.plugins = new List<DeploymentService.PluginDescription>(
229          (DeploymentService.PluginDescription[])((object[])e.Result)[1]);
230
231
232        UpdateProductsList();
233        dirtyProducts.Clear();
234        EnableControls();
235      }
236      StatusView.HideProgressIndicator();
237      StatusView.RemoveMessage(RefreshMessage);
238      StatusView.UnlockUI();
239    }
240    #endregion
241
242    private void UpdateProductsList() {
243      productsListView.Items.Clear();
244      foreach (var prodDesc in products) {
245        productsListView.Items.Add(CreateListViewItem(prodDesc));
246      }
247      foreach (ColumnHeader column in productsListView.Columns)
248        if (productsListView.Items.Count > 0)
249          column.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
250        else column.AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize);
251    }
252
253    private void productsListBox_SelectedIndexChanged(object sender, EventArgs e) {
254      bool productSelected = productsListView.SelectedItems.Count > 0;
255      detailsGroupBox.Enabled = productSelected;
256      deleteProductButton.Enabled = productSelected;
257      uploadButton.Enabled = dirtyProducts.Count > 0;
258      if (productSelected) {
259        DeploymentService.ProductDescription activeProduct = (DeploymentService.ProductDescription)((ListViewItem)productsListView.SelectedItems[0]).Tag;
260        nameTextBox.Text = activeProduct.Name;
261        versionTextBox.Text = activeProduct.Version.ToString();
262
263        // populate plugins list view
264        ListViewItem activeItem = (ListViewItem)productsListView.SelectedItems[0];
265        foreach (var plugin in plugins.OfType<IPluginDescription>()) {
266          pluginListView.Items.Add(CreateListViewItem(plugin));
267        }
268
269        pluginListView.CheckItems(from plugin in activeProduct.Plugins
270                                  let item = FindItemForPlugin(plugin)
271                                  where item != null
272                                  select item);
273
274      } else {
275        nameTextBox.Text = string.Empty;
276        versionTextBox.Text = string.Empty;
277        pluginListView.Items.Clear();
278      }
279    }
280
281
282    #region button event handlers
283    private void newProductButton_Click(object sender, EventArgs e) {
284      var newProduct = new DeploymentService.ProductDescription("New product", new Version("0.0.0.0"));
285      ListViewItem item = CreateListViewItem(newProduct);
286      productsListView.Items.Add(item);
287      MarkProductDirty(newProduct);
288    }
289
290    private void saveButton_Click(object sender, EventArgs e) {
291      StatusView.LockUI();
292      StatusView.ShowProgressIndicator();
293      StatusView.ShowMessage(UploadMessage);
294      uploadChangedProductsWorker.RunWorkerAsync(dirtyProducts);
295    }
296    private void refreshButton_Click(object sender, EventArgs e) {
297      StatusView.LockUI();
298      StatusView.ShowProgressIndicator();
299      StatusView.ShowMessage(RefreshMessage);
300      refreshProductsWorker.RunWorkerAsync();
301    }
302    private void deleteProductButton_Click(object sender, EventArgs e) {
303      StatusView.LockUI();
304      StatusView.ShowProgressIndicator();
305      StatusView.ShowMessage(DeleteProductMessage);
306      var selectedProducts = from item in productsListView.SelectedItems.OfType<ListViewItem>()
307                             select (DeploymentService.ProductDescription)item.Tag;
308      deleteProductWorker.RunWorkerAsync(selectedProducts.ToList());
309    }
310
311    #endregion
312
313    #region textbox changed event handlers
314    private void nameTextBox_TextChanged(object sender, EventArgs e) {
315      if (productsListView.SelectedItems.Count > 0) {
316        ListViewItem activeItem = (ListViewItem)productsListView.SelectedItems[0];
317        DeploymentService.ProductDescription activeProduct = (DeploymentService.ProductDescription)activeItem.Tag;
318        if (string.IsNullOrEmpty(nameTextBox.Name)) {
319          errorProvider.SetError(nameTextBox, "Invalid value");
320        } else {
321          if (activeProduct.Name != nameTextBox.Text) {
322            activeProduct.Name = nameTextBox.Text;
323            activeItem.SubItems[0].Text = activeProduct.Name;
324            errorProvider.SetError(nameTextBox, string.Empty);
325            MarkProductDirty(activeProduct);
326          }
327        }
328      }
329    }
330
331
332    private void versionTextBox_TextChanged(object sender, EventArgs e) {
333      if (productsListView.SelectedItems.Count > 0) {
334        ListViewItem activeItem = (ListViewItem)productsListView.SelectedItems[0];
335        DeploymentService.ProductDescription activeProduct = (DeploymentService.ProductDescription)activeItem.Tag;
336        try {
337          var newVersion = new Version(versionTextBox.Text);
338          if (activeProduct.Version != newVersion) {
339            activeProduct.Version = newVersion;
340            activeItem.SubItems[1].Text = versionTextBox.Text;
341            errorProvider.SetError(versionTextBox, string.Empty);
342            MarkProductDirty(activeProduct);
343          }
344        }
345        catch (OverflowException) {
346          errorProvider.SetError(versionTextBox, "Invalid value");
347        }
348
349        catch (ArgumentException) {
350          errorProvider.SetError(versionTextBox, "Invalid value");
351        }
352        catch (FormatException) {
353          errorProvider.SetError(versionTextBox, "Invalid value");
354        }
355      }
356    }
357    #endregion
358
359
360    #region plugin list view
361    private void pluginListView_ItemChecked(object sender, ItemCheckedEventArgs e) {
362      ListViewItem activeItem = (ListViewItem)productsListView.SelectedItems[0];
363      DeploymentService.ProductDescription activeProduct = (DeploymentService.ProductDescription)activeItem.Tag;
364      activeProduct.Plugins = (from item in pluginListView.CheckedItems.OfType<ListViewItem>()
365                               select (DeploymentService.PluginDescription)item.Tag).ToArray();
366      MarkProductDirty(activeProduct);
367    }
368    #endregion
369
370    #region helper
371    private void MarkProductDirty(HeuristicLab.PluginInfrastructure.Advanced.DeploymentService.ProductDescription activeProduct) {
372      if (!dirtyProducts.Contains(activeProduct)) {
373        dirtyProducts.Add(activeProduct);
374        var item = FindItemForProduct(activeProduct);
375        item.ImageIndex = 1;
376      }
377    }
378    private ListViewItem CreateListViewItem(DeploymentService.ProductDescription productDescription) {
379      ListViewItem item = new ListViewItem(new string[] { productDescription.Name, productDescription.Version.ToString() });
380      item.Tag = productDescription;
381      item.ImageIndex = 0;
382      return item;
383    }
384
385    private ListViewItem CreateListViewItem(IPluginDescription plugin) {
386      ListViewItem item = new ListViewItem(new string[] { plugin.Name, plugin.Version.ToString(),
387          string.Empty, plugin.Description });
388      item.Tag = plugin;
389      item.ImageIndex = 0;
390      item.Checked = false;
391      return item;
392    }
393
394    private ListViewItem FindItemForProduct(HeuristicLab.PluginInfrastructure.Advanced.DeploymentService.ProductDescription activeProduct) {
395      return (from item in productsListView.Items.OfType<ListViewItem>()
396              let product = item.Tag as DeploymentService.ProductDescription
397              where product != null
398              where product == activeProduct
399              select item).Single();
400    }
401
402    private ListViewItem FindItemForPlugin(IPluginDescription plugin) {
403      return (from i in pluginListView.Items.Cast<ListViewItem>()
404              let p = i.Tag as IPluginDescription
405              where p != null
406              where p.Name == plugin.Name
407              where p.Version == plugin.Version
408              select i).SingleOrDefault();
409    }
410
411    private void DisableControls() {
412      newProductButton.Enabled = false;
413      productsListView.Enabled = false;
414      detailsGroupBox.Enabled = false;
415      deleteProductButton.Enabled = false;
416      nameTextBox.Text = string.Empty;
417      versionTextBox.Text = string.Empty;
418      pluginListView.Items.Clear();
419    }
420    private void EnableControls() {
421      newProductButton.Enabled = true;
422      productsListView.Enabled = true;
423    }
424    #endregion
425
426  }
427}
Note: See TracBrowser for help on using the repository browser.