#region License Information
/* HeuristicLab
* Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeuristicLab is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HeuristicLab. If not, see .
*/
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using HeuristicLab.Clients.Access;
using HeuristicLab.Common.Resources;
using HeuristicLab.Core.Views;
using HeuristicLab.MainForm;
namespace HeuristicLab.Clients.Hive.Administrator.Views {
[View("ProjectView")]
[Content(typeof(Project), IsDefaultView = false)]
public partial class ProjectResourcesView : ItemView {
private const int slaveImageIndex = 0;
private const int slaveGroupImageIndex = 1;
public const string ungroupedGroupName = "UNGROUPED";
public const string ungroupedGroupDescription = "Contains slaves that are not assigned to any group.";
private readonly HashSet assignedResources = new HashSet();
private readonly HashSet inheritedResources = new HashSet();
private readonly Color ownedResourceColor = Color.LightGreen;
public new Project Content {
get { return (Project)base.Content; }
set { base.Content = value; }
}
public ProjectResourcesView() {
InitializeComponent();
treeView.ImageList.Images.Add(VSImageLibrary.MonitorLarge);
treeView.ImageList.Images.Add(VSImageLibrary.NetworkCenterLarge);
}
#region Overrides
protected override void OnContentChanged() {
base.OnContentChanged();
if (Content == null) {
assignedResources.Clear();
inheritedResources.Clear();
treeView.Nodes.Clear();
detailsViewHost.Content = null;
} else {
UpdateAssignedResources();
UpdateInheritedResources();
var top = BuildResourceTree(HiveAdminClient.Instance.Resources);
detailsViewHost.Content = top;
}
}
#endregion
#region Event Handlers
private void ProjectResourcesView_Load(object sender, EventArgs e) {
}
private void refreshButton_Click(object sender, EventArgs e) {
UpdateAssignedResources();
UpdateInheritedResources();
var top = BuildResourceTree(HiveAdminClient.Instance.Resources);
detailsViewHost.Content = top;
}
private void inheritButton_Click(object sender, EventArgs e) {
SetAssignedProjectResources(Content.Id, Enumerable.Empty());
UpdateAssignedResources();
UpdateInheritedResources();
var top = BuildResourceTree(HiveAdminClient.Instance.Resources);
detailsViewHost.Content = top;
}
private async void saveButton_Click(object sender, EventArgs e) {
await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
action: () => SetAssignedProjectResources(Content.Id, assignedResources.Select(x => x.Id)));
}
private void treeView_AfterSelect(object sender, TreeViewEventArgs e) {
var selectedResource = (Resource)e.Node.Tag;
detailsViewHost.Content = selectedResource;
}
private void treeView_BeforeCheck(object sender, TreeViewCancelEventArgs e) {
var checkedResource = (Resource)e.Node.Tag;
if (inheritedResources.Contains(checkedResource) || checkedResource.Id == Guid.Empty) e.Cancel = true;
}
private void treeView_AfterCheck(object sender, TreeViewEventArgs e) {
var checkedResource = (Resource)e.Node.Tag;
if (e.Node.Checked)
assignedResources.Add(checkedResource);
else
assignedResources.Remove(checkedResource);
}
#endregion
#region Helpers
private static IEnumerable GetAssignedResourcesForProject(Guid projectId) {
var assignedProjectResources = HiveServiceLocator.Instance.CallHiveService(s => s.GetAssignedResourcesForProject(projectId));
var resourceIds = new HashSet(assignedProjectResources.Select(x => x.ResourceId));
return HiveAdminClient.Instance.Resources.Where(x => resourceIds.Contains(x.Id));
}
private static void SetAssignedProjectResources(Guid projectId, IEnumerable resourceIds) {
HiveServiceLocator.Instance.CallHiveService(s => {
var currentlyAssignedResources = s.GetAssignedResourcesForProject(projectId);
s.UnassignProjectResources(projectId, currentlyAssignedResources.Select(x => x.ResourceId).ToList());
s.AssignProjectResources(projectId, resourceIds.ToList());
});
}
private void UpdateAssignedResources() {
assignedResources.Clear();
foreach (var r in GetAssignedResourcesForProject(Content.Id))
assignedResources.Add(r);
}
private void UpdateInheritedResources() {
inheritedResources.Clear();
var parentProject = HiveAdminClient.Instance.Projects.SingleOrDefault(x => x.Id == Content.ParentProjectId);
while (parentProject != null) {
foreach (var r in GetAssignedResourcesForProject(parentProject.Id))
inheritedResources.Add(r);
parentProject = HiveAdminClient.Instance.Projects.SingleOrDefault(x => x.Id == parentProject.ParentProjectId);
}
}
private Resource BuildResourceTree(IEnumerable resources) {
treeView.Nodes.Clear();
if (!resources.Any()) return null;
treeView.BeforeCheck -= treeView_BeforeCheck;
treeView.AfterCheck -= treeView_AfterCheck;
var slaveGroups = new HashSet(resources.OfType());
var slaves = new HashSet(resources.OfType());
var stack = new Stack(slaveGroups.OrderByDescending(x => x.Name));
var top = stack.Peek();
TreeNode currentNode = null;
Resource currentResource = null;
while (stack.Any()) {
var newResource = stack.Pop();
var newNode = new TreeNode(newResource.Name) { Tag = newResource };
while (currentNode != null && newResource.ParentResourceId != currentResource.Id) {
currentNode = currentNode.Parent;
currentResource = currentNode == null ? null : (Resource)currentNode.Tag;
}
if (currentNode == null) {
treeView.Nodes.Add(newNode);
} else {
currentNode.Nodes.Add(newNode);
}
if (newResource is Slave) {
newNode.ImageIndex = slaveImageIndex;
} else {
newNode.ImageIndex = slaveGroupImageIndex;
var childSlaves = slaves.Where(x => x.ParentResourceId == newResource.Id);
foreach (var slave in childSlaves.OrderBy(x => x.Name)) {
slaves.Remove(slave);
var slaveNode = new TreeNode(slave.Name) { Tag = slave };
slaveNode.SelectedImageIndex = slaveNode.ImageIndex = slaveImageIndex;
if (slave.OwnerUserId == UserInformation.Instance.User.Id)
slaveNode.BackColor = ownedResourceColor;
if (inheritedResources.Contains(slave)) {
slaveNode.Checked = true;
slaveNode.Text += " (Inherited)";
slaveNode.ForeColor = SystemColors.GrayText;
} else if (assignedResources.Contains(slave))
slaveNode.Checked = true;
newNode.Nodes.Add(slaveNode);
}
var childSlaveGroups = slaveGroups.Where(x => x.ParentResourceId == newResource.Id);
if (childSlaveGroups.Any()) {
foreach (var slaveGroup in childSlaveGroups.OrderByDescending(x => x.Name)) {
slaveGroups.Remove(slaveGroup);
stack.Push(slaveGroup);
}
currentNode = newNode;
currentResource = newResource;
}
}
newNode.SelectedImageIndex = newNode.ImageIndex;
if (newResource.OwnerUserId == UserInformation.Instance.User.Id)
newNode.BackColor = ownedResourceColor;
if (inheritedResources.Contains(newResource)) {
newNode.Checked = true;
newNode.Text += " (Inherited)";
newNode.ForeColor = SystemColors.GrayText;
} else if (assignedResources.Contains(newResource))
newNode.Checked = true;
}
var ungroupedNode = new TreeNode(ungroupedGroupName) {
ForeColor = SystemColors.GrayText,
Tag = new SlaveGroup() {
Name = ungroupedGroupName,
Description = ungroupedGroupDescription
}
};
foreach (var slave in slaves.OrderBy(x => x.Name)) {
var slaveNode = new TreeNode(slave.Name) { Tag = slave };
ungroupedNode.Nodes.Add(slaveNode);
}
treeView.Nodes.Add(ungroupedNode);
treeView.BeforeCheck += treeView_BeforeCheck;
treeView.AfterCheck += treeView_AfterCheck;
treeView.ExpandAll();
return top;
}
#endregion
}
}