From a6e5fdd00fa4f8adcc67d709e95391d3ccaaaf52 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 3 Mar 2021 10:32:12 -0500 Subject: added functionPlot. trying to make fitWidth make sense everywhere (lightbox, stacking panels with autosize columns, etc). --- src/client/views/nodes/DocumentContentsView.tsx | 3 +- src/client/views/nodes/DocumentView.tsx | 17 +++--- src/client/views/nodes/EquationBox.tsx | 39 +++++++++---- src/client/views/nodes/FunctionPlotBox.scss | 0 src/client/views/nodes/FunctionPlotBox.tsx | 76 +++++++++++++++++++++++++ 5 files changed, 112 insertions(+), 23 deletions(-) create mode 100644 src/client/views/nodes/FunctionPlotBox.scss create mode 100644 src/client/views/nodes/FunctionPlotBox.tsx (limited to 'src/client/views/nodes') diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 02c112745..32542d056 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -12,6 +12,7 @@ import { YoutubeBox } from "./../../apis/youtube/YoutubeBox"; import { AudioBox } from "./AudioBox"; import { LabelBox } from "./LabelBox"; import { EquationBox } from "./EquationBox"; +import { FunctionPlotBox } from "./FunctionPlotBox"; import { SliderBox } from "./SliderBox"; import { LinkBox } from "./LinkBox"; import { ScriptingBox } from "./ScriptingBox"; @@ -223,7 +224,7 @@ export class DocumentContentsView extends React.Component { return this.docView?._componentView?.reverseNativeScaling?.() ? 0 : returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, this.props.freezeDimensions)); } - shouldNotScale = () => this.layoutDoc._fitWidth || [CollectionViewType.Docking, CollectionViewType.Tree].includes(this.Document._viewType as any); - @computed get effectiveNativeWidth() { return this.nativeWidth || (this.shouldNotScale() ? 0 : NumCast(this.layoutDoc.width)); } - @computed get effectiveNativeHeight() { return this.nativeHeight || (this.shouldNotScale() ? 0 : NumCast(this.layoutDoc.height)); } + shouldNotScale = () => (this.layoutDoc._fitWidth && !this.nativeWidth) || [CollectionViewType.Docking, CollectionViewType.Tree].includes(this.Document._viewType as any); + @computed get effectiveNativeWidth() { return this.shouldNotScale() ? 0 : (this.nativeWidth || NumCast(this.layoutDoc.width)); } + @computed get effectiveNativeHeight() { return this.shouldNotScale() ? 0 : (this.nativeHeight || NumCast(this.layoutDoc.height)); } @computed get nativeScaling() { + if (this.shouldNotScale()) return 1; const minTextScale = this.Document.type === DocumentType.RTF ? 0.1 : 0; - if (this.effectiveNativeWidth && (this.layoutDoc?._fitWidth || this.props.PanelHeight() / this.effectiveNativeHeight > this.props.PanelWidth() / this.effectiveNativeWidth)) { + if (this.props.PanelHeight() / this.effectiveNativeHeight > this.props.PanelWidth() / this.effectiveNativeWidth) { return Math.max(minTextScale, this.props.PanelWidth() / this.effectiveNativeWidth); // width-limited or fitWidth } - return this.effectiveNativeWidth && this.effectiveNativeHeight ? Math.max(minTextScale, this.props.PanelHeight() / this.effectiveNativeHeight) : 1; // height-limited or unscaled + return Math.max(minTextScale, this.props.PanelHeight() / this.effectiveNativeHeight); // height-limited or unscaled } @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(), - this.props.Document._fitWidth ? - Math.max(NumCast(this.props.Document._height), NumCast(((this.props.Document.scrollHeight || 0) as number) * this.props.PanelWidth() / this.effectiveNativeWidth, this.props.PanelHeight())) : - this.effectiveNativeHeight * this.nativeScaling - ); + return Math.min(this.props.PanelHeight(), Math.max(NumCast(this.layoutDoc.scrollHeight), this.effectiveNativeHeight) * this.nativeScaling); } return this.props.PanelHeight(); } diff --git a/src/client/views/nodes/EquationBox.tsx b/src/client/views/nodes/EquationBox.tsx index 5bc73d5d9..5bb904f91 100644 --- a/src/client/views/nodes/EquationBox.tsx +++ b/src/client/views/nodes/EquationBox.tsx @@ -1,18 +1,22 @@ import EquationEditor from 'equation-editor-react'; +import { action, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { documentSchema } from '../../../fields/documentSchemas'; -import { createSchema, makeInterface } from '../../../fields/Schema'; -import { StrCast, NumCast } from '../../../fields/Types'; -import { ViewBoxBaseComponent } from '../DocComponent'; -import { FieldView, FieldViewProps } from './FieldView'; -import './LabelBox.scss'; import { Id } from '../../../fields/FieldSymbols'; -import { simulateMouseClick } from '../../../Utils'; +import { createSchema, makeInterface } from '../../../fields/Schema'; +import { NumCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { reaction, action } from 'mobx'; import { Docs } from '../../documents/Documents'; +import { ViewBoxBaseComponent } from '../DocComponent'; import { LightboxView } from '../LightboxView'; +import { FieldView, FieldViewProps } from './FieldView'; +import './LabelBox.scss'; +import functionPlot from "function-plot"; +import { DocumentManager } from '../../util/DocumentManager'; +import { Utils } from '../../../Utils'; +import { HeightSym, WidthSym } from '../../../fields/Doc'; + const EquationSchema = createSchema({}); @@ -39,18 +43,29 @@ export class EquationBox extends ViewBoxBaseComponent { const _height = Number(getComputedStyle(this._ref.current!.element.current).height.replace("px", "")); const _width = Number(getComputedStyle(this._ref.current!.element.current).width.replace("px", "")); - if (e.key === "Enter" || e.key === "Tab") { + if (e.key === "Enter") { const nextEq = Docs.Create.EquationDocument({ title: "# math", text: StrCast(this.dataDoc.text), _width, _height: 25, - x: NumCast(this.layoutDoc.x) + (e.key === "Tab" ? _width + 10 : 0), y: NumCast(this.layoutDoc.y) + (e.key === "Enter" ? _height + 10 : 0) + x: NumCast(this.layoutDoc.x), y: NumCast(this.layoutDoc.y) + _height + 10 }); EquationBox.SelectOnLoad = nextEq[Id]; this.props.addDocument?.(nextEq); e.stopPropagation(); + + } + if (e.key === "Tab") { + const graph = Docs.Create.FunctionPlotDocument([this.rootDoc], { + x: NumCast(this.layoutDoc.x) + this.layoutDoc[WidthSym](), + y: NumCast(this.layoutDoc.y), + _width: 400, _height: 300, _backgroundColor: "white" + }); + this.props.addDocument?.(graph); + e.stopPropagation(); } if (e.key === "Backspace" && !this.dataDoc.text) this.props.removeDocument?.(this.rootDoc); } @@ -72,11 +87,11 @@ export class EquationBox extends ViewBoxBaseComponent - ); + autoOperatorNames="sin cos tan" /> + ); } } \ No newline at end of file diff --git a/src/client/views/nodes/FunctionPlotBox.scss b/src/client/views/nodes/FunctionPlotBox.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/client/views/nodes/FunctionPlotBox.tsx b/src/client/views/nodes/FunctionPlotBox.tsx new file mode 100644 index 000000000..dba08b506 --- /dev/null +++ b/src/client/views/nodes/FunctionPlotBox.tsx @@ -0,0 +1,76 @@ +import EquationEditor from 'equation-editor-react'; +import functionPlot from "function-plot"; +import { observer } from 'mobx-react'; +import * as React from 'react'; +import { documentSchema } from '../../../fields/documentSchemas'; +import { createSchema, makeInterface } from '../../../fields/Schema'; +import { StrCast } from '../../../fields/Types'; +import { TraceMobx } from '../../../fields/util'; +import { ViewBoxBaseComponent } from '../DocComponent'; +import { FieldView, FieldViewProps } from './FieldView'; +import './LabelBox.scss'; +import { DocListCast } from '../../../fields/Doc'; +import { computed } from 'mobx'; + + +const EquationSchema = createSchema({}); + +type EquationDocument = makeInterface<[typeof EquationSchema, typeof documentSchema]>; +const EquationDocument = makeInterface(EquationSchema, documentSchema); + +@observer +export class FunctionPlotBox extends ViewBoxBaseComponent(EquationDocument) { + public static LayoutString(fieldKey: string) { return FieldView.LayoutString(FunctionPlotBox, fieldKey); } + public static GraphCount = 0; + _ref: React.RefObject = React.createRef(); + _plot: any; + _plotId = ""; + constructor(props: any) { + super(props); + this._plotId = "graph" + FunctionPlotBox.GraphCount++; + } + createGraph = (ele: HTMLDivElement) => { + let width = this.props.PanelWidth(); + let height = this.props.PanelHeight(); + const fn = StrCast(DocListCast(this.dataDoc.data).lastElement()?.text, "x^2").replace(/\\frac\{(.*)\}\{(.*)\}/, "($1/$2)"); + console.log("Graphing:" + fn); + try { + this._plot = functionPlot({ + target: "#" + ele.id, + width, + height, + yAxis: { domain: [-1, 9] }, + grid: true, + data: [ + { + fn, + // derivative: { fn: "2 * x", updateOnMouseMove: true } + } + ] + }); + } catch (e) { + console.log(e); + } + } + @computed get theGraph() { + const fn = StrCast(DocListCast(this.dataDoc.data).lastElement()?.text, "x^2"); + return
r && this.createGraph(r)} style={{ position: "absolute", width: "100%", height: "100%" }} + onPointerDown={e => e.stopPropagation()} />; + } + render() { + TraceMobx(); + return (
+ {this.theGraph} +
+
); + } +} \ No newline at end of file -- cgit v1.2.3-70-g09d2