diff options
Diffstat (limited to 'karbon/tools/vtexttool.cpp')
| -rw-r--r-- | karbon/tools/vtexttool.cpp | 1159 | 
1 files changed, 1159 insertions, 0 deletions
diff --git a/karbon/tools/vtexttool.cpp b/karbon/tools/vtexttool.cpp new file mode 100644 index 000000000..e7fa848d2 --- /dev/null +++ b/karbon/tools/vtexttool.cpp @@ -0,0 +1,1159 @@ +/* This file is part of the KDE project +   Copyright (C) 2001, 2002, 2003 The Karbon Developers + +   This library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Library General Public +   License as published by the Free Software Foundation; either +   version 2 of the License, or (at your option) any later version. + +   This library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Library General Public License for more details. + +   You should have received a copy of the GNU Library General Public License +   along with this library; see the file COPYING.LIB.  If not, write to +   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include <math.h> + +#include <tqcheckbox.h> +#include <tqcombobox.h> +#include <tqcursor.h> +#include <tqlabel.h> +#include <tqlayout.h> +#include <tqlineedit.h> +#include <tqpainter.h> +#include <tqpixmap.h> +#include <tqpushbutton.h> +#include <tqtabwidget.h> + +#include <kdebug.h> +#include <tdefontcombo.h> +#include <tdefontdialog.h> +#include <kiconloader.h> +#include <knuminput.h> +#include <tdeglobalsettings.h> + +#include <karbon_view.h> +#include <karbon_part.h> +#include <core/vdocument.h> +#include <core/vglobal.h> +#include <core/vselection.h> +#include <core/vfill.h> +#include <core/vgroup.h> +#include <core/vstroke.h> +#include <core/vcursor.h> +#include <render/vpainterfactory.h> +#include <render/vkopainter.h> +#include "vtexttool.h" + + +static void +traceShape( VKoPainter* p, int x, int y, int w, int h ) +{ +	p->newPath(); +	p->moveTo( KoPoint( x + w , y + h ) ); +	p->lineTo( KoPoint( x + w / 3, y + h ) ); +	p->lineTo( KoPoint( x + w / 3, y + h / 3 ) ); +	p->lineTo( KoPoint( x + w , y + h / 3 ) ); +	p->lineTo( KoPoint( x + w , y + h ) ); + +	p->moveTo( KoPoint( x , y ) ); +	p->lineTo( KoPoint( x + ( w / 3 ) * 2, y ) ); +	p->lineTo( KoPoint( x + ( w / 3 ) * 2, y + ( h / 3 ) * 2 ) ); +	p->lineTo( KoPoint( x , y + ( h / 3 ) * 2 ) ); +	p->lineTo( KoPoint( x , y ) ); +} + +ShadowPreview::ShadowPreview( ShadowWidget* parent ) +		: TQWidget( parent ), m_parent( parent ) +{ +	setBackgroundMode( TQt::NoBackground ); +	setMinimumSize( 60, 60 ); + +	connect( this, TQT_SIGNAL( changed( int, int, bool ) ), m_parent, TQT_SLOT( setShadowValues( int, int, bool ) ) ); +} + +ShadowPreview::~ShadowPreview() +{ +} + +void +ShadowPreview::mouseReleaseEvent( TQMouseEvent* e ) +{ +	int dx = e->x() - width() / 2; +	int dy = e->y() - height() / 2; + +	float fd = sqrt( double( dx * dx + dy * dy ) ); +	int a; + +	if( fd == 0 ) +		a = 0; +	else if( dy == 0 && dx < 0 ) +		a = 180; +	else +	{ +		float r = acos( dx / fd ); +		a = int( ( dy <= 0 ? r : VGlobal::twopi - r ) / VGlobal::twopi * 360. ); +	} + +	emit changed( a, ( int ) fd, m_parent->isTranslucent() ); +} + +void +ShadowPreview::paintEvent( TQPaintEvent* ) +{ +	int w = width() - 4; +	int h = height() - 4; +	int d = m_parent->shadowDistance(); +	int a = 360 - m_parent->shadowAngle(); + +	TQPixmap pm( w, h ); +	VKoPainter p( TQT_TQPAINTDEVICE(&pm), w, h ); +	VColor color( VColor::rgb ); + +	VFill fill; +	TDEIconLoader il; +	fill.pattern() = VPattern( il.iconPath( "karbon.png", TDEIcon::Small ) ); +	fill.setType( VFill::patt ); + +	p.newPath(); +	p.moveTo( KoPoint( 0, 0 ) ); +	p.lineTo( KoPoint( 0, h ) ); +	p.lineTo( KoPoint( w, h ) ); +	p.lineTo( KoPoint( w, 0 ) ); +	p.lineTo( KoPoint( 0, 0 ) ); +	p.setBrush( fill ); +	p.fillPath(); + +	color.set( 1., 1., 1. ); +	color.setOpacity( .5 ); +	p.setBrush( VFill( color ) ); +	p.fillPath(); + +	if( m_parent->isTranslucent() ) +	{ +		color.set( 0., 0., 0. ); +		color.setOpacity( .3 ); +	} +	else +	{ +		color.set( .3, .3, .3 ); +		color.setOpacity( 1. ); +	} + +	p.setPen( VStroke( color ) ); +	p.setBrush( VFill( color ) ); + +	traceShape( +		&p, +		int( w / 4 + d * cos( a / 360. * VGlobal::twopi ) ), +		int( h / 4 + d * sin( a / 360. * VGlobal::twopi ) ), int( w / 2 ), int( h / 2 ) ); + +	p.strokePath(); +	p.fillPath(); + +	color.set( 0., 0., 1. ); +	color.setOpacity( 1. ); +	p.setBrush( VFill( color ) ); +	color.set( 0., 0., .5 ); +	p.setPen( VStroke( color ) ); +	traceShape( &p, w / 4, h / 4, w / 2, h / 2 ); +	p.strokePath(); +	p.fillPath(); + +	if( !m_parent->useShadow() ) +	{ +		p.newPath(); +		p.moveTo( KoPoint( 0, 0 ) ); +		p.lineTo( KoPoint( 0, h ) ); +		p.lineTo( KoPoint( w, h ) ); +		p.lineTo( KoPoint( w, 0 ) ); +		p.lineTo( KoPoint( 0, 0 ) ); +		VColor c( colorGroup().background() ); +		c.setOpacity( .8 ); +		p.setBrush( VFill( c ) ); +		p.fillPath(); +	} + +	p.end(); + +	TQPainter painter( this ); +	painter.drawPixmap( 2, 2, pm ); +	painter.setPen( colorGroup().light() ); +	painter.moveTo( 1, height() - 1 ); +	painter.lineTo( 1, 1 ); +	painter.lineTo( width() - 1, 1 ); +	painter.lineTo( width() - 1, height() - 1 ); +	painter.lineTo( 1, height() - 1 ); +	painter.setPen( colorGroup().dark() ); +	painter.moveTo( 0, height() - 1 ); +	painter.lineTo( 0, 0 ); +	painter.lineTo( width() - 1, 0 ); +	painter.moveTo( width() - 2, 2 ); +	painter.lineTo( width() - 2, height() - 2 ); +	painter.lineTo( 2, height() - 2 ); +	painter.setPen( TQt::black ); +	painter.drawLine( width() / 2 - 2, height() / 2, width() / 2 + 2, height() / 2 ); +	painter.drawLine( width() / 2, height() / 2 - 2, width() / 2, height() / 2 + 2 ); +} + +ShadowWidget::ShadowWidget( TQWidget* parent, const char* name, int angle, int distance, bool translucent ) +		: TQGroupBox( parent, name ) +{ +	setTitle( i18n( "Shadow" ) ); +	setSizePolicy( TQSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::Minimum ) ); + +	TQGridLayout* layout = new TQGridLayout( this ); +	layout->addRowSpacing( 0, 12 ); +	layout->setMargin( 3 ); +	layout->setSpacing( 2 ); +	layout->setColStretch( 0, 1 ); +	layout->setColStretch( 1, 0 ); +	layout->setColStretch( 2, 2 ); +	layout->addMultiCellWidget( m_preview = new ShadowPreview( this ), 1, 3, 0, 0 ); +	layout->addWidget( new TQLabel( i18n( "Angle:" ), this ), 1, 1 ); +	layout->addWidget( m_angle = new KIntNumInput( this ), 1, 2 ); +	layout->addWidget( new TQLabel( i18n( "Distance:" ), this ), 2, 1 ); +	layout->addWidget( m_distance = new KIntNumInput( this ), 2, 2 ); +	layout->addWidget( m_useShadow = new TQCheckBox( i18n( "Shadow" ), this ), 3, 1 ); +	layout->addWidget( m_translucent = new TQCheckBox( i18n( "Draw translucent shadow" ), this ), 3, 2 ); +	m_distance->setRange( 1, 37, 1, true ); +	m_angle->setRange( 0, 360, 10, true ); +	m_angle->setValue( angle ); +	m_distance->setValue( distance ); +	m_translucent->setChecked( translucent ); + +	connect( m_angle, TQT_SIGNAL( valueChanged( int ) ), this, TQT_SLOT( updatePreview( int ) ) ); +	connect( m_distance, TQT_SIGNAL( valueChanged( int ) ), this, TQT_SLOT( updatePreview( int ) ) ); +	connect( m_useShadow, TQT_SIGNAL( clicked() ), this, TQT_SLOT( updatePreview() ) ); +	connect( m_translucent, TQT_SIGNAL( clicked() ), this, TQT_SLOT( updatePreview() ) ); + +	updatePreview(); +} + +ShadowWidget::~ShadowWidget() +{ +} + +void +ShadowWidget::setUseShadow( bool use ) +{ +	m_useShadow->setChecked( use ); +	updatePreview(); +} + +bool ShadowWidget::useShadow() +{ +	return m_useShadow->isChecked(); +} + +void +ShadowWidget::setShadowAngle( int angle ) +{ +	m_angle->setValue( angle ); +	m_preview->repaint(); +} + +int +ShadowWidget::shadowAngle() +{ +	return m_angle->value(); +} + +void +ShadowWidget::setShadowDistance( int distance ) +{ +	m_distance->setValue( distance ); +	m_preview->repaint(); +} + +int +ShadowWidget::shadowDistance() +{ +	return m_distance->value(); +} + +void +ShadowWidget::setTranslucent( bool translucent ) +{ +	m_translucent->setChecked( translucent ); +	m_preview->repaint(); +} + +bool ShadowWidget::isTranslucent() +{ +	return m_translucent->isChecked(); +} + +void +ShadowWidget::setShadowValues( int angle, int distance, bool translucent ) +{ +	m_angle->setValue( angle ); +	m_distance->setValue( distance ); +	m_translucent->setChecked( translucent ); +	updatePreview(); +} + +void +ShadowWidget::updatePreview( int ) +{ +	m_preview->repaint(); +} + +void +ShadowWidget::updatePreview() +{ +	m_preview->repaint(); +	bool ok = m_useShadow->isChecked(); +	m_angle->setEnabled( ok ); +	m_distance->setEnabled( ok ); +	m_translucent->setEnabled( ok ); +} + +VTextOptionsWidget::VTextOptionsWidget( VTextTool* tool, TQWidget *parent ) +	: KDialogBase( parent, "", true, i18n( "Text" ), Ok | Cancel ), m_tool( tool ) +{ +	//setSizePolicy( TQSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::Minimum ) ); +	//setFrameStyle( Box | Sunken ); +	TQWidget *base = new TQWidget( this ); +	TQVBoxLayout* mainLayout = new TQVBoxLayout( base ); +	mainLayout->setMargin( 3 ); + +	mainLayout->add( m_tabWidget = new TQTabWidget( base ) ); + +	m_tabWidget->setFont( TQFont( TDEGlobalSettings::generalFont().family() , 8 ) ); + +	TQWidget* textWidget = new TQWidget( m_tabWidget ); + +	TQGridLayout* textLayout = new TQGridLayout( textWidget ); + +	TQStringList list; +	TDEFontChooser::getFontList( list, TDEFontChooser::SmoothScalableFonts ); + +	textLayout->setMargin( 3 ); +	textLayout->setSpacing( 2 ); +	textLayout->addMultiCellWidget( m_fontCombo = new TDEFontCombo( list, textWidget ), 0, 0, 0, 2 ); +	textLayout->addWidget( m_fontSize = new KIntNumInput( textWidget ), 1, 0 ); +	textLayout->addWidget( m_boldCheck = new TQCheckBox( i18n( "Bold" ), textWidget ), 1, 1 ); +	textLayout->addWidget( m_italicCheck = new TQCheckBox( i18n( "Italic" ), textWidget ), 1, 2 ); +	textLayout->addMultiCellWidget( m_textEditor = new TQLineEdit( textWidget ), 2, 2, 0, 2 ); + +	m_tabWidget->addTab( textWidget, i18n( "Text" ) ); + +	TQWidget* posWidget = new TQWidget( m_tabWidget ); +	 +	TQGridLayout* posLayout = new TQGridLayout( posWidget ); +	textLayout->setMargin( 3 ); +	posLayout->setSpacing( 2 ); +	posLayout->addWidget( new TQLabel( i18n( "Alignment:" ), posWidget ), 0, 0 ); +	posLayout->addWidget( m_textAlignment = new TQComboBox( posWidget ), 0, 1 ); +	posLayout->addWidget( new TQLabel( i18n( "Position:" ), posWidget ), 1, 0 ); +	posLayout->addWidget( m_textPosition = new TQComboBox( posWidget ), 1, 1 ); +	posLayout->addWidget( new TQLabel( i18n( "Offset:" ), posWidget ), 2, 0 ); +	posLayout->addWidget( m_textOffset = new KDoubleNumInput( posWidget ), 2, 1 ); +	posLayout->setColStretch( 0, 0 ); +	posLayout->setColStretch( 1, 1 ); +	 +	m_tabWidget->addTab( posWidget, i18n( "Position" ) ); + +	TQWidget* fxWidget = new TQWidget( m_tabWidget ); + +	TQVBoxLayout* fxLayout = new TQVBoxLayout( fxWidget ); + +	fxLayout->setMargin( 3 ); +	fxLayout->setSpacing( 2 ); +	fxLayout->add( m_shadow = new ShadowWidget( fxWidget, 0L, 315, 4, true ) ); + +	TQHBoxLayout* fxLayout2 = new TQHBoxLayout( fxLayout ); + +	fxLayout2->setSpacing( 2 ); +	fxLayout2->addWidget( m_editBasePath = new TQPushButton( i18n( "Edit Base Path" ), fxWidget ) ); +	fxLayout2->addWidget( m_convertToShapes = new TQPushButton( i18n( "Convert to Shapes" ), fxWidget ) ); + +	m_tabWidget->addTab( fxWidget, i18n( "Effects" ) ); + +	m_fontCombo->setCurrentText( TDEGlobalSettings::generalFont().family() ); + +	m_fontSize->setValue( 12 ); +	m_fontSize->setSuffix( " pt" ); + +	m_textEditor->setMinimumHeight( 100 ); +	m_textEditor->setText( i18n( "New text") ); +	m_textEditor->selectAll(); + +	m_convertToShapes->setEnabled( true ); + +	m_textAlignment->insertItem( i18n( "Horizontal alignment", "Left") ); +	m_textAlignment->insertItem( i18n( "Horizontal alignment", "Center") ); +	m_textAlignment->insertItem( i18n( "Horizontal alignment", "Right") ); + +	m_textPosition->insertItem( i18n( "Vertical alignment", "Above") ); +	m_textPosition->insertItem( i18n( "Vertical alignment", "On") ); +	m_textPosition->insertItem( i18n( "Vertical alignment", "Under") ); + +	m_textOffset->setRange( 0.0, 100.0, 1.0, true ); + +	connect( m_fontCombo, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( valueChanged( int ) ) ); +	connect( m_boldCheck, TQT_SIGNAL( stateChanged( int ) ), this, TQT_SLOT( valueChanged( int ) ) ); +	connect( m_italicCheck, TQT_SIGNAL( stateChanged( int ) ), this, TQT_SLOT( valueChanged( int ) ) ); +	connect( m_fontSize, TQT_SIGNAL( valueChanged( int ) ), this, TQT_SLOT( valueChanged( int ) ) ); +	connect( m_textPosition, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( valueChanged( int ) ) ); +	connect( m_textAlignment, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( valueChanged( int ) ) ); +	connect( m_textOffset, TQT_SIGNAL( valueChanged( double ) ), this, TQT_SLOT( valueChanged( double ) ) ); +	connect( m_textEditor, TQT_SIGNAL( returnPressed() ), this, TQT_SLOT( accept() ) ); +	connect( m_textEditor, TQT_SIGNAL( textChanged( const TQString& ) ), this, TQT_SLOT( textChanged( const TQString& ) ) ); +	connect( m_editBasePath, TQT_SIGNAL( clicked() ), this, TQT_SLOT( editBasePath() ) ); +	connect( m_convertToShapes, TQT_SIGNAL( clicked() ), this, TQT_SLOT( convertToShapes() ) ); +	connect( this, TQT_SIGNAL( cancelClicked() ), this, TQT_SLOT( cancel() ) ); + +	setMainWidget( base ); +	setFixedSize( baseSize() ); +} + +VTextOptionsWidget::~VTextOptionsWidget() +{ +} + +void +VTextOptionsWidget::valueChanged( int ) +{ +	m_fontCombo->setBold( m_boldCheck->isChecked() ); +	m_fontCombo->setItalic( m_italicCheck->isChecked() ); + +	m_textEditor->setFont( TQFont( m_fontCombo->currentText(), m_fontSize->value(), ( m_boldCheck->isChecked() ? 75 : 50 ), m_italicCheck->isChecked() ) ); + +	if( m_tool && isVisible() )  +		m_tool->textChanged(); +} + +void +VTextOptionsWidget::valueChanged( double ) +{ +	if( m_tool && isVisible() )  +		m_tool->textChanged(); +} + +void +VTextOptionsWidget::accept() +{ +	if( m_tool ) +		m_tool->accept(); +	hide(); +} + +void +VTextOptionsWidget::cancel() +{ +	if( m_tool ) +		m_tool->cancel(); +} + +void +VTextOptionsWidget::textChanged( const TQString& ) +{ +	if( m_tool && isVisible() ) +		m_tool->textChanged(); +} + +void +VTextOptionsWidget::editBasePath() +{ +	if( m_tool ) +		m_tool->editBasePath(); +} + +void +VTextOptionsWidget::convertToShapes() +{ +	if( m_tool ) +		m_tool->convertToShapes(); +} + +void +VTextOptionsWidget::setFont( const TQFont& font ) +{ +	m_fontCombo->setCurrentText( font.family() ); + +	m_boldCheck->setChecked( font.bold() ); + +	m_italicCheck->setChecked( font.italic() ); + +	m_fontSize->setValue( font.pointSize() ); + +	m_fontCombo->setBold( m_boldCheck->isChecked() ); +	m_fontCombo->setItalic( m_italicCheck->isChecked() ); + +	m_textEditor->setFont( TQFont( m_fontCombo->currentText(), m_fontSize->value(), ( m_boldCheck->isChecked() ? 75 : 50 ), m_italicCheck->isChecked() ) ); +} + +TQFont VTextOptionsWidget::font() +{ +	return TQFont( m_fontCombo->currentText(), m_fontSize->value(), ( m_boldCheck->isChecked() ? 75 : 50 ), m_italicCheck->isChecked() ); +} + +void +VTextOptionsWidget::setText( const TQString& text ) +{ +	m_textEditor->setText( text ); +} + +TQString VTextOptionsWidget::text() +{ +	return m_textEditor->text(); +} + +void +VTextOptionsWidget::setPosition( VText::Position position ) +{ +	m_textPosition->setCurrentItem( position ); +} + +VText::Position VTextOptionsWidget::position() +{ +	return ( VText::Position ) m_textPosition->currentItem(); +} + +void +VTextOptionsWidget::setAlignment( VText::Alignment alignment ) +{ +	m_textAlignment->setCurrentItem( alignment ); +} + +VText::Alignment VTextOptionsWidget::alignment() +{ +	return ( VText::Alignment ) m_textAlignment->currentItem(); +} + +void  +VTextOptionsWidget::setOffset( double offset ) +{ +	if( offset < 0.0 ) offset = 0.0; +	if( offset > 100.0 ) offset = 100.0; + +	m_textOffset->setValue( offset ); +} +double  +VTextOptionsWidget::offset() +{ +	return m_textOffset->value(); +} + +void +VTextOptionsWidget::setUseShadow( bool state ) +{ +	m_shadow->setUseShadow( state ); +} + +bool VTextOptionsWidget::useShadow() +{ +	return m_shadow->useShadow(); +} + +void +VTextOptionsWidget::setShadow( int angle, int distance, bool translucent ) +{ +	m_shadow->setShadowValues( angle, distance, translucent ); +} + +bool VTextOptionsWidget::translucentShadow() +{ +	return m_shadow->isTranslucent(); +} + +int +VTextOptionsWidget::shadowAngle() +{ +	return m_shadow->shadowAngle(); +} + +int +VTextOptionsWidget::shadowDistance() +{ +	return m_shadow->shadowDistance(); +} + +void  +VTextOptionsWidget::initialize( VObject &text ) +{ +	if( m_tool ) +		m_tool->visit( text ); +} + +VTextTool::VTextTool( KarbonView *view ) +		: VTool( view, "tool_text" ) +{ +	m_optionsWidget = new VTextOptionsWidget( this, 0L ); +	m_text = 0L; +	m_editedText = 0L; +	registerTool( this ); +	m_cursor = new TQCursor( VCursor::createCursor( VCursor::CrossHair ) ); +} + +VTextTool::~VTextTool() +{ +	delete m_optionsWidget; +	delete m_editedText; +	delete m_cursor; +} + +TQString VTextTool::contextHelp() +{ +	TQString s = i18n( "<qt><b>Text Tool</b><br>" ); +	s += i18n("<i>Click</i> on document to place horizontal text.<br>" ); +	s += i18n("<i>Click and drag</i> in document to place directional text.<br>" ); +	s += i18n("<i>Click</i> on a selected path object to place text along its outline.<br>" ); +	s += i18n("<i>Click</i> on a selected text object to change it.<br></qt>" ); + +	return s; +} + +void +VTextTool::activate() +{ +	VTool::activate(); +	view()->statusMessage()->setText( i18n( "Text Tool" ) ); +	view()->setCursor( *m_cursor ); + +	m_creating = true; +	m_text = 0L; +	delete m_editedText; +	m_editedText = 0L; +} + +void +VTextTool::deactivate() +{ +} + +void +VTextTool::draw( VPainter* painter ) +{ +	if( m_editedText ) +		m_editedText->draw( painter, &m_editedText->boundingBox() ); +} + +void +VTextTool::drawPathCreation() +{ +	VPainter * painter = view()->painterFactory()->editpainter(); + +	painter->setZoomFactor( view()->zoom() ); + +	painter->setRasterOp( TQt::NotROP ); +	painter->newPath(); +	painter->setPen( TQt::DotLine ); +	painter->setBrush( TQt::NoBrush ); + +	painter->moveTo( first() ); +	painter->lineTo( m_last ); +	painter->strokePath(); +} + +void +VTextTool::drawEditedText() +{ +	if( m_editedText )  +		view()->repaintAll( m_editedText->boundingBox() ); +} + +void +VTextTool::mouseButtonPress() +{ +	m_last = first(); +	drawPathCreation(); +	m_stepwise = false; +} + +void +VTextTool::mouseButtonRelease() +{ +	if( ! view() )  +		return; + +	VSelection* selection = view()->part()->document().selection(); +	VObject* selObj = selection->objects().getFirst(); + +	// initialize dialog with single selected object +	if( selection->objects().count() == 1 && selObj->boundingBox().contains( last() ) ) +		m_optionsWidget->initialize( *selObj ); +	else  +	{ +		// use a default horizontal path when just clicking +		VSubpath path( 0L ); +		path.moveTo( first() ); +		path.lineTo( KoPoint( first().x()+10, first().y() ) ); +	 +		if( ! createText( path ) ) +			return; +	} + +	if( dynamic_cast<VText*>( selObj ) && selObj->boundingBox().contains( last() ) ) +		m_optionsWidget->setCaption( i18n( "Change Text") ); +	else  +		m_optionsWidget->setCaption( i18n( "Insert Text") ); + +	m_optionsWidget->show(); +} + +void +VTextTool::mouseDrag() +{ +	drawPathCreation(); + +	if( m_stepwise && shiftPressed() ) +	{ +		KoPoint act = last(); +		KoPoint dst = act - first(); +  +		double angle = atan2( dst.y(), dst.x() ); +		if( angle < 0 ) +			angle += VGlobal::twopi; + +		// calculate previuos and next modulo 45 degree step  +		double prevStep = angle - fmod( angle, VGlobal::pi_2 / 2.0f ); +		double nextStep = prevStep + VGlobal::pi_2 / 2.0f; +		// calculate distance between first and last point +		double length = sqrt( dst.x()*dst.x() + dst.y()*dst.y() ); + +		// use nearest step +		if( angle - prevStep < nextStep - angle ) +		{ +			m_last.setX( first().x() + length * cos( prevStep ) ); +			m_last.setY( first().y() + length * sin( prevStep ) ); +		} +		else +		{ +			m_last.setX( first().x() + length * cos( nextStep ) ); +			m_last.setY( first().y() + length * sin( nextStep ) ); +		} +	} +	else +		m_last = last(); + +	drawPathCreation(); +} + +void +VTextTool::mouseDragRelease() +{ +	drawPathCreation(); + +	if( m_creating && m_editedText ) +	{ +		drawEditedText(); +		delete m_editedText; +		m_editedText = 0L; +	} + +	// use dragged path to create text along +	VSubpath path( 0L ); +	path.moveTo( first() ); +	path.lineTo( m_last ); + +	if( createText( path ) ) +	{ +		m_optionsWidget->setCaption( i18n( "Insert Text") ); +		m_optionsWidget->show(); +	} +} + +bool +VTextTool::createText( VSubpath &path ) +{ +	// no original text is used +	m_text = 0L; +	delete m_editedText; + +	m_editedText = new VText( m_optionsWidget->font(), path, m_optionsWidget->position(), m_optionsWidget->alignment(), m_optionsWidget->text() ); +	 +	if( ! m_editedText )  +		return false; + +	m_editedText->setState( VObject::edit ); + +#ifdef HAVE_KARBONTEXT +	m_editedText->traceText(); +#endif + +	// yes, we are creating a new text object +	m_creating = true; + +	return true; +} + +void +VTextTool::textChanged() +{ +	if( !m_editedText ) +		return; + +	if( !m_creating && m_text && m_text->state() != VObject::hidden ) +	{ +		// hide the original text if we are changing it +		m_text->setState( VObject::hidden ); +		view()->repaintAll( m_text->boundingBox() ); +	} +	else +		view()->repaintAll( m_editedText->boundingBox() ); + +	m_editedText->setText( m_optionsWidget->text() ); +	m_editedText->setFont( m_optionsWidget->font() ); +	m_editedText->setPosition( m_optionsWidget->position() ); +	m_editedText->setAlignment( m_optionsWidget->alignment() ); +	m_editedText->setOffset( 0.01 * m_optionsWidget->offset()  ); +#ifdef HAVE_KARBONTEXT +	m_editedText->traceText(); +#endif + +	drawEditedText(); +} + +void +VTextTool::accept() +{ +	if( !m_editedText ) +		return; + +	VTextCmd* cmd; + +	if( !m_creating ) +	{ +		cmd = new VTextCmd( +				  &view()->part()->document(), +				  i18n( "Change Text" ), +				  m_text, +				  m_editedText->font(), +				  m_editedText->basePath(), +				  m_editedText->position(), +				  m_editedText->alignment(), +				  m_editedText->offset(), +				  m_editedText->text(), +				  m_optionsWidget->useShadow(), +				  m_optionsWidget->shadowAngle(), +				  m_optionsWidget->shadowDistance(), +				  m_optionsWidget->translucentShadow() ); +	} +	else +	{ +		VText *newText = m_editedText->clone(); +		newText->setUseShadow( m_optionsWidget->useShadow() ); +		newText->setShadow( m_optionsWidget->shadowAngle(), m_optionsWidget->shadowDistance(), m_optionsWidget->translucentShadow() ); + +		cmd = new VTextCmd( +				  &view()->part()->document(), +				  i18n( "Insert Text" ), +				  newText ); + +		delete m_editedText; +		m_editedText = 0L; +	} + +	view()->part()->addCommand( cmd, true ); +	view()->part()->repaintAllViews(); +	m_creating = false; +} + +void +VTextTool::cancel() +{ +	if( m_text ) +	{ +		// show original text if we canceled changing it +		m_text->setState( VObject::selected ); +		view()->repaintAll( m_text->boundingBox() ); +	} +	else +		drawPathCreation(); + +	delete m_editedText; +	m_editedText = 0L; +} + +void +VTextTool::editBasePath() +{ +	if( !m_editedText ) +		return; + +	view()->part()->document().selection()->clear(); +	view()->part()->document().selection()->append( &m_editedText->basePath() ); +	view()->part()->repaintAllViews(); +} + +void +VTextTool::convertToShapes() +{ +	if( !m_text ) +		return; + +	VTextToCompositeCmd* cmd = new VTextToCompositeCmd( +								   &view()->part()->document(), +								   i18n( "Text Conversion" ), +								   m_text ); + +	view()->part()->addCommand( cmd, true ); + +	m_creating = false; + +	delete m_editedText; + +	m_text = 0L; +	m_editedText = 0L; +} + +void +VTextTool::visitVPath( VPath& composite ) +{ +	if( composite.paths().count() == 0 ) +		return; + +	if( createText( *composite.paths().getFirst() ) ) +		drawEditedText(); +} + +void +VTextTool::visitVSubpath( VSubpath& path ) +{ +	if( createText( path ) ) +		drawEditedText(); +} + +void +VTextTool::visitVText( VText& text ) +{ +	m_text = &text; +	delete m_editedText; +	m_editedText = text.clone(); + +	m_optionsWidget->setFont( text.font() ); +	m_optionsWidget->setText( text.text() ); +	m_optionsWidget->setPosition( text.position() ); +	m_optionsWidget->setAlignment( text.alignment() ); +	m_optionsWidget->setOffset( text.offset() * 100.0 ); +	m_optionsWidget->setUseShadow( text.useShadow() ); +	m_optionsWidget->setShadow( text.shadowAngle(), text.shadowDistance(), text.translucentShadow() ); +	m_creating = false; +	m_text->setState( VObject::hidden ); +	m_editedText->setState( VObject::edit ); +} + +VTextTool::VTextCmd::VTextCmd( VDocument* doc, const TQString& name, VText* text ) +		: VCommand( doc, name, "14_text" ), m_text( text ) +{ +	m_textModifications = 0L; + +	m_executed = false; +} + +VTextTool::VTextCmd::VTextCmd( VDocument* doc, const TQString& name, VText* text, +							   const TQFont &newFont, const VSubpath& newBasePath, VText::Position newPosition, VText::Alignment newAlignment, double newOffset, const TQString& newText, +							   bool newUseShadow, int newShadowAngle, int newShadowDistance, bool newTranslucentShadow ) +		: VCommand( doc, name, "14_text" ), m_text( text ) +{ +	m_textModifications = new VTextModifPrivate(); +	m_textModifications->newFont = newFont; +	m_textModifications->oldFont = text->font(); +	m_textModifications->newBasePath = newBasePath; +	m_textModifications->oldBasePath = text->basePath(); +	m_textModifications->newPosition = newPosition; +	m_textModifications->oldPosition = text->position(); +	m_textModifications->newAlignment = newAlignment; +	m_textModifications->oldAlignment = text->alignment(); +	m_textModifications->newOffset = newOffset; +	m_textModifications->oldOffset = text->offset(); +	m_textModifications->newText = newText; +	m_textModifications->oldText = text->text(); +	m_textModifications->newUseShadow = newUseShadow; +	m_textModifications->oldUseShadow = text->useShadow(); +	m_textModifications->newShadowAngle = newShadowAngle; +	m_textModifications->oldShadowAngle = text->shadowAngle(); +	m_textModifications->newShadowDistance = newShadowDistance; +	m_textModifications->oldShadowDistance = text->shadowDistance(); +	m_textModifications->newTranslucentShadow = newTranslucentShadow; +	m_textModifications->oldTranslucentShadow = text->translucentShadow(); + +	m_executed = false; +} + +VTextTool::VTextCmd::~VTextCmd() +{ +	delete m_textModifications; +} + +void +VTextTool::VTextCmd::execute() +{ +	if( !m_text ) +		return; + +	if( !m_textModifications ) +	{ +		if( m_text->state() == VObject::deleted ) +			m_text->setState( VObject::normal ); +		else +		{ +			m_text->setState( VObject::normal ); +			document()->append( m_text ); +			document()->selection()->clear(); +			document()->selection()->append( m_text ); +		} +	} +	else +	{ +		m_text->setFont( m_textModifications->newFont ); +		m_text->setBasePath( m_textModifications->newBasePath ); +		m_text->setPosition( m_textModifications->newPosition ); +		m_text->setAlignment( m_textModifications->newAlignment ); +		m_text->setOffset( m_textModifications->newOffset ); +		m_text->setText( m_textModifications->newText ); +		m_text->setUseShadow( m_textModifications->newUseShadow ); +		m_text->setShadow( m_textModifications->newShadowAngle, m_textModifications->newShadowDistance, m_textModifications->newTranslucentShadow ); + +#ifdef HAVE_KARBONTEXT +		m_text->traceText(); +#endif + +		m_text->setState( VObject::normal ); +	} + +	m_executed = true; + +	setSuccess( true ); +} + +void +VTextTool::VTextCmd::unexecute() +{ +	if( !m_text ) +		return; + +	if( !m_textModifications ) +	{ +		document()->selection()->take( *m_text ); +		m_text->setState( VObject::deleted ); +	} +	else +	{ +		m_text->setFont( m_textModifications->oldFont ); +		m_text->setBasePath( m_textModifications->oldBasePath ); +		m_text->setPosition( m_textModifications->oldPosition ); +		m_text->setAlignment( m_textModifications->oldAlignment ); +		m_text->setOffset( m_textModifications->oldOffset ); +		m_text->setText( m_textModifications->oldText ); +		m_text->setUseShadow( m_textModifications->oldUseShadow ); +		m_text->setShadow( m_textModifications->oldShadowAngle, m_textModifications->oldShadowDistance, m_textModifications->oldTranslucentShadow ); + +#ifdef HAVE_KARBONTEXT +		m_text->traceText(); +#endif + +		m_text->setState( VObject::normal ); +	} + +	m_executed = false; + +	setSuccess( false ); +} + +VTextTool::VTextToCompositeCmd::VTextToCompositeCmd( VDocument* doc, const TQString& name, VText* text ) +		: VCommand( doc, name, "14_text" ), m_text( text ), m_group( 0L ), m_executed( false ) +{ +} + +VTextTool::VTextToCompositeCmd::~VTextToCompositeCmd() +{ +} + +void +VTextTool::VTextToCompositeCmd::execute() +{ +	if( !m_text ) +		return; + +	if( !m_group ) +	{ +		m_group = m_text->toVGroup(); +		document()->append( m_group ); +	} + +	m_text->setState( VObject::deleted ); +	m_group->setState( VObject::normal ); +	document()->selection()->clear(); +	document()->selection()->append( m_group ); + +	m_executed = true; + +	setSuccess( true ); +} + +void +VTextTool::VTextToCompositeCmd::unexecute() +{ +	if( !m_text ) +		return; + +	m_text->setState( VObject::normal ); + +	document()->selection()->take( *m_group ); + +	m_group->setState( VObject::deleted ); + +	m_executed = false; + +	setSuccess( false ); +} + +bool +VTextTool::showDialog() const +{ +	VSelection* selection = view()->part()->document().selection(); + +	// initialize dialog with single selected object +	if( selection->objects().count() == 1 ) +		m_optionsWidget->initialize( *selection->objects().getFirst()); +	else  +		return false; + +	if( dynamic_cast<VText*>( selection->objects().getFirst() ) ) +		m_optionsWidget->setCaption(i18n( "Change Text") ); +	else  +		m_optionsWidget->setCaption(i18n( "Insert Text") ); + +	m_optionsWidget->show(); +	return true; +} + +void  +VTextTool::mouseDragShiftPressed() +{ +	m_stepwise = true; +	mouseDrag(); +} + +void  +VTextTool::mouseDragShiftReleased() +{ +	m_stepwise = false; +	mouseDrag(); +} + +void +VTextTool::setup( TDEActionCollection *collection ) +{ +	m_action = static_cast<TDERadioAction *>(collection -> action( name() ) ); + +	if( m_action == 0 ) +	{ +		m_action = new TDERadioAction( i18n( "Text Tool" ), "14_text", TQt::SHIFT+TQt::Key_T, this, TQT_SLOT( activate() ), collection, name() ); +		m_action->setToolTip( i18n( "Text Tool" ) ); +		m_action->setExclusiveGroup( "misc" ); +		//m_ownAction = true; +	} +} + +#include "vtexttool.moc" +  | 
