egui/emigui/src/style.rs

259 lines
8.2 KiB
Rust
Raw Normal View History

2018-12-26 16:01:46 +00:00
use crate::{math::*, types::*};
2018-12-26 13:38:46 +00:00
2018-12-27 17:19:06 +00:00
#[derive(Clone, Debug)]
2018-12-26 22:08:50 +00:00
pub struct Style {
2018-12-27 17:19:06 +00:00
/// Show rectangles around each widget
pub debug_rects: bool,
/// For stuff like check marks in check boxes.
2018-12-26 22:08:50 +00:00
pub line_width: f32,
}
impl Default for Style {
fn default() -> Style {
2018-12-27 17:19:06 +00:00
Style {
debug_rects: false,
line_width: 2.0,
}
}
}
2018-12-27 18:30:31 +00:00
impl Style {
/// e.g. the background of the slider
fn background_fill_color(&self) -> Color {
2019-03-11 14:30:32 +00:00
gray(34, 200)
2018-12-27 18:30:31 +00:00
}
fn text_color(&self) -> Color {
2019-03-11 14:30:32 +00:00
gray(255, 200)
2018-12-27 18:30:31 +00:00
}
/// Fill color of the interactive part of a component (button, slider grab, checkbox, ...)
fn interact_fill_color(&self, interact: &InteractInfo) -> Color {
if interact.active {
2019-03-11 14:30:32 +00:00
srgba(100, 100, 200, 255)
2018-12-27 18:30:31 +00:00
} else if interact.hovered {
2019-03-11 14:30:32 +00:00
srgba(100, 100, 150, 255)
2018-12-27 18:30:31 +00:00
} else {
2019-03-11 14:30:32 +00:00
srgba(60, 60, 70, 255)
2018-12-27 18:30:31 +00:00
}
}
/// Stroke and text color of the interactive part of a component (button, slider grab, checkbox, ...)
fn interact_stroke_color(&self, interact: &InteractInfo) -> Color {
if interact.active {
2019-03-11 14:30:32 +00:00
gray(255, 255)
2018-12-27 18:30:31 +00:00
} else if interact.hovered {
2019-03-11 14:30:32 +00:00
gray(255, 200)
2018-12-27 18:30:31 +00:00
} else {
2019-03-11 14:30:32 +00:00
gray(255, 170)
2018-12-27 18:30:31 +00:00
}
}
2018-12-27 22:55:16 +00:00
/// Returns small icon rectangle and big icon rectangle
fn icon_rectangles(&self, rect: &Rect) -> (Rect, Rect) {
2018-12-27 18:30:31 +00:00
let box_side = 16.0;
let big_icon_rect = Rect::from_center_size(
vec2(rect.min().x + 4.0 + box_side * 0.5, rect.center().y),
vec2(box_side, box_side),
);
let small_icon_rect = Rect::from_center_size(big_icon_rect.center(), vec2(10.0, 10.0));
2018-12-27 22:55:16 +00:00
(small_icon_rect, big_icon_rect)
2018-12-27 18:30:31 +00:00
}
}
2018-12-27 17:19:06 +00:00
fn debug_rect(rect: Rect) -> PaintCmd {
PaintCmd::Rect {
corner_radius: 0.0,
fill_color: None,
outline: Some(Outline {
2019-03-11 14:30:32 +00:00
color: gray(255, 255),
2018-12-27 17:19:06 +00:00
width: 1.0,
}),
2019-01-14 13:26:02 +00:00
rect,
2018-12-26 22:08:50 +00:00
}
}
2018-12-26 13:38:46 +00:00
/// TODO: a Style struct which defines colors etc
2018-12-26 22:08:50 +00:00
fn translate_cmd(out_commands: &mut Vec<PaintCmd>, style: &Style, cmd: GuiCmd) {
2018-12-26 13:38:46 +00:00
match cmd {
2018-12-26 16:32:58 +00:00
GuiCmd::PaintCommands(mut commands) => out_commands.append(&mut commands),
2019-01-14 13:26:02 +00:00
GuiCmd::Button { interact } => {
2018-12-26 21:17:33 +00:00
out_commands.push(PaintCmd::Rect {
2019-03-11 14:30:32 +00:00
corner_radius: 10.0,
2018-12-27 18:30:31 +00:00
fill_color: Some(style.interact_fill_color(&interact)),
2018-12-26 21:17:33 +00:00
outline: None,
2019-01-14 13:26:02 +00:00
rect: interact.rect,
2018-12-26 21:17:33 +00:00
});
2018-12-27 17:19:06 +00:00
if style.debug_rects {
2019-01-14 13:26:02 +00:00
out_commands.push(debug_rect(interact.rect));
2018-12-27 17:19:06 +00:00
}
2018-12-26 21:17:33 +00:00
}
2019-01-14 13:26:02 +00:00
GuiCmd::Checkbox { checked, interact } => {
let (small_icon_rect, big_icon_rect) = style.icon_rectangles(&interact.rect);
2018-12-26 21:17:33 +00:00
out_commands.push(PaintCmd::Rect {
corner_radius: 3.0,
2018-12-27 18:30:31 +00:00
fill_color: Some(style.interact_fill_color(&interact)),
2018-12-26 21:17:33 +00:00
outline: None,
2019-01-14 13:26:02 +00:00
rect: big_icon_rect,
2018-12-26 21:17:33 +00:00
});
2018-12-27 18:30:31 +00:00
let stroke_color = style.interact_stroke_color(&interact);
2018-12-26 21:17:33 +00:00
if checked {
out_commands.push(PaintCmd::Line {
points: vec![
2018-12-27 18:30:31 +00:00
vec2(small_icon_rect.min().x, small_icon_rect.center().y),
vec2(small_icon_rect.center().x, small_icon_rect.max().y),
vec2(small_icon_rect.max().x, small_icon_rect.min().y),
2018-12-26 21:17:33 +00:00
],
2018-12-27 16:47:32 +00:00
color: stroke_color,
2018-12-26 22:08:50 +00:00
width: style.line_width,
2018-12-26 16:01:46 +00:00
});
2018-12-26 13:38:46 +00:00
}
2018-12-26 21:17:33 +00:00
2018-12-27 17:19:06 +00:00
if style.debug_rects {
2019-01-14 13:26:02 +00:00
out_commands.push(debug_rect(interact.rect));
2018-12-27 17:19:06 +00:00
}
2018-12-26 21:17:33 +00:00
}
2019-01-14 13:26:02 +00:00
GuiCmd::FoldableHeader { interact, open } => {
2018-12-27 18:30:31 +00:00
let fill_color = style.interact_fill_color(&interact);
let stroke_color = style.interact_stroke_color(&interact);
2018-12-27 18:08:43 +00:00
out_commands.push(PaintCmd::Rect {
corner_radius: 3.0,
fill_color: Some(fill_color),
outline: None,
2019-01-14 13:26:02 +00:00
rect: interact.rect,
2018-12-27 18:08:43 +00:00
});
2019-01-14 13:26:02 +00:00
let (small_icon_rect, _) = style.icon_rectangles(&interact.rect);
2018-12-27 18:08:43 +00:00
// Draw a minus:
out_commands.push(PaintCmd::Line {
points: vec![
2018-12-27 18:30:31 +00:00
vec2(small_icon_rect.min().x, small_icon_rect.center().y),
vec2(small_icon_rect.max().x, small_icon_rect.center().y),
2018-12-27 18:08:43 +00:00
],
color: stroke_color,
width: style.line_width,
});
2018-12-27 22:55:16 +00:00
if !open {
2018-12-27 18:08:43 +00:00
// Draw it as a plus:
out_commands.push(PaintCmd::Line {
points: vec![
2018-12-27 18:30:31 +00:00
vec2(small_icon_rect.center().x, small_icon_rect.min().y),
vec2(small_icon_rect.center().x, small_icon_rect.max().y),
2018-12-27 18:08:43 +00:00
],
color: stroke_color,
width: style.line_width,
});
}
}
2019-01-14 13:26:02 +00:00
GuiCmd::RadioButton { checked, interact } => {
2018-12-27 18:30:31 +00:00
let fill_color = style.interact_fill_color(&interact);
let stroke_color = style.interact_stroke_color(&interact);
2018-12-26 21:26:15 +00:00
2019-01-14 13:26:02 +00:00
let (small_icon_rect, big_icon_rect) = style.icon_rectangles(&interact.rect);
2018-12-26 21:26:15 +00:00
out_commands.push(PaintCmd::Circle {
2018-12-27 18:30:31 +00:00
center: big_icon_rect.center(),
2018-12-27 16:47:32 +00:00
fill_color: Some(fill_color),
2018-12-26 21:26:15 +00:00
outline: None,
2018-12-27 18:30:31 +00:00
radius: big_icon_rect.size.x / 2.0,
2018-12-26 21:26:15 +00:00
});
if checked {
out_commands.push(PaintCmd::Circle {
2018-12-27 18:30:31 +00:00
center: small_icon_rect.center(),
fill_color: Some(stroke_color),
2018-12-26 21:26:15 +00:00
outline: None,
2018-12-27 18:30:31 +00:00
radius: small_icon_rect.size.x / 2.0,
2018-12-26 21:26:15 +00:00
});
}
2018-12-27 17:19:06 +00:00
if style.debug_rects {
2019-01-14 13:26:02 +00:00
out_commands.push(debug_rect(interact.rect));
2018-12-27 17:19:06 +00:00
}
2018-12-26 21:26:15 +00:00
}
2018-12-26 16:01:46 +00:00
GuiCmd::Slider {
interact,
max,
min,
value,
} => {
2019-01-14 13:26:02 +00:00
let rect = interact.rect;
let thickness = rect.size().y;
2019-03-11 14:30:32 +00:00
let thin_size = vec2(rect.size.x, thickness / 5.0);
let thin_rect = Rect::from_center_size(rect.center(), thin_size);
2018-12-26 16:01:46 +00:00
let marker_center_x = remap_clamp(value, min, max, rect.min().x, rect.max().x);
2018-12-26 16:32:58 +00:00
out_commands.push(PaintCmd::Rect {
2019-03-11 14:30:32 +00:00
corner_radius: 4.0,
2018-12-27 18:30:31 +00:00
fill_color: Some(style.background_fill_color()),
2019-03-11 14:30:32 +00:00
outline: Some(Outline {
color: gray(200, 255), // TODO
width: 1.0,
}),
2019-01-14 13:26:02 +00:00
rect: thin_rect,
2018-12-26 16:01:46 +00:00
});
2019-03-11 14:30:32 +00:00
out_commands.push(PaintCmd::Circle {
center: vec2(marker_center_x, thin_rect.center().y),
2018-12-27 18:30:31 +00:00
fill_color: Some(style.interact_fill_color(&interact)),
2019-03-11 14:30:32 +00:00
outline: Some(Outline {
color: style.interact_stroke_color(&interact),
width: 1.5,
}),
radius: thickness / 3.0,
2018-12-26 16:01:46 +00:00
});
2018-12-27 17:19:06 +00:00
if style.debug_rects {
out_commands.push(debug_rect(rect));
}
2018-12-26 16:32:58 +00:00
}
GuiCmd::Text {
color,
2018-12-26 16:32:58 +00:00
pos,
2019-01-05 14:28:07 +00:00
text,
text_style,
2019-01-05 14:28:07 +00:00
x_offsets,
2018-12-26 16:32:58 +00:00
} => {
let color = color.unwrap_or_else(|| style.text_color());
2018-12-26 16:32:58 +00:00
out_commands.push(PaintCmd::Text {
2019-01-05 14:28:07 +00:00
color,
2019-01-12 23:55:56 +00:00
text_style,
2018-12-27 22:55:16 +00:00
pos,
2018-12-26 16:32:58 +00:00
text,
2019-01-05 14:28:07 +00:00
x_offsets,
2018-12-26 16:01:46 +00:00
});
2018-12-26 13:38:46 +00:00
}
2018-12-28 22:29:24 +00:00
GuiCmd::Window { rect } => {
out_commands.push(PaintCmd::Rect {
corner_radius: 5.0,
fill_color: Some(style.background_fill_color()),
outline: Some(Outline {
2019-03-11 14:30:32 +00:00
color: gray(255, 255), // TODO
2018-12-28 22:29:24 +00:00
width: 1.0,
}),
rect,
2018-12-28 22:29:24 +00:00
});
}
2018-12-26 13:38:46 +00:00
}
}
pub fn into_paint_commands<GuiCmdIterator>(
2018-12-28 22:29:24 +00:00
gui_commands: GuiCmdIterator,
style: &Style,
) -> Vec<PaintCmd>
where
GuiCmdIterator: Iterator<Item = GuiCmd>,
2018-12-28 22:29:24 +00:00
{
2018-12-26 16:01:46 +00:00
let mut paint_commands = vec![];
for gui_cmd in gui_commands {
translate_cmd(&mut paint_commands, style, gui_cmd)
2018-12-26 16:01:46 +00:00
}
paint_commands
2018-12-26 13:38:46 +00:00
}