LEDButton.cpp

Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     
00008     This program is free software; you can redistribute it and/or
00009     modify it under the terms of the GNU General Public License as
00010     published by the Free Software Foundation; either version 2 of the
00011     License, or (at your option) any later version.  See the file
00012     COPYING included with this distribution for more information.
00013 */
00014 
00015 /*
00016     This is a modified version of a source file from the KDE
00017     libraries.  Copyright (c) 1998-2004 Jörg Habenicht, Richard J
00018     Moore, Chris Cannam and others, distributed under the GNU Lesser
00019     General Public License.
00020 
00021     Ported to Qt4 by Chris Cannam.
00022 */
00023 
00024 
00025 #include "LEDButton.h"
00026 
00027 #include <QPainter>
00028 #include <QImage>
00029 #include <QColor>
00030 #include <QMouseEvent>
00031 
00032 #include <iostream>
00033 
00034 
00035 class LEDButton::LEDButtonPrivate
00036 {
00037     friend class LEDButton;
00038 
00039     int dark_factor;
00040     QColor offcolor;
00041     QPixmap *off_map;
00042     QPixmap *on_map;
00043 };
00044 
00045 
00046 LEDButton::LEDButton(QWidget *parent) :
00047     QWidget(parent),
00048     led_state(true)
00049 {
00050     QColor col(Qt::green);
00051     d = new LEDButton::LEDButtonPrivate;
00052     d->dark_factor = 300;
00053     d->offcolor = col.dark(300);
00054     d->off_map = 0;
00055     d->on_map = 0;
00056     
00057     setColor(col);
00058 }
00059 
00060 
00061 LEDButton::LEDButton(const QColor& col, QWidget *parent) :
00062     QWidget(parent),
00063     led_state(true)
00064 {
00065     d = new LEDButton::LEDButtonPrivate;
00066     d->dark_factor = 300;
00067     d->offcolor = col.dark(300);
00068     d->off_map = 0;
00069     d->on_map = 0;
00070 
00071     setColor(col);
00072 }
00073 
00074 LEDButton::LEDButton(const QColor& col, bool state, QWidget *parent) :
00075     QWidget(parent),
00076     led_state(state)
00077 {
00078     d = new LEDButton::LEDButtonPrivate;
00079     d->dark_factor = 300;
00080     d->offcolor = col.dark(300);
00081     d->off_map = 0;
00082     d->on_map = 0;
00083 
00084     setColor(col);
00085 }
00086 
00087 LEDButton::~LEDButton()
00088 {
00089     delete d->off_map;
00090     delete d->on_map;
00091     delete d;
00092 }
00093 
00094 void
00095 LEDButton::mousePressEvent(QMouseEvent *e)
00096 {
00097     std::cerr << "LEDButton(" << this << ")::mousePressEvent" << std::endl;
00098 
00099     if (e->buttons() & Qt::LeftButton) {
00100         toggle();
00101         bool newState = state();
00102         std::cerr << "emitting new state " << newState << std::endl;
00103         emit stateChanged(newState);
00104     }
00105 }
00106 
00107 void
00108 LEDButton::enterEvent(QEvent *)
00109 {
00110     emit mouseEntered();
00111 }
00112 
00113 void
00114 LEDButton::leaveEvent(QEvent *)
00115 {
00116     emit mouseLeft();
00117 }
00118 
00119 void
00120 LEDButton::paintEvent(QPaintEvent *)
00121 {
00122     QPainter paint;
00123     QColor color;
00124     QBrush brush;
00125     QPen pen;
00126                 
00127     // First of all we want to know what area should be updated
00128     // Initialize coordinates, width, and height of the LED
00129     int width = this->width();
00130 
00131     // Make sure the LED is round!
00132     if (width > this->height())
00133         width = this->height();
00134     width -= 2; // leave one pixel border
00135     if (width < 0) 
00136         width = 0;
00137 
00138     QPixmap *tmpMap = 0;
00139 
00140     if (led_state) {
00141         if (d->on_map) {
00142             paint.begin(this);
00143             paint.drawPixmap(0, 0, *d->on_map);
00144             paint.end();
00145             return;
00146         }
00147     } else {
00148         if (d->off_map) {
00149             paint.begin(this);
00150             paint.drawPixmap(0, 0, *d->off_map);
00151             paint.end();
00152             return;
00153         }
00154     }
00155 
00156     int scale = 1;
00157     width *= scale;
00158 
00159     tmpMap = new QPixmap(width, width);
00160     tmpMap->fill(palette().background().color());
00161     paint.begin(tmpMap);
00162 
00163     paint.setRenderHint(QPainter::Antialiasing, true);
00164 
00165     // Set the color of the LED according to given parameters
00166     color = (led_state) ? led_color : d->offcolor;
00167 
00168     // Set the brush to SolidPattern, this fills the entire area
00169     // of the ellipse which is drawn first
00170     brush.setStyle(Qt::SolidPattern);
00171     brush.setColor(color);
00172     paint.setBrush(brush);
00173 
00174     // Draws a "flat" LED with the given color:
00175     paint.drawEllipse( scale, scale, width - scale*2, width - scale*2 );
00176 
00177     // Draw the bright light spot of the LED now, using modified "old"
00178     // painter routine taken from KDEUI´s LEDButton widget:
00179 
00180     // Setting the new width of the pen is essential to avoid "pixelized"
00181     // shadow like it can be observed with the old LED code
00182     pen.setWidth( 2 * scale );
00183 
00184     // shrink the light on the LED to a size about 2/3 of the complete LED
00185     int pos = width/5 + 1;
00186     int light_width = width;
00187     light_width *= 2;
00188     light_width /= 3;
00189         
00190     // Calculate the LED´s "light factor":
00191     int light_quote = (130*2/(light_width?light_width:1))+100;
00192 
00193     // Now draw the bright spot on the LED:
00194     while (light_width) {
00195         color = color.light( light_quote );                      // make color lighter
00196         pen.setColor( color );                                   // set color as pen color
00197         paint.setPen( pen );                                     // select the pen for drawing
00198         paint.drawEllipse( pos, pos, light_width, light_width ); // draw the ellipse (circle)
00199         light_width--;
00200         if (!light_width)
00201             break;
00202         paint.drawEllipse( pos, pos, light_width, light_width );
00203         light_width--;
00204         if (!light_width)
00205             break;
00206         paint.drawEllipse( pos, pos, light_width, light_width );
00207         pos++; light_width--;
00208     }
00209 
00210     // Drawing of bright spot finished, now draw a thin border
00211     // around the LED which resembles a shadow with light coming
00212     // from the upper left.
00213 
00214 //    pen.setWidth( 2 * scale + 1 ); // ### shouldn't this value be smaller for smaller LEDs?
00215     pen.setWidth(2 * scale);
00216     brush.setStyle(Qt::NoBrush);
00217     paint.setBrush(brush); // This avoids filling of the ellipse
00218 
00219     // Set the initial color value to colorGroup().light() (bright) and start
00220     // drawing the shadow border at 45° (45*16 = 720).
00221 
00222     int angle = -720;
00223     color = palette().light().color();
00224     
00225     for (int arc = 120; arc < 2880; arc += 240) {
00226         pen.setColor(color);
00227         paint.setPen(pen);
00228         int w = width - pen.width()/2 - scale + 1;
00229         paint.drawArc(pen.width()/2 + 1, pen.width()/2 + 1, w - 2, w - 2, angle + arc, 240);
00230         paint.drawArc(pen.width()/2 + 1, pen.width()/2 + 1, w - 2, w - 2, angle - arc, 240);
00231         color = color.dark(110); //FIXME: this should somehow use the contrast value
00232     }   // end for ( angle = 720; angle < 6480; angle += 160 )
00233 
00234     paint.end();
00235     //
00236     // painting done
00237 
00238     QPixmap *&dest = led_state ? d->on_map : d->off_map;
00239 
00240     if (scale > 1) {
00241 
00242         QImage i = tmpMap->toImage();
00243         width /= scale;
00244         delete tmpMap;
00245         dest = new QPixmap(QPixmap::fromImage
00246                            (i.scaled(width, width, 
00247                                      Qt::KeepAspectRatio,
00248                                      Qt::SmoothTransformation)));
00249 
00250     } else {
00251 
00252         dest = tmpMap;
00253     }
00254 
00255     paint.begin(this);
00256     paint.drawPixmap(0, 0, *dest);
00257     paint.end();
00258 }
00259 
00260 bool
00261 LEDButton::state() const
00262 {
00263     return led_state;
00264 }
00265 
00266 QColor
00267 LEDButton::color() const
00268 {
00269     return led_color;
00270 }
00271 
00272 void
00273 LEDButton::setState( bool state )
00274 {
00275     if (led_state != state)
00276     {
00277         led_state = state;
00278         update();
00279     }
00280 }
00281 
00282 void
00283 LEDButton::toggleState()
00284 {
00285     led_state = (led_state == true) ? false : true;
00286     // setColor(led_color);
00287     update();
00288 }
00289 
00290 void
00291 LEDButton::setColor(const QColor& col)
00292 {
00293     if(led_color!=col) {
00294         led_color = col;
00295         d->offcolor = col.dark(d->dark_factor);
00296         delete d->on_map;
00297         d->on_map = 0;
00298         delete d->off_map;
00299         d->off_map = 0;
00300         update();
00301     }
00302 }
00303 
00304 void
00305 LEDButton::setDarkFactor(int darkfactor)
00306 {
00307     if (d->dark_factor != darkfactor) {
00308         d->dark_factor = darkfactor;
00309         d->offcolor = led_color.dark(darkfactor);
00310         update();
00311     }
00312 }
00313 
00314 int
00315 LEDButton::darkFactor() const
00316 {
00317     return d->dark_factor;
00318 }
00319 
00320 void
00321 LEDButton::toggle()
00322 {
00323     toggleState();
00324 }
00325 
00326 void
00327 LEDButton::on()
00328 {
00329     setState(true);
00330 }
00331 
00332 void
00333 LEDButton::off()
00334 {
00335     setState(false);
00336 }
00337 
00338 QSize
00339 LEDButton::sizeHint() const
00340 {
00341     return QSize(17, 17);
00342 }
00343 
00344 QSize
00345 LEDButton::minimumSizeHint() const
00346 {
00347     return QSize(17, 17);
00348 }
00349 

Generated on Wed Feb 20 15:45:26 2008 for SonicVisualiser by  doxygen 1.5.1