summaryrefslogtreecommitdiffstats
path: root/src/flowcontainer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/flowcontainer.cpp')
-rw-r--r--src/flowcontainer.cpp407
1 files changed, 407 insertions, 0 deletions
diff --git a/src/flowcontainer.cpp b/src/flowcontainer.cpp
new file mode 100644
index 0000000..32eb20e
--- /dev/null
+++ b/src/flowcontainer.cpp
@@ -0,0 +1,407 @@
+/***************************************************************************
+ * Copyright (C) 2003-2005 by David Saxton *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#include "canvasitemparts.h"
+#include "cells.h"
+#include "icndocument.h"
+#include "flowcontainer.h"
+#include "fpnode.h"
+#include "nodegroup.h"
+#include "resizeoverlay.h"
+
+#include <kiconloader.h>
+#include <qpainter.h>
+
+#include <cmath>
+
+const int topStrip = 24;
+const int botStrip = 16;
+
+FlowContainer::FlowContainer( ICNDocument *_icnDocument, bool newItem, const QString &id )
+ : FlowPart( _icnDocument, newItem, id )
+{
+ m_ext_in = m_int_in = m_int_out = m_ext_out = 0l;
+ b_expanded = true;
+
+ addButton( "expandBtn", QRect( offsetX(), offsetY()+24 - 11, 22, 22 ), KGlobal::iconLoader()->loadIcon( "down", KIcon::Small ), true );
+ m_rectangularOverlay = new RectangularOverlay( this, 8, 8 );
+ setSize( -160, -120, 320, 240 );
+
+
+ m_int_in = (FPNode*)createNode( width()/2, 8+topStrip, Node::dir_down, "int_in", Node::fp_out );
+ m_int_out = (FPNode*)createNode( width()/2, height()-8-botStrip, Node::dir_up, "int_out", Node::fp_in );
+
+ button("expandBtn")->setState(true);
+
+ updateAttachedPositioning();
+ updateNodeLevels();
+}
+
+
+FlowContainer::~FlowContainer()
+{
+}
+
+
+void FlowContainer::updateNodeLevels()
+{
+ FlowPart::updateNodeLevels();
+
+ int l = level();
+
+ if (m_ext_in)
+ m_ext_in->setLevel(l);
+ if (m_ext_out)
+ m_ext_out->setLevel(l);
+
+ if (m_int_in)
+ m_int_in->setLevel(l+1);
+ if (m_int_out)
+ m_int_out->setLevel(l+1);
+}
+
+
+void FlowContainer::filterEndPartIDs( QStringList *ids )
+{
+ // Remove *all* nodes except for very bottom one
+ if (m_int_out) {
+ ids->remove(m_int_out->childId());
+ }
+ if (m_ext_in) {
+ ids->remove(m_ext_in->childId());
+ }
+ if (m_int_in) {
+ ids->remove(m_int_in->childId());
+ }
+}
+
+
+void FlowContainer::createTopContainerNode()
+{
+ m_ext_in = (FPNode*)createNode( width()/2, -8, Node::dir_up, "ext_in", Node::fp_in );
+ m_ext_in->setLevel( level() );
+ m_rectangularOverlay->removeTopMiddle();
+ updateAttachedPositioning();
+}
+
+
+void FlowContainer::createBotContainerNode()
+{
+ m_ext_out = (FPNode*)createNode( width()/2, height()+8, Node::dir_down, "ext_out", Node::fp_out );
+ m_ext_out->setLevel( level() );
+ m_rectangularOverlay->removeBotMiddle();
+ updateAttachedPositioning();
+}
+
+
+QSize FlowContainer::minimumSize() const
+{
+ return QSize( 160, 64 );
+}
+
+
+void FlowContainer::drawShape( QPainter &p )
+{
+ if (b_deleted)
+ return;
+
+ if ( !m_sizeRect.isValid() )
+ return;
+
+ const int _x = (int)x()+offsetX();
+ const int _y = (int)y()+offsetY();
+
+ int col = 0xef + level()*0x6;
+ if ( col > 0xff ) col = 0xff;
+ p.setBrush( QColor( col, 0xff, col ) );
+ if( b_expanded )
+ {
+ p.setPen(Qt::DotLine);
+ p.drawRoundRect( _x, _y, width(), topStrip, 1500/width(), 1500/topStrip );
+ p.drawRoundRect( _x, _y+height()-botStrip, width(), botStrip, 1500/width(), 1500/botStrip );
+ }
+ else
+ {
+ p.setPen(QPen((isSelected()?m_selectedCol:Qt::black),1,Qt::SolidLine));
+ p.drawRoundRect( _x, _y, width(), topStrip, 1500/width(), 1500/topStrip );
+ }
+
+ p.setPen( Qt::black );
+ p.setFont( font() );
+ p.drawText( QRect( 22 + _x+8, _y, width()-8, topStrip ), Qt::AlignLeft | Qt::AlignVCenter, m_caption );
+
+ if( b_expanded )
+ {
+ p.setPen(Qt::SolidLine);
+ p.setBrush( Qt::NoBrush );
+ p.drawRoundRect( _x, _y, width(), height(), 1500/width(), 1500/height() );
+ }
+}
+
+
+void FlowContainer::childAdded( Item *child )
+{
+ if (!child)
+ return;
+
+ FlowPart::childAdded(child);
+
+ connect( this, SIGNAL(movedBy(double, double )), child, SLOT(moveBy(double, double )) );
+ child->setZ( ICNDocument::Z::Item + child->level() );
+
+ updateContainedVisibility();
+}
+
+
+void FlowContainer::childRemoved( Item *child )
+{
+ FlowPart::childRemoved(child);
+
+ if (!b_expanded)
+ child->setVisible(true);
+
+ disconnect( this, SIGNAL(movedBy(double, double )), child, SLOT(moveBy(double, double )) );
+}
+
+
+void FlowContainer::updateConnectorPoints( bool add )
+{
+ if ( b_deleted || !isVisible() )
+ add = false;
+
+ if ( b_pointsAdded == add )
+ return;
+
+ b_pointsAdded = add;
+
+ Cells *cells = p_icnDocument->cells();
+ if (!cells) return;
+
+ int _x = (int)x()+offsetX();
+ int _y = (int)y()+offsetY();
+ int w = width();
+ int h = b_expanded ? height() : topStrip;
+
+ const int mult = add ? 1 : -1;
+
+ // Top strip
+ for ( int y=_y; y <_y+24; ++y )
+ {
+ for ( int x = _x; x<=_x+w; x += 8 )
+ {
+ if ( p_icnDocument->isValidCellReference( x/8, y/8 ) )
+ {
+ (*cells)[x/8][y/8].CIpenalty += mult*ICNDocument::hs_item;
+ }
+ }
+ }
+
+ // Bottom strip
+ for ( int y = _y+h-16; y <= _y+h; ++y )
+ {
+ for ( int x = _x; x<=_x+width(); x += 8 )
+ {
+ if ( p_icnDocument->isValidCellReference( x/8, y/8 ) )
+ {
+ (*cells)[x/8][y/8].CIpenalty += mult*ICNDocument::hs_item;
+ }
+ }
+ }
+
+ // Left strip
+ int x = _x;
+ for ( int y = _y+24; y<_y+h-16; y += 8 )
+ {
+ if ( p_icnDocument->isValidCellReference( x/8, y/8 ) )
+ {
+ (*cells)[x/8][y/8].CIpenalty += mult*ICNDocument::hs_item;
+ }
+ }
+
+ // Right strip
+ x = _x+width();
+ for ( int y = _y+24; y<_y+h-16; y += 8 )
+ {
+ if ( p_icnDocument->isValidCellReference( x/8, y/8 ) )
+ {
+ (*cells)[x/8][y/8].CIpenalty += mult*ICNDocument::hs_item;
+ }
+ }
+}
+
+
+void FlowContainer::setFullBounds( bool full )
+{
+ if ( full || !b_expanded )
+ {
+ QRect bounds = b_expanded ? m_sizeRect : QRect( m_sizeRect.x(), m_sizeRect.y(), m_sizeRect.width(), topStrip );
+ setPoints( QPointArray(bounds) );
+ return;
+ }
+
+// kdDebug() << k_funcinfo << "width="<<width()<<" height="<<height()<<endl;
+
+ QPointArray pa(10);
+ pa[0] = QPoint( 0, 0 );
+ pa[1] = QPoint( width(), 0 );
+ pa[2] = QPoint( width(), height() );
+ pa[3] = QPoint( 0, height() );
+ pa[4] = QPoint( 0, 0 );
+ pa[5] = QPoint( 8, topStrip );
+ pa[6] = QPoint( 8, height()-botStrip );
+ pa[7] = QPoint( width()-8, height()-botStrip );
+ pa[8] = QPoint( width()-8, topStrip );
+ pa[9] = QPoint( 8, topStrip );
+ pa.translate( offsetX(), offsetY() );
+ setPoints(pa);
+}
+
+
+void FlowContainer::buttonStateChanged(const QString &/*id*/, bool state)
+{
+ setExpanded(state);
+}
+
+
+bool FlowContainer::parentIsCollapsed() const
+{
+ if ( !p_parentItem )
+ return false;
+
+ FlowContainer *fc = dynamic_cast<FlowContainer*>((Item*)(p_parentItem));
+ return !fc->isExpanded() || fc->parentIsCollapsed();
+}
+
+
+void FlowContainer::setSelected( bool yes )
+{
+ if ( yes == isSelected() )
+ return;
+
+ FlowPart::setSelected(yes);
+ m_rectangularOverlay->showResizeHandles( yes && isVisible() );
+}
+
+
+void FlowContainer::setExpanded( bool expanded )
+{
+ if ( b_expanded == expanded )
+ return;
+
+ updateConnectorPoints(false);
+
+ // Set this now, so that child items that we call know whether or not we actually are expanded
+ b_expanded = expanded;
+
+ updateContainedVisibility();
+ updateAttachedPositioning();
+
+ p_itemDocument->setModified(true);
+ m_rectangularOverlay->setVisible(expanded);
+ setFullBounds(false);
+
+ bool nodesMoved = (m_ext_out != 0l);
+ if (nodesMoved)
+ p_icnDocument->requestRerouteInvalidatedConnectors();
+
+ p_icnDocument->requestStateSave();
+}
+
+
+void FlowContainer::postResize()
+{
+// kdDebug() << k_funcinfo << "width="<<width()<<endl;
+ setFullBounds(false);
+ FlowPart::postResize();
+}
+
+
+void FlowContainer::updateAttachedPositioning()
+{
+ if (b_deleted)
+ return;
+
+ int _x = int(x())+offsetX();
+ int _y = int(y())+offsetY();
+ int w = int((std::floor(float((width()+8)/16)))*16);
+ int h = height();
+
+ if (m_ext_in)
+ m_ext_in->move( _x+w/2, _y-8 );
+
+ if (m_int_in)
+ m_int_in->move( _x+w/2, _y+8+topStrip );
+
+ if (b_expanded)
+ {
+ if (m_int_out)
+ m_int_out->move( _x+w/2, _y+h-8-botStrip );
+
+ if (m_ext_out)
+ m_ext_out->move( _x+w/2, _y+h-8+botStrip );
+ }
+ else
+ {
+ // (Note: dont really care where internal nodes are if not expanded)
+
+ if (m_ext_out)
+ m_ext_out->move( _x+w/2, _y+8+topStrip );
+ }
+
+ button("expandBtn")->setGuiPartSize( 22, 22 );
+ button("expandBtn")->move( int(x())+offsetX()+7, int(y())+offsetY()+1 );
+}
+
+
+void FlowContainer::updateContainedVisibility()
+{
+ if (b_deleted)
+ return;
+
+ if (m_ext_in)
+ m_ext_in->setVisible( isVisible() );
+ if (m_int_in)
+ m_int_in->setVisible( isVisible() && b_expanded );
+ if (m_int_out)
+ m_int_out->setVisible( isVisible() && b_expanded );
+ if (m_ext_out)
+ m_ext_out->setVisible( isVisible() );
+
+ const ItemList::iterator cEnd = m_children.end();
+ for ( ItemList::iterator it = m_children.begin(); it != cEnd; ++it )
+ {
+ if (*it)
+ (*it)->setVisible( isVisible() && b_expanded );
+ }
+
+ m_rectangularOverlay->setVisible( isVisible() && b_expanded );
+
+ NodeGroupList hidableNodeGroups;
+ p_icnDocument->getTranslatable( children(true) += GuardedItem(this), 0, 0, &hidableNodeGroups );
+
+ NodeGroupList::iterator hngEnd = hidableNodeGroups.end();
+ for ( NodeGroupList::iterator it = hidableNodeGroups.begin(); it != hngEnd; ++it )
+ (*it)->setVisible(b_expanded);
+}
+
+
+void FlowContainer::setVisible( bool yes )
+{
+ if (b_deleted)
+ {
+ FlowPart::setVisible(false);
+ return;
+ }
+
+ FlowPart::setVisible(yes);
+ updateContainedVisibility();
+}
+
+#include "flowcontainer.moc"