-
Notifications
You must be signed in to change notification settings - Fork 21
Expand file tree
/
Copy pathVuoCodeGutter.cc
More file actions
142 lines (118 loc) · 4.16 KB
/
Copy pathVuoCodeGutter.cc
File metadata and controls
142 lines (118 loc) · 4.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/**
* @file
* VuoCodeGutter implementation.
*
* @copyright Copyright © 2012–2026 Kosada Incorporated.
* This code may be modified and distributed under the terms of the GNU Lesser General Public License (LGPL) version 2 or later.
* For more information, see https://vuo.org/license.
*/
#include "VuoCodeGutter.hh"
#include <sys/param.h>
#include "VuoCodeEditor.hh"
#include "VuoCodeEditorStages.hh"
#include "VuoCodeWindow.hh"
#include "VuoShaderIssues.hh"
qreal VuoCodeGutter::leftMargin = 5;
qreal VuoCodeGutter::rightMargin = 5;
/**
* Creates a gutter.
*/
VuoCodeGutter::VuoCodeGutter(VuoCodeEditor *editor)
: QWidget(editor)
{
codeEditor = editor;
scrollPosition = 0;
lineNumberFont = QFont("Menlo");
connect(codeEditor, &QTextEdit::textChanged, this, &VuoCodeGutter::textChanged);
connect(codeEditor->verticalScrollBar(), &QAbstractSlider::valueChanged, this, &VuoCodeGutter::handleSliderMoved);
}
/**
* Updates the gutter's font size to match the main code editor.
*/
void VuoCodeGutter::updateLineNumberFont()
{
lineNumberFont.setPointSize(codeEditor->font().pointSize() * .8);
resizeEvent(NULL);
update();
}
void VuoCodeGutter::paintEvent(QPaintEvent *event)
{
QRect r = event->rect();
QPainter painter(this);
painter.fillRect(r, codeEditor->gutterColor);
painter.setPen(codeEditor->gutterTextColor);
painter.setFont(lineNumberFont);
QFontMetrics lineNumberFontMetrics(lineNumberFont);
int lineHeight = codeEditor->fontMetrics().height();
int baselineAdjustment = codeEditor->fontMetrics().ascent() - lineNumberFontMetrics.ascent();
int gutterWidth = width() - rightMargin;
// QFontMetrics.lineHeight is in pixels, but QTextEdit doesn't quantize lines to pixels,
// so we can't just draw at multiples of lineHeight.
// Instead, get the actual position of each line from the QTextLayout.
QTextCursor cursor = codeEditor->textCursor();
cursor.movePosition(QTextCursor::Start);
QTextBlock block = cursor.block();
int viewportHeight = codeEditor->viewport()->geometry().height();
int lineNumber = 0;
VuoCodeWindow *codeWindow = static_cast<VuoCodeWindow *>(window());
if (codeWindow->issues)
{
vector<VuoShaderIssues::Issue> issues = codeWindow->issues->issuesForStage(codeWindow->stages->currentStage());
// The issue list is assumed to be sorted by line number.
// Therefore we only need to advance through it once, instead of once for every line number.
vector<VuoShaderIssues::Issue>::iterator issueIterator = issues.begin();
int iconSize = codeEditor->errorIcon->height() / window()->devicePixelRatio();
do
{
++lineNumber;
qreal y = block.layout()->position().y() - scrollPosition;
if (y < -lineHeight)
continue;
if (y > viewportHeight)
break;
painter.drawText(QRectF(0, y + baselineAdjustment + 1, gutterWidth, lineHeight),
Qt::AlignRight, QString::number(lineNumber));
bool haveIssue = false;
while (issueIterator != issues.end())
{
if (issueIterator->lineNumber == lineNumber)
{
haveIssue = true;
break;
}
if (issueIterator->lineNumber > lineNumber)
break;
++issueIterator;
}
if (haveIssue)
painter.drawPixmap(leftMargin, y + (lineHeight - iconSize) / 2, iconSize, iconSize, *codeEditor->errorIcon);
} while ((block = block.next()).isValid());
}
}
void VuoCodeGutter::handleSliderMoved(int value)
{
scrollPosition = value;
update();
}
void VuoCodeGutter::textChanged()
{
resizeEvent(NULL);
update();
}
void VuoCodeGutter::resizeEvent(QResizeEvent *event)
{
int lineNumberDigits = MAX(2, log10(codeEditor->document()->lineCount()) + 1);
QFontMetricsF lineNumberFontMetrics(lineNumberFont);
int iconSize = codeEditor->errorIcon->height() / window()->devicePixelRatio();
int width = leftMargin + iconSize + leftMargin + lineNumberFontMetrics.horizontalAdvance('0') * lineNumberDigits + rightMargin;
if (width == size().width())
return;
QRect c = codeEditor->rect();
setGeometry(QRect(c.left(), c.top(), width, c.height()));
codeEditor->setViewportMargins(width, 0, 0, 0);
if (codeEditor->parent())
{
VuoCodeEditorStages *stages = static_cast<VuoCodeEditorStages *>(codeEditor->parent()->parent());
stages->updatePosition();
}
}