Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.cs @ 15412

Last change on this file since 15412 was 15412, checked in by jkarder, 7 years ago

#2839:

  • worked on resources and projects views
  • changed resource selector to be able to select projects and assigned resources
  • updated service clients
File size: 12.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2017 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.Windows.Forms;
27using HeuristicLab.Collections;
28using HeuristicLab.Common.Resources;
29using HeuristicLab.Core;
30using HeuristicLab.Core.Views;
31using HeuristicLab.MainForm;
32using HeuristicLab.MainForm.WindowsForms;
33
34namespace HeuristicLab.Clients.Hive.JobManager.Views {
35  [View("Hive Project Selector View")]
36  [Content(typeof(IItemList<Project>), true)]
37  public partial class HiveProjectSelector : ItemView, IDisposable {
38    private const int greenFlagImageIndex = 0;
39    private const int redFlagImageIndex = 1;
40    private const int slaveImageIndex = 0;
41    private const int slaveGroupImageIndex = 1;
42
43    private readonly ISet<TreeNode> mainTreeNodes = new HashSet<TreeNode>();
44    private readonly ISet<TreeNode> filteredTreeNodes = new HashSet<TreeNode>();
45    private readonly ISet<TreeNode> nodeStore = new HashSet<TreeNode>();
46    private readonly ISet<Resource> resources = new HashSet<Resource>();
47
48    private string currentSearchString;
49
50    private Project selectedProject;
51    public Project SelectedProject {
52      get { return selectedProject; }
53      set {
54        if (selectedProject == value) return;
55        selectedProject = value;
56        UpdateResources();
57        OnSelectedProjectChanged();
58      }
59    }
60
61    private readonly IObservableSet<Resource> selectedResources = new ObservableSet<Resource>();
62    public IEnumerable<Resource> SelectedResources { get { return selectedResources; } }
63
64    public new IItemList<Project> Content {
65      get { return (IItemList<Project>)base.Content; }
66      set { base.Content = value; }
67    }
68
69    public HiveProjectSelector() {
70      InitializeComponent();
71
72      projectsImageList.Images.Add(VSImageLibrary.FlagGreen);
73      projectsImageList.Images.Add(VSImageLibrary.FlagRed);
74      resourcesImageList.Images.Add(VSImageLibrary.MonitorLarge);
75      resourcesImageList.Images.Add(VSImageLibrary.NetworkCenterLarge);
76    }
77
78    #region Overrides
79    protected override void OnContentChanged() {
80      base.OnContentChanged();
81
82      if (Content != null) {
83        UpdateMainTree();
84        ExtractStatistics();
85      } else {
86        mainTreeNodes.Clear();
87        UpdateFilteredTree();
88      }
89
90      SelectedProject = null;
91    }
92    #endregion
93
94    #region Event Handlers
95    private void HiveProjectSelector_Load(object sender, EventArgs e) {
96      projectsTreeView.Nodes.Clear();
97      resourcesTreeView.Nodes.Clear();
98      SelectedProject = null;
99    }
100
101    private void searchTextBox_TextChanged(object sender, EventArgs e) {
102      currentSearchString = searchTextBox.Text.ToLower();
103      UpdateFilteredTree();
104    }
105
106    private void projectsTreeView_MouseDoubleClick(object sender, MouseEventArgs e) {
107      OnProjectsTreeViewDoubleClicked();
108    }
109
110    private void projectsTreeView_MouseDown(object sender, MouseEventArgs e) {
111      var node = projectsTreeView.GetNodeAt(new Point(e.X, e.Y));
112
113      SelectedProject = (Project)node?.Tag;
114
115      if (node == null) {
116        projectsTreeView.SelectedNode = null;
117      }
118
119      ExtractStatistics();
120    }
121
122    private void resourcesTreeView_MouseDown(object sender, MouseEventArgs e) {
123      var node = resourcesTreeView.GetNodeAt(new Point(e.X, e.Y));
124
125      if (node == null) {
126        resourcesTreeView.SelectedNode = null;
127      }
128
129      ExtractStatistics((Resource)node?.Tag);
130    }
131
132    private void resourcesTreeView_AfterCheck(object sender, TreeViewEventArgs e) {
133      var resource = (Resource)e.Node.Tag;
134
135      if (e.Node.Checked)
136        selectedResources.Add(resource);
137      else
138        selectedResources.Remove(resource);
139
140      ExtractStatistics((Resource)resourcesTreeView.SelectedNode?.Tag);
141      OnSelectedResourcesChanged();
142    }
143    #endregion
144
145    #region Helpers
146    private void UpdateMainTree() {
147      mainTreeNodes.Clear();
148
149      foreach (Project g in Content.OrderBy(x => x.Name)) {
150        if (g.ParentProjectId == null) {
151          TreeNode tn = new TreeNode();
152          tn.ImageIndex = greenFlagImageIndex;
153          tn.SelectedImageIndex = tn.ImageIndex;
154
155          tn.Tag = g;
156          tn.Text = g.Name;
157          tn.Checked = selectedResources.Any(x => x.Id == g.Id);
158
159          BuildMainTree(tn);
160          mainTreeNodes.Add(tn);
161        }
162      }
163      UpdateFilteredTree();
164    }
165
166    private void BuildMainTree(TreeNode tn) {
167      foreach (Project r in Content.Where(s => s.ParentProjectId != null && s.ParentProjectId == ((Project)tn.Tag).Id).OrderBy(x => x.Name)) {
168        TreeNode stn = new TreeNode(r.Name);
169        stn.ImageIndex = redFlagImageIndex;
170        stn.SelectedImageIndex = stn.ImageIndex;
171        stn.Tag = r;
172        stn.Checked = selectedResources.Any(x => x.Id == r.Id);
173        tn.Nodes.Add(stn);
174        mainTreeNodes.Add(stn);
175
176        BuildMainTree(stn);
177      }
178    }
179
180    private void UpdateFilteredTree() {
181      filteredTreeNodes.Clear();
182      foreach (TreeNode n in mainTreeNodes) {
183        n.BackColor = SystemColors.Window;
184        if (currentSearchString == null || ((Project)n.Tag).Name.ToLower().Contains(currentSearchString)) {
185          n.BackColor = string.IsNullOrEmpty(currentSearchString) ? SystemColors.Window : Color.LightBlue;
186          filteredTreeNodes.Add(n);
187          TraverseParentNodes(n);
188        }
189      }
190      UpdateProjectsTree();
191    }
192
193    private void UpdateProjectsTree() {
194      projectsTreeView.Nodes.Clear();
195      nodeStore.Clear();
196
197      foreach (TreeNode node in filteredTreeNodes) {
198        var clone = nodeStore.SingleOrDefault(x => ((Project)x.Tag).Id == ((Project)node.Tag).Id);
199        if (clone == null) {
200          clone = (TreeNode)node.Clone();
201          nodeStore.Add(clone);
202          clone.Nodes.Clear();
203        }
204        foreach (TreeNode child in node.Nodes)
205          if (filteredTreeNodes.Any(x => ((Project)x.Tag).Id == ((Project)child.Tag).Id)) {
206            var childClone = nodeStore.SingleOrDefault(x => ((Project)x.Tag).Id == ((Project)child.Tag).Id);
207            if (childClone == null) {
208              childClone = (TreeNode)child.Clone();
209              nodeStore.Add(childClone);
210              childClone.Nodes.Clear();
211            }
212            clone.Nodes.Add(childClone);
213          }
214      }
215      projectsTreeView.Nodes.AddRange(nodeStore.Where(x => ((Project)x.Tag).ParentProjectId == null).ToArray());
216      if (string.IsNullOrEmpty(currentSearchString)) ExpandSlaveGroupNodes();
217      else projectsTreeView.ExpandAll();
218    }
219
220    private void TraverseParentNodes(TreeNode node) {
221      if (node != null) {
222        for (TreeNode parent = node.Parent; parent != null; parent = parent.Parent)
223          filteredTreeNodes.Add(parent);
224      }
225    }
226
227    private void UpdateResources() {
228      selectedResources.Clear();
229
230      if (selectedProject != null) {
231        var assignedResources = HiveServiceLocator.Instance.CallHiveService(s => s.GetAssignedResourcesForProject(selectedProject.Id));
232        var assignedResourceIds = new HashSet<Guid>(assignedResources.Select(x => x.ResourceId));
233
234        foreach (var resource in HiveAdminClient.Instance.Resources) {
235          if (assignedResourceIds.Contains(resource.Id)) {
236            resources.Add(resource);
237            selectedResources.Add(resource);
238          }
239        }
240      }
241
242      BuildResourceTree(selectedResources);
243      ExtractStatistics();
244      OnSelectedResourcesChanged();
245    }
246
247    private Resource BuildResourceTree(IEnumerable<Resource> resources) {
248      resourcesTreeView.Nodes.Clear();
249      if (!resources.Any()) return null;
250
251      var mainResources = new HashSet<Resource>(resources.Where(x => x.ParentResourceId == null));
252      var subResources = new HashSet<Resource>(resources.Except(mainResources));
253
254      var stack = new Stack<Resource>(mainResources.OrderByDescending(x => x.Name));
255      var top = stack.Peek();
256
257      TreeNode currentNode = null;
258      Resource currentResource = null;
259
260      while (stack.Any()) {
261        var newResource = stack.Pop();
262        var newNode = new TreeNode(newResource.Name) {
263          Checked = true,
264          ImageIndex = newResource is Slave ? slaveImageIndex : slaveGroupImageIndex,
265          Tag = newResource
266        };
267
268        while (currentNode != null && newResource.ParentResourceId != currentResource.Id) {
269          currentNode = currentNode.Parent;
270          currentResource = currentNode == null ? null : (Resource)currentNode.Tag;
271        }
272
273        if (currentNode == null) {
274          resourcesTreeView.Nodes.Add(newNode);
275        } else {
276          currentNode.Nodes.Add(newNode);
277        }
278
279        newNode.SelectedImageIndex = newNode.ImageIndex;
280
281        var childResources = subResources.Where(x => x.ParentResourceId == newResource.Id);
282        if (childResources.Any()) {
283          foreach (var resource in childResources.OrderByDescending(x => x.Name)) {
284            subResources.Remove(resource);
285            stack.Push(resource);
286          }
287          currentNode = newNode;
288          currentResource = newResource;
289        }
290      }
291
292      resourcesTreeView.ExpandAll();
293
294      return top;
295    }
296
297    private void ExpandSlaveGroupNodes() {
298      foreach (TreeNode n in nodeStore.Where(x => x.Tag is SlaveGroup)) {
299        TreeNode[] children = new TreeNode[n.Nodes.Count];
300        n.Nodes.CopyTo(children, 0);
301        if (children.Any(x => x.Tag is SlaveGroup)) n.Expand();
302      }
303    }
304
305    private void ExtractStatistics(Resource resource = null) {
306      ISet<Slave> selectedSlaves = null;
307
308      if (resource != null) {
309        var slaveGroup = resource as SlaveGroup;
310        if (slaveGroup != null) {
311          var children = new HashSet<Resource>(resources.Where(x => x.ParentResourceId == slaveGroup.Id));
312          int nrOfChildren = children.Count;
313          do {
314            var newChildren = resources.Where(x => children.Any(y => y.Id == x.ParentResourceId));
315            foreach (var newChild in newChildren)
316              children.Add(newChild);
317          } while (children.Count > nrOfChildren);
318          selectedSlaves = new HashSet<Slave>(children.OfType<Slave>());
319          selectedSlaves.IntersectWith(selectedResources.OfType<Slave>());
320        } else {
321          selectedSlaves = new HashSet<Slave>(new[] { resource as Slave });
322        }
323      } else {
324        selectedSlaves = new HashSet<Slave>(selectedResources.OfType<Slave>());
325      }
326
327      int sumCores = selectedSlaves.OfType<Slave>().Sum(x => x.Cores.GetValueOrDefault());
328      int sumFreeCores = selectedSlaves.OfType<Slave>().Sum(x => x.FreeCores.GetValueOrDefault());
329      double sumMemory = selectedSlaves.OfType<Slave>().Sum(x => x.Memory.GetValueOrDefault()) / 1024.0;
330      double sumFreeMemory = selectedSlaves.OfType<Slave>().Sum(x => x.FreeMemory.GetValueOrDefault()) / 1024.0;
331
332      coresSummaryLabel.Text = $"{sumCores} Total ({sumFreeCores} Free / {sumCores - sumFreeCores} Used)";
333      memorySummaryLabel.Text = $"{sumMemory:0.00} GB Total ({sumFreeMemory:0.00} GB Free / {(sumMemory - sumFreeMemory):0.00} GB Used)";
334    }
335    #endregion
336
337    #region Events
338    public event EventHandler SelectedProjectChanged;
339    private void OnSelectedProjectChanged() {
340      SelectedProjectChanged?.Invoke(this, EventArgs.Empty);
341    }
342
343    public event EventHandler SelectedResourcesChanged;
344    private void OnSelectedResourcesChanged() {
345      SelectedResourcesChanged?.Invoke(this, EventArgs.Empty);
346    }
347
348    public event EventHandler ProjectsTreeViewDoubleClicked;
349    private void OnProjectsTreeViewDoubleClicked() {
350      ProjectsTreeViewDoubleClicked?.Invoke(this, EventArgs.Empty);
351    }
352    #endregion
353  }
354}
Note: See TracBrowser for help on using the repository browser.