Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
03/28/19 16:54:20 (5 years ago)
Author:
abeham
Message:

#2521: merged changes from r15684 to trunk HEAD (r16716) and resolved all merge conflicts

  • it doesn't build
Location:
branches/2521_ProblemRefactoring
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/2521_ProblemRefactoring

  • branches/2521_ProblemRefactoring/HeuristicLab.Clients.Hive.Administrator

    • Property svn:mergeinfo set to (toggle deleted branches)
      /branches/2520_PersistenceReintegration/HeuristicLab.Clients.Hive.Administratormergedeligible
      /branches/2839_HiveProjectManagement/HeuristicLab.Clients.Hive.Administratormergedeligible
      /branches/2947_ConfigurableIndexedDataTable/HeuristicLab.Clients.Hive.Administratormergedeligible
      /branches/2965_CancelablePersistence/HeuristicLab.Clients.Hive.Administratormergedeligible
      /branches/2972_PDPRowSelect/HeuristicLab.Clients.Hive.Administratormergedeligible
      /stable/HeuristicLab.Clients.Hive.Administratormergedeligible
      /trunk/HeuristicLab.Clients.Hive.Administratormergedeligible
      /branches/1721-RandomForestPersistence/HeuristicLab.Clients.Hive.Administrator10321-10322
      /branches/2892_LR-prediction-intervals/HeuristicLab.Clients.Hive.Administrator15743-16388
      /branches/2915-AbsoluteSymbol/HeuristicLab.Clients.Hive.Administrator15943-16355
      /branches/Algorithms.GradientDescent/HeuristicLab.Clients.Hive.Administrator5516-5520
      /branches/Benchmarking/sources/HeuristicLab.Clients.Hive.Administrator6917-7005
      /branches/CloningRefactoring/HeuristicLab.Clients.Hive.Administrator4656-4721
      /branches/CodeEditor/HeuristicLab.Clients.Hive.Administrator11700-11806
      /branches/DataAnalysis Refactoring/HeuristicLab.Clients.Hive.Administrator5471-5808
      /branches/DataAnalysis SolutionEnsembles/HeuristicLab.Clients.Hive.Administrator5815-6180
      /branches/DataAnalysis/HeuristicLab.Clients.Hive.Administrator4458-4459,​4462,​4464
      /branches/DataPreprocessing/HeuristicLab.Clients.Hive.Administrator10085-11101
      /branches/GP.Grammar.Editor/HeuristicLab.Clients.Hive.Administrator6284-6795
      /branches/GP.Symbols (TimeLag, Diff, Integral)/HeuristicLab.Clients.Hive.Administrator5060
      /branches/HLScript/HeuristicLab.Clients.Hive.Administrator10331-10358
      /branches/HeuristicLab.DatasetRefactor/sources/HeuristicLab.Clients.Hive.Administrator11570-12508
      /branches/HeuristicLab.Problems.DataAnalysis.Trading/HeuristicLab.Clients.Hive.Administrator6123-9799
      /branches/HeuristicLab.Problems.Orienteering/HeuristicLab.Clients.Hive.Administrator11130-12721
      /branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator15377-15760
      /branches/HiveStatistics/sources/HeuristicLab.Clients.Hive.Administrator12440-12877
      /branches/LogResidualEvaluator/HeuristicLab.Clients.Hive.Administrator10202-10483
      /branches/NET40/sources/HeuristicLab.Clients.Hive.Administrator5138-5162
      /branches/NSGA-II Changes/HeuristicLab.Clients.Hive.Administrator12033-12122
      /branches/ParallelEngine/HeuristicLab.Clients.Hive.Administrator5175-5192
      /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Clients.Hive.Administrator7568-7810
      /branches/QAPAlgorithms/HeuristicLab.Clients.Hive.Administrator6350-6627
      /branches/Restructure trunk solution/HeuristicLab.Clients.Hive.Administrator6828
      /branches/RuntimeOptimizer/HeuristicLab.Clients.Hive.Administrator8943-9078
      /branches/ScatterSearch (trunk integration)/HeuristicLab.Clients.Hive.Administrator7787-8333
      /branches/SlaveShutdown/HeuristicLab.Clients.Hive.Administrator8944-8956
      /branches/SpectralKernelForGaussianProcesses/HeuristicLab.Clients.Hive.Administrator10204-10479
      /branches/SuccessProgressAnalysis/HeuristicLab.Clients.Hive.Administrator5370-5682
      /branches/Trunk/HeuristicLab.Clients.Hive.Administrator6829-6865
      /branches/UnloadJobs/HeuristicLab.Clients.Hive.Administrator9168-9215
      /branches/VNS/HeuristicLab.Clients.Hive.Administrator5594-5752
      /branches/crossvalidation-2434/HeuristicLab.Clients.Hive.Administrator12948-12950
      /branches/histogram/HeuristicLab.Clients.Hive.Administrator5959-6341
  • branches/2521_ProblemRefactoring/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.cs

    r16692 r16723  
    11#region License Information
    22/* HeuristicLab
    3  * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3 * Copyright (C) 2002-2019 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44 *
    55 * This file is part of HeuristicLab.
     
    2222using System;
    2323using System.Collections.Generic;
     24using System.ComponentModel;
    2425using System.Drawing;
    2526using System.Linq;
    26 using System.ServiceModel.Security;
    27 using System.Threading;
    28 using System.Threading.Tasks;
    2927using System.Windows.Forms;
    3028using HeuristicLab.Clients.Access;
    3129using HeuristicLab.Clients.Hive.Views;
     30using HeuristicLab.Collections;
     31using HeuristicLab.Common.Resources;
    3232using HeuristicLab.Core;
    3333using HeuristicLab.Core.Views;
    3434using HeuristicLab.MainForm;
    35 using TS = System.Threading.Tasks;
    3635
    3736namespace HeuristicLab.Clients.Hive.Administrator.Views {
     
    3938  [Content(typeof(IItemList<Resource>), false)]
    4039  public partial class ResourcesView : ItemView, IDisposable {
     40    private const int slaveImageIndex = 0;
     41    private const int slaveGroupImageIndex = 1;
     42    public const string UNGROUPED_GROUP_NAME = "UNGROUPED";
     43    public const string UNGROUPED_GROUP_DESCRIPTION = "Contains slaves that are not assigned to any group.";
     44    private const string SELECTED_TAG = ""; // " [selected]";
     45    private const string NOT_STORED_TAG = "*"; // " [not stored]";
     46    private const string CHANGES_NOT_STORED_TAG = "*"; // " [changes not stored]";
     47
     48    private readonly Color changedColor = Color.FromArgb(255, 87, 191, 193); // #57bfc1
     49    private readonly Color selectedBackColor = Color.DodgerBlue;
     50    private readonly Color selectedForeColor = Color.White;
     51    private readonly Color calculatingColor = Color.FromArgb(255, 58, 114, 35); // #3a7223
     52    private readonly Color offlineColor = Color.FromArgb(255, 187, 36, 36); // #bb2424
     53    private readonly Color grayTextColor = SystemColors.GrayText;
     54
     55
     56    private TreeNode ungroupedGroupNode;
     57
     58    private Resource selectedResource = null;
     59    public Resource SelectedResource {
     60      get { return selectedResource; }
     61      set { if (selectedResource != value) ChangeSelectedResource(value); }
     62    }
     63
     64    private readonly object locker = new object();
     65    private bool refreshingInternal = false;
     66    private bool refreshingExternal = false;
     67
    4168    public new IItemList<Resource> Content {
    4269      get { return (IItemList<Resource>)base.Content; }
     
    4471    }
    4572
    46     public const string UngroupedGroupName = "UNGROUPED";
    47     private const int slaveImageIndex = 0;
    48     private const int slaveGroupImageIndex = 1;
    49     private readonly Color ownedResourceColor = Color.LightGreen;
    50     private TS.Task progressTask;
    51     private bool stopProgressTask;
    52     private bool currentlyAuthorized;
    53 
    54 
    5573    public ResourcesView() {
    5674      InitializeComponent();
    57       treeSlaveGroup.ImageList.Images.Add(HeuristicLab.Common.Resources.VSImageLibrary.MonitorLarge);
    58       treeSlaveGroup.ImageList.Images.Add(HeuristicLab.Common.Resources.VSImageLibrary.NetworkCenterLarge);
    59 
    60       HiveAdminClient.Instance.Refreshing += new EventHandler(Instance_Refreshing);
    61       HiveAdminClient.Instance.Refreshed += new EventHandler(Instance_Refreshed);
    62 
    63       Access.AccessClient.Instance.Refreshing += new EventHandler(AccessClient_Refreshing);
    64       Access.AccessClient.Instance.Refreshed += new EventHandler(AccessClient_Refreshed);
    65     }
    66 
    67     private void UpdateProgress() {
    68       while (!stopProgressTask) {
    69         int diff = (progressBar.Maximum - progressBar.Minimum) / 10;
    70 
    71         if (progressBar.InvokeRequired) {
    72           progressBar.Invoke(new Action(delegate() { progressBar.Value = (progressBar.Value + diff) % progressBar.Maximum; }));
    73         } else {
    74           progressBar.Value = (progressBar.Value + diff) % progressBar.Maximum;
    75         }
    76 
    77         //ok, this is not very clever...
    78         Thread.Sleep(500);
    79       }
    80       if (progressBar.InvokeRequired) {
    81         progressBar.Invoke(new Action(delegate() { progressBar.Value = progressBar.Minimum; }));
    82       } else {
    83         progressBar.Value = progressBar.Minimum;
    84       }
    85     }
    86 
    87     void Instance_Refreshing(object sender, EventArgs e) {
    88       stopProgressTask = false;
    89       progressTask = new TS.Task(UpdateProgress);
    90       progressTask.Start();
    91       SetEnabledStateOfControls();
    92     }
    93 
    94     void Instance_Refreshed(object sender, EventArgs e) {
    95       stopProgressTask = true;
    96       SetEnabledStateOfControls();
    97     }
    98 
    99     void AccessClient_Refreshing(object sender, EventArgs e) {
    100       stopProgressTask = false;
    101       progressTask = new TS.Task(UpdateProgress);
    102       progressTask.Start();
    103       SetEnabledStateOfControls();
    104       btnPermissionsSave.Enabled = false;
    105     }
    106 
    107     void AccessClient_Refreshed(object sender, EventArgs e) {
    108       stopProgressTask = true;
    109       SetEnabledStateOfControls();
    110     }
    111 
    112     #region Register Content Events
    113     protected override void DeregisterContentEvents() {
    114       Content.ItemsAdded -= new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<Resource>>(Content_ItemsAdded);
    115       Content.ItemsRemoved -= new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<Resource>>(Content_ItemsRemoved);
    116       base.DeregisterContentEvents();
    117     }
     75
     76      treeView.ImageList.Images.Add(VSImageLibrary.MonitorLarge);
     77      treeView.ImageList.Images.Add(VSImageLibrary.NetworkCenterLarge);
     78
     79      HiveAdminClient.Instance.Refreshing += HiveAdminClient_Instance_Refreshing;
     80      HiveAdminClient.Instance.Refreshed += HiveAdminClient_Instance_Refreshed;
     81    }
     82
     83    #region Overrides
    11884    protected override void RegisterContentEvents() {
    11985      base.RegisterContentEvents();
    120       Content.ItemsAdded += new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<Resource>>(Content_ItemsAdded);
    121       Content.ItemsRemoved += new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<Resource>>(Content_ItemsRemoved);
    122     }
    123     #endregion
     86      Content.ItemsAdded += Content_ItemsAdded;
     87      Content.ItemsRemoved += Content_ItemsRemoved;
     88    }
     89
     90    protected override void DeregisterContentEvents() {
     91      Content.ItemsRemoved -= Content_ItemsRemoved;
     92      Content.ItemsAdded -= Content_ItemsAdded;
     93      base.DeregisterContentEvents();
     94    }
    12495
    12596    protected override void OnContentChanged() {
    12697      base.OnContentChanged();
    12798      if (Content == null) {
    128         slaveView.Content = null;
     99        treeView.Nodes.Clear();
     100        viewHost.Content = null;
    129101        scheduleView.Content = null;
    130         permissionView.Content = null;
    131         permissionView.FetchSelectedUsers = null;
    132         treeSlaveGroup.Nodes.Clear();
    133102      } else {
    134         permissionView.Content = Access.AccessClient.Instance;
    135         treeSlaveGroup.Nodes.Clear();
    136 
    137         //rebuild
    138         TreeNode ungrp = new TreeNode(UngroupedGroupName);
    139         ungrp.ImageIndex = slaveGroupImageIndex;
    140         ungrp.SelectedImageIndex = ungrp.ImageIndex;
    141         var newGroup = new SlaveGroup();
    142         newGroup.Name = UngroupedGroupName;
    143         newGroup.Id = Guid.NewGuid();
    144         newGroup.Description = "Contains slaves which are in no group";
    145         ungrp.Tag = newGroup;
    146 
    147         foreach (Resource g in Content) {
    148           if (g.GetType() == typeof(SlaveGroup)) {
    149             //root node
    150             if (g.ParentResourceId == null) {
    151               TreeNode tn = new TreeNode();
    152               tn.ImageIndex = slaveGroupImageIndex;
    153               tn.SelectedImageIndex = tn.ImageIndex;
    154 
    155               tn.Tag = g;
    156               tn.Text = g.Name;
    157               if (g.OwnerUserId == Access.UserInformation.Instance.User.Id) tn.BackColor = ownedResourceColor;
    158 
    159               BuildSlaveGroupTree(g, tn);
    160               treeSlaveGroup.Nodes.Add(tn);
    161             }
    162           } else if (g.GetType() == typeof(Slave)) {
    163             if (g.ParentResourceId == null) {
    164               var stn = new TreeNode(g.Name);
    165               stn.ImageIndex = slaveImageIndex;
    166               stn.SelectedImageIndex = stn.ImageIndex;
    167               stn.Tag = g;
    168               if (g.OwnerUserId == Access.UserInformation.Instance.User.Id) stn.BackColor = ownedResourceColor;
    169               ungrp.Nodes.Add(stn);
    170             }
    171           }
    172         }
    173         treeSlaveGroup.Nodes.Add(ungrp);
    174       }
    175     }
    176 
    177     private void BuildSlaveGroupTree(Resource g, TreeNode tn) {
    178       foreach (Resource r in Content.Where(s => s.ParentResourceId != null && s.ParentResourceId == g.Id)) {
    179         TreeNode stn = new TreeNode(r.Name);
    180         if (r is Slave) {
    181           stn.ImageIndex = slaveImageIndex;
    182         } else if (r is SlaveGroup) {
    183           stn.ImageIndex = slaveGroupImageIndex;
    184         }
    185         stn.SelectedImageIndex = stn.ImageIndex;
    186         stn.Tag = r;
    187         if (r.OwnerUserId == Access.UserInformation.Instance.User.Id) stn.BackColor = ownedResourceColor;
    188         tn.Nodes.Add(stn);
    189 
    190         BuildSlaveGroupTree(r, stn);
    191       }
     103        BuildResourceTree(Content);
     104      }
     105      SetEnabledStateOfControls();
    192106    }
    193107
    194108    protected override void SetEnabledStateOfControls() {
    195109      base.SetEnabledStateOfControls();
    196       if (Content == null) {
    197         btnAddGroup.Enabled = false;
     110
     111      bool locked = Content == null || Locked || ReadOnly;
     112      bool addLocked = locked
     113                    || !IsAdmin()
     114                    || (selectedResource is Slave && selectedResource.ParentResourceId != null)
     115                    || (selectedResource != null && selectedResource.Id == Guid.Empty);
     116
     117      HashSet<Guid> descendantResources = null;
     118      bool selectedRDeleteLocked = selectedResource == null
     119                              || (selectedResource.Id != Guid.Empty && (!HiveAdminClient.Instance.ResourceDescendants.TryGetValue(selectedResource.Id, out descendantResources) || descendantResources.Any()));
     120
     121      var nodes = GetCheckedNodes(treeView.Nodes).ToList();
     122      var checkedResources = nodes.Select(x => x.Tag).OfType<Resource>().ToList();
     123      bool checkedRDeleteLocked = false;
     124      for (int i = 0; !checkedRDeleteLocked && i < checkedResources.Count; i++) {
     125        if (checkedResources[i].Id != Guid.Empty &&
     126            (!HiveAdminClient.Instance.ResourceDescendants.TryGetValue(checkedResources[i].Id, out descendantResources) ||
     127             descendantResources.Any()))
     128          checkedRDeleteLocked = true;
     129      }
     130
     131      bool deleteLocked = locked
     132                          || !IsAdmin()
     133                          || !Content.Any()
     134                          || checkedResources.Any() && checkedRDeleteLocked
     135                          || !checkedResources.Any() && selectedRDeleteLocked;
     136
     137      bool saveLocked = locked
     138                       || !IsAdmin()
     139                       || !Content.Any()
     140                       || selectedResource == null;
     141
     142      btnAddGroup.Enabled = !addLocked;
     143      btnRemoveGroup.Enabled = !deleteLocked;
     144      btnSave.Enabled = !saveLocked;
     145      viewHost.Locked = locked || !IsAdmin();
     146      scheduleView.Locked = locked || !IsAdmin();
     147    }
     148    #endregion
     149
     150    #region Event Handlers
     151    private void Content_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<Resource>> e) {
     152      if (InvokeRequired) Invoke((Action<object, CollectionItemsChangedEventArgs<IndexedItem<Resource>>>)Content_ItemsAdded, sender, e);
     153      else {
     154        OnContentChanged();
     155      }
     156    }
     157
     158    private void Content_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<Resource>> e) {
     159      if (InvokeRequired) Invoke((Action<object, CollectionItemsChangedEventArgs<IndexedItem<Resource>>>)Content_ItemsRemoved, sender, e);
     160      else {
     161        OnContentChanged();
     162      }
     163    }
     164
     165    private void SlaveViewContent_PropertyChanged(object sender, PropertyChangedEventArgs e) {
     166      if (InvokeRequired) Invoke((Action<object, PropertyChangedEventArgs>)SlaveViewContent_PropertyChanged, sender, e);
     167      else {
     168        OnContentChanged();
     169        if (e.PropertyName == "HbInterval") {
     170          UpdateChildHbIntervall((Resource)viewHost.Content);
     171        }
     172      }
     173    }
     174
     175    private void HiveAdminClient_Instance_Refreshing(object sender, EventArgs e) {
     176      if (InvokeRequired) Invoke((Action<object, EventArgs>)HiveAdminClient_Instance_Refreshing, sender, e);
     177      else {
     178        lock (locker) {
     179          if (refreshingExternal) return;
     180          if (!refreshingInternal) refreshingExternal = true;
     181        }
     182
     183        Progress.Show(this, "Refreshing ...", ProgressMode.Indeterminate);
     184        SetEnabledStateOfControls();
     185      }
     186    }
     187
     188    private void HiveAdminClient_Instance_Refreshed(object sender, EventArgs e) {
     189      if (InvokeRequired) Invoke((Action<object, EventArgs>)HiveAdminClient_Instance_Refreshed, sender, e);
     190      else {
     191        if (refreshingExternal) refreshingExternal = false;
     192        Content = HiveAdminClient.Instance.Resources;
     193
     194        Progress.Hide(this);
     195        SetEnabledStateOfControls();
     196      }
     197    }
     198
     199    private async void ResourcesView_Load(object sender, EventArgs e) {
     200      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(() => UpdateResources());
     201    }
     202
     203    private void ResourcesView_Disposed(object sender, EventArgs e) {
     204      HiveAdminClient.Instance.Refreshed -= HiveAdminClient_Instance_Refreshed;
     205      HiveAdminClient.Instance.Refreshing -= HiveAdminClient_Instance_Refreshing;
     206    }
     207
     208    private async void btnRefresh_Click(object sender, EventArgs e) {
     209      lock (locker) {
     210        if (!btnRefresh.Enabled) return;
     211        btnRefresh.Enabled = false;
     212      }
     213
     214      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
     215        action: () => UpdateResources(),
     216        finallyCallback: () => btnRefresh.Enabled = true);
     217    }
     218
     219    private void btnAddGroup_Click(object sender, EventArgs e) {
     220      var parentResourceId = selectedResource is SlaveGroup ? selectedResource.Id : (Guid?)null;
     221
     222      var group = new SlaveGroup {
     223        Name = "New Group",
     224        OwnerUserId = UserInformation.Instance.User.Id,
     225        ParentResourceId = parentResourceId
     226      };
     227
     228      SelectedResource = group;
     229      Content.Add(group);
     230    }
     231
     232    private async void btnRemoveGroup_Click(object sender, EventArgs e) {
     233      var nodes = GetCheckedNodes(treeView.Nodes).ToList();
     234      var checkedResources = nodes.Select(x => x.Tag).OfType<Resource>().ToList();
     235      if (selectedResource == null && !checkedResources.Any()) return;
     236
     237      lock (locker) {
     238        if (!btnRemoveGroup.Enabled) return;
    198239        btnRemoveGroup.Enabled = false;
     240      }
     241
     242      if (checkedResources.Count > 0) {
     243        var result = MessageBox.Show(
     244          "Do you really want to delete all " + checkedResources.Count + " checked resources?",
     245          "HeuristicLab Hive Administrator",
     246          MessageBoxButtons.YesNo,
     247          MessageBoxIcon.Question);
     248        if (result == DialogResult.Yes) {
     249          await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
     250            action: () => {
     251              RemoveResource(checkedResources);
     252            });
     253        }
     254      } else {
     255        var res = checkedResources.Any() ? checkedResources.First() : selectedResource;
     256        var result = MessageBox.Show(
     257          "Do you really want to delete the selected resource " + res.Name + "?",
     258          "HeuristicLab Hive Administrator",
     259          MessageBoxButtons.YesNo,
     260          MessageBoxIcon.Question);
     261        if (result == DialogResult.Yes) {
     262          await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
     263            action: () => {
     264              RemoveResource(res);
     265            });
     266        }
     267      }
     268
     269      OnContentChanged();
     270      SetEnabledStateOfControls();
     271    }
     272
     273    private async void btnSave_Click(object sender, EventArgs e) {
     274      lock (locker) {
     275        if (!btnSave.Enabled) return;
    199276        btnSave.Enabled = false;
    200         btnPermissionsSave.Enabled = false;
    201         permissionView.Enabled = false;
    202         scheduleView.SetEnabledStateOfSchedule(false);
    203         btnPermissionsSave.Enabled = false;
    204         permissionView.Enabled = false;
     277      }
     278
     279      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
     280        action: () => {
     281          var resourcesToSave = Content.Where(x => x.Id == Guid.Empty || x.Modified);
     282          foreach (var resource in resourcesToSave)
     283            resource.Store();
     284          UpdateResources();
     285        });
     286
     287      OnContentChanged();
     288      SetEnabledStateOfControls();
     289    }
     290
     291    private void treeSlaveGroup_MouseDown(object sender, MouseEventArgs e) {
     292      var node = treeView.GetNodeAt(e.Location);
     293      if (node == null || node == ungroupedGroupNode) return;
     294      var r = (Resource)node.Tag;
     295      if (!HiveAdminClient.Instance.DisabledParentResources.Contains(r)) ChangeSelectedResourceNode(node);
     296    }
     297
     298    private void treeSlaveGroup_BeforeSelect(object sender, TreeViewCancelEventArgs e) {
     299      e.Cancel = true;
     300    }
     301
     302    private void treeSlaveGroup_BeforeCheck(object sender, TreeViewCancelEventArgs e) {
     303      if (!IsAdmin() || e.Node == ungroupedGroupNode) {
     304        e.Cancel = true;
    205305      } else {
    206         btnAddGroup.Enabled = true;
    207         btnRemoveGroup.Enabled = true;
    208         btnSave.Enabled = true;
    209         scheduleView.SetEnabledStateOfSchedule(IsAuthorized(slaveView.Content));
    210         btnPermissionsSave.Enabled = permissionView.FetchSelectedUsers != null;
    211         permissionView.Enabled = permissionView.FetchSelectedUsers != null;
    212       }
    213     }
    214 
    215     private bool IsAuthorized(Resource resource) {
    216       return resource != null
    217           && resource.Name != UngroupedGroupName
    218           && resource.Id != Guid.Empty
    219           && UserInformation.Instance.UserExists
    220           && (resource.OwnerUserId == UserInformation.Instance.User.Id || HiveRoles.CheckAdminUserPermissions());
    221     }
    222 
    223     private void treeSlaveGroup_AfterSelect(object sender, TreeViewEventArgs e) {
    224       if (e.Action != TreeViewAction.Unknown) {
    225         Resource selectedResource = ((Resource)e.Node.Tag);
    226         currentlyAuthorized = IsAuthorized(selectedResource);
    227         if (currentlyAuthorized) {
    228           permissionView.FetchSelectedUsers = new Func<List<Guid>>(() => {
    229             return HiveServiceLocator.Instance.CallHiveService<List<ResourcePermission>>(service => {
    230               return service.GetResourcePermissions(selectedResource.Id);
    231             }).Select(x => x.GrantedUserId).ToList();
    232           });
    233           if (!tabSlaveGroup.TabPages.Contains(tabPermissions)) tabSlaveGroup.TabPages.Add(tabPermissions);
     306        var r = (Resource)e.Node.Tag;
     307        if (HiveAdminClient.Instance.DisabledParentResources.Contains(r)) {
     308          e.Cancel = true;
     309        }
     310      }
     311    }
     312
     313    private void treeSlaveGroup_AfterCheck(object sender, TreeViewEventArgs e) {
     314      SetEnabledStateOfControls();
     315    }
     316
     317    private void treeSlaveGroup_DragDrop(object sender, DragEventArgs e) {
     318      if (e.Effect == DragDropEffects.None) return;
     319
     320      var targetNode = treeView.GetNodeAt(treeView.PointToClient(new Point(e.X, e.Y)));
     321      var targetResource = (targetNode != null) ? (Resource)targetNode.Tag : null;
     322      var resources = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat) as IEnumerable<Resource>;
     323
     324      foreach (var r in resources) {
     325        r.ParentResourceId = targetResource != null ? targetResource.Id : (Guid?)null;
     326      }
     327
     328      // TODO
     329      //HiveAdminClient.Instance.UpdateResourceGenealogy(Content);
     330      OnContentChanged();
     331    }
     332
     333    private void treeSlaveGroup_ItemDrag(object sender, ItemDragEventArgs e) {
     334      if (!IsAdmin()) return;
     335
     336      var nodes = GetCheckedNodes(treeView.Nodes).ToList();
     337      TreeNode sourceNode = (TreeNode)e.Item;
     338      if (!sourceNode.Checked) nodes.Add(sourceNode);
     339      nodes.Remove(ungroupedGroupNode);
     340      ungroupedGroupNode.Checked = false;
     341      var resources = nodes.Select(x => x.Tag).OfType<Resource>().ToList();
     342
     343      if (resources.Count > 0) {
     344        DataObject data = new DataObject();
     345        data.SetData(HeuristicLab.Common.Constants.DragDropDataFormat, resources);
     346        var action = DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link | DragDropEffects.Move);
     347        if (action.HasFlag(DragDropEffects.Move)) {
     348          foreach (var node in nodes) node.Remove();
     349          StyleTreeNode(ungroupedGroupNode, (Resource)ungroupedGroupNode.Tag, resources);
     350        }
     351      }
     352    }
     353
     354    private IEnumerable<TreeNode> GetCheckedNodes(TreeNodeCollection nodes) {
     355      if (nodes != null) {
     356        foreach (var node in nodes.OfType<TreeNode>()) {
     357          if (node.Checked && node != ungroupedGroupNode) yield return node;
     358          foreach (var child in GetCheckedNodes(node.Nodes))
     359            yield return child;
     360        }
     361      }
     362    }
     363
     364    private void treeSlaveGroup_DragEnterOver(object sender, DragEventArgs e) {
     365      e.Effect = DragDropEffects.Move;
     366      var resources = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat) as IEnumerable<Resource>;
     367      var targetNode = treeView.GetNodeAt(treeView.PointToClient(new Point(e.X, e.Y)));
     368      var targetResource = (targetNode != null ? targetNode.Tag : null) as Resource;
     369
     370      if (!IsAdmin()
     371        || resources == null
     372        || !resources.Any()
     373        || resources.Any(x => !HiveAdminClient.Instance.CheckParentChange(x, targetResource))
     374        || (targetNode != null && (targetNode == ungroupedGroupNode || targetNode.Parent == ungroupedGroupNode))) {
     375        e.Effect = DragDropEffects.None;
     376      }
     377    }
     378
     379    private void TabSlaveGroup_TabIndexChanged(object sender, EventArgs e) {
     380      throw new NotImplementedException();
     381    }
     382
     383    private async void TabSlaveGroup_Selected(object sender, System.Windows.Forms.TabControlEventArgs e) {
     384      if (e.TabPage == tabSchedule) {
     385        await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
     386          action: () => UpdateSchedule(),
     387          finallyCallback: () => scheduleView.Content = HiveAdminClient.Instance.Downtimes);
     388      }
     389      SetEnabledStateOfControls();
     390    }
     391    #endregion
     392
     393    #region Helpers
     394    private void BuildResourceTree(IEnumerable<Resource> resources) {
     395      treeView.Nodes.Clear();
     396      if (!resources.Any()) return;
     397
     398      var disabledParentResources = HiveAdminClient.Instance.DisabledParentResources;
     399      var mainResources = new HashSet<Resource>(resources.OfType<SlaveGroup>()
     400        .Where(x => x.ParentResourceId == null));
     401      //var parentedMainResources = new HashSet<Resource>(resources.OfType<SlaveGroup>()
     402      //  .Where(x => x.ParentResourceId.HasValue && !resources.Select(y => y.Id).Contains(x.ParentResourceId.Value)));
     403      //mainResources.UnionWith(parentedMainResources);
     404      var mainDisabledParentResources = new HashSet<Resource>(disabledParentResources.Where(x => x.ParentResourceId == null || x.ParentResourceId == Guid.Empty));
     405      mainResources.UnionWith(mainDisabledParentResources);
     406      var subResources = new HashSet<Resource>(resources.Union(disabledParentResources).Except(mainResources).OrderByDescending(x => x.Name));
     407
     408      var stack = new Stack<Resource>(mainResources.OrderByDescending(x => x.Name));
     409      if (selectedResource != null) SelectedResource = resources.Where(x => x.Id == selectedResource.Id).FirstOrDefault();
     410      bool nodeSelected = false;
     411
     412      TreeNode currentNode = null;
     413      Resource currentResource = null;
     414
     415      while (stack.Any()) {
     416        var newResource = stack.Pop();
     417        var newNode = new TreeNode(newResource.Name) { Tag = newResource };
     418        StyleTreeNode(newNode, newResource, resources);
     419
     420        if (selectedResource == null && !disabledParentResources.Contains(newResource)) {
     421          SelectedResource = newResource;
     422        }
     423        if (!nodeSelected && selectedResource != null && newResource.Id == selectedResource.Id) {
     424          newNode.BackColor = selectedBackColor;
     425          newNode.ForeColor = selectedForeColor;
     426          newNode.Text += SELECTED_TAG;
     427          nodeSelected = true;
     428        }
     429
     430        if (disabledParentResources.Contains(newResource)) {
     431          newNode.Checked = false;
     432          newNode.ForeColor = grayTextColor;
     433        }
     434
     435        // search for parent node of newNode and save in currentNode
     436        // necessary since newNodes (stack top items) might be siblings
     437        // or grand..grandparents of previous node (currentNode)
     438        while (currentNode != null && newResource.ParentResourceId != currentResource.Id) {
     439          currentNode = currentNode.Parent;
     440          currentResource = currentNode == null ? null : (Resource)currentNode.Tag;
     441        }
     442
     443        if (currentNode == null) {
     444          treeView.Nodes.Add(newNode);
    234445        } else {
    235           permissionView.FetchSelectedUsers = null;
    236           btnPermissionsSave.Enabled = false;
    237           if (selectedResource.Id == Guid.Empty) {
    238             if (!tabSlaveGroup.TabPages.Contains(tabPermissions)) tabSlaveGroup.TabPages.Add(tabPermissions);
    239           } else tabSlaveGroup.TabPages.Remove(tabPermissions);
    240         }
    241 
    242         if (slaveView.Content != null && slaveView.Content is SlaveGroup) {
    243           slaveView.Content.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler(SlaveViewContent_PropertyChanged);
    244         }
    245 
    246         slaveView.Content = selectedResource;
    247         HiveAdminClient.Instance.DowntimeForResourceId = selectedResource.Id;
    248 
    249         if (selectedResource is SlaveGroup) {
    250           slaveView.Content.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(SlaveViewContent_PropertyChanged);
    251         }
    252 
    253         if (tabSlaveGroup.SelectedIndex == 1) {
    254           UpdateScheduleAsync();
    255         } else if (tabSlaveGroup.SelectedIndex == 2) {
    256           UpdatePermissionsAsync();
    257         }
    258       }
    259     }
    260 
    261     void SlaveViewContent_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) {
    262       OnContentChanged();
    263       if (e.PropertyName == "HbInterval") {
    264         UpdateChildHbIntervall(slaveView.Content);
     446          currentNode.Nodes.Add(newNode);
     447        }
     448
     449        if (newResource is SlaveGroup) {
     450          var childResources = subResources.Where(x => x.ParentResourceId == newResource.Id);
     451          if (childResources.Any()) {
     452            foreach (var resource in childResources.OrderByDescending(x => x.Name)) {
     453              subResources.Remove(resource);
     454              stack.Push(resource);
     455            }
     456            currentNode = newNode;
     457            currentResource = newResource;
     458          }
     459        }
     460        newNode.SelectedImageIndex = newNode.ImageIndex;
     461      }
     462
     463      // collapse slave-only nodes
     464      foreach (TreeNode n in treeView.Nodes) {
     465        CollapseSlaveOnlyNodes(n);
     466      }
     467
     468      ungroupedGroupNode = new TreeNode(UNGROUPED_GROUP_NAME) {
     469        ForeColor = SystemColors.GrayText,
     470        ImageIndex = slaveGroupImageIndex,
     471        Tag = new SlaveGroup() {
     472          Name = UNGROUPED_GROUP_NAME,
     473          Description = UNGROUPED_GROUP_DESCRIPTION
     474        }
     475      };
     476
     477      foreach (var slave in subResources.OfType<Slave>().OrderBy(x => x.Name)) {
     478        var slaveNode = new TreeNode(slave.Name) { Tag = slave };
     479        StyleTreeNode(slaveNode, slave, resources);
     480        ungroupedGroupNode.Nodes.Add(slaveNode);
     481        if (selectedResource == null) {
     482          SelectedResource = slave;
     483        }
     484
     485        if (slave.Id == selectedResource.Id && !nodeSelected) {
     486          slaveNode.BackColor = selectedBackColor;
     487          slaveNode.ForeColor = selectedForeColor;
     488          slaveNode.Text += SELECTED_TAG;
     489          nodeSelected = true;
     490        }
     491      }
     492
     493      if (ungroupedGroupNode.Nodes.Count > 0) {
     494        ungroupedGroupNode.Text += " [" + ungroupedGroupNode.Nodes.Count.ToString() + "]";
     495        ungroupedGroupNode.Expand();
     496        treeView.Nodes.Add(ungroupedGroupNode);
     497      }
     498    }
     499
     500    private void CollapseSlaveOnlyNodes(TreeNode tn) {
     501      Resource r = (Resource)tn.Tag;
     502      var descendants = GetResourceDescendants();
     503      if (descendants.ContainsKey(r.Id)) {
     504        if (descendants[r.Id].OfType<SlaveGroup>().Any()) {
     505          tn.Expand();
     506          foreach (TreeNode n in tn.Nodes) CollapseSlaveOnlyNodes(n);
     507        } else {
     508          tn.Collapse();
     509        }
     510      }
     511    }
     512
     513    private void ExpandResourceNodesOfInterest(TreeNodeCollection nodes) {
     514      foreach (TreeNode n in nodes) {
     515        Resource r = (Resource)n.Tag;
     516        if (n.Nodes.Count > 0) {
     517          if (HiveAdminClient.Instance.GetAvailableResourceDescendants(r.Id).OfType<SlaveGroup>().Any()) {
     518            n.Expand();
     519            ExpandResourceNodesOfInterest(n.Nodes);
     520          } else {
     521            n.Collapse();
     522          }
     523        } else {
     524          n.Collapse();
     525        }
    265526      }
    266527    }
     
    275536    }
    276537
    277     private void btnAddGroup_Click(object sender, EventArgs e) {
    278       SlaveGroup newGroup = new SlaveGroup();
    279       newGroup.Name = "New Group";
    280       newGroup.OwnerUserId = UserInformation.Instance.User.Id;
    281       Content.Add(newGroup);
    282     }
    283 
    284     void Content_ItemsRemoved(object sender, Collections.CollectionItemsChangedEventArgs<Collections.IndexedItem<Resource>> e) {
    285       OnContentChanged();
    286     }
    287 
    288     void Content_ItemsAdded(object sender, Collections.CollectionItemsChangedEventArgs<Collections.IndexedItem<Resource>> e) {
    289       OnContentChanged();
    290     }
    291 
    292     private void btnRemoveGroup_Click(object sender, EventArgs e) {
    293       if (treeSlaveGroup.SelectedNode != null && treeSlaveGroup.SelectedNode.Tag != null) {
    294         Resource res = (Resource)treeSlaveGroup.SelectedNode.Tag;
    295 
    296         DialogResult diagRes = MessageBox.Show("Do you really want to delete " + res.Name + "?", "HeuristicLab Hive Administrator", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
    297         if (diagRes == DialogResult.Yes) {
    298           if (res is Slave) {
    299             Content.Remove(res);
    300             HiveAdminClient.Delete(res);
    301           } else if (res is SlaveGroup) {
    302             //only delete empty groups
    303             if (Content.Where(s => s.ParentResourceId == res.Id).Count() < 1) {
    304               Content.Remove(res);
    305               HiveAdminClient.Delete(res);
    306             } else {
    307               MessageBox.Show("Only empty groups can be deleted.", "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
    308             }
     538    private void UpdateResources() {
     539      lock (locker) {
     540        if (refreshingInternal || refreshingExternal) return;
     541        refreshingInternal = true;
     542      }
     543
     544      try {
     545        HiveAdminClient.Instance.Refresh();
     546      } catch (AnonymousUserException) {
     547        ShowHiveInformationDialog();
     548      } finally {
     549        refreshingInternal = false;
     550      }
     551    }
     552
     553    private void RemoveResource(Resource resource) {
     554      if (resource == null) return;
     555
     556      try {
     557        if (resource.Id != Guid.Empty) {
     558          SelectedResource = HiveAdminClient.Instance.GetAvailableResourceAncestors(resource.Id).LastOrDefault();
     559
     560          // deal with all new, but not yet saved resources
     561          var newResources = Content.Where(x => x.ParentResourceId == resource.Id).ToList();
     562          if (newResources.Any(x => x.Id != Guid.Empty)) return;
     563          foreach (var nr in newResources) Content.Remove(nr);
     564
     565          HiveAdminClient.Delete(resource);
     566          UpdateResources();
     567        } else {
     568          SelectedResource = Content.FirstOrDefault(x => x.Id == resource.ParentResourceId);
     569          Content.Remove(resource);
     570        }
     571      } catch (AnonymousUserException) {
     572        ShowHiveInformationDialog();
     573      }
     574    }
     575
     576    private void RemoveResource(IEnumerable<Resource> resources) {
     577      if (resources == null || !resources.Any()) return;
     578
     579      var ids = resources.Select(x => x.Id).ToList();
     580      try {
     581        bool update = false;
     582        foreach (var r in resources) {
     583          if (r.Id != Guid.Empty) {
     584            if (r.Id == SelectedResource.Id)
     585              SelectedResource = HiveAdminClient.Instance.GetAvailableResourceAncestors(r.Id).LastOrDefault();
     586
     587            // deal with all new, but not yet saved resources
     588            var newResources = Content.Where(x => x.ParentResourceId == r.Id).ToList();
     589            if (newResources.Any(x => x.Id != Guid.Empty)) return;
     590            foreach (var nr in newResources) Content.Remove(nr);
     591
     592            HiveAdminClient.Delete(r);
     593            update = true;
     594          } else {
     595            if (r.Id == SelectedResource.Id)
     596              SelectedResource = Content.FirstOrDefault(x => x.Id == r.ParentResourceId);
     597            Content.Remove(r);
    309598          }
    310599        }
    311       }
    312     }
    313 
    314     private void btnSave_Click(object sender, EventArgs e) {
    315       foreach (Resource res in Content) {
    316         if (res is SlaveGroup && res.Id == Guid.Empty) {
    317           SlaveGroup slaveGroup = (SlaveGroup)res;
    318           slaveGroup.Store();
    319         } else if (res.Id != Guid.Empty && res.Modified) {
    320           res.Store();
    321         }
    322       }
    323     }
    324 
    325     private void treeSlaveGroup_DragDrop(object sender, DragEventArgs e) {
    326       if (e.Data.GetDataPresent("System.Windows.Forms.TreeNode", false)) {
    327         Point pt = ((TreeView)sender).PointToClient(new Point(e.X, e.Y));
    328         TreeNode destNode = ((TreeView)sender).GetNodeAt(pt);
    329         TreeNode newNode = (TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode");
    330 
    331         if (destNode.TreeView == newNode.TreeView) {
    332           if (destNode.Text == UngroupedGroupName || (destNode.Parent != null && destNode.Parent.Text == UngroupedGroupName)) {
    333             MessageBox.Show(string.Format("You can't drag items to the group \"{0}\".{1}This group only contains slaves which haven't yet been assigned to a real group.",
    334               UngroupedGroupName, Environment.NewLine), "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Information);
    335             return;
    336           }
    337 
    338           SlaveGroup sgrp = null;
    339           TreeNode parentNode = null;
    340           if (destNode.Tag != null && destNode.Tag is SlaveGroup) {
    341             sgrp = (SlaveGroup)destNode.Tag;
    342             parentNode = destNode;
    343           } else if (destNode.Parent != null && destNode.Parent.Tag is SlaveGroup) {
    344             sgrp = (SlaveGroup)destNode.Parent.Tag;
    345             parentNode = destNode.Parent;
    346           }
    347 
    348           if (newNode.Tag is SlaveGroup && CheckParentsEqualsMovedNode(parentNode, newNode)) {
    349             return;
    350           }
    351 
    352           SlaveGroup parent = (SlaveGroup)parentNode.Tag;
    353 
    354           if (parent.OwnerUserId != null && !IsAuthorized(parent)) {
    355             MessageBox.Show(string.Format("You don't have the permissions to drag items to the group \"{0}\".", ((Resource)parentNode.Tag).Name),
    356               "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
    357             return;
    358           }
    359 
    360           if (sgrp != null && newNode.Tag != null) {
    361             //save parent group to get an id
    362             if (sgrp.Id == Guid.Empty) {
    363               sgrp.Store();
    364             }
    365 
    366             if (newNode.Tag is Slave) {
    367               Slave slave = (Slave)newNode.Tag;
    368               if (slave.ParentResourceId == null || (slave.ParentResourceId != null && slave.ParentResourceId != sgrp.Id)) {
    369                 slave.ParentResourceId = sgrp.Id;
    370                 newNode.Remove();
    371                 parentNode.Nodes.Clear();
    372                 BuildSlaveGroupTree(sgrp, parentNode);
    373               }
    374             } else if (newNode.Tag is SlaveGroup) {
    375               SlaveGroup slaveGroup = (SlaveGroup)newNode.Tag;
    376               if (slaveGroup.ParentResourceId == null || (slaveGroup.ParentResourceId != null && slaveGroup.ParentResourceId != sgrp.Id)) {
    377                 slaveGroup.ParentResourceId = sgrp.Id;
    378                 newNode.Remove();
    379                 parentNode.Nodes.Clear();
    380                 BuildSlaveGroupTree(sgrp, parentNode);
    381               }
    382             }
    383           }
    384         }
    385       }
    386     }
    387 
    388     private bool CheckParentsEqualsMovedNode(TreeNode dest, TreeNode movedNode) {
    389       TreeNode tmp = dest;
    390 
    391       while (tmp != null) {
    392         if (tmp == movedNode) {
    393           return true;
    394         }
    395         tmp = tmp.Parent;
    396       }
    397       return false;
    398     }
    399 
    400     private void treeSlaveGroup_ItemDrag(object sender, ItemDragEventArgs e) {
    401       TreeNode sourceNode = (TreeNode)e.Item;
    402       if (IsAuthorized((Resource)sourceNode.Tag))
    403         DoDragDrop(sourceNode, DragDropEffects.All);
    404     }
    405 
    406     private void treeSlaveGroup_DragEnter(object sender, DragEventArgs e) {
    407       e.Effect = DragDropEffects.Move;
    408     }
    409 
    410     private void treeSlaveGroup_DragOver(object sender, DragEventArgs e) {
    411       e.Effect = DragDropEffects.Move;
    412     }
    413 
    414     private void treeSlaveGroup_QueryContinueDrag(object sender, QueryContinueDragEventArgs e) {
    415       e.Action = DragAction.Continue;
    416     }
    417 
    418     void ResetView() {
    419       if (this.InvokeRequired) {
    420         Invoke(new Action(ResetView));
     600        if (update) UpdateResources();
     601      } catch (AnonymousUserException) {
     602        ShowHiveInformationDialog();
     603      }
     604    }
     605
     606    private void UpdateSchedule() {
     607      try {
     608        HiveAdminClient.Instance.RefreshCalendar();
     609      } catch (AnonymousUserException) {
     610        ShowHiveInformationDialog();
     611      }
     612    }
     613
     614    private bool IsAdmin() {
     615      return HiveRoles.CheckAdminUserPermissions();
     616    }
     617
     618    private void StyleTreeNode(TreeNode n, Resource r, IEnumerable<Resource> resources) {
     619      n.Text = r.Name;
     620      n.BackColor = Color.Transparent;
     621      n.ForeColor = Color.Black;
     622
     623      if (HiveAdminClient.Instance.DisabledParentResources.Select(x => x.Id).Contains(r.Id)) {
     624        n.ForeColor = grayTextColor;
     625      } else if (r.Id == Guid.Empty && n != ungroupedGroupNode /*!r.Name.StartsWith(UNGROUPED_GROUP_NAME)*/) {
     626        // not stored (i.e. new)
     627        n.Text += NOT_STORED_TAG;
     628      } else if (r.Modified && n != ungroupedGroupNode /*!r.Name.StartsWith(UNGROUPED_GROUP_NAME)*/) {
     629        // changed
     630        n.Text += CHANGES_NOT_STORED_TAG;
     631      }
     632
     633      // slave count
     634      int childSlavesCount = 0;
     635      if (r.Id != Guid.Empty && r is SlaveGroup) {
     636        var descendants = GetResourceDescendants();
     637        if (descendants.ContainsKey(r.Id)) {
     638          childSlavesCount = resources
     639            .OfType<Slave>()
     640            .Where(x => descendants[r.Id].Select(y => y.Id)
     641              .Contains(x.Id))
     642            .Count();
     643        }
     644      } else if (n == ungroupedGroupNode /*|| r.Name.StartsWith(UNGROUPED_GROUP_NAME)*/) {
     645        childSlavesCount = resources
     646          .OfType<Slave>()
     647          .Where(x => x.ParentResourceId == null
     648            || (x.ParentResourceId.HasValue && x.ParentResourceId.Value == Guid.Empty))
     649          .Count();
     650      }
     651      if (childSlavesCount > 0)
     652        n.Text += " [" + childSlavesCount.ToString() + "]";
     653
     654      // slave image index, state, utilization
     655      if (r is Slave) {
     656        n.ImageIndex = slaveImageIndex;
     657        var s = r as Slave;
     658        if (s.SlaveState == SlaveState.Calculating) {
     659          n.ForeColor = calculatingColor;
     660          n.Text += " [" + s.CpuUtilization.ToString("N2") + "%]";
     661        } else if (s.SlaveState == SlaveState.Offline) {
     662          n.ForeColor = offlineColor;
     663          if (s.LastHeartbeat.HasValue)
     664            n.Text += " [" + (s.LastHeartbeat != null ? s.LastHeartbeat.Value.ToString("g") : null) + "]";
     665        }
    421666      } else {
    422         treeSlaveGroup.Nodes.Clear();
    423 
    424         if (slaveView.Content != null && slaveView.Content is SlaveGroup) {
    425           slaveView.Content.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler(SlaveViewContent_PropertyChanged);
    426         }
    427         slaveView.Content = null;
     667        n.ImageIndex = slaveGroupImageIndex;
     668      }
     669
     670      // ungrouped
     671      if (n == ungroupedGroupNode /*r.Name.StartsWith(UNGROUPED_GROUP_NAME)*/) {
     672        n.ForeColor = SystemColors.GrayText;
     673      }
     674    }
     675
     676    private void ResetTreeNodes(TreeNodeCollection nodes, IEnumerable<Resource> resources) {
     677      foreach (TreeNode n in nodes) {
     678        StyleTreeNode(n, (Resource)n.Tag, resources);
     679        if (n.Nodes.Count > 0) {
     680          ResetTreeNodes(n.Nodes, resources);
     681        }
     682      }
     683    }
     684
     685    private async void ChangeSelectedResource(Resource resource) {
     686      selectedResource = resource;
     687      viewHost.Content = selectedResource;
     688
     689      HiveAdminClient.Instance.DowntimeForResourceId = selectedResource != null ? selectedResource.Id : Guid.Empty;
     690      if (tabSlaveGroup.SelectedTab == tabSchedule) {
     691        await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
     692          action: () => UpdateSchedule(),
     693          finallyCallback: () => scheduleView.Content = HiveAdminClient.Instance.Downtimes);
     694      }
     695
     696      SetEnabledStateOfControls();
     697    }
     698
     699    private void ChangeSelectedResourceNode(TreeNode resourceNode) {
     700      if (resourceNode == null) return;
     701      SelectedResource = (Resource)resourceNode.Tag;
     702      ResetTreeNodes(treeView.Nodes, Content);
     703      resourceNode.BackColor = selectedBackColor;
     704      resourceNode.ForeColor = selectedForeColor;
     705      resourceNode.Text += SELECTED_TAG;
     706    }
     707
     708    private void ShowHiveInformationDialog() {
     709      if (InvokeRequired) Invoke((Action)ShowHiveInformationDialog);
     710      else {
     711        using (HiveInformationDialog dialog = new HiveInformationDialog()) {
     712          dialog.ShowDialog(this);
     713        }
     714      }
     715    }
     716
     717    private void ResetView() {
     718      if (InvokeRequired) Invoke((Action)ResetView);
     719      else {
     720        treeView.Nodes.Clear();
     721
     722        if (viewHost.Content != null && viewHost.Content is SlaveGroup) {
     723          ((SlaveGroup)viewHost.Content).PropertyChanged -= SlaveViewContent_PropertyChanged;
     724        }
     725
     726        viewHost.Content = null;
    428727        if (scheduleView.Content != null) {
    429728          scheduleView.Content.Clear();
    430729        }
     730
    431731        HiveAdminClient.Instance.ResetDowntime();
    432732      }
    433733    }
    434734
    435     private void UpdateResources() {
    436       ResetView();
    437 
    438       try {
    439         if (!Access.UserInformation.Instance.UserExists) {
    440           //do a refresh just in case that the user has changed his usr and pwd in between
    441           Access.UserInformation.Instance.Refresh();
    442         }
    443         HiveAdminClient.Instance.Refresh();
    444         Content = HiveAdminClient.Instance.Resources;
    445       }
    446       catch (MessageSecurityException) {
    447         ShowMessageSecurityException();
    448       }
    449       catch (AnonymousUserException) {
    450         ShowHiveInformationDialog();
    451       }
    452     }
    453 
    454     private void ShowMessageSecurityException() {
    455       if (this.InvokeRequired) {
    456         Invoke(new Action(ShowMessageSecurityException));
    457       } else {
    458         MessageBox.Show("A Message Security error has occured. This normally means that your user name or password is wrong.", "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
    459       }
    460     }
    461 
    462     private void ShowHiveInformationDialog() {
    463       if (this.InvokeRequired) {
    464         Invoke(new Action(ShowHiveInformationDialog));
    465       } else {
    466         using (HiveInformationDialog dialog = new HiveInformationDialog()) {
    467           dialog.ShowDialog(this);
    468         }
    469       }
    470     }
    471 
    472     private void UpdateResourcesAsync() {
    473       TS.Task.Factory.StartNew(UpdateResources).ContinueWith((t) => {
    474         DisplayError(t.Exception);
    475       }, TaskContinuationOptions.OnlyOnFaulted);
    476     }
    477 
    478     private void UpdateSchedule() {
    479       HiveAdminClient.Instance.RefreshCalendar();
    480       scheduleView.Invoke(new Action(() => {
    481         scheduleView.Content = HiveAdminClient.Instance.Downtimes;
    482         SetEnabledStateOfControls();
    483       }));
    484     }
    485 
    486     private void UpdateScheduleAsync() {
    487       TS.Task.Factory.StartNew(UpdateSchedule).ContinueWith((t) => {
    488         DisplayError(t.Exception);
    489       }, TaskContinuationOptions.OnlyOnFaulted);
    490     }
    491 
    492     private void UpdatePermissions() {
    493       if (permissionView.Content != null && permissionView.FetchSelectedUsers != null)
    494         permissionView.Invoke(new Action(() => permissionView.ManualRefresh()));
    495     }
    496 
    497     private void UpdatePermissionsAsync() {
    498       TS.Task.Factory.StartNew(UpdatePermissions).ContinueWith((t) => {
    499         DisplayError(t.Exception);
    500       }, TaskContinuationOptions.OnlyOnFaulted);
    501     }
    502 
    503 
    504     private void DisplayError(Exception ex) {
    505       MessageBox.Show(string.Format("An error occured while updating: {0} {1}", Environment.NewLine, ex.Message), "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
    506     }
    507 
    508     private void tabSlaveGroup_SelectedIndexChanged(object sender, EventArgs e) {
    509       if (tabSlaveGroup.SelectedIndex == 1) {
    510         UpdateScheduleAsync();
    511       } else if (tabSlaveGroup.SelectedIndex == 2) {
    512         UpdatePermissionsAsync();
    513       }
    514     }
    515 
    516     private void btnRefresh_Click(object sender, EventArgs e) {
    517       UpdateResourcesAsync();
    518     }
    519 
    520     private void ResourcesView_Load(object sender, EventArgs e) {
    521       UpdateResourcesAsync();
    522     }
    523 
    524     private void btnPermissionsSave_Click(object sender, EventArgs e) {
    525       SetEnabledStateOfControls();
    526       HiveServiceLocator.Instance.CallHiveService(service => {
    527         service.GrantResourcePermissions(((Resource)treeSlaveGroup.SelectedNode.Tag).Id, permissionView.GetAddedUsers().Select(x => x.Id).ToList());
    528         service.RevokeResourcePermissions(((Resource)treeSlaveGroup.SelectedNode.Tag).Id, permissionView.GetDeletedUsers().Select(x => x.Id).ToList());
    529       });
    530       SetEnabledStateOfControls();
    531     }
     735
     736    private Dictionary<Guid, HashSet<Resource>> GetResourceDescendants() {
     737      var resourceDescendants = new Dictionary<Guid, HashSet<Resource>>();
     738      //var resources = Content.Where(x => x.Id != Guid.Empty).Union(HiveAdminClient.Instance.DisabledParentResources).ToList();     
     739      var resources = Content.Union(HiveAdminClient.Instance.DisabledParentResources).ToList();
     740
     741      foreach (var r in resources) {
     742        if (!resourceDescendants.ContainsKey(r.Id))
     743          resourceDescendants.Add(r.Id, new HashSet<Resource>());
     744      }
     745      foreach (var r in resources) {
     746        var parentResourceId = r.ParentResourceId;
     747        while (parentResourceId != null) {
     748          var parent = resources.SingleOrDefault(x => x.Id == parentResourceId);
     749          if (parent != null) {
     750            resourceDescendants[parent.Id].Add(r);
     751            parentResourceId = parent.ParentResourceId;
     752          } else {
     753            parentResourceId = null;
     754          }
     755        }
     756      }
     757      return resourceDescendants;
     758    }
     759
     760    #endregion
    532761  }
    533762}
Note: See TracChangeset for help on using the changeset viewer.