Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectResourcesView.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectResourcesView.cs	(revision 15557)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectResourcesView.cs	(revision 15559)
@@ -40,6 +40,12 @@
 
     private readonly HashSet<Resource> assignedResources = new HashSet<Resource>();
+    private readonly HashSet<Resource> newAssignedResources = new HashSet<Resource>();
     private readonly HashSet<Resource> inheritedResources = new HashSet<Resource>();
-    private readonly Color ownedResourceColor = Color.LightGreen;
+    private readonly HashSet<Resource> newInheritedResources = new HashSet<Resource>();
+    private readonly Dictionary<Guid, HashSet<Resource>> resourceAncestors = new Dictionary<Guid, HashSet<Resource>>();
+    private readonly Dictionary<Guid, HashSet<Resource>> resourceDescendants = new Dictionary<Guid, HashSet<Resource>>();
+    //private readonly Color ownedResourceColor = Color.LightGreen;
+    private readonly Color changedAssignmentColor = Color.FromArgb(255, Color.LightGreen);
+    private readonly Color changedInheritanceColor = Color.FromArgb(255, Color.LightGray);
 
     public new Project Content {
@@ -60,14 +66,17 @@
       if (Content == null) {
         assignedResources.Clear();
+        newAssignedResources.Clear();
         inheritedResources.Clear();
+        resourceAncestors.Clear();
         treeView.Nodes.Clear();
         detailsViewHost.Content = null;
       } else {
         UpdateAssignedResources();
-        UpdateInheritedResources();
+        UpdateResourceGenealogy();
         var top = BuildResourceTree(HiveAdminClient.Instance.Resources);
         detailsViewHost.Content = top;
       }
     }
+
     #endregion
 
@@ -79,5 +88,5 @@
     private void refreshButton_Click(object sender, EventArgs e) {
       UpdateAssignedResources();
-      UpdateInheritedResources();
+      UpdateResourceGenealogy();
       var top = BuildResourceTree(HiveAdminClient.Instance.Resources);
       detailsViewHost.Content = top;
@@ -85,7 +94,8 @@
 
     private void inheritButton_Click(object sender, EventArgs e) {
+      return;
       SetAssignedProjectResources(Content.Id, Enumerable.Empty<Guid>());
       UpdateAssignedResources();
-      UpdateInheritedResources();
+      UpdateResourceGenealogy();
       var top = BuildResourceTree(HiveAdminClient.Instance.Resources);
       detailsViewHost.Content = top;
@@ -94,5 +104,8 @@
     private async void saveButton_Click(object sender, EventArgs e) {
       await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
-        action: () => SetAssignedProjectResources(Content.Id, assignedResources.Select(x => x.Id)));
+        action: () => {
+          SetAssignedProjectResources(Content.Id, newAssignedResources.Select(x => x.Id));
+        });
+      UpdateResourceTree();
     }
 
@@ -104,24 +117,43 @@
     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;
+      if (newInheritedResources.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);
+      if (e.Node.Checked) {
+        newAssignedResources.Add(checkedResource);
+      } else {
+        newAssignedResources.Remove(checkedResource);
+      }
+
+      UpdateNewAssignedResources();
+      UpdateNewInheritedResources();
+      var top = BuildResourceTree(HiveAdminClient.Instance.Resources);
+      detailsViewHost.Content = top;
     }
     #endregion
 
     #region Helpers
