Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: drag root node should layout at its current place #9035

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions packages/affine/block-surface/src/view/mindmap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,10 @@ export class MindMapView extends GfxElementModelView<MindmapElementModel> {
if (payload.props['xywh']) {
updateButtons();
}
if (payload.props['hidden'] !== undefined) {
if (
payload.props['hidden'] !== undefined ||
payload.props['opacity'] !== undefined
) {
this._updateButtonVisibility(payload.id);
}
}
Expand Down Expand Up @@ -170,6 +173,7 @@ export class MindMapView extends GfxElementModelView<MindmapElementModel> {

if (!latestNode) {
buttonModel.opacity = 0;
buttonModel.hidden = true;
return;
}

Expand All @@ -187,9 +191,9 @@ export class MindMapView extends GfxElementModelView<MindmapElementModel> {

buttonModel.hidden = latestNode.element.hidden;
buttonModel.opacity =
hasChildren && notHidden && (collapsed || isNodeSelected || hovered)
(hasChildren && notHidden && (collapsed || isNodeSelected || hovered)
? 1
: 0;
: 0) * (latestNode.element.opacity ?? 1);
}

private _updateCollapseButton(node: MindmapNode) {
Expand Down
11 changes: 11 additions & 0 deletions packages/affine/model/src/elements/mindmap/mindmap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,17 @@ export class MindmapElementModel extends GfxGroupLikeElementModel<MindmapElement
return this._nodeMap.get(id) ?? null;
}

getNodeByPath(path: number[]): MindmapNode | null {
let node: MindmapNode | null = this._tree;

for (let i = 1; i < path.length; i++) {
node = node?.children[path[i]];
if (!node) return null;
}

return node;
}

getParentNode(id: string) {
const node = this.children.get(id);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ export class EdgelessRootBlockComponent extends BlockComponent<
return this.std.event;
}

get fontLoader() {
return this.std.get(FontLoaderService);
}

get gfx() {
return this.std.get(GfxControllerIdentifier);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ import { calculateResponseArea } from './drag-utils.js';
type DragMindMapCtx = {
mindmap: MindmapElementModel;
node: MindmapNode;
clear?: () => void;
clear: () => void;
/**
* Whether the dragged node is the root node of the mind map
*/
isRoot: boolean;
originalMindMapBound: Bound;
startPoint: PointerEventState;
};
Expand Down Expand Up @@ -95,75 +99,72 @@ export class MindMapExt extends DefaultToolExt {
node: hoveredNode,
};

// 1. not hovered on any mind map or
// 2. hovered on the other mind map but not on any node
// then consider user is trying to detach the node
// hovered on the currently dragged mind map but
// 1. not hovered on any node or
// 2. hovered on the node that is itself or its children (which is not allowed)
// then consider user is trying to drop the node to its original position
if (
!hoveredMindMap ||
(hoveredMindMap !== dragMindMapCtx.mindmap && !hoveredNode)
hoveredNode &&
!MindmapUtils.containsNode(
hoveredMindMap!,
hoveredNode,
dragMindMapCtx.node
)
) {
hoveredCtx.detach = true;

const reset = (hoveredCtx.abort = MindmapUtils.hideNodeConnector(
const operation = MindmapUtils.tryMoveNode(
hoveredMindMap!,
hoveredNode,
dragMindMapCtx.mindmap,
dragMindMapCtx.node
));

hoveredCtx.abort = () => {
reset?.();
dragMindMapCtx.node,
[x, y],
options => this._drawIndicator(options)
);

if (operation) {
hoveredCtx.abort = operation.abort;
hoveredCtx.merge = operation.merge;
}
} else if (dragMindMapCtx.isRoot) {
dragMindMapCtx.mindmap.layout();
hoveredCtx.merge = () => {
dragMindMapCtx.mindmap.layout();
};
} else {
// hovered on the currently dragging mind map but
// 1. not hovered on any node or
// 2. hovered on the node that is itself or its children (which is not allowed)
// then consider user is trying to drop the node to its original position
if (
!hoveredNode ||
MindmapUtils.containsNode(
hoveredMindMap,
hoveredNode,
dragMindMapCtx.node
)
) {
const { mindmap, node } = dragMindMapCtx;

// if the node is the root node, then do nothing
if (node === mindmap.tree) {
return;
}

const nodeBound = node.element.elementBound;
// if `hoveredMindMap` is not null
// either the node is hovered on the dragged node's children
// or the there is no hovered node at all
// then consider user is trying to place the node to its original position
if (hoveredMindMap) {
const { node: draggedNode, mindmap } = dragMindMapCtx;
const nodeBound = draggedNode.element.elementBound;

hoveredCtx.abort = this._drawIndicator({
targetMindMap: mindmap,
target: node,
target: draggedNode,
sourceMindMap: mindmap,
source: node,
newParent: node.parent!,
source: draggedNode,
newParent: draggedNode.parent!,
insertPosition: {
type: 'sibling',
layoutDir: mindmap.getLayoutDir(node) as Exclude<
layoutDir: mindmap.getLayoutDir(draggedNode) as Exclude<
LayoutType,
LayoutType.BALANCE
>,
position: y > nodeBound.y + nodeBound.h / 2 ? 'next' : 'prev',
},
path: mindmap.getPath(node),
path: mindmap.getPath(draggedNode),
});
} else {
const operation = MindmapUtils.tryMoveNode(
hoveredMindMap,
hoveredNode,
hoveredCtx.detach = true;

const reset = (hoveredCtx.abort = MindmapUtils.hideNodeConnector(
dragMindMapCtx.mindmap,
dragMindMapCtx.node,
[x, y],
options => this._drawIndicator(options)
);
dragMindMapCtx.node
));

if (operation) {
hoveredCtx.abort = operation.abort;
hoveredCtx.merge = operation.merge;
}
hoveredCtx.abort = () => {
reset?.();
};
}
}
},
Expand Down Expand Up @@ -205,7 +206,7 @@ export class MindMapExt extends DefaultToolExt {
}

hoveredCtx = null;
dragMindMapCtx.clear?.();
dragMindMapCtx.clear();
this._responseAreaUpdated.clear();
},
};
Expand Down Expand Up @@ -395,8 +396,7 @@ export class MindMapExt extends DefaultToolExt {
const mindmap = dragState.movedElements[0].group as MindmapElementModel;
const mindmapNode = mindmap.getNode(dragState.movedElements[0].id)!;
const mindmapBound = mindmap.elementBound;

dragState.movedElements.splice(0, 1);
const isRoot = mindmapNode === mindmap.tree;

mindmapBound.x -= NODE_HORIZONTAL_SPACING;
mindmapBound.y -= NODE_VERTICAL_SPACING * 2;
Expand All @@ -405,19 +405,25 @@ export class MindMapExt extends DefaultToolExt {

this._calcDragResponseArea(mindmap);

const clearDragImage = this._setupDragNodeImage(
mindmapNode,
dragState.event
);
const clearDragStatus = isRoot
? mindmap.stashTree(mindmapNode)
: this._setupDragNodeImage(mindmapNode, dragState.event);
const clearOpacity = this._updateNodeOpacity(mindmap, mindmapNode);

if (!isRoot) {
dragState.movedElements.splice(0, 1);
}

const mindMapDragCtx: DragMindMapCtx = {
mindmap,
node: mindmapNode,
isRoot,
clear: () => {
clearOpacity();
clearDragImage?.();
dragState.movedElements.push(mindmapNode.element);
clearDragStatus?.();
if (!isRoot) {
dragState.movedElements.push(mindmapNode.element);
}
},
originalMindMapBound: mindmapBound,
startPoint: dragState.event,
Expand Down
Loading
Loading