Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Operators.Views.GraphVisualization/3.3/OperatorGraphVisualization/OperatorShapeInfo.cs @ 6031

Last change on this file since 6031 was 6031, checked in by mkommend, 13 years ago

#1488: Corrected locking of OperatorShapeInfo.

File size: 7.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2011 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.Collections.Generic;
23using System.Drawing;
24using System.Linq;
25using HeuristicLab.Common;
26using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
27using Netron.Diagramming.Core;
28
29namespace HeuristicLab.Operators.Views.GraphVisualization {
30  [StorableClass]
31  internal class OperatorShapeInfo : ShapeInfo, IOperatorShapeInfo {
32    [Storable]
33    private List<string> labels;
34
35    private object lockObject = new object();
36
37    [StorableConstructor]
38    protected OperatorShapeInfo(bool deserializing) : base(deserializing) { }
39    protected OperatorShapeInfo(OperatorShapeInfo original, Cloner cloner)
40      : base(original, cloner) {
41      collapsed = original.collapsed;
42      color = original.color;
43      lineColor = original.lineColor;
44      lineWidth = original.lineWidth;
45      title = original.title;
46
47      //mkommend: necessary because cloning a Bitmap is not threadsafe
48      //see http://stackoverflow.com/questions/1851292/invalidoperationexception-object-is-currently-in-use-elsewhere for further information
49      if (original.icon != null) {
50        lock (original.lockObject) {
51          icon = (Bitmap)original.icon.Clone();
52        }
53      }
54
55      connectorNames = new List<string>(original.connectorNames);
56      labels = new List<string>(original.labels);
57    }
58    public override IDeepCloneable Clone(Cloner cloner) {
59      return new OperatorShapeInfo(this, cloner);
60    }
61
62    public OperatorShapeInfo()
63      : base(typeof(OperatorShape)) {
64      this.connectorNames = new List<string>();
65      this.labels = new List<string>();
66    }
67
68    public OperatorShapeInfo(IEnumerable<string> connectorNames)
69      : this() {
70      foreach (string connectorName in connectorNames)
71        this.connectorNames.Add(connectorName);
72    }
73
74    public OperatorShapeInfo(IEnumerable<string> connectorNames, IEnumerable<string> labels)
75      : this(connectorNames) {
76      foreach (string label in labels)
77        this.labels.Add(label);
78    }
79
80    public void AddConnector(string connectorName) {
81      if (!this.connectorNames.Contains(connectorName)) {
82        this.connectorNames.Add(connectorName);
83        this.OnChanged();
84      }
85    }
86
87    public void RemoveConnector(string connectorName) {
88      if (this.connectorNames.Contains(connectorName)) {
89        this.connectorNames.Remove(connectorName);
90        this.OnChanged();
91      }
92    }
93
94    public void UpdateLabels(IEnumerable<string> labels) {
95      this.labels = new List<string>(labels);
96      this.OnChanged();
97    }
98
99    [Storable]
100    private List<string> connectorNames;
101    public override IEnumerable<string> Connectors {
102      get { return this.connectorNames; }
103    }
104
105    [Storable]
106    private bool collapsed;
107    public bool Collapsed {
108      get { return this.collapsed; }
109      set {
110        if (this.collapsed != value) {
111          this.collapsed = value;
112          this.OnChanged();
113        }
114      }
115    }
116
117    [Storable]
118    private string title;
119    public string Title {
120      get { return this.title; }
121      set {
122        if (this.title != value) {
123          this.title = value;
124          this.OnChanged();
125        }
126      }
127    }
128
129    [Storable]
130    private Color color;
131    public Color Color {
132      get { return this.color; }
133      set {
134        if (this.color != value) {
135          this.color = value;
136          this.OnChanged();
137        }
138      }
139    }
140
141    [Storable]
142    private Color lineColor;
143    public Color LineColor {
144      get { return this.lineColor; }
145      set {
146        if (this.lineColor != value) {
147          this.lineColor = value;
148          this.OnChanged();
149        }
150      }
151    }
152
153    [Storable]
154    private float lineWidth;
155    public float LineWidth {
156      get { return this.lineWidth; }
157      set {
158        if (this.lineWidth != value) {
159          this.lineWidth = value;
160          this.OnChanged();
161        }
162      }
163    }
164
165    private Bitmap icon;
166    public Bitmap Icon {
167      get { return this.icon; }
168      set {
169        if (this.icon != value) {
170          this.icon = value;
171          this.OnChanged();
172        }
173      }
174    }
175
176    public override IShape CreateShape() {
177      OperatorShape shape = (OperatorShape)base.CreateShape();
178      shape.Title = this.Title;
179      shape.Color = this.Color;
180      shape.LineColor = this.LineColor;
181      shape.LineWidth = this.LineWidth;
182      shape.Icon = this.Icon;
183      shape.Collapsed = this.Collapsed;
184      foreach (string connectorName in this.connectorNames)
185        if (connectorName != OperatorShapeInfoFactory.SuccessorConnector && connectorName != OperatorShapeInfoFactory.PredecessorConnector)
186          shape.AddConnector(connectorName);
187
188      shape.UpdateLabels(this.labels);
189      return shape;
190    }
191
192    public override void UpdateShape(IShape shape) {
193      base.UpdateShape(shape);
194      OperatorShape operatorShape = (OperatorShape)shape;
195      operatorShape.Title = this.Title;
196      operatorShape.Color = this.Color;
197      operatorShape.LineColor = this.LineColor;
198      operatorShape.LineWidth = this.LineWidth;
199      operatorShape.Icon = this.Icon;
200      operatorShape.Collapsed = this.Collapsed;
201
202      int i = 0;
203      int j = 0;
204      //remove old connectors and skip correct connectors
205      List<string> oldConnectorNames = operatorShape.AdditionalConnectorNames.ToList();
206      while (i < this.connectorNames.Count && j < oldConnectorNames.Count) {
207        if (connectorNames[i] == OperatorShapeInfoFactory.SuccessorConnector ||
208          connectorNames[i] == OperatorShapeInfoFactory.PredecessorConnector)
209          i++;
210        else if (oldConnectorNames[j] == OperatorShapeInfoFactory.SuccessorConnector ||
211          oldConnectorNames[j] == OperatorShapeInfoFactory.PredecessorConnector)
212          j++;
213        else if (this.connectorNames[i] != oldConnectorNames[j]) {
214          operatorShape.RemoveConnector(oldConnectorNames[j]);
215          j++;
216        } else {
217          i++;
218          j++;
219        }
220      }
221      //remove remaining old connectors
222      for (; j < oldConnectorNames.Count; j++)
223        operatorShape.RemoveConnector(oldConnectorNames[j]);
224
225      //add new connectors except successor and connector
226      for (; i < this.connectorNames.Count; i++)
227        if (this.connectorNames[i] != OperatorShapeInfoFactory.SuccessorConnector && this.connectorNames[i] != OperatorShapeInfoFactory.PredecessorConnector)
228          operatorShape.AddConnector(this.connectorNames[i]);
229
230      operatorShape.UpdateLabels(this.labels);
231    }
232
233    public override void UpdateShapeInfo(IShape shape) {
234      base.UpdateShapeInfo(shape);
235      OperatorShape operatorShape = (OperatorShape)shape;
236      this.Title = operatorShape.Title;
237      this.Color = operatorShape.Color;
238      this.LineColor = operatorShape.LineColor;
239      this.LineWidth = operatorShape.LineWidth;
240      this.Icon = operatorShape.Icon;
241      this.Collapsed = operatorShape.Collapsed;
242    }
243  }
244}
Note: See TracBrowser for help on using the repository browser.