feat: Add an options panel

Right now it just controls debugging options for what gets logged to the
  console during execution. But at some point we should add on/off switches
  for the two main facilities.

  Also implements just enough additional commands to successfully render
  the very first illustration in Joyce's Euclid, namely Book 1, Def I.2.
This commit is contained in:
Glen Whitney 2023-10-04 23:05:39 -07:00
parent 58469f793e
commit 92308d2197
7 changed files with 107 additions and 17 deletions

View File

@ -15,8 +15,12 @@
"js": ["adapptext.js"], "js": ["adapptext.js"],
"run_at": "document_start" "run_at": "document_start"
} }
], ],
"web_accessible_resources": [{ "options_ui": {
"page": "options.html",
"browser_style": false
},
"web_accessible_resources": [{
"matches": ["<all_urls>"], "matches": ["<all_urls>"],
"resources": [ "resources": [
"deps/x_ite/x_ite.mjs", "deps/x_ite/x_ite.mjs",
@ -24,6 +28,8 @@
"deps/x_ite/assets/components/Scripting.js", "deps/x_ite/assets/components/Scripting.js",
"deps/x_ite/assets/components/Text.js", "deps/x_ite/assets/components/Text.js",
"adapptlet.js", "adapptlet.js",
"adapptypes.js",
"options.js",
"deps/GeoGebra/deployggb.js", "deps/GeoGebra/deployggb.js",
"deps/GeoGebra/HTML5/5.0/webSimple/5F2C6F84737382D2A3B062804F6250CE.cache.js", "deps/GeoGebra/HTML5/5.0/webSimple/5F2C6F84737382D2A3B062804F6250CE.cache.js",
"deps/GeoGebra/HTML5/5.0/webSimple/webSimple.nocache.js", "deps/GeoGebra/HTML5/5.0/webSimple/webSimple.nocache.js",
@ -31,6 +37,6 @@
"deps/GeoGebra/HTML5/5.0/webSimple/deferredjs/*", "deps/GeoGebra/HTML5/5.0/webSimple/deferredjs/*",
"deps/GeoGebra/HTML5/5.0/css/bundles/simple-bundle.css" "deps/GeoGebra/HTML5/5.0/css/bundles/simple-bundle.css"
] ]
}], }],
"permissions": ["tabs", "scripting"] "permissions": ["storage"]
} }

19
etc/options.html Normal file
View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<h3>Debugging</h3>
Trace the following to the JavaScript console:
<h4>Java Geometry Applets</h4>
<label for="commands">Commands executed</label>
<input type="checkbox" id="commands">
<label for="color">Colors assigned</label>
<input type="checkbox" id="color">
<script src="options.js" type="module"></script>
</body>
</html>

View File

@ -1,4 +1,4 @@
import {AppletDescription, AdapParams, params} from ./adapptypes.ts {AppletDescription, AdapParams, params, flags, ConfigType} from ./adapptypes.ts
// (At least some of) Joyce's pages have inline scripts that remove their // (At least some of) Joyce's pages have inline scripts that remove their
// own applet nodes, so we have to watch for them as they are added. Hence, // own applet nodes, so we have to watch for them as they are added. Hence,
@ -37,11 +37,13 @@ function addScriptTag(url: string, module = false)
if module then script.type = 'module' if module then script.type = 'module'
document.head.appendChild script document.head.appendChild script
document.addEventListener "DOMContentLoaded", => document.addEventListener "DOMContentLoaded", async =>
finalJoyceApplet := document.querySelector "applet[code='Geometry']" finalJoyceApplet := document.querySelector "applet[code='Geometry']"
if joyceApplets.length or finalJoyceApplet if joyceApplets.length or finalJoyceApplet
config := await browser.storage.local.get(flags) as ConfigType
adapParams: AdapParams := { adapParams: AdapParams := {
codebase: browser.runtime.getURL('deps/GeoGebra/HTML5/5.0/webSimple'), codebase: browser.runtime.getURL('deps/GeoGebra/HTML5/5.0/webSimple'),
config,
joyceApplets } joyceApplets }
// @ts-ignore // @ts-ignore
window.wrappedJSObject.adapParams = cloneInto(adapParams, window) window.wrappedJSObject.adapParams = cloneInto(adapParams, window)

View File

