#region License Information /* HeuristicLab * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Linq; using System.Windows.Forms; using HeuristicLab.Clients.Access; using HeuristicLab.Clients.Hive.Views; using HeuristicLab.Collections; using HeuristicLab.Common.Resources; using HeuristicLab.Core; using HeuristicLab.Core.Views; using HeuristicLab.MainForm; namespace HeuristicLab.Clients.Hive.Administrator.Views { [View("Projects View")] [Content(typeof(IItemList), false)] public partial class ProjectsView : ItemView, IDisposable { private const int greenFlagImageIndex = 0; private const int redFlagImageIndex = 1; private readonly Color changedColor = Color.FromArgb(255, 87, 191, 193); // #57bfc1 private readonly Color selectedColor = Color.FromArgb(255, 240, 194, 59); // #f0c23b private readonly object locker = new object(); private Project selectedProject = null; public new IItemList Content { get { return (IItemList)base.Content; } set { base.Content = value; } } public ProjectsView() { InitializeComponent(); projectsTreeView.ImageList.Images.Add(VSImageLibrary.FlagGreen); projectsTreeView.ImageList.Images.Add(VSImageLibrary.FlagRed); HiveAdminClient.Instance.Refreshing += HiveAdminClient_Instance_Refreshing; HiveAdminClient.Instance.Refreshed += HiveAdminClient_Instance_Refreshed; AccessClient.Instance.Refreshing += AccessClient_Instance_Refreshing; AccessClient.Instance.Refreshed += AccessClient_Instance_Refreshed; } #region Overrides protected override void OnClosing(FormClosingEventArgs e) { AccessClient.Instance.Refreshed -= AccessClient_Instance_Refreshed; AccessClient.Instance.Refreshing -= AccessClient_Instance_Refreshing; HiveAdminClient.Instance.Refreshed -= HiveAdminClient_Instance_Refreshed; HiveAdminClient.Instance.Refreshing -= HiveAdminClient_Instance_Refreshing; base.OnClosing(e); } protected override void RegisterContentEvents() { base.RegisterContentEvents(); Content.ItemsAdded += Content_ItemsAdded; Content.ItemsRemoved += Content_ItemsRemoved; } protected override void DeregisterContentEvents() { Content.ItemsRemoved -= Content_ItemsRemoved; Content.ItemsAdded -= Content_ItemsAdded; base.DeregisterContentEvents(); } protected override void OnContentChanged() { base.OnContentChanged(); if (Content == null) { projectsTreeView.Nodes.Clear(); projectView.Content = null; projectPermissionsView.Content = null; projectResourcesView.Content = null; } else { var top = BuildProjectTree(Content); projectView.Content = top; projectPermissionsView.Content = top; projectResourcesView.Content = top; } } protected override void SetEnabledStateOfControls() { base.SetEnabledStateOfControls(); bool enabled = Content != null && !ReadOnly; refreshButton.Enabled = enabled; addButton.Enabled = enabled; removeButton.Enabled = enabled; saveProjectButton.Enabled = enabled; projectView.Enabled = enabled; projectPermissionsView.Enabled = enabled; projectResourcesView.Enabled = enabled; } #endregion #region Event Handlers private void Content_ItemsAdded(object sender, CollectionItemsChangedEventArgs> e) { if (InvokeRequired) Invoke((Action>>)Content_ItemsAdded, sender, e); else { OnContentChanged(); } } private void Content_ItemsRemoved(object sender, CollectionItemsChangedEventArgs> e) { if (InvokeRequired) Invoke((Action>>)Content_ItemsRemoved, sender, e); else { OnContentChanged(); } } private void ProjectViewContent_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (InvokeRequired) Invoke((Action)ProjectViewContent_PropertyChanged, sender, e); else { OnContentChanged(); } } private void HiveAdminClient_Instance_Refreshing(object sender, EventArgs e) { if (InvokeRequired) Invoke((Action)HiveAdminClient_Instance_Refreshing, sender, e); else { var mainForm = MainFormManager.GetMainForm(); mainForm.AddOperationProgressToView(this, "Refreshing ..."); SetEnabledStateOfControls(); } } private void HiveAdminClient_Instance_Refreshed(object sender, EventArgs e) { if (InvokeRequired) Invoke((Action)HiveAdminClient_Instance_Refreshed, sender, e); else { var mainForm = MainFormManager.GetMainForm(); mainForm.RemoveOperationProgressFromView(this); SetEnabledStateOfControls(); } } private void AccessClient_Instance_Refreshing(object sender, EventArgs e) { if (InvokeRequired) Invoke((Action)AccessClient_Instance_Refreshing, sender, e); else { var mainForm = MainFormManager.GetMainForm(); mainForm.AddOperationProgressToView(this, "Refreshing ..."); SetEnabledStateOfControls(); } } private void AccessClient_Instance_Refreshed(object sender, EventArgs e) { if (InvokeRequired) Invoke((Action)AccessClient_Instance_Refreshed, sender, e); else { var mainForm = MainFormManager.GetMainForm(); mainForm.RemoveOperationProgressFromView(this); SetEnabledStateOfControls(); } } private async void ProjectsView_Load(object sender, EventArgs e) { await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions( action: () => UpdateProjects(), finallyCallback: () => Content = HiveAdminClient.Instance.Projects); } private async void refreshButton_Click(object sender, EventArgs e) { lock (locker) { if (!refreshButton.Enabled) return; refreshButton.Enabled = false; } await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions( action: () => UpdateProjects(), finallyCallback: () => { Content = HiveAdminClient.Instance.Projects; refreshButton.Enabled = true; }); } private void addButton_Click(object sender, EventArgs e) { Guid? parentProjectId = null; if (selectedProject != null) parentProjectId = selectedProject.Id; var project = new Project { Name = "New Project", OwnerUserId = UserInformation.Instance.User.Id, ParentProjectId = parentProjectId }; Content.Add(project); } private async void removeButton_Click(object sender, EventArgs e) { lock (locker) { if (!removeButton.Enabled) return; removeButton.Enabled = false; } var selectedNode = projectsTreeView.SelectedNode; if (selectedNode == null || selectedNode.Tag == null) return; var project = (Project)selectedNode.Tag; var result = MessageBox.Show( "Do you really want to delete " + project.Name + "?", "HeuristicLab Hive Administrator", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (result == DialogResult.Yes) { if (Content.Any(x => x.ParentProjectId == project.Id)) { MessageBox.Show( "Only empty projects can be deleted.", "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error); } else { await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions( action: () => RemoveProject(project), finallyCallback: () => { Content.Remove(project); removeButton.Enabled = true; }); } } } private async void saveProjectButton_Click(object sender, EventArgs e) { lock (locker) { if (!saveProjectButton.Enabled) return; saveProjectButton.Enabled = false; } await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions( action: () => { var projectsToSave = Content.Where(x => x.Id == Guid.Empty || x.Modified); foreach (var project in projectsToSave) project.Store(); }, finallyCallback: () => saveProjectButton.Enabled = true); OnContentChanged(); } private void projectsTreeView_AfterSelect(object sender, TreeViewEventArgs e) { selectedProject = (Project)e.Node.Tag; ReColorTreeNodes(projectsTreeView.Nodes, selectedColor, Color.Transparent, true); e.Node.BackColor = selectedColor; e.Node.Text += " [selected]"; //if (projectView.Content != null) // projectView.Content.PropertyChanged -= ProjectViewContent_PropertyChanged; projectView.Content = selectedProject; projectPermissionsView.Content = selectedProject; projectResourcesView.Content = selectedProject; //if (selectedProject != null) // selectedProject.PropertyChanged += ProjectViewContent_PropertyChanged; //if (IsAuthorized(selectedProject)) { // if (!tabControl.TabPages.Contains(permissionsTabPage)) // tabControl.TabPages.Add(permissionsTabPage); // if (!tabControl.TabPages.Contains(resourcesTabPage)) // tabControl.TabPages.Add(resourcesTabPage); //} else { // if (tabControl.TabPages.Contains(permissionsTabPage)) // tabControl.TabPages.Remove(permissionsTabPage); // if (tabControl.TabPages.Contains(resourcesTabPage)) // tabControl.TabPages.Remove(resourcesTabPage); //} } private void projectsTreeView_DragDrop(object sender, DragEventArgs e) { var sourceNode = (TreeNode)e.Data.GetData(typeof(TreeNode)); if (sourceNode == null) return; var treeView = (TreeView)sender; if (sourceNode.TreeView != treeView) return; var targetPoint = treeView.PointToClient(new Point(e.X, e.Y)); var targetNode = treeView.GetNodeAt(targetPoint); if (sourceNode == targetNode) return; if (sourceNode.Parent == null) treeView.Nodes.Remove(sourceNode); else { sourceNode.Parent.Nodes.Remove(sourceNode); ((Project)sourceNode.Tag).ParentProjectId = null; } if (targetNode == null) { treeView.Nodes.Add(sourceNode); } else { targetNode.Nodes.Add(sourceNode); ((Project)sourceNode.Tag).ParentProjectId = ((Project)targetNode.Tag).Id; } } private void projectsTreeView_ItemDrag(object sender, ItemDragEventArgs e) { var sourceNode = (TreeNode)e.Item; if (IsAuthorized((Project)sourceNode.Tag)) DoDragDrop(sourceNode, DragDropEffects.All); } private void projectsTreeView_DragEnter(object sender, DragEventArgs e) { e.Effect = DragDropEffects.Move; } private void projectsTreeView_DragOver(object sender, DragEventArgs e) { e.Effect = DragDropEffects.Move; } private void projectsTreeView_QueryContinueDrag(object sender, QueryContinueDragEventArgs e) { e.Action = DragAction.Continue; } #endregion #region Helpers private void ReColorTreeNodes(TreeNodeCollection nodes, Color c1, Color c2, bool resetText) { foreach(TreeNode n in nodes) { if(n.BackColor.Equals(c1)) { n.BackColor = c2; if (resetText) n.Text = ((Project)n.Tag).Name; } if (n.Nodes.Count > 0) { ReColorTreeNodes(n.Nodes, c1, c2, resetText); } } } private Project BuildProjectTree(IEnumerable projects) { projectsTreeView.Nodes.Clear(); if (!projects.Any()) return null; var mainProjects = new HashSet(projects.Where(x => x.ParentProjectId == null)); var parentedMainProjects = new HashSet(projects .Where(x => x.ParentProjectId.HasValue && !projects.Select(y => y.Id).Contains(x.ParentProjectId.Value))); mainProjects.UnionWith(parentedMainProjects); var subProbjects = new HashSet(projects.Except(mainProjects)); var stack = new Stack(mainProjects.OrderByDescending(x => x.Name)); Project top = null; TreeNode currentNode = null; Project currentProject = null; while (stack.Any()) { var newProject = stack.Pop(); var newNode = new TreeNode(newProject.Name) { Tag = newProject }; if (top == null) { top = newProject; newNode.BackColor = selectedColor; newNode.Text += " [selected]"; } while (currentNode != null && newProject.ParentProjectId != currentProject.Id) { currentNode = currentNode.Parent; currentProject = currentNode == null ? null : (Project)currentNode.Tag; } if (currentNode == null) { projectsTreeView.Nodes.Add(newNode); newNode.ImageIndex = greenFlagImageIndex; } else { currentNode.Nodes.Add(newNode); newNode.ImageIndex = redFlagImageIndex; } newNode.SelectedImageIndex = newNode.ImageIndex; var childProjects = subProbjects.Where(x => x.ParentProjectId == newProject.Id); if (childProjects.Any()) { foreach (var project in childProjects.OrderByDescending(x => x.Name)) { subProbjects.Remove(project); stack.Push(project); } currentNode = newNode; currentProject = newProject; } } projectsTreeView.ExpandAll(); return top; } private void UpdateProjects() { try { HiveAdminClient.Instance.Refresh(); } catch (AnonymousUserException) { ShowHiveInformationDialog(); } } private void RemoveProject(Project project) { try { HiveAdminClient.Delete(project); } catch (AnonymousUserException) { ShowHiveInformationDialog(); } } private bool IsAuthorized(Project project) { return project != null && UserInformation.Instance.UserExists; //&& (project.OwnerUserId == UserInformation.Instance.User.Id || HiveRoles.CheckAdminUserPermissions()); } private void ShowHiveInformationDialog() { if (InvokeRequired) Invoke((Action)ShowHiveInformationDialog); else { using (HiveInformationDialog dialog = new HiveInformationDialog()) { dialog.ShowDialog(this); } } } #endregion } }