comparison widgets/LEDButton.cpp @ 0:fc9323a41f5a

start base : Sonic Visualiser sv1-1.0rc1
author lbajardsilogic
date Fri, 11 May 2007 09:08:14 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:fc9323a41f5a
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Sonic Visualiser
5 An audio file viewer and annotation editor.
6 Centre for Digital Music, Queen Mary, University of London.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version. See the file
12 COPYING included with this distribution for more information.
13 */
14
15 /*
16 This is a modified version of a source file from the KDE
17 libraries. Copyright (c) 1998-2004 Jörg Habenicht, Richard J
18 Moore, Chris Cannam and others, distributed under the GNU Lesser
19 General Public License.
20
21 Ported to Qt4 by Chris Cannam.
22 */
23
24
25 #include "LEDButton.h"
26
27 #include <QPainter>
28 #include <QImage>
29 #include <QColor>
30 #include <QMouseEvent>
31
32 #include <iostream>
33
34
35 class LEDButton::LEDButtonPrivate
36 {
37 friend class LEDButton;
38
39 int dark_factor;
40 QColor offcolor;
41 QPixmap *off_map;
42 QPixmap *on_map;
43 };
44
45
46 LEDButton::LEDButton(QWidget *parent) :
47 QWidget(parent),
48 led_state(true)
49 {
50 QColor col(Qt::green);
51 d = new LEDButton::LEDButtonPrivate;
52 d->dark_factor = 300;
53 d->offcolor = col.dark(300);
54 d->off_map = 0;
55 d->on_map = 0;
56
57 setColor(col);
58 }
59
60
61 LEDButton::LEDButton(const QColor& col, QWidget *parent) :
62 QWidget(parent),
63 led_state(true)
64 {
65 d = new LEDButton::LEDButtonPrivate;
66 d->dark_factor = 300;
67 d->offcolor = col.dark(300);
68 d->off_map = 0;
69 d->on_map = 0;
70
71 setColor(col);
72 }
73
74 LEDButton::LEDButton(const QColor& col, bool state, QWidget *parent) :
75 QWidget(parent),
76 led_state(state)
77 {
78 d = new LEDButton::LEDButtonPrivate;
79 d->dark_factor = 300;
80 d->offcolor = col.dark(300);
81 d->off_map = 0;
82 d->on_map = 0;
83
84 setColor(col);
85 }
86
87 LEDButton::~LEDButton()
88 {
89 delete d->off_map;
90 delete d->on_map;
91 delete d;
92 }
93
94 void
95 LEDButton::mousePressEvent(QMouseEvent *e)
96 {
97 std::cerr << "LEDButton(" << this << ")::mousePressEvent" << std::endl;
98
99 if (e->buttons() & Qt::LeftButton) {
100 toggle();
101 bool newState = state();
102 std::cerr << "emitting new state " << newState << std::endl;
103 emit stateChanged(newState);
104 }
105 }
106
107 void
108 LEDButton::enterEvent(QEvent *)
109 {
110 emit mouseEntered();
111 }
112
113 void
114 LEDButton::leaveEvent(QEvent *)
115 {
116 emit mouseLeft();
117 }
118
119 void
120 LEDButton::paintEvent(QPaintEvent *)
121 {
122 QPainter paint;
123 QColor color;
124 QBrush brush;
125 QPen pen;
126
127 // First of all we want to know what area should be updated
128 // Initialize coordinates, width, and height of the LED
129 int width = this->width();
130
131 // Make sure the LED is round!
132 if (width > this->height())
133 width = this->height();
134 width -= 2; // leave one pixel border
135 if (width < 0)
136 width = 0;
137
138 QPixmap *tmpMap = 0;
139
140 if (led_state) {
141 if (d->on_map) {
142 paint.begin(this);
143 paint.drawPixmap(0, 0, *d->on_map);
144 paint.end();
145 return;
146 }
147 } else {
148 if (d->off_map) {
149 paint.begin(this);
150 paint.drawPixmap(0, 0, *d->off_map);
151 paint.end();
152 return;
153 }
154 }
155
156 int scale = 1;
157 width *= scale;
158
159 tmpMap = new QPixmap(width, width);
160 tmpMap->fill(palette().background().color());
161 paint.begin(tmpMap);
162
163 paint.setRenderHint(QPainter::Antialiasing, true);
164
165 // Set the color of the LED according to given parameters
166 color = (led_state) ? led_color : d->offcolor;
167
168 // Set the brush to SolidPattern, this fills the entire area
169 // of the ellipse which is drawn first
170 brush.setStyle(Qt::SolidPattern);
171 brush.setColor(color);
172 paint.setBrush(brush);
173
174 // Draws a "flat" LED with the given color:
175 paint.drawEllipse( scale, scale, width - scale*2, width - scale*2 );
176
177 // Draw the bright light spot of the LED now, using modified "old"
178 // painter routine taken from KDEUI´s LEDButton widget:
179
180 // Setting the new width of the pen is essential to avoid "pixelized"
181 // shadow like it can be observed with the old LED code
182 pen.setWidth( 2 * scale );
183
184 // shrink the light on the LED to a size about 2/3 of the complete LED
185 int pos = width/5 + 1;
186 int light_width = width;
187 light_width *= 2;
188 light_width /= 3;
189
190 // Calculate the LED´s "light factor":
191 int light_quote = (130*2/(light_width?light_width:1))+100;
192
193 // Now draw the bright spot on the LED:
194 while (light_width) {
195 color = color.light( light_quote ); // make color lighter
196 pen.setColor( color ); // set color as pen color
197 paint.setPen( pen ); // select the pen for drawing
198 paint.drawEllipse( pos, pos, light_width, light_width ); // draw the ellipse (circle)
199 light_width--;
200 if (!light_width)
201 break;
202 paint.drawEllipse( pos, pos, light_width, light_width );
203 light_width--;
204 if (!light_width)
205 break;
206 paint.drawEllipse( pos, pos, light_width, light_width );
207 pos++; light_width--;
208 }
209
210 // Drawing of bright spot finished, now draw a thin border
211 // around the LED which resembles a shadow with light coming
212 // from the upper left.
213
214 // pen.setWidth( 2 * scale + 1 ); // ### shouldn't this value be smaller for smaller LEDs?
215 pen.setWidth(2 * scale);
216 brush.setStyle(Qt::NoBrush);
217 paint.setBrush(brush); // This avoids filling of the ellipse
218
219 // Set the initial color value to colorGroup().light() (bright) and start
220 // drawing the shadow border at 45° (45*16 = 720).
221
222 int angle = -720;
223 color = palette().light().color();
224
225 for (int arc = 120; arc < 2880; arc += 240) {
226 pen.setColor(color);
227 paint.setPen(pen);
228 int w = width - pen.width()/2 - scale + 1;
229 paint.drawArc(pen.width()/2 + 1, pen.width()/2 + 1, w - 2, w - 2, angle + arc, 240);
230 paint.drawArc(pen.width()/2 + 1, pen.width()/2 + 1, w - 2, w - 2, angle - arc, 240);
231 color = color.dark(110); //FIXME: this should somehow use the contrast value
232 } // end for ( angle = 720; angle < 6480; angle += 160 )
233
234 paint.end();
235 //
236 // painting done
237
238 QPixmap *&dest = led_state ? d->on_map : d->off_map;
239
240 if (scale > 1) {
241
242 QImage i = tmpMap->toImage();
243 width /= scale;
244 delete tmpMap;
245 dest = new QPixmap(QPixmap::fromImage
246 (i.scaled(width, width,
247 Qt::KeepAspectRatio,
248 Qt::SmoothTransformation)));
249
250 } else {
251
252 dest = tmpMap;
253 }
254
255 paint.begin(this);
256 paint.drawPixmap(0, 0, *dest);
257 paint.end();
258 }
259
260 bool
261 LEDButton::state() const
262 {
263 return led_state;
264 }
265
266 QColor
267 LEDButton::color() const
268 {
269 return led_color;
270 }
271
272 void
273 LEDButton::setState( bool state )
274 {
275 if (led_state != state)
276 {
277 led_state = state;
278 update();
279 }
280 }
281
282 void
283 LEDButton::toggleState()
284 {
285 led_state = (led_state == true) ? false : true;
286 // setColor(led_color);
287 update();
288 }
289
290 void
291 LEDButton::setColor(const QColor& col)
292 {
293 if(led_color!=col) {
294 led_color = col;
295 d->offcolor = col.dark(d->dark_factor);
296 delete d->on_map;
297 d->on_map = 0;
298 delete d->off_map;
299 d->off_map = 0;
300 update();
301 }
302 }
303
304 void
305 LEDButton::setDarkFactor(int darkfactor)
306 {
307 if (d->dark_factor != darkfactor) {
308 d->dark_factor = darkfactor;
309 d->offcolor = led_color.dark(darkfactor);
310 update();
311 }
312 }
313
314 int
315 LEDButton::darkFactor() const
316 {
317 return d->dark_factor;
318 }
319
320 void
321 LEDButton::toggle()
322 {
323 toggleState();
324 }
325
326 void
327 LEDButton::on()
328 {
329 setState(true);
330 }
331
332 void
333 LEDButton::off()
334 {
335 setState(false);
336 }
337
338 QSize
339 LEDButton::sizeHint() const
340 {
341 return QSize(17, 17);
342 }
343
344 QSize
345 LEDButton::minimumSizeHint() const
346 {
347 return QSize(17, 17);
348 }
349