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