#region License Information
/* HeuristicLab
* Copyright (C) 2002-2018 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.Text;
using System.Windows.Forms;
using HeuristicLab.Clients.Hive.JobManager.ExtensionMethods;
using HeuristicLab.Core;
using HeuristicLab.Core.Views;
using HeuristicLab.MainForm;
using HeuristicLab.MainForm.WindowsForms;
namespace HeuristicLab.Clients.Hive.JobManager.Views {
[View("Hive Resource Selector View")]
[Content(typeof(IItemList), true)]
public partial class HiveResourceSelector : ItemView, IDisposable {
private const int slaveImageIndex = 0;
private const int slaveGroupImageIndex = 1;
private string currentSearchString;
private ISet mainTreeNodes;
private ISet filteredTreeNodes;
private ISet nodeStore;
private ISet selectedResources;
public ISet SelectedResources {
get { return selectedResources; }
set { selectedResources = value; }
}
public new IItemList Content {
get { return (IItemList)base.Content; }
set { base.Content = value; }
}
public HiveResourceSelector() {
InitializeComponent();
mainTreeNodes = new HashSet();
filteredTreeNodes = new HashSet();
nodeStore = new HashSet();
selectedResources = new HashSet();
imageList.Images.Add(HeuristicLab.Common.Resources.VSImageLibrary.MonitorLarge);
imageList.Images.Add(HeuristicLab.Common.Resources.VSImageLibrary.NetworkCenterLarge);
}
public void StartProgressView() {
if (InvokeRequired) {
Invoke(new Action(StartProgressView));
} else {
var message = "Downloading resources. Please be patient.";
MainFormManager.GetMainForm().AddOperationProgressToView(this, message);
}
}
public void FinishProgressView() {
if (InvokeRequired) {
Invoke(new Action(FinishProgressView));
} else {
MainFormManager.GetMainForm().RemoveOperationProgressFromView(this);
}
}
protected override void OnContentChanged() {
base.OnContentChanged();
if (Content != null) {
selectedResources = new HashSet(Content.Where(x => selectedResources.Any(y => x.Id == y.Id)));
UpdateMainTree();
ExtractStatistics();
} else {
mainTreeNodes.Clear();
UpdateFilteredTree();
}
}
#region MainTree Methods
private void UpdateMainTree() {
mainTreeNodes.Clear();
foreach (Resource g in Content) {
if (g.GetType() == typeof(SlaveGroup)) {
//root node
if (g.ParentResourceId == null) {
TreeNode tn = new TreeNode();
tn.ImageIndex = slaveGroupImageIndex;
tn.SelectedImageIndex = tn.ImageIndex;
tn.Tag = g;
tn.Text = g.Name;
tn.Checked = selectedResources.Any(x => x.Id == g.Id);
BuildMainTree(tn);
mainTreeNodes.Add(tn);
}
}
}
UpdateFilteredTree();
}
private void BuildMainTree(TreeNode tn) {
foreach (Resource r in Content.Where(s => s.ParentResourceId != null && s.ParentResourceId == ((Resource)tn.Tag).Id)) {
TreeNode stn = new TreeNode(r.Name);
if (r is Slave) stn.ImageIndex = slaveImageIndex;
else if (r is SlaveGroup) stn.ImageIndex = slaveGroupImageIndex;
stn.SelectedImageIndex = stn.ImageIndex;
stn.Tag = r;
stn.Checked = selectedResources.Any(x => x.Id == r.Id);
tn.Nodes.Add(stn);
mainTreeNodes.Add(stn);
BuildMainTree(stn);
}
}
#endregion
#region FilteredTree Methods
private void UpdateFilteredTree() {
filteredTreeNodes.Clear();
foreach (TreeNode n in mainTreeNodes) {
n.BackColor = SystemColors.Window;
if (currentSearchString == null || ((Resource)n.Tag).Name.ToLower().Contains(currentSearchString)) {
n.BackColor = string.IsNullOrEmpty(currentSearchString) ? SystemColors.Window : Color.LightBlue;
filteredTreeNodes.Add(n);
TraverseParentNodes(n);
}
}
UpdateResourceTree();
}
private void TraverseParentNodes(TreeNode node) {
if (node != null) {
for (TreeNode parent = node.Parent; parent != null; parent = parent.Parent)
filteredTreeNodes.Add(parent);
}
}
#endregion
#region ResourceTree Methods
private void UpdateResourceTree() {
resourcesTreeView.Nodes.Clear();
nodeStore.Clear();
foreach (TreeNode node in filteredTreeNodes) {
var clone = nodeStore.SingleOrDefault(x => ((Resource)x.Tag).Id == ((Resource)node.Tag).Id);
if (clone == null) {
clone = (TreeNode)node.Clone();
nodeStore.Add(clone);
clone.Nodes.Clear();
}
foreach (TreeNode child in node.Nodes)
if (filteredTreeNodes.Any(x => ((Resource)x.Tag).Id == ((Resource)child.Tag).Id)) {
var childClone = nodeStore.SingleOrDefault(x => ((Resource)x.Tag).Id == ((Resource)child.Tag).Id);
if (childClone == null) {
childClone = (TreeNode)child.Clone();
nodeStore.Add(childClone);
childClone.Nodes.Clear();
}
clone.Nodes.Add(childClone);
}
}
resourcesTreeView.Nodes.AddRange(nodeStore.Where(x => ((Resource)x.Tag).ParentResourceId == null).ToArray());
if (string.IsNullOrEmpty(currentSearchString)) ExpandSlaveGroupNodes();
else resourcesTreeView.ExpandAll();
}
#endregion
#region Events
private void resourcesTreeView_AfterCheck(object sender, TreeViewEventArgs e) {
if (e.Action != TreeViewAction.Unknown) {
if (e.Node.Checked) {
IncludeChildNodes(mainTreeNodes.SingleOrDefault(x => ((Resource)x.Tag).Id == ((Resource)e.Node.Tag).Id));
IncludeParentNodes(mainTreeNodes.SingleOrDefault(x => ((Resource)x.Tag).Id == ((Resource)e.Node.Tag).Id));
} else {
ExcludeChildNodes(mainTreeNodes.SingleOrDefault(x => ((Resource)x.Tag).Id == ((Resource)e.Node.Tag).Id));
ExcludeParentNodes(mainTreeNodes.SingleOrDefault(x => ((Resource)x.Tag).Id == ((Resource)e.Node.Tag).Id));
}
ExtractStatistics();
}
}
private void resourcesTreeView_AfterSelect(object sender, TreeViewEventArgs e) {
if (e.Action != TreeViewAction.Unknown) {
ExtractStatistics(e.Node);
}
}
private void searchTextBox_TextChanged(object sender, System.EventArgs e) {
currentSearchString = searchTextBox.Text.ToLower();
UpdateFilteredTree();
}
#endregion
#region Helpers
private void IncludeChildNodes(TreeNode node) {
if (node != null) {
node.Checked = true;
selectedResources.Add((Resource)node.Tag);
AdjustNodeCheckedState(node);
foreach (TreeNode n in node.Nodes) IncludeChildNodes(n);
}
}
private void IncludeParentNodes(TreeNode node) {
if (node != null && node.Parent != null) {
TreeNode parent = node.Parent;
if (parent.Nodes.OfType().All(x => x.Checked)) {
parent.Checked = true;
selectedResources.Add((Resource)parent.Tag);
AdjustNodeCheckedState(parent);
IncludeParentNodes(parent);
}
}
}
private void ExcludeChildNodes(TreeNode node) {
if (node != null) {
node.Checked = false;
selectedResources.Remove((Resource)node.Tag);
AdjustNodeCheckedState(node);
foreach (TreeNode n in node.Nodes) ExcludeChildNodes(n);
}
}
private void ExcludeParentNodes(TreeNode node) {
if (node != null) {
node.Checked = false;
selectedResources.Remove((Resource)node.Tag);
AdjustNodeCheckedState(node);
ExcludeParentNodes(node.Parent);
}
}
private void AdjustNodeCheckedState(TreeNode node) {
var filterdNode = filteredTreeNodes.SingleOrDefault(x => ((Resource)x.Tag).Id == ((Resource)node.Tag).Id);
var storedNode = nodeStore.SingleOrDefault(x => ((Resource)x.Tag).Id == ((Resource)node.Tag).Id);
if (filterdNode != null) filterdNode.Checked = node.Checked;
if (storedNode != null) storedNode.Checked = node.Checked;
}
private void ExpandSlaveGroupNodes() {
foreach (TreeNode n in nodeStore.Where(x => x.Tag is SlaveGroup)) {
TreeNode[] children = new TreeNode[n.Nodes.Count];
n.Nodes.CopyTo(children, 0);
if (children.Any(x => x.Tag is SlaveGroup)) n.Expand();
}
}
private void ExtractStatistics(TreeNode treeNode = null) {
StringBuilder sb = new StringBuilder();
Resource resource = treeNode == null ? null : treeNode.Tag as Resource;
ISet resources = treeNode == null ? selectedResources : new HashSet(treeNode.DescendantNodes().Select(x => x.Tag as Resource)); ;
IEnumerable slaveGroups = resources.OfType();
IEnumerable slaves = resources.OfType();
int cpuSpeed = 0, cores = 0, freeCores = 0, memory = 0, freeMemory = 0;
string contextString = treeNode == null ? "Selected" : "Included";
if (resources.Any() || resource != null) {
foreach (Slave s in slaves) {
cpuSpeed += s.CpuSpeed.GetValueOrDefault();
cores += s.Cores.GetValueOrDefault();
freeCores += s.FreeCores.GetValueOrDefault();
memory += s.Memory.GetValueOrDefault();
freeMemory += s.FreeMemory.GetValueOrDefault();
}
if (resource != null) {
if (resource is SlaveGroup) sb.Append("Slave group: ");
else if (resource is Slave) {
sb.Append("Slave: ");
if (!resources.Any()) {
Slave s = resource as Slave;
cpuSpeed = s.CpuSpeed.GetValueOrDefault();
cores = s.Cores.GetValueOrDefault();
freeCores = s.FreeCores.GetValueOrDefault();
memory = s.Memory.GetValueOrDefault();
freeMemory = s.FreeMemory.GetValueOrDefault();
}
}
sb.AppendLine(string.Format("{0}", resource.Name));
}
if (resource == null || resource is SlaveGroup) {
if (resources.Any()) {
sb.AppendFormat("{0} slave groups ({1}): ", contextString, slaveGroups.Count());
foreach (SlaveGroup sg in slaveGroups) sb.AppendFormat("{0}; ", sg.Name);
sb.AppendLine();
sb.AppendFormat("{0} slaves ({1}): ", contextString, slaves.Count());
foreach (Slave s in slaves) sb.AppendFormat("{0}; ", s.Name);
sb.AppendLine();
} else {
sb.Append("The selection does not inlcude any further resources.");
}
}
sb.AppendLine();
sb.AppendLine(string.Format("CPU speed: {0} MHz", cpuSpeed));
if (resources.Any()) sb.AppendLine(string.Format("Avg. CPU speed: {0:0.00} MHz", (double)cpuSpeed / resources.Count()));
sb.AppendLine(string.Format("Cores: {0}", cores));
sb.AppendLine(string.Format("Free cores: {0}", freeCores));
if (resources.Any()) sb.AppendLine(string.Format("Avg. free cores: {0:0.00}", (double)freeCores / resources.Count()));
sb.AppendLine(string.Format("Memory: {0} MB", memory));
sb.AppendFormat("Free memory: {0} MB", freeMemory);
if (resources.Any()) sb.Append(string.Format("{0}Avg. free memory: {1:0.00} MB", Environment.NewLine, (double)freeMemory / resources.Count()));
} else {
sb.Append("No resources selected.");
}
descriptionTextBox.Text = sb.ToString();
}
#endregion
}
}