Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2839_HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.cs @ 15978

Last change on this file since 15978 was 15978, checked in by jzenisek, 6 years ago

#2839: applied several fixes:

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