Skip to content

Commit

Permalink
configurable shape types, introduce react-mathquill
Browse files Browse the repository at this point in the history
  • Loading branch information
ryan-williams committed Oct 4, 2023
1 parent b73f033 commit 8a5088e
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 24 deletions.
15 changes: 15 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"react": "^18.2.0",
"react-bootstrap": "^2.8.0",
"react-dom": "^18.0.0",
"react-mathquill": "^1.0.3",
"react-plotly.js": "^2.6.0",
"react-resizable": "^3.0.5",
"react-scroll-wheel-handler": "^2.2.0",
Expand Down
14 changes: 13 additions & 1 deletion pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1558,7 +1558,19 @@ export function Body() {
toggle={setShapesShown}
tooltip={"\"Wide\" version of the \"Vars\" table above. View shapes' dimensions/coordinates, copy to clipboard"}
>
{vars && <ShapesTable sets={sets || []} vars={vars}/>}
{
vars &&
<ShapesTable
sets={sets || []}
setShape={(idx, shape) => {
if (!shapes) return
const newShapes = shapes.map((s, i) => i == idx ? shape : s)
setInitialShapes(newShapes)
setUrlFragmentShapes({ shapes: newShapes, precisionSchemeId: urlShapesPrecisionScheme })
}}
vars={vars}
/>
}
<div>
Copy as{' '}
<CopyLayout label={"JS"} shapesTextFn={() => shapesStr(shapeStrJS)} />,{' '}
Expand Down
10 changes: 10 additions & 0 deletions src/components/tables/shapes.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,14 @@
td.skipped {
background-color: #ddd;
}
td.varCell {
min-width: 4em;
max-width: 4em;
overflow: hidden;
}
th {
.math {
font-weight: bold;
}
}
}
75 changes: 62 additions & 13 deletions src/components/tables/shapes.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,64 @@
import {getRadii, mapShape, S} from "../../lib/shape";
import {getRadii, mapShape, S, Shape} from "../../lib/shape";
import React, {ReactNode} from "react";
import {Vars} from "../../lib/vars";
import css from "./shapes.module.scss"
import OverlayTrigger from "react-bootstrap/OverlayTrigger";
import Tooltip from "react-bootstrap/Tooltip";
import dynamic from "next/dynamic";
import {sqrt} from "../../lib/math";
const StaticMathField = dynamic(() => import("react-mathquill").then(m => { m.addStyles(); return m.StaticMathField }), { ssr: false })

export type Props = {
sets: S[]
setShape: (idx: number, shape: Shape<number>) => void
vars: Vars
precision?: number
}

