~ubuntu-branches/ubuntu/precise/koffice/precise

« back to all changes in this revision

Viewing changes to karbon/plugins/tools/KarbonPencilTool.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2010-09-21 15:36:35 UTC
  • mfrom: (1.4.1 upstream) (60.2.11 maverick)
  • Revision ID: james.westby@ubuntu.com-20100921153635-6tejqkiro2u21ydi
Tags: 1:2.2.2-0ubuntu3
Add kubuntu_03_fix-crash-on-closing-sqlite-connection-2.2.2.diff and
kubuntu_04_support-large-memo-values-for-msaccess-2.2.2.diff as
recommended by upstream http://kexi-
project.org/wiki/wikiview/index.php@Kexi2.2_Patches.html#sqlite_stab
ility

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
#include <KoShapeController.h>
29
29
#include <KoShapeManager.h>
30
30
#include <KoSelection.h>
31
 
#include <KoCanvasResourceProvider.h>
 
31
#include <KoResourceManager.h>
32
32
#include <KoColor.h>
33
33
#include <KoPathPoint.h>
34
34
#include <KoPathPointData.h>
47
47
 
48
48
#include <math.h>
49
49
 
50
 
qreal squareDistance( const QPointF &p1, const QPointF &p2)
 
50
qreal squareDistance(const QPointF &p1, const QPointF &p2)
51
51
{
52
 
    qreal dx = p1.x()-p2.x();
53
 
    qreal dy = p1.y()-p2.y();
 
52
    qreal dx = p1.x() - p2.x();
 
53
    qreal dy = p1.y() - p2.y();
54
54
    return dx*dx + dy*dy;
55
55
}
56
56
 
57
57
KarbonPencilTool::KarbonPencilTool(KoCanvasBase *canvas)
58
 
    : KoTool( canvas ),  m_mode( ModeCurve ), m_optimizeRaw( false )
59
 
    , m_optimizeCurve( false ), m_combineAngle( 15.0 ), m_fittingError( 5.0 )
60
 
    , m_close( false ), m_shape( 0 )
61
 
    , m_existingStartPoint(0), m_existingEndPoint(0), m_hoveredPoint(0)
 
58
        : KoToolBase(canvas),  m_mode(ModeCurve), m_optimizeRaw(false)
 
59
        , m_optimizeCurve(false), m_combineAngle(15.0), m_fittingError(5.0)
 
60
        , m_close(false), m_shape(0)
 
61
        , m_existingStartPoint(0), m_existingEndPoint(0), m_hoveredPoint(0)
62
62
{
63
63
}
64
64
 
66
66
{
67
67
}
68
68
 
69
 
void KarbonPencilTool::paint( QPainter &painter, const KoViewConverter &converter )
 
