| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| |
| #include <functional> |
| #include <boost/bind.hpp> |
| |
| #include <com/sun/star/awt/Point.hpp> |
| #include <com/sun/star/awt/Size.hpp> |
| #include "oox/drawingml/diagram/diagram.hxx" |
| #include "oox/drawingml/fillproperties.hxx" |
| |
| using rtl::OUString; |
| using namespace ::com::sun::star; |
| |
| namespace oox { namespace drawingml { |
| |
| namespace dgm { |
| |
| |
| void Connection::dump() |
| { |
| OSL_TRACE("dgm: cnx modelId %s, srcId %s, dstId %s", |
| OUSTRING_TO_CSTR( msModelId ), |
| OUSTRING_TO_CSTR( msSourceId ), |
| OUSTRING_TO_CSTR( msDestId ) ); |
| } |
| |
| Point::Point() |
| : mpShape( new Shape( "com.sun.star.drawing.GraphicObjectShape" ) ) |
| , mnType( 0 ) |
| { |
| } |
| |
| void Point::dump() |
| { |
| OSL_TRACE( "dgm: pt cnxId %s, modelId %s", |
| OUSTRING_TO_CSTR( msCnxId ), |
| OUSTRING_TO_CSTR( msModelId ) ); |
| } |
| |
| void Point::setModelId( const ::rtl::OUString & sModelId ) |
| { |
| msModelId = sModelId; |
| mpShape->setName( msModelId ); |
| } |
| |
| |
| bool PointsTree::addChild( const PointsTreePtr & pChild ) |
| { |
| bool added = false; |
| |
| OSL_ENSURE( pChild->mpParent.expired(), "can't add, has already a parent" ); |
| OSL_ENSURE( mpNode, "has no node" ); |
| if( mpNode && pChild->mpParent.expired() ) |
| { |
| pChild->mpParent = shared_from_this(); |
| maChildrens.push_back( pChild ); |
| added = true; |
| } |
| |
| return added; |
| } |
| |
| PointsTreePtr PointsTree::getParent() const |
| { |
| if( !mpParent.expired() ) |
| { |
| return mpParent.lock() ; |
| } |
| return PointsTreePtr(); |
| } |
| |
| |
| } // dgm namespace |
| |
| DiagramData::DiagramData() |
| : mpFillProperties( new FillProperties ) |
| { |
| } |
| |
| void DiagramData::dump() |
| { |
| OSL_TRACE("Dgm: DiagramData # of cnx: %d", maConnections.size() ); |
| std::for_each( maConnections.begin(), maConnections.end(), |
| boost::bind( &dgm::Connection::dump, _1 ) ); |
| OSL_TRACE("Dgm: DiagramData # of pt: %d", maPoints.size() ); |
| std::for_each( maPoints.begin(), maPoints.end(), |
| boost::bind( &dgm::Point::dump, _1 ) ); |
| } |
| |
| static void setPosition( const dgm::PointPtr & pPoint, const awt::Point & pt ) |
| { |
| ShapePtr pShape = pPoint->getShape(); |
| awt::Size sz; |
| sz.Width = 50; |
| sz.Height = 50; |
| pShape->setPosition( pt ); |
| pShape->setSize( sz ); |
| } |
| |
| void DiagramLayout::layout( const dgm::PointsTreePtr & pTree, const awt::Point & pt ) |
| { |
| setPosition( pTree->getPoint(), pt ); |
| awt::Point nextPt = pt; |
| nextPt.Y += 50; |
| dgm::PointsTree::Childrens::const_iterator iter; |
| for( iter = pTree->beginChild(); iter != pTree->endChild(); iter++ ) |
| { |
| layout( *iter, nextPt ); |
| nextPt.X += 50; |
| } |
| } |
| |
| void Diagram::setData( const DiagramDataPtr & pData) |
| { |
| mpData = pData; |
| } |
| |
| |
| void Diagram::setLayout( const DiagramLayoutPtr & pLayout) |
| { |
| mpLayout = pLayout; |
| } |
| |
| void Diagram::setQStyles( const DiagramQStylesPtr & pStyles) |
| { |
| mpQStyles = pStyles; |
| } |
| |
| |
| void Diagram::setColors( const DiagramColorsPtr & pColors) |
| { |
| mpColors = pColors; |
| } |
| |
| void Diagram::build( ) |
| { |
| OSL_TRACE( "building diagram" ); |
| typedef std::map< OUString, dgm::PointPtr > PointsMap; |
| PointsMap aPointsMap; |
| dgm::Points::iterator aPointsIter( mpData->getPoints( ).begin() ); |
| for( ; aPointsIter != mpData->getPoints( ).end() ; aPointsIter++ ) |
| { |
| const OUString & sName((*aPointsIter)->getModelId()); |
| if( sName.getLength() > 0 ) |
| { |
| aPointsMap[ sName ] = *aPointsIter; |
| } |
| } |
| |
| typedef std::map< OUString, dgm::PointsTreePtr > PointsTreeMap; |
| PointsTreeMap aTreeMap; |
| PointsTreeMap aRoots; |
| |
| dgm::Connections & aConnections(mpData->getConnections( ) ); |
| dgm::Connections::iterator aCnxIter; |
| for( aCnxIter = aConnections.begin(); aCnxIter != aConnections.end(); ++aCnxIter ) |
| { |
| OSL_ENSURE( *aCnxIter, "NULL connection found" ); |
| if( (*aCnxIter)->mnType != XML_parOf ) |
| { |
| // OSL_TRACE( "ignoring relation %s", OUSTRING_TO_CSTR( (*aCnxIter)->msModelId ) ); |
| continue; |
| } |
| dgm::PointPtr pDest; |
| dgm::PointsTreePtr pSource; |
| PointsMap::iterator iterP; |
| OUString & srcId( (*aCnxIter)->msSourceId ); |
| OUString & dstId( (*aCnxIter)->msDestId ); |
| OSL_TRACE( "connexion %s -> %s", OUSTRING_TO_CSTR( srcId ), |
| OUSTRING_TO_CSTR( dstId ) ); |
| |
| PointsTreeMap::iterator iterT = aTreeMap.find( srcId ); |
| if( iterT != aTreeMap.end() ) |
| { |
| pSource = iterT->second; |
| } |
| else |
| { |
| // this tree node is not found. create it with the source |
| // and make it the root node. |
| iterP = aPointsMap.find( srcId ); |
| if( iterP != aPointsMap.end() ) |
| { |
| pSource.reset( new dgm::PointsTree( iterP->second ) ); |
| aRoots[ srcId ] = pSource; |
| aTreeMap[ srcId ] = pSource; |
| } |
| else |
| { |
| OSL_TRACE("parent node not found !"); |
| } |
| } |
| iterP = aPointsMap.find( dstId ); |
| if( iterP != aPointsMap.end() ) |
| { |
| pDest = iterP->second; |
| } |
| OSL_ENSURE( pDest, "destination not found" ); |
| OSL_ENSURE( pSource, "source not found" ); |
| if(pDest && pSource) |
| { |
| dgm::PointsTreePtr pNode( new dgm::PointsTree( pDest ) ); |
| bool added = pSource->addChild( pNode ); |
| (void)added; |
| aRoots.erase( dstId ); |
| OSL_ENSURE( added, "add child failed" ); |
| aTreeMap[ dstId ] = pNode; |
| } |
| } |
| // check bounds |
| OSL_ENSURE( aRoots.size() == 1, "more than one root" ); |
| // #i92239# roots may be empty |
| if( !aRoots.empty() ) |
| { |
| mpRoot = aRoots.begin()->second; |
| OSL_TRACE( "root is %s", OUSTRING_TO_CSTR( mpRoot->getPoint()->getModelId() ) ); |
| for( PointsTreeMap::iterator iter = aTreeMap.begin(); |
| iter != aTreeMap.end(); iter++ ) |
| { |
| if(! iter->second->getParent() ) |
| { |
| OSL_TRACE("node without parent %s", OUSTRING_TO_CSTR( iter->first ) ); |
| } |
| } |
| } |
| } |
| |
| |
| void Diagram::addTo( const ShapePtr & pParentShape ) |
| { |
| dgm::Points & aPoints( mpData->getPoints( ) ); |
| dgm::Points::iterator aPointsIter; |
| build( ); |
| if( mpRoot.get() ) |
| mpLayout->layout( mpRoot, awt::Point( 0, 0 ) ); |
| |
| for( aPointsIter = aPoints.begin(); aPointsIter != aPoints.end(); ++aPointsIter ) |
| { |
| if( ( *aPointsIter )->getType() != XML_node ) |
| { |
| continue; |
| } |
| ShapePtr pShape = ( *aPointsIter )->getShape( ); |
| if( pShape->getName( ).getLength() > 0 ) |
| { |
| maShapeMap[ pShape->getName( ) ] = pShape; |
| OSL_TRACE( "Dgm: added shape %s to map", OUSTRING_TO_CSTR( pShape->getName() ) ); |
| } |
| pParentShape->addChild( pShape ); |
| } |
| |
| OSL_TRACE( "Dgm: addTo() # of childs %d", pParentShape->getChildren().size() ); |
| for( std::vector< ShapePtr >::iterator iter = pParentShape->getChildren().begin(); |
| iter != pParentShape->getChildren().end(); ++iter) |
| { |
| OSL_TRACE( "Dgm: shape name %s", OUSTRING_TO_CSTR( (*iter)->getName() ) ); |
| } |
| } |
| |
| OUString Diagram::getLayoutId() const |
| { |
| OUString sLayoutId; |
| if( mpLayout ) |
| { |
| sLayoutId = mpLayout->getUniqueId(); |
| } |
| return sLayoutId; |
| } |
| |
| |
| } } |