00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "cnitemgroup.h"
00012 #include "canvasitemparts.h"
00013 #include "dptext.h"
00014 #include "canvasmanipulator.h"
00015 #include "connector.h"
00016 #include "flowcontainer.h"
00017 #include "icndocument.h"
00018 #include "itemview.h"
00019 #include "mechanicsdocument.h"
00020 #include "mechanicsgroup.h"
00021 #include "mechanicsitem.h"
00022 #include "node.h"
00023 #include "nodegroup.h"
00024 #include "picitem.h"
00025 #include "resizeoverlay.h"
00026
00027 #include <cmath>
00028
00029 #include <kconfig.h>
00030 #include <kdebug.h>
00031 #include <kglobal.h>
00032
00033 #include <qpainter.h>
00034 #include <qtimer.h>
00035
00036
00037
00038
00039
00040
00041 CMManager::CMManager( ItemDocument *itemDocument )
00042 : QObject()
00043 {
00044 b_allowItemScroll = true;
00045 p_lastMouseOverResizeHandle = 0;
00046 m_canvasManipulator = 0;
00047 p_itemDocument = itemDocument;
00048 m_cmState = 0;
00049 p_lastMouseOverItem = 0;
00050 p_lastItemClicked = 0;
00051 m_drawAction = -1;
00052 m_allowItemScrollTmr = new QTimer(this);
00053 connect( m_allowItemScrollTmr, SIGNAL(timeout()), this, SLOT(slotAllowItemScroll()) );
00054
00055 KGlobal::config()->setGroup("General");
00056 slotSetManualRoute( KGlobal::config()->readBoolEntry( "ManualRouting", false));
00057 }
00058
00059 CMManager::~CMManager()
00060 {
00061 delete m_allowItemScrollTmr;
00062 delete m_canvasManipulator;
00063
00064 const ManipulatorInfoList::iterator end = m_manipulatorInfoList.end();
00065 for ( ManipulatorInfoList::iterator it = m_manipulatorInfoList.begin(); it != end; ++it ) {
00066 delete *it;
00067 }
00068
00069 m_manipulatorInfoList.clear();
00070 }
00071
00072 void CMManager::addManipulatorInfo( ManipulatorInfo *eventInfo )
00073 {
00074 if ( eventInfo && !m_manipulatorInfoList.contains(eventInfo) ) {
00075 m_manipulatorInfoList.prepend(eventInfo);
00076 }
00077 }
00078
00079 void CMManager::cancelCurrentManipulation()
00080 {
00081 delete m_canvasManipulator;
00082 m_canvasManipulator = 0;
00083 setRepeatedAddId();
00084 }
00085
00086 void CMManager::mousePressEvent( EventInfo eventInfo )
00087 {
00088 if (m_canvasManipulator) {
00089 if (m_canvasManipulator->mousePressedRepeat(eventInfo)) {
00090 delete m_canvasManipulator;
00091 m_canvasManipulator = 0;
00092 }
00093 return;
00094 }
00095
00096 uint eventState=0;
00097 if(eventInfo.isRightClick)
00098 eventState |= CMManager::es_right_click;
00099
00100 if(eventInfo.ctrlPressed)
00101 eventState |= CMManager::es_ctrl_pressed;
00102
00103 uint itemType=0;
00104 uint cnItemType=0;
00105
00106 switch(eventInfo.itemRtti) {
00107 case ItemDocument::RTTI::None: itemType = CMManager::it_none; break;
00108 case ItemDocument::RTTI::Node: itemType = CMManager::it_node; break;
00109 case ItemDocument::RTTI::Connector: itemType = CMManager::it_connector; break;
00110 case ItemDocument::RTTI::Pin: itemType = CMManager::it_pin; break;
00111 case ItemDocument::RTTI::ResizeHandle: itemType = CMManager::it_resize_handle; break;
00112 case ItemDocument::RTTI::DrawPart:
00113 {
00114 itemType = CMManager::it_drawpart;
00115 DrawPart *drawPartClickedOn = dynamic_cast<DrawPart*>(eventInfo.qcanvasItemClickedOn);
00116
00117 if ( drawPartClickedOn->mousePressEvent(eventInfo) ) {
00118 p_lastItemClicked = drawPartClickedOn;
00119 return;
00120 }
00121
00122 if ( drawPartClickedOn->isMovable() )
00123 cnItemType |= CMManager::isi_isMovable;
00124 break;
00125 }
00126 case ItemDocument::RTTI::Widget:
00127 {
00128 Widget *widget = dynamic_cast<Widget*>(eventInfo.qcanvasItemClickedOn);
00129 if (widget)
00130 eventInfo.qcanvasItemClickedOn = widget->parent();
00131 }
00132 case ItemDocument::RTTI::CNItem:
00133 {
00134 itemType = CMManager::it_canvas_item;
00135 CNItem *cnItemClickedOn = dynamic_cast<CNItem*>(eventInfo.qcanvasItemClickedOn);
00136
00137 if(cnItemClickedOn->mousePressEvent(eventInfo) )
00138 {
00139 p_lastItemClicked = cnItemClickedOn;
00140 return;
00141 }
00142
00143 if(cnItemClickedOn->isMovable() )
00144 cnItemType |= CMManager::isi_isMovable;
00145 break;
00146 }
00147 case ItemDocument::RTTI::MechanicsItem:
00148 {
00149 itemType = CMManager::it_mechanics_item;
00150 MechanicsItem *p_mechanicsItemClickedOn = dynamic_cast<MechanicsItem*>(eventInfo.qcanvasItemClickedOn);
00151
00152 if ( p_mechanicsItemClickedOn->mousePressEvent(eventInfo) )
00153 {
00154 p_lastItemClicked = p_mechanicsItemClickedOn;
00155 return;
00156 }
00157 break;
00158 }
00159 }
00160
00161
00162
00163 const ManipulatorInfoList::iterator end = m_manipulatorInfoList.end();
00164
00165 for ( ManipulatorInfoList::iterator it = m_manipulatorInfoList.begin(); it != end && !m_canvasManipulator; ++it ) {
00166 if ( (*it)->m_acceptManipulationPtr( eventState, m_cmState, itemType, cnItemType ) ) {
00167 m_canvasManipulator = (*it)->m_createManipulatorPtr( p_itemDocument, this );
00168 }
00169 }
00170
00171 if (m_canvasManipulator) {
00172 if (m_canvasManipulator->mousePressedInitial(eventInfo)) {
00173 delete m_canvasManipulator;
00174 m_canvasManipulator = 0;
00175 }
00176 }
00177 }
00178
00179 void CMManager::mouseDoubleClickEvent( const EventInfo &eventInfo )
00180 {
00181 Item *item = dynamic_cast<Item*>(eventInfo.qcanvasItemClickedOn);
00182 if (item) {
00183 item->mouseDoubleClickEvent(eventInfo);
00184 return;
00185 }
00186
00187 Widget *widget = dynamic_cast<Widget*>(eventInfo.qcanvasItemClickedOn);
00188 if (widget) {
00189 widget->parent()->mouseDoubleClickEvent(eventInfo);
00190 return;
00191 }
00192 }
00193
00194 void CMManager::mouseMoveEvent( const EventInfo &eventInfo )
00195 {
00196 if (m_canvasManipulator)
00197 {
00198 if (m_canvasManipulator->mouseMoved(eventInfo))
00199 {
00200 kdDebug() << k_funcinfo << "About to delete" << endl;
00201 delete m_canvasManipulator;
00202 kdDebug() << k_funcinfo << "Deleted" << endl;
00203 m_canvasManipulator = 0;
00204 kdDebug() << k_funcinfo << "Nullified" << endl;
00205 }
00206 ItemView *itemView = dynamic_cast<ItemView*>(p_itemDocument->activeView());
00207
00208 if (itemView) itemView->scrollToMouse(eventInfo.pos);
00209 return;
00210 }
00211
00212
00213 QCanvasItem *qcnItem = p_itemDocument->itemAtTop(eventInfo.pos);
00214 Item *item;
00215 Widget *widget = dynamic_cast<Widget*>(qcnItem);
00216 if(widget) item = widget->parent();
00217 else item = dynamic_cast<Item*>(qcnItem);
00218
00219 if ( p_lastMouseOverItem != (QGuardedPtr<Item>)item ) {
00220 QEvent event(QEvent::Leave);
00221
00222 if (p_lastMouseOverItem) p_lastMouseOverItem->leaveEvent();
00223
00224 if (item) item->enterEvent();
00225
00226 p_lastMouseOverItem = item;
00227 }
00228
00229
00230 if(p_lastItemClicked) {
00231 p_lastItemClicked->mouseMoveEvent(eventInfo);
00232 } else if(item) {
00233 item->mouseMoveEvent(eventInfo);
00234 }
00235
00236
00237 updateCurrentResizeHandle( dynamic_cast<ResizeHandle*>(qcnItem) );
00238 }
00239
00240 void CMManager::updateCurrentResizeHandle( ResizeHandle * resizeHandle )
00241 {
00242 if ( p_lastMouseOverResizeHandle != (QGuardedPtr<ResizeHandle>)resizeHandle )
00243 {
00244 if (p_lastMouseOverResizeHandle)
00245 p_lastMouseOverResizeHandle->setHover(false);
00246 p_lastMouseOverResizeHandle = resizeHandle;
00247 if (resizeHandle) resizeHandle->setHover(true);
00248 }
00249 }
00250
00251 void CMManager::mouseReleaseEvent( const EventInfo &eventInfo )
00252 {
00253
00254 if(m_canvasManipulator && m_canvasManipulator->mouseReleased(eventInfo)) {
00255 delete m_canvasManipulator;
00256 m_canvasManipulator = 0;
00257 }
00258
00259 if (p_lastItemClicked) {
00260 p_lastItemClicked->mouseReleaseEvent(eventInfo);
00261 p_lastItemClicked=0;
00262 }
00263
00264 updateCurrentResizeHandle( dynamic_cast<ResizeHandle*>( p_itemDocument->itemAtTop(eventInfo.pos) ) );
00265 }
00266
00267 void CMManager::wheelEvent( const EventInfo &eventInfo )
00268 {
00269 bool accepted = false;
00270 if (b_allowItemScroll) {
00271 QCanvasItem *qcnItem = p_itemDocument->itemAtTop(eventInfo.pos);
00272 Item *item;
00273 Widget *widget = dynamic_cast<Widget*>(qcnItem);
00274 if(widget) item = widget->parent();
00275 else item = dynamic_cast<Item*>(qcnItem);
00276
00277 if(item) accepted = item->wheelEvent(eventInfo);
00278 }
00279
00280 if (!accepted) {
00281
00282 b_allowItemScroll = false;
00283 m_allowItemScrollTmr->stop();
00284 m_allowItemScrollTmr->start(500,true);
00285
00286 ItemView *itemView = dynamic_cast<ItemView*>(p_itemDocument->activeView());
00287 if (itemView) {
00288 itemView->cvbEditor()->setPassEventsToView(false);
00289 itemView->cvbEditor()->contentsWheelEvent( eventInfo.wheelEvent( 0, 0 ) );
00290 itemView->cvbEditor()->setPassEventsToView(true);
00291 }
00292 }
00293 }
00294
00295 void CMManager::setDrawAction( int drawAction )
00296 {
00297 if ( m_drawAction == drawAction ) return;
00298
00299 m_drawAction = drawAction;
00300 setCMState( cms_draw, (m_drawAction != -1) );
00301 }
00302
00303 void CMManager::slotSetManualRoute( bool manualRoute )
00304 {
00305 KGlobal::config()->setGroup("General");
00306 KGlobal::config()->writeEntry( "ManualRouting", manualRoute );
00307
00308 setCMState( cms_manual_route, manualRoute );
00309 }
00310
00311 void CMManager::setCMState( CMState type, bool state )
00312 {
00313
00314 state ? (m_cmState|=type) : (m_cmState&=(~type));
00315
00316 if ( type == CMManager::cms_manual_route )
00317 emit manualRoutingChanged(state);
00318 }
00319
00320 void CMManager::setRepeatedAddId( const QString & repeatedId )
00321 {
00322 m_repeatedItemId = repeatedId;
00323 }
00324
00325 CanvasManipulator::CanvasManipulator( ItemDocument *itemDocument, CMManager *cmManager )
00326 {
00327 p_itemDocument = itemDocument;
00328 p_icnDocument = dynamic_cast<ICNDocument*>(itemDocument);
00329 p_mechanicsDocument = dynamic_cast<MechanicsDocument*>(itemDocument);
00330 p_canvas = p_itemDocument->canvas();
00331
00332 p_selectList = p_itemDocument->selectList();
00333 p_cnItemSelectList = dynamic_cast<CNItemGroup*>(p_selectList);
00334 p_mechItemSelectList = dynamic_cast<MechanicsGroup*>(p_selectList);
00335 p_cnItemClickedOn = 0;
00336 p_cmManager = cmManager;
00337 }
00338
00339 CanvasManipulator::~CanvasManipulator()
00340 {
00341 }
00342
00343 CMRepeatedItemAdd::CMRepeatedItemAdd( ItemDocument *itemDocument, CMManager *cmManager )
00344 : CanvasManipulator( itemDocument, cmManager )
00345 {
00346 }
00347
00348 CMRepeatedItemAdd::~CMRepeatedItemAdd()
00349 {
00350 }
00351
00352 CanvasManipulator* CMRepeatedItemAdd::construct( ItemDocument *itemDocument, CMManager *cmManager )
00353 {
00354 return new CMRepeatedItemAdd(itemDocument,cmManager);
00355 }
00356
00357 ManipulatorInfo *CMRepeatedItemAdd::manipulatorInfo()
00358 {
00359 ManipulatorInfo *eventInfo = new ManipulatorInfo();
00360 eventInfo->m_acceptManipulationPtr = CMRepeatedItemAdd::acceptManipulation;
00361 eventInfo->m_createManipulatorPtr = CMRepeatedItemAdd::construct;
00362 return eventInfo;
00363 }
00364
00365 bool CMRepeatedItemAdd::acceptManipulation( uint , uint cmState, uint , uint )
00366 {
00367 return (cmState & CMManager::cms_repeated_add);
00368 }
00369
00370 bool CMRepeatedItemAdd::mousePressedRepeat( const EventInfo &eventInfo )
00371 {
00372 return mousePressedInitial(eventInfo);
00373 }
00374
00375 bool CMRepeatedItemAdd::mousePressedInitial( const EventInfo &eventInfo )
00376 {
00377 m_eventInfo = eventInfo;
00378 if (eventInfo.isRightClick) {
00379 p_cmManager->setCMState( CMManager::cms_repeated_add, false );
00380 return true;
00381 }
00382
00383 p_icnDocument->addItem( p_cmManager->repeatedItemId(), eventInfo.pos, true );
00384 p_itemDocument->requestStateSave();
00385 return false;
00386 }
00387
00388 bool CMRepeatedItemAdd::mouseMoved( const EventInfo & )
00389 {
00390 return false;
00391 }
00392
00393 bool CMRepeatedItemAdd::mouseReleased( const EventInfo & )
00394 {
00395 return false;
00396 }
00397
00398 CMRightClick::CMRightClick( ItemDocument *itemDocument, CMManager *cmManager )
00399 : CanvasManipulator( itemDocument, cmManager )
00400 {
00401 }
00402
00403 CMRightClick::~CMRightClick()
00404 {
00405 }
00406
00407 CanvasManipulator* CMRightClick::construct( ItemDocument *itemDocument, CMManager *cmManager )
00408 {
00409 return new CMRightClick(itemDocument,cmManager);
00410 }
00411
00412 ManipulatorInfo *CMRightClick::manipulatorInfo()
00413 {
00414 ManipulatorInfo *eventInfo = new ManipulatorInfo();
00415
00416 eventInfo->m_acceptManipulationPtr = CMRightClick::acceptManipulation;
00417 eventInfo->m_createManipulatorPtr = CMRightClick::construct;
00418 return eventInfo;
00419 }
00420
00421 bool CMRightClick::acceptManipulation( uint eventState, uint , uint , uint )
00422 {
00423 return eventState & CMManager::es_right_click;
00424 }
00425
00426 bool CMRightClick::mousePressedInitial( const EventInfo &eventInfo )
00427 {
00428 m_eventInfo = eventInfo;
00429 p_itemDocument->canvasRightClick( eventInfo.globalPos, eventInfo.qcanvasItemClickedOn );
00430 return true;
00431 }
00432
00433 bool CMRightClick::mouseMoved( const EventInfo & )
00434 {
00435 return true;
00436 }
00437
00438 bool CMRightClick::mouseReleased( const EventInfo & )
00439 {
00440 return true;
00441 }
00442
00443
00444 ConnectorDraw::ConnectorDraw( ItemDocument *itemDocument, CMManager *cmManager )
00445 : CanvasManipulator( itemDocument, cmManager )
00446 {
00447 p_startNode = 0;
00448 p_startConnector = 0;
00449 p_endNode = 0;
00450 p_endConnector = 0;
00451 }
00452
00453 ConnectorDraw::~ConnectorDraw()
00454 {
00455 }
00456
00457 QColor ConnectorDraw::validConnectionColor()
00458 {
00459 return QColor(255, 166, 0);
00460 }
00461
00462 static double qpoint_distance( const QPoint & p1, const QPoint & p2 )
00463 {
00464 double dx = p1.x() - p2.x();
00465 double dy = p1.y() - p2.y();
00466
00467 return std::sqrt( dx*dx + dy*dy );
00468 }
00469
00470 QPoint ConnectorDraw::toValidPos( const QPoint & clickPos, Connector * clickedConnector ) const
00471 {
00472 if(!clickedConnector ) return clickPos;
00473
00474 const QPointList pointList = clickedConnector->connectorPoints();
00475 QPointList::const_iterator end = pointList.end();
00476
00477 double dl[] = { 0.5, 8.5, 11.5, 18.0, 23.0 };
00478
00479 for ( unsigned i = 0; i < 5; ++i ) {
00480 for ( QPointList::const_iterator it = pointList.begin(); it != end; ++it ) {
00481 if(qpoint_distance( *it, clickPos ) <= dl[i]) return *it;
00482 }
00483 }
00484
00485 return clickPos;
00486 }
00487
00488 Connector *ConnectorDraw::toConnector( Node * node )
00489 {
00490 if( !node || node->numCon( true, false ) < 3) return 0;
00491
00492 const ConnectorList inList = node->inputConnectorList();
00493 if( !inList.isEmpty() )
00494 return *inList.begin();
00495
00496 const ConnectorList outList = node->outputConnectorList();
00497 if( !outList.isEmpty() )
00498 return *outList.begin();
00499
00500 return 0;
00501 }
00502
00503 void ConnectorDraw::grabEndStuff( QCanvasItem * endItem, const QPoint & pos, bool posIsExact )
00504 {
00505 if (!endItem) return;
00506
00507 CNItem * cnItem = dynamic_cast<CNItem*>(endItem);
00508 if ( cnItem && !posIsExact )
00509 p_endNode = cnItem->getClosestNode(pos);
00510 else p_endNode = dynamic_cast<Node*>(endItem);
00511
00512 if ( p_endNode && p_endNode->numCon( true, false ) > 2 ) {
00513 p_endConnector = toConnector(p_endNode);
00514 p_endNode = 0;
00515 }
00516
00517
00518 if ( posIsExact && p_endNode && (p_endNode->x() != pos.x() || p_endNode->y() != pos.y()) )
00519 p_endNode = 0;
00520
00521 if(!p_endConnector)
00522 p_endConnector = dynamic_cast<Connector*>(endItem);
00523 }
00524
00525
00526
00527 CMAutoConnector::CMAutoConnector( ItemDocument *itemDocument, CMManager *cmManager )
00528 : ConnectorDraw( itemDocument, cmManager )
00529 {
00530 m_connectorLine = 0;
00531 p_startNode = 0;
00532 p_startConnector = 0;
00533 }
00534
00535 CMAutoConnector::~CMAutoConnector()
00536 {
00537 delete m_connectorLine;
00538 m_connectorLine = 0;
00539 }
00540
00541 CanvasManipulator* CMAutoConnector::construct( ItemDocument *itemDocument, CMManager *cmManager )
00542 {
00543 return new CMAutoConnector(itemDocument,cmManager);
00544 }
00545
00546 ManipulatorInfo *CMAutoConnector::manipulatorInfo()
00547 {
00548 ManipulatorInfo *eventInfo = new ManipulatorInfo();
00549 eventInfo->m_acceptManipulationPtr = CMAutoConnector::acceptManipulation;
00550 eventInfo->m_createManipulatorPtr = CMAutoConnector::construct;
00551 return eventInfo;
00552 }
00553
00554 bool CMAutoConnector::acceptManipulation( uint , uint cmState, uint itemType, uint )
00555 {
00556 return (itemType & (CMManager::it_node | CMManager::it_connector)) && !(cmState & CMManager::cms_manual_route);
00557 }
00558
00559 bool CMAutoConnector::mousePressedInitial( const EventInfo &eventInfo )
00560 {
00561 m_eventInfo = eventInfo;
00562 p_startNode = dynamic_cast<Node*>(eventInfo.qcanvasItemClickedOn);
00563
00564 if (p_startNode) {
00565 m_eventInfo.pos = m_prevPos = p_icnDocument->gridSnap( QPoint( (int)p_startNode->x(), (int)p_startNode->y() ) );
00566 if (p_startNode->numCon( true, false ) > 2)
00567 {
00568 p_startConnector = toConnector(p_startNode);
00569 p_startNode = 0;
00570 }
00571 } else if (p_startConnector = dynamic_cast<Connector*>(eventInfo.qcanvasItemClickedOn) )
00572 {
00573
00574 startConnectorPoint = m_eventInfo.pos = m_prevPos = toValidPos( m_eventInfo.pos, p_startConnector );
00575 } else return true;
00576
00577 p_icnDocument->unselectAll();
00578
00579 delete m_connectorLine;
00580 m_connectorLine = new QCanvasLine(p_canvas);
00581 m_connectorLine->setPen( QColor(0,0,0) );
00582 m_connectorLine->setZ( ItemDocument::Z::ConnectorCreateLine );
00583 m_connectorLine->show();
00584 return false;
00585 }
00586
00587 bool CMAutoConnector::mouseMoved( const EventInfo &eventInfo )
00588 {
00589 const QPoint pos = eventInfo.pos;
00590
00591 int newX = p_icnDocument->gridSnap( pos.x() );
00592 int newY = p_icnDocument->gridSnap( pos.y() );
00593
00594 bool movedFlag = false;
00595
00596 if ( newX != m_prevPos.x() ) {
00597 m_prevPos.setX(newX);
00598 movedFlag = true;
00599 }
00600
00601 if ( newY != m_prevPos.y() ) {
00602 m_prevPos.setY(newY);
00603 movedFlag = true;
00604 }
00605
00606 m_connectorLine->setPoints( m_eventInfo.pos.x(), m_eventInfo.pos.y(), newX, newY );
00607
00608 if (movedFlag) {
00609 QCanvasItem *startItem = 0;
00610 if (p_startNode)
00611 startItem = p_startNode;
00612 else if (p_startConnector)
00613 startItem = p_startConnector;
00614
00615 QCanvasItem *endItem = p_icnDocument->itemAtTop( QPoint( newX, newY ) );
00616 if ( endItem && endItem->rtti() == ItemDocument::RTTI::CNItem )
00617 endItem = (static_cast<CNItem*>(endItem))->getClosestNode( QPoint( newX, newY ) );
00618
00619 bool validLine = p_icnDocument->canConnect( startItem, endItem );
00620 m_connectorLine->setPen( validLine ? validConnectionColor() : Qt::black );
00621 }
00622 return false;
00623 }
00624
00625 bool CMAutoConnector::mouseReleased( const EventInfo &eventInfo )
00626 {
00627 const QPoint pos = eventInfo.pos;
00628
00629 QPoint end = m_connectorLine->endPoint();
00630 delete m_connectorLine;
00631 m_connectorLine = 0;
00632
00633 QCanvasItem *qcanvasItem = p_icnDocument->itemAtTop(end);
00634 if ( !qcanvasItem )
00635 return true;
00636
00637 grabEndStuff( qcanvasItem, pos, false );
00638
00639 if (p_startConnector) {
00640 if (p_endConnector) {
00641 if ( !p_icnDocument->createConnector( p_endConnector, p_startConnector, p_icnDocument->gridSnap(pos), startConnectorPoint ) )
00642 return true;
00643 } else if (p_endNode) {
00644 if ( !p_icnDocument->createConnector( p_endNode, p_startConnector, startConnectorPoint ) )
00645 return true;
00646 } else return true;
00647 } else if (p_startNode) {
00648 if (p_endConnector) {
00649 if ( !p_icnDocument->createConnector( p_startNode, p_endConnector, p_icnDocument->gridSnap(pos) ) )
00650 return true;
00651 } else if (p_endNode) {
00652 if ( !p_icnDocument->createConnector( p_startNode, p_endNode ) )
00653 return true;
00654 } else return true;
00655 } else return true;
00656
00657 p_itemDocument->requestStateSave();
00658 return true;
00659 }
00660
00661
00662
00663
00664 CMManualConnector::CMManualConnector( ItemDocument *itemDocument, CMManager *cmManager )
00665 : ConnectorDraw( itemDocument, cmManager )
00666 {
00667 m_manualConnectorDraw = 0;
00668 }
00669
00670 CMManualConnector::~CMManualConnector()
00671 {
00672 delete m_manualConnectorDraw;
00673 m_manualConnectorDraw = 0;
00674 }
00675
00676 CanvasManipulator* CMManualConnector::construct( ItemDocument *itemDocument, CMManager *cmManager )
00677 {
00678 return new CMManualConnector(itemDocument,cmManager);
00679 }
00680
00681 ManipulatorInfo *CMManualConnector::manipulatorInfo()
00682 {
00683 ManipulatorInfo *eventInfo = new ManipulatorInfo();
00684 eventInfo->m_acceptManipulationPtr = CMManualConnector::acceptManipulation;
00685 eventInfo->m_createManipulatorPtr = CMManualConnector::construct;
00686 return eventInfo;
00687 }
00688
00689 bool CMManualConnector::acceptManipulation( uint , uint cmState, uint itemType, uint )
00690 {
00691 return (itemType & (CMManager::it_node | CMManager::it_connector)) && (cmState & CMManager::cms_manual_route);
00692 }
00693
00694 bool CMManualConnector::mousePressedInitial( const EventInfo &eventInfo )
00695 {
00696 if ( eventInfo.isRightClick ) return true;
00697
00698 m_eventInfo = eventInfo;
00699 p_icnDocument->unselectAll();
00700 QPoint sp;
00701
00702 if ( eventInfo.itemRtti == ItemDocument::RTTI::Node ) {
00703 p_startNode = static_cast<Node*>(eventInfo.qcanvasItemClickedOn);
00704 sp.setX( (int)p_startNode->x() );
00705 sp.setY( (int)p_startNode->y() );
00706 if ( p_startNode->numCon( true, false ) > 2 ) {
00707 p_startConnector = toConnector(p_startNode);
00708 p_startNode = 0;
00709 }
00710 } else {
00711 p_startConnector = dynamic_cast<Connector*>(eventInfo.qcanvasItemClickedOn);
00712 sp = toValidPos( eventInfo.pos, p_startConnector );
00713 }
00714 startConnectorPoint = sp;
00715
00716 if (m_manualConnectorDraw) {
00717 delete m_manualConnectorDraw;
00718 m_manualConnectorDraw = 0;
00719 }
00720 m_manualConnectorDraw = new ManualConnectorDraw( p_icnDocument, sp );
00721 return false;
00722 }
00723
00724 bool CMManualConnector::mousePressedRepeat( const EventInfo &eventInfo )
00725 {
00726 m_eventInfo = eventInfo;
00727 if ( eventInfo.isRightClick ) return true;
00728
00729 m_manualConnectorDraw->mouseClicked( p_icnDocument->gridSnap(m_eventInfo.pos) );
00730 return false;
00731 }
00732
00733 bool CMManualConnector::mouseMoved( const EventInfo &eventInfo )
00734 {
00735 if(!m_manualConnectorDraw ) return true;
00736
00737 const QPoint pos = eventInfo.pos;
00738
00739 int newX = p_icnDocument->gridSnap( pos.x() );
00740 int newY = p_icnDocument->gridSnap( pos.y() );
00741
00742 bool movedFlag = false;
00743
00744 if(newX != m_prevPos.x()) {
00745 m_prevPos.setX(newX);
00746 movedFlag = true;
00747 }
00748
00749 if(newY != m_prevPos.y() ) {
00750 m_prevPos.setY(newY);
00751 movedFlag = true;
00752 }
00753
00754 if ( movedFlag ) {
00755 QCanvasItem *startItem = 0;
00756 if (p_startNode) startItem = p_startNode;
00757 else if (p_startConnector)
00758 startItem = p_startConnector;
00759
00760 QCanvasItem * endItem = p_icnDocument->itemAtTop( QPoint( newX, newY ) );
00761
00762
00763 if(Node * node = dynamic_cast<Node*>(endItem) ) {
00764 if(node->x() != newX || node->y() != newY )
00765 endItem = 0;
00766 }
00767
00768 bool validLine = p_icnDocument->canConnect( startItem, endItem );
00769
00770 m_manualConnectorDraw->setColor( validLine ? validConnectionColor() : Qt::black );
00771 m_manualConnectorDraw->mouseMoved( QPoint( newX, newY ) );
00772 }
00773
00774 return false;
00775 }
00776
00777 bool CMManualConnector::mouseReleased( const EventInfo &eventInfo )
00778 {
00779 if (!m_manualConnectorDraw) return true;
00780
00781 QPoint pos = p_icnDocument->gridSnap(eventInfo.pos);
00782 grabEndStuff( m_manualConnectorDraw->mouseClicked(pos), pos, true );
00783
00784 if(!p_endNode && !p_endConnector ) return false;
00785
00786
00787 QPointList list = m_manualConnectorDraw->pointList();
00788 delete m_manualConnectorDraw;
00789 m_manualConnectorDraw = 0;
00790
00791 if (p_startConnector) {
00792 if (p_endConnector) {
00793 if ( !p_icnDocument->createConnector( p_endConnector, p_startConnector, p_icnDocument->gridSnap(pos), startConnectorPoint, &list ) )
00794 return true;
00795 } else {
00796 if ( !p_icnDocument->createConnector( p_endNode, p_startConnector, startConnectorPoint, &list ) )
00797 return true;
00798 }
00799 } else if (p_startNode) {
00800 if (p_endConnector) {
00801 if ( !p_icnDocument->createConnector( p_startNode, p_endConnector, p_icnDocument->gridSnap(pos), &list ) )
00802 return true;
00803 } else {
00804 if ( !p_icnDocument->createConnector( p_startNode, p_endNode, &list ) )
00805 return true;
00806 }
00807 } else return true;
00808
00809 p_itemDocument->requestStateSave();
00810 return true;
00811 }
00812
00813
00814 CMItemMove::CMItemMove( ItemDocument *itemDocument, CMManager *cmManager )
00815 : CanvasManipulator( itemDocument, cmManager )
00816 {
00817 p_flowContainerCandidate = 0;
00818 }
00819
00820 CMItemMove::~CMItemMove()
00821 {
00822 }
00823
00824 CanvasManipulator* CMItemMove::construct( ItemDocument *itemDocument, CMManager *cmManager )
00825 {
00826 return new CMItemMove(itemDocument,cmManager);
00827 }
00828
00829 ManipulatorInfo *CMItemMove::manipulatorInfo()
00830 {
00831 ManipulatorInfo *eventInfo = new ManipulatorInfo();
00832 eventInfo->m_acceptManipulationPtr = CMItemMove::acceptManipulation;
00833 eventInfo->m_createManipulatorPtr = CMItemMove::construct;
00834 return eventInfo;
00835 }
00836
00837 bool CMItemMove::acceptManipulation( uint eventState, uint , uint itemType, uint cnItemType )
00838 {
00839 return ((itemType & CMManager::it_canvas_item) || (itemType & CMManager::it_drawpart)) && (cnItemType & CMManager::isi_isMovable) && !(eventState & CMManager::es_right_click);
00840 }
00841
00842 bool CMItemMove::mousePressedInitial( const EventInfo &eventInfo )
00843 {
00844 m_eventInfo = eventInfo;
00845 m_prevPos = eventInfo.pos;
00846
00847 Item *item = dynamic_cast<Item*>(eventInfo.qcanvasItemClickedOn);
00848 if (!item) return true;
00849
00850 if ( !p_selectList->contains(item) )
00851 {
00852 if (!eventInfo.ctrlPressed)
00853 p_itemDocument->unselectAll();
00854
00855 p_itemDocument->select(item);
00856 } else if (m_eventInfo.ctrlPressed)
00857 p_itemDocument->unselect(item);
00858
00859 if ( p_selectList->isEmpty() ) return true;
00860
00861
00862 p_flowContainerCandidate = 0;
00863 {
00864 const ItemList &itemList = p_icnDocument->itemList();
00865 const ItemList::const_iterator ciEnd = itemList.end();
00866 for ( ItemList::const_iterator it = itemList.begin(); it != ciEnd; ++it )
00867 {
00868 if ( FlowContainer *flowContainer = dynamic_cast<FlowContainer*>((Item*)*it) )
00869 flowContainer->setFullBounds(true);
00870 }
00871 }
00872
00873 ItemList itemList = p_cnItemSelectList->items(false);
00874 itemList.remove((Item*)0);
00875
00876 const ItemList::iterator itemListEnd = itemList.end();
00877 for ( ItemList::iterator it = itemList.begin(); it != itemListEnd; ++it )
00878 {
00879 CNItem *cnItem = dynamic_cast<CNItem*>((Item*)*it);
00880 if ( !cnItem || !cnItem->canvas() ) continue;
00881
00882 cnItem->setInitialPos(m_eventInfo.pos);
00883 }
00884
00885 ConnectorList fixedConnectors;
00886 p_icnDocument->getTranslatable( itemList, &fixedConnectors, &m_translatableConnectors, &m_translatableNodeGroups );
00887
00888 const ConnectorList::iterator fixedConnectorsEnd = fixedConnectors.end();
00889 for ( ConnectorList::iterator it = fixedConnectors.begin(); it != fixedConnectorsEnd; ++it )
00890 (*it)->setSemiHidden(true);
00891
00892 p_flowContainerCandidate = p_icnDocument->flowContainer(eventInfo.pos);
00893
00894 return false;
00895 }
00896
00897 bool CMItemMove::mouseMoved( const EventInfo &eventInfo )
00898 {
00899 const QPoint pos = eventInfo.pos;
00900
00901 int x = pos.x();
00902 int y = pos.y();
00903
00904 const ItemList itemList = p_cnItemSelectList->items();
00905 const ItemList::const_iterator end = itemList.end();
00906 int dx=0, dy=0;
00907
00908 for ( ItemList::const_iterator it = itemList.begin(); it != end; ++it )
00909 {
00910 if(!*it || !(*it)->isMovable() )
00911 continue;
00912
00913 const QRect oldRect = (*it)->boundingRect();
00914 (*it)->setChanged();
00915
00916 if(CNItem *cnItem = dynamic_cast<CNItem*>((Item*)*it) ) {
00917 dx = -int((*it)->x());
00918 dy = -int((*it)->y());
00919 cnItem->snap( x, y );
00920 dx += int((*it)->x());
00921 dy += int((*it)->y());
00922 } else (*it)->moveBy( eventInfo.pos.x()-m_prevPos.x(), eventInfo.pos.y()-m_prevPos.y() );
00923
00924 QRect newRect = (*it)->boundingRect();
00925 QRect merged = oldRect | newRect;
00926 }
00927
00928 if ( (dx != 0) || (dy != 0) ) {
00929 const ConnectorList::iterator frEnd = m_translatableConnectors.end();
00930 for ( ConnectorList::iterator it = m_translatableConnectors.begin(); it != frEnd; ++it )
00931 (*it)->translateRoute( dx, dy );
00932
00933 const NodeGroupList::iterator end = m_translatableNodeGroups.end();
00934 for ( NodeGroupList::iterator it = m_translatableNodeGroups.begin(); it != end; ++it )
00935 (*it)->translate( dx, dy );
00936 }
00937
00938 FlowContainer *fc = p_icnDocument->flowContainer(pos);
00939 if(fc != p_flowContainerCandidate ) {
00940 if(p_flowContainerCandidate ) {
00941 p_flowContainerCandidate->setSelected(false);
00942 p_flowContainerCandidate = 0;
00943 }
00944 }
00945
00946 if (fc) {
00947 p_flowContainerCandidate = fc;
00948 p_flowContainerCandidate->setSelected(true);
00949 }
00950
00951 p_itemDocument->