Changeset 12694 for branches/HeuristicLab.Problems.Orienteering/HeuristicLab.Optimizer/3.3/NewItemDialog.cs
- Timestamp:
- 07/09/15 13:07:30 (9 years ago)
- Location:
- branches/HeuristicLab.Problems.Orienteering
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/HeuristicLab.Problems.Orienteering
- Property svn:mergeinfo changed
-
Property
svn:global-ignores
set to
*.nuget
packages
-
branches/HeuristicLab.Problems.Orienteering/HeuristicLab.Optimizer
-
Property
svn:mergeinfo
set to
(toggle deleted branches)
/branches/HLScript/HeuristicLab.Optimizer merged eligible /stable/HeuristicLab.Optimizer merged eligible /trunk/sources/HeuristicLab.Optimizer merged eligible /branches/1721-RandomForestPersistence/HeuristicLab.Optimizer 10321-10322 /branches/Algorithms.GradientDescent/HeuristicLab.Optimizer 5516-5520 /branches/Benchmarking/sources/HeuristicLab.Optimizer 6917-7005 /branches/CloningRefactoring/HeuristicLab.Optimizer 4656-4721 /branches/CodeEditor/HeuristicLab.Optimizer 11700-11806 /branches/DataAnalysis Refactoring/HeuristicLab.Optimizer 5471-5808 /branches/DataAnalysis SolutionEnsembles/HeuristicLab.Optimizer 5815-6180 /branches/DataAnalysis/HeuristicLab.Optimizer 4458-4459,4462,4464 /branches/DataPreprocessing/HeuristicLab.Optimizer 10085-11101 /branches/EnumValue in CreateExperiment/HeuristicLab.Optimizer 12251-12678 /branches/GP.Grammar.Editor/HeuristicLab.Optimizer 6284-6795 /branches/GP.Symbols (TimeLag, Diff, Integral)/HeuristicLab.Optimizer 5060 /branches/HeuristicLab.DatasetRefactor/sources/HeuristicLab.Optimizer 11570-12508 /branches/HeuristicLab.Problems.DataAnalysis.Trading/HeuristicLab.Optimizer 6123-9799 /branches/LogResidualEvaluator/HeuristicLab.Optimizer 10202-10483 /branches/NET40/sources/HeuristicLab.Optimizer 5138-5162 /branches/NSGA-II Changes/HeuristicLab.Optimizer 12033-12122 /branches/NewItemDialog/HeuristicLab.Optimizer 12184-12284 /branches/ParallelEngine/HeuristicLab.Optimizer 5175-5192 /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Optimizer 7568-7810 /branches/QAPAlgorithms/HeuristicLab.Optimizer 6350-6627 /branches/Restructure trunk solution/HeuristicLab.Optimizer 6828 /branches/RuntimeOptimizer/HeuristicLab.Optimizer 8943-9078 /branches/ScatterSearch (trunk integration)/HeuristicLab.Optimizer 7787-8333 /branches/SlaveShutdown/HeuristicLab.Optimizer 8944-8956 /branches/SpectralKernelForGaussianProcesses/HeuristicLab.Optimizer 10204-10479 /branches/SuccessProgressAnalysis/HeuristicLab.Optimizer 5370-5682 /branches/Trunk/HeuristicLab.Optimizer 6829-6865 /branches/UnloadJobs/HeuristicLab.Optimizer 9168-9215 /branches/VNS/HeuristicLab.Optimizer 5594-5752 /branches/histogram/HeuristicLab.Optimizer 5959-6341
-
Property
svn:mergeinfo
set to
(toggle deleted branches)
-
branches/HeuristicLab.Problems.Orienteering/HeuristicLab.Optimizer/3.3/NewItemDialog.cs
r11185 r12694 1 1 #region License Information 2 2 /* HeuristicLab 3 * Copyright (C) 2002-201 4Heuristic and Evolutionary Algorithms Laboratory (HEAL)3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 4 * 5 5 * This file is part of HeuristicLab. … … 21 21 22 22 using System; 23 using System.Collections; 24 using System.Collections.Generic; 23 25 using System.Drawing; 24 26 using System.Linq; 25 27 using System.Windows.Forms; 28 using HeuristicLab.Common; 29 using HeuristicLab.Common.Resources; 26 30 using HeuristicLab.Core; 27 31 using HeuristicLab.PluginInfrastructure; … … 29 33 namespace HeuristicLab.Optimizer { 30 34 internal partial class NewItemDialog : Form { 31 private bool initialized; 35 private bool isInitialized; 36 37 private readonly List<TreeNode> treeNodes; 38 private string currentSearchString; 39 40 private Type selectedType; 41 public Type SelectedType { 42 get { return selectedType; } 43 private set { 44 if (value != selectedType) { 45 selectedType = value; 46 OnSelectedTypeChanged(); 47 } 48 } 49 } 32 50 33 51 private IItem item; … … 37 55 38 56 public NewItemDialog() { 39 initialized = false; 57 InitializeComponent(); 58 treeNodes = new List<TreeNode>(); 59 currentSearchString = string.Empty; 40 60 item = null; 41 InitializeComponent();61 SelectedTypeChanged += this_SelectedTypeChanged; 42 62 } 43 63 44 64 private void NewItemDialog_Load(object sender, EventArgs e) { 45 if (!initialized) { 46 var categories = from t in ApplicationManager.Manager.GetTypes(typeof(IItem)) 47 where CreatableAttribute.IsCreatable(t) 48 orderby CreatableAttribute.GetCategory(t), ItemAttribute.GetName(t), ItemAttribute.GetVersion(t) ascending 49 group t by CreatableAttribute.GetCategory(t) into c 50 select c; 51 52 itemsListView.SmallImageList = new ImageList(); 53 itemsListView.SmallImageList.Images.Add(HeuristicLab.Common.Resources.VSImageLibrary.Class); // default icon 54 foreach (var category in categories) { 55 ListViewGroup group = new ListViewGroup(category.Key); 56 itemsListView.Groups.Add(group); 57 foreach (var creatable in category) { 58 string name = ItemAttribute.GetName(creatable); 59 string version = ItemAttribute.GetVersion(creatable).ToString(); 60 string description = ItemAttribute.GetDescription(creatable); 61 ListViewItem item = new ListViewItem(new string[] { name, version, description }, group); 62 item.ImageIndex = 0; 63 Image image = ItemAttribute.GetImage(creatable); 64 if (image != null) { 65 itemsListView.SmallImageList.Images.Add(image); 66 item.ImageIndex = itemsListView.SmallImageList.Images.Count - 1; 67 } 68 item.Tag = creatable; 69 itemsListView.Items.Add(item); 65 if (isInitialized) return; 66 67 // Sorted by hasOrdering to create category nodes first with concrete ordering. 68 // Items with categoryname without ordering are inserted afterwards correctly 69 var categories = 70 from type in ApplicationManager.Manager.GetTypes(typeof(IItem)) 71 where CreatableAttribute.IsCreatable(type) 72 let category = CreatableAttribute.GetCategory(type) 73 let hasOrdering = category.Contains(CreatableAttribute.Categories.OrderToken) 74 let name = ItemAttribute.GetName(type) 75 let priority = CreatableAttribute.GetPriority(type) 76 let version = ItemAttribute.GetVersion(type) 77 orderby category, hasOrdering descending, priority, name, version ascending 78 group type by category into categoryGroup 79 select categoryGroup; 80 81 var rootNode = CreateCategoryTree(categories); 82 CreateItemNodes(rootNode, categories); 83 84 foreach (TreeNode topNode in rootNode.Nodes) 85 treeNodes.Add(topNode); 86 foreach (var node in treeNodes) 87 typesTreeView.Nodes.Add((TreeNode)node.Clone()); 88 89 typesTreeView.TreeViewNodeSorter = new ItemTreeNodeComparer(); 90 typesTreeView.Sort(); 91 92 isInitialized = true; 93 } 94 95 private TreeNode CreateCategoryTree(IEnumerable<IGrouping<string, Type>> categories) { 96 imageList.Images.Add(VSImageLibrary.Class); // default icon 97 imageList.Images.Add(VSImageLibrary.Namespace); // plugins 98 99 var rootNode = new TreeNode(); 100 101 // CategoryNode 102 // Tag: raw string, used for sorting, e.g. 1$$$Algorithms###2$$$Single Solution 103 // Name: full name = combined category name with parent categories, used for finding nodes in tree, e.g. Algorithms###Single Solution 104 // Text: category name, used for displaying on node itself, e.g. Single Solution 105 106 foreach (var category in categories) { 107 var rawName = category.Key; 108 string fullName = CreatableAttribute.Categories.GetFullName(rawName); 109 string name = CreatableAttribute.Categories.GetName(rawName); 110 111 // Skip categories with same full name because the raw name can still be different (missing order) 112 if (rootNode.Nodes.Find(fullName, true).Length > 0) 113 continue; 114 115 var categoryNode = new TreeNode(name, 1, 1) { 116 Name = fullName, 117 Tag = rawName 118 }; 119 120 var parents = CreatableAttribute.Categories.GetParentRawNames(rawName); 121 var parentNode = FindOrCreateParentNode(rootNode, parents); 122 if (parentNode != null) 123 parentNode.Nodes.Add(categoryNode); 124 else 125 rootNode.Nodes.Add(categoryNode); 126 } 127 128 return rootNode; 129 } 130 private TreeNode FindOrCreateParentNode(TreeNode node, IEnumerable<string> rawParentNames) { 131 TreeNode parentNode = null; 132 string rawName = null; 133 foreach (string rawParentName in rawParentNames) { 134 rawName = rawName == null ? rawParentName : rawName + CreatableAttribute.Categories.SplitToken + rawParentName; 135 var fullName = CreatableAttribute.Categories.GetFullName(rawName); 136 parentNode = node.Nodes.Find(fullName, false).SingleOrDefault(); 137 if (parentNode == null) { 138 var name = CreatableAttribute.Categories.GetName(rawName); 139 parentNode = new TreeNode(name, 1, 1) { 140 Name = fullName, 141 Tag = rawName 142 }; 143 node.Nodes.Add(parentNode); 144 } 145 node = parentNode; 146 } 147 return parentNode; 148 } 149 private void CreateItemNodes(TreeNode node, IEnumerable<IGrouping<string, Type>> categories) { 150 foreach (var category in categories) { 151 var fullName = CreatableAttribute.Categories.GetFullName(category.Key); 152 var categoryNode = node.Nodes.Find(fullName, true).Single(); 153 foreach (var creatable in category) { 154 var itemNode = CreateItemNode(creatable); 155 itemNode.Name = itemNode.Name + ":" + fullName; 156 categoryNode.Nodes.Add(itemNode); 157 } 158 } 159 } 160 private TreeNode CreateItemNode(Type creatable) { 161 string name = ItemAttribute.GetName(creatable); 162 163 var itemNode = new TreeNode(name) { 164 ImageIndex = 0, 165 Tag = creatable, 166 Name = name 167 }; 168 169 var image = ItemAttribute.GetImage(creatable); 170 if (image != null) { 171 imageList.Images.Add(image); 172 itemNode.ImageIndex = imageList.Images.Count - 1; 173 } 174 itemNode.SelectedImageIndex = itemNode.ImageIndex; 175 176 return itemNode; 177 } 178 179 private void NewItemDialog_Shown(object sender, EventArgs e) { 180 searchTextBox.Text = string.Empty; 181 searchTextBox.Focus(); 182 SelectedType = null; 183 typesTreeView.SelectedNode = null; 184 UpdateDescription(); 185 186 foreach (TreeNode node in typesTreeView.Nodes) 187 node.Expand(); 188 typesTreeView.Nodes[0].EnsureVisible(); 189 } 190 191 public virtual void Filter(string searchString) { 192 if (InvokeRequired) { 193 Invoke(new Action<string>(Filter), searchString); 194 } else { 195 searchString = searchString.ToLower(); 196 var selectedNode = typesTreeView.SelectedNode; 197 198 if (!searchString.Contains(currentSearchString)) { 199 typesTreeView.BeginUpdate(); 200 // expand search -> restore all tree nodes 201 typesTreeView.Nodes.Clear(); 202 foreach (TreeNode node in treeNodes) 203 typesTreeView.Nodes.Add((TreeNode)node.Clone()); 204 typesTreeView.EndUpdate(); 205 } 206 207 // remove nodes 208 typesTreeView.BeginUpdate(); 209 var searchTokens = searchString.Split(' '); 210 int i = 0; 211 while (i < typesTreeView.Nodes.Count) { 212 var categoryNode = typesTreeView.Nodes[i]; 213 bool remove = FilterNode(categoryNode, searchTokens); 214 if (remove) 215 typesTreeView.Nodes.RemoveAt(i); 216 else i++; 217 } 218 typesTreeView.EndUpdate(); 219 currentSearchString = searchString; 220 221 // select first item 222 typesTreeView.BeginUpdate(); 223 var firstNode = FirstVisibleNode; 224 while (firstNode != null && !(firstNode.Tag is Type)) 225 firstNode = firstNode.NextVisibleNode; 226 if (firstNode != null) 227 typesTreeView.SelectedNode = firstNode; 228 229 if (typesTreeView.Nodes.Count == 0) { 230 SelectedType = null; 231 typesTreeView.Enabled = false; 232 } else { 233 SetTreeNodeVisibility(); 234 typesTreeView.Enabled = true; 235 } 236 typesTreeView.EndUpdate(); 237 238 RestoreSelectedNode(selectedNode); 239 UpdateDescription(); 240 } 241 } 242 243 private bool FilterNode(TreeNode node, string[] searchTokens) { 244 if (node.Tag is string) { // Category node 245 int i = 0; 246 while (i < node.Nodes.Count) { 247 bool remove = FilterNode(node.Nodes[i], searchTokens); 248 if (remove) 249 node.Nodes.RemoveAt(i); 250 else i++; 251 } 252 return node.Nodes.Count == 0; 253 } if (node.Tag is Type) { // Type node 254 var text = node.Text; 255 if (searchTokens.Any(searchToken => !text.ToLower().Contains(searchToken))) { 256 var typeTag = (Type)node.Tag; 257 if (typeTag == SelectedType) { 258 SelectedType = null; 259 typesTreeView.SelectedNode = null; 70 260 } 71 } 72 for (int i = 0; i < itemsListView.Columns.Count; i++) 73 itemsListView.Columns[i].AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent); 74 initialized = true; 75 } 76 } 77 78 private void NewItemDialog_Shown(object sender, EventArgs e) { 79 item = null; 80 } 81 82 private void itemTypesListView_SelectedIndexChanged(object sender, EventArgs e) { 83 okButton.Enabled = itemsListView.SelectedItems.Count == 1; 84 } 261 return true; 262 } 263 return false; 264 } 265 throw new InvalidOperationException("Encountered neither a category nor a creatable node during tree traversal."); 266 } 267 268 protected virtual void UpdateDescription() { 269 itemDescriptionTextBox.Text = string.Empty; 270 pluginDescriptionTextBox.Text = string.Empty; 271 pluginTextBox.Text = string.Empty; 272 versionTextBox.Text = string.Empty; 273 274 if (typesTreeView.SelectedNode != null) { 275 var node = typesTreeView.SelectedNode; 276 string category = node.Tag as string; 277 if (category != null) { 278 itemDescriptionTextBox.Text = string.Join(" - ", node.Name.Split(new[] { CreatableAttribute.Categories.SplitToken }, StringSplitOptions.RemoveEmptyEntries)); 279 } 280 Type type = node.Tag as Type; 281 if (type != null) { 282 string description = ItemAttribute.GetDescription(type); 283 var version = ItemAttribute.GetVersion(type); 284 var plugin = ApplicationManager.Manager.GetDeclaringPlugin(type); 285 if (description != null) 286 itemDescriptionTextBox.Text = description; 287 if (plugin != null) { 288 pluginTextBox.Text = plugin.Name; 289 pluginDescriptionTextBox.Text = plugin.Description; 290 } 291 if (version != null) 292 versionTextBox.Text = version.ToString(); 293 } 294 } else if (typesTreeView.Nodes.Count == 0) { 295 itemDescriptionTextBox.Text = "No types found"; 296 } 297 } 298 299 #region Events 300 public event EventHandler SelectedTypeChanged; 301 protected virtual void OnSelectedTypeChanged() { 302 if (SelectedTypeChanged != null) 303 SelectedTypeChanged(this, EventArgs.Empty); 304 } 305 #endregion 306 307 #region Control Events 308 protected virtual void searchTextBox_TextChanged(object sender, EventArgs e) { 309 Filter(searchTextBox.Text); 310 } 311 312 protected virtual void itemsTreeView_AfterSelect(object sender, TreeViewEventArgs e) { 313 if (typesTreeView.SelectedNode == null) SelectedType = null; 314 else SelectedType = typesTreeView.SelectedNode.Tag as Type; 315 UpdateDescription(); 316 } 317 318 protected virtual void itemsTreeView_VisibleChanged(object sender, EventArgs e) { 319 if (Visible) SetTreeNodeVisibility(); 320 } 321 #endregion 322 323 #region Helpers 324 private void RestoreSelectedNode(TreeNode selectedNode) { 325 if (selectedNode != null) { 326 var node = typesTreeView.Nodes.Find(selectedNode.Name, true).SingleOrDefault(); 327 if (node != null) 328 typesTreeView.SelectedNode = node; 329 if (typesTreeView.SelectedNode == null) 330 SelectedType = null; 331 } 332 } 333 private void SetTreeNodeVisibility() { 334 TreeNode selectedNode = typesTreeView.SelectedNode; 335 if (string.IsNullOrEmpty(currentSearchString) && (typesTreeView.Nodes.Count > 1)) { 336 typesTreeView.CollapseAll(); 337 if (selectedNode != null) typesTreeView.SelectedNode = selectedNode; 338 } else { 339 typesTreeView.ExpandAll(); 340 } 341 if (selectedNode != null) selectedNode.EnsureVisible(); 342 } 343 #endregion 85 344 86 345 private void okButton_Click(object sender, EventArgs e) { 87 if ( itemsListView.SelectedItems.Count == 1) {88 item = (IItem)Activator.CreateInstance( (Type)itemsListView.SelectedItems[0].Tag);346 if (SelectedType != null) { 347 item = (IItem)Activator.CreateInstance(SelectedType); 89 348 DialogResult = DialogResult.OK; 90 349 Close(); 91 350 } 92 351 } 93 private void itemT ypesListView_DoubleClick(object sender, EventArgs e) {94 if ( itemsListView.SelectedItems.Count == 1) {95 item = (IItem)Activator.CreateInstance( (Type)itemsListView.SelectedItems[0].Tag);352 private void itemTreeView_DoubleClick(object sender, EventArgs e) { 353 if (SelectedType != null) { 354 item = (IItem)Activator.CreateInstance(SelectedType); 96 355 DialogResult = DialogResult.OK; 97 356 Close(); 98 357 } 99 358 } 359 private void this_SelectedTypeChanged(object sender, EventArgs e) { 360 okButton.Enabled = SelectedType != null; 361 } 362 363 private TreeNode toolStripMenuNode; 364 private void typesTreeView_MouseDown(object sender, MouseEventArgs e) { 365 if (e.Button == MouseButtons.Right) { 366 Point coordinates = typesTreeView.PointToClient(Cursor.Position); 367 toolStripMenuNode = typesTreeView.GetNodeAt(coordinates); 368 369 if (toolStripMenuNode != null && coordinates.X >= toolStripMenuNode.Bounds.Left && 370 coordinates.X <= toolStripMenuNode.Bounds.Right) { 371 typesTreeView.SelectedNode = toolStripMenuNode; 372 373 expandToolStripMenuItem.Enabled = 374 expandToolStripMenuItem.Visible = !toolStripMenuNode.IsExpanded && toolStripMenuNode.Nodes.Count > 0; 375 collapseToolStripMenuItem.Enabled = collapseToolStripMenuItem.Visible = toolStripMenuNode.IsExpanded; 376 } else { 377 expandToolStripMenuItem.Enabled = expandToolStripMenuItem.Visible = false; 378 collapseToolStripMenuItem.Enabled = collapseToolStripMenuItem.Visible = false; 379 } 380 expandAllToolStripMenuItem.Enabled = 381 expandAllToolStripMenuItem.Visible = 382 !typesTreeView.Nodes.OfType<TreeNode>().All(x => TreeNodeIsFullyExpanded(x)); 383 collapseAllToolStripMenuItem.Enabled = 384 collapseAllToolStripMenuItem.Visible = typesTreeView.Nodes.OfType<TreeNode>().Any(x => x.IsExpanded); 385 if (contextMenuStrip.Items.Cast<ToolStripMenuItem>().Any(item => item.Enabled)) 386 contextMenuStrip.Show(Cursor.Position); 387 } 388 } 389 private bool TreeNodeIsFullyExpanded(TreeNode node) { 390 return (node.Nodes.Count == 0) || (node.IsExpanded && node.Nodes.OfType<TreeNode>().All(x => TreeNodeIsFullyExpanded(x))); 391 } 392 393 private void expandToolStripMenuItem_Click(object sender, EventArgs e) { 394 typesTreeView.BeginUpdate(); 395 if (toolStripMenuNode != null) toolStripMenuNode.ExpandAll(); 396 typesTreeView.EndUpdate(); 397 } 398 private void expandAllToolStripMenuItem_Click(object sender, EventArgs e) { 399 typesTreeView.BeginUpdate(); 400 typesTreeView.ExpandAll(); 401 typesTreeView.EndUpdate(); 402 } 403 private void collapseToolStripMenuItem_Click(object sender, EventArgs e) { 404 typesTreeView.BeginUpdate(); 405 if (toolStripMenuNode != null) toolStripMenuNode.Collapse(); 406 typesTreeView.EndUpdate(); 407 } 408 private void collapseAllToolStripMenuItem_Click(object sender, EventArgs e) { 409 typesTreeView.BeginUpdate(); 410 typesTreeView.CollapseAll(); 411 typesTreeView.EndUpdate(); 412 } 413 414 private void clearSearchButton_Click(object sender, EventArgs e) { 415 searchTextBox.Text = string.Empty; 416 searchTextBox.Focus(); 417 } 418 419 private void searchTextBox_KeyDown(object sender, KeyEventArgs e) { 420 if (typesTreeView.Nodes.Count == 0) 421 return; 422 423 if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down) { 424 var selectedNode = typesTreeView.SelectedNode; 425 426 if (selectedNode == null) { // nothing selected => select first 427 if (e.KeyCode == Keys.Down) typesTreeView.SelectedNode = FirstVisibleNode; 428 } else { 429 if (e.KeyCode == Keys.Down && selectedNode.NextVisibleNode != null) 430 typesTreeView.SelectedNode = selectedNode.NextVisibleNode; 431 if (e.KeyCode == Keys.Up && selectedNode.PrevVisibleNode != null) 432 typesTreeView.SelectedNode = selectedNode.PrevVisibleNode; 433 } 434 e.Handled = true; 435 } 436 } 437 438 private TreeNode FirstVisibleNode { 439 get { 440 return typesTreeView.Nodes.Count > 0 ? typesTreeView.Nodes[0] : null; 441 } 442 } 443 444 private class ItemTreeNodeComparer : IComparer { 445 private static readonly IComparer<string> Comparer = new NaturalStringComparer(); 446 public int Compare(object x, object y) { 447 var lhs = (TreeNode)x; 448 var rhs = (TreeNode)y; 449 450 if (lhs.Tag is string && rhs.Tag is string) { 451 return Comparer.Compare((string)lhs.Tag, (string)rhs.Tag); 452 } 453 if (lhs.Tag is string) { 454 return -1; 455 } 456 return 1; 457 } 458 } 100 459 } 101 460 }
Note: See TracChangeset
for help on using the changeset viewer.