* work save
This commit is contained in:
parent
c7a7f69285
commit
101302255b
|
@ -3,4 +3,7 @@ const QSet<QChar> SynWordBreakChars{'.', ',', ';', ':',
|
|||
'"', '\'', '!', '?', '[', ']', '(', ')', '{', '}', '^', '-', '=', '+',
|
||||
'-', '*', '/', '\\', '|'};
|
||||
const QChar SynTabChar('\t');
|
||||
const QChar SynSpaceGlyph(' ');
|
||||
const QChar SynTabGlyph(0x2192);
|
||||
const QChar SynSpaceGlyph('.');
|
||||
const QChar SynLineBreakGlyph(0x2193);
|
||||
const QChar SynSoftBreakGlyph(0x2193);
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
extern const QSet<QChar> SynWordBreakChars;
|
||||
extern const QChar SynTabChar;
|
||||
extern const QChar SynSpaceGlyph;
|
||||
extern const QChar SynTabGlyph;
|
||||
extern const QChar SynLineBreakGlyph;
|
||||
extern const QChar SynSoftBreakGlyph;
|
||||
|
||||
|
||||
#define MAX_SCROLL 65535
|
||||
|
||||
|
|
|
@ -56,6 +56,19 @@ void SynGutter::setChanged()
|
|||
emit changed();
|
||||
}
|
||||
|
||||
QColor SynGutter::textColor() const
|
||||
{
|
||||
return mTextColor;
|
||||
}
|
||||
|
||||
void SynGutter::setTextColor(const QColor &value)
|
||||
{
|
||||
if (mTextColor!=value) {
|
||||
mTextColor = value;
|
||||
setChanged();
|
||||
}
|
||||
}
|
||||
|
||||
int SynGutter::width() const
|
||||
{
|
||||
return mWidth;
|
||||
|
|
|
@ -76,6 +76,9 @@ public:
|
|||
QString formatLineNumber(int line);
|
||||
int realGutterWidth(int charWidth);
|
||||
|
||||
QColor textColor() const;
|
||||
void setTextColor(const QColor &value);
|
||||
|
||||
signals:
|
||||
void changed();
|
||||
private:
|
||||
|
@ -83,6 +86,7 @@ private:
|
|||
private:
|
||||
bool mAutoSize;
|
||||
QColor mBorderColor;
|
||||
QColor mTextColor;
|
||||
QColor mColor;
|
||||
int mDigitCount;
|
||||
QFont mFont;
|
||||
|
|
|
@ -254,7 +254,7 @@ void SynEdit::invalidateGutterLines(int FirstLine, int LastLine)
|
|||
if (!isVisible())
|
||||
return;
|
||||
if (FirstLine == -1 && LastLine == -1) {
|
||||
rcInval = QRect(clientLeft(), clientTop(), mGutterWidth, clientHeight());
|
||||
rcInval = QRect(0, 0, mGutterWidth, clientHeight());
|
||||
if (mStateFlags.testFlag(SynStateFlag::sfLinesChanging))
|
||||
mInvalidateRect = mInvalidateRect.united(rcInval);
|
||||
else
|
||||
|
@ -274,7 +274,7 @@ void SynEdit::invalidateGutterLines(int FirstLine, int LastLine)
|
|||
LastLine = std::min(LastLine, mTopLine + mLinesInWindow);
|
||||
// any line visible?
|
||||
if (LastLine >= FirstLine) {
|
||||
rcInval = {clientLeft(), clientTop()+mTextHeight * (FirstLine - mTopLine),
|
||||
rcInval = {0, mTextHeight * (FirstLine - mTopLine),
|
||||
mGutterWidth, mTextHeight * (LastLine - mTopLine + 1)};
|
||||
if (mStateFlags.testFlag(SynStateFlag::sfLinesChanging)) {
|
||||
mInvalidateRect = mInvalidateRect.united(rcInval);
|
||||
|
@ -379,22 +379,38 @@ int SynEdit::charToColumn(int aLine, int aChar)
|
|||
throw BaseError(SynEdit::tr("Line %1 is out of range").arg(aLine));
|
||||
}
|
||||
|
||||
int SynEdit::stringColumns(const QString &line)
|
||||
int SynEdit::stringColumns(const QString &line, int colsBefore)
|
||||
{
|
||||
int columns = 0;
|
||||
if (!line.isEmpty()) {
|
||||
int charCols;
|
||||
for (int i=0;i<line.length();i++) {
|
||||
QChar ch = line[i];
|
||||
if (ch == '\t') {
|
||||
charCols = mTabWidth - columns % mTabWidth;
|
||||
} else {
|
||||
charCols = charColumns(ch);
|
||||
}
|
||||
columns+=charCols;
|
||||
int columns = colsBefore;
|
||||
int charCols;
|
||||
for (int i=0;i<line.length();i++) {
|
||||
QChar ch = line[i];
|
||||
if (ch == '\t') {
|
||||
charCols = mTabWidth - columns % mTabWidth;
|
||||
} else {
|
||||
charCols = charColumns(ch);
|
||||
}
|
||||
columns+=charCols;
|
||||
}
|
||||
return columns-colsBefore;
|
||||
}
|
||||
|
||||
int SynEdit::getLineIndent(const QString &line)
|
||||
{
|
||||
int indents = 0;
|
||||
for (QChar ch:line) {
|
||||
switch(ch.digitValue()) {
|
||||
case '\t':
|
||||
indents+=mTabWidth;
|
||||
break;
|
||||
case ' ':
|
||||
indents+=1;
|
||||
break;
|
||||
default:
|
||||
return indents;
|
||||
}
|
||||
}
|
||||
return columns;
|
||||
return indents;
|
||||
}
|
||||
|
||||
int SynEdit::rowToLine(int aRow)
|
||||
|
@ -576,6 +592,8 @@ void SynEdit::clearUndo()
|
|||
|
||||
int SynEdit::charColumns(QChar ch)
|
||||
{
|
||||
if (ch == ' ')
|
||||
return 1;
|
||||
return std::ceil(fontMetrics().horizontalAdvance(ch) * dpiFactor() / mCharWidth);
|
||||
}
|
||||
|
||||
|
@ -751,7 +769,7 @@ int SynEdit::clientLeft()
|
|||
|
||||
QRect SynEdit::clientRect()
|
||||
{
|
||||
return QRect(clientLeft(),clientTop(), clientWidth(), clientHeight());
|
||||
return QRect(0,0, clientWidth(), clientHeight());
|
||||
}
|
||||
|
||||
void SynEdit::synFontChanged()
|
||||
|
@ -1274,6 +1292,83 @@ void SynEdit::initializeCaret()
|
|||
//todo:
|
||||
}
|
||||
|
||||
PSynEditFoldRange SynEdit::foldStartAtLine(int Line)
|
||||
{
|
||||
for (int i = 0; i<mAllFoldRanges.count();i++) {
|
||||
PSynEditFoldRange range = mAllFoldRanges[i];
|
||||
if (range->fromLine == Line ){
|
||||
return range;
|
||||
} else if (range->fromLine>Line)
|
||||
break; // sorted by line. don't bother scanning further
|
||||
}
|
||||
}
|
||||
|
||||
QString SynEdit::substringByColumns(const QString &s, int startColumn, int &colLen)
|
||||
{
|
||||
|
||||
int len = s.length();
|
||||
int columns = 0;
|
||||
int i = 0;
|
||||
int oldColumns;
|
||||
while (columns < startColumn) {
|
||||
oldColumns = columns;
|
||||
if (i < len && s[i] == '\t')
|
||||
columns += mTabWidth - (columns % mTabWidth);
|
||||
else
|
||||
columns += charColumns(s[i]);
|
||||
i++;
|
||||
}
|
||||
QString result;
|
||||
if (i>=len) {
|
||||
colLen = 0;
|
||||
return result;
|
||||
}
|
||||
if (colLen>result.capacity()) {
|
||||
result.resize(colLen);
|
||||
}
|
||||
int j=0;
|
||||
if (i>0) {
|
||||
result[0]=s[i-1];
|
||||
j++;
|
||||
}
|
||||
while (i<len && columns<startColumn+colLen) {
|
||||
result[j]=s[i];
|
||||
if (i < len && s[i] == '\t')
|
||||
columns += mTabWidth - (columns % mTabWidth);
|
||||
else
|
||||
columns += charColumns(s[i]);
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
result.resize(j);
|
||||
colLen = columns-oldColumns;
|
||||
return result;
|
||||
}
|
||||
|
||||
PSynEditFoldRange SynEdit::foldAroundLine(int Line)
|
||||
{
|
||||
return foldAroundLineEx(Line,false,false,false);
|
||||
}
|
||||
|
||||
PSynEditFoldRange SynEdit::foldAroundLineEx(int Line, bool WantCollapsed, bool AcceptFromLine, bool AcceptToLine)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
PSynEditFoldRange SynEdit::CheckFoldRange(PSynEditFoldRanges FoldRangeToCheck, int Line, bool WantCollapsed, bool AcceptFromLine, bool AcceptToLine)
|
||||
{
|
||||
for (int i = 0; i< FoldRangeToCheck->count(); i++) {
|
||||
PSynEditFoldRange range = (*FoldRangeToCheck)[i];
|
||||
if (((range->fromLine < Line) || ((range->fromLine <= Line) && AcceptFromLine)) &&
|
||||
((range->toLine > Line) || ((range->toLine >= Line) && AcceptToLine))) {
|
||||
if (range->collapsed == WantCollapsed) {
|
||||
return range;
|
||||
}
|
||||
}
|
||||
}
|
||||
return PSynEditFoldRange();
|
||||
}
|
||||
|
||||
void SynEdit::sizeOrFontChanged(bool bFont)
|
||||
{
|
||||
if (mCharWidth != 0) {
|
||||
|
@ -1307,6 +1402,16 @@ int SynEdit::tabWidth() const
|
|||
return mTabWidth;
|
||||
}
|
||||
|
||||
bool SynEdit::onSpecialLineColors(int, QColor &, QColor &)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SynEdit::onEditingAreas(int, SynEditingAreaList &)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SynEdit::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
if (mPainterLock>0)
|
||||
|
@ -1320,10 +1425,10 @@ void SynEdit::paintEvent(QPaintEvent *event)
|
|||
rcClip = event->rect();
|
||||
// columns
|
||||
nC1 = mLeftChar;
|
||||
if (rcClip.left() > mGutterWidth + 2 + clientLeft())
|
||||
nC1 += (rcClip.left() - mGutterWidth - 2 - clientLeft()) % mCharWidth;
|
||||
if (rcClip.left() > mGutterWidth + 2 )
|
||||
nC1 += (rcClip.left() - mGutterWidth - 2 ) % mCharWidth;
|
||||
nC2 = mLeftChar +
|
||||
(rcClip.right() - mGutterWidth - 2 - clientLeft() + mCharWidth - 1) % mCharWidth;
|
||||
(rcClip.right() - mGutterWidth - 2 + mCharWidth - 1) % mCharWidth;
|
||||
// lines
|
||||
nL1 = MinMax(mTopLine + rcClip.top() % mTextHeight, mTopLine, displayLineCount());
|
||||
nL2 = MinMax(mTopLine + (rcClip.bottom() + mTextHeight - 1) % mTextHeight, 1, displayLineCount());
|
||||
|
@ -1336,23 +1441,23 @@ void SynEdit::paintEvent(QPaintEvent *event)
|
|||
});
|
||||
|
||||
// First paint paint the text area if it was (partly) invalidated.
|
||||
if (rcClip.right() > mGutterWidth + clientLeft()) {
|
||||
if (rcClip.right() > mGutterWidth ) {
|
||||
rcDraw = rcClip;
|
||||
rcDraw.setLeft( std::max(rcDraw.left(), mGutterWidth + clientLeft()));
|
||||
rcDraw.setLeft( std::max(rcDraw.left(), mGutterWidth));
|
||||
paintTextLines(rcDraw, nL1, nL2, nC1, nC2);
|
||||
}
|
||||
|
||||
// Then the gutter area if it was (partly) invalidated.
|
||||
if (rcClip.left() < clientLeft() + mGutterWidth) {
|
||||
if (rcClip.left() < mGutterWidth) {
|
||||
rcDraw = rcClip;
|
||||
rcDraw.setRight(clientLeft() + mGutterWidth);
|
||||
rcDraw.setRight(mGutterWidth);
|
||||
paintGutter(rcDraw, nL1, nL2);
|
||||
}
|
||||
|
||||
//PluginsAfterPaint(Canvas, rcClip, nL1, nL2);
|
||||
// If there is a custom paint handler call it.
|
||||
doOnPaint();
|
||||
doOnPaintTransient(SynTransientType:: ttAfter);
|
||||
doOnPaintTransient(SynTransientType::ttAfter);
|
||||
}
|
||||
|
||||
int SynEdit::maxScrollWidth() const
|
||||
|
|
|
@ -125,12 +125,12 @@ using SynPreparePaintHighlightTokenProc = std::function<void(int row,
|
|||
SynFontStyles& style, QColor& foreground, QColor& background)>;
|
||||
using SynReplaceTextProc = std::function<void(const QString& ASearch, const QString& AReplace,
|
||||
int Line, int Column, int wordLen, SynReplaceAction& action)>;
|
||||
using SynSpecialLineColorsProc = std::function<void(int Line,
|
||||
bool& Special, QColor& foreground, QColor& backgroundColor)>;
|
||||
using SynEditingAreasProc = std::function<void(int Line, SynEditingAreaList& areaList,
|
||||
QColor& borderColor,SynEditingAreaType& areaType)>;
|
||||
using SynGutterGetTextProc = std::function<void(int aLine, QString& aText)>;
|
||||
using SynTGutterPaintProc = std::function<void(int aLine, int X, int Y)>;
|
||||
//using SynSpecialLineColorsProc = std::function<void(int Line,
|
||||
// bool& Special, QColor& foreground, QColor& backgroundColor)>;
|
||||
//using SynEditingAreasProc = std::function<void(int Line, SynEditingAreaList& areaList,
|
||||
// QColor& borderColor,SynEditingAreaType& areaType)>;
|
||||
//using SynGutterGetTextProc = std::function<void(int aLine, QString& aText)>;
|
||||
//using SynTGutterPaintProc = std::function<void(int aLine, int X, int Y)>;
|
||||
|
||||
class SynEdit;
|
||||
using PSynEdit = std::shared_ptr<SynEdit>;
|
||||
|
@ -163,7 +163,8 @@ public:
|
|||
DisplayCoord bufferToDisplayPos(const BufferCoord& p);
|
||||
BufferCoord displayToBufferPos(const DisplayCoord& p);
|
||||
int charToColumn(int aLine, int aChar);
|
||||
int stringColumns(const QString& line);
|
||||
int stringColumns(const QString& line, int colsBefore);
|
||||
int getLineIndent(const QString& line);
|
||||
int rowToLine(int aRow);
|
||||
int lineToRow(int aLine);
|
||||
int foldRowToLine(int Row);
|
||||
|
@ -241,6 +242,15 @@ signals:
|
|||
void fontChanged();
|
||||
void tabSizeChanged();
|
||||
|
||||
protected:
|
||||
virtual bool onSpecialLineColors(int Line,
|
||||
QColor& foreground, QColor& backgroundColor) ;
|
||||
virtual void onEditingAreas(int Line, SynEditingAreaList& areaList);
|
||||
virtual void onGutterGetText(int aLine, QString& aText);
|
||||
virtual void onGutterPaint(int aLine, int X, int Y);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
void clearAreaList(SynEditingAreaList areaList);
|
||||
void computeCaret(int X, int Y);
|
||||
|
@ -287,6 +297,11 @@ private:
|
|||
const QString& Value, bool AddToUndoList);
|
||||
void doOnPaintTransientEx(SynTransientType TransientType, bool Lock);
|
||||
void initializeCaret();
|
||||
PSynEditFoldRange foldStartAtLine(int Line);
|
||||
QString substringByColumns(const QString& s, int startColumn, int& colLen);
|
||||
PSynEditFoldRange foldAroundLine(int Line);
|
||||
PSynEditFoldRange foldAroundLineEx(int Line, bool WantCollapsed, bool AcceptFromLine, bool AcceptToLine);
|
||||
PSynEditFoldRange CheckFoldRange(PSynEditFoldRanges FoldRangeToCheck,int Line, bool WantCollapsed, bool AcceptFromLine, bool AcceptToLine);
|
||||
|
||||
private slots:
|
||||
void bookMarkOptionsChanged();
|
||||
|
@ -400,10 +415,10 @@ private:
|
|||
SynProcessCommandProc mOnProcessingUserCommand;
|
||||
|
||||
SynReplaceTextProc mOnReplaceText;
|
||||
SynSpecialLineColorsProc mOnSpecialLineColors;
|
||||
SynEditingAreasProc mOnEditingAreas;
|
||||
SynGutterGetTextProc mOnGutterGetText;
|
||||
SynTGutterPaintProc mOnGutterPaint;
|
||||
// SynSpecialLineColorsProc mOnSpecialLineColors;
|
||||
// SynEditingAreasProc mOnEditingAreas;
|
||||
// SynGutterGetTextProc mOnGutterGetText;
|
||||
// SynTGutterPaintProc mOnGutterPaint;
|
||||
int mGutterWidth;
|
||||
|
||||
//caret blink related
|
||||
|
@ -418,6 +433,4 @@ protected:
|
|||
friend class SynEditTextPainter;
|
||||
};
|
||||
|
||||
class
|
||||
|
||||
#endif // SYNEDIT_H
|
||||
|
|
|
@ -379,7 +379,7 @@ int SynEditStringList::calculateLineColumns(int Index)
|
|||
{
|
||||
PSynEditStringRec line = mList[Index];
|
||||
|
||||
line->fColumns = mEdit->stringColumns(line->fString);
|
||||
line->fColumns = mEdit->stringColumns(line->fString,0);
|
||||
return line->fColumns;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,9 +3,276 @@
|
|||
#include "Constants.h"
|
||||
#include <cmath>
|
||||
|
||||
SynEditTextPainter::SynEditTextPainter(SynEdit *edit)
|
||||
SynEditTextPainter::SynEditTextPainter(SynEdit *edit, int FirstRow, int LastRow, int FirstCol, int LastCol)
|
||||
{
|
||||
this->edit = edit;
|
||||
this->aFirstRow = FirstRow;
|
||||
this->aLastRow = LastRow;
|
||||
this->FirstCol = FirstCol;
|
||||
this->LastCol = LastCol;
|
||||
}
|
||||
|
||||
void SynEditTextPainter::paintTextLines(const QRect& clip)
|
||||
{
|
||||
AClip = clip;
|
||||
vFirstLine = edit->rowToLine(aFirstRow);
|
||||
vLastLine = edit->rowToLine(aLastRow);
|
||||
bCurrentLine = false;
|
||||
// If the right edge is visible and in the invalid area, prepare to paint it.
|
||||
// Do this first to realize the pen when getting the dc variable.
|
||||
QString SynTabGlyphString = SynTabGlyph;
|
||||
bDoRightEdge = false;
|
||||
if (edit->mRightEdge > 0) { // column value
|
||||
nRightEdge = edit->mTextOffset + edit->mRightEdge * edit->mCharWidth; // pixel value
|
||||
if (nRightEdge >= AClip.left() &&nRightEdge <= AClip.right()) {
|
||||
bDoRightEdge = true;
|
||||
QPen pen(edit->mRightEdgeColor,1);
|
||||
painter->setPen(pen);
|
||||
}
|
||||
}
|
||||
|
||||
// Paint the visible text lines. To make this easier, compute first the
|
||||
// necessary information about the selected area: is there any visible
|
||||
// selected area, and what are its lines / columns?
|
||||
if (vLastLine >= vFirstLine) {
|
||||
ComputeSelectionInfo();
|
||||
PaintLines();
|
||||
}
|
||||
|
||||
// If anything of the two pixel space before the text area is visible, then
|
||||
// fill it with the component background color.
|
||||
if (AClip.left() < edit->clientLeft()+ edit->mGutterWidth + 2) {
|
||||
rcToken = AClip;
|
||||
rcToken.setLeft( std::max(AClip.left(), edit->mGutterWidth));
|
||||
rcToken.setRight(edit->mGutterWidth + 2);
|
||||
// Paint whole left edge of the text with same color.
|
||||
// (value of WhiteAttribute can vary in e.g. MultiSyn)
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(colEditorBG());
|
||||
painter->drawRect(rcToken);
|
||||
// Adjust the invalid area to not include this area.
|
||||
AClip.setLeft(rcToken.right());
|
||||
}
|
||||
// If there is anything visible below the last line, then fill this as well.
|
||||
rcToken = AClip;
|
||||
rcToken.setTop((aLastRow - edit->mTopLine + 1) * edit->mTextHeight);
|
||||
if (rcToken.top() < rcToken.bottom()) {
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(colEditorBG());
|
||||
painter->drawRect(rcToken);
|
||||
// Draw the right edge if necessary.
|
||||
if (bDoRightEdge) {
|
||||
QPen pen(edit->mRightEdgeColor,1);
|
||||
painter->setPen(pen);
|
||||
painter->drawLine(nRightEdge, rcToken.top(),nRightEdge, rcToken.bottom() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// This messes with pen colors, so draw after right margin has been drawn
|
||||
PaintFoldAttributes();
|
||||
}
|
||||
|
||||
void SynEditTextPainter::paintGutter(const QRect& clip)
|
||||
{
|
||||
int cRow;
|
||||
int cMark;
|
||||
QRect rcLine, rcFold;
|
||||
QList<int> aGutterOffs;
|
||||
bool bHasOtherMarks;
|
||||
QString s;
|
||||
int vFirstLine;
|
||||
int vLastLine;
|
||||
int vLine;
|
||||
int vMarkRow;
|
||||
int vGutterRow;
|
||||
int vLineTop;
|
||||
QSize TextSize;
|
||||
int x;
|
||||
PSynEditFoldRange FoldRange;
|
||||
|
||||
AClip = clip;
|
||||
|
||||
//todo: Does the following comment still apply?
|
||||
// Changed to use fTextDrawer.BeginDrawing and fTextDrawer.EndDrawing only
|
||||
// when absolutely necessary. Note: Never change brush / pen / font of the
|
||||
// canvas inside of this block (only through methods of fTextDrawer)!
|
||||
// If we have to draw the line numbers then we don't want to erase
|
||||
// the background first. Do it line by line with TextRect instead
|
||||
// and fill only the area after the last visible line.
|
||||
painter->setBrush(edit->mGutter.color());
|
||||
painter->setPen(Qt::NoPen);
|
||||
rcLine=AClip;
|
||||
|
||||
painter->drawRect(AClip);
|
||||
|
||||
if (edit->mGutter.showLineNumbers()) {
|
||||
if (edit->mGutter.useFontStyle()) {
|
||||
painter->setFont(edit->mGutter.font());
|
||||
painter->setPen(edit->mGutter.textColor());
|
||||
} else {
|
||||
painter->setPen(edit->palette().color(QPalette::Text));
|
||||
}
|
||||
painter->setBrush(edit->mGutter.color());
|
||||
|
||||
// prepare the rect initially
|
||||
rcLine = AClip;
|
||||
rcLine.setRight( std::max(rcLine.right(), edit->mGutterWidth - 2));
|
||||
rcLine.setBottom(rcLine.top());
|
||||
painter->drawRect(AClip);
|
||||
|
||||
// draw each line if it is not hidden by a fold
|
||||
for (int cRow = aFirstRow; cRow <= aLastRow; cRow++) {
|
||||
vLine = edit->rowToLine(cRow);
|
||||
if ((vLine > edit->mLines->count()) && (edit->mLines->count() > 0 ))
|
||||
break;
|
||||
vLineTop = (cRow - edit->mTopLine) * edit->mTextHeight;
|
||||
|
||||
// next line rect
|
||||
rcLine.setTop(vLineTop);
|
||||
rcLine.setBottom(rcLine.top() + edit->mTextHeight);
|
||||
|
||||
s = edit->mGutter.formatLineNumber(vLine);
|
||||
|
||||
if (edit->mOnGutterGetText) {
|
||||
edit->mOnGutterGetText(vLine,s);
|
||||
}
|
||||
|
||||
QRectF textRect;
|
||||
textRect = painter->boundingRect(textRect, Qt::AlignLeft,s);
|
||||
painter->drawText(
|
||||
(edit->mGutterWidth - edit->mGutter.rightOffset() - 2) - textRect.width(),
|
||||
rcLine.top() + ((edit->mTextHeight - int(textRect.height())) % 2),
|
||||
s
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the folding lines and squares
|
||||
if (edit->mUseCodeFolding) {
|
||||
for (cRow = aFirstRow; cRow<=aLastRow; cRow++) {
|
||||
vLine = edit->rowToLine(cRow);
|
||||
if ((vLine > edit->mLines->count()) && (edit->mLines->count() != 0))
|
||||
break;
|
||||
|
||||
// Form a rectangle for the square the user can click on
|
||||
//rcFold.Left := Gutter.RealGutterWidth(CharWidth) - Gutter.RightOffset;
|
||||
rcFold.setLeft(edit->mGutterWidth - edit->mGutter.rightOffset());
|
||||
rcFold.setRight(rcFold.left() + edit->mGutter.rightOffset() - 4);
|
||||
rcFold.setTop((cRow - edit->mTopLine) * edit->mTextHeight);
|
||||
rcFold.setBottom(rcFold.top() + edit->mTextHeight);
|
||||
|
||||
painter->setPen(edit->mCodeFolding.folderBarLinesColor);
|
||||
|
||||
|
||||
// Need to paint a line?
|
||||
if (edit->foldAroundLine(vLine)) {
|
||||
x = rcFold.left() + (rcFold.width() % 2);
|
||||
painter->drawLine(x,rcFold.top(), x, rcFold.bottom());
|
||||
}
|
||||
|
||||
// Need to paint a line end?
|
||||
if (edit->foldEndAtLine(vLine)) {
|
||||
x = rcFold.left() + (rcFold.width() % 2);
|
||||
painter->drawLine(x,rcFold.top(), x, rcFold.top() + rcFold.height() % 2);
|
||||
painter->drawLine(x,
|
||||
rcFold.top() + rcFold.height() % 2,
|
||||
rcFold.right() - 2 ,
|
||||
rcFold.top() + rcFold.height() % 2);
|
||||
}
|
||||
// Any fold ranges beginning on this line?
|
||||
FoldRange = edit->foldStartAtLine(vLine);
|
||||
if (FoldRange) {
|
||||
// Draw the bottom part of a line
|
||||
if (!FoldRange->collapsed) {
|
||||
x = rcFold.left() + (rcFold.width() % 2);
|
||||
painter->drawLine(x, rcFold.top() + rcFold.height() % 2,
|
||||
x, rcFold.bottom());
|
||||
}
|
||||
|
||||
// make a square rect
|
||||
inflateRect(rcFold,-2, 0);
|
||||
rcFold.setTop(
|
||||
rcFold.top() + ((edit->mTextHeight - rcFold.width()) % 2));
|
||||
rcFold.setBottom(rcFold.top() + rcFold.width());
|
||||
|
||||
// Paint the square the user can click on
|
||||
painter->setBrush(edit->mGutter.color());
|
||||
painter->setPen(edit->mCodeFolding.folderBarLinesColor);
|
||||
painter->drawRect(rcFold);
|
||||
|
||||
// Paint minus sign
|
||||
painter->drawLine(
|
||||
rcFold.left() + 2, rcFold.top() + (rcFold.height() % 2 ),
|
||||
rcFold.right() - 2, rcFold.top() + (rcFold.height() % 2 ));
|
||||
// Paint vertical line of plus sign
|
||||
if (FoldRange->collapsed) {
|
||||
x = rcFold.left() + (rcFold.width() % 2);
|
||||
painter->drawLine(x, rcFold.top() + 2,
|
||||
x, rcFold.bottom() + 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// // the gutter separator if visible
|
||||
// if (edit->mGutter.borderStyle <> gbsNone) and (AClip.Right >= fGutterWidth - 2) then
|
||||
// with Canvas do begin
|
||||
// Pen.Color := fGutter.BorderColor;
|
||||
// Pen.Width := 1;
|
||||
// with AClip do begin
|
||||
// if fGutter.BorderStyle = gbsMiddle then begin
|
||||
// MoveTo(fGutterWidth - 2, Top);
|
||||
// LineTo(fGutterWidth - 2, Bottom);
|
||||
// Pen.Color := fGutter.Color;
|
||||
// end;
|
||||
// MoveTo(fGutterWidth - 1, Top);
|
||||
// LineTo(fGutterWidth - 1, Bottom);
|
||||
// end;
|
||||
// end;
|
||||
|
||||
// // now the gutter marks
|
||||
// if BookMarkOptions.GlyphsVisible and (Marks.Count > 0) and (aLastRow >= aFirstRow) then begin
|
||||
// aGutterOffs := AllocMem((aLastRow - aFirstRow + 1) * SizeOf(integer));
|
||||
// vFirstLine := RowToLine(aFirstRow);
|
||||
// vLastLine := RowToLine(aLastRow);
|
||||
// try
|
||||
// // Instead of making a two pass loop we look while drawing the bookmarks
|
||||
// // whether there is any other mark to be drawn
|
||||
// bHasOtherMarks := FALSE;
|
||||
// for cMark := 0 to Marks.Count - 1 do
|
||||
// with Marks[cMark] do
|
||||
// if Visible and (Line >= vFirstLine) and (Line <= vLastLine) then begin
|
||||
// if IsBookmark <> BookMarkOptions.DrawBookmarksFirst then
|
||||
// bHasOtherMarks := TRUE
|
||||
// else begin
|
||||
// vMarkRow := LineToRow(Line);
|
||||
// if vMarkRow >= aFirstRow then
|
||||
// DrawMark(Marks[cMark], aGutterOffs[vMarkRow - aFirstRow], vMarkRow);
|
||||
// end
|
||||
// end;
|
||||
// if bHasOtherMarks then
|
||||
// for cMark := 0 to Marks.Count - 1 do
|
||||
// with Marks[cMark] do begin
|
||||
// if Visible and (IsBookmark <> BookMarkOptions.DrawBookmarksFirst)
|
||||
// and (Line >= vFirstLine) and (Line <= vLastLine) then begin
|
||||
// vMarkRow := LineToRow(Line);
|
||||
// if vMarkRow >= aFirstRow then
|
||||
// DrawMark(Marks[cMark], aGutterOffs[vMarkRow - aFirstRow], vMarkRow);
|
||||
// end;
|
||||
// end;
|
||||
// if Assigned(OnGutterPaint) then
|
||||
// for cRow := aFirstRow to aLastRow do begin
|
||||
// OnGutterPaint(Self, cRow, aGutterOffs[cRow - aFirstRow],
|
||||
// (vGutterRow - TopLine) * LineHeight);
|
||||
// end;
|
||||
// finally
|
||||
// FreeMem(aGutterOffs);
|
||||
// end;
|
||||
// end;
|
||||
for (cRow = aFirstRow; cRow <=aLastRow; cRow++) {
|
||||
vLine = edit->rowToLine(cRow);
|
||||
edit->onGutterPaint(vLine, 0, (cRow - edit->mTopLine) * edit->mTextHeight);
|
||||
}
|
||||
}
|
||||
|
||||
QColor SynEditTextPainter::colEditorBG()
|
||||
|
@ -127,7 +394,7 @@ void SynEditTextPainter::PaintToken(const QString &Token, int TokenCols, int Col
|
|||
}
|
||||
}
|
||||
|
||||
void SynEditTextPainter::PaintEditAreas(PSynEditingAreaList areaList)
|
||||
void SynEditTextPainter::PaintEditAreas(const SynEditingAreaList &areaList)
|
||||
{
|
||||
QRect rc;
|
||||
int x1,x2;
|
||||
|
@ -136,7 +403,7 @@ void SynEditTextPainter::PaintEditAreas(PSynEditingAreaList areaList)
|
|||
rc=rcLine;
|
||||
rc.setBottom(rc.bottom()-1);
|
||||
setDrawingColors(false);
|
||||
for (PSynEditingArea p:*areaList) {
|
||||
for (PSynEditingArea p:areaList) {
|
||||
if (p->beginX > LastCol)
|
||||
continue;
|
||||
if (p->endX < FirstCol)
|
||||
|
@ -393,7 +660,7 @@ void SynEditTextPainter::PaintFoldAttributes()
|
|||
LastNonBlank = vLine - 1;
|
||||
while (LastNonBlank + 1 < edit->mLines->count() && edit->mLines->getString(LastNonBlank).trimmed().isEmpty())
|
||||
LastNonBlank++;
|
||||
LineIndent = edit->GetLineIndent(edit->mLines->getString(LastNonBlank));
|
||||
LineIndent = edit->getLineIndent(edit->mLines->getString(LastNonBlank));
|
||||
// Step horizontal coord
|
||||
TabSteps = edit->mTabWidth;
|
||||
while (TabSteps < LineIndent) {
|
||||
|
@ -408,7 +675,7 @@ void SynEditTextPainter::PaintFoldAttributes()
|
|||
}
|
||||
|
||||
if (!edit->mUseCodeFolding)
|
||||
exit;
|
||||
return;
|
||||
|
||||
// Paint collapsed lines using changed pen
|
||||
if (edit->mCodeFolding.showCollapsedLine) {
|
||||
|
@ -450,11 +717,11 @@ void SynEditTextPainter::PaintLines()
|
|||
int vLine;
|
||||
QString sLine; // the current line
|
||||
QString sToken; // highlighter token info
|
||||
int nTokenPos, nTokenLen;
|
||||
int nTokenStartColumn, nTokenColumnLen;
|
||||
PSynHighlighterAttribute attr;
|
||||
int vFirstChar;
|
||||
int vLastChar;
|
||||
PSynEditingAreaList areaList;
|
||||
SynEditingAreaList areaList;
|
||||
QColor colBorder;
|
||||
PSynEditFoldRange foldRange;
|
||||
int nC1,nC2,nFold;
|
||||
|
@ -480,7 +747,7 @@ void SynEditTextPainter::PaintLines()
|
|||
// use special values for them.
|
||||
colFG = edit->palette().color(QPalette::Text);
|
||||
colBG = colEditorBG();
|
||||
bSpecialLine = edit->DoOnSpecialLineColors(vLine, colFG, colBG);
|
||||
bSpecialLine = edit->onSpecialLineColors(vLine, colFG, colBG);
|
||||
if (bSpecialLine) {
|
||||
// The selection colors are just swapped, like seen in Delphi.
|
||||
colSelFG = colBG;
|
||||
|
@ -489,7 +756,7 @@ void SynEditTextPainter::PaintLines()
|
|||
colSelFG = edit->mSelectedForeground;
|
||||
colSelBG = edit->mSelectedBackground;
|
||||
}
|
||||
edit->DoOnEditAreas(vLine, areaList);
|
||||
edit->onEditingAreas(vLine, areaList);
|
||||
// Removed word wrap support
|
||||
vFirstChar = FirstCol;
|
||||
vLastChar = LastCol;
|
||||
|
@ -536,26 +803,26 @@ void SynEditTextPainter::PaintLines()
|
|||
rcToken = rcLine;
|
||||
if (!edit->mHighlighter || !edit->mHighlighter->enabled()) {
|
||||
sToken = sLine;
|
||||
nTokenLen = edit->mLines->lineColumns(vLine-1);
|
||||
if (edit->mShowSpecChar && (!bLineSelected) && (!bSpecialLine) && (nTokenLen < vLastChar)) {
|
||||
nTokenColumnLen = edit->mLines->lineColumns(vLine-1);
|
||||
if (edit->mShowSpecChar && (!bLineSelected) && (!bSpecialLine) && (nTokenColumnLen < vLastChar)) {
|
||||
sToken = sToken + SynLineBreakGlyph;
|
||||
nTokenLen = sToken + edit->charColumns(SynLineBreakGlyph);
|
||||
nTokenColumnLen += edit->charColumns(SynLineBreakGlyph);
|
||||
}
|
||||
if (bComplexLine) {
|
||||
setDrawingColors(false);
|
||||
rcToken.setLeft(std::max(rcLine.left(), ColumnToXValue(FirstCol)));
|
||||
rcToken.setRight(std::min(rcLine.right(), ColumnToXValue(nLineSelStart)));
|
||||
PaintToken(sToken, nTokenLen, 0, FirstCol, nLineSelStart,false);
|
||||
PaintToken(sToken, nTokenColumnLen, 0, FirstCol, nLineSelStart,false);
|
||||
rcToken.setLeft(std::max(rcLine.left(), ColumnToXValue(nLineSelEnd)));
|
||||
rcToken.setRight(std::min(rcLine.right(), ColumnToXValue(LastCol)));
|
||||
PaintToken(sToken, nTokenLen, 0, nLineSelEnd, LastCol,true);
|
||||
PaintToken(sToken, nTokenColumnLen, 0, nLineSelEnd, LastCol,true);
|
||||
setDrawingColors(false);
|
||||
rcToken.setLeft(std::max(rcLine.left(), ColumnToXValue(nLineSelStart)));
|
||||
rcToken.setRight(std::min(rcLine.right(), ColumnToXValue(nLineSelEnd)));
|
||||
PaintToken(sToken, nTokenLen, 0, nLineSelStart, nLineSelEnd - 1,false);
|
||||
PaintToken(sToken, nTokenColumnLen, 0, nLineSelStart, nLineSelEnd - 1,false);
|
||||
} else {
|
||||
setDrawingColors(bLineSelected);
|
||||
PaintToken(sToken, nTokenLen, 0, FirstCol, LastCol,bLineSelected);
|
||||
PaintToken(sToken, nTokenColumnLen, 0, FirstCol, LastCol,bLineSelected);
|
||||
}
|
||||
} else {
|
||||
// Initialize highlighter with line text and range info. It is
|
||||
|
@ -577,7 +844,7 @@ void SynEditTextPainter::PaintLines()
|
|||
// or the line having special colors. For spaces the foreground color
|
||||
// is ignored as well.
|
||||
TokenAccu.Columns = 0;
|
||||
nTokenPos = 0;
|
||||
nTokenStartColumn = 0;
|
||||
// Test first whether anything of this token is visible.
|
||||
while (edit->mHighlighter->eol()) {
|
||||
sToken = edit->mHighlighter->getToken();
|
||||
|
@ -591,13 +858,13 @@ void SynEditTextPainter::PaintLines()
|
|||
if (sToken.isEmpty())
|
||||
throw BaseError(SynEdit::tr("The highlighter seems to be in an infinite loop"));
|
||||
}
|
||||
nTokenPos = edit->charToColumn(vLine,edit->mHighlighter->getTokenPos());
|
||||
nTokenLen = edit->stringColumns(sToken);
|
||||
if (nTokenPos + nTokenLen >= vFirstChar) {
|
||||
if (nTokenPos + nTokenLen >= vLastChar) {
|
||||
if (nTokenPos >= vLastChar)
|
||||
nTokenStartColumn = edit->charToColumn(vLine,edit->mHighlighter->getTokenPos());
|
||||
nTokenColumnLen = edit->stringColumns(sToken, nTokenStartColumn-1);
|
||||
if (nTokenStartColumn + nTokenColumnLen >= vFirstChar) {
|
||||
if (nTokenStartColumn + nTokenColumnLen >= vLastChar) {
|
||||
if (nTokenStartColumn >= vLastChar)
|
||||
break; //*** BREAK ***
|
||||
nTokenLen = vLastChar - nTokenPos - 1;
|
||||
nTokenColumnLen = vLastChar - nTokenStartColumn - 1;
|
||||
}
|
||||
// It's at least partially visible. Get the token attributes now.
|
||||
attr = edit->mHighlighter->getTokenAttribute();
|
||||
|
@ -614,25 +881,25 @@ void SynEditTextPainter::PaintLines()
|
|||
} else if (sToken == "}") {
|
||||
GetBraceColorAttr(edit->mHighlighter->getBraceLevel()+1,attr);
|
||||
}
|
||||
AddHighlightToken(sToken, nTokenPos - (vFirstChar - FirstCol),
|
||||
nTokenLen, vLine,attr);
|
||||
AddHighlightToken(sToken, nTokenStartColumn - (vFirstChar - FirstCol),
|
||||
nTokenColumnLen, vLine,attr);
|
||||
}
|
||||
// Let the highlighter scan the next token.
|
||||
edit->mHighlighter->next();
|
||||
}
|
||||
// Don't assume HL.GetTokenPos is valid after HL.GetEOL == True.
|
||||
nTokenPos += edit->stringColumns(sToken);
|
||||
if (edit->mHighlighter->eol() && (nTokenPos < vLastChar)) {
|
||||
nTokenStartColumn += edit->stringColumns(sToken,nTokenStartColumn-1);
|
||||
if (edit->mHighlighter->eol() && (nTokenStartColumn < vLastChar)) {
|
||||
int lineColumns = edit->mLines->lineColumns(vLine-1);
|
||||
// Draw text that couldn't be parsed by the highlighter, if any.
|
||||
if (nTokenPos < lineColumns) {
|
||||
if (nTokenPos + 1 < vFirstChar)
|
||||
nTokenPos = vFirstChar - 1;
|
||||
nTokenLen = std::min(lineColumns, vLastChar) - (nTokenPos + 1);
|
||||
if (nTokenLen > 0) {
|
||||
sToken = edit->subStringByColumns(sLine,nTokenPos+1,nTokenLen);
|
||||
AddHighlightToken(sToken, nTokenPos - (vFirstChar - FirstCol),
|
||||
edit->stringColumns(sToken), vLine, PSynHighlighterAttribute());
|
||||
if (nTokenStartColumn < lineColumns) {
|
||||
if (nTokenStartColumn + 1 < vFirstChar)
|
||||
nTokenStartColumn = vFirstChar - 1;
|
||||
nTokenColumnLen = std::min(lineColumns, vLastChar) - (nTokenStartColumn + 1);
|
||||
if (nTokenColumnLen > 0) {
|
||||
sToken = edit->substringByColumns(sLine,nTokenStartColumn+1,nTokenColumnLen);
|
||||
AddHighlightToken(sToken, nTokenStartColumn - (vFirstChar - FirstCol),
|
||||
nTokenColumnLen, vLine, PSynHighlighterAttribute());
|
||||
}
|
||||
}
|
||||
// Draw LineBreak glyph.
|
||||
|
@ -647,12 +914,12 @@ void SynEditTextPainter::PaintLines()
|
|||
// Paint folding
|
||||
foldRange = edit->foldStartAtLine(vLine);
|
||||
if ((foldRange) && foldRange->collapsed) {
|
||||
sFold = " ... } ";
|
||||
nFold = edit->stringColumns(sFold);
|
||||
attr = edit->mHighlighter->symbolAttribute();
|
||||
GetBraceColorAttr(edit->mHighlighter->getBraceLevel(),attr);
|
||||
AddHighlightToken(sFold,edit->mLines->lineColumns(vLine-1)+1 - (vFirstChar - FirstCol)
|
||||
, nFold, vLine, attr);
|
||||
sFold = " ... } ";
|
||||
nFold = edit->stringColumns(sFold,edit->mLines->lineColumns(vLine-1));
|
||||
attr = edit->mHighlighter->symbolAttribute();
|
||||
GetBraceColorAttr(edit->mHighlighter->getBraceLevel(),attr);
|
||||
AddHighlightToken(sFold,edit->mLines->lineColumns(vLine-1)+1 - (vFirstChar - FirstCol)
|
||||
, nFold, vLine, attr);
|
||||
}
|
||||
|
||||
// Draw anything that's left in the TokenAccu record. Fill to the end
|
||||
|
@ -667,10 +934,15 @@ void SynEditTextPainter::PaintLines()
|
|||
// the flicker. Should not cost very much anyway, compared to the many
|
||||
// calls to ExtTextOut.
|
||||
if (bDoRightEdge) {
|
||||
painter->paintEngine(nRightEdge, rcLine.top(),nRightEdge,rcLine.bottom()+1);
|
||||
painter->drawLine(nRightEdge, rcLine.top(),nRightEdge,rcLine.bottom()+1);
|
||||
}
|
||||
bCurrentLine = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SynEditTextPainter::drawMark(PSynEditMark aMark, int &aGutterOff, int aMarkRow)
|
||||
{
|
||||
//todo
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "Types.h"
|
||||
#include "highlighter/base.h"
|
||||
#include "../utils.h"
|
||||
#include "MiscClasses.h"
|
||||
|
||||
class SynEdit;
|
||||
class SynEditTextPainter
|
||||
|
@ -21,15 +22,19 @@ class SynEditTextPainter
|
|||
};
|
||||
|
||||
public:
|
||||
SynEditTextPainter(SynEdit * edit);
|
||||
SynEditTextPainter(SynEdit * edit,int FirstRow, int LastRow,
|
||||
int FirstCol, int LastCol);
|
||||
void paintTextLines(const QRect& clip);
|
||||
void paintGutter(const QRect& clip);
|
||||
|
||||
private:
|
||||
QColor colEditorBG();
|
||||
void ComputeSelectionInfo();
|
||||
void setDrawingColors(bool Selected);
|
||||
int ColumnToXValue(int Col);
|
||||
void PaintToken(const QString& Token, int TokenLen, int ColumnsBefore,
|
||||
int First, int Last, bool isSelection);
|
||||
void PaintEditAreas(PSynEditingAreaList areaList);
|
||||
void PaintEditAreas(const SynEditingAreaList& areaList);
|
||||
void PaintHighlightToken(bool bFillToEOL);
|
||||
bool TokenIsSpaces(bool& bSpacesTest, const QString& Token, bool& bIsSpaces);
|
||||
void AddHighlightToken(const QString& Token, int ColumnsBefore, int TokenColumns,
|
||||
|
@ -38,6 +43,8 @@ public:
|
|||
void PaintFoldAttributes();
|
||||
void GetBraceColorAttr(int level, PSynHighlighterAttribute &attr);
|
||||
void PaintLines();
|
||||
void drawMark(PSynEditMark aMark,int& aGutterOff, int aMarkRow);
|
||||
|
||||
private:
|
||||
SynEdit* edit;
|
||||
QPainter* painter;
|
||||
|
|
|
@ -350,3 +350,16 @@ void decodeKey(const int combinedKey, int &key, Qt::KeyboardModifiers &modifiers
|
|||
}
|
||||
key = combinedKey & ~(Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier | Qt::KeypadModifier);
|
||||
}
|
||||
|
||||
void inflateRect(QRect &rect, int delta)
|
||||
{
|
||||
inflateRect(rect,delta,delta);
|
||||
}
|
||||
|
||||
void inflateRect(QRect &rect, int dx, int dy)
|
||||
{
|
||||
rect.setLeft(rect.left()-dx);
|
||||
rect.setRight(rect.right()+dx);
|
||||
rect.setTop(rect.top()-dy);
|
||||
rect.setBottom(rect.bottom()+dy);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <utility>
|
||||
#include <functional>
|
||||
#include <QString>
|
||||
#include <QRect>
|
||||
|
||||
class QByteArray;
|
||||
class QString;
|
||||
|
@ -92,6 +93,9 @@ void ReadFileToLines(const QString& fileName, QTextCodec* codec, LineProcessFunc
|
|||
|
||||
void decodeKey(int combinedKey, int& key, Qt::KeyboardModifiers& modifiers);
|
||||
|
||||
void inflateRect(QRect& rect, int delta);
|
||||
void inflateRect(QRect& rect, int dx, int dy);
|
||||
|
||||
template <class F>
|
||||
class final_action
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue