Skip to content

Fixes #2888 Add manual major interval and minor count override for chart axes#2889

Merged
rwmcintosh merged 4 commits into
V13from
2888-axis-major-interval-minor-count
Jun 16, 2026
Merged

Fixes #2888 Add manual major interval and minor count override for chart axes#2889
rwmcintosh merged 4 commits into
V13from
2888-axis-major-interval-minor-count

Conversation

@rwmcintosh

@rwmcintosh rwmcintosh commented Jun 15, 2026

Copy link
Copy Markdown
Member

Fixes #2888

Summary

Adds two optional, per-axis settings that let the user override the automatic tick calculation for chart axes, mirroring how Min/Max already work:

  • Major Interval (float?) → DevExpress NumericScaleOptions.GridSpacing (spacing between major gridlines, in axis units).
  • Minor Count (int?) → DevExpress Axis.MinorCount (number of minor ticks between two major ticks).

Behavior

  • Both are nullable and independent; when set they override the automatic calculation, and clearing a field re-engages auto (same UX as Min/Max).
  • Applied to linearly-scaled axes only — logarithmic axes keep their decade gridlines and fixed minor count.
  • MajorInterval is reset when the axis unit changes (it is expressed in axis units, like Min/Max); MinorCount is unit-independent and preserved.
  • Editable both in the axis-options grid and the single-axis settings dialog.
  • Persisted in project XML and snapshots, and carried by chart templates / Clone.
  • Validation: MajorInterval must be > 0; MinorCount must be within the range DevExpress accepts (greater than 0 and less than 100). The binder also falls back to the automatic count for any out-of-range value, so an invalid value can never crash the chart.

Tests

  • Domain validation and UpdateFrom (AxisSpecs)
  • Snapshot round-trip (AxisMapperSpecs) and XML round-trip (AxisXmlSerializerSpecs + AssertForSpecs.AreEqualAxis)
  • Binder behavior (AxisBinderSpecs): override applied on linear axes, falls back to auto when cleared or out of range, ignored on log axes

All green: dotnet build 0 errors; Core and UI axis specs pass.

image image

🤖 Generated with Claude Code

Summary by CodeRabbit

Summary by CodeRabbit

Release Notes

  • New Features
    • Added chart axis options for major interval (gridline/tick spacing) and minor ticks (ticks between major ticks).
    • Extended axis settings UI with new fields to configure these values.
  • Validation
    • Added rules to ensure major interval > 0 and minor ticks is within the allowed range.
  • Updates
    • Updated axis settings, mapping, and serialization so these values persist and reload correctly.
  • Tests
    • Added/extended coverage for interval/tick behavior and validation.

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 22d994b0-5926-4939-83c8-a8a756b7152d

📥 Commits

Reviewing files that changed from the base of the PR and between e21b373 and 866768b.

📒 Files selected for processing (15)
  • src/OSPSuite.Assets/UIConstants.cs
  • src/OSPSuite.Core/Chart/Axis.cs
  • src/OSPSuite.Core/Serialization/Chart/AxisXmlSerializer.cs
  • src/OSPSuite.Core/Snapshots/Axis.cs
  • src/OSPSuite.Core/Snapshots/Mappers/AxisMapper.cs
  • src/OSPSuite.Presentation/Presenters/Charts/AxisSettingsPresenter.cs
  • src/OSPSuite.UI/Binders/AxisBinder.cs
  • src/OSPSuite.UI/Views/Charts/AxisSettingsView.cs
  • src/OSPSuite.UI/Views/Charts/SingleAxisSettingsView.Designer.cs
  • src/OSPSuite.UI/Views/Charts/SingleAxisSettingsView.cs
  • tests/OSPSuite.Core.IntegrationTests/Serializers/AxisXmlSerializerSpecs.cs
  • tests/OSPSuite.Core.Tests/Domain/AxisSpecs.cs
  • tests/OSPSuite.Core.Tests/Mappers/AxisMapperSpecs.cs
  • tests/OSPSuite.HelpersForTests/AssertForSpecs.cs
  • tests/OSPSuite.UI.Tests/Binders/AxisBinderSpecs.cs
🚧 Files skipped from review as they are similar to previous changes (10)
  • src/OSPSuite.Core/Snapshots/Mappers/AxisMapper.cs
  • src/OSPSuite.UI/Views/Charts/SingleAxisSettingsView.cs
  • tests/OSPSuite.Core.IntegrationTests/Serializers/AxisXmlSerializerSpecs.cs
  • tests/OSPSuite.HelpersForTests/AssertForSpecs.cs
  • src/OSPSuite.Presentation/Presenters/Charts/AxisSettingsPresenter.cs
  • tests/OSPSuite.Core.Tests/Mappers/AxisMapperSpecs.cs
  • tests/OSPSuite.UI.Tests/Binders/AxisBinderSpecs.cs
  • tests/OSPSuite.Core.Tests/Domain/AxisSpecs.cs
  • src/OSPSuite.UI/Views/Charts/AxisSettingsView.cs
  • src/OSPSuite.UI/Binders/AxisBinder.cs

