// -*- C++ -*- // // This file is part of the Coriolis Software. // Copyright (c) UPMC/LIP6 2008-2008, All Rights Reserved // // =================================================================== // // $Id$ // // x-----------------------------------------------------------------x // | | // | C O R I O L I S | // | V L S I B a c k e n d D a t a - B a s e | // | | // | Author : Jean-Paul CHAPUT | // | E-mail : Jean-Paul.Chaput@asim.lip6.fr | // | =============================================================== | // | C++ Module : "./CellWidget.cpp" | // | *************************************************************** | // | U p d a t e s | // | | // x-----------------------------------------------------------------x #include #include #include #include #include #include #include #include #include "hurricane/DataBase.h" #include "hurricane/Technology.h" #include "hurricane/BasicLayer.h" #include "hurricane/Cell.h" #include "hurricane/Instance.h" #include "hurricane/Slice.h" #include "hurricane/Segment.h" #include "hurricane/Horizontal.h" #include "hurricane/Vertical.h" #include "hurricane/Contact.h" #include "hurricane/Pad.h" #include "hurricane/RoutingPad.h" #include "hurricane/ExtensionGo.h" #include "hurricane/viewer/Graphics.h" #include "hurricane/viewer/PaletteItem.h" #include "hurricane/viewer/PaletteWidget.h" // #include "MapView.h" #include "hurricane/viewer/Command.h" #include "hurricane/viewer/CellWidget.h" namespace Hurricane { // ------------------------------------------------------------------- // Collections. typedef Hurricane::Filter OccurrenceHF; typedef Hurricane::Locator OccurrenceHL; typedef Hurricane::Collection OccurrenceHC; // ------------------------------------------------------------------- // Class : "Occurrences_IsSelectable". class Occurrences_IsSelectable : public OccurrenceHF { public: inline Occurrences_IsSelectable ( const CellWidget* ); inline Occurrences_IsSelectable ( const Occurrences_IsSelectable& ); virtual OccurrenceHF* getClone () const; virtual bool accept ( Occurrence ) const; virtual string _getString () const; private: const CellWidget* _cellWidget; }; inline Occurrences_IsSelectable::Occurrences_IsSelectable ( const CellWidget* widget ) : OccurrenceHF() , _cellWidget(widget) { } inline Occurrences_IsSelectable::Occurrences_IsSelectable ( const Occurrences_IsSelectable& rhs ) : OccurrenceHF() , _cellWidget(rhs._cellWidget) { } OccurrenceHF* Occurrences_IsSelectable::getClone () const { return new Occurrences_IsSelectable(_cellWidget); } bool Occurrences_IsSelectable::accept ( Occurrence occurrence ) const { Entity* entity = occurrence.getEntity(); if ( !entity ) return false; ExtensionGo* eGo = dynamic_cast(entity); if ( eGo ) return _cellWidget->isSelectable ( eGo->getName() ); Component* component = dynamic_cast(entity); if ( component ) { return _cellWidget->isSelectable ( component->getLayer() ); } return true; } string Occurrences_IsSelectable::_getString () const { return ""; } // ------------------------------------------------------------------- // Class : "Hurricane::CellWidget::Spot". CellWidget::Spot::Spot ( CellWidget* cw ) : _cellWidget(cw) , _spotPoint() , _restore(false) , _showSpot(true) { } void CellWidget::Spot::restore () { if ( _restore ) { _cellWidget->getDrawingPlanes().copyToScreen ( _spotPoint.x()-5, _spotPoint.y()-5, 10, 10 ); _restore = false; } } void CellWidget::Spot::setRestore ( bool state ) { _restore = state; } QPoint CellWidget::Spot::computeSpotPoint ( const QPoint& screenPoint ) { Point mousePoint = _cellWidget->screenToDbuPoint ( screenPoint ); Point spotPoint = Point ( DbU::getOnSnapGrid(mousePoint.getX()) , DbU::getOnSnapGrid(mousePoint.getY()) ); return _cellWidget->dbuToScreenPoint(spotPoint); } void CellWidget::Spot::moveTo ( const QPoint& screenPoint ) { restore (); if ( !_showSpot ) return; _restore = true; QPainter& screenPainter = _cellWidget->getDrawingPlanes().painter(PlaneId::Widget); _spotPoint = computeSpotPoint ( screenPoint ); screenPainter.setPen ( Graphics::getPen("spot") ); screenPainter.drawRect ( _spotPoint.x()-3, _spotPoint.y()-3, 6, 6 ); } // ------------------------------------------------------------------- // Class : "Hurricane::CellWidget::RedrawEvent". CellWidget::RedrawEvent::RedrawEvent ( EventType type, int shift, CellWidget* widget ) : _type(type) , _shift(shift) { } // ------------------------------------------------------------------- // Class : "Hurricane::CellWidget::RedrawManager". CellWidget::RedrawManager::RedrawManager ( CellWidget* widget ) : _widget (widget) , _events () , _overrun(false) , _refreshInterrupt(false) { } CellWidget::RedrawManager::~RedrawManager () { while ( !_events.empty() ) { delete _events.front (); _events.pop_front (); } } void CellWidget::RedrawManager::goLeft ( int shift ) { list::iterator ievent = _events.end(); if ( !_events.empty() && (_events.back()->getType() == RedrawEvent::Refresh) ) --ievent; _events.insert ( ievent, new RedrawEvent(RedrawEvent::GoLeft,shift,_widget) ); if ( !_overrun ) { if ( _events.size() == 1 ) process (); else _overrun = true; } } void CellWidget::RedrawManager::goRight ( int shift ) { list::iterator ievent = _events.end(); if ( !_events.empty() && (_events.back()->getType() == RedrawEvent::Refresh) ) --ievent; _events.insert ( ievent, new RedrawEvent(RedrawEvent::GoRight,shift,_widget) ); if ( !_overrun ) { if ( _events.size() == 1 ) process (); else _overrun = true; } } void CellWidget::RedrawManager::goUp ( int shift ) { list::iterator ievent = _events.end(); if ( !_events.empty() && (_events.back()->getType() == RedrawEvent::Refresh) ) --ievent; _events.insert ( ievent, new RedrawEvent(RedrawEvent::GoUp,shift,_widget) ); if ( !_overrun ) { if ( _events.size() == 1 ) process (); else _overrun = true; } } void CellWidget::RedrawManager::goDown ( int shift ) { list::iterator ievent = _events.end(); if ( !_events.empty() && (_events.back()->getType() == RedrawEvent::Refresh) ) --ievent; _events.insert ( ievent, new RedrawEvent(RedrawEvent::GoDown,shift,_widget) ); if ( !_overrun ) { if ( _events.size() == 1 ) process (); else _overrun = true; } } void CellWidget::RedrawManager::refresh () { if ( !_events.empty() && (_events.back()->getType() == RedrawEvent::Refresh) ) { _refreshInterrupt = true; } else if ( _events.empty() ) { _events.push_back ( new RedrawEvent(RedrawEvent::Refresh,0,_widget) ); if ( !_overrun ) { if ( _events.size() == 1 ) process (); else _overrun = true; } } } inline void CellWidget::RedrawManager::process () { while ( !_events.empty() ) { RedrawEvent* event = _events.front (); switch ( event->getType() ) { case RedrawEvent::GoLeft: _widget->_goLeft ( event->getShift() ); break; case RedrawEvent::GoRight: _widget->_goRight ( event->getShift() ); break; case RedrawEvent::GoUp: _widget->_goUp ( event->getShift() ); break; case RedrawEvent::GoDown: _widget->_goDown ( event->getShift() ); break; case RedrawEvent::Refresh: _widget->_refresh (); break; } if ( event->getType() == RedrawEvent::Refresh ) _events.pop_back (); else _events.pop_front (); delete event; if ( _events.empty() && (_overrun || _refreshInterrupt) ) { _events.push_back ( new RedrawEvent(RedrawEvent::Refresh,0,_widget) ); _overrun = false; _refreshInterrupt = false; } } } // ------------------------------------------------------------------- // Class : "Hurricane::CellWidget::DrawingPlanes". CellWidget::DrawingPlanes::DrawingPlanes ( const QSize& size, CellWidget* cw ) : _cellWidget(cw) , _printer(NULL) , _normalPen() , _linePen() , _workingPlane(0) , _lineMode(false) { for ( size_t i=0 ; i<2 ; i++ ) _planes[i] = new QPixmap ( size ); } CellWidget::DrawingPlanes::~DrawingPlanes () { for ( size_t i=0 ; i<2 ; i++ ) { if ( _painters[i].isActive() ) _painters[i].end(); delete _planes[i]; } } void CellWidget::DrawingPlanes::setPen ( const QPen& pen ) { _normalPen = pen; _linePen = pen; _linePen.setStyle ( Qt::SolidLine ); _linePen.setWidth ( 1 ); if ( _lineMode ) { _painters[0].setPen ( _linePen ); _painters[1].setPen ( _linePen ); } else { _painters[0].setPen ( _normalPen ); _painters[1].setPen ( _normalPen ); } } void CellWidget::DrawingPlanes::setBrush ( const QBrush& brush ) { _painters[PlaneId::Normal ].setBrush ( brush ); _painters[PlaneId::Selection].setBrush ( brush ); } void CellWidget::DrawingPlanes::setBackground ( const QBrush& brush ) { _painters[PlaneId::Normal ].setBackground ( brush ); _painters[PlaneId::Selection].setBackground ( brush ); } void CellWidget::DrawingPlanes::setBackgroundMode ( Qt::BGMode mode ) { _painters[PlaneId::Normal ].setBackgroundMode ( mode ); _painters[PlaneId::Selection].setBackgroundMode ( mode ); } void CellWidget::DrawingPlanes::setLineMode ( bool mode ) { if ( _lineMode != mode ) { _lineMode = mode; if ( _lineMode ) painter().setPen ( _linePen ); else painter().setPen ( _normalPen ); } } void CellWidget::DrawingPlanes::resize ( const QSize& size ) { for ( size_t i=0 ; i<2 ; i++ ) { bool activePainter = _painters[i].isActive(); if ( activePainter ) _painters[i].end(); delete _planes[i]; _planes[i] = new QPixmap ( size ); if ( activePainter ) _painters[i].begin ( _planes[i] ); } } void CellWidget::DrawingPlanes::shiftLeft ( int dx ) { paintersBegin (); _painters[PlaneId::Normal ].drawPixmap ( dx, 0, *_planes[0], 0, 0, width()-dx, height() ); _painters[PlaneId::Selection].drawPixmap ( dx, 0, *_planes[1], 0, 0, width()-dx, height() ); paintersEnd (); } void CellWidget::DrawingPlanes::shiftRight ( int dx ) { paintersBegin (); _painters[PlaneId::Normal ].drawPixmap ( 0, 0, *_planes[0], dx, 0, width()-dx, height() ); _painters[PlaneId::Selection].drawPixmap ( 0, 0, *_planes[1], dx, 0, width()-dx, height() ); paintersEnd (); } void CellWidget::DrawingPlanes::shiftUp ( int dy ) { paintersBegin (); _painters[PlaneId::Normal ].drawPixmap ( 0, dy, *_planes[0], 0, 0, width(), height()-dy ); _painters[PlaneId::Selection].drawPixmap ( 0, dy, *_planes[1], 0, 0, width(), height()-dy ); paintersEnd (); } void CellWidget::DrawingPlanes::shiftDown ( int dy ) { paintersBegin (); _painters[PlaneId::Normal ].drawPixmap ( 0, 0, *_planes[0], 0, dy, width(), height()-dy ); _painters[PlaneId::Selection].drawPixmap ( 0, 0, *_planes[1], 0, dy, width(), height()-dy ); paintersEnd (); } void CellWidget::DrawingPlanes::copyToSelect ( int sx, int sy, int w, int h ) { painterBegin ( PlaneId::Selection ); _painters[PlaneId::Selection].setPen ( Qt::NoPen ); _painters[PlaneId::Selection].setBackground ( Graphics::getBrush("background") ); _painters[PlaneId::Selection].eraseRect ( sx, sy, w, h ); //_painters[PlaneId::Selection].setOpacity ( 0.5 ); _painters[PlaneId::Selection].drawPixmap ( sx, sy, *_planes[0], sx, sy, w, h ); painterEnd ( PlaneId::Selection ); } void CellWidget::DrawingPlanes::copyToScreen ( int sx, int sy, int w, int h ) { if ( _cellWidget->showSelection() ) _painters[PlaneId::Widget].drawPixmap ( sx, sy , *_planes[PlaneId::Selection] , _cellWidget->getOffsetVA().rx()+sx, _cellWidget->getOffsetVA().ry()+sy , w, h ); else _painters[PlaneId::Widget].drawPixmap ( sx, sy , *_planes[PlaneId::Normal] , _cellWidget->getOffsetVA().rx()+sx, _cellWidget->getOffsetVA().ry()+sy , w, h ); } void CellWidget::DrawingPlanes::copyToPrinter ( int sx, int sy, int w, int h, QPrinter* printer ) { bool imageOnly = false; int ximage = 0; int yimage = 0; if ( !printer ) return; if ( imageOnly ) { printer->setPaperSize ( QSizeF(w,h), QPrinter::DevicePixel ); printer->setPageMargins ( 0.0, 0.0, 0.0, 0.0, QPrinter::DevicePixel ); } _printer = printer; painterBegin ( PlaneId::Printer ); if ( !imageOnly ) { QFont font ( "Bitstream Vera Sans", 12 ); font.setWeight ( QFont::Bold ); DbU::Unit x1 = _cellWidget->displayToDbuX ( sx ); DbU::Unit x2 = _cellWidget->displayToDbuX ( sx+w ); DbU::Unit y1 = _cellWidget->displayToDbuY ( sy ); DbU::Unit y2 = _cellWidget->displayToDbuY ( sy+h ); string title = "Unicorn:" + getString(_cellWidget->getCell()) + " area [ " + DbU::getValueString(x1) + " " + DbU::getValueString(y1) + " ] [ " + DbU::getValueString(x2) + " " + DbU::getValueString(y2) + " ]"; QRect titleArea = QRect ( 0, 0, _printer->width(), 50 ); _painters[PlaneId::Printer].setFont ( font ); _painters[PlaneId::Printer].drawText ( titleArea, Qt::AlignVCenter|Qt::AlignHCenter, title.c_str() ); ximage = (_printer->width() > w) ? (_printer->width()-w)/2 : 0; yimage = 100; } cerr << "sy: " << sy << " offsetVA.ry(): " << _cellWidget->getOffsetVA().ry() << endl; cerr << "w: " << w << " h:" << h << endl; if ( _cellWidget->showSelection() ) _painters[PlaneId::Printer].drawPixmap ( ximage, yimage , *_planes[PlaneId::Selection] , _cellWidget->getOffsetVA().rx()+sx, _cellWidget->getOffsetVA().ry()+sy , w, h ); else _painters[PlaneId::Printer].drawPixmap ( ximage, yimage , *_planes[PlaneId::Normal] , _cellWidget->getOffsetVA().rx()+sx, _cellWidget->getOffsetVA().ry()+sy , w, h ); if ( !imageOnly ) { _painters[PlaneId::Printer].setPen ( QPen(QBrush(QColor("black")), 1.0) ); _painters[PlaneId::Printer].drawRect ( ximage-2, 98, w+4, h+4 ); } painterEnd ( PlaneId::Printer ); _printer = NULL; } // ------------------------------------------------------------------- // Class : "Hurricane::CellWidget::DrawingQuery". CellWidget::DrawingQuery::DrawingQuery ( CellWidget* widget ) : Query() , _cellWidget(widget) , _drawExtensionGo(NULL) , _goCount(0) , _extensionGoCount(0) , _instanceCount(0) { } void CellWidget::DrawingQuery::setDrawExtensionGo ( const Name& name ) { map >::iterator idraw = _drawExtensionGos.find ( name ); if ( idraw != _drawExtensionGos.end() ) { _drawExtensionGo = idraw->second.second; if ( idraw->second.first ) idraw->second.first ( _cellWidget ); } else _drawExtensionGo = NULL; } bool CellWidget::DrawingQuery::hasMasterCellCallback () const { return true; } void CellWidget::DrawingQuery::masterCellCallback () { _instanceCount++; Box bbox = getTransformation().getBox(getMasterCell()->getAbutmentBox()); _cellWidget->drawBox ( bbox ); } bool CellWidget::DrawingQuery::hasGoCallback () const { return true; } void CellWidget::DrawingQuery::goCallback ( Go* go ) { drawGo ( go, getBasicLayer(), getArea(), getTransformation() ); } void CellWidget::DrawingQuery::drawGo ( const Go* go , const BasicLayer* basicLayer , const Box& area , const Transformation& transformation ) { //cerr << "DrawingQuery::drawGo() - " << go << endl; static QRect rectangle; static unsigned int state; const Component* component = dynamic_cast(go); if ( component ) { _goCount++; rectangle = _cellWidget->dbuToDisplayRect ( transformation.getBox(component->getBoundingBox(basicLayer)) ); state = ( (rectangle.width() > 2) ? 1:0) | ( (rectangle.height() > 2) ? 2:0); switch ( state ) { case 0: break; case 1: _cellWidget->drawScreenLine ( rectangle.bottomLeft(), rectangle.bottomRight() ); break; case 2: _cellWidget->drawScreenLine ( rectangle.bottomLeft(), rectangle.topLeft () ); break; case 3: _cellWidget->drawScreenRect ( rectangle ); break; } } } bool CellWidget::DrawingQuery::hasExtensionGoCallback () const { return true; } void CellWidget::DrawingQuery::extensionGoCallback ( Go* go ) { drawExtensionGo ( _cellWidget, go, getBasicLayer(), getArea(), getTransformation() ); } void CellWidget::DrawingQuery::drawExtensionGo ( CellWidget* widget , const Go* go , const BasicLayer* basicLayer , const Box& area , const Transformation& transformation ) { if ( _drawExtensionGo ) { _extensionGoCount++; _drawExtensionGo ( widget, go, basicLayer, area, transformation ); } } bool CellWidget::DrawingQuery::hasRubberCallback () const { return true; } void CellWidget::DrawingQuery::rubberCallback ( Rubber* rubber ) { drawRubber ( rubber, getArea(), getTransformation() ); } void CellWidget::DrawingQuery::drawRubber ( const Rubber* rubber , const Box& area , const Transformation& transformation ) { static QPoint center; static QPoint extremity; static QPoint steiner; switch ( _cellWidget->getRubberShape() ) { case CellWidget::Steiner: center = _cellWidget->dbuToDisplayPoint(transformation.getPoint(rubber->getBarycenter())); forEach ( Hook*, hook, rubber->getHooks() ) { extremity = _cellWidget->dbuToDisplayPoint ( transformation.getPoint(hook->getComponent()->getCenter()) ); steiner = QPoint ( extremity.x(), center.y() ); _cellWidget->drawScreenLine ( center , steiner , PlaneId::Working, false ); _cellWidget->drawScreenLine ( steiner, extremity, PlaneId::Working, false ); } break; case CellWidget::Barycentric: center = _cellWidget->dbuToDisplayPoint(transformation.getPoint(rubber->getBarycenter())); forEach ( Hook*, hook, rubber->getHooks() ) { extremity = _cellWidget->dbuToDisplayPoint ( transformation.getPoint(hook->getComponent()->getCenter()) ); _cellWidget->drawScreenLine ( center, extremity, PlaneId::Working, false ); } break; case CellWidget::Centric: default: center = _cellWidget->dbuToDisplayPoint(transformation.getPoint(rubber->getCenter())); forEach ( Hook*, hook, rubber->getHooks() ) { extremity = _cellWidget->dbuToDisplayPoint ( transformation.getPoint(hook->getComponent()->getCenter()) ); _cellWidget->drawScreenLine ( center, extremity, PlaneId::Working, false ); } break; } } // ------------------------------------------------------------------- // Class : "Hurricane::CellWidget::TextDrawingQuery". CellWidget::TextDrawingQuery::TextDrawingQuery ( CellWidget* widget ) : Query() ,_cellWidget(widget) { setBasicLayer ( NULL ); setFilter ( Query::DoMasterCells|Query::DoTerminalCells ); setStartLevel ( 0 ); setStopLevel ( 1 ); } bool CellWidget::TextDrawingQuery::hasMasterCellCallback () const { return true; } void CellWidget::TextDrawingQuery::masterCellCallback () { Box bbox = getTransformation().getBox(getMasterCell()->getAbutmentBox()); if ( getDepth() == 2 ) _cellWidget->drawText ( Point(bbox.getXMin(),bbox.getYMin()) , getInstance()->getName() , -90 , true ); } bool CellWidget::TextDrawingQuery::hasGoCallback () const { return false; } void CellWidget::TextDrawingQuery::goCallback ( Go* ) { } bool CellWidget::TextDrawingQuery::hasRubberCallback () const { return false; } void CellWidget::TextDrawingQuery::rubberCallback ( Rubber* ) { } bool CellWidget::TextDrawingQuery::hasExtensionGoCallback () const { return false; } void CellWidget::TextDrawingQuery::extensionGoCallback ( Go* ) { } // ------------------------------------------------------------------- // Class : "Hurricane::CellWidget::SelectorCriterions". CellWidget::SelectorCriterions::SelectorCriterions ( CellWidget* cw ) : _cellWidget(cw) , _criterions() { } CellWidget::SelectorCriterions::~SelectorCriterions () { clear (); } bool CellWidget::SelectorCriterions::add ( const Net* net, bool delayRedraw ) { if ( !_cellWidget->isSelected(Occurrence(net)) ) { _criterions.push_back ( new NetSelectorCriterion(net) ); _criterions.back()->doSelection ( _cellWidget, delayRedraw ); return true; } return false; } bool CellWidget::SelectorCriterions::add ( Box area ) { _criterions.push_back ( new AreaSelectorCriterion(area) ); _criterions.back()->doSelection ( _cellWidget, true ); return true; } bool CellWidget::SelectorCriterions::remove ( const Net* net, bool delayRedraw ) { if ( !_cellWidget->isSelected(Occurrence(net)) ) return false; size_t i=0; for ( ; i<_criterions.size() ; i++ ) if ( _criterions[i]->getNet() == net ) break; if ( i < _criterions.size() ) { swap ( _criterions[i], *(_criterions.end()-1) ); _criterions.back()->undoSelection ( _cellWidget, delayRedraw ); _criterions.pop_back (); } else return false; return true; } void CellWidget::SelectorCriterions::clear () { for ( size_t i=0 ; i<_criterions.size() ; i++ ) delete _criterions[i]; _criterions.clear (); } void CellWidget::SelectorCriterions::revalidate () { size_t i = 0; size_t last = _criterions.size (); while ( i < last ) { if ( _criterions[i]->isValid(_cellWidget) ) { _criterions[i]->doSelection ( _cellWidget, true ); ++i; } else swap ( _criterions[i], _criterions[--last] ); } _criterions.erase ( _criterions.begin()+last, _criterions.end() ); } // ------------------------------------------------------------------- // Class : "Hurricane::CellWidget". const int CellWidget::_stripWidth = 100; CellWidget::CellWidget ( QWidget* parent ) : QWidget(parent) , _technology(NULL) , _palette(NULL) , _displayArea(0,0,6*_stripWidth,6*_stripWidth) , _visibleArea(_stripWidth,_stripWidth,4*_stripWidth,4*_stripWidth) , _scale(1.0) , _offsetVA(_stripWidth,_stripWidth) , _redrawManager(this) , _drawingPlanes(QSize(6*_stripWidth,6*_stripWidth),this) , _drawingQuery(this) , _textDrawingQuery(this) , _queryFilter(~Query::DoTerminalCells) , _darkening(100) , _mousePosition(0,0) , _spot(this) , _cell(NULL) , _cellChanged(true) , _showBoundaries(true) , _showSelection(false) , _cumulativeSelection(false) , _selectionHasChanged(false) , _delaySelectionChanged(0) , _cellModificated(true) , _selectors() , _selection(this) , _commands() , _redrawRectCount(0) , _textFontHeight(20) , _rubberShape(Steiner) { //setBackgroundRole ( QPalette::Dark ); //setAutoFillBackground ( false ); setAttribute ( Qt::WA_OpaquePaintEvent ); //setAttribute ( Qt::WA_NoSystemBackground ); //setAttribute ( Qt::WA_PaintOnScreen ); //setAttribute ( Qt::WA_StaticContents ); setSizePolicy ( QSizePolicy::Expanding, QSizePolicy::Expanding ); setFocusPolicy ( Qt::StrongFocus ); setMouseTracking ( true ); //_mapView = new MapView ( this ); DataBase* database = DataBase::getDB(); if ( database ) _technology = database->getTechnology (); QFont font = Graphics::getNormalFont(); _textFontHeight = QFontMetrics(font).ascent(); } CellWidget::~CellWidget () { cerr << "CellWidget::~CellWidget()" << endl; for ( size_t i=0 ; i<_commands.size() ; i++ ) unbindCommand ( _commands[i] ); } void CellWidget::styleChange ( void* emitter ) { refresh (); emit styleChanged(emitter); } void CellWidget::updatePalette () { emit updatePalette(getCell()); } void CellWidget::bindToPalette ( PaletteWidget* palette ) { detachFromPalette (); _palette = palette; connect ( _palette, SIGNAL(paletteChanged()) , this , SLOT(refresh()) ); connect ( this , SIGNAL(cellChanged(Cell*)) , _palette, SLOT(updateExtensions(Cell*)) ); connect ( this , SIGNAL(updatePalette(Cell*)), _palette, SLOT(updateExtensions(Cell*)) ); connect ( this , SIGNAL(styleChanged(void*)) , _palette, SLOT(styleChange(void*)) ); } void CellWidget::detachFromPalette () { if ( _palette ) { disconnect ( _palette, SIGNAL(paletteChanged()) , this , SLOT(refresh()) ); disconnect ( this , SIGNAL(cellChanged(Cell*)) , _palette, SLOT(updateExtensions(Cell*)) ); disconnect ( this , SIGNAL(updatePalette(Cell*)), _palette, SLOT(updateExtensions(Cell*)) ); disconnect ( this , SIGNAL(styleChanged(void*)) , _palette, SLOT(styleChange(void*)) ); _palette = NULL; } } void CellWidget::bindCommand ( Command* command ) { for ( size_t i=0 ; i<_commands.size() ; i++ ) if ( _commands[i] == command ) return; _commands.push_back ( command ); } void CellWidget::unbindCommand ( Command* command ) { size_t i = 0; for ( ; i<_commands.size() ; i++ ) if ( _commands[i] == command ) break; for ( ; i+1<_commands.size() ; i++ ) _commands[i] = _commands[i+1]; _commands.pop_back (); } void CellWidget::pushCursor ( Qt::CursorShape cursor ) { setCursor ( cursor ); _cursors.push_back ( cursor ); } void CellWidget::popCursor () { _cursors.pop_back (); if ( !_cursors.empty() ) setCursor ( _cursors.back() ); else unsetCursor (); } QSize CellWidget::minimumSizeHint () const { return QSize(_stripWidth*4,_stripWidth*4); } void CellWidget::rubberChange () { switch ( getRubberShape() ) { case Centric: setRubberShape(Barycentric); break; case Barycentric: setRubberShape(Steiner ); break; case Steiner: setRubberShape(Centric ); break; } emit settingsChanged(); } void CellWidget::setShowSelection ( bool state ) { if ( state != _showSelection ) { _showSelection = state; _selectionHasChanged = false; refresh (); emit showSelectionToggled ( state ); } } void CellWidget::setCumulativeSelection ( bool state ) { _cumulativeSelection = state; } void CellWidget::_redraw ( QRect redrawArea ) { // cerr << "CellWidget::redraw() - start " // << _selectionHasChanged << " filter:" // << _queryFilter << endl; static bool timedout; static Timer timer; if ( !isVisible() ) return; timer.start (); timedout = false; _cellChanged = false; _redrawRectCount = 0; pushCursor ( Qt::BusyCursor ); if ( ! ( _selectionHasChanged && _showSelection ) || _cellModificated ) { _spot.setRestore ( false ); _drawingPlanes.copyToSelect ( redrawArea ); _drawingPlanes.select ( PlaneId::Normal ); _drawingPlanes.painterBegin (); _drawingPlanes.painter().setPen ( Qt::NoPen ); _drawingPlanes.painter().setBackground ( Graphics::getBrush("background") ); _drawingPlanes.painter().setClipRect ( redrawArea ); _drawingPlanes.painter().eraseRect ( redrawArea ); repaint (); setDarkening ( (_showSelection) ? Graphics::getDarkening() : 100 ); if ( _cell ) { Box redrawBox = displayToDbuBox ( redrawArea ); _drawingQuery.resetGoCount (); _drawingQuery.resetExtensionGoCount(); _drawingQuery.resetInstanceCount(); _drawingQuery.setExtensionMask ( 0 ); _drawingQuery.setArea ( redrawBox ); _drawingQuery.setTransformation ( Transformation() ); forEach ( BasicLayer*, iLayer, _technology->getBasicLayers() ) { _drawingPlanes.setPen ( Graphics::getPen ((*iLayer)->getName(),getDarkening()) ); _drawingPlanes.setBrush ( Graphics::getBrush((*iLayer)->getName(),getDarkening()) ); if ( isDrawable((*iLayer)->getName()) ) { _drawingQuery.setBasicLayer ( *iLayer ); _drawingQuery.setFilter ( _queryFilter & ~(Query::DoMasterCells|Query::DoRubbers) ); _drawingQuery.doQuery (); _drawingPlanes.copyToSelect ( redrawArea ); repaint (); } QApplication::processEvents(); if ( _redrawManager.interrupted() ) { //cerr << "CellWidget::redraw() - interrupt after " << (*iLayer)->getName() << endl; break; } //if ( timeout("redraw [layer]",timer,10.0,timedout) ) break; } if ( /*!timeout("redraw [boundaries]",timer,10.0,timedout) &&*/ (!_redrawManager.interrupted()) ) { if ( isDrawable("boundaries") ) { _drawingPlanes.setPen ( Graphics::getPen ("boundaries",getDarkening()) ); _drawingPlanes.setBrush ( Graphics::getBrush("boundaries",getDarkening()) ); _drawingQuery.setBasicLayer ( NULL ); _drawingQuery.setFilter ( _queryFilter & ~(Query::DoComponents|Query::DoRubbers) ); _drawingQuery.doQuery (); _drawingPlanes.copyToSelect ( redrawArea ); repaint (); } } if ( /*!timeout("redraw [rubbers]",timer,10.0,timedout) &&*/ (!_redrawManager.interrupted()) ) { if ( isDrawable("rubber") ) { _drawingPlanes.setPen ( Graphics::getPen ("rubber",getDarkening()) ); _drawingPlanes.setBrush ( Graphics::getBrush("rubber",getDarkening()) ); _drawingQuery.setBasicLayer ( NULL ); _drawingQuery.setFilter ( _queryFilter & ~(Query::DoComponents|Query::DoMasterCells) ); _drawingQuery.doQuery (); _drawingPlanes.copyToSelect ( redrawArea ); repaint (); } } QApplication::processEvents(); if ( /*!timeout("redraw [text.instances]",timer,10.0,timedout) &&*/ (!_redrawManager.interrupted()) ) { if ( isDrawable("text.instance") ) { _drawingPlanes.setPen ( Graphics::getPen ("text.instance",getDarkening()) ); _drawingPlanes.setBrush ( Graphics::getBrush("text.instance",getDarkening()) ); _drawingPlanes.setBackground ( Graphics::getBrush("boundaries" ,getDarkening()) ); _textDrawingQuery.setArea ( redrawBox ); _textDrawingQuery.setTransformation ( Transformation() ); _textDrawingQuery.doQuery (); _drawingPlanes.copyToSelect ( redrawArea ); repaint (); } } //_drawingQuery.setFilter ( _queryFilter & ~Query::DoMasterCells ); forEach ( ExtensionSlice*, islice, _cell->getExtensionSlices() ) { QApplication::processEvents(); if ( /*timeout("redraw [extension]",timer,10.0,timedout) ||*/ (_redrawManager.interrupted()) ) break; if ( isDrawableExtension((*islice)->getName()) ) { _drawingQuery.setExtensionMask ( (*islice)->getMask() ); _drawingQuery.setDrawExtensionGo ( (*islice)->getName() ); _drawingQuery.setFilter ( Query::DoExtensionGos ); _drawingQuery.doQuery (); _drawingPlanes.copyToSelect ( redrawArea ); repaint (); } } } _drawingPlanes.painterEnd (); _cellModificated = false; } setDarkening ( 100 ); if ( _showSelection ) redrawSelection ( redrawArea ); popCursor (); timer.stop (); cerr << "CellWidget::redraw() - " << _redrawRectCount << " in " << timer.getCombTime() << "s (" << setprecision(3) << (timer.getCombTime()/_redrawRectCount) << " s/r)"; if ( _drawingQuery.getGoCount() ) cerr << " " << _drawingQuery.getGoCount() << " (" << setprecision(3) << (timer.getCombTime()/_drawingQuery.getGoCount()) << " s/go)"; else cerr << " 0 Gos"; if ( _drawingQuery.getExtensionGoCount() ) cerr << " " << _drawingQuery.getExtensionGoCount() << " (" << setprecision(3) << (timer.getCombTime()/_drawingQuery.getExtensionGoCount()) << " s/ego)"; else cerr << " 0 eGos"; if ( _drawingQuery.getInstanceCount() ) cerr << " " << _drawingQuery.getInstanceCount() << " (" << setprecision(3) << (timer.getCombTime()/_drawingQuery.getInstanceCount()) << " s/inst)"; else cerr << " 0 Instances"; cerr << endl; } void CellWidget::redrawSelection ( QRect redrawArea ) { _drawingPlanes.copyToSelect ( redrawArea.x() , redrawArea.y() , redrawArea.width() , redrawArea.height() ); _drawingPlanes.select ( PlaneId::Selection ); _drawingPlanes.painterBegin (); _drawingPlanes.painter().setPen ( Qt::NoPen ); _drawingPlanes.painter().setBackground ( Graphics::getBrush("background") ); _drawingPlanes.painter().setClipRect ( redrawArea ); if ( _cell ) { Box redrawBox = displayToDbuBox ( redrawArea ); SelectorSet::iterator iselector; forEach ( BasicLayer*, basicLayer, _technology->getBasicLayers() ) { //if ( !isDrawableLayer(basicLayer->getName()) ) continue; _drawingPlanes.setPen ( Graphics::getPen (basicLayer->getName()) ); _drawingPlanes.setBrush ( Graphics::getBrush(basicLayer->getName()) ); iselector = _selectors.begin (); for ( ; iselector != _selectors.end() ; iselector++ ) { Occurrence occurrence = (*iselector)->getOccurrence(); Transformation transformation = occurrence.getPath().getTransformation(); Instance* instance = dynamic_cast(occurrence.getEntity()); if ( instance ) { // Temporary. //drawInstance ( instance, basicLayer, redrawBox, transformation ); continue; } Component* component = dynamic_cast(occurrence.getEntity()); if ( !component ) break; if ( !component->getLayer() ) continue; if ( !component->getLayer()->contains(*basicLayer) ) continue; _drawingQuery.drawGo ( dynamic_cast(occurrence.getEntity()) , *basicLayer , redrawBox , transformation ); } } _drawingPlanes.setPen ( Graphics::getPen ("rubber") ); _drawingPlanes.setBrush ( Graphics::getBrush("rubber") ); for ( ; iselector != _selectors.end() ; iselector++ ) { Occurrence occurrence = (*iselector)->getOccurrence(); Transformation transformation = occurrence.getPath().getTransformation(); Rubber* rubber = dynamic_cast(occurrence.getEntity()); if ( !rubber ) break; _drawingQuery.drawRubber ( rubber, redrawBox, transformation ); } Name extensionName = ""; for ( ; iselector != _selectors.end() ; iselector++ ) { Occurrence occurrence = (*iselector)->getOccurrence(); Transformation transformation = occurrence.getPath().getTransformation(); ExtensionGo* eGo = dynamic_cast(occurrence.getEntity()); if ( !eGo ) break; if ( eGo->getName() != extensionName ) { extensionName = eGo->getName(); _drawingQuery.setDrawExtensionGo ( extensionName ); } if ( isDrawable(extensionName) ) _drawingQuery.drawExtensionGo ( this, eGo, NULL, redrawBox, transformation ); } repaint (); } _drawingPlanes.painterEnd (); _selectionHasChanged = false; } bool CellWidget::isDrawable ( const Name& name ) { PaletteItem* item = (_palette) ? _palette->find(name) : NULL; return (!item || item->isItemVisible()) && ( Graphics::getThreshold(name)/DbU::lambda(1.0) < _scale ); } bool CellWidget::isDrawableLayer ( const Name& layerName ) { PaletteItem* item = (_palette) ? _palette->find(layerName) : NULL; return !item || item->isItemVisible(); } bool CellWidget::isDrawableExtension ( const Name& extensionName ) { PaletteItem* item = (_palette) ? _palette->find(extensionName) : NULL; return (!item || item->isItemVisible()); } bool CellWidget::isSelectable ( const Name& name ) const { PaletteItem* item = (_palette) ? _palette->find(name) : NULL; return (!item || item->isItemSelectable()); } bool CellWidget::isSelectable ( const Layer* layer ) const { PaletteItem* item = NULL; forEach ( BasicLayer*, ilayer, layer->getBasicLayers() ) { item = (_palette) ? _palette->find(ilayer->getName()) : NULL; if ( item && item->isItemSelectable() ) return true; } return false; } void CellWidget::drawBox ( DbU::Unit x1, DbU::Unit y1, DbU::Unit x2, DbU::Unit y2 ) { _redrawRectCount++; _drawingPlanes.setLineMode ( false ); _drawingPlanes.painter().drawRect ( dbuToDisplayRect(x1,y1,x2,y2) ); } void CellWidget::drawBox ( const Box& box ) { _redrawRectCount++; _drawingPlanes.setLineMode ( false ); _drawingPlanes.painter().drawRect ( dbuToDisplayRect(box) ); } void CellWidget::drawText ( const Point& point, const Name& text, int angle, bool reverse ) { _drawingPlanes.painter().save(); if ( reverse ) { _drawingPlanes.painter().setPen ( Graphics::getPen ("background") ); _drawingPlanes.painter().setBackgroundMode ( Qt::OpaqueMode ); } _drawingPlanes.painter().translate( dbuToDisplayPoint(point) ); _drawingPlanes.painter().rotate( angle ); _drawingPlanes.painter().drawText ( 0, _textFontHeight, getString(text).c_str() ); _drawingPlanes.painter().restore(); } void CellWidget::drawLine ( DbU::Unit x1, DbU::Unit y1, DbU::Unit x2, DbU::Unit y2, bool mode ) { _redrawRectCount++; _drawingPlanes.setLineMode ( mode ); _drawingPlanes.painter().drawLine ( dbuToDisplayPoint(x1,y1), dbuToDisplayPoint(x2,y2) ); } void CellWidget::drawLine ( const Point& p1, const Point& p2, bool mode ) { _redrawRectCount++; _drawingPlanes.setLineMode ( mode ); _drawingPlanes.painter().drawLine ( dbuToDisplayPoint(p1), dbuToDisplayPoint(p2) ); } void CellWidget::drawScreenLine ( const QPoint& p1, const QPoint& p2, size_t plane, bool mode ) { _redrawRectCount++; _drawingPlanes.setLineMode ( mode ); _drawingPlanes.painter(plane).drawLine ( p1, p2 ); } void CellWidget::drawScreenPolyline ( const QPoint* points, int count, int width, size_t plane ) { QPen pen = _drawingPlanes.painter(plane).pen (); pen.setWidth ( width ); _drawingPlanes.painter(plane).setPen ( pen ); _drawingPlanes.painter(plane).drawPolyline ( points, count ); } void CellWidget::drawScreenRect ( const QPoint& p1, const QPoint& p2, size_t plane ) { _drawingPlanes.setLineMode ( false ); _drawingPlanes.painter(plane).drawRect ( QRect(p1,p2) ); } void CellWidget::drawScreenRect ( const QRect& r, size_t plane ) { _redrawRectCount++; _drawingPlanes.setLineMode ( false ); _drawingPlanes.painter(plane).drawRect ( r ); } void CellWidget::drawGrid () { _drawingPlanes.painter(PlaneId::Widget).setPen ( Graphics::getPen("grid") ); bool lambdaGrid = false; if ( Graphics::getThreshold("grid")/DbU::lambda(1.0) < _scale/5 ) lambdaGrid = true; DbU::Unit gridStep = DbU::getSnapGridStep(); DbU::Unit superGridStep = gridStep*5; DbU::Unit xGrid; DbU::Unit yGrid; QPoint center; for ( yGrid = DbU::getOnSnapGrid(_visibleArea.getYMin()) ; yGrid < _visibleArea.getYMax() ; yGrid += gridStep ) { for ( xGrid = DbU::getOnSnapGrid(_visibleArea.getXMin()) ; xGrid < _visibleArea.getXMax() ; xGrid += gridStep ) { center = dbuToScreenPoint(xGrid,yGrid); if ( (xGrid % superGridStep) || (yGrid % superGridStep) ) { if ( lambdaGrid ) _drawingPlanes.painter(PlaneId::Widget).drawPoint ( center ); } else { if ( lambdaGrid ) { _drawingPlanes.painter(PlaneId::Widget).drawLine ( center.x()-3, center.y() , center.x()+3, center.y() ); _drawingPlanes.painter(PlaneId::Widget).drawLine ( center.x() , center.y()-3, center.x() , center.y()+3 ); } else { _drawingPlanes.painter(PlaneId::Widget).drawPoint ( center ); } } } } } void CellWidget::goLeft ( int dx ) { if ( !dx ) dx = geometry().size().width() / 4; _redrawManager.goLeft ( dx ); } void CellWidget::goRight ( int dx ) { if ( !dx ) dx = geometry().size().width() / 4; _redrawManager.goRight ( dx ); } void CellWidget::goUp ( int dy ) { if ( !dy ) dy = geometry().size().height() / 4; _redrawManager.goUp ( dy ); } void CellWidget::goDown ( int dy ) { if ( !dy ) dy = geometry().size().height() / 4; _redrawManager.goDown ( dy ); } void CellWidget::displayReframe ( bool delayed ) { _offsetVA.rx() = _stripWidth; _offsetVA.ry() = _stripWidth; DbU::Unit xmin = (DbU::Unit)( _visibleArea.getXMin() - ((float)_offsetVA.x()/_scale) ); DbU::Unit xmax = (DbU::Unit)( xmin + ((float)_drawingPlanes.width()/_scale) ) ; DbU::Unit ymax = (DbU::Unit)( _visibleArea.getYMax() + ((float)_offsetVA.y()/_scale) ); DbU::Unit ymin = (DbU::Unit)( ymax - ((float)_drawingPlanes.height()/_scale) ) ; _displayArea = Box ( xmin, ymin, xmax, ymax ); if ( !delayed ) _redrawManager.refresh (); } void CellWidget::setScale ( float scale ) { _scale = scale; Point center = _visibleArea.getCenter(); _visibleArea.makeEmpty (); _visibleArea.merge ( (DbU::Unit)( center.getX() - width () / (_scale*2) ) , (DbU::Unit)( center.getY() - height() / (_scale*2) ) , (DbU::Unit)( center.getX() + width () / (_scale*2) ) , (DbU::Unit)( center.getY() + height() / (_scale*2) ) ); //cerr << "_visibleArea: " << _visibleArea << " (offset: " << _offsetVA.x() << ")" << endl; //cerr << " " << center << endl; displayReframe (); } void CellWidget::reframe ( const Box& box, bool delayed ) { //cerr << "CellWidget::reframe() - " << box << endl; //cerr << " widget size := " << _drawingPlanes.width() << "x" << _drawingPlanes.height() << endl; //cerr << " CellWidget::reframe() - widget size := " << width() << "x" << height() << endl; int width = this->width (); int height = this->height (); float scaleX = width / (float)box.getWidth (); float scaleY = height / (float)box.getHeight(); _scale = min ( scaleX, scaleY ); Point center = box.getCenter(); width /= 2; height /= 2; _visibleArea = Box ( (DbU::Unit)( center.getX() - width / _scale ) , (DbU::Unit)( center.getY() - height / _scale ) , (DbU::Unit)( center.getX() + width / _scale ) , (DbU::Unit)( center.getY() + height / _scale ) ); displayReframe ( delayed ); //cerr << " _displayArea: " << _displayArea << " (offset: " << _offsetVA.x() << ")" << endl; } void CellWidget::fitToContents ( bool delayed ) { Box boundingBox = Box ( DbU::lambda(0) , DbU::lambda(0) , DbU::lambda(10) , DbU::lambda(50) ); if ( _cell ) boundingBox = _cell->getBoundingBox(); reframe ( boundingBox, delayed ); } void CellWidget::_goLeft ( int dx ) { _visibleArea.translate ( - (DbU::Unit)( dx / _scale ) , 0 ); if ( _offsetVA.rx() - dx >= 0 ) { _offsetVA.rx() -= dx; repaint (); return; } int shift = ( 1 + ( dx - _offsetVA.rx() ) / _stripWidth ) * _stripWidth; _displayArea.translate ( - (DbU::Unit)( shift / _scale ) , 0 ); _offsetVA.rx() -= dx - shift; if ( shift >= _drawingPlanes.width() ) _redrawManager.refresh (); else { _drawingPlanes.shiftLeft ( shift ); _redraw ( QRect ( QPoint(0,0), QSize(shift,_drawingPlanes.height()) ) ); } assert ( _offsetVA.rx() >= 0 ); } void CellWidget::_goRight ( int dx ) { //cerr << "CellWidget::goRight() - dx: " << dx << " (offset: " << _offsetVA.rx() << ")" << endl; _visibleArea.translate ( (DbU::Unit)( dx / _scale ) , 0 ); if ( _offsetVA.rx() + dx < 2*_stripWidth ) { _offsetVA.rx() += dx; repaint (); return; } int shift = ( ( _offsetVA.rx() + dx ) / _stripWidth ) * _stripWidth; _displayArea.translate ( (DbU::Unit)( shift / _scale ) , 0 ); _offsetVA.rx() += dx - shift; if ( shift >= _drawingPlanes.width() ) _redrawManager.refresh (); else { _drawingPlanes.shiftRight ( shift ); _redraw ( QRect ( QPoint(_drawingPlanes.width()-shift,0) , QSize (shift,_drawingPlanes.height()) ) ); } assert ( _offsetVA.rx() >= 0 ); } void CellWidget::_goUp ( int dy ) { //cerr << "CellWidget::shiftUp() - " << dy << " (offset: " << _offsetVA.ry() << ")" << endl; _visibleArea.translate ( 0, (DbU::Unit)( dy / _scale ) ); if ( _offsetVA.ry() - dy >= 0 ) { _offsetVA.ry() -= dy; repaint (); return; } int shift = ( 1 + ( dy - _offsetVA.ry() ) / _stripWidth ) * _stripWidth; _displayArea.translate ( 0, (DbU::Unit)( shift / _scale ) ); _offsetVA.ry() -= dy - shift; if ( shift >= _drawingPlanes.height() ) _redrawManager.refresh (); else { _drawingPlanes.shiftUp ( shift ); _redraw ( QRect ( QPoint(0,0), QSize(_drawingPlanes.width(),shift) ) ); } assert ( _offsetVA.ry() >= 0 ); } void CellWidget::_goDown ( int dy ) { //cerr << "CellWidget::shiftDown() - " << dy << " (offset: " << _offsetVA.ry() << ")" << endl; _visibleArea.translate ( 0, - (DbU::Unit)( dy / _scale ) ); if ( _offsetVA.ry() + dy < 2*_stripWidth ) { _offsetVA.ry() += dy; repaint (); return; } int shift = ( ( _offsetVA.ry() + dy ) / _stripWidth ) * _stripWidth; _displayArea.translate ( 0, - (DbU::Unit)( shift / _scale ) ); _offsetVA.ry() += dy - shift; if ( shift >= _drawingPlanes.height() ) _redrawManager.refresh (); else { _drawingPlanes.shiftDown ( shift ); _redraw ( QRect ( QPoint (0,_drawingPlanes.height()-shift) , QSize (_drawingPlanes.width(), shift) ) ); } assert ( _offsetVA.ry() >= 0 ); } void CellWidget::_refresh () { _redraw ( QRect(QPoint(0,0),_drawingPlanes.size()) ); } void CellWidget::showEvent ( QShowEvent* ) { //cerr << "CellWidget::showEvent() - size: " << geometry().width() << "x" << geometry().height() << endl; if ( _cellChanged ) fitToContents(); } void CellWidget::paintEvent ( QPaintEvent* event ) { _drawingPlanes.painterBegin ( PlaneId::Widget ); _drawingPlanes.copyToScreen (); for ( size_t i=0 ; i<_commands.size() ; i++ ) _commands[i]->draw ( this ); if ( isDrawable("grid") ) drawGrid (); if ( isDrawable("spot") ) _spot.moveTo ( _mousePosition ); _drawingPlanes.painterEnd ( PlaneId::Widget ); } void CellWidget::resizeEvent ( QResizeEvent* ) { //cerr << "CellWidget::resizeEvent() - size: " << geometry().width() << "x" << geometry().height() << endl; QSize uaDelta ( 0, 0 ); QSize uaSize = geometry().size(); uaSize.rwidth () += 2*_stripWidth; uaSize.rheight() += 2*_stripWidth; if ( uaSize.width () > _drawingPlanes.width () ) uaDelta.rwidth () = uaSize.width () - _drawingPlanes.width (); if ( uaSize.height() > _drawingPlanes.height() ) uaDelta.rheight() = uaSize.height() - _drawingPlanes.height(); if ( uaDelta.width() || uaDelta.height() ) { _displayArea.inflate ( 0, 0, (DbU::Unit)(uaDelta.width()/_scale), (DbU::Unit)(uaDelta.height()/_scale) ); _visibleArea.inflate ( 0, 0, (DbU::Unit)(uaDelta.width()/_scale), (DbU::Unit)(uaDelta.height()/_scale) ); QSize bufferSize ( ( ( uaSize.width () / _stripWidth ) + 1 ) * _stripWidth , ( ( uaSize.height() / _stripWidth ) + 1 ) * _stripWidth ); _drawingPlanes.resize ( bufferSize ); } _redrawManager.refresh (); } void CellWidget::wheelEvent ( QWheelEvent* event ) { bool commandActive = false; for ( size_t i=0 ; i<_commands.size() && !commandActive; i++ ) commandActive = _commands[i]->wheelEvent ( this, event ); if ( !commandActive ) QWidget::wheelEvent ( event ); } void CellWidget::keyPressEvent ( QKeyEvent* event ) { bool commandActive = false; for ( size_t i=0 ; i<_commands.size() && !commandActive; i++ ) commandActive = _commands[i]->keyPressEvent ( this, event ); if ( !commandActive ) QWidget::keyPressEvent ( event ); } void CellWidget::keyReleaseEvent ( QKeyEvent* event ) { bool commandActive = false; for ( size_t i=0 ; i<_commands.size() && !commandActive; i++ ) commandActive = _commands[i]->keyReleaseEvent ( this, event ); if ( !commandActive ) QWidget::keyReleaseEvent ( event ); } void CellWidget::mouseMoveEvent ( QMouseEvent* event ) { bool commandActive = false; for ( size_t i=0 ; i<_commands.size() && !commandActive; i++ ) commandActive = _commands[i]->mouseMoveEvent ( this, event ); if ( !commandActive ) { Point mousePoint = screenToDbuPoint ( _mousePosition = event->pos() ); emit mousePositionChanged ( Point ( DbU::getOnSnapGrid(mousePoint.getX()) , DbU::getOnSnapGrid(mousePoint.getY()) ) ); repaint (); } } void CellWidget::mousePressEvent ( QMouseEvent* event ) { bool commandActive = false; for ( size_t i=0 ; i<_commands.size() && !commandActive; i++ ) commandActive = _commands[i]->mousePressEvent ( this, event ); _spot.setShowSpot ( !commandActive ); } void CellWidget::mouseReleaseEvent ( QMouseEvent* event ) { bool commandActive = false; for ( size_t i=0 ; i<_commands.size() && !commandActive; i++ ) commandActive = _commands[i]->mouseReleaseEvent ( this, event ); _spot.setShowSpot ( true ); } QPoint CellWidget::dbuToDisplayPoint ( DbU::Unit x, DbU::Unit y ) const { return QPoint ( dbuToDisplayX(x), dbuToDisplayY(y) ); } QPoint CellWidget::dbuToDisplayPoint ( const Point& point ) const { return dbuToDisplayPoint ( point.getX(), point.getY() ); } QRect CellWidget::dbuToDisplayRect ( DbU::Unit x1, DbU::Unit y1, DbU::Unit x2, DbU::Unit y2, bool usePoint ) const { int width, height; if ( usePoint ) { width = dbuToDisplayX(x2) - dbuToDisplayX(x1); height = dbuToDisplayY(y1) - dbuToDisplayY(y2); } else { width = dbuToDisplayLength ( x2 - x1 ); height = dbuToDisplayLength ( y2 - y1 ); } return QRect ( dbuToDisplayX(x1) , dbuToDisplayY(y2) , width ? width : 1 , height ? height : 1 ); } QRect CellWidget::dbuToDisplayRect ( const Box& box, bool usePoint ) const { return dbuToDisplayRect ( box.getXMin() , box.getYMin() , box.getXMax() , box.getYMax() , usePoint ); } QPoint CellWidget::dbuToScreenPoint ( DbU::Unit x, DbU::Unit y ) const { return QPoint ( dbuToScreenX(x), dbuToScreenY(y) ); } void CellWidget::setShowBoundaries ( bool state ) { if ( _showBoundaries != state ) { _showBoundaries = state; _redrawManager.refresh (); } } void CellWidget::setCell ( Cell* cell ) { //cerr << "CellWidget::setCell() - " << cell << endl; cellPreModificate (); _cellChanged = true; _cell = cell; _drawingQuery .setCell ( cell ); _textDrawingQuery.setCell ( cell ); emit cellChanged ( cell ); fitToContents ( true ); cellPostModificate (); } Occurrences CellWidget::getOccurrencesUnder ( const Box& area ) const { return getCell()->getOccurrencesUnder(area).getSubSet(Occurrences_IsSelectable(this)); } void CellWidget::select ( const Net* net, bool delayRedraw ) { ++_delaySelectionChanged; if ( !_cumulativeSelection ) unselectAll ( true ); bool added = _selection.add ( net, delayRedraw ); if ( !--_delaySelectionChanged && added ) emit selectionChanged(_selectors,_cell); } bool CellWidget::isSelected ( Occurrence occurrence ) { if ( !occurrence.isValid() ) throw Error ( "Can't select occurrence : invalid occurrence" ); if ( occurrence.getOwnerCell() != getCell() ) throw Error ( "Can't select occurrence : incompatible occurrence" ); Property* property = occurrence.getProperty ( Selector::getPropertyName() ); if ( !property ) return false; Selector* selector = dynamic_cast(property); if ( !selector ) throw Error ( "Abnormal property named " + getString(Selector::getPropertyName()) ); return selector->isAttachedTo(this); } void CellWidget::select ( Occurrence occurrence ) { if ( !occurrence.isValid() ) throw Error ( "Can't select occurrence : invalid occurrence" ); if ( occurrence.getOwnerCell() != getCell() ) throw Error ( "Can't select occurrence : incompatible occurrence" ); //if ( !_cumulativeSelection ) unselectAll ( true ); Property* property = occurrence.getProperty ( Selector::getPropertyName() ); Selector* selector = NULL; if ( !property ) selector = Selector::create ( occurrence ); else { selector = dynamic_cast(property); if ( !selector ) throw Error ( "Abnormal property named " + getString(Selector::getPropertyName()) ); } selector->attachTo(this); _selectionHasChanged = true; if ( !_delaySelectionChanged ) emit selectionChanged(_selectors,_cell); } void CellWidget::selectOccurrencesUnder ( Box selectArea ) { ++_delaySelectionChanged; if ( !_cumulativeSelection ) unselectAll ( true ); bool added = _selection.add ( selectArea ); if ( !--_delaySelectionChanged && added ) emit selectionChanged(_selectors,_cell); } void CellWidget::unselect ( const Net* net, bool delayRedraw ) { ++_delaySelectionChanged; bool removed = _selection.remove ( net, delayRedraw ); if ( !--_delaySelectionChanged && removed ) emit selectionChanged(_selectors,_cell); } void CellWidget::unselect ( Occurrence occurrence ) { if ( !occurrence.isValid() ) throw Error ( "Can't unselect occurrence : invalid occurrence" ); if ( occurrence.getOwnerCell() != getCell() ) throw Error ( "Can't unselect occurrence : incompatible occurrence" ); Property* property = occurrence.getProperty ( Selector::getPropertyName() ); if ( property ) { Selector* selector = dynamic_cast(property); if ( !selector ) throw Error ( "Abnormal property named " + getString(Selector::getPropertyName()) ); selector->detachFrom(this); } _selectionHasChanged = true; if ( !_delaySelectionChanged ) emit selectionChanged(_selectors,_cell); } void CellWidget::unselectAll ( bool delayRedraw ) { ++_delaySelectionChanged; _selection.clear (); _unselectAll ( delayRedraw ); if ( !--_delaySelectionChanged ) emit selectionChanged(_selectors,_cell); } void CellWidget::toggleSelect ( Occurrence occurrence, bool fromPopup ) { if ( !occurrence.isValid() ) throw Error ( "Can't select occurrence : invalid occurrence" ); if ( occurrence.getOwnerCell() != getCell() ) throw Error ( "Can't select occurrence : incompatible occurrence" ); Property* property = occurrence.getProperty ( Selector::getPropertyName() ); Selector* selector = NULL; if ( !property ) { selector = Selector::create ( occurrence ); selector->attachTo ( this ); } else { selector = dynamic_cast(property); if ( !selector ) throw Error ( "Abnormal property named " + getString(Selector::getPropertyName()) ); selector->detachFrom ( this ); } _selectionHasChanged = true; if ( _showSelection ) _redrawManager.refresh (); if ( fromPopup ) emit occurrenceToggled ( occurrence ); } void CellWidget::_select ( const Net* net, bool delayRedraw ) { select ( Occurrence(net) ); forEach ( Component*, component, net->getComponents() ) { Occurrence occurrence ( *component ); select ( occurrence ); } forEach ( Rubber*, rubber, net->getRubbers() ) { Occurrence occurrence ( *rubber ); select ( occurrence ); } if ( !delayRedraw && _showSelection ) _redrawManager.refresh (); } void CellWidget::_unselect ( const Net* net, bool delayRedraw ) { unselect ( Occurrence(net) ); forEach ( Component*, component, net->getComponents() ) { Occurrence occurrence ( *component ); unselect ( occurrence ); } forEach ( Rubber*, rubber, net->getRubbers() ) { Occurrence occurrence ( *rubber ); unselect ( occurrence ); } if ( !delayRedraw && _showSelection ) _redrawManager.refresh (); } void CellWidget::_selectOccurrencesUnder ( Box selectArea ) { forEach ( Occurrence, ioccurrence, getOccurrencesUnder(selectArea) ) select ( *ioccurrence ); } void CellWidget::_unselectAll ( bool delayRedraw ) { SelectorSet::iterator iselector; while ( !_selectors.empty() ) (*_selectors.begin())->detachFrom ( this ); if ( !_selectionHasChanged ) _selectionHasChanged = true; if ( !delayRedraw && _showSelection ) _redrawManager.refresh (); } void CellWidget::cellPreModificate () { _unselectAll ( true ); emit selectionChanged(_selectors,_cell); emit cellPreModificated (); } void CellWidget::cellPostModificate () { _cellModificated = true; ++_delaySelectionChanged; _selection.revalidate (); updatePalette (); _redrawManager.refresh (); --_delaySelectionChanged; emit selectionChanged(_selectors,_cell); emit cellPostModificated (); } } // End of Hurricane namespace.