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