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"
23 #include "../../core/main.hpp"
25 #include <QTextDocument>
26 #include <QTextLayout>
29 #include <QPropertyAnimation>
30 #include <QtCore/qmath.h>
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
>();
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();
67 while(b
.isValid() && bottom
< viewport()->rect().height())
71 QTextLayout
*l
= b
.layout();
72 QRectF r
= l
->boundingRect();
75 // Block not within the selection. Will skip it.
79 // Block within the selection.
80 width
= qMax(width
, l
->maximumWidth() + r
.left());
84 if(b
== endBlock
) break;
95 //qDebug("no visible block.");
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
;
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
;
121 if(b
== startBlock
) {
123 range
.length
= startPos
;
124 range
.format
.setForeground(QColor(0,0,0,0));
125 range
.format
.setBackground(Qt::NoBrush
);
126 selections
.append(range
);
131 range
.length
= (b
== endBlock
? endPos
: b
.length() - 1) - range
.start
;
132 range
.format
= evalCodeTextFormat
;
133 selections
.append(range
);
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;
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
);
167 connect(anim
, SIGNAL(finished()), item
, SLOT(deleteLater()));