diff options
Diffstat (limited to '')
| -rw-r--r-- | graphics/src/layer.rs | 40 | ||||
| -rw-r--r-- | graphics/src/widget.rs | 3 | ||||
| -rw-r--r-- | graphics/src/widget/tooltip.rs | 145 | 
3 files changed, 176 insertions, 12 deletions
diff --git a/graphics/src/layer.rs b/graphics/src/layer.rs index ab40b114..7dce1d4c 100644 --- a/graphics/src/layer.rs +++ b/graphics/src/layer.rs @@ -82,7 +82,12 @@ impl<'a> Layer<'a> {          let mut layers = vec![first_layer]; -        Self::process_primitive(&mut layers, Vector::new(0.0, 0.0), primitive); +        Self::process_primitive( +            &mut layers, +            Vector::new(0.0, 0.0), +            primitive, +            0, +        );          layers      } @@ -91,13 +96,19 @@ impl<'a> Layer<'a> {          layers: &mut Vec<Self>,          translation: Vector,          primitive: &'a Primitive, +        current_layer: usize,      ) {          match primitive {              Primitive::None => {}              Primitive::Group { primitives } => {                  // TODO: Inspect a bit and regroup (?)                  for primitive in primitives { -                    Self::process_primitive(layers, translation, primitive) +                    Self::process_primitive( +                        layers, +                        translation, +                        primitive, +                        current_layer, +                    )                  }              }              Primitive::Text { @@ -109,7 +120,7 @@ impl<'a> Layer<'a> {                  horizontal_alignment,                  vertical_alignment,              } => { -                let layer = layers.last_mut().unwrap(); +                let layer = &mut layers[current_layer];                  layer.text.push(Text {                      content, @@ -128,7 +139,7 @@ impl<'a> Layer<'a> {                  border_width,                  border_color,              } => { -                let layer = layers.last_mut().unwrap(); +                let layer = &mut layers[current_layer];                  // TODO: Move some of these computations to the GPU (?)                  layer.quads.push(Quad { @@ -146,7 +157,7 @@ impl<'a> Layer<'a> {                  });              }              Primitive::Mesh2D { buffers, size } => { -                let layer = layers.last_mut().unwrap(); +                let layer = &mut layers[current_layer];                  let bounds = Rectangle::new(                      Point::new(translation.x, translation.y), @@ -167,7 +178,7 @@ impl<'a> Layer<'a> {                  offset,                  content,              } => { -                let layer = layers.last_mut().unwrap(); +                let layer = &mut layers[current_layer];                  let translated_bounds = *bounds + translation;                  // Only draw visible content @@ -175,16 +186,15 @@ impl<'a> Layer<'a> {                      layer.bounds.intersection(&translated_bounds)                  {                      let clip_layer = Layer::new(clip_bounds); -                    let new_layer = Layer::new(layer.bounds); -                      layers.push(clip_layer); +                      Self::process_primitive(                          layers,                          translation                              - Vector::new(offset.x as f32, offset.y as f32),                          content, +                        layers.len() - 1,                      ); -                    layers.push(new_layer);                  }              }              Primitive::Translate { @@ -195,13 +205,19 @@ impl<'a> Layer<'a> {                      layers,                      translation + *new_translation,                      &content, +                    current_layer,                  );              }              Primitive::Cached { cache } => { -                Self::process_primitive(layers, translation, &cache); +                Self::process_primitive( +                    layers, +                    translation, +                    &cache, +                    current_layer, +                );              }              Primitive::Image { handle, bounds } => { -                let layer = layers.last_mut().unwrap(); +                let layer = &mut layers[current_layer];                  layer.images.push(Image::Raster {                      handle: handle.clone(), @@ -209,7 +225,7 @@ impl<'a> Layer<'a> {                  });              }              Primitive::Svg { handle, bounds } => { -                let layer = layers.last_mut().unwrap(); +                let layer = &mut layers[current_layer];                  layer.images.push(Image::Vector {                      handle: handle.clone(), diff --git a/graphics/src/widget.rs b/graphics/src/widget.rs index 159ca91b..190ea9c0 100644 --- a/graphics/src/widget.rs +++ b/graphics/src/widget.rs @@ -20,6 +20,7 @@ pub mod scrollable;  pub mod slider;  pub mod svg;  pub mod text_input; +pub mod tooltip;  mod column;  mod row; @@ -48,6 +49,8 @@ pub use scrollable::Scrollable;  pub use slider::Slider;  #[doc(no_inline)]  pub use text_input::TextInput; +#[doc(no_inline)] +pub use tooltip::Tooltip;  pub use column::Column;  pub use image::Image; diff --git a/graphics/src/widget/tooltip.rs b/graphics/src/widget/tooltip.rs new file mode 100644 index 00000000..51b465a5 --- /dev/null +++ b/graphics/src/widget/tooltip.rs @@ -0,0 +1,145 @@ +//! Decorate content and apply alignment. +use crate::backend::{self, Backend}; +use crate::defaults::{self, Defaults}; +use crate::{Primitive, Renderer, Vector}; + +use iced_native::container; +use iced_native::layout::{self, Layout}; +use iced_native::{Element, Point, Rectangle, Size, Text}; + +/// An element decorating some content. +/// +/// This is an alias of an `iced_native` tooltip with a default +/// `Renderer`. +pub type Tooltip<'a, Message, Backend> = +    iced_native::Tooltip<'a, Message, Renderer<Backend>>; + +pub use iced_native::tooltip::Position; + +impl<B> iced_native::tooltip::Renderer for Renderer<B> +where +    B: Backend + backend::Text, +{ +    const DEFAULT_PADDING: u16 = 5; + +    fn draw<Message>( +        &mut self, +        defaults: &Defaults, +        cursor_position: Point, +        content_layout: Layout<'_>, +        viewport: &Rectangle, +        content: &Element<'_, Message, Self>, +        tooltip: &Text<Self>, +        position: Position, +        style_sheet: &<Self as container::Renderer>::Style, +        gap: u16, +        padding: u16, +    ) -> Self::Output { +        let (content, mouse_interaction) = content.draw( +            self, +            &defaults, +            content_layout, +            cursor_position, +            viewport, +        ); + +        let bounds = content_layout.bounds(); + +        if bounds.contains(cursor_position) { +            use iced_native::Widget; + +            let gap = f32::from(gap); +            let padding = f32::from(padding); +            let style = style_sheet.style(); + +            let defaults = Defaults { +                text: defaults::Text { +                    color: style.text_color.unwrap_or(defaults.text.color), +                }, +            }; + +            let tooltip_layout = Widget::<(), Self>::layout( +                tooltip, +                self, +                &layout::Limits::new(Size::ZERO, viewport.size()) +                    .pad(f32::from(padding)), +            ); + +            let tooltip_bounds = tooltip_layout.bounds(); + +            let x_center = +                bounds.x + (bounds.width - tooltip_bounds.width) / 2.0; + +            let y_center = +                bounds.y + (bounds.height - tooltip_bounds.height) / 2.0; + +            let offset = match position { +                Position::Top => Vector::new( +                    x_center, +                    bounds.y - tooltip_bounds.height - gap - padding, +                ), +                Position::Bottom => Vector::new( +                    x_center, +                    bounds.y + bounds.height + gap + padding, +                ), +                Position::Left => Vector::new( +                    bounds.x - tooltip_bounds.width - gap - padding, +                    y_center, +                ), +                Position::Right => Vector::new( +                    bounds.x + bounds.width + gap + padding, +                    y_center, +                ), +                Position::FollowCursor => Vector::new( +                    cursor_position.x, +                    cursor_position.y - tooltip_bounds.height, +                ), +            }; + +            let (tooltip, _) = Widget::<(), Self>::draw( +                tooltip, +                self, +                &defaults, +                Layout::with_offset(offset, &tooltip_layout), +                cursor_position, +                viewport, +            ); + +            let tooltip_bounds = Rectangle { +                x: offset.x - padding, +                y: offset.y - padding, +                width: tooltip_bounds.width + padding * 2.0, +                height: tooltip_bounds.height + padding * 2.0, +            }; + +            ( +                Primitive::Group { +                    primitives: vec![ +                        content, +                        Primitive::Clip { +                            bounds: *viewport, +                            offset: Vector::new(0, 0), +                            content: Box::new( +                                if let Some(background) = +                                    crate::container::background( +                                        tooltip_bounds, +                                        &style, +                                    ) +                                { +                                    Primitive::Group { +                                        primitives: vec![background, tooltip], +                                    } +                                } else { +                                    tooltip +                                }, +                            ), +                        }, +                    ], +                }, +                mouse_interaction, +            ) +        } else { +            (content, mouse_interaction) +        } +    } +}  | 
