svgui
1.9
|
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 cerr << "LEDButton(" << this << ")::mousePressEvent" << endl; 00098 00099 if (e->buttons() & Qt::LeftButton) { 00100 toggle(); 00101 bool newState = state(); 00102 SVDEBUG << "emitting new state " << newState << 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 if (d->on_map->size() == size()) { 00143 paint.begin(this); 00144 paint.drawPixmap(0, 0, *d->on_map); 00145 paint.end(); 00146 return; 00147 } else { 00148 delete d->on_map; 00149 d->on_map = 0; 00150 } 00151 } 00152 } else { 00153 if (d->off_map) { 00154 if (d->off_map->size() == size()) { 00155 paint.begin(this); 00156 paint.drawPixmap(0, 0, *d->off_map); 00157 paint.end(); 00158 return; 00159 } else { 00160 delete d->off_map; 00161 d->off_map = 0; 00162 } 00163 } 00164 } 00165 00166 int scale = 1; 00167 width *= scale; 00168 00169 tmpMap = new QPixmap(width, width); 00170 tmpMap->fill(palette().background().color()); 00171 paint.begin(tmpMap); 00172 00173 paint.setRenderHint(QPainter::Antialiasing, true); 00174 00175 // Set the color of the LED according to given parameters 00176 color = (led_state) ? led_color : d->offcolor; 00177 00178 // Set the brush to SolidPattern, this fills the entire area 00179 // of the ellipse which is drawn first 00180 brush.setStyle(Qt::SolidPattern); 00181 brush.setColor(color); 00182 paint.setBrush(brush); 00183 00184 // Draws a "flat" LED with the given color: 00185 paint.drawEllipse( scale, scale, width - scale*2, width - scale*2 ); 00186 00187 // Draw the bright light spot of the LED now, using modified "old" 00188 // painter routine taken from KDEUI´s LEDButton widget: 00189 00190 // Setting the new width of the pen is essential to avoid "pixelized" 00191 // shadow like it can be observed with the old LED code 00192 pen.setWidth( 2 * scale ); 00193 00194 // shrink the light on the LED to a size about 2/3 of the complete LED 00195 int pos = width/5 + 1; 00196 int light_width = width; 00197 light_width *= 2; 00198 light_width /= 3; 00199 00200 // Calculate the LED´s "light factor": 00201 int light_quote = (130*2/(light_width?light_width:1))+100; 00202 00203 // Now draw the bright spot on the LED: 00204 while (light_width) { 00205 color = color.light( light_quote ); // make color lighter 00206 pen.setColor( color ); // set color as pen color 00207 paint.setPen( pen ); // select the pen for drawing 00208 paint.drawEllipse( pos, pos, light_width, light_width ); // draw the ellipse (circle) 00209 light_width--; 00210 if (!light_width) 00211 break; 00212 paint.drawEllipse( pos, pos, light_width, light_width ); 00213 light_width--; 00214 if (!light_width) 00215 break; 00216 paint.drawEllipse( pos, pos, light_width, light_width ); 00217 pos++; light_width--; 00218 } 00219 00220 // Drawing of bright spot finished, now draw a thin border 00221 // around the LED which resembles a shadow with light coming 00222 // from the upper left. 00223 00224 // pen.setWidth( 2 * scale + 1 ); // ### shouldn't this value be smaller for smaller LEDs? 00225 pen.setWidth(2 * scale); 00226 brush.setStyle(Qt::NoBrush); 00227 paint.setBrush(brush); // This avoids filling of the ellipse 00228 00229 // Set the initial color value to colorGroup().light() (bright) and start 00230 // drawing the shadow border at 45° (45*16 = 720). 00231 00232 int angle = -720; 00233 color = palette().light().color(); 00234 00235 for (int arc = 120; arc < 2880; arc += 240) { 00236 pen.setColor(color); 00237 paint.setPen(pen); 00238 int w = width - pen.width()/2 - scale + 1; 00239 paint.drawArc(pen.width()/2 + 1, pen.width()/2 + 1, w - 2, w - 2, angle + arc, 240); 00240 paint.drawArc(pen.width()/2 + 1, pen.width()/2 + 1, w - 2, w - 2, angle - arc, 240); 00241 color = color.dark(110); //FIXME: this should somehow use the contrast value 00242 } // end for ( angle = 720; angle < 6480; angle += 160 ) 00243 00244 paint.end(); 00245 // 00246 // painting done 00247 00248 QPixmap *&dest = led_state ? d->on_map : d->off_map; 00249 00250 if (scale > 1) { 00251 00252 QImage i = tmpMap->toImage(); 00253 width /= scale; 00254 delete tmpMap; 00255 dest = new QPixmap(QPixmap::fromImage 00256 (i.scaled(width, width, 00257 Qt::KeepAspectRatio, 00258 Qt::SmoothTransformation))); 00259 00260 } else { 00261 00262 dest = tmpMap; 00263 } 00264 00265 paint.begin(this); 00266 paint.drawPixmap(0, 0, *dest); 00267 paint.end(); 00268 } 00269 00270 bool 00271 LEDButton::state() const 00272 { 00273 return led_state; 00274 } 00275 00276 QColor 00277 LEDButton::color() const 00278 { 00279 return led_color; 00280 } 00281 00282 void 00283 LEDButton::setState( bool state ) 00284 { 00285 if (led_state != state) 00286 { 00287 led_state = state; 00288 update(); 00289 } 00290 } 00291 00292 void 00293 LEDButton::toggleState() 00294 { 00295 led_state = (led_state == true) ? false : true; 00296 // setColor(led_color); 00297 update(); 00298 } 00299 00300 void 00301 LEDButton::setColor(const QColor& col) 00302 { 00303 if(led_color!=col) { 00304 led_color = col; 00305 d->offcolor = col.dark(d->dark_factor); 00306 delete d->on_map; 00307 d->on_map = 0; 00308 delete d->off_map; 00309 d->off_map = 0; 00310 update(); 00311 } 00312 } 00313 00314 void 00315 LEDButton::setDarkFactor(int darkfactor) 00316 { 00317 if (d->dark_factor != darkfactor) { 00318 d->dark_factor = darkfactor; 00319 d->offcolor = led_color.dark(darkfactor); 00320 update(); 00321 } 00322 } 00323 00324 int 00325 LEDButton::darkFactor() const 00326 { 00327 return d->dark_factor; 00328 } 00329 00330 void 00331 LEDButton::toggle() 00332 { 00333 toggleState(); 00334 } 00335 00336 void 00337 LEDButton::on() 00338 { 00339 setState(true); 00340 } 00341 00342 void 00343 LEDButton::off() 00344 { 00345 setState(false); 00346 } 00347 00348 QSize 00349 LEDButton::sizeHint() const 00350 { 00351 return QSize(17, 17); 00352 } 00353 00354 QSize 00355 LEDButton::minimumSizeHint() const 00356 { 00357 return QSize(17, 17); 00358 } 00359