window: support 'previous' background value for better composability

This commit is contained in:
Andrzej Rybczak
2014-11-11 17:37:59 +01:00
parent d26c3c8fc5
commit 059db198be
6 changed files with 72 additions and 71 deletions

View File

@@ -58,7 +58,7 @@ Clock::Clock()
Width = Config.clock_display_seconds ? 60 : 40; Width = Config.clock_display_seconds ? 60 : 40;
m_pane = NC::Window(0, MainStartY, COLS, MainHeight, "", Config.main_color, NC::Border::None); m_pane = NC::Window(0, MainStartY, COLS, MainHeight, "", Config.main_color, NC::Border::None);
w = NC::Window((COLS-Width)/2, (MainHeight-Height)/2+MainStartY, Width, Height-1, "", Config.main_color, NC::Border(Config.main_color.foreground())); w = NC::Window((COLS-Width)/2, (MainHeight-Height)/2+MainStartY, Width, Height-1, "", Config.main_color, NC::Border::None);
} }
void Clock::resize() void Clock::resize()

View File

@@ -120,7 +120,7 @@ void showSongs(NC::Menu<T> &menu, const MPD::Song &s,
x_off -= Config.now_playing_suffix_length; x_off -= Config.now_playing_suffix_length;
if (is_selected) if (is_selected)
x_off -= Config.selected_item_suffix_length; x_off -= Config.selected_item_suffix_length;
menu << NC::XY(x_off, y) << right_aligned; menu << NC::TermManip::ClearToEOL << NC::XY(x_off, y) << right_aligned;
} }
if (is_now_playing) if (is_now_playing)

View File

@@ -189,14 +189,18 @@ expressions<CharT> parseBracket(const string<CharT> &s,
{ {
++it; ++it;
rangeCheck(s, it, end); rangeCheck(s, it, end);
auto jt = it;
string<CharT> scolor; string<CharT> scolor;
do do
scolor += *it++; scolor += *it++;
while (it != end && *it != ')'); while (it != end && *it != ')');
rangeCheck(s, it, end); rangeCheck(s, it, end);
result.push_back(boost::lexical_cast<NC::Color>( auto value = convertString<char, CharT>::apply(scolor);
convertString<char, CharT>::apply(scolor) try {
)); result.push_back(boost::lexical_cast<NC::Color>(value));
} catch (boost::bad_lexical_cast &) {
throwError(s, jt, "invalid color \"" + value + "\"");
}
} }
else else
throwError(s, it, invalidCharacter(*it)); throwError(s, it, invalidCharacter(*it));

View File

@@ -444,7 +444,7 @@ void write_bindings(NC::Scrollpad &w)
section(w, "", "List of available colors"); section(w, "", "List of available colors");
for (int i = 0; i < COLORS; ++i) for (int i = 0; i < COLORS; ++i)
w << NC::Color(i) << i+1 << NC::Color::End << " "; w << NC::Color(i, NC::Color::transparent) << i+1 << NC::Color::End << " ";
} }
} }

View File

