kivio

kivio_1d_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_1d_stencil.h"
40#include "kivio_arrowhead.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#include "kivio_stencil_spawner.h"
53#include "kivio_stencil_spawner_info.h"
54#include "kivio_stencil_spawner_set.h"
55#include "kivio_text_style.h"
56#include "kivio_connector_target.h"
57
58#include <kdebug.h>
59#include <math.h>
60#include <KoZoomHandler.h>
61
62#include <tqbitmap.h>
63#include <tqpainter.h>
64
71Kivio1DStencil::Kivio1DStencil()
72 : KivioStencil()
73{
74 m_pFillStyle = new KivioFillStyle();
75 m_pLineStyle = new KivioLineStyle();
76 m_pTextStyle = new KivioTextStyle();
77
78 m_pConnectorPoints = new TQPtrList<KivioConnectorPoint>;
79 m_pConnectorPoints->setAutoDelete(true);
80
81 m_pStart = new KivioConnectorPoint(this, true);
82 m_pStart->setPosition(72.0f, 18.0f, false);
83
84 m_pEnd = new KivioConnectorPoint(this, true);
85 m_pEnd->setPosition(0.0f, 18.0f, false);
86
87 m_pLeft = new KivioConnectorPoint(this, false);
88 m_pLeft->setPosition(36.0f, 36.0f, false);
89
90 m_pRight = new KivioConnectorPoint(this, false);
91 m_pRight->setPosition(36.0f, 0.0f, false);
92
93 m_pTextConn = new KivioConnectorPoint(this, false);
94 m_pTextConn->setPosition(36.0f, 18.0f, false);
95
96 m_connectorWidth = 36.0f;
97 m_needsWidth = true;
98 m_needsText = false;
99
100 m_pConnectorPoints->append( m_pStart );
101 m_pConnectorPoints->append( m_pEnd );
102 m_pConnectorPoints->append( m_pLeft );
103 m_pConnectorPoints->append( m_pRight );
104 m_pConnectorPoints->append( m_pTextConn );
105}
106
107
111Kivio1DStencil::~Kivio1DStencil()
112{
113 delete m_pFillStyle;
114 delete m_pLineStyle;
115 delete m_pTextStyle;
116 delete m_pConnectorPoints;
117}
118
119void Kivio1DStencil::setFGColor( TQColor c )
120{
121 m_pLineStyle->setColor(c);
122}
123
124TQColor Kivio1DStencil::fgColor()
125{
126 return m_pLineStyle->color();
127}
128
129void Kivio1DStencil::setLineWidth( double f )
130{
131 m_pLineStyle->setWidth(f);
132}
133
134double Kivio1DStencil::lineWidth()
135{
136 return m_pLineStyle->width();
137}
138
139void Kivio1DStencil::setLinePattern(int p)
140{
141 m_pLineStyle->setStyle(p);
142}
143
144int Kivio1DStencil::linePattern()
145{
146 return m_pLineStyle->style();
147}
148
149void Kivio1DStencil::setFillPattern(int p)
150{
151 m_pFillStyle->setBrushStyle(static_cast<TQt::BrushStyle>(p));
152}
153
154int Kivio1DStencil::fillPattern()
155{
156 return m_pFillStyle->brushStyle();
157}
158
159void Kivio1DStencil::setBGColor( TQColor c )
160{
161 m_pFillStyle->setColor(c);
162}
163
164TQColor Kivio1DStencil::bgColor()
165{
166 return m_pFillStyle->color();
167}
168
169
171// Position functions
173void Kivio1DStencil::setX( double x )
174{
175 double dx = x - m_x;
176 KivioConnectorPoint *p = m_pConnectorPoints->first();
177
178 while( p )
179 {
180 p->disconnect();
181 p->setX( p->x() + dx, false );
182 p = m_pConnectorPoints->next();
183 }
184
185 m_x = x;
186}
187
188void Kivio1DStencil::setY( double y )
189{
190 double dy = y - m_y;
191 KivioConnectorPoint *p = m_pConnectorPoints->first();
192
193 while( p )
194 {
195 p->disconnect();
196 p->setY( p->y() + dy, false );
197 p = m_pConnectorPoints->next();
198 }
199
200 m_y = y;
201}
202
203void Kivio1DStencil::setPosition( double x, double y )
204{
205 double dx = x - m_x;
206 double dy = y - m_y;
207
208 m_x += dx;
209 m_y += dy;
210
211 KivioConnectorPoint *p = m_pConnectorPoints->first();
212 while( p )
213 {
214 p->setPosition( p->x()+dx, p->y()+dy, false );
215 p->disconnect();
216
217 p = m_pConnectorPoints->next();
218 }
219
220
221 m_x = x;
222 m_y = y;
223}
224
225
226
228// Connection tool functions
230void Kivio1DStencil::setStartPoint( double x, double y )
231{
232 double oldX = m_pStart->x();
233 double oldY = m_pStart->y();
234
235 m_pStart->setPosition(x, y, false);
236 m_pStart->disconnect();
237
238 updateConnectorPoints(m_pStart, oldX, oldY);
239}
240
241
242void Kivio1DStencil::setEndPoint( double x, double y )
243{
244 double oldX = m_pEnd->x();
245 double oldY = m_pEnd->y();
246
247 m_pEnd->setPosition(x, y, false);
248 m_pEnd->disconnect();
249
250 updateConnectorPoints(m_pEnd, oldX, oldY);
251}
252
253void Kivio1DStencil::updateConnectorPoints( KivioConnectorPoint *p, double /*oldX*/, double /*oldY*/ )
254{
255 // If p is the start or end, we need to adjust the width connectors
256 if( p == m_pStart || p == m_pEnd )
257 {
258 double vx = m_pStart->x() - m_pEnd->x();
259 double vy = m_pStart->y() - m_pEnd->y();
260 double len = sqrt( vx*vx + vy*vy );
261 double midX = (m_pStart->x() + m_pEnd->x())/2.0f;
262 double midY = (m_pStart->y() + m_pEnd->y())/2.0f;
263
264 vx /= len;
265 vy /= len;
266
267 double d = m_connectorWidth/2.0f;
268
269 m_pLeft->setPosition( midX + d*vy, midY + d*(-vx), false );
270 m_pRight->setPosition( midX + d*(-vy), midY + d*vx, false );
271 }
272
273 updateGeometry();
274}
275
276
277void Kivio1DStencil::paint( KivioIntraStencilData * )
278{
279 /* Derived class must implement this */
280}
281
282void Kivio1DStencil::paintOutline( KivioIntraStencilData *pData )
283{
284 /* Derived class should implement this */
285 paint( pData );
286}
287
288void Kivio1DStencil::paintConnectorTargets( KivioIntraStencilData * )
289{
290}
291
292void Kivio1DStencil::paintSelectionHandles( KivioIntraStencilData *pData )
293{
294 KivioPainter *painter = pData->painter;
295 double x1, y1;
296 int flag;
297
298 KoZoomHandler* zoomHandler = pData->zoomHandler;
299
300 KivioConnectorPoint *p = m_pConnectorPoints->first();
301 while( p )
302 {
303 // If we don't need width connectors and we are on a width connector,
304 // ignore it.
305 x1 = zoomHandler->zoomItX(p->x());
306 y1 = zoomHandler->zoomItY(p->y());
307
308 flag = (p->target()) ? KivioPainter::cpfConnected : 0;
309
310 if( p==m_pTextConn )
311 {
312 if( m_needsText==true )
313 {
314 painter->drawHandle( x1, y1, 0 );
315 }
316 }
317 else if( p==m_pLeft || p==m_pRight )
318 {
319 if( m_needsWidth==true )
320 {
321 painter->drawHandle( x1, y1, 0 );
322 }
323 }
324 else if( p==m_pStart )
325 {
326 painter->drawHandle( x1, y1, KivioPainter::cpfStart | flag );
327 }
328 else if( p==m_pEnd )
329 {
330 painter->drawHandle( x1, y1, KivioPainter::cpfEnd | flag );
331 }
332 else
333 {
334 if( p->connectable() ) {
335 painter->drawHandle( x1, y1, KivioPainter::cpfConnectable | flag );
336 } else {
337 painter->drawHandle( x1, y1, flag );
338 }
339 }
340
341 p = m_pConnectorPoints->next();
342 }
343}
344
345
346
348// Collision detection
350KivioCollisionType Kivio1DStencil::checkForCollision( KoPoint *, double )
351{
352 /* Derived class must implement this */
353
354 return kctNone;
355}
356
357
358
359
361// Custom dragging
363
371void Kivio1DStencil::customDrag( KivioCustomDragData *pData )
372{
373 setCustomIDPoint(pData->id, KoPoint(pData->x, pData->y), pData->page);
374}
375
376
380void Kivio1DStencil::updateGeometry()
381{
382 double minX, minY, maxX, maxY;
383
384 minX = 1000000000000.0f;
385 minY = minX;
386 maxX = -100000000000.0f;
387 maxY = maxX;
388
389
390 KivioConnectorPoint *p;
391 p = m_pConnectorPoints->first();
392 while( p )
393 {
394 if( p->x() < minX )
395 minX = p->x();
396 if( p->x() > maxX )
397 maxX = p->x();
398 if( p->y() < minY )
399 minY = p->y();
400 if( p->y() > maxY )
401 maxY = p->y();
402
403 p = m_pConnectorPoints->next();
404 }
405
406
407 m_x = minX;
408 m_y = minY;
409 m_w = maxX - minX + 1.0f;
410 m_h = maxY - minY + 1.0f;
411}
412
413
414
415// file i/o routines
416bool Kivio1DStencil::loadXML( const TQDomElement &e )
417{
418 TQDomNode node;
419 TQString name;
420
421 node = e.firstChild();
422 while( !node.isNull() )
423 {
424 name = node.nodeName();
425
426 if( name == "KivioStencilProperties" )
427 {
428 loadProperties(node.toElement() );
429 }
430
431 node = node.nextSibling();
432 }
433
434 updateGeometry();
435
436 return true;
437}
438
439
440TQDomElement Kivio1DStencil::createRootElement( TQDomDocument &doc )
441{
442 TQDomElement e = doc.createElement("KivioPluginStencil");
443
444 XmlWriteString( e, "id", m_pSpawner->info()->id() );
445 XmlWriteString( e, "setId", m_pSpawner->set()->id() );
446
447 return e;
448}
449
450
451TQDomElement Kivio1DStencil::saveXML( TQDomDocument &doc )
452{
453 TQDomElement e = createRootElement(doc);
454
455 e.appendChild( saveProperties(doc) );
456
457 return e;
458}
459
460
461
462KivioStencil *Kivio1DStencil::duplicate()
463{
464 /* Derived class must implement this function */
465 return NULL;
466}
467
468
469bool Kivio1DStencil::boolAllTrue( bool *boolArray, int count )
470{
471 int i;
472
473 for( i=0; i<count; i++ )
474 {
475 if( boolArray[i]==false )
476 return false;
477 }
478
479 return true;
480}
481
482bool Kivio1DStencil::boolContainsFalse( bool *boolArray, int count )
483{
484 int i;
485
486 for( i=0; i<count; i++ )
487 {
488 if( boolArray[i]==false )
489 return true;
490 }
491
492 return false;
493}
494
495void Kivio1DStencil::searchForConnections( KivioPage *pPage )
496{
497 bool *done = new bool[ m_pConnectorPoints->count()];
498 unsigned int i;
499
500 for(i = 0; i < m_pConnectorPoints->count(); i++) {
501 done[i] = false;
502 }
503
504 KivioConnectorPoint *p;
505 i = 0;
506 p = m_pConnectorPoints->first();
507
508 while( p )
509 {
510 if( p->targetId() == -1 ) {
511 done[i] = true;
512 }
513
514 i++;
515 p = m_pConnectorPoints->next();
516 }
517
518 // No connections? BaiL!
519 if( boolAllTrue( done, m_pConnectorPoints->count() ) )
520 {
521 delete [] done;
522 return;
523 }
524
525 KivioLayer *pLayer = pPage->firstLayer();
526
527 while( pLayer && ( boolContainsFalse(done, m_pConnectorPoints->count()) ) )
528 {
529 KivioStencil *pStencil = pLayer->firstStencil();
530
531 while( pStencil && ( boolContainsFalse(done, m_pConnectorPoints->count()) ) )
532 {
533 // No connecting to ourself!
534 if((pStencil != this))
535 {
536
537 // Iterate through all connectors attempting to connect it to the stencil.
538 // If it connects, mark it as done
539 i=0;
540 p = m_pConnectorPoints->first();
541 while( p )
542 {
543 if( !done[i] && p->targetId() != -1 )
544 {
545 if(pStencil->connectToTarget( p, p->targetId()))
546 {
547 done[i] = true;
548 }
549 }
550
551 i++;
552 p = m_pConnectorPoints->next();
553 }
554
555 }
556
557 pStencil = pLayer->nextStencil();
558 }
559
560 pLayer = pPage->nextLayer();
561 }
562
563 delete [] done;
564}
565
566void Kivio1DStencil::searchForConnections( KivioPage *pPage, double threshold )
567{
568 bool *done = new bool[ m_pConnectorPoints->count()];
569 int i;
570
571 for( i=0; i<(int)m_pConnectorPoints->count(); i++ ) {
572 done[i] = false;
573 }
574
575 KivioConnectorPoint *p;
576 i = 0;
577 p = m_pConnectorPoints->first();
578
579 while( p )
580 {
581 if(p->target() != 0L) {
582 done[i] = true;
583 }
584
585 i++;
586 p = m_pConnectorPoints->next();
587 }
588
589 // No connections? BaiL!
590 if( boolAllTrue( done, m_pConnectorPoints->count() ) )
591 {
592 delete [] done;
593 return;
594 }
595
596 KivioLayer *pLayer = pPage->firstLayer();
597
598 while( pLayer && ( boolContainsFalse(done, m_pConnectorPoints->count()) ) )
599 {
600 KivioStencil *pStencil = pLayer->firstStencil();
601
602 while( pStencil && ( boolContainsFalse(done, m_pConnectorPoints->count()) ) )
603 {
604 // No connecting to ourself!
605 if( pStencil != this )
606 {
607
608 // Iterate through all connectors attempting to connect it to the stencil.
609 // If it connects, mark it as done
610 i = 0;
611 p = m_pConnectorPoints->first();
612
613 while( p )
614 {
615 if( !done[i] && p->target() == 0 )
616 {
617 if( pStencil->connectToTarget( p, threshold ) )
618 {
619 done[i] = true;
620 }
621 }
622
623 i++;
624 p = m_pConnectorPoints->next();
625 }
626
627 }
628
629 pStencil = pLayer->nextStencil();
630 }
631
632 pLayer = pPage->nextLayer();
633 }
634
635 delete [] done;
636}
637
639// resize handles
641int Kivio1DStencil::resizeHandlePositions()
642{
643 return (int)krhpNone;
644}
645
646TQDomElement Kivio1DStencil::saveConnectors( TQDomDocument &doc )
647{
648 TQDomElement eConns = doc.createElement("KivioConnectorList");
649
650 KivioConnectorPoint *p;
651 p = m_pConnectorPoints->first();
652 while( p )
653 {
654 eConns.appendChild( p->saveXML(doc) );
655
656 p = m_pConnectorPoints->next();
657 }
658
659 return eConns;
660}
661
662bool Kivio1DStencil::loadConnectors( const TQDomElement &e )
663{
664 m_pConnectorPoints->clear();
665
666 KivioConnectorPoint *p;
667
668 TQDomNode node = e.firstChild();
669 TQDomElement e2;
670 TQString name;
671
672 while( !node.isNull() )
673 {
674 e2 = node.toElement();
675 name = e2.nodeName();
676
677 if( name == "KivioConnectorPoint" )
678 {
679 p = new KivioConnectorPoint();
680 p->setStencil(this);
681 p->loadXML( e2 );
682
683 m_pConnectorPoints->append( p );
684 p = NULL;
685 }
686
687 node = node.nextSibling();
688 }
689
690 // Set the pointers to the start,end,left,right points
691 m_pStart = m_pConnectorPoints->first();
692 m_pEnd = m_pConnectorPoints->next();
693 m_pLeft = m_pConnectorPoints->next();
694 m_pRight = m_pConnectorPoints->next();
695 m_pTextConn = m_pConnectorPoints->next();
696
697 // Hopefully this will help with backwards compatibility
698 if( m_pStart == NULL ) {
699 m_pStart = new KivioConnectorPoint(this, true);
700 }
701 if( m_pEnd == NULL ) {
702 m_pEnd = new KivioConnectorPoint(this, true);
703 }
704 if( m_pLeft == NULL ) {
705 m_pLeft = new KivioConnectorPoint(this, false);
706 }
707 if( m_pRight == NULL ) {
708 m_pRight = new KivioConnectorPoint(this, false);
709 }
710 if( m_pTextConn == NULL ) {
711 m_pTextConn = new KivioConnectorPoint(this, false);
712 }
713
714
715 return true;
716}
717
718TQDomElement Kivio1DStencil::saveProperties( TQDomDocument &doc )
719{
720 TQDomElement propE = doc.createElement("KivioStencilProperties");
721
722 TQDomElement connE = doc.createElement("Kivio1DProperties");
723 XmlWriteFloat( connE, "connectorWidth", m_connectorWidth );
724 XmlWriteInt( connE, "needsWidth", m_needsWidth );
725 propE.appendChild( connE );
726
727 propE.appendChild( m_pLineStyle->saveXML( doc ) );
728
729 propE.appendChild( m_pFillStyle->saveXML( doc ) );
730
731 propE.appendChild( m_pTextStyle->saveXML( doc ) );
732
733 propE.appendChild( saveConnectors(doc) );
734
735 TQDomElement customE = doc.createElement("CustomData");
736 if( saveCustom( customE, doc )==true )
737 {
738 propE.appendChild( customE );
739 }
740
741 return propE;
742}
743
744bool Kivio1DStencil::loadProperties( const TQDomElement &e )
745{
746 TQDomNode node;
747 TQDomElement nodeE;
748 TQString nodeName;
749
750 node = e.firstChild();
751 while( !node.isNull() )
752 {
753 nodeE = node.toElement();
754 nodeName = node.nodeName();
755
756 if( nodeName == "KivioFillStyle" )
757 {
758 m_pFillStyle->loadXML( nodeE );
759 }
760 else if( nodeName == "KivioLineStyle" )
761 {
762 m_pLineStyle->loadXML( nodeE );
763 }
764 else if( nodeName == "KivioTextStyle" )
765 {
766 m_pTextStyle->loadXML( nodeE );
767 }
768 else if( nodeName == "KivioConnectorList" )
769 {
770 loadConnectors( nodeE );
771 }
772 else if( nodeName == "Kivio1DProperties" )
773 {
774 m_needsWidth = (bool)XmlReadInt( nodeE, "needsWidth", (int)true );
775 m_connectorWidth = XmlReadFloat( nodeE, "connectorWidth", 36.0f );
776 }
777 else if( nodeName == "CustomData" )
778 {
779 loadCustom( nodeE );
780 }
781
782 node = node.nextSibling();
783 }
784
785 return true;
786}
787
788bool Kivio1DStencil::loadCustom( const TQDomElement & )
789{
790 return true;
791}
792
793bool Kivio1DStencil::saveCustom( TQDomElement &, TQDomDocument & )
794{
795 return false;
796}
797
798void Kivio1DStencil::copyBasicInto( Kivio1DStencil *pStencil )
799{
800 KivioConnectorPoint *pSrc, *pTg;
801
802 // Copy the spawner
803 pStencil->setSpawner( m_pSpawner );
804
805 // Copy the connector points
806 pSrc = m_pConnectorPoints->first();
807 pTg = pStencil->m_pConnectorPoints->first();
808 while( pSrc && pTg )
809 {
810 pTg->setPosition( pSrc->x(), pSrc->y(), false );
811
812 pSrc = m_pConnectorPoints->next();
813 pTg = pStencil->m_pConnectorPoints->next();
814 }
815
816 // Copy the dimensions
817 pStencil->m_x = m_x;
818 pStencil->m_y = m_y;
819 pStencil->m_w = m_w;
820 pStencil->m_h = m_h;
821
822 // Copy over the width info
823 pStencil->m_connectorWidth = m_connectorWidth;
824 pStencil->m_needsWidth = m_needsWidth;
825
826 // Copy over the styles
827 m_pFillStyle->copyInto( pStencil->m_pFillStyle );
828 m_pLineStyle->copyInto( pStencil->m_pLineStyle );
829 m_pTextStyle->copyInto( pStencil->m_pTextStyle );
830
831 // Copy over the protection
832 *(pStencil->m_pProtection) = *m_pProtection;
833 *(pStencil->m_pCanProtect) = *m_pCanProtect;
834}
835
836void Kivio1DStencil::drawText( KivioIntraStencilData *pData )
837{
838 if(m_pTextStyle->text().isEmpty()) {
839 return;
840 }
841
842 KoZoomHandler* zoomHandler = pData->zoomHandler;
843 KivioPainter *painter = pData->painter;
844
845 int _x, _y, _w, _h;
846
847 _x = zoomHandler->zoomItX(m_pTextConn->x());
848 _y = zoomHandler->zoomItY(m_pTextConn->y());
849 _w = 10000000;
850 _h = 10000000;
851
852 TQFont f = m_pTextStyle->font();
853 int tf = m_pTextStyle->hTextAlign() | m_pTextStyle->vTextAlign();
854
855 f.setPointSizeFloat(f.pointSizeFloat() * (((float)zoomHandler->zoom()) / 100.0));
856 painter->setFont(f);
857 TQRect boundRect = painter->boundingRect( _x, _y, _w, _h, tf, m_pTextStyle->text() );
858 TQPixmap pix(boundRect.width(), boundRect.height());
859 pix.fill();
860 TQPainter p(&pix);
861 p.setPen(m_pTextStyle->color());
862 p.setFont(f);
863 p.drawText( 0, 0, boundRect.width(), boundRect.height(), tf, m_pTextStyle->text() );
864 TQBitmap mask;
865 mask = pix;
866 pix.setMask(mask);
867 painter->drawPixmap(_x, _y, pix);
868}
869
870bool Kivio1DStencil::connected()
871{
872 KivioConnectorPoint *p;
873 p = m_pConnectorPoints->first();
874
875 while( p )
876 {
877 if(p->target() != 0) {
878 return true;
879 }
880
881 p = m_pConnectorPoints->next();
882 }
883
884 return false;
885}
886
887void Kivio1DStencil::disconnectFromTargets()
888{
889 KivioConnectorPoint *p;
890 p = m_pConnectorPoints->first();
891
892 while( p )
893 {
894 p->disconnect(true);
895 p = m_pConnectorPoints->next();
896 }
897}
898
899KivioLineStyle Kivio1DStencil::lineStyle()
900{
901 return *m_pLineStyle;
902}
903
904void Kivio1DStencil::setLineStyle(KivioLineStyle ls)
905{
906 ls.copyInto(m_pLineStyle);
907}
908
909void Kivio1DStencil::setCustomIDPoint(int customID, const KoPoint& point, KivioPage* page)
910{
911 double oldX, oldY;
912 KivioConnectorPoint *p;
913
914 // Locate the point specified by customID
915 p = m_pConnectorPoints->at( customID - (kctCustom+1));
916
917 if( !p )
918 {
919 kdDebug(43000) << "Kivio1DStencil::customDrag() - KivioConnectorPoint customID: " << (customID - (kctCustom+1)) << " not found\n" << endl;
920 return;
921 }
922
923 oldX = p->x();
924 oldY = p->y();
925 p->setPosition(point.x(),point.y(),true);
926
927 if( p->connectable()==true )
928 {
929 // Attempt a snap....
930 KivioLayer *pCurLayer = page->curLayer();
931 KivioLayer *pLayer = page->firstLayer(); //page->curLayer();
932 bool foundConnection = false;
933
934 while( pLayer && !foundConnection )
935 {
936 // To be connected to, a layer must be visible and connectable
937 if( pLayer!=pCurLayer )
938 {
939 if( pLayer->connectable()==false || pLayer->visible()==false )
940 {
941 pLayer = page->nextLayer();
942 continue;
943 }
944 }
945
946 // Tell the layer to search for a target
947 if( pLayer->connectPointToTarget( p, 8.0f ) )
948 {
949 foundConnection = true;
950 }
951
952 pLayer = page->nextLayer();
953 }
954
955 if( foundConnection == false )
956 {
957 p->disconnect();
958 }
959 }
960
961 // If it is a start/end point, then make a request to update the connectors (must be implemented by stencil developer)
962 if( customID == kctCustom+1 || customID == kctCustom+2 )
963 {
964 // If it's the end connector, then update the text point
965 if( p==m_pEnd && m_needsText==true )
966 {
967 m_pTextConn->setPosition( m_pTextConn->x() + (m_pEnd->x() - oldX),
968 m_pTextConn->y() + (m_pEnd->y() - oldY), false );
969 }
970
971 updateConnectorPoints(p, oldX, oldY);
972 }
973 // If it is one of the width handles, then fix the width and update the opposite point
974 // only if the stencils 'needs width' connectors
975 else if( (customID == kctCustom+3 || customID == kctCustom+4) && (m_needsWidth==true) )
976 {
977 double vx = m_pStart->x() - m_pEnd->x();
978 double vy = m_pStart->y() - m_pEnd->y();
979 double len = sqrt( vx*vx + vy*vy );
980 double midX = (m_pStart->x() + m_pEnd->x())/2.0f;
981 double midY = (m_pStart->y() + m_pEnd->y())/2.0f;
982
983 vx /= len;
984 vy /= len;
985
986 double d = shortestDistance( m_pStart, m_pEnd, (customID==kctCustom+3) ? m_pLeft : m_pRight );
987
988 m_pLeft->setPosition( midX + d*vy, midY + d*(-vx), false );
989 m_pRight->setPosition( midX + d*(-vy), midY + d*vx, false );
990
991 m_connectorWidth = d*2.0f;
992
993 updateConnectorPoints(p, oldX, oldY);
994 return;
995 }
996 // Text handle
997 else if( customID == kctCustom+5 )
998 {
999 updateConnectorPoints(p, oldX, oldY);
1000 }
1001}
1002
1003KoPoint Kivio1DStencil::customIDPoint(int customID)
1004{
1005 KivioConnectorPoint *p;
1006
1007 // Locate the point specified by customID
1008 p = m_pConnectorPoints->at( customID - (kctCustom+1));
1009
1010 return p->position();
1011}