Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.cs @ 7910

Last change on this file since 7910 was 7910, checked in by jkarder, 12 years ago

#1711:

  • added resource selection dialog
  • added extension method that returns all descendants of a TreeNode
  • relaxed service access permissions
File size: 12.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 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.Drawing;
25using System.Linq;
26using System.Text;
27using System.Windows.Forms;
28using HeuristicLab.Clients.Hive.JobManager.ExtensionMethods;
29using HeuristicLab.Core;
30using HeuristicLab.Core.Views;
31using HeuristicLab.MainForm;
32using HeuristicLab.MainForm.WindowsForms;
33
34namespace HeuristicLab.Clients.Hive.JobManager.Views {
35  public partial class HiveResourceSelector : ItemView, IDisposable {
36    private const int slaveImageIndex = 0;
37    private const int slaveGroupImageIndex = 1;
38    private string currentSearchString;
39    private ISet<TreeNode> mainTreeNodes;
40    private ISet<TreeNode> filteredTreeNodes;
41    private ISet<TreeNode> nodeStore;
42
43    private ISet<Resource> selectedResources;
44    public ISet<Resource> SelectedResources {
45      get { return selectedResources; }
46      set { selectedResources = value; }
47    }
48
49    private ProgressView progressView;
50    public ProgressView ProgressView {
51      get { return progressView; }
52      set { progressView = value; }
53    }
54
55    public new IItemList<Resource> Content {
56      get { return (IItemList<Resource>)base.Content; }
57      set { base.Content = value; }
58    }
59
60    public HiveResourceSelector() {
61      InitializeComponent();
62      mainTreeNodes = new HashSet<TreeNode>();
63      filteredTreeNodes = new HashSet<TreeNode>();
64      nodeStore = new HashSet<TreeNode>();
65      selectedResources = new HashSet<Resource>();
66      imageList.Images.Add(HeuristicLab.Common.Resources.VSImageLibrary.MonitorLarge);
67      imageList.Images.Add(HeuristicLab.Common.Resources.VSImageLibrary.NetworkCenterLarge);
68    }
69
70    public void StartProgressView() {
71      if (InvokeRequired) {
72        Invoke(new Action(StartProgressView));
73      } else {
74        if (progressView == null) {
75          IProgress prog = new Progress();
76          prog.Status = "Downloading resources. Please be patient.";
77          progressView = new ProgressView(this, prog);
78        }
79      }
80    }
81
82    public void FinishProgressView() {
83      if (InvokeRequired) {
84        Invoke(new Action(FinishProgressView));
85      } else {
86        if (progressView != null) {
87          progressView.Finish();
88          progressView = null;
89          SetEnabledStateOfControls();
90        }
91      }
92    }
93
94    protected override void OnContentChanged() {
95      base.OnContentChanged();
96      selectedResources = new HashSet<Resource>(Content.Where(x => selectedResources.Any(y => x.Id == y.Id)));
97      UpdateMainTree();
98      ExtractStatistics();
99    }
100
101    #region MainTree Methods
102    private void UpdateMainTree() {
103      mainTreeNodes.Clear();
104
105      foreach (Resource g in Content) {
106        if (g.GetType() == typeof(SlaveGroup)) {
107          //root node
108          if (g.ParentResourceId == null) {
109            TreeNode tn = new TreeNode();
110            tn.ImageIndex = slaveGroupImageIndex;
111            tn.SelectedImageIndex = tn.ImageIndex;
112
113            tn.Tag = g;
114            tn.Text = g.Name;
115            tn.Checked = selectedResources.Any(x => x.Id == g.Id);
116
117            BuildMainTree(tn);
118            mainTreeNodes.Add(tn);
119          }
120        }
121      }
122      UpdateFilteredTree();
123    }
124
125    private void BuildMainTree(TreeNode tn) {
126      foreach (Resource r in Content.Where(s => s.ParentResourceId != null && s.ParentResourceId == ((Resource)tn.Tag).Id)) {
127        TreeNode stn = new TreeNode(r.Name);
128        if (r is Slave) stn.ImageIndex = slaveImageIndex;
129        else if (r is SlaveGroup) stn.ImageIndex = slaveGroupImageIndex;
130        stn.SelectedImageIndex = stn.ImageIndex;
131        stn.Tag = r;
132        stn.Checked = selectedResources.Any(x => x.Id == r.Id);
133        tn.Nodes.Add(stn);
134        mainTreeNodes.Add(stn);
135
136        BuildMainTree(stn);
137      }
138    }
139    #endregion
140
141    #region FilteredTree Methods
142    private void UpdateFilteredTree() {
143      filteredTreeNodes.Clear();
144      foreach (TreeNode n in mainTreeNodes) {
145        n.BackColor = SystemColors.Window;
146        if (currentSearchString == null || ((Resource)n.Tag).Name.ToLower().Contains(currentSearchString)) {
147          n.BackColor = string.IsNullOrEmpty(currentSearchString) ? SystemColors.Window : Color.LightBlue;
148          filteredTreeNodes.Add(n);
149          TraverseParentNodes(n);
150        }
151      }
152      UpdateResourceTree();
153    }
154
155    private void TraverseParentNodes(TreeNode node) {
156      if (node != null) {
157        for (TreeNode parent = node.Parent; parent != null; parent = parent.Parent)
158          filteredTreeNodes.Add(parent);
159      }
160    }
161    #endregion
162
163    #region ResourceTree Methods
164    private void UpdateResourceTree() {
165      resourcesTreeView.Nodes.Clear();
166      nodeStore.Clear();
167
168      foreach (TreeNode node in filteredTreeNodes) {
169        var clone = nodeStore.SingleOrDefault(x => ((Resource)x.Tag).Id == ((Resource)node.Tag).Id);
170        if (clone == null) {
171          clone = (TreeNode)node.Clone();
172          nodeStore.Add(clone);
173          clone.Nodes.Clear();
174        }
175        foreach (TreeNode child in node.Nodes)
176          if (filteredTreeNodes.Any(x => ((Resource)x.Tag).Id == ((Resource)child.Tag).Id)) {
177            var childClone = nodeStore.SingleOrDefault(x => ((Resource)x.Tag).Id == ((Resource)child.Tag).Id);
178            if (childClone == null) {
179              childClone = (TreeNode)child.Clone();
180              nodeStore.Add(childClone);
181              childClone.Nodes.Clear();
182            }
183            clone.Nodes.Add(childClone);
184          }
185      }
186      resourcesTreeView.Nodes.AddRange(nodeStore.Where(x => ((Resource)x.Tag).ParentResourceId == null).ToArray());
187      if (string.IsNullOrEmpty(currentSearchString)) ExpandSlaveGroupNodes();
188      else resourcesTreeView.ExpandAll();
189    }
190    #endregion
191
192    #region Events
193    private void resourcesTreeView_AfterCheck(object sender, TreeViewEventArgs e) {
194      if (e.Action != TreeViewAction.Unknown) {
195        if (e.Node.Checked) {
196          IncludeChildNodes(mainTreeNodes.SingleOrDefault(x => ((Resource)x.Tag).Id == ((Resource)e.Node.Tag).Id));
197          IncludeParentNodes(mainTreeNodes.SingleOrDefault(x => ((Resource)x.Tag).Id == ((Resource)e.Node.Tag).Id));
198        } else {
199          ExcludeChildNodes(mainTreeNodes.SingleOrDefault(x => ((Resource)x.Tag).Id == ((Resource)e.Node.Tag).Id));
200          ExcludeParentNodes(mainTreeNodes.SingleOrDefault(x => ((Resource)x.Tag).Id == ((Resource)e.Node.Tag).Id));
201        }
202        ExtractStatistics();
203      }
204    }
205
206    private void resourcesTreeView_AfterSelect(object sender, TreeViewEventArgs e) {
207      if (e.Action != TreeViewAction.Unknown) {
208        ExtractStatistics(e.Node);
209      }
210    }
211
212    private void searchTextBox_TextChanged(object sender, System.EventArgs e) {
213      currentSearchString = searchTextBox.Text.ToLower();
214      UpdateFilteredTree();
215    }
216    #endregion
217
218    #region Helpers
219    private void IncludeChildNodes(TreeNode node) {
220      if (node != null) {
221        node.Checked = true;
222        selectedResources.Add((Resource)node.Tag);
223        AdjustNodeCheckedState(node);
224        foreach (TreeNode n in node.Nodes) IncludeChildNodes(n);
225      }
226    }
227
228    private void IncludeParentNodes(TreeNode node) {
229      if (node != null && node.Parent != null) {
230        TreeNode parent = node.Parent;
231        if (parent.Nodes.OfType<TreeNode>().All(x => x.Checked)) {
232          parent.Checked = true;
233          selectedResources.Add((Resource)parent.Tag);
234          AdjustNodeCheckedState(parent);
235          IncludeParentNodes(parent);
236        }
237      }
238    }
239
240    private void ExcludeChildNodes(TreeNode node) {
241      if (node != null) {
242        node.Checked = false;
243        selectedResources.Remove((Resource)node.Tag);
244        AdjustNodeCheckedState(node);
245        foreach (TreeNode n in node.Nodes) ExcludeChildNodes(n);
246      }
247    }
248
249    private void ExcludeParentNodes(TreeNode node) {
250      if (node != null) {
251        node.Checked = false;
252        selectedResources.Remove((Resource)node.Tag);
253        AdjustNodeCheckedState(node);
254        ExcludeParentNodes(node.Parent);
255      }
256    }
257
258    private void AdjustNodeCheckedState(TreeNode node) {
259      var filterdNode = filteredTreeNodes.SingleOrDefault(x => ((Resource)x.Tag).Id == ((Resource)node.Tag).Id);
260      var storedNode = nodeStore.SingleOrDefault(x => ((Resource)x.Tag).Id == ((Resource)node.Tag).Id);
261      if (filterdNode != null) filterdNode.Checked = node.Checked;
262      if (storedNode != null) storedNode.Checked = node.Checked;
263    }
264
265    private void ExpandSlaveGroupNodes() {
266      foreach (TreeNode n in nodeStore.Where(x => x.Tag is SlaveGroup)) {
267        TreeNode[] children = new TreeNode[n.Nodes.Count];
268        n.Nodes.CopyTo(children, 0);
269        if (children.Any(x => x.Tag is SlaveGroup)) n.Expand();
270      }
271    }
272
273    private void ExtractStatistics(TreeNode treeNode = null) {
274      StringBuilder sb = new StringBuilder();
275      Resource resource = treeNode == null ? null : treeNode.Tag as Resource;
276      ISet<Resource> resources = treeNode == null ? selectedResources : new HashSet<Resource>(treeNode.DescendantNodes().Select(x => x.Tag as Resource)); ;
277      IEnumerable<SlaveGroup> slaveGroups = resources.OfType<SlaveGroup>();
278      IEnumerable<Slave> slaves = resources.OfType<Slave>();
279      int cpuSpeed = 0, cores = 0, freeCores = 0, memory = 0, freeMemory = 0;
280      string contextString = treeNode == null ? "Selected" : "Included";
281
282      if (resources.Any() || resource != null) {
283        foreach (Slave s in slaves) {
284          cpuSpeed += s.CpuSpeed.GetValueOrDefault();
285          cores += s.Cores.GetValueOrDefault();
286          freeCores += s.FreeCores.GetValueOrDefault();
287          memory += s.Memory.GetValueOrDefault();
288          freeMemory += s.FreeMemory.GetValueOrDefault();
289        }
290        if (resource != null) {
291          if (resource is SlaveGroup) sb.Append("Slave group: ");
292          else if (resource is Slave) {
293            sb.Append("Slave: ");
294            if (!resources.Any()) {
295              Slave s = resource as Slave;
296              cpuSpeed = s.CpuSpeed.GetValueOrDefault();
297              cores = s.Cores.GetValueOrDefault();
298              freeCores = s.FreeCores.GetValueOrDefault();
299              memory = s.Memory.GetValueOrDefault();
300              freeMemory = s.FreeMemory.GetValueOrDefault();
301            }
302          }
303          sb.AppendLine(string.Format("{0}", resource.Name));
304        }
305        if (resource == null || resource is SlaveGroup) {
306          if (resources.Any()) {
307            sb.AppendFormat("{0} slave groups ({1}): ", contextString, slaveGroups.Count());
308            foreach (SlaveGroup sg in slaveGroups) sb.AppendFormat("{0}; ", sg.Name);
309            sb.AppendLine();
310            sb.AppendFormat("{0} slaves ({1}): ", contextString, slaves.Count());
311            foreach (Slave s in slaves) sb.AppendFormat("{0}; ", s.Name);
312            sb.AppendLine();
313          } else {
314            sb.Append("The selection does not inlcude any further resources.");
315          }
316        }
317        sb.AppendLine();
318        sb.AppendLine(string.Format("CPU speed: {0} MHz", cpuSpeed));
319        if (resources.Any()) sb.AppendLine(string.Format("Avg. CPU speed: {0:0.00} MHz", (double)cpuSpeed / resources.Count()));
320        sb.AppendLine(string.Format("Cores: {0}", cores));
321        sb.AppendLine(string.Format("Free cores: {0}", freeCores));
322        if (resources.Any()) sb.AppendLine(string.Format("Avg. free cores: {0:0.00}", (double)freeCores / resources.Count()));
323        sb.AppendLine(string.Format("Memory: {0} MB", memory));
324        sb.AppendFormat("Free memory: {0} MB", freeMemory);
325        if (resources.Any()) sb.Append(string.Format("{0}Avg. free memory: {1:0.00} MB", Environment.NewLine, (double)freeMemory / resources.Count()));
326      } else {
327        sb.Append("No resources selected.");
328      }
329
330      descriptionTextBox.Text = sb.ToString();
331    }
332    #endregion
333  }
334}
Note: See TracBrowser for help on using the repository browser.