69
void KarbonPencilTool::paint(QPainter &painter, const KoViewConverter &converter)
70
70
{
71
71
    if (m_shape) {
72
72
        painter.save();
73
73
 
74
 
        painter.setMatrix( m_shape->absoluteTransformation( &converter ) * painter.matrix() );
 
74
        painter.setMatrix(m_shape->absoluteTransformation(&converter) * painter.matrix());
75
75
 
76
76
        painter.save();
77
 
        m_shape->paint( painter, converter );
 
77
        m_shape->paint(painter, converter);
78
78
        painter.restore();
79
79
 
80
 
        if( m_shape->border() )
81
 
        {
 
80
        if (m_shape->border()) {
82
81
            painter.save();
83
 
            m_shape->border()->paintBorder( m_shape, painter, converter );
 
82
            m_shape->border()->paint(m_shape, painter, converter);
84
83
            painter.restore();
85
84
        }
86
85
 
87
86
        painter.restore();
88
87
    }
89
 
    
 
88
 
90
89
    if (m_hoveredPoint) {
91
90
        painter.save();
92
91
        painter.setMatrix(m_hoveredPoint->parent()->absoluteTransformation(&converter), true);
93
92
        KoShape::applyConversion(painter, converter);
94
93
 
95
 
        int handleRadius = m_canvas->resourceProvider()->handleRadius();
 
94
        int handleRadius = canvas()->resourceManager()->handleRadius();
96
95
        painter.setPen(Qt::blue);      //TODO make configurable
97
96
        painter.setBrush(Qt::white);   //TODO make configurable
98
97
        m_hoveredPoint->paint(painter, handleRadius, KoPathPoint::Node);
99
 
        
 
98
 
100
99
        painter.restore();
101
100
    }
102
101
}
105
104
{
106
105
}
107
106
 
108
 
void KarbonPencilTool::mousePressEvent( KoPointerEvent *event )
 
107
void KarbonPencilTool::mousePressEvent(KoPointerEvent *event)
109
108
{
110
 
    if( ! m_shape )
111
 
    {
 
109
    if (! m_shape) {
112
110
        m_shape = new KoPathShape();
113
 
        m_shape->setShapeId( KoPathShapeId );
114
 
        m_shape->setBorder( currentBorder() );
 
111
        m_shape->setShapeId(KoPathShapeId);
 
112
        m_shape->setBorder(currentBorder());
115
113
        m_points.clear();
116
 
        
 
114
 
117
115
        QPointF point = event->point;
118
116
        m_existingStartPoint = endPointAtPosition(point);
119
117
        if (m_existingStartPoint)
120
118
            point = m_existingStartPoint->parent()->shapeToDocument(m_existingStartPoint->point());
121
 
        
122
 
        addPoint( point );
 
119
 
 
120
        addPoint(point);
123
121
    }
124
122
}
125
123
 
126
 
void KarbonPencilTool::mouseMoveEvent( KoPointerEvent *event )
 
124
void KarbonPencilTool::mouseMoveEvent(KoPointerEvent *event)
127
125
{
128
 
    if( event->buttons() & Qt::LeftButton )
129
 
        addPoint( event->point );
130
 
    
 
126
    if (event->buttons() & Qt::LeftButton)
 
127
        addPoint(event->point);
 
128
 
131
129
    KoPathPoint * endPoint = endPointAtPosition(event->point);
132
130
    if (m_hoveredPoint != endPoint) {
133
131
        if (m_hoveredPoint) {
134
132
            QPointF nodePos = m_hoveredPoint->parent()->shapeToDocument(m_hoveredPoint->point());
135
 
            m_canvas->updateCanvas(handlePaintRect(nodePos));
 
133
            canvas()->updateCanvas(handlePaintRect(nodePos));
136
134
        }
137
135
        m_hoveredPoint = endPoint;
138
136
        if (m_hoveredPoint) {
139
137
            QPointF nodePos = m_hoveredPoint->parent()->shapeToDocument(m_hoveredPoint->point());
140
 
            m_canvas->updateCanvas(handlePaintRect(nodePos));
 
138
            canvas()->updateCanvas(handlePaintRect(nodePos));
141
139
        }
142
140
    }
143
141
}
144
142
 
145
 
void KarbonPencilTool::mouseReleaseEvent( KoPointerEvent *event )
 
143
void KarbonPencilTool::mouseReleaseEvent(KoPointerEvent *event)
146
144
{
147
 
    if( ! m_shape )
 
145
    if (! m_shape)
148
146
        return;
149
 
    
 
147
 
150
148
    QPointF point = event->point;
151
149
    m_existingEndPoint = endPointAtPosition(point);
152
150
    if (m_existingEndPoint)
153
151
        point = m_existingEndPoint->parent()->shapeToDocument(m_existingEndPoint->point());
154
 
    
155
 
    addPoint( point );
156
 
    finish( event->modifiers() & Qt::ShiftModifier );
 
152
 
 
153
    addPoint(point);
 
154
    finish(event->modifiers() & Qt::ShiftModifier);
157
155
 
158
156
    m_existingStartPoint = 0;
159
157
    m_existingEndPoint = 0;
160
158
    m_hoveredPoint = 0;
161
 
    
 
159
 
162
160
    // the original path may be different from the one added
163
 
    m_canvas->updateCanvas( m_shape->boundingRect() );
 
161
    canvas()->updateCanvas(m_shape->boundingRect());
164
162
    delete m_shape;
165
163
    m_shape = 0;
166
164
    m_points.clear();
168
166
 
169
167
void KarbonPencilTool::keyPressEvent(QKeyEvent *event)
170
168
{
171
 
    if ( m_shape ) {
 
169
    if (m_shape) {
172
170
        event->accept();
173
 
    }
174
 
    else {
 
171
    } else {
175
172
        event->ignore();
176
173
    }
177
174
}
178
175
 
179
 
void KarbonPencilTool::activate( bool )
 
176
void KarbonPencilTool::activate(ToolActivation, const QSet<KoShape*> &)
180
177
{
181
178
    m_points.clear();
182
179
    m_close = false;
183
 
    useCursor(Qt::ArrowCursor, true);
 
180
    useCursor(Qt::ArrowCursor);
184
181
}
185
182
 
186
183
void KarbonPencilTool::deactivate()
193
190
    m_hoveredPoint = 0;
194
191
}
195
192
 
196
 
void KarbonPencilTool::addPoint( const QPointF & point )
 
193
void KarbonPencilTool::addPoint(const QPointF & point)
197
194
{
198
 
    if( ! m_shape )
 
195
    if (! m_shape)
199
196
        return;
200
197
 
201
198
    // do a moveTo for the first point added
202
 
    if( m_points.empty() )
203
 
        m_shape->moveTo( point );
 
199
    if (m_points.empty())
 
200
        m_shape->moveTo(point);
204
201
    // do not allow coincident points
205
 
    else if( point != m_points.last() )
206
 
        m_shape->lineTo( point );
 
202
    else if (point != m_points.last())
 
203
        m_shape->lineTo(point);
207
204
    else
208
205
        return;
209
206
 
210
 
    m_points.append( point );
211
 
    m_canvas->updateCanvas( m_shape->boundingRect() );
 
207
    m_points.append(point);
 
208
    canvas()->updateCanvas(m_shape->boundingRect());
212
209
}
213
210
 
214
 
qreal KarbonPencilTool::lineAngle( const QPointF &p1, const QPointF &p2 )
 
211
qreal KarbonPencilTool::lineAngle(const QPointF &p1, const QPointF &p2)
215
212
{
216
 
    qreal angle = atan2( p2.y() - p1.y(), p2.x() - p1.x() );
217
 
    if( angle < 0.0 )
218
 
        angle += 2*M_PI;
 
213
    qreal angle = atan2(p2.y() - p1.y(), p2.x() - p1.x());
 
214
    if (angle < 0.0)
 
215
        angle += 2 * M_PI;
219
216
 
220
217
    return angle * 180.0 / M_PI;
221
218
}
222
219
 
223
 
void KarbonPencilTool::finish( bool closePath )
 
220
void KarbonPencilTool::finish(bool closePath)
224
221
{
225
 
    if( m_points.count() < 2 )
 
222
    if (m_points.count() < 2)
226
223
        return;
227
224
 
228
225
    KoPathShape * path = 0;
229
226
    QList<QPointF> complete;
230
227
    QList<QPointF> *points = &m_points;
231
228
 
232
 
    if( m_mode == ModeStraight || m_optimizeRaw || m_optimizeCurve )
233
 
    {
 
229
    if (m_mode == ModeStraight || m_optimizeRaw || m_optimizeCurve) {
234
230
        float combineAngle;
235
231
 
236
 
        if( m_mode == ModeStraight )
 
232
        if (m_mode == ModeStraight)
237
233
            combineAngle = m_combineAngle;
238
234
        else
239
235
            combineAngle = 0.50f;
240
236
 
241
237
        //Add the first two points
242
 
        complete.append( m_points[0] );
243
 
        complete.append( m_points[1] );
 
238
        complete.append(m_points[0]);
 
239
        complete.append(m_points[1]);
244
240
 
245
241
        //Now we need to get the angle of the first line
246
 
        float lastAngle = lineAngle( complete[0], complete[1] );
 
242
        float lastAngle = lineAngle(complete[0], complete[1]);
247
243
 
248
244
        uint pointCount = m_points.count();
249
 
        for( uint i = 2; i < pointCount; ++i )
250
 
        {
251
 
            float angle = lineAngle( complete.last(), m_points[i] );
252
 
            if( qAbs( angle - lastAngle ) < combineAngle )
 
245
        for (uint i = 2; i < pointCount; ++i) {
 
246
            float angle = lineAngle(complete.last(), m_points[i]);
 
247
            if (qAbs(angle - lastAngle) < combineAngle)
253
248
                complete.removeLast();
254
 
            complete.append( m_points[i] );
 
249
            complete.append(m_points[i]);
255
250
            lastAngle = angle;
256
251
        }
257
252
 
259
254
        points = &complete;
260
255
    }
261
256
 
262
 
    switch( m_mode )
263
 
    {
264
 
        case ModeCurve:
265
 
        {
266
 
            path = bezierFit( *points, m_fittingError );
267
 
        }
268
 
        break;
269
 
        case ModeStraight:
270
 
        case ModeRaw:
271
 
        {
272
 
            path = new KoPathShape();
273
 
            uint pointCount = points->count();
274
 
            path->moveTo( points->at( 0 ) );
275
 
            for( uint i = 1; i < pointCount; ++i )
276
 
                path->lineTo( points->at(i) );
277
 
        }
278
 
        break;
 
257
    switch (m_mode) {
 
258
    case ModeCurve: {
 
259
        path = bezierFit(*points, m_fittingError);
 
260
    }
 
261
    break;
 
262
    case ModeStraight:
 
263
    case ModeRaw: {
 
264
        path = new KoPathShape();
 
265
        uint pointCount = points->count();
 
266
        path->moveTo(points->at(0));
 
267
        for (uint i = 1; i < pointCount; ++i)
 
268
            path->lineTo(points->at(i));
 
269
    }
 
270
    break;
279
271
    }
280
272
 
281
 
    if( ! path )
 
273
    if (! path)
282
274
        return;
283
275
 
284
276
    KoShape * startShape = 0;
285
277
    KoShape * endShape = 0;
286
 
    
287
 
    if( closePath ) {
 
278
 
 
279
    if (closePath) {
288
280
        path->close();
289
281
        path->normalize();
290
 
    }
291
 
    else {
 
282
    } else {
292
283
        path->normalize();
293
284
        if (connectPaths(path, m_existingStartPoint, m_existingEndPoint)) {
294
285
            if (m_existingStartPoint)
299
290
    }
300
291
 
301
292
    // set the proper shape id
302
 
    path->setShapeId( KoPathShapeId );
303
 
    path->setBorder( currentBorder() );
304
 
    
305
 
    QUndoCommand * cmd = m_canvas->shapeController()->addShape( path );
306
 
    if( cmd )
307
 
    {
308
 
        KoSelection *selection = m_canvas->shapeManager()->selection();
 
293
    path->setShapeId(KoPathShapeId);
 
294
    path->setBorder(currentBorder());
 
295
 
 
296
    QUndoCommand * cmd = canvas()->shapeController()->addShape(path);
 
297
    if (cmd) {
 
298
        KoSelection *selection = canvas()->shapeManager()->selection();
309
299
        selection->deselectAll();
310
 
        selection->select( path );
311
 
        
 
300
        selection->select(path);
 
301
 
312
302
        if (startShape)
313
 
            m_canvas->shapeController()->removeShape(startShape, cmd);
 
303
            canvas()->shapeController()->removeShape(startShape, cmd);
314
304
        if (endShape && startShape != endShape)
315
 
            m_canvas->shapeController()->removeShape(endShape, cmd);
316
 
        
317
 
        m_canvas->addCommand( cmd );
318
 
    }
319
 
    else
320
 
    {
321
 
        m_canvas->updateCanvas( path->boundingRect() );
 
305
            canvas()->shapeController()->removeShape(endShape, cmd);
 
306
 
 
307
        canvas()->addCommand(cmd);
 
308
    } else {
 
309
        canvas()->updateCanvas(path->boundingRect());
322
310
        delete path;
323
311
    }
324
312
}
326
314
QWidget * KarbonPencilTool::createOptionWidget()
327
315
{
328
316
    QWidget *optionWidget = new QWidget();
329
 
    QVBoxLayout * layout = new QVBoxLayout( optionWidget );
330
 
 
331
 
    QHBoxLayout *modeLayout = new QHBoxLayout( optionWidget );
332
 
    modeLayout->setSpacing( 3 );
333
 
    QLabel *modeLabel = new QLabel( i18n( "Precision:" ), optionWidget );
334
 
    KComboBox * modeBox = new KComboBox( optionWidget );
335
 
    modeBox->addItem( i18nc( "The raw line data", "Raw" ) );
336
 
    modeBox->addItem( i18n( "Curve" ) );
337
 
    modeBox->addItem( i18n( "Straight" ) );
338
 
    modeLayout->addWidget( modeLabel );
339
 
    modeLayout->addWidget( modeBox, 1 );
340
 
    layout->addLayout( modeLayout );
341
 
 
342
 
    QStackedWidget * stackedWidget = new QStackedWidget( optionWidget );
343
 
 
344
 
    QWidget * rawBox = new QWidget( stackedWidget );
345
 
    QVBoxLayout * rawLayout = new QVBoxLayout( rawBox );
346
 
    QCheckBox * optimizeRaw = new QCheckBox( i18n( "Optimize" ), rawBox );
347
 
    rawLayout->addWidget( optimizeRaw );
348
 
    rawLayout->setContentsMargins( 0, 0, 0, 0 );
349
 
    
350
 
    QWidget * curveBox = new QWidget( stackedWidget );
351
 
    QHBoxLayout * curveLayout = new QHBoxLayout( curveBox );
352
 
    QCheckBox * optimizeCurve = new QCheckBox( i18n( "Optimize" ), curveBox );
353
 
    KDoubleNumInput * fittingError = new KDoubleNumInput( 0.0, 400.0, m_fittingError, curveBox, 0.50, 3 );
354
 
    fittingError->setToolTip( i18n( "Exactness:" ) );
355
 
    curveLayout->addWidget( optimizeCurve );
356
 
    curveLayout->addWidget( fittingError );
357
 
    curveLayout->setContentsMargins( 0, 0, 0, 0 );
358
 
    
359
 
    QWidget * straightBox = new QWidget( stackedWidget );
360
 
    QVBoxLayout * straightLayout = new QVBoxLayout( straightBox );
361
 
    KDoubleNumInput * combineAngle = new KDoubleNumInput( 0.0, 360.0, m_combineAngle, straightBox, 0.50, 3 );
362
 
    combineAngle->setSuffix( " deg" );
363
 
    combineAngle->setLabel( i18n( "Combine angle:" ), Qt::AlignLeft|Qt::AlignVCenter );
364
 
    straightLayout->addWidget( combineAngle );
365
 
    straightLayout->setContentsMargins( 0, 0, 0, 0 );
366
 
    
367
 
    stackedWidget->addWidget( rawBox );
368
 
    stackedWidget->addWidget( curveBox );
369
 
    stackedWidget->addWidget( straightBox );
370
 
    layout->addWidget( stackedWidget, 1 );
371
 
    layout->addStretch( 1 );
372
 
 
373
 
    connect( modeBox, SIGNAL(activated(int)), stackedWidget, SLOT(setCurrentIndex(int)));
374
 
    connect( modeBox, SIGNAL(activated(int)), this, SLOT(selectMode(int)));
375
 
    connect( optimizeRaw, SIGNAL(stateChanged(int)), this, SLOT(setOptimize(int)));
376
 
    connect( optimizeCurve, SIGNAL(stateChanged(int)), this, SLOT(setOptimize(int)));
377
 
    connect( fittingError, SIGNAL(valueChanged(double)), this, SLOT(setDelta(double)));
378
 
    connect( combineAngle, SIGNAL(valueChanged(double)), this, SLOT(setDelta(double)));
379
 
 
380
 
    modeBox->setCurrentIndex( m_mode );
381
 
    stackedWidget->setCurrentIndex( m_mode );
 
317
    QVBoxLayout * layout = new QVBoxLayout(optionWidget);
 
318
 
 
319
    QHBoxLayout *modeLayout = new QHBoxLayout(optionWidget);
 
320
    modeLayout->setSpacing(3);
 
321
    QLabel *modeLabel = new QLabel(i18n("Precision:"), optionWidget);
 
322
    KComboBox * modeBox = new KComboBox(optionWidget);
 
323
    modeBox->addItem(i18nc("The raw line data", "Raw"));
 
324
    modeBox->addItem(i18n("Curve"));
 
325
    modeBox->addItem(i18n("Straight"));
 
326
    modeLayout->addWidget(modeLabel);
 
327
    modeLayout->addWidget(modeBox, 1);
 
328
    layout->addLayout(modeLayout);
 
329
 
 
330
    QStackedWidget * stackedWidget = new QStackedWidget(optionWidget);
 
331
 
 
332
    QWidget * rawBox = new QWidget(stackedWidget);
 
333
    QVBoxLayout * rawLayout = new QVBoxLayout(rawBox);
 
334
    QCheckBox * optimizeRaw = new QCheckBox(i18n("Optimize"), rawBox);
 
335
    rawLayout->addWidget(optimizeRaw);
 
336
    rawLayout->setContentsMargins(0, 0, 0, 0);
 
337
 
 
338
    QWidget * curveBox = new QWidget(stackedWidget);
 
339
    QHBoxLayout * curveLayout = new QHBoxLayout(curveBox);
 
340
    QCheckBox * optimizeCurve = new QCheckBox(i18n("Optimize"), curveBox);
 
341
    KDoubleNumInput * fittingError = new KDoubleNumInput(0.0, 400.0, m_fittingError, curveBox, 0.50, 3);
 
342
    fittingError->setToolTip(i18n("Exactness:"));
 
343
    curveLayout->addWidget(optimizeCurve);
 
344
    curveLayout->addWidget(fittingError);
 
345
    curveLayout->setContentsMargins(0, 0, 0, 0);
 
346
 
 
347
    QWidget * straightBox = new QWidget(stackedWidget);
 
348
    QVBoxLayout * straightLayout = new QVBoxLayout(straightBox);
 
349
    KDoubleNumInput * combineAngle = new KDoubleNumInput(0.0, 360.0, m_combineAngle, straightBox, 0.50, 3);
 
350
    combineAngle->setSuffix(" deg");
 
351
    combineAngle->setLabel(i18n("Combine angle:"), Qt::AlignLeft | Qt::AlignVCenter);
 
352
    straightLayout->addWidget(combineAngle);
 
353
    straightLayout->setContentsMargins(0, 0, 0, 0);
 
354
 
 
355
    stackedWidget->addWidget(rawBox);
 
356
    stackedWidget->addWidget(curveBox);
 
357
    stackedWidget->addWidget(straightBox);
 
358
    layout->addWidget(stackedWidget, 1);
 
359
    layout->addStretch(1);
 
360
 
 
361
    connect(modeBox, SIGNAL(activated(int)), stackedWidget, SLOT(setCurrentIndex(int)));
 
362
    connect(modeBox, SIGNAL(activated(int)), this, SLOT(selectMode(int)));
 
363
    connect(optimizeRaw, SIGNAL(stateChanged(int)), this, SLOT(setOptimize(int)));
 
364
    connect(optimizeCurve, SIGNAL(stateChanged(int)), this, SLOT(setOptimize(int)));
 
365
    connect(fittingError, SIGNAL(valueChanged(double)), this, SLOT(setDelta(double)));
 
366
    connect(combineAngle, SIGNAL(valueChanged(double)), this, SLOT(setDelta(double)));
 
367
 
 
368
    modeBox->setCurrentIndex(m_mode);
 
369
    stackedWidget->setCurrentIndex(m_mode);
382
370
 
383
371
    return optionWidget;
384
372
}
385
373
 
386
 
void KarbonPencilTool::selectMode( int mode )
 
374
void KarbonPencilTool::selectMode(int mode)
387
375
{
388
 
    m_mode = static_cast<PencilMode>( mode );
 
376
    m_mode = static_cast<PencilMode>(mode);
389
377
}
390
378
 
391
 
void KarbonPencilTool::setOptimize( int state )
 
379
void KarbonPencilTool::setOptimize(int state)
392
380
{
393
 
    if( m_mode == ModeRaw )
 
381
    if (m_mode == ModeRaw)
394
382
        m_optimizeRaw = state == Qt::Checked ? true : false;
395
383
    else
396
384
        m_optimizeCurve = state == Qt::Checked ? true : false;
397
385
}
398
386
 
399
 
void KarbonPencilTool::setDelta( double delta )
 
387
void KarbonPencilTool::setDelta(double delta)
400
388
{
401
 
    if( m_mode == ModeCurve )
 
389
    if (m_mode == ModeCurve)
402
390
        m_fittingError = delta;
403
 
    else if( m_mode == ModeStraight )
 
391
    else if (m_mode == ModeStraight)
404
392
        m_combineAngle = delta;
405
393
}
406
394
 
407
395
KoLineBorder * KarbonPencilTool::currentBorder()
408
396
{
409
 
    KoLineBorder * border = new KoLineBorder( m_canvas->resourceProvider()->activeBorder() );
410
 
    border->setColor( m_canvas->resourceProvider()->foregroundColor().toQColor() ); 
 
397
    KoLineBorder * border = new KoLineBorder(canvas()->resourceManager()->activeBorder());
 
398
    border->setColor(canvas()->resourceManager()->foregroundColor().toQColor());
411
399
    return border;
412
400
}
413
401
 
414
 
KoPathPoint* KarbonPencilTool::endPointAtPosition( const QPointF &position )
 
402
KoPathPoint* KarbonPencilTool::endPointAtPosition(const QPointF &position)
415
403
{
416
404
    QRectF roi = handleGrabRect(position);
417
 
    QList<KoShape *> shapes = m_canvas->shapeManager()->shapesAt(roi);
418
 
    
 
405
    QList<KoShape *> shapes = canvas()->shapeManager()->shapesAt(roi);
 
406
 
419
407
    KoPathPoint * nearestPoint = 0;
420
408
    qreal minDistance = HUGE_VAL;
421
 
    uint grabSensitivity = m_canvas->resourceProvider()->grabSensitivity();
422
 
    qreal maxDistance = m_canvas->viewConverter()->viewToDocumentX(grabSensitivity);
423
 
    
 
409
    uint grabSensitivity = canvas()->resourceManager()->grabSensitivity();
 
410
    qreal maxDistance = canvas()->viewConverter()->viewToDocumentX(grabSensitivity);
 
411
 
424
412
    foreach(KoShape *shape, shapes) {
425
413
        KoPathShape * path = dynamic_cast<KoPathShape*>(shape);
426
414
        if (!path)
428
416
        KoParameterShape *paramShape = dynamic_cast<KoParameterShape*>(shape);
429
417
        if (paramShape && paramShape->isParametricShape())
430
418
            continue;
431
 
        
 
419
 
432
420
        KoPathPoint * p = 0;
433
421
        uint subpathCount = path->subpathCount();
434
422
        for (uint i = 0; i < subpathCount; ++i) {
442
430
                minDistance = d;
443
431
            }
444
432
            // check end of subpath
445
 
            p = path->pointByIndex(KoPathPointIndex(i, path->pointCountSubpath(i)-1));
 
433
            p = path->pointByIndex(KoPathPointIndex(i, path->subpathPointCount(i) - 1));
446
434
            d = squareDistance(position, path->shapeToDocument(p->point()));
447
435
            if (d < minDistance && d < maxDistance) {
448
436
                nearestPoint = p;
450
438
            }
451
439
        }
452
440
    }
453
 
    
 
441
 
454
442
    return nearestPoint;
455
443
}
456
444
 
457
 
bool KarbonPencilTool::connectPaths( KoPathShape *pathShape, KoPathPoint *pointAtStart, KoPathPoint *pointAtEnd )
 
445
bool KarbonPencilTool::connectPaths(KoPathShape *pathShape, KoPathPoint *pointAtStart, KoPathPoint *pointAtEnd)
458
446
{
459
447
    // at least one point must be valid
460
448
    if (!pointAtStart && !pointAtEnd)
462
450
    // do not allow connecting to the same point twice
463
451
    if (pointAtStart == pointAtEnd)
464
452
        pointAtEnd = 0;
465
 
    
 
453
 
466
454
    // we have hit an existing path point on start/finish
467
455
    // what we now do is:
468
456
    // 1. combine the new created path with the ones we hit on start/finish
469
457
    // 2. merge the endpoints of the corresponding subpaths
470
 
    
471
 
    uint newPointCount = pathShape->pointCountSubpath(0);
 
458
 
 
459
    uint newPointCount = pathShape->subpathPointCount(0);
472
460
    KoPathPointIndex newStartPointIndex(0, 0);
473
 
    KoPathPointIndex newEndPointIndex(0, newPointCount-1);
 
461
    KoPathPointIndex newEndPointIndex(0, newPointCount - 1);
474
462
    KoPathPoint * newStartPoint = pathShape->pointByIndex(newStartPointIndex);
475
463
    KoPathPoint * newEndPoint = pathShape->pointByIndex(newEndPointIndex);
476
 
    
 
464
 
477
465
    KoPathShape * startShape = pointAtStart ? pointAtStart->parent() : 0;
478
466
    KoPathShape * endShape = pointAtEnd ? pointAtEnd->parent() : 0;
479
 
    
 
467
 
480
468
    // combine with the path we hit on start
481
 
    KoPathPointIndex startIndex(-1,-1);
 
469
    KoPathPointIndex startIndex(-1, -1);
482
470
    if (pointAtStart) {
483
471
        startIndex = startShape->pathPointIndex(pointAtStart);
484
472
        pathShape->combine(startShape);
485
 
        pathShape->moveSubpath(0, pathShape->subpathCount()-1);
 
473
        pathShape->moveSubpath(0, pathShape->subpathCount() - 1);
486
474
    }
487
475
    // combine with the path we hit on finish
488
 
    KoPathPointIndex endIndex(-1,-1);
 
476
    KoPathPointIndex endIndex(-1, -1);
489
477
    if (pointAtEnd) {
490
478
        endIndex = endShape->pathPointIndex(pointAtEnd);
491
479
        if (endShape != startShape) {
495
483
    }
496
484
    // do we connect twice to a single subpath ?
497
485
    bool connectToSingleSubpath = (startShape == endShape && startIndex.first == endIndex.first);
498
 
    
 
486
 
499
487
    if (startIndex.second == 0 && !connectToSingleSubpath) {
500
488
        pathShape->reverseSubpath(startIndex.first);
501
 
        startIndex.second = pathShape->pointCountSubpath(startIndex.first)-1;
 
489
        startIndex.second = pathShape->subpathPointCount(startIndex.first) - 1;
502
490
    }
503
491
    if (endIndex.second > 0 && !connectToSingleSubpath) {
504
492
        pathShape->reverseSubpath(endIndex.first);
505
493
        endIndex.second = 0;
506
494
    }
507
 
    
 
495
 
508
496
    // after combining we have a path where with the subpaths in the following
509
497
    // order:
510
498
    // 1. the subpaths of the pathshape we started the new path at
511
499
    // 2. the subpath we just created
512
500
    // 3. the subpaths of the pathshape we finished the new path at
513
 
    
 
501
 
514
502
    // get the path points we want to merge, as these are not going to
515
503
    // change while merging
516
504
    KoPathPoint * existingStartPoint = pathShape->pointByIndex(startIndex);
517
505
    KoPathPoint * existingEndPoint = pathShape->pointByIndex(endIndex);
518
 
    
 
506
 
519
507
    // merge first two points
520
508
    if (existingStartPoint) {
521
509
        KoPathPointData pd1(pathShape, pathShape->pathPointIndex(existingStartPoint));
530
518
        KoPathPointMergeCommand cmd2(pd3, pd4);
531
519
        cmd2.redo();
532
520
    }
533
 
    
 
521
 
534
522
    return true;
535
523
}
536
524