1 /*************************************************************************
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3  *
4  * Copyright 2000, 2010 Oracle and/or its affiliates.
5  *
6  * OpenOffice.org - a multi-platform office productivity suite
7  *
8  * This file is part of OpenOffice.org.
9  *
10  * OpenOffice.org is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU Lesser General Public License version 3
12  * only, as published by the Free Software Foundation.
13  *
14  * OpenOffice.org is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU Lesser General Public License version 3 for more details
18  * (a copy is included in the LICENSE file that accompanied this code).
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * version 3 along with OpenOffice.org.  If not, see
22  * <http://www.openoffice.org/license.html>
23  * for a copy of the LGPLv3 License.
24  *
25  ************************************************************************/
26 
27 #include "precompiled_chart2.hxx"
28 
29 #include "ChartModelClone.hxx"
30 #include "ChartModelHelper.hxx"
31 #include "ControllerLockGuard.hxx"
32 #include "DataSourceHelper.hxx"
33 
34 /** === begin UNO includes === **/
35 #include <com/sun/star/chart2/XAnyDescriptionAccess.hpp>
36 #include <com/sun/star/util/XCloneable.hpp>
37 #include <com/sun/star/chart2/XChartDocument.hpp>
38 #include <com/sun/star/view/XSelectionSupplier.hpp>
39 #include <com/sun/star/lang/XComponent.hpp>
40 #include <com/sun/star/chart2/XTitled.hpp>
41 #include <com/sun/star/util/XModifiable.hpp>
42 #include <com/sun/star/chart2/data/XDataSource.hpp>
43 #include <com/sun/star/chart2/data/XLabeledDataSequence.hpp>
44 /** === end UNO includes === **/
45 
46 #include <comphelper/property.hxx>
47 #include <tools/diagnose_ex.h>
48 
49 //......................................................................................................................
50 namespace chart
51 {
52 //......................................................................................................................
53 
54 	/** === begin UNO using === **/
55 	using ::com::sun::star::uno::Reference;
56 	using ::com::sun::star::uno::XInterface;
57 	using ::com::sun::star::uno::UNO_QUERY;
58 	using ::com::sun::star::uno::UNO_QUERY_THROW;
59 	using ::com::sun::star::uno::UNO_SET_THROW;
60 	using ::com::sun::star::uno::Exception;
61 	using ::com::sun::star::uno::RuntimeException;
62 	using ::com::sun::star::uno::Any;
63 	using ::com::sun::star::uno::makeAny;
64 	using ::com::sun::star::uno::Sequence;
65 	using ::com::sun::star::uno::Type;
66     using ::com::sun::star::frame::XModel;
67     using ::com::sun::star::util::XCloneable;
68     using ::com::sun::star::chart2::XChartDocument;
69     using ::com::sun::star::chart2::XInternalDataProvider;
70     using ::com::sun::star::chart2::XAnyDescriptionAccess;
71     using ::com::sun::star::view::XSelectionSupplier;
72     using ::com::sun::star::lang::XComponent;
73     using ::com::sun::star::chart2::XTitled;
74     using ::com::sun::star::util::XModifiable;
75     using ::com::sun::star::chart2::data::XDataSource;
76     using ::com::sun::star::chart2::data::XLabeledDataSequence;
77     /** === end UNO using === **/
78 
79     // =================================================================================================================
80     // = helper
81     // =================================================================================================================
82     namespace
83     {
84         Reference< XModel > lcl_cloneModel( const Reference< XModel > & xModel )
85         {
86             Reference< XModel > xResult;
87             try
88             {
89                 const Reference< XCloneable > xCloneable( xModel, UNO_QUERY_THROW );
90                 xResult.set( xCloneable->createClone(), UNO_QUERY_THROW );
91             }
92             catch( const Exception& )
93             {
94         	    DBG_UNHANDLED_EXCEPTION();
95             }
96             return xResult;
97         }
98 
99     }
100 
101     // =================================================================================================================
102     // = ChartModelClone
103     // =================================================================================================================
104     // -----------------------------------------------------------------------------------------------------------------
105     ChartModelClone::ChartModelClone( const Reference< XModel >& i_model, const ModelFacet i_facet )
106     {
107         m_xModelClone.set( lcl_cloneModel( i_model ) );
108 
109         try
110         {
111             if ( i_facet == E_MODEL_WITH_DATA )
112             {
113                 const Reference< XChartDocument > xChartDoc( m_xModelClone, UNO_QUERY_THROW );
114                 ENSURE_OR_THROW( xChartDoc->hasInternalDataProvider(), "invalid chart model" );
115 
116                 const Reference< XCloneable > xCloneable( xChartDoc->getDataProvider(), UNO_QUERY_THROW );
117                 m_xDataClone.set( xCloneable->createClone(), UNO_QUERY_THROW );
118             }
119 
120             if ( i_facet == E_MODEL_WITH_SELECTION )
121             {
122                 const Reference< XSelectionSupplier > xSelSupp( m_xModelClone->getCurrentController(), UNO_QUERY_THROW );
123                 m_aSelection = xSelSupp->getSelection();
124             }
125         }
126         catch( const Exception& )
127         {
128             DBG_UNHANDLED_EXCEPTION();
129         }
130     }
131 
132 
133     // -----------------------------------------------------------------------------------------------------------------
134     ChartModelClone::~ChartModelClone()
135     {
136         if ( !impl_isDisposed() )
137             dispose();
138     }
139 
140     // -----------------------------------------------------------------------------------------------------------------
141     void ChartModelClone::dispose()
142     {
143         if ( impl_isDisposed() )
144             return;
145 
146         try
147         {
148             Reference< XComponent > xComp( m_xModelClone, UNO_QUERY_THROW );
149             xComp->dispose();
150         }
151         catch( const Exception& )
152         {
153     	    DBG_UNHANDLED_EXCEPTION();
154         }
155         m_xModelClone.clear();
156         m_xDataClone.clear();
157         m_aSelection.clear();
158     }
159 
160     // -----------------------------------------------------------------------------------------------------------------
161     ModelFacet ChartModelClone::getFacet() const
162     {
163         if ( m_aSelection.hasValue() )
164             return E_MODEL_WITH_SELECTION;
165         if ( m_xDataClone.is() )
166             return E_MODEL_WITH_DATA;
167         return E_MODEL;
168     }
169 
170     // -----------------------------------------------------------------------------------------------------------------
171     void ChartModelClone::applyToModel( const Reference< XModel >& i_model ) const
172     {
173         applyModelContentToModel( i_model, m_xModelClone, m_xDataClone );
174 
175         if ( m_aSelection.hasValue() )
176         {
177             try
178             {
179                 Reference< XSelectionSupplier > xCurrentSelectionSuppl( i_model->getCurrentController(), UNO_QUERY_THROW );
180                 xCurrentSelectionSuppl->select( m_aSelection );
181             }
182             catch( const Exception& )
183             {
184         	    DBG_UNHANDLED_EXCEPTION();
185             }
186         }
187     }
188 
189     // -----------------------------------------------------------------------------------------------------------------
190     namespace
191     {
192         void ImplApplyDataToModel( const Reference< XModel >& i_model, const Reference< XInternalDataProvider > & i_data )
193         {
194             Reference< XChartDocument > xDoc( i_model, UNO_QUERY );
195             OSL_ASSERT( xDoc.is() && xDoc->hasInternalDataProvider() );
196 
197             // copy data from stored internal data provider
198             if( xDoc.is() && xDoc->hasInternalDataProvider())
199             {
200                 Reference< XAnyDescriptionAccess > xCurrentData( xDoc->getDataProvider(), UNO_QUERY );
201                 Reference< XAnyDescriptionAccess > xSavedData( i_data, UNO_QUERY );
202                 if ( xCurrentData.is() && xSavedData.is() )
203                 {
204                     xCurrentData->setData( xSavedData->getData() );
205                     xCurrentData->setAnyRowDescriptions( xSavedData->getAnyRowDescriptions());
206                     xCurrentData->setAnyColumnDescriptions( xSavedData->getAnyColumnDescriptions());
207                 }
208             }
209         }
210     }
211 
212     // -----------------------------------------------------------------------------------------------------------------
213     void ChartModelClone::applyModelContentToModel( const Reference< XModel >& i_model,
214         const Reference< XModel >& i_modelToCopyFrom, const Reference< XInternalDataProvider >& i_data )
215     {
216         ENSURE_OR_RETURN_VOID( i_model.is(), "ChartModelElement::applyModelContentToModel: invalid source model!" );
217         ENSURE_OR_RETURN_VOID( i_modelToCopyFrom.is(), "ChartModelElement::applyModelContentToModel: invalid source model!" );
218         try
219         {
220             // /-- loccked controllers of destination
221             ControllerLockGuard aLockedControllers( i_model );
222             Reference< XChartDocument > xSource( i_modelToCopyFrom, UNO_QUERY_THROW );
223             Reference< XChartDocument > xDestination( i_model, UNO_QUERY_THROW );
224 
225             // propagate the correct flag for plotting of hidden values to the data provider and all used sequences
226             ChartModelHelper::setIncludeHiddenCells( ChartModelHelper::isIncludeHiddenCells( i_modelToCopyFrom ) , i_model );
227 
228             // diagram
229             xDestination->setFirstDiagram( xSource->getFirstDiagram() );
230 
231             // main title
232             Reference< XTitled > xDestinationTitled( xDestination, UNO_QUERY_THROW );
233             Reference< XTitled > xSourceTitled( xSource, UNO_QUERY_THROW );
234             xDestinationTitled->setTitleObject( xSourceTitled->getTitleObject() );
235 
236             // page background
237             ::comphelper::copyProperties(
238                 xSource->getPageBackground(),
239                 xDestination->getPageBackground() );
240 
241             // apply data (not applied in standard Undo)
242             if ( i_data.is() )
243                 ImplApplyDataToModel( i_model, i_data );
244 
245             // register all sequences at the internal data provider to get adapted
246             // indexes when columns are added/removed
247             if ( xDestination->hasInternalDataProvider() )
248             {
249                 Reference< XInternalDataProvider > xNewDataProvider( xDestination->getDataProvider(), UNO_QUERY );
250                 Reference< XDataSource > xUsedData( DataSourceHelper::getUsedData( i_model ) );
251                 if ( xUsedData.is() && xNewDataProvider.is() )
252                 {
253                     Sequence< Reference< XLabeledDataSequence > > aData( xUsedData->getDataSequences() );
254                     for( sal_Int32 i=0; i<aData.getLength(); ++i )
255                     {
256                         xNewDataProvider->registerDataSequenceForChanges( aData[i]->getValues() );
257                         xNewDataProvider->registerDataSequenceForChanges( aData[i]->getLabel() );
258                     }
259                 }
260             }
261 
262             // restore modify status
263             Reference< XModifiable > xSourceMod( xSource, UNO_QUERY );
264             Reference< XModifiable > xDestMod( xDestination, UNO_QUERY );
265             if ( xSourceMod.is() && xDestMod.is() && !xSourceMod->isModified() )
266             {
267                 xDestMod->setModified( sal_False );
268             }
269             // \-- loccked controllers of destination
270         }
271         catch( const Exception& )
272         {
273             DBG_UNHANDLED_EXCEPTION();
274         }
275     }
276 
277 
278 //......................................................................................................................
279 } // namespace chart
280 //......................................................................................................................
281