#region License Information /* HeuristicLab * Copyright (C) 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 HeuristicLab.Collections; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Parameters; using HEAL.Attic; namespace HeuristicLab.Operators { /// /// A base class for operators which apply arbitrary many other operators of a specific type. /// [Item("MultiOperator", "A base class for operators which apply arbitrary many other operators of a specific type.")] [StorableType("B8991981-2A8E-4A84-914D-24EE977BFB8F")] public abstract class MultiOperator : InstrumentedOperator, IMultiOperator where T : class, IOperator { private List> operatorParameters; protected IEnumerable> OperatorParameters { get { return operatorParameters; } } [Storable] private IItemList operators; public IItemList Operators { get { return operators; } protected set { if (operators != value) { if (value == null) throw new ArgumentException(); DeregisterOperatorsEvents(); operators = value; RegisterOperatorsEvents(); UpdateOperatorParameters(); } } } IEnumerable IMultiOperator.Operators { get { return operators.AsEnumerable(); } } [StorableConstructor] protected MultiOperator(StorableConstructorFlag _) : base(_) { } protected MultiOperator(MultiOperator original, Cloner cloner) : base(original, cloner) { this.operators = cloner.Clone>(original.operators); Initialize(); } public MultiOperator() : base() { this.operators = new ItemList(); Initialize(); } [StorableHook(HookType.AfterDeserialization)] private void AfterDeserialization() { Initialize(); } public virtual bool AddOperator(IOperator op) { var tOp = op as T; if (tOp == null) return false; operators.Add(tOp); return true; } public virtual bool RemoveOperator(IOperator op) { var tOp = op as T; if (tOp == null) return false; return operators.Remove(tOp); } private void Initialize() { if (operators != null) RegisterOperatorsEvents(); operatorParameters = new List>(); for (int i = 0; i < Operators.Count; i++) { IValueParameter opParam = (IValueParameter)Parameters[i.ToString()]; operatorParameters.Add(opParam); opParam.ValueChanged += new EventHandler(opParam_ValueChanged); } } private void UpdateOperatorParameters() { foreach (IValueParameter opParam in operatorParameters) { opParam.ValueChanged -= new EventHandler(opParam_ValueChanged); Parameters.Remove(opParam.Name); } operatorParameters.Clear(); for (int i = 0; i < Operators.Count; i++) { IValueParameter opParam = new OptionalValueParameter(i.ToString(), string.Empty, Operators[i]); opParam.Hidden = true; opParam.ValueChanged += new EventHandler(opParam_ValueChanged); Parameters.Add(opParam); operatorParameters.Add(opParam); } } #region Events private void RegisterOperatorsEvents() { operators.ItemsAdded += new CollectionItemsChangedEventHandler>(Operators_ItemsAdded); operators.ItemsRemoved += new CollectionItemsChangedEventHandler>(Operators_ItemsRemoved); operators.ItemsReplaced += new CollectionItemsChangedEventHandler>(Operators_ItemsReplaced); operators.ItemsMoved += new CollectionItemsChangedEventHandler>(Operators_ItemsMoved); operators.CollectionReset += new CollectionItemsChangedEventHandler>(Operators_CollectionReset); } private void DeregisterOperatorsEvents() { operators.ItemsAdded -= new CollectionItemsChangedEventHandler>(Operators_ItemsAdded); operators.ItemsRemoved -= new CollectionItemsChangedEventHandler>(Operators_ItemsRemoved); operators.ItemsReplaced -= new CollectionItemsChangedEventHandler>(Operators_ItemsReplaced); operators.ItemsMoved -= new CollectionItemsChangedEventHandler>(Operators_ItemsMoved); operators.CollectionReset -= new CollectionItemsChangedEventHandler>(Operators_CollectionReset); } protected virtual void Operators_ItemsAdded(object sender, CollectionItemsChangedEventArgs> e) { UpdateOperatorParameters(); } protected virtual void Operators_ItemsRemoved(object sender, CollectionItemsChangedEventArgs> e) { UpdateOperatorParameters(); } protected virtual void Operators_ItemsReplaced(object sender, CollectionItemsChangedEventArgs> e) { foreach (IndexedItem item in e.Items) operatorParameters[item.Index].Value = item.Value; } protected virtual void Operators_ItemsMoved(object sender, CollectionItemsChangedEventArgs> e) { foreach (IndexedItem item in e.Items) operatorParameters[item.Index].Value = item.Value; } protected virtual void Operators_CollectionReset(object sender, CollectionItemsChangedEventArgs> e) { UpdateOperatorParameters(); } private void opParam_ValueChanged(object sender, EventArgs e) { IValueParameter opParam = (IValueParameter)sender; if (opParam.Value == null) operators.RemoveAt(operatorParameters.IndexOf(opParam)); else operators[operatorParameters.IndexOf(opParam)] = opParam.Value; } #endregion } }