- Enhancement: Vertically scroll by pixel.

This commit is contained in:
Roy Qu 2024-03-22 21:56:04 +08:00
parent 8307f1b38f
commit a83ee3f16a
9 changed files with 120 additions and 137 deletions

View File

@ -132,6 +132,7 @@ Red Panda C++ Version 2.26
- Enhancement: New option for compiler set "Don't localize gcc output messages" - Enhancement: New option for compiler set "Don't localize gcc output messages"
- Enhancement: Optimization for drawing scrollbars. - Enhancement: Optimization for drawing scrollbars.
- Enhancement: Issue #213 Expands macro when finding function tips. - Enhancement: Issue #213 Expands macro when finding function tips.
- Enhancement: Vertically scroll by pixel.
Red Panda C++ Version 2.25 Red Panda C++ Version 2.25

View File

@ -5086,7 +5086,7 @@ void Editor::reformat(bool doReparse)
#endif #endif
if (newContent.isEmpty()) if (newContent.isEmpty())
return; return;
int oldTopLine = topLine(); int oldTopPos = topPos();
QSynedit::BufferCoord mOldCaret = caretXY(); QSynedit::BufferCoord mOldCaret = caretXY();
beginEditing(); beginEditing();
@ -5099,7 +5099,7 @@ void Editor::reformat(bool doReparse)
setOptions(newOptions); setOptions(newOptions);
replaceAll(QString::fromUtf8(newContent)); replaceAll(QString::fromUtf8(newContent));
setCaretXY(mOldCaret); setCaretXY(mOldCaret);
setTopLine(oldTopLine); setTopPos(oldTopPos);
setOptions(oldOptions); setOptions(oldOptions);
endEditing(); endEditing();

View File