📝 Walkthrough

Walkthrough

Adds optional MajorInterval (float?) and MinorTicks (int?) properties to the Axis model with validation rules, constants, and UpdateFrom support. These properties are persisted via XML serialization and snapshots, exposed in the axis settings presenter and UI views, rendered by AxisBinder for linear axes, and covered by unit, integration, and UI tests.

Changes

Axis MajorInterval and MinorTicks Feature

Layer / File(s) Summary
Axis model contracts, constants, and validation messages
src/OSPSuite.Assets/UIConstants.cs, src/OSPSuite.Core/Chart/Axis.cs
Adds MIN_MINOR_TICKS/MAX_MINOR_TICKS constants, nullable MajorInterval and MinorTicks public properties with backing fields, constructor initialization, UpdateFrom copying, and business validation rules. Adds UI caption strings and validation message strings in UIConstants.
XML serialization and snapshot persistence
src/OSPSuite.Core/Serialization/Chart/AxisXmlSerializer.cs, src/OSPSuite.Core/Snapshots/Axis.cs, src/OSPSuite.Core/Snapshots/Mappers/AxisMapper.cs
Maps MajorInterval and MinorTicks in the XML serializer, adds them as nullable snapshot properties, and updates AxisMapper to copy values in both MapToSnapshot and MapToModel directions.
Presentation: AxisOptionsColumns and UnitChanged reset
src/OSPSuite.Presentation/Presenters/Charts/AxisSettingsPresenter.cs
Adds MajorInterval and MinorTicks to AxisOptionsColumns, registers column captions, and resets MajorInterval to null when the axis unit changes.
AxisBinder manual tick rendering
src/OSPSuite.UI/Binders/AxisBinder.cs
Introduces helpers to detect manual major/minor tick settings, validate MinorTicks within OSPAxis bounds, and apply NumericScaleOptions/minor tick configuration for linear axes, with fallback to auto settings for invalid or absent values. Logarithmic axes bypass this path.
AxisSettingsView and SingleAxisSettingsView UI wiring
src/OSPSuite.UI/Views/Charts/AxisSettingsView.cs, src/OSPSuite.UI/Views/Charts/SingleAxisSettingsView.cs, src/OSPSuite.UI/Views/Charts/SingleAxisSettingsView.Designer.cs
Adds bound grid columns in AxisSettingsView, adds majorIntervalTextBox/minorTicksTextBox controls and layout items in the designer, and wires bindings and captions in SingleAxisSettingsView.
Tests: model, mapper, serializer, binder, and helpers
tests/OSPSuite.Core.Tests/Domain/AxisSpecs.cs, tests/OSPSuite.Core.Tests/Mappers/AxisMapperSpecs.cs, tests/OSPSuite.HelpersForTests/AssertForSpecs.cs, tests/OSPSuite.Core.IntegrationTests/Serializers/AxisXmlSerializerSpecs.cs, tests/OSPSuite.UI.Tests/Binders/AxisBinderSpecs.cs
Adds validation specs for rule boundaries, UpdateFrom copy assertions, mapper round-trip observations, AreEqualAxis helper assertions, XML serialization integration test with values, and five AxisBinder tick-behavior scenarios covering linear and logarithmic axis cases.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant SingleAxisSettingsView
  participant AxisSettingsPresenter
  participant Axis
  participant AxisBinder
  participant OSPAxis as DevExpress OSPAxis

  User->>SingleAxisSettingsView: Enter MajorInterval / MinorTicks
  SingleAxisSettingsView->>Axis: set MajorInterval, MinorTicks
  User->>AxisSettingsPresenter: Change axis unit
  AxisSettingsPresenter->>Axis: MajorInterval = null
  AxisBinder->>Axis: read MajorInterval, MinorTicks
  AxisBinder->>AxisBinder: hasManualTickSettings?
  alt Linear axis with manual settings
    AxisBinder->>OSPAxis: NumericScaleOptions.GridSpacing = MajorInterval
    AxisBinder->>OSPAxis: Tickmarks.MinorVisible, MinorCount
  else No manual settings or logarithmic
    AxisBinder->>OSPAxis: AutoGrid = true, default MinorCount
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • msevestre
  • Yuri05

Poem

🐇 Hoppity hop, the gridlines align,
Major intervals, precisely defined!
Minor ticks count from one to ninety-nine,
Unit changed? The interval resigns.
Log axes sleep — they know their place,
Two new fields now tick with grace! ✨

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding manual major interval and minor count overrides for chart axes, directly matching the issue reference and PR objectives.
Linked Issues check ✅ Passed The PR implements all acceptance criteria from issue #2888: adding nullable MajorInterval and MinorTicks properties, validation enforcement, UI bindings, serialization support, and proper behavior for linear vs logarithmic axes with unit-specific handling.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing major interval and minor count overrides for chart axes; no unrelated modifications were introduced.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 2888-axis-major-interval-minor-count

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@rwmcintosh rwmcintosh self-assigned this Jun 15, 2026
@rwmcintosh

