Skip to content

Issue #583: confirm before overwriting in the Save As dialog#1008

Merged
timmolter merged 1 commit into
developfrom
issue-583-save-as-overwrite-confirmation
Jul 20, 2026
Merged

Issue #583: confirm before overwriting in the Save As dialog#1008
timmolter merged 1 commit into
developfrom
issue-583-save-as-overwrite-confirmation

Conversation

@timmolter

Copy link
Copy Markdown
Member

Fixes #583.

Right-click → Save As… silently overwrote an existing file, with no confirmation. This affected every chart type, not just PieChart as reported.

Cause

Swing's JFileChooser has no built-in overwrite confirmation — there is no setOverwriteConfirmation flag, and the JDK 21 javadoc has no method, field, or client property for it. showSaveAsDialog() went straight from APPROVE_OPTION to the encoder, which opens a truncating FileOutputStream.

Fix

  • OverwriteConfirmingFileChooser — overrides approveSelection() to prompt when the target exists. This is the standard Swing idiom; the javadoc documents approveSelection as the hook the UI calls precisely so it can be intercepted. Declining returns without calling super, leaving the dialog open so a different name can be picked.
  • resolveSaveTarget(File, FileFilter) — resolves the path that will actually be written.
  • suffixOf(FileFilter) — reads the suffix off SuffixSaveFilter instead of comparing description strings ("*.jpg,*.JPG"), removing seven brittle literals.

The part that needed care

The check cannot run against the raw selection. Users typically type chart and pick the format from the drop-down, and the encoder appends the extension itself — so checking getSelectedFile().exists() would miss the most common case entirely.

Resolution therefore calls the same addFileExtension method the matching encoder calls. This is not incidental: BitmapEncoder and VectorGraphicsEncoder differ (< vs <= on the length guard, and only the bitmap one normalizes an existing extension to lowercase). Reimplementing the rule would have reintroduced the bug on edge cases.

Worth noting that JavaFX's FileChooser — which inherits confirmation "for free" from native dialogs — has open bugs for exactly this: JDK-8124315 (no confirmation on Windows when an extension filter is used and the extension is omitted) and JDK-8123775 (GTK ignores the extension when deciding). The platforms that got this for free still got the extension case wrong.

Testing

New XChartPanelSaveTargetTest — 5 cases covering extension-omitted, no-duplication, encoder agreement, and the null-filter fallback. No XChartPanel is constructed, per the headless-CI constraint. Full suite: 146 pass. The dialog behavior itself was verified manually.

Deliberately out of scope

  • Did not migrate to ChartEncoder.saveChart. It is the modern non-deprecated API and would collapse the switch to one line, but its raster path is a plain ImageIO.write with no quality control, while the JPG branch uses saveJPGWithQuality(..., 1.0f). Switching would silently degrade JPEG output. Worth revisiting if ChartEncoder gains a quality parameter.
  • showExportAsDialog() still overwrites CSV exports silently. Same class of bug, but it writes N files into a chosen directory, so a per-file prompt is the wrong shape and it needs its own design. Happy to file separately.

🤖 Generated with Claude Code

Save As silently overwrote an existing file. Swing's JFileChooser has no
built-in overwrite confirmation, so add one by overriding approveSelection;
declining leaves the dialog open so a different name can be chosen.

The check has to run against the extension-resolved path, not the raw
selection: the user typically types "chart" and picks the format from the
filter drop-down, and the encoder appends the extension itself, so checking
the selection would miss the most common case. Resolution reuses the very
same addFileExtension method the matching encoder calls, since the bitmap
and vector implementations differ slightly and reimplementing the rule
would reintroduce the bug on edge cases.

Also drives the encoder dispatch off the filter's suffix instead of
comparing its description string ("*.jpg,*.JPG"), which the path
resolution needed anyway.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@timmolter
timmolter merged commit 5ae95db into develop Jul 20, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Overwriting when saving PieChart graphic

1 participant