You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/kivio/kiviopart/kiviosdk/kivio_layer.cpp

592 lines
14 KiB

/*
* Kivio - Visual Modelling and Flowcharting
* Copyright (C) 2000-2001 theKompany.com & Dave Marotti
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "kivio_common.h"
#include "kivio_connector_point.h"
#include "kivio_connector_target.h"
#include "kivio_group_stencil.h"
#include "kivio_intra_stencil_data.h"
#include "kivio_layer.h"
#include "kivio_painter.h"
#include "kivio_stencil.h"
#include "kivio_stencil_spawner.h"
#include "kivio_stencil_spawner_info.h"
#include "kivio_stencil_spawner_set.h"
#include "KIvioLayerIface.h"
#include "kivio_doc.h"
#include "kivio_page.h"
#include <tqdom.h>
#include <klocale.h>
#include <kdebug.h>
#include <KoZoomHandler.h>
#include <KoPoint.h>
#include <KoStore.h>
#include <KoXmlWriter.h>
KivioLayer::KivioLayer( KivioPage *pPage )
:m_pStencilList(NULL)
{
m_pPage = pPage;
m_name = i18n("Untitled Layer");
m_pStencilList = new TQPtrList<KivioStencil>;
m_pStencilList->setAutoDelete(true);
m_pDeletedStencilList = new TQPtrList<KivioStencil>;
m_pDeletedStencilList->setAutoDelete(true);
m_flags = 0;
m_dcop = 0;
setVisible(true);
setConnectable(false);
setEditable(true);
setPrintable(true);
}
DCOPObject* KivioLayer::dcopObject()
{
if ( !m_dcop )
m_dcop = new KIvioLayerIface( this );
return m_dcop;
}
KivioLayer::~KivioLayer()
{
kdDebug(43000)<<"KivioLayer::~KivioLayer()***************:"<<this<<endl;
if( m_pStencilList )
{
delete m_pStencilList;
m_pStencilList = NULL;
}
delete m_pDeletedStencilList;
delete m_dcop;
}
bool KivioLayer::addStencil( KivioStencil *pStencil )
{
int pos = m_pDeletedStencilList->findRef(pStencil);
if ( pos != -1 )
m_pDeletedStencilList->take( pos);
m_pStencilList->append( pStencil );
return true;
}
void KivioLayer::takeStencilFromList( KivioStencil *pStencil )
{
int pos=m_pStencilList->findRef(pStencil);
m_pStencilList->take( pos );
m_pDeletedStencilList->append( pStencil );
}
void KivioLayer::insertStencil( KivioStencil *pStencil )
{
int pos=m_pDeletedStencilList->findRef(pStencil);
if ( pos != -1 )
m_pDeletedStencilList->take( pos);
m_pStencilList->append( pStencil );
}
bool KivioLayer::removeStencil( KivioStencil *pStencil )
{
return m_pStencilList->remove( pStencil );
}
/**
* Returns a new stencil of the type described by stencilE
*
* @param stencilE The XML element to load from
*
* This will search through all KivioStencilSpawnerSets and attempt to
* locate the stencil described by stencilE. If it finds it, it allocates
* a new copy of it, loads the data from stencilE into it, and returns
* it.
*
* @returns A new, loaded stencil.
*/
KivioStencil *KivioLayer::loadSMLStencil( const TQDomElement &stencilE )
{
TQString setId, _id;
kdDebug(43000) << "KivioLayer::loadSMLStencil() " << setId << " " << _id << endl;
setId = XmlReadString( stencilE, "setId", "" );
_id = XmlReadString( stencilE, "id", "" );
if( setId.length() == 0 ||
_id.length() == 0 )
{
return NULL;
}
// Locate the spawner set
KivioStencilSpawner *pSpawner = m_pPage->doc()->findStencilSpawner(setId,_id);
if( pSpawner )
{
KivioStencil *pStencil = pSpawner->newStencil();
pStencil->loadXML( stencilE );
return pStencil;
}
return NULL;
}
/**
* Returns a new stencil of the type described by stencilE
*
* @param stencilE The XML element to load from
*
* This will search through all KivioStencilSpawnerSets and attempt to
* locate the stencil described by stencilE. If it finds it, it allocates
* a new copy of it, loads the data from stencilE into it, and returns
* it.
*
* @returns A new, loaded stencil.
*/
KivioStencil *KivioLayer::loadGroupStencil( const TQDomElement &stencilE )
{
kdDebug(43000) << "KivioLayer::loadGroupStencil()" << endl;
KivioGroupStencil *pStencil = new KivioGroupStencil();
if(pStencil->loadXML( stencilE, this )==false)
{
delete pStencil;
return NULL;
}
return pStencil;
}
KivioStencil *KivioLayer::loadPluginStencil( const TQDomElement &stencilE )
{
TQString setId, _id;
kdDebug(43000) << "KivioLayer::loadPluginStencil() " << setId.ascii() << " / " << _id << endl;
setId = XmlReadString( stencilE, "setId", "" );
_id = XmlReadString( stencilE, "id", "" );
if( setId.length() == 0 ||
_id.length() == 0 )
return NULL;
// Locate the spawner set
KivioStencilSpawner *pSpawner = m_pPage->doc()->findStencilSpawner(setId, _id);
if( pSpawner )
{
KivioStencil *pStencil = pSpawner->newStencil();
pStencil->loadXML( stencilE );
return pStencil;
}
return NULL;
}
bool KivioLayer::loadXML( const TQDomElement &layerE )
{
m_flags = XmlReadInt( layerE, "flags", 1 );
kdDebug(43000) << "Flags: " << m_flags << endl;
m_name = XmlReadString( layerE, "name", "layerX" );
TQDomNode node;
node = layerE.firstChild();
while( !node.isNull() )
{
TQString name = node.nodeName();
if( name == "KivioSMLStencil" || name == "KivioPyStencil" )
{
KivioStencil *pStencil = loadSMLStencil( node.toElement() );
if( pStencil )
{
pStencil->updateGeometry();
m_pStencilList->append( pStencil );
}
else
{
kdWarning(43000) << "KivioLayer::loadXML() - Unknown KivioSMLStencil (id=" <<
XmlReadString( node.toElement(), "id", "" ) << " set=" <<
XmlReadString( node.toElement(), "setId", "" ) << ") found." << endl;
}
}
else if( name == "KivioGroupStencil" )
{
KivioStencil *pStencil = loadGroupStencil( node.toElement() );
if( pStencil )
{
m_pStencilList->append(pStencil);
}
else
{
kdWarning(43000) << "KivioLayer::loadXML() - Unable to load KivioGroupStencil" << endl;
}
}
else if( name == "KivioPluginStencil" )
{
KivioStencil *pStencil = loadPluginStencil( node.toElement() );
if( pStencil )
{
m_pStencilList->append(pStencil);
}
else
{
kdWarning(43000) << "KivioLayer - Unable to load KivioPluginStencil" << endl;
kdWarning(43000) << "KivioLayer::loadXML() - Unable to load KivioPluginStencil (id=" <<
XmlReadString( node.toElement(), "id", "" ) << " set=" <<
XmlReadString( node.toElement(), "setId", "" ) << ") found." << endl;
}
}
node = node.nextSibling();
}
return true;
}
void KivioLayer::loadOasis(const TQDomElement& layer)
{
m_name = layer.attribute("draw:name");
// TODO OASIS Load flags
}
TQDomElement KivioLayer::saveXML( TQDomDocument &doc )
{
TQDomElement e = doc.createElement("KivioLayer");
XmlWriteInt( e, "flags", m_flags );
XmlWriteString( e, "name", m_name );
KivioStencil *pStencil = m_pStencilList->first();
while( pStencil )
{
e.appendChild( pStencil->saveXML( doc ) );
pStencil = m_pStencilList->next();
}
return e;
}
void KivioLayer::saveOasis(KoXmlWriter* layerWriter)
{
layerWriter->startElement("draw:layer");
layerWriter->addAttribute("draw:name", m_name);
// TODO OASIS Save flags
layerWriter->endElement(); // draw:layer
}
void KivioLayer::paintContent( KivioPainter& painter, const TQRect&, bool, TQPoint,
KoZoomHandler* zoom )
{
if(!visible()) {
return;
}
KivioStencil *pStencil = m_pStencilList->first();
KivioIntraStencilData data;
painter.setFGColor( TQColor(0,0,0) );
data.painter = &painter;
data.zoomHandler = zoom;
while( pStencil )
{
if(!pStencil->hidden()) {
pStencil->paint( &data );
}
pStencil = m_pStencilList->next();
}
}
void KivioLayer::printContent( KivioPainter& painter, int xdpi, int ydpi )
{
if(!printable() || !visible())
return;
if(!xdpi) {
xdpi = KoGlobal::dpiX();
}
if(!ydpi) {
ydpi = KoGlobal::dpiY();
}
KivioStencil *pStencil = m_pStencilList->first();
KivioIntraStencilData data;
KoZoomHandler zoomHandler;
zoomHandler.setZoomAndResolution(100, xdpi, ydpi);
painter.setFGColor( TQColor(0,0,0) );
data.painter = &painter;
data.zoomHandler = &zoomHandler;
data.printing = true;
while( pStencil )
{
pStencil->paint( &data );
pStencil = m_pStencilList->next();
}
}
void KivioLayer::printContent(KivioPainter& painter, KoZoomHandler* zoomHandler)
{
if(!printable() || !visible())
return;
KivioStencil *pStencil = m_pStencilList->first();
KivioIntraStencilData data;
painter.setFGColor( TQColor(0,0,0) );
data.painter = &painter;
data.zoomHandler = zoomHandler;
data.printing = true;
while( pStencil )
{
pStencil->paint( &data );
pStencil = m_pStencilList->next();
}
}
void KivioLayer::paintConnectorTargets( KivioPainter& painter, const TQRect&, bool, TQPoint,
KoZoomHandler* zoom )
{
if(!visible()) {
return;
}
KivioIntraStencilData data;
painter.setFGColor( TQColor(0,0,0) );
data.painter = &painter;
data.zoomHandler = zoom;
KivioStencil *pStencil = m_pStencilList->first();
while( pStencil )
{
if(!pStencil->hidden()) {
pStencil->paintConnectorTargets( &data );
}
pStencil = m_pStencilList->next();
}
}
void KivioLayer::paintSelectionHandles( KivioPainter& painter, const TQRect&, bool, TQPoint, KoZoomHandler* zoom )
{
if(!visible()) {
return;
}
KivioIntraStencilData data;
painter.setFGColor( TQColor(0,0,0) );
data.painter = &painter;
data.zoomHandler = zoom;
KivioStencil *pStencil = m_pStencilList->first();
while( pStencil )
{
if( pStencil->isSelected() && !pStencil->hidden() )
pStencil->paintSelectionHandles( &data );
pStencil = m_pStencilList->next();
}
}
KivioStencil *KivioLayer::checkForStencil( KoPoint *pPoint, int *collisionType, float threshold, bool selectedOnly )
{
KivioStencil *pStencil;
int colType;
if(editable()) {
pStencil = m_pStencilList->last();
while( pStencil )
{
// If we are only supposed to check the selected stencils, then only do that. Otherwise
// check them all.
if( (selectedOnly==true && pStencil->isSelected()==true) ||
(selectedOnly==false) )
{
if( (colType = pStencil->checkForCollision( pPoint, threshold )) != kctNone )
{
// Assign the collision type and return
*collisionType = colType;
return pStencil;
}
}
pStencil = m_pStencilList->prev();
}
}
*collisionType = kctNone;
return NULL;
}
void KivioLayer::setVisible( bool f )
{
if( f==true )
{
m_flags = m_flags | FLOW_LAYER_VISIBLE;
}
else
{
m_flags = m_flags & (~FLOW_LAYER_VISIBLE);
}
}
void KivioLayer::setConnectable( bool f )
{
if( f==true )
{
m_flags = m_flags | FLOW_LAYER_CONNECTABLE;
}
else
{
m_flags = m_flags & (~FLOW_LAYER_CONNECTABLE);
}
}
void KivioLayer::setEditable(bool f)
{
if(f) {
m_flags = m_flags & (~FLOW_LAYER_NOT_EDITABLE);
} else {
m_flags = m_flags | FLOW_LAYER_NOT_EDITABLE;
}
}
void KivioLayer::setPrintable(bool f)
{
if(f) {
m_flags = m_flags & (~FLOW_LAYER_NOT_PRINTABLE);
} else {
m_flags = m_flags | FLOW_LAYER_NOT_PRINTABLE;
}
}
int KivioLayer::generateStencilIds( int next )
{
KivioStencil *pStencil;
pStencil = m_pStencilList->first();
while( pStencil )
{
next = pStencil->generateIds( next );
pStencil = m_pStencilList->next();
}
return next;
}
void KivioLayer::searchForConnections( KivioPage *p )
{
KivioStencil *pStencil;
KivioStencil *pCur;
pStencil = m_pStencilList->first();
while( pStencil )
{
// Backup the current list position
pCur = pStencil;
pStencil->searchForConnections( p );
// Restore it
m_pStencilList->find( pCur );
pStencil = m_pStencilList->next();
}
}
KivioStencil *KivioLayer::takeStencil( KivioStencil *p )
{
m_pStencilList->find( p );
return m_pStencilList->take();
}
/**
* Attempts to connect a KivioConnectorPoint to a KivioConnectorTarget of each stencil.
*
* @param p The point to attempt the connection with
* @param thresh The threshold to use
* @returns The KivioConnectorTarget the point connected to
*/
KivioConnectorTarget *KivioLayer::connectPointToTarget( KivioConnectorPoint *p, float thresh )
{
KivioConnectorTarget *pTarget;
KivioStencil *pStencil = m_pStencilList->last();
while( pStencil )
{
// Don't allow the connector point to connect to the stencil that owns it
if( pStencil != p->stencil() )
{
pTarget = pStencil->connectToTarget(p, thresh);
if( pTarget )
{
return pTarget;
}
}
pStencil = m_pStencilList->prev();
}
return NULL;
}
KoPoint KivioLayer::snapToTarget( const KoPoint& p, double thresh, bool& hit )
{
KoPoint retVal = p;
KivioStencil *pStencil = m_pStencilList->last();
while( pStencil && !hit)
{
retVal = pStencil->snapToTarget(p, thresh, hit);
pStencil = m_pStencilList->prev();
}
return retVal;
}