Add Field type for FormWidgets

embed
Manos Pitsidianakis 2019-03-01 14:01:06 +02:00
parent e285d1006b
commit f93310d424
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
2 changed files with 157 additions and 46 deletions

View File

@ -20,6 +20,7 @@
*/ */
use super::*; use super::*;
use fnv::FnvHashMap;
mod contact_list; mod contact_list;
@ -128,7 +129,13 @@ impl Component for ContactManager {
match self.form.buttons_result() { match self.form.buttons_result() {
None => {}, None => {},
Some(true) => { Some(true) => {
let mut new_card = Card::from(std::mem::replace(&mut self.form, FormWidget::default()).collect().unwrap()); let mut fields = std::mem::replace(&mut self.form, FormWidget::default()).collect().unwrap();
let fields: FnvHashMap<String, String> = fields.into_iter().map(|(s, v)| {
(s, match v {
Field::Text(v, _) => v,
Field::Choice(mut v, c) => v.remove(c),
})}).collect();
let mut new_card = Card::from(fields);
new_card.set_id(*self.card.id()); new_card.set_id(*self.card.id());
context.accounts[self.account_pos].address_book.add_card(new_card); context.accounts[self.account_pos].address_book.add_card(new_card);
context.replies.push_back(UIEvent { context.replies.push_back(UIEvent {

View File

@ -8,12 +8,7 @@ enum FormFocus {
TextInput, TextInput,
} }
/* type Cursor = usize;
enum Field {
Text(String),
Choice(Vec<String>),
}
*/
impl Default for FormFocus { impl Default for FormFocus {
fn default() -> FormFocus { fn default() -> FormFocus {
@ -21,9 +16,132 @@ impl Default for FormFocus {
} }
} }
#[derive(Debug, )]
pub enum Field {
Text(String, Cursor),
Choice(Vec<String>, Cursor),
}
use Field::*;
impl Default for Field {
fn default() -> Field {
Field::Text(String::new(), 0)
}
}
impl Field {
fn as_str(&self) -> &str {
match self {
Text(ref s, _) => {
s
},
Choice(ref v, cursor) => {
if v.is_empty() {
""
} else {
v[*cursor].as_str()
}
}
}
}
fn draw_cursor(&self, grid: &mut CellBuffer, area: Area) {
let upper_left = upper_left!(area);
match self {
Text(_, cursor) => {
change_colors(grid, (pos_inc(upper_left, (*cursor, 0)), (pos_inc(upper_left, (*cursor, 0)))), Color::Default, Color::Byte(248));
},
Choice(_, cursor) => {
}
}
}
}
impl Component for Field {
fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
write_string_to_grid(
self.as_str(),
grid,
Color::Default,
Color::Default,
area,
false);
}
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
match event.event_type {
UIEventType::InsertInput(Key::Right) => {
match self {
Text(ref s, ref mut cursor) => {
if *cursor < s.len().saturating_sub(1) {
*cursor += 1;
}
},
Choice(ref vec, ref mut cursor) => {
*cursor = if *cursor == vec.len().saturating_sub(1) {
0
} else {
*cursor + 1
};
}
}
},
UIEventType::InsertInput(Key::Left) => {
match self {
Text(_, ref mut cursor) => {
if *cursor == 0 {
return false;
} else {
*cursor -= 1;
}
},
Choice(_, ref mut cursor) => {
if *cursor == 0 {
return false;
} else {
*cursor -= 1;
}
}
}
},
UIEventType::InsertInput(Key::Char(k)) => {
if let Text(ref mut s, ref mut cursor) = self {
s.insert(*cursor, k);
*cursor += 1;
}
},
UIEventType::InsertInput(Key::Backspace) => {
if let Text(ref mut s, ref mut cursor) = self {
if *cursor > 0 {
*cursor -= 1;
s.pop();
}
}
},
_ => {
return false;
}
}
self.set_dirty();
true
}
fn is_dirty(&self) -> bool {
true
}
fn set_dirty(&mut self) {}
}
impl fmt::Display for Field {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Display::fmt("field", f)
}
}
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct FormWidget { pub struct FormWidget {
fields: FnvHashMap<String, String>, fields: FnvHashMap<String, Field>,
cursors: Vec<usize>, cursors: Vec<usize>,
layout: Vec<String>, layout: Vec<String>,
buttons: ButtonWidget<bool>, buttons: ButtonWidget<bool>,
@ -53,20 +171,26 @@ impl FormWidget {
self.buttons.push(val); self.buttons.push(val);
} }
pub fn push_choices(&mut self, value: (String, Vec<String>)) {
self.field_name_max_length = std::cmp::max(self.field_name_max_length, value.0.len());
self.layout.push(value.0.clone());
self.fields.insert(value.0, Choice(value.1, 0));
self.cursors.push(0);
}
pub fn push(&mut self, value: (String, String)) { pub fn push(&mut self, value: (String, String)) {
self.field_name_max_length = std::cmp::max(self.field_name_max_length, value.0.len()); self.field_name_max_length = std::cmp::max(self.field_name_max_length, value.0.len());
self.layout.push(value.0.clone()); self.layout.push(value.0.clone());
self.fields.insert(value.0, value.1); self.fields.insert(value.0, Text(value.1, 0));
self.cursors.push(0); self.cursors.push(0);
} }
pub fn insert(&mut self, index: usize, value: (String, String)) { pub fn insert(&mut self, index: usize, value: (String, Field)) {
self.layout.insert(index, value.0.clone()); self.layout.insert(index, value.0.clone());
self.fields.insert(value.0, value.1); self.fields.insert(value.0, value.1);
self.cursors.insert(index, 0); self.cursors.insert(index, 0);
} }
pub fn collect(self) -> Option<FnvHashMap<String, String>> { pub fn collect(self) -> Option<FnvHashMap<String, Field>> {
if let Some(true) = self.buttons_result() { if let Some(true) = self.buttons_result() {
Some(self.fields) Some(self.fields)
} else { } else {
@ -84,7 +208,7 @@ impl Component for FormWidget {
let bottom_right = bottom_right!(area); let bottom_right = bottom_right!(area);
for (i, k) in self.layout.iter().enumerate() { for (i, k) in self.layout.iter().enumerate() {
let v = &self.fields[k]; let v = self.fields.get_mut(k).unwrap();
write_string_to_grid( write_string_to_grid(
k.as_str(), k.as_str(),
grid, grid,
@ -93,23 +217,16 @@ impl Component for FormWidget {
(pos_inc(upper_left, (1, i * 2)), set_y(bottom_right, i * 2 + get_y(upper_left))), (pos_inc(upper_left, (1, i * 2)), set_y(bottom_right, i * 2 + get_y(upper_left))),
false, false,
); );
write_string_to_grid( v.draw(grid,
v.as_str(), (pos_inc(upper_left, (self.field_name_max_length + 3, i * 2)), set_y(bottom_right, i * 2 + get_y(upper_left))), context);
grid,
Color::Default,
Color::Default,
(pos_inc(upper_left, (self.field_name_max_length + 3, i * 2)), set_y(bottom_right, i * 2 + get_y(upper_left))),
false,
);
if i == self.cursor { if i == self.cursor {
if self.focus == FormFocus::Fields { if self.focus == FormFocus::Fields {
change_colors(grid, (pos_inc(upper_left, (0, i * 2)), set_y(bottom_right, i * 2 + get_y(upper_left))), Color::Default, Color::Byte(246)); change_colors(grid, (pos_inc(upper_left, (0, i * 2)), set_y(bottom_right, i * 2 + get_y(upper_left))), Color::Default, Color::Byte(246));
} }
if self.focus == FormFocus::TextInput { if self.focus == FormFocus::TextInput {
change_colors(grid, v.draw_cursor(grid,
(pos_inc(upper_left, (self.field_name_max_length + 3 + self.cursors[i], i * 2)), (pos_inc(upper_left, (self.field_name_max_length + 3 , i * 2)),
(get_x(upper_left) + self.field_name_max_length + 3 + self.cursors[i], i * 2 + get_y(upper_left))), (get_x(upper_left) + self.field_name_max_length + 3, i * 2 + get_y(upper_left))));
Color::Default, Color::Byte(248));
} }
} }
} }
@ -148,19 +265,17 @@ impl Component for FormWidget {
}); });
}, },
UIEventType::InsertInput(Key::Right) if self.focus == FormFocus::TextInput => { UIEventType::InsertInput(Key::Right) if self.focus == FormFocus::TextInput => {
if self.cursors[self.cursor] < self.fields[&self.layout[self.cursor]].len().saturating_sub(1) { let field = self.fields.get_mut(&self.layout[self.cursor]).unwrap();
self.cursors[self.cursor] += 1; field.process_event(event, context);
}
}, },
UIEventType::InsertInput(Key::Left) if self.focus == FormFocus::TextInput => { UIEventType::InsertInput(Key::Left) if self.focus == FormFocus::TextInput => {
if self.cursors[self.cursor] == 0 { let field = self.fields.get_mut(&self.layout[self.cursor]).unwrap();
if !field.process_event(event, context) {
self.focus = FormFocus::Fields; self.focus = FormFocus::Fields;
context.replies.push_back(UIEvent { context.replies.push_back(UIEvent {
id: 0, id: 0,
event_type: UIEventType::ChangeMode(UIMode::Normal), event_type: UIEventType::ChangeMode(UIMode::Normal),
}); });
} else {
self.cursors[self.cursor] = self.cursors[self.cursor] - 1;
} }
}, },
UIEventType::ChangeMode(UIMode::Normal) if self.focus == FormFocus::TextInput => { UIEventType::ChangeMode(UIMode::Normal) if self.focus == FormFocus::TextInput => {
@ -168,22 +283,11 @@ impl Component for FormWidget {
}, },
UIEventType::InsertInput(Key::Char(k)) if self.focus == FormFocus::TextInput => { UIEventType::InsertInput(Key::Char(k)) if self.focus == FormFocus::TextInput => {
let field = self.fields.get_mut(&self.layout[self.cursor]).unwrap(); let field = self.fields.get_mut(&self.layout[self.cursor]).unwrap();
field.insert(self.cursors[self.cursor], k); field.process_event(event, context);
self.cursors[self.cursor] += 1;
}, },
UIEventType::InsertInput(Key::Backspace) if self.focus == FormFocus::TextInput => { UIEventType::InsertInput(Key::Backspace) if self.focus == FormFocus::TextInput => {
let field = self.fields.get_mut(&self.layout[self.cursor]).unwrap(); let field = self.fields.get_mut(&self.layout[self.cursor]).unwrap();
match self.cursors[self.cursor] { field.process_event(event, context);
i if i == 0 => {},
i if i == field.len() => {
field.pop();
self.cursors[self.cursor] -= 1;
},
_ => {
field.remove(self.cursors[self.cursor]);
self.cursors[self.cursor] -= 1;
}
}
}, },
_ => { _ => {
return false; return false;