source: branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectsView.cs @ 15422

Last change on this file since 15422 was 15422, checked in by jkarder, 3 years ago

#2839: worked on resources and projects views

File size: 14.3 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("Projects View")]
38  [Content(typeof(IItemList<Project>), false)]
39  public partial class ProjectsView : ItemView, IDisposable {
40    private const int greenFlagImageIndex = 0;
41    private const int redFlagImageIndex = 1;
42
43    private readonly object locker = new object();
44
45    public new IItemList<Project> Content {
46      get { return (IItemList<Project>)base.Content; }
47      set { base.Content = value; }
48    }
49
50    public ProjectsView() {
51      InitializeComponent();
52
53      projectsTreeView.ImageList.Images.Add(VSImageLibrary.FlagGreen);
54      projectsTreeView.ImageList.Images.Add(VSImageLibrary.FlagRed);
55
56      HiveAdminClient.Instance.Refreshing += HiveAdminClient_Instance_Refreshing;
57      HiveAdminClient.Instance.Refreshed += HiveAdminClient_Instance_Refreshed;
58      AccessClient.Instance.Refreshing += AccessClient_Instance_Refreshing;
59      AccessClient.Instance.Refreshed += AccessClient_Instance_Refreshed;
60    }
61
62    #region Overrides
63    protected override void OnClosing(FormClosingEventArgs e) {
64      AccessClient.Instance.Refreshed -= AccessClient_Instance_Refreshed;
65      AccessClient.Instance.Refreshing -= AccessClient_Instance_Refreshing;
66      HiveAdminClient.Instance.Refreshed -= HiveAdminClient_Instance_Refreshed;
67      HiveAdminClient.Instance.Refreshing -= HiveAdminClient_Instance_Refreshing;
68      base.OnClosing(e);
69    }
70
71    protected override void RegisterContentEvents() {
72      base.RegisterContentEvents();
73      Content.ItemsAdded += Content_ItemsAdded;
74      Content.ItemsRemoved += Content_ItemsRemoved;
75    }
76
77    protected override void DeregisterContentEvents() {
78      Content.ItemsRemoved -= Content_ItemsRemoved;
79      Content.ItemsAdded -= Content_ItemsAdded;
80      base.DeregisterContentEvents();
81    }
82
83    protected override void OnContentChanged() {
84      base.OnContentChanged();
85      if (Content == null) {
86        projectsTreeView.Nodes.Clear();
87        projectView.Content = null;
88        projectPermissionsView.Content = null;
89        projectResourcesView.Content = null;
90      } else {
91        var top = BuildProjectTree(Content);
92        projectView.Content = top;
93        projectPermissionsView.Content = top;
94        projectResourcesView.Content = top;
95      }
96    }
97
98    protected override void SetEnabledStateOfControls() {
99      base.SetEnabledStateOfControls();
100      bool enabled = Content != null && !ReadOnly;
101      refreshButton.Enabled = enabled;
102      addButton.Enabled = enabled;
103      removeButton.Enabled = enabled;
104      saveProjectButton.Enabled = enabled;
105      projectView.Enabled = enabled;
106      projectPermissionsView.Enabled = enabled;
107      projectResourcesView.Enabled = enabled;
108    }
109    #endregion
110
111    #region Event Handlers
112    private void Content_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<Project>> e) {
113      if (InvokeRequired) Invoke((Action<object, CollectionItemsChangedEventArgs<IndexedItem<Project>>>)Content_ItemsAdded, sender, e);
114      else {
115        OnContentChanged();
116      }
117    }
118
119    private void Content_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<Project>> e) {
120      if (InvokeRequired) Invoke((Action<object, CollectionItemsChangedEventArgs<IndexedItem<Project>>>)Content_ItemsRemoved, sender, e);
121      else {
122        OnContentChanged();
123      }
124    }
125
126    private void ProjectViewContent_PropertyChanged(object sender, PropertyChangedEventArgs e) {
127      if (InvokeRequired) Invoke((Action<object, PropertyChangedEventArgs>)ProjectViewContent_PropertyChanged, sender, e);
128      else {
129        OnContentChanged();
130      }
131    }
132
133    private void HiveAdminClient_Instance_Refreshing(object sender, EventArgs e) {
134      if (InvokeRequired) Invoke((Action<object, EventArgs>)HiveAdminClient_Instance_Refreshing, sender, e);
135      else {
136        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
137        mainForm.AddOperationProgressToView(this, "Refreshing ...");
138        SetEnabledStateOfControls();
139      }
140    }
141
142    private void HiveAdminClient_Instance_Refreshed(object sender, EventArgs e) {
143      if (InvokeRequired) Invoke((Action<object, EventArgs>)HiveAdminClient_Instance_Refreshed, sender, e);
144      else {
145        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
146        mainForm.RemoveOperationProgressFromView(this);
147        SetEnabledStateOfControls();
148      }
149    }
150
151    private void AccessClient_Instance_Refreshing(object sender, EventArgs e) {
152      if (InvokeRequired) Invoke((Action<object, EventArgs>)AccessClient_Instance_Refreshing, sender, e);
153      else {
154        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
155        mainForm.AddOperationProgressToView(this, "Refreshing ...");
156        SetEnabledStateOfControls();
157      }
158    }
159
160    private void AccessClient_Instance_Refreshed(object sender, EventArgs e) {
161      if (InvokeRequired) Invoke((Action<object, EventArgs>)AccessClient_Instance_Refreshed, sender, e);
162      else {
163        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
164        mainForm.RemoveOperationProgressFromView(this);
165        SetEnabledStateOfControls();
166      }
167    }
168
169    private async void ProjectsView_Load(object sender, EventArgs e) {
170      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
171        action: () => UpdateProjects(),
172        finallyCallback: () => Content = HiveAdminClient.Instance.Projects);
173    }
174
175    private async void refreshButton_Click(object sender, EventArgs e) {
176      lock (locker) {
177        if (!refreshButton.Enabled) return;
178        refreshButton.Enabled = false;
179      }
180
181      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
182        action: () => UpdateProjects(),
183        finallyCallback: () => {
184          Content = HiveAdminClient.Instance.Projects;
185          refreshButton.Enabled = true;
186        });
187    }
188
189    private void addButton_Click(object sender, EventArgs e) {
190      var project = new Project {
191        Name = "New Project",
192        OwnerUserId = UserInformation.Instance.User.Id
193      };
194      Content.Add(project);
195    }
196
197    private async void removeButton_Click(object sender, EventArgs e) {
198      lock (locker) {
199        if (!removeButton.Enabled) return;
200        removeButton.Enabled = false;
201      }
202
203      var selectedNode = projectsTreeView.SelectedNode;
204      if (selectedNode == null || selectedNode.Tag == null) return;
205
206      var project = (Project)selectedNode.Tag;
207      var result = MessageBox.Show(
208        "Do you really want to delete " + project.Name + "?",
209        "HeuristicLab Hive Administrator",
210        MessageBoxButtons.YesNo,
211        MessageBoxIcon.Question);
212
213      if (result == DialogResult.Yes) {
214        if (Content.Any(x => x.ParentProjectId == project.Id)) {
215          MessageBox.Show(
216            "Only empty projects can be deleted.",
217            "HeuristicLab Hive Administrator",
218            MessageBoxButtons.OK,
219            MessageBoxIcon.Error);
220        } else {
221          await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
222            action: () => RemoveProject(project),
223            finallyCallback: () => {
224              Content.Remove(project);
225              removeButton.Enabled = true;
226            });
227        }
228      }
229    }
230
231    private async void saveProjectButton_Click(object sender, EventArgs e) {
232      lock (locker) {
233        if (!saveProjectButton.Enabled) return;
234        saveProjectButton.Enabled = false;
235      }
236
237      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
238        action: () => {
239          var projectsToSave = Content.Where(x => x.Id == Guid.Empty || x.Modified);
240          foreach (var project in projectsToSave)
241            project.Store();
242        },
243        finallyCallback: () => saveProjectButton.Enabled = true);
244    }
245
246    private void projectsTreeView_AfterSelect(object sender, TreeViewEventArgs e) {
247      var selectedProject = (Project)e.Node.Tag;
248
249      if (projectView.Content != null)
250        projectView.Content.PropertyChanged -= ProjectViewContent_PropertyChanged;
251
252      projectView.Content = selectedProject;
253      projectPermissionsView.Content = selectedProject;
254      projectResourcesView.Content = selectedProject;
255
256      if (selectedProject != null)
257        selectedProject.PropertyChanged += ProjectViewContent_PropertyChanged;
258
259      if (IsAuthorized(selectedProject)) {
260        if (!tabControl.TabPages.Contains(permissionsTabPage))
261          tabControl.TabPages.Add(permissionsTabPage);
262        if (!tabControl.TabPages.Contains(resourcesTabPage))
263          tabControl.TabPages.Add(resourcesTabPage);
264      } else {
265        if (tabControl.TabPages.Contains(permissionsTabPage))
266          tabControl.TabPages.Remove(permissionsTabPage);
267        if (tabControl.TabPages.Contains(resourcesTabPage))
268          tabControl.TabPages.Remove(resourcesTabPage);
269      }
270    }
271
272    private void projectsTreeView_DragDrop(object sender, DragEventArgs e) {
273      var sourceNode = (TreeNode)e.Data.GetData(typeof(TreeNode));
274      if (sourceNode == null) return;
275
276      var treeView = (TreeView)sender;
277      if (sourceNode.TreeView != treeView) return;
278
279      var targetPoint = treeView.PointToClient(new Point(e.X, e.Y));
280      var targetNode = treeView.GetNodeAt(targetPoint);
281
282      if (sourceNode == targetNode) return;
283
284      if (sourceNode.Parent == null)
285        treeView.Nodes.Remove(sourceNode);
286      else {
287        sourceNode.Parent.Nodes.Remove(sourceNode);
288        ((Project)sourceNode.Tag).ParentProjectId = null;
289      }
290
291      if (targetNode == null) {
292        treeView.Nodes.Add(sourceNode);
293      } else {
294        targetNode.Nodes.Add(sourceNode);
295        ((Project)sourceNode.Tag).ParentProjectId = ((Project)targetNode.Tag).Id;
296      }
297    }
298
299    private void projectsTreeView_ItemDrag(object sender, ItemDragEventArgs e) {
300      var sourceNode = (TreeNode)e.Item;
301      if (IsAuthorized((Project)sourceNode.Tag))
302        DoDragDrop(sourceNode, DragDropEffects.All);
303    }
304
305    private void projectsTreeView_DragEnter(object sender, DragEventArgs e) {
306      e.Effect = DragDropEffects.Move;
307    }
308
309    private void projectsTreeView_DragOver(object sender, DragEventArgs e) {
310      e.Effect = DragDropEffects.Move;
311    }
312
313    private void projectsTreeView_QueryContinueDrag(object sender, QueryContinueDragEventArgs e) {
314      e.Action = DragAction.Continue;
315    }
316    #endregion
317
318    #region Helpers
319    private Project BuildProjectTree(IEnumerable<Project> projects) {
320      projectsTreeView.Nodes.Clear();
321      if (!projects.Any()) return null;
322
323      var mainProjects = new HashSet<Project>(projects.Where(x => x.ParentProjectId == null));
324      var subProbjects = new HashSet<Project>(projects.Except(mainProjects));
325
326      var stack = new Stack<Project>(mainProjects.OrderByDescending(x => x.Name));
327      var top = stack.Peek();
328
329      TreeNode currentNode = null;
330      Project currentProject = null;
331
332      while (stack.Any()) {
333        var newProject = stack.Pop();
334        var newNode = new TreeNode(newProject.Name) { Tag = newProject };
335
336        while (currentNode != null && newProject.ParentProjectId != currentProject.Id) {
337          currentNode = currentNode.Parent;
338          currentProject = currentNode == null ? null : (Project)currentNode.Tag;
339        }
340
341        if (currentNode == null) {
342          projectsTreeView.Nodes.Add(newNode);
343          newNode.ImageIndex = greenFlagImageIndex;
344        } else {
345          currentNode.Nodes.Add(newNode);
346          newNode.ImageIndex = redFlagImageIndex;
347        }
348
349        newNode.SelectedImageIndex = newNode.ImageIndex;
350
351        var childProjects = subProbjects.Where(x => x.ParentProjectId == newProject.Id);
352        if (childProjects.Any()) {
353          foreach (var project in childProjects.OrderByDescending(x => x.Name)) {
354            subProbjects.Remove(project);
355            stack.Push(project);
356          }
357          currentNode = newNode;
358          currentProject = newProject;
359        }
360      }
361
362      projectsTreeView.ExpandAll();
363
364      return top;
365    }
366
367    private void UpdateProjects() {
368      try {
369        HiveAdminClient.Instance.Refresh();
370      } catch (AnonymousUserException) {
371        ShowHiveInformationDialog();
372      }
373    }
374
375    private void RemoveProject(Project project) {
376      try {
377        HiveAdminClient.Delete(project);
378      } catch (AnonymousUserException) {
379        ShowHiveInformationDialog();
380      }
381    }
382
383    private bool IsAuthorized(Project project) {
384      return project != null
385          && UserInformation.Instance.UserExists
386          && (project.OwnerUserId == UserInformation.Instance.User.Id || HiveRoles.CheckAdminUserPermissions());
387    }
388
389    private void ShowHiveInformationDialog() {
390      if (InvokeRequired) Invoke((Action)ShowHiveInformationDialog);
391      else {
392        using (HiveInformationDialog dialog = new HiveInformationDialog()) {
393          dialog.ShowDialog(this);
394        }
395      }
396    }
397    #endregion
398  }
399}
Note: See TracBrowser for help on using the repository browser.