Currently it considers non-integer values for Width/Height "invalid", which isn't good for Cm/Inches.
Plus, it looks very aggressive, and validation in Windows 98 is normally done with dialogs on submit.
I had put this off for a long time because I wanted to get it exactly correct, but some is better than none!
And some dialogs are custom anyways, so there's no "right" answer.
It needs label to be a sibling of the radio, to do the styling of the radio buttons using a pseudo element on the label.
Unfortunately, it doesn't just not style radios that aren't in the right structure, it makes them invisible. I think this could be fixed by resetting styles for `label input[type=radio]` (todo)
This is not ideal. There are surely race conditions where it can still end up with the document overwritten, and if you hit Cancel after saying Save, ditto.
Ideally it should not be able to overwrite the session while loading in the first place!
I guess that wouldn't be too hard...
This also improves the dialog around saving without a file extension, or with the wrong file extension, which is also part of improving the safety (in this less than ideal scheme).
It shouldn't cancel the whole selection manipulation if you pan; you should be able to pan/zoom to position the selection exactly how you want it, ideally.
I struggled with the pinch zooming for a while because, despite testing that `from_canvas_coords(to_canvas_coords({clientX: 50, clientY: 50}))` works correctly (and at different zoom levels etc.), `to_canvas_coords({x: anything, y: anything})` was unbeknownst to me giving `{x: 0, y: 0}`
I really need a type checker.
Today I learned: ~~(NaN) === 0
Don't hold a last scroll state. This is important for changing how the pinch zooming works, to have it independent.
But the zooming code was tied into the panning code, and is now (more) broken.
I remembered I had implemented pinch zooming fairly nicely in another project: https://github.com/1j01/janitorial-android
It checks for a threshold of distance change before zooming in or out, which has the nice effect that there's no near-boundary pinch levels/distances where it can oscillate more easily; as soon as you cross a boundary to a new zoom level, you have to go the whole threshold back, which makes it much more stable.
It's also flexible in that I was able to define a set of zoom levels, which don't have to be evenly spaced, although it'd be nice to adjust the threshold between them too, maybe just to match mathematically in a logarithmic way, but potentially I could just include thresholds along with the zoom levels list, that'd be pretty simple to do if I wanted fine grained control.
I haven't included a list of zoom levels here, but it's an option.