Index: /branches/OKB (trunk integration)/HeuristicLab.Clients.OKB/3.3/HeuristicLab.Clients.OKB-3.3.csproj
===================================================================
--- /branches/OKB (trunk integration)/HeuristicLab.Clients.OKB/3.3/HeuristicLab.Clients.OKB-3.3.csproj	(revision 5354)
+++ /branches/OKB (trunk integration)/HeuristicLab.Clients.OKB/3.3/HeuristicLab.Clients.OKB-3.3.csproj	(revision 5355)
@@ -100,4 +100,7 @@
   <ItemGroup>
     <Compile Include="AdministratorMenuItem.cs" />
+    <Compile Include="ItemWrapper.cs" />
+    <Compile Include="NamedItemWrapper.cs" />
+    <Compile Include="OKBRun.cs" />
     <Compile Include="EmptyAlgorithm.cs" />
     <Compile Include="OKBAlgorithm.cs" />
Index: /branches/OKB (trunk integration)/HeuristicLab.Clients.OKB/3.3/ItemWrapper.cs
===================================================================
--- /branches/OKB (trunk integration)/HeuristicLab.Clients.OKB/3.3/ItemWrapper.cs	(revision 5355)
+++ /branches/OKB (trunk integration)/HeuristicLab.Clients.OKB/3.3/ItemWrapper.cs	(revision 5355)
@@ -0,0 +1,128 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Clients.OKB {
+  [Item("ItemWrapper", "A wrapper which wraps an IItem.")]
+  [StorableClass]
+  public class ItemWrapper<T> : IItem where T : class, IItem {
+    private T wrappedItem;
+    protected virtual T WrappedItem {
+      get { return wrappedItem; }
+      set {
+        if (value == null) throw new ArgumentNullException("WrappedItem", "WrappedItem cannot be null.");
+        if (value != wrappedItem) {
+          DeregisterWrappedItemEvents();
+          wrappedItem = value;
+          RegisterWrappedItemEvents();
+
+          OnToStringChanged();
+          OnItemImageChanged();
+          OnWrappedItemChanged();
+        }
+      }
+    }
+
+    public virtual string ItemName {
+      get { return wrappedItem.ItemName; }
+    }
+    public virtual string ItemDescription {
+      get { return wrappedItem.ItemDescription; }
+    }
+    public Version ItemVersion {
+      get { return wrappedItem.ItemVersion; }
+    }
+    public virtual Image ItemImage {
+      get { return WrappedItem.ItemImage; }
+    }
+
+    #region Persistence Properties
+    [Storable(Name = "WrappedItem")]
+    private T StorableWrappedItem {
+      get { return wrappedItem; }
+      set {
+        wrappedItem = value;
+        RegisterWrappedItemEvents();
+      }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected ItemWrapper(bool deserializing) { }
+    protected ItemWrapper(ItemWrapper<T> original, Cloner cloner) {
+      cloner.RegisterClonedObject(original, this);
+      wrappedItem = cloner.Clone(original.wrappedItem);
+      RegisterWrappedItemEvents();
+    }
+    public ItemWrapper(T item) {
+      if (item == null) throw new ArgumentNullException("item", "ItemWrapper cannot wrap a null reference.");
+      wrappedItem = item;
+      RegisterWrappedItemEvents();
+    }
+
+    public object Clone() {
+      return Clone(new Cloner());
+    }
+    public virtual IDeepCloneable Clone(Cloner cloner) {
+      return new ItemWrapper<T>(this, cloner);
+    }
+
+    public override string ToString() {
+      return wrappedItem.ToString();
+    }
+
+    protected virtual void OnWrappedItemChanged() { }
+
+    #region Events
+    public event EventHandler ItemImageChanged;
+    protected virtual void OnItemImageChanged() {
+      EventHandler handler = ItemImageChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler ToStringChanged;
+    protected virtual void OnToStringChanged() {
+      EventHandler handler = ToStringChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    protected virtual void RegisterWrappedItemEvents() {
+      WrappedItem.ToStringChanged += new EventHandler(WrappedItem_ToStringChanged);
+      WrappedItem.ItemImageChanged += new EventHandler(WrappedItem_ItemImageChanged);
+    }
+    protected virtual void DeregisterWrappedItemEvents() {
+      WrappedItem.ToStringChanged -= new EventHandler(WrappedItem_ToStringChanged);
+      WrappedItem.ItemImageChanged -= new EventHandler(WrappedItem_ItemImageChanged);
+    }
+
+    protected virtual void WrappedItem_ToStringChanged(object sender, EventArgs e) {
+      OnToStringChanged();
+    }
+    protected virtual void WrappedItem_ItemImageChanged(object sender, EventArgs e) {
+      OnItemImageChanged();
+    }
+    #endregion
+  }
+}
Index: /branches/OKB (trunk integration)/HeuristicLab.Clients.OKB/3.3/MultiObjectiveOKBProblem.cs
===================================================================
--- /branches/OKB (trunk integration)/HeuristicLab.Clients.OKB/3.3/MultiObjectiveOKBProblem.cs	(revision 5354)
+++ /branches/OKB (trunk integration)/HeuristicLab.Clients.OKB/3.3/MultiObjectiveOKBProblem.cs	(revision 5355)
@@ -30,5 +30,7 @@
   [Creatable("Optimization Knowledge Base (OKB)")]
   [StorableClass]
-  public sealed class MultiObjectiveOKBProblem : OKBProblem, IMultiObjectiveProblem {
+  public sealed class MultiObjectiveOKBProblem : OKBProblem, IMultiObjectiveProblem, IStorableContent {
+    public string Filename { get; set; }
+
     public override Type ProblemType {
       get { return typeof(IMultiObjectiveProblem); }
Index: /branches/OKB (trunk integration)/HeuristicLab.Clients.OKB/3.3/NamedItemWrapper.cs
===================================================================
--- /branches/OKB (trunk integration)/HeuristicLab.Clients.OKB/3.3/NamedItemWrapper.cs	(revision 5355)
+++ /branches/OKB (trunk integration)/HeuristicLab.Clients.OKB/3.3/NamedItemWrapper.cs	(revision 5355)
@@ -0,0 +1,114 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Clients.OKB {
+  [Item("NamedItemWrapper", "A wrapper which wraps an INamedItem.")]
+  [StorableClass]
+  public class NamedItemWrapper<T> : ItemWrapper<T>, INamedItem where T : class, INamedItem {
+    protected override T WrappedItem {
+      get { return base.WrappedItem; }
+      set {
+        if (value == null) throw new ArgumentNullException("WrappedItem", "WrappedItem cannot be null.");
+        if (value != base.WrappedItem) {
+          CancelEventArgs<string> e = new CancelEventArgs<string>(value.Name);
+          OnNameChanging(e);
+          if (!e.Cancel) base.WrappedItem = value;
+        }
+      }
+    }
+
+    public virtual string Name {
+      get { return WrappedItem.Name; }
+      set { WrappedItem.Name = value; }
+    }
+    public virtual bool CanChangeName {
+      get { return WrappedItem.CanChangeName; }
+    }
+    public virtual string Description {
+      get { return WrappedItem.Description; }
+      set { WrappedItem.Description = value; }
+    }
+    public virtual bool CanChangeDescription {
+      get { return WrappedItem.CanChangeDescription; }
+    }
+
+    [StorableConstructor]
+    protected NamedItemWrapper(bool deserializing) : base(deserializing) { }
+    protected NamedItemWrapper(NamedItemWrapper<T> original, Cloner cloner) : base(original, cloner) { }
+    public NamedItemWrapper(T item) : base(item) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new NamedItemWrapper<T>(this, cloner);
+    }
+
+    protected override void OnWrappedItemChanged() {
+      base.OnWrappedItemChanged();
+      OnNameChanged();
+      OnDescriptionChanged();
+    }
+
+    #region Events
+    public event EventHandler<CancelEventArgs<string>> NameChanging;
+    protected virtual void OnNameChanging(CancelEventArgs<string> e) {
+      var handler = NameChanging;
+      if (handler != null) handler(this, e);
+    }
+    public event EventHandler NameChanged;
+    protected virtual void OnNameChanged() {
+      var handler = NameChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler DescriptionChanged;
+    protected virtual void OnDescriptionChanged() {
+      var handler = DescriptionChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    protected override void RegisterWrappedItemEvents() {
+      base.RegisterWrappedItemEvents();
+      WrappedItem.NameChanging += new EventHandler<CancelEventArgs<string>>(WrappedItem_NameChanging);
+      WrappedItem.NameChanged += new EventHandler(WrappedItem_NameChanged);
+      WrappedItem.DescriptionChanged += new EventHandler(WrappedItem_DescriptionChanged);
+    }
+    protected override void DeregisterWrappedItemEvents() {
+      WrappedItem.NameChanging -= new EventHandler<CancelEventArgs<string>>(WrappedItem_NameChanging);
+      WrappedItem.NameChanged -= new EventHandler(WrappedItem_NameChanged);
+      WrappedItem.DescriptionChanged -= new EventHandler(WrappedItem_DescriptionChanged);
+      base.DeregisterWrappedItemEvents();
+    }
+
+    protected virtual void WrappedItem_NameChanging(object sender, CancelEventArgs<string> e) {
+      OnNameChanging(e);
+    }
+    protected virtual void WrappedItem_NameChanged(object sender, EventArgs e) {
+      OnNameChanged();
+    }
+    protected virtual void WrappedItem_DescriptionChanged(object sender, EventArgs e) {
+      OnDescriptionChanged();
+    }
+    #endregion
+  }
+}
Index: /branches/OKB (trunk integration)/HeuristicLab.Clients.OKB/3.3/OKBAlgorithm.cs
===================================================================
--- /branches/OKB (trunk integration)/HeuristicLab.Clients.OKB/3.3/OKBAlgorithm.cs	(revision 5354)
+++ /branches/OKB (trunk integration)/HeuristicLab.Clients.OKB/3.3/OKBAlgorithm.cs	(revision 5355)
@@ -24,4 +24,5 @@
 using System.Drawing;
 using System.IO;
+using HeuristicLab.Collections;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -34,5 +35,7 @@
   [Creatable("Optimization Knowledge Base (OKB)")]
   [StorableClass]
-  public sealed class OKBAlgorithm : Item, IAlgorithm {
+  public sealed class OKBAlgorithm : Item, IAlgorithm, IStorableContent {
+    public string Filename { get; set; }
+
     private long algorithmId;
     public long AlgorithmId {
@@ -48,4 +51,5 @@
           OnNameChanging(e);
           if (!e.Cancel) {
+            IProblem problem = algorithm.Problem;
             DeregisterAlgorithmEvents();
             algorithm = value;
@@ -57,4 +61,13 @@
             OnDescriptionChanged();
             OnAlgorithmChanged();
+            OnStoreAlgorithmInEachRunChanged();
+
+            try {
+              algorithm.Problem = problem;
+            }
+            catch (ArgumentException) {
+              algorithm.Problem = null;
+            }
+            algorithm.Prepare(true);
           }
         }
@@ -104,6 +117,8 @@
     }
 
+    private int runsCounter;
+    private RunCollection runs;
     public RunCollection Runs {
-      get { return Algorithm.Runs; }
+      get { return runs; }
     }
     public bool StoreAlgorithmInEachRun {
@@ -124,4 +139,17 @@
         algorithm = value;
         RegisterAlgorithmEvents();
+      }
+    }
+    [Storable(Name = "RunsCounter")]
+    private int StorableRunsCounter {
+      get { return runsCounter; }
+      set { runsCounter = value; }
+    }
+    [Storable(Name = "Runs")]
+    private RunCollection StorableRuns {
+      get { return runs; }
+      set {
+        runs = value;
+        RegisterRunsEvents();
       }
     }
@@ -135,4 +163,7 @@
       algorithm = cloner.Clone(original.algorithm);
       RegisterAlgorithmEvents();
+      runsCounter = original.runsCounter;
+      runs = cloner.Clone(original.runs);
+      RegisterRunsEvents();
     }
     public OKBAlgorithm()
@@ -141,4 +172,7 @@
       algorithm = new EmptyAlgorithm("No algorithm selected. Please choose an algorithm from the OKB.");
       RegisterAlgorithmEvents();
+      runsCounter = 0;
+      runs = new RunCollection();
+      RegisterRunsEvents();
     }
 
@@ -167,8 +201,9 @@
 
     public void Prepare() {
-      Algorithm.Prepare();
+      Algorithm.Prepare(true);
     }
     public void Prepare(bool clearRuns) {
-      Algorithm.Prepare(clearRuns);
+      if (clearRuns) runs.Clear();
+      Algorithm.Prepare(true);
     }
     public void Start() {
@@ -240,4 +275,6 @@
     public event EventHandler Stopped;
     private void OnStopped() {
+      runsCounter++;
+      runs.Add(new HeuristicLab.Optimization.Run(string.Format("{0} Run {1}", Name, runsCounter), this));
       var handler = Stopped;
       if (handler != null) handler(this, EventArgs.Empty);
@@ -328,4 +365,11 @@
       OnExceptionOccurred(e.Value);
     }
+
+    private void RegisterRunsEvents() {
+      runs.CollectionReset += new CollectionItemsChangedEventHandler<IRun>(Runs_CollectionReset);
+    }
+    private void Runs_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
+      runsCounter = runs.Count;
+    }
     #endregion
   }
Index: /branches/OKB (trunk integration)/HeuristicLab.Clients.OKB/3.3/OKBRun.cs
===================================================================
--- /branches/OKB (trunk integration)/HeuristicLab.Clients.OKB/3.3/OKBRun.cs	(revision 5355)
+++ /branches/OKB (trunk integration)/HeuristicLab.Clients.OKB/3.3/OKBRun.cs	(revision 5355)
@@ -0,0 +1,104 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Clients.OKB {
+  [Item("OKB Run", "The parameters and results of an algorithm run which are stored in the OKB.")]
+  [StorableClass]
+  public sealed class OKBRun : NamedItemWrapper<IRun>, IRun, IStorableContent {
+    public string Filename { get; set; }
+
+    private long runId;
+    public long RunId {
+      get { return runId; }
+    }
+
+    public IAlgorithm Algorithm {
+      get { return WrappedItem.Algorithm; }
+    }
+    public IDictionary<string, IItem> Parameters {
+      get { return WrappedItem.Parameters; }
+    }
+    public IDictionary<string, IItem> Results {
+      get { return WrappedItem.Results; }
+    }
+
+    public Color Color {
+      get { return WrappedItem.Color; }
+      set { WrappedItem.Color = value; }
+    }
+    public bool Visible {
+      get { return WrappedItem.Visible; }
+      set { WrappedItem.Visible = value; }
+    }
+
+    #region Persistence Properties
+    [Storable(Name = "RunId")]
+    private long StorableRunId {
+      get { return runId; }
+      set { runId = value; }
+    }
+    #endregion
+
+    [StorableConstructor]
+    private OKBRun(bool deserializing) : base(deserializing) { }
+    private OKBRun(OKBRun original, Cloner cloner)
+      : base(original, cloner) {
+      runId = original.runId;
+    }
+    public OKBRun(IRun run)
+      : base(run) {
+      runId = -1;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new OKBRun(this, cloner);
+    }
+
+    #region Events
+    public event EventHandler Changed;
+    private void OnChanged() {
+      var handler = Changed;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    protected override void RegisterWrappedItemEvents() {
+      base.RegisterWrappedItemEvents();
+      WrappedItem.Changed += new EventHandler(WrappedItem_Changed);
+    }
+    protected override void DeregisterWrappedItemEvents() {
+      WrappedItem.Changed -= new EventHandler(WrappedItem_Changed);
+      base.DeregisterWrappedItemEvents();
+    }
+
+    private void WrappedItem_Changed(object sender, EventArgs e) {
+      OnChanged();
+    }
+    #endregion
+  }
+}
Index: /branches/OKB (trunk integration)/HeuristicLab.Clients.OKB/3.3/SingleObjectiveOKBProblem.cs
===================================================================
--- /branches/OKB (trunk integration)/HeuristicLab.Clients.OKB/3.3/SingleObjectiveOKBProblem.cs	(revision 5354)
+++ /branches/OKB (trunk integration)/HeuristicLab.Clients.OKB/3.3/SingleObjectiveOKBProblem.cs	(revision 5355)
@@ -30,5 +30,7 @@
   [Creatable("Optimization Knowledge Base (OKB)")]
   [StorableClass]
-  public sealed class SingleObjectiveOKBProblem : OKBProblem, ISingleObjectiveProblem {
+  public sealed class SingleObjectiveOKBProblem : OKBProblem, ISingleObjectiveProblem, IStorableContent {
+    public string Filename { get; set; }
+
     public override Type ProblemType {
       get { return typeof(ISingleObjectiveProblem); }
