Allow custom position in popover
This commit is contained in:
parent
70d54d6f20
commit
001fd744c5
1 changed files with 32 additions and 10 deletions
|
|
@ -9,7 +9,9 @@ use iced_core::mouse;
|
||||||
use iced_core::overlay;
|
use iced_core::overlay;
|
||||||
use iced_core::renderer;
|
use iced_core::renderer;
|
||||||
use iced_core::widget::{Operation, OperationOutputWrapper, Tree};
|
use iced_core::widget::{Operation, OperationOutputWrapper, Tree};
|
||||||
use iced_core::{Clipboard, Element, Layout, Length, Point, Rectangle, Shell, Size, Widget};
|
use iced_core::{
|
||||||
|
Clipboard, Element, Layout, Length, Point, Rectangle, Shell, Size, Vector, Widget,
|
||||||
|
};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
|
||||||
pub use iced_style::container::{Appearance, StyleSheet};
|
pub use iced_style::container::{Appearance, StyleSheet};
|
||||||
|
|
@ -25,19 +27,26 @@ pub struct Popover<'a, Message, Renderer> {
|
||||||
content: Element<'a, Message, Renderer>,
|
content: Element<'a, Message, Renderer>,
|
||||||
// XXX Avoid refcell; improve iced overlay API?
|
// XXX Avoid refcell; improve iced overlay API?
|
||||||
popup: RefCell<Element<'a, Message, Renderer>>,
|
popup: RefCell<Element<'a, Message, Renderer>>,
|
||||||
|
position: Option<Point>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Message, Renderer> Popover<'a, Message, Renderer> {
|
impl<'a, Message, Renderer> Popover<'a, Message, Renderer> {
|
||||||
fn new(
|
pub fn new(
|
||||||
content: impl Into<Element<'a, Message, Renderer>>,
|
content: impl Into<Element<'a, Message, Renderer>>,
|
||||||
popup: impl Into<Element<'a, Message, Renderer>>,
|
popup: impl Into<Element<'a, Message, Renderer>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
content: content.into(),
|
content: content.into(),
|
||||||
popup: RefCell::new(popup.into()),
|
popup: RefCell::new(popup.into()),
|
||||||
|
position: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn position(mut self, position: Point) -> Self {
|
||||||
|
self.position = Some(position);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
// TODO More options for positioning similar to GdkPopup, xdg_popup
|
// TODO More options for positioning similar to GdkPopup, xdg_popup
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -145,9 +154,20 @@ where
|
||||||
layout: Layout<'_>,
|
layout: Layout<'_>,
|
||||||
_renderer: &Renderer,
|
_renderer: &Renderer,
|
||||||
) -> Option<overlay::Element<'b, Message, Renderer>> {
|
) -> Option<overlay::Element<'b, Message, Renderer>> {
|
||||||
// Set position to center of bottom edge
|
|
||||||
let bounds = layout.bounds();
|
let bounds = layout.bounds();
|
||||||
let position = Point::new(bounds.x + bounds.width / 2.0, bounds.y + bounds.height);
|
let (position, centered) = match self.position {
|
||||||
|
Some(relative) => (
|
||||||
|
bounds.position() + Vector::new(relative.x, relative.y),
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
None => {
|
||||||
|
// Set position to center of bottom edge
|
||||||
|
(
|
||||||
|
Point::new(bounds.x + bounds.width / 2.0, bounds.y + bounds.height),
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// XXX needed to use RefCell to get &mut for popup element
|
// XXX needed to use RefCell to get &mut for popup element
|
||||||
Some(overlay::Element::new(
|
Some(overlay::Element::new(
|
||||||
|
|
@ -155,6 +175,7 @@ where
|
||||||
Box::new(Overlay {
|
Box::new(Overlay {
|
||||||
tree: &mut tree.children[1],
|
tree: &mut tree.children[1],
|
||||||
content: &self.popup,
|
content: &self.popup,
|
||||||
|
centered,
|
||||||
}),
|
}),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
@ -171,9 +192,10 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Overlay<'a, 'b, Message, Renderer> {
|
pub struct Overlay<'a, 'b, Message, Renderer> {
|
||||||
tree: &'a mut Tree,
|
tree: &'a mut Tree,
|
||||||
content: &'a RefCell<Element<'b, Message, Renderer>>,
|
content: &'a RefCell<Element<'b, Message, Renderer>>,
|
||||||
|
centered: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b, Message, Renderer> overlay::Overlay<Message, Renderer>
|
impl<'a, 'b, Message, Renderer> overlay::Overlay<Message, Renderer>
|
||||||
|
|
@ -182,13 +204,13 @@ where
|
||||||
Renderer: iced_core::Renderer,
|
Renderer: iced_core::Renderer,
|
||||||
{
|
{
|
||||||
fn layout(&self, renderer: &Renderer, bounds: Size, mut position: Point) -> layout::Node {
|
fn layout(&self, renderer: &Renderer, bounds: Size, mut position: Point) -> layout::Node {
|
||||||
// Position is set to the center bottom of the lower widget
|
|
||||||
|
|
||||||
let limits = layout::Limits::new(Size::UNIT, bounds);
|
let limits = layout::Limits::new(Size::UNIT, bounds);
|
||||||
let mut node = self.content.borrow().as_widget().layout(renderer, &limits);
|
let mut node = self.content.borrow().as_widget().layout(renderer, &limits);
|
||||||
|
if self.centered {
|
||||||
let width = node.size().width;
|
// Position is set to the center bottom of the lower widget
|
||||||
position.x = (position.x - width / 2.0).clamp(0.0, bounds.width - width);
|
let width = node.size().width;
|
||||||
|
position.x = (position.x - width / 2.0).clamp(0.0, bounds.width - width);
|
||||||
|
}
|
||||||
node.move_to(position);
|
node.move_to(position);
|
||||||
|
|
||||||
node
|
node
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue