Skip to content

Commit

Permalink
feat: add event support
Browse files Browse the repository at this point in the history
  • Loading branch information
doouding committed Dec 9, 2024
1 parent f4d2fb7 commit 15992c9
Show file tree
Hide file tree
Showing 7 changed files with 154 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import type { PointerEventState } from '@blocksuite/block-std';
import type {
GfxLocalElementModel,
GfxPrimitiveElementModel,
} from '@blocksuite/block-std/gfx';

import { Bound } from '@blocksuite/global/utils';

import { DefaultModeDragType, DefaultToolExt } from './ext.js';

export class CanvasElementEventExt extends DefaultToolExt {
private _currentStackedElm: (
| GfxPrimitiveElementModel
| GfxLocalElementModel
)[] = [];

override supportedDragTypes: DefaultModeDragType[] = [
DefaultModeDragType.None,
];

private _executeInReverseOrder(
callback: (elm: GfxPrimitiveElementModel | GfxLocalElementModel) => void,
arr = this._currentStackedElm
): void {
for (let i = arr.length - 1; i >= 0; i--) {
callback(arr[i]);
}
}

override click(_evt: PointerEventState): void {
this._executeInReverseOrder(elm => elm.onClick?.(_evt));
}

override dblClick(_evt: PointerEventState): void {
this._executeInReverseOrder(elm => elm.onDblClick?.(_evt));
}

override pointerDown(_evt: PointerEventState): void {
this._executeInReverseOrder(elm => elm.onPointerDown?.(_evt));
}

override pointerMove(_evt: PointerEventState): void {
const [x, y] = this.gfx.viewport.toModelCoord(_evt.x, _evt.y);
const hoveredElm = this.gfx.grid.search(new Bound(x, y, 1, 1), {
filter: ['canvas', 'local'],
}) as (GfxPrimitiveElementModel | GfxLocalElementModel)[];
const stackedElmMap = new Map(
this._currentStackedElm.map((val, index) => [val, index])
);

this._executeInReverseOrder(elm => {
if (stackedElmMap.has(elm)) {
const idx = stackedElmMap.get(elm)!;
this._currentStackedElm.splice(idx, 1);
elm.onPointerMove?.(_evt);
} else {
elm.onPointerEnter?.(_evt);
}
}, hoveredElm);
this._executeInReverseOrder(elm => elm.onPointerLeave?.(_evt));

this._currentStackedElm = hoveredElm;
}

override pointerUp(_evt: PointerEventState): void {
this._executeInReverseOrder(elm => elm.onPointerUp?.(_evt));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ export type DragState = {
};

export class DefaultToolExt {
readonly supportedDragTypes: DefaultModeDragType[] = [];

get gfx() {
return this.defaultTool.gfx;
}
Expand All @@ -37,6 +39,10 @@ export class DefaultToolExt {

constructor(protected defaultTool: DefaultTool) {}

click(_evt: PointerEventState) {}

dblClick(_evt: PointerEventState) {}

initDrag(_: DragState): {
dragStart?: (evt: PointerEventState) => void;
dragMove?: (evt: PointerEventState) => void;
Expand All @@ -47,5 +53,11 @@ export class DefaultToolExt {

mounted() {}

pointerDown(_evt: PointerEventState) {}

pointerMove(_evt: PointerEventState) {}

pointerUp(_evt: PointerEventState) {}

unmounted() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ type DragMindMapCtx = {
export class MindMapExt extends DefaultToolExt {
private _responseAreaUpdated = new Set<MindmapElementModel>();

override supportedDragTypes: DefaultModeDragType[] = [
DefaultModeDragType.ContentMoving,
];

private get _indicatorOverlay() {
return this.std.getOptional(
OverlayIdentifier('mindmap-indicator')
Expand Down
27 changes: 25 additions & 2 deletions packages/blocks/src/root-block/edgeless/gfx-tool/default-tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import {
mountTextElementEditor,
} from '../utils/text.js';
import { fitToScreen } from '../utils/viewport.js';
import { CanvasElementEventExt } from './default-tool-ext/event-ext.js';
import { DefaultModeDragType } from './default-tool-ext/ext.js';
import { MindMapExt } from './default-tool-ext/mind-map-ext/mind-map-ext.js';

Expand Down Expand Up @@ -241,6 +242,12 @@ export class DefaultTool extends BaseTool {
) as EdgelessFrameManager;
}

private get _supportedExts() {
return this._exts.filter(ext =>
ext.supportedDragTypes.includes(this.dragType)
);
}

/**
* Get the end position of the dragging area in the model coordinate
*/
Expand Down Expand Up @@ -578,7 +585,7 @@ export class DefaultTool extends BaseTool {
event,
};

this._extHandlers = this._exts.map(ext => ext.initDrag(ctx));
this._extHandlers = this._supportedExts.map(ext => ext.initDrag(ctx));
this._selectedBounds = this._toBeMoved.map(element =>
Bound.deserialize(element.xywh)
);
Expand Down Expand Up @@ -732,6 +739,7 @@ export class DefaultTool extends BaseTool {
}

this._isDoubleClickedOnMask = false;
this._supportedExts.forEach(ext => ext.click?.(e));
}

override deactivate() {
Expand Down Expand Up @@ -809,6 +817,8 @@ export class DefaultTool extends BaseTool {
}
}

this._supportedExts.forEach(ext => ext.click?.(e));

if (
e.raw.target &&
e.raw.target instanceof HTMLElement &&
Expand Down Expand Up @@ -990,14 +1000,21 @@ export class DefaultTool extends BaseTool {
})
);

this._exts = [MindMapExt].map(constructor => new constructor(this));
this._exts = [MindMapExt, CanvasElementEventExt].map(
constructor => new constructor(this)
);
this._exts.forEach(ext => ext.mounted());
}

override pointerDown(e: PointerEventState): void {
this._supportedExts.forEach(ext => ext.pointerDown(e));
}

override pointerMove(e: PointerEventState) {
const hovered = this._pick(e.x, e.y, {
hitThreshold: 10,
});

if (
isFrameBlock(hovered) &&
hovered.externalBound?.isPointInBound(
Expand All @@ -1008,6 +1025,12 @@ export class DefaultTool extends BaseTool {
} else {
this.frameOverlay.clear();
}

this._supportedExts.forEach(ext => ext.pointerMove(e));
}

override pointerUp(e: PointerEventState) {
this._supportedExts.forEach(ext => ext.pointerUp(e));
}

override tripleClick() {
Expand Down
15 changes: 15 additions & 0 deletions packages/framework/block-std/src/gfx/model/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {
XYWH,
} from '@blocksuite/global/utils';

import type { PointerEventState } from '../../event/index.js';
import type { EditorHost } from '../../view/element/lit-host.js';
import type { GfxGroupModel, GfxModel } from './model.js';

Expand Down Expand Up @@ -42,6 +43,20 @@ export interface GfxCompatibleInterface extends IBound, GfxElementGeometry {
readonly deserializedXYWH: XYWH;

readonly elementBound: Bound;

onPointerEnter?: (e: PointerEventState) => void;

onPointerLeave?: (e: PointerEventState) => void;

onPointerMove?: (e: PointerEventState) => void;

onPointerDown?: (e: PointerEventState) => void;

onPointerUp?: (e: PointerEventState) => void;

onClick?: (e: PointerEventState) => void;

onDblClick?: (e: PointerEventState) => void;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
import { DocCollection, type Y } from '@blocksuite/store';
import { createMutex } from 'lib0/mutex';

import type { PointerEventState } from '../../../event/index.js';
import type { EditorHost } from '../../../view/index.js';
import type {
GfxCompatibleInterface,
Expand Down Expand Up @@ -79,6 +80,20 @@ export abstract class GfxPrimitiveElementModel<

protected _stashed: Map<keyof Props | string, unknown>;

onClick?: ((e: PointerEventState) => void) | undefined;

onDblClick?: ((e: PointerEventState) => void) | undefined;

onPointerDown?: ((e: PointerEventState) => void) | undefined;

onPointerEnter?: ((e: PointerEventState) => void) | undefined;

onPointerLeave?: ((e: PointerEventState) => void) | undefined;

onPointerMove?: ((e: PointerEventState) => void) | undefined;

onPointerUp?: ((e: PointerEventState) => void) | undefined;

abstract rotate: number;

surface!: SurfaceBlockModel;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
} from '@blocksuite/global/utils';
import { mutex } from 'lib0';

import type { PointerEventState } from '../../../event/index.js';
import type { EditorHost } from '../../../view/index.js';
import type { GfxCompatibleInterface, PointTestOptions } from '../base.js';
import type { GfxGroupModel } from '../model.js';
Expand All @@ -34,6 +35,20 @@ export abstract class GfxLocalElementModel implements GfxCompatibleInterface {

index: string = 'a0';

onClick?: (e: PointerEventState) => void;

onDblClick?: (e: PointerEventState) => void;

onPointerDown?: (e: PointerEventState) => void;

onPointerEnter?: (e: PointerEventState) => void;

onPointerLeave?: (e: PointerEventState) => void;

onPointerMove?: (e: PointerEventState) => void;

onPointerUp?: (e: PointerEventState) => void;

opacity: number = 1;

rotate: number = 0;
Expand Down

0 comments on commit 15992c9

Please sign in to comment.