///|
/// SVG user units and tick font sizes use the same point-scale coordinate system.
pub fn tick_space_from_length(
length : Double,
label_size : Double,
horizontal : Bool,
) -> Double {
let size = label_size * (if horizontal { 3.0 } else { 2.0 })
let points = length / 72.0 * 72.0
if size > 0.0 {
(points / size).floor()
} else {
2147483647.0
}
}
///|
pub fn Axis::set_tick_label_size(self : Axis, size : Double) -> Unit {
self.tick_label_size = Some(if size < 1.0 { 1.0 } else { size })
}
///|
pub fn Axis::tick_label_size(self : Axis) -> Double {
self.tick_label_size.unwrap_or(10.0)
}
///|
pub fn Axis::bind_tick_geometry(
self : Axis,
provider : () -> Double,
horizontal : Bool,
) -> Unit {
self.tick_length_provider = Some(provider)
self.tick_horizontal = horizontal
}
///|
pub fn Axis::set_tick_layout(
self : Axis,
length : Double,
horizontal : Bool,
active~ : Bool = false,
origin? : Double,
) -> Unit {
self.tick_layout_origin = origin
self.tick_layout_length = Some(length)
self.tick_layout_active = active
self.tick_horizontal = horizontal
if !active {
self.tick_layout_view = None
}
}
///|
pub fn Axis::clear_tick_layout(self : Axis) -> Unit {
self.tick_layout_active = false
self.tick_layout_view = None
}
///|
pub fn Axis::set_tick_view(self : Axis, lower : Double, upper : Double) -> Unit {
self.tick_layout_view = Some((lower, upper))
}
///|
pub fn Axis::tick_space_length(self : Axis) -> Double? {
if self.tick_layout_active {
return self.tick_layout_length
}
match self.tick_length_provider {
Some(provider) => Some(provider())
None => self.tick_layout_length
}
}
///|
pub fn Axis::get_tick_space(self : Axis) -> Double {
match self.tick_space_length() {
Some(length) =>
tick_space_from_length(
length,
self.tick_label_size(),
self.tick_horizontal,
)
None => 9.0
}
}
///|
pub fn Axis::bind_view_interval(
self : Axis,
provider : () -> (Double, Double) raise @core.DataError,
) -> Unit {
self.numeric_view_provider = Some(provider)
}
///|
/// Bind Scene's projected rendering view without replacing a user override.
pub fn Axis::bind_render_view_interval(
self : Axis,
provider : () -> (Double, Double) raise @core.DataError,
) -> Unit {
self.render_view_provider = Some(provider)
}
///|
fn Axis::has_view_interval_provider(self : Axis) -> Bool {
self.numeric_view_provider is Some(_) || self.render_view_provider is Some(_)
}
///|
/// Read the panel's own view for lifecycle operations, preserving user overrides.
/// A render projection is needed only when no view has been stored yet.
pub fn Axis::lifecycle_view_interval_checked(
self : Axis,
) -> (Double, Double) raise @core.DataError {
self.resolve_autoscale_view()
if self.numeric_view_provider is Some(provider) {
return provider()
}
if self.has_autoscale_view_provider() && self.uses_numeric_autoscale() {
return (self.stored_view.lower(), self.stored_view.upper())
}
if self.current_view_limits() is Some(view) {
return (view.lower(), view.upper())
}
match self.render_view_provider {
Some(provider) => provider()
None => (self.stored_view.lower(), self.stored_view.upper())
}
}
///|
pub fn Axis::view_interval_checked(
self : Axis,
) -> (Double, Double) raise @core.DataError {
if self.tick_layout_view is Some(view) {
return view
}
self.resolve_autoscale_view()
match self.numeric_view_provider {
Some(provider) => provider()
None => {
if self.has_autoscale_view_provider() && self.uses_numeric_autoscale() {
return (self.stored_view.lower(), self.stored_view.upper())
}
if self.render_view_provider is Some(provider) {
return provider()
}
let view = self.current_view_limits().unwrap_or(self.stored_view)
(view.lower(), view.upper())
}
}
}
///|
fn Axis::bind_maxn_context(self : Axis, value : @ticker.MaxNLocator) -> Unit {
value.bind_tick_space(fn() { self.get_tick_space() })
value.bind_view_interval(() => self.view_interval_checked())
}