Copy link
Copy Markdown
Member Author

@coderabbitai full review please

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

@rwmcintosh Sure! I'll kick off a full review of the PR right away.

✅ Action performed

Full review finished.

@rwmcintosh rwmcintosh requested review from Yuri05 and msevestre June 15, 2026 18:44
@rwmcintosh rwmcintosh added this to v13 Jun 15, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/OSPSuite.UI.Tests/Binders/AxisBinderSpecs.cs (1)

122-205: ⚡ Quick win

Add a regression spec for invalid MajorInterval fallback.

Current scenarios validate invalid MinorCount, but there is no equivalent test for MajorInterval <= 0 reverting to automatic grid. Please add one to lock the expected fallback behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/OSPSuite.UI.Tests/Binders/AxisBinderSpecs.cs` around lines 122 - 205,
Add a new test class (similar in structure to
When_refreshing_adapter_and_a_linear_axis_has_an_out_of_range_minor_count) to
verify the fallback behavior when MajorInterval is invalid (<=0). In the Context
method, set the axis MajorInterval to an invalid value such as 0 or a negative
number. In the Because method, call RefreshRange with the same parameters as
other similar tests. Add an Observation method that verifies the axis
automatically falls back to automatic grid behavior by checking that AutoGrid is
enabled (ShouldBeTrue) rather than throwing an error. This test should be placed
after the out-of-range minor count scenario and before the logarithmic axis
scenario to maintain the logical test grouping.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/OSPSuite.UI/Binders/AxisBinder.cs`:
- Line 217: The hasManualTickSettings property at line 217 checks only
Axis.MajorInterval.HasValue without validating that the value is greater than
zero, and the same issue occurs at line 226. Create a new validation property
similar to the existing hasValidMinorCount pattern that checks both HasValue and
validates that MajorInterval is greater than zero, then update the
hasManualTickSettings property and the condition at line 226 to use this new
validation method instead of just checking HasValue. This will ensure invalid
MajorInterval values don't propagate to GridSpacing and the binder gracefully
falls back to automatic grid mode.

---

Nitpick comments:
In `@tests/OSPSuite.UI.Tests/Binders/AxisBinderSpecs.cs`:
- Around line 122-205: Add a new test class (similar in structure to
When_refreshing_adapter_and_a_linear_axis_has_an_out_of_range_minor_count) to
verify the fallback behavior when MajorInterval is invalid (<=0). In the Context
method, set the axis MajorInterval to an invalid value such as 0 or a negative
number. In the Because method, call RefreshRange with the same parameters as
other similar tests. Add an Observation method that verifies the axis
automatically falls back to automatic grid behavior by checking that AutoGrid is
enabled (ShouldBeTrue) rather than throwing an error. This test should be placed
after the out-of-range minor count scenario and before the logarithmic axis
scenario to maintain the logical test grouping.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1289cb29-83a6-49c5-843b-8d9457518d63

📥 Commits

Reviewing files that changed from the base of the PR and between 6933cfe and e21b373.

📒 Files selected for processing (15)
  • src/OSPSuite.Assets/UIConstants.cs
  • src/OSPSuite.Core/Chart/Axis.cs
  • src/OSPSuite.Core/Serialization/Chart/AxisXmlSerializer.cs
  • src/OSPSuite.Core/Snapshots/Axis.cs
  • src/OSPSuite.Core/Snapshots/Mappers/AxisMapper.cs
  • src/OSPSuite.Presentation/Presenters/Charts/AxisSettingsPresenter.cs
  • src/OSPSuite.UI/Binders/AxisBinder.cs
  • src/OSPSuite.UI/Views/Charts/AxisSettingsView.cs
  • src/OSPSuite.UI/Views/Charts/SingleAxisSettingsView.Designer.cs
  • src/OSPSuite.UI/Views/Charts/SingleAxisSettingsView.cs
  • tests/OSPSuite.Core.IntegrationTests/Serializers/AxisXmlSerializerSpecs.cs
  • tests/OSPSuite.Core.Tests/Domain/AxisSpecs.cs
  • tests/OSPSuite.Core.Tests/Mappers/AxisMapperSpecs.cs
  • tests/OSPSuite.HelpersForTests/AssertForSpecs.cs
  • tests/OSPSuite.UI.Tests/Binders/AxisBinderSpecs.cs

Comment thread src/OSPSuite.UI/Binders/AxisBinder.cs Outdated
@rwmcintosh rwmcintosh merged commit 844d652 into V13 Jun 16, 2026
2 checks passed
@rwmcintosh rwmcintosh deleted the 2888-axis-major-interval-minor-count branch June 16, 2026 17:39
@github-project-automation github-project-automation Bot moved this to Done in v13 Jun 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Allow manual override of axis major tick interval and minor tick count

2 participants