diff --git a/backends/keymapper/remap-dialog.cpp b/backends/keymapper/remap-dialog.cpp index fb84a02e7c6..8d5ba3c6528 100644 --- a/backends/keymapper/remap-dialog.cpp +++ b/backends/keymapper/remap-dialog.cpp @@ -33,20 +33,21 @@ #include "common/system.h" #include "gui/gui-manager.h" #include "gui/widgets/popup.h" -#include "gui/widgets/scrollbar.h" +#include "gui/widgets/scrollcontainer.h" #include "gui/ThemeEval.h" #include "common/translation.h" namespace Common { enum { - kRemapCmd = 'REMP', - kClearCmd = 'CLER', - kCloseCmd = 'CLOS' + kRemapCmd = 'REMP', + kClearCmd = 'CLER', + kCloseCmd = 'CLOS', + kReflowCmd = 'REFL' }; RemapDialog::RemapDialog() - : Dialog("KeyMapper"), _topAction(0), _remapTimeout(0), _topKeymapIsGui(false), _remapAction(nullptr) { + : Dialog("KeyMapper"), _remapTimeout(0), _remapAction(nullptr) { _keymapper = g_system->getEventManager()->getKeymapper(); assert(_keymapper); @@ -57,10 +58,8 @@ RemapDialog::RemapDialog() _kmPopUpDesc = new GUI::StaticTextWidget(this, "KeyMapper.PopupDesc", _("Keymap:")); _kmPopUp = new GUI::PopUpWidget(this, "KeyMapper.Popup"); - _scrollBar = new GUI::ScrollBarWidget(this, 0, 0, 0, 0); - - GUI::ContainerWidget *keymapArea = new GUI::ContainerWidget(this, "KeyMapper.KeymapArea"); - keymapArea->setBackgroundType(GUI::ThemeEngine::kWidgetBackgroundNo); + _scrollContainer = new GUI::ScrollContainerWidget(this, "KeyMapper.KeymapArea", "", kReflowCmd); + _scrollContainer->setTarget(this); new GUI::ButtonWidget(this, "KeyMapper.Close", _("Close"), 0, kCloseCmd); } @@ -81,10 +80,13 @@ void RemapDialog::open() { _changes = false; - Dialog::open(); - _kmPopUp->setSelected(0); + loadKeymap(); + refreshKeymap(); + reflowActionWidgets(); + + Dialog::open(); } void RemapDialog::close() { @@ -96,101 +98,54 @@ void RemapDialog::close() { Dialog::close(); } -void RemapDialog::reflowLayout() { - Dialog::reflowLayout(); - +void RemapDialog::reflowActionWidgets() { int buttonHeight = g_gui.xmlEval()->getVar("Globals.Button.Height", 0); - int scrollbarWidth = g_gui.xmlEval()->getVar("Globals.Scrollbar.Width", 0); - - int16 areaX, areaY; - uint16 areaW, areaH; - g_gui.xmlEval()->getWidgetData((const String&)String("KeyMapper.KeymapArea"), areaX, areaY, areaW, areaH); int spacing = g_gui.xmlEval()->getVar("Globals.KeyMapper.Spacing"); int keyButtonWidth = g_gui.xmlEval()->getVar("Globals.KeyMapper.ButtonWidth"); int clearButtonWidth = g_gui.xmlEval()->getVar("Globals.Line.Height"); int clearButtonHeight = g_gui.xmlEval()->getVar("Globals.Line.Height"); - - int colWidth = areaW - scrollbarWidth; - int labelWidth = colWidth - (keyButtonWidth + spacing + clearButtonWidth + spacing); - - _rowCount = (areaH + spacing) / (buttonHeight + spacing); - debug(7, "rowCount = %d" , _rowCount); - if (colWidth <= 0 || _rowCount <= 0) - error("Remap dialog too small to display any keymaps"); - - _scrollBar->resize(areaX + areaW - scrollbarWidth, areaY, scrollbarWidth, areaH); - _scrollBar->_entriesPerPage = _rowCount; - _scrollBar->_numEntries = 1; - _scrollBar->recalc(); + int labelWidth = getWidth() - (spacing + keyButtonWidth + spacing + clearButtonWidth + spacing); uint textYOff = (buttonHeight - kLineHeight) / 2; uint clearButtonYOff = (buttonHeight - clearButtonHeight) / 2; - uint oldSize = _keymapWidgets.size(); - uint newSize = _rowCount; - _keymapWidgets.reserve(newSize); + for (uint i = 0; i < _actions.size(); i++) { + uint x = spacing; + uint y = spacing + (i) * (buttonHeight + spacing); - for (uint i = 0; i < newSize; i++) { - ActionWidgets widg; - - if (i >= _keymapWidgets.size()) { - widg.actionText = - new GUI::StaticTextWidget(this, 0, 0, 0, 0, "", Graphics::kTextAlignLeft); - widg.keyButton = - new GUI::ButtonWidget(this, 0, 0, 0, 0, "", 0, kRemapCmd + i); - widg.clearButton = addClearButton(this, "", kClearCmd + i, 0, 0, clearButtonWidth, clearButtonHeight); - _keymapWidgets.push_back(widg); - } else { - widg = _keymapWidgets[i]; - } - - uint x = areaX; - uint y = areaY + (i) * (buttonHeight + spacing); - - widg.keyButton->resize(x, y, keyButtonWidth, buttonHeight); - widg.clearButton->resize(x + keyButtonWidth + spacing, y + clearButtonYOff, clearButtonWidth, clearButtonHeight); - widg.actionText->resize(x + keyButtonWidth + spacing + clearButtonWidth + spacing, y + textYOff, labelWidth, kLineHeight); - - } - while (oldSize > newSize) { - ActionWidgets widg = _keymapWidgets.remove_at(--oldSize); - - removeWidget(widg.actionText); - delete widg.actionText; - - removeWidget(widg.keyButton); - delete widg.keyButton; - - removeWidget(widg.clearButton); - delete widg.clearButton; + ActionRow &row = _actions[i]; + row.keyButton->resize(x, y, keyButtonWidth, buttonHeight); + row.clearButton->resize(x + keyButtonWidth + spacing, y + clearButtonYOff, clearButtonWidth, clearButtonHeight); + row.actionText->resize(x + keyButtonWidth + spacing + clearButtonWidth + spacing, y + textYOff, labelWidth, kLineHeight); } } void RemapDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) { debug(3, "RemapDialog::handleCommand %u %u", cmd, data); - if (cmd >= kRemapCmd && cmd < kRemapCmd + _keymapWidgets.size()) { + if (cmd >= kRemapCmd && cmd < kRemapCmd + _actions.size()) { startRemapping(cmd - kRemapCmd); - } else if (cmd >= kClearCmd && cmd < kClearCmd + _keymapWidgets.size()) { + } else if (cmd >= kClearCmd && cmd < kClearCmd + _actions.size()) { clearMapping(cmd - kClearCmd); - } else if (cmd == GUI::kPopUpItemSelectedCmd) { - loadKeymap(); - } else if (cmd == GUI::kSetPositionCmd) { - refreshKeymap(); } else if (cmd == kCloseCmd) { close(); + } else if (cmd == kReflowCmd) { + reflowActionWidgets(); + } else if (cmd == GUI::kPopUpItemSelectedCmd) { + clearKeymap(); + loadKeymap(); + refreshKeymap(); + _scrollContainer->reflowLayout(); + g_gui.scheduleTopDialogRedraw(); } else { GUI::Dialog::handleCommand(sender, cmd, data); } } void RemapDialog::clearMapping(uint i) { - if (_topAction + i >= _currentActions.size()) - return; - debug(3, "clear the mapping %u", i); - Action *activeRemapAction = _currentActions[_topAction + i]; + Action *activeRemapAction = _actions[i].action; _keymapper->clearMapping(activeRemapAction); _changes = true; @@ -199,25 +154,21 @@ void RemapDialog::clearMapping(uint i) { } void RemapDialog::startRemapping(uint i) { - if (_topAction + i >= _currentActions.size()) - return; - if (_remapInputWatcher->isWatching()) { // Handle a second click on the button as a stop to remapping stopRemapping(); return; } - _remapAction = _currentActions[_topAction + i]; + _remapAction = _actions[i].action; _remapTimeout = g_system->getMillis() + kRemapTimeoutDelay; _remapInputWatcher->startWatching(); - _keymapWidgets[i].keyButton->setLabel("..."); - _keymapWidgets[i].keyButton->markAsDirty(); + _actions[i].keyButton->setLabel("..."); + _actions[i].keyButton->markAsDirty(); } void RemapDialog::stopRemapping() { - _topAction = -1; _remapAction = nullptr; refreshKeymap(); @@ -246,79 +197,58 @@ void RemapDialog::handleTickle() { Dialog::handleTickle(); } -void RemapDialog::loadKeymap() { - _currentActions.clear(); +void RemapDialog::clearKeymap() { + for (uint i = 0; i < _actions.size(); i++) { + if (_actions[i].keyButton) _scrollContainer->removeWidget(_actions[i].keyButton); + if (_actions[i].actionText) _scrollContainer->removeWidget(_actions[i].actionText); + if (_actions[i].clearButton) _scrollContainer->removeWidget(_actions[i].clearButton); - if (_kmPopUp->getSelected() != -1) { - // This is the regular view of a keymap that isn't the topmost one. - // It shows all of that keymap's actions - - Keymap *km = _keymapTable[_kmPopUp->getSelectedTag()]; - - List::iterator it; - - for (it = km->getActions().begin(); it != km->getActions().end(); ++it) { - _currentActions.push_back(*it); - } + delete _actions[i].keyButton; + delete _actions[i].actionText; + delete _actions[i].clearButton; } - // refresh scroll bar - _scrollBar->_currentPos = 0; - _scrollBar->_numEntries = _currentActions.size(); - _scrollBar->recalc(); + _actions.clear(); +} - // force refresh - _topAction = -1; - refreshKeymap(); +void RemapDialog::loadKeymap() { + assert(_actions.empty()); + assert(_kmPopUp->getSelected() != -1); + + Keymap *km = _keymapTable[_kmPopUp->getSelectedTag()]; + for (List::iterator it = km->getActions().begin(); it != km->getActions().end(); ++it) { + ActionRow row; + row.action = *it; + + _actions.push_back(row); + } } void RemapDialog::refreshKeymap() { - int newTopAction = _scrollBar->_currentPos; + int clearButtonWidth = g_gui.xmlEval()->getVar("Globals.Line.Height"); + int clearButtonHeight = g_gui.xmlEval()->getVar("Globals.Line.Height"); - if (newTopAction == _topAction) - return; + for (uint i = 0; i < _actions.size(); i++) { + ActionRow &row = _actions[i]; - _topAction = newTopAction; - - //_container->markAsDirty(); - _scrollBar->markAsDirty(); - - uint actionI = _topAction; - - for (uint widgetI = 0; widgetI < _keymapWidgets.size(); widgetI++) { - ActionWidgets &widg = _keymapWidgets[widgetI]; - - if (actionI < _currentActions.size()) { - debug(8, "RemapDialog::refreshKeymap actionI=%u", actionI); - Action *action = _currentActions[actionI]; - - widg.actionText->setLabel(action->description); - - Keymap *keymap = action->getParent(); - - const HardwareInput *mappedInput = keymap->getActionMapping(action); - if (mappedInput) - widg.keyButton->setLabel(mappedInput->description); - else - widg.keyButton->setLabel("-"); - - widg.actionText->setVisible(true); - widg.keyButton->setVisible(true); - widg.clearButton->setVisible(true); - - actionI++; - } else { - widg.actionText->setVisible(false); - widg.keyButton->setVisible(false); - widg.clearButton->setVisible(false); + if (!row.actionText) { + row.actionText = new GUI::StaticTextWidget(_scrollContainer, 0, 0, 0, 0, "", Graphics::kTextAlignLeft); + row.keyButton = new GUI::ButtonWidget(_scrollContainer, 0, 0, 0, 0, "", 0, kRemapCmd + i); + row.clearButton = addClearButton(_scrollContainer, "", kClearCmd + i, 0, 0, clearButtonWidth, clearButtonHeight); } + + row.actionText->setLabel(row.action->description); + + Keymap *keymap = row.action->getParent(); + + const HardwareInput *mappedInput = keymap->getActionMapping(row.action); + if (mappedInput) + row.keyButton->setLabel(mappedInput->description); + else + row.keyButton->setLabel("-"); } - - // need to redraw entire Dialog so that invisible widgets disappear - g_gui.scheduleTopDialogRedraw(); } - } // End of namespace Common #endif // #ifdef ENABLE_KEYMAPPER diff --git a/backends/keymapper/remap-dialog.h b/backends/keymapper/remap-dialog.h index 58fcf8c474f..3e887aacd88 100644 --- a/backends/keymapper/remap-dialog.h +++ b/backends/keymapper/remap-dialog.h @@ -32,7 +32,7 @@ namespace GUI { class ButtonWidget; class PopUpWidget; -class ScrollBarWidget; +class ScrollContainerWidget; class StaticTextWidget; } @@ -49,20 +49,25 @@ public: virtual ~RemapDialog(); virtual void open(); virtual void close(); - virtual void reflowLayout(); virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data); virtual void handleMouseDown(int x, int y, int button, int clickCount); virtual void handleTickle(); protected: - struct ActionWidgets { + struct ActionRow { + Common::Action *action; + GUI::StaticTextWidget *actionText; GUI::ButtonWidget *keyButton; GUI::ButtonWidget *clearButton; + + ActionRow() : action(nullptr), actionText(nullptr), keyButton(nullptr), clearButton(nullptr) { } }; void loadKeymap(); void refreshKeymap(); + void clearKeymap(); + void reflowActionWidgets(); void clearMapping(uint i); void startRemapping(uint i); void stopRemapping(); @@ -74,22 +79,15 @@ protected: Action *_remapAction; uint32 _remapTimeout; - Array _currentActions; - int _topAction; - GUI::StaticTextWidget *_kmPopUpDesc; GUI::PopUpWidget *_kmPopUp; - GUI::ScrollBarWidget *_scrollBar; + GUI::ScrollContainerWidget *_scrollContainer; - uint _rowCount; - - Array _keymapWidgets; static const uint32 kRemapTimeoutDelay = 3000; bool _changes; - bool _topKeymapIsGui; - + Array _actions; }; } // End of namespace Common diff --git a/gui/themes/default.inc b/gui/themes/default.inc index 60a81b5ed51..8f568c624ad 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -2536,8 +2536,8 @@ const char *defaultXML1 = "" "" "" "" -"" -"" +"" +"" "" @@ -2551,10 +2551,12 @@ const char *defaultXML1 = "" "width='600' " "height='280' " "/>" +"" "" "" +"" "" "" "" @@ -4281,10 +4283,12 @@ const char *defaultXML1 = "" "width='300' " "height='120' " "/>" +"" "" "" +"" "" "" "" diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip index e60ad7b34c5..233e750e422 100644 Binary files a/gui/themes/scummclassic.zip and b/gui/themes/scummclassic.zip differ diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx index 7e9c2c0f243..8c4a44ee375 100644 --- a/gui/themes/scummclassic/classic_layout.stx +++ b/gui/themes/scummclassic/classic_layout.stx @@ -1705,8 +1705,8 @@ - - + + @@ -1720,9 +1720,11 @@ width = '600' height = '280' /> - + + + diff --git a/gui/themes/scummclassic/classic_layout_lowres.stx b/gui/themes/scummclassic/classic_layout_lowres.stx index a96c8fe5be7..01934aadac8 100644 --- a/gui/themes/scummclassic/classic_layout_lowres.stx +++ b/gui/themes/scummclassic/classic_layout_lowres.stx @@ -1689,9 +1689,11 @@ width = '300' height = '120' /> - + + + diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip index 659af99e6fd..fbaf621489a 100644 Binary files a/gui/themes/scummmodern.zip and b/gui/themes/scummmodern.zip differ diff --git a/gui/themes/scummmodern/scummmodern_layout.stx b/gui/themes/scummmodern/scummmodern_layout.stx index 204a6fb1e57..a55530e1050 100644 --- a/gui/themes/scummmodern/scummmodern_layout.stx +++ b/gui/themes/scummmodern/scummmodern_layout.stx @@ -1719,8 +1719,8 @@ - - + + @@ -1734,11 +1734,14 @@ width = '600' height = '280' /> - + + + + - + + + diff --git a/gui/themes/scummremastered.zip b/gui/themes/scummremastered.zip index b28e12f038c..ffe5eed6085 100644 Binary files a/gui/themes/scummremastered.zip and b/gui/themes/scummremastered.zip differ diff --git a/gui/themes/scummremastered/remastered_layout.stx b/gui/themes/scummremastered/remastered_layout.stx index 4e62314f4d5..2281c06dbeb 100644 --- a/gui/themes/scummremastered/remastered_layout.stx +++ b/gui/themes/scummremastered/remastered_layout.stx @@ -1719,8 +1719,8 @@ - - + + @@ -1734,11 +1734,14 @@ width = '600' height = '280' /> - + + + +