straight_connector.cpp
1/*
2 * Kivio - Visual Modelling and Flowcharting
3 * Copyright (C) 2000-2001 theKompany.com & Dave Marotti
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19#include <stdio.h>
20#include <math.h>
21#include "straight_connector.h"
22
23#include "kivio_common.h"
24#include "kivio_connector_target.h"
25#include "kivio_layer.h"
26#include "kivio_line_style.h"
27#include "kivio_page.h"
28#include "kivio_painter.h"
29#include "kivio_stencil.h"
30#include "kivio_stencil_spawner.h"
31#include "kivio_stencil_spawner_info.h"
32#include "kivio_stencil_spawner_set.h"
33#include "kivio_text_style.h"
34#include "tkmath.h"
35
36#include <tqcolor.h>
37#include <tqpixmap.h>
38#include <kdebug.h>
39#include <KoZoomHandler.h>
40
41#include "straight_connector.xpm"
42
43
44static TQPixmap *pIcon = NULL;
45
46static KivioStencilSpawnerInfo sinfo = KivioStencilSpawnerInfo("Dave Marotti", "Straight Connector", "Dave Marotti - Straight Connector", "Basic Straight Connector", "0.1", "http://localhost/", "", "off");
47
48#include <kgenericfactory.h>
49K_EXPORT_COMPONENT_FACTORY( straight_connector, KGenericFactory<KivioConnectorFactory>( "KivioConnectorFactory" ) )
50
51KivioConnectorFactory::KivioConnectorFactory(TQObject *parent, const char* name, const TQStringList& args) :
52 KivioStencilFactory(parent, name, args)
53{
54 kdDebug(43000) << "new straight line connector factory: " << endl;
55}
56
57KivioStencil *KivioConnectorFactory::NewStencil()
58{
59 return new KivioStraightConnector();
60}
61
62KivioStencil *KivioConnectorFactory::NewStencil(const TQString&)
63{
64 return new KivioStraightConnector();
65}
66
67//FIXME: Is this a memory leak?
68TQPixmap *KivioConnectorFactory::GetIcon()
69{
70 if( pIcon )
71 return pIcon;
72
73 pIcon = new TQPixmap( (const char **)straight_connector_xpm );
74 return pIcon;
75}
76
77KivioStencilSpawnerInfo *KivioConnectorFactory::GetSpawnerInfo()
78{
79 return &sinfo;
80}
81
82
83KivioStraightConnector::KivioStraightConnector()
84 : Kivio1DStencil()
85{
86 m_pStart->setPosition(0.0f, 0.0f, false);
87 m_pEnd->setPosition(72.0f, 72.0f, false);
88
89 m_startAH = new KivioArrowHead();
90 m_endAH = new KivioArrowHead();
91 m_needsWidth = false;
92 m_needsText = true;
93
94 m_pCanProtect->clearBit( kpAspect );
95 m_pCanProtect->clearBit( kpWidth );
96 m_pCanProtect->clearBit( kpHeight );
97 m_pCanProtect->clearBit( kpX );
98 m_pCanProtect->clearBit( kpY );
99
100 // This is a stencil of type connector
101 setType(kstConnector);
102}
103
104KivioStraightConnector::~KivioStraightConnector()
105{
106 delete m_startAH;
107 delete m_endAH;
108}
109
110void KivioStraightConnector::setStartPoint( double x, double y )
111{
112 m_pStart->setPosition( x, y, false );
113 m_pStart->disconnect();
114}
115
116void KivioStraightConnector::setEndPoint( double x, double y )
117{
118 m_pEnd->setPosition( x, y, false );
119 m_pEnd->disconnect();
120
121 if( m_needsText )
122 {
123 m_pTextConn->setPosition( (m_pStart->x()+m_pEnd->x())/2.0f,
124 (m_pStart->y()+m_pEnd->y())/2.0f,
125 false );
126 }
127}
128
129KivioCollisionType KivioStraightConnector::checkForCollision( KoPoint *p, double threshold )
130{
131 const double end_thresh = 4.0f;
132
133 double px = p->x();
134 double py = p->y();
135
136 KivioConnectorPoint *pPoint;
137
138 int i = kctCustom + 1;
139 pPoint = m_pConnectorPoints->first();
140 while( pPoint )
141 {
142 if( px >= pPoint->x() - end_thresh &&
143 px <= pPoint->x() + end_thresh &&
144 py >= pPoint->y() - end_thresh &&
145 py <= pPoint->y() + end_thresh )
146 {
147 return (KivioCollisionType)i;
148 }
149
150 i++;
151 pPoint = m_pConnectorPoints->next();
152 }
153
154
155 if( collisionLine( m_pStart->x(), m_pStart->y(),
156 m_pEnd->x(), m_pEnd->y(),
157 px, py,
158 threshold ) )
159 {
160 return kctBody;
161 }
162
163 return kctNone;
164}
165
166KivioStencil *KivioStraightConnector::duplicate()
167{
168 KivioStraightConnector *pStencil = new KivioStraightConnector();
169
170 copyBasicInto( pStencil );
171
172 // Copy the arrow head information
173 pStencil->setStartAHType( m_startAH->type() );
174 pStencil->setStartAHWidth( m_startAH->width() );
175 pStencil->setStartAHLength( m_startAH->length() );
176
177 pStencil->setEndAHType( m_endAH->type() );
178 pStencil->setEndAHWidth( m_endAH->width() );
179 pStencil->setEndAHLength( m_endAH->length() );
180
181 *(pStencil->protection()) = *m_pProtection;
182 *(pStencil->canProtect()) = *m_pCanProtect;
183
184 return pStencil;
185}
186
187void KivioStraightConnector::paint( KivioIntraStencilData *pData )
188{
189 KivioPainter *painter = pData->painter;
190 KoZoomHandler* zoomHandler = pData->zoomHandler;
191 double x1, y1, x2, y2;
192 double vecX, vecY;
193 double len;
194
195
196 painter->setLineStyle(m_pLineStyle);
197 double lineWidth = m_pLineStyle->width();
198 painter->setLineWidth(zoomHandler->zoomItY(lineWidth));
199
200 x1 = zoomHandler->zoomItX(m_pStart->x());
201 x2 = zoomHandler->zoomItX(m_pEnd->x());
202
203 y1 = zoomHandler->zoomItY(m_pStart->y());
204 y2 = zoomHandler->zoomItY(m_pEnd->y());
205
206
207 // Calculate the direction vector from start -> end
208 vecX = m_pEnd->x() - m_pStart->x();
209 vecY = m_pEnd->y() - m_pStart->y();
210
211 // Normalize the vector
212 len = sqrt( vecX*vecX + vecY*vecY );
213 if( len )
214 {
215 vecX /= len;
216 vecY /= len;
217
218 // Move the endpoints by the cuts
219 x1 += vecX * zoomHandler->zoomItX(m_startAH->cut());
220 y1 += vecY * zoomHandler->zoomItY(m_startAH->cut());
221
222 x2 -= vecX * zoomHandler->zoomItX(m_endAH->cut());
223 y2 -= vecY * zoomHandler->zoomItY(m_endAH->cut());
224 }
225
226
227 // Draw the line
228 painter->drawLine( x1, y1, x2, y2 );
229
230
231 // Now draw the arrow heads
232 if( len )
233 {
234 painter->setBGColor( m_pFillStyle->color() );
235
236 m_startAH->paint(painter, m_pStart->x(), m_pStart->y(), -vecX, -vecY, zoomHandler);
237 m_endAH->paint(painter, m_pEnd->x(), m_pEnd->y(), vecX, vecY, zoomHandler);
238 }
239
240 // Text
241 drawText(pData);
242}
243
244void KivioStraightConnector::paintOutline( KivioIntraStencilData *pData )
245{
246 KivioPainter *painter = pData->painter;
247 KoZoomHandler* zoomHandler = pData->zoomHandler;
248 double x1, y1, x2, y2;
249 double vecX, vecY;
250 double len;
251
252
253 painter->setLineStyle(m_pLineStyle);
254 double lineWidth = m_pLineStyle->width();
255 painter->setLineWidth(zoomHandler->zoomItY(lineWidth));
256
257 x1 = zoomHandler->zoomItX(m_pStart->x());
258 x2 = zoomHandler->zoomItX(m_pEnd->x());
259
260 y1 = zoomHandler->zoomItY(m_pStart->y());
261 y2 = zoomHandler->zoomItY(m_pEnd->y());
262
263
264 // Calculate the direction vector from start -> end
265 vecX = m_pEnd->x() - m_pStart->x();
266 vecY = m_pEnd->y() - m_pStart->y();
267
268 // Normalize the vector
269 len = sqrt( vecX*vecX + vecY*vecY );
270 if( len )
271 {
272 vecX /= len;
273 vecY /= len;
274
275 // Move the endpoints by the cuts
276 x1 += vecX * zoomHandler->zoomItX(m_startAH->cut());
277 y1 += vecY * zoomHandler->zoomItY(m_startAH->cut());
278
279 x2 -= vecX * zoomHandler->zoomItX(m_endAH->cut());
280 y2 -= vecY * zoomHandler->zoomItY(m_endAH->cut());
281 }
282
283
284 // Draw the line
285 painter->drawLine( x1, y1, x2, y2 );
286
287
288 // Now draw the arrow heads
289 if( len )
290 {
291 painter->setBGColor( m_pFillStyle->color() );
292
293 m_startAH->paint(painter, m_pStart->x(), m_pStart->y(), -vecX, -vecY, zoomHandler);
294 m_endAH->paint(painter, m_pEnd->x(), m_pEnd->y(), vecX, vecY, zoomHandler);
295 }
296
297 // Text
298 // Don't paint text in outline mode as it makes moving harder
299 drawText(pData);
300}
301
302bool KivioStraightConnector::saveCustom( TQDomElement &e, TQDomDocument &doc )
303{
304 e.appendChild( saveArrowHeads(doc) );
305
306 return true;
307}
308
309bool KivioStraightConnector::loadCustom( const TQDomElement &e )
310{
311 TQDomNode node;
312 TQString name;
313
314 node = e.firstChild();
315 while( !node.isNull() )
316 {
317 name = node.nodeName();
318 if( name == "KivioArrowHeads" )
319 {
320 loadArrowHeads( node.toElement() );
321 }
322
323 node = node.nextSibling();
324 }
325
326 updateGeometry();
327
328 return true;
329}
330
331TQDomElement KivioStraightConnector::saveArrowHeads( TQDomDocument &doc )
332{
333 TQDomElement e = doc.createElement("KivioArrowHeads");
334
335 e.appendChild( m_startAH->saveXML(doc) );
336 e.appendChild( m_endAH->saveXML(doc) );
337
338 return e;
339}
340
341bool KivioStraightConnector::loadArrowHeads( const TQDomElement &e )
342{
343 TQDomNode node;
344 TQString nodeName;
345 TQDomElement arrowE;
346 bool first=true;
347
348 node = e.firstChild();
349 while( !node.isNull() )
350 {
351 nodeName = node.nodeName();
352 arrowE = node.toElement();
353
354 if( nodeName == "KivioArrowHead" )
355 {
356 if( first==true )
357 {
358 m_startAH->loadXML(arrowE);
359
360 first = false;
361 }
362 else
363 {
364 m_endAH->loadXML(arrowE);
365 }
366 }
367
368 node = node.nextSibling();
369 }
370
371 return true;
372}
373
374bool KivioStraightConnector::hasTextBox() const
375{
376 return true;
377}
378
379#include "straight_connector.moc"