Index: trunk/HeuristicLab.Clients.Hive.JobManager/3.3/HeuristicLab.Clients.Hive.JobManager-3.3.csproj
===================================================================
--- trunk/HeuristicLab.Clients.Hive.JobManager/3.3/HeuristicLab.Clients.Hive.JobManager-3.3.csproj	(revision 15682)
+++ trunk/HeuristicLab.Clients.Hive.JobManager/3.3/HeuristicLab.Clients.Hive.JobManager-3.3.csproj	(revision 16117)
@@ -105,4 +105,5 @@
     <Compile Include="ExtensionMethods\TreeNodeExtensions.cs" />
     <Compile Include="ListViewItemDateComparer.cs" />
+    <Compile Include="ListViewItemComparer.cs" />
     <Compile Include="MenuItems\CreateHiveJobMenuItem.cs" />
     <Compile Include="MenuItems\RunInHiveMenuItem.cs" />
@@ -159,4 +160,14 @@
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Clients.Access\3.3\HeuristicLab.Clients.Access-3.3.csproj">
+      <Project>{494f87f4-0f25-4d33-a382-10cdb2174d48}</Project>
+      <Name>HeuristicLab.Clients.Access-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Clients.Common\3.3\HeuristicLab.Clients.Common-3.3.csproj">
+      <Project>{730a9104-d4d1-4360-966b-e49b7571dda3}</Project>
+      <Name>HeuristicLab.Clients.Common-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Clients.Hive.Views\3.3\HeuristicLab.Clients.Hive.Views-3.3.csproj">
       <Project>{E1D6C801-892A-406A-B606-F158E36DD3C3}</Project>
Index: trunk/HeuristicLab.Clients.Hive.JobManager/3.3/ListViewItemComparer.cs
===================================================================
--- trunk/HeuristicLab.Clients.Hive.JobManager/3.3/ListViewItemComparer.cs	(revision 16117)
+++ trunk/HeuristicLab.Clients.Hive.JobManager/3.3/ListViewItemComparer.cs	(revision 16117)
@@ -0,0 +1,79 @@
+﻿#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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections;
+using System.Windows.Forms;
+
+namespace HeuristicLab.Clients.Hive.JobManager {
+  public class ListViewItemComparer : IComparer {
+    private int[] cols;
+    public SortOrder[] Orders { get; set; }
+    private const string dateFormat = "dd.MM.yyyy HH:mm";
+
+    public ListViewItemComparer() {
+      cols = new []{ 0 };
+      Orders = new[] { SortOrder.Ascending };
+    }
+
+    public ListViewItemComparer(int[] columns, SortOrder[] orders) {
+      cols = columns;
+      Orders = orders;
+    }
+
+    public int Compare(object x, object y) {
+      int returnVal;
+      bool result;
+      ListViewItem listViewItemX, listViewItemY;
+      listViewItemX = x as ListViewItem;
+      listViewItemY = y as ListViewItem;
+
+      if (listViewItemX == null || listViewItemY == null) {
+        throw new ArgumentException(string.Format("The ListViewItemComparer expects ListViewItems but received {0} and {1}.",
+          x.GetType().ToString(), y.GetType().ToString()));
+      }
+
+      int cmpres = 0;
+      for (int i = 0; i < cols.Length && cmpres == 0; i++) {
+        string textX = listViewItemX.SubItems[cols[i]].Text;
+        string textY = listViewItemY.SubItems[cols[i]].Text;
+
+        DateTime dateX, dateY;
+        int intX, intY;
+        double doubleX, doubleY;
+
+        if(DateTime.TryParse(textX, out dateX) && DateTime.TryParse(textY, out dateY)) {
+          cmpres = DateTime.Compare(dateX, dateY);
+        } else if(Int32.TryParse(textX, out intX) && Int32.TryParse(textY, out intY)) {
+          cmpres = (intX == intY) ? 0 : (intX > intY) ? 1 : -1;
+        } else if(Double.TryParse(textX, out doubleX) && Double.TryParse(textY, out doubleY)) {
+          cmpres = (doubleX == doubleY) ? 0 : (doubleX > doubleY) ? 1 : -1;
+        } else {
+          cmpres = String.Compare(textX, textY);
+        }
+        if(Orders[i] == SortOrder.Descending) {
+          cmpres *= -1;
+        }
+      }
+      return cmpres;
+    }
+  }
+}
Index: trunk/HeuristicLab.Clients.Hive.JobManager/3.3/MenuItems/JobManagerMenuItem.cs
===================================================================
--- trunk/HeuristicLab.Clients.Hive.JobManager/3.3/MenuItems/JobManagerMenuItem.cs	(revision 15682)
+++ trunk/HeuristicLab.Clients.Hive.JobManager/3.3/MenuItems/JobManagerMenuItem.cs	(revision 16117)
@@ -20,23 +20,41 @@
 #endregion
 
+using System;
 using System.Collections.Generic;
 using System.Windows.Forms;
+using HeuristicLab.Clients.Access;
 using HeuristicLab.MainForm;
 using HeuristicLab.Optimizer;
 
 namespace HeuristicLab.Clients.Hive.JobManager {
-  public class JobManagerMenuItem : HeuristicLab.MainForm.WindowsForms.MenuItem, IOptimizerUserInterfaceItemProvider {
+  public class JobManagerMenuItem : MainForm.WindowsForms.MenuItem, IOptimizerUserInterfaceItemProvider {
     public override string Name {
       get { return "&Job Manager"; }
     }
+
     public override IEnumerable<string> Structure {
       get { return new string[] { "&Services", "&Hive" }; }
     }
+
     public override void Execute() {
-      MainFormManager.MainForm.ShowContent(HiveClient.Instance);
+      if (HiveRoles.CheckHiveUserPermissions()) {
+        MainFormManager.MainForm.ShowContent(HiveClient.Instance);
+      } else if (!UserInformation.Instance.UserExists) {
+        MessageBox.Show(
+          "Couldn't fetch user information from the server." + Environment.NewLine +
+          "Please verify that you have an existing user and that your user name and password is correct.",
+          "HeuristicLab Hive Job Manager", MessageBoxButtons.OK, MessageBoxIcon.Error);
+      } else {
+        MessageBox.Show(
+          "You do not seem to have the permissions to use the Hive Job Manager." + Environment.NewLine +
+          "If that's not the case or you have any questions please write an email to support@heuristiclab.com",
+          "HeuristicLab Hive Job Manager", MessageBoxButtons.OK, MessageBoxIcon.Error);
+      }
     }
+
     public override int Position {
       get { return 10000; }
     }
+
     public override Keys ShortCutKeys {
       get { return Keys.Control | Keys.H; }
Index: trunk/HeuristicLab.Clients.Hive.JobManager/3.3/MenuItems/RunInHiveMenuItem.cs
===================================================================
--- trunk/HeuristicLab.Clients.Hive.JobManager/3.3/MenuItems/RunInHiveMenuItem.cs	(revision 15682)
+++ trunk/HeuristicLab.Clients.Hive.JobManager/3.3/MenuItems/RunInHiveMenuItem.cs	(revision 16117)
@@ -22,5 +22,8 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using System.Threading;
+using System.Windows.Forms;
+using HeuristicLab.Clients.Hive.JobManager.Views;
 using HeuristicLab.Core;
 using HeuristicLab.MainForm;
@@ -82,9 +85,25 @@
       task.ItemTask.ComputeInParallel = content is Experiment || content is BatchRun;
 
-      progress = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>().AddOperationProgressToContent(this.content, "Uploading to Hive...");
-      rJob.Progress = progress;
-      progress.ProgressStateChanged += progress_ProgressStateChanged;
+      var hiveResourceSelectorDialog = new HiveResourceSelectorDialog(rJob.Job.Id, rJob.Job.ProjectId);
 
-      HiveClient.StartJob(new Action<Exception>(HandleEx), rJob, new CancellationToken());
+      if (HiveClient.Instance.Projects.Count == 1) {
+        var project = HiveClient.Instance.Projects.FirstOrDefault();
+        if (project != null && project.Id != Guid.Empty)
+          hiveResourceSelectorDialog.SelectedProjectId = project.Id;
+      }
+
+      if (hiveResourceSelectorDialog.ShowDialog((UserControl)activeView) == DialogResult.OK) {
+        var selectedProject = hiveResourceSelectorDialog.SelectedProject;
+        if (selectedProject != null) {
+          rJob.Job.ProjectId = selectedProject.Id;
+          rJob.Job.ResourceIds = hiveResourceSelectorDialog.SelectedResources.Select(x => x.Id).ToList();
+
+          progress = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>().AddOperationProgressToContent(this.content, "Uploading to Hive...");
+          rJob.Progress = progress;
+          progress.ProgressStateChanged += progress_ProgressStateChanged;
+
+          HiveClient.StartJob(new Action<Exception>(HandleEx), rJob, new CancellationToken());
+        }
+      }
     }
 
Index: trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Plugin.cs.frame
===================================================================
--- trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Plugin.cs.frame	(revision 15682)
+++ trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Plugin.cs.frame	(revision 16117)
@@ -25,4 +25,6 @@
   [Plugin("HeuristicLab.Clients.Hive.JobManager", "3.3.15.$WCREV$")]
   [PluginFile("HeuristicLab.Clients.Hive.JobManager-3.3.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.Clients.Access", "3.3")]
+  [PluginDependency("HeuristicLab.Clients.Common", "3.3")]
   [PluginDependency("HeuristicLab.Clients.Hive", "3.3")]
   [PluginDependency("HeuristicLab.Clients.Hive.Views", "3.3")]
Index: trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveJobManagerView.Designer.cs
===================================================================
--- trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveJobManagerView.Designer.cs	(revision 15682)
+++ trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveJobManagerView.Designer.cs	(revision 16117)
@@ -45,6 +45,8 @@
     /// </summary>
     private void InitializeComponent() {
+      this.components = new System.ComponentModel.Container();
       this.hiveExperimentListView = new RefreshableHiveJobListView();
       this.refreshButton = new System.Windows.Forms.Button();
+      this.toolTip = new System.Windows.Forms.ToolTip(this.components);
       this.SuspendLayout();
       // 
@@ -69,4 +71,5 @@
       this.refreshButton.Size = new System.Drawing.Size(24, 24);
       this.refreshButton.TabIndex = 1;
+      this.toolTip.SetToolTip(this.refreshButton, "Refresh data");
       this.refreshButton.UseVisualStyleBackColor = true;
       this.refreshButton.Click += new System.EventHandler(this.refreshButton_Click);
@@ -87,5 +90,5 @@
     private RefreshableHiveJobListView hiveExperimentListView;
     private System.Windows.Forms.Button refreshButton;
-
+    private System.Windows.Forms.ToolTip toolTip;
 
   }
Index: trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.Designer.cs
===================================================================
--- trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.Designer.cs	(revision 15682)
+++ trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.Designer.cs	(revision 16117)
@@ -21,5 +21,5 @@
 
 namespace HeuristicLab.Clients.Hive.JobManager.Views {
-  partial class HiveResourceSelector {
+  partial class HiveProjectSelector {
     /// <summary> 
     /// Required designer variable.
@@ -46,79 +46,57 @@
     private void InitializeComponent() {
       this.components = new System.ComponentModel.Container();
-      System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(HiveResourceSelector));
-      this.resourcesGroupBox = new System.Windows.Forms.GroupBox();
-      this.splitContainer = new System.Windows.Forms.SplitContainer();
-      this.resourcesTreeView = new System.Windows.Forms.TreeView();
-      this.imageList = new System.Windows.Forms.ImageList(this.components);
+      this.projectsGroupBox = new System.Windows.Forms.GroupBox();
+      this.projectsImageList = new System.Windows.Forms.ImageList(this.components);
+      this.resourcesImageList = new System.Windows.Forms.ImageList(this.components);
       this.searchLabel = new System.Windows.Forms.Label();
       this.searchTextBox = new System.Windows.Forms.TextBox();
-      this.descriptionTextBox = new System.Windows.Forms.TextBox();
       this.toolTip = new System.Windows.Forms.ToolTip(this.components);
-      this.resourcesGroupBox.SuspendLayout();
-      ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
-      this.splitContainer.Panel1.SuspendLayout();
-      this.splitContainer.Panel2.SuspendLayout();
-      this.splitContainer.SuspendLayout();
+      this.splitContainer2 = new System.Windows.Forms.SplitContainer();
+      this.projectsTreeView = new System.Windows.Forms.TreeView();
+      this.resourcesTreeView = new HeuristicLab.Clients.Hive.Views.TreeView.NoDoubleClickTreeView();
+      this.summaryGroupBox = new System.Windows.Forms.GroupBox();
+      this.coresLabel = new System.Windows.Forms.Label();
+      this.coresSummaryLabel = new System.Windows.Forms.Label();
+      this.memoryLabel = new System.Windows.Forms.Label();
+      this.memorySummaryLabel = new System.Windows.Forms.Label();
+      this.projectsGroupBox.SuspendLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit();
+      this.splitContainer2.Panel1.SuspendLayout();
+      this.splitContainer2.Panel2.SuspendLayout();
+      this.splitContainer2.SuspendLayout();
+      this.summaryGroupBox.SuspendLayout();
       this.SuspendLayout();
       // 
-      // resourcesGroupBox
-      // 
-      this.resourcesGroupBox.Controls.Add(this.splitContainer);
-      this.resourcesGroupBox.Dock = System.Windows.Forms.DockStyle.Fill;
-      this.resourcesGroupBox.Location = new System.Drawing.Point(0, 0);
-      this.resourcesGroupBox.Name = "resourcesGroupBox";
-      this.resourcesGroupBox.Size = new System.Drawing.Size(308, 365);
-      this.resourcesGroupBox.TabIndex = 0;
-      this.resourcesGroupBox.TabStop = false;
-      this.resourcesGroupBox.Text = "Available Resources";
-      // 
-      // splitContainer
-      // 
-      this.splitContainer.Dock = System.Windows.Forms.DockStyle.Fill;
-      this.splitContainer.Location = new System.Drawing.Point(3, 16);
-      this.splitContainer.Name = "splitContainer";
-      this.splitContainer.Orientation = System.Windows.Forms.Orientation.Horizontal;
-      // 
-      // splitContainer.Panel1
-      // 
-      this.splitContainer.Panel1.Controls.Add(this.resourcesTreeView);
-      this.splitContainer.Panel1.Controls.Add(this.searchLabel);
-      this.splitContainer.Panel1.Controls.Add(this.searchTextBox);
-      // 
-      // splitContainer.Panel2
-      // 
-      this.splitContainer.Panel2.Controls.Add(this.descriptionTextBox);
-      this.splitContainer.Size = new System.Drawing.Size(302, 346);
-      this.splitContainer.SplitterDistance = 219;
-      this.splitContainer.TabIndex = 0;
-      // 
-      // resourcesTreeView
-      // 
-      this.resourcesTreeView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-            | System.Windows.Forms.AnchorStyles.Left)
-            | System.Windows.Forms.AnchorStyles.Right)));
-      this.resourcesTreeView.CheckBoxes = true;
-      this.resourcesTreeView.HideSelection = false;
-      this.resourcesTreeView.ImageIndex = 0;
-      this.resourcesTreeView.ImageList = this.imageList;
-      this.resourcesTreeView.Location = new System.Drawing.Point(3, 29);
-      this.resourcesTreeView.Name = "resourcesTreeView";
-      this.resourcesTreeView.SelectedImageIndex = 0;
-      this.resourcesTreeView.ShowNodeToolTips = true;
-      this.resourcesTreeView.Size = new System.Drawing.Size(296, 196);
-      this.resourcesTreeView.TabIndex = 2;
-      this.resourcesTreeView.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.resourcesTreeView_AfterCheck);
-      this.resourcesTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.resourcesTreeView_AfterSelect);
-      // 
-      // imageList
-      // 
-      this.imageList.ColorDepth = System.Windows.Forms.ColorDepth.Depth8Bit;
-      this.imageList.ImageSize = new System.Drawing.Size(16, 16);
-      this.imageList.TransparentColor = System.Drawing.Color.Transparent;
+      // projectsGroupBox
+      // 
+      this.projectsGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.projectsGroupBox.Controls.Add(this.searchLabel);
+      this.projectsGroupBox.Controls.Add(this.splitContainer2);
+      this.projectsGroupBox.Controls.Add(this.searchTextBox);
+      this.projectsGroupBox.Location = new System.Drawing.Point(3, 3);
+      this.projectsGroupBox.Name = "projectsGroupBox";
+      this.projectsGroupBox.Size = new System.Drawing.Size(426, 461);
+      this.projectsGroupBox.TabIndex = 0;
+      this.projectsGroupBox.TabStop = false;
+      this.projectsGroupBox.Text = "Available Projects";
+      // 
+      // projectsImageList
+      // 
+      this.projectsImageList.ColorDepth = System.Windows.Forms.ColorDepth.Depth8Bit;
+      this.projectsImageList.ImageSize = new System.Drawing.Size(16, 16);
+      this.projectsImageList.TransparentColor = System.Drawing.Color.Transparent;
+      // 
+      // resourcesImageList
+      // 
+      this.resourcesImageList.ColorDepth = System.Windows.Forms.ColorDepth.Depth8Bit;
+      this.resourcesImageList.ImageSize = new System.Drawing.Size(16, 16);
+      this.resourcesImageList.TransparentColor = System.Drawing.Color.Transparent;
       // 
       // searchLabel
       // 
       this.searchLabel.Image = HeuristicLab.Common.Resources.VSImageLibrary.Zoom;
