From c3eea60fa586e8ff9cf59497c041044fd0143bb1 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 28 Mar 2019 21:03:17 -0400 Subject: organized collectionfreeformview. fixed issues with showing links --- .../collectionFreeForm/CollectionFreeFormView.scss | 95 ++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss new file mode 100644 index 000000000..9c5e98005 --- /dev/null +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -0,0 +1,95 @@ +@import "../../global_variables"; + +.collectionfreeformview-container { + .collectionfreeformview > .jsx-parser { + position: absolute; + height: 100%; + width: 100%; + } + + .inking-canvas { + transform-origin: 50000px 50000px; + } + //nested freeform views + // .collectionfreeformview-container { + // background-image: linear-gradient(to right, $light-color-secondary 1px, transparent 1px), + // linear-gradient(to bottom, $light-color-secondary 1px, transparent 1px); + // background-size: 30px 30px; + // } + + box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw; + border: 0px solid $light-color-secondary; + border-radius: $border-radius; + box-sizing: border-box; + position: relative; + overflow: hidden; + top: 0; + left: 0; + width: 100%; + height: 100%; + .collectionfreeformview { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + .inking-canvas { + transform-origin: 50000px 50000px; + } + } +} +.collectionfreeformview-overlay { + .collectionfreeformview > .jsx-parser { + position: absolute; + height: 100%; + } + .formattedTextBox-cont { + background: $light-color-secondary; + } + + .inking-canvas { + transform-origin: 50000px 50000px; + } + + opacity: 0.99; + border: 0px solid transparent; + border-radius: $border-radius; + box-sizing: border-box; + position:relative; + overflow: hidden; + top: 0; + left: 0; + width: 100%; + height: 100%; + .collectionfreeformview { + .formattedTextBox-cont { + background:yellow; + } + } +} + +// selection border...? +.border { + border-style: solid; + box-sizing: border-box; + width: 98%; + height: 98%; + border-radius: $border-radius; +} + +//this is an animation for the blinking cursor! +@keyframes blink { + 0% { + opacity: 0; + } + 49% { + opacity: 0; + } + 50% { + opacity: 1; + } +} + +#prevCursor { + animation: blink 1s infinite; +} -- cgit v1.2.3-70-g09d2 From da7a12f9b49b43534658524b1da846948fbf3947 Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 29 Mar 2019 14:37:26 -0400 Subject: fixed some bugs added some small features to histograms. --- src/client/Server.ts | 4 ++-- src/client/documents/Documents.ts | 4 ++-- src/client/northstar/dash-nodes/HistogramBox.tsx | 17 ++++++++++++----- .../northstar/dash-nodes/HistogramBoxPrimitives.tsx | 5 ++++- src/client/northstar/utils/SizeConverter.ts | 2 +- src/client/util/DragManager.ts | 2 ++ src/client/views/Main.tsx | 6 +++--- .../collectionFreeForm/CollectionFreeFormView.scss | 20 ++++++++++---------- 8 files changed, 36 insertions(+), 24 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss') diff --git a/src/client/Server.ts b/src/client/Server.ts index feafe9eb4..37e3c2c0d 100644 --- a/src/client/Server.ts +++ b/src/client/Server.ts @@ -75,7 +75,7 @@ export class Server { existingFields[id] = field; } } - SocketStub.SEND_FIELDS_REQUEST(neededFieldIds, (fields) => { + SocketStub.SEND_FIELDS_REQUEST(neededFieldIds, action((fields: FieldMap) => { for (let id of neededFieldIds) { let field = fields[id]; if (field) { @@ -104,7 +104,7 @@ export class Server { cb({ ...fields, ...existingFields }) } }, { fireImmediately: true }) - }); + })); }; if (callback) { fn(callback); diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 663ccae61..0bf275df8 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -190,8 +190,8 @@ export namespace Documents { return assignToDelegate(SetInstanceOptions(GetAudioPrototype(), options, [new URL(url), AudioField]), options); } - export function HistogramDocument(histoOp: HistogramOperation, options: DocumentOptions = {}, id?: string) { - return assignToDelegate(SetInstanceOptions(GetHistogramPrototype(), options, [histoOp, HistogramField], id).MakeDelegate(), options); + export function HistogramDocument(histoOp: HistogramOperation, options: DocumentOptions = {}, id?: string, delegId?: string) { + return assignToDelegate(SetInstanceOptions(GetHistogramPrototype(), options, [histoOp, HistogramField], id).MakeDelegate(delegId), options); } export function TextDocument(options: DocumentOptions = {}) { return assignToDelegate(SetInstanceOptions(GetTextPrototype(), options, ["", TextField]).MakeDelegate(), options); diff --git a/src/client/northstar/dash-nodes/HistogramBox.tsx b/src/client/northstar/dash-nodes/HistogramBox.tsx index 9f8c2cfd0..dba4ce900 100644 --- a/src/client/northstar/dash-nodes/HistogramBox.tsx +++ b/src/client/northstar/dash-nodes/HistogramBox.tsx @@ -9,7 +9,7 @@ import { CurrentUserUtils } from "../../../server/authentication/models/current_ import { FilterModel } from '../../northstar/core/filter/FilterModel'; import { ChartType, VisualBinRange } from '../../northstar/model/binRanges/VisualBinRange'; import { VisualBinRangeHelper } from "../../northstar/model/binRanges/VisualBinRangeHelper"; -import { AggregateBinRange, BinRange, DoubleValueAggregateResult, HistogramResult, Catalog } from "../../northstar/model/idea/idea"; +import { AggregateBinRange, BinRange, DoubleValueAggregateResult, HistogramResult, Catalog, AggregateFunction } from "../../northstar/model/idea/idea"; import { ModelHelpers } from "../../northstar/model/ModelHelpers"; import { HistogramOperation } from "../../northstar/operations/HistogramOperation"; import { PIXIRectangle } from "../../northstar/utils/MathUtil"; @@ -21,6 +21,7 @@ import "../utils/Extensions" import "./HistogramBox.scss"; import { HistogramBoxPrimitives } from './HistogramBoxPrimitives'; import { HistogramLabelPrimitives } from "./HistogramLabelPrimitives"; +import { AttributeTransformationModel } from "../core/attribute/AttributeTransformationModel"; export interface HistogramPrimitivesProps { HistoBox: HistogramBox; @@ -104,7 +105,11 @@ export class HistogramBox extends React.Component { @action xLabelPointerDown = (e: React.PointerEvent) => { - + this.HistoOp.X = new AttributeTransformationModel(this.HistoOp.X.AttributeModel, this.HistoOp.X.AggregateFunction == AggregateFunction.None ? AggregateFunction.Count : AggregateFunction.None); + } + @action + yLabelPointerDown = (e: React.PointerEvent) => { + this.HistoOp.Y = new AttributeTransformationModel(this.HistoOp.Y.AttributeModel, this.HistoOp.Y.AggregateFunction == AggregateFunction.None ? AggregateFunction.Count : AggregateFunction.None); } componentWillUnmount() { @@ -138,12 +143,12 @@ export class HistogramBox extends React.Component { runInAction(() => { this.PanelWidth = r.entry.width; this.PanelHeight = r.entry.height })}> {({ measureRef }) =>
-
+
{labelY}
-
{
-
{labelX}
+
+ {labelX} +
} diff --git a/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx b/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx index d2f1be4fd..5e403eb9c 100644 --- a/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx +++ b/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx @@ -1,5 +1,5 @@ import React = require("react") -import { computed, observable, runInAction } from "mobx"; +import { computed, observable, runInAction, reaction } from "mobx"; import { observer } from "mobx-react"; import { Utils as DashUtils } from '../../../Utils'; import { AttributeTransformationModel } from "../../northstar/core/attribute/AttributeTransformationModel"; @@ -19,6 +19,9 @@ import "./HistogramBoxPrimitives.scss"; export class HistogramBoxPrimitives extends React.Component { private get histoOp() { return this.props.HistoBox.HistoOp; } private get renderDimension() { return this.props.HistoBox.SizeConverter.RenderDimension; } + componentDidMount() { + reaction(() => this.props.HistoBox.HistogramResult, () => this._selectedPrims.length = 0); + } @observable _selectedPrims: HistogramBinPrimitive[] = []; @computed get xaxislines() { return this.renderGridLinesAndLabels(0); } @computed get yaxislines() { return this.renderGridLinesAndLabels(1); } diff --git a/src/client/northstar/utils/SizeConverter.ts b/src/client/northstar/utils/SizeConverter.ts index 30627dfd5..bb91ed4a7 100644 --- a/src/client/northstar/utils/SizeConverter.ts +++ b/src/client/northstar/utils/SizeConverter.ts @@ -62,7 +62,7 @@ export class SizeConverter { public DataToScreenPointRange(axis: number, bin: Bin, aggregateKey: AggregateKey) { var value = ModelHelpers.GetAggregateResult(bin, aggregateKey) as DoubleValueAggregateResult; - if (value.hasResult) + if (value && value.hasResult) return [this.DataToScreenCoord(value.result!, axis) - 5, this.DataToScreenCoord(value.result!, axis) + 5]; return [undefined, undefined]; diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 661fa4dc8..70b1c9829 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -186,6 +186,8 @@ export namespace DragManager { e.preventDefault(); x += e.movementX; y += e.movementY; + if (dragData instanceof DocumentDragData) + dragData.aliasOnDrop = e.ctrlKey || e.altKey; if (e.shiftKey) { abortDrag(); CollectionDockingView.Instance.StartOtherDrag(doc, { pageX: e.pageX, pageY: e.pageY, preventDefault: () => { }, button: 0 }); diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 2f20b102c..75855c3d1 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -245,7 +245,7 @@ export class Main extends React.Component { let addTextNode = action(() => Documents.TextDocument({ width: 200, height: 200, title: "a text note" })) let addColNode = action(() => Documents.FreeformDocument([], { width: 200, height: 200, title: "a freeform collection" })); let addSchemaNode = action(() => Documents.SchemaDocument([], { width: 200, height: 200, title: "a schema collection" })); - let addTreeNode = action(() => Documents.TreeDocument(this._northstarSchemas, { width: 100, height: 400, title: "northstar schemas" })); + let addTreeNode = action(() => Documents.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas" })); let addVideoNode = action(() => Documents.VideoDocument(videourl, { width: 200, height: 200, title: "video node" })); let addPDFNode = action(() => Documents.PdfDocument(pdfurl, { width: 200, height: 200, title: "a schema collection" })); let addImageNode = action(() => Documents.ImageDocument(imgurl, { width: 200, height: 200, title: "an image of a cat" })); @@ -340,7 +340,7 @@ export class Main extends React.Component { let schemaDoc = Documents.TreeDocument([], { width: 50, height: 100, title: schema.displayName! }); let schemaDocuments = schemaDoc.GetList(KeyStore.Data, [] as Document[]); CurrentUserUtils.GetAllNorthstarColumnAttributes(schema).map(attr => { - Server.GetField(attr.displayName!, action((field: Opt) => { + Server.GetField(attr.displayName! + ".alias", action((field: Opt) => { if (field instanceof Document) { schemaDocuments.push(field); } else { @@ -349,7 +349,7 @@ export class Main extends React.Component { new AttributeTransformationModel(atmod, AggregateFunction.None), new AttributeTransformationModel(atmod, AggregateFunction.Count), new AttributeTransformationModel(atmod, AggregateFunction.Count)); - schemaDocuments.push(Documents.HistogramDocument(histoOp, { width: 200, height: 200, title: attr.displayName! }, attr.displayName!)); + schemaDocuments.push(Documents.HistogramDocument(histoOp, { width: 200, height: 200, title: attr.displayName! }, undefined, attr.displayName! + ".alias")); } })); }); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss index 9c5e98005..215a75243 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -1,5 +1,15 @@ @import "../../global_variables"; +.collectionfreeformview { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + .inking-canvas { + transform-origin: 50000px 50000px; + } +} .collectionfreeformview-container { .collectionfreeformview > .jsx-parser { position: absolute; @@ -27,16 +37,6 @@ left: 0; width: 100%; height: 100%; - .collectionfreeformview { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - .inking-canvas { - transform-origin: 50000px 50000px; - } - } } .collectionfreeformview-overlay { .collectionfreeformview > .jsx-parser { -- cgit v1.2.3-70-g09d2 From eb220da697e2383b1e368dee743613158994746e Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 31 Mar 2019 17:58:11 -0400 Subject: restructured marquee and preview cursor to not need reactions. fixed some inking bugs. --- src/client/views/InkingCanvas.tsx | 25 ++- .../CollectionFreeFormLinksView.tsx | 1 + .../collectionFreeForm/CollectionFreeFormView.scss | 1 + .../collectionFreeForm/CollectionFreeFormView.tsx | 199 ++++++++------------- .../collectionFreeForm/MarqueeView.scss | 6 + .../collections/collectionFreeForm/MarqueeView.tsx | 169 +++++++++-------- .../collectionFreeForm/PreviewCursor.scss | 7 +- .../collectionFreeForm/PreviewCursor.tsx | 71 +++++--- 8 files changed, 245 insertions(+), 234 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss') diff --git a/src/client/views/InkingCanvas.tsx b/src/client/views/InkingCanvas.tsx index 36a8834a0..8fb74ec48 100644 --- a/src/client/views/InkingCanvas.tsx +++ b/src/client/views/InkingCanvas.tsx @@ -1,16 +1,15 @@ -import { observer } from "mobx-react"; -import { observable } from "mobx"; import { action, computed } from "mobx"; -import { InkingControl } from "./InkingControl"; -import React = require("react"); -import { Transform } from "../util/Transform"; +import { observer } from "mobx-react"; import { Document } from "../../fields/Document"; -import { KeyStore } from "../../fields/KeyStore"; +import { FieldWaiting } from "../../fields/Field"; import { InkField, InkTool, StrokeData, StrokeMap } from "../../fields/InkField"; -import { InkingStroke } from "./InkingStroke"; -import "./InkingCanvas.scss" +import { KeyStore } from "../../fields/KeyStore"; import { Utils } from "../../Utils"; -import { FieldWaiting } from "../../fields/Field"; +import { Transform } from "../util/Transform"; +import "./InkingCanvas.scss"; +import { InkingControl } from "./InkingControl"; +import { InkingStroke } from "./InkingStroke"; +import React = require("react"); interface InkCanvasProps { getScreenTransform: () => Transform; @@ -71,8 +70,7 @@ export class InkingCanvas extends React.Component { // start the new line, saves a uuid to represent the field of the stroke this._idGenerator = Utils.GenerateGuid(); - let data = this.inkData; - data.set(this._idGenerator, + this.inkData.set(this._idGenerator, { pathData: [point], color: InkingControl.Instance.selectedColor, @@ -80,7 +78,6 @@ export class InkingCanvas extends React.Component { tool: InkingControl.Instance.selectedTool, page: this.props.Document.GetNumber(KeyStore.CurPage, -1) }); - this.inkData = data; this._isDrawing = true; } @@ -163,9 +160,7 @@ export class InkingCanvas extends React.Component { }) return ( - -
+
{paths} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index f793b3a49..ea392eaea 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -96,6 +96,7 @@ export class CollectionFreeFormLinksView extends React.Component {this.uniqueConnections.map(c => )} + {this.props.children} ); } } \ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss index 215a75243..c979b27a9 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -6,6 +6,7 @@ left: 0; width: 100%; height: 100%; + transform-origin: left top; .inking-canvas { transform-origin: 50000px 50000px; } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 1f90b0d46..cdc5bdfb0 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -3,7 +3,6 @@ import { observer } from "mobx-react"; import { Document } from "../../../../fields/Document"; import { FieldWaiting } from "../../../../fields/Field"; import { KeyStore } from "../../../../fields/KeyStore"; -import { ListField } from "../../../../fields/ListField"; import { TextField } from "../../../../fields/TextField"; import { DragManager } from "../../../util/DragManager"; import { Transform } from "../../../util/Transform"; @@ -14,10 +13,9 @@ import { DocumentContentsView } from "../../nodes/DocumentContentsView"; import { DocumentViewProps } from "../../nodes/DocumentView"; import { COLLECTION_BORDER_WIDTH } from "../CollectionView"; import { CollectionViewBase } from "../CollectionViewBase"; -import { MarqueeView } from "./MarqueeView"; -import { PreviewCursor } from "./PreviewCursor"; import { CollectionFreeFormLinksView } from "./CollectionFreeFormLinksView"; import "./CollectionFreeFormView.scss"; +import { MarqueeView } from "./MarqueeView"; import React = require("react"); import v5 = require("uuid/v5"); @@ -27,12 +25,15 @@ export class CollectionFreeFormView extends CollectionViewBase { private _selectOnLoaded: string = ""; // id of document that should be selected once it's loaded (used for click-to-type) public addLiveTextBox = (newBox: Document) => { - // mark this collection so that when the text box is created we can send it the SelectOnLoad prop to focus itself + // mark this collection so that when the text box is created we can send it the SelectOnLoad prop to focus itself and receive text input this._selectOnLoaded = newBox.Id; - //set text to be the typed key and get focus on text box - this.props.addDocument(newBox, false); - //remove cursor from screen - this.PreviewCursorVisible = false; + this.addDocument(newBox, false); + } + + public addDocument = (newBox: Document, allowDuplicates: boolean) => { + let added = this.props.addDocument(newBox, false); + this.bringToFront(newBox); + return added; } public selectDocuments = (docs: Document[]) => { @@ -42,23 +43,15 @@ export class CollectionFreeFormView extends CollectionViewBase { public getActiveDocuments = () => { var curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1); - const lvalue = this.props.Document.GetT>(this.props.fieldKey, ListField); - let active: Document[] = []; - if (lvalue && lvalue != FieldWaiting) { - lvalue.Data.map(doc => { - var page = doc.GetNumber(KeyStore.Page, -1); - if (page == curPage || page == -1) { - active.push(doc); - } - }) - } - - return active; + return this.props.Document.GetList(this.props.fieldKey, [] as Document[]).reduce((active, doc) => { + var page = doc.GetNumber(KeyStore.Page, -1); + if (page == curPage || page == -1) { + active.push(doc); + } + return active; + }, [] as Document[]); } - //determines whether the blinking cursor for indicating whether a text will be made on key down is visible - @observable public PreviewCursorVisible: boolean = false; - @observable public MarqueeVisible = false; @observable public DownX: number = 0; @observable public DownY: number = 0; @observable private _lastX: number = 0; @@ -100,12 +93,10 @@ export class CollectionFreeFormView extends CollectionViewBase { cleanupInteractions = () => { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); - this.MarqueeVisible = false; } @action onPointerDown = (e: React.PointerEvent): void => { - this.PreviewCursorVisible = false; if ((e.button === 2 && this.props.active() && (!this.isAnnotationOverlay || this.zoomScaling != 1)) || e.button == 0) { document.removeEventListener("pointermove", this.onPointerMove); document.addEventListener("pointermove", this.onPointerMove); @@ -120,28 +111,13 @@ export class CollectionFreeFormView extends CollectionViewBase { onPointerUp = (e: PointerEvent): void => { e.stopPropagation(); - if (Math.abs(this.DownX - e.clientX) < 4 && Math.abs(this.DownY - e.clientY) < 4) { - //show preview text cursor on tap - this.PreviewCursorVisible = true; - //select is not already selected - if (!this.props.isSelected()) { - this.props.select(false); - } - } this.cleanupInteractions(); } @action onPointerMove = (e: PointerEvent): void => { if (!e.cancelBubble && this.props.active()) { - if (e.buttons == 1 && !e.altKey && !e.metaKey) { - this.MarqueeVisible = true; - } - if (this.MarqueeVisible) { - e.stopPropagation(); - e.preventDefault(); - } - else if ((!this.isAnnotationOverlay || this.zoomScaling != 1) && !e.shiftKey) { + if ((!this.isAnnotationOverlay || this.zoomScaling != 1) && !e.shiftKey) { let x = this.props.Document.GetNumber(KeyStore.PanX, 0); let y = this.props.Document.GetNumber(KeyStore.PanY, 0); let [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY); @@ -264,16 +240,12 @@ export class CollectionFreeFormView extends CollectionViewBase { @computed get views() { var curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1); - const lvalue = this.props.Document.GetT>(this.props.fieldKey, ListField); - if (lvalue && lvalue != FieldWaiting) { - return lvalue.Data.map(doc => { - if (!doc) return null; - var page = doc.GetNumber(KeyStore.Page, 0); - return (page != curPage && page != 0) ? (null) : - (); - }) - } - return null; + return this.props.Document.GetList(this.props.fieldKey, [] as Document[]).filter(doc => doc).reduce((prev, doc) => { + var page = doc.GetNumber(KeyStore.Page, -1); + if (page == curPage || page == -1) + prev.push(); + return prev; + }, [] as JSX.Element[]) } @computed @@ -290,15 +262,10 @@ export class CollectionFreeFormView extends CollectionViewBase { } getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH).translate(-this.centeringShiftX, -this.centeringShiftY).transform(this.getLocalTransform()) - getMarqueeTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH) + getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH) getLocalTransform = (): Transform => Transform.Identity.scale(1 / this.scale).translate(this.panX, this.panY); noScaling = () => 1; - //when focus is lost, this will remove the preview cursor - @action - onBlur = (): void => { - this.PreviewCursorVisible = false; - } private crosshairs?: HTMLCanvasElement; drawCrosshairs = (backgroundColor: string) => { @@ -345,71 +312,63 @@ export class CollectionFreeFormView extends CollectionViewBase { return (
super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY))} - onWheel={this.onPointerWheel} - onDrop={this.onDrop.bind(this)} - onDragOver={this.onDragOver} - onBlur={this.onBlur} - style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }}// , zIndex: !this.props.isTopMost ? -1 : undefined }} - tabIndex={0} - ref={this.createDropTarget}> -
- {this.backgroundView} - - - {this.views} - - {super.getCursors().map(entry => { - if (entry.Data.length > 0) { - let id = entry.Data[0][0]; - let email = entry.Data[0][1]; - let point = entry.Data[1]; - this.drawCrosshairs("#" + v5(id, v5.URL).substring(0, 6).toUpperCase() + "22") - return ( -
- { if (el) this.crosshairs = el }} - width={20} - height={20} - style={{ - position: 'absolute', - width: "20px", - height: "20px", - opacity: 0.5, - borderRadius: "50%", - border: "2px solid black" - }} - /> -

super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY))} + onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} onWheel={this.onPointerWheel} + style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }} tabIndex={0} ref={this.createDropTarget}> + +

