From da6283875ec7f59af602e14ed19fcab93533f377 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 14 Jun 2022 13:00:27 -0400 Subject: made shared with me doc count decrement when a document is viewed (double-clicked, dragged out) --- src/client/views/nodes/button/FontIconBadge.tsx | 30 ++++++++++++------------- src/client/views/nodes/button/FontIconBox.tsx | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) (limited to 'src/client/views/nodes') diff --git a/src/client/views/nodes/button/FontIconBadge.tsx b/src/client/views/nodes/button/FontIconBadge.tsx index cf86b5e07..3b5aac221 100644 --- a/src/client/views/nodes/button/FontIconBadge.tsx +++ b/src/client/views/nodes/button/FontIconBadge.tsx @@ -7,30 +7,30 @@ import { DragManager } from "../../../util/DragManager"; import "./FontIconBadge.scss"; interface FontIconBadgeProps { - collection: Doc | undefined; + value: string | undefined; } @observer export class FontIconBadge extends React.Component { _notifsRef = React.createRef(); - onPointerDown = (e: React.PointerEvent) => { - setupMoveUpEvents(this, e, - (e: PointerEvent) => { - const dragData = new DragManager.DocumentDragData([this.props.collection!]); - DragManager.StartDocumentDrag([this._notifsRef.current!], dragData, e.x, e.y); - return true; - }, - returnFalse, emptyFunction, false); - } + // onPointerDown = (e: React.PointerEvent) => { + // setupMoveUpEvents(this, e, + // (e: PointerEvent) => { + // const dragData = new DragManager.DocumentDragData([this.props.collection!]); + // DragManager.StartDocumentDrag([this._notifsRef.current!], dragData, e.x, e.y); + // return true; + // }, + // returnFalse, emptyFunction, false); + // } render() { - if (!(this.props.collection instanceof Doc)) return (null); - const length = DocListCast(this.props.collection.data).filter(d => GetEffectiveAcl(d) !== AclPrivate).length; // Object.keys(d).length).length; // filter out any documents that we can't read + if (this.props.value === undefined) return (null); return
-
0 ? { "display": "initial" } : { "display": "none" }} - onPointerDown={this.onPointerDown} > - {length} +
+ {this.props.value}
; } diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx index a1b9023f3..97e6eddfe 100644 --- a/src/client/views/nodes/button/FontIconBox.tsx +++ b/src/client/views/nodes/button/FontIconBox.tsx @@ -521,7 +521,7 @@ export class FontIconBox extends DocComponent() {
{this.icon === "pres-trail" ? trailsIcon : } {menuLabel} - +
); break; -- cgit v1.2.3-70-g09d2 From 85cb5c02e5d2adbb6d181a5924f8a490131bb04d Mon Sep 17 00:00:00 2001 From: mehekj Date: Thu, 23 Jun 2022 12:37:39 -0400 Subject: fixed audio bugs pausing and switching dashboards while recording --- src/client/views/nodes/AudioBox.tsx | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'src/client/views/nodes') diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 94cef2906..c42c2306a 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -63,7 +63,6 @@ export class AudioBox extends ViewBoxAnnotatableComponent disposer?.()); - // removes doc from active recordings if recording when closed - const ind = DocUtils.ActiveRecordings.indexOf(this); - ind !== -1 && DocUtils.ActiveRecordings.splice(ind, 1); + this.mediaState === media_state.Recording && this.stopRecording(); } @action @@ -220,10 +216,8 @@ export class AudioBox extends ViewBoxAnnotatableComponent { if (this.mediaState === media_state.Recording) { setTimeout(this.updateRecordTime, 30); - if (this._paused) { - this._pausedTime += (new Date().getTime() - this._recordStart) / 1000; - } else { - this.layoutDoc._currentTimecode = (new Date().getTime() - this._recordStart - this.pauseTime) / 1000; + if (!this._paused) { + this.layoutDoc._currentTimecode = (new Date().getTime() - this._recordStart - this._pausedTime) / 1000; } } } @@ -253,7 +247,9 @@ export class AudioBox extends ViewBoxAnnotatableComponent { setupMoveUpEvents(this, e, returnFalse, returnFalse, action(() => { - this._pauseEnd = new Date().getTime(); this._paused = false; + this._pausedTime += new Date().getTime() - this._pauseStart; this._recorder.resume(); }), false); } -- cgit v1.2.3-70-g09d2 From e4ebdbbefb2696ea6b75464a93a5714ab0245135 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 23 Jun 2022 14:11:57 -0400 Subject: fixes for resizing native sized documents with fitwidth on/off and nativeHeightUnfrozen on/off --- src/client/documents/Documents.ts | 2 +- src/client/views/DocumentDecorations.tsx | 23 ++++++++++++----------- src/client/views/nodes/DocumentView.tsx | 3 +-- 3 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src/client/views/nodes') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index fc73deb36..f3f9bd1d9 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -362,7 +362,7 @@ export namespace Docs { [DocumentType.RTF, { layout: { view: FormattedTextBox, dataField: "text" }, options: { - _height: 35, _xMargin: 10, _yMargin: 10, nativeDimModifiable: true, nativeHeightUnfrozen: true, treeViewGrowsHorizontally: true, + _height: 35, _xMargin: 10, _yMargin: 10, nativeDimModifiable: true, treeViewGrowsHorizontally: true, forceReflow: true, links: "@links(self)" } }], diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 4247501bb..bef7c85a4 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -311,7 +311,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P move[1] = thisPt.y - this._snapY; this._snapX = thisPt.x; this._snapY = thisPt.y; - let dragBottom = false, dragRight = false, dragBotRight = false; + let dragBottom = false, dragRight = false, dragBotRight = false, dragTop = false; let dX = 0, dY = 0, dW = 0, dH = 0; switch (this._resizeHdlId.split(" ")[0]) { case "": break; @@ -329,7 +329,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P case "documentDecorations-topResizer": dY = -1; dH = -move[1]; - dragBottom = true; + dragTop = true; break; case "documentDecorations-bottomLeftResizer": dX = -1; @@ -361,27 +361,28 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P const doc = Document(docView.rootDoc); const nwidth = docView.nativeWidth; const nheight = docView.nativeHeight; - const docheight = doc._height || 0; - const docwidth = doc._width || 0; + let docheight = doc._height || 0; + let docwidth = doc._width || 0; const width = docwidth; let height = (docheight || (nheight / nwidth * width)); height = !height || isNaN(height) ? 20 : height; const scale = docView.props.ScreenToLocalTransform().Scale; - const modifyNativeDim = (e.ctrlKey || doc.forceReflow) && doc.nativeDimModifiable; + const modifyNativeDim = (e.ctrlKey || doc.forceReflow) && doc.nativeDimModifiable && ((!dragBottom && !dragTop) || doc.nativeHeightUnfrozen); if (nwidth && nheight) { - if (nwidth / nheight !== width / height && !dragBottom) { + if (nwidth / nheight !== width / height && !dragBottom && !dragTop) { height = nheight / nwidth * width; } - if (modifyNativeDim && !dragBottom) { // ctrl key enables modification of the nativeWidth or nativeHeight durin the interaction + if (modifyNativeDim && !dragBottom && !dragTop) { // ctrl key enables modification of the nativeWidth or nativeHeight durin the interaction if (Math.abs(dW) > Math.abs(dH)) dH = dW * nheight / nwidth; else dW = dH * nwidth / nheight; } } let actualdW = Math.max(width + (dW * scale), 20); let actualdH = Math.max(height + (dH * scale), 20); - const fixedAspect = (nwidth && nheight && !doc._fitWidth); + const fixedAspect = (nwidth && nheight && (!doc._fitWidth || doc.nativeHeightUnfrozen)); + console.log(fixedAspect); if (fixedAspect) { - if ((Math.abs(dW) > Math.abs(dH) && (!dragBottom || !modifyNativeDim)) || dragRight) { + if ((Math.abs(dW) > Math.abs(dH) && ((!dragBottom && !dragTop)|| !modifyNativeDim)) || dragRight) { if (dragRight && modifyNativeDim) { doc._nativeWidth = actualdW / (doc._width || 1) * Doc.NativeWidth(doc); } else { @@ -394,7 +395,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P doc._width = actualdW; } else { - if (dragBottom && (modifyNativeDim || + if ((dragBottom|| dragTop) && (modifyNativeDim || (docView.layoutDoc.nativeHeightUnfrozen && docView.layoutDoc._fitWidth))) { // frozen web pages, PDFs, and some RTFS have frozen nativewidth/height. But they are marked to allow their nativeHeight to be explicitly modified with fitWidth and vertical resizing. (ie, with fitWidth they can't grow horizontally to match a vertical resize so it makes more sense to change their nativeheight even if the ctrl key isn't used) doc._nativeHeight = actualdH / (doc._height || 1) * Doc.NativeHeight(doc); doc._autoHeight = false; @@ -417,7 +418,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P dH && (doc._autoHeight = false); } doc.x = (doc.x || 0) + dX * (actualdW - docwidth); - doc.y = (doc.y || 0) + dY * (actualdH - docheight); + doc.y = (doc.y || 0) + (dragBottom ? 0: dY * (actualdH - docheight)); doc._lastModified = new DateField(); } const val = this._dragHeights.get(docView.layoutDoc); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 8d4fd376f..4c612891b 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1249,7 +1249,7 @@ export class DocumentView extends React.Component { return this.props.PanelHeight(); } @computed get Xshift() { return this.effectiveNativeWidth ? (this.props.PanelWidth() - this.effectiveNativeWidth * this.nativeScaling) / 2 : 0; } - @computed get Yshift() { return this.effectiveNativeWidth && this.effectiveNativeHeight && Math.abs(this.Xshift) < 0.001 ? (this.props.PanelHeight() - this.effectiveNativeHeight * this.nativeScaling) / 2 : 0; } + @computed get Yshift() { return this.effectiveNativeWidth && this.effectiveNativeHeight && Math.abs(this.Xshift) < 0.001 && !this.layoutDoc.nativeHeightUnfrozen ? Math.max(0, (this.props.PanelHeight() - this.effectiveNativeHeight * this.nativeScaling) / 2) : 0; } @computed get centeringX() { return this.props.dontCenter?.includes("x") ? 0 : this.Xshift; } @computed get centeringY() { return this.props.dontCenter?.includes("y") ? 0 : this.Yshift; } @@ -1343,7 +1343,6 @@ export class DocumentView extends React.Component { transition: this.props.dataTransition, position: this.props.Document.isInkMask ? "absolute" : undefined, transform: isButton ? undefined : `translate(${this.centeringX}px, ${this.centeringY}px)`, - margin: this.fitWidth ? "auto" : undefined, width: isButton || isPresTreeElement ? "100%" : xshift() ?? `${100 * (this.props.PanelWidth() - this.Xshift * 2) / this.props.PanelWidth()}%`, height: isButton || this.props.forceAutoHeight ? undefined : yshift() ?? (this.fitWidth ? `${this.panelHeight}px` : `${100 * this.effectiveNativeHeight / this.effectiveNativeWidth * this.props.PanelWidth() / this.props.PanelHeight()}%`), -- cgit v1.2.3-70-g09d2 From c230b687f467c20613f411795afffcfa55989042 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 23 Jun 2022 15:39:24 -0400 Subject: fixes for getBounds (& docDecorations) for docs with scroll heights & native Heights/ --- src/client/views/DocumentDecorations.tsx | 4 ++-- src/client/views/nodes/DocumentView.tsx | 5 +++-- src/client/views/nodes/formattedText/FormattedTextBox.tsx | 1 + 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src/client/views/nodes') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index bef7c85a4..669718e81 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -367,7 +367,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P let height = (docheight || (nheight / nwidth * width)); height = !height || isNaN(height) ? 20 : height; const scale = docView.props.ScreenToLocalTransform().Scale; - const modifyNativeDim = (e.ctrlKey || doc.forceReflow) && doc.nativeDimModifiable && ((!dragBottom && !dragTop) || doc.nativeHeightUnfrozen); + const modifyNativeDim = (e.ctrlKey || doc.forceReflow) && doc.nativeDimModifiable && ((!dragBottom && !dragTop) || e.ctrlKey || doc.nativeHeightUnfrozen); if (nwidth && nheight) { if (nwidth / nheight !== width / height && !dragBottom && !dragTop) { height = nheight / nwidth * width; @@ -379,7 +379,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P } let actualdW = Math.max(width + (dW * scale), 20); let actualdH = Math.max(height + (dH * scale), 20); - const fixedAspect = (nwidth && nheight && (!doc._fitWidth || doc.nativeHeightUnfrozen)); + const fixedAspect = (nwidth && nheight && (!doc._fitWidth || e.ctrlKey || doc.nativeHeightUnfrozen)); console.log(fixedAspect); if (fixedAspect) { if ((Math.abs(dW) > Math.abs(dH) && ((!dragBottom && !dragTop)|| !modifyNativeDim)) || dragRight) { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 4c612891b..2ea976813 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1243,8 +1243,9 @@ export class DocumentView extends React.Component { @computed get panelWidth() { return this.effectiveNativeWidth ? this.effectiveNativeWidth * this.nativeScaling : this.props.PanelWidth(); } @computed get panelHeight() { - if (this.effectiveNativeHeight) { - return Math.min(this.props.PanelHeight(), Math.max(this.ComponentView?.getScrollHeight?.() ?? NumCast(this.layoutDoc.scrollHeight), this.effectiveNativeHeight) * this.nativeScaling); + if (this.effectiveNativeHeight && !this.layoutDoc.nativeHeightUnfrozen) { + const scrollHeight = this.fitWidth ? Math.max(this.ComponentView?.getScrollHeight?.() ?? NumCast(this.layoutDoc.scrollHeight)) : 0; + return Math.min(this.props.PanelHeight(), Math.max(scrollHeight, this.effectiveNativeHeight) * this.nativeScaling); } return this.props.PanelHeight(); } diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index d3dee3c89..9ae604e9b 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -854,6 +854,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp return this._didScroll ? this._focusSpeed : undefined; // if we actually scrolled, then return some focusSpeed } + getScrollHeight = () => this.scrollHeight; // if the scroll height has changed and we're in autoHeight mode, then we need to update the textHeight component of the doc. // Since we also monitor all component height changes, this will update the document's height. resetNativeHeight = (scrollHeight: number) => { -- cgit v1.2.3-70-g09d2 From 71790cb5ee62fa443a24e6a5181383cf46350c32 Mon Sep 17 00:00:00 2001 From: Naafiyan Ahmed Date: Wed, 29 Jun 2022 16:16:18 -0400 Subject: basic graph not working --- src/client/documents/Documents.ts | 2 +- src/client/views/nodes/DataViz.scss | 0 src/client/views/nodes/DataViz.tsx | 21 -- src/client/views/nodes/DataVizBox/DataVizBox.scss | 0 src/client/views/nodes/DataVizBox/DataVizBox.tsx | 90 ++++++++ src/client/views/nodes/DataVizBox/DrawHelper.ts | 247 +++++++++++++++++++++ .../views/nodes/DataVizBox/HistogramBox.scss | 18 ++ src/client/views/nodes/DataVizBox/HistogramBox.tsx | 159 +++++++++++++ src/client/views/nodes/DataVizBox/TableBox.scss | 22 ++ src/client/views/nodes/DataVizBox/TableBox.tsx | 37 +++ src/client/views/nodes/DocumentContentsView.tsx | 2 +- 11 files changed, 575 insertions(+), 23 deletions(-) delete mode 100644 src/client/views/nodes/DataViz.scss delete mode 100644 src/client/views/nodes/DataViz.tsx create mode 100644 src/client/views/nodes/DataVizBox/DataVizBox.scss create mode 100644 src/client/views/nodes/DataVizBox/DataVizBox.tsx create mode 100644 src/client/views/nodes/DataVizBox/DrawHelper.ts create mode 100644 src/client/views/nodes/DataVizBox/HistogramBox.scss create mode 100644 src/client/views/nodes/DataVizBox/HistogramBox.tsx create mode 100644 src/client/views/nodes/DataVizBox/TableBox.scss create mode 100644 src/client/views/nodes/DataVizBox/TableBox.tsx (limited to 'src/client/views/nodes') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 01cfe90da..59a1d41a8 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -37,7 +37,7 @@ import { AudioBox } from "../views/nodes/AudioBox"; import { FontIconBox } from "../views/nodes/button/FontIconBox"; import { ColorBox } from "../views/nodes/ColorBox"; import { ComparisonBox } from "../views/nodes/ComparisonBox"; -import { DataVizBox } from "../views/nodes/DataViz"; +import { DataVizBox } from "../views/nodes/DataVizBox/DataVizBox"; import { DocFocusOptions } from "../views/nodes/DocumentView"; import { EquationBox } from "../views/nodes/EquationBox"; import { FieldViewProps } from "../views/nodes/FieldView"; diff --git a/src/client/views/nodes/DataViz.scss b/src/client/views/nodes/DataViz.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/client/views/nodes/DataViz.tsx b/src/client/views/nodes/DataViz.tsx deleted file mode 100644 index d9541dba0..000000000 --- a/src/client/views/nodes/DataViz.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { observer } from "mobx-react"; -import * as React from "react"; -import { ViewBoxBaseComponent } from '../DocComponent'; -import "./DataViz.scss"; -import { FieldView, FieldViewProps } from "./FieldView"; - -@observer -export class DataVizBox extends ViewBoxBaseComponent() { - - public static LayoutString(fieldKey: string) { return FieldView.LayoutString(DataVizBox, fieldKey); } - - render() { - return ( -
-
- Hi -
-
- ); - } -} \ No newline at end of file diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.scss b/src/client/views/nodes/DataVizBox/DataVizBox.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx new file mode 100644 index 000000000..592723ee9 --- /dev/null +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -0,0 +1,90 @@ +import { action, computed, observable } from "mobx"; +import { observer } from "mobx-react"; +import * as React from "react"; +import { StrCast } from "../../../../fields/Types"; +import { ViewBoxBaseComponent } from "../../DocComponent"; +import { FieldViewProps, FieldView } from "../FieldView"; +import "./DataVizBox.scss"; +import { HistogramBox } from "./HistogramBox"; +import { TableBox } from "./TableBox"; + +enum DataVizView { + TABLE = "table", + HISTOGRAM= "histogram" +} + + +@observer +export class DataVizBox extends ViewBoxBaseComponent() { + @observable private pairs: {x: number, y:number}[] = [{x: 1, y:2}]; + + // TODO: nda - make this use enum values instead + // @observable private currView: DataVizView = DataVizView.TABLE; + @computed get currView() { + if (this.rootDoc._dataVizView) { + return StrCast(this.rootDoc._dataVizView); + } else { + return "table"; + } + } + + constructor(props: any) { + super(props); + if (!this.rootDoc._dataVizView) { + // TODO: nda - this might not always want to default to "table" + this.rootDoc._dataVizView = "table"; + } + } + + public static LayoutString(fieldKey: string) { return FieldView.LayoutString(DataVizBox, fieldKey); } + + @action + private createPairs() { + const xVals: number[] = [0, 1, 2, 3, 4, 5]; + // const yVals: number[] = [10, 20, 30, 40, 50, 60]; + const yVals: number[] = [1, 2, 3, 4, 5, 6]; + let pairs: { + x: number, + y:number + }[] = []; + if (xVals.length != yVals.length) return pairs; + for (let i = 0; i < xVals.length; i++) { + pairs.push({x: xVals[i], y: yVals[i]}); + } + this.pairs = pairs; + return pairs; + } + + @computed get selectView() { + switch(this.currView) { + case "table": + return () + case "histogram": + return () + } + } + + @computed get pairVals() { + return this.createPairs(); + } + + componentDidMount() { + this.createPairs(); + } + + // handle changing the view using a button + @action changeViewHandler(e: React.MouseEvent) { + e.preventDefault(); + e.stopPropagation(); + this.rootDoc._dataVizView = this.currView == "table" ? "histogram" : "table"; + } + + render() { + return ( +
+ + {this.selectView} +
+ ); + } +} \ No newline at end of file diff --git a/src/client/views/nodes/DataVizBox/DrawHelper.ts b/src/client/views/nodes/DataVizBox/DrawHelper.ts new file mode 100644 index 000000000..595cecebf --- /dev/null +++ b/src/client/views/nodes/DataVizBox/DrawHelper.ts @@ -0,0 +1,247 @@ +export class PIXIPoint { + public get x() { return this.coords[0]; } + public get y() { return this.coords[1]; } + public set x(value: number) { this.coords[0] = value; } + public set y(value: number) { this.coords[1] = value; } + public coords: number[] = [0, 0]; + constructor(x: number, y: number) { + this.coords[0] = x; + this.coords[1] = y; + } +} + +export class PIXIRectangle { + public x: number; + public y: number; + public width: number; + public height: number; + public get left() { return this.x; } + public get right() { return this.x + this.width; } + public get top() { return this.y; } + public get bottom() { return this.top + this.height; } + public static get EMPTY() { return new PIXIRectangle(0, 0, -1, -1); } + constructor(x: number, y: number, width: number, height: number) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } +} + +export class MathUtil { + + public static EPSILON: number = 0.001; + + public static Sign(value: number): number { + return value >= 0 ? 1 : -1; + } + + public static AddPoint(p1: PIXIPoint, p2: PIXIPoint, inline: boolean = false): PIXIPoint { + if (inline) { + p1.x += p2.x; + p1.y += p2.y; + return p1; + } + else { + return new PIXIPoint(p1.x + p2.x, p1.y + p2.y); + } + } + + public static Perp(p1: PIXIPoint): PIXIPoint { + return new PIXIPoint(-p1.y, p1.x); + } + + public static DividePoint(p1: PIXIPoint, by: number, inline: boolean = false): PIXIPoint { + if (inline) { + p1.x /= by; + p1.y /= by; + return p1; + } + else { + return new PIXIPoint(p1.x / by, p1.y / by); + } + } + + public static MultiplyConstant(p1: PIXIPoint, by: number, inline: boolean = false) { + if (inline) { + p1.x *= by; + p1.y *= by; + return p1; + } + else { + return new PIXIPoint(p1.x * by, p1.y * by); + } + } + + public static SubtractPoint(p1: PIXIPoint, p2: PIXIPoint, inline: boolean = false): PIXIPoint { + if (inline) { + p1.x -= p2.x; + p1.y -= p2.y; + return p1; + } + else { + return new PIXIPoint(p1.x - p2.x, p1.y - p2.y); + } + } + + public static Area(rect: PIXIRectangle): number { + return rect.width * rect.height; + } + + public static DistToLineSegment(v: PIXIPoint, w: PIXIPoint, p: PIXIPoint) { + // Return minimum distance between line segment vw and point p + var l2 = MathUtil.DistSquared(v, w); // i.e. |w-v|^2 - avoid a sqrt + if (l2 === 0.0) return MathUtil.Dist(p, v); // v === w case + // Consider the line extending the segment, parameterized as v + t (w - v). + // We find projection of point p onto the line. + // It falls where t = [(p-v) . (w-v)] / |w-v|^2 + // We clamp t from [0,1] to handle points outside the segment vw. + var dot = MathUtil.Dot( + MathUtil.SubtractPoint(p, v), + MathUtil.SubtractPoint(w, v)) / l2; + var t = Math.max(0, Math.min(1, dot)); + // Projection falls on the segment + var projection = MathUtil.AddPoint(v, + MathUtil.MultiplyConstant( + MathUtil.SubtractPoint(w, v), t)); + return MathUtil.Dist(p, projection); + } + + public static LineSegmentIntersection(ps1: PIXIPoint, pe1: PIXIPoint, ps2: PIXIPoint, pe2: PIXIPoint): PIXIPoint | undefined { + var a1 = pe1.y - ps1.y; + var b1 = ps1.x - pe1.x; + + var a2 = pe2.y - ps2.y; + var b2 = ps2.x - pe2.x; + + var delta = a1 * b2 - a2 * b1; + if (delta === 0) { + return undefined; + } + var c2 = a2 * ps2.x + b2 * ps2.y; + var c1 = a1 * ps1.x + b1 * ps1.y; + var invdelta = 1 / delta; + return new PIXIPoint((b2 * c1 - b1 * c2) * invdelta, (a1 * c2 - a2 * c1) * invdelta); + } + + public static PointInPIXIRectangle(p: PIXIPoint, rect: PIXIRectangle): boolean { + if (p.x < rect.left - this.EPSILON) { + return false; + } + if (p.x > rect.right + this.EPSILON) { + return false; + } + if (p.y < rect.top - this.EPSILON) { + return false; + } + if (p.y > rect.bottom + this.EPSILON) { + return false; + } + + return true; + } + + public static LinePIXIRectangleIntersection(lineFrom: PIXIPoint, lineTo: PIXIPoint, rect: PIXIRectangle): Array { + var r1 = new PIXIPoint(rect.left, rect.top); + var r2 = new PIXIPoint(rect.right, rect.top); + var r3 = new PIXIPoint(rect.right, rect.bottom); + var r4 = new PIXIPoint(rect.left, rect.bottom); + var ret = new Array(); + var dist = this.Dist(lineFrom, lineTo); + var inter = this.LineSegmentIntersection(lineFrom, lineTo, r1, r2); + if (inter && this.PointInPIXIRectangle(inter, rect) && + this.Dist(inter, lineFrom) < dist && this.Dist(inter, lineTo) < dist) { + ret.push(inter); + } + inter = this.LineSegmentIntersection(lineFrom, lineTo, r2, r3); + if (inter && this.PointInPIXIRectangle(inter, rect) && + this.Dist(inter, lineFrom) < dist && this.Dist(inter, lineTo) < dist) { + ret.push(inter); + } + inter = this.LineSegmentIntersection(lineFrom, lineTo, r3, r4); + if (inter && this.PointInPIXIRectangle(inter, rect) && + this.Dist(inter, lineFrom) < dist && this.Dist(inter, lineTo) < dist) { + ret.push(inter); + } + inter = this.LineSegmentIntersection(lineFrom, lineTo, r4, r1); + if (inter && this.PointInPIXIRectangle(inter, rect) && + this.Dist(inter, lineFrom) < dist && this.Dist(inter, lineTo) < dist) { + ret.push(inter); + } + return ret; + } + + public static Intersection(rect1: PIXIRectangle, rect2: PIXIRectangle): PIXIRectangle { + const left = Math.max(rect1.x, rect2.x); + const right = Math.min(rect1.x + rect1.width, rect2.x + rect2.width); + const top = Math.max(rect1.y, rect2.y); + const bottom = Math.min(rect1.y + rect1.height, rect2.y + rect2.height); + return new PIXIRectangle(left, top, right - left, bottom - top); + } + + public static Dist(p1: PIXIPoint, p2: PIXIPoint): number { + return Math.sqrt(MathUtil.DistSquared(p1, p2)); + } + + public static Dot(p1: PIXIPoint, p2: PIXIPoint): number { + return p1.x * p2.x + p1.y * p2.y; + } + + public static Normalize(p1: PIXIPoint) { + var d = this.Length(p1); + return new PIXIPoint(p1.x / d, p1.y / d); + } + + public static Length(p1: PIXIPoint): number { + return Math.sqrt(p1.x * p1.x + p1.y * p1.y); + } + + public static DistSquared(p1: PIXIPoint, p2: PIXIPoint): number { + const a = p1.x - p2.x; + const b = p1.y - p2.y; + return (a * a + b * b); + } + + public static RectIntersectsRect(r1: PIXIRectangle, r2: PIXIRectangle): boolean { + return !(r2.x > r1.x + r1.width || + r2.x + r2.width < r1.x || + r2.y > r1.y + r1.height || + r2.y + r2.height < r1.y); + } + + public static ArgMin(temp: number[]): number { + let index = 0; + let value = temp[0]; + for (let i = 1; i < temp.length; i++) { + if (temp[i] < value) { + value = temp[i]; + index = i; + } + } + return index; + } + + public static ArgMax(temp: number[]): number { + let index = 0; + let value = temp[0]; + for (let i = 1; i < temp.length; i++) { + if (temp[i] > value) { + value = temp[i]; + index = i; + } + } + return index; + } + + public static Combinations(chars: T[]) { + let result = new Array(); + let f = (prefix: any, chars: any) => { + for (let i = 0; i < chars.length; i++) { + result.push(prefix.concat(chars[i])); + f(prefix.concat(chars[i]), chars.slice(i + 1)); + } + }; + f([], chars); + return result; + } +} \ No newline at end of file diff --git a/src/client/views/nodes/DataVizBox/HistogramBox.scss b/src/client/views/nodes/DataVizBox/HistogramBox.scss new file mode 100644 index 000000000..5aac9dc77 --- /dev/null +++ b/src/client/views/nodes/DataVizBox/HistogramBox.scss @@ -0,0 +1,18 @@ +// change the stroke color of line-svg class +.svgLine { + position: absolute; + background: darkGray; + stroke: #000; + stroke-width: 1px; + width:100%; + height:100%; + opacity: 0.4; +} + +.svgContainer { + position: absolute; + top:0; + left:0; + width:100%; + height: 100%; +} \ No newline at end of file diff --git a/src/client/views/nodes/DataVizBox/HistogramBox.tsx b/src/client/views/nodes/DataVizBox/HistogramBox.tsx new file mode 100644 index 000000000..00dc2ef46 --- /dev/null +++ b/src/client/views/nodes/DataVizBox/HistogramBox.tsx @@ -0,0 +1,159 @@ +import { action, computed, observable } from "mobx"; +import { observer } from "mobx-react"; +import * as React from "react"; +import { Doc } from "../../../../fields/Doc"; +import { NumCast } from "../../../../fields/Types"; +import "./HistogramBox.scss"; + +interface HistogramBoxProps { + rootDoc: Doc; + pairs: { + x: number, + y: number + }[] +} + + +export class HistogramBox extends React.Component { + + private origin = {x: 0.1 * this.width, y: 0.9 * this.height}; + + @computed get width() { + return NumCast(this.props.rootDoc.width); + } + + @computed get height() { + return NumCast(this.props.rootDoc.height); + } + + @computed get x() { + return NumCast(this.props.rootDoc.x); + } + + @computed get y() { + return NumCast(this.props.rootDoc.y); + } + + @computed get generatePoints() { + // evenly distribute points along the x axis + const xVals: number[] = this.props.pairs.map(p => p.x); + const yVals: number[] = this.props.pairs.map(p => p.y); + + const xMin = Math.min(...xVals); + const xMax = Math.max(...xVals); + const yMin = Math.min(...yVals); + const yMax = Math.max(...yVals); + + const xRange = xMax - xMin; + const yRange = yMax - yMin; + + const xScale = this.width / xRange; + const yScale = this.height / yRange; + + const xOffset = (this.x + (0.1 * this.width)) - xMin * xScale; + const yOffset = (this.y + (0.25 * this.height)) - yMin * yScale; + + const points: { + x: number, + y: number + }[] = this.props.pairs.map(p => { + return { + x: (p.x * xScale + xOffset) + this.origin.x, + y: (p.y * yScale + yOffset) + } + }); + + return points; + } + + @computed get generateGraphLine() { + const points = this.generatePoints; + // loop through points and create a line from each point to the next + let lines: { + x1: number, + y1: number, + x2: number, + y2: number + }[] = []; + for (let i = 0; i < points.length - 1; i++) { + lines.push({ + x1: points[i].x, + y1: points[i].y, + x2: points[i + 1].x, + y2: points[i + 1].y + }); + } + // generate array of svg with lines + let svgLines: JSX.Element[] = []; + for (let i = 0; i < lines.length; i++) { + svgLines.push( + + ); + } + + let res = []; + for (let i = 0; i < svgLines.length; i++) { + res.push({svgLines[i]}) + } + return res; + } + + @computed get generateAxes() { + + const xAxis = { + x1: 0.1 * this.width, + x2: 0.9 * this.width, + y1: 0.9 * this.height, + y2: 0.9 * this.height, + }; + + const yAxis = { + x1: 0.1 * this.width, + x2: 0.1 * this.width, + y1: 0.25 * this.height, + y2: 0.9 * this.height, + }; + + + return ( + [ + ( + {/* */} + + + {/* */} + ), + ( + + + {/* */} + ) + ] + ) + } + + + render() { + return ( +
histogram box + {/* + {this.generateSVGLine} + */} + {this.generateAxes[0]} + {this.generateAxes[1]} + {this.generateGraphLine.map(line => line)} +
+ ) + + } + +} \ No newline at end of file diff --git a/src/client/views/nodes/DataVizBox/TableBox.scss b/src/client/views/nodes/DataVizBox/TableBox.scss new file mode 100644 index 000000000..1264d6a46 --- /dev/null +++ b/src/client/views/nodes/DataVizBox/TableBox.scss @@ -0,0 +1,22 @@ +.table { + margin-top: 10px; + margin-bottom: 10px; + margin-left: 10px; + margin-right: 10px; +} + +.table-row { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + padding: 5px; + border-bottom: 1px solid #ccc; +} + +.table-container { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} \ No newline at end of file diff --git a/src/client/views/nodes/DataVizBox/TableBox.tsx b/src/client/views/nodes/DataVizBox/TableBox.tsx new file mode 100644 index 000000000..dfa8262d8 --- /dev/null +++ b/src/client/views/nodes/DataVizBox/TableBox.tsx @@ -0,0 +1,37 @@ +import { action, computed, observable } from "mobx"; +import { observer } from "mobx-react"; +import * as React from "react"; + +interface TableBoxProps { + pairs: {x: number, y:number}[] +} + + +export class TableBox extends React.Component { + + + + render() { + return ( +
+ + + + + + + + + {this.props.pairs.map(p => { + return ( + + + ) + })} + +
xy
{p.x}{p.y}
+
+ ) + } + +} \ No newline at end of file diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 371d85a32..96ac3e332 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -19,7 +19,7 @@ import { AudioBox } from "./AudioBox"; import { FontIconBox } from "./button/FontIconBox"; import { ColorBox } from "./ColorBox"; import { ComparisonBox } from "./ComparisonBox"; -import { DataVizBox } from "./DataViz"; +import { DataVizBox } from "./DataVizBox/DataVizBox"; import { DocumentViewProps } from "./DocumentView"; import "./DocumentView.scss"; import { EquationBox } from "./EquationBox"; -- cgit v1.2.3-70-g09d2 From ea6e63648b21c46672b1b7cb1da0cbaa6857d0c1 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 30 Jun 2022 11:01:46 -0400 Subject: fixed up some more initialization --- src/client/util/CurrentUserUtils.ts | 37 +++++++--------------- src/client/util/DropConverter.ts | 2 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 6 ++-- 3 files changed, 16 insertions(+), 29 deletions(-) (limited to 'src/client/views/nodes') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 2a0702a58..a39081d10 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -9,30 +9,25 @@ import { RichTextField } from "../../fields/RichTextField"; import { listSpec } from "../../fields/Schema"; import { ComputedField, ScriptField } from "../../fields/ScriptField"; import { Cast, DateCast, DocCast, FieldValue, NumCast, PromiseValue, ScriptCast, StrCast } from "../../fields/Types"; -import { ImageField, nullAudio } from "../../fields/URLField"; +import { nullAudio } from "../../fields/URLField"; import { SharingPermissions } from "../../fields/util"; import { OmitKeys, Utils } from "../../Utils"; import { DocServer } from "../DocServer"; import { Docs, DocumentOptions, DocUtils, FInfo } from "../documents/Documents"; import { DocumentType } from "../documents/DocumentTypes"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; -import { CollectionFreeFormView } from "../views/collections/collectionFreeForm"; import { TreeViewType } from "../views/collections/CollectionTreeView"; import { CollectionView, CollectionViewType } from "../views/collections/CollectionView"; import { TreeView } from "../views/collections/TreeView"; import { Colors } from "../views/global/globalEnums"; import { MainView } from "../views/MainView"; import { ButtonType, NumButtonType } from "../views/nodes/button/FontIconBox"; -import { CollectionFreeFormDocumentView } from "../views/nodes/CollectionFreeFormDocumentView"; -import { DocumentView } from "../views/nodes/DocumentView"; import { OverlayView } from "../views/OverlayView"; -import { DocumentManager } from "./DocumentManager"; import { DragManager } from "./DragManager"; -import { makeTemplate, MakeTemplate } from "./DropConverter"; +import { MakeTemplate } from "./DropConverter"; import { HistoryUtil } from "./History"; import { LinkManager } from "./LinkManager"; import { ScriptingGlobals } from "./ScriptingGlobals"; -import { SearchUtil } from "./SearchUtil"; import { SelectionManager } from "./SelectionManager"; import { ColorScheme } from "./SettingsManager"; import { SharingManager } from "./SharingManager"; @@ -149,11 +144,7 @@ export class CurrentUserUtils { } return templateBtn; }; - const makeTemp = (doc:Doc) => { - doc.isTemplateDoc = makeTemplate(doc); - return doc; - } - return this.AssignScripts(assignBtnAndTempOpts(tempBtn, btnOpts, templateOpts) ?? this.createToolButton( {...btnOpts, dragFactory: makeTemp(template(templateOpts))}), reqdScripts); + return this.AssignScripts(assignBtnAndTempOpts(tempBtn, btnOpts, templateOpts) ?? this.createToolButton( {...btnOpts, dragFactory: MakeTemplate(template(templateOpts))}), reqdScripts); }); const reqdOpts:DocumentOptions = { @@ -176,11 +167,7 @@ export class CurrentUserUtils { const reqdNoteList = reqdTempOpts.map(opts => { const reqdOpts = {...opts, title: "text", system: true}; const noteType = tempNotes ? DocListCast(tempNotes.data).find(doc => doc.noteType === opts.noteType): undefined; - const makeTemp = (doc:Doc, noteType?:string) => { - doc.isTemplateDoc = makeTemplate(doc, true, noteType??"Note"); - return doc; - } - return this.AssignOpts(noteType, reqdOpts) ?? makeTemp(Docs.Create.TextDocument("",reqdOpts), opts.noteType); + return this.AssignOpts(noteType, reqdOpts) ?? MakeTemplate(Docs.Create.TextDocument("",reqdOpts), true, opts.noteType??"Note"); }); const reqdOpts:DocumentOptions = { title: "Note Layouts", _height: 75, system: true }; @@ -280,8 +267,7 @@ export class CurrentUserUtils { // " " + // " " + // "
"; - Doc.GetProto(header).isTemplateDoc = makeTemplate(Doc.GetProto(header), true, "headerView"); - Doc.GetProto(header).title = "Untitled Header"; + MakeTemplate(Doc.GetProto(header), true, "Untitled Header"); return header; } const emptyThings:{key:string, // the field name where the empty thing will be stored @@ -705,7 +691,7 @@ export class CurrentUserUtils { { title: "Color", toolTip: "Font color", btnType: ButtonType.ColorButton, icon: "font", ignoreClick: true, scripts: {script: '{ return setFontColor(value, _readOnly_); }'}}, { title: "Bold", toolTip: "Bold (Ctrl+B)", btnType: ButtonType.ToggleButton, icon: "bold", scripts: {onClick: '{ return toggleBold(_readOnly_); }'} }, { title: "Italic", toolTip: "Italic (Ctrl+I)", btnType: ButtonType.ToggleButton, icon: "italic", scripts: {onClick: '{ return toggleItalic(_readOnly_);}'} }, - { title: "Under", toolTip: "Underline (Ctrl+U)", btnType: ButtonType.ToggleButton, icon: "underline", scripts: {onClick:'{ return toggleUnderline(_readOnly_);}'} }, + { title: "Under", toolTip: "Underline (Ctrl+U)", btnType: ButtonType.ToggleButton, icon: "underline", scripts: {onClick: '{ return toggleUnderline(_readOnly_);}'} }, { title: "Bullets", toolTip: "Bullet List", btnType: ButtonType.ToggleButton, icon: "list", scripts: {onClick: '{ return setBulletList("bullet", _readOnly_);}'} }, { title: "#", toolTip: "Number List", btnType: ButtonType.ToggleButton, icon: "list-ol", scripts: {onClick: '{ return setBulletList("decimal", _readOnly_);}'} }, @@ -797,10 +783,11 @@ export class CurrentUserUtils { const reqdSubMenuOpts = { ...OmitKeys(params, ["scripts", "funcs", "subMenu"]).omit, childDontRegisterViews: true, flexGap: 0, _height: 30, ignoreClick: true, linearViewSubMenu: true, linearViewExpandable: true, }; - return this.AssignScripts(this.AssignOpts(menuBtnDoc, reqdSubMenuOpts) ?? - (ctxtMenuBtnsDoc[StrCast(params.title)]= this.linearButtonList(reqdSubMenuOpts, params.subMenu.map(sub => - this.setupContextMenuButton(sub, DocListCast(menuBtnDoc?.data).find(doc => doc.title === sub.title)) - ))), undefined, params.funcs); + const items = params.subMenu?.map(sub => + this.setupContextMenuButton(sub, DocListCast(menuBtnDoc?.data).find(doc => doc.title === sub.title)) + ); + return this.AssignScripts( + this.AssignDocField(ctxtMenuBtnsDoc, StrCast(params.title), (opts) => this.linearButtonList(opts, items??[]), reqdSubMenuOpts, items), undefined, params.funcs); } }); return this.AssignOpts(ctxtMenuBtnsDoc, reqdCtxtOpts, ctxtMenuBtns); @@ -985,7 +972,7 @@ export class CurrentUserUtils { switch (options.fieldType) { case "boolean": opts.fieldValues = new List(options.values as any); break; case "number": opts.fieldValues = new List(options.values as any); break; - case "Doc": opts.fieldValues = new List(options.values as any); break; + case Doc.name: opts.fieldValues = new List(options.values as any); break; default: opts.fieldValues = new List(options.values as any); break;// string, pointerEvents, dimUnit, dropActionType } this.AssignDocField(infos, pair[0], opts => Doc.assign(new Doc(), OmitKeys(opts,["values"]).omit), opts); diff --git a/src/client/util/DropConverter.ts b/src/client/util/DropConverter.ts index 076afd3a0..256ab5c44 100644 --- a/src/client/util/DropConverter.ts +++ b/src/client/util/DropConverter.ts @@ -20,7 +20,7 @@ export function MakeTemplate(doc: Doc, first: boolean = true, rename: Opt = undefined): boolean { +function makeTemplate(doc: Doc, first: boolean = true, rename: Opt = undefined): boolean { const layoutDoc = doc.layout instanceof Doc && doc.layout.isTemplateForField ? doc.layout : doc; if (layoutDoc.layout instanceof Doc) { // its already a template return true; diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 9ae604e9b..8e1698eba 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -29,7 +29,7 @@ import { CurrentUserUtils } from '../../../util/CurrentUserUtils'; import { DictationManager } from '../../../util/DictationManager'; import { DocumentManager } from '../../../util/DocumentManager'; import { DragManager } from "../../../util/DragManager"; -import { makeTemplate } from '../../../util/DropConverter'; +import { MakeTemplate } from '../../../util/DropConverter'; import { LinkManager } from '../../../util/LinkManager'; import { SelectionManager } from "../../../util/SelectionManager"; import { SnappingManager } from '../../../util/SnappingManager'; @@ -682,7 +682,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp if (!this.layoutDoc.isTemplateDoc) { const title = StrCast(this.rootDoc.title); this.rootDoc.title = "text"; - this.rootDoc.isTemplateDoc = makeTemplate(this.rootDoc, true, title); + MakeTemplate(this.rootDoc, true, title); } else if (!this.rootDoc.isTemplateDoc) { const title = StrCast(this.rootDoc.title); this.rootDoc.title = "text"; @@ -691,7 +691,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp this.rootDoc.isTemplateDoc = false; this.rootDoc.isTemplateForField = ""; this.rootDoc.layoutKey = "layout"; - this.rootDoc.isTemplateDoc = makeTemplate(this.rootDoc, true, title); + MakeTemplate(this.rootDoc, true, title); setTimeout(() => { this.rootDoc._autoHeight = this.layoutDoc._autoHeight; // autoHeight, width and height this.rootDoc._width = this.layoutDoc._width || 300; // are stored on the template, since we're getting rid of the old template -- cgit v1.2.3-70-g09d2