diff options
author | 2020-06-05 14:02:29 +0200 | |
---|---|---|
committer | 2020-06-05 14:02:29 +0200 | |
commit | 4dc5bffdfbfb09a017f35c12b484301fcf044876 (patch) | |
tree | 2175e006a72050aaef4789bc1bf8d5513274057f /native | |
parent | e8e656b3300093e384771a6083e25e9395bbeb50 (diff) | |
download | iced-4dc5bffdfbfb09a017f35c12b484301fcf044876.tar.gz iced-4dc5bffdfbfb09a017f35c12b484301fcf044876.tar.bz2 iced-4dc5bffdfbfb09a017f35c12b484301fcf044876.zip |
Draft draggable and graphics logic for `TitleBar`
Diffstat (limited to 'native')
-rw-r--r-- | native/src/renderer/null.rs | 21 | ||||
-rw-r--r-- | native/src/widget/pane_grid.rs | 32 | ||||
-rw-r--r-- | native/src/widget/pane_grid/content.rs | 60 | ||||
-rw-r--r-- | native/src/widget/pane_grid/state.rs | 16 | ||||
-rw-r--r-- | native/src/widget/pane_grid/title_bar.rs | 103 |
5 files changed, 184 insertions, 48 deletions
diff --git a/native/src/renderer/null.rs b/native/src/renderer/null.rs index b8695b9c..29df3e14 100644 --- a/native/src/renderer/null.rs +++ b/native/src/renderer/null.rs @@ -1,7 +1,7 @@ use crate::{ - button, checkbox, column, progress_bar, radio, row, scrollable, slider, - text, text_input, Color, Element, Font, HorizontalAlignment, Layout, Point, - Rectangle, Renderer, Size, VerticalAlignment, + button, checkbox, column, container, progress_bar, radio, row, scrollable, + slider, text, text_input, Color, Element, Font, HorizontalAlignment, + Layout, Point, Rectangle, Renderer, Size, VerticalAlignment, }; /// A renderer that does nothing. @@ -226,3 +226,18 @@ impl progress_bar::Renderer for Null { ) { } } + +impl container::Renderer for Null { + type Style = (); + + fn draw<Message>( + &mut self, + _defaults: &Self::Defaults, + _bounds: Rectangle, + _cursor_position: Point, + _style: &Self::Style, + _content: &Element<'_, Message, Self>, + _content_layout: Layout<'_>, + ) { + } +} diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs index bf9c76fd..c0c3839e 100644 --- a/native/src/widget/pane_grid.rs +++ b/native/src/widget/pane_grid.rs @@ -30,7 +30,7 @@ pub use title_bar::TitleBar; use crate::{ container, keyboard, layout, mouse, row, Clipboard, Element, Event, Hasher, - Layout, Length, Point, Size, Widget, + Layout, Length, Point, Rectangle, Size, Widget, }; /// A collection of panes distributed using either vertical or horizontal splits @@ -427,17 +427,18 @@ where clicked_region.next() { match &self.on_drag { - Some(on_drag) - if content.is_over_drag_target( - layout, - cursor_position, - ) => - { - self.state.pick_pane(pane); - - messages.push(on_drag(DragEvent::Picked { - pane: *pane, - })); + Some(on_drag) => { + if let Some(origin) = + content.drag_origin(layout, cursor_position) + { + self.state.pick_pane(pane, origin); + + messages.push(on_drag(DragEvent::Picked { + pane: *pane, + })); + } else { + self.state.focus(pane); + } } _ => { self.state.focus(pane); @@ -448,7 +449,7 @@ where } } mouse::Event::ButtonReleased(mouse::Button::Left) => { - if let Some(pane) = self.state.picked_pane() { + if let Some((pane, _)) = self.state.picked_pane() { self.state.focus(&pane); if let Some(on_drag) = &self.on_drag { @@ -657,7 +658,7 @@ pub trait Renderer: crate::Renderer + container::Renderer + Sized { &mut self, defaults: &Self::Defaults, content: &[(Pane, Content<'_, Message, Self>)], - dragging: Option<Pane>, + dragging: Option<(Pane, Point)>, resizing: Option<Axis>, layout: Layout<'_>, cursor_position: Point, @@ -676,6 +677,8 @@ pub trait Renderer: crate::Renderer + container::Renderer + Sized { fn draw_pane<Message>( &mut self, defaults: &Self::Defaults, + bounds: Rectangle, + style: &Self::Style, title_bar: Option<(&TitleBar<'_, Message, Self>, Layout<'_>)>, body: (&Element<'_, Message, Self>, Layout<'_>), cursor_position: Point, @@ -684,6 +687,7 @@ pub trait Renderer: crate::Renderer + container::Renderer + Sized { fn draw_title_bar<Message>( &mut self, defaults: &Self::Defaults, + bounds: Rectangle, style: &Self::Style, title: (&Element<'_, Message, Self>, Layout<'_>), controls: Option<(&Element<'_, Message, Self>, Layout<'_>)>, diff --git a/native/src/widget/pane_grid/content.rs b/native/src/widget/pane_grid/content.rs index a30b0e7d..843dcec4 100644 --- a/native/src/widget/pane_grid/content.rs +++ b/native/src/widget/pane_grid/content.rs @@ -1,7 +1,7 @@ use crate::container; use crate::layout; use crate::pane_grid::{self, TitleBar}; -use crate::{Clipboard, Element, Event, Hasher, Layout, Point, Size}; +use crate::{Clipboard, Element, Event, Hasher, Layout, Point, Size, Vector}; /// The content of a [`Pane`]. /// @@ -9,6 +9,7 @@ use crate::{Clipboard, Element, Event, Hasher, Layout, Point, Size}; pub struct Content<'a, Message, Renderer: container::Renderer> { title_bar: Option<TitleBar<'a, Message, Renderer>>, body: Element<'a, Message, Renderer>, + style: Renderer::Style, } impl<'a, Message, Renderer> Content<'a, Message, Renderer> @@ -19,6 +20,7 @@ where Self { title_bar: None, body: body.into(), + style: Renderer::Style::default(), } } @@ -29,6 +31,14 @@ where self.title_bar = Some(title_bar); self } + + /// Sets the style of the [`TitleBar`]. + /// + /// [`TitleBar`]: struct.TitleBar.html + pub fn style(mut self, style: impl Into<Renderer::Style>) -> Self { + self.style = style.into(); + self + } } impl<'a, Message, Renderer> Content<'a, Message, Renderer> @@ -49,6 +59,8 @@ where renderer.draw_pane( defaults, + layout.bounds(), + &self.style, Some((title_bar, title_bar_layout)), (&self.body, body_layout), cursor_position, @@ -56,6 +68,8 @@ where } else { renderer.draw_pane( defaults, + layout.bounds(), + &self.style, None, (&self.body, layout), cursor_position, @@ -63,12 +77,25 @@ where } } - pub(crate) fn is_over_drag_target( + pub fn drag_origin( &self, - _layout: Layout<'_>, - _cursor_position: Point, - ) -> bool { - false + layout: Layout<'_>, + cursor_position: Point, + ) -> Option<Point> { + if let Some(title_bar) = &self.title_bar { + let mut children = layout.children(); + let title_bar_layout = children.next().unwrap(); + + if title_bar.is_over_draggable(title_bar_layout, cursor_position) { + let position = layout.position(); + + Some(cursor_position - Vector::new(position.x, position.y)) + } else { + None + } + } else { + None + } } pub(crate) fn layout( @@ -115,14 +142,31 @@ where renderer: &Renderer, clipboard: Option<&dyn Clipboard>, ) { + let body_layout = if let Some(title_bar) = &mut self.title_bar { + let mut children = layout.children(); + + title_bar.on_event( + event.clone(), + children.next().unwrap(), + cursor_position, + messages, + renderer, + clipboard, + ); + + children.next().unwrap() + } else { + layout + }; + self.body.on_event( event, - layout, + body_layout, cursor_position, messages, renderer, clipboard, - ) + ); } pub(crate) fn hash_layout(&self, state: &mut Hasher) { diff --git a/native/src/widget/pane_grid/state.rs b/native/src/widget/pane_grid/state.rs index 943120e3..a8431dec 100644 --- a/native/src/widget/pane_grid/state.rs +++ b/native/src/widget/pane_grid/state.rs @@ -313,13 +313,14 @@ pub struct Internal { action: Action, } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq)] pub enum Action { Idle { focus: Option<Pane>, }, Dragging { pane: Pane, + origin: Point, }, Resizing { split: Split, @@ -334,7 +335,7 @@ impl Action { Action::Idle { focus } | Action::Resizing { focus, .. } => { focus.map(|pane| (pane, Focus::Idle)) } - Action::Dragging { pane } => Some((*pane, Focus::Dragging)), + Action::Dragging { pane, .. } => Some((*pane, Focus::Dragging)), } } } @@ -351,9 +352,9 @@ impl Internal { } } - pub fn picked_pane(&self) -> Option<Pane> { + pub fn picked_pane(&self) -> Option<(Pane, Point)> { match self.action { - Action::Dragging { pane } => Some(pane), + Action::Dragging { pane, origin } => Some((pane, origin)), _ => None, } } @@ -385,8 +386,11 @@ impl Internal { self.action = Action::Idle { focus: Some(*pane) }; } - pub fn pick_pane(&mut self, pane: &Pane) { - self.action = Action::Dragging { pane: *pane }; + pub fn pick_pane(&mut self, pane: &Pane, origin: Point) { + self.action = Action::Dragging { + pane: *pane, + origin, + }; } pub fn pick_split(&mut self, split: &Split, axis: Axis) { diff --git a/native/src/widget/pane_grid/title_bar.rs b/native/src/widget/pane_grid/title_bar.rs index 1fd06411..dc96dcbf 100644 --- a/native/src/widget/pane_grid/title_bar.rs +++ b/native/src/widget/pane_grid/title_bar.rs @@ -1,7 +1,7 @@ use crate::container; use crate::layout; use crate::pane_grid; -use crate::{Element, Layout, Point, Size}; +use crate::{Clipboard, Element, Event, Layout, Point, Size}; pub struct TitleBar<'a, Message, Renderer: container::Renderer> { title: Element<'a, Message, Renderer>, @@ -38,6 +38,14 @@ where self.padding = units; self } + + /// Sets the style of the [`TitleBar`]. + /// + /// [`TitleBar`]: struct.TitleBar.html + pub fn style(mut self, style: impl Into<Renderer::Style>) -> Self { + self.style = style.into(); + self + } } impl<'a, Message, Renderer> TitleBar<'a, Message, Renderer> @@ -50,30 +58,63 @@ where defaults: &Renderer::Defaults, layout: Layout<'_>, cursor_position: Point, + show_controls: bool, ) -> Renderer::Output { + let mut children = layout.children(); + let padded = children.next().unwrap(); + if let Some(controls) = &self.controls { - let mut children = layout.children(); + let mut children = padded.children(); let title_layout = children.next().unwrap(); let controls_layout = children.next().unwrap(); renderer.draw_title_bar( defaults, + layout.bounds(), &self.style, (&self.title, title_layout), - Some((controls, controls_layout)), + if show_controls { + Some((controls, controls_layout)) + } else { + None + }, cursor_position, ) } else { renderer.draw_title_bar( defaults, + layout.bounds(), &self.style, - (&self.title, layout), + (&self.title, padded), None, cursor_position, ) } } + pub fn is_over_draggable( + &self, + layout: Layout<'_>, + cursor_position: Point, + ) -> bool { + if layout.bounds().contains(cursor_position) { + let mut children = layout.children(); + let padded = children.next().unwrap(); + + if self.controls.is_some() { + let mut children = padded.children(); + let _ = children.next().unwrap(); + let controls_layout = children.next().unwrap(); + + !controls_layout.bounds().contains(cursor_position) + } else { + true + } + } else { + false + } + } + pub(crate) fn layout( &self, renderer: &Renderer, @@ -82,38 +123,66 @@ where let padding = f32::from(self.padding); let limits = limits.pad(padding); - let mut node = if let Some(controls) = &self.controls { + let node = if let Some(controls) = &self.controls { let max_size = limits.max(); - let title_layout = self - .title + let mut controls_layout = controls .layout(renderer, &layout::Limits::new(Size::ZERO, max_size)); - let title_size = title_layout.size(); + let controls_size = controls_layout.size(); + let space_before_controls = max_size.width - controls_size.width; - let mut controls_layout = controls.layout( + let mut title_layout = self.title.layout( renderer, &layout::Limits::new( Size::ZERO, - Size::new( - max_size.width - title_size.width, - max_size.height, - ), + Size::new(space_before_controls, max_size.height), ), ); - controls_layout.move_to(Point::new(title_size.width, 0.0)); + title_layout.move_to(Point::new(padding, padding)); + controls_layout + .move_to(Point::new(space_before_controls + padding, padding)); + + let title_size = title_layout.size(); + let height = title_size.height.max(controls_size.height); layout::Node::with_children( - max_size, + Size::new(max_size.width, height), vec![title_layout, controls_layout], ) } else { self.title.layout(renderer, &limits) }; - node.move_to(Point::new(padding, padding)); + layout::Node::with_children(node.size().pad(padding), vec![node]) + } + + pub(crate) fn on_event( + &mut self, + event: Event, + layout: Layout<'_>, + cursor_position: Point, + messages: &mut Vec<Message>, + renderer: &Renderer, + clipboard: Option<&dyn Clipboard>, + ) { + if let Some(controls) = &mut self.controls { + let mut children = layout.children(); + let padded = children.next().unwrap(); + + let mut children = padded.children(); + let _ = children.next(); + let controls_layout = children.next().unwrap(); - node + controls.on_event( + event, + controls_layout, + cursor_position, + messages, + renderer, + clipboard, + ); + } } } |