Repository navigation
Integration batch 1: 35 contributor PRs (charts, shapes, slides, text editing, dialogs, outline files) - #1260
Merged
Merged
Conversation
Keep the keyboard while editing list text: Tab and the arrow keys moved egui's keyboard focus onto ordinary widgets, and that stray focus swallowed every later key, so lists could not be typed into or continued with Enter.
storytold#782) In release 0.7.0, Cancel in the Preferences dialog (opened via Options in the File tab) did nothing. This was previously addressed on main by storytold#757 (storytold#752). This change adds an egui_kittest regression test verifying that clicking Options from the File tab opens the Preferences dialog and clicking Cancel closes it while keeping Backstage open. In addition, the About dialog's Cancel button now properly closes the dialog instead of being ignored. Closes storytold#782.
…m the right-click menu
review.reject {index | all} drops revisions from the list without applying
them, so the open deck stays as it is: a rejected inserted slide is never
added, a rejected deleted slide stays, a rejected changed slide keeps its
current content. Accept All skips what was rejected. Rejections are kept on
the compare session (keyed by the open slide id and the revised slide) and
end with End Review; like Compare and End Review, rejecting is not an undo
step, since it leaves the document untouched.
Revisions pane: Reject next to each Accept, and Reject All.
…the body Paragraph commands (align, case, insert, paste, selectParagraph) iterated for pi in a.0..=b.0 with both ends taken verbatim from text.select, so a control-channel selection with caret u64::MAX spun the loop over 2^64 entries on the UI thread, and text.selectParagraph's at.0 + 1 overflow- panicked in debug builds. Clamp every range at the body's last paragraph and use saturating_add for the single-index arithmetic. Regression test: paragraph_commands_clamp_a_hostile_text_selection — fails on main with 'attempt to add with overflow' at cmd/text.rs:1151, passes with the clamp.
Adds PowerPoint's Outline/RTF save type: slide titles at outline level 0 (bold, larger), body paragraphs indented at their outline level, bold, italic and underline kept, non-ASCII as \u escapes. RTF outlines (ours, PowerPoint's or a word processor's, by outline level or indent) open as a presentation or drop in as slides. Co-authored-by: Cursor <cursoragent@cursor.com>
Found while testing crates/engine/src/cmd/text.rs:1151 (select_para) Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com> Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
`HeaderFooter::date_format` is documented as the `datetime1`…`datetime13` format for automatic dates, and nothing read it: grep found one hit, the field's own declaration. The Date placeholder was hardcoded to `datetime1`, so the footer date was always the short date, and a `dateFormat` parameter was accepted and silently dropped — the command returned Ok, so a caller could not tell. Everything else was already there: `datetime::field_text` renders all thirteen types and Insert ▸ Date & Time already offers them. Missing was the wiring from a choice to the placeholder. `design.headerFooter` now takes `dateFormat`, refuses anything outside the thirteen rather than ignoring it, stores it, creates the placeholder with that field type, and updates an existing one when the format changes — as it already did for a changed `dateText`. A fixed date still wins as plain text, and going back to automatic restores the remembered format. `datetime::DATE_KINDS` is the canonical list; `dialogs.rs` uses it rather than its own copy of the same thirteen strings, and the Header & Footer dialog gains a Format dropdown listing each type by what it would show now, enabled while the date is automatic. Not here: reading a deck does not populate `date_format`, so the dialog shows datetime1 preselected for a deck whose dates are something else until the user picks. That is a pptx read-side change and wants its own PR.
… layouts 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 storytold#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 #
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>
…ide visible (storytold#917) 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.
…d#832) 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 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.
…ld#830) 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.
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.
… shape (storytold#745) 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.
…torytold#832) 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.
…the settings (storytold#878) 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.
…how (storytold#868) 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.
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>
…rytold#878) 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.
…old#1103) Reuse Slides… used to insert every slide of the picked presentation. It now opens a list of that presentation's slides (number and title, all ticked), with Select All / Select None and a Keep source formatting option, and inserts only the ticked ones after the current slide. New query slide.reuseList {path | data} gives the list; slide.reuse already took `slides`. Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
A bar series' own fill was read only when solid or a gradient: a pattern (a:pattFill) was dropped, and an a:noFill series was read but drawn in the palette's colour anyway, because the chart renderer turned every fill into one colour and fell back to the palette for anything but solid. PowerPoint for Mac draws the pattern, leaves an a:noFill bar empty and draws its outline (c:spPr/a:ln) where it has one: a synthetic column chart with a red-on-yellow dkDnDiag series, an empty series with a 3 pt blue outline and an empty one without, exported as PDF, shows exactly that, legend keys included. - The chart reader reads a:pattFill (dml::pattern, shared with shapes); the chart writer writes it back for an edited chart. - Bars and their legend keys paint with the series' or point's own fill: a colour, a preset pattern (pattern::fill) or nothing, then the series' solid outline at its width. - Lines, areas and markers, which take one colour, use a pattern's foreground colour instead of the palette's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Found while testing crates/model/src/chart.rs:775-794 (axis_scale); same pattern in nice_scale :817 Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com> Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This was referenced Oct 24, 2026
This was referenced Oct 24, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Integration batch 1 merges 35 contributor PRs. Each PR head is merged unchanged with a merge commit, and conflicts are resolved inside the merge commits. Our fixes are separate
Integration:commits. Merge this PR with "Create a merge commit" so that every included PR shows as merged.Included
Charts
Tables and rendering
Shapes and canvas
Slides and design
Slide show
Animation
Outline files (RTF, text)
Text editing
Dialogs and theme
Panes and status bar
Tests
Other
numeric_charrejects '+'-signed digits so '&#+65;' stays literal in HTML paste.Changes made while merging
keyboard()incrates/ui-egui/src/lib.rskeeps main's image-paste event scan and adds the PR's focus release; both use onemodalflag. Main'styping_goes_on_after_tab_in_a_text_boxand the PR's test both stay.select_para(Clamp text.selectParagraph paragraph index to avoid overflow #904's); engine: a hostile text selection can't drive paragraph commands past the body #813 adds the clamps in insert, paste, case and paragraph formatting.crates/model/src/chart.rskeeps main's waterfall value range besideseries_data_labels, and keeps main's CRLF line endings.chart.optionskeeps main's bin and subtotal helpers and addstextColor.transparentBackgroundand addsrtf.docs/animation-parity.md: the by-paragraph row from the PR, the triggers row from main.Batch fixes
chart.optionswithdataLabelsalso resets each series' own setting, so the chart-wide switch wins. Test:chart_options_data_labels_on_overrides_series_off.rtf_to_outlineno longer splits a multi-byte character after a\uor\'escape (it panicked on non-ASCII text). Test:non_ascii_text_after_escapes_does_not_panic.dateFormatonly when one was picked, so applying it keeps an existing format. Test:header_footer_apply_keeps_an_existing_date_format.a_long_language_name_leaves_the_notes_button_clickable.unwrap/expect, as the other test modules do.Checks
cargo xtask ciat9c31b567don Linux, with craft-fonts at the ref CI uses: all 8 steps passed. 1,866 tests passed, 6 skipped.Summary by CodeRabbit