NCursesUI: refactor info_show code
Show MenuDoc info on the left of the menu if necessary. Cleanup the code.
This commit is contained in:
parent
cf37623f1a
commit
8a7e844207
|
@ -845,14 +845,20 @@ static DisplayCoord compute_pos(DisplayCoord anchor, DisplayCoord size,
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<String> make_info_box(StringView title, StringView message, ColumnCount max_width,
|
struct InfoBox
|
||||||
ConstArrayView<StringView> assistant)
|
{
|
||||||
|
DisplayCoord size;
|
||||||
|
Vector<String> contents;
|
||||||
|
};
|
||||||
|
|
||||||
|
InfoBox make_info_box(StringView title, StringView message, ColumnCount max_width,
|
||||||
|
ConstArrayView<StringView> assistant)
|
||||||
{
|
{
|
||||||
DisplayCoord assistant_size;
|
DisplayCoord assistant_size;
|
||||||
if (not assistant.empty())
|
if (not assistant.empty())
|
||||||
assistant_size = { (int)assistant.size(), assistant[0].column_length() };
|
assistant_size = { (int)assistant.size(), assistant[0].column_length() };
|
||||||
|
|
||||||
Vector<String> result;
|
InfoBox result{};
|
||||||
|
|
||||||
const ColumnCount max_bubble_width = max_width - assistant_size.column - 6;
|
const ColumnCount max_bubble_width = max_width - assistant_size.column - 6;
|
||||||
if (max_bubble_width < 4)
|
if (max_bubble_width < 4)
|
||||||
|
@ -864,8 +870,8 @@ Vector<String> make_info_box(StringView title, StringView message, ColumnCount m
|
||||||
for (auto& line : lines)
|
for (auto& line : lines)
|
||||||
bubble_width = max(bubble_width, line.column_length());
|
bubble_width = max(bubble_width, line.column_length());
|
||||||
|
|
||||||
auto line_count = max(assistant_size.line-1,
|
auto line_count = max(assistant_size.line-1, LineCount{(int)lines.size()} + 2);
|
||||||
LineCount{(int)lines.size()} + 2);
|
result.size = DisplayCoord{line_count, bubble_width + assistant_size.column + 4};
|
||||||
const auto assistant_top_margin = (line_count - assistant_size.line+1) / 2;
|
const auto assistant_top_margin = (line_count - assistant_size.line+1) / 2;
|
||||||
for (LineCount i = 0; i < line_count; ++i)
|
for (LineCount i = 0; i < line_count; ++i)
|
||||||
{
|
{
|
||||||
|
@ -899,11 +905,23 @@ Vector<String> make_info_box(StringView title, StringView message, ColumnCount m
|
||||||
else if (i == lines.size() + 1)
|
else if (i == lines.size() + 1)
|
||||||
line += "╰─" + String(dash, bubble_width) + "─╯";
|
line += "╰─" + String(dash, bubble_width) + "─╯";
|
||||||
|
|
||||||
result.push_back(std::move(line));
|
result.contents.push_back(std::move(line));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InfoBox make_simple_info_box(StringView contents, ColumnCount max_width)
|
||||||
|
{
|
||||||
|
InfoBox info_box{};
|
||||||
|
for (auto& line : wrap_lines(contents, max_width))
|
||||||
|
{
|
||||||
|
++info_box.size.line;
|
||||||
|
info_box.size.column = std::max(line.column_length(), info_box.size.column);
|
||||||
|
info_box.contents.push_back(line.str());
|
||||||
|
}
|
||||||
|
return info_box;
|
||||||
|
}
|
||||||
|
|
||||||
void NCursesUI::info_show(StringView title, StringView content,
|
void NCursesUI::info_show(StringView title, StringView content,
|
||||||
DisplayCoord anchor, Face face, InfoStyle style)
|
DisplayCoord anchor, Face face, InfoStyle style)
|
||||||
{
|
{
|
||||||
|
@ -915,59 +933,62 @@ void NCursesUI::info_show(StringView title, StringView content,
|
||||||
m_info.face = face;
|
m_info.face = face;
|
||||||
m_info.style = style;
|
m_info.style = style;
|
||||||
|
|
||||||
Vector<String> info_box;
|
const Rect rect = {m_status_on_top ? 1_line : 0_line, m_dimensions};
|
||||||
|
InfoBox info_box;
|
||||||
if (style == InfoStyle::Prompt)
|
if (style == InfoStyle::Prompt)
|
||||||
{
|
{
|
||||||
info_box = make_info_box(m_info.title, m_info.content,
|
info_box = make_info_box(m_info.title, m_info.content, m_dimensions.column, m_assistant);
|
||||||
m_dimensions.column, m_assistant);
|
anchor = DisplayCoord{m_status_on_top ? 0 : m_dimensions.line, m_dimensions.column-1};
|
||||||
anchor = DisplayCoord{m_status_on_top ? 0 : m_dimensions.line,
|
anchor = compute_pos(anchor, info_box.size, rect, m_menu, style == InfoStyle::InlineAbove);
|
||||||
m_dimensions.column-1};
|
|
||||||
}
|
}
|
||||||
else if (style == InfoStyle::Modal)
|
else if (style == InfoStyle::Modal)
|
||||||
info_box = make_info_box(m_info.title, m_info.content,
|
|
||||||
m_dimensions.column, {});
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
if (m_status_on_top)
|
info_box = make_info_box(m_info.title, m_info.content, m_dimensions.column, {});
|
||||||
anchor.line += 1;
|
auto half = [](const DisplayCoord& c) { return DisplayCoord{c.line / 2, c.column / 2}; };
|
||||||
ColumnCount col = anchor.column;
|
anchor = rect.pos + half(rect.size) - half(info_box.size);
|
||||||
if (style == InfoStyle::MenuDoc and m_menu)
|
}
|
||||||
col = m_menu.pos.column + m_menu.size.column;
|
else if (style == InfoStyle::MenuDoc)
|
||||||
|
{
|
||||||
|
if (not m_menu)
|
||||||
|
return;
|
||||||
|
|
||||||
const ColumnCount max_width = m_dimensions.column - col;
|
const auto right_max_width = m_dimensions.column - (m_menu.pos.column + m_menu.size.column);
|
||||||
|
const auto left_max_width = m_menu.pos.column;
|
||||||
|
const auto max_width = std::max(right_max_width, left_max_width);
|
||||||
if (max_width < 4)
|
if (max_width < 4)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (auto& line : wrap_lines(m_info.content, max_width))
|
info_box = make_simple_info_box(m_info.content, max_width);
|
||||||
info_box.push_back(line.str());
|
anchor.line = m_menu.pos.line;
|
||||||
}
|
if (info_box.size.column <= right_max_width or right_max_width >= left_max_width)
|
||||||
|
anchor.column = m_menu.pos.column + m_menu.size.column;
|
||||||
const DisplayCoord size{(int)info_box.size(),
|
else
|
||||||
accumulate(info_box | transform(&String::column_length), 0_col,
|
anchor.column = m_menu.pos.column - info_box.size.column;
|
||||||
[](auto&& lhs, auto&& rhs){ return std::max(lhs, rhs); })};
|
|
||||||
const Rect rect = {m_status_on_top ? 1_line : 0_line, m_dimensions};
|
|
||||||
DisplayCoord pos;
|
|
||||||
if (style == InfoStyle::MenuDoc and m_menu)
|
|
||||||
pos = m_menu.pos + DisplayCoord{0_line, m_menu.size.column};
|
|
||||||
else if (style == InfoStyle::Modal)
|
|
||||||
{
|
|
||||||
auto half = [](const DisplayCoord& c) { return DisplayCoord{c.line / 2, c.column / 2}; };
|
|
||||||
pos = rect.pos + half(rect.size) - half(size);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
pos = compute_pos(anchor, size, rect, m_menu, style == InfoStyle::InlineAbove);
|
{
|
||||||
|
const ColumnCount max_width = m_dimensions.column - anchor.column;
|
||||||
|
if (max_width < 4)
|
||||||
|
return;
|
||||||
|
|
||||||
|
info_box = make_simple_info_box(m_info.content, max_width);
|
||||||
|
anchor = compute_pos(anchor, info_box.size, rect, m_menu, style == InfoStyle::InlineAbove);
|
||||||
|
|
||||||
|
if (m_status_on_top)
|
||||||
|
anchor.line += 1;
|
||||||
|
}
|
||||||
|
|
||||||
// The info box does not fit
|
// The info box does not fit
|
||||||
if (pos < rect.pos or pos + size > rect.pos + rect.size)
|
if (anchor < rect.pos or anchor + info_box.size > rect.pos + rect.size)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_info.create(pos, size);
|
m_info.create(anchor, info_box.size);
|
||||||
|
|
||||||
wbkgd(m_info.win, COLOR_PAIR(get_color_pair(face)));
|
wbkgd(m_info.win, COLOR_PAIR(get_color_pair(face)));
|
||||||
for (size_t line = 0; line < info_box.size(); ++line)
|
for (auto line = 0_line; line < info_box.size.line; ++line)
|
||||||
{
|
{
|
||||||
wmove(m_info.win, line, 0);
|
wmove(m_info.win, (int)line, 0);
|
||||||
add_str(m_info.win, info_box[line]);
|
add_str(m_info.win, info_box.contents[(int)line]);
|
||||||
}
|
}
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user