Skip to content

Commit

Permalink
feat: add basic button render
Browse files Browse the repository at this point in the history
  • Loading branch information
doouding committed Dec 9, 2024
1 parent b7b2b40 commit 9b93621
Show file tree
Hide file tree
Showing 10 changed files with 322 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,7 @@ export function mindmap(
ctx.globalAlpha = origin;
}
}
});

model.extraConnectors.forEach(connector => {
const dx = connector.x - bound.x;
const dy = connector.y - bound.y;

renderConnector(connector, ctx, matrix.translate(dx, dy), renderer, rc);
model.getCollapseButton(to);
});
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import type { ShapeElementModel } from '@blocksuite/affine-model';
import type {
LocalShapeElementModel,
ShapeElementModel,
} from '@blocksuite/affine-model';

import type { RoughCanvas } from '../../../utils/rough/canvas.js';
import type { CanvasRenderer } from '../../canvas-renderer.js';

import { type Colors, drawGeneralShape } from './utils.js';

export function diamond(
model: ShapeElementModel,
model: ShapeElementModel | LocalShapeElementModel,
ctx: CanvasRenderingContext2D,
matrix: DOMMatrix,
renderer: CanvasRenderer,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import type { ShapeElementModel } from '@blocksuite/affine-model';
import type {
LocalShapeElementModel,
ShapeElementModel,
} from '@blocksuite/affine-model';

import type { RoughCanvas } from '../../../utils/rough/canvas.js';
import type { CanvasRenderer } from '../../canvas-renderer.js';

import { type Colors, drawGeneralShape } from './utils.js';

export function ellipse(
model: ShapeElementModel,
model: ShapeElementModel | LocalShapeElementModel,
ctx: CanvasRenderingContext2D,
matrix: DOMMatrix,
renderer: CanvasRenderer,
Expand Down
19 changes: 12 additions & 7 deletions packages/affine/block-surface/src/renderer/elements/shape/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import type { ShapeElementModel, ShapeType } from '@blocksuite/affine-model';
import type {
LocalShapeElementModel,
ShapeElementModel,
ShapeType,
} from '@blocksuite/affine-model';
import type { IBound } from '@blocksuite/global/utils';

import {
Expand Down Expand Up @@ -30,7 +34,7 @@ import { type Colors, horizontalOffset, verticalOffset } from './utils.js';
const shapeRenderers: Record<
ShapeType,
(
model: ShapeElementModel,
model: ShapeElementModel | LocalShapeElementModel,
ctx: CanvasRenderingContext2D,
matrix: DOMMatrix,
renderer: CanvasRenderer,
Expand All @@ -45,7 +49,7 @@ const shapeRenderers: Record<
};

export function shape(
model: ShapeElementModel,
model: ShapeElementModel | LocalShapeElementModel,
ctx: CanvasRenderingContext2D,
matrix: DOMMatrix,
renderer: CanvasRenderer,
Expand Down Expand Up @@ -76,7 +80,7 @@ export function shape(
}

function renderText(
model: ShapeElementModel,
model: ShapeElementModel | LocalShapeElementModel,
ctx: CanvasRenderingContext2D,
{ color }: Colors
) {
Expand All @@ -103,9 +107,10 @@ function renderText(
fontWeight
);
const metrics = getFontMetrics(fontFamily, fontSize, fontWeight);
const lines = deltaInsertsToChunks(
wrapTextDeltas(text, font, w - horPadding * 2)
);
const lines =
typeof text === 'string'
? [text.split('\n').map(line => ({ insert: line }))]
: deltaInsertsToChunks(wrapTextDeltas(text, font, w - horPadding * 2));
const horOffset = horizontalOffset(model.w, model.textAlign, horPadding);
const vertOffset =
verticalOffset(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import type { ShapeElementModel } from '@blocksuite/affine-model';
import type {
LocalShapeElementModel,
ShapeElementModel,
} from '@blocksuite/affine-model';

import type { RoughCanvas } from '../../../utils/rough/canvas.js';
import type { CanvasRenderer } from '../../canvas-renderer.js';
Expand All @@ -11,7 +14,7 @@ import { type Colors, drawGeneralShape } from './utils.js';
const K_RECT = 1 - 0.5522847498;

export function rect(
model: ShapeElementModel,
model: ShapeElementModel | LocalShapeElementModel,
ctx: CanvasRenderingContext2D,
matrix: DOMMatrix,
renderer: CanvasRenderer,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import type { ShapeElementModel } from '@blocksuite/affine-model';
import type {
LocalShapeElementModel,
ShapeElementModel,
} from '@blocksuite/affine-model';

import type { RoughCanvas } from '../../../utils/rough/canvas.js';
import type { CanvasRenderer } from '../../canvas-renderer.js';

import { type Colors, drawGeneralShape } from './utils.js';

export function triangle(
model: ShapeElementModel,
model: ShapeElementModel | LocalShapeElementModel,
ctx: CanvasRenderingContext2D,
matrix: DOMMatrix,
renderer: CanvasRenderer,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type {
LocalShapeElementModel,
ShapeElementModel,
TextAlign,
TextVerticalAlign,
Expand Down Expand Up @@ -28,7 +29,7 @@ export type Colors = {

export function drawGeneralShape(
ctx: CanvasRenderingContext2D,
shapeModel: ShapeElementModel,
shapeModel: ShapeElementModel | LocalShapeElementModel,
renderer: CanvasRenderer,
filled: boolean,
fillColor: string,
Expand Down
109 changes: 92 additions & 17 deletions packages/affine/model/src/elements/mindmap/mindmap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import type { ConnectorStyle, MindmapStyleGetter } from './style.js';

import { LayoutType, MindmapStyle } from '../../consts/mindmap.js';
import { LocalConnectorElementModel } from '../connector/local-connector.js';
import { LocalShapeElementModel } from '../shape/shape.js';
import { mindmapStyleGetters } from './style.js';
import { findInfiniteLoop } from './utils.js';

Expand All @@ -38,6 +39,7 @@ export type NodeDetail = {
*/
index: string;
parent?: string;
collapsed?: boolean;
};

export type MindmapNode = {
Expand Down Expand Up @@ -153,9 +155,9 @@ export class MindmapElementModel extends GfxGroupLikeElementModel<MindmapElement

private _tree!: MindmapRoot;

connectors = new Map<string, LocalConnectorElementModel>();
collapseButtons = new Map<string, LocalShapeElementModel>();

extraConnectors = new Map<string, LocalConnectorElementModel>();
connectors = new Map<string, LocalConnectorElementModel>();

get nodeMap() {
return this._nodeMap;
Expand Down Expand Up @@ -214,6 +216,23 @@ export class MindmapElementModel extends GfxGroupLikeElementModel<MindmapElement
tree.left.reverse();
}

private _isCollapseButtonOutdated(options: {
button: LocalShapeElementModel;
node: MindmapNode;
updateKey?: boolean;
}) {
const { button, node } = options;
const cacheKey = `${node.detail.collapsed ?? false}-${node.element.xywh}-${this.style}`;

if (button.cache.get('MINDMAP_COLLAPSE_BUTTON') === cacheKey) {

Check failure on line 227 in packages/affine/model/src/elements/mindmap/mindmap.ts

View workflow job for this annotation

GitHub Actions / Build

Property 'cache' does not exist on type 'LocalShapeElementModel'.
return false;
} else if (options.updateKey) {
button.cache.set('MINDMAP_COLLAPSE_BUTTON', cacheKey);

Check failure on line 230 in packages/affine/model/src/elements/mindmap/mindmap.ts

View workflow job for this annotation

GitHub Actions / Build

Property 'cache' does not exist on type 'LocalShapeElementModel'.
}

return true;
}

private _isConnectorOutdated(
options: {
connector: LocalConnectorElementModel;
Expand All @@ -226,12 +245,10 @@ export class MindmapElementModel extends GfxGroupLikeElementModel<MindmapElement
const { connector, from, to, layout } = options;
const cacheKey = `${from.element.xywh}-${to.element.xywh}-${layout}-${this.style}`;

// @ts-ignore
if (connector['MINDMAP_CONNECTOR'] === cacheKey) {
if (connector.cache.get('MINDMAP_CONNECTOR') === cacheKey) {

Check failure on line 248 in packages/affine/model/src/elements/mindmap/mindmap.ts

View workflow job for this annotation

GitHub Actions / Build

Property 'cache' does not exist on type 'LocalConnectorElementModel'.
return { outdated: false, cacheKey };
} else if (updateKey) {
// @ts-ignore
connector['MINDMAP_CONNECTOR'] = cacheKey;
connector.cache.set('MINDMAP_CONNECTOR', cacheKey);

Check failure on line 251 in packages/affine/model/src/elements/mindmap/mindmap.ts

View workflow job for this annotation

GitHub Actions / Build

Property 'cache' does not exist on type 'LocalConnectorElementModel'.
}

return { outdated: true, cacheKey };
Expand All @@ -253,17 +270,11 @@ export class MindmapElementModel extends GfxGroupLikeElementModel<MindmapElement
from: MindmapNode,
to: MindmapNode,
layout: LayoutType,
connectorStyle: ConnectorStyle,
extra: boolean = false
connectorStyle: ConnectorStyle
) {
const id = `#${from.id}-${to.id}`;

if (extra) {
this.extraConnectors.set(
id,
new LocalConnectorElementModel(this.surface)
);
} else if (this.connectors.has(id)) {
if (this.connectors.has(id)) {
const connector = this.connectors.get(id)!;
const { outdated } = this._isConnectorOutdated({
connector,
Expand All @@ -287,9 +298,7 @@ export class MindmapElementModel extends GfxGroupLikeElementModel<MindmapElement
this.connectors.set(id, connector);
}

const connector = extra
? this.extraConnectors.get(id)!
: this.connectors.get(id)!;
const connector = this.connectors.get(id)!;

connector.id = id;
connector.source = {
Expand Down Expand Up @@ -532,6 +541,72 @@ export class MindmapElementModel extends GfxGroupLikeElementModel<MindmapElement
return node.children;
}

getCollapseButton(node: MindmapNode) {
const id = `collapse-btn-${node.id}`;
const btnExisted = this.collapseButtons.has(id);
const collapseButton =
this.collapseButtons.get(id) || new LocalShapeElementModel(this.surface);

if (
!btnExisted ||
this._isCollapseButtonOutdated({
button: collapseButton,
node,
updateKey: true,
})
) {
const style = this.styleGetter.getNodeStyle(node, this.getPath(node));
const buttonStyle = node.detail.collapsed
? style.expandButton
: style.collapseButton;

Object.entries(buttonStyle).forEach(([key, value]) => {
if (Object.hasOwn(collapseButton, key)) {
// @ts-ignore
collapseButton[key as unknown] = value;
}
});

const nodeElementBound = node.element.elementBound;
const buttonBound = nodeElementBound.moveDelta(
6 + nodeElementBound.w,
(nodeElementBound.h - buttonStyle.height) / 2
);

buttonBound.w = buttonStyle.width;
buttonBound.h = buttonStyle.height;
collapseButton.xywh = buttonBound.serialize();
collapseButton.groupSignal.value = this.id;
collapseButton.opacity = 0;
}

if (!btnExisted) {
this.collapseButtons.set(id, collapseButton);
this.surface.addLocalElement(collapseButton);

collapseButton.onPointerEnter = () => {
collapseButton.opacity = 1;
};
collapseButton.onPointerLeave = () => {
collapseButton.opacity = 0;
};
collapseButton.onClick = () => {
const nodeDetail = this.children.get(node.id);

if (nodeDetail) {
this.surface.doc.transact(() => {
this.children.set(node.id, {
...nodeDetail,
collapsed: nodeDetail.collapsed ? false : true,
});
});
}
};
}

return collapseButton;
}

getConnector(from: MindmapNode, to: MindmapNode) {
if (!this._nodeMap.has(from.id) || !this._nodeMap.has(to.id)) {
return null;
Expand Down
Loading

0 comments on commit 9b93621

Please sign in to comment.