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