karbon

vgradientwidget.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2001, The Karbon Developers
00003    Copyright (C) 2002, The Karbon Developers
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include <qlabel.h>
00022 #include <qframe.h>
00023 #include <qbitmap.h>
00024 
00025 #include <kcolorbutton.h>
00026 #include <kcombobox.h>
00027 #include <klocale.h>
00028 #include <qpainter.h>
00029 #include <kiconloader.h>
00030 
00031 #include "vgradientwidget.h"
00032 #include "vcolordlg.h"
00033 #include "vfill.h"
00034 #include "vkopainter.h"
00035 #include "vcursor.h"
00036 
00037 #define midPoint_width 7
00038 #define midPoint_height 10
00039 static unsigned char midPoint_bits[] = {
00040    0x08, 0x08, 0x1c, 0x1c, 0x2a, 0x2a, 0x08, 0x08, 0x08, 0x08
00041 };
00042 
00043 #define colorStopBorder_width 11
00044 #define colorStopBorder_height 11
00045 static unsigned char colorStopBorder_bits[] = {
00046    0x20, 0x00, 0x50, 0x00, 0x50, 0x00, 0x88, 0x00, 0x88, 0x00, 0x04, 0x01,
00047    0x04, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x04, 0xff, 0x07
00048 };
00049 
00050 #define colorStop_width 9
00051 #define colorStop_height 10
00052 static unsigned char colorStop_bits[] = {
00053    0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x38, 0x00, 0x38, 0x00, 0x7c, 0x00,
00054    0x7c, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xff, 0x01
00055 };
00056 
00057 VGradientWidget::VGradientWidget( VGradient& gradient, QWidget* parent, const char* name )
00058         : QWidget( parent, name ), m_gradient( &gradient )
00059 {
00060     setBackgroundMode( Qt::NoBackground );
00061     setMinimumSize( 105, 35 );
00062 } // VGradientWidget::VGradientWidget
00063 
00064 VGradientWidget::~VGradientWidget()
00065 {
00066 } // VGradientWidget::~VGradientWidget
00067 
00068 void VGradientWidget::paintColorStop( QPainter& p, int x, VColor& color )
00069 {
00070     QBitmap bitmap;
00071 
00072     bitmap = QBitmap( colorStop_width, colorStop_height, colorStop_bits, true );
00073     bitmap.setMask( bitmap );
00074     p.setPen( color );
00075     p.drawPixmap( x - 4, 1, bitmap );
00076 
00077     bitmap = QBitmap( colorStopBorder_width, colorStopBorder_height, colorStopBorder_bits, true );
00078     bitmap.setMask( bitmap );
00079     p.setPen( Qt::black );
00080     p.drawPixmap( x - 5, 1, bitmap );
00081 } // VGradientWidget::paintColorStop
00082 
00083 void VGradientWidget::paintMidPoint( QPainter& p, int x )
00084 {
00085     QBitmap bitmap( midPoint_width, midPoint_height, midPoint_bits, true );
00086     bitmap.setMask( bitmap );
00087     p.setPen( Qt::black );
00088     p.drawPixmap( x - 3, 1, bitmap );
00089 } // VGradientWidget::paintMidPoint
00090 
00091 void VGradientWidget::paintEvent( QPaintEvent* )
00092 {
00093     int w = width() - 4;  // available width for gradient and points
00094     int h = height() - 7; // available height for gradient and points
00095     int ph = colorStopBorder_height + 2; // point marker height
00096     int gh = h - ph;       // gradient area height
00097 
00098     QPixmap pixmap( width(), height() );
00099     VKoPainter gp( &pixmap, width(), height() );
00100     gp.setRasterOp( Qt::XorROP );
00101     VGradient gradient( *m_gradient );
00102     gradient.setType( VGradient::linear );
00103     gradient.setOrigin( KoPoint( 2, 2 ) );
00104     gradient.setFocalPoint( KoPoint( 2, 2 ) );
00105     gradient.setVector( KoPoint( 2 + w, 2 ) );
00106     VFill fill;
00107     KIconLoader il;
00108     fill.pattern() = VPattern( il.iconPath( "karbon.png", KIcon::Small ) );
00109     fill.setType( VFill::patt );
00110     gp.setBrush( fill );
00111     gp.drawRect( KoRect( 2, 2, w, gh ) );
00112     fill.gradient() = gradient;
00113     fill.setType( VFill::grad );
00114     gp.setBrush( fill );
00115     gp.drawRect( KoRect( 2, 2, w, gh ) );
00116     gp.end();
00117 
00118     QPainter p( &pixmap );
00119 
00120     p.setPen( colorGroup().light() );
00121     // light frame around widget
00122     p.moveTo( 1, height() - 1 );
00123     p.lineTo( 1, 1 );
00124     p.lineTo( width() - 1, 1 );
00125     p.lineTo( width() - 1, height() - 1 );
00126     p.lineTo( 1, height() - 1 );
00127 
00128     // light line between gradient and point area
00129     p.moveTo( 1, 3 + gh );
00130     p.lineTo( width() - 1, 3 + gh );
00131 
00132     p.setPen( colorGroup().dark() );
00133     // left-top frame around widget
00134     p.moveTo( 0, height() - 1 );
00135     p.lineTo( 0, 0 );
00136     p.lineTo( width() - 1, 0 );
00137 
00138     // right-bottom from around gradient
00139     p.moveTo( width() - 2, 2 );
00140     p.lineTo( width() - 2, 2 + gh );
00141     p.lineTo( 2, 2 + gh );
00142 
00143     // upper line around point area
00144     p.moveTo( 1, height() - 3 - ph );
00145     p.lineTo( width() - 1, height() - 3 - ph );
00146 
00147     // right-bottom line around point area
00148     p.moveTo( width() - 2, height() - ph - 1 );
00149     p.lineTo( width() - 2, height() - 2 );
00150     p.lineTo( 2, height() - 2 );
00151     
00152     m_pntArea.setRect( 2, height() - ph - 2, w, ph );
00153     // clear point area
00154     p.fillRect( m_pntArea.x(), m_pntArea.y(), m_pntArea.width(), m_pntArea.height(), colorGroup().background() );
00155 
00156     p.setClipRect( m_pntArea.x(), m_pntArea.y(), m_pntArea.width(), m_pntArea.height() );
00157     p.translate( m_pntArea.x(), m_pntArea.y() );
00158     
00159     QPtrList<VColorStop>& colorStops = m_gradient->m_colorStops;
00160     if( colorStops.count() > 1 )
00161     {
00162         VColorStop* stop, *nextstop;
00163         for( stop = colorStops.first(), nextstop = colorStops.next();
00164                 nextstop; stop = nextstop, nextstop = colorStops.next() )
00165         {
00166             paintColorStop( p, (int)( stop->rampPoint * m_pntArea.width() ), stop->color );
00167             paintMidPoint( p, (int)(( stop->rampPoint + ( nextstop->rampPoint - stop->rampPoint ) * stop->midPoint ) * m_pntArea.width() ) );
00168         }
00169         paintColorStop( p, int( stop->rampPoint * w ), stop->color );
00170     }
00171     p.end();
00172     bitBlt( this, 0, 0, &pixmap, 0, 0, width(), height() );
00173 } // VGradientWidget::paintEvent
00174 
00175 void VGradientWidget::mousePressEvent( QMouseEvent* e )
00176 {
00177     if( ! m_pntArea.contains( e->x(), e->y() ) )
00178         return;
00179 
00180     QPtrList<VColorStop>& colorStops = m_gradient->m_colorStops;
00181 
00182     currentPoint = 0;
00183 
00184     int x = e->x() - m_pntArea.left();
00185 
00186     int i = colorStops.count() - 1;
00187     VColorStop *stop, *nextstop = 0;
00188     for( stop = colorStops.last(); i >= 0; i--, stop = colorStops.prev() )
00189     {
00190         int r = int( stop->rampPoint * m_pntArea.width() );
00191         if( nextstop )
00192         {
00193             int m = int( ( stop->rampPoint + ( nextstop->rampPoint - stop->rampPoint ) * stop->midPoint ) *  m_pntArea.width() );
00194             if( ( x > m - 5 ) && ( x < m + 5 ) )
00195             {
00196                 // found mid point at position
00197                 currentPoint = 2 * i + 2;
00198                 if( e->button() == Qt::LeftButton )
00199                     setCursor( VCursor::horzMove() );
00200                 return;
00201             }
00202         }
00203         if( ( x > r - 5 ) && ( x < r + 5 ) )
00204         {
00205             // found ramp point at position
00206             currentPoint = 2 * i + 1;
00207             if( e->button() == Qt::LeftButton )
00208                 setCursor( VCursor::horzMove() );
00209             return;
00210         }
00211 
00212         nextstop = stop;
00213     }
00214 } // VGradientWidget::mousePressEvent
00215 
00216 void VGradientWidget::mouseReleaseEvent( QMouseEvent* e )
00217 {
00218     if( e->button() == Qt::RightButton && currentPoint )
00219     {
00220         if( m_pntArea.contains( e->x(), e->y() ) && ( currentPoint % 2 == 1 ) )
00221         {
00222             int x = e->x() - m_pntArea.left();
00223             // check if we are still above the actual ramp point
00224             int r = int( m_gradient->m_colorStops.at( int(0.5 * currentPoint) )->rampPoint * m_pntArea.width() );
00225             if( ( x > r - 5 ) && ( x < r + 5 ) )
00226             {
00227                 m_gradient->m_colorStops.remove( int(0.5 * currentPoint) );
00228                 update();
00229                 emit changed();
00230             }
00231         }
00232     }
00233     setCursor( QCursor( Qt::ArrowCursor ) );
00234 } // VGradientWidget::mouseReleaseEvent
00235 
00236 void VGradientWidget::mouseDoubleClickEvent( QMouseEvent* e )
00237 {
00238     if( ! m_pntArea.contains( e->x(), e->y() ) )
00239         return;
00240 
00241     if( e->button() != Qt::LeftButton )
00242         return;
00243 
00244     if( currentPoint % 2 == 1 )
00245     {
00246         // ramp point hit -> change color
00247         VColorDlg* d = new VColorDlg( m_gradient->m_colorStops.at( currentPoint / 2 )->color, this->topLevelWidget() );
00248         if( d->exec() == QDialog::Accepted )
00249         {
00250             m_gradient->m_colorStops.at( currentPoint / 2 )->color = d->Color();
00251             update();
00252             emit changed();
00253         }
00254         delete d;
00255     }
00256     else if( currentPoint == 0 )
00257     {
00258         // now point hit -> create new color stop
00259         VColorDlg* d = new VColorDlg( m_gradient->m_colorStops.at( 0 )->color, this->topLevelWidget() );
00260         if( d->exec() == QDialog::Accepted )
00261         {
00262             m_gradient->addStop( d->Color(), (float)( e->x() - 2 ) / ( m_pntArea.width() ), 0.5 );
00263             update();
00264             emit changed();
00265         }
00266         delete d;
00267     }
00268 } // VGradientWidget::mouseDoubleClickEvent
00269 
00270 void VGradientWidget::mouseMoveEvent( QMouseEvent* e )
00271 {
00272     if( e->state() & Qt::RightButton )
00273         return;
00274 
00275     QPtrList<VColorStop>& colorStops = m_gradient->m_colorStops;
00276 
00277     if( currentPoint >= colorStops.count() * 2 )
00278         return;
00279 
00280     int x = e->x() - m_pntArea.left();
00281 
00282     if( currentPoint % 2 == 1 )
00283     {
00284         // move ramp point
00285         int actRP = int( 0.5 * ( currentPoint - 1 ) );
00286         int prevRP = actRP - 1;
00287         int nextRP = int( 0.5 * ( currentPoint + 1 ) );
00288         // Clip the color stop between to others.
00289         x = kMin( x, ( actRP < int( colorStops.count() - 1 ) ) ? int( colorStops.at( nextRP )->rampPoint * m_pntArea.width() ) : m_pntArea.width() );
00290         x = kMax( x, ( actRP > 0 ) ? int( colorStops.at( prevRP )->rampPoint * m_pntArea.width() ) : 0 );
00291         colorStops.at( actRP )->rampPoint = (float)( x ) / m_pntArea.width();
00292         update();
00293         emit changed();
00294     }
00295     else if( currentPoint > 0 )
00296     {
00297         // move mid point
00298         int prevRP = int( 0.5 * ( currentPoint - 1 ) );
00299         int nextRP = int( 0.5 * ( currentPoint + 1 ) );
00300         // Clip the mid point between to ramp points.
00301         x = kMin( x, int( colorStops.at( nextRP )->rampPoint * m_pntArea.width() ) );
00302         x = kMax( x, int( colorStops.at( prevRP )->rampPoint * m_pntArea.width() ) );
00303         colorStops.at( prevRP )->midPoint = ( (float)( x ) / m_pntArea.width() - ( colorStops.at( prevRP )->rampPoint ) ) / ( colorStops.at( nextRP )->rampPoint - colorStops.at( prevRP )->rampPoint );
00304         update();
00305         emit changed();
00306     }
00307 } // VGradientWidget::mouseMoveEvent
00308 
00309 #include "vgradientwidget.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys