use std::num::NonZero;
use unicode_width::UnicodeWidthStr;
use crate::canvas::*;
use super::*;
pub struct Label {
has_focus: bool,
text: String,
text_alignment: HorizontalAlignment,
base: WidgetBase,
focus_color: Option<Color>,
}
impl Default for Label {
fn default() -> Self {
let mut s = Self {
has_focus: false,
text: String::default(),
text_alignment: HorizontalAlignment::Center,
base: WidgetBase::default(),
focus_color: None,
};
s.base.constraints.y.min = NonZero::<TSize>::MIN;
s.base.constraints.y.max = Size::Fixed(NonZero::<TSize>::MIN);
s
}
}
impl Label {
pub fn set_text_alignment(&mut self, alignment: HorizontalAlignment) {
self.text_alignment = alignment;
}
pub fn set_text(&mut self, text: &str) {
self.text.clear();
self.text.push_str(text);
let old = self.base.constraints.x.max;
self.base.constraints.x.max =
Size::Fixed(NonZero::new(self.text.width() as TSize).unwrap_or(NonZero::<TSize>::MIN));
if old != self.base.constraints.x.max {
self.provoke_changed_property(WindowProperty::Size);
}
}
pub fn get_text(&self) -> &str {
&self.text
}
pub fn set_focus_color(&mut self, color: Option<Color>) {
self.focus_color = color;
}
}
impl Window for Label {
fn render(&self, canvas: &mut Canvas) {
let fg = match self.base.enabled {
true => match self.has_focus {
true => self.focus_color,
false => None,
},
false => self.base.colors.disabled,
}
.or(self.base.colors.base_fg);
let mut row = canvas.get_row_variable_width(TSize::MIN).unwrap();
let text_w = self.text.width() as TSize;
match self.text_alignment {
HorizontalAlignment::Left => {}
HorizontalAlignment::Center => {
row.skip(row.width().checked_sub(text_w).unwrap_or_default() / 2);
}
HorizontalAlignment::Right => {
row.skip(row.width().checked_sub(text_w).unwrap_or_default());
}
}
row.add_string(
&self.text,
fg,
self.base.colors.base_bg,
Style::default(),
Some(VariableWidthGlyphRow::DOT3_REPLACEMENT),
)
.unwrap()
}
fn handle_event(&mut self, event: &mut WindowEvent) {
match event.raw() {
Event::FocusGained => self.has_focus = true,
Event::FocusLost => self.has_focus = false,
_ => {}
}
}
fn is_enabled(&self) -> bool {
self.base.enabled
}
}
impl WindowLayout for Label {
fn desired_size(&self, available_size: TPoint) -> TPoint {
self.base.desired_size(available_size)
}
fn alignment(&self) -> (super::HorizontalAlignment, super::VerticalAlignment) {
self.base.alignment
}
fn margin(&self) -> Thickness {
self.base.margin
}
fn border(&self) -> BorderStyle {
self.base.border
}
fn is_visible(&self) -> bool {
self.base.visibility
}
}
impl HasWindowUID for Label {
fn uid(&self) -> WindowUID {
self.base.uid
}
}
impl Widget for Label {
fn set_alignment(&mut self, horizontal: HorizontalAlignment, vertical: VerticalAlignment) {
self.base.alignment = (horizontal, vertical);
self.provoke_changed_property(WindowProperty::Alignment);
}
fn set_visibility(&mut self, visibility: bool) {
self.base.visibility = visibility;
self.provoke_changed_property(WindowProperty::IsVisible);
}
fn set_width(&mut self, width: super::Size) {
self.base.size.x = width;
self.provoke_changed_property(WindowProperty::Size);
}
fn set_height(&mut self, _: super::Size) {}
fn set_margin(&mut self, margin: Thickness) {
self.base.margin = margin;
self.provoke_changed_property(WindowProperty::Margin);
}
fn set_border(&mut self, border: BorderStyle) {
self.base.border = border;
self.provoke_changed_property(WindowProperty::Border);
}
fn set_enabled_state(&mut self, is_enabled: bool) {
self.base.enabled = is_enabled;
}
fn set_width_constraint(&mut self, width: SizeConstraint) {
self.base.constraints.x = width;
self.provoke_changed_property(WindowProperty::Size);
}
fn set_height_constraint(&mut self, _: SizeConstraint) {}
}
impl WidgetColors for Label {
fn set_disabled_color(&mut self, color: Option<Color>) {
self.base.colors.disabled = color;
}
fn set_base_fg_color(&mut self, color: Option<Color>) {
self.base.colors.base_fg = color;
}
fn set_base_bg_color(&mut self, color: Option<Color>) {
self.base.colors.base_bg = color;
}
}