Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2839_HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.cs @ 15819

Last change on this file since 15819 was 15819, checked in by jzenisek, 6 years ago

#2839: implemented refreshing list of available (i.e. for non-admins assignable) resources depending on currently selected project

File size: 24.6 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
54
55
56    private TreeNode ungroupedGroupNode;
57
58    private Resource selectedResource = null;
59    public Resource SelectedResource {
60      get { return selectedResource; }
61      set { if (selectedResource != value) ChangeSelectedResource(value); }
62    }
63
64    private readonly object locker = new object();
65
66    public new IItemList<Resource> Content {
67      get { return (IItemList<Resource>)base.Content; }
68      set { base.Content = value; }
69    }
70
71    public ResourcesView() {
72      InitializeComponent();
73
74      treeView.ImageList.Images.Add(VSImageLibrary.MonitorLarge);
75      treeView.ImageList.Images.Add(VSImageLibrary.NetworkCenterLarge);
76
77      HiveAdminClient.Instance.Refreshing += HiveAdminClient_Instance_Refreshing;
78      HiveAdminClient.Instance.Refreshed += HiveAdminClient_Instance_Refreshed;
79      AccessClient.Instance.Refreshing += AccessClient_Instance_Refreshing;
80      AccessClient.Instance.Refreshed += AccessClient_Instance_Refreshed;
81    }
82
83    #region Overrides
84    protected override void OnClosing(FormClosingEventArgs e) {
85      AccessClient.Instance.Refreshed -= AccessClient_Instance_Refreshed;
86      AccessClient.Instance.Refreshing -= AccessClient_Instance_Refreshing;
87      HiveAdminClient.Instance.Refreshed -= HiveAdminClient_Instance_Refreshed;
88      HiveAdminClient.Instance.Refreshing -= HiveAdminClient_Instance_Refreshing;
89      base.OnClosing(e);
90    }
91
92    protected override void RegisterContentEvents() {
93      base.RegisterContentEvents();
94      Content.ItemsAdded += Content_ItemsAdded;
95      Content.ItemsRemoved += Content_ItemsRemoved;
96    }
97
98    protected override void DeregisterContentEvents() {
99      Content.ItemsRemoved -= Content_ItemsRemoved;
100      Content.ItemsAdded -= Content_ItemsAdded;
101      base.DeregisterContentEvents();
102    }
103
104    protected override void OnContentChanged() {
105      base.OnContentChanged();
106      if (Content == null) {
107        treeView.Nodes.Clear();
108        viewHost.Content = null;
109        scheduleView.Content = null;
110      } else {
111        BuildResourceTree(Content);
112      }
113    }
114
115    protected override void SetEnabledStateOfControls() {
116      base.SetEnabledStateOfControls();
117
118      bool locked = Content == null || Locked || ReadOnly || !IsAdmin();
119      bool scheduleLocked = locked || (selectedResource != null && selectedResource.Id == Guid.Empty);
120      bool addLocked = locked || (selectedResource != null && selectedResource.Id == Guid.Empty) || selectedResource is Slave;
121
122      btnAddGroup.Enabled = !addLocked;
123      btnRemoveGroup.Enabled = !locked;
124      btnSave.Enabled = !locked;
125      viewHost.Locked = locked;
126      scheduleView.Locked = locked;
127      scheduleView.SetEnabledStateOfSchedule(!scheduleLocked);
128    }
129    #endregion
130
131    #region Event Handlers
132    private void Content_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<Resource>> e) {
133      if (InvokeRequired) Invoke((Action<object, CollectionItemsChangedEventArgs<IndexedItem<Resource>>>)Content_ItemsAdded, sender, e);
134      else {
135        OnContentChanged();
136      }
137    }
138
139    private void Content_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<Resource>> e) {
140      if (InvokeRequired) Invoke((Action<object, CollectionItemsChangedEventArgs<IndexedItem<Resource>>>)Content_ItemsRemoved, sender, e);
141      else {
142        OnContentChanged();
143      }
144    }
145
146    private void SlaveViewContent_PropertyChanged(object sender, PropertyChangedEventArgs e) {
147      if (InvokeRequired) Invoke((Action<object, PropertyChangedEventArgs>)SlaveViewContent_PropertyChanged, sender, e);
148      else {
149        OnContentChanged();
150        if (e.PropertyName == "HbInterval") {
151          UpdateChildHbIntervall((Resource)viewHost.Content);
152        }
153      }
154    }
155
156    private void HiveAdminClient_Instance_Refreshing(object sender, EventArgs e) {
157      if (InvokeRequired) Invoke((Action<object, EventArgs>)HiveAdminClient_Instance_Refreshing, sender, e);
158      else {
159        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
160        mainForm.AddOperationProgressToView(this, "Refreshing ...");
161        SetEnabledStateOfControls();
162      }
163    }
164
165    private void HiveAdminClient_Instance_Refreshed(object sender, EventArgs e) {
166      if (InvokeRequired) Invoke((Action<object, EventArgs>)HiveAdminClient_Instance_Refreshed, sender, e);
167      else {
168        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
169        mainForm.RemoveOperationProgressFromView(this);
170        SetEnabledStateOfControls();
171      }
172    }
173
174    private void AccessClient_Instance_Refreshing(object sender, EventArgs e) {
175      if (InvokeRequired) Invoke((Action<object, EventArgs>)AccessClient_Instance_Refreshing, sender, e);
176      else {
177        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
178        mainForm.AddOperationProgressToView(this, "Refreshing ...");
179        SetEnabledStateOfControls();
180      }
181    }
182
183    private void AccessClient_Instance_Refreshed(object sender, EventArgs e) {
184      if (InvokeRequired) Invoke((Action<object, EventArgs>)AccessClient_Instance_Refreshed, sender, e);
185      else {
186        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
187        mainForm.RemoveOperationProgressFromView(this);
188        SetEnabledStateOfControls();
189      }
190    }
191
192    private async void ResourcesView_Load(object sender, EventArgs e) {
193      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
194        action: () => UpdateResources());
195    }
196
197    private async void btnRefresh_Click(object sender, EventArgs e) {
198      lock (locker) {
199        if (!btnRefresh.Enabled) return;
200        btnRefresh.Enabled = false;
201      }
202
203      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
204        action: () => UpdateResources(),
205        finallyCallback: () => btnRefresh.Enabled = true);
206    }
207
208    private void btnAddGroup_Click(object sender, EventArgs e) {
209      Guid? parentResourceId = null;
210      if(!IsAdmin()) {
211        MessageBox.Show(
212          "You have no permission to add a resource group.",
213          "HeuristicLab Hive Administrator",
214          MessageBoxButtons.OK,
215          MessageBoxIcon.Information);
216        return;
217      } else if(selectedResource != null && selectedResource.Id == Guid.Empty) {
218        MessageBox.Show(
219          "You cannot add a resource group to a not yet stored group.",
220          "HeuristicLab Hive Administrator",
221          MessageBoxButtons.OK,
222          MessageBoxIcon.Information);
223        return;
224      }
225     
226      if (selectedResource != null && selectedResource is SlaveGroup) parentResourceId = selectedResource.Id;
227      var group = new SlaveGroup {
228        Name = "New Group",
229        OwnerUserId = UserInformation.Instance.User.Id,
230        ParentResourceId = parentResourceId
231      };
232
233      HiveAdminClient.Instance.UpdateResourceGenealogy(Content);
234      SelectedResource = group;
235      Content.Add(group);
236    }
237
238    private async void btnRemoveGroup_Click(object sender, EventArgs e) {
239      if (selectedResource == null) return;
240
241      lock (locker) {
242        if (!btnRemoveGroup.Enabled) return;
243        btnRemoveGroup.Enabled = false;
244      }
245
246      if (!IsAdmin()) {
247        MessageBox.Show(
248          "You have no permission to delete resources.",
249          "HeuristicLab Hive Administrator",
250          MessageBoxButtons.OK,
251          MessageBoxIcon.Information);
252        return;
253      }
254
255      if (Content.Any(x => x.ParentResourceId == selectedResource.Id)) {
256        MessageBox.Show(
257          "Only empty resources can be deleted.",
258          "HeuristicLab Hive Administrator",
259          MessageBoxButtons.OK,
260          MessageBoxIcon.Error);
261        return;
262      }
263
264      var result = MessageBox.Show(
265        "Do you really want to delete " + selectedResource.Name + "?",
266        "HeuristicLab Hive Administrator",
267        MessageBoxButtons.YesNo,
268        MessageBoxIcon.Question);
269      if (result == DialogResult.Yes) {
270        await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
271          action: () => {
272            RemoveResource(selectedResource);
273          },
274          finallyCallback: () => {
275            btnRemoveGroup.Enabled = true;
276          });
277      }
278    }
279
280    private async void btnSave_Click(object sender, EventArgs e) {
281      lock (locker) {
282        if (!btnSave.Enabled) return;
283        btnSave.Enabled = false;
284      }
285
286      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
287        action: () => {
288          var resourcesToSave = Content.Where(x => x.Id == Guid.Empty || x.Modified);
289          foreach (var resource in resourcesToSave)
290            resource.Store();
291          UpdateResources();
292        },
293        finallyCallback: () => btnSave.Enabled = true);
294
295      OnContentChanged();
296    }
297
298    private void treeSlaveGroup_MouseDown(object sender, MouseEventArgs e) {
299      var node = treeView.GetNodeAt(e.Location);
300      if(node != null && node != ungroupedGroupNode) ChangeSelectedResourceNode(node);
301    }
302
303    private void treeSlaveGroup_BeforeSelect(object sender, TreeViewCancelEventArgs e) {
304      e.Cancel = true;
305    }
306
307    private void treeSlaveGroup_BeforeCheck(object sender, TreeViewCancelEventArgs e) {
308      if(e.Node == ungroupedGroupNode) {
309        e.Cancel = true;
310      }
311    }
312
313    private void treeSlaveGroup_DragDrop(object sender, DragEventArgs e) {
314      if (e.Effect == DragDropEffects.None) return;
315
316      var targetNode = treeView.GetNodeAt(treeView.PointToClient(new Point(e.X, e.Y)));
317      var targetResource = (targetNode != null) ? (Resource)targetNode.Tag : null;
318      var resources = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat) as IEnumerable<Resource>;
319
320      foreach(var r in resources) {
321        r.ParentResourceId = targetResource?.Id;
322      }
323
324      HiveAdminClient.Instance.UpdateResourceGenealogy(Content);
325      OnContentChanged();
326    }
327
328    private void treeSlaveGroup_ItemDrag(object sender, ItemDragEventArgs e) {
329      if (!IsAdmin()) return;
330
331      var nodes = GetCheckedNodes(treeView.Nodes).ToList();
332      TreeNode sourceNode = (TreeNode)e.Item;
333      if(!sourceNode.Checked) nodes.Add(sourceNode);
334      nodes.Remove(ungroupedGroupNode);
335      ungroupedGroupNode.Checked = false;
336      var resources = nodes.Select(x => x.Tag).OfType<Resource>().ToList();
337
338      if(resources.Count > 0) {
339        DataObject data = new DataObject();
340        data.SetData(HeuristicLab.Common.Constants.DragDropDataFormat, resources);
341        var action = DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link | DragDropEffects.Move);
342        if(action.HasFlag(DragDropEffects.Move)) {
343          foreach (var node in nodes) node.Remove();
344          StyleTreeNode(ungroupedGroupNode, (Resource)ungroupedGroupNode.Tag, resources);
345        }
346      }
347    }
348
349    private IEnumerable<TreeNode> GetCheckedNodes(TreeNodeCollection nodes) {
350      if (nodes != null) {
351        foreach (var node in nodes.OfType<TreeNode>()) {
352          if (node.Checked && node != ungroupedGroupNode) yield return node;
353            foreach (var child in GetCheckedNodes(node.Nodes))
354              yield return child;
355          }
356      }
357    }
358
359    private void treeSlaveGroup_DragEnterOver(object sender, DragEventArgs e) {
360      e.Effect = DragDropEffects.Move;
361      var resources = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat) as IEnumerable<Resource>;
362      var targetNode = treeView.GetNodeAt(treeView.PointToClient(new Point(e.X, e.Y)));
363      var targetResource = targetNode?.Tag as Resource;
364
365      if(!IsAdmin()
366        || resources == null
367        || !resources.Any()
368        || resources.Any(x => !HiveAdminClient.Instance.CheckParentChange(x, targetResource))
369        || (targetNode != null && (targetNode == ungroupedGroupNode || targetNode.Parent == ungroupedGroupNode))) {
370        e.Effect = DragDropEffects.None;
371      }
372    }
373
374    private void TabSlaveGroup_TabIndexChanged(object sender, EventArgs e) {
375      throw new NotImplementedException();
376    }
377
378    private async void TabSlaveGroup_Selected(object sender, System.Windows.Forms.TabControlEventArgs e) {
379      if(e.TabPage == tabSchedule) {
380        await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
381          action: () => UpdateSchedule(),
382          finallyCallback: () => scheduleView.Content = HiveAdminClient.Instance.Downtimes);
383      }
384      SetEnabledStateOfControls();
385    }
386    #endregion
387
388    #region Helpers
389    private void BuildResourceTree(IEnumerable<Resource> resources) {
390      treeView.Nodes.Clear();
391      if (!resources.Any()) return;
392
393      var mainResources = new HashSet<Resource>(resources.OfType<SlaveGroup>()
394        .Where(x => x.ParentResourceId == null));
395      var parentedMainResources = new HashSet<Resource>(resources.OfType<SlaveGroup>()
396        .Where(x => x.ParentResourceId.HasValue && !resources.Select(y => y.Id).Contains(x.ParentResourceId.Value)));
397      mainResources.UnionWith(parentedMainResources);
398      var subResources = new HashSet<Resource>(resources.Except(mainResources).OrderByDescending(x => x.Name));
399
400      var stack = new Stack<Resource>(mainResources.OrderByDescending(x => x.Name));
401      if (selectedResource != null) SelectedResource = resources.Where(x => x.Id == selectedResource.Id).FirstOrDefault();
402      bool nodeSelected = false;
403
404      TreeNode currentNode = null;
405      Resource currentResource = null;
406
407      while (stack.Any()) {
408        var newResource = stack.Pop();
409        var newNode = new TreeNode(newResource.Name) { Tag = newResource };
410        StyleTreeNode(newNode, newResource, resources);
411
412        if (selectedResource == null) {
413          SelectedResource = newResource;
414        }
415        if (newResource.Id == selectedResource.Id && !nodeSelected) {
416          newNode.BackColor = selectedBackColor;
417          newNode.ForeColor = selectedForeColor;
418          newNode.Text += SELECTED_TAG;
419          nodeSelected = true;
420        }
421
422        // search for parent node of newNode and save in currentNode
423        // necessary since newNodes (stack top items) might be siblings
424        // or grand..grandparents of previous node (currentNode)
425        while (currentNode != null && newResource.ParentResourceId != currentResource.Id) {
426          currentNode = currentNode.Parent;
427          currentResource = currentNode == null ? null : (Resource)currentNode.Tag;
428        }
429
430        if (currentNode == null) {
431          treeView.Nodes.Add(newNode);
432        } else {
433          currentNode.Nodes.Add(newNode);
434        }
435
436        if (newResource is SlaveGroup) {
437          var childResources = subResources.Where(x => x.ParentResourceId == newResource.Id);
438          if (childResources.Any()) {
439            foreach (var resource in childResources.OrderByDescending(x => x.Name)) {
440              subResources.Remove(resource);
441              stack.Push(resource);
442            }
443            currentNode = newNode;
444            currentResource = newResource;
445          }
446        }
447        newNode.SelectedImageIndex = newNode.ImageIndex;
448      }
449
450      // collapse slave-only nodes
451      foreach(TreeNode n in treeView.Nodes) {
452        CollapseSlaveOnlyNodes(n);
453      }
454     
455      ungroupedGroupNode = new TreeNode(UNGROUPED_GROUP_NAME) {
456        ForeColor = SystemColors.GrayText,
457        Tag = new SlaveGroup() {
458          Name = UNGROUPED_GROUP_NAME,
459          Description = UNGROUPED_GROUP_DESCRIPTION
460        }
461      };
462
463      foreach (var slave in subResources.OfType<Slave>().OrderBy(x => x.Name)) {
464        var slaveNode = new TreeNode(slave.Name) { Tag = slave };
465        StyleTreeNode(slaveNode, slave, resources);
466        ungroupedGroupNode.Nodes.Add(slaveNode);
467        if (selectedResource == null) {
468          SelectedResource = slave;
469        }
470
471        if (slave.Id == selectedResource.Id && !nodeSelected) {
472          slaveNode.BackColor = selectedBackColor;
473          slaveNode.ForeColor = selectedForeColor;
474          slaveNode.Text += SELECTED_TAG;
475          nodeSelected = true;
476        }
477      }
478
479      if (ungroupedGroupNode.Nodes.Count > 0) {
480        ungroupedGroupNode.Text += " [" + ungroupedGroupNode.Nodes.Count.ToString() + "]";
481        ungroupedGroupNode.Expand();
482      }
483      treeView.Nodes.Add(ungroupedGroupNode);     
484    }
485
486    private void CollapseSlaveOnlyNodes(TreeNode tn) {
487      Resource r = (Resource)tn.Tag;
488      var descendants = HiveAdminClient.Instance.ResourceDescendants;
489      if(descendants.ContainsKey(r.Id)) {
490        if(descendants[r.Id].OfType<SlaveGroup>().Any()) {
491          tn.Expand();
492          foreach (TreeNode n in tn.Nodes) CollapseSlaveOnlyNodes(n);
493        } else {
494          tn.Collapse();
495        }
496      }
497    }
498
499    private void UpdateChildHbIntervall(Resource resource) {
500      foreach (Resource r in Content.Where(x => x.ParentResourceId == resource.Id)) {
501        r.HbInterval = resource.HbInterval;
502        if (r is SlaveGroup) {
503          UpdateChildHbIntervall(r);
504        }
505      }
506    }
507
508    private void UpdateResources() {
509      try {
510        HiveAdminClient.Instance.Refresh();
511        Content = HiveAdminClient.Instance.Resources;
512      } catch(AnonymousUserException) {
513        ShowHiveInformationDialog();
514      }
515    }
516
517    private void RemoveResource(Resource resource) {
518      if (resource == null) return;
519
520      try {
521        if (resource.Id != Guid.Empty) {
522          var resourcesToSave = Content.Where(x => x.Id == Guid.Empty || x.Modified);
523          foreach (var r in resourcesToSave)
524            r.Store();
525          HiveAdminClient.Delete(resource);
526          UpdateResources();
527        } else {
528          Content.Remove(selectedResource);
529        }
530      } catch(AnonymousUserException) {
531        ShowHiveInformationDialog();
532      }
533    }
534
535    private void UpdateSchedule() {
536      try {
537        HiveAdminClient.Instance.RefreshCalendar();
538      } catch (AnonymousUserException) {
539        ShowHiveInformationDialog();
540      }
541    }
542
543    private bool IsAdmin() {
544      return HiveRoles.CheckAdminUserPermissions();
545    }
546
547    private void StyleTreeNode(TreeNode n, Resource r, IEnumerable<Resource> resources) {
548      n.Text = r.Name;
549      n.BackColor = Color.Transparent;
550      n.ForeColor = Color.Black;
551
552      // not stored (i.e. new), changed
553      if (r.Id == Guid.Empty && n != ungroupedGroupNode /*!r.Name.StartsWith(UNGROUPED_GROUP_NAME)*/) {
554        n.Text += NOT_STORED_TAG;
555      } else if (r.Modified && n != ungroupedGroupNode /*!r.Name.StartsWith(UNGROUPED_GROUP_NAME)*/) {
556        n.Text += CHANGES_NOT_STORED_TAG;
557      }
558
559      // slave count
560      int childSlavesCount = 0;
561      if (r.Id != Guid.Empty && r is SlaveGroup) {
562        var descendants = HiveAdminClient.Instance.ResourceDescendants;
563        if (descendants.ContainsKey(r.Id)) {
564          childSlavesCount = resources
565            .OfType<Slave>()
566            .Where(x => descendants[r.Id].Select(y => y.Id)
567            .Contains(x.Id))
568            .Count();
569        }
570      } else if(n == ungroupedGroupNode /*|| r.Name.StartsWith(UNGROUPED_GROUP_NAME)*/) {
571        childSlavesCount = resources
572          .OfType<Slave>()
573          .Where(x => x.ParentResourceId == null
574            || (x.ParentResourceId.HasValue && x.ParentResourceId.Value == Guid.Empty))
575          .Count();
576      }
577      if (childSlavesCount > 0)
578        n.Text += " [" + childSlavesCount.ToString() + "]";
579
580      // slave image index, state, utilization
581      if (r is Slave) {
582        n.ImageIndex = slaveImageIndex;
583        var s = r as Slave;
584        if (s.SlaveState == SlaveState.Calculating) {
585          n.ForeColor = calculatingColor;
586          n.Text += " [" + s.CpuUtilization.ToString("N2") + "%]";
587        } else if (s.SlaveState == SlaveState.Offline) {
588          n.ForeColor = offlineColor;
589          if (s.LastHeartbeat.HasValue)
590            n.Text += " [" + s.LastHeartbeat?.ToString("g") + "]";
591        }
592      } else {
593        n.ImageIndex = slaveGroupImageIndex;
594      }
595
596      // ungrouped
597      if(n == ungroupedGroupNode /*r.Name.StartsWith(UNGROUPED_GROUP_NAME)*/) {
598        n.ForeColor = ForeColor = SystemColors.GrayText;
599      }
600    }
601
602    private void ResetTreeNodes(TreeNodeCollection nodes, IEnumerable<Resource> resources) {
603      foreach (TreeNode n in nodes) {
604        StyleTreeNode(n, (Resource)n.Tag, resources);
605        if (n.Nodes.Count > 0) {
606          ResetTreeNodes(n.Nodes, resources);
607        }
608      }
609    }
610
611    private async void ChangeSelectedResource(Resource resource) {
612      selectedResource = resource;
613      viewHost.Content = selectedResource;
614
615      HiveAdminClient.Instance.DowntimeForResourceId = selectedResource != null ? selectedResource.Id : Guid.Empty;
616      if (tabSlaveGroup.SelectedTab == tabSchedule) {
617        await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
618          action: () => UpdateSchedule(),
619          finallyCallback: () => scheduleView.Content = HiveAdminClient.Instance.Downtimes);
620      }
621
622      SetEnabledStateOfControls();
623    }
624
625    private void ChangeSelectedResourceNode(TreeNode resourceNode) {
626      if (resourceNode == null) return;
627      SelectedResource = (Resource)resourceNode.Tag;
628      ResetTreeNodes(treeView.Nodes, Content);
629      resourceNode.BackColor = selectedBackColor;
630      resourceNode.ForeColor = selectedForeColor;
631      resourceNode.Text += SELECTED_TAG;
632    }
633
634    private void ShowHiveInformationDialog() {
635      if (InvokeRequired) Invoke((Action)ShowHiveInformationDialog);
636      else {
637        using (HiveInformationDialog dialog = new HiveInformationDialog()) {
638          dialog.ShowDialog(this);
639        }
640      }
641    }
642
643    private void ResetView() {
644      if (InvokeRequired) Invoke((Action)ResetView);
645      else {
646        treeView.Nodes.Clear();
647
648        if (viewHost.Content != null && viewHost.Content is SlaveGroup) {
649          ((SlaveGroup)viewHost.Content).PropertyChanged -= SlaveViewContent_PropertyChanged;
650        }
651
652        viewHost.Content = null;
653        if (scheduleView.Content != null) {
654          scheduleView.Content.Clear();
655        }
656
657        HiveAdminClient.Instance.ResetDowntime();
658      }
659    }
660
661    #endregion
662  }
663}
Note: See TracBrowser for help on using the repository browser.