| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410 |
- // SPDX-License-Identifier: GPL-3.0-only
- unit UToolPolygon;
- {$mode objfpc}{$H+}
- interface
- uses
- Classes, SysUtils, UTool, UToolVectorial, BGRABitmap, BGRABitmapTypes,
- LCVectorOriginal, LCLType;
- const
- EasyBezierMinimumDotProduct = 0.5;
- type
- { TToolRectangle }
- TToolRectangle = class(TVectorialTool)
- protected
- function ShapeClass: TVectorShapeAny; override;
- end;
- { TToolEllipse }
- TToolEllipse = class(TVectorialTool)
- protected
- function ShapeClass: TVectorShapeAny; override;
- function GetGridMatrix: TAffineMatrix; override;
- end;
- { TToolPolygon }
- TToolPolygon = class(TVectorialTool)
- protected
- class var RightClickHintShown: boolean;
- class var RemovePointHintShown: boolean;
- initiallyClosed : boolean;
- function ShapeClass: TVectorShapeAny; override;
- function CreateShape: TVectorShape; override;
- function ShouldCloseShape: boolean; virtual;
- procedure UpdateManagerCloseShape({%H-}AClose: boolean); virtual;
- procedure AssignShapeStyleClosed(AShape: TVectorShape); virtual;
- procedure AssignShapeStyle(AMatrix: TAffineMatrix; AAlwaysFit: boolean); override;
- procedure UpdateUserMode; virtual;
- procedure ShapeValidated; override;
- function DoToolKeyDown(var key: Word): TRect; override;
- function RoundCoordinate(constref ptF: TPointF): TPointF; override;
- public
- class procedure ForgetHintShown;
- function ToolUp: TRect; override;
- function ToolKeyPress(var key: TUTF8Char): TRect; override;
- end;
- { TToolPolyline }
- TToolPolyline = class(TToolPolygon)
- protected
- function CreateShape: TVectorShape; override;
- function ShouldCloseShape: boolean; override;
- procedure AssignShapeStyleClosed(AShape: TVectorShape); override;
- procedure UpdateManagerCloseShape({%H-}AClose: boolean); override;
- function GetManagerShapeOptions: TShapeOptions; override;
- function HasBrush: boolean; override;
- public
- function HasPen: boolean; override;
- function GetContextualToolbars: TContextualToolbars; override;
- end;
- { TToolSpline }
- TToolSpline = class(TToolPolygon)
- private
- FCurrentMode: TToolSplineMode;
- FNextCurveMode: TEasyBezierCurveMode;
- FCurveModeHintShown: Boolean;
- function GetCurrentMode: TToolSplineMode;
- procedure SetCurrentMode(AValue: TToolSplineMode);
- protected
- function ShapeClass: TVectorShapeAny; override;
- function CreateShape: TVectorShape; override;
- procedure AssignShapeStyle(AMatrix: TAffineMatrix; AAlwaysFit: boolean); override;
- procedure UpdateUserMode; override;
- public
- constructor Create(AManager: TToolManager); override;
- function ToolKeyPress(var key: TUTF8Char): TRect; override;
- property CurrentMode: TToolSplineMode read GetCurrentMode write SetCurrentMode;
- end;
- { TToolOpenedCurve }
- TToolOpenedCurve = class(TToolSpline)
- protected
- function ShouldCloseShape: boolean; override;
- procedure UpdateManagerCloseShape({%H-}AClose: boolean); override;
- function GetManagerShapeOptions: TShapeOptions; override;
- function HasBrush: boolean; override;
- public
- function HasPen: boolean; override;
- function GetContextualToolbars: TContextualToolbars; override;
- end;
- implementation
- uses LazPaintType, LCVectorRectShapes, LCVectorPolyShapes, BGRATransform;
- { TToolOpenedCurve }
- function TToolOpenedCurve.ShouldCloseShape: boolean;
- begin
- result := false;
- end;
- procedure TToolOpenedCurve.UpdateManagerCloseShape(AClose: boolean);
- begin
- //nothing
- end;
- function TToolOpenedCurve.GetManagerShapeOptions: TShapeOptions;
- begin
- Result:= manager.ShapeOptions - [toFillShape] + [toDrawShape];
- end;
- function TToolOpenedCurve.HasPen: boolean;
- begin
- Result:= true;
- end;
- function TToolOpenedCurve.HasBrush: boolean;
- begin
- Result:= false;
- end;
- function TToolOpenedCurve.GetContextualToolbars: TContextualToolbars;
- begin
- Result:= inherited GetContextualToolbars - [ctShape, ctCloseShape];
- end;
- { TToolPolyline }
- function TToolPolyline.CreateShape: TVectorShape;
- begin
- Result:=inherited CreateShape;
- inherited AssignShapeStyleClosed(Result);
- end;
- function TToolPolyline.ShouldCloseShape: boolean;
- begin
- result := false;
- end;
- procedure TToolPolyline.AssignShapeStyleClosed(AShape: TVectorShape);
- begin
- //nothing
- end;
- procedure TToolPolyline.UpdateManagerCloseShape(AClose: boolean);
- begin
- //nothing
- end;
- function TToolPolyline.GetManagerShapeOptions: TShapeOptions;
- begin
- Result:= manager.ShapeOptions - [toFillShape] + [toDrawShape];
- end;
- function TToolPolyline.HasPen: boolean;
- begin
- Result:= true;
- end;
- function TToolPolyline.HasBrush: boolean;
- begin
- Result:= false;
- end;
- function TToolPolyline.GetContextualToolbars: TContextualToolbars;
- begin
- Result:= inherited GetContextualToolbars - [ctShape, ctCloseShape];
- end;
- { TToolEllipse }
- function TToolEllipse.ShapeClass: TVectorShapeAny;
- begin
- result := TEllipseShape;
- end;
- function TToolEllipse.GetGridMatrix: TAffineMatrix;
- begin
- Result:= AffineMatrixScale(0.5, 0.5);
- end;
- { TToolRectangle }
- function TToolRectangle.ShapeClass: TVectorShapeAny;
- begin
- result := TRectShape;
- end;
- { TToolSpline }
- function TToolSpline.GetCurrentMode: TToolSplineMode;
- begin
- if Assigned(FShape) then
- FCurrentMode := ToolSplineModeFromShape(FShape);
- result := FCurrentMode;
- end;
- procedure TToolSpline.SetCurrentMode(AValue: TToolSplineMode);
- begin
- if FCurrentMode = AValue then exit;
- FCurrentMode := AValue;
- UpdateUserMode;
- end;
- function TToolSpline.ShapeClass: TVectorShapeAny;
- begin
- result := TCurveShape;
- end;
- procedure TToolSpline.UpdateUserMode;
- var
- c: TCurveShape;
- begin
- if FShape = nil then exit;
- if FQuickDefine then
- begin
- FShape.Usermode := vsuCreate;
- exit;
- end;
- c := TCurveShape(FShape);
- case FCurrentMode of
- tsmMovePoint: if not (c.Usermode in [vsuEdit,vsuCreate]) then c.Usermode := vsuEdit;
- tsmCurveModeAuto: if c.Usermode <> vsuCreate then c.Usermode := vsuCurveSetAuto else
- if c.PointCount > 1 then c.CurveMode[c.PointCount-2] := cmAuto;
- tsmCurveModeAngle: if c.Usermode <> vsuCreate then c.Usermode := vsuCurveSetAngle else
- if c.PointCount > 1 then c.CurveMode[c.PointCount-2] := cmAngle;
- tsmCurveModeSpline: if c.Usermode <> vsuCreate then c.Usermode := vsuCurveSetCurve else
- if c.PointCount > 1 then c.CurveMode[c.PointCount-2] := cmCurve;
- end;
- end;
- function TToolSpline.CreateShape: TVectorShape;
- begin
- result := inherited CreateShape;
- TCurveShape(result).CosineAngle:= EasyBezierMinimumDotProduct;
- if not FCurveModeHintShown then
- begin
- Manager.ToolPopup(tpmCurveModeHint);
- FCurveModeHintShown := true;
- end;
- end;
- procedure TToolSpline.AssignShapeStyle(AMatrix: TAffineMatrix; AAlwaysFit: boolean);
- begin
- inherited AssignShapeStyle(AMatrix, AAlwaysFit);
- TCurveShape(FShape).SplineStyle:= Manager.SplineStyle;
- end;
- constructor TToolSpline.Create(AManager: TToolManager);
- begin
- inherited Create(AManager);
- FNextCurveMode := cmAuto;
- end;
- function TToolSpline.ToolKeyPress(var key: TUTF8Char): TRect;
- begin
- if (Key='z') or (Key = 'Z') then
- begin
- CurrentMode:= tsmMovePoint;
- result := OnlyRenderChange;
- Key := #0;
- end else
- begin
- Result:=inherited ToolKeyPress(key);
- if Key='x' then Key := #0;
- end;
- end;
- { TToolPolygon }
- function TToolPolygon.ShapeClass: TVectorShapeAny;
- begin
- result := TPolylineShape;
- end;
- function TToolPolygon.CreateShape: TVectorShape;
- begin
- result := inherited CreateShape;
- initiallyClosed := ShouldCloseShape;
- if not RightClickHintShown then
- begin
- Manager.ToolPopup(tpmRightClickFinishShape);
- RightClickHintShown := true;
- end;
- end;
- function TToolPolygon.ShouldCloseShape: boolean;
- begin
- result := toCloseShape in Manager.ShapeOptions;
- end;
- procedure TToolPolygon.UpdateManagerCloseShape(AClose: boolean);
- var
- opt: TShapeOptions;
- begin
- opt := Manager.ShapeOptions;
- if AClose then
- include(opt, toCloseShape)
- else
- exclude(opt, toCloseShape);
- Manager.ShapeOptions:= opt;
- end;
- procedure TToolPolygon.AssignShapeStyleClosed(AShape: TVectorShape);
- begin
- (AShape as TCustomPolypointShape).Closed := ShouldCloseShape;
- end;
- procedure TToolPolygon.AssignShapeStyle(AMatrix: TAffineMatrix; AAlwaysFit: boolean);
- begin
- inherited AssignShapeStyle(AMatrix, AAlwaysFit);
- AssignShapeStyleClosed(TCustomPolypointShape(FShape));
- TCustomPolypointShape(FShape).ArrowStartKind := Manager.ArrowStart;
- TCustomPolypointShape(FShape).ArrowEndKind := Manager.ArrowEnd;
- TCustomPolypointShape(FShape).ArrowSize := Manager.ArrowSize;
- TCustomPolypointShape(FShape).LineCap:= Manager.LineCap;
- UpdateUserMode;
- end;
- procedure TToolPolygon.UpdateUserMode;
- begin
- if FShape = nil then exit;
- if FQuickDefine then FShape.Usermode := vsuCreate;
- end;
- procedure TToolPolygon.ShapeValidated;
- begin
- inherited ShapeValidated;
- if not initiallyClosed then UpdateManagerCloseShape(False);
- end;
- function TToolPolygon.ToolUp: TRect;
- begin
- Result:=inherited ToolUp;
- if Assigned(FShape) then
- begin
- UpdateManagerCloseShape((FShape as TCustomPolypointShape).Closed);
- if not RemovePointHintShown and ((FShape as TCustomPolypointShape).ValidatedPointCount >= 3) then
- begin
- Manager.ToolPopup(tpmBackspaceRemoveLastPoint);
- RemovePointHintShown := true;
- end;
- end;
- end;
- function TToolPolygon.ToolKeyPress(var key: TUTF8Char): TRect;
- var
- keyCode: Word;
- begin
- if (Key='i') or (Key='I') then
- begin
- keyCode := VK_INSERT;
- ToolKeyDown(keyCode);
- if keyCode = 0 then key := #0;
- keyCode := VK_INSERT;
- ToolKeyUp(keyCode);
- result := EmptyRect;
- end else
- Result:=inherited ToolKeyPress(key);
- end;
- function TToolPolygon.DoToolKeyDown(var key: Word): TRect;
- begin
- if (key = VK_RETURN) and Assigned(FShape)
- and (FShape.Usermode = vsuCreate) then
- begin
- FShape.Usermode:= vsuEdit;
- result := OnlyRenderChange;
- key := 0;
- exit;
- end else
- Result:=inherited DoToolKeyDown(key);
- end;
- function TToolPolygon.RoundCoordinate(constref ptF: TPointF): TPointF;
- begin
- If Editor.GridActive then
- result := Editor.SnapToGrid(ptF, false)
- else
- result := ptF;
- end;
- class procedure TToolPolygon.ForgetHintShown;
- begin
- RemovePointHintShown := false;
- RemovePointHintShown := false;
- end;
- initialization
- RegisterTool(ptRect,TToolRectangle);
- RegisterTool(ptEllipse,TToolEllipse);
- RegisterTool(ptPolygon,TToolPolygon);
- RegisterTool(ptSpline,TToolSpline);
- RegisterTool(ptPolyline,TToolPolyline);
- RegisterTool(ptOpenedCurve,TToolOpenedCurve);
- end.
|