Free cookie consent management tool by TermsFeed Policy Generator

source: branches/GBT/HeuristicLab.Optimizer/3.3/NewItemDialog.cs @ 12495

Last change on this file since 12495 was 12495, checked in by gkronber, 9 years ago

#2261: merged trunk changes to branch
r12494
#2403: added a null check in the MatlabParameterVectorEvaluator to prevent exceptions when clearstate is called


r12493
#2369: added support for squared errors and relative errors to error-characteristic-curve view


r12492
#2392: implemented PearsonsRCalculator to fix incorrect correlation values in the correlation matrix.


r12491
#2402 don't set task state to waiting when it fails


r12490
#2401 added missing Mono.Cecil plugin dependency


r12488
#2400 - Interfaces for Capaciated-, PickupAndDelivery- and TimeWindowed-ProblemInstances now specify an additional penalty parameter to set the current penalty factor for the constraint relaxation. - The setter of the penalty-property in ...


r12485
#2374 made RegressionSolution and ClassificationSolution non-abstract


r12482
#2320: Fixed warnings in unit test solutions introduced in r12420 by marking methods as obsolete.


r12481
#2320: Fixed AfterDeserialization of GEArtifialAntEvaluator.


r12480
#2320: Fixed error in symbolicexpressiontree crossover regarding the wiring of lookup parameters if persisted file is loaded.


r12479
#2397 moved GeoIP project into ExtLibs


r12478
#2329 fixed bug in simple code editor


r12476
#2331 removed outdated plugins


r12475
#2368 fixed compile warnings


r12474
#2399 worked on Mono project prepare script


r12473
#2329 added a simple code editor for Linux


r12472
#2399 - fixed MathJax.js file name - worked on Mono project prepare script


r12471
#2399 worked on Mono project prepare script


r12470
#2399 fixed pre-build events in project files


r12465
#2399 worked on mono project prepare script


r12464
#2399 added patch to project


r12463
#2399 fixed EPPlus so that it compiles on Linux


r12461
#2398: Skip root and start symbols when calculating impacts and replacement values in the pruning operators.


r12458
#2354 show label when no data is displayed and don't show the legend


r12457
#2353 removed duplicated call to Any() in Hive Status page


r12456
#2368 fixed modifier


r12455
#2368 added support in persistence for typecaches in streams


r12445
#2394: Changed Web.config compilation from debug to release to force script bundling. Changed history loading type from lazy to eager loading to increase performance. Fixed "getCoreStatus" typo in statusCtrl.js


r12443
#2394: Fixed UserTaskQuery and GetStatusHistory in the WebApp.Status plugin


r12442
#2394 added nuget folders to svn ignore list


r12435
#2394: Improved PluginManager and updated hive status monitor.


r12434
#2396 added symbolic expression tree formatter for C#


r12433
#2395: Minor change in DoubleValue.GetValue.


r12432
#2395 Use simple round-trip format for doubles because G17 prints some strange numbers (20.22 to 20.219999999999999999). Some accuracy can still be lost on 64bit machines, but should be very rare and minimal. double.MaxValue can still be pa...


r12431
#2395 Fixed parsing issues by using the G17 format.


r12430
#2394 added missing package config


r12429
#2394 added missing package config


r12428
#2394 added web app and status page to trunk


r12424
#2320: Adapted plugin file and updated project file of SymbolicExpressionTreeEncoding.


r12422
#2320: Merged the encoding class and all accompanying changes in the trunk.


r12401
#2387 Fixed a bug where the automatic selection of the first element behaved differently for the NewItemDialog.


r12400
#2387 Forgot to commit a file.


r12399
#2387 - Added context-menu for expanding and collapsing tree-nodes. - Improve response time when expanding/collapsing all nodes for TypeSelector and NewItemDialog.


r12398
#2387 - Added clearSearch-button in TypeSelector. - Adapted behavior of TypeSelector and NewItemDialog that a selected node stays selected as long as it matches the search criteria.


r12397
#2387 - Adapted behavior of the matching in the TypeSelector that it behave the same as the NewItemDialog. The search string is tokenized by space and matches if all tokens are contained, (eg. "Sym Reg" matches "SymbolicRegression...")...


r12393
#2025 - Removed Expand/CollapseAll buttons. - Removed cycling of items.


r12392
#2386: Updated GetHashCode method in the EnumerableBoolEqualityComparer.


File size: 15.9 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2015 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;
24using System.Collections.Generic;
25using System.Drawing;
26using System.Linq;
27using System.Windows.Forms;
28using HeuristicLab.Core;
29using HeuristicLab.PluginInfrastructure;
30
31namespace HeuristicLab.Optimizer {
32  internal partial class NewItemDialog : Form {
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    }
48
49    private IItem item;
50    public IItem Item {
51      get { return item; }
52    }
53
54    public NewItemDialog() {
55      InitializeComponent();
56      treeNodes = new List<TreeNode>();
57      currentSearchString = string.Empty;
58      item = null;
59      SelectedTypeChanged += this_SelectedTypeChanged;
60    }
61
62    private void NewItemDialog_Load(object sender, EventArgs e) {
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;
240          }
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
323
324    private void okButton_Click(object sender, EventArgs e) {
325      if (SelectedType != null) {
326        item = (IItem)Activator.CreateInstance(SelectedType);
327        DialogResult = DialogResult.OK;
328        Close();
329      }
330    }
331    private void itemTreeView_DoubleClick(object sender, EventArgs e) {
332      if (SelectedType != null) {
333        item = (IItem)Activator.CreateInstance(SelectedType);
334        DialogResult = DialogResult.OK;
335        Close();
336      }
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    }
443  }
444}
Note: See TracBrowser for help on using the repository browser.