use controls::{Button, Control, Label, Orientation, Root, Sizer, Slider, XY};
use serde_json::value::Value;
use failure::err_msg;
use failure::Error as FError;
use std::collections::BTreeMap;
use std::convert::TryInto;
pub enum Color {
Controls,
Labels,
Text,
Pressed,
Unpressed,
Background,
}
pub struct Gui {
pub title: String,
pub root_control: Option<Box<dyn Control>>,
sizerstack: Vec<Vec<i32>>,
colors: BTreeMap<String, String>,
}
impl Gui {
pub fn new_gui(title: String) -> Gui {
Gui {
title: title,
root_control: None,
sizerstack: Vec::new(),
colors: BTreeMap::new(),
}
}
pub fn to_root(self) -> Result<Root, FError> {
match self.root_control {
Some(rc) => {
if self.sizerstack.is_empty() {
let mut colors = serde_json::Map::new();
for (key,value) in self.colors {
colors.insert(key, Value::String(value));
};
Ok(Root {
title: self.title.clone(),
root_control: rc,
colors: colors,
})
} else {
Err(err_msg("there are still incomplete sizers!"))
}
}
None => Err(err_msg("no controls in the gui yet!")),
}
}
pub fn next_id(&self) -> Result<Vec<i32>, FError> {
match &self.root_control {
Some(rc) => match self.sizerstack.last() {
Some(id) => match get_control(id, &**rc) {
Some(c) => match c.sub_controls() {
Some(sc) => {
let mut nid = id.clone();
nid.push(sc.len().try_into().unwrap());
Ok(nid)
}
None => Err(err_msg(format!("element is not a sizer: {:?}", id))),
},
None => Err(err_msg(format!("element not found: {:?}", id))),
},
None => Err(err_msg(
"no active sizer and gui is not empty; can't assign a control id!",
)),
},
None => Ok(Vec::new()),
}
}
pub fn add_control(&mut self, control: Box<dyn Control>) -> Result<&mut Gui, FError> {
match &mut self.root_control {
None => {
self.root_control = Some(control);
Ok(self)
}
Some(rootcontrol) =>
{
match self.sizerstack.last() {
None => Err(err_msg("no active sizer, can't add new element!")),
Some(id) => {
match get_control_mut(id, &mut **rootcontrol) {
Some(c) => c.add_control(control),
None => (),
}
Ok(self)
}
}
}
}
}
pub fn add_button(&mut self, name: String, label: Option<String>) -> Result<&mut Gui, FError> {
let newbutton = Box::new(Button {
control_id: self.next_id()?,
name: String::from(name),
label: label,
pressed: false,
});
self.add_control(newbutton)
}
pub fn add_slider(
&mut self,
name: String,
label: Option<String>,
orientation: Orientation,
) -> Result<&mut Gui, FError> {
let newslider = Box::new(Slider {
control_id: self.next_id()?,
name: String::from(name),
label: label,
location: 0.5,
pressed: false,
orientation: orientation,
});
self.add_control(newslider)
}
pub fn add_xy(&mut self, name: String, label: Option<String>) -> Result<&mut Gui, FError> {
let newxy = Box::new(XY {
control_id: self.next_id()?,
name: String::from(name),
label: label,
location: (0.5, 0.5),
pressed: false,
});
self.add_control(newxy)
}
pub fn add_label(&mut self, name: String, label: String) -> Result<&mut Gui, FError> {
let newlabel = Box::new(Label {
control_id: self.next_id()?,
name: name,
label: label,
});
self.add_control(newlabel)
}
pub fn add_sizer(&mut self, orientation: Orientation, proportions: Option<Vec<f32>>) -> Result<&mut Gui, FError> {
let id = self.next_id()?;
let newsizer = Box::new(Sizer {
control_id: id.clone(),
controls: Vec::new(),
orientation: orientation,
proportions: proportions,
});
self.add_control(newsizer)?;
self.sizerstack.push(id);
Ok(self)
}
pub fn end_sizer(&mut self) -> Result<&mut Gui, FError> {
if self.sizerstack.is_empty() {
Err(err_msg(
"mismatched end_sizer() call; sizer stack is empty!",
))
} else {
self.sizerstack.pop();
Ok(self)
}
}
pub fn set_color(&mut self, color: Color, hexstring: &str) -> &mut Gui {
let cs = match color {
Color::Controls => "controlsColor",
Color::Labels => "labelsColor",
Color::Text => "textColor",
Color::Pressed => "pressedColor",
Color::Unpressed => "unpressedColor",
Color::Background => "backgroundColor",
};
self.colors.insert(cs.to_string(), hexstring.to_string());
self
}
}
fn get_control<'a>(id: &Vec<i32>, control: &'a dyn Control) -> Option<&'a dyn Control> {
if *id == *control.control_id() {
Some(control)
} else {
match control.sub_controls() {
Some(cs) => {
let mut ret = None;
for c in cs.iter() {
match get_control(id, &**c) {
Some(cr) => ret = Some(cr),
None => (),
};
}
ret
}
None => None,
}
}
}
fn get_control_mut<'a>(id: &Vec<i32>, control: &'a mut dyn Control) -> Option<&'a mut dyn Control> {
if *id == *control.control_id() {
Some(control)
} else {
match control.mut_sub_controls() {
Some(cs) => {
let mut ret = None;
for c in cs.iter_mut() {
match get_control_mut(id, &mut **c) {
Some(cr) => ret = Some(cr),
None => (),
};
}
ret
}
None => None,
}
}
}