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 : VCommand( doc, i18n( "Whirl Pinch" ) )
00122 {
00123 m_selection = document()->selection()->clone();
00124
00125 m_angle = angle;
00126 m_pinch = pinch;
00127 m_radius = radius;
00128 m_center = m_selection->boundingBox().center();
00129 }
00130
00131 VWhirlPinchCmd::~VWhirlPinchCmd()
00132 {
00133 delete( m_selection );
00134 }
00135
00136 void
00137 VWhirlPinchCmd::execute()
00138 {
00139 VObjectListIterator itr( m_selection->objects() );
00140 for ( ; itr.current() ; ++itr )
00141 visit( *itr.current() );
00142 }
00143
00144 void
00145 VWhirlPinchCmd::unexecute()
00146 {
00147 }
00148
00149 void
00150 VWhirlPinchCmd::visitVPath( VPath& composite )
00151 {
00152
00153
00154
00155
00156 VVisitor::visitVPath( composite );
00157 }
00158
00159 void
00160 VWhirlPinchCmd::visitVSubpath( VSubpath& path )
00161 {
00162 QWMatrix m;
00163 KoPoint delta;
00164 double dist;
00165
00166 path.first();
00167
00168 while( path.current() )
00169 {
00170
00171
00172
00173
00174
00175
00176 delta = path.current()->knot() - m_center;
00177 dist = sqrt( delta.x() * delta.x() + delta.y() * delta.y() );
00178
00179 if( dist < m_radius )
00180 {
00181 m.reset();
00182
00183 dist /= m_radius;
00184
00185
00186 m.translate( m_center.x(), m_center.y() );
00187 m.scale(
00188 pow( sin( VGlobal::pi_2 * dist ), -m_pinch ),
00189 pow( sin( VGlobal::pi_2 * dist ), -m_pinch ) );
00190
00191
00192 m.rotate( m_angle * ( 1.0 - dist ) * ( 1.0 - dist ) );
00193 m.translate( -m_center.x(), -m_center.y() );
00194
00195 path.current()->setKnot( path.current()->knot().transform( m ) );
00196 }
00197
00198 if( path.current()->isCurve() )
00199 {
00200 delta = path.current()->point( 0 ) - m_center;
00201 dist = sqrt( delta.x() * delta.x() + delta.y() * delta.y() );
00202
00203 if( dist < m_radius )
00204 {
00205 m.reset();
00206
00207 dist /= m_radius;
00208
00209
00210 m.translate( m_center.x(), m_center.y() );
00211 m.scale(
00212 pow( sin( VGlobal::pi_2 * dist ), -m_pinch ),
00213 pow( sin( VGlobal::pi_2 * dist ), -m_pinch ) );
00214
00215
00216 m.rotate( m_angle * ( 1.0 - dist ) * ( 1.0 - dist ) );
00217 m.translate( -m_center.x(), -m_center.y() );
00218
00219 path.current()->setPoint( 0, path.current()->point(0).transform( m ) );
00220 }
00221
00222
00223 delta = path.current()->point( 1 ) - m_center;
00224 dist = sqrt( delta.x() * delta.x() + delta.y() * delta.y() );
00225
00226 if( dist < m_radius )
00227 {
00228 m.reset();
00229
00230 dist /= m_radius;
00231
00232
00233 m.translate( m_center.x(), m_center.y() );
00234 m.scale(
00235 pow( sin( VGlobal::pi_2 * dist ), -m_pinch ),
00236 pow( sin( VGlobal::pi_2 * dist ), -m_pinch ) );
00237
00238
00239 m.rotate( m_angle * ( 1.0 - dist ) * ( 1.0 - dist ) );
00240 m.translate( -m_center.x(), -m_center.y() );
00241
00242 path.current()->setPoint( 1, path.current()->point(1).transform( m ) );
00243 }
00244 }
00245
00246
00247 if( !success() )
00248 setSuccess();
00249
00250
00251 path.next();
00252 }
00253
00254
00255 path.invalidateBoundingBox();
00256 }
00257
00258 #include "whirlpinchplugin.moc"
00259