#region License Information /* HeuristicLab * Copyright (C) 2002-2015 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.Drawing; using System.Linq; using System.Windows.Forms; using HeuristicLab.Core; using HeuristicLab.PluginInfrastructure; namespace HeuristicLab.Optimizer { internal partial class NewItemDialog : Form { private bool isInitialized; private List treeNodes; private string currentSearchString; private Type selectedType; public Type SelectedType { get { return selectedType; } private set { if (value != selectedType) { selectedType = value; OnSelectedTypeChanged(); } } } private IItem item; public IItem Item { get { return item; } } public NewItemDialog() { InitializeComponent(); treeNodes = new List(); currentSearchString = string.Empty; item = null; SelectedTypeChanged += this_SelectedTypeChanged; } private void NewItemDialog_Load(object sender, EventArgs e) { if (isInitialized) return; var categories = from t in ApplicationManager.Manager.GetTypes(typeof(IItem)) where CreatableAttribute.IsCreatable(t) orderby CreatableAttribute.GetCategory(t), ItemAttribute.GetName(t), ItemAttribute.GetVersion(t) ascending group t by CreatableAttribute.GetCategory(t) into c select c; imageList.Images.Add(HeuristicLab.Common.Resources.VSImageLibrary.Class); // default icon imageList.Images.Add(HeuristicLab.Common.Resources.VSImageLibrary.Namespace); // plugins foreach (var category in categories) { var categoryNode = new TreeNode(category.Key) { ImageIndex = 1, Tag = category.Key, }; categoryNode.SelectedImageIndex = categoryNode.ImageIndex; foreach (var creatable in category) { string name = ItemAttribute.GetName(creatable); var itemNode = new TreeNode(name) { ImageIndex = 0, Tag = creatable }; categoryNode.Nodes.Add(itemNode); var image = ItemAttribute.GetImage(creatable); if (image != null) { imageList.Images.Add(image); itemNode.ImageIndex = imageList.Images.Count - 1; } itemNode.SelectedImageIndex = itemNode.ImageIndex; } if (categoryNode.Nodes.Count > 0) treeNodes.Add(categoryNode); } foreach (var node in treeNodes) typesTreeView.Nodes.Add((TreeNode)node.Clone()); isInitialized = true; } private void NewItemDialog_Shown(object sender, EventArgs e) { searchTextBox.Text = string.Empty; searchTextBox.Focus(); } public virtual void Filter(string searchString) { if (InvokeRequired) { Invoke(new Action(Filter), searchString); } else { searchString = searchString.ToLower(); if (!searchString.Contains(currentSearchString)) { typesTreeView.BeginUpdate(); // expand saerch -> restore all tree nodes var selectedNode = typesTreeView.SelectedNode; typesTreeView.Nodes.Clear(); foreach (TreeNode node in treeNodes) typesTreeView.Nodes.Add((TreeNode)node.Clone()); RestoreSelectedNode(selectedNode); typesTreeView.EndUpdate(); } // remove nodes typesTreeView.BeginUpdate(); int i = 0; var searchTokens = searchString.Split(' '); while (i < typesTreeView.Nodes.Count) { int j = 0; while (j < typesTreeView.Nodes[i].Nodes.Count) { if (searchTokens.Any(searchToken => !typesTreeView.Nodes[i].Nodes[j].Text.ToLower().Contains(searchToken))) { if ((typesTreeView.Nodes[i].Nodes[j].Tag as Type).Equals(SelectedType)) SelectedType = null; typesTreeView.Nodes[i].Nodes[j].Remove(); } else j++; } if (typesTreeView.Nodes[i].Nodes.Count == 0) typesTreeView.Nodes[i].Remove(); else i++; } typesTreeView.EndUpdate(); currentSearchString = searchString; // if there is just one type node left, select by default if (typesTreeView.Nodes.Count == 1) { if (typesTreeView.Nodes[0].Nodes.Count == 1) { typesTreeView.SelectedNode = typesTreeView.Nodes[0].Nodes[0]; } } if (typesTreeView.Nodes.Count == 0) { SelectedType = null; typesTreeView.Enabled = false; } else { SetTreeNodeVisibility(); typesTreeView.Enabled = true; } UpdateDescription(); } } protected virtual void UpdateDescription() { descriptionTextBox.Text = string.Empty; if (typesTreeView.SelectedNode != null) { string category = typesTreeView.SelectedNode.Tag as string; if (category != null) { descriptionTextBox.Text = category; pluginTextBox.Text = string.Empty; versionTextBox.Text = string.Empty; } Type type = typesTreeView.SelectedNode.Tag as Type; if (type != null) { string description = ItemAttribute.GetDescription(type); var version = ItemAttribute.GetVersion(type); var plugin = ApplicationManager.Manager.GetDeclaringPlugin(type); if (description != null) descriptionTextBox.Text = description; if (plugin != null) pluginTextBox.Text = plugin.Name; if (version != null) versionTextBox.Text = version.ToString(); } } else if (typesTreeView.Nodes.Count == 0) { descriptionTextBox.Text = "No types found"; pluginTextBox.Text = string.Empty; versionTextBox.Text = string.Empty; } } #region Events public event EventHandler SelectedTypeChanged; protected virtual void OnSelectedTypeChanged() { if (SelectedTypeChanged != null) SelectedTypeChanged(this, EventArgs.Empty); } #endregion #region Control Events protected virtual void searchTextBox_TextChanged(object sender, EventArgs e) { Filter(searchTextBox.Text); } protected virtual void itemsTreeView_AfterSelect(object sender, TreeViewEventArgs e) { if (typesTreeView.SelectedNode == null) SelectedType = null; else SelectedType = typesTreeView.SelectedNode.Tag as Type; UpdateDescription(); } protected virtual void itemsTreeView_VisibleChanged(object sender, EventArgs e) { if (Visible) SetTreeNodeVisibility(); } #endregion #region Helpers private void RestoreSelectedNode(TreeNode selectedNode) { if (selectedNode != null) { foreach (TreeNode node in typesTreeView.Nodes) { if (node.Text.Equals(selectedNode.Text)) typesTreeView.SelectedNode = node; foreach (TreeNode child in node.Nodes) { if ((child.Text.Equals(selectedNode.Text)) && (child.Tag == selectedNode.Tag)) typesTreeView.SelectedNode = child; } } if (typesTreeView.SelectedNode == null) SelectedType = null; } } private void SetTreeNodeVisibility() { TreeNode selectedNode = typesTreeView.SelectedNode; if (string.IsNullOrEmpty(currentSearchString) && (typesTreeView.Nodes.Count > 1)) { typesTreeView.CollapseAll(); if (selectedNode != null) typesTreeView.SelectedNode = selectedNode; } else { typesTreeView.ExpandAll(); } if (selectedNode != null) selectedNode.EnsureVisible(); } #endregion private void okButton_Click(object sender, EventArgs e) { if (SelectedType != null) { item = (IItem)Activator.CreateInstance(SelectedType); DialogResult = DialogResult.OK; Close(); } } private void itemTreeView_DoubleClick(object sender, EventArgs e) { if (SelectedType != null) { item = (IItem)Activator.CreateInstance(SelectedType); DialogResult = DialogResult.OK; Close(); } } private void this_SelectedTypeChanged(object sender, EventArgs e) { okButton.Enabled = SelectedType != null; } private void expandAllButton_Click(object sender, EventArgs e) { typesTreeView.ExpandAll(); } private void collapseAllButton_Click(object sender, EventArgs e) { typesTreeView.CollapseAll(); } private TreeNode toolStripMenuNode = null; private void typesTreeView_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Right) { Point coordinates = typesTreeView.PointToClient(Cursor.Position); toolStripMenuNode = typesTreeView.GetNodeAt(coordinates); if (toolStripMenuNode != null && coordinates.X >= toolStripMenuNode.Bounds.Left && coordinates.X <= toolStripMenuNode.Bounds.Right) { typesTreeView.SelectedNode = toolStripMenuNode; expandToolStripMenuItem.Enabled = expandToolStripMenuItem.Visible = !toolStripMenuNode.IsExpanded && toolStripMenuNode.Nodes.Count > 0; collapseToolStripMenuItem.Enabled = collapseToolStripMenuItem.Visible = toolStripMenuNode.IsExpanded; } else { expandToolStripMenuItem.Enabled = expandToolStripMenuItem.Visible = false; collapseToolStripMenuItem.Enabled = collapseToolStripMenuItem.Visible = false; } expandAllToolStripMenuItem.Enabled = expandAllToolStripMenuItem.Visible = !typesTreeView.Nodes.OfType().All(x => TreeNodeIsFullyExpanded(x)); collapseAllToolStripMenuItem.Enabled = collapseAllToolStripMenuItem.Visible = typesTreeView.Nodes.OfType().Any(x => x.IsExpanded); if (contextMenuStrip.Items.Cast().Any(item => item.Enabled)) contextMenuStrip.Show(Cursor.Position); } } private bool TreeNodeIsFullyExpanded(TreeNode node) { return (node.Nodes.Count == 0) || (node.IsExpanded && node.Nodes.OfType().All(x => TreeNodeIsFullyExpanded(x))); } private void expandToolStripMenuItem_Click(object sender, EventArgs e) { if (toolStripMenuNode != null) toolStripMenuNode.ExpandAll(); } private void expandAllToolStripMenuItem_Click(object sender, EventArgs e) { typesTreeView.ExpandAll(); } private void collapseToolStripMenuItem_Click(object sender, EventArgs e) { if (toolStripMenuNode != null) toolStripMenuNode.Collapse(); } private void collapseAllToolStripMenuItem_Click(object sender, EventArgs e) { typesTreeView.CollapseAll(); } } }