@@ -198,47 +198,45 @@ int add_base()
namespace NC { namespace NC {
Color Color::Default(0, -1, true, false); const short Color::transparent = -1;
Color Color::Black(COLOR_BLACK, -1); const short Color::previous = -2;
Color Color::Red(COLOR_RED, -1);
Color Color::Green(COLOR_GREEN, -1); Color Color::Default(0, 0, true, false);
Color Color::Yellow(COLOR_YELLOW, -1); Color Color::Black(COLOR_BLACK, Color::transparent);
Color Color::Blue(COLOR_BLUE, -1); Color Color::Red(COLOR_RED, Color::transparent);
Color Color::Magenta(COLOR_MAGENTA, -1); Color Color::Green(COLOR_GREEN, Color::transparent);
Color Color::Cyan(COLOR_CYAN, -1); Color Color::Yellow(COLOR_YELLOW, Color::transparent);
Color Color::White(COLOR_WHITE, -1); Color Color::Blue(COLOR_BLUE, Color::transparent);
Color Color::Magenta(COLOR_MAGENTA, Color::transparent);
Color Color::Cyan(COLOR_CYAN, Color::transparent);
Color Color::White(COLOR_WHITE, Color::transparent);
Color Color::End(0, 0, false, true); Color Color::End(0, 0, false, true);
std::ostream &operator<<(std::ostream &os, const Color &c) int Color::pairNumber() const
{ {
if (c.isDefault()) int result;
os << "default"; if (isDefault())
else if (c == Color::Black) result = 0;
os << "black"; else if (previousBackground())
else if (c == Color::Red) throw std::logic_error("color depends on the previous background value");
os << "red"; else if (isEnd())
else if (c == Color::Green) throw std::logic_error("'end' doesn't have a corresponding pair number");
os << "green";
else if (c == Color::Yellow)
os << "yellow";
else if (c == Color::Blue)
os << "blue";
else if (c == Color::Magenta)
os << "magenta";
else if (c == Color::Cyan)
os << "cyan";
else if (c == Color::White)
os << "white";
else if (c.isEnd())
os << "end";
else else
os << c.foreground() << "_" << c.background(); {
return os; // colors start with 0, but pairs start with 1. additionally
// first pairs are for transparent background, which has a
// value of -1, so we need to add 1 to both foreground and
// background value.
result = background() + 1;
result *= COLORS;
result += foreground() + 1;
}
return result;
} }
std::istream &operator>>(std::istream &is, Color &c) std::istream &operator>>(std::istream &is, Color &c)
{ {
auto get_single_color = [](const std::string &s) { auto get_single_color = [](const std::string &s, bool background) {
short result = -1; short result = -1;
if (s == "black") if (s == "black")
result = COLOR_BLACK; result = COLOR_BLACK;
@@ -256,6 +254,8 @@ 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 == "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());
@@ -274,16 +274,16 @@ std::istream &operator>>(std::istream &is, Color &c)
c = Color::End; c = Color::End;
else else
{ {
short value = get_single_color(sc); short value = get_single_color(sc, false);
if (value != -1) if (value != -1)
c = Color(value); c = Color(value, NC::Color::transparent);
else else
{ {
size_t underscore = sc.find('_'); size_t underscore = sc.find('_');
if (underscore != std::string::npos) if (underscore != std::string::npos)
{ {
short fg = get_single_color(sc.substr(0, underscore)); short fg = get_single_color(sc.substr(0, underscore), false);
short bg = get_single_color(sc.substr(underscore+1)); short bg = get_single_color(sc.substr(underscore+1), true);
if (fg != -1 && bg != -1) if (fg != -1 && bg != -1)
c = Color(fg, bg); c = Color(fg, bg);
else else
@@ -471,22 +471,6 @@ void destroyScreen()
endwin(); endwin();
} }
int Color::pairNumber() const
{
int result;
if (isDefault())
result = 0;
else if (isEnd())
throw std::logic_error("'end' doesn't have a corresponding pair number");
else
{
result = background();
result *= COLORS;
result += foreground();
}
return result;
}
Window::Window(size_t startx, Window::Window(size_t startx,
size_t starty, size_t starty,
size_t width, size_t width,
@@ -622,7 +606,11 @@ void Window::setColor(Color c)
if (c.isDefault()) if (c.isDefault())
c = m_base_color; c = m_base_color;
if (c != Color::Default) if (c != Color::Default)
{
if (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
wcolor_set(m_window, m_base_color.pairNumber(), nullptr); wcolor_set(m_window, m_base_color.pairNumber(), nullptr);
m_color = std::move(c); m_color = std::move(c);

View File

@@ -128,10 +128,15 @@ private:
struct Color struct Color
{ {
Color() : m_rep(0, -1, true, false) { } friend struct Window;
Color(short foregound_value, short background_value = -1,
static const short transparent;
static const short previous;
Color() : m_rep(0, transparent, true, false) { }
Color(short foreground_value, short background_value,
bool is_default = false, bool is_end = false) bool is_default = false, bool is_end = false)
: m_rep(foregound_value + 1, background_value + 1, is_default, is_end) : m_rep(foreground_value, background_value, is_default, is_end)
{ {
if (isDefault() && isEnd()) if (isDefault() && isEnd())
throw std::logic_error("Color flag can't be marked as both 'default' and 'end'"); throw std::logic_error("Color flag can't be marked as both 'default' and 'end'");
@@ -150,14 +155,6 @@ struct Color
return m_rep < rhs.m_rep; return m_rep < rhs.m_rep;
} }
short foreground() const
{
return std::get<0>(m_rep);
}
short background() const
{
return std::get<1>(m_rep);
}
bool isDefault() const bool isDefault() const
{ {
return std::get<2>(m_rep); return std::get<2>(m_rep);
@@ -181,10 +178,22 @@ struct Color
static Color End; static Color End;
private: private:
short foreground() const
{
return std::get<0>(m_rep);
}
short background() const
{
return std::get<1>(m_rep);
}
bool previousBackground() const
{
return background() == previous;
}
std::tuple<short, short, bool, bool> m_rep; std::tuple<short, short, bool, bool> m_rep;
}; };
std::ostream &operator<<(std::ostream &os, const Color &c);
std::istream &operator>>(std::istream &is, Color &f); std::istream &operator>>(std::istream &is, Color &f);
/// Terminal manipulation functions /// Terminal manipulation functions