Index: /branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectResourcesView.cs
===================================================================
--- /branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectResourcesView.cs	(revision 15626)
+++ /branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectResourcesView.cs	(revision 15627)
@@ -152,5 +152,5 @@
 
     private static IEnumerable<Resource> GetAssignedResourcesForProject(Guid projectId) {
-      var assignedProjectResources = HiveServiceLocator.Instance.CallHiveService(s => s.GetAssignedResourcesForProject(projectId));
+      var assignedProjectResources = HiveServiceLocator.Instance.CallHiveService(s => s.GetAssignedResourcesForProjectAdministration(projectId));
       return HiveAdminClient.Instance.Resources.Where(x => assignedProjectResources.Select(y => y.ResourceId).Contains(x.Id));
     }
@@ -242,8 +242,11 @@
 
       var mainResources = new HashSet<Resource>(resources.OfType<SlaveGroup>().Where(x => x.ParentResourceId == null));
+      var parentedMainResources = new HashSet<Resource>(resources.OfType<SlaveGroup>()
+        .Where(x => x.ParentResourceId.HasValue && !resources.Select(y => y.Id).Contains(x.ParentResourceId.Value)));
+      mainResources.UnionWith(parentedMainResources);
       var subResources = new HashSet<Resource>(resources.Except(mainResources));
 
       var stack = new Stack<Resource>(mainResources.OrderByDescending(x => x.Name));
-      var top = stack.Peek();
+      Resource top = null;
 
       TreeNode currentNode = null;