-      this.searchLabel.Location = new System.Drawing.Point(3, 3);
+      this.searchLabel.Location = new System.Drawing.Point(6, 19);
       this.searchLabel.Name = "searchLabel";
       this.searchLabel.Size = new System.Drawing.Size(20, 20);
@@ -128,42 +106,132 @@
       // searchTextBox
       // 
-      this.searchTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
-            | System.Windows.Forms.AnchorStyles.Right)));
-      this.searchTextBox.Location = new System.Drawing.Point(29, 3);
+      this.searchTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.searchTextBox.Location = new System.Drawing.Point(32, 19);
       this.searchTextBox.Name = "searchTextBox";
-      this.searchTextBox.Size = new System.Drawing.Size(270, 20);
+      this.searchTextBox.Size = new System.Drawing.Size(388, 20);
       this.searchTextBox.TabIndex = 1;
       this.toolTip.SetToolTip(this.searchTextBox, "Enter string to search for resources");
       this.searchTextBox.TextChanged += new System.EventHandler(this.searchTextBox_TextChanged);
       // 
-      // descriptionTextBox
-      // 
-      this.descriptionTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-            | System.Windows.Forms.AnchorStyles.Left)
-            | System.Windows.Forms.AnchorStyles.Right)));
-      this.descriptionTextBox.Font = new System.Drawing.Font("Courier New", 8.25F);
-      this.descriptionTextBox.Location = new System.Drawing.Point(3, 3);
-      this.descriptionTextBox.Multiline = true;
-      this.descriptionTextBox.Name = "descriptionTextBox";
-      this.descriptionTextBox.ReadOnly = true;
-      this.descriptionTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both;
-      this.descriptionTextBox.Size = new System.Drawing.Size(296, 108);
-      this.descriptionTextBox.TabIndex = 0;
-      this.descriptionTextBox.WordWrap = false;
-      // 
-      // HiveResourceSelector
-      // 
-      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      // splitContainer2
+      // 
+      this.splitContainer2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.splitContainer2.Location = new System.Drawing.Point(6, 45);
+      this.splitContainer2.Name = "splitContainer2";
+      // 
+      // splitContainer2.Panel1
+      // 
+      this.splitContainer2.Panel1.Controls.Add(this.projectsTreeView);
+      // 
+      // splitContainer2.Panel2
+      // 
+      this.splitContainer2.Panel2.Controls.Add(this.resourcesTreeView);
+      this.splitContainer2.Size = new System.Drawing.Size(414, 410);
+      this.splitContainer2.SplitterDistance = 204;
+      this.splitContainer2.TabIndex = 4;
+      // 
+      // projectsTreeView
+      // 
+      this.projectsTreeView.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.projectsTreeView.HideSelection = false;
+      this.projectsTreeView.ImageIndex = 0;
+      this.projectsTreeView.ImageList = this.projectsImageList;
+      this.projectsTreeView.Location = new System.Drawing.Point(0, 0);
+      this.projectsTreeView.Name = "projectsTreeView";
+      this.projectsTreeView.SelectedImageIndex = 0;
+      this.projectsTreeView.ShowNodeToolTips = true;
+      this.projectsTreeView.Size = new System.Drawing.Size(204, 410);
+      this.projectsTreeView.TabIndex = 3;
+      this.projectsTreeView.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.projectsTreeView_MouseDoubleClick);
+      this.projectsTreeView.BeforeSelect += new System.Windows.Forms.TreeViewCancelEventHandler(this.projectsTreeView_BeforeSelect);
+      this.projectsTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.projectsTreeView_AfterSelect);
+      // 
+      // resourcesTreeView
+      // 
+      this.resourcesTreeView.CheckBoxes = true;
+      this.resourcesTreeView.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.resourcesTreeView.ImageIndex = 0;
+      this.resourcesTreeView.ImageList = this.resourcesImageList;
+      this.resourcesTreeView.Location = new System.Drawing.Point(0, 0);
+      this.resourcesTreeView.Name = "resourcesTreeView";
+      this.resourcesTreeView.SelectedImageIndex = 0;
+      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);
+      this.resourcesTreeView.BeforeSelect += new System.Windows.Forms.TreeViewCancelEventHandler(this.resourcesTreeView_BeforeSelect);
+      // 
+      // summaryGroupBox
+      // 
+      this.summaryGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.summaryGroupBox.Controls.Add(this.memorySummaryLabel);
+      this.summaryGroupBox.Controls.Add(this.memoryLabel);
+      this.summaryGroupBox.Controls.Add(this.coresSummaryLabel);
+      this.summaryGroupBox.Controls.Add(this.coresLabel);
+      this.summaryGroupBox.Location = new System.Drawing.Point(3, 470);
+      this.summaryGroupBox.Name = "summaryGroupBox";
+      this.summaryGroupBox.Size = new System.Drawing.Size(426, 71);
+      this.summaryGroupBox.TabIndex = 1;
+      this.summaryGroupBox.TabStop = false;
+      this.summaryGroupBox.Text = "Computing Resources";
+      // 
+      // coresLabel
+      // 
+      this.coresLabel.AutoSize = true;
+      this.coresLabel.Location = new System.Drawing.Point(6, 22);
+      this.coresLabel.Name = "coresLabel";
+      this.coresLabel.Size = new System.Drawing.Size(37, 13);
+      this.coresLabel.TabIndex = 1;
+      this.coresLabel.Text = "Cores:";
+      // 
+      // coresSummaryLabel
+      // 
+      this.coresSummaryLabel.AutoSize = true;
+      this.coresSummaryLabel.Location = new System.Drawing.Point(59, 22);
+      this.coresSummaryLabel.Name = "coresSummaryLabel";
+      this.coresSummaryLabel.Size = new System.Drawing.Size(124, 13);
+      this.coresSummaryLabel.TabIndex = 5;
+      this.coresSummaryLabel.Text = "0 Total (0 Free / 0 Used)";
+      // 
+      // memoryLabel
+      // 
+      this.memoryLabel.AutoSize = true;
+      this.memoryLabel.Location = new System.Drawing.Point(6, 48);
+      this.memoryLabel.Name = "memoryLabel";
+      this.memoryLabel.Size = new System.Drawing.Size(47, 13);
+      this.memoryLabel.TabIndex = 7;
+      this.memoryLabel.Text = "Memory:";
+      // 
+      // memorySummaryLabel
+      // 
+      this.memorySummaryLabel.AutoSize = true;
+      this.memorySummaryLabel.Location = new System.Drawing.Point(59, 48);
+      this.memorySummaryLabel.Name = "memorySummaryLabel";
+      this.memorySummaryLabel.Size = new System.Drawing.Size(223, 13);
+      this.memorySummaryLabel.TabIndex = 8;
+      this.memorySummaryLabel.Text = "0.00 GB Total (0.00 GB Free / 0.00 GB Used)";
+      // 
+      // HiveProjectSelector
+      // 
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
-      this.Controls.Add(this.resourcesGroupBox);
-      this.Name = "HiveResourceSelector";
-      this.Size = new System.Drawing.Size(308, 365);
-      this.resourcesGroupBox.ResumeLayout(false);
-      this.splitContainer.Panel1.ResumeLayout(false);
-      this.splitContainer.Panel1.PerformLayout();
-      this.splitContainer.Panel2.ResumeLayout(false);
-      this.splitContainer.Panel2.PerformLayout();
-      ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit();
-      this.splitContainer.ResumeLayout(false);
+      this.Controls.Add(this.summaryGroupBox);
+      this.Controls.Add(this.projectsGroupBox);
+      this.Name = "HiveProjectSelector";
+      this.Size = new System.Drawing.Size(432, 544);
+      this.Load += new System.EventHandler(this.HiveProjectSelector_Load);
+      this.projectsGroupBox.ResumeLayout(false);
+      this.projectsGroupBox.PerformLayout();
+      this.splitContainer2.Panel1.ResumeLayout(false);
+      this.splitContainer2.Panel2.ResumeLayout(false);
+      ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit();
+      this.splitContainer2.ResumeLayout(false);
+      this.summaryGroupBox.ResumeLayout(false);
+      this.summaryGroupBox.PerformLayout();
       this.ResumeLayout(false);
 
@@ -172,13 +240,18 @@
     #endregion
 
-    protected System.Windows.Forms.GroupBox resourcesGroupBox;
-    protected System.Windows.Forms.SplitContainer splitContainer;
+    protected System.Windows.Forms.GroupBox projectsGroupBox;
     protected System.Windows.Forms.Label searchLabel;
     protected System.Windows.Forms.TextBox searchTextBox;
-    protected System.Windows.Forms.TreeView resourcesTreeView;
-    protected System.Windows.Forms.TextBox descriptionTextBox;
-    protected System.Windows.Forms.ImageList imageList;
+    protected System.Windows.Forms.ImageList projectsImageList;
     protected System.Windows.Forms.ToolTip toolTip;
-
+    private System.Windows.Forms.ImageList resourcesImageList;
+    private System.Windows.Forms.SplitContainer splitContainer2;
+    protected System.Windows.Forms.TreeView projectsTreeView;
+    protected HeuristicLab.Clients.Hive.Views.TreeView.NoDoubleClickTreeView resourcesTreeView;
+    private System.Windows.Forms.GroupBox summaryGroupBox;
+    protected System.Windows.Forms.Label coresLabel;
+    protected System.Windows.Forms.Label memorySummaryLabel;
+    protected System.Windows.Forms.Label memoryLabel;
+    protected System.Windows.Forms.Label coresSummaryLabel;
   }
 }
Index: trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.cs
===================================================================
--- trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.cs	(revision 15682)
+++ trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelector.cs	(revision 16117)
@@ -1,5 +1,5 @@
 ﻿#region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -24,7 +24,7 @@
 using System.Drawing;
 using System.Linq;
-using System.Text;
 using System.Windows.Forms;
-using HeuristicLab.Clients.Hive.JobManager.ExtensionMethods;
+using HeuristicLab.Collections;
+using HeuristicLab.Common.Resources;
 using HeuristicLab.Core;
 using HeuristicLab.Core.Views;
