import { Graphics } from '@pixi/graphics' ; import { Point } from '@pixi/math' ; import { Renderer } from '@pixi/core' ; import type { Container } from '@pixi/display' ; import type { InteractionEvent } from '@pixi/interaction' ; import type { Handle , Transformer } from './Transformer' ; see TransformerHandle export interface ITransformerHandleStyle { /** Fill color of the handle */ color : number ; /** Outline color of the handle */ outlineColor : number ; /** Outline thickness around the handle */ outlineThickness : number ; /** Radius (or size for non-circular handles) of the handle */ radius : number ; /**  TransformerHandle provides three types of handle shapes - 'circle', 'square', 'tooth'.  shape : string ; } ignore const DEFAULT_HANDLE_STYLE = { color : 0xffffff , outlineColor : 0x000000 , outlineThickness : 1 , radius : 8 , shape : 'tooth' , } ; /**
 * The transfomer handle base implementation.
 */ export class TransformerHandle extends Graphics { onHandleDelta : ( pointerPosition : Point ) => void ; onHandleCommit : ( ) => void ; protected _handle : Handle ; protected _style : ITransformerHandleStyle ; protected _dirty : boolean ; private _pointerDown : boolean ; private _pointerDragging : boolean ; private _pointerPosition : Point ; private _pointerMoveTarget : Container | null ; param { Transformer } transformer param { string } handle param { object } styleOpts param { function } handler param { function } commit param { string } cursor constructor ( protected readonly transformer , handle , styleOpts = { } , handler , commit , cursor ? ) { super ( ) ; const style = Object . assign ( { } , DEFAULT_HANDLE_STYLE , styleOpts ) ; this . _handle = handle ; this . _style = style ; this . onHandleDelta = handler ; this . onHandleCommit = commit ; /**
         * This flags whether this handle should be redrawn in the next frame due to style changes.
         */ this . _dirty = true ; this . interactive = true ; this . cursor = cursor || 'move' ; this . _pointerDown = false ; this . _pointerDragging = false ; this . _pointerPosition = new Point ( ) ; this . _pointerMoveTarget = null ; this . on ( 'mousedown' , this . onPointerDown , this ) ; this . on ( 'mouseup' , this . onPointerUp , this ) ; this . on ( 'mouseupoutside' , this . onPointerUp , this ) ; } get handle ( ) : Handle { return this . _handle ; } set handle ( handle ) { this . _handle = handle ; this . _dirty = true ; } /**
     * The currently applied handle style.
     */ get style ( ) : Partial < ITransformerHandleStyle > { return this . _style ; } set style ( value ) { this . _style = Object . assign ( { } , DEFAULT_HANDLE_STYLE , value ) ; this . _dirty = true ; } render ( renderer ) { if ( this . _dirty ) { this . draw ( ) ; this . _dirty = false ; } super . render ( renderer ) ; } /**
     * Redraws the handle's geometry. This is called on a `render` if {@code this._dirty} is true.
     */ protected draw ( ) { const handle = this . _handle ; const style = this . _style ; const radius = style . radius ; this . clear ( ) . lineStyle ( style . outlineThickness , style . outlineColor ) . beginFill ( style . color ) ; if ( style . shape === 'square' ) { this . drawRect ( - radius / 2 , - radius / 2 , radius , radius ) ; } else if ( style . shape === 'tooth' ) { switch ( handle ) { case 'middleLeft' : this . drawPolygon ( [ - radius / 2 , - radius / 2 , - radius / 2 , radius / 2 , radius / 2 , radius / 2 , radius * 1.1 , 0 , radius / 2 , - radius / 2 , ] ) ; break ; case 'topCenter' : this . drawPolygon ( [ - radius / 2 , - radius / 2 , radius / 2 , - radius / 2 , radius / 2 , radius / 2 , 0 , radius * 1.1 , - radius / 2 , radius / 2 , ] ) ; break ; case 'middleRight' : this . drawPolygon ( [ - radius / 2 , radius / 2 , - radius * 1.1 , 0 , - radius / 2 , - radius / 2 , radius / 2 , - radius / 2 , radius / 2 , radius / 2 , ] ) ; break ; case 'bottomCenter' : this . drawPolygon ( [ 0 , - radius * 1.1 , radius / 2 , - radius / 2 , radius / 2 , radius / 2 , - radius / 2 , radius / 2 , - radius / 2 , - radius / 2 , ] ) ; break ; case 'rotator' : this . drawCircle ( 0 , 0 , radius / Math . sqrt ( 2 ) ) ; break ; default : this . drawRect ( - radius / 2 , - radius / 2 , radius , radius ) ; break ; } } else { this . drawCircle ( 0 , 0 , radius ) ; } this . endFill ( ) ; } param e protected onPointerDown ( e ) { this . _pointerDown = true ; this . _pointerDragging = false ; e . stopPropagation ( ) ; if ( this . _pointerMoveTarget ) { this . _pointerMoveTarget . off ( 'pointermove' , this . onPointerMove , this ) ; this . _pointerMoveTarget = null ; } this . _pointerMoveTarget = this . transformer . stage || this ; this . _pointerMoveTarget . on ( 'pointermove' , this . onPointerMove , this ) ; } param e protected onPointerMove ( e ) { if ( ! this . _pointerDown ) { return ; } if ( this . _pointerDragging ) { this . onDrag ( e ) ; } else { this . onDragStart ( e ) ; } e . stopPropagation ( ) ; } param e protected onPointerUp ( e ) { if ( this . _pointerDragging ) { this . onDragEnd ( e ) ; } this . _pointerDown = false ; if ( this . _pointerMoveTarget ) { this . _pointerMoveTarget . off ( 'pointermove' , this . onPointerMove , this ) ; this . _pointerMoveTarget = null ; } } param e protected onDragStart ( e ) { this . _pointerPosition . copyFrom ( e . data . global ) ; this . _pointerDragging = true ; } param e protected onDrag ( e ) { const currentPosition = e . data . global ; if ( this . onHandleDelta ) { this . onHandleDelta ( currentPosition ) ; } this . _pointerPosition . copyFrom ( currentPosition ) ; } param _ protected onDragEnd ( _ ) { this . _pointerDragging = false ; if ( this . onHandleCommit ) { this . onHandleCommit ( ) ; } } }