diff --git a/src/bin.rs b/src/bin.rs index 7907d8fd..7f2d857c 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -307,7 +307,10 @@ fn run_app() -> Result<()> { let window = Box::new(Tabbed::new(vec![ Box::new(listing::Listing::new(&mut state.context)), Box::new(ContactList::new(&state.context)), - Box::new(StatusPanel::new()), + Box::new(StatusPanel::new(crate::conf::value( + &state.context, + "theme_default", + ))), ])); let status_bar = Box::new(StatusBar::new(window)); diff --git a/src/components/contacts.rs b/src/components/contacts.rs index a2028e07..040f33b2 100644 --- a/src/components/contacts.rs +++ b/src/components/contacts.rs @@ -43,29 +43,13 @@ pub struct ContactManager { form: FormWidget, account_pos: usize, content: CellBuffer, + theme_default: ThemeAttribute, dirty: bool, has_changes: bool, initialized: bool, } -impl Default for ContactManager { - fn default() -> Self { - ContactManager { - id: Uuid::nil(), - parent_id: Uuid::nil(), - card: Card::new(), - mode: ViewMode::Edit, - form: FormWidget::default(), - account_pos: 0, - content: CellBuffer::new(100, 1, Cell::with_char(' ')), - dirty: true, - has_changes: false, - initialized: false, - } - } -} - impl fmt::Display for ContactManager { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "contacts") @@ -73,6 +57,30 @@ impl fmt::Display for ContactManager { } impl ContactManager { + fn new(context: &Context) -> Self { + let theme_default: ThemeAttribute = crate::conf::value(context, "theme_default"); + let default_cell = { + let mut ret = Cell::with_char(' '); + ret.set_fg(theme_default.fg) + .set_bg(theme_default.bg) + .set_attrs(theme_default.attrs); + ret + }; + ContactManager { + id: Uuid::nil(), + parent_id: Uuid::nil(), + card: Card::new(), + mode: ViewMode::Edit, + form: FormWidget::default(), + account_pos: 0, + content: CellBuffer::new(100, 1, default_cell), + theme_default, + dirty: true, + has_changes: false, + initialized: false, + } + } + fn initialize(&mut self) { let (width, _) = self.content.size(); @@ -80,8 +88,8 @@ impl ContactManager { "Last edited: ", &mut self.content, Color::Byte(250), - Color::Default, - Attr::Default, + self.theme_default.bg, + self.theme_default.attrs, ((0, 0), (width - 1, 0)), None, ); @@ -89,8 +97,8 @@ impl ContactManager { &self.card.last_edited(), &mut self.content, Color::Byte(250), - Color::Default, - Attr::Default, + self.theme_default.bg, + self.theme_default.attrs, ((x, 0), (width - 1, 0)), None, ); @@ -103,8 +111,8 @@ impl ContactManager { "This contact's origin is external and cannot be edited within meli.", &mut self.content, Color::Byte(250), - Color::Default, - Attr::Default, + self.theme_default.bg, + self.theme_default.attrs, ((x, y), (width - 1, y)), None, ); @@ -151,7 +159,7 @@ impl Component for ContactManager { clear_area( grid, (upper_left, set_y(bottom_right, get_y(upper_left) + 1)), - Default::default(), + self.theme_default, ); copy_area_with_break(grid, &self.content, area, ((0, 0), (width - 1, 0))); self.dirty = false; diff --git a/src/components/contacts/contact_list.rs b/src/components/contacts/contact_list.rs index 95e66052..fc99334a 100644 --- a/src/components/contacts/contact_list.rs +++ b/src/components/contacts/contact_list.rs @@ -131,22 +131,25 @@ impl ContactList { min_width.2 = cmp::max(min_width.2, c.url().split_graphemes().len()); } + let default_cell = { + let mut ret = Cell::with_char(' '); + ret.set_fg(self.theme_default.fg) + .set_bg(self.theme_default.bg) + .set_attrs(self.theme_default.attrs); + ret + }; /* name column */ self.data_columns.columns[0] = - CellBuffer::new_with_context(min_width.0, self.length, Cell::with_char(' '), context); + CellBuffer::new_with_context(min_width.0, self.length, default_cell, context); /* email column */ self.data_columns.columns[1] = - CellBuffer::new_with_context(min_width.1, self.length, Cell::with_char(' '), context); + CellBuffer::new_with_context(min_width.1, self.length, default_cell, context); /* url column */ self.data_columns.columns[2] = - CellBuffer::new_with_context(min_width.2, self.length, Cell::with_char(' '), context); + CellBuffer::new_with_context(min_width.2, self.length, default_cell, context); /* source column */ - self.data_columns.columns[3] = CellBuffer::new_with_context( - "external".len(), - self.length, - Cell::with_char(' '), - context, - ); + self.data_columns.columns[3] = + CellBuffer::new_with_context("external".len(), self.length, default_cell, context); let account = &context.accounts[self.account_pos]; let book = &account.address_book; @@ -201,13 +204,16 @@ impl ContactList { } if self.length == 0 { + let default_cell = { + let mut ret = Cell::with_char(' '); + ret.set_fg(self.theme_default.fg) + .set_bg(self.theme_default.bg) + .set_attrs(self.theme_default.attrs); + ret + }; let message = "Address book is empty.".to_string(); - self.data_columns.columns[0] = CellBuffer::new_with_context( - message.len(), - self.length, - Cell::with_char(' '), - context, - ); + self.data_columns.columns[0] = + CellBuffer::new_with_context(message.len(), self.length, default_cell, context); write_string_to_grid( &message, &mut self.data_columns.columns[0], @@ -445,6 +451,8 @@ impl ContactList { } clear_area(grid, area, self.theme_default); /* Page_no has changed, so draw new page */ + + let header_attrs = crate::conf::value(context, "widgets.list.header"); let mut x = get_x(upper_left); for i in 0..self.data_columns.columns.len() { if self.data_columns.widths[i] == 0 { @@ -460,9 +468,9 @@ impl ContactList { _ => "", }, grid, - Color::Black, - Color::White, - Attr::Bold, + header_attrs.fg, + header_attrs.bg, + header_attrs.attrs, ( set_x(upper_left!(area), x), ( @@ -502,8 +510,8 @@ impl ContactList { upper_left!(area), set_y(bottom_right, get_y(upper_left!(area))), ), - Color::Black, - Color::White, + header_attrs.fg, + header_attrs.bg, ); if top_idx + rows > self.length { @@ -595,7 +603,7 @@ impl Component for ContactList { UIEvent::Input(ref key) if shortcut!(key == shortcuts[Self::DESCRIPTION]["create_contact"]) => { - let mut manager = ContactManager::default(); + let mut manager = ContactManager::new(context); manager.set_parent_id(self.id); manager.account_pos = self.account_pos; @@ -612,7 +620,7 @@ impl Component for ContactList { let account = &mut context.accounts[self.account_pos]; let book = &mut account.address_book; let card = book[&self.id_positions[self.cursor_pos]].clone(); - let mut manager = ContactManager::default(); + let mut manager = ContactManager::new(context); manager.set_parent_id(self.id); manager.card = card; manager.account_pos = self.account_pos; diff --git a/src/components/mail/status.rs b/src/components/mail/status.rs index f9cc3227..18885072 100644 --- a/src/components/mail/status.rs +++ b/src/components/mail/status.rs @@ -29,6 +29,7 @@ pub struct StatusPanel { status: Option, content: CellBuffer, dirty: bool, + theme_default: ThemeAttribute, id: ComponentId, } @@ -50,8 +51,8 @@ impl Component for StatusPanel { let (_, y) = write_string_to_grid( "Worker threads", &mut self.content, - Color::Default, - Color::Default, + self.theme_default.fg, + self.theme_default.bg, Attr::Bold, ((1, 1), (width - 1, height - 1)), Some(1), @@ -73,9 +74,9 @@ impl Component for StatusPanel { max_name = max_name ), &mut self.content, - Color::Default, - Color::Default, - Attr::Default, + self.theme_default.fg, + self.theme_default.bg, + self.theme_default.attrs, ((1, y), (width - 1, height - 1)), Some(1), ); @@ -88,8 +89,8 @@ impl Component for StatusPanel { write_string_to_grid( "Static threads", &mut self.content, - Color::Default, - Color::Default, + self.theme_default.fg, + self.theme_default.bg, Attr::Bold, ((1, y + 1), (width - 1, height - 1)), Some(1), @@ -113,9 +114,9 @@ impl Component for StatusPanel { max_name = max_name ), &mut self.content, - Color::Default, - Color::Default, - Attr::Default, + self.theme_default.fg, + self.theme_default.bg, + self.theme_default.attrs, ((1, y), (width - 1, height - 1)), Some(1), ); @@ -131,7 +132,7 @@ impl Component for StatusPanel { std::cmp::min(width.saturating_sub(cols), self.cursor.0), std::cmp::min(height.saturating_sub(rows), self.cursor.1), ); - clear_area(grid, area, Default::default()); + clear_area(grid, area, self.theme_default); copy_area( grid, &self.content, @@ -170,7 +171,7 @@ impl Component for StatusPanel { return true; } UIEvent::Input(Key::Char('\n')) if self.status.is_none() => { - self.status = Some(AccountStatus::new(self.account_cursor)); + self.status = Some(AccountStatus::new(self.account_cursor, self.theme_default)); return true; } UIEvent::Input(Key::Esc) if self.status.is_some() => { @@ -224,8 +225,15 @@ impl Component for StatusPanel { } impl StatusPanel { - pub fn new() -> StatusPanel { - let mut content = CellBuffer::new(120, 40, Cell::default()); + pub fn new(theme_default: ThemeAttribute) -> StatusPanel { + let default_cell = { + let mut ret = Cell::with_char(' '); + ret.set_fg(theme_default.fg) + .set_bg(theme_default.bg) + .set_attrs(theme_default.attrs); + ret + }; + let mut content = CellBuffer::new(120, 40, default_cell); content.set_growable(true); StatusPanel { @@ -234,18 +242,26 @@ impl StatusPanel { content, status: None, dirty: true, + theme_default, id: ComponentId::new_v4(), } } fn draw_accounts(&mut self, context: &Context) { + let default_cell = { + let mut ret = Cell::with_char(' '); + ret.set_fg(self.theme_default.fg) + .set_bg(self.theme_default.bg) + .set_attrs(self.theme_default.attrs); + ret + }; self.content - .resize(120, 40 + context.accounts.len() * 20, Cell::default()); + .resize(120, 40 + context.accounts.len() * 20, default_cell); write_string_to_grid( "Accounts", &mut self.content, - Color::Default, - Color::Default, - Attr::Default, + self.theme_default.fg, + self.theme_default.bg, + self.theme_default.attrs, ((2, 10), (120 - 1, 10)), Some(2), ); @@ -258,8 +274,8 @@ impl StatusPanel { let (x, y) = write_string_to_grid( a.name(), &mut self.content, - Color::Default, - Color::Default, + self.theme_default.fg, + self.theme_default.bg, Attr::Bold, ((3, 12 + i * 10), (120 - 2, 12 + i * 10)), Some(3), @@ -268,17 +284,17 @@ impl StatusPanel { " ▒██▒ ", &mut self.content, Color::Byte(32), - Color::Default, - Attr::Default, + self.theme_default.bg, + self.theme_default.attrs, ((x, y), (120 - 2, 12 + i * 10)), None, ); write_string_to_grid( &a.runtime_settings.account().identity, &mut self.content, - Color::Default, - Color::Default, - Attr::Default, + self.theme_default.fg, + self.theme_default.bg, + self.theme_default.attrs, ((4, y + 2), (120 - 2, y + 2)), None, ); @@ -298,9 +314,9 @@ impl StatusPanel { let (mut column_width, _) = write_string_to_grid( &format!("Messages total {}, unseen {}", count.1, count.0), &mut self.content, - Color::Default, - Color::Default, - Attr::Default, + self.theme_default.fg, + self.theme_default.bg, + self.theme_default.attrs, ((5, y + 3), (120 - 2, y + 3)), None, ); @@ -309,9 +325,9 @@ impl StatusPanel { write_string_to_grid( &format!("Contacts total {}", a.address_book.len()), &mut self.content, - Color::Default, - Color::Default, - Attr::Default, + self.theme_default.fg, + self.theme_default.bg, + self.theme_default.attrs, ((5, y + 4), (120 - 2, y + 4)), None, ) @@ -322,9 +338,9 @@ impl StatusPanel { write_string_to_grid( &format!("Backend {}", a.settings.account().format()), &mut self.content, - Color::Default, - Color::Default, - Attr::Default, + self.theme_default.fg, + self.theme_default.bg, + self.theme_default.attrs, ((5, y + 5), (120 - 2, y + 5)), None, ) @@ -334,9 +350,9 @@ impl StatusPanel { write_string_to_grid( "Special Mailboxes:", &mut self.content, - Color::Default, - Color::Default, - Attr::Default, + self.theme_default.fg, + self.theme_default.bg, + Attr::Bold, ((5 + column_width, y + 2), (120 - 2, y + 2)), None, ); @@ -349,9 +365,9 @@ impl StatusPanel { write_string_to_grid( &format!("{}: {}", f.path(), f.special_usage()), &mut self.content, - Color::Default, - Color::Default, - Attr::Default, + self.theme_default.fg, + self.theme_default.bg, + self.theme_default.attrs, ((5 + column_width, y + 3 + i), (120 - 2, y + 2)), None, ); @@ -372,9 +388,9 @@ impl Component for AccountStatus { let (_x, _y) = write_string_to_grid( "(Press Esc to return)", &mut self.content, - Color::Default, - Color::Default, - Attr::Default, + self.theme_default.fg, + self.theme_default.bg, + Attr::Bold, ((1, 0), (width - 1, height - 1)), None, ); @@ -383,8 +399,8 @@ impl Component for AccountStatus { let (_x, _y) = write_string_to_grid( "Tag support: ", &mut self.content, - Color::Default, - Color::Default, + self.theme_default.fg, + self.theme_default.bg, Attr::Bold, ((1, line), (width - 1, height - 1)), None, @@ -396,9 +412,9 @@ impl Component for AccountStatus { "no" }, &mut self.content, - Color::Default, - Color::Default, - Attr::Default, + self.theme_default.fg, + self.theme_default.bg, + self.theme_default.attrs, ((_x, _y), (width - 1, height - 1)), None, ); @@ -406,8 +422,8 @@ impl Component for AccountStatus { let (_x, _y) = write_string_to_grid( "Cache backend: ", &mut self.content, - Color::Default, - Color::Default, + self.theme_default.fg, + self.theme_default.bg, Attr::Bold, ((1, line), (width - 1, height - 1)), None, @@ -440,9 +456,9 @@ impl Component for AccountStatus { } }, &mut self.content, - Color::Default, - Color::Default, - Attr::Default, + self.theme_default.fg, + self.theme_default.bg, + self.theme_default.attrs, ((_x, _y), (width - 1, height - 1)), None, ); @@ -451,8 +467,8 @@ impl Component for AccountStatus { write_string_to_grid( "Special Mailboxes:", &mut self.content, - Color::Default, - Color::Default, + self.theme_default.fg, + self.theme_default.bg, Attr::Bold, ((1, line), (width - 1, height - 1)), None, @@ -466,9 +482,9 @@ impl Component for AccountStatus { write_string_to_grid( &format!("{}: {}", f.path(), f.special_usage()), &mut self.content, - Color::Default, - Color::Default, - Attr::Default, + self.theme_default.fg, + self.theme_default.bg, + self.theme_default.attrs, ((1, line), (width - 1, height - 1)), None, ); @@ -477,8 +493,8 @@ impl Component for AccountStatus { write_string_to_grid( "Subscribed folders:", &mut self.content, - Color::Default, - Color::Default, + self.theme_default.fg, + self.theme_default.bg, Attr::Bold, ((1, line), (width - 1, height - 1)), None, @@ -490,9 +506,9 @@ impl Component for AccountStatus { write_string_to_grid( f.path(), &mut self.content, - Color::Default, - Color::Default, - Attr::Default, + self.theme_default.fg, + self.theme_default.bg, + self.theme_default.attrs, ((1, line), (width - 1, height - 1)), None, ); @@ -507,8 +523,8 @@ impl Component for AccountStatus { write_string_to_grid( "Server Capabilities:", &mut self.content, - Color::Default, - Color::Default, + self.theme_default.fg, + self.theme_default.bg, Attr::Bold, ((1, line), (width - 1, height - 1)), None, @@ -521,9 +537,9 @@ impl Component for AccountStatus { write_string_to_grid( "meli support:", &mut self.content, - Color::Default, - Color::Default, - Attr::Default, + self.theme_default.fg, + self.theme_default.bg, + self.theme_default.attrs, ((max_name_width + 6, line), (width - 1, height - 1)), None, ); @@ -534,9 +550,9 @@ impl Component for AccountStatus { write_string_to_grid( &cap, &mut self.content, - Color::Default, - Color::Default, - Attr::Default, + self.theme_default.fg, + self.theme_default.bg, + self.theme_default.attrs, ((1, line + i), (width - 1, height - 1)), None, ); @@ -550,8 +566,8 @@ impl Component for AccountStatus { "supported", &mut self.content, Color::Green, - Color::Default, - Attr::Default, + self.theme_default.bg, + self.theme_default.attrs, ((max_name_width + 6, line + i), (width - 1, height - 1)), None, ); @@ -560,8 +576,8 @@ impl Component for AccountStatus { "not supported", &mut self.content, Color::Red, - Color::Default, - Attr::Default, + self.theme_default.bg, + self.theme_default.attrs, ((max_name_width + 6, line + i), (width - 1, height - 1)), None, ); @@ -578,7 +594,7 @@ impl Component for AccountStatus { std::cmp::min(width.saturating_sub(cols), self.cursor.0), std::cmp::min(height.saturating_sub(rows), self.cursor.1), ); - clear_area(grid, area, Default::default()); + clear_area(grid, area, self.theme_default); copy_area( grid, &self.content, @@ -641,8 +657,15 @@ impl Component for AccountStatus { } impl AccountStatus { - pub fn new(account_pos: usize) -> AccountStatus { - let mut content = CellBuffer::new(120, 5, Cell::default()); + pub fn new(account_pos: usize, theme_default: ThemeAttribute) -> AccountStatus { + let default_cell = { + let mut ret = Cell::with_char(' '); + ret.set_fg(theme_default.fg) + .set_bg(theme_default.bg) + .set_attrs(theme_default.attrs); + ret + }; + let mut content = CellBuffer::new(120, 5, default_cell); content.set_growable(true); AccountStatus { @@ -650,6 +673,7 @@ impl AccountStatus { account_pos, content, dirty: true, + theme_default, id: ComponentId::new_v4(), } } @@ -661,6 +685,7 @@ struct AccountStatus { account_pos: usize, content: CellBuffer, dirty: bool, + theme_default: ThemeAttribute, id: ComponentId, } diff --git a/src/components/utilities/widgets.rs b/src/components/utilities/widgets.rs index fd6507d3..c5faf3fc 100644 --- a/src/components/utilities/widgets.rs +++ b/src/components/utilities/widgets.rs @@ -649,7 +649,8 @@ where { fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) { if self.dirty { - clear_area(grid, area, crate::conf::value(context, "theme_default")); + let theme_default = crate::conf::value(context, "theme_default"); + clear_area(grid, area, theme_default); let upper_left = upper_left!(area); let mut len = 0; @@ -658,11 +659,11 @@ where write_string_to_grid( k.as_str(), grid, - Color::Default, + theme_default.fg, if i == self.cursor && self.focus { Color::Byte(246) } else { - Color::Default + theme_default.bg }, Attr::Bold, ( diff --git a/src/conf/themes.rs b/src/conf/themes.rs index 6a1ee99a..5f993957 100644 --- a/src/conf/themes.rs +++ b/src/conf/themes.rs @@ -158,6 +158,7 @@ const DEFAULT_KEYS: &'static [&'static str] = &[ "tab.focused", "tab.unfocused", "tab.bar", + "widgets.list.header", "widgets.form.label", "widgets.form.field", "widgets.form.highlighted", @@ -476,6 +477,11 @@ impl Default for Theme { add!("tab.focused"); add!("tab.unfocused", dark = { fg: Color::Byte(15), bg: Color::Byte(8), }, light = { fg: Color::Byte(15), bg: Color::Byte(8), }); add!("tab.bar"); + add!( + "widgets.list.header", + dark = { fg: Color::Black, bg: Color::White, attrs: Attr::Bold }, + light = {fg: Color::White, bg: Color::Black, attrs: Attr::Bold } + ); add!( "widgets.form.label", dark = { attrs: Attr::Bold },