Skip to content

Commit 4d518d4

Browse files
Merge pull request #5 from Developer-Mike/portals
Portals
2 parents 2322db4 + 93e470a commit 4d518d4

14 files changed

+730
-71
lines changed

README.md

Lines changed: 65 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ All features can be enabled/disabled in the settings.
3838
- Database shape
3939
- [Presentation mode](#presentation)
4040
- Create presentations by connecting nodes with arrows
41+
- [Portals](#portals)
42+
- Embed other canvases inside your canvas
43+
- Create edges (arrows) to the embedded canvas
4144
- [Better readonly](#better-readonly)
4245
- Disable node popup menus
4346
- Lock the canvas' position
@@ -160,6 +163,14 @@ In presentation mode, you can navigate through the nodes using the arrow keys. T
160163
- Change slides using the arrow keys
161164
- Exit the presentation using the `ESC` key
162165

166+
## Portals
167+
Embed other canvases inside your canvas and create edges (arrows) to the embedded canvas.
168+
169+
<img src="./assets/sample-portal-usage.png" alt="Portal example"/>
170+
171+
### Usage
172+
- Embed a canvas file and click on the door icon of the popup menu to open a portal
173+
163174
## Better Readonly
164175
- Disable node popup menus
165176
- Lock the canvas' position
@@ -180,28 +191,60 @@ Move the current selection to a new canvas and create a link in the current canv
180191
## Canvas Events
181192
All custom events are prefixed with `advanced-canvas:` and can be listened to using `app.workspace.on` (Just like the default events).
182193

183-
Events:
184-
- `advanced-canvas:canvas-changed`
185-
- Fired when a new canvas gets loaded
186-
- Payload: `Canvas`
187-
- `advanced-canvas:viewport-changed:before` and `advanced-canvas:viewport-changed:after`
188-
- Fired before and after the viewport gets changed
189-
- Payload: `Canvas`
190-
- `advanced-canvas:zoom-to-bbox:before` and `advanced-canvas:zoom-to-bbox:after`
191-
- Fired before and after the canvas gets zoomed to a bounding box (e.g. zoom to selection, zoom to fit all)
192-
- Payload: `Canvas`, `BBox`
193-
- `advanced-canvas:popup-menu-created`
194-
- Fired when the a node popup menu gets created (Not firing multiple times if it gets moved between nodes of the same type)
195-
- Payload: `Canvas`, `Node`
196-
- `advanced-canvas:nodes-changed`
197-
- Fired when any node gets changed
198-
- Payload: `Canvas`, `Node[]`
199-
- `advanced-canvas:node-interaction`
200-
- Fired when a node gets hovered over
201-
- Payload: `Canvas`, `Node`
202-
- `advanced-canvas:readonly-changed`
203-
- Fired when the readonly state of the canvas changes
204-
- Payload: `Canvas`, `boolean`
194+
<details>
195+
<summary>
196+
All Events (19)
197+
</summary>
198+
199+
- `advanced-canvas:canvas-changed`
200+
- Fired when a new canvas gets loaded
201+
- Payload: `Canvas`
202+
- `advanced-canvas:viewport-changed:before` and `advanced-canvas:viewport-changed:after`
203+
- Fired before and after the viewport gets changed
204+
- Payload: `Canvas`
205+
- `advanced-canvas:node-moved`
206+
- Fired when a node gets moved
207+
- Payload: `Canvas`, `Node`
208+
- `advanced-canvas:dragging-state-changed`
209+
- Fired when the dragging state of the canvas changes
210+
- Payload: `Canvas`, `boolean`
211+
- `advanced-canvas:node-removed`
212+
- Fired when a node gets removed
213+
- Payload: `Canvas`, `Node`
214+
- `advanced-canvas:selection-changed`
215+
- Fired when the selection of the canvas changes
216+
- Payload: `Canvas`, `updateSelection: (() => void) => void`
217+
- `advanced-canvas:zoom-to-bbox:before` and `advanced-canvas:zoom-to-bbox:after`
218+
- Fired before and after the canvas gets zoomed to a bounding box (e.g. zoom to selection, zoom to fit all)
219+
- Payload: `Canvas`, `BBox`
220+
- `advanced-canvas:popup-menu-created`
221+
- Fired when the a node popup menu gets created (Not firing multiple times if it gets moved between nodes of the same type)
222+
- Payload: `Canvas`, `Node`
223+
- `advanced-canvas:nodes-changed`
224+
- Fired when any node gets changed
225+
- Payload: `Canvas`, `Node[]`
226+
- `advanced-canvas:node-interaction`
227+
- Fired when a node gets hovered over
228+
- Payload: `Canvas`, `Node`
229+
- `advanced-canvas:undo`
230+
- Fired when undo gets called
231+
- Payload: `Canvas`
232+
- `advanced-canvas:redo`
233+
- Fired when redo gets called
234+
- Payload: `Canvas`
235+
- `advanced-canvas:readonly-changed`
236+
- Fired when the readonly state of the canvas changes
237+
- Payload: `Canvas`, `boolean`
238+
- `advanced-canvas:data-requested`
239+
- Fired when the canvas data gets requested
240+
- Payload: `Canvas`, `CanvasData (Reference!)`
241+
- `advanced-canvas:load-data`
242+
- Fired when the canvas data gets set
243+
- Payload: `Canvas`, `CanvasData (Reference!)`, `setData: (CanvasData) => void`
244+
- `advanced-canvas:canvas-saved:before` and `advanced-canvas:canvas-saved:after`
245+
- Fired before and after the canvas gets saved
246+
- Payload: `Canvas`
247+
</details>
205248

206249
## Settings
207250
Every feature can be enabled/disabled in the settings. All features were made to be as customizable as possible.

assets/sample-portal-usage.png

159 KB
Loading

package-lock.json

Lines changed: 0 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/@types/Canvas.d.ts

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { TFile, View } from "obsidian"
1+
import { TFile, View, WorkspaceLeaf } from "obsidian"
22

33
export interface Size {
44
width: number
@@ -20,8 +20,13 @@ export interface BBox {
2020
export interface Canvas {
2121
view: CanvasView
2222
config: CanvasConfig
23+
options: CanvasOptions
2324

2425
getData(): CanvasData
26+
setData(data: CanvasData): void
27+
28+
/** Basically setData, but without modifying the history */
29+
importData(data: CanvasData): void
2530

2631
nodes: Map<string, CanvasNode>
2732
edges: Map<string, CanvasEdge>
@@ -47,6 +52,9 @@ export interface Canvas {
4752
ty: number
4853
tZoom: number
4954

55+
isDragging: boolean
56+
setDragging(dragging: boolean): void
57+
5058
zoomToBbox(bbox: BBox): void
5159
zoomToSelection(): void
5260

@@ -57,12 +65,17 @@ export interface Canvas {
5765
getSelectionData(): SelectionData
5866
deselectAll(): void
5967

68+
toggleObjectSnapping(enabled: boolean): void
6069
dragTempNode(dragEvent: any, nodeSize: Size, onDropped: (position: Position) => void): void
70+
6171
createTextNode(options: TextNodeOptions): CanvasNode
6272
createGroupNode(options: GroupNodeOptions): CanvasNode
6373
createFileNode(options: FileNodeOptions): CanvasNode
74+
6475
removeNode(node: CanvasNode): void
76+
removeEdge(edge: CanvasEdge): void
6577

78+
history: CanvasHistory
6679
undo(): void
6780
redo(): void
6881

@@ -74,6 +87,24 @@ export interface Canvas {
7487
lockedY: number
7588
lockedZoom: number
7689
setNodeData(node: CanvasNode, key: keyof CanvasNodeData, value: any): void
90+
foreignCanvasData: { [key: string]: CanvasData }
91+
}
92+
93+
export interface CanvasOptions {
94+
snapToObjects: boolean
95+
snapToGrid: boolean
96+
}
97+
98+
export interface CanvasHistory {
99+
data: CanvasData[]
100+
current: number
101+
max: number
102+
103+
applyHistory: (data: CanvasData) => void
104+
canUndo: () => boolean
105+
undo: () => CanvasData|null
106+
canRedo: () => boolean
107+
redo: () => CanvasData|null
77108
}
78109

79110
export interface SelectionData {
@@ -87,7 +118,17 @@ export interface CanvasConfig {
87118
}
88119

89120
export interface CanvasView extends View {
121+
_loaded: boolean
90122
file: TFile
123+
canvas: Canvas
124+
leaf: CanvasWorkspaceLeaf
125+
126+
getViewData(): string
127+
setViewData(data: string): void
128+
}
129+
130+
export interface CanvasWorkspaceLeaf extends WorkspaceLeaf {
131+
id: string
91132
}
92133

93134
export interface NodeOptions {
@@ -118,8 +159,25 @@ export interface CanvasData {
118159
export type CanvasNodeType = 'text' | 'group' | 'file' | 'link'
119160
export interface CanvasNodeData {
120161
type: CanvasNodeType
162+
text?: string
163+
label?: string
164+
file?: string
165+
121166
shape: string
122167
isStartNode: boolean
168+
edgesToNodeFromPortal?: { [key: string]: CanvasEdgeData[] }
169+
170+
// Portal node
171+
portalToFile?: string
172+
closedPortalWidth?: number
173+
closedPortalHeight?: number
174+
portalIdMaps?: {
175+
nodeIdMap: { [key: string]: string }
176+
edgeIdMap: { [key: string]: string }
177+
}
178+
179+
// Node from portal
180+
portalId?: string
123181

124182
[key: string]: any
125183
}
@@ -129,9 +187,16 @@ export interface CanvasNode {
129187
nodeEl: HTMLElement
130188
getBBox(): BBox
131189

190+
file?: TFile
191+
192+
x: number
193+
y: number
194+
width: number
195+
height: number
196+
132197
color: string
198+
zIndex: number
133199

134-
/** @deprecated Use `canvas.setNodeData` instead */
135200
setData(data: CanvasNodeData): void
136201
getData(): CanvasNodeData
137202
}
@@ -145,6 +210,8 @@ export interface CanvasEdgeData {
145210

146211
fromSide: Side
147212
toSide: Side
213+
214+
portalId?: string
148215
}
149216

150217
export interface CanvasEdge {

src/canvas-extensions/interaction-tagger-canvas-extension.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ export default class InteractionTaggerCanvasExtension {
2222
const datasetKey = TARGET_NODE_DATASET_PREFIX + dataKey.toString().charAt(0).toUpperCase() + dataKey.toString().slice(1)
2323

2424
const dataValue = node?.getData()[dataKey]
25-
if (dataValue) interactionEl.dataset[datasetKey] = dataValue
25+
26+
if (dataValue === undefined) delete interactionEl.dataset[datasetKey]
27+
else interactionEl.dataset[datasetKey] = dataValue
2628
}
2729
}
2830
))

src/canvas-extensions/node-data-tagger-canvas-extension.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Canvas, CanvasNode, CanvasNodeData } from "src/@types/Canvas"
22
import { CanvasEvent } from "src/events/events"
33
import AdvancedCanvasPlugin from "src/main"
44

5-
export const EXPOSED_DATA = ['type', 'isStartNode', 'shape'] as (keyof CanvasNodeData)[]
5+
export const EXPOSED_DATA = ['type', 'shape', 'isStartNode', 'portalToFile', 'portalId'] as (keyof CanvasNodeData)[]
66

77
export default class NodeDataTaggerCanvasExtension {
88
plugin: AdvancedCanvasPlugin
@@ -19,7 +19,9 @@ export default class NodeDataTaggerCanvasExtension {
1919

2020
for (const dataKey of EXPOSED_DATA) {
2121
const dataValue = nodeData[dataKey]
22-
node.nodeEl.dataset[dataKey] = dataValue
22+
23+
if (dataValue === undefined) delete node.nodeEl.dataset[dataKey]
24+
else node.nodeEl.dataset[dataKey] = dataValue
2325
}
2426
}
2527
}

0 commit comments

Comments
 (0)