1+ import { Canvas } from "src/@types/Canvas"
2+ import AdvancedCanvasPlugin from "src/main"
3+ import * as CanvasHelper from "src/utils/canvas-helper"
4+
5+ type Direction = 'up' | 'down' | 'left' | 'right'
6+ const DRIECTIONS = [ 'up' , 'down' , 'left' , 'right' ] as Direction [ ]
7+ const DIRECTION_KEYS = {
8+ up : 'ArrowUp' ,
9+ down : 'ArrowDown' ,
10+ left : 'ArrowLeft' ,
11+ right : 'ArrowRight'
12+ }
13+
14+ export default class CommandsCanvasExtension {
15+ plugin : AdvancedCanvasPlugin
16+
17+ constructor ( plugin : AdvancedCanvasPlugin ) {
18+ this . plugin = plugin
19+
20+ if ( ! this . plugin . settingsManager . getSetting ( 'commandsFeatureEnabled' ) ) return
21+
22+ this . plugin . addCommand ( {
23+ id : 'create-text-node' ,
24+ name : 'Create text node' ,
25+ checkCallback : CanvasHelper . canvasCommand (
26+ this . plugin ,
27+ ( canvas : Canvas ) => ! canvas . readonly ,
28+ ( canvas : Canvas ) => this . createTextNode ( canvas )
29+ )
30+ } )
31+
32+ for ( const direction of DRIECTIONS ) {
33+ this . plugin . addCommand ( {
34+ id : `clone-node-${ direction } ` ,
35+ name : `Clone node ${ direction } ` ,
36+ checkCallback : CanvasHelper . canvasCommand (
37+ this . plugin ,
38+ ( canvas : Canvas ) => ! canvas . readonly && canvas . selection . size === 1 && canvas . selection . values ( ) . next ( ) . value ?. getData ( ) . type === 'text' ,
39+ ( canvas : Canvas ) => this . cloneNode ( canvas , direction )
40+ )
41+ } )
42+
43+ this . plugin . addCommand ( {
44+ id : `expand-node-${ direction } ` ,
45+ name : `Expand node ${ direction } ` ,
46+ hotkeys : [
47+ {
48+ modifiers : [ 'Alt' ] ,
49+ key : DIRECTION_KEYS [ direction ]
50+ }
51+ ] ,
52+ checkCallback : CanvasHelper . canvasCommand (
53+ this . plugin ,
54+ ( canvas : Canvas ) => ! canvas . readonly && canvas . selection . size === 1 ,
55+ ( canvas : Canvas ) => this . expandNode ( canvas , direction )
56+ )
57+ } )
58+ }
59+ }
60+
61+ private createTextNode ( canvas : Canvas ) {
62+ const size = canvas . config . defaultTextNodeDimensions
63+ const pos = CanvasHelper . getCenterCoordinates ( canvas , size )
64+
65+ canvas . createTextNode ( { pos : pos , size : size } )
66+ }
67+
68+ private cloneNode ( canvas : Canvas , cloneDirection : Direction ) {
69+ const sourceNode = canvas . selection . values ( ) . next ( ) . value
70+ if ( ! sourceNode ) return
71+ const sourceNodeData = sourceNode . getData ( )
72+
73+ const nodeMargin = this . plugin . settingsManager . getSetting ( 'cloneNodeMargin' )
74+ const offset = {
75+ x : ( sourceNode . width + nodeMargin ) * ( cloneDirection === 'left' ? - 1 : ( cloneDirection === 'right' ? 1 : 0 ) ) ,
76+ y : ( sourceNode . height + nodeMargin ) * ( cloneDirection === 'up' ? - 1 : ( cloneDirection === 'down' ? 1 : 0 ) )
77+ }
78+
79+ const clonedNode = canvas . createTextNode ( {
80+ pos : {
81+ x : sourceNode . x + offset . x ,
82+ y : sourceNode . y + offset . y
83+ } ,
84+ size : {
85+ width : sourceNode . width ,
86+ height : sourceNode . height
87+ }
88+ } )
89+
90+ clonedNode . color = sourceNode . color
91+ canvas . setNodeUnknownData ( clonedNode , 'shape' , sourceNodeData . shape )
92+
93+ if ( this . plugin . settingsManager . getSetting ( 'zoomToClonedNode' ) )
94+ canvas . zoomToBbox ( clonedNode . getBBox ( ) )
95+ }
96+
97+ private expandNode ( canvas : Canvas , expandDirection : Direction ) {
98+ const node = canvas . selection . values ( ) . next ( ) . value
99+ if ( ! node ) return
100+
101+ const expandNodeStepSize = this . plugin . settingsManager . getSetting ( 'expandNodeStepSize' )
102+ const expand = {
103+ x : expandDirection === 'left' ? - 1 : ( expandDirection === 'right' ? 1 : 0 ) ,
104+ y : expandDirection === 'up' ? - 1 : ( expandDirection === 'down' ? 1 : 0 )
105+ }
106+
107+ node . setData ( {
108+ ...node . getData ( ) ,
109+ width : node . width + expand . x * expandNodeStepSize ,
110+ height : node . height + expand . y * expandNodeStepSize
111+ } )
112+ }
113+ }
0 commit comments