aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2021-02-24 22:04:31 -0500
committerbobzel <zzzman@gmail.com>2021-02-24 22:04:31 -0500
commit3410e107435410a5635a70f12ee05e2d874ff01c (patch)
tree5d9fdfbc66199665a33847f67edae8650f2aae34 /src
parent58adadeaaf97c57a15d42fea86e75180fc3b2c14 (diff)
cleaned up DocumentView's contentView api to be more general. fixed screenToLocal for freeformView's whenb _fitToBox is set. moved webBox menu items out of CollectionMenu and into WebBox using the contentView API.
Diffstat (limited to 'src')
-rw-r--r--src/client/views/collections/CollectionMenu.tsx57
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss2
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx18
-rw-r--r--src/client/views/nodes/DocumentView.tsx17
-rw-r--r--src/client/views/nodes/ImageBox.tsx2
-rw-r--r--src/client/views/nodes/VideoBox.tsx2
-rw-r--r--src/client/views/nodes/WebBox.tsx47
7 files changed, 68 insertions, 77 deletions
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 423c94005..591b4161e 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -560,7 +560,6 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
@computed get isText() {
return this.selectedDoc?.type === DocumentType.RTF || (RichTextMenu.Instance?.view as any) ? true : false;
}
- @computed get webBoxUrl() { return this.selectedDocumentView?.ComponentView?.url?.(); }
@undoBatch
@action
@@ -733,58 +732,6 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
</div>;
}
-
- onWebUrlDrop = (e: React.DragEvent) => {
- const { dataTransfer } = e;
- const html = dataTransfer.getData("text/html");
- const uri = dataTransfer.getData("text/uri-list");
- const url = uri || html || this.webBoxUrl || "";
- const newurl = url.startsWith(window.location.origin) ?
- url.replace(window.location.origin, this.webBoxUrl?.match(/http[s]?:\/\/[^\/]*/)?.[0] || "") : url;
- this.submitWebUrl(newurl);
- e.stopPropagation();
- }
- onWebUrlValueKeyDown = (e: React.KeyboardEvent) => {
- e.key === "Enter" && this.submitWebUrl(this._keyInput.current!.value);
- e.stopPropagation();
- }
- submitWebUrl = (url: string) => this.selectedDocumentView?.ComponentView?.submitURL?.(url);
- webUrlForward = () => this.selectedDocumentView?.ComponentView?.forward?.();
- webUrlBack = () => this.selectedDocumentView?.ComponentView?.back?.();
-
- private _keyInput = React.createRef<HTMLInputElement>();
-
- @computed get urlEditor() {
- return (
- <div className="collectionMenu-webUrlButtons" onDrop={this.onWebUrlDrop} onDragOver={e => e.preventDefault()} >
- <input className="collectionMenu-urlInput" key={this.webBoxUrl}
- placeholder="ENTER URL"
- defaultValue={this.webBoxUrl}
- onDrop={this.onWebUrlDrop}
- onDragOver={e => e.preventDefault()}
- onKeyDown={this.onWebUrlValueKeyDown}
- onClick={(e) => {
- this._keyInput.current!.select();
- e.stopPropagation();
- }}
- ref={this._keyInput}
- />
- <div style={{ display: "flex", flexDirection: "row", justifyContent: "space-between", maxWidth: "250px", }}>
- <button className="submitUrl" onClick={() => this.submitWebUrl(this._keyInput.current!.value)} onDragOver={e => e.stopPropagation()} onDrop={this.onWebUrlDrop}>
- GO
- </button>
- <button className="submitUrl" onClick={this.webUrlBack}>
- <FontAwesomeIcon icon="caret-left" size="lg"></FontAwesomeIcon>
- </button>
- <button className="submitUrl" onClick={this.webUrlForward}>
- <FontAwesomeIcon icon="caret-right" size="lg"></FontAwesomeIcon>
- </button>
- </div>
- </div>
- );
- }
-
-
@observable viewType = this.selectedDoc?._viewType;
render() {
@@ -811,9 +758,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
</>
: null}
- {!this.props.isOverlay || this.document.type !== DocumentType.WEB || this.isText || this.props.isDoc ? (null) :
- this.urlEditor
- }
+ {!this.selectedDocumentView?.ComponentView?.menuControls ? (null) : this.selectedDocumentView?.ComponentView?.menuControls?.()}
{!this.isText ?
<>
{this.drawButtons}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
index a05c25c9b..eb0538c41 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
@@ -191,7 +191,7 @@
.collectionfreeformview-container {
// touch action none means that the browser will handle none of the touch actions. this allows us to implement our own actions.
touch-action: none;
-
+ transform-origin: top left;
.collectionfreeformview-placeholder {
background: gray;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 96ef7af01..92c09ff3f 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -69,7 +69,7 @@ type PanZoomDocument = makeInterface<[typeof panZoomSchema, typeof collectionSch
const PanZoomDocument = makeInterface(panZoomSchema, collectionSchema, documentSchema, pageSchema);
export type collectionFreeformViewProps = {
parentActive: (outsideReaction: boolean) => boolean;
- forceScaling?: boolean; // whether to force scaling of content (needed by ImageBox)
+ annotationLayerHostsContent?: boolean; // whether to force scaling of content (needed by ImageBox)
viewDefDivClick?: ScriptField;
childPointerEvents?: boolean;
scaleField?: string;
@@ -157,10 +157,11 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
freeformData = (force?: boolean) => this.fitToContent || force ? this.fitToContentVals : undefined;
freeformDocFilters = () => this._focusFilters || this.docFilters();
freeformRangeDocFilters = () => this._focusRangeFilters || this.docRangeFilters();
+ reverseNativeScaling = () => this.fitToContent ? true : false;
panX = () => this.freeformData()?.panX ?? NumCast(this.Document._panX);
panY = () => this.freeformData()?.panY ?? NumCast(this.Document._panY);
zoomScaling = () => (this.freeformData()?.scale ?? NumCast(this.Document[this.scaleFieldKey], 1));
- contentTransform = () => `translate(${this.cachedCenteringShiftX}px, ${this.cachedCenteringShiftY}px) scale(${this.zoomScaling()}) translate(${-this.panX()}px, ${-this.panY()}px)`
+ contentTransform = () => `translate(${this.cachedCenteringShiftX}px, ${this.cachedCenteringShiftY}px) scale(${this.zoomScaling()}) translate(${-this.panX()}px, ${-this.panY()}px)`;
getTransform = () => this.cachedGetTransform.copy();
getLocalTransform = () => this.cachedGetLocalTransform.copy();
getContainerTransform = () => this.cachedGetContainerTransform.copy();
@@ -1274,11 +1275,11 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
}
@undoBatch
- toggleNativeDimensions = () => Doc.toggleNativeDimensions(this.layoutDoc, 1, this.nativeWidth, this.nativeHeight);
+ toggleNativeDimensions = () => Doc.toggleNativeDimensions(this.layoutDoc, 1, this.nativeWidth, this.nativeHeight)
@undoBatch
@action
- toggleLockTransform = () => this.layoutDoc._lockedTransform = this.layoutDoc._lockedTransform ? undefined : true;
+ toggleLockTransform = () => this.layoutDoc._lockedTransform = this.layoutDoc._lockedTransform ? undefined : true
onContextMenu = (e: React.MouseEvent) => {
if (this.props.isAnnotationOverlay || this.props.Document.annotationOn || !ContextMenu.Instance) return;
@@ -1462,7 +1463,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
}
@computed get contentScaling() {
- if (this.props.isAnnotationOverlay && !this.props.forceScaling) return 0;
+ if (this.props.isAnnotationOverlay && !this.props.annotationLayerHostsContent) return 0;
const nw = this.nativeWidth;
const nh = this.nativeHeight;
const hscale = nh ? this.props.PanelHeight() / nh : 1;
@@ -1484,10 +1485,9 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
onContextMenu={this.onContextMenu}
style={{
pointerEvents: this.backgroundEvents ? "all" : undefined,
- transform: this.contentScaling ? `scale(${this.contentScaling})` : "",
- transformOrigin: this.contentScaling ? "left top" : "",
- width: this.contentScaling ? `${100 / this.contentScaling}%` : "",
- height: this.contentScaling ? `${100 / this.contentScaling}%` : this.isAnnotationOverlay ? (this.Document.scrollHeight ? this.Document.scrollHeight : "100%") : this.props.PanelHeight()
+ transform: `scale(${this.contentScaling || 1})`,
+ width: `${100 / (this.contentScaling || 1)}%`,
+ height: this.isAnnotationOverlay && this.Document.scrollHeight ? this.Document.scrollHeight : `${100 / (this.contentScaling || 1)}%`// : this.isAnnotationOverlay ? (this.Document.scrollHeight ? this.Document.scrollHeight : "100%") : this.props.PanelHeight()
}}>
{this.Document._freeformLOD && !this.props.active() && !this.props.isAnnotationOverlay && this.props.renderDepth > 0 ?
this.placeholder : this.marqueeView}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 5dfb3e99b..ec2c77a82 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -76,14 +76,13 @@ export type DocAfterFocusFunc = (notFocused: boolean) => Promise<ViewAdjustment>
export type DocFocusFunc = (doc: Doc, options?: DocFocusOptions) => void;
export type StyleProviderFunc = (doc: Opt<Doc>, props: Opt<DocumentViewProps | FieldViewProps>, property: string) => any;
export interface DocComponentView {
- getAnchor?: () => Doc;
+ getAnchor?: () => Doc; // returns an Anchor Doc that represents the current state of the doc's componentview (e.g., the current playhead location of a an audio/video box)
scrollFocus?: (doc: Doc, smooth: boolean) => Opt<number>; // returns the duration of the focus
- setViewSpec?: (anchor: Doc, preview: boolean) => void;
- back?: () => boolean;
- forward?: () => boolean;
- url?: () => string;
- submitURL?: (url: string) => boolean;
- freeformData?: (force?: boolean) => Opt<{ panX: number, panY: number, scale: number, bounds: { x: number, y: number, r: number, b: number } }>;
+ setViewSpec?: (anchor: Doc, preview: boolean) => void; // sets viewing information for a componentview, typically when following a link. 'preview' tells the view to use the values without writing to the document
+ reverseNativeScaling?: () => boolean; // DocumentView's setup screenToLocal based on the doc having a nativeWidth/Height. However, some content views (e.g., FreeFormView w/ fitToBox set) may ignore the native dimensions so this flags the DocumentView to not do Nativre scaling.
+ menuControls?: any; // controls to display in the top menu bar when the document is selected.
+ // this is kind of hacky since it's not really a generic interface. need to think about how to do this better (it's used to fit a tab's contents to view when shown in a lightbox and to setup the minimap)
+ freeformData?: (force?: boolean) => Opt<{ panX: number, panY: number, scale: number, bounds: { x: number, y: number, r: number, b: number } }>; // the content bounds, pan position and zoom scale of a content view (typically for FreeformViews)
}
export interface DocumentViewSharedProps {
renderDepth: number;
@@ -990,8 +989,8 @@ export class DocumentView extends React.Component<DocumentViewProps> {
@computed get docViewPath() { return this.props.docViewPath ? [...this.props.docViewPath(), this] : [this]; }
@computed get layoutDoc() { return Doc.Layout(this.Document, this.props.LayoutTemplate?.()); }
- @computed get nativeWidth() { return returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, this.props.freezeDimensions)); }
- @computed get nativeHeight() { return returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, this.props.freezeDimensions) || 0); }
+ @computed get nativeWidth() { return this.docView?._componentView?.reverseNativeScaling?.() ? 0 : returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, this.props.freezeDimensions)); }
+ @computed get nativeHeight() { return this.docView?._componentView?.reverseNativeScaling?.() ? 0 : returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, this.props.freezeDimensions) || 0); }
@computed get nativeScaling() {
if (this.nativeWidth && (this.layoutDoc?._fitWidth || this.props.PanelHeight() / this.nativeHeight > this.props.PanelWidth() / this.nativeWidth)) {
return this.props.PanelWidth() / this.nativeWidth; // width-limited or fitWidth
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 728e5e02f..4c3031ae2 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -381,7 +381,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps, ImageD
removeDocument={this.removeDocument}
moveDocument={this.moveDocument}
addDocument={this.addDocument}
- forceScaling={true}
+ annotationLayerHostsContent={true}
focus={this.props.focus}
isSelected={this.props.isSelected}
select={emptyFunction}
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 435563255..ac67949f9 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -552,7 +552,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
<CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit}
fieldKey={this.annotationKey}
isAnnotationOverlay={true}
- forceScaling={true}
+ annotationLayerHostsContent={true}
select={emptyFunction}
active={this.annotationsActive}
scaling={returnOne}
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 663a8b8e4..2cd6f5f33 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -46,6 +46,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef();
private _iframeIndicatorRef = React.createRef<HTMLDivElement>();
private _iframeDragRef = React.createRef<HTMLDivElement>();
+ private _keyInput = React.createRef<HTMLInputElement>();
private _ignoreScroll = false;
private _initialScroll: Opt<number>;
@observable private _marqueeing: number[] | undefined;
@@ -262,6 +263,52 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
return true;
}
+ menuControls = () => this.urlEditor;
+ onWebUrlDrop = (e: React.DragEvent) => {
+ const { dataTransfer } = e;
+ const html = dataTransfer.getData("text/html");
+ const uri = dataTransfer.getData("text/uri-list");
+ const url = uri || html || this._url || "";
+ const newurl = url.startsWith(window.location.origin) ?
+ url.replace(window.location.origin, this._url?.match(/http[s]?:\/\/[^\/]*/)?.[0] || "") : url;
+ this.submitURL(newurl);
+ e.stopPropagation();
+ }
+ onWebUrlValueKeyDown = (e: React.KeyboardEvent) => {
+ e.key === "Enter" && this.submitURL(this._keyInput.current!.value);
+ e.stopPropagation();
+ }
+
+ @computed get urlEditor() {
+ return (
+ <div className="collectionMenu-webUrlButtons" onDrop={this.onWebUrlDrop} onDragOver={e => e.preventDefault()} >
+ <input className="collectionMenu-urlInput" key={this._url}
+ placeholder="ENTER URL"
+ defaultValue={this._url}
+ onDrop={this.onWebUrlDrop}
+ onDragOver={e => e.preventDefault()}
+ onKeyDown={this.onWebUrlValueKeyDown}
+ onClick={(e) => {
+ this._keyInput.current!.select();
+ e.stopPropagation();
+ }}
+ ref={this._keyInput}
+ />
+ <div style={{ display: "flex", flexDirection: "row", justifyContent: "space-between", maxWidth: "250px", }}>
+ <button className="submitUrl" onClick={() => this.submitURL(this._keyInput.current!.value)} onDragOver={e => e.stopPropagation()} onDrop={this.onWebUrlDrop}>
+ GO
+ </button>
+ <button className="submitUrl" onClick={this.back}>
+ <FontAwesomeIcon icon="caret-left" size="lg"></FontAwesomeIcon>
+ </button>
+ <button className="submitUrl" onClick={this.forward}>
+ <FontAwesomeIcon icon="caret-right" size="lg"></FontAwesomeIcon>
+ </button>
+ </div>
+ </div>
+ );
+ }
+
editToggleBtn() {
return <Tooltip title={<div className="dash-tooltip" >{`${this.props.Document.isAnnotating ? "Exit" : "Enter"} annotation mode`}</div>}>
<div className="webBox-annotationToggle"