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 #include "precompiled_reportdesign.hxx"
24 
25 #include "RptUndo.hxx"
26 #include "uistrings.hrc"
27 #include "rptui_slotid.hrc"
28 #include "UITools.hxx"
29 #include "UndoEnv.hxx"
30 
31 #include <dbaccess/IController.hxx>
32 #include <com/sun/star/report/XSection.hpp>
33 #include <com/sun/star/beans/PropertyAttribute.hpp>
34 
35 #include <com/sun/star/awt/Point.hpp>
36 #include <com/sun/star/awt/Size.hpp>
37 #include <svx/unoshape.hxx>
38 #include <boost/bind.hpp>
39 #include <functional>
40 
41 namespace rptui
42 {
43 	using namespace ::com::sun::star;
44 	using namespace uno;
45 	using namespace lang;
46 	using namespace script;
47 	using namespace beans;
48 	using namespace awt;
49 	using namespace util;
50 	using namespace container;
51 	using namespace report;
52 
53 //----------------------------------------------------------------------------
54 namespace
55 {
56     void lcl_collectElements(const uno::Reference< report::XSection >& _xSection,::std::vector< uno::Reference< drawing::XShape> >& _rControls)
57     {
58         if ( _xSection.is() )
59 		{
60 			sal_Int32 nCount = _xSection->getCount();
61 			_rControls.reserve(nCount);
62 			while ( nCount )
63 			{
64                 uno::Reference< drawing::XShape> xShape(_xSection->getByIndex(nCount-1),uno::UNO_QUERY);
65 				_rControls.push_back(xShape);
66 				_xSection->remove(xShape);
67 				--nCount;
68 			}
69 		} // if ( _xSection.is() )
70     }
71     //----------------------------------------------------------------------------
72     void lcl_insertElements(const uno::Reference< report::XSection >& _xSection,const ::std::vector< uno::Reference< drawing::XShape> >& _aControls)
73     {
74         if ( _xSection.is() )
75 	    {
76 		    ::std::vector< uno::Reference< drawing::XShape> >::const_reverse_iterator aIter = _aControls.rbegin();
77 		    ::std::vector< uno::Reference< drawing::XShape> >::const_reverse_iterator aEnd = _aControls.rend();
78 		    for (; aIter != aEnd; ++aIter)
79             {
80                 try
81                 {
82                     const awt::Point aPos = (*aIter)->getPosition();
83                     const awt::Size aSize = (*aIter)->getSize();
84 			        _xSection->add(*aIter);
85                     (*aIter)->setPosition( aPos );
86         		    (*aIter)->setSize( aSize );
87                 }
88                 catch(const uno::Exception&)
89                 {
90                     OSL_ENSURE(0,"lcl_insertElements:Exception caught!");
91                 }
92             }
93 	    }
94     }
95     //----------------------------------------------------------------------------
96     void lcl_setValues(const uno::Reference< report::XSection >& _xSection,const ::std::vector< ::std::pair< ::rtl::OUString ,uno::Any> >& _aValues)
97     {
98         if ( _xSection.is() )
99 	    {
100 		    ::std::vector< ::std::pair< ::rtl::OUString ,uno::Any> >::const_iterator aIter = _aValues.begin();
101 		    ::std::vector< ::std::pair< ::rtl::OUString ,uno::Any> >::const_iterator aEnd = _aValues.end();
102 		    for (; aIter != aEnd; ++aIter)
103             {
104                 try
105                 {
106 			        _xSection->setPropertyValue(aIter->first,aIter->second);
107                 }
108                 catch(const uno::Exception&)
109                 {
110                     OSL_ENSURE(0,"lcl_setValues:Exception caught!");
111                 }
112             }
113 	    }
114     }
115 }
116 //----------------------------------------------------------------------------
117 TYPEINIT1( OSectionUndo,         OCommentUndoAction );
118 DBG_NAME(rpt_OSectionUndo)
119 //----------------------------------------------------------------------------
120 OSectionUndo::OSectionUndo(OReportModel& _rMod
121                            ,sal_uInt16 _nSlot
122 						   ,Action _eAction
123 						   ,sal_uInt16 nCommentID)
124 : OCommentUndoAction(_rMod,nCommentID)
125 ,m_eAction(_eAction)
126 ,m_nSlot(_nSlot)
127 ,m_bInserted(false)
128 {
129     DBG_CTOR(rpt_OSectionUndo,NULL);
130 }
131 // -----------------------------------------------------------------------------
132 OSectionUndo::~OSectionUndo()
133 {
134     if ( !m_bInserted )
135     {
136         OXUndoEnvironment& rEnv = static_cast< OReportModel& >( rMod ).GetUndoEnv();
137         ::std::vector< uno::Reference< drawing::XShape> >::iterator aEnd = m_aControls.end();
138         for (::std::vector< uno::Reference< drawing::XShape> >::iterator aIter = m_aControls.begin(); aIter != aEnd; ++aIter)
139         {
140             uno::Reference< drawing::XShape> xShape = *aIter;
141             rEnv.RemoveElement(xShape);
142 
143 #if OSL_DEBUG_LEVEL > 0
144             SvxShape* pShape = SvxShape::getImplementation( xShape );
145             SdrObject* pObject = pShape ? pShape->GetSdrObject() : NULL;
146             OSL_ENSURE( pShape && pShape->HasSdrObjectOwnership() && pObject && !pObject->IsInserted(),
147                 "OSectionUndo::~OSectionUndo: inconsistency in the shape/object ownership!" );
148 #endif
149             try
150             {
151                 comphelper::disposeComponent(xShape);
152             }
153             catch(uno::Exception)
154             {
155                 OSL_ENSURE(0,"Exception caught!");
156             }
157         }
158     }
159     DBG_DTOR(rpt_OSectionUndo,NULL);
160 }
161 // -----------------------------------------------------------------------------
162 void OSectionUndo::collectControls(const uno::Reference< report::XSection >& _xSection)
163 {
164     m_aControls.clear();
165 	try
166 	{
167         // copy all properties for restoring
168         uno::Reference< beans::XPropertySetInfo> xInfo = _xSection->getPropertySetInfo();
169         uno::Sequence< beans::Property> aSeq = xInfo->getProperties();
170         const beans::Property* pIter = aSeq.getConstArray();
171         const beans::Property* pEnd	 = pIter + aSeq.getLength();
172         for(;pIter != pEnd;++pIter)
173         {
174             if ( 0 == (pIter->Attributes & beans::PropertyAttribute::READONLY) )
175                 m_aValues.push_back(::std::pair< ::rtl::OUString ,uno::Any>(pIter->Name,_xSection->getPropertyValue(pIter->Name)));
176         }
177         lcl_collectElements(_xSection,m_aControls);
178 	}
179 	catch(uno::Exception&)
180 	{
181 	}
182 }
183 //----------------------------------------------------------------------------
184 void OSectionUndo::Undo()
185 {
186     try
187     {
188 		switch ( m_eAction )
189 		{
190 		case Inserted:
191             implReRemove();
192             break;
193 
194 		case Removed:
195             implReInsert();
196             break;
197     	}
198     }
199     catch( const Exception& )
200     {
201         OSL_ENSURE( sal_False, "OSectionUndo::Undo: caught an exception!" );
202     }
203 }
204 //----------------------------------------------------------------------------
205 void OSectionUndo::Redo()
206 {
207     try
208     {
209 	    switch ( m_eAction )
210 		{
211 		case Inserted:
212             implReInsert();
213             break;
214 
215 		case Removed:
216             implReRemove();
217 			break;
218     	}
219     }
220     catch( const Exception& )
221     {
222         OSL_ENSURE( sal_False, "OSectionUndo::Redo: caught an exception!" );
223     }
224 }
225 //----------------------------------------------------------------------------
226 TYPEINIT1( OReportSectionUndo,         OSectionUndo );
227 //----------------------------------------------------------------------------
228 OReportSectionUndo::OReportSectionUndo(OReportModel& _rMod,sal_uInt16 _nSlot
229 									   ,::std::mem_fun_t< uno::Reference< report::XSection >
230 											,OReportHelper> _pMemberFunction
231 									   ,const uno::Reference< report::XReportDefinition >& _xReport
232 									   ,Action _eAction
233 									   ,sal_uInt16 nCommentID)
234 : OSectionUndo(_rMod,_nSlot,_eAction,nCommentID)
235 ,m_aReportHelper(_xReport)
236 ,m_pMemberFunction(_pMemberFunction)
237 {
238 	if( m_eAction == Removed )
239         collectControls(m_pMemberFunction(&m_aReportHelper));
240 }
241 // -----------------------------------------------------------------------------
242 OReportSectionUndo::~OReportSectionUndo()
243 {
244 }
245 //----------------------------------------------------------------------------
246 void OReportSectionUndo::implReInsert( )
247 {
248 	const uno::Sequence< beans::PropertyValue > aArgs;
249 	m_pController->executeChecked(m_nSlot,aArgs);
250 	uno::Reference< report::XSection > xSection = m_pMemberFunction(&m_aReportHelper);
251     lcl_insertElements(xSection,m_aControls);
252     lcl_setValues(xSection,m_aValues);
253     m_bInserted = true;
254 }
255 //----------------------------------------------------------------------------
256 void OReportSectionUndo::implReRemove( )
257 {
258     if( m_eAction == Removed )
259         collectControls(m_pMemberFunction(&m_aReportHelper));
260 	const uno::Sequence< beans::PropertyValue > aArgs;
261 	m_pController->executeChecked(m_nSlot,aArgs);
262     m_bInserted = false;
263 }
264 //----------------------------------------------------------------------------
265 TYPEINIT1( OGroupSectionUndo,         OSectionUndo );
266 //----------------------------------------------------------------------------
267 OGroupSectionUndo::OGroupSectionUndo(OReportModel& _rMod,sal_uInt16 _nSlot
268 									   ,::std::mem_fun_t< uno::Reference< report::XSection >
269 											,OGroupHelper> _pMemberFunction
270 									   ,const uno::Reference< report::XGroup >& _xGroup
271 									   ,Action _eAction
272 									   ,sal_uInt16 nCommentID)
273 : OSectionUndo(_rMod,_nSlot,_eAction,nCommentID)
274 ,m_aGroupHelper(_xGroup)
275 ,m_pMemberFunction(_pMemberFunction)
276 {
277     if( m_eAction == Removed )
278     {
279         uno::Reference< report::XSection > xSection = m_pMemberFunction(&m_aGroupHelper);
280 		if ( xSection.is() )
281             m_sName = xSection->getName();
282         collectControls(xSection);
283     }
284 }
285 //----------------------------------------------------------------------------
286 String OGroupSectionUndo::GetComment() const
287 {
288     if ( !m_sName.getLength() )
289     {
290         try
291         {
292             uno::Reference< report::XSection > xSection = const_cast<OGroupSectionUndo*>(this)->m_pMemberFunction(&const_cast<OGroupSectionUndo*>(this)->m_aGroupHelper);
293 
294 		    if ( xSection.is() )
295                 m_sName = xSection->getName();
296         }
297         catch(uno::Exception&)
298         {}
299     }
300     return m_strComment + m_sName;
301 }
302 //----------------------------------------------------------------------------
303 void OGroupSectionUndo::implReInsert( )
304 {
305 	uno::Sequence< beans::PropertyValue > aArgs(2);
306 
307 	aArgs[0].Name = SID_GROUPHEADER_WITHOUT_UNDO == m_nSlot? PROPERTY_HEADERON : PROPERTY_FOOTERON;
308 	aArgs[0].Value <<= sal_True;
309 	aArgs[1].Name = PROPERTY_GROUP;
310 	aArgs[1].Value <<= m_aGroupHelper.getGroup();
311 	m_pController->executeChecked(m_nSlot,aArgs);
312 
313 	uno::Reference< report::XSection > xSection = m_pMemberFunction(&m_aGroupHelper);
314     lcl_insertElements(xSection,m_aControls);
315     lcl_setValues(xSection,m_aValues);
316     m_bInserted = true;
317 }
318 //----------------------------------------------------------------------------
319 void OGroupSectionUndo::implReRemove( )
320 {
321     if( m_eAction == Removed )
322         collectControls(m_pMemberFunction(&m_aGroupHelper));
323 
324 	uno::Sequence< beans::PropertyValue > aArgs(2);
325 
326 	aArgs[0].Name = SID_GROUPHEADER_WITHOUT_UNDO == m_nSlot? PROPERTY_HEADERON : PROPERTY_FOOTERON;
327 	aArgs[0].Value <<= sal_False;
328 	aArgs[1].Name = PROPERTY_GROUP;
329 	aArgs[1].Value <<= m_aGroupHelper.getGroup();
330 
331 	m_pController->executeChecked(m_nSlot,aArgs);
332     m_bInserted = false;
333 }
334 //----------------------------------------------------------------------------
335 TYPEINIT1( OGroupUndo,         OCommentUndoAction );
336 //----------------------------------------------------------------------------
337 OGroupUndo::OGroupUndo(OReportModel& _rMod
338 					   ,sal_uInt16 nCommentID
339 					   ,Action	_eAction
340 					   ,const uno::Reference< report::XGroup>& _xGroup
341 					   ,const uno::Reference< report::XReportDefinition >& _xReportDefinition)
342 : OCommentUndoAction(_rMod,nCommentID)
343 ,m_xGroup(_xGroup)
344 ,m_xReportDefinition(_xReportDefinition)
345 ,m_eAction(_eAction)
346 {
347 	m_nLastPosition = getPositionInIndexAccess(m_xReportDefinition->getGroups().get(),m_xGroup);
348 }
349 //----------------------------------------------------------------------------
350 void OGroupUndo::implReInsert( )
351 {
352 	try
353 	{
354 		m_xReportDefinition->getGroups()->insertByIndex(m_nLastPosition,uno::makeAny(m_xGroup));
355 	}
356 	catch(uno::Exception&)
357 	{
358 		OSL_ENSURE(0,"Exception catched while undoing remove group");
359 	}
360 }
361 //----------------------------------------------------------------------------
362 void OGroupUndo::implReRemove( )
363 {
364 	try
365 	{
366 		m_xReportDefinition->getGroups()->removeByIndex(m_nLastPosition);
367 	}
368 	catch(uno::Exception&)
369 	{
370 		OSL_ENSURE(0,"Exception catched while redoing remove group");
371 	}
372 }
373 //----------------------------------------------------------------------------
374 void OGroupUndo::Undo()
375 {
376 	switch ( m_eAction )
377 	{
378 	case Inserted:
379         implReRemove();
380         break;
381 
382 	case Removed:
383         implReInsert();
384         break;
385     }
386 
387 }
388 //----------------------------------------------------------------------------
389 void OGroupUndo::Redo()
390 {
391 	switch ( m_eAction )
392 	{
393 	case Inserted:
394         implReInsert();
395         break;
396 
397 	case Removed:
398         implReRemove();
399 		break;
400     }
401 }
402 //----------------------------------------------------------------------------
403 //============================================================================
404 } // rptui
405 //============================================================================
406 
407 
408