@@ -33,295 +33,803 @@
 
 namespace HeuristicLab.Clients.Hive.JobManager.Views {
-  [View("Hive Resource Selector View")]
-  [Content(typeof(IItemList<Resource>), true)]
-  public partial class HiveResourceSelector : ItemView, IDisposable {
+  [View("Hive Project Selector View")]
+  [Content(typeof(IItemList<Project>), true)]
+  public partial class HiveProjectSelector : ItemView, IDisposable {
+    private const int greenFlagImageIndex = 0;
+    private const int redFlagImageIndex = 1;
     private const int slaveImageIndex = 0;
     private const int slaveGroupImageIndex = 1;
+    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 const string CURRENT_SELECTION_TAG = " [current assignment]";
+    private const string NEW_SELECTION_TAG = " [new assignment]";
+    private const string CHANGED_SELECTION_TAG = " [changed assignment]";
+    private const string ADDED_SELECTION_TAG = " [added assignment]";
+    private const string REMOVED_SELECTION_TAG = " [removed assignment]";
+    private const string SELECTED_TAG = " [assigned]";
+    private const string INCLUDED_TAG = " [included]";
+    private const string ADDED_INCLUDE_TAG = " [added include]";
+    private const string REMOVED_INCLUDE_TAG = " [removed include]";
+
+    private TreeNode additionalNode;
+
+    private readonly HashSet<TreeNode> mainTreeNodes = new HashSet<TreeNode>();
+    private readonly HashSet<TreeNode> filteredTreeNodes = 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 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 selectedBackColor = Color.DodgerBlue;
+    private readonly Color selectedForeColor = Color.White;
+    private readonly Color controlTextColor = SystemColors.ControlText;
+    private readonly Color grayTextColor = SystemColors.GrayText;
+
     private string currentSearchString;
-    private ISet<TreeNode> mainTreeNodes;
-    private ISet<TreeNode> filteredTreeNodes;
-    private ISet<TreeNode> nodeStore;
-    
-    private ISet<Resource> selectedResources;
-    public ISet<Resource> SelectedResources {
-      get { return selectedResources; }
-      set { selectedResources = value; }
-    }
-
-    public new IItemList<Resource> Content {
-      get { return (IItemList<Resource>)base.Content; }
+
+    private void resetHiveResourceSelector() {
+      lastSelectedProject = null;
+      selectedProject = null;
+      projectId = null;
+    }
+
+    private Guid jobId;
+    public Guid JobId {
+      get { return jobId; }
+      set {
+        if (jobId == value) return;
+        jobId = value;
+        resetHiveResourceSelector();
+      }
+    }
+
+    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;
+      }
+    }
+
+    private IEnumerable<Guid> selectedResourceIds;
+    public IEnumerable<Guid> SelectedResourceIds {
+      get { return selectedResourceIds; }
+      set {
+        if (selectedResourceIds == value) return;
+        selectedResourceIds = value;
+      }
+    }
+
+    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 {
+        if (selectedProject == value) return;
+
+        if ((JobId == Guid.Empty || JobId == null) 
+          && (value == null || SelectedProject == null || value.Id != SelectedProject.Id)) selectedResourceIds = null;
+        lastSelectedProject = selectedProject;
+        selectedProject = value;
+
+        UpdateResourceTree();
+        ExtractStatistics();
+        OnSelectedProjectChanged();
+      }
+    }
+
+    public int AssignedCores {
+      get {
+        HashSet<Slave> newAssignedSlaves = new HashSet<Slave>(newAssignedResources.OfType<Slave>());
+        foreach(var slaveGroup in newAssignedResources.OfType<SlaveGroup>()) {
+          foreach(var slave in HiveClient.Instance.GetAvailableResourceDescendants(slaveGroup.Id).OfType<Slave>()) {
+            newAssignedSlaves.Add(slave);
+          }
+        }
+        return newAssignedSlaves.Sum(x => x.Cores.GetValueOrDefault());
+      }
+    }
+
+    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 {
+      get { return (IItemList<Project>)base.Content; }
       set { base.Content = value; }
     }
 
-    public HiveResourceSelector() {
+    public HiveProjectSelector() {
       InitializeComponent();
-      mainTreeNodes = new HashSet<TreeNode>();
-      filteredTreeNodes = new HashSet<TreeNode>();
-      nodeStore = new HashSet<TreeNode>();
-      selectedResources = new HashSet<Resource>();
-      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<HeuristicLab.MainForm.WindowsForms.MainForm>().AddOperationProgressToView(this, message);
-      }
-    }
-
-    public void FinishProgressView() {
-      if (InvokeRequired) {
-        Invoke(new Action(FinishProgressView));
-      } else {
-        MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().RemoveOperationProgressFromView(this);
-      }
-    }
-
+
+      projectsImageList.Images.Add(VSImageLibrary.FlagGreen);
+      projectsImageList.Images.Add(VSImageLibrary.FlagRed);
+      resourcesImageList.Images.Add(VSImageLibrary.MonitorLarge);
+      resourcesImageList.Images.Add(VSImageLibrary.NetworkCenterLarge);
+    }
+
+    #region Overrides
     protected override void OnContentChanged() {
       base.OnContentChanged();
 
-      if (Content != null) {
-        selectedResources = new HashSet<Resource>(Content.Where(x => selectedResources.Any(y => x.Id == y.Id)));
-        UpdateMainTree();
+      if (Content != null) {               
+        if (SelectedProjectId.HasValue && SelectedProjectId.Value != Guid.Empty) {
+          SelectedProject = GetSelectedProjectById(SelectedProjectId.Value);
+        } else {
+          SelectedProject = null;
+        }
+        //ExtractStatistics();
+        UpdateProjectTree();
+
+      } else {
+        lastSelectedProject = null;
+        selectedProject = null;
+        selectedProjectId = null;
+        projectsTreeView.Nodes.Clear();
+        resourcesTreeView.Nodes.Clear();
+      }
+    }
+
+    #endregion
+
+    #region Event Handlers
+    private void HiveProjectSelector_Load(object sender, EventArgs e) {
+      projectsTreeView.Nodes.Clear();
+      resourcesTreeView.Nodes.Clear();
+    }
+
+    private void searchTextBox_TextChanged(object sender, EventArgs e) {
+      currentSearchString = searchTextBox.Text.ToLower();
+      //UpdateFilteredTree();
+      UpdateProjectTree();
+    }
+
+    private void projectsTreeView_MouseDoubleClick(object sender, MouseEventArgs e) {
+      OnProjectsTreeViewDoubleClicked();
+    }
+
+    private void projectsTreeView_BeforeSelect(object sender, TreeViewCancelEventArgs e) {
+      var node = (Project)e.Node.Tag;
+      if (HiveClient.Instance.DisabledParentProjects.Contains(node)) {
+        e.Cancel = true;
+      }
+    }
+
+    private void projectsTreeView_AfterSelect(object sender, TreeViewEventArgs e) {
+      var node = (Project)e.Node.Tag;
+
+      if (node == null) {
+        projectsTreeView.SelectedNode = null;
+      } else if (HiveClient.Instance.DisabledParentProjects.Contains(node)) {
+        return;
+      } else {
+        ResetTreeNodes(projectsTreeView.Nodes);
+        e.Node.BackColor = selectedBackColor;
+        e.Node.ForeColor = selectedForeColor;
+
+        if (node.Id == projectId) {
+          e.Node.Text += CURRENT_SELECTION_TAG;
+        } else if (projectId == null || projectId == Guid.Empty) {
+          e.Node.Text += NEW_SELECTION_TAG;
+        } else {
+          e.Node.Text += CHANGED_SELECTION_TAG;
+        }
+
+
+      }
+      SelectedProject = node;
+    }
+
+    private void resourcesTreeView_MouseDown(object sender, MouseEventArgs e) {
+      var node = resourcesTreeView.GetNodeAt(new Point(e.X, e.Y));
+
+      if (node == null || node == additionalNode) {
+        resourcesTreeView.SelectedNode = null;
         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);
-      }
+        var r = (Resource)node.Tag;
+        if (!HiveClient.Instance.DisabledParentResources.Contains(r)) {
+          ExtractStatistics((Resource)node.Tag);
+        } else {
+          resourcesTreeView.SelectedNode = null;
+          ExtractStatistics();
+        } 
+      }
+    }
+
+    private void resourcesTreeView_BeforeSelect(object sender, TreeViewCancelEventArgs e) {
+      if(e.Node == null || e.Node == additionalNode) {
+        e.Cancel = true;
+      } else {
+        var r = (Resource)e.Node.Tag;
+        if(r == null || HiveClient.Instance.DisabledParentResources.Contains(r)) {
+          e.Cancel = true;
+        }
+      }
+
+    }
+
+    private void resourcesTreeView_BeforeCheck(object sender, TreeViewCancelEventArgs e) {
+      if(e.Node == null || e.Node == additionalNode) {
+        e.Cancel = true;
+      } else {
+        var checkedResource = (Resource)e.Node.Tag;
+        if (checkedResource == null
+          || checkedResource.Id == Guid.Empty
+          || HiveClient.Instance.DisabledParentResources.Contains(checkedResource)
+          || newIncludedResources.Contains(checkedResource)) {
+          e.Cancel = true;
+
+          var selectedNode = resourcesTreeView.SelectedNode;
+          var selectedResource = (Resource)(selectedNode != null ? selectedNode.Tag : null);
+
+          ExtractStatistics(selectedResource);
+        }
+      }
+    }
+
+    private void resourcesTreeView_AfterCheck(object sender, TreeViewEventArgs e) {
+      var checkedResource = (Resource)e.Node.Tag;
+      if (e.Node.Checked) {
+        newAssignedResources.Add(checkedResource);
+      } else {
+        newAssignedResources.Remove(checkedResource);
+      }
+
+      UpdateResourceTreeAfterCheck();
+      ExtractStatistics();
+      OnAssignedResourcesChanged();
+    }
+
+    private void resourcesTreeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) {
+      return;
     }
     #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);
