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