source: trunk/sources/HeuristicLab.Operators/3.3/MultiOperator.cs @ 3729

Last change on this file since 3729 was 3729, checked in by swagner, 12 years ago

Fixed exception thrown in OperatorGraph views when removing one of the operator parameters of a MultiOperator (#1004)

File size: 5.9 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 HeuristicLab.Collections;
26using HeuristicLab.Common;
27using HeuristicLab.Core;
28using HeuristicLab.Parameters;
29using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
30
31namespace HeuristicLab.Operators {
32  /// <summary>
33  /// A base class for operators which apply arbitrary many other operators of a specific type.
34  /// </summary>
35  [Item("MultiOperator<T>", "A base class for operators which apply arbitrary many other operators of a specific type.")]
36  [StorableClass]
37  public abstract class MultiOperator<T> : SingleSuccessorOperator where T : class, IOperator {
38    private List<IValueParameter<T>> operatorParameters;
39
40    [Storable]
41    private IItemList<T> operators;
42    public IItemList<T> Operators {
43      get { return operators; }
44      protected set {
45        if (operators != value) {
46          if (value == null) throw new ArgumentException();
47          DeregisterOperatorsEvents();
48          operators = value;
49          RegisterOperatorsEvents();
50        }
51      }
52    }
53
54    public MultiOperator()
55      : base() {
56      this.operators = new ItemList<T>();
57      Initialize();
58    }
59
60    [StorableConstructor]
61    protected MultiOperator(bool deserializing) : base(deserializing) { }
62
63    [StorableHook(HookType.AfterDeserialization)]
64    private void Initialize() {
65      if (operators != null) RegisterOperatorsEvents();
66      operatorParameters = new List<IValueParameter<T>>();
67      for (int i = 0; i < Operators.Count; i++) {
68        IValueParameter<T> opParam = (IValueParameter<T>)Parameters[i.ToString()];
69        operatorParameters.Add(opParam);
70        opParam.ValueChanged += new EventHandler(opParam_ValueChanged);
71      }
72    }
73
74    public override IDeepCloneable Clone(Cloner cloner) {
75      MultiOperator<T> clone = (MultiOperator<T>)base.Clone(cloner);
76      clone.operators = (IItemList<T>)cloner.Clone(operators);
77      clone.Initialize();
78      return clone;
79    }
80
81    private void UpdateOperatorParameters() {
82      foreach (IValueParameter<T> opParam in operatorParameters) {
83        opParam.ValueChanged -= new EventHandler(opParam_ValueChanged);
84        Parameters.Remove(opParam.Name);
85      }
86      operatorParameters.Clear();
87      for (int i = 0; i < Operators.Count; i++) {
88        IValueParameter<T> opParam = new OptionalValueParameter<T>(i.ToString(), string.Empty, Operators[i]);
89        opParam.ValueChanged += new EventHandler(opParam_ValueChanged);
90        Parameters.Add(opParam);
91        operatorParameters.Add(opParam);
92      }
93    }
94
95    #region Events
96    private void RegisterOperatorsEvents() {
97      operators.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<T>>(Operators_ItemsAdded);
98      operators.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<T>>(Operators_ItemsRemoved);
99      operators.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<T>>(Operators_ItemsReplaced);
100      operators.ItemsMoved += new CollectionItemsChangedEventHandler<IndexedItem<T>>(Operators_ItemsMoved);
101      operators.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<T>>(Operators_CollectionReset);
102    }
103    private void DeregisterOperatorsEvents() {
104      operators.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<T>>(Operators_ItemsAdded);
105      operators.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<T>>(Operators_ItemsRemoved);
106      operators.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<T>>(Operators_ItemsReplaced);
107      operators.ItemsMoved -= new CollectionItemsChangedEventHandler<IndexedItem<T>>(Operators_ItemsMoved);
108      operators.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<T>>(Operators_CollectionReset);
109    }
110    protected virtual void Operators_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<T>> e) {
111      UpdateOperatorParameters();
112    }
113    protected virtual void Operators_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<T>> e) {
114      UpdateOperatorParameters();
115    }
116    protected virtual void Operators_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<T>> e) {
117      foreach (IndexedItem<T> item in e.Items)
118        operatorParameters[item.Index].Value = item.Value;
119    }
120    protected virtual void Operators_ItemsMoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<T>> e) {
121      foreach (IndexedItem<T> item in e.Items)
122        operatorParameters[item.Index].Value = item.Value;
123    }
124    protected virtual void Operators_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<T>> e) {
125      UpdateOperatorParameters();
126    }
127    private void opParam_ValueChanged(object sender, EventArgs e) {
128      IValueParameter<T> opParam = (IValueParameter<T>)sender;
129      if (opParam.Value == null)
130        operators.RemoveAt(operatorParameters.IndexOf(opParam));
131      else
132        operators[operatorParameters.IndexOf(opParam)] = opParam.Value;
133    }
134    #endregion
135  }
136}
Note: See TracBrowser for help on using the repository browser.