diff options
| author | Bob Zeleznik <zzzman@gmail.com> | 2019-10-15 00:23:00 -0400 |
|---|---|---|
| committer | Bob Zeleznik <zzzman@gmail.com> | 2019-10-15 00:23:00 -0400 |
| commit | 26e215b0cddbb4c14cfd8eb7a720a373e797c615 (patch) | |
| tree | 6fee5686953a7926627cc10f4f5cf27f79bb231a /src/client | |
| parent | e8e713173e93eaa9fc2d2865d5efabdcca51b1f3 (diff) | |
cleaned up current_user_utils. cleaned up some interactions with colorBox, textbox height
Diffstat (limited to 'src/client')
| -rw-r--r-- | src/client/documents/Documents.ts | 19 | ||||
| -rw-r--r-- | src/client/views/DocComponent.tsx | 34 | ||||
| -rw-r--r-- | src/client/views/InkingControl.tsx | 8 | ||||
| -rw-r--r-- | src/client/views/MainView.tsx | 16 | ||||
| -rw-r--r-- | src/client/views/nodes/ColorBox.scss | 7 | ||||
| -rw-r--r-- | src/client/views/nodes/ColorBox.tsx | 12 | ||||
| -rw-r--r-- | src/client/views/nodes/FormattedTextBox.tsx | 13 | ||||
| -rw-r--r-- | src/client/views/nodes/PDFBox.tsx | 3 |
8 files changed, 87 insertions, 25 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 1f89d2993..13cc7815c 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -40,7 +40,7 @@ import { ButtonBox } from "../views/nodes/ButtonBox"; import { FontIconBox } from "../views/nodes/FontIconBox"; import { SchemaHeaderField, RandomPastel } from "../../new_fields/SchemaHeaderField"; import { PresBox } from "../views/nodes/PresBox"; -import { ComputedField } from "../../new_fields/ScriptField"; +import { ComputedField, ScriptField } from "../../new_fields/ScriptField"; import { ProxyField } from "../../new_fields/Proxy"; import { DocumentType } from "./DocumentTypes"; import { LinkFollowBox } from "../views/linking/LinkFollowBox"; @@ -65,7 +65,10 @@ export interface DocumentOptions { page?: number; scale?: number; fitWidth?: boolean; + forceActive?: boolean; + preventTreeViewOpen?: boolean; // ignores the treeViewOpen Doc flag which allows a treeViewItem's expande/collapse state to be independent of other views of the same document in the tree view layout?: string | Doc; + hideHeadings?: boolean; // whether stacking view column headings should be hidden isTemplate?: boolean; templates?: List<string>; viewType?: number; @@ -84,11 +87,21 @@ export interface DocumentOptions { documentText?: string; borderRounding?: string; boxShadow?: string; + sectionFilter?: string; // field key used to determine headings for sections in stacking and masonry views schemaColumns?: List<SchemaHeaderField>; dockingConfig?: string; autoHeight?: boolean; + removeDropProperties?: List<string>; // list of properties that should be removed from a document when it is dropped. e.g., a creator button may be forceActive to allow it be dragged, but the forceActive property can be removed from the dropped document dbDoc?: Doc; + onClick?: ScriptField; + onDragStart?: ScriptField; //script to execute at start of drag operation -- e.g., when a "creator" button is dragged this script generates a different document to drop icon?: string; + gridGap?: number; // gap between items in masonry view + xMargin?: number; // gap between left edge of document and start of masonry/stacking layouts + yMargin?: number; // gap between top edge of dcoument and start of masonry/stacking layouts + panel?: Doc; // panel to display in 'targetContainer' as the result of a button onClick script + targetContainer?: Doc; // document whose proto will be set to 'panel' as the result of a onClick click script + convertToButtons?: boolean; // whether documents dropped onto a collection should be converted to buttons that will construct the dropped document // [key: string]: Opt<Field>; } @@ -457,6 +470,10 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, viewType: CollectionViewType.Freeform }, id); } + export function LinearDocument(documents: Array<Doc>, options: DocumentOptions, id?: string) { + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, viewType: CollectionViewType.Linear }, id); + } + export function SchemaDocument(schemaColumns: SchemaHeaderField[], documents: Array<Doc>, options: DocumentOptions) { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { chromeStatus: "collapsed", schemaColumns: new List(schemaColumns), ...options, viewType: CollectionViewType.Schema }); } diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 2c5992259..b05966bb5 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -1,10 +1,17 @@ import * as React from 'react'; import { Doc } from '../../new_fields/Doc'; import { computed, action } from 'mobx'; -import { Cast } from '../../new_fields/Types'; +import { Cast, BoolCast } from '../../new_fields/Types'; import { listSpec } from '../../new_fields/Schema'; +import { InkingControl } from './InkingControl'; +import { InkTool } from '../../new_fields/InkField'; -export function DocComponent<P extends { Document: Doc }, T>(schemaCtor: (doc: Doc) => T) { + +/// DocComponents returns a generic base class for React views of document fields that are not interactive +interface DocComponentProps { + Document: Doc; +} +export function DocComponent<P extends DocComponentProps, T>(schemaCtor: (doc: Doc) => T) { class Component extends React.Component<P> { //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then @computed @@ -15,6 +22,27 @@ export function DocComponent<P extends { Document: Doc }, T>(schemaCtor: (doc: D return Component; } + +/// DocStaticProps return a base class for React views of document fields that are interactive only when selected (e.g. ColorBox) +interface DocStaticProps { + Document: Doc; + isSelected: () => boolean; + renderDepth: number; +} +export function DocStaticComponent<P extends DocStaticProps, T>(schemaCtor: (doc: Doc) => T) { + class Component extends React.Component<P> { + //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then + @computed + get Document(): T { + return schemaCtor(this.props.Document); + } + active = () => (this.props.Document.forceActive || this.props.isSelected() || this.props.renderDepth === 0) && !InkingControl.Instance.selectedTool; + } + return Component; +} + + +/// DocAnnotatbleComponent return a base class for React views of document fields that are annotatable *and* interactive when selected (e.g., pdf, image) interface DocAnnotatableProps { Document: Doc; DataDoc?: Doc; @@ -57,7 +85,7 @@ export function DocAnnotatableComponent<P extends DocAnnotatableProps, T>(schema return Doc.AddDocToList(this.extensionDoc, this.props.fieldExt, doc); } whenActiveChanged = (isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive); - active = () => this.props.isSelected() || this._isChildActive || this.props.renderDepth === 0; + active = () => (InkingControl.Instance.selectedTool === InkTool.None) && (BoolCast(this.props.Document.forceActive) || this.props.isSelected() || this._isChildActive || this.props.renderDepth === 0); } return Component; }
\ No newline at end of file diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx index 38734a03d..d42d8d2d9 100644 --- a/src/client/views/InkingControl.tsx +++ b/src/client/views/InkingControl.tsx @@ -48,6 +48,14 @@ export class InkingControl extends React.Component { let selected = SelectionManager.SelectedDocuments(); let oldColors = selected.map(view => { let targetDoc = view.props.Document.layout instanceof Doc ? view.props.Document.layout : view.props.Document.isTemplate ? view.props.Document : Doc.GetProto(view.props.Document); + let sel = window.getSelection(); + if (StrCast(targetDoc.layout).indexOf("FormattedTextBox") !== -1 && (!sel || sel.toString() !== "")) { + targetDoc.color = this._selectedColor; + return { + target: targetDoc, + previous: StrCast(targetDoc.color) + }; + } let oldColor = StrCast(targetDoc.backgroundColor); let matchedColor = this._selectedColor; const cvd = view.props.ContainingCollectionDoc; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index ddea3e223..701f094e2 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -343,12 +343,12 @@ export class MainView extends React.Component { if (!(sidebarContent instanceof Doc)) { return (null); } - let libraryButtonDoc = Cast(CurrentUserUtils.UserDocument.libraryButtons, Doc) as Doc; - libraryButtonDoc.columnWidth = this.flyoutWidth / 3 - 30; + let sidebarButtonsDoc = Cast(CurrentUserUtils.UserDocument.sidebarButtons, Doc) as Doc; + sidebarButtonsDoc.columnWidth = this.flyoutWidth / 3 - 30; return <div className="mainView-flyoutContainer"> <div className="mainView-tabButtons" style={{ height: `${this._buttonBarHeight}px` }}> <DocumentView - Document={libraryButtonDoc} + Document={sidebarButtonsDoc} DataDoc={undefined} addDocument={undefined} addDocTab={this.addDocTabFunc} @@ -443,18 +443,20 @@ export class MainView extends React.Component { } addButtonDoc = (doc: Doc) => { - Doc.AddDocToList(CurrentUserUtils.UserDocument, "docButtons", doc); + Doc.AddDocToList(CurrentUserUtils.UserDocument.expandingButtons as Doc, "data", doc); return true; } remButtonDoc = (doc: Doc) => { - Doc.RemoveDocFromList(CurrentUserUtils.UserDocument, "docButtons", doc); + Doc.RemoveDocFromList(CurrentUserUtils.UserDocument.expandingButtons as Doc, "data", doc); return true; } @computed get docButtons() { return <div className="mainView-docButtons" style={{ left: (this._flyoutTranslate ? this.flyoutWidth : 0) + 20 }} > <MainViewNotifs /> - <CollectionLinearView Document={CurrentUserUtils.UserDocument} DataDoc={undefined} - fieldKey={"docButtons"} + <CollectionLinearView + Document={CurrentUserUtils.UserDocument.expandingButtons as Doc} + DataDoc={undefined} + fieldKey={"data"} fieldExt={""} showHiddenControls={true} select={emptyFunction} diff --git a/src/client/views/nodes/ColorBox.scss b/src/client/views/nodes/ColorBox.scss index 8df617fca..32a7891c6 100644 --- a/src/client/views/nodes/ColorBox.scss +++ b/src/client/views/nodes/ColorBox.scss @@ -1,10 +1,13 @@ -.colorBox-container { +.colorBox-container, .colorBox-container-interactive { width:100%; height:100%; position: relative; - pointer-events:all; + pointer-events: none; .sketch-picker { margin:auto; } +} +.colorBox-container-interactive { + pointer-events:all; }
\ No newline at end of file diff --git a/src/client/views/nodes/ColorBox.tsx b/src/client/views/nodes/ColorBox.tsx index 4aff770f9..d280258ae 100644 --- a/src/client/views/nodes/ColorBox.tsx +++ b/src/client/views/nodes/ColorBox.tsx @@ -4,13 +4,19 @@ import { SketchPicker } from 'react-color'; import { FieldView, FieldViewProps } from './FieldView'; import "./ColorBox.scss"; import { InkingControl } from "../InkingControl"; +import { DocStaticComponent } from "../DocComponent"; +import { documentSchema } from "./DocumentView"; +import { makeInterface } from "../../../new_fields/Schema"; + +type ColorDocument = makeInterface<[typeof documentSchema]>; +const ColorDocument = makeInterface(documentSchema); @observer -export class ColorBox extends React.Component<FieldViewProps> { +export class ColorBox extends DocStaticComponent<FieldViewProps, ColorDocument>(ColorDocument) { public static LayoutString(fieldKey?: string) { return FieldView.LayoutString(ColorBox, fieldKey); } render() { - return <div className="colorBox-container" > + return <div className={`colorBox-container${this.active() ? "-interactive" : ""}`} onPointerDown={e => e.button === 0 && !e.ctrlKey && e.stopPropagation()}> <SketchPicker color={InkingControl.Instance.selectedColor} onChange={InkingControl.Instance.switchColor} /> </div>; } -}
\ No newline at end of file +}
\ No newline at end of file diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index b05d0046c..181f37d36 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -43,7 +43,6 @@ import { FormattedTextBoxComment, formattedTextBoxCommentPlugin } from './Format import React = require("react"); import { ContextMenuProps } from '../ContextMenuItem'; import { ContextMenu } from '../ContextMenu'; -import { TextShadowProperty } from 'csstype'; library.add(faEdit); library.add(faSmile, faTextHeight, faUpload); @@ -490,7 +489,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe ); this._heightReactionDisposer = reaction( - () => this.props.Document[WidthSym](), + () => [this.props.Document[WidthSym](), this.props.Document.autoHeight], () => this.tryUpdateHeight() ); @@ -984,13 +983,13 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe @action tryUpdateHeight() { - const ChromeHeight = this.props.ChromeHeight; - let sh = this._ref.current ? this._ref.current.scrollHeight : 0; - if (!this.props.Document.isAnimating && this.props.Document.autoHeight && sh !== 0 && getComputedStyle(this._ref.current!.parentElement!).top === "0px") { + let scrollHeight = this._ref.current ? this._ref.current.scrollHeight : 0; + if (!this.props.Document.isAnimating && this.props.Document.autoHeight && scrollHeight !== 0 && + 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 let nh = this.props.Document.isTemplate ? 0 : NumCast(this.dataDoc.nativeHeight, 0); let dh = NumCast(this.props.Document.height, 0); - this.props.Document.height = Math.max(10, (nh ? dh / nh * sh : sh) + (ChromeHeight ? ChromeHeight() : 0)); - this.dataDoc.nativeHeight = nh ? sh : undefined; + this.props.Document.height = Math.max(10, (nh ? dh / nh * scrollHeight : scrollHeight) + (this.props.ChromeHeight ? this.props.ChromeHeight() : 0)); + this.dataDoc.nativeHeight = nh ? scrollHeight : undefined; } } diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 63b412a23..19797400f 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -115,7 +115,6 @@ export class PDFBox extends DocAnnotatableComponent<FieldViewProps, PdfDocument> private newScriptChange = (e: React.ChangeEvent<HTMLInputElement>) => this._scriptValue = e.currentTarget.value; whenActiveChanged = (isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive); - active = () => this.props.isSelected() || this._isChildActive || this.props.renderDepth === 0; setPdfViewer = (pdfViewer: PDFViewer) => { this._pdfViewer = pdfViewer; }; searchStringChanged = (e: React.ChangeEvent<HTMLInputElement>) => this._searchString = e.currentTarget.value; @@ -205,7 +204,7 @@ export class PDFBox extends DocAnnotatableComponent<FieldViewProps, PdfDocument> _initialScale: number | undefined; // the initial scale of the PDF when first rendered which determines whether the document will be live on startup or not. Getting bigger after startup won't make it automatically be live.... render() { const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField); - let classname = "pdfBox-cont" + (InkingControl.Instance.selectedTool || !this.active ? "" : "-interactive"); + let classname = "pdfBox-cont" + (this.active() ? "-interactive" : ""); let noPdf = !(pdfUrl instanceof PdfField) || !this._pdf; if (this._initialScale === undefined) this._initialScale = this.props.ScreenToLocalTransform().Scale; if (this.props.isSelected() || this.props.Document.scrollY !== undefined) this._everActive = true; |