+
+    //private void DisableResourceTree(TreeNode node) {
+    //  foreach(var n in node.Nodes) {
+
+    //  }
+    //}
+
+    private void UpdateResourceTree() {
+      UpdateAssignedResources();
+      UpdateResourceGenealogy();
+      var top = BuildResourceTree(HiveAdminClient.Instance.Resources);
+      detailsViewHost.Content = top;
+    }
+
     private static IEnumerable<Resource> GetAssignedResourcesForProject(Guid projectId) {
       var assignedProjectResources = HiveServiceLocator.Instance.CallHiveService(s => s.GetAssignedResourcesForProject(projectId));
-      var resourceIds = new HashSet<Guid>(assignedProjectResources.Select(x => x.ResourceId));
-      return HiveAdminClient.Instance.Resources.Where(x => resourceIds.Contains(x.Id));
-    }
-
-    private static void SetAssignedProjectResources(Guid projectId, IEnumerable<Guid> resourceIds) {
+      return HiveAdminClient.Instance.Resources.Where(x => assignedProjectResources.Select(y => y.ResourceId).Contains(x.Id));
+    }
+
+    private void SetAssignedProjectResources(Guid projectId, IEnumerable<Guid> resourceIds) {
       HiveServiceLocator.Instance.CallHiveService(s => {
         var currentlyAssignedResources = s.GetAssignedResourcesForProject(projectId);
@@ -131,18 +163,73 @@
     }
 
+    private void UpdateNewAssignedResources() {
+      for(int i = newAssignedResources.Count -1; i >= 0; i--) {
+        if(newAssignedResources.Intersect(resourceAncestors[newAssignedResources.ElementAt(i).Id]).Any()) {
+          newAssignedResources.Remove(newAssignedResources.ElementAt(i));
+        }
+      }
+    }
+
     private void UpdateAssignedResources() {
       assignedResources.Clear();
-      foreach (var r in GetAssignedResourcesForProject(Content.Id))
+      newAssignedResources.Clear();
+      foreach (var r in GetAssignedResourcesForProject(Content.Id)) {
         assignedResources.Add(r);
-    }
-
-    private void UpdateInheritedResources() {
+        newAssignedResources.Add(r);
+      }
+    }
+
+    private void UpdateNewInheritedResources() {
+      newInheritedResources.Clear();
+      foreach (var a in newAssignedResources) {
+        if (resourceDescendants.ContainsKey(a.Id)) {
+          foreach (var r in resourceDescendants[a.Id]) {
+            newInheritedResources.Add(r);
+          }
+        }
+      }
+    }
+
+    private void UpdateResourceGenealogy() {
+      resourceAncestors.Clear();
+      resourceDescendants.Clear();
+      var resources = HiveAdminClient.Instance.Resources;
+
+      foreach(var r in resources) {
+        resourceAncestors.Add(r.Id, new HashSet<Resource>());
+        resourceDescendants.Add(r.Id, new HashSet<Resource>());
+      }
+
+      foreach(var r in resources) { 
+        var parentResourceId = r.ParentResourceId;
+        while(parentResourceId != null) {
+          var parent = resources.SingleOrDefault(x => x.Id == parentResourceId);
+          if(parent != null) {
+            resourceAncestors[r.Id].Add(parent);
+            resourceDescendants[parent.Id].Add(r);
+            parentResourceId = parent.ParentResourceId;
+          } else {
+            parentResourceId = null;
+          }
+        }
+      }
+
       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);
-      }
+      newInheritedResources.Clear();
+      foreach(var a in assignedResources) {
+        if (resourceDescendants.ContainsKey(a.Id)) {
+          foreach(var r in resourceDescendants[a.Id]) {
+            inheritedResources.Add(r);
+            newInheritedResources.Add(r);
+          }
+        }
+      }
+
+      //foreach(var r in resources) {
+      //  if (resourceAncestors.ContainsKey(r.Id)
+      //    && resourceAncestors[r.Id].Intersect(assignedResources.Select(x => x.Id)).Any()) {
+      //    inheritedResources.Add(r);
+      //  }
+      //}
     }
 
@@ -154,12 +241,17 @@
       treeView.AfterCheck -= treeView_AfterCheck;
 
-      var slaveGroups = new HashSet<SlaveGroup>(resources.OfType<SlaveGroup>());
-      var slaves = new HashSet<Slave>(resources.OfType<Slave>());
-
-      var stack = new Stack<Resource>(slaveGroups.OrderByDescending(x => x.Name));
+      var mainResources = new HashSet<Resource>(resources.OfType<SlaveGroup>().Where(x => x.ParentResourceId == null));
+      var subResources = new HashSet<Resource>(resources.Except(mainResources));
+
+      var stack = new Stack<Resource>(mainResources.OrderByDescending(x => x.Name));
       var top = stack.Peek();
 
       TreeNode currentNode = null;
       Resource currentResource = null;
