Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Core.Views/3.3/TypeSelector.cs @ 4826

Last change on this file since 4826 was 4826, checked in by epitzer, 14 years ago

Fully display the tree view after repopulating, which creates handles for all nodes and no problems occur when deleting nodes. (#1277)

File size: 14.2 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 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.Generic;
24using System.Linq;
25using System.Text;
26using System.Windows.Forms;
27using HeuristicLab.Common;
28using HeuristicLab.PluginInfrastructure;
29
30namespace HeuristicLab.Core.Views {
31  public partial class TypeSelector : UserControl {
32    protected List<TreeNode> treeNodes;
33    protected string currentSearchString;
34    protected TypeSelectorDialog typeSelectorDialog;
35
36    protected Type baseType;
37    public Type BaseType {
38      get { return baseType; }
39    }
40    protected bool showNotInstantiableTypes;
41    public bool ShowNotInstantiableTypes {
42      get { return showNotInstantiableTypes; }
43    }
44    protected bool showGenericTypes;
45    public bool ShowGenericTypes {
46      get { return showGenericTypes; }
47    }
48    public string Caption {
49      get { return typesGroupBox.Text; }
50      set {
51        if (InvokeRequired)
52          Invoke(new Action<string>(delegate(string s) { Caption = s; }), value);
53        else
54          typesGroupBox.Text = value;
55      }
56    }
57    public TreeView TypesTreeView {
58      get { return typesTreeView; }
59    }
60    protected Type selectedType;
61    public Type SelectedType {
62      get { return selectedType; }
63      private set {
64        if (value != selectedType) {
65          selectedType = value;
66          OnSelectedTypeChanged();
67        }
68      }
69    }
70
71    public TypeSelector() {
72      InitializeComponent();
73      treeNodes = new List<TreeNode>();
74      currentSearchString = string.Empty;
75      selectedType = null;
76    }
77
78    public virtual void Configure(Type baseType, bool showNotInstantiableTypes, bool showGenericTypes) {
79      if (baseType == null) throw new ArgumentNullException();
80      if (InvokeRequired)
81        Invoke(new Action<Type, bool, bool>(Configure), baseType, showNotInstantiableTypes, showGenericTypes);
82      else {
83        this.baseType = baseType;
84        this.showNotInstantiableTypes = showNotInstantiableTypes;
85        this.showGenericTypes = showGenericTypes;
86
87        typeParametersSplitContainer.Panel2Collapsed = !showGenericTypes;
88
89        TreeNode selectedNode = typesTreeView.SelectedNode;
90        typesTreeView.Nodes.Clear();
91        treeNodes.Clear();
92        imageList.Images.Clear();
93        imageList.Images.Add(HeuristicLab.Common.Resources.VS2008ImageLibrary.Class);      // default icon
94        imageList.Images.Add(HeuristicLab.Common.Resources.VS2008ImageLibrary.Namespace);  // plugins
95        imageList.Images.Add(HeuristicLab.Common.Resources.VS2008ImageLibrary.Interface);  // interfaces
96        imageList.Images.Add(HeuristicLab.Common.Resources.VS2008ImageLibrary.Template);   // generic types
97
98        var plugins = from p in ApplicationManager.Manager.Plugins
99                      orderby p.Name, p.Version ascending
100                      select p;
101        foreach (IPluginDescription plugin in plugins) {
102          TreeNode pluginNode = new TreeNode();
103          pluginNode.Text = plugin.Name;
104          pluginNode.ImageIndex = 1;
105          pluginNode.SelectedImageIndex = pluginNode.ImageIndex;
106          pluginNode.Tag = plugin;
107
108          var types = from t in ApplicationManager.Manager.GetTypes(BaseType, plugin, false)
109                      orderby t.Name ascending
110                      select t;
111          foreach (Type type in types) {
112            bool valid = true;
113            valid = valid && (ShowGenericTypes || !type.ContainsGenericParameters);
114            valid = valid && (ShowNotInstantiableTypes || !type.IsAbstract);
115            valid = valid && (ShowNotInstantiableTypes || !type.IsInterface);
116            valid = valid && (ShowNotInstantiableTypes || !type.HasElementType);
117            valid = valid && (ShowNotInstantiableTypes || type.GetConstructor(Type.EmptyTypes) != null); //check for public default ctor
118            if (valid) {
119              TreeNode typeNode = new TreeNode();
120              string name = ItemAttribute.GetName(type);
121              typeNode.Text = name != null ? name : type.GetPrettyName();
122              typeNode.ImageIndex = 0;
123              if (type.IsInterface) typeNode.ImageIndex = 2;
124              else if (type.ContainsGenericParameters) typeNode.ImageIndex = 3;
125              else if (imageList.Images.ContainsKey(type.FullName)) typeNode.ImageIndex = imageList.Images.IndexOfKey(type.FullName);
126              else if (typeof(IItem).IsAssignableFrom(type) && !type.IsInterface && !type.IsAbstract) {
127                try {
128                  IItem item = (IItem)Activator.CreateInstance(type);
129                  imageList.Images.Add(type.FullName, item.ItemImage);
130                  typeNode.ImageIndex = imageList.Images.IndexOfKey(type.FullName);
131                } catch (Exception) { }
132              }
133              typeNode.SelectedImageIndex = typeNode.ImageIndex;
134              typeNode.Tag = type;
135              pluginNode.Nodes.Add(typeNode);
136            }
137          }
138          if (pluginNode.Nodes.Count > 0)
139            treeNodes.Add(pluginNode);
140        }
141        foreach (TreeNode node in treeNodes)
142          typesTreeView.Nodes.Add((TreeNode)node.Clone());
143        RestoreSelectedNode(selectedNode);
144        Filter(searchTextBox.Text);
145
146        UpdateTypeParameters();
147      }
148    }
149
150    public virtual void Filter(string searchString) {
151      if (InvokeRequired)
152        Invoke(new Action<string>(Filter), searchString);
153      else {
154        searchString = searchString.ToLower();
155
156        if (!searchString.Contains(currentSearchString)) {
157          typesTreeView.BeginUpdate();
158          // expand search -> restore all tree nodes
159          TreeNode selectedNode = typesTreeView.SelectedNode;
160          typesTreeView.Nodes.Clear();
161          foreach (TreeNode node in treeNodes)
162            typesTreeView.Nodes.Add((TreeNode)node.Clone());
163          RestoreSelectedNode(selectedNode);
164          typesTreeView.EndUpdate();
165        }
166
167
168        // remove nodes
169        typesTreeView.BeginUpdate();
170        int i = 0;
171        while (i < typesTreeView.Nodes.Count) {
172          int j = 0;
173          while (j < typesTreeView.Nodes[i].Nodes.Count) {
174            if (!typesTreeView.Nodes[i].Nodes[j].Text.ToLower().Contains(searchString))
175              typesTreeView.Nodes[i].Nodes[j].Remove();
176            else
177              j++;
178          }
179          if (typesTreeView.Nodes[i].Nodes.Count == 0)
180            typesTreeView.Nodes[i].Remove();
181          else
182            i++;
183        }
184        typesTreeView.EndUpdate();
185        currentSearchString = searchString;
186
187        // if there is just one type node left, select by default
188        if (typesTreeView.Nodes.Count == 1) {
189          if (typesTreeView.Nodes[0].Nodes.Count == 1) {
190            typesTreeView.SelectedNode = typesTreeView.Nodes[0].Nodes[0];
191          }
192        }
193
194        if (typesTreeView.Nodes.Count == 0) {
195          SelectedType = null;
196          typesTreeView.Enabled = false;
197        } else {
198          SetTreeNodeVisibility();
199          typesTreeView.Enabled = true;
200        }
201        UpdateDescription();
202      }
203    }
204
205    public virtual object CreateInstanceOfSelectedType(params object[] args) {
206      if (SelectedType == null)
207        throw new InvalidOperationException("No type selected.");
208      else
209        return Activator.CreateInstance(SelectedType, args);
210    }
211
212    protected virtual void UpdateTypeParameters() {
213      typeParametersListView.Items.Clear();
214      if ((SelectedType == null) || !SelectedType.ContainsGenericParameters) {
215        typeParametersGroupBox.Enabled = false;
216        typeParametersSplitContainer.Panel2Collapsed = true;
217      } else {
218        typeParametersGroupBox.Enabled = true;
219        typeParametersSplitContainer.Panel2Collapsed = false;
220        setTypeParameterButton.Enabled = false;
221
222        foreach (Type param in SelectedType.GetGenericArguments()) {
223          if (param.IsGenericParameter) {
224            ListViewItem item = new ListViewItem();
225            item.Text = param.Name;
226
227            item.ToolTipText = "Constraints:";
228            Type[] constraints = param.GetGenericParameterConstraints();
229            if (constraints.Length == 0) {
230              item.ToolTipText += " none";
231            } else {
232              foreach (Type constraint in constraints)
233                item.ToolTipText += " " + constraint.GetPrettyName();
234            }
235
236            item.Tag = param;
237            typeParametersListView.Items.Add(item);
238          }
239        }
240        typeParametersListView.Columns[0].AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
241      }
242    }
243
244    protected virtual void SetTypeParameter() {
245      if (typeSelectorDialog == null) {
246        typeSelectorDialog = new TypeSelectorDialog();
247        typeSelectorDialog.Caption = "Select Type of Generic Type Parameter";
248      }
249      Type param = typeParametersListView.SelectedItems[0].Tag as Type;
250      Type[] contraints = param.GetGenericParameterConstraints();
251      typeSelectorDialog.TypeSelector.Configure(typeof(IItem), true, true);
252
253      if (typeSelectorDialog.ShowDialog(this) == DialogResult.OK) {
254        Type selected = typeSelectorDialog.TypeSelector.SelectedType;
255        Type[] parameters = SelectedType.GetGenericArguments();
256        parameters[param.GenericParameterPosition] = selected;
257        SelectedType = SelectedType.GetGenericTypeDefinition().MakeGenericType(parameters);
258
259        typeParametersListView.SelectedItems[0].Text = param.Name + ": " + selected.GetPrettyName();
260        typeParametersListView.Columns[0].AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
261      }
262    }
263
264    protected virtual void UpdateDescription() {
265      descriptionTextBox.Text = string.Empty;
266
267      if (typesTreeView.SelectedNode != null) {
268        IPluginDescription plugin = typesTreeView.SelectedNode.Tag as IPluginDescription;
269        if (plugin != null) {
270          StringBuilder sb = new StringBuilder();
271          sb.Append("Plugin: ").Append(plugin.Name).Append(Environment.NewLine);
272          sb.Append("Version: ").Append(plugin.Version.ToString()).Append(Environment.NewLine);
273          descriptionTextBox.Text = sb.ToString();
274        }
275        Type type = typesTreeView.SelectedNode.Tag as Type;
276        if (type != null) {
277          string description = ItemAttribute.GetDescription(type);
278          if (description != null)
279            descriptionTextBox.Text = description;
280        }
281      } else if (typesTreeView.Nodes.Count == 0) {
282        descriptionTextBox.Text = "No types found";
283      }
284    }
285
286    #region Events
287    public event EventHandler SelectedTypeChanged;
288    protected virtual void OnSelectedTypeChanged() {
289      if (SelectedTypeChanged != null)
290        SelectedTypeChanged(this, EventArgs.Empty);
291    }
292    #endregion
293
294    #region Control Events
295    protected virtual void searchTextBox_TextChanged(object sender, System.EventArgs e) {
296      Filter(searchTextBox.Text);
297    }
298
299    protected virtual void typesTreeView_AfterSelect(object sender, TreeViewEventArgs e) {
300      if (typesTreeView.SelectedNode == null) SelectedType = null;
301      else SelectedType = typesTreeView.SelectedNode.Tag as Type;
302      UpdateTypeParameters();
303      UpdateDescription();
304    }
305    protected virtual void typesTreeView_ItemDrag(object sender, ItemDragEventArgs e) {
306      TreeNode node = (TreeNode)e.Item;
307      Type type = node.Tag as Type;
308      if ((type != null) && (!type.IsInterface) && (!type.IsAbstract) && (!type.HasElementType) && (!type.ContainsGenericParameters)) {
309        object o = Activator.CreateInstance(type);
310        DataObject data = new DataObject();
311        data.SetData("Type", type);
312        data.SetData("Value", o);
313        DoDragDrop(data, DragDropEffects.Copy);
314      }
315    }
316    protected virtual void typesTreeView_VisibleChanged(object sender, EventArgs e) {
317      if (Visible) SetTreeNodeVisibility();
318    }
319
320    protected virtual void typeParametersListView_SelectedIndexChanged(object sender, EventArgs e) {
321      setTypeParameterButton.Enabled = typeParametersListView.SelectedItems.Count == 1;
322    }
323    protected virtual void typeParametersListView_DoubleClick(object sender, EventArgs e) {
324      if (typeParametersListView.SelectedItems.Count == 1)
325        SetTypeParameter();
326    }
327
328    protected virtual void setTypeParameterButton_Click(object sender, EventArgs e) {
329      SetTypeParameter();
330    }
331    #endregion
332
333    #region Helpers
334    private void RestoreSelectedNode(TreeNode selectedNode) {
335      if (selectedNode != null) {
336        foreach (TreeNode node in typesTreeView.Nodes) {
337          if (node.Text.Equals(selectedNode.Text)) typesTreeView.SelectedNode = node;
338          foreach (TreeNode child in node.Nodes) {
339            if ((child.Text.Equals(selectedNode.Text)) && (child.Tag == selectedNode.Tag))
340              typesTreeView.SelectedNode = child;
341          }
342        }
343        if (typesTreeView.SelectedNode == null) SelectedType = null;
344      }
345    }
346    private void SetTreeNodeVisibility() {
347      TreeNode selectedNode = typesTreeView.SelectedNode;
348      if (string.IsNullOrEmpty(currentSearchString) && (typesTreeView.Nodes.Count > 1)) {
349        typesTreeView.CollapseAll();
350        if (selectedNode != null) typesTreeView.SelectedNode = selectedNode;
351      } else {
352        typesTreeView.ExpandAll();
353      }
354      if (selectedNode != null) selectedNode.EnsureVisible();
355    }
356    #endregion
357  }
358}
Note: See TracBrowser for help on using the repository browser.