Commit Graph
214 Commits
Author SHA1 Message Date
prxnvt d1f69878f6 Form controls: Space on a checkbox cell toggles it once while a slider or spin button is focused
With a slider or spin button focused, the Space key reached the grid and toggled a checkbox cell,
and the space it types then started a cell edit over the toggle (Escape cancelled the edit but
not the toggle). Now the typed space is dropped while a control is focused and the active cell
is a checkbox, as it is for a focused button: Space on a cell does what it does with no control
focused and nothing more, a checkbox cell toggles once with no edit, any other cell starts an
edit with a space. The path with no control focused is unchanged.

Test (kittest): space_on_a_checkbox_cell_toggles_it_once_while_a_slider_is_focused (toggled once,
no editor, the slider's value and focus unchanged; a second Space toggles back).
docs/ui-parity.md says so.
2026-11-02 03:06:40 -05:00
prxnvt 8495cc99e1 Form controls: Space on a focused slider or spin button starts a cell edit
The space a Space press types was dropped while any control was focused, because Space presses
a focused button. A slider or spin button doesn't take Space, so with one focused Space neither
worked the control nor started a cell edit, while every other character did. Now the space is
dropped only for a focused button; on a slider or spin button it reaches the grid like any other
character and starts a cell edit. The control keeps the keyboard, as the control last worked:
Space is a key it doesn't take, exactly like a letter, and letting go on Space alone would make
Space differ from every other printable key.

Test (kittest): space_starts_a_cell_edit_while_a_slider_or_spin_button_is_focused (a cell edit
starts with a space, the control's value is unchanged, Escape cancels, the arrows still step it).
docs/ui-parity.md says so.
2026-11-02 02:41:19 -05:00
prxnvt be0882a148 Form controls: a button gives the keyboard back when the grid takes a key or a click
A click on a button focused it, and the focus stayed while the grid moved the cell cursor with
the arrows, Tab or Delete, or opened a cell's menu with a right-click, so a later Enter or Space
pressed the button again without a new click, and Space could not start a cell edit. Now a key
press the focused button doesn't take (any key but Space, Enter and Escape, or one with Ctrl,
Cmd or Alt) gives the keyboard back to the grid, and any press that isn't a left click on the
grid, a right-click on a cell included, moves the focus off a control. A slider or spin button
keeps the keyboard as the control last worked.

Tests (kittest): a_button_gives_the_keyboard_back_when_the_grid_takes_a_key (arrow, then Enter
moves the cursor and does not press; arrow, then Space starts a cell edit; Cmd+arrow takes the
keyboard too) and a_right_click_on_a_cell_takes_the_keyboard_from_a_button. docs/ui-parity.md
says so.
2026-11-02 02:22:18 -05:00
prxnvt dcefd523eb Merge w/objects (082e3794, main 25881a8e) into w/form-controls
ROADMAP.md: both header changes (form controls first, then main's chart data tables), the form-controls progress-log and revision rows on top of main's rows.
docs/file-format-parity.md: both header changes (form controls first, then main's page order and chart data tables), the form-controls revision row on top of main's rows.
docs/macros.md: both header changes (form buttons first, then main's step-editor close rule).
docs/target-app-parity.md: both header changes (form controls and catalog 280 / 296 first, then main's ToolPak, page order and data tables), the form-controls revision row on top of main's rows.
docs/ui-parity.md: both header changes (form controls first, then main's Trace Error and page order; catalog count 280 / 296), the form-controls revision row on top of main's rows.
crates/model/src/sheet.rs: the push_object test helper (w/objects, b874f586) gets main's new Chart field, data_table: None, so the model crate's tests compile.
crates/ui-egui/tests/it/chart_data_table.rs: main's new test selects its chart through select_object_id, the one selection of w/objects, instead of the selected_chart field that w/objects replaced.
2026-11-02 01:47:07 -05:00
prxnvt 082e379412 Merge origin/main (25881a8e) into w/objects
ROADMAP.md, docs/chart-parity.md, docs/gaps.md, docs/target-app-parity.md, docs/ui-parity.md: the header change notes combine this branch's note with main's, dated today; main's revision and progress rows stay and this branch's rows are re-dated on top. Code merged without conflict.
2026-11-02 01:30:43 -05:00
Brandon Thomas 63607f881b Merge PR #3133
# Conflicts:
#	docs/ui-parity.md
2026-11-01 23:08:38 -05:00
Brandon Thomas e361f922d5 Merge PR #3130
# Conflicts:
#	docs/file-format-parity.md
#	docs/target-app-parity.md
#	docs/ui-parity.md
2026-11-01 23:08:37 -05:00
Ingmar LübbeandClaude Opus 5.5 f46c47f3cf Formulas: Trace Error draws arrows back to the cell an error starts in
New query command formulas.traceError and a Trace Error item in the
Error Checking menu, between Error Checking… and Circular References.
From the cell it follows the first reference that shows the same error
(in a range, its first cell showing it) to the cell the error starts in,
as measured in Excel, and returns that source and the arrows: links
between the error cells, and arrows from the source's own references.
The walk visits each cell once and stops after 10,000 links.

The grid's trace now holds arrows with the sheets of both ends, built
once from the command's result. Error links are drawn in a new red sheet
token, the other arrows in a token for the blue they had. "Trace Error"
is translated in all 18 catalogs (German: Spur zum Fehler).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SAgnkqJiy3v24Hp25dQLRj
2026-11-02 01:59:50 +01:00
Ingmar LübbeandClaude Opus 5.5 e2c523881f Page Layout: Page Setup's page order (Down, then over / Over, then down)
A sheet more than one page wide and tall always printed down, then
over. PrintSettings gains the page order (serde default Down, then
over), pageLayout.pageSetup takes pageOrder, and the pagination numbers
the pages in it, so printing, PDF export, the print preview, Page Break
Preview, Page Layout view and the &P/&N, first-page and odd/even
headers follow the printed sequence. XLSX reads <pageSetup pageOrder>
and writes pageOrder="overThenDown" only, as Excel does.

The Page Setup dialog gets a Page order choice with a small picture of
the order and runs pageLayout.pageSetup, so the order and the margins
are one undo step; the labels are translated where the dialog is, and
the dialog is now in German too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SAgnkqJiy3v24Hp25dQLRj
2026-11-02 01:43:14 +01:00
Ingmar LübbeandClaude Opus 5.5 bf79931b30 Formulas: trace arrows stay when the sheet is zoomed (#3097)
A zoom changes the workbook's revision, which the trace arrows are tied
to, so every zoom removed the arrows of Trace Precedents and Trace
Dependents. Zooming moves no cell: Trace::keep_through_zoom carries
arrows that were current over a zoom from the View tab, the Zoom dialog,
the status bar's buttons and slider, Ctrl+wheel and the control channel.
Undoing a zoom is still an edit and removes them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SAgnkqJiy3v24Hp25dQLRj
2026-11-02 01:08:19 +01:00
prxnvt 40aa1e8b66 Merge w/objects (df98e9ce, with origin/main f5030432) into w/form-controls
ROADMAP.md: both headers combined (form controls first, then main's entries); the form controls progress-log and revision rows re-dated 2026-11-01 on top of main's rows; the branch's duplicate floating-objects rows dropped in favour of main's.
docs/file-format-parity.md: header combined the same way; the form controls revision row on top of main's rows.
docs/target-app-parity.md: header combined; the form controls revision row (catalog 276 / 292 -> 280 / 296) on top of main's rows; the duplicate chart-resizing row dropped in favour of main's.
docs/ui-parity.md: header combined, its catalog count set to 280 / 296; the form controls revision row on top of main's rows; the duplicate floating-objects row dropped.
crates/ui-egui/tests/it/keytips_generated.rs: regenerated with cargo xtask keytips (370 sequences).
crates/model/src/sheet.rs: the exhaustive push_object test helper and the two-of-every-kind list gained the Control kind, which main's new test module did not know.
2026-11-01 16:59:58 -05:00
prxnvt dd9a01e3b2 Merge origin/main (f5030432) into pr/objects
ROADMAP.md: main's header and rows kept; this branch's progress-log and revision rows re-dated 2026-11-01 on top; the Change note names both.
docs/gaps.md: main's §13 Solver rows kept; this branch's §4 row re-dated 2026-11-01 on top; the Change note names both.
docs/target-app-parity.md: main's Solver and Insert Function rows kept; this branch's chart-handles row re-dated 2026-11-01 on top; the Change note names both.
docs/ui-parity.md: main's Function Library and Esc rows kept; this branch's floating-objects row re-dated 2026-11-01 on top; the Change note names both.
2026-11-01 16:34:14 -05:00
campbellcodyandCodex b6c4500fa7 M7: add data tables beneath charts
Add command and UI controls for chart data tables, shared chart and PDF rendering, and native XLSX persistence. Cover live values, blanks, formatting, alignment, undo/redo, bounds and table flags with regression tests.

Co-Authored-By: Codex <noreply@openai.com>
2026-11-01 15:30:46 -05:00
FredApps 10b763e7a4 Merge current main into PR467 and preserve both documentation histories 2026-11-01 19:06:22 +01:00
prxnvt 0fb3ea7a68 Docs: revision history for form controls
file-format-parity.md, target-app-parity.md and ui-parity.md gave form
controls a new timestamp line without a matching revision-history row;
each now has one. The file-format-parity.md timestamp line keeps the
earlier change it replaced, as the other docs do.
2026-10-31 16:12:07 -04:00
prxnvt 7042306478 UI: Insert › Controls, form controls on the sheet, Assign Action and Format Control
The Insert tab gains Button, Slider and Spin Button beside Cell
Controls › Checkbox, which is unchanged. Each arms placement: a drag on
the grid draws the control at that size (a tall drag makes a vertical
slider), a click places it at its default size, and Escape disarms. Key
tips (N B U, N S L, N S B) place one at the active cell. A new button
opens Assign Action, as Excel opens Assign Macro.

form_controls.rs draws the controls in the sheet tokens, so they look
the same in both themes: buttons with hover and pressed states, sliders
with a track, a filled part and a thumb (and the value beside the thumb
while it is dragged), spin buttons with two arrows, stacked or side by
side. A plain click works a control: dragging the thumb, clicking the
track (a page), clicking or holding an arrow (it repeats after 0.4 s),
pressing a button (it runs on release over it). A drag or a hold is one
undo step. The control last worked takes the arrows, Page Up and Page
Down, Home and End, and Space or Enter for a button. Ctrl or Cmd+click
or a right-click selects a control to move or resize it; a right-click
opens the object menu, which for a control adds Edit Text and Assign
Action (buttons) and Format Control before Delete.
Double-clicking a selected control opens its editor. On a right-to-left
sheet a control moves as a whole and works where it is drawn.

Assign Action runs a macro (from the list or typed, on the selection or
a fixed range, with an optional output cell) or a command (searched
among those a macro may run, with JSON parameters). Format Control edits
the value, limits, incremental and page change, cell link, orientation,
name and the locked and print flags, checking the same rules as the
engine. A button whose action needs approval, or whose macro would write
over data, asks in a prompt whose buttons press it again with the
answer.

New theme tokens (thumb, hover, pressed, fill, focus ring) are in the
contrast test; Button, Slider and Spin icons are drawn in code; the new
labels are translated in every interface language. The catalog gains
Developer › Controls (280 / 296).
2026-10-31 16:11:54 -04:00
Zarvinx f2bef898e8 #3035: let Esc leave File-page fields before closing 2026-10-31 18:09:27 +01:00
prxnvt e7591de2ec Objects: one selection for charts, pictures, shapes and slicers, with eight resize handles
The sheet tracked the selected object as a bare id in `selected_chart`, so
only charts and text boxes drew a selection frame, only the bottom-right
corner resized, and the kind of the selected object had to be guessed from
the id. The selection is now `SheetApp::selected_object: Option<ObjRef>`,
with `selected_chart()` kept for the Chart Design tab and the Format Chart
pane.

- Model: `ObjKind` (chart, image, shape, slicer) and `ObjRef { kind, id }`;
  `Sheet` helpers find, move and remove an object by `ObjRef` and walk every
  object's anchor in a fixed order. `next_object_id` saturates instead of
  overflowing on an id at `u32::MAX` read from a file.
- Commands: `object.delete`, `object.move` and `object.setAnchorMode` accept
  the four kinds through one parameter check, refuse an unknown kind or id
  instead of succeeding silently, and clamp hostile offsets. `object.delete`
  replies with the deleted object. Arrange and the Selection Pane include
  slicers, which stack above the other objects.
- Sheet: the selected object of any kind draws a frame with eight handles
  over every object. Each handle resizes only its own edges, which never
  cross; the body moves the object, and the first drag frame already applies
  the pointer's movement. The pointer shows the handle's resize cursor or a
  move cursor, with the diagonals swapped on a right-to-left sheet, where the
  frame moves with its object.
- Keys: Escape drops the object selection; Delete and Backspace keep
  deleting the selected object (#213). A selection whose object disappears
  (undo, redo, delete, sheet switch) is cleared.
- Double-click: `open_object` routes by kind (a text box edits in place, a
  chart opens Format Chart).
- Control protocol: `ui.inspect` reports `selectedObject {kind, id}` and
  keeps `selectedChart`; `ui.object.select` selects any object and replies
  with its rect. The snapshot example takes `--object <id>`.

Tests: engine tests for every kind by kind and id, the Selection Pane and
hostile parameters; UI tests for selecting each kind (a slicer over a chart
takes the click), all eight handles on four kinds, cursors, Delete,
Backspace and Escape, undo and redo, double-click routing, and resizing on a
right-to-left sheet. Existing tests use the new selection API.
2026-10-31 05:51:02 -04:00
prxnvt 474472f999 Engine: Recently Used follows the formulas entered; Insert Function category list
formulas.recentlyUsed scanned the session journal for cell.set inputs.
It missed formulas entered by range.* commands, lost them when the
journal dropped its oldest entries (a large file open or a long script
is enough), and started empty in every session. The Function Library's
Recently Used menu and the Insert Function dialog list what it returns.

- Prefs::recent_functions (a new engine module, recent.rs) holds the
  ten functions most recently entered in a formula, newest first.
  Session::execute updates it for every cell.* and range.* command it
  journals, from any source (the interface, the control channel, MCP or
  a script). It reads at most 2,000 of the formulas a command enters,
  starting from the last one; formulas longer than Excel's limit are
  skipped. formulas.recentlyUsed
  returns it. It never reads the journal back, so the journal's caps do
  not affect it.
- The list is kept with the other engine preferences (prefs.json, the
  browser's storage on the web), so it survives a restart as Excel's
  does. It is read leniently: a malformed value loses only this list. A
  fresh install starts from common functions.

The Insert Function dialog is titled "Insert Function", as in Excel (it
said "Formula Builder"), and gains a working category list: Most
Recently Used, All, then each category in Excel's order. A category may
be given by label or by engine id, so a Function Library menu or the
control channel (ui.dialog.set) opens it on one, and a new search
switches to All. The dialog keeps its translated labels and its search
in the interface language. Each row shows the function's name and its
category in two columns; the category column starts after the widest
name shown, so a long name in any font or formula language stays clear
of it. A function counts as recently used once its formula is entered,
not when OK is pressed. The unused "Formula Builder" translations are
removed.

Tests: engine unit tests for reading functions from formulas (strings,
unknown names, over-long and malformed formulas), the formulas a
command enters (newest first, within the budget), the ten-name list
and the lenient read of prefs.json; tests/it/recently_used.rs for
cell.set and range.setValues from the session, a failed command, a
cleared journal and a save and reload of the preferences. UI tests for
the menu's order and the dialog's title, categories, engine-id
category, search and OK, and for the category column with a wide font.
2026-10-31 04:00:56 -04:00
prxnvt 6aa5a78828 UI: Formulas › Function Library as labelled buttons with category menus
The Function Library group was a big Insert Function button followed by
AutoSum and seven big category buttons that all drew the same icon, the
widest group on the Formulas tab. It is now laid out as Excel lays it
out when the window is not wide enough for a big button per category:
big Insert Function and AutoSum buttons, then the categories as
labelled small buttons in columns of three:

  Recently Used    Text                 Math & Trig
  Financial        Date & Time          More Functions
  Logical          Lookup & Reference

- The category buttons draw a new code-drawn icon, Icon::FnBook, a book
  whose spine and glyph (star, coins, question mark, letter, clock,
  magnifier, theta, dots) take the category's colour from the theme's
  category palette. icons::paint_accent draws an icon with an accent
  colour, and widgets::small_button_accent is a small button that uses
  it; small_button is unchanged for its callers.
- AutoSum stays the big split button: the icon inserts SUM, the label
  and arrow open the AutoSum menu, which now reads Sum, Average, Count
  Numbers, Max, Min and More Functions… and is shared with Home ›
  Editing. Its tooltip names the control only, so the shortcut comes
  from the platform lookup (Alt+= on Windows and Linux).
- Each category menu lists its functions with their descriptions on
  hover and ends with Insert Function…, which opens the dialog with
  that category. More Functions cascades into Statistical, Engineering,
  Cube, Information, Compatibility and Web. Recently Used lists what
  the engine's formulas.recentlyUsed returns.
- The function categories, the function list (built once) and the menus
  live in a new function_library module; the dialog's category labels
  come from it.
- keytips.json gains MR for Recently Used, Excel's sequence. Labelled
  small and big buttons report their label to accessibility.
- The one-line labels (Date & Time, Lookup & Reference, Math & Trig,
  More Functions) replace the two-line keys in every interface
  language, with the same words. Recently Used is translated in Czech,
  German, Spanish, French, Japanese, Korean, Portuguese, Russian and
  Chinese; the other languages show it in English, their fallback.

Tests: tests/it/function_library.rs covers the layout (columns of three
level with the tab's other columns), each category menu and its Insert
Function… row, the More Functions cascade, the AutoSum split button and
its menu, and the MR key tip. A ribbon unit test keeps Command-key
glyphs out of the ribbon's text. chart_resize picks the chart menu's
Delete now that Home › Cells' Delete has an accessible name.
2026-10-31 03:35:06 -04:00
Michael HatzandClaude Opus 5.5 8f93ba2e9c Print checkbox cells as boxes, not TRUE/FALSE (#2972)
A checkbox cell drew a box on screen but printed and exported to PDF
its value as TRUE or FALSE. The print path now draws the box as the
grid does: white with a grey outline when unchecked, green with a
white tick when checked. Other values in a checkbox cell still print
as text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 23:14:20 +01:00
Brandon Thomas 75f7056e1b Review fixes: keep Plutonium-fream's contributor entry, order ui-parity changelog 2026-10-30 15:42:48 -04:00
Brandon Thomas d0cc17852e Merge PR #2919
# Conflicts:
#	docs/ui-parity.md
2026-10-30 15:42:31 -04:00
Brandon Thomas 15ea238fb7 Merge PR #2883
# Conflicts:
#	contributors/people.toml
#	docs/ui-parity.md
2026-10-30 15:42:31 -04:00
KameronandClaude Fable 5.1 57e40d2d14 Formula pointing: Ctrl+arrow and Ctrl+Shift+arrow jump to the edge of the data
While a formula reference is being pointed from the keyboard, Ctrl+arrow
(⌘arrow on a Mac) moved the pointed cell by one, and Ctrl+Shift+arrow
extended the pointed range by one cell, so `=COUNTIF(`, a click on the top
of a column and ⌘⇧↓ pointed at two cells instead of the column of data.
Both now go to the edge of the data region, as the same keys do on the
selection outside an edit: `point_move` takes `jump` and uses the engine's
`selection::jump`, which Ctrl+arrow on the grid already uses, so the two
agree (last filled cell of a run, else the next filled cell, else the sheet
edge). A pointed range that reaches the sheet edge is written as whole
columns or rows (`A:B`), as Excel writes it.

The editor used to read Shift from `i.modifiers`, the modifier state when
the frame's input was collected; an arrow pressed and released within one
frame (a control client's `ui.key`, an automation tool's keystroke) had
already lost it. It now reads the modifiers carried by the arrow's own key
event, as the grid's keyboard handler does.

Test: ctrl_arrows_in_point_mode_jump_to_the_edge_of_the_data (down to the
last filled cell, right across the data, down to the sheet edge, Ctrl+Up
without Shift to the next filled cell, then a plain arrow).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-29 15:11:55 -07:00
Roman Lisunov 0688e83752 Merge upstream main and retain numpad insertion documentation 2026-10-29 14:45:20 +02:00
fream 45cc92ae3c fix(ui): prefill existing hyperlinks in link editor (#2876) 2026-10-29 11:49:33 +01:00
RomanLis91andClaude Opus 5.5 a8e03ef40f fix(keyboard): Ctrl with the numpad's + inserts rows, columns or cells, as in Excel
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QJaF5jevKidVoJcnTyBFub
2026-10-27 23:40:35 +02:00
prxnvt c801e50e40 Merge #2152 (f8e1f8df, with main at f6b0cec6) into #478
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/io.rs
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/lib.rs
#	docs/target-app-parity.md
#	docs/ui-parity.md
2026-10-26 00:32:55 -04:00
prxnvt f8e1f8dfc0 Merge #2145 (4d26e395, with main at f6b0cec6) into #2152
# Conflicts:
#	crates/engine/src/io.rs
#	crates/engine/src/lib.rs
#	docs/target-app-parity.md
2026-10-26 00:29:13 -04:00
Pranav 1cd45cc909 Merge branch 'main' into pr/macros-ui 2026-10-25 23:54:09 -04:00
Pranav b552b7a929 Merge branch 'main' into pr/macros-record 2026-10-25 23:49:08 -04:00
aiongg f102fe29a1 Merge g3 into g4
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/cmd/edit.rs
#	crates/engine/src/cmd/formulas.rs
#	crates/engine/src/cmd/inspect.rs
#	crates/engine/src/cmd/pivot.rs
#	crates/ui-egui/src/lib.rs
#	crates/ui-egui/src/tabs.rs
#	docs/gaps.md
#	docs/ui-parity.md
2026-10-26 02:45:41 +00:00
aiongg 015b9abe5b Merge g2 into g3
# Conflicts:
#	Cargo.lock
#	Cargo.toml
#	ROADMAP.md
#	apps/gridcraft/src/main.rs
#	crates/ui-egui/src/lib.rs
#	docs/ui-parity.md
2026-10-26 02:37:36 +00:00
aiongg 929495e274 Merge g1 into g2
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/cmd/extra.rs
#	crates/engine/src/lib.rs
#	crates/engine/src/tests.rs
#	docs/control-protocol.md
#	docs/ui-parity.md
2026-10-26 02:37:33 +00:00
aiongg 903bece86f Merge upstream main into g1
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/tests.rs
#	crates/ui-egui/src/lib.rs
#	docs/ui-parity.md
2026-10-26 02:23:11 +00:00
Brandon Thomas 0665476b35 Merge pull request #2493 from Harrison-Booth:feat/options-iteration-fields
# Conflicts:
#	docs/function-parity.md
#	docs/ui-parity.md
2026-10-25 09:36:59 -04:00
Bryan MarkandClaude Opus 5.5 802c782360 AutoSum: a selected row gets its total to the right, as in Excel
AutoSum over any selection of more than one cell wrote a total under each column, so a row
selected (B2:E2) got four one-cell totals in row 3 instead of =SUM(B2:E2) in F2.

As Excel does, totals now go in the selection's empty last row or column, and otherwise past
it:
- a single row: its total in its last cell when that is empty, else just to its right;
- a block whose last column is empty: each row's total there; whose last row is empty: each
  column's; both: both, and the block's total in the corner;
- otherwise totals under each column, as before.

A whole-row selection still stops at the data's last column, and all totals are one undo step.
Tests: autosum_over_a_row_totals_it_to_the_right,
autosum_over_a_whole_row_totals_it_after_the_data and
autosum_fills_a_selections_empty_last_column_and_row; each fails without the change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 20:34:30 +08:00
prxnvt 1443ec417c UI: macro step editor with a debug bar and grid overlays
New Macro (Automate › Macros) and Step Into, Edit and Create in the
Macros dialog open a resizable step editor. It works on a draft of the
macro and saves it with macro.save.

The step list shows each step's number, a breakpoint dot in the gutter
(click to set or clear), a category icon, a summary, an error marker
and an enabled checkbox; Repeat bodies and If branches are indented
under their step, and rows drag to reorder within their list. Add Step
opens a command picker (control steps first; commands a macro may
never run are left out) and fills in the command's required
parameters; Duplicate and Delete act on the selected step.

The inspector's Details tab edits the selected step. Reference
parameters are reference boxes that take a typed reference or a
selection on the grid, with a Rel/Abs switch between a token relative
to the example input and an absolute reference, and token suggestions.
The Inputs tab sets each input's shape, header and column types (Use
current selection as example infers them); the Output tab sets the
anchor and the conflict rule.

The debug bar has Check (a dry run that colours the grid: inputs blue,
writes green, writes over data red), Run, Step, Continue, Run to Here
and Stop, which asks whether to keep the changes or undo them. The
debugger receives the editor's breakpoints with breakpointsOnly, so a
dot cleared while paused takes effect at once; the current step is
selected, its parameters are shown as they will run, and its target is
outlined on the grid. While a macro is debugged, the status bar says so
and Show reopens the editor.

List drag and drop lives in a small dnd module. The debugger icons are
drawn in code, and the breakpoint and sheet overlay colours are theme
tokens covered by the contrast test.
2026-10-25 06:48:57 -04:00
prxnvt 5512c1a269 UI: Automate › Macros group, Record Macro and Macros dialogs, recording status, macro shortcuts
The Automate tab gains a Macros group: Macros opens the Macros dialog,
Record Macro opens the Record Macro dialog (name, Ctrl+Shift shortcut
letter, description, Use Relative References) and turns into Stop
Recording while recording, Use Relative References sets how the next
recording starts, and Run Macro runs the macro run last; its menu lists
the recent macros, then every macro. While recording, the status bar
shows a red dot, "Recording · N steps" and Stop.

The Macros dialog (Automate › Macros, View › Macros, Alt+F8) lists the
workbook's macros with their shortcuts, then its Automate scripts, and
says when the file carries a VBA project, which is kept and not run.
Run, Delete (which asks first) and Options (shortcut letter and
description) act on the selected row. The dialog keeps the result of
view.macros, so the scripts and the VBA entry are listed as before.

A macro that needs approval asks with Run, and one whose output would
land on data asks with Overwrite, Shift Down and Shift Right; each
button runs the command again with its answer. Ctrl+Shift+letter
(Cmd+Shift on a Mac) runs the macro with that shortcut; the letters
GridCraft uses keep their meaning. The View › Macros keytips (WMR, WMV)
now open the Record Macro and Macros dialogs.

Icons for macros, recording and relative references are drawn in code,
the recording dot is a theme token covered by the contrast test, and
large and small ribbon buttons and icon buttons carry accessible names.
2026-10-25 06:48:57 -04:00
prxnvt b40fa4e065 Merge #2145 (2fb31f11, with main at 17b9f6ff) into #2152
Main refuses window.* steps in scripts, so the recorder test's script step that a macro may not
run is app.commands.
2026-10-25 02:29:03 -04:00
aiongg 17b9f6ff01 Paste Name and Go To: follow-ups from the batch review (#2540)
* Go To: names match in any case and script, as formulas match them

* Paste Name: only the names in view are laid out

* Docs: LAMBDA recursion limit and called error names; one Page Layout view row with the side margin marked unverified

* Go To and Paste Name: cargo fmt
2026-10-25 01:24:24 -04:00
aiongg f65e9f6bed Merge upstream main into the batch
# Conflicts:
#	crates/ui-egui/src/formula_bar.rs
#	crates/ui-egui/src/ribbon.rs
#	crates/ui-egui/tests/it/main.rs
2026-10-25 03:34:46 +00:00
Pranav e1a12fa337 UI: theme tokens with a contrast test, ribbon overflow arrows and split button, multi-line formula bar, code editor widget (#456)
* UI: theme tokens for icon, reference and sheet-control colours; WCAG contrast test

Tokens gains the colours the chrome was hard-coding, each with a light
and a dark value: on_accent (text on an accent fill), an eight-colour
category palette (theme::Cat), the paper colour inside icons, reference
colours for the formula bar and for the sheet, the message box warning
disc, the tab bar scroll thumb, and sheet_control_* colours that follow
the sheet and so stay light in both themes.

What now comes from the tokens:
- icons: paper (white pages glared in dark mode) and the accent
  constants; icons placed on the sheet use icons::paint_on_sheet, which
  keeps the light colours;
- reference colours (editor::REF_COLORS), which were hard to read on the
  dark formula field;
- white text on the accent in OK, Solve, slicer tiles and the AutoSave
  switch, 2:1 on the dark accent;
- the comments pane (a white card with light text in dark mode), gallery
  hover and swatch outlines, the message box disc, the tab bar thumb,
  chart selection frames, and the sheet's filter and validation buttons.

A unit test (theme::contrast_tests) checks every token pair used by the
ribbon, popups, dialogs, panes, formula bar, status bar and sheet in
both themes against WCAG 2: 4.5:1 for text and 3:1 for glyphs. It caught
the dark danger red (3.5:1 on hover) and the selected header text (4.1:1
light), which are adjusted.

* UI: ribbon scroll arrows, large split button for Formulas › AutoSum

- widgets::big_split_button: the icon runs the default action, the
  label and its arrow open the menu. It returns both responses, with
  accessible names ("AutoSum" and "AutoSum options"). big_button shares
  its label layout.
- Formulas › AutoSum uses it: the icon inserts SUM as before, and the
  arrow, which used to do the same, opens the Sum / Average / Count /
  Max / Min / More Functions menu that Home › AutoSum already had
  (shared as autosum_menu). Its keytip is unchanged.
- When a tab's groups are wider than the window, arrows at the card's
  edges scroll them; before, only the mouse wheel did and nothing showed
  that the tab went on. ribbon::RibbonOverflow records the groups' and
  the card's sizes each frame.
- A test checks every tab fits the card's three rows. It found View ›
  Show stacking four checkboxes, with Headings cut off; Show is now two
  columns (Ruler, Gridlines / Formula Bar, Headings).

Tests: tests/ribbon_layout.rs (the split button's two parts, AutoSum's
icon and menu, the scroll arrows, the card height).

* UI: formula bar grows from one to five lines; code editor widget

The formula bar is a top-aligned row: the Name Box and the cancel,
enter and fx buttons stay on the first line while the field grows. Its
height is the content's laid-out line count (Alt+Enter or wrapped text)
times the font's row height, from one line (30 px, as before) to five,
then the field scrolls with the caret in view. This holds while editing
and while viewing a cell. The height eases over 120 ms when the line
count changes, and the chevron pins it at five lines (it used to give a
fixed 72 px). The in-cell editor likewise stops at five lines and
scrolls. formula_bar::BarLayout records where the parts went, for tests.

widgets::code_editor(ui, id, &mut text, Lang, max_lines) is a small
code editor for features that edit code: the monospace font, syntax
colours from Tokens::syntax (new, with light and dark values in the
contrast test) for Python (keywords, strings including triple-quoted
ones, numbers, comments and builtins) and LaTeX (commands, scripts and
comments), Tab inserting four spaces (or indenting every selected line,
Shift+Tab dedenting), Enter keeping the line's indentation (one level
more after a Python colon), and a scroll area that follows the caret.
The tokenizer and the edits are pure functions with tests, including
hostile input that must keep spans on char boundaries.

kittest (tests/formula_bar.rs) covers Alt+Enter up to eight lines with
the Name Box and buttons fixed and the caret visible, the commit,
viewing the committed cell, the chevron, the ease, the in-cell cap and
the code editor's Tab and Enter.

* UI: Shift+Tab in the code editor dedents instead of indenting

The editor consumed plain Tab before Shift+Tab, and egui's key match ignores Shift
when the pattern lacks it, so a Shift+Tab was taken as Tab and indented the line.
Shift+Tab is now consumed first; a plain Tab still inserts spaces.

* UI: the ribbon card stays inside a narrow window, so its right scroll arrow is on screen

The row above the ribbon can be wider than a narrow window, and the card took that width, so the
right scroll arrow was drawn past the window's edge and couldn't be clicked: below about 640 px on
macOS, and at 700 px with Linux's wider default fonts, where CI's ribbon test failed. The card is
now kept within the window with the same margin it has on the left.

* UI: each ribbon tab keeps a scroll offset of its own

The ribbon's scroll area used one identity for every tab, so scrolling an overflowing tab and
switching to another overflowing one hid that tab's first groups. Each tab now has its own scroll
state: a tab opened after another was scrolled starts at its left edge, and a tab keeps its offset
while others are used.

* UI: the in-cell editor keeps its whole width for the text and shows every line

Merged with main, the grid's own test asked the in-cell editor to wrap its
text at the field's full width and to show every line (the editor never
scrolls); the editor widget wrapped it inside the formula bar's scroll area,
which took the bar's width off the text (168 px tall where 156 was right),
and the grid capped it at five lines. The in-cell editor now shows the text
field on its own, through the one show_edit helper the formula bar also
uses, and grows with every line; the formula bar keeps its five lines and
its caret scroll. The branch's five-line test for the cell editor becomes a
grows-with-every-line test.

* Docs: the UI building blocks' revision rows carry the date they land

The rows said 2026-10-11, older than upstream rows above them, and the
ui-parity row said the in-cell editor is capped at five lines.

* UI: the formula bar's view of a cell starts at the cell's top

The bar's read-only view kept one scroll offset for every cell, so a cell
shown after scrolling another's text started scrolled. The offset is kept
per cell now.

* UI: the editor's field does nothing with Enter on its own

The editor handles Enter (commit) and Alt+Enter (a line break) itself, and a
message box over the editor takes Enter to close. The field under it is a
multi-line TextEdit since the bar grew, whose own return key would add a
line if it ever saw Enter; return_key(None) keeps that from depending on
where focus sits. A test shows Enter over a message box adds nothing to the
entry (focus is off the field then, so it passed before too: this is
hardening, not a repair). The doc comment split by the show_edit helper is
mended.

* Docs: ui-parity says the in-cell editor shows every line, and its revision table is whole

A sentence still said the in-cell editor stops at five lines, and a blank
line between the table's separator and its first row ended the table.

* UI: the split button's tooltip carries the shortcut hint like every ribbon button's

big_split_button built its tooltip with the bare translation, so AutoSum,
which became a split button, lost its shortcut hint. It uses tip_text now;
the split-button test hovers the button and looks for the hint.

* UI: a selection that ends at the start of a line leaves that line alone

Selecting "a\n" in "a\nb" and pressing Tab also indented b, and Shift+Tab
could take its indentation: the line after the selection was counted as
touched. It is touched only when the selection reaches into it.

* UI: the code editor applies its keys in input order, with the typing around them

The editor consumed Enter, Tab and Shift+Tab before the text field saw the
frame's events, so a frame carrying typed text followed by Enter (events
gather between repaints, and under key repeat) put the newline before the
text, and two Enters in one frame made one line. The editor now walks the
frame's events in order and applies typed text, pastes, Enter, Tab,
Shift+Tab, Backspace and Delete itself, taking them from the queue; the
first event it does not handle and everything after it stay for the field,
which runs next, so the order holds either way.

* UI: the code editor keeps the input order past the keys the text field handles

The editor applied its keys up to the first event it did not handle and
left that event and everything after it to the text field, which has
its own Tab and Enter: select all followed by Tab in one frame replaced
the code with a tab character, and since the platform sends a key event
before each text event, an Enter after ordinary typing lost its
indentation.

The editor now applies its keys up to the first event the field acts on
(a caret or selection key, a key under a command modifier, IME, a click);
that event and the run after it stay for the field; from the editor's
next key on, the keyboard events are held back under the editor's id for
its next pass, where it puts them ahead of that pass's input and splits
again. They go only to the editor they were typed into, only while it
still has the focus, and only in the pass right after; otherwise they
are dropped rather than typed into another widget. Printable key presses
do not split the stream. Tab under a command or option modifier is taken
off the queue, and Enter under Shift or Option is the editor's newline,
so the field never gets a Tab or an Enter of a focused editor.

* UI: the ribbon layout and formula bar tests join the crate's integration test binary

Since #2372 the crate's integration tests are one binary built from tests/it/, one module per file; only tests that set process-wide state stay separate. These two set none.

* UI: the formula bar's one-line height follows the font, so five lines fit on Windows

One line was a fixed 30 px and the bar grew by one row height per line.
The panel's and the field's margins take 12 px of that, and rounding to
the pixel grid up to another, so a row taller than 17 px lost the last
counted line: with the Windows UI font (17.28 px rows) five lines showed
four, and bar_grows_to_five_lines_then_scrolls_with_name_box_pinned
failed there.

formula_bar::one_line(row_h) is 30 px unless the rows need more, and
every counted line fits whatever the font. The kittest heights are
computed from it rather than from 30, and a unit test checks the
arithmetic for rows of 15.6 to 20 px.

* UI: Paste Special's OK button uses the on-accent colour

It was the one OK button still drawn white on the accent: 2.14:1 in the dark theme, where every other OK uses on_accent (7.1:1).
2026-10-24 20:54:34 -06:00
aiongg 1e50c72698 Merge storytold/gridcraft#2488: Headers and footers: printing follows the Scale with Document and Align with Page Margins check boxes
# Conflicts:
#	docs/ui-parity.md
2026-10-25 02:54:23 +00:00
aiongg b58846a549 Merge storytold/gridcraft#2482: Outline: Settings puts summary rows above and summary columns left of their detail
# Conflicts:
#	docs/ui-parity.md
2026-10-25 02:54:23 +00:00
aiongg 1713334579 Merge storytold/gridcraft#2477: Sheet tabs: drag the handle at the scrollbar's left edge to give the tabs more or less room
# Conflicts:
#	ROADMAP.md
#	docs/ui-parity.md
2026-10-25 02:54:22 +00:00
aiongg cb1fb89549 Merge storytold/gridcraft#2467: PivotTables: right-clicking a value cell offers Show Details in the cell menu
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/cmd/pivot.rs
#	docs/ui-parity.md
2026-10-25 02:46:38 +00:00
aiongg 8356b33c78 Merge storytold/gridcraft#2456: Fill handle: Fill Days, Fill Weekdays, Fill Months and Fill Years for a date
# Conflicts:
#	ROADMAP.md
#	docs/ui-parity.md
2026-10-25 02:46:16 +00:00
aiongg 2741680144 Merge storytold/gridcraft#2427: Keyboard: Ctrl+Shift+U expands and collapses the formula bar instead of underlining
# Conflicts:
#	ROADMAP.md
#	docs/ui-parity.md
2026-10-25 02:46:16 +00:00