mirror of https://github.com/stella-emu/stella.git
added single char aggregation for undos
fixed potential bug when moving cursor one word left
This commit is contained in:
parent
d7171b5260
commit
6c315c76be
|
@ -90,7 +90,7 @@ bool EditableWidget::tryInsertChar(char c, int pos)
|
||||||
if(_filter(tolower(c)))
|
if(_filter(tolower(c)))
|
||||||
{
|
{
|
||||||
_editString.insert(pos, 1, c);
|
_editString.insert(pos, 1, c);
|
||||||
myUndoHandler->doo(_editString);
|
myUndoHandler->doChar(); // aggregate single chars
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -140,7 +140,6 @@ bool EditableWidget::handleControlKeys(StellaKey key, StellaMod mod)
|
||||||
{
|
{
|
||||||
bool shift = StellaModTest::isShift(mod);
|
bool shift = StellaModTest::isShift(mod);
|
||||||
bool handled = true;
|
bool handled = true;
|
||||||
bool dirty = true;
|
|
||||||
|
|
||||||
switch(key)
|
switch(key)
|
||||||
{
|
{
|
||||||
|
@ -154,13 +153,13 @@ bool EditableWidget::handleControlKeys(StellaKey key, StellaMod mod)
|
||||||
handled = copySelectedText();
|
handled = copySelectedText();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KBDK_E:
|
//case KBDK_E:
|
||||||
if(shift)
|
// if(shift)
|
||||||
_selectSize += _caretPos - int(_editString.size());
|
// _selectSize += _caretPos - int(_editString.size());
|
||||||
else
|
// else
|
||||||
_selectSize = 0;
|
// _selectSize = 0;
|
||||||
setCaretPos(int(_editString.size()));
|
// setCaretPos(int(_editString.size()));
|
||||||
break;
|
// break;
|
||||||
|
|
||||||
case KBDK_D:
|
case KBDK_D:
|
||||||
handled = killChar(+1);
|
handled = killChar(+1);
|
||||||
|
@ -196,13 +195,29 @@ bool EditableWidget::handleControlKeys(StellaKey key, StellaMod mod)
|
||||||
|
|
||||||
case KBDK_Y:
|
case KBDK_Y:
|
||||||
case KBDK_Z:
|
case KBDK_Z:
|
||||||
|
{
|
||||||
|
string oldString = _editString;
|
||||||
|
|
||||||
|
myUndoHandler->endChars(_editString);
|
||||||
|
// Reverse Y and Z for QWERTZ keyboards
|
||||||
if(key == KBDK_Y != instance().eventHandler().isQwertz())
|
if(key == KBDK_Y != instance().eventHandler().isQwertz())
|
||||||
dirty = myUndoHandler->redo(_editString);
|
handled = myUndoHandler->redo(_editString);
|
||||||
else
|
else
|
||||||
dirty = myUndoHandler->undo(_editString);
|
if(shift)
|
||||||
_caretPos = int(_editString.size()); // TODO: put at last difference
|
handled = myUndoHandler->redo(_editString);
|
||||||
|
else
|
||||||
|
handled = myUndoHandler->undo(_editString);
|
||||||
|
|
||||||
|
if(handled)
|
||||||
|
{
|
||||||
|
// Put caret at last difference
|
||||||
|
myUndoHandler->lastDiff(_editString, oldString);
|
||||||
|
_caretPos = myUndoHandler->lastDiff(_editString, oldString);
|
||||||
_selectSize = 0;
|
_selectSize = 0;
|
||||||
|
sendCommand(EditableWidget::kChangedCmd, key, _id);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case KBDK_LEFT:
|
case KBDK_LEFT:
|
||||||
handled = moveWord(-1, shift);
|
handled = moveWord(-1, shift);
|
||||||
|
@ -218,11 +233,13 @@ bool EditableWidget::handleControlKeys(StellaKey key, StellaMod mod)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
handled = false;
|
handled = false;
|
||||||
dirty = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dirty)
|
if(handled)
|
||||||
|
{
|
||||||
|
myUndoHandler->endChars(_editString);
|
||||||
setDirty();
|
setDirty();
|
||||||
|
}
|
||||||
|
|
||||||
return handled;
|
return handled;
|
||||||
}
|
}
|
||||||
|
@ -271,7 +288,10 @@ bool EditableWidget::handleShiftKeys(StellaKey key)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(handled)
|
if(handled)
|
||||||
|
{
|
||||||
|
myUndoHandler->endChars(_editString);
|
||||||
setDirty();
|
setDirty();
|
||||||
|
}
|
||||||
|
|
||||||
return handled;
|
return handled;
|
||||||
}
|
}
|
||||||
|
@ -321,7 +341,7 @@ bool EditableWidget::handleNormalKeys(StellaKey key)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KBDK_LEFT:
|
case KBDK_LEFT:
|
||||||
if (_selectSize)
|
if(_selectSize)
|
||||||
handled = setCaretPos(selectStartPos());
|
handled = setCaretPos(selectStartPos());
|
||||||
else if(_caretPos > 0)
|
else if(_caretPos > 0)
|
||||||
handled = setCaretPos(_caretPos - 1);
|
handled = setCaretPos(_caretPos - 1);
|
||||||
|
@ -348,7 +368,10 @@ bool EditableWidget::handleNormalKeys(StellaKey key)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(handled)
|
if(handled)
|
||||||
|
{
|
||||||
|
myUndoHandler->endChars(_editString);
|
||||||
setDirty();
|
setDirty();
|
||||||
|
}
|
||||||
if(!selectMode)
|
if(!selectMode)
|
||||||
_selectSize = 0;
|
_selectSize = 0;
|
||||||
|
|
||||||
|
@ -490,6 +513,7 @@ bool EditableWidget::killChar(int direction, bool addEdit)
|
||||||
{
|
{
|
||||||
if(_caretPos > 0)
|
if(_caretPos > 0)
|
||||||
{
|
{
|
||||||
|
myUndoHandler->endChars(_editString);
|
||||||
_caretPos--;
|
_caretPos--;
|
||||||
_editString.erase(_caretPos, 1);
|
_editString.erase(_caretPos, 1);
|
||||||
handled = true;
|
handled = true;
|
||||||
|
@ -501,6 +525,7 @@ bool EditableWidget::killChar(int direction, bool addEdit)
|
||||||
}
|
}
|
||||||
else if(direction == 1) // Delete next character (delete)
|
else if(direction == 1) // Delete next character (delete)
|
||||||
{
|
{
|
||||||
|
myUndoHandler->endChars(_editString);
|
||||||
_editString.erase(_caretPos, 1);
|
_editString.erase(_caretPos, 1);
|
||||||
handled = true;
|
handled = true;
|
||||||
if(_selectSize > 0)
|
if(_selectSize > 0)
|
||||||
|
@ -616,7 +641,7 @@ bool EditableWidget::moveWord(int direction, bool select)
|
||||||
{
|
{
|
||||||
while (currentPos < int(_editString.size()))
|
while (currentPos < int(_editString.size()))
|
||||||
{
|
{
|
||||||
if (_editString[currentPos - 1] == ' ')
|
if (currentPos && _editString[currentPos - 1] == ' ')
|
||||||
{
|
{
|
||||||
if (!space)
|
if (!space)
|
||||||
break;
|
break;
|
||||||
|
@ -677,6 +702,7 @@ bool EditableWidget::killSelectedText(bool addEdit)
|
||||||
{
|
{
|
||||||
if(_selectSize)
|
if(_selectSize)
|
||||||
{
|
{
|
||||||
|
myUndoHandler->endChars(_editString);
|
||||||
if(_selectSize < 0)
|
if(_selectSize < 0)
|
||||||
{
|
{
|
||||||
_caretPos += _selectSize;
|
_caretPos += _selectSize;
|
||||||
|
@ -694,16 +720,7 @@ bool EditableWidget::killSelectedText(bool addEdit)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool EditableWidget::cutSelectedText()
|
bool EditableWidget::cutSelectedText()
|
||||||
{
|
{
|
||||||
string selected = selectString();
|
return copySelectedText() && killSelectedText();
|
||||||
|
|
||||||
// only cut and copy if anything is selected, else keep old cut text
|
|
||||||
if(!selected.empty())
|
|
||||||
{
|
|
||||||
instance().eventHandler().copyText(selected);
|
|
||||||
killSelectedText();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -726,6 +743,8 @@ bool EditableWidget::pasteSelectedText()
|
||||||
bool selected = !selectString().empty();
|
bool selected = !selectString().empty();
|
||||||
string pasted;
|
string pasted;
|
||||||
|
|
||||||
|
myUndoHandler->endChars(_editString);
|
||||||
|
|
||||||
// retrieve the pasted text
|
// retrieve the pasted text
|
||||||
instance().eventHandler().pasteText(pasted);
|
instance().eventHandler().pasteText(pasted);
|
||||||
// remove the currently selected text
|
// remove the currently selected text
|
||||||
|
|
|
@ -21,15 +21,35 @@
|
||||||
UndoHandler::UndoHandler(size_t size)
|
UndoHandler::UndoHandler(size_t size)
|
||||||
: mySize(size)
|
: mySize(size)
|
||||||
{
|
{
|
||||||
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void UndoHandler::reset()
|
void UndoHandler::reset()
|
||||||
{
|
{
|
||||||
myBuffer.clear();
|
myBuffer.clear();
|
||||||
|
myCharMode = false;
|
||||||
myRedoCount = 0;
|
myRedoCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void UndoHandler::doChar()
|
||||||
|
{
|
||||||
|
myCharMode = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool UndoHandler::endChars(const string& text)
|
||||||
|
{
|
||||||
|
if(myCharMode)
|
||||||
|
{
|
||||||
|
doo(text);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void UndoHandler::doo(const string& text)
|
void UndoHandler::doo(const string& text)
|
||||||
{
|
{
|
||||||
|
@ -43,6 +63,7 @@ void UndoHandler::doo(const string& text)
|
||||||
|
|
||||||
// add text to buffer
|
// add text to buffer
|
||||||
myBuffer.push_front(text);
|
myBuffer.push_front(text);
|
||||||
|
myCharMode = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -68,3 +89,18 @@ bool UndoHandler::redo(string& text)
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
uInt32 UndoHandler::lastDiff(const string& text, const string& oldText) const
|
||||||
|
{
|
||||||
|
uInt32 pos = uInt32(text.size());
|
||||||
|
|
||||||
|
for(auto itn = text.crbegin(), ito = oldText.crbegin();
|
||||||
|
itn != text.crend() && ito != oldText.crend(); ++itn, ++ito)
|
||||||
|
{
|
||||||
|
if(*itn != *ito)
|
||||||
|
break;
|
||||||
|
pos--;
|
||||||
|
}
|
||||||
|
return uInt32(pos);
|
||||||
|
}
|
|
@ -33,14 +33,31 @@ class UndoHandler
|
||||||
UndoHandler(size_t size = 100);
|
UndoHandler(size_t size = 100);
|
||||||
~UndoHandler() = default;
|
~UndoHandler() = default;
|
||||||
|
|
||||||
|
// Reset undo buffer
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
// Add input to undo buffer
|
||||||
void doo(const string& text);
|
void doo(const string& text);
|
||||||
|
// Retrieve last input from undo buffer
|
||||||
bool undo(string& text);
|
bool undo(string& text);
|
||||||
|
// Retrieve next input from undo buffer
|
||||||
bool redo(string& text);
|
bool redo(string& text);
|
||||||
|
|
||||||
|
// Add single char for aggregation
|
||||||
|
void doChar();
|
||||||
|
// Add aggregated single chars to undo buffer
|
||||||
|
bool endChars(const string& text);
|
||||||
|
|
||||||
|
// Get index into text of last different character
|
||||||
|
uInt32 lastDiff(const string& text, const string& oldText) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::deque<string> myBuffer;
|
std::deque<string> myBuffer;
|
||||||
|
// Undo buffer size
|
||||||
size_t mySize{0};
|
size_t mySize{0};
|
||||||
|
// Aggregated single chars flag
|
||||||
|
bool myCharMode{false};
|
||||||
|
// Number of chars available for redo
|
||||||
uInt32 myRedoCount{0};
|
uInt32 myRedoCount{0};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Reference in New Issue