- enhancement: draw cursor for column mode

- enahcnement: edit/delete in multiline ( column mode), press ese to exit
This commit is contained in:
Roy Qu 2022-03-25 22:13:00 +08:00
parent 8b224010e0
commit 0fc995e56a
4 changed files with 155 additions and 61 deletions

View File

@ -18,9 +18,9 @@ Red Panda C++ Version 1.0.1
- enhancement: switch capslock won't cancel code completion - enhancement: switch capslock won't cancel code completion
- enhancement: double click on item in code completion list will use it to complete - enhancement: double click on item in code completion list will use it to complete
- fix: goto declaration by ctrl+click will incorrectly select contents - fix: goto declaration by ctrl+click will incorrectly select contents
- enhancement: alt+shift+arrow do column selection
- fix: input may cause error, if selection in column mode and begin/end at the same column - fix: input may cause error, if selection in column mode and begin/end at the same column
- enhancement: draw selection line if selection in column mode and begin/end at the same column - enhancement: draw cursor for column mode
- enahcnement: edit/delete in multiline ( column mode), press ese to exit
Red Panda C++ Version 1.0.0 Red Panda C++ Version 1.0.0
- fix: calculation for code snippets's tab stop positions is not correct - fix: calculation for code snippets's tab stop positions is not correct

View File

