use crate::prelude::MIN_FILE_DIALOG_SIZE;
use crate::ui::prelude::*;
use buffer_graphics_lib::prelude::Positioning::LeftTop;
use buffer_graphics_lib::prelude::*;
impl Default for UiStyle {
fn default() -> Self {
Self {
checkbox: Default::default(),
button: Default::default(),
text_field: Default::default(),
toggle_button: Default::default(),
alert: Default::default(),
dialog: DialogStyle::new_default_size(MIN_FILE_DIALOG_SIZE),
background: Color {
r: 30,
g: 30,
b: 140,
a: 255,
},
title_text: TextFormat::new(
WrappingStrategy::None,
PixelFont::Standard8x10,
WHITE,
LeftTop,
),
body_text: TextFormat::new(
WrappingStrategy::None,
PixelFont::Standard6x7,
WHITE,
LeftTop,
),
tooltip: Default::default(),
icon_button: Default::default(),
toggle_icon_button: Default::default(),
menu: MenuBarStyle::default(),
}
}
}
impl Default for ButtonStyle {
fn default() -> Self {
Self {
text: ColorSet::new_values(WHITE, WHITE, WHITE, LIGHT_GRAY),
font: PixelFont::Standard6x7,
border: ColorSet::new_values(LIGHT_GRAY, CYAN, RED, DARK_GRAY),
shadow: ColorSet::new_same(DARK_GRAY),
rounding: 2,
}
}
}
impl Default for ToggleButtonStyle {
fn default() -> Self {
Self {
text: ToggleColorSet::new_same(WHITE),
font: PixelFont::Standard6x7,
border: ToggleColorSet::new_values(LIGHT_GRAY, CYAN, WHITE, CYAN, RED, DARK_GRAY),
shadow: ToggleColorSet::new_values(
DARK_GRAY, DARK_GRAY, WHITE, WHITE, DARK_GRAY, DARK_GRAY,
),
rounding: 6,
}
}
}
impl Default for TextFieldStyle {
fn default() -> Self {
Self {
text_color: FocusColorSet::new_values(BLACK, BLACK, BLACK, RED, DARK_GRAY),
background_color: FocusColorSet::new_same(WHITE),
border_color: FocusColorSet::new_values(DARK_GRAY, DARK_GRAY, CYAN, RED, LIGHT_GRAY),
cursor: FocusColorSet::new_same(BLACK),
}
}
}
impl Default for AlertStyle {
fn default() -> Self {
Self {
background: Some(Color {
r: 20,
g: 20,
b: 120,
a: 255,
}),
text: WHITE,
warning_text: RED,
font: PixelFont::Standard6x7,
button: ButtonStyle::default(),
border: Some(LIGHT_GRAY),
shadow: Some(DARK_GRAY),
shade: Some(Color::new(0, 0, 0, 127)),
}
}
}
impl DialogStyle {
pub fn new_default_size(size: (usize, usize)) -> Self {
let bounds = Rect::new_with_size((0, 0), size.0, size.1);
Self::new_default(bounds.translate_by(Coord::from(size) / 2))
}
pub fn new_default(bounds: Rect) -> Self {
Self::new(
bounds,
Some(Color {
r: 30,
g: 30,
b: 140,
a: 255,
}),
WHITE,
Some(LIGHT_GRAY),
Some(DARK_GRAY),
Some(Color {
r: 0,
g: 0,
b: 0,
a: 150,
}),
)
}
#[allow(clippy::too_many_arguments)]
pub fn new(
bounds: Rect,
background: Option<Color>,
text: Color,
border: Option<Color>,
shadow: Option<Color>,
shade: Option<Color>,
) -> Self {
Self {
bounds,
background,
text,
border,
shadow,
shade,
}
}
}
impl Default for TooltipStyle {
fn default() -> Self {
Self {
text: ColorSet::new_same(WHITE),
background: ColorSet::new_same(BLACK),
border: ColorSet::new_same(LIGHT_GRAY),
shadow: ColorSet::new_same(DARK_GRAY),
font: PixelFont::Standard4x5,
padding: 2,
}
}
}
impl Default for IconButtonStyle {
fn default() -> Self {
Self {
tooltip: TooltipStyle::default(),
border: ColorSet::new_values(LIGHT_GRAY, CYAN, RED, DARK_GRAY),
shadow: ColorSet::new_same(DARK_GRAY),
rounding: 2,
padding: 4,
}
}
}
impl Default for ToggleIconButtonStyle {
fn default() -> Self {
Self {
tooltip: TooltipStyle::default(),
border: ToggleColorSet::new_values(LIGHT_GRAY, CYAN, WHITE, CYAN, RED, DARK_GRAY),
shadow: ToggleColorSet::new_values(
DARK_GRAY, DARK_GRAY, WHITE, WHITE, DARK_GRAY, DARK_GRAY,
),
rounding: 6,
padding: 4,
}
}
}
impl Default for MenuBarStyle {
fn default() -> Self {
Self {
background: ColorSet::new_same(BLUE.with_saturate(0.8)),
border: ColorSet::new_same(WHITE),
menu_item: MenuItemStyle::default(),
dropdown_item: DropdownItemStyle::default(),
}
}
}
impl Default for MenuItemStyle {
fn default() -> Self {
Self {
background: FocusColorSet::menu(BLUE.with_saturate(0.8), TRANSPARENT, TRANSPARENT),
text: FocusColorSet::new_values(OFF_WHITE, WHITE, WHITE, LIGHT_GRAY, MID_GRAY),
font: Default::default(),
dropdown_background: Some(BLUE.with_saturate(0.8)),
padding: Padding::new(2, 2, 2, 1),
}
}
}
impl Default for DropdownItemStyle {
fn default() -> Self {
Self {
background: FocusColorSet::menu(BLUE.with_saturate(0.8), TRANSPARENT, TRANSPARENT),
text: FocusColorSet::new_values(OFF_WHITE, WHITE, WHITE, LIGHT_GRAY, MID_GRAY),
font: PixelFont::default(),
arrow: DropdownItemStyle::dropdown_arrow_for_font(
PixelFont::default(),
FocusColorSet::new_values(OFF_WHITE, LIGHT_GRAY, WHITE, LIGHT_GRAY, MID_GRAY),
),
padding: Padding::new(2, 2, 2, 1),
}
}
}
impl DropdownItemStyle {
fn dropdown_arrow_for_font(font: PixelFont, colors: FocusColorSet) -> IconSet {
let mut buffer = Graphics::create_buffer_u8(font.size().0, font.size().1);
let mut graphics = Graphics::new_u8_rgba(&mut buffer, font.size().0, font.size().1)
.unwrap_or_else(|err| {
panic!(
"Unable to create graphics using {font:?} when generating menu arrow: {err:?}"
)
});
graphics.draw_triangle(
Triangle::right_angle(
(0, 0),
font.size().0.min(font.size().1),
AnglePosition::Right,
)
.move_center_to(coord!(font.size().0 / 2, font.size().1 / 2)),
fill(WHITE),
);
let icon = graphics
.copy_to_indexed_image(false)
.unwrap_or_else(|err| panic!("Unable to create menu arrow icon: {err:?}"));
let idx = icon.get_palette().iter().position(|c| c == &WHITE).unwrap_or_else(|| panic!("Unable to find color in menubar arrow, please raise an issue on Github emmabritton/pixel-graphics-lib"));
let recolor = |image: &IndexedImage, color: Color| {
let mut img = image.clone();
img.set_color_unchecked(idx as u8, color);
img
};
IconSet {
normal: Some(recolor(&icon, colors.normal.unwrap_or(WHITE))),
focused: Some(recolor(
&icon,
colors.focused.unwrap_or(colors.normal.unwrap_or(WHITE)),
)),
hover: Some(recolor(
&icon,
colors.hover.unwrap_or(colors.normal.unwrap_or(WHITE)),
)),
error: Some(recolor(
&icon,
colors.error.unwrap_or(colors.disabled.unwrap_or(MID_GRAY)),
)),
disabled: Some(recolor(
&icon,
colors.disabled.unwrap_or(colors.error.unwrap_or(MID_GRAY)),
)),
}
}
}
impl Default for CheckboxStyle {
fn default() -> Self {
let [checked_icon, check_box] = CheckboxStyle::icons();
CheckboxStyle {
checked_icon,
check_box,
text: ColorSet::new_values(WHITE, WHITE, WHITE, LIGHT_GRAY),
icon: ColorSet::new_values(WHITE, WHITE, WHITE, LIGHT_GRAY),
font: PixelFont::Standard6x7,
spacing: 4,
}
}
}
impl CheckboxStyle {
fn icons() -> [IndexedImage; 2] {
let size = 9;
let mut box_buffer = Graphics::create_buffer_u8(size, size);
let mut check_buffer = Graphics::create_buffer_u8(size, size);
let mut box_graphics = Graphics::new_u8_rgba(&mut box_buffer, size, size).unwrap();
let mut check_graphics = Graphics::new_u8_rgba(&mut check_buffer, size, size).unwrap();
box_graphics.draw_rect(Rect::new((0, 0), (size - 1, size - 1)), stroke(WHITE));
check_graphics.draw_line((1, 4), (3, 5), WHITE);
check_graphics.draw_line((1, 4), (3, 6), WHITE);
check_graphics.draw_line((1, 5), (3, 7), WHITE);
check_graphics.draw_line((3, 5), (7, 1), WHITE);
check_graphics.draw_line((3, 6), (8, 1), WHITE);
check_graphics.draw_line((3, 7), (8, 2), WHITE);
[
check_graphics.copy_to_indexed_image(false).unwrap(),
box_graphics.copy_to_indexed_image(false).unwrap(),
]
}
}