feat(core): buttons allow usage of inverted icon

[no changelog]
tychovrahe/trbootloader/main_before
tychovrahe 1 year ago
parent a7adef79f9
commit 30c10d879e

@ -58,7 +58,16 @@ where
}
pub fn with_icon(pos: ButtonPos, image: Icon, styles: ButtonStyleSheet) -> Self {
Self::new(pos, ButtonContent::Icon(image), styles)
Self::new(pos, ButtonContent::Icon(image, None), styles)
}
pub fn with_icon_and_pressed(
pos: ButtonPos,
image: Icon,
pressed: Icon,
styles: ButtonStyleSheet,
) -> Self {
Self::new(pos, ButtonContent::Icon(image, Some(pressed)), styles)
}
pub fn content(&self) -> &ButtonContent<T> {
@ -74,7 +83,7 @@ where
/// Changing the icon content of the button.
pub fn set_icon(&mut self, image: Icon) {
self.content = ButtonContent::Icon(image);
self.content = ButtonContent::Icon(image, None);
}
/// Changing the text content of the button.
@ -121,7 +130,18 @@ where
};
let content_width = match &self.content {
ButtonContent::Text(text) => style.font.visible_text_width(text.as_ref()),
ButtonContent::Icon(icon) => icon.toif.width() - 1,
ButtonContent::Icon(icon, icon_pressed) => {
let width = if self.state == State::Pressed {
if let Some(icon_pressed) = icon_pressed {
icon_pressed.toif.width()
} else {
icon.toif.width()
}
} else {
icon.toif.width()
};
width - 1
}
};
content_width + 2 * outline
};
@ -131,11 +151,19 @@ where
// drawing the icon in active (black on white) state
let button_height = match &self.content {
ButtonContent::Text(_) => theme::BUTTON_HEIGHT,
ButtonContent::Icon(icon) => {
ButtonContent::Icon(icon, icon_pressed) => {
if style.with_outline {
theme::BUTTON_HEIGHT
} else {
icon.toif.height()
if self.state == State::Pressed {
if let Some(icon_pressed) = icon_pressed {
icon_pressed.toif.height()
} else {
icon.toif.height()
}
} else {
icon.toif.height()
}
}
}
};
@ -246,7 +274,22 @@ where
background_color,
);
}
ButtonContent::Icon(icon) => {
ButtonContent::Icon(icon, pressed) => {
let mut fg_color = text_color;
let mut bg_color = background_color;
let icon = if self.state == State::Pressed {
// Inverse colors for pressed state
if let Some(pressed) = pressed {
fg_color = background_color;
bg_color = text_color;
pressed
} else {
icon
}
} else {
icon
};
if style.with_outline {
// Accounting for the 8*8 icon with empty left column and bottom row
// (which fits the outline nicely and symmetrically)
@ -255,21 +298,13 @@ where
} else {
// Positioning the icon in the corresponding corner/center
match self.pos {
ButtonPos::Left => icon.draw(
area.bottom_left(),
BOTTOM_LEFT,
text_color,
background_color,
),
ButtonPos::Right => icon.draw(
area.bottom_right(),
BOTTOM_RIGHT,
text_color,
background_color,
),
ButtonPos::Middle => {
icon.draw(area.center(), CENTER, text_color, background_color)
ButtonPos::Left => {
icon.draw(area.bottom_left(), BOTTOM_LEFT, fg_color, bg_color)
}
ButtonPos::Right => {
icon.draw(area.bottom_right(), BOTTOM_RIGHT, fg_color, bg_color)
}
ButtonPos::Middle => icon.draw(area.center(), CENTER, bg_color, bg_color),
}
}
}
@ -285,7 +320,7 @@ enum State {
pub enum ButtonContent<T> {
Text(T),
Icon(Icon),
Icon(Icon, Option<Icon>),
}
pub struct ButtonStyleSheet {
@ -354,6 +389,7 @@ impl ButtonStyleSheet {
pub struct ButtonDetails<T> {
pub text: Option<T>,
pub icon: Option<Icon>,
pub pressed_icon: Option<Icon>,
pub duration: Option<Duration>,
pub with_outline: bool,
pub with_arms: bool,
@ -367,6 +403,7 @@ impl<T> ButtonDetails<T> {
Self {
text: Some(text),
icon: None,
pressed_icon: None,
duration: None,
with_outline: true,
with_arms: false,
@ -380,6 +417,7 @@ impl<T> ButtonDetails<T> {
Self {
text: None,
icon: Some(icon),
pressed_icon: None,
duration: None,
with_outline: true,
with_arms: false,
@ -398,6 +436,7 @@ impl<T> ButtonDetails<T> {
Self::icon(Icon::new(theme::ICON_CANCEL))
.with_no_outline()
.with_offset(Offset::new(2, -2))
.with_pressed_icon(Icon::new(theme::ICON_CANCEL_INVERTED))
}
/// Left arrow to signal going back. No outline.
@ -465,6 +504,12 @@ impl<T> ButtonDetails<T> {
self
}
/// Second icon for the pressed state
pub fn with_pressed_icon(mut self, icon: Icon) -> Self {
self.pressed_icon = Some(icon);
self
}
/// Specific duration of the hold-to-confirm.
pub fn with_duration(mut self, duration: Duration) -> Self {
self.duration = Some(duration);
@ -563,11 +608,15 @@ where
}
/// Left cancel, armed text and icon.
pub fn cancel_armed_icon(middle: T, right: Icon) -> Self {
pub fn cancel_armed_icon(middle: T, right: (Icon, Option<Icon>)) -> Self {
let mut right_btn = ButtonDetails::icon(right.0).with_no_outline();
if let Some(pressed) = right.1 {
right_btn = right_btn.with_pressed_icon(pressed);
}
Self::new(
Some(ButtonDetails::cancel_icon()),
Some(ButtonDetails::armed_text(middle)),
Some(ButtonDetails::icon(right).with_no_outline()),
Some(right_btn),
)
}
@ -908,7 +957,8 @@ where
t.component("Button");
match &self.content {
ButtonContent::Text(text) => t.string("text", text.as_ref()),
ButtonContent::Icon(_) => t.bool("icon", true),
ButtonContent::Icon(_, None) => t.bool("icon", true),
ButtonContent::Icon(_, Some(_)) => t.bool("icon (with pressed state)", true),
}
}
}

@ -76,7 +76,11 @@ where
if let Some(text) = btn_details.text.clone() {
Button::with_text(pos, text, btn_details.style())
} else if let Some(icon) = btn_details.icon {
Button::with_icon(pos, icon, btn_details.style())
if let Some(pressed) = btn_details.pressed_icon {
Button::with_icon_and_pressed(pos, icon, pressed, btn_details.style())
} else {
Button::with_icon(pos, icon, btn_details.style())
}
} else {
panic!("ButtonContainer: no text or icon provided");
}
@ -473,9 +477,12 @@ where
ButtonContent::Text(text) => {
t.string("text", text.as_ref());
}
ButtonContent::Icon(_cursor) => {
ButtonContent::Icon(_cursor, None) => {
t.bool("icon", true);
}
ButtonContent::Icon(_cursor, Some(_)) => {
t.bool("icon (with pressed state)", true);
}
}
} else if let ButtonType::HoldToConfirm(htc) = &self.button_type {
t.string("text", htc.get_text().as_ref());

Loading…
Cancel
Save