tree changes

This commit is contained in:
2020-08-19 00:47:05 +03:00
parent c582d8ff46
commit ccd6a9888f
240 changed files with 30 additions and 12 deletions

View File

@@ -0,0 +1,27 @@
/*
PIP - Platform Independent Primitives
Module includes
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICONSOLEMODULE_H
#define PICONSOLEMODULE_H
#include "pikbdlistener.h"
#include "piscreen.h"
#include "piscreentiles.h"
#endif // PICONSOLEMODULE_H

View File

@@ -0,0 +1,472 @@
/*
PIP - Platform Independent Primitives
Keyboard grabber for console
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piincludes_p.h"
#include "pikbdlistener.h"
#ifndef WINDOWS
# include <termios.h>
#else
# include <wincon.h>
#endif
/** \class PIKbdListener
* \brief Keyboard console input listener
* \details This class provide listening of console keyboard input.
* There is two ways to receive pressed key:
* * external static function with format "void func(char key, void * data_)"
* * event \a keyPressed()
*
* Also there is static variable \a exiting which by default is set to
* \b false. If \a enableExitCapture() was called and listener was started
* with function \a start(), this variable will be set to \b true if exit
* key will be pressed. By default exit key is 'Q' = shift + 'q'.
* To wait for this variable changes to \b true there is WAIT_FOR_EXIT macro
* \snippet pikbdlistener.cpp main
* */
bool PIKbdListener::exiting;
PIKbdListener * PIKbdListener::_object = 0;
#ifndef WINDOWS
// unix
const PIKbdListener::EscSeq PIKbdListener::esc_seq[] = {
{"OA", PIKbdListener::UpArrow, 0, 0 , 1 },
{"OA", PIKbdListener::UpArrow, 4, 0 , 0 },
{"[1A", PIKbdListener::UpArrow, 0, 0 , 0 },
{"[A", PIKbdListener::UpArrow, 0, vt_all , 0 },
{"OB", PIKbdListener::DownArrow, 0, 0 , 1 },
{"OB", PIKbdListener::DownArrow, 4, 0 , 0 },
{"[1B", PIKbdListener::DownArrow, 0, 0 , 0 },
{"[B", PIKbdListener::DownArrow, 0, vt_all , 0 },
{"OC", PIKbdListener::RightArrow, 0, 0 , 1 },
{"OC", PIKbdListener::RightArrow, 4, 0 , 0 },
{"[1C", PIKbdListener::RightArrow, 0, 0 , 0 },
{"[C", PIKbdListener::RightArrow, 0, vt_all , 0 },
{"OD", PIKbdListener::LeftArrow, 0, 0 , 1 },
{"OD", PIKbdListener::LeftArrow, 4, 0 , 0 },
{"[1D", PIKbdListener::LeftArrow, 0, 0 , 0 },
{"[D", PIKbdListener::LeftArrow, 0, vt_all , 0 },
{"[H", PIKbdListener::Home, 0, vt_xterm , 0 },
{"[1H", PIKbdListener::Home, 0, 0 , 0 },
{"OH", PIKbdListener::Home, 0, 0 , 1 },
{"[1~", PIKbdListener::Home, 0, vt_linux , 0 },
{"[F", PIKbdListener::End, 0, vt_xterm , 0 },
{"[1F", PIKbdListener::End, 0, 0 , 0 },
{"OF", PIKbdListener::End, 0, 0 , 1 },
{"[4~", PIKbdListener::End, 0, vt_linux , 0 },
{"[2~", PIKbdListener::Insert, 0, vt_all , 0 },
{"[3~", PIKbdListener::Delete, 0, vt_all , 0 },
{"[5~", PIKbdListener::PageUp, 0, vt_all , 0 },
{"[6~", PIKbdListener::PageDown, 0, vt_all , 0 },
{"[Z", PIKbdListener::Tab, 1, vt_xterm , 0 },
{"OP", PIKbdListener::F1, 0, vt_xterm , 0 },
{"[[A", PIKbdListener::F1, 0, vt_linux , 0 },
{"[11~", PIKbdListener::F1, 0, 0 , 0 },
{"[25~", PIKbdListener::F1, 1, vt_linux , 0 },
{"OQ", PIKbdListener::F2, 0, vt_xterm , 0 },
{"[[B", PIKbdListener::F2, 0, vt_linux , 0 },
{"[12~", PIKbdListener::F2, 0, 0 , 0 },
{"[26~", PIKbdListener::F2, 1, vt_linux , 0 },
{"OR", PIKbdListener::F3, 0, vt_xterm , 0 },
{"[[C", PIKbdListener::F3, 0, vt_linux , 0 },
{"[13~", PIKbdListener::F3, 0, 0 , 0 },
{"[28~", PIKbdListener::F3, 1, vt_linux , 0 },
{"OS", PIKbdListener::F4, 0, vt_xterm , 0 },
{"[[D", PIKbdListener::F4, 0, vt_linux , 0 },
{"[14~", PIKbdListener::F4, 0, 0 , 0 },
{"[29~", PIKbdListener::F4, 1, vt_linux , 0 },
{"[[E", PIKbdListener::F5, 0, vt_linux , 0 },
{"OT", PIKbdListener::F5, 0, 0 , 0 },
{"[15~", PIKbdListener::F5, 0, vt_xterm , 0 },
{"[31~", PIKbdListener::F5, 1, vt_linux , 0 },
{"OU", PIKbdListener::F6, 0, 0 , 0 },
{"[17~", PIKbdListener::F6, 0, vt_all , 0 },
{"[32~", PIKbdListener::F6, 1, vt_linux , 0 },
{"OV", PIKbdListener::F7, 0, 0 , 0 },
{"[18~", PIKbdListener::F7, 0, vt_all , 0 },
{"[33~", PIKbdListener::F7, 1, vt_linux , 0 },
{"OW", PIKbdListener::F8, 0, 0 , 0 },
{"[19~", PIKbdListener::F8, 0, vt_all , 0 },
{"[34~", PIKbdListener::F8, 1, vt_linux , 0 },
{"OX", PIKbdListener::F9, 0, 0 , 0 },
{"[20~", PIKbdListener::F9, 0, vt_all , 0 },
{"[35~", PIKbdListener::F9, 1, vt_linux , 0 },
{"OY", PIKbdListener::F10, 0, 0 , 0 },
{"[21~", PIKbdListener::F10, 0, vt_all , 0 },
{"[36~", PIKbdListener::F10, 1, vt_linux , 0 },
{"OZ", PIKbdListener::F11, 0, 0 , 0 },
{"[23~", PIKbdListener::F11, 0, vt_all , 0 },
{"O[", PIKbdListener::F12, 0, 0 , 0 },
{"[24~", PIKbdListener::F12, 0, vt_all , 0 },
// End
{0, 0, 0, 0, 0},
};
void setupTerminal(bool on) {
printf("\e[?1000"); printf(on ? "h" : "l");
printf("\e[?1002"); printf(on ? "h" : "l");
fflush(0);
}
#endif
PRIVATE_DEFINITION_START(PIKbdListener)
#ifdef WINDOWS
void * hIn, * hOut;
DWORD smode, tmode;
CONSOLE_SCREEN_BUFFER_INFO sbi;
#else
struct termios sterm, tterm;
#endif
#ifdef WINDOWS
DWORD
#else
int
#endif
ret;
PRIVATE_DEFINITION_END(PIKbdListener)
PIKbdListener::PIKbdListener(KBFunc slot, void * _d, bool startNow): PIThread() {
setName("keyboard_listener");
_object = this;
#ifdef WINDOWS
PRIVATE->hIn = GetStdHandle(STD_INPUT_HANDLE);
PRIVATE->hOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleMode(PRIVATE->hIn, &PRIVATE->smode);
#else
tcgetattr(0, &PRIVATE->sterm);
#endif
is_active = true;
ret_func = slot;
kbddata_ = _d;
dbl_interval = 400;
PIKbdListener::exiting = exit_enabled = false;
if (startNow) start();
}
PIKbdListener::~PIKbdListener() {
terminate();
end();
}
void PIKbdListener::begin() {
#ifdef WINDOWS
GetConsoleMode(PRIVATE->hIn, &PRIVATE->tmode);
SetConsoleMode(PRIVATE->hIn, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT | ENABLE_EXTENDED_FLAGS);
#else
struct termios term;
tcgetattr(0, &term);
term.c_lflag &= ~(ECHO | ICANON);
term.c_lflag |= NOFLSH | IEXTEN;
PRIVATE->tterm = term;
tcsetattr(0, TCSANOW, &term);
setupTerminal(true);
#endif
}
#ifdef WINDOWS
PIKbdListener::KeyModifiers getModifiers(DWORD v, bool * shift = 0) {
PIKbdListener::KeyModifiers ret;
bool ctrl = v & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED);
bool shi = v & SHIFT_PRESSED;
bool alt = v & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED);
if (ctrl) ret |= PIKbdListener::Ctrl;
if (shi) ret |= PIKbdListener::Shift;
if (alt) ret |= PIKbdListener::Alt;
//if (meta) ret |= PIKbdListener::Meta;
if (v & CAPSLOCK_ON) shi = !shi;
if (shift) *shift = shi;
return ret;
}
PIKbdListener::MouseButtons getButtons(DWORD v) {
PIKbdListener::MouseButtons ret;
if (v & FROM_LEFT_1ST_BUTTON_PRESSED) ret |= PIKbdListener::MouseLeft;
if (v & RIGHTMOST_BUTTON_PRESSED) ret |= PIKbdListener::MouseRight;
if (v & FROM_LEFT_2ND_BUTTON_PRESSED) ret |= PIKbdListener::MouseMiddle;
return ret;
}
#endif
void PIKbdListener::readKeyboard() {
ke.key = 0;
ke.modifiers = 0;
memset(rc, 0, 8);
#ifdef WINDOWS
INPUT_RECORD ir;
ReadConsoleInput(PRIVATE->hIn, &ir, 1, &(PRIVATE->ret));
//piCout << ir.EventType;
switch (ir.EventType) {
case KEY_EVENT: {
KEY_EVENT_RECORD ker = ir.Event.KeyEvent;
if (ker.bKeyDown) {
bool shift = false;
ke.modifiers = getModifiers(ker.dwControlKeyState, &shift);
//piCout << "key" << int(ker.wVirtualKeyCode) << int(ker.uChar.AsciiChar);
switch (ker.wVirtualKeyCode) {
case 8: PRIVATE->ret = 1; ke.key = Backspace; break;
case 33: PRIVATE->ret = 1; ke.key = PageUp; break;
case 34: PRIVATE->ret = 1; ke.key = PageDown; break;
case 35: PRIVATE->ret = 1; ke.key = End; break;
case 36: PRIVATE->ret = 1; ke.key = Home; break;
case 37: PRIVATE->ret = 1; ke.key = LeftArrow; break;
case 38: PRIVATE->ret = 1; ke.key = UpArrow; break;
case 39: PRIVATE->ret = 1; ke.key = RightArrow; break;
case 40: PRIVATE->ret = 1; ke.key = DownArrow; break;
case 45: PRIVATE->ret = 1; ke.key = Insert; break;
case 46: PRIVATE->ret = 1; ke.key = Delete; break;
case '\r':
case '\n': PRIVATE->ret = 1; ke.key = Return; break;
case ' ': PRIVATE->ret = 1; ke.key = Space; break;
case '\t': PRIVATE->ret = 1; ke.key = Tab; break;
case 112: PRIVATE->ret = 1; ke.key = F1; break;
case 113: PRIVATE->ret = 1; ke.key = F2; break;
case 114: PRIVATE->ret = 1; ke.key = F3; break;
case 115: PRIVATE->ret = 1; ke.key = F4; break;
case 116: PRIVATE->ret = 1; ke.key = F5; break;
case 117: PRIVATE->ret = 1; ke.key = F6; break;
case 118: PRIVATE->ret = 1; ke.key = F7; break;
case 119: PRIVATE->ret = 1; ke.key = F8; break;
case 120: PRIVATE->ret = 1; ke.key = F9; break;
case 121: PRIVATE->ret = 1; ke.key = F10; break;
case 122: PRIVATE->ret = 1; ke.key = F11; break;
case 123: PRIVATE->ret = 1; ke.key = F12; break;
default:
PRIVATE->ret = 1;
rc[0] = 1;
{
PIChar ch = PIChar::fromConsole(ker.uChar.AsciiChar);
if (shift) ch = ch.toUpper();
ke.key = ch.unicode16Code();
}
break;
}
if (ke.key == 0) {piMSleep(10); return;}
} else {piMSleep(10); return;}
}
break;
case MOUSE_EVENT: {
MOUSE_EVENT_RECORD mer = ir.Event.MouseEvent;
GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi);
me.modifiers = getModifiers(mer.dwControlKeyState);
MouseButtons mb = getButtons(mer.dwButtonState);
if (mer.dwEventFlags & MOUSE_WHEELED) {
memcpy((void*)(&we), (const void*)(&me), sizeof(me));
we.action = MouseWheel;
we.direction = short((mer.dwButtonState >> 8) & 0xFFFF) > 0;
//piCout << "wheel" << we.direction;
wheelEvent(we, kbddata_);
break;
} else {
me.x = mer.dwMousePosition.X;
me.y = mer.dwMousePosition.Y - PRIVATE->sbi.srWindow.Top;
bool move = mer.dwEventFlags & MOUSE_MOVED;
if (move) {
if (me.action == MouseButtonRelease) {
me.action = MouseMove;
return;
}
if (me.buttons == 0) return;
me.action = MouseMove;
} else {
if (mb > me.buttons) {
if (tm_dbl.elapsed_m() <= dbl_interval && prev_p_me.x == me.x && prev_p_me.y == me.y)
me.action = MouseButtonDblClick;
else {
me.action = MouseButtonPress;
prev_p_me = me;
}
tm_dbl.reset();
}
else if (mb < me.buttons) me.action = MouseButtonRelease;
else {if (mb != 0) piCoutObj << "WTF"; break;}
}
me.buttons = mb;
if (piCompareBinary(&prev_me, &me, sizeof(me)))
break;
memcpy((void*)(&prev_me), (const void*)(&me), sizeof(me));
//PIString _s[] = {"press", "release", "dbl click", "move"};
//piCoutObj << _s[me.action] << me.buttons << ":" << me.x << me.y;
mouseEvent(me, kbddata_);
break;
}
}
break;
default:
piMSleep(10);
return;
}
#else
tcsetattr(0, TCSANOW, &PRIVATE->tterm);
PRIVATE->ret = read(0, rc, 8);
/*piCout << "key" << PIString(rc).replaceAll("\e", "\\e");
for (int i = 0; i < PRIVATE->ret; ++i)
PICout(0) << PICoutManipulators::Hex << int(((uchar * )&rc)[i]) << ' ';
PICout(0) << "\n";
for (int i = 0; i < PRIVATE->ret; ++i)
cout << "'" << (char)(rc[i]) << "' ";
cout << endl;*/
if (rc[0] == 0) {piMSleep(10); return;}
if (PRIVATE->ret < 0 || PRIVATE->ret > 7) {piMSleep(10); return;}
if (PRIVATE->ret == 1) ke.key = PIChar::fromConsole(rc[0]).unicode16Code();
int mod(0);
// 2 - shift 1
// 3 - alt 2
// 4 - alt+shift 3
// 5 - ctrl 4
// 8 - ctrl+alt+shift 7
if (rc[0] == '\e') { // search for Alt
if (PRIVATE->ret == 2) {
mod = 2;
ke.key = PIChar::fromConsole(rc[1]).unicode16Code();
} else {// escape-seq
if (rc[1] == '\e') { // search for Alt
for (int i = 1; i < 7; ++i) rc[i] = rc[i + 1];
mod = 2;
PRIVATE->ret--;
}
if (rc[1] == '[') {
if (rc[2] == 'M') { // mouse
if (PRIVATE->ret >= 5) {
me.x = uchar(rc[4] - '!');
me.y = uchar(rc[5] - '!');
int b = rc[3] & 0x7, a = rc[3] & 0x60;
if (a == 0x60) {
memcpy((void*)(&we), (const void*)(&me), sizeof(me));
we.action = MouseWheel;
we.direction = (b == 0);
//piCout << "wheel" << we.direction;
wheelEvent(we, kbddata_);
} else {
switch (b) {
case 0: me.buttons = MouseLeft; break;
case 1: me.buttons = MouseMiddle; break;
case 2: me.buttons = MouseRight; break;
default: break;
}
if (a == 0x20) {
if (b == 3) {
me.action = MouseButtonRelease;
me.buttons = 0;
} else {
if (tm_dbl.elapsed_m() <= dbl_interval && prev_p_me.x == me.x && prev_p_me.y == me.y)
me.action = MouseButtonDblClick;
else {
me.action = MouseButtonPress;
prev_p_me = me;
}
tm_dbl.reset();
}
}
if (a == 0x40) me.action = MouseMove;
//PIString _s[] = {"press", "release", "dbl click", "move"};
//piCoutObj << _s[me.action] << me.buttons << ":" << me.x << me.y;
mouseEvent(me, kbddata_);
}
//piCout << me.x << me.y << PICoutManipulators::Hex << b << a;
}
return;
} else {
for (int i = 2; i < 7; ++i) // search for modifier
if (rc[i] == ';') {
mod |= rc[i + 1] - '0' - 1;
for (int j = i; j < 6; ++j) rc[j] = rc[j + 2];
rc[6] = rc[7] = 0;
PRIVATE->ret -= 2;
break;
}
}
}
if (PRIVATE->ret >= 3 && rc[1] == 'O') { // search for modifier (F1-F4)
if (rc[2] >= '1' && rc[2] <= '8') {
mod |= rc[2] - '0' - 1;
for (int j = 2; j < 6; ++j) rc[j] = rc[j + 1];
rc[7] = 0;
PRIVATE->ret--;
}
}
for (int i = 0; ; ++i) {
if (!esc_seq[i].seq) break;
//piCout << "search" << rc[1] << esc_seq[i].seq;
if (strcmp(esc_seq[i].seq, &(rc[1])) == 0) {
ke.key = esc_seq[i].key;
mod |= esc_seq[i].mod;
break;
}
}
}
if (mod >= 0 && mod <= 15) {
if (mod & 0x1) ke.modifiers |= Shift;
if (mod & 0x2) ke.modifiers |= Alt;
if (mod & 0x4) ke.modifiers |= Ctrl;
//if (mod & 0x8) ke.modifiers |= Meta;
}
/*cout << "wo mods (" << mod << ")\n";
for (int i = 0; i < PRIVATE->ret; ++i)
cout << "'" << (char)(rc[i]) << "' ";
cout << endl;*/
}
if (ke.key == 0 && PRIVATE->ret > 1)
ke.key = PIChar(rc).unicode16Code();
#endif
if ((rc[0] == '\n' || rc[0] == '\r') && PRIVATE->ret == 1)
ke.key = Return;
if (exit_enabled && ke.key == exit_key) {
PIKbdListener::exiting = true;
return;
}
if (PRIVATE->ret > 0) {
keyPressed(ke, kbddata_);
if (ret_func != 0) ret_func(ke, kbddata_);
}
}
void PIKbdListener::end() {
//cout << "list end" << endl;
#ifdef WINDOWS
SetConsoleMode(PRIVATE->hIn, PRIVATE->smode);
#else
tcsetattr(0, TCSANOW, &PRIVATE->sterm);
setupTerminal(false);
#endif
}
void PIKbdListener::setActive(bool yes) {
is_active = yes;
if (is_active) {
#ifdef WINDOWS
SetConsoleMode(PRIVATE->hIn, PRIVATE->tmode);
#else
tcsetattr(0, TCSANOW, &PRIVATE->tterm);
setupTerminal(true);
#endif
} else {
#ifdef WINDOWS
SetConsoleMode(PRIVATE->hIn, PRIVATE->smode);
#else
tcsetattr(0, TCSANOW, &PRIVATE->sterm);
setupTerminal(false);
#endif
}
}

