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

View File

@@ -120,7 +120,7 @@ void showSongs(NC::Menu<T> &menu, const MPD::Song &s,
x_off -= Config.now_playing_suffix_length;
if (is_selected)
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)

View File

@@ -189,14 +189,18 @@ expressions<CharT> parseBracket(const string<CharT> &s,
{
++it;
rangeCheck(s, it, end);
auto jt = it;
string<CharT> scolor;
do
scolor += *it++;
while (it != end && *it != ')');
rangeCheck(s, it, end);
result.push_back(boost::lexical_cast<NC::Color>(
convertString<char, CharT>::apply(scolor)
));
auto value = 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
throwError(s, it, invalidCharacter(*it));

View File

@@ -444,7 +444,7 @@ void write_bindings(NC::Scrollpad &w)
section(w, "", "List of available colors");
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 {
Color Color::Default(0, -1, true, false);
Color Color::Black(COLOR_BLACK, -1);
Color Color::Red(COLOR_RED, -1);
Color Color::Green(COLOR_GREEN, -1);
Color Color::Yellow(COLOR_YELLOW, -1);
Color Color::Blue(COLOR_BLUE, -1);
Color Color::Magenta(COLOR_MAGENTA, -1);
Color Color::Cyan(COLOR_CYAN, -1);
Color Color::White(COLOR_WHITE, -1);
const short Color::transparent = -1;
const short Color::previous = -2;
Color Color::Default(0, 0, true, false);
Color Color::Black(COLOR_BLACK, Color::transparent);
Color Color::Red(COLOR_RED, Color::transparent);
Color Color::Green(COLOR_GREEN, Color::transparent);
Color Color::Yellow(COLOR_YELLOW, Color::transparent);
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);
std::ostream &operator<<(std::ostream &os, const Color &c)
int Color::pairNumber() const
{
if (c.isDefault())
os << "default";
else if (c == Color::Black)
os << "black";
else if (c == Color::Red)
os << "red";
else if (c == Color::Green)
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";
int result;
if (isDefault())
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");
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)
{
auto get_single_color = [](const std::string &s) {
auto get_single_color = [](const std::string &s, bool background) {
short result = -1;
if (s == "black")
result = COLOR_BLACK;
@@ -256,6 +254,8 @@ std::istream &operator>>(std::istream &is, Color &c)
result = COLOR_CYAN;
else if (s == "white")
result = COLOR_WHITE;
else if (background && s == "previous")
result = NC::Color::previous;
else if (std::all_of(s.begin(), s.end(), isdigit))
{
result = atoi(s.c_str());
@@ -274,16 +274,16 @@ std::istream &operator>>(std::istream &is, Color &c)
c = Color::End;
else
{
short value = get_single_color(sc);
short value = get_single_color(sc, false);
if (value != -1)
c = Color(value);
c = Color(value, NC::Color::transparent);
else
{
size_t underscore = sc.find('_');
if (underscore != std::string::npos)
{
short fg = get_single_color(sc.substr(0, underscore));
short bg = get_single_color(sc.substr(underscore+1));
short fg = get_single_color(sc.substr(0, underscore), false);
short bg = get_single_color(sc.substr(underscore+1), true);
if (fg != -1 && bg != -1)
c = Color(fg, bg);
else
@@ -471,22 +471,6 @@ void destroyScreen()
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,
size_t starty,
size_t width,
@@ -622,7 +606,11 @@ void Window::setColor(Color c)
if (c.isDefault())
c = m_base_color;
if (c != Color::Default)
{
if (c.previousBackground())
c = Color(c.foreground(), m_color.background());
wcolor_set(m_window, c.pairNumber(), nullptr);
}
else
wcolor_set(m_window, m_base_color.pairNumber(), nullptr);
m_color = std::move(c);

View File

@@ -128,10 +128,15 @@ private:
struct Color
{
Color() : m_rep(0, -1, true, false) { }
Color(short foregound_value, short background_value = -1,
friend struct Window;
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)
: 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())
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;
}
short foreground() const
{
return std::get<0>(m_rep);
}
short background() const
{
return std::get<1>(m_rep);
}
bool isDefault() const
{
return std::get<2>(m_rep);
@@ -181,10 +178,22 @@ struct Color
static Color End;
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::ostream &operator<<(std::ostream &os, const Color &c);
std::istream &operator>>(std::istream &is, Color &f);
/// Terminal manipulation functions