karbon

whirlpinchplugin.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2002, The Karbon Developers
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
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     // add input fields:
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     // signals and slots:
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     // first subdivide:
00137 //  VInsertKnots insertKnots( 2 );
00138 //  insertKnots.visit( composite );
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 // TODO: selfmade this function since it's gone:
00157 //      path.current()->convertToCurve();
00158 
00159         // Apply effect to each segment node.
00160         for( int i = 0; i < curr->degree(); ++i )
00161         {
00162             // calculate distance from whirl center to actual point
00163             delta = curr->point( i ) - m_center;
00164             dist = sqrt( delta.x() * delta.x() + delta.y() * delta.y() );
00165     
00166             // check if point is inside the whirl radius
00167             if( dist < m_radius )
00168             {
00169                 m.reset();
00170     
00171                 // normalize distance to whirl radius
00172                 dist /= m_radius;
00173     
00174                 double scale = pow( sin( VGlobal::pi_2 * dist ), -m_pinch );
00175                 // pinch:
00176                 m.translate( m_center.x(), m_center.y() );
00177                 m.scale( scale, scale );
00178     
00179                 // whirl:
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     // Invalidate bounding box once.
00195     path.invalidateBoundingBox();
00196 }
00197 
00198 #include "whirlpinchplugin.moc"
00199 
KDE Home | KDE Accessibility Home | Description of Access Keys