aboutsummaryrefslogtreecommitdiff
path: root/backends/keymapper/remap-dialog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'backends/keymapper/remap-dialog.cpp')
-rw-r--r--backends/keymapper/remap-dialog.cpp334
1 files changed, 334 insertions, 0 deletions
diff --git a/backends/keymapper/remap-dialog.cpp b/backends/keymapper/remap-dialog.cpp
new file mode 100644
index 0000000000..a3c010d28b
--- /dev/null
+++ b/backends/keymapper/remap-dialog.cpp
@@ -0,0 +1,334 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#include "backends/keymapper/remap-dialog.h"
+
+#ifdef ENABLE_KEYMAPPER
+
+#include "gui/eval.h"
+#include "gui/newgui.h"
+#include "gui/PopUpWidget.h"
+#include "gui/ScrollBarWidget.h"
+
+namespace Common {
+
+enum {
+ kRemapCmd = 'REMP',
+ kCloseCmd = 'CLOS'
+};
+
+RemapDialog::RemapDialog()
+ : Dialog("remap"), _keymapTable(0), _activeRemapAction(0), _topAction(0), _remapTimeout(0) {
+
+ _keymapper = g_system->getEventManager()->getKeymapper();
+ assert(_keymapper);
+
+ int labelWidth = g_gui.evaluator()->getVar("remap_popup_labelW");
+ _kmPopUp = new GUI::PopUpWidget(this, "remap_popup", "Keymap: ", labelWidth);
+
+ _scrollBar = new GUI::ScrollBarWidget(this, 0, 0, 0, 0);
+
+ new GUI::ButtonWidget(this, "remap_close_button", "Close", kCloseCmd);
+}
+
+RemapDialog::~RemapDialog() {
+ if (_keymapTable) free(_keymapTable);
+}
+
+void RemapDialog::open() {
+ bool divider = false;
+ _activeKeymaps = &_keymapper->getActiveStack();
+ if (_activeKeymaps->size() > 0) {
+ _kmPopUp->appendEntry(_activeKeymaps->top().keymap->getName() + " (Active)");
+ divider = true;
+ }
+
+ Keymapper::Domain *_globalKeymaps = &_keymapper->getGlobalDomain();
+ Keymapper::Domain *_gameKeymaps = 0;
+
+ int keymapCount = 0;
+ if (_globalKeymaps->count() == 0)
+ _globalKeymaps = 0;
+ else
+ keymapCount += _globalKeymaps->count();
+
+ if (ConfMan.getActiveDomain() != 0) {
+ _gameKeymaps = &_keymapper->getGameDomain();
+ if (_gameKeymaps->count() == 0)
+ _gameKeymaps = 0;
+ else
+ keymapCount += _gameKeymaps->count();
+ }
+
+ _keymapTable = (Keymap**)malloc(sizeof(Keymap*) * keymapCount);
+
+ Keymapper::Domain::iterator it;
+ uint32 idx = 0;
+ if (_globalKeymaps) {
+ if (divider) _kmPopUp->appendEntry("");
+ for (it = _globalKeymaps->begin(); it != _globalKeymaps->end(); it++) {
+ _kmPopUp->appendEntry(it->_value->getName() + " (Global)", idx);
+ _keymapTable[idx++] = it->_value;
+ }
+ divider = true;
+ }
+ if (_gameKeymaps) {
+ if (divider) _kmPopUp->appendEntry("");
+ for (it = _gameKeymaps->begin(); it != _gameKeymaps->end(); it++) {
+ _kmPopUp->appendEntry(it->_value->getName() + " (Game)", idx);
+ _keymapTable[idx++] = it->_value;
+ }
+ }
+
+ _changes = false;
+
+ Dialog::open();
+
+ _kmPopUp->setSelected(0);
+ loadKeymap();
+}
+
+void RemapDialog::close() {
+ _kmPopUp->clearEntries();
+ if (_keymapTable) {
+ free(_keymapTable);
+ _keymapTable = 0;
+ }
+ if (_changes)
+ ConfMan.flushToDisk();
+ Dialog::close();
+}
+
+void RemapDialog::reflowLayout() {
+ int scrollbarWidth, buttonHeight;
+ if (g_gui.getWidgetSize() == GUI::kBigWidgetSize) {
+ buttonHeight = GUI::kBigButtonHeight;
+ scrollbarWidth = GUI::kBigScrollBarWidth;
+ } else {
+ buttonHeight = GUI::kButtonHeight;
+ scrollbarWidth = GUI::kNormalScrollBarWidth;
+ }
+ int areaX = g_gui.evaluator()->getVar("remap_keymap_area.x");
+ int areaY = g_gui.evaluator()->getVar("remap_keymap_area.y");
+ int areaW = g_gui.evaluator()->getVar("remap_keymap_area.w");
+ int areaH = g_gui.evaluator()->getVar("remap_keymap_area.h");
+ int spacing = g_gui.evaluator()->getVar("remap_spacing");
+ int labelWidth = g_gui.evaluator()->getVar("remap_label_width");
+ int buttonWidth = g_gui.evaluator()->getVar("remap_button_width");
+ int colWidth = labelWidth + buttonWidth + spacing;
+ _colCount = (areaW - scrollbarWidth) / colWidth;
+ _rowCount = (areaH + spacing) / (buttonHeight + spacing);
+ if (_colCount <= 0 || _rowCount <= 0)
+ error("Remap dialog too small to display any keymaps!");
+
+ _kmPopUp->changeLabelWidth(labelWidth);
+
+ _scrollBar->resize(areaX + areaW - scrollbarWidth, areaY, scrollbarWidth, areaH);
+ _scrollBar->_entriesPerPage = _rowCount;
+ _scrollBar->_numEntries = 1;
+ _scrollBar->recalc();
+
+ uint textYOff = (buttonHeight - kLineHeight) / 2;
+ uint oldSize = _keymapWidgets.size();
+ uint newSize = _rowCount * _colCount;
+ _keymapWidgets.reserve(newSize);
+ for (uint i = 0; i < newSize; i++) {
+ ActionWidgets widg;
+ if (i >= _keymapWidgets.size()) {
+ widg.actionText =
+ new GUI::StaticTextWidget(this, 0, 0, 0, 0, "", Graphics::kTextAlignRight);
+ widg.keyButton =
+ new GUI::ButtonWidget(this, 0, 0, 0, 0, "", kRemapCmd + i);
+ _keymapWidgets.push_back(widg);
+ } else {
+ widg = _keymapWidgets[i];
+ }
+ uint x = areaX + (i % _colCount) * colWidth;
+ uint y = areaY + (i / _colCount) * (buttonHeight + spacing);
+ widg.actionText->resize(x, y + textYOff, labelWidth, kLineHeight);
+ widg.keyButton->resize(x + labelWidth, y, buttonWidth, buttonHeight);
+ }
+ while (oldSize > newSize) {
+ ActionWidgets widg = _keymapWidgets.remove_at(--oldSize);
+ removeWidget(widg.actionText);
+ delete widg.actionText;
+ removeWidget(widg.keyButton);
+ delete widg.keyButton;
+ }
+ Dialog::reflowLayout();
+}
+
+void RemapDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
+ if (cmd >= kRemapCmd && cmd < kRemapCmd + _keymapWidgets.size()) {
+ startRemapping(cmd - kRemapCmd);
+ } else if (cmd == GUI::kPopUpItemSelectedCmd) {
+ loadKeymap();
+ } else if (cmd == GUI::kSetPositionCmd) {
+ refreshKeymap();
+ } else if (cmd == kCloseCmd) {
+ close();
+ } else {
+ GUI::Dialog::handleCommand(sender, cmd, data);
+ }
+}
+
+void RemapDialog::startRemapping(uint i) {
+ if (_topAction + i >= _currentActions.size()) return;
+ _remapTimeout = getMillis() + kRemapTimeoutDelay;
+ _activeRemapAction = _currentActions[_topAction + i].action;
+ _keymapWidgets[i].keyButton->setLabel("...");
+ _keymapWidgets[i].keyButton->draw();
+ _keymapper->setEnabled(false);
+
+}
+
+void RemapDialog::stopRemapping() {
+ _topAction = -1;
+ refreshKeymap();
+ _activeRemapAction = 0;
+ _keymapper->setEnabled(true);
+}
+
+void RemapDialog::handleKeyUp(Common::KeyState state) {
+ if (_activeRemapAction) {
+ const HardwareKey *hwkey = _keymapper->getHardwareKey(state);
+ if (hwkey) {
+ _activeRemapAction->mapKey(hwkey);
+ // TODO: _activeRemapAction->getParent()->saveMappings();
+ _changes = true;
+ stopRemapping();
+ }
+ } else {
+ GUI::Dialog::handleKeyDown(state);
+ }
+}
+
+void RemapDialog::handleMouseDown(int x, int y, int button, int clickCount) {
+ if (_activeRemapAction)
+ stopRemapping();
+ else
+ Dialog::handleMouseDown(x, y, button, clickCount);
+}
+
+void RemapDialog::handleTickle() {
+ if (_activeRemapAction && getMillis() > _remapTimeout)
+ stopRemapping();
+ Dialog::handleTickle();
+}
+
+void RemapDialog::loadKeymap() {
+ _currentActions.clear();
+ if (_activeKeymaps->size() > 0 && _kmPopUp->getSelected() == 0) {
+ // load active keymaps
+
+ List<const HardwareKey*> freeKeys (_keymapper->getHardwareKeySet()->getHardwareKeys());
+
+ // add most active keymap's keys
+ Keymapper::MapRecord top = _activeKeymaps->top();
+ List<Action*>::iterator actIt;
+ for (actIt = top.keymap->getActions().begin(); actIt != top.keymap->getActions().end(); ++actIt) {
+ Action *act = *actIt;
+ ActionInfo info = {act, false, act->description};
+ _currentActions.push_back(info);
+ if (act->getMappedKey())
+ freeKeys.remove(act->getMappedKey());
+ }
+
+ // loop through remaining finding mappings for unmapped keys
+ if (top.inherit) {
+ for (int i = _activeKeymaps->size() - 2; i >= 0; --i) {
+ Keymapper::MapRecord mr = (*_activeKeymaps)[i];
+ List<const HardwareKey*>::iterator keyIt = freeKeys.begin();
+ while (keyIt != freeKeys.end()) {
+ Action *act = mr.keymap->getMappedAction((*keyIt)->key);
+ if (act) {
+ ActionInfo info = {act, true, act->description + " (" + mr.keymap->getName() + ")"};
+ _currentActions.push_back(info);
+ freeKeys.erase(keyIt++);
+ } else {
+ ++keyIt;
+ }
+ }
+ if (mr.inherit == false || freeKeys.empty()) break;
+ }
+ }
+
+ } else if (_kmPopUp->getSelected() != -1) {
+ Keymap *km = _keymapTable[_kmPopUp->getSelectedTag()];
+
+ List<Action*>::iterator it;
+ for (it = km->getActions().begin(); it != km->getActions().end(); it++) {
+ ActionInfo info = {*it, false, (*it)->description};
+ _currentActions.push_back(info);
+ }
+ }
+
+ // refresh scroll bar
+ _scrollBar->_currentPos = 0;
+ _scrollBar->_numEntries = (_currentActions.size() + _colCount - 1) / _colCount;
+ _scrollBar->recalc();
+ // force refresh
+ _topAction = -1;
+ refreshKeymap();
+}
+
+void RemapDialog::refreshKeymap() {
+ int newTopAction = _scrollBar->_currentPos * _colCount;
+ if (newTopAction == _topAction) return;
+ _topAction = newTopAction;
+
+ //_container->draw();
+ _scrollBar->draw();
+
+ uint actionI = _topAction;
+ for (uint widgetI = 0; widgetI < _keymapWidgets.size(); widgetI++) {
+ ActionWidgets& widg = _keymapWidgets[widgetI];
+ if (actionI < _currentActions.size()) {
+ ActionInfo& info = _currentActions[actionI];
+ widg.actionText->setLabel(info.description + ": ");
+ widg.actionText->setEnabled(!info.inherited);
+ const HardwareKey *mappedKey = info.action->getMappedKey();
+ if (mappedKey)
+ widg.keyButton->setLabel(mappedKey->description);
+ else
+ widg.keyButton->setLabel("-");
+ widg.actionText->clearFlags(GUI::WIDGET_INVISIBLE);
+ widg.keyButton->clearFlags(GUI::WIDGET_INVISIBLE);
+ actionI++;
+ } else {
+ widg.actionText->setFlags(GUI::WIDGET_INVISIBLE);
+ widg.keyButton->setFlags(GUI::WIDGET_INVISIBLE);
+ }
+ //widg.actionText->draw();
+ //widg.keyButton->draw();
+ }
+ // need to redraw entire Dialog so that invisible
+ // widgets disappear
+ draw();
+}
+
+
+} // end of namespace Common
+
+#endif // #ifdef ENABLE_KEYMAPPER