source: branches/2931_OR-Tools_LP_MIP/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.cs @ 16139

Last change on this file since 16139 was 16139, checked in by ddorfmei, 14 months ago

#2931: Merged [16046-16138/trunk] into branch

File size: 26.4 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.ComponentModel;
25using System.Drawing;
26using System.Linq;
27using System.Windows.Forms;
28using HeuristicLab.Clients.Access;
29using HeuristicLab.Clients.Hive.Views;
30using HeuristicLab.Collections;
31using HeuristicLab.Common.Resources;
32using HeuristicLab.Core;
33using HeuristicLab.Core.Views;
34using HeuristicLab.MainForm;
35
36namespace HeuristicLab.Clients.Hive.Administrator.Views {
37  [View("Resources View")]
38  [Content(typeof(IItemList<Resource>), false)]
39  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
67    public new IItemList<Resource> Content {
68      get { return (IItemList<Resource>)base.Content; }
69      set { base.Content = value; }
70    }
71
72    public ResourcesView() {
73      InitializeComponent();
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
93    protected override void RegisterContentEvents() {
94      base.RegisterContentEvents();
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    }
104
105    protected override void OnContentChanged() {
106      base.OnContentChanged();
107      if (Content == null) {
108        treeView.Nodes.Clear();
109        viewHost.Content = null;
110        scheduleView.Content = null;
111      } else {
112        BuildResourceTree(Content);
113      }
114      SetEnabledStateOfControls();
115    }
116
117    protected override void SetEnabledStateOfControls() {
118      base.SetEnabledStateOfControls();
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
128      bool deleteLocked = locked
129                       || !IsAdmin()
130                       || !Content.Any()
131                       || selectedResource == null
132                       || (selectedResource.Id != Guid.Empty && (!HiveAdminClient.Instance.ResourceDescendants.TryGetValue(selectedResource.Id, out descendantResources) || descendantResources.Any()));
133
134      bool saveLocked = locked
135                       || !IsAdmin()
136                       || !Content.Any()
137                       || selectedResource == null;
138
139      btnAddGroup.Enabled = !addLocked;
140      btnRemoveGroup.Enabled = !deleteLocked;
141      btnSave.Enabled = !saveLocked;
142      viewHost.Locked = locked || !IsAdmin();
143      scheduleView.Locked = locked || !IsAdmin();
144    }
145    #endregion
146
147    #region Event Handlers
148    private void Content_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<Resource>> e) {
149      if (InvokeRequired) Invoke((Action<object, CollectionItemsChangedEventArgs<IndexedItem<Resource>>>)Content_ItemsAdded, sender, e);
150      else {
151        OnContentChanged();
152      }
153    }
154
155    private void Content_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<Resource>> e) {
156      if (InvokeRequired) Invoke((Action<object, CollectionItemsChangedEventArgs<IndexedItem<Resource>>>)Content_ItemsRemoved, sender, e);
157      else {
158        OnContentChanged();
159      }
160    }
161
162    private void SlaveViewContent_PropertyChanged(object sender, PropertyChangedEventArgs e) {
163      if (InvokeRequired) Invoke((Action<object, PropertyChangedEventArgs>)SlaveViewContent_PropertyChanged, sender, e);
164      else {
165        OnContentChanged();
166        if (e.PropertyName == "HbInterval") {
167          UpdateChildHbIntervall((Resource)viewHost.Content);
168        }
169      }
170    }
171
172    private void HiveAdminClient_Instance_Refreshing(object sender, EventArgs e) {
173      if (InvokeRequired) Invoke((Action<object, EventArgs>)HiveAdminClient_Instance_Refreshing, sender, e);
174      else {
175        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
176        mainForm.AddOperationProgressToView(this, "Refreshing ...");
177        SetEnabledStateOfControls();
178      }
179    }
180
181    private void HiveAdminClient_Instance_Refreshed(object sender, EventArgs e) {
182      if (InvokeRequired) Invoke((Action<object, EventArgs>)HiveAdminClient_Instance_Refreshed, sender, e);
183      else {
184        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
185        mainForm.RemoveOperationProgressFromView(this);
186        SetEnabledStateOfControls();
187      }
188    }
189
190    private void AccessClient_Instance_Refreshing(object sender, EventArgs e) {
191      if (InvokeRequired) Invoke((Action<object, EventArgs>)AccessClient_Instance_Refreshing, sender, e);
192      else {
193        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
194        mainForm.AddOperationProgressToView(this, "Refreshing ...");
195        SetEnabledStateOfControls();
196      }
197    }
198
199    private void AccessClient_Instance_Refreshed(object sender, EventArgs e) {
200      if (InvokeRequired) Invoke((Action<object, EventArgs>)AccessClient_Instance_Refreshed, sender, e);
201      else {
202        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
203        mainForm.RemoveOperationProgressFromView(this);
204        SetEnabledStateOfControls();
205      }
206    }
207
208    private async void ResourcesView_Load(object sender, EventArgs e) {
209      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
210        action: () => UpdateResources());
211    }
212
213    private async void btnRefresh_Click(object sender, EventArgs e) {
214      lock (locker) {
215        if (!btnRefresh.Enabled) return;
216        btnRefresh.Enabled = false;
217      }
218
219      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
220        action: () => UpdateResources(),
221        finallyCallback: () => btnRefresh.Enabled = true);
222    }
223
224    private void btnAddGroup_Click(object sender, EventArgs e) {
225      var parentResourceId = selectedResource is SlaveGroup ? selectedResource.Id : (Guid?)null;
226
227      var group = new SlaveGroup {
228        Name = "New Group",
229        OwnerUserId = UserInformation.Instance.User.Id,
230        ParentResourceId = parentResourceId
231      };
232
233      SelectedResource = group;
234      Content.Add(group);
235    }
236
237    private async void btnRemoveGroup_Click(object sender, EventArgs e) {
238      if (selectedResource == null) return;
239
240      lock (locker) {
241        if (!btnRemoveGroup.Enabled) return;
242        btnRemoveGroup.Enabled = false;
243      }
244
245      var result = MessageBox.Show(
246        "Do you really want to delete " + selectedResource.Name + "?",
247        "HeuristicLab Hive Administrator",
248        MessageBoxButtons.YesNo,
249        MessageBoxIcon.Question);
250      if (result == DialogResult.Yes) {
251        await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
252          action: () => {
253            RemoveResource(selectedResource);
254          });
255
256        OnContentChanged();
257        SetEnabledStateOfControls();
258      }
259    }
260
261    private async void btnSave_Click(object sender, EventArgs e) {
262      lock (locker) {
263        if (!btnSave.Enabled) return;
264        btnSave.Enabled = false;
265      }
266
267      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
268        action: () => {
269          var resourcesToSave = Content.Where(x => x.Id == Guid.Empty || x.Modified);
270          foreach (var resource in resourcesToSave)
271            resource.Store();
272          UpdateResources();
273        });
274
275      OnContentChanged();
276      SetEnabledStateOfControls();
277    }
278
279    private void treeSlaveGroup_MouseDown(object sender, MouseEventArgs e) {
280      var node = treeView.GetNodeAt(e.Location);
281      if (node == null || node == ungroupedGroupNode) return;
282      var r = (Resource)node.Tag;
283      if (!HiveAdminClient.Instance.DisabledParentResources.Contains(r)) ChangeSelectedResourceNode(node);
284    }
285
286    private void treeSlaveGroup_BeforeSelect(object sender, TreeViewCancelEventArgs e) {
287      e.Cancel = true;
288    }
289
290    private void treeSlaveGroup_BeforeCheck(object sender, TreeViewCancelEventArgs e) {
291      if (e.Node == ungroupedGroupNode) {
292        e.Cancel = true;
293      } else {
294        var r = (Resource)e.Node.Tag;
295        if (HiveAdminClient.Instance.DisabledParentResources.Contains(r)) {
296          e.Cancel = true;
297        }
298      }
299    }
300
301    private void treeSlaveGroup_DragDrop(object sender, DragEventArgs e) {
302      if (e.Effect == DragDropEffects.None) return;
303
304      var targetNode = treeView.GetNodeAt(treeView.PointToClient(new Point(e.X, e.Y)));
305      var targetResource = (targetNode != null) ? (Resource)targetNode.Tag : null;
306      var resources = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat) as IEnumerable<Resource>;
307
308      foreach (var r in resources) {
309        r.ParentResourceId = targetResource != null ? targetResource.Id : (Guid?)null;
310      }
311
312      // TODO
313      //HiveAdminClient.Instance.UpdateResourceGenealogy(Content);
314      OnContentChanged();
315    }
316
317    private void treeSlaveGroup_ItemDrag(object sender, ItemDragEventArgs e) {
318      if (!IsAdmin()) return;
319
320      var nodes = GetCheckedNodes(treeView.Nodes).ToList();
321      TreeNode sourceNode = (TreeNode)e.Item;
322      if (!sourceNode.Checked) nodes.Add(sourceNode);
323      nodes.Remove(ungroupedGroupNode);
324      ungroupedGroupNode.Checked = false;
325      var resources = nodes.Select(x => x.Tag).OfType<Resource>().ToList();
326
327      if (resources.Count > 0) {
328        DataObject data = new DataObject();
329        data.SetData(HeuristicLab.Common.Constants.DragDropDataFormat, resources);
330        var action = DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link | DragDropEffects.Move);
331        if (action.HasFlag(DragDropEffects.Move)) {
332          foreach (var node in nodes) node.Remove();
333          StyleTreeNode(ungroupedGroupNode, (Resource)ungroupedGroupNode.Tag, resources);
334        }
335      }
336    }
337
338    private IEnumerable<TreeNode> GetCheckedNodes(TreeNodeCollection nodes) {
339      if (nodes != null) {
340        foreach (var node in nodes.OfType<TreeNode>()) {
341          if (node.Checked && node != ungroupedGroupNode) yield return node;
342          foreach (var child in GetCheckedNodes(node.Nodes))
343            yield return child;
344        }
345      }
346    }
347
348    private void treeSlaveGroup_DragEnterOver(object sender, DragEventArgs e) {
349      e.Effect = DragDropEffects.Move;
350      var resources = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat) as IEnumerable<Resource>;
351      var targetNode = treeView.GetNodeAt(treeView.PointToClient(new Point(e.X, e.Y)));
352      var targetResource = (targetNode != null ? targetNode.Tag : null) as Resource;
353
354      if (!IsAdmin()
355        || resources == null
356        || !resources.Any()
357        || resources.Any(x => !HiveAdminClient.Instance.CheckParentChange(x, targetResource))
358        || (targetNode != null && (targetNode == ungroupedGroupNode || targetNode.Parent == ungroupedGroupNode))) {
359        e.Effect = DragDropEffects.None;
360      }
361    }
362
363    private void TabSlaveGroup_TabIndexChanged(object sender, EventArgs e) {
364      throw new NotImplementedException();
365    }
366
367    private async void TabSlaveGroup_Selected(object sender, System.Windows.Forms.TabControlEventArgs e) {
368      if (e.TabPage == tabSchedule) {
369        await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
370          action: () => UpdateSchedule(),
371          finallyCallback: () => scheduleView.Content = HiveAdminClient.Instance.Downtimes);
372      }
373      SetEnabledStateOfControls();
374    }
375    #endregion
376
377    #region Helpers
378    private void BuildResourceTree(IEnumerable<Resource> resources) {
379      treeView.Nodes.Clear();
380      if (!resources.Any()) return;
381
382      var disabledParentResources = HiveAdminClient.Instance.DisabledParentResources;
383      var mainResources = new HashSet<Resource>(resources.OfType<SlaveGroup>()
384        .Where(x => x.ParentResourceId == null));
385      //var parentedMainResources = new HashSet<Resource>(resources.OfType<SlaveGroup>()
386      //  .Where(x => x.ParentResourceId.HasValue && !resources.Select(y => y.Id).Contains(x.ParentResourceId.Value)));
387      //mainResources.UnionWith(parentedMainResources);
388      var mainDisabledParentResources = new HashSet<Resource>(disabledParentResources.Where(x => x.ParentResourceId == null || x.ParentResourceId == Guid.Empty));
389      mainResources.UnionWith(mainDisabledParentResources);
390      var subResources = new HashSet<Resource>(resources.Union(disabledParentResources).Except(mainResources).OrderByDescending(x => x.Name));
391
392      var stack = new Stack<Resource>(mainResources.OrderByDescending(x => x.Name));
393      if (selectedResource != null) SelectedResource = resources.Where(x => x.Id == selectedResource.Id).FirstOrDefault();
394      bool nodeSelected = false;
395
396      TreeNode currentNode = null;
397      Resource currentResource = null;
398
399      while (stack.Any()) {
400        var newResource = stack.Pop();
401        var newNode = new TreeNode(newResource.Name) { Tag = newResource };
402        StyleTreeNode(newNode, newResource, resources);
403
404        if (selectedResource == null && !disabledParentResources.Contains(newResource)) {
405          SelectedResource = newResource;
406        }
407        if (!nodeSelected && selectedResource != null && newResource.Id == selectedResource.Id) {
408          newNode.BackColor = selectedBackColor;
409          newNode.ForeColor = selectedForeColor;
410          newNode.Text += SELECTED_TAG;
411          nodeSelected = true;
412        }
413
414        if (disabledParentResources.Contains(newResource)) {
415          newNode.Checked = false;
416          newNode.ForeColor = grayTextColor;
417        }
418
419        // search for parent node of newNode and save in currentNode
420        // necessary since newNodes (stack top items) might be siblings
421        // or grand..grandparents of previous node (currentNode)
422        while (currentNode != null && newResource.ParentResourceId != currentResource.Id) {
423          currentNode = currentNode.Parent;
424          currentResource = currentNode == null ? null : (Resource)currentNode.Tag;
425        }
426
427        if (currentNode == null) {
428          treeView.Nodes.Add(newNode);
429        } else {
430          currentNode.Nodes.Add(newNode);
431        }
432
433        if (newResource is SlaveGroup) {
434          var childResources = subResources.Where(x => x.ParentResourceId == newResource.Id);
435          if (childResources.Any()) {
436            foreach (var resource in childResources.OrderByDescending(x => x.Name)) {
437              subResources.Remove(resource);
438              stack.Push(resource);
439            }
440            currentNode = newNode;
441            currentResource = newResource;
442          }
443        }
444        newNode.SelectedImageIndex = newNode.ImageIndex;
445      }
446
447      // collapse slave-only nodes
448      foreach (TreeNode n in treeView.Nodes) {
449        CollapseSlaveOnlyNodes(n);
450      }
451
452      ungroupedGroupNode = new TreeNode(UNGROUPED_GROUP_NAME) {
453        ForeColor = SystemColors.GrayText,
454        ImageIndex = slaveGroupImageIndex,
455        Tag = new SlaveGroup() {
456          Name = UNGROUPED_GROUP_NAME,
457          Description = UNGROUPED_GROUP_DESCRIPTION
458        }
459      };
460
461      foreach (var slave in subResources.OfType<Slave>().OrderBy(x => x.Name)) {
462        var slaveNode = new TreeNode(slave.Name) { Tag = slave };
463        StyleTreeNode(slaveNode, slave, resources);
464        ungroupedGroupNode.Nodes.Add(slaveNode);
465        if (selectedResource == null) {
466          SelectedResource = slave;
467        }
468
469        if (slave.Id == selectedResource.Id && !nodeSelected) {
470          slaveNode.BackColor = selectedBackColor;
471          slaveNode.ForeColor = selectedForeColor;
472          slaveNode.Text += SELECTED_TAG;
473          nodeSelected = true;
474        }
475      }
476
477      if (ungroupedGroupNode.Nodes.Count > 0) {
478        ungroupedGroupNode.Text += " [" + ungroupedGroupNode.Nodes.Count.ToString() + "]";
479        ungroupedGroupNode.Expand();
480        treeView.Nodes.Add(ungroupedGroupNode);
481      }
482    }
483
484    private void CollapseSlaveOnlyNodes(TreeNode tn) {
485      Resource r = (Resource)tn.Tag;
486      var descendants = GetResourceDescendants();
487      if (descendants.ContainsKey(r.Id)) {
488        if (descendants[r.Id].OfType<SlaveGroup>().Any()) {
489          tn.Expand();
490          foreach (TreeNode n in tn.Nodes) CollapseSlaveOnlyNodes(n);
491        } else {
492          tn.Collapse();
493        }
494      }
495    }
496
497    private void ExpandResourceNodesOfInterest(TreeNodeCollection nodes) {
498      foreach (TreeNode n in nodes) {
499        Resource r = (Resource)n.Tag;
500        if (n.Nodes.Count > 0) {
501          if (HiveAdminClient.Instance.GetAvailableResourceDescendants(r.Id).OfType<SlaveGroup>().Any()) {
502            n.Expand();
503            ExpandResourceNodesOfInterest(n.Nodes);
504          } else {
505            n.Collapse();
506          }
507        } else {
508          n.Collapse();
509        }
510      }
511    }
512
513    private void UpdateChildHbIntervall(Resource resource) {
514      foreach (Resource r in Content.Where(x => x.ParentResourceId == resource.Id)) {
515        r.HbInterval = resource.HbInterval;
516        if (r is SlaveGroup) {
517          UpdateChildHbIntervall(r);
518        }
519      }
520    }
521
522    private void UpdateResources() {
523      try {
524        HiveAdminClient.Instance.Refresh();
525        Content = HiveAdminClient.Instance.Resources;
526      } catch (AnonymousUserException) {
527        ShowHiveInformationDialog();
528      }
529    }
530
531    private void RemoveResource(Resource resource) {
532      if (resource == null) return;
533
534      try {
535        if (resource.Id != Guid.Empty) {
536          SelectedResource = HiveAdminClient.Instance.GetAvailableResourceAncestors(resource.Id).LastOrDefault();
537          HiveAdminClient.Delete(resource);
538          UpdateResources();
539        } else {
540          SelectedResource = null;
541          Content.Remove(resource);
542        }
543      } catch (AnonymousUserException) {
544        ShowHiveInformationDialog();
545      }
546    }
547
548    private void UpdateSchedule() {
549      try {
550        HiveAdminClient.Instance.RefreshCalendar();
551      } catch (AnonymousUserException) {
552        ShowHiveInformationDialog();
553      }
554    }
555
556    private bool IsAdmin() {
557      return HiveRoles.CheckAdminUserPermissions();
558    }
559
560    private void StyleTreeNode(TreeNode n, Resource r, IEnumerable<Resource> resources) {
561      n.Text = r.Name;
562      n.BackColor = Color.Transparent;
563      n.ForeColor = Color.Black;
564
565      if (HiveAdminClient.Instance.DisabledParentResources.Select(x => x.Id).Contains(r.Id)) {
566        n.ForeColor = grayTextColor;
567      } else if (r.Id == Guid.Empty && n != ungroupedGroupNode /*!r.Name.StartsWith(UNGROUPED_GROUP_NAME)*/) {
568        // not stored (i.e. new)
569        n.Text += NOT_STORED_TAG;
570      } else if (r.Modified && n != ungroupedGroupNode /*!r.Name.StartsWith(UNGROUPED_GROUP_NAME)*/) {
571        // changed
572        n.Text += CHANGES_NOT_STORED_TAG;
573      }
574
575      // slave count
576      int childSlavesCount = 0;
577      if (r.Id != Guid.Empty && r is SlaveGroup) {
578        var descendants = GetResourceDescendants();
579        if (descendants.ContainsKey(r.Id)) {
580          childSlavesCount = resources
581            .OfType<Slave>()
582            .Where(x => descendants[r.Id].Select(y => y.Id)
583              .Contains(x.Id))
584            .Count();
585        }
586      } else if (n == ungroupedGroupNode /*|| r.Name.StartsWith(UNGROUPED_GROUP_NAME)*/) {
587        childSlavesCount = resources
588          .OfType<Slave>()
589          .Where(x => x.ParentResourceId == null
590            || (x.ParentResourceId.HasValue && x.ParentResourceId.Value == Guid.Empty))
591          .Count();
592      }
593      if (childSlavesCount > 0)
594        n.Text += " [" + childSlavesCount.ToString() + "]";
595
596      // slave image index, state, utilization
597      if (r is Slave) {
598        n.ImageIndex = slaveImageIndex;
599        var s = r as Slave;
600        if (s.SlaveState == SlaveState.Calculating) {
601          n.ForeColor = calculatingColor;
602          n.Text += " [" + s.CpuUtilization.ToString("N2") + "%]";
603        } else if (s.SlaveState == SlaveState.Offline) {
604          n.ForeColor = offlineColor;
605          if (s.LastHeartbeat.HasValue)
606            n.Text += " [" + (s.LastHeartbeat != null ? s.LastHeartbeat.Value.ToString("g") : null) + "]";
607        }
608      } else {
609        n.ImageIndex = slaveGroupImageIndex;
610      }
611
612      // ungrouped
613      if (n == ungroupedGroupNode /*r.Name.StartsWith(UNGROUPED_GROUP_NAME)*/) {
614        n.ForeColor = SystemColors.GrayText;
615      }
616    }
617
618    private void ResetTreeNodes(TreeNodeCollection nodes, IEnumerable<Resource> resources) {
619      foreach (TreeNode n in nodes) {
620        StyleTreeNode(n, (Resource)n.Tag, resources);
621        if (n.Nodes.Count > 0) {
622          ResetTreeNodes(n.Nodes, resources);
623        }
624      }
625    }
626
627    private async void ChangeSelectedResource(Resource resource) {
628      selectedResource = resource;
629      viewHost.Content = selectedResource;
630
631      HiveAdminClient.Instance.DowntimeForResourceId = selectedResource != null ? selectedResource.Id : Guid.Empty;
632      if (tabSlaveGroup.SelectedTab == tabSchedule) {
633        await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
634          action: () => UpdateSchedule(),
635          finallyCallback: () => scheduleView.Content = HiveAdminClient.Instance.Downtimes);
636      }
637
638      SetEnabledStateOfControls();
639    }
640
641    private void ChangeSelectedResourceNode(TreeNode resourceNode) {
642      if (resourceNode == null) return;
643      SelectedResource = (Resource)resourceNode.Tag;
644      ResetTreeNodes(treeView.Nodes, Content);
645      resourceNode.BackColor = selectedBackColor;
646      resourceNode.ForeColor = selectedForeColor;
647      resourceNode.Text += SELECTED_TAG;
648    }
649
650    private void ShowHiveInformationDialog() {
651      if (InvokeRequired) Invoke((Action)ShowHiveInformationDialog);
652      else {
653        using (HiveInformationDialog dialog = new HiveInformationDialog()) {
654          dialog.ShowDialog(this);
655        }
656      }
657    }
658
659    private void ResetView() {
660      if (InvokeRequired) Invoke((Action)ResetView);
661      else {
662        treeView.Nodes.Clear();
663
664        if (viewHost.Content != null && viewHost.Content is SlaveGroup) {
665          ((SlaveGroup)viewHost.Content).PropertyChanged -= SlaveViewContent_PropertyChanged;
666        }
667
668        viewHost.Content = null;
669        if (scheduleView.Content != null) {
670          scheduleView.Content.Clear();
671        }
672
673        HiveAdminClient.Instance.ResetDowntime();
674      }
675    }
676
677
678    private Dictionary<Guid, HashSet<Resource>> GetResourceDescendants() {
679      var resourceDescendants = new Dictionary<Guid, HashSet<Resource>>();
680      var resources = Content.Union(HiveAdminClient.Instance.DisabledParentResources).ToList();
681
682      foreach (var r in resources) resourceDescendants.Add(r.Id, new HashSet<Resource>());
683      foreach (var r in resources) {
684        var parentResourceId = r.ParentResourceId;
685        while (parentResourceId != null) {
686          var parent = resources.SingleOrDefault(x => x.Id == parentResourceId);
687          if (parent != null) {
688            resourceDescendants[parent.Id].Add(r);
689            parentResourceId = parent.ParentResourceId;
690          } else {
691            parentResourceId = null;
692          }
693        }
694      }
695      return resourceDescendants;
696    }
697
698    #endregion
699  }
700}
Note: See TracBrowser for help on using the repository browser.