Changeset 4068 for trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.Netron/3.0.2672.12446/Netron.Diagramming.Core-3.0.2672.12446/BaseClasses/ShapeBase.cs
- Timestamp:
- 07/22/10 00:44:01 (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.Netron/3.0.2672.12446/Netron.Diagramming.Core-3.0.2672.12446/BaseClasses/ShapeBase.cs
r2768 r4068 1 1 using System; 2 using System. Diagnostics;2 using System.ComponentModel; 3 3 using System.Drawing; 4 using System.ComponentModel;5 4 using System.Windows.Forms; 6 using System.Drawing.Drawing2D; 7 namespace Netron.Diagramming.Core 8 { 9 // ---------------------------------------------------------------------- 10 /// <summary> 11 /// Abstract base class for shapes. 12 /// </summary> 13 // ---------------------------------------------------------------------- 14 public abstract partial class ShapeBase : DiagramEntityBase, IShape 15 { 16 #region Fields 17 18 // ------------------------------------------------------------------ 19 /// <summary> 20 /// Implementation of IVersion - the current version of 21 /// ShapeBase. 22 /// </summary> 23 // ------------------------------------------------------------------ 24 protected const double shapeBaseVersion = 1.0; 25 26 // ------------------------------------------------------------------ 27 /// <summary> 28 /// Specifies if connectors are drawn. 29 /// </summary> 30 // ------------------------------------------------------------------ 31 protected bool mShowConnectors = true; 32 33 // ------------------------------------------------------------------ 34 /// <summary> 35 /// The collection of Connectors onto which you can attach a 36 /// connection. 37 /// </summary> 38 // ------------------------------------------------------------------ 39 protected CollectionBase<IConnector> mConnectors; 40 41 protected bool mIsFixed = false; 42 43 #endregion 44 45 #region Properties 46 47 // ------------------------------------------------------------------ 48 /// <summary> 49 /// Gets the current version. 50 /// </summary> 51 // ------------------------------------------------------------------ 52 public override double Version 53 { 54 get 55 { 56 return shapeBaseVersion; 57 } 5 namespace Netron.Diagramming.Core { 6 // ---------------------------------------------------------------------- 7 /// <summary> 8 /// Abstract base class for shapes. 9 /// </summary> 10 // ---------------------------------------------------------------------- 11 public abstract partial class ShapeBase : DiagramEntityBase, IShape { 12 #region Fields 13 14 // ------------------------------------------------------------------ 15 /// <summary> 16 /// Implementation of IVersion - the current version of 17 /// ShapeBase. 18 /// </summary> 19 // ------------------------------------------------------------------ 20 protected const double shapeBaseVersion = 1.0; 21 22 // ------------------------------------------------------------------ 23 /// <summary> 24 /// Specifies if connectors are drawn. 25 /// </summary> 26 // ------------------------------------------------------------------ 27 protected bool mShowConnectors = true; 28 29 // ------------------------------------------------------------------ 30 /// <summary> 31 /// The collection of Connectors onto which you can attach a 32 /// connection. 33 /// </summary> 34 // ------------------------------------------------------------------ 35 protected CollectionBase<IConnector> mConnectors; 36 37 protected bool mIsFixed = false; 38 39 #endregion 40 41 #region Properties 42 43 // ------------------------------------------------------------------ 44 /// <summary> 45 /// Gets the current version. 46 /// </summary> 47 // ------------------------------------------------------------------ 48 public override double Version { 49 get { 50 return shapeBaseVersion; 51 } 52 } 53 54 // ------------------------------------------------------------------ 55 /// <summary> 56 /// Gets the image for this shape when displaying in a library (i.e. 57 /// toolbox). 58 /// </summary> 59 // ------------------------------------------------------------------ 60 public virtual Image LibraryImage { 61 get { 62 return null; 63 } 64 } 65 66 // ------------------------------------------------------------------ 67 /// <summary> 68 /// Gets or sets if the connectors are drawn. 69 /// </summary> 70 // ------------------------------------------------------------------ 71 public bool ShowConnectors { 72 get { 73 return this.mShowConnectors; 74 } 75 set { 76 bool oldValue = mShowConnectors; 77 this.mShowConnectors = value; 78 if (oldValue != value) { 79 Invalidate(); 58 80 } 59 60 // ------------------------------------------------------------------ 61 /// <summary> 62 /// Gets the image for this shape when displaying in a library (i.e. 63 /// toolbox). 64 /// </summary> 65 // ------------------------------------------------------------------ 66 public virtual Image LibraryImage 67 { 68 get 69 { 70 return null; 71 } 81 RaiseOnChange(this, new EntityEventArgs(this)); 82 } 83 } 84 85 // ------------------------------------------------------------------ 86 /// <summary> 87 /// Gets or sets the canvas to which the entity belongs 88 /// </summary> 89 /// <value></value> 90 // ------------------------------------------------------------------ 91 public override IModel Model { 92 get { 93 return base.Model; 94 } 95 set { 96 base.Model = value; 97 if (Connectors == null) 98 throw new InconsistencyException("The connectors collection is 'null'."); 99 foreach (IConnector con in Connectors) { 100 con.Model = value; 72 101 } 73 74 // ------------------------------------------------------------------ 75 /// <summary> 76 /// Gets or sets if the connectors are drawn. 77 /// </summary> 78 // ------------------------------------------------------------------ 79 public bool ShowConnectors 80 { 81 get 82 { 83 return this.mShowConnectors; 84 } 85 set 86 { 87 bool oldValue = mShowConnectors; 88 this.mShowConnectors = value; 89 if (oldValue != value) 90 { 91 Invalidate(); 92 } 93 RaiseOnChange(this, new EntityEventArgs(this)); 94 } 102 } 103 } 104 105 // ------------------------------------------------------------------ 106 /// <summary> 107 /// Gets or sets the Connectors attached to this shape. 108 /// </summary> 109 // ------------------------------------------------------------------ 110 public CollectionBase<IConnector> Connectors { 111 get { return mConnectors; } 112 set { mConnectors = value; } 113 } 114 115 // ------------------------------------------------------------------ 116 /// <summary> 117 /// Gets or sets the width of the bundle 118 /// </summary> 119 // ------------------------------------------------------------------ 120 [Browsable(true), 121 Description("The width of the shape"), 122 Category("Layout")] 123 public int Width { 124 get { 125 return this.mRectangle.Width; 126 } 127 set { 128 Transform( 129 this.Rectangle.X, 130 this.Rectangle.Y, 131 value, 132 this.Height); 133 } 134 } 135 136 // ------------------------------------------------------------------ 137 /// <summary> 138 /// Gets or sets the height of the bundle 139 /// </summary> 140 // ------------------------------------------------------------------ 141 [Browsable(true), 142 Description("The height of the shape"), 143 Category("Layout")] 144 public int Height { 145 get { 146 return this.mRectangle.Height; 147 } 148 set { 149 Transform( 150 this.Rectangle.X, 151 this.Rectangle.Y, 152 this.Width, 153 value); 154 } 155 } 156 157 // ------------------------------------------------------------------ 158 /// <summary> 159 /// the x-coordinate of the upper-left corner 160 /// </summary> 161 // ------------------------------------------------------------------ 162 [Browsable(true), 163 Description("The x-coordinate of the upper-left corner"), 164 Category("Layout")] 165 public int X { 166 get { 167 return mRectangle.X; 168 } 169 set { 170 Point p = new Point(value - mRectangle.X, mRectangle.Y); 171 this.MoveBy(p); 172 173 //if(Model!=null) 174 // Model.RaiseOnInvalidate(); //note that 'this.Invalidate()' will not be enough 175 } 176 } 177 178 // ------------------------------------------------------------------ 179 /// <summary> 180 /// the y-coordinate of the upper-left corner 181 /// </summary> 182 // ------------------------------------------------------------------ 183 [Browsable(true), Description("The y-coordinate of the upper-left corner"), Category("Layout")] 184 public int Y { 185 get { 186 return mRectangle.Y; 187 } 188 set { 189 Point p = new Point(mRectangle.X, value - mRectangle.Y); 190 this.MoveBy(p); 191 //Model.RaiseOnInvalidate(); 192 } 193 } 194 195 // ------------------------------------------------------------------ 196 /// <summary> 197 /// Gets or sets the location of the bundle; 198 /// </summary> 199 // ------------------------------------------------------------------ 200 [Browsable(false)] 201 public Point Location { 202 get { 203 return new Point(this.mRectangle.X, this.mRectangle.Y); 204 } 205 set { 206 //we use the move method but it requires the delta value, not 207 // an absolute position! 208 Point p = new Point( 209 value.X - mRectangle.X, 210 value.Y - mRectangle.Y); 211 212 // If you'd use this it would indeed move the bundle but not 213 // the connectors of the bundle 214 // this.mRectangle.X = value.X; this.mRectangle.Y = value.Y; Invalidate(); 215 this.MoveBy(p); 216 } 217 } 218 219 // ------------------------------------------------------------------ 220 /// <summary> 221 /// Gets the bounds of the paintable entity 222 /// </summary> 223 /// <value></value> 224 // ------------------------------------------------------------------ 225 public override Rectangle Rectangle { 226 get { 227 return mRectangle; 228 } 229 //set{mRectangle = value; 230 231 //this.Invalidate(); } 232 } 233 234 #endregion 235 236 #region Constructor 237 238 239 /// <summary> 240 /// Constructor with the site of the bundle 241 /// </summary> 242 /// <param name="model"></param> 243 protected ShapeBase(IModel model) 244 : base(model) { 245 } 246 247 /// <summary> 248 /// Initializes a new instance of the <see cref="T:ShapeBase"/> class. 249 /// </summary> 250 protected ShapeBase() 251 : base() { 252 } 253 254 /// <summary> 255 /// Inits this instance. 256 /// </summary> 257 protected override void Initialize() { 258 base.Initialize(); 259 mConnectors = new CollectionBase<IConnector>(); 260 mConnectors.OnItemAdded += new EventHandler<CollectionEventArgs<IConnector>>(mConnectors_OnItemAdded); 261 mRectangle = new Rectangle(0, 0, 100, 70); 262 } 263 264 #endregion 265 266 #region Methods 267 268 // ------------------------------------------------------------------ 269 /// <summary> 270 /// Overrides the base 'OnBeforeDelete' to tell all attached 271 /// connectors they're being deleted. 272 /// </summary> 273 /// <param name="deleteCommand"></param> 274 // ------------------------------------------------------------------ 275 public override void OnBeforeDelete(DeleteCommand deleteCommand) { 276 base.OnBeforeDelete(deleteCommand); 277 foreach (IConnector con in this.mConnectors) { 278 con.OnBeforeDelete(deleteCommand); 279 } 280 } 281 282 // ------------------------------------------------------------------ 283 /// <summary> 284 /// Overrides the base 'OnAfterDelete' to tell all attached 285 /// connectors they have been deleted. 286 /// </summary> 287 /// <param name="deleteCommand"></param> 288 // ------------------------------------------------------------------ 289 public override void OnAfterDelete(DeleteCommand deleteCommand) { 290 base.OnAfterDelete(deleteCommand); 291 foreach (IConnector con in this.mConnectors) { 292 con.OnAfterDelete(deleteCommand); 293 } 294 } 295 296 // ------------------------------------------------------------------ 297 /// <summary> 298 /// Generates a new Uid for this entity. 299 /// </summary> 300 /// <param name="recursive">bool: If the Uid has to be changed 301 /// recursively down to the sub-entities, set to true, otherwise 302 /// false.</param> 303 // ------------------------------------------------------------------ 304 public override void NewUid(bool recursive) { 305 306 if (recursive) { 307 foreach (IConnector connector in Connectors) { 308 connector.NewUid(recursive); 95 309 } 96 97 // ------------------------------------------------------------------ 98 /// <summary> 99 /// Gets or sets the canvas to which the entity belongs 100 /// </summary> 101 /// <value></value> 102 // ------------------------------------------------------------------ 103 public override IModel Model 104 { 105 get 106 { 107 return base.Model; 108 } 109 set 110 { 111 base.Model = value; 112 if (Connectors == null) 113 throw new InconsistencyException("The connectors collection is 'null'."); 114 foreach (IConnector con in Connectors) 115 { 116 con.Model = value; 117 } 118 } 310 base.NewUid(recursive); 311 } else 312 base.NewUid(recursive); 313 } 314 315 // ------------------------------------------------------------------ 316 /// <summary> 317 /// Part of the initialization, this method connects newly added 318 /// connectors to the parenting shape. 319 /// </summary> 320 /// <param name="sender">object</param> 321 /// <param name="e">CollectionEventArgs<IConnector></param> 322 // ------------------------------------------------------------------ 323 void mConnectors_OnItemAdded( 324 object sender, 325 CollectionEventArgs<IConnector> e) { 326 e.Item.Parent = this; 327 } 328 329 // ------------------------------------------------------------------ 330 /// <summary> 331 /// The custom menu to be added to the base menu of this entity. 332 /// 'null' is returned here. 333 /// </summary> 334 /// <returns>ToolStripItem[]</returns> 335 // ------------------------------------------------------------------ 336 public override ToolStripItem[] Menu() { 337 return null; 338 } 339 340 // ------------------------------------------------------------------ 341 /// <summary> 342 /// Returns the connector hit by the mouse, if any. 343 /// </summary> 344 /// <param name="p">Point: The mouse coordinates</param> 345 /// <returns>IConnector: The connector hit by the mouse</returns> 346 // ------------------------------------------------------------------ 347 public IConnector HitConnector(Point p) { 348 for (int k = 0; k < mConnectors.Count; k++) { 349 if (mConnectors[k].Hit(p)) { 350 mConnectors[k].Hovered = true; 351 mConnectors[k].Invalidate(); 352 return mConnectors[k]; 353 } else { 354 mConnectors[k].Hovered = false; 355 mConnectors[k].Invalidate(); 356 119 357 } 120 358 121 // ------------------------------------------------------------------ 122 /// <summary> 123 /// Gets or sets the Connectors attached to this shape. 124 /// </summary> 125 // ------------------------------------------------------------------ 126 public CollectionBase<IConnector> Connectors 127 { 128 get { return mConnectors; } 129 set { mConnectors = value; } 130 } 131 132 // ------------------------------------------------------------------ 133 /// <summary> 134 /// Gets or sets the width of the bundle 135 /// </summary> 136 // ------------------------------------------------------------------ 137 [Browsable(true), 138 Description("The width of the shape"), 139 Category("Layout")] 140 public int Width 141 { 142 get 143 { 144 return this.mRectangle.Width; 145 } 146 set 147 { 148 Transform( 149 this.Rectangle.X, 150 this.Rectangle.Y, 151 value, 152 this.Height); 153 } 154 } 155 156 // ------------------------------------------------------------------ 157 /// <summary> 158 /// Gets or sets the height of the bundle 159 /// </summary> 160 // ------------------------------------------------------------------ 161 [Browsable(true), 162 Description("The height of the shape"), 163 Category("Layout")] 164 public int Height 165 { 166 get 167 { 168 return this.mRectangle.Height; 169 } 170 set 171 { 172 Transform( 173 this.Rectangle.X, 174 this.Rectangle.Y, 175 this.Width, 176 value); 177 } 178 } 179 180 // ------------------------------------------------------------------ 181 /// <summary> 182 /// the x-coordinate of the upper-left corner 183 /// </summary> 184 // ------------------------------------------------------------------ 185 [Browsable(true), 186 Description("The x-coordinate of the upper-left corner"), 187 Category("Layout")] 188 public int X 189 { 190 get 191 { 192 return mRectangle.X; 193 } 194 set 195 { 196 Point p = new Point(value - mRectangle.X, mRectangle.Y); 197 this.MoveBy(p); 198 199 //if(Model!=null) 200 // Model.RaiseOnInvalidate(); //note that 'this.Invalidate()' will not be enough 201 } 202 } 203 204 // ------------------------------------------------------------------ 205 /// <summary> 206 /// the y-coordinate of the upper-left corner 207 /// </summary> 208 // ------------------------------------------------------------------ 209 [Browsable(true), Description("The y-coordinate of the upper-left corner"), Category("Layout")] 210 public int Y 211 { 212 get 213 { 214 return mRectangle.Y; 215 } 216 set 217 { 218 Point p = new Point(mRectangle.X, value - mRectangle.Y); 219 this.MoveBy(p); 220 //Model.RaiseOnInvalidate(); 221 } 222 } 223 224 // ------------------------------------------------------------------ 225 /// <summary> 226 /// Gets or sets the location of the bundle; 227 /// </summary> 228 // ------------------------------------------------------------------ 229 [Browsable(false)] 230 public Point Location 231 { 232 get 233 { 234 return new Point(this.mRectangle.X, this.mRectangle.Y); 235 } 236 set 237 { 238 //we use the move method but it requires the delta value, not 239 // an absolute position! 240 Point p = new Point( 241 value.X - mRectangle.X, 242 value.Y - mRectangle.Y); 243 244 // If you'd use this it would indeed move the bundle but not 245 // the connectors of the bundle 246 // this.mRectangle.X = value.X; this.mRectangle.Y = value.Y; Invalidate(); 247 this.MoveBy(p); 248 } 249 } 250 251 // ------------------------------------------------------------------ 252 /// <summary> 253 /// Gets the bounds of the paintable entity 254 /// </summary> 255 /// <value></value> 256 // ------------------------------------------------------------------ 257 public override Rectangle Rectangle 258 { 259 get 260 { 261 return mRectangle; 262 } 263 //set{mRectangle = value; 264 265 //this.Invalidate(); } 266 } 267 268 #endregion 269 270 #region Constructor 271 272 273 /// <summary> 274 /// Constructor with the site of the bundle 275 /// </summary> 276 /// <param name="model"></param> 277 protected ShapeBase(IModel model) 278 : base(model) 279 { 280 } 281 282 /// <summary> 283 /// Initializes a new instance of the <see cref="T:ShapeBase"/> class. 284 /// </summary> 285 protected ShapeBase() 286 : base() 287 { 288 } 289 290 /// <summary> 291 /// Inits this instance. 292 /// </summary> 293 protected override void Initialize() 294 { 295 base.Initialize(); 296 mConnectors = new CollectionBase<IConnector>(); 297 mConnectors.OnItemAdded += new EventHandler<CollectionEventArgs<IConnector>>(mConnectors_OnItemAdded); 298 mRectangle = new Rectangle(0, 0, 100, 70); 299 } 300 301 #endregion 302 303 #region Methods 304 305 // ------------------------------------------------------------------ 306 /// <summary> 307 /// Overrides the base 'OnBeforeDelete' to tell all attached 308 /// connectors they're being deleted. 309 /// </summary> 310 /// <param name="deleteCommand"></param> 311 // ------------------------------------------------------------------ 312 public override void OnBeforeDelete(DeleteCommand deleteCommand) 313 { 314 base.OnBeforeDelete(deleteCommand); 315 foreach (IConnector con in this.mConnectors) 316 { 317 con.OnBeforeDelete(deleteCommand); 318 } 319 } 320 321 // ------------------------------------------------------------------ 322 /// <summary> 323 /// Overrides the base 'OnAfterDelete' to tell all attached 324 /// connectors they have been deleted. 325 /// </summary> 326 /// <param name="deleteCommand"></param> 327 // ------------------------------------------------------------------ 328 public override void OnAfterDelete(DeleteCommand deleteCommand) 329 { 330 base.OnAfterDelete(deleteCommand); 331 foreach (IConnector con in this.mConnectors) 332 { 333 con.OnAfterDelete(deleteCommand); 334 } 335 } 336 337 // ------------------------------------------------------------------ 338 /// <summary> 339 /// Generates a new Uid for this entity. 340 /// </summary> 341 /// <param name="recursive">bool: If the Uid has to be changed 342 /// recursively down to the sub-entities, set to true, otherwise 343 /// false.</param> 344 // ------------------------------------------------------------------ 345 public override void NewUid(bool recursive) 346 { 359 360 } 361 return null; 362 } 363 364 // ------------------------------------------------------------------ 365 /// <summary> 366 /// Overrides the abstract paint method. Nothing performed here, 367 /// let the sub-shapes do the painting. 368 /// </summary> 369 /// <param name="g">a graphics object onto which to paint</param> 370 // ------------------------------------------------------------------ 371 public override void Paint(Graphics g) { 372 return; 373 } 374 375 // ------------------------------------------------------------------ 376 /// <summary> 377 /// Override the abstract Hit method. Here a simple hit test is 378 /// performed by checking if our "Rectangle" contains the point 379 /// specified. Override this to perform more complex hit testing. 380 /// </summary> 381 /// <param name="p">Point</param> 382 /// <returns>bool</returns> 383 // ------------------------------------------------------------------ 384 public override bool Hit(Point p) { 385 Rectangle r = new Rectangle(p, new Size(5, 5)); 386 return Rectangle.Contains(r); 387 } 388 389 // ------------------------------------------------------------------ 390 /// <summary> 391 /// Overrides the abstract Invalidate method. This shape's rectangle 392 /// is inflated (not permanently) by a size of (40, 40) to ensure 393 /// the whole area is refreshed. 394 /// </summary> 395 // ------------------------------------------------------------------ 396 public override void Invalidate() { 397 Rectangle r = Rectangle; 398 r.Offset(-10, -10); 399 r.Inflate(40, 40); 400 if (Model != null) { 401 Model.RaiseOnInvalidateRectangle(r); 402 } 403 } 404 405 // ------------------------------------------------------------------ 406 /// <summary> 407 /// Moves the entity with the given shift (offset). 408 /// </summary> 409 /// <param name="p">Represents a shift-vector, not the absolute 410 /// position!</param> 411 // ------------------------------------------------------------------ 412 public override void MoveBy(Point p) { 413 Rectangle recBefore = mRectangle; 414 recBefore.Inflate(20, 20); 415 416 this.mRectangle.X += p.X; 417 this.mRectangle.Y += p.Y; 418 419 UpdatePaintingMaterial(); 420 421 for (int k = 0; k < this.mConnectors.Count; k++) { 422 mConnectors[k].MoveBy(p); 423 } 424 RaiseOnChange(this, new EntityEventArgs(this)); 425 //refresh things 426 this.Invalidate(recBefore);//position before the move 427 this.Invalidate();//current position 428 429 } 430 431 // ------------------------------------------------------------------ 432 /// <summary> 433 /// Scales the entity with the given factor at the given origin. 434 /// <remarks>More an historical milestone than used code.</remarks> 435 /// </summary> 436 /// <param name="origin">The origin.</param> 437 /// <param name="scaleX">The scale X.</param> 438 /// <param name="scaleY">The scale Y.</param> 439 // ------------------------------------------------------------------ 440 void Scale( 441 Point origin, 442 double scaleX, 443 double scaleY) { 444 #region Variables 445 //temporary variables to assign the new location of the mConnectors 446 double a, b; 447 //the new location of the connector 448 Point p; 449 //calculated/scaled/biased corners of the new rectangle 450 double ltx = 0, lty = 0, rbx = 0, rby = 0; 451 452 Rectangle currentRectangle = Rectangle; 453 //we only need to transform the LT and RB corners since the rest of the rectangle can be deduced from that 454 /* 455 PointF[] corners = new PointF[]{new PointF(currentRectangle.X, currentRectangle.Y), 456 new PointF(currentRectangle.Right, currentRectangle.Bottom), 347 457 348 if (recursive) 349 { 350 foreach (IConnector connector in Connectors) 351 { 352 connector.NewUid(recursive); 353 } 354 base.NewUid(recursive); 355 } 356 else 357 base.NewUid(recursive); 358 } 359 360 // ------------------------------------------------------------------ 361 /// <summary> 362 /// Part of the initialization, this method connects newly added 363 /// connectors to the parenting shape. 364 /// </summary> 365 /// <param name="sender">object</param> 366 /// <param name="e">CollectionEventArgs<IConnector></param> 367 // ------------------------------------------------------------------ 368 void mConnectors_OnItemAdded( 369 object sender, 370 CollectionEventArgs<IConnector> e) 371 { 372 e.Item.Parent = this; 373 } 374 375 // ------------------------------------------------------------------ 376 /// <summary> 377 /// The custom menu to be added to the base menu of this entity. 378 /// 'null' is returned here. 379 /// </summary> 380 /// <returns>ToolStripItem[]</returns> 381 // ------------------------------------------------------------------ 382 public override ToolStripItem[] Menu() 383 { 384 return null; 385 } 386 387 // ------------------------------------------------------------------ 388 /// <summary> 389 /// Returns the connector hit by the mouse, if any. 390 /// </summary> 391 /// <param name="p">Point: The mouse coordinates</param> 392 /// <returns>IConnector: The connector hit by the mouse</returns> 393 // ------------------------------------------------------------------ 394 public IConnector HitConnector(Point p) 395 { 396 for (int k = 0; k < mConnectors.Count; k++) 397 { 398 if (mConnectors[k].Hit(p)) 399 { 400 mConnectors[k].Hovered = true; 401 mConnectors[k].Invalidate(); 402 return mConnectors[k]; 403 } 404 else 405 { 406 mConnectors[k].Hovered = false; 407 mConnectors[k].Invalidate(); 408 409 } 410 411 412 } 413 return null; 414 } 415 416 // ------------------------------------------------------------------ 417 /// <summary> 418 /// Overrides the abstract paint method. Nothing performed here, 419 /// let the sub-shapes do the painting. 420 /// </summary> 421 /// <param name="g">a graphics object onto which to paint</param> 422 // ------------------------------------------------------------------ 423 public override void Paint(Graphics g) 424 { 425 return; 426 } 427 428 // ------------------------------------------------------------------ 429 /// <summary> 430 /// Override the abstract Hit method. Here a simple hit test is 431 /// performed by checking if our "Rectangle" contains the point 432 /// specified. Override this to perform more complex hit testing. 433 /// </summary> 434 /// <param name="p">Point</param> 435 /// <returns>bool</returns> 436 // ------------------------------------------------------------------ 437 public override bool Hit(Point p) 438 { 439 Rectangle r = new Rectangle(p, new Size(5, 5)); 440 return Rectangle.Contains(r); 441 } 442 443 // ------------------------------------------------------------------ 444 /// <summary> 445 /// Overrides the abstract Invalidate method. This shape's rectangle 446 /// is inflated (not permanently) by a size of (40, 40) to ensure 447 /// the whole area is refreshed. 448 /// </summary> 449 // ------------------------------------------------------------------ 450 public override void Invalidate() 451 { 452 Rectangle r = Rectangle; 453 r.Offset(-10, -10); 454 r.Inflate(40, 40); 455 if (Model != null) 456 { 457 Model.RaiseOnInvalidateRectangle(r); 458 } 459 } 460 461 // ------------------------------------------------------------------ 462 /// <summary> 463 /// Moves the entity with the given shift (offset). 464 /// </summary> 465 /// <param name="p">Represents a shift-vector, not the absolute 466 /// position!</param> 467 // ------------------------------------------------------------------ 468 public override void MoveBy(Point p) 469 { 470 Rectangle recBefore = mRectangle; 471 recBefore.Inflate(20, 20); 472 473 this.mRectangle.X += p.X; 474 this.mRectangle.Y += p.Y; 475 476 UpdatePaintingMaterial(); 477 478 for (int k = 0; k < this.mConnectors.Count; k++) 479 { 480 mConnectors[k].MoveBy(p); 481 } 482 RaiseOnChange(this, new EntityEventArgs(this)); 483 //refresh things 484 this.Invalidate(recBefore);//position before the move 485 this.Invalidate();//current position 486 487 } 488 489 // ------------------------------------------------------------------ 490 /// <summary> 491 /// Scales the entity with the given factor at the given origin. 492 /// <remarks>More an historical milestone than used code.</remarks> 493 /// </summary> 494 /// <param name="origin">The origin.</param> 495 /// <param name="scaleX">The scale X.</param> 496 /// <param name="scaleY">The scale Y.</param> 497 // ------------------------------------------------------------------ 498 void Scale( 499 Point origin, 500 double scaleX, 501 double scaleY) 502 { 503 #region Variables 504 //temporary variables to assign the new location of the mConnectors 505 double a, b; 506 //the new location of the connector 507 Point p; 508 //calculated/scaled/biased corners of the new rectangle 509 double ltx = 0, lty = 0, rbx = 0, rby = 0; 510 511 Rectangle currentRectangle = Rectangle; 512 //we only need to transform the LT and RB corners since the rest of the rectangle can be deduced from that 513 /* 514 PointF[] corners = new PointF[]{new PointF(currentRectangle.X, currentRectangle.Y), 515 new PointF(currentRectangle.Right, currentRectangle.Bottom), 516 517 }; 518 */ 519 Rectangle newRectangle; 520 #endregion 521 522 #region Transformation matrix 523 524 ltx = Math.Round((currentRectangle.X - origin.X) * scaleX, 1) + origin.X; 525 lty = Math.Round((currentRectangle.Y - origin.Y) * scaleY, 1) + origin.Y; 526 527 rbx = Math.Round((currentRectangle.Right - origin.X) * scaleX, 1) + origin.X; 528 rby = Math.Round((currentRectangle.Bottom - origin.Y) * scaleY, 1) + origin.Y; 529 530 //corners[0] = new PointF 531 //Matrix m = new Matrix(); 532 // m.Translate(-origin.X, -origin.Y,MatrixOrder.Append); 533 // m.Scale(scaleX, scaleY, MatrixOrder.Append); 534 // m.Translate(origin.X, origin.Y, MatrixOrder.Append); 535 #endregion 536 537 //transfor the LTRB points of the current rectangle 538 //m.TransformPoints(corners); 539 540 #region Bias 541 /* 458 }; 459 */ 460 Rectangle newRectangle; 461 #endregion 462 463 #region Transformation matrix 464 465 ltx = Math.Round((currentRectangle.X - origin.X) * scaleX, 1) + origin.X; 466 lty = Math.Round((currentRectangle.Y - origin.Y) * scaleY, 1) + origin.Y; 467 468 rbx = Math.Round((currentRectangle.Right - origin.X) * scaleX, 1) + origin.X; 469 rby = Math.Round((currentRectangle.Bottom - origin.Y) * scaleY, 1) + origin.Y; 470 471 //corners[0] = new PointF 472 //Matrix m = new Matrix(); 473 // m.Translate(-origin.X, -origin.Y,MatrixOrder.Append); 474 // m.Scale(scaleX, scaleY, MatrixOrder.Append); 475 // m.Translate(origin.X, origin.Y, MatrixOrder.Append); 476 #endregion 477 478 //transfor the LTRB points of the current rectangle 479 //m.TransformPoints(corners); 480 481 #region Bias 482 /* 542 483 if(currentRectangle.Y <= origin.Y + ViewBase.TrackerOffset && origin.Y - ViewBase.TrackerOffset <= currentRectangle.Y) 543 484 { … … 564 505 } 565 506 */ 566 567 507 #endregion 508 /* 568 509 ltx = Math.Round(ltx); 569 510 lty = Math.Round(lty); … … 571 512 rby = Math.Round(rby); 572 513 * */ 573 //now we can re-create the rectangle of this shape 574 //newRectangle = RectangleF.FromLTRB(ltx, lty, rbx, rby); 575 newRectangle = Rectangle.FromLTRB(Convert.ToInt32(ltx), Convert.ToInt32(lty), Convert.ToInt32(rbx), Convert.ToInt32(rby)); 576 //if ((newRectangle.Width <= 50 && scaleX < 1) || (newRectangle.Height <= 50 && scaleY < 1)) 577 // return; 578 #region Scaling of the mConnectors 579 //Note that this mechanism is way easier than the calculations in the old Netron library 580 //and it also allows dynamic mConnectors. 581 foreach (IConnector cn in this.mConnectors) 582 { 583 //De profundis: ge wilt het gewoon nie weten hoeveel bloed, zweet en tranen ik in de onderstaande berekeningen heb gestoken... 584 //met al de afrondingen en meetkundinge schaalafwijkingen..tis een wonder dat ik eruit ben geraakt. 585 586 //Scaling preserves proportions, so we calculate the proportions before the rectangle was resized and 587 //re-assign the same proportion after the rectangle is resized. 588 //I have tried many, many different possibilities but the accumulation of double-to-int conversions is a real pain. 589 //The only working solution I found was to cut things off after the first decimal. 590 a = Math.Round(((double)cn.Point.X - (double)mRectangle.X) / (double)mRectangle.Width, 1) * newRectangle.Width + ltx; 591 b = Math.Round(((double)cn.Point.Y - (double)mRectangle.Y) / (double)mRectangle.Height, 1) * newRectangle.Height + lty; 592 p = new Point(Convert.ToInt32(a), Convert.ToInt32(b)); 593 cn.Point = p; 594 } 595 #endregion 596 597 //assign the new calculated rectangle to this shape 598 this.mRectangle = newRectangle; 599 600 RaiseOnChange(this, new EntityEventArgs(this)); 601 602 //invalidate the space before the resize; very important if the scaling is a contraction! 603 this.Invalidate(currentRectangle); 604 //invalidate the current situation 605 this.Invalidate(); 606 } 607 608 // ------------------------------------------------------------------ 609 /// <summary> 610 /// Transforms the entity to the given new rectangle. 611 /// </summary> 612 /// <param name="x">The x-coordinate of the new rectangle.</param> 613 /// <param name="y">The y-coordinate of the new rectangle.</param> 614 /// <param name="width">The width.</param> 615 /// <param name="height">The height.</param> 616 // ------------------------------------------------------------------ 617 public virtual void Transform(int x, int y, int width, int height) 618 { 619 // Make sure the new size is valid. 620 if ((width < myMinSize.Width) || 621 (height < myMinSize.Height) || 622 (width > myMaxSize.Width) || 623 (height > myMaxSize.Height)) 624 { 625 return; 626 } 627 628 double a, b; 629 Point p; 630 Rectangle before = mRectangle; 631 before.Inflate(20, 20); 632 foreach (IConnector cn in this.mConnectors) 633 { 634 a = Math.Round( 635 ( (double)cn.Point.X - (double)mRectangle.X ) / 636 (double)mRectangle.Width, 1) * width + x - cn.Point.X; 637 638 b = Math.Round( 639 ( (double)cn.Point.Y - (double)mRectangle.Y ) / 640 (double)mRectangle.Height, 1) * height + y - cn.Point.Y; 641 642 p = new Point(Convert.ToInt32(a), Convert.ToInt32(b)); 643 cn.MoveBy(p); 644 } 645 646 mRectangle = new Rectangle(x, y, width, height); 647 648 RaiseOnChange(this, new EntityEventArgs(this)); 649 650 // Update the material; the gradient depends on the rectangle 651 UpdatePaintingMaterial(); 652 Invalidate(before); 653 654 // If we're attached to a group, make sure to let him know 655 // we've moved/resized. 656 if (mGroup != null) 657 { 658 mGroup.CalculateRectangle(); 659 mGroup.Invalidate(); 660 661 // The group will invalidate us when it's invalidated so just 662 // stop now. 663 //return; 664 } 665 666 Invalidate(mRectangle); 667 } 668 669 // ------------------------------------------------------------------ 670 /// <summary> 671 /// Transforms the entity to the given new rectangle. 672 /// </summary> 673 /// <param name="rectangle">The new bounds.</param> 674 // ------------------------------------------------------------------ 675 public virtual void Transform(Rectangle rectangle) 676 { 677 Transform( 678 rectangle.X, 679 rectangle.Y, 680 rectangle.Width, 681 rectangle.Height); 682 } 683 684 #endregion 685 } 514 //now we can re-create the rectangle of this shape 515 //newRectangle = RectangleF.FromLTRB(ltx, lty, rbx, rby); 516 newRectangle = Rectangle.FromLTRB(Convert.ToInt32(ltx), Convert.ToInt32(lty), Convert.ToInt32(rbx), Convert.ToInt32(rby)); 517 //if ((newRectangle.Width <= 50 && scaleX < 1) || (newRectangle.Height <= 50 && scaleY < 1)) 518 // return; 519 #region Scaling of the mConnectors 520 //Note that this mechanism is way easier than the calculations in the old Netron library 521 //and it also allows dynamic mConnectors. 522 foreach (IConnector cn in this.mConnectors) { 523 //De profundis: ge wilt het gewoon nie weten hoeveel bloed, zweet en tranen ik in de onderstaande berekeningen heb gestoken... 524 //met al de afrondingen en meetkundinge schaalafwijkingen..tis een wonder dat ik eruit ben geraakt. 525 526 //Scaling preserves proportions, so we calculate the proportions before the rectangle was resized and 527 //re-assign the same proportion after the rectangle is resized. 528 //I have tried many, many different possibilities but the accumulation of double-to-int conversions is a real pain. 529 //The only working solution I found was to cut things off after the first decimal. 530 a = Math.Round(((double)cn.Point.X - (double)mRectangle.X) / (double)mRectangle.Width, 1) * newRectangle.Width + ltx; 531 b = Math.Round(((double)cn.Point.Y - (double)mRectangle.Y) / (double)mRectangle.Height, 1) * newRectangle.Height + lty; 532 p = new Point(Convert.ToInt32(a), Convert.ToInt32(b)); 533 cn.Point = p; 534 } 535 #endregion 536 537 //assign the new calculated rectangle to this shape 538 this.mRectangle = newRectangle; 539 540 RaiseOnChange(this, new EntityEventArgs(this)); 541 542 //invalidate the space before the resize; very important if the scaling is a contraction! 543 this.Invalidate(currentRectangle); 544 //invalidate the current situation 545 this.Invalidate(); 546 } 547 548 // ------------------------------------------------------------------ 549 /// <summary> 550 /// Transforms the entity to the given new rectangle. 551 /// </summary> 552 /// <param name="x">The x-coordinate of the new rectangle.</param> 553 /// <param name="y">The y-coordinate of the new rectangle.</param> 554 /// <param name="width">The width.</param> 555 /// <param name="height">The height.</param> 556 // ------------------------------------------------------------------ 557 public virtual void Transform(int x, int y, int width, int height) { 558 // Make sure the new size is valid. 559 if ((width < myMinSize.Width) || 560 (height < myMinSize.Height) || 561 (width > myMaxSize.Width) || 562 (height > myMaxSize.Height)) { 563 return; 564 } 565 566 double a, b; 567 Point p; 568 Rectangle before = mRectangle; 569 before.Inflate(20, 20); 570 foreach (IConnector cn in this.mConnectors) { 571 a = Math.Round( 572 ((double)cn.Point.X - (double)mRectangle.X) / 573 (double)mRectangle.Width, 1) * width + x - cn.Point.X; 574 575 b = Math.Round( 576 ((double)cn.Point.Y - (double)mRectangle.Y) / 577 (double)mRectangle.Height, 1) * height + y - cn.Point.Y; 578 579 p = new Point(Convert.ToInt32(a), Convert.ToInt32(b)); 580 cn.MoveBy(p); 581 } 582 583 mRectangle = new Rectangle(x, y, width, height); 584 585 RaiseOnChange(this, new EntityEventArgs(this)); 586 587 // Update the material; the gradient depends on the rectangle 588 UpdatePaintingMaterial(); 589 Invalidate(before); 590 591 // If we're attached to a group, make sure to let him know 592 // we've moved/resized. 593 if (mGroup != null) { 594 mGroup.CalculateRectangle(); 595 mGroup.Invalidate(); 596 597 // The group will invalidate us when it's invalidated so just 598 // stop now. 599 //return; 600 } 601 602 Invalidate(mRectangle); 603 } 604 605 // ------------------------------------------------------------------ 606 /// <summary> 607 /// Transforms the entity to the given new rectangle. 608 /// </summary> 609 /// <param name="rectangle">The new bounds.</param> 610 // ------------------------------------------------------------------ 611 public virtual void Transform(Rectangle rectangle) { 612 Transform( 613 rectangle.X, 614 rectangle.Y, 615 rectangle.Width, 616 rectangle.Height); 617 } 618 619 #endregion 620 } 686 621 }
Note: See TracChangeset
for help on using the changeset viewer.