maolan-widgets 0.0.20

Widgets used for Maolan DAW
Documentation
use iced::{
    Border, Color, Element, Length, alignment,
    widget::{button, row, text},
};
use iced_fonts::lucide::{chevron_right, square, square_check_big};

pub fn base_button<'a, Message>(
    content: impl Into<Element<'a, Message>>,
    msg: Message,
) -> button::Button<'a, Message>
where
    Message: Clone + 'a,
{
    button(content)
        .padding([4, 8])
        .style(|theme, status| {
            use button::{Status, Style};

            let palette = theme.extended_palette();
            let base = Style {
                text_color: palette.background.base.text,
                border: Border::default().rounded(6.0),
                ..Style::default()
            };
            match status {
                Status::Active => base.with_background(Color::TRANSPARENT),
                Status::Hovered => base.with_background(Color::from_rgb(
                    palette.primary.weak.color.r * 1.2,
                    palette.primary.weak.color.g * 1.2,
                    palette.primary.weak.color.b * 1.2,
                )),
                Status::Disabled => base.with_background(Color::from_rgb(0.5, 0.5, 0.5)),
                Status::Pressed => base.with_background(palette.primary.weak.color),
            }
        })
        .on_press(msg)
}

pub fn menu_button<Message>(
    label: impl Into<String>,
    width: Option<Length>,
    height: Option<Length>,
    msg: Message,
) -> Element<'static, Message, iced::Theme, iced::Renderer>
where
    Message: Clone + 'static,
{
    let label = label.into();
    base_button(
        text(label)
            .height(height.unwrap_or(Length::Shrink))
            .align_y(alignment::Vertical::Center),
        msg,
    )
    .width(width.unwrap_or(Length::Shrink))
    .height(height.unwrap_or(Length::Shrink))
    .into()
}

pub fn menu_dropdown<Message>(
    label: impl Into<String>,
    message: Message,
) -> Element<'static, Message, iced::Theme, iced::Renderer>
where
    Message: Clone + 'static,
{
    menu_button(label, Some(Length::Shrink), Some(Length::Shrink), message)
}

pub fn menu_item<Message>(
    label: impl Into<String>,
    message: Message,
) -> Element<'static, Message, iced::Theme, iced::Renderer>
where
    Message: Clone + 'static,
{
    menu_button(label, Some(Length::Fill), Some(Length::Shrink), message)
}

pub fn menu_checkbox_item<Message>(
    label: impl Into<String>,
    checked: bool,
    message: Message,
) -> Element<'static, Message, iced::Theme, iced::Renderer>
where
    Message: Clone + 'static,
{
    let label = label.into();
    let icon = if checked {
        square_check_big()
    } else {
        square()
    };
    base_button(
        row![
            icon.width(20).align_y(alignment::Vertical::Center),
            text(label)
                .height(Length::Shrink)
                .align_y(alignment::Vertical::Center),
        ]
        .spacing(6)
        .align_y(iced::Alignment::Center),
        message,
    )
    .width(Length::Fill)
    .height(Length::Shrink)
    .into()
}

pub fn menu_item_maybe<Message>(
    label: impl Into<String>,
    message: Option<Message>,
) -> Element<'static, Message, iced::Theme, iced::Renderer>
where
    Message: Clone + 'static,
{
    let label = label.into();
    let btn = button(
        text(label)
            .height(Length::Shrink)
            .align_y(alignment::Vertical::Center),
    )
    .padding([4, 8])
    .style(|theme: &iced::Theme, status| {
        use button::{Status, Style};

        let palette = theme.extended_palette();
        let base = Style {
            text_color: palette.background.base.text,
            border: Border::default().rounded(6.0),
            ..Style::default()
        };
        match status {
            Status::Active => base.with_background(Color::TRANSPARENT),
            Status::Hovered => base.with_background(Color::from_rgb(
                palette.primary.weak.color.r * 1.2,
                palette.primary.weak.color.g * 1.2,
                palette.primary.weak.color.b * 1.2,
            )),
            Status::Disabled => base.with_background(Color::from_rgb(0.5, 0.5, 0.5)),
            Status::Pressed => base.with_background(palette.primary.weak.color),
        }
    })
    .width(Length::Fill)
    .height(Length::Shrink);
    if let Some(message) = message {
        btn.on_press(message).into()
    } else {
        btn.into()
    }
}

pub fn submenu<Message>(
    label: impl Into<String>,
    msg: Message,
) -> Element<'static, Message, iced::Theme, iced::Renderer>
where
    Message: Clone + 'static,
{
    let label = label.into();
    base_button(
        row![
            text(label)
                .width(Length::Fill)
                .align_y(alignment::Vertical::Center),
            chevron_right(),
        ]
        .align_y(iced::Alignment::Center),
        msg,
    )
    .width(Length::Fill)
    .height(Length::Shrink)
    .into()
}