aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/util/SelectionManager.ts45
-rw-r--r--src/client/views/collections/CollectionCarousel3DView.tsx149
-rw-r--r--src/client/views/collections/CollectionView.tsx2
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx7
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx9
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx2
-rw-r--r--src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx3
-rw-r--r--src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx3
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaView.tsx318
-rw-r--r--src/client/views/collections/collectionSchema/SchemaRowBox.tsx31
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.scss4
-rw-r--r--src/client/views/nodes/DocumentView.tsx18
12 files changed, 282 insertions, 309 deletions
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 0f4f77588..313c255a0 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -1,3 +1,4 @@
+import { ModalManager } from '@material-ui/core';
import { action, observable, ObservableMap } from 'mobx';
import { computedFn } from 'mobx-utils';
import { Doc, Opt } from '../../fields/Doc';
@@ -10,7 +11,8 @@ import { ScriptingGlobals } from './ScriptingGlobals';
export namespace SelectionManager {
class Manager {
@observable IsDragging: boolean = false;
- SelectedViews: ObservableMap<DocumentView, Doc> = new ObservableMap();
+ SelectedViewsMap: ObservableMap<DocumentView, Doc> = new ObservableMap();
+ @observable SelectedViews: DocumentView[] = [];
@observable SelectedSchemaDocument: Doc | undefined;
@action
@@ -20,7 +22,7 @@ export namespace SelectionManager {
@action
SelectView(docView: DocumentView, ctrlPressed: boolean): void {
// if doc is not in SelectedDocuments, add it
- if (!manager.SelectedViews.get(docView) && docView.props.Document.type !== DocumentType.MARKER) {
+ if (!manager.SelectedViewsMap.get(docView) && docView.props.Document.type !== DocumentType.MARKER) {
if (!ctrlPressed) {
if (LinkManager.currentLink && !LinkManager.Links(docView.rootDoc).includes(LinkManager.currentLink) && docView.rootDoc !== LinkManager.currentLink) {
LinkManager.currentLink = undefined;
@@ -28,33 +30,38 @@ export namespace SelectionManager {
this.DeselectAll();
}
- manager.SelectedViews.set(docView, docView.rootDoc);
+ manager.SelectedViews.push(docView);
+ manager.SelectedViewsMap.set(docView, docView.rootDoc);
docView.props.whenChildContentsActiveChanged(true);
- } else if (!ctrlPressed && (Array.from(manager.SelectedViews.entries()).length > 1 || manager.SelectedSchemaDocument)) {
- Array.from(manager.SelectedViews.keys()).map(dv => dv !== docView && dv.props.whenChildContentsActiveChanged(false));
+ } else if (!ctrlPressed && (Array.from(manager.SelectedViewsMap.entries()).length > 1 || manager.SelectedSchemaDocument)) {
+ Array.from(manager.SelectedViewsMap.keys()).map(dv => dv !== docView && dv.props.whenChildContentsActiveChanged(false));
manager.SelectedSchemaDocument = undefined;
- manager.SelectedViews.clear();
- manager.SelectedViews.set(docView, docView.rootDoc);
+ manager.SelectedViews.length = 0;
+ manager.SelectedViewsMap.clear();
+ manager.SelectedViews.push(docView);
+ manager.SelectedViewsMap.set(docView, docView.rootDoc);
}
}
@action
- DeselectView(docView: DocumentView): void {
- if (manager.SelectedViews.get(docView)) {
- manager.SelectedViews.delete(docView);
+ DeselectView(docView?: DocumentView): void {
+ if (docView && manager.SelectedViewsMap.get(docView)) {
+ manager.SelectedViewsMap.delete(docView);
+ manager.SelectedViews.splice(manager.SelectedViews.indexOf(docView), 1);
docView.props.whenChildContentsActiveChanged(false);
}
}
@action
DeselectAll(): void {
manager.SelectedSchemaDocument = undefined;
- Array.from(manager.SelectedViews.keys()).forEach(dv => dv.props.whenChildContentsActiveChanged(false));
- manager.SelectedViews.clear();
+ Array.from(manager.SelectedViewsMap.keys()).forEach(dv => dv.props.whenChildContentsActiveChanged(false));
+ manager.SelectedViewsMap.clear();
+ manager.SelectedViews.length = 0;
}
}
const manager = new Manager();
- export function DeselectView(docView: DocumentView): void {
+ export function DeselectView(docView?: DocumentView): void {
manager.DeselectView(docView);
}
export function SelectView(docView: DocumentView, ctrlPressed: boolean): void {
@@ -67,7 +74,7 @@ export namespace SelectionManager {
const IsSelectedCache = computedFn(function isSelected(doc: DocumentView) {
// wrapping get() in a computedFn only generates mobx() invalidations when the return value of the function for the specific get parameters has changed
- return manager.SelectedViews.get(doc) ? true : false;
+ return manager.SelectedViewsMap.get(doc) ? true : false;
});
// computed functions, such as used in IsSelected generate errors if they're called outside of a
// reaction context. Specifying the context with 'outsideReaction' allows an efficiency feature
@@ -76,7 +83,7 @@ export namespace SelectionManager {
return !doc
? false
: outsideReaction
- ? manager.SelectedViews.get(doc)
+ ? manager.SelectedViewsMap.get(doc)
? true
: false // get() accesses a hashtable -- setting anything in the hashtable generates a mobx invalidation for every get()
: IsSelectedCache(doc);
@@ -85,7 +92,7 @@ export namespace SelectionManager {
export function DeselectAll(except?: Doc): void {
let found: DocumentView | undefined = undefined;
if (except) {
- for (const view of Array.from(manager.SelectedViews.keys())) {
+ for (const view of Array.from(manager.SelectedViewsMap.keys())) {
if (view.props.Document === except) found = view;
}
}
@@ -95,13 +102,15 @@ export namespace SelectionManager {
}
export function Views(): Array<DocumentView> {
- return Array.from(manager.SelectedViews.keys()); //.filter(dv => manager.SelectedViews.get(dv)?._viewType !== CollectionViewType.Docking);
+ return manager.SelectedViews;
+ // Array.from(manager.SelectedViewsMap.keys()); //.filter(dv => manager.SelectedViews.get(dv)?._viewType !== CollectionViewType.Docking);
}
export function SelectedSchemaDoc(): Doc | undefined {
return manager.SelectedSchemaDocument;
}
export function Docs(): Doc[] {
- return Array.from(manager.SelectedViews.values()).filter(doc => doc?._viewType !== CollectionViewType.Docking);
+ return manager.SelectedViews.map(dv => dv.rootDoc).filter(doc => doc?._viewType !== CollectionViewType.Docking);
+ // Array.from(manager.SelectedViewsMap.values()).filter(doc => doc?._viewType !== CollectionViewType.Docking);
}
}
ScriptingGlobals.add(function SelectionManager_selectedDocType(type: string, expertMode: boolean, checkContext?: boolean) {
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index 01f41869e..57ff1b292 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -9,7 +9,7 @@ import { OmitKeys, returnFalse, Utils } from '../../../Utils';
import { DragManager } from '../../util/DragManager';
import { DocumentView } from '../nodes/DocumentView';
import { StyleProp } from '../StyleProvider';
-import "./CollectionCarousel3DView.scss";
+import './CollectionCarousel3DView.scss';
import { CollectionSubView } from './CollectionSubView';
@observer
@@ -20,134 +20,143 @@ export class CollectionCarousel3DView extends CollectionSubView() {
private _dropDisposer?: DragManager.DragDropDisposer;
- componentWillUnmount() { this._dropDisposer?.(); }
+ componentWillUnmount() {
+ this._dropDisposer?.();
+ }
- protected createDashEventsTarget = (ele: HTMLDivElement | null) => { //used for stacking and masonry view
+ protected createDashEventsTarget = (ele: HTMLDivElement | null) => {
+ //used for stacking and masonry view
this._dropDisposer?.();
if (ele) {
this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc);
}
- }
+ };
panelWidth = () => this.props.PanelWidth() / 3;
panelHeight = () => this.props.PanelHeight() * 0.6;
onChildDoubleClick = () => ScriptCast(this.layoutDoc.onChildDoubleClick);
+ isContentActive = () => this.props.isSelected() || this.props.isContentActive() || this.props.isAnyChildContentActive();
+ isChildContentActive = () => (this.isContentActive() ? true : false);
+
@computed get content() {
const currentIndex = NumCast(this.layoutDoc._itemIndex);
- const displayDoc = (childPair: { layout: Doc, data: Doc }) => {
- return <DocumentView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "childLayoutTemplate", "childLayoutString"]).omit}
- onDoubleClick={this.onChildDoubleClick}
- renderDepth={this.props.renderDepth + 1}
- LayoutTemplate={this.props.childLayoutTemplate}
- LayoutTemplateString={this.props.childLayoutString}
- Document={childPair.layout}
- DataDoc={childPair.data}
- PanelWidth={this.panelWidth}
- PanelHeight={this.panelHeight}
- bringToFront={returnFalse}
- />;
+ const displayDoc = (childPair: { layout: Doc; data: Doc }) => {
+ return (
+ <DocumentView
+ {...OmitKeys(this.props, ['NativeWidth', 'NativeHeight', 'childLayoutTemplate', 'childLayoutString']).omit}
+ onDoubleClick={this.onChildDoubleClick}
+ renderDepth={this.props.renderDepth + 1}
+ LayoutTemplate={this.props.childLayoutTemplate}
+ LayoutTemplateString={this.props.childLayoutString}
+ Document={childPair.layout}
+ DataDoc={childPair.data}
+ isContentActive={this.isChildContentActive}
+ isDocumentActive={this.props.childDocumentsActive?.() || this.Document._childDocumentsActive ? this.props.isDocumentActive : this.isContentActive}
+ PanelWidth={this.panelWidth}
+ PanelHeight={this.panelHeight}
+ bringToFront={returnFalse}
+ />
+ );
};
- return (this.childLayoutPairs.map((childPair, index) => {
+ return this.childLayoutPairs.map((childPair, index) => {
return (
- <div key={childPair.layout[Id]}
- className={`collectionCarousel3DView-item${index === currentIndex ? "-active" : ""} ${index}`}
- style={index === currentIndex ?
- { opacity: '1', transform: 'scale(1.3)', width: this.panelWidth() } :
- { opacity: '0.5', transform: 'scale(0.6)', userSelect: 'none', width: this.panelWidth() }}>
+ <div
+ key={childPair.layout[Id]}
+ className={`collectionCarousel3DView-item${index === currentIndex ? '-active' : ''} ${index}`}
+ style={index === currentIndex ? { opacity: '1', transform: 'scale(1.3)', width: this.panelWidth() } : { opacity: '0.5', transform: 'scale(0.6)', userSelect: 'none', width: this.panelWidth() }}>
{displayDoc(childPair)}
- </div>);
- }));
+ </div>
+ );
+ });
}
changeSlide = (direction: number) => {
this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + direction + this.childLayoutPairs.length) % this.childLayoutPairs.length;
- }
+ };
onArrowClick = (e: React.MouseEvent, direction: number) => {
e.stopPropagation();
this.changeSlide(direction);
- !this.layoutDoc.autoScrollOn && (this.layoutDoc.showScrollButton = (direction === 1) ? "fwd" : "back"); // while autoscroll is on, keep the other autoscroll button hidden
+ !this.layoutDoc.autoScrollOn && (this.layoutDoc.showScrollButton = direction === 1 ? 'fwd' : 'back'); // while autoscroll is on, keep the other autoscroll button hidden
!this.layoutDoc.autoScrollOn && this.fadeScrollButton(); // keep pause button visible while autoscroll is on
- }
+ };
interval?: number;
startAutoScroll = (direction: number) => {
this.interval = window.setInterval(() => {
this.changeSlide(direction);
}, this.scrollSpeed);
- }
+ };
stopAutoScroll = () => {
window.clearInterval(this.interval);
this.interval = undefined;
this.fadeScrollButton();
- }
+ };
toggleAutoScroll = (direction: number) => {
this.layoutDoc.autoScrollOn = this.layoutDoc.autoScrollOn ? false : true;
this.layoutDoc.autoScrollOn ? this.startAutoScroll(direction) : this.stopAutoScroll();
- }
+ };
fadeScrollButton = () => {
window.setTimeout(() => {
- !this.layoutDoc.autoScrollOn && (this.layoutDoc.showScrollButton = "none"); //fade away after 1.5s if it's not clicked.
+ !this.layoutDoc.autoScrollOn && (this.layoutDoc.showScrollButton = 'none'); //fade away after 1.5s if it's not clicked.
}, 1500);
- }
+ };
@computed get buttons() {
if (!this.props.isContentActive()) return null;
- return <div className="arrow-buttons" >
- <div key="back" className="carousel3DView-back" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }}
- onClick={(e) => this.onArrowClick(e, -1)}
- >
- <FontAwesomeIcon icon={"angle-left"} size={"2x"} />
- </div>
- <div key="fwd" className="carousel3DView-fwd" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }}
- onClick={(e) => this.onArrowClick(e, 1)}
- >
- <FontAwesomeIcon icon={"angle-right"} size={"2x"} />
+ return (
+ <div className="arrow-buttons">
+ <div key="back" className="carousel3DView-back" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }} onClick={e => this.onArrowClick(e, -1)}>
+ <FontAwesomeIcon icon={'angle-left'} size={'2x'} />
+ </div>
+ <div key="fwd" className="carousel3DView-fwd" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }} onClick={e => this.onArrowClick(e, 1)}>
+ <FontAwesomeIcon icon={'angle-right'} size={'2x'} />
+ </div>
+ {this.autoScrollButton}
</div>
- {this.autoScrollButton}
- </div>;
+ );
}
@computed get autoScrollButton() {
const whichButton = this.layoutDoc.showScrollButton;
- return <>
- <div className={`carousel3DView-back-scroll${whichButton === "back" ? "" : "-hidden"}`} style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }}
- onClick={() => this.toggleAutoScroll(-1)}>
- {this.layoutDoc.autoScrollOn ? <FontAwesomeIcon icon={"pause"} size={"1x"} /> : <FontAwesomeIcon icon={"angle-double-left"} size={"1x"} />}
- </div>
- <div className={`carousel3DView-fwd-scroll${whichButton === "fwd" ? "" : "-hidden"}`} style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }}
- onClick={() => this.toggleAutoScroll(1)}>
- {this.layoutDoc.autoScrollOn ? <FontAwesomeIcon icon={"pause"} size={"1x"} /> : <FontAwesomeIcon icon={"angle-double-right"} size={"1x"} />}
- </div>
- </>;
+ return (
+ <>
+ <div className={`carousel3DView-back-scroll${whichButton === 'back' ? '' : '-hidden'}`} style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }} onClick={() => this.toggleAutoScroll(-1)}>
+ {this.layoutDoc.autoScrollOn ? <FontAwesomeIcon icon={'pause'} size={'1x'} /> : <FontAwesomeIcon icon={'angle-double-left'} size={'1x'} />}
+ </div>
+ <div className={`carousel3DView-fwd-scroll${whichButton === 'fwd' ? '' : '-hidden'}`} style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }} onClick={() => this.toggleAutoScroll(1)}>
+ {this.layoutDoc.autoScrollOn ? <FontAwesomeIcon icon={'pause'} size={'1x'} /> : <FontAwesomeIcon icon={'angle-double-right'} size={'1x'} />}
+ </div>
+ </>
+ );
}
@computed get dots() {
- return (this.childLayoutPairs.map((_child, index) =>
- <div key={Utils.GenerateGuid()} className={`dot${index === NumCast(this.layoutDoc._itemIndex) ? "-active" : ""}`}
- onClick={() => this.layoutDoc._itemIndex = index} />));
+ return this.childLayoutPairs.map((_child, index) => <div key={Utils.GenerateGuid()} className={`dot${index === NumCast(this.layoutDoc._itemIndex) ? '-active' : ''}`} onClick={() => (this.layoutDoc._itemIndex = index)} />);
}
render() {
const index = NumCast(this.layoutDoc._itemIndex);
const translateX = this.panelWidth() * (1 - index);
- return <div className="collectionCarousel3DView-outer" ref={this.createDashEventsTarget}
- style={{
- background: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor),
- color: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Color),
- }} >
- <div className="carousel-wrapper" style={{ transform: `translateX(${translateX}px)` }}>
- {this.content}
- </div>
- {this.props.Document._chromeHidden ? (null) : this.buttons}
- <div className="dot-bar">
- {this.dots}
+ return (
+ <div
+ className="collectionCarousel3DView-outer"
+ ref={this.createDashEventsTarget}
+ style={{
+ background: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor),
+ color: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Color),
+ }}>
+ <div className="carousel-wrapper" style={{ transform: `translateX(${translateX}px)` }}>
+ {this.content}
+ </div>
+ {this.props.Document._chromeHidden ? null : this.buttons}
+ <div className="dot-bar">{this.dots}</div>
</div>
- </div>;
+ );
}
-} \ No newline at end of file
+}
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index eafa50d27..51624689e 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -257,7 +257,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatab
return StrCast(this.rootDoc.childLayoutString, this.props.childLayoutString);
}
- isContentActive = (outsideReaction?: boolean) => this.props.isContentActive();
+ isContentActive = (outsideReaction?: boolean) => this.props.isContentActive() || this.isAnyChildContentActive();
render() {
TraceMobx();
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
index fa0695fb2..81b0c4d8a 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
@@ -116,6 +116,8 @@ export function computeStarburstLayout(poolData: Map<string, PoolData>, pivotDoc
zIndex: NumCast(layout.zIndex),
pair: { layout, data },
replica: '',
+ color: 'white',
+ backgroundColor: 'white',
});
});
const divider = { type: 'div', color: 'transparent', x: -burstRadius[0], y: 0, width: 15, height: 15, payload: undefined };
@@ -408,7 +410,7 @@ function normalizeResults(
.map(ele => {
const newPosRaw = ele[1];
if (newPosRaw) {
- const newPos = {
+ const newPos: PoolData = {
x: newPosRaw.x * scale,
y: newPosRaw.y * scale,
z: newPosRaw.z,
@@ -417,6 +419,9 @@ function normalizeResults(
zIndex: newPosRaw.zIndex,
width: (newPosRaw.width || 0) * scale,
height: newPosRaw.height! * scale,
+ backgroundColor: newPosRaw.backgroundColor,
+ opacity: newPosRaw.opacity,
+ color: newPosRaw.color,
pair: ele[1].pair,
};
poolData.set(newPos.pair.layout[Id] + (newPos.replica || ''), { transition: 'all 1s', ...newPos });
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 3a8edb1a5..4f81af95d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1291,10 +1291,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
};
pointerEvents = () => {
const engine = this.props.layoutEngine?.() || StrCast(this.props.Document._layoutEngine);
- const pointerEvents =
- this.props.isContentActive() === false || DocumentDecorations.Instance.Interacting
- ? 'none'
- : this.props.childPointerEvents ?? (this.props.viewDefDivClick || (engine === computePassLayout.name && !this.props.isSelected(true)) ? 'none' : this.props.pointerEvents?.());
+ const pointerEvents = DocumentDecorations.Instance.Interacting
+ ? 'none'
+ : this.props.childPointerEvents ?? (this.props.viewDefDivClick || (engine === computePassLayout.name && !this.props.isSelected(true)) ? 'none' : this.props.pointerEvents?.());
return pointerEvents;
};
getChildDocView(entry: PoolData) {
@@ -1995,7 +1994,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
TraceMobx();
return (
<div
- className={'collectionfreeformview-container'}
+ className="collectionfreeformview-container"
ref={this.createDashEventsTarget}
onWheel={this.onPointerWheel}
onClick={this.onClick}
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx
index 9581563ce..c9168d40a 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx
@@ -3,8 +3,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@material-ui/core';
import { observer } from 'mobx-react';
import { unimplementedFunction } from '../../../../Utils';
-import { DocumentType } from '../../../documents/DocumentTypes';
-import { SelectionManager } from '../../../util/SelectionManager';
import { AntimodeMenu, AntimodeMenuProps } from '../../AntimodeMenu';
@observer
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
index 88d045fa7..b73b1d779 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
@@ -2,14 +2,13 @@ import { action, computed } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { Doc, DocListCast } from '../../../../fields/Doc';
-import { List } from '../../../../fields/List';
import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
import { returnFalse } from '../../../../Utils';
import { DragManager, dropActionType } from '../../../util/DragManager';
import { SnappingManager } from '../../../util/SnappingManager';
import { Transform } from '../../../util/Transform';
import { undoBatch } from '../../../util/UndoManager';
-import { DocFocusOptions, DocumentView } from '../../nodes/DocumentView';
+import { DocumentView } from '../../nodes/DocumentView';
import { CollectionSubView } from '../CollectionSubView';
import './CollectionMulticolumnView.scss';
import ResizeBar from './MulticolumnResizer';
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
index f18917bef..0cca83803 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
@@ -2,14 +2,13 @@ import { action, computed } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { Doc, DocListCast } from '../../../../fields/Doc';
-import { List } from '../../../../fields/List';
import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
import { returnFalse } from '../../../../Utils';
import { DragManager, dropActionType } from '../../../util/DragManager';
import { SnappingManager } from '../../../util/SnappingManager';
import { Transform } from '../../../util/Transform';
import { undoBatch } from '../../../util/UndoManager';
-import { DocFocusOptions, DocumentView } from '../../nodes/DocumentView';
+import { DocumentView } from '../../nodes/DocumentView';
import { CollectionSubView } from '../CollectionSubView';
import './CollectionMultirowView.scss';
import HeightLabel from './MultirowHeightLabel';
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 151e6cbef..ad31113a2 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -1,15 +1,17 @@
import React = require('react');
-import { action, computed, observable, ObservableMap, ObservableSet, untracked } from 'mobx';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { action, computed, observable, ObservableMap, trace, untracked } from 'mobx';
import { observer } from 'mobx-react';
-import { Doc, DocListCast, Field, Opt, StrListCast } from '../../../../fields/Doc';
+import { Doc, DocListCast, Field, StrListCast } from '../../../../fields/Doc';
import { Id } from '../../../../fields/FieldSymbols';
import { List } from '../../../../fields/List';
import { RichTextField } from '../../../../fields/RichTextField';
import { listSpec } from '../../../../fields/Schema';
import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Types';
import { ImageField } from '../../../../fields/URLField';
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTransparent, returnTrue, setupMoveUpEvents, smoothScroll, Utils } from '../../../../Utils';
+import { emptyFunction, returnEmptyDoclist, returnEmptyString, returnFalse, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../Utils';
import { Docs, DocUtils } from '../../../documents/Documents';
+import { DocumentManager } from '../../../util/DocumentManager';
import { DragManager } from '../../../util/DragManager';
import { SelectionManager } from '../../../util/SelectionManager';
import { Transform } from '../../../util/Transform';
@@ -17,18 +19,14 @@ import { undoBatch } from '../../../util/UndoManager';
import { ContextMenu } from '../../ContextMenu';
import { ContextMenuProps } from '../../ContextMenuItem';
import { EditableView } from '../../EditableView';
-import { DocComponentView, DocFocusOptions, DocumentView } from '../../nodes/DocumentView';
+import { DocFocusOptions, DocumentView } from '../../nodes/DocumentView';
import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox';
+import { KeyValueBox } from '../../nodes/KeyValueBox';
+import { DefaultStyleProvider } from '../../StyleProvider';
import { CollectionSubView } from '../CollectionSubView';
import './CollectionSchemaView.scss';
import { SchemaColumnHeader } from './SchemaColumnHeader';
import { SchemaRowBox } from './SchemaRowBox';
-import { DefaultStyleProvider } from '../../StyleProvider';
-import { DocumentManager } from '../../../util/DocumentManager';
-import { ScriptField } from '../../../../fields/ScriptField';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { IconButton } from 'browndash-components';
-import { KeyValueBox } from '../../nodes/KeyValueBox';
export enum ColumnType {
Number,
@@ -43,7 +41,6 @@ const defaultColumnKeys: string[] = ['title', 'type', 'author', 'creationDate',
@observer
export class CollectionSchemaView extends CollectionSubView() {
private _ref: HTMLDivElement | null = null;
- private _selectedDocSortedArray: Doc[] = [];
private _closestDropIndex: number = 0;
private _previewRef: HTMLDivElement | null = null;
private _makeNewColumn: boolean = false;
@@ -53,13 +50,11 @@ export class CollectionSchemaView extends CollectionSubView() {
public static _rowMenuWidth: number = 100;
public static _previewDividerWidth: number = 4;
- @observable _lastSelectedRow: number | undefined;
@computed get _selectedDocs() {
- return new Set(SelectionManager.Docs().filter(doc => Doc.AreProtosEqual(DocCast(doc.context), this.props.Document)));
+ return SelectionManager.Docs().filter(doc => Doc.AreProtosEqual(DocCast(doc.context), this.props.Document));
}
@observable _rowEles: ObservableMap = new ObservableMap<Doc, HTMLDivElement>();
@observable _colEles: HTMLDivElement[] = [];
- @observable _isDragging: boolean = false;
@observable _displayColumnWidths: number[] | undefined;
@observable _columnMenuIndex: number | undefined;
@observable _menuOptions: string[] = [];
@@ -133,7 +128,7 @@ export class CollectionSchemaView extends CollectionSubView() {
}
componentDidMount() {
- this.props.setContentView?.(this as DocComponentView);
+ this.props.setContentView?.(this);
document.addEventListener('keydown', this.onKeyDown);
}
@@ -143,24 +138,36 @@ export class CollectionSchemaView extends CollectionSubView() {
@action
onKeyDown = (e: KeyboardEvent) => {
- if (this._selectedDocs.size > 0) {
- if (e.key == 'ArrowDown') {
- const lastDoc = Array.from(this._selectedDocs.values()).lastElement();
- const lastIndex = this.rowIndex(lastDoc);
- if (lastIndex >= 0 && lastIndex < this.childDocs.length - 1) {
- !e.shiftKey && this.clearSelection();
- const newDoc = this.childDocs[lastIndex + 1];
- this.addDocToSelection(newDoc, e.shiftKey, lastIndex + 1);
- }
- }
- if (e.key == 'ArrowUp') {
- const firstDoc = Array.from(this._selectedDocs.values())[0];
- const firstIndex = this.rowIndex(firstDoc);
- if (firstIndex > 0 && firstIndex < this.childDocs.length) {
- !e.shiftKey && this.clearSelection();
- const newDoc = this.childDocs[firstIndex - 1];
- this.addDocToSelection(newDoc, e.shiftKey, firstIndex - 1);
- }
+ if (this._selectedDocs.length > 0) {
+ switch (e.key) {
+ case 'ArrowDown':
+ {
+ const lastDoc = this._selectedDocs.lastElement();
+ const lastIndex = this.rowIndex(lastDoc);
+ const curDoc = this.childDocs[lastIndex];
+ if (lastIndex >= 0 && lastIndex < this.childDocs.length - 1) {
+ !e.shiftKey && this.clearSelection();
+ const newDoc = this.childDocs[lastIndex + 1];
+ if (this._selectedDocs.includes(newDoc)) SelectionManager.DeselectView(DocumentManager.Instance.getFirstDocumentView(curDoc));
+ else this.addDocToSelection(newDoc, e.shiftKey, lastIndex + 1);
+ }
+ e.stopPropagation();
+ }
+ break;
+ case 'ArrowUp':
+ {
+ const firstDoc = this._selectedDocs.lastElement();
+ const firstIndex = this.rowIndex(firstDoc);
+ const curDoc = this.childDocs[firstIndex];
+ if (firstIndex > 0 && firstIndex < this.childDocs.length) {
+ !e.shiftKey && this.clearSelection();
+ const newDoc = this.childDocs[firstIndex - 1];
+ if (this._selectedDocs.includes(newDoc)) SelectionManager.DeselectView(DocumentManager.Instance.getFirstDocumentView(curDoc));
+ else this.addDocToSelection(newDoc, e.shiftKey, firstIndex - 1);
+ }
+ e.stopPropagation();
+ }
+ break;
}
}
};
@@ -326,60 +333,25 @@ export class CollectionSchemaView extends CollectionSubView() {
addDocToSelection = (doc: Doc, extendSelection: boolean, index: number) => {
const rowDocView = DocumentManager.Instance.getDocumentView(doc);
if (rowDocView) SelectionManager.SelectView(rowDocView, extendSelection);
- this._lastSelectedRow = index;
- };
-
- @action
- removeDocFromSelection = (doc: Doc) => {
- const rowDocView = DocumentManager.Instance.getDocumentView(doc);
- if (rowDocView) SelectionManager.DeselectView(rowDocView);
- if (this._selectedDocs.size === 0) {
- this._lastSelectedRow = undefined;
- }
};
@action
- clearSelection = () => {
- SelectionManager.DeselectAll();
- this._lastSelectedRow = undefined;
- };
-
- rowOnClickScript = ScriptField.MakeFunction('scriptContext.selectRow(self, shiftKey, ctrlKey || metaKey)', { scriptContext: 'any', shiftKey: 'boolean', ctrlKey: 'boolean', metaKey: 'boolean' })!;
-
- @action
- selectRow = (doc: Doc, shift: boolean, ctrl: boolean) => {
- const index = this.childDocs.indexOf(doc);
- if (index < 0) return;
- if (shift && this._lastSelectedRow !== undefined) {
- const startRow = Math.min(this._lastSelectedRow, index);
- const endRow = Math.max(this._lastSelectedRow, index);
- for (let i = startRow; i <= endRow; i++) {
- const currDoc = this.childDocs[i];
- if (!this._selectedDocs.has(currDoc)) this.addDocToSelection(currDoc, true, i);
- }
- this._lastSelectedRow = index;
- } else if (ctrl) {
- if (!this._selectedDocs.has(doc)) {
- this.addDocToSelection(doc, true, index);
- } else {
- this.removeDocFromSelection(doc);
- }
- } else {
- if (!this._selectedDocs.has(doc)) {
- this.clearSelection();
- this.addDocToSelection(doc, false, index);
- }
+ clearSelection = () => SelectionManager.DeselectAll();
+
+ selectRows = (rootDoc: Doc, lastSelected: Doc) => {
+ const index = this.childDocs.indexOf(rootDoc);
+ const lastSelectedRow = this.childDocs.indexOf(lastSelected);
+ const startRow = Math.min(lastSelectedRow, index);
+ const endRow = Math.max(lastSelectedRow, index);
+ for (let i = startRow; i <= endRow; i++) {
+ const currDoc = this.childDocs[i];
+ if (!this._selectedDocs.includes(currDoc)) this.addDocToSelection(currDoc, true, i);
}
};
- @action
- sortedSelectedDocs = (): Doc[] => {
- return this.childDocs.filter(doc => this._selectedDocs.has(doc));
- };
+ sortedSelectedDocs = () => this.childDocs.filter(doc => this._selectedDocs.includes(doc));
- setDropIndex = (index: number) => {
- this._closestDropIndex = index;
- };
+ setDropIndex = (index: number) => (this._closestDropIndex = index);
@action
onInternalDrop = (e: Event, de: DragManager.DropEvent) => {
@@ -394,17 +366,20 @@ export class CollectionSchemaView extends CollectionSubView() {
return total + curr;
}, CollectionSchemaView._rowMenuWidth);
this.swapColumns(de.complete.columnDragData.colIndex, i);
+ e.stopPropagation();
return true;
}
- if (super.onInternalDrop(e, de)) {
- this._isDragging = false;
- const pushedDocs: Doc[] = this.childDocs.filter((doc: Doc, index: number) => index >= this._closestDropIndex && !this._selectedDocs.has(doc));
+ const draggedDocs = de.complete.docDragData?.draggedDocuments;
+ if (draggedDocs && super.onInternalDrop(e, de)) {
+ const pushedDocs = this.childDocs.filter((doc, index) => index >= this._closestDropIndex && !draggedDocs.includes(doc));
this.props.removeDocument?.(pushedDocs);
- this.props.removeDocument?.(this._selectedDocSortedArray);
- this.addDocument(this._selectedDocSortedArray);
+ this.props.removeDocument?.(draggedDocs);
+ this.addDocument(draggedDocs);
this.addDocument(pushedDocs);
this.setSort(undefined);
- this.clearSelection();
+ SelectionManager.DeselectAll();
+ setTimeout(() => draggedDocs.forEach(doc => DocumentManager.Instance.AddViewRenderedCb(doc, dv => dv.select(true))), 100);
+ e.stopPropagation();
return true;
}
return false;
@@ -412,46 +387,11 @@ export class CollectionSchemaView extends CollectionSubView() {
@action
onExternalDrop = async (e: React.DragEvent): Promise<void> => {
- super.onExternalDrop(
- e,
- {},
- undoBatch(
- action(docus => {
- this._isDragging = false;
- docus.map((doc: Doc) => {
- this.addDocument(doc);
- });
- })
- )
- );
+ super.onExternalDrop(e, {}, undoBatch(action(docus => docus.map((doc: Doc) => this.addDocument(doc)))));
this.setSort(undefined);
};
- @action
- startDrag = (e: PointerEvent, doc: Doc, index: number) => {
- if (!this._selectedDocs.has(doc)) {
- this.clearSelection();
- this.addDocToSelection(doc, false, index);
- }
- this._isDragging = true;
- this._selectedDocSortedArray = this.sortedSelectedDocs();
- const dragData = new DragManager.DocumentDragData(this._selectedDocSortedArray, 'move');
- dragData.moveDocument = this.props.moveDocument;
- const dragItem: HTMLElement[] = Array.from(this._selectedDocs.values()).map((doc: Doc) => this._rowEles.get(doc));
-
- DragManager.StartDocumentDrag(
- dragItem.map(ele => ele),
- dragData,
- e.clientX,
- e.clientY,
- undefined
- );
- return true;
- };
-
- onDividerDown = (e: React.PointerEvent) => {
- setupMoveUpEvents(this, e, this.onDividerMove, emptyFunction, emptyFunction);
- };
+ onDividerDown = (e: React.PointerEvent) => setupMoveUpEvents(this, e, this.onDividerMove, emptyFunction, emptyFunction);
@action
onDividerMove = (e: PointerEvent, down: number[], delta: number[]) => {
@@ -557,9 +497,6 @@ export class CollectionSchemaView extends CollectionSubView() {
return undefined;
};
- isChildContentActive = () =>
- this.props.isDocumentActive?.() && (this.props.childDocumentsActive?.() || BoolCast(this.rootDoc.childDocumentsActive)) ? true : this.props.childDocumentsActive?.() === false || this.rootDoc.childDocumentsActive === false ? false : undefined;
-
@computed get fieldDefaultInput() {
switch (this._newFieldType) {
case ColumnType.Number:
@@ -644,23 +581,17 @@ export class CollectionSchemaView extends CollectionSubView() {
ContextMenu.Instance.clearItems();
ContextMenu.Instance.addItem({
description: 'Change field',
- event: () => {
- this.openColumnMenu(index, false);
- },
+ event: () => this.openColumnMenu(index, false),
icon: 'pencil-alt',
});
ContextMenu.Instance.addItem({
description: 'Filter field',
- event: () => {
- this.openFilterMenu(index);
- },
+ event: () => this.openFilterMenu(index),
icon: 'filter',
});
ContextMenu.Instance.addItem({
description: 'Delete column',
- event: () => {
- this.removeColumn(index);
- },
+ event: () => this.removeColumn(index),
icon: 'trash',
});
ContextMenu.Instance.displayMenu(x, y, undefined, false);
@@ -672,9 +603,7 @@ export class CollectionSchemaView extends CollectionSubView() {
this._menuOptions = this.documentKeys.filter(value => value.toLowerCase().includes(this._menuValue.toLowerCase()));
};
- getFieldFilters = (field: string) => {
- return StrListCast(this.Document._docFilters).filter(filter => filter.split(':')[0] == field);
- };
+ getFieldFilters = (field: string) => StrListCast(this.Document._docFilters).filter(filter => filter.split(':')[0] == field);
removeFieldFilters = (field: string) => {
this.getFieldFilters(field).forEach(filter => {
@@ -694,9 +623,7 @@ export class CollectionSchemaView extends CollectionSubView() {
};
@action
- updateFilterSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
- this._filterValue = e.target.value;
- };
+ updateFilterSearch = (e: React.ChangeEvent<HTMLInputElement>) => (this._filterValue = e.target.value);
@computed get newFieldMenu() {
return (
@@ -705,7 +632,6 @@ export class CollectionSchemaView extends CollectionSubView() {
<input
type="radio"
name="newFieldType"
- id=""
checked={this._newFieldType == ColumnType.Number}
onChange={action(() => {
this._newFieldType = ColumnType.Number;
@@ -718,7 +644,6 @@ export class CollectionSchemaView extends CollectionSubView() {
<input
type="radio"
name="newFieldType"
- id=""
checked={this._newFieldType == ColumnType.Boolean}
onChange={action(() => {
this._newFieldType = ColumnType.Boolean;
@@ -731,7 +656,6 @@ export class CollectionSchemaView extends CollectionSubView() {
<input
type="radio"
name="newFieldType"
- id=""
checked={this._newFieldType == ColumnType.String}
onChange={action(() => {
this._newFieldType = ColumnType.String;
@@ -880,13 +804,11 @@ export class CollectionSchemaView extends CollectionSubView() {
);
}
- tableWidthFunc = () => this.tableWidth;
- rowHeightFunc = () => CollectionSchemaView._rowHeight;
- rowClickScriptFunc = () => this.rowOnClickScript;
isContentActive = () => this.props.isSelected() || this.props.isContentActive();
screenToLocal = () => this.props.ScreenToLocalTransform().translate(-this.tableWidth, 0);
previewWidthFunc = () => this.previewWidth;
render() {
+ trace();
return (
<div
className="collectionSchemaView"
@@ -894,6 +816,12 @@ export class CollectionSchemaView extends CollectionSubView() {
this._ref = ele;
this.createDashEventsTarget(ele);
}}
+ onPointerDown={e => {
+ // this is analogous to the panning code for a freeform view.
+ // however, schema views don't pan so it does nothing. but it does eat the pointerDown event
+ // if the content is active to prevent the schema from being dragged
+ this.isContentActive() && setupMoveUpEvents(this, e, returnFalse, emptyFunction, emptyFunction, false);
+ }}
onDrop={this.onExternalDrop.bind(this)}>
<div className="schema-table">
<div className="schema-header-row" style={{ height: CollectionSchemaView._rowHeight }}>
@@ -927,53 +855,16 @@ export class CollectionSchemaView extends CollectionSubView() {
</div>
{this._columnMenuIndex !== undefined && this.renderColumnMenu}
{this._filterColumnIndex !== undefined && this.renderFilterMenu}
- <div className="schema-table-content">
- {this.childDocs.map((doc: Doc, index: number) => {
- const dataDoc = !doc.isTemplateDoc && !doc.isTemplateForField && !doc.PARAMS ? undefined : this.props.DataDoc;
- let dref: Opt<DocumentView>;
- return (
- <div className="schema-row-wrapper" style={{ maxHeight: CollectionSchemaView._rowHeight }}>
- <DocumentView
- {...this.props}
- ref={r => (dref = r || undefined)}
- LayoutTemplate={this.props.childLayoutTemplate}
- LayoutTemplateString={SchemaRowBox.LayoutString(this.props.fieldKey)}
- Document={doc}
- DataDoc={dataDoc}
- ContainingCollectionView={this.props.CollectionView}
- ContainingCollectionDoc={this.Document}
- PanelWidth={this.tableWidthFunc}
- PanelHeight={this.rowHeightFunc}
- styleProvider={DefaultStyleProvider}
- focus={this.focusDocument}
- docFilters={this.childDocFilters}
- docRangeFilters={this.childDocRangeFilters}
- searchFilterDocs={this.searchFilterDocs}
- rootSelected={this.rootSelected}
- ScreenToLocalTransform={Transform.Identity}
- bringToFront={emptyFunction}
- isDocumentActive={this.isContentActive}
- isContentActive={emptyFunction}
- hideDecorations={true}
- hideTitle={true}
- hideDocumentButtonBar={true}
- hideLinkAnchors={true}
- fitWidth={returnTrue}
- onClick={this.rowClickScriptFunc}
- scriptContext={this}
- />
- </div>
- );
- })}
- </div>
+ <CollectionSchemaViewDocs schema={this} />
+
<EditableView GetValue={returnEmptyString} SetValue={this.addNewTextDoc} placeholder={"Type ':' for commands"} contents={'+ New Node'} menuCallback={this.menuCallback} />
</div>
{this.previewWidth > 0 && <div className="schema-preview-divider" style={{ width: CollectionSchemaView._previewDividerWidth }} onPointerDown={this.onDividerDown}></div>}
{this.previewWidth > 0 && (
<div style={{ width: `${this.previewWidth}px` }} ref={ref => (this._previewRef = ref)}>
- {this._lastSelectedRow !== undefined && (
+ {Array.from(this._selectedDocs).lastElement() && (
<DocumentView
- Document={this.childDocs[this._lastSelectedRow]}
+ Document={Array.from(this._selectedDocs).lastElement()}
DataDoc={undefined}
fitContentsToBox={returnTrue}
dontCenter={'y'}
@@ -1007,3 +898,54 @@ export class CollectionSchemaView extends CollectionSubView() {
);
}
}
+
+interface CollectionSchemaViewDocsProps {
+ schema: CollectionSchemaView;
+}
+
+@observer
+class CollectionSchemaViewDocs extends React.Component<CollectionSchemaViewDocsProps> {
+ tableWidthFunc = () => this.props.schema.tableWidth;
+ rowHeightFunc = () => CollectionSchemaView._rowHeight;
+ render() {
+ return (
+ <div className="schema-table-content">
+ {this.props.schema.childDocs.map((doc: Doc, index: number) => {
+ const dataDoc = !doc.isTemplateDoc && !doc.isTemplateForField && !doc.PARAMS ? undefined : this.props.schema.props.DataDoc;
+ return (
+ <div className="schema-row-wrapper" style={{ maxHeight: CollectionSchemaView._rowHeight }}>
+ <DocumentView
+ {...this.props.schema.props}
+ LayoutTemplate={this.props.schema.props.childLayoutTemplate}
+ LayoutTemplateString={SchemaRowBox.LayoutString(this.props.schema.props.fieldKey)}
+ Document={doc}
+ DataDoc={dataDoc}
+ ContainingCollectionView={this.props.schema.props.CollectionView}
+ ContainingCollectionDoc={this.props.schema.Document}
+ PanelWidth={this.tableWidthFunc}
+ PanelHeight={this.rowHeightFunc}
+ styleProvider={DefaultStyleProvider}
+ focus={this.props.schema.focusDocument}
+ docFilters={this.props.schema.childDocFilters}
+ docRangeFilters={this.props.schema.childDocRangeFilters}
+ searchFilterDocs={this.props.schema.searchFilterDocs}
+ rootSelected={this.props.schema.rootSelected}
+ ScreenToLocalTransform={Transform.Identity}
+ bringToFront={emptyFunction}
+ isDocumentActive={this.props.schema.props.childDocumentsActive?.() ? this.props.schema.props.isDocumentActive : this.props.schema.isContentActive}
+ isContentActive={emptyFunction}
+ whenChildContentsActiveChanged={active => this.props.schema.props.whenChildContentsActiveChanged(active)}
+ hideDecorations={true}
+ hideTitle={true}
+ hideDocumentButtonBar={true}
+ hideLinkAnchors={true}
+ fitWidth={returnTrue}
+ scriptContext={this}
+ />
+ </div>
+ );
+ })}
+ </div>
+ );
+ }
+}
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 87284be70..0c8c0ee59 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -1,9 +1,9 @@
import React = require('react');
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed } from 'mobx';
+import { computed } from 'mobx';
import { observer } from 'mobx-react';
-import { emptyFunction, setupMoveUpEvents } from '../../../../Utils';
import { DragManager } from '../../../util/DragManager';
+import { SnappingManager } from '../../../util/SnappingManager';
import { undoBatch } from '../../../util/UndoManager';
import { ViewBoxBaseComponent } from '../../DocComponent';
import { Colors } from '../../global/globalEnums';
@@ -36,24 +36,30 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps>() {
return this.schemaView?.rowIndex(this.rootDoc) ?? -1;
}
- @action
- onRowPointerDown = (e: React.PointerEvent) => {
- if (!this.isContentActive()) return;
- setupMoveUpEvents(this, e, e => this.schemaView?.startDrag(e, this.rootDoc, this.rowIndex) ?? true, emptyFunction, emptyFunction);
+ componentDidMount(): void {
+ this.props.setContentView?.(this);
+ }
+
+ select = (ctrlKey: boolean, shiftKey: boolean) => {
+ if (!this.schemaView) return;
+ const lastSelected = Array.from(this.schemaView._selectedDocs).lastElement();
+ if (shiftKey && lastSelected) this.schemaView.selectRows(this.rootDoc, lastSelected);
+ else {
+ this.props.select?.(ctrlKey);
+ }
};
onPointerEnter = (e: any) => {
- if (!this.schemaView?._isDragging) return;
+ //if (!this.schemaView?._isDragging) return;
+ if (!SnappingManager.GetIsDragging()) return;
document.removeEventListener('pointermove', this.onPointerMove);
document.addEventListener('pointermove', this.onPointerMove);
};
onPointerMove = (e: any) => {
- if (!this.schemaView?._isDragging) return;
- let dragIsRow: boolean = true;
- DragManager.docsBeingDragged.forEach(doc => {
- dragIsRow = this.schemaView?._selectedDocs.has(doc) ?? false;
- });
+ if (!SnappingManager.GetIsDragging()) return;
+ const dragIsRow = DragManager.docsBeingDragged.some(doc => doc.context === this.schemaDoc); // this.schemaView?._selectedDocs.has(doc) ?? false;
+
if (this._ref && dragIsRow) {
const rect = this._ref.getBoundingClientRect();
const y = e.clientY - rect.top; //y position within the element.
@@ -88,7 +94,6 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps>() {
? { height: CollectionSchemaView._rowHeight, backgroundColor: Colors.LIGHT_BLUE, pointerEvents: this.schemaView?.props.isContentActive() ? 'all' : undefined /*, opacity: this.props.dragging ? 0.5 : 1 */ }
: { height: CollectionSchemaView._rowHeight, pointerEvents: this.schemaView?.props.isContentActive() ? 'all' : undefined }
}
- onPointerDown={this.onRowPointerDown}
onPointerEnter={this.onPointerEnter}
onPointerLeave={this.onPointerLeave}
ref={(row: HTMLDivElement | null) => {
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.scss b/src/client/views/nodes/CollectionFreeFormDocumentView.scss
index 724394025..f99011b8f 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.scss
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.scss
@@ -5,5 +5,5 @@
touch-action: manipulation;
top: 0;
left: 0;
- pointer-events: none;
-} \ No newline at end of file
+ //pointer-events: none;
+}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index c13934945..1f717932e 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -121,6 +121,7 @@ export interface DocComponentView {
addDocTab?: (doc: Doc, where: OpenWhere) => boolean; // determines how to add a document - used in following links to open the target ina local lightbox
reverseNativeScaling?: () => boolean; // DocumentView's setup screenToLocal based on the doc having a nativeWidth/Height. However, some content views (e.g., FreeFormView w/ fitContentsToBox set) may ignore the native dimensions so this flags the DocumentView to not do Nativre scaling.
shrinkWrap?: () => void; // requests a document to display all of its contents with no white space. currently only implemented (needed?) for freeform views
+ select?: (ctrlKey: boolean, shiftKey: boolean) => void;
menuControls?: () => JSX.Element; // controls to display in the top menu bar when the document is selected.
isAnyChildContentActive?: () => boolean; // is any child content of the document active
getKeyFrameEditing?: () => boolean; // whether the document is in keyframe editing mode (if it is, then all hidden documents that are not active at the keyframe time will still be shown)
@@ -236,7 +237,7 @@ export interface DocumentViewInternalProps extends DocumentViewProps {
NativeHeight: () => number;
isSelected: (outsideReaction?: boolean) => boolean;
isHovering: () => boolean;
- select: (ctrlPressed: boolean) => void;
+ select: (ctrlPressed: boolean, shiftPress?: boolean) => void;
DocumentView: () => DocumentView;
viewPath: () => DocumentView[];
}
@@ -538,7 +539,9 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
startDragging(x: number, y: number, dropAction: dropActionType, hideSource = false) {
if (this._mainCont.current) {
- const dragData = new DragManager.DocumentDragData([this.props.Document]);
+ const views = SelectionManager.Views().filter(dv => dv.docView?._mainCont.current);
+ const selected = views.some(dv => dv.rootDoc === this.Document) ? views : [this.props.DocumentView()];
+ const dragData = new DragManager.DocumentDragData(selected.map(dv => dv.rootDoc));
const [left, top] = this.props.ScreenToLocalTransform().scale(this.NativeDimScaling).inverse().transformPoint(0, 0);
dragData.offset = this.props
.ScreenToLocalTransform()
@@ -551,8 +554,13 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
dragData.canEmbed = this.props.canEmbedOnDrag;
const ffview = this.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView;
ffview && runInAction(() => (ffview.ChildDrag = this.props.DocumentView()));
- DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { hideSource: hideSource || (!dropAction && !this.layoutDoc.onDragStart && !this.props.dontHideOnDrag) }, () =>
- setTimeout(action(() => ffview && (ffview.ChildDrag = undefined)))
+ DragManager.StartDocumentDrag(
+ selected.map(dv => dv.docView!._mainCont.current!),
+ dragData,
+ x,
+ y,
+ { hideSource: hideSource || (!dropAction && !this.layoutDoc.onDragStart && !this.props.dontHideOnDrag) },
+ () => setTimeout(action(() => ffview && (ffview.ChildDrag = undefined)))
); // this needs to happen after the drop event is processed.
ffview?.setupDragLines(false);
}
@@ -659,7 +667,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
}),
350
);
- this.props.select(e.ctrlKey || e.shiftKey);
+ (this._componentView?.select ?? this.props.select)(e.ctrlKey || e.metaKey, e.shiftKey);
}
preventDefault = false;
}