use iced::widget::button;
use iced::{Background, Border, Color};
use crate::app::TopMenuIndicator;
use super::super::theme::{
tokyo_blue, tokyo_board, tokyo_border, tokyo_muted, tokyo_red, tokyo_surface, tokyo_surface_2,
tokyo_surface_3, tokyo_surface_3_tint, tokyo_text,
};
fn is_button_active(status: button::Status) -> bool {
matches!(status, button::Status::Hovered | button::Status::Pressed)
}
pub(crate) fn action_button_style(status: button::Status) -> button::Style {
let disabled = matches!(status, button::Status::Disabled);
let background = match status {
button::Status::Pressed => tokyo_surface_2(),
button::Status::Hovered => tokyo_surface(),
_ => tokyo_board(),
};
let border_color = if disabled {
Color {
a: 0.35,
..tokyo_border()
}
} else {
tokyo_border()
};
let text_color = if disabled {
tokyo_muted()
} else {
tokyo_text()
};
button::Style {
background: Some(Background::Color(background)),
text_color,
border: Border {
radius: 6.0.into(),
width: 1.0,
color: border_color,
},
..button::Style::default()
}
}
pub(crate) fn enter_button_style(status: button::Status) -> button::Style {
let background = match status {
button::Status::Pressed => tokyo_surface_2(),
button::Status::Hovered => tokyo_surface(),
_ => tokyo_board(),
};
button::Style {
background: Some(Background::Color(background)),
text_color: tokyo_text(),
border: Border {
radius: 6.0.into(),
width: 1.0,
color: tokyo_border(),
},
..button::Style::default()
}
}
pub(crate) fn modal_field_button_style(status: button::Status) -> button::Style {
let background = match status {
button::Status::Hovered => Color {
a: 0.45,
..tokyo_surface()
},
button::Status::Pressed => tokyo_surface_2(),
_ => Color::TRANSPARENT,
};
button::Style {
background: Some(Background::Color(background)),
text_color: tokyo_text(),
border: Border {
radius: 6.0.into(),
width: 1.0,
color: tokyo_border(),
},
..button::Style::default()
}
}
pub(crate) fn modal_tab_button_style(status: button::Status, active: bool) -> button::Style {
let background = match (active, status) {
(true, _) => tokyo_surface(),
(false, button::Status::Hovered) => Color {
a: 0.45,
..tokyo_surface()
},
(false, button::Status::Pressed) => tokyo_surface_2(),
_ => Color::TRANSPARENT,
};
button::Style {
background: Some(Background::Color(background)),
text_color: tokyo_text(),
border: Border {
radius: 6.0.into(),
width: 1.0,
color: tokyo_border(),
},
..button::Style::default()
}
}
pub(crate) fn modal_dropdown_option_style(
status: button::Status,
highlighted: bool,
) -> button::Style {
let background = match (highlighted, status) {
(true, _) => tokyo_surface(),
(false, button::Status::Hovered) => Color {
a: 0.45,
..tokyo_surface()
},
(false, button::Status::Pressed) => tokyo_surface_2(),
_ => Color::TRANSPARENT,
};
button::Style {
background: Some(Background::Color(background)),
text_color: tokyo_text(),
border: Border {
radius: 4.0.into(),
width: 0.0,
color: Color::TRANSPARENT,
},
..button::Style::default()
}
}
pub(crate) fn menu_button_style(
status: button::Status,
indicator: TopMenuIndicator,
) -> button::Style {
let background = match indicator {
TopMenuIndicator::ArrowFill => tokyo_surface_2(),
TopMenuIndicator::TabRing => Color::TRANSPARENT,
TopMenuIndicator::Hidden if is_button_active(status) => tokyo_surface_2(),
TopMenuIndicator::Hidden => Color::TRANSPARENT,
};
let keyboard_focused = indicator == TopMenuIndicator::TabRing;
button::Style {
background: Some(Background::Color(background)),
text_color: tokyo_text(),
border: Border {
radius: 6.0.into(),
width: if keyboard_focused { 1.0 } else { 0.0 },
color: if keyboard_focused {
tokyo_blue()
} else {
Color::TRANSPARENT
},
},
..button::Style::default()
}
}
pub(crate) fn menu_button_disabled_style(_status: button::Status) -> button::Style {
button::Style {
background: Some(Background::Color(Color::TRANSPARENT)),
text_color: tokyo_muted(),
border: Border {
radius: 6.0.into(),
..Border::default()
},
..button::Style::default()
}
}
pub(crate) fn step_button_style(status: button::Status) -> button::Style {
let background = if is_button_active(status) {
tokyo_surface_3_tint()
} else {
Color::TRANSPARENT
};
button::Style {
background: Some(Background::Color(background)),
text_color: tokyo_text(),
border: Border {
radius: 3.0.into(),
width: 0.0,
color: Color::TRANSPARENT,
},
..button::Style::default()
}
}
pub(crate) fn opcode_option_style(status: button::Status, highlighted: bool) -> button::Style {
let background = if highlighted || is_button_active(status) {
tokyo_surface_3()
} else {
Color::TRANSPARENT
};
button::Style {
background: Some(Background::Color(background)),
text_color: tokyo_text(),
border: Border::default(),
..button::Style::default()
}
}
pub(crate) fn caption_button_style(status: button::Status) -> button::Style {
let background = match status {
button::Status::Hovered => tokyo_surface_2(),
button::Status::Pressed => tokyo_surface_3(),
_ => Color::TRANSPARENT,
};
button::Style {
background: Some(Background::Color(background)),
text_color: tokyo_text(),
border: Border {
radius: 4.0.into(),
..Border::default()
},
..button::Style::default()
}
}
pub(crate) fn close_caption_button_style(status: button::Status) -> button::Style {
let background = match status {
button::Status::Hovered => tokyo_red(),
button::Status::Pressed => Color {
a: 0.85,
..tokyo_red()
},
_ => Color::TRANSPARENT,
};
button::Style {
background: Some(Background::Color(background)),
text_color: tokyo_text(),
border: Border {
radius: 4.0.into(),
..Border::default()
},
..button::Style::default()
}
}
#[cfg(test)]
mod tests {
use super::super::super::theme::{tokyo_blue, tokyo_board};
use super::*;
#[test]
fn action_button_resting_background_matches_app_plate() {
let active = action_button_style(button::Status::Active);
let disabled = action_button_style(button::Status::Disabled);
assert_eq!(active.background, Some(Background::Color(tokyo_board())));
assert_eq!(disabled.background, Some(Background::Color(tokyo_board())));
}
#[test]
fn enter_button_resting_background_matches_app_plate() {
let style = enter_button_style(button::Status::Active);
assert_eq!(style.background, Some(Background::Color(tokyo_board())));
}
#[test]
fn keyboard_focused_menu_item_uses_blue_border_without_fill() {
let style = menu_button_style(button::Status::Active, TopMenuIndicator::TabRing);
assert_eq!(
style.background,
Some(Background::Color(Color::TRANSPARENT))
);
assert_eq!(style.border.width, 1.0);
assert_eq!(style.border.color, tokyo_blue());
}
#[test]
fn arrow_focused_menu_item_uses_hover_fill_without_border() {
let style = menu_button_style(button::Status::Active, TopMenuIndicator::ArrowFill);
assert_eq!(style.background, Some(Background::Color(tokyo_surface_2())));
assert_eq!(style.border.width, 0.0);
assert_eq!(style.border.color, Color::TRANSPARENT);
}
}