1- import { Notice } from 'obsidian'
2- import { Canvas , CanvasEdge , CanvasNode , Position , Size } from 'src/@types/Canvas'
1+ import { Menu , Notice } from 'obsidian'
2+ import { BBox , Canvas , CanvasEdge , CanvasElement , CanvasNode , Position , Size } from 'src/@types/Canvas'
33import AdvancedCanvasPlugin from 'src/main'
44import { CanvasEvent } from 'src/events/events'
55import * as CanvasHelper from "src/utils/canvas-helper"
@@ -19,6 +19,23 @@ export default class PresentationCanvasExtension {
1919
2020 if ( ! this . plugin . settings . getSetting ( 'presentationFeatureEnabled' ) ) return
2121
22+ /* Add wrap in slide option to context menu */
23+ this . plugin . registerEvent ( this . plugin . app . workspace . on (
24+ 'canvas:selection-menu' ,
25+ ( menu : Menu , canvas : Canvas ) => {
26+ menu . addItem ( ( item ) =>
27+ item
28+ . setTitle ( 'Wrap in slide' )
29+ . setIcon ( 'gallery-vertical' )
30+ . onClick ( ( ) => this . addSlide ( canvas , undefined ,
31+ BBoxHelper . enlargeBBox ( BBoxHelper . combineBBoxes (
32+ [ ...canvas . selection . values ( ) ] . map ( ( element : CanvasElement ) => element . getBBox ( ) )
33+ ) , this . plugin . settings . getSetting ( 'wrapInSlidePadding' ) )
34+ ) )
35+ )
36+ }
37+ ) )
38+
2239 this . plugin . addCommand ( {
2340 id : 'create-new-slide' ,
2441 name : 'Create new slide' ,
@@ -69,6 +86,11 @@ export default class PresentationCanvasExtension {
6986 CanvasEvent . PopupMenuCreated ,
7087 ( canvas : Canvas ) => this . onPopupMenuCreated ( canvas )
7188 ) )
89+
90+ this . plugin . registerEvent ( this . plugin . app . workspace . on (
91+ CanvasEvent . NodeMoved ,
92+ ( canvas : Canvas , node : CanvasNode ) => this . onNodeMoved ( canvas , node )
93+ ) )
7294 }
7395
7496 onCanvasChanged ( canvas : Canvas ) : void {
@@ -81,7 +103,7 @@ export default class PresentationCanvasExtension {
81103 label : 'Drag to add slide' ,
82104 icon : 'gallery-vertical'
83105 } ,
84- ( ) => this . getSlideSize ( ) ,
106+ ( ) => this . getDefaultSlideSize ( ) ,
85107 ( canvas : Canvas , pos : Position ) => this . addSlide ( canvas , pos )
86108 )
87109 )
@@ -105,6 +127,28 @@ export default class PresentationCanvasExtension {
105127 } )
106128 )
107129 }
130+
131+ private onNodeMoved ( _canvas : Canvas , node : CanvasNode ) {
132+ const nodeData = node . getData ( )
133+ if ( ! nodeData . sideRatio ) return
134+
135+ const nodeBBox = node . getBBox ( )
136+ const nodeSize = {
137+ width : nodeBBox . maxX - nodeBBox . minX ,
138+ height : nodeBBox . maxY - nodeBBox . minY
139+ }
140+ const nodeAspectRatio = nodeSize . width / nodeSize . height
141+
142+ if ( nodeAspectRatio < nodeData . sideRatio )
143+ nodeSize . width = nodeSize . height * nodeData . sideRatio
144+ else nodeSize . height = nodeSize . width / nodeData . sideRatio
145+
146+ node . setData ( {
147+ ...nodeData ,
148+ width : nodeSize . width ,
149+ height : nodeSize . height
150+ } )
151+ }
108152
109153 private getStartNode ( canvas : Canvas ) : CanvasNode | undefined {
110154 for ( const [ _ , node ] of canvas . nodes ) {
@@ -123,26 +167,56 @@ export default class PresentationCanvasExtension {
123167 if ( node !== startNode ) node . setData ( { ...node . getData ( ) , isStartNode : true } )
124168 }
125169
126- private getSlideSize ( ) : Size {
170+ private getDefaultSlideSize ( ) : Size {
127171 const slideSizeString = this . plugin . settings . getSetting ( 'defaultSlideSize' )
128172 const slideSizeArray = slideSizeString . split ( 'x' ) . map ( ( value : string ) => parseInt ( value ) )
129173 return { width : slideSizeArray [ 0 ] , height : slideSizeArray [ 1 ] }
130174 }
131175
132- private addSlide ( canvas : Canvas , pos ?: Position ) {
133- if ( ! pos ) pos = CanvasHelper . getCenterCoordinates ( canvas , this . getSlideSize ( ) )
176+ private getSlideAspectRatio ( ) : number {
177+ const slideSize = this . getDefaultSlideSize ( )
178+ return slideSize . width / slideSize . height
179+ }
134180
181+ private addSlide ( canvas : Canvas , pos ?: Position , bbox ?: BBox ) {
135182 const isStartNode = this . getStartNode ( canvas ) == null
136- const nodeSize = this . getSlideSize ( )
183+ const slideSize = this . getDefaultSlideSize ( )
184+ const slideAspectRatio = this . getSlideAspectRatio ( )
185+
186+ if ( bbox ) {
187+ const bboxWidth = bbox . maxX - bbox . minX
188+ const bboxHeight = bbox . maxY - bbox . minY
189+
190+ // Make sure the nodes fit inside the bounding box while keeping the aspect ratio
191+ if ( bboxWidth / bboxHeight > slideAspectRatio ) {
192+ slideSize . width = bboxWidth
193+ slideSize . height = bboxWidth / slideAspectRatio
194+ } else {
195+ slideSize . height = bboxHeight
196+ slideSize . width = bboxHeight * slideAspectRatio
197+ }
198+
199+ pos = {
200+ x : bbox . minX ,
201+ y : bbox . minY
202+ }
203+ }
204+
205+ // If no position is provided, use the center of the canvas
206+ if ( ! pos ) pos = CanvasHelper . getCenterCoordinates ( canvas , this . getDefaultSlideSize ( ) )
137207
138208 const groupNode = canvas . createGroupNode ( {
139209 pos : pos ,
140- size : nodeSize ,
210+ size : slideSize ,
141211 label : isStartNode ? START_SLIDE_NAME : DEFAULT_SLIDE_NAME ,
142212 focus : false ,
143213 } )
144214
145- if ( isStartNode ) groupNode . setData ( { ...groupNode . getData ( ) , isStartNode : true } )
215+ groupNode . setData ( {
216+ ...groupNode . getData ( ) ,
217+ sideRatio : slideAspectRatio ,
218+ isStartNode : isStartNode ? true : undefined ,
219+ } )
146220 }
147221
148222 private async animateNodeTransition ( canvas : Canvas , fromNode : CanvasNode | undefined , toNode : CanvasNode ) {
0 commit comments