@ -114,10 +114,15 @@ function dispatchJcommand(
switch name switch name
'background' 'background'
newback := joyce2rgb value, backgroundRGB newback := joyce2rgb value, backgroundRGB
if adapParams.config?.commands
console.log 'Setting background to', value, 'interpreted as',
newback
for i of [0..2] for i of [0..2]
backgroundRGB[i] = newback[i] backgroundRGB[i] = newback[i]
api.setGraphicsOptions 1, bgColor: colorsea(backgroundRGB).hex() api.setGraphicsOptions 1, bgColor: colorsea(backgroundRGB).hex()
'title' 'title'
if adapParams.config?.commands
console.log 'Setting title to', value
api.evalCommand `TitlePoint = Corner(1,1) api.evalCommand `TitlePoint = Corner(1,1)
Text("${value}", TitlePoint + (2,5))` Text("${value}", TitlePoint + (2,5))`
/e\[\d+\]/ /e\[\d+\]/
@ -144,6 +149,9 @@ function jToG(
index: number, index: number,
backgroundRGB: RGB): Commander backgroundRGB: RGB): Commander
[jname, klass, method, data, ...colors] := jCom.split ';' [jname, klass, method, data, ...colors] := jCom.split ';'
if adapParams.config?.commands
console.log 'Defining', jname, 'as a', klass, 'constructed by',
method, 'from', data, 'colored as', colors
cmdr .= freshCommander() cmdr .= freshCommander()
unless klass in classHandler unless klass in classHandler
console.warn `Unknown entity class ${klass}` console.warn `Unknown entity class ${klass}`
@ -182,7 +190,7 @@ function jToG(
else // we have to decorate else // we have to decorate
dimension .= cmdr.parts.findLastIndex .includes name dimension .= cmdr.parts.findLastIndex .includes name
cmdr.callbacks.push (api: AppletObject, parts: DimParts) => cmdr.callbacks.push (api: AppletObject, parts: DimParts) =>
trace := false // e.g., klass is 'polygon' trace := adapParams.config?.color
// Operate in order faces, lines, point, caption so that // Operate in order faces, lines, point, caption so that
// we can adjust components after setting overall color, etc. // we can adjust components after setting overall color, etc.
@ -209,7 +217,7 @@ function jToG(
// Lines default to black: // Lines default to black:
if invisible colors[2] if invisible colors[2]
for each line of parts[1] for each line of parts[1]
unless line in elements if line is name or line not in elements
console.log 'Hiding line', line if trace console.log 'Hiding line', line if trace
api.setVisible line, false api.setVisible line, false
else else
@ -220,11 +228,12 @@ function jToG(
api.setColor line, ...lineRGB api.setColor line, ...lineRGB
// Now color the points: // Now color the points:
console.log 'Considering point colors for', name if trace
if invisible colors[1] if invisible colors[1]
// Hide all the dim-0 elements that are not their own independent // Hide all the dim-0 elements that are not distinct independent
// items: // items:
for each point of parts[0] for each point of parts[0]
unless point in elements if point is name or point not in elements
console.log 'Hiding point', point if trace console.log 'Hiding point', point if trace
api.setVisible point, false api.setVisible point, false
else if dimension is 0 or colors[1] // Need to color the points else if dimension is 0 or colors[1] // Need to color the points
@ -492,8 +501,7 @@ classHandler: Record<JoyceClass, ClassHandler> :=
auxiliaries.push ...[1..4].map (n) => aux + n auxiliaries.push ...[1..4].map (n) => aux + n
unless madeSegment unless madeSegment
commands.push `${name} = Segment(${ends[0]},${ends[1]})` commands.push `${name} = Segment(${ends[0]},${ends[1]})`
callbacks.push (api: AppletObject) => callbacks.push (api: AppletObject) => api.setLabelVisible name, true
api.setLabelVisible name, true
parts[0].push ...ends parts[0].push ...ends
circle: (name, method, args) => circle: (name, method, args) =>
@ -529,9 +537,9 @@ classHandler: Record<JoyceClass, ClassHandler> :=
api.renameObject obj, newObj api.renameObject obj, newObj
switch api.getObjectType newObj switch api.getObjectType newObj
'segment' 'segment'
parts[1].push newObj moreParts[1].push newObj
'point' 'point'
parts[0].push newObj moreParts[0].push newObj
api.setVisible newObj, false api.setVisible newObj, false
/triangle|quadrilateral/ /triangle|quadrilateral/
pt := args.subpoints pt := args.subpoints
@ -546,9 +554,42 @@ classHandler: Record<JoyceClass, ClassHandler> :=
if obj is name continue if obj is name continue
newObj := 'GeoAux' + index + obj newObj := 'GeoAux' + index + obj
api.renameObject obj, newObj api.renameObject obj, newObj
parts[1].push newObj moreParts[1].push newObj
sector: (name, method, args, index) =>
return := freshCommander()
return.value.ends = ['', '']
{commands, callbacks, parts, auxiliaries, ends} := return.value
aux := name + 'aUx'
parts[2].push name
switch method
'sector'
unless args.subpoints?.length is 3 return
parts[0].push ...args.subpoints
[center, end, start] := args.subpoints
ends[0] = start
ends[1] = end
parms := center + ', ' + start + ', ' + end
commands.push
`${name} = CircularSector(${parms})`
`${aux}1 = CircularArc(${parms})`
parts[1].push aux + 1
callbacks.push (api: AppletObject) =>
api.setLineThickness name, 1
// The rest of this function is a weird roundabout way to make
// the lines of the sector have zero opacity.
// I got it from
// https://www.reddit.com/r/geogebra/comments/12cbr85/setlineopacity_command/
// I don't really understand how/why it works, but it seems to
// So that's good enough for me
xml := api.getXML name
xml.replace(/opacity="\d+"/, 'opacity="0"')
api.evalXML(xml)
// This last step is especially confusing... I think
// evaluating the modified XML created a sort of second
// copy of the entity, and so we have to hide the original one
api.setVisible name, false
sector: (name, method, args) => freshCommander()
plane: (name, method, args) => freshCommander() plane: (name, method, args) => freshCommander()
sphere: (name, method, args) => freshCommander() sphere: (name, method, args) => freshCommander()
polyhedron: (name, method, args) => freshCommander() polyhedron: (name, method, args) => freshCommander()

View File

@ -1,3 +1,7 @@
export const flags = ['commands', 'color'] as const
export type FlagType = (typeof flags)[number]
export type ConfigType = Partial<Record<FlagType, boolean>>
export type AppletDescription export type AppletDescription
html: string html: string
params: Record<string, string> params: Record<string, string>
@ -8,6 +12,7 @@ export type AppletDescription
export type AdapParams export type AdapParams
codebase?: string codebase?: string
loader?: string loader?: string
config?: ConfigType
joyceApplets: AppletDescription[] joyceApplets: AppletDescription[]
export function params(kids: HTMLCollection): Record<string, string> export function params(kids: HTMLCollection): Record<string, string>

16
src/options.civet Normal file
View File

@ -0,0 +1,16 @@
import {flags} from ./adapptypes.ts
console.log('arrived')
boxes := ['commands', 'color']
cache := await browser.storage.local.get boxes
console.log('Found', cache)
for each box of boxes
checkbox := document.getElementById(box) as HTMLInputElement
unless checkbox then continue
checkbox.checked = cache[box] ?? false
document.body.addEventListener 'click', (event) ->
elt := event.target as HTMLInputElement
unless elt.tagName is 'INPUT' and elt.type is 'checkbox' then return
browser.storage.local.set [elt.id]: elt.checked

View File

@ -1,7 +1,7 @@
# Takes one parameter, the destination directory # Takes one parameter, the destination directory
mkdir -p $1/deps/x_ite/assets/images mkdir -p $1/deps/x_ite/assets/images
mkdir -p $1/deps/x_ite/assets/components mkdir -p $1/deps/x_ite/assets/components
cp etc/manifest.json $1 cp etc/manifest.json etc/options.html $1
cp etc/deps/x_ite/x_ite.css $1/deps/x_ite cp etc/deps/x_ite/x_ite.css $1/deps/x_ite
cp etc/deps/x_ite/assets/images/logo.128.png $1/deps/x_ite/assets/images cp etc/deps/x_ite/assets/images/logo.128.png $1/deps/x_ite/assets/images
cp etc/deps/x_ite/x_ite.mjs $1/deps/x_ite cp etc/deps/x_ite/x_ite.mjs $1/deps/x_ite
@ -10,3 +10,4 @@ cp -r etc/deps/GeoGebra $1/deps
npx rollup public/js/giveAwrl.js --dir extension npx rollup public/js/giveAwrl.js --dir extension
npx rollup public/js/adapptlet.js --file extension/adapptlet.js npx rollup public/js/adapptlet.js --file extension/adapptlet.js
npx rollup public/js/adapptext.js --file extension/adapptext.js npx rollup public/js/adapptext.js --file extension/adapptext.js
cp public/js/options.js public/js/adapptypes.js extension