-      }
-    }
+    #region Helpers
+
+    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(Content.Where(p => HiveClient.Instance.GetAvailableProjectAncestors(project.Id).Select(x => x.Id).Contains(p.Id)));
+          }
+        }
+        BuildProjectTree(filteredProjects);
+      }
+    }
+
+    private void BuildProjectTree(IEnumerable<Project> projects) {
+      projectsTreeView.Nodes.Clear();
+      if (!projects.Any()) return;
+
+      var disabledParentProjects = HiveClient.Instance.DisabledParentProjects;
+      // select all top level projects (withouth parent, or without any ancestor 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)
+      //  && !projects.SelectMany(y => HiveClient.Instance.ProjectAncestors[y.Id]).Contains(x.ParentProjectId.Value)));
+      //mainProjects.UnionWith(parentedMainProjects);
+      var mainDisabledParentProjects = new HashSet<Project>(disabledParentProjects.Where(x => x.ParentProjectId == null || x.ParentProjectId == Guid.Empty));
+      mainProjects.UnionWith(mainDisabledParentProjects);
+      var subProbjects = new HashSet<Project>(projects.Union(disabledParentProjects).Except(mainProjects));
+      //foreach (var p in subProbjects) {
+      //  p.ParentProjectId = HiveClient.Instance.ProjectAncestors[p.Id].Where(x => projects.Select(y => y.Id).Contains(x)).FirstOrDefault();
+      //}
+
+      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(disabledParentProjects.Contains(newProject)) {
+          newNode.Checked = false;
+          newNode.ForeColor = grayTextColor;
+        }
+        else if (SelectedProject != null && SelectedProject.Id.Equals(newProject.Id)) {
+          newNode.BackColor = selectedBackColor;
+          newNode.ForeColor = selectedForeColor;
+          if(SelectedProject.Id == projectId) {
+            newNode.Text += CURRENT_SELECTION_TAG;
+          } else if (projectId == null || projectId == Guid.Empty) {
+            newNode.Text += NEW_SELECTION_TAG;
+          } else {
+            newNode.Text += CHANGED_SELECTION_TAG;
+          }
+        }
+
+        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 static IEnumerable<Resource> GetAssignedResourcesForProject(Guid projectId) {
+      var assignedProjectResources = HiveServiceLocator.Instance.CallHiveService(s => s.GetAssignedResourcesForProject(projectId));
+      return HiveClient.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 HiveClient.Instance.Resources.Where(x => assignedJobResources.Select(y => y.ResourceId).Contains(x.Id));
+    }
+
+    private void UpdateResourceTree() {
+      UpdateAvailableResources();
+      UpdateAssignedResources();
+      UpdateIncludedResources();
+      BuildResourceTree(availableResources);
+    }
+
+    private void UpdateResourceTreeAfterCheck() {
+      resourcesTreeView.BeforeCheck -= resourcesTreeView_BeforeCheck;
+      resourcesTreeView.AfterCheck -= resourcesTreeView_AfterCheck;
+      UpdateNewAssignedResources();
+      UpdateNewIncludedResources();
+      SetTreeNodes(resourcesTreeView.Nodes);
+      resourcesTreeView.BeforeCheck += resourcesTreeView_BeforeCheck;
+      resourcesTreeView.AfterCheck += resourcesTreeView_AfterCheck;
+    }
+
+    private void UpdateAvailableResources() {
+      availableResources.Clear();
+      if (selectedProject != null) {
+        var assignedProjectResources = GetAssignedResourcesForProject(selectedProject.Id);
+        foreach (var resource in assignedProjectResources) {
+          availableResources.Add(resource);
+          foreach(var descendant in HiveClient.Instance.Resources.Where(x => HiveClient.Instance.ResourceDescendants[resource.Id].Contains(x.Id))) {
+            availableResources.Add(descendant);
+          }
+        }
+      }
+      //ExtractStatistics();
+      //OnAssignedResourcesChanged();
+    }
+
+    private void UpdateAssignedResources() {
+      assignedResources.Clear();
+      newAssignedResources.Clear();
+
+      if (JobId == Guid.Empty || JobId == null) { // new, unchanged jobs get all avaialable resources
+        // update new assigned resources
+        if(selectedResourceIds == null) {
+          foreach (var resource in availableResources
+            .Where(x => !x.ParentResourceId.HasValue
+            || !availableResources.Select(y => y.Id).Contains(x.ParentResourceId.Value))) {
+            newAssignedResources.Add(resource);
+          }
+        } else {
+          foreach(var resource in availableResources.Where(x => selectedResourceIds.Contains(x.Id))) {
+            newAssignedResources.Add(resource);
+          }
+        }
+      } else if(selectedProject.Id == projectId) { // existent, unchanged jobs get all assigned resources
+        // update assigned resources
+        var assignedJobResources = GetAssignedResourcesForJob(JobId);
+        foreach (var resource in assignedJobResources) {
+          assignedResources.Add(resource);
+          if (selectedResourceIds == null) {
+            newAssignedResources.Add(resource);
+          }
+        }
+
+        if(selectedResourceIds != null) {
+          foreach (var resource in availableResources.Where(x => selectedResourceIds.Contains(x.Id))) {
+            newAssignedResources.Add(resource);
+          }
+        }
+      }
+
+      //ExtractStatistics();
+      OnAssignedResourcesChanged();
+    }
+
+    private void UpdateNewAssignedResources() {
+      for(int i = newAssignedResources.Count-1; i>=0; i--) {
+        if(newAssignedResources.Intersect(HiveClient.Instance.GetAvailableResourceAncestors(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 HiveClient.Instance.GetAvailableResourceDescendants(item.Id)) {
+            includedResources.Add(descendant);
+          }
+        }
+      }
+
+      foreach (var item in newAssignedResources) {
+        foreach (var descendant in HiveClient.Instance.GetAvailableResourceDescendants(item.Id)) {
+          newIncludedResources.Add(descendant);
+        }
+      }
+    }
+
+    private void UpdateNewIncludedResources() {
+      newIncludedResources.Clear();
+      foreach (var item in newAssignedResources) {
+        foreach (var descendant in HiveClient.Instance.GetAvailableResourceDescendants(item.Id)) {
+          newIncludedResources.Add(descendant);
+        }
+      }
+    }
+
+    private void BuildResourceTree(IEnumerable<Resource> resources) {
+      resourcesTreeView.Nodes.Clear();
+      if (!resources.Any()) return;
+
+      resourcesTreeView.BeforeCheck -= resourcesTreeView_BeforeCheck;
+      resourcesTreeView.AfterCheck -= resourcesTreeView_AfterCheck;
+
+      var disabledParentResources = HiveClient.Instance.DisabledParentResources;
+      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 mainDisabledParentResources = new HashSet<Resource>(disabledParentResources.Where(x => x.ParentResourceId == null || x.ParentResourceId == Guid.Empty));
+      mainResources.UnionWith(mainDisabledParentResources);
+      var subResources = new HashSet<Resource>(resources.Union(disabledParentResources).Except(mainResources).OrderByDescending(x => x.Name));
+
+      var addedAssignments = newAssignedResources.Except(assignedResources);
+      var removedAssignments = assignedResources.Except(newAssignedResources);
+      var addedIncludes = newIncludedResources.Except(includedResources);
+      var removedIncludes = includedResources.Except(newIncludedResources);
+
+      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 (disabledParentResources.Contains(newResource)) {
+          newNode.Checked = false;
+          newNode.ForeColor = grayTextColor;
+        } else if (newAssignedResources.Select(x => x.Id).Contains(newResource.Id)) {
+          newNode.Checked = true;
+          if(!addedAssignments.Select(x => x.Id).Contains(newResource.Id) && !removedAssignments.Select(x => x.Id).Contains(newResource.Id)) {
+            newNode.Text += SELECTED_TAG;
+          }
+        } else if (newIncludedResources.Select(x => x.Id).Contains(newResource.Id)) {
+          newNode.Checked = true;
+          newNode.ForeColor = grayTextColor;
+        }
+
+        if (includedResources.Select(x => x.Id).Contains(newResource.Id) && newIncludedResources.Select(x => x.Id).Contains(newResource.Id)) {
+          newNode.Text += INCLUDED_TAG;
+        } else if (addedIncludes.Select(x => x.Id).Contains(newResource.Id)) {
+          newNode.BackColor = addedIncludeColor;
+          newNode.ForeColor = grayTextColor;
+          newNode.Text += ADDED_INCLUDE_TAG;
+        } else if (removedIncludes.Select(x => x.Id).Contains(newResource.Id)) {
+          newNode.BackColor = removedIncludeColor;
+          newNode.Text += REMOVED_INCLUDE_TAG;
+        }
+
+        if (addedAssignments.Select(x => x.Id).Contains(newResource.Id)) {
+          newNode.BackColor = addedAssignmentColor;
+          newNode.ForeColor = controlTextColor;
+          newNode.Text += ADDED_SELECTION_TAG;
+        } else if (removedAssignments.Select(x => x.Id).Contains(newResource.Id)) {
+          newNode.BackColor = removedAssignmentColor;
+          newNode.ForeColor = controlTextColor;
+          newNode.Text += REMOVED_SELECTION_TAG;
+        }
+
+        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()) {
+
+        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);
+      }
+
+      ExpandResourceNodesOfInterest(resourcesTreeView.Nodes);
+
+      resourcesTreeView.BeforeCheck += resourcesTreeView_BeforeCheck;
+      resourcesTreeView.AfterCheck += resourcesTreeView_AfterCheck;
+    }
+
+    private void ExpandResourceNodesOfInterest(TreeNodeCollection nodes) {
+      foreach(TreeNode n in nodes) {
+        Resource r = (Resource)n.Tag;
+        if(n.Nodes.Count > 0) {
+          if(HiveClient.Instance.GetAvailableResourceDescendants(r.Id).OfType<SlaveGroup>().Any()
+            || HiveClient.Instance.GetAvailableResourceDescendants(r.Id).OfType<Slave>().Intersect(assignedResources.Union(newAssignedResources)).Any()) {
+            n.Expand();
+            ExpandResourceNodesOfInterest(n.Nodes);
+          } else {
+            n.Collapse();
+          }   
+        } else {
+          n.Collapse();
+        }
+      }
+    }
+
+    private void CollapseSlaveOnlyNodes(TreeNode tn) {
+      if (!(tn.Tag is Resource)) return;
+
+      Resource r = (Resource)tn.Tag;
+      if (HiveClient.Instance.GetAvailableResourceDescendants(r.Id).OfType<SlaveGroup>().Any()) {
+        tn.Expand();
+        foreach (TreeNode n in tn.Nodes) CollapseSlaveOnlyNodes(n);
+      } else {
+        tn.Collapse();
+      }
+    }
+
+    private void ExtractStatistics(Resource resource = null) { 
+      HashSet<Slave> newAssignedSlaves = new HashSet<Slave>(newAssignedResources.OfType<Slave>());
+      foreach (var slaveGroup in newAssignedResources.OfType<SlaveGroup>()) {
+        foreach (var slave in HiveClient.Instance.GetAvailableResourceDescendants(slaveGroup.Id).OfType<Slave>()) {
+          newAssignedSlaves.Add(slave);
+        }
+      }
+
+      HashSet<Slave> selectedSlaves = null;
+
+      if (resource != null) {
+        var slaveGroup = resource as SlaveGroup;
+        if (slaveGroup != null) {
+          selectedSlaves = new HashSet<Slave>(HiveClient.Instance.GetAvailableResourceDescendants(slaveGroup.Id).OfType<Slave>());
+        } else {
+          selectedSlaves = new HashSet<Slave>(new[] { resource as Slave });
+        }
+      } else {
+        selectedSlaves = newAssignedSlaves;
+      }
+
+      int sumCores = selectedSlaves.Sum(x => x.Cores.GetValueOrDefault());
+      int sumFreeCores = selectedSlaves.Sum(x => x.FreeCores.GetValueOrDefault());
+      double sumMemory = selectedSlaves.Sum(x => x.Memory.GetValueOrDefault()) / 1024.0;
+      double sumFreeMemory = selectedSlaves.Sum(x => x.FreeMemory.GetValueOrDefault()) / 1024.0;
+
+      coresSummaryLabel.Text = string.Format("{0} Total ({1} Free / {2} Used)", sumCores, sumFreeCores, sumCores - sumFreeCores);
+      memorySummaryLabel.Text = string.Format("{0:0.00} GB Total ({1:0.00} GB Free / {2:0.00} GB Used)", sumMemory, sumFreeMemory, sumMemory - sumFreeMemory);
+    }
+
+    private void StyleTreeNode(TreeNode n, string name) {
+      n.Text = name;
+      n.BackColor = Color.Transparent;
+      n.ForeColor = Color.Black;
+
+      if(n.Tag is Project) {
+        var p = (Project)n.Tag;
+        if(HiveClient.Instance.DisabledParentProjects.Select(x => x.Id).Contains(p.Id)) {
+          n.Checked = false;
+          n.ForeColor = grayTextColor;
+        }
+      } else if(n.Tag is Resource) {
+        var r = (Resource)n.Tag;
+        if(HiveClient.Instance.DisabledParentResources.Select(x => x.Id).Contains(r.Id) || n == additionalNode) {
+          n.Checked = false;
+          n.ForeColor = grayTextColor;
+        }
+      }
+    }
+
+    private void ResetTreeNodes(TreeNodeCollection nodes) {
+      foreach (TreeNode n in nodes) {
+        string name = "";
+        if (n.Tag is Project) name = ((Project)n.Tag).Name;
+        else if (n.Tag is Resource) name = ((Resource)n.Tag).Name;
+        StyleTreeNode(n, name);
+        if (n.Nodes.Count > 0) {
+          ResetTreeNodes(n.Nodes);
+        }
+      }
+    }
+
+    private void SetTreeNodes(TreeNodeCollection nodes) {
+      var addedAssignments = newAssignedResources.Except(assignedResources);
+      var removedAssignments = assignedResources.Except(newAssignedResources);
+      var addedIncludes = newIncludedResources.Except(includedResources);
+      var removedIncludes = includedResources.Except(newIncludedResources);
+
+      foreach (TreeNode n in nodes) {
+
+        if(n.Tag is Resource) {
+          // reset
+          var resource = (Resource)n.Tag;
+          n.Text = resource.Name;
+          n.BackColor = Color.Transparent;
+          n.ForeColor = Color.Black;
+          n.Checked = false;
+
+          if (HiveClient.Instance.DisabledParentResources.Select(x => x.Id).Contains(resource.Id) || n == additionalNode) {
+            n.ForeColor = grayTextColor;
+          }
+
+          // add additional info
+          if (newAssignedResources.Select(x => x.Id).Contains(resource.Id)) {
+            n.Checked = true;
+            if (!addedAssignments.Select(x => x.Id).Contains(resource.Id) && !removedAssignments.Select(x => x.Id).Contains(resource.Id)) {
+              n.Text += SELECTED_TAG;
+            }
+          } else if (newIncludedResources.Select(x => x.Id).Contains(resource.Id)) {
+            n.Checked = true;
+            n.ForeColor = grayTextColor;
+          }
+
+          if (includedResources.Select(x => x.Id).Contains(resource.Id) && newIncludedResources.Select(x => x.Id).Contains(resource.Id)) {
+            n.Text += INCLUDED_TAG;
+          } else if (addedIncludes.Select(x => x.Id).Contains(resource.Id)) {
+            n.BackColor = addedIncludeColor;
+            n.ForeColor = grayTextColor;
+            n.Text += ADDED_INCLUDE_TAG;
+          } else if (removedIncludes.Select(x => x.Id).Contains(resource.Id)) {
+            n.BackColor = removedIncludeColor;
+            n.Text += REMOVED_INCLUDE_TAG;
+          }
+
+          if (addedAssignments.Select(x => x.Id).Contains(resource.Id)) {
+            n.BackColor = addedAssignmentColor;
+            n.ForeColor = controlTextColor;
+            n.Text += ADDED_SELECTION_TAG;
+          } else if (removedAssignments.Select(x => x.Id).Contains(resource.Id)) {
+            n.BackColor = removedAssignmentColor;
+            n.ForeColor = controlTextColor;
+            n.Text += REMOVED_SELECTION_TAG;
+          }
+        }
+
+        if(n.Nodes.Count > 0) {
+          SetTreeNodes(n.Nodes);
+        }
+      }
+    }
+
     #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<TreeNode>().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<Resource> resources = treeNode == null ? selectedResources : new HashSet<Resource>(treeNode.DescendantNodes().Select(x => x.Tag as Resource)); ;
