Repository navigation
Conversation
df2f3c4 to
cc74716
Compare
AppKit draws the traffic lights 16 pt from the top of the window on macOS 27, but the title bar was 38 pt, so they sat above its centre line. On macOS the bar is now 32 pt, centred on them: content starts after the lights with the gap they keep from the top, and the Present button shrinks to 22 pt to keep a margin. Same approach as wordcraft #255 and gridcraft #323, with the light metrics measured on macOS 27. Linux, Windows and web are unchanged.
|
Thank you for the work here, @pierrevbc — a GridCraft data editor for charts is something we'd like. We can't merge this version, though, for these reasons:
An acceptable shape would keep chart data editing inside DeckCraft (or hand data to another app only through an explicit, user-initiated UI action with no paths taken from command params), without the CLAUDE.md and Cargo.lock changes. We'd be glad to review that. If you haven't already, come join us on Discord: https://discord.gg/artcraft |
Main keeps an unchanged chart's embedded workbook (storytold#355), but a chart made in DeckCraft, or one whose data or options changed, was written with no workbook: no part under ppt/embeddings/, no package relationship, no c:externalData. PowerPoint's Edit Data had nothing to open. - Export: an unchanged chart still goes back with its kept parts; an edited or new chart gets a workbook generated from its data, laid out where the chart part's formulas point (Sheet1, categories in A, one column per series), with its c:externalData. - Scatter series with different X values and multi-series bubble charts get their own columns instead of overlapping ranges. - ChartKept::workbook finds the kept workbook part. - The plain-chart fallback of an Office 2016 chart gets none: the workbook belongs to the chartEx part.
Every chart command clears the original chart part, so any edit (a new title, another chart type, a legend) made the export drop the chart's workbook for a generated one: extra sheets, formulas and formatting were lost even when the data had not changed. - Model: Chart.source, the series formulas of the imported chart part (name, categories or X values, values, bubble sizes) with the data as read. Commands keep it. - Export: when the data still fits the original ranges, the chart part is written with its original formulas. Unchanged data keeps the kept workbook byte for byte; changed data rewrites only the changed cells in it. Every other zip entry is copied as is. - Cells keep their style; a new name in a table header renames the table column; a value typed over a formula replaces it and drops the calculation chain; fullCalcOnLoad is set when the workbook holds formulas. - Series or points added or removed, a category chart turned into a scatter chart (or back), literal data, shared or array formulas, a table column name that would clash or is used by a structured reference: the workbook is generated from the chart data, as before.
…nd gallery - ChartType gains the variants PowerPoint and LibreOffice Impress offer as types of their own: points-only, stacked and 100% stacked lines with or without markers, 100% stacked area, exploded pie and doughnut, pie of pie and bar of pie, scatter with lines (and markers), radar with markers or points only, and the stock charts with an open price or a volume column (open-high-low-close, volume-high-low-close, volume-open-high-low-close). - Chart.variant (ChartVariant) holds what makes the other variants: stepped lines, explosion, the pie of pie split and second plot size, and 3-D (ThreeD: view angles, bar shape box/cylinder/cone/pyramid, series in depth). - ChartPreset::GALLERY lists the gallery by family (Column, Bar, Pie, Area, Line, XY (Scatter), Bubble, Radar, Stock, Combo with secondary-axis and stacked column-line combos, then main's Office 2016 types: Treemap, Sunburst, Histogram and Pareto, Box & Whisker, Waterfall, Funnel); apply() turns a chart into one, matches() tells which one a chart is. The Insert > Chart and Change Chart Type menus list it by family, the current type checked. - insert.chart and chart.type take a preset id (column3d, lineSmooth, stockOhlc, columnLineSecondary...) as well as the type names they took before. - Up/down bars stay main's Chart::up_down_bars: open-high-low-close presets set it, the type says which series is the open price. - PPTX: read and write every type and variant (c:ofPieChart, the 3-D groups with c:view3D, bar shape and series axis, explosion, the volume group of a stock chart, points-only series, a stepped-line extension), on top of main's trendlines, error bars, stock high-low lines, log axes, minor gridlines, reversed categories and chartEx. - Tests: every gallery entry round trips (type, variant, data, workbook, same part on a second export), odd data stays valid.
The chart data as a data sheet shows it, the commands that edit it, and the Edit Data window. The window, live title editing and type picker build on yefan911's storytold#195, re-expressed here without its CSV export and external spreadsheet launcher: the data stays inside DeckCraft. Model (chart_data): - One row per point, series names on the header row, and the columns each chart type needs: categories and one value column per series; scatter X values (shared, or one column per series) then Y values; bubble sizes; stock series labelled by role (volume, open, high, low, close); combo series by their own type. - Cells set from text (decimal comma, thousands separators, percent; an empty cell is a gap; a row past the last point adds one). Points and series inserted, removed and moved, point fills following their points; rows and columns switched; tab-separated blocks pasted at a cell (the table grows) and copied back. Notes for data a type can't show. Commands (Chart Design > Data), for the editor, the control channel and MCP alike: - chart.grid (query), chart.setCell, chart.paste, chart.insertRows / deleteRows / moveRow, chart.insertSeries / deleteSeries / moveSeries, chart.switchRowColumn, chart.title. - chart.data and insert.chart take X values and bubble sizes per series (or xValues for all), stock series by role, numbers as numeric text, and null for a gap. A data command that changes nothing leaves no undo step; commands carrying the same undoGroup in a row make one undo step, so typing in a cell updates the chart at each key and undoes at once. - insert.chart opens the data editor only when asked (editData, which the ribbon passes); double-clicking a chart opens it. Programmatic calls never open dialogs. Edit Data window (ui-egui chartdata): - Spreadsheet letters and row numbers, columns following the chart type, live update at each key, a cell that isn't a number yet stays red; Enter and the arrow keys move; paste from Excel or LibreOffice; toolbar to insert, delete and move rows and series, switch row and column, copy, undo and redo. Chart title field and a Type menu with the chart gallery. It reads the chart every frame, so undo and other commands show at once; large tables draw only the rows in view. Co-authored-by: yefan911 <nodmcaplsmilo@gmail.com>
An imported chart whose data changed shape got a new workbook: other sheets, formulas and formatting were lost as soon as a series or a point was added or removed. - The export now maps every cell the chart read before and every cell it reads now. Ranges grow or shrink from their first cell; a new series goes next to the last one, as far from it as that one is from the one before (or shares the X values or categories they all share); cells no longer read are cleared. Series in rows work as series in columns. - Cells read for the first time must be empty in the workbook, so nothing typed there is overwritten; otherwise, or when two series would need different values in one cell, the workbook is generated as before. - A table that covers exactly the chart data follows it: its range, its filter range and its columns (a new column is named after its header cell). Tables with a totals row, sorting or filters are left alone. - Formulas whose range did not change are written as they were read. Checked with LibreOffice: the workbooks of every edit in the tests open with the cells the chart formulas point to.
Model (chart_format) and commands for fonts, element boxes, legend, axes (bounds, units, log scale, reverse, number format, tick marks, label position and rotation, crossing, gridlines), data labels (parts, position, number format, separator), series (fill, line, markers, smooth, invert if negative, explosion), points, series options (gap width, overlap, hole size, first slice angle, vary colours), Change Colors palettes, Chart Styles, Quick Layout and Reset to Match Style. PPTX: spPr with gradients and dashes, txPr and rich title runs, legend overlay and box, full axes in schema order (logBase, orientation, gridline lines, numFmt, tick marks, tickLblPos, rotation, crosses, units), dLbls with parts, position (only where the chart type allows it), number format and separator, markers, invertIfNegative, explosion, dPt, firstSliceAng, palette colours, on every plot group the chart types write (primary and secondary axes, scatter X axes, 3-D groups, pie and bar of pie, stock charts). Main's chart fields for the same options are written as main writes them. The chart formatting is drawn in a later commit.
…in's chart fields Format pane and ribbon: - The Format pane's Chart Options picks a chart element (chart and plot area, title, legend, axes, axis titles, gridlines, data labels, each series) and shows its options: fill, border, font, legend position, axis bounds, units, log scale, reverse order, crossing, tick marks, label position and rotation, number format, gridlines, label parts and positions, gap width, overlap, pie angle and explosion, hole size, markers, smoothing and point colours. Its chart area page keeps storytold#195's basics: title, type (the chart gallery), elements, Edit Data. - Chart Design gains Add Chart Element, Quick Layout, Change Colors and Chart Styles; the new Chart Format tab holds the element picker, Format Selection, Reset to Match Style, and the element's fill, outline and text. - Scatter and bubble charts get X axis bounds. Formatting follows the chart type and variant: a marker on a type without markers turns it into its variant with markers (the series' own type in a combo); a pie or doughnut explosion is the exploded type's; point explosions follow points inserted, removed and moved; styles and layouts know every pie type and combo lines. Main's chart fields hold what both have, with no second copy in ChartFormat: the legend overlay, each series' type and axis in a combo, the value axes' bounds, major unit, number format, visibility, log base and minor gridlines (Chart::y_*, y2_*, y_log_base, minor_gridlines), a category axis' direction (Chart::cat_reversed), the chart and title text sizes, and number formats through main's numfmt (which now rounds halves away from zero, as spreadsheets do). chart.format.axis and the pane set them; the reader and writer read and write them where main does.
The chart renderer lays out the frame (chart box, title, legend) with the chart's formatting, then fills the plot for the chart's family. Types and variants: - Radar charts on a web of spokes and value rings: lines, markers, points only, filled. - Scatter and bubble charts on two value axes (the X axis from zero as main draws it), with bubble areas in proportion to their sizes. - Stock charts: high-low lines with close ticks, or up/down bars from open to close when the chart has them (main's up_down_bars), volume columns on their own axis. - Combo charts draw each series as its own type, with a secondary value axis on the right. - Exploded pies and doughnuts, doughnut rings per series, pie of pie and bar of pie with their connector lines. - 100% stacked lines and areas; stacked areas fill between series; area points sit on the category ticks; smooth (main's smoothed line) and stepped lines, marker shapes, line keys in the legend. - A simple depth for 3-D charts: boxes, cylinders, cones and pyramids for columns and bars, a tilted pie with its rim. Formatting: element fonts and boxes, legend positions and overlay, axis titles, value scales with fixed bounds, units, log base and reverse order, tick marks, minor and category gridlines, rotated tick labels, gradient and outlined bars with gap and overlap, invert if negative, marker symbols, data label parts and positions, pie first slice angle and explosion by series and by point, palettes. On top of main's chart drawing: waterfalls (increase, decrease and total colours, connectors), histograms and Pareto charts (the column chart of their bins), box and whisker boxes, trendlines with forecast slots, error bars, log axes and minor gridlines from main's fields, reversed categories, point fills and single-series colours by point, Office's automatic axis limits (main's axis_scale), and main's funnel, treemap, sunburst and region map layouts. The radar and stock drawing of radar.rs is replaced by the painter's, which also draws markers, points-only radars, volume and formatting. Tests: every gallery entry draws, variants differ, odd data (no series, NaN, huge values, thousands of points) never panics, formatting changes the picture on every type.
chart-type-parity.md rebased on main 9859da3 (main's Office 2016 types in the gallery, main's fields for what both have); checklist rows for chart type variants and chart formatting, Edit chart data and chart elements done, summary regenerated by cargo xtask parity; gaps, file-format-parity, ui-parity and the ROADMAP progress log.
|
Thanks for the review, and for the clear description of what an acceptable shape looks like. I've reworked the branch along those lines and force-pushed it:
|
…name says (.png, .jpg, .tif or .pam) (storytold#255) `render --out p1.png` wrote a netpbm PAM stream (P7) whatever the name, so a `.png` could not be opened by any PNG reader. The CLI already links the engine, whose export module encodes PNG, JPEG and TIFF, so the output format now follows the extension: `.png`, `.jpg`/`.jpeg` (quality 90), `.tif`/`.tiff`, and `.pam` for the raw stream as before. Any other name is refused up front, before the page is rendered, with the accepted list. `export::encode_image` wraps the three encoders behind `ImageFormat` so the CLI and `Exporter::image` share one match. Tests (apps/pdfcraft-cli/tests/render.rs): a `.png` gets the PNG signature and an IHDR with the rendered size; `.JPG` and `.tif` get JPEG/TIFF magic; `.pam` still gets the P7 header and the right number of bytes; `.bmp` fails with the message and writes nothing. Co-authored-by: wstock <1394687+wstock@users.noreply.github.com> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> Co-authored-by: Brandon Thomas <echelon@gmail.com>
Builds on #241 (chart workbooks; please land it first: this branch starts with #241's two code
commits, rebased on current
main) and on yefan911's #195 (the chart data window, live titleediting and the type picker), re-expressed in our own code and credited with a
Co-authored-bytrailer on the data editor commit. Rebased on
mainat 9859da3, after the chart work that landedsince the first version of this PR (NikitkaRa's chart series, #355, #150, #151, #157, #486, #502).
Review points addressed
chart.gridcraftis gone, with theCSV export (
Chart::to_csv/load_csv), the "Open in GridCraft" button, the hard-codedC:\Users\parra\gridcraftpath, thegridcraftonPATHand everystd::processandstd::env::temp_diruse from that code. Chart data is edited inside DeckCraft only: the Edit Datawindow and the
chart.*data commands.git diff origin/main..charts-v2adds nostd::process,Command::newortemp_dir.CLAUDE.md/AGENTS.mdchanges. Untouched.Cargo.lockchanges. Untouched: no dependency was added, nothing is downgraded.editing, the type picker, double-click to edit data, Edit Data opening after Insert ▸ Chart) is
written in the data editor commit, with yefan911 as co-author.
Commits
pptx: write a workbook for edited and new charts(PPTX export: a workbook for edited and new charts, updated in place when the data changes #241, rebased): main now keeps an unchangedchart's workbook (Charts: keep the embedded workbook when a chart is saved unchanged (#335) #355); an edited or new chart gets a workbook generated from its data, laid
out where the chart part's formulas point, so Edit Data in PowerPoint has something to open.
The workbook lives in main's
ChartKept(ChartKept::workbook()), not in a field of its own.pptx: update chart workbooks in place instead of rebuilding them(PPTX export: a workbook for edited and new charts, updated in place when the data changes #241, rebased):Chart::sourcekeeps the series formulas; an edited chart whose data still fits writes itsoriginal workbook with only the changed cells rewritten.
Charts: every LibreOffice chart type and variant in the model, PPTX and gallery.Charts: data editor for every chart type, and data commands(co-authored by yefan911).Charts: keep the workbook when series or points are added or removed.Charts: formatting model, chart.format.* commands, and PPTX.Charts: Format pane chart options, Chart Design/Format ribbon, and main's chart fields.Charts: draw every chart type, variant and formatting.Charts: progress docs and chart type parity.What this PR adds
Chart types
ChartTypegains the variants PowerPoint and Impress offer as types of their own (points-only,stacked and 100% lines with or without markers, 100% area, exploded pie and doughnut, pie of pie,
bar of pie, scatter with lines, radar with markers or points only, stock with an open price or a
volume column), and
Chart::variantholds stepped lines, explosion, the pie of pie split and 3-D(view angles, bar shape).
ChartPreset::GALLERY: 68 entries in 16 families (Column, Bar, Pie, Area, Line, XY, Bubble,Radar, Stock, Combo, then main's Office 2016 types: Treemap, Sunburst, Histogram and Pareto,
Box & Whisker, Waterfall, Funnel). Insert ▸ Chart and Change Chart Type show it by family, the
current one checked;
insert.chartandchart.typetake preset ids (column3d,lineSmooth,stockOhlc,columnLineSecondary…) and the old names.c:explosion,c:ofPieChart, thevolume group of a stock chart, 3-D groups and
c:view3D, combos with their secondary axis).Stepped lines have no OOXML element: a chart-space extension keeps them.
docs/chart-type-parity.mdaudits every type.Data
crates/model/src/chart_data.rs: each type's data as a table (categories; X shared or perseries and Y for scatter charts; sizes for bubbles; stock prices by role; series types in combos).
chart.grid,chart.setCell,chart.paste,chart.insertRows,chart.deleteRows,chart.moveRow,chart.insertSeries,chart.deleteSeries,chart.moveSeries,chart.switchRowColumn,chart.title;undoGroupmakes one undo step per edited cell;insert.chartandchart.datatake X values, sizes and stock roles.crates/ui-egui/src/chartdata.rs): spreadsheet letters and row numbers,columns following the chart type, live update at each key, paste from Excel or LibreOffice,
toolbar for rows and series, title field and a Type menu with the gallery. It opens from
Chart Design ▸ Edit Data, after Insert ▸ Chart (
editData, which only the ribbon passes) and on adouble-click; scripted calls never open it.
Formatting
crates/model/src/chart_format.rsandchart.format.element|legend|axis|labels|series|point|options,chart.colors,chart.style,chart.quickLayout,chart.resetStyle: fonts, fills, borders,axes (bounds, units, log scale, reverse, crossing, tick marks, label position and rotation,
number format, gridlines), data label parts and positions, series and point looks, markers,
explosion, palettes, styles and layouts.
Change Colors and Chart Styles; a Chart Format tab.
What comes from main, and how this PR builds on it
Where main now has the same feature, this branch keeps main's model fields and code and makes ours
set, write and draw them; there is no second copy:
ChartKept)write_kept, freshkeptNnameschartExreading and writing,chartex.rslayouts, histogram and box viewschartex::drawfor funnels, treemaps, sunbursts and mapsChart::up_down_bars,c:stockChartwriting (hiLowLines, upDownBars), the radar web layoutup_down_bars; the painter draws up/down bars when it is set. Our radar and stock painters (markers, points only, volume, formatting) replaceradar.rsdraw_trendlinesand its helperssmooth_path,varyColorsdefaultChart::cat_reversed,minor_gridlines,y_log_base,value_x_scalechart.format.axisand the Format pane set these fields (no copy inAxisFormatfor the value or category axis); the painter draws themdeckcraft_model::chart::axis_scaleclamp_soft)numfmtgains rounding of halves away from zero, as spreadsheets do (main already had scientificnotation; ours is gone). The PPTX reader no longer gives a stock chart
varyColors(ac:stockCharthas no such element).How it was tested
cargo xtask cipasses (fmt, pdf-deps, clippy, test, assets, layers, wasm) from an emptytarget dir: 1753 tests pass (6 ignored).
chart_embed.rsbuilds its fixtures without the workbook DeckCraft now writes for its own charts,and an edited chart is checked to get a workbook of its own data instead of none (never the stale
one). Main's render tests (trendlines, axis titles, point fills and bar widths, reversed bars,
combo axes, Office 2016 layouts, radar, stock and combo, degenerate frames, varied colours) pass.
export); formatting round trips on every family; workbooks follow added and removed series and
points; odd data stays valid.
editData,title, type, double-click), formatting commands setting main's fields, the soak.
deckcraft-cli run, rendered withdeckcraft-cli render, exported to PPTX, rendered again fromthe PPTX, and converted with LibreOffice. Not checked in PowerPoint or Excel.
Known limits
ChartKept, which a native.deckcraftsave does not store: afterreopening a
.deckcraft, an imported chart gets a workbook generated from its data.bubble scale, pie of pie connector lines, 3-D walls and floor; elements are picked in the pane,
not on the slide.
Related
(rebased on current
main, workbook in main'sChartKept), so this PR's own changes start atcommit 3.