aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections
diff options
context:
space:
mode:
authorSam Wilkins <samwilkins333@gmail.com>2019-09-12 03:10:25 -0400
committerSam Wilkins <samwilkins333@gmail.com>2019-09-12 03:10:25 -0400
commitd68dfd98a75d188a832da6f27d641b451fca7c56 (patch)
tree2103e87d335d9651e1878748a4fc7c9c6f9f7a13 /src/client/views/collections
parent2dd8b13fd3fa30fc390251ed75da3207efed4d5b (diff)
parent186d7aed7b99b1373e99b51cfe0c88c8167c8290 (diff)
merged with master and batch directory upload requests
Diffstat (limited to 'src/client/views/collections')
-rw-r--r--src/client/views/collections/CollectionBaseView.tsx3
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx2
-rw-r--r--src/client/views/collections/CollectionSchemaCells.tsx3
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx10
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx24
-rw-r--r--src/client/views/collections/ParentDocumentSelector.tsx4
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx8
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx8
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx99
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx41
10 files changed, 164 insertions, 38 deletions
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index b6ed6aaa0..b7036b3ff 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -12,6 +12,7 @@ import { ContextMenu } from '../ContextMenu';
import { FieldViewProps } from '../nodes/FieldView';
import './CollectionBaseView.scss';
import { DateField } from '../../../new_fields/DateField';
+import { DocumentType } from '../../documents/DocumentTypes';
export enum CollectionViewType {
Invalid,
@@ -126,7 +127,7 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
let targetDataDoc = this.props.fieldExt || this.props.Document.isTemplate ? this.extensionDoc : this.props.Document;
let targetField = (this.props.fieldExt || this.props.Document.isTemplate) && this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey;
let value = Cast(targetDataDoc[targetField], listSpec(Doc), []);
- let index = value.reduce((p, v, i) => (v instanceof Doc && v[Id] === doc[Id]) ? i : p, -1);
+ let index = value.reduce((p, v, i) => (v instanceof Doc && Doc.AreProtosEqual(v, doc)) ? i : p, -1);
PromiseValue(Cast(doc.annotationOn, Doc)).then(annotationOn =>
annotationOn === this.dataDoc.Document && (doc.annotationOn = undefined));
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 95f94875c..fb8b0c41b 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -607,7 +607,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
}
return Transform.Identity();
}
- get previewPanelCenteringOffset() { return this.nativeWidth && !BoolCast(this._document!.ignoreAspect) ? (this._panelWidth - this.nativeWidth()) / 2 : 0; }
+ get previewPanelCenteringOffset() { return this.nativeWidth() && !BoolCast(this._document!.ignoreAspect) ? (this._panelWidth - this.nativeWidth()) / 2 : 0; }
addDocTab = (doc: Doc, dataDoc: Doc | undefined, location: string) => {
if (doc.dockingConfig) {
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 9c26a08f0..c59107b53 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -214,7 +214,8 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
isEditingCallback={this.isEditingCallback}
display={"inline"}
contents={contents}
- height={Number(MAX_ROW_HEIGHT)}
+ height={"auto"}
+ maxHeight={Number(MAX_ROW_HEIGHT)}
GetValue={() => {
let field = props.Document[props.fieldKey];
if (Field.IsField(field)) {
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 97b31bf2a..91e10b0ac 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -310,6 +310,10 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
sectionMasonry(heading: SchemaHeaderField | undefined, docList: Doc[]) {
let cols = Math.max(1, Math.min(docList.length,
Math.floor((this.props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap))));
+ if (isNaN(cols)) {
+ console.log("naN");
+ cols = 1;
+ }
return <div key={heading ? heading.heading : "empty"} className="collectionStackingView-masonrySection">
{!heading ? (null) :
<div key={`${heading.heading}`} className="collectionStackingView-sectionHeader" style={{ background: heading.color }}
@@ -358,8 +362,12 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
subItems.push({ description: `${this.props.Document.fillColumn ? "Variable Size" : "Autosize"} Column`, event: () => this.props.Document.fillColumn = !this.props.Document.fillColumn, icon: "plus" });
subItems.push({ description: `${this.props.Document.showTitles ? "Hide Titles" : "Show Titles"}`, event: () => this.props.Document.showTitles = !this.props.Document.showTitles ? "title" : "", icon: "plus" });
subItems.push({ description: `${this.props.Document.showCaptions ? "Hide Captions" : "Show Captions"}`, event: () => this.props.Document.showCaptions = !this.props.Document.showCaptions ? "caption" : "", icon: "plus" });
- subItems.push({ description: "Edit onChildClick script", icon: "edit", event: () => ScriptBox.EditClickScript(this.props.Document, "onChildClick") });
ContextMenu.Instance.addItem({ description: "Stacking Options ...", subitems: subItems, icon: "eye" });
+
+ let existingOnClick = ContextMenu.Instance.findByDescription("OnClick...");
+ let onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : [];
+ onClicks.push({ description: "Edit onChildClick script", icon: "edit", event: (obj: any) => ScriptBox.EditButtonScript("On Child Clicked...", this.props.Document, "onChildClick", obj.x, obj.y) });
+ !existingOnClick && ContextMenu.Instance.addItem({ description: "OnClick...", subitems: onClicks, icon: "hand-point-right" });
}
}
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 50f03005c..f5bb76966 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -52,6 +52,7 @@ export interface TreeViewProps {
active: () => boolean;
showHeaderFields: () => boolean;
preventTreeViewOpen: boolean;
+ renderedIds: string[];
}
library.add(faTrashAlt);
@@ -274,7 +275,9 @@ class TreeView extends React.Component<TreeViewProps> {
let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false, true);
contentElement = TreeView.GetChildElements(contents instanceof Doc ? [contents] :
DocListCast(contents), this.props.treeViewId, doc, undefined, key, addDoc, remDoc, this.move,
- this.props.dropAction, this.props.addDocTab, this.props.pinToPres, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.renderDepth, this.props.showHeaderFields, this.props.preventTreeViewOpen);
+ this.props.dropAction, this.props.addDocTab, this.props.pinToPres, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active,
+ this.props.panelWidth, this.props.renderDepth, this.props.showHeaderFields, this.props.preventTreeViewOpen,
+ [...this.props.renderedIds, doc[Id]]);
} else {
contentElement = <EditableView
key="editableView"
@@ -306,7 +309,8 @@ class TreeView extends React.Component<TreeViewProps> {
TreeView.GetChildElements(docs as Doc[], this.props.treeViewId, this.props.document.layout as Doc,
this.resolvedDataDoc, expandKey, addDoc, remDoc, this.move,
this.props.dropAction, this.props.addDocTab, this.props.pinToPres, this.props.ScreenToLocalTransform,
- this.props.outerXf, this.props.active, this.props.panelWidth, this.props.renderDepth, this.props.showHeaderFields, this.props.preventTreeViewOpen)}
+ this.props.outerXf, this.props.active, this.props.panelWidth, this.props.renderDepth, this.props.showHeaderFields, this.props.preventTreeViewOpen,
+ [...this.props.renderedIds, this.props.document[Id]])}
</ul >;
} else if (this.treeViewExpandedView === "fields") {
return <ul><div ref={this._dref} style={{ display: "inline-block" }} key={this.props.document[Id] + this.props.document.title}>
@@ -373,6 +377,7 @@ class TreeView extends React.Component<TreeViewProps> {
style={{
color: this.props.document.isMinimized ? "red" : "black",
background: Doc.IsBrushed(this.props.document) ? "#06121212" : "0",
+ fontWeight: this.props.document.search_string ? "bold" : undefined,
outline: BoolCast(this.props.document.workspaceBrush) ? "dashed 1px #06123232" : undefined,
pointerEvents: this.props.active() || SelectionManager.GetIsDragging() ? "all" : "none"
}} >
@@ -391,7 +396,7 @@ class TreeView extends React.Component<TreeViewProps> {
{this.renderTitle}
</div>
<div className="treeViewItem-border">
- {!this.treeViewOpen ? (null) : this.renderContent}
+ {!this.treeViewOpen || this.props.renderedIds.indexOf(this.props.document[Id]) !== -1 ? (null) : this.renderContent}
</div>
</li>
</div>;
@@ -414,7 +419,8 @@ class TreeView extends React.Component<TreeViewProps> {
panelWidth: () => number,
renderDepth: number,
showHeaderFields: () => boolean,
- preventTreeViewOpen: boolean
+ preventTreeViewOpen: boolean,
+ renderedIds: string[]
) {
let docs = docList.filter(child => !child.excludeFromLibrary && child.opacity !== 0);
let viewSpecScript = Cast(containingCollection.viewSpecScript, ScriptField);
@@ -501,7 +507,8 @@ class TreeView extends React.Component<TreeViewProps> {
parentKey={key}
active={active}
showHeaderFields={showHeaderFields}
- preventTreeViewOpen={preventTreeViewOpen} />;
+ preventTreeViewOpen={preventTreeViewOpen}
+ renderedIds={renderedIds} />;
});
}
}
@@ -591,13 +598,14 @@ export class CollectionTreeView extends CollectionSubView(Document) {
<div id="body" className="collectionTreeView-dropTarget"
style={{ overflow: "auto", background: StrCast(this.props.Document.backgroundColor, "lightgray") }}
onContextMenu={this.onContextMenu}
- onWheel={(e: React.WheelEvent) => (e.target as any).scrollHeight > (e.target as any).clientHeight && e.stopPropagation()}
+ onWheel={(e: React.WheelEvent) => this._mainEle && this._mainEle.scrollHeight > this._mainEle.clientHeight && e.stopPropagation()}
onDrop={this.onTreeDrop}
ref={this.createTreeDropTarget}>
<EditableView
contents={this.resolvedDataDoc.title}
display={"block"}
- height={72}
+ maxHeight={72}
+ height={"auto"}
GetValue={() => StrCast(this.resolvedDataDoc.title)}
SetValue={undoBatch((value: string) => (Doc.GetProto(this.resolvedDataDoc).title = value) ? true : true)}
OnFillDown={undoBatch((value: string) => {
@@ -614,7 +622,7 @@ export class CollectionTreeView extends CollectionSubView(Document) {
TreeView.GetChildElements(this.childDocs, this.props.Document[Id], this.props.Document, this.props.DataDoc, this.props.fieldKey, addDoc, this.remove,
moveDoc, dropAction, this.props.addDocTab, this.props.pinToPres, this.props.ScreenToLocalTransform,
this.outerXf, this.props.active, this.props.PanelWidth, this.props.renderDepth, () => this.props.Document.chromeStatus !== "disabled",
- BoolCast(this.props.Document.preventTreeViewOpen))
+ BoolCast(this.props.Document.preventTreeViewOpen), [])
}
</ul>
</div >
diff --git a/src/client/views/collections/ParentDocumentSelector.tsx b/src/client/views/collections/ParentDocumentSelector.tsx
index 17111af58..d8475a467 100644
--- a/src/client/views/collections/ParentDocumentSelector.tsx
+++ b/src/client/views/collections/ParentDocumentSelector.tsx
@@ -38,8 +38,8 @@ export class SelectorContextMenu extends React.Component<SelectorProps> {
return () => {
col = Doc.IsPrototype(col) ? Doc.MakeDelegate(col) : col;
if (NumCast(col.viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) {
- const newPanX = NumCast(target.x) + NumCast(target.width) / NumCast(target.zoomBasis, 1) / 2;
- const newPanY = NumCast(target.y) + NumCast(target.height) / NumCast(target.zoomBasis, 1) / 2;
+ const newPanX = NumCast(target.x) + NumCast(target.width) / 2;
+ const newPanY = NumCast(target.y) + NumCast(target.height) / 2;
col.panX = newPanX;
col.panY = newPanY;
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
index 6af87b138..790c6694b 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
@@ -39,10 +39,10 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
// let l = this.props.LinkDocs;
let a = this.props.A;
let b = this.props.B;
- let x1 = NumCast(a.x) + (BoolCast(a.isMinimized, false) ? 5 : NumCast(a.width) / NumCast(a.zoomBasis, 1) / 2);
- let y1 = NumCast(a.y) + (BoolCast(a.isMinimized, false) ? 5 : NumCast(a.height) / NumCast(a.zoomBasis, 1) / 2);
- let x2 = NumCast(b.x) + (BoolCast(b.isMinimized, false) ? 5 : NumCast(b.width) / NumCast(b.zoomBasis, 1) / 2);
- let y2 = NumCast(b.y) + (BoolCast(b.isMinimized, false) ? 5 : NumCast(b.height) / NumCast(b.zoomBasis, 1) / 2);
+ let x1 = NumCast(a.x) + (BoolCast(a.isMinimized, false) ? 5 : NumCast(a.width) / 2);
+ let y1 = NumCast(a.y) + (BoolCast(a.isMinimized, false) ? 5 : NumCast(a.height) / 2);
+ let x2 = NumCast(b.x) + (BoolCast(b.isMinimized, false) ? 5 : NumCast(b.width) / 2);
+ let y2 = NumCast(b.y) + (BoolCast(b.isMinimized, false) ? 5 : NumCast(b.height) / 2);
let text = "";
// let first = this.props.LinkDocs[0];
// if (this.props.LinkDocs.length === 1) text += first.title + (first.linkDescription ? "(" + StrCast(first.linkDescription) + ")" : "");
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index 2d94f1b8e..a25627dd1 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -31,8 +31,8 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
// let srcTarg = srcDoc;
// let x1 = NumCast(srcDoc.x);
// let x2 = NumCast(dstDoc.x);
- // let x1w = NumCast(srcDoc.width, -1) / NumCast(srcDoc.zoomBasis, 1);
- // let x2w = NumCast(dstDoc.width, -1) / NumCast(srcDoc.zoomBasis, 1);
+ // let x1w = NumCast(srcDoc.width, -1);
+ // let x2w = NumCast(dstDoc.width, -1);
// if (x1w < 0 || x2w < 0 || i === j) { }
// else {
// let findBrush = (field: (Doc | Promise<Doc>)[]) => field.findIndex(brush => {
@@ -120,9 +120,9 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
render() {
return (
<div className="collectionfreeformlinksview-container">
- {/* <svg className="collectionfreeformlinksview-svgCanvas">
+ <svg className="collectionfreeformlinksview-svgCanvas">
{this.uniqueConnections}
- </svg> */}
+ </svg>
{this.props.children}
</div>
);
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 1af534ecd..3377775db 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -3,12 +3,12 @@ import { faEye } from "@fortawesome/free-regular-svg-icons";
import { faBraille, faChalkboard, faCompass, faCompressArrowsAlt, faExpandArrowsAlt, faPaintBrush, faTable, faUpload } from "@fortawesome/free-solid-svg-icons";
import { action, computed, IReactionDisposer, observable, reaction, trace } from "mobx";
import { observer } from "mobx-react";
-import { Doc, DocListCastAsync, Field, FieldResult, HeightSym, Opt, WidthSym } from "../../../../new_fields/Doc";
+import { Doc, DocListCastAsync, Field, FieldResult, HeightSym, Opt, WidthSym, DocListCast } from "../../../../new_fields/Doc";
import { Id } from "../../../../new_fields/FieldSymbols";
import { InkField, StrokeData } from "../../../../new_fields/InkField";
import { createSchema, makeInterface } from "../../../../new_fields/Schema";
import { ScriptField } from "../../../../new_fields/ScriptField";
-import { BoolCast, Cast, FieldValue, NumCast, StrCast } from "../../../../new_fields/Types";
+import { BoolCast, Cast, FieldValue, NumCast, StrCast, PromiseValue } from "../../../../new_fields/Types";
import { emptyFunction, returnEmptyString, returnOne, Utils } from "../../../../Utils";
import { CognitiveServices } from "../../../cognitive_services/CognitiveServices";
import { Docs } from "../../../documents/Documents";
@@ -39,6 +39,7 @@ import { MarqueeView } from "./MarqueeView";
import React = require("react");
import { DocServer } from "../../../DocServer";
import { FormattedTextBox } from "../../nodes/FormattedTextBox";
+import { CurrentUserUtils } from "../../../../server/authentication/models/current_user_utils";
library.add(faEye as any, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload, faBraille, faChalkboard);
@@ -153,6 +154,7 @@ export namespace PivotView {
y={pos.y}
width={pos.width}
height={pos.height}
+ jitterRotation={NumCast(target.props.Document.jitterRotation)}
{...target.getChildDocumentViewProps(doc)}
/>,
bounds: {
@@ -225,8 +227,12 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
return bounds;
}
+ @computed get actualContentBounds() {
+ return this.fitToBox && !this.isAnnotationOverlay ? this.ComputeContentBounds(this.elements.filter(e => e.bounds && !e.bounds.z).map(e => e.bounds!)) : undefined;
+ }
+
@computed get contentBounds() {
- let bounds = this.fitToBox && !this.isAnnotationOverlay ? this.ComputeContentBounds(this.elements.filter(e => e.bounds && !e.bounds.z).map(e => e.bounds!)) : undefined;
+ let bounds = this.actualContentBounds;
let res = {
panX: bounds ? (bounds.x + bounds.r) / 2 : this.Document.panX || 0,
panY: bounds ? (bounds.y + bounds.b) / 2 : this.Document.panY || 0,
@@ -252,12 +258,34 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
private getLocalTransform = (): Transform => Transform.Identity().scale(1 / this.zoomScaling()).translate(this.panX(), this.panY());
private addLiveTextBox = (newBox: Doc) => {
FormattedTextBox.SelectOnLoad = newBox[Id];// track the new text box so we can give it a prop that tells it to focus itself when it's displayed
- this.addDocument(newBox, false);
+ newBox.heading = 1;
+ for (let i = 0; i < this.childDocs.length; i++) {
+ if (this.childDocs[i].heading == 1) {
+ newBox.heading = 2;
+ }
+ }
+ PromiseValue(Cast(this.props.Document.ruleProvider, Doc)).then(ruleProvider => {
+ if (!ruleProvider) ruleProvider = this.props.Document;
+ // saturation shift
+ // let col = NumCast(ruleProvider["ruleColor_" + NumCast(newBox.heading)]);
+ // let back = Utils.fromRGBAstr(StrCast(this.props.Document.backgroundColor));
+ // let hsl = Utils.RGBToHSL(back.r, back.g, back.b);
+ // let newcol = { h: hsl.h, s: hsl.s + col, l: hsl.l };
+ // col && (Doc.GetProto(newBox).backgroundColor = Utils.toRGBAstr(Utils.HSLtoRGB(newcol.h, newcol.s, newcol.l)));
+ // OR transparency set
+ let col = StrCast(ruleProvider["ruleColor_" + NumCast(newBox.heading)]);
+ (newBox.backgroundColor === newBox.defaultBackgroundColor) && col && (Doc.GetProto(newBox).backgroundColor = col);
+
+ let round = StrCast(ruleProvider["ruleRounding_" + NumCast(newBox.heading)]);
+ round && (Doc.GetProto(newBox).borderRounding = round);
+ newBox.ruleProvider = ruleProvider;
+ this.addDocument(newBox, false);
+ });
}
private addDocument = (newBox: Doc, allowDuplicates: boolean) => {
this.props.addDocument(newBox, false);
this.bringToFront(newBox);
- this.updateClusters();
+ this.updateCluster(newBox);
return true;
}
private selectDocuments = (docs: Doc[]) => {
@@ -325,7 +353,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
this.bringToFront(d);
});
- this.updateClusters();
+ de.data.droppedDocuments.length == 1 && this.updateCluster(de.data.droppedDocuments[0]);
}
}
else if (de.data instanceof DragManager.AnnotationDragData) {
@@ -385,6 +413,8 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
return false;
}
@observable sets: (Doc[])[] = [];
+
+ @undoBatch
@action
updateClusters() {
this.sets.length = 0;
@@ -413,12 +443,42 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
this.sets.map((set, i) => set.map(member => member.cluster = i));
}
+ @undoBatch
+ @action
+ updateCluster(doc: Doc) {
+ if (this.props.Document.useClusters) {
+ this.sets.map(set => Doc.IndexOf(doc, set) !== -1 && set.splice(Doc.IndexOf(doc, set), 1));
+ let preferredInd = NumCast(doc.cluster);
+ doc.cluster = -1;
+ this.sets.map((set, i) => set.map(member => {
+ if (doc.cluster === -1 && Doc.IndexOf(member, this.childDocs) !== -1 && this.boundsOverlap(doc, member)) {
+ doc.cluster = i;
+ }
+ }));
+ if (doc.cluster === -1 && preferredInd !== -1 && (!this.sets[preferredInd] || !this.sets[preferredInd].filter(member => Doc.IndexOf(member, this.childDocs) !== -1).length)) {
+ doc.cluster = preferredInd;
+ }
+ this.sets.map((set, i) => {
+ if (doc.cluster === -1 && !set.filter(member => Doc.IndexOf(member, this.childDocs) !== -1).length) {
+ doc.cluster = i;
+ }
+ });
+ if (doc.cluster === -1) {
+ doc.cluster = this.sets.length;
+ this.sets.push([doc]);
+ } else {
+ for (let i = this.sets.length; i <= doc.cluster; i++) !this.sets[i] && this.sets.push([]);
+ this.sets[doc.cluster].push(doc);
+ }
+ }
+ }
+
getClusterColor = (doc: Doc) => {
if (this.props.Document.useClusters) {
let cluster = NumCast(doc.cluster);
if (this.sets.length <= cluster) {
- setTimeout(() => this.updateClusters(), 0);
- return;
+ setTimeout(() => this.updateCluster(doc), 0);// this.updateClusters(), 0);
+ return "";
}
let set = this.sets.length > cluster ? this.sets[cluster] : undefined;
let colors = ["#da42429e", "#31ea318c", "#8c4000", "#4a7ae2c4", "#d809ff", "#ff7601", "#1dffff", "yellow", "#1b8231f2", "#000000ad"];
@@ -743,7 +803,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
const initScript = this.Document.arrangeInit;
const script = this.Document.arrangeScript;
let state: any = undefined;
- const docs = this.childDocs;
+ let docs = this.childDocs;
+ let overlayDocs = DocListCast(this.props.Document.localOverlays);
+ overlayDocs && docs.push(...overlayDocs);
let elements: ViewDefResult[] = [];
if (initScript) {
const initResult = initScript.script.run({ docs, collection: this.Document });
@@ -766,6 +828,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
if (pair.layout && !(pair.data instanceof Promise)) {
prev.push({
ele: <CollectionFreeFormDocumentView key={doc[Id]}
+ jitterRotation={NumCast(this.props.Document.jitterRotation)}
x={script ? pos.x : undefined} y={script ? pos.y : undefined}
width={script ? pos.width : undefined} height={script ? pos.height : undefined} {...this.getChildDocumentViewProps(pair.layout, pair.data)} />,
bounds: { x: pos.x || 0, y: pos.y || 0, z: pos.z, width: NumCast(pos.width), height: NumCast(pos.height) }
@@ -870,6 +933,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
Docs.Prototypes.get(DocumentType.TEXT).defaultBackgroundColor = "#f1efeb"; // backward compatibility with databases that didn't have a default background color on prototypes
Docs.Prototypes.get(DocumentType.COL).defaultBackgroundColor = "white";
this.props.Document.useClusters = !this.props.Document.useClusters;
+ this.updateClusters();
},
icon: !this.props.Document.useClusters ? "braille" : "braille"
});
@@ -880,9 +944,22 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
});
layoutItems.push({ description: "Arrange contents in grid", event: this.arrangeContents, icon: "table" });
layoutItems.push({ description: "Analyze Strokes", event: this.analyzeStrokes, icon: "paint-brush" });
+ layoutItems.push({ description: "Jitter Rotation", event: action(() => this.props.Document.jitterRotation = 10), icon: "paint-brush" });
+
+ let noteItems: ContextMenuProps[] = [];
+ let notes = DocListCast((CurrentUserUtils.UserDocument.noteTypes as Doc).data);
+ notes.map((node, i) => noteItems.push({ description: (i + 1) + ": " + StrCast(node.title), event: () => this.createText(i), icon: "eye" }));
+ layoutItems.push({ description: "Add Note ...", subitems: noteItems, icon: "eye" })
ContextMenu.Instance.addItem({ description: "Freeform Options ...", subitems: layoutItems, icon: "eye" });
}
+ createText = (noteStyle: number) => {
+ let pt = this.getTransform().transformPoint(ContextMenu.Instance.pageX, ContextMenu.Instance.pageY);
+ let notes = DocListCast((CurrentUserUtils.UserDocument.noteTypes as Doc).data);
+ let text = Docs.Create.TextDocument({ width: 200, height: 100, x: pt[0], y: pt[1], autoHeight: true, title: StrCast(notes[noteStyle % notes.length].title) });
+ text.layout = notes[noteStyle % notes.length];
+ this.addLiveTextBox(text);
+ }
private childViews = () => [
<CollectionFreeFormBackgroundView key="backgroundView" {...this.props} {...this.getDocumentViewProps(this.props.Document)} />,
@@ -921,6 +998,10 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
}
render() {
+ this.props.Document.fitX = this.actualContentBounds && this.actualContentBounds.x;
+ this.props.Document.fitY = this.actualContentBounds && this.actualContentBounds.y;
+ this.props.Document.fitW = this.actualContentBounds && (this.actualContentBounds.r - this.actualContentBounds.x);
+ this.props.Document.fitH = this.actualContentBounds && (this.actualContentBounds.b - this.actualContentBounds.y);
const easing = () => this.props.Document.panTransformType === "Ease";
Doc.UpdateDocumentExtensionForField(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey);
return (
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 27eafd769..fe48a3485 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -1,11 +1,11 @@
import * as htmlToImage from "html-to-image";
import { action, computed, observable } from "mobx";
import { observer } from "mobx-react";
-import { Doc, FieldResult } from "../../../../new_fields/Doc";
+import { Doc, FieldResult, DocListCast } from "../../../../new_fields/Doc";
import { Id } from "../../../../new_fields/FieldSymbols";
import { InkField, StrokeData } from "../../../../new_fields/InkField";
import { List } from "../../../../new_fields/List";
-import { Cast, NumCast } from "../../../../new_fields/Types";
+import { Cast, NumCast, StrCast } from "../../../../new_fields/Types";
import { Utils } from "../../../../Utils";
import { DocServer } from "../../../DocServer";
import { Docs } from "../../../documents/Documents";
@@ -20,6 +20,9 @@ import { CollectionFreeFormView } from "./CollectionFreeFormView";
import "./MarqueeView.scss";
import React = require("react");
import { SchemaHeaderField, RandomPastel } from "../../../../new_fields/SchemaHeaderField";
+import { string } from "prop-types";
+import { listSpec } from "../../../../new_fields/Schema";
+import { CurrentUserUtils } from "../../../../server/authentication/models/current_user_utils";
interface MarqueeViewProps {
getContainerTransform: () => Transform;
@@ -93,9 +96,13 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
}
});
} else if (!e.ctrlKey) {
- let newBox = Docs.Create.TextDocument({ width: 200, height: 100, x: x, y: y, title: "-typed text-" });
- newBox.proto!.autoHeight = true;
- this.props.addLiveTextDocument(newBox);
+ this.props.addLiveTextDocument(
+ Docs.Create.TextDocument({ width: 200, height: 100, x: x, y: y, autoHeight: true, title: "-typed text-" }));
+ } else if (e.keyCode > 48 && e.keyCode <= 57) {
+ let notes = DocListCast((CurrentUserUtils.UserDocument.noteTypes as Doc).data);
+ let text = Docs.Create.TextDocument({ width: 200, height: 100, x: x, y: y, autoHeight: true, title: "-typed text-" });
+ text.layout = notes[(e.keyCode - 49) % notes.length];
+ this.props.addLiveTextDocument(text);
}
e.stopPropagation();
}
@@ -273,14 +280,33 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
return d;
});
}
+ let defaultPalette = ["rgb(114,229,239)", "rgb(255,246,209)", "rgb(255,188,156)", "rgb(247,220,96)", "rgb(122,176,238)",
+ "rgb(209,150,226)", "rgb(127,235,144)", "rgb(252,188,189)", "rgb(247,175,81)",];
+ let colorPalette = Cast(this.props.container.props.Document.colorPalette, listSpec("string"));
+ if (!colorPalette) this.props.container.props.Document.colorPalette = new List<string>(defaultPalette);
+ let palette = Array.from(Cast(this.props.container.props.Document.colorPalette, listSpec("string")) as string[]);
+ let usedPaletted = new Map<string, number>();
+ [...this.props.activeDocuments(), this.props.container.props.Document].map(child => {
+ let bg = StrCast(child.backgroundColor);
+ if (palette.indexOf(bg) !== -1) {
+ palette.splice(palette.indexOf(bg), 1);
+ if (usedPaletted.get(bg)) usedPaletted.set(bg, usedPaletted.get(bg)! + 1);
+ else usedPaletted.set(bg, 1);
+ }
+ });
+ usedPaletted.delete("#f1efeb");
+ usedPaletted.delete("white");
+ usedPaletted.delete("rgba(255,255,255,1)");
+ let usedSequnce = Array.from(usedPaletted.keys()).sort((a, b) => usedPaletted.get(a)! < usedPaletted.get(b)! ? -1 : usedPaletted.get(a)! > usedPaletted.get(b)! ? 1 : 0);
+ let chosenColor = (usedPaletted.size === 0) ? "white" : palette.length ? palette[0] : usedSequnce[0];
let inkData = this.ink ? this.ink.inkData : undefined;
let newCollection = Docs.Create.FreeformDocument(selected, {
x: bounds.left,
y: bounds.top,
panX: 0,
panY: 0,
- backgroundColor: this.props.container.isAnnotationOverlay ? undefined : "white",
- defaultBackgroundColor: this.props.container.isAnnotationOverlay ? undefined : "white",
+ backgroundColor: this.props.container.isAnnotationOverlay ? undefined : chosenColor,
+ defaultBackgroundColor: this.props.container.isAnnotationOverlay ? undefined : chosenColor,
width: bounds.width,
height: bounds.height,
title: e.key === "s" || e.key === "S" ? "-summary-" : "a nested collection",
@@ -330,6 +356,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
this.props.addLiveTextDocument(summary);
}
else {
+ newCollection.ruleProvider = this.props.container.props.Document;
this.props.addDocument(newCollection, false);
this.props.selectDocuments([newCollection]);
}