#region License Information
/* HeuristicLab
* Copyright (C) 2002-2018 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.Linq;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using HeuristicLab.Collections;
using HeuristicLab.Common;
using HeuristicLab.Core;
using HeuristicLab.Core.Views;
using HeuristicLab.MainForm;
using HeuristicLab.MainForm.WindowsForms;
using HeuristicLab.Persistence.Core;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
using HeuristicLab.Persistence.Default.Xml;
using HeuristicLab.PluginInfrastructure;
namespace HeuristicLab.Scripting.Views {
[View("ItemCollection View")]
[Content(typeof(VariableStore), true)]
public partial class VariableStoreView : AsynchronousContentView {
#region Image Names
private const string ErrorImageName = "Error";
private const string WarningImageName = "Warning";
private const string HeuristicLabObjectImageName = "HeuristicLabObject";
private const string ObjectImageName = "Object";
private const string NothingImageName = "Nothing";
#endregion
private readonly Regex SafeVariableNameRegex = new Regex("^[@]?[_a-zA-Z][_a-zA-Z0-9]*$");
private const string DefaultVariableName = "enter_name";
protected readonly Dictionary itemListViewItemMapping;
protected readonly Dictionary serializableLookup;
protected TypeSelectorDialog typeSelectorDialog;
protected bool validDragOperation;
public new VariableStore Content {
get { return (VariableStore)base.Content; }
set { base.Content = value; }
}
public ListView ItemsListView {
get { return variableListView; }
}
public VariableStoreView() {
InitializeComponent();
itemListViewItemMapping = new Dictionary();
serializableLookup = new Dictionary();
var images = variableListView.SmallImageList.Images;
images.Add(ErrorImageName, Common.Resources.VSImageLibrary.Error);
images.Add(WarningImageName, Common.Resources.VSImageLibrary.Warning);
images.Add(HeuristicLabObjectImageName, Common.Resources.HeuristicLab.Icon.ToBitmap());
images.Add(ObjectImageName, Common.Resources.VSImageLibrary.Object);
images.Add(NothingImageName, Common.Resources.VSImageLibrary.Nothing);
}
protected override void Dispose(bool disposing) {
if (disposing) {
if (typeSelectorDialog != null) typeSelectorDialog.Dispose();
if (components != null) components.Dispose();
}
base.Dispose(disposing);
}
protected override void DeregisterContentEvents() {
Content.ItemsAdded -= Content_ItemsAdded;
Content.ItemsReplaced -= Content_ItemsReplaced;
Content.ItemsRemoved -= Content_ItemsRemoved;
Content.CollectionReset -= Content_CollectionReset;
foreach (var variable in Content) {
var item = variable.Value as IItem;
if (item != null) item.ToStringChanged -= item_ToStringChanged;
}
base.DeregisterContentEvents();
}
protected override void RegisterContentEvents() {
base.RegisterContentEvents();
Content.ItemsAdded += Content_ItemsAdded;
Content.ItemsReplaced += Content_ItemsReplaced;
Content.ItemsRemoved += Content_ItemsRemoved;
Content.CollectionReset += Content_CollectionReset;
foreach (var variable in Content) {
var item = variable.Value as IItem;
if (item != null) item.ToStringChanged += item_ToStringChanged;
}
}
protected override void OnContentChanged() {
base.OnContentChanged();
variableListView.Items.Clear();
itemListViewItemMapping.Clear();
if (Content != null) {
Caption += " (" + Content.GetType().Name + ")";
foreach (var item in Content)
AddVariable(item);
AdjustListViewColumnSizes();
SortItemsListView(SortOrder.Ascending);
}
}
protected override void SetEnabledStateOfControls() {
base.SetEnabledStateOfControls();
if (Content == null) {
addButton.Enabled = false;
sortAscendingButton.Enabled = false;
sortDescendingButton.Enabled = false;
removeButton.Enabled = false;
variableListView.LabelEdit = false;
} else {
bool enabled = !Locked && !ReadOnly;
addButton.Enabled = enabled;
sortAscendingButton.Enabled = variableListView.Items.Count > 1;
sortDescendingButton.Enabled = variableListView.Items.Count > 1;
removeButton.Enabled = enabled && variableListView.SelectedItems.Count > 0;
variableListView.LabelEdit = enabled;
}
}
protected virtual object CreateItem() {
if (typeSelectorDialog == null) {
typeSelectorDialog = new TypeSelectorDialog { Caption = "Select Item" };
typeSelectorDialog.TypeSelector.Caption = "Available Items";
typeSelectorDialog.TypeSelector.Configure(typeof(IItem), false, true);
}
if (typeSelectorDialog.ShowDialog(this) == DialogResult.OK) {
try {
return (object)typeSelectorDialog.TypeSelector.CreateInstanceOfSelectedType();
} catch (Exception ex) {
ErrorHandling.ShowErrorDialog(this, ex);
}
}
return null;
}
protected virtual void AddVariable(KeyValuePair variable) {
if (string.IsNullOrEmpty(variable.Key)) throw new ArgumentException("The variable must have a name.", "variable");
bool serializable = IsSerializable(variable);
var listViewItem = new ListViewItem();
AssignVariableToListViewItem(listViewItem, variable);
SetImageKey(listViewItem, serializable);
SetToolTipText(listViewItem, serializable);
variableListView.Items.Add(listViewItem);
itemListViewItemMapping[variable.Key] = listViewItem;
sortAscendingButton.Enabled = variableListView.Items.Count > 1;
sortDescendingButton.Enabled = variableListView.Items.Count > 1;
}
protected virtual void RemoveVariable(KeyValuePair variable) {
if (string.IsNullOrEmpty(variable.Key)) throw new ArgumentException("The variable must have a name.", "variable");
ListViewItem listViewItem;
if (!itemListViewItemMapping.TryGetValue(variable.Key, out listViewItem)) return;
itemListViewItemMapping.Remove(variable.Key);
variableListView.Items.Remove(listViewItem);
sortAscendingButton.Enabled = variableListView.Items.Count > 1;
sortDescendingButton.Enabled = variableListView.Items.Count > 1;
}
protected virtual void UpdateVariable(KeyValuePair variable) {
if (string.IsNullOrEmpty(variable.Key)) throw new ArgumentException("The variable must have a name.", "variable");
ListViewItem listViewItem;
if (!itemListViewItemMapping.TryGetValue(variable.Key, out listViewItem))
throw new ArgumentException("A variable with the specified name does not exist.", "variable");
bool serializable = IsSerializable(variable);
AssignVariableToListViewItem(listViewItem, variable);
SetImageKey(listViewItem, serializable);
SetToolTipText(listViewItem, serializable);
}
#region ListView Events
protected virtual void variableListView_SelectedIndexChanged(object sender, EventArgs e) {
removeButton.Enabled = (Content != null) && !Locked && !ReadOnly && variableListView.SelectedItems.Count > 0;
AdjustListViewColumnSizes();
}
protected virtual void variableListView_KeyDown(object sender, KeyEventArgs e) {
switch (e.KeyCode) {
case Keys.Delete:
if ((variableListView.SelectedItems.Count > 0) && !Locked && !ReadOnly) {
foreach (ListViewItem item in variableListView.SelectedItems)
Content.Remove(item.Text);
}
break;
case Keys.F2:
if (variableListView.SelectedItems.Count != 1) return;
var selectedItem = variableListView.SelectedItems[0];
if (variableListView.LabelEdit)
selectedItem.BeginEdit();
break;
case Keys.A:
if (e.Modifiers.HasFlag(Keys.Control)) {
foreach (ListViewItem item in variableListView.Items)
item.Selected = true;
}
break;
}
}
protected virtual void variableListView_DoubleClick(object sender, EventArgs e) {
if (variableListView.SelectedItems.Count != 1) return;
var item = variableListView.SelectedItems[0].Tag as KeyValuePair?;
if (item == null) return;
var value = item.Value.Value as IContent;
if (value == null) return;
IContentView view = MainFormManager.MainForm.ShowContent(value);
if (view == null) return;
view.ReadOnly = ReadOnly;
view.Locked = Locked;
}
protected virtual void variableListView_ItemDrag(object sender, ItemDragEventArgs e) {
if (Locked || variableListView.SelectedItems.Count != 1) return;
var listViewItem = variableListView.SelectedItems[0];
var item = (KeyValuePair)listViewItem.Tag;
if (!(item.Value is IDeepCloneable)) return;
var data = new DataObject(HeuristicLab.Common.Constants.DragDropDataFormat, item);
DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link);
}
protected virtual void variableListView_DragEnter(object sender, DragEventArgs e) {
validDragOperation = !Locked && !ReadOnly;
object item = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
if (item is KeyValuePair) {
var variable = (KeyValuePair)item;
validDragOperation &= variable.Value is IDeepCloneable;
} else {
validDragOperation &= item is IDeepCloneable;
}
}
protected virtual void variableListView_DragOver(object sender, DragEventArgs e) {
e.Effect = DragDropEffects.None;
if (validDragOperation) {
if ((e.KeyState & 32) == 32) e.Effect = DragDropEffects.Link; // ALT key
else if (e.AllowedEffect.HasFlag(DragDropEffects.Copy)) e.Effect = DragDropEffects.Copy;
else if (e.AllowedEffect.HasFlag(DragDropEffects.Link)) e.Effect = DragDropEffects.Link;
}
}
protected virtual void variableListView_DragDrop(object sender, DragEventArgs e) {
if (e.Effect == DragDropEffects.None) return;
object item = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
string variableName;
bool editLabel;
if (item is KeyValuePair) {
var variable = (KeyValuePair)item;
variableName = GenerateNewVariableName(out editLabel, variable.Key, false);
item = variable.Value;
} else {
var namedItem = item as INamedItem;
if (namedItem != null)
variableName = GenerateNewVariableName(out editLabel, namedItem.Name, false);
else
variableName = GenerateNewVariableName(out editLabel);
}
var cloneable = item as IDeepCloneable;
if (cloneable == null) return;
Content.Add(variableName, e.Effect.HasFlag(DragDropEffects.Copy) ? cloneable.Clone() : cloneable);
var listViewItem = variableListView.FindItemWithText(variableName);
variableListView.SelectedItems.Clear();
if (editLabel) listViewItem.BeginEdit();
}
private void variableListView_AfterLabelEdit(object sender, LabelEditEventArgs e) {
string name = e.Label;
if (!string.IsNullOrEmpty(name)) {
var variable = (KeyValuePair)variableListView.Items[e.Item].Tag;
if (!Content.ContainsKey(name)) {
Content.Remove(variable.Key);
Content.Add(name, variable.Value);
}
}
e.CancelEdit = true;
}
#endregion
#region Button Events
protected virtual void addButton_Click(object sender, EventArgs e) {
object variableValue = CreateItem();
if (variableValue == null) return;
string variableName;
var namedItem = variableValue as INamedItem;
if (namedItem != null)
variableName = GenerateNewVariableName(namedItem.Name, false);
else
variableName = GenerateNewVariableName();
Content.Add(variableName, variableValue);
var item = variableListView.FindItemWithText(variableName);
variableListView.SelectedItems.Clear();
item.BeginEdit();
}
protected virtual void sortAscendingButton_Click(object sender, EventArgs e) {
SortItemsListView(SortOrder.Ascending);
}
protected virtual void sortDescendingButton_Click(object sender, EventArgs e) {
SortItemsListView(SortOrder.Descending);
}
protected virtual void removeButton_Click(object sender, EventArgs e) {
if (variableListView.SelectedItems.Count > 0) {
foreach (ListViewItem item in variableListView.SelectedItems)
Content.Remove(item.Text);
variableListView.SelectedItems.Clear();
}
}
#endregion
#region Content Events
protected virtual void Content_ItemsAdded(object sender, CollectionItemsChangedEventArgs> e) {
var variables = e.Items;
foreach (var variable in variables) {
var item = variable.Value as IItem;
if (item != null) item.ToStringChanged += item_ToStringChanged;
}
InvokeVariableAction(AddVariable, variables);
}
protected virtual void Content_ItemsReplaced(object sender, CollectionItemsChangedEventArgs> e) {
var oldVariables = e.OldItems;
foreach (var variable in oldVariables) {
var item = variable.Value as IItem;
if (item != null) item.ToStringChanged -= item_ToStringChanged;
}
var newVariables = e.Items;
foreach (var variable in newVariables) {
var item = variable.Value as IItem;
if (item != null) item.ToStringChanged += item_ToStringChanged;
}
InvokeVariableAction(UpdateVariable, e.Items);
}
protected virtual void Content_ItemsRemoved(object sender, CollectionItemsChangedEventArgs> e) {
var variables = e.Items;
foreach (var variable in variables) {
var item = variable.Value as IItem;
if (item != null) item.ToStringChanged -= item_ToStringChanged;
}
InvokeVariableAction(RemoveVariable, variables);
}
protected virtual void Content_CollectionReset(object sender, CollectionItemsChangedEventArgs> e) {
if (InvokeRequired) Invoke((Action