Stop hardcoding certain component colors
`Color::Byte` references were before themes were introduced in the code base. Their presence is a bug and they should all be replaced by theme values. Closes #124 Stop hardcoding certain component colors #124 https://git.meli.delivery/meli/meli/issues/124pull/144/head
parent
5823178cc2
commit
2eb22a290a
|
@ -171,8 +171,20 @@ In this mode, cursor locations (i.e., currently selected entries/items) will use
|
||||||
.It
|
.It
|
||||||
theme_default
|
theme_default
|
||||||
.It
|
.It
|
||||||
|
error_message
|
||||||
|
.It
|
||||||
|
email_header
|
||||||
|
.It
|
||||||
|
highlight
|
||||||
|
.It
|
||||||
status.bar
|
status.bar
|
||||||
.It
|
.It
|
||||||
|
status.command_bar
|
||||||
|
.It
|
||||||
|
status.history
|
||||||
|
.It
|
||||||
|
status.history.hints
|
||||||
|
.It
|
||||||
status.notification
|
status.notification
|
||||||
.It
|
.It
|
||||||
tab.focused
|
tab.focused
|
||||||
|
|
|
@ -80,7 +80,7 @@ impl ContactManager {
|
||||||
let (x, _) = write_string_to_grid(
|
let (x, _) = write_string_to_grid(
|
||||||
"Last edited: ",
|
"Last edited: ",
|
||||||
&mut self.content,
|
&mut self.content,
|
||||||
Color::Byte(250),
|
self.theme_default.fg,
|
||||||
self.theme_default.bg,
|
self.theme_default.bg,
|
||||||
self.theme_default.attrs,
|
self.theme_default.attrs,
|
||||||
((0, 0), (width - 1, 0)),
|
((0, 0), (width - 1, 0)),
|
||||||
|
@ -89,7 +89,7 @@ impl ContactManager {
|
||||||
let (x, y) = write_string_to_grid(
|
let (x, y) = write_string_to_grid(
|
||||||
&self.card.last_edited(),
|
&self.card.last_edited(),
|
||||||
&mut self.content,
|
&mut self.content,
|
||||||
Color::Byte(250),
|
self.theme_default.fg,
|
||||||
self.theme_default.bg,
|
self.theme_default.bg,
|
||||||
self.theme_default.attrs,
|
self.theme_default.attrs,
|
||||||
((x, 0), (width - 1, 0)),
|
((x, 0), (width - 1, 0)),
|
||||||
|
@ -102,7 +102,7 @@ impl ContactManager {
|
||||||
write_string_to_grid(
|
write_string_to_grid(
|
||||||
"This contact's origin is external and cannot be edited within meli.",
|
"This contact's origin is external and cannot be edited within meli.",
|
||||||
&mut self.content,
|
&mut self.content,
|
||||||
Color::Byte(250),
|
self.theme_default.fg,
|
||||||
self.theme_default.bg,
|
self.theme_default.bg,
|
||||||
self.theme_default.attrs,
|
self.theme_default.attrs,
|
||||||
((x, y), (width - 1, y)),
|
((x, y), (width - 1, y)),
|
||||||
|
|
|
@ -49,6 +49,7 @@ pub struct ContactList {
|
||||||
data_columns: DataColumns,
|
data_columns: DataColumns,
|
||||||
initialized: bool,
|
initialized: bool,
|
||||||
theme_default: ThemeAttribute,
|
theme_default: ThemeAttribute,
|
||||||
|
highlight_theme: ThemeAttribute,
|
||||||
|
|
||||||
id_positions: Vec<CardId>,
|
id_positions: Vec<CardId>,
|
||||||
|
|
||||||
|
@ -95,6 +96,7 @@ impl ContactList {
|
||||||
mode: ViewMode::List,
|
mode: ViewMode::List,
|
||||||
data_columns: DataColumns::default(),
|
data_columns: DataColumns::default(),
|
||||||
theme_default: crate::conf::value(context, "theme_default"),
|
theme_default: crate::conf::value(context, "theme_default"),
|
||||||
|
highlight_theme: crate::conf::value(context, "highlight"),
|
||||||
initialized: false,
|
initialized: false,
|
||||||
dirty: true,
|
dirty: true,
|
||||||
movement: None,
|
movement: None,
|
||||||
|
@ -222,7 +224,7 @@ impl ContactList {
|
||||||
/* Reset previously highlighted line */
|
/* Reset previously highlighted line */
|
||||||
let fg_color = self.theme_default.fg;
|
let fg_color = self.theme_default.fg;
|
||||||
let bg_color = if idx == self.new_cursor_pos {
|
let bg_color = if idx == self.new_cursor_pos {
|
||||||
Color::Byte(246)
|
self.highlight_theme.bg
|
||||||
} else {
|
} else {
|
||||||
self.theme_default.bg
|
self.theme_default.bg
|
||||||
};
|
};
|
||||||
|
|
|
@ -586,7 +586,7 @@ To: {}
|
||||||
grid,
|
grid,
|
||||||
theme_default.fg,
|
theme_default.fg,
|
||||||
if self.cursor == Cursor::Sign {
|
if self.cursor == Cursor::Sign {
|
||||||
Color::Byte(237)
|
crate::conf::value(context, "highlight").bg
|
||||||
} else {
|
} else {
|
||||||
theme_default.bg
|
theme_default.bg
|
||||||
},
|
},
|
||||||
|
@ -600,7 +600,7 @@ To: {}
|
||||||
grid,
|
grid,
|
||||||
theme_default.fg,
|
theme_default.fg,
|
||||||
if self.cursor == Cursor::Sign {
|
if self.cursor == Cursor::Sign {
|
||||||
Color::Byte(237)
|
crate::conf::value(context, "highlight").bg
|
||||||
} else {
|
} else {
|
||||||
theme_default.bg
|
theme_default.bg
|
||||||
},
|
},
|
||||||
|
@ -636,7 +636,7 @@ To: {}
|
||||||
grid,
|
grid,
|
||||||
theme_default.fg,
|
theme_default.fg,
|
||||||
if self.cursor == Cursor::Encrypt {
|
if self.cursor == Cursor::Encrypt {
|
||||||
Color::Byte(237)
|
crate::conf::value(context, "highlight").bg
|
||||||
} else {
|
} else {
|
||||||
theme_default.bg
|
theme_default.bg
|
||||||
},
|
},
|
||||||
|
@ -650,7 +650,7 @@ To: {}
|
||||||
grid,
|
grid,
|
||||||
theme_default.fg,
|
theme_default.fg,
|
||||||
if self.cursor == Cursor::Encrypt {
|
if self.cursor == Cursor::Encrypt {
|
||||||
Color::Byte(237)
|
crate::conf::value(context, "highlight").bg
|
||||||
} else {
|
} else {
|
||||||
theme_default.bg
|
theme_default.bg
|
||||||
},
|
},
|
||||||
|
@ -665,7 +665,7 @@ To: {}
|
||||||
grid,
|
grid,
|
||||||
theme_default.fg,
|
theme_default.fg,
|
||||||
if self.cursor == Cursor::Attachments {
|
if self.cursor == Cursor::Attachments {
|
||||||
Color::Byte(237)
|
crate::conf::value(context, "highlight").bg
|
||||||
} else {
|
} else {
|
||||||
theme_default.bg
|
theme_default.bg
|
||||||
},
|
},
|
||||||
|
@ -679,7 +679,7 @@ To: {}
|
||||||
grid,
|
grid,
|
||||||
theme_default.fg,
|
theme_default.fg,
|
||||||
if self.cursor == Cursor::Attachments {
|
if self.cursor == Cursor::Attachments {
|
||||||
Color::Byte(237)
|
crate::conf::value(context, "highlight").bg
|
||||||
} else {
|
} else {
|
||||||
theme_default.bg
|
theme_default.bg
|
||||||
},
|
},
|
||||||
|
@ -809,9 +809,9 @@ impl Component for Composer {
|
||||||
"COMPOSING MESSAGE"
|
"COMPOSING MESSAGE"
|
||||||
},
|
},
|
||||||
grid,
|
grid,
|
||||||
Color::Byte(189),
|
crate::conf::value(context, "highlight").fg,
|
||||||
Color::Byte(167),
|
crate::conf::value(context, "highlight").bg,
|
||||||
Attr::DEFAULT,
|
crate::conf::value(context, "highlight").attrs,
|
||||||
(
|
(
|
||||||
pos_dec(upper_left!(header_area), (0, 1)),
|
pos_dec(upper_left!(header_area), (0, 1)),
|
||||||
bottom_right!(header_area),
|
bottom_right!(header_area),
|
||||||
|
@ -825,8 +825,8 @@ impl Component for Composer {
|
||||||
set_x(pos_dec(upper_left!(header_area), (0, 1)), x),
|
set_x(pos_dec(upper_left!(header_area), (0, 1)), x),
|
||||||
set_y(bottom_right!(header_area), y),
|
set_y(bottom_right!(header_area), y),
|
||||||
),
|
),
|
||||||
Color::Byte(189),
|
crate::conf::value(context, "highlight").fg,
|
||||||
Color::Byte(167),
|
crate::conf::value(context, "highlight").bg,
|
||||||
);
|
);
|
||||||
clear_area(
|
clear_area(
|
||||||
grid,
|
grid,
|
||||||
|
@ -943,7 +943,7 @@ impl Component for Composer {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
theme_default.fg,
|
theme_default.fg,
|
||||||
Color::Byte(237),
|
crate::conf::value(context, "highlight").bg,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Cursor::Sign | Cursor::Encrypt | Cursor::Attachments => {}
|
Cursor::Sign | Cursor::Encrypt | Cursor::Attachments => {}
|
||||||
|
|
|
@ -131,7 +131,7 @@ impl Component for EditAttachmentsRefMut<'_, '_> {
|
||||||
for (i, a) in self.draft.attachments().iter().enumerate() {
|
for (i, a) in self.draft.attachments().iter().enumerate() {
|
||||||
let bg = if let EditAttachmentCursor::AttachmentNo(u) = self.inner.cursor {
|
let bg = if let EditAttachmentCursor::AttachmentNo(u) = self.inner.cursor {
|
||||||
if u == i {
|
if u == i {
|
||||||
Color::Byte(237)
|
crate::conf::value(context, "highlight").bg
|
||||||
} else {
|
} else {
|
||||||
theme_default.bg
|
theme_default.bg
|
||||||
}
|
}
|
||||||
|
|
|
@ -1918,7 +1918,7 @@ impl Listing {
|
||||||
write_string_to_grid(
|
write_string_to_grid(
|
||||||
"offline",
|
"offline",
|
||||||
&mut self.menu_content,
|
&mut self.menu_content,
|
||||||
Color::Byte(243),
|
crate::conf::value(context, "error_message").fg,
|
||||||
account_attrs.bg,
|
account_attrs.bg,
|
||||||
account_attrs.attrs,
|
account_attrs.attrs,
|
||||||
(pos_inc(upper_left, (0, 1)), bottom_right),
|
(pos_inc(upper_left, (0, 1)), bottom_right),
|
||||||
|
|
|
@ -116,9 +116,9 @@ impl Component for OfflineListing {
|
||||||
let (x, _) = write_string_to_grid(
|
let (x, _) = write_string_to_grid(
|
||||||
"offline: ",
|
"offline: ",
|
||||||
grid,
|
grid,
|
||||||
Color::Byte(243),
|
conf::value(context, "error_message").fg,
|
||||||
theme_default.bg,
|
conf::value(context, "error_message").bg,
|
||||||
theme_default.attrs,
|
conf::value(context, "error_message").attrs,
|
||||||
area,
|
area,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
@ -135,9 +135,9 @@ impl Component for OfflineListing {
|
||||||
let (_, mut y) = write_string_to_grid(
|
let (_, mut y) = write_string_to_grid(
|
||||||
"loading...",
|
"loading...",
|
||||||
grid,
|
grid,
|
||||||
Color::Byte(243),
|
conf::value(context, "highlight").fg,
|
||||||
theme_default.bg,
|
conf::value(context, "highlight").bg,
|
||||||
theme_default.attrs,
|
conf::value(context, "highlight").attrs,
|
||||||
area,
|
area,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|
|
@ -179,48 +179,14 @@ impl EnvelopeView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* TODO: add recolor changes so that this function returns a vector of required highlights
|
|
||||||
* to pass to write_string...
|
|
||||||
pub fn plain_text_to_buf(s: &str, highlight_urls: bool) -> CellBuffer {
|
|
||||||
let mut buf = CellBuffer::from(s);
|
|
||||||
|
|
||||||
if highlight_urls {
|
|
||||||
let lines: Vec<&str> = s.split('\n').map(|l| l.trim_end()).collect();
|
|
||||||
let mut shift = 0;
|
|
||||||
let mut lidx_total = 0;
|
|
||||||
let finder = LinkFinder::new();
|
|
||||||
for r in &lines {
|
|
||||||
for l in finder.links(&r) {
|
|
||||||
let offset = if lidx_total < 10 {
|
|
||||||
3
|
|
||||||
} else if lidx_total < 100 {
|
|
||||||
4
|
|
||||||
} else if lidx_total < 1000 {
|
|
||||||
5
|
|
||||||
} else {
|
|
||||||
panic!("BUG: Message body with more than 100 urls");
|
|
||||||
};
|
|
||||||
for i in 1..=offset {
|
|
||||||
buf[(l.start() + shift - i, 0)].set_fg(Color::Byte(226));
|
|
||||||
//buf[(l.start() + shift - 2, 0)].set_fg(Color::Byte(226));
|
|
||||||
//buf[(l.start() + shift - 3, 0)].set_fg(Color::Byte(226));
|
|
||||||
}
|
|
||||||
lidx_total += 1;
|
|
||||||
}
|
|
||||||
// Each Cell represents one char so next line will be:
|
|
||||||
shift += r.chars().count() + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buf
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Component for EnvelopeView {
|
impl Component for EnvelopeView {
|
||||||
fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
||||||
let upper_left = upper_left!(area);
|
let upper_left = upper_left!(area);
|
||||||
let bottom_right = bottom_right!(area);
|
let bottom_right = bottom_right!(area);
|
||||||
|
let theme_default = crate::conf::value(context, "theme_default");
|
||||||
|
let email_header_theme = crate::conf::value(context, "email_header");
|
||||||
|
|
||||||
let y: usize = {
|
let y: usize = {
|
||||||
if self.mode == ViewMode::Raw {
|
if self.mode == ViewMode::Raw {
|
||||||
|
@ -231,72 +197,77 @@ impl Component for EnvelopeView {
|
||||||
let (x, y) = write_string_to_grid(
|
let (x, y) = write_string_to_grid(
|
||||||
&format!("Date: {}", self.mail.date_as_str()),
|
&format!("Date: {}", self.mail.date_as_str()),
|
||||||
grid,
|
grid,
|
||||||
Color::Byte(33),
|
email_header_theme.fg,
|
||||||
Color::Default,
|
email_header_theme.bg,
|
||||||
Attr::DEFAULT,
|
email_header_theme.attrs,
|
||||||
area,
|
area,
|
||||||
Some(get_x(upper_left)),
|
Some(get_x(upper_left)),
|
||||||
);
|
);
|
||||||
for x in x..=get_x(bottom_right) {
|
for x in x..=get_x(bottom_right) {
|
||||||
grid[(x, y)].set_ch(' ');
|
grid[(x, y)]
|
||||||
grid[(x, y)].set_bg(Color::Default);
|
.set_ch(' ')
|
||||||
grid[(x, y)].set_fg(Color::Default);
|
.set_fg(theme_default.fg)
|
||||||
|
.set_bg(theme_default.bg);
|
||||||
}
|
}
|
||||||
let (x, y) = write_string_to_grid(
|
let (x, y) = write_string_to_grid(
|
||||||
&format!("From: {}", self.mail.field_from_to_string()),
|
&format!("From: {}", self.mail.field_from_to_string()),
|
||||||
grid,
|
grid,
|
||||||
Color::Byte(33),
|
email_header_theme.fg,
|
||||||
Color::Default,
|
email_header_theme.bg,
|
||||||
Attr::DEFAULT,
|
email_header_theme.attrs,
|
||||||
(set_y(upper_left, y + 1), bottom_right),
|
(set_y(upper_left, y + 1), bottom_right),
|
||||||
Some(get_x(upper_left)),
|
Some(get_x(upper_left)),
|
||||||
);
|
);
|
||||||
for x in x..=get_x(bottom_right) {
|
for x in x..=get_x(bottom_right) {
|
||||||
grid[(x, y)].set_ch(' ');
|
grid[(x, y)]
|
||||||
grid[(x, y)].set_bg(Color::Default);
|
.set_ch(' ')
|
||||||
grid[(x, y)].set_fg(Color::Default);
|
.set_fg(theme_default.fg)
|
||||||
|
.set_bg(theme_default.bg);
|
||||||
}
|
}
|
||||||
let (x, y) = write_string_to_grid(
|
let (x, y) = write_string_to_grid(
|
||||||
&format!("To: {}", self.mail.field_to_to_string()),
|
&format!("To: {}", self.mail.field_to_to_string()),
|
||||||
grid,
|
grid,
|
||||||
Color::Byte(33),
|
email_header_theme.fg,
|
||||||
Color::Default,
|
email_header_theme.bg,
|
||||||
Attr::DEFAULT,
|
email_header_theme.attrs,
|
||||||
(set_y(upper_left, y + 1), bottom_right),
|
(set_y(upper_left, y + 1), bottom_right),
|
||||||
Some(get_x(upper_left)),
|
Some(get_x(upper_left)),
|
||||||
);
|
);
|
||||||
for x in x..=get_x(bottom_right) {
|
for x in x..=get_x(bottom_right) {
|
||||||
grid[(x, y)].set_ch(' ');
|
grid[(x, y)]
|
||||||
grid[(x, y)].set_bg(Color::Default);
|
.set_ch(' ')
|
||||||
grid[(x, y)].set_fg(Color::Default);
|
.set_fg(theme_default.fg)
|
||||||
|
.set_bg(theme_default.bg);
|
||||||
}
|
}
|
||||||
let (x, y) = write_string_to_grid(
|
let (x, y) = write_string_to_grid(
|
||||||
&format!("Subject: {}", self.mail.subject()),
|
&format!("Subject: {}", self.mail.subject()),
|
||||||
grid,
|
grid,
|
||||||
Color::Byte(33),
|
email_header_theme.fg,
|
||||||
Color::Default,
|
email_header_theme.bg,
|
||||||
Attr::DEFAULT,
|
email_header_theme.attrs,
|
||||||
(set_y(upper_left, y + 1), bottom_right),
|
(set_y(upper_left, y + 1), bottom_right),
|
||||||
Some(get_x(upper_left)),
|
Some(get_x(upper_left)),
|
||||||
);
|
);
|
||||||
for x in x..=get_x(bottom_right) {
|
for x in x..=get_x(bottom_right) {
|
||||||
grid[(x, y)].set_ch(' ');
|
grid[(x, y)]
|
||||||
grid[(x, y)].set_bg(Color::Default);
|
.set_ch(' ')
|
||||||
grid[(x, y)].set_fg(Color::Default);
|
.set_fg(theme_default.fg)
|
||||||
|
.set_bg(theme_default.bg);
|
||||||
}
|
}
|
||||||
let (x, y) = write_string_to_grid(
|
let (x, y) = write_string_to_grid(
|
||||||
&format!("Message-ID: <{}>", self.mail.message_id_raw()),
|
&format!("Message-ID: <{}>", self.mail.message_id_raw()),
|
||||||
grid,
|
grid,
|
||||||
Color::Byte(33),
|
email_header_theme.fg,
|
||||||
Color::Default,
|
email_header_theme.bg,
|
||||||
Attr::DEFAULT,
|
email_header_theme.attrs,
|
||||||
(set_y(upper_left, y + 1), bottom_right),
|
(set_y(upper_left, y + 1), bottom_right),
|
||||||
Some(get_x(upper_left)),
|
Some(get_x(upper_left)),
|
||||||
);
|
);
|
||||||
for x in x..=get_x(bottom_right) {
|
for x in x..=get_x(bottom_right) {
|
||||||
grid[(x, y)].set_ch(' ');
|
grid[(x, y)]
|
||||||
grid[(x, y)].set_bg(Color::Default);
|
.set_ch(' ')
|
||||||
grid[(x, y)].set_fg(Color::Default);
|
.set_fg(theme_default.fg)
|
||||||
|
.set_bg(theme_default.bg);
|
||||||
}
|
}
|
||||||
clear_area(
|
clear_area(
|
||||||
grid,
|
grid,
|
||||||
|
@ -322,14 +293,7 @@ impl Component for EnvelopeView {
|
||||||
self.mode = ViewMode::Subview;
|
self.mode = ViewMode::Subview;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let text = {
|
let text = { self.attachment_to_text(&body, context) };
|
||||||
self.attachment_to_text(&body, context)
|
|
||||||
/*
|
|
||||||
let text = self.attachment_to_text(&body);
|
|
||||||
// URL indexes must be colored (ugh..)
|
|
||||||
EnvelopeView::plain_text_to_buf(&text, self.mode == ViewMode::Url)
|
|
||||||
*/
|
|
||||||
};
|
|
||||||
let cursor_pos = if self.mode.is_attachment() {
|
let cursor_pos = if self.mode.is_attachment() {
|
||||||
Some(0)
|
Some(0)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -266,6 +266,7 @@ impl ThreadView {
|
||||||
width = cmp::max(width, e.index.0 * 4 + e.heading.grapheme_width() + 2);
|
width = cmp::max(width, e.index.0 * 4 + e.heading.grapheme_width() + 2);
|
||||||
}
|
}
|
||||||
let theme_default = crate::conf::value(context, "theme_default");
|
let theme_default = crate::conf::value(context, "theme_default");
|
||||||
|
let highlight_theme = crate::conf::value(context, "highlight");
|
||||||
let mut content = CellBuffer::new_with_context(width, height, None, context);
|
let mut content = CellBuffer::new_with_context(width, height, None, context);
|
||||||
if self.reversed {
|
if self.reversed {
|
||||||
for (y, e) in self.entries.iter().rev().enumerate() {
|
for (y, e) in self.entries.iter().rev().enumerate() {
|
||||||
|
@ -294,12 +295,12 @@ impl ThreadView {
|
||||||
if e.seen {
|
if e.seen {
|
||||||
theme_default.fg
|
theme_default.fg
|
||||||
} else {
|
} else {
|
||||||
Color::Byte(0)
|
highlight_theme.fg
|
||||||
},
|
},
|
||||||
if e.seen {
|
if e.seen {
|
||||||
theme_default.bg
|
theme_default.bg
|
||||||
} else {
|
} else {
|
||||||
Color::Byte(251)
|
highlight_theme.bg
|
||||||
},
|
},
|
||||||
theme_default.attrs,
|
theme_default.attrs,
|
||||||
(
|
(
|
||||||
|
@ -308,19 +309,10 @@ impl ThreadView {
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
{
|
|
||||||
let envelope: EnvelopeRef = context.accounts[&self.coordinates.0]
|
|
||||||
.collection
|
|
||||||
.get_env(e.msg_hash);
|
|
||||||
if envelope.has_attachments() {
|
|
||||||
content[(e.index.0 * 4 + e.heading.grapheme_width(), 2 * y)]
|
|
||||||
.set_fg(Color::Byte(103));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(len) = highlight_reply_subjects[y] {
|
if let Some(len) = highlight_reply_subjects[y] {
|
||||||
let index = e.index.0 * 4 + 1 + e.heading.grapheme_width() - len;
|
let index = e.index.0 * 4 + 1 + e.heading.grapheme_width() - len;
|
||||||
let area = ((index, 2 * y), (width - 2, 2 * y));
|
let area = ((index, 2 * y), (width - 2, 2 * y));
|
||||||
change_colors(&mut content, area, Color::Byte(33), theme_default.bg);
|
change_colors(&mut content, area, highlight_theme.fg, theme_default.bg);
|
||||||
}
|
}
|
||||||
set_and_join_box(&mut content, (e.index.0 * 4, 2 * y), BoxBoundary::Vertical);
|
set_and_join_box(&mut content, (e.index.0 * 4, 2 * y), BoxBoundary::Vertical);
|
||||||
set_and_join_box(
|
set_and_join_box(
|
||||||
|
@ -375,12 +367,12 @@ impl ThreadView {
|
||||||
if e.seen {
|
if e.seen {
|
||||||
theme_default.fg
|
theme_default.fg
|
||||||
} else {
|
} else {
|
||||||
Color::Byte(0)
|
highlight_theme.fg
|
||||||
},
|
},
|
||||||
if e.seen {
|
if e.seen {
|
||||||
theme_default.bg
|
theme_default.bg
|
||||||
} else {
|
} else {
|
||||||
Color::Byte(251)
|
highlight_theme.bg
|
||||||
},
|
},
|
||||||
theme_default.attrs,
|
theme_default.attrs,
|
||||||
(
|
(
|
||||||
|
@ -389,19 +381,10 @@ impl ThreadView {
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
{
|
|
||||||
let envelope: EnvelopeRef = context.accounts[&self.coordinates.0]
|
|
||||||
.collection
|
|
||||||
.get_env(e.msg_hash);
|
|
||||||
if envelope.has_attachments() {
|
|
||||||
content[(e.index.0 * 4 + e.heading.grapheme_width(), 2 * y)]
|
|
||||||
.set_fg(Color::Byte(103));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(_len) = highlight_reply_subjects[y] {
|
if let Some(_len) = highlight_reply_subjects[y] {
|
||||||
let index = e.index.0 * 4 + 1;
|
let index = e.index.0 * 4 + 1;
|
||||||
let area = ((index, 2 * y), (width - 2, 2 * y));
|
let area = ((index, 2 * y), (width - 2, 2 * y));
|
||||||
change_colors(&mut content, area, Color::Byte(33), theme_default.bg);
|
change_colors(&mut content, area, highlight_theme.fg, theme_default.bg);
|
||||||
}
|
}
|
||||||
set_and_join_box(&mut content, (e.index.0 * 4, 2 * y), BoxBoundary::Vertical);
|
set_and_join_box(&mut content, (e.index.0 * 4, 2 * y), BoxBoundary::Vertical);
|
||||||
set_and_join_box(
|
set_and_join_box(
|
||||||
|
@ -439,7 +422,7 @@ impl ThreadView {
|
||||||
.collect();
|
.collect();
|
||||||
if idx == *visibles[self.cursor_pos] {
|
if idx == *visibles[self.cursor_pos] {
|
||||||
let theme_default = crate::conf::value(context, "theme_default");
|
let theme_default = crate::conf::value(context, "theme_default");
|
||||||
let bg_color = Color::Byte(246);
|
let bg_color = crate::conf::value(context, "highlight").bg;
|
||||||
let attrs = if self.use_color {
|
let attrs = if self.use_color {
|
||||||
theme_default.attrs
|
theme_default.attrs
|
||||||
} else {
|
} else {
|
||||||
|
@ -695,7 +678,7 @@ impl ThreadView {
|
||||||
let (x, y) = write_string_to_grid(
|
let (x, y) = write_string_to_grid(
|
||||||
&envelope.subject(),
|
&envelope.subject(),
|
||||||
grid,
|
grid,
|
||||||
Color::Byte(33),
|
crate::conf::value(context, "highlight").fg,
|
||||||
theme_default.bg,
|
theme_default.bg,
|
||||||
theme_default.attrs,
|
theme_default.attrs,
|
||||||
area,
|
area,
|
||||||
|
@ -729,7 +712,7 @@ impl ThreadView {
|
||||||
for x in get_x(upper_left)..=get_x(bottom_right) {
|
for x in get_x(upper_left)..=get_x(bottom_right) {
|
||||||
set_and_join_box(grid, (x, y - 1), BoxBoundary::Horizontal);
|
set_and_join_box(grid, (x, y - 1), BoxBoundary::Horizontal);
|
||||||
grid[(x, y - 1)]
|
grid[(x, y - 1)]
|
||||||
.set_fg(Color::Byte(33))
|
.set_fg(theme_default.fg)
|
||||||
.set_bg(theme_default.bg);
|
.set_bg(theme_default.bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -803,7 +786,7 @@ impl ThreadView {
|
||||||
let (x, y) = write_string_to_grid(
|
let (x, y) = write_string_to_grid(
|
||||||
&envelope.subject(),
|
&envelope.subject(),
|
||||||
grid,
|
grid,
|
||||||
Color::Byte(33),
|
theme_default.fg,
|
||||||
theme_default.bg,
|
theme_default.bg,
|
||||||
theme_default.attrs,
|
theme_default.attrs,
|
||||||
area,
|
area,
|
||||||
|
|
|
@ -230,9 +230,9 @@ impl StatusBar {
|
||||||
let (_, y) = write_string_to_grid(
|
let (_, y) = write_string_to_grid(
|
||||||
self.ex_buffer.as_str(),
|
self.ex_buffer.as_str(),
|
||||||
grid,
|
grid,
|
||||||
Color::Byte(219),
|
crate::conf::value(context, "status.command_bar").fg,
|
||||||
Color::Byte(88),
|
crate::conf::value(context, "status.command_bar").bg,
|
||||||
Attr::DEFAULT,
|
crate::conf::value(context, "status.command_bar").attrs,
|
||||||
area,
|
area,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
@ -242,7 +242,12 @@ impl StatusBar {
|
||||||
) {
|
) {
|
||||||
cell.set_attrs(Attr::UNDERLINE);
|
cell.set_attrs(Attr::UNDERLINE);
|
||||||
}
|
}
|
||||||
change_colors(grid, area, Color::Byte(219), Color::Byte(88));
|
change_colors(
|
||||||
|
grid,
|
||||||
|
area,
|
||||||
|
crate::conf::value(context, "status.command_bar").fg,
|
||||||
|
crate::conf::value(context, "status.command_bar").bg,
|
||||||
|
);
|
||||||
context.dirty_areas.push_back(area);
|
context.dirty_areas.push_back(area);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -387,8 +392,8 @@ impl Component for StatusBar {
|
||||||
change_colors(
|
change_colors(
|
||||||
grid,
|
grid,
|
||||||
hist_area,
|
hist_area,
|
||||||
Color::Byte(197), // DeepPink2,
|
crate::conf::value(context, "status.history").fg,
|
||||||
Color::Byte(174), //LightPink3
|
crate::conf::value(context, "status.history").bg,
|
||||||
);
|
);
|
||||||
context.dirty_areas.push_back(hist_area);
|
context.dirty_areas.push_back(hist_area);
|
||||||
hist_area
|
hist_area
|
||||||
|
@ -420,8 +425,8 @@ impl Component for StatusBar {
|
||||||
change_colors(
|
change_colors(
|
||||||
grid,
|
grid,
|
||||||
hist_area,
|
hist_area,
|
||||||
Color::Byte(88), // DarkRed,
|
crate::conf::value(context, "status.history.hints").fg,
|
||||||
Color::Byte(174), //LightPink3
|
crate::conf::value(context, "status.history.hints").bg,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
for (y_offset, s) in self
|
for (y_offset, s) in self
|
||||||
|
@ -435,9 +440,9 @@ impl Component for StatusBar {
|
||||||
let (x, y) = write_string_to_grid(
|
let (x, y) = write_string_to_grid(
|
||||||
s.as_str(),
|
s.as_str(),
|
||||||
grid,
|
grid,
|
||||||
Color::Byte(88), // DarkRed,
|
crate::conf::value(context, "status.history.hints").fg,
|
||||||
Color::Byte(174), //LightPink3
|
crate::conf::value(context, "status.history.hints").bg,
|
||||||
Attr::DEFAULT,
|
crate::conf::value(context, "status.history.hints").attrs,
|
||||||
(
|
(
|
||||||
set_y(
|
set_y(
|
||||||
upper_left!(hist_area),
|
upper_left!(hist_area),
|
||||||
|
@ -450,9 +455,9 @@ impl Component for StatusBar {
|
||||||
write_string_to_grid(
|
write_string_to_grid(
|
||||||
&s.description,
|
&s.description,
|
||||||
grid,
|
grid,
|
||||||
Color::White,
|
crate::conf::value(context, "status.history.hints").fg,
|
||||||
Color::Byte(174),
|
crate::conf::value(context, "status.history.hints").bg,
|
||||||
Attr::DEFAULT,
|
crate::conf::value(context, "status.history.hints").attrs,
|
||||||
((x + 2, y), bottom_right!(hist_area)),
|
((x + 2, y), bottom_right!(hist_area)),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
@ -469,15 +474,15 @@ impl Component for StatusBar {
|
||||||
get_y(bottom_right!(hist_area)) - hist_height + y_offset + 1,
|
get_y(bottom_right!(hist_area)) - hist_height + y_offset + 1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Color::Byte(88), // DarkRed,
|
crate::conf::value(context, "status.history.hints").fg,
|
||||||
Color::Byte(173), //LightSalmon3
|
crate::conf::value(context, "status.history.hints").bg,
|
||||||
);
|
);
|
||||||
write_string_to_grid(
|
write_string_to_grid(
|
||||||
&s.as_str()[self.ex_buffer.as_str().len()..],
|
&s.as_str()[self.ex_buffer.as_str().len()..],
|
||||||
grid,
|
grid,
|
||||||
Color::Byte(97), // MediumPurple3,
|
crate::conf::value(context, "status.history.hints").fg,
|
||||||
Color::Byte(88), //LightPink3
|
crate::conf::value(context, "status.history.hints").bg,
|
||||||
Attr::DEFAULT,
|
crate::conf::value(context, "status.history.hints").attrs,
|
||||||
(
|
(
|
||||||
(
|
(
|
||||||
get_x(upper_left)
|
get_x(upper_left)
|
||||||
|
@ -891,8 +896,6 @@ impl Tabbed {
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
{
|
{
|
||||||
c.set_ch(' ').set_bg(tab_unfocused_attribute.bg);
|
c.set_ch(' ').set_bg(tab_unfocused_attribute.bg);
|
||||||
//.set_fg(tab_unfocused_attribute.bg)
|
|
||||||
//.set_bg(Color::Byte(7));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.cursor_pos == self.children.len() - 1 {
|
if self.cursor_pos == self.children.len() - 1 {
|
||||||
|
|
|
@ -355,8 +355,8 @@ impl Pager {
|
||||||
);
|
);
|
||||||
if l.starts_with("⤷") {
|
if l.starts_with("⤷") {
|
||||||
grid[upper_left]
|
grid[upper_left]
|
||||||
.set_fg(Color::Byte(240))
|
.set_fg(crate::conf::value(context, "highlight").fg)
|
||||||
.set_attrs(Attr::BOLD);
|
.set_attrs(crate::conf::value(context, "highlight").attrs);
|
||||||
}
|
}
|
||||||
upper_left = pos_inc(upper_left, (0, 1));
|
upper_left = pos_inc(upper_left, (0, 1));
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,8 +121,8 @@ impl Field {
|
||||||
change_colors(
|
change_colors(
|
||||||
grid,
|
grid,
|
||||||
(pos_inc(upper_left, (pos, 0)), pos_inc(upper_left, (pos, 0))),
|
(pos_inc(upper_left, (pos, 0)), pos_inc(upper_left, (pos, 0))),
|
||||||
Color::Default,
|
crate::conf::value(context, "theme_default").fg,
|
||||||
Color::Byte(248),
|
crate::conf::value(context, "highlight").bg,
|
||||||
);
|
);
|
||||||
if term.grapheme_len() <= 2 {
|
if term.grapheme_len() <= 2 {
|
||||||
return;
|
return;
|
||||||
|
@ -810,7 +810,7 @@ where
|
||||||
grid,
|
grid,
|
||||||
theme_default.fg,
|
theme_default.fg,
|
||||||
if i == self.cursor && self.focus {
|
if i == self.cursor && self.focus {
|
||||||
Color::Byte(246)
|
crate::conf::value(context, "highlight").bg
|
||||||
} else {
|
} else {
|
||||||
theme_default.bg
|
theme_default.bg
|
||||||
},
|
},
|
||||||
|
@ -965,8 +965,8 @@ impl Component for AutoComplete {
|
||||||
get_y(pos_inc(upper_left, (0, (self.cursor - 1) % rows))),
|
get_y(pos_inc(upper_left, (0, (self.cursor - 1) % rows))),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Color::Default,
|
crate::conf::value(context, "highlight").fg,
|
||||||
Color::Byte(246),
|
crate::conf::value(context, "highlight").bg,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if rows < self.entries.len() {
|
if rows < self.entries.len() {
|
||||||
|
@ -1020,6 +1020,7 @@ impl AutoComplete {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: remove hardcoded color values
|
||||||
let mut content = CellBuffer::new(
|
let mut content = CellBuffer::new(
|
||||||
entries
|
entries
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
@ -244,7 +244,13 @@ fn unlink_attrs<'k, 't: 'k>(theme: &'t Theme, mut key: &'k Cow<'static, str>) ->
|
||||||
|
|
||||||
const DEFAULT_KEYS: &[&str] = &[
|
const DEFAULT_KEYS: &[&str] = &[
|
||||||
"theme_default",
|
"theme_default",
|
||||||
|
"error_message",
|
||||||
|
"email_header",
|
||||||
|
"highlight",
|
||||||
"status.bar",
|
"status.bar",
|
||||||
|
"status.command_bar",
|
||||||
|
"status.history",
|
||||||
|
"status.history.hints",
|
||||||
"status.notification",
|
"status.notification",
|
||||||
"tab.focused",
|
"tab.focused",
|
||||||
"tab.unfocused",
|
"tab.unfocused",
|
||||||
|
@ -1312,7 +1318,17 @@ impl Default for Themes {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
add!("theme_default", dark = { fg: Color::Default, bg: Color::Default, attrs: Attr::DEFAULT }, light = { fg: Color::Default, bg: Color::Default, attrs: Attr::DEFAULT });
|
add!("theme_default", dark = { fg: Color::Default, bg: Color::Default, attrs: Attr::DEFAULT }, light = { fg: Color::Default, bg: Color::Default, attrs: Attr::DEFAULT });
|
||||||
|
|
||||||
|
add!("error_message", dark = { fg: Color::Byte(243), bg: Color::Default, attrs: Attr::DEFAULT }, light = { fg: Color::Byte(243), bg: Color::Default, attrs: Attr::DEFAULT });
|
||||||
|
|
||||||
|
add!("email_header", dark = { fg: Color::Byte(33), bg: Color::Default, attrs: Attr::DEFAULT }, light = { fg: Color::Byte(33), bg: Color::Default, attrs: Attr::DEFAULT });
|
||||||
|
|
||||||
|
add!("highlight", dark = { fg: Color::Byte(240), bg: Color::Byte(237), attrs: Attr::BOLD }, light = { fg: Color::Byte(240), bg: Color::Byte(237), attrs: Attr::BOLD });
|
||||||
|
|
||||||
add!("status.bar", dark = { fg: Color::Byte(123), bg: Color::Byte(26) }, light = { fg: Color::Byte(123), bg: Color::Byte(26) });
|
add!("status.bar", dark = { fg: Color::Byte(123), bg: Color::Byte(26) }, light = { fg: Color::Byte(123), bg: Color::Byte(26) });
|
||||||
|
add!("status.command_bar", dark = { fg: Color::Byte(219), bg: Color::Byte(88) }, light = { fg: Color::Byte(219), bg: Color::Byte(88) });
|
||||||
|
add!("status.history", dark = { fg: Color::Byte(197), bg: Color::Byte(174) }, light = { fg: Color::Byte(197), bg: Color::Byte(174) });
|
||||||
|
add!("status.history.hints", dark = { fg: Color::Black, bg: "status.command_bar" }, light = { fg: Color::Black, bg: "status.command_bar" });
|
||||||
add!("status.notification", dark = { fg: Color::Byte(219), bg: Color::Default }, light = { fg: Color::Byte(219), bg: Color::Default });
|
add!("status.notification", dark = { fg: Color::Byte(219), bg: Color::Default }, light = { fg: Color::Byte(219), bg: Color::Default });
|
||||||
|
|
||||||
add!("tab.focused");
|
add!("tab.focused");
|
||||||
|
|
|
@ -1381,7 +1381,6 @@ pub mod boundaries {
|
||||||
break;
|
break;
|
||||||
} else if adj == 0b0100 {
|
} else if adj == 0b0100 {
|
||||||
cell.set_ch(bin_to_ch(0b0101));
|
cell.set_ch(bin_to_ch(0b0101));
|
||||||
cell.set_fg(Color::Byte(240));
|
|
||||||
bin_set |= 0b0100;
|
bin_set |= 0b0100;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1422,7 +1421,6 @@ pub mod boundaries {
|
||||||
if let Some(cell) = grid.get_mut(x, y - 1) {
|
if let Some(cell) = grid.get_mut(x, y - 1) {
|
||||||
if let Some(adj) = ch_to_bin(cell.ch()) {
|
if let Some(adj) = ch_to_bin(cell.ch()) {
|
||||||
cell.set_ch(bin_to_ch(adj | 0b1000));
|
cell.set_ch(bin_to_ch(adj | 0b1000));
|
||||||
cell.set_fg(Color::Byte(240));
|
|
||||||
} else {
|
} else {
|
||||||
bin_set &= 0b1101;
|
bin_set &= 0b1101;
|
||||||
}
|
}
|
||||||
|
@ -1441,7 +1439,6 @@ pub mod boundaries {
|
||||||
if let Some(cell) = grid.get_mut(x, y + 1) {
|
if let Some(cell) = grid.get_mut(x, y + 1) {
|
||||||
if let Some(adj) = ch_to_bin(cell.ch()) {
|
if let Some(adj) = ch_to_bin(cell.ch()) {
|
||||||
cell.set_ch(bin_to_ch(adj | 0b0010));
|
cell.set_ch(bin_to_ch(adj | 0b0010));
|
||||||
cell.set_fg(Color::Byte(240));
|
|
||||||
} else {
|
} else {
|
||||||
bin_set &= 0b0111;
|
bin_set &= 0b0111;
|
||||||
}
|
}
|
||||||
|
@ -1476,7 +1473,6 @@ pub mod boundaries {
|
||||||
} else if adj == 0b0010 {
|
} else if adj == 0b0010 {
|
||||||
bin_set |= 0b0010;
|
bin_set |= 0b0010;
|
||||||
cell.set_ch(bin_to_ch(0b1010));
|
cell.set_ch(bin_to_ch(0b1010));
|
||||||
cell.set_fg(Color::Byte(240));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1501,7 +1497,6 @@ pub mod boundaries {
|
||||||
} else if adj == 0b1000 {
|
} else if adj == 0b1000 {
|
||||||
bin_set |= 0b1000;
|
bin_set |= 0b1000;
|
||||||
cell.set_ch(bin_to_ch(0b1010));
|
cell.set_ch(bin_to_ch(0b1010));
|
||||||
cell.set_fg(Color::Byte(240));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1521,7 +1516,6 @@ pub mod boundaries {
|
||||||
if let Some(cell) = grid.get_mut(x - 1, y) {
|
if let Some(cell) = grid.get_mut(x - 1, y) {
|
||||||
if let Some(adj) = ch_to_bin(cell.ch()) {
|
if let Some(adj) = ch_to_bin(cell.ch()) {
|
||||||
cell.set_ch(bin_to_ch(adj | 0b0001));
|
cell.set_ch(bin_to_ch(adj | 0b0001));
|
||||||
cell.set_fg(Color::Byte(240));
|
|
||||||
} else {
|
} else {
|
||||||
bin_set &= 0b1011;
|
bin_set &= 0b1011;
|
||||||
}
|
}
|
||||||
|
@ -1540,7 +1534,6 @@ pub mod boundaries {
|
||||||
if let Some(cell) = grid.get_mut(x + 1, y) {
|
if let Some(cell) = grid.get_mut(x + 1, y) {
|
||||||
if let Some(adj) = ch_to_bin(cell.ch()) {
|
if let Some(adj) = ch_to_bin(cell.ch()) {
|
||||||
cell.set_ch(bin_to_ch(adj | 0b0100));
|
cell.set_ch(bin_to_ch(adj | 0b0100));
|
||||||
cell.set_fg(Color::Byte(240));
|
|
||||||
} else {
|
} else {
|
||||||
bin_set &= 0b1110;
|
bin_set &= 0b1110;
|
||||||
}
|
}
|
||||||
|
@ -1576,8 +1569,6 @@ pub mod boundaries {
|
||||||
BoxBoundary::Vertical => '|',
|
BoxBoundary::Vertical => '|',
|
||||||
BoxBoundary::Horizontal => '-',
|
BoxBoundary::Horizontal => '-',
|
||||||
});
|
});
|
||||||
|
|
||||||
grid[idx].set_fg(Color::Byte(240));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1587,7 +1578,6 @@ pub mod boundaries {
|
||||||
};
|
};
|
||||||
|
|
||||||
grid[idx].set_ch(bin_to_ch(bin_set));
|
grid[idx].set_ch(bin_to_ch(bin_set));
|
||||||
grid[idx].set_fg(Color::Byte(240));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Puts boundaries in `area`.
|
/// Puts boundaries in `area`.
|
||||||
|
@ -1601,21 +1591,13 @@ pub mod boundaries {
|
||||||
|
|
||||||
if !grid.ascii_drawing {
|
if !grid.ascii_drawing {
|
||||||
for x in get_x(upper_left)..get_x(bottom_right) {
|
for x in get_x(upper_left)..get_x(bottom_right) {
|
||||||
grid[(x, get_y(upper_left))]
|
grid[(x, get_y(upper_left))].set_ch(HORZ_BOUNDARY);
|
||||||
.set_ch(HORZ_BOUNDARY)
|
grid[(x, get_y(bottom_right))].set_ch(HORZ_BOUNDARY);
|
||||||
.set_fg(Color::Byte(240));
|
|
||||||
grid[(x, get_y(bottom_right))]
|
|
||||||
.set_ch(HORZ_BOUNDARY)
|
|
||||||
.set_fg(Color::Byte(240));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for y in get_y(upper_left)..get_y(bottom_right) {
|
for y in get_y(upper_left)..get_y(bottom_right) {
|
||||||
grid[(get_x(upper_left), y)]
|
grid[(get_x(upper_left), y)].set_ch(VERT_BOUNDARY);
|
||||||
.set_ch(VERT_BOUNDARY)
|
grid[(get_x(bottom_right), y)].set_ch(VERT_BOUNDARY);
|
||||||
.set_fg(Color::Byte(240));
|
|
||||||
grid[(get_x(bottom_right), y)]
|
|
||||||
.set_ch(VERT_BOUNDARY)
|
|
||||||
.set_fg(Color::Byte(240));
|
|
||||||
}
|
}
|
||||||
set_and_join_box(grid, upper_left, BoxBoundary::Horizontal);
|
set_and_join_box(grid, upper_left, BoxBoundary::Horizontal);
|
||||||
set_and_join_box(
|
set_and_join_box(
|
||||||
|
|
Loading…
Reference in New Issue