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 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_chart2.hxx"
30 
31 #include "chartview/DrawModelWrapper.hxx"
32 #include "macros.hxx"
33 #include "ShapeFactory.hxx"
34 #include "ChartItemPool.hxx"
35 #include "ObjectIdentifier.hxx"
36 #include <svx/unomodel.hxx>
37 #include <svl/itempool.hxx>
38 // header for class SfxBoolItem
39 #include <svl/eitem.hxx>
40 // header for define EE_PARA_HYPHENATE
41 #include <editeng/eeitem.hxx>
42 // header for class Svx3DPercentDiagonalItem
43 #include <svx/svx3ditems.hxx>
44 // header for class SvtPathOptions
45 #include <unotools/pathoptions.hxx>
46 // header E3dObjFactory
47 #include <svx/objfac3d.hxx>
48 // header for class SdrObjList
49 #include <svx/svdpage.hxx>
50 // header for SvxUnoXDashTable_createInstance
51 #include <svx/XPropertyTable.hxx>
52 // header for class XDashList
53 #include <svx/xtable.hxx>
54 // header for class SdrOutliner
55 #include <svx/svdoutl.hxx>
56 // header for class LinguMgr
57 #include <editeng/unolingu.hxx>
58 // header for class Application
59 #include <vcl/svapp.hxx>
60 // header for class VirtualDevice
61 #include <vcl/virdev.hxx>
62 
63 #include <com/sun/star/container/XChild.hpp>
64 #include <com/sun/star/lang/XUnoTunnel.hpp>
65 
66 #include <sfx2/objsh.hxx>
67 #include <com/sun/star/linguistic2/XHyphenator.hpp>
68 #include <com/sun/star/linguistic2/XSpellChecker1.hpp>
69 
70 using namespace ::com::sun::star;
71 
72 //.............................................................................
73 namespace
74 {
75 // this code is copied from sfx2/source/doc/objembed.cxx
76 SfxObjectShell * lcl_GetParentObjectShell( const uno::Reference< frame::XModel > & xModel )
77 {
78     SfxObjectShell* pResult = NULL;
79 
80     try
81     {
82         uno::Reference< container::XChild > xChildModel( xModel, uno::UNO_QUERY );
83         if ( xChildModel.is() )
84         {
85             uno::Reference< lang::XUnoTunnel > xParentTunnel( xChildModel->getParent(), uno::UNO_QUERY );
86             if ( xParentTunnel.is() )
87             {
88                 SvGlobalName aSfxIdent( SFX_GLOBAL_CLASSID );
89                 pResult = reinterpret_cast< SfxObjectShell * >(
90                     xParentTunnel->getSomething( uno::Sequence< sal_Int8 >( aSfxIdent.GetByteSequence() ) ) );
91             }
92         }
93     }
94     catch( uno::Exception& )
95     {
96         // TODO: error handling
97     }
98 
99     return pResult;
100 }
101 
102 // this code is copied from sfx2/source/doc/objembed.cxx.  It is a workaround to
103 // get the reference device (e.g. printer) fromthe parent document
104 OutputDevice * lcl_GetParentRefDevice( const uno::Reference< frame::XModel > & xModel )
105 {
106     SfxObjectShell * pParent = lcl_GetParentObjectShell( xModel );
107     if ( pParent )
108         return pParent->GetDocumentRefDev();
109     return NULL;
110 }
111 
112 } // anonymous namespace
113 
114 //..    ...........................................................................
115 namespace chart
116 {
117 //.............................................................................
118 
119 DrawModelWrapper::DrawModelWrapper(
120 		uno::Reference<uno::XComponentContext> const & xContext )
121         : SdrModel( SvtPathOptions().GetPalettePath() )
122         , m_xMCF(0)
123         , m_pChartItemPool(0)
124         , m_xMainDrawPage(0)
125         , m_xHiddenDrawPage(0)
126         , m_apRefDevice(0)
127 {
128     m_pChartItemPool = ChartItemPool::CreateChartItemPool();
129 
130     m_xMCF = xContext->getServiceManager();
131 
132     SetScaleUnit(MAP_100TH_MM);
133     SetScaleFraction(Fraction(1, 1));
134     SetDefaultFontHeight(423);     // 12pt
135 
136 	SfxItemPool* pMasterPool = &GetItemPool();
137 	pMasterPool->SetDefaultMetric(SFX_MAPUNIT_100TH_MM);
138 	pMasterPool->SetPoolDefaultItem(SfxBoolItem(EE_PARA_HYPHENATE, sal_True) );
139 	pMasterPool->SetPoolDefaultItem(Svx3DPercentDiagonalItem (5));
140 
141     SfxItemPool* pPool = pMasterPool;
142 	// append chart pool to end of pool chain
143 	for (;;)
144 	{
145 		SfxItemPool* pSecondary = pPool->GetSecondaryPool();
146 		if (!pSecondary)
147 			break;
148 
149 		pPool = pSecondary;
150 	}
151 	pPool->SetSecondaryPool(m_pChartItemPool);
152 	pMasterPool->FreezeIdRanges();
153 
154     //this factory needs to be created before first use of 3D scenes once upon an office runtime
155     //@todo in future this should be done by drawing engine itself on demand
156     static bool b3dFactoryInitialized = false;
157     if(!b3dFactoryInitialized)
158     {
159         E3dObjFactory aObjFactory;
160         b3dFactoryInitialized = true;
161     }
162 
163     //Hyphenyation and spellchecking
164     SdrOutliner& rOutliner = GetDrawOutliner();
165     try
166 	{
167         uno::Reference< linguistic2::XHyphenator > xHyphenator( LinguMgr::GetHyphenator() );
168 	    if( xHyphenator.is() )
169 		    rOutliner.SetHyphenator( xHyphenator );
170 
171         uno::Reference< linguistic2::XSpellChecker1 > xSpellChecker( LinguMgr::GetSpellChecker() );
172 	    if ( xSpellChecker.is() )
173 		    rOutliner.SetSpeller( xSpellChecker );
174 	}
175 	catch(...)
176 	{
177 		DBG_ERROR("Can't get Hyphenator or SpellChecker for chart");
178 	}
179 
180     //ref device for font rendering
181     OutputDevice* pDefaultDevice = rOutliner.GetRefDevice();
182     if( !pDefaultDevice )
183         pDefaultDevice = Application::GetDefaultDevice();
184     m_apRefDevice = std::auto_ptr< OutputDevice >( new VirtualDevice( *pDefaultDevice ) );
185     MapMode aMapMode = m_apRefDevice->GetMapMode();
186     aMapMode.SetMapUnit(MAP_100TH_MM);
187     m_apRefDevice->SetMapMode(aMapMode);
188     SetRefDevice(m_apRefDevice.get());
189     rOutliner.SetRefDevice(m_apRefDevice.get());
190 }
191 
192 DrawModelWrapper::~DrawModelWrapper()
193 {
194     //remove m_pChartItemPool from pool chain
195     if(m_pChartItemPool)
196     {
197 	    SfxItemPool* pPool = &GetItemPool();
198 	    for (;;)
199 	    {
200 		    SfxItemPool* pSecondary = pPool->GetSecondaryPool();
201 		    if(pSecondary == m_pChartItemPool)
202 		    {
203 			    pPool->SetSecondaryPool (NULL);
204 			    break;
205 		    }
206 		    pPool = pSecondary;
207 	    }
208         SfxItemPool::Free(m_pChartItemPool);
209     }
210 }
211 
212 uno::Reference< uno::XInterface > DrawModelWrapper
213 ::createUnoModel()
214 {
215 	uno::Reference< lang::XComponent > xComponent = new SvxUnoDrawingModel( this ); //tell Andreas Schluens if SvxUnoDrawingModel is not needed anymore -> remove export from svx to avoid link problems in writer
216 	return uno::Reference< uno::XInterface >::query( xComponent );
217 }
218 
219 uno::Reference< frame::XModel > DrawModelWrapper::getUnoModel()
220 {
221     uno::Reference< uno::XInterface > xI = this->SdrModel::getUnoModel();
222     return uno::Reference<frame::XModel>::query( xI );
223 }
224 
225 SdrModel& DrawModelWrapper::getSdrModel()
226 {
227     return *this;
228 }
229 
230 uno::Reference< lang::XMultiServiceFactory > DrawModelWrapper::getShapeFactory()
231 {
232     uno::Reference< lang::XMultiServiceFactory > xShapeFactory( this->getUnoModel(), uno::UNO_QUERY );
233     return xShapeFactory;
234 }
235 
236 uno::Reference< drawing::XDrawPage > DrawModelWrapper::getMainDrawPage()
237 {
238     //create draw page:
239 	if( !m_xMainDrawPage.is() )
240     {
241         uno::Reference< drawing::XDrawPagesSupplier > xDrawPagesSuplier( this->getUnoModel(), uno::UNO_QUERY );
242         if( xDrawPagesSuplier.is() )
243         {
244             uno::Reference< drawing::XDrawPages > xDrawPages( xDrawPagesSuplier->getDrawPages () );
245             if( xDrawPages->getCount()>1 )
246             {
247                 uno::Any aPage = xDrawPages->getByIndex( 0 ) ;
248                 aPage >>= m_xMainDrawPage;
249             }
250             if(!m_xMainDrawPage.is())
251             {
252                 m_xMainDrawPage = xDrawPages->insertNewByIndex( 0 );
253             }
254         }
255     }
256     //ensure that additional shapes are in front of the chart objects so create the chart root before
257     ShapeFactory(this->getShapeFactory()).getOrCreateChartRootShape( m_xMainDrawPage );
258     return m_xMainDrawPage;
259 }
260 uno::Reference< drawing::XDrawPage > DrawModelWrapper::getHiddenDrawPage()
261 {
262     if( !m_xHiddenDrawPage.is() )
263     {
264         uno::Reference< drawing::XDrawPagesSupplier > xDrawPagesSuplier( this->getUnoModel(), uno::UNO_QUERY );
265         if( xDrawPagesSuplier.is() )
266         {
267             uno::Reference< drawing::XDrawPages > xDrawPages( xDrawPagesSuplier->getDrawPages () );
268             if( xDrawPages->getCount()>1 )
269             {
270                 uno::Any aPage = xDrawPages->getByIndex( 1 ) ;
271                 aPage >>= m_xHiddenDrawPage;
272             }
273 
274             if(!m_xHiddenDrawPage.is())
275             {
276                 if( xDrawPages->getCount()==0 )
277                     m_xMainDrawPage = xDrawPages->insertNewByIndex( 0 );
278                 m_xHiddenDrawPage = xDrawPages->insertNewByIndex( 1 );
279             }
280         }
281     }
282     return m_xHiddenDrawPage;
283 }
284 void DrawModelWrapper::clearMainDrawPage()
285 {
286     //uno::Reference<drawing::XShapes> xChartRoot( m_xMainDrawPage, uno::UNO_QUERY );
287     uno::Reference<drawing::XShapes> xChartRoot( ShapeFactory::getChartRootShape( m_xMainDrawPage ) );
288     if( xChartRoot.is() )
289     {
290         sal_Int32 nSubCount = xChartRoot->getCount();
291         uno::Reference< drawing::XShape > xShape;
292         for( sal_Int32 nS = nSubCount; nS--; )
293         {
294             if( xChartRoot->getByIndex( nS ) >>= xShape )
295                 xChartRoot->remove( xShape );
296         }
297     }
298 }
299 
300 uno::Reference< drawing::XShapes > DrawModelWrapper::getChartRootShape(
301     const uno::Reference< drawing::XDrawPage>& xDrawPage )
302 {
303     return ShapeFactory::getChartRootShape( xDrawPage );
304 }
305 
306 void DrawModelWrapper::lockControllers()
307 {
308     uno::Reference< frame::XModel > xDrawModel( this->getUnoModel() );
309     if( xDrawModel.is())
310 		xDrawModel->lockControllers();
311 }
312 void DrawModelWrapper::unlockControllers()
313 {
314     uno::Reference< frame::XModel > xDrawModel( this->getUnoModel() );
315     if( xDrawModel.is())
316 		xDrawModel->unlockControllers();
317 }
318 
319 void DrawModelWrapper::attachParentReferenceDevice( const uno::Reference< frame::XModel > & xChartModel )
320 {
321     OutputDevice * pParentRefDev( lcl_GetParentRefDevice( xChartModel ));
322     if( pParentRefDev )
323     {
324         SetRefDevice( pParentRefDev );
325     }
326 }
327 
328 OutputDevice* DrawModelWrapper::getReferenceDevice() const
329 {
330     return SdrModel::GetRefDevice();
331 }
332 
333 SfxItemPool& DrawModelWrapper::GetItemPool()
334 {
335     return this->SdrModel::GetItemPool();
336 }
337 const SfxItemPool& DrawModelWrapper::GetItemPool() const
338 {
339     return this->SdrModel::GetItemPool();
340 }
341 XColorTable* DrawModelWrapper::GetColorTable() const
342 {
343     return this->SdrModel::GetColorTable();
344 }
345 XDashList* DrawModelWrapper::GetDashList() const
346 {
347     return this->SdrModel::GetDashList();
348 }
349 XLineEndList* DrawModelWrapper::GetLineEndList() const
350 {
351     return this->SdrModel::GetLineEndList();
352 }
353 XGradientList* DrawModelWrapper::GetGradientList() const
354 {
355     return this->SdrModel::GetGradientList();
356 }
357 XHatchList* DrawModelWrapper::GetHatchList() const
358 {
359     return this->SdrModel::GetHatchList();
360 }
361 XBitmapList* DrawModelWrapper::GetBitmapList() const
362 {
363     return this->SdrModel::GetBitmapList();
364 }
365 
366 SdrObject* DrawModelWrapper::getNamedSdrObject( const rtl::OUString& rName )
367 {
368     if(rName.getLength()==0)
369         return 0;
370     return getNamedSdrObject( rName, GetPage(0) );
371 }
372 
373 SdrObject* DrawModelWrapper::getNamedSdrObject( const String& rObjectCID, SdrObjList* pSearchList )
374 {
375     if(!pSearchList || rObjectCID.Len()==0)
376         return 0;
377     sal_uLong nCount = pSearchList->GetObjCount();
378     for( sal_uLong nN=0; nN<nCount; nN++  )
379     {
380         SdrObject* pObj = pSearchList->GetObj(nN);
381         if(!pObj)
382             continue;
383         if( ObjectIdentifier::areIdenticalObjects( rObjectCID, pObj->GetName() ) )
384             return pObj;
385         pObj = DrawModelWrapper::getNamedSdrObject( rObjectCID, pObj->GetSubList() );
386         if(pObj)
387             return pObj;
388     }
389     return 0;
390 }
391 
392 bool DrawModelWrapper::removeShape( const uno::Reference< drawing::XShape >& xShape )
393 {
394     uno::Reference< container::XChild > xChild( xShape, uno::UNO_QUERY );
395     if( xChild.is() )
396     {
397         uno::Reference<drawing::XShapes> xShapes( xChild->getParent(), uno::UNO_QUERY );
398         if( xShapes.is() )
399         {
400             xShapes->remove(xShape);
401             return true;
402         }
403     }
404     return false;
405 }
406 
407 //.............................................................................
408 } //namespace chart
409 //.............................................................................
410