xref: /AOO41X/main/oox/source/drawingml/diagram/diagram.cxx (revision ca5ec2004b000a7d9aaa8381be8ac2853e3b1dc7)
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