Changeset 5485
- Timestamp:
- 02/16/11 11:06:56 (14 years ago)
- Location:
- trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.Netron/3.0.2672.12446/Netron.Diagramming.Core-3.0.2672.12446
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.Netron/3.0.2672.12446/Netron.Diagramming.Core-3.0.2672.12446/Core/ControllerBase.cs
r4068 r5485 154 154 protected CollectionBase<IKeyboardListener> keyboardListeners; 155 155 protected CollectionBase<IDragDropListener> dragdropListeners; 156 pr otectedIDiagramControl parentControl;156 private IDiagramControl parentControl; 157 157 protected CollectionBase<ITool> registeredTools; 158 158 protected CollectionBase<IActivity> registeredActivity; … … 192 192 public IDiagramControl ParentControl { 193 193 get { return parentControl; } 194 internal set { parentControl = value; }194 protected internal set { parentControl = value; } 195 195 } 196 196 /// <summary> -
trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.Netron/3.0.2672.12446/Netron.Diagramming.Core-3.0.2672.12446/Diagram elements/Connections/Connection.cs
r3175 r5485 2 2 using System.Drawing; 3 3 using System.Drawing.Drawing2D; 4 namespace Netron.Diagramming.Core 5 { 6 /// <summary> 7 /// Represents the connection between two connectors 8 /// </summary> 9 public sealed partial class Connection : ConnectionBase 10 { 11 12 13 // ------------------------------------------------------------------ 14 /// <summary> 15 /// Implementation of IVersion - the current version of 16 /// Connection. 17 /// </summary> 18 // ------------------------------------------------------------------ 19 private const double connectionVersion = 1.0; 20 21 #region Hack for the caps 22 private const float capslength = 0.01F; 23 private const float standardsshift = 7F; 24 private const float arrowshift = 0.1F; 25 /// <summary> 26 /// the ration between the arrow width to the line width 27 /// </summary> 28 private const float capsratio = 5.5F; 29 private const float generalizationration = 2.2F; 30 private float capsshift; 31 private Pen leftPen; 32 private Pen rightPen; 33 private PointF unitvector; 34 35 #endregion 36 37 #region Properties 38 39 // ------------------------------------------------------------------ 40 /// <summary> 41 /// Gets the current version. 42 /// </summary> 43 // ------------------------------------------------------------------ 44 public override double Version 45 { 46 get 47 { 48 return connectionVersion; 49 } 4 namespace Netron.Diagramming.Core { 5 /// <summary> 6 /// Represents the connection between two connectors 7 /// </summary> 8 public sealed partial class Connection : ConnectionBase { 9 10 11 // ------------------------------------------------------------------ 12 /// <summary> 13 /// Implementation of IVersion - the current version of 14 /// Connection. 15 /// </summary> 16 // ------------------------------------------------------------------ 17 private const double connectionVersion = 1.0; 18 19 #region Hack for the caps 20 private const float capslength = 0.01F; 21 private const float standardsshift = 7F; 22 private const float arrowshift = 0.1F; 23 /// <summary> 24 /// the ration between the arrow width to the line width 25 /// </summary> 26 private const float capsratio = 5.5F; 27 private const float generalizationration = 2.2F; 28 private float capsshift; 29 private Pen leftPen; 30 private Pen rightPen; 31 private PointF unitvector; 32 33 #endregion 34 35 #region Properties 36 37 // ------------------------------------------------------------------ 38 /// <summary> 39 /// Gets the current version. 40 /// </summary> 41 // ------------------------------------------------------------------ 42 public override double Version { 43 get { 44 return connectionVersion; 45 } 46 } 47 48 /// <summary> 49 /// Gets the friendly name of the entity to be displayed in the UI 50 /// </summary> 51 /// <value></value> 52 public override string EntityName { 53 get { return "Default Connection"; } 54 } 55 /// <summary> 56 /// The bounds of the paintable entity 57 /// </summary> 58 /// <value></value> 59 public override Rectangle Rectangle { 60 get { 61 if ((From == null) || (To == null)) { 62 return Rectangle.Empty; 50 63 } 51 52 /// <summary> 53 /// Gets the friendly name of the entity to be displayed in the UI 54 /// </summary> 55 /// <value></value> 56 public override string EntityName 57 { 58 get { return "Default Connection"; } 59 } 60 /// <summary> 61 /// The bounds of the paintable entity 62 /// </summary> 63 /// <value></value> 64 public override Rectangle Rectangle 65 { 66 get 67 { 68 if ( (From == null) || (To == null) ) 69 { 70 return Rectangle.Empty; 71 } 72 return Rectangle.FromLTRB( 73 Math.Min(From.Point.X, To.Point.X), 74 Math.Min(From.Point.Y, To.Point.Y), 75 Math.Max(From.Point.X, To.Point.X), 76 Math.Max(From.Point.Y, To.Point.Y)); 77 } 78 } 79 80 #endregion 81 82 #region Constructor 83 84 /// <summary> 85 /// Constructs a connection between the two given points 86 /// </summary> 87 /// <param name="mFrom">the starting point of the connection</param> 88 /// <param name="mTo">the end-point of the connection</param> 89 /// <param name="model">The model.</param> 90 public Connection(Point mFrom, Point mTo, IModel model):base(model) 91 { 92 this.From = new Connector(mFrom, model); 93 this.From.Name = "From"; 94 this.From.Parent = this; 95 this.To = new Connector(mTo, model); 96 this.To.Name = "To"; 97 this.To.Parent = this; 98 PenStyle = ArtPalette.GetDefaultPenStyle(); 99 } 100 101 /// <summary> 102 /// Initializes a new instance of the <see cref="T:Connection"/> class. 103 /// </summary> 104 /// <param name="from">From.</param> 105 /// <param name="to">To.</param> 106 public Connection(Point from, Point to) 107 : base(from, to) 108 { 109 } 110 111 public Connection() : base(new Point(10,10), new Point(20,20)) { 112 113 } 114 #endregion 115 116 #region Methods 117 118 /// <summary> 119 /// Paints the connection on the canvas. 120 /// </summary> 121 /// <param name="g"></param> 122 public override void Paint(Graphics g) 123 { 124 g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; 125 base.Paint(g); 126 127 if (Hovered) 128 { 129 g.DrawLine(ArtPalette.HighlightPen, From.Point, To.Point); 130 } 131 else 132 { 133 g.DrawLine(mPenStyle.DrawingPen(), From.Point, To.Point); 134 } 135 136 if(ArtPalette.EnableShadows) 137 g.DrawLine(ArtPalette.ConnectionShadow, From.Point.X + 5, From.Point.Y + 5, To.Point.X + 5, To.Point.Y + 5); 138 139 if (leftPen != null) 140 { 141 g.DrawLine(leftPen, From.Point.X + capsshift * unitvector.X, From.Point.Y + capsshift * unitvector.Y, From.Point.X + (capsshift + capslength) * unitvector.X, From.Point.Y + (capsshift + capslength) * unitvector.Y); 142 } 143 if (rightPen != null) 144 { 145 g.DrawLine(rightPen, To.Point.X - (capsshift + capslength) * unitvector.X, To.Point.Y - (capsshift + capslength) * unitvector.Y, To.Point.X - capsshift * unitvector.X, To.Point.Y - capsshift * unitvector.Y); 146 } 147 } 148 /// <summary> 149 /// Invalidates the connection 150 /// </summary> 151 public override void Invalidate() 152 { 153 154 float x = 0, y = 0; 155 try 156 { 157 if (To == null || From == null) return; 158 double length = Math.Sqrt((To.Point.X - From.Point.X) * (To.Point.X - From.Point.X) + (To.Point.Y - From.Point.Y) * (To.Point.Y - From.Point.Y)); 159 x = Convert.ToSingle(Convert.ToDouble(To.Point.X - From.Point.X) / length); 160 y = Convert.ToSingle(Convert.ToDouble(To.Point.Y - From.Point.Y) / length); 161 } 162 catch (OverflowException exc) 163 { 164 throw new InconsistencyException("So, you tried to shrink the connection too much...", exc); 165 } 166 unitvector = new PointF(x, y); 167 /* the old way 168 Rectangle f = new Rectangle(From.Point,new Size(10,10)); 169 Rectangle t = new Rectangle(To.Point,new Size(10,10)); 170 this.Invalidate(Rectangle.Union(f,t)); 171 */ 172 base.Invalidate(); 173 174 } 175 176 /// <summary> 177 /// Tests if the mouse hits this connection 178 /// </summary> 179 /// <param name="p"></param> 180 /// <returns></returns> 181 public override bool Hit(Point p) 182 { 183 Point p1,p2, s; 184 RectangleF r1, r2; 185 float o,u; 186 p1 = From.Point; p2 = To.Point; 187 188 // p1 must be the leftmost point. 189 if (p1.X > p2.X) { s = p2; p2 = p1; p1 = s; } 190 191 r1 = new RectangleF(p1.X, p1.Y, 0, 0); 192 r2 = new RectangleF(p2.X, p2.Y, 0, 0); 193 r1.Inflate(3, 3); 194 r2.Inflate(3, 3); 195 if (RectangleF.Union(r1, r2).Contains(p)) 196 { 64 return Rectangle.FromLTRB( 65 Math.Min(From.Point.X, To.Point.X), 66 Math.Min(From.Point.Y, To.Point.Y), 67 Math.Max(From.Point.X, To.Point.X), 68 Math.Max(From.Point.Y, To.Point.Y)); 69 } 70 } 71 72 #endregion 73 74 #region Constructor 75 76 /// <summary> 77 /// Constructs a connection between the two given points 78 /// </summary> 79 /// <param name="mFrom">the starting point of the connection</param> 80 /// <param name="mTo">the end-point of the connection</param> 81 /// <param name="model">The model.</param> 82 public Connection(Point mFrom, Point mTo, IModel model) 83 : base(model) { 84 this.From = new Connector(mFrom, model); 85 this.From.Name = "From"; 86 this.From.Parent = this; 87 this.To = new Connector(mTo, model); 88 this.To.Name = "To"; 89 this.To.Parent = this; 90 PenStyle = ArtPalette.GetDefaultPenStyle(); 91 } 92 93 /// <summary> 94 /// Initializes a new instance of the <see cref="T:Connection"/> class. 95 /// </summary> 96 /// <param name="from">From.</param> 97 /// <param name="to">To.</param> 98 public Connection(Point from, Point to) 99 : base(from, to) { 100 } 101 102 public Connection() 103 : base(new Point(10, 10), new Point(20, 20)) { 104 105 } 106 #endregion 107 108 #region Methods 109 110 /// <summary> 111 /// Paints the connection on the canvas. 112 /// </summary> 113 /// <param name="g"></param> 114 public override void Paint(Graphics g) { 115 g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; 116 base.Paint(g); 117 118 if (Hovered) { 119 g.DrawLine(ArtPalette.HighlightPen, From.Point, To.Point); 120 } else { 121 g.DrawLine(mPenStyle.DrawingPen(), From.Point, To.Point); 122 } 123 124 if (ArtPalette.EnableShadows) 125 g.DrawLine(ArtPalette.ConnectionShadow, From.Point.X + 5, From.Point.Y + 5, To.Point.X + 5, To.Point.Y + 5); 126 127 if (leftPen != null) { 128 g.DrawLine(leftPen, From.Point.X + capsshift * unitvector.X, From.Point.Y + capsshift * unitvector.Y, From.Point.X + (capsshift + capslength) * unitvector.X, From.Point.Y + (capsshift + capslength) * unitvector.Y); 129 } 130 if (rightPen != null) { 131 g.DrawLine(rightPen, To.Point.X - (capsshift + capslength) * unitvector.X, To.Point.Y - (capsshift + capslength) * unitvector.Y, To.Point.X - capsshift * unitvector.X, To.Point.Y - capsshift * unitvector.Y); 132 } 133 } 134 /// <summary> 135 /// Invalidates the connection 136 /// </summary> 137 public override void Invalidate() { 138 139 float x = 0, y = 0; 140 try { 141 if (To == null || From == null) return; 142 double length = Math.Sqrt((To.Point.X - From.Point.X) * (To.Point.X - From.Point.X) + (To.Point.Y - From.Point.Y) * (To.Point.Y - From.Point.Y)); 143 x = Convert.ToSingle(Convert.ToDouble(To.Point.X - From.Point.X) / length); 144 y = Convert.ToSingle(Convert.ToDouble(To.Point.Y - From.Point.Y) / length); 145 } 146 catch (OverflowException exc) { 147 throw new InconsistencyException("So, you tried to shrink the connection too much...", exc); 148 } 149 unitvector = new PointF(x, y); 150 /* the old way 151 Rectangle f = new Rectangle(From.Point,new Size(10,10)); 152 Rectangle t = new Rectangle(To.Point,new Size(10,10)); 153 this.Invalidate(Rectangle.Union(f,t)); 154 */ 155 base.Invalidate(); 156 157 } 158 159 /// <summary> 160 /// Tests if the mouse hits this connection 161 /// </summary> 162 /// <param name="p"></param> 163 /// <returns></returns> 164 public override bool Hit(Point p) { 165 Point p1, p2, s; 166 RectangleF r1, r2; 167 p1 = From.Point; p2 = To.Point; 168 169 // p1 must be the leftmost point. 170 if (p1.X > p2.X) { s = p2; p2 = p1; p1 = s; } 171 172 r1 = new RectangleF(p1.X, p1.Y, 0, 0); 173 r2 = new RectangleF(p2.X, p2.Y, 0, 0); 174 r1.Inflate(3, 3); 175 r2.Inflate(3, 3); 176 if (RectangleF.Union(r1, r2).Contains(p)) { 197 177 PointF connectionVector = new PointF(p2.X - p1.X, p2.Y - p1.Y); 198 178 PointF normalVector = new PointF(connectionVector.Y, connectionVector.X * -1); … … 203 183 204 184 return distance < 5; 205 } 206 return false; 207 } 208 209 /// <summary> 210 /// Moves the connection with the given shift 211 /// </summary> 212 /// <param name="p"></param> 213 public override void MoveBy(Point p) 214 { 215 if (From.AttachedTo != null || To.AttachedTo != null) return; 216 217 Rectangle rec = this.Rectangle; 218 rec.Inflate(20, 20); 219 this.From.MoveBy(p); 220 this.To.MoveBy(p); 221 this.Invalidate(); 222 this.Invalidate(rec); 223 } 224 /// <summary> 225 /// Updates pens and brushes. 226 /// <remarks>The .Net API allows you to simply set caps but the visual results are less than satisfactory, to say the least. So, there is 227 /// a hack here (unfortunately) which amounts to use two pen for one connection; one pen for the line and one for the (custom) cap. This is 228 /// the easiest way to have visible arrow which otherwise is miniaturistic. There is also a custom shift of the caps since the location is sometime 229 /// inappropriate; the arrow is drawn with the tip at the end of the connection while the diamond or circle caps are drawn with their center at the connection 230 /// end. So, altogether a lot of tweaking and I really find it regrettable that the out-of-the-box caps are not what they should be (besides some obvious bugs like 231 /// the 'not implemented' one if you try to fill a custom cap...). 232 /// </remarks> 233 /// </summary> 234 protected override void UpdatePaintingMaterial() 235 { 236 base.UpdatePaintingMaterial(); 237 #region Hack 238 //see the code comments of the LinePenStyle to understand the problem and this hack 239 if (this.PenStyle is LinePenStyle) 240 { 241 242 LinePenStyle lp = PenStyle as LinePenStyle; 243 if (lp.StartCap == System.Drawing.Drawing2D.LineCap.NoAnchor) 244 { 245 leftPen = null; 246 } 247 else 248 { 249 250 251 if (lp.StartCap == System.Drawing.Drawing2D.LineCap.Custom) 252 { 253 //leftPen.StartCap = System.Drawing.Drawing2D.LineCap.Custom; 254 //AdjustableArrowCap ccap = new AdjustableArrowCap(lp.Width+2, lp.Width+2, true); 255 //leftPen.CustomStartCap = ccap; 256 leftPen = new Pen(lp.Color, lp.Width * generalizationration); 257 leftPen.CustomStartCap = LinePenStyle.GenerallizationCap; //change to something like lp.CustomStartCap if you have more than one custom cap 258 capsshift = standardsshift; 259 } 260 else if (lp.StartCap == LineCap.ArrowAnchor) 261 { 262 leftPen = new Pen(lp.Color, lp.Width * capsratio); 263 leftPen.StartCap = lp.StartCap; 264 capsshift = arrowshift; 265 } 266 else 267 { 268 leftPen = new Pen(lp.Color, lp.Width * capsratio); 269 leftPen.StartCap = lp.StartCap; 270 capsshift = standardsshift; 271 } 272 } 273 274 if (lp.EndCap == System.Drawing.Drawing2D.LineCap.NoAnchor) 275 { 276 rightPen = null; 277 } 278 else 279 { 280 281 if (lp.EndCap == System.Drawing.Drawing2D.LineCap.Custom) 282 { 283 //leftPen.StartCap = System.Drawing.Drawing2D.LineCap.Custom; 284 //AdjustableArrowCap ccap = new AdjustableArrowCap(lp.Width+2, lp.Width+2, true); 285 //leftPen.CustomStartCap = ccap; 286 //rightPen = new Pen(lp.Color, lp.Width * generalizationration); 287 //rightPen.CustomEndCap = lp.CustomEndCap; 288 //capsshift = standardsshift; 289 Pen.CustomEndCap = LinePenStyle.GenerallizationCap; 290 } 291 292 else if (lp.EndCap == LineCap.ArrowAnchor) 293 { 294 rightPen = new Pen(lp.Color, lp.Width * capsratio); 295 rightPen.EndCap = lp.EndCap; 296 capsshift = arrowshift; 297 } 298 else 299 { 300 rightPen = new Pen(lp.Color, lp.Width * capsratio); 301 rightPen.EndCap = lp.EndCap; 302 capsshift = standardsshift; 303 } 304 } 305 306 } 307 #endregion 308 } 309 310 311 312 #endregion 313 314 } 185 } 186 return false; 187 } 188 189 /// <summary> 190 /// Moves the connection with the given shift 191 /// </summary> 192 /// <param name="p"></param> 193 public override void MoveBy(Point p) { 194 if (From.AttachedTo != null || To.AttachedTo != null) return; 195 196 Rectangle rec = this.Rectangle; 197 rec.Inflate(20, 20); 198 this.From.MoveBy(p); 199 this.To.MoveBy(p); 200 this.Invalidate(); 201 this.Invalidate(rec); 202 } 203 /// <summary> 204 /// Updates pens and brushes. 205 /// <remarks>The .Net API allows you to simply set caps but the visual results are less than satisfactory, to say the least. So, there is 206 /// a hack here (unfortunately) which amounts to use two pen for one connection; one pen for the line and one for the (custom) cap. This is 207 /// the easiest way to have visible arrow which otherwise is miniaturistic. There is also a custom shift of the caps since the location is sometime 208 /// inappropriate; the arrow is drawn with the tip at the end of the connection while the diamond or circle caps are drawn with their center at the connection 209 /// end. So, altogether a lot of tweaking and I really find it regrettable that the out-of-the-box caps are not what they should be (besides some obvious bugs like 210 /// the 'not implemented' one if you try to fill a custom cap...). 211 /// </remarks> 212 /// </summary> 213 protected override void UpdatePaintingMaterial() { 214 base.UpdatePaintingMaterial(); 215 #region Hack 216 //see the code comments of the LinePenStyle to understand the problem and this hack 217 if (this.PenStyle is LinePenStyle) { 218 219 LinePenStyle lp = PenStyle as LinePenStyle; 220 if (lp.StartCap == System.Drawing.Drawing2D.LineCap.NoAnchor) { 221 leftPen = null; 222 } else { 223 224 225 if (lp.StartCap == System.Drawing.Drawing2D.LineCap.Custom) { 226 //leftPen.StartCap = System.Drawing.Drawing2D.LineCap.Custom; 227 //AdjustableArrowCap ccap = new AdjustableArrowCap(lp.Width+2, lp.Width+2, true); 228 //leftPen.CustomStartCap = ccap; 229 leftPen = new Pen(lp.Color, lp.Width * generalizationration); 230 leftPen.CustomStartCap = LinePenStyle.GenerallizationCap; //change to something like lp.CustomStartCap if you have more than one custom cap 231 capsshift = standardsshift; 232 } else if (lp.StartCap == LineCap.ArrowAnchor) { 233 leftPen = new Pen(lp.Color, lp.Width * capsratio); 234 leftPen.StartCap = lp.StartCap; 235 capsshift = arrowshift; 236 } else { 237 leftPen = new Pen(lp.Color, lp.Width * capsratio); 238 leftPen.StartCap = lp.StartCap; 239 capsshift = standardsshift; 240 } 241 } 242 243 if (lp.EndCap == System.Drawing.Drawing2D.LineCap.NoAnchor) { 244 rightPen = null; 245 } else { 246 247 if (lp.EndCap == System.Drawing.Drawing2D.LineCap.Custom) { 248 //leftPen.StartCap = System.Drawing.Drawing2D.LineCap.Custom; 249 //AdjustableArrowCap ccap = new AdjustableArrowCap(lp.Width+2, lp.Width+2, true); 250 //leftPen.CustomStartCap = ccap; 251 //rightPen = new Pen(lp.Color, lp.Width * generalizationration); 252 //rightPen.CustomEndCap = lp.CustomEndCap; 253 //capsshift = standardsshift; 254 Pen.CustomEndCap = LinePenStyle.GenerallizationCap; 255 } else if (lp.EndCap == LineCap.ArrowAnchor) { 256 rightPen = new Pen(lp.Color, lp.Width * capsratio); 257 rightPen.EndCap = lp.EndCap; 258 capsshift = arrowshift; 259 } else { 260 rightPen = new Pen(lp.Color, lp.Width * capsratio); 261 rightPen.EndCap = lp.EndCap; 262 capsshift = standardsshift; 263 } 264 } 265 266 } 267 #endregion 268 } 269 270 271 272 #endregion 273 274 } 315 275 }
Note: See TracChangeset
for help on using the changeset viewer.