use crate::{CheckButton, Label, PopupEvent, Slider, SliderEvent, common::*};
use crate::{Dropdown, DropdownEvent, Textbox, TextboxEvent, CheckboxEvent};
#[derive(PartialEq)]
pub enum LengthBoxEvent {
SetType(Units),
SetValue(f32, bool),
Reset(bool),
}
pub struct LengthBox {
name: String,
slider: Entity,
textbox: Entity,
dropdown: Entity,
stretch: f32,
percentage: f32,
pixels: f32,
units: Units,
pixels_max: f32,
check_auto: Entity,
check_stretch: Entity,
check_percentage: Entity,
check_pixels: Entity,
on_changed: Option<Box<dyn Fn(&mut Self, &mut State, Entity)>>,
}
impl LengthBox {
pub fn new(name: &str) -> Self {
LengthBox {
name: name.to_owned(),
slider: Entity::null(),
textbox: Entity::null(),
dropdown: Entity::null(),
stretch: 1.0,
percentage: 0.0,
pixels: 0.0,
units: Units::Auto,
pixels_max: 20.0,
check_auto: Entity::null(),
check_stretch: Entity::null(),
check_percentage: Entity::null(),
check_pixels: Entity::null(),
on_changed: None,
}
}
pub fn with_init(mut self, init: Units) -> Self {
self.units = init;
match self.units {
Units::Stretch(val) => {
self.stretch = val;
}
Units::Pixels(val) => {
self.pixels = val;
}
Units::Percentage(val) => {
self.percentage = val;
}
_=> {}
}
self
}
pub fn on_changed<F>(mut self, callback: F) -> Self
where F: 'static + Fn(&mut Self, &mut State, Entity)
{
self.on_changed = Some(Box::new(callback));
self
}
pub fn with_pixels_max(mut self, max: f32) -> Self {
self.pixels_max = max;
self
}
pub fn value(&self) -> Units {
match self.units {
Units::Auto => {
Units::Auto
}
Units::Stretch(_) => {
Units::Stretch(self.stretch)
}
Units::Percentage(_) => {
Units::Percentage(self.percentage)
}
Units::Pixels(_) => {
Units::Pixels(self.pixels)
}
}
}
}
impl Widget for LengthBox {
type Ret = Entity;
type Data = Units;
fn on_build(&mut self, state: &mut State, entity: Entity) -> Self::Ret {
entity.set_layout_type(state, LayoutType::Row).set_col_between(state, Pixels(10.0));
self.slider = Slider::new()
.with_min(0.0)
.with_max(self.pixels_max)
.on_changing(|data, state, slider|{
slider.emit(state, LengthBoxEvent::SetValue(data.value, true));
})
.build(state, entity, |builder|
builder
.set_child_top(Auto)
.set_child_bottom(Auto)
);
Label::new(&self.name).build(state, self.slider, |builder|
builder
.set_position_type(PositionType::SelfDirected)
.set_child_top(Stretch(1.0))
.set_child_bottom(Stretch(1.0))
.set_child_left(Pixels(5.0))
.set_hoverable(false)
.set_focusable(false)
);
self.textbox = Textbox::new("auto")
.on_submit(|data, state, textbox|{
if &data.text == "auto" {
textbox.emit(state, LengthBoxEvent::SetType(Units::Auto));
textbox.emit(state, LengthBoxEvent::Reset(true));
} else {
if let Some(last_char) = data.text.chars().last() {
let mut val_text = data.text.as_ref();
let mut val_type = Units::Auto;
match last_char {
's' => {
val_text = &data.text[0..data.text.len()-1];
val_type = Units::Stretch(0.0);
}
'%' => {
val_text = &data.text[0..data.text.len()-1];
val_type = Units::Percentage(0.0);
}
'x' => {
if let Some(previous_char) = data.text[0..data.text.len()-1].chars().last() {
if previous_char == 'p' {
val_text = &data.text[0..data.text.len()-2];
val_type = Units::Pixels(0.0);
}
}
}
_=> {},
}
if let Ok(val) = val_text.parse::<f32>() {
if val_type != Units::Auto {
textbox.emit(state, LengthBoxEvent::SetType(val_type));
} else {
textbox.emit(state, LengthBoxEvent::SetType(Units::Pixels(val)));
}
textbox.emit(state, LengthBoxEvent::SetValue(val, true));
} else {
textbox.emit(state, LengthBoxEvent::Reset(true));
}
} else {
textbox.emit(state, LengthBoxEvent::Reset(true));
}
}
})
.build(state, entity, |builder|
builder
.set_width(Pixels(80.0))
.set_child_space(Stretch(1.0))
);
self.dropdown = Dropdown::<()>::new("auto")
.build(state, entity, |builder| {
builder
.set_width(Pixels(80.0))
.set_child_left(Pixels(0.0))
.set_child_right(Pixels(0.0))
.class("unit")
});
self.dropdown.set_width(state, Pixels(80.0));
self.check_auto = CheckButton::with_label("auto")
.on_checked(|_, state, button|{
println!("This thing here: {}", button);
button.emit(state, LengthBoxEvent::SetType(Units::Auto));
button.emit(state, LengthBoxEvent::Reset(true));
button.emit(state, PopupEvent::Close);
button.emit(state, DropdownEvent::SetText("auto".to_string()));
})
.build(state, self.dropdown, |builder|
builder
);
entity.emit_to(state, self.check_auto, CheckboxEvent::Check);
self.check_stretch = CheckButton::with_label("stretch")
.on_checked(|_, state, button|{
button.emit(state, LengthBoxEvent::SetType(Units::Stretch(0.0)));
button.emit(state, LengthBoxEvent::Reset(true));
button.emit(state, PopupEvent::Close);
button.emit(state, DropdownEvent::SetText("stretch".to_string()));
})
.build(state, self.dropdown, |builder|
builder
);
self.check_percentage = CheckButton::with_label("%")
.on_checked(|_, state, button|{
button.emit(state, LengthBoxEvent::SetType(Units::Percentage(0.0)));
button.emit(state, LengthBoxEvent::Reset(true));
button.emit(state, PopupEvent::Close);
button.emit(state, DropdownEvent::SetText("%".to_string()));
})
.build(state, self.dropdown, |builder|
builder
);
self.check_pixels = CheckButton::with_label("px")
.on_checked(|_, state, button|{
button.emit(state, LengthBoxEvent::SetType(Units::Pixels(0.0)));
button.emit(state, LengthBoxEvent::Reset(true));
button.emit(state, PopupEvent::Close);
button.emit(state, DropdownEvent::SetText("px".to_string()));
})
.build(state, self.dropdown, |builder|
builder
);
entity.set_element(state, "length_box");
entity
}
fn on_update(&mut self, state: &mut State, entity: Entity, data: &Self::Data) {
if *data != self.value() {
entity.emit(state, LengthBoxEvent::SetType(*data));
match data {
Units::Auto => {
entity.emit_to(state, entity, LengthBoxEvent::SetValue(0.0, false));
}
Units::Stretch(val) | Units::Percentage(val) | Units::Pixels(val) => {
entity.emit_to(state, entity, LengthBoxEvent::SetValue(*val, false));
}
}
}
}
fn on_event(&mut self, state: &mut State, entity: Entity, event: &mut Event) {
if let Some(lengthbox_event) = event.message.downcast() {
match lengthbox_event {
LengthBoxEvent::SetValue(val, flag) => {
match self.units {
Units::Auto => {
entity.emit_to(state, self.dropdown, DropdownEvent::SetText("-".to_string()));
entity.emit_to(state, self.textbox, TextboxEvent::SetValue("auto".to_string()));
entity.emit_to(state, self.slider, SliderEvent::SetValue(0.0));
self.check_auto.emit(state, CheckboxEvent::Check);
self.check_auto.emit(state, DropdownEvent::SetText("auto".to_string()));
self.slider.set_disabled(state, true);
}
Units::Stretch(_) => {
self.stretch = *val;
entity.emit_to(state, self.dropdown, DropdownEvent::SetText("stretch".to_string()));
entity.emit_to(state, self.textbox, TextboxEvent::SetValue(format!("{:.0}s", val)));
entity.emit_to(state, self.slider, SliderEvent::SetMax(10.0));
entity.emit_to(state, self.slider, SliderEvent::SetValue(*val));
self.check_stretch.emit(state, CheckboxEvent::Check);
self.check_stretch.emit(state, DropdownEvent::SetText("stretch".to_string()));
self.slider.set_disabled(state, false);
}
Units::Percentage(_) => {
self.percentage = *val;
entity.emit_to(state, self.dropdown, DropdownEvent::SetText("%".to_string()));
entity.emit_to(state, self.textbox, TextboxEvent::SetValue(format!("{:.0}%", val)));
entity.emit_to(state, self.slider, SliderEvent::SetMax(100.0));
entity.emit_to(state, self.slider, SliderEvent::SetValue(*val));
self.check_percentage.emit(state, CheckboxEvent::Check);
self.check_percentage.emit(state, DropdownEvent::SetText("%".to_string()));
self.slider.set_disabled(state, false);
}
Units::Pixels(_) => {
self.pixels = *val;
entity.emit_to(state, self.dropdown, DropdownEvent::SetText("px".to_string()));
entity.emit_to(state, self.textbox, TextboxEvent::SetValue(format!("{:.0}px", val)));
entity.emit_to(state, self.slider, SliderEvent::SetMax(self.pixels_max));
entity.emit_to(state, self.slider, SliderEvent::SetValue(*val));
self.check_pixels.emit(state, CheckboxEvent::Check);
self.check_pixels.emit(state, DropdownEvent::SetText("px".to_string()));
self.slider.set_disabled(state, false);
}
}
if *flag {
if let Some(callback) = self.on_changed.take() {
(callback)(self, state, entity);
self.on_changed = Some(callback);
}
}
event.consume();
}
LengthBoxEvent::SetType(units) => {
self.units = *units;
event.consume();
}
LengthBoxEvent::Reset(flag) => {
match self.units {
Units::Auto => {
entity.emit_to(state, entity, LengthBoxEvent::SetValue(0.0, *flag));
}
Units::Stretch(_) => {
entity.emit_to(state, entity, LengthBoxEvent::SetValue(self.stretch, *flag));
}
Units::Percentage(_) => {
entity.emit_to(state, entity, LengthBoxEvent::SetValue(self.percentage, *flag));
}
Units::Pixels(_) => {
entity.emit_to(state, entity, LengthBoxEvent::SetValue(self.pixels, *flag));
}
}
event.consume();
}
}
}
}
}