egui_charts/ui_kit/buttons/
split_button.rs1use crate::theme::ThemeExt;
8use egui::emath::GuiRounding;
9
10use super::{ButtonSize, ButtonVariant, finish};
11use crate::icons::{Icon, icons};
12use crate::tokens::DESIGN_TOKENS;
13use egui::{Rect, Response, Sense, Ui, Vec2, vec2};
14
15pub struct SplitButton {
38 icon: &'static Icon,
39 size: ButtonSize,
40 tooltip: Option<String>,
41 expanded: bool,
42 selected: Option<bool>,
43}
44
45impl SplitButton {
46 pub fn new(icon: &'static Icon) -> Self {
48 Self {
49 icon,
50 size: ButtonSize::MD,
51 tooltip: None,
52 expanded: false,
53 selected: None,
54 }
55 }
56
57 #[must_use]
59 pub fn size(mut self, size: ButtonSize) -> Self {
60 self.size = size;
61 self
62 }
63
64 #[must_use]
66 pub fn tooltip(mut self, text: impl Into<String>) -> Self {
67 self.tooltip = Some(text.into());
68 self
69 }
70
71 #[must_use]
73 pub fn expanded(mut self, expanded: bool) -> Self {
74 self.expanded = expanded;
75 self
76 }
77
78 #[must_use]
80 pub fn selected(mut self, selected: bool) -> Self {
81 self.selected = Some(selected);
82 self
83 }
84
85 pub fn show(self, ui: &mut Ui) -> Response {
87 let button_size = Vec2::splat(self.size.pixels());
88 let (rect, response) = ui.allocate_exact_size(button_size, Sense::click());
89 crate::styles::focus::draw_focus_ring(ui, &response, ui.active_theme().radius.sm);
90
91 let show_active = self.expanded || self.selected == Some(true);
92 if ui.is_rect_visible(rect) {
93 let hovered = response.hovered();
94 let pressed = response.is_pointer_button_down_on();
95 let variant = if show_active {
96 ButtonVariant::Primary
97 } else {
98 ButtonVariant::Ghost
99 };
100 ui.painter().rect_filled(
101 rect,
102 ui.active_theme().radius.sm,
103 variant.bg_color(ui, hovered, pressed),
104 );
105
106 let color = if show_active {
107 variant.fg_color(ui)
108 } else {
109 ui.style().interact(&response).fg_stroke.color
110 };
111 let icon_size = Vec2::splat(self.size.icon_pixels(None));
112 self.icon
113 .as_image_tinted(icon_size, color)
114 .paint_at(ui, Rect::from_center_size(rect.center(), icon_size));
115
116 let size = Vec2::splat(DESIGN_TOKENS.sizing.icon_sm);
117 let chevron = Rect::from_min_size(rect.right_bottom() - size + vec2(0.0, 4.0), size)
118 .round_to_pixels(ui.pixels_per_point());
119 icons::CHEVRON_DOWN
120 .as_image_tinted(size, color)
121 .paint_at(ui, chevron);
122 }
123
124 ui.ctx()
125 .accesskit_node_builder(response.id, |node| node.set_expanded(self.expanded));
126 let tooltip = self.tooltip.as_deref();
127 finish(
128 response,
129 self.selected,
130 tooltip.unwrap_or_default(),
131 tooltip,
132 )
133 }
134}