aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2024-11-05 10:22:31 -0500
committerbobzel <zzzman@gmail.com>2024-11-05 10:22:31 -0500
commit10a89be0b184df2750a4b3eceb48db205cb83e95 (patch)
treec0284ee35e1e1f075db11c14ab837c9c5c950c5f /src
parent4ab636e338a11e8153d43adddb0e0d3e6bad57ec (diff)
fixed display of where control point will be added on mouse moves. fixed clickable ink line to not select fill area unless its actually painted. added end cap properties to ink stroke ui. enabled more than one ink stroke to show editable control points when multiselected.
Diffstat (limited to 'src')
-rw-r--r--src/client/views/ComponentDecorations.tsx6
-rw-r--r--src/client/views/DocumentDecorations.tsx10
-rw-r--r--src/client/views/InkingStroke.tsx14
-rw-r--r--src/client/views/PropertiesView.scss1
-rw-r--r--src/client/views/PropertiesView.tsx33
5 files changed, 42 insertions, 22 deletions
diff --git a/src/client/views/ComponentDecorations.tsx b/src/client/views/ComponentDecorations.tsx
index 929b549e0..28e9d9792 100644
--- a/src/client/views/ComponentDecorations.tsx
+++ b/src/client/views/ComponentDecorations.tsx
@@ -5,11 +5,7 @@ import { DocumentView } from './nodes/DocumentView';
@observer
export class ComponentDecorations extends React.Component<{ boundsTop: number; boundsLeft: number }, { value: string }> {
- // eslint-disable-next-line no-use-before-define
- static Instance: ComponentDecorations;
-
render() {
- const seldoc = DocumentView.Selected().lastElement();
- return seldoc?.ComponentView?.componentUI?.(this.props.boundsLeft, this.props.boundsTop) ?? null;
+ return DocumentView.Selected().map(seldoc => seldoc?.ComponentView?.componentUI?.(this.props.boundsLeft, this.props.boundsTop) ?? null);
}
}
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 66043c033..492c2bda1 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -181,7 +181,13 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
};
onBackgroundDown = (e: React.PointerEvent) => {
- setupMoveUpEvents(this, e, moveEv => this.onBackgroundMove(false, moveEv), emptyFunction, emptyFunction);
+ setupMoveUpEvents(
+ this,
+ e,
+ moveEv => this.onBackgroundMove(false, moveEv),
+ emptyFunction,
+ (clickEv, doubleTap) => doubleTap && DocumentView.Selected().some(dv => dv.Document.layout_isSvg) && (InkStrokeProperties.Instance._controlButton = true)
+ );
e.stopPropagation();
};
@action
@@ -791,7 +797,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
transformOrigin,
background: SnappingManager.ShiftKey ? undefined : 'yellow',
pointerEvents: SnappingManager.ShiftKey || SnappingManager.IsResizing ? 'none' : 'all',
- display: DocumentView.Selected().length <= 1 || hideDecorations ? 'none' : undefined,
+ display: DocumentView.Selected().length <= 1 || InkStrokeProperties.Instance._controlButton || hideDecorations ? 'none' : undefined,
transform: `rotate(${rotation}deg)`,
}}
onPointerDown={this.onBackgroundDown}
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 5199eb02b..f847db6c2 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 { Property } from 'csstype';
-import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
+import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { DashColor, returnFalse, setupMoveUpEvents } from '../../ClientUtils';
@@ -66,9 +66,14 @@ export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>()
private _handledClick = false; // flag denoting whether ink stroke has handled a psuedo-click onPointerUp so that the real onClick event can be stopPropagated
private _disposers: { [key: string]: IReactionDisposer } = {};
+ constructor(props: FieldViewProps) {
+ super(props);
+ makeObservable(this);
+ }
+
@observable _nearestSeg?: number = undefined; // nearest Bezier segment along the ink stroke to the cursor (used for displaying the Add Point highlight)
@observable _nearestT?: number = undefined; // nearest t value within the nearest Bezier segment "
- @observable _nearestScrPt?: { X: number; Y: number }; // nearst screen point on the ink stroke ""
+ @observable _nearestScrPt?: { X: number; Y: number } = { X: 0, Y: 0 }; // nearst screen point on the ink stroke ""
componentDidMount() {
this._props.setContentViewBox?.(this);
@@ -155,6 +160,7 @@ export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>()
const wasSelected = InkStrokeProperties.Instance._currentPoint === controlIndex;
const isEditing = InkStrokeProperties.Instance._controlButton && this._props.isSelected();
this.controlUndo = undefined;
+ this._nearestScrPt = undefined;
setupMoveUpEvents(
this,
e,
@@ -275,7 +281,7 @@ export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>()
.map(p => ({ X: p[0], Y: p[1] }));
const { distance, nearestT, nearestSeg, nearestPt } = InkStrokeProperties.nearestPtToStroke(screenPts, { X: e.clientX, Y: e.clientY });
- if (distance < 40) {
+ if (distance < 40 && !e.buttons) {
this._nearestT = nearestT;
this._nearestSeg = nearestSeg;
this._nearestScrPt = nearestPt;
@@ -427,7 +433,7 @@ export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>()
StrCast(this.layoutDoc.stroke_lineJoin) as Property.StrokeLinejoin,
StrCast(this.layoutDoc.stroke_lineCap) as Property.StrokeLinecap,
StrCast(this.layoutDoc.stroke_bezier),
- !closed || !fillColor || DashColor(fillColor).alpha() === 0 ? 'none' : fillColor,
+ 'none',
startMarker,
endMarker,
markerScale,
diff --git a/src/client/views/PropertiesView.scss b/src/client/views/PropertiesView.scss
index a5e60b831..693c75ebf 100644
--- a/src/client/views/PropertiesView.scss
+++ b/src/client/views/PropertiesView.scss
@@ -508,6 +508,7 @@
display: flex;
margin-bottom: 3px;
margin-left: 4px;
+ justify-content: space-evenly;
.arrows-head {
display: flex;
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index c539b1d0a..10c2a9898 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -3,6 +3,7 @@ import { faAnchor, faArrowRight, faWindowMaximize } from '@fortawesome/free-soli
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Checkbox, Tooltip } from '@mui/material';
import { Colors, EditableText, IconButton, NumberInput, Size, Slider, Toggle, ToggleType, Type } from 'browndash-components';
+import { Property } from 'csstype';
import { concat } from 'lodash';
import { IReactionDisposer, action, computed, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
@@ -830,11 +831,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@computed get shapeHgt() { return NumCast(this.selectedDoc?._height); } // prettier-ignore
set shapeHgt(value) { this.selectedDoc && (this.selectedDoc._height = Math.round(value * 100) / 100); } // prettier-ignore
@computed get strokeThk(){ return NumCast(this.selectedStrokes.lastElement()?.[DocData].stroke_width); } // prettier-ignore
- set strokeThk(value) {
- this.selectedStrokes.forEach(doc => {
- doc[DocData].stroke_width = Math.round(value * 100) / 100;
- });
- }
+ set strokeThk(value) { this.selectedStrokes.forEach(doc => { doc[DocData].stroke_width = Math.round(value * 100) / 100; }); } // prettier-ignore
@computed get hgtInput() {
return this.inputBoxDuo(
@@ -1025,7 +1022,13 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
doc[DocData].stroke_dash = value ? this._lastDash : undefined;
});
}
- @computed get widthStk() { return this.getField('stroke_width') || '1'; } // prettier-ignore
+ @computed get lineCapStk() { return (this.getField('stroke_lineCap') || 'round' ) as Property.StrokeLinecap; } // prettier-ignore
+ set lineCapStk(value) {
+ this.selectedStrokes.forEach(doc => {
+ doc[DocData].stroke_lineCap = value;
+ });
+ }
+ @computed get widthStk() { return this.getField('stroke') || '1'; } // prettier-ignore
set widthStk(value) {
this.selectedStrokes.forEach(doc => {
doc[DocData].stroke_width = Number(value);
@@ -1127,7 +1130,6 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
<div className="arrows-head">
<div className="arrows-head-title">Arrow Head: </div>
<input
- key="markHead"
className="arrows-head-input"
type="checkbox"
checked={this.markHead !== ''}
@@ -1137,16 +1139,25 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
<div className="arrows-tail">
<div className="arrows-tail-title">Arrow End: </div>
<input
- key="markTail"
className="arrows-tail-input"
type="checkbox"
checked={this.markTail !== ''}
- onChange={undoable(
- action(() => { this.markTail = this.markTail ? '' : 'arrow'; }) ,"change arrow tail"
- )}
+ onChange={undoable(action(() => { this.markTail = this.markTail ? '' : 'arrow'; }) ,"change arrow tail")}
/>
</div>
</div>
+ <div className="arrows">
+ {["butt", "round", "square"].map(cap =>
+ <div className="arrows-tail" key={cap}>
+ <div className="arrows-tail-title">{cap}</div>
+ <input
+ className="arrows-tail-input"
+ type="checkbox"
+ checked={this.lineCapStk === cap}
+ onChange={undoable(action(() => { this.lineCapStk = cap as Property.StrokeLinecap; }), `change lineCap ${cap}`)}
+ />
+ </div>)}
+ </div>
<div className="dashed">
<div className="dashed-title">Dashed Line:</div>
<input key="markHead" className="dashed-input" type="checkbox" checked={this.dashdStk === '2'} onChange={this.changeDash} />