00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "canvasitemparts.h"
00012 #include "icndocument.h"
00013 #include "cells.h"
00014 #include "component.h"
00015 #include "ecnode.h"
00016 #include "fpnode.h"
00017 #include "itemdocumentdata.h"
00018 #include <kdebug.h>
00019
00020 #include <qbitarray.h>
00021 #include <qpainter.h>
00022
00023 #include <cmath>
00024
00025
00026 CNItem::CNItem( ICNDocument *icnDocument, bool newItem, const QString &id )
00027 : Item( icnDocument, newItem, id ),
00028 CIWidgetMgr( icnDocument->canvas(), this ),
00029 p_icnDocument(icnDocument),
00030 b_pointsAdded(false)
00031 {
00032 setZ( ICNDocument::Z::Item );
00033 setSelected(false);
00034
00035 m_brushCol = QColor( 0xf7, 0xf7, 0xff );
00036 m_selectedCol = QColor( 101, 134, 192 );
00037
00038 setBrush(m_brushCol);
00039 setPen( Qt::black );
00040 }
00041
00042 CNItem::~CNItem()
00043 {
00044 const TextMap::iterator textMapEnd = m_textMap.end();
00045 for ( TextMap::iterator it = m_textMap.begin(); it != textMapEnd; ++it )
00046 {
00047 if (it.data())
00048 it.data()->setCanvas(0);
00049 delete (Text*)it.data();
00050 }
00051 m_textMap.clear();
00052
00053 updateConnectorPoints(false);
00054 }
00055
00056 int CNItem::rtti() const
00057 {
00058 return ItemDocument::RTTI::CNItem;
00059 }
00060
00061 bool CNItem::preResize( QRect sizeRect )
00062 {
00063 if ( (std::abs(sizeRect.width()) < minimumSize().width()) ||
00064 (std::abs(sizeRect.height()) < minimumSize().height()) )
00065 return false;
00066
00067 updateConnectorPoints(false);
00068 return true;
00069 }
00070
00071 void CNItem::postResize()
00072 {
00073 updateAttachedPositioning();
00074 }
00075
00076 void CNItem::setVisible( bool yes )
00077 {
00078 if (b_deleted) {
00079 Item::setVisible(false);
00080 return;
00081 }
00082
00083 Item::setVisible(yes);
00084
00085 const TextMap::iterator textMapEnd = m_textMap.end();
00086 for(TextMap::iterator it = m_textMap.begin(); it != textMapEnd; ++it) {
00087 it.data()->setVisible(yes);
00088 }
00089
00090 const NodeMap::iterator nodeMapEnd = m_nodeMap.end();
00091 for(NodeMap::iterator it = m_nodeMap.begin(); it != nodeMapEnd; ++it) {
00092 it.data().node->setVisible(yes);
00093 }
00094
00095 CNItem::setDrawWidgets(yes);
00096
00097 if (!yes)
00098 updateConnectorPoints(false);
00099 }
00100
00101 void CNItem::setInitialPos( const QPoint &pos )
00102 {
00103 m_offset = pos - QPoint( (int)x(), (int)y() );
00104 }
00105
00106 void CNItem::reparented( Item *oldParent, Item *newParent )
00107 {
00108 Item::reparented( oldParent, newParent );
00109 updateNodeLevels();
00110 }
00111
00112 void CNItem::updateNodeLevels()
00113 {
00114 int l = level();
00115
00116
00117 const NodeMap::iterator nodeMapEnd = m_nodeMap.end();
00118 for ( NodeMap::iterator it = m_nodeMap.begin(); it != nodeMapEnd; ++it )
00119 {
00120 it.data().node->setLevel(l);
00121 }
00122
00123 const ItemList::iterator end = m_children.end();
00124 for ( ItemList::iterator it = m_children.begin(); it != end; ++it )
00125 {
00126 if ( CNItem *cnItem = dynamic_cast<CNItem*>((Item*)*it) )
00127 cnItem->updateNodeLevels();
00128 }
00129 }
00130
00131 ConnectorList CNItem::connectorList()
00132 {
00133 ConnectorList list;
00134
00135 const NodeMap::iterator nodeMapEnd = m_nodeMap.end();
00136 for ( NodeMap::iterator it = m_nodeMap.begin(); it != nodeMapEnd; ++it )
00137 {
00138 Node *node = p_icnDocument->nodeWithID(it.data().id);
00139 if (node)
00140 {
00141 ConnectorList nodeList = node->inputConnectorList();
00142 ConnectorList::iterator end = nodeList.end();
00143 for ( ConnectorList::iterator it = nodeList.begin(); it != end; ++it )
00144 {
00145 if ( *it && !list.contains(*it) )
00146 {
00147 list.append(*it);
00148 }
00149 }
00150 nodeList = node->outputConnectorList();
00151 end = nodeList.end();
00152 for ( ConnectorList::iterator it = nodeList.begin(); it != end; ++it )
00153 {
00154 if ( *it && !list.contains(*it) )
00155 {
00156 list.append(*it);
00157 }
00158 }
00159 }
00160 }
00161
00162 return list;
00163 }
00164
00165 void CNItem::removeItem()
00166 {
00167 if (b_deleted)
00168 return;
00169
00170 const TextMap::iterator textMapEnd = m_textMap.end();
00171 for ( TextMap::iterator it = m_textMap.begin(); it != textMapEnd; ++it )
00172 it.data()->setCanvas(0);
00173
00174 Item::removeItem();
00175 updateConnectorPoints(false);
00176 }
00177
00178 void CNItem::restoreFromItemData( const ItemData &itemData )
00179 {
00180 Item::restoreFromItemData(itemData);
00181
00182 updateConnectorPoints(false);
00183
00184 {
00185 const BoolMap::const_iterator end = itemData.buttonMap.end();
00186 for ( BoolMap::const_iterator it = itemData.buttonMap.begin(); it != end; ++it )
00187 {
00188 Button *b = button(it.key());
00189 if (b)
00190 b->setState(it.data());
00191 }
00192 }
00193 {
00194 const IntMap::const_iterator end = itemData.sliderMap.end();
00195 for ( IntMap::const_iterator it = itemData.sliderMap.begin(); it != end; ++it )
00196 {
00197 Slider *s = slider(it.key());
00198 if (s)
00199 s->setValue(it.data());
00200 }
00201 }
00202 }
00203
00204 ItemData CNItem::itemData() const
00205 {
00206 ItemData itemData = Item::itemData();
00207
00208 const WidgetMap::const_iterator end = m_widgetMap.end();
00209 for ( WidgetMap::const_iterator it = m_widgetMap.begin(); it != end; ++it )
00210 {
00211 if ( Slider *slider = dynamic_cast<Slider*>(*it) )
00212 itemData.sliderMap[slider->id()] = slider->value();
00213
00214 else if ( Button *button = dynamic_cast<Button*>(*it) )
00215 itemData.buttonMap[button->id()] = button->state();
00216
00217 }
00218
00219 return itemData;
00220 }
00221
00222 Node* CNItem::createNode( double _x, double _y, int orientation, const QString &name, uint type )
00223 {
00224 orientation %= 360;
00225 if(orientation < 0 ) orientation += 360;
00226
00227 Node::node_dir dir;
00228
00229 if (orientation == 0 ) dir = Node::dir_right;
00230 else if (orientation == 90 ) dir = Node::dir_down;
00231 else if (orientation == 180 ) dir = Node::dir_left;
00232 else if (orientation == 270 ) dir = Node::dir_up;
00233 else {
00234 kdError() << k_funcinfo << "Unknown orientation: " << orientation << endl;
00235 return 0;
00236 }
00237
00238 Node *node;
00239 if ( (type == Node::ec_pin) || (type == Node::ec_junction) )
00240 {
00241 node = new ECNode( p_icnDocument, Node::node_type(type), dir, QPoint( 0, 0 ) );
00242 } else {
00243 node = new FPNode( p_icnDocument, Node::node_type(type), dir, QPoint( 0, 0 ) );
00244 }
00245
00246 node->setLevel( level() );
00247
00248 node->setParentItem(this);
00249 node->setChildId(name);
00250
00251 NodeInfo info;
00252 info.id = node->id();
00253 info.node = node;
00254 info.x = _x;
00255 info.y = _y;
00256 info.orientation = orientation;
00257
00258 m_nodeMap[name] = info;
00259
00260 updateAttachedPositioning();
00261
00262 return node;
00263 }
00264
00265 bool CNItem::removeNode( const QString &name )
00266 {
00267 NodeMap::iterator it = m_nodeMap.find(name);
00268 if ( it == m_nodeMap.end() ) {
00269 return false;
00270 }
00271 it.data().node->removeNode();
00272 p_icnDocument->flushDeleteList();
00273 m_nodeMap.erase(it);
00274 return true;
00275 }
00276
00277 Node *CNItem::getClosestNode( const QPoint &pos )
00278 {
00279
00280 Node *shortestNode = 0;
00281 double shortestDistance = 1e10;
00282
00283 const NodeMap::iterator end = m_nodeMap.end();
00284 for ( NodeMap::iterator it = m_nodeMap.begin(); it != end; ++it )
00285 {
00286 Node *node = p_icnDocument->nodeWithID(it.data().id);
00287 if (node)
00288 {
00289
00290
00291 double distance = std::pow(node->x()-pos.x(),2) + std::pow(node->y()-pos.y(),2);
00292
00293 if ( distance < shortestDistance ) {
00294 shortestDistance = distance;
00295 shortestNode = node;
00296 }
00297 }
00298 }
00299
00300 return shortestNode;
00301 }
00302
00303 void CNItem::updateAttachedPositioning()
00304 {
00305
00306 }
00307
00308 void CNItem::updateZ( int baseZ )
00309 {
00310 Item::updateZ(baseZ);
00311 double _z = z();
00312
00313 const NodeMap::iterator nodeMapEnd = m_nodeMap.end();
00314 for ( NodeMap::iterator it = m_nodeMap.begin(); it != nodeMapEnd; ++it )
00315 it.data().node->setZ( _z + 0.5 );
00316
00317 const WidgetMap::iterator widgetMapEnd = m_widgetMap.end();
00318 for ( WidgetMap::iterator it = m_widgetMap.begin(); it != widgetMapEnd; ++it )
00319 it.data()->setZ( _z + 0.5 );
00320
00321 const TextMap::iterator textMapEnd = m_textMap.end();
00322 for ( TextMap::iterator it = m_textMap.begin(); it != textMapEnd; ++it )
00323 it.data()->setZ( _z + 0.5 );
00324 }
00325
00326 void CNItem::snap( int newx, int newy )
00327 {
00328
00329
00330
00331 moveBy( 4+newx-m_offset.x()-x()-(int)(newx-m_offset.x())%8, 4+newy-m_offset.y()-y()-(int)(newy-m_offset.y())%8 );
00332 }
00333
00334 void CNItem::moveBy( double dx, double dy )
00335 {
00336 if ( dx == 0 && dy == 0 ) return;
00337 updateConnectorPoints(false);
00338 Item::moveBy( dx, dy );
00339
00340 setWidgetsPos( QPoint( int(x()), int(y()) ) );
00341 }
00342
00343 bool CNItem::mousePressEvent( const EventInfo &info )
00344 {
00345 bool accepted = Item::mousePressEvent(info);
00346 if (!accepted) accepted = CIWidgetMgr::mousePressEvent(info);
00347 if (accepted) setChanged();
00348 return accepted;
00349 }
00350
00351 bool CNItem::mouseReleaseEvent( const EventInfo &info )
00352 {
00353 bool accepted = Item::mouseReleaseEvent(info);
00354
00355 if (!accepted) accepted = CIWidgetMgr::mouseReleaseEvent(info);
00356 if (accepted) setChanged();
00357
00358 return accepted;
00359 }
00360
00361 bool CNItem::mouseDoubleClickEvent( const EventInfo &info )
00362 {
00363 bool accepted = Item::mouseDoubleClickEvent(info);
00364 if (!accepted)
00365 accepted = CIWidgetMgr::mouseDoubleClickEvent(info);
00366 if (accepted)
00367 setChanged();
00368 return accepted;
00369 }
00370
00371 bool CNItem::mouseMoveEvent( const EventInfo &info )
00372 {
00373 bool accepted = Item::mouseMoveEvent(info);
00374 if (!accepted) accepted = CIWidgetMgr::mouseMoveEvent(info);
00375 if (accepted) setChanged();
00376 return accepted;
00377 }
00378
00379 bool CNItem::wheelEvent( const EventInfo &info )
00380 {
00381 bool accepted = Item::wheelEvent(info);
00382 if (!accepted) accepted = CIWidgetMgr::wheelEvent(info);
00383 if (accepted) setChanged();
00384 return accepted;
00385 }
00386
00387 void CNItem::enterEvent()
00388 {
00389 Item::enterEvent();
00390 CIWidgetMgr::enterEvent();
00391 setChanged();
00392 }
00393
00394 void CNItem::leaveEvent()
00395 {
00396 Item::leaveEvent();
00397 CIWidgetMgr::leaveEvent();
00398 setChanged();
00399 }
00400
00401 void CNItem::drawShape( QPainter &p )
00402 {
00403 if(!isVisible()) return;
00404
00405
00406 if(isSelected()) p.setPen(m_selectedCol);
00407
00408 p.drawPolygon(areaPoints());
00409 p.drawPolyline(areaPoints());
00410
00411 }
00412
00413 void CNItem::initPainter( QPainter &p )
00414 {
00415 if(isSelected()) p.setPen(m_selectedCol);
00416 }
00417
00418 void CNItem::updateConnectorPoints( bool add )
00419 {
00420 if(b_deleted || !isVisible()) add = false;
00421
00422 if(b_pointsAdded == add) return;
00423
00424 b_pointsAdded = add;
00425
00426 Cells *cells = p_icnDocument->cells();
00427 if (!cells) return;
00428
00429 const int cx = cells->width();
00430 const int cy = cells->height();
00431
00432 if ( cx < 1 || cy < 1 ) return;
00433
00434
00435
00436 QWMatrix m;
00437 if ( Component *c = dynamic_cast<Component*>(this) )
00438 m = c->transMatrix( c->angleDegrees(), c->flipped(), int(x()), int(y()), false );
00439
00440
00441
00442 const QPoint start_UM = QPoint( int(x()+offsetX())-cellSize, int(y()+offsetY())-cellSize );
00443 const QPoint end_UM = start_UM + QPoint( width()+2*cellSize, height()+2*cellSize );
00444
00445 const QPoint start_M = m.map(start_UM)/cellSize;
00446 const QPoint end_M = m.map(end_UM)/cellSize;
00447
00448 int sx_M = start_M.x();
00449 int ex_M = end_M.x();
00450
00451 int sy_M = start_M.y();
00452 int ey_M = end_M.y();
00453
00454
00455 if ( sx_M > ex_M ) {
00456 const int temp = sx_M;
00457 sx_M = ex_M;
00458 ex_M = temp;
00459 }
00460
00461 if ( sy_M > ey_M ) {
00462 const int temp = sy_M;
00463 sy_M = ey_M;
00464 ey_M = temp;
00465 }
00466
00467 ex_M++;
00468 ey_M++;
00469
00470 const int mult = add ? 1 : -1;
00471
00472 for ( int x = sx_M; x < ex_M; x++ )
00473 {
00474 for ( int y = sy_M; y < ey_M; y++ )
00475 {
00476 if ( p_icnDocument->isValidCellReference( x, y ) )
00477 {
00478 if ( x != sx_M && y != sy_M && x != (ex_M-1) && y != (ey_M-1) )
00479 {
00480 (*cells)[x][y].CIpenalty += mult*ICNDocument::hs_item;
00481 } else {
00482
00483 (*cells)[x][y].CIpenalty += mult*ICNDocument::hs_connector*5;
00484 }
00485 }
00486 }
00487 }
00488
00489 #if 0
00490
00491 NodeMap::iterator end = m_nodeMap.end();
00492 for ( NodeMap::iterator it = m_nodeMap.begin(); it != end; ++it )
00493 {
00494 const int x = (int)((it->second.node->x()-4)/cellSize);
00495 const int y = (int)((it->second.node->y()-4)/cellSize);
00496 if ( p_icnDocument->isValidCellReference(x,y) ) {
00497 (*cells)[x][y].CIpenalty -= mult*ICNDocument::hs_connector*5;
00498 }
00499 }
00500 #endif
00501
00502 const TextMap::iterator textMapEnd = m_textMap.end();
00503 for ( TextMap::iterator it = m_textMap.begin(); it != textMapEnd; ++it )
00504 {
00505 it.data()->updateConnectorPoints(add);
00506 }
00507
00508 const WidgetMap::iterator widgetMapEnd = m_widgetMap.end();
00509 for ( WidgetMap::iterator it = m_widgetMap.begin(); it != widgetMapEnd; ++it )
00510 {
00511 it.data()->updateConnectorPoints(add);
00512 }
00513 }
00514
00515 Text* CNItem::addDisplayText( const QString &id, const QRect & pos, const QString &display, bool internal, int flags )
00516 {
00517 Text *text = 0;
00518 TextMap::iterator it = m_textMap.find(id);
00519 if ( it != m_textMap.end() )
00520 {
00521
00522 delete it.data();
00523 m_textMap.remove(it);
00524 }
00525
00526 text = new Text( "", this, pos, canvas(), flags );
00527 text->setZ( z()+(internal?0.1:-0.1) );
00528
00529 m_textMap[id] = text;
00530
00531
00532 setDisplayText( id, display );
00533 text->show();
00534 return text;
00535 }
00536
00537 void CNItem::setDisplayText( const QString &id, const QString &display )
00538 {
00539 TextMap::iterator it = m_textMap.find(id);
00540 if ( it == m_textMap.end() )
00541 {
00542 kdError() << "CNItem::setDisplayText: Could not find text with id \""<<id<<"\""<<endl;
00543 return;
00544 }
00545 it.data()->setText(display);
00546 updateAttachedPositioning();
00547 }
00548
00549 void CNItem::removeDisplayText( const QString &id )
00550 {
00551 TextMap::iterator it = m_textMap.find(id);
00552 if ( it == m_textMap.end() ) {
00553
00554 return;
00555 }
00556
00557 it.data()->updateConnectorPoints(false);
00558 delete it.data();
00559 m_textMap.remove(it);
00560 }
00561
00562 QString CNItem::nodeId( const QString &internalNodeId )
00563 {
00564 NodeMap::iterator it = m_nodeMap.find(internalNodeId);
00565 if ( it == m_nodeMap.end() ) return "";
00566 else return it.data().id;
00567 }
00568
00569 Node *CNItem::childNode( const QString &childId )
00570 {
00571 return p_icnDocument->nodeWithID( nodeId(childId) );
00572 }
00573
00574 NodeInfo::NodeInfo()
00575 {
00576 node = 0;
00577 x = 0.;
00578 y = 0.;
00579 orientation = 0;
00580 }
00581
00582 #include "cnitem.moc"
00583