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