mirror of https://github.com/stella-emu/stella.git
added undo/redo to EditableWidget
This commit is contained in:
parent
7ef46b366d
commit
b2fa192529
|
@ -27,6 +27,15 @@ EventHandlerSDL2::EventHandlerSDL2(OSystem& osystem)
|
|||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
#ifdef GUI_SUPPORT
|
||||
{
|
||||
ostringstream buf;
|
||||
myQwertz = int('y') == int(SDL_GetKeyFromScancode(SDL_Scancode(KBDK_Z)));
|
||||
buf << "Keyboard: " << (myQwertz ? "QWERTZ" : "QWERTY");
|
||||
Logger::debug(buf.str());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JOYSTICK_SUPPORT
|
||||
if(SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
|
||||
{
|
||||
|
|
|
@ -338,6 +338,11 @@ class EventHandler
|
|||
virtual void enableTextEvents(bool enable) = 0;
|
||||
|
||||
#ifdef GUI_SUPPORT
|
||||
/**
|
||||
Check for QWERTZ keyboard layout
|
||||
*/
|
||||
bool isQwertz() { return myQwertz; }
|
||||
|
||||
/**
|
||||
Clipboard methods.
|
||||
*/
|
||||
|
@ -359,6 +364,11 @@ class EventHandler
|
|||
// Global OSystem object
|
||||
OSystem& myOSystem;
|
||||
|
||||
#ifdef GUI_SUPPORT
|
||||
// Keyboard layout
|
||||
bool myQwertz{false};
|
||||
#endif
|
||||
|
||||
/**
|
||||
Methods which are called by derived classes to handle specific types
|
||||
of input.
|
||||
|
|
|
@ -47,6 +47,9 @@ void EditableWidget::setText(const string& str, bool)
|
|||
if(_filter(tolower(c)))
|
||||
_editString.push_back(c);
|
||||
|
||||
clearEdits();
|
||||
doEdit();
|
||||
|
||||
_caretPos = int(_editString.size());
|
||||
_selectSize = 0;
|
||||
|
||||
|
@ -78,12 +81,64 @@ void EditableWidget::lostFocusWidget()
|
|||
_selectSize = 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void EditableWidget::clearEdits()
|
||||
{
|
||||
_editBuffer.clear();
|
||||
_redoCount = 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void EditableWidget::doEdit()
|
||||
{
|
||||
constexpr size_t UNDO_SIZE = 100;
|
||||
|
||||
// clear redos
|
||||
for(; _redoCount; _redoCount--)
|
||||
_editBuffer.pop_back();
|
||||
|
||||
if(_editBuffer.size() == UNDO_SIZE)
|
||||
_editBuffer.pop_front();
|
||||
_editBuffer.push_back(_editString);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool EditableWidget::undoEdit()
|
||||
{
|
||||
if(_editBuffer.size() - _redoCount - 1)
|
||||
{
|
||||
_redoCount++;
|
||||
_editString = _editBuffer[_editBuffer.size() - _redoCount - 1];
|
||||
_caretPos = int(_editString.size()); // TODO: put at last difference
|
||||
_selectSize = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool EditableWidget::redoEdit()
|
||||
{
|
||||
if(_redoCount)
|
||||
{
|
||||
_redoCount--;
|
||||
_editString = _editBuffer[_editBuffer.size() - _redoCount - 1];
|
||||
_caretPos = int(_editString.size()); // TODO: put at last difference
|
||||
_selectSize = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool EditableWidget::tryInsertChar(char c, int pos)
|
||||
{
|
||||
if(_filter(tolower(c)))
|
||||
{
|
||||
_editString.insert(pos, 1, c);
|
||||
doEdit();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -187,8 +242,12 @@ bool EditableWidget::handleControlKeys(StellaKey key, StellaMod mod)
|
|||
sendCommand(EditableWidget::kChangedCmd, key, _id);
|
||||
break;
|
||||
|
||||
case KBDK_Y:
|
||||
case KBDK_Z:
|
||||
// TODO: undo
|
||||
if(key == KBDK_Y != instance().eventHandler().isQwertz())
|
||||
dirty = redoEdit();
|
||||
else
|
||||
dirty = undoEdit();
|
||||
break;
|
||||
|
||||
case KBDK_LEFT:
|
||||
|
@ -469,7 +528,7 @@ int EditableWidget::scrollOffset()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool EditableWidget::killChar(int direction)
|
||||
bool EditableWidget::killChar(int direction, bool addEdit)
|
||||
{
|
||||
bool handled = false;
|
||||
|
||||
|
@ -480,12 +539,20 @@ bool EditableWidget::killChar(int direction)
|
|||
_caretPos--;
|
||||
_editString.erase(_caretPos, 1);
|
||||
handled = true;
|
||||
if(_selectSize < 0)
|
||||
_selectSize++;
|
||||
if(addEdit)
|
||||
doEdit();
|
||||
}
|
||||
}
|
||||
else if(direction == 1) // Delete next character (delete)
|
||||
{
|
||||
_editString.erase(_caretPos, 1);
|
||||
handled = true;
|
||||
if(_selectSize > 0)
|
||||
_selectSize--;
|
||||
if(addEdit)
|
||||
doEdit();
|
||||
}
|
||||
|
||||
return handled;
|
||||
|
@ -502,12 +569,13 @@ bool EditableWidget::killLine(int direction)
|
|||
if(count > 0)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
killChar(-1);
|
||||
killChar(-1, false);
|
||||
|
||||
handled = true;
|
||||
// remove selection for removed text
|
||||
if(_selectSize < 0)
|
||||
_selectSize = 0;
|
||||
doEdit();
|
||||
}
|
||||
}
|
||||
else if(direction == 1) // erase from current position to end of line
|
||||
|
@ -516,12 +584,13 @@ bool EditableWidget::killLine(int direction)
|
|||
if(count > 0)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
killChar(+1);
|
||||
killChar(+1, false);
|
||||
|
||||
handled = true;
|
||||
// remove selection for removed text
|
||||
if(_selectSize > 0)
|
||||
_selectSize = 0;
|
||||
doEdit();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -551,12 +620,13 @@ bool EditableWidget::killLastWord()
|
|||
if(count > 0)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
killChar(-1);
|
||||
killChar(-1, false);
|
||||
|
||||
handled = true;
|
||||
// remove selection for removed word
|
||||
if(_selectSize < 0)
|
||||
_selectSize = std::min(_selectSize + count, 0);
|
||||
doEdit();
|
||||
}
|
||||
|
||||
return handled;
|
||||
|
@ -649,7 +719,7 @@ int EditableWidget::selectEndPos()
|
|||
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool EditableWidget::killSelectedText()
|
||||
bool EditableWidget::killSelectedText(bool addEdit)
|
||||
{
|
||||
if(_selectSize)
|
||||
{
|
||||
|
@ -660,6 +730,8 @@ bool EditableWidget::killSelectedText()
|
|||
}
|
||||
_editString.erase(_caretPos, _selectSize);
|
||||
_selectSize = 0;
|
||||
if(addEdit)
|
||||
doEdit();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -703,7 +775,7 @@ bool EditableWidget::pasteSelectedText()
|
|||
// retrieve the pasted text
|
||||
instance().eventHandler().pasteText(pasted);
|
||||
// remove the currently selected text
|
||||
killSelectedText();
|
||||
killSelectedText(false);
|
||||
// insert filtered paste text instead
|
||||
ostringstream buf;
|
||||
bool lastOk = true; // only one filler char per invalid character (block)
|
||||
|
@ -725,5 +797,10 @@ bool EditableWidget::pasteSelectedText()
|
|||
// position cursor at the end of pasted text
|
||||
_caretPos += int(buf.str().length());
|
||||
|
||||
return selected || !pasted.empty();
|
||||
if(selected || !pasted.empty())
|
||||
{
|
||||
doEdit();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#define EDITABLE_WIDGET_HXX
|
||||
|
||||
#include <functional>
|
||||
#include <deque>
|
||||
|
||||
#include "Widget.hxx"
|
||||
#include "Rect.hxx"
|
||||
|
@ -89,18 +90,23 @@ class EditableWidget : public Widget, public CommandSender
|
|||
bool handleControlKeys(StellaKey key, StellaMod mod);
|
||||
bool handleShiftKeys(StellaKey key);
|
||||
bool handleNormalKeys(StellaKey key);
|
||||
bool killChar(int direction);
|
||||
bool killChar(int direction, bool addEdit = true);
|
||||
bool killLine(int direction);
|
||||
bool killLastWord();
|
||||
bool moveWord(int direction, bool select);
|
||||
|
||||
bool killSelectedText();
|
||||
bool killSelectedText(bool addEdit = true);
|
||||
int selectStartPos();
|
||||
int selectEndPos();
|
||||
// Clipboard
|
||||
bool cutSelectedText();
|
||||
bool copySelectedText();
|
||||
bool pasteSelectedText();
|
||||
// Undo
|
||||
void clearEdits();
|
||||
void doEdit();
|
||||
bool undoEdit();
|
||||
bool redoEdit();
|
||||
|
||||
// Use the current TextFilter to insert a character into the
|
||||
// internal buffer
|
||||
|
@ -109,6 +115,9 @@ class EditableWidget : public Widget, public CommandSender
|
|||
private:
|
||||
bool _editable{true};
|
||||
string _editString;
|
||||
|
||||
std::deque<string> _editBuffer;
|
||||
int _redoCount{0};
|
||||
int _caretPos{0};
|
||||
// Size of current selected text
|
||||
// 0 = no selection
|
||||
|
|
Loading…
Reference in New Issue