/*************************************************************************** * 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 "cnitem.h" #include "icndocument.h" #include "connector.h" #include "itemdocumentdata.h" #include "node.h" #include #include Node::Node( ICNDocument *icnDocument, Node::node_type type, node_dir dir, const TQPoint &pos, TQString *id ) : TQObject(), TQCanvasPolygon( icnDocument->canvas() ) { p_nodeGroup = 0l; p_parentItem = 0L; b_deleted = false; m_dir = dir; m_type = type; p_icnDocument = icnDocument; m_level = 0; m_selectedColor = TQColor( 101, 134, 192 ); if (id) { m_id = *id; if ( !p_icnDocument->registerUID(*id) ) kdError() << k_funcinfo << "Could not register id " << *id << endl; } else m_id = p_icnDocument->generateUID("node"+TQString::number(type)); initPoints(); move( pos.x(), pos.y() ); setBrush( TQt::black ); setPen( TQt::black ); show(); emit (moved(this)); } Node::~Node() { p_icnDocument->unregisterUID( id() ); } int Node::rtti() const { return ICNDocument::RTTI::Node; } void Node::setLevel( const int level ) { m_level = level; } bool Node::acceptInput() const { return type() != fp_out; } bool Node::acceptOutput() const { return type() != fp_in; } void Node::setVisible( bool yes ) { if ( isVisible() == yes ) return; TQCanvasPolygon::setVisible(yes); const ConnectorList::iterator inputEnd = m_inputConnectorList.end(); for ( ConnectorList::iterator it = m_inputConnectorList.begin(); it != inputEnd; ++it ) { Connector *connector = *it; if (connector) { if ( isVisible() ) connector->setVisible(true); else { Node *node = connector->startNode(); connector->setVisible( node && node->isVisible() ); } } } const ConnectorList::iterator outputEnd = m_outputConnectorList.end(); for ( ConnectorList::iterator it = m_outputConnectorList.begin(); it != outputEnd; ++it ) { Connector *connector = *it; if (connector) { if ( isVisible() ) connector->setVisible(true); else { Node *node = connector->endNode(); connector->setVisible( node && node->isVisible() ); } } } } bool Node::isConnected( Node *node, NodeList *checkedNodes ) { if ( this == node ) return true; bool firstNode = !checkedNodes; if (firstNode) checkedNodes = new NodeList(); else if ( checkedNodes->contains(this) ) return false; checkedNodes->append(this); const ConnectorList::const_iterator inputEnd = m_inputConnectorList.end(); for ( ConnectorList::const_iterator it = m_inputConnectorList.begin(); it != inputEnd; ++it ) { Connector *connector = *it; if (connector) { Node *startNode = connector->startNode(); if ( startNode && startNode->isConnected( node, checkedNodes ) ) { if (firstNode) { delete checkedNodes; } return true; } } } const ConnectorList::const_iterator outputEnd = m_outputConnectorList.end(); for ( ConnectorList::const_iterator it = m_outputConnectorList.begin(); it != outputEnd; ++it ) { Connector *connector = *it; if (connector) { Node *endNode = connector->endNode(); if ( endNode && endNode->isConnected( node, checkedNodes ) ) { if (firstNode) { delete checkedNodes; } return true; } } } if (firstNode) { delete checkedNodes; } return false; } void Node::setOrientation( node_dir dir ) { if ( m_dir == dir ) return; if ( dir != Node::dir_up && dir != Node::dir_right && dir != Node::dir_down && dir != Node::dir_left ) { kdDebug() << "Node::setOrientation: Unknown node direction "<level()); connect( p_parentItem, TQT_SIGNAL(movedBy(double, double )), this, TQT_SLOT(moveBy(double, double)) ); connect( p_parentItem, TQT_SIGNAL(removed(Item*)), this, TQT_SLOT(removeNode(Item*)) ); } void Node::removeNode() { if (b_deleted) return; b_deleted = true; emit removed(this); p_icnDocument->appendDeleteList(this); } void Node::moveBy( double dx, double dy ) { if ( dx == 0 && dy == 0 ) return; TQCanvasPolygon::moveBy( dx, dy ); emit moved(this); } int Node::numCon( bool includeParentItem, bool includeHiddenConnectors ) const { unsigned count = 0; const ConnectorList connectors[2] = { m_inputConnectorList, m_outputConnectorList }; for ( unsigned i = 0; i < 2; i++ ) { ConnectorList::const_iterator end = connectors[i].end(); for ( ConnectorList::const_iterator it = connectors[i].begin(); it != end; ++it ) { if ( *it && (includeHiddenConnectors || (*it)->canvas()) ) count++; } } if ( isChildNode() && includeParentItem ) count++; return count; } void Node::addOutputConnector( Connector * const connector ) { if ( type() == fp_in || !handleNewConnector(connector) ) return; m_outputConnectorList.append(connector); if ( type() == fp_out || type() == fp_junction ) { // We can only have one output connector, so remove the others. Note // that this code has to come *after* adding the new output connector, // as this node will delete itself if it's an fp_junction and there are // no output connectors. const ConnectorList connectors = m_outputConnectorList; const ConnectorList::const_iterator end = connectors.end(); for ( ConnectorList::const_iterator it = connectors.begin(); it != end; ++it ) { Connector * con = *it; if ( con && con != connector ) con->removeConnector(); } } m_outputConnectorList.remove((Connector*)0l); } void Node::addInputConnector( Connector * const connector ) { if ( type() == fp_out || !handleNewConnector(connector) ) return; m_inputConnectorList.append(connector); } bool Node::handleNewConnector( Connector * connector ) { if (!connector) return false; if ( m_inputConnectorList.contains(connector) || m_outputConnectorList.contains(connector) ) { kdWarning() << k_funcinfo << " Already have connector = " << connector << endl; return false; } connect( this, TQT_SIGNAL(removed(Node*)), connector, TQT_SLOT(removeConnector(Node*)) ); connect( connector, TQT_SIGNAL(removed(Connector*)), this, TQT_SLOT(checkForRemoval(Connector*)) ); connect( connector, TQT_SIGNAL(selected(bool)), this, TQT_SLOT(setNodeSelected(bool)) ); if ( !isChildNode() ) p_icnDocument->slotRequestAssignNG(); return true; } Connector* Node::createInputConnector( Node * startNode ) { if ( type() == fp_out || !startNode ) return 0l; Connector *connector = new Connector( startNode, this, p_icnDocument ); addInputConnector(connector); return connector; } void Node::removeConnector( Connector *connector ) { if (!connector) return; ConnectorList::iterator it; it = m_inputConnectorList.find(connector); if ( it != m_inputConnectorList.end() ) { (*it)->removeConnector(); (*it) = 0L; } it = m_outputConnectorList.find(connector); if ( it != m_outputConnectorList.end() ) { (*it)->removeConnector(); (*it) = 0L; } } void Node::checkForRemoval( Connector *connector ) { removeConnector(connector); setNodeSelected(false); removeNullConnectors(); if (!p_parentItem) { int conCount = m_inputConnectorList.count() + m_outputConnectorList.count(); if ( conCount < 2 ) removeNode(); } if ( type() == Node::fp_junction && m_outputConnectorList.isEmpty() ) removeNode(); } void Node::removeNullConnectors() { m_inputConnectorList.remove((Connector*)0L); m_outputConnectorList.remove((Connector*)0L); } NodeData Node::nodeData() const { NodeData data; data.x = x(); data.y = y(); return data; } void Node::setNodeSelected( bool yes ) { if ( isSelected() == yes ) return; TQCanvasItem::setSelected(yes); setPen( yes ? m_selectedColor : TQt::black ); setBrush( yes ? m_selectedColor : TQt::black ); } #include "node.moc"