scide: DocManager - report warnings via the status bar
[supercollider.git] / editors / sc-ide / widgets / code_editor / overlay.cpp
bloba305aaab987f5e57cf8b96623a8a1d7fcc17f849
1 /*
2 SuperCollider Qt IDE
3 Copyright (c) 2012 Jakob Leben & Tim Blechmann
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "overlay.hpp"
22 #include "editor.hpp"
23 #include "../../core/main.hpp"
25 #include <QTextDocument>
26 #include <QTextLayout>
27 #include <QTextBlock>
28 #include <QPainter>
29 #include <QPropertyAnimation>
30 #include <QtCore/qmath.h>
31 #include <QDebug>
33 namespace ScIDE {
35 void CodeEditor::blinkCode( const QTextCursor & c )
37 if( !c.document() || !c.hasSelection() ) return;
39 Settings::Manager *settings = Main::settings();
40 settings->beginGroup("IDE/editor/colors");
41 QTextCharFormat evalCodeTextFormat = settings->value("evaluatedCode").value<QTextCharFormat>();
42 settings->endGroup();
44 QTextDocument *doc = c.document();
46 int startPos = c.selectionStart();
47 int endPos = c.selectionEnd();
48 QTextBlock startBlock = doc->findBlock(startPos);
49 QTextBlock endBlock = doc->findBlock(endPos);
50 startPos -= startBlock.position();
51 endPos -= endBlock.position();
53 // Get the bounds of visible blocks within the cursor's selection:
55 QTextBlock b = firstVisibleBlock();
56 int idx = b.blockNumber();
57 int sidx = startBlock.blockNumber();
59 QTextBlock firstBlock, lastBlock;
60 firstBlock = lastBlock = b;
62 QRectF geom = blockBoundingGeometry(b).translated(contentOffset());
63 qreal top = geom.top();
64 qreal bottom = top;
65 qreal width=0;
67 while(b.isValid() && bottom < viewport()->rect().height())
69 if(b.isVisible())
71 QTextLayout *l = b.layout();
72 QRectF r = l->boundingRect();
73 bottom += r.height();
74 if(idx < sidx) {
75 // Block not within the selection. Will skip it.
76 top = bottom;
78 else {
79 // Block within the selection.
80 width = qMax(width, l->maximumWidth() + r.left());
84 if(b == endBlock) break;
86 b = b.next();
87 ++idx;
88 if(top == bottom)
89 firstBlock = b;
92 lastBlock = b;
94 if(bottom == top) {
95 //qDebug("no visible block.");
96 return;
99 // Construct a pixmap to render the code on:
101 QPixmap pix( QSize(qCeil(width), qCeil(bottom - top)) );
102 pix.fill(QColor(0,0,0,0));
104 // Render the visible blocks:
106 QPainter painter(&pix);
107 QVector<QTextLayout::FormatRange> selections;
108 b = firstBlock;
109 int y=0;
110 while(true)
112 QRectF r = b.layout()->boundingRect();
114 // Use extra char formatting to hide code outside of selection
115 // and modify the appearance of selected code:
117 QTextLayout::FormatRange range;
118 selections.clear();
120 int start = 0;
121 if(b == startBlock) {
122 range.start = 0;
123 range.length = startPos;
124 range.format.setForeground(QColor(0,0,0,0));
125 range.format.setBackground(Qt::NoBrush);
126 selections.append(range);
127 start = startPos;
130 range.start = start;
131 range.length = (b == endBlock ? endPos : b.length() - 1) - range.start;
132 range.format = evalCodeTextFormat;
133 selections.append(range);
135 if(b == endBlock) {
136 range.start = range.start + range.length;
137 range.length = b.length() - 1 - range.start;
138 range.format.setForeground(QColor(0,0,0,0));
139 range.format.setBackground(Qt::NoBrush);
140 selections.append(range);
143 b.layout()->draw(&painter, QPointF(0,y), selections);
145 if(b == lastBlock) break;
147 y += r.height();
149 b = b.next();
152 // Create an overlay item to display the pixmap, and animate it:
154 CodeFragmentOverlay *item = new CodeFragmentOverlay();
155 item->setPixmap(pix);
156 item->setPos(geom.left(), top);
158 mOverlay->addItem(item);
160 QPropertyAnimation *anim = new QPropertyAnimation(item, "opacity", item);
161 anim->setDuration(mBlinkDuration);
162 anim->setStartValue(1.0);
163 anim->setEndValue(0.0);
164 anim->setEasingCurve( QEasingCurve::InCubic );
165 anim->start();
167 connect(anim, SIGNAL(finished()), item, SLOT(deleteLater()));
170 } // namespace ScIDE