[refactor] unify InteractInfo and GuiResponse to Response

This commit is contained in:
Emil Ernerfeldt 2020-08-30 08:52:42 +02:00
parent 843074eb7d
commit c23dfd155c
15 changed files with 212 additions and 294 deletions

View file

@ -140,7 +140,7 @@ impl Area {
} }
} }
pub fn show(self, ctx: &Arc<Context>, add_contents: impl FnOnce(&mut Ui)) -> InteractInfo { pub fn show(self, ctx: &Arc<Context>, add_contents: impl FnOnce(&mut Ui)) -> Response {
let prepared = self.begin(ctx); let prepared = self.begin(ctx);
let mut content_ui = prepared.content_ui(ctx); let mut content_ui = prepared.content_ui(ctx);
add_contents(&mut content_ui); add_contents(&mut content_ui);
@ -166,7 +166,7 @@ impl Prepared {
) )
} }
pub(crate) fn end(self, ctx: &Arc<Context>, content_ui: Ui) -> InteractInfo { pub(crate) fn end(self, ctx: &Arc<Context>, content_ui: Ui) -> Response {
let Prepared { let Prepared {
layer, layer,
mut state, mut state,
@ -183,11 +183,11 @@ impl Prepared {
} else { } else {
None None
}; };
let move_interact = let move_response =
ctx.interact(layer, clip_rect, rect, interact_id, Sense::click_and_drag()); ctx.interact(layer, clip_rect, rect, interact_id, Sense::click_and_drag());
let input = ctx.input(); let input = ctx.input();
if move_interact.active { if move_response.active {
state.pos += input.mouse.delta; state.pos += input.mouse.delta;
state.vel = input.mouse.velocity; state.vel = input.mouse.velocity;
} else { } else {
@ -219,7 +219,7 @@ impl Prepared {
// &format!("Area size: {:?}", state.size), // &format!("Area size: {:?}", state.size),
// ); // );
if move_interact.active if move_response.active
|| mouse_pressed_on_area(ctx, layer) || mouse_pressed_on_area(ctx, layer)
|| !ctx.memory().areas.visible_last_frame(&layer) || !ctx.memory().areas.visible_last_frame(&layer)
{ {
@ -228,7 +228,7 @@ impl Prepared {
} }
ctx.memory().areas.set_state(layer, state); ctx.memory().areas.set_state(layer, state);
move_interact move_response
} }
} }

View file

@ -69,11 +69,11 @@ impl State {
} }
/// Paint the arrow icon that indicated if the region is open or not /// Paint the arrow icon that indicated if the region is open or not
pub fn paint_icon(&self, ui: &mut Ui, interact: &InteractInfo) { pub fn paint_icon(&self, ui: &mut Ui, response: &Response) {
let stroke_color = ui.style().interact(interact).stroke_color; let stroke_color = ui.style().interact(response).stroke_color;
let stroke_width = ui.style().interact(interact).stroke_width; let stroke_width = ui.style().interact(response).stroke_width;
let rect = interact.rect; let rect = response.rect;
let openness = self.openness(ui); let openness = self.openness(ui);
@ -135,10 +135,10 @@ impl State {
r r
})) }))
} else if self.open { } else if self.open {
let r_interact = ui.add_custom(add_contents); let ret_rect = ui.add_custom(add_contents);
let full_size = r_interact.1.size(); let full_size = ret_rect.1.size();
self.open_height = Some(full_size.y); self.open_height = Some(full_size.y);
Some(r_interact) Some(ret_rect)
} else { } else {
None None
} }
@ -211,27 +211,27 @@ impl CollapsingHeader {
); );
let rect = ui.allocate_space(size); let rect = ui.allocate_space(size);
let interact = ui.interact(rect, id, Sense::click()); let response = ui.interact(rect, id, Sense::click());
let text_pos = pos2(text_pos.x, interact.rect.center().y - galley.size.y / 2.0); let text_pos = pos2(text_pos.x, response.rect.center().y - galley.size.y / 2.0);
let mut state = State::from_memory_with_default_open(ui.ctx(), id, default_open); let mut state = State::from_memory_with_default_open(ui.ctx(), id, default_open);
if interact.clicked { if response.clicked {
state.toggle(ui); state.toggle(ui);
} }
let bg_index = ui.painter().add(PaintCmd::Noop); let bg_index = ui.painter().add(PaintCmd::Noop);
{ {
let (mut icon_rect, _) = ui.style().icon_rectangles(interact.rect); let (mut icon_rect, _) = ui.style().icon_rectangles(response.rect);
icon_rect.set_center(pos2( icon_rect.set_center(pos2(
interact.rect.left() + ui.style().indent / 2.0, response.rect.left() + ui.style().indent / 2.0,
interact.rect.center().y, response.rect.center().y,
)); ));
let icon_interact = InteractInfo { let icon_response = Response {
rect: icon_rect, rect: icon_rect,
..interact ..response.clone()
}; };
state.paint_icon(ui, &icon_interact); state.paint_icon(ui, &icon_response);
} }
let painter = ui.painter(); let painter = ui.painter();
@ -239,16 +239,16 @@ impl CollapsingHeader {
text_pos, text_pos,
galley, galley,
label.text_style, label.text_style,
ui.style().interact(&interact).stroke_color, ui.style().interact(&response).stroke_color,
); );
painter.set( painter.set(
bg_index, bg_index,
PaintCmd::Rect { PaintCmd::Rect {
corner_radius: ui.style().interact(&interact).corner_radius, corner_radius: ui.style().interact(&response).corner_radius,
fill: ui.style().interact(&interact).bg_fill, fill: ui.style().interact(&response).bg_fill,
outline: None, outline: None,
rect: interact.rect, rect: response.rect,
}, },
); );
@ -257,8 +257,8 @@ impl CollapsingHeader {
pub fn show<R>(self, ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> Option<R> { pub fn show<R>(self, ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> Option<R> {
let Prepared { id, mut state } = self.begin(ui); let Prepared { id, mut state } = self.begin(ui);
let r_interact = state.add_contents(ui, |ui| ui.indent(id, add_contents).0); let ret_response = state.add_contents(ui, |ui| ui.indent(id, add_contents).0);
let ret = r_interact.map(|ri| ri.0); let ret = ret_response.map(|ri| ri.0);
ui.memory().collapsing_headers.insert(id, state); ui.memory().collapsing_headers.insert(id, state);
ret ret
} }

View file

@ -18,7 +18,7 @@ pub fn show_popup(
id: Id, id: Id,
window_pos: Pos2, window_pos: Pos2,
add_contents: impl FnOnce(&mut Ui), add_contents: impl FnOnce(&mut Ui),
) -> InteractInfo { ) -> Response {
use containers::*; use containers::*;
Area::new(id) Area::new(id)
.order(Order::Foreground) .order(Order::Foreground)

View file

@ -119,7 +119,7 @@ impl Resize {
struct Prepared { struct Prepared {
id: Id, id: Id,
state: State, state: State,
corner_interact: Option<InteractInfo>, corner_response: Option<Response>,
content_ui: Ui, content_ui: Ui,
} }
@ -143,19 +143,19 @@ impl Resize {
let position = ui.available().min; let position = ui.available().min;
let corner_interact = if self.resizable { let corner_response = if self.resizable {
// Resize-corner: // Resize-corner:
let corner_size = Vec2::splat(ui.style().resize_corner_size); let corner_size = Vec2::splat(ui.style().resize_corner_size);
let corner_rect = let corner_rect =
Rect::from_min_size(position + state.desired_size - corner_size, corner_size); Rect::from_min_size(position + state.desired_size - corner_size, corner_size);
let corner_interact = ui.interact(corner_rect, id.with("corner"), Sense::drag()); let corner_response = ui.interact(corner_rect, id.with("corner"), Sense::drag());
if corner_interact.active { if corner_response.active {
if let Some(mouse_pos) = ui.input().mouse.pos { if let Some(mouse_pos) = ui.input().mouse.pos {
state.desired_size = mouse_pos - position + 0.5 * corner_interact.rect.size(); state.desired_size = mouse_pos - position + 0.5 * corner_response.rect.size();
} }
} }
Some(corner_interact) Some(corner_response)
} else { } else {
None None
}; };
@ -188,7 +188,7 @@ impl Resize {
Prepared { Prepared {
id, id,
state, state,
corner_interact, corner_response,
content_ui, content_ui,
} }
} }
@ -204,7 +204,7 @@ impl Resize {
let Prepared { let Prepared {
id, id,
mut state, mut state,
corner_interact, corner_response,
content_ui, content_ui,
} = prepared; } = prepared;
@ -229,7 +229,7 @@ impl Resize {
// ------------------------------ // ------------------------------
if self.outline && corner_interact.is_some() { if self.outline && corner_response.is_some() {
let rect = Rect::from_min_size(content_ui.top_left(), state.desired_size); let rect = Rect::from_min_size(content_ui.top_left(), state.desired_size);
let rect = rect.expand(2.0); // breathing room for content let rect = rect.expand(2.0); // breathing room for content
ui.painter().add(paint::PaintCmd::Rect { ui.painter().add(paint::PaintCmd::Rect {
@ -240,10 +240,10 @@ impl Resize {
}); });
} }
if let Some(corner_interact) = corner_interact { if let Some(corner_response) = corner_response {
paint_resize_corner(ui, &corner_interact); paint_resize_corner(ui, &corner_response);
if corner_interact.hovered || corner_interact.active { if corner_response.hovered || corner_response.active {
ui.ctx().output().cursor_icon = CursorIcon::ResizeNwSe; ui.ctx().output().cursor_icon = CursorIcon::ResizeNwSe;
} }
} }
@ -267,10 +267,10 @@ impl Resize {
use crate::paint::LineStyle; use crate::paint::LineStyle;
pub fn paint_resize_corner(ui: &mut Ui, interact: &InteractInfo) { pub fn paint_resize_corner(ui: &mut Ui, response: &Response) {
let color = ui.style().interact(interact).stroke_color; let color = ui.style().interact(response).stroke_color;
let width = ui.style().interact(interact).stroke_width; let width = ui.style().interact(response).stroke_width;
paint_resize_corner_with_style(ui, &interact.rect, LineStyle::new(width, color)); paint_resize_corner_with_style(ui, &response.rect, LineStyle::new(width, color));
} }
pub fn paint_resize_corner_with_style(ui: &mut Ui, rect: &Rect, style: LineStyle) { pub fn paint_resize_corner_with_style(ui: &mut Ui, rect: &Rect, style: LineStyle) {

View file

@ -175,8 +175,8 @@ impl Prepared {
if content_is_too_small { if content_is_too_small {
// Drag contents to scroll (for touch screens mostly): // Drag contents to scroll (for touch screens mostly):
let content_interact = ui.interact(inner_rect, id.with("area"), Sense::drag()); let content_response = ui.interact(inner_rect, id.with("area"), Sense::drag());
if content_interact.active { if content_response.active {
state.offset.y -= ui.input().mouse.delta.y; state.offset.y -= ui.input().mouse.delta.y;
} }
} }
@ -225,26 +225,26 @@ impl Prepared {
// intentionally use same id for inside and outside of handle // intentionally use same id for inside and outside of handle
let interact_id = id.with("vertical"); let interact_id = id.with("vertical");
let mut interact = ui.interact(handle_rect, interact_id, Sense::click_and_drag()); let mut response = ui.interact(handle_rect, interact_id, Sense::click_and_drag());
if let Some(mouse_pos) = ui.input().mouse.pos { if let Some(mouse_pos) = ui.input().mouse.pos {
if interact.active { if response.active {
if inner_rect.top() <= mouse_pos.y && mouse_pos.y <= inner_rect.bottom() { if inner_rect.top() <= mouse_pos.y && mouse_pos.y <= inner_rect.bottom() {
state.offset.y += state.offset.y +=
ui.input().mouse.delta.y * content_size.y / inner_rect.height(); ui.input().mouse.delta.y * content_size.y / inner_rect.height();
} }
} else { } else {
// Check for mouse down outside handle: // Check for mouse down outside handle:
let scroll_bg_interact = let scroll_bg_response =
ui.interact(outer_scroll_rect, interact_id, Sense::click_and_drag()); ui.interact(outer_scroll_rect, interact_id, Sense::click_and_drag());
if scroll_bg_interact.active { if scroll_bg_response.active {
// Center scroll at mouse pos: // Center scroll at mouse pos:
let mpos_top = mouse_pos.y - handle_rect.height() / 2.0; let mpos_top = mouse_pos.y - handle_rect.height() / 2.0;
state.offset.y = remap(mpos_top, top..=bottom, 0.0..=content_size.y); state.offset.y = remap(mpos_top, top..=bottom, 0.0..=content_size.y);
} }
interact = interact.union(scroll_bg_interact); response = response.union(scroll_bg_response);
} }
} }
@ -265,8 +265,8 @@ impl Prepared {
} }
let style = ui.style(); let style = ui.style();
let handle_fill = style.interact(&interact).fill; let handle_fill = style.interact(&response).fill;
let handle_outline = style.interact(&interact).rect_outline; let handle_outline = style.interact(&response).rect_outline;
ui.painter().add(paint::PaintCmd::Rect { ui.painter().add(paint::PaintCmd::Rect {
rect: outer_scroll_rect, rect: outer_scroll_rect,

View file

@ -156,11 +156,7 @@ impl<'open> Window<'open> {
} }
impl<'open> Window<'open> { impl<'open> Window<'open> {
pub fn show( pub fn show(self, ctx: &Arc<Context>, add_contents: impl FnOnce(&mut Ui)) -> Option<Response> {
self,
ctx: &Arc<Context>,
add_contents: impl FnOnce(&mut Ui),
) -> Option<InteractInfo> {
self.show_impl(ctx, Box::new(add_contents)) self.show_impl(ctx, Box::new(add_contents))
} }
@ -168,7 +164,7 @@ impl<'open> Window<'open> {
self, self,
ctx: &Arc<Context>, ctx: &Arc<Context>,
add_contents: Box<dyn FnOnce(&mut Ui) + 'c>, add_contents: Box<dyn FnOnce(&mut Ui) + 'c>,
) -> Option<InteractInfo> { ) -> Option<Response> {
let Window { let Window {
title_label, title_label,
open, open,
@ -309,9 +305,9 @@ impl<'open> Window<'open> {
); );
} }
} }
let full_interact = area.end(ctx, area_content_ui); let full_response = area.end(ctx, area_content_ui);
Some(full_interact) Some(full_response)
} }
} }
@ -603,11 +599,11 @@ fn show_title_bar(
ui.allocate_space(vec2(0.0, 0.0)); // HACK: will add left spacing ui.allocate_space(vec2(0.0, 0.0)); // HACK: will add left spacing
let rect = ui.allocate_space(Vec2::splat(button_size)); let rect = ui.allocate_space(Vec2::splat(button_size));
let collapse_button_interact = ui.interact(rect, collapsing_id, Sense::click()); let collapse_button_response = ui.interact(rect, collapsing_id, Sense::click());
if collapse_button_interact.clicked { if collapse_button_response.clicked {
collapsing.toggle(ui); collapsing.toggle(ui);
} }
collapsing.paint_icon(ui, &collapse_button_interact); collapsing.paint_icon(ui, &collapse_button_response);
} }
let title_galley = title_label.layout(ui); let title_galley = title_label.layout(ui);
@ -688,7 +684,7 @@ impl TitleBar {
} }
} }
fn close_button_ui(&self, ui: &mut Ui) -> InteractInfo { fn close_button_ui(&self, ui: &mut Ui) -> Response {
let button_size = ui.style().start_icon_width; let button_size = ui.style().start_icon_width;
let button_rect = Rect::from_min_size( let button_rect = Rect::from_min_size(
pos2( pos2(
@ -702,13 +698,13 @@ impl TitleBar {
} }
} }
fn close_button(ui: &mut Ui, rect: Rect) -> InteractInfo { fn close_button(ui: &mut Ui, rect: Rect) -> Response {
let close_id = ui.make_child_id("window_close_button"); let close_id = ui.make_child_id("window_close_button");
let interact = ui.interact(rect, close_id, Sense::click()); let response = ui.interact(rect, close_id, Sense::click());
ui.expand_to_include_child(interact.rect); ui.expand_to_include_child(response.rect);
let stroke_color = ui.style().interact(&interact).stroke_color; let stroke_color = ui.style().interact(&response).stroke_color;
let stroke_width = ui.style().interact(&interact).stroke_width; let stroke_width = ui.style().interact(&response).stroke_width;
ui.painter().line_segment( ui.painter().line_segment(
[rect.left_top(), rect.right_bottom()], [rect.left_top(), rect.right_bottom()],
(stroke_width, stroke_color), (stroke_width, stroke_color),
@ -717,5 +713,5 @@ fn close_button(ui: &mut Ui, rect: Rect) -> InteractInfo {
[rect.right_top(), rect.left_bottom()], [rect.right_top(), rect.left_bottom()],
(stroke_width, stroke_color), (stroke_width, stroke_color),
); );
interact response
} }

View file

@ -347,14 +347,15 @@ impl Context {
} }
} }
pub fn interact( /// Use `ui.interact` instead
&self, pub(crate) fn interact(
self: &Arc<Self>,
layer: Layer, layer: Layer,
clip_rect: Rect, clip_rect: Rect,
rect: Rect, rect: Rect,
interaction_id: Option<Id>, interaction_id: Option<Id>,
sense: Sense, sense: Sense,
) -> InteractInfo { ) -> Response {
let interact_rect = rect.expand2(0.5 * self.style().item_spacing); // make it easier to click. TODO: nice way to do this let interact_rect = rect.expand2(0.5 * self.style().item_spacing); // make it easier to click. TODO: nice way to do this
let hovered = self.contains_mouse(layer, clip_rect, interact_rect); let hovered = self.contains_mouse(layer, clip_rect, interact_rect);
let has_kb_focus = interaction_id let has_kb_focus = interaction_id
@ -363,7 +364,8 @@ impl Context {
if interaction_id.is_none() || sense == Sense::nothing() { if interaction_id.is_none() || sense == Sense::nothing() {
// Not interested in input: // Not interested in input:
return InteractInfo { return Response {
ctx: self.clone(),
sense, sense,
rect, rect,
hovered, hovered,
@ -385,7 +387,8 @@ impl Context {
if self.input.mouse.pressed { if self.input.mouse.pressed {
if hovered { if hovered {
let mut info = InteractInfo { let mut response = Response {
ctx: self.clone(),
sense, sense,
rect, rect,
hovered: true, hovered: true,
@ -398,7 +401,7 @@ impl Context {
if sense.click && memory.interaction.click_id.is_none() { if sense.click && memory.interaction.click_id.is_none() {
// start of a click // start of a click
memory.interaction.click_id = Some(interaction_id); memory.interaction.click_id = Some(interaction_id);
info.active = true; response.active = true;
} }
if sense.drag if sense.drag
@ -408,13 +411,14 @@ impl Context {
memory.interaction.drag_id = Some(interaction_id); memory.interaction.drag_id = Some(interaction_id);
memory.interaction.drag_is_window = false; memory.interaction.drag_is_window = false;
memory.window_interaction = None; // HACK: stop moving windows (if any) memory.window_interaction = None; // HACK: stop moving windows (if any)
info.active = true; response.active = true;
} }
info response
} else { } else {
// miss // miss
InteractInfo { Response {
ctx: self.clone(),
sense, sense,
rect, rect,
hovered, hovered,
@ -426,7 +430,8 @@ impl Context {
} }
} else if self.input.mouse.released { } else if self.input.mouse.released {
let clicked = hovered && active && self.input.mouse.could_be_click; let clicked = hovered && active && self.input.mouse.could_be_click;
InteractInfo { Response {
ctx: self.clone(),
sense, sense,
rect, rect,
hovered, hovered,
@ -436,7 +441,8 @@ impl Context {
has_kb_focus, has_kb_focus,
} }
} else if self.input.mouse.down { } else if self.input.mouse.down {
InteractInfo { Response {
ctx: self.clone(),
sense, sense,
rect, rect,
hovered: hovered && active, hovered: hovered && active,
@ -446,7 +452,8 @@ impl Context {
has_kb_focus, has_kb_focus,
} }
} else { } else {
InteractInfo { Response {
ctx: self.clone(),
sense, sense,
rect, rect,
hovered, hovered,

View file

@ -625,8 +625,8 @@ impl Painting {
fn content(&mut self, ui: &mut Ui) { fn content(&mut self, ui: &mut Ui) {
let rect = ui.allocate_space(ui.available_finite().size()); let rect = ui.allocate_space(ui.available_finite().size());
let interact = ui.interact(rect, ui.id(), Sense::drag()); let response = ui.interact(rect, ui.id(), Sense::drag());
let rect = interact.rect; let rect = response.rect;
let clip_rect = ui.clip_rect().intersect(rect); // Make sure we don't paint out of bounds let clip_rect = ui.clip_rect().intersect(rect); // Make sure we don't paint out of bounds
let painter = Painter::new(ui.ctx().clone(), ui.layer(), clip_rect); let painter = Painter::new(ui.ctx().clone(), ui.layer(), clip_rect);
@ -636,7 +636,7 @@ impl Painting {
let current_line = self.lines.last_mut().unwrap(); let current_line = self.lines.last_mut().unwrap();
if interact.active { if response.active {
if let Some(mouse_pos) = ui.input().mouse.pos { if let Some(mouse_pos) = ui.input().mouse.pos {
let canvas_pos = mouse_pos - rect.min; let canvas_pos = mouse_pos - rect.min;
if current_line.last() != Some(&canvas_pos) { if current_line.last() != Some(&canvas_pos) {
@ -669,7 +669,7 @@ use crate::layout::*;
#[cfg_attr(feature = "serde", serde(default))] #[cfg_attr(feature = "serde", serde(default))]
struct LayoutDemo { struct LayoutDemo {
dir: Direction, dir: Direction,
align: Option<Align>, // None == jusitifed align: Option<Align>, // None == justified
reversed: bool, reversed: bool,
} }
@ -735,7 +735,7 @@ impl LayoutDemo {
} }
if ui if ui
.add(RadioButton::new(self.align == None, "Justified")) .add(RadioButton::new(self.align == None, "Justified"))
.tooltip_text("Try to fill full width/heigth (e.g. buttons)") .tooltip_text("Try to fill full width/height (e.g. buttons)")
.clicked .clicked
{ {
self.align = None; self.align = None;

View file

@ -111,19 +111,19 @@ fn menu_impl<'c>(
button = button.fill(Some(ui.style().interact.active.fill)); button = button.fill(Some(ui.style().interact.active.fill));
} }
let button_interact = ui.add(button); let button_response = ui.add(button);
interact_with_menu_button(&mut bar_state, ui.input(), menu_id, &button_interact); interact_with_menu_button(&mut bar_state, ui.input(), menu_id, &button_response);
if bar_state.open_menu == Some(menu_id) { if bar_state.open_menu == Some(menu_id) {
let area = Area::new(menu_id) let area = Area::new(menu_id)
.order(Order::Foreground) .order(Order::Foreground)
.fixed_pos(button_interact.rect.left_bottom()); .fixed_pos(button_response.rect.left_bottom());
let frame = Frame::menu(ui.style()); let frame = Frame::menu(ui.style());
let resize = Resize::default().auto_sized().outline(false); let resize = Resize::default().auto_sized().outline(false);
let menu_interact = area.show(ui.ctx(), |ui| { let menu_response = area.show(ui.ctx(), |ui| {
frame.show(ui, |ui| { frame.show(ui, |ui| {
resize.show(ui, |ui| { resize.show(ui, |ui| {
let mut style = ui.style().clone(); let mut style = ui.style().clone();
@ -141,7 +141,7 @@ fn menu_impl<'c>(
}) })
}); });
if menu_interact.hovered && ui.input().mouse.released { if menu_response.hovered && ui.input().mouse.released {
bar_state.open_menu = None; bar_state.open_menu = None;
} }
} }
@ -153,9 +153,9 @@ fn interact_with_menu_button(
bar_state: &mut BarState, bar_state: &mut BarState,
input: &InputState, input: &InputState,
menu_id: Id, menu_id: Id,
button_interact: &GuiResponse, button_response: &Response,
) { ) {
if button_interact.hovered && input.mouse.pressed { if button_response.hovered && input.mouse.pressed {
if bar_state.open_menu.is_some() { if bar_state.open_menu.is_some() {
bar_state.open_menu = None; bar_state.open_menu = None;
} else { } else {
@ -164,7 +164,7 @@ fn interact_with_menu_button(
} }
} }
if button_interact.hovered && input.mouse.released && bar_state.open_menu.is_some() { if button_response.hovered && input.mouse.released && bar_state.open_menu.is_some() {
let time_since_open = input.time - bar_state.open_time; let time_since_open = input.time - bar_state.open_time;
if time_since_open < 0.4 { if time_since_open < 0.4 {
// A quick click // A quick click
@ -176,7 +176,7 @@ fn interact_with_menu_button(
} }
} }
if button_interact.hovered && bar_state.open_menu.is_some() { if button_response.hovered && bar_state.open_menu.is_some() {
bar_state.open_menu = Some(menu_id); bar_state.open_menu = Some(menu_id);
} }
} }

View file

@ -152,12 +152,12 @@ impl Default for Interact {
} }
impl Interact { impl Interact {
pub fn style(&self, interact: &InteractInfo) -> &WidgetStyle { pub fn style(&self, response: &Response) -> &WidgetStyle {
if interact.active || interact.has_kb_focus { if response.active || response.has_kb_focus {
&self.active &self.active
} else if interact.sense == Sense::nothing() { } else if response.sense == Sense::nothing() {
&self.disabled &self.disabled
} else if interact.hovered { } else if response.hovered {
&self.hovered &self.hovered
} else { } else {
&self.inactive &self.inactive
@ -216,9 +216,10 @@ impl Default for MenuBar {
} }
impl Style { impl Style {
// TODO: rename style.interact() to something better
/// Use this style for interactive things /// Use this style for interactive things
pub fn interact(&self, interact: &InteractInfo) -> &WidgetStyle { pub fn interact(&self, response: &Response) -> &WidgetStyle {
self.interact.style(interact) self.interact.style(response)
} }
/// Returns small icon rectangle and big icon rectangle /// Returns small icon rectangle and big icon rectangle

View file

@ -46,75 +46,16 @@ impl Default for CursorIcon {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/// The result of an interaction.
///
/// For instance, this lets you know whether or not a widget has been clicked this frame.
#[derive(Clone, Copy, Debug)]
// #[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct InteractInfo {
// IN:
/// The region of the screen we are talking about
pub rect: Rect,
/// The senses (click or drag) that the widget is interested in (if any).
pub sense: Sense,
// OUT:
/// The mouse is hovering above this thing
pub hovered: bool,
/// The mouse pressed this thing earlier, and now released on this thing too.
pub clicked: bool,
pub double_clicked: bool,
/// The mouse is interacting with this thing (e.g. dragging it or holding it)
pub active: bool,
/// This widget has the keyboard focus (i.e. is receiving key pressed)
pub has_kb_focus: bool,
}
impl InteractInfo {
pub fn nothing() -> Self {
Self {
rect: Rect::nothing(),
sense: Sense::nothing(),
hovered: false,
clicked: false,
double_clicked: false,
active: false,
has_kb_focus: false,
}
}
pub fn from_rect(rect: Rect) -> Self {
Self {
rect,
..Self::nothing()
}
}
pub fn union(self, other: Self) -> Self {
Self {
rect: self.rect.union(other.rect),
sense: self.sense.union(other.sense),
hovered: self.hovered || other.hovered,
clicked: self.clicked || other.clicked,
double_clicked: self.double_clicked || other.double_clicked,
active: self.active || other.active,
has_kb_focus: self.has_kb_focus || other.has_kb_focus,
}
}
}
// ----------------------------------------------------------------------------
/// The result of adding a widget to an `Ui`. /// The result of adding a widget to an `Ui`.
/// ///
/// This lets you know whether or not a widget has been clicked this frame. /// This lets you know whether or not a widget has been clicked this frame.
/// It also lets you easily show a tooltip on hover. /// It also lets you easily show a tooltip on hover.
pub struct GuiResponse { #[derive(Clone)]
pub struct Response {
// CONTEXT:
/// Used for optionally showing a tooltip
pub ctx: Arc<Context>,
// IN: // IN:
/// The area of the screen we are talking about /// The area of the screen we are talking about
pub rect: Rect, pub rect: Rect,
@ -129,6 +70,7 @@ pub struct GuiResponse {
/// The mouse clicked this thing this frame /// The mouse clicked this thing this frame
pub clicked: bool, pub clicked: bool,
/// The thing was double-clicked
pub double_clicked: bool, pub double_clicked: bool,
/// The mouse is interacting with this thing (e.g. dragging it) /// The mouse is interacting with this thing (e.g. dragging it)
@ -136,13 +78,9 @@ pub struct GuiResponse {
/// This widget has the keyboard focus (i.e. is receiving key pressed) /// This widget has the keyboard focus (i.e. is receiving key pressed)
pub has_kb_focus: bool, pub has_kb_focus: bool,
// CONTEXT:
/// Used for optionally showing a tooltip
pub ctx: Arc<Context>,
} }
impl GuiResponse { impl Response {
/// Show some stuff if the item was hovered /// Show some stuff if the item was hovered
pub fn tooltip(&mut self, add_contents: impl FnOnce(&mut Ui)) -> &mut Self { pub fn tooltip(&mut self, add_contents: impl FnOnce(&mut Ui)) -> &mut Self {
if self.hovered { if self.hovered {
@ -159,16 +97,18 @@ impl GuiResponse {
} }
} }
impl Into<InteractInfo> for GuiResponse { impl Response {
fn into(self) -> InteractInfo { pub fn union(self, other: Self) -> Self {
InteractInfo { assert!(Arc::ptr_eq(&self.ctx, &other.ctx));
rect: self.rect, Self {
sense: self.sense, ctx: self.ctx,
hovered: self.hovered, rect: self.rect.union(other.rect),
clicked: self.clicked, sense: self.sense.union(other.sense),
double_clicked: self.double_clicked, hovered: self.hovered || other.hovered,
active: self.active, clicked: self.clicked || other.clicked,
has_kb_focus: self.has_kb_focus, double_clicked: self.double_clicked || other.double_clicked,
active: self.active || other.active,
has_kb_focus: self.has_kb_focus || other.has_kb_focus,
} }
} }
} }

View file

@ -327,12 +327,12 @@ impl Ui {
/// # Interaction /// # Interaction
impl Ui { impl Ui {
pub fn interact(&self, rect: Rect, id: Id, sense: Sense) -> InteractInfo { pub fn interact(&self, rect: Rect, id: Id, sense: Sense) -> Response {
self.ctx() self.ctx()
.interact(self.layer(), self.clip_rect(), rect, Some(id), sense) .interact(self.layer(), self.clip_rect(), rect, Some(id), sense)
} }
pub fn interact_hover(&self, rect: Rect) -> InteractInfo { pub fn interact_hover(&self, rect: Rect) -> Response {
self.ctx() self.ctx()
.interact(self.layer(), self.clip_rect(), rect, None, Sense::nothing()) .interact(self.layer(), self.clip_rect(), rect, None, Sense::nothing())
} }
@ -341,30 +341,6 @@ impl Ui {
self.interact_hover(rect).hovered self.interact_hover(rect).hovered
} }
#[must_use]
pub fn response(&mut self, interact: InteractInfo) -> GuiResponse {
// TODO: unify GuiResponse and InteractInfo. They are the same thing!
let InteractInfo {
sense,
hovered,
clicked,
double_clicked,
active,
has_kb_focus,
rect,
} = interact;
GuiResponse {
sense,
hovered,
clicked,
double_clicked,
active,
has_kb_focus,
rect,
ctx: self.ctx().clone(),
}
}
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// Stuff that moves the cursor, i.e. allocates space in this ui! // Stuff that moves the cursor, i.e. allocates space in this ui!
@ -429,44 +405,43 @@ impl Ui {
/// # Adding widgets /// # Adding widgets
impl Ui { impl Ui {
pub fn add(&mut self, widget: impl Widget) -> GuiResponse { pub fn add(&mut self, widget: impl Widget) -> Response {
let interact = widget.ui(self); widget.ui(self)
self.response(interact)
} }
/// Shortcut for `add(Label::new(text))` /// Shortcut for `add(Label::new(text))`
pub fn label(&mut self, label: impl Into<Label>) -> GuiResponse { pub fn label(&mut self, label: impl Into<Label>) -> Response {
self.add(label.into()) self.add(label.into())
} }
/// Shortcut for `add(Label::new(text).heading())` /// Shortcut for `add(Label::new(text).heading())`
pub fn heading(&mut self, label: impl Into<Label>) -> GuiResponse { pub fn heading(&mut self, label: impl Into<Label>) -> Response {
self.add(label.into().heading()) self.add(label.into().heading())
} }
/// Shortcut for `add(Hyperlink::new(url))` /// Shortcut for `add(Hyperlink::new(url))`
pub fn hyperlink(&mut self, url: impl Into<String>) -> GuiResponse { pub fn hyperlink(&mut self, url: impl Into<String>) -> Response {
self.add(Hyperlink::new(url)) self.add(Hyperlink::new(url))
} }
/// Shortcut for `add(Button::new(text))` /// Shortcut for `add(Button::new(text))`
pub fn button(&mut self, text: impl Into<String>) -> GuiResponse { pub fn button(&mut self, text: impl Into<String>) -> Response {
self.add(Button::new(text)) self.add(Button::new(text))
} }
// Argument order matching that of Dear ImGui // Argument order matching that of Dear ImGui
/// Show a checkbox. /// Show a checkbox.
pub fn checkbox(&mut self, text: impl Into<String>, checked: &mut bool) -> GuiResponse { pub fn checkbox(&mut self, text: impl Into<String>, checked: &mut bool) -> Response {
self.add(Checkbox::new(checked, text)) self.add(Checkbox::new(checked, text))
} }
// Argument order matching that of Dear ImGui // Argument order matching that of Dear ImGui
/// Show a radio button. /// Show a radio button.
pub fn radio(&mut self, text: impl Into<String>, checked: bool) -> GuiResponse { pub fn radio(&mut self, text: impl Into<String>, checked: bool) -> Response {
self.add(RadioButton::new(checked, text)) self.add(RadioButton::new(checked, text))
} }
pub fn text_edit(&mut self, text: &mut String) -> GuiResponse { pub fn text_edit(&mut self, text: &mut String) -> Response {
self.add(TextEdit::new(text)) self.add(TextEdit::new(text))
} }
@ -477,7 +452,7 @@ impl Ui {
text: impl Into<String>, text: impl Into<String>,
current_value: &mut Value, current_value: &mut Value,
radio_value: Value, radio_value: Value,
) -> GuiResponse { ) -> Response {
let response = self.radio(text, *current_value == radio_value); let response = self.radio(text, *current_value == radio_value);
if response.clicked { if response.clicked {
*current_value = radio_value; *current_value = radio_value;
@ -486,13 +461,13 @@ impl Ui {
} }
/// Shortcut for `add(Separator::new())` /// Shortcut for `add(Separator::new())`
pub fn separator(&mut self) -> GuiResponse { pub fn separator(&mut self) -> Response {
self.add(Separator::new()) self.add(Separator::new())
} }
/// Modify an angle. The given angle should be in radians, but is shown to the user in degrees. /// Modify an angle. The given angle should be in radians, but is shown to the user in degrees.
/// The angle is NOT wrapped, so the user may select, for instance 720° = 2𝞃 = 4π /// The angle is NOT wrapped, so the user may select, for instance 720° = 2𝞃 = 4π
pub fn drag_angle(&mut self, radians: &mut f32) -> GuiResponse { pub fn drag_angle(&mut self, radians: &mut f32) -> Response {
#![allow(clippy::float_cmp)] #![allow(clippy::float_cmp)]
let mut degrees = radians.to_degrees(); let mut degrees = radians.to_degrees();

View file

@ -19,7 +19,7 @@ use paint::*;
/// Anything implementing Widget can be added to a Ui with `Ui::add` /// Anything implementing Widget can be added to a Ui with `Ui::add`
pub trait Widget { pub trait Widget {
fn ui(self, ui: &mut Ui) -> InteractInfo; fn ui(self, ui: &mut Ui) -> Response;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -123,7 +123,7 @@ macro_rules! label {
} }
impl Widget for Label { impl Widget for Label {
fn ui(self, ui: &mut Ui) -> InteractInfo { fn ui(self, ui: &mut Ui) -> Response {
let galley = self.layout(ui); let galley = self.layout(ui);
let rect = ui.allocate_space(galley.size); let rect = ui.allocate_space(galley.size);
self.paint_galley(ui, rect.min, galley); self.paint_galley(ui, rect.min, galley);
@ -174,7 +174,7 @@ impl Hyperlink {
} }
impl Widget for Hyperlink { impl Widget for Hyperlink {
fn ui(self, ui: &mut Ui) -> InteractInfo { fn ui(self, ui: &mut Ui) -> Response {
let Hyperlink { url, text } = self; let Hyperlink { url, text } = self;
let color = color::LIGHT_BLUE; let color = color::LIGHT_BLUE;
@ -183,18 +183,18 @@ impl Widget for Hyperlink {
let font = &ui.fonts()[text_style]; let font = &ui.fonts()[text_style];
let galley = font.layout_multiline(text, ui.available().width()); let galley = font.layout_multiline(text, ui.available().width());
let rect = ui.allocate_space(galley.size); let rect = ui.allocate_space(galley.size);
let interact = ui.interact(rect, id, Sense::click()); let response = ui.interact(rect, id, Sense::click());
if interact.hovered { if response.hovered {
ui.ctx().output().cursor_icon = CursorIcon::PointingHand; ui.ctx().output().cursor_icon = CursorIcon::PointingHand;
} }
if interact.clicked { if response.clicked {
ui.ctx().output().open_url = Some(url); ui.ctx().output().open_url = Some(url);
} }
if interact.hovered { if response.hovered {
// Underline: // Underline:
for line in &galley.lines { for line in &galley.lines {
let pos = interact.rect.min; let pos = response.rect.min;
let y = pos.y + line.y_max; let y = pos.y + line.y_max;
let y = ui.painter().round_to_pixel(y); let y = ui.painter().round_to_pixel(y);
let min_x = pos.x + line.min_x(); let min_x = pos.x + line.min_x();
@ -207,9 +207,9 @@ impl Widget for Hyperlink {
} }
ui.painter() ui.painter()
.galley(interact.rect.min, galley, text_style, color); .galley(response.rect.min, galley, text_style, color);
interact response
} }
} }
@ -269,7 +269,7 @@ impl Button {
} }
impl Widget for Button { impl Widget for Button {
fn ui(self, ui: &mut Ui) -> InteractInfo { fn ui(self, ui: &mut Ui) -> Response {
let Button { let Button {
text, text,
text_color, text_color,
@ -285,20 +285,20 @@ impl Widget for Button {
let mut size = galley.size + 2.0 * padding; let mut size = galley.size + 2.0 * padding;
size.y = size.y.max(ui.style().clickable_diameter); size.y = size.y.max(ui.style().clickable_diameter);
let rect = ui.allocate_space(size); let rect = ui.allocate_space(size);
let interact = ui.interact(rect, id, sense); let response = ui.interact(rect, id, sense);
let text_cursor = interact.rect.left_center() + vec2(padding.x, -0.5 * galley.size.y); let text_cursor = response.rect.left_center() + vec2(padding.x, -0.5 * galley.size.y);
let bg_fill = fill.or(ui.style().interact(&interact).bg_fill); let bg_fill = fill.or(ui.style().interact(&response).bg_fill);
ui.painter().add(PaintCmd::Rect { ui.painter().add(PaintCmd::Rect {
rect: interact.rect, rect: response.rect,
corner_radius: ui.style().interact(&interact).corner_radius, corner_radius: ui.style().interact(&response).corner_radius,
fill: bg_fill, fill: bg_fill,
outline: ui.style().interact(&interact).rect_outline, outline: ui.style().interact(&response).rect_outline,
}); });
let stroke_color = ui.style().interact(&interact).stroke_color; let stroke_color = ui.style().interact(&response).stroke_color;
let text_color = text_color.unwrap_or(stroke_color); let text_color = text_color.unwrap_or(stroke_color);
ui.painter() ui.painter()
.galley(text_cursor, galley, text_style, text_color); .galley(text_cursor, galley, text_style, text_color);
interact response
} }
} }
@ -329,7 +329,7 @@ impl<'a> Checkbox<'a> {
} }
impl<'a> Widget for Checkbox<'a> { impl<'a> Widget for Checkbox<'a> {
fn ui(self, ui: &mut Ui) -> InteractInfo { fn ui(self, ui: &mut Ui) -> Response {
let Checkbox { let Checkbox {
checked, checked,
text, text,
@ -345,21 +345,21 @@ impl<'a> Widget for Checkbox<'a> {
+ galley.size + galley.size
+ ui.style().button_padding; + ui.style().button_padding;
let rect = ui.allocate_space(size); let rect = ui.allocate_space(size);
let interact = ui.interact(rect, id, Sense::click()); let response = ui.interact(rect, id, Sense::click());
let text_cursor = let text_cursor =
interact.rect.min + ui.style().button_padding + vec2(ui.style().start_icon_width, 0.0); response.rect.min + ui.style().button_padding + vec2(ui.style().start_icon_width, 0.0);
if interact.clicked { if response.clicked {
*checked = !*checked; *checked = !*checked;
} }
let (small_icon_rect, big_icon_rect) = ui.style().icon_rectangles(interact.rect); let (small_icon_rect, big_icon_rect) = ui.style().icon_rectangles(response.rect);
ui.painter().add(PaintCmd::Rect { ui.painter().add(PaintCmd::Rect {
rect: big_icon_rect, rect: big_icon_rect,
corner_radius: ui.style().interact(&interact).corner_radius, corner_radius: ui.style().interact(&response).corner_radius,
fill: ui.style().interact(&interact).bg_fill, fill: ui.style().interact(&response).bg_fill,
outline: ui.style().interact(&interact).rect_outline, outline: ui.style().interact(&response).rect_outline,
}); });
let stroke_color = ui.style().interact(&interact).stroke_color; let stroke_color = ui.style().interact(&response).stroke_color;
if *checked { if *checked {
ui.painter().add(PaintCmd::Path { ui.painter().add(PaintCmd::Path {
@ -377,7 +377,7 @@ impl<'a> Widget for Checkbox<'a> {
let text_color = text_color.unwrap_or(stroke_color); let text_color = text_color.unwrap_or(stroke_color);
ui.painter() ui.painter()
.galley(text_cursor, galley, text_style, text_color); .galley(text_cursor, galley, text_style, text_color);
interact response
} }
} }
@ -407,7 +407,7 @@ impl RadioButton {
} }
impl Widget for RadioButton { impl Widget for RadioButton {
fn ui(self, ui: &mut Ui) -> InteractInfo { fn ui(self, ui: &mut Ui) -> Response {
let RadioButton { let RadioButton {
checked, checked,
text, text,
@ -422,14 +422,14 @@ impl Widget for RadioButton {
+ galley.size + galley.size
+ ui.style().button_padding; + ui.style().button_padding;
let rect = ui.allocate_space(size); let rect = ui.allocate_space(size);
let interact = ui.interact(rect, id, Sense::click()); let response = ui.interact(rect, id, Sense::click());
let text_cursor = let text_cursor =
interact.rect.min + ui.style().button_padding + vec2(ui.style().start_icon_width, 0.0); response.rect.min + ui.style().button_padding + vec2(ui.style().start_icon_width, 0.0);
let bg_fill = ui.style().interact(&interact).bg_fill; let bg_fill = ui.style().interact(&response).bg_fill;
let stroke_color = ui.style().interact(&interact).stroke_color; let stroke_color = ui.style().interact(&response).stroke_color;
let (small_icon_rect, big_icon_rect) = ui.style().icon_rectangles(interact.rect); let (small_icon_rect, big_icon_rect) = ui.style().icon_rectangles(response.rect);
let painter = ui.painter(); let painter = ui.painter();
@ -437,7 +437,7 @@ impl Widget for RadioButton {
center: big_icon_rect.center(), center: big_icon_rect.center(),
radius: big_icon_rect.width() / 2.0, radius: big_icon_rect.width() / 2.0,
fill: bg_fill, fill: bg_fill,
outline: ui.style().interact(&interact).rect_outline, // TODO outline: ui.style().interact(&response).rect_outline, // TODO
}); });
if checked { if checked {
@ -451,7 +451,7 @@ impl Widget for RadioButton {
let text_color = text_color.unwrap_or(stroke_color); let text_color = text_color.unwrap_or(stroke_color);
painter.galley(text_cursor, galley, text_style, text_color); painter.galley(text_cursor, galley, text_style, text_color);
interact response
} }
} }
@ -499,7 +499,7 @@ impl Separator {
} }
impl Widget for Separator { impl Widget for Separator {
fn ui(self, ui: &mut Ui) -> InteractInfo { fn ui(self, ui: &mut Ui) -> Response {
let Separator { let Separator {
line_width, line_width,
spacing, spacing,
@ -582,7 +582,7 @@ impl<'a> DragValue<'a> {
} }
impl<'a> Widget for DragValue<'a> { impl<'a> Widget for DragValue<'a> {
fn ui(self, ui: &mut Ui) -> InteractInfo { fn ui(self, ui: &mut Ui) -> Response {
let Self { let Self {
value, value,
speed, speed,
@ -617,7 +617,7 @@ impl<'a> Widget for DragValue<'a> {
} else { } else {
ui.memory().temp_edit_string = Some(value_text); ui.memory().temp_edit_string = Some(value_text);
} }
response.into() response
} else { } else {
let button = Button::new(format!("{}{}{}", prefix, value_text, suffix)) let button = Button::new(format!("{}{}{}", prefix, value_text, suffix))
.sense(Sense::click_and_drag()) .sense(Sense::click_and_drag())
@ -638,7 +638,7 @@ impl<'a> Widget for DragValue<'a> {
// otherwise we will just keep rounding to the same value while moving the mouse. // otherwise we will just keep rounding to the same value while moving the mouse.
} }
} }
response.into() response
} }
} }
} }

View file

@ -124,7 +124,7 @@ fn x_range(rect: &Rect) -> RangeInclusive<f32> {
impl<'a> Slider<'a> { impl<'a> Slider<'a> {
/// Just the slider, no text /// Just the slider, no text
fn allocate_slide_space(&self, ui: &mut Ui, height: f32) -> InteractInfo { fn allocate_slide_space(&self, ui: &mut Ui, height: f32) -> Response {
let id = self.id.unwrap_or_else(|| ui.make_position_id()); let id = self.id.unwrap_or_else(|| ui.make_position_id());
let desired_size = vec2(ui.available().width(), height); let desired_size = vec2(ui.available().width(), height);
let rect = ui.allocate_space(desired_size); let rect = ui.allocate_space(desired_size);
@ -132,15 +132,15 @@ impl<'a> Slider<'a> {
} }
/// Just the slider, no text /// Just the slider, no text
fn slider_ui(&mut self, ui: &mut Ui, interact: InteractInfo) { fn slider_ui(&mut self, ui: &mut Ui, response: &Response) {
let rect = &interact.rect; let rect = &response.rect;
let x_range = x_range(rect); let x_range = x_range(rect);
let range = self.range.clone(); let range = self.range.clone();
debug_assert!(range.start() <= range.end()); debug_assert!(range.start() <= range.end());
if let Some(mouse_pos) = ui.input().mouse.pos { if let Some(mouse_pos) = ui.input().mouse.pos {
if interact.active { if response.active {
let aim_radius = ui.input().aim_radius(); let aim_radius = ui.input().aim_radius();
let new_value = crate::math::smart_aim::best_in_range_f32( let new_value = crate::math::smart_aim::best_in_range_f32(
self.value_from_x_clamped(mouse_pos.x - aim_radius, x_range.clone()), self.value_from_x_clamped(mouse_pos.x - aim_radius, x_range.clone()),
@ -171,10 +171,10 @@ impl<'a> Slider<'a> {
ui.painter().add(PaintCmd::Circle { ui.painter().add(PaintCmd::Circle {
center: pos2(marker_center_x, rail_rect.center().y), center: pos2(marker_center_x, rail_rect.center().y),
radius: handle_radius(rect), radius: handle_radius(rect),
fill: Some(ui.style().interact(&interact).fill), fill: Some(ui.style().interact(response).fill),
outline: Some(LineStyle::new( outline: Some(LineStyle::new(
ui.style().interact(&interact).stroke_width, ui.style().interact(response).stroke_width,
ui.style().interact(&interact).stroke_color, ui.style().interact(response).stroke_color,
)), )),
}); });
} }
@ -255,7 +255,7 @@ impl<'a> Slider<'a> {
} }
impl<'a> Widget for Slider<'a> { impl<'a> Widget for Slider<'a> {
fn ui(mut self, ui: &mut Ui) -> InteractInfo { fn ui(mut self, ui: &mut Ui) -> Response {
let text_style = TextStyle::Button; let text_style = TextStyle::Button;
let font = &ui.fonts()[text_style]; let font = &ui.fonts()[text_style];
let height = font.line_spacing().max(ui.style().clickable_diameter); let height = font.line_spacing().max(ui.style().clickable_diameter);
@ -265,13 +265,13 @@ impl<'a> Widget for Slider<'a> {
ui.columns(2, |columns| { ui.columns(2, |columns| {
let slider_ui = &mut columns[0]; let slider_ui = &mut columns[0];
let slider_interact = self.allocate_slide_space(slider_ui, height); let slider_response = self.allocate_slide_space(slider_ui, height);
self.slider_ui(slider_ui, slider_interact); self.slider_ui(slider_ui, &slider_response);
let x_range = x_range(&slider_interact.rect); let x_range = x_range(&slider_response.rect);
// Place the text in line with the slider on the left: // Place the text in line with the slider on the left:
let text_ui = &mut columns[1]; let text_ui = &mut columns[1];
text_ui.set_desired_height(slider_interact.rect.height()); text_ui.set_desired_height(slider_response.rect.height());
text_ui.inner_layout( text_ui.inner_layout(
Layout::horizontal(Align::Center), Layout::horizontal(Align::Center),
text_ui.available().size(), text_ui.available().size(),
@ -280,12 +280,12 @@ impl<'a> Widget for Slider<'a> {
}, },
); );
slider_interact slider_response
}) })
} else { } else {
let interact = self.allocate_slide_space(ui, height); let response = self.allocate_slide_space(ui, height);
self.slider_ui(ui, interact); self.slider_ui(ui, &response);
interact response
} }
} }
} }

View file

@ -74,7 +74,7 @@ impl<'t> TextEdit<'t> {
} }
impl<'t> Widget for TextEdit<'t> { impl<'t> Widget for TextEdit<'t> {
fn ui(self, ui: &mut Ui) -> InteractInfo { fn ui(self, ui: &mut Ui) -> Response {
let TextEdit { let TextEdit {
text, text,
id, id,
@ -108,14 +108,14 @@ impl<'t> Widget for TextEdit<'t> {
} else { } else {
Sense::nothing() Sense::nothing()
}; };
let interact = ui.interact(rect, id, sense); // TODO: implement drag-select let response = ui.interact(rect, id, sense); // TODO: implement drag-select
if interact.clicked && enabled { if response.clicked && enabled {
ui.memory().request_kb_focus(id); ui.memory().request_kb_focus(id);
if let Some(mouse_pos) = ui.input().mouse.pos { if let Some(mouse_pos) = ui.input().mouse.pos {
state.cursor = Some(galley.char_at(mouse_pos - interact.rect.min).char_idx); state.cursor = Some(galley.char_at(mouse_pos - response.rect.min).char_idx);
} }
} else if ui.input().mouse.click || (ui.input().mouse.pressed && !interact.hovered) { } else if ui.input().mouse.click || (ui.input().mouse.pressed && !response.hovered) {
// User clicked somewhere else // User clicked somewhere else
ui.memory().surrender_kb_focus(id); ui.memory().surrender_kb_focus(id);
} }
@ -123,7 +123,7 @@ impl<'t> Widget for TextEdit<'t> {
ui.memory().surrender_kb_focus(id); ui.memory().surrender_kb_focus(id);
} }
if interact.hovered && enabled { if response.hovered && enabled {
ui.output().cursor_icon = CursorIcon::Text; ui.output().cursor_icon = CursorIcon::Text;
} }
@ -179,12 +179,12 @@ impl<'t> Widget for TextEdit<'t> {
let painter = ui.painter(); let painter = ui.painter();
{ {
let bg_rect = interact.rect.expand(2.0); // breathing room for content let bg_rect = response.rect.expand(2.0); // breathing room for content
painter.add(PaintCmd::Rect { painter.add(PaintCmd::Rect {
rect: bg_rect, rect: bg_rect,
corner_radius: ui.style().interact.style(&interact).corner_radius, corner_radius: ui.style().interact(&response).corner_radius,
fill: Some(ui.style().dark_bg_color), fill: Some(ui.style().dark_bg_color),
outline: ui.style().interact.style(&interact).rect_outline, outline: ui.style().interact(&response).rect_outline,
}); });
} }
@ -199,7 +199,7 @@ impl<'t> Widget for TextEdit<'t> {
if show_cursor { if show_cursor {
if let Some(cursor) = state.cursor { if let Some(cursor) = state.cursor {
let cursor_pos = interact.rect.min + galley.char_start_pos(cursor); let cursor_pos = response.rect.min + galley.char_start_pos(cursor);
painter.line_segment( painter.line_segment(
[cursor_pos, cursor_pos + vec2(0.0, line_spacing)], [cursor_pos, cursor_pos + vec2(0.0, line_spacing)],
(ui.style().text_cursor_width, color::WHITE), (ui.style().text_cursor_width, color::WHITE),
@ -208,11 +208,10 @@ impl<'t> Widget for TextEdit<'t> {
} }
} }
let text_color = let text_color = text_color.unwrap_or_else(|| ui.style().interact(&response).stroke_color);
text_color.unwrap_or_else(|| ui.style().interact.style(&interact).stroke_color); painter.galley(response.rect.min, galley, text_style, text_color);
painter.galley(interact.rect.min, galley, text_style, text_color);
ui.memory().text_edit.insert(id, state); ui.memory().text_edit.insert(id, state);
interact response
} }
} }