diff options
author | Bob Zeleznik <zzzman@gmail.com> | 2020-01-28 22:54:17 -0500 |
---|---|---|
committer | Bob Zeleznik <zzzman@gmail.com> | 2020-01-28 22:54:17 -0500 |
commit | 2ec1a14b2ea19bd66d5f7525619bb9cdd38d39bd (patch) | |
tree | 36cd88311940b018807268fce4c035b73313041a /src | |
parent | a7633a83876404a53d1355b33e4561465bb3a316 (diff) |
fixed clusters -- added shift for joining multiselections to clusters.
Diffstat (limited to 'src')
-rw-r--r-- | src/client/util/DragManager.ts | 4 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 42 | ||||
-rw-r--r-- | src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 39 |
3 files changed, 55 insertions, 30 deletions
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 601a7e856..c05a2de96 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -94,6 +94,7 @@ export namespace DragManager { readonly x: number, readonly y: number, readonly complete: DragCompleteEvent, + readonly shiftKey: boolean, readonly altKey: boolean, readonly metaKey: boolean, readonly ctrlKey: boolean @@ -340,7 +341,7 @@ export namespace DragManager { if (dragData instanceof DocumentDragData) { dragData.userDropAction = e.ctrlKey ? "alias" : undefined; } - if (e.shiftKey && CollectionDockingView.Instance) { + if (e.shiftKey && CollectionDockingView.Instance && dragData.droppedDocuments.length === 1) { AbortDrag(); finishDrag?.(new DragCompleteEvent(true, dragData)); CollectionDockingView.Instance.StartOtherDrag({ @@ -409,6 +410,7 @@ export namespace DragManager { x: e.x, y: e.y, complete: complete, + shiftKey: e.shiftKey, altKey: e.altKey, metaKey: e.metaKey, ctrlKey: e.ctrlKey diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 4ba58ac84..bac968165 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -155,7 +155,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { this.bringToFront(d); })); - de.complete.docDragData.droppedDocuments.length === 1 && this.updateCluster(de.complete.docDragData.droppedDocuments[0]); + (de.complete.docDragData.droppedDocuments.length === 1 || de.shiftKey) && this.updateClusterDocs(de.complete.docDragData.droppedDocuments); } } else if (de.complete.annoDragData) { @@ -213,6 +213,41 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { this.childLayoutPairs.map(pair => pair.layout).map(c => this.updateCluster(c)); } + @action + updateClusterDocs(docs: Doc[]) { + const childLayouts = this.childLayoutPairs.map(pair => pair.layout); + if (this.props.Document.useClusters) { + const docFirst = docs[0]; + docs.map(doc => this._clusterSets.map(set => Doc.IndexOf(doc, set) !== -1 && set.splice(Doc.IndexOf(doc, set), 1))); + const preferredInd = NumCast(docFirst.cluster); + docs.map(doc => doc.cluster = -1); + docs.map(doc => this._clusterSets.map((set, i) => set.map(member => { + if (docFirst.cluster === -1 && Doc.IndexOf(member, childLayouts) !== -1 && Doc.overlapping(doc, member, this._clusterDistance)) { + docFirst.cluster = i; + } + }))); + if (docFirst.cluster === -1 && preferredInd !== -1 && (!this._clusterSets[preferredInd] || !this._clusterSets[preferredInd].filter(member => Doc.IndexOf(member, childLayouts) !== -1).length)) { + docFirst.cluster = preferredInd; + } + this._clusterSets.map((set, i) => { + if (docFirst.cluster === -1 && !set.filter(member => Doc.IndexOf(member, childLayouts) !== -1).length) { + docFirst.cluster = i; + } + }); + if (docFirst.cluster === -1) { + docs.map(doc => { + doc.cluster = this._clusterSets.length; + this._clusterSets.push([doc]); + }); + } else { + for (let i = this._clusterSets.length; i <= NumCast(docFirst.cluster); i++) !this._clusterSets[i] && this._clusterSets.push([]); + docs.map(doc => this._clusterSets[doc.cluster = NumCast(docFirst.cluster)].push(doc)); + } + childLayouts.map(child => !this._clusterSets.some((set, i) => Doc.IndexOf(child, set) !== -1 && child.cluster === i) && this.updateCluster(child)); + childLayouts.map(child => Doc.GetProto(child).clusterStr = child.cluster?.toString()); + } + } + @undoBatch @action updateCluster(doc: Doc) { @@ -270,7 +305,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { return; } this._hitCluster = this.props.Document.useClusters ? this.pickCluster(this.getTransform().transformPoint(e.clientX, e.clientY)) !== -1 : false; - if (e.button === 0 && !e.shiftKey && !e.altKey && !e.ctrlKey && this.props.active(true)) { + if (e.button === 0 && (!e.shiftKey || this._hitCluster) && !e.altKey && !e.ctrlKey && this.props.active(true)) { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); document.addEventListener("pointermove", this.onPointerMove); @@ -397,7 +432,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { let x = this.Document._panX || 0; let y = this.Document._panY || 0; - const docs = this.childLayoutPairs.map(pair => pair.layout); + const docs = this.childLayoutPairs.filter(pair => pair.layout instanceof Doc && !pair.layout.isMinimized).map(pair => pair.layout); const [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY); if (!this.isAnnotationOverlay && docs.length) { PDFMenu.Instance.fadeOut(true); @@ -406,7 +441,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { const maxx = this.childDataProvider(docs[0]).width + minx;//docs.length ? NumCast(docs[0].width) + minx : minx; const maxy = this.childDataProvider(docs[0]).height + miny;//docs.length ? NumCast(docs[0].height) + miny : miny; const ranges = docs.filter(doc => doc).reduce((range, doc) => { - const layoutDoc = Doc.Layout(doc); const x = this.childDataProvider(doc).x;//NumCast(doc.x); const y = this.childDataProvider(doc).y;//NumCast(doc.y); const xe = this.childDataProvider(doc).width + x;//x + NumCast(layoutDoc.width); diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 682e43164..3244b7d3e 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -28,6 +28,8 @@ export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { @observer export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeFormDocumentViewProps, PositionDocument>(PositionDocument) { _disposer: IReactionDisposer | undefined = undefined; + + @observable _animPos: number[] | undefined = undefined; get displayName() { return "CollectionFreeFormDocumentView(" + this.props.Document.title + ")"; } // this makes mobx trace() statements more descriptive get transform() { return `scale(${this.props.ContentScaling()}) translate(${this.X}px, ${this.Y}px) rotate(${anime.random(-1, 1) * this.props.jitterRotation}deg)`; } get X() { return this._animPos !== undefined ? this._animPos[0] : this.renderScriptDim ? this.renderScriptDim.x : this.props.x !== undefined ? this.props.x : this.dataProvider ? this.dataProvider.x : (this.Document.x || 0); } @@ -56,37 +58,25 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF return undefined; } - componentWillUnmount() { - this._disposer && this._disposer(); - } + componentWillUnmount() { this._disposer?.(); } componentDidMount() { - this._disposer = reaction(() => this.props.Document.animateToPos ? Array.from(Cast(this.props.Document.animateToPos, listSpec("number"))!) : undefined, - target => this._animPos = !target ? undefined : target[2] ? [NumCast(this.layoutDoc.x), NumCast(this.layoutDoc.y)] : this.props.ScreenToLocalTransform().transformPoint(target[0], target[1]), + this._disposer = reaction(() => Array.from(Cast(this.props.Document?.animateToPos, listSpec("number"), null)), + target => this._animPos = !target ? undefined : target[2] ? [NumCast(this.layoutDoc.x), NumCast(this.layoutDoc.y)] : + this.props.ScreenToLocalTransform().transformPoint(target[0], target[1]), { fireImmediately: true }); } contentScaling = () => this.nativeWidth > 0 && !this.props.Document.ignoreAspect && !this.props.fitToBox ? this.width / this.nativeWidth : 1; - panelWidth = () => this.props.PanelWidth(); - panelHeight = () => this.props.PanelHeight(); + clusterColorFunc = (doc: Doc) => this.clusterColor; + panelWidth = () => (this.dataProvider?.width || this.props.PanelWidth()); + panelHeight = () => (this.dataProvider?.height || this.props.PanelHeight()); getTransform = (): Transform => this.props.ScreenToLocalTransform() .translate(-this.X, -this.Y) .scale(1 / this.contentScaling()) - borderRounding = () => { - const ld = this.layoutDoc[StrCast(this.layoutDoc.layoutKey, "layout")] instanceof Doc ? this.layoutDoc[StrCast(this.layoutDoc.layoutKey, "layout")] as Doc : undefined; - return StrCast((ld || this.props.Document).borderRounding); - } - @computed get clusterColor() { return this.props.backgroundColor(this.props.Document); } - clusterColorFunc = (doc: Doc) => this.clusterColor; - - @observable _animPos: number[] | undefined = undefined; - - finalPanelWidth = () => (this.dataProvider ? this.dataProvider.width : this.panelWidth()); - finalPanelHeight = () => (this.dataProvider ? this.dataProvider.height : this.panelHeight()); - render() { TraceMobx(); return <div className="collectionFreeFormDocumentView-container" @@ -97,7 +87,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF this.clusterColor ? (`${this.clusterColor} ${StrCast(this.layoutDoc.boxShadow, `0vw 0vw ${(this.layoutDoc.isBackground ? 100 : 50) / this.props.ContentScaling()}px`)}`) : // if it's just in a cluster, make the shadown roughly match the cluster border extent this.layoutDoc.isBackground ? undefined : // if it's a background & has a cluster color, make the shadow spread really big StrCast(this.layoutDoc.boxShadow, ""), - borderRadius: this.borderRounding(), + borderRadius: StrCast(Doc.Layout(this.layoutDoc).borderRounding), transform: this.transform, transition: this.Document.isAnimating ? ".5s ease-in" : this.props.transition ? this.props.transition : this.dataProvider ? this.dataProvider.transition : StrCast(this.layoutDoc.transition), width: this.width, @@ -105,22 +95,21 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF zIndex: this.Document.zIndex || 0, }} > - {!this.props.fitToBox ? <DocumentView {...this.props} dragDivName={"collectionFreeFormDocumentView-container"} ContentScaling={this.contentScaling} ScreenToLocalTransform={this.getTransform} backgroundColor={this.clusterColorFunc} - PanelWidth={this.finalPanelWidth} - PanelHeight={this.finalPanelHeight} + PanelWidth={this.panelWidth} + PanelHeight={this.panelHeight} /> : <ContentFittingDocumentView {...this.props} CollectionDoc={this.props.ContainingCollectionDoc} DataDocument={this.props.DataDoc} getTransform={this.getTransform} active={returnFalse} focus={(doc: Doc) => this.props.focus(doc, false)} - PanelWidth={this.finalPanelWidth} - PanelHeight={this.finalPanelHeight} + PanelWidth={this.panelWidth} + PanelHeight={this.panelHeight} />} </div>; } |