From 68d18976359434c46cc9bde3df6fbe708021761e Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sun, 5 May 2019 15:10:18 -0400
Subject: fixed problem with annotations being added to view document instead
 of proto.  added keyvalue indication for fields that only exist on prootype

---
 src/client/views/collections/CollectionBaseView.tsx | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

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

diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 76adfcdcd..cbb568c07 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -100,12 +100,12 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
                     value.push(doc);
                 }
             } else {
-                this.props.Document[this.props.fieldKey] = new List([doc]);
+                Doc.SetOnPrototype(this.props.Document, this.props.fieldKey, new List([doc]));
             }
             // set the ZoomBasis only if hasn't already been set -- bcz: maybe set/resetting the ZoomBasis should be a parameter to addDocument?
             if (this.collectionViewType === CollectionViewType.Freeform || this.collectionViewType === CollectionViewType.Invalid) {
                 let zoom = NumCast(this.props.Document.scale, 1);
-                doc.zoomBasis = zoom;
+                Doc.SetOnPrototype(doc, "zoomBasis", zoom);
             }
         }
         return true;
-- 
cgit v1.2.3-70-g09d2


From 26141a697ae52a7edf3cc6845ce2153111f8860e Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 7 May 2019 15:26:29 -0400
Subject: added Bullet template

---
 src/client/views/DocumentDecorations.tsx             | 15 ++++++++++++---
 src/client/views/TemplateMenu.tsx                    | 20 +++++++++++++++-----
 src/client/views/Templates.tsx                       | 18 +++++-------------
 src/client/views/collections/CollectionBaseView.tsx  | 10 +++++++---
 .../views/nodes/CollectionFreeFormDocumentView.tsx   |  9 +++++----
 5 files changed, 44 insertions(+), 28 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index e2f445874..8ae71fdc8 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -507,9 +507,18 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         }
 
         let templates: Map<Template, boolean> = new Map();
