update dev300-m58
[ooovba.git] / svx / source / form / formcontrolling.cxx
blob69a2fb308ecce0f3f2335523531352a655243ac0
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: formcontrolling.cxx,v $
10 * $Revision: 1.13 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
34 #include "formcontrolling.hxx"
35 #include "fmurl.hxx"
36 #include <svx/svxids.hrc>
37 #include "fmprop.hrc"
38 #include "fmtools.hxx"
40 /** === begin UNO includes === **/
41 #include <com/sun/star/form/runtime/FormOperations.hpp>
42 #include <com/sun/star/form/runtime/FormFeature.hpp>
43 #include <com/sun/star/beans/XPropertySet.hpp>
44 #include <com/sun/star/sdb/XSQLErrorBroadcaster.hpp>
45 /** === end UNO includes === **/
47 #include <tools/diagnose_ex.h>
48 #include <comphelper/anytostring.hxx>
49 #include <cppuhelper/exc_hlp.hxx>
50 #include <osl/diagnose.h>
52 #include <functional>
53 #include <algorithm>
55 //........................................................................
56 namespace svx
58 //........................................................................
60 /** === begin UNO using === **/
61 using ::com::sun::star::uno::Reference;
62 using ::com::sun::star::lang::XMultiServiceFactory;
63 using ::com::sun::star::form::XFormController;
64 using ::com::sun::star::form::XForm;
65 using ::com::sun::star::form::runtime::FormOperations;
66 using ::com::sun::star::uno::Exception;
67 using ::com::sun::star::sdbc::XRowSet;
68 using ::com::sun::star::form::runtime::FeatureState;
69 using ::com::sun::star::uno::Any;
70 using ::com::sun::star::uno::Sequence;
71 using ::com::sun::star::beans::NamedValue;
72 using ::com::sun::star::uno::RuntimeException;
73 using ::com::sun::star::beans::XPropertySet;
74 using ::com::sun::star::uno::UNO_QUERY_THROW;
75 using ::com::sun::star::sdbc::SQLException;
76 using ::com::sun::star::sdb::XSQLErrorBroadcaster;
77 using ::com::sun::star::sdb::SQLErrorEvent;
78 using ::com::sun::star::lang::EventObject;
79 /** === end UNO using === **/
80 namespace FormFeature = ::com::sun::star::form::runtime::FormFeature;
82 //====================================================================
83 //= FeatureSlotTranslation
84 //====================================================================
85 namespace
87 struct FeatureDescription
89 ::rtl::OUString sURL; // the URL
90 sal_Int32 nSlotId; // the SFX-compatible slot ID
91 sal_Int16 nFormFeature; // the css.form.runtime.FormFeature ID
93 typedef ::std::vector< FeatureDescription > FeatureDescriptions;
95 //................................................................
96 const FeatureDescriptions& getFeatureDescriptions()
98 static FeatureDescriptions s_aFeatureDescriptions;
99 if ( s_aFeatureDescriptions.empty() )
101 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
102 if ( s_aFeatureDescriptions.empty() )
104 FeatureDescription aDescriptions[] = {
105 { FMURL_FORM_POSITION, SID_FM_RECORD_ABSOLUTE, FormFeature::MoveAbsolute },
106 { FMURL_FORM_RECORDCOUNT, SID_FM_RECORD_TOTAL, FormFeature::TotalRecords },
107 { FMURL_RECORD_MOVEFIRST, SID_FM_RECORD_FIRST, FormFeature::MoveToFirst },
108 { FMURL_RECORD_MOVEPREV, SID_FM_RECORD_PREV, FormFeature::MoveToPrevious },
109 { FMURL_RECORD_MOVENEXT, SID_FM_RECORD_NEXT, FormFeature::MoveToNext },
110 { FMURL_RECORD_MOVELAST, SID_FM_RECORD_LAST, FormFeature::MoveToLast },
111 { FMURL_RECORD_MOVETONEW, SID_FM_RECORD_NEW, FormFeature::MoveToInsertRow },
112 { FMURL_RECORD_SAVE, SID_FM_RECORD_SAVE, FormFeature::SaveRecordChanges },
113 { FMURL_RECORD_DELETE, SID_FM_RECORD_DELETE, FormFeature::DeleteRecord },
114 { FMURL_FORM_REFRESH, SID_FM_REFRESH, FormFeature::ReloadForm },
115 { FMURL_FORM_REFRESH_CURRENT_CONTROL,
116 SID_FM_REFRESH_FORM_CONTROL,FormFeature::RefreshCurrentControl },
117 { FMURL_RECORD_UNDO, SID_FM_RECORD_UNDO, FormFeature::UndoRecordChanges },
118 { FMURL_FORM_SORT_UP, SID_FM_SORTUP, FormFeature::SortAscending },
119 { FMURL_FORM_SORT_DOWN, SID_FM_SORTDOWN, FormFeature::SortDescending },
120 { FMURL_FORM_SORT, SID_FM_ORDERCRIT, FormFeature::InteractiveSort },
121 { FMURL_FORM_AUTO_FILTER, SID_FM_AUTOFILTER, FormFeature::AutoFilter },
122 { FMURL_FORM_FILTER, SID_FM_FILTERCRIT, FormFeature::InteractiveFilter },
123 { FMURL_FORM_APPLY_FILTER, SID_FM_FORM_FILTERED, FormFeature::ToggleApplyFilter },
124 { FMURL_FORM_REMOVE_FILTER, SID_FM_REMOVE_FILTER_SORT, FormFeature::RemoveFilterAndSort }
126 for ( size_t i=0; i<sizeof(aDescriptions)/sizeof(aDescriptions[0]); ++i )
127 s_aFeatureDescriptions.push_back( aDescriptions[i] );
130 return s_aFeatureDescriptions;
134 //--------------------------------------------------------------------
135 namespace
137 //................................................................
138 struct MatchFeatureDescriptionByURL : public ::std::unary_function< FeatureDescription, bool >
140 const ::rtl::OUString& m_rURL;
141 MatchFeatureDescriptionByURL( const ::rtl::OUString& _rURL ) :m_rURL( _rURL ) { }
143 bool operator()( const FeatureDescription& _compare )
145 return m_rURL == _compare.sURL;
149 //................................................................
150 struct MatchFeatureDescriptionBySlotId : public ::std::unary_function< FeatureDescription, bool >
152 sal_Int32 m_nSlotId;
153 MatchFeatureDescriptionBySlotId( sal_Int32 _nSlotId ) :m_nSlotId( _nSlotId ) { }
155 bool operator()( const FeatureDescription& _compare )
157 return m_nSlotId == _compare.nSlotId;
161 //................................................................
162 struct MatchFeatureDescriptionByFormFeature : public ::std::unary_function< FeatureDescription, bool >
164 sal_Int32 m_nFormFeature;
165 MatchFeatureDescriptionByFormFeature( sal_Int32 _nFormFeature ) :m_nFormFeature( _nFormFeature ) { }
167 bool operator()( const FeatureDescription& _compare )
169 return m_nFormFeature == _compare.nFormFeature;
173 //................................................................
174 struct FormFeatureToSlotId : public ::std::unary_function< sal_Int16, sal_Int32 >
176 sal_Int32 operator()( sal_Int16 _FormFeature )
178 return FeatureSlotTranslation::getSlotIdForFormFeature( _FormFeature );
183 //--------------------------------------------------------------------
184 sal_Int32 FeatureSlotTranslation::getControllerFeatureSlotIdForURL( const ::rtl::OUString& _rMainURL )
186 const FeatureDescriptions& rDescriptions( getFeatureDescriptions() );
187 FeatureDescriptions::const_iterator pos = ::std::find_if( rDescriptions.begin(), rDescriptions.end(), MatchFeatureDescriptionByURL( _rMainURL ) );
188 return ( pos != rDescriptions.end() ) ? pos->nSlotId : -1;
191 //--------------------------------------------------------------------
192 ::rtl::OUString FeatureSlotTranslation::getControllerFeatureURLForSlotId( sal_Int32 _nSlotId )
194 const FeatureDescriptions& rDescriptions( getFeatureDescriptions() );
195 FeatureDescriptions::const_iterator pos = ::std::find_if( rDescriptions.begin(), rDescriptions.end(), MatchFeatureDescriptionBySlotId( _nSlotId ) );
196 OSL_ENSURE( pos != rDescriptions.end(), "FeatureSlotTranslation::getControllerFeatureURLForSlotId: not found!" );
197 return ( pos != rDescriptions.end() ) ? pos->sURL : ::rtl::OUString();
200 //--------------------------------------------------------------------
201 sal_Bool FeatureSlotTranslation::isFeatureURL( const ::rtl::OUString& _rMainURL )
203 return ( _rMainURL.indexOf( FMURL_FORMSLOTS_PREFIX ) == 0 );
206 //--------------------------------------------------------------------
207 sal_Int16 FeatureSlotTranslation::getFormFeatureForSlotId( sal_Int32 _nSlotId )
209 const FeatureDescriptions& rDescriptions( getFeatureDescriptions() );
210 FeatureDescriptions::const_iterator pos = ::std::find_if( rDescriptions.begin(), rDescriptions.end(), MatchFeatureDescriptionBySlotId( _nSlotId ) );
211 OSL_ENSURE( pos != rDescriptions.end(), "FeatureSlotTranslation::getFormFeatureForSlotId: not found!" );
212 return ( pos != rDescriptions.end() ) ? pos->nFormFeature : -1;
215 //--------------------------------------------------------------------
216 sal_Int32 FeatureSlotTranslation::getSlotIdForFormFeature( sal_Int16 _nFormFeature )
218 const FeatureDescriptions& rDescriptions( getFeatureDescriptions() );
219 FeatureDescriptions::const_iterator pos = ::std::find_if( rDescriptions.begin(), rDescriptions.end(), MatchFeatureDescriptionByFormFeature( _nFormFeature ) );
220 OSL_ENSURE( pos != rDescriptions.end(), "FeatureSlotTranslation::getSlotIdForFormFeature: not found!" );
221 return ( pos != rDescriptions.end() ) ? pos->nSlotId : -1;
224 //====================================================================
225 //= ControllerFeatures
226 //====================================================================
227 //--------------------------------------------------------------------
228 ControllerFeatures::ControllerFeatures( const Reference< XMultiServiceFactory >& _rxORB, IControllerFeatureInvalidation* _pInvalidationCallback )
229 :m_aContext( _rxORB )
230 ,m_pInvalidationCallback( _pInvalidationCallback )
231 ,m_pImpl( NULL )
235 //--------------------------------------------------------------------
236 ControllerFeatures::ControllerFeatures( const Reference< XMultiServiceFactory >& _rxORB,
237 const Reference< XFormController >& _rxController, IControllerFeatureInvalidation* _pInvalidationCallback )
238 :m_aContext( _rxORB )
239 ,m_pInvalidationCallback( _pInvalidationCallback )
240 ,m_pImpl( NULL )
242 assign( _rxController );
245 //--------------------------------------------------------------------
246 ControllerFeatures::ControllerFeatures( const Reference< XMultiServiceFactory >& _rxORB,
247 const Reference< XForm >& _rxForm, IControllerFeatureInvalidation* _pInvalidationCallback )
248 :m_aContext( _rxORB )
249 ,m_pInvalidationCallback( _pInvalidationCallback )
250 ,m_pImpl( NULL )
252 assign( _rxForm );
255 //--------------------------------------------------------------------
256 void ControllerFeatures::assign( const Reference< XFormController >& _rxController )
258 dispose();
259 m_pImpl = new FormControllerHelper( m_aContext, _rxController, m_pInvalidationCallback );
260 m_pImpl->acquire();
263 //--------------------------------------------------------------------
264 void ControllerFeatures::assign( const Reference< XForm >& _rxForm )
266 dispose();
267 m_pImpl = new FormControllerHelper( m_aContext, _rxForm, m_pInvalidationCallback );
268 m_pImpl->acquire();
271 //--------------------------------------------------------------------
272 ControllerFeatures::~ControllerFeatures()
274 dispose();
277 //--------------------------------------------------------------------
278 void ControllerFeatures::dispose()
280 if ( m_pImpl )
282 m_pImpl->dispose();
283 m_pImpl->release();
284 m_pImpl = NULL;
288 //====================================================================
289 //= FormControllerHelper
290 //====================================================================
291 //--------------------------------------------------------------------
292 FormControllerHelper::FormControllerHelper( const ::comphelper::ComponentContext& _rContext,
293 const Reference< XFormController >& _rxController, IControllerFeatureInvalidation* _pInvalidationCallback )
294 :m_aContext( _rContext )
295 ,m_pInvalidationCallback( _pInvalidationCallback )
297 osl_incrementInterlockedCount( &m_refCount );
300 m_xFormOperations = FormOperations::createWithFormController( m_aContext.getUNOContext(), _rxController );
301 if ( m_xFormOperations.is() )
302 m_xFormOperations->setFeatureInvalidation( this );
304 // to prevent the controller from displaying any error messages which happen while we operate on it,
305 // we add ourself as XSQLErrorListener. By contract, a FormController displays errors if and only if
306 // no SQLErrorListeners are registered.
307 Reference< XSQLErrorBroadcaster > xErrorBroadcast( _rxController, UNO_QUERY_THROW );
308 xErrorBroadcast->addSQLErrorListener( this );
310 catch( const Exception& )
312 DBG_UNHANDLED_EXCEPTION();
314 osl_decrementInterlockedCount( &m_refCount );
317 //--------------------------------------------------------------------
318 FormControllerHelper::FormControllerHelper( const ::comphelper::ComponentContext& _rContext,
319 const Reference< XForm >& _rxForm, IControllerFeatureInvalidation* _pInvalidationCallback )
320 :m_aContext( _rContext )
321 ,m_pInvalidationCallback( _pInvalidationCallback )
323 osl_incrementInterlockedCount( &m_refCount );
326 m_xFormOperations = FormOperations::createWithForm( m_aContext.getUNOContext(), _rxForm );
327 if ( m_xFormOperations.is() )
328 m_xFormOperations->setFeatureInvalidation( this );
330 catch( const Exception& )
332 DBG_UNHANDLED_EXCEPTION();
334 osl_decrementInterlockedCount( &m_refCount );
337 //--------------------------------------------------------------------
338 FormControllerHelper::~FormControllerHelper( )
342 acquire();
343 dispose();
345 catch( const Exception& )
347 DBG_UNHANDLED_EXCEPTION();
351 //--------------------------------------------------------------------
352 void FormControllerHelper::dispose()
354 if ( m_xFormOperations.is() )
355 m_xFormOperations->dispose();
356 m_xFormOperations.clear();
359 //--------------------------------------------------------------------
360 sal_Bool FormControllerHelper::isEnabled( sal_Int32 _nSlotId ) const
362 if ( !m_xFormOperations.is() )
363 return sal_False;
364 return m_xFormOperations->isEnabled( FeatureSlotTranslation::getFormFeatureForSlotId( _nSlotId ) );
367 //--------------------------------------------------------------------
368 Reference< XRowSet > FormControllerHelper::getCursor() const
370 Reference< XRowSet > xCursor;
371 if ( m_xFormOperations.is() )
372 xCursor = m_xFormOperations->getCursor();
373 return xCursor;
376 //--------------------------------------------------------------------
377 void FormControllerHelper::getState( sal_Int32 _nSlotId, FeatureState& _rState ) const
379 if ( m_xFormOperations.is() )
380 _rState = m_xFormOperations->getState( FeatureSlotTranslation::getFormFeatureForSlotId( _nSlotId ) );
383 //--------------------------------------------------------------------
384 sal_Bool FormControllerHelper::commitCurrentControl( ) const
386 return impl_operateForm_nothrow( COMMIT_CONTROL );
389 //--------------------------------------------------------------------
390 sal_Bool FormControllerHelper::commitCurrentRecord() const
392 return impl_operateForm_nothrow( COMMIT_RECORD );
395 //--------------------------------------------------------------------
396 bool FormControllerHelper::moveRight( ) const
398 return impl_operateForm_nothrow( FormFeature::MoveToNext );
401 //--------------------------------------------------------------------
402 bool FormControllerHelper::moveLeft( ) const
404 return impl_operateForm_nothrow( FormFeature::MoveToPrevious );
407 //--------------------------------------------------------------------
408 void FormControllerHelper::execute( sal_Int32 _nSlotId, const ::rtl::OUString& _rParamName, const Any& _rParamValue ) const
410 Sequence< NamedValue > aArguments(1);
411 aArguments[0].Name = _rParamName;
412 aArguments[0].Value = _rParamValue;
414 impl_operateForm_nothrow( EXECUTE_ARGS, FeatureSlotTranslation::getFormFeatureForSlotId( _nSlotId ), aArguments );
417 //--------------------------------------------------------------------
418 bool FormControllerHelper::impl_operateForm_nothrow( const FormOperation _eWhat, const sal_Int16 _nFeature,
419 const Sequence< NamedValue >& _rArguments ) const
421 if ( !m_xFormOperations.is() )
422 return false;
424 Any aError;
425 bool bSuccess = false;
426 const_cast< FormControllerHelper* >( this )->m_aOperationError.clear();
429 switch ( _eWhat )
431 case COMMIT_CONTROL:
432 bSuccess = m_xFormOperations->commitCurrentControl();
433 break;
435 case COMMIT_RECORD:
437 sal_Bool bDummy( sal_False );
438 bSuccess = m_xFormOperations->commitCurrentRecord( bDummy );
440 break;
442 case EXECUTE:
443 m_xFormOperations->execute( _nFeature );
444 bSuccess = true;
445 break;
447 case EXECUTE_ARGS:
448 m_xFormOperations->executeWithArguments( _nFeature, _rArguments );
449 bSuccess = true;
450 break;
453 catch ( const SQLException& )
455 aError = ::cppu::getCaughtException();
457 catch( const Exception& )
459 SQLException aFallbackError;
460 aFallbackError.Message = ::comphelper::anyToString( ::cppu::getCaughtException() );
461 aError <<= aFallbackError;
464 if ( bSuccess )
465 return true;
467 // display the error. Prefer the one reported in errorOccured over the one caught.
468 if ( m_aOperationError.hasValue() )
469 displayException( m_aOperationError );
470 else if ( aError.hasValue() )
471 displayException( aError );
472 else
473 OSL_ENSURE( false, "FormControllerHelper::impl_operateForm_nothrow: no success, but no error?" );
475 return false;
478 //--------------------------------------------------------------------
479 void FormControllerHelper::execute( sal_Int32 _nSlotId ) const
481 impl_operateForm_nothrow( EXECUTE, FeatureSlotTranslation::getFormFeatureForSlotId( _nSlotId ),
482 Sequence< NamedValue >() );
485 //--------------------------------------------------------------------
486 void SAL_CALL FormControllerHelper::invalidateFeatures( const Sequence< ::sal_Int16 >& _Features ) throw (RuntimeException)
488 if ( !m_pInvalidationCallback )
489 // nobody's interested in ...
490 return;
492 ::std::vector< sal_Int32 > aFeatures( _Features.getLength() );
493 ::std::transform(
494 _Features.getConstArray(),
495 _Features.getConstArray() + _Features.getLength(),
496 aFeatures.begin(),
497 FormFeatureToSlotId()
500 m_pInvalidationCallback->invalidateFeatures( aFeatures );
503 //--------------------------------------------------------------------
504 void SAL_CALL FormControllerHelper::invalidateAllFeatures() throw (RuntimeException)
506 if ( !m_pInvalidationCallback )
507 // nobody's interested in ...
508 return;
510 // actually, it's a little bit more than the supported features,
511 // but on the medium term, we are to support everything listed
512 // here
513 ::std::vector< sal_Int32 > aSupportedFeatures;
514 sal_Int32 pSupportedFeatures[] =
516 SID_FM_RECORD_FIRST,
517 SID_FM_RECORD_NEXT,
518 SID_FM_RECORD_PREV,
519 SID_FM_RECORD_LAST,
520 SID_FM_RECORD_NEW,
521 SID_FM_RECORD_DELETE,
522 SID_FM_RECORD_ABSOLUTE,
523 SID_FM_RECORD_TOTAL,
524 SID_FM_RECORD_SAVE,
525 SID_FM_RECORD_UNDO,
526 SID_FM_REMOVE_FILTER_SORT,
527 SID_FM_SORTUP,
528 SID_FM_SORTDOWN,
529 SID_FM_ORDERCRIT,
530 SID_FM_AUTOFILTER,
531 SID_FM_FILTERCRIT,
532 SID_FM_FORM_FILTERED,
533 SID_FM_REFRESH,
534 SID_FM_REFRESH_FORM_CONTROL,
535 SID_FM_SEARCH,
536 SID_FM_FILTER_START,
537 SID_FM_VIEW_AS_GRID
539 sal_Int32 nFeatureCount = sizeof( pSupportedFeatures ) / sizeof( pSupportedFeatures[ 0 ] );
540 aSupportedFeatures.resize( nFeatureCount );
541 ::std::copy( pSupportedFeatures, pSupportedFeatures + nFeatureCount, aSupportedFeatures.begin() );
543 m_pInvalidationCallback->invalidateFeatures( aSupportedFeatures );
546 //--------------------------------------------------------------------
547 void SAL_CALL FormControllerHelper::errorOccured( const SQLErrorEvent& _Event ) throw (RuntimeException)
549 OSL_ENSURE( !m_aOperationError.hasValue(), "FormControllerHelper::errorOccured: two errors during one operation?" );
550 m_aOperationError = _Event.Reason;
553 //--------------------------------------------------------------------
554 void SAL_CALL FormControllerHelper::disposing( const EventObject& /*_Source*/ ) throw (RuntimeException)
556 // not interested in
559 //--------------------------------------------------------------------
560 sal_Bool FormControllerHelper::isInsertionRow() const
562 sal_Bool bIs = sal_False;
563 if ( m_xFormOperations.is() )
564 bIs = m_xFormOperations->isInsertionRow();
565 return bIs;
568 //--------------------------------------------------------------------
569 sal_Bool FormControllerHelper::isModifiedRow() const
571 sal_Bool bIs = sal_False;
572 if ( m_xFormOperations.is() )
573 bIs = m_xFormOperations->isModifiedRow();
574 return bIs;
576 //--------------------------------------------------------------------
577 bool FormControllerHelper::canDoFormFilter() const
579 if ( !m_xFormOperations.is() )
580 return false;
582 bool bCanDo = false;
585 Reference< XPropertySet > xCursorProperties( m_xFormOperations->getCursor(), UNO_QUERY_THROW );
587 bool bEscapeProcessing( false );
588 OSL_VERIFY( xCursorProperties->getPropertyValue( FM_PROP_ESCAPE_PROCESSING ) >>= bEscapeProcessing );
590 ::rtl::OUString sActiveCommand;
591 OSL_VERIFY( xCursorProperties->getPropertyValue( FM_PROP_ACTIVECOMMAND ) >>= sActiveCommand );
593 bool bInsertOnlyForm( false );
594 OSL_VERIFY( xCursorProperties->getPropertyValue( FM_PROP_INSERTONLY ) >>= bInsertOnlyForm );
596 bCanDo = bEscapeProcessing && ( sActiveCommand.getLength() > 0 ) && !bInsertOnlyForm;
598 catch( const Exception& )
600 DBG_UNHANDLED_EXCEPTION();
602 return bCanDo;
605 //........................................................................
606 } // namespace svx
607 //........................................................................