git-svn-id: svn://db.shs.com.ru/pip@110 12ceb7fc-bf1f-11e4-8940-5bc7170c53b5
256 lines
7.6 KiB
C++
256 lines
7.6 KiB
C++
/*
|
|
PIP - Platform Independent Primitives
|
|
Console output/input
|
|
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "piscreendrawer.h"
|
|
|
|
/** \class PIScreenDrawer
|
|
* \brief Console output class
|
|
* \details
|
|
* \section PIScreen_sec0 Synopsis
|
|
* This class provides output to console with automatic alignment and update.
|
|
* It supports tabs, keyboard listening, formats and colors.
|
|
*
|
|
* \section PIScreen_sec1 Layout
|
|
* %PIScreen works with variable pointers. You should add your variables with
|
|
* functions \a addVariable() which receives label name, pointer to variable
|
|
* and optional column and format. Columns count is dynamically increased if
|
|
* new column used. E.g. if you add variable to empty tab to column 3, columns
|
|
* count will be increased to 3, but two firsts columns will be empty. Each column
|
|
* filled from top to bottom, but you can add just string with function
|
|
* \a addString() or add empty line with function \a addEmptyLine(). Layout scheme:
|
|
* \image html piconsole_layout.png
|
|
*
|
|
* \section PIScreen_sec2 Keyboard usage
|
|
* %PIScreen should to be single in application. %PIScreen aggregate PIKbdListener
|
|
* which grab keyboard and automatic switch tabs by theirs bind keys. If there is no
|
|
* tab binded to pressed key external function "slot" will be called
|
|
*
|
|
**/
|
|
|
|
using namespace PIScreenTypes;
|
|
|
|
|
|
PIScreenDrawer::PIScreenDrawer(PIVector<PIVector<Cell> > & c): cells(c) {
|
|
arts_[LineVertical] =
|
|
#ifdef PIP_ICU
|
|
PIChar::fromUTF8("│");
|
|
#else
|
|
PIChar('|');
|
|
#endif
|
|
|
|
arts_[LineHorizontal] =
|
|
#ifdef PIP_ICU
|
|
PIChar::fromUTF8("─");
|
|
#else
|
|
PIChar('-');
|
|
#endif
|
|
|
|
arts_[Cross] =
|
|
#ifdef PIP_ICU
|
|
PIChar::fromUTF8("┼");
|
|
#else
|
|
PIChar('+');
|
|
#endif
|
|
|
|
arts_[CornerTopLeft] =
|
|
#ifdef PIP_ICU
|
|
PIChar::fromUTF8("┌");
|
|
#else
|
|
PIChar('+');
|
|
#endif
|
|
|
|
arts_[CornerTopRight] =
|
|
#ifdef PIP_ICU
|
|
PIChar::fromUTF8("┐");
|
|
#else
|
|
PIChar('+');
|
|
#endif
|
|
|
|
arts_[CornerBottomLeft] =
|
|
#ifdef PIP_ICU
|
|
PIChar::fromUTF8("└");
|
|
#else
|
|
PIChar('+');
|
|
#endif
|
|
|
|
arts_[CornerBottomRight] =
|
|
#ifdef PIP_ICU
|
|
PIChar::fromUTF8("┘");
|
|
#else
|
|
PIChar('+');
|
|
#endif
|
|
}
|
|
|
|
|
|
void PIScreenDrawer::clear() {
|
|
for (int i = 0; i < cells.size_s(); ++i)
|
|
cells[i].fill(Cell());
|
|
}
|
|
|
|
|
|
void PIScreenDrawer::drawPixel(int x, int y, const PIChar & c, Color col_char, Color col_back, CharFlags flags_char) {
|
|
if (x < 0 || x >= width || y < 0 || y >= height) return;
|
|
cells[y][x].symbol = c;
|
|
cells[y][x].format.color_char = col_char;
|
|
cells[y][x].format.color_back = col_back;
|
|
cells[y][x].format.flags = flags_char;
|
|
}
|
|
|
|
|
|
void PIScreenDrawer::drawLine(int x0, int y0, int x1, int y1, const PIChar & c, Color col_char, Color col_back, CharFlags flags_char) {
|
|
if (x0 == x1 && y0 == y1) drawPixel(x0, y0, c, col_char, col_back, flags_char);
|
|
Cell cc;
|
|
cc.symbol = c;
|
|
cc.format.color_char = col_char;
|
|
cc.format.color_back = col_back;
|
|
cc.format.flags = flags_char;
|
|
int x = 0, y = 0;
|
|
if (piAbsi(x1 - x0) >= piAbsi(y1 - y0)) {
|
|
float dy = (y1 - y0) / float(piAbsi(x1 - x0)), cy = y0;
|
|
int dx = x0 < x1 ? 1 : -1;
|
|
for (int i = x0; i != x1; i += dx) {
|
|
x = i; y = piRound(cy);
|
|
if (x >= 0 && x < width && y >= 0 && y < height)
|
|
cells[y][x] = cc;
|
|
cy += dy;
|
|
}
|
|
y = piRound(cy);
|
|
if (x1 >= 0 && x1 < width && y >= 0 && y < height)
|
|
cells[y][x1] = cc;
|
|
} else {
|
|
float dx = (x1 - x0) / float(piAbsi(y1 - y0)), cx = x0;
|
|
int dy = y0 < y1 ? 1 : -1;
|
|
for (int i = y0; i != y1; i += dy) {
|
|
x = piRound(cx); y = i;
|
|
if (x >= 0 && x < width && y >= 0 && y < height)
|
|
cells[y][x] = cc;
|
|
cx += dx;
|
|
}
|
|
x = piRound(cx);
|
|
if (x >= 0 && x < width && y1 >= 0 && y1 < height)
|
|
cells[y1][x] = cc;
|
|
}
|
|
}
|
|
|
|
|
|
void PIScreenDrawer::drawRect(int x0, int y0, int x1, int y1, const PIChar & c, Color col_char, Color col_back, CharFlags flags_char) {
|
|
if (x0 == x1 && y0 == y1) drawPixel(x0, y0, c, col_char, col_back, flags_char);
|
|
Cell cc;
|
|
cc.symbol = c;
|
|
cc.format.color_char = col_char;
|
|
cc.format.color_back = col_back;
|
|
cc.format.flags = flags_char;
|
|
int dx = x0 < x1 ? 1 : -1;
|
|
int dy = y0 < y1 ? 1 : -1;
|
|
int xs[2] = {x0, x1};
|
|
int ys[2] = {y0, y1};
|
|
for (int k = 0; k < 2; ++k) {
|
|
int j = ys[k];
|
|
if (j >= 0 && j < height) {
|
|
PIVector<Cell> & cv(cells[j]);
|
|
for (int i = x0; i != x1; i += dx)
|
|
if (i >= 0 && i < width)
|
|
cv[i] = cc;
|
|
}
|
|
j = xs[k];
|
|
if (j >= 0 && j < width) {
|
|
for (int i = y0; i != y1; i += dy)
|
|
if (i >= 0 && i < height)
|
|
cells[i][j] = cc;
|
|
}
|
|
}
|
|
int i = x1, j = y1;
|
|
if (i >= 0 && i < width && j >= 0 && j < height)
|
|
cells[j][i] = cc;
|
|
}
|
|
|
|
|
|
void PIScreenDrawer::drawFrame(int x0, int y0, int x1, int y1, Color col_char, Color col_back, CharFlags flags_char) {
|
|
if (x0 == x1 && y0 == y1) return;
|
|
Cell cc;
|
|
cc.format.color_char = col_char;
|
|
cc.format.color_back = col_back;
|
|
cc.format.flags = flags_char;
|
|
int dx = x0 < x1 ? 1 : -1;
|
|
int dy = y0 < y1 ? 1 : -1;
|
|
int xs[2] = {x0, x1};
|
|
int ys[2] = {y0, y1};
|
|
for (int k = 0; k < 2; ++k) {
|
|
int j = ys[k];
|
|
if (j >= 0 && j < height) {
|
|
PIVector<Cell> & cv(cells[j]);
|
|
cc.symbol = artChar(LineHorizontal);
|
|
for (int i = x0 + 1; i != x1; i += dx)
|
|
if (i >= 0 && i < width)
|
|
cv[i] = cc;
|
|
}
|
|
j = xs[k];
|
|
if (j >= 0 && j < width) {
|
|
cc.symbol = artChar(LineVertical);
|
|
for (int i = y0 + 1; i != y1; i += dy)
|
|
if (i >= 0 && i < height)
|
|
cells[i][j] = cc;
|
|
}
|
|
}
|
|
int i = x0, j = y0; cc.symbol = artChar(CornerTopLeft);
|
|
if (i >= 0 && i < width && j >= 0 && j < height) cells[j][i] = cc;
|
|
i = x1, j = y0; cc.symbol = artChar(CornerTopRight);
|
|
if (i >= 0 && i < width && j >= 0 && j < height) cells[j][i] = cc;
|
|
i = x0, j = y1; cc.symbol = artChar(CornerBottomLeft);
|
|
if (i >= 0 && i < width && j >= 0 && j < height) cells[j][i] = cc;
|
|
i = x1, j = y1; cc.symbol = artChar(CornerBottomRight);
|
|
if (i >= 0 && i < width && j >= 0 && j < height) cells[j][i] = cc;
|
|
}
|
|
|
|
|
|
void PIScreenDrawer::fillRect(int x0, int y0, int x1, int y1, const PIChar & c, Color col_char, Color col_back, CharFlags flags_char) {
|
|
if (x0 == x1 && y0 == y1) drawPixel(x0, y0, c, col_char, col_back, flags_char);
|
|
Cell cc;
|
|
cc.symbol = c;
|
|
cc.format.color_char = col_char;
|
|
cc.format.color_back = col_back;
|
|
cc.format.flags = flags_char;
|
|
int dx = x0 < x1 ? 1 : -1;
|
|
int dy = y0 < y1 ? 1 : -1;
|
|
for (int j = y0; j != y1; j += dy)
|
|
if (j >= 0 && j < height) {
|
|
PIVector<Cell> & cv(cells[j]);
|
|
for (int i = x0; i != x1; i += dx)
|
|
if (i >= 0 && i < width)
|
|
cv[i] = cc;
|
|
}
|
|
}
|
|
|
|
|
|
void PIScreenDrawer::drawText(int x, int y, const PIString & s, Color col_char, Color col_back, CharFlags flags_char) {
|
|
if (x < 0 || x >= width || y < 0 || y >= height) return;
|
|
PIVector<Cell> & cv(cells[y]);
|
|
Cell cc;
|
|
cc.format.color_char = col_char;
|
|
cc.format.color_back = col_back;
|
|
cc.format.flags = flags_char;
|
|
for (int i = 0; i < s.size_s(); ++i) {
|
|
int j = i + x;
|
|
if (j >= 0 && j < width) {
|
|
cc.symbol = s[i];
|
|
cv[j] = cc;
|
|
}
|
|
}
|
|
}
|