Index: /branches/2877_HiveImprovements/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.cs
===================================================================
--- /branches/2877_HiveImprovements/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.cs	(revision 15612)
+++ /branches/2877_HiveImprovements/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.cs	(revision 15613)
@@ -48,4 +48,6 @@
     private const int slaveGroupImageIndex = 1;
     private readonly Color ownedResourceColor = Color.LightGreen;
+    private readonly Color calculatingColor = Color.DarkGreen;
+    private readonly Color offlineColor = Color.Red;
     private TS.Task progressTask;
     private bool stopProgressTask;
@@ -136,58 +138,78 @@
 
         //rebuild
-        TreeNode ungrp = new TreeNode(UngroupedGroupName);
-        ungrp.ImageIndex = slaveGroupImageIndex;
-        ungrp.SelectedImageIndex = ungrp.ImageIndex;
-        var newGroup = new SlaveGroup();
-        newGroup.Name = UngroupedGroupName;
-        newGroup.Id = Guid.NewGuid();
-        newGroup.Description = "Contains slaves which are in no group";
-        ungrp.Tag = newGroup;
-
-        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;
-              if (g.OwnerUserId == Access.UserInformation.Instance.User.Id) tn.BackColor = ownedResourceColor;
-
-              BuildSlaveGroupTree(g, tn);
-              treeSlaveGroup.Nodes.Add(tn);
-            }
-          } else if (g.GetType() == typeof(Slave)) {
-            if (g.ParentResourceId == null) {
-              var stn = new TreeNode(g.Name);
-              stn.ImageIndex = slaveImageIndex;
-              stn.SelectedImageIndex = stn.ImageIndex;
-              stn.Tag = g;
-              if (g.OwnerUserId == Access.UserInformation.Instance.User.Id) stn.BackColor = ownedResourceColor;
-              ungrp.Nodes.Add(stn);
-            }
-          }
-        }
-        treeSlaveGroup.Nodes.Add(ungrp);
-      }
-    }
-
-    private void BuildSlaveGroupTree(Resource g, TreeNode tn) {
-      foreach (Resource r in Content.Where(s => s.ParentResourceId != null && s.ParentResourceId == g.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;
-        if (r.OwnerUserId == Access.UserInformation.Instance.User.Id) stn.BackColor = ownedResourceColor;
-        tn.Nodes.Add(stn);
-
-        BuildSlaveGroupTree(r, stn);
-      }
+        var ungroupedSlaves = new SlaveGroup {
+          Id = Guid.NewGuid(),
+          Name = UngroupedGroupName,
+          Description = "Slaves without a group"
+        };
+        var ungroupedSlavesCount = 0;
+        var ungroupedNode = CreateTreeNodeFromResource(ungroupedSlaves);
+
+        var parentlessResources = from r in Content
+                                  where r.ParentResourceId == null
+                                  orderby r.Name
+                                  select r;
+        foreach (Resource r in parentlessResources) {
+          if (r.GetType() == typeof(SlaveGroup)) {  // root node
+            var root = CreateTreeNodeFromResource(r);
+            treeSlaveGroup.Nodes.Add(root);
+            BuildSlaveGroupTree((SlaveGroup)r, root);
+          } else if (r.GetType() == typeof(Slave)) {  // ungrouped slaves
+            ungroupedNode.Nodes.Add(CreateTreeNodeFromResource(r));
+            ungroupedSlavesCount++;
+          }
+        }
+        if (ungroupedSlavesCount > 0)
+          ungroupedNode.Text += "   [" + ungroupedSlavesCount.ToString() + "]";
+        treeSlaveGroup.Nodes.Add(ungroupedNode);
+      }
+    }
+
+    private void BuildSlaveGroupTree(SlaveGroup group, TreeNode node) {
+      var childGroups = from r in Content.OfType<SlaveGroup>()
+                        where r.ParentResourceId == @group.Id
+                        orderby r.Name
+                        select r;
+      foreach (var g in childGroups) {
+        var childNode = CreateTreeNodeFromResource(g);
+        node.Nodes.Add(childNode);
+        BuildSlaveGroupTree(g, childNode);
+      }
+
+      var childSlaves = from r in Content.OfType<Slave>()
+                        where r.ParentResourceId == @group.Id
+                        orderby r.Name
+                        select r;
+      foreach (var s in childSlaves)
+        node.Nodes.Add(CreateTreeNodeFromResource(s));
+      var childSlavesCount = childSlaves.Count();
+      if (childSlavesCount > 0)
+        node.Text += "   [" + childSlavesCount.ToString() + "]";
+    }
+
+    private TreeNode CreateTreeNodeFromResource(Resource r) {
+      var node = new TreeNode();
+      node.Text = r.Name;
+
+      if (r is SlaveGroup) {
+        node.ImageIndex = slaveGroupImageIndex;
+      } else if (r is Slave) {
+        var s = r as Slave;
+        node.ImageIndex = slaveImageIndex;
+        if (s.SlaveState == SlaveState.Calculating) {
+          node.ForeColor = calculatingColor;
+          node.Text += "   [" + s.CpuUtilization.ToString("N2") + " %]";
+        } else if (s.SlaveState == SlaveState.Offline) {
+          node.ForeColor = offlineColor;
+          if (s.LastHeartbeat.HasValue)
+            node.Text += "   [" + s.LastHeartbeat?.ToString("g") + "]";
+        }
+      }
+      node.SelectedImageIndex = node.ImageIndex;
+
+      if (r.OwnerUserId == Access.UserInformation.Instance.User.Id) node.BackColor = ownedResourceColor;
+
+      node.Tag = r;
+      return node;
     }
 
