1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-30 21:30:03 -04:00

Simplify and improve the default visual style

This commit is contained in:
Emil Ernerfeldt
2020-05-17 09:44:09 +02:00
parent 01568acef2
commit 037b22be7f
17 changed files with 393 additions and 189 deletions

View File

@@ -63,7 +63,8 @@ impl CollapsingHeader {
let text_pos = available.min + vec2(ui.style().indent, 0.0);
let galley = label.layout(available.width() - ui.style().indent, ui);
let text_max_x = text_pos.x + galley.size.x;
let desired_width = available.width().max(text_max_x - available.left());
let desired_width = text_max_x - available.left();
let desired_width = desired_width.max(available.width());
let interact = ui.reserve_space(
vec2(
@@ -87,9 +88,19 @@ impl CollapsingHeader {
*state
};
let animation_time = ui.style().animation_time;
let time_since_toggle = (ui.input().time - state.toggle_time) as f32;
let time_since_toggle = time_since_toggle + ui.input().dt; // Instant feedback
let openness = if state.open {
remap_clamp(time_since_toggle, 0.0..=animation_time, 0.0..=1.0)
} else {
remap_clamp(time_since_toggle, 0.0..=animation_time, 1.0..=0.0)
};
let animate = time_since_toggle < animation_time;
let where_to_put_background = ui.paint_list_len();
paint_icon(ui, &state, &interact);
paint_icon(ui, &interact, openness);
ui.add_galley(
text_pos,
@@ -102,18 +113,14 @@ impl CollapsingHeader {
where_to_put_background,
PaintCmd::Rect {
corner_radius: ui.style().interact(&interact).corner_radius,
fill_color: ui.style().interact(&interact).fill_color,
outline: ui.style().interact(&interact).outline,
fill_color: ui.style().interact(&interact).bg_fill_color,
outline: None,
rect: interact.rect,
},
);
ui.expand_to_include_child(interact.rect); // TODO: remove, just a test
let animation_time = ui.style().animation_time;
let time_since_toggle = (ui.input().time - state.toggle_time) as f32;
let time_since_toggle = time_since_toggle + ui.input().dt; // Instant feedback
let animate = time_since_toggle < animation_time;
if animate {
ui.indent(id, |child_ui| {
let max_height = if state.open {
@@ -154,7 +161,7 @@ impl CollapsingHeader {
}
}
fn paint_icon(ui: &mut Ui, state: &State, interact: &InteractInfo) {
fn paint_icon(ui: &mut Ui, interact: &InteractInfo, openness: f32) {
let stroke_color = ui.style().interact(interact).stroke_color;
let stroke_width = ui.style().interact(interact).stroke_width;
@@ -164,25 +171,24 @@ fn paint_icon(ui: &mut Ui, state: &State, interact: &InteractInfo) {
interact.rect.center().y,
));
// Draw a minus:
ui.add_paint_cmd(PaintCmd::LineSegment {
points: [
pos2(small_icon_rect.left(), small_icon_rect.center().y),
pos2(small_icon_rect.right(), small_icon_rect.center().y),
],
color: stroke_color,
width: stroke_width,
});
if !state.open {
// Draw it as a plus:
ui.add_paint_cmd(PaintCmd::LineSegment {
points: [
pos2(small_icon_rect.center().x, small_icon_rect.top()),
pos2(small_icon_rect.center().x, small_icon_rect.bottom()),
],
color: stroke_color,
width: stroke_width,
});
// Draw a pointy triangle arrow:
let rect = Rect::from_center_size(
small_icon_rect.center(),
vec2(small_icon_rect.width(), small_icon_rect.height()) * 0.75,
);
let mut points = [rect.left_top(), rect.right_top(), rect.center_bottom()];
let rotation = Vec2::angled(remap(openness, 0.0..=1.0, -TAU / 4.0..=0.0));
for p in &mut points {
let v = *p - rect.center();
let v = rotation.rotate_other(v);
*p = rect.center() + v;
}
// }
ui.add_paint_cmd(PaintCmd::Path {
path: mesher::Path::from_point_loop(&points),
closed: true,
fill_color: None,
outline: Some(Outline::new(stroke_width, stroke_color)),
});
}

View File

@@ -15,16 +15,25 @@ impl Frame {
Self {
margin: style.window_padding,
corner_radius: style.window.corner_radius,
fill_color: Some(style.background_fill_color()),
fill_color: Some(style.background_fill_color),
outline: Some(Outline::new(1.0, color::WHITE)),
}
}
pub fn menu_bar(_style: &Style) -> Self {
Self {
margin: Vec2::splat(1.0),
corner_radius: 0.0,
fill_color: None,
outline: Some(Outline::new(0.5, color::white(128))),
}
}
pub fn menu(style: &Style) -> Self {
Self {
margin: Vec2::splat(1.0),
corner_radius: 2.0,
fill_color: Some(style.background_fill_color()),
fill_color: Some(style.background_fill_color),
outline: Some(Outline::new(1.0, color::white(128))),
}
}
@@ -33,7 +42,7 @@ impl Frame {
Self {
margin: style.window_padding,
corner_radius: 5.0,
fill_color: Some(style.background_fill_color()),
fill_color: Some(style.background_fill_color),
outline: Some(Outline::new(1.0, color::white(128))),
}
}

View File

@@ -21,13 +21,16 @@ impl Default for BarState {
}
pub fn bar(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui)) -> InteractInfo {
ui.horizontal(|ui| {
Frame::default().show(ui, |ui| {
ui.inner_layout(Layout::horizontal(Align::Center), |ui| {
Frame::menu_bar(ui.style()).show(ui, |ui| {
let mut style = ui.style().clone();
style.button_padding = vec2(2.0, 0.0);
style.interact.inactive.fill_color = None;
style.interact.inactive.outline = None;
style.interact.hovered.fill_color = None;
// style.interact.active.bg_fill_color = None;
style.interact.active.rect_outline = None;
// style.interact.hovered.bg_fill_color = None;
style.interact.hovered.rect_outline = None;
style.interact.inactive.bg_fill_color = None;
style.interact.inactive.rect_outline = None;
ui.set_style(style);
// Take full width and fixed height:
@@ -55,7 +58,7 @@ pub fn menu(ui: &mut Ui, title: impl Into<String>, add_contents: impl FnOnce(&mu
let mut button = Button::new(title);
if bar_state.open_menu == Some(menu_id) {
button = button.fill_color(ui.style().interact.active.fill_color);
button = button.fill_color(Some(ui.style().interact.active.fill_color));
}
let button_interact = ui.add(button);
@@ -75,11 +78,12 @@ pub fn menu(ui: &mut Ui, title: impl Into<String>, add_contents: impl FnOnce(&mu
resize.show(ui, |ui| {
let mut style = ui.style().clone();
style.button_padding = vec2(2.0, 0.0);
style.interact.inactive.fill_color = None;
style.interact.inactive.outline = None;
style.interact.active.corner_radius = 0.0;
style.interact.hovered.corner_radius = 0.0;
style.interact.inactive.corner_radius = 0.0;
// style.interact.active.bg_fill_color = None;
style.interact.active.rect_outline = None;
// style.interact.hovered.bg_fill_color = None;
style.interact.hovered.rect_outline = None;
style.interact.inactive.bg_fill_color = None;
style.interact.inactive.rect_outline = None;
ui.set_style(style);
ui.set_layout(Layout::justified(Direction::Vertical));
add_contents(ui)

View File

@@ -27,6 +27,7 @@ pub struct Resize {
expand_width_to_fit_content: bool,
expand_height_to_fit_content: bool,
outline: bool,
handle_offset: Vec2,
}
@@ -34,13 +35,14 @@ impl Default for Resize {
fn default() -> Self {
Self {
resizable: true,
min_size: Vec2::splat(32.0),
min_size: Vec2::splat(16.0),
max_size: Vec2::infinity(),
default_size: vec2(f32::INFINITY, 200.0), // TODO
auto_shrink_width: false,
auto_shrink_height: false,
expand_width_to_fit_content: true,
expand_height_to_fit_content: true,
outline: true,
handle_offset: Default::default(),
}
}
@@ -128,12 +130,6 @@ impl Resize {
self
}
/// Offset the position of the resize handle by this much
pub fn handle_offset(mut self, handle_offset: Vec2) -> Self {
self.handle_offset = handle_offset;
self
}
pub fn auto_shrink_width(mut self, auto_shrink_width: bool) -> Self {
self.auto_shrink_width = auto_shrink_width;
self
@@ -143,6 +139,17 @@ impl Resize {
self.auto_shrink_height = auto_shrink_height;
self
}
/// Offset the position of the resize handle by this much
pub fn handle_offset(mut self, handle_offset: Vec2) -> Self {
self.handle_offset = handle_offset;
self
}
pub fn outline(mut self, outline: bool) -> Self {
self.outline = outline;
self
}
}
// TODO: a common trait for Things that follow this pattern
@@ -240,6 +247,17 @@ impl Resize {
// ------------------------------
if self.outline && corner_interact.is_some() {
let rect = Rect::from_min_size(position, state.size);
let rect = rect.expand(2.0); // breathing room for content
ui.add_paint_cmd(PaintCmd::Rect {
rect,
corner_radius: 3.0,
fill_color: None,
outline: Some(ui.style().thin_outline),
});
}
if let Some(corner_interact) = corner_interact {
paint_resize_corner(ui, &corner_interact);

View File

@@ -165,19 +165,19 @@ impl ScrollArea {
let style = outer_ui.style();
let handle_fill_color = style.interact(&handle_interact).fill_color;
let handle_outline = style.interact(&handle_interact).outline;
let handle_outline = style.interact(&handle_interact).rect_outline;
outer_ui.add_paint_cmd(PaintCmd::Rect {
rect: outer_scroll_rect,
corner_radius,
fill_color: Some(color::gray(0, 196)), // TODO style
fill_color: Some(outer_ui.style().dark_bg_color),
outline: None,
});
outer_ui.add_paint_cmd(PaintCmd::Rect {
rect: handle_rect.expand(-2.0),
corner_radius,
fill_color: handle_fill_color,
fill_color: Some(handle_fill_color),
outline: handle_outline,
});
}

View File

@@ -28,11 +28,12 @@ impl<'open> Window<'open> {
area,
frame: None,
resize: Resize::default()
.handle_offset(Vec2::splat(4.0))
.auto_shrink_width(true)
.auto_expand_height(false)
.auto_expand_width(true)
.auto_shrink_height(false)
.auto_expand_height(false),
.auto_shrink_width(true)
.handle_offset(Vec2::splat(4.0))
.outline(false),
scroll: Some(
ScrollArea::default()
.always_show_scroll(false)
@@ -137,28 +138,89 @@ impl<'open> Window<'open> {
let frame = frame.unwrap_or_else(|| Frame::window(&ctx.style()));
// TODO: easier way to compose these
area.show(ctx, |ui| {
frame.show(ui, |ui| {
resize.show(ui, |ui| {
ui.horizontal(|ui| {
// TODO: prettier close button, and to the right of the window
if let Some(open) = open {
if ui.add(Button::new("X")).clicked {
*open = false;
}
if true {
// TODO: easier way to compose these
area.show(ctx, |ui| {
frame.show(ui, |ui| {
resize.show(ui, |ui| {
show_title_bar(ui, title_label, open);
if let Some(scroll) = scroll {
scroll.show(ui, add_contents)
} else {
add_contents(ui)
}
ui.add(title_label);
});
ui.add(Separator::new().line_width(1.0)); // TODO: nicer way to split window title from contents
if let Some(scroll) = scroll {
scroll.show(ui, add_contents)
} else {
add_contents(ui)
}
})
})
})
})
} else {
// TODO: something like this, with collapsing contents
area.show(ctx, |ui| {
frame.show(ui, |ui| {
CollapsingHeader::new(title_label.text()).show(ui, |ui| {
resize.show(ui, |ui| {
if let Some(scroll) = scroll {
scroll.show(ui, add_contents)
} else {
add_contents(ui)
}
})
});
})
})
}
}
}
fn show_title_bar(ui: &mut Ui, title_label: Label, open: Option<&mut bool>) {
let button_size = ui.style().clickable_diameter;
// TODO: show collapse button
let title_rect = ui.add(title_label).rect;
if let Some(open) = open {
let close_max_x = title_rect.right() + ui.style().item_spacing.x + button_size;
let close_max_x = close_max_x.max(ui.rect_finite().right());
let close_rect = Rect::from_min_size(
pos2(
close_max_x - button_size,
title_rect.center().y - 0.5 * button_size,
),
Vec2::splat(button_size),
);
if close_button(ui, close_rect).clicked {
*open = false;
}
}
ui.add(Separator::new().line_width(1.0)); // TODO: nicer way to split window title from contents
}
fn close_button(ui: &mut Ui, rect: Rect) -> InteractInfo {
let close_id = ui.make_child_id("window_close_button");
let interact = ui.interact_rect(rect, close_id);
ui.expand_to_include_child(interact.rect);
// ui.add_paint_cmd(PaintCmd::Rect {
// corner_radius: ui.style().interact(&interact).corner_radius,
// fill_color: ui.style().interact(&interact).bg_fill_color,
// outline: ui.style().interact(&interact).rect_outline,
// rect: interact.rect,
// });
let rect = rect.expand(-4.0);
let stroke_color = ui.style().interact(&interact).stroke_color;
let stroke_width = ui.style().interact(&interact).stroke_width;
ui.add_paint_cmd(PaintCmd::line_segment(
[rect.left_top(), rect.right_bottom()],
stroke_color,
stroke_width,
));
ui.add_paint_cmd(PaintCmd::line_segment(
[rect.right_top(), rect.left_bottom()],
stroke_color,
stroke_width,
));
interact
}