-      IEnumerable<SlaveGroup> slaveGroups = resources.OfType<SlaveGroup>();
-      IEnumerable<Slave> slaves = resources.OfType<Slave>();
-      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();
+    public event EventHandler SelectedProjectChanged;
+    private void OnSelectedProjectChanged() {
+      var handler = SelectedProjectChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler AssignedResourcesChanged;
+    private void OnAssignedResourcesChanged() {
+      var handler = AssignedResourcesChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler ProjectsTreeViewDoubleClicked;
+    private void OnProjectsTreeViewDoubleClicked() {
+      var handler = ProjectsTreeViewDoubleClicked;
+      if (handler != null) handler(this, EventArgs.Empty);
     }
     #endregion
Index: trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelectorDialog.Designer.cs
===================================================================
--- trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelectorDialog.Designer.cs	(revision 15682)
+++ trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelectorDialog.Designer.cs	(revision 16117)
@@ -45,9 +45,12 @@
     /// </summary>
     private void InitializeComponent() {
-      System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(HiveResourceSelectorDialog));
+      this.components = new System.ComponentModel.Container();
       this.okButton = new System.Windows.Forms.Button();
       this.cancelButton = new System.Windows.Forms.Button();
       this.refreshButton = new System.Windows.Forms.Button();
-      this.hiveResourceSelector = new HeuristicLab.Clients.Hive.JobManager.Views.HiveResourceSelector();
+      this.toolTip = new System.Windows.Forms.ToolTip(this.components);
+      this.errorProvider = new System.Windows.Forms.ErrorProvider(this.components);
+      this.hiveResourceSelector = new HeuristicLab.Clients.Hive.JobManager.Views.HiveProjectSelector();
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
       this.SuspendLayout();
       // 
@@ -56,4 +59,5 @@
       this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
       this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK;
+      this.okButton.Enabled = false;
       this.okButton.Location = new System.Drawing.Point(405, 609);
       this.okButton.Name = "okButton";
@@ -62,4 +66,6 @@
       this.okButton.Text = "&OK";
       this.okButton.UseVisualStyleBackColor = true;
+      this.errorProvider.SetIconAlignment(this.okButton, System.Windows.Forms.ErrorIconAlignment.MiddleLeft);
+      this.errorProvider.SetIconPadding(this.okButton, 2);
       // 
       // cancelButton
@@ -82,24 +88,37 @@
       this.refreshButton.Size = new System.Drawing.Size(24, 24);
       this.refreshButton.TabIndex = 3;
+      this.toolTip.SetToolTip(this.refreshButton, "Refresh data");
       this.refreshButton.UseVisualStyleBackColor = true;
       this.refreshButton.Click += new System.EventHandler(this.refreshButton_Click);
       // 
+      // errorProvider
+      // 
+      this.errorProvider.BlinkStyle = System.Windows.Forms.ErrorBlinkStyle.NeverBlink;
+      this.errorProvider.ContainerControl = this;
+      // 
       // hiveResourceSelector
       // 
-      this.hiveResourceSelector.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-            | System.Windows.Forms.AnchorStyles.Left)
+      this.hiveResourceSelector.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
       this.hiveResourceSelector.Caption = "View";
       this.hiveResourceSelector.Content = null;
+      this.hiveResourceSelector.JobId = new System.Guid("00000000-0000-0000-0000-000000000000");
       this.hiveResourceSelector.Location = new System.Drawing.Point(12, 12);
       this.hiveResourceSelector.Name = "hiveResourceSelector";
+      this.hiveResourceSelector.ProjectId = null;
       this.hiveResourceSelector.ReadOnly = false;
+      this.hiveResourceSelector.SelectedProject = null;
+      this.hiveResourceSelector.SelectedProjectId = null;
+      this.hiveResourceSelector.SelectedResourceIds = null;
       this.hiveResourceSelector.Size = new System.Drawing.Size(549, 591);
       this.hiveResourceSelector.TabIndex = 0;
+      this.hiveResourceSelector.SelectedProjectChanged += new System.EventHandler(this.hiveResourceSelector_SelectedProjectChanged);
+      this.hiveResourceSelector.AssignedResourcesChanged += new System.EventHandler(this.hiveResourceSelector_SelectedResourcesChanged);
+      this.hiveResourceSelector.ProjectsTreeViewDoubleClicked += new System.EventHandler(this.hiveResourceSelector_ProjectsTreeViewDoubleClicked);
       // 
       // HiveResourceSelectorDialog
       // 
       this.AcceptButton = this.okButton;
-      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
       this.CancelButton = this.cancelButton;
@@ -115,7 +134,7 @@
       this.ShowInTaskbar = false;
       this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
-      this.Text = "Select Resources";
-      this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.HiveResourceSelectorDialog_FormClosing);
+      this.Text = "Select Project";
       this.Load += new System.EventHandler(this.HiveResourceSelectorDialog_Load);
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
       this.ResumeLayout(false);
 
@@ -126,6 +145,8 @@
     protected System.Windows.Forms.Button okButton;
     protected System.Windows.Forms.Button cancelButton;
-    protected HiveResourceSelector hiveResourceSelector;
     protected System.Windows.Forms.Button refreshButton;
+    protected System.Windows.Forms.ToolTip toolTip;
+    protected System.Windows.Forms.ErrorProvider errorProvider;
+    protected HiveProjectSelector hiveResourceSelector;
   }
 }
Index: trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelectorDialog.cs
===================================================================
--- trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelectorDialog.cs	(revision 15682)
+++ trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveResourceSelectorDialog.cs	(revision 16117)
@@ -20,47 +20,161 @@
 #endregion
 
+using System;
 using System.Collections.Generic;
-using System.Threading.Tasks;
+using System.ComponentModel;
+using System.Linq;
 using System.Windows.Forms;
-using HeuristicLab.PluginInfrastructure;
+using HeuristicLab.Clients.Hive.Views;
+using HeuristicLab.MainForm;
+using HeuristicLab.Core;
 
 namespace HeuristicLab.Clients.Hive.JobManager.Views {
   public partial class HiveResourceSelectorDialog : Form {
-    public HiveResourceSelectorDialog() {
+    private readonly object locker = new object();
+    private bool updatingProjects = false;
+
+    public Project SelectedProject {
+      get { return hiveResourceSelector.SelectedProject; }
+    }
+
+    public IEnumerable<Resource> SelectedResources {
+      get { return hiveResourceSelector.AssignedResources; }
+    }
+
+    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 the persisted projectId)
+    private Guid? selectedProjectId;
+    public Guid? SelectedProjectId {
+      get { return selectedProjectId; }
+      set { selectedProjectId = value; }
+    }
+
+    // currently selected resourceIds (if null, perform lookup in HiveResourceSelector)
+    private IEnumerable<Guid> selectedResourceIds;
+    public IEnumerable<Guid> SelectedResourceIds {
+      get { return selectedResourceIds; }
+      set { selectedResourceIds = value; }
+    }
+
+
+
+    public HiveResourceSelectorDialog(Guid jobId, Guid projectId) {
+      this.jobId = jobId;
+      this.projectId = projectId;
+      this.selectedProjectId = projectId;
       InitializeComponent();
     }
 
-    public ISet<Resource> GetSelectedResources() { return hiveResourceSelector.SelectedResources; }
-
-    private void HiveResourceSelectorDialog_Load(object sender, System.EventArgs e) {
-      HiveAdminClient.Instance.Refreshed += new System.EventHandler(Instance_Refreshed);
-      DownloadResources();
+    #region Overrides
+    protected override void OnLoad(EventArgs e) {
+      HiveClient.Instance.Refreshing += HiveClient_Instance_Refreshing;
+      HiveClient.Instance.Refreshed += HiveClient_Instance_Refreshed;
+      base.OnLoad(e);
     }
 
-    private void HiveResourceSelectorDialog_FormClosing(object sender, FormClosingEventArgs e) {
-      HiveAdminClient.Instance.Refreshed -= new System.EventHandler(Instance_Refreshed);
+    protected override void OnClosing(CancelEventArgs e) {
+      HiveClient.Instance.Refreshed -= HiveClient_Instance_Refreshed;
+      HiveClient.Instance.Refreshing -= HiveClient_Instance_Refreshing;
+      base.OnClosing(e);
+    }
+    #endregion
+
+    #region Event Handlers
+    private void HiveClient_Instance_Refreshing(object sender, EventArgs e) {
+      if (InvokeRequired) Invoke((Action<object, EventArgs>)HiveClient_Instance_Refreshing, sender, e);
+      else {
+        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
+        mainForm.AddOperationProgressToView(this, "Refreshing ...");
+        refreshButton.Enabled = false;
+      }
     }
 
-    void Instance_Refreshed(object sender, System.EventArgs e) {
-      hiveResourceSelector.Content = HiveAdminClient.Instance.Resources;
+    private void HiveClient_Instance_Refreshed(object sender, EventArgs e) {
+      if (InvokeRequired) Invoke((Action<object, EventArgs>)HiveClient_Instance_Refreshed, sender, e);
+      else {
+        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
+        mainForm.RemoveOperationProgressFromView(this);
+        refreshButton.Enabled = true;
+      }
     }
 
-    private void refreshButton_Click(object sender, System.EventArgs e) {
-      DownloadResources();
+    private async void HiveResourceSelectorDialog_Load(object sender, EventArgs e) {
+      lock (locker) {
+        if (updatingProjects) return;
+        updatingProjects = true;
+      }
+
+      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
+        action: () => UpdateProjects(),
+        finallyCallback: () => updatingProjects = false);
     }
 
-    private void DownloadResources() {
-      var task = System.Threading.Tasks.Task.Factory.StartNew(DownloadResourcesAsync);
-      task.ContinueWith(t => {
-        hiveResourceSelector.FinishProgressView();
-        ErrorHandling.ShowErrorDialog(this, "An error occurred while downloading the tasks.", t.Exception);
-      }, TaskContinuationOptions.OnlyOnFaulted);
+    private async void refreshButton_Click(object sender, EventArgs e) {
+      lock (locker) {
+        if (updatingProjects) return;
+        updatingProjects = true;
+      }
+
+      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
+        action: () => UpdateProjects(),
+        finallyCallback: () => updatingProjects = false);
     }
 
-    private void DownloadResourcesAsync() {
-      hiveResourceSelector.StartProgressView();
-      HiveAdminClient.Instance.Refresh();
-      hiveResourceSelector.FinishProgressView();
+    private void hiveResourceSelector_SelectedProjectChanged(object sender, EventArgs e) {
+      okButton.Enabled = hiveResourceSelector.SelectedProject != null && hiveResourceSelector.AssignedResources.Any();
     }
+
+    private void hiveResourceSelector_SelectedResourcesChanged(object sender, EventArgs e) {
+      okButton.Enabled = hiveResourceSelector.AssignedResources.Any();
+
+      if(!hiveResourceSelector.AssignedResources.Any()) {
+        errorProvider.SetError(okButton, "Note: currently no resources are assigned");
+      } else if(hiveResourceSelector.AssignedCores == 0) {
+        errorProvider.SetError(okButton, "Note: currently no resources with cores are assigned");
+      } else {
+        errorProvider.SetError(okButton, string.Empty);
+      }
+    }
+
+    private void hiveResourceSelector_ProjectsTreeViewDoubleClicked(object sender, EventArgs e) {
+      if (hiveResourceSelector.SelectedProject == null) return;
+      if (!hiveResourceSelector.AssignedResources.Any()) return;
+
+      DialogResult = DialogResult.OK;
+      Close();
+    }
+    #endregion
+
+    #region Helpers
+    private void UpdateProjects() {
+      HiveClient.Instance.RefreshProjectsAndResources();
+      hiveResourceSelector.JobId = jobId;
+      hiveResourceSelector.ProjectId = projectId;
+      hiveResourceSelector.SelectedProjectId = selectedProjectId;
+      hiveResourceSelector.SelectedResourceIds = selectedResourceIds;
+      hiveResourceSelector.Content = HiveClient.Instance.Projects;
+    }
+
+    private void ShowHiveInformationDialog() {
+      if (InvokeRequired) Invoke((Action)ShowHiveInformationDialog);
+      else {
+        using (HiveInformationDialog dialog = new HiveInformationDialog()) {
+          dialog.ShowDialog(this);
+        }
+      }
+    }
+    #endregion
   }
 }
Index: trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/RefreshableHiveJobListView.cs
===================================================================
--- trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/RefreshableHiveJobListView.cs	(revision 15682)
+++ trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/RefreshableHiveJobListView.cs	(revision 16117)
@@ -41,17 +41,27 @@
       this.itemsListView.Columns.Add(new ColumnHeader("Date") { Text = "Date" });
       this.itemsListView.Columns.Add(new ColumnHeader("Name") { Text = "Name" });
+      this.itemsListView.Columns.Add(new ColumnHeader("Project") { Text = "Project" });
 
       this.itemsListView.HeaderStyle = ColumnHeaderStyle.Clickable;
       this.itemsListView.FullRowSelect = true;
 
-      this.itemsListView.ListViewItemSorter = new ListViewItemDateComparer(0, SortOrder.Ascending);
+      this.itemsListView.ListViewItemSorter = new ListViewItemComparer(new int[] { 2, 0 }, new SortOrder[] { SortOrder.Ascending, SortOrder.Ascending });
+
+      foreach (ColumnHeader c in this.itemsListView.Columns) {
+        c.AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize);
+        int w = c.Width;
+        c.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
+        if(w > c.Width) {
+          c.AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize);
+        }
+      }
     }
 
     protected override void SortItemsListView(SortOrder sortOrder) {
       if (itemsListView.Sorting == sortOrder || sortOrder == SortOrder.None) return;
-      ((ListViewItemDateComparer)itemsListView.ListViewItemSorter).Order = sortOrder;
+      ((ListViewItemComparer)itemsListView.ListViewItemSorter).Orders[1] = sortOrder;
       itemsListView.Sorting = sortOrder;
       itemsListView.Sort();
-      AdjustListViewColumnSizes();
+      //AdjustListViewColumnSizes();
     }
 
@@ -133,5 +143,10 @@
         base.Content_ItemsAdded(sender, e);
         foreach (ColumnHeader c in this.itemsListView.Columns) {
+          c.AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize);
+          int w = c.Width;
           c.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
+          if (w > c.Width) {
+            c.AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize);
+          }
         }
         foreach (var item in e.Items) {
@@ -180,4 +195,6 @@
       listViewItem.SubItems.Insert(0, new ListViewItem.ListViewSubItem(listViewItem, item.Job.DateCreated.ToString()));
       listViewItem.SubItems.Insert(1, new ListViewItem.ListViewSubItem(listViewItem, item.Job.Name));
+      listViewItem.SubItems.Insert(2, new ListViewItem.ListViewSubItem(listViewItem, HiveClient.Instance.GetProjectAncestry(item.Job.ProjectId)));
+      
       listViewItem.Group = GetListViewGroup(item.Job.OwnerUsername);
       return listViewItem;
@@ -189,4 +206,5 @@
       listViewItem.SubItems[0].Text = item == null ? "null" : item.Job.DateCreated.ToString("dd.MM.yyyy HH:mm");
       listViewItem.SubItems[1].Text = item == null ? "null" : item.Job.Name;
+      listViewItem.SubItems[2].Text = item == null ? "null" : HiveClient.Instance.GetProjectAncestry(item.Job.ProjectId);
       listViewItem.Group = GetListViewGroup(item.Job.OwnerUsername);
       listViewItem.ToolTipText = item == null ? string.Empty : item.ItemName + ": " + item.ItemDescription;
Index: trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/RefreshableHiveJobView.Designer.cs
===================================================================
--- trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/RefreshableHiveJobView.Designer.cs	(revision 15682)
+++ trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/RefreshableHiveJobView.Designer.cs	(revision 16117)
@@ -63,11 +63,15 @@
       this.executionTimeTextBox = new System.Windows.Forms.TextBox();
       this.pauseButton = new System.Windows.Forms.Button();
-      this.resourceIdsLabel = new System.Windows.Forms.Label();
-      this.resourceNamesTextBox = new System.Windows.Forms.TextBox();
+      this.projectLabel = new System.Windows.Forms.Label();
+      this.projectNameTextBox = new System.Windows.Forms.TextBox();
       this.nameLabel = new System.Windows.Forms.Label();
       this.nameTextBox = new System.Windows.Forms.TextBox();
+      this.descriptionLabel = new System.Windows.Forms.Label();
+      this.descriptionTextBox = new System.Windows.Forms.TextBox();
       this.toolTip = new System.Windows.Forms.ToolTip(this.components);
       this.refreshButton = new System.Windows.Forms.Button();
+      this.updateButton = new System.Windows.Forms.Button();
       this.UnloadButton = new System.Windows.Forms.Button();
+      this.searchButton = new System.Windows.Forms.Button();
       this.refreshAutomaticallyCheckBox = new System.Windows.Forms.CheckBox();
       this.infoGroupBox = new System.Windows.Forms.GroupBox();
@@ -78,5 +82,4 @@
       this.calculatingLabel = new System.Windows.Forms.Label();
       this.jobsLabel = new System.Windows.Forms.Label();
-      this.searchButton = new System.Windows.Forms.Button();
       this.tabControl.SuspendLayout();
       this.tasksTabPage.SuspendLayout();
@@ -91,6 +94,6 @@
       // 
       this.tabControl.AllowDrop = true;
-      this.tabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-            | System.Windows.Forms.AnchorStyles.Left)
+      this.tabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
       this.tabControl.Controls.Add(this.tasksTabPage);
