From 007433dabbd6a8a5f702ac393ecd2b40b1c3a9d8 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 8 May 2019 18:31:14 -0400
Subject: fixes for templates including changing the relative order of
 CollectionOverlayView in the stack

---
 .../collections/collectionFreeForm/CollectionFreeFormLinksView.tsx      | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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

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";
-- 
cgit v1.2.3-70-g09d2


From 39fd912fd4cd33f30a943290295a59992b9868eb Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Thu, 9 May 2019 17:39:44 -0400
Subject: various cleanup to icons, summaries...

---
 src/client/util/DocumentManager.ts                 | 18 ++++++++++++--
 src/client/util/SelectionManager.ts                | 17 +++++++++++++
 src/client/views/DocumentDecorations.tsx           | 28 ++++++++++++++++++----
 src/client/views/TemplateMenu.tsx                  | 16 +++++++++----
 .../CollectionFreeFormLinkView.scss                |  8 +++----
 .../CollectionFreeFormLinkView.tsx                 |  6 ++---
 .../CollectionFreeFormLinksView.tsx                |  2 +-
 .../collections/collectionFreeForm/MarqueeView.tsx | 17 ++++++-------
 .../views/nodes/CollectionFreeFormDocumentView.tsx | 17 ++++++-------
 src/client/views/nodes/DocumentView.tsx            | 14 +++++++----
 10 files changed, 104 insertions(+), 39 deletions(-)

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

diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 4c264c7ec..779b07ce5 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -1,8 +1,9 @@
 import { computed, observable } from 'mobx';
 import { DocumentView } from '../views/nodes/DocumentView';
 import { Doc } from '../../new_fields/Doc';
-import { FieldValue, Cast } from '../../new_fields/Types';
+import { FieldValue, Cast, BoolCast } from '../../new_fields/Types';
 import { listSpec } from '../../new_fields/Schema';
