Optimization and cleanup of VirtualKeyboardGUI

svn-id: r33916
This commit is contained in:
Stephen Kennedy 2008-08-15 21:00:54 +00:00
parent 93780d51ca
commit 8c2340d323
3 changed files with 75 additions and 63 deletions

View File

@ -30,9 +30,9 @@
namespace Common { namespace Common {
VirtualKeyboardGUI::VirtualKeyboardGUI(VirtualKeyboard *kbd) VirtualKeyboardGUI::VirtualKeyboardGUI(VirtualKeyboard *kbd)
: _kbd(kbd), _displaying(false), _needRedraw(false), _drag(false), : _kbd(kbd), _displaying(false), _drag(false),
_drawCaret(false), _refreshDisplay(false), _displayEnabled(false), _drawCaret(false), _displayEnabled(false), _firstRun(true),
_firstRun(true), _cursorAnimateTimer(0), _cursorAnimateCounter(0) { _cursorAnimateTimer(0), _cursorAnimateCounter(0) {
assert(_kbd); assert(_kbd);
assert(g_system); assert(g_system);
@ -51,16 +51,21 @@ VirtualKeyboardGUI::~VirtualKeyboardGUI() {
void VirtualKeyboardGUI::initMode(VirtualKeyboard::Mode *mode) { void VirtualKeyboardGUI::initMode(VirtualKeyboard::Mode *mode) {
_kbdSurface = mode->image; _kbdSurface = mode->image;
_kbdTransparentColor = mode->transparentColor; _kbdTransparentColor = mode->transparentColor;
_kbdBound.setWidth(_kbdSurface->w + 1); _kbdBound.setWidth(_kbdSurface->w);
_kbdBound.setHeight(_kbdSurface->h + 1); _kbdBound.setHeight(_kbdSurface->h);
_needRedraw = true;
_dispSurface.free(); _dispSurface.free();
_displayEnabled = false; _displayEnabled = false;
if (!mode->displayArea) if (mode->displayArea)
return; setupDisplayArea(*(mode->displayArea), mode->displayFontColor);
Rect r = *(mode->displayArea);
if (_displaying) {
extendDirtyRect(_kbdBound);
redraw();
}
}
void VirtualKeyboardGUI::setupDisplayArea(Rect& r, OverlayColor forecolor) {
// choose font // choose font
_dispFont = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); _dispFont = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont);
if (!fontIsSuitable(_dispFont, r)) { if (!fontIsSuitable(_dispFont, r)) {
@ -68,12 +73,13 @@ void VirtualKeyboardGUI::initMode(VirtualKeyboard::Mode *mode) {
if (!fontIsSuitable(_dispFont, r)) if (!fontIsSuitable(_dispFont, r))
return; return;
} }
_dispX = r.left; _dispX = _kbdBound.left + r.left;
_dispY = r.top + (r.height() + 1 - _dispFont->getFontHeight()) / 2; _dispY = _kbdBound.top + r.top + (r.height() - _dispFont->getFontHeight()) / 2;
_dispSurface.create(r.width() + 1, _dispFont->getFontHeight(), sizeof(OverlayColor));
_dispI = 0; _dispI = 0;
_dispForeColor = mode->displayFontColor; _dispForeColor = forecolor;
_dispBackColor = _dispForeColor + 0xFF; _dispBackColor = _dispForeColor + 0xFF;
_dispSurface.create(r.width(), _dispFont->getFontHeight(), sizeof(OverlayColor));
_dispSurface.fillRect(r, _dispBackColor);
_displayEnabled = true; _displayEnabled = true;
} }
@ -86,10 +92,10 @@ void VirtualKeyboardGUI::run() {
if (_lastScreenChanged != _system->getScreenChangeID()) if (_lastScreenChanged != _system->getScreenChangeID())
screenChanged(); screenChanged();
// TODO: set default position if position is somehow invalid // TODO: set default position if position is somehow invalid (ie. after screen change)
if (_firstRun) { if (_firstRun) {
_firstRun = false; _firstRun = false;
setDefaultPosition(); moveToDefaultPosition();
} }
if (!g_gui.isActive()) { if (!g_gui.isActive()) {
@ -98,10 +104,10 @@ void VirtualKeyboardGUI::run() {
} }
_overlayBackup.create(_system->getOverlayWidth(), _system->getOverlayHeight(), sizeof(OverlayColor)); _overlayBackup.create(_system->getOverlayWidth(), _system->getOverlayHeight(), sizeof(OverlayColor));
_system->grabOverlay((OverlayColor*)_overlayBackup.pixels, _overlayBackup.w); _system->grabOverlay((OverlayColor*)_overlayBackup.pixels, _overlayBackup.w);
resetDirtyRect();
setupCursor(); setupCursor();
forceRedraw();
_displaying = true; _displaying = true;
mainLoop(); mainLoop();
@ -127,44 +133,43 @@ void VirtualKeyboardGUI::reset() {
_kbdSurface = 0; _kbdSurface = 0;
} }
void VirtualKeyboardGUI::setDefaultPosition() void VirtualKeyboardGUI::moveToDefaultPosition()
{ {
int16 scrW = _system->getOverlayWidth(), scrH = _system->getOverlayHeight(); int16 scrW = _system->getOverlayWidth(), scrH = _system->getOverlayHeight();
int16 kbdW = _kbdBound.width(), kbdH = _kbdBound.height(); int16 kbdW = _kbdBound.width(), kbdH = _kbdBound.height();
int16 posX = 0, posY = 0; int16 x = 0, y = 0;
if (scrW != kbdW) { if (scrW != kbdW) {
switch (_kbd->_hAlignment) { switch (_kbd->_hAlignment) {
case VirtualKeyboard::kAlignLeft: case VirtualKeyboard::kAlignLeft:
posX = 0; x = 0;
break; break;
case VirtualKeyboard::kAlignCentre: case VirtualKeyboard::kAlignCentre:
posX = (scrW - kbdW) / 2; x = (scrW - kbdW) / 2;
break; break;
case VirtualKeyboard::kAlignRight: case VirtualKeyboard::kAlignRight:
posX = scrW - kbdW; x = scrW - kbdW;
break; break;
} }
} }
if (scrH != kbdH) { if (scrH != kbdH) {
switch (_kbd->_vAlignment) { switch (_kbd->_vAlignment) {
case VirtualKeyboard::kAlignTop: case VirtualKeyboard::kAlignTop:
posY = 0; y = 0;
break; break;
case VirtualKeyboard::kAlignMiddle: case VirtualKeyboard::kAlignMiddle:
posY = (scrH - kbdH) / 2; y = (scrH - kbdH) / 2;
break; break;
case VirtualKeyboard::kAlignBottom: case VirtualKeyboard::kAlignBottom:
posY = scrH - kbdH; y = scrH - kbdH;
break; break;
} }
} }
_kbdBound.moveTo(posX, posY); move(x, y);
} }
void VirtualKeyboardGUI::move(int16 x, int16 y) { void VirtualKeyboardGUI::move(int16 x, int16 y) {
// add old position to dirty area // add old position to dirty area
extendDirtyRect(_kbdBound); extendDirtyRect(_kbdBound);
_needRedraw = true;
// snap to edge of screen // snap to edge of screen
if (ABS(x) < SNAP_WIDTH) if (ABS(x) < SNAP_WIDTH)
@ -178,7 +183,14 @@ void VirtualKeyboardGUI::move(int16 x, int16 y) {
if (ABS(y - y2) < SNAP_WIDTH) if (ABS(y - y2) < SNAP_WIDTH)
y = y2; y = y2;
_dispX += x - _kbdBound.left;
_dispY += y - _kbdBound.top;
_kbdBound.moveTo(x, y); _kbdBound.moveTo(x, y);
// add new position to dirty area
extendDirtyRect(_kbdBound);
redraw();
} }
void VirtualKeyboardGUI::screenChanged() { void VirtualKeyboardGUI::screenChanged() {
@ -192,13 +204,9 @@ void VirtualKeyboardGUI::mainLoop() {
Common::EventManager *eventMan = _system->getEventManager(); Common::EventManager *eventMan = _system->getEventManager();
while (_displaying) { while (_displaying) {
if (_displayEnabled) { if (_kbd->_keyQueue.hasStringChanged())
if (_kbd->_keyQueue.hasStringChanged()) updateDisplay();
_refreshDisplay = true; animateCaret();
animateCaret();
if (_refreshDisplay) updateDisplay();
}
if (_needRedraw) redraw();
animateCursor(); animateCursor();
_system->updateScreen(); _system->updateScreen();
Common::Event event; Common::Event event;
@ -252,18 +260,21 @@ void VirtualKeyboardGUI::extendDirtyRect(const Rect &r) {
} else { } else {
_dirtyRect = r; _dirtyRect = r;
} }
_dirtyRect.clip(Rect(0, 0, _overlayBackup.w, _overlayBackup.h)); _dirtyRect.clip(Rect(_overlayBackup.w, _overlayBackup.h));
} }
void VirtualKeyboardGUI::resetDirtyRect() { void VirtualKeyboardGUI::resetDirtyRect() {
_dirtyRect.setWidth(-1); _dirtyRect.setWidth(-1);
} }
void VirtualKeyboardGUI::forceRedraw() {
extendDirtyRect(Rect(_overlayBackup.w, _overlayBackup.h));
redraw();
}
void VirtualKeyboardGUI::redraw() { void VirtualKeyboardGUI::redraw() {
assert(_kbdSurface); assert(_kbdSurface);
extendDirtyRect(_kbdBound);
Graphics::SurfaceKeyColored surf; Graphics::SurfaceKeyColored surf;
surf.create(_dirtyRect.width(), _dirtyRect.height(), sizeof(OverlayColor)); surf.create(_dirtyRect.width(), _dirtyRect.height(), sizeof(OverlayColor));
@ -277,16 +288,12 @@ void VirtualKeyboardGUI::redraw() {
src += _overlayBackup.w; src += _overlayBackup.w;
} }
int16 keyX = _kbdBound.left - _dirtyRect.left; surf.blit(_kbdSurface, _kbdBound.left - _dirtyRect.left, _kbdBound.top - _dirtyRect.top, _kbdTransparentColor);
int16 keyY = _kbdBound.top - _dirtyRect.top; if (_displayEnabled) surf.blit(&_dispSurface, _dispX - _dirtyRect.left, _dispY - _dirtyRect.top, _dispBackColor);
surf.blit(_kbdSurface, keyX, keyY, _kbdTransparentColor);
if (_displayEnabled) surf.blit(&_dispSurface, keyX + _dispX, keyY + _dispY, _dispBackColor);
_system->copyRectToOverlay((OverlayColor*)surf.pixels, surf.w, _system->copyRectToOverlay((OverlayColor*)surf.pixels, surf.w,
_dirtyRect.left, _dirtyRect.top, surf.w, surf.h); _dirtyRect.left, _dirtyRect.top, surf.w, surf.h);
surf.free(); surf.free();
_needRedraw = false;
resetDirtyRect(); resetDirtyRect();
} }
@ -301,15 +308,21 @@ uint VirtualKeyboardGUI::calculateEndIndex(const String& str, uint startIndex) {
} }
void VirtualKeyboardGUI::animateCaret() { void VirtualKeyboardGUI::animateCaret() {
if (!_displayEnabled) return;
if (_system->getMillis() % kCaretBlinkTime < kCaretBlinkTime / 2) { if (_system->getMillis() % kCaretBlinkTime < kCaretBlinkTime / 2) {
if (!_drawCaret) { if (!_drawCaret) {
_drawCaret = true; _drawCaret = true;
_refreshDisplay = true; _dispSurface.drawLine(_caretX, 0, _caretX, _dispSurface.h, _dispForeColor);
extendDirtyRect(Rect(_dispX + _caretX, _dispY, _dispX + _caretX + 1, _dispY + _dispSurface.h));
redraw();
} }
} else { } else {
if (_drawCaret) { if (_drawCaret) {
_drawCaret = false; _drawCaret = false;
_refreshDisplay = true; _dispSurface.drawLine(_caretX, 0, _caretX, _dispSurface.h, _dispBackColor);
extendDirtyRect(Rect(_dispX + _caretX, _dispY, _dispX + _caretX + 1, _dispY + _dispSurface.h));
redraw();
} }
} }
} }
@ -317,8 +330,6 @@ void VirtualKeyboardGUI::animateCaret() {
void VirtualKeyboardGUI::updateDisplay() { void VirtualKeyboardGUI::updateDisplay() {
if (!_displayEnabled) return; if (!_displayEnabled) return;
_refreshDisplay = false;
// calculate the text to display // calculate the text to display
uint cursorPos = _kbd->_keyQueue.getInsertIndex(); uint cursorPos = _kbd->_keyQueue.getInsertIndex();
String wholeText = _kbd->_keyQueue.getString(); String wholeText = _kbd->_keyQueue.getString();
@ -333,15 +344,15 @@ void VirtualKeyboardGUI::updateDisplay() {
String dispText = String(wholeText.c_str() + _dispI, wholeText.c_str() + dispTextEnd); String dispText = String(wholeText.c_str() + _dispI, wholeText.c_str() + dispTextEnd);
// draw to display surface // draw to display surface
_dispSurface.fillRect(Rect(0, 0, _dispSurface.w, _dispSurface.h), _dispBackColor); _dispSurface.fillRect(Rect(_dispSurface.w, _dispSurface.h), _dispBackColor);
_dispFont->drawString(&_dispSurface, dispText, 0, 0, _dispSurface.w, _dispForeColor); _dispFont->drawString(&_dispSurface, dispText, 0, 0, _dispSurface.w, _dispForeColor);
if (_drawCaret) {
String beforeCaret(wholeText.c_str() + _dispI, wholeText.c_str() + cursorPos); String beforeCaret(wholeText.c_str() + _dispI, wholeText.c_str() + cursorPos);
int16 caretX = _dispFont->getStringWidth(beforeCaret); _caretX = _dispFont->getStringWidth(beforeCaret);
_dispSurface.drawLine(caretX, 0, caretX, _dispSurface.h, _dispForeColor); if (_drawCaret) _dispSurface.drawLine(_caretX, 0, _caretX, _dispSurface.h, _dispForeColor);
}
_needRedraw = true; extendDirtyRect(Rect(_dispX, _dispY, _dispX + _dispSurface.w, _dispY + _dispSurface.h));
redraw();
} }
void VirtualKeyboardGUI::setupCursor() { void VirtualKeyboardGUI::setupCursor() {

View File

@ -53,45 +53,43 @@ private:
OSystem *_system; OSystem *_system;
VirtualKeyboard *_kbd; VirtualKeyboard *_kbd;
Rect _kbdBound;
Graphics::Surface *_kbdSurface; Graphics::Surface *_kbdSurface;
OverlayColor _kbdTransparentColor; OverlayColor _kbdTransparentColor;
Point _dragPoint;
bool _drag;
static const int SNAP_WIDTH = 10; static const int SNAP_WIDTH = 10;
Graphics::Surface _overlayBackup; Graphics::Surface _overlayBackup;
Rect _dirtyRect; Rect _dirtyRect;
bool _displayEnabled; bool _displayEnabled;
bool _refreshDisplay;
Graphics::Surface _dispSurface; Graphics::Surface _dispSurface;
const Graphics::Font *_dispFont; const Graphics::Font *_dispFont;
int16 _dispX, _dispY; int16 _dispX, _dispY;
uint _dispI; uint _dispI;
OverlayColor _dispForeColor, _dispBackColor; OverlayColor _dispForeColor, _dispBackColor;
Rect _kbdBound;
Point _dragPoint;
bool _drag;
bool _displaying; bool _displaying;
bool _firstRun; bool _firstRun;
bool _needRedraw;
int _lastScreenChanged; int _lastScreenChanged;
void setDefaultPosition(); void setupDisplayArea(Rect& r, OverlayColor forecolor);
void move(int16 x, int16 y); void move(int16 x, int16 y);
void moveToDefaultPosition();
void screenChanged(); void screenChanged();
void mainLoop(); void mainLoop();
void extendDirtyRect(const Rect &r); void extendDirtyRect(const Rect &r);
void resetDirtyRect(); void resetDirtyRect();
void redraw(); void redraw();
void forceRedraw();
void updateDisplay(); void updateDisplay();
bool fontIsSuitable(const Graphics::Font *font, const Rect& rect); bool fontIsSuitable(const Graphics::Font *font, const Rect& rect);
uint calculateEndIndex(const String& str, uint startIndex); uint calculateEndIndex(const String& str, uint startIndex);
bool _drawCaret; bool _drawCaret;
int16 _caretX;
static const int kCaretBlinkTime = 500; static const int kCaretBlinkTime = 500;
void animateCaret(); void animateCaret();

View File

@ -308,6 +308,7 @@ void VirtualKeyboard::KeyPressQueue::deleteKey() {
while((it->strLen)-- > 0) while((it->strLen)-- > 0)
_keysStr.deleteChar(_strPos); _keysStr.deleteChar(_strPos);
_keys.erase(it); _keys.erase(it);
_strChanged = true;
} }
void VirtualKeyboard::KeyPressQueue::moveLeft() { void VirtualKeyboard::KeyPressQueue::moveLeft() {
@ -315,6 +316,7 @@ void VirtualKeyboard::KeyPressQueue::moveLeft() {
return; return;
_keyPos--; _keyPos--;
_strPos -= _keyPos->strLen; _strPos -= _keyPos->strLen;
_strChanged = true;
} }
void VirtualKeyboard::KeyPressQueue::moveRight() { void VirtualKeyboard::KeyPressQueue::moveRight() {
@ -322,6 +324,7 @@ void VirtualKeyboard::KeyPressQueue::moveRight() {
return; return;
_strPos += _keyPos->strLen; _strPos += _keyPos->strLen;
_keyPos++; _keyPos++;
_strChanged = true;
} }
KeyState VirtualKeyboard::KeyPressQueue::pop() { KeyState VirtualKeyboard::KeyPressQueue::pop() {