+ {this.backgroundView} + + {this.views} + + {super.getCursors().map(entry => { + if (entry.Data.length > 0) { + let id = entry.Data[0][0]; + let email = entry.Data[0][1]; + let point = entry.Data[1]; + this.drawCrosshairs("#" + v5(id, v5.URL).substring(0, 6).toUpperCase() + "22") + return ( +
{email[0].toUpperCase()}

-
- ); - } - })} -
- - {this.overlayView} - + > + { if (el) this.crosshairs = el }} + width={20} + height={20} + style={{ + position: 'absolute', + width: "20px", + height: "20px", + opacity: 0.5, + borderRadius: "50%", + border: "2px solid black" + }} + /> +

{email[0].toUpperCase()}

+
+ ); + } + })} +
+ {this.overlayView} +
); } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.scss b/src/client/views/collections/collectionFreeForm/MarqueeView.scss index 6d9a79344..1ee3b244b 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.scss +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.scss @@ -1,8 +1,14 @@ .marqueeView { + position: absolute; + width:100%; + height:100%; +} +.marquee { border-style: dashed; box-sizing: border-box; position: absolute; border-width: 1px; border-color: black; + pointer-events: none; } \ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 2692690dd..2b0e7d228 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -1,62 +1,58 @@ -import { action, IReactionDisposer, observable, reaction } from "mobx"; +import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; import { Document } from "../../../../fields/Document"; -import { FieldWaiting, Opt } from "../../../../fields/Field"; +import { FieldWaiting } from "../../../../fields/Field"; +import { InkField, StrokeData } from "../../../../fields/InkField"; import { KeyStore } from "../../../../fields/KeyStore"; import { Documents } from "../../../documents/Documents"; import { SelectionManager } from "../../../util/SelectionManager"; import { Transform } from "../../../util/Transform"; +import { InkingCanvas } from "../../InkingCanvas"; import { CollectionFreeFormView } from "./CollectionFreeFormView"; import "./MarqueeView.scss"; +import { PreviewCursor } from "./PreviewCursor"; import React = require("react"); -import { InkField, StrokeData } from "../../../../fields/InkField"; -import { Utils } from "../../../../Utils"; -import { InkingCanvas } from "../../InkingCanvas"; interface MarqueeViewProps { - getMarqueeTransform: () => Transform; + getContainerTransform: () => Transform; getTransform: () => Transform; container: CollectionFreeFormView; addDocument: (doc: Document, allowDuplicates: false) => boolean; activeDocuments: () => Document[]; selectDocuments: (docs: Document[]) => void; removeDocument: (doc: Document) => boolean; + addLiveTextDocument: (doc: Document) => void; } @observer export class MarqueeView extends React.Component { - private _reactionDisposer: Opt; - @observable _lastX: number = 0; @observable _lastY: number = 0; @observable _downX: number = 0; @observable _downY: number = 0; - - componentDidMount() { - this._reactionDisposer = reaction( - () => this.props.container.MarqueeVisible, - (visible: boolean) => this.onPointerDown(visible, this.props.container.DownX, this.props.container.DownY)) - } - componentWillUnmount() { - if (this._reactionDisposer) { - this._reactionDisposer(); - } - this.cleanupInteractions(); - } + @observable _used: boolean = false; + @observable _visible: boolean = false; + static DRAG_THRESHOLD = 4; @action - cleanupInteractions = () => { - document.removeEventListener("pointermove", this.onPointerMove, true) - document.removeEventListener("pointerup", this.onPointerUp, true); + cleanupInteractions = (all: boolean = false) => { + if (all) { + document.removeEventListener("pointermove", this.onPointerMove, true) + document.removeEventListener("pointerup", this.onPointerUp, true); + } else { + this._used = true; + } document.removeEventListener("keydown", this.marqueeCommand, true); + this._visible = false; } @action - onPointerDown = (visible: boolean, downX: number, downY: number): void => { - if (visible) { - this._downX = this._lastX = downX; - this._downY = this._lastY = downY; + onPointerDown = (e: React.PointerEvent): void => { + if (e.buttons == 1 && !e.altKey && !e.metaKey && this.props.container.props.active()) { + this._downX = this._lastX = e.pageX; + this._downY = this._lastY = e.pageY; + this._used = false; document.addEventListener("pointermove", this.onPointerMove, true) document.addEventListener("pointerup", this.onPointerUp, true); document.addEventListener("keydown", this.marqueeCommand, true); @@ -67,11 +63,20 @@ export class MarqueeView extends React.Component onPointerMove = (e: PointerEvent): void => { this._lastX = e.pageX; this._lastY = e.pageY; + if (!e.cancelBubble) { + if (!this._used && e.buttons == 1 && !e.altKey && !e.metaKey && + (Math.abs(this._lastX - this._downX) > MarqueeView.DRAG_THRESHOLD || Math.abs(this._lastY - this._downY) > MarqueeView.DRAG_THRESHOLD)) { + this._visible = true; + } + e.stopPropagation(); + e.preventDefault(); + } } @action onPointerUp = (e: PointerEvent): void => { - this.cleanupInteractions(); + this.cleanupInteractions(true); + this._visible = false; if (!e.shiftKey) { SelectionManager.DeselectAll(); } @@ -83,6 +88,7 @@ export class MarqueeView extends React.Component return !(r2.left > r1.left + r1.width || r2.left + r2.width < r1.left || r2.top > r1.top + r1.height || r2.top + r2.height < r1.top); } + @computed get Bounds() { let left = this._downX < this._lastX ? this._downX : this._lastX; let top = this._downY < this._lastY ? this._downY : this._lastY; @@ -95,7 +101,10 @@ export class MarqueeView extends React.Component marqueeCommand = (e: KeyboardEvent) => { if (e.key == "Backspace" || e.key == "Delete") { this.marqueeSelect().map(d => this.props.removeDocument(d)); - this.props.container.props.Document.SetData(KeyStore.Ink, this.marqueeInkSelect(false), InkField); + let ink = this.props.container.props.Document.GetT(KeyStore.Ink, InkField); + if (ink && ink != FieldWaiting && ink.Data) { + this.marqueeInkDelete(ink.Data); + } this.cleanupInteractions(); } if (e.key == "c") { @@ -104,53 +113,61 @@ export class MarqueeView extends React.Component this.props.removeDocument(d); d.SetNumber(KeyStore.X, d.GetNumber(KeyStore.X, 0) - bounds.left - bounds.width / 2); d.SetNumber(KeyStore.Y, d.GetNumber(KeyStore.Y, 0) - bounds.top - bounds.height / 2); - d.SetNumber(KeyStore.Page, 0); + d.SetNumber(KeyStore.Page, -1); d.SetText(KeyStore.Title, "" + d.GetNumber(KeyStore.Width, 0) + " " + d.GetNumber(KeyStore.Height, 0)); return d; }); - let liftedInk = this.marqueeInkSelect(true); - this.props.container.props.Document.SetData(KeyStore.Ink, this.marqueeInkSelect(false), InkField); - //setTimeout(() => { - let newCollection = Documents.FreeformDocument(selected, { - x: bounds.left, - y: bounds.top, - panx: 0, - pany: 0, - width: bounds.width, - height: bounds.height, - backgroundColor: "Transparent", - ink: liftedInk, - title: "a nested collection" - }); - this.props.addDocument(newCollection, false); + let ink = this.props.container.props.Document.GetT(KeyStore.Ink, InkField); + if (ink && ink != FieldWaiting && ink.Data) { + //setTimeout(() => { + let newCollection = Documents.FreeformDocument(selected, { + x: bounds.left, + y: bounds.top, + panx: 0, + pany: 0, + width: bounds.width, + height: bounds.height, + backgroundColor: "Transparent", + ink: this.marqueeInkSelect(ink.Data), + title: "a nested collection" + }); + this.props.addDocument(newCollection, false); + this.marqueeInkDelete(ink.Data); + } // }, 100); this.cleanupInteractions(); } } - marqueeInkSelect(select: boolean) { - let selRect = this.Bounds; - let centerShiftX = 0 - (selRect.left + selRect.width / 2); // moves each point by the offset that shifts the selection's center to the origin. - let centerShiftY = 0 - (selRect.top + selRect.height / 2); - let ink = this.props.container.props.Document.GetT(KeyStore.Ink, InkField); - if (ink && ink != FieldWaiting && ink.Data) { - let idata = new Map(); - ink.Data.forEach((value: StrokeData, key: string, map: any) => { - let inside = InkingCanvas.IntersectStrokeRect(value, selRect); - if (inside && select) { - idata.set(key, - { - pathData: value.pathData.map(val => { return { x: val.x + centerShiftX, y: val.y + centerShiftY } }), - color: value.color, - width: value.width, - tool: value.tool, - page: -1 - }); - } else if (!inside && !select) { - idata.set(key, value); - } - }) - return idata; - } + @action + marqueeInkSelect(ink: Map) { + let idata = new Map(); + let centerShiftX = 0 - (this.Bounds.left + this.Bounds.width / 2); // moves each point by the offset that shifts the selection's center to the origin. + let centerShiftY = 0 - (this.Bounds.top + this.Bounds.height / 2); + ink.forEach((value: StrokeData, key: string, map: any) => { + if (InkingCanvas.IntersectStrokeRect(value, this.Bounds)) { + idata.set(key, + { + pathData: value.pathData.map(val => { return { x: val.x + centerShiftX, y: val.y + centerShiftY } }), + color: value.color, + width: value.width, + tool: value.tool, + page: -1 + }); + } + }); + return idata; + } + + @action + marqueeInkDelete(ink: Map, ) { + // bcz: this appears to work but when you restart all the deleted strokes come back -- InkField isn't observing its changes so they aren't written to the DB. + // ink.forEach((value: StrokeData, key: string, map: any) => + // InkingCanvas.IntersectStrokeRect(value, this.Bounds) && ink.delete(key)); + + let idata = new Map(); + ink.forEach((value: StrokeData, key: string, map: any) => + !InkingCanvas.IntersectStrokeRect(value, this.Bounds) && idata.set(key, value)); + this.props.container.props.Document.SetDataOnPrototype(KeyStore.Ink, idata, InkField); } marqueeSelect() { @@ -168,8 +185,16 @@ export class MarqueeView extends React.Component } render() { - let p = this.props.getMarqueeTransform().transformPoint(this._downX < this._lastX ? this._downX : this._lastX, this._downY < this._lastY ? this._downY : this._lastY); - let v = this.props.getMarqueeTransform().transformDirection(this._lastX - this._downX, this._lastY - this._downY); - return (!this.props.container.MarqueeVisible ? (null) :
); + let p = this.props.getContainerTransform().transformPoint(this._downX < this._lastX ? this._downX : this._lastX, this._downY < this._lastY ? this._downY : this._lastY); + let v = this.props.getContainerTransform().transformDirection(this._lastX - this._downX, this._lastY - this._downY); + return
+ + {this.props.children} + {!this._visible ? (null) : +
} + + +
; } } \ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/PreviewCursor.scss b/src/client/views/collections/collectionFreeForm/PreviewCursor.scss index a797411f6..7d6d5aaab 100644 --- a/src/client/views/collections/collectionFreeForm/PreviewCursor.scss +++ b/src/client/views/collections/collectionFreeForm/PreviewCursor.scss @@ -5,6 +5,11 @@ transform-origin: left top; pointer-events: none; } +.previewCursorView { + position: absolute; + width:100%; + height:100%; +} //this is an animation for the blinking cursor! @keyframes blink { @@ -14,5 +19,5 @@ } #previewCursor { - animation: blink 1s infinite; + animation: blink 1s infinite; } \ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx b/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx index 95364f04b..339e056a8 100644 --- a/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx +++ b/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx @@ -1,7 +1,6 @@ -import { action, IReactionDisposer, observable, reaction } from "mobx"; +import { action, observable } from "mobx"; import { observer } from "mobx-react"; import { Document } from "../../../../fields/Document"; -import { Opt } from "../../../../fields/Field"; import { Documents } from "../../../documents/Documents"; import { Transform } from "../../../util/Transform"; import { CollectionFreeFormView } from "./CollectionFreeFormView"; @@ -11,43 +10,50 @@ import React = require("react"); export interface PreviewCursorProps { getTransform: () => Transform; + getContainerTransform: () => Transform; container: CollectionFreeFormView; addLiveTextDocument: (doc: Document) => void; } @observer export class PreviewCursor extends React.Component { - private _reactionDisposer: Opt; - @observable _lastX: number = 0; @observable _lastY: number = 0; + @observable public _visible: boolean = false; + @observable public DownX: number = 0; + @observable public DownY: number = 0; + _showOnUp: boolean = false; + public _previewDivRef = React.createRef(); - componentDidMount() { - this._reactionDisposer = reaction( - () => this.props.container.PreviewCursorVisible, - (visible: boolean) => this.onCursorPlaced(visible, this.props.container.DownX, this.props.container.DownY)) - } - componentWillUnmount() { - if (this._reactionDisposer) { - this._reactionDisposer(); - } - this.cleanupInteractions(); + @action + cleanupInteractions = () => { + document.removeEventListener("pointerup", this.onPointerUp, true); } - @action - cleanupInteractions = () => { + onPointerDown = (e: React.PointerEvent) => { + this._visible = false; document.removeEventListener("keypress", this.onKeyPress, false); + this._showOnUp = true; + this._lastX = this.DownX = e.pageX; + this._lastY = this.DownY = e.pageY; + document.addEventListener("pointerup", this.onPointerUp, true); + document.addEventListener("pointermove", this.onPointerMove, true); + } + @action + onPointerMove = (e: PointerEvent): void => { + if (Math.abs(this.DownX - e.clientX) > 4 || Math.abs(this.DownY - e.clientY) > 4) { + this._showOnUp = false; + } } @action - onCursorPlaced = (visible: boolean, downX: number, downY: number): void => { - if (visible) { + onPointerUp = (e: PointerEvent): void => { + if (this._showOnUp) { document.addEventListener("keypress", this.onKeyPress, false); - this._lastX = downX; - this._lastY = downY; - } else - this.cleanupInteractions(); + this._visible = true; + } + this.cleanupInteractions(); } @action @@ -61,16 +67,29 @@ export class PreviewCursor extends React.Component { let [x, y] = this.props.getTransform().transformPoint(this._lastX, this._lastY); let newBox = Documents.TextDocument({ width: 200, height: 100, x: x, y: y, title: "typed text" }); this.props.addLiveTextDocument(newBox); + document.removeEventListener("keypress", this.onKeyPress, false); + this._visible = false; e.stopPropagation(); } } + //when focus is lost, this will remove the preview cursor + @action + onBlur = (): void => { + this._visible = false; + document.removeEventListener("keypress", this.onKeyPress, false); + } render() { //get local position and place cursor there! - let [x, y] = this.props.getTransform().transformPoint(this._lastX, this._lastY); + let p = this.props.getContainerTransform().transformPoint(this._lastX, this._lastY); + if (this._visible && this._previewDivRef.current) + this._previewDivRef.current!.focus(); return ( - !this.props.container.PreviewCursorVisible ? (null) : -
I
) - +
+ {this.props.children} + {!this._visible ? (null) : +
I
} +
+ ) } } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 2ac86b53d28abb8be2f3abd501b801e543973e28 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 31 Mar 2019 22:45:43 -0400 Subject: restructured inkingCanvas and linksViews --- src/client/views/InkingCanvas.scss | 164 +++------------------ src/client/views/InkingCanvas.tsx | 121 +++++++-------- src/client/views/InkingControl.scss | 135 +++++++++++++++++ src/client/views/InkingControl.tsx | 3 +- .../CollectionFreeFormLinksView.scss | 3 + .../CollectionFreeFormLinksView.tsx | 9 +- .../collectionFreeForm/CollectionFreeFormView.scss | 10 -- .../collectionFreeForm/CollectionFreeFormView.tsx | 10 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 6 +- src/client/views/nodes/PDFBox.tsx | 10 +- 10 files changed, 233 insertions(+), 238 deletions(-) create mode 100644 src/client/views/InkingControl.scss (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss') diff --git a/src/client/views/InkingCanvas.scss b/src/client/views/InkingCanvas.scss index e79b146b9..6d7821cd2 100644 --- a/src/client/views/InkingCanvas.scss +++ b/src/client/views/InkingCanvas.scss @@ -1,149 +1,25 @@ @import "global_variables"; -.inking-canvas { + +.inkingCanvas-paths, .inkingCanvas-paths-none { position: absolute; top: -50000px; - left: -50000px; // z-index: 99; //overlays ink on top of everything - svg { - position:absolute; - width: 100000px; - height: 100000px; - .highlight { - mix-blend-mode: multiply; - } - } + left: -50000px; + width: 100000px; + height: 100000px; + //z-index: 10000; // z-index: 99; //overlays ink on top of everything but that messes up blending and events don't propagate down to nested collections + .highlight { + mix-blend-mode: multiply; + } + .inkingCanvas-children { + transform: translate(50000px, 50000px); + pointer-events: none; + } + cursor:"crosshair"; + pointer-events: auto; + +} +.inkingCanvas-paths-none { + pointer-events: none; + cursor: "arrow"; } -.inking-control { - position: absolute; - left: 70px; - bottom: 70px; - margin: 0; - padding: 0; - display: flex; - label, - input, - option { - font-size: 12px; - } - input[type="range"] { - -webkit-appearance: none; - background-color: transparent; - vertical-align: middle; - margin-top: 8px; - &:focus { - outline: none; - } - &::-webkit-slider-runnable-track { - width: 100%; - height: 3px; - border-radius: 1.5px; - cursor: pointer; - background: $intermediate-color; - } - &::-webkit-slider-thumb { - height: 12px; - width: 12px; - border: 1px solid $intermediate-color; - border-radius: 6px; - background: $light-color; - cursor: pointer; - -webkit-appearance: none; - margin-top: -4px; - } - &::-moz-range-track { - width: 100%; - height: 3px; - border-radius: 1.5px; - cursor: pointer; - background: $light-color; - } - &::-moz-range-thumb { - height: 12px; - width: 12px; - border: 1px solid $intermediate-color; - border-radius: 6px; - background: $light-color; - cursor: pointer; - -webkit-appearance: none; - margin-top: -4px; - } - } - input[type="text"] { - border: none; - padding: 0 0px; - background: transparent; - color: $dark-color; - font-size: 12px; - margin-top: 4px; - } - .ink-panel { - margin: 6px 12px 6px 0; - height: 30px; - vertical-align: middle; - line-height: 36px; - padding: 0 10px; - color: $intermediate-color; - &:first { - margin-top: 0; - } - } - .ink-tools { - display: flex; - background-color: transparent; - border-radius: 0; - padding: 0; - button { - height: 36px; - padding: 0px; - padding-bottom: 3px; - margin-left: 10px; - background-color: transparent; - color: $intermediate-color; - } - button:hover { - transform: scale(1.15); - } - } - .ink-size { - display: flex; - justify-content: space-between; - input[type="text"] { - width: 42px; - } - >* { - margin-right: 6px; - &:last-child { - margin-right: 0; - } - } - } - .ink-color { - display: flex; - position: relative; - padding-right: 0; - label { - margin-right: 6px; - } - .ink-color-display { - border-radius: 11px; - width: 22px; - height: 22px; - margin-top: 6px; - cursor: pointer; - text-align: center; // span { - // color: $light-color; - // font-size: 8px; - // user-select: none; - // } - } - .ink-color-picker { - background-color: $light-color; - border-radius: 5px; - padding: 12px; - position: absolute; - bottom: 36px; - left: -3px; - box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw; - } - } -} \ No newline at end of file diff --git a/src/client/views/InkingCanvas.tsx b/src/client/views/InkingCanvas.tsx index 8fb74ec48..a971264b9 100644 --- a/src/client/views/InkingCanvas.tsx +++ b/src/client/views/InkingCanvas.tsx @@ -57,51 +57,62 @@ export class InkingCanvas extends React.Component { } @action - handleMouseDown = (e: React.PointerEvent): void => { - if (e.button != 0 || + onPointerDown = (e: React.PointerEvent): void => { + this._isDrawing = false; + if (e.button != 0 || e.altKey || e.ctrlKey || InkingControl.Instance.selectedTool === InkTool.None) { return; } - e.stopPropagation() - if (InkingControl.Instance.selectedTool === InkTool.Eraser) { - return - } - const point = this.relativeCoordinatesForEvent(e); - - // start the new line, saves a uuid to represent the field of the stroke - this._idGenerator = Utils.GenerateGuid(); - this.inkData.set(this._idGenerator, - { - pathData: [point], - color: InkingControl.Instance.selectedColor, - width: InkingControl.Instance.selectedWidth, - tool: InkingControl.Instance.selectedTool, - page: this.props.Document.GetNumber(KeyStore.CurPage, -1) - }); + document.addEventListener("pointermove", this.onPointerMove, true); + document.addEventListener("pointerup", this.onPointerUp, true); + e.stopPropagation(); + this._isDrawing = true; + if (InkingControl.Instance.selectedTool != InkTool.Eraser) { + const point = this.relativeCoordinatesForEvent(e.clientX, e.clientY); + + // start the new line, saves a uuid to represent the field of the stroke + this._idGenerator = Utils.GenerateGuid(); + this.inkData.set(this._idGenerator, + { + pathData: [point], + color: InkingControl.Instance.selectedColor, + width: InkingControl.Instance.selectedWidth, + tool: InkingControl.Instance.selectedTool, + page: this.props.Document.GetNumber(KeyStore.CurPage, -1) + }); + } } - @action - handleMouseMove = (e: React.PointerEvent): void => { - if (!this._isDrawing || - InkingControl.Instance.selectedTool === InkTool.None) { - return; + onPointerUp = (e: PointerEvent): void => { + if (this._isDrawing) { + document.removeEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); + this._isDrawing = false; + e.stopPropagation(); } - e.stopPropagation() - if (InkingControl.Instance.selectedTool === InkTool.Eraser) { - return - } - const point = this.relativeCoordinatesForEvent(e); + } - // add points to new line as it is being drawn - let data = this.inkData; - let strokeData = data.get(this._idGenerator); - if (strokeData) { - strokeData.pathData.push(point); - data.set(this._idGenerator, strokeData); + @action + onPointerMove = (e: PointerEvent): void => { + if (this._isDrawing) { + e.stopPropagation() + e.preventDefault(); + if (InkingControl.Instance.selectedTool === InkTool.Eraser) { + return + } + const point = this.relativeCoordinatesForEvent(e.clientX, e.clientY); + + // add points to new line as it is being drawn + let data = this.inkData; + let strokeData = data.get(this._idGenerator); + if (strokeData) { + strokeData.pathData.push(point); + data.set(this._idGenerator, strokeData); + } + + this.inkData = data; } - - this.inkData = data; } @action @@ -109,8 +120,8 @@ export class InkingCanvas extends React.Component { this._isDrawing = false; } - relativeCoordinatesForEvent = (e: React.MouseEvent): { x: number, y: number } => { - let [x, y] = this.props.getScreenTransform().transformPoint(e.clientX, e.clientY); + relativeCoordinatesForEvent = (ex: number, ey: number): { x: number, y: number } => { + let [x, y] = this.props.getScreenTransform().transformPoint(ex, ey); x += InkingCanvas.InkOffset; y += InkingCanvas.InkOffset; return { x, y }; @@ -124,32 +135,9 @@ export class InkingCanvas extends React.Component { } render() { - // styling for cursor - let canvasStyle = {}; - if (InkingControl.Instance.selectedTool === InkTool.None) { - canvasStyle = { pointerEvents: "none" }; - } else { - canvasStyle = { pointerEvents: "auto", cursor: "crosshair" }; - } - - // get data from server - // let inkField = this.props.Document.GetT(KeyStore.Ink, InkField); - // if (!inkField || inkField == FieldWaiting) { - // return (
- // - // - //
) - // } - - let lines = this.inkData; - // parse data from server - let paths: Array = [] let curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1) - Array.from(lines).map(item => { - let id = item[0]; - let strokeData = item[1]; + let paths = Array.from(this.inkData).reduce((paths, [id, strokeData]) => { if (strokeData.page == -1 || strokeData.page == curPage) paths.push( { width={strokeData.width} tool={strokeData.tool} deleteCallback={this.removeLine} />) - }) + return paths; + }, [] as JSX.Element[]); + let svgCanvasStyle = InkingControl.Instance.selectedTool == InkTool.None ? "-none" : ""; return ( -
- +
+ {paths} + {this.props.children}
) } diff --git a/src/client/views/InkingControl.scss b/src/client/views/InkingControl.scss new file mode 100644 index 000000000..0d8fd8784 --- /dev/null +++ b/src/client/views/InkingControl.scss @@ -0,0 +1,135 @@ +@import "global_variables"; +.inking-control { + position: absolute; + left: 70px; + bottom: 70px; + margin: 0; + padding: 0; + display: flex; + label, + input, + option { + font-size: 12px; + } + input[type="range"] { + -webkit-appearance: none; + background-color: transparent; + vertical-align: middle; + margin-top: 8px; + &:focus { + outline: none; + } + &::-webkit-slider-runnable-track { + width: 100%; + height: 3px; + border-radius: 1.5px; + cursor: pointer; + background: $intermediate-color; + } + &::-webkit-slider-thumb { + height: 12px; + width: 12px; + border: 1px solid $intermediate-color; + border-radius: 6px; + background: $light-color; + cursor: pointer; + -webkit-appearance: none; + margin-top: -4px; + } + &::-moz-range-track { + width: 100%; + height: 3px; + border-radius: 1.5px; + cursor: pointer; + background: $light-color; + } + &::-moz-range-thumb { + height: 12px; + width: 12px; + border: 1px solid $intermediate-color; + border-radius: 6px; + background: $light-color; + cursor: pointer; + -webkit-appearance: none; + margin-top: -4px; + } + } + input[type="text"] { + border: none; + padding: 0 0px; + background: transparent; + color: $dark-color; + font-size: 12px; + margin-top: 4px; + } + .ink-panel { + margin: 6px 12px 6px 0; + height: 30px; + vertical-align: middle; + line-height: 36px; + padding: 0 10px; + color: $intermediate-color; + &:first { + margin-top: 0; + } + } + .ink-tools { + display: flex; + background-color: transparent; + border-radius: 0; + padding: 0; + button { + height: 36px; + padding: 0px; + padding-bottom: 3px; + margin-left: 10px; + background-color: transparent; + color: $intermediate-color; + } + button:hover { + transform: scale(1.15); + } + } + .ink-size { + display: flex; + justify-content: space-between; + input[type="text"] { + width: 42px; + } + >* { + margin-right: 6px; + &:last-child { + margin-right: 0; + } + } + } + .ink-color { + display: flex; + position: relative; + padding-right: 0; + label { + margin-right: 6px; + } + .ink-color-display { + border-radius: 11px; + width: 22px; + height: 22px; + margin-top: 6px; + cursor: pointer; + text-align: center; // span { + // color: $light-color; + // font-size: 8px; + // user-select: none; + // } + } + .ink-color-picker { + background-color: $light-color; + border-radius: 5px; + padding: 12px; + position: absolute; + bottom: 36px; + left: -3px; + box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw; + } + } +} \ No newline at end of file diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx index eb2172d03..c1519dff8 100644 --- a/src/client/views/InkingControl.tsx +++ b/src/client/views/InkingControl.tsx @@ -2,10 +2,9 @@ import { observable, action, computed } from "mobx"; import { CirclePicker, ColorResult } from 'react-color' import React = require("react"); -import "./InkingCanvas.scss" import { InkTool } from "../../fields/InkField"; import { observer } from "mobx-react"; -import "./InkingCanvas.scss" +import "./InkingControl.scss" import { library } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faPen, faHighlighter, faEraser, faBan } from '@fortawesome/free-solid-svg-icons'; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.scss index 9af0df7f5..4341c82f7 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.scss @@ -4,4 +4,7 @@ width: 20000px; height: 20000px; pointer-events: none; + } + .collectionfreeformlinksview-container { + pointer-events: none; } \ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index ea392eaea..ef60aa672 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -94,9 +94,12 @@ export class CollectionFreeFormLinksView extends React.Component - {this.uniqueConnections.map(c => )} +
+ + {this.uniqueConnections.map(c => )} + {this.props.children} - ); +
+ ); } } \ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss index c979b27a9..81d21d89a 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -7,9 +7,6 @@ width: 100%; height: 100%; transform-origin: left top; - .inking-canvas { - transform-origin: 50000px 50000px; - } } .collectionfreeformview-container { .collectionfreeformview > .jsx-parser { @@ -18,9 +15,6 @@ width: 100%; } - .inking-canvas { - transform-origin: 50000px 50000px; - } //nested freeform views // .collectionfreeformview-container { // background-image: linear-gradient(to right, $light-color-secondary 1px, transparent 1px), @@ -48,10 +42,6 @@ background: $light-color-secondary; } - .inking-canvas { - transform-origin: 50000px 50000px; - } - opacity: 0.99; border: 0px solid transparent; border-radius: $border-radius; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index cdc5bdfb0..ae1c775e6 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -314,16 +314,18 @@ export class CollectionFreeFormView extends CollectionViewBase {
super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY))} onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} onWheel={this.onPointerWheel} - style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }} tabIndex={0} ref={this.createDropTarget}> + style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }} ref={this.createDropTarget}>
{this.backgroundView} - - {this.views} - + + + {this.views} + + {super.getCursors().map(entry => { if (entry.Data.length > 0) { let id = entry.Data[0][0]; diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 7f951864e..d52b662bd 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -1,4 +1,4 @@ -import { computed, trace, reaction, runInAction, observable } from "mobx"; +import { computed } from "mobx"; import { observer } from "mobx-react"; import { KeyStore } from "../../../fields/KeyStore"; import { NumberField } from "../../../fields/NumberField"; @@ -6,8 +6,7 @@ import { Transform } from "../../util/Transform"; import { DocumentView, DocumentViewProps } from "./DocumentView"; import "./DocumentView.scss"; import React = require("react"); -import { Document } from "../../../fields/Document"; -import { DocumentManager } from "../../util/DocumentManager"; +import { thisExpression } from "babel-types"; @observer @@ -75,6 +74,7 @@ export class CollectionFreeFormDocumentView extends React.Component { @observable private _interactive: boolean = false; @observable private _loaded: boolean = false; - @computed private get curPage() { return this.props.doc.GetNumber(KeyStore.CurPage, -1); } + @computed private get curPage() { return this.props.doc.GetNumber(KeyStore.CurPage, 1); } @computed private get thumbnailPage() { return this.props.doc.GetNumber(KeyStore.ThumbnailPage, -1); } componentDidMount() { @@ -435,8 +435,6 @@ export class PDFBox extends React.Component { @computed get pdfContent() { let page = this.curPage; - if (page == 0) - page = 1; const renderHeight = 2400; let pdfUrl = this.props.doc.GetT(this.props.fieldKey, PDFField); let xf = this.props.doc.GetNumber(KeyStore.NativeHeight, 0) / renderHeight; @@ -463,10 +461,8 @@ export class PDFBox extends React.Component { return [ this._pageInfo.area.filter(() => this._pageInfo.area).map((element: any) => element), this._currAnno.map((element: any) => element), -
- {this.pdfContent} - {proxy} -
+ this.pdfContent, + proxy ]; } -- cgit v1.2.3-70-g09d2 From b78aff5115862cbfa5e704422cb738aa7fd73c64 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 4 Apr 2019 14:13:29 -0400 Subject: fixed a number of smaller issues related to linking --- src/client/northstar/dash-nodes/HistogramBox.scss | 5 + src/client/util/DragManager.ts | 533 +++++++------- src/client/util/SelectionManager.ts | 74 +- src/client/views/DocumentDecorations.scss | 61 +- src/client/views/DocumentDecorations.tsx | 81 ++- src/client/views/InkingCanvas.scss | 2 + src/client/views/Main.scss | 7 + .../views/collections/CollectionDockingView.scss | 2 +- .../views/collections/CollectionPDFView.scss | 2 + .../views/collections/CollectionVideoView.scss | 2 + .../views/collections/CollectionViewBase.tsx | 20 + .../CollectionFreeFormLinkView.tsx | 8 +- .../CollectionFreeFormLinksView.scss | 2 + .../collectionFreeForm/CollectionFreeFormView.scss | 6 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 13 +- .../collectionFreeForm/MarqueeView.scss | 2 + .../collectionFreeForm/PreviewCursor.scss | 4 + .../views/nodes/CollectionFreeFormDocumentView.tsx | 4 + src/client/views/nodes/DocumentView.scss | 2 + src/client/views/nodes/PDFBox.scss | 4 + src/client/views/nodes/WebBox.scss | 2 + src/fields/Document.ts | 773 +++++++++++---------- 22 files changed, 882 insertions(+), 727 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss') diff --git a/src/client/northstar/dash-nodes/HistogramBox.scss b/src/client/northstar/dash-nodes/HistogramBox.scss index b11840a65..94da36e29 100644 --- a/src/client/northstar/dash-nodes/HistogramBox.scss +++ b/src/client/northstar/dash-nodes/HistogramBox.scss @@ -1,6 +1,8 @@ .histogrambox-container { padding: 0vw; position: absolute; + top: 0; + left:0; text-align: center; width: 100%; height: 100%; @@ -8,6 +10,7 @@ } .histogrambox-xaxislabel { position:absolute; + left:0; width:100%; text-align: center; bottom:0; @@ -19,11 +22,13 @@ position:absolute; height:100%; width: 25px; + left:0; bottom:0; background: lightgray; } .histogrambox-yaxislabel-text { position:absolute; + left:0; transform-origin: left; transform: rotate(-90deg); text-align: center; diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index c0f482e18..e8f8cce7c 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -8,304 +8,307 @@ import { CollectionView } from "../views/collections/CollectionView"; import { DocumentView } from "../views/nodes/DocumentView"; export function setupDrag( - _reference: React.RefObject, - docFunc: () => Document, - removeFunc: (containingCollection: CollectionView) => void = () => {} + _reference: React.RefObject, + docFunc: () => Document, + removeFunc: (containingCollection: CollectionView) => void = () => { } ) { - let onRowMove = action( - (e: PointerEvent): void => { - e.stopPropagation(); - e.preventDefault(); + let onRowMove = action( + (e: PointerEvent): void => { + e.stopPropagation(); + e.preventDefault(); - document.removeEventListener("pointermove", onRowMove); - document.removeEventListener("pointerup", onRowUp); - var dragData = new DragManager.DocumentDragData([docFunc()]); - dragData.removeDocument = removeFunc; - DragManager.StartDocumentDrag([_reference.current!], dragData); - } - ); - let onRowUp = action( - (e: PointerEvent): void => { - document.removeEventListener("pointermove", onRowMove); - document.removeEventListener("pointerup", onRowUp); - } - ); - let onItemDown = (e: React.PointerEvent) => { - // if (this.props.isSelected() || this.props.isTopMost) { - if (e.button == 0) { - e.stopPropagation(); - if (e.shiftKey) { - CollectionDockingView.Instance.StartOtherDrag([docFunc()], e); - } else { - document.addEventListener("pointermove", onRowMove); - document.addEventListener("pointerup", onRowUp); - } - } - //} - }; - return onItemDown; + document.removeEventListener("pointermove", onRowMove); + document.removeEventListener("pointerup", onRowUp); + var dragData = new DragManager.DocumentDragData([docFunc()]); + dragData.removeDocument = removeFunc; + DragManager.StartDocumentDrag([_reference.current!], dragData); + } + ); + let onRowUp = action( + (e: PointerEvent): void => { + document.removeEventListener("pointermove", onRowMove); + document.removeEventListener("pointerup", onRowUp); + } + ); + let onItemDown = (e: React.PointerEvent) => { + // if (this.props.isSelected() || this.props.isTopMost) { + if (e.button == 0) { + e.stopPropagation(); + if (e.shiftKey) { + CollectionDockingView.Instance.StartOtherDrag([docFunc()], e); + } else { + document.addEventListener("pointermove", onRowMove); + document.addEventListener("pointerup", onRowUp); + } + } + //} + }; + return onItemDown; } export namespace DragManager { - export function Root() { - const root = document.getElementById("root"); - if (!root) { - throw new Error("No root element found"); + export function Root() { + const root = document.getElementById("root"); + if (!root) { + throw new Error("No root element found"); + } + return root; } - return root; - } - let dragDiv: HTMLDivElement; + let dragDiv: HTMLDivElement; - export enum DragButtons { - Left = 1, - Right = 2, - Both = Left | Right - } + export enum DragButtons { + Left = 1, + Right = 2, + Both = Left | Right + } - interface DragOptions { - handlers: DragHandlers; + interface DragOptions { + handlers: DragHandlers; - hideSource: boolean | (() => boolean); - } + hideSource: boolean | (() => boolean); + } - export interface DragDropDisposer { - (): void; - } + export interface DragDropDisposer { + (): void; + } - export class DragCompleteEvent {} + export class DragCompleteEvent { } - export interface DragHandlers { - dragComplete: (e: DragCompleteEvent) => void; - } + export interface DragHandlers { + dragComplete: (e: DragCompleteEvent) => void; + } - export interface DropOptions { - handlers: DropHandlers; - } - export class DropEvent { - constructor( - readonly x: number, - readonly y: number, - readonly data: { [id: string]: any } - ) {} - } + export interface DropOptions { + handlers: DropHandlers; + } + export class DropEvent { + constructor( + readonly x: number, + readonly y: number, + readonly data: { [id: string]: any } + ) { } + } - export interface DropHandlers { - drop: (e: Event, de: DropEvent) => void; - } + export interface DropHandlers { + drop: (e: Event, de: DropEvent) => void; + } - export function MakeDropTarget( - element: HTMLElement, - options: DropOptions - ): DragDropDisposer { - if ("canDrop" in element.dataset) { - throw new Error( - "Element is already droppable, can't make it droppable again" - ); + export function MakeDropTarget( + element: HTMLElement, + options: DropOptions + ): DragDropDisposer { + if ("canDrop" in element.dataset) { + throw new Error( + "Element is already droppable, can't make it droppable again" + ); + } + element.dataset["canDrop"] = "true"; + const handler = (e: Event) => { + const ce = e as CustomEvent; + options.handlers.drop(e, ce.detail); + }; + element.addEventListener("dashOnDrop", handler); + return () => { + element.removeEventListener("dashOnDrop", handler); + delete element.dataset["canDrop"]; + }; } - element.dataset["canDrop"] = "true"; - const handler = (e: Event) => { - const ce = e as CustomEvent; - options.handlers.drop(e, ce.detail); - }; - element.addEventListener("dashOnDrop", handler); - return () => { - element.removeEventListener("dashOnDrop", handler); - delete element.dataset["canDrop"]; - }; - } - export class DocumentDragData { - constructor(dragDoc: Document[]) { - this.draggedDocuments = dragDoc; - this.droppedDocuments = dragDoc; + export class DocumentDragData { + constructor(dragDoc: Document[]) { + this.draggedDocuments = dragDoc; + this.droppedDocuments = dragDoc; + } + draggedDocuments: Document[]; + droppedDocuments: Document[]; + xOffset?: number; + yOffset?: number; + aliasOnDrop?: boolean; + removeDocument?: (collectionDrop: CollectionView) => void; + [id: string]: any; } - draggedDocuments: Document[]; - droppedDocuments: Document[]; - xOffset?: number; - yOffset?: number; - aliasOnDrop?: boolean; - removeDocument?: (collectionDrop: CollectionView) => void; - [id: string]: any; - } - export function StartDocumentDrag( - eles: HTMLElement[], - dragData: DocumentDragData, - options?: DragOptions - ) { - StartDrag( - eles, - dragData, - options, - (dropData: { [id: string]: any }) => - (dropData.droppedDocuments = dragData.aliasOnDrop - ? dragData.draggedDocuments.map(d => d.CreateAlias()) - : dragData.draggedDocuments) - ); - } + export function StartDocumentDrag( + eles: HTMLElement[], + dragData: DocumentDragData, + options?: DragOptions + ) { + StartDrag( + eles, + dragData, + options, + (dropData: { [id: string]: any }) => + (dropData.droppedDocuments = dragData.aliasOnDrop + ? dragData.draggedDocuments.map(d => d.CreateAlias()) + : dragData.draggedDocuments) + ); + } - export class LinkDragData { - constructor(linkSourceDoc: DocumentView) { - this.linkSourceDocumentView = linkSourceDoc; + export class LinkDragData { + constructor(linkSourceDoc: DocumentView) { + this.linkSourceDocumentView = linkSourceDoc; + } + droppedDocuments: Document[] = []; + linkSourceDocumentView: DocumentView; + [id: string]: any; } - linkSourceDocumentView: DocumentView; - [id: string]: any; - } - export function StartLinkDrag( - ele: HTMLElement, - dragData: LinkDragData, - options?: DragOptions - ) { - StartDrag([ele], dragData, options); - } - function StartDrag( - eles: HTMLElement[], - dragData: { [id: string]: any }, - options?: DragOptions, - finishDrag?: (dropData: { [id: string]: any }) => void - ) { - if (!dragDiv) { - dragDiv = document.createElement("div"); - dragDiv.className = "dragManager-dragDiv"; - DragManager.Root().appendChild(dragDiv); + export function StartLinkDrag( + ele: HTMLElement, + dragData: LinkDragData, + options?: DragOptions + ) { + StartDrag([ele], dragData, options); } + function StartDrag( + eles: HTMLElement[], + dragData: { [id: string]: any }, + options?: DragOptions, + finishDrag?: (dropData: { [id: string]: any }) => void + ) { + if (!dragDiv) { + dragDiv = document.createElement("div"); + dragDiv.className = "dragManager-dragDiv"; + DragManager.Root().appendChild(dragDiv); + } - let scaleXs: number[] = []; - let scaleYs: number[] = []; - let xs: number[] = []; - let ys: number[] = []; + let scaleXs: number[] = []; + let scaleYs: number[] = []; + let xs: number[] = []; + let ys: number[] = []; - const docs: Document[] = - dragData instanceof DocumentDragData ? dragData.draggedDocuments : []; - let dragElements = eles.map(ele => { - const w = ele.offsetWidth, - h = ele.offsetHeight; - const rect = ele.getBoundingClientRect(); - const scaleX = rect.width / w, - scaleY = rect.height / h; - let x = rect.left, - y = rect.top; - xs.push(x); - ys.push(y); - scaleXs.push(scaleX); - scaleYs.push(scaleY); - let dragElement = ele.cloneNode(true) as HTMLElement; - dragElement.style.opacity = "0.7"; - dragElement.style.position = "absolute"; - dragElement.style.bottom = ""; - dragElement.style.left = ""; - dragElement.style.transformOrigin = "0 0"; - dragElement.style.zIndex = "1000"; - dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`; - dragElement.style.width = `${rect.width / scaleX}px`; - dragElement.style.height = `${rect.height / scaleY}px`; + const docs: Document[] = + dragData instanceof DocumentDragData ? dragData.draggedDocuments : []; + let dragElements = eles.map(ele => { + const w = ele.offsetWidth, + h = ele.offsetHeight; + const rect = ele.getBoundingClientRect(); + const scaleX = rect.width / w, + scaleY = rect.height / h; + let x = rect.left, + y = rect.top; + xs.push(x); + ys.push(y); + scaleXs.push(scaleX); + scaleYs.push(scaleY); + let dragElement = ele.cloneNode(true) as HTMLElement; + dragElement.style.opacity = "0.7"; + dragElement.style.position = "absolute"; + dragElement.style.margin = "0"; + dragElement.style.top = "0"; + dragElement.style.bottom = ""; + dragElement.style.left = "0"; + dragElement.style.transformOrigin = "0 0"; + dragElement.style.zIndex = "1000"; + dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`; + dragElement.style.width = `${rect.width / scaleX}px`; + dragElement.style.height = `${rect.height / scaleY}px`; - // bcz: PDFs don't show up if you clone them because they contain a canvas. - // however, PDF's have a thumbnail field that contains an image of their canvas. - // So we replace the pdf's canvas with the image thumbnail - if (docs.length) { - var pdfBox = dragElement.getElementsByClassName( - "pdfBox-cont" - )[0] as HTMLElement; - let thumbnail = docs[0].GetT(KeyStore.Thumbnail, ImageField); - if (pdfBox && pdfBox.childElementCount && thumbnail) { - let img = new Image(); - img!.src = thumbnail.toString(); - img!.style.position = "absolute"; - img!.style.width = `${rect.width / scaleX}px`; - img!.style.height = `${rect.height / scaleY}px`; - pdfBox.replaceChild(img!, pdfBox.children[0]); + // bcz: PDFs don't show up if you clone them because they contain a canvas. + // however, PDF's have a thumbnail field that contains an image of their canvas. + // So we replace the pdf's canvas with the image thumbnail + if (docs.length) { + var pdfBox = dragElement.getElementsByClassName( + "pdfBox-cont" + )[0] as HTMLElement; + let thumbnail = docs[0].GetT(KeyStore.Thumbnail, ImageField); + if (pdfBox && pdfBox.childElementCount && thumbnail) { + let img = new Image(); + img!.src = thumbnail.toString(); + img!.style.position = "absolute"; + img!.style.width = `${rect.width / scaleX}px`; + img!.style.height = `${rect.height / scaleY}px`; + pdfBox.replaceChild(img!, pdfBox.children[0]); + } + } + + dragDiv.appendChild(dragElement); + return dragElement; + }); + + let hideSource = false; + if (options) { + if (typeof options.hideSource === "boolean") { + hideSource = options.hideSource; + } else { + hideSource = options.hideSource(); + } } - } + eles.map(ele => (ele.hidden = hideSource)); - dragDiv.appendChild(dragElement); - return dragElement; - }); + const moveHandler = (e: PointerEvent) => { + e.stopPropagation(); + e.preventDefault(); + if (dragData instanceof DocumentDragData) + dragData.aliasOnDrop = e.ctrlKey || e.altKey; + if (e.shiftKey) { + abortDrag(); + CollectionDockingView.Instance.StartOtherDrag(docs, { + pageX: e.pageX, + pageY: e.pageY, + preventDefault: () => { }, + button: 0 + }); + } + dragElements.map( + (dragElement, i) => + (dragElement.style.transform = `translate(${(xs[i] += + e.movementX)}px, ${(ys[i] += e.movementY)}px) scale(${ + scaleXs[i] + }, ${scaleYs[i]})`) + ); + }; - let hideSource = false; - if (options) { - if (typeof options.hideSource === "boolean") { - hideSource = options.hideSource; - } else { - hideSource = options.hideSource(); - } + const abortDrag = () => { + document.removeEventListener("pointermove", moveHandler, true); + document.removeEventListener("pointerup", upHandler); + dragElements.map(dragElement => dragDiv.removeChild(dragElement)); + eles.map(ele => (ele.hidden = false)); + }; + const upHandler = (e: PointerEvent) => { + abortDrag(); + FinishDrag(eles, e, dragData, options, finishDrag); + }; + document.addEventListener("pointermove", moveHandler, true); + document.addEventListener("pointerup", upHandler); } - eles.map(ele => (ele.hidden = hideSource)); - const moveHandler = (e: PointerEvent) => { - e.stopPropagation(); - e.preventDefault(); - if (dragData instanceof DocumentDragData) - dragData.aliasOnDrop = e.ctrlKey || e.altKey; - if (e.shiftKey) { - abortDrag(); - CollectionDockingView.Instance.StartOtherDrag(docs, { - pageX: e.pageX, - pageY: e.pageY, - preventDefault: () => {}, - button: 0 + function FinishDrag( + dragEles: HTMLElement[], + e: PointerEvent, + dragData: { [index: string]: any }, + options?: DragOptions, + finishDrag?: (dragData: { [index: string]: any }) => void + ) { + let removed = dragEles.map(dragEle => { + let parent = dragEle.parentElement; + if (parent) parent.removeChild(dragEle); + return [dragEle, parent]; }); - } - dragElements.map( - (dragElement, i) => - (dragElement.style.transform = `translate(${(xs[i] += - e.movementX)}px, ${(ys[i] += e.movementY)}px) scale(${ - scaleXs[i] - }, ${scaleYs[i]})`) - ); - }; - - const abortDrag = () => { - document.removeEventListener("pointermove", moveHandler, true); - document.removeEventListener("pointerup", upHandler); - dragElements.map(dragElement => dragDiv.removeChild(dragElement)); - eles.map(ele => (ele.hidden = false)); - }; - const upHandler = (e: PointerEvent) => { - abortDrag(); - FinishDrag(eles, e, dragData, options, finishDrag); - }; - document.addEventListener("pointermove", moveHandler, true); - document.addEventListener("pointerup", upHandler); - } - - function FinishDrag( - dragEles: HTMLElement[], - e: PointerEvent, - dragData: { [index: string]: any }, - options?: DragOptions, - finishDrag?: (dragData: { [index: string]: any }) => void - ) { - let removed = dragEles.map(dragEle => { - let parent = dragEle.parentElement; - if (parent) parent.removeChild(dragEle); - return [dragEle, parent]; - }); - const target = document.elementFromPoint(e.x, e.y); - removed.map(r => { - let dragEle: HTMLElement = r[0]!; - let parent: HTMLElement | null = r[1]; - if (parent) parent.appendChild(dragEle); - }); - if (target) { - if (finishDrag) finishDrag(dragData); + const target = document.elementFromPoint(e.x, e.y); + removed.map(r => { + let dragEle: HTMLElement = r[0]!; + let parent: HTMLElement | null = r[1]; + if (parent) parent.appendChild(dragEle); + }); + if (target) { + if (finishDrag) finishDrag(dragData); - target.dispatchEvent( - new CustomEvent("dashOnDrop", { - bubbles: true, - detail: { - x: e.x, - y: e.y, - data: dragData - } - }) - ); + target.dispatchEvent( + new CustomEvent("dashOnDrop", { + bubbles: true, + detail: { + x: e.x, + y: e.y, + data: dragData + } + }) + ); - if (options) { - options.handlers.dragComplete({}); - } + if (options) { + options.handlers.dragComplete({}); + } + } + DocumentDecorations.Instance.Hidden = false; } - DocumentDecorations.Instance.Hidden = false; - } } diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 438659108..958c14491 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -3,48 +3,46 @@ import { DocumentView } from "../views/nodes/DocumentView"; import { Document } from "../../fields/Document"; export namespace SelectionManager { - class Manager { - @observable - SelectedDocuments: Array = []; - - @action - SelectDoc(doc: DocumentView, ctrlPressed: boolean): void { - // if doc is not in SelectedDocuments, add it - if (!ctrlPressed) { - manager.SelectedDocuments = []; - } - - if (manager.SelectedDocuments.indexOf(doc) === -1) { - manager.SelectedDocuments.push(doc); - } + class Manager { + @observable + SelectedDocuments: Array = []; + + @action + SelectDoc(doc: DocumentView, ctrlPressed: boolean): void { + // if doc is not in SelectedDocuments, add it + if (!ctrlPressed) { + manager.SelectedDocuments = []; + } + + if (manager.SelectedDocuments.indexOf(doc) === -1) { + manager.SelectedDocuments.push(doc); + } + } } - } - const manager = new Manager(); + const manager = new Manager(); - export function SelectDoc(doc: DocumentView, ctrlPressed: boolean): void { - if (!doc.isMinimized()) { - manager.SelectDoc(doc, ctrlPressed); + export function SelectDoc(doc: DocumentView, ctrlPressed: boolean): void { + manager.SelectDoc(doc, ctrlPressed); } - } - - export function IsSelected(doc: DocumentView): boolean { - return manager.SelectedDocuments.indexOf(doc) !== -1; - } - - export function DeselectAll(except?: Document): void { - let found: DocumentView | undefined = undefined; - if (except) { - for (let i = 0; i < manager.SelectedDocuments.length; i++) { - let view = manager.SelectedDocuments[i]; - if (view.props.Document == except) found = view; - } + + export function IsSelected(doc: DocumentView): boolean { + return manager.SelectedDocuments.indexOf(doc) !== -1; + } + + export function DeselectAll(except?: Document): void { + let found: DocumentView | undefined = undefined; + if (except) { + for (let i = 0; i < manager.SelectedDocuments.length; i++) { + let view = manager.SelectedDocuments[i]; + if (view.props.Document == except) found = view; + } + } + manager.SelectedDocuments.length = 0; + if (found) manager.SelectedDocuments.push(found); } - manager.SelectedDocuments.length = 0; - if (found) manager.SelectedDocuments.push(found); - } - export function SelectedDocuments(): Array { - return manager.SelectedDocuments; - } + export function SelectedDocuments(): Array { + return manager.SelectedDocuments; + } } diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss index befe175b5..080c9fa1e 100644 --- a/src/client/views/DocumentDecorations.scss +++ b/src/client/views/DocumentDecorations.scss @@ -2,13 +2,16 @@ #documentDecorations-container { position: absolute; + top: 0; + left:0; display: grid; z-index: 1000; grid-template-rows: 20px 8px 1fr 8px; - grid-template-columns: 8px 1fr 8px; + grid-template-columns: 8px 8px 1fr 8px; pointer-events: none; #documentDecorations-centerCont { + grid-column:3; background: none; } @@ -18,6 +21,24 @@ opacity: 0.8; } + #documentDecorations-topLeftResizer, + #documentDecorations-leftResizer, + #documentDecorations-bottomLeftResizer { + grid-column: 1 + } + + #documentDecorations-topResizer, + #documentDecorations-bottomResizer { + grid-column-start: 2; + grid-column-end: 4; + } + + #documentDecorations-bottomRightResizer, + #documentDecorations-topRightResizer, + #documentDecorations-rightResizer { + grid-column:4 + } + #documentDecorations-topLeftResizer, #documentDecorations-bottomRightResizer { cursor: nwse-resize; @@ -39,15 +60,19 @@ } .title{ background: lightblue; - grid-column-start:2; - grid-column-end: 4; + grid-column-start:3; + grid-column-end: 5; pointer-events: auto; } } .documentDecorations-minimizeButton { - background: rgb(250, 57, 9); + background:$alt-accent; + opacity: 0.8; + grid-column-start: 1; + grid-column-end: 3; pointer-events: all; + text-align: center; } .documentDecorations-background { background: lightblue; @@ -87,7 +112,8 @@ // } // } .linkFlyout { - grid-column: 1/4 + grid-column: 1/4; + margin-left: 25px; } .linkButton-empty:hover { @@ -102,6 +128,31 @@ cursor: pointer; } +.linkButton-linker { + position:absolute; + bottom:0px; + left: 0px; + height: 20px; + width: 20px; + margin-top: 10px; + margin-right: 5px; + border-radius: 50%; + opacity: 0.9; + pointer-events: auto; + color: $dark-color; + border: $dark-color 1px solid; + text-transform: uppercase; + letter-spacing: 2px; + font-size: 75%; + transition: transform 0.2s; + text-align: center; + display: flex; + justify-content: center; + align-items: center; +} +.linkButton-tray { + grid-column: 1/4; +} .linkButton-empty { height: 20px; width: 20px; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index b74737ec9..a46087c9a 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -1,10 +1,11 @@ -import { action, computed, observable } from "mobx"; +import { action, computed, observable, trace, runInAction } from "mobx"; import { observer } from "mobx-react"; import { Key } from "../../fields/Key"; //import ContentEditable from 'react-contenteditable' import { KeyStore } from "../../fields/KeyStore"; import { ListField } from "../../fields/ListField"; import { NumberField } from "../../fields/NumberField"; +import { Document } from "../../fields/Document"; import { TextField } from "../../fields/TextField"; import { DragManager } from "../util/DragManager"; import { SelectionManager } from "../util/SelectionManager"; @@ -13,6 +14,7 @@ import './DocumentDecorations.scss'; import { DocumentView } from "./nodes/DocumentView"; import { LinkMenu } from "./nodes/LinkMenu"; import React = require("react"); +import { FieldWaiting } from "../../fields/Field"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -28,6 +30,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> private _linkBoxHeight = 30; private _titleHeight = 20; private _linkButton = React.createRef(); + private _linkerButton = React.createRef(); //@observable private _title: string = this._documents[0].props.Document.Title; @observable private _title: string = this._documents.length > 0 ? this._documents[0].props.Document.Title : ""; @observable private _fieldKey: Key = KeyStore.Title; @@ -174,18 +177,40 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> } } - onLinkButtonDown = (e: React.PointerEvent): void => { - // if () - // let linkMenu = new LinkMenu(SelectionManager.SelectedDocuments()[0]); - // linkMenu.Hidden = false; - console.log("down"); + onLinkerButtonDown = (e: React.PointerEvent): void => { + e.stopPropagation(); + document.removeEventListener("pointermove", this.onLinkerButtonMoved) + document.addEventListener("pointermove", this.onLinkerButtonMoved); + document.removeEventListener("pointerup", this.onLinkerButtonUp) + document.addEventListener("pointerup", this.onLinkerButtonUp); + } + onLinkerButtonUp = (e: PointerEvent): void => { + document.removeEventListener("pointermove", this.onLinkerButtonMoved) + document.removeEventListener("pointerup", this.onLinkerButtonUp) + e.stopPropagation(); + } + onLinkerButtonMoved = (e: PointerEvent): void => { + if (this._linkerButton.current != null) { + document.removeEventListener("pointermove", this.onLinkerButtonMoved) + document.removeEventListener("pointerup", this.onLinkerButtonUp) + let dragData = new DragManager.LinkDragData(SelectionManager.SelectedDocuments()[0]); + DragManager.StartLinkDrag(this._linkerButton.current, dragData, { + handlers: { + dragComplete: action(() => { }), + }, + hideSource: false + }) + } + e.stopPropagation(); + } + + onLinkButtonDown = (e: React.PointerEvent): void => { e.stopPropagation(); document.removeEventListener("pointermove", this.onLinkButtonMoved) document.addEventListener("pointermove", this.onLinkButtonMoved); document.removeEventListener("pointerup", this.onLinkButtonUp) document.addEventListener("pointerup", this.onLinkButtonUp); - } onLinkButtonUp = (e: PointerEvent): void => { @@ -194,18 +219,32 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> e.stopPropagation(); } - onLinkButtonMoved = (e: PointerEvent): void => { if (this._linkButton.current != null) { document.removeEventListener("pointermove", this.onLinkButtonMoved) - document.removeEventListener("pointerup", this.onLinkButtonUp) - let dragData = new DragManager.LinkDragData(SelectionManager.SelectedDocuments()[0]); - DragManager.StartLinkDrag(this._linkButton.current, dragData, { - handlers: { - dragComplete: action(() => { }), - }, - hideSource: false - }) + document.removeEventListener("pointerup", this.onLinkButtonUp); + + let sourceDoc = SelectionManager.SelectedDocuments()[0].props.Document; + let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document) + let draggedDocs = (srcTarg && srcTarg != FieldWaiting) ? + srcTarg.GetList(KeyStore.LinkedToDocs, [] as Document[]).map(linkDoc => + (linkDoc.GetT(KeyStore.LinkedToDocs, Document)) as Document) : []; + let draggedFromDocs = (srcTarg && srcTarg != FieldWaiting) ? + srcTarg.GetList(KeyStore.LinkedFromDocs, [] as Document[]).map(linkDoc => + (linkDoc.GetT(KeyStore.LinkedFromDocs, Document)) as Document) : []; + draggedDocs.push(...draggedFromDocs); + if (draggedDocs.length) { + let dragData = new DragManager.DocumentDragData(draggedDocs.map(d => { + let annot = d.GetT(KeyStore.AnnotationOn, Document); // bcz: ... needs to change ... the annotationOn document may not have been retrieved yet... + return annot && annot != FieldWaiting ? annot : d; + })); + DragManager.StartDocumentDrag([this._linkButton.current], dragData, { + handlers: { + dragComplete: action(() => { }), + }, + hideSource: false + }) + } } e.stopPropagation(); } @@ -298,7 +337,6 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> } getValue = (): string => { - console.log("value watched"); if (this._title === "changed" && this._documents.length > 0) { let field = this._documents[0].props.Document.Get(this._fieldKey); if (field instanceof TextField) { @@ -338,8 +376,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> linkButton = ( - + }>
{linkCount}
); @@ -361,7 +398,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> top: bounds.y - this._resizeBorderWidth / 2 - this._titleHeight, opacity: this._opacity }}> -
v
+
...
e.preventDefault()}>
e.preventDefault()}>
@@ -373,8 +410,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
e.preventDefault()}>
e.preventDefault()}>
-
{linkButton}
- +
{linkButton}
+
∞
) diff --git a/src/client/views/InkingCanvas.scss b/src/client/views/InkingCanvas.scss index 35c8ee942..c5a2a50cb 100644 --- a/src/client/views/InkingCanvas.scss +++ b/src/client/views/InkingCanvas.scss @@ -2,6 +2,8 @@ .inkingCanvas-paths-ink, .inkingCanvas-paths-markers, .inkingCanvas-noSelect, .inkingCanvas-canSelect { position: absolute; + top: 0; + left:0; width: 8192px; height: 8192px; cursor:"crosshair"; diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss index 698a9c617..594803aab 100644 --- a/src/client/views/Main.scss +++ b/src/client/views/Main.scss @@ -7,6 +7,9 @@ body { overflow: hidden; font-family: $sans-serif; margin: 0; + position:absolute; + top: 0; + left:0; } #dash-title { @@ -158,11 +161,15 @@ button:hover { width:100%; height:100%; position:absolute; + top: 0; + left:0; } #mainContent-div { width:100%; height:100%; position:absolute; + top: 0; + left:0; } #add-options-content { display: table; diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss index 2706c3272..583d50c5b 100644 --- a/src/client/views/collections/CollectionDockingView.scss +++ b/src/client/views/collections/CollectionDockingView.scss @@ -3,7 +3,7 @@ } .collectiondockingview-container { - position: relative; + position: absolute; top: 0; left: 0; overflow: hidden; diff --git a/src/client/views/collections/CollectionPDFView.scss b/src/client/views/collections/CollectionPDFView.scss index 0144625c1..0eca3f1cd 100644 --- a/src/client/views/collections/CollectionPDFView.scss +++ b/src/client/views/collections/CollectionPDFView.scss @@ -9,6 +9,8 @@ width: 100%; height: 100%; position: absolute; + top: 0; + left:0; } .collectionPdfView-backward { diff --git a/src/client/views/collections/CollectionVideoView.scss b/src/client/views/collections/CollectionVideoView.scss index cbb981b13..ed56ad268 100644 --- a/src/client/views/collections/CollectionVideoView.scss +++ b/src/client/views/collections/CollectionVideoView.scss @@ -3,6 +3,8 @@ width: 100%; height: 100%; position: absolute; + top: 0; + left:0; } .collectionVideoView-time{ diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx index 2b0689800..daeca69e2 100644 --- a/src/client/views/collections/CollectionViewBase.tsx +++ b/src/client/views/collections/CollectionViewBase.tsx @@ -17,6 +17,8 @@ import { NumberField } from "../../../fields/NumberField"; import request = require("request"); import { ServerUtils } from "../../../server/ServerUtil"; import { Server } from "../../Server"; +import { CollectionDockingView } from "./CollectionDockingView"; +import { runReactions } from "mobx/lib/internal"; export interface CollectionViewProps { fieldKey: Key; @@ -92,6 +94,24 @@ export class CollectionViewBase extends React.Component e.stopPropagation(); return added; } + if (de.data instanceof DragManager.LinkDragData) { + let sourceDoc: Document = de.data.linkSourceDocumentView.props.Document; + if (sourceDoc) runInAction(() => { + let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document) + if (srcTarg && srcTarg != FieldWaiting) { + let linkDocs = srcTarg.GetList(KeyStore.LinkedToDocs, [] as Document[]); + linkDocs.map(linkDoc => { + let targDoc = linkDoc.GetT(KeyStore.LinkedToDocs, Document); + if (targDoc && targDoc != FieldWaiting) { + let dropdoc = targDoc.MakeDelegate(); + de.data.droppedDocuments.push(dropdoc); + this.props.addDocument(dropdoc, false); + } + }) + } + }) + return true; + } return false; } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index e84f0c5ad..3dfd74ec8 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -23,10 +23,10 @@ export class CollectionFreeFormLinkView extends React.Component { if (super.drop(e, de)) { - if (de.data instanceof DragManager.DocumentDragData) { - let screenX = de.x - (de.data.xOffset as number || 0); - let screenY = de.y - (de.data.yOffset as number || 0); + let droppedDocs = de.data.droppedDocuments as Document[]; + let xoff = de.data.xOffset as number || 0; + let yoff = de.data.yOffset as number || 0; + if (droppedDocs && droppedDocs.length) { + let screenX = de.x - xoff; + let screenY = de.y - yoff; const [x, y] = this.getTransform().transformPoint(screenX, screenY); - let dragDoc = de.data.draggedDocuments[0]; + let dragDoc = de.data.droppedDocuments[0]; let dragX = dragDoc.GetNumber(KeyStore.X, 0); let dragY = dragDoc.GetNumber(KeyStore.Y, 0); - de.data.draggedDocuments.map(d => { + droppedDocs.map(d => { let docX = d.GetNumber(KeyStore.X, 0); let docY = d.GetNumber(KeyStore.Y, 0); d.SetNumber(KeyStore.X, x + (docX - dragX)); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.scss b/src/client/views/collections/collectionFreeForm/MarqueeView.scss index 1ee3b244b..0b406e722 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.scss +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.scss @@ -1,6 +1,8 @@ .marqueeView { position: absolute; + top:0; + left:0; width:100%; height:100%; } diff --git a/src/client/views/collections/collectionFreeForm/PreviewCursor.scss b/src/client/views/collections/collectionFreeForm/PreviewCursor.scss index 21210be2b..7a67c29bf 100644 --- a/src/client/views/collections/collectionFreeForm/PreviewCursor.scss +++ b/src/client/views/collections/collectionFreeForm/PreviewCursor.scss @@ -3,9 +3,13 @@ color: black; position: absolute; transform-origin: left top; + top: 0; + left:0; pointer-events: none; } .previewCursorView { + top: 0; + left:0; position: absolute; width:100%; height:100%; diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index d52b662bd..1a0f0cbbd 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -66,8 +66,12 @@ export class CollectionFreeFormDocumentView extends React.Component } + panelWidth = () => this.props.Document.GetBoolean(KeyStore.Minimized, false) ? 10 : this.props.PanelWidth(); + panelHeight = () => this.props.Document.GetBoolean(KeyStore.Minimized, false) ? 10 : this.props.PanelHeight(); render() { return ( diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss index 127a6b535..5126e69f9 100644 --- a/src/client/views/nodes/DocumentView.scss +++ b/src/client/views/nodes/DocumentView.scss @@ -2,6 +2,8 @@ .documentView-node { position: absolute; + top: 0; + left:0; background: $light-color; //overflow: hidden; &.minimized { diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss index ad947afd5..830dfe6c6 100644 --- a/src/client/views/nodes/PDFBox.scss +++ b/src/client/views/nodes/PDFBox.scss @@ -1,12 +1,16 @@ .react-pdf__Page { transform-origin: left top; position: absolute; + top: 0; + left:0; } .react-pdf__Document { position: absolute; } .pdfBox-buttonTray { position:absolute; + top: 0; + left:0; z-index: 25; } .pdfBox-contentContainer { diff --git a/src/client/views/nodes/WebBox.scss b/src/client/views/nodes/WebBox.scss index a535b2638..c73bc0c47 100644 --- a/src/client/views/nodes/WebBox.scss +++ b/src/client/views/nodes/WebBox.scss @@ -2,6 +2,8 @@ .webBox-cont { padding: 0vw; position: absolute; + top: 0; + left:0; width: 100%; height: 100%; overflow: scroll; diff --git a/src/fields/Document.ts b/src/fields/Document.ts index 8e71019a4..92d03d765 100644 --- a/src/fields/Document.ts +++ b/src/fields/Document.ts @@ -9,415 +9,420 @@ import { Server } from "../client/Server"; import { Types } from "../server/Message"; import { UndoManager } from "../client/util/UndoManager"; import { HtmlField } from "./HtmlField"; +import { BooleanField } from "./BooleanField"; export class Document extends Field { - //TODO tfs: We should probably store FieldWaiting in fields when we request it from the server so that we don't set up multiple server gets for the same document and field - public fields: ObservableMap< - string, - { key: Key; field: Field } - > = new ObservableMap(); - public _proxies: ObservableMap = new ObservableMap(); - - constructor(id?: string, save: boolean = true) { - super(id); - - if (save) { - Server.UpdateField(this); + //TODO tfs: We should probably store FieldWaiting in fields when we request it from the server so that we don't set up multiple server gets for the same document and field + public fields: ObservableMap< + string, + { key: Key; field: Field } + > = new ObservableMap(); + public _proxies: ObservableMap = new ObservableMap(); + + constructor(id?: string, save: boolean = true) { + super(id); + + if (save) { + Server.UpdateField(this); + } } - } - UpdateFromServer(data: [string, string][]) { - for (const key in data) { - const element = data[key]; - this._proxies.set(element[0], element[1]); - } - } - - public Width = () => { - return this.GetNumber(KeyStore.Width, 0); - }; - public Height = () => { - return this.GetNumber( - KeyStore.Height, - this.GetNumber(KeyStore.NativeWidth, 0) - ? (this.GetNumber(KeyStore.NativeHeight, 0) / - this.GetNumber(KeyStore.NativeWidth, 0)) * - this.GetNumber(KeyStore.Width, 0) - : 0 - ); - }; - public Scale = () => { - return this.GetNumber(KeyStore.Scale, 1); - }; - - @computed - public get Title(): string { - let title = this.Get(KeyStore.Title, true); - if (title) - if (title != FieldWaiting && title instanceof TextField) - return title.Data; - else return "-waiting-"; - let parTitle = this.GetT(KeyStore.Title, TextField); - if (parTitle) - if (parTitle != FieldWaiting) return parTitle.Data + ".alias"; - else return "-waiting-.alias"; - return "-untitled-"; - } - - @computed - public get Fields() { - return this.fields; - } - - /** - * Get the field in the document associated with the given key. If the - * associated field has not yet been filled in from the server, a request - * to the server will automatically be sent, the value will be filled in - * when the request is completed, and {@link Field.ts#FieldWaiting} will be returned. - * @param key - The key of the value to get - * @param ignoreProto - If true, ignore any prototype this document - * might have and only search for the value on this immediate document. - * If false (default), search up the prototype chain, starting at this document, - * for a document that has a field associated with the given key, and return the first - * one found. - * - * @returns If the document does not have a field associated with the given key, returns `undefined`. - * If the document does have an associated field, but the field has not been fetched from the server, returns {@link Field.ts#FieldWaiting}. - * If the document does have an associated field, and the field has not been fetched from the server, returns the associated field. - */ - Get(key: Key, ignoreProto: boolean = false): FieldValue { - let field: FieldValue; - if (ignoreProto) { - if (this.fields.has(key.Id)) { - field = this.fields.get(key.Id)!.field; - } else if (this._proxies.has(key.Id)) { - Server.GetDocumentField(this, key); - /* - The field might have been instantly filled from the cache - Maybe we want to just switch back to returning the value - from Server.GetDocumentField if it's in the cache - */ - if (this.fields.has(key.Id)) { - field = this.fields.get(key.Id)!.field; - } else { - field = FieldWaiting; + UpdateFromServer(data: [string, string][]) { + for (const key in data) { + const element = data[key]; + this._proxies.set(element[0], element[1]); } - } - } else { - let doc: FieldValue = this; - while (doc && doc != FieldWaiting && field != FieldWaiting) { - let curField = doc.fields.get(key.Id); - let curProxy = doc._proxies.get(key.Id); - if (!curField || (curProxy && curField.field.Id !== curProxy)) { - if (curProxy) { - Server.GetDocumentField(doc, key); - /* + } + + public Width = () => { + return this.GetNumber(KeyStore.Width, 0); + }; + public Height = () => { + return this.GetNumber( + KeyStore.Height, + this.GetNumber(KeyStore.NativeWidth, 0) + ? (this.GetNumber(KeyStore.NativeHeight, 0) / + this.GetNumber(KeyStore.NativeWidth, 0)) * + this.GetNumber(KeyStore.Width, 0) + : 0 + ); + }; + public Scale = () => { + return this.GetNumber(KeyStore.Scale, 1); + }; + + @computed + public get Title(): string { + let title = this.Get(KeyStore.Title, true); + if (title) + if (title != FieldWaiting && title instanceof TextField) + return title.Data; + else return "-waiting-"; + let parTitle = this.GetT(KeyStore.Title, TextField); + if (parTitle) + if (parTitle != FieldWaiting) return parTitle.Data + ".alias"; + else return "-waiting-.alias"; + return "-untitled-"; + } + + @computed + public get Fields() { + return this.fields; + } + + /** + * Get the field in the document associated with the given key. If the + * associated field has not yet been filled in from the server, a request + * to the server will automatically be sent, the value will be filled in + * when the request is completed, and {@link Field.ts#FieldWaiting} will be returned. + * @param key - The key of the value to get + * @param ignoreProto - If true, ignore any prototype this document + * might have and only search for the value on this immediate document. + * If false (default), search up the prototype chain, starting at this document, + * for a document that has a field associated with the given key, and return the first + * one found. + * + * @returns If the document does not have a field associated with the given key, returns `undefined`. + * If the document does have an associated field, but the field has not been fetched from the server, returns {@link Field.ts#FieldWaiting}. + * If the document does have an associated field, and the field has not been fetched from the server, returns the associated field. + */ + Get(key: Key, ignoreProto: boolean = false): FieldValue { + let field: FieldValue; + if (ignoreProto) { + if (this.fields.has(key.Id)) { + field = this.fields.get(key.Id)!.field; + } else if (this._proxies.has(key.Id)) { + Server.GetDocumentField(this, key); + /* The field might have been instantly filled from the cache Maybe we want to just switch back to returning the value from Server.GetDocumentField if it's in the cache */ - if (this.fields.has(key.Id)) { - field = this.fields.get(key.Id)!.field; - } else { - field = FieldWaiting; + if (this.fields.has(key.Id)) { + field = this.fields.get(key.Id)!.field; + } else { + field = FieldWaiting; + } } - break; - } - if ( - doc.fields.has(KeyStore.Prototype.Id) || - doc._proxies.has(KeyStore.Prototype.Id) - ) { - doc = doc.GetPrototype(); - } else { - break; - } } else { - field = curField.field; - break; + let doc: FieldValue = this; + while (doc && doc != FieldWaiting && field != FieldWaiting) { + let curField = doc.fields.get(key.Id); + let curProxy = doc._proxies.get(key.Id); + if (!curField || (curProxy && curField.field.Id !== curProxy)) { + if (curProxy) { + Server.GetDocumentField(doc, key); + /* + The field might have been instantly filled from the cache + Maybe we want to just switch back to returning the value + from Server.GetDocumentField if it's in the cache + */ + if (this.fields.has(key.Id)) { + field = this.fields.get(key.Id)!.field; + } else { + field = FieldWaiting; + } + break; + } + if ( + doc.fields.has(KeyStore.Prototype.Id) || + doc._proxies.has(KeyStore.Prototype.Id) + ) { + doc = doc.GetPrototype(); + } else { + break; + } + } else { + field = curField.field; + break; + } + } + if (doc == FieldWaiting) field = FieldWaiting; } - } - if (doc == FieldWaiting) field = FieldWaiting; + + return field; } - return field; - } - - /** - * Tries to get the field associated with the given key, and if there is an - * associated field, calls the given callback with that field. - * @param key - The key of the value to get - * @param callback - A function that will be called with the associated field, if it exists, - * once it is fetched from the server (this may be immediately if the field has already been fetched). - * Note: The callback will not be called if there is no associated field. - * @returns `true` if the field exists on the document and `callback` will be called, and `false` otherwise - */ - GetAsync(key: Key, callback: (field: Opt) => void): void { - //TODO: This currently doesn't deal with prototypes - let field = this.fields.get(key.Id); - if (field && field.field) { - callback(field.field); - } else if (this._proxies.has(key.Id)) { - Server.GetDocumentField(this, key, callback); - } else if (this._proxies.has(KeyStore.Prototype.Id)) { - this.GetTAsync(KeyStore.Prototype, Document, proto => { - if (proto) { - proto.GetAsync(key, callback); + /** + * Tries to get the field associated with the given key, and if there is an + * associated field, calls the given callback with that field. + * @param key - The key of the value to get + * @param callback - A function that will be called with the associated field, if it exists, + * once it is fetched from the server (this may be immediately if the field has already been fetched). + * Note: The callback will not be called if there is no associated field. + * @returns `true` if the field exists on the document and `callback` will be called, and `false` otherwise + */ + GetAsync(key: Key, callback: (field: Opt) => void): void { + //TODO: This currently doesn't deal with prototypes + let field = this.fields.get(key.Id); + if (field && field.field) { + callback(field.field); + } else if (this._proxies.has(key.Id)) { + Server.GetDocumentField(this, key, callback); + } else if (this._proxies.has(KeyStore.Prototype.Id)) { + this.GetTAsync(KeyStore.Prototype, Document, proto => { + if (proto) { + proto.GetAsync(key, callback); + } else { + callback(undefined); + } + }); } else { - callback(undefined); + callback(undefined); } - }); - } else { - callback(undefined); } - } - - GetTAsync(key: Key, ctor: { new (): T }): Promise>; - GetTAsync( - key: Key, - ctor: { new (): T }, - callback: (field: Opt) => void - ): void; - GetTAsync( - key: Key, - ctor: { new (): T }, - callback?: (field: Opt) => void - ): Promise> | void { - let fn = (cb: (field: Opt) => void) => { - return this.GetAsync(key, field => { - cb(Cast(field, ctor)); - }); - }; - if (callback) { - fn(callback); - } else { - return new Promise(res => fn(res)); + + GetTAsync(key: Key, ctor: { new(): T }): Promise>; + GetTAsync( + key: Key, + ctor: { new(): T }, + callback: (field: Opt) => void + ): void; + GetTAsync( + key: Key, + ctor: { new(): T }, + callback?: (field: Opt) => void + ): Promise> | void { + let fn = (cb: (field: Opt) => void) => { + return this.GetAsync(key, field => { + cb(Cast(field, ctor)); + }); + }; + if (callback) { + fn(callback); + } else { + return new Promise(res => fn(res)); + } } - } - - /** - * Same as {@link Document#GetAsync}, except a field of the given type - * will be created if there is no field associated with the given key, - * or the field associated with the given key is not of the given type. - * @param ctor - Constructor of the field type to get. E.g., TextField, ImageField, etc. - */ - GetOrCreateAsync( - key: Key, - ctor: { new (): T }, - callback: (field: T) => void - ): void { - //This currently doesn't deal with prototypes - if (this._proxies.has(key.Id)) { - Server.GetDocumentField(this, key, field => { - if (field && field instanceof ctor) { - callback(field); + + /** + * Same as {@link Document#GetAsync}, except a field of the given type + * will be created if there is no field associated with the given key, + * or the field associated with the given key is not of the given type. + * @param ctor - Constructor of the field type to get. E.g., TextField, ImageField, etc. + */ + GetOrCreateAsync( + key: Key, + ctor: { new(): T }, + callback: (field: T) => void + ): void { + //This currently doesn't deal with prototypes + if (this._proxies.has(key.Id)) { + Server.GetDocumentField(this, key, field => { + if (field && field instanceof ctor) { + callback(field); + } else { + let newField = new ctor(); + this.Set(key, newField); + callback(newField); + } + }); } else { - let newField = new ctor(); - this.Set(key, newField); - callback(newField); + let newField = new ctor(); + this.Set(key, newField); + callback(newField); } - }); - } else { - let newField = new ctor(); - this.Set(key, newField); - callback(newField); } - } - - /** - * Same as {@link Document#Get}, except that it will additionally - * check if the field is of the given type. - * @param ctor - Constructor of the field type to get. E.g., `TextField`, `ImageField`, etc. - * @returns Same as {@link Document#Get}, except will return `undefined` - * if there is an associated field but it is of the wrong type. - */ - GetT( - key: Key, - ctor: { new (...args: any[]): T }, - ignoreProto: boolean = false - ): FieldValue { - var getfield = this.Get(key, ignoreProto); - if (getfield != FieldWaiting) { - return Cast(getfield, ctor); + + /** + * Same as {@link Document#Get}, except that it will additionally + * check if the field is of the given type. + * @param ctor - Constructor of the field type to get. E.g., `TextField`, `ImageField`, etc. + * @returns Same as {@link Document#Get}, except will return `undefined` + * if there is an associated field but it is of the wrong type. + */ + GetT( + key: Key, + ctor: { new(...args: any[]): T }, + ignoreProto: boolean = false + ): FieldValue { + var getfield = this.Get(key, ignoreProto); + if (getfield != FieldWaiting) { + return Cast(getfield, ctor); + } + return FieldWaiting; } - return FieldWaiting; - } - - GetOrCreate( - key: Key, - ctor: { new (): T }, - ignoreProto: boolean = false - ): T { - const field = this.GetT(key, ctor, ignoreProto); - if (field && field != FieldWaiting) { - return field; + + GetOrCreate( + key: Key, + ctor: { new(): T }, + ignoreProto: boolean = false + ): T { + const field = this.GetT(key, ctor, ignoreProto); + if (field && field != FieldWaiting) { + return field; + } + const newField = new ctor(); + this.Set(key, newField); + return newField; } - const newField = new ctor(); - this.Set(key, newField); - return newField; - } - - GetData( - key: Key, - ctor: { new (): U }, - defaultVal: T - ): T { - let val = this.Get(key); - let vval = val && val instanceof ctor ? val.Data : defaultVal; - return vval; - } - - GetHtml(key: Key, defaultVal: string): string { - return this.GetData(key, HtmlField, defaultVal); - } - - GetNumber(key: Key, defaultVal: number): number { - return this.GetData(key, NumberField, defaultVal); - } - - GetText(key: Key, defaultVal: string): string { - return this.GetData(key, TextField, defaultVal); - } - - GetList(key: Key, defaultVal: T[]): T[] { - return this.GetData>(key, ListField, defaultVal); - } - - @action - Set(key: Key, field: Field | undefined, setOnPrototype = false): void { - let old = this.fields.get(key.Id); - let oldField = old ? old.field : undefined; - if (setOnPrototype) { - this.SetOnPrototype(key, field); - } else { - if (field) { - this.fields.set(key.Id, { key, field }); - this._proxies.set(key.Id, field.Id); - // Server.AddDocumentField(this, key, field); - } else { - this.fields.delete(key.Id); - this._proxies.delete(key.Id); - // Server.DeleteDocumentField(this, key); - } - Server.UpdateField(this); + + GetData( + key: Key, + ctor: { new(): U }, + defaultVal: T + ): T { + let val = this.Get(key); + let vval = val && val instanceof ctor ? val.Data : defaultVal; + return vval; } - if (oldField || field) { - UndoManager.AddEvent({ - undo: () => this.Set(key, oldField, setOnPrototype), - redo: () => this.Set(key, field, setOnPrototype) - }); + + GetHtml(key: Key, defaultVal: string): string { + return this.GetData(key, HtmlField, defaultVal); } - } - - @action - SetOnPrototype(key: Key, field: Field | undefined): void { - this.GetTAsync(KeyStore.Prototype, Document, (f: Opt) => { - f && f.Set(key, field); - }); - } - - @action - SetDataOnPrototype( - key: Key, - value: T, - ctor: { new (): U }, - replaceWrongType = true - ) { - this.GetTAsync(KeyStore.Prototype, Document, (f: Opt) => { - f && f.SetData(key, value, ctor); - }); - } - - @action - SetData( - key: Key, - value: T, - ctor: { new (data: T): U }, - replaceWrongType = true - ) { - let field = this.Get(key, true); - if (field instanceof ctor) { - field.Data = value; - } else if (!field || replaceWrongType) { - let newField = new ctor(value); - // newField.Data = value; - this.Set(key, newField); + + GetBoolean(key: Key, defaultVal: boolean): boolean { + return this.GetData(key, BooleanField, defaultVal); } - } - - @action - SetText(key: Key, value: string, replaceWrongType = true) { - this.SetData(key, value, TextField, replaceWrongType); - } - - @action - SetNumber(key: Key, value: number, replaceWrongType = true) { - this.SetData(key, value, NumberField, replaceWrongType); - } - - GetPrototype(): FieldValue { - return this.GetT(KeyStore.Prototype, Document, true); - } - - GetAllPrototypes(): Document[] { - let protos: Document[] = []; - let doc: FieldValue = this; - while (doc && doc != FieldWaiting) { - protos.push(doc); - doc = doc.GetPrototype(); + + GetNumber(key: Key, defaultVal: number): number { + return this.GetData(key, NumberField, defaultVal); + } + + GetText(key: Key, defaultVal: string): string { + return this.GetData(key, TextField, defaultVal); + } + + GetList(key: Key, defaultVal: T[]): T[] { + return this.GetData>(key, ListField, defaultVal); + } + + @action + Set(key: Key, field: Field | undefined, setOnPrototype = false): void { + let old = this.fields.get(key.Id); + let oldField = old ? old.field : undefined; + if (setOnPrototype) { + this.SetOnPrototype(key, field); + } else { + if (field) { + this.fields.set(key.Id, { key, field }); + this._proxies.set(key.Id, field.Id); + // Server.AddDocumentField(this, key, field); + } else { + this.fields.delete(key.Id); + this._proxies.delete(key.Id); + // Server.DeleteDocumentField(this, key); + } + Server.UpdateField(this); + } + if (oldField || field) { + UndoManager.AddEvent({ + undo: () => this.Set(key, oldField, setOnPrototype), + redo: () => this.Set(key, field, setOnPrototype) + }); + } + } + + @action + SetOnPrototype(key: Key, field: Field | undefined): void { + this.GetTAsync(KeyStore.Prototype, Document, (f: Opt) => { + f && f.Set(key, field); + }); + } + + @action + SetDataOnPrototype( + key: Key, + value: T, + ctor: { new(): U }, + replaceWrongType = true + ) { + this.GetTAsync(KeyStore.Prototype, Document, (f: Opt) => { + f && f.SetData(key, value, ctor); + }); + } + + @action + SetData( + key: Key, + value: T, + ctor: { new(data: T): U }, + replaceWrongType = true + ) { + let field = this.Get(key, true); + if (field instanceof ctor) { + field.Data = value; + } else if (!field || replaceWrongType) { + let newField = new ctor(value); + // newField.Data = value; + this.Set(key, newField); + } + } + + @action + SetText(key: Key, value: string, replaceWrongType = true) { + this.SetData(key, value, TextField, replaceWrongType); + } + + @action + SetNumber(key: Key, value: number, replaceWrongType = true) { + this.SetData(key, value, NumberField, replaceWrongType); + } + + GetPrototype(): FieldValue { + return this.GetT(KeyStore.Prototype, Document, true); + } + + GetAllPrototypes(): Document[] { + let protos: Document[] = []; + let doc: FieldValue = this; + while (doc && doc != FieldWaiting) { + protos.push(doc); + doc = doc.GetPrototype(); + } + return protos; + } + + CreateAlias(id?: string): Document { + let alias = new Document(id); + this.GetTAsync(KeyStore.Prototype, Document, (f: Opt) => { + f && alias.Set(KeyStore.Prototype, f); + }); + + return alias; + } + + MakeDelegate(id?: string): Document { + let delegate = new Document(id); + + delegate.Set(KeyStore.Prototype, this); + + return delegate; + } + + ToScriptString(): string { + return ""; + } + + TrySetValue(value: any): boolean { + throw new Error("Method not implemented."); + } + GetValue() { + return this.Title; + var title = + (this._proxies.has(KeyStore.Title.Id) ? "???" : this.Title) + + "(" + + this.Id + + ")"; + return title; + //throw new Error("Method not implemented."); + } + Copy(): Field { + throw new Error("Method not implemented."); + } + + ToJson(): { type: Types; data: [string, string][]; _id: string } { + let fields: [string, string][] = []; + this._proxies.forEach((field, key) => { + if (field) { + fields.push([key, field as string]); + } + }); + + return { + type: Types.Document, + data: fields, + _id: this.Id + }; } - return protos; - } - - CreateAlias(id?: string): Document { - let alias = new Document(id); - this.GetTAsync(KeyStore.Prototype, Document, (f: Opt) => { - f && alias.Set(KeyStore.Prototype, f); - }); - - return alias; - } - - MakeDelegate(id?: string): Document { - let delegate = new Document(id); - - delegate.Set(KeyStore.Prototype, this); - - return delegate; - } - - ToScriptString(): string { - return ""; - } - - TrySetValue(value: any): boolean { - throw new Error("Method not implemented."); - } - GetValue() { - return this.Title; - var title = - (this._proxies.has(KeyStore.Title.Id) ? "???" : this.Title) + - "(" + - this.Id + - ")"; - return title; - //throw new Error("Method not implemented."); - } - Copy(): Field { - throw new Error("Method not implemented."); - } - - ToJson(): { type: Types; data: [string, string][]; _id: string } { - let fields: [string, string][] = []; - this._proxies.forEach((field, key) => { - if (field) { - fields.push([key, field as string]); - } - }); - - return { - type: Types.Document, - data: fields, - _id: this.Id - }; - } } -- cgit v1.2.3-70-g09d2 From 89fd4327db1536990b4a4dc218819a1077f82445 Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 9 Apr 2019 15:14:46 -0400 Subject: fixed layout of collection freeforms. --- .../collectionFreeForm/CollectionFreeFormView.scss | 8 ++- .../collectionFreeForm/CollectionFreeFormView.tsx | 60 ++++++++++++---------- 2 files changed, 40 insertions(+), 28 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss index 79d520069..81f2146e4 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -1,5 +1,11 @@ @import "../../global_variables"; - +.collectionfreeformview-measure { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + } .collectionfreeformview { position: absolute; top: 0; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index e694bc7a7..1feb30db1 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1,4 +1,4 @@ -import { action, computed, observable, trace } from "mobx"; +import { action, computed, observable, trace, ObservableSet, runInAction } from "mobx"; import { observer } from "mobx-react"; import { Document } from "../../../../fields/Document"; import { FieldWaiting } from "../../../../fields/Field"; @@ -24,6 +24,7 @@ import { DocumentManager } from "../../../util/DocumentManager"; import { SelectionManager } from "../../../util/SelectionManager"; import { NumberField } from "../../../../fields/NumberField"; import { Main } from "../../Main"; +import Measure from "react-measure"; @observer export class CollectionFreeFormView extends CollectionSubView { @@ -67,8 +68,8 @@ export class CollectionFreeFormView extends CollectionSubView { @observable public DownY: number = 0; @observable private _lastX: number = 0; @observable private _lastY: number = 0; - - private outerElement?: HTMLDivElement; + @observable private _pwidth: number = 0; + @observable private _pheight: number = 0; @computed get panX(): number { return this.props.Document.GetNumber(KeyStore.PanX, 0); } @computed get panY(): number { return this.props.Document.GetNumber(KeyStore.PanY, 0); } @@ -77,8 +78,8 @@ export class CollectionFreeFormView extends CollectionSubView { @computed get nativeWidth() { return this.props.Document.GetNumber(KeyStore.NativeWidth, 0); } @computed get nativeHeight() { return this.props.Document.GetNumber(KeyStore.NativeHeight, 0); } @computed get zoomScaling() { return this.props.Document.GetNumber(KeyStore.Scale, 1); } - @computed get centeringShiftX() { return !this.props.Document.GetNumber(KeyStore.NativeWidth, 0) && this.outerElement ? this.outerElement.clientWidth / 2 : 0; } // shift so pan position is at center of window for non-overlay collections - @computed get centeringShiftY() { return !this.props.Document.GetNumber(KeyStore.NativeHeight, 0) && this.outerElement ? this.outerElement.clientHeight / 2 : 0; }// shift so pan position is at center of window for non-overlay collections + @computed get centeringShiftX() { return !this.props.Document.GetNumber(KeyStore.NativeWidth, 0) ? this._pwidth / 2 : 0; } // shift so pan position is at center of window for non-overlay collections + @computed get centeringShiftY() { return !this.props.Document.GetNumber(KeyStore.NativeHeight, 0) ? this._pheight / 2 : 0; }// shift so pan position is at center of window for non-overlay collections @undoBatch @action @@ -311,29 +312,34 @@ export class CollectionFreeFormView extends CollectionSubView { const pany: number = -this.props.Document.GetNumber(KeyStore.PanY, 0); return ( -
super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY))} - onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} onWheel={this.onPointerWheel} - style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }} ref={this.createDropTarget}> - - -
- {this.backgroundView} - - - {this.childViews} - - - + runInAction(() => { this._pwidth = r.entry.width; this._pheight = r.entry.height })}> + {({ measureRef }) => ( +
+
super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY))} + onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} onWheel={this.onPointerWheel} + style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }} ref={this.createDropTarget}> + + +
+ {this.backgroundView} + + + {this.childViews} + + + +
+ {this.overlayView} +
+
- {this.overlayView} - - -
+
)} + ); } } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From f8d4fa3d161da88e63e51c4a8940a3c44d0ae62e Mon Sep 17 00:00:00 2001 From: Hannah Chow Date: Tue, 9 Apr 2019 22:01:44 -0400 Subject: for now --- src/client/views/DocumentDecorations.scss | 9 +- src/client/views/DocumentDecorations.tsx | 3 +- .../collectionFreeForm/CollectionFreeFormView.scss | 140 ++++++++++++--------- .../collectionFreeForm/CollectionFreeFormView.tsx | 15 ++- src/client/views/nodes/LinkBox.tsx | 1 + src/fields/KeyStore.ts | 1 + 6 files changed, 102 insertions(+), 67 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss') diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss index ecc738076..3871be35b 100644 --- a/src/client/views/DocumentDecorations.scss +++ b/src/client/views/DocumentDecorations.scss @@ -69,6 +69,7 @@ } } + .documentDecorations-closeButton { background: $alt-accent; opacity: 0.8; @@ -125,6 +126,10 @@ // } // } +.linkFlyout { + grid-column: 2/4; +} + .linkButton-empty:hover { background: $main-accent; transform: scale(1.05); @@ -162,10 +167,6 @@ transform: scale(1.05); } -.linkButton-tray { - grid-column: 1/4; -} - .linkButton-empty { height: 20px; width: 20px; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index bb4437a6a..4a329dd36 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -442,9 +442,10 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
e.preventDefault()}>
{linkButton}
-
+
+
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss index 81f2146e4..f9d786c9b 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -1,92 +1,110 @@ @import "../../global_variables"; + .collectionfreeformview-measure { position: absolute; top: 0; left: 0; width: 100%; height: 100%; - } -.collectionfreeformview { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - transform-origin: left top; } -.collectionfreeformview-container { - .collectionfreeformview > .jsx-parser { + +.collectionfreeformview-ease { position: absolute; + top: 0; + left: 0; + width: 100%; height: 100%; + transform-origin: left top; + transition: transform 2s; +} + +.collectionfreeformview-none { + position: absolute; + top: 0; + left: 0; width: 100%; - } + height: 100%; + transform-origin: left top; +} + +.collectionfreeformview-container { + .collectionfreeformview>.jsx-parser { + position: absolute; + height: 100%; + width: 100%; + } - //nested freeform views - // .collectionfreeformview-container { + //nested freeform views + // .collectionfreeformview-container { // background-image: linear-gradient(to right, $light-color-secondary 1px, transparent 1px), // linear-gradient(to bottom, $light-color-secondary 1px, transparent 1px); // background-size: 30px 30px; - // } + // } - box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw; - border: 0px solid $light-color-secondary; - border-radius: $border-radius; - box-sizing: border-box; - position: absolute; - overflow: hidden; - top: 0; - left: 0; - width: 100%; - height: 100%; -} -.collectionfreeformview-overlay { - .collectionfreeformview > .jsx-parser { + box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw; + border: 0px solid $light-color-secondary; + border-radius: $border-radius; + box-sizing: border-box; position: absolute; + overflow: hidden; + top: 0; + left: 0; + width: 100%; height: 100%; - } - .formattedTextBox-cont { - background: $light-color-secondary; - } - - opacity: 0.99; - border: 0px solid transparent; - border-radius: $border-radius; - box-sizing: border-box; - position:absolute; - overflow: hidden; - top: 0; - left: 0; - width: 100%; - height: 100%; - .collectionfreeformview { +} + +.collectionfreeformview-overlay { + .collectionfreeformview>.jsx-parser { + position: absolute; + height: 100%; + } + .formattedTextBox-cont { - background:yellow; + background: $light-color-secondary; + } + + opacity: 0.99; + border: 0px solid transparent; + border-radius: $border-radius; + box-sizing: border-box; + position:absolute; + overflow: hidden; + top: 0; + left: 0; + width: 100%; + height: 100%; + + .collectionfreeformview { + .formattedTextBox-cont { + background: yellow; + } } - } } // selection border...? .border { - border-style: solid; - box-sizing: border-box; - width: 98%; - height: 98%; - border-radius: $border-radius; + border-style: solid; + box-sizing: border-box; + width: 98%; + height: 98%; + border-radius: $border-radius; } //this is an animation for the blinking cursor! @keyframes blink { - 0% { - opacity: 0; - } - 49% { - opacity: 0; - } - 50% { - opacity: 1; - } + 0% { + opacity: 0; + } + + 49% { + opacity: 0; + } + + 50% { + opacity: 1; + } } #prevCursor { - animation: blink 1s infinite; -} + animation: blink 1s infinite; +} \ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 1feb30db1..4562fd8a7 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -206,6 +206,7 @@ export class CollectionFreeFormView extends CollectionSubView { const newPanY = Math.min((1 - 1 / x1) * this.nativeHeight, Math.max(0, panY)); this.props.Document.SetNumber(KeyStore.PanX, this.isAnnotationOverlay ? newPanX : panX); this.props.Document.SetNumber(KeyStore.PanY, this.isAnnotationOverlay ? newPanY : panY); + } @action @@ -249,10 +250,16 @@ export class CollectionFreeFormView extends CollectionSubView { } focusDocument = (doc: Document) => { + this.props.Document.SetText(KeyStore.PanTransformType, "Ease"); let x = doc.GetNumber(KeyStore.X, 0) + doc.GetNumber(KeyStore.Width, 0) / 2; let y = doc.GetNumber(KeyStore.Y, 0) + doc.GetNumber(KeyStore.Height, 0) / 2; this.SetPan(x, y); this.props.focus(this.props.Document); + // if(this.props.Document.GetText(KeyStore.PanTransformType, "") === "Ease") { + // setTimeout(function(){ + // this.props.Document.SetText(KeyStore.PanTransformType, "None"); + // }.bind(this),5000); // wait 5 seconds, then reset to false + // } } getDocumentViewProps(document: Document): DocumentViewProps { @@ -311,6 +318,12 @@ export class CollectionFreeFormView extends CollectionSubView { const panx: number = -this.props.Document.GetNumber(KeyStore.PanX, 0); const pany: number = -this.props.Document.GetNumber(KeyStore.PanY, 0); + if (this.props.Document.GetText(KeyStore.PanTransformType, "") === "Ease") { + var freeformclass = "collectionfreeformview-ease"; + } else { + var freeformclass = "collectionfreeformview-none"; + } + return ( runInAction(() => { this._pwidth = r.entry.width; this._pheight = r.entry.height })}> {({ measureRef }) => ( @@ -324,7 +337,7 @@ export class CollectionFreeFormView extends CollectionSubView { getContainerTransform={this.getContainerTransform} getTransform={this.getTransform}> -
{this.backgroundView} diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index ca1b97eba..396f5f577 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -54,6 +54,7 @@ export class LinkBox extends React.Component { } let contextView = DocumentManager.Instance.getDocumentView(contextDoc); if (contextView) { + contextDoc.SetText(KeyStore.PanTransformType, "Ease"); contextView.props.focus(contextDoc); } else { CollectionDockingView.Instance.AddRightSplit(contextDoc); diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts index 425408273..3a57d0f0a 100644 --- a/src/fields/KeyStore.ts +++ b/src/fields/KeyStore.ts @@ -47,6 +47,7 @@ export namespace KeyStore { export const Workspaces = new Key("Workspaces"); export const Minimized = new Key("Minimized"); export const CopyDraggedItems = new Key("CopyDraggedItems"); + export const PanTransformType = new Key("PanTransformType"); export const KeyList: Key[] = [Prototype, X, Y, Page, Title, Author, PanX, PanY, Scale, NativeWidth, NativeHeight, Width, Height, ZIndex, Data, Annotations, ViewType, Layout, BackgroundColor, BackgroundLayout, OverlayLayout, LayoutKeys, -- cgit v1.2.3-70-g09d2 From fd8e6bf2cacf8bed7c3363eeb777c731741266d5 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 11 Apr 2019 20:19:57 -0400 Subject: made COLLECTION_BORDER_WIDTH a CSS variable accessible from code. changed global css variable file name --- src/client/util/DragManager.ts | 5 ++-- src/client/util/TooltipTextMenu.scss | 2 +- src/client/views/ContextMenu.scss | 2 +- src/client/views/DocumentDecorations.scss | 2 +- src/client/views/InkingCanvas.scss | 2 +- src/client/views/InkingControl.scss | 2 +- src/client/views/Main.scss | 2 +- src/client/views/_global_variables.scss | 28 ------------------- src/client/views/_global_variables.scss.d.ts | 7 ----- src/client/views/_global_variables.ts | 8 ------ .../views/collections/CollectionBaseView.tsx | 1 - .../views/collections/CollectionDockingView.scss | 6 +++++ .../views/collections/CollectionDockingView.tsx | 9 +------ .../views/collections/CollectionSchemaView.scss | 6 +++-- .../views/collections/CollectionSchemaView.tsx | 10 ++++--- .../views/collections/CollectionTreeView.scss | 6 +++-- .../views/collections/CollectionTreeView.tsx | 4 +-- .../CollectionFreeFormRemoteCursors.scss | 2 +- .../collectionFreeForm/CollectionFreeFormView.scss | 10 ++++--- .../collectionFreeForm/CollectionFreeFormView.tsx | 31 ++++++++++++---------- src/client/views/globalCssVariables.scss | 29 ++++++++++++++++++++ src/client/views/globalCssVariables.scss.d.ts | 8 ++++++ src/client/views/nodes/DocumentView.scss | 2 +- src/client/views/nodes/FormattedTextBox.scss | 2 +- src/client/views/nodes/KeyValueBox.scss | 2 +- src/client/views/nodes/KeyValuePair.scss | 2 +- src/client/views/nodes/LinkBox.scss | 2 +- src/client/views/nodes/LinkEditor.scss | 2 +- 28 files changed, 99 insertions(+), 95 deletions(-) delete mode 100644 src/client/views/_global_variables.scss delete mode 100644 src/client/views/_global_variables.scss.d.ts delete mode 100644 src/client/views/_global_variables.ts create mode 100644 src/client/views/globalCssVariables.scss create mode 100644 src/client/views/globalCssVariables.scss.d.ts (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 333c474c1..3d8bbb49c 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -5,8 +5,7 @@ import { CollectionDockingView } from "../views/collections/CollectionDockingVie import { DocumentDecorations } from "../views/DocumentDecorations"; import { Main } from "../views/Main"; import { DocumentView } from "../views/nodes/DocumentView"; -// import globalStyles from "../views/_global_variables"; -import * as globalStyles from "../views/_global_variables.scss"; // bcz: why doesn't this work? +import * as globalCssVariables from "../views/globalCssVariables.scss"; export function setupDrag(_reference: React.RefObject, docFunc: () => Document, moveFunc?: DragManager.MoveFunction, copyOnDrop: boolean = false) { let onRowMove = action((e: PointerEvent): void => { @@ -178,7 +177,7 @@ export namespace DragManager { dragElement.style.bottom = ""; dragElement.style.left = "0"; dragElement.style.transformOrigin = "0 0"; - dragElement.style.zIndex = globalStyles.contextMenuZindex;// "1000"; + dragElement.style.zIndex = globalCssVariables.contextMenuZindex;// "1000"; dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`; dragElement.style.width = `${rect.width / scaleX}px`; dragElement.style.height = `${rect.height / scaleY}px`; diff --git a/src/client/util/TooltipTextMenu.scss b/src/client/util/TooltipTextMenu.scss index ea580d104..7deea3be6 100644 --- a/src/client/util/TooltipTextMenu.scss +++ b/src/client/util/TooltipTextMenu.scss @@ -1,4 +1,4 @@ -@import "../views/global_variables"; +@import "../views/globalCssVariables"; .tooltipMenu { position: absolute; diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index 5acf598cf..fe884ca85 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -1,4 +1,4 @@ -@import "global_variables"; +@import "globalCssVariables"; .contextMenu-cont { position: absolute; display: flex; diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss index 321bda384..ce84b6106 100644 --- a/src/client/views/DocumentDecorations.scss +++ b/src/client/views/DocumentDecorations.scss @@ -1,4 +1,4 @@ -@import "global_variables"; +@import "globalCssVariables"; .documentDecorations { position: absolute; diff --git a/src/client/views/InkingCanvas.scss b/src/client/views/InkingCanvas.scss index 42ae38c73..2c550051c 100644 --- a/src/client/views/InkingCanvas.scss +++ b/src/client/views/InkingCanvas.scss @@ -1,4 +1,4 @@ -@import "global_variables"; +@import "globalCssVariables"; .inkingCanvas { opacity:0.99; diff --git a/src/client/views/InkingControl.scss b/src/client/views/InkingControl.scss index 0d8fd8784..ba4ec41af 100644 --- a/src/client/views/InkingControl.scss +++ b/src/client/views/InkingControl.scss @@ -1,4 +1,4 @@ -@import "global_variables"; +@import "globalCssVariables"; .inking-control { position: absolute; left: 70px; diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss index 7329b8eb6..f3af26f37 100644 --- a/src/client/views/Main.scss +++ b/src/client/views/Main.scss @@ -1,4 +1,4 @@ -@import "global_variables"; +@import "globalCssVariables"; @import "nodeModuleOverrides"; html, body { diff --git a/src/client/views/_global_variables.scss b/src/client/views/_global_variables.scss deleted file mode 100644 index cd6af2dac..000000000 --- a/src/client/views/_global_variables.scss +++ /dev/null @@ -1,28 +0,0 @@ -@import url("https://fonts.googleapis.com/css?family=Noto+Sans:400,700|Crimson+Text:400,400i,700"); -// colors -$light-color: #fcfbf7; -$light-color-secondary: rgb(241, 239, 235); -$main-accent: #61aaa3; -// $alt-accent: #cdd5ec; -// $alt-accent: #cdeceb; -$alt-accent: #59dff7; -$lighter-alt-accent: rgb(207, 220, 240); -$intermediate-color: #9c9396; -$dark-color: #121721; -// fonts -$sans-serif: "Noto Sans", sans-serif; -// $sans-serif: "Roboto Slab", sans-serif; -$serif: "Crimson Text", serif; -// misc values -$border-radius: 0.3em; -// - - // dragged items -$contextMenu-zindex: 1000; // context menu shows up over everything -$mainTextInput-zindex: 999; // then text input overlay so that it's context menu will appear over decorations, etc -$docDecorations-zindex: 998; // then doc decorations appear over everything else -$remoteCursors-zindex: 997; // ... not sure what level the remote cursors should go -- is this right? - -:export { - contextMenuZindex: $contextMenu-zindex; -} \ No newline at end of file diff --git a/src/client/views/_global_variables.scss.d.ts b/src/client/views/_global_variables.scss.d.ts deleted file mode 100644 index ebee7dbce..000000000 --- a/src/client/views/_global_variables.scss.d.ts +++ /dev/null @@ -1,7 +0,0 @@ - -interface IGlobalScss { - contextMenuZindex: string; // context menu shows up over everything -} -declare const globalStyleVariables: IGlobalScss; - -export = globalStyleVariables; \ No newline at end of file diff --git a/src/client/views/_global_variables.ts b/src/client/views/_global_variables.ts deleted file mode 100644 index caedc7aad..000000000 --- a/src/client/views/_global_variables.ts +++ /dev/null @@ -1,8 +0,0 @@ -import * as globalStyleVariables from "../views/_global_variables.scss"; - -export interface IGlobalScss { - contextMenuZindex: string; // context menu shows up over everything -} -let globalStyles = globalStyleVariables as any as IGlobalScss; - -export default globalStyles; \ No newline at end of file diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index ac320eda3..0ace700ce 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -34,7 +34,6 @@ export interface CollectionViewProps extends FieldViewProps { contentRef?: React.Ref; } -export const COLLECTION_BORDER_WIDTH = 1; @observer export class CollectionBaseView extends React.Component { diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss index 583d50c5b..13dd9faa8 100644 --- a/src/client/views/collections/CollectionDockingView.scss +++ b/src/client/views/collections/CollectionDockingView.scss @@ -1,8 +1,14 @@ +@import "../../views/globalCssVariables.scss"; + .collectiondockingview-content { height: 100%; } .collectiondockingview-container { + width: 100%; + height: 100%; + border-style: solid; + border-width: $COLLECTION_BORDER_WIDTH; position: absolute; top: 0; left: 0; diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 212cf8a69..05470f405 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -13,7 +13,6 @@ import { Server } from "../../Server"; import { undoBatch } from "../../util/UndoManager"; import { DocumentView } from "../nodes/DocumentView"; import "./CollectionDockingView.scss"; -import { COLLECTION_BORDER_WIDTH } from "./CollectionBaseView"; import React = require("react"); import { SubCollectionViewProps } from "./CollectionSubView"; import { ServerUtils } from "../../../server/ServerUtil"; @@ -271,13 +270,7 @@ export class CollectionDockingView extends React.Component + onPointerDown={this.onPointerDown} onPointerUp={this.onPointerUp} ref={this._containerRef} /> ); } } diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index c3a2e88ac..40e49bb5f 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -1,4 +1,4 @@ -@import "../global_variables"; +@import "../globalCssVariables"; //options menu styling #schemaOptionsMenuBtn { @@ -53,7 +53,9 @@ .collectionSchemaView-container { - border: 1px solid $intermediate-color; + border-width: $COLLECTION_BORDER_WIDTH; + border-color : $intermediate-color; + border-style: solid; border-radius: $border-radius; box-sizing: border-box; position: absolute; diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index f1b3e1b8f..0cb88eab0 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -25,7 +25,7 @@ import "./CollectionSchemaView.scss"; import { CollectionView } from "./CollectionView"; import { CollectionSubView } from "./CollectionSubView"; import { TextField } from "../../../fields/TextField"; -import { COLLECTION_BORDER_WIDTH } from "./CollectionBaseView"; +import * as globalCssVariables from "../../views/globalCssVariables.scss"; import { emptyFunction, returnFalse } from "../../../Utils"; @@ -245,11 +245,13 @@ export class CollectionSchemaView extends CollectionSubView { this._contentScaling = r.entry.width / selected!.GetNumber(KeyStore.NativeWidth, r.entry.width); } + @computed + get borderWidth() { return globalCssVariables.COLLECTION_BORDER_WIDTH; } getContentScaling = (): number => this._contentScaling; getPanelWidth = (): number => this._panelWidth; getPanelHeight = (): number => this._panelHeight; - getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this.DIVIDER_WIDTH - this._dividerX, - COLLECTION_BORDER_WIDTH).scale(1 / this._contentScaling); - getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this.DIVIDER_WIDTH - this._dividerX - this._tableWidth, - COLLECTION_BORDER_WIDTH).scale(1 / this._contentScaling); + getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this._dividerX, - this.borderWidth).scale(1 / this._contentScaling); + getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this._dividerX - this._tableWidth, - this.borderWidth).scale(1 / this._contentScaling); focusDocument = (doc: Document) => { }; @@ -349,7 +351,7 @@ export class CollectionSchemaView extends CollectionSubView { ); return ( -
+
this.onDrop(e, {})} ref={this.createDropTarget}> {({ measureRef }) => diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss index f2affbf55..973eead97 100644 --- a/src/client/views/collections/CollectionTreeView.scss +++ b/src/client/views/collections/CollectionTreeView.scss @@ -1,7 +1,9 @@ -@import "../global_variables"; +@import "../globalCssVariables"; .collectionTreeView-dropTarget { - border: 0px solid transparent; + border-width: $COLLECTION_BORDER_WIDTH; + border-color: transparent; + border-style: solid; border-radius: $border-radius; box-sizing: border-box; height: 100%; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 659cff9fe..20ec16822 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -11,9 +11,9 @@ import { setupDrag, DragManager } from "../../util/DragManager"; import { EditableView } from "../EditableView"; import "./CollectionTreeView.scss"; import { CollectionView } from "./CollectionView"; +import * as globalCssVariables from "../../views/globalCssVariables.scss"; import { CollectionSubView } from "./CollectionSubView"; import React = require("react"); -import { COLLECTION_BORDER_WIDTH } from './CollectionBaseView'; import { props } from 'bluebird'; @@ -139,7 +139,7 @@ export class CollectionTreeView extends CollectionSubView { ); return ( -
e.stopPropagation()} onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget} style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }}> +
e.stopPropagation()} onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget}>
); } - getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH).translate(-this.centeringShiftX, -this.centeringShiftY).transform(this.getLocalTransform()); - getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH); + @computed + get borderWidth() { + return this.isAnnotationOverlay ? 0 : globalCssVariables.COLLECTION_BORDER_WIDTH; + } + getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth, -this.borderWidth).translate(-this.centeringShiftX, -this.centeringShiftY).transform(this.getLocalTransform()); + getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth, -this.borderWidth); getLocalTransform = (): Transform => Transform.Identity().scale(1 / this.scale).translate(this.panX, this.panY); noScaling = () => 1; childViews = () => this.views; @@ -317,8 +321,7 @@ export class CollectionFreeFormView extends CollectionSubView {
super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY))} - onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} onWheel={this.onPointerWheel} - style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }} ref={this.createDropTarget}> + onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} onWheel={this.onPointerWheel} ref={this.createDropTarget}> diff --git a/src/client/views/globalCssVariables.scss b/src/client/views/globalCssVariables.scss new file mode 100644 index 000000000..5c8e9c8fc --- /dev/null +++ b/src/client/views/globalCssVariables.scss @@ -0,0 +1,29 @@ +@import url("https://fonts.googleapis.com/css?family=Noto+Sans:400,700|Crimson+Text:400,400i,700"); +// colors +$light-color: #fcfbf7; +$light-color-secondary: rgb(241, 239, 235); +$main-accent: #61aaa3; +// $alt-accent: #cdd5ec; +// $alt-accent: #cdeceb; +$alt-accent: #59dff7; +$lighter-alt-accent: rgb(207, 220, 240); +$intermediate-color: #9c9396; +$dark-color: #121721; +// fonts +$sans-serif: "Noto Sans", sans-serif; +// $sans-serif: "Roboto Slab", sans-serif; +$serif: "Crimson Text", serif; +// misc values +$border-radius: 0.3em; +// + + // dragged items +$contextMenu-zindex: 1000; // context menu shows up over everything +$mainTextInput-zindex: 999; // then text input overlay so that it's context menu will appear over decorations, etc +$docDecorations-zindex: 998; // then doc decorations appear over everything else +$remoteCursors-zindex: 997; // ... not sure what level the remote cursors should go -- is this right? +$COLLECTION_BORDER_WIDTH: 1; +:export { + contextMenuZindex: $contextMenu-zindex; + COLLECTION_BORDER_WIDTH: $COLLECTION_BORDER_WIDTH; +} \ No newline at end of file diff --git a/src/client/views/globalCssVariables.scss.d.ts b/src/client/views/globalCssVariables.scss.d.ts new file mode 100644 index 000000000..e874b815d --- /dev/null +++ b/src/client/views/globalCssVariables.scss.d.ts @@ -0,0 +1,8 @@ + +interface IGlobalScss { + contextMenuZindex: string; // context menu shows up over everything + COLLECTION_BORDER_WIDTH: number; +} +declare const globalCssVariables: IGlobalScss; + +export = globalCssVariables; \ No newline at end of file diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss index 5126e69f9..039d1bcc6 100644 --- a/src/client/views/nodes/DocumentView.scss +++ b/src/client/views/nodes/DocumentView.scss @@ -1,4 +1,4 @@ -@import "../global_variables"; +@import "../globalCssVariables"; .documentView-node { position: absolute; diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index d2ba52cf9..3978c3d38 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -1,4 +1,4 @@ -@import "../global_variables"; +@import "../globalCssVariables"; .ProseMirror { width: 100%; height: auto; diff --git a/src/client/views/nodes/KeyValueBox.scss b/src/client/views/nodes/KeyValueBox.scss index 63ae75424..f60edc675 100644 --- a/src/client/views/nodes/KeyValueBox.scss +++ b/src/client/views/nodes/KeyValueBox.scss @@ -1,4 +1,4 @@ -@import "../global_variables"; +@import "../globalCssVariables"; .keyValueBox-cont { overflow-y: scroll; height: 100%; diff --git a/src/client/views/nodes/KeyValuePair.scss b/src/client/views/nodes/KeyValuePair.scss index 64e871e1c..0bb92e5a3 100644 --- a/src/client/views/nodes/KeyValuePair.scss +++ b/src/client/views/nodes/KeyValuePair.scss @@ -1,4 +1,4 @@ -@import "../global_variables"; +@import "../globalCssVariables"; .container{ display: flex; diff --git a/src/client/views/nodes/LinkBox.scss b/src/client/views/nodes/LinkBox.scss index 5d5f782d2..8bc70b48f 100644 --- a/src/client/views/nodes/LinkBox.scss +++ b/src/client/views/nodes/LinkBox.scss @@ -1,4 +1,4 @@ -@import "../global_variables"; +@import "../globalCssVariables"; .link-container { width: 100%; height: 35px; diff --git a/src/client/views/nodes/LinkEditor.scss b/src/client/views/nodes/LinkEditor.scss index fb0c69cff..ea2e7289c 100644 --- a/src/client/views/nodes/LinkEditor.scss +++ b/src/client/views/nodes/LinkEditor.scss @@ -1,4 +1,4 @@ -@import "../global_variables"; +@import "../globalCssVariables"; .edit-container { width: 100%; height: auto; -- cgit v1.2.3-70-g09d2 From 0737a14e2c436ab9613c638bcebdc5480df1d4d4 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 13 Apr 2019 00:23:44 -0400 Subject: repairs to keyvaluebox --- .../views/collections/CollectionSchemaView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.scss | 10 +-- .../collectionFreeForm/MarqueeView.scss | 2 +- src/client/views/nodes/DocumentView.scss | 2 +- src/client/views/nodes/KeyValueBox.scss | 91 ++++++++++++++++++---- src/client/views/nodes/KeyValueBox.tsx | 53 ++++++++++--- src/client/views/nodes/KeyValuePair.scss | 20 ++++- src/client/views/nodes/KeyValuePair.tsx | 56 ++++++------- 8 files changed, 175 insertions(+), 61 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss') diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 162a39170..fdb82690a 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -17,6 +17,7 @@ import { Server } from "../../Server"; import { SetupDrag } from "../../util/DragManager"; import { CompileScript, ToField } from "../../util/Scripting"; import { Transform } from "../../util/Transform"; +import { COLLECTION_BORDER_WIDTH } from "../../views/globalCssVariables.scss"; import { anchorPoints, Flyout } from "../DocumentDecorations"; import '../DocumentDecorations.scss'; import { EditableView } from "../EditableView"; @@ -24,7 +25,6 @@ import { DocumentView } from "../nodes/DocumentView"; import { FieldView, FieldViewProps } from "../nodes/FieldView"; import "./CollectionSchemaView.scss"; import { CollectionSubView } from "./CollectionSubView"; -import { COLLECTION_BORDER_WIDTH } from "../../views/globalCssVariables.scss"; // bcz: need to add drag and drop of rows and columns. This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657 diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss index f3ac4a383..26c794e91 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -1,13 +1,13 @@ @import "../../globalCssVariables"; .collectionfreeformview-measure { - position: absolute; + position: inherit; top: 0; left: 0; width: 100%; height: 100%; } .collectionfreeformview { - position: absolute; + position: inherit; top: 0; left: 0; width: 100%; @@ -16,7 +16,7 @@ } .collectionfreeformview-container { .collectionfreeformview > .jsx-parser { - position: absolute; + position: inherit; height: 100%; width: 100%; } @@ -43,7 +43,7 @@ } .collectionfreeformview-overlay { .collectionfreeformview > .jsx-parser { - position: absolute; + position: inherit; height: 100%; } .formattedTextBox-cont { @@ -56,7 +56,7 @@ border-style: solid; border-radius: $border-radius; box-sizing: border-box; - position:absolute; + position: absolute; overflow: hidden; top: 0; left: 0; diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.scss b/src/client/views/collections/collectionFreeForm/MarqueeView.scss index 0b406e722..e5ffcec76 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.scss +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.scss @@ -1,6 +1,6 @@ .marqueeView { - position: absolute; + position: inherit; top:0; left:0; width:100%; diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss index 039d1bcc6..a946ac1a8 100644 --- a/src/client/views/nodes/DocumentView.scss +++ b/src/client/views/nodes/DocumentView.scss @@ -1,7 +1,7 @@ @import "../globalCssVariables"; .documentView-node { - position: absolute; + position: inherit; top: 0; left:0; background: $light-color; //overflow: hidden; diff --git a/src/client/views/nodes/KeyValueBox.scss b/src/client/views/nodes/KeyValueBox.scss index f60edc675..6ebd73f2c 100644 --- a/src/client/views/nodes/KeyValueBox.scss +++ b/src/client/views/nodes/KeyValueBox.scss @@ -1,6 +1,7 @@ @import "../globalCssVariables"; .keyValueBox-cont { overflow-y: scroll; + width:100%; height: 100%; background-color: $light-color; border: 1px solid $intermediate-color; @@ -8,31 +9,58 @@ box-sizing: border-box; display: inline-block; .imageBox-cont img { - max-height: 45px; - height: auto; - } - td { - padding: 6px 8px; - border-right: 1px solid $intermediate-color; - border-top: 1px solid $intermediate-color; - &:last-child { - border-right: none; - } + width: auto; } } +$header-height: 30px; +.keyValueBox-tbody { + width:100%; + height:100%; + position: absolute; + overflow-y: scroll; +} +.keyValueBox-key { + display: inline-block; + height:100%; + width:50%; + text-align: center; +} +.keyValueBox-fields { + display: inline-block; + height:100%; + width:50%; + text-align: center; +} .keyValueBox-table { - position: relative; + position: absolute; + width:100%; + height:100%; border-collapse: collapse; } - +.keyValueBox-td-key { + display:inline-block; + height:30px; +} +.keyValueBox-td-value { + display:inline-block; + height:30px; +} +.keyValueBox-valueRow { + width:100%; + height:30px; + display: inline-block; +} .keyValueBox-header { + width:100%; + position: relative; + display: inline-block; background: $intermediate-color; color: $light-color; text-transform: uppercase; letter-spacing: 2px; font-size: 12px; - height: 30px; + height: $header-height; padding-top: 4px; th { font-weight: normal; @@ -43,13 +71,50 @@ } .keyValueBox-evenRow { + position: relative; + display: inline-block; + width:100%; + height:$header-height; background: $light-color; .formattedTextBox-cont { background: $light-color; } } +.keyValueBox-cont { + .collectionfreeformview-overlay { + position: relative; + } +} +.keyValueBox-dividerDraggerThumb{ + position: relative; + width: 4px; + float: left; + height: 30px; + width: 10px; + z-index: 20; + right: 0; + top: 0; + border-radius: 10px; + background: gray; + pointer-events: all; +} +.keyValueBox-dividerDragger{ + position: relative; + width: 100%; + float: left; + height: 37px; + z-index: 20; + right: 0; + top: 0; + background: transparent; + pointer-events: none; +} .keyValueBox-oddRow { + position: relative; + display: inline-block; + width:100%; + height:30px; background: $light-color-secondary; .formattedTextBox-cont { background: $light-color-secondary; diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index bcac113f0..29e4af160 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -1,23 +1,25 @@ +import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app import { Document } from '../../../fields/Document'; -import { FieldWaiting, Field } from '../../../fields/Field'; +import { Field, FieldWaiting } from '../../../fields/Field'; +import { Key } from '../../../fields/Key'; import { KeyStore } from '../../../fields/KeyStore'; +import { CompileScript, ToField } from "../../util/Scripting"; import { FieldView, FieldViewProps } from './FieldView'; import "./KeyValueBox.scss"; import { KeyValuePair } from "./KeyValuePair"; import React = require("react"); -import { CompileScript, ToField } from "../../util/Scripting"; -import { Key } from '../../../fields/Key'; -import { observable, action } from "mobx"; @observer export class KeyValueBox extends React.Component { + private _mainCont = React.createRef(); public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(KeyValueBox, fieldStr); } @observable private _keyInput: string = ""; @observable private _valueInput: string = ""; + @computed get splitPercentage() { return this.props.Document.GetNumber(KeyStore.SchemaSplitPercentage, 50); } constructor(props: FieldViewProps) { @@ -90,7 +92,7 @@ export class KeyValueBox extends React.Component { let rows: JSX.Element[] = []; let i = 0; for (let key in ids) { - rows.push(); + rows.push(); } return rows; } @@ -107,24 +109,51 @@ export class KeyValueBox extends React.Component { newKeyValue = () => ( - - - + + + + + + + ) + @action + onDividerMove = (e: PointerEvent): void => { + let nativeWidth = this._mainCont.current!.getBoundingClientRect(); + this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, Math.max(0, 100 - Math.round((e.clientX - nativeWidth.left) / nativeWidth.width * 100))); + } + @action + onDividerUp = (e: PointerEvent): void => { + document.removeEventListener("pointermove", this.onDividerMove); + document.removeEventListener('pointerup', this.onDividerUp); + } + onDividerDown = (e: React.PointerEvent) => { + e.stopPropagation(); + e.preventDefault(); + document.addEventListener("pointermove", this.onDividerMove); + document.addEventListener('pointerup', this.onDividerUp); + } + render() { - return (
+ let dividerDragger = this.splitPercentage === 0 ? (null) : +
+
+
; + + return (
- + - - + + {this.createTable()} {this.newKeyValue()}
KeyFieldsKeyFields
+ {dividerDragger}
); } } \ No newline at end of file diff --git a/src/client/views/nodes/KeyValuePair.scss b/src/client/views/nodes/KeyValuePair.scss index 0bb92e5a3..04d002c7b 100644 --- a/src/client/views/nodes/KeyValuePair.scss +++ b/src/client/views/nodes/KeyValuePair.scss @@ -1,12 +1,30 @@ @import "../globalCssVariables"; .container{ + width:100%; + height:100%; display: flex; flex-direction: row; flex-wrap: nowrap; justify-content: space-between; } +.keyValuePair-td-key { + display:inline-block; + width: 50%; +} +.keyValuePair-td-value { + display:inline-block; + width: 50%; +} +.keyValuePair-keyField { + width:100%; + text-align: center; + position: relative; + overflow: auto; +} .delete{ - color: red; + position: relative; + background-color: transparent; + color:red; } \ No newline at end of file diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 7f43d8fdf..3e0b61c3d 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -20,6 +20,7 @@ export interface KeyValuePairProps { rowStyle: string; fieldId: string; doc: Document; + keyWidth: number; } @observer export class KeyValuePair extends React.Component { @@ -61,45 +62,46 @@ export class KeyValuePair extends React.Component { ); return ( - {/* */} - +
-
{this.key.Name}
+
{this.key.Name}
- { - let field = props.Document.Get(props.fieldKey); - if (field && field instanceof Field) { - return field.ToScriptString(); - } - return field || ""; - }} - SetValue={(value: string) => { - let script = CompileScript(value, { addReturn: true }); - if (!script.compiled) { - return false; + + { + let field = props.Document.Get(props.fieldKey); + if (field && field instanceof Field) { + return field.ToScriptString(); } - let res = script.run(); - if (!res.success) return false; - const field = res.result; - if (field instanceof Field) { - props.Document.Set(props.fieldKey, field); - return true; - } else { - let dataField = ToField(field); - if (dataField) { - props.Document.Set(props.fieldKey, dataField); + return field || ""; + }} + SetValue={(value: string) => { + let script = CompileScript(value, { addReturn: true }); + if (!script.compiled) { + return false; + } + let res = script.run(); + if (!res.success) return false; + const field = res.result; + if (field instanceof Field) { + props.Document.Set(props.fieldKey, field); return true; + } else { + let dataField = ToField(field); + if (dataField) { + props.Document.Set(props.fieldKey, dataField); + return true; + } } - } - return false; - }}> + return false; + }}> + ); } -- cgit v1.2.3-70-g09d2 From 582e9f5ed1da107f0fb0ae3c0e15027f79d4187a Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 17 Apr 2019 21:50:33 -0400 Subject: fixed docking view and freeform to not need --- .../views/collections/CollectionDockingView.scss | 4 -- .../views/collections/CollectionDockingView.tsx | 49 ++++++++++----------- .../collectionFreeForm/CollectionFreeFormView.scss | 9 +--- .../collectionFreeForm/CollectionFreeFormView.tsx | 50 +++++++++------------- 4 files changed, 44 insertions(+), 68 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss') diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss index b4d9efc47..0e7e0afa7 100644 --- a/src/client/views/collections/CollectionDockingView.scss +++ b/src/client/views/collections/CollectionDockingView.scss @@ -2,10 +2,6 @@ .collectiondockingview-content { height: 100%; - text-align:center; -} -.collectiondockingview-content-height { - height: 100%; } .lm_active .messageCounter{ color:white; diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 62321b7a8..39e27b601 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -316,7 +316,7 @@ interface DockedFrameProps { @observer export class DockedFrameRenderer extends React.Component { - private _mainCont = React.createRef(); + _mainCont = React.createRef(); @observable private _panelWidth = 0; @observable private _panelHeight = 0; @observable private _document: Opt; @@ -326,38 +326,32 @@ export class DockedFrameRenderer extends React.Component { Server.GetField(this.props.documentId, action((f: Opt) => this._document = f as Document)); } - private _nativeWidth = () => this._document!.GetNumber(KeyStore.NativeWidth, this._panelWidth); - private _nativeHeight = () => this._document!.GetNumber(KeyStore.NativeHeight, this._panelHeight); - private _contentScaling = () => { - let wscale = this._panelWidth / (this._nativeWidth() ? this._nativeWidth() : this._panelWidth); - if (wscale * this._nativeHeight() > this._panelHeight) - return this._panelHeight / (this._nativeHeight() ? this._nativeHeight() : this._panelHeight); + nativeWidth = () => this._document!.GetNumber(KeyStore.NativeWidth, this._panelWidth); + nativeHeight = () => this._document!.GetNumber(KeyStore.NativeHeight, this._panelHeight); + contentScaling = () => { + let wscale = this._panelWidth / (this.nativeWidth() ? this.nativeWidth() : this._panelWidth); + if (wscale * this.nativeHeight() > this._panelHeight) + return this._panelHeight / (this.nativeHeight() ? this.nativeHeight() : this._panelHeight); return wscale; } ScreenToLocalTransform = () => { let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont.current!.children[0].firstChild as HTMLElement); scale = Utils.GetScreenTransform(this._mainCont.current!).scale; - return CollectionDockingView.Instance.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(scale / this._contentScaling()); + return CollectionDockingView.Instance.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(scale / this.contentScaling()); } - get previewPanelCenteringOffset() { return (this._panelWidth - this._nativeWidth() * this._contentScaling()) / 2; } + get previewPanelCenteringOffset() { return (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2; } - - render() { - if (!this._document) { - return (null); - } - let wscale = this._panelWidth / (this._nativeWidth() ? this._nativeWidth() : this._panelWidth); - let name = (wscale * this._nativeHeight() > this._panelHeight) ? "" : "-height"; - var content = -
- { whenActiveChanged={emptyFunction} focus={emptyDocFunction} ContainingCollectionView={undefined} /> -
; +
); + } - return { this._panelWidth = r.entry.width; this._panelHeight = r.entry.height; })}> - {({ measureRef }) =>
{content}
} -
; + render() { + return !this._document ? (null) : + { this._panelWidth = r.entry.width; this._panelHeight = r.entry.height; })}> + {({ measureRef }) =>
{this.content}
} +
; } } \ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss index 392bd514f..57706b51e 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -1,11 +1,4 @@ @import "../../globalCssVariables"; -.collectionfreeformview-measure { - position: inherit; - top: 0; - left: 0; - width: 100%; - height: 100%; - } .collectionfreeformview { position: inherit; top: 0; @@ -52,7 +45,7 @@ } opacity: 0.99; - border-width: 0; + border-width: 0; border-color: transparent; border-style: solid; border-radius: $border-radius; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 80322c900..d4385b12c 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -28,8 +28,8 @@ export class CollectionFreeFormView extends CollectionSubView { private _selectOnLoaded: string = ""; // id of document that should be selected once it's loaded (used for click-to-type) private _lastX: number = 0; private _lastY: number = 0; - @observable private _pwidth: number = 0; - @observable private _pheight: number = 0; + private get _pwidth() { return this.props.PanelWidth(); } + private get _pheight() { return this.props.PanelHeight(); } @computed get nativeWidth() { return this.props.Document.GetNumber(KeyStore.NativeWidth, 0); } @computed get nativeHeight() { return this.props.Document.GetNumber(KeyStore.NativeHeight, 0); } @@ -268,11 +268,6 @@ export class CollectionFreeFormView extends CollectionSubView { return docviews; } - @action - onResize = (r: any) => { - this._pwidth = r.entry.width; - this._pheight = r.entry.height; - } @action onCursorMove = (e: React.PointerEvent) => { super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY)); @@ -281,29 +276,24 @@ export class CollectionFreeFormView extends CollectionSubView { render() { const containerName = `collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`; return ( - - {({ measureRef }) => ( -
-
- - - - - - {this.childViews} - - - - - - -
-
)} -
+
+ + + + + + {this.childViews} + + + + + + +
); } } -- cgit v1.2.3-70-g09d2 From 575d8b339cdf74cdcb8d46dcd6e627aec2dda636 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 24 Apr 2019 23:17:44 -0400 Subject: added borderRadius and fixed a bunch of broken props along the way. --- src/client/documents/Documents.ts | 2 ++ src/client/views/Main.scss | 3 ++- src/client/views/Main.tsx | 3 ++- src/client/views/MainOverlayTextBox.tsx | 4 ++-- src/client/views/collections/CollectionBaseView.tsx | 7 ++++--- src/client/views/collections/CollectionDockingView.tsx | 3 ++- src/client/views/collections/CollectionSchemaView.tsx | 6 +++++- src/client/views/collections/CollectionSubView.tsx | 1 + src/client/views/collections/CollectionTreeView.tsx | 5 ++++- .../collectionFreeForm/CollectionFreeFormView.scss | 1 + .../collectionFreeForm/CollectionFreeFormView.tsx | 14 +++++++++++--- .../views/collections/collectionFreeForm/MarqueeView.tsx | 7 ++++--- src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 11 +++++++++++ src/client/views/nodes/DocumentView.tsx | 2 ++ src/client/views/nodes/FieldView.tsx | 7 ++++++- src/client/views/nodes/FormattedTextBox.scss | 3 +-- src/client/views/nodes/FormattedTextBox.tsx | 5 ++++- src/client/views/nodes/ImageBox.scss | 3 --- src/client/views/nodes/ImageBox.tsx | 2 +- src/fields/KeyStore.ts | 3 ++- 20 files changed, 67 insertions(+), 25 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 0e6661819..879b114b6 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -55,6 +55,7 @@ export interface DocumentOptions { backgroundColor?: string; copyDraggedItems?: boolean; documentText?: string; + borderRounding?: number; } export namespace Documents { @@ -108,6 +109,7 @@ export namespace Documents { if (options.layout !== undefined) { doc.SetText(KeyStore.Layout, options.layout); } if (options.layoutKeys !== undefined) { doc.Set(KeyStore.LayoutKeys, new ListField(options.layoutKeys)); } if (options.copyDraggedItems !== undefined) { doc.SetBoolean(KeyStore.CopyDraggedItems, options.copyDraggedItems); } + if (options.borderRounding !== undefined) { doc.SetNumber(KeyStore.BorderRounding, options.borderRounding); } return doc; } diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss index 4373534b2..3edc79d39 100644 --- a/src/client/views/Main.scss +++ b/src/client/views/Main.scss @@ -42,7 +42,8 @@ h1 { } .jsx-parser { - width:100% + width:100%; + pointer-events: none; } p { diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 934616aca..057f68ed9 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -17,7 +17,7 @@ import { CurrentUserUtils } from '../../server/authentication/models/current_use import { MessageStore } from '../../server/Message'; import { RouteStore } from '../../server/RouteStore'; import { ServerUtils } from '../../server/ServerUtil'; -import { emptyDocFunction, emptyFunction, returnTrue, Utils, returnOne } from '../../Utils'; +import { emptyDocFunction, emptyFunction, returnTrue, Utils, returnOne, returnZero } from '../../Utils'; import { Documents } from '../documents/Documents'; import { ColumnAttributeModel } from '../northstar/core/attribute/AttributeModel'; import { AttributeTransformationModel } from '../northstar/core/attribute/AttributeTransformationModel'; @@ -197,6 +197,7 @@ export class Main extends React.Component { isTopMost={true} selectOnLoad={false} focus={emptyDocFunction} + borderRounding={returnZero} parentActive={returnTrue} whenActiveChanged={emptyFunction} ContainingCollectionView={undefined} />} diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx index 9aaaad084..f98f6e8a5 100644 --- a/src/client/views/MainOverlayTextBox.tsx +++ b/src/client/views/MainOverlayTextBox.tsx @@ -5,7 +5,7 @@ import * as React from 'react'; import { Document } from '../../fields/Document'; import { Key } from '../../fields/Key'; import { KeyStore } from '../../fields/KeyStore'; -import { emptyDocFunction, emptyFunction, returnTrue } from '../../Utils'; +import { emptyDocFunction, emptyFunction, returnTrue, returnZero } from '../../Utils'; import '../northstar/model/ModelExtensions'; import '../northstar/utils/Extensions'; import { DragManager } from '../util/DragManager'; @@ -97,7 +97,7 @@ export class MainOverlayTextBox extends React.Component style={{ width: `${this.TextDoc.Width()}px`, height: `${this.TextDoc.Height()}px` }}> + ScreenToLocalTransform={this._textXf} borderRounding={returnZero} PanelWidth={returnZero} PanelHeight={returnZero} focus={emptyDocFunction} />
; } diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index 097236c1d..e65770137 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -2,13 +2,12 @@ import { action, computed } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Document } from '../../../fields/Document'; -import { Field, FieldValue, FieldWaiting } from '../../../fields/Field'; +import { FieldValue, FieldWaiting } from '../../../fields/Field'; import { KeyStore } from '../../../fields/KeyStore'; import { ListField } from '../../../fields/ListField'; import { NumberField } from '../../../fields/NumberField'; import { ContextMenu } from '../ContextMenu'; import { FieldViewProps } from '../nodes/FieldView'; -import { TextField } from '../../../fields/TextField'; export enum CollectionViewType { Invalid, @@ -190,7 +189,9 @@ export class CollectionBaseView extends React.Component { }; const viewtype = this.collectionViewType; return ( -
+
{viewtype !== undefined ? this.props.children(viewtype, props) : (null)}
); diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 84159635a..eb94a4e6d 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -8,7 +8,7 @@ import { Document } from "../../../fields/Document"; import { KeyStore } from "../../../fields/KeyStore"; import Measure from "react-measure"; import { FieldId, Opt, Field, FieldWaiting } from "../../../fields/Field"; -import { Utils, returnTrue, emptyFunction, emptyDocFunction, returnOne } from "../../../Utils"; +import { Utils, returnTrue, emptyFunction, emptyDocFunction, returnOne, returnZero } from "../../../Utils"; import { Server } from "../../Server"; import { undoBatch } from "../../util/UndoManager"; import { DocumentView } from "../nodes/DocumentView"; @@ -368,6 +368,7 @@ export class DockedFrameRenderer extends React.Component { parentActive={returnTrue} whenActiveChanged={emptyFunction} focus={emptyDocFunction} + borderRounding={returnZero} ContainingCollectionView={undefined} />
); } diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index cb7a67991..dc2910ede 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -12,7 +12,7 @@ import { Field, Opt } from "../../../fields/Field"; import { Key } from "../../../fields/Key"; import { KeyStore } from "../../../fields/KeyStore"; import { ListField } from "../../../fields/ListField"; -import { emptyDocFunction, emptyFunction, returnFalse } from "../../../Utils"; +import { emptyDocFunction, emptyFunction, returnFalse, returnZero } from "../../../Utils"; import { Server } from "../../Server"; import { SetupDrag } from "../../util/DragManager"; import { CompileScript, ToField } from "../../util/Scripting"; @@ -77,6 +77,9 @@ export class CollectionSchemaView extends CollectionSubView { focus: emptyDocFunction, active: returnFalse, whenActiveChanged: emptyFunction, + borderRounding: this.props.borderRounding, + PanelHeight: returnZero, + PanelWidth: returnZero, }; let contents = ( @@ -275,6 +278,7 @@ export class CollectionSchemaView extends CollectionSubView { focus={emptyDocFunction} parentActive={this.props.active} whenActiveChanged={this.props.whenActiveChanged} + borderRounding={this.props.borderRounding} />
boolean) => boolean; PanelWidth: () => number; PanelHeight: () => number; + borderRounding: () => number; } export interface SubCollectionViewProps extends CollectionViewProps { diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index e0387f4b4..b9d1f0bd9 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -136,7 +136,10 @@ export class CollectionTreeView extends CollectionSubView { ); return ( -
e.stopPropagation()} onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget}> +
e.stopPropagation()} + onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget}>
.jsx-parser { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 7492d8744..9e2c9bf9a 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -257,6 +257,7 @@ export class CollectionFreeFormView extends CollectionSubView { focus: this.focusDocument, parentActive: this.props.active, whenActiveChanged: this.props.active, + borderRounding: this.props.borderRounding, }; } @@ -288,11 +289,17 @@ export class CollectionFreeFormView extends CollectionSubView { const containerName = `collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`; return (
- + + {this.props.Document.Title} + + */} + - @@ -340,6 +347,7 @@ interface CollectionFreeFormViewPannableContentsProps { panX: () => number; panY: () => number; zoomScaling: () => number; + borderRadius: () => number; } @observer @@ -350,7 +358,7 @@ class CollectionFreeFormViewPannableContents extends React.Component otherwise, reactions won't fire - return
+ return
{this.props.children}
; } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 898fff019..e724ab47e 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -14,7 +14,6 @@ import { CollectionFreeFormView } from "./CollectionFreeFormView"; import "./MarqueeView.scss"; import React = require("react"); import { Utils } from "../../../../Utils"; -import { ListField } from "../../../../fields/ListField"; interface MarqueeViewProps { getContainerTransform: () => Transform; @@ -25,6 +24,7 @@ interface MarqueeViewProps { selectDocuments: (docs: Document[]) => void; removeDocument: (doc: Document) => boolean; addLiveTextDocument: (doc: Document) => void; + borderRadius: () => number; } @observer @@ -138,7 +138,7 @@ export class MarqueeView extends React.Component this.cleanupInteractions(true); e.stopPropagation(); } - if (e.key === "c" || e.key === "r") { + if (e.key === "c" || e.key === "r" || e.key === "e") { e.stopPropagation(); let bounds = this.Bounds; let selected = this.marqueeSelect().map(d => { @@ -156,6 +156,7 @@ export class MarqueeView extends React.Component y: bounds.top, panx: 0, pany: 0, + borderRounding: e.key === "e" ? -1 : undefined, backgroundColor: selected.length ? "white" : "", scale: zoomBasis, width: bounds.width * zoomBasis, @@ -250,7 +251,7 @@ export class MarqueeView extends React.Component } render() { - return
+ return
{this.props.children} {!this._visible ? (null) : this.marqueeDiv}
; diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 420324d40..8caf5ff31 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -65,6 +65,7 @@ export class CollectionFreeFormDocumentView extends React.Component; } @@ -148,6 +149,15 @@ export class CollectionFreeFormDocumentView extends React.Component { + let br = this.props.Document.GetNumber(KeyStore.BorderRounding, 0); + return br >= 0 ? br : + this.props.Document.GetNumber(KeyStore.NativeWidth, 0) === 0 ? + Math.min(this.props.PanelWidth(), this.props.PanelHeight()) + : + Math.min(this.props.Document.GetNumber(KeyStore.NativeWidth, 0), this.props.Document.GetNumber(KeyStore.NativeHeight, 0)); + } + render() { let maximizedDoc = this.props.Document.GetT(KeyStore.MaximizedDoc, Document); let zoomFade = 1; @@ -168,6 +178,7 @@ export class CollectionFreeFormDocumentView extends React.Component boolean; whenActiveChanged: (isActive: boolean) => void; toggleMinimized: () => void; + borderRounding: () => number; } export interface JsxArgs extends DocumentViewProps { Keys: { [name: string]: Key }; @@ -277,6 +278,7 @@ export class DocumentView extends React.Component {
boolean; whenActiveChanged: (isActive: boolean) => void; focus: (doc: Document) => void; + PanelWidth: () => number; + PanelHeight: () => number; + borderRounding: () => number; } @observer @@ -100,6 +103,8 @@ export class FieldView extends React.Component { layoutKey={KeyStore.Layout} ContainingCollectionView={this.props.ContainingCollectionView} parentActive={this.props.active} + borderRounding={returnZero} + toggleMinimized={emptyFunction} whenActiveChanged={this.props.whenActiveChanged} /> ); } diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index 5eb2bf7ce..59857bab3 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -22,11 +22,10 @@ overflow-x: hidden; color: initial; height: 100%; - pointer-events: all; + pointer-events: none; } .formattedTextBox-cont-hidden { overflow: hidden; - pointer-events: none; } .menuicon { diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 9cd58c73a..4b2fdbaff 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -273,7 +273,10 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte let color = this.props.Document.GetText(KeyStore.BackgroundColor, ""); return (
{ let nativeWidth = this.props.Document.GetNumber(KeyStore.NativeWidth, 1); let interactive = InkingControl.Instance.selectedTool ? "" : "interactive" return ( -
+
Image not found {paths.length > 1 ? this.dots(paths) : (null)} {this.lightbox(paths)} diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts index 0a96beb50..aa18a9f33 100644 --- a/src/fields/KeyStore.ts +++ b/src/fields/KeyStore.ts @@ -49,12 +49,13 @@ export namespace KeyStore { export const MinimizedDoc = new Key("MinimizedDoc"); export const MaximizedDoc = new Key("MaximizedDoc"); export const CopyDraggedItems = new Key("CopyDraggedItems"); + export const BorderRounding = new Key("BorderRounding"); export const KeyList: Key[] = [Prototype, X, Y, Page, Title, Author, PanX, PanY, Scale, NativeWidth, NativeHeight, Width, Height, ZIndex, ZoomBasis, Data, Annotations, ViewType, Layout, BackgroundColor, BackgroundLayout, OverlayLayout, LayoutKeys, LayoutFields, ColumnsKey, SchemaSplitPercentage, Caption, ActiveWorkspace, DocumentText, BrushingDocs, LinkedToDocs, LinkedFromDocs, LinkDescription, LinkTags, Thumbnail, ThumbnailPage, CurPage, AnnotationOn, NumPages, Ink, Cursors, OptionalRightCollection, - Archives, Workspaces, IsMinimized, MinimizedDoc, MaximizedDoc, CopyDraggedItems + Archives, Workspaces, IsMinimized, MinimizedDoc, MaximizedDoc, CopyDraggedItems, BorderRounding ]; export function KeyLookup(keyid: string) { for (const key of KeyList) { -- cgit v1.2.3-70-g09d2 From 007433dabbd6a8a5f702ac393ecd2b40b1c3a9d8 Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 8 May 2019 18:31:14 -0400 Subject: fixes for templates including changing the relative order of CollectionOverlayView in the stack --- src/client/views/MainOverlayTextBox.tsx | 1 + src/client/views/Templates.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormLinksView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.scss | 8 ++++++-- .../collectionFreeForm/CollectionFreeFormView.tsx | 15 +++++---------- .../views/collections/collectionFreeForm/MarqueeView.tsx | 3 +++ src/client/views/nodes/FormattedTextBox.scss | 1 + src/client/views/nodes/FormattedTextBox.tsx | 6 ++---- 8 files changed, 20 insertions(+), 18 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss') diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx index d32e3f21b..3b75c248a 100644 --- a/src/client/views/MainOverlayTextBox.tsx +++ b/src/client/views/MainOverlayTextBox.tsx @@ -43,6 +43,7 @@ export class MainOverlayTextBox extends React.Component this._textXf = tx ? tx : () => Transform.Identity(); this._textTargetDiv = div; if (div) { + if (div.parentElement && div.parentElement instanceof HTMLDivElement && div.parentElement.id === "screenSpace") this._textXf = () => Transform.Identity(); this._textColor = div.style.color; div.style.color = "transparent"; this.TextScroll = div.scrollTop; diff --git a/src/client/views/Templates.tsx b/src/client/views/Templates.tsx index 6f706bdc5..02f9aa510 100644 --- a/src/client/views/Templates.tsx +++ b/src/client/views/Templates.tsx @@ -39,7 +39,7 @@ export namespace Templates { // export const BasicLayout = new Template("Basic layout", "{layout}"); export const OuterCaption = new Template("Outer caption", TemplatePosition.OutterBottom, - `
{layout}
` + `
` ); export const InnerCaption = new Template("Inner caption", TemplatePosition.InnerBottom, diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index 2d815a302..cbfbb1d2c 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -1,4 +1,4 @@ -import { computed, IReactionDisposer, reaction } from "mobx"; +import { computed, IReactionDisposer, reaction, trace } from "mobx"; import { observer } from "mobx-react"; import { Utils } from "../../../../Utils"; import { DocumentManager } from "../../../util/DocumentManager"; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss index cb849b325..063c9e2cf 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -37,7 +37,9 @@ border-radius: $border-radius; box-sizing: border-box; position: absolute; - overflow: hidden; + .marqueeView { + overflow: hidden; + } top: 0; left: 0; width: 100%; @@ -61,7 +63,9 @@ border-radius: $border-radius; box-sizing: border-box; position:absolute; - overflow: hidden; + .marqueeView { + overflow: hidden; + } top: 0; left: 0; width: 100%; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index fcc73d5b6..797f94d5f 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -110,15 +110,11 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { @action onPointerDown = (e: React.PointerEvent): void => { - let childSelected = Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), [] as Doc[]).filter(doc => doc).reduce((childSelected, doc) => { - var dv = DocumentManager.Instance.getDocumentView(doc); - return childSelected || (dv && SelectionManager.IsSelected(dv) ? true : false); - }, false); if ((CollectionFreeFormView.RIGHT_BTN_DRAG && (((e.button === 2 && (!this.isAnnotationOverlay || this.zoomScaling() !== 1)) || - (e.button === 0 && e.altKey)) && (childSelected || this.props.active()))) || + (e.button === 0 && e.altKey)) && this.props.active())) || (!CollectionFreeFormView.RIGHT_BTN_DRAG && - ((e.button === 0 && !e.altKey && (!this.isAnnotationOverlay || this.zoomScaling() !== 1)) && (childSelected || this.props.active())))) { + ((e.button === 0 && !e.altKey && (!this.isAnnotationOverlay || this.zoomScaling() !== 1)) && this.props.active()))) { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); document.addEventListener("pointermove", this.onPointerMove); @@ -233,7 +229,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { return NumCast(doc1.zIndex) - NumCast(doc2.zIndex); }).forEach((doc, index) => doc.zIndex = index + 1); doc.zIndex = docs.length + 1; - return doc; } focusDocument = (doc: Doc) => { @@ -316,18 +311,18 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { {/* */} - +
); } } @observer -class CollectionFreeFormOverlayView extends React.Component { +class CollectionFreeFormOverlayView extends React.Component boolean }> { @computed get overlayView() { return (); + isTopMost={this.props.isTopMost} isSelected={this.props.isSelected} select={emptyFunction} />); } render() { return this.overlayView; diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 9764db1d4..740c50297 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -101,6 +101,8 @@ export class MarqueeView extends React.Component document.addEventListener("pointermove", this.onPointerMove, true); document.addEventListener("pointerup", this.onPointerUp, true); document.addEventListener("keydown", this.marqueeCommand, true); + console.log(this.props.container.props.Document.title); + e.stopPropagation(); } if (e.altKey) { e.preventDefault(); @@ -180,6 +182,7 @@ export class MarqueeView extends React.Component if (ink) { this.marqueeInkDelete(ink.inkData); } + SelectionManager.DeselectAll(); this.cleanupInteractions(false); e.stopPropagation(); } diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index 9e58a8e7f..458a62c5b 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -17,6 +17,7 @@ border-radius: inherit; border-color: $intermediate-color; box-sizing: border-box; + background-color: inherit; border-style: solid; overflow-y: scroll; overflow-x: hidden; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index ee6000da7..4b3172e82 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -24,8 +24,8 @@ import { StrCast, Cast, NumCast, BoolCast } from "../../../new_fields/Types"; import { RichTextField } from "../../../new_fields/RichTextField"; import { Id } from "../../../new_fields/RefField"; import { UndoManager } from "../../util/UndoManager"; -const { buildMenuItems } = require("prosemirror-example-setup"); -const { menuBar } = require("prosemirror-menu"); +import { Transform } from "prosemirror-transform"; +import { Transform as MatrixTransform } from "../../util/Transform"; // FormattedTextBox: Displays an editable plain text node that maps to a specified Key of a Document // @@ -306,13 +306,11 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe render() { let style = this.props.isOverlay ? "scroll" : "hidden"; let rounded = NumCast(this.props.Document.borderRounding) < 0 ? "-rounded" : ""; - let color = StrCast(this.props.Document.backgroundColor); let interactive = InkingControl.Instance.selectedTool ? "" : "interactive"; return (