diff options
Diffstat (limited to 'widget')
-rw-r--r-- | widget/src/button.rs | 4 | ||||
-rw-r--r-- | widget/src/checkbox.rs | 2 | ||||
-rw-r--r-- | widget/src/container.rs | 2 | ||||
-rw-r--r-- | widget/src/overlay/menu.rs | 4 | ||||
-rw-r--r-- | widget/src/pane_grid.rs | 111 | ||||
-rw-r--r-- | widget/src/pane_grid/state.rs | 41 | ||||
-rw-r--r-- | widget/src/pick_list.rs | 2 | ||||
-rw-r--r-- | widget/src/progress_bar.rs | 4 | ||||
-rw-r--r-- | widget/src/rule.rs | 2 | ||||
-rw-r--r-- | widget/src/scrollable.rs | 26 | ||||
-rw-r--r-- | widget/src/slider.rs | 22 | ||||
-rw-r--r-- | widget/src/text_input.rs | 2 | ||||
-rw-r--r-- | widget/src/vertical_slider.rs | 22 |
13 files changed, 193 insertions, 51 deletions
diff --git a/widget/src/button.rs b/widget/src/button.rs index 7eee69cb..70fed1d5 100644 --- a/widget/src/button.rs +++ b/widget/src/button.rs @@ -395,7 +395,7 @@ where y: bounds.y + styling.shadow_offset.y, ..bounds }, - border_radius: styling.border_radius.into(), + border_radius: styling.border_radius, border_width: 0.0, border_color: Color::TRANSPARENT, }, @@ -406,7 +406,7 @@ where renderer.fill_quad( renderer::Quad { bounds, - border_radius: styling.border_radius.into(), + border_radius: styling.border_radius, border_width: styling.border_width, border_color: styling.border_color, }, diff --git a/widget/src/checkbox.rs b/widget/src/checkbox.rs index 7d43bb4a..4c8a989b 100644 --- a/widget/src/checkbox.rs +++ b/widget/src/checkbox.rs @@ -269,7 +269,7 @@ where renderer.fill_quad( renderer::Quad { bounds, - border_radius: custom_style.border_radius.into(), + border_radius: custom_style.border_radius, border_width: custom_style.border_width, border_color: custom_style.border_color, }, diff --git a/widget/src/container.rs b/widget/src/container.rs index 9d932772..13e76551 100644 --- a/widget/src/container.rs +++ b/widget/src/container.rs @@ -332,7 +332,7 @@ pub fn draw_background<Renderer>( renderer.fill_quad( renderer::Quad { bounds, - border_radius: appearance.border_radius.into(), + border_radius: appearance.border_radius, border_width: appearance.border_width, border_color: appearance.border_color, }, diff --git a/widget/src/overlay/menu.rs b/widget/src/overlay/menu.rs index 0acc6f79..84cc800c 100644 --- a/widget/src/overlay/menu.rs +++ b/widget/src/overlay/menu.rs @@ -307,7 +307,7 @@ where bounds, border_color: appearance.border_color, border_width: appearance.border_width, - border_radius: appearance.border_radius.into(), + border_radius: appearance.border_radius, }, appearance.background, ); @@ -515,7 +515,7 @@ where }, border_color: Color::TRANSPARENT, border_width: 0.0, - border_radius: appearance.border_radius.into(), + border_radius: appearance.border_radius, }, appearance.selected_background, ); diff --git a/widget/src/pane_grid.rs b/widget/src/pane_grid.rs index 67145e8e..7bddc4a6 100644 --- a/widget/src/pane_grid.rs +++ b/widget/src/pane_grid.rs @@ -30,7 +30,7 @@ pub use split::Split; pub use state::State; pub use title_bar::TitleBar; -pub use crate::style::pane_grid::{Line, StyleSheet}; +pub use crate::style::pane_grid::{Appearance, Line, StyleSheet}; use crate::container; use crate::core::event::{self, Event}; @@ -594,13 +594,18 @@ pub fn update<'a, Message, T: Draggable>( if let Some(on_drag) = on_drag { let mut dropped_region = contents .zip(layout.children()) - .filter(|(_, layout)| { - layout.bounds().contains(cursor_position) + .filter_map(|(target, layout)| { + layout_region(layout, cursor_position) + .map(|region| (target, region)) }); let event = match dropped_region.next() { - Some(((target, _), _)) if pane != target => { - DragEvent::Dropped { pane, target } + Some(((target, _), region)) if pane != target => { + DragEvent::Dropped { + pane, + target, + region, + } } _ => DragEvent::Canceled { pane }, }; @@ -657,6 +662,28 @@ pub fn update<'a, Message, T: Draggable>( event_status } +fn layout_region(layout: Layout<'_>, cursor_position: Point) -> Option<Region> { + let bounds = layout.bounds(); + + if !bounds.contains(cursor_position) { + return None; + } + + let region = if cursor_position.x < (bounds.x + bounds.width / 3.0) { + Region::Left + } else if cursor_position.x > (bounds.x + 2.0 * bounds.width / 3.0) { + Region::Right + } else if cursor_position.y < (bounds.y + bounds.height / 3.0) { + Region::Top + } else if cursor_position.y > (bounds.y + 2.0 * bounds.height / 3.0) { + Region::Bottom + } else { + Region::Center + }; + + Some(region) +} + fn click_pane<'a, Message, T>( action: &mut state::Action, layout: Layout<'_>, @@ -810,6 +837,35 @@ pub fn draw<Renderer, T>( Some((dragging, origin)) if id == dragging => { render_picked_pane = Some((pane, origin, layout)); } + Some((dragging, _)) if id != dragging => { + draw_pane( + pane, + renderer, + default_style, + layout, + pane_cursor_position, + viewport, + ); + + if picked_pane.is_some() { + if let Some(region) = layout_region(layout, cursor_position) + { + let bounds = layout_region_bounds(layout, region); + let hovered_region_style = theme.hovered_region(style); + + renderer.fill_quad( + renderer::Quad { + bounds, + border_radius: hovered_region_style + .border_radius, + border_width: hovered_region_style.border_width, + border_color: hovered_region_style.border_color, + }, + theme.hovered_region(style).background, + ); + } + } + } _ => { draw_pane( pane, @@ -884,6 +940,32 @@ pub fn draw<Renderer, T>( } } +fn layout_region_bounds(layout: Layout<'_>, region: Region) -> Rectangle { + let bounds = layout.bounds(); + + match region { + Region::Center => bounds, + Region::Top => Rectangle { + height: bounds.height / 2.0, + ..bounds + }, + Region::Left => Rectangle { + width: bounds.width / 2.0, + ..bounds + }, + Region::Right => Rectangle { + x: bounds.x + bounds.width / 2.0, + width: bounds.width / 2.0, + ..bounds + }, + Region::Bottom => Rectangle { + y: bounds.y + bounds.height / 2.0, + height: bounds.height / 2.0, + ..bounds + }, + } +} + /// An event produced during a drag and drop interaction of a [`PaneGrid`]. #[derive(Debug, Clone, Copy)] pub enum DragEvent { @@ -900,6 +982,9 @@ pub enum DragEvent { /// The [`Pane`] where the picked one was dropped on. target: Pane, + + /// The [`Region`] of the target [`Pane`] where the picked one was dropped on. + region: Region, }, /// A [`Pane`] was picked and then dropped outside of other [`Pane`] @@ -910,6 +995,22 @@ pub enum DragEvent { }, } +/// The region of a [`Pane`]. +#[derive(Debug, Clone, Copy, Default)] +pub enum Region { + /// Center region. + #[default] + Center, + /// Top region. + Top, + /// Left region. + Left, + /// Right region. + Right, + /// Bottom region. + Bottom, +} + /// An event produced during a resize interaction of a [`PaneGrid`]. #[derive(Debug, Clone, Copy)] pub struct ResizeEvent { diff --git a/widget/src/pane_grid/state.rs b/widget/src/pane_grid/state.rs index a6e2ec7f..1f034ca3 100644 --- a/widget/src/pane_grid/state.rs +++ b/widget/src/pane_grid/state.rs @@ -2,7 +2,9 @@ //! //! [`PaneGrid`]: crate::widget::PaneGrid use crate::core::{Point, Size}; -use crate::pane_grid::{Axis, Configuration, Direction, Node, Pane, Split}; +use crate::pane_grid::{ + Axis, Configuration, Direction, Node, Pane, Region, Split, +}; use std::collections::HashMap; @@ -165,6 +167,43 @@ impl<T> State<T> { Some((new_pane, new_split)) } + /// Split a target [`Pane`] with a given [`Pane`] on a given [`Region`]. + /// + /// Panes will be swapped by default for [`Region::Center`]. + pub fn split_with(&mut self, target: &Pane, pane: &Pane, region: Region) { + match region { + Region::Center => self.swap(pane, target), + Region::Top => { + self.split_and_swap(Axis::Horizontal, target, pane, true) + } + Region::Bottom => { + self.split_and_swap(Axis::Horizontal, target, pane, false) + } + Region::Left => { + self.split_and_swap(Axis::Vertical, target, pane, true) + } + Region::Right => { + self.split_and_swap(Axis::Vertical, target, pane, false) + } + } + } + + fn split_and_swap( + &mut self, + axis: Axis, + target: &Pane, + pane: &Pane, + swap: bool, + ) { + if let Some((state, _)) = self.close(pane) { + if let Some((new_pane, _)) = self.split(axis, target, state) { + if swap { + self.swap(target, &new_pane); + } + } + } + } + /// Swaps the position of the provided panes in the [`State`]. /// /// If you want to swap panes on drag and drop in your [`PaneGrid`], you diff --git a/widget/src/pick_list.rs b/widget/src/pick_list.rs index 8c445dda..dcd0629b 100644 --- a/widget/src/pick_list.rs +++ b/widget/src/pick_list.rs @@ -624,7 +624,7 @@ pub fn draw<'a, T, Renderer>( bounds, border_color: style.border_color, border_width: style.border_width, - border_radius: style.border_radius.into(), + border_radius: style.border_radius, }, style.background, ); diff --git a/widget/src/progress_bar.rs b/widget/src/progress_bar.rs index ef0d87d5..9e1e9131 100644 --- a/widget/src/progress_bar.rs +++ b/widget/src/progress_bar.rs @@ -133,7 +133,7 @@ where renderer.fill_quad( renderer::Quad { bounds: Rectangle { ..bounds }, - border_radius: style.border_radius.into(), + border_radius: style.border_radius, border_width: 0.0, border_color: Color::TRANSPARENT, }, @@ -147,7 +147,7 @@ where width: active_progress_width, ..bounds }, - border_radius: style.border_radius.into(), + border_radius: style.border_radius, border_width: 0.0, border_color: Color::TRANSPARENT, }, diff --git a/widget/src/rule.rs b/widget/src/rule.rs index 3749d7ce..272bd2b3 100644 --- a/widget/src/rule.rs +++ b/widget/src/rule.rs @@ -125,7 +125,7 @@ where renderer.fill_quad( renderer::Quad { bounds, - border_radius: style.radius.into(), + border_radius: style.radius, border_width: 0.0, border_color: Color::TRANSPARENT, }, diff --git a/widget/src/scrollable.rs b/widget/src/scrollable.rs index fd51a6a8..12e544c5 100644 --- a/widget/src/scrollable.rs +++ b/widget/src/scrollable.rs @@ -128,9 +128,8 @@ impl Properties { } /// Sets the scrollbar width of the [`Scrollable`] . - /// Silently enforces a minimum width of 1. pub fn width(mut self, width: impl Into<Pixels>) -> Self { - self.width = width.into().0.max(1.0); + self.width = width.into().0.max(0.0); self } @@ -141,9 +140,8 @@ impl Properties { } /// Sets the scroller width of the [`Scrollable`] . - /// Silently enforces a minimum width of 1. pub fn scroller_width(mut self, scroller_width: impl Into<Pixels>) -> Self { - self.scroller_width = scroller_width.into().0.max(1.0); + self.scroller_width = scroller_width.into().0.max(0.0); self } } @@ -811,14 +809,16 @@ pub fn draw<Renderer>( style: Scrollbar, scrollbar: &internals::Scrollbar| { //track - if style.background.is_some() - || (style.border_color != Color::TRANSPARENT - && style.border_width > 0.0) + if scrollbar.bounds.width > 0.0 + && scrollbar.bounds.height > 0.0 + && (style.background.is_some() + || (style.border_color != Color::TRANSPARENT + && style.border_width > 0.0)) { renderer.fill_quad( renderer::Quad { bounds: scrollbar.bounds, - border_radius: style.border_radius.into(), + border_radius: style.border_radius, border_width: style.border_width, border_color: style.border_color, }, @@ -829,14 +829,16 @@ pub fn draw<Renderer>( } //thumb - if style.scroller.color != Color::TRANSPARENT - || (style.scroller.border_color != Color::TRANSPARENT - && style.scroller.border_width > 0.0) + if scrollbar.scroller.bounds.width > 0.0 + && scrollbar.scroller.bounds.height > 0.0 + && (style.scroller.color != Color::TRANSPARENT + || (style.scroller.border_color != Color::TRANSPARENT + && style.scroller.border_width > 0.0)) { renderer.fill_quad( renderer::Quad { bounds: scrollbar.scroller.bounds, - border_radius: style.scroller.border_radius.into(), + border_radius: style.scroller.border_radius, border_width: style.scroller.border_width, border_color: style.scroller.border_color, }, diff --git a/widget/src/slider.rs b/widget/src/slider.rs index 18a49665..2851d8c3 100644 --- a/widget/src/slider.rs +++ b/widget/src/slider.rs @@ -368,16 +368,16 @@ pub fn draw<T, R>( style_sheet.active(style) }; - let (handle_width, handle_height, handle_border_radius) = match style - .handle - .shape - { - HandleShape::Circle { radius } => (radius * 2.0, radius * 2.0, radius), - HandleShape::Rectangle { - width, - border_radius, - } => (f32::from(width), bounds.height, border_radius), - }; + let (handle_width, handle_height, handle_border_radius) = + match style.handle.shape { + HandleShape::Circle { radius } => { + (radius * 2.0, radius * 2.0, radius.into()) + } + HandleShape::Rectangle { + width, + border_radius, + } => (f32::from(width), bounds.height, border_radius), + }; let value = value.into() as f32; let (range_start, range_end) = { @@ -433,7 +433,7 @@ pub fn draw<T, R>( width: handle_width, height: handle_height, }, - border_radius: handle_border_radius.into(), + border_radius: handle_border_radius, border_width: style.handle.border_width, border_color: style.handle.border_color, }, diff --git a/widget/src/text_input.rs b/widget/src/text_input.rs index bbc07dac..8f243c1a 100644 --- a/widget/src/text_input.rs +++ b/widget/src/text_input.rs @@ -982,7 +982,7 @@ pub fn draw<Renderer>( renderer.fill_quad( renderer::Quad { bounds, - border_radius: appearance.border_radius.into(), + border_radius: appearance.border_radius, border_width: appearance.border_width, border_color: appearance.border_color, }, diff --git a/widget/src/vertical_slider.rs b/widget/src/vertical_slider.rs index 2635611d..3b2430c4 100644 --- a/widget/src/vertical_slider.rs +++ b/widget/src/vertical_slider.rs @@ -366,16 +366,16 @@ pub fn draw<T, R>( style_sheet.active(style) }; - let (handle_width, handle_height, handle_border_radius) = match style - .handle - .shape - { - HandleShape::Circle { radius } => (radius * 2.0, radius * 2.0, radius), - HandleShape::Rectangle { - width, - border_radius, - } => (f32::from(width), bounds.width, border_radius), - }; + let (handle_width, handle_height, handle_border_radius) = + match style.handle.shape { + HandleShape::Circle { radius } => { + (radius * 2.0, radius * 2.0, radius.into()) + } + HandleShape::Rectangle { + width, + border_radius, + } => (f32::from(width), bounds.width, border_radius), + }; let value = value.into() as f32; let (range_start, range_end) = { @@ -431,7 +431,7 @@ pub fn draw<T, R>( width: handle_height, height: handle_width, }, - border_radius: handle_border_radius.into(), + border_radius: handle_border_radius, border_width: style.handle.border_width, border_color: style.handle.border_color, }, |