- enhancement: prohibit move selection up/down under column mode

- enhancement: prohibit move selection up/down when the last line in selection is a folded code blocks
  - enhancement: check validity of selection in column mode when moving caret by keyboard
  - enhancement: check validity of selection in column mode when moving caret by mouse
  - enhancement: only allow insert linebreak at the end of folded code block
  - enhancement: only allow delete whole folded code block
  - refactor of undo system
This commit is contained in:
Roy Qu 2022-07-02 20:19:37 +08:00
parent 39dd7e3abb
commit 348788bbcd
4 changed files with 123 additions and 56 deletions

10
NEWS.md
View File

@ -1,3 +1,13 @@
Red Panda C++ Version 1.1.4
- enhancement: prohibit move selection up/down under column mode
- enhancement: prohibit move selection up/down when the last line in selection is a folded code blocks
- enhancement: check validity of selection in column mode when moving caret by keyboard
- enhancement: check validity of selection in column mode when moving caret by mouse
- enhancement: only allow insert linebreak at the end of folded code block
- enhancement: only allow delete whole folded code block
- refactor of undo system
Red Panda C++ Version 1.1.3
- fix: wrong auto indent calculation for comments

View File

@ -653,8 +653,13 @@ QStringList splitStrings(const QString &text)
while(i<text.length()) {
if (text[i]=='\n' || text[i]=='\r') {
list.append(text.mid(start,i-start));
if (text[i]=='\r') {
i++;
while (i<text.length() && (text[i]=='\n' || text[i]=='\r')) i++;
if (i<text.length() && text[i]=='\n')
i++;
} else {
i++;
}
start=i;
} else {
i++;

View File

@ -1960,6 +1960,23 @@ void SynEdit::doMouseScroll(bool isDragging)
}
BufferCoord vCaret = displayToBufferPos(C);
if ((caretX() != vCaret.Char) || (caretY() != vCaret.Line)) {
if (mActiveSelectionMode == SynSelectionMode::smColumn) {
int startLine=std::min(mBlockBegin.Line,mBlockEnd.Line);
startLine = std::min(startLine,vCaret.Line);
int endLine=std::max(mBlockBegin.Line,mBlockEnd.Line);
endLine = std::max(endLine,vCaret.Line);
int currentCol=displayXY().Column;
for (int i=startLine;i<=endLine;i++) {
QString s = mDocument->getString(i-1);
int cols = stringColumns(s,0);
if (cols+1<currentCol) {
computeScroll(isDragging);
return;
}
}
}
// changes to line / column in one go
incPaintLock();
auto action = finally([this]{
@ -2019,7 +2036,7 @@ void SynEdit::doDeleteLastChar()
QStringList helper;
if (mCaretX > Len + 1) {
// only move caret one column
internalSetCaretX(mCaretX - 1);
return;
} else if (mCaretX == 1) {
// join this line with the last line if possible
if (mCaretY > 1) {
@ -2104,7 +2121,9 @@ void SynEdit::doDeleteCurrentChar()
updateLastCaretX();
QString Temp = lineText();
int Len = Temp.length();
if (mCaretX <= Len) {
if (mCaretX>Len+1) {
return;
} else if (mCaretX <= Len) {
QChar ch = Temp[mCaretX-1];
if (ch==' ' || ch=='\t')
shouldAddGroupBreak=true;
@ -2143,6 +2162,8 @@ void SynEdit::doDeleteWord()
{
if (mReadOnly)
return;
if (mCaretX>lineText().length()+1)
return;
BufferCoord start = wordStart();
BufferCoord end = wordEnd();
@ -2153,6 +2174,9 @@ void SynEdit::doDeleteToEOL()
{
if (mReadOnly)
return;
if (mCaretX>lineText().length()+1)
return;
deleteFromTo(caretXY(),BufferCoord{lineText().length()+1,mCaretY});
}
@ -2160,6 +2184,9 @@ void SynEdit::doDeleteToWordStart()
{
if (mReadOnly)
return;
if (mCaretX>lineText().length()+1)
return;
BufferCoord start = wordStart();
BufferCoord end = caretXY();
if (start==end) {
@ -2172,6 +2199,9 @@ void SynEdit::doDeleteToWordEnd()
{
if (mReadOnly)
return;
if (mCaretX>lineText().length()+1)
return;
BufferCoord start = caretXY();
BufferCoord end = wordEnd();
if (start == end) {
@ -2184,12 +2214,18 @@ void SynEdit::doDeleteFromBOL()
{
if (mReadOnly)
return;
if (mCaretX>lineText().length()+1)
return;
deleteFromTo(BufferCoord{1,mCaretY},caretXY());
}
void SynEdit::doDeleteLine()
{
if (!mReadOnly && (mDocument->count() > 0)) {
PSynEditFoldRange foldRange=foldStartAtLine(mCaretY);
if (foldRange && foldRange->collapsed)
return;
doOnPaintTransient(SynTransientType::ttBefore);
mUndoList->BeginBlock();
mUndoList->AddChange(SynChangeReason::crCaret,
@ -2216,7 +2252,6 @@ void SynEdit::doDeleteLine()
QString s = mDocument->getString(mCaretY-2);
mDocument->deleteAt(mCaretY - 1);
helper.insert(0,"");
qDebug()<<helper;
mUndoList->AddChange(SynChangeReason::crDelete,
BufferCoord{s.length()+1, mCaretY-1},
BufferCoord{helper.length() + 1, mCaretY},
@ -2251,6 +2286,9 @@ void SynEdit::doSelecteLine()
void SynEdit::doDuplicateLine()
{
if (!mReadOnly && (mDocument->count() > 0)) {
PSynEditFoldRange foldRange=foldStartAtLine(mCaretY);
if (foldRange && foldRange->collapsed)
return;
QString s = lineText();
doOnPaintTransient(SynTransientType::ttBefore);
mDocument->insert(mCaretY, lineText());
@ -2272,12 +2310,23 @@ void SynEdit::doDuplicateLine()
void SynEdit::doMoveSelUp()
{
if (mActiveSelectionMode == SynSelectionMode::smColumn)
return;
if (!mReadOnly && (mDocument->count() > 0) && (blockBegin().Line > 1)) {
BufferCoord origBlockBegin = blockBegin();
BufferCoord origBlockEnd = blockEnd();
PSynEditFoldRange foldRange=foldStartAtLine(origBlockEnd.Line);
if (foldRange && foldRange->collapsed)
return;
// for (int line=origBlockBegin.Line;line<=origBlockEnd.Line;line++) {
// PSynEditFoldRange foldRange=foldStartAtLine(line);
// if (foldRange && foldRange->collapsed)
// return;
// }
doOnPaintTransient(SynTransientType::ttBefore);
// Backup caret and selection
BufferCoord origBlockBegin = blockBegin();
BufferCoord origBlockEnd = blockEnd();
if (!mUndoing) {
mUndoList->BeginBlock();
@ -2314,11 +2363,21 @@ void SynEdit::doMoveSelUp()
void SynEdit::doMoveSelDown()
{
if (mActiveSelectionMode == SynSelectionMode::smColumn)
return;
if (!mReadOnly && (mDocument->count() > 0) && (blockEnd().Line < mDocument->count())) {
doOnPaintTransient(SynTransientType::ttBefore);
// Backup caret and selection
BufferCoord origBlockBegin = blockBegin();
BufferCoord origBlockEnd = blockEnd();
PSynEditFoldRange foldRange=foldStartAtLine(origBlockEnd.Line);
if (foldRange && foldRange->collapsed)
return;
// for (int line=origBlockBegin.Line;line<=origBlockEnd.Line;line++) {
// PSynEditFoldRange foldRange=foldStartAtLine(line.Line);
// if (foldRange && foldRange->collapsed)
// return;
// }
doOnPaintTransient(SynTransientType::ttBefore);
// Backup caret and selection
if (!mUndoing) {
mUndoList->BeginBlock();
mUndoList->AddChange(SynChangeReason::crCaret, // backup original caret
@ -2369,8 +2428,10 @@ void SynEdit::insertLine(bool moveCaret)
if (mReadOnly)
return;
int nLinesInserted=0;
if (!mUndoing)
mUndoList->BeginBlock();
auto action = finally([this] {
if (!mUndoing)
mUndoList->EndBlock();
});
QString helper;
@ -2380,11 +2441,16 @@ void SynEdit::insertLine(bool moveCaret)
}
QString Temp = lineText();
if (mCaretX>lineText().length()+1) {
PSynEditFoldRange foldRange = foldStartAtLine(mCaretY);
if ((foldRange) && foldRange->collapsed) {
QString s = Temp+highlighter()->foldString();
if (mCaretX > s.length()) {
if (!mUndoing) {
addCaretToUndo();
addSelectionToUndo();
}
mCaretY=foldRange->toLine;
if (mCaretY>mDocument->count()) {
mCaretY=mDocument->count();
@ -2394,6 +2460,7 @@ void SynEdit::insertLine(bool moveCaret)
}
}
}
QString Temp2 = Temp;
QString Temp3;
PSynHighlighterAttribute Attr;
@ -2430,6 +2497,7 @@ void SynEdit::insertLine(bool moveCaret)
QString indentSpacesForRightLineText = GetLeftSpacing(indentSpaces,true);
mDocument->insert(mCaretY, indentSpacesForRightLineText+rightLineText);
nLinesInserted++;
if (!mUndoing)
mUndoList->AddChange(SynChangeReason::crLineBreak, caretXY(), caretXY(), QStringList(rightLineText),
SynSelectionMode::smNormal);
@ -4885,7 +4953,7 @@ void SynEdit::moveCaretHorz(int DX, bool isSelection)
int row = lineToRow(ptDst.Line);
row++;
int line = rowToLine(row);
qDebug()<<line<<ptDst.Line;
// qDebug()<<line<<ptDst.Line;
if (line!=ptDst.Line && line<=mDocument->count()) {
ptDst.Line = line;
ptDst.Char = 1;
@ -5038,43 +5106,6 @@ void SynEdit::setSelTextPrimitiveEx(SynSelectionMode mode, const QStringList &te
bool groupUndo=false;
BufferCoord startPos = blockBegin();
BufferCoord endPos = blockEnd();
if (mode==SynSelectionMode::smNormal) {
PSynEditFoldRange foldRange = foldStartAtLine(endPos.Line);
QString s = mDocument->getString(endPos.Line-1);
if ((foldRange) && foldRange->collapsed && endPos.Char>s.length()) {
QString newS=s+highlighter()->foldString();
if (selAvail()) {
if ((startPos.Char<=s.length() || startPos.Line<endPos.Line)
&& endPos.Char>newS.length() ) {
//selection has whole block
endPos.Line = foldRange->toLine;
endPos.Char = mDocument->getString(endPos.Line-1).length()+1;
} else {
uncollapse(foldRange);
endPos.Char = s.length()+1;
if (startPos.Char>s.length())
startPos.Char=s.length()+1;
}
} else {
if (endPos.Char>newS.length()) {
//caret at the end of the block
uncollapse(foldRange);
endPos.Line = foldRange->toLine;
endPos.Char = mDocument->getString(endPos.Line-1).length()+1;
startPos=endPos;
} else {
//caret in the block { }
uncollapse(foldRange);
endPos.Char = mDocument->getString(endPos.Line-1).length()+1;
startPos=endPos;
}
}
mBlockBegin=startPos;
mBlockEnd=endPos;
mCaretX=endPos.Char;
mCaretY=endPos.Line;
}
}
if (selAvail()) {
if (!mUndoing && !text.isEmpty()) {
mUndoList->BeginBlock();
@ -5351,12 +5382,26 @@ void SynEdit::properSetLine(int ALine, const QString &ALineText, bool notify)
}
}
void SynEdit::doDeleteText(const BufferCoord &startPos, const BufferCoord &endPos, SynSelectionMode mode)
void SynEdit::doDeleteText(BufferCoord startPos, BufferCoord endPos, SynSelectionMode mode)
{
bool UpdateMarks = false;
int MarkOffset = 0;
if (mode == SynSelectionMode::smNormal) {
PSynEditFoldRange foldRange = foldStartAtLine(endPos.Line);
QString s = mDocument->getString(endPos.Line-1);
if ((foldRange) && foldRange->collapsed && endPos.Char>s.length()) {
QString newS=s+highlighter()->foldString();
if ((startPos.Char<=s.length() || startPos.Line<endPos.Line)
&& endPos.Char>newS.length() ) {
//selection has whole block
endPos.Line = foldRange->toLine;
endPos.Char = mDocument->getString(endPos.Line-1).length()+1;
} else {
return;
}
}
}
QStringList deleted=getContent(startPos,endPos,mode);
switch(mode) {
case SynSelectionMode::smNormal:
if (mDocument->count() > 0) {
@ -5428,12 +5473,20 @@ void SynEdit::doDeleteText(const BufferCoord &startPos, const BufferCoord &endPo
}
}
void SynEdit::doInsertText(const BufferCoord& pos, const QStringList& text, SynSelectionMode mode, int startLine, int endLine) {
void SynEdit::doInsertText(const BufferCoord& pos,
const QStringList& text,
SynSelectionMode mode, int startLine, int endLine) {
if (text.isEmpty())
return;
if (startLine>endLine)
std::swap(startLine,endLine);
if (mode == SynSelectionMode::smNormal) {
PSynEditFoldRange foldRange = foldStartAtLine(pos.Line);
QString s = mDocument->getString(pos.Line-1);
if ((foldRange) && foldRange->collapsed && pos.Char>s.length()+1)
return;
}
int insertedLines = 0;
BufferCoord newPos;
switch(mode){
@ -5456,7 +5509,6 @@ void SynEdit::doInsertText(const BufferCoord& pos, const QStringList& text, SynS
int SynEdit::doInsertTextByNormalMode(const BufferCoord& pos, const QStringList& text, BufferCoord &newPos)
{
QString sLeftSide;
QString sRightSide;
QString str;
@ -6225,7 +6277,7 @@ void SynEdit::mousePressEvent(QMouseEvent *event)
}else {
return;
}
} else if (button == Qt::LeftButton && mActiveSelectionMode == SynSelectionMode::smNormal) {
} else if (button == Qt::LeftButton) {
if (selAvail()) {
//remember selection state, as it will be cleared later
bWasSel = true;

View File

@ -559,7 +559,7 @@ private:
void properSetLine(int ALine, const QString& ALineText, bool notify = true);
//primitive edit operations
void doDeleteText(const BufferCoord& startPos, const BufferCoord& endPos, SynSelectionMode mode);
void doDeleteText(BufferCoord startPos, BufferCoord endPos, SynSelectionMode mode);
void doInsertText(const BufferCoord& pos, const QStringList& text, SynSelectionMode mode, int startLine, int endLine);
int doInsertTextByNormalMode(const BufferCoord& pos, const QStringList& text, BufferCoord &newPos);
int doInsertTextByColumnMode(const BufferCoord& pos, const QStringList& text, BufferCoord &newPos, int startLine, int endLine);