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