@@ -99,5 +102,5 @@
       this.tabControl.Controls.Add(this.stateTabPage);
       this.tabControl.Controls.Add(this.logTabPage);
-      this.tabControl.Location = new System.Drawing.Point(0, 78);
+      this.tabControl.Location = new System.Drawing.Point(0, 106);
       this.tabControl.Name = "tabControl";
       this.tabControl.SelectedIndex = 0;
@@ -119,6 +122,6 @@
       // 
       this.jobsTreeView.AllowDrop = true;
-      this.jobsTreeView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-            | System.Windows.Forms.AnchorStyles.Left)
+      this.jobsTreeView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
       this.jobsTreeView.Caption = "ItemTree View";
@@ -151,5 +154,5 @@
       this.refreshPermissionsButton.Size = new System.Drawing.Size(24, 24);
       this.refreshPermissionsButton.TabIndex = 23;
-      this.toolTip.SetToolTip(this.refreshPermissionsButton, "Refresh Data");
+      this.toolTip.SetToolTip(this.refreshPermissionsButton, "Refresh data");
       this.refreshPermissionsButton.UseVisualStyleBackColor = true;
       this.refreshPermissionsButton.Click += new System.EventHandler(this.refreshPermissionsButton_Click);
@@ -157,6 +160,6 @@
       // hiveExperimentPermissionListView
       // 
-      this.hiveExperimentPermissionListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-            | System.Windows.Forms.AnchorStyles.Left)
+      this.hiveExperimentPermissionListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
       this.hiveExperimentPermissionListView.Caption = "HiveExperimentPermissionList View";
@@ -183,6 +186,6 @@
       // runCollectionViewHost
       // 
-      this.runCollectionViewHost.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-            | System.Windows.Forms.AnchorStyles.Left)
+      this.runCollectionViewHost.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
       this.runCollectionViewHost.Caption = "View";
@@ -209,6 +212,6 @@
       // stateLogViewHost
       // 
-      this.stateLogViewHost.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-            | System.Windows.Forms.AnchorStyles.Left)
+      this.stateLogViewHost.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
       this.stateLogViewHost.Caption = "StateLog View";
@@ -235,6 +238,6 @@
       // logView
       // 
-      this.logView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-            | System.Windows.Forms.AnchorStyles.Left)
+      this.logView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
       this.logView.Caption = "Log View";
@@ -250,8 +253,8 @@
       this.startButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
       this.startButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.Play;
-      this.startButton.Location = new System.Drawing.Point(0, 536);
+      this.startButton.Location = new System.Drawing.Point(0, 564);
       this.startButton.Name = "startButton";
       this.startButton.Size = new System.Drawing.Size(24, 24);
-      this.startButton.TabIndex = 5;
+      this.startButton.TabIndex = 4;
       this.toolTip.SetToolTip(this.startButton, "Start/Resume Experiment");
       this.startButton.UseVisualStyleBackColor = true;
@@ -262,8 +265,8 @@
       this.stopButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
       this.stopButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.Stop;
-      this.stopButton.Location = new System.Drawing.Point(60, 536);
+      this.stopButton.Location = new System.Drawing.Point(60, 564);
       this.stopButton.Name = "stopButton";
       this.stopButton.Size = new System.Drawing.Size(24, 24);
-      this.stopButton.TabIndex = 7;
+      this.stopButton.TabIndex = 6;
       this.toolTip.SetToolTip(this.stopButton, "Stop Experiment");
       this.stopButton.UseVisualStyleBackColor = true;
@@ -274,8 +277,8 @@
       this.executionTimeLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
       this.executionTimeLabel.AutoSize = true;
-      this.executionTimeLabel.Location = new System.Drawing.Point(491, 543);
+      this.executionTimeLabel.Location = new System.Drawing.Point(491, 571);
       this.executionTimeLabel.Name = "executionTimeLabel";
       this.executionTimeLabel.Size = new System.Drawing.Size(83, 13);
-      this.executionTimeLabel.TabIndex = 9;
+      this.executionTimeLabel.TabIndex = 100;
       this.executionTimeLabel.Text = "&Execution Time:";
       // 
@@ -283,9 +286,9 @@
       // 
       this.executionTimeTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
-      this.executionTimeTextBox.Location = new System.Drawing.Point(580, 540);
+      this.executionTimeTextBox.Location = new System.Drawing.Point(580, 568);
       this.executionTimeTextBox.Name = "executionTimeTextBox";
       this.executionTimeTextBox.ReadOnly = true;
       this.executionTimeTextBox.Size = new System.Drawing.Size(137, 20);
-      this.executionTimeTextBox.TabIndex = 10;
+      this.executionTimeTextBox.TabIndex = 100;
       // 
       // pauseButton
@@ -294,49 +297,69 @@
       this.pauseButton.Enabled = false;
       this.pauseButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.Pause;
-      this.pauseButton.Location = new System.Drawing.Point(30, 536);
+      this.pauseButton.Location = new System.Drawing.Point(30, 564);
       this.pauseButton.Name = "pauseButton";
       this.pauseButton.Size = new System.Drawing.Size(24, 24);
-      this.pauseButton.TabIndex = 6;
+      this.pauseButton.TabIndex = 5;
       this.toolTip.SetToolTip(this.pauseButton, "Pause Experiment");
       this.pauseButton.UseVisualStyleBackColor = true;
       this.pauseButton.Click += new System.EventHandler(this.pauseButton_Click);
       // 
-      // resourceIdsLabel
-      // 
-      this.resourceIdsLabel.AutoSize = true;
-      this.resourceIdsLabel.Location = new System.Drawing.Point(3, 56);
-      this.resourceIdsLabel.Name = "resourceIdsLabel";
-      this.resourceIdsLabel.Size = new System.Drawing.Size(61, 13);
-      this.resourceIdsLabel.TabIndex = 12;
-      this.resourceIdsLabel.Text = "Resources:";
-      // 
-      // resourceNamesTextBox
-      // 
-      this.resourceNamesTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
-            | System.Windows.Forms.AnchorStyles.Right)));
-      this.resourceNamesTextBox.Location = new System.Drawing.Point(70, 52);
-      this.resourceNamesTextBox.Name = "resourceNamesTextBox";
-      this.resourceNamesTextBox.Size = new System.Drawing.Size(471, 20);
-      this.resourceNamesTextBox.TabIndex = 2;
-      this.resourceNamesTextBox.Validated += new System.EventHandler(this.resourceNamesTextBox_Validated);
+      // projectLabel
+      // 
+      this.projectLabel.AutoSize = true;
+      this.projectLabel.Location = new System.Drawing.Point(3, 83);
+      this.projectLabel.Name = "projectLabel";
+      this.projectLabel.Size = new System.Drawing.Size(43, 13);
+      this.projectLabel.TabIndex = 100;
+      this.projectLabel.Text = "Project:";
+      // 
+      // projectNameTextBox
+      // 
+      this.projectNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.projectNameTextBox.Location = new System.Drawing.Point(100, 80);
+      this.projectNameTextBox.Name = "projectNameTextBox";
+      this.projectNameTextBox.ReadOnly = true;
+      this.projectNameTextBox.Size = new System.Drawing.Size(471, 20);
+      this.projectNameTextBox.TabIndex = 100;
+      this.projectNameTextBox.Validated += new System.EventHandler(this.resourceNamesTextBox_Validated);
       // 
       // nameLabel
       // 
       this.nameLabel.AutoSize = true;
-      this.nameLabel.Location = new System.Drawing.Point(3, 30);
+      this.nameLabel.Location = new System.Drawing.Point(3, 35);
       this.nameLabel.Name = "nameLabel";
       this.nameLabel.Size = new System.Drawing.Size(38, 13);
-      this.nameLabel.TabIndex = 20;
+      this.nameLabel.TabIndex = 100;
       this.nameLabel.Text = "Name:";
       // 
       // nameTextBox
       // 
-      this.nameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
-            | System.Windows.Forms.AnchorStyles.Right)));
-      this.nameTextBox.Location = new System.Drawing.Point(70, 27);
+      this.nameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.nameTextBox.Location = new System.Drawing.Point(71, 32);
       this.nameTextBox.Name = "nameTextBox";
-      this.nameTextBox.Size = new System.Drawing.Size(501, 20);
+      this.nameTextBox.Size = new System.Drawing.Size(500, 20);
       this.nameTextBox.TabIndex = 1;
       this.nameTextBox.Validated += new System.EventHandler(this.nameTextBox_Validated);
+      // 
+      // descriptionLabel
+      // 
+      this.descriptionLabel.AutoSize = true;
+      this.descriptionLabel.Location = new System.Drawing.Point(3, 59);
+      this.descriptionLabel.Name = "descriptionLabel";
+      this.descriptionLabel.Size = new System.Drawing.Size(63, 13);
+      this.descriptionLabel.TabIndex = 100;
+      this.descriptionLabel.Text = "Description:";
+      // 
+      // descriptionTextBox
+      // 
+      this.descriptionTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.descriptionTextBox.Location = new System.Drawing.Point(71, 56);
+      this.descriptionTextBox.Name = "descriptionTextBox";
+      this.descriptionTextBox.Size = new System.Drawing.Size(500, 20);
+      this.descriptionTextBox.TabIndex = 2;
+      this.descriptionTextBox.Validated += new System.EventHandler(this.descriptionTextBox_Validated);
       // 
       // refreshButton
@@ -346,27 +369,49 @@
       this.refreshButton.Name = "refreshButton";
       this.refreshButton.Size = new System.Drawing.Size(24, 24);
-      this.refreshButton.TabIndex = 22;
+      this.refreshButton.TabIndex = 7;
       this.toolTip.SetToolTip(this.refreshButton, "Refresh Data");
       this.refreshButton.UseVisualStyleBackColor = true;
       this.refreshButton.Click += new System.EventHandler(this.refreshButton_Click);
       // 
+      // updateButton
+      // 
+      this.updateButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.Save;
+      this.updateButton.Location = new System.Drawing.Point(30, 0);
+      this.updateButton.Name = "updateButton";
+      this.updateButton.Size = new System.Drawing.Size(24, 24);
+      this.updateButton.TabIndex = 8;
+      this.toolTip.SetToolTip(this.updateButton, "Update Job (Name, Project, Resources)");
+      this.updateButton.UseVisualStyleBackColor = true;
+      this.updateButton.Click += new System.EventHandler(this.updateButton_Click);
+      // 
       // UnloadButton
       // 
       this.UnloadButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.Disconnect;
-      this.UnloadButton.Location = new System.Drawing.Point(30, 0);
+      this.UnloadButton.Location = new System.Drawing.Point(57, 0);
       this.UnloadButton.Name = "UnloadButton";
       this.UnloadButton.Size = new System.Drawing.Size(24, 24);
-      this.UnloadButton.TabIndex = 27;
+      this.UnloadButton.TabIndex = 9;
       this.toolTip.SetToolTip(this.UnloadButton, "Unload Job");
       this.UnloadButton.UseVisualStyleBackColor = true;
       this.UnloadButton.Click += new System.EventHandler(this.UnloadButton_Click);
       // 