@@ -262,4 +265,5 @@
 
       while (stack.Any()) {
+        if(top == null)  top = stack.Peek();
         var newResource = stack.Pop();
         var newNode = new TreeNode(newResource.Name) { Tag = newResource };
Index: /branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectsView.cs
===================================================================
--- /branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectsView.cs	(revision 15626)
+++ /branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectsView.cs	(revision 15627)
@@ -45,4 +45,6 @@
     private readonly object locker = new object();
 
+    private Project selectedProject = null;
+
     public new IItemList<Project> Content {
       get { return (IItemList<Project>)base.Content; }
@@ -190,7 +192,10 @@
 
     private void addButton_Click(object sender, EventArgs e) {
+      Guid? parentProjectId = null;
+      if (selectedProject != null) parentProjectId = selectedProject.Id;
       var project = new Project {
         Name = "New Project",
-        OwnerUserId = UserInformation.Instance.User.Id
+        OwnerUserId = UserInformation.Instance.User.Id,
+        ParentProjectId = parentProjectId
       };
       Content.Add(project);
@@ -244,14 +249,17 @@
         },
         finallyCallback: () => saveProjectButton.Enabled = true);
+
+      OnContentChanged();
     }
 
     private void projectsTreeView_AfterSelect(object sender, TreeViewEventArgs e) {
-      var selectedProject = (Project)e.Node.Tag;
-      ReColorTreeNodes(projectsTreeView.Nodes, selectedColor, Color.Transparent);
+      selectedProject = (Project)e.Node.Tag;
+      ReColorTreeNodes(projectsTreeView.Nodes, selectedColor, Color.Transparent, true);
       e.Node.BackColor = selectedColor;
+      e.Node.Text += " [selected]";
       
 
-      if (projectView.Content != null)
-        projectView.Content.PropertyChanged -= ProjectViewContent_PropertyChanged;
+      //if (projectView.Content != null)
+      //  projectView.Content.PropertyChanged -= ProjectViewContent_PropertyChanged;
 
       projectView.Content = selectedProject;
@@ -259,6 +267,6 @@
       projectResourcesView.Content = selectedProject;
 
-      if (selectedProject != null)
-        selectedProject.PropertyChanged += ProjectViewContent_PropertyChanged;
+      //if (selectedProject != null)
+      //  selectedProject.PropertyChanged += ProjectViewContent_PropertyChanged;
 
       if (IsAuthorized(selectedProject)) {
@@ -322,11 +330,12 @@
 
     #region Helpers
-    private void ReColorTreeNodes(TreeNodeCollection nodes, Color c1, Color c2) {
+    private void ReColorTreeNodes(TreeNodeCollection nodes, Color c1, Color c2, bool resetText) {
       foreach(TreeNode n in nodes) {
         if(n.BackColor.Equals(c1)) {
           n.BackColor = c2;
+          if (resetText) n.Text = ((Project)n.Tag).Name;
         }
         if (n.Nodes.Count > 0) {
-          ReColorTreeNodes(n.Nodes, c1, c2);
+          ReColorTreeNodes(n.Nodes, c1, c2, resetText);
         }
       }
@@ -338,9 +347,12 @@
 
       var mainProjects = new HashSet<Project>(projects.Where(x => x.ParentProjectId == null));
+      var parentedMainProjects = new HashSet<Project>(projects
+        .Where(x => x.ParentProjectId.HasValue
+        && !projects.Select(y => y.Id).Contains(x.ParentProjectId.Value)));
+            mainProjects.UnionWith(parentedMainProjects);
       var subProbjects = new HashSet<Project>(projects.Except(mainProjects));
 
       var stack = new Stack<Project>(mainProjects.OrderByDescending(x => x.Name));
-      var top = stack.Peek();
-      bool first = true;
+      Project top = null;
 
       TreeNode currentNode = null;
@@ -350,7 +362,8 @@
         var newProject = stack.Pop();
         var newNode = new TreeNode(newProject.Name) { Tag = newProject };
-        if (first) {
+        if (top == null) {
+          top = newProject;
           newNode.BackColor = selectedColor;
-          first = false;
+          newNode.Text += " [selected]";
         }
 
Index: /branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.Designer.cs
===================================================================
--- /branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.Designer.cs	(revision 15626)
+++ /branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.Designer.cs	(revision 15627)
@@ -147,5 +147,5 @@
       this.projectsTreeView.TabIndex = 3;
       this.projectsTreeView.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.projectsTreeView_MouseDoubleClick);
-      this.projectsTreeView.MouseDown += new System.Windows.Forms.MouseEventHandler(this.projectsTreeView_MouseDown);
+      this.projectsTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.projectsTreeView_AfterSelect);
       // 
       // resourcesTreeView
@@ -160,4 +160,6 @@
       this.resourcesTreeView.Size = new System.Drawing.Size(206, 410);
       this.resourcesTreeView.TabIndex = 0;
+      this.resourcesTreeView.NodeMouseDoubleClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.resourcesTreeView_NodeMouseDoubleClick);
+      this.resourcesTreeView.BeforeCheck += new System.Windows.Forms.TreeViewCancelEventHandler(this.resourcesTreeView_BeforeCheck);
       this.resourcesTreeView.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.resourcesTreeView_AfterCheck);
       this.resourcesTreeView.MouseDown += new System.Windows.Forms.MouseEventHandler(this.resourcesTreeView_MouseDown);
Index: /branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.cs
===================================================================
--- /branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.cs	(revision 15626)
+++ /branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.cs	(revision 15627)
@@ -40,25 +40,105 @@
     private const int slaveImageIndex = 0;
     private const int slaveGroupImageIndex = 1;
-
-    private readonly ISet<TreeNode> mainTreeNodes = new HashSet<TreeNode>();
-    private readonly ISet<TreeNode> filteredTreeNodes = new HashSet<TreeNode>();
-    private readonly ISet<TreeNode> nodeStore = new HashSet<TreeNode>();
-    private readonly ISet<Resource> resources = new HashSet<Resource>();
+    public const string additionalSlavesGroupName = "Additional Slaves";
+    public const string additionalSlavesGroupDescription = "Contains additional slaves which are either ungrouped or the parenting slave group is not assigned to the selected project.";
+
+
+    private readonly HashSet<TreeNode> mainTreeNodes = new HashSet<TreeNode>();
+    private readonly HashSet<TreeNode> filteredTreeNodes = new HashSet<TreeNode>();
+    private readonly HashSet<TreeNode> nodeStore = new HashSet<TreeNode>();
+
+    private readonly HashSet<Resource> availableResources = new HashSet<Resource>();
+    private readonly HashSet<Resource> assignedResources = new HashSet<Resource>();
+    private readonly HashSet<Resource> includedResources = new HashSet<Resource>();
+    private readonly HashSet<Resource> newAssignedResources = new HashSet<Resource>();
+    private readonly HashSet<Resource> newIncludedResources = new HashSet<Resource>();
+
+    private readonly Dictionary<Guid, HashSet<Project>> projectAncestors = new Dictionary<Guid, HashSet<Project>>();
+    private readonly Dictionary<Guid, HashSet<Project>> projectDescendants = new Dictionary<Guid, HashSet<Project>>();
+    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 IEnumerable<Resource> addedResources;
+    private IEnumerable<Resource> removedResources;
+    private IEnumerable<Resource> addedIncludes;
+    private IEnumerable<Resource> removedIncludes;
+
+    private readonly Color addedAssignmentColor = Color.FromArgb(255, 87, 191, 193); // #57bfc1
+    private readonly Color removedAssignmentColor = Color.FromArgb(255, 236, 159, 72); // #ec9f48
+    private readonly Color addedIncludeColor = Color.FromArgb(25, 169, 221, 221); // #a9dddd
+    private readonly Color removedIncludeColor = Color.FromArgb(25, 249, 210, 145); // #f9d291
+    private readonly Color selectedColor = Color.FromArgb(255, 240, 194, 59); // #f0c23b
 
     private string currentSearchString;
 
+    private Guid jobId;
+    public Guid JobId {
+      get { return jobId; }
+      set {
+        if (jobId == value) return;
+        jobId = value;
+      }
+    }
+
+    private Guid? projectId;
+    public Guid? ProjectId {
+      get { return projectId; }
+      set {
+        if (projectId == value) return;
+        projectId = value;
+      }
+    }
+
+    private Guid? selectedProjectId;
+    public Guid? SelectedProjectId {
+      get { return selectedProjectId; }
+      set {
+        if (selectedProjectId == value) return;
+        selectedProjectId = value;
+      }
+    }
+
+    public bool ChangedProject {
+      get {
+        return (selectedProject == null || selectedProject.Id == projectId) ? false : true;
+      }
+    }
+
+    public bool ChangedProjectSelection {
+      get {
+        if ((lastSelectedProject == null && selectedProject != null) 
+          || (lastSelectedProject != null && selectedProject == null)
+          || (lastSelectedProject != null && selectedProject != null && lastSelectedProject.Id != selectedProject.Id))
+          return true;
+        else return false;
+      }
+    }
+
+    public bool ChangedResources {
+      get { return !assignedResources.SetEquals(newAssignedResources); }
+    }
+
+    private Project lastSelectedProject;
     private Project selectedProject;
     public Project SelectedProject {
       get { return selectedProject; }
       set {
+        lastSelectedProject = selectedProject;
         if (selectedProject == value) return;
         selectedProject = value;
-        UpdateResources();
+        UpdateResourceTree();
         OnSelectedProjectChanged();
       }
     }
-
-    private readonly IObservableSet<Resource> selectedResources = new ObservableSet<Resource>();
-    public IEnumerable<Resource> SelectedResources { get { return selectedResources; } }
+    public IEnumerable<Resource> AssignedResources {
+      get { return newAssignedResources; }
+      set {
+        if (newAssignedResources == value) return;
+        newAssignedResources.Clear();
+        foreach(var resource in value) {
+          newAssignedResources.Add(resource);
+        }
+      }
+    }
 
     public new IItemList<Project> Content {
@@ -80,14 +160,21 @@
       base.OnContentChanged();
 
-      if (Content != null) {
-        UpdateMainTree();
-        ExtractStatistics();
+      if (Content != null) {       
+        UpdateProjectGenealogy();
+        UpdateResourceGenealogy();
+        
+        if (SelectedProjectId.HasValue) {
+          SelectedProject = GetSelectedProjectById(SelectedProjectId.Value);
+        } else {
+          SelectedProject = null;
+        }
+        UpdateProjectTree();
+
       } else {
-        mainTreeNodes.Clear();
-        UpdateFilteredTree();
-      }
-
-      SelectedProject = null;
-    }
+        projectsTreeView.Nodes.Clear();
+        resourcesTreeView.Nodes.Clear();
+      }
+    }
+
     #endregion
 
