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

Last change on this file since 16117 was 16117, checked in by jkarder, 13 months ago

#2839: merged [15377-16116/branches/2839_HiveProjectManagement] into trunk

File size: 32.6 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    public const string additionalSlavesGroupName = "Additional Slaves";
43    public const string additionalSlavesGroupDescription = "Contains additional slaves which are either ungrouped or the parenting slave group is not assigned to the selected project.";
44
45    private const string CURRENT_SELECTION_TAG = " [current assignment]";
46    private const string NEW_SELECTION_TAG = " [new assignment]";
47    private const string CHANGED_SELECTION_TAG = " [changed assignment]";
48    private const string ADDED_SELECTION_TAG = " [added assignment]";
49    private const string REMOVED_SELECTION_TAG = " [removed assignment]";
50    private const string SELECTED_TAG = " [assigned]";
51    private const string INCLUDED_TAG = " [included]";
52    private const string ADDED_INCLUDE_TAG = " [added include]";
53    private const string REMOVED_INCLUDE_TAG = " [removed include]";
54
55    private TreeNode additionalNode;
56
57    private readonly HashSet<TreeNode> mainTreeNodes = new HashSet<TreeNode>();
58    private readonly HashSet<TreeNode> filteredTreeNodes = new HashSet<TreeNode>();
59
60    private readonly HashSet<Resource> availableResources = new HashSet<Resource>();
61    private readonly HashSet<Resource> assignedResources = new HashSet<Resource>();
62    private readonly HashSet<Resource> includedResources = new HashSet<Resource>();
63    private readonly HashSet<Resource> newAssignedResources = new HashSet<Resource>();
64    private readonly HashSet<Resource> newIncludedResources = new HashSet<Resource>();
65
66    private readonly Color addedAssignmentColor = Color.FromArgb(255, 87, 191, 193); // #57bfc1
67    private readonly Color removedAssignmentColor = Color.FromArgb(255, 236, 159, 72); // #ec9f48
68    private readonly Color addedIncludeColor = Color.FromArgb(25, 169, 221, 221); // #a9dddd
69    private readonly Color removedIncludeColor = Color.FromArgb(25, 249, 210, 145); // #f9d291
70    private readonly Color selectedBackColor = Color.DodgerBlue;
71    private readonly Color selectedForeColor = Color.White;
72    private readonly Color controlTextColor = SystemColors.ControlText;
73    private readonly Color grayTextColor = SystemColors.GrayText;
74
75    private string currentSearchString;
76
77    private void resetHiveResourceSelector() {
78      lastSelectedProject = null;
79      selectedProject = null;
80      projectId = null;
81    }
82
83    private Guid jobId;
84    public Guid JobId {
85      get { return jobId; }
86      set {
87        if (jobId == value) return;
88        jobId = value;
89        resetHiveResourceSelector();
90      }
91    }
92
93    private Guid? projectId;
94    public Guid? ProjectId {
95      get { return projectId; }
96      set {
97        if (projectId == value) return;
98        projectId = value;
99      }
100    }
101
102    private Guid? selectedProjectId;
103    public Guid? SelectedProjectId {
104      get { return selectedProjectId; }
105      set {
106        if (selectedProjectId == value) return;
107        selectedProjectId = value;
108      }
109    }
110
111    private IEnumerable<Guid> selectedResourceIds;
112    public IEnumerable<Guid> SelectedResourceIds {
113      get { return selectedResourceIds; }
114      set {
115        if (selectedResourceIds == value) return;
116        selectedResourceIds = value;
117      }
118    }
119
120    public bool ChangedProjectSelection {
121      get {
122        if ((lastSelectedProject == null && selectedProject != null) 
123          || (lastSelectedProject != null && selectedProject == null)
124          || (lastSelectedProject != null && selectedProject != null && lastSelectedProject.Id != selectedProject.Id))
125          return true;
126        else return false;
127      }
128    }
129
130    public bool ChangedResources {
131      get { return !assignedResources.SetEquals(newAssignedResources); }
132    }
133
134    private Project lastSelectedProject;
135    private Project selectedProject;
136    public Project SelectedProject {
137      get { return selectedProject; }
138      set {
139        if (selectedProject == value) return;
140
141        if ((JobId == Guid.Empty || JobId == null) 
142          && (value == null || SelectedProject == null || value.Id != SelectedProject.Id)) selectedResourceIds = null;
143        lastSelectedProject = selectedProject;
144        selectedProject = value;
145
146        UpdateResourceTree();
147        ExtractStatistics();
148        OnSelectedProjectChanged();
149      }
150    }
151
152    public int AssignedCores {
153      get {
154        HashSet<Slave> newAssignedSlaves = new HashSet<Slave>(newAssignedResources.OfType<Slave>());
155        foreach(var slaveGroup in newAssignedResources.OfType<SlaveGroup>()) {
156          foreach(var slave in HiveClient.Instance.GetAvailableResourceDescendants(slaveGroup.Id).OfType<Slave>()) {
157            newAssignedSlaves.Add(slave);
158          }
159        }
160        return newAssignedSlaves.Sum(x => x.Cores.GetValueOrDefault());
161      }
162    }
163
164    public IEnumerable<Resource> AssignedResources {
165      get { return newAssignedResources; }
166      set {
167        if (newAssignedResources == value) return;
168        newAssignedResources.Clear();
169        foreach(var resource in value) {
170          newAssignedResources.Add(resource);
171        }
172      }
173    }
174
175
176    public new IItemList<Project> Content {
177      get { return (IItemList<Project>)base.Content; }
178      set { base.Content = value; }
179    }
180
181    public HiveProjectSelector() {
182      InitializeComponent();
183
184      projectsImageList.Images.Add(VSImageLibrary.FlagGreen);
185      projectsImageList.Images.Add(VSImageLibrary.FlagRed);
186      resourcesImageList.Images.Add(VSImageLibrary.MonitorLarge);
187      resourcesImageList.Images.Add(VSImageLibrary.NetworkCenterLarge);
188    }
189
190    #region Overrides
191    protected override void OnContentChanged() {
192      base.OnContentChanged();
193
194      if (Content != null) {               
195        if (SelectedProjectId.HasValue && SelectedProjectId.Value != Guid.Empty) {
196          SelectedProject = GetSelectedProjectById(SelectedProjectId.Value);
197        } else {
198          SelectedProject = null;
199        }
200        //ExtractStatistics();
201        UpdateProjectTree();
202
203      } else {
204        lastSelectedProject = null;
205        selectedProject = null;
206        selectedProjectId = null;
207        projectsTreeView.Nodes.Clear();
208        resourcesTreeView.Nodes.Clear();
209      }
210    }
211
212    #endregion
213
214    #region Event Handlers
215    private void HiveProjectSelector_Load(object sender, EventArgs e) {
216      projectsTreeView.Nodes.Clear();
217      resourcesTreeView.Nodes.Clear();
218    }
219
220    private void searchTextBox_TextChanged(object sender, EventArgs e) {
221      currentSearchString = searchTextBox.Text.ToLower();
222      //UpdateFilteredTree();
223      UpdateProjectTree();
224    }
225
226    private void projectsTreeView_MouseDoubleClick(object sender, MouseEventArgs e) {
227      OnProjectsTreeViewDoubleClicked();
228    }
229
230    private void projectsTreeView_BeforeSelect(object sender, TreeViewCancelEventArgs e) {
231      var node = (Project)e.Node.Tag;
232      if (HiveClient.Instance.DisabledParentProjects.Contains(node)) {
233        e.Cancel = true;
234      }
235    }
236
237    private void projectsTreeView_AfterSelect(object sender, TreeViewEventArgs e) {
238      var node = (Project)e.Node.Tag;
239
240      if (node == null) {
241        projectsTreeView.SelectedNode = null;
242      } else if (HiveClient.Instance.DisabledParentProjects.Contains(node)) {
243        return;
244      } else {
245        ResetTreeNodes(projectsTreeView.Nodes);
246        e.Node.BackColor = selectedBackColor;
247        e.Node.ForeColor = selectedForeColor;
248
249        if (node.Id == projectId) {
250          e.Node.Text += CURRENT_SELECTION_TAG;
251        } else if (projectId == null || projectId == Guid.Empty) {
252          e.Node.Text += NEW_SELECTION_TAG;
253        } else {
254          e.Node.Text += CHANGED_SELECTION_TAG;
255        }
256
257
258      }
259      SelectedProject = node;
260    }
261
262    private void resourcesTreeView_MouseDown(object sender, MouseEventArgs e) {
263      var node = resourcesTreeView.GetNodeAt(new Point(e.X, e.Y));
264
265      if (node == null || node == additionalNode) {
266        resourcesTreeView.SelectedNode = null;
267        ExtractStatistics();
268      } else {
269        var r = (Resource)node.Tag;
270        if (!HiveClient.Instance.DisabledParentResources.Contains(r)) {
271          ExtractStatistics((Resource)node.Tag);
272        } else {
273          resourcesTreeView.SelectedNode = null;
274          ExtractStatistics();
275        } 
276      }
277    }
278
279    private void resourcesTreeView_BeforeSelect(object sender, TreeViewCancelEventArgs e) {
280      if(e.Node == null || e.Node == additionalNode) {
281        e.Cancel = true;
282      } else {
283        var r = (Resource)e.Node.Tag;
284        if(r == null || HiveClient.Instance.DisabledParentResources.Contains(r)) {
285          e.Cancel = true;
286        }
287      }
288
289    }
290
291    private void resourcesTreeView_BeforeCheck(object sender, TreeViewCancelEventArgs e) {
292      if(e.Node == null || e.Node == additionalNode) {
293        e.Cancel = true;
294      } else {
295        var checkedResource = (Resource)e.Node.Tag;
296        if (checkedResource == null
297          || checkedResource.Id == Guid.Empty
298          || HiveClient.Instance.DisabledParentResources.Contains(checkedResource)
299          || newIncludedResources.Contains(checkedResource)) {
300          e.Cancel = true;
301
302          var selectedNode = resourcesTreeView.SelectedNode;
303          var selectedResource = (Resource)(selectedNode != null ? selectedNode.Tag : null);
304
305          ExtractStatistics(selectedResource);
306        }
307      }
308    }
309
310    private void resourcesTreeView_AfterCheck(object sender, TreeViewEventArgs e) {
311      var checkedResource = (Resource)e.Node.Tag;
312      if (e.Node.Checked) {
313        newAssignedResources.Add(checkedResource);
314      } else {
315        newAssignedResources.Remove(checkedResource);
316      }
317
318      UpdateResourceTreeAfterCheck();
319      ExtractStatistics();
320      OnAssignedResourcesChanged();
321    }
322
323    private void resourcesTreeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) {
324      return;
325    }
326    #endregion
327
328    #region Helpers
329
330    private Project GetSelectedProjectById(Guid projectId) {
331      return Content.Where(x => x.Id == projectId).SingleOrDefault();
332    }
333
334    private void UpdateProjectTree() {
335
336      if (string.IsNullOrEmpty(currentSearchString)) {
337        BuildProjectTree(Content);
338      } else {
339        HashSet<Project> filteredProjects = new HashSet<Project>();
340        foreach(var project in Content) {
341          if(project.Name.ToLower().Contains(currentSearchString.ToLower())) {
342            filteredProjects.Add(project);
343            filteredProjects.UnionWith(Content.Where(p => HiveClient.Instance.GetAvailableProjectAncestors(project.Id).Select(x => x.Id).Contains(p.Id)));
344          }
345        }
346        BuildProjectTree(filteredProjects);
347      }
348    }
349
350    private void BuildProjectTree(IEnumerable<Project> projects) {
351      projectsTreeView.Nodes.Clear();
352      if (!projects.Any()) return;
353
354      var disabledParentProjects = HiveClient.Instance.DisabledParentProjects;
355      // select all top level projects (withouth parent, or without any ancestor within current project collection)
356      var mainProjects = new HashSet<Project>(projects.Where(x => x.ParentProjectId == null));
357      //var parentedMainProjects = new HashSet<Project>(projects
358      //  .Where(x => x.ParentProjectId.HasValue
359      //  && !projects.Select(y => y.Id).Contains(x.ParentProjectId.Value)
360      //  && !projects.SelectMany(y => HiveClient.Instance.ProjectAncestors[y.Id]).Contains(x.ParentProjectId.Value)));
361      //mainProjects.UnionWith(parentedMainProjects);
362      var mainDisabledParentProjects = new HashSet<Project>(disabledParentProjects.Where(x => x.ParentProjectId == null || x.ParentProjectId == Guid.Empty));
363      mainProjects.UnionWith(mainDisabledParentProjects);
364      var subProbjects = new HashSet<Project>(projects.Union(disabledParentProjects).Except(mainProjects));
365      //foreach (var p in subProbjects) {
366      //  p.ParentProjectId = HiveClient.Instance.ProjectAncestors[p.Id].Where(x => projects.Select(y => y.Id).Contains(x)).FirstOrDefault();
367      //}
368
369      var stack = new Stack<Project>(mainProjects.OrderByDescending(x => x.Name));
370
371      TreeNode currentNode = null;
372      Project currentProject = null;
373
374      while(stack.Any()) {
375        var newProject = stack.Pop();
376        var newNode = new TreeNode(newProject.Name) { Tag = newProject };
377
378        while (currentNode != null && newProject.ParentProjectId != currentProject.Id) {
379          currentNode = currentNode.Parent;
380          currentProject = currentNode == null ? null : (Project)currentNode.Tag;
381        }
382
383        if (currentNode == null) {
384          projectsTreeView.Nodes.Add(newNode);
385          newNode.ImageIndex = greenFlagImageIndex;
386        } else {
387          currentNode.Nodes.Add(newNode);
388          newNode.ImageIndex = redFlagImageIndex;
389        }
390
391        newNode.SelectedImageIndex = newNode.ImageIndex;
392
393        if(disabledParentProjects.Contains(newProject)) {
394          newNode.Checked = false;
395          newNode.ForeColor = grayTextColor;
396        }
397        else if (SelectedProject != null && SelectedProject.Id.Equals(newProject.Id)) {
398          newNode.BackColor = selectedBackColor;
399          newNode.ForeColor = selectedForeColor;
400          if(SelectedProject.Id == projectId) {
401            newNode.Text += CURRENT_SELECTION_TAG;
402          } else if (projectId == null || projectId == Guid.Empty) {
403            newNode.Text += NEW_SELECTION_TAG;
404          } else {
405            newNode.Text += CHANGED_SELECTION_TAG;
406          }
407        }
408
409        if (!string.IsNullOrEmpty(currentSearchString) && newProject.Name.ToLower().Contains(currentSearchString.ToLower())) {
410          newNode.BackColor = Color.LightBlue;
411        }
412
413        var childProjects = subProbjects.Where(x => x.ParentProjectId == newProject.Id);
414        if (childProjects.Any()) {
415          foreach (var project in childProjects.OrderByDescending(x => x.Name)) {
416            subProbjects.Remove(project);
417            stack.Push(project);
418          }
419          currentNode = newNode;
420          currentProject = newProject;
421        }
422      }
423
424      projectsTreeView.ExpandAll();
425    }
426
427    private static IEnumerable<Resource> GetAssignedResourcesForProject(Guid projectId) {
428      var assignedProjectResources = HiveServiceLocator.Instance.CallHiveService(s => s.GetAssignedResourcesForProject(projectId));
429      return HiveClient.Instance.Resources.Where(x => assignedProjectResources.Select(y => y.ResourceId).Contains(x.Id));
430    }
431
432    private static IEnumerable<Resource> GetAssignedResourcesForJob(Guid jobId) {
433      var assignedJobResources = HiveServiceLocator.Instance.CallHiveService(s => s.GetAssignedResourcesForJob(jobId));
434      return HiveClient.Instance.Resources.Where(x => assignedJobResources.Select(y => y.ResourceId).Contains(x.Id));
435    }
436
437    private void UpdateResourceTree() {
438      UpdateAvailableResources();
439      UpdateAssignedResources();
440      UpdateIncludedResources();
441      BuildResourceTree(availableResources);
442    }
443
444    private void UpdateResourceTreeAfterCheck() {
445      resourcesTreeView.BeforeCheck -= resourcesTreeView_BeforeCheck;
446      resourcesTreeView.AfterCheck -= resourcesTreeView_AfterCheck;
447      UpdateNewAssignedResources();
448      UpdateNewIncludedResources();
449      SetTreeNodes(resourcesTreeView.Nodes);
450      resourcesTreeView.BeforeCheck += resourcesTreeView_BeforeCheck;
451      resourcesTreeView.AfterCheck += resourcesTreeView_AfterCheck;
452    }
453
454    private void UpdateAvailableResources() {
455      availableResources.Clear();
456      if (selectedProject != null) {
457        var assignedProjectResources = GetAssignedResourcesForProject(selectedProject.Id);
458        foreach (var resource in assignedProjectResources) {
459          availableResources.Add(resource);
460          foreach(var descendant in HiveClient.Instance.Resources.Where(x => HiveClient.Instance.ResourceDescendants[resource.Id].Contains(x.Id))) {
461            availableResources.Add(descendant);
462          }
463        }
464      }
465      //ExtractStatistics();
466      //OnAssignedResourcesChanged();
467    }
468
469    private void UpdateAssignedResources() {
470      assignedResources.Clear();
471      newAssignedResources.Clear();
472
473      if (JobId == Guid.Empty || JobId == null) { // new, unchanged jobs get all avaialable resources
474        // update new assigned resources
475        if(selectedResourceIds == null) {
476          foreach (var resource in availableResources
477            .Where(x => !x.ParentResourceId.HasValue
478            || !availableResources.Select(y => y.Id).Contains(x.ParentResourceId.Value))) {
479            newAssignedResources.Add(resource);
480          }
481        } else {
482          foreach(var resource in availableResources.Where(x => selectedResourceIds.Contains(x.Id))) {
483            newAssignedResources.Add(resource);
484          }
485        }
486      } else if(selectedProject.Id == projectId) { // existent, unchanged jobs get all assigned resources
487        // update assigned resources
488        var assignedJobResources = GetAssignedResourcesForJob(JobId);
489        foreach (var resource in assignedJobResources) {
490          assignedResources.Add(resource);
491          if (selectedResourceIds == null) {
492            newAssignedResources.Add(resource);
493          }
494        }
495
496        if(selectedResourceIds != null) {
497          foreach (var resource in availableResources.Where(x => selectedResourceIds.Contains(x.Id))) {
498            newAssignedResources.Add(resource);
499          }
500        }
501      }
502
503      //ExtractStatistics();
504      OnAssignedResourcesChanged();
505    }
506
507    private void UpdateNewAssignedResources() {
508      for(int i = newAssignedResources.Count-1; i>=0; i--) {
509        if(newAssignedResources.Intersect(HiveClient.Instance.GetAvailableResourceAncestors(newAssignedResources.ElementAt(i).Id)).Any()) {
510          newAssignedResources.Remove(newAssignedResources.ElementAt(i));
511        }
512      }
513    }
514
515    private void UpdateIncludedResources() {
516      includedResources.Clear();
517      newIncludedResources.Clear();
518
519      if (JobId != Guid.Empty) {
520        foreach (var item in assignedResources) {
521          foreach (var descendant in HiveClient.Instance.GetAvailableResourceDescendants(item.Id)) {
522            includedResources.Add(descendant);
523          }
524        }
525      }
526
527      foreach (var item in newAssignedResources) {
528        foreach (var descendant in HiveClient.Instance.GetAvailableResourceDescendants(item.Id)) {
529          newIncludedResources.Add(descendant);
530        }
531      }
532    }
533
534    private void UpdateNewIncludedResources() {
535      newIncludedResources.Clear();
536      foreach (var item in newAssignedResources) {
537        foreach (var descendant in HiveClient.Instance.GetAvailableResourceDescendants(item.Id)) {
538          newIncludedResources.Add(descendant);
539        }
540      }
541    }
542
543    private void BuildResourceTree(IEnumerable<Resource> resources) {
544      resourcesTreeView.Nodes.Clear();
545      if (!resources.Any()) return;
546
547      resourcesTreeView.BeforeCheck -= resourcesTreeView_BeforeCheck;
548      resourcesTreeView.AfterCheck -= resourcesTreeView_AfterCheck;
549
550      var disabledParentResources = HiveClient.Instance.DisabledParentResources;
551      var mainResources = new HashSet<Resource>(resources.OfType<SlaveGroup>().Where(x => x.ParentResourceId == null));
552      //var parentedMainResources = new HashSet<Resource>(resources.OfType<SlaveGroup>()
553      //  .Where(x => x.ParentResourceId.HasValue && !resources.Select(y => y.Id).Contains(x.ParentResourceId.Value)));
554      //mainResources.UnionWith(parentedMainResources);
555      //var subResources = new HashSet<Resource>(resources.Except(mainResources));
556      var mainDisabledParentResources = new HashSet<Resource>(disabledParentResources.Where(x => x.ParentResourceId == null || x.ParentResourceId == Guid.Empty));
557      mainResources.UnionWith(mainDisabledParentResources);
558      var subResources = new HashSet<Resource>(resources.Union(disabledParentResources).Except(mainResources).OrderByDescending(x => x.Name));
559
560      var addedAssignments = newAssignedResources.Except(assignedResources);
561      var removedAssignments = assignedResources.Except(newAssignedResources);
562      var addedIncludes = newIncludedResources.Except(includedResources);
563      var removedIncludes = includedResources.Except(newIncludedResources);
564
565      TreeNode currentNode = null;
566      Resource currentResource = null;
567
568      var stack = new Stack<Resource>(mainResources.OrderByDescending(x => x.Name));
569
570      while (stack.Any()) {
571        var newResource = stack.Pop();
572        var newNode = new TreeNode(newResource.Name) { Tag = newResource };
573
574        // search for parent node of newNode and save in currentNode
575        // necessary since newNodes (stack top items) might be siblings
576        // or grand..grandparents of previous node (currentNode)
577        while (currentNode != null && newResource.ParentResourceId != currentResource.Id) {
578          currentNode = currentNode.Parent;
579          currentResource = currentNode == null ? null : (Resource)currentNode.Tag;
580        }
581
582        if (currentNode == null) {
583          resourcesTreeView.Nodes.Add(newNode);
584        } else {
585          currentNode.Nodes.Add(newNode);
586        }
587
588        if (disabledParentResources.Contains(newResource)) {
589          newNode.Checked = false;
590          newNode.ForeColor = grayTextColor;
591        } else if (newAssignedResources.Select(x => x.Id).Contains(newResource.Id)) {
592          newNode.Checked = true;
593          if(!addedAssignments.Select(x => x.Id).Contains(newResource.Id) && !removedAssignments.Select(x => x.Id).Contains(newResource.Id)) {
594            newNode.Text += SELECTED_TAG;
595          }
596        } else if (newIncludedResources.Select(x => x.Id).Contains(newResource.Id)) {
597          newNode.Checked = true;
598          newNode.ForeColor = grayTextColor;
599        }
600
601        if (includedResources.Select(x => x.Id).Contains(newResource.Id) && newIncludedResources.Select(x => x.Id).Contains(newResource.Id)) {
602          newNode.Text += INCLUDED_TAG;
603        } else if (addedIncludes.Select(x => x.Id).Contains(newResource.Id)) {
604          newNode.BackColor = addedIncludeColor;
605          newNode.ForeColor = grayTextColor;
606          newNode.Text += ADDED_INCLUDE_TAG;
607        } else if (removedIncludes.Select(x => x.Id).Contains(newResource.Id)) {
608          newNode.BackColor = removedIncludeColor;
609          newNode.Text += REMOVED_INCLUDE_TAG;
610        }
611
612        if (addedAssignments.Select(x => x.Id).Contains(newResource.Id)) {
613          newNode.BackColor = addedAssignmentColor;
614          newNode.ForeColor = controlTextColor;
615          newNode.Text += ADDED_SELECTION_TAG;
616        } else if (removedAssignments.Select(x => x.Id).Contains(newResource.Id)) {
617          newNode.BackColor = removedAssignmentColor;
618          newNode.ForeColor = controlTextColor;
619          newNode.Text += REMOVED_SELECTION_TAG;
620        }
621
622        if (newResource is Slave) {
623          newNode.ImageIndex = slaveImageIndex;
624        } else {
625          newNode.ImageIndex = slaveGroupImageIndex;
626
627          var childResources = subResources.Where(x => x.ParentResourceId == newResource.Id);
628          if (childResources.Any()) {
629            foreach (var resource in childResources.OrderByDescending(x => x.Name)) {
630              subResources.Remove(resource);
631              stack.Push(resource);
632            }
633            currentNode = newNode;
634            currentResource = newResource;
635          }
636        }
637        newNode.SelectedImageIndex = newNode.ImageIndex;
638      }
639
640      var singleSlaves = subResources.OfType<Slave>();
641      if (singleSlaves.Any()) {
642
643        additionalNode = new TreeNode(additionalSlavesGroupName) {
644          ForeColor = SystemColors.GrayText,
645          Tag = new SlaveGroup() {
646            Name = additionalSlavesGroupName,
647            Description = additionalSlavesGroupDescription
648          }
649        };
650
651        foreach (var slave in singleSlaves.OrderBy(x => x.Name)) {
652          var slaveNode = new TreeNode(slave.Name) { Tag = slave };
653          additionalNode.Nodes.Add(slaveNode);
654        }
655
656        resourcesTreeView.Nodes.Add(additionalNode);
657      }
658
659      ExpandResourceNodesOfInterest(resourcesTreeView.Nodes);
660
661      resourcesTreeView.BeforeCheck += resourcesTreeView_BeforeCheck;
662      resourcesTreeView.AfterCheck += resourcesTreeView_AfterCheck;
663    }
664
665    private void ExpandResourceNodesOfInterest(TreeNodeCollection nodes) {
666      foreach(TreeNode n in nodes) {
667        Resource r = (Resource)n.Tag;
668        if(n.Nodes.Count > 0) {
669          if(HiveClient.Instance.GetAvailableResourceDescendants(r.Id).OfType<SlaveGroup>().Any()
670            || HiveClient.Instance.GetAvailableResourceDescendants(r.Id).OfType<Slave>().Intersect(assignedResources.Union(newAssignedResources)).Any()) {
671            n.Expand();
672            ExpandResourceNodesOfInterest(n.Nodes);
673          } else {
674            n.Collapse();
675          }   
676        } else {
677          n.Collapse();
678        }
679      }
680    }
681
682    private void CollapseSlaveOnlyNodes(TreeNode tn) {
683      if (!(tn.Tag is Resource)) return;
684
685      Resource r = (Resource)tn.Tag;
686      if (HiveClient.Instance.GetAvailableResourceDescendants(r.Id).OfType<SlaveGroup>().Any()) {
687        tn.Expand();
688        foreach (TreeNode n in tn.Nodes) CollapseSlaveOnlyNodes(n);
689      } else {
690        tn.Collapse();
691      }
692    }
693
694    private void ExtractStatistics(Resource resource = null) { 
695      HashSet<Slave> newAssignedSlaves = new HashSet<Slave>(newAssignedResources.OfType<Slave>());
696      foreach (var slaveGroup in newAssignedResources.OfType<SlaveGroup>()) {
697        foreach (var slave in HiveClient.Instance.GetAvailableResourceDescendants(slaveGroup.Id).OfType<Slave>()) {
698          newAssignedSlaves.Add(slave);
699        }
700      }
701
702      HashSet<Slave> selectedSlaves = null;
703
704      if (resource != null) {
705        var slaveGroup = resource as SlaveGroup;
706        if (slaveGroup != null) {
707          selectedSlaves = new HashSet<Slave>(HiveClient.Instance.GetAvailableResourceDescendants(slaveGroup.Id).OfType<Slave>());
708        } else {
709          selectedSlaves = new HashSet<Slave>(new[] { resource as Slave });
710        }
711      } else {
712        selectedSlaves = newAssignedSlaves;
713      }
714
715      int sumCores = selectedSlaves.Sum(x => x.Cores.GetValueOrDefault());
716      int sumFreeCores = selectedSlaves.Sum(x => x.FreeCores.GetValueOrDefault());
717      double sumMemory = selectedSlaves.Sum(x => x.Memory.GetValueOrDefault()) / 1024.0;
718      double sumFreeMemory = selectedSlaves.Sum(x => x.FreeMemory.GetValueOrDefault()) / 1024.0;
719
720      coresSummaryLabel.Text = string.Format("{0} Total ({1} Free / {2} Used)", sumCores, sumFreeCores, sumCores - sumFreeCores);
721      memorySummaryLabel.Text = string.Format("{0:0.00} GB Total ({1:0.00} GB Free / {2:0.00} GB Used)", sumMemory, sumFreeMemory, sumMemory - sumFreeMemory);
722    }
723
724    private void StyleTreeNode(TreeNode n, string name) {
725      n.Text = name;
726      n.BackColor = Color.Transparent;
727      n.ForeColor = Color.Black;
728
729      if(n.Tag is Project) {
730        var p = (Project)n.Tag;
731        if(HiveClient.Instance.DisabledParentProjects.Select(x => x.Id).Contains(p.Id)) {
732          n.Checked = false;
733          n.ForeColor = grayTextColor;
734        }
735      } else if(n.Tag is Resource) {
736        var r = (Resource)n.Tag;
737        if(HiveClient.Instance.DisabledParentResources.Select(x => x.Id).Contains(r.Id) || n == additionalNode) {
738          n.Checked = false;
739          n.ForeColor = grayTextColor;
740        }
741      }
742    }
743
744    private void ResetTreeNodes(TreeNodeCollection nodes) {
745      foreach (TreeNode n in nodes) {
746        string name = "";
747        if (n.Tag is Project) name = ((Project)n.Tag).Name;
748        else if (n.Tag is Resource) name = ((Resource)n.Tag).Name;
749        StyleTreeNode(n, name);
750        if (n.Nodes.Count > 0) {
751          ResetTreeNodes(n.Nodes);
752        }
753      }
754    }
755
756    private void SetTreeNodes(TreeNodeCollection nodes) {
757      var addedAssignments = newAssignedResources.Except(assignedResources);
758      var removedAssignments = assignedResources.Except(newAssignedResources);
759      var addedIncludes = newIncludedResources.Except(includedResources);
760      var removedIncludes = includedResources.Except(newIncludedResources);
761
762      foreach (TreeNode n in nodes) {
763
764        if(n.Tag is Resource) {
765          // reset
766          var resource = (Resource)n.Tag;
767          n.Text = resource.Name;
768          n.BackColor = Color.Transparent;
769          n.ForeColor = Color.Black;
770          n.Checked = false;
771
772          if (HiveClient.Instance.DisabledParentResources.Select(x => x.Id).Contains(resource.Id) || n == additionalNode) {
773            n.ForeColor = grayTextColor;
774          }
775
776          // add additional info
777          if (newAssignedResources.Select(x => x.Id).Contains(resource.Id)) {
778            n.Checked = true;
779            if (!addedAssignments.Select(x => x.Id).Contains(resource.Id) && !removedAssignments.Select(x => x.Id).Contains(resource.Id)) {
780              n.Text += SELECTED_TAG;
781            }
782          } else if (newIncludedResources.Select(x => x.Id).Contains(resource.Id)) {
783            n.Checked = true;
784            n.ForeColor = grayTextColor;
785          }
786
787          if (includedResources.Select(x => x.Id).Contains(resource.Id) && newIncludedResources.Select(x => x.Id).Contains(resource.Id)) {
788            n.Text += INCLUDED_TAG;
789          } else if (addedIncludes.Select(x => x.Id).Contains(resource.Id)) {
790            n.BackColor = addedIncludeColor;
791            n.ForeColor = grayTextColor;
792            n.Text += ADDED_INCLUDE_TAG;
793          } else if (removedIncludes.Select(x => x.Id).Contains(resource.Id)) {
794            n.BackColor = removedIncludeColor;
795            n.Text += REMOVED_INCLUDE_TAG;
796          }
797
798          if (addedAssignments.Select(x => x.Id).Contains(resource.Id)) {
799            n.BackColor = addedAssignmentColor;
800            n.ForeColor = controlTextColor;
801            n.Text += ADDED_SELECTION_TAG;
802          } else if (removedAssignments.Select(x => x.Id).Contains(resource.Id)) {
803            n.BackColor = removedAssignmentColor;
804            n.ForeColor = controlTextColor;
805            n.Text += REMOVED_SELECTION_TAG;
806          }
807        }
808
809        if(n.Nodes.Count > 0) {
810          SetTreeNodes(n.Nodes);
811        }
812      }
813    }
814
815    #endregion
816
817    #region Events
818    public event EventHandler SelectedProjectChanged;
819    private void OnSelectedProjectChanged() {
820      var handler = SelectedProjectChanged;
821      if (handler != null) handler(this, EventArgs.Empty);
822    }
823
824    public event EventHandler AssignedResourcesChanged;
825    private void OnAssignedResourcesChanged() {
826      var handler = AssignedResourcesChanged;
827      if (handler != null) handler(this, EventArgs.Empty);
828    }
829
830    public event EventHandler ProjectsTreeViewDoubleClicked;
831    private void OnProjectsTreeViewDoubleClicked() {
832      var handler = ProjectsTreeViewDoubleClicked;
833      if (handler != null) handler(this, EventArgs.Empty);
834    }
835    #endregion
836  }
837}
Note: See TracBrowser for help on using the repository browser.