Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 33 additions & 2 deletions egui_plot/src/axis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use std::fmt::Debug;
use std::ops::RangeInclusive;
use std::sync::Arc;

use egui::Color32;
use egui::FontId;
use egui::Pos2;
use egui::Rangef;
use egui::Rect;
Expand Down Expand Up @@ -62,6 +64,8 @@ pub struct AxisHints<'a> {
pub(super) min_thickness: f32,
pub(super) placement: Placement,
pub(super) label_spacing: Rangef,
pub(super) tick_label_color: Option<Color32>,
pub(super) tick_label_font: Option<FontId>,
}

impl<'a> AxisHints<'a> {
Expand Down Expand Up @@ -89,6 +93,8 @@ impl<'a> AxisHints<'a> {
Axis::X => Rangef::new(60.0, 80.0), // labels can get pretty wide
Axis::Y => Rangef::new(20.0, 30.0), // text isn't very high
},
tick_label_color: None,
Copy link
Contributor

Choose a reason for hiding this comment

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

whats the default?
maybe set it to a default which we already use

Copy link
Contributor

Choose a reason for hiding this comment

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

else use Default::default()

Copy link
Author

@TommiKabelitz TommiKabelitz Nov 24, 2025

Choose a reason for hiding this comment

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

Currently the default is whatever is in ui.visuals().text_color() when the plot is actually rendered because this function

/// Determine a color from a 0-1 strength value.
pub fn color_from_strength(ui: &Ui, strength: f32) -> Color32 {
    let base_color = ui.visuals().text_color();
    base_color.gamma_multiply(strength.sqrt())
}

is called to determine the color when the plot is shown.

I am still just calling this function when color is None so the behavior is not changing. I could potentially move the default to the instantiation of AxisHints, but that would change the behavior in cases where ui.visuals().text_color() is changed between creation of the axes and showing the plot.

Copy link
Contributor

Choose a reason for hiding this comment

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

works for me

tick_label_font: None,
}
}

Expand Down Expand Up @@ -157,6 +163,20 @@ impl<'a> AxisHints<'a> {
self.label_spacing = range.into();
self
}

/// Set the color of the axis tick labels.
#[inline]
pub fn tick_label_color(mut self, color: impl Into<Color32>) -> Self {
self.tick_label_color = Some(color.into());
self
}

/// Set the font of the axis tick labels.
#[inline]
pub fn tick_label_font(mut self, font: FontId) -> Self {
self.tick_label_font = Some(font);
self
}
}

#[derive(Clone)]
Expand Down Expand Up @@ -274,8 +294,19 @@ impl<'a> AxisWidget<'a> {
// Fade in labels as they get further apart:
let strength = remap_clamp(spacing_in_points, label_spacing, 0.0..=1.0);

let text_color = colors::color_from_strength(ui, strength);
let galley = painter.layout_no_wrap(text, font_id.clone(), text_color);
let text_color = if let Some(color) = self.hints.tick_label_color {
color.gamma_multiply(strength.sqrt())
} else {
super::color_from_strength(ui, strength)
};

let label_font_id = self
.hints
.tick_label_font
.clone()
Copy link
Contributor

Choose a reason for hiding this comment

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

2x clones?
Is there something else possible?

Copy link
Author

@TommiKabelitz TommiKabelitz Nov 24, 2025

Choose a reason for hiding this comment

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

I could be mistaken, but I don't think so. Cloning FontId is pretty cheap as it is just an f32 and the FontFamily enum which is an Arc.

I think you need to clone in both cases as layout_no_wrap expects an owned FontId. When the font has not been specified we use the global one so you need to clone. When it is specified, you have to clone as we only have a reference to self and so cannot move it out of the shared reference.

The implications of changing layout_no_wrap to accept an owned value look to be significant at a glance.

.unwrap_or(font_id.clone());

let galley = painter.layout_no_wrap(text, label_font_id, text_color);
let galley_size = match axis {
Axis::X => galley.size(),
Axis::Y => galley.size() + 2.0 * SIDE_MARGIN * Vec2::X,
Expand Down