Changeset 522 for GraphicTest/Packages/Graphics32/GR32_Layers.pas
- Timestamp:
- Apr 17, 2019, 10:42:18 AM (5 years ago)
- Location:
- GraphicTest/Packages/Graphics32
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
GraphicTest/Packages/Graphics32
-
Property svn:ignore
set to
lib
-
Property svn:ignore
set to
-
GraphicTest/Packages/Graphics32/GR32_Layers.pas
r450 r522 63 63 TCustomLayer = class; 64 64 TPositionedLayer = class; 65 TRubberbandLayer = class; 65 66 TLayerClass = class of TCustomLayer; 66 67 … … 111 112 function MouseMove(Shift: TShiftState; X, Y: Integer): TCustomLayer; 112 113 function MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer): TCustomLayer; 114 113 115 property OnChanging: TNotifyEvent read FOnChanging write FOnChanging; 114 116 property OnChange: TNotifyEvent read FOnChange write FOnChange; … … 122 124 constructor Create(AOwner: TPersistent); 123 125 destructor Destroy; override; 126 124 127 function Add(ItemClass: TLayerClass): TCustomLayer; 125 128 procedure Assign(Source: TPersistent); override; … … 131 134 procedure GetViewportScale(out ScaleX, ScaleY: TFloat); virtual; 132 135 procedure GetViewportShift(out ShiftX, ShiftY: TFloat); virtual; 136 133 137 property Count: Integer read GetCount; 134 138 property Owner: TPersistent read FOwner; … … 137 141 property MouseEvents: Boolean read FMouseEvents write SetMouseEvents; 138 142 end; 143 144 {$IFDEF COMPILER2009_UP} 145 TLayerEnum = class 146 private 147 FIndex: Integer; 148 FLayerCollection: TLayerCollection; 149 public 150 constructor Create(ALayerCollection: TLayerCollection); 151 152 function GetCurrent: TCustomLayer; 153 function MoveNext: Boolean; 154 155 property Current: TCustomLayer read GetCurrent; 156 end; 157 158 TLayerCollectionHelper = class Helper for TLayerCollection 159 public 160 function GetEnumerator: TLayerEnum; 161 end; 162 {$ENDIF} 139 163 140 164 TLayerState = (lsMouseLeft, lsMouseRight, lsMouseMiddle); … … 151 175 FLayerStates: TLayerStates; 152 176 FLayerOptions: Cardinal; 177 FTag: Integer; 178 FClicked: Boolean; 153 179 FOnHitTest: THitTestEvent; 154 180 FOnMouseDown: TMouseEvent; … … 156 182 FOnMouseUp: TMouseEvent; 157 183 FOnPaint: TPaintLayerEvent; 158 FTag: Integer;159 184 FOnDestroy: TNotifyEvent; 185 FOnDblClick: TNotifyEvent; 186 FOnClick: TNotifyEvent; 160 187 function GetIndex: Integer; 161 188 function GetMouseEvents: Boolean; … … 170 197 procedure AddNotification(ALayer: TCustomLayer); 171 198 procedure Changing; 199 procedure Click; 200 procedure DblClick; 172 201 function DoHitTest(X, Y: Integer): Boolean; virtual; 173 202 procedure DoPaint(Buffer: TBitmap32); … … 184 213 procedure SetLayerCollection(Value: TLayerCollection); virtual; 185 214 procedure SetLayerOptions(Value: Cardinal); virtual; 215 186 216 property Invalid: Boolean read GetInvalid write SetInvalid; 187 217 property ForceUpdate: Boolean read GetForceUpdate write SetForceUpdate; … … 189 219 constructor Create(ALayerCollection: TLayerCollection); virtual; 190 220 destructor Destroy; override; 221 191 222 procedure BeforeDestruction; override; 192 223 procedure BringToFront; … … 198 229 procedure SendToBack; 199 230 procedure SetAsMouseListener; 231 200 232 property Cursor: TCursor read FCursor write SetCursor; 201 233 property Index: Integer read GetIndex write SetIndex; … … 206 238 property Tag: Integer read FTag write FTag; 207 239 property Visible: Boolean read GetVisible write SetVisible; 240 208 241 property OnDestroy: TNotifyEvent read FOnDestroy write FOnDestroy; 209 242 property OnHitTest: THitTestEvent read FOnHitTest write FOnHitTest; 210 243 property OnPaint: TPaintLayerEvent read FOnPaint write FOnPaint; 244 property OnClick: TNotifyEvent read FOnClick write FOnClick; 245 property OnDblClick: TNotifyEvent read FOnDblClick write FOnDblClick; 211 246 property OnMouseDown: TMouseEvent read FOnMouseDown write FOnMouseDown; 212 247 property OnMouseMove: TMouseMoveEvent read FOnMouseMove write FOnMouseMove; … … 225 260 public 226 261 constructor Create(ALayerCollection: TLayerCollection); override; 262 227 263 function GetAdjustedRect(const R: TFloatRect): TFloatRect; virtual; 228 264 function GetAdjustedLocation: TFloatRect; 265 229 266 property Location: TFloatRect read FLocation write SetLocation; 230 267 property Scaled: Boolean read FScaled write SetScaled; … … 245 282 constructor Create(ALayerCollection: TLayerCollection); override; 246 283 destructor Destroy; override; 284 247 285 property AlphaHit: Boolean read FAlphaHit write FAlphaHit; 248 286 property Bitmap: TBitmap32 read FBitmap write SetBitmap; … … 250 288 end; 251 289 252 T DragState = (dsNone, dsMove, dsSizeL, dsSizeT, dsSizeR, dsSizeB,290 TRBDragState = (dsNone, dsMove, dsSizeL, dsSizeT, dsSizeR, dsSizeB, 253 291 dsSizeTL, dsSizeTR, dsSizeBL, dsSizeBR); 254 292 TRBHandles = set of (rhCenter, rhSides, rhCorners, rhFrame, 255 293 rhNotLeftSide, rhNotRightSide, rhNotTopSide, rhNotBottomSide, 256 294 rhNotTLCorner, rhNotTRCorner, rhNotBLCorner, rhNotBRCorner); 257 TRBOptions = set of (roProportional, roConstrained );295 TRBOptions = set of (roProportional, roConstrained, roQuantized); 258 296 TRBResizingEvent = procedure( 259 297 Sender: TObject; 260 298 const OldLocation: TFloatRect; 261 299 var NewLocation: TFloatRect; 262 DragState: T DragState;300 DragState: TRBDragState; 263 301 Shift: TShiftState) of object; 264 302 TRBConstrainEvent = TRBResizingEvent; 303 304 TRubberbandPassMouse = class(TPersistent) 305 private 306 FOwner: TRubberbandLayer; 307 FEnabled: Boolean; 308 FToChild: Boolean; 309 FLayerUnderCursor: Boolean; 310 FCancelIfPassed: Boolean; 311 protected 312 function GetChildUnderCursor(X, Y: Integer): TPositionedLayer; 313 public 314 constructor Create(AOwner: TRubberbandLayer); 315 316 property Enabled: Boolean read FEnabled write FEnabled default False; 317 property ToChild: Boolean read FToChild write FToChild default False; 318 property ToLayerUnderCursor: Boolean read FLayerUnderCursor write FLayerUnderCursor default False; 319 property CancelIfPassed: Boolean read FCancelIfPassed write FCancelIfPassed default False; 320 end; 265 321 266 322 TRubberbandLayer = class(TPositionedLayer) … … 273 329 FHandleFill: TColor32; 274 330 FHandles: TRBHandles; 275 FHandleSize: Integer;331 FHandleSize: TFloat; 276 332 FMinWidth: TFloat; 277 333 FMaxHeight: TFloat; … … 282 338 FOnConstrain: TRBConstrainEvent; 283 339 FOptions: TRBOptions; 340 FQuantized: Integer; 341 FPassMouse: TRubberbandPassMouse; 284 342 procedure SetFrameStippleStep(const Value: TFloat); 285 343 procedure SetFrameStippleCounter(const Value: TFloat); … … 288 346 procedure SetHandleFrame(Value: TColor32); 289 347 procedure SetHandles(Value: TRBHandles); 290 procedure SetHandleSize(Value: Integer);348 procedure SetHandleSize(Value: TFloat); 291 349 procedure SetOptions(const Value: TRBOptions); 350 procedure SetQuantized(const Value: Integer); 292 351 protected 293 IsDragging: Boolean;294 DragState: TDragState;295 OldLocation: TFloatRect;296 MouseShift: TFloatPoint;352 FIsDragging: Boolean; 353 FDragState: TRBDragState; 354 FOldLocation: TFloatRect; 355 FMouseShift: TFloatPoint; 297 356 function DoHitTest(X, Y: Integer): Boolean; override; 298 procedure DoResizing(var OldLocation, NewLocation: TFloatRect; DragState: T DragState; Shift: TShiftState); virtual;299 procedure DoConstrain(var OldLocation, NewLocation: TFloatRect; DragState: T DragState; Shift: TShiftState); virtual;357 procedure DoResizing(var OldLocation, NewLocation: TFloatRect; DragState: TRBDragState; Shift: TShiftState); virtual; 358 procedure DoConstrain(var OldLocation, NewLocation: TFloatRect; DragState: TRBDragState; Shift: TShiftState); virtual; 300 359 procedure DoSetLocation(const NewLocation: TFloatRect); override; 301 function GetDragState(X, Y: Integer): T DragState; virtual;360 function GetDragState(X, Y: Integer): TRBDragState; virtual; 302 361 procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; 303 362 procedure MouseMove(Shift: TShiftState; X, Y: Integer); override; … … 306 365 procedure Paint(Buffer: TBitmap32); override; 307 366 procedure SetLayerOptions(Value: Cardinal); override; 367 procedure SetDragState(const Value: TRBDragState); overload; 368 procedure SetDragState(const Value: TRBDragState; const X, Y: Integer); overload; 308 369 procedure UpdateChildLayer; 370 procedure DrawHandle(Buffer: TBitmap32; X, Y: TFloat); virtual; 309 371 public 310 372 constructor Create(ALayerCollection: TLayerCollection); override; 373 destructor Destroy; override; 374 311 375 procedure SetFrameStipple(const Value: Array of TColor32); 376 procedure Quantize; 377 312 378 property ChildLayer: TPositionedLayer read FChildLayer write SetChildLayer; 313 379 property Options: TRBOptions read FOptions write SetOptions; 314 380 property Handles: TRBHandles read FHandles write SetHandles; 315 property HandleSize: Integerread FHandleSize write SetHandleSize;381 property HandleSize: TFloat read FHandleSize write SetHandleSize; 316 382 property HandleFill: TColor32 read FHandleFill write SetHandleFill; 317 383 property HandleFrame: TColor32 read FHandleFrame write SetHandleFrame; … … 322 388 property MinHeight: TFloat read FMinHeight write FMinHeight; 323 389 property MinWidth: TFloat read FMinWidth write FMinWidth; 390 property Quantized: Integer read FQuantized write SetQuantized default 8; 391 property PassMouseToChild: TRubberbandPassMouse read FPassMouse; 392 324 393 property OnUserChange: TNotifyEvent read FOnUserChange write FOnUserChange; 325 394 property OnConstrain: TRBConstrainEvent read FOnConstrain write FOnConstrain; … … 330 399 331 400 uses 332 TypInfo, GR32_Image, GR32_LowLevel, GR32_Resamplers, GR32_RepaintOpt ;401 TypInfo, GR32_Image, GR32_LowLevel, GR32_Resamplers, GR32_RepaintOpt, Types; 333 402 334 403 { mouse state mapping } … … 375 444 procedure TLayerCollection.BeginUpdate; 376 445 begin 377 if FUpdateCount = 0 then Changing; 446 if FUpdateCount = 0 then 447 Changing; 378 448 Inc(FUpdateCount); 379 449 end; … … 381 451 procedure TLayerCollection.Changed; 382 452 begin 383 if Assigned(FOnChange) then FOnChange(Self); 453 if Assigned(FOnChange) then 454 FOnChange(Self); 384 455 end; 385 456 386 457 procedure TLayerCollection.Changing; 387 458 begin 388 if Assigned(FOnChanging) then FOnChanging(Self); 459 if Assigned(FOnChanging) then 460 FOnChanging(Self); 389 461 end; 390 462 … … 415 487 begin 416 488 FUpdateCount := 1; // disable update notification 417 if Assigned(FItems) then Clear; 489 if Assigned(FItems) then 490 Clear; 418 491 FItems.Free; 419 492 inherited; … … 423 496 begin 424 497 Dec(FUpdateCount); 425 if FUpdateCount = 0 then Changed; 498 if FUpdateCount = 0 then 499 Changed; 426 500 Assert(FUpdateCount >= 0, 'Unpaired EndUpdate'); 427 501 end; … … 434 508 begin 435 509 Result := Items[I]; 436 if (Result.LayerOptions and OptionsMask) = 0 then Continue; // skip to the next one 510 if (Result.LayerOptions and OptionsMask) = 0 then 511 Continue; // skip to the next one 437 512 if Result.HitTest(X, Y) then Exit; 438 513 end; … … 442 517 procedure TLayerCollection.GDIUpdate; 443 518 begin 444 if (FUpdateCount = 0) and Assigned(FOnGDIUpdate) then FOnGDIUpdate(Self); 519 if (FUpdateCount = 0) and Assigned(FOnGDIUpdate) then 520 FOnGDIUpdate(Self); 445 521 end; 446 522 … … 538 614 begin 539 615 Result := MouseListener; 540 if Result = nil then Result := FindLayerAtPos(X, Y, LOB_MOUSE_EVENTS); 541 if Assigned(Result) then Result.MouseMove(Shift, X, Y) 542 else if FOwner is TControl then Screen.Cursor := TControl(FOwner).Cursor; 616 if Result = nil then 617 Result := FindLayerAtPos(X, Y, LOB_MOUSE_EVENTS); 618 619 if Assigned(Result) then 620 Result.MouseMove(Shift, X, Y) 621 else if FOwner is TControl then 622 Screen.Cursor := TControl(FOwner).Cursor; 543 623 end; 544 624 … … 546 626 begin 547 627 Result := MouseListener; 548 if Result = nil then Result := FindLayerAtPos(X, Y, LOB_MOUSE_EVENTS); 628 if Result = nil then 629 Result := FindLayerAtPos(X, Y, LOB_MOUSE_EVENTS); 549 630 550 631 if Assigned(Result) then … … 562 643 procedure TLayerCollection.Notify(Action: TLayerListNotification; Layer: TCustomLayer; Index: Integer); 563 644 begin 564 if Assigned(FOnListNotify) then FOnListNotify(Self, Action, Layer, Index); 645 if Assigned(FOnListNotify) then 646 FOnListNotify(Self, Action, Layer, Index); 565 647 end; 566 648 … … 607 689 procedure TLayerCollection.DoUpdateArea(const Rect: TRect); 608 690 begin 609 if Assigned(FOnAreaUpdated) then FOnAreaUpdated(Self, Rect, AREAINFO_RECT); 610 Changed; 691 if Assigned(FOnAreaUpdated) then 692 FOnAreaUpdated(Self, Rect, AREAINFO_RECT); 693 Changed; 611 694 end; 612 695 613 696 procedure TLayerCollection.DoUpdateLayer(Layer: TCustomLayer); 614 697 begin 615 if Assigned(FOnLayerUpdated) then FOnLayerUpdated(Self, Layer); 698 if Assigned(FOnLayerUpdated) then 699 FOnLayerUpdated(Self, Layer); 616 700 Changed; 617 701 end; … … 639 723 end; 640 724 725 726 {$IFDEF COMPILER2009_UP} 727 { TLayerEnum } 728 729 constructor TLayerEnum.Create(ALayerCollection: TLayerCollection); 730 begin 731 inherited Create; 732 FLayerCollection := ALayerCollection; 733 FIndex := -1; 734 end; 735 736 function TLayerEnum.GetCurrent: TCustomLayer; 737 begin 738 Result := FLayerCollection.Items[FIndex]; 739 end; 740 741 function TLayerEnum.MoveNext: Boolean; 742 begin 743 Result := FIndex < Pred(FLayerCollection.Count); 744 if Result then 745 Inc(FIndex); 746 end; 747 748 749 { TLayerCollectionHelper } 750 751 function TLayerCollectionHelper.GetEnumerator: TLayerEnum; 752 begin 753 Result := TLayerEnum.Create(Self); 754 end; 755 {$ENDIF} 756 757 641 758 { TCustomLayer } 642 759 760 constructor TCustomLayer.Create(ALayerCollection: TLayerCollection); 761 begin 762 LayerCollection := ALayerCollection; 763 FLayerOptions := LOB_VISIBLE; 764 end; 765 766 destructor TCustomLayer.Destroy; 767 var 768 I: Integer; 769 begin 770 if Assigned(FFreeNotifies) then 771 begin 772 for I := FFreeNotifies.Count - 1 downto 0 do 773 begin 774 TCustomLayer(FFreeNotifies[I]).Notification(Self); 775 if FFreeNotifies = nil then Break; 776 end; 777 FFreeNotifies.Free; 778 FFreeNotifies := nil; 779 end; 780 SetLayerCollection(nil); 781 inherited; 782 end; 783 643 784 procedure TCustomLayer.AddNotification(ALayer: TCustomLayer); 644 785 begin 645 if not Assigned(FFreeNotifies) then FFreeNotifies := TList.Create; 646 if FFreeNotifies.IndexOf(ALayer) < 0 then FFreeNotifies.Add(ALayer); 786 if not Assigned(FFreeNotifies) then 787 FFreeNotifies := TList.Create; 788 if FFreeNotifies.IndexOf(ALayer) < 0 then 789 FFreeNotifies.Add(ALayer); 647 790 end; 648 791 649 792 procedure TCustomLayer.BeforeDestruction; 650 793 begin 651 if Assigned(FOnDestroy) then FOnDestroy(Self); 794 if Assigned(FOnDestroy) then 795 FOnDestroy(Self); 652 796 inherited; 653 797 end; … … 664 808 begin 665 809 Update; 666 if Visible then FLayerCollection.Changed 810 if Visible then 811 FLayerCollection.Changed 667 812 else if (FLayerOptions and LOB_GDI_OVERLAY) <> 0 then 668 813 FLayerCollection.GDIUpdate; … … 678 823 begin 679 824 Update(Rect); 680 if Visible then FLayerCollection.Changed 825 if Visible then 826 FLayerCollection.Changed 681 827 else if (FLayerOptions and LOB_GDI_OVERLAY) <> 0 then 682 828 FLayerCollection.GDIUpdate; … … 694 840 end; 695 841 696 constructor TCustomLayer.Create(ALayerCollection: TLayerCollection); 697 begin 698 LayerCollection := ALayerCollection; 699 FLayerOptions := LOB_VISIBLE; 700 end; 701 702 destructor TCustomLayer.Destroy; 703 var 704 I: Integer; 705 begin 706 if Assigned(FFreeNotifies) then 707 begin 708 for I := FFreeNotifies.Count - 1 downto 0 do 709 begin 710 TCustomLayer(FFreeNotifies[I]).Notification(Self); 711 if FFreeNotifies = nil then Break; 712 end; 713 FFreeNotifies.Free; 714 FFreeNotifies := nil; 715 end; 716 SetLayerCollection(nil); 717 inherited; 842 procedure TCustomLayer.Click; 843 begin 844 FClicked := False; 845 if Assigned(FOnClick) then 846 FOnClick(Self); 847 end; 848 849 procedure TCustomLayer.DblClick; 850 begin 851 FClicked := False; 852 if Assigned(FOnDblClick) then 853 FOnDblClick(Self); 718 854 end; 719 855 720 856 function TCustomLayer.DoHitTest(X, Y: Integer): Boolean; 721 857 begin 722 Result := True;858 Result := Visible; 723 859 end; 724 860 … … 726 862 begin 727 863 Paint(Buffer); 728 if Assigned(FOnPaint) then FOnPaint(Self, Buffer); 864 if Assigned(FOnPaint) then 865 FOnPaint(Self, Buffer); 729 866 end; 730 867 … … 755 892 begin 756 893 Result := DoHitTest(X, Y); 757 if Assigned(FOnHitTest) then FOnHitTest(Self, X, Y, Result); 894 if Assigned(FOnHitTest) then 895 FOnHitTest(Self, X, Y, Result); 758 896 end; 759 897 760 898 procedure TCustomLayer.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); 761 899 begin 762 if Assigned(FOnMouseDown) then FOnMouseDown(Self, Button, Shift, X, Y); 900 if (Button = mbLeft) then 901 begin 902 if (ssDouble in Shift) then 903 DblClick 904 else 905 FClicked := True; 906 end; 907 if Assigned(FOnMouseDown) then 908 FOnMouseDown(Self, Button, Shift, X, Y); 763 909 end; 764 910 … … 766 912 begin 767 913 Screen.Cursor := Cursor; 768 if Assigned(FOnMouseMove) then FOnMouseMove(Self, Shift, X, Y); 914 if Assigned(FOnMouseMove) then 915 FOnMouseMove(Self, Shift, X, Y); 769 916 end; 770 917 … … 772 919 begin 773 920 Screen.Cursor := crDefault; 774 if Assigned(FOnMouseUp) then FOnMouseUp(Self, Button, Shift, X, Y); 921 if (Button = mbLeft) and FClicked then 922 Click; 923 if Assigned(FOnMouseUp) then 924 FOnMouseUp(Self, Button, Shift, X, Y); 775 925 end; 776 926 … … 819 969 begin 820 970 FCursor := Value; 821 if FLayerCollection.MouseListener = Self then Screen.Cursor := Value; 971 if FLayerCollection.MouseListener = Self then 972 Screen.Cursor := Value; 822 973 end; 823 974 end; … … 857 1008 if Assigned(Value) then 858 1009 Value.InsertItem(Self); 1010 FLayerCollection := Value; 859 1011 end; 860 1012 end; … … 948 1100 begin 949 1101 with GetAdjustedRect(FLocation) do 950 Result := (X >= Left) and (X < Right) and (Y >= Top) and (Y < Bottom); 1102 Result := (X >= Left) and (X < Right) and (Y >= Top) and (Y < Bottom) and 1103 inherited DoHitTest(X, Y); 951 1104 end; 952 1105 … … 1076 1229 DstRect := MakeRect(GetAdjustedRect(FLocation)); 1077 1230 ClipRect := Buffer.ClipRect; 1078 IntersectRect(TempRect, ClipRect, DstRect);1079 if IsRectEmpty(TempRect) then Exit;1231 GR32.IntersectRect(TempRect, ClipRect, DstRect); 1232 if GR32.IsRectEmpty(TempRect) then Exit; 1080 1233 1081 1234 SrcRect := MakeRect(0, 0, Bitmap.Width, Bitmap.Height); … … 1090 1243 if (LayerWidth < 0.5) or (LayerHeight < 0.5) then Exit; 1091 1244 ImageRect := TCustomImage32(LayerCollection.FOwner).GetBitmapRect; 1092 IntersectRect(ClipRect, ClipRect, ImageRect);1245 GR32.IntersectRect(ClipRect, ClipRect, ImageRect); 1093 1246 end; 1094 1247 StretchTransfer(Buffer, DstRect, ClipRect, FBitmap, SrcRect, … … 1109 1262 end; 1110 1263 end; 1264 1265 1266 { TRubberbandPassMouse } 1267 1268 constructor TRubberbandPassMouse.Create(AOwner: TRubberbandLayer); 1269 begin 1270 FOwner := AOwner; 1271 FEnabled := False; 1272 FToChild := False; 1273 FLayerUnderCursor := False; 1274 FCancelIfPassed := False; 1275 end; 1276 1277 function TRubberbandPassMouse.GetChildUnderCursor(X, Y: Integer): TPositionedLayer; 1278 var 1279 Layer: TCustomLayer; 1280 Index: Integer; 1281 begin 1282 Result := nil; 1283 for Index := FOwner.LayerCollection.Count - 1 downto 0 do 1284 begin 1285 Layer := FOwner.LayerCollection.Items[Index]; 1286 if ((Layer.LayerOptions and LOB_MOUSE_EVENTS) > 0) and 1287 (Layer is TPositionedLayer) and Layer.HitTest(X, Y) then 1288 begin 1289 Result := TPositionedLayer(Layer); 1290 Exit; 1291 end; 1292 end; 1293 end; 1294 1111 1295 1112 1296 { TRubberbandLayer } … … 1121 1305 FMinWidth := 10; 1122 1306 FMinHeight := 10; 1307 FQuantized := 8; 1123 1308 FLayerOptions := LOB_VISIBLE or LOB_MOUSE_EVENTS; 1124 1309 SetFrameStipple([clWhite32, clWhite32, clBlack32, clBlack32]); 1310 FPassMouse := TRubberbandPassMouse.Create(Self); 1125 1311 FFrameStippleStep := 1; 1126 1312 FFrameStippleCounter := 0; 1127 1313 end; 1128 1314 1315 destructor TRubberbandLayer.Destroy; 1316 begin 1317 FPassMouse.Free; 1318 inherited; 1319 end; 1320 1129 1321 function TRubberbandLayer.DoHitTest(X, Y: Integer): Boolean; 1130 1322 begin 1131 Result := GetDragState(X, Y) <> dsNone; 1323 if (Visible) then 1324 Result := (GetDragState(X, Y) <> dsNone) 1325 else 1326 Result := False; 1132 1327 end; 1133 1328 1134 1329 procedure TRubberbandLayer.DoResizing(var OldLocation, 1135 NewLocation: TFloatRect; DragState: T DragState; Shift: TShiftState);1330 NewLocation: TFloatRect; DragState: TRBDragState; Shift: TShiftState); 1136 1331 begin 1137 1332 if Assigned(FOnResizing) then … … 1140 1335 1141 1336 procedure TRubberbandLayer.DoConstrain(var OldLocation, 1142 NewLocation: TFloatRect; DragState: T DragState; Shift: TShiftState);1337 NewLocation: TFloatRect; DragState: TRBDragState; Shift: TShiftState); 1143 1338 begin 1144 1339 if Assigned(FOnConstrain) then … … 1152 1347 end; 1153 1348 1154 function TRubberbandLayer.GetDragState(X, Y: Integer): T DragState;1349 function TRubberbandLayer.GetDragState(X, Y: Integer): TRBDragState; 1155 1350 var 1156 1351 R: TRect; … … 1158 1353 dl, dt, dr, db, dx, dy: Boolean; 1159 1354 Sz: Integer; 1355 const 1356 DragZone = 1; 1160 1357 begin 1161 1358 Result := dsNone; 1162 Sz := FHandleSize + 1;1359 Sz := Ceil(FHandleSize + DragZone); 1163 1360 dh_center := rhCenter in FHandles; 1164 1361 dh_sides := rhSides in FHandles; … … 1186 1383 else if dl and dy and dh_sides and not(rhNotLeftSide in FHandles) then Result := dsSizeL 1187 1384 else if dt and dx and dh_sides and not(rhNotTopSide in FHandles) then Result := dsSizeT 1188 else if dh_center and PtInRect(R,Point(X, Y)) then Result := dsMove;1385 else if dh_center and GR32.PtInRect(R, GR32.Point(X, Y)) then Result := dsMove; 1189 1386 end; 1190 1387 1191 1388 procedure TRubberbandLayer.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); 1192 1389 var 1193 ALoc: TFloatRect; 1194 begin 1195 if IsDragging then Exit; 1196 DragState := GetDragState(X, Y); 1197 IsDragging := DragState <> dsNone; 1198 if IsDragging then 1199 begin 1200 OldLocation := Location; 1201 1202 ALoc := GetAdjustedRect(FLocation); 1203 case DragState of 1204 dsMove: MouseShift := FloatPoint(X - ALoc.Left, Y - ALoc.Top); 1390 PositionedLayer: TPositionedLayer; 1391 begin 1392 if FPassMouse.Enabled then 1393 begin 1394 if FPassMouse.ToLayerUnderCursor then 1395 PositionedLayer := FPassMouse.GetChildUnderCursor(X, Y) 1205 1396 else 1206 MouseShift := FloatPoint(0, 0); 1207 end; 1208 end; 1397 PositionedLayer := ChildLayer; 1398 1399 if FPassMouse.ToChild and Assigned(ChildLayer) then 1400 begin 1401 ChildLayer.MouseDown(Button, Shift, X, Y); 1402 if FPassMouse.CancelIfPassed then 1403 Exit; 1404 end; 1405 1406 if (PositionedLayer <> ChildLayer) and Assigned(PositionedLayer) then 1407 begin 1408 PositionedLayer.MouseDown(Button, Shift, X, Y); 1409 if FPassMouse.CancelIfPassed then 1410 Exit; 1411 end; 1412 end; 1413 1414 if FIsDragging then Exit; 1415 SetDragState(GetDragState(X, Y), X, Y); 1209 1416 inherited; 1210 1417 end; … … 1212 1419 procedure TRubberbandLayer.MouseMove(Shift: TShiftState; X, Y: Integer); 1213 1420 const 1214 CURSOR_ID: array [T DragState] of TCursor = (crDefault, crDefault, crSizeWE,1421 CURSOR_ID: array [TRBDragState] of TCursor = (crDefault, crDefault, crSizeWE, 1215 1422 crSizeNS, crSizeWE, crSizeNS, crSizeNWSE, crSizeNESW, crSizeNESW, crSizeNWSE); 1216 1423 var 1217 1424 Mx, My: TFloat; 1218 1425 L, T, R, B, W, H: TFloat; 1426 Quantize: Boolean; 1219 1427 ALoc, NewLocation: TFloatRect; 1220 1428 … … 1234 1442 1235 1443 begin 1236 if not IsDragging then 1237 begin 1238 DragState := GetDragState(X, Y); 1239 if DragState = dsMove then Screen.Cursor := Cursor 1240 else Screen.Cursor := CURSOR_ID[DragState]; 1444 if not FIsDragging then 1445 begin 1446 FDragState := GetDragState(X, Y); 1447 if FDragState = dsMove then 1448 Screen.Cursor := Cursor 1449 else 1450 Screen.Cursor := CURSOR_ID[FDragState]; 1241 1451 end 1242 1452 else 1243 1453 begin 1244 Mx := X - MouseShift.X;1245 My := Y - MouseShift.Y;1454 Mx := X - FMouseShift.X; 1455 My := Y - FMouseShift.Y; 1246 1456 if Scaled then 1247 1457 with Location do 1248 1458 begin 1249 1459 ALoc := GetAdjustedRect(FLocation); 1250 if IsRectEmpty(ALoc) then Exit;1460 if GR32.IsRectEmpty(ALoc) then Exit; 1251 1461 Mx := (Mx - ALoc.Left) / (ALoc.Right - ALoc.Left) * (Right - Left) + Left; 1252 1462 My := (My - ALoc.Top) / (ALoc.Bottom - ALoc.Top) * (Bottom - Top) + Top; 1253 1463 end; 1254 1464 1255 with OldLocation do1465 with FOldLocation do 1256 1466 begin 1257 1467 L := Left; … … 1263 1473 end; 1264 1474 1265 if DragState = dsMove then 1475 Quantize := (roQuantized in Options) and not (ssAlt in Shift); 1476 1477 if FDragState = dsMove then 1266 1478 begin 1267 1479 L := Mx; 1268 1480 T := My; 1481 if Quantize then 1482 begin 1483 L := Round(L / FQuantized) * FQuantized; 1484 T := Round(T / FQuantized) * FQuantized; 1485 end; 1269 1486 R := L + W; 1270 1487 B := T + H; … … 1272 1489 else 1273 1490 begin 1274 if DragState in [dsSizeL, dsSizeTL, dsSizeBL] then 1491 if FDragState in [dsSizeL, dsSizeTL, dsSizeBL] then 1492 begin 1275 1493 IncLT(L, R, Mx - L, MinWidth, MaxWidth); 1276 1277 if DragState in [dsSizeR, dsSizeTR, dsSizeBR] then 1494 if Quantize then 1495 L := Round(L / FQuantized) * FQuantized; 1496 end; 1497 1498 if FDragState in [dsSizeR, dsSizeTR, dsSizeBR] then 1499 begin 1278 1500 IncRB(L, R, Mx - R, MinWidth, MaxWidth); 1279 1280 if DragState in [dsSizeT, dsSizeTL, dsSizeTR] then 1501 if Quantize then 1502 R := Round(R / FQuantized) * FQuantized; 1503 end; 1504 1505 if FDragState in [dsSizeT, dsSizeTL, dsSizeTR] then 1506 begin 1281 1507 IncLT(T, B, My - T, MinHeight, MaxHeight); 1282 1283 if DragState in [dsSizeB, dsSizeBL, dsSizeBR] then 1508 if Quantize then 1509 T := Round(T / FQuantized) * FQuantized; 1510 end; 1511 1512 if FDragState in [dsSizeB, dsSizeBL, dsSizeBR] then 1513 begin 1284 1514 IncRB(T, B, My - B, MinHeight, MaxHeight); 1515 if Quantize then 1516 B := Round(B / FQuantized) * FQuantized; 1517 end; 1285 1518 end; 1286 1519 … … 1288 1521 1289 1522 if roConstrained in FOptions then 1290 DoConstrain( OldLocation, NewLocation,DragState, Shift);1523 DoConstrain(FOldLocation, NewLocation, FDragState, Shift); 1291 1524 1292 1525 if roProportional in FOptions then 1293 1526 begin 1294 case DragState of1527 case FDragState of 1295 1528 dsSizeB, dsSizeBR: 1296 NewLocation.Right := OldLocation.Left + (OldLocation.Right - OldLocation.Left) * (NewLocation.Bottom - NewLocation.Top) / (OldLocation.Bottom -OldLocation.Top);1529 NewLocation.Right := FOldLocation.Left + (FOldLocation.Right - FOldLocation.Left) * (NewLocation.Bottom - NewLocation.Top) / (FOldLocation.Bottom - FOldLocation.Top); 1297 1530 dsSizeT, dsSizeTL: 1298 NewLocation.Left := OldLocation.Right - (OldLocation.Right - OldLocation.Left) * (NewLocation.Bottom - NewLocation.Top) / (OldLocation.Bottom -OldLocation.Top);1531 NewLocation.Left := FOldLocation.Right - (FOldLocation.Right - FOldLocation.Left) * (NewLocation.Bottom - NewLocation.Top) / (FOldLocation.Bottom - FOldLocation.Top); 1299 1532 dsSizeR, dsSizeBL: 1300 NewLocation.Bottom := OldLocation.Top + (OldLocation.Bottom - OldLocation.Top) * (NewLocation.Right - NewLocation.Left) / (OldLocation.Right -OldLocation.Left);1533 NewLocation.Bottom := FOldLocation.Top + (FOldLocation.Bottom - FOldLocation.Top) * (NewLocation.Right - NewLocation.Left) / (FOldLocation.Right - FOldLocation.Left); 1301 1534 dsSizeL, dsSizeTR: 1302 NewLocation.Top := OldLocation.Bottom - (OldLocation.Bottom - OldLocation.Top) * (NewLocation.Right - NewLocation.Left) / (OldLocation.Right -OldLocation.Left);1535 NewLocation.Top := FOldLocation.Bottom - (FOldLocation.Bottom - FOldLocation.Top) * (NewLocation.Right - NewLocation.Left) / (FOldLocation.Right - FOldLocation.Left); 1303 1536 end; 1304 1537 end; 1305 1538 1306 DoResizing( OldLocation, NewLocation,DragState, Shift);1539 DoResizing(FOldLocation, NewLocation, FDragState, Shift); 1307 1540 1308 1541 if (NewLocation.Left <> Location.Left) or … … 1312 1545 begin 1313 1546 Location := NewLocation; 1314 if Assigned(FOnUserChange) then FOnUserChange(Self); 1547 if Assigned(FOnUserChange) then 1548 FOnUserChange(Self); 1315 1549 end; 1316 1550 end; … … 1318 1552 1319 1553 procedure TRubberbandLayer.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); 1320 begin 1321 IsDragging := False; 1554 var 1555 PositionedLayer: TPositionedLayer; 1556 begin 1557 if FPassMouse.Enabled then 1558 begin 1559 if FPassMouse.ToLayerUnderCursor then 1560 PositionedLayer := FPassMouse.GetChildUnderCursor(X, Y) 1561 else 1562 PositionedLayer := ChildLayer; 1563 1564 if FPassMouse.ToChild and Assigned(ChildLayer) then 1565 begin 1566 ChildLayer.MouseUp(Button, Shift, X, Y); 1567 if FPassMouse.CancelIfPassed then 1568 Exit; 1569 end; 1570 1571 if (PositionedLayer <> ChildLayer) and Assigned(PositionedLayer) then 1572 begin 1573 PositionedLayer.MouseUp(Button, Shift, X, Y); 1574 if FPassMouse.CancelIfPassed then 1575 Exit; 1576 end; 1577 end; 1578 1579 FIsDragging := False; 1322 1580 inherited; 1323 1581 end; … … 1329 1587 end; 1330 1588 1589 procedure TRubberbandLayer.DrawHandle(Buffer: TBitmap32; X, Y: TFloat); 1590 var 1591 HandleRect: TRect; 1592 begin 1593 // Coordinate specifies exact center of handle. I.e. center of 1594 // pixel if handle is odd number of pixels wide. 1595 1596 HandleRect.Left := Floor(X - FHandleSize); 1597 HandleRect.Right := HandleRect.Left + Ceil(FHandleSize*2); 1598 HandleRect.Top := Floor(Y - FHandleSize); 1599 HandleRect.Bottom := HandleRect.Top + Ceil(FHandleSize*2); 1600 1601 Buffer.FrameRectTS(HandleRect, FHandleFrame); 1602 1603 GR32.InflateRect(HandleRect, -1, -1); 1604 Buffer.FillRectTS(HandleRect, FHandleFill); 1605 end; 1606 1331 1607 procedure TRubberbandLayer.Paint(Buffer: TBitmap32); 1332 var 1333 Cx, Cy: Integer; 1608 1609 var 1610 CenterX, CenterY: TFloat; 1334 1611 R: TRect; 1335 1336 procedure DrawHandle(X, Y: Integer);1337 begin1338 Buffer.FillRectTS(X - FHandleSize, Y - FHandleSize, X + FHandleSize, Y + FHandleSize, FHandleFill);1339 Buffer.FrameRectTS(X - FHandleSize, Y - FHandleSize, X + FHandleSize, Y + FHandleSize, FHandleFrame);1340 end;1341 1342 1612 begin 1343 1613 R := MakeRect(GetAdjustedRect(FLocation)); … … 1354 1624 if rhCorners in FHandles then 1355 1625 begin 1356 if not(rhNotTLCorner in FHandles) then DrawHandle( Left, Top);1357 if not(rhNotTRCorner in FHandles) then DrawHandle( Right, Top);1358 if not(rhNotBLCorner in FHandles) then DrawHandle( Left, Bottom);1359 if not(rhNotBRCorner in FHandles) then DrawHandle( Right, Bottom);1626 if not(rhNotTLCorner in FHandles) then DrawHandle(Buffer, Left+0.5, Top+0.5); 1627 if not(rhNotTRCorner in FHandles) then DrawHandle(Buffer, Right-0.5, Top+0.5); 1628 if not(rhNotBLCorner in FHandles) then DrawHandle(Buffer, Left+0.5, Bottom-0.5); 1629 if not(rhNotBRCorner in FHandles) then DrawHandle(Buffer, Right-0.5, Bottom-0.5); 1360 1630 end; 1361 1631 if rhSides in FHandles then 1362 1632 begin 1363 Cx := (Left + Right) div 2; 1364 Cy := (Top + Bottom) div 2; 1365 if not(rhNotTopSide in FHandles) then DrawHandle(Cx, Top); 1366 if not(rhNotLeftSide in FHandles) then DrawHandle(Left, Cy); 1367 if not(rhNotRightSide in FHandles) then DrawHandle(Right, Cy); 1368 if not(rhNotBottomSide in FHandles) then DrawHandle(Cx, Bottom); 1369 end; 1370 end; 1633 CenterX := (Left + Right) / 2; 1634 CenterY := (Top + Bottom) / 2; 1635 if not(rhNotTopSide in FHandles) then DrawHandle(Buffer, CenterX, Top+0.5); 1636 if not(rhNotLeftSide in FHandles) then DrawHandle(Buffer, Left+0.5, CenterY); 1637 if not(rhNotRightSide in FHandles) then DrawHandle(Buffer, Right-0.5, CenterY); 1638 if not(rhNotBottomSide in FHandles) then DrawHandle(Buffer, CenterX, Bottom-0.5); 1639 end; 1640 end; 1641 end; 1642 1643 procedure TRubberbandLayer.Quantize; 1644 begin 1645 Location := FloatRect( 1646 Round(Location.Left / Quantized) * Quantized, 1647 Round(Location.Top / Quantized) * Quantized, 1648 Round(Location.Right / Quantized) * Quantized, 1649 Round(Location.Bottom / Quantized) * Quantized); 1371 1650 end; 1372 1651 … … 1385 1664 end; 1386 1665 1666 procedure TRubberbandLayer.SetDragState(const Value: TRBDragState); 1667 begin 1668 SetDragState(Value, 0, 0); 1669 end; 1670 1671 procedure TRubberbandLayer.SetDragState(const Value: TRBDragState; const X, Y: Integer); 1672 var 1673 ALoc: TFloatRect; 1674 begin 1675 FDragState := Value; 1676 FIsDragging := FDragState <> dsNone; 1677 1678 if FIsDragging then 1679 begin 1680 FOldLocation := Location; 1681 1682 ALoc := GetAdjustedRect(FLocation); 1683 1684 case FDragState of 1685 dsMove: FMouseShift := FloatPoint(X - ALoc.Left, Y - ALoc.Top); 1686 else 1687 FMouseShift := FloatPoint(0, 0); 1688 end; 1689 end; 1690 end; 1691 1387 1692 procedure TRubberbandLayer.SetHandleFill(Value: TColor32); 1388 1693 begin … … 1412 1717 end; 1413 1718 1414 procedure TRubberbandLayer.SetHandleSize(Value: Integer); 1415 begin 1416 if Value < 1 then Value := 1; 1719 procedure TRubberbandLayer.SetHandleSize(Value: TFloat); 1720 begin 1721 if Value < 1 then 1722 Value := 1; 1417 1723 if Value <> FHandleSize then 1418 1724 begin … … 1466 1772 end; 1467 1773 1774 procedure TRubberbandLayer.SetQuantized(const Value: Integer); 1775 begin 1776 if Value < 1 then 1777 raise Exception.Create('Value must be larger than zero!'); 1778 1779 FQuantized := Value; 1780 end; 1781 1468 1782 end.
Note:
See TracChangeset
for help on using the changeset viewer.