diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Utils.ts | 12 | ||||
-rw-r--r-- | src/client/util/InteractionUtils.tsx | 15 | ||||
-rw-r--r-- | src/client/util/bezierFit.ts | 7 | ||||
-rw-r--r-- | src/client/views/GestureOverlay.tsx | 8 | ||||
-rw-r--r-- | src/client/views/InkControlPtHandles.tsx | 3 | ||||
-rw-r--r-- | src/client/views/InkStrokeProperties.ts | 50 | ||||
-rw-r--r-- | src/client/views/InkingStroke.tsx | 11 | ||||
-rw-r--r-- | src/client/views/PropertiesView.tsx | 15 |
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 !== ""} |