@@ -96,10 +183,11 @@
       projectsTreeView.Nodes.Clear();
       resourcesTreeView.Nodes.Clear();
-      SelectedProject = null;
+      //SelectedProject = null;
     }
 
     private void searchTextBox_TextChanged(object sender, EventArgs e) {
       currentSearchString = searchTextBox.Text.ToLower();
-      UpdateFilteredTree();
+      //UpdateFilteredTree();
+      UpdateProjectTree();
     }
 
@@ -108,11 +196,22 @@
     }
 
-    private void projectsTreeView_MouseDown(object sender, MouseEventArgs e) {
-      var node = projectsTreeView.GetNodeAt(new Point(e.X, e.Y));
-
-      SelectedProject = (Project)node?.Tag;
-
+    private void projectsTreeView_AfterSelect(object sender, TreeViewEventArgs e) {
+      var node = (Project)e.Node.Tag;
+      
       if (node == null) {
         projectsTreeView.SelectedNode = null;
+      } else {
+        ReColorTreeNodes(projectsTreeView.Nodes, selectedColor, Color.Transparent, true);
+        e.Node.BackColor = selectedColor;
+        
+        if(node.Id == projectId) {
+          e.Node.Text += " [current selection]";
+        } else if(projectId == null || projectId == Guid.Empty) {
+          e.Node.Text += " [new selection]";
+        } else {
+          e.Node.Text += " [changed selection]";
+        }
+
+        SelectedProject = node;
       }
 
@@ -130,18 +229,31 @@
     }
 
+    private void resourcesTreeView_BeforeCheck(object sender, TreeViewCancelEventArgs e) {
+      var checkedResource = (Resource)e.Node.Tag;
+      if (newIncludedResources.Contains(checkedResource) || checkedResource.Id == Guid.Empty) e.Cancel = true;
+    }
+
     private void resourcesTreeView_AfterCheck(object sender, TreeViewEventArgs e) {
-      var resource = (Resource)e.Node.Tag;
-
-      if (e.Node.Checked)
-        selectedResources.Add(resource);
-      else
-        selectedResources.Remove(resource);
-
-      ExtractStatistics((Resource)resourcesTreeView.SelectedNode?.Tag);
-      OnSelectedResourcesChanged();
+      var checkedResource = (Resource)e.Node.Tag;
+      if (e.Node.Checked) {
+        newAssignedResources.Add(checkedResource);
+      } else {
+        newAssignedResources.Remove(checkedResource);
+      }
+
+      UpdateNewResourceTree();
+      //ExtractStatistics((Resource)resourcesTreeView.SelectedNode?.Tag);
+      OnAssignedResourcesChanged();
+    }
+
+    private void resourcesTreeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) {
+      return;
     }
     #endregion
 
     #region Helpers
+
+
+    #region old
     private void UpdateMainTree() {
       mainTreeNodes.Clear();
@@ -155,5 +267,5 @@
           tn.Tag = g;
           tn.Text = g.Name;
-          tn.Checked = selectedResources.Any(x => x.Id == g.Id);
+          tn.Checked = assignedResources.Any(x => x.Id == g.Id);
 
           BuildMainTree(tn);
@@ -170,5 +282,5 @@
         stn.SelectedImageIndex = stn.ImageIndex;
         stn.Tag = r;
-        stn.Checked = selectedResources.Any(x => x.Id == r.Id);
+        stn.Checked = assignedResources.Any(x => x.Id == r.Id);
         tn.Nodes.Add(stn);
         mainTreeNodes.Add(stn);
@@ -224,26 +336,460 @@
       }
     }
