aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/InkingStroke.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/InkingStroke.tsx')
-rw-r--r--src/client/views/InkingStroke.tsx65
1 files changed, 40 insertions, 25 deletions
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index c915ae65a..b3647249a 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -21,7 +21,7 @@
Most of the operations that can be performed on an InkStroke (eg delete a point, rotate, stretch) are implemented in the InkStrokeProperties helper class
*/
import React = require('react');
-import { action, IReactionDisposer, observable, reaction } from 'mobx';
+import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import { Doc } from '../../fields/Doc';
import { Height, Width } from '../../fields/DocSymbols';
@@ -88,11 +88,11 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps>() {
if (!addAsAnnotation && !pinProps) return this.rootDoc;
- const anchor = Docs.Create.InkConfigDocument({
+ const anchor = Docs.Create.ConfigDocument({
title: 'Ink anchor:' + this.rootDoc.title,
// set presentation timing for restoring shape
- presDuration: 1100,
- presTransition: 1000,
+ presentation_duration: 1100,
+ presentation_transition: 1000,
annotationOn: this.rootDoc,
});
if (anchor) {
@@ -297,6 +297,18 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps>() {
*/
nearestScreenPt = () => this._nearestScrPt;
+ @computed get screenCtrlPts() {
+ const { inkData, inkScaleX, inkScaleY, inkStrokeWidth, inkTop, inkLeft } = this.inkScaledData();
+ return inkData
+ .map(point =>
+ this.screenToLocal()
+ .inverse()
+ .transformPoint((point.X - inkLeft - inkStrokeWidth / 2) * inkScaleX + inkStrokeWidth / 2, (point.Y - inkTop - inkStrokeWidth / 2) * inkScaleY + inkStrokeWidth / 2)
+ )
+ .map(p => ({ X: p[0], Y: p[1] }));
+ }
+ startPt = () => this.screenCtrlPts[0];
+ endPt = () => this.screenCtrlPts.lastElement();
/**
* @param boundsLeft the screen space left coordinate of the ink stroke
* @param boundsTop the screen space top coordinate of the ink stroke
@@ -304,18 +316,10 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps>() {
*/
componentUI = (boundsLeft: number, boundsTop: number) => {
const inkDoc = this.props.Document;
- const { inkData, inkScaleX, inkScaleY, inkStrokeWidth, inkTop, inkLeft } = this.inkScaledData();
+ const { inkData, inkStrokeWidth } = this.inkScaledData();
const screenSpaceCenterlineStrokeWidth = Math.min(3, inkStrokeWidth * this.screenToLocal().inverse().Scale); // the width of the blue line widget that shows the centerline of the ink stroke
const screenInkWidth = this.screenToLocal().inverse().transformDirection(inkStrokeWidth, inkStrokeWidth);
- const screenPts = inkData
- .map(point =>
- this.screenToLocal()
- .inverse()
- .transformPoint((point.X - inkLeft - inkStrokeWidth / 2) * inkScaleX + inkStrokeWidth / 2, (point.Y - inkTop - inkStrokeWidth / 2) * inkScaleY + inkStrokeWidth / 2)
- )
- .map(p => ({ X: p[0], Y: p[1] }));
- const screenHdlPts = screenPts;
const startMarker = StrCast(this.layoutDoc.stroke_startMarker);
const endMarker = StrCast(this.layoutDoc.stroke_endMarker);
@@ -323,13 +327,13 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps>() {
return SnappingManager.GetIsDragging() ? null : !InkStrokeProperties.Instance._controlButton ? (
!this.props.isSelected() || InkingStroke.IsClosed(inkData) ? null : (
<div className="inkstroke-UI" style={{ clip: `rect(${boundsTop}px, 10000px, 10000px, ${boundsLeft}px)` }}>
- <InkEndPtHandles inkView={this} inkDoc={inkDoc} startPt={screenPts[0]} endPt={screenPts.lastElement()} screenSpaceLineWidth={screenSpaceCenterlineStrokeWidth} />
+ <InkEndPtHandles inkView={this} inkDoc={inkDoc} startPt={this.startPt} endPt={this.endPt} screenSpaceLineWidth={screenSpaceCenterlineStrokeWidth} />
</div>
)
) : (
<div className="inkstroke-UI" style={{ clip: `rect(${boundsTop}px, 10000px, 10000px, ${boundsLeft}px)` }}>
{InteractionUtils.CreatePolyline(
- screenPts,
+ this.screenCtrlPts,
0,
0,
Colors.MEDIUM_BLUE,
@@ -350,14 +354,23 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps>() {
1.0,
false
)}
- <InkControlPtHandles inkView={this} inkDoc={inkDoc} inkCtrlPoints={inkData} screenCtrlPoints={screenHdlPts} nearestScreenPt={this.nearestScreenPt} screenSpaceLineWidth={screenSpaceCenterlineStrokeWidth} />
- <InkTangentHandles inkView={this} inkDoc={inkDoc} screenCtrlPoints={screenHdlPts} screenSpaceLineWidth={screenSpaceCenterlineStrokeWidth} ScreenToLocalTransform={this.screenToLocal} />
+ <InkControlPtHandles inkView={this} inkDoc={inkDoc} inkCtrlPoints={inkData} screenCtrlPoints={this.screenCtrlPts} nearestScreenPt={this.nearestScreenPt} screenSpaceLineWidth={screenSpaceCenterlineStrokeWidth} />
+ <InkTangentHandles inkView={this} inkDoc={inkDoc} screenCtrlPoints={this.screenCtrlPts} screenSpaceLineWidth={screenSpaceCenterlineStrokeWidth} ScreenToLocalTransform={this.screenToLocal} />
</div>
);
};
_subContentView: DocComponentView | undefined;
setSubContentView = (doc: DocComponentView) => (this._subContentView = doc);
+ @computed get fillColor() {
+ const isInkMask = BoolCast(this.layoutDoc.stroke_isInkMask);
+ return isInkMask ? DashColor(StrCast(this.layoutDoc.fillColor, 'transparent')).blacken(0).rgb().toString() : this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.FillColor) ?? 'transparent';
+ }
+ @computed get strokeColor() {
+ const { inkData } = this.inkScaledData();
+ const fillColor = this.fillColor;
+ return !InkingStroke.IsClosed(inkData) && fillColor && fillColor !== 'transparent' ? fillColor : this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Color) ?? StrCast(this.layoutDoc.color);
+ }
render() {
TraceMobx();
const { inkData, inkStrokeWidth, inkLeft, inkTop, inkScaleX, inkScaleY, inkWidth, inkHeight } = this.inkScaledData();
@@ -367,8 +380,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps>() {
const markerScale = NumCast(this.layoutDoc.stroke_markerScale, 1);
const closed = InkingStroke.IsClosed(inkData);
const isInkMask = BoolCast(this.layoutDoc.stroke_isInkMask);
- const fillColor = isInkMask ? DashColor(StrCast(this.layoutDoc.fillColor, 'transparent')).blacken(0).rgb().toString() : this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.FillColor) ?? 'transparent';
- const strokeColor = !closed && fillColor && fillColor !== 'transparent' ? fillColor : this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Color) ?? StrCast(this.layoutDoc.color);
+ const fillColor = this.fillColor;
// bcz: Hack!! Not really sure why, but having fractional values for width/height of mask ink strokes causes the dragging clone (see DragManager) to be offset from where it should be.
if (isInkMask && (this.layoutDoc[Width]() !== Math.round(this.layoutDoc[Width]()) || this.layoutDoc[Height]() !== Math.round(this.layoutDoc[Height]()))) {
@@ -383,7 +395,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps>() {
inkData,
inkLeft,
inkTop,
- strokeColor,
+ this.strokeColor,
inkStrokeWidth,
inkStrokeWidth,
StrCast(this.layoutDoc.stroke_lineJoin),
@@ -403,20 +415,23 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps>() {
);
const highlight = !this.controlUndo && this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Highlighting);
const highlightIndex = highlight?.highlightIndex;
- const highlightColor = highlight?.highlightIndex ? highlight?.highlightColor : StrCast(this.layoutDoc.stroke_outlineColor, !closed && fillColor && fillColor !== 'transparent' ? StrCast(this.layoutDoc.color, 'transparent') : 'transparent');
+ const highlightColor =
+ (!this.props.isSelected() || !isInkMask) && highlight?.highlightIndex
+ ? highlight?.highlightColor
+ : StrCast(this.layoutDoc.stroke_outlineColor, !closed && fillColor && fillColor !== 'transparent' ? StrCast(this.layoutDoc.color, 'transparent') : 'transparent');
// Invisible polygonal line that enables the ink to be selected by the user.
- const clickableLine = (downHdlr?: (e: React.PointerEvent) => void, suppressFill: boolean = false, mask: boolean = false) =>
+ const clickableLine = (downHdlr?: (e: React.PointerEvent) => void, mask: boolean = false) =>
InteractionUtils.CreatePolyline(
inkData,
inkLeft,
inkTop,
- highlightColor,
+ mask && highlightColor === 'transparent' ? this.strokeColor : highlightColor,
inkStrokeWidth,
inkStrokeWidth + (fillColor ? (closed ? 2 : (highlightIndex ?? 0) + 2) : 2),
StrCast(this.layoutDoc.stroke_lineJoin),
StrCast(this.layoutDoc.stroke_lineCap),
StrCast(this.layoutDoc.stroke_bezier),
- !closed ? 'none' : !isInkMask && (fillColor === 'transparent' || suppressFill) ? 'none' : fillColor,
+ !closed || !fillColor || DashColor(fillColor).alpha() === 0 ? 'none' : fillColor,
'',
'',
markerScale,
@@ -456,7 +471,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps>() {
cursor: this.props.isSelected() ? 'default' : undefined,
}}
{...interactions}>
- {clickableLine(this.onPointerDown, undefined, isInkMask)}
+ {clickableLine(this.onPointerDown, isInkMask)}
{isInkMask ? null : inkLine}
</svg>
{!closed || (!RTFCast(this.rootDoc.text)?.Text && (!this.props.isSelected() || Doc.UserDoc().activeInkHideTextLabels)) ? null : (