diff options
| author | Bob Zeleznik <zzzman@gmail.com> | 2020-07-13 08:44:02 -0400 |
|---|---|---|
| committer | Bob Zeleznik <zzzman@gmail.com> | 2020-07-13 08:44:02 -0400 |
| commit | c5eee7d838acb6991d1e37e0160cf77f5fc6aa34 (patch) | |
| tree | 52b67af1bb2d63ae303b9ede9d77d3cb36b30094 /src/client/views/collections | |
| parent | 6f985b10f71ace2303b669d4e2a1165ff3a29eda (diff) | |
| parent | 40dbd220ef0170098bed4da8d6f3b2727190654e (diff) | |
Merge branch 'master' into acls_uv
Diffstat (limited to 'src/client/views/collections')
8 files changed, 678 insertions, 134 deletions
diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx index c370415be..dd4df20c9 100644 --- a/src/client/views/collections/CollectionLinearView.tsx +++ b/src/client/views/collections/CollectionLinearView.tsx @@ -16,6 +16,7 @@ import { Id } from '../../../fields/FieldSymbols'; import { DocumentLinksButton } from '../nodes/DocumentLinksButton'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { LinkDescriptionPopup } from '../nodes/LinkDescriptionPopup'; +import { Tooltip } from '@material-ui/core'; type LinearDocument = makeInterface<[typeof documentSchema,]>; @@ -110,17 +111,22 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { const flexDir: any = StrCast(this.Document.flexDirection); const backgroundColor = StrCast(this.props.Document.backgroundColor, "black"); const color = StrCast(this.props.Document.color, "white"); + + const menuOpener = <label htmlFor={`${guid}`} style={{ + background: backgroundColor === color ? "black" : backgroundColor, + // width: "18px", height: "18px", fontSize: "12.5px", + // transition: this.props.Document.linearViewIsExpanded ? "transform 0.2s" : "transform 0.5s", + // transform: this.props.Document.linearViewIsExpanded ? "" : "rotate(45deg)" + }} + onPointerDown={e => e.stopPropagation()} > + <p>+</p> + </label>; + return <div className="collectionLinearView-outer"> <div className="collectionLinearView" ref={this.createDashEventsTarget} > - <label htmlFor={`${guid}`} title="Close Menu" style={{ - background: backgroundColor === color ? "black" : backgroundColor, - // width: "18px", height: "18px", fontSize: "12.5px", - // transition: this.props.Document.linearViewIsExpanded ? "transform 0.2s" : "transform 0.5s", - // transform: this.props.Document.linearViewIsExpanded ? "" : "rotate(45deg)" - }} - onPointerDown={e => e.stopPropagation()} > - <p>+</p> - </label> + <Tooltip title={BoolCast(this.props.Document.linearViewIsExpanded) ? "Close menu" : "Open menu"} placement="top"> + {menuOpener} + </Tooltip> <input id={`${guid}`} type="checkbox" checked={BoolCast(this.props.Document.linearViewIsExpanded)} ref={this.addMenuToggle} onChange={action((e: any) => this.props.Document.linearViewIsExpanded = this.addMenuToggle.current!.checked)} /> @@ -171,11 +177,17 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { onPointerDown={e => e.stopPropagation()} > <span className="bottomPopup-text" > Creating link from: {DocumentLinksButton.StartLink.title} </span> - <span className="bottomPopup-descriptions" onClick={this.changeDescriptionSetting} - > Labels: {LinkDescriptionPopup.showDescriptions ? LinkDescriptionPopup.showDescriptions : "ON"} - </span> - <span className="bottomPopup-exit" onClick={this.exitLongLinks} - >Exit</span> + <Tooltip title={LinkDescriptionPopup.showDescriptions ? "Turn off description pop-up" : + "Turn on description pop-up"} placement="top"> + <span className="bottomPopup-descriptions" onClick={this.changeDescriptionSetting} + > Labels: {LinkDescriptionPopup.showDescriptions ? LinkDescriptionPopup.showDescriptions : "ON"} + </span> + </Tooltip> + + <Tooltip title="Exit link clicking mode" placement="top"> + <span className="bottomPopup-exit" onClick={this.exitLongLinks} + >Clear</span> + </Tooltip> {/* <FontAwesomeIcon icon="times-circle" size="lg" style={{ color: "red" }} onClick={this.exitLongLinks} /> */} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index a24693c30..ae79c27e0 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -110,10 +110,10 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo const pt2norm = [pt2vec[0] / pt2len * ptlen, pt2vec[1] / pt2len * ptlen]; const aActive = this.props.A.isSelected() || Doc.IsBrushed(this.props.A.props.Document); const bActive = this.props.A.isSelected() || Doc.IsBrushed(this.props.A.props.Document); - const text = StrCast(this.props.A.props.Document.linkRelationship); + const text = StrCast(this.props.A.props.Document.description); return !a.width || !b.width || ((!this.props.LinkDocs.length || !this.props.LinkDocs[0].linkDisplay) && !aActive && !bActive) ? (null) : (<> <text x={(Math.min(pt1[0], pt2[0]) * 2 + Math.max(pt1[0], pt2[0])) / 3} y={(pt1[1] + pt2[1]) / 2}> - {text !== "-ungrouped-" ? text : ""} + {text} </text> <path className="collectionfreeformlinkview-linkLine" style={{ opacity: this._opacity, strokeDasharray: "2 2" }} d={`M ${pt1[0]} ${pt1[1]} C ${pt1[0] + pt1norm[0]} ${pt1[1] + pt1norm[1]}, ${pt2[0] + pt2norm[0]} ${pt2[1] + pt2norm[1]}, ${pt2[0]} ${pt2[1]}`} /> diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index d9aabd7c2..ef6ea8f99 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -84,6 +84,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P private _lastY: number = 0; private _downX: number = 0; private _downY: number = 0; + private _lastClientY: number | undefined = 0; + private _lastClientX: number | undefined = 0; private _inkToTextStartX: number | undefined; private _inkToTextStartY: number | undefined; private _wordPalette: Map<string, string> = new Map<string, string>(); @@ -101,6 +103,10 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P @observable _clusterSets: (Doc[])[] = []; @observable _timelineRef = React.createRef<Timeline>(); + @observable _marqueeRef = React.createRef<HTMLDivElement>(); + @observable canPanX: boolean = true; + @observable canPanY: boolean = true; + @computed get fitToContentScaling() { return this.fitToContent ? NumCast(this.layoutDoc.fitToContentScaling, 1) : 1; } @computed get fitToContent() { return (this.props.fitToBox || this.Document._fitToBox) && !this.isAnnotationOverlay; } @computed get parentScaling() { return this.props.ContentScaling && this.fitToContent && !this.isAnnotationOverlay ? this.props.ContentScaling() : 1; } @@ -575,6 +581,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P @action onPointerUp = (e: PointerEvent): void => { + this._lastClientY = this._lastClientX = undefined; if (InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE)) return; document.removeEventListener("pointermove", this.onPointerMove); @@ -1027,7 +1034,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P const transform = `translate(${x}px, ${y}px)`; if (viewDef.type === "text") { const text = Cast(viewDef.text, "string"); // don't use NumCast, StrCast, etc since we want to test for undefined below - const fontSize = Cast(viewDef.fontSize, "number"); + const fontSize = Cast(viewDef.fontSize, "string"); return [text, x, y].some(val => val === undefined) ? undefined : { ele: <div className="collectionFreeform-customText" key={(text || "") + x + y + z + color} style={{ width, height, color, fontSize, transform }}> @@ -1143,10 +1150,19 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P this._layoutComputeReaction = reaction(() => this.doLayoutComputation, (elements) => this._layoutElements = elements || [], { fireImmediately: true, name: "doLayout" }); + + const handler = (e: Event) => this.handleDragging(e, (e as CustomEvent<DragEvent>).detail); + + document.addEventListener("dashDragging", handler); } + componentWillUnmount() { this._layoutComputeReaction?.(); + + const handler = (e: Event) => this.handleDragging(e, (e as CustomEvent<DragEvent>).detail); + document.removeEventListener("dashDragging", handler); } + @computed get views() { return this._layoutElements.filter(ele => ele.bounds && !ele.bounds.z).map(ele => ele.ele); } elementFunc = () => this._layoutElements; @@ -1155,6 +1171,43 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY)); } + + // <div ref={this._marqueeRef}> + + @action + handleDragging = (e: CustomEvent<React.DragEvent>, de: DragEvent) => { + if ((e as any).handlePan) return; + (e as any).handlePan = true; + this._lastClientY = e.detail.clientY; + this._lastClientX = e.detail.clientX; + + if (this._marqueeRef?.current) { + const dragX = e.detail.clientX; + const dragY = e.detail.clientY; + const bounds = this._marqueeRef.current?.getBoundingClientRect(); + + let deltaX = dragX - bounds.left < 25 ? -2 : bounds.right - dragX < 25 ? 2 : 0; + let deltaY = dragY - bounds.top < 25 ? -2 : bounds.bottom - dragY < 25 ? 2 : 0; + (deltaX !== 0 || deltaY !== 0) && this.continuePan(deltaX, deltaY); + } + e.stopPropagation(); + } + + continuePan = (deltaX: number, deltaY: number) => { + setTimeout(action(() => { + const dragY = this._lastClientY; + const dragX = this._lastClientX; + if (dragY !== undefined && dragX !== undefined && this._marqueeRef.current) { + const bounds = this._marqueeRef.current.getBoundingClientRect()!; + this.Document._panY = NumCast(this.Document._panY) + deltaY; + this.Document._panX = NumCast(this.Document._panX) + deltaX; + if (dragY - bounds.top < 25 || bounds.bottom - dragY < 25 || dragX - bounds.left < 25 || bounds.right - dragX < 25) { + this.continuePan(deltaX, deltaY); + } + } else this._lastClientY !== undefined && this._lastClientX !== undefined && this.continuePan(deltaX, deltaY); + }), 50); + } + promoteCollection = undoBatch(action(() => { const childDocs = this.childDocs.slice(); childDocs.forEach(doc => { @@ -1336,7 +1389,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P return false; }); @computed get marqueeView() { - return <MarqueeView {...this.props} + return <MarqueeView + {...this.props} nudge={this.nudge} addDocTab={this.addDocTab} activeDocuments={this.getActiveDocuments} @@ -1346,14 +1400,15 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P getContainerTransform={this.getContainerTransform} getTransform={this.getTransform} isAnnotationOverlay={this.isAnnotationOverlay}> - <CollectionFreeFormViewPannableContents - centeringShiftX={this.centeringShiftX} - centeringShiftY={this.centeringShiftY} - transition={Cast(this.layoutDoc._viewTransition, "string", null)} - viewDefDivClick={this.props.viewDefDivClick} - zoomScaling={this.zoomScaling} panX={this.panX} panY={this.panY}> - {this.children} - </CollectionFreeFormViewPannableContents> + <div ref={this._marqueeRef}> + <CollectionFreeFormViewPannableContents + centeringShiftX={this.centeringShiftX} + centeringShiftY={this.centeringShiftY} + transition={Cast(this.layoutDoc._viewTransition, "string", null)} + viewDefDivClick={this.props.viewDefDivClick} + zoomScaling={this.zoomScaling} panX={this.panX} panY={this.panY}> + {this.children} + </CollectionFreeFormViewPannableContents></div> {this.showTimeline ? <Timeline ref={this._timelineRef} {...this.props} /> : (null)} </MarqueeView>; } diff --git a/src/client/views/collections/collectionFreeForm/FormatShapePane.scss b/src/client/views/collections/collectionFreeForm/FormatShapePane.scss new file mode 100644 index 000000000..88876471c --- /dev/null +++ b/src/client/views/collections/collectionFreeForm/FormatShapePane.scss @@ -0,0 +1,64 @@ +.antimodeMenu-button { + width: 200px; + position: relative; + text-align: left; + + .color-previewI { + width: 100%; + height: 40%; + } + + .color-previewII { + width: 100%; + height: 100%; + } +} + +.antimenu-Buttonup { + position: absolute; + width: 20; + height: 10; + right: 0; + padding: 0; +} + +.formatShapePane-inputBtn { + width: inherit; + position: absolute; +} + +.sketch-picker { + background: #323232; + + .flexbox-fit { + background: #323232; + } +} + +.btn-group { + display: grid; + grid-template-columns: auto auto auto auto; + /* Make the buttons appear below each other */ +} + +.btn-group-palette { + display: block; + /* Make the buttons appear below each other */ +} + +.btn-draw { + display: inline; + /* Make the buttons appear below each other */ +} + +.btn2-group { + display: block; + background: #323232; + grid-template-columns: auto; + + /* Make the buttons appear below each other */ + .antimodeMenu-button { + background: #323232; + display: block; + } +}
\ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx new file mode 100644 index 000000000..56ba9e96a --- /dev/null +++ b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx @@ -0,0 +1,305 @@ +import React = require("react"); +import { IconProp } from '@fortawesome/fontawesome-svg-core'; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { action, computed, observable } from "mobx"; +import { observer } from "mobx-react"; +import { Doc, Field, Opt } from "../../../../fields/Doc"; +import { Document } from "../../../../fields/documentSchemas"; +import { InkField } from "../../../../fields/InkField"; +import { BoolCast, Cast, NumCast } from "../../../../fields/Types"; +import { DocumentType } from "../../../documents/DocumentTypes"; +import { SelectionManager } from "../../../util/SelectionManager"; +import AntimodeMenu from "../../AntimodeMenu"; +import "./FormatShapePane.scss"; + +@observer +export default class FormatShapePane extends AntimodeMenu { + static Instance: FormatShapePane; + + private _lastFill = "#D0021B"; + private _lastLine = "#D0021B"; + private _lastDash = "2"; + private _palette = ["#D0021B", "#F5A623", "#F8E71C", "#8B572A", "#7ED321", "#417505", "#9013FE", "#4A90E2", "#50E3C2", "#B8E986", "#000000", "#4A4A4A", "#9B9B9B", "#FFFFFF"]; + private _mode = ["fill-drip", "ruler-combined"]; + + @observable private _subOpen = [false, false, false, false]; + @observable private _currMode = "fill-drip"; + @observable private _lock = false; + @observable private _fillBtn = false; + @observable private _lineBtn = false; + + getField(key: string) { + return this.selectedInk?.reduce((p, i) => + (p === undefined || (p && p === i.rootDoc[key])) && i.rootDoc[key] !== "0" ? Field.toString(i.rootDoc[key] as Field) : "", undefined as Opt<string>) + } + + @computed get selectedInk() { + const inks = SelectionManager.SelectedDocuments().filter(i => Document(i.rootDoc).type === DocumentType.INK); + return inks.length ? inks : undefined; + } + @computed get unFilled() { return this.selectedInk?.reduce((p, i) => p && !i.rootDoc.fillColor ? true : false, true) || false; } + @computed get unStrokd() { return this.selectedInk?.reduce((p, i) => p && !i.rootDoc.color ? true : false, true) || false; } + @computed get solidFil() { return this.selectedInk?.reduce((p, i) => p && i.rootDoc.fillColor ? true : false, true) || false; } + @computed get solidStk() { return this.selectedInk?.reduce((p, i) => p && i.rootDoc.color && (!i.rootDoc.strokeDash || i.rootDoc.strokeDash === "0") ? true : false, true) || false; } + @computed get dashdStk() { return !this.unStrokd && this.getField("strokeDash") || ""; } + @computed get colorFil() { const ccol = this.getField("fillColor") || ""; ccol && (this._lastFill = ccol); return ccol; } + @computed get colorStk() { const ccol = this.getField("color") || ""; ccol && (this._lastLine = ccol); return ccol; } + @computed get widthStk() { return this.getField("strokeWidth") || "1"; } + @computed get markHead() { return this.getField("strokeStartMarker") || ""; } + @computed get markTail() { return this.getField("strokeEndMarker") || ""; } + @computed get shapeHgt() { return this.getField("_height"); } + @computed get shapeWid() { return this.getField("_width"); } + @computed get shapeXps() { return this.getField("x"); } + @computed get shapeYps() { return this.getField("y"); } + @computed get shapeRot() { return this.getField("rotation"); } + set unFilled(value) { this.colorFil = value ? "" : this._lastFill; } + set solidFil(value) { this.unFilled = !value; } + set colorFil(value) { value && (this._lastFill = value); this.selectedInk?.forEach(i => i.rootDoc.fillColor = value ? value : undefined); } + set colorStk(value) { value && (this._lastLine = value); this.selectedInk?.forEach(i => i.rootDoc.color = value ? value : undefined); } + set markHead(value) { this.selectedInk?.forEach(i => i.rootDoc.strokeStartMarker = value); } + set markTail(value) { this.selectedInk?.forEach(i => i.rootDoc.strokeEndMarker = value); } + set unStrokd(value) { this.colorStk = value ? "" : this._lastLine; } + set solidStk(value) { this.dashdStk = ""; this.unStrokd = !value; } + set dashdStk(value) { + value && (this._lastDash = value) && (this.unStrokd = false); + this.selectedInk?.forEach(i => i.rootDoc.strokeDash = value ? this._lastDash : undefined); + } + set shapeXps(value) { this.selectedInk?.forEach(i => i.rootDoc.x = Number(value)); } + set shapeYps(value) { this.selectedInk?.forEach(i => i.rootDoc.y = Number(value)); } + set shapeRot(value) { this.selectedInk?.forEach(i => i.rootDoc.rotation = Number(value)); } + set widthStk(value) { this.selectedInk?.forEach(i => i.rootDoc.strokeWidth = Number(value)); } + set shapeWid(value) { + this.selectedInk?.filter(i => i.rootDoc._width && i.rootDoc._height).forEach(i => { + const oldWidth = NumCast(i.rootDoc._width); + i.rootDoc._width = Number(value); + this._lock && (i.rootDoc._height = (i.rootDoc._width * NumCast(i.rootDoc._height)) / oldWidth); + }); + } + set shapeHgt(value) { + this.selectedInk?.filter(i => i.rootDoc._width && i.rootDoc._height).forEach(i => { + const oldHeight = NumCast(i.rootDoc._height); + i.rootDoc._height = Number(value); + this._lock && (i.rootDoc._width = (i.rootDoc._height * NumCast(i.rootDoc._width)) / oldHeight); + }); + } + + constructor(props: Readonly<{}>) { + super(props); + FormatShapePane.Instance = this; + this._canFade = false; + this.Pinned = BoolCast(Doc.UserDoc()["menuFormatShape-pinned"]); + } + + @action + closePane = () => { + this.fadeOut(false); + this.Pinned = false; + } + + @action + upDownButtons = (dirs: string, field: string) => { + switch (field) { + case "rot": this.rotate((dirs === "up" ? .1 : -.1)); break; + case "Xps": this.selectedInk?.forEach(i => i.rootDoc.x = NumCast(i.rootDoc.x) + (dirs === "up" ? 10 : -10)); break; + case "Yps": this.selectedInk?.forEach(i => i.rootDoc.y = NumCast(i.rootDoc.y) + (dirs === "up" ? 10 : -10)); break; + case "stk": this.selectedInk?.forEach(i => i.rootDoc.strokeWidth = NumCast(i.rootDoc.strokeWidth) + (dirs === "up" ? .1 : -.1)); break; + case "wid": this.selectedInk?.filter(i => i.rootDoc._width && i.rootDoc._height).forEach(i => { + const oldWidth = NumCast(i.rootDoc._width); + i.rootDoc._width = oldWidth + (dirs === "up" ? 10 : - 10); + this._lock && (i.rootDoc._height = (i.rootDoc._width / oldWidth * NumCast(i.rootDoc._height))); + }); + break; + case "hgt": this.selectedInk?.filter(i => i.rootDoc._width && i.rootDoc._height).forEach(i => { + const oldHeight = NumCast(i.rootDoc._height); + i.rootDoc._height = oldHeight + (dirs === "up" ? 10 : - 10); + this._lock && (i.rootDoc._width = (i.rootDoc._height / oldHeight * NumCast(i.rootDoc._width))); + }); + break; + } + } + + @action + rotate = (degrees: number) => { + this.selectedInk?.forEach(action(inkView => { + const doc = Document(inkView.rootDoc); + if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) { + const angle = Number(degrees) - Number(doc.rotation); + doc.rotation = Number(degrees); + const ink = Cast(doc.data, InkField)?.inkData; + if (ink) { + const xs = ink.map(p => p.X); + const ys = ink.map(p => p.Y); + const left = Math.min(...xs); + const top = Math.min(...ys); + const right = Math.max(...xs); + const bottom = Math.max(...ys); + const _centerPoints: { X: number, Y: number }[] = []; + _centerPoints.push({ X: left, Y: top }); + + const newPoints: { X: number, Y: number }[] = []; + for (var i = 0; i < ink.length; i++) { + const newX = Math.cos(angle) * (ink[i].X - _centerPoints[0].X) - Math.sin(angle) * (ink[i].Y - _centerPoints[0].Y) + _centerPoints[0].X; + const newY = Math.sin(angle) * (ink[i].X - _centerPoints[0].X) + Math.cos(angle) * (ink[i].Y - _centerPoints[0].Y) + _centerPoints[0].Y; + newPoints.push({ X: newX, Y: newY }); + } + doc.data = new InkField(newPoints); + const xs2 = newPoints.map(p => p.X); + const ys2 = newPoints.map(p => p.Y); + const left2 = Math.min(...xs2); + const top2 = Math.min(...ys2); + const right2 = Math.max(...xs2); + const bottom2 = Math.max(...ys2); + doc._height = (bottom2 - top2) * inkView.props.ScreenToLocalTransform().Scale; + doc._width = (right2 - left2) * inkView.props.ScreenToLocalTransform().Scale; + } + } + })); + } + + + colorPicker(setter: (color: string) => {}) { + return <div className="btn-group-palette" key="colorpicker" > + {this._palette.map(color => + <button className="antimodeMenu-button" key={color} onPointerDown={action(() => setter(color))} style={{ zIndex: 1001, position: "relative" }}> + <div className="color-previewII" style={{ backgroundColor: color }} /> + </button>)} + </div>; + } + inputBox = (key: string, value: any, setter: (val: string) => {}) => { + return <> + <input style={{ color: "black", width: 80, position: "absolute", right: 20 }} + type="text" value={value} + onChange={e => setter(e.target.value)} + autoFocus /> + <button className="antiMenu-Buttonup" key="up" onPointerDown={action(() => this.upDownButtons("up", key))}> + ˄ + </button> + <br /> + <button className="antiMenu-Buttonup" key="down" onPointerDown={action(() => this.upDownButtons("down", key))} style={{ marginTop: -8 }}> + ˅ + </button> + </>; + } + + colorButton(value: string, setter: () => {}) { + return <> + <button className="antimodeMenu-button" key="fill" onPointerDown={action(e => setter())} style={{ position: "absolute", right: 80 }}> + <FontAwesomeIcon icon="fill-drip" size="lg" /> + <div className="color-previewI" style={{ backgroundColor: value ?? "121212" }} /> + </button> + <br /> <br /> + </>; + } + + @computed get fillButton() { return this.colorButton(this.colorFil, () => this._fillBtn = !this._fillBtn); } + @computed get lineButton() { return this.colorButton(this.colorStk, () => this._lineBtn = !this._lineBtn); } + + @computed get fillPicker() { return this.colorPicker((color: string) => this.colorFil = color); } + @computed get linePicker() { return this.colorPicker((color: string) => this.colorStk = color); } + + @computed get stkInput() { return this.inputBox("stk", this.widthStk, (val: string) => this.widthStk = val); } + @computed get hgtInput() { return this.inputBox("hgt", this.shapeHgt, (val: string) => this.shapeHgt = val); } + @computed get widInput() { return this.inputBox("wid", this.shapeWid, (val: string) => this.shapeWid = val); } + @computed get rotInput() { return this.inputBox("rot", this.shapeRot, (val: string) => this.shapeRot = val); } + @computed get XpsInput() { return this.inputBox("Xps", this.shapeXps, (val: string) => this.shapeXps = val); } + @computed get YpsInput() { return this.inputBox("Yps", this.shapeYps, (val: string) => this.shapeYps = val); } + + @computed get propertyGroupItems() { + const fillCheck = <div key="fill" style={{ display: this._subOpen[0] ? "" : "none", width: "inherit", backgroundColor: "#323232", color: "white", }}> + <input className="formatShapePane-inputBtn" type="radio" checked={this.unFilled} onChange={action(() => this.unFilled = true)} /> + No Fill + <br /> + <input className="formatShapePane-inputBtn" type="radio" checked={this.solidFil} onChange={action(() => this.solidFil = true)} /> + Solid Fill + <br /> <br /> + {this.solidFil ? "Color" : ""} + {this.solidFil ? this.fillButton : ""} + {this._fillBtn && this.solidFil ? this.fillPicker : ""} + </div>; + + const markers = <> + <input key="markHead" className="formatShapePane-inputBtn" type="checkbox" checked={this.markHead !== ""} onChange={action(() => this.markHead = this.markHead ? "" : "arrow")} /> + Arrow Head + <br /> + <input key="markTail" className="formatShapePane-inputBtn" type="checkbox" checked={this.markTail !== ""} onChange={action(() => this.markTail = this.markTail ? "" : "arrow")} /> + Arrow End + <br /> + </>; + + const lineCheck = <div key="lineCheck" style={{ display: this._subOpen[1] ? "" : "none", width: "inherit", backgroundColor: "#323232", color: "white", }}> + <input className="formatShapePane-inputBtn" type="radio" checked={this.unStrokd} onChange={action(() => this.unStrokd = true)} /> + No Line + <br /> + <input className="formatShapePane-inputBtn" type="radio" checked={this.solidStk} onChange={action(() => this.solidStk = true)} /> + Solid Line + <br /> + <input className="formatShapePane-inputBtn" type="radio" checked={this.dashdStk ? true : false} onChange={action(() => this.dashdStk = "2")} /> + Dash Line + <br /> + <br /> + {(this.solidStk || this.dashdStk) ? "Color" : ""} + {(this.solidStk || this.dashdStk) ? this.lineButton : ""} + {(this.solidStk || this.dashdStk) && this._lineBtn ? this.linePicker : ""} + <br /> + {(this.solidStk || this.dashdStk) ? "Width" : ""} + {(this.solidStk || this.dashdStk) ? this.stkInput : ""} + {(this.solidStk || this.dashdStk) ? <input type="range" defaultValue={Number(this.widthStk)} min={1} max={100} onChange={e => this.widthStk = e.target.value} /> : (null)} + <br /> <br /> + {(this.solidStk || this.dashdStk) ? markers : ""} + </div>; + + const sizeCheck = <div key="sizeCheck" style={{ display: this._subOpen[2] ? "" : "none", width: "inherit", backgroundColor: "#323232", color: "white", }}> + Height {this.hgtInput} + <br /> <br /> + Width {this.widInput} + <br /> <br /> + <input className="formatShapePane-inputBtn" style={{ right: 0 }} type="checkbox" checked={this._lock} onChange={action(() => this._lock = !this._lock)} /> + Lock Ratio + <br /> <br /> + Rotation {this.rotInput} + <br /> <br /> + </div>; + + const positionCheck = <div key="posCheck" style={{ display: this._subOpen[3] ? "" : "none", width: "inherit", backgroundColor: "#323232", color: "white", }}> + Horizontal {this.XpsInput} + <br /> <br /> + Vertical {this.YpsInput} + <br /> <br /> + </div>; + + const subMenus = this._currMode === "fill-drip" ? [`fill`, `line`] : [`size`, `position`]; + const menuItems = this._currMode === "fill-drip" ? [fillCheck, lineCheck] : [sizeCheck, positionCheck]; + const indexOffset = this._currMode === "fill-drip" ? 0 : 2; + return <div className="antimodeMenu-sub" key="submenu" style={{ position: "absolute", width: "inherit", top: 60 }}> + {subMenus.map((subMenu, i) => + <div key={subMenu} style={{ width: "inherit" }}> + <button className="antimodeMenu-button" onPointerDown={action(() => this._subOpen[i + indexOffset] = !this._subOpen[i + indexOffset])} + style={{ backgroundColor: "121212", position: "relative", width: "inherit" }}> + {this._subOpen[i + indexOffset] ? "▼" : "▶︎"} + {subMenu} + </button> + {menuItems[i]} + </div>)} + </div>; + } + + @computed get closeBtn() { + return <button className="antimodeMenu-button" key="close" onPointerDown={action(() => this.closePane())} style={{ position: "absolute", right: 0 }}> + X + </button>; + } + + @computed get propertyGroupBtn() { + return <div className="antimodeMenu-button-tab" key="modes"> + {this._mode.map(mode => + <button className="antimodeMenu-button" key={mode} onPointerDown={action(() => this._currMode = mode)} + style={{ backgroundColor: this._currMode === mode ? "121212" : "", position: "relative", top: 30 }}> + <FontAwesomeIcon icon={mode as IconProp} size="lg" /> + </button>)} + </div>; + } + + render() { + return this.getElementVert([this.closeBtn, this.propertyGroupBtn, this.propertyGroupItems]); + } +}
\ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.scss b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.scss index 753de6bef..03c6c97ab 100644 --- a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.scss +++ b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.scss @@ -25,8 +25,13 @@ /* Make the buttons appear below each other */ } +.btn-draw { + display: inline; + /* Make the buttons appear below each other */ +} + .btn2-group { - display: block; + display: grid; background: #323232; grid-template-columns: auto; diff --git a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx index f47fca6ac..15707ad9e 100644 --- a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx +++ b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx @@ -17,6 +17,8 @@ import { DocumentType } from "../../../documents/DocumentTypes"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { IconProp, library } from '@fortawesome/fontawesome-svg-core'; import { faBold, faItalic, faChevronLeft, faUnderline, faStrikethrough, faSubscript, faSuperscript, faIndent, faEyeDropper, faCaretDown, faPalette, faArrowsAlt, faHighlighter, faLink, faPaintRoller, faSleigh, faBars, faFillDrip, faBrush, faPenNib, faShapes, faArrowLeft, faEllipsisH, faBezierCurve, } from "@fortawesome/free-solid-svg-icons"; +import { Cast, StrCast, BoolCast } from "../../../../fields/Types"; +import FormatShapePane from "./FormatShapePane"; library.add(faBold, faItalic, faChevronLeft, faUnderline, faStrikethrough, faSuperscript, faSubscript, faIndent, faEyeDropper, faCaretDown, faPalette, faArrowsAlt, faHighlighter, faLink, faPaintRoller, faBars, faFillDrip, faBrush, faPenNib, faShapes, faArrowLeft, faEllipsisH, faBezierCurve); @@ -26,23 +28,33 @@ library.add(faBold, faItalic, faChevronLeft, faUnderline, faStrikethrough, faSup export default class InkOptionsMenu extends AntimodeMenu { static Instance: InkOptionsMenu; - private _palette = ["#D0021B", "#F5A623", "#F8E71C", "#8B572A", "#7ED321", "#417505", "#9013FE", "#4A90E2", "#50E3C2", "#B8E986", "#000000", "#4A4A4A", "#9B9B9B", "#FFFFFF", "none"]; + private _palette = ["#D0021B", "#F5A623", "#F8E71C", "#8B572A", "#7ED321", "#417505", "#9013FE", "#4A90E2", "#50E3C2", "#B8E986", "#000000", "#4A4A4A", "#9B9B9B", "#FFFFFF", ""]; private _width = ["1", "5", "10", "100"]; // private _buttons = ["circle", "triangle", "rectangle", "arrow", "line"]; // private _icons = ["O", "∆", "ロ", "➜", "-"]; - private _buttons = ["circle", "triangle", "rectangle", "line", "noRec", "",]; - private _icons = ["O", "∆", "ロ", "⎯", "✖︎", " "]; + // private _buttons = ["circle", "triangle", "rectangle", "line", "noRec", "",]; + // private _icons = ["O", "∆", "ロ", "⎯⎯⎯", "✖︎", " "]; //arrowStart and arrowEnd must match and defs must exist in Inking Stroke - private _arrowStart = ["arrowHead", "arrowHead", "dot", "dot", "none"]; - private _arrowEnd = ["none", "arrowEnd", "none", "dot", "none"]; - private _arrowIcons = ["→", "↔︎", "•", "••", " "]; + // private _arrowStart = ["arrowStart", "arrowStart", "dot", "dot", "none"]; + // private _arrowEnd = ["none", "arrowEnd", "none", "dot", "none"]; + // private _arrowIcons = ["→", "↔︎", "•", "••", " "]; + private _draw = ["⎯", "→", "↔︎", "∿", "↝", "↭", "ロ", "O", "∆"]; + private _head = ["", "", "arrow", "", "", "arrow", "", "", ""]; + private _end = ["", "arrow", "arrow", "", "arrow", "arrow", "", "", ""]; + private _shape = ["line", "line", "line", "", "", "", "rectangle", "circle", "triangle"]; + + @observable _shapesNum = this._shape.length; + @observable _selected = this._shapesNum; + + @observable private collapsed: boolean = false; + @observable _double = ""; @observable _colorBtn = false; @observable _widthBtn = false; @observable _fillBtn = false; - @observable _arrowBtn = false; - @observable _dashBtn = false; - @observable _shapeBtn = false; + // @observable _arrowBtn = false; + // @observable _dashBtn = false; + // @observable _shapeBtn = false; @@ -50,18 +62,40 @@ export default class InkOptionsMenu extends AntimodeMenu { super(props); InkOptionsMenu.Instance = this; this._canFade = false; // don't let the inking menu fade away + this.Pinned = BoolCast(Doc.UserDoc()["menuInkOptions-pinned"]); + } - getColors = () => { - return this._palette; + @action + toggleMenuPin = (e: React.MouseEvent) => { + Doc.UserDoc()["menuInkOptions-pinned"] = this.Pinned = !this.Pinned; + if (!this.Pinned) { + // this.fadeOut(true); + } } @action - changeArrow = (arrowStart: string, arrowEnd: string) => { - SetActiveArrowStart(arrowStart); - SetActiveArrowEnd(arrowEnd); + protected toggleCollapse = (e: React.MouseEvent) => { + this.collapsed = !this.collapsed; + setTimeout(() => { + const x = Math.min(this._left, window.innerWidth - InkOptionsMenu.Instance.width); + InkOptionsMenu.Instance.jumpTo(x, this._top, true); + }, 0); + } + + + + + getColors = () => { + return this._palette; } + // @action + // changeArrow = (arrowStart: string, arrowEnd: string) => { + // SetActiveArrowStart(arrowStart); + // SetActiveArrowEnd(arrowEnd); + // } + @action changeColor = (color: string, type: string) => { const col: ColorState = { @@ -93,14 +127,8 @@ export default class InkOptionsMenu extends AntimodeMenu { case "bezier": // doc.strokeBezier === 300 ? doc.strokeBezier = 0 : doc.strokeBezier = 300; break; - case "arrowStart": - doc.arrowStart = String(value); - break; - case "arrowEnd": - doc.arrowEnd = String(value); - break; case "dash": - doc.dash = Number(value); + doc.strokeDash = Number(value); default: break; } @@ -117,43 +145,103 @@ export default class InkOptionsMenu extends AntimodeMenu { @action changeDash = (e: React.PointerEvent): void => { SetActiveDash(ActiveDash() === "0" ? "2" : "0"); - this.editProperties(ActiveDash(), "dash"); + this.editProperties(ActiveDash(), "strokeDash"); } - @computed get arrowPicker() { - var currIcon; - for (var i = 0; i < this._arrowStart.length; i++) { - if (this._arrowStart[i] === ActiveArrowStart() && this._arrowEnd[i] === ActiveArrowEnd()) { - currIcon = this._arrowIcons[i]; - if (this._arrowIcons[i] === " ") { - currIcon = "➤"; - } - } - } - var arrowPicker = <button - className="antimodeMenu-button" - key="arrow" - onPointerDown={action(e => this._arrowBtn = !this._arrowBtn)} - style={{ backgroundColor: this._arrowBtn ? "121212" : "" }}> - {currIcon} - </button>; - if (this._arrowBtn) { - arrowPicker = <div className="btn2-group" key="arrows"> - {arrowPicker} - {this._arrowStart.map((arrowStart, i) => { - return <button - className="antimodeMenu-button" - key={arrowStart} - onPointerDown={action(() => { SetActiveArrowStart(arrowStart); SetActiveArrowEnd(this._arrowEnd[i]); this.editProperties(arrowStart, "arrowStart"), this.editProperties(this._arrowEnd[i], "arrowEnd"); this._arrowBtn = false; })} - style={{ backgroundColor: this._arrowBtn ? "121212" : "" }}> - {this._arrowIcons[i]} - </button>; - })} - </div>; - } - return arrowPicker; + @computed get drawButtons() { + const drawButtons = <div className="btn-draw" key="draw"> + {this._draw.map((icon, i) => { + return <button + className="antimodeMenu-button" + key={icon} + onPointerDown={action(() => { + this._double = ""; + + if (this._selected !== i) { + this._selected = i; + Doc.SetSelectedTool(InkTool.Pen); + SetActiveArrowStart(this._head[i]); + SetActiveArrowEnd(this._end[i]); + SetActiveBezierApprox("300"); + + GestureOverlay.Instance.InkShape = this._shape[i]; + } else { + this._selected = this._shapesNum; + Doc.SetSelectedTool(InkTool.None); + SetActiveArrowStart(""); + SetActiveArrowEnd(""); + GestureOverlay.Instance.InkShape = ""; + SetActiveBezierApprox("0"); + + } + console.log(this._selected); + + })} + onDoubleClick={action(() => { + console.log("double"); + this._double = this._draw[i]; + if (this._selected !== i) { + this._selected = i; + Doc.SetSelectedTool(InkTool.Pen); + SetActiveArrowStart(this._head[i]); + SetActiveArrowEnd(this._end[i]); + SetActiveBezierApprox("300"); + + GestureOverlay.Instance.InkShape = this._shape[i]; + } else { + this._selected = this._shapesNum; + Doc.SetSelectedTool(InkTool.None); + SetActiveArrowStart(""); + SetActiveArrowEnd(""); + GestureOverlay.Instance.InkShape = ""; + SetActiveBezierApprox("0"); + + } + + + + })} + style={{ backgroundColor: i === this._selected ? "121212" : "", fontSize: "20" }}> + {this._draw[i]} + </button>; + })}</div>; + return drawButtons; } + // @computed get arrowPicker() { + // var currIcon; + // for (var i = 0; i < this._arrowStart.length; i++) { + // if (this._arrowStart[i] === ActiveArrowStart() && this._arrowEnd[i] === ActiveArrowEnd()) { + // currIcon = this._arrowIcons[i]; + // if (this._arrowIcons[i] === " ") { + // currIcon = "➤"; + // } + // } + // } + // var arrowPicker = <button + // className="antimodeMenu-button" + // key="arrow" + // onPointerDown={action(e => this._arrowBtn = !this._arrowBtn)} + // style={{ backgroundColor: this._arrowBtn ? "121212" : "" }}> + // {currIcon} + // </button>; + // if (this._arrowBtn) { + // arrowPicker = <div className="btn2-group" key="arrows"> + // {arrowPicker} + // {this._arrowStart.map((arrowStart, i) => { + // return <button + // className="antimodeMenu-button" + // key={arrowStart} + // onPointerDown={action(() => { SetActiveArrowStart(arrowStart); SetActiveArrowEnd(this._arrowEnd[i]); this.editProperties(arrowStart, "arrowStart"), this.editProperties(this._arrowEnd[i], "arrowEnd"); this._arrowBtn = false; })} + // style={{ backgroundColor: this._arrowBtn ? "121212" : "" }}> + // {this._arrowIcons[i]} + // </button>; + // })} + // </div>; + // } + // return arrowPicker; + // } + @computed get widthPicker() { var widthPicker = <button className="antimodeMenu-button" @@ -170,7 +258,7 @@ export default class InkOptionsMenu extends AntimodeMenu { className="antimodeMenu-button" key={wid} onPointerDown={action(() => { SetActiveInkWidth(wid); this._widthBtn = false; this.editProperties(wid, "width"); })} - style={{ backgroundColor: this._widthBtn ? "121212" : "" }}> + style={{ backgroundColor: this._widthBtn ? "121212" : "", zIndex: 1001 }}> {wid} </button>; })} @@ -200,7 +288,7 @@ export default class InkOptionsMenu extends AntimodeMenu { className="antimodeMenu-button" key={color} onPointerDown={action(() => { this.changeColor(color, "color"); this._colorBtn = false; this.editProperties(color, "color"); })} - style={{ backgroundColor: this._colorBtn ? "121212" : "" }}> + style={{ backgroundColor: this._colorBtn ? "121212" : "", zIndex: 1001 }}> {/* <FontAwesomeIcon icon="pen-nib" size="lg" /> */} <div className="color-previewII" style={{ backgroundColor: color }}></div> </button>; @@ -209,6 +297,14 @@ export default class InkOptionsMenu extends AntimodeMenu { } return colorPicker; } + @computed get formatPane() { + return <button className="antimodeMenu-button" key="format" + title="toggle foramatting pane" + onPointerDown={action(e => FormatShapePane.Instance.Pinned = !FormatShapePane.Instance.Pinned)} + style={{ backgroundColor: this._fillBtn ? "121212" : "" }}> + <FontAwesomeIcon icon="chevron-right" size="lg" /> + </button>; + } @computed get fillPicker() { var fillPicker = <button @@ -221,14 +317,14 @@ export default class InkOptionsMenu extends AntimodeMenu { <div className="color-previewI" style={{ backgroundColor: ActiveFillColor() ?? "121212" }}></div> </button>; if (this._fillBtn) { - fillPicker = <div className="btn-group" key="fill"> + fillPicker = <div className="btn-group" key="fill" > {fillPicker} {this._palette.map(color => { return <button className="antimodeMenu-button" key={color} onPointerDown={action(() => { this.changeColor(color, "fill"); this._fillBtn = false; this.editProperties(color, "fill"); })} - style={{ backgroundColor: this._fillBtn ? "121212" : "" }}> + style={{ backgroundColor: this._fillBtn ? "121212" : "", zIndex: 1001 }}> <div className="color-previewII" style={{ backgroundColor: color }}></div> </button>; })} @@ -238,48 +334,48 @@ export default class InkOptionsMenu extends AntimodeMenu { return fillPicker; } - @computed get shapePicker() { - var currIcon; - if (GestureOverlay.Instance.InkShape === "") { - currIcon = <FontAwesomeIcon icon="shapes" size="lg" />; - } else { - for (var i = 0; i < this._icons.length; i++) { - if (GestureOverlay.Instance.InkShape === this._buttons[i]) { - currIcon = this._icons[i]; - } - } - } - var shapePicker = <button - className="antimodeMenu-button" - key="shape" - onPointerDown={action(e => this._shapeBtn = !this._shapeBtn)} - style={{ backgroundColor: this._shapeBtn ? "121212" : "" }}> - {currIcon} - </button>; - if (this._shapeBtn) { - shapePicker = <div className="btn2-group" key="shape"> - {shapePicker} - {this._buttons.map((btn, i) => { - var ttl = btn; - if (btn === "") { - ttl = "no shape"; - } - if (btn === "noRec") { - ttl = "disable shape recognition"; - } - return <button - className="antimodeMenu-button" - title={`Draw ${btn}`} - key={ttl} - onPointerDown={action((e) => { GestureOverlay.Instance.InkShape = btn; this._shapeBtn = false; })} - style={{ backgroundColor: this._shapeBtn ? "121212" : "" }}> - {this._icons[i]} - </button>; - })} - </div>; - } - return shapePicker; - } + // @computed get shapePicker() { + // var currIcon; + // if (GestureOverlay.Instance.InkShape === "") { + // currIcon = <FontAwesomeIcon icon="shapes" size="lg" />; + // } else { + // for (var i = 0; i < this._icons.length; i++) { + // if (GestureOverlay.Instance.InkShape === this._buttons[i]) { + // currIcon = this._icons[i]; + // } + // } + // } + // var shapePicker = <button + // className="antimodeMenu-button" + // key="shape" + // onPointerDown={action(e => this._shapeBtn = !this._shapeBtn)} + // style={{ backgroundColor: this._shapeBtn ? "121212" : "" }}> + // {currIcon} + // </button>; + // if (this._shapeBtn) { + // shapePicker = <div className="btn2-group" key="shape"> + // {shapePicker} + // {this._buttons.map((btn, i) => { + // var ttl = btn; + // if (btn === "") { + // ttl = "no shape"; + // } + // if (btn === "noRec") { + // ttl = "disable shape recognition"; + // } + // return <button + // className="antimodeMenu-button" + // title={`Draw ${btn}`} + // key={ttl} + // onPointerDown={action((e) => { GestureOverlay.Instance.InkShape = btn; this._shapeBtn = false; })} + // style={{ backgroundColor: this._shapeBtn ? "121212" : "", fontSize: "20" }}> + // {this._icons[i]} + // </button>; + // })} + // </div>; + // } + // return shapePicker; + // } @computed get bezierButton() { return <button @@ -310,23 +406,30 @@ export default class InkOptionsMenu extends AntimodeMenu { // <button className="antimodeMenu-button" title="Drag" key="drag" onPointerDown={e => this.dragStart(e)}> // <FontAwesomeIcon icon="arrows-alt" size="lg" /> // </button>, - this.shapePicker, - this.bezierButton, + // this.shapePicker, + // this.bezierButton, this.widthPicker, this.colorPicker, this.fillPicker, - this.arrowPicker, - this.dashButton, + this.drawButtons, + this.formatPane, + // this.arrowPicker, + // this.dashButton, + <button className="antimodeMenu-button" key="pin menu" title="Pin menu" onClick={this.toggleMenuPin} style={{ backgroundColor: this.Pinned ? "#121212" : "", display: this.collapsed ? "none" : undefined }}> + <FontAwesomeIcon icon="thumbtack" size="lg" style={{ transitionProperty: "transform", transitionDuration: "0.1s", transform: `rotate(${this.Pinned ? 45 : 0}deg)` }} /> + </button> ]; + + // return this.getElement(buttons); return this.getElement(buttons); } } Scripting.addGlobal(function activatePen(penBtn: any) { if (penBtn) { - Doc.SetSelectedTool(InkTool.Pen); InkOptionsMenu.Instance.jumpTo(300, 300); + InkOptionsMenu.Instance.Pinned = true; } else { - Doc.SetSelectedTool(InkTool.None); + InkOptionsMenu.Instance.Pinned = false; InkOptionsMenu.Instance.fadeOut(true); } }); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 8ce2dc9a4..8aab2e6a5 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -130,7 +130,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque } else if (!e.ctrlKey && !e.metaKey) { FormattedTextBox.SelectOnLoadChar = FormattedTextBox.DefaultLayout ? e.key : ""; const tbox = Docs.Create.TextDocument("", { - _width: 200, _height: 100, x: x, y: y, _autoHeight: true, _fontSize: NumCast(Doc.UserDoc().fontSize), + _width: 200, _height: 100, x: x, y: y, _autoHeight: true, _fontSize: StrCast(Doc.UserDoc().fontSize), _fontFamily: StrCast(Doc.UserDoc().fontFamily), title: "-typed text-" }); |