-
-    private void UpdateResources() {
-      selectedResources.Clear();
-
+    #endregion
+
+    private Project GetSelectedProjectById(Guid projectId) {
+      return Content.Where(x => x.Id == projectId).SingleOrDefault();
+    }
+
+    private void UpdateProjectTree() {
+
+      if (string.IsNullOrEmpty(currentSearchString)) {
+        BuildProjectTree(Content);
+      } else {
+        HashSet<Project> filteredProjects = new HashSet<Project>();
+        foreach(var project in Content) {
+          if(project.Name.ToLower().Contains(currentSearchString.ToLower())) {
+            filteredProjects.Add(project);
+            filteredProjects.UnionWith(projectAncestors[project.Id]);
+          }
+        }
+        BuildProjectTree(filteredProjects);
+      }
+    }
+
+    private void BuildProjectTree(IEnumerable<Project> projects) {
+      projectsTreeView.Nodes.Clear();
+      if (!projects.Any()) return;
+
+      // select all top level projects (withouth parent, or without parent within current project collection)
+      var mainProjects = new HashSet<Project>(projects.Where(x => x.ParentProjectId == null));
+      var parentedMainProjects = new HashSet<Project>(projects
+        .Where(x => x.ParentProjectId.HasValue
+        && !projects.Select(y => y.Id).Contains(x.ParentProjectId.Value)));
+      mainProjects.UnionWith(parentedMainProjects);
+      var subProbjects = new HashSet<Project>(projects.Except(mainProjects));
+
+      var stack = new Stack<Project>(mainProjects.OrderByDescending(x => x.Name));
+
+      TreeNode currentNode = null;
+      Project currentProject = null;
+
+      while(stack.Any()) {
+        var newProject = stack.Pop();
+        var newNode = new TreeNode(newProject.Name) { Tag = newProject };
+
+        while (currentNode != null && newProject.ParentProjectId != currentProject.Id) {
+          currentNode = currentNode.Parent;
+          currentProject = currentNode == null ? null : (Project)currentNode.Tag;
+        }
+
+        if (currentNode == null) {
+          projectsTreeView.Nodes.Add(newNode);
+          newNode.ImageIndex = greenFlagImageIndex;
+        } else {
+          currentNode.Nodes.Add(newNode);
+          newNode.ImageIndex = redFlagImageIndex;
+        }
+
+        newNode.SelectedImageIndex = newNode.ImageIndex;
+
+        if (SelectedProject != null && SelectedProject.Id.Equals(newProject.Id)) {
+          newNode.BackColor = selectedColor;
+          if(SelectedProject.Id == projectId) {
+            newNode.Text += " [current selection]";
+          } else if (projectId == null || projectId == Guid.Empty) {
+            newNode.Text += " [new selection]";
+          } else {
+            newNode.Text += " [changed selection]";
+          }
+        }
+
+        if (!string.IsNullOrEmpty(currentSearchString) && newProject.Name.ToLower().Contains(currentSearchString.ToLower())) {
+          newNode.BackColor = Color.LightBlue;
+        }
+
+        var childProjects = subProbjects.Where(x => x.ParentProjectId == newProject.Id);
+        if (childProjects.Any()) {
+          foreach (var project in childProjects.OrderByDescending(x => x.Name)) {
+            subProbjects.Remove(project);
+            stack.Push(project);
+          }
+          currentNode = newNode;
+          currentProject = newProject;
+        }
+      }
+
+      projectsTreeView.ExpandAll();
+    }
+
+    private void UpdateProjectGenealogy() {
+      projectAncestors.Clear();
+      projectDescendants.Clear();
+      var projects = Content;
+
+      foreach (var p in projects) {
+        projectAncestors.Add(p.Id, new HashSet<Project>());
+        projectDescendants.Add(p.Id, new HashSet<Project>());
+      }
+
+      foreach (var p in projects) {
+        var parentProjectId = p.ParentProjectId;
+        while (parentProjectId != null) {
+          var parent = projects.SingleOrDefault(x => x.Id == parentProjectId);
+          if (parent != null) {
+            projectAncestors[p.Id].Add(parent);
+            projectDescendants[parent.Id].Add(p);
+            parentProjectId = parent.ParentProjectId;
+          } else {
+            parentProjectId = null;
+          }
+        }
+      }
+    }
+
+
+    private static IEnumerable<Resource> GetAssignedResourcesForProject(Guid projectId) {
+      var assignedProjectResources = HiveServiceLocator.Instance.CallHiveService(s => s.GetAssignedResourcesForProject(projectId));
+      return HiveAdminClient.Instance.Resources.Where(x => assignedProjectResources.Select(y => y.ResourceId).Contains(x.Id));
+    }
+
+    private static IEnumerable<Resource> GetAssignedResourcesForJob(Guid jobId) {
+      var assignedJobResources = HiveServiceLocator.Instance.CallHiveService(s => s.GetAssignedResourcesForJob(jobId));
+      return HiveAdminClient.Instance.Resources.Where(x => assignedJobResources.Select(y => y.ResourceId).Contains(x.Id));
+    }
+
+    private void UpdateResourceTree() {
+      UpdateAvailableResources();
+      UpdateAssignedResources();
+      UpdateIncludedResources();
+      BuildResourceTree(availableResources);
+    }
+
+    private void UpdateNewResourceTree() {
+      UpdateNewAssignedResources();
+      UpdateNewIncludedResources();
+      BuildResourceTree(availableResources);
+    }
+
+    private void UpdateAvailableResources() {
+      availableResources.Clear();
       if (selectedProject != null) {
-        var assignedResources = HiveServiceLocator.Instance.CallHiveService(s => s.GetAssignedResourcesForProject(selectedProject.Id));
-        var assignedResourceIds = new HashSet<Guid>(assignedResources.Select(x => x.ResourceId));
-
-        foreach (var resource in HiveAdminClient.Instance.Resources) {
-          if (assignedResourceIds.Contains(resource.Id)) {
-            resources.Add(resource);
-            selectedResources.Add(resource);
-          }
-        }
-      }
-
-      BuildResourceTree(selectedResources);
+        var assignedProjectResources = GetAssignedResourcesForProject(selectedProject.Id);
+        foreach (var resource in assignedProjectResources) {
+          availableResources.Add(resource);
+          foreach(var descendant in resourceDescendants[resource.Id]) {
+            availableResources.Add(descendant);
+          }
+        }
+      }
       ExtractStatistics();
-      OnSelectedResourcesChanged();
-    }
-
-    private Resource BuildResourceTree(IEnumerable<Resource> resources) {
+      //OnAssignedResourcesChanged();
+    }
+
+    private void UpdateAssignedResources() {
+
+      if (JobId == Guid.Empty && ChangedProjectSelection) { // new, unchanged jobs get all avaialable resources
+        // update new assigned resources
+        assignedResources.Clear();
+        newAssignedResources.Clear();
+        foreach (var resource in availableResources
+          .Where(x => !x.ParentResourceId.HasValue
+          || !availableResources.Select(y => y.Id).Contains(x.ParentResourceId.Value))) {
+          newAssignedResources.Add(resource);
+        }
+
+      } else if(JobId != Guid.Empty) { // existent, unchanged jobs get all assigned resources
+        // update assigned resources
+        var assignedJobResources = GetAssignedResourcesForJob(JobId);
+        foreach (var resource in assignedJobResources) {
+          assignedResources.Add(resource);
+        }
+
+        if(ChangedProjectSelection) {
+          newAssignedResources.Clear();
+          foreach (var resource in assignedJobResources) {
+            newAssignedResources.Add(resource);
+          }
+        }
+      } else {
+        var newAssignedResourceIds = newAssignedResources.Select(x => x.Id).ToList();
+        newAssignedResources.Clear();
+        foreach(var r in availableResources.Where(x => newAssignedResourceIds.Contains(x.Id))) {
+          newAssignedResources.Add(r);
+        }
+      }
+
+      ExtractStatistics();
+      OnAssignedResourcesChanged();
+    }
+
+    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 UpdateIncludedResources() {
+      includedResources.Clear();
+      newIncludedResources.Clear();
+      if (JobId != Guid.Empty) {
+        foreach (var item in assignedResources) {
+          foreach (var descendant in resourceDescendants[item.Id]) {
+            includedResources.Add(descendant);
+            newIncludedResources.Add(descendant);
+          }
+        }
+      } else {
+        foreach (var item in newAssignedResources) {
+          foreach (var descendant in resourceDescendants[item.Id]) {
+            newIncludedResources.Add(descendant);
+          }
+        }
+      }
+    }
+
+    private void UpdateNewIncludedResources() {
+      newIncludedResources.Clear();
+      foreach (var item in newAssignedResources) {
+        foreach (var descendant in resourceDescendants[item.Id]) {
+          newIncludedResources.Add(descendant);
+        }
+      }
+    }
+
+    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;
+          }
+        }
+      }
+    }
+
+    private void BuildResourceTree(IEnumerable<Resource> resources) {
+      resourcesTreeView.Nodes.Clear();
+      if (!resources.Any()) return;
+
+      resourcesTreeView.BeforeCheck -= resourcesTreeView_BeforeCheck;
+      resourcesTreeView.AfterCheck -= resourcesTreeView_AfterCheck;
+
+      var mainResources = new HashSet<Resource>(resources.OfType<SlaveGroup>().Where(x => x.ParentResourceId == null));
+      var parentedMainResources = new HashSet<Resource>(resources.OfType<SlaveGroup>()
+        .Where(x => x.ParentResourceId.HasValue && !resources.Select(y => y.Id).Contains(x.ParentResourceId.Value)));
+      mainResources.UnionWith(parentedMainResources);
+      var subResources = new HashSet<Resource>(resources.Except(mainResources));
+
+      var addedAssignments = newAssignedResources.Except(assignedResources);
+      var removedAssignments = assignedResources.Except(newAssignedResources);
+      var addedIncludes = newIncludedResources.Except(includedResources);
+      var removedIncludes = includedResources.Except(newIncludedResources);
+
+      HashSet<TreeNode> expandedNodes = new HashSet<TreeNode>();
+      TreeNode currentNode = null;
+      Resource currentResource = null;
+
+      var stack = new Stack<Resource>(mainResources.OrderByDescending(x => x.Name));
+
+      while (stack.Any()) {
+        var newResource = stack.Pop();
+        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;
+          currentResource = currentNode == null ? null : (Resource)currentNode.Tag;
+        }
+
+        if (currentNode == null) {
+          resourcesTreeView.Nodes.Add(newNode);
+        } else {
+          currentNode.Nodes.Add(newNode);
+        }
+
+        if(newAssignedResources.Select(x => x.Id).Contains(newResource.Id)
+          || assignedResources.Select(x => x.Id).Contains(newResource.Id)
+          || newIncludedResources.Select(x => x.Id).Contains(newResource.Id)
+          || includedResources.Select(x => x.Id).Contains(newResource.Id)) {
+          expandedNodes.Add(newNode);
+        }
+
+        if (newAssignedResources.Select(x => x.Id).Contains(newResource.Id)) {
+          newNode.Checked = true;
+        } else if (newIncludedResources.Select(x => x.Id).Contains(newResource.Id)) {
+          newNode.Checked = true;
+          newNode.ForeColor = SystemColors.GrayText;
+        }
+
+        if (includedResources.Select(x => x.Id).Contains(newResource.Id) && newIncludedResources.Select(x => x.Id).Contains(newResource.Id)) {
+          newNode.Text += " [included]";
+        } else if (addedIncludes.Select(x => x.Id).Contains(newResource.Id)) {
+          newNode.BackColor = addedIncludeColor;
+          newNode.ForeColor = SystemColors.GrayText;
+          newNode.Text += " [added include]";
+        } else if (removedIncludes.Select(x => x.Id).Contains(newResource.Id)) {
+          newNode.BackColor = removedIncludeColor;
+          newNode.Text += " [removed include]";
+        }
+
+        if (addedAssignments.Select(x => x.Id).Contains(newResource.Id)) {
+          newNode.BackColor = addedAssignmentColor;
+          newNode.ForeColor = SystemColors.ControlText;
+          newNode.Text += " [added selection]";
+        } else if (removedAssignments.Select(x => x.Id).Contains(newResource.Id)) {
+          newNode.BackColor = removedAssignmentColor;
+          newNode.ForeColor = SystemColors.ControlText;
+          newNode.Text += " [removed selection]";
+        }
+
+        if (newResource is Slave) {
+          newNode.ImageIndex = slaveImageIndex;
+        } else {
+          newNode.ImageIndex = slaveGroupImageIndex;
+
+          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;
+            currentResource = newResource;
+          }
+        }
+        newNode.SelectedImageIndex = newNode.ImageIndex;
+      }
+
+      var singleSlaves = subResources.OfType<Slave>();
+      if (singleSlaves.Any()) {
+
+        var additionalNode = new TreeNode(additionalSlavesGroupName) {
+          ForeColor = SystemColors.GrayText,
+          Tag = new SlaveGroup() {
+            Name = additionalSlavesGroupName,
+            Description = additionalSlavesGroupDescription
+          }
+        };
+
+        foreach (var slave in singleSlaves.OrderBy(x => x.Name)) {
+          var slaveNode = new TreeNode(slave.Name) { Tag = slave };
+          additionalNode.Nodes.Add(slaveNode);
+        }
+
+        resourcesTreeView.Nodes.Add(additionalNode);
+      }
+
+      
+      foreach (var node in expandedNodes) {
+        node.Expand();
+        var parent = node.Parent;
+        while(parent != null) {
+          parent.Expand();
+          parent = parent.Parent;
+        }
+      }
+
+      resourcesTreeView.BeforeCheck += resourcesTreeView_BeforeCheck;
+      resourcesTreeView.AfterCheck += resourcesTreeView_AfterCheck;
+      //resourcesTreeView.ExpandAll();
+    }
+
+    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(Resource resource = null) {
+      ISet<Slave> selectedSlaves = null;
+
+      if (resource != null) {
+
+
+        var slaveGroup = resource as SlaveGroup;
+        if (slaveGroup != null) {
+          selectedSlaves = new HashSet<Slave>(resourceDescendants[slaveGroup.Id].OfType<Slave>());
+          selectedSlaves.IntersectWith(newAssignedResources.OfType<Slave>());
+        } else {
+          selectedSlaves = new HashSet<Slave>(new[] { resource as Slave });
+        }
+      } else {
+        selectedSlaves = new HashSet<Slave>(newAssignedResources.OfType<Slave>());
+      }
+
+      int sumCores = selectedSlaves.OfType<Slave>().Sum(x => x.Cores.GetValueOrDefault());
+      int sumFreeCores = selectedSlaves.OfType<Slave>().Sum(x => x.FreeCores.GetValueOrDefault());
+      double sumMemory = selectedSlaves.OfType<Slave>().Sum(x => x.Memory.GetValueOrDefault()) / 1024.0;
+      double sumFreeMemory = selectedSlaves.OfType<Slave>().Sum(x => x.FreeMemory.GetValueOrDefault()) / 1024.0;
+
+      coresSummaryLabel.Text = $"{sumCores} Total ({sumFreeCores} Free / {sumCores - sumFreeCores} Used)";
+      memorySummaryLabel.Text = $"{sumMemory:0.00} GB Total ({sumFreeMemory:0.00} GB Free / {(sumMemory - sumFreeMemory):0.00} GB Used)";
+    }
+
+    private void ReColorTreeNodes(TreeNodeCollection nodes, Color c1, Color c2, bool resetText) {
+      foreach (TreeNode n in nodes) {
+        if (n.BackColor.Equals(c1)) {
+          n.BackColor = c2;
+          if(resetText) n.Text = ((Project)n.Tag).Name;
+        }
+        if (n.Nodes.Count > 0) {
+          ReColorTreeNodes(n.Nodes, c1, c2, resetText);
+        }
+      }
+    }
+
+    private void ExtractStatistics_Old(Resource resource = null) {
+      ISet<Slave> selectedSlaves = null;
+
+      if (resource != null) {
+        var slaveGroup = resource as SlaveGroup;
+        if (slaveGroup != null) {
+          var children = new HashSet<Resource>(availableResources.Where(x => x.ParentResourceId == slaveGroup.Id));
+          int nrOfChildren = children.Count;
+          do {
+            var newChildren = availableResources.Where(x => children.Any(y => y.Id == x.ParentResourceId));
+            foreach (var newChild in newChildren)
+              children.Add(newChild);
+          } while (children.Count > nrOfChildren);
+          selectedSlaves = new HashSet<Slave>(children.OfType<Slave>());
+          selectedSlaves.IntersectWith(assignedResources.OfType<Slave>());
+        } else {
+          selectedSlaves = new HashSet<Slave>(new[] { resource as Slave });
+        }
+      } else {
+        selectedSlaves = new HashSet<Slave>(assignedResources.OfType<Slave>());
+      }
+
+      int sumCores = selectedSlaves.OfType<Slave>().Sum(x => x.Cores.GetValueOrDefault());
+      int sumFreeCores = selectedSlaves.OfType<Slave>().Sum(x => x.FreeCores.GetValueOrDefault());
+      double sumMemory = selectedSlaves.OfType<Slave>().Sum(x => x.Memory.GetValueOrDefault()) / 1024.0;
+      double sumFreeMemory = selectedSlaves.OfType<Slave>().Sum(x => x.FreeMemory.GetValueOrDefault()) / 1024.0;
+
+      coresSummaryLabel.Text = $"{sumCores} Total ({sumFreeCores} Free / {sumCores - sumFreeCores} Used)";
+      memorySummaryLabel.Text = $"{sumMemory:0.00} GB Total ({sumFreeMemory:0.00} GB Free / {(sumMemory - sumFreeMemory):0.00} GB Used)";
+    }
+
+    private Resource BuildResourceTree_Old(IEnumerable<Resource> resources) {
       resourcesTreeView.Nodes.Clear();
       if (!resources.Any()) return null;
@@ -295,42 +841,4 @@
     }
 