View File

@@ -0,0 +1,256 @@
/*! \file pikbdlistener.h
* \brief Keyboard console input listener
*/
/*
PIP - Platform Independent Primitives
Keyboard grabber for console
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIKBDLISTENER_H
#define PIKBDLISTENER_H
#include "pithread.h"
#define WAIT_FOR_EXIT while (!PIKbdListener::exiting) piMSleep(PIP_MIN_MSLEEP*5);
class PIP_EXPORT PIKbdListener: public PIThread
{
PIOBJECT_SUBCLASS(PIKbdListener, PIThread)
friend class PIConsole;
friend class PITerminal;
public:
//! Special keyboard keys
enum SpecialKey {
Tab /** Tab key */ = 0x09,
Return /** Enter key */ = 0x0a,
Esc /** Escape key */ = 0x1b,
Space /** Space key */ = 0x20,
Backspace /** Backspace key */ = 0x7f,
UpArrow /** Up arrow key */ = -1,
DownArrow /** Down arrow key */ = -2,
RightArrow /** Right arrow key */ = -3,
LeftArrow /** Left arrow key */ = -4,
Home /** Home key */ = -5,
End /** End key */ = -6,
PageUp /** Page up key */ = -7,
PageDown /** Page down key */ = -8,
Insert /** Delete key */ = -9,
Delete /** Delete key */ = -10,
F1 /** F1 key */ = -11,
F2 /** F2 key */ = -12,
F3 /** F3 key */ = -13,
F4 /** F4 key */ = -14,
F5 /** F5 key */ = -15,
F6 /** F6 key */ = -16,
F7 /** F7 key */ = -17,
F8 /** F8 key */ = -18,
F9 /** F9 key */ = -19,
F10 /** F10 key */ = -20,
F11 /** F11 key */ = -21,
F12 /** F12 key */ = -22
};
//! Keyboard modifiers
enum KeyModifier {
Ctrl /** Control key */ = 0x1,
Shift /** Shift key */ = 0x2,
Alt /** Alt key */ = 0x4
//Meta /** Meta (windows) key */ = 0x8
};
typedef PIFlags<KeyModifier> KeyModifiers;
//! This struct contains information about pressed keyboard key
struct PIP_EXPORT KeyEvent {
KeyEvent(int k = 0, KeyModifiers m = 0) {key = k; modifiers = m;}
//! Pressed key. It can be simple \b char or special key (see PIKbdListener::SpecialKey)
int key;
//! Active keyboard modifiers. It contains PIKbdListener::KeyModifier bitfields
KeyModifiers modifiers;
};
//! Mouse buttons
enum MouseButton {
MouseLeft /** Left button */ = 0x01,
MouseRight /** Right button */ = 0x02,
MouseMiddle /** Middle button */ = 0x04
};
//! Mouse actions
enum MouseAction {
MouseButtonPress /** Mouse button pressed */,
MouseButtonRelease /** Mouse button released */,
MouseButtonDblClick /** Mouse button double click */,
MouseMove /** Mouse moved */,
MouseWheel /** Mouse wheel rotated */
};
typedef PIFlags<MouseButton> MouseButtons;
//! This struct contains information about mouse action
struct PIP_EXPORT MouseEvent {
MouseEvent(MouseAction a = MouseButtonPress, MouseButtons b = 0, KeyModifiers m = 0) {x = y = 0; action = a; buttons = b; modifiers = m;}
//! Event X coordinate in view-space, from 0
int x;
//! Event Y coordinate in view-space, from 0
int y;
//! Mouse action type
MouseAction action;
//! Pressed buttons. It contains PIKbdListener::MouseButton bitfields
MouseButtons buttons;
//! Active keyboard modifiers. It contains PIKbdListener::KeyModifier bitfields
KeyModifiers modifiers;
};
//! This struct contains information about mouse wheel action
struct PIP_EXPORT WheelEvent: public MouseEvent {
WheelEvent(): MouseEvent() {direction = false;}
//! Wheel direction, /b true - up, /b fasle - down
bool direction;
};
typedef std::function<void(KeyEvent, void *)> KBFunc;
//! Constructs keyboard listener with external function "slot" and custom data "data"
explicit PIKbdListener(KBFunc slot = 0, void * data = 0, bool startNow = true);
~PIKbdListener();
//! Returns custom data
void * data() {return kbddata_;}
//! Set custom data to "_data"
void setData(void * _data) {kbddata_ = _data;}
//! Set external function to "slot"
void setSlot(KBFunc slot) {ret_func = slot;}
//! Set external function to "slot"
void setSlot(std::function<void(KeyEvent)> slot) {ret_func = [slot](KeyEvent e, void *){slot(e);};}
//! Returns if exit key if awaiting
bool exitCaptured() const {return exit_enabled;}
//! Returns exit key, default 'Q'
int exitKey() const {return exit_key;}
double doubleClickInterval() const {return dbl_interval;}
void setDoubleClickInterval(double v) {dbl_interval = v;}
void readKeyboard();
//! Returns if keyboard listening is active (not running!)
bool isActive() {return is_active;}
EVENT_HANDLER( void, enableExitCapture) {enableExitCapture('Q');}
EVENT_HANDLER1(void, enableExitCapture, int, key) {exit_enabled = true; exit_key = key;}
EVENT_HANDLER(void, disableExitCapture) {exit_enabled = false;}
EVENT_HANDLER(void, setActive) {setActive(true);}
EVENT_HANDLER1(void, setActive, bool, yes);
EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void * , data)
EVENT2(mouseEvent, PIKbdListener::MouseEvent, mouse, void * , data)
EVENT2(wheelEvent, PIKbdListener::WheelEvent, wheel, void * , data)
//! \handlers
//! \{
//! \fn void enableExitCapture(int key = 'Q')
//! \brief Enable exit key "key" awaiting
//! \fn void disableExitCapture()
//! \brief Disable exit key awaiting
//! \fn void setActive(bool yes = true)
//! \brief Set keyboard listening is active or not
//! \}
//! \events
//! \{
//! \fn void keyPressed(PIKbdListener::KeyEvent key, void * data)
//! \brief Raise on key "key" pressed, "data" is custom data
//! \}
static bool exiting;
static PIKbdListener * instance() {return _object;}
private:
void begin();
void run() {readKeyboard();}
void end();
#ifndef WINDOWS
struct PIP_EXPORT EscSeq {
const char * seq;
int key;
int mod;
int vt;
int flags;
// 1 - shift
// 2 - alt
// 4 - ctrl
};
enum VTType {
vt_none,
vt_xterm = 0x1,
vt_linux = 0x2,
vt_all = 0xFF
};
static const EscSeq esc_seq[];
#endif
PRIVATE_DECLARATION(PIP_EXPORT)
KBFunc ret_func;
int exit_key;
bool exit_enabled, is_active;
void * kbddata_;
char rc[8];
double dbl_interval;
PITimeMeasurer tm_dbl;
KeyEvent ke;
MouseEvent me, prev_me, prev_p_me;
WheelEvent we;
static PIKbdListener * _object;
};
inline PIByteArray & operator <<(PIByteArray & s, const PIKbdListener::KeyEvent & v) {s << v.key << v.modifiers; return s;}
inline PIByteArray & operator <<(PIByteArray & s, const PIKbdListener::MouseEvent & v) {s << v.x << v.y << (int)v.action << v.buttons << v.modifiers; return s;}
inline PIByteArray & operator <<(PIByteArray & s, const PIKbdListener::WheelEvent & v) {s << (*(PIKbdListener::MouseEvent*)&v) << (uchar)v.direction; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIKbdListener::KeyEvent & v) {s >> v.key >> v.modifiers; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIKbdListener::MouseEvent & v) {int a(0); s >> v.x >> v.y >> a >> v.buttons >> v.modifiers; v.action = (PIKbdListener::MouseAction)a; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIKbdListener::WheelEvent & v) {uchar d(0); s >> (*(PIKbdListener::MouseEvent*)&v) >> d; v.direction = d; return s;}
#endif // PIKBDLISTENER_H

