karbon

vtexttool.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2001, 2002, 2003 The Karbon Developers
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18*/
19
20#include <math.h>
21
22#include <tqcheckbox.h>
23#include <tqcombobox.h>
24#include <tqcursor.h>
25#include <tqlabel.h>
26#include <tqlayout.h>
27#include <tqlineedit.h>
28#include <tqpainter.h>
29#include <tqpixmap.h>
30#include <tqpushbutton.h>
31#include <tqtabwidget.h>
32
33#include <kdebug.h>
34#include <tdefontcombo.h>
35#include <tdefontdialog.h>
36#include <kiconloader.h>
37#include <knuminput.h>
38#include <tdeglobalsettings.h>
39
40#include <karbon_view.h>
41#include <karbon_part.h>
42#include <core/vdocument.h>
43#include <core/vglobal.h>
44#include <core/vselection.h>
45#include <core/vfill.h>
46#include <core/vgroup.h>
47#include <core/vstroke.h>
48#include <core/vcursor.h>
49#include <render/vpainterfactory.h>
50#include <render/vkopainter.h>
51#include "vtexttool.h"
52
53
54static void
55traceShape( VKoPainter* p, int x, int y, int w, int h )
56{
57 p->newPath();
58 p->moveTo( KoPoint( x + w , y + h ) );
59 p->lineTo( KoPoint( x + w / 3, y + h ) );
60 p->lineTo( KoPoint( x + w / 3, y + h / 3 ) );
61 p->lineTo( KoPoint( x + w , y + h / 3 ) );
62 p->lineTo( KoPoint( x + w , y + h ) );
63
64 p->moveTo( KoPoint( x , y ) );
65 p->lineTo( KoPoint( x + ( w / 3 ) * 2, y ) );
66 p->lineTo( KoPoint( x + ( w / 3 ) * 2, y + ( h / 3 ) * 2 ) );
67 p->lineTo( KoPoint( x , y + ( h / 3 ) * 2 ) );
68 p->lineTo( KoPoint( x , y ) );
69}
70
71ShadowPreview::ShadowPreview( ShadowWidget* parent )
72 : TQWidget( parent ), m_parent( parent )
73{
74 setBackgroundMode( TQt::NoBackground );
75 setMinimumSize( 60, 60 );
76
77 connect( this, TQ_SIGNAL( changed( int, int, bool ) ), m_parent, TQ_SLOT( setShadowValues( int, int, bool ) ) );
78}
79
80ShadowPreview::~ShadowPreview()
81{
82}
83
84void
85ShadowPreview::mouseReleaseEvent( TQMouseEvent* e )
86{
87 int dx = e->x() - width() / 2;
88 int dy = e->y() - height() / 2;
89
90 float fd = sqrt( double( dx * dx + dy * dy ) );
91 int a;
92
93 if( fd == 0 )
94 a = 0;
95 else if( dy == 0 && dx < 0 )
96 a = 180;
97 else
98 {
99 float r = acos( dx / fd );
100 a = int( ( dy <= 0 ? r : VGlobal::twopi - r ) / VGlobal::twopi * 360. );
101 }
102
103 emit changed( a, ( int ) fd, m_parent->isTranslucent() );
104}
105
106void
107ShadowPreview::paintEvent( TQPaintEvent* )
108{
109 int w = width() - 4;
110 int h = height() - 4;
111 int d = m_parent->shadowDistance();
112 int a = 360 - m_parent->shadowAngle();
113
114 TQPixmap pm( w, h );
115 VKoPainter p( &pm, w, h );
116 VColor color( VColor::rgb );
117
118 VFill fill;
119 TDEIconLoader il;
120 fill.pattern() = VPattern( il.iconPath( "karbon.png", TDEIcon::Small ) );
121 fill.setType( VFill::patt );
122
123 p.newPath();
124 p.moveTo( KoPoint( 0, 0 ) );
125 p.lineTo( KoPoint( 0, h ) );
126 p.lineTo( KoPoint( w, h ) );
127 p.lineTo( KoPoint( w, 0 ) );
128 p.lineTo( KoPoint( 0, 0 ) );
129 p.setBrush( fill );
130 p.fillPath();
131
132 color.set( 1., 1., 1. );
133 color.setOpacity( .5 );
134 p.setBrush( VFill( color ) );
135 p.fillPath();
136
137 if( m_parent->isTranslucent() )
138 {
139 color.set( 0., 0., 0. );
140 color.setOpacity( .3 );
141 }
142 else
143 {
144 color.set( .3, .3, .3 );
145 color.setOpacity( 1. );
146 }
147
148 p.setPen( VStroke( color ) );
149 p.setBrush( VFill( color ) );
150
151 traceShape(
152 &p,
153 int( w / 4 + d * cos( a / 360. * VGlobal::twopi ) ),
154 int( h / 4 + d * sin( a / 360. * VGlobal::twopi ) ), int( w / 2 ), int( h / 2 ) );
155
156 p.strokePath();
157 p.fillPath();
158
159 color.set( 0., 0., 1. );
160 color.setOpacity( 1. );
161 p.setBrush( VFill( color ) );
162 color.set( 0., 0., .5 );
163 p.setPen( VStroke( color ) );
164 traceShape( &p, w / 4, h / 4, w / 2, h / 2 );
165 p.strokePath();
166 p.fillPath();
167
168 if( !m_parent->useShadow() )
169 {
170 p.newPath();
171 p.moveTo( KoPoint( 0, 0 ) );
172 p.lineTo( KoPoint( 0, h ) );
173 p.lineTo( KoPoint( w, h ) );
174 p.lineTo( KoPoint( w, 0 ) );
175 p.lineTo( KoPoint( 0, 0 ) );
176 VColor c( colorGroup().background() );
177 c.setOpacity( .8 );
178 p.setBrush( VFill( c ) );
179 p.fillPath();
180 }
181
182 p.end();
183
184 TQPainter painter( this );
185 painter.drawPixmap( 2, 2, pm );
186 painter.setPen( colorGroup().light() );
187 painter.moveTo( 1, height() - 1 );
188 painter.lineTo( 1, 1 );
189 painter.lineTo( width() - 1, 1 );
190 painter.lineTo( width() - 1, height() - 1 );
191 painter.lineTo( 1, height() - 1 );
192 painter.setPen( colorGroup().dark() );
193 painter.moveTo( 0, height() - 1 );
194 painter.lineTo( 0, 0 );
195 painter.lineTo( width() - 1, 0 );
196 painter.moveTo( width() - 2, 2 );
197 painter.lineTo( width() - 2, height() - 2 );
198 painter.lineTo( 2, height() - 2 );
199 painter.setPen( TQt::black );
200 painter.drawLine( width() / 2 - 2, height() / 2, width() / 2 + 2, height() / 2 );
201 painter.drawLine( width() / 2, height() / 2 - 2, width() / 2, height() / 2 + 2 );
202}
203
204ShadowWidget::ShadowWidget( TQWidget* parent, const char* name, int angle, int distance, bool translucent )
205 : TQGroupBox( parent, name )
206{
207 setTitle( i18n( "Shadow" ) );
208 setSizePolicy( TQSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::Minimum ) );
209
210 TQGridLayout* layout = new TQGridLayout( this );
211 layout->addRowSpacing( 0, 12 );
212 layout->setMargin( 3 );
213 layout->setSpacing( 2 );
214 layout->setColStretch( 0, 1 );
215 layout->setColStretch( 1, 0 );
216 layout->setColStretch( 2, 2 );
217 layout->addMultiCellWidget( m_preview = new ShadowPreview( this ), 1, 3, 0, 0 );
218 layout->addWidget( new TQLabel( i18n( "Angle:" ), this ), 1, 1 );
219 layout->addWidget( m_angle = new KIntNumInput( this ), 1, 2 );
220 layout->addWidget( new TQLabel( i18n( "Distance:" ), this ), 2, 1 );
221 layout->addWidget( m_distance = new KIntNumInput( this ), 2, 2 );
222 layout->addWidget( m_useShadow = new TQCheckBox( i18n( "Shadow" ), this ), 3, 1 );
223 layout->addWidget( m_translucent = new TQCheckBox( i18n( "Draw translucent shadow" ), this ), 3, 2 );
224 m_distance->setRange( 1, 37, 1, true );
225 m_angle->setRange( 0, 360, 10, true );
226 m_angle->setValue( angle );
227 m_distance->setValue( distance );
228 m_translucent->setChecked( translucent );
229
230 connect( m_angle, TQ_SIGNAL( valueChanged( int ) ), this, TQ_SLOT( updatePreview( int ) ) );
231 connect( m_distance, TQ_SIGNAL( valueChanged( int ) ), this, TQ_SLOT( updatePreview( int ) ) );
232 connect( m_useShadow, TQ_SIGNAL( clicked() ), this, TQ_SLOT( updatePreview() ) );
233 connect( m_translucent, TQ_SIGNAL( clicked() ), this, TQ_SLOT( updatePreview() ) );
234
235 updatePreview();
236}
237
238ShadowWidget::~ShadowWidget()
239{
240}
241
242void
243ShadowWidget::setUseShadow( bool use )
244{
245 m_useShadow->setChecked( use );
246 updatePreview();
247}
248
249bool ShadowWidget::useShadow()
250{
251 return m_useShadow->isChecked();
252}
253
254void
255ShadowWidget::setShadowAngle( int angle )
256{
257 m_angle->setValue( angle );
258 m_preview->repaint();
259}
260
261int
262ShadowWidget::shadowAngle()
263{
264 return m_angle->value();
265}
266
267void
268ShadowWidget::setShadowDistance( int distance )
269{
270 m_distance->setValue( distance );
271 m_preview->repaint();
272}
273
274int
275ShadowWidget::shadowDistance()
276{
277 return m_distance->value();
278}
279
280void
281ShadowWidget::setTranslucent( bool translucent )
282{
283 m_translucent->setChecked( translucent );
284 m_preview->repaint();
285}
286
287bool ShadowWidget::isTranslucent()
288{
289 return m_translucent->isChecked();
290}
291
292void
293ShadowWidget::setShadowValues( int angle, int distance, bool translucent )
294{
295 m_angle->setValue( angle );
296 m_distance->setValue( distance );
297 m_translucent->setChecked( translucent );
298 updatePreview();
299}
300
301void
302ShadowWidget::updatePreview( int )
303{
304 m_preview->repaint();
305}
306
307void
308ShadowWidget::updatePreview()
309{
310 m_preview->repaint();
311 bool ok = m_useShadow->isChecked();
312 m_angle->setEnabled( ok );
313 m_distance->setEnabled( ok );
314 m_translucent->setEnabled( ok );
315}
316
317VTextOptionsWidget::VTextOptionsWidget( VTextTool* tool, TQWidget *parent )
318 : KDialogBase( parent, "", true, i18n( "Text" ), Ok | Cancel ), m_tool( tool )
319{
320 //setSizePolicy( TQSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::Minimum ) );
321 //setFrameStyle( Box | Sunken );
322 TQWidget *base = new TQWidget( this );
323 TQVBoxLayout* mainLayout = new TQVBoxLayout( base );
324 mainLayout->setMargin( 3 );
325
326 mainLayout->add( m_tabWidget = new TQTabWidget( base ) );
327
328 m_tabWidget->setFont( TQFont( TDEGlobalSettings::generalFont().family() , 8 ) );
329
330 TQWidget* textWidget = new TQWidget( m_tabWidget );
331
332 TQGridLayout* textLayout = new TQGridLayout( textWidget );
333
334 TQStringList list;
335 TDEFontChooser::getFontList( list, TDEFontChooser::SmoothScalableFonts );
336
337 textLayout->setMargin( 3 );
338 textLayout->setSpacing( 2 );
339 textLayout->addMultiCellWidget( m_fontCombo = new TDEFontCombo( list, textWidget ), 0, 0, 0, 2 );
340 textLayout->addWidget( m_fontSize = new KIntNumInput( textWidget ), 1, 0 );
341 textLayout->addWidget( m_boldCheck = new TQCheckBox( i18n( "Bold" ), textWidget ), 1, 1 );
342 textLayout->addWidget( m_italicCheck = new TQCheckBox( i18n( "Italic" ), textWidget ), 1, 2 );
343 textLayout->addMultiCellWidget( m_textEditor = new TQLineEdit( textWidget ), 2, 2, 0, 2 );
344
345 m_tabWidget->addTab( textWidget, i18n( "Text" ) );
346
347 TQWidget* posWidget = new TQWidget( m_tabWidget );
348
349 TQGridLayout* posLayout = new TQGridLayout( posWidget );
350 textLayout->setMargin( 3 );
351 posLayout->setSpacing( 2 );
352 posLayout->addWidget( new TQLabel( i18n( "Alignment:" ), posWidget ), 0, 0 );
353 posLayout->addWidget( m_textAlignment = new TQComboBox( posWidget ), 0, 1 );
354 posLayout->addWidget( new TQLabel( i18n( "Position:" ), posWidget ), 1, 0 );
355 posLayout->addWidget( m_textPosition = new TQComboBox( posWidget ), 1, 1 );
356 posLayout->addWidget( new TQLabel( i18n( "Offset:" ), posWidget ), 2, 0 );
357 posLayout->addWidget( m_textOffset = new KDoubleNumInput( posWidget ), 2, 1 );
358 posLayout->setColStretch( 0, 0 );
359 posLayout->setColStretch( 1, 1 );
360
361 m_tabWidget->addTab( posWidget, i18n( "Position" ) );
362
363 TQWidget* fxWidget = new TQWidget( m_tabWidget );
364
365 TQVBoxLayout* fxLayout = new TQVBoxLayout( fxWidget );
366
367 fxLayout->setMargin( 3 );
368 fxLayout->setSpacing( 2 );
369 fxLayout->add( m_shadow = new ShadowWidget( fxWidget, 0L, 315, 4, true ) );
370
371 TQHBoxLayout* fxLayout2 = new TQHBoxLayout( fxLayout );
372
373 fxLayout2->setSpacing( 2 );
374 fxLayout2->addWidget( m_editBasePath = new TQPushButton( i18n( "Edit Base Path" ), fxWidget ) );
375 fxLayout2->addWidget( m_convertToShapes = new TQPushButton( i18n( "Convert to Shapes" ), fxWidget ) );
376
377 m_tabWidget->addTab( fxWidget, i18n( "Effects" ) );
378
379 m_fontCombo->setCurrentText( TDEGlobalSettings::generalFont().family() );
380
381 m_fontSize->setValue( 12 );
382 m_fontSize->setSuffix( " pt" );
383
384 m_textEditor->setMinimumHeight( 100 );
385 m_textEditor->setText( i18n( "New text") );
386 m_textEditor->selectAll();
387
388 m_convertToShapes->setEnabled( true );
389
390 m_textAlignment->insertItem( i18n( "Horizontal alignment", "Left") );
391 m_textAlignment->insertItem( i18n( "Horizontal alignment", "Center") );
392 m_textAlignment->insertItem( i18n( "Horizontal alignment", "Right") );
393
394 m_textPosition->insertItem( i18n( "Vertical alignment", "Above") );
395 m_textPosition->insertItem( i18n( "Vertical alignment", "On") );
396 m_textPosition->insertItem( i18n( "Vertical alignment", "Under") );
397
398 m_textOffset->setRange( 0.0, 100.0, 1.0, true );
399
400 connect( m_fontCombo, TQ_SIGNAL( activated( int ) ), this, TQ_SLOT( valueChanged( int ) ) );
401 connect( m_boldCheck, TQ_SIGNAL( stateChanged( int ) ), this, TQ_SLOT( valueChanged( int ) ) );
402 connect( m_italicCheck, TQ_SIGNAL( stateChanged( int ) ), this, TQ_SLOT( valueChanged( int ) ) );
403 connect( m_fontSize, TQ_SIGNAL( valueChanged( int ) ), this, TQ_SLOT( valueChanged( int ) ) );
404 connect( m_textPosition, TQ_SIGNAL( activated( int ) ), this, TQ_SLOT( valueChanged( int ) ) );
405 connect( m_textAlignment, TQ_SIGNAL( activated( int ) ), this, TQ_SLOT( valueChanged( int ) ) );
406 connect( m_textOffset, TQ_SIGNAL( valueChanged( double ) ), this, TQ_SLOT( valueChanged( double ) ) );
407 connect( m_textEditor, TQ_SIGNAL( returnPressed() ), this, TQ_SLOT( accept() ) );
408 connect( m_textEditor, TQ_SIGNAL( textChanged( const TQString& ) ), this, TQ_SLOT( textChanged( const TQString& ) ) );
409 connect( m_editBasePath, TQ_SIGNAL( clicked() ), this, TQ_SLOT( editBasePath() ) );
410 connect( m_convertToShapes, TQ_SIGNAL( clicked() ), this, TQ_SLOT( convertToShapes() ) );
411 connect( this, TQ_SIGNAL( cancelClicked() ), this, TQ_SLOT( cancel() ) );
412
413 setMainWidget( base );
414 setFixedSize( baseSize() );
415}
416
417VTextOptionsWidget::~VTextOptionsWidget()
418{
419}
420
421void
422VTextOptionsWidget::valueChanged( int )
423{
424 m_fontCombo->setBold( m_boldCheck->isChecked() );
425 m_fontCombo->setItalic( m_italicCheck->isChecked() );
426
427 m_textEditor->setFont( TQFont( m_fontCombo->currentText(), m_fontSize->value(), ( m_boldCheck->isChecked() ? 75 : 50 ), m_italicCheck->isChecked() ) );
428
429 if( m_tool && isVisible() )
430 m_tool->textChanged();
431}
432
433void
434VTextOptionsWidget::valueChanged( double )
435{
436 if( m_tool && isVisible() )
437 m_tool->textChanged();
438}
439
440void
441VTextOptionsWidget::accept()
442{
443 if( m_tool )
444 m_tool->accept();
445 hide();
446}
447
448void
449VTextOptionsWidget::cancel()
450{
451 if( m_tool )
452 m_tool->cancel();
453}
454
455void
456VTextOptionsWidget::textChanged( const TQString& )
457{
458 if( m_tool && isVisible() )
459 m_tool->textChanged();
460}
461
462void
463VTextOptionsWidget::editBasePath()
464{
465 if( m_tool )
466 m_tool->editBasePath();
467}
468
469void
470VTextOptionsWidget::convertToShapes()
471{
472 if( m_tool )
473 m_tool->convertToShapes();
474}
475
476void
477VTextOptionsWidget::setFont( const TQFont& font )
478{
479 m_fontCombo->setCurrentText( font.family() );
480
481 m_boldCheck->setChecked( font.bold() );
482
483 m_italicCheck->setChecked( font.italic() );
484
485 m_fontSize->setValue( font.pointSize() );
486
487 m_fontCombo->setBold( m_boldCheck->isChecked() );
488 m_fontCombo->setItalic( m_italicCheck->isChecked() );
489
490 m_textEditor->setFont( TQFont( m_fontCombo->currentText(), m_fontSize->value(), ( m_boldCheck->isChecked() ? 75 : 50 ), m_italicCheck->isChecked() ) );
491}
492
493TQFont VTextOptionsWidget::font()
494{
495 return TQFont( m_fontCombo->currentText(), m_fontSize->value(), ( m_boldCheck->isChecked() ? 75 : 50 ), m_italicCheck->isChecked() );
496}
497
498void
499VTextOptionsWidget::setText( const TQString& text )
500{
501 m_textEditor->setText( text );
502}
503
504TQString VTextOptionsWidget::text()
505{
506 return m_textEditor->text();
507}
508
509void
510VTextOptionsWidget::setPosition( VText::Position position )
511{
512 m_textPosition->setCurrentItem( position );
513}
514
515VText::Position VTextOptionsWidget::position()
516{
517 return ( VText::Position ) m_textPosition->currentItem();
518}
519
520void
521VTextOptionsWidget::setAlignment( VText::Alignment alignment )
522{
523 m_textAlignment->setCurrentItem( alignment );
524}
525
526VText::Alignment VTextOptionsWidget::alignment()
527{
528 return ( VText::Alignment ) m_textAlignment->currentItem();
529}
530
531void
532VTextOptionsWidget::setOffset( double offset )
533{
534 if( offset < 0.0 ) offset = 0.0;
535 if( offset > 100.0 ) offset = 100.0;
536
537 m_textOffset->setValue( offset );
538}
539double
540VTextOptionsWidget::offset()
541{
542 return m_textOffset->value();
543}
544
545void
546VTextOptionsWidget::setUseShadow( bool state )
547{
548 m_shadow->setUseShadow( state );
549}
550
551bool VTextOptionsWidget::useShadow()
552{
553 return m_shadow->useShadow();
554}
555
556void
557VTextOptionsWidget::setShadow( int angle, int distance, bool translucent )
558{
559 m_shadow->setShadowValues( angle, distance, translucent );
560}
561
562bool VTextOptionsWidget::translucentShadow()
563{
564 return m_shadow->isTranslucent();
565}
566
567int
568VTextOptionsWidget::shadowAngle()
569{
570 return m_shadow->shadowAngle();
571}
572
573int
574VTextOptionsWidget::shadowDistance()
575{
576 return m_shadow->shadowDistance();
577}
578
579void
580VTextOptionsWidget::initialize( VObject &text )
581{
582 if( m_tool )
583 m_tool->visit( text );
584}
585
586VTextTool::VTextTool( KarbonView *view )
587 : VTool( view, "tool_text" )
588{
589 m_optionsWidget = new VTextOptionsWidget( this, 0L );
590 m_text = 0L;
591 m_editedText = 0L;
592 registerTool( this );
593 m_cursor = new TQCursor( VCursor::createCursor( VCursor::CrossHair ) );
594}
595
596VTextTool::~VTextTool()
597{
598 delete m_optionsWidget;
599 delete m_editedText;
600 delete m_cursor;
601}
602
603TQString VTextTool::contextHelp()
604{
605 TQString s = i18n( "<qt><b>Text Tool</b><br>" );
606 s += i18n("<i>Click</i> on document to place horizontal text.<br>" );
607 s += i18n("<i>Click and drag</i> in document to place directional text.<br>" );
608 s += i18n("<i>Click</i> on a selected path object to place text along its outline.<br>" );
609 s += i18n("<i>Click</i> on a selected text object to change it.<br></qt>" );
610
611 return s;
612}
613
614void
616{
618 view()->statusMessage()->setText( i18n( "Text Tool" ) );
619 view()->setCursor( *m_cursor );
620
621 m_creating = true;
622 m_text = 0L;
623 delete m_editedText;
624 m_editedText = 0L;
625}
626
627void
629{
630}
631
632void
633VTextTool::draw( VPainter* painter )
634{
635 if( m_editedText )
636 m_editedText->draw( painter, &m_editedText->boundingBox() );
637}
638
639void
640VTextTool::drawPathCreation()
641{
642 VPainter * painter = view()->painterFactory()->editpainter();
643
644 painter->setZoomFactor( view()->zoom() );
645
646 painter->setRasterOp( TQt::NotROP );
647 painter->newPath();
648 painter->setPen( TQt::DotLine );
649 painter->setBrush( TQt::NoBrush );
650
651 painter->moveTo( first() );
652 painter->lineTo( m_last );
653 painter->strokePath();
654}
655
656void
657VTextTool::drawEditedText()
658{
659 if( m_editedText )
660 view()->repaintAll( m_editedText->boundingBox() );
661}
662
663void
665{
666 m_last = first();
667 drawPathCreation();
668 m_stepwise = false;
669}
670
671void
673{
674 if( ! view() )
675 return;
676
677 VSelection* selection = view()->part()->document().selection();
678 VObject* selObj = selection->objects().getFirst();
679
680 // initialize dialog with single selected object
681 if( selection->objects().count() == 1 && selObj->boundingBox().contains( last() ) )
682 m_optionsWidget->initialize( *selObj );
683 else
684 {
685 // use a default horizontal path when just clicking
686 VSubpath path( 0L );
687 path.moveTo( first() );
688 path.lineTo( KoPoint( first().x()+10, first().y() ) );
689
690 if( ! createText( path ) )
691 return;
692 }
693
694 if( dynamic_cast<VText*>( selObj ) && selObj->boundingBox().contains( last() ) )
695 m_optionsWidget->setCaption( i18n( "Change Text") );
696 else
697 m_optionsWidget->setCaption( i18n( "Insert Text") );
698
699 m_optionsWidget->show();
700}
701
702void
704{
705 drawPathCreation();
706
707 if( m_stepwise && shiftPressed() )
708 {
709 KoPoint act = last();
710 KoPoint dst = act - first();
711
712 double angle = atan2( dst.y(), dst.x() );
713 if( angle < 0 )
714 angle += VGlobal::twopi;
715
716 // calculate previuos and next modulo 45 degree step
717 double prevStep = angle - fmod( angle, VGlobal::pi_2 / 2.0f );
718 double nextStep = prevStep + VGlobal::pi_2 / 2.0f;
719 // calculate distance between first and last point
720 double length = sqrt( dst.x()*dst.x() + dst.y()*dst.y() );
721
722 // use nearest step
723 if( angle - prevStep < nextStep - angle )
724 {
725 m_last.setX( first().x() + length * cos( prevStep ) );
726 m_last.setY( first().y() + length * sin( prevStep ) );
727 }
728 else
729 {
730 m_last.setX( first().x() + length * cos( nextStep ) );
731 m_last.setY( first().y() + length * sin( nextStep ) );
732 }
733 }
734 else
735 m_last = last();
736
737 drawPathCreation();
738}
739
740void
742{
743 drawPathCreation();
744
745 if( m_creating && m_editedText )
746 {
747 drawEditedText();
748 delete m_editedText;
749 m_editedText = 0L;
750 }
751
752 // use dragged path to create text along
753 VSubpath path( 0L );
754 path.moveTo( first() );
755 path.lineTo( m_last );
756
757 if( createText( path ) )
758 {
759 m_optionsWidget->setCaption( i18n( "Insert Text") );
760 m_optionsWidget->show();
761 }
762}
763
764bool
765VTextTool::createText( VSubpath &path )
766{
767 // no original text is used
768 m_text = 0L;
769 delete m_editedText;
770
771 m_editedText = new VText( m_optionsWidget->font(), path, m_optionsWidget->position(), m_optionsWidget->alignment(), m_optionsWidget->text() );
772
773 if( ! m_editedText )
774 return false;
775
776 m_editedText->setState( VObject::edit );
777
778#ifdef HAVE_KARBONTEXT
779 m_editedText->traceText();
780#endif
781
782 // yes, we are creating a new text object
783 m_creating = true;
784
785 return true;
786}
787
788void
789VTextTool::textChanged()
790{
791 if( !m_editedText )
792 return;
793
794 if( !m_creating && m_text && m_text->state() != VObject::hidden )
795 {
796 // hide the original text if we are changing it
797 m_text->setState( VObject::hidden );
798 view()->repaintAll( m_text->boundingBox() );
799 }
800 else
801 view()->repaintAll( m_editedText->boundingBox() );
802
803 m_editedText->setText( m_optionsWidget->text() );
804 m_editedText->setFont( m_optionsWidget->font() );
805 m_editedText->setPosition( m_optionsWidget->position() );
806 m_editedText->setAlignment( m_optionsWidget->alignment() );
807 m_editedText->setOffset( 0.01 * m_optionsWidget->offset() );
808#ifdef HAVE_KARBONTEXT
809 m_editedText->traceText();
810#endif
811
812 drawEditedText();
813}
814
815void
817{
818 if( !m_editedText )
819 return;
820
821 VTextCmd* cmd;
822
823 if( !m_creating )
824 {
825 cmd = new VTextCmd(
826 &view()->part()->document(),
827 i18n( "Change Text" ),
828 m_text,
829 m_editedText->font(),
830 m_editedText->basePath(),
831 m_editedText->position(),
832 m_editedText->alignment(),
833 m_editedText->offset(),
834 m_editedText->text(),
835 m_optionsWidget->useShadow(),
836 m_optionsWidget->shadowAngle(),
837 m_optionsWidget->shadowDistance(),
838 m_optionsWidget->translucentShadow() );
839 }
840 else
841 {
842 VText *newText = m_editedText->clone();
843 newText->setUseShadow( m_optionsWidget->useShadow() );
844 newText->setShadow( m_optionsWidget->shadowAngle(), m_optionsWidget->shadowDistance(), m_optionsWidget->translucentShadow() );
845
846 cmd = new VTextCmd(
847 &view()->part()->document(),
848 i18n( "Insert Text" ),
849 newText );
850
851 delete m_editedText;
852 m_editedText = 0L;
853 }
854
855 view()->part()->addCommand( cmd, true );
856 view()->part()->repaintAllViews();
857 m_creating = false;
858}
859
860void
862{
863 if( m_text )
864 {
865 // show original text if we canceled changing it
866 m_text->setState( VObject::selected );
867 view()->repaintAll( m_text->boundingBox() );
868 }
869 else
870 drawPathCreation();
871
872 delete m_editedText;
873 m_editedText = 0L;
874}
875
876void
877VTextTool::editBasePath()
878{
879 if( !m_editedText )
880 return;
881
882 view()->part()->document().selection()->clear();
883 view()->part()->document().selection()->append( &m_editedText->basePath() );
884 view()->part()->repaintAllViews();
885}
886
887void
888VTextTool::convertToShapes()
889{
890 if( !m_text )
891 return;
892
893 VTextToCompositeCmd* cmd = new VTextToCompositeCmd(
894 &view()->part()->document(),
895 i18n( "Text Conversion" ),
896 m_text );
897
898 view()->part()->addCommand( cmd, true );
899
900 m_creating = false;
901
902 delete m_editedText;
903
904 m_text = 0L;
905 m_editedText = 0L;
906}
907
908void
909VTextTool::visitVPath( VPath& composite )
910{
911 if( composite.paths().count() == 0 )
912 return;
913
914 if( createText( *composite.paths().getFirst() ) )
915 drawEditedText();
916}
917
918void
919VTextTool::visitVSubpath( VSubpath& path )
920{
921 if( createText( path ) )
922 drawEditedText();
923}
924
925void
926VTextTool::visitVText( VText& text )
927{
928 m_text = &text;
929 delete m_editedText;
930 m_editedText = text.clone();
931
932 m_optionsWidget->setFont( text.font() );
933 m_optionsWidget->setText( text.text() );
934 m_optionsWidget->setPosition( text.position() );
935 m_optionsWidget->setAlignment( text.alignment() );
936 m_optionsWidget->setOffset( text.offset() * 100.0 );
937 m_optionsWidget->setUseShadow( text.useShadow() );
938 m_optionsWidget->setShadow( text.shadowAngle(), text.shadowDistance(), text.translucentShadow() );
939 m_creating = false;
940 m_text->setState( VObject::hidden );
941 m_editedText->setState( VObject::edit );
942}
943
944VTextTool::VTextCmd::VTextCmd( VDocument* doc, const TQString& name, VText* text )
945 : VCommand( doc, name, "14_text" ), m_text( text )
946{
947 m_textModifications = 0L;
948
949 m_executed = false;
950}
951
952VTextTool::VTextCmd::VTextCmd( VDocument* doc, const TQString& name, VText* text,
953 const TQFont &newFont, const VSubpath& newBasePath, VText::Position newPosition, VText::Alignment newAlignment, double newOffset, const TQString& newText,
954 bool newUseShadow, int newShadowAngle, int newShadowDistance, bool newTranslucentShadow )
955 : VCommand( doc, name, "14_text" ), m_text( text )
956{
957 m_textModifications = new VTextModifPrivate();
958 m_textModifications->newFont = newFont;
959 m_textModifications->oldFont = text->font();
960 m_textModifications->newBasePath = newBasePath;
961 m_textModifications->oldBasePath = text->basePath();
962 m_textModifications->newPosition = newPosition;
963 m_textModifications->oldPosition = text->position();
964 m_textModifications->newAlignment = newAlignment;
965 m_textModifications->oldAlignment = text->alignment();
966 m_textModifications->newOffset = newOffset;
967 m_textModifications->oldOffset = text->offset();
968 m_textModifications->newText = newText;
969 m_textModifications->oldText = text->text();
970 m_textModifications->newUseShadow = newUseShadow;
971 m_textModifications->oldUseShadow = text->useShadow();
972 m_textModifications->newShadowAngle = newShadowAngle;
973 m_textModifications->oldShadowAngle = text->shadowAngle();
974 m_textModifications->newShadowDistance = newShadowDistance;
975 m_textModifications->oldShadowDistance = text->shadowDistance();
976 m_textModifications->newTranslucentShadow = newTranslucentShadow;
977 m_textModifications->oldTranslucentShadow = text->translucentShadow();
978
979 m_executed = false;
980}
981
982VTextTool::VTextCmd::~VTextCmd()
983{
984 delete m_textModifications;
985}
986
987void
989{
990 if( !m_text )
991 return;
992
993 if( !m_textModifications )
994 {
995 if( m_text->state() == VObject::deleted )
996 m_text->setState( VObject::normal );
997 else
998 {
999 m_text->setState( VObject::normal );
1000 document()->append( m_text );
1001 document()->selection()->clear();
1002 document()->selection()->append( m_text );
1003 }
1004 }
1005 else
1006 {
1007 m_text->setFont( m_textModifications->newFont );
1008 m_text->setBasePath( m_textModifications->newBasePath );
1009 m_text->setPosition( m_textModifications->newPosition );
1010 m_text->setAlignment( m_textModifications->newAlignment );
1011 m_text->setOffset( m_textModifications->newOffset );
1012 m_text->setText( m_textModifications->newText );
1013 m_text->setUseShadow( m_textModifications->newUseShadow );
1014 m_text->setShadow( m_textModifications->newShadowAngle, m_textModifications->newShadowDistance, m_textModifications->newTranslucentShadow );
1015
1016#ifdef HAVE_KARBONTEXT
1017 m_text->traceText();
1018#endif
1019
1020 m_text->setState( VObject::normal );
1021 }
1022
1023 m_executed = true;
1024
1025 setSuccess( true );
1026}
1027
1028void
1030{
1031 if( !m_text )
1032 return;
1033
1034 if( !m_textModifications )
1035 {
1036 document()->selection()->take( *m_text );
1037 m_text->setState( VObject::deleted );
1038 }
1039 else
1040 {
1041 m_text->setFont( m_textModifications->oldFont );
1042 m_text->setBasePath( m_textModifications->oldBasePath );
1043 m_text->setPosition( m_textModifications->oldPosition );
1044 m_text->setAlignment( m_textModifications->oldAlignment );
1045 m_text->setOffset( m_textModifications->oldOffset );
1046 m_text->setText( m_textModifications->oldText );
1047 m_text->setUseShadow( m_textModifications->oldUseShadow );
1048 m_text->setShadow( m_textModifications->oldShadowAngle, m_textModifications->oldShadowDistance, m_textModifications->oldTranslucentShadow );
1049
1050#ifdef HAVE_KARBONTEXT
1051 m_text->traceText();
1052#endif
1053
1054 m_text->setState( VObject::normal );
1055 }
1056
1057 m_executed = false;
1058
1059 setSuccess( false );
1060}
1061
1062VTextTool::VTextToCompositeCmd::VTextToCompositeCmd( VDocument* doc, const TQString& name, VText* text )
1063 : VCommand( doc, name, "14_text" ), m_text( text ), m_group( 0L ), m_executed( false )
1064{
1065}
1066
1067VTextTool::VTextToCompositeCmd::~VTextToCompositeCmd()
1068{
1069}
1070
1071void
1073{
1074 if( !m_text )
1075 return;
1076
1077 if( !m_group )
1078 {
1079 m_group = m_text->toVGroup();
1080 document()->append( m_group );
1081 }
1082
1083 m_text->setState( VObject::deleted );
1084 m_group->setState( VObject::normal );
1085 document()->selection()->clear();
1086 document()->selection()->append( m_group );
1087
1088 m_executed = true;
1089
1090 setSuccess( true );
1091}
1092
1093void
1095{
1096 if( !m_text )
1097 return;
1098
1099 m_text->setState( VObject::normal );
1100
1101 document()->selection()->take( *m_group );
1102
1103 m_group->setState( VObject::deleted );
1104
1105 m_executed = false;
1106
1107 setSuccess( false );
1108}
1109
1110bool
1112{
1113 VSelection* selection = view()->part()->document().selection();
1114
1115 // initialize dialog with single selected object
1116 if( selection->objects().count() == 1 )
1117 m_optionsWidget->initialize( *selection->objects().getFirst());
1118 else
1119 return false;
1120
1121 if( dynamic_cast<VText*>( selection->objects().getFirst() ) )
1122 m_optionsWidget->setCaption(i18n( "Change Text") );
1123 else
1124 m_optionsWidget->setCaption(i18n( "Insert Text") );
1125
1126 m_optionsWidget->show();
1127 return true;
1128}
1129
1130void
1132{
1133 m_stepwise = true;
1134 mouseDrag();
1135}
1136
1137void
1139{
1140 m_stepwise = false;
1141 mouseDrag();
1142}
1143
1144void
1145VTextTool::setup( TDEActionCollection *collection )
1146{
1147 m_action = static_cast<TDERadioAction *>(collection -> action( name() ) );
1148
1149 if( m_action == 0 )
1150 {
1151 m_action = new TDERadioAction( i18n( "Text Tool" ), "14_text", TQt::SHIFT+TQt::Key_T, this, TQ_SLOT( activate() ), collection, name() );
1152 m_action->setToolTip( i18n( "Text Tool" ) );
1153 m_action->setExclusiveGroup( "misc" );
1154 //m_ownAction = true;
1155 }
1156}
1157
1158#include "vtexttool.moc"
1159
void repaintAllViews(bool repaint=true)
repaint all views attached to this koDocument
void addCommand(VCommand *cmd, bool repaint=false)
insert a command into the undo/redo-history:
@ rgb
the RGB colorspace (red, green and blue components)
Definition vcolor.h:45
The base class for all karbon commands.
Definition vcommand.h:42
virtual void unexecute()
Unexecutes the command.
Definition vcommand.h:75
virtual void execute()=0
Executes the command.
@ CrossHair
unthemed crosshair cursor
Definition vcursor.h:38
static TQCursor createCursor(CursorType type)
Creates a predefined cursor of the specified type.
Definition vcursor.cpp:75
All non-visual, static doc info is in here.
Definition vdocument.h:53
VSelection * selection() const
Returns a pointer to the selection.
Definition vdocument.h:238
@ patt
gradient fill
Definition vfill.h:52
The base class for all karbon objects.
Definition vobject.h:50
@ selected
visible, active and can be manipulated by tools
Definition vobject.h:61
@ deleted
deleted, nearly dead
Definition vobject.h:58
@ normal
visible, not active
Definition vobject.h:54
@ edit
visible, active and is currently manipulated by a tool
Definition vobject.h:62
@ hidden
hidden
Definition vobject.h:56
virtual const KoRect & boundingBox() const
Calculates the tightest bounding box around the object.
Definition vobject.h:111
A composite path consists of one or many subpaths.
Definition vcomposite.h:48
const VObjectList & objects() const
Read only access to the selected objects.
Definition vselection.h:136
void append()
Adds all objects to the selection.
void clear()
Removes the references to all objects, not the objects themselves.
VSubpath provides a sophisticated list of VSegment.
Definition vpath.h:43
The base class for all karbon tools.
Definition vtool.h:52
virtual void mouseDragRelease()
Mouse button release.
Definition vtool.h:220
virtual void mouseButtonPress()
Left mouse button press.
Definition vtool.h:185
const KoPoint & last() const
The last mouse coordinate.
Definition vtool.h:285
const KoPoint & first() const
Most tools need to know the first mouse coordinate.
Definition vtool.h:280
virtual void mouseButtonRelease()
Left mouse button release.
Definition vtool.h:195
TDERadioAction * action() const
Returns the tool's associated action object.
Definition vtool.h:151
virtual void accept()
Terminates the current tool drawing (if any).
Definition vtool.h:265
virtual void cancel()
Cancels all tool operations.
Definition vtool.h:255
virtual void deactivate()
Deactivates the tool.
Definition vtool.h:83
virtual void activate()
Called during the tool activation.
Definition vtool.cpp:252
bool shiftPressed() const
The status of the shift key.
Definition vtool.h:292
TDERadioAction * m_action
The tool's action object.
Definition vtool.h:309
virtual void mouseDragShiftPressed()
Mouse drag with "Shift" key pressed at the same time.
Definition vtool.h:225
virtual void mouseDragShiftReleased()
"Shift" key released while mouse drag.
Definition vtool.h:235
virtual TQString contextHelp()
The context help of the tool.
Definition vtool.h:98
virtual void mouseDrag()
Mouse drag.
Definition vtool.h:215
KarbonView * view() const
Returns the connected karbon part.
Definition vtool.cpp:66
virtual bool showDialog() const
Shows the tools option dialog.
Definition vtool.h:88
void setSuccess(bool success=true)
Set the success property.
Definition vvisitor.h:142