coriolis/hurricane/src/viewer/PaletteWidget.cpp

496 lines
14 KiB
C++

// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC/LIP6 2008-2010, All Rights Reserved
//
// ===================================================================
//
// $Id$
//
// x-----------------------------------------------------------------x
// | |
// | H U R R I C A N E |
// | 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 : "./PaletteWidget.cpp" |
// | *************************************************************** |
// | U p d a t e s |
// | |
// x-----------------------------------------------------------------x
#include <limits>
#include <QLabel>
#include <QCheckBox>
#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGridLayout>
#include "hurricane/DataBase.h"
#include "hurricane/Technology.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/BasicLayers.h"
#include "hurricane/ExtensionSlice.h"
#include "hurricane/Cell.h"
#include "hurricane/viewer/Graphics.h"
#include "hurricane/viewer/PaletteItem.h"
#include "hurricane/viewer/PaletteNamedItem.h"
#include "hurricane/viewer/PaletteLayerItem.h"
#include "hurricane/viewer/PaletteExtensionGoItem.h"
#include "hurricane/viewer/PaletteWidget.h"
namespace {
using namespace std;
using namespace Hurricane;
class GridBuffer {
public:
GridBuffer ( QGridLayout*, size_t rowMax, size_t startRow=0, size_t startColumn=0 );
inline int getRow () const;
inline int getColumn () const;
inline int getCurrentRow () const;
void addSection ( QWidget*, Qt::Alignment align=0 );
void addWidget ( QWidget*, Qt::Alignment align=0 );
void newColumn ();
void flushWidgets ();
inline bool columnOverload () const;
protected:
QGridLayout* _grid;
size_t _rowMax;
size_t _row;
size_t _column;
vector<QWidget*> _widgets;
vector<Qt::Alignment> _aligns;
};
GridBuffer::GridBuffer ( QGridLayout* grid, size_t maxRow, size_t startRow, size_t startColumn )
: _grid (grid)
, _rowMax (maxRow)
, _row (startRow)
, _column (startColumn)
, _widgets()
, _aligns ()
{ }
inline int GridBuffer::getRow () const { return _row; }
inline int GridBuffer::getColumn () const { return _column; }
inline int GridBuffer::getCurrentRow () const { return _widgets.size() + _row; }
inline bool GridBuffer::columnOverload () const { return getCurrentRow() > (int)_rowMax; }
void GridBuffer::flushWidgets ()
{
if ( columnOverload() ) {
_column++;
_row = 0;
}
for ( size_t i=0 ; i < _widgets.size() ; ++i )
_grid->addWidget ( _widgets[i], _row++, _column, _aligns[i] );
_widgets.clear ();
_aligns.clear ();
}
void GridBuffer::newColumn ()
{
if ( columnOverload() ) return;
flushWidgets ();
_column++;
_row = 0;
}
void GridBuffer::addWidget ( QWidget* widget, Qt::Alignment align )
{
_widgets.push_back ( widget );
_aligns .push_back ( align );
}
void GridBuffer::addSection ( QWidget* widget, Qt::Alignment align )
{
flushWidgets ();
_widgets.push_back ( widget );
_aligns .push_back ( align );
}
} // End of anonymous namespace.
namespace Hurricane {
QWidget* PaletteWidget::_createGroupItem ( const Name& name )
{
QLabel* groupLabel = new QLabel ();
groupLabel->setText ( getString(name).c_str() );
groupLabel->setFont ( Graphics::getFixedFont(QFont::Bold,false,false) );
return groupLabel;
}
PaletteNamedItem* PaletteWidget::_createNamedItem ( const Name& name, bool checked )
{
PaletteNamedItem* item = PaletteNamedItem::create ( name, checked );
connect ( item, SIGNAL(visibleToggled()), this, SIGNAL(paletteChanged()) );
return item;
}
PaletteLayerItem* PaletteWidget::_createLayerItem ( BasicLayer* layer, bool checked )
{
PaletteLayerItem* item = PaletteLayerItem::create ( layer, checked );
connect ( item, SIGNAL(visibleToggled()), this, SIGNAL(paletteChanged()) );
return item;
}
PaletteExtensionGoItem* PaletteWidget::_createExtensionGoItem ( const Name& name, bool checked )
{
PaletteExtensionGoItem* item = PaletteExtensionGoItem::create ( name );
connect ( item, SIGNAL(visibleToggled()), this, SIGNAL(paletteChanged()) );
return item;
}
PaletteWidget::PaletteWidget ( QWidget* parent )
: QWidget (parent)
, _scrollArea (new QScrollArea(this))
, _layerItems ()
, _extensionGoItems()
, _showAll (new QPushButton(_scrollArea))
, _hideAll (new QPushButton(_scrollArea))
, _grid (new QGridLayout())
, _columnHeight (22)
, _extensionRow (0)
, _extensionColumn (0)
, _extensionGroup (NULL)
{
setContentsMargins ( 0, 0, 0, 0 );
_scrollArea->setWidgetResizable ( true );
QVBoxLayout* vLayout = new QVBoxLayout ();
QHBoxLayout* hLayout = new QHBoxLayout ();
_showAll->setIcon ( QIcon(":/images/palette_show_all.png") );
_showAll->setFlat ( true );
_hideAll->setIcon ( QIcon(":/images/palette_hide_all.png") );
_hideAll->setFlat ( true );
connect ( _showAll, SIGNAL(clicked()), this, SLOT(showAll()) );
connect ( _hideAll, SIGNAL(clicked()), this, SLOT(hideAll()) );
hLayout->addStretch ();
hLayout->addWidget ( _showAll );
hLayout->addStretch ();
hLayout->addWidget ( _hideAll );
hLayout->addStretch ();
QFrame* separator = new QFrame ();
separator->setFrameShape ( QFrame::HLine );
separator->setFrameShadow ( QFrame::Sunken );
vLayout->setSpacing ( 0 );
vLayout->addLayout ( hLayout );
vLayout->addWidget ( separator );
vLayout->addSpacing ( 5 );
vLayout->addLayout ( _grid );
_grid->setHorizontalSpacing ( 10 );
_grid->setVerticalSpacing ( 0 );
//_grid->setSizeConstraint ( QLayout::SetFixedSize );
vLayout->addStretch ();
QWidget* scrollAdaptator = new QWidget ();
scrollAdaptator->setLayout ( vLayout );
_scrollArea->setContentsMargins ( 0, 0, 0, 0 );
_scrollArea->setWidget ( scrollAdaptator );
_scrollArea->setHorizontalScrollBarPolicy ( Qt::ScrollBarAsNeeded );
_scrollArea->setVerticalScrollBarPolicy ( Qt::ScrollBarAsNeeded );
_scrollArea->setFrameStyle ( QFrame::Plain );
vLayout = new QVBoxLayout ();
vLayout->setSpacing ( 0 );
vLayout->addWidget ( _scrollArea );
setLayout ( vLayout );
}
void PaletteWidget::build ()
{
GridBuffer gridBuffer ( _grid, _columnHeight );
size_t gi = 0;
const vector<DrawingGroup*>& groups = Graphics::getStyle()->getDrawingGroups();
const vector<DrawingStyle*>& styles = groups[gi]->getDrawingStyles();
gridBuffer.addSection ( _createGroupItem(groups[gi]->getName()), Qt::AlignHCenter );
for ( size_t si=0 ; si<styles.size() ; si++ ) {
if ( not styles[si]->isGoMatched() ) continue;
if ( styles[si]->getName() == DisplayStyle::Foreground ) continue;
if ( styles[si]->getName() == DisplayStyle::Background ) continue;
if ( styles[si]->getName() == DisplayStyle::SelectionDraw ) continue;
if ( styles[si]->getName() == DisplayStyle::SelectionFill ) continue;
PaletteNamedItem* item = _createNamedItem ( styles[si]->getName() );
gridBuffer.addWidget ( item );
_layerItems [ item->getName() ] = item;
}
if ( _columnHeight < numeric_limits<size_t>::max() )
gridBuffer.newColumn ();
else
gridBuffer.flushWidgets ();
DataBase* database = DataBase::getDB();
if ( database ) {
Technology* technology = database->getTechnology();
if ( technology ) {
for ( gi=1 ; gi<groups.size() ; gi++ ) {
gridBuffer.addSection ( _createGroupItem(groups[gi]->getName()), Qt::AlignHCenter );
const vector<DrawingStyle*>& styles = groups[gi]->getDrawingStyles();
for ( size_t si=0 ; si<styles.size() ; si++ ) {
BasicLayer* basicLayer = technology->getBasicLayer ( styles[si]->getName() );
if ( basicLayer ) {
PaletteLayerItem* item = _createLayerItem ( basicLayer );
gridBuffer.addWidget ( item );
_layerItems [ item->getName() ] = item;
}
}
}
size_t si = 0;
forEach ( BasicLayer*, basicLayer, technology->getBasicLayers() ) {
if ( !find((*basicLayer)->getName()) ) {
if ( !si )
gridBuffer.addSection ( _createGroupItem("Unmatcheds"), Qt::AlignHCenter );
PaletteLayerItem* item = _createLayerItem ( *basicLayer );
gridBuffer.addWidget ( item );
_layerItems [ item->getName() ] = item;
cerr << "[WARNING] BasicLayer \"" << (*basicLayer)->getName()
<< "\" has no associated DisplayStyle." << endl;
si++;
}
}
if ( si ) gi++;
}
}
if ( _columnHeight < numeric_limits<size_t>::max() )
gridBuffer.newColumn ();
else
gridBuffer.flushWidgets ();
_extensionRow = gridBuffer.getRow();
_extensionColumn = gridBuffer.getColumn();
_extensionGroup = _createGroupItem ( "Extensions" );
gridBuffer.addSection ( _extensionGroup, Qt::AlignHCenter );
gridBuffer.flushWidgets ();
}
void PaletteWidget::updateExtensions ( Cell* cell )
{
_grid->removeWidget ( _extensionGroup );
_extensionGroup->deleteLater ();
_extensionGroup = NULL;
PaletteItems::iterator iextension = _extensionGoItems.begin();
for ( ; iextension != _extensionGoItems.end() ; ++iextension ) {
_grid->removeWidget ( iextension->second );
iextension->second->deleteLater ();
}
_extensionGoItems.clear ();
GridBuffer gridBuffer ( _grid, _columnHeight, _extensionRow, _extensionColumn );
_extensionGroup = _createGroupItem ( "Extensions" );
gridBuffer.addSection ( _extensionGroup, Qt::AlignHCenter );
if ( cell ) {
forEach ( ExtensionSlice*, extension, cell->getExtensionSlices() ) {
PaletteExtensionGoItem* item = _createExtensionGoItem ( (*extension)->getName(), false );
gridBuffer.addWidget ( item );
_extensionGoItems [ item->getName() ] = item;
}
}
gridBuffer.flushWidgets ();
}
void PaletteWidget::_getSection ( const QString section, QLabel*& label, vector<PaletteItem*>& items ) const
{
label = NULL;
items.clear ();
bool found = false;
for ( int index=0 ; index < _grid->count() ; index++ ) {
QLayoutItem* item = _grid->itemAt ( index );
if ( !item ) continue;
QLabel* ilabel = dynamic_cast<QLabel*>(item->widget());
if ( ilabel ) {
if ( found ) break;
if ( ilabel->text() != section ) continue;
found = true;
label = ilabel;
} else if ( found ) {
PaletteItem* paletteItem = dynamic_cast<PaletteItem*>(item->widget());
if ( paletteItem ) items.push_back ( paletteItem );
}
}
}
void PaletteWidget::setSectionVisible ( const QString section, bool visible )
{
QLabel* label;
vector<PaletteItem*> items;
_getSection ( section, label, items );
if ( !label ) return;
if ( visible ) label->show ();
else label->hide ();
for ( size_t i=0 ; i<items.size() ; ++i ) {
if ( visible ) items[i]->show ();
else items[i]->hide ();
}
}
bool PaletteWidget::isDrawable ( const Name& name ) const
{
PaletteItem* item = find ( name );
if ( item )
return item->isItemVisible ();
return false;
}
bool PaletteWidget::isSelectable ( const Name& name ) const
{
PaletteItem* item = find ( name );
if ( item )
return item->isItemSelectable ();
return false;
}
void PaletteWidget::showAll ()
{
PaletteItems::iterator iitem = _layerItems.begin();
for ( ; iitem != _layerItems.end() ; iitem++ )
iitem->second->setItemVisible ( true );
iitem = _extensionGoItems.begin();
for ( ; iitem != _extensionGoItems.end() ; iitem++ )
iitem->second->setItemVisible ( true );
emit paletteChanged();
}
void PaletteWidget::hideAll ()
{
PaletteItems::iterator iitem = _layerItems.begin();
for ( ; iitem != _layerItems.end() ; iitem++ )
iitem->second->setItemVisible ( false );
iitem = _extensionGoItems.begin();
for ( ; iitem != _extensionGoItems.end() ; iitem++ )
iitem->second->setItemVisible ( false );
emit paletteChanged();
}
void PaletteWidget::showSection ( const QString section )
{
QLabel* label;
vector<PaletteItem*> items;
_getSection ( section, label, items );
if ( !label ) return;
for ( size_t i=0 ; i<items.size() ; ++i )
items[i]->setItemVisible ( true );
}
void PaletteWidget::hideSection ( const QString section )
{
QLabel* label;
vector<PaletteItem*> items;
_getSection ( section, label, items );
if ( !label ) return;
for ( size_t i=0 ; i<items.size() ; ++i )
items[i]->setItemVisible ( false );
}
PaletteItem* PaletteWidget::find ( const Name& name ) const
{
PaletteItems::const_iterator iitem = _layerItems.find(name);
if ( iitem != _layerItems.end() )
return iitem->second;
iitem = _extensionGoItems.find(name);
if ( iitem != _extensionGoItems.end() )
return iitem->second;
return NULL;
}
void PaletteWidget::setItemVisible ( const Name& name, bool visible )
{
PaletteItem* item = find ( name );
if ( item ) {
item->setItemVisible ( visible );
emit paletteChanged();
}
}
void PaletteWidget::changeStyle ()
{
PaletteItems::iterator iitem = _layerItems.begin();
for ( ; iitem != _layerItems.end() ; iitem++ )
iitem->second->changeStyle ();
iitem = _extensionGoItems.begin();
for ( ; iitem != _extensionGoItems.end() ; iitem++ )
iitem->second->changeStyle ();
}
} // End of Hurricane namespace.