View File

@@ -0,0 +1,160 @@
/*! \file piscreen.h
* \brief Console GUI class
*/
/*
PIP - Platform Independent Primitives
Console GUI
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PISCREEN_H
#define PISCREEN_H
#include "pip_console_export.h"
#include "piscreentile.h"
#include "piscreendrawer.h"
class PIP_CONSOLE_EXPORT PIScreen: public PIThread, public PIScreenTypes::PIScreenBase
{
PIOBJECT_SUBCLASS(PIScreen, PIThread)
class SystemConsole;
public:
//! Constructs %PIScreen with key handler "slot" and if "startNow" start it
PIScreen(bool startNow = true, PIKbdListener::KBFunc slot = 0);
~PIScreen();
//! Directly call function from \a PIKbdListener
void enableExitCapture(int key = 'Q') {listener->enableExitCapture(key);}
//! Directly call function from \a PIKbdListener
void disableExitCapture() {listener->disableExitCapture();}
//! Directly call function from \a PIKbdListener
bool exitCaptured() const {return listener->exitCaptured();}
//! Directly call function from \a PIKbdListener
int exitKey() const {return listener->exitKey();}
int windowWidth() const {return console.width;}
int windowHeight() const {return console.height;}
bool isMouseEnabled() const {return mouse_;}
void setMouseEnabled(bool on);
PIScreenTile * rootTile() {return &root;}
PIScreenTile * tileByName(const PIString & name);
void setDialogTile(PIScreenTile * t);
PIScreenTile * dialogTile() const {return tile_dialog;}
PIScreenDrawer * drawer() {return &drawer_;}
void clear() {drawer_.clear();}
void resize(int w, int h) {console.resize(w, h);}
EVENT_HANDLER0(void, waitForFinish);
EVENT_HANDLER0(void, start) {start(false);}
EVENT_HANDLER1(void, start, bool, wait) {PIThread::start(40); if (wait) waitForFinish();}
EVENT_HANDLER0(void, stop) {stop(false);}
EVENT_HANDLER1(void, stop, bool, clear);
EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void * , data)
EVENT2(tileEvent, PIScreenTile * , tile, PIScreenTypes::TileEvent, e)
//! \handlers
//! \{
//! \fn void waitForFinish()
//! \brief block until finished (exit key will be pressed)
//! \fn void start(bool wait = false)
//! \brief Start console output and if "wait" block until finished (exit key will be pressed)
//! \fn void stop(bool clear = false)
//! \brief Stop console output and if "clear" clear the screen
//! \}
//! \events
//! \{
//! \fn void keyPressed(PIKbdListener::KeyEvent key, void * data)
//! \brief Raise on key "key" pressed, "data" is pointer to %PIConsole object
//! \fn void tileEvent(PIScreenTile * tile, PIScreenTypes::TileEvent e)
//! \brief Raise on some event "e" from tile "tile"
//! \}
private:
class PIP_CONSOLE_EXPORT SystemConsole {
public:
SystemConsole();
~SystemConsole();
void begin();
void end();
void prepare();
void clear();
void print();
void resize(int w, int h);
void toUpperLeft();
void moveTo(int x = 0, int y = 0);
void hideCursor();
void showCursor();
void clearScreen();
void clearScreenLower();
#ifdef WINDOWS
void getWinCurCoord();
void clearLine();
void newLine();
ushort attributes(const PIScreenTypes::Cell & c);
#else
PIString formatString(const PIScreenTypes::Cell & c);
#endif
PRIVATE_DECLARATION(PIP_CONSOLE_EXPORT)
int width, height, pwidth, pheight;
int mouse_x, mouse_y;
PIVector<PIVector<PIScreenTypes::Cell> > cells, pcells;
};
void begin();
void run();
void end();
void key_event(PIKbdListener::KeyEvent key);
EVENT_HANDLER1(void, mouse_event, PIKbdListener::MouseEvent, me);
EVENT_HANDLER1(void, wheel_event, PIKbdListener::WheelEvent, we);
static void key_eventS(PIKbdListener::KeyEvent key, void * t) {((PIScreen*)t)->key_event(key);}
PIVector<PIScreenTile*> tiles() {return root.children();}
PIVector<PIScreenTile*> prepareMouse(PIKbdListener::MouseEvent * e);
PIVector<PIScreenTile*> tilesUnderMouse(int x, int y);
bool nextFocus(PIScreenTile * rt, PIKbdListener::KeyEvent key = PIKbdListener::KeyEvent());
void tileEventInternal(PIScreenTile * t, PIScreenTypes::TileEvent e);
void tileRemovedInternal(PIScreenTile * t);
void tileSetFocusInternal(PIScreenTile * t);
bool mouse_;
SystemConsole console;
PIScreenDrawer drawer_;
PIKbdListener * listener;
PIKbdListener::KBFunc ret_func;
PIScreenTile root;
PIScreenTile * tile_focus, * tile_dialog;
};
#endif // PISCREEN_H

View File

@@ -0,0 +1,78 @@
/*! \file piscreenconsole.h
* \brief Tile for PIScreen with PIConsole API
*
* This file declares TileVars
*/
/*
PIP - Platform Independent Primitives
Tile for PIScreen with PIConsole API
Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PISCREENCONSOLE_H
#define PISCREENCONSOLE_H
#include "pip_console_export.h"
#include "piscreentiles.h"
/// NOTE: incomplete class
/// TODO: write TileVars
class PIP_CONSOLE_EXPORT TileVars: public PIScreenTile {
public:
TileVars(const PIString & n = PIString());
protected:
struct PIP_CONSOLE_EXPORT Variable {
Variable() {nx = ny = type = offset = bitFrom = bitCount = size = 0; format = PIScreenTypes::CellFormat(); ptr = 0;}
bool isEmpty() const {return (ptr == 0);}
PIString name;
PIScreenTypes::CellFormat format;
int nx;
int ny;
int type;
int offset;
int bitFrom;
int bitCount;
int size;
const void * ptr;
/*void operator =(const Variable & src) {
name = src.name;
format = src.format;
nx = src.nx;
ny = src.ny;
type = src.type;
offset = src.offset;
bitFrom = src.bitFrom;
bitCount = src.bitCount;
size = src.size;
ptr = src.ptr;
}*/
};
PIVector<Variable> variables;
PIScreenTypes::Alignment alignment;
void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d);
};
class PIP_CONSOLE_EXPORT PIScreenConsoleTile : public PIScreenTile
{
public:
PIScreenConsoleTile();
};
#endif // PISCREENCONSOLE_H

