1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 29 #include <functional> 30 #include <boost/bind.hpp> 31 32 #include <com/sun/star/awt/Point.hpp> 33 #include <com/sun/star/awt/Size.hpp> 34 #include "oox/drawingml/diagram/diagram.hxx" 35 #include "oox/drawingml/fillproperties.hxx" 36 37 using rtl::OUString; 38 using namespace ::com::sun::star; 39 40 namespace oox { namespace drawingml { 41 42 namespace dgm { 43 44 45 void Connection::dump() 46 { 47 OSL_TRACE("dgm: cnx modelId %s, srcId %s, dstId %s", 48 OUSTRING_TO_CSTR( msModelId ), 49 OUSTRING_TO_CSTR( msSourceId ), 50 OUSTRING_TO_CSTR( msDestId ) ); 51 } 52 53 Point::Point() 54 : mpShape( new Shape( "com.sun.star.drawing.GraphicObjectShape" ) ) 55 , mnType( 0 ) 56 { 57 } 58 59 void Point::dump() 60 { 61 OSL_TRACE( "dgm: pt cnxId %s, modelId %s", 62 OUSTRING_TO_CSTR( msCnxId ), 63 OUSTRING_TO_CSTR( msModelId ) ); 64 } 65 66 void Point::setModelId( const ::rtl::OUString & sModelId ) 67 { 68 msModelId = sModelId; 69 mpShape->setName( msModelId ); 70 } 71 72 73 bool PointsTree::addChild( const PointsTreePtr & pChild ) 74 { 75 bool added = false; 76 77 OSL_ENSURE( pChild->mpParent.expired(), "can't add, has already a parent" ); 78 OSL_ENSURE( mpNode, "has no node" ); 79 if( mpNode && pChild->mpParent.expired() ) 80 { 81 pChild->mpParent = shared_from_this(); 82 maChildrens.push_back( pChild ); 83 added = true; 84 } 85 86 return added; 87 } 88 89 PointsTreePtr PointsTree::getParent() const 90 { 91 if( !mpParent.expired() ) 92 { 93 return mpParent.lock() ; 94 } 95 return PointsTreePtr(); 96 } 97 98 99 } // dgm namespace 100 101 DiagramData::DiagramData() 102 : mpFillProperties( new FillProperties ) 103 { 104 } 105 106 void DiagramData::dump() 107 { 108 OSL_TRACE("Dgm: DiagramData # of cnx: %d", maConnections.size() ); 109 std::for_each( maConnections.begin(), maConnections.end(), 110 boost::bind( &dgm::Connection::dump, _1 ) ); 111 OSL_TRACE("Dgm: DiagramData # of pt: %d", maPoints.size() ); 112 std::for_each( maPoints.begin(), maPoints.end(), 113 boost::bind( &dgm::Point::dump, _1 ) ); 114 } 115 116 static void setPosition( const dgm::PointPtr & pPoint, const awt::Point & pt ) 117 { 118 ShapePtr pShape = pPoint->getShape(); 119 awt::Size sz; 120 sz.Width = 50; 121 sz.Height = 50; 122 pShape->setPosition( pt ); 123 pShape->setSize( sz ); 124 } 125 126 void DiagramLayout::layout( const dgm::PointsTreePtr & pTree, const awt::Point & pt ) 127 { 128 setPosition( pTree->getPoint(), pt ); 129 awt::Point nextPt = pt; 130 nextPt.Y += 50; 131 dgm::PointsTree::Childrens::const_iterator iter; 132 for( iter = pTree->beginChild(); iter != pTree->endChild(); iter++ ) 133 { 134 layout( *iter, nextPt ); 135 nextPt.X += 50; 136 } 137 } 138 139 void Diagram::setData( const DiagramDataPtr & pData) 140 { 141 mpData = pData; 142 } 143 144 145 void Diagram::setLayout( const DiagramLayoutPtr & pLayout) 146 { 147 mpLayout = pLayout; 148 } 149 150 void Diagram::setQStyles( const DiagramQStylesPtr & pStyles) 151 { 152 mpQStyles = pStyles; 153 } 154 155 156 void Diagram::setColors( const DiagramColorsPtr & pColors) 157 { 158 mpColors = pColors; 159 } 160 161 void Diagram::build( ) 162 { 163 OSL_TRACE( "building diagram" ); 164 typedef std::map< OUString, dgm::PointPtr > PointsMap; 165 PointsMap aPointsMap; 166 dgm::Points::iterator aPointsIter( mpData->getPoints( ).begin() ); 167 for( ; aPointsIter != mpData->getPoints( ).end() ; aPointsIter++ ) 168 { 169 const OUString & sName((*aPointsIter)->getModelId()); 170 if( sName.getLength() > 0 ) 171 { 172 aPointsMap[ sName ] = *aPointsIter; 173 } 174 } 175 176 typedef std::map< OUString, dgm::PointsTreePtr > PointsTreeMap; 177 PointsTreeMap aTreeMap; 178 PointsTreeMap aRoots; 179 180 dgm::Connections & aConnections(mpData->getConnections( ) ); 181 dgm::Connections::iterator aCnxIter; 182 for( aCnxIter = aConnections.begin(); aCnxIter != aConnections.end(); ++aCnxIter ) 183 { 184 OSL_ENSURE( *aCnxIter, "NULL connection found" ); 185 if( (*aCnxIter)->mnType != XML_parOf ) 186 { 187 // OSL_TRACE( "ignoring relation %s", OUSTRING_TO_CSTR( (*aCnxIter)->msModelId ) ); 188 continue; 189 } 190 dgm::PointPtr pDest; 191 dgm::PointsTreePtr pSource; 192 PointsMap::iterator iterP; 193 OUString & srcId( (*aCnxIter)->msSourceId ); 194 OUString & dstId( (*aCnxIter)->msDestId ); 195 OSL_TRACE( "connexion %s -> %s", OUSTRING_TO_CSTR( srcId ), 196 OUSTRING_TO_CSTR( dstId ) ); 197 198 PointsTreeMap::iterator iterT = aTreeMap.find( srcId ); 199 if( iterT != aTreeMap.end() ) 200 { 201 pSource = iterT->second; 202 } 203 else 204 { 205 // this tree node is not found. create it with the source 206 // and make it the root node. 207 iterP = aPointsMap.find( srcId ); 208 if( iterP != aPointsMap.end() ) 209 { 210 pSource.reset( new dgm::PointsTree( iterP->second ) ); 211 aRoots[ srcId ] = pSource; 212 aTreeMap[ srcId ] = pSource; 213 } 214 else 215 { 216 OSL_TRACE("parent node not found !"); 217 } 218 } 219 iterP = aPointsMap.find( dstId ); 220 if( iterP != aPointsMap.end() ) 221 { 222 pDest = iterP->second; 223 } 224 OSL_ENSURE( pDest, "destination not found" ); 225 OSL_ENSURE( pSource, "source not found" ); 226 if(pDest && pSource) 227 { 228 dgm::PointsTreePtr pNode( new dgm::PointsTree( pDest ) ); 229 bool added = pSource->addChild( pNode ); 230 (void)added; 231 aRoots.erase( dstId ); 232 OSL_ENSURE( added, "add child failed" ); 233 aTreeMap[ dstId ] = pNode; 234 } 235 } 236 // check bounds 237 OSL_ENSURE( aRoots.size() == 1, "more than one root" ); 238 // #i92239# roots may be empty 239 if( !aRoots.empty() ) 240 { 241 mpRoot = aRoots.begin()->second; 242 OSL_TRACE( "root is %s", OUSTRING_TO_CSTR( mpRoot->getPoint()->getModelId() ) ); 243 for( PointsTreeMap::iterator iter = aTreeMap.begin(); 244 iter != aTreeMap.end(); iter++ ) 245 { 246 if(! iter->second->getParent() ) 247 { 248 OSL_TRACE("node without parent %s", OUSTRING_TO_CSTR( iter->first ) ); 249 } 250 } 251 } 252 } 253 254 255 void Diagram::addTo( const ShapePtr & pParentShape ) 256 { 257 dgm::Points & aPoints( mpData->getPoints( ) ); 258 dgm::Points::iterator aPointsIter; 259 build( ); 260 if( mpRoot.get() ) 261 mpLayout->layout( mpRoot, awt::Point( 0, 0 ) ); 262 263 for( aPointsIter = aPoints.begin(); aPointsIter != aPoints.end(); ++aPointsIter ) 264 { 265 if( ( *aPointsIter )->getType() != XML_node ) 266 { 267 continue; 268 } 269 ShapePtr pShape = ( *aPointsIter )->getShape( ); 270 if( pShape->getName( ).getLength() > 0 ) 271 { 272 maShapeMap[ pShape->getName( ) ] = pShape; 273 OSL_TRACE( "Dgm: added shape %s to map", OUSTRING_TO_CSTR( pShape->getName() ) ); 274 } 275 pParentShape->addChild( pShape ); 276 } 277 278 OSL_TRACE( "Dgm: addTo() # of childs %d", pParentShape->getChildren().size() ); 279 for( std::vector< ShapePtr >::iterator iter = pParentShape->getChildren().begin(); 280 iter != pParentShape->getChildren().end(); ++iter) 281 { 282 OSL_TRACE( "Dgm: shape name %s", OUSTRING_TO_CSTR( (*iter)->getName() ) ); 283 } 284 } 285 286 OUString Diagram::getLayoutId() const 287 { 288 OUString sLayoutId; 289 if( mpLayout ) 290 { 291 sLayoutId = mpLayout->getUniqueId(); 292 } 293 return sLayoutId; 294 } 295 296 297 } } 298