-    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(Resource resource = null) {
-      ISet<Slave> selectedSlaves = null;
-
-      if (resource != null) {
-        var slaveGroup = resource as SlaveGroup;
-        if (slaveGroup != null) {
-          var children = new HashSet<Resource>(resources.Where(x => x.ParentResourceId == slaveGroup.Id));
-          int nrOfChildren = children.Count;
-          do {
-            var newChildren = resources.Where(x => children.Any(y => y.Id == x.ParentResourceId));
-            foreach (var newChild in newChildren)
-              children.Add(newChild);
-          } while (children.Count > nrOfChildren);
-          selectedSlaves = new HashSet<Slave>(children.OfType<Slave>());
-          selectedSlaves.IntersectWith(selectedResources.OfType<Slave>());
-        } else {
-          selectedSlaves = new HashSet<Slave>(new[] { resource as Slave });
-        }
-      } else {
-        selectedSlaves = new HashSet<Slave>(selectedResources.OfType<Slave>());
-      }
-
-      int sumCores = selectedSlaves.OfType<Slave>().Sum(x => x.Cores.GetValueOrDefault());
-      int sumFreeCores = selectedSlaves.OfType<Slave>().Sum(x => x.FreeCores.GetValueOrDefault());
-      double sumMemory = selectedSlaves.OfType<Slave>().Sum(x => x.Memory.GetValueOrDefault()) / 1024.0;
-      double sumFreeMemory = selectedSlaves.OfType<Slave>().Sum(x => x.FreeMemory.GetValueOrDefault()) / 1024.0;
-
-      coresSummaryLabel.Text = $"{sumCores} Total ({sumFreeCores} Free / {sumCores - sumFreeCores} Used)";
-      memorySummaryLabel.Text = $"{sumMemory:0.00} GB Total ({sumFreeMemory:0.00} GB Free / {(sumMemory - sumFreeMemory):0.00} GB Used)";
-    }
     #endregion
 