@ -3281,7 +3281,7 @@ bool MainWindow::saveLastOpens()
fileObj["focused"] = editor->hasFocus(); fileObj["focused"] = editor->hasFocus();
fileObj["caretX"] = editor->caretX(); fileObj["caretX"] = editor->caretX();
fileObj["caretY"] = editor->caretY(); fileObj["caretY"] = editor->caretY();
fileObj["topLine"] = editor->topLine(); fileObj["top"] = editor->topPos();
fileObj["left"] = editor->leftPos(); fileObj["left"] = editor->leftPos();
filesArray.append(fileObj); filesArray.append(fileObj);
} }
@ -3383,8 +3383,8 @@ void MainWindow::loadLastOpens()
pos.ch = fileObj["caretX"].toInt(1); pos.ch = fileObj["caretX"].toInt(1);
pos.line = fileObj["caretY"].toInt(1); pos.line = fileObj["caretY"].toInt(1);
editor->setCaretXY(pos); editor->setCaretXY(pos);
editor->setTopLine( editor->setTopPos(
fileObj["topLine"].toInt(1) fileObj["top"].toInt(1)
); );
editor->setLeftPos( editor->setLeftPos(
fileObj["left"].toInt(1) fileObj["left"].toInt(1)
@ -5482,11 +5482,11 @@ void MainWindow::onFileChanged(const QString &path)
QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes|QMessageBox::No,
QMessageBox::No) == QMessageBox::Yes) { QMessageBox::No) == QMessageBox::Yes) {
try { try {
int topLine = e->topLine(); int top = e->topPos();
QSynedit::BufferCoord caretPos = e->caretXY(); QSynedit::BufferCoord caretPos = e->caretXY();
e->loadFile(); e->loadFile();
e->setCaretPositionAndActivate(caretPos.line,1); e->setCaretPositionAndActivate(caretPos.line,1);
e->setTopLine(topLine); e->setTopPos(top);
} catch(FileError e) { } catch(FileError e) {
QMessageBox::critical(this,tr("Error"),e.reason()); QMessageBox::critical(this,tr("Error"),e.reason());
} }

View File

@ -425,7 +425,7 @@ Editor *Project::openUnit(PProjectUnit &unit, const PProjectEditorLayout &layout
//editor->setInProject(true); //editor->setInProject(true);
editor->setCaretY(layout->caretY); editor->setCaretY(layout->caretY);
editor->setCaretX(layout->caretX); editor->setCaretX(layout->caretX);
editor->setTopLine(layout->topLine); editor->setTopPos(layout->top);
editor->setLeftPos(layout->left); editor->setLeftPos(layout->left);
editor->activate(); editor->activate();
return editor; return editor;
@ -662,7 +662,7 @@ void Project::saveLayout()
jsonLayout["filename"]=unit->fileName(); jsonLayout["filename"]=unit->fileName();
jsonLayout["caretX"]=editor->caretX(); jsonLayout["caretX"]=editor->caretX();
jsonLayout["caretY"]=editor->caretY(); jsonLayout["caretY"]=editor->caretY();
jsonLayout["topLine"]=editor->topLine(); jsonLayout["top"]=editor->topPos();
jsonLayout["left"]=editor->leftPos(); jsonLayout["left"]=editor->leftPos();
jsonLayout["isOpen"]=true; jsonLayout["isOpen"]=true;
jsonLayout["focused"]=(editor==e); jsonLayout["focused"]=(editor==e);
@ -678,7 +678,7 @@ void Project::saveLayout()
jsonLayout["filename"]=unit->fileName(); jsonLayout["filename"]=unit->fileName();
jsonLayout["caretX"]=oldLayout->caretX; jsonLayout["caretX"]=oldLayout->caretX;
jsonLayout["caretY"]=oldLayout->caretY; jsonLayout["caretY"]=oldLayout->caretY;
jsonLayout["topLine"]=oldLayout->topLine; jsonLayout["top"]=oldLayout->top;
jsonLayout["left"]=oldLayout->left; jsonLayout["left"]=oldLayout->left;
jsonLayout["isOpen"]=false; jsonLayout["isOpen"]=false;
jsonLayout["focused"]=false; jsonLayout["focused"]=false;
@ -1945,7 +1945,7 @@ QHash<QString, PProjectEditorLayout> Project::loadLayout()
if (mUnits.contains(unitFilename)) { if (mUnits.contains(unitFilename)) {
PProjectEditorLayout editorLayout = std::make_shared<ProjectEditorLayout>(); PProjectEditorLayout editorLayout = std::make_shared<ProjectEditorLayout>();
editorLayout->filename=unitFilename; editorLayout->filename=unitFilename;
editorLayout->topLine=jsonLayout["topLine"].toInt(); editorLayout->top=jsonLayout["top"].toInt();
editorLayout->left=jsonLayout["left"].toInt(); editorLayout->left=jsonLayout["left"].toInt();
editorLayout->caretX=jsonLayout["caretX"].toInt(); editorLayout->caretX=jsonLayout["caretX"].toInt();
editorLayout->caretY=jsonLayout["caretY"].toInt(); editorLayout->caretY=jsonLayout["caretY"].toInt();
@ -2175,7 +2175,7 @@ void Project::loadUnitLayout(Editor *e)
if (layout) { if (layout) {
e->setCaretY(layout->caretY); e->setCaretY(layout->caretY);
e->setCaretX(layout->caretX); e->setCaretX(layout->caretX);
e->setTopLine(layout->topLine); e->setTopPos(layout->top);
e->setLeftPos(layout->left); e->setLeftPos(layout->left);
} }
} }

View File

@ -61,7 +61,7 @@ struct ProjectModelNode {
struct ProjectEditorLayout { struct ProjectEditorLayout {
QString filename; QString filename;
int topLine; int top;
int left; int left;
int caretX; int caretX;
int caretY; int caretY;

View File

@ -370,7 +370,7 @@ std::shared_ptr<SearchResultTreeItem> SearchInFileDialog::batchFindInEditor(QSyn
QSynedit::BufferCoord caretBackup = e->caretXY(); QSynedit::BufferCoord caretBackup = e->caretXY();
QSynedit::BufferCoord blockBeginBackup = e->blockBegin(); QSynedit::BufferCoord blockBeginBackup = e->blockBegin();
QSynedit::BufferCoord blockEndBackup = e->blockEnd(); QSynedit::BufferCoord blockEndBackup = e->blockEnd();
int toplineBackup = e->topLine(); int topPosBackup = e->topPos();
int leftPosBackup = e->leftPos(); int leftPosBackup = e->leftPos();
PSearchResultTreeItem parentItem = std::make_shared<SearchResultTreeItem>(); PSearchResultTreeItem parentItem = std::make_shared<SearchResultTreeItem>();
@ -393,7 +393,7 @@ std::shared_ptr<SearchResultTreeItem> SearchInFileDialog::batchFindInEditor(QSyn
// restore // restore
e->setCaretXY(caretBackup); e->setCaretXY(caretBackup);
e->setTopLine(toplineBackup); e->setTopPos(topPosBackup);
e->setLeftPos(leftPosBackup); e->setLeftPos(leftPosBackup);
e->setCaretAndSelection( e->setCaretAndSelection(
caretBackup, caretBackup,

View File

@ -74,7 +74,7 @@ void QSynEditPainter::paintEditingArea(const QRect& clip)
} }
// If there is anything visible below the last line, then fill this as well. // If there is anything visible below the last line, then fill this as well.
mRcToken = mClip; mRcToken = mClip;
mRcToken.setTop((mLastRow - mEdit->mTopLine + 1) * mEdit->mTextHeight); mRcToken.setTop((mLastRow - mEdit->yposToRow(0) + 1) * mEdit->mTextHeight);
if (mRcToken.top() < mRcToken.bottom()) { if (mRcToken.top() < mRcToken.bottom()) {
mPainter->fillRect(mRcToken,colEditorBG()); mPainter->fillRect(mRcToken,colEditorBG());
// Draw the right edge if necessary. // Draw the right edge if necessary.
@ -139,7 +139,7 @@ void QSynEditPainter::paintGutter(const QRect& clip)
} else { } else {
mPainter->setPen(textColor); mPainter->setPen(textColor);
} }
int lineTop = (row - mEdit->mTopLine) * mEdit->mTextHeight; int lineTop = (row - 1) * mEdit->mTextHeight - mEdit->mTopPos;
// next line rect // next line rect
rcLine.setTop(lineTop); rcLine.setTop(lineTop);
@ -168,7 +168,7 @@ void QSynEditPainter::paintGutter(const QRect& clip)
// Form a rectangle for the square the user can click on // Form a rectangle for the square the user can click on
rcFold.setLeft(mEdit->mGutterWidth - mEdit->mGutter.rightOffset()); rcFold.setLeft(mEdit->mGutterWidth - mEdit->mGutter.rightOffset());
rcFold.setTop((row - mEdit->mTopLine) * mEdit->mTextHeight); rcFold.setTop((row - 1) * mEdit->mTextHeight - mEdit->mTopPos);
rcFold.setRight(rcFold.left() + mEdit->mGutter.rightOffset() - 4); rcFold.setRight(rcFold.left() + mEdit->mGutter.rightOffset() - 4);
rcFold.setBottom(rcFold.top() + mEdit->mTextHeight); rcFold.setBottom(rcFold.top() + mEdit->mTextHeight);
@ -231,7 +231,7 @@ void QSynEditPainter::paintGutter(const QRect& clip)
int line = mEdit->rowToLine(row); int line = mEdit->rowToLine(row);
if ((line > mEdit->mDocument->count()) && (mEdit->mDocument->count() != 0)) if ((line > mEdit->mDocument->count()) && (mEdit->mDocument->count() != 0))
break; break;
mEdit->onGutterPaint(*mPainter,line, 0, (row - mEdit->mTopLine) * mEdit->mTextHeight); mEdit->onGutterPaint(*mPainter,line, 0, (row - mEdit->yposToRow(0)) * mEdit->mTextHeight);
} }
} }
@ -818,7 +818,7 @@ void QSynEditPainter::paintFoldAttributes()
break; break;
int X; int X;
// Set vertical coord // Set vertical coord
int Y = (row - mEdit->mTopLine) * mEdit->mTextHeight; // limit inside clip rect int Y = (row - mEdit->yposToRow(0)) * mEdit->mTextHeight; // limit inside clip rect
if (mEdit->mTextHeight % 2 == 1 && vLine % 2 == 0) { if (mEdit->mTextHeight % 2 == 1 && vLine % 2 == 0) {
Y++; Y++;
} }
@ -887,7 +887,7 @@ void QSynEditPainter::paintFoldAttributes()
if (range->collapsed && !range->parentCollapsed() && if (range->collapsed && !range->parentCollapsed() &&
(range->fromLine <= mLastLine) && (range->fromLine >= mFirstLine) ) { (range->fromLine <= mLastLine) && (range->fromLine >= mFirstLine) ) {
// Get starting and end points // Get starting and end points
int Y = (mEdit->lineToRow(range->fromLine) - mEdit->mTopLine + 1) * mEdit->mTextHeight - 1; int Y = (mEdit->lineToRow(range->fromLine) - mEdit->yposToRow(0) + 1) * mEdit->mTextHeight - 1;
mPainter->drawLine(mClip.left(),Y, mClip.right(),Y); mPainter->drawLine(mClip.left(),Y, mClip.right(),Y);
} }
} }
@ -933,7 +933,7 @@ void QSynEditPainter::paintLines()
// Initialize rcLine for drawing. Note that Top and Bottom are updated // Initialize rcLine for drawing. Note that Top and Bottom are updated
// inside the loop. Get only the starting point for this. // inside the loop. Get only the starting point for this.
mRcLine = mClip; mRcLine = mClip;
mRcLine.setBottom((mFirstRow - mEdit->mTopLine) * mEdit->mTextHeight); mRcLine.setBottom((mFirstRow - 1) * mEdit->mTextHeight - mEdit->mTopPos);
mTokenAccu.width = 0; mTokenAccu.width = 0;
mTokenAccu.left = 0; mTokenAccu.left = 0;
mTokenAccu.style = FontStyle::fsNone; mTokenAccu.style = FontStyle::fsNone;
@ -1015,7 +1015,7 @@ void QSynEditPainter::paintLines()
// Update the rcLine rect to this line. // Update the rcLine rect to this line.
// rcLine.setTop(rcLine.bottom()); // rcLine.setTop(rcLine.bottom());
// rcLine.setBottom(rcLine.bottom()+edit->mTextHeight); // rcLine.setBottom(rcLine.bottom()+edit->mTextHeight);
mRcLine.setTop((row - mEdit->mTopLine) * mEdit->mTextHeight); mRcLine.setTop((row - 1) * mEdit->mTextHeight - mEdit->mTopPos);
mRcLine.setHeight(mEdit->mTextHeight); mRcLine.setHeight(mEdit->mTextHeight);
// if (mIsSpecialLine && colSpBG.isValid()) // if (mIsSpecialLine && colSpBG.isValid())

View File

@ -132,7 +132,7 @@ QSynEdit::QSynEdit(QWidget *parent) : QAbstractScrollArea(parent),
mWantReturns = true; mWantReturns = true;
mWantTabs = false; mWantTabs = false;
mLeftPos = 0; mLeftPos = 0;
mTopLine = 1; mTopPos = 0;
mCaretX = 1; mCaretX = 1;
mLastCaretColumn = 1; mLastCaretColumn = 1;
mCaretY = 1; mCaretY = 1;
@ -432,9 +432,9 @@ void QSynEdit::addCaretToUndo()
void QSynEdit::addLeftTopToUndo() void QSynEdit::addLeftTopToUndo()
{ {
BufferCoord p; BufferCoord p;
//todo: use buffer coord to save left pos is ugly //todo: use buffer coord to save left/top pos is ugly
p.ch = leftPos(); p.ch = leftPos();
p.line = topLine(); p.line = topPos();
mUndoList->addChange(ChangeReason::LeftTop,p,p,QStringList(), mActiveSelectionMode); mUndoList->addChange(ChangeReason::LeftTop,p,p,QStringList(), mActiveSelectionMode);
} }
@ -636,8 +636,7 @@ bool QSynEdit::pointToLine(const QPoint &point, int &line)
return false; return false;
} }
line = rowToLine( line = rowToLine(
std::max(1, mTopLine + (point.y() / mTextHeight)) yposToRow(point.y() / mTextHeight));
);
return true; return true;
} }
@ -681,11 +680,11 @@ void QSynEdit::invalidateGutterLines(int firstLine, int lastLine)
else else
lastLine = INT_MAX; lastLine = INT_MAX;
} }
firstLine = std::max(firstLine, mTopLine); firstLine = std::min(firstLine, yposToRow(0) );
lastLine = std::min(lastLine, mTopLine + mLinesInWindow); lastLine = std::max(lastLine, yposToRow(clientHeight()));
// any line visible? // any line visible?
if (lastLine >= firstLine) { if (lastLine >= firstLine) {
rcInval = {0, mTextHeight * (firstLine - mTopLine), rcInval = {0, mTextHeight * (firstLine-1) - mTopPos,
mGutterWidth, mTextHeight * (lastLine - firstLine + 1)}; mGutterWidth, mTextHeight * (lastLine - firstLine + 1)};
if (mStateFlags.testFlag(StateFlag::sfLinesChanging)) { if (mStateFlags.testFlag(StateFlag::sfLinesChanging)) {
mInvalidateRect = mInvalidateRect.united(rcInval); mInvalidateRect = mInvalidateRect.united(rcInval);
@ -745,7 +744,7 @@ QPoint QSynEdit::displayCoordToPixels(const DisplayCoord &coord) const
{ {
QPoint result; QPoint result;
result.setX(coord.x + textOffset()); result.setX(coord.x + textOffset());
result.setY((coord.row - mTopLine) * mTextHeight); result.setY((coord.row-1) * mTextHeight - mTopPos);
return result; return result;
} }
@ -980,9 +979,9 @@ void QSynEdit::invalidateLine(int line)
// invalidate text area of this line // invalidate text area of this line
if (useCodeFolding()) if (useCodeFolding())
line = foldLineToRow(line); line = foldLineToRow(line);
if (line >= mTopLine && line <= mTopLine + mLinesInWindow) { if (line >= yposToRow(0) && line <= yposToRow(clientHeight())) {
rcInval = { mGutterWidth, rcInval = { mGutterWidth,
mTextHeight * (line - mTopLine), mTextHeight * (line-1) - mTopPos,
clientWidth(), clientWidth(),
mTextHeight}; mTextHeight};
if (mStateFlags.testFlag(StateFlag::sfLinesChanging)) if (mStateFlags.testFlag(StateFlag::sfLinesChanging))
@ -1026,16 +1025,14 @@ void QSynEdit::invalidateLines(int firstLine, int lastLine)
lastLine = lineToRow(lastLine + 1) - 1; lastLine = lineToRow(lastLine + 1) - 1;
} }
// mTopLine is in display coordinates, so FirstLine and LastLine must be firstLine = std::min(firstLine, yposToRow(0));
// converted previously. lastLine = std::max(lastLine, yposToRow(clientHeight()));
firstLine = std::max(firstLine, mTopLine);
lastLine = std::min(lastLine, mTopLine + mLinesInWindow);
// any line visible? // any line visible?
if (lastLine >= firstLine) { if (lastLine >= firstLine) {
QRect rcInval = { QRect rcInval = {
clientLeft()+mGutterWidth, clientLeft()+mGutterWidth,
mTextHeight * (firstLine - mTopLine), mTextHeight * (firstLine-1) - mTopPos,
clientWidth(), mTextHeight * (lastLine - firstLine + 1) clientWidth(), mTextHeight * (lastLine - firstLine + 1)
}; };
if (mStateFlags.testFlag(StateFlag::sfLinesChanging)) if (mStateFlags.testFlag(StateFlag::sfLinesChanging))
@ -1246,7 +1243,7 @@ void QSynEdit::processGutterClick(QMouseEvent *event)
QRect rect; QRect rect;
rect.setLeft(mGutterWidth - mGutter.rightOffset()); rect.setLeft(mGutterWidth - mGutter.rightOffset());
rect.setRight(rect.left() + mGutter.rightOffset() - 4); rect.setRight(rect.left() + mGutter.rightOffset() - 4);
rect.setTop((row - mTopLine) * mTextHeight); rect.setTop((row - 1) * mTextHeight - mTopPos);
rect.setBottom(rect.top() + mTextHeight - 1); rect.setBottom(rect.top() + mTextHeight - 1);
if (rect.contains(event->pos())) { if (rect.contains(event->pos())) {
if (foldRange->collapsed) if (foldRange->collapsed)
@ -1744,7 +1741,7 @@ void QSynEdit::doToggleBlockComment()
} }
void QSynEdit::doMouseScroll(bool isDragging) void QSynEdit::doMouseScroll(bool isDragging, int scrollX, int scrollY)
{ {
if (mDropped) { if (mDropped) {
mDropped=false; mDropped=false;
@ -1764,23 +1761,23 @@ void QSynEdit::doMouseScroll(bool isDragging)
iMousePos = mapFromGlobal(iMousePos); iMousePos = mapFromGlobal(iMousePos);
coord = pixelsToNearestGlyphPos(iMousePos.x(), iMousePos.y()); coord = pixelsToNearestGlyphPos(iMousePos.x(), iMousePos.y());
coord.row = minMax(coord.row, 1, displayLineCount()); coord.row = minMax(coord.row, 1, displayLineCount());
if (mScrollDeltaX != 0) { if (scrollX != 0) {
int x; int x;
setLeftPos(leftPos() + mScrollDeltaX * mMouseSelectionScrollSpeed); setLeftPos(leftPos() + scrollX * mMouseSelectionScrollSpeed);
x = leftPos(); x = leftPos();
if (mScrollDeltaX > 0) // scrolling right? if (scrollX > 0) // scrolling right?
x+=viewWidth(); x+=viewWidth();
coord.x = x; coord.x = x;
} }
if (mScrollDeltaY != 0) { if (scrollY != 0) {
int y; int y;
//qDebug()<<mScrollDeltaY; //qDebug()<<mScrollDeltaY;
if (QApplication::queryKeyboardModifiers().testFlag(Qt::ShiftModifier)) if (QApplication::queryKeyboardModifiers().testFlag(Qt::ShiftModifier))
setTopLine(mTopLine + mScrollDeltaY * mLinesInWindow); setTopPos(mTopPos + scrollY * mLinesInWindow * mTextHeight);
else else
setTopLine(mTopLine + mScrollDeltaY * mMouseSelectionScrollSpeed); setTopPos(mTopPos + scrollY * mMouseSelectionScrollSpeed * mTextHeight);
y = mTopLine; y = yposToRow(0);
if (mScrollDeltaY > 0) // scrolling down? if (scrollY > 0) // scrolling down?
y+=mLinesInWindow - 1; y+=mLinesInWindow - 1;
coord.row = minMax(y, 1, displayLineCount()); coord.row = minMax(y, 1, displayLineCount());
} }
@ -2549,15 +2546,11 @@ void QSynEdit::computeScroll(bool isDragging)
{ {
QPoint iMousePos = QCursor::pos(); QPoint iMousePos = QCursor::pos();
iMousePos = mapFromGlobal(iMousePos); iMousePos = mapFromGlobal(iMousePos);
int X=iMousePos.x(); int x=iMousePos.x();
int Y=iMousePos.y(); int y=iMousePos.y();
QRect iScrollBounds; // relative to the client area QRect iScrollBounds; // relative to the client area
int dispX=2,dispY = 2; int dispX=2,dispY = 2;
// if (isDragging) {
// dispX = mCharWidth / 2 -1;
// dispY = mTextHeight/ 2 -1;
// }
int left = mGutterWidth+frameWidth()+dispX; int left = mGutterWidth+frameWidth()+dispX;
int top = frameWidth()+dispY; int top = frameWidth()+dispY;
iScrollBounds = QRect(left, iScrollBounds = QRect(left,
@ -2565,32 +2558,22 @@ void QSynEdit::computeScroll(bool isDragging)
clientWidth()-left-dispX, clientWidth()-left-dispX,
clientHeight()-top-dispY); clientHeight()-top-dispY);
if (X < iScrollBounds.left()) int scrollX,scrollY;
mScrollDeltaX = (X - iScrollBounds.left()) / mCharWidth - 1; if (x < iScrollBounds.left())
else if (X >= iScrollBounds.right()) scrollX = (x - iScrollBounds.left()) / mCharWidth - 1;
mScrollDeltaX = (X - iScrollBounds.right()) / mCharWidth + 1; else if (x >= iScrollBounds.right())
scrollX = (x - iScrollBounds.right()) / mCharWidth + 1;
else else
mScrollDeltaX = 0; scrollX = 0;
// if (isDragging && (X<0 || X>clientRect().width())) { if (y < iScrollBounds.top())
// mScrollDeltaX = 0; scrollY = (y - iScrollBounds.top()) / mTextHeight - 1;
// } else if (y >= iScrollBounds.bottom()) {
scrollY = (y - iScrollBounds.bottom()) / mTextHeight + 1;
} else
scrollY = 0;
if (Y < iScrollBounds.top()) doMouseScroll(isDragging, scrollX, scrollY);
mScrollDeltaY = (Y - iScrollBounds.top()) / mTextHeight - 1;
else if (Y >= iScrollBounds.bottom())
mScrollDeltaY = (Y - iScrollBounds.bottom()) / mTextHeight + 1;
else
mScrollDeltaY = 0;
// if (isDragging && (Y<0 || Y>clientRect().height())) {
// mScrollDeltaY = 0;
// }
// if (mScrollDeltaX!=0 || mScrollDeltaY!=0) {
doMouseScroll(isDragging);
// }
} }
void QSynEdit::doBlockIndent() void QSynEdit::doBlockIndent()
@ -3078,15 +3061,15 @@ void QSynEdit::ensureCursorPosVisibleEx(bool ForceToMiddle)
// Make sure Y is visible // Make sure Y is visible
int vCaretRow = displayY(); int vCaretRow = displayY();
if (ForceToMiddle) { if (ForceToMiddle) {
if (vCaretRow < mTopLine || vCaretRow>(mTopLine + (mLinesInWindow - 2))) if (vCaretRow < yposToRow(0) || vCaretRow>(yposToRow(0) + (mLinesInWindow - 2)))
setTopLine( vCaretRow - (mLinesInWindow - 1) / 2); setTopPos( (vCaretRow - (mLinesInWindow - 1) / 2-1) * mTextHeight);
} else { } else {
if (vCaretRow < mTopLine) if (vCaretRow < yposToRow(0))
setTopLine(vCaretRow); setTopPos(vCaretRow);
else if (vCaretRow > mTopLine + (mLinesInWindow - 2) && mLinesInWindow > 2) { else if (vCaretRow > yposToRow(0) + (mLinesInWindow - 2) && mLinesInWindow > 2) {
setTopLine(vCaretRow - (mLinesInWindow - 2) ); setTopPos( (vCaretRow - (mLinesInWindow - 2) -1) * mTextHeight);
} else } else
setTopLine(mTopLine); setTopPos(mTopPos);
} }
} }
@ -3190,7 +3173,7 @@ void QSynEdit::updateVScrollbar()
nMin = 1; nMin = 1;
nMax = std::max(1, nMaxScroll); nMax = std::max(1, nMaxScroll);
nPage = mLinesInWindow; nPage = mLinesInWindow;
nPos = mTopLine; nPos = mTopPos;
verticalScrollBar()->setMinimum(nMin); verticalScrollBar()->setMinimum(nMin);
verticalScrollBar()->setMaximum(nMax); verticalScrollBar()->setMaximum(nMax);
verticalScrollBar()->setPageStep(nPage); verticalScrollBar()->setPageStep(nPage);
@ -3824,7 +3807,7 @@ void QSynEdit::onSizeOrFontChanged(bool bFont)
//if (!mOptions.testFlag(SynEditorOption::eoScrollPastEol)) //if (!mOptions.testFlag(SynEditorOption::eoScrollPastEol))
setLeftPos(mLeftPos); setLeftPos(mLeftPos);
//if (!mOptions.testFlag(SynEditorOption::eoScrollPastEof)) //if (!mOptions.testFlag(SynEditorOption::eoScrollPastEof))
setTopLine(mTopLine); setTopPos(mTopPos);
} }
} }
@ -3836,7 +3819,7 @@ void QSynEdit::onChanged()
void QSynEdit::onScrolled(int) void QSynEdit::onScrolled(int)
{ {
mLeftPos = horizontalScrollBar()->value(); mLeftPos = horizontalScrollBar()->value();
mTopLine = verticalScrollBar()->value(); mTopPos = verticalScrollBar()->value();
invalidate(); invalidate();
} }
@ -4101,7 +4084,7 @@ void QSynEdit::setOptions(const EditorOptions &Value)
//if (!mOptions.testFlag(eoScrollPastEol)) //if (!mOptions.testFlag(eoScrollPastEol))
setLeftPos(mLeftPos); setLeftPos(mLeftPos);
//if (!mOptions.testFlag(eoScrollPastEof)) //if (!mOptions.testFlag(eoScrollPastEof))
setTopLine(mTopLine); setTopPos(mTopPos);
bool bUpdateAll = bool bUpdateAll =
!sameEditorOption(Value,mOptions, eoShowLeadingSpaces) !sameEditorOption(Value,mOptions, eoShowLeadingSpaces)
@ -4221,7 +4204,7 @@ void QSynEdit::doUndoItem()
case ChangeReason::LeftTop: case ChangeReason::LeftTop:
BufferCoord p; BufferCoord p;
p.ch = leftPos(); p.ch = leftPos();
p.line = topLine(); p.line = topPos();
mRedoList->addRedo( mRedoList->addRedo(
item->changeReason(), item->changeReason(),
p, p,
@ -4229,7 +4212,7 @@ void QSynEdit::doUndoItem()
item->changeSelMode(), item->changeSelMode(),
item->changeNumber()); item->changeNumber());
setLeftPos(item->changeStartPos().ch); setLeftPos(item->changeStartPos().ch);
setTopLine(item->changeStartPos().line); setTopPos(item->changeStartPos().line);
break; break;
case ChangeReason::Selection: case ChangeReason::Selection:
mRedoList->addRedo( mRedoList->addRedo(
@ -4426,7 +4409,7 @@ void QSynEdit::doRedoItem()
case ChangeReason::LeftTop: case ChangeReason::LeftTop:
BufferCoord p; BufferCoord p;
p.ch = leftPos(); p.ch = leftPos();
p.line = topLine(); p.line = topPos();
mUndoList->restoreChange( mUndoList->restoreChange(
item->changeReason(), item->changeReason(),
p, p,
@ -4434,7 +4417,7 @@ void QSynEdit::doRedoItem()
item->changeSelMode(), item->changeSelMode(),
item->changeNumber()); item->changeNumber());
setLeftPos(item->changeStartPos().ch); setLeftPos(item->changeStartPos().ch);
setTopLine(item->changeStartPos().line); setTopPos(item->changeStartPos().line);
break; break;
case ChangeReason::Selection: case ChangeReason::Selection:
mUndoList->restoreChange( mUndoList->restoreChange(
@ -4952,7 +4935,8 @@ void QSynEdit::doGotoBlockStart(bool isSelection)
if (document()->blockStarted(line-1)>document()->blockEnded(line-1)) { if (document()->blockStarted(line-1)>document()->blockEnded(line-1)) {
moveCaretVert(line+1-mCaretY, isSelection); moveCaretVert(line+1-mCaretY, isSelection);
moveCaretToLineStart(isSelection); moveCaretToLineStart(isSelection);
setTopLine(line-1); line = lineToRow(line);
setTopPos((line-1)*mTextHeight);
return; return;
} }
line--; line--;
@ -4974,7 +4958,8 @@ void QSynEdit::doGotoBlockEnd(bool isSelection)
if (document()->blockEnded(line-1)>document()->blockStarted(line-1)) { if (document()->blockEnded(line-1)>document()->blockStarted(line-1)) {
moveCaretVert(line-1-mCaretY, isSelection); moveCaretVert(line-1-mCaretY, isSelection);
moveCaretToLineStart(isSelection); moveCaretToLineStart(isSelection);
setTopLine(line-mLinesInWindow+1); line = lineToRow(line) - mLinesInWindow + 1;
setTopPos((line-1)*mTextHeight);
return; return;
} }
line++; line++;
@ -5669,11 +5654,11 @@ void QSynEdit::executeCommand(EditCommand command, QChar ch, void *pData)
} }
case EditCommand::PageTop: case EditCommand::PageTop:
case EditCommand::SelPageTop: case EditCommand::SelPageTop:
moveCaretVert(mTopLine-mCaretY, command == EditCommand::SelPageTop); moveCaretVert(yposToRow(0)-mCaretY, command == EditCommand::SelPageTop);
break; break;
case EditCommand::PageBottom: case EditCommand::PageBottom:
case EditCommand::SelPageBottom: case EditCommand::SelPageBottom:
moveCaretVert(mTopLine+mLinesInWindow-1-mCaretY, command == EditCommand::SelPageBottom); moveCaretVert(yposToRow(0)+mLinesInWindow-1-mCaretY, command == EditCommand::SelPageBottom);
break; break;
case EditCommand::EditorStart: case EditCommand::EditorStart:
case EditCommand::SelEditorStart: case EditCommand::SelEditorStart:
@ -5923,9 +5908,9 @@ void QSynEdit::updateMouseCursor(){
bool QSynEdit::isCaretVisible() bool QSynEdit::isCaretVisible()
{ {
DisplayCoord caret = displayXY(); DisplayCoord caret = displayXY();
if (caret.row < mTopLine) if (caret.row < yposToRow(0))
return false; return false;
if (caret.row >= mTopLine + mLinesInWindow ) if (caret.row >= yposToRow(clientHeight()) )
return false; return false;
if (caret.x < mLeftPos) if (caret.x < mLeftPos)
return false; return false;
@ -5973,8 +5958,8 @@ void QSynEdit::paintEvent(QPaintEvent *event)
nX1 += (rcClip.left() - mGutterWidth - 2 ) ; nX1 += (rcClip.left() - mGutterWidth - 2 ) ;
nX2 = mLeftPos + (rcClip.right() - mGutterWidth - 2); nX2 = mLeftPos + (rcClip.right() - mGutterWidth - 2);
// lines // lines
nL1 = minMax(mTopLine + rcClip.top() / mTextHeight, mTopLine, displayLineCount()); nL1 = minMax(yposToRow(0) + rcClip.top() / mTextHeight, yposToRow(0), displayLineCount());
nL2 = minMax(mTopLine + (rcClip.bottom() + mTextHeight - 1) / mTextHeight, 1, displayLineCount()); nL2 = minMax(yposToRow(0) + (rcClip.bottom() + mTextHeight - 1) / mTextHeight, 1, displayLineCount());
//qDebug()<<"Paint:"<<nL1<<nL2<<nC1<<nC2; //qDebug()<<"Paint:"<<nL1<<nL2<<nC1<<nC2;
@ -6283,11 +6268,11 @@ void QSynEdit::wheelEvent(QWheelEvent *event)
mWheelAccumulatedDeltaY+=event->angleDelta().y(); mWheelAccumulatedDeltaY+=event->angleDelta().y();
while (mWheelAccumulatedDeltaY>=120) { while (mWheelAccumulatedDeltaY>=120) {
mWheelAccumulatedDeltaY-=120; mWheelAccumulatedDeltaY-=120;
verticalScrollBar()->setValue(verticalScrollBar()->value()+sign*mMouseWheelScrollSpeed); verticalScrollBar()->setValue(verticalScrollBar()->value()+sign*mMouseWheelScrollSpeed*mTextHeight);
} }
while (mWheelAccumulatedDeltaY<=-120) { while (mWheelAccumulatedDeltaY<=-120) {
mWheelAccumulatedDeltaY+=120; mWheelAccumulatedDeltaY+=120;
verticalScrollBar()->setValue(verticalScrollBar()->value()-sign*mMouseWheelScrollSpeed); verticalScrollBar()->setValue(verticalScrollBar()->value()-sign*mMouseWheelScrollSpeed*mTextHeight);
} }
if ( (mWheelAccumulatedDeltaX>0 &&event->angleDelta().x()<0) if ( (mWheelAccumulatedDeltaX>0 &&event->angleDelta().x()<0)
@ -6374,7 +6359,7 @@ void QSynEdit::dropEvent(QDropEvent *event)
// } // }
coord = ensureBufferCoordValid(coord); coord = ensureBufferCoordValid(coord);
bool lastLineUsed = coord.line == mDocument->count(); bool lastLineUsed = coord.line == mDocument->count();
int topLine = mTopLine; int topPos = mTopPos;
int leftPos = mLeftPos; int leftPos = mLeftPos;
int line=mDocument->count()-1; int line=mDocument->count()-1;
QString s=mDocument->getLine(line-1); QString s=mDocument->getLine(line-1);
@ -6429,7 +6414,7 @@ void QSynEdit::dropEvent(QDropEvent *event)
coord.ch -= mDragSelEndSave.ch-1; coord.ch -= mDragSelEndSave.ch-1;
} else { } else {
coord.line -= mDragSelEndSave.line-mDragSelBeginSave.line; coord.line -= mDragSelEndSave.line-mDragSelBeginSave.line;
topLine -= mDragSelEndSave.line-mDragSelBeginSave.line; topPos -= (mDragSelEndSave.line-mDragSelBeginSave.line) * mTextHeight;
} }
} }
} }
@ -6437,7 +6422,7 @@ void QSynEdit::dropEvent(QDropEvent *event)
endEditing(); endEditing();
event->acceptProposedAction(); event->acceptProposedAction();
mDropped = true; mDropped = true;
setTopLine(topLine); setTopPos(topPos);
setLeftPos(leftPos); setLeftPos(leftPos);
internalSetCaretXY(coord); internalSetCaretXY(coord);
} }
@ -6476,9 +6461,9 @@ void QSynEdit::dragLeaveEvent(QDragLeaveEvent *)
int QSynEdit::maxScrollHeight() const int QSynEdit::maxScrollHeight() const
{ {
if (mOptions.testFlag(eoScrollPastEof)) if (mOptions.testFlag(eoScrollPastEof))
return std::max(displayLineCount(),1); return std::max(displayLineCount(),1) * mTextHeight - 1;
else else
return std::max(displayLineCount()-mLinesInWindow+1, 1); return std::max((displayLineCount()-mLinesInWindow+1) * mTextHeight - 1 , 1) ;
} }
bool QSynEdit::modified() const bool QSynEdit::modified() const
@ -6564,8 +6549,7 @@ void QSynEdit::onLinesChanged()
mInvalidateRect = {0,0,0,0}; mInvalidateRect = {0,0,0,0};
if (mGutter.showLineNumbers() && (mGutter.autoSize())) if (mGutter.showLineNumbers() && (mGutter.autoSize()))
mGutter.autoSizeDigitCount(mDocument->count()); mGutter.autoSizeDigitCount(mDocument->count());
//if (!mOptions.testFlag(SynEditorOption::eoScrollPastEof)) setTopPos(mTopPos);
setTopLine(mTopLine);
} }
void QSynEdit::onLinesChanging() void QSynEdit::onLinesChanging()
@ -6584,7 +6568,7 @@ void QSynEdit::onLinesCleared()
// set caret and selected block to start of text // set caret and selected block to start of text
setCaretXY({1,1}); setCaretXY({1,1});
// scroll to start of text // scroll to start of text
setTopLine(1); setTopPos(0);
setLeftPos(0); setLeftPos(0);
mStatusChanges.setFlag(StatusChange::scAll); mStatusChanges.setFlag(StatusChange::scAll);
} }
@ -6714,15 +6698,19 @@ void QSynEdit::setBlockEnd(BufferCoord value)
} }
if (value.ch != mBlockEnd.ch || value.line != mBlockEnd.line) { if (value.ch != mBlockEnd.ch || value.line != mBlockEnd.line) {
if (mActiveSelectionMode == SelectionMode::Column && value.ch != mBlockEnd.ch) { if (mActiveSelectionMode == SelectionMode::Column && value.ch != mBlockEnd.ch) {
BufferCoord oldBlockEnd = mBlockEnd;
mBlockEnd = value;
invalidateLines( invalidateLines(
std::min(mBlockBegin.line, std::min(mBlockEnd.line, value.line)), std::min(mBlockBegin.line, std::min(mBlockEnd.line, oldBlockEnd.line)),
std::max(mBlockBegin.line, std::max(mBlockEnd.line, value.line))); std::max(mBlockBegin.line, std::max(mBlockEnd.line, oldBlockEnd.line)));
mBlockEnd = value;
} else { } else {
int nLine = mBlockEnd.line; BufferCoord oldBlockEnd = mBlockEnd;
mBlockEnd = value; mBlockEnd = value;
if (mActiveSelectionMode != SelectionMode::Column || mBlockBegin.ch != mBlockEnd.ch) if (mActiveSelectionMode != SelectionMode::Column || oldBlockEnd.line != mBlockEnd.line) {
invalidateLines(nLine, mBlockEnd.line); invalidateLines(
std::min(mBlockBegin.line, std::min(mBlockEnd.line, oldBlockEnd.line)),
std::max(mBlockBegin.line, std::max(mBlockEnd.line, oldBlockEnd.line)));
}
} }
setStatusChanged(StatusChange::scSelection); setStatusChanged(StatusChange::scSelection);
} }
@ -6863,22 +6851,18 @@ int QSynEdit::linesInWindow() const
return mLinesInWindow; return mLinesInWindow;
} }
int QSynEdit::topLine() const int QSynEdit::topPos() const
{ {
return mTopLine; return mTopPos;
} }
void QSynEdit::setTopLine(int Value) void QSynEdit::setTopPos(int value)
{ {
Value = std::min(Value,maxScrollHeight()); value = std::min(value,maxScrollHeight());
// if (mOptions.testFlag(SynEditorOption::eoScrollPastEof)) value = std::max(value, 1);
// Value = std::min(Value, displayLineCount()); if (value != mTopPos) {
// else verticalScrollBar()->setValue(value);
// Value = std::min(Value, displayLineCount() - mLinesInWindow + 1); setStatusChanged(StatusChange::scTopPos);
Value = std::max(Value, 1);
if (Value != mTopLine) {
verticalScrollBar()->setValue(Value);
setStatusChanged(StatusChange::scTopLine);
} }
} }

