diff options
Diffstat (limited to 'src')
4 files changed, 61 insertions, 91 deletions
diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx index 03afbe7bf..6e8f9a2df 100644 --- a/src/client/views/MarqueeAnnotator.tsx +++ b/src/client/views/MarqueeAnnotator.tsx @@ -58,6 +58,36 @@ export class MarqueeAnnotator extends React.Component<MarqueeAnnotatorProps> { this._height = this._width = 0; document.addEventListener("pointermove", this.onSelectMove); document.addEventListener("pointerup", this.onSelectEnd); + + AnchorMenu.Instance.Highlight = this.highlight; + /** + * This function is used by the AnchorMenu to create an anchor highlight and a new linked text annotation. + * It also initiates a Drag/Drop interaction to place the text annotation. + */ + AnchorMenu.Instance.StartDrag = action(async (e: PointerEvent, ele: HTMLElement) => { + e.preventDefault(); + e.stopPropagation(); + const targetCreator = () => { + const target = CurrentUserUtils.GetNewTextDoc("Note linked to " + this.props.rootDoc.title, 0, 0, 100, 100); + FormattedTextBox.SelectOnLoad = target[Id]; + return target; + }; + const anchorCreator = () => { + const annoDoc = this.highlight("rgba(173, 216, 230, 0.75)"); // hyperlink color + annoDoc.isLinkButton = true; // prevents link button from showing up --- maybe not a good thing? + this.props.addDocument(annoDoc); + return annoDoc; + }; + DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.props.rootDoc, anchorCreator, targetCreator), e.pageX, e.pageY, { + dragComplete: e => { + if (!e.aborted && e.annoDragData && e.annoDragData.annotationDocument && e.annoDragData.dropDocument && !e.linkDocument) { + e.linkDocument = DocUtils.MakeLink({ doc: e.annoDragData.annotationDocument }, { doc: e.annoDragData.dropDocument }, "Annotation"); + e.annoDragData.annotationDocument.isPushpin = e.annoDragData?.dropDocument.annotationOn === this.props.rootDoc; + } + e.linkDocument && e.annoDragData?.linkDropCallback?.(e as { linkDocument: Doc });// bcz: typescript can't figure out that this is valid even though we tested e.linkDocument + } + }); + }); } componentWillUnmount() { document.removeEventListener("pointermove", this.onSelectMove); @@ -154,36 +184,6 @@ export class MarqueeAnnotator extends React.Component<MarqueeAnnotatorProps> { AnchorMenu.Instance.Marquee = { left: this._left, top: this._top, width: this._width, height: this._height }; } - AnchorMenu.Instance.Highlight = this.highlight; - /** - * This function is used by the AnchorMenu to create an anchor highlight and a new linked text annotation. - * It also initiates a Drag/Drop interaction to place the text annotation. - */ - AnchorMenu.Instance.StartDrag = action(async (e: PointerEvent, ele: HTMLElement) => { - e.preventDefault(); - e.stopPropagation(); - const targetCreator = () => { - const target = CurrentUserUtils.GetNewTextDoc("Note linked to " + this.props.rootDoc.title, 0, 0, 100, 100); - FormattedTextBox.SelectOnLoad = target[Id]; - return target; - }; - const anchorCreator = () => { - const annoDoc = this.highlight("rgba(173, 216, 230, 0.75)"); // hyperlink color - annoDoc.isLinkButton = true; // prevents link button from showing up --- maybe not a good thing? - this.props.addDocument(annoDoc); - return annoDoc; - }; - DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.props.rootDoc, anchorCreator, targetCreator), e.pageX, e.pageY, { - dragComplete: e => { - if (!e.aborted && e.annoDragData && e.annoDragData.annotationDocument && e.annoDragData.dropDocument && !e.linkDocument) { - e.linkDocument = DocUtils.MakeLink({ doc: e.annoDragData.annotationDocument }, { doc: e.annoDragData.dropDocument }, "Annotation"); - e.annoDragData.annotationDocument.isPushpin = e.annoDragData?.dropDocument.annotationOn === this.props.rootDoc; - } - e.linkDocument && e.annoDragData?.linkDropCallback?.(e as { linkDocument: Doc });// bcz: typescript can't figure out that this is valid even though we tested e.linkDocument - } - }); - }); - if (this._width > 10 || this._height > 10) { // configure and show the annotation/link menu if a the drag region is big enough const marquees = this.props.mainCont.getElementsByClassName("marqueeAnnotator-dragBox"); if (marquees?.length) { // copy the temporary marquee to allow for multiple selections (not currently available though). diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 9041d9b21..d9cd4fd4e 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -175,9 +175,10 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P addDocument = (newBox: Doc | Doc[]) => { let retVal = false; if (newBox instanceof Doc) { - retVal = this.props.addDocument?.(newBox) || false; - retVal && this.bringToFront(newBox); - retVal && this.updateCluster(newBox); + if (retVal = this.props.addDocument?.(newBox) || false) { + this.bringToFront(newBox); + this.updateCluster(newBox); + } } else { retVal = this.props.addDocument?.(newBox) || false; // bcz: deal with clusters @@ -267,11 +268,9 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P @undoBatch internalAnchorAnnoDrop(e: Event, annoDragData: DragManager.AnchorAnnoDragData, xp: number, yp: number) { - const dragDoc = annoDragData.dropDocument!; - const dropPos = [NumCast(dragDoc.x), NumCast(dragDoc.y)]; - dragDoc.x = xp - annoDragData.offset[0] + (NumCast(dragDoc.x) - dropPos[0]); - dragDoc.y = yp - annoDragData.offset[1] + (NumCast(dragDoc.y) - dropPos[1]); - this.bringToFront(dragDoc); + annoDragData.dropDocument!.x = xp - annoDragData.offset[0]; + annoDragData.dropDocument!.y = yp - annoDragData.offset[1]; + this.bringToFront(annoDragData.dropDocument!); return true; } @@ -636,26 +635,17 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P @action onPointerMove = (e: PointerEvent): void => { + if (this.props.Document._isGroup) return; // groups don't pan when dragged -- instead let the event go through to allow the group itself to drag + if (InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) return; if (InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE)) { - if (this.props.active(true)) { - e.stopPropagation(); - } - return; - } - if (InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) { - return; - } - if (!e.cancelBubble) { - if (this.props.Document._isGroup) return; // groups don't pan when dragged -- instead let the event go through to allow the group itself to drag + if (this.props.active(true)) e.stopPropagation(); + } else if (!e.cancelBubble) { if (Doc.GetSelectedTool() === InkTool.None) { if (this.tryDragCluster(e, this._hitCluster)) { - 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 - e.preventDefault(); document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); - return; } - (!MarqueeView.DragMarquee || e.altKey) && this.pan(e); + else this.pan(e); } 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 e.preventDefault(); @@ -821,18 +811,10 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P if (!e.ctrlKey && this.props.Document.scrollHeight !== undefined) { // things that can scroll vertically should do that instead of zooming e.stopPropagation(); } - else if (this.props.active(true)) { - if (!e.ctrlKey && MarqueeView.DragMarquee) { - this.setPan(this.panX() + e.deltaX, this.panY() + e.deltaY, "None", true); - e.stopPropagation(); - e.preventDefault(); - } - else if (!this.Document._isGroup) { - e.stopPropagation(); - e.preventDefault(); - this.zoom(e.clientX, e.clientY, e.deltaY); // if (!this.props.isAnnotationOverlay) // bcz: do we want to zoom in on images/videos/etc? - } - + else if (this.props.active(true) && !this.Document._isGroup) { + e.stopPropagation(); + e.preventDefault(); + this.zoom(e.clientX, e.clientY, e.deltaY); // if (!this.props.isAnnotationOverlay) // bcz: do we want to zoom in on images/videos/etc? } this.props.Document.targetScale = NumCast(this.props.Document[this.scaleFieldKey]); } @@ -1301,22 +1283,13 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P @undoBatch layoutDocsInGrid = () => { - const docs = this.childLayoutPairs; - const startX = this.Document._panX || 0; - let x = startX; - let y = this.Document._panY || 0; - let i = 0; - const width = Math.max(...docs.map(doc => NumCast(doc.layout._width))); - const height = Math.max(...docs.map(doc => NumCast(doc.layout._height))); - docs.forEach(pair => { - pair.layout.x = x; - pair.layout.y = y; - x += width + 20; - if (++i === 6) { - i = 0; - x = startX; - y += height + 20; - } + const docs = this.childLayoutPairs.map(pair => pair.layout); + const width = Math.max(...docs.map(doc => NumCast(doc._width))) + 20; + const height = Math.max(...docs.map(doc => NumCast(doc._height))) + 20; + const dim = Math.ceil(Math.sqrt(docs.length)); + docs.forEach((doc, i) => { + doc.x = (this.Document._panX || 0) + (i % dim) * width - width * dim / 2; + doc.y = (this.Document._panY || 0) + Math.floor(i / dim) * height - height * dim / 2; }); } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 4008a20b3..e61cf83bb 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -46,7 +46,6 @@ interface MarqueeViewProps { export class MarqueeView extends React.Component<SubCollectionViewProps & MarqueeViewProps> { private _commandExecuted = false; - @observable public static DragMarquee = false; @observable _lastX: number = 0; @observable _lastY: number = 0; @observable _downX: number = 0; @@ -220,8 +219,8 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque this._downY = this._lastY = e.clientY; if (!(e.nativeEvent as any).marqueeHit) { (e.nativeEvent as any).marqueeHit = true; - // allow marquee if right click OR alt+left click OR space bar + left click - if (e.button === 2 || (e.button === 0 && (e.altKey || (MarqueeView.DragMarquee && this.props.active(true))))) { + // allow marquee if right click OR alt+left click + if (e.button === 2 || (e.button === 0 && e.altKey)) { // if (e.altKey || (MarqueeView.DragMarquee && this.props.active(true))) { this.setPreviewCursor(e.clientX, e.clientY, true); // (!e.altKey) && e.stopPropagation(); // bcz: removed so that you can alt-click on button in a collection to switch link following behaviors. @@ -251,9 +250,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque } else { this.cleanupInteractions(true); // stop listening for events if another lower-level handle (e.g. another Marquee) has stopPropagated this } - if (e.altKey || MarqueeView.DragMarquee) { - e.preventDefault(); - } + e.altKey && e.preventDefault(); } @action @@ -290,9 +287,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque } this.cleanupInteractions(true, this._commandExecuted); - if (e.altKey || MarqueeView.DragMarquee) { - e.preventDefault(); - } + e.altKey && e.preventDefault(); } clearSelection() { @@ -659,7 +654,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque style={{ overflow: (!this.props.ContainingCollectionView && this.props.isAnnotationOverlay) ? "visible" : StrCast(this.props.Document._overflow), - cursor: MarqueeView.DragMarquee && this ? "crosshair" : "hand" + cursor: "hand" }} onDragOver={e => e.preventDefault()} onScroll={(e) => e.currentTarget.scrollTop = e.currentTarget.scrollLeft = 0} onClick={this.onClick} onPointerDown={this.onPointerDown}> diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 7687690b2..ca6dc87ae 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -385,10 +385,12 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu this._setPreviewCursor?.(e.clientX, e.clientY, true); } if (!e.altKey && e.button === 0 && this.active(true)) { + this._marqueeing = [e.clientX, e.clientY]; if (e.target && ((e.target as any).className.includes("endOfContent") || ((e.target as any).parentElement.className !== "textLayer"))) { - this._marqueeing = [e.clientX, e.clientY]; // if texLayer is hit, then we select text instead of using a marquee document.addEventListener("pointermove", this.onSelectMove); // need this to prevent document from being dragged if stopPropagation doesn't get called } else { + // if textLayer is hit, then we select text instead of using a marquee so clear out the marquee. + setTimeout(action(() => this._marqueeing = undefined), 100); // bcz: hack .. anchor menu is setup within MarqueeAnnotator so we need to at least create the marqueeAnnotator even though we aren't using it. // clear out old marquees and initialize menu for new selection AnchorMenu.Instance.Status = "marquee"; this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove())); |