Skip to content

Commit

Permalink
feat: DrawRelationship
Browse files Browse the repository at this point in the history
  • Loading branch information
dineug committed Nov 12, 2023
1 parent 847b499 commit 542f2a1
Show file tree
Hide file tree
Showing 33 changed files with 597 additions and 92 deletions.
2 changes: 1 addition & 1 deletion packages/erd-editor/src/components/erd-editor/ErdEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
} from '@dineug/r-html';
import { fromEvent, merge, throttleTime } from 'rxjs';

import { appContext, createAppContext } from '@/components/context';
import { appContext, createAppContext } from '@/components/appContext';
import Erd from '@/components/erd/Erd';
import GlobalStyles from '@/components/global-styles/GlobalStyles';
import Theme from '@/components/theme/Theme';
Expand Down
4 changes: 2 additions & 2 deletions packages/erd-editor/src/components/erd/Erd.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createRef, FC, html, observable, ref } from '@dineug/r-html';

import { useAppContext } from '@/components/context';
import { useAppContext } from '@/components/appContext';
import Canvas from '@/components/erd/canvas/Canvas';
import DragSelect from '@/components/erd/drag-select/DragSelect';
import ErdContextMenu, {
Expand Down Expand Up @@ -126,7 +126,7 @@ const Erd: FC<ErdProps> = (props, ctx) => {
@touchstart=${handleDragSelect}
@wheel=${handleWheel}
>
<${Canvas} canvas=${canvas} />
<${Canvas} root=${root} canvas=${canvas} />
<${Minimap} />
${state.dragSelect
? html`
Expand Down
11 changes: 10 additions & 1 deletion packages/erd-editor/src/components/erd/canvas/Canvas.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { cache, FC, html, Ref, ref, repeat } from '@dineug/r-html';

import { useAppContext } from '@/components/context';
import { useAppContext } from '@/components/appContext';
import DrawRelationship from '@/components/erd/canvas/draw-relationship/DrawRelationship';
import HighLevelTable from '@/components/erd/canvas/high-level-table/HighLevelTable';
import Memo from '@/components/erd/canvas/memo/Memo';
import Table from '@/components/erd/canvas/table/Table';
Expand All @@ -9,6 +10,7 @@ import { query } from '@/utils/collection/query';
import * as styles from './Canvas.styles';

export type CanvasProps = {
root: Ref<HTMLDivElement>;
canvas: Ref<HTMLDivElement>;
};

Expand All @@ -20,6 +22,7 @@ const Canvas: FC<CanvasProps> = (props, ctx) => {
const {
settings: { width, height, scrollTop, scrollLeft, zoomLevel, show },
doc: { tableIds, memoIds },
editor: { drawRelationship },
collections,
} = store.state;

Expand Down Expand Up @@ -61,6 +64,12 @@ const Canvas: FC<CanvasProps> = (props, ctx) => {
memo => memo.id,
memo => html`<${Memo} memo=${memo} />`
)}
${drawRelationship?.start
? html`<${DrawRelationship}
root=${props.root}
draw=${drawRelationship}
/>`
: null}
</div>
`;
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { css } from '@dineug/r-html';

export const root = css`
position: absolute;
top: 0;
left: 0;
pointer-events: none;
stroke: var(--key-fk);
overflow: visible;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { FC, onMounted, Ref, svg } from '@dineug/r-html';
import { fromEvent } from 'rxjs';

import { useAppContext } from '@/components/appContext';
import { drawRelationshipAction } from '@/engine/modules/editor/atom.actions';
import { DrawRelationship as DrawRelationshipType } from '@/engine/modules/editor/state';
import { useUnmounted } from '@/hooks/useUnmounted';
import { getDraw } from '@/utils/draw-relationship/drawRelationship';

import * as styles from './DrawRelationship.styles';

export type DrawRelationshipProps = {
root: Ref<HTMLDivElement>;
draw: DrawRelationshipType;
};

const DrawRelationship: FC<DrawRelationshipProps> = (props, ctx) => {
const app = useAppContext(ctx);
const { addUnsubscribe } = useUnmounted();

onMounted(() => {
const $root = props.root.value;
const { store } = app.value;

addUnsubscribe(
fromEvent<MouseEvent>($root, 'mousemove').subscribe(event => {
event.preventDefault();
const { x, y } = $root.getBoundingClientRect();

store.dispatch(
drawRelationshipAction({
x: event.clientX - x,
y: event.clientY - y,
})
);
})
);
});

return () => {
const { store } = app.value;
const {
settings: { width, height },
} = store.state;

const { path, line } = getDraw(store.state, props.draw);

return svg`
<svg
class=${styles.root}
style=${{
width: `${width}px`,
height: `${height}px`,
'min-width': `${width}px`,
'min-height': `${height}px`,
}}
>
<g>
<path
d=${path.path.d()}
stroke-dasharray="10"
stroke-width="3"
fill="transparent"
></path>
<line
x1=${path.line.start.x1} y1=${path.line.start.y1}
x2=${path.line.start.x2} y2=${path.line.start.y2}
stroke-width="3"
></line>
<line
x1=${line.start.base.x1} y1=${line.start.base.y1}
x2=${line.start.base.x2} y2=${line.start.base.y2}
stroke-width="3"
></line>
<line
x1=${line.start.base2.x1} y1=${line.start.base2.y1}
x2=${line.start.base2.x2} y2=${line.start.base2.y2}
stroke-width="3"
></line>
<line
x1=${line.start.center2.x1} y1=${line.start.center2.y1}
x2=${line.start.center2.x2} y2=${line.start.center2.y2}
stroke-width="3"
></line>
</g>
</svg>
`;
};
};

export default DrawRelationship;
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FC, html } from '@dineug/r-html';

import { useAppContext } from '@/components/context';
import { useAppContext } from '@/components/appContext';
import * as styles from '@/components/erd/canvas/table/Table.styles';
import { useMoveTable } from '@/components/erd/canvas/table/useMoveTable';
import { Table } from '@/internal-types';
Expand Down
2 changes: 1 addition & 1 deletion packages/erd-editor/src/components/erd/canvas/memo/Memo.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FC, html } from '@dineug/r-html';

import { useAppContext } from '@/components/context';
import { useAppContext } from '@/components/appContext';
import MemoSash from '@/components/erd/canvas/memo/memo-sash/MemoSash';
import Icon from '@/components/primitives/icon/Icon';
import { moveAllAction$ } from '@/engine/modules/editor/generator.actions';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { FC, html } from '@dineug/r-html';

import { useAppContext } from '@/components/context';
import { useAppContext } from '@/components/appContext';
import Sash, { SashProps, SashType } from '@/components/primitives/sash/Sash';
import { MEMO_MIN_HEIGHT, MEMO_MIN_WIDTH } from '@/constants/layout';
import { resizeMemoAction } from '@/engine/modules/memo/atom.actions';
import { Memo, ValuesType } from '@/internal-types';
import { DirectionName } from '@/utils/draw-relationship';
import { drag$, DragMove } from '@/utils/globalEventObservable';

export type MemoSashProps = {
Expand All @@ -25,14 +26,6 @@ const Position = {
} as const;
type Position = ValuesType<typeof Position>;

const Direction = {
left: 'left',
right: 'right',
top: 'top',
bottom: 'bottom',
} as const;
type Direction = ValuesType<typeof Direction>;

const createSash = (
top: number,
left: number
Expand All @@ -43,42 +36,42 @@ const createSash = (
> => [
{
type: SashType.vertical,
position: 'left',
position: Position.left,
},
{
type: SashType.vertical,
position: 'right',
position: Position.right,
left,
},
// {
// type: SashType.horizontal,
// position: 'top',
// position: Position.top,
// },
{
type: SashType.horizontal,
position: 'bottom',
position: Position.bottom,
top,
},
{
type: SashType.edge,
position: 'lt',
position: Position.lt,
cursor: 'nwse-resize',
},
{
type: SashType.edge,
position: 'rt',
position: Position.rt,
cursor: 'nesw-resize',
left,
},
{
type: SashType.edge,
position: 'lb',
position: Position.lb,
cursor: 'nesw-resize',
top,
},
{
type: SashType.edge,
position: 'rb',
position: Position.rb,
cursor: 'nwse-resize',
top,
left,
Expand All @@ -101,25 +94,28 @@ const MemoSash: FC<MemoSashProps> = (props, ctx) => {

const resizeWidth = (
{ movementX, x }: DragMove,
direction: Direction
direction: DirectionName
): ResizeMemo => {
const ui = Object.assign({ change: false }, props.memo.ui);
const mouseDirection: Direction = movementX < 0 ? 'left' : 'right';
const mouseDirection =
movementX < 0 ? DirectionName.left : DirectionName.right;
const width =
direction === 'left' ? ui.width - movementX : ui.width + movementX;
direction === DirectionName.left
? ui.width - movementX
: ui.width + movementX;

switch (mouseDirection) {
case 'left':
case DirectionName.left:
if (MEMO_MIN_WIDTH < width && x < clientX) {
direction === 'left' && (ui.x += movementX);
direction === DirectionName.left && (ui.x += movementX);
clientX += movementX;
ui.width = width;
ui.change = true;
}
break;
case 'right':
case DirectionName.right:
if (MEMO_MIN_WIDTH < width && x > clientX) {
direction === 'left' && (ui.x += movementX);
direction === DirectionName.left && (ui.x += movementX);
clientX += movementX;
ui.width = width;
ui.change = true;
Expand All @@ -131,25 +127,28 @@ const MemoSash: FC<MemoSashProps> = (props, ctx) => {

const resizeHeight = (
{ movementY, y }: DragMove,
direction: Direction
direction: DirectionName
): ResizeMemo => {
const ui = Object.assign({ change: false }, props.memo.ui);
const mouseDirection: Direction = movementY < 0 ? 'top' : 'bottom';
const mouseDirection =
movementY < 0 ? DirectionName.top : DirectionName.bottom;
const height =
direction === 'top' ? ui.height - movementY : ui.height + movementY;
direction === DirectionName.top
? ui.height - movementY
: ui.height + movementY;

switch (mouseDirection) {
case 'top':
case DirectionName.top:
if (MEMO_MIN_HEIGHT < height && y < clientY) {
direction === 'top' && (ui.y += movementY);
direction === DirectionName.top && (ui.y += movementY);
clientY += movementY;
ui.height = height;
ui.change = true;
}
break;
case 'bottom':
case DirectionName.bottom:
if (MEMO_MIN_HEIGHT < height && y > clientY) {
direction === 'top' && (ui.y += movementY);
direction === DirectionName.top && (ui.y += movementY);
clientY += movementY;
ui.height = height;
ui.change = true;
Expand All @@ -166,29 +165,29 @@ const MemoSash: FC<MemoSashProps> = (props, ctx) => {
let horizontalUI: ResizeMemo | null = null;

switch (position) {
case 'left':
case 'right':
case Position.left:
case Position.right:
verticalUI = resizeWidth(dragMove, position);
break;
case 'top':
case 'bottom':
case Position.top:
case Position.bottom:
horizontalUI = resizeHeight(dragMove, position);
break;
case 'lt':
verticalUI = resizeWidth(dragMove, 'left');
horizontalUI = resizeHeight(dragMove, 'top');
case Position.lt:
verticalUI = resizeWidth(dragMove, DirectionName.left);
horizontalUI = resizeHeight(dragMove, DirectionName.top);
break;
case 'rt':
verticalUI = resizeWidth(dragMove, 'right');
horizontalUI = resizeHeight(dragMove, 'top');
case Position.rt:
verticalUI = resizeWidth(dragMove, DirectionName.right);
horizontalUI = resizeHeight(dragMove, DirectionName.top);
break;
case 'lb':
verticalUI = resizeWidth(dragMove, 'left');
horizontalUI = resizeHeight(dragMove, 'bottom');
case Position.lb:
verticalUI = resizeWidth(dragMove, DirectionName.left);
horizontalUI = resizeHeight(dragMove, DirectionName.bottom);
break;
case 'rb':
verticalUI = resizeWidth(dragMove, 'right');
horizontalUI = resizeHeight(dragMove, 'bottom');
case Position.rb:
verticalUI = resizeWidth(dragMove, DirectionName.right);
horizontalUI = resizeHeight(dragMove, DirectionName.bottom);
break;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FC, html, repeat } from '@dineug/r-html';

import { useAppContext } from '@/components/context';
import { useAppContext } from '@/components/appContext';
import Column from '@/components/erd/canvas/table/column/Column';
import EditInput from '@/components/primitives/edit-input/EditInput';
import Icon from '@/components/primitives/icon/Icon';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { DOMTemplateLiterals, FC, html, repeat } from '@dineug/r-html';

import { useAppContext } from '@/components/context';
import { useAppContext } from '@/components/appContext';
import ColumnKey from '@/components/erd/canvas/table/column/column-key/ColumnKey';
import ColumnNotNull from '@/components/erd/canvas/table/column/column-not-null/ColumnNotNull';
import ColumnOption from '@/components/erd/canvas/table/column/column-option/ColumnOption';
Expand Down
Loading

0 comments on commit 542f2a1

Please sign in to comment.