use eframe::egui;
pub const TOOLBAR_BTN: f32 = 28.0;
fn square() -> egui::Vec2 {
egui::vec2(TOOLBAR_BTN, TOOLBAR_BTN)
}
const BUG_FILL: egui::Color32 = egui::Color32::from_rgb(0xE1, 0x54, 0x4A);
const BUG_INK: egui::Color32 = egui::Color32::from_rgb(0x5E, 0x1A, 0x14);
const BOOK_FILL: egui::Color32 = egui::Color32::from_rgb(0x2E, 0x9E, 0x8F);
const BOOK_INK: egui::Color32 = egui::Color32::from_rgb(0x12, 0x48, 0x40);
const DRAW_FILL: egui::Color32 = egui::Color32::from_rgb(0xF2, 0xB3, 0x3D);
const DRAW_INK: egui::Color32 = egui::Color32::from_rgb(0x6E, 0x4A, 0x12);
const BUG_LAYERS: &[(&str, egui::Color32)] = &[("\u{E05A}", BUG_FILL), ("\u{1F41E}", BUG_INK)];
const BOOK_LAYERS: &[(&str, egui::Color32)] = &[("\u{E05B}", BOOK_FILL), ("\u{1F4DA}", BOOK_INK)];
const DRAW_LAYERS: &[(&str, egui::Color32)] = &[("\u{E05C}", DRAW_FILL), ("\u{270D}", DRAW_INK)];
fn color_layers(glyph: &str) -> Option<&'static [(&'static str, egui::Color32)]> {
match glyph {
"\u{1F41E}" => Some(BUG_LAYERS), "\u{1F4DA}" => Some(BOOK_LAYERS), "\u{270D}" => Some(DRAW_LAYERS), _ => None,
}
}
pub fn button(ui: &mut egui::Ui, glyph: &str, tooltip: &str) -> egui::Response {
if let Some(layers) = color_layers(glyph) {
return layered_button(ui, layers, tooltip);
}
ui.add(egui::Button::new(glyph).min_size(square()))
.on_hover_text(tooltip)
}
pub fn button_enabled(
ui: &mut egui::Ui,
enabled: bool,
glyph: &str,
tooltip: &str,
) -> egui::Response {
if let Some(layers) = color_layers(glyph) {
return layered_button_enabled(ui, enabled, layers, tooltip);
}
ui.add_enabled(enabled, egui::Button::new(glyph).min_size(square()))
.on_hover_text(tooltip)
}
pub fn layered_button(
ui: &mut egui::Ui,
layers: &[(&str, egui::Color32)],
tooltip: &str,
) -> egui::Response {
layered_button_enabled(ui, true, layers, tooltip)
}
pub fn layered_button_enabled(
ui: &mut egui::Ui,
enabled: bool,
layers: &[(&str, egui::Color32)],
tooltip: &str,
) -> egui::Response {
let response = ui
.add_enabled(enabled, egui::Button::new("").min_size(square()))
.on_hover_text(tooltip);
let opacity = if enabled {
1.0
} else {
ui.visuals().disabled_alpha()
};
paint_layers(ui, response.rect, layers, opacity);
response
}
pub fn layered_toggle(
ui: &mut egui::Ui,
selected: bool,
layers: &[(&str, egui::Color32)],
tooltip: &str,
) -> egui::Response {
let response = ui
.add(egui::Button::new("").min_size(square()).selected(selected))
.on_hover_text(tooltip);
paint_layers(ui, response.rect, layers, 1.0);
response
}
fn paint_layers(
ui: &egui::Ui,
rect: egui::Rect,
layers: &[(&str, egui::Color32)],
opacity: f32,
) {
let mut font = egui::TextStyle::Button.resolve(ui.style());
font.size = 17.0;
for (glyph, color) in layers {
ui.painter().text(
rect.center(),
egui::Align2::CENTER_CENTER,
*glyph,
font.clone(),
color.gamma_multiply(opacity),
);
}
}
pub fn toggle(ui: &mut egui::Ui, selected: bool, glyph: &str, tooltip: &str) -> egui::Response {
if let Some(layers) = color_layers(glyph) {
return layered_toggle(ui, selected, layers, tooltip);
}
ui.add(egui::Button::new(glyph).min_size(square()).selected(selected))
.on_hover_text(tooltip)
}
pub struct SelectResult {
pub changed: Option<String>,
pub header_rect: egui::Rect,
pub item_rects: Vec<(String, egui::Rect)>,
}
pub fn select(
ui: &mut egui::Ui,
id_source: &str,
current: &str,
options: &[(&str, &str)],
) -> SelectResult {
let current_label = options
.iter()
.find(|(_, id)| *id == current)
.map(|(label, _)| *label)
.unwrap_or(current);
let mut changed = None;
let mut item_rects = Vec::new();
let inner = egui::ComboBox::from_id_salt(("toolbar-select", id_source))
.selected_text(current_label)
.show_ui(ui, |ui| {
for (label, id) in options {
let resp = ui.selectable_label(*id == current, *label);
item_rects.push(((*id).to_string(), resp.rect));
if resp.clicked() && *id != current {
changed = Some((*id).to_string());
}
}
});
SelectResult { changed, header_rect: inner.response.rect, item_rects }
}