View File

@@ -0,0 +1,69 @@
/*! \file piscreendrawer.h
* \brief Drawer for PIScreen
*/
/*
PIP - Platform Independent Primitives
Drawer for PIScreen
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PISCREENDRAWER_H
#define PISCREENDRAWER_H
#include "pip_console_export.h"
#include "piscreentypes.h"
#include "pistring.h"
class PIP_CONSOLE_EXPORT PIScreenDrawer
{
friend class PIScreen;
PIScreenDrawer(PIVector<PIVector<PIScreenTypes::Cell> > & c);
public:
enum ArtChar {
LineVertical = 1,
LineHorizontal,
Cross,
CornerTopLeft,
CornerTopRight,
CornerBottomLeft,
CornerBottomRight,
Unchecked,
Checked
};
void clear();
void clearRect(int x0, int y0, int x1, int y1) {fillRect(x0, y0, x1, y1, ' ');}
void drawPixel(int x, int y, const PIChar & c, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::CharFlags flags_char = 0);
void drawLine(int x0, int y0, int x1, int y1, const PIChar & c, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::CharFlags flags_char = 0);
void drawRect(int x0, int y0, int x1, int y1, const PIChar & c, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::CharFlags flags_char = 0);
void drawFrame(int x0, int y0, int x1, int y1, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::CharFlags flags_char = 0);
void drawText(int x, int y, const PIString & s, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Transparent, PIScreenTypes::CharFlags flags_char = 0);
void fillRect(int x0, int y0, int x1, int y1, const PIChar & c, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::CharFlags flags_char = 0);
void fillRect(int x0, int y0, int x1, int y1, PIVector<PIVector<PIScreenTypes::Cell> > & content);
PIChar artChar(const ArtChar type) const {return arts_.value(type, PIChar(' '));}
static void clear(PIVector<PIVector<PIScreenTypes::Cell> > & cells);
private:
PIVector<PIVector<PIScreenTypes::Cell> > & cells;
int width, height;
PIMap<ArtChar, PIChar> arts_;
};
#endif // PISCREENDRAWER_H

View File

@@ -0,0 +1,107 @@
/*! \file piscreentile.h
* \brief Basic PIScreen tile
*/
/*
PIP - Platform Independent Primitives
Basic PIScreen tile
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PISCREENTILE_H
#define PISCREENTILE_H
#include "pip_console_export.h"
#include "piscreentypes.h"
#include "pikbdlistener.h"
class PIScreenDrawer;
class PIP_CONSOLE_EXPORT PIScreenTile: public PIObject {
friend class PIScreen;
PIOBJECT_SUBCLASS(PIScreenTile, PIObject)
public:
PIScreenTile(const PIString & n = PIString(), PIScreenTypes::Direction d = PIScreenTypes::Vertical, PIScreenTypes::SizePolicy p = PIScreenTypes::Preferred);
virtual ~PIScreenTile();
void addTile(PIScreenTile * t);
void takeTile(PIScreenTile * t);
void removeTile(PIScreenTile * t);
PIScreenTile * parentTile() const {return parent;}
PIVector<PIScreenTile * > children(bool only_visible = false);
PIScreenTile * childUnderMouse(int x, int y);
void show() {visible = true;}
void hide() {visible = false;}
void setFocus();
bool hasFocus() const {return has_focus;}
void setMargins(int m) {marginLeft = marginRight = marginTop = marginBottom = m;}
void setMargins(int l, int r, int t, int b) {marginLeft = l; marginRight = r; marginTop = t; marginBottom = b;}
int x() const {return x_;}
int y() const {return y_;}
int width() const {return width_;}
int height() const {return height_;}
PIScreenTypes::Direction direction;
PIScreenTypes::SizePolicy size_policy;
PIScreenTypes::FocusFlags focus_flags;
PIScreenTypes::CellFormat back_format;
PIChar back_symbol;
int minimumWidth, minimumHeight;
int maximumWidth, maximumHeight;
int marginLeft, marginRight, marginTop, marginBottom;
int spacing;
bool visible;
protected:
//! Returns desired tile size in "w" and "h"
virtual void sizeHint(int & w, int & h) const;
//! Tile has been resized to "w"x"h"
virtual void resizeEvent(int w, int h) {}
//! Draw tile with drawer "d" in world-space coordinates
virtual void drawEvent(PIScreenDrawer * d) {}
//! Return "true" if you process key
virtual bool keyEvent(PIKbdListener::KeyEvent key) {return false;}
//! Return "true" if you process event
virtual bool mouseEvent(PIKbdListener::MouseEvent me) {return false;}
//! Return "true" if you process wheel
virtual bool wheelEvent(PIKbdListener::WheelEvent we) {return false;}
void raiseEvent(PIScreenTypes::TileEvent e);
void setScreen(PIScreenTypes::PIScreenBase * s);
void deleteChildren();
void drawEventInternal(PIScreenDrawer * d);
void layout();
bool needLayout() {return size_policy != PIScreenTypes::Ignore;}
PIVector<PIScreenTile * > tiles;
PIScreenTile * parent;
PIScreenTypes::PIScreenBase * screen;
int x_, y_, width_, height_;
bool has_focus;
private:
int pw, ph;
};
#endif // PISCREENTILE_H

View File

@@ -0,0 +1,214 @@
/*! \file piscreentiles.h
* \brief Various tiles for PIScreen
*/
/*
PIP - Platform Independent Primitives
Various tiles for PIScreen
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PISCREENTILES_H
#define PISCREENTILES_H
#include "pip_console_export.h"
#include "piscreentile.h"
class PIP_CONSOLE_EXPORT TileSimple: public PIScreenTile {
PIOBJECT_SUBCLASS(TileSimple, PIScreenTile)
public:
typedef PIPair<PIString, PIScreenTypes::CellFormat> Row;
TileSimple(const PIString & n = PIString());
TileSimple(const Row & r);
virtual ~TileSimple() {}
PIVector<Row> content;
PIScreenTypes::Alignment alignment;
protected:
void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d);
};
class TileList;
class PIP_CONSOLE_EXPORT TileScrollBar: public PIScreenTile {
PIOBJECT_SUBCLASS(TileScrollBar, PIScreenTile)
friend class TileList;
public:
TileScrollBar(const PIString & n = PIString());
virtual ~TileScrollBar() {}
void setMinimum(int v);
void setMaximum(int v);
void setValue(int v);
int minimum() const {return minimum_;}
int maximum() const {return maximum_;}
int value() const {return value_;}
int thickness;
protected:
void _check();
void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d);
bool mouseEvent(PIKbdListener::MouseEvent me);
int minimum_, maximum_, value_;
PIChar line_char;
};
class PIP_CONSOLE_EXPORT TileList: public PIScreenTile {
PIOBJECT_SUBCLASS(TileList, PIScreenTile)
public:
TileList(const PIString & n = PIString());
virtual ~TileList() {}
enum SelectionMode {
NoSelection,
SingleSelection,
MultiSelection
};
enum EventType {
SelectionChanged,
RowPressed
};
typedef PIPair<PIString, PIScreenTypes::CellFormat> Row;
PIDeque<Row> content;
PIScreenTypes::Alignment alignment;
SelectionMode selection_mode;
PISet<int> selected;
int lhei, cur, offset;
protected:
void sizeHint(int & w, int & h) const;
void resizeEvent(int w, int h);
void drawEvent(PIScreenDrawer * d);
bool keyEvent(PIKbdListener::KeyEvent key);
bool mouseEvent(PIKbdListener::MouseEvent me);
bool wheelEvent(PIKbdListener::WheelEvent we);
TileScrollBar * scroll;
bool mouse_sel;
};
class PIP_CONSOLE_EXPORT TileButton: public PIScreenTile {
PIOBJECT_SUBCLASS(TileButton, PIScreenTile)
public:
TileButton(const PIString & n = PIString());
virtual ~TileButton() {}
enum EventType {
ButtonClicked
};
PIScreenTypes::CellFormat format;
PIString text;
protected:
void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d);
bool keyEvent(PIKbdListener::KeyEvent key);
bool mouseEvent(PIKbdListener::MouseEvent me);
};
class PIP_CONSOLE_EXPORT TileButtons: public PIScreenTile {
PIOBJECT_SUBCLASS(TileButtons, PIScreenTile)
public:
TileButtons(const PIString & n = PIString());
virtual ~TileButtons() {}
enum EventType {
ButtonSelected
};
typedef PIPair<PIString, PIScreenTypes::CellFormat> Button;
PIScreenTypes::Alignment alignment;
PIVector<Button> content;
int cur;
protected:
void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d);
bool keyEvent(PIKbdListener::KeyEvent key);
bool mouseEvent(PIKbdListener::MouseEvent me);
struct Rect {
Rect(int _x0 = 0, int _y0 = 0, int _x1 = 0, int _y1 = 0): x0(_x0),y0(_y0),x1(_x1),y1(_y1) {}
int x0,y0,x1,y1;
};
PIVector<Rect> btn_rects;
};
class PIP_CONSOLE_EXPORT TileCheck: public PIScreenTile {
PIOBJECT_SUBCLASS(TileCheck, PIScreenTile)
public:
TileCheck(const PIString & n = PIString());
virtual ~TileCheck() {}
enum EventType {
Toggled
};
PIScreenTypes::CellFormat format;
PIString text;
bool toggled;
protected:
void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d);
bool keyEvent(PIKbdListener::KeyEvent key);
bool mouseEvent(PIKbdListener::MouseEvent me);
};
class PIP_CONSOLE_EXPORT TileProgress: public PIScreenTile {
PIOBJECT_SUBCLASS(TileProgress, PIScreenTile)
public:
TileProgress(const PIString & n = PIString());
virtual ~TileProgress() {}
PIScreenTypes::CellFormat format;
PIString prefix;
PIString suffix;
double maximum;
double value;
protected:
void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d);
};
class PIP_CONSOLE_EXPORT TilePICout: public TileList {
PIOBJECT_SUBCLASS(TilePICout, PIScreenTile)
public:
TilePICout(const PIString & n = PIString());
virtual ~TilePICout() {}
PIScreenTypes::CellFormat format;
int max_lines;
protected:
void drawEvent(PIScreenDrawer * d);
bool keyEvent(PIKbdListener::KeyEvent key);
};
class PIP_CONSOLE_EXPORT TileInput: public PIScreenTile {
PIOBJECT_SUBCLASS(TileInput, PIScreenTile)
public:
TileInput(const PIString & n = PIString());
virtual ~TileInput() {}
PIScreenTypes::CellFormat format;
PIString text;
int max_length;
protected:
void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d);
bool keyEvent(PIKbdListener::KeyEvent key);
void reserCursor();
int cur, offset;
bool inv;
PITimeMeasurer tm_blink;
};
#endif // PISCREENTILES_H

View File

@@ -0,0 +1,147 @@
/*! \file piscreentypes.h
* \brief Types for PIScreen
*/
/*
PIP - Platform Independent Primitives
Types for PIScreen
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PISCREENTYPES_H
#define PISCREENTYPES_H
#include "pip_console_export.h"
#include "pivariant.h"
class PIScreenTile;
namespace PIScreenTypes {
//! Color for chars or background
enum Color {
Default /** Default */,
Black /** Black */,
Red /** Red */,
Green /** Green */,
Blue /** Blue */,
Cyan /** Cyan */,
Magenta /** Magenta */,
Yellow /** Yellow */,
White /** White */,
Transparent /** Save previous color */
};
//! Flags for chars
enum CharFlag {
Bold /** Bold or bright */ = 0x1,
Blink /** Blink text */ = 0x2,
Underline /** Underline text */ = 0x4,
Inverse = 0x08
};
//! Alignment
enum Alignment {
Left /** Left */ ,
Center /** Center */ ,
Right /** Right */
};
//! Size policy
enum SizePolicy {
Fixed /** Fixed size */ ,
Preferred /** Preferred size */ ,
Expanding /** Maximum available size */ ,
Ignore /** Ignore layout logic */
};
//! Direction
enum Direction {
Horizontal /** Horizontal */ ,
Vertical /** Vertical */
};
//! Focus flags
enum FocusFlag {
CanHasFocus /** Tile can has focus */ = 0x1,
NextByTab /** Focus passed to next tile by tab key */ = 0x2,
NextByArrowsHorizontal /** Focus passed to next tile by arrow keys left or right */ = 0x4,
NextByArrowsVertical /** Focus passed to next tile by arrow keys up or down */ = 0x8,
NextByArrowsAll /** Focus passed to next tile by any arrow key */ = NextByArrowsHorizontal | NextByArrowsVertical,
FocusOnMouse /** Tile focused on mouse press */ = 0x10,
FocusOnWheel /** Tile focused on wheel */ = 0x20,
FocusOnMouseOrWheel /** Tile focused on mouse press or wheel */ = FocusOnMouse | FocusOnWheel
};
typedef PIFlags<CharFlag> CharFlags;
typedef PIFlags<FocusFlag> FocusFlags;
union PIP_CONSOLE_EXPORT CellFormat {
CellFormat(ushort f = 0) {raw_format = f;}
CellFormat(Color col_char, Color col_back = Default, CharFlags flags_ = 0) {
color_char = col_char;
color_back = col_back;
flags = flags_;
}
ushort raw_format;
struct {
ushort color_char : 4;
ushort color_back : 4;
ushort flags : 8;
};
bool operator ==(const CellFormat & c) const {return raw_format == c.raw_format;}
bool operator !=(const CellFormat & c) const {return raw_format != c.raw_format;}
};
struct PIP_CONSOLE_EXPORT Cell {
Cell(PIChar c = PIChar(' '), CellFormat f = CellFormat()) {symbol = c; format = f;}
CellFormat format;
PIChar symbol;
bool operator ==(const Cell & c) const {return format == c.format && symbol == c.symbol;}
bool operator !=(const Cell & c) const {return format != c.format || symbol != c.symbol;}
Cell & operator =(const Cell & c) {
symbol = c.symbol;
if (c.format.color_back == Transparent) {
format.color_char = c.format.color_char;
format.flags = c.format.flags;
} else format = c.format;
return *this;
}
};
struct PIP_CONSOLE_EXPORT TileEvent {
TileEvent(int t = -1, const PIVariant & d = PIVariant()): type(t), data(d) {}
int type;
PIVariant data;
};
class PIP_CONSOLE_EXPORT PIScreenBase {
public:
PIScreenBase() {}
virtual ~PIScreenBase() {}
virtual void tileEventInternal(PIScreenTile * , TileEvent) {}
virtual void tileRemovedInternal(PIScreenTile * ) {}
virtual void tileSetFocusInternal(PIScreenTile * ) {}
};
}
inline PIByteArray & operator <<(PIByteArray & s, const PIScreenTypes::Cell & v) {s << v.format.raw_format << v.symbol; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIScreenTypes::Cell & v) {s >> v.format.raw_format >> v.symbol; return s;}
#endif // PISCREENTYPES_H

