Animate foldable regions
This commit is contained in:
parent
0ed578341b
commit
9be5537418
2 changed files with 59 additions and 12 deletions
|
@ -1,14 +1,30 @@
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::{window::WindowState, *};
|
use crate::{window::WindowState, *};
|
||||||
|
|
||||||
|
// TODO: move together with foldable code into own file
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct FoldableState {
|
||||||
|
pub open: bool,
|
||||||
|
pub toggle_time: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for FoldableState {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
open: false,
|
||||||
|
toggle_time: -std::f64::INFINITY,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct Memory {
|
pub struct Memory {
|
||||||
/// The widget being interacted with (e.g. dragged, in case of a slider).
|
/// The widget being interacted with (e.g. dragged, in case of a slider).
|
||||||
pub(crate) active_id: Option<Id>,
|
pub(crate) active_id: Option<Id>,
|
||||||
|
|
||||||
/// Which foldable regions are open.
|
/// Which foldable regions are open.
|
||||||
pub(crate) open_foldables: HashSet<Id>,
|
pub(crate) foldables: HashMap<Id, FoldableState>,
|
||||||
|
|
||||||
windows: HashMap<Id, WindowState>,
|
windows: HashMap<Id, WindowState>,
|
||||||
|
|
||||||
|
|
|
@ -166,23 +166,21 @@ impl Region {
|
||||||
Some(id),
|
Some(id),
|
||||||
);
|
);
|
||||||
|
|
||||||
let open = {
|
let state = {
|
||||||
let mut memory = self.ctx.memory.lock();
|
let mut memory = self.ctx.memory.lock();
|
||||||
|
let mut state = memory.foldables.entry(id).or_default();
|
||||||
if interact.clicked {
|
if interact.clicked {
|
||||||
if memory.open_foldables.contains(&id) {
|
state.open = !state.open;
|
||||||
memory.open_foldables.remove(&id);
|
state.toggle_time = self.ctx.input.time;
|
||||||
} else {
|
|
||||||
memory.open_foldables.insert(id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
memory.open_foldables.contains(&id)
|
*state
|
||||||
};
|
};
|
||||||
|
|
||||||
let fill_color = self.style.interact_fill_color(&interact);
|
let fill_color = self.style.interact_fill_color(&interact);
|
||||||
let stroke_color = self.style.interact_stroke_color(&interact);
|
let stroke_color = self.style.interact_stroke_color(&interact);
|
||||||
|
|
||||||
self.add_paint_cmd(PaintCmd::Rect {
|
self.add_paint_cmd(PaintCmd::Rect {
|
||||||
corner_radius: 5.0,
|
corner_radius: self.style.interaction_corner_radius,
|
||||||
fill_color,
|
fill_color,
|
||||||
outline: Some(Outline::new(1.0, color::WHITE)),
|
outline: Some(Outline::new(1.0, color::WHITE)),
|
||||||
rect: interact.rect,
|
rect: interact.rect,
|
||||||
|
@ -198,7 +196,8 @@ impl Region {
|
||||||
color: stroke_color,
|
color: stroke_color,
|
||||||
width: self.style.line_width,
|
width: self.style.line_width,
|
||||||
});
|
});
|
||||||
if !open {
|
|
||||||
|
if !state.open {
|
||||||
// Draw it as a plus:
|
// Draw it as a plus:
|
||||||
self.add_paint_cmd(PaintCmd::Line {
|
self.add_paint_cmd(PaintCmd::Line {
|
||||||
points: vec![
|
points: vec![
|
||||||
|
@ -217,7 +216,39 @@ impl Region {
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
if open {
|
let animation_time = self.style().animation_time;
|
||||||
|
let time_since_toggle = (self.ctx.input.time - state.toggle_time) as f32;
|
||||||
|
if time_since_toggle < animation_time {
|
||||||
|
self.indent(id, |region| {
|
||||||
|
// animation time
|
||||||
|
|
||||||
|
let max_height = if state.open {
|
||||||
|
remap(
|
||||||
|
time_since_toggle,
|
||||||
|
0.0,
|
||||||
|
animation_time,
|
||||||
|
50.0, // Get instant feedback
|
||||||
|
1500.0, // We don't expect to get bigger than this
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
remap_clamp(
|
||||||
|
time_since_toggle,
|
||||||
|
0.0,
|
||||||
|
animation_time,
|
||||||
|
50.0, // TODO: state.open_height
|
||||||
|
0.0,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
region
|
||||||
|
.clip_rect
|
||||||
|
.set_height(region.clip_rect.height().min(max_height));
|
||||||
|
|
||||||
|
add_contents(region);
|
||||||
|
|
||||||
|
region.bounding_size.y = region.bounding_size.y.min(max_height);
|
||||||
|
});
|
||||||
|
} else if state.open {
|
||||||
self.indent(id, add_contents);
|
self.indent(id, add_contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue