Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
07/04/19 14:28:13 (5 years ago)
Author:
mkommend
Message:

#2839: Merged 16117, 16122, 16173, 16184, 16185, 16186, 16187, 16202, 16203, 16204, 16205, 16208, 16211, 16209, 16211, 16219, 16257, 16247 into stable.

Location:
stable
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • stable

  • stable/HeuristicLab.Clients.Hive.Administrator

    • Property svn:mergeinfo set to (toggle deleted branches)
      /branches/2839_HiveProjectManagement/HeuristicLab.Clients.Hive.Administratormergedeligible
      /trunk/HeuristicLab.Clients.Hive.Administratormergedeligible
      /branches/1721-RandomForestPersistence/HeuristicLab.Clients.Hive.Administrator10321-10322
      /branches/2916_IndexedDataTableSerialization/HeuristicLab.Clients.Hive.Administrator15918
      /branches/2947_ConfigurableIndexedDataTable/HeuristicLab.Clients.Hive.Administrator16148-16526
      /branches/2972_PDPRowSelect/HeuristicLab.Clients.Hive.Administrator16444-16518
      /branches/Algorithms.GradientDescent/HeuristicLab.Clients.Hive.Administrator5516-5520
      /branches/Async/HeuristicLab.Clients.Hive.Administrator13329-15286
      /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/symbreg-factors-2650/HeuristicLab.Clients.Hive.Administrator14232-14825
      /trunk/sources/HeuristicLab.Clients.Hive.Administrator9493,​9496,​9498,​9504-9506,​9515-9517,​9520-9521,​9523,​9530-9531,​9534-9537,​9540,​9542-9544,​9552-9555,​9568-9569,​9587,​9590-9592,​9600,​9607-9608,​9610-9611,​9613,​9618,​9623-9624,​9626,​9647-9649,​9652,​9657-9660,​9664-9666,​9675,​9692,​9695,​9699,​9702,​9710,​9714,​9718-9720,​9740-9741,​9751-9752,​9755,​9762,​9764-9775,​9777-9778,​9782-9786,​9792,​9794-9795,​9803-9812,​9816-9822,​9824-9825,​9828,​9830,​9833,​9837-9841,​9845,​9848-9851,​9855,​9859-9860,​9863,​9865-9868,​9871,​9893-9897,​9900-9902,​9905-9907,​9910,​9915-9916,​9919-9921,​9928,​9930,​9934-9935,​9938-9941,​9944,​9946,​9949,​9955-9956,​9958-9959,​9964-9965,​9973-9975,​9978,​9980-9982,​9988-9989,​9991-9992,​9994-9995,​9997,​10000-10005,​10009-10010,​10015,​10130,​10149-10150,​10154,​10170-10171,​10173-10176,​10195-10196,​10212-10213,​10231,​10261,​10273,​10291-10292,​10295,​10298,​10323-10324,​10346,​10348,​10355,​10359-10360,​10362-10363,​10365-10366,​10368,​10375,​10378,​10391,​10401,​10406-10407,​10414,​10417-10418,​10428,​10432-10433,​10435,​10440,​10448,​10453,​10460,​10465-10466,​10469-10470,​10472,​10474-10477,​10480,​10484,​10486,​10488-10500,​10503-10504,​10506,​10510-10512,​10519-10523,​10526,​10531,​10540-10541,​10543,​10545,​10561-10566,​10575-10578,​10596-10597,​10599,​10601-10607,​10639,​10642-10643,​10646,​10651-10653,​10727,​10731,​10745,​10747,​10761,​10767,​10774,​10787-10791,​10793-10794,​10796,​10799-10800,​10826,​10857-10862,​10865,​10885,​10889,​10894-10896,​10924,​10926-10927,​10937,​10941,​10953,​10955-10956,​10958-10961,​10963,​10975,​10983-10986,​10988-10989,​10996,​11007-11008,​11012-11014,​11019,​11024-11027,​11031,​11034-11035,​11048,​11050-11052,​11056-11058,​11060,​11065-11067,​11071,​11074-11082,​11086-11088,​11091-11093,​11095-11097,​11099-11100,​11102,​11108,​11111-11117,​11123-11128,​11131,​11135,​11153,​11156,​11161,​11214,​11241,​11243,​11248-11251,​11256,​11263,​11274,​11280,​11282-11283,​11285-11287,​11290,​11292,​11294-11296,​11298,​11300,​11302,​11306,​11308-11309,​11313,​11315,​11317,​11324,​11326,​11330-11332,​11337-11348,​11352-11353,​11361-11362,​11364-11367,​11380-11382,​11384,​11389,​11391-11392,​11394,​11403-11404,​11410-11411,​11417-11420,​11422,​11426-11430,​11432,​11434-11437,​11439-11448,​11450,​11453,​11455-11457,​11464,​11466-11467,​11469-11472,​11474,​11477-11480,​11483,​11494-11498,​11504,​11514-11515,​11523-11525,​11532-11533,​11536,​11540-11542,​11544-11545,​11547-11549,​11555,​11557,​11581,​11592,​11596-11597,​11599-11600,​11605,​11608,​11610,​11615-11616,​11618,​11623,​11631,​11634,​11650-11652,​11657,​11675,​11679-11680,​11703-11706,​11715,​11717,​11721,​11723-11725,​11734-11736,​11756-11758,​11762-11764,​11766,​11771-11772,​11781-11782,​11784,​11787-11790,​11794,​11807-11811,​11815-11816,​11818-11819,​11822,​11825-11831,​11833-11837,​11839-11840,​11853-11854,​11856,​11877-11879,​11882,​11890,​11909,​11912-11918,​11921,​11930,​11933-11934,​11936,​11938-11939,​11942,​11945,​11948,​11950-11951,​11955-11956,​11958-11961,​11963,​11967,​11970-11971,​11978,​11982-11984,​11987-11994,​11996,​11998-12004,​12015-12744,​12755,​12770,​12772,​12787,​12790-12798,​12801,​12807,​12810-12812,​12816-12819,​12835-12837,​12839,​12844-12846,​12851,​12855,​12868,​12873,​12875,​12878-12879,​12883,​12885-12886,​12889,​12894-12907,​12911-12918,​12920-12921,​12925-12927,​12932,​12934,​12936-12938,​12940,​12946-12948,​12953-12954,​12959-12961,​12971-12973,​12975-12978,​12981-12983,​12986-12987,​13000-13005,​13008,​13014,​13016,​13024-13027,​13030,​13033-13034,​13036,​13038-13040,​13051,​13054-13060,​13064-13066,​13078,​13080,​13087,​13093-13094,​13100-13104,​13109,​13116,​13118-13121,​13131,​13133,​13136-13143,​13154,​13157-13160,​13162-13165,​13167-13169,​13173,​13180-13181,​13183,​13186,​13198,​13200-13201,​13203-13205,​13209-13210,​13212,​13214,​13217-13219,​13222-13228,​13230-13239,​13241-13245,​13247-13257,​13260-13261,​13266-13271,​13288,​13300,​13307-13309,​13311,​13313-13315,​13318,​13392-13393,​13395,​13402,​13406,​13411,​13413-13415,​13419-13420,​13425,​13427-13430,​13433-13434,​13438-13442,​13445-13447,​13450,​13458,​13471,​13473-13474,​13484,​13491,​13494,​13498-13504,​13507-13514,​13516-13517,​13525-13526,​13529,​13534-13535,​13539-13540,​13549-13550,​13552,​13560,​13566-13567,​13570-13573,​13579-13582,​13584-13586,​13592-13593,​13597,​13614,​13616,​13621,​13626-13629,​13635,​13644-13646,​13648,​13650-13655,​13657-13662,​13666,​13669-13671,​13675-13684,​13690-13693,​13695,​13697-13705,​13707-13709,​13711,​13715,​13721,​13724,​13746,​13760-13761,​13764-13766,​13779,​13784-13786,​13796,​13800-13802,​13807,​13813,​13826,​13838,​13863,​13869,​13889-13891,​13895,​13898-13901,​13916-13917,​13921-13922,​13925,​13932-13935,​13938-13939,​13941-13942,​13958,​13963-13964,​13975,​13978,​13983-13987,​13992-13993,​13998,​14000-14001,​14007-14008,​14011,​14014-14017,​14024-14026,​14032,​14034,​14036-14037,​14056-14057,​14071,​14082-14083,​14095-14096,​14098-14100,​14102-14103,​14107,​14109-14110,​14118-14122,​14124-14127,​14130-14132,​14135-14136,​14140,​14142,​14144,​14150,​14152,​14155-14160,​14162-14164,​14167-14169,​14174-14175,​14177-14179,​14181,​14189,​14191,​14196,​14198,​14200,​14202-14207,​14209,​14221-14224,​14226-14230,​14234-14236,​14244-14247,​14250,​14255-14258,​14260,​14267-14268,​14270-14273,​14282,​14284-14300,​14307,​14314-14316,​14319,​14322,​14332,​14340-14350,​14352-14358,​14367-14369,​14371-14372,​14376,​14378,​14381-14382,​14384,​14388,​14390-14391,​14393-14394,​14396,​14400,​14405,​14407-14408,​14412,​14418,​14422-14423,​14425,​14432-14439,​14443,​14457-14458,​14463-14465,​14468-14469,​14475-14476,​14478-14479,​14481-14483,​14486,​14493-14494,​14504,​14506-14509,​14516-14517,​14519,​14522-14523,​14527-14529,​14531-14533,​14548,​14553,​14561,​14582,​14597,​14623,​14630,​14647,​14651-14652,​14654,​14656,​14659-14660,​14662-14663,​14672,​14685,​14687,​14692,​14697,​14706,​14708-14709,​14718,​14721-14722,​14726,​14732,​14734,​14737-14738,​14740,​14748-14750,​14769-14770,​14772-14775,​14779-14781,​14786,​14789-14791,​14793,​14805,​14809-14810,​14817,​14819-14820,​14826-14832,​14839-14843,​14845-14847,​14851-14854,​14857,​14860-14865,​14871,​14877,​14882,​14886,​14889-14890,​14899,​14901,​14904,​14911-14912,​14916,​14918,​14936-14938,​14940,​14943-14951,​14955,​14971,​14978-14979,​14982,​14984,​14987,​14992,​14995,​15002-15010,​15013,​15015-15016,​15023-15024,​15026,​15029,​15040,​15042,​15044,​15046-15054,​15058,​15067-15077,​15079-15080,​15083-15088,​15091-15096,​15098-15099,​15102-15107,​15110-15114,​15119-15126,​15129,​15135,​15139,​15156-15158,​15160,​15162-15169,​15172-15173,​15178-15181,​15184-15185,​15187,​15191-15192,​15194,​15198,​15201,​15203,​15205-15211,​15213-15214,​15221-15228,​15230,​15233-15236,​15240-15241,​15246-15248,​15264-15266,​15271,​15276,​15287-15288,​15300-15302,​15312,​15325-15327,​15329,​15335-15336,​15339,​15357-15358,​15361,​15367-15368,​15370-15372,​15376,​15383,​15388,​15390,​15393,​15395-15398,​15400,​15402,​15408-15409,​15419,​15427,​15447-15448,​15452,​15461,​15464,​15478,​15480-15481,​15483,​15486,​15498-15499,​15502,​15505,​15513,​15517-15518,​15532,​15534,​15545,​15548,​15551,​15556,​15560,​15570,​15591,​15594,​15596,​15598,​15607,​15610-15611,​15621-15623,​15626,​15637-15638,​15645,​15665,​15667,​15672-15674
      /trunk/sources/HeuristicLab.Problems.TestFunctions.MultiObjective/HeuristicLab.Clients.Hive.Administrator14175
  • stable/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.cs

    r15584 r17059  
    11#region License Information
    22/* HeuristicLab
    3  * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3 * Copyright (C) 2002-2017 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
     57    private TreeNode ungroupedGroupNode;
     58
     59    private Resource selectedResource = null;
     60    public Resource SelectedResource {
     61      get { return selectedResource; }
     62      set { if (selectedResource != value) ChangeSelectedResource(value); }
     63    }
     64
     65    private readonly object locker = new object();
     66
    4167    public new IItemList<Resource> Content {
    4268      get { return (IItemList<Resource>)base.Content; }
     
    4470    }
    4571
    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 
    5572    public ResourcesView() {
    5673      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     }
     74
     75      treeView.ImageList.Images.Add(VSImageLibrary.MonitorLarge);
     76      treeView.ImageList.Images.Add(VSImageLibrary.NetworkCenterLarge);
     77
     78      HiveAdminClient.Instance.Refreshing += HiveAdminClient_Instance_Refreshing;
     79      HiveAdminClient.Instance.Refreshed += HiveAdminClient_Instance_Refreshed;
     80      AccessClient.Instance.Refreshing += AccessClient_Instance_Refreshing;
     81      AccessClient.Instance.Refreshed += AccessClient_Instance_Refreshed;
     82    }
     83
     84    #region Overrides
     85    protected override void OnClosing(FormClosingEventArgs e) {
     86      AccessClient.Instance.Refreshed -= AccessClient_Instance_Refreshed;
     87      AccessClient.Instance.Refreshing -= AccessClient_Instance_Refreshing;
     88      HiveAdminClient.Instance.Refreshed -= HiveAdminClient_Instance_Refreshed;
     89      HiveAdminClient.Instance.Refreshing -= HiveAdminClient_Instance_Refreshing;
     90      base.OnClosing(e);
     91    }
     92
    11893    protected override void RegisterContentEvents() {
    11994      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
     95      Content.ItemsAdded += Content_ItemsAdded;
     96      Content.ItemsRemoved += Content_ItemsRemoved;
     97    }
     98
     99    protected override void DeregisterContentEvents() {
     100      Content.ItemsRemoved -= Content_ItemsRemoved;
     101      Content.ItemsAdded -= Content_ItemsAdded;
     102      base.DeregisterContentEvents();
     103    }
    124104
    125105    protected override void OnContentChanged() {
    126106      base.OnContentChanged();
    127107      if (Content == null) {
    128         slaveView.Content = null;
     108        treeView.Nodes.Clear();
     109        viewHost.Content = null;
    129110        scheduleView.Content = null;
    130         permissionView.Content = null;
    131         permissionView.FetchSelectedUsers = null;
    132         treeSlaveGroup.Nodes.Clear();
    133111      } 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       }
     112        BuildResourceTree(Content);
     113      }
     114      SetEnabledStateOfControls();
    192115    }
    193116
    194117    protected override void SetEnabledStateOfControls() {
    195118      base.SetEnabledStateOfControls();
    196       if (Content == null) {
    197         btnAddGroup.Enabled = false;
     119
     120      bool locked = Content == null || Locked || ReadOnly;
     121      bool addLocked = locked
     122                    || !IsAdmin()
     123                    || (selectedResource is Slave && selectedResource.ParentResourceId != null)
     124                    || (selectedResource != null && selectedResource.Id == Guid.Empty);
     125
     126      HashSet<Guid> descendantResources = null;
     127      bool selectedRDeleteLocked = selectedResource == null
     128                              || (selectedResource.Id != Guid.Empty && (!HiveAdminClient.Instance.ResourceDescendants.TryGetValue(selectedResource.Id, out descendantResources) || descendantResources.Any()));
     129
     130      var nodes = GetCheckedNodes(treeView.Nodes).ToList();
     131      var checkedResources = nodes.Select(x => x.Tag).OfType<Resource>().ToList();
     132      bool checkedRDeleteLocked = false;
     133      for (int i = 0; !checkedRDeleteLocked && i < checkedResources.Count; i++) {
     134        if (checkedResources[i].Id != Guid.Empty &&
     135            (!HiveAdminClient.Instance.ResourceDescendants.TryGetValue(checkedResources[i].Id, out descendantResources) ||
     136             descendantResources.Any()))
     137          checkedRDeleteLocked = true;
     138      }
     139
     140      bool deleteLocked = locked
     141                          || !IsAdmin()
     142                          || !Content.Any()
     143                          || checkedResources.Any() && checkedRDeleteLocked
     144                          || !checkedResources.Any() && selectedRDeleteLocked;
     145
     146      bool saveLocked = locked
     147                       || !IsAdmin()
     148                       || !Content.Any()
     149                       || selectedResource == null;
     150
     151      btnAddGroup.Enabled = !addLocked;
     152      btnRemoveGroup.Enabled = !deleteLocked;
     153      btnSave.Enabled = !saveLocked;
     154      viewHost.Locked = locked || !IsAdmin();
     155      scheduleView.Locked = locked || !IsAdmin();
     156    }
     157    #endregion
     158
     159    #region Event Handlers
     160    private void Content_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<Resource>> e) {
     161      if (InvokeRequired) Invoke((Action<object, CollectionItemsChangedEventArgs<IndexedItem<Resource>>>)Content_ItemsAdded, sender, e);
     162      else {
     163        OnContentChanged();
     164      }
     165    }
     166
     167    private void Content_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<Resource>> e) {
     168      if (InvokeRequired) Invoke((Action<object, CollectionItemsChangedEventArgs<IndexedItem<Resource>>>)Content_ItemsRemoved, sender, e);
     169      else {
     170        OnContentChanged();
     171      }
     172    }
     173
     174    private void SlaveViewContent_PropertyChanged(object sender, PropertyChangedEventArgs e) {
     175      if (InvokeRequired) Invoke((Action<object, PropertyChangedEventArgs>)SlaveViewContent_PropertyChanged, sender, e);
     176      else {
     177        OnContentChanged();
     178        if (e.PropertyName == "HbInterval") {
     179          UpdateChildHbIntervall((Resource)viewHost.Content);
     180        }
     181      }
     182    }
     183
     184    private void HiveAdminClient_Instance_Refreshing(object sender, EventArgs e) {
     185      if (InvokeRequired) Invoke((Action<object, EventArgs>)HiveAdminClient_Instance_Refreshing, sender, e);
     186      else {
     187        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
     188        mainForm.AddOperationProgressToView(this, "Refreshing ...");
     189        SetEnabledStateOfControls();
     190      }
     191    }
     192
     193    private void HiveAdminClient_Instance_Refreshed(object sender, EventArgs e) {
     194      if (InvokeRequired) Invoke((Action<object, EventArgs>)HiveAdminClient_Instance_Refreshed, sender, e);
     195      else {
     196        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
     197        mainForm.RemoveOperationProgressFromView(this);
     198        SetEnabledStateOfControls();
     199      }
     200    }
     201
     202    private void AccessClient_Instance_Refreshing(object sender, EventArgs e) {
     203      if (InvokeRequired) Invoke((Action<object, EventArgs>)AccessClient_Instance_Refreshing, sender, e);
     204      else {
     205        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
     206        mainForm.AddOperationProgressToView(this, "Refreshing ...");
     207        SetEnabledStateOfControls();
     208      }
     209    }
     210
     211    private void AccessClient_Instance_Refreshed(object sender, EventArgs e) {
     212      if (InvokeRequired) Invoke((Action<object, EventArgs>)AccessClient_Instance_Refreshed, sender, e);
     213      else {
     214        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
     215        mainForm.RemoveOperationProgressFromView(this);
     216        SetEnabledStateOfControls();
     217      }
     218    }
     219
     220    private async void ResourcesView_Load(object sender, EventArgs e) {
     221      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
     222        action: () => UpdateResources());
     223    }
     224
     225    private async void btnRefresh_Click(object sender, EventArgs e) {
     226      lock (locker) {
     227        if (!btnRefresh.Enabled) return;
     228        btnRefresh.Enabled = false;
     229      }
     230
     231      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
     232        action: () => UpdateResources(),
     233        finallyCallback: () => btnRefresh.Enabled = true);
     234    }
     235
     236    private void btnAddGroup_Click(object sender, EventArgs e) {
     237      var parentResourceId = selectedResource is SlaveGroup ? selectedResource.Id : (Guid?)null;
     238
     239      var group = new SlaveGroup {
     240        Name = "New Group",
     241        OwnerUserId = UserInformation.Instance.User.Id,
     242        ParentResourceId = parentResourceId
     243      };
     244
     245      SelectedResource = group;
     246      Content.Add(group);
     247    }
     248
     249    private async void btnRemoveGroup_Click(object sender, EventArgs e) {     
     250      var nodes = GetCheckedNodes(treeView.Nodes).ToList();
     251      var checkedResources = nodes.Select(x => x.Tag).OfType<Resource>().ToList();
     252      if (selectedResource == null && !checkedResources.Any()) return;
     253
     254      lock (locker) {
     255        if (!btnRemoveGroup.Enabled) return;
    198256        btnRemoveGroup.Enabled = false;
     257      }
     258
     259      if (checkedResources.Count > 0) {
     260        var result = MessageBox.Show(
     261          "Do you really want to delete all " + checkedResources.Count + " checked resources?",
     262          "HeuristicLab Hive Administrator",
     263          MessageBoxButtons.YesNo,
     264          MessageBoxIcon.Question);
     265        if (result == DialogResult.Yes) {
     266          await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
     267            action: () => {
     268              RemoveResource(checkedResources);
     269            });
     270        }
     271      } else {
     272        var res = checkedResources.Any() ? checkedResources.First() : selectedResource;
     273        var result = MessageBox.Show(
     274          "Do you really want to delete the selected resource " + res.Name + "?",
     275          "HeuristicLab Hive Administrator",
     276          MessageBoxButtons.YesNo,
     277          MessageBoxIcon.Question);
     278        if (result == DialogResult.Yes) {
     279          await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
     280            action: () => {
     281              RemoveResource(res);
     282            });
     283        }
     284      }
     285
     286      OnContentChanged();
     287      SetEnabledStateOfControls();
     288    }
     289
     290    private async void btnSave_Click(object sender, EventArgs e) {
     291      lock (locker) {
     292        if (!btnSave.Enabled) return;
    199293        btnSave.Enabled = false;
    200         btnPermissionsSave.Enabled = false;
    201         permissionView.Enabled = false;
    202         scheduleView.SetEnabledStateOfSchedule(false);
    203         btnPermissionsSave.Enabled = false;
    204         permissionView.Enabled = false;
     294      }
     295
     296      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
     297        action: () => {
     298          var resourcesToSave = Content.Where(x => x.Id == Guid.Empty || x.Modified);
     299          foreach (var resource in resourcesToSave)
     300            resource.Store();
     301          UpdateResources();
     302        });
     303
     304      OnContentChanged();
     305      SetEnabledStateOfControls();
     306    }
     307
     308    private void treeSlaveGroup_MouseDown(object sender, MouseEventArgs e) {
     309      var node = treeView.GetNodeAt(e.Location);
     310      if (node == null || node == ungroupedGroupNode) return;
     311      var r = (Resource)node.Tag;
     312      if (!HiveAdminClient.Instance.DisabledParentResources.Contains(r)) ChangeSelectedResourceNode(node);
     313    }
     314
     315    private void treeSlaveGroup_BeforeSelect(object sender, TreeViewCancelEventArgs e) {
     316      e.Cancel = true;
     317    }
     318
     319    private void treeSlaveGroup_BeforeCheck(object sender, TreeViewCancelEventArgs e) {
     320      if (!IsAdmin() || e.Node == ungroupedGroupNode) {
     321        e.Cancel = true;
    205322      } 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);
     323        var r = (Resource)e.Node.Tag;
     324        if (HiveAdminClient.Instance.DisabledParentResources.Contains(r)) {
     325          e.Cancel = true;
     326        }
     327      }
     328    }
     329
     330    private void treeSlaveGroup_AfterCheck(object sender, TreeViewEventArgs e) {
     331      SetEnabledStateOfControls();
     332    }
     333
     334    private void treeSlaveGroup_DragDrop(object sender, DragEventArgs e) {
     335      if (e.Effect == DragDropEffects.None) return;
     336
     337      var targetNode = treeView.GetNodeAt(treeView.PointToClient(new Point(e.X, e.Y)));
     338      var targetResource = (targetNode != null) ? (Resource)targetNode.Tag : null;
     339      var resources = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat) as IEnumerable<Resource>;
     340
     341      foreach (var r in resources) {
     342        r.ParentResourceId = targetResource != null ? targetResource.Id : (Guid?)null;
     343      }
     344
     345      // TODO
     346      //HiveAdminClient.Instance.UpdateResourceGenealogy(Content);
     347      OnContentChanged();
     348    }
     349
     350    private void treeSlaveGroup_ItemDrag(object sender, ItemDragEventArgs e) {
     351      if (!IsAdmin()) return;
     352
     353      var nodes = GetCheckedNodes(treeView.Nodes).ToList();
     354      TreeNode sourceNode = (TreeNode)e.Item;
     355      if (!sourceNode.Checked) nodes.Add(sourceNode);
     356      nodes.Remove(ungroupedGroupNode);
     357      ungroupedGroupNode.Checked = false;
     358      var resources = nodes.Select(x => x.Tag).OfType<Resource>().ToList();
     359
     360      if (resources.Count > 0) {
     361        DataObject data = new DataObject();
     362        data.SetData(HeuristicLab.Common.Constants.DragDropDataFormat, resources);
     363        var action = DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link | DragDropEffects.Move);
     364        if (action.HasFlag(DragDropEffects.Move)) {
     365          foreach (var node in nodes) node.Remove();
     366          StyleTreeNode(ungroupedGroupNode, (Resource)ungroupedGroupNode.Tag, resources);
     367        }
     368      }
     369    }
     370
     371    private IEnumerable<TreeNode> GetCheckedNodes(TreeNodeCollection nodes) {
     372      if (nodes != null) {
     373        foreach (var node in nodes.OfType<TreeNode>()) {
     374          if (node.Checked && node != ungroupedGroupNode) yield return node;
     375          foreach (var child in GetCheckedNodes(node.Nodes))
     376            yield return child;
     377        }
     378      }
     379    }
     380
     381    private void treeSlaveGroup_DragEnterOver(object sender, DragEventArgs e) {
     382      e.Effect = DragDropEffects.Move;
     383      var resources = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat) as IEnumerable<Resource>;
     384      var targetNode = treeView.GetNodeAt(treeView.PointToClient(new Point(e.X, e.Y)));
     385      var targetResource = (targetNode != null ? targetNode.Tag : null) as Resource;
     386
     387      if (!IsAdmin()
     388        || resources == null
     389        || !resources.Any()
     390        || resources.Any(x => !HiveAdminClient.Instance.CheckParentChange(x, targetResource))
     391        || (targetNode != null && (targetNode == ungroupedGroupNode || targetNode.Parent == ungroupedGroupNode))) {
     392        e.Effect = DragDropEffects.None;
     393      }
     394    }
     395
     396    private void TabSlaveGroup_TabIndexChanged(object sender, EventArgs e) {
     397      throw new NotImplementedException();
     398    }
     399
     400    private async void TabSlaveGroup_Selected(object sender, System.Windows.Forms.TabControlEventArgs e) {
     401      if (e.TabPage == tabSchedule) {
     402        await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
     403          action: () => UpdateSchedule(),
     404          finallyCallback: () => scheduleView.Content = HiveAdminClient.Instance.Downtimes);
     405      }
     406      SetEnabledStateOfControls();
     407    }
     408    #endregion
     409
     410    #region Helpers
     411    private void BuildResourceTree(IEnumerable<Resource> resources) {
     412      treeView.Nodes.Clear();
     413      if (!resources.Any()) return;
     414
     415      var disabledParentResources = HiveAdminClient.Instance.DisabledParentResources;
     416      var mainResources = new HashSet<Resource>(resources.OfType<SlaveGroup>()
     417        .Where(x => x.ParentResourceId == null));
     418      //var parentedMainResources = new HashSet<Resource>(resources.OfType<SlaveGroup>()
     419      //  .Where(x => x.ParentResourceId.HasValue && !resources.Select(y => y.Id).Contains(x.ParentResourceId.Value)));
     420      //mainResources.UnionWith(parentedMainResources);
     421      var mainDisabledParentResources = new HashSet<Resource>(disabledParentResources.Where(x => x.ParentResourceId == null || x.ParentResourceId == Guid.Empty));
     422      mainResources.UnionWith(mainDisabledParentResources);
     423      var subResources = new HashSet<Resource>(resources.Union(disabledParentResources).Except(mainResources).OrderByDescending(x => x.Name));
     424
     425      var stack = new Stack<Resource>(mainResources.OrderByDescending(x => x.Name));
     426      if (selectedResource != null) SelectedResource = resources.Where(x => x.Id == selectedResource.Id).FirstOrDefault();
     427      bool nodeSelected = false;
     428
     429      TreeNode currentNode = null;
     430      Resource currentResource = null;
     431
     432      while (stack.Any()) {
     433        var newResource = stack.Pop();
     434        var newNode = new TreeNode(newResource.Name) { Tag = newResource };
     435        StyleTreeNode(newNode, newResource, resources);
     436
     437        if (selectedResource == null && !disabledParentResources.Contains(newResource)) {
     438          SelectedResource = newResource;
     439        }
     440        if (!nodeSelected && selectedResource != null && newResource.Id == selectedResource.Id) {
     441          newNode.BackColor = selectedBackColor;
     442          newNode.ForeColor = selectedForeColor;
     443          newNode.Text += SELECTED_TAG;
     444          nodeSelected = true;
     445        }
     446
     447        if (disabledParentResources.Contains(newResource)) {
     448          newNode.Checked = false;
     449          newNode.ForeColor = grayTextColor;
     450        }
     451
     452        // search for parent node of newNode and save in currentNode
     453        // necessary since newNodes (stack top items) might be siblings
     454        // or grand..grandparents of previous node (currentNode)
     455        while (currentNode != null && newResource.ParentResourceId != currentResource.Id) {
     456          currentNode = currentNode.Parent;
     457          currentResource = currentNode == null ? null : (Resource)currentNode.Tag;
     458        }
     459
     460        if (currentNode == null) {
     461          treeView.Nodes.Add(newNode);
    234462        } 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);
     463          currentNode.Nodes.Add(newNode);
     464        }
     465
     466        if (newResource is SlaveGroup) {
     467          var childResources = subResources.Where(x => x.ParentResourceId == newResource.Id);
     468          if (childResources.Any()) {
     469            foreach (var resource in childResources.OrderByDescending(x => x.Name)) {
     470              subResources.Remove(resource);
     471              stack.Push(resource);
     472            }
     473            currentNode = newNode;
     474            currentResource = newResource;
     475          }
     476        }
     477        newNode.SelectedImageIndex = newNode.ImageIndex;
     478      }
     479
     480      // collapse slave-only nodes
     481      foreach (TreeNode n in treeView.Nodes) {
     482        CollapseSlaveOnlyNodes(n);
     483      }
     484
     485      ungroupedGroupNode = new TreeNode(UNGROUPED_GROUP_NAME) {
     486        ForeColor = SystemColors.GrayText,
     487        ImageIndex = slaveGroupImageIndex,
     488        Tag = new SlaveGroup() {
     489          Name = UNGROUPED_GROUP_NAME,
     490          Description = UNGROUPED_GROUP_DESCRIPTION
     491        }
     492      };
     493
     494      foreach (var slave in subResources.OfType<Slave>().OrderBy(x => x.Name)) {
     495        var slaveNode = new TreeNode(slave.Name) { Tag = slave };
     496        StyleTreeNode(slaveNode, slave, resources);
     497        ungroupedGroupNode.Nodes.Add(slaveNode);
     498        if (selectedResource == null) {
     499          SelectedResource = slave;
     500        }
     501
     502        if (slave.Id == selectedResource.Id && !nodeSelected) {
     503          slaveNode.BackColor = selectedBackColor;
     504          slaveNode.ForeColor = selectedForeColor;
     505          slaveNode.Text += SELECTED_TAG;
     506          nodeSelected = true;
     507        }
     508      }
     509
     510      if (ungroupedGroupNode.Nodes.Count > 0) {
     511        ungroupedGroupNode.Text += " [" + ungroupedGroupNode.Nodes.Count.ToString() + "]";
     512        ungroupedGroupNode.Expand();
     513        treeView.Nodes.Add(ungroupedGroupNode);
     514      }
     515    }
     516
     517    private void CollapseSlaveOnlyNodes(TreeNode tn) {
     518      Resource r = (Resource)tn.Tag;
     519      var descendants = GetResourceDescendants();
     520      if (descendants.ContainsKey(r.Id)) {
     521        if (descendants[r.Id].OfType<SlaveGroup>().Any()) {
     522          tn.Expand();
     523          foreach (TreeNode n in tn.Nodes) CollapseSlaveOnlyNodes(n);
     524        } else {
     525          tn.Collapse();
     526        }
     527      }
     528    }
     529
     530    private void ExpandResourceNodesOfInterest(TreeNodeCollection nodes) {
     531      foreach (TreeNode n in nodes) {
     532        Resource r = (Resource)n.Tag;
     533        if (n.Nodes.Count > 0) {
     534          if (HiveAdminClient.Instance.GetAvailableResourceDescendants(r.Id).OfType<SlaveGroup>().Any()) {
     535            n.Expand();
     536            ExpandResourceNodesOfInterest(n.Nodes);
     537          } else {
     538            n.Collapse();
     539          }
     540        } else {
     541          n.Collapse();
     542        }
    265543      }
    266544    }
     
    275553    }
    276554
    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             }
     555    private void UpdateResources() {
     556      try {
     557        HiveAdminClient.Instance.Refresh();
     558        Content = HiveAdminClient.Instance.Resources;
     559      } catch (AnonymousUserException) {
     560        ShowHiveInformationDialog();
     561      }
     562    }
     563
     564    private void RemoveResource(Resource resource) {
     565      if (resource == null) return;
     566
     567      try {
     568        if (resource.Id != Guid.Empty) {
     569          SelectedResource = HiveAdminClient.Instance.GetAvailableResourceAncestors(resource.Id).LastOrDefault();
     570
     571          // deal with all new, but not yet saved resources
     572          var newResources = Content.Where(x => x.ParentResourceId == resource.Id).ToList();
     573          if (newResources.Any(x => x.Id != Guid.Empty)) return;
     574          foreach (var nr in newResources) Content.Remove(nr);
     575
     576          HiveAdminClient.Delete(resource);         
     577          UpdateResources();
     578        } else {
     579          SelectedResource = Content.FirstOrDefault(x => x.Id == resource.ParentResourceId);
     580          Content.Remove(resource);
     581        }
     582      } catch (AnonymousUserException) {
     583        ShowHiveInformationDialog();
     584      }
     585    }
     586
     587    private void RemoveResource(IEnumerable<Resource> resources) {
     588      if (resources == null || !resources.Any()) return;
     589
     590      var ids = resources.Select(x => x.Id).ToList();     
     591      try {
     592        bool update = false;
     593        foreach (var r in resources) {         
     594          if (r.Id != Guid.Empty)  {
     595            if(r.Id == SelectedResource.Id)
     596              SelectedResource = HiveAdminClient.Instance.GetAvailableResourceAncestors(r.Id).LastOrDefault();
     597
     598            // deal with all new, but not yet saved resources
     599            var newResources = Content.Where(x => x.ParentResourceId == r.Id).ToList();
     600            if (newResources.Any(x => x.Id != Guid.Empty)) return;
     601            foreach (var nr in newResources) Content.Remove(nr);
     602
     603            HiveAdminClient.Delete(r);
     604            update = true;
     605          } else {
     606            if (r.Id == SelectedResource.Id)
     607              SelectedResource = Content.FirstOrDefault(x => x.Id == r.ParentResourceId);
     608            Content.Remove(r);
    309609          }
    310610        }
    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));
     611        if (update) UpdateResources();
     612      } catch (AnonymousUserException) {
     613        ShowHiveInformationDialog();
     614      }
     615    }
     616
     617    private void UpdateSchedule() {
     618      try {
     619        HiveAdminClient.Instance.RefreshCalendar();
     620      } catch (AnonymousUserException) {
     621        ShowHiveInformationDialog();
     622      }
     623    }
     624
     625    private bool IsAdmin() {
     626      return HiveRoles.CheckAdminUserPermissions();
     627    }
     628
     629    private void StyleTreeNode(TreeNode n, Resource r, IEnumerable<Resource> resources) {
     630      n.Text = r.Name;
     631      n.BackColor = Color.Transparent;
     632      n.ForeColor = Color.Black;
     633
     634      if (HiveAdminClient.Instance.DisabledParentResources.Select(x => x.Id).Contains(r.Id)) {
     635        n.ForeColor = grayTextColor;
     636      } else if (r.Id == Guid.Empty && n != ungroupedGroupNode /*!r.Name.StartsWith(UNGROUPED_GROUP_NAME)*/) {
     637        // not stored (i.e. new)
     638        n.Text += NOT_STORED_TAG;
     639      } else if (r.Modified && n != ungroupedGroupNode /*!r.Name.StartsWith(UNGROUPED_GROUP_NAME)*/) {
     640        // changed
     641        n.Text += CHANGES_NOT_STORED_TAG;
     642      }
     643
     644      // slave count
     645      int childSlavesCount = 0;
     646      if (r.Id != Guid.Empty && r is SlaveGroup) {
     647        var descendants = GetResourceDescendants();
     648        if (descendants.ContainsKey(r.Id)) {
     649          childSlavesCount = resources
     650            .OfType<Slave>()
     651            .Where(x => descendants[r.Id].Select(y => y.Id)
     652              .Contains(x.Id))
     653            .Count();
     654        }
     655      } else if (n == ungroupedGroupNode /*|| r.Name.StartsWith(UNGROUPED_GROUP_NAME)*/) {
     656        childSlavesCount = resources
     657          .OfType<Slave>()
     658          .Where(x => x.ParentResourceId == null
     659            || (x.ParentResourceId.HasValue && x.ParentResourceId.Value == Guid.Empty))
     660          .Count();
     661      }
     662      if (childSlavesCount > 0)
     663        n.Text += " [" + childSlavesCount.ToString() + "]";
     664
     665      // slave image index, state, utilization
     666      if (r is Slave) {
     667        n.ImageIndex = slaveImageIndex;
     668        var s = r as Slave;
     669        if (s.SlaveState == SlaveState.Calculating) {
     670          n.ForeColor = calculatingColor;
     671          n.Text += " [" + s.CpuUtilization.ToString("N2") + "%]";
     672        } else if (s.SlaveState == SlaveState.Offline) {
     673          n.ForeColor = offlineColor;
     674          if (s.LastHeartbeat.HasValue)
     675            n.Text += " [" + (s.LastHeartbeat != null ? s.LastHeartbeat.Value.ToString("g") : null) + "]";
     676        }
    421677      } 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;
     678        n.ImageIndex = slaveGroupImageIndex;
     679      }
     680
     681      // ungrouped
     682      if (n == ungroupedGroupNode /*r.Name.StartsWith(UNGROUPED_GROUP_NAME)*/) {
     683        n.ForeColor = SystemColors.GrayText;
     684      }
     685    }
     686
     687    private void ResetTreeNodes(TreeNodeCollection nodes, IEnumerable<Resource> resources) {
     688      foreach (TreeNode n in nodes) {
     689        StyleTreeNode(n, (Resource)n.Tag, resources);
     690        if (n.Nodes.Count > 0) {
     691          ResetTreeNodes(n.Nodes, resources);
     692        }
     693      }
     694    }
     695
     696    private async void ChangeSelectedResource(Resource resource) {
     697      selectedResource = resource;
     698      viewHost.Content = selectedResource;
     699
     700      HiveAdminClient.Instance.DowntimeForResourceId = selectedResource != null ? selectedResource.Id : Guid.Empty;
     701      if (tabSlaveGroup.SelectedTab == tabSchedule) {
     702        await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
     703          action: () => UpdateSchedule(),
     704          finallyCallback: () => scheduleView.Content = HiveAdminClient.Instance.Downtimes);
     705      }
     706
     707      SetEnabledStateOfControls();
     708    }
     709
     710    private void ChangeSelectedResourceNode(TreeNode resourceNode) {
     711      if (resourceNode == null) return;
     712      SelectedResource = (Resource)resourceNode.Tag;
     713      ResetTreeNodes(treeView.Nodes, Content);
     714      resourceNode.BackColor = selectedBackColor;
     715      resourceNode.ForeColor = selectedForeColor;
     716      resourceNode.Text += SELECTED_TAG;
     717    }
     718
     719    private void ShowHiveInformationDialog() {
     720      if (InvokeRequired) Invoke((Action)ShowHiveInformationDialog);
     721      else {
     722        using (HiveInformationDialog dialog = new HiveInformationDialog()) {
     723          dialog.ShowDialog(this);
     724        }
     725      }
     726    }
     727
     728    private void ResetView() {
     729      if (InvokeRequired) Invoke((Action)ResetView);
     730      else {
     731        treeView.Nodes.Clear();
     732
     733        if (viewHost.Content != null && viewHost.Content is SlaveGroup) {
     734          ((SlaveGroup)viewHost.Content).PropertyChanged -= SlaveViewContent_PropertyChanged;
     735        }
     736
     737        viewHost.Content = null;
    428738        if (scheduleView.Content != null) {
    429739          scheduleView.Content.Clear();
    430740        }
     741
    431742        HiveAdminClient.Instance.ResetDowntime();
    432743      }
    433744    }
    434745
    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     }
     746
     747    private Dictionary<Guid, HashSet<Resource>> GetResourceDescendants() {
     748      var resourceDescendants = new Dictionary<Guid, HashSet<Resource>>();
     749      //var resources = Content.Where(x => x.Id != Guid.Empty).Union(HiveAdminClient.Instance.DisabledParentResources).ToList();     
     750      var resources = Content.Union(HiveAdminClient.Instance.DisabledParentResources).ToList();
     751
     752      foreach (var r in resources) {
     753        if(!resourceDescendants.ContainsKey(r.Id))
     754          resourceDescendants.Add(r.Id, new HashSet<Resource>());
     755      }
     756      foreach (var r in resources) {
     757        var parentResourceId = r.ParentResourceId;
     758        while (parentResourceId != null) {
     759          var parent = resources.SingleOrDefault(x => x.Id == parentResourceId);
     760          if (parent != null) {
     761            resourceDescendants[parent.Id].Add(r);
     762            parentResourceId = parent.ParentResourceId;
     763          } else {
     764            parentResourceId = null;
     765          }
     766        }
     767      }
     768      return resourceDescendants;
     769    }
     770
     771    #endregion
    532772  }
    533773}
Note: See TracChangeset for help on using the changeset viewer.