-        let doc = SelectionManager.SelectedDocuments()[0];
         Array.from(Object.values(Templates.TemplateList)).map(template => {
-            let docTemps = doc.templates;
+            let docTemps = SelectionManager.SelectedDocuments().reduce((res: string[], doc: DocumentView, i) => {
+                let temps = doc.props.Document.templates;
+                if (temps instanceof List) {
+                    temps.map(temp => {
+                        if (temp !== Templates.Bullet.Layout || i === 0) {
+                            res.push(temp);
+                        }
+                    })
+                }
+                return res
+            }, [] as string[]);
             let checked = false;
             docTemps.forEach(temp => {
                 if (template.Layout === temp) {
@@ -560,7 +569,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                             <FontAwesomeIcon className="fa-icon-link" icon="link" size="sm" />
                         </div>
                     </div>
-                    <TemplateMenu doc={doc} templates={templates} />
+                    <TemplateMenu docs={SelectionManager.SelectedDocuments()} templates={templates} />
                 </div>
             </div >
         </div>
diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index f29d9c8a1..376feb5a5 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -4,6 +4,8 @@ import { observer } from "mobx-react";
 import './DocumentDecorations.scss';
 import { Template } from "./Templates";
 import { DocumentView } from "./nodes/DocumentView";
+import { List } from "../../new_fields/List";
+import { Doc } from "../../new_fields/Doc";
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -25,24 +27,32 @@ class TemplateToggle extends React.Component<{ template: Template, checked: bool
 }
 
 export interface TemplateMenuProps {
-    doc: DocumentView;
+    docs: DocumentView[];
     templates: Map<Template, boolean>;
 }
 
 @observer
 export class TemplateMenu extends React.Component<TemplateMenuProps> {
-
     @observable private _hidden: boolean = true;
 
-
     @action
     toggleTemplate = (event: React.ChangeEvent<HTMLInputElement>, template: Template): void => {
         if (event.target.checked) {
-            this.props.doc.addTemplate(template);
+            if (template.Name == "Bullet") {
+                this.props.docs[0].addTemplate(template);
+                this.props.docs[0].props.Document.maximizedDocs = new List<Doc>(this.props.docs.filter((v, i) => i !== 0).map(v => v.props.Document));
+            } else {
+                this.props.docs.map(d => d.addTemplate(template));
+            }
             this.props.templates.set(template, true);
             this.props.templates.forEach((checked, template) => console.log("Set Checked + " + checked + " " + this.props.templates.get(template)));
         } else {
-            this.props.doc.removeTemplate(template);
+            if (template.Name == "Bullet") {
+                this.props.docs[0].removeTemplate(template);
+                this.props.docs[0].props.Document.maximizedDocs = undefined;
+            } else {
+                this.props.docs.map(d => d.removeTemplate(template));
+            }
             this.props.templates.set(template, false);
             this.props.templates.forEach((checked, template) => console.log("Unset Checked + " + checked + " " + this.props.templates.get(template)));
         }
diff --git a/src/client/views/Templates.tsx b/src/client/views/Templates.tsx
index 738272913..51fca4c41 100644
--- a/src/client/views/Templates.tsx
+++ b/src/client/views/Templates.tsx
@@ -54,21 +54,13 @@ export namespace Templates {
         `<div><div style="height:calc(100% - 25px); margin-top: 25px; width:100%;position:absolute;">{layout}</div>
         <div style="height:25px; width:100%; position:absolute; top: 0; background-color: rgba(0, 0, 0, .4); color: white; padding:2px 10px">{props.Document.title}</div></div>`
     );
-    export const Summary = new Template("Title", TemplatePosition.InnerTop,
-        `<div style="height:100%; width:100%;position:absolute; margin:0; padding: 0">
-            <div style="height:60%; width:100%;position:absolute;background:yellow; padding:0; margin:0">
-                {layout}
-            </div>
-            <div style="bottom:0px; height:40%; width:50%; position:absolute; background-color: rgba(0, 0, 0, .4); color: white;">
-                <FieldView {...props} fieldKey={"doc1"} />
-            </div>
-            <div style="bottom:0; left: 50%; height:40%; width:50%; position:absolute; background-color: rgba(0, 0, 0, .4); color: white;">
-                <FieldView {...props} fieldKey={"doc2"} />
-            </div>
-        </div>`
+
+    export const Bullet = new Template("Bullet", TemplatePosition.InnerTop,
+        `<div><div style="height:100%; width:100%;position:absolute;">{layout}</div>
+        <div className="isBullet" style="height:25px; width:25px; margin-left:-25px; pointer-events:all; position:absolute; top: 0; background-color: rgba(0, 0, 0, .4); color: white; padding:2px 10px"/></div>`
     );
 
-    export const TemplateList: Template[] = [Title, OuterCaption, InnerCaption, SideCaption];
+    export const TemplateList: Template[] = [Title, OuterCaption, InnerCaption, SideCaption, Bullet];
 
     export function sortTemplates(a: Template, b: Template) {
         if (a.Position < b.Position) { return -1; }
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index cbb568c07..14b92af48 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -95,15 +95,18 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         if (!this.createsCycle(doc, props.Document)) {
             //TODO This won't create the field if it doesn't already exist
             const value = Cast(props.Document[props.fieldKey], listSpec(Doc));
+            let alreadyAdded = true;
             if (value !== undefined) {
-                if (allowDuplicates || !value.some(v => v[Id] === doc[Id])) {
+                if (allowDuplicates || !value.some(v => v instanceof Doc && v[Id] === doc[Id])) {
+                    alreadyAdded = false;
                     value.push(doc);
                 }
             } else {
+                alreadyAdded = false;
                 Doc.SetOnPrototype(this.props.Document, this.props.fieldKey, new List([doc]));
             }
             // set the ZoomBasis only if hasn't already been set -- bcz: maybe set/resetting the ZoomBasis should be a parameter to addDocument?
-            if (this.collectionViewType === CollectionViewType.Freeform || this.collectionViewType === CollectionViewType.Invalid) {
+            if (!alreadyAdded && (this.collectionViewType === CollectionViewType.Freeform || this.collectionViewType === CollectionViewType.Invalid)) {
                 let zoom = NumCast(this.props.Document.scale, 1);
                 Doc.SetOnPrototype(doc, "zoomBasis", zoom);
             }
@@ -118,7 +121,8 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         const value = Cast(props.Document[props.fieldKey], listSpec(Doc), []);
         let index = -1;
         for (let i = 0; i < value.length; i++) {
-            if (value[i][Id] === doc[Id]) {
+            let v = value[i];
+            if (v instanceof Doc && v[Id] === doc[Id]) {
                 index = i;
                 break;
             }
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index c4f85847a..df78d92e2 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -127,6 +127,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
     }
     @action
     public toggleIcon = async (): Promise<void> => {
+        UndoManager.GetOpenBatches().forEach(batch => console.log(batch.batchName));
         SelectionManager.DeselectAll();
         let isMinimized: boolean | undefined;
         let maximizedDocs = await DocListCast(this.props.Document.maximizedDocs);
@@ -144,8 +145,8 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
                     if (isMinimized === undefined) {
                         isMinimized = BoolCast(maximizedDoc.isMinimized, false);
                     }
-                    let minx = NumCast(minimizedTarget.x, undefined) + NumCast(minimizedTarget.width, undefined) / 2;
-                    let miny = NumCast(minimizedTarget.y, undefined) + NumCast(minimizedTarget.height, undefined) / 2;
+                    let minx = NumCast(minimizedTarget.x, undefined) + NumCast(minimizedTarget.width, undefined) * this.getTransform().Scale / 2;
+                    let miny = NumCast(minimizedTarget.y, undefined) + NumCast(minimizedTarget.height, undefined) * this.getTransform().Scale / 2;
                     let maxx = NumCast(maximizedDoc.x, undefined);
                     let maxy = NumCast(maximizedDoc.y, undefined);
                     let maxw = NumCast(maximizedDoc.width, undefined);
@@ -153,7 +154,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
                     if (minx !== undefined && miny !== undefined && maxx !== undefined && maxy !== undefined &&
                         maxw !== undefined && maxh !== undefined) {
                         let scrpt = this.props.ScreenToLocalTransform().inverse().transformPoint(minx, miny);
-                        maximizedDoc.isMinimized = false;
+                        if (isMinimized) maximizedDoc.isMinimized = false;
                         maximizedDoc.isIconAnimating = new List<number>([scrpt[0], scrpt[1], maxx, maxy, maxw, maxh, Date.now(), isMinimized ? 1 : 0])
                     }
                 }
@@ -175,7 +176,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
         let altKey = e.altKey;
         if (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD &&
             Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD) {
-            if (BoolCast(this.props.Document.isButton, false)) {
+            if (BoolCast(this.props.Document.isButton, false) || (e.target as any).className === "isBullet") {
                 let maximizedDocs = await DocListCast(this.props.Document.maximizedDocs);
                 if (maximizedDocs) {   // bcz: need a better way to associate behaviors with click events on widget-documents
                     if ((altKey && !this.props.Document.maximizeOnRight) || (!altKey && this.props.Document.maximizeOnRight)) {
-- 
cgit v1.2.3-70-g09d2