+
+      var assignmentDiff = new HashSet<Resource>(newAssignedResources);
+      assignmentDiff.SymmetricExceptWith(assignedResources);
+      var inheritanceDiff = new HashSet<Resource>(newInheritedResources);
+      inheritanceDiff.SymmetricExceptWith(inheritedResources);
 
       while (stack.Any()) {
@@ -167,4 +259,7 @@
         var newNode = new TreeNode(newResource.Name) { Tag = newResource };
 
+        // search for parent node of newNode and save in currentNode
+        // necessary since newNodes (stack top items) might be siblings
+        // or grand..grandparents of previous node (currentNode)
         while (currentNode != null && newResource.ParentResourceId != currentResource.Id) {
           currentNode = currentNode.Parent;
@@ -178,4 +273,21 @@
         }
 
+
+        if (newAssignedResources.Contains(newResource)) {
+          newNode.Checked = true;
+        } else if (newInheritedResources.Contains(newResource)) {
+          newNode.Checked = true;
+          newNode.Text += " (Inherited)";
+          newNode.ForeColor = SystemColors.GrayText;
+        }
+
+        if (assignmentDiff.Contains(newResource)) {
+          newNode.BackColor = changedAssignmentColor;
+          newNode.Text += " [changed]";
+        } else if(inheritanceDiff.Contains(newResource)) {
+          newNode.BackColor = changedInheritanceColor;
+          newNode.Text += " [changed]";
+        }
+
         if (newResource is Slave) {
           newNode.ImageIndex = slaveImageIndex;
@@ -183,27 +295,9 @@
           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);
+          var childResources = subResources.Where(x => x.ParentResourceId == newResource.Id);
+          if (childResources.Any()) {
+            foreach (var resource in childResources.OrderByDescending(x => x.Name)) {
+              subResources.Remove(resource);
+              stack.Push(resource);
             }
             currentNode = newNode;
@@ -211,14 +305,7 @@
           }
         }
-
         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;
+        //if (newResource.OwnerUserId == UserInformation.Instance.User.Id)
+        //  newNode.BackColor = ownedResourceColor;
       }
 
@@ -231,5 +318,5 @@
       };
 
-      foreach (var slave in slaves.OrderBy(x => x.Name)) {
+      foreach (var slave in subResources.OfType<Slave>().OrderBy(x => x.Name)) {
         var slaveNode = new TreeNode(slave.Name) { Tag = slave };
         ungroupedNode.Nodes.Add(slaveNode);
@@ -243,4 +330,5 @@
       return top;
     }
+
     #endregion
   }
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectsView.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectsView.cs	(revision 15557)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectsView.cs	(revision 15559)
@@ -40,4 +40,6 @@
     private const int greenFlagImageIndex = 0;
     private const int redFlagImageIndex = 1;
+    private readonly Color changedColor = Color.FromArgb(255, Color.LightGreen);
+    private readonly Color selectedColor = Color.SkyBlue;
 
     private readonly object locker = new object();
@@ -246,4 +248,7 @@
     private void projectsTreeView_AfterSelect(object sender, TreeViewEventArgs e) {
       var selectedProject = (Project)e.Node.Tag;
+      ReColorTreeNodes(projectsTreeView.Nodes, selectedColor, Color.Transparent);
+      e.Node.BackColor = selectedColor;
+      
 
       if (projectView.Content != null)
@@ -317,4 +322,15 @@
 
     #region Helpers
+    private void ReColorTreeNodes(TreeNodeCollection nodes, Color c1, Color c2) {
+      foreach(TreeNode n in nodes) {
+        if(n.BackColor.Equals(c1)) {
+          n.BackColor = c2;
+        }
+        if (n.Nodes.Count > 0) {
+          ReColorTreeNodes(n.Nodes, c1, c2);
+        }
+      }
+    }
+
     private Project BuildProjectTree(IEnumerable<Project> projects) {
       projectsTreeView.Nodes.Clear();
@@ -326,11 +342,16 @@
       var stack = new Stack<Project>(mainProjects.OrderByDescending(x => x.Name));
       var top = stack.Peek();
+      bool first = true;
 
       TreeNode currentNode = null;
       Project currentProject = null;
-
+      
       while (stack.Any()) {
         var newProject = stack.Pop();
         var newNode = new TreeNode(newProject.Name) { Tag = newProject };
+        if (first) {
+          newNode.BackColor = selectedColor;
+          first = false;
+        }
 
         while (currentNode != null && newProject.ParentProjectId != currentProject.Id) {
