ui/themes: expand theme coverage to status panel and contacts

memfd
Manos Pitsidianakis 2020-02-09 00:30:50 +02:00
parent 22fb0c0844
commit c22a141b14
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
6 changed files with 179 additions and 128 deletions

View File

@ -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));

View File

@ -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;

View File

@ -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;

View File

@ -29,6 +29,7 @@ pub struct StatusPanel {
status: Option<AccountStatus>,
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,
}

View File

@ -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,
(

View File

@ -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 },