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 else if( !m_optionsWidget->selectedPattern() )
00334 KMessageBox::error( 0L, i18n( "Please select a pattern." ), "" );
00335
00336 bool strokeSelected = false;
00337
00338
00339
00340
00341
00342
00343
00344 if( view()->part()->document().selection()->objects().count() == 1 )
00345 {
00346 VObject *obj = view()->part()->document().selection()->objects().getFirst();
00347
00348 if( ( ! strokeSelected && obj->fill()->type() != VFill::patt ) || (strokeSelected && obj->stroke()->type() != VStroke::patt ) )
00349 {
00350 KoRect bbox = obj->boundingBox();
00351 oldPattern.setOrigin( bbox.bottomLeft() + 0.5*(bbox.topLeft()-bbox.bottomLeft()) );
00352 oldPattern.setVector( bbox.bottomRight() + 0.5*(bbox.topRight()-bbox.bottomRight()) );
00353 }
00354 }
00355
00356 VPattern m_pattern = *m_optionsWidget->selectedPattern();
00357
00358
00359 m_pattern.setOrigin( oldPattern.origin() );
00360 m_pattern.setVector( oldPattern.vector() );
00361
00362 if( ! strokeSelected )
00363 {
00364 VFill fill;
00365 fill.pattern() = m_pattern;
00366 fill.setType( VFill::patt );
00367 view()->part()->addCommand(
00368 new VFillCmd( &view()->part()->document(), fill, "14_pattern" ), true );
00369 }
00370 else
00371 {
00372 VStroke stroke;
00373 stroke.pattern() = m_pattern;
00374 stroke.setType( VStroke::patt );
00375 view()->part()->addCommand(
00376 new VStrokeCmd( &view()->part()->document(), &stroke, "14_pattern" ), true );
00377 }
00378 }
00379
00380 void
00381 VPatternTool::mouseDragRelease()
00382 {
00383 if( ! view() || m_state == normal )
00384 return;
00385
00386 if( view()->part()->document().selection()->objects().count() == 0 )
00387 {
00388 draw();
00389 return;
00390 }
00391
00392 if( !m_optionsWidget->selectedPattern() )
00393 {
00394 draw();
00395 KMessageBox::error( 0L, i18n( "Please select a pattern." ), "" );
00396 return;
00397 }
00398
00399
00400 if( m_state == moveOrigin )
00401 m_pattern.setOrigin( last() );
00402 else if( m_state == moveVector )
00403 m_pattern.setVector( last() );
00404 else if( m_state == createNew )
00405 {
00406 m_pattern.setOrigin( first() );
00407 m_pattern.setVector( last() );
00408 }
00409
00410 m_state = normal;
00411
00412 VStrokeFillPreview* preview = view()->strokeFillPreview();
00413 if( ! preview )
00414 return;
00415
00416
00417 {
00418 VFill fill;
00419 fill.pattern() = m_pattern;
00420 fill.setType( VFill::patt );
00421 view()->part()->addCommand(
00422 new VFillCmd( &view()->part()->document(), fill, "14_pattern" ), true );
00423 }
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434 }
00435
00436 void
00437 VPatternTool::cancel()
00438 {
00439
00440 if( isDragging() )
00441 draw();
00442 m_state = normal;
00443 }
00444
00445 bool
00446 VPatternTool::showDialog() const
00447 {
00448 return m_optionsWidget->exec() == QDialog::Accepted;
00449 }
00450
00451 void
00452 VPatternTool::setup( KActionCollection *collection )
00453 {
00454 m_action = static_cast<KRadioAction *>(collection -> action( name() ) );
00455
00456 if( m_action == 0 )
00457 {
00458 m_action = new KRadioAction( i18n( "Pattern Tool" ), "14_pattern", Qt::SHIFT+Qt::Key_H, this, SLOT( activate() ), collection, name() );
00459 m_action->setToolTip( i18n( "Pattern" ) );
00460 m_action->setExclusiveGroup( "misc" );
00461
00462 }
00463 }
00464
00465 void
00466 VPatternTool::setCursor() const
00467 {
00468 if( !view() ) return;
00469
00470
00471 if( m_origin.contains( last() ) || m_vector.contains( last() ) )
00472 view()->setCursor( QCursor( Qt::SizeAllCursor ) );
00473 else
00474 view()->setCursor( QCursor( Qt::arrowCursor ) );
00475 }
00476
00477 bool
00478 VPatternTool::keyReleased( Qt::Key key )
00479 {
00480
00481 switch( key )
00482 {
00483 case Qt::Key_I:
00484 if( shiftPressed() )
00485 m_handleSize++;
00486 else if( m_handleSize > 3 )
00487 m_handleSize--;
00488 break;
00489 default: return false;
00490 }
00491
00492 if( view() )
00493 view()->repaintAll( view()->part()->document().selection()->boundingBox() );
00494
00495 return true;
00496 }
00497
00498 void
00499 VPatternTool::targetChanged()
00500 {
00501 if( view() )
00502 view()->repaintAll( view()->part()->document().selection()->boundingBox() );
00503 }
00504
00505 #include "vpatterntool.moc"