[style] Fade out windows on close
This commit is contained in:
parent
29bb7c9f9d
commit
e2217ff63a
7 changed files with 86 additions and 27 deletions
|
@ -158,6 +158,34 @@ impl Area {
|
||||||
add_contents(&mut content_ui);
|
add_contents(&mut content_ui);
|
||||||
prepared.end(ctx, content_ui)
|
prepared.end(ctx, content_ui)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn show_open_close_animation(&self, ctx: &CtxRef, frame: &Frame, is_open: bool) {
|
||||||
|
// must be called first so animation managers know the latest state
|
||||||
|
let visibility_factor = ctx.animate_bool(self.id.with("close_animation"), is_open);
|
||||||
|
|
||||||
|
if is_open {
|
||||||
|
// we actually only show close animations.
|
||||||
|
// when opening a window we show it right away.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if visibility_factor <= 0.0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let layer_id = LayerId::new(self.order, self.id);
|
||||||
|
let area_rect = ctx.memory().areas.get(self.id).map(|area| area.rect());
|
||||||
|
if let Some(area_rect) = area_rect {
|
||||||
|
let clip_rect = ctx.available_rect();
|
||||||
|
let painter = Painter::new(ctx.clone(), layer_id, clip_rect);
|
||||||
|
|
||||||
|
// shrinkage: looks kinda a bad on its own
|
||||||
|
// let area_rect =
|
||||||
|
// Rect::from_center_size(area_rect.center(), visibility_factor * area_rect.size());
|
||||||
|
|
||||||
|
let frame = frame.multiply_with_opacity(visibility_factor);
|
||||||
|
painter.add(frame.paint(area_rect));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Prepared {
|
impl Prepared {
|
||||||
|
|
|
@ -90,6 +90,13 @@ impl Frame {
|
||||||
self.stroke = stroke;
|
self.stroke = stroke;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn multiply_with_opacity(mut self, opacity: f32) -> Self {
|
||||||
|
self.fill = self.fill.linear_multiply(opacity);
|
||||||
|
self.stroke.color = self.stroke.color.linear_multiply(opacity);
|
||||||
|
self.shadow.color = self.shadow.color.linear_multiply(opacity);
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Prepared {
|
pub struct Prepared {
|
||||||
|
@ -122,6 +129,31 @@ impl Frame {
|
||||||
prepared.end(ui);
|
prepared.end(ui);
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn paint(&self, outer_rect: Rect) -> Shape {
|
||||||
|
let Self {
|
||||||
|
margin: _,
|
||||||
|
corner_radius,
|
||||||
|
shadow,
|
||||||
|
fill,
|
||||||
|
stroke,
|
||||||
|
} = *self;
|
||||||
|
|
||||||
|
let frame_shape = Shape::Rect {
|
||||||
|
rect: outer_rect,
|
||||||
|
corner_radius,
|
||||||
|
fill,
|
||||||
|
stroke,
|
||||||
|
};
|
||||||
|
|
||||||
|
if shadow == Default::default() {
|
||||||
|
frame_shape
|
||||||
|
} else {
|
||||||
|
let shadow = shadow.tessellate(outer_rect, corner_radius);
|
||||||
|
let shadow = Shape::Triangles(shadow);
|
||||||
|
Shape::Vec(vec![shadow, frame_shape])
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Prepared {
|
impl Prepared {
|
||||||
|
@ -141,26 +173,9 @@ impl Prepared {
|
||||||
..
|
..
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
let frame_shape = Shape::Rect {
|
let shape = frame.paint(outer_rect);
|
||||||
rect: outer_rect,
|
ui.painter().set(where_to_put_background, shape);
|
||||||
corner_radius: frame.corner_radius,
|
|
||||||
fill: frame.fill,
|
|
||||||
stroke: frame.stroke,
|
|
||||||
};
|
|
||||||
|
|
||||||
if frame.shadow == Default::default() {
|
|
||||||
ui.painter().set(where_to_put_background, frame_shape);
|
|
||||||
} else {
|
|
||||||
let shadow = frame.shadow.tessellate(outer_rect, frame.corner_radius);
|
|
||||||
let shadow = Shape::Triangles(shadow);
|
|
||||||
ui.painter().set(
|
|
||||||
where_to_put_background,
|
|
||||||
Shape::Vec(vec![shadow, frame_shape]),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
ui.advance_cursor_after_rect(outer_rect);
|
ui.advance_cursor_after_rect(outer_rect);
|
||||||
|
|
||||||
outer_rect
|
outer_rect
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -224,7 +224,12 @@ impl<'open> Window<'open> {
|
||||||
with_title_bar,
|
with_title_bar,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
if matches!(open, Some(false)) && !ctx.memory().everything_is_visible() {
|
let frame = frame.unwrap_or_else(|| Frame::window(&ctx.style()));
|
||||||
|
|
||||||
|
let is_open = !matches!(open, Some(false)) || ctx.memory().everything_is_visible();
|
||||||
|
area.show_open_close_animation(ctx, &frame, is_open);
|
||||||
|
|
||||||
|
if !is_open {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,8 +249,6 @@ impl<'open> Window<'open> {
|
||||||
let resize = resize.resizable(false); // We move it manually
|
let resize = resize.resizable(false); // We move it manually
|
||||||
let mut resize = resize.id(resize_id);
|
let mut resize = resize.id(resize_id);
|
||||||
|
|
||||||
let frame = frame.unwrap_or_else(|| Frame::window(&ctx.style()));
|
|
||||||
|
|
||||||
let mut area = area.begin(ctx);
|
let mut area = area.begin(ctx);
|
||||||
|
|
||||||
let title_content_spacing = 2.0 * ctx.style().spacing.item_spacing.y;
|
let title_content_spacing = 2.0 * ctx.style().spacing.item_spacing.y;
|
||||||
|
|
|
@ -22,7 +22,7 @@ impl Default for WidgetGallery {
|
||||||
radio: Enum::First,
|
radio: Enum::First,
|
||||||
scalar: 42.0,
|
scalar: 42.0,
|
||||||
string: "Hello World!".to_owned(),
|
string: "Hello World!".to_owned(),
|
||||||
color: (egui::Rgba::from(egui::Color32::LIGHT_BLUE) * 0.5).into(),
|
color: egui::Color32::LIGHT_BLUE.linear_multiply(0.5),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,6 +129,14 @@ impl Color32 {
|
||||||
pub fn to_tuple(&self) -> (u8, u8, u8, u8) {
|
pub fn to_tuple(&self) -> (u8, u8, u8, u8) {
|
||||||
(self.r(), self.g(), self.b(), self.a())
|
(self.r(), self.g(), self.b(), self.a())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Multiply with 0.5 to make color half as opaque.
|
||||||
|
pub fn linear_multiply(self, factor: f32) -> Color32 {
|
||||||
|
debug_assert!(0.0 <= factor && factor <= 1.0);
|
||||||
|
// As an unfortunate side-effect of using premultiplied alpha
|
||||||
|
// we need a somewhat expensive conversion to linear space and back.
|
||||||
|
Rgba::from(self).multiply(factor).into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
/// A rectangular shadow with a soft penumbra.
|
/// The color and fuzziness of a fuzzy shape.
|
||||||
|
/// Can be used for a rectangular shadow with a soft penumbra.
|
||||||
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
||||||
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub struct Shadow {
|
pub struct Shadow {
|
||||||
// The shadow extends this much outside the rect.
|
/// The shadow extends this much outside the rect.
|
||||||
|
/// The size of the fuzzy penumbra.
|
||||||
pub extrusion: f32,
|
pub extrusion: f32,
|
||||||
|
|
||||||
|
/// Color of the opaque center of the shadow.
|
||||||
pub color: Color32,
|
pub color: Color32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -420,8 +420,9 @@ fn stroke_path(
|
||||||
|
|
||||||
fn mul_color(color: Color32, factor: f32) -> Color32 {
|
fn mul_color(color: Color32, factor: f32) -> Color32 {
|
||||||
debug_assert!(0.0 <= factor && factor <= 1.0);
|
debug_assert!(0.0 <= factor && factor <= 1.0);
|
||||||
// sRGBA correct fading requires conversion to linear space and back again because of premultiplied alpha
|
// As an unfortunate side-effect of using premultiplied alpha
|
||||||
Rgba::from(color).multiply(factor).into()
|
// we need a somewhat expensive conversion to linear space and back.
|
||||||
|
color.linear_multiply(factor)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in a new issue