+      // searchButton
+      // 
+      this.searchButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.Zoom;
+      this.searchButton.Location = new System.Drawing.Point(71, 79);
+      this.searchButton.Name = "searchButton";
+      this.searchButton.Size = new System.Drawing.Size(24, 24);
+      this.searchButton.TabIndex = 3;
+      this.toolTip.SetToolTip(this.searchButton, "Select project and resources");
+      this.searchButton.UseVisualStyleBackColor = true;
+      this.searchButton.Click += new System.EventHandler(this.searchButton_Click);
+      // 
       // refreshAutomaticallyCheckBox
       // 
       this.refreshAutomaticallyCheckBox.AutoSize = true;
-      this.refreshAutomaticallyCheckBox.Location = new System.Drawing.Point(70, 3);
+      this.refreshAutomaticallyCheckBox.Location = new System.Drawing.Point(100, 3);
       this.refreshAutomaticallyCheckBox.Name = "refreshAutomaticallyCheckBox";
       this.refreshAutomaticallyCheckBox.Size = new System.Drawing.Size(127, 17);
-      this.refreshAutomaticallyCheckBox.TabIndex = 24;
+      this.refreshAutomaticallyCheckBox.TabIndex = 100;
       this.refreshAutomaticallyCheckBox.Text = "&Refresh automatically";
       this.refreshAutomaticallyCheckBox.UseVisualStyleBackColor = true;
@@ -382,5 +427,5 @@
       this.infoGroupBox.Controls.Add(this.calculatingLabel);
       this.infoGroupBox.Controls.Add(this.jobsLabel);
-      this.infoGroupBox.Location = new System.Drawing.Point(580, 5);
+      this.infoGroupBox.Location = new System.Drawing.Point(578, 16);
       this.infoGroupBox.Name = "infoGroupBox";
       this.infoGroupBox.Size = new System.Drawing.Size(133, 89);
@@ -391,28 +436,28 @@
       // finishedTextBox
       // 
-      this.finishedTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+      this.finishedTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
       this.finishedTextBox.Location = new System.Drawing.Point(74, 64);
       this.finishedTextBox.Name = "finishedTextBox";
       this.finishedTextBox.Size = new System.Drawing.Size(53, 20);
-      this.finishedTextBox.TabIndex = 5;
+      this.finishedTextBox.TabIndex = 100;
       // 
       // calculatingTextBox
       // 
-      this.calculatingTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+      this.calculatingTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
       this.calculatingTextBox.Location = new System.Drawing.Point(74, 40);
       this.calculatingTextBox.Name = "calculatingTextBox";
       this.calculatingTextBox.Size = new System.Drawing.Size(53, 20);
-      this.calculatingTextBox.TabIndex = 4;
+      this.calculatingTextBox.TabIndex = 100;
       // 
       // jobsTextBox
       // 
-      this.jobsTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+      this.jobsTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
       this.jobsTextBox.Location = new System.Drawing.Point(74, 16);
       this.jobsTextBox.Name = "jobsTextBox";
       this.jobsTextBox.Size = new System.Drawing.Size(53, 20);
-      this.jobsTextBox.TabIndex = 3;
+      this.jobsTextBox.TabIndex = 100;
       // 
       // finishedLabel
@@ -422,5 +467,5 @@
       this.finishedLabel.Name = "finishedLabel";
       this.finishedLabel.Size = new System.Drawing.Size(49, 13);
-      this.finishedLabel.TabIndex = 2;
+      this.finishedLabel.TabIndex = 100;
       this.finishedLabel.Text = "Finished:";
       // 
@@ -431,5 +476,5 @@
       this.calculatingLabel.Name = "calculatingLabel";
       this.calculatingLabel.Size = new System.Drawing.Size(62, 13);
-      this.calculatingLabel.TabIndex = 1;
+      this.calculatingLabel.TabIndex = 100;
       this.calculatingLabel.Text = "Calculating:";
       // 
@@ -440,38 +485,30 @@
       this.jobsLabel.Name = "jobsLabel";
       this.jobsLabel.Size = new System.Drawing.Size(46, 13);
-      this.jobsLabel.TabIndex = 0;
+      this.jobsLabel.TabIndex = 100;
       this.jobsLabel.Text = "Waiting:";
       // 
-      // searchButton
-      // 
-      this.searchButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
-      this.searchButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.Zoom;
-      this.searchButton.Location = new System.Drawing.Point(547, 50);
-      this.searchButton.Name = "searchButton";
-      this.searchButton.Size = new System.Drawing.Size(24, 24);
-      this.searchButton.TabIndex = 26;
-      this.searchButton.UseVisualStyleBackColor = true;
-      this.searchButton.Click += new System.EventHandler(this.searchButton_Click);
-      // 
       // RefreshableHiveJobView
       // 
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
-      this.Controls.Add(this.UnloadButton);
       this.Controls.Add(this.searchButton);
       this.Controls.Add(this.infoGroupBox);
       this.Controls.Add(this.refreshAutomaticallyCheckBox);
       this.Controls.Add(this.refreshButton);
+      this.Controls.Add(this.updateButton);
+      this.Controls.Add(this.UnloadButton);
       this.Controls.Add(this.nameTextBox);
       this.Controls.Add(this.nameLabel);
+      this.Controls.Add(this.descriptionTextBox);
+      this.Controls.Add(this.descriptionLabel);
       this.Controls.Add(this.tabControl);
       this.Controls.Add(this.startButton);
       this.Controls.Add(this.executionTimeTextBox);
       this.Controls.Add(this.executionTimeLabel);
-      this.Controls.Add(this.resourceNamesTextBox);
+      this.Controls.Add(this.projectNameTextBox);
       this.Controls.Add(this.pauseButton);
-      this.Controls.Add(this.resourceIdsLabel);
+      this.Controls.Add(this.projectLabel);
       this.Controls.Add(this.stopButton);
       this.Name = "RefreshableHiveJobView";
-      this.Size = new System.Drawing.Size(717, 560);
+      this.Size = new System.Drawing.Size(717, 588);
       this.tabControl.ResumeLayout(false);
       this.tasksTabPage.ResumeLayout(false);
@@ -493,6 +530,6 @@
     private System.Windows.Forms.TextBox executionTimeTextBox;
     private System.Windows.Forms.Button pauseButton;
-    private System.Windows.Forms.Label resourceIdsLabel;
-    private System.Windows.Forms.TextBox resourceNamesTextBox;
+    private System.Windows.Forms.Label projectLabel;
+    private System.Windows.Forms.TextBox projectNameTextBox;
     private System.Windows.Forms.TabPage logTabPage;
     private Core.Views.LogView logView;
@@ -501,6 +538,10 @@
     private System.Windows.Forms.Label nameLabel;
     private System.Windows.Forms.TextBox nameTextBox;
+    private System.Windows.Forms.Label descriptionLabel;
+    private System.Windows.Forms.TextBox descriptionTextBox;
     private System.Windows.Forms.ToolTip toolTip;
     private System.Windows.Forms.Button refreshButton;
+    private System.Windows.Forms.Button updateButton;
+    private System.Windows.Forms.Button UnloadButton;
     private System.Windows.Forms.CheckBox refreshAutomaticallyCheckBox;
     private System.Windows.Forms.GroupBox infoGroupBox;
@@ -520,6 +561,4 @@
     private System.Windows.Forms.Button searchButton;
     private MainForm.WindowsForms.DragOverTabControl tabControl;
-    private System.Windows.Forms.Button UnloadButton;
-
   }
 }
Index: trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/RefreshableHiveJobView.cs
===================================================================
--- trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/RefreshableHiveJobView.cs	(revision 15682)
+++ trunk/HeuristicLab.Clients.Hive.JobManager/3.3/Views/RefreshableHiveJobView.cs	(revision 16117)
@@ -23,5 +23,4 @@
 using System.ComponentModel;
 using System.Linq;
-using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
@@ -34,4 +33,5 @@
 using HeuristicLab.Optimization;
 using HeuristicLab.PluginInfrastructure;
+using System.Collections.Generic;
 
 namespace HeuristicLab.Clients.Hive.JobManager.Views {
@@ -45,8 +45,12 @@
     private bool SuppressEvents { get; set; }
     private object runCollectionViewLocker = new object();
+    private Project selectedProject;
+    private Dictionary<Guid, Guid> originalJobProjectAssignment = new Dictionary<Guid, Guid>();
 
     public new RefreshableJob Content {
       get { return (RefreshableJob)base.Content; }
-      set { base.Content = value; }
+      set {
+        base.Content = value;
+      }
     }
 
@@ -117,6 +121,7 @@
         if (Content == null) {
           nameTextBox.Text = string.Empty;
+          descriptionTextBox.Text = string.Empty;
           executionTimeTextBox.Text = string.Empty;
-          resourceNamesTextBox.Text = string.Empty;
+          projectNameTextBox.Text = string.Empty;
           refreshAutomaticallyCheckBox.Checked = false;
           lock (runCollectionViewLocker) {
@@ -128,8 +133,45 @@
           stateLogViewHost.Content = null;
         } else {
+          if(Content.Job != null 
+            && Content.Job.Id != Guid.Empty 
+            && !originalJobProjectAssignment.ContainsKey(Content.Job.Id)) {
+            originalJobProjectAssignment.Add(Content.Job.Id, Content.Job.ProjectId);
+          }
+
+          if (Content.Job != null && Content.Job.ProjectId == Guid.Empty) {
+            if (HiveClient.Instance != null && HiveClient.Instance.Projects != null && HiveClient.Instance.Projects.Count == 1) {
+              var p = HiveClient.Instance.Projects.FirstOrDefault();
+              if (p != null && p.Id != Guid.Empty) {
+                hiveResourceSelectorDialog = new HiveResourceSelectorDialog(Content.Job.Id, Content.Job.ProjectId);
+                Content.Job.ProjectId = p.Id;
+                Content.Job.ResourceIds = HiveClient.Instance.GetAvailableResourcesForProject(p.Id).Select(x => x.Id).ToList();
+                hiveResourceSelectorDialog.SelectedProjectId = Content.Job.ProjectId;
+                hiveResourceSelectorDialog.SelectedResourceIds = Content.Job.ResourceIds;
+              }                
+            }
+          }
+
+
           nameTextBox.Text = Content.Job.Name;
+          descriptionTextBox.Text = Content.Job.Description;
           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) {
+            if(selectedProject == null || selectedProject.Id != Content.Job.ProjectId) {
+              selectedProject = GetProject(Content.Job.ProjectId);
+              if (selectedProject != null) {
+                projectNameTextBox.Text = selectedProject.Name;
+              } else {
+                projectNameTextBox.Text = string.Empty;
+              }
+            }
+          } else {
+            selectedProject = null;
+            projectNameTextBox.Text = string.Empty;
+            Content.Job.ResourceIds = null;
+          }
+          
           logView.Content = Content.Log;
           lock (runCollectionViewLocker) {
@@ -137,6 +179,5 @@
           }
         }
-      }
-      finally {
+      } finally {
         SuppressEvents = false;
       }
@@ -158,5 +199,6 @@
       tabControl.Enabled = !Locked;
       nameTextBox.Enabled = !Locked;
-      resourceNamesTextBox.Enabled = !Locked;
+      descriptionTextBox.Enabled = !Locked;
+      projectNameTextBox.Enabled = !Locked;
       searchButton.Enabled = !Locked;
       jobsTreeView.Enabled = !Locked;
@@ -182,11 +224,12 @@
           tabControl.Enabled = !Content.IsProgressing;
 
-          this.nameTextBox.ReadOnly = !Content.IsControllable || Content.ExecutionState != ExecutionState.Prepared || alreadyUploaded || Content.IsProgressing;
-          this.resourceNamesTextBox.ReadOnly = !Content.IsControllable || Content.ExecutionState != ExecutionState.Prepared || alreadyUploaded || Content.IsProgressing;
-          this.searchButton.Enabled = Content.IsControllable && Content.ExecutionState == ExecutionState.Prepared && !alreadyUploaded && !Content.IsProgressing;
+          this.nameTextBox.ReadOnly = Content.IsProgressing;
+          this.descriptionTextBox.ReadOnly = Content.IsProgressing;
+          this.searchButton.Enabled = !Content.IsProgressing && Content.ExecutionState != ExecutionState.Stopped;
           this.jobsTreeView.ReadOnly = !Content.IsControllable || Content.ExecutionState != ExecutionState.Prepared || alreadyUploaded || Content.IsProgressing;
 
           this.refreshAutomaticallyCheckBox.Enabled = Content.IsControllable && alreadyUploaded && jobsLoaded && (Content.ExecutionState == ExecutionState.Started || Content.ExecutionState == ExecutionState.Paused) && !Content.IsProgressing;
           this.refreshButton.Enabled = Content.IsDownloadable && alreadyUploaded && !Content.IsProgressing;
+          this.updateButton.Enabled = Content.ExecutionState != ExecutionState.Prepared && Content.ExecutionState != ExecutionState.Stopped && !Content.IsProgressing;
 
           this.UnloadButton.Enabled = Content.HiveTasks != null && Content.HiveTasks.Count > 0 && alreadyUploaded && !Content.IsProgressing;
@@ -333,15 +376,39 @@
     #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(hiveResourceSelectorDialog.JobId != Content.Job.Id) {
