|
|
|
/***************************************************************************
|
|
|
|
* Copyright (C) 2003-2005 by David Saxton *
|
|
|
|
* david@bluehaze.org *
|
|
|
|
* *
|
|
|
|
* 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 <tqpainter.h>
|
|
|
|
|
|
|
|
#include <cmath>
|
|
|
|
|
|
|
|
const int topStrip = 24;
|
|
|
|
const int botStrip = 16;
|
|
|
|
|
|
|
|
FlowContainer::FlowContainer( ICNDocument *_icnDocument, bool newItem, const TQString &id )
|
|
|
|
: FlowPart( _icnDocument, newItem, id )
|
|
|
|
{
|
|
|
|
m_ext_in = m_int_in = m_int_out = m_ext_out = 0l;
|
|
|
|
b_expanded = true;
|
|
|
|
|
|
|
|
addButton( "expandBtn", TQRect( 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( TQStringList *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();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQSize FlowContainer::minimumSize() const
|
|
|
|
{
|
|
|
|
return TQSize( 160, 64 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void FlowContainer::drawShape( TQPainter &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( TQColor( col, 0xff, col ) );
|
|
|
|
if( b_expanded )
|
|
|
|
{
|
|
|
|
p.setPen(TQt::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(TQPen((isSelected()?m_selectedCol:TQt::black),1,TQt::SolidLine));
|
|
|
|
p.drawRoundRect( _x, _y, width(), topStrip, 1500/width(), 1500/topStrip );
|
|
|
|
}
|
|
|
|
|
|
|
|
p.setPen( TQt::black );
|
|
|
|
p.setFont( font() );
|
|
|
|
p.drawText( TQRect( 22 + _x+8, _y, width()-8, topStrip ), TQt::AlignLeft | TQt::AlignVCenter, m_caption );
|
|
|
|
|
|
|
|
if( b_expanded )
|
|
|
|
{
|
|
|
|
p.setPen(TQt::SolidLine);
|
|
|
|
p.setBrush( TQt::NoBrush );
|
|
|
|
p.drawRoundRect( _x, _y, width(), height(), 1500/width(), 1500/height() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void FlowContainer::childAdded( Item *child )
|
|
|
|
{
|
|
|
|
if (!child)
|
|
|
|
return;
|
|
|
|
|
|
|
|
FlowPart::childAdded(child);
|
|
|
|
|
|
|
|
connect( this, TQT_SIGNAL(movedBy(double, double )), child, TQT_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, TQT_SIGNAL(movedBy(double, double )), child, TQT_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 )
|
|
|
|
{
|
|
|
|
TQRect bounds = b_expanded ? m_sizeRect : TQRect( m_sizeRect.x(), m_sizeRect.y(), m_sizeRect.width(), topStrip );
|
|
|
|
setPoints( TQPointArray(bounds) );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// kdDebug() << k_funcinfo << "width="<<width()<<" height="<<height()<<endl;
|
|
|
|
|
|
|
|
TQPointArray pa(10);
|
|
|
|
pa[0] = TQPoint( 0, 0 );
|
|
|
|
pa[1] = TQPoint( width(), 0 );
|
|
|
|
pa[2] = TQPoint( width(), height() );
|
|
|
|
pa[3] = TQPoint( 0, height() );
|
|
|
|
pa[4] = TQPoint( 0, 0 );
|
|
|
|
pa[5] = TQPoint( 8, topStrip );
|
|
|
|
pa[6] = TQPoint( 8, height()-botStrip );
|
|
|
|
pa[7] = TQPoint( width()-8, height()-botStrip );
|
|
|
|
pa[8] = TQPoint( width()-8, topStrip );
|
|
|
|
pa[9] = TQPoint( 8, topStrip );
|
|
|
|
pa.translate( offsetX(), offsetY() );
|
|
|
|
setPoints(pa);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void FlowContainer::buttonStateChanged(const TQString &/*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"
|