diff --git a/src/components/contacts.rs b/src/components/contacts.rs index c01c89a6..b3e2a95c 100644 --- a/src/components/contacts.rs +++ b/src/components/contacts.rs @@ -40,7 +40,7 @@ pub struct ContactManager { parent_id: ComponentId, pub card: Card, mode: ViewMode, - form: FormWidget, + form: FormWidget, account_pos: usize, content: CellBuffer, theme_default: ThemeAttribute, @@ -118,24 +118,30 @@ impl ContactManager { ); } - self.form = FormWidget::new("Save".into()); + self.form = FormWidget::new(("Save".into(), true)); self.form.add_button(("Cancel(Esc)".into(), false)); self.form - .push(("NAME".into(), self.card.name().to_string())); + .push(("NAME".into(), self.card.name().to_string().into())); self.form.push(( "ADDITIONAL NAME".into(), - self.card.additionalname().to_string(), + self.card.additionalname().to_string().into(), + )); + self.form.push(( + "NAME PREFIX".into(), + self.card.name_prefix().to_string().into(), + )); + self.form.push(( + "NAME SUFFIX".into(), + self.card.name_suffix().to_string().into(), )); self.form - .push(("NAME PREFIX".into(), self.card.name_prefix().to_string())); + .push(("E-MAIL".into(), self.card.email().to_string().into())); self.form - .push(("NAME SUFFIX".into(), self.card.name_suffix().to_string())); + .push(("URL".into(), self.card.url().to_string().into())); self.form - .push(("E-MAIL".into(), self.card.email().to_string())); - self.form.push(("URL".into(), self.card.url().to_string())); - self.form.push(("KEY".into(), self.card.key().to_string())); + .push(("KEY".into(), self.card.key().to_string().into())); for (k, v) in self.card.extra_properties() { - self.form.push((k.to_string(), v.to_string())); + self.form.push((k.to_string().into(), v.to_string().into())); } } @@ -209,10 +215,10 @@ impl Component for ContactManager { .into_iter() .map(|(s, v)| { ( - s, + s.to_string(), match v { Field::Text(v, _) => v.as_str().to_string(), - Field::Choice(mut v, c) => v.remove(c), + Field::Choice(mut v, c) => v.remove(c).to_string(), }, ) }) diff --git a/src/components/mail/compose.rs b/src/components/mail/compose.rs index 31cbf5b5..a29bad49 100644 --- a/src/components/mail/compose.rs +++ b/src/components/mail/compose.rs @@ -78,7 +78,7 @@ pub struct Composer { pager: Pager, draft: Draft, - form: FormWidget, + form: FormWidget, mode: ViewMode, @@ -403,7 +403,7 @@ impl Composer { fn update_form(&mut self) { let old_cursor = self.form.cursor(); - self.form = FormWidget::new("Save".into()); + self.form = FormWidget::new(("Save".into(), true)); self.form.hide_buttons(); self.form.set_cursor(old_cursor); let headers = self.draft.headers(); @@ -412,7 +412,7 @@ impl Composer { if k == "To" || k == "Cc" || k == "Bcc" { self.form.push_cl(( k.into(), - headers[k].to_string(), + headers[k].to_string().into(), Box::new(move |c, term| { let book: &AddressBook = &c.accounts[&account_hash].address_book; let results: Vec = book.search(term); @@ -423,7 +423,7 @@ impl Composer { }), )); } else { - self.form.push((k.into(), headers[k].to_string())); + self.form.push((k.into(), headers[k].to_string().into())); } } } diff --git a/src/components/utilities/widgets.rs b/src/components/utilities/widgets.rs index 363bf37b..0b17d24e 100644 --- a/src/components/utilities/widgets.rs +++ b/src/components/utilities/widgets.rs @@ -20,6 +20,7 @@ */ use super::*; +use std::borrow::Cow; use std::collections::HashMap; type AutoCompleteFn = Box Vec + Send + Sync>; @@ -41,7 +42,7 @@ impl Default for FormFocus { pub enum Field { Text(UText, Option<(AutoCompleteFn, AutoComplete)>), - Choice(Vec, Cursor), + Choice(Vec>, Cursor), } impl Debug for Field { @@ -69,7 +70,7 @@ impl Field { if v.is_empty() { "" } else { - v[*cursor].as_str() + v[*cursor].as_ref() } } } @@ -89,7 +90,7 @@ impl Field { pub fn into_string(self) -> String { match self { Text(s, _) => s.into_string(), - Choice(mut v, cursor) => v.remove(cursor), + Choice(mut v, cursor) => v.remove(cursor).to_string(), } } @@ -288,18 +289,35 @@ impl fmt::Display for Field { f, "{}", match self { - Text(ref s, _) => s.as_str().to_string(), - Choice(ref v, ref cursor) => v[*cursor].clone(), + Text(ref s, _) => s.as_str(), + Choice(ref v, ref cursor) => v[*cursor].as_ref(), } ) } } +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum FormButtonActions { + Accept, + Reset, + Cancel, + Other(&'static str), +} + +impl Default for FormButtonActions { + fn default() -> Self { + FormButtonActions::Cancel + } +} + #[derive(Debug, Default)] -pub struct FormWidget { - fields: HashMap, - layout: Vec, - buttons: ButtonWidget, +pub struct FormWidget +where + T: 'static + std::fmt::Debug + Copy + Default + Send + Sync, +{ + fields: HashMap, Field>, + layout: Vec>, + buttons: ButtonWidget, field_name_max_length: usize, cursor: usize, @@ -309,16 +327,16 @@ pub struct FormWidget { id: ComponentId, } -impl fmt::Display for FormWidget { +impl fmt::Display for FormWidget { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt("", f) } } -impl FormWidget { - pub fn new(action: String) -> FormWidget { +impl FormWidget { + pub fn new(action: (Cow<'static, str>, T)) -> FormWidget { FormWidget { - buttons: ButtonWidget::new((action, true)), + buttons: ButtonWidget::new(action), focus: FormFocus::Fields, hide_buttons: false, id: ComponentId::new_v4(), @@ -344,16 +362,16 @@ impl FormWidget { self.layout.len() } - pub fn add_button(&mut self, val: (String, bool)) { + pub fn add_button(&mut self, val: (Cow<'static, str>, T)) { self.buttons.push(val); } - pub fn push_choices(&mut self, value: (String, Vec)) { + pub fn push_choices(&mut self, value: (Cow<'static, str>, Vec>)) { 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)); } - pub fn push_cl(&mut self, value: (String, String, AutoCompleteFn)) { + pub fn push_cl(&mut self, value: (Cow<'static, str>, String, AutoCompleteFn)) { 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( @@ -364,43 +382,43 @@ impl FormWidget { ), ); } - pub fn push(&mut self, value: (String, String)) { + pub fn push(&mut self, value: (Cow<'static, str>, 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, Text(UText::new(value.1), None)); } - pub fn insert(&mut self, index: usize, value: (String, Field)) { + pub fn insert(&mut self, index: usize, value: (Cow<'static, str>, Field)) { self.layout.insert(index, value.0.clone()); self.fields.insert(value.0, value.1); } - pub fn values(&self) -> &HashMap { + pub fn values(&self) -> &HashMap, Field> { &self.fields } - pub fn values_mut(&mut self) -> &mut HashMap { + pub fn values_mut(&mut self) -> &mut HashMap, Field> { &mut self.fields } - pub fn collect(self) -> Option> { - if let Some(true) = self.buttons_result() { + pub fn collect(self) -> Option, Field>> { + if self.buttons_result().is_some() { Some(self.fields) } else { None } } - pub fn buttons_result(&self) -> Option { + pub fn buttons_result(&self) -> Option { self.buttons.result } } -impl Component for FormWidget { +impl Component for FormWidget { fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) { let upper_left = upper_left!(area); let bottom_right = bottom_right!(area); - if self.dirty { + if self.is_dirty() { let theme_default = crate::conf::value(context, "theme_default"); clear_area( grid, @@ -416,7 +434,7 @@ impl Component for FormWidget { let v = self.fields.get_mut(k).unwrap(); /* Write field label */ write_string_to_grid( - k.as_str(), + k.as_ref(), grid, label_attrs.fg, label_attrs.bg, @@ -621,10 +639,10 @@ impl Component for FormWidget { #[derive(Debug, Default)] pub struct ButtonWidget where - T: 'static + std::fmt::Debug + Default + Send + Sync, + T: 'static + std::fmt::Debug + Copy + Default + Send + Sync, { - buttons: HashMap, - layout: Vec, + buttons: HashMap, T>, + layout: Vec>, result: Option, cursor: usize, @@ -636,7 +654,7 @@ where impl fmt::Display for ButtonWidget where - T: 'static + std::fmt::Debug + Default + Send + Sync, + T: 'static + std::fmt::Debug + Copy + Default + Send + Sync, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt("", f) @@ -645,9 +663,9 @@ where impl ButtonWidget where - T: 'static + std::fmt::Debug + Default + Send + Sync, + T: 'static + std::fmt::Debug + Copy + Default + Send + Sync, { - pub fn new(init_val: (String, T)) -> ButtonWidget { + pub fn new(init_val: (Cow<'static, str>, T)) -> ButtonWidget { ButtonWidget { layout: vec![init_val.0.clone()], buttons: vec![init_val].into_iter().collect(), @@ -659,7 +677,7 @@ where } } - pub fn push(&mut self, value: (String, T)) { + pub fn push(&mut self, value: (Cow<'static, str>, T)) { self.layout.push(value.0.clone()); self.buttons.insert(value.0, value.1); } @@ -668,14 +686,25 @@ where self.result.is_some() } + pub fn result(&self) -> Option { + self.result + } + pub fn set_focus(&mut self, new_val: bool) { self.focus = new_val; } + + pub fn set_cursor(&mut self, new_val: usize) { + if self.buttons.is_empty() { + return; + } + self.cursor = new_val % self.buttons.len(); + } } impl Component for ButtonWidget where - T: 'static + std::fmt::Debug + Default + Send + Sync, + T: 'static + std::fmt::Debug + Copy + Default + Send + Sync, { fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) { if self.dirty { @@ -687,7 +716,7 @@ where for (i, k) in self.layout.iter().enumerate() { let cur_len = k.len(); write_string_to_grid( - k.as_str(), + k.as_ref(), grid, theme_default.fg, if i == self.cursor && self.focus {