View File

@ -48,7 +48,7 @@ enum StatusChange {
scCaretX = 0x0002, scCaretX = 0x0002,
scCaretY = 0x0004, scCaretY = 0x0004,
scLeftPos = 0x0008, scLeftPos = 0x0008,
scTopLine = 0x0010, scTopPos = 0x0010,
scInsertMode = 0x0020, scInsertMode = 0x0020,
scModifyChanged = 0x0040, scModifyChanged = 0x0040,
scSelection = 0x0080, scSelection = 0x0080,
@ -176,7 +176,7 @@ public:
void invalidateGutterLines(int FirstLine, int LastLine); void invalidateGutterLines(int FirstLine, int LastLine);
int yposToRow(int y) const { int yposToRow(int y) const {
return std::max(1, mTopLine + (y / mTextHeight)); return std::max(1, ((y + mTopPos) / mTextHeight) + 1 );
} }
DisplayCoord pixelsToNearestGlyphPos(int aX, int aY) const; DisplayCoord pixelsToNearestGlyphPos(int aX, int aY) const;
@ -333,8 +333,8 @@ public:
bool isCaretVisible(); bool isCaretVisible();
// setter && getters // setter && getters
int topLine() const; int topPos() const;
void setTopLine(int value); void setTopPos(int value);
int linesInWindow() const; int linesInWindow() const;
@ -651,7 +651,7 @@ private:
void doUncomment(); void doUncomment();
void doToggleComment(); void doToggleComment();
void doToggleBlockComment(); void doToggleBlockComment();
void doMouseScroll(bool isDragging); void doMouseScroll(bool isDragging, int scrollX, int scrollY);
QString getDisplayStringAtLine(int line) const; QString getDisplayStringAtLine(int line) const;
@ -702,7 +702,7 @@ private:
QColor mRightEdgeColor; QColor mRightEdgeColor;
ScrollStyle mScrollBars; ScrollStyle mScrollBars;
int mTextHeight; int mTextHeight;
int mTopLine; int mTopPos;
PSyntaxer mSyntaxer; PSyntaxer mSyntaxer;
QColor mSelectedForeground; QColor mSelectedForeground;
QColor mSelectedBackground; QColor mSelectedBackground;
@ -742,8 +742,6 @@ private:
// fFocusList: TList; // fFocusList: TList;
// fPlugins: TList; // fPlugins: TList;
QTimer* mScrollTimer; QTimer* mScrollTimer;
int mScrollDeltaX;
int mScrollDeltaY;
PSynEdit fChainedEditor; PSynEdit fChainedEditor;