@@ -341,7 +849,7 @@
     }
 
-    public event EventHandler SelectedResourcesChanged;
-    private void OnSelectedResourcesChanged() {
-      SelectedResourcesChanged?.Invoke(this, EventArgs.Empty);
+    public event EventHandler AssignedResourcesChanged;
+    private void OnAssignedResourcesChanged() {
+      AssignedResourcesChanged?.Invoke(this, EventArgs.Empty);
     }
 
Index: /branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelectorDialog.Designer.cs
===================================================================
--- /branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelectorDialog.Designer.cs	(revision 15626)
+++ /branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelectorDialog.Designer.cs	(revision 15627)
@@ -98,5 +98,5 @@
       this.hiveResourceSelector.TabIndex = 0;
       this.hiveResourceSelector.SelectedProjectChanged += new System.EventHandler(this.hiveResourceSelector_SelectedProjectChanged);
-      this.hiveResourceSelector.SelectedResourcesChanged += new System.EventHandler(this.hiveResourceSelector_SelectedResourcesChanged);
+      this.hiveResourceSelector.AssignedResourcesChanged += new System.EventHandler(this.hiveResourceSelector_SelectedResourcesChanged);
       this.hiveResourceSelector.ProjectsTreeViewDoubleClicked += new System.EventHandler(this.hiveResourceSelector_ProjectsTreeViewDoubleClicked);
       // 
Index: /branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelectorDialog.cs
===================================================================
--- /branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelectorDialog.cs	(revision 15626)
+++ /branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelectorDialog.cs	(revision 15627)
@@ -27,4 +27,5 @@
 using HeuristicLab.Clients.Hive.Views;
 using HeuristicLab.MainForm;
+using HeuristicLab.Core;
 
 namespace HeuristicLab.Clients.Hive.JobManager.Views {
@@ -38,8 +39,32 @@
 
     public IEnumerable<Resource> SelectedResources {
-      get { return hiveResourceSelector.SelectedResources; }
+      get { return hiveResourceSelector.AssignedResources; }
     }
 
-    public HiveResourceSelectorDialog() {
+    private Guid jobId;
+    public Guid JobId {
+      get { return hiveResourceSelector.JobId; }
+      set { jobId = value; }
+    }
+
+    // persisted projectId
+    private Guid? projectId;
+    public Guid? ProjectId {
+      get { return hiveResourceSelector.ProjectId; }
+      set { projectId = value; }
+    }
+
+    // currently selected projectId (initially persisted projectId)
+    private Guid? selectedProjectId;
+    public Guid? SelectedProjectId {
+      get { return selectedProjectId; }
+      set { selectedProjectId = value; }
+    }
+
+
+    public HiveResourceSelectorDialog(Guid jobId, Guid projectId) {
+      this.jobId = jobId;
+      this.projectId = projectId;
+      this.selectedProjectId = projectId;
       InitializeComponent();
     }
@@ -105,5 +130,5 @@
 
     private void hiveResourceSelector_SelectedResourcesChanged(object sender, EventArgs e) {
-      okButton.Enabled = hiveResourceSelector.SelectedResources.Any();
+      okButton.Enabled = hiveResourceSelector.AssignedResources.Any();
     }
 
@@ -119,5 +144,9 @@
     private void UpdateProjects() {
       HiveAdminClient.Instance.Refresh();
-      hiveResourceSelector.Content = HiveAdminClient.Instance.Projects;
+      hiveResourceSelector.JobId = jobId;
+      hiveResourceSelector.ProjectId = projectId;
+      hiveResourceSelector.SelectedProjectId = selectedProjectId;
+      var projectList = new ItemList<Project>(HiveServiceLocator.Instance.CallHiveService(s => s.GetProjects()));
+      hiveResourceSelector.Content = projectList;
     }
 
Index: /branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/RefreshableHiveJobView.cs
===================================================================
--- /branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/RefreshableHiveJobView.cs	(revision 15626)
+++ /branches/HiveProjectManagement/HeuristicLab.Clients.Hive.JobManager/3.3/Views/RefreshableHiveJobView.cs	(revision 15627)
@@ -33,4 +33,5 @@
 using HeuristicLab.Optimization;
 using HeuristicLab.PluginInfrastructure;
+using System.Collections.Generic;
 
 namespace HeuristicLab.Clients.Hive.JobManager.Views {
@@ -44,4 +45,5 @@
     private bool SuppressEvents { get; set; }
     private object runCollectionViewLocker = new object();
+    private Project selectedProject;
 
     public new RefreshableJob Content {
@@ -129,6 +131,19 @@
           nameTextBox.Text = Content.Job.Name;
           executionTimeTextBox.Text = Content.ExecutionTime.ToString();
-          //resourceNamesTextBox.Text = Content.Job.ResourceNames;
           refreshAutomaticallyCheckBox.Checked = Content.RefreshAutomatically;
+
+          // project look up
+          if(Content.Job.ProjectId != null && Content.Job.ProjectId != Guid.Empty) {
+            selectedProject = GetProject(Content.Job.ProjectId);
+            if(selectedProject != null) {
+              projectNameTextBox.Text = selectedProject.Name;
+            } else {
+              projectNameTextBox.Text = string.Empty;
+            }
+          } else {
+            selectedProject = null;
+            projectNameTextBox.Text = string.Empty;
+          }
+          
           logView.Content = Content.Log;
           lock (runCollectionViewLocker) {
@@ -330,12 +345,23 @@
     #region Control events
     private void searchButton_Click(object sender, EventArgs e) {
-      if (hiveResourceSelectorDialog == null)
-        hiveResourceSelectorDialog = new HiveResourceSelectorDialog();
+      if (hiveResourceSelectorDialog == null) {
+        hiveResourceSelectorDialog = new HiveResourceSelectorDialog(Content.Job.Id, Content.Job.ProjectId);
+      } else if(selectedProject != null) {
+        hiveResourceSelectorDialog.SelectedProjectId = Content.Job.ProjectId;
+      } else {
+        hiveResourceSelectorDialog.SelectedProjectId = null;
+      }
 
       if (hiveResourceSelectorDialog.ShowDialog(this) == DialogResult.OK) {
-        var selectedProject = hiveResourceSelectorDialog.SelectedProject;
-        projectNameTextBox.Text = selectedProject.Name;
-        Content.Job.ProjectId = selectedProject.Id;
-        Content.Job.ResourceIds = hiveResourceSelectorDialog.SelectedResources.Select(x => x.Id).ToList();
+        selectedProject = hiveResourceSelectorDialog.SelectedProject;
+        if(selectedProject != null) {
+          projectNameTextBox.Text = selectedProject.Name;
+          Content.Job.ProjectId = selectedProject.Id;
+          Content.Job.ResourceIds = hiveResourceSelectorDialog.SelectedResources.Select(x => x.Id).ToList();
+        } else {
+          projectNameTextBox.Text = string.Empty;
+          Content.Job.ProjectId = Guid.Empty;
+          Content.Job.ResourceIds = null;
+        }
       }
     }
@@ -344,4 +370,8 @@
       if (nameTextBox.Text.Trim() == string.Empty) {
         MessageBox.Show("Please enter a name for the job before uploading it!", "HeuristicLab Hive Job Manager", MessageBoxButtons.OK, MessageBoxIcon.Information);
+      } else if (Content.Job.ProjectId == null || Content.Job.ProjectId == Guid.Empty) {
+        MessageBox.Show("Please select a project before uploading the job!", "HeuristicLab Hive Job Manager", MessageBoxButtons.OK, MessageBoxIcon.Information);
+      } else if (Content.Job.ResourceIds == null || !Content.Job.ResourceIds.Any()) {
+        MessageBox.Show("Please select resources before uploading the job!", "HeuristicLab Hive Job Manager", MessageBoxButtons.OK, MessageBoxIcon.Information);
       } else if (Content.ExecutionState == ExecutionState.Paused) {
         var task = System.Threading.Tasks.Task.Factory.StartNew(ResumeJobAsync, Content);
@@ -436,4 +466,8 @@
       }
     }
+   
+    private Project GetProject(Guid projectId) {
+      return HiveServiceLocator.Instance.CallHiveService(s => s.GetProject(projectId));
+    }
     #endregion
 
