Opening a sheet on a device rebuilds the DOM, so every element is new and
the history, which matched by identity, pruned each sheet as soon as it was
recorded. On a device entries now match by id, and Back reopens a view on
the current element rather than the snapshot it was recorded with.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ctrl+click picks out several boxes on the sheet, and Ctrl/Shift+click several
rows in the tree. Copies are named on from their original (Add1 -> Add2), sit
one step right and down, and keep the links that ran between the copied
components. One undo step; on a device the originals are read back in full
and the copies made there.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A palette drag dropped on a tree row adds the component inside that row's
component, placed under its lowest child. The row under the pointer is
highlighted, and resting on a collapsed branch opens it, loading it from
the device when live without moving the selection or the open sheet.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The chosen kit is remembered in editor.properties [Palette]; a file without it
opens on its first kit. Saving preferences now keeps the other sections.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Redo is gone in both file and device mode: the Edit menu entry, Ctrl/Cmd+Y
and Ctrl/Cmd+Shift+Z, and the redo stack. An undone step is dropped.
Undoing past the last save now leaves the saved depth unreachable, so a
new edit cannot be mistaken for the saved state.
Renames on a device are undoable: LiveRenameCommand renames back on the
device first, and warns and clears history if the device refuses.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Right-clicking a tree row selects it, and on a device that reopens the
sheet and rebuilds the DOM after the popup captured the row's element.
Delete then ran on a stale element: the device delete went through but
no undo step was recorded. Popup actions now look the component up by
id when they run.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Uses LiveComponentCommand, so undoing a delete puts the user back on
the device with its exact cred, perm and prov.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Undo and redo now work against a connected device; each step is sent
there through Sox. Deleting a component first reads its whole subtree
back (config, unloaded children, links, place among siblings) so undo
can recreate it; recreated components take new device ids, which the
DOM elements pick up so later steps still reach them. Binary Buf
config (a user's cred) is read with read_prop, since the cache decodes
every Buf as a Str. Moves, tidy layout, and Properties / page editor /
user edits record only what the device accepted.
A step that does not fully reach the device warns and clears the
history. History is also cleared on every view change in live mode,
as opening a sheet rebuilds the DOM from the device.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The final vertical run into an input slot now stands at least
1.5 * GRID_SIZE in front of the box, so the arrowhead sits on a straight
run instead of on the bend. Column gaps in tidy layout widen to match.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rebuilding the tree (live child loads, edits) now restores every row that
was expanded, matched by component id or name path. Double-click no longer
toggles a row through ttk's default binding.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Tested on a P-ION (fw 1.32) at 192.168.1.252 with everything else as
in 5acca52: with the 0x81 header forced on, the app save is answered
but the app.sab file open never is, and the device drops off the
network. Without it, the same Get with File works.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The save and file-open requests used their own fixed resend intervals
(5 s / 15 s) and the hello asked for 256-byte packets. Ontrol's Sedona
Java stack does neither and works with the P-ION: the standard backoff
(1, 2, 4, 8 s) sends a busy device a few copies with the same seqNum,
which its receive window drops. Both are removed.
Also fixes a race in SendWindow.send(): the packet entered the window
before its payload and sent_time were set, so housekeeping could resend
it with an empty payload, and the device would then drop the real one
as a duplicate.
Tested on a P-ION at 192.168.1.252, App > Get with File: save 3.2 s
(2 resends), app.sab + kits.scode in 11.3 s with 500-byte chunks
(was 14.6 s at 256), device stayed up, files identical to a 256-byte
backup.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A real P-ION (fw 1.32) restarted on every Sox file get. Ontrol's Niagara 4
driver gets app.sab from the same device, so its settings are copied:
- DASP hello asks for 256-byte packets (idealMax/absMax), so file chunks
are 238 bytes
- the message-length header (0x81) goes to Orion only, decided once the
platform id is read
- the app is saved on the device before app.sab is read, the save resent
every 5 s rather than 1 s (a P-ION save takes 2-3+ s)
- the file open is resent every 15 s; DASP gains a per-packet resend
interval for this
Tested on a P-ION at 192.168.1.252: save 3.2 s, app.sab + kits.scode +
app.sax in 15.8 s, no resends, device stayed up. The unsaved-changes
question became a notice, since the app is now always saved first.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reads app.sab and kits.scode over Sox file transfer, decodes app.sab to
app.sax (byte-identical to sedonac), and on Orion/Rion also fetches the
images and fonts the app names, with their sources from Sedona home's
banks. Offers to save the app on the device first when it is dirty, and
asks where to save with <Sedona home>/store/apps and
app-<device>-<app>-<timestamp>.zip filled in.
DASP trace lines are now printed by their own thread: printing from the
network threads to an unread stdout pipe blocked the receiver and made
file transfers time out.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Connect and Discover stay enabled while a device is connected. Pressing
Connect in the dialog drops the current device before the new one is
tried; cancelling the dialog leaves the connection alone.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Opening a file now drops the live connection once a file is chosen, without
asking. File > Exit and the window close box go through quit_app, which
closes the Sox session properly instead of leaving it for the device to
time out.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hovering a slot row highlights the half under the pointer and shows a
direction cursor. Pressing on a slot drags a rubber band; dropping on
another slot links them, dropping on a title bar opens the Link dialog
with the dragged slot preselected, and a no-entry cursor marks a slot
that would refuse the link. A right click that never moves still opens
the context menu.
The palette now leaves out types whose facets carry @palette=false, and
kits with nothing placeable left.
Also points the default device host at 192.168.1.251.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The schema built from a Sox session spelled checksums as signed decimals,
so no kit matched a manifest: Installed showed raw checksums and Action
read "Keep at checksum ...". They are now 8 hex digits like a .sax file,
and checksums compare regardless of zero-padding.
A device session only loads folders as they are opened, so only sys
counted as used. Used kits now come from the whole component tree, read
one request at a time so a small controller is not flooded into dropping
the session.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rename is offered from both the canvas and the navigation tree. Names are
checked against Sedona's Component.checkName rules (1-7 ASCII chars, a
letter first, then letters, digits or '_') and must be unique among
siblings. In file mode link paths through the old name are rewritten and
the rename is one undo step; in live mode it goes to the device via Sox
and warns if the device rejects it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
In live mode the device is now written first and the document only takes
what the device accepted. Every live_hooks failure records a reason, and
warn_failure() shows it in a dialog and the status bar instead of failing
silently.
- Move, properties, OX page editor: rejected values are rolled back and listed
- Add/remove link: no longer edits the DOM alone when an end can't be resolved
- Add/delete component: report why the device refused
- Tidy Layout: sends each new position to the device, reverts refusals,
marks the document dirty, and pushes no undo step in live mode
- User Manager: add (one Sox add carrying cred/perm/prov), edit and delete
now go to the device
- Binary Buf slots (e.g. User.cred) are sent as Buf bytes, not as Str text
- Bump version to 0.0.0.136
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The root tree row now names the app component, "app (<host:port>)" or
"app (<file>)", and offers Properties from its context menu and on
double-click. The live DOM's <app> element now carries its type and slot
values, and the refresh-by-id lookup finds it, so the view shows real
sys::App values.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The device builds the schema and version replies in a fixed 512-byte
packet and drops whatever does not fit. Read strings defensively, recover
a cut-off checksum from the one local manifest matching its prefix, and
fail with a clear message when the kit list cannot be recovered.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The font and image rows are now dropdowns filled from <sedona home>/ontrol:
fontBank/imageBank on Rion, fontBankXL/imageBankXL on Orion. Orion lists
.oxfl fonts in landscape and .oxfp fonts in portrait, read from the
platform service's screenOrientation (loaded from the device in live mode
when the tree has not reached it). Images show their file extension while
the slot keeps the bare name. The font dialog is gone.
In portrait the Page Editor draws a 480x800 screen in
frame_orion_portrait.png, and the canvas renders text with the .oxfp
fonts, whose glyphs are stored a quarter turn anticlockwise.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Edit mode, snap to grid and the widgets/properties pane are now toggles on
the main toolbar while the Page Editor is open. Outside edit mode the page
and the property sheet are read-only; drags snap to the 10px grid when
snapping is on. The default window grows by the right pane's width so the
canvas is not squeezed when the pane shows.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Page Editor canvas now paints widgets WYSIWYG instead of as
labelled placeholder boxes, following the ontrolOx draw() code and the
R-ION firmware:
- text drawn with the device's own bitmap fonts (fontBank .bin /
fontBankXL .oxfl), Windows font fallback; alignment, clipping at the
box edge, half-size subscript digits, transparent vs filled boxes;
the line is centred on the box even when the font is taller
- each widget shows the text its `in` selects: NumericLabel formats,
lookup items, Boolean true/false text and colours, date and time
- images from the local image banks, centred or cropped; missing ones
drawn as the device's red/white checker; page background image
- 10x10 pixel grid over the page colour, with a Grid toggle
- widgets hit-tested by layout box so transparent labels stay
clickable; hidden widgets shown as a dashed outline
- layout row gets an X/Y/Width/Height dialog
- scaled device frame cached per zoom (redraws ~15 ms)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Page Editor's right pane now shows the selected widget's properties
under the widget tree, laid out like Workbench's Ox editor rather than
as raw Sedona slots:
- layout (x, y, width, height), font (name, size, style)
- alignment / transparent / subscriptDigits from the attributes bits
- shape, RGB565 colours with a swatch and picker
- DateLabelSet date options split out of dateFormatOptions
- lookup labelText editor (prefix, items, suffix) and NumericLabel
printf-format editor, min/max as one row
- image name picker, slot link chooser for in/blink/visibility/touch
- Buf text decoded from base64 (Latin-1), plain text in live mode
Edits commit on Enter/focus-out/selection as one undo step and are
written to the device in live mode. Canvas drag-moves now use the same
path, so they are undoable and reach the device too.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Types with intermediate parents (e.g. ontrolOx::PushButtonImage ->
Widget -> Service -> Component) only got Component + own slots, so
config/runtime streams were decoded against the wrong slot list and
x/y/imageFileName came out wrong.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Makes the 320x240 screen cutout at offset (76,62) transparent,
matching the Orion frame style so the page background color
shows through correctly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Toolbar zoom buttons (in/out/reset/fit) and Ctrl+MouseWheel now
control the page editor canvas when it is active. Frame image is
scaled via PIL for smooth rendering at any zoom level.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Three PNG frames in assets/ with transparent screen cutouts:
- frame_orion.png (1144x849, screen at 191,169 = 800x480)
- frame_rion.png (433x396, screen centered at 76,62 = 320x240)
- frame_rion_portrait.png (856x1134, screen at 190,170 = 480x800)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New ox_page_view.py with OxPageViewPanel: canvas rendering at device
resolution (800x480 Orion, 320x240 Rion), RGB565 color conversion,
widget tree, selection handles, drag-move, device frame image support.
Wired into main.py with context menu, history, panel lifecycle.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Permissions dialog now uses two-level UI: compact Edit User with >> buttons
opening a separate grid dialog (Groups x Operator/Admin columns) with
Clear All / Set All and auto-cascade (write implies read, admin implies operator)
- Provisioning has its own >> popup dialog
- Removed live mode restrictions for add/edit/delete user operations
- Broadened type detection and added safe int conversion for live mode values
- Double-click on tree node or canvas box opens special view (User Manager for
UserService, Properties for other components)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>