1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: formcontrolling.cxx,v $
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"
36 #include <svx/svxids.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>
55 //........................................................................
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 //====================================================================
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 //--------------------------------------------------------------------
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 >
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
)
235 //--------------------------------------------------------------------
236 ControllerFeatures::ControllerFeatures( const Reference
< XMultiServiceFactory
>& _rxORB
,
237 const Reference
< XFormController
>& _rxController
, IControllerFeatureInvalidation
* _pInvalidationCallback
)
238 :m_aContext( _rxORB
)
239 ,m_pInvalidationCallback( _pInvalidationCallback
)
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
)
255 //--------------------------------------------------------------------
256 void ControllerFeatures::assign( const Reference
< XFormController
>& _rxController
)
259 m_pImpl
= new FormControllerHelper( m_aContext
, _rxController
, m_pInvalidationCallback
);
263 //--------------------------------------------------------------------
264 void ControllerFeatures::assign( const Reference
< XForm
>& _rxForm
)
267 m_pImpl
= new FormControllerHelper( m_aContext
, _rxForm
, m_pInvalidationCallback
);
271 //--------------------------------------------------------------------
272 ControllerFeatures::~ControllerFeatures()
277 //--------------------------------------------------------------------
278 void ControllerFeatures::dispose()
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( )
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() )
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();
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() )
425 bool bSuccess
= false;
426 const_cast< FormControllerHelper
* >( this )->m_aOperationError
.clear();
432 bSuccess
= m_xFormOperations
->commitCurrentControl();
437 sal_Bool
bDummy( sal_False
);
438 bSuccess
= m_xFormOperations
->commitCurrentRecord( bDummy
);
443 m_xFormOperations
->execute( _nFeature
);
448 m_xFormOperations
->executeWithArguments( _nFeature
, _rArguments
);
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
;
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
);
473 OSL_ENSURE( false, "FormControllerHelper::impl_operateForm_nothrow: no success, but no error?" );
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 ...
492 ::std::vector
< sal_Int32
> aFeatures( _Features
.getLength() );
494 _Features
.getConstArray(),
495 _Features
.getConstArray() + _Features
.getLength(),
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 ...
510 // actually, it's a little bit more than the supported features,
511 // but on the medium term, we are to support everything listed
513 ::std::vector
< sal_Int32
> aSupportedFeatures
;
514 sal_Int32 pSupportedFeatures
[] =
521 SID_FM_RECORD_DELETE
,
522 SID_FM_RECORD_ABSOLUTE
,
526 SID_FM_REMOVE_FILTER_SORT
,
532 SID_FM_FORM_FILTERED
,
534 SID_FM_REFRESH_FORM_CONTROL
,
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
)
559 //--------------------------------------------------------------------
560 sal_Bool
FormControllerHelper::isInsertionRow() const
562 sal_Bool bIs
= sal_False
;
563 if ( m_xFormOperations
.is() )
564 bIs
= m_xFormOperations
->isInsertionRow();
568 //--------------------------------------------------------------------
569 sal_Bool
FormControllerHelper::isModifiedRow() const
571 sal_Bool bIs
= sal_False
;
572 if ( m_xFormOperations
.is() )
573 bIs
= m_xFormOperations
->isModifiedRow();
576 //--------------------------------------------------------------------
577 bool FormControllerHelper::canDoFormFilter() const
579 if ( !m_xFormOperations
.is() )
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();
605 //........................................................................
607 //........................................................................