aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/LinkBox.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/LinkBox.tsx')
-rw-r--r--src/client/views/nodes/LinkBox.tsx90
1 files changed, 56 insertions, 34 deletions
diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index 38ff21209..e66fed84b 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -1,19 +1,19 @@
import React = require('react');
import { Bezier } from 'bezier-js';
-import { computed, action } from 'mobx';
+import { computed, IReactionDisposer, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import { Height, Width } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
import { DocCast, NumCast, StrCast } from '../../../fields/Types';
import { aggregateBounds, emptyFunction, returnAlways, returnFalse, Utils } from '../../../Utils';
import { DocumentManager } from '../../util/DocumentManager';
+import { Transform } from '../../util/Transform';
+import { CollectionFreeFormView } from '../collections/collectionFreeForm';
import { ViewBoxBaseComponent } from '../DocComponent';
import { StyleProp } from '../StyleProvider';
import { ComparisonBox } from './ComparisonBox';
import { FieldView, FieldViewProps } from './FieldView';
import './LinkBox.scss';
-import { CollectionFreeFormView } from '../collections/collectionFreeForm';
-import { Transform } from '../../util/Transform';
@observer
export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
@@ -22,9 +22,6 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
onClickScriptDisable = returnAlways;
- componentDidMount() {
- this.props.setContentView?.(this);
- }
@computed get anchor1() {
const anchor1 = DocCast(this.rootDoc.link_anchor_1);
const anchor_1 = anchor1?.layout_unrendered ? DocCast(anchor1.annotationOn) : anchor1;
@@ -56,45 +53,70 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
return { left: 0, top: 0, right: 0, bottom: 0, center: undefined };
};
- render() {
- if (this.layoutDoc._layout_isSvg && (this.anchor1 || this.anchor2)?.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView) {
- const a = (this.anchor1 ?? this.anchor2)!;
- const b = (this.anchor2 ?? this.anchor1)!;
-
- const parxf = this.props.docViewPath()[this.props.docViewPath().length - 2].ComponentView as CollectionFreeFormView;
- const this_xf = parxf?.getTransform() ?? Transform.Identity; //this.props.ScreenToLocalTransform();
- const a_invXf = a.props.ScreenToLocalTransform().inverse();
- const b_invXf = b.props.ScreenToLocalTransform().inverse();
- const a_scrBds = { tl: a_invXf.transformPoint(0, 0), br: a_invXf.transformPoint(a.rootDoc[Width](), a.rootDoc[Height]()) };
- const b_scrBds = { tl: b_invXf.transformPoint(0, 0), br: b_invXf.transformPoint(b.rootDoc[Width](), b.rootDoc[Height]()) };
- const a_bds = { tl: this_xf.transformPoint(a_scrBds.tl[0], a_scrBds.tl[1]), br: this_xf.transformPoint(a_scrBds.br[0], a_scrBds.br[1]) };
- const b_bds = { tl: this_xf.transformPoint(b_scrBds.tl[0], b_scrBds.tl[1]), br: this_xf.transformPoint(b_scrBds.br[0], b_scrBds.br[1]) };
+ disposer: IReactionDisposer | undefined;
+ componentDidMount() {
+ this.props.setContentView?.(this);
+ this.disposer = reaction(
+ () => {
+ if (this.layoutDoc._layout_isSvg && (this.anchor1 || this.anchor2)?.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView) {
+ const a = (this.anchor1 ?? this.anchor2)!;
+ const b = (this.anchor2 ?? this.anchor1)!;
- const ppt1 = [(a_bds.tl[0] + a_bds.br[0]) / 2, (a_bds.tl[1] + a_bds.br[1]) / 2];
- const pt1 = Utils.getNearestPointInPerimeter(a_bds.tl[0], a_bds.tl[1], a_bds.br[0] - a_bds.tl[0], a_bds.br[1] - a_bds.tl[1], (b_bds.tl[0] + b_bds.br[0]) / 2, (b_bds.tl[1] + b_bds.br[1]) / 2);
- const pt2 = Utils.getNearestPointInPerimeter(b_bds.tl[0], b_bds.tl[1], b_bds.br[0] - b_bds.tl[0], b_bds.br[1] - b_bds.tl[1], (a_bds.tl[0] + a_bds.br[0]) / 2, (a_bds.tl[1] + a_bds.br[1]) / 2);
- const ppt2 = [(b_bds.tl[0] + b_bds.br[0]) / 2, (b_bds.tl[1] + b_bds.br[1]) / 2];
+ const parxf = this.props.docViewPath()[this.props.docViewPath().length - 2].ComponentView as CollectionFreeFormView;
+ const this_xf = parxf?.getTransform() ?? Transform.Identity; //this.props.ScreenToLocalTransform();
+ const a_invXf = a.props.ScreenToLocalTransform().inverse();
+ const b_invXf = b.props.ScreenToLocalTransform().inverse();
+ const a_scrBds = { tl: a_invXf.transformPoint(0, 0), br: a_invXf.transformPoint(a.rootDoc[Width](), a.rootDoc[Height]()) };
+ const b_scrBds = { tl: b_invXf.transformPoint(0, 0), br: b_invXf.transformPoint(b.rootDoc[Width](), b.rootDoc[Height]()) };
+ const a_bds = { tl: this_xf.transformPoint(a_scrBds.tl[0], a_scrBds.tl[1]), br: this_xf.transformPoint(a_scrBds.br[0], a_scrBds.br[1]) };
+ const b_bds = { tl: this_xf.transformPoint(b_scrBds.tl[0], b_scrBds.tl[1]), br: this_xf.transformPoint(b_scrBds.br[0], b_scrBds.br[1]) };
- const pts = [ppt1, pt1, pt2, ppt2].map(pt => [pt[0], pt[1]]);
- const [lx, rx, ty, by] = [Math.min(pt1[0], pt2[0]), Math.max(pt1[0], pt2[0]), Math.min(pt1[1], pt2[1]), Math.max(pt1[1], pt2[1])];
- setTimeout(
- action(() => {
- this.layoutDoc.x = lx;
- this.layoutDoc.y = ty;
- this.layoutDoc._width = rx - lx;
- this.layoutDoc._height = by - ty;
- })
- );
+ const ppt1 = [(a_bds.tl[0] + a_bds.br[0]) / 2, (a_bds.tl[1] + a_bds.br[1]) / 2];
+ const pt1 = Utils.getNearestPointInPerimeter(a_bds.tl[0], a_bds.tl[1], a_bds.br[0] - a_bds.tl[0], a_bds.br[1] - a_bds.tl[1], (b_bds.tl[0] + b_bds.br[0]) / 2, (b_bds.tl[1] + b_bds.br[1]) / 2);
+ const pt2 = Utils.getNearestPointInPerimeter(b_bds.tl[0], b_bds.tl[1], b_bds.br[0] - b_bds.tl[0], b_bds.br[1] - b_bds.tl[1], (a_bds.tl[0] + a_bds.br[0]) / 2, (a_bds.tl[1] + a_bds.br[1]) / 2);
+ const ppt2 = [(b_bds.tl[0] + b_bds.br[0]) / 2, (b_bds.tl[1] + b_bds.br[1]) / 2];
+ const pts = [ppt1, pt1, pt2, ppt2].map(pt => [pt[0], pt[1]]);
+ const [lx, rx, ty, by] = [Math.min(pt1[0], pt2[0]), Math.max(pt1[0], pt2[0]), Math.min(pt1[1], pt2[1]), Math.max(pt1[1], pt2[1])];
+ return { pts, lx, rx, ty, by };
+ }
+ return undefined;
+ },
+ params => {
+ this.renderProps = params;
+ if (params) {
+ if (
+ Math.abs(params.lx - NumCast(this.layoutDoc.x)) > 1e-5 ||
+ Math.abs(params.ty - NumCast(this.layoutDoc.y)) > 1e-5 ||
+ Math.abs(params.rx - params.lx - NumCast(this.layoutDoc._width)) > 1e-5 ||
+ Math.abs(params.by - params.ty - NumCast(this.layoutDoc._height)) > 1e-5
+ ) {
+ this.layoutDoc.x = params?.lx;
+ this.layoutDoc.y = params?.ty;
+ this.layoutDoc._width = params.rx - params?.lx;
+ this.layoutDoc._height = params?.by - params?.ty;
+ }
+ }
+ },
+ { fireImmediately: true }
+ );
+ }
+ componentWillUnmount(): void {
+ this.disposer?.();
+ }
+ @observable renderProps: { lx: number; rx: number; ty: number; by: number; pts: number[][] } | undefined;
+ render() {
+ if (this.renderProps) {
const highlight = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Highlighting);
const highlightColor = highlight?.highlightIndex ? highlight?.highlightColor : undefined;
- const bez = new Bezier(pts.map(p => ({ x: p[0], y: p[1] })));
+ const bez = new Bezier(this.renderProps.pts.map(p => ({ x: p[0], y: p[1] })));
const text = bez.get(0.5);
const linkDesc = StrCast(this.rootDoc.link_description) || 'description';
const strokeWidth = NumCast(this.rootDoc.stroke_width, 4);
const dash = StrCast(this.rootDoc.stroke_dash);
const strokeDasharray = dash && Number(dash) ? String(strokeWidth * Number(dash)) : undefined;
+ const { pts, lx, ty, rx, by } = this.renderProps;
return (
<div style={{ transition: 'inherit', pointerEvents: 'none', position: 'absolute', width: '100%', height: '100%' }}>
<svg width={Math.max(100, rx - lx)} height={Math.max(100, by - ty)} style={{ transition: 'inherit', overflow: 'visible' }}>