Add rect field to InteractInfo struct
This commit is contained in:
parent
6e8cc8439b
commit
3f84836c20
7 changed files with 73 additions and 89 deletions
|
@ -19,14 +19,17 @@ pub struct LayoutOptions {
|
|||
/// Horizontal and vertical padding within a window frame.
|
||||
pub window_padding: Vec2,
|
||||
|
||||
/// Button size is text size plus this on each side
|
||||
pub button_padding: Vec2,
|
||||
|
||||
/// Horizontal and vertical spacing between widgets
|
||||
pub item_spacing: Vec2,
|
||||
|
||||
/// Indent foldable regions etc by this much.
|
||||
pub indent: f32,
|
||||
|
||||
/// Button size is text size plus this on each side
|
||||
pub button_padding: Vec2,
|
||||
/// Anything clickable is (at least) this wide.
|
||||
pub clickable_diameter: f32,
|
||||
|
||||
/// Checkboxed, radio button and foldables have an icon at the start.
|
||||
/// The text starts after this many pixels.
|
||||
|
@ -36,10 +39,11 @@ pub struct LayoutOptions {
|
|||
impl Default for LayoutOptions {
|
||||
fn default() -> Self {
|
||||
LayoutOptions {
|
||||
item_spacing: vec2(8.0, 4.0),
|
||||
window_padding: vec2(6.0, 6.0),
|
||||
indent: 21.0,
|
||||
button_padding: vec2(5.0, 3.0),
|
||||
item_spacing: vec2(8.0, 4.0),
|
||||
indent: 21.0,
|
||||
clickable_diameter: 10.0,
|
||||
start_icon_width: 20.0,
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +62,9 @@ pub struct GuiResponse {
|
|||
/// The mouse is interacting with this thing (e.g. dragging it)
|
||||
pub active: bool,
|
||||
|
||||
/// The region of the screen we are talking about
|
||||
pub rect: Rect,
|
||||
|
||||
/// Used for showing a popup (if any)
|
||||
data: Arc<Data>,
|
||||
}
|
||||
|
@ -308,7 +315,7 @@ impl Region {
|
|||
let font = &self.fonts()[text_style];
|
||||
let (text, text_size) = font.layout_multiline(&text, self.width());
|
||||
let text_cursor = self.cursor + self.options().button_padding;
|
||||
let (rect, interact) = self.reserve_space(
|
||||
let interact = self.reserve_space(
|
||||
vec2(
|
||||
self.available_space.x,
|
||||
text_size.y + 2.0 * self.options().button_padding.y,
|
||||
|
@ -328,11 +335,7 @@ impl Region {
|
|||
memory.open_foldables.contains(&id)
|
||||
};
|
||||
|
||||
self.add_graphic(GuiCmd::FoldableHeader {
|
||||
interact,
|
||||
rect,
|
||||
open,
|
||||
});
|
||||
self.add_graphic(GuiCmd::FoldableHeader { interact, open });
|
||||
self.add_text(
|
||||
text_cursor + vec2(self.options().start_icon_width, 0.0),
|
||||
text_style,
|
||||
|
@ -366,7 +369,7 @@ impl Region {
|
|||
};
|
||||
add_contents(&mut child_region);
|
||||
let size = child_region.bounding_size;
|
||||
self.reserve_space_inner(indent + size);
|
||||
self.reserve_space_without_padding(indent + size);
|
||||
}
|
||||
|
||||
/// A horizontally centered region of the given width.
|
||||
|
@ -398,7 +401,7 @@ impl Region {
|
|||
};
|
||||
add_contents(&mut child_region);
|
||||
let size = child_region.bounding_size;
|
||||
self.reserve_space_inner(size);
|
||||
self.reserve_space_without_padding(size);
|
||||
}
|
||||
|
||||
/// Temporarily split split a vertical layout into several columns.
|
||||
|
@ -436,7 +439,7 @@ impl Region {
|
|||
max_height = size.y.max(max_height);
|
||||
}
|
||||
|
||||
self.reserve_space_inner(vec2(self.available_space.x, max_height));
|
||||
self.reserve_space_without_padding(vec2(self.available_space.x, max_height));
|
||||
result
|
||||
}
|
||||
|
||||
|
@ -448,16 +451,14 @@ impl Region {
|
|||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
pub fn reserve_space(
|
||||
&mut self,
|
||||
size: Vec2,
|
||||
interaction_id: Option<Id>,
|
||||
) -> (Rect, InteractInfo) {
|
||||
pub fn reserve_space(&mut self, size: Vec2, interaction_id: Option<Id>) -> InteractInfo {
|
||||
let rect = Rect {
|
||||
pos: self.cursor,
|
||||
size,
|
||||
};
|
||||
self.reserve_space_inner(size + self.options().item_spacing);
|
||||
|
||||
self.reserve_space_without_padding(size + self.options().item_spacing);
|
||||
|
||||
let hovered = rect.contains(self.input().mouse_pos);
|
||||
let clicked = hovered && self.input().mouse_clicked;
|
||||
let active = if interaction_id.is_some() {
|
||||
|
@ -470,17 +471,17 @@ impl Region {
|
|||
false
|
||||
};
|
||||
|
||||
let interact = InteractInfo {
|
||||
InteractInfo {
|
||||
rect,
|
||||
hovered,
|
||||
clicked,
|
||||
active,
|
||||
};
|
||||
(rect, interact)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Return a Rect
|
||||
/// Reserve this much space and move the cursor.
|
||||
pub fn reserve_space_inner(&mut self, size: Vec2) {
|
||||
pub fn reserve_space_without_padding(&mut self, size: Vec2) {
|
||||
if self.dir == Direction::Horizontal {
|
||||
self.cursor.x += size.x;
|
||||
self.available_space.x -= size.x;
|
||||
|
@ -524,10 +525,12 @@ impl Region {
|
|||
}
|
||||
|
||||
pub fn response(&mut self, interact: InteractInfo) -> GuiResponse {
|
||||
// TODO: unify GuiResponse and InteractInfo. They are the same thing!
|
||||
GuiResponse {
|
||||
hovered: interact.hovered,
|
||||
clicked: interact.clicked,
|
||||
active: interact.active,
|
||||
rect: interact.rect,
|
||||
data: self.data.clone(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -128,6 +128,10 @@ impl Rect {
|
|||
pub fn max(&self) -> Vec2 {
|
||||
self.pos + self.size
|
||||
}
|
||||
|
||||
pub fn size(&self) -> Vec2 {
|
||||
self.size
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lerp(min: f32, max: f32, t: f32) -> f32 {
|
||||
|
|
|
@ -272,16 +272,15 @@ impl Painter {
|
|||
corner_radius,
|
||||
fill_color,
|
||||
outline,
|
||||
pos,
|
||||
size,
|
||||
rect,
|
||||
} => {
|
||||
path_points.clear();
|
||||
path_normals.clear();
|
||||
|
||||
let min = *pos;
|
||||
let max = *pos + *size;
|
||||
let min = rect.min();
|
||||
let max = rect.max();
|
||||
|
||||
let cr = corner_radius.min(size.x * 0.5).min(size.y * 0.5);
|
||||
let cr = corner_radius.min(rect.size.x * 0.5).min(rect.size.y * 0.5);
|
||||
|
||||
if cr <= 0.0 {
|
||||
path_points.push(vec2(min.x, min.y));
|
||||
|
|
|
@ -72,8 +72,7 @@ fn debug_rect(rect: Rect) -> PaintCmd {
|
|||
color: srgba(255, 255, 255, 255),
|
||||
width: 1.0,
|
||||
}),
|
||||
pos: rect.pos,
|
||||
size: rect.size,
|
||||
rect,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,30 +80,24 @@ fn debug_rect(rect: Rect) -> PaintCmd {
|
|||
fn translate_cmd(out_commands: &mut Vec<PaintCmd>, style: &Style, cmd: GuiCmd) {
|
||||
match cmd {
|
||||
GuiCmd::PaintCommands(mut commands) => out_commands.append(&mut commands),
|
||||
GuiCmd::Button { interact, rect } => {
|
||||
GuiCmd::Button { interact } => {
|
||||
out_commands.push(PaintCmd::Rect {
|
||||
corner_radius: 5.0,
|
||||
fill_color: Some(style.interact_fill_color(&interact)),
|
||||
outline: None,
|
||||
pos: rect.pos,
|
||||
size: rect.size,
|
||||
rect: interact.rect,
|
||||
});
|
||||
if style.debug_rects {
|
||||
out_commands.push(debug_rect(rect));
|
||||
out_commands.push(debug_rect(interact.rect));
|
||||
}
|
||||
}
|
||||
GuiCmd::Checkbox {
|
||||
checked,
|
||||
interact,
|
||||
rect,
|
||||
} => {
|
||||
let (small_icon_rect, big_icon_rect) = style.icon_rectangles(&rect);
|
||||
GuiCmd::Checkbox { checked, interact } => {
|
||||
let (small_icon_rect, big_icon_rect) = style.icon_rectangles(&interact.rect);
|
||||
out_commands.push(PaintCmd::Rect {
|
||||
corner_radius: 3.0,
|
||||
fill_color: Some(style.interact_fill_color(&interact)),
|
||||
outline: None,
|
||||
pos: big_icon_rect.pos,
|
||||
size: big_icon_rect.size,
|
||||
rect: big_icon_rect,
|
||||
});
|
||||
|
||||
let stroke_color = style.interact_stroke_color(&interact);
|
||||
|
@ -122,14 +115,10 @@ fn translate_cmd(out_commands: &mut Vec<PaintCmd>, style: &Style, cmd: GuiCmd) {
|
|||
}
|
||||
|
||||
if style.debug_rects {
|
||||
out_commands.push(debug_rect(rect));
|
||||
out_commands.push(debug_rect(interact.rect));
|
||||
}
|
||||
}
|
||||
GuiCmd::FoldableHeader {
|
||||
interact,
|
||||
open,
|
||||
rect,
|
||||
} => {
|
||||
GuiCmd::FoldableHeader { interact, open } => {
|
||||
let fill_color = style.interact_fill_color(&interact);
|
||||
let stroke_color = style.interact_stroke_color(&interact);
|
||||
|
||||
|
@ -137,13 +126,12 @@ fn translate_cmd(out_commands: &mut Vec<PaintCmd>, style: &Style, cmd: GuiCmd) {
|
|||
corner_radius: 3.0,
|
||||
fill_color: Some(fill_color),
|
||||
outline: None,
|
||||
pos: rect.pos,
|
||||
size: rect.size,
|
||||
rect: interact.rect,
|
||||
});
|
||||
|
||||
// TODO: paint a little triangle or arrow or something instead of this
|
||||
|
||||
let (small_icon_rect, _) = style.icon_rectangles(&rect);
|
||||
let (small_icon_rect, _) = style.icon_rectangles(&interact.rect);
|
||||
// Draw a minus:
|
||||
out_commands.push(PaintCmd::Line {
|
||||
points: vec![
|
||||
|
@ -165,15 +153,11 @@ fn translate_cmd(out_commands: &mut Vec<PaintCmd>, style: &Style, cmd: GuiCmd) {
|
|||
});
|
||||
}
|
||||
}
|
||||
GuiCmd::RadioButton {
|
||||
checked,
|
||||
interact,
|
||||
rect,
|
||||
} => {
|
||||
GuiCmd::RadioButton { checked, interact } => {
|
||||
let fill_color = style.interact_fill_color(&interact);
|
||||
let stroke_color = style.interact_stroke_color(&interact);
|
||||
|
||||
let (small_icon_rect, big_icon_rect) = style.icon_rectangles(&rect);
|
||||
let (small_icon_rect, big_icon_rect) = style.icon_rectangles(&interact.rect);
|
||||
|
||||
out_commands.push(PaintCmd::Circle {
|
||||
center: big_icon_rect.center(),
|
||||
|
@ -192,16 +176,16 @@ fn translate_cmd(out_commands: &mut Vec<PaintCmd>, style: &Style, cmd: GuiCmd) {
|
|||
}
|
||||
|
||||
if style.debug_rects {
|
||||
out_commands.push(debug_rect(rect));
|
||||
out_commands.push(debug_rect(interact.rect));
|
||||
}
|
||||
}
|
||||
GuiCmd::Slider {
|
||||
interact,
|
||||
max,
|
||||
min,
|
||||
rect,
|
||||
value,
|
||||
} => {
|
||||
let rect = interact.rect;
|
||||
let thin_rect = Rect::from_center_size(rect.center(), vec2(rect.size.x, 6.0));
|
||||
let marker_center_x = remap_clamp(value, min, max, rect.min().x, rect.max().x);
|
||||
|
||||
|
@ -214,16 +198,14 @@ fn translate_cmd(out_commands: &mut Vec<PaintCmd>, style: &Style, cmd: GuiCmd) {
|
|||
corner_radius: 2.0,
|
||||
fill_color: Some(style.background_fill_color()),
|
||||
outline: None,
|
||||
pos: thin_rect.pos,
|
||||
size: thin_rect.size,
|
||||
rect: thin_rect,
|
||||
});
|
||||
|
||||
out_commands.push(PaintCmd::Rect {
|
||||
corner_radius: 3.0,
|
||||
fill_color: Some(style.interact_fill_color(&interact)),
|
||||
outline: None,
|
||||
pos: marker_rect.pos,
|
||||
size: marker_rect.size,
|
||||
rect: marker_rect,
|
||||
});
|
||||
|
||||
if style.debug_rects {
|
||||
|
@ -253,8 +235,7 @@ fn translate_cmd(out_commands: &mut Vec<PaintCmd>, style: &Style, cmd: GuiCmd) {
|
|||
color: srgba(255, 255, 255, 255), // TODO
|
||||
width: 1.0,
|
||||
}),
|
||||
pos: rect.pos,
|
||||
size: rect.size,
|
||||
rect: rect,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,6 +89,9 @@ pub struct InteractInfo {
|
|||
|
||||
/// The mouse is interacting with this thing (e.g. dragging it)
|
||||
pub active: bool,
|
||||
|
||||
/// The region of the screen we are talking about
|
||||
pub rect: Rect,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
|
@ -97,29 +100,24 @@ pub enum GuiCmd {
|
|||
/// The background for a button
|
||||
Button {
|
||||
interact: InteractInfo,
|
||||
rect: Rect,
|
||||
},
|
||||
Checkbox {
|
||||
checked: bool,
|
||||
interact: InteractInfo,
|
||||
rect: Rect,
|
||||
},
|
||||
/// The header button background for a foldable region
|
||||
FoldableHeader {
|
||||
interact: InteractInfo,
|
||||
open: bool,
|
||||
rect: Rect,
|
||||
},
|
||||
RadioButton {
|
||||
checked: bool,
|
||||
interact: InteractInfo,
|
||||
rect: Rect,
|
||||
},
|
||||
Slider {
|
||||
interact: InteractInfo,
|
||||
max: f32,
|
||||
min: f32,
|
||||
rect: Rect,
|
||||
value: f32,
|
||||
},
|
||||
/// Paint a single line of mono-space text.
|
||||
|
@ -167,8 +165,7 @@ pub enum PaintCmd {
|
|||
corner_radius: f32,
|
||||
fill_color: Option<Color>,
|
||||
outline: Option<Outline>,
|
||||
pos: Vec2,
|
||||
size: Vec2,
|
||||
rect: Rect,
|
||||
},
|
||||
/// Paint a single line of text
|
||||
Text {
|
||||
|
|
|
@ -42,7 +42,7 @@ impl Widget for Label {
|
|||
let font = ®ion.fonts()[self.text_style];
|
||||
let (text, text_size) = font.layout_multiline(&self.text, region.width());
|
||||
region.add_text(region.cursor(), self.text_style, text);
|
||||
let (_, interact) = region.reserve_space(text_size, None);
|
||||
let interact = region.reserve_space(text_size, None);
|
||||
region.response(interact)
|
||||
}
|
||||
}
|
||||
|
@ -66,9 +66,9 @@ impl Widget for Button {
|
|||
let font = ®ion.fonts()[text_style];
|
||||
let (text, text_size) = font.layout_multiline(&self.text, region.width());
|
||||
let text_cursor = region.cursor() + region.options().button_padding;
|
||||
let (rect, interact) =
|
||||
let interact =
|
||||
region.reserve_space(text_size + 2.0 * region.options().button_padding, Some(id));
|
||||
region.add_graphic(GuiCmd::Button { interact, rect });
|
||||
region.add_graphic(GuiCmd::Button { interact });
|
||||
region.add_text(text_cursor, text_style, text);
|
||||
region.response(interact)
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ impl<'a> Widget for Checkbox<'a> {
|
|||
let text_cursor = region.cursor()
|
||||
+ region.options().button_padding
|
||||
+ vec2(region.options().start_icon_width, 0.0);
|
||||
let (rect, interact) = region.reserve_space(
|
||||
let interact = region.reserve_space(
|
||||
region.options().button_padding
|
||||
+ vec2(region.options().start_icon_width, 0.0)
|
||||
+ text_size
|
||||
|
@ -113,7 +113,6 @@ impl<'a> Widget for Checkbox<'a> {
|
|||
region.add_graphic(GuiCmd::Checkbox {
|
||||
checked: *self.checked,
|
||||
interact,
|
||||
rect,
|
||||
});
|
||||
region.add_text(text_cursor, text_style, text);
|
||||
region.response(interact)
|
||||
|
@ -150,7 +149,7 @@ impl Widget for RadioButton {
|
|||
let text_cursor = region.cursor()
|
||||
+ region.options().button_padding
|
||||
+ vec2(region.options().start_icon_width, 0.0);
|
||||
let (rect, interact) = region.reserve_space(
|
||||
let interact = region.reserve_space(
|
||||
region.options().button_padding
|
||||
+ vec2(region.options().start_icon_width, 0.0)
|
||||
+ text_size
|
||||
|
@ -160,7 +159,6 @@ impl Widget for RadioButton {
|
|||
region.add_graphic(GuiCmd::RadioButton {
|
||||
checked: self.checked,
|
||||
interact,
|
||||
rect,
|
||||
});
|
||||
region.add_text(text_cursor, text_style, text);
|
||||
region.response(interact)
|
||||
|
@ -218,24 +216,28 @@ impl<'a> Widget for Slider<'a> {
|
|||
if text_on_top {
|
||||
let (text, text_size) = font.layout_multiline(&full_text, region.width());
|
||||
region.add_text(region.cursor(), text_style, text);
|
||||
region.reserve_space_inner(text_size);
|
||||
region.reserve_space_without_padding(text_size);
|
||||
naked.add_to(region)
|
||||
} else {
|
||||
region.columns(2, |columns| {
|
||||
columns[1].add(label(full_text));
|
||||
naked.add_to(&mut columns[0])
|
||||
let response = naked.add_to(&mut columns[0]);
|
||||
columns[1].available_space.y = response.rect.size().y;
|
||||
columns[1].add(label(full_text)); // TODO: centered!
|
||||
response
|
||||
})
|
||||
}
|
||||
} else {
|
||||
let height = font.line_spacing().max(region.options().clickable_diameter);
|
||||
|
||||
let value = self.value;
|
||||
let min = self.min;
|
||||
let max = self.max;
|
||||
debug_assert!(min <= max);
|
||||
let id = region.combined_id(self.id);
|
||||
let (slider_rect, interact) = region.reserve_space(
|
||||
let interact = region.reserve_space(
|
||||
Vec2 {
|
||||
x: region.available_space.x,
|
||||
y: font.line_spacing(),
|
||||
y: height,
|
||||
},
|
||||
id,
|
||||
);
|
||||
|
@ -243,8 +245,8 @@ impl<'a> Widget for Slider<'a> {
|
|||
if interact.active {
|
||||
*value = remap_clamp(
|
||||
region.input().mouse_pos.x,
|
||||
slider_rect.min().x,
|
||||
slider_rect.max().x,
|
||||
interact.rect.min().x,
|
||||
interact.rect.max().x,
|
||||
min,
|
||||
max,
|
||||
);
|
||||
|
@ -254,7 +256,6 @@ impl<'a> Widget for Slider<'a> {
|
|||
interact,
|
||||
max,
|
||||
min,
|
||||
rect: slider_rect,
|
||||
value: *value,
|
||||
});
|
||||
|
||||
|
|
|
@ -82,8 +82,7 @@ impl App {
|
|||
gui.add_graphic(GuiCmd::PaintCommands(vec![PaintCmd::Rect {
|
||||
corner_radius: self.corner_radius,
|
||||
fill_color: Some(srgba(136, 136, 136, 255)),
|
||||
pos,
|
||||
size: self.size,
|
||||
rect: Rect::from_min_size(pos, self.size),
|
||||
outline: Some(Outline {
|
||||
width: self.stroke_width,
|
||||
color: srgba(255, 255, 255, 255),
|
||||
|
|
Loading…
Reference in a new issue