00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <qcursor.h>
00021 #include <qlabel.h>
00022
00023 #include <klocale.h>
00024
00025 #include <karbon_part.h>
00026 #include <karbon_view.h>
00027 #include <karbon_factory.h>
00028 #include <render/vpainter.h>
00029 #include <render/vpainterfactory.h>
00030 #include "vgradienttool.h"
00031 #include <widgets/vgradienttabwidget.h>
00032 #include <commands/vfillcmd.h>
00033 #include <commands/vstrokecmd.h>
00034 #include <core/vstroke.h>
00035 #include <core/vselection.h>
00036 #include <widgets/vstrokefillpreview.h>
00037
00038 #include <kdebug.h>
00039
00040 VGradientTool::VGradientOptionsWidget::VGradientOptionsWidget( VGradient& gradient )
00041 : KDialogBase( 0L, "", true, i18n( "Edit Gradient" ), Ok | Cancel )
00042 {
00043 m_gradientWidget = new VGradientTabWidget( gradient, KarbonFactory::rServer(), this );
00044 setMainWidget( m_gradientWidget );
00045 setFixedSize( baseSize() );
00046 }
00047
00048 VGradientTool::VGradientTool( KarbonView *view )
00049 : VTool( view, "gradienttool" ), m_state( normal ), m_handleSize( 3 ), m_active( false )
00050 {
00051 setName( "tool_gradient" );
00052 m_optionsWidget = new VGradientOptionsWidget( m_gradient );
00053 registerTool( this );
00054 }
00055
00056 VGradientTool::~VGradientTool()
00057 {
00058 delete m_optionsWidget;
00059 }
00060
00061 void
00062 VGradientTool::activate()
00063 {
00064 m_active = true;
00065 m_state = normal;
00066 view()->statusMessage()->setText( i18n( "Gradient" ) );
00067 view()->setCursor( QCursor( Qt::crossCursor ) );
00068 VTool::activate();
00069
00070 if( view() )
00071 {
00072
00073 view()->part()->document().selection()->showHandle( false );
00074
00075 VStrokeFillPreview* preview = view()->strokeFillPreview();
00076 if( preview )
00077 {
00078 connect( preview, SIGNAL( fillSelected() ), this, SLOT( targetChanged() ) );
00079 connect( preview, SIGNAL( strokeSelected() ), this, SLOT( targetChanged() ) );
00080 }
00081 view()->repaintAll( view()->part()->document().selection()->boundingBox() );
00082 }
00083 }
00084
00085 void
00086 VGradientTool::deactivate()
00087 {
00088 m_active = false;
00089
00090 if( view() )
00091 {
00092
00093 view()->part()->document().selection()->showHandle( true );
00094 VStrokeFillPreview* preview = view()->strokeFillPreview();
00095 if( preview )
00096 {
00097 disconnect( preview, SIGNAL( fillSelected() ), this, SLOT( targetChanged() ) );
00098 disconnect( preview, SIGNAL( strokeSelected() ), this, SLOT( targetChanged() ) );
00099 }
00100 view()->repaintAll( view()->part()->document().selection()->boundingBox() );
00101 }
00102 }
00103
00104 QString
00105 VGradientTool::statusText()
00106 {
00107 return i18n( "Gradient tool" );
00108 }
00109
00110 QString
00111 VGradientTool::contextHelp()
00112 {
00113 QString s = i18n( "<qt><b>Gradient tool:</b><br>" );
00114 s += i18n( "<i>Click and drag</i> to choose the gradient vector.<br>" );
00115 s += i18n( "<i>Click and drag</i> a gradient vector handle to change the gradient vector.<br>" );
00116 s += i18n( "<i>Shift click and drag</i> to move the radial gradient focal point.<br>" );
00117 s += i18n( "<i>Press i or Shift+i</i> to decrease or increase the handle size.<br>" );
00118 s += i18n( "<br><b>Gradient editing:</b><br>" );
00119 s += i18n( "<i>Click and drag</i> to move points.<br>" );
00120 s += i18n( "<i>Double click</i> on a color point to edit it.<br>" );
00121 s += i18n( "<i>Right click</i> on a color point to remove it.</qt>" );
00122 return s;
00123 }
00124
00125 bool
00126 VGradientTool::getGradient( VGradient &gradient )
00127 {
00128 if( ! view() )
00129 return false;
00130
00131
00132 VStrokeFillPreview *preview = view()->strokeFillPreview();
00133 bool strokeSelected = ( preview && preview->strokeIsSelected() );
00134
00135 VSelection* selection = view()->part()->document().selection();
00136 if( selection->objects().count() != 1 )
00137 return false;
00138
00139 VObject *obj = selection->objects().getFirst();
00140
00141 if( strokeSelected && obj->stroke()->type() == VStroke::grad )
00142 gradient = obj->stroke()->gradient();
00143 else if( ! strokeSelected && obj->fill()->type() == VFill::grad )
00144 gradient = obj->fill()->gradient();
00145 else
00146 return false;
00147
00148 return true;
00149 }
00150
00151 bool
00152 VGradientTool::getOpacity( double &opacity )
00153 {
00154 if( ! view() )
00155 return false;
00156
00157
00158 VStrokeFillPreview *preview = view()->strokeFillPreview();
00159 bool strokeSelected = ( preview && preview->strokeIsSelected() );
00160
00161 VSelection* selection = view()->part()->document().selection();
00162 if( selection->objects().count() != 1 )
00163 return false;
00164
00165 VObject *obj = selection->objects().getFirst();
00166
00167 if( strokeSelected && obj->stroke()->type() == VStroke::grad )
00168 opacity = obj->stroke()->color().opacity();
00169 else if( ! strokeSelected && obj->fill()->type() == VFill::grad )
00170 opacity = obj->fill()->color().opacity();
00171 else return false;
00172
00173 return true;
00174 }
00175
00176 void
00177 VGradientTool::draw( VPainter* painter )
00178 {
00179 if( ! m_active )
00180 return;
00181
00182 if( m_state != normal )
00183 return;
00184
00185 if( ! getGradient( m_gradient ) )
00186 return;
00187
00188 KoPoint s = m_gradient.origin();
00189 KoPoint e = m_gradient.vector();
00190 KoPoint f = m_gradient.focalPoint();
00191
00192
00193 m_origin = KoRect( s.x()-m_handleSize, s.y()-m_handleSize, 2*m_handleSize, 2*m_handleSize );
00194 m_vector = KoRect( e.x()-m_handleSize, e.y()-m_handleSize, 2*m_handleSize, 2*m_handleSize );
00195 m_center = KoRect( f.x()-m_handleSize, f.y()-m_handleSize, 2*m_handleSize, 2*m_handleSize );
00196
00197 painter->setPen( Qt::blue.light() );
00198 painter->setBrush( Qt::blue.light() );
00199 painter->setRasterOp( Qt::XorROP );
00200
00201
00202 painter->newPath();
00203 painter->moveTo( s );
00204 painter->lineTo( e );
00205 painter->strokePath();
00206
00207 if( m_gradient.type() == VGradient::radial )
00208 {
00209
00210 double size = (double)m_handleSize / view()->zoom();
00211 KoPoint focal = m_center.center();
00212 KoRect cross = KoRect( focal.x()-3*size, focal.y()-3*size, 6*size, 6*size );
00213 painter->newPath();
00214 painter->moveTo( cross.topLeft() );
00215 painter->lineTo( cross.bottomRight() );
00216 painter->strokePath();
00217 painter->newPath();
00218 painter->moveTo( cross.bottomLeft() );
00219 painter->lineTo( cross.topRight() );
00220 painter->strokePath();
00221 }
00222
00223 painter->drawNode( m_origin.center(), m_handleSize );
00224 painter->drawNode( m_vector.center(), m_handleSize );
00225 }
00226
00227 void
00228 VGradientTool::draw()
00229 {
00230 if( ! view() || view()->part()->document().selection()->objects().count() == 0 )
00231 return;
00232
00233 VPainter *painter = view()->painterFactory()->editpainter();
00234 painter->setRasterOp( Qt::NotROP );
00235
00236 painter->setPen( Qt::DotLine );
00237 painter->newPath();
00238
00239
00240 if( m_state == moveOrigin || m_state == moveVector )
00241 {
00242 painter->moveTo( m_fixed );
00243 painter->lineTo( m_current );
00244
00245 painter->drawNode( m_fixed, m_handleSize );
00246 painter->drawNode( m_current, m_handleSize );
00247 }
00248 else if( m_state == createNew )
00249 {
00250 painter->moveTo( first() );
00251 painter->lineTo( m_current );
00252
00253 painter->drawNode( first(), m_handleSize );
00254 painter->drawNode( m_current, m_handleSize );
00255 }
00256 else if( m_state == moveCenter )
00257 {
00258
00259 double size = (double)m_handleSize / view()->zoom();
00260 KoRect cross = KoRect( m_current.x()-3*size, m_current.y()-3*size, 6*size, 6*size );
00261 painter->moveTo( cross.topLeft() );
00262 painter->lineTo( cross.bottomRight() );
00263 painter->strokePath();
00264 painter->newPath();
00265 painter->moveTo( cross.bottomLeft() );
00266 painter->lineTo( cross.topRight() );
00267 }
00268
00269 painter->strokePath();
00270 }
00271
00272 void
00273 VGradientTool::mouseDrag()
00274 {
00275 if( m_state == normal )
00276 return;
00277
00278
00279 draw();
00280
00281 m_current = last();
00282
00283 draw();
00284 }
00285
00286 void
00287 VGradientTool::mouseButtonPress()
00288 {
00289 m_current = first();
00290
00291
00292 if( m_center.contains( m_current ) && shiftPressed())
00293 {
00294 m_state = moveCenter;
00295 }
00296 else if( m_origin.contains( m_current ) )
00297 {
00298 m_state = moveOrigin;
00299 m_fixed = m_vector.center();
00300 }
00301 else if( m_vector.contains( m_current ) )
00302 {
00303 m_state = moveVector;
00304 m_fixed = m_origin.center();
00305 }
00306 else
00307 m_state = createNew;
00308 }
00309
00310 void
00311 VGradientTool::mouseButtonRelease()
00312 {
00313 m_state = normal;
00314
00315 if( ! view() || view()->part()->document().selection()->objects().count() == 0 )
00316 return;
00317
00318
00319 VGradient oldGradient = m_gradient;
00320
00321 bool strokeSelected = false;
00322
00323
00324 VStrokeFillPreview* preview = view()->strokeFillPreview();
00325 if( preview && preview->strokeIsSelected() )
00326 strokeSelected = true;
00327
00328 if( first() == last() )
00329 {
00330 m_optionsWidget->gradientWidget()->setGradient( m_gradient );
00331 if( strokeSelected )
00332 {
00333 m_optionsWidget->gradientWidget()->setTarget( VGradientTabWidget::STROKE );
00334 m_optionsWidget->gradientWidget()->setOpacity( 1.0 );
00335 }
00336 else
00337 {
00338 m_optionsWidget->gradientWidget()->setTarget( VGradientTabWidget::FILL );
00339 double opacity;
00340 if( getOpacity( opacity ) )
00341 m_optionsWidget->gradientWidget()->setOpacity( opacity );
00342 }
00343
00344 if( ! showDialog() )
00345 return;
00346
00347 m_gradient = m_optionsWidget->gradientWidget()->gradient();
00348
00349
00350 strokeSelected = ( m_optionsWidget->gradientWidget()->target() == VGradientTabWidget::STROKE );
00351 }
00352
00353
00354 if( view()->part()->document().selection()->objects().count() == 1 )
00355 {
00356 VObject *obj = view()->part()->document().selection()->objects().getFirst();
00357
00358 if( ( ! strokeSelected && obj->fill()->type() != VFill::grad )
00359 || ( strokeSelected && obj->stroke()->type() != VStroke::grad ) )
00360 {
00361 KoRect bbox = obj->boundingBox();
00362 switch( m_gradient.type() )
00363 {
00364 case VGradient::linear:
00365 oldGradient.setOrigin( bbox.bottomLeft() + 0.5*(bbox.bottomRight()-bbox.bottomLeft()) );
00366 oldGradient.setVector( bbox.topLeft() + 0.5*(bbox.topRight()-bbox.topLeft()) );
00367 oldGradient.setFocalPoint( bbox.center() );
00368 break;
00369 case VGradient::radial:
00370 oldGradient.setOrigin( bbox.center() );
00371 oldGradient.setVector( bbox.topLeft() + 0.5*(bbox.topRight()-bbox.topLeft()) );
00372 oldGradient.setFocalPoint( bbox.center() );
00373 break;
00374 case VGradient::conic:
00375 oldGradient.setOrigin( bbox.center() );
00376 oldGradient.setVector( bbox.topLeft() + 0.5*(bbox.topRight()-bbox.topLeft()) );
00377 oldGradient.setFocalPoint( bbox.center() );
00378 break;
00379 }
00380 }
00381 }
00382
00383
00384 if( oldGradient.origin() == oldGradient.vector() )
00385 oldGradient.vector().rx()+=1;
00386
00387
00388 m_gradient.setVector( oldGradient.vector() );
00389 m_gradient.setOrigin( oldGradient.origin() );
00390 m_gradient.setFocalPoint( oldGradient.focalPoint() );
00391
00392 if( ! strokeSelected )
00393 {
00394 VFill fill;
00395 fill.gradient() = m_gradient;
00396 fill.setType( VFill::grad );
00397 VColor c = fill.color();
00398 c.setOpacity( m_optionsWidget->gradientWidget()->opacity() );
00399 fill.setColor( c, false );
00400 view()->part()->addCommand(
00401 new VFillCmd( &view()->part()->document(), fill, "14_gradient" ), true );
00402 }
00403 else
00404 {
00405 view()->part()->addCommand(
00406 new VStrokeCmd( &view()->part()->document(), &m_gradient ), true );
00407 }
00408 }
00409
00410 void
00411 VGradientTool::mouseDragRelease()
00412 {
00413 if( ! view() || m_state == normal )
00414 return;
00415
00416 if( view()->part()->document().selection()->objects().count() == 0 )
00417 {
00418 draw();
00419 return;
00420 }
00421
00422 if( m_state == moveOrigin )
00423 m_gradient.setOrigin( last() );
00424 else if( m_state == moveVector )
00425 m_gradient.setVector( last() );
00426 else if( m_state == moveCenter )
00427 m_gradient.setFocalPoint( last() );
00428 else if( m_state == createNew )
00429 {
00430 m_gradient.setOrigin( first() );
00431 m_gradient.setFocalPoint( first() );
00432 m_gradient.setVector( last() );
00433 }
00434
00435 m_state = normal;
00436
00437 VStrokeFillPreview* preview = view()->strokeFillPreview();
00438 if( ! preview )
00439 return;
00440
00441 if( ! preview->strokeIsSelected() )
00442 {
00443 VFill fill;
00444 fill.gradient() = m_gradient;
00445 fill.setType( VFill::grad );
00446 VColor c = fill.color();
00447 c.setOpacity( m_optionsWidget->gradientWidget()->opacity() );
00448 fill.setColor( c, false );
00449 view()->part()->addCommand(
00450 new VFillCmd( &view()->part()->document(), fill, "14_gradient" ), true );
00451 }
00452 else
00453 view()->part()->addCommand(
00454 new VStrokeCmd( &view()->part()->document(), &m_gradient ), true );
00455 }
00456
00457 void
00458 VGradientTool::cancel()
00459 {
00460
00461 if( isDragging() )
00462 draw();
00463 m_state = normal;
00464 }
00465
00466 bool
00467 VGradientTool::showDialog() const
00468 {
00469 return m_optionsWidget->exec() == QDialog::Accepted;
00470 }
00471
00472 void
00473 VGradientTool::setup( KActionCollection *collection )
00474 {
00475 m_action = static_cast<KRadioAction *>(collection -> action( name() ) );
00476
00477 if( m_action == 0 )
00478 {
00479 m_action = new KRadioAction( i18n( "Gradient Tool" ), "14_gradient", Qt::Key_G, this, SLOT( activate() ), collection, name() );
00480 m_action->setToolTip( i18n( "Gradient" ) );
00481 m_action->setExclusiveGroup( "misc" );
00482
00483 }
00484 }
00485
00486 void
00487 VGradientTool::setCursor() const
00488 {
00489 if( !view() ) return;
00490
00491
00492 if( m_origin.contains( last() ) || m_vector.contains( last() ) || m_center.contains( last() ) )
00493 view()->setCursor( QCursor( Qt::SizeAllCursor ) );
00494 else
00495 view()->setCursor( QCursor( Qt::arrowCursor ) );
00496 }
00497
00498 bool
00499 VGradientTool::keyReleased( Qt::Key key )
00500 {
00501
00502 switch( key )
00503 {
00504 case Qt::Key_I:
00505 if( shiftPressed() )
00506 m_handleSize++;
00507 else if( m_handleSize > 3 )
00508 m_handleSize--;
00509 break;
00510 default: return false;
00511 }
00512
00513 if( view() )
00514 view()->repaintAll( view()->part()->document().selection()->boundingBox() );
00515
00516 return true;
00517 }
00518
00519 void
00520 VGradientTool::targetChanged()
00521 {
00522 if( view() )
00523 view()->repaintAll( view()->part()->document().selection()->boundingBox() );
00524 }
00525
00526 #include "vgradienttool.moc"