722 lines
19 KiB
C++
722 lines
19 KiB
C++
/*
|
|
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/>.
|
|
*/
|
|
|
|
#include "piscreentiles.h"
|
|
#include "piscreendrawer.h"
|
|
|
|
|
|
using namespace PIScreenTypes;
|
|
|
|
|
|
TileSimple::TileSimple(const PIString & n): PIScreenTile(n) {
|
|
alignment = Left;
|
|
}
|
|
|
|
|
|
TileSimple::TileSimple(const TileSimple::Row & r): PIScreenTile() {
|
|
alignment = Left;
|
|
content << r;
|
|
}
|
|
|
|
|
|
void TileSimple::sizeHint(int & w, int & h) const {
|
|
w = h = 0;
|
|
piForeachC (Row & r, content)
|
|
w = piMaxi(w, r.first.size_s());
|
|
h = content.size_s();
|
|
}
|
|
|
|
|
|
void TileSimple::drawEvent(PIScreenDrawer * d) {
|
|
for (int i = 0; i < content.size_s(); ++i) {
|
|
Row & r(content[i]);
|
|
int rx = 0;
|
|
switch (alignment) {
|
|
case Left: rx = x_; break;
|
|
case Center: rx = x_ + (width_ - r.first.size_s()) / 2; break;
|
|
case Right: rx = x_ + width_ - r.first.size_s(); break;
|
|
};
|
|
d->drawText(rx, y_ + i, r.first, (Color)r.second.color_char, (Color)r.second.color_back, r.second.flags);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
TileScrollBar::TileScrollBar(const PIString & n) {
|
|
direction = Vertical;
|
|
thickness = 1;
|
|
minimum_ = value_ = 0;
|
|
maximum_ = 100;
|
|
}
|
|
|
|
|
|
void TileScrollBar::setMinimum(int v) {
|
|
minimum_ = v;
|
|
_check();
|
|
}
|
|
|
|
|
|
void TileScrollBar::setMaximum(int v) {
|
|
maximum_ = v;
|
|
_check();
|
|
}
|
|
|
|
|
|
void TileScrollBar::setValue(int v) {
|
|
value_ = v;
|
|
_check();
|
|
}
|
|
|
|
|
|
void TileScrollBar::_check() {
|
|
value_ = piClampi(value_, minimum_, maximum_);
|
|
}
|
|
|
|
|
|
void TileScrollBar::sizeHint(int & w, int & h) const {
|
|
w = h = 0;
|
|
if (direction == Vertical) {
|
|
w = thickness;
|
|
h = 255;
|
|
} else {
|
|
h = thickness;
|
|
w = 255;
|
|
}
|
|
}
|
|
|
|
|
|
void TileScrollBar::drawEvent(PIScreenDrawer * d) {
|
|
line_char = d->artChar(direction == Vertical ? PIScreenDrawer::LineVertical : PIScreenDrawer::LineHorizontal);
|
|
d->fillRect(x_, y_, x_ + width_, y_ + height_, line_char, Green);
|
|
if (value_ >= minimum_ && value_ <= maximum_) {
|
|
if (direction == Vertical) {
|
|
int c = piRoundf((float(value_ - minimum_) / (maximum_ - minimum_)) * (height_ - 1));
|
|
d->drawLine(x_, y_ + c, x_ + width_ - 1, y_ + c, ' ', Green, Green);
|
|
} else {
|
|
int c = piRoundf((float(value_ - minimum_) / (maximum_ - minimum_)) * (width_ - 1));
|
|
d->drawLine(x_ + c, y_, x_ + c, y_ + height_ - 1, ' ', Green, Green);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
bool TileScrollBar::mouseEvent(PIKbdListener::MouseEvent me) {
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
TileList::TileList(const PIString & n): PIScreenTile(n) {
|
|
alignment = Left;
|
|
focus_flags = CanHasFocus | NextByArrowsHorizontal | NextByTab | FocusOnMouseOrWheel;
|
|
lhei = offset = cur = 0;
|
|
mouse_sel = false;
|
|
selection_mode = NoSelection;
|
|
scroll = new TileScrollBar();
|
|
scroll->size_policy = Ignore;
|
|
addTile(scroll);
|
|
}
|
|
|
|
|
|
void TileList::sizeHint(int & w, int & h) const {
|
|
w = h = 0;
|
|
piForeachC (Row & r, content)
|
|
w = piMaxi(w, r.first.size_s());
|
|
h = 3;
|
|
}
|
|
|
|
|
|
void TileList::resizeEvent(int w, int h) {
|
|
scroll->x_ = x_ + width_ - 1;
|
|
scroll->y_ = y_;
|
|
scroll->width_ = 1;
|
|
scroll->height_ = height_;
|
|
}
|
|
|
|
|
|
void TileList::drawEvent(PIScreenDrawer * d) {
|
|
lhei = height_ - 2;
|
|
//int osp = piMini(3, lhei / 4);
|
|
int is = piClampi(offset, 0, piMaxi(0, content.size_s() - 1)), ie = piClampi(offset + lhei, 0, content.size_s());
|
|
if (is > 0) d->drawText(x_, y_, PIString(" /\\ ").repeat(width_ / 4), Green, Default, Bold);
|
|
if (ie < content.size_s()) d->drawText(x_, y_ + height_ - 1, PIString(" \\/ ").repeat(width_ / 4), Green, Default, Bold);
|
|
//piCout << is << ie << offset << lhei << content.size_s();
|
|
for (int i = is; i < ie; ++i) {
|
|
Row & r(content[i]);
|
|
bool sel = i == cur && has_focus;
|
|
if (sel) {
|
|
int cy = y_ + i - is + 1;
|
|
d->drawLine(x_, cy, x_ + width_ - 2, cy, ' ', Default, Blue);
|
|
}
|
|
int rx(0);
|
|
switch (alignment) {
|
|
case Left: rx = x_; break;
|
|
case Center: rx = x_ + (width_ - 1 - r.first.size_s()) / 2; break;
|
|
case Right: rx = x_ + width_ - 1 - r.first.size_s(); break;
|
|
};
|
|
CharFlags cf = r.second.flags;
|
|
Color cc = (Color)r.second.color_char;
|
|
if (selected[i]) {
|
|
cf |= Bold;
|
|
cc = Yellow;
|
|
}
|
|
d->drawText(rx, y_ + i - is + 1, r.first, cc, sel ? Blue : Default, cf);
|
|
}
|
|
scroll->setMaximum(piMaxi(0, content.size_s() - 1));
|
|
scroll->setValue(cur);
|
|
/*int cx = x_ + width_ - 1;
|
|
d->drawLine(cx, y_ + 1, cx, y_ + height_ - 2, vert_line, Green);
|
|
if (content.size_s() > 1)
|
|
d->drawPixel(cx, y_ + piRound(float(cur) / (content.size_s() - 1) * (lhei - 1)) + 1, ' ', Green, Green);
|
|
if (ie < content.size_s()) d->drawText(x_, y_ + height_ - 1, PIString(" \\/ ").repeat(width_ / 4), Green, Default, Bold);*/
|
|
}
|
|
|
|
|
|
bool TileList::keyEvent(PIKbdListener::KeyEvent key) {
|
|
lhei = height_ - 2;
|
|
int oo(0), osp = piMini(3, lhei / 4);
|
|
switch (key.key) {
|
|
case PIKbdListener::PageUp:
|
|
cur -= lhei / 2;
|
|
oo -= lhei / 2;
|
|
case PIKbdListener::UpArrow:
|
|
cur--;
|
|
oo--;
|
|
if (key.modifiers[PIKbdListener::Ctrl]) {
|
|
cur -= 4;
|
|
oo -= 4;
|
|
}
|
|
if (cur < 0) cur = 0;
|
|
if (cur - offset < osp) offset += oo;
|
|
if (offset < 0) offset = 0;
|
|
return true;
|
|
case PIKbdListener::Space:
|
|
if (cur < 0 || cur >= content.size_s()) return true;
|
|
switch (selection_mode) {
|
|
case NoSelection: return false;
|
|
case SingleSelection:
|
|
if (selected.isEmpty()) selected << cur;
|
|
else {
|
|
bool add = !selected[cur];
|
|
selected.clear();
|
|
if (add) selected << cur;
|
|
}
|
|
raiseEvent(TileEvent(SelectionChanged));
|
|
return true;
|
|
case MultiSelection:
|
|
if (selected[cur]) selected.remove(cur);
|
|
else selected << cur;
|
|
raiseEvent(TileEvent(SelectionChanged));
|
|
break;
|
|
}
|
|
case PIKbdListener::PageDown:
|
|
if (key.key == PIKbdListener::PageDown) {
|
|
cur += lhei / 2;
|
|
oo += lhei / 2;
|
|
}
|
|
case PIKbdListener::DownArrow:
|
|
cur++;
|
|
oo++;
|
|
if (key.modifiers[PIKbdListener::Ctrl]) {
|
|
cur += 4;
|
|
oo += 4;
|
|
}
|
|
if (cur >= content.size_s()) cur = content.size_s() - 1;
|
|
if (cur - offset >= lhei - osp) offset += oo;
|
|
if (offset >= content.size_s() - lhei) offset = content.size_s() - lhei;
|
|
if (offset < 0) offset = 0;
|
|
return true;
|
|
case PIKbdListener::Home:
|
|
cur = offset = 0;
|
|
return true;
|
|
case PIKbdListener::End:
|
|
cur = content.size_s() - 1;
|
|
offset = content.size_s() - lhei;
|
|
if (offset < 0) offset = 0;
|
|
return true;
|
|
case PIKbdListener::Return:
|
|
if (cur >= 0 && cur < content.size_s())
|
|
raiseEvent(TileEvent(RowPressed, cur));
|
|
return true;
|
|
case '*':
|
|
if (selection_mode == TileList::MultiSelection) {
|
|
PISet<int> nsel;
|
|
for (int i = 0; i < content.size_s(); ++i)
|
|
if (!selected[i]) nsel << i;
|
|
selected = nsel;
|
|
}
|
|
raiseEvent(TileEvent(SelectionChanged));
|
|
return true;
|
|
case 'A':
|
|
if (selection_mode == TileList::MultiSelection) {
|
|
selected.clear();
|
|
for (int i = 0; i < content.size_s(); ++i)
|
|
selected << i;
|
|
}
|
|
raiseEvent(TileEvent(SelectionChanged));
|
|
return true;
|
|
}
|
|
return PIScreenTile::keyEvent(key);
|
|
}
|
|
|
|
|
|
bool TileList::mouseEvent(PIKbdListener::MouseEvent me) {
|
|
if (me.action == PIKbdListener::MouseButtonRelease) return true;
|
|
int mp = me.y - y() - 1 + offset;
|
|
if (mp < 0 || mp >= content.size_s()) return true;
|
|
cur = mp;
|
|
switch (me.action) {
|
|
case PIKbdListener::MouseButtonPress:
|
|
mouse_sel = !selected.contains(cur);
|
|
break;
|
|
case PIKbdListener::MouseButtonDblClick:
|
|
keyEvent(PIKbdListener::KeyEvent(PIKbdListener::Return));
|
|
//raiseEvent(TileEvent(RowPressed, cur));
|
|
return true;
|
|
default: break;
|
|
}
|
|
if (me.buttons[PIKbdListener::MouseRight]) {
|
|
switch (selection_mode) {
|
|
case SingleSelection:
|
|
selected.clear();
|
|
selected << cur;
|
|
raiseEvent(TileEvent(SelectionChanged));
|
|
break;
|
|
case MultiSelection:
|
|
if (mouse_sel) selected << cur;
|
|
else selected.remove(cur);
|
|
raiseEvent(TileEvent(SelectionChanged));
|
|
break;
|
|
default: break;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool TileList::wheelEvent(PIKbdListener::WheelEvent we) {
|
|
keyEvent(PIKbdListener::KeyEvent(we.direction ? PIKbdListener::PageUp : PIKbdListener::PageDown));
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
TileButton::TileButton(const PIString & n): PIScreenTile(n) {
|
|
focus_flags = CanHasFocus | NextByTab | NextByArrowsAll | FocusOnMouse;
|
|
}
|
|
|
|
|
|
void TileButton::sizeHint(int & w, int & h) const {
|
|
w = text.size_s() + 2;
|
|
h = 1;
|
|
}
|
|
|
|
|
|
void TileButton::drawEvent(PIScreenDrawer * d) {
|
|
Color cb = has_focus ? Blue : Cyan;
|
|
Color ct = has_focus ? White : Black;
|
|
int ff = has_focus ? Bold : 0;
|
|
d->fillRect(x_, y_, x_ + width_, y_ + 1, ' ', Default, cb);
|
|
d->drawText(x_, y_, "[", ct, Transparent, ff);
|
|
d->drawText(x_ + (width_ - text.size_s()) / 2, y_, text, ct, Transparent, ff);
|
|
d->drawText(x_ + width_ - 1, y_, "]", ct, Transparent, ff);
|
|
}
|
|
|
|
|
|
bool TileButton::keyEvent(PIKbdListener::KeyEvent key) {
|
|
if (key.key == PIKbdListener::Space || key.key == PIKbdListener::Return) {
|
|
raiseEvent(TileEvent(ButtonClicked));
|
|
return true;
|
|
}
|
|
return PIScreenTile::keyEvent(key);
|
|
}
|
|
|
|
|
|
bool TileButton::mouseEvent(PIKbdListener::MouseEvent me) {
|
|
if (me.action != PIKbdListener::MouseButtonRelease) return true;
|
|
keyEvent(PIKbdListener::KeyEvent(PIKbdListener::Return));
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
TileButtons::TileButtons(const PIString & n): PIScreenTile(n) {
|
|
focus_flags = CanHasFocus | NextByTab | FocusOnMouse;
|
|
direction = Horizontal;
|
|
alignment = PIScreenTypes::Center;
|
|
cur = 0;
|
|
}
|
|
|
|
|
|
void TileButtons::sizeHint(int & w, int & h) const {
|
|
w = h = 0;
|
|
if (direction == Horizontal) {
|
|
piForeachC (Button & b, content)
|
|
w += b.first.size_s() + 4;
|
|
w += piMaxi(0, content.size_s() - 1) * 2;
|
|
h += 1;
|
|
} else {
|
|
piForeachC (Button & b, content)
|
|
w = piMaxi(w, b.first.size_s() + 4);
|
|
h += content.size_s();
|
|
h += piMaxi(0, content.size_s() - 1);
|
|
}
|
|
}
|
|
|
|
|
|
void TileButtons::drawEvent(PIScreenDrawer * d) {
|
|
int cx = x_, cy = y_, shw, shh;
|
|
sizeHint(shw, shh);
|
|
btn_rects.resize(content.size());
|
|
int dx = 0;
|
|
switch (alignment) {
|
|
case PIScreenTypes::Center: dx = (width_ - shw) / 2; break;
|
|
case PIScreenTypes::Right: dx = width_ - shw; break;
|
|
default: break;
|
|
}
|
|
if (direction == PIScreenTypes::Horizontal)
|
|
cx += dx;
|
|
for (int i = 0; i < content.size_s(); ++i) {
|
|
Color cb = Cyan;
|
|
Color ct = Black;
|
|
int ff = 0;
|
|
if (i == cur && has_focus) {
|
|
cb = Blue;
|
|
ct = White;
|
|
ff = Bold;
|
|
}
|
|
Button & b(content[i]);
|
|
int cw = b.first.size_s() + 2, xo(0);
|
|
if (direction == Vertical) {
|
|
cw = width_ - 2;
|
|
xo = (cw - b.first.size_s()) / 2 - 1;
|
|
}
|
|
btn_rects[i] = Rect(cx, cy, cx + cw + 2, cy + 1);
|
|
d->fillRect(cx, cy, cx + cw + 2, cy + 1, ' ', Default, cb);
|
|
d->drawText(cx, cy, "[", ct, Transparent, ff);
|
|
d->drawText(cx + xo + 2, cy, b.first, ct, Transparent, ff);
|
|
d->drawText(cx + cw + 1, cy, "]", ct, Transparent, ff);
|
|
if (direction == Horizontal)
|
|
cx += b.first.size_s() + 6;
|
|
else
|
|
cy += 2;
|
|
}
|
|
}
|
|
|
|
|
|
bool TileButtons::keyEvent(PIKbdListener::KeyEvent key) {
|
|
switch (key.key) {
|
|
case PIKbdListener::LeftArrow:
|
|
case PIKbdListener::UpArrow:
|
|
cur--;
|
|
if (cur < 0) cur = 0;
|
|
return true;
|
|
case PIKbdListener::RightArrow:
|
|
case PIKbdListener::DownArrow:
|
|
cur++;
|
|
if (cur >= content.size_s()) cur = content.size_s() - 1;
|
|
return true;
|
|
case PIKbdListener::Space:
|
|
case PIKbdListener::Return:
|
|
raiseEvent(TileEvent(ButtonSelected, cur));
|
|
return true;
|
|
};
|
|
return PIScreenTile::keyEvent(key);
|
|
}
|
|
|
|
|
|
bool TileButtons::mouseEvent(PIKbdListener::MouseEvent me) {
|
|
if (me.action == PIKbdListener::MouseMove || me.action == PIKbdListener::MouseButtonPress) {
|
|
for (int i = 0; i < btn_rects.size_s(); ++i)
|
|
if (me.x >= btn_rects[i].x0 && me.x < btn_rects[i].x1 &&
|
|
me.y >= btn_rects[i].y0 && me.y < btn_rects[i].y1) {
|
|
cur = i;
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
if (me.action != PIKbdListener::MouseButtonRelease) return true;
|
|
keyEvent(PIKbdListener::KeyEvent(PIKbdListener::Return));
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
TileCheck::TileCheck(const PIString & n): PIScreenTile(n) {
|
|
focus_flags = CanHasFocus | NextByTab | NextByArrowsAll | FocusOnMouse;
|
|
toggled = false;
|
|
}
|
|
|
|
|
|
void TileCheck::sizeHint(int & w, int & h) const {
|
|
w = text.size_s() + 4;
|
|
h = 1;
|
|
}
|
|
|
|
|
|
void TileCheck::drawEvent(PIScreenDrawer * d) {
|
|
Color cb = has_focus ? Blue : Cyan;
|
|
Color ct = has_focus ? White : Black;
|
|
int ff = has_focus ? Bold : 0;
|
|
PIString cs("[ ]");
|
|
if (toggled) cs[1] = '*';
|
|
d->fillRect(x_, y_, x_ + width_, y_ + 1, ' ', Default, cb);
|
|
d->drawText(x_, y_, cs, ct, Transparent, ff);
|
|
d->drawText(x_ + 4, y_, text, ct, Transparent, ff);
|
|
}
|
|
|
|
|
|
bool TileCheck::keyEvent(PIKbdListener::KeyEvent key) {
|
|
if (key.key == PIKbdListener::Space || key.key == PIKbdListener::Return) {
|
|
toggled = !toggled;
|
|
raiseEvent(TileEvent(Toggled, toggled));
|
|
return true;
|
|
}
|
|
return PIScreenTile::keyEvent(key);
|
|
}
|
|
|
|
|
|
bool TileCheck::mouseEvent(PIKbdListener::MouseEvent me) {
|
|
if (me.action == PIKbdListener::MouseButtonPress) {
|
|
keyEvent(PIKbdListener::KeyEvent(PIKbdListener::Return));
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
|
|
TileProgress::TileProgress(const PIString & n): PIScreenTile(n) {
|
|
maximum = 100.;
|
|
value = 0.;
|
|
suffix = " %";
|
|
}
|
|
|
|
|
|
void TileProgress::sizeHint(int & w, int & h) const {
|
|
w = 20;
|
|
h = 1;
|
|
}
|
|
|
|
|
|
void TileProgress::drawEvent(PIScreenDrawer * d) {
|
|
int v = maximum == 0. ? 0 : piClampd(piRoundd(value / maximum * 100.), 0, 100);
|
|
PIString s = prefix + PIString::fromNumber(piRoundd(value)) + suffix;
|
|
int w = piRoundd(v / 100. * width_), sx = (width_ - s.size_s()) / 2;
|
|
d->fillRect(x_, y_, x_ + width_, y_ + 1, ' ', Default, Cyan);
|
|
d->fillRect(x_, y_, x_ + w, y_ + 1, ' ', Default, Blue);
|
|
if (w < sx)
|
|
d->drawText(x_ + sx, y_, s, Black, Transparent);
|
|
else if (w >= sx + s.size_s())
|
|
d->drawText(x_ + sx, y_, s, White, Transparent);
|
|
else {
|
|
int fw = w - sx;
|
|
d->drawText(x_ + sx, y_, s.left(fw), White, Transparent);
|
|
d->drawText(x_ + sx + fw, y_, s.cutLeft(fw), Black, Transparent);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
TilePICout::TilePICout(const PIString & n): TileList(n) {
|
|
max_lines = 1024;
|
|
selection_mode = TileList::SingleSelection;
|
|
PICout::setOutputDevices(PICout::Buffer);
|
|
PICout::setBufferActive(true);
|
|
}
|
|
|
|
|
|
void TilePICout::drawEvent(PIScreenDrawer * d) {
|
|
PIString out = PICout::buffer(true);
|
|
if (!out.isEmpty()) {
|
|
PIStringList l = out.split("\n");
|
|
bool scroll = (cur == content.size_s() - 1) || !has_focus;
|
|
piForeachC (PIString & s, l)
|
|
content << TileList::Row(s.trimmed(), format);
|
|
if (content.size_s() > max_lines)
|
|
content.remove(0, content.size_s() - max_lines);
|
|
if (scroll) {
|
|
offset = piMaxi(0, content.size_s() - lhei);
|
|
cur = content.size_s() - 1;
|
|
}
|
|
}
|
|
TileList::drawEvent(d);
|
|
}
|
|
|
|
|
|
bool TilePICout::keyEvent(PIKbdListener::KeyEvent key) {
|
|
if (key.key == 'C') {
|
|
content.clear();
|
|
cur = offset = 0;
|
|
return true;
|
|
}
|
|
return TileList::keyEvent(key);
|
|
}
|
|
|
|
|
|
|
|
|
|
TileInput::TileInput(const PIString & n): PIScreenTile(n) {
|
|
focus_flags = CanHasFocus | NextByTab | FocusOnMouse;
|
|
back_format.color_back = White;
|
|
format.color_char = Black;
|
|
format.color_back = White;
|
|
max_length = 1024;
|
|
cur = offset = 0;
|
|
inv = false;
|
|
}
|
|
|
|
|
|
void TileInput::sizeHint(int & w, int & h) const {
|
|
w = 32;
|
|
h = 1;
|
|
}
|
|
|
|
|
|
void TileInput::drawEvent(PIScreenDrawer * d) {
|
|
PIString ps = text.mid(offset, width_ - 2);
|
|
d->drawText(x_ + 1, y_, ps, (Color)format.color_char, Transparent, (CharFlags)format.flags);
|
|
if (offset > 0)
|
|
d->drawText(x_, y_, "<", Green, Black, Bold);
|
|
if (text.size_s() - offset >= width_ - 2)
|
|
d->drawText(x_ + width_ - 1, y_, ">", Green, Black, Bold);
|
|
if (!has_focus) return;
|
|
Color cb = (Color)format.color_char, cc = (Color)format.color_back;
|
|
if (tm_blink.elapsed_m() >= 650) {
|
|
tm_blink.reset();
|
|
inv = !inv;
|
|
}
|
|
if (inv) piSwap(cb, cc);
|
|
d->drawText(x_ + 1 + cur - offset, y_, text.mid(cur, 1).expandLeftTo(1, ' '), cc, cb, (CharFlags)format.flags);
|
|
}
|
|
|
|
|
|
bool TileInput::keyEvent(PIKbdListener::KeyEvent key) {
|
|
int lwid = piMaxi(0, width_ - 2);
|
|
int oo(0), osp = piMini(3, lwid / 4);
|
|
lwid--;
|
|
switch (key.key) {
|
|
case PIKbdListener::LeftArrow:
|
|
cur--;
|
|
oo--;
|
|
if (key.modifiers[PIKbdListener::Ctrl]) {
|
|
cur -= 4;
|
|
oo -= 4;
|
|
}
|
|
if (cur < 0) cur = 0;
|
|
if (cur - offset < osp) offset += oo;
|
|
if (offset < 0) offset = 0;
|
|
reserCursor();
|
|
return true;
|
|
case PIKbdListener::RightArrow:
|
|
cur++;
|
|
oo++;
|
|
if (key.modifiers[PIKbdListener::Ctrl]) {
|
|
cur += 4;
|
|
oo += 4;
|
|
}
|
|
if (cur > text.size_s()) cur = text.size_s();
|
|
if (cur - offset >= lwid - osp) offset += oo;
|
|
if (offset >= text.size_s() - lwid) offset = text.size_s() - lwid;
|
|
if (offset < 0) offset = 0;
|
|
reserCursor();
|
|
return true;
|
|
case PIKbdListener::Home:
|
|
cur = offset = 0;
|
|
reserCursor();
|
|
return true;
|
|
case PIKbdListener::End:
|
|
cur = text.size_s();
|
|
offset = text.size_s() - lwid;
|
|
if (offset < 0) offset = 0;
|
|
reserCursor();
|
|
return true;
|
|
case PIKbdListener::Backspace:
|
|
if (cur > text.size_s() || text.isEmpty())
|
|
return true;
|
|
text.remove(cur - 1, 1);
|
|
cur--;
|
|
if (cur > text.size_s()) cur = text.size_s();
|
|
if (cur - offset >= lwid - osp) offset += oo;
|
|
if (offset >= text.size_s() - lwid) offset = text.size_s() - lwid;
|
|
if (offset < 0) offset = 0;
|
|
reserCursor();
|
|
return true;
|
|
case PIKbdListener::Delete:
|
|
if (cur >= text.size_s() || text.isEmpty())
|
|
return true;
|
|
text.remove(cur, 1);
|
|
if (cur < 0) cur = 0;
|
|
if (cur > text.size_s()) cur = text.size_s();
|
|
if (cur - offset < osp) offset += oo;
|
|
if (offset < 0) offset = 0;
|
|
reserCursor();
|
|
return true;
|
|
case PIKbdListener::UpArrow:
|
|
case PIKbdListener::DownArrow:
|
|
case PIKbdListener::PageUp:
|
|
case PIKbdListener::PageDown:
|
|
case PIKbdListener::Insert:
|
|
case PIKbdListener::Return:
|
|
case PIKbdListener::Esc:
|
|
case PIKbdListener::F1:
|
|
case PIKbdListener::F2:
|
|
case PIKbdListener::F3:
|
|
case PIKbdListener::F4:
|
|
case PIKbdListener::F5:
|
|
case PIKbdListener::F6:
|
|
case PIKbdListener::F7:
|
|
case PIKbdListener::F8:
|
|
case PIKbdListener::F9:
|
|
case PIKbdListener::F10:
|
|
case PIKbdListener::F11:
|
|
case PIKbdListener::F12:
|
|
break;
|
|
default:
|
|
PIChar tc
|
|
#ifdef WINDOWS
|
|
= PIChar(key.key);
|
|
#else
|
|
= PIChar::fromUTF8((char *)&(key.key));
|
|
#endif
|
|
text.insert(cur, tc);
|
|
cur++;
|
|
oo++;
|
|
if (cur - offset >= lwid - osp) offset += oo;
|
|
if (offset >= text.size_s() - lwid) offset = text.size_s() - lwid;
|
|
if (offset < 0) offset = 0;
|
|
reserCursor();
|
|
return true;
|
|
}
|
|
return PIScreenTile::keyEvent(key);
|
|
}
|
|
|
|
|
|
void TileInput::reserCursor() {
|
|
tm_blink.reset();
|
|
inv = false;
|
|
}
|