window: change internal color representation

This commit is contained in:
Andrzej Rybczak
2014-11-08 16:34:38 +01:00
parent 8d9ddd5ff8
commit 75bae9862e
14 changed files with 211 additions and 222 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));
w = NC::Window((COLS-Width)/2, (MainHeight-Height)/2+MainStartY, Width, Height-1, "", Config.main_color, NC::Border(Config.main_color.foreground()));
}
void Clock::resize()
@@ -129,9 +129,9 @@ void Clock::update()
char buf[64];
std::strftime(buf, 64, "%x", &time);
attron(COLOR_PAIR(int(Config.main_color)));
color_set(Config.main_color.pairNumber(), nullptr);
mvprintw(w.getStarty()+w.getHeight(), w.getStartX()+(w.getWidth()-strlen(buf))/2, "%s", buf);
attroff(COLOR_PAIR(int(Config.main_color)));
standend();
refresh();
for (int k = 0; k < 6; ++k)

View File

@@ -124,7 +124,7 @@ void showSongs(NC::Menu<T> &menu, const MPD::Song &s, const ProxySongList &pl, c
else if (isdigit(*it)) // color
{
if (!discard_colors)
menu << NC::Color(*it-'0');
menu << charToColor(*it);
}
else if (*it == 'R') // right align
{

View File

@@ -27,6 +27,7 @@
#include "settings.h"
#include "status.h"
#include "utility/string.h"
#include "utility/type_conversions.h"
#include "utility/wide_string.h"
template <typename Iterator, typename PredicateT>
@@ -344,7 +345,7 @@ void stringToBuffer(Iterator first, Iterator last, NC::BasicBuffer<typename Iter
}
else if (isdigit(*it))
{
buf << NC::Color(*it-'0');
buf << charToColor(*it);
}
else
{

View File

@@ -196,7 +196,7 @@ public:
/// Sets custom color of highlighted position
/// @param col custom color
void setHighlightColor(Color color) { m_highlight_color = color; }
void setHighlightColor(Color color) { m_highlight_color = std::move(color); }
/// @return state of highlighting
bool isHighlighted() { return m_highlight_enabled; }
@@ -323,7 +323,7 @@ Menu<ItemT>::Menu(size_t startx,
const std::string &title,
Color color,
Border border)
: Window(startx, starty, width, height, title, color, border),
: Window(startx, starty, width, height, title, std::move(color), border),
m_item_displayer(0),
m_beginning(0),
m_highlight(0),

View File

@@ -107,7 +107,7 @@ int main(int argc, char **argv)
cerr_buffer = std::cerr.rdbuf();
std::cerr.rdbuf(errorlog.rdbuf());
NC::initScreen("ncmpcpp ver. " VERSION, Config.colors_enabled);
NC::initScreen(Config.colors_enabled);
Actions::OriginalStatusbarVisibility = Config.statusbar_visibility;

View File

@@ -30,9 +30,9 @@ using Global::myInactiveScreen;
void drawSeparator(int x)
{
attron(COLOR_PAIR(int(Config.main_color)));
color_set(Config.main_color.pairNumber(), nullptr);
mvvline(Global::MainStartY, x, 0, Global::MainHeight);
attroff(COLOR_PAIR(int(Config.main_color)));
standend();
refresh();
}

View File

@@ -130,7 +130,7 @@ void Scrollpad::clear()
delwin(m_window);
m_window = newpad(m_height, m_width);
setTimeout(m_window_timeout);
setColor(m_color, m_bg_color);
setColor(m_color);
keypad(m_window, 1);
}
@@ -276,7 +276,7 @@ void Scrollpad::reset()
bool Scrollpad::setProperties(Color begin, const std::string &s, Color end, size_t id, boost::regex::flag_type flags)
{
return regexSearch(m_buffer, begin, s, end, id, flags);
return regexSearch(m_buffer, std::move(begin), s, std::move(end), id, flags);
}
bool Scrollpad::setProperties(Format begin, const std::string &s, Format end, size_t id, boost::regex::flag_type flags)

View File

@@ -671,19 +671,18 @@ void Status::Changes::flags()
// this is done by raw ncurses because creating another
// window only for handling this is quite silly
attrset(A_BOLD|COLOR_PAIR(int(Config.state_line_color)));
attrset(A_BOLD);
color_set(Config.state_line_color.pairNumber(), nullptr);
mvhline(1, 0, 0, COLS);
if (!switch_state.empty())
{
mvprintw(1, COLS-switch_state.length()-3, "[");
attroff(COLOR_PAIR(int(Config.state_line_color)));
attron(COLOR_PAIR(int(Config.state_flags_color)));
color_set(Config.state_flags_color.pairNumber(), nullptr);
mvprintw(1, COLS-switch_state.length()-2, "%s", switch_state.c_str());
attroff(COLOR_PAIR(int(Config.state_flags_color)));
attron(COLOR_PAIR(int(Config.state_line_color)));
color_set(Config.state_line_color.pairNumber(), nullptr);
mvprintw(1, COLS-2, "]");
}
attrset(0);
standend();
refresh();
break;
case Design::Alternative:

View File

@@ -36,7 +36,7 @@ template <typename CharT> class BasicBuffer
enum class Type { Color, Format };
Property(size_t position_, NC::Color color_, int id_)
: m_type(Type::Color), m_position(position_), m_color(color_), m_id(id_) { }
: m_type(Type::Color), m_position(position_), m_color(std::move(color_)), m_id(id_) { }
Property(size_t position_, NC::Format format_, int id_)
: m_type(Type::Format), m_position(position_), m_format(format_), m_id(id_) { }
@@ -94,15 +94,15 @@ public:
const Properties &properties() const { return m_properties; }
template <typename PropertyT>
void setProperty(size_t position, PropertyT property, size_t id = -1)
void setProperty(size_t position, PropertyT &&property, size_t id = -1)
{
m_properties.insert(Property(position, property, id));
m_properties.insert(Property(position, std::forward<PropertyT>(property), id));
}
template <typename PropertyT>
bool removeProperty(size_t position, PropertyT property, size_t id = -1)
bool removeProperty(size_t position, PropertyT &&property, size_t id = -1)
{
auto it = m_properties.find(Property(position, property, id));
auto it = m_properties.find(Property(position, std::forward<PropertyT>(property), id));
bool found = it != m_properties.end();
if (found)
m_properties.erase(it);

View File

@@ -21,6 +21,35 @@
#include <cassert>
#include "utility/type_conversions.h"
NC::Color charToColor(char c)
{
switch (c)
{
case '0':
return NC::Color::Default;
case '1':
return NC::Color::Black;
case '2':
return NC::Color::Red;
case '3':
return NC::Color::Green;
case '4':
return NC::Color::Yellow;
case '5':
return NC::Color::Blue;
case '6':
return NC::Color::Magenta;
case '7':
return NC::Color::Cyan;
case '8':
return NC::Color::White;
case '9':
return NC::Color::End;
default:
throw std::runtime_error("invalid character");
}
}
NC::Color stringToColor(const std::string &color)
{
NC::Color result = NC::Color::Default;

View File

@@ -26,6 +26,8 @@
#include "window.h"
#include "enums.h"
NC::Color charToColor(char c);
NC::Color stringToColor(const std::string &color);
NC::Border stringToBorder(const std::string &border);

View File

@@ -51,7 +51,7 @@ const int fps = 25;
// toColor: a scaling function for coloring. For numbers 0 to max this function returns
// a coloring from the lowest color to the highest, and colors will not loop from 0 to max.
NC::Color toColor(size_t number, size_t max, bool wrap = true)
const NC::Color &toColor(size_t number, size_t max, bool wrap = true)
{
const auto colors_size = Config.visualizer_colors.size();
const auto index = (number * colors_size) / max;

View File

@@ -38,6 +38,7 @@
#include "window.h"
namespace {
namespace rl {
bool aborted;
@@ -194,43 +195,43 @@ int add_base()
}
}
namespace NC {//
namespace NC {
std::ostream &operator<<(std::ostream &os, Color c)
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);
Color Color::End(0, 0, false, true);
std::ostream &operator<<(std::ostream &os, const Color &c)
{
switch (c)
{
case Color::Default:
os << "default";
break;
case Color::Black:
os << "black";
break;
case Color::Red:
os << "red";
break;
case Color::Green:
os << "green";
break;
case Color::Yellow:
os << "yellow";
break;
case Color::Blue:
os << "blue";
break;
case Color::Magenta:
os << "magenta";
break;
case Color::Cyan:
os << "cyan";
break;
case Color::White:
os << "white";
break;
case Color::End:
os << "color_end";
break;
}
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 << "color_end";
else
os << "color_" << c.foreground() << "_" << c.background();
return os;
}
@@ -386,31 +387,19 @@ std::ostream &operator<<(std::ostream &os, Scroll s)
return os;
}
void initScreen(GNUC_UNUSED const char *window_title, bool enable_colors)
void initScreen(bool enable_colors)
{
const int ColorsTable[] =
{
COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW,
COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE
};
# ifdef XCURSES
Xinitscr(1, const_cast<char **>(&window_title));
# else
initscr();
# endif // XCURSES
if (has_colors() && enable_colors)
{
start_color();
use_default_colors();
int num = 1;
# ifdef USE_PDCURSES
int i = 0;
# else
int i = -1;
# endif // USE_PDCURSES
for (; i < 8; ++i)
for (int j = 0; j < 8; ++j)
init_pair(num++, ColorsTable[j], i < 0 ? i : ColorsTable[i]);
int npair = 1;
for (int bg = -1; bg < COLORS; ++bg)
{
for (int fg = 0; npair < COLOR_PAIRS && fg < COLORS; ++fg, ++npair)
init_pair(npair, fg, bg);
}
}
raw();
nonl();
@@ -450,6 +439,22 @@ 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,
@@ -465,9 +470,7 @@ Window::Window(size_t startx,
m_height(height),
m_window_timeout(-1),
m_color(color),
m_bg_color(Color::Default),
m_base_color(color),
m_base_bg_color(Color::Default),
m_border(border),
m_prompt_hook(0),
m_title(title),
@@ -513,9 +516,7 @@ Window::Window(const Window &rhs)
, m_height(rhs.m_height)
, m_window_timeout(rhs.m_window_timeout)
, m_color(rhs.m_color)
, m_bg_color(rhs.m_bg_color)
, m_base_color(rhs.m_base_color)
, m_base_bg_color(rhs.m_base_bg_color)
, m_border(rhs.m_border)
, m_prompt_hook(rhs.m_prompt_hook)
, m_title(rhs.m_title)
@@ -538,9 +539,7 @@ Window::Window(Window &&rhs)
, m_height(rhs.m_height)
, m_window_timeout(rhs.m_window_timeout)
, m_color(rhs.m_color)
, m_bg_color(rhs.m_bg_color)
, m_base_color(rhs.m_base_color)
, m_base_bg_color(rhs.m_base_bg_color)
, m_border(rhs.m_border)
, m_prompt_hook(rhs.m_prompt_hook)
, m_title(std::move(rhs.m_title))
@@ -566,9 +565,7 @@ Window &Window::operator=(Window rhs)
std::swap(m_height, rhs.m_height);
std::swap(m_window_timeout, rhs.m_window_timeout);
std::swap(m_color, rhs.m_color);
std::swap(m_bg_color, rhs.m_bg_color);
std::swap(m_base_color, rhs.m_base_color);
std::swap(m_base_bg_color, rhs.m_base_bg_color);
std::swap(m_border, rhs.m_border);
std::swap(m_prompt_hook, rhs.m_prompt_hook);
std::swap(m_title, rhs.m_title);
@@ -588,23 +585,20 @@ Window::~Window()
delwin(m_border_window);
}
void Window::setColor(Color fg, Color bg)
void Window::setColor(Color c)
{
if (fg == Color::Default)
fg = m_base_color;
if (fg != Color::Default)
wattron(m_window, COLOR_PAIR(int(bg)*8+int(fg)));
if (c.isDefault())
c = m_base_color;
if (c != Color::Default)
wcolor_set(m_window, c.pairNumber(), nullptr);
else
wattroff(m_window, COLOR_PAIR(int(m_color)));
m_color = fg;
m_bg_color = bg;
wcolor_set(m_window, m_base_color.pairNumber(), nullptr);
m_color = std::move(c);
}
void Window::setBaseColor(Color fg, Color bg)
void Window::setBaseColor(Color c)
{
m_base_color = fg;
m_base_bg_color = bg;
m_base_color = std::move(c);
}
void Window::setBorder(Border border)
@@ -663,7 +657,7 @@ void Window::recreate(size_t width, size_t height)
delwin(m_window);
m_window = newpad(height, width);
setTimeout(m_window_timeout);
setColor(m_color, m_bg_color);
setColor(m_color);
keypad(m_window, 1);
}
@@ -712,7 +706,7 @@ void Window::refreshBorder() const
if (m_border != Border::None)
attron(COLOR_PAIR(int(m_border)));
else
attron(COLOR_PAIR(int(m_base_color)));
wcolor_set(m_border_window, m_base_color.pairNumber(), nullptr);
mvhline(m_start_y-1, m_start_x, 0, m_width);
attron(A_BOLD);
mvhline(m_start_y-2, m_start_x, 32, m_width); // clear title line
@@ -961,7 +955,7 @@ const std::string &Window::getTitle() const
return m_title;
}
Color Window::getColor() const
const Color &Window::getColor() const
{
return m_color;
}
@@ -1002,43 +996,27 @@ void Window::scroll(Scroll where)
}
Window &Window::operator<<(Colors colors)
Window &Window::operator<<(const Color &c)
{
if (colors.fg == Color::End || colors.bg == Color::End)
if (c.isDefault())
{
*this << Color::End;
return *this;
while (!m_color_stack.empty())
m_color_stack.pop();
setColor(m_base_color);
}
m_color_stack.push(colors);
setColor(colors.fg, colors.bg);
return *this;
}
Window &Window::operator<<(Color color)
{
switch (color)
else if (c.isEnd())
{
case Color::Default:
while (!m_color_stack.empty())
m_color_stack.pop();
setColor(m_base_color, m_base_bg_color);
break;
case Color::End:
if (!m_color_stack.empty())
m_color_stack.pop();
if (!m_color_stack.empty())
setColor(m_color_stack.top().fg, m_color_stack.top().bg);
else
setColor(m_base_color, m_base_bg_color);
break;
default:
Color bg;
if (m_color_stack.empty())
bg = m_bg_color;
else
bg = m_color_stack.top().bg;
m_color_stack.push(Colors(color, bg));
setColor(m_color_stack.top().fg, m_color_stack.top().bg);
if (!m_color_stack.empty())
m_color_stack.pop();
if (!m_color_stack.empty())
setColor(m_color_stack.top());
else
setColor(m_base_color);
}
else
{
setColor(c);
m_color_stack.push(c);
}
return *this;
}
@@ -1090,7 +1068,7 @@ Window &Window::operator<<(int (*f)(WINDOW *))
return *this;
}
Window &Window::operator<<(XY coords)
Window &Window::operator<<(const XY &coords)
{
goToXY(coords.x, coords.y);
return *this;

View File

@@ -35,6 +35,7 @@
#include <stack>
#include <vector>
#include <string>
#include <tuple>
#include <queue>
// define some Ctrl-? keys
@@ -125,11 +126,66 @@ private:
std::string m_prompt;
};
/// Colors used by NCurses
enum class Color { Default, Black, Red, Green, Yellow, Blue, Magenta, Cyan, White, End };
struct Color
{
Color() : m_rep(0, -1, true, false) { }
Color(short foregound_value, short background_value = -1,
bool is_default = false, bool is_end = false)
: m_rep(foregound_value + 1, background_value + 1, is_default, is_end)
{
if (isDefault() && isEnd())
throw std::logic_error("Color flag can't be marked as both 'default' and 'end'");
}
std::ostream &operator<<(std::ostream &os, Color c);
std::istream &operator>>(std::istream &is, Color &c);
bool operator==(const Color &rhs) const
{
return m_rep == rhs.m_rep;
}
bool operator!=(const Color &rhs) const
{
return m_rep != rhs.m_rep;
}
bool operator<(const Color &rhs) const
{
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);
}
bool isEnd() const
{
return std::get<3>(m_rep);
}
int pairNumber() const;
static Color Default;
static Color Black;
static Color Red;
static Color Green;
static Color Yellow;
static Color Blue;
static Color Magenta;
static Color Cyan;
static Color White;
static Color End;
private:
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);
/// Format flags used by NCurses
enum class Format {
@@ -154,22 +210,12 @@ enum class Scroll { Up, Down, PageUp, PageDown, Home, End };
std::ostream &operator<<(std::ostream &os, Scroll s);
/// Initializes curses screen and sets some additional attributes
/// @param window_title title of the window (has an effect only if pdcurses lib is used)
/// @param enable_colors enables colors
void initScreen(const char *window_title, bool enable_colors);
void initScreen(bool enable_colors);
/// Destroys the screen
void destroyScreen();
/// Struct used to set color of both foreground and background of window
/// @see Window::operator<<()
struct Colors
{
Colors(Color one, Color two = Color::Default) : fg(one), bg(two) { }
Color fg;
Color bg;
};
/// Struct used for going to given coordinates
/// @see Window::operator<<()
struct XY
@@ -244,7 +290,7 @@ struct Window
const std::string &getTitle() const;
/// @return current window's color
Color getColor() const;
const Color &getColor() const;
/// @return current window's border
Border getBorder() const;
@@ -301,7 +347,7 @@ struct Window
/// Sets window's base color
/// @param fg foregound base color
/// @param bg background base color
void setBaseColor(Color fg, Color bg = Color::Default);
void setBaseColor(Color c);
/// Sets window's border
/// @param border new window's border
@@ -365,89 +411,25 @@ struct Window
virtual void scroll(Scroll where);
/// Applies function of compatible prototype to internal WINDOW pointer
/// The mostly used function in this case seem to be wclrtoeol(), which
/// clears the window from current cursor position to the end of line.
/// Note that delwin() also matches that prototype, but I wouldn't
/// recommend anyone passing this pointer here ;)
/// @param f pointer to function to call with internal WINDOW pointer
/// @return reference to itself
Window &operator<<(int (*f)(WINDOW *));
/// Applies foreground and background colors to window
/// @param colors struct that holds new colors information
/// @return reference to itself
Window &operator<<(Colors colors);
/// Applies foregound color to window. Note that colors applied
/// that way are stacked, i.e if you applied Color::Red, then Color::Green
/// and Color::End, current color would be Color::Red. If you want to discard
/// all colors and fall back to base one, pass Color::Default.
/// @param color new color value
/// @return reference to itself
Window &operator<<(Color color);
/// Applies format flag to window. Note that these attributes are
/// also stacked, so if you applied Format::Bold twice, to get rid of
/// it you have to pass Format::NoBold also twice.
/// @param format format flag
/// @return reference to itself
Window &operator<<(const Color &color);
Window &operator<<(Format format);
/// Moves current cursor position to given coordinates.
/// @param coords struct that holds information about new coordinations
/// @return reference to itself
Window &operator<<(XY coords);
/// Prints string to window
/// @param s const pointer to char array to be printed
/// @return reference to itself
Window &operator<<(const XY &coords);
Window &operator<<(const char *s);
/// Prints single character to window
/// @param c character to be printed
/// @return reference to itself
Window &operator<<(char c);
/// Prints wide string to window
/// @param ws const pointer to wchar_t array to be printed
/// @return reference to itself
Window &operator<<(const wchar_t *ws);
/// Prints single wide character to window
/// @param wc wide character to be printed
/// @return reference to itself
Window &operator<<(wchar_t wc);
/// Prints int to window
/// @param i integer value to be printed
/// @return reference to itself
Window &operator<<(int i);
/// Prints double to window
/// @param d double value to be printed
/// @return reference to itself
Window &operator<<(double d);
/// Prints size_t to window
/// @param s size value to be printed
/// @return reference to itself
Window &operator<<(size_t s);
/// Prints std::string to window
/// @param s string to be printed
/// @return reference to itself
Window &operator<<(const std::string &s);
/// Prints std::wstring to window
/// @param ws wide string to be printed
/// @return reference to itself
Window &operator<<(const std::wstring &ws);
protected:
/// Sets colors of window (interal use only)
/// @param fg foregound color
/// @param bg background color
///
void setColor(Color fg, Color bg = Color::Default);
void setColor(Color c);
/// Refreshes window's border
///
@@ -485,11 +467,9 @@ protected:
/// current colors
Color m_color;
Color m_bg_color;
/// base colors
Color m_base_color;
Color m_base_bg_color;
/// current border
Border m_border;
@@ -524,7 +504,7 @@ private:
std::string m_title;
/// stack of colors
std::stack<Colors> m_color_stack;
std::stack<Color> m_color_stack;
/// input queue of a window. you can put characters there using
/// PushChar and they will be immediately consumed and