kivio

kivio_base_connector_stencil.cpp

00001 /*
00002  * Kivio - Visual Modelling and Flowcharting
00003  * Copyright (C) 2000-2001 theKompany.com & Dave Marotti
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00018  */
00019 
00020 /*
00021  * Implementing a connector involves deriving from this class.
00022  *
00023  * You need to implement the following routines:
00024  *   setStartPoint
00025  *   setEndPoint
00026  *   checkForCollision
00027  *   duplicate
00028  *   paint
00029  *   paintOutline
00030  *   saveXML
00031  *   loadXML
00032  *
00033  * Save and Load should call saveConnectors, loadConnectors, saveProperties, and
00034  * loadProperties.  These are helper functions which take care of the common
00035  * acts of saving/loading connectors and colors/line-styles, etc...
00036  *
00037  */
00038 
00039 #include "kivio_arrowhead.h"
00040 #include "kivio_base_connector_stencil.h"
00041 #include "kivio_common.h"
00042 #include "kivio_connector_point.h"
00043 #include "kivio_custom_drag_data.h"
00044 #include "kivio_fill_style.h"
00045 #include "kivio_intra_stencil_data.h"
00046 #include "kivio_layer.h"
00047 #include "kivio_line_style.h"
00048 #include "kivio_page.h"
00049 #include "kivio_painter.h"
00050 #include "kivio_point.h"
00051 #include "kivio_stencil.h"
00052 
00053 #include <kdebug.h>
00054 #include <KoZoomHandler.h>
00055 
00062 KivioBaseConnectorStencil::KivioBaseConnectorStencil()
00063     : KivioStencil()
00064 {
00065     m_pFillStyle = new KivioFillStyle();
00066     m_pLineStyle = new KivioLineStyle();
00067 
00068     m_pConnectorPoints = new QPtrList<KivioConnectorPoint>;
00069     m_pConnectorPoints->setAutoDelete(true);
00070 
00071 }
00072 
00073 
00077 KivioBaseConnectorStencil::~KivioBaseConnectorStencil()
00078 {
00079     delete m_pFillStyle;
00080     delete m_pLineStyle;
00081     delete m_pConnectorPoints;
00082 }
00083 
00084 void KivioBaseConnectorStencil::setFGColor( QColor c )
00085 {
00086     m_pLineStyle->setColor(c);
00087 }
00088 
00089 QColor KivioBaseConnectorStencil::fgColor()
00090 {
00091     return m_pLineStyle->color();
00092 }
00093 
00094 void KivioBaseConnectorStencil::setLineWidth( double f )
00095 {
00096     m_pLineStyle->setWidth(f);
00097 }
00098 
00099 double KivioBaseConnectorStencil::lineWidth()
00100 {
00101     return m_pLineStyle->width();
00102 }
00103 
00104 void KivioBaseConnectorStencil::setBGColor( QColor c )
00105 {
00106     m_pFillStyle->setColor(c);
00107 }
00108 
00109 QColor KivioBaseConnectorStencil::bgColor()
00110 {
00111     return m_pFillStyle->color();
00112 }
00113 
00114 
00116 // Position functions
00118 void KivioBaseConnectorStencil::setX( double x )
00119 {
00120     double dx = x - m_x;
00121 
00122     m_x += dx;
00123 
00124     KivioConnectorPoint *p = m_pConnectorPoints->first();
00125     while( p )
00126     {
00127         p->setX( p->x() + dx, false );
00128         p->disconnect();
00129 
00130         p = m_pConnectorPoints->next();
00131     }
00132 
00133 
00134     m_x = x;
00135 }
00136 
00137 void KivioBaseConnectorStencil::setY( double y )
00138 {
00139     double dy = y - m_y;
00140 
00141     m_y += dy;
00142 
00143     KivioConnectorPoint *p = m_pConnectorPoints->first();
00144     while( p )
00145     {
00146         p->setY( p->y() + dy, false );
00147         p->disconnect();
00148 
00149         p = m_pConnectorPoints->next();
00150     }
00151 
00152     m_y = y;
00153 }
00154 
00155 void KivioBaseConnectorStencil::setPosition( double x, double y )
00156 {
00157     double dx = x - m_x;
00158     double dy = y - m_y;
00159 
00160     m_x += dx;
00161     m_y += dy;
00162 
00163     KivioConnectorPoint *p = m_pConnectorPoints->first();
00164     while( p )
00165     {
00166         p->setPosition( p->x()+dx, p->y()+dy, false );
00167         p->disconnect();
00168 
00169         p = m_pConnectorPoints->next();
00170     }
00171 
00172 
00173     m_x = x;
00174     m_y = y;
00175 }
00176 
00177 
00178 
00180 // Connection tool functions
00182 void KivioBaseConnectorStencil::setStartPoint( double /*x*/, double /*y*/ )
00183 {
00184     /* Derived class must implement this function */
00185     // m_start.setPosition( x, y, false );
00186     // m_start.disconnect();
00187 }
00188 
00189 
00190 void KivioBaseConnectorStencil::setEndPoint( double /*x*/, double /*y*/ )
00191 {
00192     /* Derived class must implement this function */
00193     // m_end.setPosition( x, y, false );
00194     // m_end.disconnect();
00195 }
00196 
00197 
00198 void KivioBaseConnectorStencil::paint( KivioIntraStencilData * )
00199 {
00200     /* Derived class must implement this */
00201 }
00202 
00203 void KivioBaseConnectorStencil::paintOutline( KivioIntraStencilData *pData )
00204 {
00205     /* Derived class should implement this */
00206     paint( pData );
00207 }
00208 
00209 void KivioBaseConnectorStencil::paintConnectorTargets( KivioIntraStencilData * )
00210 {
00211 }
00212 
00213 void KivioBaseConnectorStencil::paintSelectionHandles( KivioIntraStencilData *pData )
00214 {
00215   // Handle Width
00216   const double HW = 6.0f;
00217   const double HWP1 = HW+1.0f;
00218 
00219   // Handle Width Over 2
00220   const double HWo2 = HW/2.0f;
00221 
00222   // Stencil data
00223   KoZoomHandler* zoomHandler = pData->zoomHandler;
00224   KivioPainter *painter = pData->painter;
00225   double x1, y1;
00226 
00227   painter->setLineWidth(1.0f);
00228   painter->setFGColor(QColor(0,0,0));
00229 
00230   KivioConnectorPoint *p = m_pConnectorPoints->first();
00231   while( p )
00232   {
00233     x1 = zoomHandler->zoomItX(p->x()) - HWo2;
00234     y1 = zoomHandler->zoomItY(p->y()) - HWo2;
00235 
00236     if( p->target() )
00237         painter->setBGColor(QColor(200,0,0));
00238     else
00239         painter->setBGColor(QColor(0,200,0));
00240 
00241     painter->fillRect( x1, y1, HWP1, HWP1 );
00242 
00243     p = m_pConnectorPoints->next();
00244   }
00245 }
00246 
00247 
00248 
00250 // Collision detection
00252 KivioCollisionType KivioBaseConnectorStencil::checkForCollision( KoPoint *, double )
00253 {
00254     /* Derived class must implement this */
00255     return kctNone;
00256 }
00257 
00258 
00259 
00260 
00262 // Custom dragging
00264 
00272 void KivioBaseConnectorStencil::customDrag( KivioCustomDragData *pData )
00273 {
00274     double _x = pData->x;
00275     double _y = pData->y;
00276     int id = pData->id;
00277 
00278     KivioConnectorPoint *p;
00279 
00280     // Locate the point specified by id
00281     p = m_pConnectorPoints->at( id - (kctCustom+1));
00282 
00283     if( !p )
00284     {
00285        kdDebug(43000) << "KivioBaseConnectorStencil::customDrag() - KivioConnectorPoint id: " << (id - (kctCustom+1)) << "  not found\n" << endl;
00286        return;
00287     }
00288 
00289     p->setPosition( _x, _y, true );
00290 
00291 
00292     KivioLayer *pCurLayer = pData->page->curLayer();
00293     KivioLayer *pLayer = pData->page->firstLayer(); //pData->page->curLayer();
00294 
00295     while( pLayer )
00296     {
00297         // To be connected to, a layer must be visible and connectable
00298         if( pLayer!=pCurLayer )
00299         {
00300             if( pLayer->connectable()==false || pLayer->visible()==false )
00301             {
00302                 pLayer = pData->page->nextLayer();
00303                 continue;
00304             }
00305         }
00306 
00307         // Tell the layer to search for a target
00308         if( pLayer->connectPointToTarget( p, 8.0f ) )
00309         {
00310             return;
00311         }
00312 
00313         pLayer = pData->page->nextLayer();
00314     }
00315 
00316 
00317     // Nope, disconnect
00318     p->disconnect();
00319 }
00320 
00321 
00325 void KivioBaseConnectorStencil::updateGeometry()
00326 {
00327     double minX, minY, maxX, maxY;
00328 
00329     minX = 1000000000000.0f;
00330     minY = minX;
00331     maxX = -100000000000.0f;
00332     maxY = maxX;
00333 
00334     KivioConnectorPoint *p;
00335     p = m_pConnectorPoints->first();
00336     while( p )
00337     {
00338         if( p->x() < minX )
00339             minX = p->x();
00340         if( p->x() > maxX )
00341             maxX = p->x();
00342         if( p->y() < minY )
00343             minY = p->y();
00344         if( p->y() > maxY )
00345             maxY = p->y();
00346 
00347         p = m_pConnectorPoints->next();
00348     }
00349 
00350     m_x = minX;
00351     m_y = minY;
00352     m_w = maxX - minX + 1.0f;
00353     m_h = maxY - minY + 1.0f;
00354 }
00355 
00356 
00357 
00358 // file i/o routines
00359 bool KivioBaseConnectorStencil::loadXML( const QDomElement & )
00360 {
00361     return false;
00362 }
00363 
00364 QDomElement KivioBaseConnectorStencil::saveXML( QDomDocument & )
00365 {
00366     return QDomElement();
00367 }
00368 
00369 
00370 
00371 KivioStencil *KivioBaseConnectorStencil::duplicate()
00372 {
00373     /* Derived class must implement this function */
00374     return NULL;
00375 }
00376 
00377 
00378 bool KivioBaseConnectorStencil::boolAllTrue( bool *boolArray, int count )
00379 {
00380     int i;
00381 
00382     for( i=0; i<count; i++ )
00383     {
00384         if( boolArray[i]==false )
00385             return false;
00386     }
00387 
00388     return true;
00389 }
00390 
00391 bool KivioBaseConnectorStencil::boolContainsFalse( bool *boolArray, int count )
00392 {
00393     int i;
00394 
00395     for( i=0; i<count; i++ )
00396     {
00397         if( boolArray[i]==false )
00398             return true;
00399     }
00400 
00401     return false;
00402 }
00403 
00404 
00405 void KivioBaseConnectorStencil::searchForConnections( KivioPage *pPage )
00406 {
00407     bool *done = new bool[ m_pConnectorPoints->count() ];
00408 
00409     int i;
00410 
00411     for( i=0; i<(int)m_pConnectorPoints->count(); i++ )
00412         done[i] = false;
00413 
00414     KivioConnectorPoint *p;
00415 
00416     i=0;
00417     p = m_pConnectorPoints->first();
00418     while( p )
00419     {
00420         if( p->targetId() == -1 )
00421             done[i] = true;
00422 
00423         i++;
00424         p = m_pConnectorPoints->next();
00425     }
00426 
00427 
00428     // No connections? BaiL!
00429     if( boolAllTrue( done, m_pConnectorPoints->count() ) )
00430     {
00431        delete [] done;
00432        return;
00433     }
00434 
00435 
00436 
00437     KivioLayer *pLayer = pPage->firstLayer();
00438     while( pLayer && ( boolContainsFalse(done, m_pConnectorPoints->count()) ) )
00439     {
00440         KivioStencil *pStencil = pLayer->firstStencil();
00441 
00442         while( pStencil && ( boolContainsFalse(done, m_pConnectorPoints->count()) ) )
00443         {
00444             // No connecting to ourself!
00445             if( pStencil != this )
00446             {
00447 
00448                 // Iterate through all connectors attempting to connect it to the stencil.
00449                 // If it connects, mark it as done
00450                 i=0;
00451                 p = m_pConnectorPoints->first();
00452                 while( p )
00453                 {
00454                     if( !done[i] &&
00455                          p->targetId() != -1 )
00456                     {
00457                         if( pStencil->connectToTarget( p, p->targetId() ) )
00458                         {
00459                             done[i] = true;
00460                         }
00461                     }
00462 
00463                     i++;
00464                     p = m_pConnectorPoints->next();
00465                 }
00466 
00467             }
00468 
00469             pStencil = pLayer->nextStencil();
00470         }
00471 
00472         pLayer = pPage->nextLayer();
00473     }
00474 
00475     delete [] done;
00476 }
00477 
00478 
00480 // resize handles
00482 int KivioBaseConnectorStencil::resizeHandlePositions()
00483 {
00484     return (int)krhpNone;
00485 }
00486 
00487 QDomElement KivioBaseConnectorStencil::saveConnectors( QDomDocument &doc )
00488 {
00489     QDomElement eConns = doc.createElement("KivioConnectors");
00490 
00491     KivioConnectorPoint *p;
00492     p = m_pConnectorPoints->first();
00493     while( p )
00494     {
00495         eConns.appendChild( p->saveXML(doc) );
00496 
00497         p = m_pConnectorPoints->next();
00498     }
00499 
00500     return eConns;
00501 }
00502 
00503 bool KivioBaseConnectorStencil::loadConnectors( const QDomElement &e )
00504 {
00505     m_pConnectorPoints->clear();
00506 
00507     KivioConnectorPoint *p;
00508 
00509     QDomNode node = e.firstChild();
00510     QDomElement e2;
00511     QString name;
00512 
00513     while( !node.isNull() )
00514     {
00515         e2 = node.toElement();
00516         name = e2.nodeName();
00517 
00518         if( name == "KivioConnectorPoint" )
00519         {
00520             p = new KivioConnectorPoint();
00521             p->setStencil(this);
00522             p->loadXML( e2 );
00523 
00524             m_pConnectorPoints->append( p );
00525             p = NULL;
00526         }
00527 
00528         node = node.nextSibling();
00529     }
00530 
00531     return true;
00532 }
00533 
00534 QDomElement KivioBaseConnectorStencil::saveProperties( QDomDocument &doc )
00535 {
00536     QDomElement propE = doc.createElement("KivioConnectorProperties");
00537 
00538     propE.appendChild( m_pLineStyle->saveXML( doc ) );
00539 
00540     propE.appendChild( m_pFillStyle->saveXML( doc ) );
00541 
00542     return propE;
00543 }
00544 
00545 bool KivioBaseConnectorStencil::loadProperties( const QDomElement &e )
00546 {
00547     QDomNode node;
00548     QString nodeName;
00549 
00550     node = e.firstChild();
00551     while( !node.isNull() )
00552     {
00553         nodeName = node.nodeName();
00554         if( nodeName == "KivioFillStyle" )
00555         {
00556             m_pFillStyle->loadXML( node.toElement() );
00557         }
00558         else if( nodeName == "KivioLineStyle" )
00559         {
00560             m_pLineStyle->loadXML( node.toElement() );
00561         }
00562 
00563         node = node.nextSibling();
00564     }
00565 
00566     return true;
00567 }
KDE Home | KDE Accessibility Home | Description of Access Keys