From 4d4bebb5d2e7555fac4224a497b815c40365fe91 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Fri, 6 Sep 2019 21:10:31 -0400
Subject: fixed clustering to be persistent

---
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 41 +++++++++++++++++++---
 1 file changed, 37 insertions(+), 4 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index fac4d4970..4f6055260 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -256,7 +256,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     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[]) => {
@@ -324,7 +324,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) {
@@ -384,6 +384,8 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
         return false;
     }
     @observable sets: (Doc[])[] = [];
+
+    @undoBatch
     @action
     updateClusters() {
         this.sets.length = 0;
@@ -412,12 +414,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"];
@@ -869,6 +901,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"
         });
-- 
cgit v1.2.3-70-g09d2


From 0fea8592b5bd790334d0557c3ef30eb03973c601 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Fri, 6 Sep 2019 23:19:21 -0400
Subject: changed sub-menu pop up location.  added rotation jitter

---
 src/client/views/ContextMenuItem.tsx                       |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx          | 14 ++++++++++----
 src/client/views/nodes/CollectionFreeFormDocumentView.tsx  |  4 +++-
 3 files changed, 14 insertions(+), 6 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx
index 90f7be33f..1a0839060 100644
--- a/src/client/views/ContextMenuItem.tsx
+++ b/src/client/views/ContextMenuItem.tsx
@@ -89,7 +89,7 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select
             );
         } else if ("subitems" in this.props) {
             let submenu = !this.overItem ? (null) :
-                <div className="contextMenu-subMenu-cont" style={{ marginLeft: "100.5%", left: "0px" }}>
+                <div className="contextMenu-subMenu-cont" style={{ marginLeft: "10.5%", left: "0px" }}>
                     {this._items.map(prop => <ContextMenuItem {...prop} key={prop.description} closeMenu={this.props.closeMenu} />)}
                 </div>;
             return (
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 4f6055260..2df2a3464 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -152,6 +152,7 @@ export namespace PivotView {
                         y={pos.y}
                         width={pos.width}
                         height={pos.height}
+                        jitterRotation={NumCast(target.props.Document.jitterRotation)}
                         {...target.getChildDocumentViewProps(doc)}
                     />,
                     bounds: {
@@ -797,6 +798,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) }
@@ -912,10 +914,14 @@ 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: "1: Note", event: () => this.createText("Note", "yellow"), icon: "eye" });
-        layoutItems.push({ description: "2: Idea", event: () => this.createText("Idea", "pink"), icon: "eye" });
-        layoutItems.push({ description: "3: Topic", event: () => this.createText("Topic", "lightBlue"), icon: "eye" });
-        layoutItems.push({ description: "4: Person", event: () => this.createText("Person", "lightGreen"), icon: "eye" });
+        layoutItems.push({ description: "Jitter Rotation", event: action(() => this.props.Document.jitterRotation = 10), icon: "paint-brush" });
+
+        let noteItems: ContextMenuProps[] = [];
+        noteItems.push({ description: "1: Note", event: () => this.createText("Note", "yellow"), icon: "eye" });
+        noteItems.push({ description: "2: Idea", event: () => this.createText("Idea", "pink"), icon: "eye" });
+        noteItems.push({ description: "3: Topic", event: () => this.createText("Topic", "lightBlue"), icon: "eye" });
+        noteItems.push({ description: "4: Person", event: () => this.createText("Person", "lightGreen"), icon: "eye" });
+        layoutItems.push({ description: "Add Note ...", subitems: noteItems, icon: "eye" })
         ContextMenu.Instance.addItem({ description: "Freeform Options ...", subitems: layoutItems, icon: "eye" });
     }
 
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index c9c394960..f07584b4f 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -8,12 +8,14 @@ import { DocumentView, DocumentViewProps, positionSchema } from "./DocumentView"
 import "./DocumentView.scss";
 import React = require("react");
 import { Doc } from "../../../new_fields/Doc";
+import { random } from "animejs";
 
 export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
     x?: number;
     y?: number;
     width?: number;
     height?: number;
+    jitterRotation: number;
 }
 
 const schema = createSchema({
@@ -27,7 +29,7 @@ const FreeformDocument = makeInterface(schema, positionSchema);
 
 @observer
 export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeFormDocumentViewProps, FreeformDocument>(FreeformDocument) {
-    @computed get transform() { return `scale(${this.props.ContentScaling()}) translate(${this.X}px, ${this.Y}px) scale(${this.zoom}) `; }
+    @computed get transform() { return `scale(${this.props.ContentScaling()}) translate(${this.X}px, ${this.Y}px) rotate(${random(-1, 1) * this.props.jitterRotation}deg) scale(${this.zoom}) `; }
     @computed get X() { return this.props.x !== undefined ? this.props.x : this.Document.x || 0; }
     @computed get Y() { return this.props.y !== undefined ? this.props.y : this.Document.y || 0; }
     @computed get width(): number { return BoolCast(this.props.Document.willMaximize) ? 0 : this.props.width !== undefined ? this.props.width : this.Document.width || 0; }
-- 
cgit v1.2.3-70-g09d2

