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