Vuo 2.4.4
Loading...
Searching...
No Matches
VuoCodeGutter.cc
Go to the documentation of this file.
1
10#include "VuoCodeGutter.hh"
11
12#include <sys/param.h>
13
14#include "VuoCodeEditor.hh"
16#include "VuoCodeWindow.hh"
17#include "VuoShaderIssues.hh"
18
19qreal VuoCodeGutter::leftMargin = 5;
20qreal VuoCodeGutter::rightMargin = 5;
21
26 : QWidget(editor)
27{
28 codeEditor = editor;
29 scrollPosition = 0;
30
31 lineNumberFont = QFont("Menlo");
32
33 connect(codeEditor, &QTextEdit::textChanged, this, &VuoCodeGutter::textChanged);
34 connect(codeEditor->verticalScrollBar(), &QAbstractSlider::valueChanged, this, &VuoCodeGutter::handleSliderMoved);
35}
36
41{
42 lineNumberFont.setPointSize(codeEditor->font().pointSize() * .8);
43 resizeEvent(NULL);
44 update();
45}
46
47void VuoCodeGutter::paintEvent(QPaintEvent *event)
48{
49 QRect r = event->rect();
50
51 QPainter painter(this);
52 painter.fillRect(r, codeEditor->gutterColor);
53
54 painter.setPen(codeEditor->gutterTextColor);
55 painter.setFont(lineNumberFont);
56 QFontMetrics lineNumberFontMetrics(lineNumberFont);
57 int lineHeight = codeEditor->fontMetrics().height();
58 int baselineAdjustment = codeEditor->fontMetrics().ascent() - lineNumberFontMetrics.ascent();
59 int gutterWidth = width() - rightMargin;
60
61 // QFontMetrics.lineHeight is in pixels, but QTextEdit doesn't quantize lines to pixels,
62 // so we can't just draw at multiples of lineHeight.
63 // Instead, get the actual position of each line from the QTextLayout.
64 QTextCursor cursor = codeEditor->textCursor();
65 cursor.movePosition(QTextCursor::Start);
66 QTextBlock block = cursor.block();
67 int viewportHeight = codeEditor->viewport()->geometry().height();
68 int lineNumber = 0;
69
70 VuoCodeWindow *codeWindow = static_cast<VuoCodeWindow *>(window());
71 if (codeWindow->issues)
72 {
73 vector<VuoShaderIssues::Issue> issues = codeWindow->issues->issuesForStage(codeWindow->stages->currentStage());
74 // The issue list is assumed to be sorted by line number.
75 // Therefore we only need to advance through it once, instead of once for every line number.
76 vector<VuoShaderIssues::Issue>::iterator issueIterator = issues.begin();
77
78 int iconSize = codeEditor->errorIcon->height() / window()->devicePixelRatio();
79
80 do
81 {
82 ++lineNumber;
83 qreal y = block.layout()->position().y() - scrollPosition;
84 if (y < -lineHeight)
85 continue;
86 if (y > viewportHeight)
87 break;
88
89 painter.drawText(QRectF(0, y + baselineAdjustment + 1, gutterWidth, lineHeight),
90 Qt::AlignRight, QString::number(lineNumber));
91
92 bool haveIssue = false;
93 while (issueIterator != issues.end())
94 {
95 if (issueIterator->lineNumber == lineNumber)
96 {
97 haveIssue = true;
98 break;
99 }
100 if (issueIterator->lineNumber > lineNumber)
101 break;
102 ++issueIterator;
103 }
104 if (haveIssue)
105 painter.drawPixmap(leftMargin, y + (lineHeight - iconSize) / 2, iconSize, iconSize, *codeEditor->errorIcon);
106 } while ((block = block.next()).isValid());
107 }
108}
109
110void VuoCodeGutter::handleSliderMoved(int value)
111{
112 scrollPosition = value;
113 update();
114}
115
116void VuoCodeGutter::textChanged()
117{
118 resizeEvent(NULL);
119 update();
120}
121
122void VuoCodeGutter::resizeEvent(QResizeEvent *event)
123{
124 int lineNumberDigits = MAX(2, log10(codeEditor->document()->lineCount()) + 1);
125 QFontMetricsF lineNumberFontMetrics(lineNumberFont);
126 int iconSize = codeEditor->errorIcon->height() / window()->devicePixelRatio();
127 int width = leftMargin + iconSize + leftMargin + lineNumberFontMetrics.horizontalAdvance('0') * lineNumberDigits + rightMargin;
128
129 if (width == size().width())
130 return;
131
132 QRect c = codeEditor->rect();
133 setGeometry(QRect(c.left(), c.top(), width, c.height()));
134
135 codeEditor->setViewportMargins(width, 0, 0, 0);
136
137 if (codeEditor->parent())
138 {
139 VuoCodeEditorStages *stages = static_cast<VuoCodeEditorStages *>(codeEditor->parent()->parent());
140 stages->updatePosition();
141 }
142}