+        hiveResourceSelectorDialog.JobId = Content.Job.Id;
+        hiveResourceSelectorDialog.SelectedProjectId = Content.Job.ProjectId;
+        hiveResourceSelectorDialog.SelectedResourceIds = Content.Job.ResourceIds;
+
+        if (originalJobProjectAssignment.ContainsKey(Content.Job.Id)) {
+          hiveResourceSelectorDialog.ProjectId = originalJobProjectAssignment[Content.Job.Id];
+        } else {
+          hiveResourceSelectorDialog.ProjectId = Guid.Empty;
+        }
+      } else if(hiveResourceSelectorDialog.JobId == Guid.Empty && Content.Job.Id == Guid.Empty) {
+        hiveResourceSelectorDialog.JobId = Content.Job.Id;
+        hiveResourceSelectorDialog.ProjectId = Guid.Empty;
+        hiveResourceSelectorDialog.SelectedProjectId = Content.Job.ProjectId;
+        hiveResourceSelectorDialog.SelectedResourceIds = Content.Job.ResourceIds;
+      } else {
+        hiveResourceSelectorDialog.SelectedProjectId = Content.Job.ProjectId;
+        hiveResourceSelectorDialog.SelectedResourceIds = Content.Job.ResourceIds;
+      }
+
       if (hiveResourceSelectorDialog.ShowDialog(this) == DialogResult.OK) {
-        StringBuilder sb = new StringBuilder();
-        foreach (Resource resource in hiveResourceSelectorDialog.GetSelectedResources()) {
-          sb.Append(resource.Name);
-          sb.Append(";");
-        }
-        resourceNamesTextBox.Text = sb.ToString();
-        if (Content.Job.ResourceNames != resourceNamesTextBox.Text)
-          Content.Job.ResourceNames = resourceNamesTextBox.Text;
+        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 {
+          selectedProject = null;
+          projectNameTextBox.Text = string.Empty;
+          Content.Job.ProjectId = Guid.Empty;
+          Content.Job.ResourceIds = null;
+        }
+        SetEnabledStateOfExecutableButtons();
       }
     }
@@ -350,4 +417,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);
@@ -359,4 +430,5 @@
       } else {
         HiveClient.StartJob((Exception ex) => ErrorHandling.ShowErrorDialog(this, "Start failed.", ex), Content, new CancellationToken());
+        UpdateSelectorDialog();
       }
     }
@@ -403,7 +475,12 @@
     }
 
+    private void descriptionTextBox_Validated(object sender, EventArgs e) {
+      if (!SuppressEvents && Content.Job != null && Content.Job.Description != descriptionTextBox.Text)
+        Content.Job.Description = descriptionTextBox.Text;
+    }
+
     private void resourceNamesTextBox_Validated(object sender, EventArgs e) {
-      if (!SuppressEvents && Content.Job != null && Content.Job.ResourceNames != resourceNamesTextBox.Text)
-        Content.Job.ResourceNames = resourceNamesTextBox.Text;
+      //if (!SuppressEvents && Content.Job != null && Content.Job.ResourceNames != resourceNamesTextBox.Text)
+      //  Content.Job.ResourceNames = resourceNamesTextBox.Text;
     }
 
@@ -417,102 +494,39 @@
         try {
           invoker.EndInvoke(ar);
-        }
-        catch (Exception ex) {
-          ThreadPool.QueueUserWorkItem(delegate(object exception) { ErrorHandling.ShowErrorDialog(this, (Exception)exception); }, ex);
+        } catch (Exception ex) {
+          ThreadPool.QueueUserWorkItem(delegate (object exception) { ErrorHandling.ShowErrorDialog(this, (Exception)exception); }, ex);
         }
       }, null);
-    }
-
-    private void refreshPermissionsButton_Click(object sender, EventArgs e) {
-      if (this.Content.Job.Id == Guid.Empty) {
-        MessageBox.Show("You have to upload the Job first before you can share it.", "HeuristicLab Hive Job Manager", MessageBoxButtons.OK, MessageBoxIcon.Information);
-      } else {
-        hiveExperimentPermissionListView.Content = HiveClient.GetJobPermissions(this.Content.Job.Id);
-      }
-    }
-    #endregion
-
-    #region Helpers
-    private void SetEnabledStateOfExecutableButtons() {
-      if (Content == null) {
-        startButton.Enabled = pauseButton.Enabled = stopButton.Enabled = false;
-      } else {
-        startButton.Enabled = Content.IsControllable && Content.HiveTasks != null && Content.HiveTasks.Count > 0 && (Content.ExecutionState == ExecutionState.Prepared || Content.ExecutionState == ExecutionState.Paused) && !Content.IsProgressing;
-        pauseButton.Enabled = Content.IsControllable && Content.ExecutionState == ExecutionState.Started && !Content.IsProgressing;
-        stopButton.Enabled = Content.IsControllable && (Content.ExecutionState == ExecutionState.Started || Content.ExecutionState == ExecutionState.Paused) && !Content.IsProgressing;
-      }
-    }
-    #endregion
-
-    #region Drag & Drop
-    private void jobsTreeView_DragOver(object sender, DragEventArgs e) {
-      jobsTreeView_DragEnter(sender, e);
-    }
-
-    private void jobsTreeView_DragEnter(object sender, DragEventArgs e) {
-      e.Effect = DragDropEffects.None;
-      var obj = (IDeepCloneable)e.Data.GetData(Constants.DragDropDataFormat);
-
-      Type objType = obj.GetType();
-      if (ItemTask.IsTypeSupported(objType)) {
-        if (Content.Id != Guid.Empty) e.Effect = DragDropEffects.None;
-        else if ((e.KeyState & 32) == 32) e.Effect = DragDropEffects.Link;  // ALT key
-        else if (e.AllowedEffect.HasFlag(DragDropEffects.Copy)) e.Effect = DragDropEffects.Copy;
-      }
-    }
-
-    private void jobsTreeView_DragDrop(object sender, DragEventArgs e) {
-      if (e.Effect != DragDropEffects.None) {
-        var obj = (IItem)e.Data.GetData(Constants.DragDropDataFormat);
-
-        IItem newObj = null;
-        if (e.Effect.HasFlag(DragDropEffects.Copy)) {
-          newObj = (IItem)obj.Clone();
-        } else {
-          newObj = obj;
-        }
-
-        //IOptimizer and IExecutables need some special care
-        if (newObj is IOptimizer) {
-          ((IOptimizer)newObj).Runs.Clear();
-        }
-        if (newObj is IExecutable) {
-          IExecutable exec = (IExecutable)newObj;
-          if (exec.ExecutionState != ExecutionState.Prepared) {
-            exec.Prepare();
-          }
-        }
-
-        ItemTask hiveTask = ItemTask.GetItemTaskForItem(newObj);
-        Content.HiveTasks.Add(hiveTask.CreateHiveTask());
-      }
-    }
-    #endregion
-
-    private void tabControl_SelectedIndexChanged(object sender, EventArgs e) {
-      if (tabControl.SelectedTab == permissionTabPage) {
-        if (!Content.IsSharable) {
-          MessageBox.Show("Unable to load permissions. You have insufficient access privileges.", "HeuristicLab Hive Job Manager", MessageBoxButtons.OK, MessageBoxIcon.Information);
-          tabControl.SelectedTab = tasksTabPage;
-        }
-      }
-    }
-
-    private RunCollection GetAllRunsFromJob(RefreshableJob job) {
-      if (job != null) {
-        RunCollection runs = new RunCollection() { OptimizerName = job.ItemName };
-
-        foreach (HiveTask subTask in job.HiveTasks) {
-          if (subTask is OptimizerHiveTask) {
-            OptimizerHiveTask ohTask = subTask as OptimizerHiveTask;
-            ohTask.ExecuteReadActionOnItemTask(new Action(delegate() {
-              runs.AddRange(ohTask.ItemTask.Item.Runs);
-            }));
-          }
-        }
-        return runs;
-      } else {
-        return null;
-      }
+      UpdateSelectorDialog();
+    }
+
+    private void updateButton_Click2(object sender, EventArgs e) {
+      if (Content.ExecutionState == ExecutionState.Stopped) {
+        MessageBox.Show("Job cannot be updated once it stopped.", "HeuristicLab Hive Job Manager", MessageBoxButtons.OK, MessageBoxIcon.Information);
+        return;
+      }
+
+      HiveClient.UpdateJob(
+        (Exception ex) => ErrorHandling.ShowErrorDialog(this, "Update failed.", ex), 
+        Content, 
+        new CancellationToken());
+      UpdateSelectorDialog();
+    }
+
+    private void updateButton_Click(object sender, EventArgs e) {
+      if (Content.ExecutionState == ExecutionState.Stopped) {
+        MessageBox.Show("Job cannot be updated once it stopped.", "HeuristicLab Hive Job Manager", MessageBoxButtons.OK, MessageBoxIcon.Information);
+        return;
+      }
+
+      var invoker = new Action<RefreshableJob>(HiveClient.UpdateJob);
+      invoker.BeginInvoke(Content, (ar) => {
+        try {
+          invoker.EndInvoke(ar);
+        } catch (Exception ex) {
+          ThreadPool.QueueUserWorkItem(delegate (object exception) { ErrorHandling.ShowErrorDialog(this, (Exception)exception); }, ex);
+        }
+      }, null);
+      UpdateSelectorDialog();
     }
 
@@ -526,4 +540,113 @@
       SetEnabledStateOfControls();
     }
+
+    private void refreshPermissionsButton_Click(object sender, EventArgs e) {
+      if (this.Content.Job.Id == Guid.Empty) {
+        MessageBox.Show("You have to upload the Job first before you can share it.", "HeuristicLab Hive Job Manager", MessageBoxButtons.OK, MessageBoxIcon.Information);
+      } else {
+        hiveExperimentPermissionListView.Content = HiveClient.GetJobPermissions(this.Content.Job.Id);
+      }
+    }
+    #endregion
+
+    #region Helpers
+    private void SetEnabledStateOfExecutableButtons() {
+      if (Content == null) {
+        startButton.Enabled = pauseButton.Enabled = stopButton.Enabled = false;
+      } else {
+        startButton.Enabled = Content.IsControllable && Content.HiveTasks != null && Content.HiveTasks.Count > 0 
+          && Content.Job.ProjectId != null && Content.Job.ProjectId != Guid.Empty && Content.Job.ResourceIds != null  && Content.Job.ResourceIds.Any() 
+          && (Content.ExecutionState == ExecutionState.Prepared || Content.ExecutionState == ExecutionState.Paused) && !Content.IsProgressing;
+        pauseButton.Enabled = Content.IsControllable && Content.ExecutionState == ExecutionState.Started && !Content.IsProgressing;
+        stopButton.Enabled = Content.IsControllable && (Content.ExecutionState == ExecutionState.Started || Content.ExecutionState == ExecutionState.Paused) && !Content.IsProgressing;
+      }
+    }
+   
+    private Project GetProject(Guid projectId) {
+      return HiveServiceLocator.Instance.CallHiveService(s => s.GetProject(projectId));
+    }
+
+    private void UpdateSelectorDialog() {
+      if(hiveResourceSelectorDialog != null) {
+        hiveResourceSelectorDialog = null;
+        //hiveResourceSelectorDialog.JobId = Content.Job.Id;
+        //hiveResourceSelectorDialog.SelectedProjectId = Content.Job.ProjectId;
+        //hiveResourceSelectorDialog.SelectedResourceIds = Content.Job.ResourceIds;
+      }
+    }
+    #endregion
+
+    #region Drag & Drop
+    private void jobsTreeView_DragOver(object sender, DragEventArgs e) {
+      jobsTreeView_DragEnter(sender, e);
+    }
+
+    private void jobsTreeView_DragEnter(object sender, DragEventArgs e) {
+      e.Effect = DragDropEffects.None;
+      var obj = (IDeepCloneable)e.Data.GetData(Constants.DragDropDataFormat);
+
+      Type objType = obj.GetType();
+      if (ItemTask.IsTypeSupported(objType)) {
+        if (Content.Id != Guid.Empty) e.Effect = DragDropEffects.None;
+        else if ((e.KeyState & 32) == 32) e.Effect = DragDropEffects.Link;  // ALT key
+        else if (e.AllowedEffect.HasFlag(DragDropEffects.Copy)) e.Effect = DragDropEffects.Copy;
+      }
+    }
+
+    private void jobsTreeView_DragDrop(object sender, DragEventArgs e) {
+      if (e.Effect != DragDropEffects.None) {
+        var obj = (IItem)e.Data.GetData(Constants.DragDropDataFormat);
+
+        IItem newObj = null;
+        if (e.Effect.HasFlag(DragDropEffects.Copy)) {
+          newObj = (IItem)obj.Clone();
+        } else {
+          newObj = obj;
+        }
+
+        //IOptimizer and IExecutables need some special care
+        if (newObj is IOptimizer) {
+          ((IOptimizer)newObj).Runs.Clear();
+        }
+        if (newObj is IExecutable) {
+          IExecutable exec = (IExecutable)newObj;
+          if (exec.ExecutionState != ExecutionState.Prepared) {
+            exec.Prepare();
+          }
+        }
+
+        ItemTask hiveTask = ItemTask.GetItemTaskForItem(newObj);
+        Content.HiveTasks.Add(hiveTask.CreateHiveTask());
+      }
+    }
+    #endregion
+
+    private void tabControl_SelectedIndexChanged(object sender, EventArgs e) {
+      if (tabControl.SelectedTab == permissionTabPage) {
+        if (!Content.IsSharable) {
+          MessageBox.Show("Unable to load permissions. You have insufficient access privileges.", "HeuristicLab Hive Job Manager", MessageBoxButtons.OK, MessageBoxIcon.Information);
+          tabControl.SelectedTab = tasksTabPage;
+        }
+      }
+    }
+
+    private RunCollection GetAllRunsFromJob(RefreshableJob job) {
+      if (job != null) {
+        RunCollection runs = new RunCollection() { OptimizerName = job.ItemName };
+
+        foreach (HiveTask subTask in job.HiveTasks) {
+          if (subTask is OptimizerHiveTask) {
+            OptimizerHiveTask ohTask = subTask as OptimizerHiveTask;
+            ohTask.ExecuteReadActionOnItemTask(new Action(delegate () {
+              runs.AddRange(ohTask.ItemTask.Item.Runs);
+            }));
+          }
+        }
+        return runs;
+      } else {
+        return null;
+      }
+    }
+
   }
 }
