aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbob <bcz@cs.brown.edu>2019-06-10 13:03:47 -0400
committerbob <bcz@cs.brown.edu>2019-06-10 13:03:47 -0400
commitc56851026c4054cde26ea36a9a24db14fac6c49c (patch)
treedba7d78e0d30a378d805a27c4f9b4360b822e812
parenta2742057084ac0c78ed5f360b1078b5b267eff1f (diff)
fixes for treeview highlighting, templates, field deletion, overlaytext box positioning
-rw-r--r--src/Utils.ts2
-rw-r--r--src/client/util/DragManager.ts6
-rw-r--r--src/client/util/SelectionManager.ts9
-rw-r--r--src/client/views/MainOverlayTextBox.tsx8
-rw-r--r--src/client/views/Templates.tsx16
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx24
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx3
-rw-r--r--src/client/views/nodes/DocumentView.tsx6
-rw-r--r--src/new_fields/util.ts4
9 files changed, 42 insertions, 36 deletions
diff --git a/src/Utils.ts b/src/Utils.ts
index 611c61135..e8a80bdc3 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -15,7 +15,7 @@ export class Utils {
return v5(seed, v5.URL);
}
- public static GetScreenTransform(ele: HTMLElement): { scale: number, translateX: number, translateY: number } {
+ public static GetScreenTransform(ele?: HTMLElement): { scale: number, translateX: number, translateY: number } {
if (!ele) {
return { scale: 1, translateX: 1, translateY: 1 };
}
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 4c9f798a8..8ee1ad2af 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -1,9 +1,10 @@
-import { action, runInAction } from "mobx";
+import { action, runInAction, observable } from "mobx";
import { Doc, DocListCastAsync } from "../../new_fields/Doc";
import { Cast } from "../../new_fields/Types";
import { emptyFunction } from "../../Utils";
import { CollectionDockingView } from "../views/collections/CollectionDockingView";
import * as globalCssVariables from "../views/globalCssVariables.scss";
+import { SelectionManager } from "./SelectionManager";
export type dropActionType = "alias" | "copy" | undefined;
export function SetupDrag(_reference: React.RefObject<HTMLElement>, docFunc: () => Doc | Promise<Doc>, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType, options?: any, dontHideOnDrop?: boolean) {
@@ -194,7 +195,7 @@ export namespace DragManager {
dragDiv.style.pointerEvents = "none";
DragManager.Root().appendChild(dragDiv);
}
-
+ SelectionManager.SetIsDragging(true);
let scaleXs: number[] = [];
let scaleYs: number[] = [];
let xs: number[] = [];
@@ -293,6 +294,7 @@ export namespace DragManager {
};
let hideDragElements = () => {
+ SelectionManager.SetIsDragging(false);
dragElements.map(dragElement => dragElement.parentNode === dragDiv && dragDiv.removeChild(dragElement));
eles.map(ele => (ele.hidden = false));
};
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 0e22d576c..ddad4b818 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -1,4 +1,4 @@
-import { observable, action } from "mobx";
+import { observable, action, runInAction } from "mobx";
import { Doc } from "../../new_fields/Doc";
import { DocumentView } from "../views/nodes/DocumentView";
import { FormattedTextBox } from "../views/nodes/FormattedTextBox";
@@ -6,8 +6,8 @@ import { NumCast } from "../../new_fields/Types";
export namespace SelectionManager {
class Manager {
- @observable
- SelectedDocuments: Array<DocumentView> = [];
+ @observable IsDragging: boolean = false;
+ @observable SelectedDocuments: Array<DocumentView> = [];
@action
SelectDoc(doc: DocumentView, ctrlPressed: boolean): void {
@@ -51,6 +51,9 @@ export namespace SelectionManager {
if (found) manager.SelectDoc(found, false);
}
+ export function SetIsDragging(dragging: boolean) { runInAction(() => manager.IsDragging = dragging); }
+ export function GetIsDragging() { return manager.IsDragging; }
+
export function SelectedDocuments(): Array<DocumentView> {
return manager.SelectedDocuments;
}
diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx
index 6bbd70a25..0eb3e9707 100644
--- a/src/client/views/MainOverlayTextBox.tsx
+++ b/src/client/views/MainOverlayTextBox.tsx
@@ -1,7 +1,7 @@
import { action, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { emptyFunction, returnTrue, returnZero } from '../../Utils';
+import { emptyFunction, returnTrue, returnZero, Utils } from '../../Utils';
import { DragManager } from '../util/DragManager';
import { Transform } from '../util/Transform';
import "normalize.css";
@@ -29,7 +29,8 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
MainOverlayTextBox.Instance = this;
reaction(() => FormattedTextBox.InputBoxOverlay,
(box?: FormattedTextBox) => {
- if (box) this.setTextDoc(box.props.fieldKey, box.CurrentDiv, box.props.ScreenToLocalTransform);
+ let sxf = Utils.GetScreenTransform(box ? box.CurrentDiv : undefined);
+ if (box) this.setTextDoc(box.props.fieldKey, box.CurrentDiv, () => new Transform(-sxf.translateX, -sxf.translateY, 1 / sxf.scale));
else this.setTextDoc();
});
}
@@ -93,9 +94,10 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
if (FormattedTextBox.InputBoxOverlay && this._textTargetDiv) {
let textRect = this._textTargetDiv.getBoundingClientRect();
let s = this._textXf().Scale;
+ let auto = FormattedTextBox.InputBoxOverlay.props.height;
return <div className="mainOverlayTextBox-textInput" style={{ transform: `translate(${textRect.left}px, ${textRect.top}px) scale(${1 / s},${1 / s})`, width: "auto", height: "auto" }} >
<div className="mainOverlayTextBox-textInput" onPointerDown={this.textBoxDown} ref={this._textProxyDiv} onScroll={this.textScroll}
- style={{ width: `${textRect.width * s}px`, height: `${textRect.height * s}px` }}>
+ style={{ width: `${textRect.width * s}px`, height: auto ? "auto" : `${textRect.height * s}px` }}>
<FormattedTextBox color={`${this._textColor}`} fieldKey={this._textFieldKey} hideOnLeave={this._textHideOnLeave} isOverlay={true} Document={FormattedTextBox.InputBoxOverlay.props.Document} isSelected={returnTrue} select={emptyFunction} isTopMost={true}
selectOnLoad={true} ContainingCollectionView={undefined} whenActiveChanged={emptyFunction} active={returnTrue}
ScreenToLocalTransform={this._textXf} PanelWidth={returnZero} PanelHeight={returnZero} focus={emptyFunction} addDocTab={this.addDocTab} />
diff --git a/src/client/views/Templates.tsx b/src/client/views/Templates.tsx
index 8943bbcaf..3cd525afa 100644
--- a/src/client/views/Templates.tsx
+++ b/src/client/views/Templates.tsx
@@ -41,21 +41,13 @@ export namespace Templates {
export const Caption = new Template("Caption", TemplatePosition.OutterBottom,
`<div>
- <div style="height:100%; width:100%;position:absolute;">{layout}</div>
+ <div style="height:100%; width:100%;">{layout}</div>
<div style="bottom: 0; font-size:14px; width:100%; position:absolute">
- <FormattedTextBox {...props} fieldKey={"caption"} hideOnLeave={"true"} />
+ <FormattedTextBox {...props} height="min-content" fieldKey={"caption"} hideOnLeave={"true"} />
</div>
</div>` );
- export const ImageTitle = new Template("Image Title", TemplatePosition.InnerTop,
- `<div style="height:100%">
- <div style="height:100%; width:100%;position:absolute;">{layout}</div>
- <div style="height:25px; width:100%; position:absolute; top: 0; background-color: rgba(0, 0, 0, .4); color: white; ">
- <span style="text-align:center;width:100%;font-size:20px;position:absolute;overflow:hidden;white-space:nowrap;text-overflow:ellipsis">{props.Document.title}</span>
- </div>
- </div>` );
-
- export const TextTitle = new Template("Text Title", TemplatePosition.InnerTop,
+ export const Title = new Template("Title", TemplatePosition.InnerTop,
`<div style="height:100%">
<div style="height:25px; width:100%; background-color: rgba(0, 0, 0, .4); color: white; ">
<span style="text-align:center;width:100%;font-size:20px;position:absolute;overflow:hidden;white-space:nowrap;text-overflow:ellipsis">{props.Document.title}</span>
@@ -92,7 +84,7 @@ export namespace Templates {
</div > `);
}
- export const TemplateList: Template[] = [TextTitle, Header, ImageTitle, Caption, Bullet];
+ export const TemplateList: Template[] = [Title, Header, Caption, Bullet];
export function sortTemplates(a: Template, b: Template) {
if (a.Position < b.Position) { return -1; }
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 8dc10bcd1..8a6764c58 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -20,6 +20,7 @@ import { CollectionSubView } from "./CollectionSubView";
import "./CollectionTreeView.scss";
import React = require("react");
import { Transform } from '../../util/Transform';
+import { SelectionManager } from '../../util/SelectionManager';
export interface TreeViewProps {
@@ -32,6 +33,7 @@ export interface TreeViewProps {
ScreenToLocalTransform: () => Transform;
treeViewId: string;
parentKey: string;
+ active: () => boolean;
}
export enum BulletType {
@@ -69,7 +71,7 @@ class TreeView extends React.Component<TreeViewProps> {
@action onMouseLeave = () => { this._isOver = false; }
onPointerEnter = (e: React.PointerEvent): void => {
- this.props.document.libraryBrush = true;
+ this.props.active() && (this.props.document.libraryBrush = true);
if (e.buttons === 1) {
this._header!.current!.className = "treeViewItem-header";
document.addEventListener("pointermove", this.onDragMove, true);
@@ -149,7 +151,10 @@ class TreeView extends React.Component<TreeViewProps> {
</div>);
return (
<div className="docContainer" id={`docContainer-${this.props.parentKey}`} ref={reference} onPointerDown={onItemDown} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}
- style={{ background: BoolCast(this.props.document.protoBrush, false) ? "#06123232" : BoolCast(this.props.document.libraryBrush, false) ? "#06121212" : "0" }}
+ style={{
+ background: BoolCast(this.props.document.protoBrush, false) ? "#06123232" : BoolCast(this.props.document.libraryBrush, false) ? "#06121212" : "0",
+ pointerEvents: this.props.active() || SelectionManager.GetIsDragging() ? "all" : "none"
+ }}
>
{editableView(StrCast(this.props.document.title))}
{openRight}
@@ -225,18 +230,19 @@ class TreeView extends React.Component<TreeViewProps> {
while (keys.indexOf("proto") !== -1) keys.splice(keys.indexOf("proto"), 1);
}
keys.map(key => {
- let docList = DocListCast(this.props.document[key]);
+ let docList = Cast(this.props.document[key], listSpec(Doc));
let remDoc = (doc: Doc) => this.remove(doc, key);
let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => TreeView.AddDocToList(this.props.document, key, doc, addBefore, before);
let doc = Cast(this.props.document[key], Doc);
- if (doc instanceof Doc || docList.length) {
+ if (doc instanceof Doc || docList) {
if (!this._collapsed) {
bulletType = BulletType.Collapsible;
contentElement.push(<ul key={key + "more"}>
{(key === "data") ? (null) :
<span className="collectionTreeView-keyHeader" style={{ display: "block", marginTop: "7px" }} key={key}>{key}</span>}
<div style={{ display: "block" }}>
- {TreeView.GetChildElements(doc instanceof Doc ? [doc] : docList, this.props.treeViewId, key, addDoc, remDoc, this.move, this.props.dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform)}
+ {TreeView.GetChildElements(doc instanceof Doc ? [doc] : DocListCast(docList), this.props.treeViewId, key, addDoc, remDoc, this.move,
+ this.props.dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.props.active)}
</div>
</ul >);
} else {
@@ -266,11 +272,12 @@ class TreeView extends React.Component<TreeViewProps> {
move: DragManager.MoveFunction,
dropAction: dropActionType,
addDocTab: (doc: Doc, where: string) => void,
- screenToLocalXf: () => Transform
+ screenToLocalXf: () => Transform,
+ active: () => boolean
) {
return docs.filter(child => !child.excludeFromLibrary && (key !== "data" || !child.isMinimized)).map(child =>
<TreeView document={child} treeViewId={treeViewId} key={child[Id]} deleteDoc={remove} addDocument={add} moveDocument={move}
- dropAction={dropAction} addDocTab={addDocTab} ScreenToLocalTransform={screenToLocalXf} parentKey={key} />);
+ dropAction={dropAction} addDocTab={addDocTab} ScreenToLocalTransform={screenToLocalXf} parentKey={key} active={active} />);
}
}
@@ -309,7 +316,8 @@ export class CollectionTreeView extends CollectionSubView(Document) {
}
let addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => TreeView.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before);
let moveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc);
- let childElements = TreeView.GetChildElements(this.childDocs, this.props.Document[Id], this.props.fieldKey, addDoc, this.remove, moveDoc, dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform);
+ let childElements = TreeView.GetChildElements(this.childDocs, this.props.Document[Id], this.props.fieldKey, addDoc, this.remove,
+ moveDoc, dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.props.active);
return (
<div id="body" className="collectionTreeView-dropTarget"
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index d23bef2d3..63f24ff53 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -6,7 +6,6 @@ import { InkField, StrokeData } from "../../../../new_fields/InkField";
import { createSchema, makeInterface } from "../../../../new_fields/Schema";
import { BoolCast, Cast, FieldValue, NumCast } from "../../../../new_fields/Types";
import { emptyFunction, returnOne } from "../../../../Utils";
-import { DocServer } from "../../../DocServer";
import { DocumentManager } from "../../../util/DocumentManager";
import { DragManager } from "../../../util/DragManager";
import { HistoryUtil } from "../../../util/History";
@@ -26,7 +25,6 @@ import "./CollectionFreeFormView.scss";
import { MarqueeView } from "./MarqueeView";
import React = require("react");
import v5 = require("uuid/v5");
-import { Docs } from "../../../documents/Documents";
export const panZoomSchema = createSchema({
panX: "number",
@@ -218,6 +216,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
@action
setPan(panX: number, panY: number) {
+
this.props.Document.panTransformType = "None";
var scale = this.getLocalTransform().inverse().Scale;
const newPanX = Math.min((1 - 1 / scale) * this.nativeWidth, Math.max(0, panX));
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 2ac6d12bf..19f5c7d36 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -349,9 +349,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
dst.nativeHeight = src.nativeHeight;
}
else {
- const docs = await SearchUtil.Search(`data_l:"${destDoc[Id]}"`, true);
- const views = docs.map(d => DocumentManager.Instance.getDocumentView(d)).filter(d => d).map(d => d as DocumentView);
- DocUtils.MakeLink(sourceDoc, destDoc, views.length ? views[0].props.Document : undefined);
+ // const docs = await SearchUtil.Search(`data_l:"${destDoc[Id]}"`, true);
+ // const views = docs.map(d => DocumentManager.Instance.getDocumentView(d)).filter(d => d).map(d => d as DocumentView);
+ DocUtils.MakeLink(sourceDoc, destDoc, this.props.ContainingCollectionView ? this.props.ContainingCollectionView.props.Document : undefined);
de.data.droppedDocuments.push(destDoc);
}
}
diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts
index fe0da2e7a..8cb1db953 100644
--- a/src/new_fields/util.ts
+++ b/src/new_fields/util.ts
@@ -6,7 +6,7 @@ import { FieldValue } from "./Types";
import { RefField } from "./RefField";
import { ObjectField } from "./ObjectField";
import { action } from "mobx";
-import { Parent, OnUpdate, Update, Id } from "./FieldSymbols";
+import { Parent, OnUpdate, Update, Id, SelfProxy } from "./FieldSymbols";
import { ComputedField } from "../fields/ScriptField";
export const setter = action(function (target: any, prop: string | symbol | number, value: any, receiver: any): boolean {
@@ -86,7 +86,7 @@ export function deleteProperty(target: any, prop: string | number | symbol) {
delete target[prop];
return true;
}
- target[prop] = undefined;
+ target[SelfProxy][prop] = undefined;
return true;
}