Mercurial > projects > qtd
comparison demos/deform/pathdeform.d @ 41:691e68637348
non-working deform example
author | maxter |
---|---|
date | Sun, 17 May 2009 12:41:14 +0000 |
parents | |
children | 849b66609571 |
comparison
equal
deleted
inserted
replaced
40:a5cc4ada07f5 | 41:691e68637348 |
---|---|
1 /**************************************************************************** | |
2 ** | |
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). | |
4 ** Contact: Qt Software Information (qt-info@nokia.com) | |
5 ** | |
6 ** This file is part of the demonstration applications of the Qt Toolkit. | |
7 ** | |
8 ** $QT_BEGIN_LICENSE:LGPL$ | |
9 ** Commercial Usage | |
10 ** Licensees holding valid Qt Commercial licenses may use this file in | |
11 ** accordance with the Qt Commercial License Agreement provided with the | |
12 ** Software or, alternatively, in accordance with the terms contained in | |
13 ** a written agreement between you and Nokia. | |
14 ** | |
15 ** GNU Lesser General Public License Usage | |
16 ** Alternatively, this file may be used under the terms of the GNU Lesser | |
17 ** General Public License version 2.1 as published by the Free Software | |
18 ** Foundation and appearing in the file LICENSE.LGPL included in the | |
19 ** packaging of this file. Please review the following information to | |
20 ** ensure the GNU Lesser General Public License version 2.1 requirements | |
21 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | |
22 ** | |
23 ** In addition, as a special exception, Nokia gives you certain | |
24 ** additional rights. These rights are described in the Nokia Qt LGPL | |
25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this | |
26 ** package. | |
27 ** | |
28 ** GNU General Public License Usage | |
29 ** Alternatively, this file may be used under the terms of the GNU | |
30 ** General Public License version 3.0 as published by the Free Software | |
31 ** Foundation and appearing in the file LICENSE.GPL included in the | |
32 ** packaging of this file. Please review the following information to | |
33 ** ensure the GNU General Public License version 3.0 requirements will be | |
34 ** met: http://www.gnu.org/copyleft/gpl.html. | |
35 ** | |
36 ** If you are unsure which license is appropriate for your use, please | |
37 ** contact the sales department at qt-sales@nokia.com. | |
38 ** $QT_END_LICENSE$ | |
39 ** | |
40 ****************************************************************************/ | |
41 | |
42 import arthurwidgets, | |
43 qt.gui.QPainterPath, | |
44 | |
45 qt.gui.QApplication, | |
46 qt.gui.QMouseEvent, | |
47 qt.core.QDateTime, | |
48 qt.core.QTimerEvent, | |
49 qt.core.QBasicTimer, | |
50 qt.gui.QLayout, | |
51 qt.gui.QLineEdit, | |
52 qt.gui.QPainter, | |
53 qt.gui.QSlider, | |
54 qt.gui.QLabel, | |
55 qt.gui.QDesktopWidget, | |
56 qt.gui.QGroupBox, | |
57 qt.gui.QPushButton, | |
58 qt.gui.QVBoxLayout, | |
59 qt.gui.QGridLayout, | |
60 qt.gui.QHBoxLayout, | |
61 qt.gui.QRadialGradient, | |
62 qt.opengl.QGLFormat, | |
63 tango.math.Math; | |
64 | |
65 class PathDeformControls : QWidget | |
66 { | |
67 private PathDeformRenderer m_renderer; | |
68 | |
69 mixin Signal!("okPressed"); | |
70 mixin Signal!("quitPressed"); | |
71 | |
72 this(QWidget parent, PathDeformRenderer renderer, bool smallScreen) | |
73 { | |
74 super(parent); | |
75 m_renderer = renderer; | |
76 | |
77 if (smallScreen) | |
78 layoutForSmallScreen(); | |
79 else | |
80 layoutForDesktop(); | |
81 } | |
82 | |
83 void layoutForDesktop() | |
84 { | |
85 QGroupBox mainGroup = new QGroupBox(this); | |
86 mainGroup.setTitle(tr("Controls")); | |
87 | |
88 QGroupBox radiusGroup = new QGroupBox(mainGroup); | |
89 radiusGroup.setTitle(tr("Lens Radius")); | |
90 QSlider radiusSlider = new QSlider(Qt.Horizontal, radiusGroup); | |
91 radiusSlider.setRange(15, 150); | |
92 radiusSlider.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed); | |
93 | |
94 QGroupBox deformGroup = new QGroupBox(mainGroup); | |
95 deformGroup.setTitle(tr("Deformation")); | |
96 QSlider deformSlider = new QSlider(Qt.Horizontal, deformGroup); | |
97 deformSlider.setRange(-100, 100); | |
98 deformSlider.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed); | |
99 | |
100 QGroupBox fontSizeGroup = new QGroupBox(mainGroup); | |
101 fontSizeGroup.setTitle(tr("Font Size")); | |
102 QSlider fontSizeSlider = new QSlider(Qt.Horizontal, fontSizeGroup); | |
103 fontSizeSlider.setRange(16, 200); | |
104 fontSizeSlider.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed); | |
105 | |
106 QGroupBox textGroup = new QGroupBox(mainGroup); | |
107 textGroup.setTitle(tr("Text")); | |
108 QLineEdit textInput = new QLineEdit(textGroup); | |
109 | |
110 QPushButton animateButton = new QPushButton(mainGroup); | |
111 animateButton.setText(tr("Animated")); | |
112 animateButton.setCheckable(true); | |
113 | |
114 QPushButton showSourceButton = new QPushButton(mainGroup); | |
115 showSourceButton.setText(tr("Show Source")); | |
116 | |
117 version (QT_OPENGL_SUPPORT) | |
118 { | |
119 QPushButton enableOpenGLButton = new QPushButton(mainGroup); | |
120 enableOpenGLButton.setText(tr("Use OpenGL")); | |
121 enableOpenGLButton.setCheckable(true); | |
122 enableOpenGLButton.setChecked(m_renderer.usesOpenGL()); | |
123 if (!QGLFormat.hasOpenGL()) | |
124 enableOpenGLButton.hide(); | |
125 } | |
126 | |
127 QPushButton whatsThisButton = new QPushButton(mainGroup); | |
128 whatsThisButton.setText(tr("What's This?")); | |
129 whatsThisButton.setCheckable(true); | |
130 | |
131 mainGroup.setFixedWidth(180); | |
132 | |
133 QVBoxLayout mainGroupLayout = new QVBoxLayout(mainGroup); | |
134 mainGroupLayout.addWidget(radiusGroup); | |
135 mainGroupLayout.addWidget(deformGroup); | |
136 mainGroupLayout.addWidget(fontSizeGroup); | |
137 mainGroupLayout.addWidget(textGroup); | |
138 mainGroupLayout.addWidget(animateButton); | |
139 mainGroupLayout.addStretch(1); | |
140 version (QT_OPENGL_SUPPORT) | |
141 { | |
142 mainGroupLayout.addWidget(enableOpenGLButton); | |
143 } | |
144 mainGroupLayout.addWidget(showSourceButton); | |
145 mainGroupLayout.addWidget(whatsThisButton); | |
146 | |
147 QVBoxLayout radiusGroupLayout = new QVBoxLayout(radiusGroup); | |
148 radiusGroupLayout.addWidget(radiusSlider); | |
149 | |
150 QVBoxLayout deformGroupLayout = new QVBoxLayout(deformGroup); | |
151 deformGroupLayout.addWidget(deformSlider); | |
152 | |
153 QVBoxLayout fontSizeGroupLayout = new QVBoxLayout(fontSizeGroup); | |
154 fontSizeGroupLayout.addWidget(fontSizeSlider); | |
155 | |
156 QVBoxLayout textGroupLayout = new QVBoxLayout(textGroup); | |
157 textGroupLayout.addWidget(textInput); | |
158 | |
159 QVBoxLayout mainLayout = new QVBoxLayout(this); | |
160 mainLayout.addWidget(mainGroup); | |
161 mainLayout.setMargin(0); | |
162 | |
163 radiusSlider.valueChanged.connect(&m_renderer.setRadius); | |
164 deformSlider.valueChanged.connect(&m_renderer.setIntensity); | |
165 fontSizeSlider.valueChanged.connect(&m_renderer.setFontSize); | |
166 animateButton.clicked.connect(&m_renderer.setAnimated); | |
167 version (QT_OPENGL_SUPPORT) | |
168 { | |
169 enableOpenGLButton.clicked.connect(&m_renderer.enableOpenGL); | |
170 } | |
171 | |
172 textInput.textChanged.connect(&m_renderer.setText); | |
173 m_renderer.descriptionEnabledChanged.connect(&whatsThisButton.setChecked); | |
174 whatsThisButton.clicked.connect(&m_renderer.setDescriptionEnabled); | |
175 showSourceButton.clicked.connect(&m_renderer.showSource); | |
176 | |
177 animateButton.animateClick(); | |
178 deformSlider.setValue(80); | |
179 fontSizeSlider.setValue(120); | |
180 radiusSlider.setValue(100); | |
181 textInput.setText(tr("Qt")); | |
182 } | |
183 | |
184 void layoutForSmallScreen() | |
185 { | |
186 QGroupBox mainGroup = new QGroupBox(this); | |
187 mainGroup.setTitle(tr("Controls")); | |
188 | |
189 QLabel radiusLabel = new QLabel(mainGroup); | |
190 radiusLabel.setText(tr("Lens Radius:")); | |
191 QSlider radiusSlider = new QSlider(Qt.Horizontal, mainGroup); | |
192 radiusSlider.setRange(15, 150); | |
193 radiusSlider.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed); | |
194 | |
195 QLabel deformLabel = new QLabel(mainGroup); | |
196 deformLabel.setText(tr("Deformation:")); | |
197 QSlider deformSlider = new QSlider(Qt.Horizontal, mainGroup); | |
198 deformSlider.setRange(-100, 100); | |
199 deformSlider.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed); | |
200 | |
201 QLabel fontSizeLabel = new QLabel(mainGroup); | |
202 fontSizeLabel.setText(tr("Font Size:")); | |
203 QSlider fontSizeSlider = new QSlider(Qt.Horizontal, mainGroup); | |
204 fontSizeSlider.setRange(16, 200); | |
205 fontSizeSlider.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed); | |
206 | |
207 QPushButton animateButton = new QPushButton(tr("Animated"), mainGroup); | |
208 animateButton.setCheckable(true); | |
209 | |
210 version (QT_OPENGL_SUPPORT) | |
211 { | |
212 QPushButton enableOpenGLButton = new QPushButton(mainGroup); | |
213 enableOpenGLButton.setText(tr("Use OpenGL")); | |
214 enableOpenGLButton.setCheckable(true); | |
215 enableOpenGLButton.setChecked(m_renderer.usesOpenGL()); | |
216 if (!QGLFormat.hasOpenGL()) | |
217 enableOpenGLButton.hide(); | |
218 } | |
219 | |
220 QPushButton quitButton = new QPushButton(tr("Quit"), mainGroup); | |
221 QPushButton okButton = new QPushButton(tr("OK"), mainGroup); | |
222 | |
223 | |
224 QGridLayout mainGroupLayout = new QGridLayout(mainGroup); | |
225 mainGroupLayout.setMargin(0); | |
226 mainGroupLayout.addWidget(radiusLabel, 0, 0, Qt.AlignRight); | |
227 mainGroupLayout.addWidget(radiusSlider, 0, 1); | |
228 mainGroupLayout.addWidget(deformLabel, 1, 0, Qt.AlignRight); | |
229 mainGroupLayout.addWidget(deformSlider, 1, 1); | |
230 mainGroupLayout.addWidget(fontSizeLabel, 2, 0, Qt.AlignRight); | |
231 mainGroupLayout.addWidget(fontSizeSlider, 2, 1); | |
232 mainGroupLayout.addWidget(animateButton, 3,0, 1,2); | |
233 version (QT_OPENGL_SUPPORT) | |
234 { | |
235 mainGroupLayout.addWidget(enableOpenGLButton, 4,0, 1,2); | |
236 } | |
237 | |
238 QVBoxLayout mainLayout = new QVBoxLayout(this); | |
239 mainLayout.addWidget(mainGroup); | |
240 mainLayout.addStretch(1); | |
241 mainLayout.addWidget(okButton); | |
242 mainLayout.addWidget(quitButton); | |
243 | |
244 quitButton.clicked.connect(&emitQuitSignal); | |
245 okButton.clicked.connect(&emitOkSignal); | |
246 radiusSlider.valueChanged.connect(&m_renderer.setRadius); | |
247 deformSlider.valueChanged.connect(&m_renderer.setIntensity); | |
248 fontSizeSlider.valueChanged.connect(&m_renderer.setFontSize); | |
249 animateButton.clicked.connect(&m_renderer.setAnimated); | |
250 version (QT_OPENGL_SUPPORT) | |
251 { | |
252 enableOpenGLButton.clicked.connect(&m_renderer.enableOpenGL); | |
253 } | |
254 | |
255 | |
256 animateButton.animateClick(); | |
257 deformSlider.setValue(80); | |
258 fontSizeSlider.setValue(120); | |
259 | |
260 QRect screen_size = QApplication.desktop().screenGeometry(); | |
261 radiusSlider.setValue(qMin(screen_size.width(), screen_size.height())/5); | |
262 m_renderer.setText(tr("Qt")); | |
263 } | |
264 | |
265 | |
266 void emitQuitSignal() | |
267 { quitPressed.emit; } | |
268 | |
269 void emitOkSignal() | |
270 { okPressed.emit; } | |
271 } | |
272 | |
273 | |
274 class PathDeformWidget : QWidget | |
275 { | |
276 private: | |
277 PathDeformRenderer m_renderer; | |
278 PathDeformControls m_controls; | |
279 | |
280 public: | |
281 this(QWidget parent, bool smallScreen) | |
282 { | |
283 super(parent); | |
284 | |
285 setWindowTitle(tr("Vector Deformation")); | |
286 | |
287 m_renderer = new PathDeformRenderer(this, smallScreen); | |
288 m_renderer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding); | |
289 | |
290 // Layouts | |
291 QHBoxLayout mainLayout = new QHBoxLayout(this); | |
292 mainLayout.addWidget(m_renderer); | |
293 | |
294 m_controls = new PathDeformControls(null, m_renderer, smallScreen); | |
295 m_controls.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Minimum); | |
296 | |
297 if (!smallScreen) | |
298 mainLayout.addWidget(m_controls); | |
299 | |
300 m_renderer.loadSourceFile(":res/deform/pathdeform.d"); | |
301 m_renderer.loadDescription(":res/deform/pathdeform.html"); | |
302 m_renderer.setDescriptionEnabled(false); | |
303 | |
304 m_renderer.clicked.connect(&showControls); | |
305 m_controls.okPressed.connect(&hideControls); | |
306 | |
307 m_controls.quitPressed.connect(&QApplication.quit); | |
308 } | |
309 | |
310 void showControls() | |
311 { | |
312 m_controls.showFullScreen; | |
313 } | |
314 | |
315 void hideControls() | |
316 { | |
317 m_controls.hide; | |
318 } | |
319 | |
320 void setWidgetStyle(QStyle style) // TODO: QWidget.setStyle is not virtual | |
321 { | |
322 super.setStyle(style); | |
323 if (m_controls) | |
324 { | |
325 m_controls.setStyle(style); | |
326 | |
327 auto widgets = m_controls.findChildren!(QWidget); | |
328 foreach (w; widgets) | |
329 w.setStyle(style); | |
330 } | |
331 } | |
332 } | |
333 | |
334 private QRect circle_bounds(QPointF center, qreal radius, qreal compensation) | |
335 { | |
336 return new QRect(qRound(center.x() - radius - compensation), | |
337 qRound(center.y() - radius - compensation), | |
338 qRound((radius + compensation) * 2), | |
339 qRound((radius + compensation) * 2)); | |
340 } | |
341 | |
342 enum | |
343 { | |
344 LENS_EXTENT = 10 | |
345 } | |
346 | |
347 class PathDeformRenderer : ArthurFrame | |
348 { | |
349 private: | |
350 QBasicTimer m_repaintTimer; | |
351 // QBasicTimer m_fpsTimer; | |
352 // int m_fpsCounter; | |
353 QTime m_repaintTracker; | |
354 | |
355 QPainterPath[] m_paths; | |
356 QPointF[] m_advances; | |
357 QRectF m_pathBounds; | |
358 string m_text; | |
359 | |
360 QPixmap m_lens_pixmap; | |
361 QImage m_lens_image; | |
362 | |
363 int m_fontSize; | |
364 bool m_animated; | |
365 | |
366 qreal m_intensity; | |
367 qreal m_radius; | |
368 QPointF m_pos; | |
369 QPointF m_offset; | |
370 QPointF m_direction; | |
371 QPointF m_mousePress; | |
372 bool m_mouseDrag; | |
373 bool m_smallScreen; | |
374 | |
375 public: | |
376 mixin Signal!("clicked"); | |
377 | |
378 this(QWidget widget, bool smallScreen) | |
379 { | |
380 super(widget); | |
381 m_radius = 100; | |
382 m_pos = QPointF(m_radius, m_radius); | |
383 m_direction = QPointF(1, 1); | |
384 m_fontSize = 24; | |
385 m_animated = true; | |
386 m_repaintTimer.start(25, this); | |
387 m_repaintTracker.start(); | |
388 m_intensity = 100; | |
389 m_smallScreen = smallScreen; | |
390 | |
391 // m_fpsTimer.start(1000, this); | |
392 // m_fpsCounter = 0; | |
393 | |
394 generateLensPixmap(); | |
395 } | |
396 | |
397 void setFontSize(int fontSize) { m_fontSize = fontSize; setText(m_text); } | |
398 | |
399 override QSize sizeHint() { return QSize(600, 500); } | |
400 | |
401 bool animated() { return m_animated; } | |
402 int radius() { return cast(int)m_radius; } | |
403 int fontSize() { return m_fontSize; } | |
404 int intensity() { return cast(int)m_intensity; } | |
405 string text() { return m_text; } | |
406 | |
407 | |
408 void setText(string text) | |
409 { | |
410 m_text = text; | |
411 | |
412 auto f = new QFont("times new roman,utopia"); | |
413 f.setStyleStrategy(QFont.ForceOutline); | |
414 f.setPointSize(m_fontSize); | |
415 f.setStyleHint(QFont.Times); | |
416 | |
417 m_paths = null; | |
418 m_pathBounds = new QRectF(); | |
419 | |
420 QPointF advance; | |
421 | |
422 auto path = new QPainterPath; | |
423 path.addText(advance, f, text); | |
424 m_pathBounds = m_pathBounds.united(path.boundingRect); | |
425 m_paths ~= path; | |
426 | |
427 foreach (ref p; m_paths) | |
428 p = (new QMatrix(1, 0, 0, 1, -m_pathBounds.x(), -m_pathBounds.y())).map(path); | |
429 | |
430 update; | |
431 } | |
432 | |
433 | |
434 void generateLensPixmap() | |
435 { | |
436 qreal rad = m_radius + LENS_EXTENT; | |
437 | |
438 QRect bounds = circle_bounds(QPointF(), rad, 0); | |
439 | |
440 QPainter painter = new QPainter; | |
441 | |
442 if (preferImage()) { | |
443 m_lens_image = new QImage(bounds.size(), QImage.Format_ARGB32_Premultiplied); | |
444 m_lens_image.fill(0); | |
445 painter.begin(m_lens_image); | |
446 } else { | |
447 m_lens_pixmap = new QPixmap(bounds.size()); | |
448 m_lens_pixmap.fill(new QColor(Qt.transparent)); | |
449 painter.begin(m_lens_pixmap); | |
450 } | |
451 | |
452 auto gr = new QRadialGradient(rad, rad, rad, 3 * rad / 5, 3 * rad / 5); | |
453 gr.setColorAt(0.0, new QColor(255, 255, 255, 191)); | |
454 gr.setColorAt(0.2, new QColor(255, 255, 127, 191)); | |
455 gr.setColorAt(0.9, new QColor(150, 150, 200, 63)); | |
456 gr.setColorAt(0.95, new QColor(0, 0, 0, 127)); | |
457 gr.setColorAt(1, new QColor(0, 0, 0, 0)); | |
458 painter.setRenderHint(QPainter.Antialiasing); | |
459 painter.setBrush(gr); | |
460 painter.setPen(Qt.NoPen); | |
461 painter.drawEllipse(0, 0, bounds.width(), bounds.height()); | |
462 } | |
463 | |
464 void setAnimated(bool animated) | |
465 { | |
466 m_animated = animated; | |
467 | |
468 if (m_animated) { | |
469 // m_fpsTimer.start(1000, this); | |
470 // m_fpsCounter = 0; | |
471 m_repaintTimer.start(25, this); | |
472 m_repaintTracker.start(); | |
473 } else { | |
474 // m_fpsTimer.stop(); | |
475 m_repaintTimer.stop(); | |
476 } | |
477 } | |
478 | |
479 override void timerEvent(QTimerEvent e) | |
480 { | |
481 | |
482 if (e.timerId == m_repaintTimer.timerId) { | |
483 | |
484 if ((new QLineF(QPointF(0,0), m_direction)).length > 1) | |
485 m_direction *= 0.995; | |
486 qreal time = m_repaintTracker.restart(); | |
487 | |
488 QRect rectBefore = circle_bounds(m_pos, m_radius, m_fontSize); | |
489 | |
490 qreal dx = m_direction.x(); | |
491 qreal dy = m_direction.y(); | |
492 if (time > 0) { | |
493 dx = dx * time * .1; | |
494 dy = dy * time * .1; | |
495 } | |
496 | |
497 m_pos += QPointF(dx, dy); | |
498 | |
499 if (m_pos.x() - m_radius < 0) { | |
500 m_direction.x = -m_direction.x; | |
501 m_pos.x = m_radius; | |
502 } else if (m_pos.x + m_radius > width) { | |
503 m_direction.x = -m_direction.x; | |
504 m_pos.x = width - m_radius; | |
505 } | |
506 | |
507 if (m_pos.y - m_radius < 0) { | |
508 m_direction.y = -m_direction.y; | |
509 m_pos.y = m_radius; | |
510 } else if (m_pos.y + m_radius > height) { | |
511 m_direction.y = -m_direction.y; | |
512 m_pos.y = height - m_radius; | |
513 } | |
514 | |
515 void noGLUpdate() | |
516 { | |
517 QRect rectAfter = circle_bounds(m_pos, m_radius, m_fontSize); | |
518 update(rectAfter.united(rectBefore)); | |
519 QApplication.syncX(); | |
520 } | |
521 | |
522 version (QT_OPENGL_SUPPORT) | |
523 { | |
524 if (usesOpenGL()) { | |
525 update; | |
526 } | |
527 else | |
528 noGLUpdate; | |
529 } | |
530 else | |
531 noGLUpdate; | |
532 } | |
533 // else if (e.timerId() == m_fpsTimer.timerId()) { | |
534 // printf("fps: %d\n", m_fpsCounter); | |
535 // emit frameRate(m_fpsCounter); | |
536 // m_fpsCounter = 0; | |
537 | |
538 // } | |
539 } | |
540 | |
541 override void mousePressEvent(QMouseEvent e) | |
542 { | |
543 setDescriptionEnabled(false); | |
544 | |
545 m_repaintTimer.stop(); | |
546 m_offset = QPointF(); | |
547 if ((new QLineF(m_pos, QPointF(e.pos))).length <= m_radius) | |
548 m_offset = m_pos - QPointF(e.pos); | |
549 | |
550 m_mousePress = e.pos; | |
551 | |
552 // If we're not running in small screen mode, always assume we're dragging | |
553 m_mouseDrag = !m_smallScreen; | |
554 | |
555 mouseMoveEvent(e); | |
556 } | |
557 | |
558 override void mouseReleaseEvent(QMouseEvent e) | |
559 { | |
560 if (e.buttons() == Qt.NoButton && m_animated) { | |
561 m_repaintTimer.start(10, this); | |
562 m_repaintTracker.start(); | |
563 } | |
564 | |
565 if (!m_mouseDrag && m_smallScreen) | |
566 clicked.emit; | |
567 } | |
568 | |
569 override void mouseMoveEvent(QMouseEvent e) | |
570 { | |
571 auto epos = QPointF(e.pos); | |
572 | |
573 if (!m_mouseDrag && (new QLineF(m_mousePress, QPointF(e.pos))).length() > 25.0) | |
574 m_mouseDrag = true; | |
575 | |
576 if (m_mouseDrag) { | |
577 QRect rectBefore = circle_bounds(m_pos, m_radius, m_fontSize); | |
578 if (e.type() == QEvent.MouseMove) { | |
579 QLineF line = new QLineF(m_pos, epos + m_offset); | |
580 line.setLength(line.length() * .1); | |
581 auto dir = QPointF(line.dx(), line.dy()); | |
582 m_direction = (m_direction + dir) / 2; | |
583 } | |
584 m_pos = epos + m_offset; | |
585 | |
586 void noGLUpdate() | |
587 { | |
588 QRect rectAfter = circle_bounds(m_pos, m_radius, m_fontSize); | |
589 update(rectBefore.united(rectAfter)); | |
590 } | |
591 | |
592 version (QT_OPENGL_SUPPORT) | |
593 { | |
594 if (usesOpenGL()) { | |
595 update; | |
596 } else | |
597 noGLUpdate; | |
598 } | |
599 else | |
600 noGLUpdate; | |
601 } | |
602 } | |
603 | |
604 QPainterPath lensDeform(QPainterPath source, QPointF offset) | |
605 { | |
606 auto path = new QPainterPath; | |
607 path.addPath(source); | |
608 | |
609 qreal flip = m_intensity / 100.0; | |
610 | |
611 for (int i=0; i<path.elementCount; ++i) { | |
612 auto e = path.elementAt(i); | |
613 | |
614 qreal x = e.x + offset.x(); | |
615 qreal y = e.y + offset.y(); | |
616 | |
617 qreal dx = x - m_pos.x(); | |
618 qreal dy = y - m_pos.y(); | |
619 qreal len = m_radius - sqrt(dx * dx + dy * dy); | |
620 | |
621 if (len > 0) { | |
622 path.setElementPositionAt(i, | |
623 x + flip * dx * len / m_radius, | |
624 y + flip * dy * len / m_radius); | |
625 } else { | |
626 path.setElementPositionAt(i, x, y); | |
627 } | |
628 | |
629 } | |
630 | |
631 return path; | |
632 } | |
633 | |
634 | |
635 override void paint(QPainter painter) | |
636 { | |
637 int pad_x = 5; | |
638 int pad_y = 5; | |
639 | |
640 int skip_x = qRound(m_pathBounds.width() + pad_x + m_fontSize/2); | |
641 int skip_y = qRound(m_pathBounds.height() + pad_y); | |
642 | |
643 painter.setPen(Qt.NoPen); | |
644 painter.setBrush(new QColor(Qt.black)); | |
645 | |
646 auto clip = painter.clipPath().boundingRect(); | |
647 | |
648 int overlap = pad_x / 2; | |
649 | |
650 for (int start_y=0; start_y < height(); start_y += skip_y) { | |
651 | |
652 if (start_y > clip.bottom()) | |
653 break; | |
654 | |
655 int start_x = -overlap; | |
656 for (; start_x < width(); start_x += skip_x) { | |
657 | |
658 if (start_y + skip_y >= clip.top() && | |
659 start_x + skip_x >= clip.left() && | |
660 start_x <= clip.right()) { | |
661 for (int i=0; i<m_paths.length; ++i) { | |
662 QPainterPath path = lensDeform(m_paths[i], QPointF(start_x, start_y)); | |
663 painter.drawPath(path); | |
664 } | |
665 } | |
666 } | |
667 overlap = skip_x - (start_x - width()); | |
668 | |
669 } | |
670 | |
671 if (preferImage) { | |
672 painter.drawImage(m_pos - QPointF(m_radius + LENS_EXTENT, m_radius + LENS_EXTENT), | |
673 m_lens_image); | |
674 } else { | |
675 painter.drawPixmap(m_pos - QPointF(m_radius + LENS_EXTENT, m_radius + LENS_EXTENT), | |
676 m_lens_pixmap); | |
677 } | |
678 } | |
679 | |
680 | |
681 void setRadius(int radius) | |
682 { | |
683 qreal max = max(m_radius, cast(qreal)radius); | |
684 m_radius = radius; | |
685 generateLensPixmap(); | |
686 if (!m_animated || m_radius < max) { | |
687 | |
688 auto noGLUpdate = (){ update(circle_bounds(m_pos, max, m_fontSize)); }; | |
689 | |
690 version (QT_OPENGL_SUPPORT) | |
691 { | |
692 if (usesOpenGL()) | |
693 update(); | |
694 else | |
695 noGLUpdate(); | |
696 } | |
697 else | |
698 noGLUpdate(); | |
699 } | |
700 } | |
701 | |
702 void setIntensity(int intensity) | |
703 { | |
704 m_intensity = intensity; | |
705 if (!m_animated) { | |
706 | |
707 auto noGLUpdate = (){ update(circle_bounds(m_pos, m_radius, m_fontSize)); }; | |
708 | |
709 version (QT_OPENGL_SUPPORT) | |
710 { | |
711 | |
712 | |
713 if (usesOpenGL()) { | |
714 update(); | |
715 } else | |
716 noGLUpdate(); | |
717 } | |
718 else | |
719 noGLUpdate(); | |
720 } | |
721 } | |
722 } |