Retain previous background by default when switching colors
This commit is contained in:
@@ -503,11 +503,10 @@
|
|||||||
## progressbar_color, progressbar_elapsed_color,
|
## progressbar_color, progressbar_elapsed_color,
|
||||||
## alternative_ui_separator_color.
|
## alternative_ui_separator_color.
|
||||||
##
|
##
|
||||||
## Note: due to technical limitations of ncurses, if 256 colors
|
## Note: due to technical limitations of older ncurses
|
||||||
## are used, it is possible to either use only the colors with
|
## versionw, if 256 colors are used there is a possibility
|
||||||
## default background color, or all pairs from 1_1 up to 254_127,
|
## that you'll be able to use only colors with transparent
|
||||||
## depending on the ncurses version used.
|
## background.
|
||||||
##
|
|
||||||
#
|
#
|
||||||
#colors_enabled = yes
|
#colors_enabled = yes
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -217,11 +217,11 @@ void Menu<ItemT>::refresh()
|
|||||||
*this << Format::Reverse;
|
*this << Format::Reverse;
|
||||||
*this << m_highlight_color;
|
*this << m_highlight_color;
|
||||||
}
|
}
|
||||||
mvwhline(m_window, line, 0, NC::Key::Space, m_width);
|
|
||||||
if ((*m_items)[m_drawn_position].isSelected())
|
if ((*m_items)[m_drawn_position].isSelected())
|
||||||
*this << m_selected_prefix;
|
*this << m_selected_prefix;
|
||||||
if (m_item_displayer)
|
if (m_item_displayer)
|
||||||
m_item_displayer(*this);
|
m_item_displayer(*this);
|
||||||
|
*this << NC::TermManip::ClearToEOL;
|
||||||
if ((*m_items)[m_drawn_position].isSelected())
|
if ((*m_items)[m_drawn_position].isSelected())
|
||||||
*this << m_selected_suffix;
|
*this << m_selected_suffix;
|
||||||
if (m_highlight_enabled && m_drawn_position == m_highlight)
|
if (m_highlight_enabled && m_drawn_position == m_highlight)
|
||||||
|
|||||||
@@ -187,6 +187,10 @@ int add_base()
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int color_pair_counter;
|
||||||
|
std::vector<int> color_pair_map;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace NC {
|
namespace NC {
|
||||||
@@ -195,42 +199,56 @@ const short Color::transparent = -1;
|
|||||||
const short Color::previous = -2;
|
const short Color::previous = -2;
|
||||||
|
|
||||||
Color Color::Default(0, 0, true, false);
|
Color Color::Default(0, 0, true, false);
|
||||||
Color Color::Black(COLOR_BLACK, Color::transparent);
|
Color Color::Black(COLOR_BLACK, Color::previous);
|
||||||
Color Color::Red(COLOR_RED, Color::transparent);
|
Color Color::Red(COLOR_RED, Color::previous);
|
||||||
Color Color::Green(COLOR_GREEN, Color::transparent);
|
Color Color::Green(COLOR_GREEN, Color::previous);
|
||||||
Color Color::Yellow(COLOR_YELLOW, Color::transparent);
|
Color Color::Yellow(COLOR_YELLOW, Color::previous);
|
||||||
Color Color::Blue(COLOR_BLUE, Color::transparent);
|
Color Color::Blue(COLOR_BLUE, Color::previous);
|
||||||
Color Color::Magenta(COLOR_MAGENTA, Color::transparent);
|
Color Color::Magenta(COLOR_MAGENTA, Color::previous);
|
||||||
Color Color::Cyan(COLOR_CYAN, Color::transparent);
|
Color Color::Cyan(COLOR_CYAN, Color::previous);
|
||||||
Color Color::White(COLOR_WHITE, Color::transparent);
|
Color Color::White(COLOR_WHITE, Color::previous);
|
||||||
Color Color::End(0, 0, false, true);
|
Color Color::End(0, 0, false, true);
|
||||||
|
|
||||||
int Color::pairNumber() const
|
int Color::pairNumber() const
|
||||||
{
|
{
|
||||||
int result;
|
int result = 0;
|
||||||
if (isDefault())
|
if (isEnd())
|
||||||
result = 0;
|
|
||||||
else if (previousBackground())
|
|
||||||
throw std::logic_error("color depends on the previous background value");
|
|
||||||
else if (isEnd())
|
|
||||||
throw std::logic_error("'end' doesn't have a corresponding pair number");
|
throw std::logic_error("'end' doesn't have a corresponding pair number");
|
||||||
|
else if (!isDefault())
|
||||||
|
{
|
||||||
|
if (!previousBackground())
|
||||||
|
result = background() + 1;
|
||||||
|
result *= 256;
|
||||||
|
result += foreground();
|
||||||
|
|
||||||
|
assert(result < int(color_pair_map.size()));
|
||||||
|
|
||||||
|
// NCurses allows for a limited number of color pairs to be registered, so
|
||||||
|
// in order to be able to support all the combinations we want to, we need
|
||||||
|
// to dynamically register only pairs of colors we're actually using.
|
||||||
|
if (!color_pair_map[result])
|
||||||
|
{
|
||||||
|
// Check if there are any unused pairs left and either register the one
|
||||||
|
// that was requested or return a default one if there is no space left.
|
||||||
|
if (color_pair_counter >= COLOR_PAIRS)
|
||||||
|
result = 0;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// colors start with 0, but pairs start with 1. additionally
|
init_pair(color_pair_counter, foreground(), background());
|
||||||
// first pairs are for transparent background, which has a
|
color_pair_map[result] = color_pair_counter;
|
||||||
// value of -1, so we need to add 1 to both foreground and
|
++color_pair_counter;
|
||||||
// background value.
|
}
|
||||||
result = background() + 1;
|
}
|
||||||
result *= COLORS;
|
result = color_pair_map[result];
|
||||||
result += foreground() + 1;
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::istream &operator>>(std::istream &is, Color &c)
|
std::istream &operator>>(std::istream &is, Color &c)
|
||||||
{
|
{
|
||||||
|
const short invalid_color_value = -1337;
|
||||||
auto get_single_color = [](const std::string &s, bool background) {
|
auto get_single_color = [](const std::string &s, bool background) {
|
||||||
short result = -1;
|
short result = invalid_color_value;
|
||||||
if (s == "black")
|
if (s == "black")
|
||||||
result = COLOR_BLACK;
|
result = COLOR_BLACK;
|
||||||
else if (s == "red")
|
else if (s == "red")
|
||||||
@@ -247,13 +265,15 @@ std::istream &operator>>(std::istream &is, Color &c)
|
|||||||
result = COLOR_CYAN;
|
result = COLOR_CYAN;
|
||||||
else if (s == "white")
|
else if (s == "white")
|
||||||
result = COLOR_WHITE;
|
result = COLOR_WHITE;
|
||||||
|
else if (background && s == "transparent")
|
||||||
|
result = NC::Color::transparent;
|
||||||
else if (background && s == "previous")
|
else if (background && s == "previous")
|
||||||
result = NC::Color::previous;
|
result = NC::Color::previous;
|
||||||
else if (std::all_of(s.begin(), s.end(), isdigit))
|
else if (std::all_of(s.begin(), s.end(), isdigit))
|
||||||
{
|
{
|
||||||
result = atoi(s.c_str());
|
result = atoi(s.c_str());
|
||||||
if (result < 1 || result > 256)
|
if (result < (background ? 0 : 1) || result > 256)
|
||||||
result = -1;
|
result = invalid_color_value;
|
||||||
else
|
else
|
||||||
--result;
|
--result;
|
||||||
}
|
}
|
||||||
@@ -276,7 +296,7 @@ std::istream &operator>>(std::istream &is, Color &c)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
short fg = get_single_color(sc, false);
|
short fg = get_single_color(sc, false);
|
||||||
if (fg == -1)
|
if (fg == invalid_color_value)
|
||||||
is.setstate(std::ios::failbit);
|
is.setstate(std::ios::failbit);
|
||||||
// Check if there is background color
|
// Check if there is background color
|
||||||
else if (!is.eof() && is.peek() == '_')
|
else if (!is.eof() && is.peek() == '_')
|
||||||
@@ -284,13 +304,13 @@ std::istream &operator>>(std::istream &is, Color &c)
|
|||||||
is.get();
|
is.get();
|
||||||
sc = get_color(is);
|
sc = get_color(is);
|
||||||
short bg = get_single_color(sc, true);
|
short bg = get_single_color(sc, true);
|
||||||
if (bg == -1)
|
if (bg == invalid_color_value)
|
||||||
is.setstate(std::ios::failbit);
|
is.setstate(std::ios::failbit);
|
||||||
else
|
else
|
||||||
c = Color(fg, bg);
|
c = Color(fg, bg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
c = Color(fg, NC::Color::transparent);
|
c = Color(fg, NC::Color::previous);
|
||||||
}
|
}
|
||||||
return is;
|
return is;
|
||||||
}
|
}
|
||||||
@@ -365,11 +385,16 @@ void initScreen(bool enable_colors, bool enable_mouse)
|
|||||||
{
|
{
|
||||||
start_color();
|
start_color();
|
||||||
use_default_colors();
|
use_default_colors();
|
||||||
int npair = 1;
|
color_pair_map.resize(256 * 256, 0);
|
||||||
for (int bg = -1; bg < COLORS; ++bg)
|
|
||||||
|
// Predefine pairs for colors with transparent background, all the other
|
||||||
|
// ones will be dynamically registered in Color::pairNumber when they're
|
||||||
|
// used.
|
||||||
|
color_pair_counter = 1;
|
||||||
|
for (int fg = 0; fg < COLORS; ++fg, ++color_pair_counter)
|
||||||
{
|
{
|
||||||
for (int fg = 0; npair < COLOR_PAIRS && fg < COLORS; ++fg, ++npair)
|
init_pair(color_pair_counter, fg, -1);
|
||||||
init_pair(npair, fg, bg);
|
color_pair_map[fg] = color_pair_counter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
raw();
|
raw();
|
||||||
@@ -418,21 +443,14 @@ void destroyScreen()
|
|||||||
endwin();
|
endwin();
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::Window(size_t startx,
|
Window::Window(size_t startx, size_t starty, size_t width, size_t height,
|
||||||
size_t starty,
|
std::string title, Color color, Border border)
|
||||||
size_t width,
|
|
||||||
size_t height,
|
|
||||||
std::string title,
|
|
||||||
Color color,
|
|
||||||
Border border)
|
|
||||||
: m_window(nullptr),
|
: m_window(nullptr),
|
||||||
m_start_x(startx),
|
m_start_x(startx),
|
||||||
m_start_y(starty),
|
m_start_y(starty),
|
||||||
m_width(width),
|
m_width(width),
|
||||||
m_height(height),
|
m_height(height),
|
||||||
m_window_timeout(-1),
|
m_window_timeout(-1),
|
||||||
m_color(color),
|
|
||||||
m_base_color(color),
|
|
||||||
m_border(std::move(border)),
|
m_border(std::move(border)),
|
||||||
m_prompt_hook(0),
|
m_prompt_hook(0),
|
||||||
m_title(std::move(title)),
|
m_title(std::move(title)),
|
||||||
@@ -463,7 +481,8 @@ Window::Window(size_t startx,
|
|||||||
|
|
||||||
m_window = newpad(m_height, m_width);
|
m_window = newpad(m_height, m_width);
|
||||||
|
|
||||||
setColor(m_color);
|
setBaseColor(color);
|
||||||
|
setColor(m_base_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::Window(const Window &rhs)
|
Window::Window(const Window &rhs)
|
||||||
@@ -548,8 +567,7 @@ void Window::setColor(Color c)
|
|||||||
c = m_base_color;
|
c = m_base_color;
|
||||||
if (c != Color::Default)
|
if (c != Color::Default)
|
||||||
{
|
{
|
||||||
if (c.previousBackground())
|
assert(!c.previousBackground());
|
||||||
c = Color(c.foreground(), m_color.background());
|
|
||||||
wcolor_set(m_window, c.pairNumber(), nullptr);
|
wcolor_set(m_window, c.pairNumber(), nullptr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -557,9 +575,12 @@ void Window::setColor(Color c)
|
|||||||
m_color = std::move(c);
|
m_color = std::move(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::setBaseColor(Color c)
|
void Window::setBaseColor(const Color &color)
|
||||||
{
|
{
|
||||||
m_base_color = std::move(c);
|
if (color.previousBackground())
|
||||||
|
m_base_color = Color(color.foreground(), Color::transparent);
|
||||||
|
else
|
||||||
|
m_base_color = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::setBorder(Border border)
|
void Window::setBorder(Border border)
|
||||||
@@ -1289,10 +1310,22 @@ Window &Window::operator<<(const Color &c)
|
|||||||
setColor(m_base_color);
|
setColor(m_base_color);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (c.previousBackground())
|
||||||
|
{
|
||||||
|
short background = m_color.isDefault()
|
||||||
|
? Color::transparent
|
||||||
|
: m_color.background();
|
||||||
|
Color cc = Color(c.foreground(), background);
|
||||||
|
setColor(cc);
|
||||||
|
m_color_stack.push(cc);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
setColor(c);
|
setColor(c);
|
||||||
m_color_stack.push(c);
|
m_color_stack.push(c);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -354,7 +354,7 @@ struct Window
|
|||||||
/// Sets window's base color
|
/// Sets window's base color
|
||||||
/// @param fg foregound base color
|
/// @param fg foregound base color
|
||||||
/// @param bg background base color
|
/// @param bg background base color
|
||||||
void setBaseColor(Color c);
|
void setBaseColor(const Color &color);
|
||||||
|
|
||||||
/// Sets window's border
|
/// Sets window's border
|
||||||
/// @param border new window's border
|
/// @param border new window's border
|
||||||
|
|||||||
Reference in New Issue
Block a user