aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes')
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx25
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx2
-rw-r--r--src/client/views/nodes/DocumentView.scss13
-rw-r--r--src/client/views/nodes/DocumentView.tsx21
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx25
-rw-r--r--src/client/views/nodes/ImageBox.tsx69
6 files changed, 81 insertions, 74 deletions
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 2e598a14d..614a68e7a 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -1,4 +1,4 @@
-import { random } from "animejs";
+import anime from "animejs";
import { computed, IReactionDisposer, observable, reaction, trace } from "mobx";
import { observer } from "mobx-react";
import { Doc, HeightSym, WidthSym } from "../../../new_fields/Doc";
@@ -11,6 +11,8 @@ import { DocumentView, DocumentViewProps } from "./DocumentView";
import React = require("react");
import { PositionDocument } from "../../../new_fields/documentSchemas";
import { TraceMobx } from "../../../new_fields/util";
+import { returnFalse } from "../../../Utils";
+import { ContentFittingDocumentView } from "./ContentFittingDocumentView";
export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
dataProvider?: (doc: Doc) => { x: number, y: number, width: number, height: number, z: number, transition?: string } | undefined;
@@ -20,13 +22,14 @@ export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
height?: number;
jitterRotation: number;
transition?: string;
+ fitToBox?: boolean;
}
@observer
export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeFormDocumentViewProps, PositionDocument>(PositionDocument) {
_disposer: IReactionDisposer | 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(${random(-1, 1) * this.props.jitterRotation}deg)`; }
+ 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); }
get Y() { return this._animPos !== undefined ? this._animPos[1] : this.renderScriptDim ? this.renderScriptDim.y : this.props.y !== undefined ? this.props.y : this.dataProvider ? this.dataProvider.y : (this.Document.y || 0); }
get width() { return this.renderScriptDim ? this.renderScriptDim.width : this.props.width !== undefined ? this.props.width : this.props.dataProvider && this.dataProvider ? this.dataProvider.width : this.layoutDoc[WidthSym](); }
@@ -83,8 +86,8 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
@observable _animPos: number[] | undefined = undefined;
- finalPanelWidth = () => this.dataProvider ? this.dataProvider.width : this.panelWidth();
- finalPanelHeight = () => this.dataProvider ? this.dataProvider.height : this.panelHeight();
+ finalPanelWidth = () => (this.dataProvider ? this.dataProvider.width : this.panelWidth());
+ finalPanelHeight = () => (this.dataProvider ? this.dataProvider.height : this.panelHeight());
render() {
TraceMobx();
@@ -104,24 +107,22 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
zIndex: this.Document.zIndex || 0,
}} >
- <DocumentView {...this.props}
+
+ {!this.props.fitToBox ? <DocumentView {...this.props}
dragDivName={"collectionFreeFormDocumentView-container"}
ContentScaling={this.contentScaling}
ScreenToLocalTransform={this.getTransform}
backgroundColor={this.clusterColorFunc}
PanelWidth={this.finalPanelWidth}
PanelHeight={this.finalPanelHeight}
- />
- {/* <ContentFittingDocumentView {...this.props}
- //dragDivName={"collectionFreeFormDocumentView-container"}
- //ContentScaling={this.contentScaling}
+ /> : <ContentFittingDocumentView {...this.props}
+ DataDocument={this.props.DataDoc}
getTransform={this.getTransform}
active={returnFalse}
focus={(doc: Doc) => this.props.focus(doc, false)}
- // backgroundColor={this.clusterColorFunc}
PanelWidth={this.finalPanelWidth}
PanelHeight={this.finalPanelHeight}
- /> */}
+ />}
</div>;
}
-} \ No newline at end of file
+}
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 8f6bfc8e1..66886165e 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -82,7 +82,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
return this.props.DataDoc;
}
get layoutDoc() {
- return this.props.DataDoc === undefined ? Doc.expandTemplateLayout(Doc.Layout(this.props.Document), this.props.Document) : Doc.Layout(this.props.Document);
+ return Doc.expandTemplateLayout(Doc.Layout(this.props.Document), this.props.Document);
}
CreateBindings(): JsxBindings {
diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss
index f44c6dd3b..2ce56c73d 100644
--- a/src/client/views/nodes/DocumentView.scss
+++ b/src/client/views/nodes/DocumentView.scss
@@ -55,7 +55,7 @@
position: absolute;
}
- .documentView-titleWrapper {
+ .documentView-titleWrapper, .documentView-titleWrapper-hover {
overflow: hidden;
color: white;
transform-origin: top left;
@@ -68,6 +68,9 @@
text-overflow: ellipsis;
white-space: pre;
}
+ .documentView-titleWrapper-hover {
+ display:none;
+ }
.documentView-searchHighlight {
position: absolute;
@@ -85,4 +88,12 @@
}
}
+}
+
+.documentView-node:hover, .documentView-node-topmost:hover {
+ > .documentView-styleWrapper {
+ > .documentView-titleWrapper-hover {
+ display:inline-block;
+ }
+ }
} \ No newline at end of file
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 10d2e2b3e..b2c2ccff5 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -29,7 +29,6 @@ import { CollectionDockingView } from "../collections/CollectionDockingView";
import { CollectionView } from "../collections/CollectionView";
import { ContextMenu } from "../ContextMenu";
import { ContextMenuProps } from '../ContextMenuItem';
-import { DictationOverlay } from '../DictationOverlay';
import { DocComponent } from "../DocComponent";
import { EditableView } from '../EditableView';
import { OverlayView } from '../OverlayView';
@@ -64,7 +63,7 @@ export interface DocumentViewProps {
moveDocument?: (doc: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => boolean;
ScreenToLocalTransform: () => Transform;
renderDepth: number;
- showOverlays?: (doc: Doc) => { title?: string, caption?: string };
+ showOverlays?: (doc: Doc) => { title?: string, titleHover?: string, caption?: string };
ContentScaling: () => number;
ruleProvider: Doc | undefined;
PanelWidth: () => number;
@@ -196,7 +195,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
ScriptBox.EditButtonScript("On Button Clicked ...", this.props.Document, "onClick", e.clientX, e.clientY);
} else if (this.props.Document.isButton === "Selector") { // this should be moved to an OnClick script
FormattedTextBoxComment.Hide();
- this.Document.links?.[0] instanceof Doc && (Doc.UserDoc().SelectedDocs = new List([Doc.LinkOtherAnchor(this.Document.links[0]!, this.props.Document)]));
+ this.Document.links?.[0] instanceof Doc && (Doc.UserDoc().SelectedDocs = new List([Doc.LinkOtherAnchor(this.Document.links[0], this.props.Document)]));
} else if (this.Document.isButton) {
SelectionManager.SelectDoc(this, e.ctrlKey); // don't think this should happen if a button action is actually triggered.
this.buttonClick(e.altKey, e.ctrlKey);
@@ -741,7 +740,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
chromeHeight = () => {
const showOverlays = this.props.showOverlays ? this.props.showOverlays(this.Document) : undefined;
const showTitle = showOverlays && "title" in showOverlays ? showOverlays.title : StrCast(this.layoutDoc.showTitle);
- return (showTitle ? 25 : 0) + 1;
+ const showTitleHover = showOverlays && "titleHover" in showOverlays ? showOverlays.titleHover : StrCast(this.layoutDoc.showTitleHover);
+ return (showTitle && !showTitleHover ? 0 : 0) + 1;
}
@computed get finalLayoutKey() { return this.props.layoutKey || "layout"; }
@@ -751,6 +751,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
return (<DocumentContentsView ContainingCollectionView={this.props.ContainingCollectionView}
ContainingCollectionDoc={this.props.ContainingCollectionDoc}
Document={this.props.Document}
+ DataDoc={this.props.DataDoc}
fitToBox={this.props.fitToBox}
LibraryPath={this.props.LibraryPath}
addDocument={this.props.addDocument}
@@ -777,8 +778,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
isSelected={this.isSelected}
select={this.select}
onClick={this.onClickHandler}
- layoutKey={this.finalLayoutKey}
- DataDoc={this.props.DataDoc} />);
+ layoutKey={this.finalLayoutKey} />);
}
linkEndpoint = (linkDoc: Doc) => Doc.LinkEndpoint(linkDoc, this.props.Document);
@@ -795,6 +795,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
TraceMobx();
const showOverlays = this.props.showOverlays ? this.props.showOverlays(this.Document) : undefined;
const showTitle = showOverlays && "title" in showOverlays ? showOverlays.title : StrCast(this.getLayoutPropStr("showTitle"));
+ const showTitleHover = showOverlays && "titleHover" in showOverlays ? showOverlays.titleHover : StrCast(this.getLayoutPropStr("showTitleHover"));
const showCaption = showOverlays && "caption" in showOverlays ? showOverlays.caption : this.getLayoutPropStr("showCaption");
const showTextTitle = showTitle && StrCast(this.layoutDoc.layout).indexOf("FormattedTextBox") !== -1 ? showTitle : undefined;
const searchHighlight = (!this.Document.searchFields ? (null) :
@@ -810,15 +811,15 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
/>
</div>);
const titleView = (!showTitle ? (null) :
- <div className="documentView-titleWrapper" style={{
+ <div className={`documentView-titleWrapper${showTitleHover ? "-hover" : ""}`} style={{
position: showTextTitle ? "relative" : "absolute",
pointerEvents: SelectionManager.GetIsDragging() ? "none" : "all",
}}>
<EditableView ref={this._titleRef}
- contents={this.Document[showTitle]}
+ contents={(this.props.DataDoc || this.props.Document)[showTitle]}
display={"block"} height={72} fontSize={12}
- GetValue={() => StrCast(this.Document[showTitle])}
- SetValue={undoBatch((value: string) => (Doc.GetProto(this.Document)[showTitle] = value) ? true : true)}
+ GetValue={() => StrCast((this.props.DataDoc || this.props.Document)[showTitle])}
+ SetValue={undoBatch((value: string) => (Doc.GetProto(this.props.DataDoc || this.props.Document)[showTitle] = value) ? true : true)}
/>
</div>);
return <>
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 8e28cf928..60842bcb0 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -906,15 +906,16 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
this.tryUpdateHeight();
// see if we need to preserve the insertion point
- const prosediv = this.ProseRef ?.children ?.[0] as any;
- const keeplocation = prosediv ?.keeplocation;
+ const prosediv = this.ProseRef?.children?.[0] as any;
+ const keeplocation = prosediv?.keeplocation;
prosediv && (prosediv.keeplocation = undefined);
- const pos = this._editorView ?.state.selection.$from.pos || 1;
- keeplocation && setTimeout(() => this._editorView ?.dispatch(this._editorView ?.state.tr.setSelection(TextSelection.create(this._editorView.state.doc, pos))));
+ const pos = this._editorView?.state.selection.$from.pos || 1;
+ keeplocation && setTimeout(() => this._editorView?.dispatch(this._editorView?.state.tr.setSelection(TextSelection.create(this._editorView.state.doc, pos))));
// jump rich text menu to this textbox
- if (this._ref.current) {
- const x = Math.min(Math.max(this._ref.current!.getBoundingClientRect().left, 0), window.innerWidth - RichTextMenu.Instance.width);
+ const { current } = this._ref;
+ if (current) {
+ const x = Math.min(Math.max(current.getBoundingClientRect().left, 0), window.innerWidth - RichTextMenu.Instance.width);
const y = this._ref.current!.getBoundingClientRect().top - RichTextMenu.Instance.height - 50;
RichTextMenu.Instance.jumpTo(x, y);
}
@@ -933,13 +934,13 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
if ((this._editorView!.root as any).getSelection().isCollapsed) { // this is a hack to allow the cursor to be placed at the end of a document when the document ends in an inline dash comment. Apparently Chrome on Windows has a bug/feature which breaks this when clicking after the end of the text.
const pcords = this._editorView!.posAtCoords({ left: e.clientX, top: e.clientY });
const node = pcords && this._editorView!.state.doc.nodeAt(pcords.pos); // get what prosemirror thinks the clicked node is (if it's null, then we didn't click on any text)
- if (pcords && node ?.type === this._editorView!.state.schema.nodes.dashComment) {
+ if (pcords && node?.type === this._editorView!.state.schema.nodes.dashComment) {
this._editorView!.dispatch(this._editorView!.state.tr.setSelection(TextSelection.create(this._editorView!.state.doc, pcords.pos + 2)));
e.preventDefault();
}
if (!node && this.ProseRef) {
const lastNode = this.ProseRef.children[this.ProseRef.children.length - 1].children[this.ProseRef.children[this.ProseRef.children.length - 1].children.length - 1]; // get the last prosemirror div
- if (e.clientY > lastNode.getBoundingClientRect().bottom) { // if we clicked below the last prosemirror div, then set the selection to be the end of the document
+ if (e.clientY > lastNode?.getBoundingClientRect().bottom) { // if we clicked below the last prosemirror div, then set the selection to be the end of the document
this._editorView!.dispatch(this._editorView!.state.tr.setSelection(TextSelection.create(this._editorView!.state.doc, this._editorView!.state.doc.content.size)));
}
}
@@ -996,7 +997,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
for (let off = 1; off < 100; off++) {
const pos = this._editorView!.posAtCoords({ left: x + off, top: y });
const node = pos && this._editorView!.state.doc.nodeAt(pos.pos);
- if (node ?.type === schema.nodes.list_item) {
+ if (node?.type === schema.nodes.list_item) {
list_node = node;
break;
}
@@ -1087,7 +1088,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
}
if (e.key === "Escape") {
this._editorView!.dispatch(state.tr.setSelection(TextSelection.create(state.doc, state.selection.from, state.selection.from)));
- (document.activeElement as any).blur ?.();
+ (document.activeElement as any).blur?.();
SelectionManager.DeselectAll();
}
e.stopPropagation();
@@ -1109,7 +1110,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
@action
tryUpdateHeight(limitHeight?: number) {
- let scrollHeight = this._ref.current ?.scrollHeight;
+ let scrollHeight = this._ref.current?.scrollHeight;
if (!this.layoutDoc.animateToPos && this.layoutDoc.autoHeight && scrollHeight &&
getComputedStyle(this._ref.current!.parentElement!).top === "0px") { // if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation
if (limitHeight && scrollHeight > limitHeight) {
@@ -1171,7 +1172,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
{this.props.Document.hideSidebar ? (null) : this.sidebarWidthPercent === "0%" ?
<div className="formattedTextBox-sidebar-handle" onPointerDown={this.sidebarDown} onClick={e => this.toggleSidebar()} /> :
<div className={"formattedTextBox-sidebar" + (InkingControl.Instance.selectedTool !== InkTool.None ? "-inking" : "")}
- style={{ width: `${this.sidebarWidthPercent}`, backgroundColor: `${StrCast(this.extensionDoc ?.backgroundColor, "transparent")}` }}>
+ style={{ width: `${this.sidebarWidthPercent}`, backgroundColor: `${StrCast(this.extensionDoc?.backgroundColor, "transparent")}` }}>
<CollectionFreeFormView {...this.props}
PanelHeight={this.props.PanelHeight}
PanelWidth={() => this.sidebarWidth}
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 09e627078..634555012 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -214,37 +214,23 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum
}
_curSuffix = "_m";
- _resized = false;
- resize = (srcpath: string) => {
- requestImageSize(srcpath)
+ _resized = "";
+ resize = (imgPath: string) => {
+ requestImageSize(imgPath)
.then((size: any) => {
const rotation = NumCast(this.dataDoc.rotation) % 180;
const realsize = rotation === 90 || rotation === 270 ? { height: size.width, width: size.height } : size;
const aspect = realsize.height / realsize.width;
if (this.Document.width && (Math.abs(1 - NumCast(this.Document.height) / NumCast(this.Document.width) / (realsize.height / realsize.width)) > 0.1)) {
setTimeout(action(() => {
- this._resized = true;
- this.Document.height = this.Document[WidthSym]() * aspect;
- this.Document.nativeHeight = realsize.height;
- this.Document.nativeWidth = realsize.width;
+ if (this.pathInfos.srcpath === imgPath && (!this.layoutDoc.isTemplateDoc || this.dataDoc !== this.layoutDoc)) {
+ this._resized = imgPath;
+ this.Document.height = this.Document[WidthSym]() * aspect;
+ this.Document.nativeHeight = realsize.height;
+ this.Document.nativeWidth = realsize.width;
+ }
}), 0);
- } else this._resized = true;
- })
- .catch((err: any) => console.log(err));
- }
- fadesize = (srcpath: string) => {
- requestImageSize(srcpath)
- .then((size: any) => {
- const rotation = NumCast(this.dataDoc.rotation) % 180;
- const realsize = rotation === 90 || rotation === 270 ? { height: size.width, width: size.height } : size;
- const aspect = realsize.height / realsize.width;
- if (this.Document.width && (Math.abs(1 - NumCast(this.Document.height) / NumCast(this.Document.width) / (realsize.height / realsize.width)) > 0.1)) {
- setTimeout(action(() => {
- this.Document.height = this.Document[WidthSym]() * aspect;
- this.Document.nativeHeight = realsize.height;
- this.Document.nativeWidth = realsize.width;
- }), 0);
- }
+ } else this._resized = imgPath;
})
.catch((err: any) => console.log(err));
}
@@ -285,18 +271,16 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum
return !tags ? (null) : (<img id={"google-tags"} src={"/assets/google_tags.png"} />);
}
- @computed get content() {
- TraceMobx();
- const extensionDoc = this.extensionDoc;
- if (!extensionDoc) return (null);
- // let transform = this.props.ScreenToLocalTransform().inverse();
+ @computed get nativeSize() {
const pw = typeof this.props.PanelWidth === "function" ? this.props.PanelWidth() : typeof this.props.PanelWidth === "number" ? (this.props.PanelWidth as any) as number : 50;
- // var [sptX, sptY] = transform.transformPoint(0, 0);
- // let [bptX, bptY] = transform.transformPoint(pw, this.props.PanelHeight());
- // let w = bptX - sptX;
-
const nativeWidth = (this.Document.nativeWidth || pw);
const nativeHeight = (this.Document.nativeHeight || 1);
+ return { nativeWidth, nativeHeight };
+ }
+
+ @computed get pathInfos() {
+ const extensionDoc = this.extensionDoc!;
+ const { nativeWidth, nativeHeight } = this.nativeSize;
let paths = [[Utils.CorsProxy("http://www.cs.brown.edu/~bcz/noImage.png"), nativeWidth / nativeHeight]];
// this._curSuffix = "";
// if (w > 20) {
@@ -308,15 +292,24 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum
// else if (this._largeRetryCount < 10) this._curSuffix = "_l";
if (field instanceof ImageField) paths = [[this.choosePath(field.url), nativeWidth / nativeHeight]];
paths.push(...altpaths);
- // }
- const rotation = NumCast(this.Document.rotation, 0);
- const aspect = (rotation % 180) ? this.Document[HeightSym]() / this.Document[WidthSym]() : 1;
- const shift = (rotation % 180) ? (nativeHeight - nativeWidth / aspect) / 2 : 0;
const srcpath = paths[Math.min(paths.length - 1, (this.Document.curPage || 0))][0] as string;
const srcaspect = paths[Math.min(paths.length - 1, (this.Document.curPage || 0))][1] as number;
const fadepath = paths[Math.min(paths.length - 1, 1)][0] as string;
+ return { srcpath, srcaspect, fadepath };
+ }
+
+ @computed get content() {
+ TraceMobx();
+ const extensionDoc = this.extensionDoc;
+ if (!extensionDoc) return (null);
+
+ const { srcpath, srcaspect, fadepath } = this.pathInfos;
+ const { nativeWidth, nativeHeight } = this.nativeSize;
+ const rotation = NumCast(this.Document.rotation, 0);
+ const aspect = (rotation % 180) ? this.Document[HeightSym]() / this.Document[WidthSym]() : 1;
+ const shift = (rotation % 180) ? (nativeHeight - nativeWidth / aspect) / 2 : 0;
- !this.Document.ignoreAspect && !this._resized && this.resize(srcpath);
+ !this.Document.ignoreAspect && this._resized !== srcpath && this.resize(srcpath);
return <div className="imageBox-cont" key={this.props.Document[Id]} ref={this.createDropTarget} onContextMenu={this.specificContextMenu}>
<div className="imageBox-fader" >