View File

@@ -0,0 +1,77 @@
/*! \file piterminal.h
* \brief Virtual terminal
*/
/*
PIP - Platform Independent Primitives
Virtual terminal
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PITERMINAL_H
#define PITERMINAL_H
#include "pip_console_export.h"
#include "pikbdlistener.h"
#include "piscreentypes.h"
class PIP_CONSOLE_EXPORT PITerminal: public PIThread
{
PIOBJECT_SUBCLASS(PITerminal, PIThread)
public:
//! Constructs %PITerminal
PITerminal();
~PITerminal();
int columns() const {return size_x;}
int rows() const {return size_y;}
bool resize(int cols, int rows);
void write(const PIByteArray & d);
void write(PIKbdListener::SpecialKey k, PIKbdListener::KeyModifiers m);
void write(PIKbdListener::KeyEvent ke);
PIVector<PIVector<PIScreenTypes::Cell> > content();
static bool isSpecialKey(int k);
bool initialize();
void destroy();
private:
void initPrivate();
void readConsole();
void getCursor(int & x, int & y);
uchar invertColor(uchar c);
void run();
#ifndef WINDOWS
void parseInput(const PIString & s);
bool isCompleteEscSeq(const PIString & es);
void applyEscSeq(PIString es);
void moveCursor(int dx, int dy);
int termType(const PIString & t);
#endif
PRIVATE_DECLARATION(PIP_CONSOLE_EXPORT)
int dsize_x, dsize_y;
int size_x, size_y, cursor_x, cursor_y;
bool cursor_blink, cursor_visible;
PITimeMeasurer cursor_tm;
PIVector<PIVector<PIScreenTypes::Cell> > cells;
};
#endif // PITERMINAL_H