Skip to content

Commit

Permalink
refactor: tool extension
Browse files Browse the repository at this point in the history
  • Loading branch information
doouding committed Sep 24, 2024
1 parent 46c2e89 commit d6b7398
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 29 deletions.
14 changes: 14 additions & 0 deletions packages/framework/block-std/src/gfx/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@ import { LifeCycleWatcherIdentifier } from '../identifier.js';
import { onSurfaceAdded } from '../utils/gfx.js';
import { GfxBlockElementModel, type GfxModel } from './gfx-block-model.js';
import { GridManager } from './grid.js';
import { KeyboardController } from './keyboard.js';
import { LayerManager } from './layer.js';
import {
GfxPrimitiveElementModel,
type PointTestOptions,
} from './surface/element-model.js';
import { ToolIdentifier } from './tool/tool.js';
import { ToolController } from './tool/tool-controller.js';
import { Viewport } from './viewport.js';

export class GfxController extends LifeCycleWatcher {
Expand All @@ -32,8 +35,12 @@ export class GfxController extends LifeCycleWatcher {

readonly grid: GridManager;

readonly keyboard: KeyboardController;

readonly layer: LayerManager;

readonly tool: ToolController;

readonly viewport: Viewport = new Viewport();

get doc() {
Expand All @@ -49,6 +56,8 @@ export class GfxController extends LifeCycleWatcher {

this.grid = new GridManager();
this.layer = new LayerManager(this.doc, null);
this.keyboard = new KeyboardController(std);
this.tool = new ToolController(std);

this._disposables.add(
onSurfaceAdded(this.doc, surface => {
Expand All @@ -63,6 +72,8 @@ export class GfxController extends LifeCycleWatcher {
this._disposables.add(this.grid.watch({ doc: this.doc }));
this._disposables.add(this.layer);
this._disposables.add(this.viewport);
this._disposables.add(this.keyboard);
this._disposables.add(this.tool);
}

/**
Expand Down Expand Up @@ -186,6 +197,9 @@ export class GfxController extends LifeCycleWatcher {

override mounted() {
this.viewport.setViewportElm(this.std.host);
this.std.provider.getAll(ToolIdentifier).forEach(tool => {
this.tool.register(tool);
});
}

override unmounted() {
Expand Down
2 changes: 1 addition & 1 deletion packages/framework/block-std/src/gfx/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export {
type SurfaceBlockProps,
type SurfaceMiddleware,
} from './surface/surface-model.js';
export { BaseTool } from './tool/tool.js';
export { BaseTool, GfxToolExtension } from './tool/tool.js';

export { ToolController } from './tool/tool-controller.js';
export * from './viewport.js';
Expand Down
43 changes: 43 additions & 0 deletions packages/framework/block-std/src/gfx/keyboard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { DisposableGroup } from '@blocksuite/global/utils';
import { Signal } from '@preact/signals-core';

import type { BlockStdScope } from '../scope/block-std-scope.js';

export class KeyboardController {
private _disposable = new DisposableGroup();

shiftKey$ = new Signal<boolean>(false);

spaceKey$ = new Signal<boolean>(false);

constructor(readonly std: BlockStdScope) {
this._init();
}

private _init() {
this._disposable.add(
this.std.event.add('keyDown', evt => {
const state = evt.get('keyboardState');

this.shiftKey$.value = state.raw.shiftKey && state.raw.key === 'Shift';
this.spaceKey$.value = state.raw.code === 'Space';
})
);

this._disposable.add(
this.std.event.add('keyUp', evt => {
const state = evt.get('keyboardState');

this.shiftKey$.value = !state.raw.shiftKey && state.raw.key === 'Shift';

if (state.raw.code === 'Space') {
this.spaceKey$.value = false;
}
})
);
}

dispose() {
this._disposable.dispose();
}
}
27 changes: 8 additions & 19 deletions packages/framework/block-std/src/gfx/tool/tool-controller.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import {
type Constructor,
DisposableGroup,
type IBound,
} from '@blocksuite/global/utils';
import { DisposableGroup, type IBound } from '@blocksuite/global/utils';
import { Signal } from '@preact/signals-core';

import type { UIEventStateContext } from '../../event/index.js';
Expand Down Expand Up @@ -66,12 +62,9 @@ export class ToolController {
};
}

get host() {
return this.std.host;
}

constructor(readonly std: BlockStdScope) {
const { addHook } = this._initializeEvents();

this[eventTarget] = {
addHook,
};
Expand Down Expand Up @@ -146,17 +139,13 @@ export class ToolController {
});
}

register(toolCtors: Constructor<BaseTool>[]) {
toolCtors.forEach(ctor => {
const tool = new ctor(this);
register(tools: BaseTool) {
if (this._tools.has(tools.toolName)) {
this._tools.get(tools.toolName)?.onunload();
}

if (this._tools.has(tool.name)) {
throw new Error(`Tool "${tool.name}" is already registered`);
}

this._tools.set(tool.name, tool);
tool.onload();
});
this._tools.set(tools.toolName, tools);
tools.onload();
}

use(toolName: string, options: Record<string, unknown> = {}) {
Expand Down
46 changes: 37 additions & 9 deletions packages/framework/block-std/src/gfx/tool/tool.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import { type Container, createIdentifier } from '@blocksuite/global/di';
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';

import type { UIEventStateContext } from '../../event/base.js';
import type { ExtensionType } from '../../extension/extension.js';

import {
eventTarget,
type SupportedEvents,
type ToolController,
} from './tool-controller.js';
import { type GfxController, GfxControllerIdentifier } from '../controller.js';
import { eventTarget, type SupportedEvents } from './tool-controller.js';

export abstract class BaseTool {
abstract readonly name: string;
static toolName: string = '';

get active() {
return this.controller.currentTool$.peek() === this;
return this.gfx.tool.currentTool$.peek() === this;
}

get toolName() {
return (this.constructor as typeof BaseTool).toolName;
}

constructor(readonly controller: ToolController) {}
constructor(readonly gfx: GfxController) {}

/**
* Called when the tool is activated.
Expand All @@ -25,7 +30,7 @@ export abstract class BaseTool {
evtName: SupportedEvents,
handler: (evtState: UIEventStateContext) => undefined | boolean
): void {
this.controller[eventTarget].addHook(evtName, handler);
this.gfx.tool[eventTarget].addHook(evtName, handler);
}

click(_: UIEventStateContext): void {}
Expand Down Expand Up @@ -65,3 +70,26 @@ export abstract class BaseTool {

tripleClick(_: UIEventStateContext): void {}
}

export const ToolIdentifier = createIdentifier<BaseTool>('GfxTool');

export function GfxToolExtension(
toolCtors: (typeof BaseTool)[]
): ExtensionType {
return {
setup: (di: Container) => {
toolCtors.forEach(Ctor => {
if (!Ctor.toolName) {
throw new BlockSuiteError(
ErrorCode.ValueNotExists,
'The tool must have a static property `toolName`'
);
}

di.addImpl(ToolIdentifier(Ctor.toolName), Ctor, [
GfxControllerIdentifier,
]);
});
},
};
}

0 comments on commit d6b7398

Please sign in to comment.