@ -1515,7 +1515,7 @@ void Editor::onStatusChanged(SynStatusChanges changes)
clearUserCodeInTabStops(); clearUserCodeInTabStops();
} }
} }
} else if (!selAvail() && highlighter() && pSettings->editor().highlightMathingBraces()){ } else if (!selAvail() &&!colSelAvail() && highlighter() && pSettings->editor().highlightMathingBraces()){
invalidateLine(mHighlightCharPos1.Line); invalidateLine(mHighlightCharPos1.Line);
invalidateLine(mHighlightCharPos2.Line); invalidateLine(mHighlightCharPos2.Line);
mHighlightCharPos1 = BufferCoord{0,0}; mHighlightCharPos1 = BufferCoord{0,0};

View File

@ -1039,7 +1039,8 @@ bool SynEdit::selAvail() const
bool SynEdit::colSelAvail() const bool SynEdit::colSelAvail() const
{ {
return (mActiveSelectionMode == SynSelectionMode::smColumn && mBlockBegin.Line!=mBlockEnd.Line); return (mActiveSelectionMode == SynSelectionMode::smColumn
&& (mBlockBegin.Line!=mBlockEnd.Line || mBlockBegin.Char!=mBlockEnd.Char));
} }
QString SynEdit::wordAtCursor() QString SynEdit::wordAtCursor()
@ -1891,6 +1892,20 @@ void SynEdit::doDeleteLastChar()
doOnPaintTransientEx(SynTransientType::ttAfter, true); doOnPaintTransientEx(SynTransientType::ttAfter, true);
}); });
if (mActiveSelectionMode==SynSelectionMode::smColumn) {
BufferCoord start=blockBegin();
BufferCoord end=blockEnd();
if (!selAvail()) {
start.Char--;
setBlockBegin(start);
setBlockEnd(end);
}
setSelectedTextEmpty();
end.Char = start.Char;
setBlockBegin(start);
setBlockEnd(end);
return;
}
if (selAvail()) { if (selAvail()) {
setSelectedTextEmpty(); setSelectedTextEmpty();
return; return;
@ -2005,38 +2020,53 @@ void SynEdit::doDeleteCurrentChar()
BufferCoord Caret; BufferCoord Caret;
if (!mReadOnly) { if (!mReadOnly) {
doOnPaintTransient(SynTransientType::ttBefore); doOnPaintTransient(SynTransientType::ttBefore);
if (selAvail())
setSelectedTextEmpty(); if (mActiveSelectionMode==SynSelectionMode::smColumn) {
else { BufferCoord start=blockBegin();
// Call UpdateLastCaretX. Even though the caret doesn't move, the BufferCoord end=blockEnd();
// current caret position should "stick" whenever text is modified. if (!selAvail()) {
updateLastCaretX(); end.Char++;
QString Temp = lineText(); setBlockBegin(start);
int Len = Temp.length(); setBlockEnd(end);
if (mCaretX <= Len) {
// delete char
helper = Temp.mid(mCaretX-1, 1);
Caret.Char = mCaretX + 1;
Caret.Line = mCaretY;
Temp.remove(mCaretX-1, 1);
properSetLine(mCaretY - 1, Temp);
} else {
// join line with the line after
if (mCaretY < mLines->count()) {
properSetLine(mCaretY - 1, Temp + mLines->getString(mCaretY));
Caret.Char = 1;
Caret.Line = mCaretY + 1;
helper = lineBreak();
mLines->deleteAt(mCaretY);
if (mCaretX==1)
doLinesDeleted(mCaretY, 1);
else
doLinesDeleted(mCaretY + 1, 1);
}
} }
if ((Caret.Char != mCaretX) || (Caret.Line != mCaretY)) { setSelectedTextEmpty();
mUndoList->AddChange(SynChangeReason::crSilentDeleteAfterCursor, caretXY(), Caret, end.Char = start.Char;
helper, SynSelectionMode::smNormal); setBlockBegin(start);
setBlockEnd(end);
} else {
if (selAvail())
setSelectedTextEmpty();
else {
// Call UpdateLastCaretX. Even though the caret doesn't move, the
// current caret position should "stick" whenever text is modified.
updateLastCaretX();
QString Temp = lineText();
int Len = Temp.length();
if (mCaretX <= Len) {
// delete char
helper = Temp.mid(mCaretX-1, 1);
Caret.Char = mCaretX + 1;
Caret.Line = mCaretY;
Temp.remove(mCaretX-1, 1);
properSetLine(mCaretY - 1, Temp);
} else {
// join line with the line after
if (mCaretY < mLines->count()) {
properSetLine(mCaretY - 1, Temp + mLines->getString(mCaretY));
Caret.Char = 1;
Caret.Line = mCaretY + 1;
helper = lineBreak();
mLines->deleteAt(mCaretY);
if (mCaretX==1)
doLinesDeleted(mCaretY, 1);
else
doLinesDeleted(mCaretY + 1, 1);
}
}
if ((Caret.Char != mCaretX) || (Caret.Line != mCaretY)) {
mUndoList->AddChange(SynChangeReason::crSilentDeleteAfterCursor, caretXY(), Caret,
helper, SynSelectionMode::smNormal);
}
} }
} }
doOnPaintTransient(SynTransientType::ttAfter); doOnPaintTransient(SynTransientType::ttAfter);
@ -2499,13 +2529,23 @@ QRect SynEdit::calculateCaretRect() const
+ lineText().mid(mCaretX-1); + lineText().mid(mCaretX-1);
coord.Column = charToColumn(sLine,mCaretX+mInputPreeditString.length()); coord.Column = charToColumn(sLine,mCaretX+mInputPreeditString.length());
} }
if (mActiveSelectionMode == SynSelectionMode::smColumn) {
coord.Row = lineToRow(blockBegin().Line);
}
QPoint caretPos = rowColumnToPixels(coord); QPoint caretPos = rowColumnToPixels(coord);
int caretWidth=mCharWidth; int caretWidth=mCharWidth;
if (mCaretY <= mLines->count() && mCaretX <= mLines->getString(mCaretY-1).length()) { if (mCaretY <= mLines->count() && mCaretX <= mLines->getString(mCaretY-1).length()) {
caretWidth = charColumns(mLines->getString(mCaretY-1)[mCaretX-1])*mCharWidth; caretWidth = charColumns(mLines->getString(mCaretY-1)[mCaretX-1])*mCharWidth;
} }
return QRect(caretPos.x(),caretPos.y(),caretWidth, if (mActiveSelectionMode == SynSelectionMode::smColumn) {
mTextHeight); return QRect(caretPos.x(),caretPos.y(),caretWidth,
mTextHeight*(lineToRow(blockEnd().Line)-
lineToRow(blockBegin().Line)+1));
} else {
return QRect(caretPos.x(),caretPos.y(),caretWidth,
mTextHeight);
}
} }
QRect SynEdit::calculateInputCaretRect() const QRect SynEdit::calculateInputCaretRect() const
@ -2732,9 +2772,19 @@ void SynEdit::doAddChar(QChar AChar)
//DoOnPaintTransient(ttBefore); //DoOnPaintTransient(ttBefore);
//mCaretX will change after setSelLength; //mCaretX will change after setSelLength;
if ((mInserting == false) && (!selAvail())) { if ((mInserting == false) && (!selAvail())) {
setSelLength(1); if (colSelAvail()) {
BufferCoord start=blockBegin();
BufferCoord end=blockEnd();
end.Char++;
setBlockBegin(start);
setBlockEnd(end);
} else
setSelLength(1);
} }
bool addInColumnMode = (mActiveSelectionMode == SynSelectionMode::smColumn);
BufferCoord oldBlockBegin = blockBegin();
BufferCoord oldBlockEnd = blockEnd();
if (isIdentChar(AChar)) { if (isIdentChar(AChar)) {
doSetSelText(AChar); doSetSelText(AChar);
} else if (AChar.isSpace()) { } else if (AChar.isSpace()) {
@ -2755,7 +2805,8 @@ void SynEdit::doAddChar(QChar AChar)
int oldCaretX=mCaretX-1; int oldCaretX=mCaretX-1;
int oldCaretY=mCaretY; int oldCaretY=mCaretY;
// auto // auto
if (mOptions.testFlag(eoAutoIndent) if (mActiveSelectionMode==SynSelectionMode::smNormal
&& mOptions.testFlag(eoAutoIndent)
&& mHighlighter && mHighlighter
&& mHighlighter->getClass()==SynHighlighterClass::CppHighlighter && mHighlighter->getClass()==SynHighlighterClass::CppHighlighter
&& (oldCaretY<=mLines->count()) ) { && (oldCaretY<=mLines->count()) ) {
@ -2822,6 +2873,13 @@ void SynEdit::doAddChar(QChar AChar)
} }
mUndoList->EndBlock(); mUndoList->EndBlock();
} }
if (addInColumnMode) {
oldBlockBegin.Char = mCaretX;
oldBlockEnd.Char = mCaretX;
setBlockBegin(oldBlockBegin);
setBlockEnd(oldBlockEnd);
setActiveSelectionMode(SynSelectionMode::smColumn);
}
//DoOnPaintTransient(ttAfter); //DoOnPaintTransient(ttAfter);
} }
@ -3755,7 +3813,7 @@ void SynEdit::paintCaret(QPainter &painter, const QRect rcClip)
switch(ct) { switch(ct) {
case SynEditCaretType::ctVerticalLine: { case SynEditCaretType::ctVerticalLine: {
QRect caretRC; QRect caretRC;
int size = std::max(1,(rcClip.bottom()-rcClip.top())/15); int size = std::max(1, mTextHeight/15);
caretRC.setLeft(rcClip.left()+1); caretRC.setLeft(rcClip.left()+1);
caretRC.setTop(rcClip.top()); caretRC.setTop(rcClip.top());
caretRC.setBottom(rcClip.bottom()); caretRC.setBottom(rcClip.bottom());
@ -3765,7 +3823,7 @@ void SynEdit::paintCaret(QPainter &painter, const QRect rcClip)
} }
case SynEditCaretType::ctHorizontalLine: { case SynEditCaretType::ctHorizontalLine: {
QRect caretRC; QRect caretRC;
int size = std::max(1,(rcClip.bottom()-rcClip.top())/15); int size = std::max(1,mTextHeight/15);
caretRC.setLeft(rcClip.left()); caretRC.setLeft(rcClip.left());
caretRC.setTop(rcClip.bottom()-1+size); caretRC.setTop(rcClip.bottom()-1+size);
caretRC.setBottom(rcClip.bottom()-1); caretRC.setBottom(rcClip.bottom()-1);
@ -4096,12 +4154,29 @@ void SynEdit::setOptions(const SynEditorOptions &Value)
void SynEdit::doAddStr(const QString &s) void SynEdit::doAddStr(const QString &s)
{ {
if (!selAvail() && !mInserting) { if (!selAvail() && !mInserting) {
BufferCoord BB = caretXY(); if (colSelAvail()) {
BufferCoord BE = BB; BufferCoord start=blockBegin();
BE.Char = BB.Char + s.length(); BufferCoord end=blockEnd();
setCaretAndSelection(caretXY(),BB,BE); end.Char+=s.length();
setCaretAndSelection(caretXY(),start,end);
} else {
BufferCoord BB = caretXY();
BufferCoord BE = BB;
BE.Char = BB.Char + s.length();
setCaretAndSelection(caretXY(),BB,BE);
}
} }
bool addInColumnMode = (mActiveSelectionMode == SynSelectionMode::smColumn);
BufferCoord oldBlockBegin = blockBegin();
BufferCoord oldBlockEnd = blockEnd();
doSetSelText(s); doSetSelText(s);
if (addInColumnMode) {
oldBlockBegin.Char = mCaretX;
oldBlockEnd.Char = mCaretX;
setBlockBegin(oldBlockBegin);
setBlockEnd(oldBlockEnd);
setActiveSelectionMode(SynSelectionMode::smColumn);
}
} }
void SynEdit::doUndo() void SynEdit::doUndo()
@ -4897,6 +4972,11 @@ void SynEdit::setSelTextPrimitiveEx(SynSelectionMode PasteMode, const QString &V
BufferCoord BE = blockEnd(); BufferCoord BE = blockEnd();
if (selAvail()) { if (selAvail()) {
deleteSelection(BB,BE); deleteSelection(BB,BE);
if (mActiveSelectionMode == SynSelectionMode::smColumn) {
BE.Char = BB.Char;
mBlockBegin = BB;
mBlockEnd = BE;
}
internalSetCaretXY(BB); internalSetCaretXY(BB);
} }
if (!Value.isEmpty()) { if (!Value.isEmpty()) {
@ -5362,8 +5442,11 @@ int SynEdit::insertTextByColumnMode(const QString &value, bool addToUndoList)
int insertCol; int insertCol;
BufferCoord lineBreakPos; BufferCoord lineBreakPos;
int result = 0; int result = 0;
// Insert string at current position BufferCoord insertPos = blockBegin();
insertCol = charToColumn(mCaretY,mCaretX); BufferCoord endPos = blockEnd();
// Insert string at begin of the selection
insertCol = charToColumn(insertPos.Line,insertPos.Char);
mCaretY=insertPos.Line;
start = 0; start = 0;
do { do {
p = GetEOL(value,start); p = GetEOL(value,start);
@ -5406,7 +5489,17 @@ int SynEdit::insertTextByColumnMode(const QString &value, bool addToUndoList)
mCaretY++; mCaretY++;
mStatusChanges.setFlag(SynStatusChange::scCaretY); mStatusChanges.setFlag(SynStatusChange::scCaretY);
} }
start = p; //if we only have one inline to insert, repeat it
if (start == 0 && p>=value.length() && p!=start) {
p=0;
if (mCaretY < endPos.Line) {
mCaretY++;
mStatusChanges.setFlag(SynStatusChange::scCaretY);
} else
break;
} else {
start = p;
}
} while (p<value.length()); } while (p<value.length());
mCaretX+=str.length(); mCaretX+=str.length();
mStatusChanges.setFlag(SynStatusChange::scCaretX); mStatusChanges.setFlag(SynStatusChange::scCaretX);
@ -5962,15 +6055,22 @@ void SynEdit::focusOutEvent(QFocusEvent *)
void SynEdit::keyPressEvent(QKeyEvent *event) void SynEdit::keyPressEvent(QKeyEvent *event)
{ {
SynEditorCommand cmd=TranslateKeyCode(event->key(),event->modifiers()); if (event->key() == Qt::Key_Escape && mActiveSelectionMode != mSelectionMode) {
if (cmd!=SynEditorCommand::ecNone) { setActiveSelectionMode(selectionMode());
commandProcessor(cmd,QChar(),nullptr); setBlockBegin(caretXY());
setBlockEnd(caretXY());
event->accept(); event->accept();
} else if (!event->text().isEmpty()) { } else {
QChar c = event->text().at(0); SynEditorCommand cmd=TranslateKeyCode(event->key(),event->modifiers());
if (c=='\t' || c.isPrint()) { if (cmd!=SynEditorCommand::ecNone) {
commandProcessor(SynEditorCommand::ecChar,c,nullptr); commandProcessor(cmd,QChar(),nullptr);
event->accept(); event->accept();
} else if (!event->text().isEmpty()) {
QChar c = event->text().at(0);
if (c=='\t' || c.isPrint()) {
commandProcessor(SynEditorCommand::ecChar,c,nullptr);
event->accept();
}
} }
} }
if (!event->isAccepted()) { if (!event->isAccepted()) {

View File

@ -1058,12 +1058,6 @@ void SynEditTextPainter::PaintLines()
PaintEditAreas(areaList); PaintEditAreas(areaList);
} }
if (nLineSelStart!=0 && nLineSelEnd!=0
&& nLineSelStart == nLineSelEnd) {
painter->setPen(edit->selectedBackground());
int x =ColumnToXValue(nLineSelStart);
painter->drawLine(x,rcLine.top(),x,rcLine.bottom()+1);
}
// Now paint the right edge if necessary. We do it line by line to reduce // Now paint the right edge if necessary. We do it line by line to reduce
// the flicker. Should not cost very much anyway, compared to the many // the flicker. Should not cost very much anyway, compared to the many
// calls to ExtTextOut. // calls to ExtTextOut.