Skip to main content

egui_charts/ui_kit/list_item/
property_content.rs

1//! PropertyContent - Key-value pair display for list items
2
3use crate::localization as l10n;
4use egui::{Color32, Response, Role, Ui, WidgetInfo};
5
6use super::content::{ContentContext, ListItemContent};
7
8/// Key-value pair content for displaying properties
9///
10/// # Example
11///
12/// ```
13/// # use egui::Color32;
14/// # use egui_charts::ui_kit::list_item::{ListItem, PropertyContent};
15/// # egui::__run_test_ui(|ui| {
16/// ListItem::new()
17///     .show(ui, PropertyContent::new("Price", "$1,234.56")
18///         .value_color(Color32::GREEN));
19/// # });
20/// ```
21pub struct PropertyContent {
22    label: String,
23    value: String,
24    value_color: Option<Color32>,
25    label_width: Option<f32>,
26}
27
28impl PropertyContent {
29    /// Create new property content with label and value
30    pub fn new(label: impl Into<String>, value: impl Into<String>) -> Self {
31        Self {
32            label: label.into(),
33            value: value.into(),
34            value_color: None,
35            label_width: None,
36        }
37    }
38
39    /// Set a custom color for the value
40    #[must_use]
41    pub fn value_color(mut self, color: Color32) -> Self {
42        self.value_color = Some(color);
43        self
44    }
45
46    /// Set a fixed width for the label column
47    #[must_use]
48    pub fn label_width(mut self, width: f32) -> Self {
49        self.label_width = Some(width);
50        self
51    }
52}
53
54impl ListItemContent for PropertyContent {
55    fn ui(self, ui: &mut Ui, context: &ContentContext<'_>) -> Response {
56        let egui_visuals = ui.style().visuals.clone();
57
58        // Label is always subdued (noninteractive)
59        let label_color = egui_visuals.weak_text_color();
60
61        // Value color (use ListVisuals text_color or custom)
62        let value_color = self
63            .value_color
64            .unwrap_or_else(|| context.visuals.text_color(&egui_visuals));
65
66        let content_rect = context.rect;
67
68        // Calculate label width (reserved for future use when we implement two-column layout)
69        let _label_width = self.label_width.unwrap_or_else(|| {
70            // Default to ~40% of available width
71            content_rect.width() * 0.4
72        });
73
74        let label = l10n::text(ui.ctx(), &self.label);
75        let value = l10n::text(ui.ctx(), &self.value);
76        let translated_label = format!("{label}: {value}");
77        context
78            .response
79            .widget_info(|| WidgetInfo::labeled(Role::Label, ui.is_enabled(), &translated_label));
80
81        if ui.is_rect_visible(content_rect) {
82            let y_center = content_rect.center().y;
83
84            // Draw label
85            ui.painter().text(
86                egui::pos2(content_rect.min.x, y_center),
87                egui::Align2::LEFT_CENTER,
88                &label,
89                egui::TextStyle::Body.resolve(ui.style()),
90                label_color,
91            );
92
93            // Draw value (right-aligned)
94            ui.painter().text(
95                egui::pos2(content_rect.max.x, y_center),
96                egui::Align2::RIGHT_CENTER,
97                &value,
98                egui::TextStyle::Body.resolve(ui.style()),
99                value_color,
100            );
101        }
102
103        context.response.clone()
104    }
105}