karbon

vpenciltool.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2001, 2002, 2003 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 <math.h>
00021 
00022 #include <qcursor.h>
00023 #include <qevent.h>
00024 #include <qlabel.h>
00025 #include <qgroupbox.h>
00026 #include <qcombobox.h>
00027 #include <qcheckbox.h>
00028 #include <qvbox.h>
00029 #include <qwidgetstack.h>
00030 
00031 #include <klocale.h>
00032 #include <knuminput.h>
00033 //#include <KoUnitWidgets.h>
00034 
00035 #include <karbon_part.h>
00036 #include <karbon_view.h>
00037 
00038 #include <core/vcolor.h>
00039 #include <core/vcomposite.h>
00040 #include <core/vfill.h>
00041 #include <core/vstroke.h>
00042 #include <core/vglobal.h>
00043 #include <core/vselection.h>
00044 #include <core/vcursor.h>
00045 #include <render/vpainter.h>
00046 #include <render/vpainterfactory.h>
00047 #include "vpenciltool.h"
00048 #include <commands/vshapecmd.h>
00049 
00050 #include "vcurvefit.h"
00051 
00052 #include "vpenciltool.moc"
00053 
00054 VPencilOptionsWidget::VPencilOptionsWidget( KarbonView*view, QWidget* parent, const char* name )
00055     : KDialogBase( parent, name, true, i18n( "Pencil Settings" ), Ok | Cancel ), m_view( view )
00056 {
00057     QVBox *vbox = new QVBox( this );
00058 
00059     m_combo = new QComboBox( vbox );
00060 
00061     m_combo->insertItem( i18n( "Raw" ) );
00062     m_combo->insertItem( i18n( "Curve" ) );
00063     m_combo->insertItem( i18n( "Straight" ) );
00064 
00065     m_widgetStack  = new QWidgetStack( vbox );
00066 
00067     QGroupBox *group1 = new QGroupBox( 2, Qt::Horizontal, i18n( "Properties" ), m_widgetStack );
00068     m_widgetStack->addWidget( group1, 1 );
00069     m_optimizeRaw = new QCheckBox( i18n( "Optimize" ), group1 );
00070 
00071     group1->setInsideMargin( 4 );
00072     group1->setInsideSpacing( 2 );
00073 
00074     QGroupBox *group2 = new QGroupBox( 2, Qt::Horizontal, i18n( "Properties" ), m_widgetStack );
00075     m_widgetStack->addWidget( group2, 2 );
00076 
00077     QVBox *vbox2 = new QVBox( group2 );
00078 
00079     m_optimizeCurve = new QCheckBox( i18n( "Optimize" ), vbox2 );
00080     m_fittingError = new KDoubleNumInput( 0.0, 400.0, 4.00, 0.50, 3, vbox2 );
00081     m_fittingError->setLabel( i18n( "Exactness:" ) );
00082 
00083     group2->setInsideMargin( 4 );
00084     group2->setInsideSpacing( 2 );
00085 
00086     QGroupBox *group3 = new QGroupBox( 2, Qt::Horizontal, i18n( "Properties" ), m_widgetStack );
00087     m_widgetStack->addWidget( group3, 3 );
00088 
00089     m_combineAngle = new KDoubleNumInput( 0.0, 360.0, 0.10, 0.50, 3, group3 );
00090     m_combineAngle->setSuffix( " deg" );
00091     m_combineAngle->setLabel( i18n( "Combine angle:" ) );
00092 
00093     group3->setInsideMargin( 4 );
00094     group3->setInsideSpacing( 2 );
00095 
00096     connect( m_combo, SIGNAL( activated( int ) ), this, SLOT( selectMode() ) );
00097 
00098     //Set the default settings
00099     m_mode = VPencilTool::CURVE;
00100     selectMode();
00101 
00102     m_optimizeCurve->setChecked( true );
00103     m_optimizeRaw->setChecked( true );
00104 
00105     setMainWidget( vbox );
00106 }
00107 
00108 float VPencilOptionsWidget::combineAngle()
00109 {
00110     return m_combineAngle->value();
00111 }
00112 
00113 bool VPencilOptionsWidget::optimize()
00114 {
00115     return ( m_optimizeRaw->isChecked() || m_optimizeCurve->isChecked() );
00116 }
00117 
00118 float VPencilOptionsWidget::fittingError()
00119 {
00120     return m_fittingError->value();
00121 }
00122 
00123 void VPencilOptionsWidget::selectMode()
00124 {
00125     m_widgetStack->raiseWidget( m_combo->currentItem() + 1 );
00126 
00127     switch( m_combo->currentItem() )
00128     {
00129         case 0: m_mode = VPencilTool::RAW; break;
00130         case 1: m_mode = VPencilTool::CURVE; break;
00131         case 2: m_mode = VPencilTool::STRAIGHT; break;
00132     }
00133 }
00134 
00135 int VPencilOptionsWidget::currentMode(){
00136     return m_mode;
00137 }
00138 
00139 /* ------------------------------------------------------------------------------------------------------------------------*/
00140 
00141 VPencilTool::VPencilTool( KarbonView *view )
00142     : VTool( view, "tool_pencil" )
00143 {
00144     m_Points.setAutoDelete( true );
00145     m_optionWidget = new VPencilOptionsWidget( view );
00146     registerTool( this );
00147     m_mode = CURVE;
00148     m_optimize = true;
00149     m_combineAngle = 3.0f;
00150     m_cursor = new QCursor( VCursor::createCursor( VCursor::CrossHair ) );
00151 }
00152 
00153 VPencilTool::~VPencilTool()
00154 {
00155     delete m_cursor;
00156 }
00157 
00158 QString
00159 VPencilTool::contextHelp()
00160 {
00161     QString s = i18n( "<qt><b>Pencil tool:</b><br>" );
00162     s += i18n( "- <i>Click</i> to begin drawing, release when you have finished.");
00163     s += i18n( "- Press <i>Enter</i> or <i>double click</i> to end the polyline.</qt>" );
00164 
00165     return s;
00166 }
00167 
00168 void
00169 VPencilTool::activate()
00170 {
00171     VTool::activate();
00172     view()->statusMessage()->setText( i18n( "Pencil Tool" ) );
00173     view()->setCursor( *m_cursor );
00174     view()->part()->document().selection()->showHandle( false );
00175 
00176     m_Points.clear();
00177     m_close = false;
00178 }
00179 
00180 void
00181 VPencilTool::deactivate()
00182 {
00183     m_Points.removeLast();
00184     m_Points.removeLast();
00185 
00186     VPath* line = 0L;
00187 
00188     QPtrList<KoPoint> complete;
00189     QPtrList<KoPoint> *points = &m_Points;
00190 
00191     if( m_Points.count() > 1 )
00192     {
00193         if( m_optimize || m_mode == STRAIGHT )
00194         {
00195             complete.setAutoDelete( true );
00196             m_Points.setAutoDelete( false );
00197 
00198             float cangle;
00199 
00200             if( m_mode == STRAIGHT )
00201                 cangle = m_combineAngle;
00202             else
00203                 cangle = 0.50f;
00204 
00205             #define ANGLE(P0,P1)\
00206                 atan((P1)->y()-(P0)->y())/((P1)->x()-(P0)->x())*(180/M_PI)
00207 
00208             //Add the first point
00209             complete.append( m_Points.first() );
00210             complete.append( m_Points.next() );
00211 
00212             //Now we need to get the angle of the first line
00213             float langle = ANGLE( complete.at( 0 ), complete.at( 1 ) );
00214 
00215             KoPoint *nextp = NULL;
00216             while( ( nextp = m_Points.next() ) )
00217             {
00218                 float angle = ANGLE( complete.last(), nextp );
00219                 if( QABS( angle - langle ) < cangle )
00220                     complete.removeLast();
00221                 complete.append(nextp);
00222                 langle=angle;
00223             }
00224             m_Points.clear();
00225             m_Points.setAutoDelete(true);
00226 
00227             points = &complete;
00228         }
00229 
00230         switch(m_mode)
00231         {
00232             case CURVE:
00233             {
00234                 line = bezierFit( *points, m_optionWidget->fittingError() );
00235                 break;
00236             }
00237             case STRAIGHT:
00238             case RAW:
00239             {
00240                 line = new VPath( 0L );
00241                 KoPoint* p1 = (*points).first();
00242                 KoPoint* plast = p1;
00243                 line->moveTo( *p1 );
00244 
00245                 KoPoint* pnext = 0L;
00246 
00247                 while( ( pnext = (*points).next() ) )
00248                 {
00249                     line->lineTo( *pnext );
00250                     plast = pnext;
00251                 }
00252                 break;
00253             }
00254         }
00255 
00256         if( shiftPressed() )
00257             line->close();
00258     }
00259 
00260     if( line )
00261     {
00262         VShapeCmd* cmd = new VShapeCmd(
00263             &view()->part()->document(),
00264             i18n( "Pencil" ),
00265             line,
00266             "14_pencil" );
00267 
00268         view()->part()->addCommand( cmd, true );
00269     }
00270 }
00271 
00272 void
00273 VPencilTool::draw()
00274 {
00275     VPainter* painter = view()->painterFactory()->editpainter();
00276     painter->setRasterOp( Qt::NotROP );
00277 
00278     m_mode = m_optionWidget->currentMode();
00279     m_optimize = m_optionWidget->optimize();
00280     m_combineAngle = m_optionWidget->combineAngle();
00281 
00282     if( m_Points.count() > 1 )
00283     {
00284         VPath line( 0L );
00285         line.moveTo( *m_Points.first() );
00286 
00287         KoPoint *pnext;
00288         while((pnext=m_Points.next())){
00289             line.lineTo( *pnext );
00290         }
00291 
00292         line.setState( VObject::edit );
00293         line.draw( painter, &line.boundingBox() );
00294     }
00295 
00296 }
00297 
00298 
00299 void
00300 VPencilTool::mouseMove()
00301 {
00302 }
00303 
00304 void
00305 VPencilTool::mouseButtonPress()
00306 {
00307     m_Points.append( new KoPoint( last() ) );
00308 
00309     draw();
00310 }
00311 
00312 void
00313 VPencilTool::mouseButtonRelease()
00314 {
00315     m_Points.append( new KoPoint( last() ) );
00316     draw();
00317     accept();
00318     return;
00319 }
00320 
00321 void
00322 VPencilTool::mouseButtonDblClick()
00323 {
00324     accept();
00325 }
00326 
00327 void
00328 VPencilTool::mouseDrag()
00329 {
00330     if( m_Points.count() != 0 )
00331     {
00332         draw();
00333 
00334         m_Points.append( new KoPoint( last() ) );
00335 
00336         draw();
00337     }
00338 }
00339 
00340 void
00341 VPencilTool::mouseDragRelease()
00342 {
00343     mouseButtonRelease();
00344 }
00345 
00346 void
00347 VPencilTool::mouseDragShiftPressed()
00348 {
00349 }
00350 
00351 void
00352 VPencilTool::mouseDragCtrlPressed()
00353 {
00354 
00355 }
00356 
00357 void
00358 VPencilTool::mouseDragShiftReleased()
00359 {
00360 }
00361 
00362 void
00363 VPencilTool::mouseDragCtrlReleased()
00364 {
00365 }
00366 
00367 void
00368 VPencilTool::cancel()
00369 {
00370     draw();
00371 
00372     m_Points.clear();
00373 }
00374 
00375 void
00376 VPencilTool::cancelStep()
00377 {
00378     draw();
00379 
00380     m_Points.clear();
00381 
00382     draw();
00383 }
00384 
00385 void
00386 VPencilTool::accept()
00387 {
00388     deactivate();
00389     activate();
00390 }
00391 
00392 bool
00393 VPencilTool::showDialog() const
00394 {
00395     return m_optionWidget->exec() == QDialog::Accepted;
00396 }
00397 
00398 void
00399 VPencilTool::setup( KActionCollection *collection )
00400 {
00401     m_action = static_cast<KRadioAction *>(collection -> action( name() ) );
00402 
00403     if( m_action == 0 )
00404     {
00405         m_action = new KRadioAction( i18n( "Pencil Tool" ), "14_pencil", Qt::SHIFT+Qt::Key_P, this, SLOT( activate() ), collection, name() );
00406         m_action->setToolTip( i18n( "Pencil" ) );
00407         m_action->setExclusiveGroup( "freehand" );
00408         //m_ownAction = true;
00409     }
00410 }
00411 
KDE Home | KDE Accessibility Home | Description of Access Keys