Changeset 15627


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

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

Location:
branches/HiveProjectManagement
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectResourcesView.cs

    r15576 r15627  
    152152
    153153    private static IEnumerable<Resource> GetAssignedResourcesForProject(Guid projectId) {
    154       var assignedProjectResources = HiveServiceLocator.Instance.CallHiveService(s => s.GetAssignedResourcesForProject(projectId));
     154      var assignedProjectResources = HiveServiceLocator.Instance.CallHiveService(s => s.GetAssignedResourcesForProjectAdministration(projectId));
    155155      return HiveAdminClient.Instance.Resources.Where(x => assignedProjectResources.Select(y => y.ResourceId).Contains(x.Id));
    156156    }
     
    242242
    243243      var mainResources = new HashSet<Resource>(resources.OfType<SlaveGroup>().Where(x => x.ParentResourceId == null));
     244      var parentedMainResources = new HashSet<Resource>(resources.OfType<SlaveGroup>()
     245        .Where(x => x.ParentResourceId.HasValue && !resources.Select(y => y.Id).Contains(x.ParentResourceId.Value)));
     246      mainResources.UnionWith(parentedMainResources);
    244247      var subResources = new HashSet<Resource>(resources.Except(mainResources));
    245248
    246249      var stack = new Stack<Resource>(mainResources.OrderByDescending(x => x.Name));
    247       var top = stack.Peek();
     250      Resource top = null;
    248251
    249252      TreeNode currentNode = null;
     
    262265
    263266      while (stack.Any()) {
     267        if(top == null)  top = stack.Peek();
    264268        var newResource = stack.Pop();
    265269        var newNode = new TreeNode(newResource.Name) { Tag = newResource };
  • branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectsView.cs

    r15567 r15627  
    4545    private readonly object locker = new object();
    4646
     47    private Project selectedProject = null;
     48
    4749    public new IItemList<Project> Content {
    4850      get { return (IItemList<Project>)base.Content; }
     
    190192
    191193    private void addButton_Click(object sender, EventArgs e) {
     194      Guid? parentProjectId = null;
     195      if (selectedProject != null) parentProjectId = selectedProject.Id;
    192196      var project = new Project {
    193197        Name = "New Project",
    194         OwnerUserId = UserInformation.Instance.User.Id
     198        OwnerUserId = UserInformation.Instance.User.Id,
     199        ParentProjectId = parentProjectId
    195200      };
    196201      Content.Add(project);
     
    244249        },
    245250        finallyCallback: () => saveProjectButton.Enabled = true);
     251
     252      OnContentChanged();
    246253    }
    247254
    248255    private void projectsTreeView_AfterSelect(object sender, TreeViewEventArgs e) {
    249       var selectedProject = (Project)e.Node.Tag;
    250       ReColorTreeNodes(projectsTreeView.Nodes, selectedColor, Color.Transparent);
     256      selectedProject = (Project)e.Node.Tag;
     257      ReColorTreeNodes(projectsTreeView.Nodes, selectedColor, Color.Transparent, true);
    251258      e.Node.BackColor = selectedColor;
     259      e.Node.Text += " [selected]";
    252260     
    253261
    254       if (projectView.Content != null)
    255         projectView.Content.PropertyChanged -= ProjectViewContent_PropertyChanged;
     262      //if (projectView.Content != null)
     263      //  projectView.Content.PropertyChanged -= ProjectViewContent_PropertyChanged;
    256264
    257265      projectView.Content = selectedProject;
     
    259267      projectResourcesView.Content = selectedProject;
    260268
    261       if (selectedProject != null)
    262         selectedProject.PropertyChanged += ProjectViewContent_PropertyChanged;
     269      //if (selectedProject != null)
     270      //  selectedProject.PropertyChanged += ProjectViewContent_PropertyChanged;
    263271
    264272      if (IsAuthorized(selectedProject)) {
     
    322330
    323331    #region Helpers
    324     private void ReColorTreeNodes(TreeNodeCollection nodes, Color c1, Color c2) {
     332    private void ReColorTreeNodes(TreeNodeCollection nodes, Color c1, Color c2, bool resetText) {
    325333      foreach(TreeNode n in nodes) {
    326334        if(n.BackColor.Equals(c1)) {
    327335          n.BackColor = c2;
     336          if (resetText) n.Text = ((Project)n.Tag).Name;
    328337        }
    329338        if (n.Nodes.Count > 0) {
    330           ReColorTreeNodes(n.Nodes, c1, c2);
     339          ReColorTreeNodes(n.Nodes, c1, c2, resetText);
    331340        }
    332341      }
     
    338347
    339348      var mainProjects = new HashSet<Project>(projects.Where(x => x.ParentProjectId == null));
     349      var parentedMainProjects = new HashSet<Project>(projects
     350        .Where(x => x.ParentProjectId.HasValue
     351        && !projects.Select(y => y.Id).Contains(x.ParentProjectId.Value)));
     352            mainProjects.UnionWith(parentedMainProjects);
    340353      var subProbjects = new HashSet<Project>(projects.Except(mainProjects));
    341354
    342355      var stack = new Stack<Project>(mainProjects.OrderByDescending(x => x.Name));
    343       var top = stack.Peek();
    344       bool first = true;
     356      Project top = null;
    345357
    346358      TreeNode currentNode = null;
     
    350362        var newProject = stack.Pop();
    351363        var newNode = new TreeNode(newProject.Name) { Tag = newProject };
    352         if (first) {
     364        if (top == null) {
     365          top = newProject;
    353366          newNode.BackColor = selectedColor;
    354           first = false;
     367          newNode.Text += " [selected]";
    355368        }
    356369
  • branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.Designer.cs

    r15412 r15627  
    147147      this.projectsTreeView.TabIndex = 3;
    148148      this.projectsTreeView.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.projectsTreeView_MouseDoubleClick);
    149       this.projectsTreeView.MouseDown += new System.Windows.Forms.MouseEventHandler(this.projectsTreeView_MouseDown);
     149      this.projectsTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.projectsTreeView_AfterSelect);
    150150      //
    151151      // resourcesTreeView
     
    160160      this.resourcesTreeView.Size = new System.Drawing.Size(206, 410);
    161161      this.resourcesTreeView.TabIndex = 0;
     162      this.resourcesTreeView.NodeMouseDoubleClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.resourcesTreeView_NodeMouseDoubleClick);
     163      this.resourcesTreeView.BeforeCheck += new System.Windows.Forms.TreeViewCancelEventHandler(this.resourcesTreeView_BeforeCheck);
    162164      this.resourcesTreeView.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.resourcesTreeView_AfterCheck);
    163165      this.resourcesTreeView.MouseDown += new System.Windows.Forms.MouseEventHandler(this.resourcesTreeView_MouseDown);
  • 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
  • branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelectorDialog.Designer.cs

    r15412 r15627  
    9898      this.hiveResourceSelector.TabIndex = 0;
    9999      this.hiveResourceSelector.SelectedProjectChanged += new System.EventHandler(this.hiveResourceSelector_SelectedProjectChanged);
    100       this.hiveResourceSelector.SelectedResourcesChanged += new System.EventHandler(this.hiveResourceSelector_SelectedResourcesChanged);
     100      this.hiveResourceSelector.AssignedResourcesChanged += new System.EventHandler(this.hiveResourceSelector_SelectedResourcesChanged);
    101101      this.hiveResourceSelector.ProjectsTreeViewDoubleClicked += new System.EventHandler(this.hiveResourceSelector_ProjectsTreeViewDoubleClicked);
    102102      //
  • branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelectorDialog.cs

    r15412 r15627  
    2727using HeuristicLab.Clients.Hive.Views;
    2828using HeuristicLab.MainForm;
     29using HeuristicLab.Core;
    2930
    3031namespace HeuristicLab.Clients.Hive.JobManager.Views {
     
    3839
    3940    public IEnumerable<Resource> SelectedResources {
    40       get { return hiveResourceSelector.SelectedResources; }
     41      get { return hiveResourceSelector.AssignedResources; }
    4142    }
    4243
    43     public HiveResourceSelectorDialog() {
     44    private Guid jobId;
     45    public Guid JobId {
     46      get { return hiveResourceSelector.JobId; }
     47      set { jobId = value; }
     48    }
     49
     50    // persisted projectId
     51    private Guid? projectId;
     52    public Guid? ProjectId {
     53      get { return hiveResourceSelector.ProjectId; }
     54      set { projectId = value; }
     55    }
     56
     57    // currently selected projectId (initially persisted projectId)
     58    private Guid? selectedProjectId;
     59    public Guid? SelectedProjectId {
     60      get { return selectedProjectId; }
     61      set { selectedProjectId = value; }
     62    }
     63
     64
     65    public HiveResourceSelectorDialog(Guid jobId, Guid projectId) {
     66      this.jobId = jobId;
     67      this.projectId = projectId;
     68      this.selectedProjectId = projectId;
    4469      InitializeComponent();
    4570    }
     
    105130
    106131    private void hiveResourceSelector_SelectedResourcesChanged(object sender, EventArgs e) {
    107       okButton.Enabled = hiveResourceSelector.SelectedResources.Any();
     132      okButton.Enabled = hiveResourceSelector.AssignedResources.Any();
    108133    }
    109134
     
    119144    private void UpdateProjects() {
    120145      HiveAdminClient.Instance.Refresh();
    121       hiveResourceSelector.Content = HiveAdminClient.Instance.Projects;
     146      hiveResourceSelector.JobId = jobId;
     147      hiveResourceSelector.ProjectId = projectId;
     148      hiveResourceSelector.SelectedProjectId = selectedProjectId;
     149      var projectList = new ItemList<Project>(HiveServiceLocator.Instance.CallHiveService(s => s.GetProjects()));
     150      hiveResourceSelector.Content = projectList;
    122151    }
    123152
  • branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/RefreshableHiveJobView.cs

    r15412 r15627  
    3333using HeuristicLab.Optimization;
    3434using HeuristicLab.PluginInfrastructure;
     35using System.Collections.Generic;
    3536
    3637namespace HeuristicLab.Clients.Hive.JobManager.Views {
     
    4445    private bool SuppressEvents { get; set; }
    4546    private object runCollectionViewLocker = new object();
     47    private Project selectedProject;
    4648
    4749    public new RefreshableJob Content {
     
    129131          nameTextBox.Text = Content.Job.Name;
    130132          executionTimeTextBox.Text = Content.ExecutionTime.ToString();
    131           //resourceNamesTextBox.Text = Content.Job.ResourceNames;
    132133          refreshAutomaticallyCheckBox.Checked = Content.RefreshAutomatically;
     134
     135          // project look up
     136          if(Content.Job.ProjectId != null && Content.Job.ProjectId != Guid.Empty) {
     137            selectedProject = GetProject(Content.Job.ProjectId);
     138            if(selectedProject != null) {
     139              projectNameTextBox.Text = selectedProject.Name;
     140            } else {
     141              projectNameTextBox.Text = string.Empty;
     142            }
     143          } else {
     144            selectedProject = null;
     145            projectNameTextBox.Text = string.Empty;
     146          }
     147         
    133148          logView.Content = Content.Log;
    134149          lock (runCollectionViewLocker) {
     
    330345    #region Control events
    331346    private void searchButton_Click(object sender, EventArgs e) {
    332       if (hiveResourceSelectorDialog == null)
    333         hiveResourceSelectorDialog = new HiveResourceSelectorDialog();
     347      if (hiveResourceSelectorDialog == null) {
     348        hiveResourceSelectorDialog = new HiveResourceSelectorDialog(Content.Job.Id, Content.Job.ProjectId);
     349      } else if(selectedProject != null) {
     350        hiveResourceSelectorDialog.SelectedProjectId = Content.Job.ProjectId;
     351      } else {
     352        hiveResourceSelectorDialog.SelectedProjectId = null;
     353      }
    334354
    335355      if (hiveResourceSelectorDialog.ShowDialog(this) == DialogResult.OK) {
    336         var selectedProject = hiveResourceSelectorDialog.SelectedProject;
    337         projectNameTextBox.Text = selectedProject.Name;
    338         Content.Job.ProjectId = selectedProject.Id;
    339         Content.Job.ResourceIds = hiveResourceSelectorDialog.SelectedResources.Select(x => x.Id).ToList();
     356        selectedProject = hiveResourceSelectorDialog.SelectedProject;
     357        if(selectedProject != null) {
     358          projectNameTextBox.Text = selectedProject.Name;
     359          Content.Job.ProjectId = selectedProject.Id;
     360          Content.Job.ResourceIds = hiveResourceSelectorDialog.SelectedResources.Select(x => x.Id).ToList();
     361        } else {
     362          projectNameTextBox.Text = string.Empty;
     363          Content.Job.ProjectId = Guid.Empty;
     364          Content.Job.ResourceIds = null;
     365        }
    340366      }
    341367    }
     
    344370      if (nameTextBox.Text.Trim() == string.Empty) {
    345371        MessageBox.Show("Please enter a name for the job before uploading it!", "HeuristicLab Hive Job Manager", MessageBoxButtons.OK, MessageBoxIcon.Information);
     372      } else if (Content.Job.ProjectId == null || Content.Job.ProjectId == Guid.Empty) {
     373        MessageBox.Show("Please select a project before uploading the job!", "HeuristicLab Hive Job Manager", MessageBoxButtons.OK, MessageBoxIcon.Information);
     374      } else if (Content.Job.ResourceIds == null || !Content.Job.ResourceIds.Any()) {
     375        MessageBox.Show("Please select resources before uploading the job!", "HeuristicLab Hive Job Manager", MessageBoxButtons.OK, MessageBoxIcon.Information);
    346376      } else if (Content.ExecutionState == ExecutionState.Paused) {
    347377        var task = System.Threading.Tasks.Task.Factory.StartNew(ResumeJobAsync, Content);
     
    436466      }
    437467    }
     468   
     469    private Project GetProject(Guid projectId) {
     470      return HiveServiceLocator.Instance.CallHiveService(s => s.GetProject(projectId));
     471    }
    438472    #endregion
    439473
Note: See TracChangeset for help on using the changeset viewer.