You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/karbon/plugins/whirlpinch/whirlpinchplugin.cc

200 lines
4.9 KiB

/* This file is part of the KDE project
Copyright (C) 2002, 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 <core/vselection.h>
#include "whirlpinchplugin.h"
#include <karbon_view.h>
#include <karbon_part.h>
#include <kgenericfactory.h>
#include <core/vdocument.h>
#include <core/vcomposite.h>
#include <core/vpath.h>
#include <core/vsegment.h>
#include <core/vglobal.h>
#include <kdebug.h>
#include <tqgroupbox.h>
#include <tqlabel.h>
#include <knuminput.h>
typedef KGenericFactory<WhirlPinchPlugin, KarbonView> WhirlPinchPluginFactory;
K_EXPORT_COMPONENT_FACTORY( karbon_whirlpinchplugin, WhirlPinchPluginFactory( "karbonwhirlpinchplugin" ) )
WhirlPinchPlugin::WhirlPinchPlugin( KarbonView *parent, const char* name, const TQStringList & ) : Plugin( TQT_TQOBJECT(parent), name )
{
new TDEAction(
i18n( "&Whirl/Pinch..." ), "14_whirl", 0, this,
TQT_SLOT( slotWhirlPinch() ), actionCollection(), "path_whirlpinch" );
m_whirlPinchDlg = new VWhirlPinchDlg();
m_whirlPinchDlg->setAngle( 20.0 );
m_whirlPinchDlg->setPinch( 0.0 );
m_whirlPinchDlg->setRadius( 100.0 );
}
void
WhirlPinchPlugin::slotWhirlPinch()
{
KarbonPart *part = ((KarbonView *)parent())->part();
if( part && m_whirlPinchDlg->exec() )
part->addCommand( new VWhirlPinchCmd( &part->document(), m_whirlPinchDlg->angle(), m_whirlPinchDlg->pinch(), m_whirlPinchDlg->radius() ), true );
}
VWhirlPinchDlg::VWhirlPinchDlg( TQWidget* parent, const char* name )
: KDialogBase( parent, name, true, i18n( "Whirl Pinch" ), Ok | Cancel )
{
// add input fields:
TQGroupBox* group = new TQGroupBox( 2, Qt::Horizontal, i18n( "Properties" ), this );
new TQLabel( i18n( "Angle:" ), group );
m_angle = new KDoubleNumInput( group );
new TQLabel( i18n( "Pinch:" ), group );
m_pinch = new KDoubleNumInput( group );
new TQLabel( i18n( "Radius:" ), group );
m_radius = new KDoubleNumInput( group );
group->setMinimumWidth( 300 );
// signals and slots:
connect( this, TQT_SIGNAL( okClicked() ), this, TQT_SLOT( accept() ) );
connect( this, TQT_SIGNAL( cancelClicked() ), this, TQT_SLOT( reject() ) );
setMainWidget( group );
setFixedSize( baseSize() );
}
double
VWhirlPinchDlg::angle() const
{
return m_angle->value();
}
double
VWhirlPinchDlg::pinch() const
{
return m_pinch->value();
}
double
VWhirlPinchDlg::radius() const
{
return m_radius->value();
}
void
VWhirlPinchDlg::setAngle( double value )
{
m_angle->setValue( value);
}
void
VWhirlPinchDlg::setPinch( double value )
{
m_pinch->setValue(value);
}
void
VWhirlPinchDlg::setRadius( double value )
{
m_radius->setValue( value);
}
VWhirlPinchCmd::VWhirlPinchCmd( VDocument* doc,
double angle, double pinch, double radius )
: VReplacingCmd( doc, i18n( "Whirl Pinch" ) )
{
m_angle = angle;
m_pinch = pinch;
m_radius = radius;
m_center = document()->selection()->boundingBox().center();
}
VWhirlPinchCmd::~VWhirlPinchCmd()
{
}
void
VWhirlPinchCmd::visitVPath( VPath& composite )
{
// first subdivide:
// VInsertKnots insertKnots( 2 );
// insertKnots.visit( composite );
VVisitor::visitVPath( composite );
}
void
VWhirlPinchCmd::visitVSubpath( VSubpath& path )
{
TQWMatrix m;
KoPoint delta;
double dist;
path.first();
VSegment *curr = path.current();
while( curr )
{
// TODO: selfmade this function since it's gone:
// path.current()->convertToCurve();
// Apply effect to each segment node.
for( int i = 0; i < curr->degree(); ++i )
{
// calculate distance from whirl center to actual point
delta = curr->point( i ) - m_center;
dist = sqrt( delta.x() * delta.x() + delta.y() * delta.y() );
// check if point is inside the whirl radius
if( dist < m_radius )
{
m.reset();
// normalize distance to whirl radius
dist /= m_radius;
double scale = pow( sin( VGlobal::pi_2 * dist ), -m_pinch );
// pinch:
m.translate( m_center.x(), m_center.y() );
m.scale( scale, scale );
// whirl:
m.rotate( m_angle * ( 1.0 - dist ) * ( 1.0 - dist ) );
m.translate( -m_center.x(), -m_center.y() );
path.current()->setPoint( i, curr->point( i ).transform( m ) );
}
}
if( !success() )
setSuccess();
curr = path.next();
}
// Invalidate bounding box once.
path.invalidateBoundingBox();
}
#include "whirlpinchplugin.moc"