annotate widgets/LEDButton.cpp @ 183:5f86ae638b04

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