Mercurial > hg > svgui
diff widgets/LEDButton.cpp @ 32:c53b949ef142
* Add LED button
* Add note model playback (currently assuming that value == MIDI pitch)
* Reorganise PlayParameters and move repository from ViewManager to new
PlayParameterRepository class
author | Chris Cannam |
---|---|
date | Wed, 15 Feb 2006 17:58:35 +0000 |
parents | |
children | 651e4e868bcc |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/widgets/LEDButton.cpp Wed Feb 15 17:58:35 2006 +0000 @@ -0,0 +1,316 @@ +/* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */ + +/* + A waveform viewer and audio annotation editor. + Chris Cannam, Queen Mary University of London, 2005-2006 + + This is experimental software. Not for distribution. +*/ + +/* + This is a modified version of a source file from the KDE + libraries. Copyright (c) 1998-2004 Jörg Habenicht, Richard J + Moore, Chris Cannam and others, distributed under the GNU Lesser + General Public License. + + Ported to Qt4 by Chris Cannam. +*/ + + +#include "LEDButton.h" + +#include <QPainter> +#include <QImage> +#include <QColor> + + +class LEDButton::LEDButtonPrivate +{ + friend class LEDButton; + + int dark_factor; + QColor offcolor; + QPixmap *off_map; + QPixmap *on_map; +}; + + +LEDButton::LEDButton(QWidget *parent) : + QWidget(parent), + led_state(On) +{ + QColor col(Qt::green); + d = new LEDButton::LEDButtonPrivate; + d->dark_factor = 300; + d->offcolor = col.dark(300); + d->off_map = 0; + d->on_map = 0; + + setColor(col); +} + + +LEDButton::LEDButton(const QColor& col, QWidget *parent) : + QWidget(parent), + led_state(On) +{ + d = new LEDButton::LEDButtonPrivate; + d->dark_factor = 300; + d->offcolor = col.dark(300); + d->off_map = 0; + d->on_map = 0; + + setColor(col); +} + +LEDButton::LEDButton(const QColor& col, LEDButton::State state, QWidget *parent) : + QWidget(parent), + led_state(state) +{ + d = new LEDButton::LEDButtonPrivate; + d->dark_factor = 300; + d->offcolor = col.dark(300); + d->off_map = 0; + d->on_map = 0; + + setColor(col); +} + +LEDButton::~LEDButton() +{ + delete d->off_map; + delete d->on_map; + delete d; +} + +void +LEDButton::paintEvent(QPaintEvent *) +{ + QPainter paint; + QColor color; + QBrush brush; + QPen pen; + + // First of all we want to know what area should be updated + // Initialize coordinates, width, and height of the LED + int width = this->width(); + + // Make sure the LED is round! + if (width > this->height()) + width = this->height(); + width -= 2; // leave one pixel border + if (width < 0) + width = 0; + + // maybe we could stop HERE, if width <=0 ? + + int scale = 1; + QPixmap *tmpMap = 0; + bool smooth = true; + + if (smooth) { + if (led_state) { + if (d->on_map) { + paint.begin(this); + paint.drawPixmap(0, 0, *d->on_map); + paint.end(); + return; + } + } else { + if (d->off_map) { + paint.begin(this); + paint.drawPixmap(0, 0, *d->off_map); + paint.end(); + return; + } + } + + scale = 3; + width *= scale; + + tmpMap = new QPixmap(width, width); + tmpMap->fill(palette().background().color()); + paint.begin(tmpMap); + + } else { + paint.begin(this); + } + + paint.setRenderHint(QPainter::Antialiasing, false); + + // Set the color of the LED according to given parameters + color = (led_state) ? led_color : d->offcolor; + + // Set the brush to SolidPattern, this fills the entire area + // of the ellipse which is drawn first + brush.setStyle(Qt::SolidPattern); + brush.setColor(color); + paint.setBrush(brush); + + // Draws a "flat" LED with the given color: + paint.drawEllipse( scale, scale, width - scale*2, width - scale*2 ); + + // Draw the bright light spot of the LED now, using modified "old" + // painter routine taken from KDEUI´s LEDButton widget: + + // Setting the new width of the pen is essential to avoid "pixelized" + // shadow like it can be observed with the old LED code + pen.setWidth( 2 * scale ); + + // shrink the light on the LED to a size about 2/3 of the complete LED + int pos = width/5 + 1; + int light_width = width; + light_width *= 2; + light_width /= 3; + + // Calculate the LED´s "light factor": + int light_quote = (130*2/(light_width?light_width:1))+100; + + // Now draw the bright spot on the LED: + while (light_width) { + color = color.light( light_quote ); // make color lighter + pen.setColor( color ); // set color as pen color + paint.setPen( pen ); // select the pen for drawing + paint.drawEllipse( pos, pos, light_width, light_width ); // draw the ellipse (circle) + light_width--; + if (!light_width) + break; + paint.drawEllipse( pos, pos, light_width, light_width ); + light_width--; + if (!light_width) + break; + paint.drawEllipse( pos, pos, light_width, light_width ); + pos++; light_width--; + } + + // Drawing of bright spot finished, now draw a thin border + // around the LED which resembles a shadow with light coming + // from the upper left. + + pen.setWidth( 2 * scale + 1 ); // ### shouldn't this value be smaller for smaller LEDs? + brush.setStyle(Qt::NoBrush); + paint.setBrush(brush); // This avoids filling of the ellipse + + // Set the initial color value to colorGroup().light() (bright) and start + // drawing the shadow border at 45° (45*16 = 720). + + int angle = -720; + color = palette().light().color(); + + for (int arc = 120; arc < 2880; arc += 240) { + pen.setColor(color); + paint.setPen(pen); + int w = width - pen.width()/2 - scale + 1; + paint.drawArc(pen.width()/2, pen.width()/2, w, w, angle + arc, 240); + paint.drawArc(pen.width()/2, pen.width()/2, w, w, angle - arc, 240); + color = color.dark(110); //FIXME: this should somehow use the contrast value + } // end for ( angle = 720; angle < 6480; angle += 160 ) + + paint.end(); + // + // painting done + + if (smooth) { + QPixmap *&dest = led_state ? d->on_map : d->off_map; + QImage i = tmpMap->toImage(); + width /= 3; + i = i.scaled(width, width, + Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + delete tmpMap; + dest = new QPixmap(QPixmap::fromImage(i)); + paint.begin(this); + paint.drawPixmap(0, 0, *dest); + paint.end(); + } +} + +LEDButton::State +LEDButton::state() const +{ + return led_state; +} + +QColor +LEDButton::color() const +{ + return led_color; +} + +void +LEDButton::setState( State state ) +{ + if (led_state != state) + { + led_state = state; + update(); + } +} + +void +LEDButton::toggleState() +{ + led_state = (led_state == On) ? Off : On; + // setColor(led_color); + update(); +} + +void +LEDButton::setColor(const QColor& col) +{ + if(led_color!=col) { + led_color = col; + d->offcolor = col.dark(d->dark_factor); + delete d->on_map; + d->on_map = 0; + delete d->off_map; + d->off_map = 0; + update(); + } +} + +void +LEDButton::setDarkFactor(int darkfactor) +{ + if (d->dark_factor != darkfactor) { + d->dark_factor = darkfactor; + d->offcolor = led_color.dark(darkfactor); + update(); + } +} + +int +LEDButton::darkFactor() const +{ + return d->dark_factor; +} + +void +LEDButton::toggle() +{ + toggleState(); +} + +void +LEDButton::on() +{ + setState(On); +} + +void +LEDButton::off() +{ + setState(Off); +} + +QSize +LEDButton::sizeHint() const +{ + return QSize(16, 16); +} + +QSize +LEDButton::minimumSizeHint() const +{ + return QSize(16, 16 ); +} +