From 019f4ae247729e59dd9545d5f39a8de1e8e56a5f Mon Sep 17 00:00:00 2001 From: Thomas Jentzsch Date: Sat, 17 Aug 2019 15:42:39 +0200 Subject: [PATCH] Implement event filter in InputDialog (resolves #517) --- src/emucore/Event.hxx | 9 + src/emucore/EventHandler.cxx | 351 +++++++++++++++++++++++++++------ src/emucore/EventHandler.hxx | 26 ++- src/gui/EventMappingWidget.cxx | 93 ++++++--- src/gui/EventMappingWidget.hxx | 8 +- src/gui/InputDialog.cxx | 8 +- src/gui/ListWidget.cxx | 11 +- 7 files changed, 417 insertions(+), 89 deletions(-) diff --git a/src/emucore/Event.hxx b/src/emucore/Event.hxx index 8683861be..92b4cd8be 100644 --- a/src/emucore/Event.hxx +++ b/src/emucore/Event.hxx @@ -124,6 +124,15 @@ class Event }; + // Event categorizing groups + enum Group + { + Menu, Emulation, + Misc, AudioVideo, States, Console, Joystick, Paddles, Keyboard, + Debug, Combo, + LastGroup + }; + // Event list version, update if the id of existing event types changed static constexpr Int32 VERSION = 3; diff --git a/src/emucore/EventHandler.cxx b/src/emucore/EventHandler.cxx index d4db078de..c510b80df 100644 --- a/src/emucore/EventHandler.cxx +++ b/src/emucore/EventHandler.cxx @@ -1250,6 +1250,80 @@ StringList EventHandler::getActionList(EventMode mode) const return l; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +StringList EventHandler::getActionList(Event::Group group) const +{ + StringList l; + + switch(group) + { + case Event::Group::Menu: + return getActionList(EventMode::kMenuMode); + + case Event::Group::Emulation: + return getActionList(EventMode::kEmulationMode); + + case Event::Group::Misc: + return getActionList(MiscEvents); + + case Event::Group::AudioVideo: + return getActionList(AudioVideoEvents); + + case Event::Group::States: + return getActionList(StateEvents); + + case Event::Group::Console: + return getActionList(ConsoleEvents); + + case Event::Group::Joystick: + return getActionList(JoystickEvents); + + case Event::Group::Paddles: + return getActionList(PaddlesEvents); + + case Event::Group::Keyboard: + return getActionList(KeyboardEvents); + + case Event::Group::Debug: + return getActionList(DebugEvents); + + case Event::Group::Combo: + return getActionList(ComboEvents); + + default: + return l; // ToDo + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +StringList EventHandler::getActionList(const EventList& events, EventMode mode) const +{ + StringList l; + + switch(mode) + { + case EventMode::kMenuMode: + for(uInt32 i = 0; i < MENU_ACTIONLIST_SIZE; ++i) + for(const auto& event : events) + if(EventHandler::ourMenuActionList[i].event == event) + { + l.push_back(EventHandler::ourMenuActionList[i].action); + break; + } + break; + + default: + for(uInt32 i = 0; i < EMUL_ACTIONLIST_SIZE; ++i) + for(const auto& event : events) + if(EventHandler::ourEmulActionList[i].event == event) + { + l.push_back(EventHandler::ourEmulActionList[i].action); + break; + } + } + return l; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VariantList EventHandler::getComboList(EventMode /**/) const { @@ -1320,62 +1394,136 @@ void EventHandler::setComboListForEvent(Event::Type event, const StringList& eve } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Event::Type EventHandler::eventAtIndex(int idx, EventMode mode) const +int EventHandler::getEmulActionListIndex(int idx, const EventList& events) const { - switch(mode) + // idx = index into intersection set of 'events' and 'ourEmulActionList' + // ordered by 'ourEmulActionList'! + Event::Type event = Event::NoType; + + for(uInt32 i = 0; i < EMUL_ACTIONLIST_SIZE; ++i) { - case EventMode::kEmulationMode: - if(idx < 0 || idx >= EMUL_ACTIONLIST_SIZE) - return Event::NoType; - else - return ourEmulActionList[idx].event; - case EventMode::kMenuMode: - if(idx < 0 || idx >= MENU_ACTIONLIST_SIZE) - return Event::NoType; - else - return ourMenuActionList[idx].event; + for(const auto& item : events) + if(EventHandler::ourEmulActionList[i].event == item) + { + idx--; + if(idx < 0) + event = item; + break; + } + if(idx < 0) + break; + } + + for(uInt32 i = 0; i < EMUL_ACTIONLIST_SIZE; ++i) + if(EventHandler::ourEmulActionList[i].event == event) + return i; + + return -1; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +int EventHandler::getActionListIndex(int idx, Event::Group group) const +{ + switch(group) + { + case Event::Group::Menu: + return idx; + + case Event::Group::Emulation: + return idx; + + case Event::Group::Misc: + return getEmulActionListIndex(idx, MiscEvents); + + case Event::Group::AudioVideo: + return getEmulActionListIndex(idx, AudioVideoEvents); + + case Event::Group::States: + return getEmulActionListIndex(idx, StateEvents); + + case Event::Group::Console: + return getEmulActionListIndex(idx, ConsoleEvents); + + case Event::Group::Joystick: + return getEmulActionListIndex(idx, JoystickEvents); + + case Event::Group::Paddles: + return getEmulActionListIndex(idx, PaddlesEvents); + + case Event::Group::Keyboard: + return getEmulActionListIndex(idx, KeyboardEvents); + + case Event::Group::Debug: + return getEmulActionListIndex(idx, DebugEvents); + + case Event::Group::Combo: + return getEmulActionListIndex(idx, ComboEvents); + default: - return Event::NoType; + return -1; + }; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Event::Type EventHandler::eventAtIndex(int idx, Event::Group group) const +{ + int index = getActionListIndex(idx, group); + + switch(group) + { + case Event::Group::Menu: + if(index < 0 || index >= MENU_ACTIONLIST_SIZE) + return Event::NoType; + else + return ourMenuActionList[index].event; + + default: + if(index < 0 || index >= EMUL_ACTIONLIST_SIZE) + return Event::NoType; + else + return ourEmulActionList[index].event; } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string EventHandler::actionAtIndex(int idx, EventMode mode) const +string EventHandler::actionAtIndex(int idx, Event::Group group) const { - switch(mode) + int index = getActionListIndex(idx, group); + + switch(group) { - case EventMode::kEmulationMode: - if(idx < 0 || idx >= EMUL_ACTIONLIST_SIZE) + case Event::Group::Menu: + if(index < 0 || index >= MENU_ACTIONLIST_SIZE) return EmptyString; else - return ourEmulActionList[idx].action; - case EventMode::kMenuMode: - if(idx < 0 || idx >= MENU_ACTIONLIST_SIZE) - return EmptyString; - else - return ourMenuActionList[idx].action; + return ourMenuActionList[index].action; + default: - return EmptyString; + if(index < 0 || index >= EMUL_ACTIONLIST_SIZE) + return EmptyString; + else + return ourEmulActionList[index].action; } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string EventHandler::keyAtIndex(int idx, EventMode mode) const +string EventHandler::keyAtIndex(int idx, Event::Group group) const { - switch(mode) + int index = getActionListIndex(idx, group); + + switch(group) { - case EventMode::kEmulationMode: - if(idx < 0 || idx >= EMUL_ACTIONLIST_SIZE) + case Event::Group::Menu: + if(index < 0 || index >= MENU_ACTIONLIST_SIZE) return EmptyString; else - return ourEmulActionList[idx].key; - case EventMode::kMenuMode: - if(idx < 0 || idx >= MENU_ACTIONLIST_SIZE) - return EmptyString; - else - return ourMenuActionList[idx].key; + return ourMenuActionList[index].key; + default: - return EmptyString; + if(index < 0 || index >= EMUL_ACTIONLIST_SIZE) + return EmptyString; + else + return ourEmulActionList[index].key; } } @@ -1579,10 +1727,14 @@ void EventHandler::exitEmulation() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - EventHandler::ActionList EventHandler::ourEmulActionList[EMUL_ACTIONLIST_SIZE] = { { Event::Quit, "Quit", "" }, + { Event::ReloadConsole, "Reload current ROM/load next game", "" }, + { Event::Fry, "Fry cartridge", "" }, { Event::ExitMode, "Exit current Stella menu/mode", "" }, { Event::OptionsMenuMode, "Enter Options menu UI", "" }, { Event::CmdMenuMode, "Toggle Commands menu UI", "" }, { Event::DebuggerMode, "Toggle Debugger mode", "" }, + { Event::TogglePauseMode, "Toggle Pause mode", "" }, + { Event::StartPauseMode, "Start Pause mode", "" }, { Event::ConsoleSelect, "Select", "" }, { Event::ConsoleReset, "Reset", "" }, @@ -1600,9 +1752,11 @@ EventHandler::ActionList EventHandler::ourEmulActionList[EMUL_ACTIONLIST_SIZE] = { Event::ChangeState, "Change state slot", "" }, { Event::ToggleAutoSlot, "Toggle automatic state slot change", "" }, { Event::LoadState, "Load state", "" }, +#ifdef PNG_SUPPORT { Event::TakeSnapshot, "Snapshot", "" }, - { Event::TogglePauseMode, "Toggle pause mode", "" }, - { Event::StartPauseMode, "Start pause mode", "" }, + { Event::ToggleContSnapshots, "Save continuous snapsh. (as defined)", "" }, + { Event::ToggleContSnapshotsFrame,"Save continuous snapsh. (every frame)", "" }, +#endif { Event::JoystickZeroUp, "P0 Joystick Up", "" }, { Event::JoystickZeroDown, "P0 Joystick Down", "" }, @@ -1665,6 +1819,16 @@ EventHandler::ActionList EventHandler::ourEmulActionList[EMUL_ACTIONLIST_SIZE] = { Event::KeyboardOneStar, "P1 Keyboard *", "" }, { Event::KeyboardOne0, "P1 Keyboard 0", "" }, { Event::KeyboardOnePound, "P1 Keyboard #", "" }, + // Video + { Event::VidmodeDecrease, "Previous zoom level", "" }, + { Event::VidmodeIncrease, "Next zoom level", "" }, + { Event::ToggleFullScreen, "Toggle fullscreen", "" }, + { Event::DecreaseOverscan, "Decrease overscan in fullscreen mode", "" }, + { Event::IncreaseOverScan, "Increase overscan in fullscreen mode", "" }, + { Event::DecreaseFormat, "Decrease display format", "" }, + { Event::IncreaseFormat, "Increase display format", "" }, + { Event::TogglePalette, "Switch palette (Standard/Z26/User)", "" }, + // TV effects: { Event::VidmodeStd, "Disable TV effects", "" }, { Event::VidmodeRGB, "Select 'RGB' preset", "" }, @@ -1701,14 +1865,6 @@ EventHandler::ActionList EventHandler::ourEmulActionList[EMUL_ACTIONLIST_SIZE] = { Event::ToggleColorLoss, "Toggle PAL color-loss effect", "" }, { Event::ToggleJitter, "Toggle TV 'Jitter' effect", "" }, // Other keys: - { Event::VidmodeDecrease, "Previous zoom level", "" }, - { Event::VidmodeIncrease, "Next zoom level", "" }, - { Event::ToggleFullScreen, "Toggle fullscreen", "" }, - { Event::DecreaseOverscan, "Decrease overscan in fullscreen mode", "" }, - { Event::IncreaseOverScan, "Increase overscan in fullscreen mode", "" }, - { Event::DecreaseFormat, "Decrease display format", "" }, - { Event::IncreaseFormat, "Increase display format", "" }, - { Event::TogglePalette, "Switch palette (Standard/Z26/User)", "" }, { Event::SoundToggle, "Toggle sound", "" }, { Event::VolumeDecrease, "Decrease volume", "" }, { Event::VolumeIncrease, "Increase volume", "" }, @@ -1716,25 +1872,19 @@ EventHandler::ActionList EventHandler::ourEmulActionList[EMUL_ACTIONLIST_SIZE] = { Event::HandleMouseControl, "Switch mouse emulation modes", "" }, { Event::ToggleGrabMouse, "Toggle grab mouse", "" }, { Event::ToggleSAPortOrder, "Swap Stelladaptor port ordering", "" }, - { Event::ReloadConsole, "Reload current ROM/load next game", "" }, - { Event::Fry, "Fry cartridge", "" }, -#ifdef PNG_SUPPORT - { Event::ToggleContSnapshots, "Save cont. PNG snapsh. (as defined)", "" }, - { Event::ToggleContSnapshotsFrame,"Save cont. PNG snapsh. (every frame)", "" }, -#endif + { Event::SaveAllStates, "Save all TM states of current game", "" }, + { Event::LoadAllStates, "Load saved TM states for current game", "" }, { Event::ToggleTimeMachine, "Toggle 'Time Machine' mode", "" }, { Event::TimeMachineMode, "Toggle 'Time Machine' UI", "" }, - { Event::RewindPause, "Rewind one state & enter pause mode", "" }, + { Event::RewindPause, "Rewind one state & enter Pause mode", "" }, { Event::Rewind1Menu, "Rewind one state & enter TM UI", "" }, { Event::Rewind10Menu, "Rewind 10 states & enter TM UI", "" }, { Event::RewindAllMenu, "Rewind all states & enter TM UI", "" }, - { Event::UnwindPause, "Unwind one state & enter pause mode", "" }, + { Event::UnwindPause, "Unwind one state & enter Pause mode", "" }, { Event::Unwind1Menu, "Unwind one state & enter TM UI", "" }, { Event::Unwind10Menu, "Unwind 10 states & enter TM UI", "" }, { Event::UnwindAllMenu, "Unwind all states & enter TM UI", "" }, - { Event::SaveAllStates, "Save all TM states of current game", "" }, - { Event::LoadAllStates, "Load saved TM states for current game", "" }, { Event::Combo1, "Combo 1", "" }, { Event::Combo2, "Combo 2", "" }, @@ -1779,3 +1929,94 @@ EventHandler::ActionList EventHandler::ourMenuActionList[MENU_ACTIONLIST_SIZE] = { Event::ToggleFullScreen, "Toggle fullscreen", "" }, { Event::Quit, "Quit", "" } }; + +// Event groups +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const EventHandler::EventList EventHandler::MiscEvents = { + Event::Quit, Event::ReloadConsole, Event::Fry, Event::StartPauseMode, + Event::TogglePauseMode, Event::OptionsMenuMode, Event::CmdMenuMode, Event::DebuggerMode, Event::ExitMode, + Event::TakeSnapshot, Event::ToggleContSnapshots, Event::ToggleContSnapshotsFrame, + // Event::MouseAxisXValue, Event::MouseAxisYValue, + // Event::MouseButtonLeftValue, Event::MouseButtonRightValue, + Event::HandleMouseControl, Event::ToggleGrabMouse, + Event::ToggleSAPortOrder, +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const EventHandler::EventList EventHandler::AudioVideoEvents = { + Event::VolumeDecrease, Event::VolumeIncrease, Event::SoundToggle, + Event::VidmodeDecrease, Event::VidmodeIncrease, + Event::ToggleFullScreen, + Event::VidmodeStd, Event::VidmodeRGB, Event::VidmodeSVideo, Event::VidModeComposite, Event::VidModeBad, Event::VidModeCustom, + Event::PreviousAttribute, Event::NextAttribute, Event::DecreaseAttribute, Event::IncreaseAttribute, + Event::ScanlinesDecrease, Event::ScanlinesIncrease, + Event::DecreasePhosphor, Event::IncreasePhosphor, Event::TogglePhosphor, + Event::DecreaseFormat, Event::IncreaseFormat, + Event::DecreaseOverscan, Event::IncreaseOverScan, + Event::TogglePalette, +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const EventHandler::EventList EventHandler::StateEvents = { + Event::ChangeState, Event::LoadState, Event::SaveState, Event::TimeMachineMode, + Event::RewindPause, Event::UnwindPause, Event::ToggleTimeMachine, + Event::Rewind1Menu, Event::Rewind10Menu, Event::RewindAllMenu, + Event::Unwind1Menu, Event::Unwind10Menu, Event::UnwindAllMenu, + Event::SaveAllStates, Event::LoadAllStates, Event::ToggleAutoSlot, +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const EventHandler::EventList EventHandler::ConsoleEvents = { + Event::ConsoleOn, Event::ConsoleOff, Event::ConsoleColor, Event::ConsoleBlackWhite, + Event::ConsoleLeftDiffA, Event::ConsoleLeftDiffB, + Event::ConsoleRightDiffA, Event::ConsoleRightDiffB, + Event::ConsoleSelect, Event::ConsoleReset, + Event::ConsoleLeftDiffToggle, Event::ConsoleRightDiffToggle, Event::ConsoleColorToggle, + Event::Console7800Pause, +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const EventHandler::EventList EventHandler::JoystickEvents = { + Event::JoystickZeroUp, Event::JoystickZeroDown, Event::JoystickZeroLeft, Event::JoystickZeroRight, + Event::JoystickZeroFire, Event::JoystickZeroFire5, Event::JoystickZeroFire9, + Event::JoystickOneUp, Event::JoystickOneDown, Event::JoystickOneLeft, Event::JoystickOneRight, + Event::JoystickOneFire, Event::JoystickOneFire5, Event::JoystickOneFire9, +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const EventHandler::EventList EventHandler::PaddlesEvents = { + Event::PaddleZeroDecrease, Event::PaddleZeroIncrease, Event::PaddleZeroAnalog, Event::PaddleZeroFire, + Event::PaddleOneDecrease, Event::PaddleOneIncrease, Event::PaddleOneAnalog, Event::PaddleOneFire, + Event::PaddleTwoDecrease, Event::PaddleTwoIncrease, Event::PaddleTwoAnalog, Event::PaddleTwoFire, + Event::PaddleThreeDecrease, Event::PaddleThreeIncrease, Event::PaddleThreeAnalog, Event::PaddleThreeFire, +}; + +const EventHandler::EventList EventHandler::KeyboardEvents = { + Event::KeyboardZero1, Event::KeyboardZero2, Event::KeyboardZero3, + Event::KeyboardZero4, Event::KeyboardZero5, Event::KeyboardZero6, + Event::KeyboardZero7, Event::KeyboardZero8, Event::KeyboardZero9, + Event::KeyboardZeroStar, Event::KeyboardZero0, Event::KeyboardZeroPound, + + Event::KeyboardOne1, Event::KeyboardOne2, Event::KeyboardOne3, + Event::KeyboardOne4, Event::KeyboardOne5, Event::KeyboardOne6, + Event::KeyboardOne7, Event::KeyboardOne8, Event::KeyboardOne9, + Event::KeyboardOneStar, Event::KeyboardOne0, Event::KeyboardOnePound, +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const EventHandler::EventList EventHandler::DebugEvents = { + Event::ToggleFrameStats, + Event::ToggleP0Collision, Event::ToggleP0Bit, Event::ToggleP1Collision, Event::ToggleP1Bit, + Event::ToggleM0Collision, Event::ToggleM0Bit, Event::ToggleM1Collision, Event::ToggleM1Bit, + Event::ToggleBLCollision, Event::ToggleBLBit, Event::TogglePFCollision, Event::TogglePFBit, + Event::ToggleCollisions, Event::ToggleBits, Event::ToggleFixedColors, + Event::ToggleColorLoss, + Event::ToggleJitter, +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const EventHandler::EventList EventHandler::ComboEvents = { + Event::Combo1, Event::Combo2, Event::Combo3, Event::Combo4, Event::Combo5, Event::Combo6, Event::Combo7, Event::Combo8, + Event::Combo9, Event::Combo10, Event::Combo11, Event::Combo12, Event::Combo13, Event::Combo14, Event::Combo15, Event::Combo16, +}; + diff --git a/src/emucore/EventHandler.hxx b/src/emucore/EventHandler.hxx index 33fa0b03c..200222fb4 100644 --- a/src/emucore/EventHandler.hxx +++ b/src/emucore/EventHandler.hxx @@ -151,7 +151,7 @@ class EventHandler bool frying() const { return myFryingFlag; } - StringList getActionList(EventMode mode) const; + StringList getActionList(Event::Group group) const; VariantList getComboList(EventMode mode) const; /** Used to access the list of events assigned to a specific combo event. */ @@ -177,9 +177,9 @@ class EventHandler return myPKeyHandler->getMappingDesc(event, mode); } - Event::Type eventAtIndex(int idx, EventMode mode) const; - string actionAtIndex(int idx, EventMode mode) const; - string keyAtIndex(int idx, EventMode mode) const; + Event::Type eventAtIndex(int idx, Event::Group group) const; + string actionAtIndex(int idx, Event::Group group) const; + string keyAtIndex(int idx, Event::Group group) const; /** Bind a key to an event/action and regenerate the mapping array(s). @@ -400,6 +400,18 @@ class EventHandler MENU_ACTIONLIST_SIZE = 18 ; + using EventList = std::vector; + // Define event groups + static const EventList MiscEvents; + static const EventList StateEvents; + static const EventList AudioVideoEvents; + static const EventList ConsoleEvents; + static const EventList JoystickEvents; + static const EventList PaddlesEvents; + static const EventList KeyboardEvents; + static const EventList DebugEvents; + static const EventList ComboEvents; + /** The following methods take care of assigning action mappings. */ @@ -408,6 +420,12 @@ class EventHandler void setDefaultJoymap(Event::Type, EventMode mode); void saveComboMapping(); + StringList getActionList(EventMode mode) const; + StringList getActionList(const EventList& events, EventMode mode = EventMode::kEmulationMode) const; + // returns the action array index of the index in the provided group + int getEmulActionListIndex(int idx, const EventList& events) const; + int getActionListIndex(int idx, Event::Group group) const; + private: // Structure used for action menu items struct ActionList { diff --git a/src/gui/EventMappingWidget.cxx b/src/gui/EventMappingWidget.cxx index 603eadcd0..2968528dc 100644 --- a/src/gui/EventMappingWidget.cxx +++ b/src/gui/EventMappingWidget.cxx @@ -21,6 +21,7 @@ #include "OSystem.hxx" #include "GuiObject.hxx" +#include "PopUpWidget.hxx" #include "FrameBuffer.hxx" #include "EventHandler.hxx" #include "Event.hxx" @@ -36,11 +37,13 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font, int x, int y, int w, int h, - const StringList& actions, EventMode mode) + EventMode mode) : Widget(boss, font, x, y, w, h), - CommandSender(boss), + CommandSender(boss), + myFilterPopup(nullptr), myComboDialog(nullptr), myEventMode(mode), + myEventGroup(Event::Group::Emulation), myActionSelected(-1), myRemapStatus(false), myLastStick(0), @@ -59,12 +62,37 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font, const int VBORDER = 8; const int ACTION_LINES = 2; int xpos = HBORDER, ypos = VBORDER; + const int listWidth = _w - buttonWidth - HBORDER * 2 - 8; + int listHeight = _h - (2 + ACTION_LINES) * lineHeight - VBORDER + 2; - myActionsList = new StringListWidget(boss, font, xpos, ypos, - _w - buttonWidth - HBORDER * 2 - 8, _h - (2 + ACTION_LINES) * lineHeight - VBORDER); + if(mode == EventMode::kEmulationMode) + { + VariantList items; + + items.clear(); + VarList::push_back(items, "All", Event::Group::Emulation); + VarList::push_back(items, "Miscellaneous", Event::Group::Misc); + VarList::push_back(items, "Video & Audio", Event::Group::AudioVideo); + VarList::push_back(items, "States", Event::Group::States); + VarList::push_back(items, "Console", Event::Group::Console); + VarList::push_back(items, "Joystick", Event::Group::Joystick); + VarList::push_back(items, "Paddles", Event::Group::Paddles); + VarList::push_back(items, "Keyboard", Event::Group::Keyboard); + VarList::push_back(items, "Combo", Event::Group::Combo); + VarList::push_back(items, "Debug", Event::Group::Debug); + + myFilterPopup = new PopUpWidget(boss, font, xpos, ypos, + listWidth - font.getStringWidth("Events ") - 23, lineHeight, + items, "Events ", 0, kFilterCmd); + myFilterPopup->setTarget(this); + addFocusWidget(myFilterPopup); + ypos += lineHeight + 8; + listHeight -= lineHeight + 8; + } + + myActionsList = new StringListWidget(boss, font, xpos, ypos, listWidth, listHeight); myActionsList->setTarget(this); myActionsList->setEditable(false); - myActionsList->setList(actions); addFocusWidget(myActionsList); // Add remap, erase, cancel and default buttons @@ -113,13 +141,15 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font, myComboButton = nullptr; // Show message for currently selected event - xpos = HBORDER; ypos = VBORDER + myActionsList->getHeight() + 8; + xpos = HBORDER; + ypos = myActionsList->getBottom() + 8; StaticTextWidget* t; t = new StaticTextWidget(boss, font, xpos, ypos+2, font.getStringWidth("Action"), fontHeight, "Action", TextAlign::Left); myKeyMapping = new EditTextWidget(boss, font, xpos + t->getWidth() + 8, ypos, - _w - xpos - t->getWidth() - 8 - HBORDER, lineHeight * ACTION_LINES, ""); + _w - xpos - t->getWidth() - 8 - HBORDER, + lineHeight + font.getFontHeight() * (ACTION_LINES - 1), ""); myKeyMapping->setEditable(false, true); myKeyMapping->clearFlags(Widget::FLAG_RETAIN_FOCUS); } @@ -129,17 +159,18 @@ void EventMappingWidget::loadConfig() { if(myFirstTime) { - myActionsList->setSelected(0); + if(myFilterPopup) + myFilterPopup->setSelectedIndex(0); + myFirstTime = false; } - else - // controller IDs may have changed in between - drawKeyMapping(); // Make sure remapping is turned off, just in case the user didn't properly // exit last time if(myRemapStatus) stopRemapping(); + + updateActions(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -147,6 +178,20 @@ void EventMappingWidget::saveConfig() { } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void EventMappingWidget::updateActions() +{ + if(myFilterPopup) + myEventGroup = Event::Group(myFilterPopup->getSelectedTag().toInt()); + else + myEventGroup = Event::Group::Menu; + StringList actions = instance().eventHandler().getActionList(myEventGroup); + + myActionsList->setList(actions); + myActionSelected = myActionsList->getSelected(); + drawKeyMapping(); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void EventMappingWidget::setDefaults() { @@ -180,7 +225,7 @@ void EventMappingWidget::startRemapping() // And show a message indicating which key is being remapped ostringstream buf; buf << "Select action for '" - << instance().eventHandler().actionAtIndex(myActionSelected, myEventMode) + << instance().eventHandler().actionAtIndex(myActionSelected, myEventGroup) << "' event"; myKeyMapping->setTextColor(kTextColorEm); myKeyMapping->setText(buf.str()); @@ -197,7 +242,7 @@ void EventMappingWidget::eraseRemapping() return; Event::Type event = - instance().eventHandler().eventAtIndex(myActionSelected, myEventMode); + instance().eventHandler().eventAtIndex(myActionSelected, myEventGroup); instance().eventHandler().eraseMapping(event, myEventMode); drawKeyMapping(); @@ -210,7 +255,7 @@ void EventMappingWidget::resetRemapping() return; Event::Type event = - instance().eventHandler().eventAtIndex(myActionSelected, myEventMode); + instance().eventHandler().eventAtIndex(myActionSelected, myEventGroup); instance().eventHandler().setDefaultMapping(event, myEventMode); drawKeyMapping(); @@ -246,7 +291,7 @@ void EventMappingWidget::drawKeyMapping() if(myActionSelected >= 0) { myKeyMapping->setTextColor(kTextColor); - myKeyMapping->setText(instance().eventHandler().keyAtIndex(myActionSelected, myEventMode)); + myKeyMapping->setText(instance().eventHandler().keyAtIndex(myActionSelected, myEventGroup)); } } @@ -261,7 +306,7 @@ void EventMappingWidget::enableButtons(bool state) if(myComboButton) { Event::Type e = - instance().eventHandler().eventAtIndex(myActionSelected, myEventMode); + instance().eventHandler().eventAtIndex(myActionSelected, myEventGroup); myComboButton->setEnabled(state && e >= Event::Combo1 && e <= Event::Combo16); } @@ -292,7 +337,7 @@ bool EventMappingWidget::handleKeyUp(StellaKey key, StellaMod mod) && (mod & (KBDM_CTRL | KBDM_SHIFT | KBDM_ALT | KBDM_GUI)) == 0) { Event::Type event = - instance().eventHandler().eventAtIndex(myActionSelected, myEventMode); + instance().eventHandler().eventAtIndex(myActionSelected, myEventGroup); // if not pressed alone, map left and right modifier keys if(myLastKey < KBDK_LCTRL || myLastKey > KBDK_RGUI) @@ -332,7 +377,7 @@ void EventMappingWidget::handleJoyUp(int stick, int button) if (myLastStick == stick && myLastButton == button) { EventHandler& eh = instance().eventHandler(); - Event::Type event = eh.eventAtIndex(myActionSelected, myEventMode); + Event::Type event = eh.eventAtIndex(myActionSelected, myEventGroup); // map either button/hat, solo button or button/axis combinations if(myLastHat != -1) @@ -368,7 +413,7 @@ void EventMappingWidget::handleJoyAxis(int stick, JoyAxis axis, JoyDir adir, int else if(myLastStick == stick && axis == myLastAxis && adir == JoyDir::NONE) { EventHandler& eh = instance().eventHandler(); - Event::Type event = eh.eventAtIndex(myActionSelected, myEventMode); + Event::Type event = eh.eventAtIndex(myActionSelected, myEventGroup); if (eh.addJoyMapping(event, myEventMode, stick, myLastButton, axis, myLastDir)) stopRemapping(); @@ -399,7 +444,7 @@ bool EventMappingWidget::handleJoyHat(int stick, int hat, JoyHatDir hdir, int bu else if(myLastStick == stick && hat == myLastHat && hdir == JoyHatDir::CENTER) { EventHandler& eh = instance().eventHandler(); - Event::Type event = eh.eventAtIndex(myActionSelected, myEventMode); + Event::Type event = eh.eventAtIndex(myActionSelected, myEventGroup); if (eh.addJoyHatMapping(event, myEventMode, stick, myLastButton, hat, myLastHatDir)) { @@ -418,6 +463,10 @@ void EventMappingWidget::handleCommand(CommandSender* sender, int cmd, { switch(cmd) { + case kFilterCmd: + updateActions(); + break; + case ListWidget::kSelectionChangedCmd: if(myActionsList->getSelected() >= 0) { @@ -454,8 +503,8 @@ void EventMappingWidget::handleCommand(CommandSender* sender, int cmd, case kComboCmd: if(myComboDialog) myComboDialog->show( - instance().eventHandler().eventAtIndex(myActionSelected, myEventMode), - instance().eventHandler().actionAtIndex(myActionSelected, myEventMode)); + instance().eventHandler().eventAtIndex(myActionSelected, myEventGroup), + instance().eventHandler().actionAtIndex(myActionSelected, myEventGroup)); break; } } diff --git a/src/gui/EventMappingWidget.hxx b/src/gui/EventMappingWidget.hxx index 55f1c7620..c199cbd53 100644 --- a/src/gui/EventMappingWidget.hxx +++ b/src/gui/EventMappingWidget.hxx @@ -40,7 +40,7 @@ class EventMappingWidget : public Widget, public CommandSender public: EventMappingWidget(GuiObject* boss, const GUI::Font& font, int x, int y, int w, int h, - const StringList& actions, EventMode mode); + EventMode mode); virtual ~EventMappingWidget() = default; bool remapMode() { return myRemapStatus; } @@ -49,6 +49,7 @@ class EventMappingWidget : public Widget, public CommandSender private: enum { + kFilterCmd = 'filt', kStartMapCmd = 'map ', kStopMapCmd = 'smap', kEraseCmd = 'eras', @@ -68,6 +69,7 @@ class EventMappingWidget : public Widget, public CommandSender void handleCommand(CommandSender* sender, int cmd, int data, int id) override; + void updateActions(); void startRemapping(); void eraseRemapping(); void resetRemapping(); @@ -84,6 +86,7 @@ class EventMappingWidget : public Widget, public CommandSender ButtonWidget* myEraseButton; ButtonWidget* myResetButton; ButtonWidget* myComboButton; + PopUpWidget* myFilterPopup; StringListWidget* myActionsList; EditTextWidget* myKeyMapping; @@ -93,6 +96,9 @@ class EventMappingWidget : public Widget, public CommandSender // we need to specify exactly which group of events we are remapping EventMode myEventMode; + // Since we can filter events, the event mode is not specific enough + Event::Group myEventGroup; + // Indicates the event that is currently selected int myActionSelected; diff --git a/src/gui/InputDialog.cxx b/src/gui/InputDialog.cxx index 4eaa25a77..476633e98 100644 --- a/src/gui/InputDialog.cxx +++ b/src/gui/InputDialog.cxx @@ -48,7 +48,6 @@ InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent, buttonHeight = font.getLineHeight() + 4; const int vBorder = 4; int xpos, ypos, tabID; - StringList actions; // Set real dimensions setSize(51 * fontWidth + 10, 17 * (lineHeight + 4) + 16 + _th, max_w, max_h); @@ -60,21 +59,19 @@ InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent, // 1) Event mapper for emulation actions tabID = myTab->addTab(" Emulation Events ", TabWidget::AUTO_WIDTH); - actions = instance().eventHandler().getActionList(EventMode::kEmulationMode); myEmulEventMapper = new EventMappingWidget(myTab, font, 2, 2, myTab->getWidth(), myTab->getHeight() - 4, - actions, EventMode::kEmulationMode); + EventMode::kEmulationMode); myTab->setParentWidget(tabID, myEmulEventMapper); addToFocusList(myEmulEventMapper->getFocusList(), myTab, tabID); // 2) Event mapper for UI actions tabID = myTab->addTab(" UI Events ", TabWidget::AUTO_WIDTH); - actions = instance().eventHandler().getActionList(EventMode::kMenuMode); myMenuEventMapper = new EventMappingWidget(myTab, font, 2, 2, myTab->getWidth(), myTab->getHeight() - 4, - actions, EventMode::kMenuMode); + EventMode::kMenuMode); myTab->setParentWidget(tabID, myMenuEventMapper); addToFocusList(myMenuEventMapper->getFocusList(), myTab, tabID); @@ -642,3 +639,4 @@ void InputDialog::UpdateDejitter() myDejitterLabel->setLabel(label.str()); } + diff --git a/src/gui/ListWidget.cxx b/src/gui/ListWidget.cxx index 2ee285d98..067864a7a 100644 --- a/src/gui/ListWidget.cxx +++ b/src/gui/ListWidget.cxx @@ -164,8 +164,13 @@ void ListWidget::recalc() { int size = int(_list.size()); - if (_currentPos >= size) - _currentPos = size - 1; + if(_currentPos >= size) + { + if(size <= _rows) + _currentPos = 0; + else + _currentPos = size - _rows; + } if (_currentPos < 0) _currentPos = 0; @@ -176,6 +181,8 @@ void ListWidget::recalc() _scrollBar->_numEntries = int(_list.size()); _scrollBar->_entriesPerPage = _rows; + // disable scrollbar if no longer necessary + scrollBarRecalc(); // Reset to normal data entry abortEditMode();