aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/collectionFreeForm
diff options
context:
space:
mode:
authorGeireann Lindfield Roberts <60007097+geireann@users.noreply.github.com>2020-07-30 21:14:34 +0800
committerGeireann Lindfield Roberts <60007097+geireann@users.noreply.github.com>2020-07-30 21:14:34 +0800
commit02bd861e780c650367c6caf1dfe85b16e03c318b (patch)
treee5a08e23721dbbac729c7b32d64d60c569aa0bf3 /src/client/views/collections/collectionFreeForm
parentb1a7c8c965ff93eca4c002f51cf67df4b8ad21ba (diff)
parentc25e942ea7b015ef163ebb772c268479cc976234 (diff)
Merge branch 'master' into presentation_updates
Diffstat (limited to 'src/client/views/collections/collectionFreeForm')
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx40
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx11
-rw-r--r--src/client/views/collections/collectionFreeForm/FormatShapePane.scss4
-rw-r--r--src/client/views/collections/collectionFreeForm/FormatShapePane.tsx376
4 files changed, 292 insertions, 139 deletions
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
index a4fd5384f..b00074cc6 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
@@ -142,9 +142,16 @@ export function computePivotLayout(
const fieldKey = "data";
const pivotColumnGroups = new Map<FieldResult<Field>, PivotColumn>();
+ let nonNumbers = 0;
const pivotFieldKey = toLabel(pivotDoc._pivotField);
childPairs.map(pair => {
- const lval = Cast(pair.layout[pivotFieldKey], listSpec("string"), null);
+ const lval = pivotFieldKey === "#" ? Array.from(Object.keys(Doc.GetProto(pair.layout))).filter(k => k.startsWith("#")).map(k => k.substring(1)) :
+ Cast(pair.layout[pivotFieldKey], listSpec("string"), null);
+
+ const num = toNumber(pair.layout[pivotFieldKey]);
+ if (num === undefined || Number.isNaN(num)) {
+ nonNumbers++;
+ }
const val = Field.toString(pair.layout[pivotFieldKey] as Field);
if (lval) {
lval.forEach((val, i) => {
@@ -168,13 +175,6 @@ export function computePivotLayout(
});
}
});
- let nonNumbers = 0;
- childPairs.map(pair => {
- const num = toNumber(pair.layout[pivotFieldKey]);
- if (num === undefined || Number.isNaN(num)) {
- nonNumbers++;
- }
- });
const pivotNumbers = nonNumbers / childPairs.length < .1;
if (pivotColumnGroups.size > 10) {
const arrayofKeys = Array.from(pivotColumnGroups.keys());
@@ -434,27 +434,3 @@ function normalizeResults(
payload: gname.payload
})));
}
-
-export function AddCustomFreeFormLayout(doc: Doc, dataKey: string): () => void {
- return () => {
- const addOverlay = (key: "arrangeScript" | "arrangeInit", options: OverlayElementOptions, params?: Record<string, string>, requiredType?: string) => {
- let overlayDisposer: () => void = emptyFunction; // filled in below after we have a reference to the scriptingBox
- const scriptField = Cast(doc[key], ScriptField);
- const scriptingBox = <ScriptBox initialText={scriptField && scriptField.script.originalScript}
- // tslint:disable-next-line: no-unnecessary-callback-wrapper
- onCancel={() => overlayDisposer()} // don't get rid of the function wrapper-- we don't want to use the current value of overlayDiposer, but the one set below
- onSave={(text, onError) => {
- const script = CompileScript(text, { params, requiredType, typecheck: false });
- if (!script.compiled) {
- onError(script.errors.map(error => error.messageText).join("\n"));
- } else {
- doc[key] = new ScriptField(script);
- overlayDisposer();
- }
- }} />;
- overlayDisposer = OverlayView.Instance.addWindow(scriptingBox, options);
- };
- addOverlay("arrangeInit", { x: 400, y: 100, width: 400, height: 300, title: "Layout Initialization" }, { collection: "Doc", docs: "Doc[]" }, undefined);
- addOverlay("arrangeScript", { x: 400, y: 500, width: 400, height: 300, title: "Layout Script" }, { doc: "Doc", index: "number", collection: "Doc", state: "any", docs: "Doc[]" }, "{x: number, y: number, width?: number, height?: number}");
- };
-}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 79540d19e..151acb64d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -58,7 +58,6 @@ export const panZoomSchema = createSchema({
currentTimecode: "number",
displayTimecode: "number",
currentFrame: "number",
- arrangeScript: ScriptField,
arrangeInit: ScriptField,
useClusters: "boolean",
fitToBox: "boolean",
@@ -892,7 +891,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
this.props.focus(doc);
} else {
const contextHgt = Doc.AreProtosEqual(annotOn, this.props.Document) && this.props.VisibleHeight ? this.props.VisibleHeight() : NumCast(annotOn._height);
- const offset = annotOn && (contextHgt / 2 * 96 / 72);
+ const offset = annotOn && (contextHgt / 2);
this.props.Document._scrollY = NumCast(doc.y) - offset;
}
@@ -1006,10 +1005,6 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
return this.props.addDocTab(doc, where);
});
getCalculatedPositions(params: { pair: { layout: Doc, data?: Doc }, index: number, collection: Doc, docs: Doc[], state: any }): PoolData {
- const result = this.Document.arrangeScript?.script.run(params, console.log);
- if (result?.success) {
- return { x: 0, y: 0, transition: "transform 1s", ...result, pair: params.pair, replica: "" };
- }
const layoutDoc = Doc.Layout(params.pair.layout);
const { x, y, opacity } = this.Document.currentFrame === undefined ? params.pair.layout :
CollectionFreeFormDocumentView.getValues(params.pair.layout, this.Document.currentFrame || 0);
@@ -1248,11 +1243,11 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
appearanceItems.push({ description: "Arrange contents in grid", event: this.layoutDocsInGrid, icon: "table" });
!appearance && ContextMenu.Instance.addItem({ description: "Appearance...", subitems: appearanceItems, icon: "eye" });
- const viewctrls = ContextMenu.Instance.findByDescription("View Controls...");
+ const viewctrls = ContextMenu.Instance.findByDescription("UI Controls...");
const viewCtrlItems = viewctrls && "subitems" in viewctrls ? viewctrls.subitems : [];
viewCtrlItems.push({ description: (Doc.UserDoc().showSnapLines ? "Hide" : "Show") + " Snap Lines", event: () => Doc.UserDoc().showSnapLines = !Doc.UserDoc().showSnapLines, icon: "compress-arrows-alt" });
viewCtrlItems.push({ description: (this.Document.useClusters ? "Hide" : "Show") + " Clusters", event: () => this.updateClusters(!this.Document.useClusters), icon: "braille" });
- !viewctrls && ContextMenu.Instance.addItem({ description: "View Controls...", subitems: viewCtrlItems, icon: "eye" });
+ !viewctrls && ContextMenu.Instance.addItem({ description: "UI Controls...", subitems: viewCtrlItems, icon: "eye" });
const options = ContextMenu.Instance.findByDescription("Options...");
const optionItems = options && "subitems" in options ? options.subitems : [];
diff --git a/src/client/views/collections/collectionFreeForm/FormatShapePane.scss b/src/client/views/collections/collectionFreeForm/FormatShapePane.scss
index 88876471c..010beb836 100644
--- a/src/client/views/collections/collectionFreeForm/FormatShapePane.scss
+++ b/src/client/views/collections/collectionFreeForm/FormatShapePane.scss
@@ -24,11 +24,13 @@
.formatShapePane-inputBtn {
width: inherit;
- position: absolute;
+ position: absolute;
}
.sketch-picker {
background: #323232;
+ width: 160px !important;
+ height: 80% !important;
.flexbox-fit {
background: #323232;
diff --git a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
index 4e328d838..ddc282e57 100644
--- a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
+++ b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
@@ -12,6 +12,8 @@ import { SelectionManager } from "../../../util/SelectionManager";
import AntimodeMenu from "../../AntimodeMenu";
import "./FormatShapePane.scss";
import { undoBatch } from "../../../util/UndoManager";
+import { ColorState, SketchPicker } from 'react-color';
+import { DocumentView } from "../../../views/nodes/DocumentView"
@observer
export default class FormatShapePane extends AntimodeMenu {
@@ -20,14 +22,16 @@ export default class FormatShapePane extends AntimodeMenu {
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 _subOpen = [false, false];
@observable private _currMode = "fill-drip";
- @observable private _lock = false;
+ @observable _lock = false;
@observable private _fillBtn = false;
@observable private _lineBtn = false;
+ @observable _controlBtn = false;
+ @observable private _controlPoints: { X: number, Y: number }[] = [];
+ @observable _currPoint = -1;
getField(key: string) {
return this.selectedInk?.reduce((p, i) =>
@@ -101,19 +105,58 @@ export default class FormatShapePane extends AntimodeMenu {
upDownButtons = (dirs: string, field: string) => {
switch (field) {
case "rot": this.rotate((dirs === "up" ? .1 : -.1)); break;
+ // case "rot": this.selectedInk?.forEach(i => i.rootDoc.rotation = NumCast(i.rootDoc.rotation) + (dirs === "up" ? 0.1 : -0.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 => {
+ //redraw points
const oldWidth = NumCast(i.rootDoc._width);
+ const oldHeight = NumCast(i.rootDoc._height);
+ const oldX = NumCast(i.rootDoc.x);
+ const oldY = NumCast(i.rootDoc.y);
i.rootDoc._width = oldWidth + (dirs === "up" ? 10 : - 10);
this._lock && (i.rootDoc._height = (i.rootDoc._width / oldWidth * NumCast(i.rootDoc._height)));
+ const doc = Document(i.rootDoc);
+ if (doc.type === DocumentType.INK && doc.x && doc.y && doc._height && doc._width) {
+ console.log(doc.x, doc.y, doc._height, doc._width);
+ const ink = Cast(doc.data, InkField)?.inkData;
+ console.log(ink);
+ if (ink) {
+ const newPoints: { X: number, Y: number }[] = [];
+ for (var j = 0; j < ink.length; j++) {
+ // (new x — oldx) + (oldxpoint * newWidt)/oldWidth
+ const newX = (doc.x - oldX) + (ink[j].X * doc._width) / oldWidth;
+ const newY = (doc.y - oldY) + (ink[j].Y * doc._height) / oldHeight;
+ newPoints.push({ X: newX, Y: newY });
+ }
+ doc.data = new InkField(newPoints);
+ }
+ }
});
break;
case "hgt": this.selectedInk?.filter(i => i.rootDoc._width && i.rootDoc._height).forEach(i => {
+ const oldWidth = NumCast(i.rootDoc._width);
const oldHeight = NumCast(i.rootDoc._height);
- i.rootDoc._height = oldHeight + (dirs === "up" ? 10 : - 10);
+ const oldX = NumCast(i.rootDoc.x);
+ const oldY = NumCast(i.rootDoc.y); i.rootDoc._height = oldHeight + (dirs === "up" ? 10 : - 10);
this._lock && (i.rootDoc._width = (i.rootDoc._height / oldHeight * NumCast(i.rootDoc._width)));
+ const doc = Document(i.rootDoc);
+ if (doc.type === DocumentType.INK && doc.x && doc.y && doc._height && doc._width) {
+ console.log(doc.x, doc.y, doc._height, doc._width);
+ const ink = Cast(doc.data, InkField)?.inkData;
+ console.log(ink);
+ if (ink) {
+ const newPoints: { X: number, Y: number }[] = [];
+ for (var j = 0; j < ink.length; j++) {
+ // (new x — oldx) + (oldxpoint * newWidt)/oldWidth
+ const newX = (doc.x - oldX) + (ink[j].X * doc._width) / oldWidth;
+ const newY = (doc.y - oldY) + (ink[j].Y * doc._height) / oldHeight;
+ newPoints.push({ X: newX, Y: newY });
+ }
+ doc.data = new InkField(newPoints);
+ }
+ }
});
break;
}
@@ -121,12 +164,11 @@ export default class FormatShapePane extends AntimodeMenu {
@undoBatch
@action
- rotate = (degrees: number) => {
- this.selectedInk?.forEach(action(inkView => {
+ rotate = (angle: number) => {
+ const _centerPoints: { X: number, Y: number }[] = [];
+ SelectionManager.SelectedDocuments().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);
@@ -135,143 +177,280 @@ export default class FormatShapePane extends AntimodeMenu {
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 });
+ }
+ }
+ }));
+
+ var index = 0;
+ SelectionManager.SelectedDocuments().forEach(action(inkView => {
+ const doc = Document(inkView.rootDoc);
+ if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) {
+ doc.rotation = Number(doc.rotation) + Number(angle);
+ const ink = Cast(doc.data, InkField)?.inkData;
+ if (ink) {
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;
+ const newX = Math.cos(angle) * (ink[i].X - _centerPoints[index].X) - Math.sin(angle) * (ink[i].Y - _centerPoints[index].Y) + _centerPoints[index].X;
+ const newY = Math.sin(angle) * (ink[i].X - _centerPoints[index].X) + Math.cos(angle) * (ink[i].Y - _centerPoints[index].Y) + _centerPoints[index].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;
+ const xs = newPoints.map(p => p.X);
+ const ys = newPoints.map(p => p.Y);
+ const left = Math.min(...xs);
+ const top = Math.min(...ys);
+ const right = Math.max(...xs);
+ const bottom = Math.max(...ys);
+
+ doc._height = (bottom - top);
+ doc._width = (right - left);
}
+ index++;
}
}));
}
+ @undoBatch
+ @action
+ control = (xDiff: number, yDiff: number, controlNum: number) => {
+ this.selectedInk?.forEach(action(inkView => {
+ if (this.selectedInk?.length === 1) {
+ const doc = Document(inkView.rootDoc);
+ if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) {
+ const ink = Cast(doc.data, InkField)?.inkData;
+ if (ink) {
+
+ const newPoints: { X: number, Y: number }[] = [];
+ const order = controlNum % 4;
+ for (var i = 0; i < ink.length; i++) {
+ if (controlNum === i ||
+ (order === 0 && i === controlNum + 1) ||
+ (order === 0 && controlNum !== 0 && i === controlNum - 2) ||
+ (order === 0 && controlNum !== 0 && i === controlNum - 1) ||
+ (order === 3 && i === controlNum - 1) ||
+ (order === 3 && controlNum !== ink.length - 1 && i === controlNum + 1) ||
+ (order === 3 && controlNum !== ink.length - 1 && i === controlNum + 2)
+ || ((ink[0].X === ink[ink.length - 1].X) && (ink[0].Y === ink[ink.length - 1].Y) && (i === 0 || i === ink.length - 1) && (controlNum === 0 || controlNum === ink.length - 1))
+ ) {
+ newPoints.push({ X: ink[i].X - (xDiff * inkView.props.ScreenToLocalTransform().Scale), Y: ink[i].Y - (yDiff * inkView.props.ScreenToLocalTransform().Scale) });
+ }
+ else {
+ newPoints.push({ X: ink[i].X, Y: ink[i].Y });
+ }
+ }
+ const oldx = doc.x;
+ const oldy = doc.y;
+ const xs = ink.map(p => p.X);
+ const ys = ink.map(p => p.Y);
+ const left = Math.min(...xs);
+ const top = Math.min(...ys);
+ 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);
+ doc._width = (right2 - left2);
+ //if points move out of bounds
- colorPicker(setter: (color: string) => {}) {
- return <div className="btn-group-palette" key="colorpicker" >
- {this._palette.map(color =>
- <button className="antimodeMenu-button" key={color} onPointerDown={undoBatch(action(() => setter(color)))} style={{ zIndex: 1001, position: "relative" }}>
- <div className="color-previewII" style={{ backgroundColor: color }} />
- </button>)}
+ doc.x = oldx - (left - left2);
+ doc.y = oldy - (top - top2);
+
+ }
+ }
+ }
+ }));
+ }
+
+ @undoBatch
+ @action
+ switchStk = (color: ColorState) => {
+ const val = String(color.hex);
+ this.colorStk = val;
+ return true;
+ }
+
+ @undoBatch
+ @action
+ switchFil = (color: ColorState) => {
+ const val = String(color.hex);
+ this.colorFil = val;
+ return true;
+ }
+
+
+ colorPicker(setter: (color: string) => {}, type: string) {
+ return <div className="btn-group-palette" key="colorpicker" style={{ width: 160, margin: 10 }}>
+ <SketchPicker onChange={type === "stk" ? this.switchStk : this.switchFil} presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF', '#f1efeb', 'transparent']}
+ color={type === "stk" ? this.colorStk : this.colorFil} />
</div>;
}
inputBox = (key: string, value: any, setter: (val: string) => {}) => {
return <>
- <input style={{ color: "black", width: 80, position: "absolute", right: 20 }}
+ <input style={{ color: "black", width: 40, position: "absolute", right: 20 }}
type="text" value={value}
- onChange={e => setter(e.target.value)}
+ onChange={undoBatch(action((e) => setter(e.target.value)))}
autoFocus />
- <button className="antiMenu-Buttonup" key="up" onPointerDown={undoBatch(action(() => this.upDownButtons("up", key)))}>
+ <button className="antiMenu-Buttonup" key="up1" onPointerDown={undoBatch(action(() => this.upDownButtons("up", key)))}>
˄
</button>
<br />
- <button className="antiMenu-Buttonup" key="down" onPointerDown={undoBatch(action(() => this.upDownButtons("down", key)))} style={{ marginTop: -8 }}>
+ <button className="antiMenu-Buttonup" key="down1" onPointerDown={undoBatch(action(() => this.upDownButtons("down", key)))} style={{ marginTop: -8 }}>
˅
</button>
</>;
}
+ inputBoxDuo = (key: string, value: any, setter: (val: string) => {}, title1: string, key2: string, value2: any, setter2: (val: string) => {}, title2: string) => {
+ return <>
+ {title1}
+ <p style={{ marginTop: -20, right: 70, position: "absolute" }}>{title2}</p>
+
+ <input style={{ color: "black", width: 40, position: "absolute", right: 130 }}
+ type="text" value={value}
+ onChange={e => setter(e.target.value)}
+ autoFocus />
+ <button className="antiMenu-Buttonup" key="up2" onPointerDown={undoBatch(action(() => this.upDownButtons("up", key)))} style={{ right: 110 }}>
+ ˄
+ </button>
+ <button className="antiMenu-Buttonup" key="down2" onPointerDown={undoBatch(action(() => this.upDownButtons("down", key)))} style={{ marginTop: 12, right: 110 }}>
+ ˅
+ </button>
+ {title2 === "" ? "" : <>
+ <input style={{ color: "black", width: 40, position: "absolute", right: 20 }}
+ type="text" value={value2}
+ onChange={e => setter2(e.target.value)}
+ autoFocus />
+ <button className="antiMenu-Buttonup" key="up3" onPointerDown={undoBatch(action(() => this.upDownButtons("up", key2)))}>
+ ˄
+ </button>
+ <br />
+ <button className="antiMenu-Buttonup" key="down3" onPointerDown={undoBatch(action(() => this.upDownButtons("down", key2)))} style={{ marginTop: -8 }}>
+ ˅
+ </button></>}
+ </>;
+ }
+
+
colorButton(value: string, setter: () => {}) {
return <>
- <button className="antimodeMenu-button" key="fill" onPointerDown={undoBatch(action(e => setter()))} style={{ position: "absolute", right: 80 }}>
- <FontAwesomeIcon icon="fill-drip" size="lg" />
- <div className="color-previewI" style={{ backgroundColor: value ?? "121212" }} />
+ <button className="antimodeMenu-button" key="color" onPointerDown={undoBatch(action(e => setter()))} style={{ position: "relative", marginTop: -5 }}>
+ <div className="color-previewII" style={{ backgroundColor: value ?? "121212" }} />
+ {value === "" || value === "transparent" ? <p style={{ fontSize: 25, color: "red", marginTop: -23, position: "fixed" }}>☒</p> : ""}
+ </button>
+ </>;
+ }
+
+ controlPointsButton() {
+ return <>
+ <button className="antimodeMenu-button" title="Edit points" key="bezier" onPointerDown={action(() => this._controlBtn = this._controlBtn ? false : true)} style={{ position: "relative", marginTop: 10, backgroundColor: this._controlBtn ? "black" : "" }}>
+ <FontAwesomeIcon icon="bezier-curve" size="lg" />
+ </button>
+ <button className="antimodeMenu-button" title="Lock ratio" key="ratio" onPointerDown={action(() => this._lock = this._lock ? false : true)} style={{ position: "relative", marginTop: 10, backgroundColor: this._lock ? "black" : "" }}>
+ <FontAwesomeIcon icon="lock" size="lg" />
+
+ </button>
+ <button className="antimodeMenu-button" key="rotate" title="Rotate 90˚" onPointerDown={action(() => this.rotate(Math.PI / 2))} style={{ position: "relative", marginTop: 10, fontSize: 15 }}>
+ ⟲
</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); }
+ lockRatioButton() {
+ return <>
+ <button className="antimodeMenu-button" key="lock" onPointerDown={action(() => this._lock = this._lock ? false : true)} style={{ position: "absolute", right: 80, backgroundColor: this._lock ? "black" : "" }}>
+ {/* <FontAwesomeIcon icon="bezier-curve" size="lg" /> */}
+ <FontAwesomeIcon icon="lock" size="lg" />
+
+ </button>
+ <br /> <br />
+ </>;
+ }
- @computed get fillPicker() { return this.colorPicker((color: string) => this.colorFil = color); }
- @computed get linePicker() { return this.colorPicker((color: string) => this.colorStk = color); }
+ rotate90Button() {
+ return <>
+ <button className="antimodeMenu-button" key="rot" onPointerDown={action(() => this.rotate(Math.PI / 2))} style={{ position: "absolute", right: 80, }}>
+ {/* <FontAwesomeIcon icon="bezier-curve" size="lg" /> */}
+ ⟲
+
+ </button>
+ <br /> <br />
+ </>;
+ }
+ @computed get fillButton() { return this.colorButton(this.colorFil, () => { this._fillBtn = !this._fillBtn; this._lineBtn = false; return true; }); }
+ @computed get lineButton() { return this.colorButton(this.colorStk, () => { this._lineBtn = !this._lineBtn; this._fillBtn = false; return true; }); }
+
+ @computed get fillPicker() { return this.colorPicker((color: string) => this.colorFil = color, "fil"); }
+ @computed get linePicker() { return this.colorPicker((color: string) => this.colorStk = color, "stk"); }
@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 dashInput() { return this.inputBox("dsh", this.widthStk, (val: string) => this.widthStk = val); }
+
+ @computed get hgtInput() { return this.inputBoxDuo("hgt", this.shapeHgt, (val: string) => this.shapeHgt = val, "H:", "wid", this.shapeWid, (val: string) => this.shapeWid = val, "W:"); }
@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 rotInput() { return this.inputBoxDuo("rot", this.shapeRot, (val: string) => { this.rotate(Number(val) - Number(this.shapeRot)); this.shapeRot = val; return true; }, "∠:", "rot", this.shapeRot, (val: string) => this.shapeRot = val, ""); }
+
+ @computed get XpsInput() { return this.inputBoxDuo("Xps", this.shapeXps, (val: string) => this.shapeXps = val, "X:", "Yps", this.shapeYps, (val: string) => this.shapeYps = val, "Y:"); }
@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={undoBatch(action(() => this.unFilled = true))} />
- No Fill
- <br />
- <input className="formatShapePane-inputBtn" type="radio" checked={this.solidFil} onChange={undoBatch(action(() => this.solidFil = true))} />
- Solid Fill
- <br /> <br />
- {this.solidFil ? "Color" : ""}
- {this.solidFil ? this.fillButton : ""}
- {this._fillBtn && this.solidFil ? this.fillPicker : ""}
- </div>;
+ @computed get controlPoints() { return this.controlPointsButton(); }
+ @computed get lockRatio() { return this.lockRatioButton(); }
+ @computed get rotate90() { return this.rotate90Button(); }
- const markers = <>
- <input key="markHead" className="formatShapePane-inputBtn" type="checkbox" checked={this.markHead !== ""} onChange={undoBatch(action(() => this.markHead = this.markHead ? "" : "arrow"))} />
- Arrow Head
- <br />
- <input key="markTail" className="formatShapePane-inputBtn" type="checkbox" checked={this.markTail !== ""} onChange={undoBatch(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={undoBatch(action(() => this.unStrokd = true))} />
- No Line
- <br />
- <input className="formatShapePane-inputBtn" type="radio" checked={this.solidStk} onChange={undoBatch(action(() => this.solidStk = true))} />
- Solid Line
- <br />
- <input className="formatShapePane-inputBtn" type="radio" checked={this.dashdStk ? true : false} onChange={undoBatch(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 />
+ @computed get propertyGroupItems() {
+ const fillCheck = <div key="fill" style={{ display: (this._subOpen[0] && this.selectedInk && this.selectedInk.length >= 1) ? "" : "none", width: "inherit", backgroundColor: "#323232", color: "white", }}>
+ Fill:
+ {this.fillButton}
+ <div style={{ float: "left", width: 100 }} >
+ Stroke:
+ {this.lineButton}
+ </div>
+
+ {this._fillBtn ? this.fillPicker : ""}
+ {this._lineBtn ? this.linePicker : ""}
+ {this._fillBtn || this._lineBtn ? "" : <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={undoBatch(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 />
+ {(this.solidStk || this.dashdStk) ? <input type="range" defaultValue={Number(this.widthStk)} min={1} max={100} onChange={undoBatch(action((e) => this.widthStk = e.target.value))} /> : (null)}
+ <br />
+ {(this.solidStk || this.dashdStk) ? <>
+ <p style={{ position: "absolute", fontSize: 12 }}>Arrow Head</p>
+ <input key="markHead" className="formatShapePane-inputBtn" type="checkbox" checked={this.markHead !== ""} onChange={undoBatch(action(() => this.markHead = this.markHead ? "" : "arrow"))} style={{ position: "absolute", right: 110, width: 20 }} />
+ <p style={{ position: "absolute", fontSize: 12, right: 30 }}>Arrow End</p>
+ <input key="markTail" className="formatShapePane-inputBtn" type="checkbox" checked={this.markTail !== ""} onChange={undoBatch(action(() => this.markTail = this.markTail ? "" : "arrow"))} style={{ position: "absolute", right: 0, width: 20 }} />
+ <br />
+ </> : ""}
+ Dash: <input key="markHead" className="formatShapePane-inputBtn" type="checkbox" checked={this.dashdStk === "2"} onChange={undoBatch(action(() => this.dashdStk = this.dashdStk === "2" ? "0" : "2"))} style={{ position: "absolute", right: 110, width: 20 }} />
+
+
+
</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;
+
+
+ const sizeCheck =
+
+ <div key="sizeCheck" style={{ display: (this._subOpen[1] && this.selectedInk && this.selectedInk.length >= 1) ? "" : "none", width: "inherit", backgroundColor: "#323232", color: "white", }}>
+ {this.controlPoints}
+ {this.hgtInput}
+ {this.XpsInput}
+ {this.rotInput}
+
+ </div>;
+
+
+ const subMenus = this._currMode === "fill-drip" ? [`Appearance`, 'Transform'] : [];
+ const menuItems = this._currMode === "fill-drip" ? [fillCheck, sizeCheck] : [];
+ const indexOffset = 0;
+
return <div className="antimodeMenu-sub" key="submenu" style={{ position: "absolute", width: "inherit", top: 60 }}>
{subMenus.map((subMenu, i) =>
<div key={subMenu} style={{ width: "inherit" }}>
@@ -302,6 +481,7 @@ export default class FormatShapePane extends AntimodeMenu {
}
render() {
- return this.getElementVert([this.closeBtn, this.propertyGroupBtn, this.propertyGroupItems]);
+ return this.getElementVert([this.closeBtn,
+ this.propertyGroupItems]);
}
} \ No newline at end of file