Free cookie consent management tool by TermsFeed Policy Generator

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

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

#2839 preliminary integration of several HiveAdministrator related improvements from #2877 (full merge pending)

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