00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <core/vselection.h>
00021 #include "whirlpinchplugin.h"
00022 #include <karbon_view.h>
00023 #include <karbon_part.h>
00024 #include <kgenericfactory.h>
00025 #include <core/vdocument.h>
00026 #include <core/vcomposite.h>
00027 #include <core/vpath.h>
00028 #include <core/vsegment.h>
00029 #include <core/vglobal.h>
00030
00031 #include <kdebug.h>
00032
00033 #include <qgroupbox.h>
00034 #include <qlabel.h>
00035
00036 #include <knuminput.h>
00037
00038 typedef KGenericFactory<WhirlPinchPlugin, KarbonView> WhirlPinchPluginFactory;
00039 K_EXPORT_COMPONENT_FACTORY( karbon_whirlpinchplugin, WhirlPinchPluginFactory( "karbonwhirlpinchplugin" ) )
00040
00041 WhirlPinchPlugin::WhirlPinchPlugin( KarbonView *parent, const char* name, const QStringList & ) : Plugin( parent, name )
00042 {
00043 new KAction(
00044 i18n( "&Whirl/Pinch..." ), "14_whirl", 0, this,
00045 SLOT( slotWhirlPinch() ), actionCollection(), "path_whirlpinch" );
00046
00047 m_whirlPinchDlg = new VWhirlPinchDlg();
00048 m_whirlPinchDlg->setAngle( 20.0 );
00049 m_whirlPinchDlg->setPinch( 0.0 );
00050 m_whirlPinchDlg->setRadius( 100.0 );
00051 }
00052
00053 void
00054 WhirlPinchPlugin::slotWhirlPinch()
00055 {
00056 KarbonPart *part = ((KarbonView *)parent())->part();
00057 if( part && m_whirlPinchDlg->exec() )
00058 part->addCommand( new VWhirlPinchCmd( &part->document(), m_whirlPinchDlg->angle(), m_whirlPinchDlg->pinch(), m_whirlPinchDlg->radius() ), true );
00059 }
00060
00061 VWhirlPinchDlg::VWhirlPinchDlg( QWidget* parent, const char* name )
00062 : KDialogBase( parent, name, true, i18n( "Whirl Pinch" ), Ok | Cancel )
00063 {
00064
00065 QGroupBox* group = new QGroupBox( 2, Qt::Horizontal, i18n( "Properties" ), this );
00066
00067 new QLabel( i18n( "Angle:" ), group );
00068 m_angle = new KDoubleNumInput( group );
00069 new QLabel( i18n( "Pinch:" ), group );
00070 m_pinch = new KDoubleNumInput( group );
00071 new QLabel( i18n( "Radius:" ), group );
00072 m_radius = new KDoubleNumInput( group );
00073 group->setMinimumWidth( 300 );
00074
00075
00076 connect( this, SIGNAL( okClicked() ), this, SLOT( accept() ) );
00077 connect( this, SIGNAL( cancelClicked() ), this, SLOT( reject() ) );
00078
00079 setMainWidget( group );
00080 setFixedSize( baseSize() );
00081 }
00082
00083 double
00084 VWhirlPinchDlg::angle() const
00085 {
00086 return m_angle->value();
00087 }
00088
00089 double
00090 VWhirlPinchDlg::pinch() const
00091 {
00092 return m_pinch->value();
00093 }
00094
00095 double
00096 VWhirlPinchDlg::radius() const
00097 {
00098 return m_radius->value();
00099 }
00100
00101 void
00102 VWhirlPinchDlg::setAngle( double value )
00103 {
00104 m_angle->setValue( value);
00105 }
00106
00107 void
00108 VWhirlPinchDlg::setPinch( double value )
00109 {
00110 m_pinch->setValue(value);
00111 }
00112
00113 void
00114 VWhirlPinchDlg::setRadius( double value )
00115 {
00116 m_radius->setValue( value);
00117 }
00118
00119 VWhirlPinchCmd::VWhirlPinchCmd( VDocument* doc,
00120 double angle, double pinch, double radius )
00121 : VReplacingCmd( doc, i18n( "Whirl Pinch" ) )
00122 {
00123 m_angle = angle;
00124 m_pinch = pinch;
00125 m_radius = radius;
00126 m_center = document()->selection()->boundingBox().center();
00127 }
00128
00129 VWhirlPinchCmd::~VWhirlPinchCmd()
00130 {
00131 }
00132
00133 void
00134 VWhirlPinchCmd::visitVPath( VPath& composite )
00135 {
00136
00137
00138
00139
00140 VVisitor::visitVPath( composite );
00141 }
00142
00143 void
00144 VWhirlPinchCmd::visitVSubpath( VSubpath& path )
00145 {
00146 QWMatrix m;
00147 KoPoint delta;
00148 double dist;
00149
00150 path.first();
00151
00152 VSegment *curr = path.current();
00153
00154 while( curr )
00155 {
00156
00157
00158
00159
00160 for( int i = 0; i < curr->degree(); ++i )
00161 {
00162
00163 delta = curr->point( i ) - m_center;
00164 dist = sqrt( delta.x() * delta.x() + delta.y() * delta.y() );
00165
00166
00167 if( dist < m_radius )
00168 {
00169 m.reset();
00170
00171
00172 dist /= m_radius;
00173
00174 double scale = pow( sin( VGlobal::pi_2 * dist ), -m_pinch );
00175
00176 m.translate( m_center.x(), m_center.y() );
00177 m.scale( scale, scale );
00178
00179
00180 m.rotate( m_angle * ( 1.0 - dist ) * ( 1.0 - dist ) );
00181 m.translate( -m_center.x(), -m_center.y() );
00182
00183 path.current()->setPoint( i, curr->point( i ).transform( m ) );
00184 }
00185
00186 }
00187
00188 if( !success() )
00189 setSuccess();
00190
00191 curr = path.next();
00192 }
00193
00194
00195 path.invalidateBoundingBox();
00196 }
00197
00198 #include "whirlpinchplugin.moc"
00199