use iced::advanced::layout::{self, Layout};
use iced::advanced::widget::{self, Widget};
use iced::advanced::{mouse, renderer};
use iced::{Border, Color, Element, Length, Rectangle, Shadow, Size};
const WIDTH: f32 = 9.0;
const HEIGHT: f32 = 9.0;
const CHEVRON_ROWS: u32 = 5;
const EDGE_ALPHA: f32 = 0.5;
const NUDGE_Y: f32 = 1.0;
#[derive(Debug, Clone, Copy)]
pub struct SortArrow {
up: bool,
}
impl SortArrow {
pub fn up() -> Self {
Self { up: true }
}
pub fn down() -> Self {
Self { up: false }
}
}
impl<Message, Theme, Renderer> Widget<Message, Theme, Renderer> for SortArrow
where
Renderer: renderer::Renderer,
{
fn size(&self) -> Size<Length> {
Size::new(Length::Fixed(WIDTH), Length::Fixed(HEIGHT))
}
fn layout(
&mut self,
_tree: &mut widget::Tree,
_renderer: &Renderer,
limits: &layout::Limits,
) -> layout::Node {
layout::atomic(limits, WIDTH, HEIGHT)
}
fn draw(
&self,
_tree: &widget::Tree,
renderer: &mut Renderer,
_theme: &Theme,
style: &renderer::Style,
layout: Layout<'_>,
_cursor: mouse::Cursor,
_viewport: &Rectangle,
) {
let bounds = layout.bounds();
let x0 = bounds.x.round();
let y0 = bounds.y.round() + NUDGE_Y;
let color = style.text_color;
let edge = Color {
a: color.a * EDGE_ALPHA,
..color
};
let mut quad = |x: f32, y: f32, w: f32, h: f32, color: Color| {
renderer.fill_quad(
renderer::Quad {
bounds: Rectangle {
x: x0 + x,
y: y0 + y,
width: w,
height: h,
},
border: Border::default(),
shadow: Shadow::default(),
snap: false,
},
color,
);
};
let fy = |row: u32| {
if self.up {
row as f32
} else {
HEIGHT - 1.0 - row as f32
}
};
let center = (WIDTH - 1.0) / 2.0;
let stem_y = if self.up { 1.0 } else { 0.0 };
quad(center, stem_y, 1.0, HEIGHT - 1.0, color);
for r in 0..CHEVRON_ROWS {
let y = fy(r);
let step = r as f32;
if r == 0 {
quad(center, y, 1.0, 1.0, color);
quad(center - 1.0, y, 1.0, 1.0, edge);
quad(center + 1.0, y, 1.0, 1.0, edge);
} else {
for side in [-1.0f32, 1.0] {
let x = center + side * step;
quad(x, y, 1.0, 1.0, color);
for shoulder in [-1.0f32, 1.0] {
let ex = x + shoulder;
if (0.0..WIDTH).contains(&ex) {
quad(ex, y, 1.0, 1.0, edge);
}
}
}
}
}
}
}
impl<'a, Message, Theme, Renderer> From<SortArrow> for Element<'a, Message, Theme, Renderer>
where
Message: 'a,
Theme: 'a,
Renderer: renderer::Renderer + 'a,
{
fn from(arrow: SortArrow) -> Self {
Element::new(arrow)
}
}