karbon

vpenciltool.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2001, 2002, 2003 The Karbon Developers
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18
19*/
20#include <math.h>
21
22#include <tqcursor.h>
23#include <tqevent.h>
24#include <tqlabel.h>
25#include <tqgroupbox.h>
26#include <tqcombobox.h>
27#include <tqcheckbox.h>
28#include <tqvbox.h>
29#include <tqwidgetstack.h>
30
31#include <tdelocale.h>
32#include <knuminput.h>
33//#include <KoUnitWidgets.h>
34
35#include <karbon_part.h>
36#include <karbon_view.h>
37
38#include <core/vcolor.h>
39#include <core/vcomposite.h>
40#include <core/vfill.h>
41#include <core/vstroke.h>
42#include <core/vglobal.h>
43#include <core/vselection.h>
44#include <core/vcursor.h>
45#include <render/vpainter.h>
46#include <render/vpainterfactory.h>
47#include "vpenciltool.h"
48#include <commands/vshapecmd.h>
49
50#include "vcurvefit.h"
51
52#include "vpenciltool.moc"
53
54VPencilOptionsWidget::VPencilOptionsWidget( KarbonView*view, TQWidget* parent, const char* name )
55 : KDialogBase( parent, name, true, i18n( "Pencil Settings" ), Ok | Cancel ), m_view( view )
56{
57 TQVBox *vbox = new TQVBox( this );
58
59 m_combo = new TQComboBox( vbox );
60
61 m_combo->insertItem( i18n( "Raw" ) );
62 m_combo->insertItem( i18n( "Curve" ) );
63 m_combo->insertItem( i18n( "Straight" ) );
64
65 m_widgetStack = new TQWidgetStack( vbox );
66
67 TQGroupBox *group1 = new TQGroupBox( 2, TQt::Horizontal, i18n( "Properties" ), m_widgetStack );
68 m_widgetStack->addWidget( group1, 1 );
69 m_optimizeRaw = new TQCheckBox( i18n( "Optimize" ), group1 );
70
71 group1->setInsideMargin( 4 );
72 group1->setInsideSpacing( 2 );
73
74 TQGroupBox *group2 = new TQGroupBox( 2, TQt::Horizontal, i18n( "Properties" ), m_widgetStack );
75 m_widgetStack->addWidget( group2, 2 );
76
77 TQVBox *vbox2 = new TQVBox( group2 );
78
79 m_optimizeCurve = new TQCheckBox( i18n( "Optimize" ), vbox2 );
80 m_fittingError = new KDoubleNumInput( 0.0, 400.0, 4.00, 0.50, 3, vbox2 );
81 m_fittingError->setLabel( i18n( "Exactness:" ) );
82
83 group2->setInsideMargin( 4 );
84 group2->setInsideSpacing( 2 );
85
86 TQGroupBox *group3 = new TQGroupBox( 2, TQt::Horizontal, i18n( "Properties" ), m_widgetStack );
87 m_widgetStack->addWidget( group3, 3 );
88
89 m_combineAngle = new KDoubleNumInput( 0.0, 360.0, 0.10, 0.50, 3, group3 );
90 m_combineAngle->setSuffix( " deg" );
91 m_combineAngle->setLabel( i18n( "Combine angle:" ) );
92
93 group3->setInsideMargin( 4 );
94 group3->setInsideSpacing( 2 );
95
96 connect( m_combo, TQ_SIGNAL( activated( int ) ), this, TQ_SLOT( selectMode() ) );
97
98 //Set the default settings
99 m_mode = VPencilTool::CURVE;
100 selectMode();
101
102 m_optimizeCurve->setChecked( true );
103 m_optimizeRaw->setChecked( true );
104
105 setMainWidget( vbox );
106}
107
108float VPencilOptionsWidget::combineAngle()
109{
110 return m_combineAngle->value();
111}
112
113bool VPencilOptionsWidget::optimize()
114{
115 return ( m_optimizeRaw->isChecked() || m_optimizeCurve->isChecked() );
116}
117
118float VPencilOptionsWidget::fittingError()
119{
120 return m_fittingError->value();
121}
122
123void VPencilOptionsWidget::selectMode()
124{
125 m_widgetStack->raiseWidget( m_combo->currentItem() + 1 );
126
127 switch( m_combo->currentItem() )
128 {
129 case 0: m_mode = VPencilTool::RAW; break;
130 case 1: m_mode = VPencilTool::CURVE; break;
131 case 2: m_mode = VPencilTool::STRAIGHT; break;
132 }
133}
134
135int VPencilOptionsWidget::currentMode(){
136 return m_mode;
137}
138
139/* ------------------------------------------------------------------------------------------------------------------------*/
140
141VPencilTool::VPencilTool( KarbonView *view )
142 : VTool( view, "tool_pencil" )
143{
144 m_Points.setAutoDelete( true );
145 m_optionWidget = new VPencilOptionsWidget( view );
146 registerTool( this );
147 m_mode = CURVE;
148 m_optimize = true;
149 m_combineAngle = 3.0f;
150 m_cursor = new TQCursor( VCursor::createCursor( VCursor::CrossHair ) );
151}
152
153VPencilTool::~VPencilTool()
154{
155 delete m_cursor;
156}
157
158TQString
160{
161 TQString s = i18n( "<qt><b>Pencil tool:</b><br>" );
162 s += i18n( "- <i>Click</i> to begin drawing, release when you have finished.");
163 s += i18n( "- Press <i>Enter</i> or <i>double click</i> to end the polyline.</qt>" );
164
165 return s;
166}
167
168void
170{
172 view()->statusMessage()->setText( i18n( "Pencil Tool" ) );
173 view()->setCursor( *m_cursor );
174 view()->part()->document().selection()->showHandle( false );
175
176 m_Points.clear();
177 m_close = false;
178}
179
180void
182{
183 m_Points.removeLast();
184 m_Points.removeLast();
185
186 VPath* line = 0L;
187
188 TQPtrList<KoPoint> complete;
189 TQPtrList<KoPoint> *points = &m_Points;
190
191 if( m_Points.count() > 1 )
192 {
193 if( m_optimize || m_mode == STRAIGHT )
194 {
195 complete.setAutoDelete( true );
196 m_Points.setAutoDelete( false );
197
198 float cangle;
199
200 if( m_mode == STRAIGHT )
201 cangle = m_combineAngle;
202 else
203 cangle = 0.50f;
204
205 #define ANGLE(P0,P1)\
206 atan((P1)->y()-(P0)->y())/((P1)->x()-(P0)->x())*(180/M_PI)
207
208 //Add the first point
209 complete.append( m_Points.first() );
210 complete.append( m_Points.next() );
211
212 //Now we need to get the angle of the first line
213 float langle = ANGLE( complete.at( 0 ), complete.at( 1 ) );
214
215 KoPoint *nextp = NULL;
216 while( ( nextp = m_Points.next() ) )
217 {
218 float angle = ANGLE( complete.last(), nextp );
219 if( TQABS( angle - langle ) < cangle )
220 complete.removeLast();
221 complete.append(nextp);
222 langle=angle;
223 }
224 m_Points.clear();
225 m_Points.setAutoDelete(true);
226
227 points = &complete;
228 }
229
230 switch(m_mode)
231 {
232 case CURVE:
233 {
234 line = bezierFit( *points, m_optionWidget->fittingError() );
235 break;
236 }
237 case STRAIGHT:
238 case RAW:
239 {
240 line = new VPath( 0L );
241 KoPoint* p1 = (*points).first();
242 KoPoint* plast = p1;
243 line->moveTo( *p1 );
244
245 KoPoint* pnext = 0L;
246
247 while( ( pnext = (*points).next() ) )
248 {
249 line->lineTo( *pnext );
250 plast = pnext;
251 }
252 break;
253 }
254 }
255
256 if( shiftPressed() )
257 line->close();
258 }
259
260 if( line )
261 {
262 VShapeCmd* cmd = new VShapeCmd(
263 &view()->part()->document(),
264 i18n( "Pencil" ),
265 line,
266 "14_pencil" );
267
268 view()->part()->addCommand( cmd, true );
269 }
270}
271
272void
274{
275 VPainter* painter = view()->painterFactory()->editpainter();
276 painter->setRasterOp( TQt::NotROP );
277
278 m_mode = m_optionWidget->currentMode();
279 m_optimize = m_optionWidget->optimize();
280 m_combineAngle = m_optionWidget->combineAngle();
281
282 if( m_Points.count() > 1 )
283 {
284 VPath line( 0L );
285 line.moveTo( *m_Points.first() );
286
287 KoPoint *pnext;
288 while((pnext=m_Points.next())){
289 line.lineTo( *pnext );
290 }
291
292 line.setState( VObject::edit );
293 line.draw( painter, &line.boundingBox() );
294 }
295
296}
297
298
299void
303
304void
306{
307 m_Points.append( new KoPoint( last() ) );
308
309 draw();
310}
311
312void
314{
315 m_Points.append( new KoPoint( last() ) );
316 draw();
317 accept();
318 return;
319}
320
321void
326
327void
329{
330 if( m_Points.count() != 0 )
331 {
332 draw();
333
334 m_Points.append( new KoPoint( last() ) );
335
336 draw();
337 }
338}
339
340void
345
346void
350
351void
356
357void
361
362void
366
367void
369{
370 draw();
371
372 m_Points.clear();
373}
374
375void
377{
378 draw();
379
380 m_Points.clear();
381
382 draw();
383}
384
385void
387{
388 deactivate();
389 activate();
390}
391
392bool
394{
395 return m_optionWidget->exec() == TQDialog::Accepted;
396}
397
398void
399VPencilTool::setup( TDEActionCollection *collection )
400{
401 m_action = static_cast<TDERadioAction *>(collection -> action( name() ) );
402
403 if( m_action == 0 )
404 {
405 m_action = new TDERadioAction( i18n( "Pencil Tool" ), "14_pencil", TQt::SHIFT+TQt::Key_P, this, TQ_SLOT( activate() ), collection, name() );
406 m_action->setToolTip( i18n( "Pencil" ) );
407 m_action->setExclusiveGroup( "freehand" );
408 //m_ownAction = true;
409 }
410}
411
@ CrossHair
unthemed crosshair cursor
Definition vcursor.h:38
static TQCursor createCursor(CursorType type)
Creates a predefined cursor of the specified type.
Definition vcursor.cpp:75
virtual void setState(const VState state)
Sets the state to a specified new state.
Definition vobject.h:163
@ edit
visible, active and is currently manipulated by a tool
Definition vobject.h:62
A composite path consists of one or many subpaths.
Definition vcomposite.h:48
virtual void draw(VPainter *painter, const KoRect *rect=0L) const
Draw the object to a painting device.
void close()
Closes the current subpath.
virtual const KoRect & boundingBox() const
Calculates the tightest bounding box around the object.
virtual void mouseDragCtrlReleased()
"Ctrl" key released while mouse drag.
virtual void mouseMove()
Mouse move.
virtual void mouseButtonRelease()
Left mouse button release.
virtual void cancel()
Cancels all tool operations.
virtual void deactivate()
Deactivates the tool.
virtual TQString contextHelp()
The context help of the tool.
short m_mode
The mode of the pencile.
TQPtrList< KoPoint > m_Points
The list of this polyline points.
virtual void cancelStep()
Cancels the last tool step (if any).
virtual void mouseDragShiftPressed()
Mouse drag with "Shift" key pressed at the same time.
virtual void activate()
Called during the tool activation.
virtual void mouseButtonPress()
Left mouse button press.
virtual void setup(TDEActionCollection *collection)
Called after tool creation.
virtual void mouseDragRelease()
Mouse button release.
virtual bool showDialog() const
Shows the tools option dialog.
virtual void accept()
Terminates the current tool drawing (if any).
virtual void mouseButtonDblClick()
Mouse button double click.
virtual void mouseDragShiftReleased()
"Shift" key released while mouse drag.
void draw()
Helper method: draws the polyline.
bool m_close
Indicates if the Line is to close.
virtual void mouseDragCtrlPressed()
Mouse drag with "Ctrl" key pressed at the same time.
virtual void mouseDrag()
Mouse drag.
The base class for all karbon tools.
Definition vtool.h:52
const KoPoint & last() const
The last mouse coordinate.
Definition vtool.h:285
TDERadioAction * action() const
Returns the tool's associated action object.
Definition vtool.h:151
virtual void activate()
Called during the tool activation.
Definition vtool.cpp:252
bool shiftPressed() const
The status of the shift key.
Definition vtool.h:292
TDERadioAction * m_action
The tool's action object.
Definition vtool.h:309
KarbonView * view() const
Returns the connected karbon part.
Definition vtool.cpp:66