kivio_base_connector_stencil.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
20/*
21 * Implementing a connector involves deriving from this class.
22 *
23 * You need to implement the following routines:
24 * setStartPoint
25 * setEndPoint
26 * checkForCollision
27 * duplicate
28 * paint
29 * paintOutline
30 * saveXML
31 * loadXML
32 *
33 * Save and Load should call saveConnectors, loadConnectors, saveProperties, and
34 * loadProperties. These are helper functions which take care of the common
35 * acts of saving/loading connectors and colors/line-styles, etc...
36 *
37 */
38
39#include "kivio_arrowhead.h"
40#include "kivio_base_connector_stencil.h"
41#include "kivio_common.h"
42#include "kivio_connector_point.h"
43#include "kivio_custom_drag_data.h"
44#include "kivio_fill_style.h"
45#include "kivio_intra_stencil_data.h"
46#include "kivio_layer.h"
47#include "kivio_line_style.h"
48#include "kivio_page.h"
49#include "kivio_painter.h"
50#include "kivio_point.h"
51#include "kivio_stencil.h"
52
53#include <kdebug.h>
54#include <KoZoomHandler.h>
55
62KivioBaseConnectorStencil::KivioBaseConnectorStencil()
63 : KivioStencil()
64{
65 m_pFillStyle = new KivioFillStyle();
66 m_pLineStyle = new KivioLineStyle();
67
68 m_pConnectorPoints = new TQPtrList<KivioConnectorPoint>;
69 m_pConnectorPoints->setAutoDelete(true);
70
71}
72
73
77KivioBaseConnectorStencil::~KivioBaseConnectorStencil()
78{
79 delete m_pFillStyle;
80 delete m_pLineStyle;
81 delete m_pConnectorPoints;
82}
83
84void KivioBaseConnectorStencil::setFGColor( TQColor c )
85{
86 m_pLineStyle->setColor(c);
87}
88
89TQColor KivioBaseConnectorStencil::fgColor()
90{
91 return m_pLineStyle->color();
92}
93
94void KivioBaseConnectorStencil::setLineWidth( double f )
95{
96 m_pLineStyle->setWidth(f);
97}
98
99double KivioBaseConnectorStencil::lineWidth()
100{
101 return m_pLineStyle->width();
102}
103
104void KivioBaseConnectorStencil::setBGColor( TQColor c )
105{
106 m_pFillStyle->setColor(c);
107}
108
109TQColor KivioBaseConnectorStencil::bgColor()
110{
111 return m_pFillStyle->color();
112}
113
114
116// Position functions
118void KivioBaseConnectorStencil::setX( double x )
119{
120 double dx = x - m_x;
121
122 m_x += dx;
123
124 KivioConnectorPoint *p = m_pConnectorPoints->first();
125 while( p )
126 {
127 p->setX( p->x() + dx, false );
128 p->disconnect();
129
130 p = m_pConnectorPoints->next();
131 }
132
133
134 m_x = x;
135}
136
137void KivioBaseConnectorStencil::setY( double y )
138{
139 double dy = y - m_y;
140
141 m_y += dy;
142
143 KivioConnectorPoint *p = m_pConnectorPoints->first();
144 while( p )
145 {
146 p->setY( p->y() + dy, false );
147 p->disconnect();
148
149 p = m_pConnectorPoints->next();
150 }
151
152 m_y = y;
153}
154
155void KivioBaseConnectorStencil::setPosition( double x, double y )
156{
157 double dx = x - m_x;
158 double dy = y - m_y;
159
160 m_x += dx;
161 m_y += dy;
162
163 KivioConnectorPoint *p = m_pConnectorPoints->first();
164 while( p )
165 {
166 p->setPosition( p->x()+dx, p->y()+dy, false );
167 p->disconnect();
168
169 p = m_pConnectorPoints->next();
170 }
171
172
173 m_x = x;
174 m_y = y;
175}
176
177
178
180// Connection tool functions
182void KivioBaseConnectorStencil::setStartPoint( double /*x*/, double /*y*/ )
183{
184 /* Derived class must implement this function */
185 // m_start.setPosition( x, y, false );
186 // m_start.disconnect();
187}
188
189
190void KivioBaseConnectorStencil::setEndPoint( double /*x*/, double /*y*/ )
191{
192 /* Derived class must implement this function */
193 // m_end.setPosition( x, y, false );
194 // m_end.disconnect();
195}
196
197
198void KivioBaseConnectorStencil::paint( KivioIntraStencilData * )
199{
200 /* Derived class must implement this */
201}
202
203void KivioBaseConnectorStencil::paintOutline( KivioIntraStencilData *pData )
204{
205 /* Derived class should implement this */
206 paint( pData );
207}
208
209void KivioBaseConnectorStencil::paintConnectorTargets( KivioIntraStencilData * )
210{
211}
212
213void KivioBaseConnectorStencil::paintSelectionHandles( KivioIntraStencilData *pData )
214{
215 // Handle Width
216 const double HW = 6.0f;
217 const double HWP1 = HW+1.0f;
218
219 // Handle Width Over 2
220 const double HWo2 = HW/2.0f;
221
222 // Stencil data
223 KoZoomHandler* zoomHandler = pData->zoomHandler;
224 KivioPainter *painter = pData->painter;
225 double x1, y1;
226
227 painter->setLineWidth(1.0f);
228 painter->setFGColor(TQColor(0,0,0));
229
230 KivioConnectorPoint *p = m_pConnectorPoints->first();
231 while( p )
232 {
233 x1 = zoomHandler->zoomItX(p->x()) - HWo2;
234 y1 = zoomHandler->zoomItY(p->y()) - HWo2;
235
236 if( p->target() )
237 painter->setBGColor(TQColor(200,0,0));
238 else
239 painter->setBGColor(TQColor(0,200,0));
240
241 painter->fillRect( x1, y1, HWP1, HWP1 );
242
243 p = m_pConnectorPoints->next();
244 }
245}
246
247
248
250// Collision detection
252KivioCollisionType KivioBaseConnectorStencil::checkForCollision( KoPoint *, double )
253{
254 /* Derived class must implement this */
255 return kctNone;
256}
257
258
259
260
262// Custom dragging
264
272void KivioBaseConnectorStencil::customDrag( KivioCustomDragData *pData )
273{
274 double _x = pData->x;
275 double _y = pData->y;
276 int id = pData->id;
277
278 KivioConnectorPoint *p;
279
280 // Locate the point specified by id
281 p = m_pConnectorPoints->at( id - (kctCustom+1));
282
283 if( !p )
284 {
285 kdDebug(43000) << "KivioBaseConnectorStencil::customDrag() - KivioConnectorPoint id: " << (id - (kctCustom+1)) << " not found\n" << endl;
286 return;
287 }
288
289 p->setPosition( _x, _y, true );
290
291
292 KivioLayer *pCurLayer = pData->page->curLayer();
293 KivioLayer *pLayer = pData->page->firstLayer(); //pData->page->curLayer();
294
295 while( pLayer )
296 {
297 // To be connected to, a layer must be visible and connectable
298 if( pLayer!=pCurLayer )
299 {
300 if( pLayer->connectable()==false || pLayer->visible()==false )
301 {
302 pLayer = pData->page->nextLayer();
303 continue;
304 }
305 }
306
307 // Tell the layer to search for a target
308 if( pLayer->connectPointToTarget( p, 8.0f ) )
309 {
310 return;
311 }
312
313 pLayer = pData->page->nextLayer();
314 }
315
316
317 // Nope, disconnect
318 p->disconnect();
319}
320
321
325void KivioBaseConnectorStencil::updateGeometry()
326{
327 double minX, minY, maxX, maxY;
328
329 minX = 1000000000000.0f;
330 minY = minX;
331 maxX = -100000000000.0f;
332 maxY = maxX;
333
334 KivioConnectorPoint *p;
335 p = m_pConnectorPoints->first();
336 while( p )
337 {
338 if( p->x() < minX )
339 minX = p->x();
340 if( p->x() > maxX )
341 maxX = p->x();
342 if( p->y() < minY )
343 minY = p->y();
344 if( p->y() > maxY )
345 maxY = p->y();
346
347 p = m_pConnectorPoints->next();
348 }
349
350 m_x = minX;
351 m_y = minY;
352 m_w = maxX - minX + 1.0f;
353 m_h = maxY - minY + 1.0f;
354}
355
356
357
358// file i/o routines
359bool KivioBaseConnectorStencil::loadXML( const TQDomElement & )
360{
361 return false;
362}
363
364TQDomElement KivioBaseConnectorStencil::saveXML( TQDomDocument & )
365{
366 return TQDomElement();
367}
368
369
370
371KivioStencil *KivioBaseConnectorStencil::duplicate()
372{
373 /* Derived class must implement this function */
374 return NULL;
375}
376
377
378bool KivioBaseConnectorStencil::boolAllTrue( bool *boolArray, int count )
379{
380 int i;
381
382 for( i=0; i<count; i++ )
383 {
384 if( boolArray[i]==false )
385 return false;
386 }
387
388 return true;
389}
390
391bool KivioBaseConnectorStencil::boolContainsFalse( bool *boolArray, int count )
392{
393 int i;
394
395 for( i=0; i<count; i++ )
396 {
397 if( boolArray[i]==false )
398 return true;
399 }
400
401 return false;
402}
403
404
405void KivioBaseConnectorStencil::searchForConnections( KivioPage *pPage )
406{
407 bool *done = new bool[ m_pConnectorPoints->count() ];
408
409 int i;
410
411 for( i=0; i<(int)m_pConnectorPoints->count(); i++ )
412 done[i] = false;
413
414 KivioConnectorPoint *p;
415
416 i=0;
417 p = m_pConnectorPoints->first();
418 while( p )
419 {
420 if( p->targetId() == -1 )
421 done[i] = true;
422
423 i++;
424 p = m_pConnectorPoints->next();
425 }
426
427
428 // No connections? BaiL!
429 if( boolAllTrue( done, m_pConnectorPoints->count() ) )
430 {
431 delete [] done;
432 return;
433 }
434
435
436
437 KivioLayer *pLayer = pPage->firstLayer();
438 while( pLayer && ( boolContainsFalse(done, m_pConnectorPoints->count()) ) )
439 {
440 KivioStencil *pStencil = pLayer->firstStencil();
441
442 while( pStencil && ( boolContainsFalse(done, m_pConnectorPoints->count()) ) )
443 {
444 // No connecting to ourself!
445 if( pStencil != this )
446 {
447
448 // Iterate through all connectors attempting to connect it to the stencil.
449 // If it connects, mark it as done
450 i=0;
451 p = m_pConnectorPoints->first();
452 while( p )
453 {
454 if( !done[i] &&
455 p->targetId() != -1 )
456 {
457 if( pStencil->connectToTarget( p, p->targetId() ) )
458 {
459 done[i] = true;
460 }
461 }
462
463 i++;
464 p = m_pConnectorPoints->next();
465 }
466
467 }
468
469 pStencil = pLayer->nextStencil();
470 }
471
472 pLayer = pPage->nextLayer();
473 }
474
475 delete [] done;
476}
477
478
480// resize handles
482int KivioBaseConnectorStencil::resizeHandlePositions()
483{
484 return (int)krhpNone;
485}
486
487TQDomElement KivioBaseConnectorStencil::saveConnectors( TQDomDocument &doc )
488{
489 TQDomElement eConns = doc.createElement("KivioConnectors");
490
491 KivioConnectorPoint *p;
492 p = m_pConnectorPoints->first();
493 while( p )
494 {
495 eConns.appendChild( p->saveXML(doc) );
496
497 p = m_pConnectorPoints->next();
498 }
499
500 return eConns;
501}
502
503bool KivioBaseConnectorStencil::loadConnectors( const TQDomElement &e )
504{
505 m_pConnectorPoints->clear();
506
507 KivioConnectorPoint *p;
508
509 TQDomNode node = e.firstChild();
510 TQDomElement e2;
511 TQString name;
512
513 while( !node.isNull() )
514 {
515 e2 = node.toElement();
516 name = e2.nodeName();
517
518 if( name == "KivioConnectorPoint" )
519 {
520 p = new KivioConnectorPoint();
521 p->setStencil(this);
522 p->loadXML( e2 );
523
524 m_pConnectorPoints->append( p );
525 p = NULL;
526 }
527
528 node = node.nextSibling();
529 }
530
531 return true;
532}
533
534TQDomElement KivioBaseConnectorStencil::saveProperties( TQDomDocument &doc )
535{
536 TQDomElement propE = doc.createElement("KivioConnectorProperties");
537
538 propE.appendChild( m_pLineStyle->saveXML( doc ) );
539
540 propE.appendChild( m_pFillStyle->saveXML( doc ) );
541
542 return propE;
543}
544
545bool KivioBaseConnectorStencil::loadProperties( const TQDomElement &e )
546{
547 TQDomNode node;
548 TQString nodeName;
549
550 node = e.firstChild();
551 while( !node.isNull() )
552 {
553 nodeName = node.nodeName();
554 if( nodeName == "KivioFillStyle" )
555 {
556 m_pFillStyle->loadXML( node.toElement() );
557 }
558 else if( nodeName == "KivioLineStyle" )
559 {
560 m_pLineStyle->loadXML( node.toElement() );
561 }
562
563 node = node.nextSibling();
564 }
565
566 return true;
567}