aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Utils.ts12
-rw-r--r--src/client/util/InteractionUtils.tsx15
-rw-r--r--src/client/util/bezierFit.ts7
-rw-r--r--src/client/views/GestureOverlay.tsx8
-rw-r--r--src/client/views/InkControlPtHandles.tsx3
-rw-r--r--src/client/views/InkStrokeProperties.ts50
-rw-r--r--src/client/views/InkingStroke.tsx11
-rw-r--r--src/client/views/PropertiesView.tsx15
8 files changed, 95 insertions, 26 deletions
diff --git a/src/Utils.ts b/src/Utils.ts
index ca1432de2..f2d9e7766 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -658,12 +658,6 @@ export function setupMoveUpEvents(
(target as any)._lastTap = Date.now();
(target as any)._downX = (target as any)._lastX = e.clientX;
(target as any)._downY = (target as any)._lastY = e.clientY;
- if (!(target as any)._doubleTime && noDoubleTapTimeout) {
- (target as any)._doubleTime = setTimeout(() => {
- noDoubleTapTimeout?.();
- (target as any)._doubleTime = undefined;
- }, doubleTapTimeout);
- }
const _moveEvent = (e: PointerEvent): void => {
if (Math.abs(e.clientX - (target as any)._downX) > Utils.DRAG_THRESHOLD || Math.abs(e.clientY - (target as any)._downY) > Utils.DRAG_THRESHOLD) {
@@ -685,6 +679,12 @@ export function setupMoveUpEvents(
const isClick = Math.abs(e.clientX - (target as any)._downX) < 4 && Math.abs(e.clientY - (target as any)._downY) < 4;
upEvent(e, [e.clientX - (target as any)._downX, e.clientY - (target as any)._downY], isClick);
if (isClick) {
+ if (!(target as any)._doubleTime && noDoubleTapTimeout) {
+ (target as any)._doubleTime = setTimeout(() => {
+ noDoubleTapTimeout?.();
+ (target as any)._doubleTime = undefined;
+ }, doubleTapTimeout);
+ }
if ((target as any)._doubleTime && (target as any)._doubleTap) {
clearTimeout((target as any)._doubleTime);
(target as any)._doubleTime = undefined;
diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx
index 4eb0be320..61872417b 100644
--- a/src/client/util/InteractionUtils.tsx
+++ b/src/client/util/InteractionUtils.tsx
@@ -91,7 +91,7 @@ export namespace InteractionUtils {
export function CreatePolyline(points: { X: number, Y: number }[], left: number, top: number,
color: string, width: number, strokeWidth: number, lineJoin: string, lineCap: string, bezier: string, fill: string, arrowStart: string, arrowEnd: string,
- dash: string | undefined, scalex: number, scaley: number, shape: string, pevents: string, opacity: number, nodefs: boolean,
+ markerScale: number, dash: string | undefined, scalex: number, scaley: number, shape: string, pevents: string, opacity: number, nodefs: boolean,
downHdlr?: ((e: React.PointerEvent) => void)) {
const pts = shape ? makePolygon(shape, points) : points;
@@ -108,6 +108,9 @@ export namespace InteractionUtils {
const Tag = (bezier ? "path" : "polyline") as keyof JSX.IntrinsicElements;
const makerStrokeWidth = strokeWidth / 2;
+ const arrowWidthFactor = 3 * (markerScale ? markerScale : 0.5);// used to be 1.5
+ const arrowLengthFactor = 5 * (markerScale ? markerScale : 0.5);
+ const arrowNotchFactor = 2 * (markerScale ? markerScale : 0.5);
return (<svg fill={color} onPointerDown={downHdlr}> {/* setting the svg fill sets the arrowStart fill */}
{nodefs ? (null) : <defs>
{arrowStart !== "dot" && arrowEnd !== "dot" ? (null) :
@@ -115,12 +118,14 @@ export namespace InteractionUtils {
<circle r={strokeWidth * 1.5} fill="context-stroke" />
</marker>}
{arrowStart !== "arrow" ? (null) :
- <marker id={`arrowStart${defGuid}`} markerUnits="userSpaceOnUse" orient="auto" overflow="visible" refX={makerStrokeWidth * 1.5} refY={0} markerWidth="10" markerHeight="7">
- <polygon style={{ stroke: color }} strokeLinejoin={lineJoin as any} strokeWidth={makerStrokeWidth * 2 / 3} points={`${3 * makerStrokeWidth} ${-makerStrokeWidth * 1.5}, ${makerStrokeWidth * 2} 0, ${3 * makerStrokeWidth} ${makerStrokeWidth * 1.5}, 0 0`} />
+ <marker id={`arrowStart${defGuid}`} markerUnits="userSpaceOnUse" orient="auto" overflow="visible" refX={makerStrokeWidth * (arrowLengthFactor - arrowNotchFactor)} refY={0} markerWidth="10" markerHeight="7">
+ <polygon style={{ stroke: color }} strokeLinejoin={lineJoin as any} strokeWidth={makerStrokeWidth * 2 / 3}
+ points={`${arrowLengthFactor * makerStrokeWidth} ${-makerStrokeWidth * arrowWidthFactor}, ${makerStrokeWidth * (arrowLengthFactor - arrowNotchFactor)} 0, ${arrowLengthFactor * makerStrokeWidth} ${makerStrokeWidth * arrowWidthFactor}, 0 0`} />
</marker>}
{arrowEnd !== "arrow" ? (null) :
- <marker id={`arrowEnd${defGuid}`} markerUnits="userSpaceOnUse" orient="auto" overflow="visible" refX={makerStrokeWidth * 1.5} refY={0} markerWidth="10" markerHeight="7">
- <polygon style={{ stroke: color }} strokeLinejoin={lineJoin as any} strokeWidth={makerStrokeWidth * 2 / 3} points={`0 ${-makerStrokeWidth * 1.5}, ${makerStrokeWidth} 0, 0 ${makerStrokeWidth * 1.5}, ${3 * makerStrokeWidth} 0`} />
+ <marker id={`arrowEnd${defGuid}`} markerUnits="userSpaceOnUse" orient="auto" overflow="visible" refX={makerStrokeWidth * arrowNotchFactor} refY={0} markerWidth="10" markerHeight="7">
+ <polygon style={{ stroke: color }} strokeLinejoin={lineJoin as any} strokeWidth={makerStrokeWidth * 2 / 3}
+ points={`0 ${-makerStrokeWidth * arrowWidthFactor}, ${makerStrokeWidth * arrowNotchFactor} 0, 0 ${makerStrokeWidth * arrowWidthFactor}, ${arrowLengthFactor * makerStrokeWidth} 0`} />
</marker>}
</defs>}
diff --git a/src/client/util/bezierFit.ts b/src/client/util/bezierFit.ts
index 784bb2e18..8fc6de6f9 100644
--- a/src/client/util/bezierFit.ts
+++ b/src/client/util/bezierFit.ts
@@ -53,8 +53,11 @@ class SmartRect {
}
}
-function Normalize(p: Point) {
- const len = Math.sqrt(p.X * p.X + p.Y * p.Y);
+export function Distance(p: Point) {
+ return Math.sqrt(p.X * p.X + p.Y * p.Y);
+}
+export function Normalize(p: Point) {
+ const len = Distance(p);
return new Point(p.X / len, p.Y / len);
}
diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index e2193c9ac..04abdbf37 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -3,7 +3,7 @@ import * as fitCurve from 'fit-curve';
import { action, computed, observable, runInAction } from "mobx";
import { observer } from "mobx-react";
import { Doc } from "../../fields/Doc";
-import { InkData, InkTool, PointData } from "../../fields/InkField";
+import { InkData, InkTool } from "../../fields/InkField";
import { Cast, FieldValue, NumCast } from "../../fields/Types";
import MobileInkOverlay from "../../mobile/MobileInkOverlay";
import { GestureUtils } from "../../pen-gestures/GestureUtils";
@@ -18,7 +18,7 @@ import { SelectionManager } from "../util/SelectionManager";
import { Transform } from "../util/Transform";
import { CollectionFreeFormViewChrome } from "./collections/CollectionMenu";
import "./GestureOverlay.scss";
-import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, SetActiveArrowStart, SetActiveDash, SetActiveFillColor, SetActiveInkColor, SetActiveInkWidth } from "./InkingStroke";
+import { ActiveArrowEnd, ActiveArrowStart, ActiveArrowScale, ActiveDash, ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, SetActiveArrowStart, SetActiveDash, SetActiveFillColor, SetActiveInkColor, SetActiveInkWidth } from "./InkingStroke";
import { DocumentView } from "./nodes/DocumentView";
import { RadialMenu } from "./nodes/RadialMenu";
import HorizontalPalette from "./Palette";
@@ -850,14 +850,14 @@ export class GestureOverlay extends Touchable {
const b = { left: -20000, right: 20000, top: -20000, bottom: 20000, width: 40000, height: 40000 };//this.getBounds(l, true);
return <svg key={i} width={b.width} height={b.height} style={{ transform: `translate(${b.left}px, ${b.top}px)`, pointerEvents: "none", position: "absolute", zIndex: 30000, overflow: "visible" }}>
{InteractionUtils.CreatePolyline(l, b.left, b.top, strokeColor, width, width, "miter", "round",
- ActiveInkBezierApprox(), "none" /*ActiveFillColor()*/, ActiveArrowStart(), ActiveArrowEnd(),
+ ActiveInkBezierApprox(), "none" /*ActiveFillColor()*/, ActiveArrowStart(), ActiveArrowEnd(), ActiveArrowScale(),
ActiveDash(), 1, 1, this.InkShape, "none", 1.0, false)}
</svg>;
}),
this._points.length <= 1 ? (null) : <svg key="svg" width={B.width} height={B.height}
style={{ transform: `translate(${B.left}px, ${B.top}px)`, pointerEvents: "none", position: "absolute", zIndex: 30000, overflow: "visible" }}>
{InteractionUtils.CreatePolyline(this._points.map(p => ({ X: p.X, Y: p.Y - (rect?.y || 0) })), B.left, B.top, ActiveInkColor(), width, width, "miter", "round", "",
- "none" /*ActiveFillColor()*/, ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), 1, 1, this.InkShape, "none", 1.0, false)}
+ "none" /*ActiveFillColor()*/, ActiveArrowStart(), ActiveArrowEnd(), ActiveArrowScale(), ActiveDash(), 1, 1, this.InkShape, "none", 1.0, false)}
</svg>]
];
}
diff --git a/src/client/views/InkControlPtHandles.tsx b/src/client/views/InkControlPtHandles.tsx
index ef457cac4..24f796105 100644
--- a/src/client/views/InkControlPtHandles.tsx
+++ b/src/client/views/InkControlPtHandles.tsx
@@ -51,12 +51,13 @@ export class InkControlPtHandles extends React.Component<InkControlProps> {
const handleIndexB = (order === 3 ? controlIndex + 2 : controlIndex + 1) % this.props.inkCtrlPoints.length;
const brokenIndices = Cast(this.props.inkDoc.brokenInkIndices, listSpec("number"));
const wasSelected = InkStrokeProperties.Instance._currentPoint === controlIndex;
+ const origInk = this.props.inkCtrlPoints.slice();
setupMoveUpEvents(this, e,
action((e: PointerEvent, down: number[], delta: number[]) => {
if (!this.controlUndo) this.controlUndo = UndoManager.StartBatch("drag ink ctrl pt");
const inkMoveEnd = ptFromScreen({ X: delta[0], Y: delta[1] });
const inkMoveStart = ptFromScreen({ X: 0, Y: 0 });
- InkStrokeProperties.Instance.moveControlPtHandle(this.props.inkView, inkMoveEnd.X - inkMoveStart.X, inkMoveEnd.Y - inkMoveStart.Y, controlIndex);
+ InkStrokeProperties.Instance.moveControlPtHandle(this.props.inkView, inkMoveEnd.X - inkMoveStart.X, inkMoveEnd.Y - inkMoveStart.Y, controlIndex, origInk);
return false;
}),
action(() => {
diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts
index 695bdcc5a..cab4e1216 100644
--- a/src/client/views/InkStrokeProperties.ts
+++ b/src/client/views/InkStrokeProperties.ts
@@ -1,4 +1,5 @@
import { Bezier } from "bezier-js";
+import { Normalize, Distance } from "../util/bezierFit";
import { action, observable, reaction } from "mobx";
import { Doc, NumListCast, Opt } from "../../fields/Doc";
import { InkData, InkField, InkTool, PointData } from "../../fields/InkField";
@@ -225,15 +226,57 @@ export class InkStrokeProperties {
*/
@undoBatch
@action
- moveControlPtHandle = (inkView: DocumentView, deltaX: number, deltaY: number, controlIndex: number) =>
+ moveControlPtHandle = (inkView: DocumentView, deltaX: number, deltaY: number, controlIndex: number, origInk?: InkData) =>
this.applyFunction(inkView, (view: DocumentView, ink: InkData, xScale: number, yScale: number) => {
const order = controlIndex % 4;
const closed = InkingStroke.IsClosed(ink);
+ if (origInk && this._currentPoint > 0 && this._currentPoint < ink.length - 1) {
+ const cpt_before = ink[controlIndex];
+ const cpt = { X: cpt_before.X + deltaX, Y: cpt_before.Y + deltaY };
+ if (true) {
+ const newink = origInk.slice();
+ const start = this._currentPoint === 0 ? 0 : this._currentPoint - 4;
+ const splicedPoints = origInk.slice(start, start + (this._currentPoint === 0 || this._currentPoint === ink.length - 1 ? 4 : 8));
+ const { nearestT, nearestSeg } = InkStrokeProperties.nearestPtToStroke(splicedPoints, cpt);
+ const samplesLeft: Point[] = [];
+ const samplesRight: Point[] = [];
+ var startDir = { x: 0, y: 0 };
+ var endDir = { x: 0, y: 0 };
+ for (var i = 0; i < nearestSeg / 4 + 1; i++) {
+ const bez = new Bezier(splicedPoints.slice(i * 4, i * 4 + 4).map(p => ({ x: p.X, y: p.Y })));
+ if (i === 0) startDir = bez.derivative(0);
+ if (i === nearestSeg / 4) endDir = bez.derivative(nearestT);
+ for (var t = 0; t < (i === nearestSeg / 4 ? nearestT + .05 : 1); t += 0.05) {
+ const pt = bez.compute(i !== nearestSeg / 4 ? t : Math.min(nearestT, t));
+ samplesLeft.push(new Point(pt.x, pt.y));
+ }
+ }
+ var { finalCtrls, error } = FitOneCurve(samplesLeft, { X: startDir.x, Y: startDir.y }, { X: endDir.x, Y: endDir.y });
+ for (var i = nearestSeg / 4; i < splicedPoints.length / 4; i++) {
+ const bez = new Bezier(splicedPoints.slice(i * 4, i * 4 + 4).map(p => ({ x: p.X, y: p.Y })));
+ if (i === nearestSeg / 4) startDir = bez.derivative(nearestT);
+ if (i === splicedPoints.length / 4 - 1) endDir = bez.derivative(1);
+ for (var t = i === nearestSeg / 4 ? nearestT : 0; t < (i === nearestSeg / 4 ? 1 + .05 + 1e-7 : 1 + 1e-7); t += 0.05) {
+ const pt = bez.compute(Math.min(1, t));
+ samplesRight.push(new Point(pt.x, pt.y));
+ }
+ }
+ const { finalCtrls: rightCtrls, error: errorRight } = FitOneCurve(samplesRight, { X: startDir.x, Y: startDir.y }, { X: endDir.x, Y: endDir.y });
+ finalCtrls = finalCtrls.concat(rightCtrls);
+ newink.splice(this._currentPoint - 4, 8, ...finalCtrls);
+ return newink;
+ }
+ }
- const newpts = ink.map((pt, i) => {
+ return ink.map((pt, i) => {
const leftHandlePoint = order === 0 && i === controlIndex + 1;
const rightHandlePoint = order === 0 && controlIndex !== 0 && i === controlIndex - 2;
if (controlIndex === i ||
+ (order === 0 && controlIndex !== 0 && i === controlIndex - 1) ||
+ (order === 3 && i === controlIndex - 1)) {
+ return ({ X: pt.X + deltaX, Y: pt.Y + deltaY });
+ }
+ if (controlIndex === i ||
leftHandlePoint ||
rightHandlePoint ||
(order === 0 && controlIndex !== 0 && i === controlIndex - 1) ||
@@ -246,7 +289,6 @@ export class InkStrokeProperties {
}
return pt;
});
- return newpts;
})
@@ -286,7 +328,7 @@ export class InkStrokeProperties {
if (snapData.distance < 10) {
const deltaX = (snapData.nearestPt.X - ink[controlIndex].X);
const deltaY = (snapData.nearestPt.Y - ink[controlIndex].Y);
- const res = this.moveControlPtHandle(inkView, deltaX, deltaY, controlIndex);
+ const res = this.moveControlPtHandle(inkView, deltaX, deltaY, controlIndex, ink.slice());
console.log("X = " + snapData.nearestPt.X + " " + snapData.nearestPt.Y);
return res;
}
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index f5dd66949..5c7fc94bd 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -31,7 +31,6 @@ import { BoolCast, Cast, NumCast, StrCast } from "../../fields/Types";
import { TraceMobx } from "../../fields/util";
import { OmitKeys, returnFalse, setupMoveUpEvents } from "../../Utils";
import { CognitiveServices } from "../cognitive_services/CognitiveServices";
-import { CurrentUserUtils } from "../util/CurrentUserUtils";
import { InteractionUtils } from "../util/InteractionUtils";
import { SnappingManager } from "../util/SnappingManager";
import { Transform } from "../util/Transform";
@@ -262,6 +261,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
const startMarker = StrCast(this.layoutDoc.strokeStartMarker);
const endMarker = StrCast(this.layoutDoc.strokeEndMarker);
+ const markerScale = NumCast(this.layoutDoc.strokeMarkerScale, 1);
return SnappingManager.GetIsDragging() ? (null) :
!InkStrokeProperties.Instance._controlButton ?
(!this.props.isSelected() || InkingStroke.IsClosed(inkData) ? (null) :
@@ -275,7 +275,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
<div className="inkstroke-UI" style={{ clip: `rect(${boundsTop}px, 10000px, 10000px, ${boundsLeft}px)` }}>
{InteractionUtils.CreatePolyline(screenPts, 0, 0, Colors.MEDIUM_BLUE, screenInkWidth[0], screenSpaceCenterlineStrokeWidth,
StrCast(inkDoc.strokeLineJoin), StrCast(this.layoutDoc.strokeLineCap), StrCast(inkDoc.strokeBezier),
- "none", startMarker, endMarker, StrCast(inkDoc.strokeDash), 1, 1, "", "none", 1.0, false)}
+ "none", startMarker, endMarker, markerScale, StrCast(inkDoc.strokeDash), 1, 1, "", "none", 1.0, false)}
<InkControlPtHandles
inkView={this.props.docViewPath().lastElement()}
inkDoc={inkDoc}
@@ -299,6 +299,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
const startMarker = StrCast(this.layoutDoc.strokeStartMarker);
const endMarker = StrCast(this.layoutDoc.strokeEndMarker);
+ const markerScale = NumCast(this.layoutDoc.strokeMarkerScale, 1);
const closed = InkingStroke.IsClosed(inkData);
const fillColor = StrCast(this.layoutDoc.fillColor, "transparent");
const strokeColor = !closed && fillColor && fillColor !== "transparent" ? fillColor : StrCast(this.layoutDoc.color);
@@ -307,7 +308,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
const inkLine = InteractionUtils.CreatePolyline(inkData, inkLeft, inkTop, strokeColor, inkStrokeWidth, inkStrokeWidth,
StrCast(this.layoutDoc.strokeLineJoin), StrCast(this.layoutDoc.strokeLineCap),
StrCast(this.layoutDoc.strokeBezier), !closed ? "none" : fillColor === "transparent" ? "none" : fillColor, startMarker, endMarker,
- StrCast(this.layoutDoc.strokeDash), inkScaleX, inkScaleY, "", "none", 1.0, false);
+ markerScale, StrCast(this.layoutDoc.strokeDash), inkScaleX, inkScaleY, "", "none", 1.0, false);
const highlightIndex = BoolCast(this.props.Document.isLinkButton) && Doc.isBrushedHighlightedDegree(this.props.Document); // bcz: Argh!! need to identify a tree view doc better than a LayoutTemlatString
const highlightColor = !highlightIndex ?
StrCast(this.layoutDoc.strokeOutlineColor, !closed && fillColor && fillColor !== "transparent" ? StrCast(this.layoutDoc.color, "transparent") : "transparent") :
@@ -317,7 +318,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
inkStrokeWidth, inkStrokeWidth + (highlightIndex && closed && fillColor && (new Color(fillColor)).alpha() < 1 ? 6 : 15),
StrCast(this.layoutDoc.strokeLineJoin), StrCast(this.layoutDoc.strokeLineCap),
StrCast(this.layoutDoc.strokeBezier), !closed ? "none" : fillColor === "transparent" ? "none" : fillColor, startMarker, endMarker,
- undefined, inkScaleX, inkScaleY, "", this.props.pointerEvents ?? (this.props.layerProvider?.(this.props.Document) === false ? "none" : "visiblepainted"), 0.0,
+ markerScale, undefined, inkScaleX, inkScaleY, "", this.props.pointerEvents ?? (this.props.layerProvider?.(this.props.Document) === false ? "none" : "visiblepainted"), 0.0,
false, downHdlr);
return <div className="inkStroke-wrapper">
@@ -370,12 +371,14 @@ export function SetActiveInkColor(value: string) { ActiveInkPen() && (ActiveInkP
export function SetActiveFillColor(value: string) { ActiveInkPen() && (ActiveInkPen().activeFillColor = value); }
export function SetActiveArrowStart(value: string) { ActiveInkPen() && (ActiveInkPen().activeArrowStart = value); }
export function SetActiveArrowEnd(value: string) { ActiveInkPen() && (ActiveInkPen().activeArrowEnd = value); }
+export function SetActiveArrowScale(value: number) { ActiveInkPen() && (ActiveInkPen().activeArrowScale = value); }
export function SetActiveDash(dash: string): void { !isNaN(parseInt(dash)) && ActiveInkPen() && (ActiveInkPen().activeDash = dash); }
export function ActiveInkPen(): Doc { return Doc.UserDoc(); }
export function ActiveInkColor(): string { return StrCast(ActiveInkPen()?.activeInkColor, "black"); }
export function ActiveFillColor(): string { return StrCast(ActiveInkPen()?.activeFillColor, ""); }
export function ActiveArrowStart(): string { return StrCast(ActiveInkPen()?.activeArrowStart, ""); }
export function ActiveArrowEnd(): string { return StrCast(ActiveInkPen()?.activeArrowEnd, ""); }
+export function ActiveArrowScale(): number { return NumCast(ActiveInkPen()?.activeArrowScale, 1); }
export function ActiveDash(): string { return StrCast(ActiveInkPen()?.activeDash, "0"); }
export function ActiveInkWidth(): number { return Number(ActiveInkPen()?.activeInkWidth); }
export function ActiveInkBezierApprox(): string { return StrCast(ActiveInkPen()?.activeInkBezier); }
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 18d5f1642..8e2426006 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -756,6 +756,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
@computed get dashdStk() { return this.selectedDoc?.strokeDash || ""; }
@computed get unStrokd() { return this.selectedDoc?.color ? true : false; }
@computed get widthStk() { return this.getField("strokeWidth") || "1"; }
+ @computed get markScal() { return Number(this.getField("strokeMakerScale") || "1"); }
@computed get markHead() { return this.getField("strokeStartMarker") || ""; }
@computed get markTail() { return this.getField("strokeEndMarker") || ""; }
set solidStk(value) { this.dashdStk = ""; this.unStrokd = !value; }
@@ -763,6 +764,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
value && (this._lastDash = value) && (this.unStrokd = false);
this.selectedDoc && (this.selectedDoc.strokeDash = value ? this._lastDash : undefined);
}
+ set markScal(value) { this.selectedDoc && (this.selectedDoc.strokeMarkerScale = Number(value)); }
set widthStk(value) { this.selectedDoc && (this.selectedDoc.strokeWidth = Number(value)); }
set unStrokd(value) { this.colorStk = value ? "" : this._lastLine; }
set markHead(value) { this.selectedDoc && (this.selectedDoc.strokeStartMarker = value); }
@@ -770,6 +772,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
@computed get stkInput() { return this.regInput("stk", this.widthStk, (val: string) => this.widthStk = val); }
+ @computed get markScaleInput() { return this.regInput("scale", this.markScal.toString(), (val: string) => this.markScal = Number(val)); }
regInput = (key: string, value: any, setter: (val: string) => {}) => {
@@ -807,6 +810,18 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
<div className="arrows">
<div className="arrows-head">
+ <div className="width-top">
+ <div className="width-title">Arrow Scale:</div>
+ {/* <div className="width-input">{this.markScalInput}</div> */}
+ </div>
+ <input className="width-range" type="range"
+ defaultValue={this.markScal} min={0} max={10}
+ onChange={(action(e => this.markScal = +e.target.value))}
+ onMouseDown={(e) => { this._widthUndo = UndoManager.StartBatch("scale undo"); }}
+ onMouseUp={(e) => { this._widthUndo?.end(); this._widthUndo = undefined; }}
+ />
+ </div>
+ <div className="arrows-head">
<div className="arrows-head-title" >Arrow Head: </div>
<input key="markHead" className="arrows-head-input" type="checkbox"
checked={this.markHead !== ""}