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:
@@ -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)),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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))),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user