export function VarCell({ skipped, children }: { skipped: boolean, children: ReactNode }) {
export function VarCell({ skipped, className, children }: { skipped: boolean, className?: string, children: ReactNode }) {
className = (className || css.varCell) + ` ${skipped ? css.skipped : ''}`
return (
skipped
? <OverlayTrigger overlay={<Tooltip>Fixed/disabled</Tooltip>}>
<td className={css.skipped}>
<td className={className}>
<span>{children}</span>
</td>
</OverlayTrigger>
: <td>{children}</td>
: <td className={className}>{children}</td>
)
}

export function ShapesTable({ sets, vars, precision = 4 }: Props) {
export function Math({ children }: { children: string }) {
return <StaticMathField className={css.math}>{children}</StaticMathField>
}
export function ShapesTable({ sets, setShape, vars, precision = 4 }: Props) {
const hasDoubleRadii = sets.some(({shape}) => shape.kind === "XYRR" || shape.kind === "XYRRT")
const hasXYRRT = sets.some(({shape}) => shape.kind === "XYRRT")
return (
<table className={css.shapesTable}>
<thead>
<tr>
<th>Name</th>
<th>x</th>
<th>y</th>
<th>rx</th>
<th>ry</th>
<th>Type</th>
<th><Math>c_x</Math></th>
<th><Math>c_y</Math></th>
{
hasDoubleRadii
? <>
<th><Math>r_x</Math></th>
<th><Math>r_y</Math></th>
</>
: <th><Math>r</Math></th>
}
{
hasXYRRT ? <th><Math>\theta</Math></th> : null
}
<th>
<OverlayTrigger
overlay={<Tooltip>Circle, XYRR (aligned ellipse), or XYRRT (unaligned ellipse)</Tooltip>}
>
<span>Type</span>
</OverlayTrigger>
</th>
</tr>
</thead>
<tbody>{
Expand All @@ -50,15 +75,39 @@ export function ShapesTable({ sets, vars, precision = 4 }: Props) {
return [skip, skip]
},
e => [ skippedVars.includes("rx"), skippedVars.includes("ry") ],
e => [ skippedVars.includes("rx"), skippedVars.includes("ry") ],
)
return <tr key={idx}>
<td style={{ textAlign: "right", }}>{name}</td>
<VarCell skipped={skipCx}>{c.x.toPrecision(precision)}</VarCell>
<VarCell skipped={skipCy}>{c.y.toPrecision(precision)}</VarCell>
<VarCell skipped={skipRx}>{ rx.toPrecision(precision)}</VarCell>
<VarCell skipped={skipRy}>{ ry.toPrecision(precision)}</VarCell>
<td>{shape.kind}</td>
{ hasDoubleRadii && <VarCell skipped={skipRy}>{ ry.toPrecision(precision)}</VarCell> }
{
hasXYRRT &&
<VarCell skipped={skippedVars.includes("t")}>{
mapShape(
shape,
() => "",
() => "",
e => e.t.toPrecision(precision)
)
}</VarCell>
}
<td>
<select value={shape.kind} onChange={e => {
if (e.target.value === shape.kind) return
const r = { x: rx, y: ry }
switch (e.target.value) {
case "Circle": setShape(idx, { kind: "Circle", c, r: sqrt(rx * ry) }); break
case "XYRR": setShape(idx, { kind: "XYRR", c, r }); break
case "XYRRT": setShape(idx, { kind: "XYRRT", c, r, t: 0 }); break
}
}}>
<option value={"Circle"}>Circle</option>
<option value={"XYRR"}>XYRR</option>
<option value={"XYRRT"}>XYRRT</option>
</select>
</td>
</tr>
})
}</tbody>
Expand Down
21 changes: 11 additions & 10 deletions src/lib/shape.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,24 +52,25 @@ export function level(xyrrt: XYRRT<number>): XYRR<number> {
}
}

export const getRadii = <D>(s: Shape<D>): [D, D] => {
switch (s.kind) {
case 'Circle': return [s.r, s.r]
case 'XYRR': return [s.r.x, s.r.y]
case 'XYRRT': return [s.r.x, s.r.y]
}
}
export const getRadii = <D>(s: Shape<D>): [D, D] => mapShape(
s,
({ r }) => [r, r],
({ r }) => [r.x, r.y],
)

export function mapShape<D, O>(
s: Shape<D>,
circleFn: (c: Circle<D>) => O,
xyrrFn: (e: XYRR<D>) => O,
xyrrtFn: (e: XYRRT<D>) => O,
xyrrtFn?: (e: XYRRT<D>) => O,
): O {
switch (s.kind) {
case 'Circle': return circleFn(s)
case 'XYRR': return xyrrFn(s)
case 'XYRRT': return xyrrtFn(s)
case 'XYRRT':
if (xyrrtFn) return xyrrtFn(s)
const { c, r } = s
return xyrrFn({ kind: "XYRR", c, r })
}
}

Expand Down Expand Up @@ -133,7 +134,7 @@ export function shapesParam(opts: Opts = {}): Param<ShapesParam | null> {
// console.log("decode shapes:", v)
if (!v) return null
const buf = ShapesBuffer.fromB64(v, opts)
const end = buf.end
// const end = buf.end
buf.seek(0)
// console.log("end:", end)
return buf.decodeShapes()
Expand Down

0 comments on commit 8a5088e

Please sign in to comment.