/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* Rosegarden A MIDI and audio sequencer and musical notation editor. Copyright 2000-2011 the Rosegarden development team. This file is based on KLed from the KDE libraries Copyright (C) 1998 Jörg Habenicht (j.habenicht@europemail.com) Including antialiasing implementation from Chris Cannam, April 2004 Other copyrights also apply to some parts of this work. Please see the AUTHORS file and individual file headers for details. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. See the file COPYING included with this distribution for more information. */ #include "Led.h" #include #include #include #include namespace Rosegarden { class Led::LedPrivate { friend class Led; int dark_factor; QColor offcolor; QPixmap *off_map; QPixmap *on_map; }; Led::Led(const QColor& col, QWidget *parent) : QWidget(parent), led_state(On) { d = new Led::LedPrivate; d->dark_factor = 300; d->offcolor = col.dark(300); d->off_map = 0; d->on_map = 0; setColor(col); } Led::~Led() { delete d->off_map; delete d->on_map; delete d; } void Led::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(paletteBackgroundColor()); 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 ); // Assign the brush to the painter // 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 Led 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--; } paint.drawPoint(pos, pos); // 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 ); // Switch off the brush paint.setBrush( brush ); // This avoids filling of the ellipse // Set the initial color value to palette().light() (bright) and start // drawing the shadow border at 45° (45*16 = 720). int angle = -720; //color = palette().light(); color = Qt::white; 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->convertToImage(); width /= 3; i = i.smoothScale(width, width); delete tmpMap; dest = new QPixmap(QPixmap::fromImage(i)); paint.begin(this); paint.drawPixmap(0, 0, *dest); paint.end(); } } Led::State Led::state() const { return led_state; } QColor Led::color() const { return led_color; } void Led::setState( State state ) { if (led_state != state) { led_state = state; update(); } } void Led::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 Led::setDarkFactor(int darkfactor) { if (d->dark_factor != darkfactor) { d->dark_factor = darkfactor; d->offcolor = led_color.dark(darkfactor); update(); } } int Led::darkFactor() const { return d->dark_factor; } void Led::toggle() { led_state = (led_state == On) ? Off : On; update(); } void Led::on() { setState(On); } void Led::off() { setState(Off); } QSize Led::sizeHint() const { return QSize(16, 16); } QSize Led::minimumSizeHint() const { return QSize(16, 16 ); } } #include "Led.moc"