diff options
-rw-r--r-- | common/imageMap.cpp | 2 | ||||
-rw-r--r-- | common/imageMap.h | 4 | ||||
-rw-r--r-- | gui/virtualKeyboard.cpp | 111 | ||||
-rw-r--r-- | gui/virtualKeyboard.h | 35 | ||||
-rw-r--r-- | gui/virtualKeyboardParser.cpp | 66 | ||||
-rw-r--r-- | gui/virtualKeyboardParser.h | 10 |
6 files changed, 198 insertions, 30 deletions
diff --git a/common/imageMap.cpp b/common/imageMap.cpp index 7c8498ea06..4646123754 100644 --- a/common/imageMap.cpp +++ b/common/imageMap.cpp @@ -35,7 +35,7 @@ void ImageMap::addPolygonMapArea(const Polygon& poly, const String& target) { areas.push_back(MapArea(poly, target)); } -MapArea *ImageMap::findMapArea(int x, int y) { +MapArea *ImageMap::findMapArea(int16 x, int16 y) { Array<MapArea>::iterator it; for (it = areas.begin(); it != areas.end(); it++) { if (it->contains(x, y)) diff --git a/common/imageMap.h b/common/imageMap.h index 4edf511825..b6a1ad36f4 100644 --- a/common/imageMap.h +++ b/common/imageMap.h @@ -49,7 +49,7 @@ public: return _shape->contains(x, y); } - const String& getTarget() { return _target; } + String getTarget() { return _target; } protected: /* shape defining the MapArea's boundary */ @@ -66,7 +66,7 @@ public: void addRectMapArea(const Rect& rect, const String& target); void addPolygonMapArea(const Polygon& poly, const String& target); - MapArea *findMapArea(int x, int y); + MapArea *findMapArea(int16 x, int16 y); protected: Array<MapArea> areas; diff --git a/gui/virtualKeyboard.cpp b/gui/virtualKeyboard.cpp index a47f890ce5..02c28bf4a2 100644 --- a/gui/virtualKeyboard.cpp +++ b/gui/virtualKeyboard.cpp @@ -31,19 +31,34 @@ namespace GUI { -VirtualKeyboard::VirtualKeyboard() { +VirtualKeyboard::VirtualKeyboard() : _currentMode(0) { assert(g_system); _system = g_system; _parser = new VirtualKeyboardParser(this); - } VirtualKeyboard::~VirtualKeyboard() { + // TODO: clean up event data pointers + delete _parser; +} + +void VirtualKeyboard::reset() { + // TODO: clean up event data pointers + _modes.clear(); + _initialMode = _currentMode = 0; + _pos.x = _pos.y = 0; + _hAlignment = kAlignCentre; + _vAlignment = kAlignBottom; + _keyQueue.clear(); + _displaying = false; } bool VirtualKeyboard::loadKeyboardPack(Common::String packName) { + // reset to default settings + reset(); + if (ConfMan.hasKey("extrapath")) Common::File::addDefaultDirectoryRecursive(ConfMan.get("extrapath")); @@ -84,19 +99,105 @@ bool VirtualKeyboard::loadKeyboardPack(Common::String packName) { return false; } - return _parser->parse(); + if (!_parser->parse()) + return false; + + if (!_initialMode) + warning("Initial mode of keyboard pack not defined"); + + ModeMap::iterator it; + for (it = _modes.begin(); it != _modes.end(); it++) { + // if no image then it means layout tag for the + // required resolution was missing from the mode tag. + if (!it->_value.image) { + warning("'%s' layout missing from '%s' mode", it->_value.resolution, it->_value.name); + return false; + } + } + + reposition(); + + return true; } -void VirtualKeyboard::show() { +void VirtualKeyboard::reposition() +{ + // calculate keyboard co-ordinates + int16 scrW = _system->getOverlayWidth(), scrH = _system->getOverlayHeight(); + int16 keyW = _currentMode->image->w, keyH = _currentMode->image->h; + if (scrW != keyW) { + switch (_hAlignment) { + case kAlignCentre: + _pos.x = (scrW - keyW) / 2; + break; + case kAlignRight: + _pos.x = scrW - keyW; + break; + } + } + if (scrH != keyH) { + switch (_vAlignment) { + case kAlignMiddle: + _pos.y = (scrH - keyH) / 2; + break; + case kAlignBottom: + _pos.y = scrH - keyH; + break; + } + } +} + +void VirtualKeyboard::processClick(int16 x, int16 y) +{ + x -= _pos.x; + y -= _pos.y; + if (x < 0 || x > _currentMode->image->w) return; + if (y < 0 || y > _currentMode->image->h) return; + + Common::MapArea *area = _currentMode->imageMap.findMapArea(x, y); + if (!area) return; + if (!_currentMode->events.contains(area->getTarget())) return; + Event evt = _currentMode->events[area->getTarget()]; + + switch (evt.type) { + case kEventKey: + // add virtual keypress to queue + _keyQueue.push_back(*(Common::KeyState*)evt.data); + break; + case kEventSwitchMode: + // switch to new mode + switchMode(*(Common::String *)evt.data); + break; + case kEventClose: + // close virtual keyboard + _displaying = false; + break; + } +} +void VirtualKeyboard::switchMode(const Common::String& newMode) { + if (!_modes.contains(newMode)) return; + _currentMode = &_modes[newMode]; + reposition(); + draw(); +} + +void VirtualKeyboard::show() { + _displaying = true; + runLoop(); } void VirtualKeyboard::runLoop() { + while (_displaying) { + + } } void VirtualKeyboard::draw() { - + _system->copyRectToOverlay((OverlayColor*)_currentMode->image->pixels, + _currentMode->image->pitch, _pos.x, _pos.y, + _currentMode->image->w, _currentMode->image->h); } } // end of namespace GUI diff --git a/gui/virtualKeyboard.h b/gui/virtualKeyboard.h index 7885f2cc17..914949aad3 100644 --- a/gui/virtualKeyboard.h +++ b/gui/virtualKeyboard.h @@ -31,6 +31,7 @@ class OSystem; #include "common/hashmap.h" #include "common/hash-str.h" #include "common/imagemap.h" +#include "common/keyboard.h" #include "common/str.h" #include "graphics/surface.h" @@ -46,6 +47,7 @@ private: enum EventType { kEventKey, kEventSwitchMode, + kEventClose, kEventMax }; @@ -65,6 +67,21 @@ private: Graphics::Surface *image; Common::ImageMap imageMap; EventMap events; + Mode() : image(0) {} + }; + + typedef Common::HashMap<Common::String, Mode, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> ModeMap; + + enum HorizontalAlignment { + kAlignLeft, + kAlignCentre, + kAlignRight + }; + + enum VerticalAlignment { + kAlignTop, + kAlignMiddle, + kAlignBottom }; public: @@ -80,10 +97,26 @@ private: friend class VirtualKeyboardParser; VirtualKeyboardParser *_parser; + // TODO : sort order of all this stuff + void reset(); + void reposition(); + void switchMode(const Common::String& newMode); + void processClick(int16 x, int16 y); void runLoop(); void draw(); - Common::HashMap<Common::String, Mode, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _modes; + bool _displaying; + + ModeMap _modes; + Mode *_initialMode; + Mode *_currentMode; + + Common::Point _pos; + HorizontalAlignment _hAlignment; + VerticalAlignment _vAlignment; + + Common::Array<Common::KeyState> _keyQueue; + }; diff --git a/gui/virtualKeyboardParser.cpp b/gui/virtualKeyboardParser.cpp index ca4a9c521a..93b670e7c9 100644 --- a/gui/virtualKeyboardParser.cpp +++ b/gui/virtualKeyboardParser.cpp @@ -59,9 +59,33 @@ bool VirtualKeyboardParser::parserCallback_Keyboard() { if (_kbdParsed) return parserError("Only a single keyboard element is allowed"); - _kbdParsed = true; + if (!kbdNode->values.contains("initial_mode")) + return parserError("Keyboard element must contain initial_mode attribute"); + + _initialModeName = kbdNode->values["initial_mode"]; + + if (kbdNode->values.contains("h_align")) { + Common::String h = kbdNode->values["h_align"]; + if (h == "left") + _keyboard->_hAlignment = VirtualKeyboard::kAlignLeft; + else if (h == "centre" || h == "center") + _keyboard->_hAlignment = VirtualKeyboard::kAlignCentre; + else if (h == "right") + _keyboard->_hAlignment = VirtualKeyboard::kAlignRight; + } + + if (kbdNode->values.contains("v_align")) { + Common::String v = kbdNode->values["h_align"]; + if (v == "top") + _keyboard->_vAlignment = VirtualKeyboard::kAlignTop; + else if (v == "middle" || v == "center") + _keyboard->_vAlignment = VirtualKeyboard::kAlignMiddle; + else if (v == "bottom") + _keyboard->_vAlignment = VirtualKeyboard::kAlignBottom; + } + return true; } @@ -81,10 +105,16 @@ bool VirtualKeyboardParser::parserCallback_Mode() { if (_keyboard->_modes.contains(name)) return parserError("Mode '%s' has already been defined", name); + // create new mode VirtualKeyboard::Mode mode; mode.name = name; _keyboard->_modes[name] = mode; - _currentMode = &(_keyboard->_modes[name]); + _mode = &(_keyboard->_modes[name]); + + // if this is the keyboard's initial mode + // then set it to be the current mode + if (name == _initialModeName) + _keyboard->_initialMode = _mode; Common::String resolutions = modeNode->values["resolutions"]; Common::StringTokenizer tok(resolutions, " ,"); @@ -98,19 +128,19 @@ bool VirtualKeyboardParser::parserCallback_Mode() { parserError("Invalid resolution specification"); } else { if (resX == scrX && resY == scrY) { - _currentMode->resolution = res; + _mode->resolution = res; break; } else if (resX < scrX && resY < scrY) { uint16 newDiff = (scrX - resX) + (scrY - resY); if (newDiff < diff) { diff = newDiff; - _currentMode->resolution = res; + _mode->resolution = res; } } } } - if (_currentMode->resolution.empty()) + if (_mode->resolution.empty()) return parserError("No acceptable resolution was found"); return true; @@ -127,10 +157,10 @@ bool VirtualKeyboardParser::parserCallback_Event() { if (!evtNode->values.contains("name") || !evtNode->values.contains("type")) return parserError("Event element must contain name and type attributes"); - assert(_currentMode); + assert(_mode); Common::String name = evtNode->values["name"]; - if (_currentMode->events.contains(name)) + if (_mode->events.contains(name)) return parserError("Event '%s' has already been defined", name); VirtualKeyboard::Event evt; @@ -170,7 +200,7 @@ bool VirtualKeyboardParser::parserCallback_Event() { } else return parserError("Event type '%s' not known", type); - _currentMode->events[name] = evt; + _mode->events[name] = evt; return true; } @@ -186,24 +216,24 @@ bool VirtualKeyboardParser::parserCallback_Layout() { if (!layoutNode->values.contains("resolution") || !layoutNode->values.contains("bitmap")) return parserError("Layout element must contain resolution and bitmap attributes"); - assert(!_currentMode->resolution.empty()); + assert(!_mode->resolution.empty()); Common::String res = layoutNode->values["resolution"]; - if (res != _currentMode->resolution) { + if (res != _mode->resolution) { layoutNode->ignore = true; return true; } - _currentMode->bitmapName = layoutNode->values["bitmap"]; + _mode->bitmapName = layoutNode->values["bitmap"]; - if (!ImageMan.registerSurface(_currentMode->bitmapName, 0)) - return parserError("Error loading bitmap '%s'", _currentMode->bitmapName.c_str()); + if (!ImageMan.registerSurface(_mode->bitmapName, 0)) + return parserError("Error loading bitmap '%s'", _mode->bitmapName.c_str()); - _currentMode->image = ImageMan.getSurface(_currentMode->bitmapName); - if (!_currentMode->image) - return parserError("Error loading bitmap '%s'", _currentMode->bitmapName.c_str()); + _mode->image = ImageMan.getSurface(_mode->bitmapName); + if (!_mode->image) + return parserError("Error loading bitmap '%s'", _mode->bitmapName.c_str()); return true; } @@ -237,7 +267,7 @@ bool VirtualKeyboardParser::parserCallback_Area() { return parserError("Invalid coords for rect area"); Common::Rect rect(x1, y1, x2, y2); - _currentMode->imageMap.addRectMapArea(rect, areaNode->values["target"]); + _mode->imageMap.addRectMapArea(rect, areaNode->values["target"]); } else if (shape == "poly") { Common::StringTokenizer tok (areaNode->values["coords"], ", "); Common::Polygon poly; @@ -252,7 +282,7 @@ bool VirtualKeyboardParser::parserCallback_Area() { } if (poly.getPointCount() < 3) return parserError("Invalid coords for polygon area"); - _currentMode->imageMap.addPolygonMapArea(poly, areaNode->values["target"]); + _mode->imageMap.addPolygonMapArea(poly, areaNode->values["target"]); } else return parserError("Area shape '%s' not known", shape); diff --git a/gui/virtualKeyboardParser.h b/gui/virtualKeyboardParser.h index b5ed59877f..6ac8e57612 100644 --- a/gui/virtualKeyboardParser.h +++ b/gui/virtualKeyboardParser.h @@ -41,14 +41,18 @@ public: protected: VirtualKeyboard *_keyboard; - VirtualKeyboard::Mode *_currentMode; + /** internal state variables of parser */ + VirtualKeyboard::Mode *_mode; // pointer to mode currently being parsed + bool _modeParsed; + Common::String _initialModeName; // name of initial keyboard mode bool _kbdParsed; bool keyCallback(Common::String keyName); void cleanup() { - _currentMode = 0; - _kbdParsed = false; + _mode = 0; + _kbdParsed = _modeParsed = false; + _initialModeName.clear(); } bool parserCallback_Keyboard(); |