diff --git a/src/BlockHub/BlockHub.ts b/src/BlockHub/BlockHub.ts
index 22138a5..6db2193 100644
--- a/src/BlockHub/BlockHub.ts
+++ b/src/BlockHub/BlockHub.ts
@@ -3,6 +3,7 @@ import { type Block } from './Block/Block'
import TextBox from './TextBoxBlock/TextBox.vue'
import Table from './TableBlock/Table.vue'
import Picture from './PictureBlock/Picture.vue'
+import Canvas from './CanvasBlock/Canvas.vue'
class BlockHub {
private _blockMap = Object.create(null)
@@ -21,6 +22,7 @@ export const BlockViews: { [key: string]: Component } = {
TextBox,
Table,
Picture,
+ Canvas,
}
export const blockHub = new BlockHub()
diff --git a/src/BlockHub/CanvasBlock/Canvas.vue b/src/BlockHub/CanvasBlock/Canvas.vue
new file mode 100644
index 0000000..9f8df2a
--- /dev/null
+++ b/src/BlockHub/CanvasBlock/Canvas.vue
@@ -0,0 +1,65 @@
+
+
+
+
+
diff --git a/src/BlockHub/CanvasBlock/CanvasBlock.ts b/src/BlockHub/CanvasBlock/CanvasBlock.ts
new file mode 100644
index 0000000..10ad3bf
--- /dev/null
+++ b/src/BlockHub/CanvasBlock/CanvasBlock.ts
@@ -0,0 +1,23 @@
+import { ArrayStore } from '@Kernel/Store/ArrayStore'
+import { Block } from '../Block/Block'
+
+export class CanvasBlock extends Block {
+ constructor(x: number, y: number, width: number, height: number) {
+ super('Canvas', x, y, width, height)
+ this.props.set('points', new ArrayStore())
+
+ const points = this.props.get('points') as ArrayStore
+ points.events.update.on(() => {
+ // TODO: fix from
+ this.props.events.update.emit({ key: 'points', from: this.points, to: this.points })
+ })
+ }
+
+ get points() {
+ return this.props.get('points') as ArrayStore
+ }
+
+ set points(points: ArrayStore) {
+ this.props.set('points', points)
+ }
+}
diff --git a/src/Kernel/Store/ArrayStore.ts b/src/Kernel/Store/ArrayStore.ts
index 609a570..8fcedef 100644
--- a/src/Kernel/Store/ArrayStore.ts
+++ b/src/Kernel/Store/ArrayStore.ts
@@ -13,10 +13,18 @@ export class ArrayStore {
}>(),
}
+ get length() {
+ return this._store.length
+ }
+
get(index: number) {
return this._store[index]
}
+ slice(index: number) {
+ return this._store.slice(index)
+ }
+
insert(index: number, ...values: Array) {
const from = [] as Array
const to = values
diff --git a/src/Kernel/ToolBox/ToolBox.ts b/src/Kernel/ToolBox/ToolBox.ts
index 1fc8ec8..f9b1cd8 100644
--- a/src/Kernel/ToolBox/ToolBox.ts
+++ b/src/Kernel/ToolBox/ToolBox.ts
@@ -59,4 +59,8 @@ export class ToolBox {
_addListener()
})
}
+
+ get currentToolType() {
+ return this._currentToolType
+ }
}
diff --git a/src/Kernel/ToolBox/controller/PenToolController.ts b/src/Kernel/ToolBox/controller/PenToolController.ts
new file mode 100644
index 0000000..75aabfe
--- /dev/null
+++ b/src/Kernel/ToolBox/controller/PenToolController.ts
@@ -0,0 +1,57 @@
+import { toSlideCoords } from '@Utils/toSlideCoords'
+import { ToolController } from './_ToolController'
+import { CanvasBlock } from '@BlockHub/CanvasBlock/CanvasBlock'
+import { selectionManager, slideManager, toolBox } from '@Kernel/index'
+import { ArrayStore } from '@Kernel/Store/ArrayStore'
+import { OriginMap } from '@Kernel/Store/_Store'
+
+export class PenToolController extends ToolController {
+ private _drawing = false
+ private _canvasBlock?: CanvasBlock
+ private _range = { left: Infinity, top: Infinity, right: -Infinity, bottom: -Infinity }
+
+ handleClick() {}
+
+ handleMouseDown(event: MouseEvent): void {
+ this._drawing = true
+ const slideElement = event.currentTarget as HTMLElement
+ const slideRect = slideElement.getBoundingClientRect()
+ this._canvasBlock = new CanvasBlock(0, 0, slideRect.width, slideRect.height)
+ slideManager.currentSlide.addBlock(this._canvasBlock)
+ }
+
+ handleMouseMove(event: MouseEvent) {
+ if (this._drawing) {
+ const { x, y } = toSlideCoords(event.currentTarget as HTMLElement, event.clientX, event.clientY)
+ this._range.left = Math.min(this._range.left, x)
+ this._range.right = Math.max(this._range.right, x)
+ this._range.top = Math.min(this._range.top, y)
+ this._range.bottom = Math.max(this._range.bottom, y)
+ this._canvasBlock?.points.push({ x, y })
+ }
+ }
+
+ handleMouseUp() {
+ if (this._drawing) {
+ this._drawing = false
+ const block = new CanvasBlock(
+ this._range.left,
+ this._range.top,
+ this._range.right - this._range.left,
+ this._range.bottom - this._range.top
+ )
+ for (const point of this._canvasBlock?.points as ArrayStore) {
+ const { x, y } = point as OriginMap
+ block.points.push({
+ x: (x as number) - this._range.left,
+ y: (y as number) - this._range.top,
+ })
+ }
+ const slide = slideManager.currentSlide
+ slide.removeBlock(this._canvasBlock as CanvasBlock)
+ slide.addBlock(block)
+ selectionManager.focus(block)
+ }
+ toolBox.events.toolChange.emit('Default')
+ }
+}
diff --git a/src/Kernel/ToolBox/controller/TextBoxToolController.ts b/src/Kernel/ToolBox/controller/TextBoxToolController.ts
index 8136193..c26c5a2 100644
--- a/src/Kernel/ToolBox/controller/TextBoxToolController.ts
+++ b/src/Kernel/ToolBox/controller/TextBoxToolController.ts
@@ -1,6 +1,6 @@
import { TextBoxBlock } from '@BlockHub/TextBoxBlock/TextBoxBlock'
import { ToolController } from './_ToolController'
-import { slideManager, toolBox } from '@Kernel/index'
+import { selectionManager, slideManager, toolBox } from '@Kernel/index'
import { TEXT_BOX_DEFAULT_HEIGHT, TEXT_BOX_DEFAULT_WIDTH } from '@Const/block'
import { toSlideCoords } from '@Utils/toSlideCoords'
@@ -49,6 +49,7 @@ export class TextBoxToolController extends ToolController {
}
this._currentBlock = undefined
this._dragging = false
+ selectionManager.focus(block)
toolBox.events.toolChange.emit('Default')
}
}
diff --git a/src/Kernel/ToolBox/controller/_index.ts b/src/Kernel/ToolBox/controller/_index.ts
index 921ef66..d05821c 100644
--- a/src/Kernel/ToolBox/controller/_index.ts
+++ b/src/Kernel/ToolBox/controller/_index.ts
@@ -1,4 +1,5 @@
import { DefaultToolController } from './DefaultToolController'
+import { PenToolController } from './PenToolController'
import { PictureToolController } from './PictureToolController'
import { TextBoxToolController } from './TextBoxToolController'
import { ToolController } from './_ToolController'
@@ -7,4 +8,5 @@ export const controllers: { [key: string]: ToolController } = {
Default: new DefaultToolController(),
Picture: new PictureToolController(),
TextBox: new TextBoxToolController(),
+ Pen: new PenToolController(),
}
diff --git a/src/Lang/Locale/en-US/ToolBar.json b/src/Lang/Locale/en-US/ToolBar.json
index 17d081f..1d30eb6 100644
--- a/src/Lang/Locale/en-US/ToolBar.json
+++ b/src/Lang/Locale/en-US/ToolBar.json
@@ -95,7 +95,11 @@
}
},
"draw": {
- "text": "Draw"
+ "text": "Draw",
+ "tools": {
+ "title": "Tools",
+ "pen": "Pen"
+ }
},
"design": {
"text": "Design"
diff --git a/src/Lang/Locale/zh-CN/ToolBar.json b/src/Lang/Locale/zh-CN/ToolBar.json
index cb17226..97a211a 100644
--- a/src/Lang/Locale/zh-CN/ToolBar.json
+++ b/src/Lang/Locale/zh-CN/ToolBar.json
@@ -95,7 +95,11 @@
}
},
"draw": {
- "text": "绘图"
+ "text": "绘图",
+ "tools": {
+ "title": "工具",
+ "pen": "画笔"
+ }
},
"design": {
"text": "设计"
diff --git a/src/UserInterface/Slide/SlideContainer.vue b/src/UserInterface/Slide/SlideContainer.vue
index b9250bb..6bfd98e 100644
--- a/src/UserInterface/Slide/SlideContainer.vue
+++ b/src/UserInterface/Slide/SlideContainer.vue
@@ -1,6 +1,6 @@
diff --git a/src/UserInterface/ToolBar/components/Draw/Tools.vue b/src/UserInterface/ToolBar/components/Draw/Tools.vue
new file mode 100644
index 0000000..7086820
--- /dev/null
+++ b/src/UserInterface/ToolBar/components/Draw/Tools.vue
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
diff --git a/src/UserInterface/ToolBar/components/Draw/index.vue b/src/UserInterface/ToolBar/components/Draw/index.vue
new file mode 100644
index 0000000..2a0790e
--- /dev/null
+++ b/src/UserInterface/ToolBar/components/Draw/index.vue
@@ -0,0 +1,7 @@
+
+
+
+
+