Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
01/17/18 15:20:29 (6 years ago)
Author:
jzenisek
Message:

#2839 worked on Hive Job Manager: improved project/resource selector to show existent assignments and preserve selections

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.cs

    r15412 r15627  
    4040    private const int slaveImageIndex = 0;
    4141    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>();
     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
     46    private readonly HashSet<TreeNode> mainTreeNodes = new HashSet<TreeNode>();
     47    private readonly HashSet<TreeNode> filteredTreeNodes = new HashSet<TreeNode>();
     48    private readonly HashSet<TreeNode> nodeStore = new HashSet<TreeNode>();
     49
     50    private readonly HashSet<Resource> availableResources = new HashSet<Resource>();
     51    private readonly HashSet<Resource> assignedResources = new HashSet<Resource>();
     52    private readonly HashSet<Resource> includedResources = new HashSet<Resource>();
     53    private readonly HashSet<Resource> newAssignedResources = new HashSet<Resource>();
     54    private readonly HashSet<Resource> newIncludedResources = new HashSet<Resource>();
     55
     56    private readonly Dictionary<Guid, HashSet<Project>> projectAncestors = new Dictionary<Guid, HashSet<Project>>();
     57    private readonly Dictionary<Guid, HashSet<Project>> projectDescendants = new Dictionary<Guid, HashSet<Project>>();
     58    private readonly Dictionary<Guid, HashSet<Resource>> resourceAncestors = new Dictionary<Guid, HashSet<Resource>>();
     59    private readonly Dictionary<Guid, HashSet<Resource>> resourceDescendants = new Dictionary<Guid, HashSet<Resource>>();
     60
     61    private IEnumerable<Resource> addedResources;
     62    private IEnumerable<Resource> removedResources;
     63    private IEnumerable<Resource> addedIncludes;
     64    private IEnumerable<Resource> removedIncludes;
     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 selectedColor = Color.FromArgb(255, 240, 194, 59); // #f0c23b
    4771
    4872    private string currentSearchString;
    4973
     74    private Guid jobId;
     75    public Guid JobId {
     76      get { return jobId; }
     77      set {
     78        if (jobId == value) return;
     79        jobId = value;
     80      }
     81    }
     82
     83    private Guid? projectId;
     84    public Guid? ProjectId {
     85      get { return projectId; }
     86      set {
     87        if (projectId == value) return;
     88        projectId = value;
     89      }
     90    }
     91
     92    private Guid? selectedProjectId;
     93    public Guid? SelectedProjectId {
     94      get { return selectedProjectId; }
     95      set {
     96        if (selectedProjectId == value) return;
     97        selectedProjectId = value;
     98      }
     99    }
     100
     101    public bool ChangedProject {
     102      get {
     103        return (selectedProject == null || selectedProject.Id == projectId) ? false : true;
     104      }
     105    }
     106
     107    public bool ChangedProjectSelection {
     108      get {
     109        if ((lastSelectedProject == null && selectedProject != null)
     110          || (lastSelectedProject != null && selectedProject == null)
     111          || (lastSelectedProject != null && selectedProject != null && lastSelectedProject.Id != selectedProject.Id))
     112          return true;
     113        else return false;
     114      }
     115    }
     116
     117    public bool ChangedResources {
     118      get { return !assignedResources.SetEquals(newAssignedResources); }
     119    }
     120
     121    private Project lastSelectedProject;
    50122    private Project selectedProject;
    51123    public Project SelectedProject {
    52124      get { return selectedProject; }
    53125      set {
     126        lastSelectedProject = selectedProject;
    54127        if (selectedProject == value) return;
    55128        selectedProject = value;
    56         UpdateResources();
     129        UpdateResourceTree();
    57130        OnSelectedProjectChanged();
    58131      }
    59132    }
    60 
    61     private readonly IObservableSet<Resource> selectedResources = new ObservableSet<Resource>();
    62     public IEnumerable<Resource> SelectedResources { get { return selectedResources; } }
     133    public IEnumerable<Resource> AssignedResources {
     134      get { return newAssignedResources; }
     135      set {
     136        if (newAssignedResources == value) return;
     137        newAssignedResources.Clear();
     138        foreach(var resource in value) {
     139          newAssignedResources.Add(resource);
     140        }
     141      }
     142    }
    63143
    64144    public new IItemList<Project> Content {
     
    80160      base.OnContentChanged();
    81161
    82       if (Content != null) {
    83         UpdateMainTree();
    84         ExtractStatistics();
     162      if (Content != null) {       
     163        UpdateProjectGenealogy();
     164        UpdateResourceGenealogy();
     165       
     166        if (SelectedProjectId.HasValue) {
     167          SelectedProject = GetSelectedProjectById(SelectedProjectId.Value);
     168        } else {
     169          SelectedProject = null;
     170        }
     171        UpdateProjectTree();
     172
    85173      } else {
    86         mainTreeNodes.Clear();
    87         UpdateFilteredTree();
    88       }
    89 
    90       SelectedProject = null;
    91     }
     174        projectsTreeView.Nodes.Clear();
     175        resourcesTreeView.Nodes.Clear();
     176      }
     177    }
     178
    92179    #endregion
    93180
     
    96183      projectsTreeView.Nodes.Clear();
    97184      resourcesTreeView.Nodes.Clear();
    98       SelectedProject = null;
     185      //SelectedProject = null;
    99186    }
    100187
    101188    private void searchTextBox_TextChanged(object sender, EventArgs e) {
    102189      currentSearchString = searchTextBox.Text.ToLower();
    103       UpdateFilteredTree();
     190      //UpdateFilteredTree();
     191      UpdateProjectTree();
    104192    }
    105193
     
    108196    }
    109197
    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 
     198    private void projectsTreeView_AfterSelect(object sender, TreeViewEventArgs e) {
     199      var node = (Project)e.Node.Tag;
     200     
    115201      if (node == null) {
    116202        projectsTreeView.SelectedNode = null;
     203      } else {
     204        ReColorTreeNodes(projectsTreeView.Nodes, selectedColor, Color.Transparent, true);
     205        e.Node.BackColor = selectedColor;
     206       
     207        if(node.Id == projectId) {
     208          e.Node.Text += " [current selection]";
     209        } else if(projectId == null || projectId == Guid.Empty) {
     210          e.Node.Text += " [new selection]";
     211        } else {
     212          e.Node.Text += " [changed selection]";
     213        }
     214
     215        SelectedProject = node;
    117216      }
    118217
     
    130229    }
    131230
     231    private void resourcesTreeView_BeforeCheck(object sender, TreeViewCancelEventArgs e) {
     232      var checkedResource = (Resource)e.Node.Tag;
     233      if (newIncludedResources.Contains(checkedResource) || checkedResource.Id == Guid.Empty) e.Cancel = true;
     234    }
     235
    132236    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();
     237      var checkedResource = (Resource)e.Node.Tag;
     238      if (e.Node.Checked) {
     239        newAssignedResources.Add(checkedResource);
     240      } else {
     241        newAssignedResources.Remove(checkedResource);
     242      }
     243
     244      UpdateNewResourceTree();
     245      //ExtractStatistics((Resource)resourcesTreeView.SelectedNode?.Tag);
     246      OnAssignedResourcesChanged();
     247    }
     248
     249    private void resourcesTreeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) {
     250      return;
    142251    }
    143252    #endregion
    144253
    145254    #region Helpers
     255
     256
     257    #region old
    146258    private void UpdateMainTree() {
    147259      mainTreeNodes.Clear();
     
    155267          tn.Tag = g;
    156268          tn.Text = g.Name;
    157           tn.Checked = selectedResources.Any(x => x.Id == g.Id);
     269          tn.Checked = assignedResources.Any(x => x.Id == g.Id);
    158270
    159271          BuildMainTree(tn);
     
    170282        stn.SelectedImageIndex = stn.ImageIndex;
    171283        stn.Tag = r;
    172         stn.Checked = selectedResources.Any(x => x.Id == r.Id);
     284        stn.Checked = assignedResources.Any(x => x.Id == r.Id);
    173285        tn.Nodes.Add(stn);
    174286        mainTreeNodes.Add(stn);
     
    224336      }
    225337    }
    226 
    227     private void UpdateResources() {
    228       selectedResources.Clear();
    229 
     338    #endregion
     339
     340    private Project GetSelectedProjectById(Guid projectId) {
     341      return Content.Where(x => x.Id == projectId).SingleOrDefault();
     342    }
     343
     344    private void UpdateProjectTree() {
     345
     346      if (string.IsNullOrEmpty(currentSearchString)) {
     347        BuildProjectTree(Content);
     348      } else {
     349        HashSet<Project> filteredProjects = new HashSet<Project>();
     350        foreach(var project in Content) {
     351          if(project.Name.ToLower().Contains(currentSearchString.ToLower())) {
     352            filteredProjects.Add(project);
     353            filteredProjects.UnionWith(projectAncestors[project.Id]);
     354          }
     355        }
     356        BuildProjectTree(filteredProjects);
     357      }
     358    }
     359
     360    private void BuildProjectTree(IEnumerable<Project> projects) {
     361      projectsTreeView.Nodes.Clear();
     362      if (!projects.Any()) return;
     363
     364      // select all top level projects (withouth parent, or without parent within current project collection)
     365      var mainProjects = new HashSet<Project>(projects.Where(x => x.ParentProjectId == null));
     366      var parentedMainProjects = new HashSet<Project>(projects
     367        .Where(x => x.ParentProjectId.HasValue
     368        && !projects.Select(y => y.Id).Contains(x.ParentProjectId.Value)));
     369      mainProjects.UnionWith(parentedMainProjects);
     370      var subProbjects = new HashSet<Project>(projects.Except(mainProjects));
     371
     372      var stack = new Stack<Project>(mainProjects.OrderByDescending(x => x.Name));
     373
     374      TreeNode currentNode = null;
     375      Project currentProject = null;
     376
     377      while(stack.Any()) {
     378        var newProject = stack.Pop();
     379        var newNode = new TreeNode(newProject.Name) { Tag = newProject };
     380
     381        while (currentNode != null && newProject.ParentProjectId != currentProject.Id) {
     382          currentNode = currentNode.Parent;
     383          currentProject = currentNode == null ? null : (Project)currentNode.Tag;
     384        }
     385
     386        if (currentNode == null) {
     387          projectsTreeView.Nodes.Add(newNode);
     388          newNode.ImageIndex = greenFlagImageIndex;
     389        } else {
     390          currentNode.Nodes.Add(newNode);
     391          newNode.ImageIndex = redFlagImageIndex;
     392        }
     393
     394        newNode.SelectedImageIndex = newNode.ImageIndex;
     395
     396        if (SelectedProject != null && SelectedProject.Id.Equals(newProject.Id)) {
     397          newNode.BackColor = selectedColor;
     398          if(SelectedProject.Id == projectId) {
     399            newNode.Text += " [current selection]";
     400          } else if (projectId == null || projectId == Guid.Empty) {
     401            newNode.Text += " [new selection]";
     402          } else {
     403            newNode.Text += " [changed selection]";
     404          }
     405        }
     406
     407        if (!string.IsNullOrEmpty(currentSearchString) && newProject.Name.ToLower().Contains(currentSearchString.ToLower())) {
     408          newNode.BackColor = Color.LightBlue;
     409        }
     410
     411        var childProjects = subProbjects.Where(x => x.ParentProjectId == newProject.Id);
     412        if (childProjects.Any()) {
     413          foreach (var project in childProjects.OrderByDescending(x => x.Name)) {
     414            subProbjects.Remove(project);
     415            stack.Push(project);
     416          }
     417          currentNode = newNode;
     418          currentProject = newProject;
     419        }
     420      }
     421
     422      projectsTreeView.ExpandAll();
     423    }
     424
     425    private void UpdateProjectGenealogy() {
     426      projectAncestors.Clear();
     427      projectDescendants.Clear();
     428      var projects = Content;
     429
     430      foreach (var p in projects) {
     431        projectAncestors.Add(p.Id, new HashSet<Project>());
     432        projectDescendants.Add(p.Id, new HashSet<Project>());
     433      }
     434
     435      foreach (var p in projects) {
     436        var parentProjectId = p.ParentProjectId;
     437        while (parentProjectId != null) {
     438          var parent = projects.SingleOrDefault(x => x.Id == parentProjectId);
     439          if (parent != null) {
     440            projectAncestors[p.Id].Add(parent);
     441            projectDescendants[parent.Id].Add(p);
     442            parentProjectId = parent.ParentProjectId;
     443          } else {
     444            parentProjectId = null;
     445          }
     446        }
     447      }
     448    }
     449
     450
     451    private static IEnumerable<Resource> GetAssignedResourcesForProject(Guid projectId) {
     452      var assignedProjectResources = HiveServiceLocator.Instance.CallHiveService(s => s.GetAssignedResourcesForProject(projectId));
     453      return HiveAdminClient.Instance.Resources.Where(x => assignedProjectResources.Select(y => y.ResourceId).Contains(x.Id));
     454    }
     455
     456    private static IEnumerable<Resource> GetAssignedResourcesForJob(Guid jobId) {
     457      var assignedJobResources = HiveServiceLocator.Instance.CallHiveService(s => s.GetAssignedResourcesForJob(jobId));
     458      return HiveAdminClient.Instance.Resources.Where(x => assignedJobResources.Select(y => y.ResourceId).Contains(x.Id));
     459    }
     460
     461    private void UpdateResourceTree() {
     462      UpdateAvailableResources();
     463      UpdateAssignedResources();
     464      UpdateIncludedResources();
     465      BuildResourceTree(availableResources);
     466    }
     467
     468    private void UpdateNewResourceTree() {
     469      UpdateNewAssignedResources();
     470      UpdateNewIncludedResources();
     471      BuildResourceTree(availableResources);
     472    }
     473
     474    private void UpdateAvailableResources() {
     475      availableResources.Clear();
    230476      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);
     477        var assignedProjectResources = GetAssignedResourcesForProject(selectedProject.Id);
     478        foreach (var resource in assignedProjectResources) {
     479          availableResources.Add(resource);
     480          foreach(var descendant in resourceDescendants[resource.Id]) {
     481            availableResources.Add(descendant);
     482          }
     483        }
     484      }
    243485      ExtractStatistics();
    244       OnSelectedResourcesChanged();
    245     }
    246 
    247     private Resource BuildResourceTree(IEnumerable<Resource> resources) {
     486      //OnAssignedResourcesChanged();
     487    }
     488
     489    private void UpdateAssignedResources() {
     490
     491      if (JobId == Guid.Empty && ChangedProjectSelection) { // new, unchanged jobs get all avaialable resources
     492        // update new assigned resources
     493        assignedResources.Clear();
     494        newAssignedResources.Clear();
     495        foreach (var resource in availableResources
     496          .Where(x => !x.ParentResourceId.HasValue
     497          || !availableResources.Select(y => y.Id).Contains(x.ParentResourceId.Value))) {
     498          newAssignedResources.Add(resource);
     499        }
     500
     501      } else if(JobId != Guid.Empty) { // existent, unchanged jobs get all assigned resources
     502        // update assigned resources
     503        var assignedJobResources = GetAssignedResourcesForJob(JobId);
     504        foreach (var resource in assignedJobResources) {
     505          assignedResources.Add(resource);
     506        }
     507
     508        if(ChangedProjectSelection) {
     509          newAssignedResources.Clear();
     510          foreach (var resource in assignedJobResources) {
     511            newAssignedResources.Add(resource);
     512          }
     513        }
     514      } else {
     515        var newAssignedResourceIds = newAssignedResources.Select(x => x.Id).ToList();
     516        newAssignedResources.Clear();
     517        foreach(var r in availableResources.Where(x => newAssignedResourceIds.Contains(x.Id))) {
     518          newAssignedResources.Add(r);
     519        }
     520      }
     521
     522      ExtractStatistics();
     523      OnAssignedResourcesChanged();
     524    }
     525
     526    private void UpdateNewAssignedResources() {
     527      for(int i = newAssignedResources.Count-1; i>=0; i--) {
     528        if(newAssignedResources.Intersect(resourceAncestors[newAssignedResources.ElementAt(i).Id]).Any()) {
     529          newAssignedResources.Remove(newAssignedResources.ElementAt(i));
     530        }
     531      }
     532    }
     533
     534    private void UpdateIncludedResources() {
     535      includedResources.Clear();
     536      newIncludedResources.Clear();
     537      if (JobId != Guid.Empty) {
     538        foreach (var item in assignedResources) {
     539          foreach (var descendant in resourceDescendants[item.Id]) {
     540            includedResources.Add(descendant);
     541            newIncludedResources.Add(descendant);
     542          }
     543        }
     544      } else {
     545        foreach (var item in newAssignedResources) {
     546          foreach (var descendant in resourceDescendants[item.Id]) {
     547            newIncludedResources.Add(descendant);
     548          }
     549        }
     550      }
     551    }
     552
     553    private void UpdateNewIncludedResources() {
     554      newIncludedResources.Clear();
     555      foreach (var item in newAssignedResources) {
     556        foreach (var descendant in resourceDescendants[item.Id]) {
     557          newIncludedResources.Add(descendant);
     558        }
     559      }
     560    }
     561
     562    private void UpdateResourceGenealogy() {
     563      resourceAncestors.Clear();
     564      resourceDescendants.Clear();
     565      var resources = HiveAdminClient.Instance.Resources;
     566
     567      foreach (var r in resources) {
     568        resourceAncestors.Add(r.Id, new HashSet<Resource>());
     569        resourceDescendants.Add(r.Id, new HashSet<Resource>());
     570      }
     571
     572      foreach (var r in resources) {
     573        var parentResourceId = r.ParentResourceId;
     574        while (parentResourceId != null) {
     575          var parent = resources.SingleOrDefault(x => x.Id == parentResourceId);
     576          if (parent != null) {
     577            resourceAncestors[r.Id].Add(parent);
     578            resourceDescendants[parent.Id].Add(r);
     579            parentResourceId = parent.ParentResourceId;
     580          } else {
     581            parentResourceId = null;
     582          }
     583        }
     584      }
     585    }
     586
     587    private void BuildResourceTree(IEnumerable<Resource> resources) {
     588      resourcesTreeView.Nodes.Clear();
     589      if (!resources.Any()) return;
     590
     591      resourcesTreeView.BeforeCheck -= resourcesTreeView_BeforeCheck;
     592      resourcesTreeView.AfterCheck -= resourcesTreeView_AfterCheck;
     593
     594      var mainResources = new HashSet<Resource>(resources.OfType<SlaveGroup>().Where(x => x.ParentResourceId == null));
     595      var parentedMainResources = new HashSet<Resource>(resources.OfType<SlaveGroup>()
     596        .Where(x => x.ParentResourceId.HasValue && !resources.Select(y => y.Id).Contains(x.ParentResourceId.Value)));
     597      mainResources.UnionWith(parentedMainResources);
     598      var subResources = new HashSet<Resource>(resources.Except(mainResources));
     599
     600      var addedAssignments = newAssignedResources.Except(assignedResources);
     601      var removedAssignments = assignedResources.Except(newAssignedResources);
     602      var addedIncludes = newIncludedResources.Except(includedResources);
     603      var removedIncludes = includedResources.Except(newIncludedResources);
     604
     605      HashSet<TreeNode> expandedNodes = new HashSet<TreeNode>();
     606      TreeNode currentNode = null;
     607      Resource currentResource = null;
     608
     609      var stack = new Stack<Resource>(mainResources.OrderByDescending(x => x.Name));
     610
     611      while (stack.Any()) {
     612        var newResource = stack.Pop();
     613        var newNode = new TreeNode(newResource.Name) { Tag = newResource };
     614
     615        // search for parent node of newNode and save in currentNode
     616        // necessary since newNodes (stack top items) might be siblings
     617        // or grand..grandparents of previous node (currentNode)
     618        while (currentNode != null && newResource.ParentResourceId != currentResource.Id) {
     619          currentNode = currentNode.Parent;
     620          currentResource = currentNode == null ? null : (Resource)currentNode.Tag;
     621        }
     622
     623        if (currentNode == null) {
     624          resourcesTreeView.Nodes.Add(newNode);
     625        } else {
     626          currentNode.Nodes.Add(newNode);
     627        }
     628
     629        if(newAssignedResources.Select(x => x.Id).Contains(newResource.Id)
     630          || assignedResources.Select(x => x.Id).Contains(newResource.Id)
     631          || newIncludedResources.Select(x => x.Id).Contains(newResource.Id)
     632          || includedResources.Select(x => x.Id).Contains(newResource.Id)) {
     633          expandedNodes.Add(newNode);
     634        }
     635
     636        if (newAssignedResources.Select(x => x.Id).Contains(newResource.Id)) {
     637          newNode.Checked = true;
     638        } else if (newIncludedResources.Select(x => x.Id).Contains(newResource.Id)) {
     639          newNode.Checked = true;
     640          newNode.ForeColor = SystemColors.GrayText;
     641        }
     642
     643        if (includedResources.Select(x => x.Id).Contains(newResource.Id) && newIncludedResources.Select(x => x.Id).Contains(newResource.Id)) {
     644          newNode.Text += " [included]";
     645        } else if (addedIncludes.Select(x => x.Id).Contains(newResource.Id)) {
     646          newNode.BackColor = addedIncludeColor;
     647          newNode.ForeColor = SystemColors.GrayText;
     648          newNode.Text += " [added include]";
     649        } else if (removedIncludes.Select(x => x.Id).Contains(newResource.Id)) {
     650          newNode.BackColor = removedIncludeColor;
     651          newNode.Text += " [removed include]";
     652        }
     653
     654        if (addedAssignments.Select(x => x.Id).Contains(newResource.Id)) {
     655          newNode.BackColor = addedAssignmentColor;
     656          newNode.ForeColor = SystemColors.ControlText;
     657          newNode.Text += " [added selection]";
     658        } else if (removedAssignments.Select(x => x.Id).Contains(newResource.Id)) {
     659          newNode.BackColor = removedAssignmentColor;
     660          newNode.ForeColor = SystemColors.ControlText;
     661          newNode.Text += " [removed selection]";
     662        }
     663
     664        if (newResource is Slave) {
     665          newNode.ImageIndex = slaveImageIndex;
     666        } else {
     667          newNode.ImageIndex = slaveGroupImageIndex;
     668
     669          var childResources = subResources.Where(x => x.ParentResourceId == newResource.Id);
     670          if (childResources.Any()) {
     671            foreach (var resource in childResources.OrderByDescending(x => x.Name)) {
     672              subResources.Remove(resource);
     673              stack.Push(resource);
     674            }
     675            currentNode = newNode;
     676            currentResource = newResource;
     677          }
     678        }
     679        newNode.SelectedImageIndex = newNode.ImageIndex;
     680      }
     681
     682      var singleSlaves = subResources.OfType<Slave>();
     683      if (singleSlaves.Any()) {
     684
     685        var additionalNode = new TreeNode(additionalSlavesGroupName) {
     686          ForeColor = SystemColors.GrayText,
     687          Tag = new SlaveGroup() {
     688            Name = additionalSlavesGroupName,
     689            Description = additionalSlavesGroupDescription
     690          }
     691        };
     692
     693        foreach (var slave in singleSlaves.OrderBy(x => x.Name)) {
     694          var slaveNode = new TreeNode(slave.Name) { Tag = slave };
     695          additionalNode.Nodes.Add(slaveNode);
     696        }
     697
     698        resourcesTreeView.Nodes.Add(additionalNode);
     699      }
     700
     701     
     702      foreach (var node in expandedNodes) {
     703        node.Expand();
     704        var parent = node.Parent;
     705        while(parent != null) {
     706          parent.Expand();
     707          parent = parent.Parent;
     708        }
     709      }
     710
     711      resourcesTreeView.BeforeCheck += resourcesTreeView_BeforeCheck;
     712      resourcesTreeView.AfterCheck += resourcesTreeView_AfterCheck;
     713      //resourcesTreeView.ExpandAll();
     714    }
     715
     716    private void ExpandSlaveGroupNodes() {
     717      foreach (TreeNode n in nodeStore.Where(x => x.Tag is SlaveGroup)) {
     718        TreeNode[] children = new TreeNode[n.Nodes.Count];
     719        n.Nodes.CopyTo(children, 0);
     720        if (children.Any(x => x.Tag is SlaveGroup)) n.Expand();
     721      }
     722    }
     723
     724    private void ExtractStatistics(Resource resource = null) {
     725      ISet<Slave> selectedSlaves = null;
     726
     727      if (resource != null) {
     728
     729
     730        var slaveGroup = resource as SlaveGroup;
     731        if (slaveGroup != null) {
     732          selectedSlaves = new HashSet<Slave>(resourceDescendants[slaveGroup.Id].OfType<Slave>());
     733          selectedSlaves.IntersectWith(newAssignedResources.OfType<Slave>());
     734        } else {
     735          selectedSlaves = new HashSet<Slave>(new[] { resource as Slave });
     736        }
     737      } else {
     738        selectedSlaves = new HashSet<Slave>(newAssignedResources.OfType<Slave>());
     739      }
     740
     741      int sumCores = selectedSlaves.OfType<Slave>().Sum(x => x.Cores.GetValueOrDefault());
     742      int sumFreeCores = selectedSlaves.OfType<Slave>().Sum(x => x.FreeCores.GetValueOrDefault());
     743      double sumMemory = selectedSlaves.OfType<Slave>().Sum(x => x.Memory.GetValueOrDefault()) / 1024.0;
     744      double sumFreeMemory = selectedSlaves.OfType<Slave>().Sum(x => x.FreeMemory.GetValueOrDefault()) / 1024.0;
     745
     746      coresSummaryLabel.Text = $"{sumCores} Total ({sumFreeCores} Free / {sumCores - sumFreeCores} Used)";
     747      memorySummaryLabel.Text = $"{sumMemory:0.00} GB Total ({sumFreeMemory:0.00} GB Free / {(sumMemory - sumFreeMemory):0.00} GB Used)";
     748    }
     749
     750    private void ReColorTreeNodes(TreeNodeCollection nodes, Color c1, Color c2, bool resetText) {
     751      foreach (TreeNode n in nodes) {
     752        if (n.BackColor.Equals(c1)) {
     753          n.BackColor = c2;
     754          if(resetText) n.Text = ((Project)n.Tag).Name;
     755        }
     756        if (n.Nodes.Count > 0) {
     757          ReColorTreeNodes(n.Nodes, c1, c2, resetText);
     758        }
     759      }
     760    }
     761
     762    private void ExtractStatistics_Old(Resource resource = null) {
     763      ISet<Slave> selectedSlaves = null;
     764
     765      if (resource != null) {
     766        var slaveGroup = resource as SlaveGroup;
     767        if (slaveGroup != null) {
     768          var children = new HashSet<Resource>(availableResources.Where(x => x.ParentResourceId == slaveGroup.Id));
     769          int nrOfChildren = children.Count;
     770          do {
     771            var newChildren = availableResources.Where(x => children.Any(y => y.Id == x.ParentResourceId));
     772            foreach (var newChild in newChildren)
     773              children.Add(newChild);
     774          } while (children.Count > nrOfChildren);
     775          selectedSlaves = new HashSet<Slave>(children.OfType<Slave>());
     776          selectedSlaves.IntersectWith(assignedResources.OfType<Slave>());
     777        } else {
     778          selectedSlaves = new HashSet<Slave>(new[] { resource as Slave });
     779        }
     780      } else {
     781        selectedSlaves = new HashSet<Slave>(assignedResources.OfType<Slave>());
     782      }
     783
     784      int sumCores = selectedSlaves.OfType<Slave>().Sum(x => x.Cores.GetValueOrDefault());
     785      int sumFreeCores = selectedSlaves.OfType<Slave>().Sum(x => x.FreeCores.GetValueOrDefault());
     786      double sumMemory = selectedSlaves.OfType<Slave>().Sum(x => x.Memory.GetValueOrDefault()) / 1024.0;
     787      double sumFreeMemory = selectedSlaves.OfType<Slave>().Sum(x => x.FreeMemory.GetValueOrDefault()) / 1024.0;
     788
     789      coresSummaryLabel.Text = $"{sumCores} Total ({sumFreeCores} Free / {sumCores - sumFreeCores} Used)";
     790      memorySummaryLabel.Text = $"{sumMemory:0.00} GB Total ({sumFreeMemory:0.00} GB Free / {(sumMemory - sumFreeMemory):0.00} GB Used)";
     791    }
     792
     793    private Resource BuildResourceTree_Old(IEnumerable<Resource> resources) {
    248794      resourcesTreeView.Nodes.Clear();
    249795      if (!resources.Any()) return null;
     
    295841    }
    296842
    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     }
    335843    #endregion
    336844
     
    341849    }
    342850
    343     public event EventHandler SelectedResourcesChanged;
    344     private void OnSelectedResourcesChanged() {
    345       SelectedResourcesChanged?.Invoke(this, EventArgs.Empty);
     851    public event EventHandler AssignedResourcesChanged;
     852    private void OnAssignedResourcesChanged() {
     853      AssignedResourcesChanged?.Invoke(this, EventArgs.Empty);
    346854    }
    347855
Note: See TracChangeset for help on using the changeset viewer.