Changeset 12466 for branches/EnumValue in CreateExperiment/HeuristicLab.Optimizer/3.3/NewItemDialog.cs
- Timestamp:
- 06/18/15 11:17:50 (9 years ago)
- Location:
- branches/EnumValue in CreateExperiment/HeuristicLab.Optimizer
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/EnumValue in CreateExperiment/HeuristicLab.Optimizer
- Property svn:mergeinfo changed
-
branches/EnumValue in CreateExperiment/HeuristicLab.Optimizer/3.3/NewItemDialog.cs
r12012 r12466 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; … … 29 31 namespace HeuristicLab.Optimizer { 30 32 internal partial class NewItemDialog : Form { 31 private bool initialized; 33 private bool isInitialized; 34 35 private readonly List<TreeNode> treeNodes; 36 private string currentSearchString; 37 38 private Type selectedType; 39 public Type SelectedType { 40 get { return selectedType; } 41 private set { 42 if (value != selectedType) { 43 selectedType = value; 44 OnSelectedTypeChanged(); 45 } 46 } 47 } 32 48 33 49 private IItem item; … … 37 53 38 54 public NewItemDialog() { 39 initialized = false; 55 InitializeComponent(); 56 treeNodes = new List<TreeNode>(); 57 currentSearchString = string.Empty; 40 58 item = null; 41 InitializeComponent();59 SelectedTypeChanged += this_SelectedTypeChanged; 42 60 } 43 61 44 62 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); 63 if (isInitialized) return; 64 65 var categories = 66 from type in ApplicationManager.Manager.GetTypes(typeof(IItem)) 67 let category = CreatableAttribute.GetCategory(type) 68 let name = ItemAttribute.GetName(type) 69 let priority = CreatableAttribute.GetPriority(type) 70 let version = ItemAttribute.GetVersion(type) 71 where CreatableAttribute.IsCreatable(type) 72 orderby category, priority, name, version ascending 73 group type by category into categoryGroup 74 select categoryGroup; 75 76 var rootNode = CreateCategoryTree(categories); 77 CreateItemNodes(rootNode, categories); 78 79 foreach (TreeNode topNode in rootNode.Nodes) 80 treeNodes.Add(topNode); 81 foreach (var node in treeNodes) 82 typesTreeView.Nodes.Add((TreeNode)node.Clone()); 83 84 typesTreeView.TreeViewNodeSorter = new ItemTreeNodeComparer(); 85 typesTreeView.Sort(); 86 87 isInitialized = true; 88 } 89 90 private TreeNode CreateCategoryTree(IEnumerable<IGrouping<string, Type>> categories) { 91 imageList.Images.Add(HeuristicLab.Common.Resources.VSImageLibrary.Class); // default icon 92 imageList.Images.Add(HeuristicLab.Common.Resources.VSImageLibrary.Namespace); // plugins 93 94 var rootNode = new TreeNode(); 95 96 foreach (var category in categories) { 97 var fullName = category.Key; 98 var tokens = fullName.Split('#'); 99 var name = tokens.Last(); 100 var parents = tokens.Take(tokens.Length - 1); 101 102 var categoryNode = new TreeNode(name, imageIndex: 1, selectedImageIndex: 1) { 103 Name = fullName, 104 Tag = fullName 105 }; 106 107 var parentNode = FindOrCreateParentNode(rootNode, parents); 108 if (parentNode != null) 109 parentNode.Nodes.Add(categoryNode); 110 else 111 rootNode.Nodes.Add(categoryNode); 112 } 113 114 return rootNode; 115 } 116 private TreeNode FindOrCreateParentNode(TreeNode node, IEnumerable<string> parentCategories) { 117 TreeNode parentNode = null; 118 string fullName = null; 119 foreach (string parentCategory in parentCategories) { 120 fullName = fullName == null ? parentCategory : fullName + "#" + parentCategory; 121 parentNode = node.Nodes.Find(fullName, searchAllChildren: false).SingleOrDefault(); 122 if (parentNode == null) { 123 parentNode = new TreeNode(parentCategory, imageIndex: 1, selectedImageIndex: 1) { 124 Name = fullName, 125 Tag = fullName 126 }; 127 node.Nodes.Add(parentNode); 128 } 129 node = parentNode; 130 } 131 return parentNode; 132 } 133 private void CreateItemNodes(TreeNode node, IEnumerable<IGrouping<string, Type>> categories) { 134 foreach (var category in categories) { 135 var categoryNode = node.Nodes.Find(category.Key, searchAllChildren: true).Single(); 136 foreach (var creatable in category) { 137 var itemNode = CreateItemNode(creatable); 138 itemNode.Name = itemNode.Name + ":" + category.Key; 139 categoryNode.Nodes.Add(itemNode); 140 } 141 } 142 } 143 private TreeNode CreateItemNode(Type creatable) { 144 string name = ItemAttribute.GetName(creatable); 145 146 var itemNode = new TreeNode(name) { 147 ImageIndex = 0, 148 Tag = creatable, 149 Name = name 150 }; 151 152 var image = ItemAttribute.GetImage(creatable); 153 if (image != null) { 154 imageList.Images.Add(image); 155 itemNode.ImageIndex = imageList.Images.Count - 1; 156 } 157 itemNode.SelectedImageIndex = itemNode.ImageIndex; 158 159 return itemNode; 160 } 161 162 private void NewItemDialog_Shown(object sender, EventArgs e) { 163 searchTextBox.Text = string.Empty; 164 searchTextBox.Focus(); 165 SelectedType = null; 166 typesTreeView.SelectedNode = null; 167 typesTreeView.CollapseAll(); 168 UpdateDescription(); 169 } 170 171 public virtual void Filter(string searchString) { 172 if (InvokeRequired) { 173 Invoke(new Action<string>(Filter), searchString); 174 } else { 175 searchString = searchString.ToLower(); 176 var selectedNode = typesTreeView.SelectedNode; 177 178 if (!searchString.Contains(currentSearchString)) { 179 typesTreeView.BeginUpdate(); 180 // expand search -> restore all tree nodes 181 typesTreeView.Nodes.Clear(); 182 foreach (TreeNode node in treeNodes) 183 typesTreeView.Nodes.Add((TreeNode)node.Clone()); 184 typesTreeView.EndUpdate(); 185 } 186 187 // remove nodes 188 typesTreeView.BeginUpdate(); 189 var searchTokens = searchString.Split(' '); 190 int i = 0; 191 while (i < typesTreeView.Nodes.Count) { 192 var categoryNode = typesTreeView.Nodes[i]; 193 bool remove = FilterNode(categoryNode, searchTokens); 194 if (remove) 195 typesTreeView.Nodes.RemoveAt(i); 196 else i++; 197 } 198 typesTreeView.EndUpdate(); 199 currentSearchString = searchString; 200 201 // select first item 202 typesTreeView.BeginUpdate(); 203 var firstNode = FirstVisibleNode; 204 while (firstNode != null && !(firstNode.Tag is Type)) 205 firstNode = firstNode.NextVisibleNode; 206 if (firstNode != null) 207 typesTreeView.SelectedNode = firstNode; 208 209 if (typesTreeView.Nodes.Count == 0) { 210 SelectedType = null; 211 typesTreeView.Enabled = false; 212 } else { 213 SetTreeNodeVisibility(); 214 typesTreeView.Enabled = true; 215 } 216 typesTreeView.EndUpdate(); 217 218 RestoreSelectedNode(selectedNode); 219 UpdateDescription(); 220 } 221 } 222 223 private bool FilterNode(TreeNode node, string[] searchTokens) { 224 if (node.Tag is string) { // Category node 225 int i = 0; 226 while (i < node.Nodes.Count) { 227 bool remove = FilterNode(node.Nodes[i], searchTokens); 228 if (remove) 229 node.Nodes.RemoveAt(i); 230 else i++; 231 } 232 return node.Nodes.Count == 0; 233 } if (node.Tag is Type) { // Type node 234 var text = node.Text; 235 if (searchTokens.Any(searchToken => !text.ToLower().Contains(searchToken))) { 236 var typeTag = (Type)node.Tag; 237 if (typeTag == SelectedType) { 238 SelectedType = null; 239 typesTreeView.SelectedNode = null; 70 240 } 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 } 241 return true; 242 } 243 return false; 244 } 245 throw new InvalidOperationException("Encountered neither a category nor a creatable node during tree traversal."); 246 } 247 248 protected virtual void UpdateDescription() { 249 itemDescriptionTextBox.Text = string.Empty; 250 pluginDescriptionTextBox.Text = string.Empty; 251 pluginTextBox.Text = string.Empty; 252 versionTextBox.Text = string.Empty; 253 254 if (typesTreeView.SelectedNode != null) { 255 string category = typesTreeView.SelectedNode.Tag as string; 256 if (category != null) { 257 itemDescriptionTextBox.Text = category; 258 } 259 Type type = typesTreeView.SelectedNode.Tag as Type; 260 if (type != null) { 261 string description = ItemAttribute.GetDescription(type); 262 var version = ItemAttribute.GetVersion(type); 263 var plugin = ApplicationManager.Manager.GetDeclaringPlugin(type); 264 if (description != null) 265 itemDescriptionTextBox.Text = description; 266 if (plugin != null) { 267 pluginTextBox.Text = plugin.Name; 268 pluginDescriptionTextBox.Text = plugin.Description; 269 } 270 if (version != null) 271 versionTextBox.Text = version.ToString(); 272 } 273 } else if (typesTreeView.Nodes.Count == 0) { 274 itemDescriptionTextBox.Text = "No types found"; 275 } 276 } 277 278 #region Events 279 public event EventHandler SelectedTypeChanged; 280 protected virtual void OnSelectedTypeChanged() { 281 if (SelectedTypeChanged != null) 282 SelectedTypeChanged(this, EventArgs.Empty); 283 } 284 #endregion 285 286 #region Control Events 287 protected virtual void searchTextBox_TextChanged(object sender, EventArgs e) { 288 Filter(searchTextBox.Text); 289 } 290 291 protected virtual void itemsTreeView_AfterSelect(object sender, TreeViewEventArgs e) { 292 if (typesTreeView.SelectedNode == null) SelectedType = null; 293 else SelectedType = typesTreeView.SelectedNode.Tag as Type; 294 UpdateDescription(); 295 } 296 297 protected virtual void itemsTreeView_VisibleChanged(object sender, EventArgs e) { 298 if (Visible) SetTreeNodeVisibility(); 299 } 300 #endregion 301 302 #region Helpers 303 private void RestoreSelectedNode(TreeNode selectedNode) { 304 if (selectedNode != null) { 305 var node = typesTreeView.Nodes.Find(selectedNode.Name, searchAllChildren: true).SingleOrDefault(); 306 if (node != null) 307 typesTreeView.SelectedNode = node; 308 if (typesTreeView.SelectedNode == null) 309 SelectedType = null; 310 } 311 } 312 private void SetTreeNodeVisibility() { 313 TreeNode selectedNode = typesTreeView.SelectedNode; 314 if (string.IsNullOrEmpty(currentSearchString) && (typesTreeView.Nodes.Count > 1)) { 315 typesTreeView.CollapseAll(); 316 if (selectedNode != null) typesTreeView.SelectedNode = selectedNode; 317 } else { 318 typesTreeView.ExpandAll(); 319 } 320 if (selectedNode != null) selectedNode.EnsureVisible(); 321 } 322 #endregion 85 323 86 324 private void okButton_Click(object sender, EventArgs e) { 87 if ( itemsListView.SelectedItems.Count == 1) {88 item = (IItem)Activator.CreateInstance( (Type)itemsListView.SelectedItems[0].Tag);325 if (SelectedType != null) { 326 item = (IItem)Activator.CreateInstance(SelectedType); 89 327 DialogResult = DialogResult.OK; 90 328 Close(); 91 329 } 92 330 } 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);331 private void itemTreeView_DoubleClick(object sender, EventArgs e) { 332 if (SelectedType != null) { 333 item = (IItem)Activator.CreateInstance(SelectedType); 96 334 DialogResult = DialogResult.OK; 97 335 Close(); 98 336 } 99 337 } 338 private void this_SelectedTypeChanged(object sender, EventArgs e) { 339 okButton.Enabled = SelectedType != null; 340 } 341 342 private TreeNode toolStripMenuNode = null; 343 private void typesTreeView_MouseDown(object sender, MouseEventArgs e) { 344 if (e.Button == MouseButtons.Right) { 345 Point coordinates = typesTreeView.PointToClient(Cursor.Position); 346 toolStripMenuNode = typesTreeView.GetNodeAt(coordinates); 347 348 if (toolStripMenuNode != null && coordinates.X >= toolStripMenuNode.Bounds.Left && 349 coordinates.X <= toolStripMenuNode.Bounds.Right) { 350 typesTreeView.SelectedNode = toolStripMenuNode; 351 352 expandToolStripMenuItem.Enabled = 353 expandToolStripMenuItem.Visible = !toolStripMenuNode.IsExpanded && toolStripMenuNode.Nodes.Count > 0; 354 collapseToolStripMenuItem.Enabled = collapseToolStripMenuItem.Visible = toolStripMenuNode.IsExpanded; 355 } else { 356 expandToolStripMenuItem.Enabled = expandToolStripMenuItem.Visible = false; 357 collapseToolStripMenuItem.Enabled = collapseToolStripMenuItem.Visible = false; 358 } 359 expandAllToolStripMenuItem.Enabled = 360 expandAllToolStripMenuItem.Visible = 361 !typesTreeView.Nodes.OfType<TreeNode>().All(x => TreeNodeIsFullyExpanded(x)); 362 collapseAllToolStripMenuItem.Enabled = 363 collapseAllToolStripMenuItem.Visible = typesTreeView.Nodes.OfType<TreeNode>().Any(x => x.IsExpanded); 364 if (contextMenuStrip.Items.Cast<ToolStripMenuItem>().Any(item => item.Enabled)) 365 contextMenuStrip.Show(Cursor.Position); 366 } 367 } 368 private bool TreeNodeIsFullyExpanded(TreeNode node) { 369 return (node.Nodes.Count == 0) || (node.IsExpanded && node.Nodes.OfType<TreeNode>().All(x => TreeNodeIsFullyExpanded(x))); 370 } 371 372 private void expandToolStripMenuItem_Click(object sender, EventArgs e) { 373 typesTreeView.BeginUpdate(); 374 if (toolStripMenuNode != null) toolStripMenuNode.ExpandAll(); 375 typesTreeView.EndUpdate(); 376 } 377 private void expandAllToolStripMenuItem_Click(object sender, EventArgs e) { 378 typesTreeView.BeginUpdate(); 379 typesTreeView.ExpandAll(); 380 typesTreeView.EndUpdate(); 381 } 382 private void collapseToolStripMenuItem_Click(object sender, EventArgs e) { 383 typesTreeView.BeginUpdate(); 384 if (toolStripMenuNode != null) toolStripMenuNode.Collapse(); 385 typesTreeView.EndUpdate(); 386 } 387 private void collapseAllToolStripMenuItem_Click(object sender, EventArgs e) { 388 typesTreeView.BeginUpdate(); 389 typesTreeView.CollapseAll(); 390 typesTreeView.EndUpdate(); 391 } 392 393 private void clearSearchButton_Click(object sender, EventArgs e) { 394 searchTextBox.Text = string.Empty; 395 searchTextBox.Focus(); 396 } 397 398 private void searchTextBox_KeyDown(object sender, KeyEventArgs e) { 399 if (typesTreeView.Nodes.Count == 0) 400 return; 401 402 if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down) { 403 var selectedNode = typesTreeView.SelectedNode; 404 405 if (selectedNode == null) { // nothing selected => select first 406 if (e.KeyCode == Keys.Down) typesTreeView.SelectedNode = FirstVisibleNode; 407 } else { 408 if (e.KeyCode == Keys.Down && selectedNode.NextVisibleNode != null) 409 typesTreeView.SelectedNode = selectedNode.NextVisibleNode; 410 if (e.KeyCode == Keys.Up && selectedNode.PrevVisibleNode != null) 411 typesTreeView.SelectedNode = selectedNode.PrevVisibleNode; 412 } 413 e.Handled = true; 414 } 415 } 416 417 private TreeNode FirstVisibleNode { 418 get { 419 return typesTreeView.Nodes.Count > 0 ? typesTreeView.Nodes[0] : null; 420 } 421 } 422 private TreeNode LastVisibleNode { 423 get { 424 var node = FirstVisibleNode; 425 while (node != null && node.NextVisibleNode != null) node = node.NextVisibleNode; 426 return node; 427 } 428 } 429 430 private class ItemTreeNodeComparer : IComparer { 431 public int Compare(object x, object y) { 432 var lhs = (TreeNode)x; 433 var rhs = (TreeNode)y; 434 435 if (lhs.Tag is string && rhs.Tag is string) { 436 return lhs.Name.CompareTo(rhs.Name); 437 } else if (lhs.Tag is string) { 438 return -1; 439 } else 440 return 1; 441 } 442 } 100 443 } 101 444 }
Note: See TracChangeset
for help on using the changeset viewer.