Commit Graph
50 Commits
Author SHA1 Message Date
FredApps 94a8fb084a Merge pull request #1152 from vangel76/perf/chart-measure-allocs
Charts: label fitting and legend measuring avoid hundreds of text layouts per render (#1149)
2026-11-08 12:08:59 +01:00
vangel76andClaude Sonnet 5.5 9354fdb0c4 Chart: fit labels with a line break by a linear scan
The width of a prefix plus an ellipsis is not monotone when the text has a
line break, so the binary search could drop a label that fits. Also pass the
series index to plot_kind in the data table (upstream/main does not compile
without it).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 17:37:20 +01:00
vangel76 5f84fadaf5 Merge remote-tracking branch 'upstream/main' into c1152 2026-11-07 17:32:43 +01:00
vangel76andClaude Sonnet 5.5 c35878948a Merge upstream/main into fix/chart-work-budgets
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 17:31:27 +01:00
FredApps 505cae34c8 Merge pull request #1150 from vangel76/fix/chart-combo-logic-cleanup
Charts: one combo plot-kind function, no dead scale helpers (#1146)
2026-11-07 16:52:46 +01:00
vangel76andClaude Sonnet 5.5 bc1625248e Chart: cap category levels in the clean-data check, recompute overflowing moving-average windows, keep disjoint stacked hairline spans apart
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 16:25:23 +01:00
vangel76andClaude Sonnet 5.5 558312cb53 Merge upstream/main into c1155
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-05 05:20:58 +01:00
Francisco Herreraandalosslessdev 1fb191571b Charts: draw every doughnut series as a ring (#1827)
* Charts: draw every doughnut series as a ring (#1827)

* Charts: submit doughnut hole size and first slice angle when the drag ends (#1827)

---------

Co-authored-by: alosslessdev <alosslessdev@users.noreply.github.com>
2026-11-05 05:13:35 +01:00
vangel76andClaude Sonnet 5.5 0955378d8e Merge upstream/main into perf/chart-measure-allocs
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-05 01:50:34 +01:00
vangel76andClaude Sonnet 5.5 4fe0816ca0 Merge upstream/main into fix/chart-work-budgets
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-02 19:49:07 +01: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
vangel76 72e959f117 Merge upstream/main into fix/chart-work-budgets 2026-10-29 23:04:21 +01:00
vangel76 bc7e37fa7d Merge upstream/main into fix/chart-combo-logic-cleanup 2026-10-29 23:03:18 +01:00
Dylan M. Taylor 7fbf3f60c8 Refactor chart for strict Clippy checks 2026-10-28 10:52:53 +00:00
vangel76andClaude Sonnet 5.5 2fe8a33c5d Merge upstream/main into fix/chart-combo-logic-cleanup
render.rs was split into render/ modules on main; the plot-kind and fixed-scale cleanups are re-applied in the new modules.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 19:52:57 +01:00
vangel76andClaude Sonnet 5.5 2f36fe1b34 Merge upstream/main into perf/chart-measure-allocs
render.rs was split into render/ modules on main; the label-fitting, legend and treemap changes are re-applied in the new modules.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 19:51:31 +01:00
vangel76andClaude Sonnet 5.5 5144ebe1de Merge upstream/main into fix/chart-work-budgets
render.rs was split into render/ modules on main; the budget and hairline-bar changes are re-applied in render.rs and render/cartesian.rs.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 19:47:54 +01:00
aiongg 3813413b65 refactor(chart): move render.rs items to render/ 2026-10-26 19:04:52 +00:00
vangel76andClaude Sonnet 5.5 ee13457b2f Merge upstream/main into fix/chart-combo-logic-cleanup
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 23:55:05 +01:00
vangel76andClaude Sonnet 5.5 8ae680547a Merge upstream/main into fix/chart-work-budgets
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 23:54:05 +01:00
3b65b9af58 Sonar maintainability: explicit imports, method paths, smaller functions (#2412)
* Sonar: explicit imports, fn paths for closures, extract helpers for cognitive complexity

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Fix imports

* Fix serde imports

* Fix engine imports

* Fix clippy gate and a type error from the explicit-import change

Remove the unused imports the review flagged (cf.rs, pivot.rs, tables.rs, cmd/sheet.rs) so clippy -D warnings passes, and point the backstage parent-folder lookup at Path::to_str, which the fn-path rewrite had broken.

Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>

* Apply rustfmt to the explicit-import cleanup so the fmt gate passes

* Share the per-directory font path expansion in theme.rs

The candidate font lists repeated the same loop over the Linux font
directories in every role. A single helper expands them in the same order,
so the lookup order is unchanged and the duplicated blocks go away.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>

* Read the Windows fonts folder in one place in theme.rs

Every script-font list repeated the same WINDIR lookup. A single helper
returns the same path, so the duplicated lines go away without changing
which font files are tried.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>

* Build the light and dark UI palettes from one table in theme.rs

Tokens::light() and Tokens::dark() listed the same 40 colour fields in the
same order, so every change had to be made twice. A single palette
constructor takes the mode and picks each colour's value, so each field is
written once and both modes keep their exact colours.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>

* Share the Noto CJK font list between the CJK script lists in theme.rs

The Japanese, Simplified and Korean lists each repeated the same loop over
the Linux CJK directories with a different locale file name. One helper
builds that loop, and each list keeps its own face index, so the lookup
order is unchanged.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>

* Share Linux Noto directory list across Thai and Hebrew font lookups

Removes the duplicated directory arrays flagged by SonarCloud new-code duplication.

* Reuse in_dirs for Thai and Hebrew Noto font candidates

Removes the remaining duplicated per-directory loops flagged by SonarCloud.

* Share one font-list builder for the Thai and Hebrew faces

The two per-script functions repeated the same Windows, macOS, Linux and
variable-font setup. A single script_fonts helper now builds both lists,
keeping the candidate order unchanged, which clears the Sonar duplication gate.

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Codebuff <noreply@codebuff.com>
2026-10-25 12:32:02 -04:00
vangel76andClaude Sonnet 5.5 8f34c42e88 Merge upstream/main into fix/chart-combo-logic-cleanup
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 10:22:03 +01:00
vangel76andClaude Sonnet 5.5 6c32845740 Merge upstream/main into fix/chart-work-budgets
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 10:19:09 +01:00
dotCooCoo 0eb2f1f6f0 Charts: 100% Stacked Area draws each value as a share of its category's total
Insert > Line or Area and the All Charts list offer 100% Stacked Area,
and insert.chart and chart.set take it as type area with subtype
stacked100. Each series' area stacks on the ones before it as its
share of the category's total. When every series on the value axis is
100% stacked and no value is negative, the axis runs from 0% to 100%.
A blank cell counts as zero, and a category whose total is zero stays
on the baseline.

An XLSX area chart with percentStacked grouping now opens as 100%
stacked and is saved back as percentStacked. It used to open as a
stacked area and was saved as stacked.
2026-10-24 16:42:59 -07:00
vangel76 c0d0d909fc Merge remote-tracking branch 'upstream/main' into fix/chart-work-budgets
# Conflicts:
#	ROADMAP.md
#	crates/chart/src/resolve.rs
2026-10-22 19:43:16 +02:00
vangel76 562004f198 Merge remote-tracking branch 'upstream/main' into perf/chart-measure-allocs
# Conflicts:
#	ROADMAP.md
2026-10-22 19:35:18 +02:00
vangel76 7f8ac83dc3 Merge remote-tracking branch 'upstream/main' into fix/chart-combo-logic-cleanup
# Conflicts:
#	ROADMAP.md
#	crates/chart/src/tests.rs
2026-10-22 19:34:40 +02:00
aiongg c7fd66d807 Integration: track t12
# Conflicts:
#	ROADMAP.md
#	crates/calc/src/tests.rs
#	crates/chart/src/tests.rs
#	crates/engine/src/tests.rs
#	crates/xlsx/src/tests/mod.rs
#	docs/chart-parity.md
2026-10-22 03:05:03 +00:00
aiongg 1316d39865 Merge PR #1151: Charts: a huge trendline forecast no longer collapses the chart (#1148)
ROADMAP.md: all rows kept.
crates/chart/src/tests.rs: both tests kept.
2026-10-22 02:37:37 +00:00
webdevtodayjason ea3ef8faf7 Charts: honor box and whisker quartile methods
Keep exclusive and inclusive quartiles per series when drawing and saving XLSX, and expose the setting through chart.set.

Fixes #1453
2026-10-16 12:37:27 -05:00
vangel76andClaude Sonnet 5.5 4a1e6de303 Charts: work and memory are bounded by series x points; ranges are clipped before evaluation (#1147)
A chart keeps at most 2,000,000 series x points (every series and the
categories keep their first points), 16 trendlines per chart; columns and
bars narrower than 0.25 px are merged per pixel column; series references
are cut after the rows that can matter before calc evaluates them; the
moving average is linear; fit_trendline allocates no Vec per point;
render borrows clean data instead of cloning it.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-13 21:21:24 +02:00
vangel76andClaude Sonnet 5.5 79cfd9b151 Charts: label fitting and legend measuring avoid hundreds of text layouts per render (#1149)
Binary search in Ctx::fit, early exit of the side-legend column measure,
no per-point Vecs in value_range/squarify, treemap carries the value.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-13 21:14:02 +02:00
vangel76andClaude Sonnet 5.5 568dd58264 Charts: a huge trendline forecast no longer collapses the chart (#1148)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-13 21:13:05 +02:00
vangel76andClaude Sonnet 5.5 5cf0e24f43 Charts: one combo plot-kind rule, no fixed_scale helper, ticks off the step grid (#1146)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-13 21:12:43 +02:00
Lexx143andClaude Fable 5.1 209d2447d9 Charts: multi-level category axes, read, drawn and written back
A category range two or more columns wide beside a column of values (year beside month, Excel's
multiLvlStrRef) was read as one flat list: 36 rows in two columns became 72 categories, the
series sat in the left half of the plot and the years and months shared one row of labels.
Saving wrote the range as a plain strRef, so Excel lost the two-level axis too.

- gridcraft_core::category_levels: the shape of a category range beside its values (levels are
  columns when the points run down the rows, rows when they run along the columns; up to three
  outer levels), shared by the chart and xlsx crates.
- ChartData.category_levels: the outer levels, nearest the labels first, one entry per category,
  non-empty where a group starts. resolve fills it; a single column is unchanged.
- render: the outer levels in rows under the labels, a group's name centred under its categories
  with a separator at each boundary; in bar charts in columns beside the labels.
- xlsx: <c:cat> written as multiLvlStrRef with the level caches (innermost first), so the axis
  survives a round trip.

Tests in core (shapes), chart (resolve and layout for columns, bars and a row of values) and
xlsx (written XML, read-back, stability, a single column stays strRef). chart-parity, gaps § 4
and the ROADMAP progress log updated.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-13 17:30:01 +03:00
Brandon Thomas 7415d3b37d Merge main into #615
# Conflicts:
#	crates/chart/src/tests.rs
2026-10-13 00:07:34 -04:00
Brandon Thomas f075c63207 Merge main into #614
# Conflicts:
#	crates/chart/src/tests.rs
2026-10-13 00:07:31 -04:00
Brandon Thomas 588e289901 Merge main into #585
# Conflicts:
#	crates/chart/src/tests.rs
2026-10-13 00:07:17 -04:00
Brandon ThomasandClaude Opus 5.5 811a8a139a Fix-up: rustfmt the area-chart label condition after merging the chart PRs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 23:33:10 -04:00
Brandon Thomas e447fb8c90 Merge pull request #613 from MarekSpodBiedry:issue-545 2026-10-12 23:21:34 -04:00
MarekSpodBiedry 91873e03eb Draw data labels on area and stacked area charts (#545) 2026-10-12 08:38:28 +02:00
MarekSpodBiedry 389c539da4 Honour the gridlines flag on box-and-whisker and stock charts (#543) 2026-10-12 08:36:18 +02:00
MarekSpodBiedry 5fb854be9c Chart: color pie, doughnut, treemap and sunburst points from the workbook theme (#579) 2026-10-12 08:36:14 +02:00
MarekSpodBiedry 3301d59f44 Fix histogram counts disagreeing with interval labels on bin boundaries (#546) 2026-10-12 08:35:31 +02:00
MarekSpodBiedry d64b30b3a4 Funnel chart: hide value labels when data labels are off (#544) 2026-10-12 08:29:56 +02:00
neilcawseandClaude Opus 5.5 8ea2342703 Charts: read, write and draw trendlines
Model: Series.trendlines (Vec<Trendline>, serde default) with kind
(linear, exponential, logarithmic, polynomial 2..6, power, moving
average 2..255), name, forward/backward forecast, set intercept,
equation / R² display and line colour, width and dash.

XLSX: read and write <c:trendline> in CT_Trendline child order, placed
after dLbls and before the data references in line, bar, area, scatter,
bubble and stock series; unknown types are skipped.

Chart: least-squares fits (transformed for exp/log/power, skipping
non-positive values; polynomials via normal equations on centred,
scaled x with partial pivoting), moving averages, forecasts that widen
the category or x axis, clipping to the plot, equation and R² labels and
legend entries ("Linear (Sales)"). Degenerate data draws nothing.

Engine: chart.addElement element="trendline" adds (type, series, order,
period, forward, backward, displayEquation, displayRSquared) or removes
trendlines; document.inspect lists each chart's trendlines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 16:39:31 -04:00
Brandon ThomasandClaude Opus 5.5 c975b5dc75 Review fix-up: uniform, plot-clamped spline smoothing
smooth_run gives every segment the same number of sub-segments (cap / n, 1..100) so long
series are smoothed end to end within the point cap, and clamps the Catmull-Rom curve to
the plot box. List "smooth" in chart.addElement's params doc, drop the smooth_demo
example, and use the test sheet's own name in series refs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 12:21:35 -04:00
justinjohn0306 69709bd458 Line charts: smooth (spline) curves (issue #52)
Add support for Excel's "smoothed line" chart style. The smooth flag flows
model -> resolve -> chart render, persists through XLSX (<c:smooth val="1"/>),
and is toggled via the chart.addElement "smooth" element.

Rendering interpolates each gap-free run with a uniform Catmull-Rom spline
(0.5 tangent scale, 100 sub-segments per data segment), so the curve passes
through every data point and rounds the vertices — matching Excel's observed
behaviour. Long runs are still decimated before smoothing.

- model: Series.smooth (#[serde(default)], so old workbooks load unchanged)
- chart: SeriesData.smooth; smooth_run + catmull in render; wired through
  resolve and the sanitize() copy; draw_runs takes the flag (line + scatter)
- engine: chart.addElement element="smooth"
- xlsx: read/write <c:smooth val> instead of hard-coding val="0"
- tests: smooth_line_adds_interpolated_points_and_keeps_endpoints,
  smooth_line_splits_at_gaps, smooth_line_setting_round_trips
- examples/smooth_demo.rs: generates a straight+smooth side-by-side workbook

cargo xtask ci: all 7 steps pass.
2026-10-10 00:09:12 +05:30
Brandon ThomasandClaude Opus 5.5 488e12de31 Rename SheetCraft to GridCraft everywhere (crates, apps, bundle ids, packaging, docs)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 01:39:08 -04:00
Brandon ThomasandClaude Opus 5.5 beb353943e M1: Excel-style egui UI, desktop app, chart renderer, MCP server, CLI, release packaging
- ui-egui: title bar with QAT, full ribbon (Home/Insert/Draw/Page Layout/Formulas/Data/
  Review/View/Automate + Table/Chart Design), formula bar with Name Box, virtualised grid
  (frozen panes, overflow, borders, CF data bars/scales/icons, tables, sparklines, filter
  buttons, charts/pictures/shapes), in-cell editor with point mode, reference colouring,
  autocomplete and argument hints, sheet tabs, status bar, dialogs, control channel
- apps/sheetcraft: desktop app (control server, file dialogs, prefs, drag & drop)
- chart: toolkit-free chart layout/rendering for 25 chart kinds + sparklines + rasteriser
- mcp + sheetcraft-cli: MCP server (headless or bridged) and CLI (info/convert/eval/cat/run/mcp)
- xtask (ci/layers/assets/wasm/version/parity), release workflows, packaging, placeholder icon
- automatic row heights

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 00:00:15 -04:00