diff options
author | 2020-05-19 17:15:44 +0200 | |
---|---|---|
committer | 2020-05-19 17:15:44 +0200 | |
commit | 05af8d00d4c0f7b8e0ece85224fd90a92da86da8 (patch) | |
tree | 98e4774a2c0d4a2a0a01aff1d772f89c4cb0aa5e /glow | |
parent | d4743183d40c6044ce6fa39e2a52919a32912cda (diff) | |
download | iced-05af8d00d4c0f7b8e0ece85224fd90a92da86da8.tar.gz iced-05af8d00d4c0f7b8e0ece85224fd90a92da86da8.tar.bz2 iced-05af8d00d4c0f7b8e0ece85224fd90a92da86da8.zip |
Draft new `iced_graphics` crate :tada:
Diffstat (limited to 'glow')
34 files changed, 52 insertions, 1354 deletions
diff --git a/glow/Cargo.toml b/glow/Cargo.toml index e130d563..212fbb30 100644 --- a/glow/Cargo.toml +++ b/glow/Cargo.toml @@ -21,9 +21,9 @@ glyph_brush = "0.6" version = "0.2" path = "../native" -[dependencies.iced_style] +[dependencies.iced_graphics] version = "0.1" -path = "../style" +path = "../graphics" [dependencies.surfman] path = "../../surfman/surfman" diff --git a/glow/src/renderer.rs b/glow/src/backend.rs index 40228a6b..7293eba1 100644 --- a/glow/src/renderer.rs +++ b/glow/src/backend.rs @@ -1,19 +1,17 @@ -use crate::{ - quad, text, triangle, Defaults, Primitive, Quad, Settings, Transformation, - Viewport, -}; - -use iced_native::{ - layout, mouse, Background, Color, Layout, Point, Rectangle, Vector, Widget, -}; - -mod widget; +use crate::quad; +use crate::text; +use crate::triangle; +use crate::{Quad, Settings, Transformation, Viewport}; +use iced_graphics::backend; +use iced_graphics::Primitive; +use iced_native::mouse; +use iced_native::{Background, Font, Point, Rectangle, Size, Vector}; /// A [`glow`] renderer. /// /// [`glow`]: https://github.com/grovesNL/glow #[derive(Debug)] -pub struct Renderer { +pub struct Backend { quad_pipeline: quad::Pipeline, text_pipeline: text::Pipeline, triangle_pipeline: triangle::Pipeline, @@ -43,7 +41,7 @@ impl<'a> Layer<'a> { } } -impl Renderer { +impl Backend { /// Creates a new [`Renderer`]. /// /// [`Renderer`]: struct.Renderer.html @@ -399,57 +397,27 @@ impl Renderer { } } -impl iced_native::Renderer for Renderer { - type Output = (Primitive, mouse::Interaction); - type Defaults = Defaults; - - fn layout<'a, Message>( - &mut self, - element: &iced_native::Element<'a, Message, Self>, - limits: &iced_native::layout::Limits, - ) -> iced_native::layout::Node { - let node = element.layout(self, limits); - - self.text_pipeline.clear_measurement_cache(); - - node +impl iced_graphics::Backend for Backend { + fn trim_measurements(&mut self) { + self.text_pipeline.trim_measurement_cache() } } -impl layout::Debugger for Renderer { - fn explain<Message>( - &mut self, - defaults: &Defaults, - widget: &dyn Widget<Message, Self>, - layout: Layout<'_>, - cursor_position: Point, - color: Color, - ) -> Self::Output { - let mut primitives = Vec::new(); - let (primitive, cursor) = - widget.draw(self, defaults, layout, cursor_position); - - explain_layout(layout, color, &mut primitives); - primitives.push(primitive); - - (Primitive::Group { primitives }, cursor) +impl backend::Text for Backend { + const ICON_FONT: Font = text::BUILTIN_ICONS; + const CHECKMARK_ICON: char = text::CHECKMARK_ICON; + + fn measure( + &self, + contents: &str, + size: f32, + font: Font, + bounds: Size, + ) -> (f32, f32) { + self.text_pipeline.measure(contents, size, font, bounds) } -} -fn explain_layout( - layout: Layout<'_>, - color: Color, - primitives: &mut Vec<Primitive>, -) { - primitives.push(Primitive::Quad { - bounds: layout.bounds(), - background: Background::Color(Color::TRANSPARENT), - border_radius: 0, - border_width: 1, - border_color: [0.6, 0.6, 0.6, 0.5].into(), - }); - - for child in layout.children() { - explain_layout(child, color, primitives); + fn space_width(&self, size: f32) -> f32 { + self.text_pipeline.space_width(size) } } diff --git a/glow/src/defaults.rs b/glow/src/defaults.rs deleted file mode 100644 index 11718a87..00000000 --- a/glow/src/defaults.rs +++ /dev/null @@ -1,32 +0,0 @@ -//! Use default styling attributes to inherit styles. -use iced_native::Color; - -/// Some default styling attributes. -#[derive(Debug, Clone, Copy)] -pub struct Defaults { - /// Text styling - pub text: Text, -} - -impl Default for Defaults { - fn default() -> Defaults { - Defaults { - text: Text::default(), - } - } -} - -/// Some default text styling attributes. -#[derive(Debug, Clone, Copy)] -pub struct Text { - /// The default color of text - pub color: Color, -} - -impl Default for Text { - fn default() -> Text { - Text { - color: Color::BLACK, - } - } -} diff --git a/glow/src/lib.rs b/glow/src/lib.rs index ce447192..27c39b99 100644 --- a/glow/src/lib.rs +++ b/glow/src/lib.rs @@ -4,10 +4,8 @@ //#![forbid(unsafe_code)] #![forbid(rust_2018_idioms)] -mod defaults; -mod primitive; +mod backend; mod quad; -mod renderer; mod text; mod transformation; mod triangle; @@ -17,15 +15,15 @@ pub mod settings; pub mod widget; pub mod window; -pub use defaults::Defaults; -pub use primitive::Primitive; -pub use renderer::Renderer; pub use settings::Settings; pub use viewport::Viewport; +pub(crate) use backend::Backend; pub(crate) use quad::Quad; pub(crate) use transformation::Transformation; +pub type Renderer = iced_graphics::Renderer<Backend>; + #[doc(no_inline)] pub use widget::*; diff --git a/glow/src/primitive.rs b/glow/src/primitive.rs deleted file mode 100644 index e73227ef..00000000 --- a/glow/src/primitive.rs +++ /dev/null @@ -1,107 +0,0 @@ -use iced_native::{ - image, svg, Background, Color, Font, HorizontalAlignment, Rectangle, Size, - Vector, VerticalAlignment, -}; - -use crate::triangle; -use std::sync::Arc; - -/// A rendering primitive. -#[derive(Debug, Clone)] -pub enum Primitive { - /// An empty primitive - None, - /// A group of primitives - Group { - /// The primitives of the group - primitives: Vec<Primitive>, - }, - /// A text primitive - Text { - /// The contents of the text - content: String, - /// The bounds of the text - bounds: Rectangle, - /// The color of the text - color: Color, - /// The size of the text - size: f32, - /// The font of the text - font: Font, - /// The horizontal alignment of the text - horizontal_alignment: HorizontalAlignment, - /// The vertical alignment of the text - vertical_alignment: VerticalAlignment, - }, - /// A quad primitive - Quad { - /// The bounds of the quad - bounds: Rectangle, - /// The background of the quad - background: Background, - /// The border radius of the quad - border_radius: u16, - /// The border width of the quad - border_width: u16, - /// The border color of the quad - border_color: Color, - }, - /// An image primitive - Image { - /// The handle of the image - handle: image::Handle, - /// The bounds of the image - bounds: Rectangle, - }, - /// An SVG primitive - Svg { - /// The path of the SVG file - handle: svg::Handle, - - /// The bounds of the viewport - bounds: Rectangle, - }, - /// A clip primitive - Clip { - /// The bounds of the clip - bounds: Rectangle, - /// The offset transformation of the clip - offset: Vector<u32>, - /// The content of the clip - content: Box<Primitive>, - }, - /// A primitive that applies a translation - Translate { - /// The translation vector - translation: Vector, - - /// The primitive to translate - content: Box<Primitive>, - }, - /// A low-level primitive to render a mesh of triangles. - /// - /// It can be used to render many kinds of geometry freely. - Mesh2D { - /// The size of the drawable region of the mesh. - /// - /// Any geometry that falls out of this region will be clipped. - size: Size, - - /// The vertex and index buffers of the mesh - buffers: triangle::Mesh2D, - }, - /// A cached primitive. - /// - /// This can be useful if you are implementing a widget where primitive - /// generation is expensive. - Cached { - /// The cached primitive - cache: Arc<Primitive>, - }, -} - -impl Default for Primitive { - fn default() -> Primitive { - Primitive::None - } -} diff --git a/glow/src/renderer/widget.rs b/glow/src/renderer/widget.rs deleted file mode 100644 index 37421fbe..00000000 --- a/glow/src/renderer/widget.rs +++ /dev/null @@ -1,19 +0,0 @@ -mod button; -mod checkbox; -mod column; -mod container; -mod pane_grid; -mod progress_bar; -mod radio; -mod row; -mod scrollable; -mod slider; -mod space; -mod text; -mod text_input; - -#[cfg(feature = "svg")] -mod svg; - -#[cfg(feature = "image")] -mod image; diff --git a/glow/src/renderer/widget/button.rs b/glow/src/renderer/widget/button.rs deleted file mode 100644 index eb225038..00000000 --- a/glow/src/renderer/widget/button.rs +++ /dev/null @@ -1,93 +0,0 @@ -use crate::{button::StyleSheet, defaults, Defaults, Primitive, Renderer}; -use iced_native::{ - mouse, Background, Color, Element, Layout, Point, Rectangle, Vector, -}; - -impl iced_native::button::Renderer for Renderer { - const DEFAULT_PADDING: u16 = 5; - - type Style = Box<dyn StyleSheet>; - - fn draw<Message>( - &mut self, - _defaults: &Defaults, - bounds: Rectangle, - cursor_position: Point, - is_disabled: bool, - is_pressed: bool, - style: &Box<dyn StyleSheet>, - content: &Element<'_, Message, Self>, - content_layout: Layout<'_>, - ) -> Self::Output { - let is_mouse_over = bounds.contains(cursor_position); - - let styling = if is_disabled { - style.disabled() - } else if is_mouse_over { - if is_pressed { - style.pressed() - } else { - style.hovered() - } - } else { - style.active() - }; - - let (content, _) = content.draw( - self, - &Defaults { - text: defaults::Text { - color: styling.text_color, - }, - }, - content_layout, - cursor_position, - ); - - ( - if styling.background.is_some() || styling.border_width > 0 { - let background = Primitive::Quad { - bounds, - background: styling - .background - .unwrap_or(Background::Color(Color::TRANSPARENT)), - border_radius: styling.border_radius, - border_width: styling.border_width, - border_color: styling.border_color, - }; - - if styling.shadow_offset == Vector::default() { - Primitive::Group { - primitives: vec![background, content], - } - } else { - // TODO: Implement proper shadow support - let shadow = Primitive::Quad { - bounds: Rectangle { - x: bounds.x + styling.shadow_offset.x, - y: bounds.y + styling.shadow_offset.y, - ..bounds - }, - background: Background::Color( - [0.0, 0.0, 0.0, 0.5].into(), - ), - border_radius: styling.border_radius, - border_width: 0, - border_color: Color::TRANSPARENT, - }; - - Primitive::Group { - primitives: vec![shadow, background, content], - } - } - } else { - content - }, - if is_mouse_over { - mouse::Interaction::Pointer - } else { - mouse::Interaction::default() - }, - ) - } -} diff --git a/glow/src/renderer/widget/checkbox.rs b/glow/src/renderer/widget/checkbox.rs deleted file mode 100644 index 0340bf62..00000000 --- a/glow/src/renderer/widget/checkbox.rs +++ /dev/null @@ -1,63 +0,0 @@ -use crate::{checkbox::StyleSheet, Primitive, Renderer}; -use iced_native::{ - checkbox, mouse, HorizontalAlignment, Rectangle, VerticalAlignment, -}; - -impl checkbox::Renderer for Renderer { - type Style = Box<dyn StyleSheet>; - - const DEFAULT_SIZE: u16 = 20; - const DEFAULT_SPACING: u16 = 15; - - fn draw( - &mut self, - bounds: Rectangle, - is_checked: bool, - is_mouse_over: bool, - (label, _): Self::Output, - style_sheet: &Self::Style, - ) -> Self::Output { - let style = if is_mouse_over { - style_sheet.hovered(is_checked) - } else { - style_sheet.active(is_checked) - }; - - let checkbox = Primitive::Quad { - bounds, - background: style.background, - border_radius: style.border_radius, - border_width: style.border_width, - border_color: style.border_color, - }; - - ( - Primitive::Group { - primitives: if is_checked { - let check = Primitive::Text { - content: crate::text::CHECKMARK_ICON.to_string(), - font: crate::text::BUILTIN_ICONS, - size: bounds.height * 0.7, - bounds: Rectangle { - x: bounds.center_x(), - y: bounds.center_y(), - ..bounds - }, - color: style.checkmark_color, - horizontal_alignment: HorizontalAlignment::Center, - vertical_alignment: VerticalAlignment::Center, - }; - - vec![checkbox, check, label] - } else { - vec![checkbox, label] - }, - }, - if is_mouse_over { - mouse::Interaction::Pointer - } else { - mouse::Interaction::default() - }, - ) - } -} diff --git a/glow/src/renderer/widget/column.rs b/glow/src/renderer/widget/column.rs deleted file mode 100644 index b853276d..00000000 --- a/glow/src/renderer/widget/column.rs +++ /dev/null @@ -1,34 +0,0 @@ -use crate::{Primitive, Renderer}; -use iced_native::{column, mouse, Element, Layout, Point}; - -impl column::Renderer for Renderer { - fn draw<Message>( - &mut self, - defaults: &Self::Defaults, - content: &[Element<'_, Message, Self>], - layout: Layout<'_>, - cursor_position: Point, - ) -> Self::Output { - let mut mouse_interaction = mouse::Interaction::default(); - - ( - Primitive::Group { - primitives: content - .iter() - .zip(layout.children()) - .map(|(child, layout)| { - let (primitive, new_mouse_interaction) = - child.draw(self, defaults, layout, cursor_position); - - if new_mouse_interaction > mouse_interaction { - mouse_interaction = new_mouse_interaction; - } - - primitive - }) - .collect(), - }, - mouse_interaction, - ) - } -} diff --git a/glow/src/renderer/widget/container.rs b/glow/src/renderer/widget/container.rs deleted file mode 100644 index 30cc3f07..00000000 --- a/glow/src/renderer/widget/container.rs +++ /dev/null @@ -1,48 +0,0 @@ -use crate::{container, defaults, Defaults, Primitive, Renderer}; -use iced_native::{Background, Color, Element, Layout, Point, Rectangle}; - -impl iced_native::container::Renderer for Renderer { - type Style = Box<dyn container::StyleSheet>; - - fn draw<Message>( - &mut self, - defaults: &Defaults, - bounds: Rectangle, - cursor_position: Point, - style_sheet: &Self::Style, - content: &Element<'_, Message, Self>, - content_layout: Layout<'_>, - ) -> Self::Output { - let style = style_sheet.style(); - - let defaults = Defaults { - text: defaults::Text { - color: style.text_color.unwrap_or(defaults.text.color), - }, - }; - - let (content, mouse_interaction) = - content.draw(self, &defaults, content_layout, cursor_position); - - if style.background.is_some() || style.border_width > 0 { - let quad = Primitive::Quad { - bounds, - background: style - .background - .unwrap_or(Background::Color(Color::TRANSPARENT)), - border_radius: style.border_radius, - border_width: style.border_width, - border_color: style.border_color, - }; - - ( - Primitive::Group { - primitives: vec![quad, content], - }, - mouse_interaction, - ) - } else { - (content, mouse_interaction) - } - } -} diff --git a/glow/src/renderer/widget/image.rs b/glow/src/renderer/widget/image.rs deleted file mode 100644 index c4c04984..00000000 --- a/glow/src/renderer/widget/image.rs +++ /dev/null @@ -1,22 +0,0 @@ -use crate::{Primitive, Renderer}; -use iced_native::{image, mouse, Layout}; - -impl image::Renderer for Renderer { - fn dimensions(&self, handle: &image::Handle) -> (u32, u32) { - self.image_pipeline.dimensions(handle) - } - - fn draw( - &mut self, - handle: image::Handle, - layout: Layout<'_>, - ) -> Self::Output { - ( - Primitive::Image { - handle, - bounds: layout.bounds(), - }, - mouse::Interaction::default(), - ) - } -} diff --git a/glow/src/renderer/widget/pane_grid.rs b/glow/src/renderer/widget/pane_grid.rs deleted file mode 100644 index 2253e4af..00000000 --- a/glow/src/renderer/widget/pane_grid.rs +++ /dev/null @@ -1,93 +0,0 @@ -use crate::{Primitive, Renderer}; -use iced_native::{ - mouse, - pane_grid::{self, Axis, Pane}, - Element, Layout, Point, Rectangle, Vector, -}; - -impl pane_grid::Renderer for Renderer { - fn draw<Message>( - &mut self, - defaults: &Self::Defaults, - content: &[(Pane, Element<'_, Message, Self>)], - dragging: Option<Pane>, - resizing: Option<Axis>, - layout: Layout<'_>, - cursor_position: Point, - ) -> Self::Output { - let pane_cursor_position = if dragging.is_some() { - // TODO: Remove once cursor availability is encoded in the type - // system - Point::new(-1.0, -1.0) - } else { - cursor_position - }; - - let mut mouse_interaction = mouse::Interaction::default(); - let mut dragged_pane = None; - - let mut panes: Vec<_> = content - .iter() - .zip(layout.children()) - .enumerate() - .map(|(i, ((id, pane), layout))| { - let (primitive, new_mouse_interaction) = - pane.draw(self, defaults, layout, pane_cursor_position); - - if new_mouse_interaction > mouse_interaction { - mouse_interaction = new_mouse_interaction; - } - - if Some(*id) == dragging { - dragged_pane = Some((i, layout)); - } - - primitive - }) - .collect(); - - let primitives = if let Some((index, layout)) = dragged_pane { - let pane = panes.remove(index); - let bounds = layout.bounds(); - - // TODO: Fix once proper layering is implemented. - // This is a pretty hacky way to achieve layering. - let clip = Primitive::Clip { - bounds: Rectangle { - x: cursor_position.x - bounds.width / 2.0, - y: cursor_position.y - bounds.height / 2.0, - width: bounds.width + 0.5, - height: bounds.height + 0.5, - }, - offset: Vector::new(0, 0), - content: Box::new(Primitive::Translate { - translation: Vector::new( - cursor_position.x - bounds.x - bounds.width / 2.0, - cursor_position.y - bounds.y - bounds.height / 2.0, - ), - content: Box::new(pane), - }), - }; - - panes.push(clip); - - panes - } else { - panes - }; - - ( - Primitive::Group { primitives }, - if dragging.is_some() { - mouse::Interaction::Grabbing - } else if let Some(axis) = resizing { - match axis { - Axis::Horizontal => mouse::Interaction::ResizingVertically, - Axis::Vertical => mouse::Interaction::ResizingHorizontally, - } - } else { - mouse_interaction - }, - ) - } -} diff --git a/glow/src/renderer/widget/progress_bar.rs b/glow/src/renderer/widget/progress_bar.rs deleted file mode 100644 index 2baeeb14..00000000 --- a/glow/src/renderer/widget/progress_bar.rs +++ /dev/null @@ -1,54 +0,0 @@ -use crate::{progress_bar::StyleSheet, Primitive, Renderer}; -use iced_native::{mouse, progress_bar, Color, Rectangle}; - -impl progress_bar::Renderer for Renderer { - type Style = Box<dyn StyleSheet>; - - const DEFAULT_HEIGHT: u16 = 30; - - fn draw( - &self, - bounds: Rectangle, - range: std::ops::RangeInclusive<f32>, - value: f32, - style_sheet: &Self::Style, - ) -> Self::Output { - let style = style_sheet.style(); - - let (range_start, range_end) = range.into_inner(); - let active_progress_width = bounds.width - * ((value - range_start) / (range_end - range_start).max(1.0)); - - let background = Primitive::Group { - primitives: vec![Primitive::Quad { - bounds: Rectangle { ..bounds }, - background: style.background, - border_radius: style.border_radius, - border_width: 0, - border_color: Color::TRANSPARENT, - }], - }; - - ( - if active_progress_width > 0.0 { - let bar = Primitive::Quad { - bounds: Rectangle { - width: active_progress_width, - ..bounds - }, - background: style.bar, - border_radius: style.border_radius, - border_width: 0, - border_color: Color::TRANSPARENT, - }; - - Primitive::Group { - primitives: vec![background, bar], - } - } else { - background - }, - mouse::Interaction::default(), - ) - } -} diff --git a/glow/src/renderer/widget/radio.rs b/glow/src/renderer/widget/radio.rs deleted file mode 100644 index cee0deb6..00000000 --- a/glow/src/renderer/widget/radio.rs +++ /dev/null @@ -1,63 +0,0 @@ -use crate::{radio::StyleSheet, Primitive, Renderer}; -use iced_native::{mouse, radio, Background, Color, Rectangle}; - -const SIZE: f32 = 28.0; -const DOT_SIZE: f32 = SIZE / 2.0; - -impl radio::Renderer for Renderer { - type Style = Box<dyn StyleSheet>; - - const DEFAULT_SIZE: u16 = SIZE as u16; - const DEFAULT_SPACING: u16 = 15; - - fn draw( - &mut self, - bounds: Rectangle, - is_selected: bool, - is_mouse_over: bool, - (label, _): Self::Output, - style_sheet: &Self::Style, - ) -> Self::Output { - let style = if is_mouse_over { - style_sheet.hovered() - } else { - style_sheet.active() - }; - - let radio = Primitive::Quad { - bounds, - background: style.background, - border_radius: (SIZE / 2.0) as u16, - border_width: style.border_width, - border_color: style.border_color, - }; - - ( - Primitive::Group { - primitives: if is_selected { - let radio_circle = Primitive::Quad { - bounds: Rectangle { - x: bounds.x + DOT_SIZE / 2.0, - y: bounds.y + DOT_SIZE / 2.0, - width: bounds.width - DOT_SIZE, - height: bounds.height - DOT_SIZE, - }, - background: Background::Color(style.dot_color), - border_radius: (DOT_SIZE / 2.0) as u16, - border_width: 0, - border_color: Color::TRANSPARENT, - }; - - vec![radio, radio_circle, label] - } else { - vec![radio, label] - }, - }, - if is_mouse_over { - mouse::Interaction::Pointer - } else { - mouse::Interaction::default() - }, - ) - } -} diff --git a/glow/src/renderer/widget/row.rs b/glow/src/renderer/widget/row.rs deleted file mode 100644 index d0b7ef09..00000000 --- a/glow/src/renderer/widget/row.rs +++ /dev/null @@ -1,34 +0,0 @@ -use crate::{Primitive, Renderer}; -use iced_native::{mouse, row, Element, Layout, Point}; - -impl row::Renderer for Renderer { - fn draw<Message>( - &mut self, - defaults: &Self::Defaults, - children: &[Element<'_, Message, Self>], - layout: Layout<'_>, - cursor_position: Point, - ) -> Self::Output { - let mut mouse_interaction = mouse::Interaction::default(); - - ( - Primitive::Group { - primitives: children - .iter() - .zip(layout.children()) - .map(|(child, layout)| { - let (primitive, new_mouse_interaction) = - child.draw(self, defaults, layout, cursor_position); - - if new_mouse_interaction > mouse_interaction { - mouse_interaction = new_mouse_interaction; - } - - primitive - }) - .collect(), - }, - mouse_interaction, - ) - } -} diff --git a/glow/src/renderer/widget/scrollable.rs b/glow/src/renderer/widget/scrollable.rs deleted file mode 100644 index 8a400b82..00000000 --- a/glow/src/renderer/widget/scrollable.rs +++ /dev/null @@ -1,125 +0,0 @@ -use crate::{Primitive, Renderer}; -use iced_native::{mouse, scrollable, Background, Color, Rectangle, Vector}; - -const SCROLLBAR_WIDTH: u16 = 10; -const SCROLLBAR_MARGIN: u16 = 2; - -impl scrollable::Renderer for Renderer { - type Style = Box<dyn iced_style::scrollable::StyleSheet>; - - fn scrollbar( - &self, - bounds: Rectangle, - content_bounds: Rectangle, - offset: u32, - ) -> Option<scrollable::Scrollbar> { - if content_bounds.height > bounds.height { - let scrollbar_bounds = Rectangle { - x: bounds.x + bounds.width - - f32::from(SCROLLBAR_WIDTH + 2 * SCROLLBAR_MARGIN), - y: bounds.y, - width: f32::from(SCROLLBAR_WIDTH + 2 * SCROLLBAR_MARGIN), - height: bounds.height, - }; - - let ratio = bounds.height / content_bounds.height; - let scrollbar_height = bounds.height * ratio; - let y_offset = offset as f32 * ratio; - - let scroller_bounds = Rectangle { - x: scrollbar_bounds.x + f32::from(SCROLLBAR_MARGIN), - y: scrollbar_bounds.y + y_offset, - width: scrollbar_bounds.width - f32::from(2 * SCROLLBAR_MARGIN), - height: scrollbar_height, - }; - - Some(scrollable::Scrollbar { - bounds: scrollbar_bounds, - scroller: scrollable::Scroller { - bounds: scroller_bounds, - }, - }) - } else { - None - } - } - - fn draw( - &mut self, - state: &scrollable::State, - bounds: Rectangle, - _content_bounds: Rectangle, - is_mouse_over: bool, - is_mouse_over_scrollbar: bool, - scrollbar: Option<scrollable::Scrollbar>, - offset: u32, - style_sheet: &Self::Style, - (content, mouse_interaction): Self::Output, - ) -> Self::Output { - ( - if let Some(scrollbar) = scrollbar { - let clip = Primitive::Clip { - bounds, - offset: Vector::new(0, offset), - content: Box::new(content), - }; - - let style = if state.is_scroller_grabbed() { - style_sheet.dragging() - } else if is_mouse_over_scrollbar { - style_sheet.hovered() - } else { - style_sheet.active() - }; - - let is_scrollbar_visible = - style.background.is_some() || style.border_width > 0; - - let scroller = if is_mouse_over - || state.is_scroller_grabbed() - || is_scrollbar_visible - { - Primitive::Quad { - bounds: scrollbar.scroller.bounds, - background: Background::Color(style.scroller.color), - border_radius: style.scroller.border_radius, - border_width: style.scroller.border_width, - border_color: style.scroller.border_color, - } - } else { - Primitive::None - }; - - let scrollbar = if is_scrollbar_visible { - Primitive::Quad { - bounds: Rectangle { - x: scrollbar.bounds.x + f32::from(SCROLLBAR_MARGIN), - width: scrollbar.bounds.width - - f32::from(2 * SCROLLBAR_MARGIN), - ..scrollbar.bounds - }, - background: style - .background - .unwrap_or(Background::Color(Color::TRANSPARENT)), - border_radius: style.border_radius, - border_width: style.border_width, - border_color: style.border_color, - } - } else { - Primitive::None - }; - - Primitive::Group { - primitives: vec![clip, scrollbar, scroller], - } - } else { - content - }, - if is_mouse_over_scrollbar || state.is_scroller_grabbed() { - mouse::Interaction::Idle - } else { - mouse_interaction - }, - ) - } -} diff --git a/glow/src/renderer/widget/slider.rs b/glow/src/renderer/widget/slider.rs deleted file mode 100644 index 220feace..00000000 --- a/glow/src/renderer/widget/slider.rs +++ /dev/null @@ -1,106 +0,0 @@ -use crate::{ - slider::{HandleShape, StyleSheet}, - Primitive, Renderer, -}; -use iced_native::{mouse, slider, Background, Color, Point, Rectangle}; - -const HANDLE_HEIGHT: f32 = 22.0; - -impl slider::Renderer for Renderer { - type Style = Box<dyn StyleSheet>; - - fn height(&self) -> u32 { - 30 - } - - fn draw( - &mut self, - bounds: Rectangle, - cursor_position: Point, - range: std::ops::RangeInclusive<f32>, - value: f32, - is_dragging: bool, - style_sheet: &Self::Style, - ) -> Self::Output { - let is_mouse_over = bounds.contains(cursor_position); - - let style = if is_dragging { - style_sheet.dragging() - } else if is_mouse_over { - style_sheet.hovered() - } else { - style_sheet.active() - }; - - let rail_y = bounds.y + (bounds.height / 2.0).round(); - - let (rail_top, rail_bottom) = ( - Primitive::Quad { - bounds: Rectangle { - x: bounds.x, - y: rail_y, - width: bounds.width, - height: 2.0, - }, - background: Background::Color(style.rail_colors.0), - border_radius: 0, - border_width: 0, - border_color: Color::TRANSPARENT, - }, - Primitive::Quad { - bounds: Rectangle { - x: bounds.x, - y: rail_y + 2.0, - width: bounds.width, - height: 2.0, - }, - background: Background::Color(style.rail_colors.1), - border_radius: 0, - border_width: 0, - border_color: Color::TRANSPARENT, - }, - ); - - let (range_start, range_end) = range.into_inner(); - - let (handle_width, handle_height, handle_border_radius) = - match style.handle.shape { - HandleShape::Circle { radius } => { - (f32::from(radius * 2), f32::from(radius * 2), radius) - } - HandleShape::Rectangle { - width, - border_radius, - } => (f32::from(width), HANDLE_HEIGHT, border_radius), - }; - - let handle_offset = (bounds.width - handle_width) - * ((value - range_start) / (range_end - range_start).max(1.0)); - - let handle = Primitive::Quad { - bounds: Rectangle { - x: bounds.x + handle_offset.round(), - y: rail_y - handle_height / 2.0, - width: handle_width, - height: handle_height, - }, - background: Background::Color(style.handle.color), - border_radius: handle_border_radius, - border_width: style.handle.border_width, - border_color: style.handle.border_color, - }; - - ( - Primitive::Group { - primitives: vec![rail_top, rail_bottom, handle], - }, - if is_dragging { - mouse::Interaction::Grabbing - } else if is_mouse_over { - mouse::Interaction::Grab - } else { - mouse::Interaction::default() - }, - ) - } -} diff --git a/glow/src/renderer/widget/space.rs b/glow/src/renderer/widget/space.rs deleted file mode 100644 index 225f7e6c..00000000 --- a/glow/src/renderer/widget/space.rs +++ /dev/null @@ -1,8 +0,0 @@ -use crate::{Primitive, Renderer}; -use iced_native::{mouse, space, Rectangle}; - -impl space::Renderer for Renderer { - fn draw(&mut self, _bounds: Rectangle) -> Self::Output { - (Primitive::None, mouse::Interaction::default()) - } -} diff --git a/glow/src/renderer/widget/svg.rs b/glow/src/renderer/widget/svg.rs deleted file mode 100644 index f6d6d0ba..00000000 --- a/glow/src/renderer/widget/svg.rs +++ /dev/null @@ -1,22 +0,0 @@ -use crate::{Primitive, Renderer}; -use iced_native::{mouse, svg, Layout}; - -impl svg::Renderer for Renderer { - fn dimensions(&self, handle: &svg::Handle) -> (u32, u32) { - self.image_pipeline.viewport_dimensions(handle) - } - - fn draw( - &mut self, - handle: svg::Handle, - layout: Layout<'_>, - ) -> Self::Output { - ( - Primitive::Svg { - handle, - bounds: layout.bounds(), - }, - mouse::Interaction::default(), - ) - } -} diff --git a/glow/src/renderer/widget/text.rs b/glow/src/renderer/widget/text.rs deleted file mode 100644 index 4605ed06..00000000 --- a/glow/src/renderer/widget/text.rs +++ /dev/null @@ -1,61 +0,0 @@ -use crate::{Primitive, Renderer}; -use iced_native::{ - mouse, text, Color, Font, HorizontalAlignment, Rectangle, Size, - VerticalAlignment, -}; - -use std::f32; - -impl text::Renderer for Renderer { - type Font = Font; - - const DEFAULT_SIZE: u16 = 20; - - fn measure( - &self, - content: &str, - size: u16, - font: Font, - bounds: Size, - ) -> (f32, f32) { - self.text_pipeline - .measure(content, f32::from(size), font, bounds) - } - - fn draw( - &mut self, - defaults: &Self::Defaults, - bounds: Rectangle, - content: &str, - size: u16, - font: Font, - color: Option<Color>, - horizontal_alignment: HorizontalAlignment, - vertical_alignment: VerticalAlignment, - ) -> Self::Output { - let x = match horizontal_alignment { - iced_native::HorizontalAlignment::Left => bounds.x, - iced_native::HorizontalAlignment::Center => bounds.center_x(), - iced_native::HorizontalAlignment::Right => bounds.x + bounds.width, - }; - - let y = match vertical_alignment { - iced_native::VerticalAlignment::Top => bounds.y, - iced_native::VerticalAlignment::Center => bounds.center_y(), - iced_native::VerticalAlignment::Bottom => bounds.y + bounds.height, - }; - - ( - Primitive::Text { - content: content.to_string(), - size: f32::from(size), - bounds: Rectangle { x, y, ..bounds }, - color: color.unwrap_or(defaults.text.color), - font, - horizontal_alignment, - vertical_alignment, - }, - mouse::Interaction::default(), - ) - } -} diff --git a/glow/src/renderer/widget/text_input.rs b/glow/src/renderer/widget/text_input.rs deleted file mode 100644 index 57be6692..00000000 --- a/glow/src/renderer/widget/text_input.rs +++ /dev/null @@ -1,261 +0,0 @@ -use crate::{text_input::StyleSheet, Primitive, Renderer}; - -use iced_native::{ - mouse, - text_input::{self, cursor}, - Background, Color, Font, HorizontalAlignment, Point, Rectangle, Size, - Vector, VerticalAlignment, -}; -use std::f32; - -impl text_input::Renderer for Renderer { - type Style = Box<dyn StyleSheet>; - - fn default_size(&self) -> u16 { - // TODO: Make this configurable - 20 - } - - fn measure_value(&self, value: &str, size: u16, font: Font) -> f32 { - let (mut width, _) = self.text_pipeline.measure( - value, - f32::from(size), - font, - Size::INFINITY, - ); - - let spaces_around = value.len() - value.trim().len(); - - if spaces_around > 0 { - let space_width = self.text_pipeline.space_width(size as f32); - width += spaces_around as f32 * space_width; - } - - width - } - - fn offset( - &self, - text_bounds: Rectangle, - font: Font, - size: u16, - value: &text_input::Value, - state: &text_input::State, - ) -> f32 { - if state.is_focused() { - let cursor = state.cursor(); - - let focus_position = match cursor.state(value) { - cursor::State::Index(i) => i, - cursor::State::Selection { end, .. } => end, - }; - - let (_, offset) = measure_cursor_and_scroll_offset( - self, - text_bounds, - value, - size, - focus_position, - font, - ); - - offset - } else { - 0.0 - } - } - - fn draw( - &mut self, - bounds: Rectangle, - text_bounds: Rectangle, - cursor_position: Point, - font: Font, - size: u16, - placeholder: &str, - value: &text_input::Value, - state: &text_input::State, - style_sheet: &Self::Style, - ) -> Self::Output { - let is_mouse_over = bounds.contains(cursor_position); - - let style = if state.is_focused() { - style_sheet.focused() - } else if is_mouse_over { - style_sheet.hovered() - } else { - style_sheet.active() - }; - - let input = Primitive::Quad { - bounds, - background: style.background, - border_radius: style.border_radius, - border_width: style.border_width, - border_color: style.border_color, - }; - - let text = value.to_string(); - - let text_value = Primitive::Text { - content: if text.is_empty() { - placeholder.to_string() - } else { - text.clone() - }, - color: if text.is_empty() { - style_sheet.placeholder_color() - } else { - style_sheet.value_color() - }, - font, - bounds: Rectangle { - y: text_bounds.center_y(), - width: f32::INFINITY, - ..text_bounds - }, - size: f32::from(size), - horizontal_alignment: HorizontalAlignment::Left, - vertical_alignment: VerticalAlignment::Center, - }; - - let (contents_primitive, offset) = if state.is_focused() { - let cursor = state.cursor(); - - let (cursor_primitive, offset) = match cursor.state(value) { - cursor::State::Index(position) => { - let (text_value_width, offset) = - measure_cursor_and_scroll_offset( - self, - text_bounds, - value, - size, - position, - font, - ); - - ( - Primitive::Quad { - bounds: Rectangle { - x: text_bounds.x + text_value_width, - y: text_bounds.y, - width: 1.0, - height: text_bounds.height, - }, - background: Background::Color( - style_sheet.value_color(), - ), - border_radius: 0, - border_width: 0, - border_color: Color::TRANSPARENT, - }, - offset, - ) - } - cursor::State::Selection { start, end } => { - let left = start.min(end); - let right = end.max(start); - - let (left_position, left_offset) = - measure_cursor_and_scroll_offset( - self, - text_bounds, - value, - size, - left, - font, - ); - - let (right_position, right_offset) = - measure_cursor_and_scroll_offset( - self, - text_bounds, - value, - size, - right, - font, - ); - - let width = right_position - left_position; - - ( - Primitive::Quad { - bounds: Rectangle { - x: text_bounds.x + left_position, - y: text_bounds.y, - width, - height: text_bounds.height, - }, - background: Background::Color( - style_sheet.selection_color(), - ), - border_radius: 0, - border_width: 0, - border_color: Color::TRANSPARENT, - }, - if end == right { - right_offset - } else { - left_offset - }, - ) - } - }; - - ( - Primitive::Group { - primitives: vec![cursor_primitive, text_value], - }, - Vector::new(offset as u32, 0), - ) - } else { - (text_value, Vector::new(0, 0)) - }; - - let text_width = self.measure_value( - if text.is_empty() { placeholder } else { &text }, - size, - font, - ); - - let contents = if text_width > text_bounds.width { - Primitive::Clip { - bounds: text_bounds, - offset, - content: Box::new(contents_primitive), - } - } else { - contents_primitive - }; - - ( - Primitive::Group { - primitives: vec![input, contents], - }, - if is_mouse_over { - mouse::Interaction::Text - } else { - mouse::Interaction::default() - }, - ) - } -} - -fn measure_cursor_and_scroll_offset( - renderer: &Renderer, - text_bounds: Rectangle, - value: &text_input::Value, - size: u16, - cursor_index: usize, - font: Font, -) -> (f32, f32) { - use iced_native::text_input::Renderer; - - let text_before_cursor = value.until(cursor_index).to_string(); - - let text_value_width = - renderer.measure_value(&text_before_cursor, size, font); - let offset = ((text_value_width + 5.0) - text_bounds.width).max(0.0); - - (text_value_width, offset) -} diff --git a/glow/src/text.rs b/glow/src/text.rs index bda619fc..159c80a6 100644 --- a/glow/src/text.rs +++ b/glow/src/text.rs @@ -130,7 +130,7 @@ impl Pipeline { .advance_width } - pub fn clear_measurement_cache(&mut self) { + pub fn trim_measurement_cache(&mut self) { // TODO: We should probably use a `GlyphCalculator` for this. However, // it uses a lifetimed `GlyphCalculatorGuard` with side-effects on drop. // This makes stuff quite inconvenient. A manual method for trimming the diff --git a/glow/src/triangle.rs b/glow/src/triangle.rs index f71022d0..8b21c0a8 100644 --- a/glow/src/triangle.rs +++ b/glow/src/triangle.rs @@ -3,6 +3,8 @@ use crate::{settings, Transformation}; use iced_native::{Rectangle, Vector}; use std::mem; +pub use iced_graphics::triangle::Mesh2D; + const UNIFORM_BUFFER_SIZE: usize = 100; const VERTEX_BUFFER_SIZE: usize = 10_000; const INDEX_BUFFER_SIZE: usize = 10_000; @@ -59,26 +61,3 @@ impl From<Transformation> for Uniforms { } } } - -/// A two-dimensional vertex with some color in __linear__ RGBA. -#[repr(C)] -#[derive(Copy, Clone, Debug)] -pub struct Vertex2D { - /// The vertex position - pub position: [f32; 2], - /// The vertex color in __linear__ RGBA. - pub color: [f32; 4], -} - -/// A set of [`Vertex2D`] and indices representing a list of triangles. -/// -/// [`Vertex2D`]: struct.Vertex2D.html -#[derive(Clone, Debug)] -pub struct Mesh2D { - /// The vertices of the mesh - pub vertices: Vec<Vertex2D>, - /// The list of vertex indices that defines the triangles of the mesh. - /// - /// Therefore, this list should always have a length that is a multiple of 3. - pub indices: Vec<u32>, -} diff --git a/glow/src/widget/button.rs b/glow/src/widget/button.rs index b738c55e..fee7a7f8 100644 --- a/glow/src/widget/button.rs +++ b/glow/src/widget/button.rs @@ -6,8 +6,8 @@ //! [`State`]: struct.State.html use crate::Renderer; +pub use iced_graphics::button::{Style, StyleSheet}; pub use iced_native::button::State; -pub use iced_style::button::{Style, StyleSheet}; /// A widget that produces a message when clicked. /// diff --git a/glow/src/widget/checkbox.rs b/glow/src/widget/checkbox.rs index da0d7a84..d27d77cc 100644 --- a/glow/src/widget/checkbox.rs +++ b/glow/src/widget/checkbox.rs @@ -1,7 +1,7 @@ //! Show toggle controls using checkboxes. use crate::Renderer; -pub use iced_style::checkbox::{Style, StyleSheet}; +pub use iced_graphics::checkbox::{Style, StyleSheet}; /// A box that can be checked. /// diff --git a/glow/src/widget/container.rs b/glow/src/widget/container.rs index 9a93a246..bc26cef2 100644 --- a/glow/src/widget/container.rs +++ b/glow/src/widget/container.rs @@ -1,7 +1,7 @@ //! Decorate content and apply alignment. use crate::Renderer; -pub use iced_style::container::{Style, StyleSheet}; +pub use iced_graphics::container::{Style, StyleSheet}; /// An element decorating some content. /// diff --git a/glow/src/widget/progress_bar.rs b/glow/src/widget/progress_bar.rs index 34450b5e..5782103c 100644 --- a/glow/src/widget/progress_bar.rs +++ b/glow/src/widget/progress_bar.rs @@ -6,7 +6,7 @@ //! [`State`]: struct.State.html use crate::Renderer; -pub use iced_style::progress_bar::{Style, StyleSheet}; +pub use iced_graphics::progress_bar::{Style, StyleSheet}; /// A bar that displays progress. /// diff --git a/glow/src/widget/radio.rs b/glow/src/widget/radio.rs index 6e5cf042..0b843d1f 100644 --- a/glow/src/widget/radio.rs +++ b/glow/src/widget/radio.rs @@ -1,7 +1,7 @@ //! Create choices using radio buttons. use crate::Renderer; -pub use iced_style::radio::{Style, StyleSheet}; +pub use iced_graphics::radio::{Style, StyleSheet}; /// A circular button representing a choice. /// diff --git a/glow/src/widget/scrollable.rs b/glow/src/widget/scrollable.rs index 1d236105..fabb4318 100644 --- a/glow/src/widget/scrollable.rs +++ b/glow/src/widget/scrollable.rs @@ -1,8 +1,8 @@ //! Navigate an endless amount of content with a scrollbar. use crate::Renderer; +pub use iced_graphics::scrollable::{Scrollbar, Scroller, StyleSheet}; pub use iced_native::scrollable::State; -pub use iced_style::scrollable::{Scrollbar, Scroller, StyleSheet}; /// A widget that can vertically display an infinite amount of content /// with a scrollbar. diff --git a/glow/src/widget/slider.rs b/glow/src/widget/slider.rs index 4e47978f..cf036829 100644 --- a/glow/src/widget/slider.rs +++ b/glow/src/widget/slider.rs @@ -6,8 +6,8 @@ //! [`State`]: struct.State.html use crate::Renderer; +pub use iced_graphics::slider::{Handle, HandleShape, Style, StyleSheet}; pub use iced_native::slider::State; -pub use iced_style::slider::{Handle, HandleShape, Style, StyleSheet}; /// An horizontal bar and a handle that selects a single value from a range of /// values. diff --git a/glow/src/widget/text_input.rs b/glow/src/widget/text_input.rs index 260fe3a6..1da3fbe6 100644 --- a/glow/src/widget/text_input.rs +++ b/glow/src/widget/text_input.rs @@ -6,8 +6,8 @@ //! [`State`]: struct.State.html use crate::Renderer; +pub use iced_graphics::text_input::{Style, StyleSheet}; pub use iced_native::text_input::State; -pub use iced_style::text_input::{Style, StyleSheet}; /// A field that can be filled with text. /// diff --git a/glow/src/window.rs b/glow/src/window.rs index b7adad82..a8edb016 100644 --- a/glow/src/window.rs +++ b/glow/src/window.rs @@ -1,6 +1,4 @@ //! Display rendering results on windows. mod backend; -mod swap_chain; pub use backend::Backend; -pub use swap_chain::SwapChain; diff --git a/glow/src/window/backend.rs b/glow/src/window/backend.rs index 05f988f7..34245f35 100644 --- a/glow/src/window/backend.rs +++ b/glow/src/window/backend.rs @@ -53,7 +53,7 @@ impl iced_native::window::Backend for Backend { .make_context_current(&self.gl_context) .expect("Make context current"); - Renderer::new(self.gl.as_ref().unwrap(), settings) + Renderer::new(crate::Backend::new(self.gl.as_ref().unwrap(), settings)) } fn create_surface<W: HasRawWindowHandle>( @@ -151,8 +151,13 @@ impl iced_native::window::Backend for Backend { gl.clear(glow::COLOR_BUFFER_BIT); } - let mouse = - renderer.draw(gl, swap_chain, output, scale_factor, overlay); + let mouse = renderer.backend_mut().draw( + gl, + swap_chain, + output, + scale_factor, + overlay, + ); { let mut surface = self diff --git a/glow/src/window/swap_chain.rs b/glow/src/window/swap_chain.rs deleted file mode 100644 index 41d19968..00000000 --- a/glow/src/window/swap_chain.rs +++ /dev/null @@ -1,5 +0,0 @@ -/// The rendering target of a window. -/// -/// It represents a series of virtual framebuffers with a scale factor. -#[derive(Debug)] -pub struct SwapChain; |