00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <math.h>
00021
00022 #include <qcheckbox.h>
00023 #include <qcombobox.h>
00024 #include <qcursor.h>
00025 #include <qlabel.h>
00026 #include <qlayout.h>
00027 #include <qlineedit.h>
00028 #include <qpainter.h>
00029 #include <qpixmap.h>
00030 #include <qpushbutton.h>
00031 #include <qtabwidget.h>
00032
00033 #include <kdebug.h>
00034 #include <kfontcombo.h>
00035 #include <kfontdialog.h>
00036 #include <kiconloader.h>
00037 #include <knuminput.h>
00038 #include <kglobalsettings.h>
00039
00040 #include <karbon_view.h>
00041 #include <karbon_part.h>
00042 #include <core/vdocument.h>
00043 #include <core/vglobal.h>
00044 #include <core/vselection.h>
00045 #include <core/vfill.h>
00046 #include <core/vgroup.h>
00047 #include <core/vstroke.h>
00048 #include <core/vcursor.h>
00049 #include <render/vpainterfactory.h>
00050 #include <render/vkopainter.h>
00051 #include "vtexttool.h"
00052
00053
00054 static void
00055 traceShape( VKoPainter* p, int x, int y, int w, int h )
00056 {
00057 p->newPath();
00058 p->moveTo( KoPoint( x + w , y + h ) );
00059 p->lineTo( KoPoint( x + w / 3, y + h ) );
00060 p->lineTo( KoPoint( x + w / 3, y + h / 3 ) );
00061 p->lineTo( KoPoint( x + w , y + h / 3 ) );
00062 p->lineTo( KoPoint( x + w , y + h ) );
00063
00064 p->moveTo( KoPoint( x , y ) );
00065 p->lineTo( KoPoint( x + ( w / 3 ) * 2, y ) );
00066 p->lineTo( KoPoint( x + ( w / 3 ) * 2, y + ( h / 3 ) * 2 ) );
00067 p->lineTo( KoPoint( x , y + ( h / 3 ) * 2 ) );
00068 p->lineTo( KoPoint( x , y ) );
00069 }
00070
00071 ShadowPreview::ShadowPreview( ShadowWidget* parent )
00072 : QWidget( parent ), m_parent( parent )
00073 {
00074 setBackgroundMode( Qt::NoBackground );
00075 setMinimumSize( 60, 60 );
00076
00077 connect( this, SIGNAL( changed( int, int, bool ) ), m_parent, SLOT( setShadowValues( int, int, bool ) ) );
00078 }
00079
00080 ShadowPreview::~ShadowPreview()
00081 {
00082 }
00083
00084 void
00085 ShadowPreview::mouseReleaseEvent( QMouseEvent* e )
00086 {
00087 int dx = e->x() - width() / 2;
00088 int dy = e->y() - height() / 2;
00089
00090 float fd = sqrt( double( dx * dx + dy * dy ) );
00091 int a;
00092
00093 if( fd == 0 )
00094 a = 0;
00095 else if( dy == 0 && dx < 0 )
00096 a = 180;
00097 else
00098 {
00099 float r = acos( dx / fd );
00100 a = int( ( dy <= 0 ? r : VGlobal::twopi - r ) / VGlobal::twopi * 360. );
00101 }
00102
00103 emit changed( a, ( int ) fd, m_parent->isTranslucent() );
00104 }
00105
00106 void
00107 ShadowPreview::paintEvent( QPaintEvent* )
00108 {
00109 int w = width() - 4;
00110 int h = height() - 4;
00111 int d = m_parent->shadowDistance();
00112 int a = 360 - m_parent->shadowAngle();
00113
00114 QPixmap pm( w, h );
00115 VKoPainter p( &pm, w, h );
00116 VColor color( VColor::rgb );
00117
00118 VFill fill;
00119 KIconLoader il;
00120 fill.pattern() = VPattern( il.iconPath( "karbon.png", KIcon::Small ) );
00121 fill.setType( VFill::patt );
00122
00123 p.newPath();
00124 p.moveTo( KoPoint( 0, 0 ) );
00125 p.lineTo( KoPoint( 0, h ) );
00126 p.lineTo( KoPoint( w, h ) );
00127 p.lineTo( KoPoint( w, 0 ) );
00128 p.lineTo( KoPoint( 0, 0 ) );
00129 p.setBrush( fill );
00130 p.fillPath();
00131
00132 color.set( 1., 1., 1. );
00133 color.setOpacity( .5 );
00134 p.setBrush( VFill( color ) );
00135 p.fillPath();
00136
00137 if( m_parent->isTranslucent() )
00138 {
00139 color.set( 0., 0., 0. );
00140 color.setOpacity( .3 );
00141 }
00142 else
00143 {
00144 color.set( .3, .3, .3 );
00145 color.setOpacity( 1. );
00146 }
00147
00148 p.setPen( VStroke( color ) );
00149 p.setBrush( VFill( color ) );
00150
00151 traceShape(
00152 &p,
00153 int( w / 4 + d * cos( a / 360. * VGlobal::twopi ) ),
00154 int( h / 4 + d * sin( a / 360. * VGlobal::twopi ) ), int( w / 2 ), int( h / 2 ) );
00155
00156 p.strokePath();
00157 p.fillPath();
00158
00159 color.set( 0., 0., 1. );
00160 color.setOpacity( 1. );
00161 p.setBrush( VFill( color ) );
00162 color.set( 0., 0., .5 );
00163 p.setPen( VStroke( color ) );
00164 traceShape( &p, w / 4, h / 4, w / 2, h / 2 );
00165 p.strokePath();
00166 p.fillPath();
00167
00168 if( !m_parent->useShadow() )
00169 {
00170 p.newPath();
00171 p.moveTo( KoPoint( 0, 0 ) );
00172 p.lineTo( KoPoint( 0, h ) );
00173 p.lineTo( KoPoint( w, h ) );
00174 p.lineTo( KoPoint( w, 0 ) );
00175 p.lineTo( KoPoint( 0, 0 ) );
00176 VColor c( colorGroup().background() );
00177 c.setOpacity( .8 );
00178 p.setBrush( VFill( c ) );
00179 p.fillPath();
00180 }
00181
00182 p.end();
00183
00184 QPainter painter( this );
00185 painter.drawPixmap( 2, 2, pm );
00186 painter.setPen( colorGroup().light() );
00187 painter.moveTo( 1, height() - 1 );
00188 painter.lineTo( 1, 1 );
00189 painter.lineTo( width() - 1, 1 );
00190 painter.lineTo( width() - 1, height() - 1 );
00191 painter.lineTo( 1, height() - 1 );
00192 painter.setPen( colorGroup().dark() );
00193 painter.moveTo( 0, height() - 1 );
00194 painter.lineTo( 0, 0 );
00195 painter.lineTo( width() - 1, 0 );
00196 painter.moveTo( width() - 2, 2 );
00197 painter.lineTo( width() - 2, height() - 2 );
00198 painter.lineTo( 2, height() - 2 );
00199 painter.setPen( Qt::black );
00200 painter.drawLine( width() / 2 - 2, height() / 2, width() / 2 + 2, height() / 2 );
00201 painter.drawLine( width() / 2, height() / 2 - 2, width() / 2, height() / 2 + 2 );
00202 }
00203
00204 ShadowWidget::ShadowWidget( QWidget* parent, const char* name, int angle, int distance, bool translucent )
00205 : QGroupBox( parent, name )
00206 {
00207 setTitle( i18n( "Shadow" ) );
00208 setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ) );
00209
00210 QGridLayout* layout = new QGridLayout( this );
00211 layout->addRowSpacing( 0, 12 );
00212 layout->setMargin( 3 );
00213 layout->setSpacing( 2 );
00214 layout->setColStretch( 0, 1 );
00215 layout->setColStretch( 1, 0 );
00216 layout->setColStretch( 2, 2 );
00217 layout->addMultiCellWidget( m_preview = new ShadowPreview( this ), 1, 3, 0, 0 );
00218 layout->addWidget( new QLabel( i18n( "Angle:" ), this ), 1, 1 );
00219 layout->addWidget( m_angle = new KIntNumInput( this ), 1, 2 );
00220 layout->addWidget( new QLabel( i18n( "Distance:" ), this ), 2, 1 );
00221 layout->addWidget( m_distance = new KIntNumInput( this ), 2, 2 );
00222 layout->addWidget( m_useShadow = new QCheckBox( i18n( "Shadow" ), this ), 3, 1 );
00223 layout->addWidget( m_translucent = new QCheckBox( i18n( "Draw translucent shadow" ), this ), 3, 2 );
00224 m_distance->setRange( 1, 37, 1, true );
00225 m_angle->setRange( 0, 360, 10, true );
00226 m_angle->setValue( angle );
00227 m_distance->setValue( distance );
00228 m_translucent->setChecked( translucent );
00229
00230 connect( m_angle, SIGNAL( valueChanged( int ) ), this, SLOT( updatePreview( int ) ) );
00231 connect( m_distance, SIGNAL( valueChanged( int ) ), this, SLOT( updatePreview( int ) ) );
00232 connect( m_useShadow, SIGNAL( clicked() ), this, SLOT( updatePreview() ) );
00233 connect( m_translucent, SIGNAL( clicked() ), this, SLOT( updatePreview() ) );
00234
00235 updatePreview();
00236 }
00237
00238 ShadowWidget::~ShadowWidget()
00239 {
00240 }
00241
00242 void
00243 ShadowWidget::setUseShadow( bool use )
00244 {
00245 m_useShadow->setChecked( use );
00246 updatePreview();
00247 }
00248
00249 bool ShadowWidget::useShadow()
00250 {
00251 return m_useShadow->isChecked();
00252 }
00253
00254 void
00255 ShadowWidget::setShadowAngle( int angle )
00256 {
00257 m_angle->setValue( angle );
00258 m_preview->repaint();
00259 }
00260
00261 int
00262 ShadowWidget::shadowAngle()
00263 {
00264 return m_angle->value();
00265 }
00266
00267 void
00268 ShadowWidget::setShadowDistance( int distance )
00269 {
00270 m_distance->setValue( distance );
00271 m_preview->repaint();
00272 }
00273
00274 int
00275 ShadowWidget::shadowDistance()
00276 {
00277 return m_distance->value();
00278 }
00279
00280 void
00281 ShadowWidget::setTranslucent( bool translucent )
00282 {
00283 m_translucent->setChecked( translucent );
00284 m_preview->repaint();
00285 }
00286
00287 bool ShadowWidget::isTranslucent()
00288 {
00289 return m_translucent->isChecked();
00290 }
00291
00292 void
00293 ShadowWidget::setShadowValues( int angle, int distance, bool translucent )
00294 {
00295 m_angle->setValue( angle );
00296 m_distance->setValue( distance );
00297 m_translucent->setChecked( translucent );
00298 updatePreview();
00299 }
00300
00301 void
00302 ShadowWidget::updatePreview( int )
00303 {
00304 m_preview->repaint();
00305 }
00306
00307 void
00308 ShadowWidget::updatePreview()
00309 {
00310 m_preview->repaint();
00311 bool ok = m_useShadow->isChecked();
00312 m_angle->setEnabled( ok );
00313 m_distance->setEnabled( ok );
00314 m_translucent->setEnabled( ok );
00315 }
00316
00317 VTextOptionsWidget::VTextOptionsWidget( VTextTool* tool, QWidget *parent )
00318 : KDialogBase( parent, "", true, i18n( "Text" ), Ok | Cancel ), m_tool( tool )
00319 {
00320
00321
00322 QWidget *base = new QWidget( this );
00323 QVBoxLayout* mainLayout = new QVBoxLayout( base );
00324 mainLayout->setMargin( 3 );
00325
00326 mainLayout->add( m_tabWidget = new QTabWidget( base ) );
00327
00328 m_tabWidget->setFont( QFont( KGlobalSettings::generalFont().family() , 8 ) );
00329
00330 QWidget* textWidget = new QWidget( m_tabWidget );
00331
00332 QGridLayout* textLayout = new QGridLayout( textWidget );
00333
00334 QStringList list;
00335 KFontChooser::getFontList( list, KFontChooser::SmoothScalableFonts );
00336
00337 textLayout->setMargin( 3 );
00338 textLayout->setSpacing( 2 );
00339 textLayout->addMultiCellWidget( m_fontCombo = new KFontCombo( list, textWidget ), 0, 0, 0, 2 );
00340 textLayout->addWidget( m_fontSize = new KIntNumInput( textWidget ), 1, 0 );
00341 textLayout->addWidget( m_boldCheck = new QCheckBox( i18n( "Bold" ), textWidget ), 1, 1 );
00342 textLayout->addWidget( m_italicCheck = new QCheckBox( i18n( "Italic" ), textWidget ), 1, 2 );
00343 textLayout->addMultiCellWidget( m_textEditor = new QLineEdit( textWidget ), 2, 2, 0, 2 );
00344
00345 m_tabWidget->addTab( textWidget, i18n( "Text" ) );
00346
00347 QWidget* posWidget = new QWidget( m_tabWidget );
00348
00349 QGridLayout* posLayout = new QGridLayout( posWidget );
00350 textLayout->setMargin( 3 );
00351 posLayout->setSpacing( 2 );
00352 posLayout->addWidget( new QLabel( i18n( "Alignment:" ), posWidget ), 0, 0 );
00353 posLayout->addWidget( m_textAlignment = new QComboBox( posWidget ), 0, 1 );
00354 posLayout->addWidget( new QLabel( i18n( "Position:" ), posWidget ), 1, 0 );
00355 posLayout->addWidget( m_textPosition = new QComboBox( posWidget ), 1, 1 );
00356 posLayout->addWidget( new QLabel( i18n( "Offset:" ), posWidget ), 2, 0 );
00357 posLayout->addWidget( m_textOffset = new KDoubleNumInput( posWidget ), 2, 1 );
00358 posLayout->setColStretch( 0, 0 );
00359 posLayout->setColStretch( 1, 1 );
00360
00361 m_tabWidget->addTab( posWidget, i18n( "Position" ) );
00362
00363 QWidget* fxWidget = new QWidget( m_tabWidget );
00364
00365 QVBoxLayout* fxLayout = new QVBoxLayout( fxWidget );
00366
00367 fxLayout->setMargin( 3 );
00368 fxLayout->setSpacing( 2 );
00369 fxLayout->add( m_shadow = new ShadowWidget( fxWidget, 0L, 315, 4, true ) );
00370
00371 QHBoxLayout* fxLayout2 = new QHBoxLayout( fxLayout );
00372
00373 fxLayout2->setSpacing( 2 );
00374 fxLayout2->addWidget( m_editBasePath = new QPushButton( i18n( "Edit Base Path" ), fxWidget ) );
00375 fxLayout2->addWidget( m_convertToShapes = new QPushButton( i18n( "Convert to Shapes" ), fxWidget ) );
00376
00377 m_tabWidget->addTab( fxWidget, i18n( "Effects" ) );
00378
00379 m_fontCombo->setCurrentText( KGlobalSettings::generalFont().family() );
00380
00381 m_fontSize->setValue( 12 );
00382 m_fontSize->setSuffix( " pt" );
00383
00384 m_textEditor->setMinimumHeight( 100 );
00385 m_textEditor->setText( i18n( "New text") );
00386 m_textEditor->selectAll();
00387
00388 m_convertToShapes->setEnabled( true );
00389
00390 m_textAlignment->insertItem( i18n( "Horizontal alignment", "Left") );
00391 m_textAlignment->insertItem( i18n( "Horizontal alignment", "Center") );
00392 m_textAlignment->insertItem( i18n( "Horizontal alignment", "Right") );
00393
00394 m_textPosition->insertItem( i18n( "Vertical alignment", "Above") );
00395 m_textPosition->insertItem( i18n( "Vertical alignment", "On") );
00396 m_textPosition->insertItem( i18n( "Vertical alignment", "Under") );
00397
00398 m_textOffset->setRange( 0.0, 100.0, 1.0, true );
00399
00400 connect( m_fontCombo, SIGNAL( activated( int ) ), this, SLOT( valueChanged( int ) ) );
00401 connect( m_boldCheck, SIGNAL( stateChanged( int ) ), this, SLOT( valueChanged( int ) ) );
00402 connect( m_italicCheck, SIGNAL( stateChanged( int ) ), this, SLOT( valueChanged( int ) ) );
00403 connect( m_fontSize, SIGNAL( valueChanged( int ) ), this, SLOT( valueChanged( int ) ) );
00404 connect( m_textPosition, SIGNAL( activated( int ) ), this, SLOT( valueChanged( int ) ) );
00405 connect( m_textAlignment, SIGNAL( activated( int ) ), this, SLOT( valueChanged( int ) ) );
00406 connect( m_textOffset, SIGNAL( valueChanged( double ) ), this, SLOT( valueChanged( double ) ) );
00407 connect( m_textEditor, SIGNAL( returnPressed() ), this, SLOT( accept() ) );
00408 connect( m_textEditor, SIGNAL( textChanged( const QString& ) ), this, SLOT( textChanged( const QString& ) ) );
00409 connect( m_editBasePath, SIGNAL( clicked() ), this, SLOT( editBasePath() ) );
00410 connect( m_convertToShapes, SIGNAL( clicked() ), this, SLOT( convertToShapes() ) );
00411 connect( this, SIGNAL( cancelClicked() ), this, SLOT( cancel() ) );
00412
00413 setMainWidget( base );
00414 setFixedSize( baseSize() );
00415 }
00416
00417 VTextOptionsWidget::~VTextOptionsWidget()
00418 {
00419 }
00420
00421 void
00422 VTextOptionsWidget::valueChanged( int )
00423 {
00424 m_fontCombo->setBold( m_boldCheck->isChecked() );
00425 m_fontCombo->setItalic( m_italicCheck->isChecked() );
00426
00427 m_textEditor->setFont( QFont( m_fontCombo->currentText(), m_fontSize->value(), ( m_boldCheck->isChecked() ? 75 : 50 ), m_italicCheck->isChecked() ) );
00428
00429 if( m_tool && isVisible() )
00430 m_tool->textChanged();
00431 }
00432
00433 void
00434 VTextOptionsWidget::valueChanged( double )
00435 {
00436 if( m_tool && isVisible() )
00437 m_tool->textChanged();
00438 }
00439
00440 void
00441 VTextOptionsWidget::accept()
00442 {
00443 if( m_tool )
00444 m_tool->accept();
00445 hide();
00446 }
00447
00448 void
00449 VTextOptionsWidget::cancel()
00450 {
00451 if( m_tool )
00452 m_tool->cancel();
00453 }
00454
00455 void
00456 VTextOptionsWidget::textChanged( const QString& )
00457 {
00458 if( m_tool && isVisible() )
00459 m_tool->textChanged();
00460 }
00461
00462 void
00463 VTextOptionsWidget::editBasePath()
00464 {
00465 if( m_tool )
00466 m_tool->editBasePath();
00467 }
00468
00469 void
00470 VTextOptionsWidget::convertToShapes()
00471 {
00472 if( m_tool )
00473 m_tool->convertToShapes();
00474 }
00475
00476 void
00477 VTextOptionsWidget::setFont( const QFont& font )
00478 {
00479 m_fontCombo->setCurrentText( font.family() );
00480
00481 m_boldCheck->setChecked( font.bold() );
00482
00483 m_italicCheck->setChecked( font.italic() );
00484
00485 m_fontSize->setValue( font.pointSize() );
00486
00487 m_fontCombo->setBold( m_boldCheck->isChecked() );
00488 m_fontCombo->setItalic( m_italicCheck->isChecked() );
00489
00490 m_textEditor->setFont( QFont( m_fontCombo->currentText(), m_fontSize->value(), ( m_boldCheck->isChecked() ? 75 : 50 ), m_italicCheck->isChecked() ) );
00491 }
00492
00493 QFont VTextOptionsWidget::font()
00494 {
00495 return QFont( m_fontCombo->currentText(), m_fontSize->value(), ( m_boldCheck->isChecked() ? 75 : 50 ), m_italicCheck->isChecked() );
00496 }
00497
00498 void
00499 VTextOptionsWidget::setText( const QString& text )
00500 {
00501 m_textEditor->setText( text );
00502 }
00503
00504 QString VTextOptionsWidget::text()
00505 {
00506 return m_textEditor->text();
00507 }
00508
00509 void
00510 VTextOptionsWidget::setPosition( VText::Position position )
00511 {
00512 m_textPosition->setCurrentItem( position );
00513 }
00514
00515 VText::Position VTextOptionsWidget::position()
00516 {
00517 return ( VText::Position ) m_textPosition->currentItem();
00518 }
00519
00520 void
00521 VTextOptionsWidget::setAlignment( VText::Alignment alignment )
00522 {
00523 m_textAlignment->setCurrentItem( alignment );
00524 }
00525
00526 VText::Alignment VTextOptionsWidget::alignment()
00527 {
00528 return ( VText::Alignment ) m_textAlignment->currentItem();
00529 }
00530
00531 void
00532 VTextOptionsWidget::setOffset( double offset )
00533 {
00534 if( offset < 0.0 ) offset = 0.0;
00535 if( offset > 100.0 ) offset = 100.0;
00536
00537 m_textOffset->setValue( offset );
00538 }
00539 double
00540 VTextOptionsWidget::offset()
00541 {
00542 return m_textOffset->value();
00543 }
00544
00545 void
00546 VTextOptionsWidget::setUseShadow( bool state )
00547 {
00548 m_shadow->setUseShadow( state );
00549 }
00550
00551 bool VTextOptionsWidget::useShadow()
00552 {
00553 return m_shadow->useShadow();
00554 }
00555
00556 void
00557 VTextOptionsWidget::setShadow( int angle, int distance, bool translucent )
00558 {
00559 m_shadow->setShadowValues( angle, distance, translucent );
00560 }
00561
00562 bool VTextOptionsWidget::translucentShadow()
00563 {
00564 return m_shadow->isTranslucent();
00565 }
00566
00567 int
00568 VTextOptionsWidget::shadowAngle()
00569 {
00570 return m_shadow->shadowAngle();
00571 }
00572
00573 int
00574 VTextOptionsWidget::shadowDistance()
00575 {
00576 return m_shadow->shadowDistance();
00577 }
00578
00579 void
00580 VTextOptionsWidget::initialize( VObject &text )
00581 {
00582 if( m_tool )
00583 m_tool->visit( text );
00584 }
00585
00586 VTextTool::VTextTool( KarbonView *view )
00587 : VTool( view, "tool_text" )
00588 {
00589 m_optionsWidget = new VTextOptionsWidget( this, 0L );
00590 m_text = 0L;
00591 m_editedText = 0L;
00592 registerTool( this );
00593 m_cursor = new QCursor( VCursor::createCursor( VCursor::CrossHair ) );
00594 }
00595
00596 VTextTool::~VTextTool()
00597 {
00598 delete m_optionsWidget;
00599 delete m_editedText;
00600 delete m_cursor;
00601 }
00602
00603 QString VTextTool::contextHelp()
00604 {
00605 QString s = i18n( "<qt><b>Text Tool</b><br>" );
00606 s += i18n("<i>Click</i> on document to place horizontal text.<br>" );
00607 s += i18n("<i>Click and drag</i> in document to place directional text.<br>" );
00608 s += i18n("<i>Click</i> on a selected path object to place text along its outline.<br>" );
00609 s += i18n("<i>Click</i> on a selected text object to change it.<br></qt>" );
00610
00611 return s;
00612 }
00613
00614 void
00615 VTextTool::activate()
00616 {
00617 VTool::activate();
00618 view()->statusMessage()->setText( i18n( "Text Tool" ) );
00619 view()->setCursor( *m_cursor );
00620
00621 m_creating = true;
00622 m_text = 0L;
00623 delete m_editedText;
00624 m_editedText = 0L;
00625 }
00626
00627 void
00628 VTextTool::deactivate()
00629 {
00630 }
00631
00632 void
00633 VTextTool::draw( VPainter* painter )
00634 {
00635 if( m_editedText )
00636 m_editedText->draw( painter, &m_editedText->boundingBox() );
00637 }
00638
00639 void
00640 VTextTool::drawPathCreation()
00641 {
00642 VPainter * painter = view()->painterFactory()->editpainter();
00643
00644 painter->setZoomFactor( view()->zoom() );
00645
00646 painter->setRasterOp( Qt::NotROP );
00647 painter->newPath();
00648 painter->setPen( Qt::DotLine );
00649 painter->setBrush( Qt::NoBrush );
00650
00651 painter->moveTo( first() );
00652 painter->lineTo( m_last );
00653 painter->strokePath();
00654 }
00655
00656 void
00657 VTextTool::drawEditedText()
00658 {
00659 if( m_editedText )
00660 view()->repaintAll( m_editedText->boundingBox() );
00661 }
00662
00663 void
00664 VTextTool::mouseButtonPress()
00665 {
00666 m_last = first();
00667 drawPathCreation();
00668 m_stepwise = false;
00669 }
00670
00671 void
00672 VTextTool::mouseButtonRelease()
00673 {
00674 if( ! view() )
00675 return;
00676
00677 VSelection* selection = view()->part()->document().selection();
00678 VObject* selObj = selection->objects().getFirst();
00679
00680
00681 if( selection->objects().count() == 1 && selObj->boundingBox().contains( last() ) )
00682 m_optionsWidget->initialize( *selObj );
00683 else
00684 {
00685
00686 VSubpath path( 0L );
00687 path.moveTo( first() );
00688 path.lineTo( KoPoint( first().x()+10, first().y() ) );
00689
00690 if( ! createText( path ) )
00691 return;
00692 }
00693
00694 if( dynamic_cast<VText*>( selObj ) && selObj->boundingBox().contains( last() ) )
00695 m_optionsWidget->setCaption( i18n( "Change Text") );
00696 else
00697 m_optionsWidget->setCaption( i18n( "Insert Text") );
00698
00699 m_optionsWidget->show();
00700 }
00701
00702 void
00703 VTextTool::mouseDrag()
00704 {
00705 drawPathCreation();
00706
00707 if( m_stepwise && shiftPressed() )
00708 {
00709 KoPoint act = last();
00710 KoPoint dst = act - first();
00711
00712 double angle = atan2( dst.y(), dst.x() );
00713 if( angle < 0 )
00714 angle += VGlobal::twopi;
00715
00716
00717 double prevStep = angle - fmod( angle, VGlobal::pi_2 / 2.0f );
00718 double nextStep = prevStep + VGlobal::pi_2 / 2.0f;
00719
00720 double length = sqrt( dst.x()*dst.x() + dst.y()*dst.y() );
00721
00722
00723 if( angle - prevStep < nextStep - angle )
00724 {
00725 m_last.setX( first().x() + length * cos( prevStep ) );
00726 m_last.setY( first().y() + length * sin( prevStep ) );
00727 }
00728 else
00729 {
00730 m_last.setX( first().x() + length * cos( nextStep ) );
00731 m_last.setY( first().y() + length * sin( nextStep ) );
00732 }
00733 }
00734 else
00735 m_last = last();
00736
00737 drawPathCreation();
00738 }
00739
00740 void
00741 VTextTool::mouseDragRelease()
00742 {
00743 drawPathCreation();
00744
00745 if( m_creating && m_editedText )
00746 {
00747 drawEditedText();
00748 delete m_editedText;
00749 m_editedText = 0L;
00750 }
00751
00752
00753 VSubpath path( 0L );
00754 path.moveTo( first() );
00755 path.lineTo( m_last );
00756
00757 if( createText( path ) )
00758 {
00759 m_optionsWidget->setCaption( i18n( "Insert Text") );
00760 m_optionsWidget->show();
00761 }
00762 }
00763
00764 bool
00765 VTextTool::createText( VSubpath &path )
00766 {
00767
00768 m_text = 0L;
00769 delete m_editedText;
00770
00771 m_editedText = new VText( m_optionsWidget->font(), path, m_optionsWidget->position(), m_optionsWidget->alignment(), m_optionsWidget->text() );
00772
00773 if( ! m_editedText )
00774 return false;
00775
00776 m_editedText->setState( VObject::edit );
00777
00778 #ifdef HAVE_KARBONTEXT
00779 m_editedText->traceText();
00780 #endif
00781
00782
00783 m_creating = true;
00784
00785 return true;
00786 }
00787
00788 void
00789 VTextTool::textChanged()
00790 {
00791 if( !m_editedText )
00792 return;
00793
00794 if( !m_creating && m_text && m_text->state() != VObject::hidden )
00795 {
00796
00797 m_text->setState( VObject::hidden );
00798 view()->repaintAll( m_text->boundingBox() );
00799 }
00800 else
00801 view()->repaintAll( m_editedText->boundingBox() );
00802
00803 m_editedText->setText( m_optionsWidget->text() );
00804 m_editedText->setFont( m_optionsWidget->font() );
00805 m_editedText->setPosition( m_optionsWidget->position() );
00806 m_editedText->setAlignment( m_optionsWidget->alignment() );
00807 m_editedText->setOffset( 0.01 * m_optionsWidget->offset() );
00808 #ifdef HAVE_KARBONTEXT
00809 m_editedText->traceText();
00810 #endif
00811
00812 drawEditedText();
00813 }
00814
00815 void
00816 VTextTool::accept()
00817 {
00818 if( !m_editedText )
00819 return;
00820
00821 VTextCmd* cmd;
00822
00823 if( !m_creating )
00824 {
00825 cmd = new VTextCmd(
00826 &view()->part()->document(),
00827 i18n( "Change Text" ),
00828 m_text,
00829 m_editedText->font(),
00830 m_editedText->basePath(),
00831 m_editedText->position(),
00832 m_editedText->alignment(),
00833 m_editedText->offset(),
00834 m_editedText->text(),
00835 m_optionsWidget->useShadow(),
00836 m_optionsWidget->shadowAngle(),
00837 m_optionsWidget->shadowDistance(),
00838 m_optionsWidget->translucentShadow() );
00839 }
00840 else
00841 {
00842 VText *newText = m_editedText->clone();
00843 newText->setUseShadow( m_optionsWidget->useShadow() );
00844 newText->setShadow( m_optionsWidget->shadowAngle(), m_optionsWidget->shadowDistance(), m_optionsWidget->translucentShadow() );
00845
00846 cmd = new VTextCmd(
00847 &view()->part()->document(),
00848 i18n( "Insert Text" ),
00849 newText );
00850
00851 delete m_editedText;
00852 m_editedText = 0L;
00853 }
00854
00855 view()->part()->addCommand( cmd, true );
00856 view()->part()->repaintAllViews();
00857 m_creating = false;
00858 }
00859
00860 void
00861 VTextTool::cancel()
00862 {
00863 if( m_text )
00864 {
00865
00866 m_text->setState( VObject::selected );
00867 view()->repaintAll( m_text->boundingBox() );
00868 }
00869 else
00870 drawPathCreation();
00871
00872 delete m_editedText;
00873 m_editedText = 0L;
00874 }
00875
00876 void
00877 VTextTool::editBasePath()
00878 {
00879 if( !m_editedText )
00880 return;
00881
00882 view()->part()->document().selection()->clear();
00883 view()->part()->document().selection()->append( &m_editedText->basePath() );
00884 view()->part()->repaintAllViews();
00885 }
00886
00887 void
00888 VTextTool::convertToShapes()
00889 {
00890 if( !m_text )
00891 return;
00892
00893 VTextToCompositeCmd* cmd = new VTextToCompositeCmd(
00894 &view()->part()->document(),
00895 i18n( "Text Conversion" ),
00896 m_text );
00897
00898 view()->part()->addCommand( cmd, true );
00899
00900 m_creating = false;
00901
00902 delete m_editedText;
00903
00904 m_text = 0L;
00905 m_editedText = 0L;
00906 }
00907
00908 void
00909 VTextTool::visitVPath( VPath& composite )
00910 {
00911 if( composite.paths().count() == 0 )
00912 return;
00913
00914 if( createText( *composite.paths().getFirst() ) )
00915 drawEditedText();
00916 }
00917
00918 void
00919 VTextTool::visitVSubpath( VSubpath& path )
00920 {
00921 if( createText( path ) )
00922 drawEditedText();
00923 }
00924
00925 void
00926 VTextTool::visitVText( VText& text )
00927 {
00928 m_text = &text;
00929 delete m_editedText;
00930 m_editedText = text.clone();
00931
00932 m_optionsWidget->setFont( text.font() );
00933 m_optionsWidget->setText( text.text() );
00934 m_optionsWidget->setPosition( text.position() );
00935 m_optionsWidget->setAlignment( text.alignment() );
00936 m_optionsWidget->setOffset( text.offset() * 100.0 );
00937 m_optionsWidget->setUseShadow( text.useShadow() );
00938 m_optionsWidget->setShadow( text.shadowAngle(), text.shadowDistance(), text.translucentShadow() );
00939 m_creating = false;
00940 m_text->setState( VObject::hidden );
00941 m_editedText->setState( VObject::edit );
00942 }
00943
00944 VTextTool::VTextCmd::VTextCmd( VDocument* doc, const QString& name, VText* text )
00945 : VCommand( doc, name, "14_text" ), m_text( text )
00946 {
00947 m_textModifications = 0L;
00948
00949 m_executed = false;
00950 }
00951
00952 VTextTool::VTextCmd::VTextCmd( VDocument* doc, const QString& name, VText* text,
00953 const QFont &newFont, const VSubpath& newBasePath, VText::Position newPosition, VText::Alignment newAlignment, double newOffset, const QString& newText,
00954 bool newUseShadow, int newShadowAngle, int newShadowDistance, bool newTranslucentShadow )
00955 : VCommand( doc, name, "14_text" ), m_text( text )
00956 {
00957 m_textModifications = new VTextModifPrivate();
00958 m_textModifications->newFont = newFont;
00959 m_textModifications->oldFont = text->font();
00960 m_textModifications->newBasePath = newBasePath;
00961 m_textModifications->oldBasePath = text->basePath();
00962 m_textModifications->newPosition = newPosition;
00963 m_textModifications->oldPosition = text->position();
00964 m_textModifications->newAlignment = newAlignment;
00965 m_textModifications->oldAlignment = text->alignment();
00966 m_textModifications->newOffset = newOffset;
00967 m_textModifications->oldOffset = text->offset();
00968 m_textModifications->newText = newText;
00969 m_textModifications->oldText = text->text();
00970 m_textModifications->newUseShadow = newUseShadow;
00971 m_textModifications->oldUseShadow = text->useShadow();
00972 m_textModifications->newShadowAngle = newShadowAngle;
00973 m_textModifications->oldShadowAngle = text->shadowAngle();
00974 m_textModifications->newShadowDistance = newShadowDistance;
00975 m_textModifications->oldShadowDistance = text->shadowDistance();
00976 m_textModifications->newTranslucentShadow = newTranslucentShadow;
00977 m_textModifications->oldTranslucentShadow = text->translucentShadow();
00978
00979 m_executed = false;
00980 }
00981
00982 VTextTool::VTextCmd::~VTextCmd()
00983 {
00984 delete m_textModifications;
00985 }
00986
00987 void
00988 VTextTool::VTextCmd::execute()
00989 {
00990 if( !m_text )
00991 return;
00992
00993 if( !m_textModifications )
00994 {
00995 if( m_text->state() == VObject::deleted )
00996 m_text->setState( VObject::normal );
00997 else
00998 {
00999 m_text->setState( VObject::normal );
01000 document()->append( m_text );
01001 document()->selection()->clear();
01002 document()->selection()->append( m_text );
01003 }
01004 }
01005 else
01006 {
01007 m_text->setFont( m_textModifications->newFont );
01008 m_text->setBasePath( m_textModifications->newBasePath );
01009 m_text->setPosition( m_textModifications->newPosition );
01010 m_text->setAlignment( m_textModifications->newAlignment );
01011 m_text->setOffset( m_textModifications->newOffset );
01012 m_text->setText( m_textModifications->newText );
01013 m_text->setUseShadow( m_textModifications->newUseShadow );
01014 m_text->setShadow( m_textModifications->newShadowAngle, m_textModifications->newShadowDistance, m_textModifications->newTranslucentShadow );
01015
01016 #ifdef HAVE_KARBONTEXT
01017 m_text->traceText();
01018 #endif
01019
01020 m_text->setState( VObject::normal );
01021 }
01022
01023 m_executed = true;
01024
01025 setSuccess( true );
01026 }
01027
01028 void
01029 VTextTool::VTextCmd::unexecute()
01030 {
01031 if( !m_text )
01032 return;
01033
01034 if( !m_textModifications )
01035 {
01036 document()->selection()->take( *m_text );
01037 m_text->setState( VObject::deleted );
01038 }
01039 else
01040 {
01041 m_text->setFont( m_textModifications->oldFont );
01042 m_text->setBasePath( m_textModifications->oldBasePath );
01043 m_text->setPosition( m_textModifications->oldPosition );
01044 m_text->setAlignment( m_textModifications->oldAlignment );
01045 m_text->setOffset( m_textModifications->oldOffset );
01046 m_text->setText( m_textModifications->oldText );
01047 m_text->setUseShadow( m_textModifications->oldUseShadow );
01048 m_text->setShadow( m_textModifications->oldShadowAngle, m_textModifications->oldShadowDistance, m_textModifications->oldTranslucentShadow );
01049
01050 #ifdef HAVE_KARBONTEXT
01051 m_text->traceText();
01052 #endif
01053
01054 m_text->setState( VObject::normal );
01055 }
01056
01057 m_executed = false;
01058
01059 setSuccess( false );
01060 }
01061
01062 VTextTool::VTextToCompositeCmd::VTextToCompositeCmd( VDocument* doc, const QString& name, VText* text )
01063 : VCommand( doc, name, "14_text" ), m_text( text ), m_group( 0L ), m_executed( false )
01064 {
01065 }
01066
01067 VTextTool::VTextToCompositeCmd::~VTextToCompositeCmd()
01068 {
01069 }
01070
01071 void
01072 VTextTool::VTextToCompositeCmd::execute()
01073 {
01074 if( !m_text )
01075 return;
01076
01077 if( !m_group )
01078 {
01079 m_group = m_text->toVGroup();
01080 document()->append( m_group );
01081 }
01082
01083 m_text->setState( VObject::deleted );
01084 m_group->setState( VObject::normal );
01085 document()->selection()->clear();
01086 document()->selection()->append( m_group );
01087
01088 m_executed = true;
01089
01090 setSuccess( true );
01091 }
01092
01093 void
01094 VTextTool::VTextToCompositeCmd::unexecute()
01095 {
01096 if( !m_text )
01097 return;
01098
01099 m_text->setState( VObject::normal );
01100
01101 document()->selection()->take( *m_group );
01102
01103 m_group->setState( VObject::deleted );
01104
01105 m_executed = false;
01106
01107 setSuccess( false );
01108 }
01109
01110 bool
01111 VTextTool::showDialog() const
01112 {
01113 VSelection* selection = view()->part()->document().selection();
01114
01115
01116 if( selection->objects().count() == 1 )
01117 m_optionsWidget->initialize( *selection->objects().getFirst());
01118 else
01119 return false;
01120
01121 if( dynamic_cast<VText*>( selection->objects().getFirst() ) )
01122 m_optionsWidget->setCaption(i18n( "Change Text") );
01123 else
01124 m_optionsWidget->setCaption(i18n( "Insert Text") );
01125
01126 m_optionsWidget->show();
01127 return true;
01128 }
01129
01130 void
01131 VTextTool::mouseDragShiftPressed()
01132 {
01133 m_stepwise = true;
01134 mouseDrag();
01135 }
01136
01137 void
01138 VTextTool::mouseDragShiftReleased()
01139 {
01140 m_stepwise = false;
01141 mouseDrag();
01142 }
01143
01144 void
01145 VTextTool::setup( KActionCollection *collection )
01146 {
01147 m_action = static_cast<KRadioAction *>(collection -> action( name() ) );
01148
01149 if( m_action == 0 )
01150 {
01151 m_action = new KRadioAction( i18n( "Text Tool" ), "14_text", Qt::SHIFT+Qt::Key_T, this, SLOT( activate() ), collection, name() );
01152 m_action->setToolTip( i18n( "Text Tool" ) );
01153 m_action->setExclusiveGroup( "misc" );
01154
01155 }
01156 }
01157
01158 #include "vtexttool.moc"
01159