Chris@58: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@32: Chris@32: /* Chris@59: Sonic Visualiser Chris@59: An audio file viewer and annotation editor. Chris@59: Centre for Digital Music, Queen Mary, University of London. Chris@32: Chris@59: This program is free software; you can redistribute it and/or Chris@59: modify it under the terms of the GNU General Public License as Chris@59: published by the Free Software Foundation; either version 2 of the Chris@59: License, or (at your option) any later version. See the file Chris@59: COPYING included with this distribution for more information. Chris@32: */ Chris@32: Chris@32: /* Chris@32: This is a modified version of a source file from the KDE Chris@32: libraries. Copyright (c) 1998-2004 Jörg Habenicht, Richard J Chris@32: Moore, Chris Cannam and others, distributed under the GNU Lesser Chris@32: General Public License. Chris@32: Chris@32: Ported to Qt4 by Chris Cannam. Chris@32: */ Chris@32: Chris@32: Chris@32: #include "LEDButton.h" Chris@32: Chris@32: #include Chris@32: #include Chris@32: #include Chris@33: #include Chris@32: Chris@34: #include Chris@34: Chris@32: Chris@32: class LEDButton::LEDButtonPrivate Chris@32: { Chris@32: friend class LEDButton; Chris@32: Chris@32: int dark_factor; Chris@32: QColor offcolor; Chris@32: QPixmap *off_map; Chris@32: QPixmap *on_map; Chris@32: }; Chris@32: Chris@32: Chris@32: LEDButton::LEDButton(QWidget *parent) : Chris@32: QWidget(parent), Chris@34: led_state(true) Chris@32: { Chris@32: QColor col(Qt::green); Chris@32: d = new LEDButton::LEDButtonPrivate; Chris@32: d->dark_factor = 300; Chris@32: d->offcolor = col.dark(300); Chris@32: d->off_map = 0; Chris@32: d->on_map = 0; Chris@32: Chris@32: setColor(col); Chris@32: } Chris@32: Chris@32: Chris@32: LEDButton::LEDButton(const QColor& col, QWidget *parent) : Chris@32: QWidget(parent), Chris@34: led_state(true) Chris@32: { Chris@32: d = new LEDButton::LEDButtonPrivate; Chris@32: d->dark_factor = 300; Chris@32: d->offcolor = col.dark(300); Chris@32: d->off_map = 0; Chris@32: d->on_map = 0; Chris@32: Chris@32: setColor(col); Chris@32: } Chris@32: Chris@34: LEDButton::LEDButton(const QColor& col, bool state, QWidget *parent) : Chris@32: QWidget(parent), Chris@32: led_state(state) Chris@32: { Chris@32: d = new LEDButton::LEDButtonPrivate; Chris@32: d->dark_factor = 300; Chris@32: d->offcolor = col.dark(300); Chris@32: d->off_map = 0; Chris@32: d->on_map = 0; Chris@32: Chris@32: setColor(col); Chris@32: } Chris@32: Chris@32: LEDButton::~LEDButton() Chris@32: { Chris@32: delete d->off_map; Chris@32: delete d->on_map; Chris@32: delete d; Chris@32: } Chris@32: Chris@32: void Chris@33: LEDButton::mousePressEvent(QMouseEvent *e) Chris@33: { Chris@34: std::cerr << "LEDButton(" << this << ")::mousePressEvent" << std::endl; Chris@34: Chris@33: if (e->buttons() & Qt::LeftButton) { Chris@33: toggle(); Chris@34: bool newState = state(); Chris@34: std::cerr << "emitting new state " << newState << std::endl; Chris@34: emit stateChanged(newState); Chris@33: } Chris@33: } Chris@33: Chris@33: void Chris@189: LEDButton::enterEvent(QEvent *) Chris@189: { Chris@189: emit mouseEntered(); Chris@189: } Chris@189: Chris@189: void Chris@189: LEDButton::leaveEvent(QEvent *) Chris@189: { Chris@189: emit mouseLeft(); Chris@189: } Chris@189: Chris@189: void Chris@32: LEDButton::paintEvent(QPaintEvent *) Chris@32: { Chris@32: QPainter paint; Chris@32: QColor color; Chris@32: QBrush brush; Chris@32: QPen pen; Chris@32: Chris@32: // First of all we want to know what area should be updated Chris@32: // Initialize coordinates, width, and height of the LED Chris@32: int width = this->width(); Chris@32: Chris@32: // Make sure the LED is round! Chris@32: if (width > this->height()) Chris@32: width = this->height(); Chris@32: width -= 2; // leave one pixel border Chris@32: if (width < 0) Chris@32: width = 0; Chris@32: Chris@34: QPixmap *tmpMap = 0; Chris@34: Chris@34: if (led_state) { Chris@34: if (d->on_map) { Chris@496: if (d->on_map->size() == size()) { Chris@496: paint.begin(this); Chris@496: paint.drawPixmap(0, 0, *d->on_map); Chris@496: paint.end(); Chris@496: return; Chris@496: } else { Chris@496: delete d->on_map; Chris@496: d->on_map = 0; Chris@496: } Chris@34: } Chris@34: } else { Chris@34: if (d->off_map) { Chris@496: if (d->off_map->size() == size()) { Chris@496: paint.begin(this); Chris@496: paint.drawPixmap(0, 0, *d->off_map); Chris@496: paint.end(); Chris@496: return; Chris@496: } else { Chris@496: delete d->off_map; Chris@496: d->off_map = 0; Chris@496: } Chris@34: } Chris@34: } Chris@32: Chris@32: int scale = 1; Chris@34: width *= scale; Chris@32: Chris@34: tmpMap = new QPixmap(width, width); Chris@34: tmpMap->fill(palette().background().color()); Chris@34: paint.begin(tmpMap); Chris@32: Chris@33: paint.setRenderHint(QPainter::Antialiasing, true); Chris@32: Chris@32: // Set the color of the LED according to given parameters Chris@32: color = (led_state) ? led_color : d->offcolor; Chris@32: Chris@32: // Set the brush to SolidPattern, this fills the entire area Chris@32: // of the ellipse which is drawn first Chris@32: brush.setStyle(Qt::SolidPattern); Chris@32: brush.setColor(color); Chris@32: paint.setBrush(brush); Chris@32: Chris@32: // Draws a "flat" LED with the given color: Chris@32: paint.drawEllipse( scale, scale, width - scale*2, width - scale*2 ); Chris@32: Chris@32: // Draw the bright light spot of the LED now, using modified "old" Chris@32: // painter routine taken from KDEUI´s LEDButton widget: Chris@32: Chris@32: // Setting the new width of the pen is essential to avoid "pixelized" Chris@32: // shadow like it can be observed with the old LED code Chris@32: pen.setWidth( 2 * scale ); Chris@32: Chris@32: // shrink the light on the LED to a size about 2/3 of the complete LED Chris@32: int pos = width/5 + 1; Chris@32: int light_width = width; Chris@32: light_width *= 2; Chris@32: light_width /= 3; Chris@32: Chris@32: // Calculate the LED´s "light factor": Chris@32: int light_quote = (130*2/(light_width?light_width:1))+100; Chris@32: Chris@32: // Now draw the bright spot on the LED: Chris@32: while (light_width) { Chris@32: color = color.light( light_quote ); // make color lighter Chris@32: pen.setColor( color ); // set color as pen color Chris@32: paint.setPen( pen ); // select the pen for drawing Chris@32: paint.drawEllipse( pos, pos, light_width, light_width ); // draw the ellipse (circle) Chris@32: light_width--; Chris@32: if (!light_width) Chris@32: break; Chris@32: paint.drawEllipse( pos, pos, light_width, light_width ); Chris@32: light_width--; Chris@32: if (!light_width) Chris@32: break; Chris@32: paint.drawEllipse( pos, pos, light_width, light_width ); Chris@32: pos++; light_width--; Chris@32: } Chris@32: Chris@32: // Drawing of bright spot finished, now draw a thin border Chris@32: // around the LED which resembles a shadow with light coming Chris@32: // from the upper left. Chris@32: Chris@33: // pen.setWidth( 2 * scale + 1 ); // ### shouldn't this value be smaller for smaller LEDs? Chris@33: pen.setWidth(2 * scale); Chris@32: brush.setStyle(Qt::NoBrush); Chris@32: paint.setBrush(brush); // This avoids filling of the ellipse Chris@32: Chris@32: // Set the initial color value to colorGroup().light() (bright) and start Chris@32: // drawing the shadow border at 45° (45*16 = 720). Chris@32: Chris@32: int angle = -720; Chris@32: color = palette().light().color(); Chris@32: Chris@32: for (int arc = 120; arc < 2880; arc += 240) { Chris@32: pen.setColor(color); Chris@32: paint.setPen(pen); Chris@32: int w = width - pen.width()/2 - scale + 1; Chris@33: paint.drawArc(pen.width()/2 + 1, pen.width()/2 + 1, w - 2, w - 2, angle + arc, 240); Chris@33: paint.drawArc(pen.width()/2 + 1, pen.width()/2 + 1, w - 2, w - 2, angle - arc, 240); Chris@32: color = color.dark(110); //FIXME: this should somehow use the contrast value Chris@32: } // end for ( angle = 720; angle < 6480; angle += 160 ) Chris@32: Chris@32: paint.end(); Chris@32: // Chris@32: // painting done Chris@32: Chris@34: QPixmap *&dest = led_state ? d->on_map : d->off_map; Chris@34: Chris@34: if (scale > 1) { Chris@34: Chris@32: QImage i = tmpMap->toImage(); Chris@33: width /= scale; Chris@32: delete tmpMap; Chris@33: dest = new QPixmap(QPixmap::fromImage Chris@33: (i.scaled(width, width, Chris@33: Qt::KeepAspectRatio, Chris@33: Qt::SmoothTransformation))); Chris@34: Chris@34: } else { Chris@34: Chris@34: dest = tmpMap; Chris@32: } Chris@34: Chris@34: paint.begin(this); Chris@34: paint.drawPixmap(0, 0, *dest); Chris@34: paint.end(); Chris@32: } Chris@32: Chris@34: bool Chris@32: LEDButton::state() const Chris@32: { Chris@32: return led_state; Chris@32: } Chris@32: Chris@32: QColor Chris@32: LEDButton::color() const Chris@32: { Chris@32: return led_color; Chris@32: } Chris@32: Chris@32: void Chris@34: LEDButton::setState( bool state ) Chris@32: { Chris@32: if (led_state != state) Chris@32: { Chris@32: led_state = state; Chris@32: update(); Chris@32: } Chris@32: } Chris@32: Chris@32: void Chris@32: LEDButton::toggleState() Chris@32: { Chris@34: led_state = (led_state == true) ? false : true; Chris@32: // setColor(led_color); Chris@32: update(); Chris@32: } Chris@32: Chris@32: void Chris@32: LEDButton::setColor(const QColor& col) Chris@32: { Chris@32: if(led_color!=col) { Chris@32: led_color = col; Chris@32: d->offcolor = col.dark(d->dark_factor); Chris@32: delete d->on_map; Chris@32: d->on_map = 0; Chris@32: delete d->off_map; Chris@32: d->off_map = 0; Chris@32: update(); Chris@32: } Chris@32: } Chris@32: Chris@32: void Chris@32: LEDButton::setDarkFactor(int darkfactor) Chris@32: { Chris@32: if (d->dark_factor != darkfactor) { Chris@32: d->dark_factor = darkfactor; Chris@32: d->offcolor = led_color.dark(darkfactor); Chris@32: update(); Chris@32: } Chris@32: } Chris@32: Chris@32: int Chris@32: LEDButton::darkFactor() const Chris@32: { Chris@32: return d->dark_factor; Chris@32: } Chris@32: Chris@32: void Chris@32: LEDButton::toggle() Chris@32: { Chris@32: toggleState(); Chris@32: } Chris@32: Chris@32: void Chris@32: LEDButton::on() Chris@32: { Chris@34: setState(true); Chris@32: } Chris@32: Chris@32: void Chris@32: LEDButton::off() Chris@32: { Chris@34: setState(false); Chris@32: } Chris@32: Chris@32: QSize Chris@32: LEDButton::sizeHint() const Chris@32: { Chris@33: return QSize(17, 17); Chris@32: } Chris@32: Chris@32: QSize Chris@32: LEDButton::minimumSizeHint() const Chris@32: { Chris@33: return QSize(17, 17); Chris@32: } Chris@32: