Create foldable areas
This commit is contained in:
parent
500312e878
commit
52eb5bdf2c
5 changed files with 146 additions and 7 deletions
|
@ -75,10 +75,11 @@ impl GuiSettings for App {
|
|||
}),
|
||||
}]));
|
||||
|
||||
gui.label("LayoutOptions:");
|
||||
let mut layout_options = gui.layout_options;
|
||||
layout_options.show_gui(gui);
|
||||
gui.layout_options = layout_options;
|
||||
gui.foldable("LayoutOptions", |gui| {
|
||||
let mut layout_options = gui.layout_options;
|
||||
layout_options.show_gui(gui);
|
||||
gui.layout_options = layout_options;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::collections::HashSet;
|
||||
|
||||
use crate::{math::*, types::*};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -7,6 +9,9 @@ pub struct LayoutOptions {
|
|||
// Horizontal and vertical spacing between widgets
|
||||
pub item_spacing: Vec2,
|
||||
|
||||
/// Indent foldable regions etc by this much.
|
||||
pub indent: f32,
|
||||
|
||||
/// Default width of buttons, sliders etc
|
||||
pub width: f32,
|
||||
|
||||
|
@ -24,6 +29,7 @@ impl Default for LayoutOptions {
|
|||
fn default() -> Self {
|
||||
LayoutOptions {
|
||||
item_spacing: Vec2 { x: 8.0, y: 4.0 },
|
||||
indent: 21.0,
|
||||
width: 200.0,
|
||||
button_height: 24.0,
|
||||
checkbox_radio_height: 24.0,
|
||||
|
@ -34,10 +40,13 @@ impl Default for LayoutOptions {
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct State {
|
||||
/// The widget being interacted with (e.g. dragged, in case of a slider).
|
||||
pub active_id: Option<Id>,
|
||||
|
||||
/// Which foldable regions are open.
|
||||
open_foldables: HashSet<Id>,
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -186,6 +195,57 @@ impl Layout {
|
|||
interact
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Areas:
|
||||
|
||||
pub fn foldable<S, F>(&mut self, label: S, add_contents: F) -> InteractInfo
|
||||
where
|
||||
S: Into<String>,
|
||||
F: FnOnce(&mut Layout),
|
||||
{
|
||||
let label: String = label.into();
|
||||
let id = self.get_id(&label);
|
||||
|
||||
let rect = Rect {
|
||||
pos: self.cursor,
|
||||
size: Vec2 {
|
||||
x: self.layout_options.width,
|
||||
y: self.layout_options.button_height,
|
||||
},
|
||||
};
|
||||
|
||||
let interact = self.interactive_rect(id, &rect);
|
||||
self.cursor.y += rect.size.y + self.layout_options.item_spacing.y;
|
||||
|
||||
if interact.clicked {
|
||||
if self.state.open_foldables.contains(&id) {
|
||||
self.state.open_foldables.remove(&id);
|
||||
} else {
|
||||
self.state.open_foldables.insert(id);
|
||||
}
|
||||
}
|
||||
let open = self.state.open_foldables.contains(&id);
|
||||
|
||||
self.commands.push(GuiCmd::FoldableHeader {
|
||||
interact,
|
||||
rect,
|
||||
label,
|
||||
open,
|
||||
});
|
||||
|
||||
if open {
|
||||
// TODO: push/pop id stack
|
||||
let old_x = self.cursor.x;
|
||||
self.cursor.x += self.layout_options.indent;
|
||||
add_contents(self);
|
||||
self.cursor.x = old_x;
|
||||
|
||||
// TODO: paint background?
|
||||
}
|
||||
|
||||
interact
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
fn interactive_rect(&mut self, id: Id, rect: &Rect) -> InteractInfo {
|
||||
|
|
|
@ -52,9 +52,10 @@ pub fn show_gui(raw_input_json: &str) -> String {
|
|||
use crate::app::GuiSettings;
|
||||
APP.lock().unwrap().show_gui(&mut emgui.layout);
|
||||
|
||||
emgui.layout.label("Style:");
|
||||
let mut style = emgui.style.clone();
|
||||
style.show_gui(&mut emgui.layout);
|
||||
emgui.layout.foldable("Style", |gui| {
|
||||
style.show_gui(gui);
|
||||
});
|
||||
emgui.style = style;
|
||||
|
||||
let commands = emgui.paint();
|
||||
|
|
70
src/style.rs
70
src/style.rs
|
@ -142,6 +142,76 @@ fn translate_cmd(out_commands: &mut Vec<PaintCmd>, style: &Style, cmd: GuiCmd) {
|
|||
out_commands.push(debug_rect(rect));
|
||||
}
|
||||
}
|
||||
GuiCmd::FoldableHeader {
|
||||
interact,
|
||||
label,
|
||||
open,
|
||||
rect,
|
||||
} => {
|
||||
let fill_color = if interact.active {
|
||||
srgba(136, 136, 136, 255)
|
||||
} else if interact.hovered {
|
||||
srgba(100, 100, 100, 255)
|
||||
} else {
|
||||
srgba(68, 68, 68, 255)
|
||||
};
|
||||
|
||||
let stroke_color = if interact.active {
|
||||
srgba(255, 255, 255, 255)
|
||||
} else if interact.hovered {
|
||||
srgba(255, 255, 255, 200)
|
||||
} else {
|
||||
srgba(255, 255, 255, 170)
|
||||
};
|
||||
|
||||
out_commands.push(PaintCmd::Rect {
|
||||
corner_radius: 3.0,
|
||||
fill_color: Some(fill_color),
|
||||
outline: None,
|
||||
pos: rect.pos,
|
||||
size: rect.size,
|
||||
});
|
||||
|
||||
// TODO: paint a little triangle or arrow or something instead of this
|
||||
|
||||
let box_side = 16.0;
|
||||
let box_rect = Rect::from_center_size(
|
||||
vec2(rect.min().x + box_side * 0.5, rect.center().y),
|
||||
vec2(box_side, box_side),
|
||||
);
|
||||
// Draw a minus:
|
||||
out_commands.push(PaintCmd::Line {
|
||||
points: vec![
|
||||
vec2(box_rect.min().x, box_rect.center().y),
|
||||
vec2(box_rect.max().x, box_rect.center().y),
|
||||
],
|
||||
color: stroke_color,
|
||||
width: style.line_width,
|
||||
});
|
||||
if open {
|
||||
// Draw it as a plus:
|
||||
out_commands.push(PaintCmd::Line {
|
||||
points: vec![
|
||||
vec2(box_rect.center().x, box_rect.min().y),
|
||||
vec2(box_rect.center().x, box_rect.max().y),
|
||||
],
|
||||
color: stroke_color,
|
||||
width: style.line_width,
|
||||
});
|
||||
}
|
||||
|
||||
out_commands.push(PaintCmd::Text {
|
||||
fill_color: stroke_color,
|
||||
font_name: style.font_name.clone(),
|
||||
font_size: style.font_size,
|
||||
pos: Vec2 {
|
||||
x: box_rect.max().x + 4.0,
|
||||
y: rect.center().y - style.font_size / 2.0,
|
||||
},
|
||||
text: label,
|
||||
text_align: TextAlign::Start,
|
||||
});
|
||||
}
|
||||
GuiCmd::RadioButton {
|
||||
checked,
|
||||
interact,
|
||||
|
|
|
@ -102,6 +102,13 @@ pub enum GuiCmd {
|
|||
rect: Rect,
|
||||
text: String,
|
||||
},
|
||||
// The header for a foldable region
|
||||
FoldableHeader {
|
||||
interact: InteractInfo,
|
||||
open: bool,
|
||||
rect: Rect,
|
||||
label: String,
|
||||
},
|
||||
RadioButton {
|
||||
checked: bool,
|
||||
interact: InteractInfo,
|
||||
|
|
Loading…
Reference in a new issue