Move widgets from core to native and web
Also made fields private and improved `Renderer` traits.
This commit is contained in:
parent
d3553adf27
commit
65eb218d3d
59 changed files with 2455 additions and 1942 deletions
|
|
@ -1,4 +1,7 @@
|
|||
use iced_native::{text, Background, Color, Font, Rectangle, Vector};
|
||||
use iced_native::{
|
||||
Background, Color, Font, HorizontalAlignment, Rectangle, Vector,
|
||||
VerticalAlignment,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Primitive {
|
||||
|
|
@ -12,8 +15,8 @@ pub enum Primitive {
|
|||
color: Color,
|
||||
size: f32,
|
||||
font: Font,
|
||||
horizontal_alignment: text::HorizontalAlignment,
|
||||
vertical_alignment: text::VerticalAlignment,
|
||||
horizontal_alignment: HorizontalAlignment,
|
||||
vertical_alignment: VerticalAlignment,
|
||||
},
|
||||
Quad {
|
||||
bounds: Rectangle,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{quad, text, Image, Primitive, Quad, Transformation};
|
||||
use iced_native::{
|
||||
renderer::Debugger, renderer::Windowed, Background, Color, Layout,
|
||||
MouseCursor, Point, Rectangle, Vector, Widget,
|
||||
renderer::{Debugger, Windowed},
|
||||
Background, Color, Layout, MouseCursor, Point, Rectangle, Vector, Widget,
|
||||
};
|
||||
|
||||
use wgpu::{
|
||||
|
|
@ -152,21 +152,21 @@ impl Renderer {
|
|||
vertical_alignment,
|
||||
} => {
|
||||
let x = match horizontal_alignment {
|
||||
iced_native::text::HorizontalAlignment::Left => bounds.x,
|
||||
iced_native::text::HorizontalAlignment::Center => {
|
||||
iced_native::HorizontalAlignment::Left => bounds.x,
|
||||
iced_native::HorizontalAlignment::Center => {
|
||||
bounds.x + bounds.width / 2.0
|
||||
}
|
||||
iced_native::text::HorizontalAlignment::Right => {
|
||||
iced_native::HorizontalAlignment::Right => {
|
||||
bounds.x + bounds.width
|
||||
}
|
||||
};
|
||||
|
||||
let y = match vertical_alignment {
|
||||
iced_native::text::VerticalAlignment::Top => bounds.y,
|
||||
iced_native::text::VerticalAlignment::Center => {
|
||||
iced_native::VerticalAlignment::Top => bounds.y,
|
||||
iced_native::VerticalAlignment::Center => {
|
||||
bounds.y + bounds.height / 2.0
|
||||
}
|
||||
iced_native::text::VerticalAlignment::Bottom => {
|
||||
iced_native::VerticalAlignment::Bottom => {
|
||||
bounds.y + bounds.height
|
||||
}
|
||||
};
|
||||
|
|
@ -183,24 +183,24 @@ impl Renderer {
|
|||
font_id: self.text_pipeline.find_font(*font),
|
||||
layout: wgpu_glyph::Layout::default()
|
||||
.h_align(match horizontal_alignment {
|
||||
iced_native::text::HorizontalAlignment::Left => {
|
||||
iced_native::HorizontalAlignment::Left => {
|
||||
wgpu_glyph::HorizontalAlign::Left
|
||||
}
|
||||
iced_native::text::HorizontalAlignment::Center => {
|
||||
iced_native::HorizontalAlignment::Center => {
|
||||
wgpu_glyph::HorizontalAlign::Center
|
||||
}
|
||||
iced_native::text::HorizontalAlignment::Right => {
|
||||
iced_native::HorizontalAlignment::Right => {
|
||||
wgpu_glyph::HorizontalAlign::Right
|
||||
}
|
||||
})
|
||||
.v_align(match vertical_alignment {
|
||||
iced_native::text::VerticalAlignment::Top => {
|
||||
iced_native::VerticalAlignment::Top => {
|
||||
wgpu_glyph::VerticalAlign::Top
|
||||
}
|
||||
iced_native::text::VerticalAlignment::Center => {
|
||||
iced_native::VerticalAlignment::Center => {
|
||||
wgpu_glyph::VerticalAlign::Center
|
||||
}
|
||||
iced_native::text::VerticalAlignment::Bottom => {
|
||||
iced_native::VerticalAlignment::Bottom => {
|
||||
wgpu_glyph::VerticalAlign::Bottom
|
||||
}
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -1,52 +1,22 @@
|
|||
use crate::{Primitive, Renderer};
|
||||
use iced_native::{
|
||||
button, layout, Background, Button, Layout, Length, MouseCursor, Point,
|
||||
Rectangle,
|
||||
};
|
||||
use iced_native::{button, Background, MouseCursor, Point, Rectangle};
|
||||
|
||||
impl button::Renderer for Renderer {
|
||||
fn layout<Message>(
|
||||
&self,
|
||||
button: &Button<Message, Self>,
|
||||
limits: &layout::Limits,
|
||||
) -> layout::Node {
|
||||
let padding = f32::from(button.padding);
|
||||
let limits = limits
|
||||
.min_width(button.min_width)
|
||||
.width(button.width)
|
||||
.height(Length::Shrink)
|
||||
.pad(padding);
|
||||
|
||||
let mut content = button.content.layout(self, &limits);
|
||||
|
||||
content.bounds.x = padding;
|
||||
content.bounds.y = padding;
|
||||
|
||||
let size = limits.resolve(content.size()).pad(padding);
|
||||
|
||||
layout::Node::with_children(size, vec![content])
|
||||
}
|
||||
|
||||
fn draw<Message>(
|
||||
fn draw(
|
||||
&mut self,
|
||||
button: &Button<Message, Self>,
|
||||
layout: Layout<'_>,
|
||||
bounds: Rectangle,
|
||||
cursor_position: Point,
|
||||
is_pressed: bool,
|
||||
background: Option<Background>,
|
||||
border_radius: u16,
|
||||
(content, _): Self::Output,
|
||||
) -> Self::Output {
|
||||
let bounds = layout.bounds();
|
||||
|
||||
let (content, _) = button.content.draw(
|
||||
self,
|
||||
layout.children().next().unwrap(),
|
||||
cursor_position,
|
||||
);
|
||||
|
||||
let is_mouse_over = bounds.contains(cursor_position);
|
||||
|
||||
// TODO: Render proper shadows
|
||||
// TODO: Make hovering and pressed styles configurable
|
||||
let shadow_offset = if is_mouse_over {
|
||||
if button.state.is_pressed {
|
||||
if is_pressed {
|
||||
0.0
|
||||
} else {
|
||||
2.0
|
||||
|
|
@ -56,7 +26,7 @@ impl button::Renderer for Renderer {
|
|||
};
|
||||
|
||||
(
|
||||
match button.background {
|
||||
match background {
|
||||
None => content,
|
||||
Some(background) => Primitive::Group {
|
||||
primitives: vec![
|
||||
|
|
@ -69,12 +39,12 @@ impl button::Renderer for Renderer {
|
|||
background: Background::Color(
|
||||
[0.0, 0.0, 0.0, 0.5].into(),
|
||||
),
|
||||
border_radius: button.border_radius,
|
||||
border_radius,
|
||||
},
|
||||
Primitive::Quad {
|
||||
bounds,
|
||||
background,
|
||||
border_radius: button.border_radius,
|
||||
border_radius,
|
||||
},
|
||||
content,
|
||||
],
|
||||
|
|
|
|||
|
|
@ -1,63 +1,35 @@
|
|||
use crate::{Primitive, Renderer};
|
||||
use iced_native::{
|
||||
checkbox, layout, text, text::HorizontalAlignment, text::VerticalAlignment,
|
||||
Align, Background, Checkbox, Column, Layout, Length, MouseCursor, Point,
|
||||
Rectangle, Row, Text, Widget,
|
||||
checkbox, Background, HorizontalAlignment, MouseCursor, Rectangle,
|
||||
VerticalAlignment,
|
||||
};
|
||||
|
||||
const SIZE: f32 = 28.0;
|
||||
|
||||
impl checkbox::Renderer for Renderer {
|
||||
fn layout<Message>(
|
||||
&self,
|
||||
checkbox: &Checkbox<Message>,
|
||||
limits: &layout::Limits,
|
||||
) -> layout::Node {
|
||||
Row::<(), Self>::new()
|
||||
.spacing(15)
|
||||
.align_items(Align::Center)
|
||||
.push(
|
||||
Column::new()
|
||||
.width(Length::Units(SIZE as u16))
|
||||
.height(Length::Units(SIZE as u16)),
|
||||
)
|
||||
.push(Text::new(&checkbox.label))
|
||||
.layout(self, limits)
|
||||
fn default_size(&self) -> u32 {
|
||||
SIZE as u32
|
||||
}
|
||||
|
||||
fn draw<Message>(
|
||||
fn draw(
|
||||
&mut self,
|
||||
checkbox: &Checkbox<Message>,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
bounds: Rectangle,
|
||||
is_checked: bool,
|
||||
is_mouse_over: bool,
|
||||
(label, _): Self::Output,
|
||||
) -> Self::Output {
|
||||
let bounds = layout.bounds();
|
||||
let mut children = layout.children();
|
||||
|
||||
let checkbox_layout = children.next().unwrap();
|
||||
let label_layout = children.next().unwrap();
|
||||
let checkbox_bounds = checkbox_layout.bounds();
|
||||
|
||||
let (label, _) = text::Renderer::draw(
|
||||
self,
|
||||
&Text::new(&checkbox.label),
|
||||
label_layout,
|
||||
);
|
||||
|
||||
let is_mouse_over = bounds.contains(cursor_position);
|
||||
|
||||
let (checkbox_border, checkbox_box) = (
|
||||
Primitive::Quad {
|
||||
bounds: checkbox_bounds,
|
||||
bounds,
|
||||
background: Background::Color([0.6, 0.6, 0.6].into()),
|
||||
border_radius: 6,
|
||||
},
|
||||
Primitive::Quad {
|
||||
bounds: Rectangle {
|
||||
x: checkbox_bounds.x + 1.0,
|
||||
y: checkbox_bounds.y + 1.0,
|
||||
width: checkbox_bounds.width - 2.0,
|
||||
height: checkbox_bounds.height - 2.0,
|
||||
x: bounds.x + 1.0,
|
||||
y: bounds.y + 1.0,
|
||||
width: bounds.width - 2.0,
|
||||
height: bounds.height - 2.0,
|
||||
},
|
||||
background: Background::Color(
|
||||
if is_mouse_over {
|
||||
|
|
@ -73,12 +45,12 @@ impl checkbox::Renderer for Renderer {
|
|||
|
||||
(
|
||||
Primitive::Group {
|
||||
primitives: if checkbox.is_checked {
|
||||
primitives: if is_checked {
|
||||
let check = Primitive::Text {
|
||||
content: crate::text::CHECKMARK_ICON.to_string(),
|
||||
font: crate::text::BUILTIN_ICONS,
|
||||
size: checkbox_bounds.height * 0.7,
|
||||
bounds: checkbox_bounds,
|
||||
size: bounds.height * 0.7,
|
||||
bounds: bounds,
|
||||
color: [0.3, 0.3, 0.3].into(),
|
||||
horizontal_alignment: HorizontalAlignment::Center,
|
||||
vertical_alignment: VerticalAlignment::Center,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use crate::{Primitive, Renderer};
|
||||
use iced_native::{column, Column, Layout, MouseCursor, Point};
|
||||
use iced_native::{column, Element, Layout, MouseCursor, Point};
|
||||
|
||||
impl column::Renderer for Renderer {
|
||||
fn draw<Message>(
|
||||
&mut self,
|
||||
column: &Column<'_, Message, Self>,
|
||||
content: &[Element<'_, Message, Self>],
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Self::Output {
|
||||
|
|
@ -12,8 +12,7 @@ impl column::Renderer for Renderer {
|
|||
|
||||
(
|
||||
Primitive::Group {
|
||||
primitives: column
|
||||
.children
|
||||
primitives: content
|
||||
.iter()
|
||||
.zip(layout.children())
|
||||
.map(|(child, layout)| {
|
||||
|
|
|
|||
|
|
@ -1,28 +1,9 @@
|
|||
use crate::{Primitive, Renderer};
|
||||
use iced_native::{image, layout, Image, Layout, Length, MouseCursor, Size};
|
||||
use iced_native::{image, Image, Layout, MouseCursor};
|
||||
|
||||
impl image::Renderer for Renderer {
|
||||
fn layout(&self, image: &Image, limits: &layout::Limits) -> layout::Node {
|
||||
let (width, height) = self.image_pipeline.dimensions(&image.path);
|
||||
|
||||
let aspect_ratio = width as f32 / height as f32;
|
||||
|
||||
// TODO: Deal with additional cases
|
||||
let (width, height) = match (image.width, image.height) {
|
||||
(Length::Units(width), _) => (
|
||||
image.width,
|
||||
Length::Units((width as f32 / aspect_ratio).round() as u16),
|
||||
),
|
||||
(_, _) => {
|
||||
(Length::Units(width as u16), Length::Units(height as u16))
|
||||
}
|
||||
};
|
||||
|
||||
let mut size = limits.width(width).height(height).resolve(Size::ZERO);
|
||||
|
||||
size.height = size.width / aspect_ratio;
|
||||
|
||||
layout::Node::new(size)
|
||||
fn dimensions(&self, path: &str) -> (u32, u32) {
|
||||
self.image_pipeline.dimensions(path)
|
||||
}
|
||||
|
||||
fn draw(&mut self, image: &Image, layout: Layout<'_>) -> Self::Output {
|
||||
|
|
|
|||
|
|
@ -1,59 +1,33 @@
|
|||
use crate::{Primitive, Renderer};
|
||||
use iced_native::{
|
||||
layout, radio, text, Align, Background, Column, Layout, Length,
|
||||
MouseCursor, Point, Radio, Rectangle, Row, Text, Widget,
|
||||
};
|
||||
use iced_native::{radio, Background, MouseCursor, Rectangle};
|
||||
|
||||
const SIZE: f32 = 28.0;
|
||||
const DOT_SIZE: f32 = SIZE / 2.0;
|
||||
|
||||
impl radio::Renderer for Renderer {
|
||||
fn layout<Message>(
|
||||
&self,
|
||||
radio: &Radio<Message>,
|
||||
limits: &layout::Limits,
|
||||
) -> layout::Node {
|
||||
Row::<(), Self>::new()
|
||||
.spacing(15)
|
||||
.align_items(Align::Center)
|
||||
.push(
|
||||
Column::new()
|
||||
.width(Length::Units(SIZE as u16))
|
||||
.height(Length::Units(SIZE as u16)),
|
||||
)
|
||||
.push(Text::new(&radio.label))
|
||||
.layout(self, limits)
|
||||
fn default_size(&self) -> u32 {
|
||||
SIZE as u32
|
||||
}
|
||||
|
||||
fn draw<Message>(
|
||||
fn draw(
|
||||
&mut self,
|
||||
radio: &Radio<Message>,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
bounds: Rectangle,
|
||||
is_selected: bool,
|
||||
is_mouse_over: bool,
|
||||
(label, _): Self::Output,
|
||||
) -> Self::Output {
|
||||
let bounds = layout.bounds();
|
||||
let mut children = layout.children();
|
||||
|
||||
let radio_bounds = children.next().unwrap().bounds();
|
||||
let label_layout = children.next().unwrap();
|
||||
|
||||
let (label, _) =
|
||||
text::Renderer::draw(self, &Text::new(&radio.label), label_layout);
|
||||
|
||||
let is_mouse_over = bounds.contains(cursor_position);
|
||||
|
||||
let (radio_border, radio_box) = (
|
||||
Primitive::Quad {
|
||||
bounds: radio_bounds,
|
||||
bounds,
|
||||
background: Background::Color([0.6, 0.6, 0.6].into()),
|
||||
border_radius: (SIZE / 2.0) as u16,
|
||||
},
|
||||
Primitive::Quad {
|
||||
bounds: Rectangle {
|
||||
x: radio_bounds.x + 1.0,
|
||||
y: radio_bounds.y + 1.0,
|
||||
width: radio_bounds.width - 2.0,
|
||||
height: radio_bounds.height - 2.0,
|
||||
x: bounds.x + 1.0,
|
||||
y: bounds.y + 1.0,
|
||||
width: bounds.width - 2.0,
|
||||
height: bounds.height - 2.0,
|
||||
},
|
||||
background: Background::Color(
|
||||
if is_mouse_over {
|
||||
|
|
@ -69,13 +43,13 @@ impl radio::Renderer for Renderer {
|
|||
|
||||
(
|
||||
Primitive::Group {
|
||||
primitives: if radio.is_selected {
|
||||
primitives: if is_selected {
|
||||
let radio_circle = Primitive::Quad {
|
||||
bounds: Rectangle {
|
||||
x: radio_bounds.x + DOT_SIZE / 2.0,
|
||||
y: radio_bounds.y + DOT_SIZE / 2.0,
|
||||
width: radio_bounds.width - DOT_SIZE,
|
||||
height: radio_bounds.height - DOT_SIZE,
|
||||
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([0.3, 0.3, 0.3].into()),
|
||||
border_radius: (DOT_SIZE / 2.0) as u16,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use crate::{Primitive, Renderer};
|
||||
use iced_native::{row, Layout, MouseCursor, Point, Row};
|
||||
use iced_native::{row, Element, Layout, MouseCursor, Point};
|
||||
|
||||
impl row::Renderer for Renderer {
|
||||
fn draw<Message>(
|
||||
&mut self,
|
||||
row: &Row<'_, Message, Self>,
|
||||
children: &[Element<'_, Message, Self>],
|
||||
layout: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
) -> Self::Output {
|
||||
|
|
@ -12,8 +12,7 @@ impl row::Renderer for Renderer {
|
|||
|
||||
(
|
||||
Primitive::Group {
|
||||
primitives: row
|
||||
.children
|
||||
primitives: children
|
||||
.iter()
|
||||
.zip(layout.children())
|
||||
.map(|(child, layout)| {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use crate::{Primitive, Renderer};
|
||||
use iced_native::{
|
||||
scrollable, Background, Layout, MouseCursor, Point, Rectangle, Scrollable,
|
||||
Vector, Widget,
|
||||
scrollable, Background, MouseCursor, Point, Rectangle, Vector,
|
||||
};
|
||||
|
||||
const SCROLLBAR_WIDTH: u16 = 10;
|
||||
|
|
@ -28,33 +27,18 @@ impl scrollable::Renderer for Renderer {
|
|||
&& scrollbar_bounds(bounds).contains(cursor_position)
|
||||
}
|
||||
|
||||
fn draw<Message>(
|
||||
fn draw(
|
||||
&mut self,
|
||||
scrollable: &Scrollable<'_, Message, Self>,
|
||||
state: &scrollable::State,
|
||||
bounds: Rectangle,
|
||||
content: Layout<'_>,
|
||||
cursor_position: Point,
|
||||
content_bounds: Rectangle,
|
||||
is_mouse_over: bool,
|
||||
is_mouse_over_scrollbar: bool,
|
||||
offset: u32,
|
||||
(content, mouse_cursor): Self::Output,
|
||||
) -> Self::Output {
|
||||
let is_mouse_over = bounds.contains(cursor_position);
|
||||
let content_bounds = content.bounds();
|
||||
|
||||
let offset = scrollable.state.offset(bounds, content_bounds);
|
||||
let is_content_overflowing = content_bounds.height > bounds.height;
|
||||
let scrollbar_bounds = scrollbar_bounds(bounds);
|
||||
let is_mouse_over_scrollbar = self.is_mouse_over_scrollbar(
|
||||
bounds,
|
||||
content_bounds,
|
||||
cursor_position,
|
||||
);
|
||||
|
||||
let cursor_position = if is_mouse_over && !is_mouse_over_scrollbar {
|
||||
Point::new(cursor_position.x, cursor_position.y + offset as f32)
|
||||
} else {
|
||||
Point::new(cursor_position.x, -1.0)
|
||||
};
|
||||
|
||||
let (content, mouse_cursor) =
|
||||
scrollable.content.draw(self, content, cursor_position);
|
||||
|
||||
let clip = Primitive::Clip {
|
||||
bounds,
|
||||
|
|
@ -64,7 +48,7 @@ impl scrollable::Renderer for Renderer {
|
|||
|
||||
(
|
||||
if is_content_overflowing
|
||||
&& (is_mouse_over || scrollable.state.is_scrollbar_grabbed())
|
||||
&& (is_mouse_over || state.is_scrollbar_grabbed())
|
||||
{
|
||||
let ratio = bounds.height / content_bounds.height;
|
||||
let scrollbar_height = bounds.height * ratio;
|
||||
|
|
@ -82,9 +66,7 @@ impl scrollable::Renderer for Renderer {
|
|||
border_radius: 5,
|
||||
};
|
||||
|
||||
if is_mouse_over_scrollbar
|
||||
|| scrollable.state.is_scrollbar_grabbed()
|
||||
{
|
||||
if is_mouse_over_scrollbar || state.is_scrollbar_grabbed() {
|
||||
let scrollbar_background = Primitive::Quad {
|
||||
bounds: Rectangle {
|
||||
x: scrollbar_bounds.x + f32::from(SCROLLBAR_MARGIN),
|
||||
|
|
@ -109,9 +91,7 @@ impl scrollable::Renderer for Renderer {
|
|||
} else {
|
||||
clip
|
||||
},
|
||||
if is_mouse_over_scrollbar
|
||||
|| scrollable.state.is_scrollbar_grabbed()
|
||||
{
|
||||
if is_mouse_over_scrollbar || state.is_scrollbar_grabbed() {
|
||||
MouseCursor::Idle
|
||||
} else {
|
||||
mouse_cursor
|
||||
|
|
|
|||
|
|
@ -1,32 +1,22 @@
|
|||
use crate::{Primitive, Renderer};
|
||||
use iced_native::{
|
||||
layout, slider, Background, Color, Layout, Length, MouseCursor, Point,
|
||||
Rectangle, Size, Slider,
|
||||
};
|
||||
use iced_native::{slider, Background, Color, MouseCursor, Point, Rectangle};
|
||||
|
||||
const HANDLE_WIDTH: f32 = 8.0;
|
||||
const HANDLE_HEIGHT: f32 = 22.0;
|
||||
|
||||
impl slider::Renderer for Renderer {
|
||||
fn layout<Message>(
|
||||
&self,
|
||||
slider: &Slider<Message>,
|
||||
limits: &layout::Limits,
|
||||
) -> layout::Node {
|
||||
let limits = limits.width(slider.width).height(Length::Units(30));
|
||||
let size = limits.resolve(Size::ZERO);
|
||||
|
||||
layout::Node::new(size)
|
||||
fn height(&self) -> u32 {
|
||||
30
|
||||
}
|
||||
|
||||
fn draw<Message>(
|
||||
fn draw(
|
||||
&mut self,
|
||||
slider: &Slider<Message>,
|
||||
layout: Layout<'_>,
|
||||
bounds: Rectangle,
|
||||
cursor_position: Point,
|
||||
range: std::ops::RangeInclusive<f32>,
|
||||
value: f32,
|
||||
is_dragging: bool,
|
||||
) -> Self::Output {
|
||||
let bounds = layout.bounds();
|
||||
|
||||
let is_mouse_over = bounds.contains(cursor_position);
|
||||
|
||||
let rail_y = bounds.y + (bounds.height / 2.0).round();
|
||||
|
|
@ -54,11 +44,10 @@ impl slider::Renderer for Renderer {
|
|||
},
|
||||
);
|
||||
|
||||
let (range_start, range_end) = slider.range.clone().into_inner();
|
||||
let (range_start, range_end) = range.into_inner();
|
||||
|
||||
let handle_offset = (bounds.width - HANDLE_WIDTH)
|
||||
* ((slider.value - range_start)
|
||||
/ (range_end - range_start).max(1.0));
|
||||
* ((value - range_start) / (range_end - range_start).max(1.0));
|
||||
|
||||
let (handle_border, handle) = (
|
||||
Primitive::Quad {
|
||||
|
|
@ -79,7 +68,7 @@ impl slider::Renderer for Renderer {
|
|||
height: HANDLE_HEIGHT,
|
||||
},
|
||||
background: Background::Color(
|
||||
if slider.state.is_dragging() {
|
||||
if is_dragging {
|
||||
[0.85, 0.85, 0.85]
|
||||
} else if is_mouse_over {
|
||||
[0.90, 0.90, 0.90]
|
||||
|
|
@ -96,7 +85,7 @@ impl slider::Renderer for Renderer {
|
|||
Primitive::Group {
|
||||
primitives: vec![rail_top, rail_bottom, handle_border, handle],
|
||||
},
|
||||
if slider.state.is_dragging() {
|
||||
if is_dragging {
|
||||
MouseCursor::Grabbing
|
||||
} else if is_mouse_over {
|
||||
MouseCursor::Grab
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
use crate::{Primitive, Renderer};
|
||||
use iced_native::{layout, text, Color, Layout, MouseCursor, Size, Text};
|
||||
use iced_native::{
|
||||
text, Color, Font, HorizontalAlignment, MouseCursor, Rectangle, Size,
|
||||
VerticalAlignment,
|
||||
};
|
||||
|
||||
use std::f32;
|
||||
|
||||
|
|
@ -7,30 +10,40 @@ use std::f32;
|
|||
const DEFAULT_TEXT_SIZE: f32 = 20.0;
|
||||
|
||||
impl text::Renderer for Renderer {
|
||||
fn layout(&self, text: &Text, limits: &layout::Limits) -> layout::Node {
|
||||
let limits = limits.width(text.width).height(text.height);
|
||||
let size = text.size.map(f32::from).unwrap_or(DEFAULT_TEXT_SIZE);
|
||||
let bounds = limits.max();
|
||||
|
||||
let (width, height) =
|
||||
self.text_pipeline
|
||||
.measure(&text.content, size, text.font, bounds);
|
||||
|
||||
let size = limits.resolve(Size::new(width, height));
|
||||
|
||||
layout::Node::new(size)
|
||||
fn default_size(&self) -> u16 {
|
||||
DEFAULT_TEXT_SIZE as u16
|
||||
}
|
||||
|
||||
fn draw(&mut self, text: &Text, layout: Layout<'_>) -> Self::Output {
|
||||
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,
|
||||
bounds: Rectangle,
|
||||
content: &str,
|
||||
size: u16,
|
||||
font: Font,
|
||||
color: Option<Color>,
|
||||
horizontal_alignment: HorizontalAlignment,
|
||||
vertical_alignment: VerticalAlignment,
|
||||
) -> Self::Output {
|
||||
(
|
||||
Primitive::Text {
|
||||
content: text.content.clone(),
|
||||
size: text.size.map(f32::from).unwrap_or(DEFAULT_TEXT_SIZE),
|
||||
bounds: layout.bounds(),
|
||||
color: text.color.unwrap_or(Color::BLACK),
|
||||
font: text.font,
|
||||
horizontal_alignment: text.horizontal_alignment,
|
||||
vertical_alignment: text.vertical_alignment,
|
||||
content: content.to_string(),
|
||||
size: f32::from(size),
|
||||
bounds,
|
||||
color: color.unwrap_or(Color::BLACK),
|
||||
font,
|
||||
horizontal_alignment,
|
||||
vertical_alignment,
|
||||
},
|
||||
MouseCursor::OutOfBounds,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use crate::{Primitive, Renderer};
|
||||
|
||||
use iced_native::{
|
||||
text::HorizontalAlignment, text::VerticalAlignment, text_input, Background,
|
||||
Color, Font, MouseCursor, Point, Rectangle, Size, TextInput, Vector,
|
||||
text_input, Background, Color, Font, HorizontalAlignment, MouseCursor,
|
||||
Point, Rectangle, Size, Vector, VerticalAlignment,
|
||||
};
|
||||
use std::f32;
|
||||
|
||||
|
|
@ -12,19 +12,22 @@ impl text_input::Renderer for Renderer {
|
|||
20
|
||||
}
|
||||
|
||||
fn draw<Message>(
|
||||
fn draw(
|
||||
&mut self,
|
||||
text_input: &TextInput<Message>,
|
||||
bounds: Rectangle,
|
||||
text_bounds: Rectangle,
|
||||
cursor_position: Point,
|
||||
size: u16,
|
||||
placeholder: &str,
|
||||
value: &text_input::Value,
|
||||
state: &text_input::State,
|
||||
) -> Self::Output {
|
||||
let is_mouse_over = bounds.contains(cursor_position);
|
||||
|
||||
let border = Primitive::Quad {
|
||||
bounds,
|
||||
background: Background::Color(
|
||||
if is_mouse_over || text_input.state.is_focused {
|
||||
if is_mouse_over || state.is_focused() {
|
||||
[0.5, 0.5, 0.5]
|
||||
} else {
|
||||
[0.7, 0.7, 0.7]
|
||||
|
|
@ -45,12 +48,12 @@ impl text_input::Renderer for Renderer {
|
|||
border_radius: 5,
|
||||
};
|
||||
|
||||
let size = f32::from(text_input.size.unwrap_or(self.default_size()));
|
||||
let text = text_input.value.to_string();
|
||||
let size = f32::from(size);
|
||||
let text = value.to_string();
|
||||
|
||||
let value = Primitive::Text {
|
||||
let text_value = Primitive::Text {
|
||||
content: if text.is_empty() {
|
||||
text_input.placeholder.clone()
|
||||
placeholder.to_string()
|
||||
} else {
|
||||
text.clone()
|
||||
},
|
||||
|
|
@ -70,14 +73,12 @@ impl text_input::Renderer for Renderer {
|
|||
vertical_alignment: VerticalAlignment::Center,
|
||||
};
|
||||
|
||||
let (contents_primitive, offset) = if text_input.state.is_focused {
|
||||
let text_before_cursor = &text_input
|
||||
.value
|
||||
.until(text_input.state.cursor_position(&text_input.value))
|
||||
.to_string();
|
||||
let (contents_primitive, offset) = if state.is_focused() {
|
||||
let text_before_cursor =
|
||||
value.until(state.cursor_position(value)).to_string();
|
||||
|
||||
let (mut text_value_width, _) = self.text_pipeline.measure(
|
||||
text_before_cursor,
|
||||
&text_before_cursor,
|
||||
size,
|
||||
Font::Default,
|
||||
Size::new(f32::INFINITY, text_bounds.height),
|
||||
|
|
@ -104,7 +105,7 @@ impl text_input::Renderer for Renderer {
|
|||
|
||||
(
|
||||
Primitive::Group {
|
||||
primitives: vec![value, cursor],
|
||||
primitives: vec![text_value, cursor],
|
||||
},
|
||||
Vector::new(
|
||||
((text_value_width + 5.0) - text_bounds.width).max(0.0)
|
||||
|
|
@ -113,7 +114,7 @@ impl text_input::Renderer for Renderer {
|
|||
),
|
||||
)
|
||||
} else {
|
||||
(value, Vector::new(0, 0))
|
||||
(text_value, Vector::new(0, 0))
|
||||
};
|
||||
|
||||
let contents = Primitive::Clip {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue