Keep blank whole-format General fallback while hiding values selected by explicit empty sections. Pin section selection, signed zeros, semicolon boundaries and General controls with regressions. Contribution on behalf of @MMexicann.
A report on 0.7.0 said the Options dialog's Cancel did nothing, and a
reproduction on 0.8.0 found it working for the appearance toggle and the
name field, without trying the other controls. This covers the rest: the
Editing checkboxes (snap to grid, smart quotes, autocorrect) and the name
field go back with Cancel, like the first checkbox does.
Verified red with the restore of the settings taken out: the name keeps
what was typed.
Adobe symbol.txt also maps 0xA0 to the euro sign (U+20AC), which
symbol_unicode lacked. Apple's Symbol maps a few codes to different
Unicode than Adobe (0xA4 to U+2044, 0xE1/0xF1 to U+3008/U+3009), so
symbol_font_draw now tries those alternatives after the Adobe character
when the installed face doesn't cover it. The Adobe aliases for
0x44/0x57/0x6D (U+2206/U+2126/U+00B5) are not Apple alternatives and
stay out.
symbol_font_char masked every bullet character to its low byte before
checking direct coverage, so a 'bullet' (U+2022) bullet drew an
unrelated Symbol code. It now maps only symbol-font codes (low byte or
U+F0xx) and falls back to the original character when the face covers
it.
Found while testing crates/format/src/lib.rs:660-665 (slides_to_outline) and :573-574 (outline_to_slides)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The painter only applied when a shape was clicked. It now also applies
when a text range is selected by drag, double-click or triple-click.
Paragraph formatting (bullets, alignment) is copied only onto
paragraphs the selection covers whole.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/pptx/src/opc.rs:283-285 (resolve)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/engine/src/cmd/slide.rs:234 (delete); same pattern in index_of :182, move_slide :269, duplicate :193 and section_add :534
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/model/src/chart.rs:1129-1135 (histogram_bins)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The reader stored a series-level `c:dLbls/c:showVal` in
`Series.data_labels`, but every drawing path tested only the chart-wide
`Chart.data_labels`: a series that asked for labels got none, and a
series that asked for none got them. The series' own setting now wins,
and a bare `<c:showVal/>` (no `val` attribute) means true, as the
schema's default.
The plot group's own setting is respected too: a group that asks for no
labels keeps them off, even when another group of a combo chart asks for
them. Before, any group that asked turned the chart-wide setting on, and
the group that said no inherited it.
Tests: `crates/pptx/tests/chart_data_labels.rs` - a bare series
`showVal` shows that series' labels while its siblings stay quiet; an
explicit `val="0"` on the first series keeps it quiet under a chart-wide
on; a combo chart keeps each group's own setting; all three settings
round-trip. Red-proof: with the series-level setting ignored, the first
two fail; with the group's setting ignored, the combo chart's bar group
shows labels it asked to keep quiet.
The model gains `Chart::series_data_labels`, the one place that decides
whether a series' labels show; the render paths (bar, column, line,
area, pie, doughnut, radar, scatter) call it.
The Options dialog applies every change as it is made, and closing it
with Cancel, Esc or the window's close button puts the settings back the
way they were. Nothing covered that, so a change to the dialog could have
dropped it unnoticed.
The kittest now covers all three ways out: a checkbox put back by Cancel,
the appearance and the interface size put back by Esc, the same checkbox
put back by the window's close button, and the dialog closing in each
case. Red-proof: with the Cancel restore removed the checkbox test fails
(the setting stays changed), with the Esc restore removed the appearance
test fails (it stays dark), and with the Esc/close restore removed the
close-button test fails (the setting stays changed).
ROADMAP progress-log row added.
The fix changed the empty-placeholder fill gate, but nothing locked the
behaviour in: a quick style's fill has to appear on an empty placeholder,
and a placeholder with no style at all still has to stay empty.
The new render test draws an empty body placeholder in the editor with a
quick style and checks that the accent fill is painted - every channel of
it - and that the same placeholder without a style stays white. With the
gate reverted to `s.fill.is_none()` alone the first assertion fails - the
placeholder stays white - so the test is red on the unfixed code.
Two gaps in the resize cursor, both found by a review of the fix:
- The handle's direction was taken from the box centre to the handle, so a
wide rectangle's corner pointed almost along an edge: a 400x80 shape's NW
corner showed a horizontal cursor. A corner drags along the diagonal
whatever the shape's proportions, so the direction is now normalised -
the diagonal at 45 degrees - and only the shape's rotation and flips
turn it.
- The cursor read the shape's own box, but the handles are drawn from the
effective one, which a placeholder inherits from its layout. Such a
placeholder showed the default arrow instead of a resize cursor.
The tests cover both: a wide shape keeps its corner cursors diagonal, and
a placeholder that inherits its box has a resize cursor. Red-proof: with
the aspect ratio back in the direction, the wide shape's NW corner shows
a horizontal cursor; with the shape's own box, the placeholder shows the
default arrow.
Home's ribbon has grown since the test was written. At the harness's
1400x900 the Editing group starts at x=1398, so the Replace Fonts
button is two pixels wide on screen and a click at its centre lands
outside the window: the button is found and enabled, but never clicked,
and the dialog assertion fails. The ribbon does not scroll sideways, so
the window has to hold it; 1800x1100 is what the other full-ribbon
tests here use.
cargo xtask ci fails at `test` on main without this.
When the Format Painter or Animation Painter was armed, the mouse cursor
stayed as the default arrow. The user had no visual indication that the
tool was active and waiting for a click on a shape to apply the copied
format.
The canvas now sets the Copy cursor while either painter is armed, and
goes back to its usual cursor once the tool is done. The override takes
precedence over the other cursor assignments (resize, move, crosshair,
text), because the painter's whole purpose at that moment is to receive
the next click.
The kittest covers both painters: it hovers over the canvas, checks the
cursor is not the Copy one yet, arms the painter and checks it is. With
the painter override removed both fail - the cursor stays Move instead
of Copy.
ROADMAP progress-log row added.
0x3C-0x3F are plain ASCII < = > ? in Adobe's symbol encoding (<= >= inf
sit at 0xA3/0xB3/0xA5 and therefore at 0x5C), so 'a<b' set in Symbol
drew 'a<=b' on macOS. Drop those four symbol_unicode arms and their
pairs in the whole-table test, and list 0x3C-0x3F as ASCII.
symbol_font_draw returned None for codes with no table entry, so U+F031
('1'), U+F028 ('(') etc. still didn't draw from Symbol. For 0x20-0x7E
with no table entry, fall back to the ASCII character itself when the
face covers it; covers_symbol now delegates to symbol_font_draw so the
shaping path picks the Symbol face for those codes too.
ROADMAP header keeps a single Last reviewed line (replaces, not adds).
The sorter's Ctrl+A runs edit.selectAll with the slides scope, so every
slide in the deck is selected, as in PowerPoint. Nothing covered the key
press itself, so a change to the shortcut could have dropped the scope.
The kittest covers the whole way: the key press, the scope and the
selection it leaves behind. Red-proof: with the sorter's Ctrl+A no longer
asking for the slides scope, the selection stays at the one current slide
and the test fails.
ROADMAP progress-log row added.
The render gate for an empty placeholder's fill checked only
s.fill.is_none(). A quick style that sets a style reference without
an explicit fill left s.fill as None, so the gate skipped the fill
even though the shape had been formatted — the style only appeared
after text was added.
The gate now also checks s.line and s.style: if any of the three has
a local override, the placeholder is considered formatted and the
fill is drawn. A truly unformatted empty placeholder still shows the
dashed outline and prompt.
The pane scrolled only by hand: past a screenful of slides, arrow-key
navigation left the current thumbnail out of view. When the slide changes,
the pane now scrolls it into view - minimally, only once the thumbnail has
left the viewport, as in PowerPoint, so a visible thumbnail never moves the
pane and the user's own scrolling stands. The pane's scroll offset is
recorded in UiState (skipped by serde) for the control channel and tests.
* M2.1: preserve chart parts through native saves
Serialize retained chart relationships and payloads in native files.
Add native and headless file-command round-trip regressions.
Contribution on behalf of @MMexicann.
* Format: bound opaque chart parts as native ZIP entries
Address maintainer feedback on the existing PR. Preserve upstream work and document tested scope and validation limits.
* Model: track transient native chart part entries
Address maintainer feedback on the existing PR. Preserve upstream work and document tested scope and validation limits.
* PPTX: initialize native chart entry metadata
Address maintainer feedback on the existing PR. Preserve upstream work and document tested scope and validation limits.
* Engine: adapt chart native roundtrip fixtures
Address maintainer feedback on the existing PR. Preserve upstream work and document tested scope and validation limits.
* Docs: describe bounded chart sidecars and validation
Address maintainer feedback on the existing PR. Preserve upstream work and document tested scope and validation limits.
* Roadmap: record bounded chart persistence evidence
Address maintainer feedback on the existing PR. Preserve upstream work and document tested scope and validation limits.
---------
Co-authored-by: skylar taylor-barrick <hi@skylar.cc>
Found while testing crates/model/src/numfmt.rs:256 (fixed)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/model/src/numfmt.rs:115-116 (general)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/engine/src/cmd/find.rs:107-121 (para_chars / para_matches; splice at :124)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A click on the frame band of an unselected or selected text box or
placeholder started text editing, so the box could not be selected,
moved, duplicated or deleted from its frame. The frame band now selects
the box whole, like PowerPoint; only a click inside takes the caret.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/engine/src/cmd/edit.rs:573-585 (delete)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A shape added after an Undo can get an undone copy's id; duplicating it then
used the move measured from the old original.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Design › Browse for Themes… with a .pptx or .potx now does what PowerPoint
does: the file's first slide master and its layouts replace the master the
current slide uses (a preserved master stays beside it), stretched to this
deck's slide size. Each slide on the old master moves to the new layout with
the same name, else the same kind, and keeps its content as Layout does. One
undo step. A .thmx still brings its theme only.
Reuse Slides' master copy (media, fresh master, layout and shape ids) moves
into reuse::import_master so both commands share it.
Co-Authored-By: Claude Code <noreply@anthropic.com>
# Please enter the commit message for your changes. Lines starting
# with '#' will be kept; you may remove them yourself if you want to.
# An empty message aborts the commit.
#
# interactive rebase in progress; onto 22db926
# Last command done (1 command done):
# pick 8992623#807: Browse for Themes brings a template's slide master and layouts
# No commands remaining.
# You are currently rebasing.
#
# Changes to be committed:
# modified: ROADMAP.md
# modified: crates/engine/src/cmd/design.rs
# modified: crates/engine/src/cmd/reuse.rs
# modified: docs/file-format-parity.md
#
Ctrl+F and typing searches without clicking the field first, and the field
keeps the keyboard after Enter finds a match.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Found while testing crates/engine/src/cmd/richclip.rs:257-283 (decode_text)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Duplicating a shape, moving the copy and duplicating that copy again places
the next copy the same distance further on. Anything else, an undone copy or
another slide gets the usual offset.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
p188:cmLst declared only xmlns:p188 but its comment bodies use a:bodyPr, a:p, a:r and
a:t, so the part was not namespace-well-formed and PowerPoint refused the saved file.
A regression test parses every written XML part with a namespace-aware reader.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>