///|
/// Return the copied converter captured when this axis entered date mode.
pub fn Axis::date_converter(self : Axis) -> @date.DateConverter? {
self.date_converter.map(converter => converter.copy())
}
///|
/// Check converter defaults against this axis' explicit unit without changing
/// the axis. Shared-axis callers use this to validate the entire group first.
pub fn Axis::validate_date_converter(
self : Axis,
converter? : @date.DateConverter,
) -> Unit raise @core.DataError {
if self.scale.is_nonlinear() ||
self.category is Some(_) ||
self.get_category_units() is Some(_) {
raise @core.DataError::InvalidTicks(
message="date converter requires a linear non-category axis",
)
}
ignore(
self.date_converter_info(
converter.unwrap_or(
self.date_converter.unwrap_or(@date.default_date_converter()),
),
),
)
}
///|
/// Replace the default date conversion/formatting configuration. Explicit
/// locators and fixed ticks/labels remain installed. Validation is atomic.
pub fn Axis::set_date_converter(
self : Axis,
converter : @date.DateConverter,
) -> Unit raise @core.DataError {
// Prepare the complete configuration before changing the axis.
let info = self.date_converter_info(converter)
self.set_date_format("")
self.date_converter = Some(converter.copy())
// Retain the convenience getter snapshot even with an explicit locator.
// The installed major role still decides which locator is queried.
self.tickers.automatic_date_locator = Some(
self.make_default_date_locator(info),
)
if self.date_timezone_is_default {
self.date_timezone = info.major_locator().timezone()
self.date_offset_minutes = info.major_locator().offset_minutes()
}
if self.tickers.major_formatter_default {
self.tickers.major_formatter_kind = Date
self.tickers.date_formatter = Some(info.major_formatter())
self.tickers.date_formatter_default = true
}
self.sync_default_date_formatter()
self.capture_date_units_extension(force=true)
}
///|
fn Axis::explicit_date_timezone(self : Axis) -> @date.DateTimeZone {
self.date_timezone.unwrap_or(
try! @date.fixed_timezone(self.date_offset_minutes),
)
}
///|
fn Axis::date_converter_info(
self : Axis,
converter : @date.DateConverter,
) -> @date.DateAxisInfo raise @core.DataError {
let unit = if self.date_timezone_is_default {
None
} else {
Some(self.explicit_date_timezone())
}
self.checked_date_axisinfo(converter, unit?)
}
///|
fn Axis::checked_date_axisinfo(
_self : Axis,
converter : @date.DateConverter,
unit? : @date.DateTimeZone,
) -> @date.DateAxisInfo raise @core.DataError {
converter.axisinfo(unit?) catch {
@date.DateError::InvalidDate(message~)
| @date.DateError::InvalidFormat(message~) =>
raise @core.DataError::InvalidTicks(message~)
}
}
///|
// Preserve the atomic convenience configuration for subsequent producers.
// Direct update_units may still select a registry converter: this captures the
// existing typed snapshot without a Python explicit-converter assignment/event.
fn Axis::capture_date_units_extension(
self : Axis,
force~ : Bool = false,
) -> Unit {
if !force &&
(
self.units_state.explicit ||
self.units_state.converter is Some(DefaultDate)
) {
return
}
if self.date_converter is Some(converter) {
self.units_state.converter = Some(
AxisUnitConverter::ExplicitDate(converter),
)
self.units_state.explicit = false
self.units_state.unit = if self.date_timezone_is_default {
None
} else {
Some(AxisUnitTag::Date(self.explicit_date_timezone()))
}
}
}