refactored EditableWidget to use events instead of scancodes (TODO: text, MacOS keys)

This commit is contained in:
thrust26 2020-11-06 18:16:21 +01:00
parent d0d55a8fec
commit 9bb30a9bc2
8 changed files with 201 additions and 200 deletions

View File

@ -29,6 +29,8 @@
#if defined(BSPF_MACOS) || defined(MACOS_KEYS)
static constexpr int MOD3 = KBDM_GUI;
static constexpr int CMD = KBDM_GUI;
static constexpr int OPTION = KBDM_ALT;
#else
static constexpr int MOD3 = KBDM_ALT;
#endif
@ -60,6 +62,7 @@ PhysicalKeyboardHandler::PhysicalKeyboardHandler(OSystem& system, EventHandler&
setDefaultMapping(Event::NoType, EventMode::kEmulationMode, updateDefaults);
setDefaultMapping(Event::NoType, EventMode::kMenuMode, updateDefaults);
setDefaultMapping(Event::NoType, EventMode::kEditMode, updateDefaults);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -151,6 +154,12 @@ void PhysicalKeyboardHandler::setDefaultMapping(Event::Type event, EventMode mod
setDefaultKey(item, event, EventMode::kMenuMode, updateDefaults);
break;
case EventMode::kEditMode:
// Edit mode events are always set because they are not saved
for(const auto& item : FixedEditMapping)
setDefaultKey(item, event, EventMode::kEditMode);
break;
default:
break;
}
@ -641,6 +650,73 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultMenuM
#endif
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::FixedEditMapping = {
// TOOD: check MacOS mappings
{Event::MoveLeftChar, KBDK_LEFT},
{Event::MoveRightChar, KBDK_RIGHT},
{Event::SelectLeftChar, KBDK_LEFT, KBDM_SHIFT},
{Event::SelectRightChar, KBDK_RIGHT, KBDM_SHIFT},
#ifdef BSPF_MACOS
{Event::MoveLeftWord, KBDK_LEFT, CMD},
// {Event::MoveRightWord, KBDK_RIGHT, KBDM_CTRL},
{Event::MoveHome, KBDK_LEFT, CMD},
{Event::MoveHome, KBDK_A, KBDM_CTRL},
{Event::MoveEnd, KBDK_RIGHT, CMD},
{Event::MoveEnd, KBDK_E, KBDM_CTRL},
{Event::SelectLeftWord, KBDK_LEFT, KBDM_SHIFT | OPTION},
// {Event::SelectRightWord, KBDK_RIGHT, KBDM_SHIFT | OPTION},
{Event::SelectHome, KBDK_A, KBDM_SHIFT | KBDM_CTRL},
{Event::SelectHome, KBDK_LEFT, KBDM_SHIFT | CMD},
{Event::SelectEnd, KBDK_E, KBDM_SHIFT | KBDM_CTRL},
{Event::SelectEnd, KBDK_RIGHT, KBDM_SHIFT | CMD},
{Event::SelectAll, KBDK_A, CMD},
{Event::Delete, KBDK_DELETE},
{Event::Delete, KBDK_KP_PERIOD}, // ???
// {Event::DeleteChar, }, // ???
{Event::DeleteWord, KBDK_W, OPTION},
{Event::DeleteHome, KBDK_BACKSPACE, CMD},
{Event::DeleteEnd, KBDK_BACKSPACE, KBDM_SHIFT | KBDM_CTRL},
{Event::Backspace, KBDK_BACKSPACE}, // ???
{Event::Undo, KBDK_Z, CMD},
{Event::Redo, KBDK_Y, CMD},
{Event::Redo, KBDK_Z, KBDM_SHIFT | CMD},
{Event::Cut, KBDK_X, CMD},
{Event::Copy, KBDK_C, CMD},
{Event::Paste, KBDK_V, CMD},
#else
{Event::MoveLeftWord, KBDK_LEFT, KBDM_CTRL},
{Event::MoveRightWord, KBDK_RIGHT, KBDM_CTRL},
{Event::MoveHome, KBDK_HOME},
{Event::MoveEnd, KBDK_END},
{Event::SelectLeftWord, KBDK_LEFT, KBDM_SHIFT | KBDM_CTRL},
{Event::SelectRightWord, KBDK_RIGHT, KBDM_SHIFT | KBDM_CTRL},
{Event::SelectHome, KBDK_HOME, KBDM_SHIFT},
{Event::SelectEnd, KBDK_END, KBDM_SHIFT},
{Event::SelectAll, KBDK_A, KBDM_CTRL},
{Event::Delete, KBDK_DELETE},
{Event::Delete, KBDK_KP_PERIOD},
{Event::DeleteChar, KBDK_D, KBDM_CTRL},
{Event::DeleteWord, KBDK_W, KBDM_CTRL},
{Event::DeleteHome, KBDK_U, KBDM_CTRL},
{Event::DeleteEnd, KBDK_K, KBDM_CTRL},
{Event::Backspace, KBDK_BACKSPACE},
{Event::Undo, KBDK_Z, KBDM_CTRL},
{Event::Redo, KBDK_Y, KBDM_CTRL},
{Event::Redo, KBDK_Z, KBDM_SHIFT | KBDM_CTRL},
{Event::Cut, KBDK_X, KBDM_CTRL},
{Event::Cut, KBDK_DELETE, KBDM_SHIFT},
{Event::Cut, KBDK_KP_PERIOD, KBDM_SHIFT},
{Event::Copy, KBDK_C, KBDM_CTRL},
{Event::Copy, KBDK_INSERT, KBDM_CTRL},
{Event::Paste, KBDK_V, KBDM_CTRL},
{Event::Paste, KBDK_INSERT, KBDM_SHIFT},
#endif
{Event::EndEdit, KBDK_RETURN},
{Event::EndEdit, KBDK_KP_ENTER},
{Event::AbortEdit, KBDK_ESCAPE},
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultJoystickMapping = {
{Event::JoystickZeroUp, KBDK_UP},

View File

@ -132,6 +132,7 @@ class PhysicalKeyboardHandler
// Controller menu and common emulation mappings
static EventMappingArray DefaultMenuMapping;
static EventMappingArray FixedEditMapping;
static EventMappingArray DefaultCommonMapping;
// Controller specific mappings
static EventMappingArray DefaultJoystickMapping;

View File

@ -136,6 +136,14 @@ class Event
ToggleCorrectAspectRatio,
MoveLeftChar, MoveRightChar, MoveLeftWord, MoveRightWord,
MoveHome, MoveEnd,
SelectLeftChar, SelectRightChar, SelectLeftWord, SelectRightWord,
SelectHome, SelectEnd, SelectAll,
Delete, DeleteChar, DeleteWord, DeleteHome, DeleteEnd, Backspace,
Cut, Copy, Paste, Undo, Redo,
AbortEdit, EndEdit,
LastType
};

View File

@ -2830,3 +2830,8 @@ const Event::EventSet EventHandler::DebugEvents = {
Event::ToggleColorLoss,
Event::ToggleJitter,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const Event::EventSet EventHandler::EditEvents = {
};

View File

@ -511,6 +511,7 @@ class EventHandler
static const Event::EventSet KeyboardEvents;
static const Event::EventSet ComboEvents;
static const Event::EventSet DebugEvents;
static const Event::EventSet EditEvents;
/**
The following methods take care of assigning action mappings.

View File

@ -79,6 +79,7 @@ static const int NUM_PORTS = 2;
enum class EventMode {
kEmulationMode, // active mapping used for emulation
kMenuMode, // mapping used for dialogs
kEditMode, // mapping used in editable widgets
kJoystickMode, // 4 extra modes for mapping controller keys separately for emulation mode
kPaddlesMode,
kKeypadMode,

View File

@ -89,6 +89,7 @@ bool EditableWidget::tryInsertChar(char c, int pos)
{
if(_filter(tolower(c)))
{
killSelectedText();
_editString.insert(pos, 1, c);
myUndoHandler->doChar(); // aggregate single chars
return true;
@ -105,7 +106,7 @@ bool EditableWidget::handleText(char text)
if(tryInsertChar(text, _caretPos))
{
_caretPos++;
_selectSize = 0;
//_selectSize = 0;
sendCommand(EditableWidget::kChangedCmd, 0, _id);
setDirty();
return true;
@ -119,94 +120,139 @@ bool EditableWidget::handleKeyDown(StellaKey key, StellaMod mod)
if(!_editable)
return true;
// Ignore all alt-mod keys
if(StellaModTest::isAlt(mod))
return true;
// Handle Control and Control-Shift keys
if(StellaModTest::isControl(mod) && handleControlKeys(key, mod))
return true;
// Handle Shift keys
if(StellaModTest::isShift(mod) && handleShiftKeys(key))
return true;
// Handle keys without modifiers
return handleNormalKeys(key);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EditableWidget::handleControlKeys(StellaKey key, StellaMod mod)
{
bool shift = StellaModTest::isShift(mod);
bool handled = true;
Event::Type event = instance().eventHandler().eventForKey(EventMode::kEditMode, key, mod);
switch(key)
switch(event)
{
case KBDK_A:
case Event::MoveLeftChar:
if(_selectSize)
handled = setCaretPos(selectStartPos());
else if(_caretPos > 0)
handled = setCaretPos(_caretPos - 1);
_selectSize = 0;
break;
case Event::MoveRightChar:
if(_selectSize)
handled = setCaretPos(selectEndPos());
else if(_caretPos < int(_editString.size()))
handled = setCaretPos(_caretPos + 1);
_selectSize = 0;
break;
case Event::MoveLeftWord:
handled = moveWord(-1, false);
_selectSize = 0;
break;
case Event::MoveRightWord:
handled = moveWord(+1, false);
_selectSize = 0;
break;
case Event::MoveHome:
handled = setCaretPos(0);
_selectSize = 0;
break;
case Event::MoveEnd:
handled = setCaretPos(int(_editString.size()));
_selectSize = 0;
break;
case Event::SelectLeftChar:
if(_caretPos > 0)
handled = moveCaretPos(-1);
break;
case Event::SelectRightChar:
if(_caretPos < int(_editString.size()))
handled = moveCaretPos(+1);
break;
case Event::SelectLeftWord:
handled = moveWord(-1, true);
break;
case Event::SelectRightWord:
handled = moveWord(+1, true);
break;
case Event::SelectHome:
handled = moveCaretPos(-_caretPos);
break;
case Event::SelectEnd:
handled = moveCaretPos(int(_editString.size()) - _caretPos);
break;
case Event::SelectAll:
if(setCaretPos(int(_editString.size())))
_selectSize = -int(_editString.size());
break;
case KBDK_C:
case KBDK_INSERT:
handled = copySelectedText();
case Event::Delete:
handled = killSelectedText();
if(!handled)
handled = killChar(+1);
if(handled) sendCommand(EditableWidget::kChangedCmd, key, _id);
break;
//case KBDK_E:
// if(shift)
// _selectSize += _caretPos - int(_editString.size());
// else
// _selectSize = 0;
// setCaretPos(int(_editString.size()));
// break;
case KBDK_D:
case Event::DeleteChar:
handled = killChar(+1);
if(handled) sendCommand(EditableWidget::kChangedCmd, key, _id);
break;
case KBDK_K:
handled = killLine(+1);
if(handled) sendCommand(EditableWidget::kChangedCmd, key, _id);
break;
case KBDK_U:
handled = killLine(-1);
if(handled) sendCommand(EditableWidget::kChangedCmd, key, _id);
break;
case KBDK_V:
handled = pasteSelectedText();
if(handled)
sendCommand(EditableWidget::kChangedCmd, key, _id);
break;
case KBDK_W:
case Event::DeleteWord:
handled = killLastWord();
if(handled) sendCommand(EditableWidget::kChangedCmd, key, _id);
break;
case KBDK_X:
case Event::DeleteEnd:
handled = killLine(+1);
if(handled) sendCommand(EditableWidget::kChangedCmd, key, _id);
break;
case Event::DeleteHome:
handled = killLine(-1);
if(handled) sendCommand(EditableWidget::kChangedCmd, key, _id);
break;
case Event::Backspace:
handled = killSelectedText();
if(!handled)
handled = killChar(-1);
if(handled) sendCommand(EditableWidget::kChangedCmd, key, _id);
break;
case Event::Cut:
handled = cutSelectedText();
if(handled)
sendCommand(EditableWidget::kChangedCmd, key, _id);
break;
case KBDK_Y:
case KBDK_Z:
case Event::Copy:
handled = copySelectedText();
break;
case Event::Paste:
handled = pasteSelectedText();
if(handled)
sendCommand(EditableWidget::kChangedCmd, key, _id);
break;
case Event::Undo:
case Event::Redo:
{
string oldString = _editString;
myUndoHandler->endChars(_editString);
// Reverse Y and Z for QWERTZ keyboards
if(key == KBDK_Y != instance().eventHandler().isQwertz())
if(event == Event::Redo != instance().eventHandler().isQwertz())
handled = myUndoHandler->redo(_editString);
else
if(shift)
handled = myUndoHandler->redo(_editString);
else
handled = myUndoHandler->undo(_editString);
handled = myUndoHandler->undo(_editString);
if(handled)
{
@ -219,152 +265,20 @@ bool EditableWidget::handleControlKeys(StellaKey key, StellaMod mod)
break;
}
case KBDK_LEFT:
handled = moveWord(-1, shift);
if(!shift)
_selectSize = 0;
break;
case KBDK_RIGHT:
handled = moveWord(+1, shift);
if(!shift)
_selectSize = 0;
break;
default:
handled = false;
}
if(handled)
{
myUndoHandler->endChars(_editString);
setDirty();
}
return handled;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EditableWidget::handleShiftKeys(StellaKey key)
{
bool handled = true;
switch(key)
{
case KBDK_DELETE:
case KBDK_KP_PERIOD:
handled = cutSelectedText();
if(handled)
sendCommand(EditableWidget::kChangedCmd, key, _id);
break;
case KBDK_INSERT:
handled = pasteSelectedText();
if(handled)
sendCommand(EditableWidget::kChangedCmd, key, _id);
break;
case KBDK_LEFT:
if(_caretPos > 0)
handled = moveCaretPos(-1);
break;
case KBDK_RIGHT:
if(_caretPos < int(_editString.size()))
handled = moveCaretPos(+1);
break;
case KBDK_HOME:
handled = moveCaretPos(-_caretPos);
break;
case KBDK_END:
handled = moveCaretPos(int(_editString.size()) - _caretPos);
break;
default:
handled = false;
}
if(handled)
{
myUndoHandler->endChars(_editString);
setDirty();
}
return handled;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EditableWidget::handleNormalKeys(StellaKey key)
{
bool selectMode = false;
bool handled = true;
switch(key)
{
case KBDK_LSHIFT:
case KBDK_RSHIFT:
case KBDK_LCTRL:
case KBDK_RCTRL:
// stay in select mode
selectMode = _selectSize;
handled = false;
break;
case KBDK_RETURN:
case KBDK_KP_ENTER:
case Event::EndEdit:
// confirm edit and exit editmode
endEditMode();
sendCommand(EditableWidget::kAcceptCmd, 0, _id);
break;
case KBDK_ESCAPE:
case Event::AbortEdit:
abortEditMode();
sendCommand(EditableWidget::kCancelCmd, 0, _id);
break;
case KBDK_BACKSPACE:
handled = killSelectedText();
if(!handled)
handled = killChar(-1);
if(handled) sendCommand(EditableWidget::kChangedCmd, key, _id);
break;
case KBDK_DELETE:
case KBDK_KP_PERIOD:
handled = killSelectedText();
if(!handled)
handled = killChar(+1);
if(handled) sendCommand(EditableWidget::kChangedCmd, key, _id);
break;
case KBDK_LEFT:
if(_selectSize)
handled = setCaretPos(selectStartPos());
else if(_caretPos > 0)
handled = setCaretPos(_caretPos - 1);
break;
case KBDK_RIGHT:
if(_selectSize)
handled = setCaretPos(selectEndPos());
else if(_caretPos < int(_editString.size()))
handled = setCaretPos(_caretPos + 1);
break;
case KBDK_HOME:
handled = setCaretPos(0);
break;
case KBDK_END:
handled = setCaretPos(int(_editString.size()));
break;
default:
killSelectedText();
handled = false;
break;
}
if(handled)
@ -372,8 +286,6 @@ bool EditableWidget::handleNormalKeys(StellaKey key)
myUndoHandler->endChars(_editString);
setDirty();
}
if(!selectMode)
_selectSize = 0;
return handled;
}

View File

@ -87,9 +87,6 @@ class EditableWidget : public Widget, public CommandSender
private:
// Line editing
bool handleControlKeys(StellaKey key, StellaMod mod);
bool handleShiftKeys(StellaKey key);
bool handleNormalKeys(StellaKey key);
bool killChar(int direction, bool addEdit = true);
bool killLine(int direction);
bool killLastWord();