+import { SelectionManager } from './SelectionManager';
 
 
 export class DocumentManager {
@@ -70,7 +71,7 @@ export class DocumentManager {
 
     @computed
     public get LinkedDocumentViews() {
-        return DocumentManager.Instance.DocumentViews.reduce((pairs, dv) => {
+        return DocumentManager.Instance.DocumentViews.filter(dv => dv.isSelected() || BoolCast(dv.props.Document.libraryBrush, false)).reduce((pairs, dv) => {
             let linksList = Cast(dv.props.Document.linkedToDocs, listSpec(Doc), []).filter(d => d).map(d => d as Doc);
             if (linksList && linksList.length) {
                 pairs.push(...linksList.reduce((pairs, link) => {
@@ -84,6 +85,19 @@ export class DocumentManager {
                     return pairs;
                 }, [] as { a: DocumentView, b: DocumentView, l: Doc }[]));
             }
+            linksList = Cast(dv.props.Document.linkedFromDocs, listSpec(Doc), []).filter(d => d).map(d => d as Doc);
+            if (linksList && linksList.length) {
+                pairs.push(...linksList.reduce((pairs, link) => {
+                    if (link) {
+                        let linkFromDoc = FieldValue(Cast(link.linkedFrom, Doc));
+                        if (linkFromDoc) {
+                            DocumentManager.Instance.getDocumentViews(linkFromDoc).map(docView1 =>
+                                pairs.push({ a: dv, b: docView1, l: link }));
+                        }
+                    }
+                    return pairs;
+                }, pairs));
+            }
             return pairs;
         }, [] as { a: DocumentView, b: DocumentView, l: Doc }[]);
     }
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index a3a8172c7..8c92c2023 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -2,6 +2,7 @@ import { observable, action } from "mobx";
 import { Doc } from "../../new_fields/Doc";
 import { DocumentView } from "../views/nodes/DocumentView";
 import { FormattedTextBox } from "../views/nodes/FormattedTextBox";
+import { NumCast } from "../../new_fields/Types";
 
 export namespace SelectionManager {
     class Manager {
@@ -68,4 +69,20 @@ export namespace SelectionManager {
     export function SelectedDocuments(): Array<DocumentView> {
         return manager.SelectedDocuments;
     }
+    export function ViewsSortedVertically(): DocumentView[] {
+        let sorted = SelectionManager.SelectedDocuments().slice().sort((doc1, doc2) => {
+            if (NumCast(doc1.props.Document.x) > NumCast(doc2.props.Document.x)) return 1;
+            if (NumCast(doc1.props.Document.x) < NumCast(doc2.props.Document.x)) return -1;
+            return 0;
+        });
+        return sorted;
+    }
+    export function ViewsSortedHorizontally(): DocumentView[] {
+        let sorted = SelectionManager.SelectedDocuments().slice().sort((doc1, doc2) => {
+            if (NumCast(doc1.props.Document.y) > NumCast(doc2.props.Document.y)) return 1;
+            if (NumCast(doc1.props.Document.y) < NumCast(doc2.props.Document.y)) return -1;
+            return 0;
+        });
+        return sorted;
+    }
 }
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 705e7a6d8..4786b4de6 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -249,7 +249,22 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             if (this._iconDoc && selectedDocs.length === 1 && this._removeIcon) {
                 selectedDocs[0].props.removeDocument && selectedDocs[0].props.removeDocument(this._iconDoc);
             }
-            !this._removeIcon && selectedDocs.length === 1 && this.getIconDoc(selectedDocs[0]).then(icon => selectedDocs[0].props.toggleMinimized());
+            if (!this._removeIcon) {
+                if (selectedDocs.length === 1)
+                    this.getIconDoc(selectedDocs[0]).then(icon => selectedDocs[0].props.toggleMinimized());
+                else {
+                    let docViews = SelectionManager.ViewsSortedVertically();
+                    let topDocView = docViews[0];
+                    let ind = topDocView.templates.indexOf(Templates.Bullet.Layout);
+                    if (ind !== -1) {
+                        topDocView.templates.splice(ind, 1);
+                        topDocView.props.Document.subBulletDocs = undefined;
+                    } else {
+                        topDocView.addTemplate(Templates.Bullet);
+                        topDocView.props.Document.subBulletDocs = new List<Doc>(docViews.filter(v => v !== topDocView).map(v => v.props.Document));
+                    }
+                }
+            }
             this._removeIcon = false;
         }
         runInAction(() => this._minimizedX = this._minimizedY = 0);
@@ -410,7 +425,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 break;
         }
 
-        FormattedTextBox.InputBoxOverlay = undefined;
+        runInAction(() => FormattedTextBox.InputBoxOverlay = undefined);
         SelectionManager.SelectedDocuments().forEach(element => {
             const rect = element.ContentDiv ? element.ContentDiv.getBoundingClientRect() : new DOMRect();
 
@@ -507,7 +522,12 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
 
         let templates: Map<Template, boolean> = new Map();
         Array.from(Object.values(Templates.TemplateList)).map(template => {
-            let docTemps = SelectionManager.SelectedDocuments().reduce((res: string[], doc: DocumentView, i) => {
+            let sorted = SelectionManager.ViewsSortedVertically().slice().sort((doc1, doc2) => {
+                if (NumCast(doc1.props.Document.x) > NumCast(doc2.props.Document.x)) return 1;
+                if (NumCast(doc1.props.Document.x) < NumCast(doc2.props.Document.x)) return -1;
+                return 0;
+            });
+            let docTemps = sorted.reduce((res: string[], doc: DocumentView, i) => {
                 let temps = doc.props.Document.templates;
                 if (temps instanceof List) {
                     temps.map(temp => {
@@ -568,7 +588,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                             <FontAwesomeIcon className="fa-icon-link" icon="link" size="sm" />
                         </div>
                     </div>
-                    <TemplateMenu docs={SelectionManager.SelectedDocuments()} templates={templates} />
+                    <TemplateMenu docs={SelectionManager.ViewsSortedVertically()} templates={templates} />
                 </div>
             </div >
         </div>
diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index d74982ef8..e2b3bd07a 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -6,6 +6,7 @@ import { Template } from "./Templates";
 import { DocumentView } from "./nodes/DocumentView";
 import { List } from "../../new_fields/List";
 import { Doc } from "../../new_fields/Doc";
+import { NumCast } from "../../new_fields/Types";
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -35,20 +36,27 @@ export interface TemplateMenuProps {
 export class TemplateMenu extends React.Component<TemplateMenuProps> {
     @observable private _hidden: boolean = true;
 
+    constructor(props: TemplateMenuProps) {
+        super(props);
+        console.log("");
+    }
+
     @action
     toggleTemplate = (event: React.ChangeEvent<HTMLInputElement>, template: Template): void => {
         if (event.target.checked) {
             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));
+                let topDocView = this.props.docs[0];
+                topDocView.addTemplate(template);
+                topDocView.props.Document.subBulletDocs = new List<Doc>(this.props.docs.filter(v => v !== topDocView).map(v => v.props.Document));
             } else {
                 this.props.docs.map(d => d.addTemplate(template));
             }
             this.props.templates.set(template, true);
         } else {
             if (template.Name == "Bullet") {
-                this.props.docs[0].removeTemplate(template);
-                this.props.docs[0].props.Document.maximizedDocs = undefined;
+                let topDocView = this.props.docs[0];
+                topDocView.removeTemplate(template);
+                topDocView.props.Document.subBulletDocs = undefined;
             } else {
                 this.props.docs.map(d => d.removeTemplate(template));
             }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss
index 3e8a8a442..737ffba7d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss
@@ -1,12 +1,12 @@
 .collectionfreeformlinkview-linkLine {
     stroke: black;
-    stroke-width: 3;
     transform: translate(10000px,10000px);
+    opacity: 0.5;
     pointer-events: all;
 }
 .collectionfreeformlinkview-linkCircle {
-    stroke: black;
-    stroke-width: 3;
+    stroke: rgb(0,0,0);
+    opacity: 0.5;
     transform: translate(10000px,10000px);
     pointer-events: all;
-}
\ No newline at end of file
+}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
index 3b700b053..63d2f7642 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
@@ -47,11 +47,11 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
         return (
             <>
                 <line key={Utils.GenerateGuid()} className="collectionfreeformlinkview-linkLine"
-                    style={{ strokeWidth: `${l.length * 5}` }}
+                    style={{ strokeWidth: `${l.length / 2}` }}
                     x1={`${x1}`} y1={`${y1}`}
                     x2={`${x2}`} y2={`${y2}`} />
-                <circle key={Utils.GenerateGuid()} className="collectionfreeformlinkview-linkLine"
-                    cx={(x1 + x2) / 2} cy={(y1 + y2) / 2} r={10} onPointerDown={this.onPointerDown} />
+                <circle key={Utils.GenerateGuid()} className="collectionfreeformlinkview-linkCircle"
+                    cx={(x1 + x2) / 2} cy={(y1 + y2) / 2} r={5} onPointerDown={this.onPointerDown} />
             </>
         );
     }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index cbfbb1d2c..1d4584cfe 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -84,7 +84,7 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
         }
         if (view.props.ContainingCollectionView) {
             let collid = view.props.ContainingCollectionView.props.Document[Id];
-            Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), []).
+            Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), []).filter(d => d).map(d => d as Doc).
                 filter(child =>
                     child[Id] === collid).map(view =>
                         DocumentManager.Instance.getDocumentViews(view).map(view =>
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 6057aaeba..d8855fe66 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -96,7 +96,8 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             document.addEventListener("pointermove", this.onPointerMove, true);
             document.addEventListener("pointerup", this.onPointerUp, true);
             document.addEventListener("keydown", this.marqueeCommand, true);
-            e.stopPropagation();
+            // bcz: do we need this?   it kills the context menu on the main collection
+            // e.stopPropagation();
         }
         if (e.altKey) {
             e.preventDefault();
@@ -228,14 +229,14 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                     newCollection.proto!.summaryDoc = summary;
                     selected = [newCollection];
                 }
-                summary.proto!.maximizedDocs = new List<Doc>(selected);
+                summary.proto!.summarizedDocs = new List<Doc>(selected);
                 summary.proto!.isButton = true;
-                selected.map(maximizedDoc => {
-                    let maxx = NumCast(maximizedDoc.x, undefined);
-                    let maxy = NumCast(maximizedDoc.y, undefined);
-                    let maxw = NumCast(maximizedDoc.width, undefined);
-                    let maxh = NumCast(maximizedDoc.height, undefined);
-                    maximizedDoc.isIconAnimating = new List<number>([scrpt[0], scrpt[1], maxx, maxy, maxw, maxh, Date.now(), 0])
+                selected.map(summarizedDoc => {
+                    let maxx = NumCast(summarizedDoc.x, undefined);
+                    let maxy = NumCast(summarizedDoc.y, undefined);
+                    let maxw = NumCast(summarizedDoc.width, undefined);
+                    let maxh = NumCast(summarizedDoc.height, undefined);
+                    summarizedDoc.isIconAnimating = new List<number>([scrpt[0], scrpt[1], maxx, maxy, maxw, maxh, Date.now(), 0])
                 });
                 this.props.addLiveTextDocument(summary);
             }
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 470c0c2f8..92033ea44 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -6,7 +6,7 @@ import "./DocumentView.scss";
 import React = require("react");
 import { DocComponent } from "../DocComponent";
 import { createSchema, makeInterface, listSpec } from "../../../new_fields/Schema";
-import { FieldValue, Cast, NumCast, BoolCast } from "../../../new_fields/Types";
+import { FieldValue, Cast, NumCast, BoolCast, StrCast } from "../../../new_fields/Types";
 import { OmitKeys, Utils } from "../../../Utils";
 import { SelectionManager } from "../../util/SelectionManager";
 import { Doc, DocListCast, HeightSym } from "../../../new_fields/Doc";
@@ -65,7 +65,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
     contentScaling = () => this.nativeWidth > 0 ? this.width / this.nativeWidth : 1;
     panelWidth = () => this.props.PanelWidth();
     panelHeight = () => this.props.PanelHeight();
-    toggleMinimized = () => this.toggleIcon();
+    toggleMinimized = async () => this.toggleIcon(await DocListCast(this.props.Document.maximizedDocs));
     getTransform = (): Transform => this.props.ScreenToLocalTransform()
         .translate(-this.X, -this.Y)
         .scale(1 / this.contentScaling()).scale(1 / this.zoom)
@@ -126,10 +126,9 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
             2);
     }
     @action
-    public toggleIcon = async (): Promise<void> => {
+    public toggleIcon = async (maximizedDocs: Doc[] | undefined): Promise<void> => {
         SelectionManager.DeselectAll();
         let isMinimized: boolean | undefined;
-        let maximizedDocs = await DocListCast(this.props.Document.maximizedDocs);
         let minimizedDoc: Doc | undefined = this.props.Document;
         if (!maximizedDocs) {
             minimizedDoc = await Cast(this.props.Document.minimizedDoc, Doc);
@@ -177,8 +176,10 @@ 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) || (e.target as any).id === "isBullet") {
-                let maximizedDocs = await DocListCast(this.props.Document.maximizedDocs);
+            let isBullet = (e.target as any).id === "isBullet";
+            let isIcon = StrCast(this.props.Document.layout).indexOf("IconBox") !== -1;
+            if (BoolCast(this.props.Document.isButton, false) || isBullet) {
+                let maximizedDocs = await DocListCast(isBullet ? this.props.Document.subBulletDocs : isIcon ? this.props.Document.maximizedDocs : this.props.Document.summarizedDocs);
                 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)) {
                         let dataDocs = await DocListCast(CollectionDockingView.Instance.props.Document.data);
@@ -195,7 +196,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
                         }
                     } else {
                         this.props.addDocument && maximizedDocs.forEach(async maxDoc => this.props.addDocument!(await maxDoc, false));
-                        this.toggleIcon();
+                        this.toggleIcon(maximizedDocs);
                     }
                 }
             }
@@ -230,7 +231,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
         return (
             <div className="collectionFreeFormDocumentView-container" ref={this._mainCont}
                 onPointerDown={this.onPointerDown}
-                onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}
+                onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave} onPointerOver={this.onPointerEnter}
                 onClick={this.onClick}
                 style={{
                     outlineColor: "black",
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index c3bf36553..25a75904b 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -18,7 +18,7 @@ import "./DocumentView.scss";
 import React = require("react");
 import { Opt, Doc, WidthSym, HeightSym, DocListCast } from "../../../new_fields/Doc";
 import { DocComponent } from "../DocComponent";
-import { createSchema, makeInterface } from "../../../new_fields/Schema";
+import { createSchema, makeInterface, listSpec } from "../../../new_fields/Schema";
 import { FieldValue, StrCast, BoolCast, Cast } from "../../../new_fields/Types";
 import { List } from "../../../new_fields/List";
 import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView";
@@ -107,6 +107,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 handlers: { drop: this.drop.bind(this) }
             });
         }
+        // bcz: kind of ugly .. setup a reaction to update the title of a summary document's target (maximizedDocs) whenver the summary doc's title changes
         this._reactionDisposer = reaction(() => [this.props.Document.maximizedDocs, this.props.Document.summaryDoc, this.props.Document.summaryDoc instanceof Doc ? this.props.Document.summaryDoc.title : ""],
             async () => {
                 let maxDoc = await DocListCast(this.props.Document.maximizedDocs);
@@ -142,10 +143,11 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         e.stopPropagation();
     }
 
-    startDragging(x: number, y: number, dropAction: dropActionType) {
+    startDragging(x: number, y: number, dropAction: dropActionType, dragSubBullets: boolean) {
         if (this._mainCont.current) {
+            let allConnected = dragSubBullets ? [this.props.Document, ...Cast(this.props.Document.subBulletDocs, listSpec(Doc), []).filter(d => d).map(d => d as Doc)] : [this.props.Document];
             const [left, top] = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(0, 0);
-            let dragData = new DragManager.DocumentDragData([this.props.Document]);
+            let dragData = new DragManager.DocumentDragData(allConnected);
             const [xoff, yoff] = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).transformDirection(x - left, y - top);
             dragData.dropAction = dropAction;
             dragData.xOffset = xoff;
@@ -167,15 +169,17 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             SelectionManager.SelectDoc(this, e.ctrlKey);
         }
     }
+    _hitIsBullet = false;
     onPointerDown = (e: React.PointerEvent): void => {
         this._downX = e.clientX;
         this._downY = e.clientY;
         if (CollectionFreeFormView.RIGHT_BTN_DRAG && (e.button === 2 || (e.button === 0 && e.altKey)) && !this.isSelected()) {
             return;
         }
+        this._hitIsBullet = (e.target && (e.target as any).id === "isBullet");
         if (e.shiftKey && e.buttons === 1) {
             if (this.props.isTopMost) {
-                this.startDragging(e.pageX, e.pageY, e.altKey || e.ctrlKey ? "alias" : undefined);
+                this.startDragging(e.pageX, e.pageY, e.altKey || e.ctrlKey ? "alias" : undefined, this._hitIsBullet);
             } else if (this.props.Document) {
                 CollectionDockingView.Instance.StartOtherDrag([Doc.MakeAlias(this.props.Document)], e);
             }
@@ -193,7 +197,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 document.removeEventListener("pointermove", this.onPointerMove);
                 document.removeEventListener("pointerup", this.onPointerUp);
                 if (!e.altKey && !this.topMost && (!CollectionFreeFormView.RIGHT_BTN_DRAG && e.buttons === 1) || (CollectionFreeFormView.RIGHT_BTN_DRAG && e.buttons === 2)) {
-                    this.startDragging(this._downX, this._downY, e.ctrlKey || e.altKey ? "alias" : undefined);
+                    this.startDragging(this._downX, this._downY, e.ctrlKey || e.altKey ? "alias" : undefined, this._hitIsBullet);
                 }
             }
             e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document'  however it does mark the event as cancelBubble=true which we test for in the move event handlers
-- 
cgit v1.2.3-70-g09d2

