Implement Widget::mouse_interaction for PaneGrid
... and fix rendering of drag interaction in `PaneGrid` by introducing an explicit `with_translation` method to `Renderer` and simplifying the `with_layer` and `Clip` primitive.
This commit is contained in:
parent
41394b4e90
commit
4a11cbd994
11 changed files with 167 additions and 66 deletions
|
|
@ -175,11 +175,7 @@ impl<'a> Layer<'a> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Primitive::Clip {
|
Primitive::Clip { bounds, content } => {
|
||||||
bounds,
|
|
||||||
offset,
|
|
||||||
content,
|
|
||||||
} => {
|
|
||||||
let layer = &mut layers[current_layer];
|
let layer = &mut layers[current_layer];
|
||||||
let translated_bounds = *bounds + translation;
|
let translated_bounds = *bounds + translation;
|
||||||
|
|
||||||
|
|
@ -192,8 +188,7 @@ impl<'a> Layer<'a> {
|
||||||
|
|
||||||
Self::process_primitive(
|
Self::process_primitive(
|
||||||
layers,
|
layers,
|
||||||
translation
|
translation,
|
||||||
- Vector::new(offset.x as f32, offset.y as f32),
|
|
||||||
content,
|
content,
|
||||||
layers.len() - 1,
|
layers.len() - 1,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -66,8 +66,6 @@ pub enum Primitive {
|
||||||
Clip {
|
Clip {
|
||||||
/// The bounds of the clip
|
/// The bounds of the clip
|
||||||
bounds: Rectangle,
|
bounds: Rectangle,
|
||||||
/// The offset transformation of the clip
|
|
||||||
offset: Vector<u32>,
|
|
||||||
/// The content of the clip
|
/// The content of the clip
|
||||||
content: Box<Primitive>,
|
content: Box<Primitive>,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -51,12 +51,7 @@ where
|
||||||
layout
|
layout
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_layer(
|
fn with_layer(&mut self, bounds: Rectangle, f: impl FnOnce(&mut Self)) {
|
||||||
&mut self,
|
|
||||||
bounds: Rectangle,
|
|
||||||
offset: Vector<u32>,
|
|
||||||
f: impl FnOnce(&mut Self),
|
|
||||||
) {
|
|
||||||
let current_primitives =
|
let current_primitives =
|
||||||
std::mem::replace(&mut self.primitives, Vec::new());
|
std::mem::replace(&mut self.primitives, Vec::new());
|
||||||
|
|
||||||
|
|
@ -67,7 +62,27 @@ where
|
||||||
|
|
||||||
self.primitives.push(Primitive::Clip {
|
self.primitives.push(Primitive::Clip {
|
||||||
bounds,
|
bounds,
|
||||||
offset,
|
content: Box::new(Primitive::Group {
|
||||||
|
primitives: layer_primitives,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_translation(
|
||||||
|
&mut self,
|
||||||
|
translation: Vector,
|
||||||
|
f: impl FnOnce(&mut Self),
|
||||||
|
) {
|
||||||
|
let current_primitives =
|
||||||
|
std::mem::replace(&mut self.primitives, Vec::new());
|
||||||
|
|
||||||
|
f(self);
|
||||||
|
|
||||||
|
let layer_primitives =
|
||||||
|
std::mem::replace(&mut self.primitives, current_primitives);
|
||||||
|
|
||||||
|
self.primitives.push(Primitive::Translate {
|
||||||
|
translation,
|
||||||
content: Box::new(Primitive::Group {
|
content: Box::new(Primitive::Group {
|
||||||
primitives: layer_primitives,
|
primitives: layer_primitives,
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
|
|
@ -46,10 +46,11 @@ pub trait Renderer: Sized {
|
||||||
element.layout(self, limits)
|
element.layout(self, limits)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_layer(
|
fn with_layer(&mut self, bounds: Rectangle, f: impl FnOnce(&mut Self));
|
||||||
|
|
||||||
|
fn with_translation(
|
||||||
&mut self,
|
&mut self,
|
||||||
bounds: Rectangle,
|
translation: Vector,
|
||||||
offset: Vector<u32>,
|
|
||||||
f: impl FnOnce(&mut Self),
|
f: impl FnOnce(&mut Self),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
use crate::pane_grid;
|
|
||||||
use crate::progress_bar;
|
use crate::progress_bar;
|
||||||
use crate::renderer::{self, Renderer};
|
use crate::renderer::{self, Renderer};
|
||||||
use crate::text;
|
use crate::text;
|
||||||
|
|
@ -19,10 +18,11 @@ impl Null {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Renderer for Null {
|
impl Renderer for Null {
|
||||||
fn with_layer(
|
fn with_layer(&mut self, _bounds: Rectangle, _f: impl FnOnce(&mut Self)) {}
|
||||||
|
|
||||||
|
fn with_translation(
|
||||||
&mut self,
|
&mut self,
|
||||||
_bounds: Rectangle,
|
_translation: Vector,
|
||||||
_offset: Vector<u32>,
|
|
||||||
_f: impl FnOnce(&mut Self),
|
_f: impl FnOnce(&mut Self),
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use crate::layout;
|
||||||
use crate::mouse;
|
use crate::mouse;
|
||||||
use crate::overlay;
|
use crate::overlay;
|
||||||
use crate::renderer;
|
use crate::renderer;
|
||||||
use crate::{Clipboard, Element, Layout, Point, Rectangle, Size, Vector};
|
use crate::{Clipboard, Element, Layout, Point, Rectangle, Size};
|
||||||
|
|
||||||
use std::hash::Hasher;
|
use std::hash::Hasher;
|
||||||
|
|
||||||
|
|
@ -359,18 +359,14 @@ where
|
||||||
|
|
||||||
let overlay_bounds = layer.layout.bounds();
|
let overlay_bounds = layer.layout.bounds();
|
||||||
|
|
||||||
renderer.with_layer(
|
renderer.with_layer(overlay_bounds, |renderer| {
|
||||||
overlay_bounds,
|
overlay.draw(
|
||||||
Vector::new(0, 0),
|
renderer,
|
||||||
|renderer| {
|
&renderer::Style::default(),
|
||||||
overlay.draw(
|
Layout::new(&layer.layout),
|
||||||
renderer,
|
cursor_position,
|
||||||
&renderer::Style::default(),
|
);
|
||||||
Layout::new(&layer.layout),
|
});
|
||||||
cursor_position,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
self.overlay = Some(layer);
|
self.overlay = Some(layer);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -471,6 +471,33 @@ where
|
||||||
.fold(event_status, event::Status::merge)
|
.fold(event_status, event::Status::merge)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mouse_interaction(
|
||||||
|
&self,
|
||||||
|
layout: Layout<'_>,
|
||||||
|
viewport: &Rectangle,
|
||||||
|
cursor_position: Point,
|
||||||
|
) -> mouse::Interaction {
|
||||||
|
if self.state.picked_pane().is_some() {
|
||||||
|
return mouse::Interaction::Grab;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some((_, axis)) = self.state.picked_split() {
|
||||||
|
return match axis {
|
||||||
|
Axis::Horizontal => mouse::Interaction::ResizingHorizontally,
|
||||||
|
Axis::Vertical => mouse::Interaction::ResizingVertically,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
self.elements
|
||||||
|
.iter()
|
||||||
|
.zip(layout.children())
|
||||||
|
.map(|((_pane, content), layout)| {
|
||||||
|
content.mouse_interaction(layout, viewport, cursor_position)
|
||||||
|
})
|
||||||
|
.max()
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
fn draw(
|
fn draw(
|
||||||
&self,
|
&self,
|
||||||
renderer: &mut Renderer,
|
renderer: &mut Renderer,
|
||||||
|
|
@ -543,22 +570,22 @@ where
|
||||||
Some((dragging, origin)) if *id == dragging => {
|
Some((dragging, origin)) if *id == dragging => {
|
||||||
let bounds = layout.bounds();
|
let bounds = layout.bounds();
|
||||||
|
|
||||||
renderer.with_layer(
|
renderer.with_translation(
|
||||||
Rectangle {
|
cursor_position
|
||||||
x: cursor_position.x - origin.x,
|
- Point::new(
|
||||||
y: cursor_position.y - origin.y,
|
bounds.x + origin.x,
|
||||||
width: bounds.width + 0.5,
|
bounds.y + origin.y,
|
||||||
height: bounds.height + 0.5,
|
),
|
||||||
},
|
|
||||||
Vector::new(0, 0),
|
|
||||||
|renderer| {
|
|renderer| {
|
||||||
pane.draw(
|
renderer.with_layer(bounds, |renderer| {
|
||||||
renderer,
|
pane.draw(
|
||||||
style,
|
renderer,
|
||||||
layout,
|
style,
|
||||||
pane_cursor_position,
|
layout,
|
||||||
viewport,
|
pane_cursor_position,
|
||||||
);
|
viewport,
|
||||||
|
);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::container;
|
use crate::container;
|
||||||
use crate::event::{self, Event};
|
use crate::event::{self, Event};
|
||||||
use crate::layout;
|
use crate::layout;
|
||||||
|
use crate::mouse;
|
||||||
use crate::overlay;
|
use crate::overlay;
|
||||||
use crate::pane_grid::TitleBar;
|
use crate::pane_grid::TitleBar;
|
||||||
use crate::renderer;
|
use crate::renderer;
|
||||||
|
|
@ -194,6 +195,41 @@ where
|
||||||
event_status.merge(body_status)
|
event_status.merge(body_status)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn mouse_interaction(
|
||||||
|
&self,
|
||||||
|
layout: Layout<'_>,
|
||||||
|
viewport: &Rectangle,
|
||||||
|
cursor_position: Point,
|
||||||
|
) -> mouse::Interaction {
|
||||||
|
let mut children = layout.children();
|
||||||
|
|
||||||
|
let (body_layout, title_bar_interaction) =
|
||||||
|
if let Some(title_bar) = &self.title_bar {
|
||||||
|
let title_bar_layout = children.next().unwrap();
|
||||||
|
|
||||||
|
let is_over_pick_area = title_bar
|
||||||
|
.is_over_pick_area(title_bar_layout, cursor_position);
|
||||||
|
|
||||||
|
if is_over_pick_area {
|
||||||
|
return mouse::Interaction::Grab;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mouse_interaction = title_bar.mouse_interaction(
|
||||||
|
title_bar_layout,
|
||||||
|
viewport,
|
||||||
|
cursor_position,
|
||||||
|
);
|
||||||
|
|
||||||
|
(children.next().unwrap(), mouse_interaction)
|
||||||
|
} else {
|
||||||
|
(children.next().unwrap(), mouse::Interaction::default())
|
||||||
|
};
|
||||||
|
|
||||||
|
self.body
|
||||||
|
.mouse_interaction(body_layout, viewport, cursor_position)
|
||||||
|
.max(title_bar_interaction)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn hash_layout(&self, state: &mut Hasher) {
|
pub(crate) fn hash_layout(&self, state: &mut Hasher) {
|
||||||
if let Some(title_bar) = &self.title_bar {
|
if let Some(title_bar) = &self.title_bar {
|
||||||
title_bar.hash_layout(state);
|
title_bar.hash_layout(state);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::container;
|
use crate::container;
|
||||||
use crate::event::{self, Event};
|
use crate::event::{self, Event};
|
||||||
use crate::layout;
|
use crate::layout;
|
||||||
|
use crate::mouse;
|
||||||
use crate::overlay;
|
use crate::overlay;
|
||||||
use crate::renderer;
|
use crate::renderer;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -249,6 +250,35 @@ where
|
||||||
control_status.merge(title_status)
|
control_status.merge(title_status)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn mouse_interaction(
|
||||||
|
&self,
|
||||||
|
layout: Layout<'_>,
|
||||||
|
viewport: &Rectangle,
|
||||||
|
cursor_position: Point,
|
||||||
|
) -> mouse::Interaction {
|
||||||
|
let mut children = layout.children();
|
||||||
|
let padded = children.next().unwrap();
|
||||||
|
|
||||||
|
let mut children = padded.children();
|
||||||
|
let title_layout = children.next().unwrap();
|
||||||
|
|
||||||
|
let title_interaction = self.content.mouse_interaction(
|
||||||
|
title_layout,
|
||||||
|
viewport,
|
||||||
|
cursor_position,
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some(controls) = &self.controls {
|
||||||
|
let controls_layout = children.next().unwrap();
|
||||||
|
|
||||||
|
controls
|
||||||
|
.mouse_interaction(controls_layout, viewport, cursor_position)
|
||||||
|
.max(title_interaction)
|
||||||
|
} else {
|
||||||
|
title_interaction
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn overlay(
|
pub(crate) fn overlay(
|
||||||
&mut self,
|
&mut self,
|
||||||
layout: Layout<'_>,
|
layout: Layout<'_>,
|
||||||
|
|
|
||||||
|
|
@ -485,15 +485,20 @@ where
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(scrollbar) = scrollbar {
|
if let Some(scrollbar) = scrollbar {
|
||||||
renderer.with_layer(bounds, Vector::new(0, offset), |renderer| {
|
renderer.with_layer(bounds, |renderer| {
|
||||||
self.content.draw(
|
renderer.with_translation(
|
||||||
renderer,
|
Vector::new(0.0, -(offset as f32)),
|
||||||
style,
|
|renderer| {
|
||||||
content_layout,
|
self.content.draw(
|
||||||
cursor_position,
|
renderer,
|
||||||
&Rectangle {
|
style,
|
||||||
y: bounds.y + offset as f32,
|
content_layout,
|
||||||
..bounds
|
cursor_position,
|
||||||
|
&Rectangle {
|
||||||
|
y: bounds.y + offset as f32,
|
||||||
|
..bounds
|
||||||
|
},
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
@ -509,7 +514,7 @@ where
|
||||||
let is_scrollbar_visible =
|
let is_scrollbar_visible =
|
||||||
style.background.is_some() || style.border_width > 0.0;
|
style.background.is_some() || style.border_width > 0.0;
|
||||||
|
|
||||||
renderer.with_layer(bounds, Vector::new(0, 0), |renderer| {
|
renderer.with_layer(bounds, |renderer| {
|
||||||
if is_scrollbar_visible {
|
if is_scrollbar_visible {
|
||||||
renderer.fill_rectangle(renderer::Quad {
|
renderer.fill_rectangle(renderer::Quad {
|
||||||
bounds: scrollbar.bounds,
|
bounds: scrollbar.bounds,
|
||||||
|
|
|
||||||
|
|
@ -751,11 +751,9 @@ where
|
||||||
};
|
};
|
||||||
|
|
||||||
if text_width > text_bounds.width {
|
if text_width > text_bounds.width {
|
||||||
renderer.with_layer(
|
renderer.with_layer(text_bounds, |renderer| {
|
||||||
text_bounds,
|
renderer.with_translation(Vector::new(-offset, 0.0), render)
|
||||||
Vector::new(offset as u32, 0),
|
});
|
||||||
render,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
render(renderer);
|
render(renderer);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue