1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "fmcontrolbordermanager.hxx"
22 #include "fmcontrollayout.hxx"
23 #include "formcontroller.hxx"
24 #include "formfeaturedispatcher.hxx"
25 #include "fmdocumentclassification.hxx"
26 #include "formcontrolling.hxx"
28 #include "svx/dialmgr.hxx"
29 #include "svx/fmresids.hrc"
30 #include "fmservs.hxx"
31 #include "svx/fmtools.hxx"
34 #include <com/sun/star/awt/FocusChangeReason.hpp>
35 #include <com/sun/star/awt/XCheckBox.hpp>
36 #include <com/sun/star/awt/XComboBox.hpp>
37 #include <com/sun/star/awt/XListBox.hpp>
38 #include <com/sun/star/awt/XVclWindowPeer.hpp>
39 #include <com/sun/star/awt/TabController.hpp>
40 #include <com/sun/star/beans/NamedValue.hpp>
41 #include <com/sun/star/beans/PropertyAttribute.hpp>
42 #include <com/sun/star/container/XIdentifierReplace.hpp>
43 #include <com/sun/star/form/TabulatorCycle.hpp>
44 #include <com/sun/star/form/validation/XValidatableFormComponent.hpp>
45 #include <com/sun/star/form/XBoundComponent.hpp>
46 #include <com/sun/star/form/XBoundControl.hpp>
47 #include <com/sun/star/form/XGridControl.hpp>
48 #include <com/sun/star/form/XLoadable.hpp>
49 #include <com/sun/star/form/XReset.hpp>
50 #include <com/sun/star/form/control/FilterControl.hpp>
51 #include <com/sun/star/frame/XController.hpp>
52 #include <com/sun/star/sdb/ParametersRequest.hpp>
53 #include <com/sun/star/sdb/RowChangeAction.hpp>
54 #include <com/sun/star/sdb/XInteractionSupplyParameters.hpp>
55 #include <com/sun/star/sdbc/ColumnValue.hpp>
56 #include <com/sun/star/sdbc/DataType.hpp>
57 #include <com/sun/star/task/InteractionHandler.hpp>
58 #include <com/sun/star/util/XURLTransformer.hpp>
59 #include <com/sun/star/form/runtime/FormOperations.hpp>
60 #include <com/sun/star/form/runtime/FormFeature.hpp>
61 #include <com/sun/star/container/XContainer.hpp>
62 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
63 #include <com/sun/star/util/NumberFormatter.hpp>
64 #include <com/sun/star/sdb/SQLContext.hpp>
65 #include <com/sun/star/sdb/XColumn.hpp>
67 #include <comphelper/enumhelper.hxx>
68 #include <comphelper/interaction.hxx>
69 #include <comphelper/namedvaluecollection.hxx>
70 #include <comphelper/processfactory.hxx>
71 #include <comphelper/propagg.hxx>
72 #include <comphelper/property.hxx>
73 #include <comphelper/sequence.hxx>
74 #include <comphelper/flagguard.hxx>
75 #include <cppuhelper/queryinterface.hxx>
76 #include <cppuhelper/supportsservice.hxx>
77 #include <cppuhelper/typeprovider.hxx>
78 #include <connectivity/IParseContext.hxx>
79 #include <connectivity/dbtools.hxx>
80 #include <connectivity/sqlparse.hxx>
81 #include <toolkit/controls/unocontrol.hxx>
82 #include <toolkit/helper/vclunohelper.hxx>
83 #include <tools/debug.hxx>
84 #include <tools/diagnose_ex.h>
85 #include <vcl/msgbox.hxx>
86 #include <vcl/svapp.hxx>
87 #include <vcl/settings.hxx>
88 #include <osl/mutex.hxx>
92 #include <o3tl/compat_functional.hxx>
94 using namespace ::com::sun::star
;
95 using namespace ::comphelper
;
96 using namespace ::connectivity
;
97 using namespace ::dbtools
;
100 ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> SAL_CALL
101 FormController_NewInstance_Impl( const ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XMultiServiceFactory
> & _rxORB
)
102 throw (css::uno::Exception
)
104 return *( new ::svxform::FormController( comphelper::getComponentContext(_rxORB
) ) );
110 using ::com::sun::star::sdb::XColumn
;
111 using ::com::sun::star::awt::XControl
;
112 using ::com::sun::star::awt::XTabController
;
113 using ::com::sun::star::awt::TabController
;
114 using ::com::sun::star::awt::XToolkit
;
115 using ::com::sun::star::awt::XWindowPeer
;
116 using ::com::sun::star::form::XGrid
;
117 using ::com::sun::star::beans::XPropertySet
;
118 using ::com::sun::star::uno::UNO_SET_THROW
;
119 using ::com::sun::star::uno::UNO_QUERY_THROW
;
120 using ::com::sun::star::container::XIndexAccess
;
121 using ::com::sun::star::uno::Exception
;
122 using ::com::sun::star::uno::XInterface
;
123 using ::com::sun::star::uno::UNO_QUERY
;
124 using ::com::sun::star::uno::Sequence
;
125 using ::com::sun::star::uno::Reference
;
126 using ::com::sun::star::beans::XPropertySetInfo
;
127 using ::com::sun::star::beans::PropertyValue
;
128 using ::com::sun::star::uno::RuntimeException
;
129 using ::com::sun::star::lang::IndexOutOfBoundsException
;
130 using ::com::sun::star::sdb::XInteractionSupplyParameters
;
131 using ::com::sun::star::awt::XTextComponent
;
132 using ::com::sun::star::awt::XTextListener
;
133 using ::com::sun::star::uno::Any
;
134 using ::com::sun::star::frame::XDispatch
;
135 using ::com::sun::star::lang::XMultiServiceFactory
;
136 using ::com::sun::star::uno::XAggregation
;
137 using ::com::sun::star::uno::Type
;
138 using ::com::sun::star::lang::IllegalArgumentException
;
139 using ::com::sun::star::sdbc::XConnection
;
140 using ::com::sun::star::sdbc::XRowSet
;
141 using ::com::sun::star::sdbc::XDatabaseMetaData
;
142 using ::com::sun::star::util::XNumberFormatsSupplier
;
143 using ::com::sun::star::util::NumberFormatter
;
144 using ::com::sun::star::util::XNumberFormatter
;
145 using ::com::sun::star::sdbcx::XColumnsSupplier
;
146 using ::com::sun::star::container::XNameAccess
;
147 using ::com::sun::star::lang::EventObject
;
148 using ::com::sun::star::beans::Property
;
149 using ::com::sun::star::container::XEnumeration
;
150 using ::com::sun::star::form::XFormComponent
;
151 using ::com::sun::star::form::runtime::XFormOperations
;
152 using ::com::sun::star::form::runtime::FilterEvent
;
153 using ::com::sun::star::form::runtime::XFilterControllerListener
;
154 using ::com::sun::star::awt::XControlContainer
;
155 using ::com::sun::star::container::XIdentifierReplace
;
156 using ::com::sun::star::lang::WrappedTargetException
;
157 using ::com::sun::star::form::XFormControllerListener
;
158 using ::com::sun::star::awt::XWindow
;
159 using ::com::sun::star::sdbc::XResultSet
;
160 using ::com::sun::star::awt::XControlModel
;
161 using ::com::sun::star::awt::XTabControllerModel
;
162 using ::com::sun::star::beans::PropertyChangeEvent
;
163 using ::com::sun::star::form::validation::XValidatableFormComponent
;
164 using ::com::sun::star::form::XLoadable
;
165 using ::com::sun::star::script::XEventAttacherManager
;
166 using ::com::sun::star::form::XBoundControl
;
167 using ::com::sun::star::beans::XPropertyChangeListener
;
168 using ::com::sun::star::awt::TextEvent
;
169 using ::com::sun::star::form::XBoundComponent
;
170 using ::com::sun::star::awt::XCheckBox
;
171 using ::com::sun::star::awt::XComboBox
;
172 using ::com::sun::star::awt::XListBox
;
173 using ::com::sun::star::awt::ItemEvent
;
174 using ::com::sun::star::util::XModifyListener
;
175 using ::com::sun::star::form::XReset
;
176 using ::com::sun::star::frame::XDispatchProviderInterception
;
177 using ::com::sun::star::form::XGridControl
;
178 using ::com::sun::star::awt::XVclWindowPeer
;
179 using ::com::sun::star::form::validation::XValidator
;
180 using ::com::sun::star::awt::FocusEvent
;
181 using ::com::sun::star::sdb::SQLContext
;
182 using ::com::sun::star::container::XChild
;
183 using ::com::sun::star::form::TabulatorCycle_RECORDS
;
184 using ::com::sun::star::container::ContainerEvent
;
185 using ::com::sun::star::lang::DisposedException
;
186 using ::com::sun::star::lang::Locale
;
187 using ::com::sun::star::beans::NamedValue
;
188 using ::com::sun::star::lang::NoSupportException
;
189 using ::com::sun::star::sdb::RowChangeEvent
;
190 using ::com::sun::star::frame::XStatusListener
;
191 using ::com::sun::star::frame::XDispatchProviderInterceptor
;
192 using ::com::sun::star::sdb::SQLErrorEvent
;
193 using ::com::sun::star::form::DatabaseParameterEvent
;
194 using ::com::sun::star::sdb::ParametersRequest
;
195 using ::com::sun::star::task::XInteractionRequest
;
196 using ::com::sun::star::util::URL
;
197 using ::com::sun::star::frame::FeatureStateEvent
;
198 using ::com::sun::star::form::runtime::XFormControllerContext
;
199 using ::com::sun::star::task::InteractionHandler
;
200 using ::com::sun::star::task::XInteractionHandler
;
201 using ::com::sun::star::form::runtime::FormOperations
;
202 using ::com::sun::star::container::XContainer
;
203 using ::com::sun::star::sdbc::SQLWarning
;
205 namespace ColumnValue
= ::com::sun::star::sdbc::ColumnValue
;
206 namespace PropertyAttribute
= ::com::sun::star::beans::PropertyAttribute
;
207 namespace FocusChangeReason
= ::com::sun::star::awt::FocusChangeReason
;
208 namespace RowChangeAction
= ::com::sun::star::sdb::RowChangeAction
;
209 namespace FormFeature
= ::com::sun::star::form::runtime::FormFeature
;
210 namespace DataType
= ::com::sun::star::sdbc::DataType
;
214 // information about the column itself
215 Reference
< XColumn
> xColumn
;
221 // information about the control(s) bound to this column
223 /// the first control which is bound to the given column, and which requires input
224 Reference
< XControl
> xFirstControlWithInputRequired
;
225 /** the first grid control which contains a column which is bound to the given database column, and requires
228 Reference
< XGrid
> xFirstGridWithInputRequiredColumn
;
229 /** if xFirstControlWithInputRequired is a grid control, then nRequiredGridColumn specifies the position
230 of the grid column which is actually bound
232 sal_Int32 nRequiredGridColumn
;
236 ,nNullable( ColumnValue::NULLABLE_UNKNOWN
)
237 ,bAutoIncrement( false )
240 ,xFirstControlWithInputRequired()
241 ,xFirstGridWithInputRequiredColumn()
242 ,nRequiredGridColumn( -1 )
247 class ColumnInfoCache
250 ColumnInfoCache( const Reference
< XColumnsSupplier
>& _rxColSupplier
);
252 size_t getColumnCount() const { return m_aColumns
.size(); }
253 const ColumnInfo
& getColumnInfo( size_t _pos
);
255 bool controlsInitialized() const { return m_bControlsInitialized
; }
256 void initializeControls( const Sequence
< Reference
< XControl
> >& _rControls
);
257 void deinitializeControls();
260 typedef ::std::vector
< ColumnInfo
> ColumnInfos
;
261 ColumnInfos m_aColumns
;
262 bool m_bControlsInitialized
;
266 ColumnInfoCache::ColumnInfoCache( const Reference
< XColumnsSupplier
>& _rxColSupplier
)
268 ,m_bControlsInitialized( false )
274 Reference
< XIndexAccess
> xColumns( _rxColSupplier
->getColumns(), UNO_QUERY_THROW
);
275 sal_Int32 nColumnCount
= xColumns
->getCount();
276 m_aColumns
.reserve( nColumnCount
);
278 Reference
< XPropertySet
> xColumnProps
;
279 for ( sal_Int32 i
= 0; i
< nColumnCount
; ++i
)
282 aColInfo
.xColumn
.set( xColumns
->getByIndex(i
), UNO_QUERY_THROW
);
284 xColumnProps
.set( aColInfo
.xColumn
, UNO_QUERY_THROW
);
285 OSL_VERIFY( xColumnProps
->getPropertyValue( FM_PROP_ISNULLABLE
) >>= aColInfo
.nNullable
);
286 OSL_VERIFY( xColumnProps
->getPropertyValue( FM_PROP_AUTOINCREMENT
) >>= aColInfo
.bAutoIncrement
);
287 OSL_VERIFY( xColumnProps
->getPropertyValue( FM_PROP_NAME
) >>= aColInfo
.sName
);
288 OSL_VERIFY( xColumnProps
->getPropertyValue( FM_PROP_ISREADONLY
) >>= aColInfo
.bReadOnly
);
290 m_aColumns
.push_back( aColInfo
);
293 catch( const Exception
& )
295 DBG_UNHANDLED_EXCEPTION();
302 bool lcl_isBoundTo( const Reference
< XPropertySet
>& _rxControlModel
, const Reference
< XInterface
>& _rxNormDBField
)
304 Reference
< XInterface
> xNormBoundField( _rxControlModel
->getPropertyValue( FM_PROP_BOUNDFIELD
), UNO_QUERY
);
305 return ( xNormBoundField
== _rxNormDBField
);
308 bool lcl_isInputRequired( const Reference
< XPropertySet
>& _rxControlModel
)
310 bool bInputRequired
= true;
311 OSL_VERIFY( _rxControlModel
->getPropertyValue( FM_PROP_INPUT_REQUIRED
) >>= bInputRequired
);
312 return bInputRequired
;
315 void lcl_resetColumnControlInfo( ColumnInfo
& _rColInfo
)
317 _rColInfo
.xFirstControlWithInputRequired
.clear();
318 _rColInfo
.xFirstGridWithInputRequiredColumn
.clear();
319 _rColInfo
.nRequiredGridColumn
= -1;
324 void ColumnInfoCache::deinitializeControls()
326 for ( ColumnInfos::iterator col
= m_aColumns
.begin();
327 col
!= m_aColumns
.end();
331 lcl_resetColumnControlInfo( *col
);
336 void ColumnInfoCache::initializeControls( const Sequence
< Reference
< XControl
> >& _rControls
)
340 // for every of our known columns, find the controls which are bound to this column
341 for ( ColumnInfos::iterator col
= m_aColumns
.begin();
342 col
!= m_aColumns
.end();
346 OSL_ENSURE( !col
->xFirstControlWithInputRequired
.is() && !col
->xFirstGridWithInputRequiredColumn
.is()
347 && ( col
->nRequiredGridColumn
== -1 ), "ColumnInfoCache::initializeControls: called me twice?" );
349 lcl_resetColumnControlInfo( *col
);
351 Reference
< XInterface
> xNormColumn( col
->xColumn
, UNO_QUERY_THROW
);
353 const Reference
< XControl
>* pControl( _rControls
.getConstArray() );
354 const Reference
< XControl
>* pControlEnd( pControl
+ _rControls
.getLength() );
355 for ( ; pControl
!= pControlEnd
; ++pControl
)
357 if ( !pControl
->is() )
360 Reference
< XPropertySet
> xModel( (*pControl
)->getModel(), UNO_QUERY_THROW
);
361 Reference
< XPropertySetInfo
> xModelPSI( xModel
->getPropertySetInfo(), UNO_SET_THROW
);
363 // special handling for grid controls
364 Reference
< XGrid
> xGrid( *pControl
, UNO_QUERY
);
367 Reference
< XIndexAccess
> xGridColAccess( xModel
, UNO_QUERY_THROW
);
368 sal_Int32 gridColCount
= xGridColAccess
->getCount();
369 sal_Int32 gridCol
= 0;
370 for ( gridCol
= 0; gridCol
< gridColCount
; ++gridCol
)
372 Reference
< XPropertySet
> xGridColumnModel( xGridColAccess
->getByIndex( gridCol
), UNO_QUERY_THROW
);
374 if ( !lcl_isBoundTo( xGridColumnModel
, xNormColumn
)
375 || !lcl_isInputRequired( xGridColumnModel
)
377 continue; // with next grid column
382 if ( gridCol
< gridColCount
)
384 // found a grid column which is bound to the given
385 col
->xFirstGridWithInputRequiredColumn
= xGrid
;
386 col
->nRequiredGridColumn
= gridCol
;
390 continue; // with next control
393 if ( !xModelPSI
->hasPropertyByName( FM_PROP_BOUNDFIELD
)
394 || !lcl_isBoundTo( xModel
, xNormColumn
)
395 || !lcl_isInputRequired( xModel
)
397 continue; // with next control
402 if ( pControl
== pControlEnd
)
403 // did not find a control which is bound to this particular column, and for which the input is required
404 continue; // with next DB column
406 col
->xFirstControlWithInputRequired
= *pControl
;
409 catch( const Exception
& )
411 DBG_UNHANDLED_EXCEPTION();
414 m_bControlsInitialized
= true;
418 const ColumnInfo
& ColumnInfoCache::getColumnInfo( size_t _pos
)
420 if ( _pos
>= m_aColumns
.size() )
421 throw IndexOutOfBoundsException();
423 return m_aColumns
[ _pos
];
426 class OParameterContinuation
: public OInteraction
< XInteractionSupplyParameters
>
428 Sequence
< PropertyValue
> m_aValues
;
431 OParameterContinuation() { }
433 Sequence
< PropertyValue
> getValues() const { return m_aValues
; }
435 // XInteractionSupplyParameters
436 virtual void SAL_CALL
setParameters( const Sequence
< PropertyValue
>& _rValues
) throw(RuntimeException
, std::exception
) SAL_OVERRIDE
;
440 void SAL_CALL
OParameterContinuation::setParameters( const Sequence
< PropertyValue
>& _rValues
) throw(RuntimeException
, std::exception
)
442 m_aValues
= _rValues
;
451 Reference
< XPropertySet
> xField
;
452 Reference
< XTextComponent
> xText
;
454 FmFieldInfo(const Reference
< XPropertySet
>& _xField
, const Reference
< XTextComponent
>& _xText
)
457 {xField
->getPropertyValue(FM_PROP_NAME
) >>= aFieldName
;}
460 class FmXAutoControl
: public UnoControl
464 FmXAutoControl() :UnoControl()
468 virtual OUString
GetComponentServiceName() SAL_OVERRIDE
{return OUString("Edit");}
469 virtual void SAL_CALL
createPeer( const Reference
< XToolkit
> & rxToolkit
, const Reference
< XWindowPeer
> & rParentPeer
) throw( RuntimeException
, std::exception
) SAL_OVERRIDE
;
472 virtual void ImplSetPeerProperty( const OUString
& rPropName
, const Any
& rVal
) SAL_OVERRIDE
;
476 void FmXAutoControl::createPeer( const Reference
< XToolkit
> & rxToolkit
, const Reference
< XWindowPeer
> & rParentPeer
) throw( RuntimeException
, std::exception
)
478 UnoControl::createPeer( rxToolkit
, rParentPeer
);
480 Reference
< XTextComponent
> xText(getPeer() , UNO_QUERY
);
483 xText
->setText(SVX_RESSTR(RID_STR_AUTOFIELD
));
484 xText
->setEditable(sal_False
);
489 void FmXAutoControl::ImplSetPeerProperty( const OUString
& rPropName
, const Any
& rVal
)
491 // these properties are ignored
492 if (rPropName
== FM_PROP_TEXT
)
495 UnoControl::ImplSetPeerProperty( rPropName
, rVal
);
499 IMPL_LINK_NOARG_TYPED( FormController
, OnActivateTabOrder
, Idle
*, void )
505 struct UpdateAllListeners
: public ::std::unary_function
< Reference
< XDispatch
>, bool >
507 bool operator()( const Reference
< XDispatch
>& _rxDispatcher
) const
509 static_cast< svx::OSingleFeatureDispatcher
* >( _rxDispatcher
.get() )->updateAllListeners();
510 // the return is a dummy only so we can use this struct in a o3tl::compose1 call
515 IMPL_LINK_NOARG_TYPED( FormController
, OnInvalidateFeatures
, Timer
*, void )
517 ::osl::MutexGuard
aGuard( m_aMutex
);
518 for ( ::std::set
< sal_Int16
>::const_iterator aLoop
= m_aInvalidFeatures
.begin();
519 aLoop
!= m_aInvalidFeatures
.end();
523 DispatcherContainer::const_iterator aDispatcherPos
= m_aFeatureDispatchers
.find( *aLoop
);
524 if ( aDispatcherPos
!= m_aFeatureDispatchers
.end() )
526 // TODO: for the real and actual listener notifications, we should release
528 UpdateAllListeners( )( aDispatcherPos
->second
);
533 FormController::FormController(const Reference
< css::uno::XComponentContext
> & _rxORB
)
534 :FormController_BASE( m_aMutex
)
535 ,OPropertySetHelper( FormController_BASE::rBHelper
)
536 ,OSQLParserClient( _rxORB
)
537 ,m_xComponentContext( _rxORB
)
538 ,m_aActivateListeners(m_aMutex
)
539 ,m_aModifyListeners(m_aMutex
)
540 ,m_aErrorListeners(m_aMutex
)
541 ,m_aDeleteListeners(m_aMutex
)
542 ,m_aRowSetApproveListeners(m_aMutex
)
543 ,m_aParameterListeners(m_aMutex
)
544 ,m_aFilterListeners(m_aMutex
)
545 ,m_pControlBorderManager( new ::svxform::ControlBorderManager
)
547 ,m_aMode( OUString( "DataMode" ) )
548 ,m_aLoadEvent( LINK( this, FormController
, OnLoad
) )
549 ,m_aToggleEvent( LINK( this, FormController
, OnToggleAutoFields
) )
550 ,m_aActivationEvent( LINK( this, FormController
, OnActivated
) )
551 ,m_aDeactivationEvent( LINK( this, FormController
, OnDeactivated
) )
552 ,m_nCurrentFilterPosition(-1)
553 ,m_bCurrentRecordModified(false)
554 ,m_bCurrentRecordNew(false)
556 ,m_bDBConnection(false)
560 ,m_bCommitLock(false)
562 ,m_bControlsSorted(false)
564 ,m_bAttachEvents(true)
565 ,m_bDetachEvents(true)
566 ,m_bAttemptedHandlerCreation( false )
567 ,m_bSuspendFilterTextListening( false )
570 osl_atomic_increment(&m_refCount
);
572 m_xTabController
= TabController::create( m_xComponentContext
);
573 m_xAggregate
= Reference
< XAggregation
>( m_xTabController
, UNO_QUERY_THROW
);
574 m_xAggregate
->setDelegator( *this );
576 osl_atomic_decrement(&m_refCount
);
578 m_aTabActivationIdle
.SetPriority( SchedulerPriority::LOWEST
);
579 m_aTabActivationIdle
.SetIdleHdl( LINK( this, FormController
, OnActivateTabOrder
) );
581 m_aFeatureInvalidationTimer
.SetTimeout( 200 );
582 m_aFeatureInvalidationTimer
.SetTimeoutHdl( LINK( this, FormController
, OnInvalidateFeatures
) );
586 FormController::~FormController()
589 ::osl::MutexGuard
aGuard( m_aMutex
);
591 m_aLoadEvent
.CancelPendingCall();
592 m_aToggleEvent
.CancelPendingCall();
593 m_aActivationEvent
.CancelPendingCall();
594 m_aDeactivationEvent
.CancelPendingCall();
596 if ( m_aTabActivationIdle
.IsActive() )
597 m_aTabActivationIdle
.Stop();
600 if ( m_aFeatureInvalidationTimer
.IsActive() )
601 m_aFeatureInvalidationTimer
.Stop();
603 disposeAllFeaturesAndDispatchers();
605 if ( m_xFormOperations
.is() )
606 m_xFormOperations
->dispose();
607 m_xFormOperations
.clear();
609 // Freigeben der Aggregation
610 if ( m_xAggregate
.is() )
612 m_xAggregate
->setDelegator( NULL
);
613 m_xAggregate
.clear();
616 DELETEZ( m_pControlBorderManager
);
621 void SAL_CALL
FormController::acquire() throw ()
623 FormController_BASE::acquire();
627 void SAL_CALL
FormController::release() throw ()
629 FormController_BASE::release();
633 Any SAL_CALL
FormController::queryInterface( const Type
& _rType
) throw(RuntimeException
, std::exception
)
635 Any aRet
= FormController_BASE::queryInterface( _rType
);
636 if ( !aRet
.hasValue() )
637 aRet
= OPropertySetHelper::queryInterface( _rType
);
638 if ( !aRet
.hasValue() )
639 aRet
= m_xAggregate
->queryAggregation( _rType
);
644 Sequence
< sal_Int8
> SAL_CALL
FormController::getImplementationId() throw( RuntimeException
, std::exception
)
646 return css::uno::Sequence
<sal_Int8
>();
649 Sequence
< Type
> SAL_CALL
FormController::getTypes( ) throw(RuntimeException
, std::exception
)
651 return comphelper::concatSequences(
652 FormController_BASE::getTypes(),
653 ::cppu::OPropertySetHelper::getTypes()
658 sal_Bool SAL_CALL
FormController::supportsService(const OUString
& ServiceName
) throw( RuntimeException
, std::exception
)
660 return cppu::supportsService(this, ServiceName
);
663 OUString SAL_CALL
FormController::getImplementationName() throw( RuntimeException
, std::exception
)
665 return OUString("org.openoffice.comp.svx.FormController");
668 Sequence
< OUString
> SAL_CALL
FormController::getSupportedServiceNames() throw( RuntimeException
, std::exception
)
670 // service names which are supported only, but cannot be used to created an
671 // instance at a service factory
672 Sequence
< OUString
> aNonCreatableServiceNames( 1 );
673 aNonCreatableServiceNames
[ 0 ] = "com.sun.star.form.FormControllerDispatcher";
675 // services which can be used to created an instance at a service factory
676 Sequence
< OUString
> aCreatableServiceNames( getSupportedServiceNames_Static() );
677 return ::comphelper::concatSequences( aCreatableServiceNames
, aNonCreatableServiceNames
);
681 sal_Bool SAL_CALL
FormController::approveReset(const EventObject
& /*rEvent*/) throw( RuntimeException
, std::exception
)
687 void SAL_CALL
FormController::resetted(const EventObject
& rEvent
) throw( RuntimeException
, std::exception
)
689 ::osl::MutexGuard
aGuard(m_aMutex
);
690 if (getCurrentControl().is() && (getCurrentControl()->getModel() == rEvent
.Source
))
695 Sequence
< OUString
> FormController::getSupportedServiceNames_Static()
697 static Sequence
< OUString
> aServices
;
698 if (!aServices
.getLength())
700 aServices
.realloc(2);
701 aServices
.getArray()[0] = "com.sun.star.form.runtime.FormController";
702 aServices
.getArray()[1] = "com.sun.star.awt.control.TabController";
710 struct ResetComponentText
: public ::std::unary_function
< Reference
< XTextComponent
>, void >
712 void operator()( const Reference
< XTextComponent
>& _rxText
)
714 _rxText
->setText( OUString() );
718 struct RemoveComponentTextListener
: public ::std::unary_function
< Reference
< XTextComponent
>, void >
720 RemoveComponentTextListener( const Reference
< XTextListener
>& _rxListener
)
721 :m_xListener( _rxListener
)
725 void operator()( const Reference
< XTextComponent
>& _rxText
)
727 _rxText
->removeTextListener( m_xListener
);
731 Reference
< XTextListener
> m_xListener
;
736 void FormController::impl_setTextOnAllFilter_throw()
738 m_bSuspendFilterTextListening
= true;
739 ::comphelper::FlagGuard
aResetFlag( m_bSuspendFilterTextListening
);
741 // reset the text for all controls
742 ::std::for_each( m_aFilterComponents
.begin(), m_aFilterComponents
.end(), ResetComponentText() );
744 if ( m_aFilterRows
.empty() )
745 // nothing to do anymore
748 if ( m_nCurrentFilterPosition
< 0 )
751 // set the text for all filters
752 OSL_ENSURE( m_aFilterRows
.size() > (size_t)m_nCurrentFilterPosition
,
753 "FormController::impl_setTextOnAllFilter_throw: m_nCurrentFilterPosition too big" );
755 if ( (size_t)m_nCurrentFilterPosition
< m_aFilterRows
.size() )
757 FmFilterRow
& rRow
= m_aFilterRows
[ m_nCurrentFilterPosition
];
758 for ( FmFilterRow::const_iterator iter2
= rRow
.begin();
763 iter2
->first
->setText( iter2
->second
);
767 // OPropertySetHelper
769 sal_Bool
FormController::convertFastPropertyValue( Any
& /*rConvertedValue*/, Any
& /*rOldValue*/,
770 sal_Int32
/*nHandle*/, const Any
& /*rValue*/ )
771 throw( IllegalArgumentException
)
777 void FormController::setFastPropertyValue_NoBroadcast( sal_Int32
/*nHandle*/, const Any
& /*rValue*/ )
778 throw( Exception
, std::exception
)
783 void FormController::getFastPropertyValue( Any
& rValue
, sal_Int32 nHandle
) const
789 OUStringBuffer aFilter
;
790 Reference
<XConnection
> xConnection(getConnection(Reference
< XRowSet
>(m_xModelAsIndex
, UNO_QUERY
)));
791 if (xConnection
.is())
793 Reference
< XDatabaseMetaData
> xMetaData(xConnection
->getMetaData());
794 Reference
< XNumberFormatsSupplier
> xFormatSupplier( getNumberFormats( xConnection
, true ) );
795 Reference
< XNumberFormatter
> xFormatter
= NumberFormatter::create(m_xComponentContext
);
796 xFormatter
->attachNumberFormatsSupplier(xFormatSupplier
);
798 Reference
< XColumnsSupplier
> xSupplyCols(m_xModelAsIndex
, UNO_QUERY
);
799 Reference
< XNameAccess
> xFields(xSupplyCols
->getColumns(), UNO_QUERY
);
801 // now add the filter rows
804 for ( FmFilterRows::const_iterator row
= m_aFilterRows
.begin(); row
!= m_aFilterRows
.end(); ++row
)
806 const FmFilterRow
& rRow
= *row
;
811 OUStringBuffer aRowFilter
;
812 for ( FmFilterRow::const_iterator condition
= rRow
.begin(); condition
!= rRow
.end(); ++condition
)
814 // get the field of the controls map
815 Reference
< XControl
> xControl( condition
->first
, UNO_QUERY_THROW
);
816 Reference
< XPropertySet
> xModelProps( xControl
->getModel(), UNO_QUERY_THROW
);
817 Reference
< XPropertySet
> xField( xModelProps
->getPropertyValue( FM_PROP_BOUNDFIELD
), UNO_QUERY_THROW
);
819 OUString
sFilterValue( condition
->second
);
821 OUString sErrorMsg
, sCriteria
;
822 const std::shared_ptr
< OSQLParseNode
> pParseNode
=
823 predicateTree( sErrorMsg
, sFilterValue
, xFormatter
, xField
);
824 OSL_ENSURE( pParseNode
!= nullptr, "FormController::getFastPropertyValue: could not parse the field value predicate!" );
825 if ( pParseNode
!= nullptr )
827 // don't use a parse context here, we need it unlocalized
828 pParseNode
->parseNodeToStr( sCriteria
, xConnection
, NULL
);
829 if ( condition
!= rRow
.begin() )
830 aRowFilter
.appendAscii( " AND " );
831 aRowFilter
.append( sCriteria
);
834 if ( !aRowFilter
.isEmpty() )
836 if ( !aFilter
.isEmpty() )
837 aFilter
.appendAscii( " OR " );
839 aFilter
.appendAscii( "( " );
840 aFilter
.append( aRowFilter
.makeStringAndClear() );
841 aFilter
.appendAscii( " )" );
845 catch( const Exception
& )
847 DBG_UNHANDLED_EXCEPTION();
848 aFilter
.setLength(0);
851 rValue
<<= aFilter
.makeStringAndClear();
855 case FM_ATTR_FORM_OPERATIONS
:
856 rValue
<<= m_xFormOperations
;
862 Reference
< XPropertySetInfo
> FormController::getPropertySetInfo() throw( RuntimeException
, std::exception
)
864 static Reference
< XPropertySetInfo
> xInfo( createPropertySetInfo( getInfoHelper() ) );
869 void FormController::fillProperties(
870 Sequence
< Property
>& /* [out] */ _rProps
,
871 Sequence
< Property
>& /* [out] */ /*_rAggregateProps*/
876 Property
* pDesc
= _rProps
.getArray();
878 pDesc
[nPos
++] = Property(FM_PROP_FILTER
, FM_ATTR_FILTER
,
879 cppu::UnoType
<OUString
>::get(),
880 PropertyAttribute::READONLY
);
881 pDesc
[nPos
++] = Property(FM_PROP_FORM_OPERATIONS
, FM_ATTR_FORM_OPERATIONS
,
882 cppu::UnoType
<XFormOperations
>::get(),
883 PropertyAttribute::READONLY
);
887 ::cppu::IPropertyArrayHelper
& FormController::getInfoHelper()
889 return *getArrayHelper();
894 void SAL_CALL
FormController::addFilterControllerListener( const Reference
< XFilterControllerListener
>& _Listener
) throw( RuntimeException
, std::exception
)
896 m_aFilterListeners
.addInterface( _Listener
);
900 void SAL_CALL
FormController::removeFilterControllerListener( const Reference
< XFilterControllerListener
>& _Listener
) throw( RuntimeException
, std::exception
)
902 m_aFilterListeners
.removeInterface( _Listener
);
906 ::sal_Int32 SAL_CALL
FormController::getFilterComponents() throw( ::com::sun::star::uno::RuntimeException
, std::exception
)
908 ::osl::MutexGuard
aGuard( m_aMutex
);
909 impl_checkDisposed_throw();
911 return m_aFilterComponents
.size();
915 ::sal_Int32 SAL_CALL
FormController::getDisjunctiveTerms() throw( ::com::sun::star::uno::RuntimeException
, std::exception
)
917 ::osl::MutexGuard
aGuard( m_aMutex
);
918 impl_checkDisposed_throw();
920 return m_aFilterRows
.size();
924 void SAL_CALL
FormController::setPredicateExpression( ::sal_Int32 _Component
, ::sal_Int32 _Term
, const OUString
& _PredicateExpression
) throw( RuntimeException
, IndexOutOfBoundsException
, std::exception
)
926 ::osl::MutexGuard
aGuard( m_aMutex
);
927 impl_checkDisposed_throw();
929 if ( ( _Component
< 0 ) || ( _Component
>= getFilterComponents() ) || ( _Term
< 0 ) || ( _Term
>= getDisjunctiveTerms() ) )
930 throw IndexOutOfBoundsException( OUString(), *this );
932 Reference
< XTextComponent
> xText( m_aFilterComponents
[ _Component
] );
933 xText
->setText( _PredicateExpression
);
935 FmFilterRow
& rFilterRow
= m_aFilterRows
[ _Term
];
936 if ( !_PredicateExpression
.isEmpty() )
937 rFilterRow
[ xText
] = _PredicateExpression
;
939 rFilterRow
.erase( xText
);
943 Reference
< XControl
> FormController::getFilterComponent( ::sal_Int32 _Component
) throw( RuntimeException
, IndexOutOfBoundsException
, std::exception
)
945 ::osl::MutexGuard
aGuard( m_aMutex
);
946 impl_checkDisposed_throw();
948 if ( ( _Component
< 0 ) || ( _Component
>= getFilterComponents() ) )
949 throw IndexOutOfBoundsException( OUString(), *this );
951 return Reference
< XControl
>( m_aFilterComponents
[ _Component
], UNO_QUERY
);
955 Sequence
< Sequence
< OUString
> > FormController::getPredicateExpressions() throw( RuntimeException
, std::exception
)
957 ::osl::MutexGuard
aGuard( m_aMutex
);
958 impl_checkDisposed_throw();
960 Sequence
< Sequence
< OUString
> > aExpressions( m_aFilterRows
.size() );
961 sal_Int32 termIndex
= 0;
962 for ( FmFilterRows::const_iterator row
= m_aFilterRows
.begin();
963 row
!= m_aFilterRows
.end();
967 const FmFilterRow
& rRow( *row
);
969 Sequence
< OUString
> aConjunction( m_aFilterComponents
.size() );
970 sal_Int32 componentIndex
= 0;
971 for ( FilterComponents::const_iterator comp
= m_aFilterComponents
.begin();
972 comp
!= m_aFilterComponents
.end();
973 ++comp
, ++componentIndex
976 FmFilterRow::const_iterator predicate
= rRow
.find( *comp
);
977 if ( predicate
!= rRow
.end() )
978 aConjunction
[ componentIndex
] = predicate
->second
;
981 aExpressions
[ termIndex
] = aConjunction
;
988 void SAL_CALL
FormController::removeDisjunctiveTerm( ::sal_Int32 _Term
) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
991 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
992 impl_checkDisposed_throw();
994 if ( ( _Term
< 0 ) || ( _Term
>= getDisjunctiveTerms() ) )
995 throw IndexOutOfBoundsException( OUString(), *this );
997 // if the to-be-deleted row is our current row, we need to shift
998 if ( _Term
== m_nCurrentFilterPosition
)
1000 if ( m_nCurrentFilterPosition
< sal_Int32( m_aFilterRows
.size() - 1 ) )
1001 ++m_nCurrentFilterPosition
;
1003 --m_nCurrentFilterPosition
;
1006 FmFilterRows::iterator pos
= m_aFilterRows
.begin() + _Term
;
1007 m_aFilterRows
.erase( pos
);
1009 // adjust m_nCurrentFilterPosition if the removed row preceded it
1010 if ( _Term
< m_nCurrentFilterPosition
)
1011 --m_nCurrentFilterPosition
;
1013 SAL_WARN_IF( !( ( m_nCurrentFilterPosition
< 0 ) != ( m_aFilterRows
.empty() ) ),
1014 "svx.form", "FormController::removeDisjunctiveTerm: inconsistency!" );
1016 // update the texts in the filter controls
1017 impl_setTextOnAllFilter_throw();
1020 aEvent
.Source
= *this;
1021 aEvent
.DisjunctiveTerm
= _Term
;
1025 m_aFilterListeners
.notifyEach( &XFilterControllerListener::disjunctiveTermRemoved
, aEvent
);
1029 void SAL_CALL
FormController::appendEmptyDisjunctiveTerm() throw (RuntimeException
, std::exception
)
1032 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
1033 impl_checkDisposed_throw();
1035 impl_appendEmptyFilterRow( aGuard
);
1040 ::sal_Int32 SAL_CALL
FormController::getActiveTerm() throw (RuntimeException
, std::exception
)
1042 ::osl::MutexGuard
aGuard( m_aMutex
);
1043 impl_checkDisposed_throw();
1045 return m_nCurrentFilterPosition
;
1049 void SAL_CALL
FormController::setActiveTerm( ::sal_Int32 _ActiveTerm
) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
1051 ::osl::MutexGuard
aGuard( m_aMutex
);
1052 impl_checkDisposed_throw();
1054 if ( ( _ActiveTerm
< 0 ) || ( _ActiveTerm
>= getDisjunctiveTerms() ) )
1055 throw IndexOutOfBoundsException( OUString(), *this );
1057 if ( _ActiveTerm
== getActiveTerm() )
1060 m_nCurrentFilterPosition
= _ActiveTerm
;
1061 impl_setTextOnAllFilter_throw();
1066 sal_Bool SAL_CALL
FormController::hasElements() throw( RuntimeException
, std::exception
)
1068 ::osl::MutexGuard
aGuard( m_aMutex
);
1069 return !m_aChildren
.empty();
1073 Type SAL_CALL
FormController::getElementType() throw( RuntimeException
, std::exception
)
1075 return cppu::UnoType
<XFormController
>::get();
1079 // XEnumerationAccess
1081 Reference
< XEnumeration
> SAL_CALL
FormController::createEnumeration() throw( RuntimeException
, std::exception
)
1083 ::osl::MutexGuard
aGuard( m_aMutex
);
1084 return new ::comphelper::OEnumerationByIndex(this);
1089 sal_Int32 SAL_CALL
FormController::getCount() throw( RuntimeException
, std::exception
)
1091 ::osl::MutexGuard
aGuard( m_aMutex
);
1092 return m_aChildren
.size();
1096 Any SAL_CALL
FormController::getByIndex(sal_Int32 Index
) throw( IndexOutOfBoundsException
, WrappedTargetException
, RuntimeException
, std::exception
)
1098 ::osl::MutexGuard
aGuard( m_aMutex
);
1100 Index
>= (sal_Int32
)m_aChildren
.size())
1101 throw IndexOutOfBoundsException();
1103 return makeAny( m_aChildren
[ Index
] );
1108 void SAL_CALL
FormController::disposing(const EventObject
& e
) throw( RuntimeException
, std::exception
)
1110 // Ist der Container disposed worden
1111 ::osl::MutexGuard
aGuard( m_aMutex
);
1112 Reference
< XControlContainer
> xContainer(e
.Source
, UNO_QUERY
);
1113 if (xContainer
.is())
1115 setContainer(Reference
< XControlContainer
> ());
1119 // ist ein Control disposed worden
1120 Reference
< XControl
> xControl(e
.Source
, UNO_QUERY
);
1123 if (getContainer().is())
1124 removeControl(xControl
);
1131 void FormController::disposeAllFeaturesAndDispatchers()
1133 for ( DispatcherContainer::iterator aDispatcher
= m_aFeatureDispatchers
.begin();
1134 aDispatcher
!= m_aFeatureDispatchers
.end();
1140 ::comphelper::disposeComponent( aDispatcher
->second
);
1142 catch( const Exception
& )
1144 DBG_UNHANDLED_EXCEPTION();
1147 m_aFeatureDispatchers
.clear();
1151 void FormController::disposing()
1153 EventObject
aEvt( *this );
1155 // if we're still active, simulate a "deactivated" event
1156 if ( m_xActiveControl
.is() )
1157 m_aActivateListeners
.notifyEach( &XFormControllerListener::formDeactivated
, aEvt
);
1159 // notify all our listeners
1160 m_aActivateListeners
.disposeAndClear(aEvt
);
1161 m_aModifyListeners
.disposeAndClear(aEvt
);
1162 m_aErrorListeners
.disposeAndClear(aEvt
);
1163 m_aDeleteListeners
.disposeAndClear(aEvt
);
1164 m_aRowSetApproveListeners
.disposeAndClear(aEvt
);
1165 m_aParameterListeners
.disposeAndClear(aEvt
);
1166 m_aFilterListeners
.disposeAndClear(aEvt
);
1168 removeBoundFieldListener();
1171 m_pControlBorderManager
->restoreAll();
1173 m_aFilterRows
.clear();
1175 ::osl::MutexGuard
aGuard( m_aMutex
);
1176 m_xActiveControl
= NULL
;
1177 implSetCurrentControl( NULL
);
1179 // clean up our children
1180 for (FmFormControllers::const_iterator i
= m_aChildren
.begin();
1181 i
!= m_aChildren
.end(); ++i
)
1183 // search the position of the model within the form
1184 Reference
< XFormComponent
> xForm((*i
)->getModel(), UNO_QUERY
);
1185 sal_uInt32 nPos
= m_xModelAsIndex
->getCount();
1186 Reference
< XFormComponent
> xTemp
;
1190 m_xModelAsIndex
->getByIndex( --nPos
) >>= xTemp
;
1191 if ( xForm
.get() == xTemp
.get() )
1193 Reference
< XInterface
> xIfc( *i
, UNO_QUERY
);
1194 m_xModelAsManager
->detach( nPos
, xIfc
);
1199 Reference
< XComponent
> (*i
, UNO_QUERY
)->dispose();
1201 m_aChildren
.clear();
1203 disposeAllFeaturesAndDispatchers();
1205 if ( m_xFormOperations
.is() )
1206 m_xFormOperations
->dispose();
1207 m_xFormOperations
.clear();
1209 if (m_bDBConnection
)
1212 setContainer( NULL
);
1216 ::comphelper::disposeComponent( m_xComposer
);
1218 m_bDBConnection
= false;
1224 static bool lcl_shouldUseDynamicControlBorder( const Reference
< XInterface
>& _rxForm
, const Any
& _rDynamicColorProp
)
1226 bool bDoUse
= false;
1227 if ( !( _rDynamicColorProp
>>= bDoUse
) )
1229 DocumentType eDocType
= DocumentClassification::classifyHostDocument( _rxForm
);
1230 return ControlLayouter::useDynamicBorderColor( eDocType
);
1237 void SAL_CALL
FormController::propertyChange(const PropertyChangeEvent
& evt
) throw( RuntimeException
, std::exception
)
1239 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1240 if ( evt
.PropertyName
== FM_PROP_BOUNDFIELD
)
1242 Reference
<XPropertySet
> xOldBound
;
1243 evt
.OldValue
>>= xOldBound
;
1244 if ( !xOldBound
.is() && evt
.NewValue
.hasValue() )
1246 Reference
< XControlModel
> xControlModel(evt
.Source
,UNO_QUERY
);
1247 Reference
< XControl
> xControl
= findControl(m_aControls
,xControlModel
,false,false);
1248 if ( xControl
.is() )
1250 startControlModifyListening( xControl
);
1251 Reference
<XPropertySet
> xProp(xControlModel
,UNO_QUERY
);
1253 xProp
->removePropertyChangeListener(FM_PROP_BOUNDFIELD
, this);
1259 bool bModifiedChanged
= (evt
.PropertyName
== FM_PROP_ISMODIFIED
);
1260 bool bNewChanged
= (evt
.PropertyName
== FM_PROP_ISNEW
);
1261 if (bModifiedChanged
|| bNewChanged
)
1263 ::osl::MutexGuard
aGuard( m_aMutex
);
1264 if (bModifiedChanged
)
1265 m_bCurrentRecordModified
= ::comphelper::getBOOL(evt
.NewValue
);
1267 m_bCurrentRecordNew
= ::comphelper::getBOOL(evt
.NewValue
);
1269 // toggle the locking
1270 if (m_bLocked
!= determineLockState())
1272 m_bLocked
= !m_bLocked
;
1274 if (isListeningForChanges())
1281 m_aToggleEvent
.Call();
1283 if (!m_bCurrentRecordModified
)
1284 m_bModified
= false;
1286 else if ( evt
.PropertyName
== FM_PROP_DYNAMIC_CONTROL_BORDER
)
1288 bool bEnable
= lcl_shouldUseDynamicControlBorder( evt
.Source
, evt
.NewValue
);
1291 m_pControlBorderManager
->enableDynamicBorderColor();
1292 if ( m_xActiveControl
.is() )
1293 m_pControlBorderManager
->focusGained( m_xActiveControl
.get() );
1297 m_pControlBorderManager
->disableDynamicBorderColor();
1304 bool FormController::replaceControl( const Reference
< XControl
>& _rxExistentControl
, const Reference
< XControl
>& _rxNewControl
)
1306 bool bSuccess
= false;
1309 Reference
< XIdentifierReplace
> xContainer( getContainer(), UNO_QUERY
);
1310 DBG_ASSERT( xContainer
.is(), "FormController::replaceControl: yes, it's not required by the service description, but XItentifierReplaces would be nice!" );
1311 if ( xContainer
.is() )
1313 // look up the ID of _rxExistentControl
1314 Sequence
< sal_Int32
> aIdentifiers( xContainer
->getIdentifiers() );
1315 const sal_Int32
* pIdentifiers
= aIdentifiers
.getConstArray();
1316 const sal_Int32
* pIdentifiersEnd
= aIdentifiers
.getConstArray() + aIdentifiers
.getLength();
1317 for ( ; pIdentifiers
!= pIdentifiersEnd
; ++pIdentifiers
)
1319 Reference
< XControl
> xCheck( xContainer
->getByIdentifier( *pIdentifiers
), UNO_QUERY
);
1320 if ( xCheck
== _rxExistentControl
)
1323 DBG_ASSERT( pIdentifiers
!= pIdentifiersEnd
, "FormController::replaceControl: did not find the control in the container!" );
1324 if ( pIdentifiers
!= pIdentifiersEnd
)
1326 bool bReplacedWasActive
= ( m_xActiveControl
.get() == _rxExistentControl
.get() );
1327 bool bReplacedWasCurrent
= ( m_xCurrentControl
.get() == _rxExistentControl
.get() );
1329 if ( bReplacedWasActive
)
1331 m_xActiveControl
= NULL
;
1332 implSetCurrentControl( NULL
);
1334 else if ( bReplacedWasCurrent
)
1336 implSetCurrentControl( _rxNewControl
);
1339 // carry over the model
1340 _rxNewControl
->setModel( _rxExistentControl
->getModel() );
1342 xContainer
->replaceByIdentifer( *pIdentifiers
, makeAny( _rxNewControl
) );
1345 if ( bReplacedWasActive
)
1347 Reference
< XWindow
> xControlWindow( _rxNewControl
, UNO_QUERY
);
1348 if ( xControlWindow
.is() )
1349 xControlWindow
->setFocus();
1354 catch( const Exception
& )
1356 DBG_UNHANDLED_EXCEPTION();
1359 Reference
< XControl
> xDisposeIt( bSuccess
? _rxExistentControl
: _rxNewControl
);
1360 ::comphelper::disposeComponent( xDisposeIt
);
1365 void FormController::toggleAutoFields(bool bAutoFields
)
1367 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1370 Sequence
< Reference
< XControl
> > aControlsCopy( m_aControls
);
1371 const Reference
< XControl
>* pControls
= aControlsCopy
.getConstArray();
1372 sal_Int32 nControls
= aControlsCopy
.getLength();
1376 // as we don't want new controls to be attached to the scripting environment
1377 // we change attach flags
1378 m_bAttachEvents
= false;
1379 for (sal_Int32 i
= nControls
; i
> 0;)
1381 Reference
< XControl
> xControl
= pControls
[--i
];
1384 Reference
< XPropertySet
> xSet(xControl
->getModel(), UNO_QUERY
);
1385 if (xSet
.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD
, xSet
))
1387 // does the model use a bound field ?
1388 Reference
< XPropertySet
> xField
;
1389 xSet
->getPropertyValue(FM_PROP_BOUNDFIELD
) >>= xField
;
1391 // is it a autofield?
1393 && ::comphelper::hasProperty( FM_PROP_AUTOINCREMENT
, xField
)
1394 && ::comphelper::getBOOL( xField
->getPropertyValue( FM_PROP_AUTOINCREMENT
) )
1397 replaceControl( xControl
, new FmXAutoControl() );
1402 m_bAttachEvents
= true;
1406 m_bDetachEvents
= false;
1407 for (sal_Int32 i
= nControls
; i
> 0;)
1409 Reference
< XControl
> xControl
= pControls
[--i
];
1412 Reference
< XPropertySet
> xSet(xControl
->getModel(), UNO_QUERY
);
1413 if (xSet
.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD
, xSet
))
1415 // does the model use a bound field ?
1416 Reference
< XPropertySet
> xField
;
1417 xSet
->getPropertyValue(FM_PROP_BOUNDFIELD
) >>= xField
;
1419 // is it a autofield?
1421 && ::comphelper::hasProperty( FM_PROP_AUTOINCREMENT
, xField
)
1422 && ::comphelper::getBOOL( xField
->getPropertyValue(FM_PROP_AUTOINCREMENT
) )
1425 OUString sServiceName
;
1426 OSL_VERIFY( xSet
->getPropertyValue( FM_PROP_DEFAULTCONTROL
) >>= sServiceName
);
1427 Reference
< XControl
> xNewControl( m_xComponentContext
->getServiceManager()->createInstanceWithContext( sServiceName
, m_xComponentContext
), UNO_QUERY
);
1428 replaceControl( xControl
, xNewControl
);
1433 m_bDetachEvents
= true;
1438 IMPL_LINK_NOARG(FormController
, OnToggleAutoFields
)
1440 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1442 toggleAutoFields(m_bCurrentRecordNew
);
1448 void SAL_CALL
FormController::textChanged(const TextEvent
& e
) throw( RuntimeException
, std::exception
)
1451 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
1452 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1453 if ( !m_bFiltering
)
1459 if ( m_bSuspendFilterTextListening
)
1462 Reference
< XTextComponent
> xText(e
.Source
,UNO_QUERY
);
1463 OUString aText
= xText
->getText();
1465 if ( m_aFilterRows
.empty() )
1466 appendEmptyDisjunctiveTerm();
1468 // Suchen der aktuellen Row
1469 if ( ( (size_t)m_nCurrentFilterPosition
>= m_aFilterRows
.size() ) || ( m_nCurrentFilterPosition
< 0 ) )
1471 OSL_ENSURE( false, "FormController::textChanged: m_nCurrentFilterPosition is wrong!" );
1475 FmFilterRow
& rRow
= m_aFilterRows
[ m_nCurrentFilterPosition
];
1477 // do we have a new filter
1478 if (!aText
.isEmpty())
1479 rRow
[xText
] = aText
;
1482 // do we have the control in the row
1483 FmFilterRow::iterator iter
= rRow
.find(xText
);
1484 // erase the entry out of the row
1485 if (iter
!= rRow
.end())
1489 // multiplex the event to our FilterControllerListeners
1491 aEvent
.Source
= *this;
1492 aEvent
.FilterComponent
= ::std::find( m_aFilterComponents
.begin(), m_aFilterComponents
.end(), xText
) - m_aFilterComponents
.begin();
1493 aEvent
.DisjunctiveTerm
= getActiveTerm();
1494 aEvent
.PredicateExpression
= aText
;
1499 // notify the changed filter expression
1500 m_aFilterListeners
.notifyEach( &XFilterControllerListener::predicateExpressionChanged
, aEvent
);
1505 void SAL_CALL
FormController::itemStateChanged(const ItemEvent
& /*rEvent*/) throw( RuntimeException
, std::exception
)
1507 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1511 // XModificationBroadcaster
1513 void SAL_CALL
FormController::addModifyListener(const Reference
< XModifyListener
> & l
) throw( RuntimeException
, std::exception
)
1515 ::osl::MutexGuard
aGuard( m_aMutex
);
1516 impl_checkDisposed_throw();
1517 m_aModifyListeners
.addInterface( l
);
1521 void FormController::removeModifyListener(const Reference
< XModifyListener
> & l
) throw( RuntimeException
, std::exception
)
1523 ::osl::MutexGuard
aGuard( m_aMutex
);
1524 impl_checkDisposed_throw();
1525 m_aModifyListeners
.removeInterface( l
);
1528 // XModificationListener
1530 void FormController::modified( const EventObject
& _rEvent
) throw( RuntimeException
, std::exception
)
1532 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1536 if ( _rEvent
.Source
!= m_xActiveControl
)
1537 { // let this control grab the focus
1538 // (this case may happen if somebody moves the scroll wheel of the mouse over a control
1539 // which does not have the focus)
1540 // 85511 - 29.05.2001 - frank.schoenheit@germany.sun.com
1542 // also, it happens when an image control gets a new image by double-clicking it
1543 // #i88458# / 2009-01-12 / frank.schoenheit@sun.com
1544 Reference
< XWindow
> xControlWindow( _rEvent
.Source
, UNO_QUERY_THROW
);
1545 xControlWindow
->setFocus();
1548 catch( const Exception
& )
1550 DBG_UNHANDLED_EXCEPTION();
1557 void FormController::impl_checkDisposed_throw() const
1559 if ( impl_isDisposed_nofail() )
1560 throw DisposedException( OUString(), *const_cast< FormController
* >( this ) );
1564 void FormController::impl_onModify()
1566 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1569 ::osl::MutexGuard
aGuard( m_aMutex
);
1574 EventObject
aEvt(static_cast<cppu::OWeakObject
*>(this));
1575 m_aModifyListeners
.notifyEach( &XModifyListener::modified
, aEvt
);
1579 void FormController::impl_addFilterRow( const FmFilterRow
& _row
)
1581 m_aFilterRows
.push_back( _row
);
1583 if ( m_aFilterRows
.size() == 1 )
1584 { // that's the first row ever
1585 OSL_ENSURE( m_nCurrentFilterPosition
== -1, "FormController::impl_addFilterRow: inconsistency!" );
1586 m_nCurrentFilterPosition
= 0;
1591 void FormController::impl_appendEmptyFilterRow( ::osl::ClearableMutexGuard
& _rClearBeforeNotify
)
1594 impl_addFilterRow( FmFilterRow() );
1596 // notify the listeners
1598 aEvent
.Source
= *this;
1599 aEvent
.DisjunctiveTerm
= (sal_Int32
)m_aFilterRows
.size() - 1;
1600 _rClearBeforeNotify
.clear();
1602 m_aFilterListeners
.notifyEach( &XFilterControllerListener::disjunctiveTermAdded
, aEvent
);
1606 bool FormController::determineLockState() const
1608 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1609 // a.) in filter mode we are always locked
1610 // b.) if we have no valid model or our model (a result set) is not alive -> we're locked
1611 // c.) if we are inserting everything is OK and we are not locked
1612 // d.) if are not updatable or on invalid position
1613 Reference
< XResultSet
> xResultSet(m_xModelAsIndex
, UNO_QUERY
);
1614 if (m_bFiltering
|| !xResultSet
.is() || !isRowSetAlive(xResultSet
))
1617 return !(m_bCanInsert
&& m_bCurrentRecordNew
)
1618 && (xResultSet
->isBeforeFirst() || xResultSet
->isAfterLast() || xResultSet
->rowDeleted() || !m_bCanUpdate
);
1623 void FormController::focusGained(const FocusEvent
& e
) throw( RuntimeException
, std::exception
)
1626 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
1627 impl_checkDisposed_throw();
1629 m_pControlBorderManager
->focusGained( e
.Source
);
1631 Reference
< XControl
> xControl(e
.Source
, UNO_QUERY
);
1632 if (m_bDBConnection
)
1634 // do we need to keep the locking of the commit
1635 // we hold the lock as long as the control differs from the current
1636 // otherwise we disabled the lock
1637 m_bCommitLock
= m_bCommitLock
&& (XControl
*)xControl
.get() != (XControl
*)m_xCurrentControl
.get();
1641 // when do we have to commit a value to form or a filter
1642 // a.) if the current value is modified
1643 // b.) there must be a current control
1644 // c.) and it must be different from the new focus owning control or
1645 // d.) the focus is moving around (so we have only one control)
1647 if ( ( m_bModified
|| m_bFiltering
)
1648 && m_xCurrentControl
.is()
1649 && ( ( xControl
.get() != m_xCurrentControl
.get() )
1650 || ( ( e
.FocusFlags
& FocusChangeReason::AROUND
)
1651 && ( m_bCycle
|| m_bFiltering
)
1656 // check the old control if the content is ok
1657 #if OSL_DEBUG_LEVEL > 1
1658 Reference
< XBoundControl
> xLockingTest(m_xCurrentControl
, UNO_QUERY
);
1659 sal_Bool bControlIsLocked
= xLockingTest
.is() && xLockingTest
->getLock();
1660 OSL_ENSURE(!bControlIsLocked
, "FormController::Gained: I'm modified and the current control is locked ? How this ?");
1661 // normalerweise sollte ein gelocktes Control nicht modified sein, also muss wohl mein bModified aus einem anderen Kontext
1662 // gesetzt worden sein, was ich nicht verstehen wuerde ...
1664 DBG_ASSERT(m_xCurrentControl
.is(), "kein CurrentControl gesetzt");
1665 // zunaechst das Control fragen ob es das IFace unterstuetzt
1666 Reference
< XBoundComponent
> xBound(m_xCurrentControl
, UNO_QUERY
);
1667 if (!xBound
.is() && m_xCurrentControl
.is())
1668 xBound
= Reference
< XBoundComponent
> (m_xCurrentControl
->getModel(), UNO_QUERY
);
1670 // lock if we lose the focus during commit
1671 m_bCommitLock
= true;
1673 // Commit nicht erfolgreich, Focus zuruecksetzen
1674 if (xBound
.is() && !xBound
->commit())
1676 // the commit failed and we don't commit again until the current control
1677 // which couldn't be commit gains the focus again
1678 Reference
< XWindow
> xWindow(m_xCurrentControl
, UNO_QUERY
);
1680 xWindow
->setFocus();
1685 m_bModified
= false;
1686 m_bCommitLock
= false;
1690 if (!m_bFiltering
&& m_bCycle
&& (e
.FocusFlags
& FocusChangeReason::AROUND
) && m_xCurrentControl
.is())
1692 SQLErrorEvent aErrorEvent
;
1693 OSL_ENSURE( m_xFormOperations
.is(), "FormController::focusGained: hmm?" );
1694 // should have been created in setModel
1697 if ( e
.FocusFlags
& FocusChangeReason::FORWARD
)
1699 if ( m_xFormOperations
.is() && m_xFormOperations
->isEnabled( FormFeature::MoveToNext
) )
1700 m_xFormOperations
->execute( FormFeature::MoveToNext
);
1704 if ( m_xFormOperations
.is() && m_xFormOperations
->isEnabled( FormFeature::MoveToPrevious
) )
1705 m_xFormOperations
->execute( FormFeature::MoveToPrevious
);
1708 catch ( const Exception
& )
1710 // don't handle this any further. That's an ... admissible error.
1711 DBG_UNHANDLED_EXCEPTION();
1716 // Immer noch ein und dasselbe Control
1717 if ( ( m_xActiveControl
== xControl
)
1718 && ( xControl
== m_xCurrentControl
)
1721 DBG_ASSERT(m_xCurrentControl
.is(), "Kein CurrentControl selektiert");
1725 bool bActivated
= !m_xActiveControl
.is() && xControl
.is();
1727 m_xActiveControl
= xControl
;
1729 implSetCurrentControl( xControl
);
1730 SAL_WARN_IF( !m_xCurrentControl
.is(), "svx.form", "implSetCurrentControl did nonsense!" );
1734 // (asynchronously) call activation handlers
1735 m_aActivationEvent
.Call();
1737 // call modify listeners
1739 m_aModifyListeners
.notifyEach( &XModifyListener::modified
, EventObject( *this ) );
1742 // invalidate all features which depend on the currently focused control
1743 if ( m_bDBConnection
&& !m_bFiltering
)
1744 implInvalidateCurrentControlDependentFeatures();
1746 if ( !m_xCurrentControl
.is() )
1749 // Control erhaelt Focus, dann eventuell in den sichtbaren Bereich
1750 Reference
< XFormControllerContext
> xContext( m_xFormControllerContext
);
1751 Reference
< XControl
> xCurrentControl( m_xCurrentControl
);
1755 if ( xContext
.is() )
1756 xContext
->makeVisible( xCurrentControl
);
1760 IMPL_LINK_NOARG( FormController
, OnActivated
)
1763 aEvent
.Source
= *this;
1764 m_aActivateListeners
.notifyEach( &XFormControllerListener::formActivated
, aEvent
);
1770 IMPL_LINK_NOARG( FormController
, OnDeactivated
)
1773 aEvent
.Source
= *this;
1774 m_aActivateListeners
.notifyEach( &XFormControllerListener::formDeactivated
, aEvent
);
1780 void FormController::focusLost(const FocusEvent
& e
) throw( RuntimeException
, std::exception
)
1782 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1784 m_pControlBorderManager
->focusLost( e
.Source
);
1786 Reference
< XControl
> xControl(e
.Source
, UNO_QUERY
);
1787 Reference
< XWindowPeer
> xNext(e
.NextFocus
, UNO_QUERY
);
1788 Reference
< XControl
> xNextControl
= isInList(xNext
);
1789 if (!xNextControl
.is())
1791 m_xActiveControl
= NULL
;
1792 m_aDeactivationEvent
.Call();
1797 void SAL_CALL
FormController::mousePressed( const awt::MouseEvent
& /*_rEvent*/ ) throw (RuntimeException
, std::exception
)
1799 // not interested in
1803 void SAL_CALL
FormController::mouseReleased( const awt::MouseEvent
& /*_rEvent*/ ) throw (RuntimeException
, std::exception
)
1805 // not interested in
1809 void SAL_CALL
FormController::mouseEntered( const awt::MouseEvent
& _rEvent
) throw (RuntimeException
, std::exception
)
1811 m_pControlBorderManager
->mouseEntered( _rEvent
.Source
);
1815 void SAL_CALL
FormController::mouseExited( const awt::MouseEvent
& _rEvent
) throw (RuntimeException
, std::exception
)
1817 m_pControlBorderManager
->mouseExited( _rEvent
.Source
);
1821 void SAL_CALL
FormController::componentValidityChanged( const EventObject
& _rSource
) throw (RuntimeException
, std::exception
)
1823 Reference
< XControl
> xControl( findControl( m_aControls
, Reference
< XControlModel
>( _rSource
.Source
, UNO_QUERY
), false, false ) );
1824 Reference
< XValidatableFormComponent
> xValidatable( _rSource
.Source
, UNO_QUERY
);
1826 OSL_ENSURE( xControl
.is() && xValidatable
.is(), "FormController::componentValidityChanged: huh?" );
1828 if ( xControl
.is() && xValidatable
.is() )
1829 m_pControlBorderManager
->validityChanged( xControl
, xValidatable
);
1833 void FormController::setModel(const Reference
< XTabControllerModel
> & Model
) throw( RuntimeException
, std::exception
)
1835 ::osl::MutexGuard
aGuard( m_aMutex
);
1836 impl_checkDisposed_throw();
1838 DBG_ASSERT(m_xTabController
.is(), "FormController::setModel : invalid aggregate !");
1842 // disconnect from the old model
1843 if (m_xModelAsIndex
.is())
1845 if (m_bDBConnection
)
1847 // we are currently working on the model
1848 EventObject
aEvt(m_xModelAsIndex
);
1852 Reference
< XLoadable
> xForm(m_xModelAsIndex
, UNO_QUERY
);
1854 xForm
->removeLoadListener(this);
1856 Reference
< XSQLErrorBroadcaster
> xBroadcaster(m_xModelAsIndex
, UNO_QUERY
);
1857 if (xBroadcaster
.is())
1858 xBroadcaster
->removeSQLErrorListener(this);
1860 Reference
< XDatabaseParameterBroadcaster
> xParamBroadcaster(m_xModelAsIndex
, UNO_QUERY
);
1861 if (xParamBroadcaster
.is())
1862 xParamBroadcaster
->removeParameterListener(this);
1866 disposeAllFeaturesAndDispatchers();
1868 if ( m_xFormOperations
.is() )
1869 m_xFormOperations
->dispose();
1870 m_xFormOperations
.clear();
1872 // set the new model wait for the load event
1873 if (m_xTabController
.is())
1874 m_xTabController
->setModel(Model
);
1875 m_xModelAsIndex
= Reference
< XIndexAccess
> (Model
, UNO_QUERY
);
1876 m_xModelAsManager
= Reference
< XEventAttacherManager
> (Model
, UNO_QUERY
);
1878 // only if both ifaces exit, the controller will work successful
1879 if (!m_xModelAsIndex
.is() || !m_xModelAsManager
.is())
1881 m_xModelAsManager
= NULL
;
1882 m_xModelAsIndex
= NULL
;
1885 if (m_xModelAsIndex
.is())
1887 // re-create m_xFormOperations
1888 m_xFormOperations
= FormOperations::createWithFormController( m_xComponentContext
, this );
1889 m_xFormOperations
->setFeatureInvalidation( this );
1891 // adding load and ui interaction listeners
1892 Reference
< XLoadable
> xForm(Model
, UNO_QUERY
);
1894 xForm
->addLoadListener(this);
1896 Reference
< XSQLErrorBroadcaster
> xBroadcaster(Model
, UNO_QUERY
);
1897 if (xBroadcaster
.is())
1898 xBroadcaster
->addSQLErrorListener(this);
1900 Reference
< XDatabaseParameterBroadcaster
> xParamBroadcaster(Model
, UNO_QUERY
);
1901 if (xParamBroadcaster
.is())
1902 xParamBroadcaster
->addParameterListener(this);
1904 // well, is the database already loaded?
1905 // then we have to simulate a load event
1906 Reference
< XLoadable
> xCursor(m_xModelAsIndex
, UNO_QUERY
);
1907 if (xCursor
.is() && xCursor
->isLoaded())
1909 EventObject
aEvt(xCursor
);
1913 Reference
< XPropertySet
> xModelProps( m_xModelAsIndex
, UNO_QUERY
);
1914 Reference
< XPropertySetInfo
> xPropInfo( xModelProps
->getPropertySetInfo() );
1916 && xPropInfo
->hasPropertyByName( FM_PROP_DYNAMIC_CONTROL_BORDER
)
1917 && xPropInfo
->hasPropertyByName( FM_PROP_CONTROL_BORDER_COLOR_FOCUS
)
1918 && xPropInfo
->hasPropertyByName( FM_PROP_CONTROL_BORDER_COLOR_MOUSE
)
1919 && xPropInfo
->hasPropertyByName( FM_PROP_CONTROL_BORDER_COLOR_INVALID
)
1922 bool bEnableDynamicControlBorder
= lcl_shouldUseDynamicControlBorder(
1923 xModelProps
.get(), xModelProps
->getPropertyValue( FM_PROP_DYNAMIC_CONTROL_BORDER
) );
1924 if ( bEnableDynamicControlBorder
)
1925 m_pControlBorderManager
->enableDynamicBorderColor();
1927 m_pControlBorderManager
->disableDynamicBorderColor();
1929 sal_Int32 nColor
= 0;
1930 if ( xModelProps
->getPropertyValue( FM_PROP_CONTROL_BORDER_COLOR_FOCUS
) >>= nColor
)
1931 m_pControlBorderManager
->setStatusColor( CONTROL_STATUS_FOCUSED
, nColor
);
1932 if ( xModelProps
->getPropertyValue( FM_PROP_CONTROL_BORDER_COLOR_MOUSE
) >>= nColor
)
1933 m_pControlBorderManager
->setStatusColor( CONTROL_STATUS_MOUSE_HOVER
, nColor
);
1934 if ( xModelProps
->getPropertyValue( FM_PROP_CONTROL_BORDER_COLOR_INVALID
) >>= nColor
)
1935 m_pControlBorderManager
->setStatusColor( CONTROL_STATUS_INVALID
, nColor
);
1939 catch( const Exception
& )
1941 DBG_UNHANDLED_EXCEPTION();
1946 Reference
< XTabControllerModel
> FormController::getModel() throw( RuntimeException
, std::exception
)
1948 ::osl::MutexGuard
aGuard( m_aMutex
);
1949 impl_checkDisposed_throw();
1951 DBG_ASSERT(m_xTabController
.is(), "FormController::getModel : invalid aggregate !");
1952 if (!m_xTabController
.is())
1953 return Reference
< XTabControllerModel
> ();
1954 return m_xTabController
->getModel();
1958 void FormController::addToEventAttacher(const Reference
< XControl
> & xControl
)
1960 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1961 OSL_ENSURE( xControl
.is(), "FormController::addToEventAttacher: invalid control - how did you reach this?" );
1962 if ( !xControl
.is() )
1963 return; /* throw IllegalArgumentException(); */
1965 // anmelden beim Eventattacher
1966 Reference
< XFormComponent
> xComp(xControl
->getModel(), UNO_QUERY
);
1967 if (xComp
.is() && m_xModelAsIndex
.is())
1969 // Und die Position des ControlModel darin suchen
1970 sal_uInt32 nPos
= m_xModelAsIndex
->getCount();
1971 Reference
< XFormComponent
> xTemp
;
1974 m_xModelAsIndex
->getByIndex(--nPos
) >>= xTemp
;
1975 if ((XFormComponent
*)xComp
.get() == (XFormComponent
*)xTemp
.get())
1977 m_xModelAsManager
->attach( nPos
, Reference
<XInterface
>( xControl
, UNO_QUERY
), makeAny(xControl
) );
1985 void FormController::removeFromEventAttacher(const Reference
< XControl
> & xControl
)
1987 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1988 OSL_ENSURE( xControl
.is(), "FormController::removeFromEventAttacher: invalid control - how did you reach this?" );
1989 if ( !xControl
.is() )
1990 return; /* throw IllegalArgumentException(); */
1992 // abmelden beim Eventattacher
1993 Reference
< XFormComponent
> xComp(xControl
->getModel(), UNO_QUERY
);
1994 if ( xComp
.is() && m_xModelAsIndex
.is() )
1996 // Und die Position des ControlModel darin suchen
1997 sal_uInt32 nPos
= m_xModelAsIndex
->getCount();
1998 Reference
< XFormComponent
> xTemp
;
2001 m_xModelAsIndex
->getByIndex(--nPos
) >>= xTemp
;
2002 if ((XFormComponent
*)xComp
.get() == (XFormComponent
*)xTemp
.get())
2004 m_xModelAsManager
->detach( nPos
, Reference
<XInterface
>( xControl
, UNO_QUERY
) );
2012 void FormController::setContainer(const Reference
< XControlContainer
> & xContainer
) throw( RuntimeException
, std::exception
)
2014 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2015 Reference
< XTabControllerModel
> xTabModel(getModel());
2016 DBG_ASSERT(xTabModel
.is() || !xContainer
.is(), "No Model defined");
2017 // if we have a new container we need a model
2018 DBG_ASSERT(m_xTabController
.is(), "FormController::setContainer : invalid aggregate !");
2020 ::osl::MutexGuard
aGuard( m_aMutex
);
2021 Reference
< XContainer
> xCurrentContainer
;
2022 if (m_xTabController
.is())
2023 xCurrentContainer
= Reference
< XContainer
> (m_xTabController
->getContainer(), UNO_QUERY
);
2024 if (xCurrentContainer
.is())
2026 xCurrentContainer
->removeContainerListener(this);
2028 if ( m_aTabActivationIdle
.IsActive() )
2029 m_aTabActivationIdle
.Stop();
2031 // clear the filter map
2032 ::std::for_each( m_aFilterComponents
.begin(), m_aFilterComponents
.end(), RemoveComponentTextListener( this ) );
2033 m_aFilterComponents
.clear();
2035 // einsammeln der Controls
2036 const Reference
< XControl
>* pControls
= m_aControls
.getConstArray();
2037 const Reference
< XControl
>* pControlsEnd
= pControls
+ m_aControls
.getLength();
2038 while ( pControls
!= pControlsEnd
)
2039 implControlRemoved( *pControls
++, true );
2041 // Datenbank spezifische Dinge vornehmen
2042 if (m_bDBConnection
&& isListeningForChanges())
2045 m_aControls
.realloc( 0 );
2048 if (m_xTabController
.is())
2049 m_xTabController
->setContainer(xContainer
);
2051 // Welche Controls gehoeren zum Container ?
2052 if (xContainer
.is() && xTabModel
.is())
2054 Sequence
< Reference
< XControlModel
> > aModels
= xTabModel
->getControlModels();
2055 const Reference
< XControlModel
> * pModels
= aModels
.getConstArray();
2056 Sequence
< Reference
< XControl
> > aAllControls
= xContainer
->getControls();
2058 sal_Int32 nCount
= aModels
.getLength();
2059 m_aControls
= Sequence
< Reference
< XControl
> >( nCount
);
2060 Reference
< XControl
> * pControls
= m_aControls
.getArray();
2062 // einsammeln der Controls
2064 for (i
= 0, j
= 0; i
< nCount
; ++i
, ++pModels
)
2066 Reference
< XControl
> xControl
= findControl( aAllControls
, *pModels
, false, true );
2067 if ( xControl
.is() )
2069 pControls
[j
++] = xControl
;
2070 implControlInserted( xControl
, true );
2074 // not every model had an associated control
2076 m_aControls
.realloc(j
);
2078 // am Container horchen
2079 Reference
< XContainer
> xNewContainer(xContainer
, UNO_QUERY
);
2080 if (xNewContainer
.is())
2081 xNewContainer
->addContainerListener(this);
2083 // Datenbank spezifische Dinge vornehmen
2084 if (m_bDBConnection
)
2086 m_bLocked
= determineLockState();
2092 // befinden sich die Controls in der richtigen Reihenfolge
2093 m_bControlsSorted
= true;
2097 Reference
< XControlContainer
> FormController::getContainer() throw( RuntimeException
, std::exception
)
2099 ::osl::MutexGuard
aGuard( m_aMutex
);
2100 impl_checkDisposed_throw();
2102 DBG_ASSERT(m_xTabController
.is(), "FormController::getContainer : invalid aggregate !");
2103 if (!m_xTabController
.is())
2104 return Reference
< XControlContainer
> ();
2105 return m_xTabController
->getContainer();
2109 Sequence
< Reference
< XControl
> > FormController::getControls() throw( RuntimeException
, std::exception
)
2111 ::osl::MutexGuard
aGuard( m_aMutex
);
2112 impl_checkDisposed_throw();
2114 if (!m_bControlsSorted
)
2116 Reference
< XTabControllerModel
> xModel
= getModel();
2120 Sequence
< Reference
< XControlModel
> > aControlModels
= xModel
->getControlModels();
2121 const Reference
< XControlModel
> * pModels
= aControlModels
.getConstArray();
2122 sal_Int32 nModels
= aControlModels
.getLength();
2124 Sequence
< Reference
< XControl
> > aNewControls(nModels
);
2126 Reference
< XControl
> * pControls
= aNewControls
.getArray();
2127 Reference
< XControl
> xControl
;
2129 // Umsortieren der Controls entsprechend der TabReihenfolge
2131 for (sal_Int32 i
= 0; i
< nModels
; ++i
, ++pModels
)
2133 xControl
= findControl( m_aControls
, *pModels
, true, true );
2134 if ( xControl
.is() )
2135 pControls
[j
++] = xControl
;
2138 // not every model had an associated control
2140 aNewControls
.realloc( j
);
2142 m_aControls
= aNewControls
;
2143 m_bControlsSorted
= true;
2149 void FormController::autoTabOrder() throw( RuntimeException
, std::exception
)
2151 ::osl::MutexGuard
aGuard( m_aMutex
);
2152 impl_checkDisposed_throw();
2154 DBG_ASSERT(m_xTabController
.is(), "FormController::autoTabOrder : invalid aggregate !");
2155 if (m_xTabController
.is())
2156 m_xTabController
->autoTabOrder();
2160 void FormController::activateTabOrder() throw( RuntimeException
, std::exception
)
2162 ::osl::MutexGuard
aGuard( m_aMutex
);
2163 impl_checkDisposed_throw();
2165 DBG_ASSERT(m_xTabController
.is(), "FormController::activateTabOrder : invalid aggregate !");
2166 if (m_xTabController
.is())
2167 m_xTabController
->activateTabOrder();
2171 void FormController::setControlLock(const Reference
< XControl
> & xControl
)
2173 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2174 bool bLocked
= isLocked();
2177 // a.) wenn der ganze Datensatz gesperrt ist
2178 // b.) wenn das zugehoerige Feld gespeert ist
2179 Reference
< XBoundControl
> xBound(xControl
, UNO_QUERY
);
2180 if (xBound
.is() && (( (bLocked
&& bLocked
!= bool(xBound
->getLock())) ||
2181 !bLocked
))) // beim entlocken immer einzelne Felder ueberprüfen
2183 // gibt es eine Datenquelle
2184 Reference
< XPropertySet
> xSet(xControl
->getModel(), UNO_QUERY
);
2185 if (xSet
.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD
, xSet
))
2187 // wie sieht mit den Properties ReadOnly und Enable aus
2189 if (::comphelper::hasProperty(FM_PROP_ENABLED
, xSet
))
2190 bTouch
= ::comphelper::getBOOL(xSet
->getPropertyValue(FM_PROP_ENABLED
));
2191 if (::comphelper::hasProperty(FM_PROP_READONLY
, xSet
))
2192 bTouch
= !::comphelper::getBOOL(xSet
->getPropertyValue(FM_PROP_READONLY
));
2196 Reference
< XPropertySet
> xField
;
2197 xSet
->getPropertyValue(FM_PROP_BOUNDFIELD
) >>= xField
;
2201 xBound
->setLock(bLocked
);
2206 Any aVal
= xField
->getPropertyValue(FM_PROP_ISREADONLY
);
2207 if (aVal
.hasValue() && ::comphelper::getBOOL(aVal
))
2208 xBound
->setLock(sal_True
);
2210 xBound
->setLock(bLocked
);
2212 catch( const Exception
& )
2214 DBG_UNHANDLED_EXCEPTION();
2225 void FormController::setLocks()
2227 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2228 // alle Controls, die mit einer Datenquelle verbunden sind locken/unlocken
2229 const Reference
< XControl
>* pControls
= m_aControls
.getConstArray();
2230 const Reference
< XControl
>* pControlsEnd
= pControls
+ m_aControls
.getLength();
2231 while ( pControls
!= pControlsEnd
)
2232 setControlLock( *pControls
++ );
2238 bool lcl_shouldListenForModifications( const Reference
< XControl
>& _rxControl
, const Reference
< XPropertyChangeListener
>& _rxBoundFieldListener
)
2240 bool bShould
= false;
2242 Reference
< XBoundComponent
> xBound( _rxControl
, UNO_QUERY
);
2247 else if ( _rxControl
.is() )
2249 Reference
< XPropertySet
> xModelProps( _rxControl
->getModel(), UNO_QUERY
);
2250 if ( xModelProps
.is() && ::comphelper::hasProperty( FM_PROP_BOUNDFIELD
, xModelProps
) )
2252 Reference
< XPropertySet
> xField
;
2253 xModelProps
->getPropertyValue( FM_PROP_BOUNDFIELD
) >>= xField
;
2254 bShould
= xField
.is();
2256 if ( !bShould
&& _rxBoundFieldListener
.is() )
2257 xModelProps
->addPropertyChangeListener( FM_PROP_BOUNDFIELD
, _rxBoundFieldListener
);
2266 void FormController::startControlModifyListening(const Reference
< XControl
> & xControl
)
2268 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2270 bool bModifyListening
= lcl_shouldListenForModifications( xControl
, this );
2273 while ( bModifyListening
)
2275 Reference
< XModifyBroadcaster
> xMod(xControl
, UNO_QUERY
);
2278 xMod
->addModifyListener(this);
2282 // alle die Text um vorzeitig ein modified zu erkennen
2283 Reference
< XTextComponent
> xText(xControl
, UNO_QUERY
);
2286 xText
->addTextListener(this);
2290 Reference
< XCheckBox
> xBox(xControl
, UNO_QUERY
);
2293 xBox
->addItemListener(this);
2297 Reference
< XComboBox
> xCbBox(xControl
, UNO_QUERY
);
2300 xCbBox
->addItemListener(this);
2304 Reference
< XListBox
> xListBox(xControl
, UNO_QUERY
);
2307 xListBox
->addItemListener(this);
2315 void FormController::stopControlModifyListening(const Reference
< XControl
> & xControl
)
2317 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2319 bool bModifyListening
= lcl_shouldListenForModifications( xControl
, NULL
);
2321 // kuenstliches while
2322 while (bModifyListening
)
2324 Reference
< XModifyBroadcaster
> xMod(xControl
, UNO_QUERY
);
2327 xMod
->removeModifyListener(this);
2330 // alle die Text um vorzeitig ein modified zu erkennen
2331 Reference
< XTextComponent
> xText(xControl
, UNO_QUERY
);
2334 xText
->removeTextListener(this);
2338 Reference
< XCheckBox
> xBox(xControl
, UNO_QUERY
);
2341 xBox
->removeItemListener(this);
2345 Reference
< XComboBox
> xCbBox(xControl
, UNO_QUERY
);
2348 xCbBox
->removeItemListener(this);
2352 Reference
< XListBox
> xListBox(xControl
, UNO_QUERY
);
2355 xListBox
->removeItemListener(this);
2363 void FormController::startListening()
2365 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2366 m_bModified
= false;
2368 // jetzt anmelden bei gebundenen feldern
2369 const Reference
< XControl
>* pControls
= m_aControls
.getConstArray();
2370 const Reference
< XControl
>* pControlsEnd
= pControls
+ m_aControls
.getLength();
2371 while ( pControls
!= pControlsEnd
)
2372 startControlModifyListening( *pControls
++ );
2376 void FormController::stopListening()
2378 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2379 m_bModified
= false;
2381 // jetzt anmelden bei gebundenen feldern
2382 const Reference
< XControl
>* pControls
= m_aControls
.getConstArray();
2383 const Reference
< XControl
>* pControlsEnd
= pControls
+ m_aControls
.getLength();
2384 while ( pControls
!= pControlsEnd
)
2385 stopControlModifyListening( *pControls
++ );
2390 Reference
< XControl
> FormController::findControl(Sequence
< Reference
< XControl
> >& _rControls
, const Reference
< XControlModel
> & xCtrlModel
,bool _bRemove
,bool _bOverWrite
) const
2392 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2393 DBG_ASSERT( xCtrlModel
.is(), "findControl - welches ?!" );
2395 Reference
< XControl
>* pControls
= _rControls
.getArray();
2396 Reference
< XControlModel
> xModel
;
2397 for ( sal_Int32 i
= 0, nCount
= _rControls
.getLength(); i
< nCount
; ++i
, ++pControls
)
2399 if ( pControls
->is() )
2401 xModel
= (*pControls
)->getModel();
2402 if ( xModel
.get() == xCtrlModel
.get() )
2404 Reference
< XControl
> xControl( *pControls
);
2406 ::comphelper::removeElementAt( _rControls
, i
);
2407 else if ( _bOverWrite
)
2413 return Reference
< XControl
> ();
2417 void FormController::implControlInserted( const Reference
< XControl
>& _rxControl
, bool _bAddToEventAttacher
)
2419 Reference
< XWindow
> xWindow( _rxControl
, UNO_QUERY
);
2422 xWindow
->addFocusListener( this );
2423 xWindow
->addMouseListener( this );
2425 if ( _bAddToEventAttacher
)
2426 addToEventAttacher( _rxControl
);
2429 // add a dispatch interceptor to the control (if supported)
2430 Reference
< XDispatchProviderInterception
> xInterception( _rxControl
, UNO_QUERY
);
2431 if ( xInterception
.is() )
2432 createInterceptor( xInterception
);
2434 if ( _rxControl
.is() )
2436 Reference
< XControlModel
> xModel( _rxControl
->getModel() );
2438 // we want to know about the reset of the model of our controls
2439 // (for correctly resetting m_bModified)
2440 Reference
< XReset
> xReset( xModel
, UNO_QUERY
);
2442 xReset
->addResetListener( this );
2444 // and we want to know about the validity, to visually indicate it
2445 Reference
< XValidatableFormComponent
> xValidatable( xModel
, UNO_QUERY
);
2446 if ( xValidatable
.is() )
2448 xValidatable
->addFormComponentValidityListener( this );
2449 m_pControlBorderManager
->validityChanged( _rxControl
, xValidatable
);
2456 void FormController::implControlRemoved( const Reference
< XControl
>& _rxControl
, bool _bRemoveFromEventAttacher
)
2458 Reference
< XWindow
> xWindow( _rxControl
, UNO_QUERY
);
2461 xWindow
->removeFocusListener( this );
2462 xWindow
->removeMouseListener( this );
2464 if ( _bRemoveFromEventAttacher
)
2465 removeFromEventAttacher( _rxControl
);
2468 Reference
< XDispatchProviderInterception
> xInterception( _rxControl
, UNO_QUERY
);
2469 if ( xInterception
.is() )
2470 deleteInterceptor( xInterception
);
2472 if ( _rxControl
.is() )
2474 Reference
< XControlModel
> xModel( _rxControl
->getModel() );
2476 Reference
< XReset
> xReset( xModel
, UNO_QUERY
);
2478 xReset
->removeResetListener( this );
2480 Reference
< XValidatableFormComponent
> xValidatable( xModel
, UNO_QUERY
);
2481 if ( xValidatable
.is() )
2482 xValidatable
->removeFormComponentValidityListener( this );
2487 void FormController::implSetCurrentControl( const Reference
< XControl
>& _rxControl
)
2489 if ( m_xCurrentControl
.get() == _rxControl
.get() )
2492 Reference
< XGridControl
> xGridControl( m_xCurrentControl
, UNO_QUERY
);
2493 if ( xGridControl
.is() )
2494 xGridControl
->removeGridControlListener( this );
2496 m_xCurrentControl
= _rxControl
;
2498 xGridControl
.set( m_xCurrentControl
, UNO_QUERY
);
2499 if ( xGridControl
.is() )
2500 xGridControl
->addGridControlListener( this );
2504 void FormController::insertControl(const Reference
< XControl
> & xControl
)
2506 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2507 m_bControlsSorted
= false;
2508 m_aControls
.realloc(m_aControls
.getLength() + 1);
2509 m_aControls
.getArray()[m_aControls
.getLength() - 1] = xControl
;
2511 if ( m_pColumnInfoCache
.get() )
2512 m_pColumnInfoCache
->deinitializeControls();
2514 implControlInserted( xControl
, m_bAttachEvents
);
2516 if (m_bDBConnection
&& !m_bFiltering
)
2517 setControlLock(xControl
);
2519 if (isListeningForChanges() && m_bAttachEvents
)
2520 startControlModifyListening( xControl
);
2524 void FormController::removeControl(const Reference
< XControl
> & xControl
)
2526 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2527 const Reference
< XControl
>* pControls
= m_aControls
.getConstArray();
2528 const Reference
< XControl
>* pControlsEnd
= pControls
+ m_aControls
.getLength();
2529 while ( pControls
!= pControlsEnd
)
2531 if ( xControl
.get() == (*pControls
++).get() )
2533 ::comphelper::removeElementAt( m_aControls
, pControls
- m_aControls
.getConstArray() - 1 );
2538 FilterComponents::iterator componentPos
= ::std::find( m_aFilterComponents
.begin(), m_aFilterComponents
.end(), xControl
);
2539 if ( componentPos
!= m_aFilterComponents
.end() )
2540 m_aFilterComponents
.erase( componentPos
);
2542 implControlRemoved( xControl
, m_bDetachEvents
);
2544 if ( isListeningForChanges() && m_bDetachEvents
)
2545 stopControlModifyListening( xControl
);
2550 void FormController::loaded(const EventObject
& rEvent
) throw( RuntimeException
, std::exception
)
2552 OSL_ENSURE( rEvent
.Source
== m_xModelAsIndex
, "FormController::loaded: where did this come from?" );
2554 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2555 ::osl::MutexGuard
aGuard( m_aMutex
);
2556 Reference
< XRowSet
> xForm(rEvent
.Source
, UNO_QUERY
);
2557 // do we have a connected data source
2558 if (xForm
.is() && getConnection(xForm
).is())
2560 Reference
< XPropertySet
> xSet(xForm
, UNO_QUERY
);
2563 Any aVal
= xSet
->getPropertyValue(FM_PROP_CYCLE
);
2564 sal_Int32 aVal2
= 0;
2565 ::cppu::enum2int(aVal2
,aVal
);
2566 m_bCycle
= !aVal
.hasValue() || aVal2
== TabulatorCycle_RECORDS
;
2567 m_bCanUpdate
= canUpdate(xSet
);
2568 m_bCanInsert
= canInsert(xSet
);
2569 m_bCurrentRecordModified
= ::comphelper::getBOOL(xSet
->getPropertyValue(FM_PROP_ISMODIFIED
));
2570 m_bCurrentRecordNew
= ::comphelper::getBOOL(xSet
->getPropertyValue(FM_PROP_ISNEW
));
2572 startFormListening( xSet
, false );
2574 // set the locks for the current controls
2575 if (getContainer().is())
2577 m_aLoadEvent
.Call();
2582 m_bCanInsert
= m_bCanUpdate
= m_bCycle
= false;
2583 m_bCurrentRecordModified
= false;
2584 m_bCurrentRecordNew
= false;
2587 m_bDBConnection
= true;
2591 m_bDBConnection
= false;
2592 m_bCanInsert
= m_bCanUpdate
= m_bCycle
= false;
2593 m_bCurrentRecordModified
= false;
2594 m_bCurrentRecordNew
= false;
2598 Reference
< XColumnsSupplier
> xFormColumns( xForm
, UNO_QUERY
);
2599 m_pColumnInfoCache
.reset( xFormColumns
.is() ? new ColumnInfoCache( xFormColumns
) : NULL
);
2601 updateAllDispatchers();
2605 void FormController::updateAllDispatchers() const
2608 m_aFeatureDispatchers
.begin(),
2609 m_aFeatureDispatchers
.end(),
2611 UpdateAllListeners(),
2612 ::o3tl::select2nd
< DispatcherContainer::value_type
>()
2618 IMPL_LINK_NOARG(FormController
, OnLoad
)
2620 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2621 m_bLocked
= determineLockState();
2628 // just one exception toggle the auto values
2629 if (m_bCurrentRecordNew
)
2630 toggleAutoFields(true);
2636 void FormController::unloaded(const EventObject
& /*rEvent*/) throw( RuntimeException
, std::exception
)
2638 ::osl::MutexGuard
aGuard( m_aMutex
);
2639 impl_checkDisposed_throw();
2641 updateAllDispatchers();
2645 void FormController::reloading(const EventObject
& /*aEvent*/) throw( RuntimeException
, std::exception
)
2647 ::osl::MutexGuard
aGuard( m_aMutex
);
2648 impl_checkDisposed_throw();
2650 // do the same like in unloading
2651 // just one exception toggle the auto values
2652 m_aToggleEvent
.CancelPendingCall();
2657 void FormController::reloaded(const EventObject
& aEvent
) throw( RuntimeException
, std::exception
)
2659 ::osl::MutexGuard
aGuard( m_aMutex
);
2660 impl_checkDisposed_throw();
2666 void FormController::unloading(const EventObject
& /*aEvent*/) throw( RuntimeException
, std::exception
)
2668 ::osl::MutexGuard
aGuard( m_aMutex
);
2669 impl_checkDisposed_throw();
2675 void FormController::unload() throw( RuntimeException
)
2677 ::osl::MutexGuard
aGuard( m_aMutex
);
2678 impl_checkDisposed_throw();
2680 m_aLoadEvent
.CancelPendingCall();
2682 // be sure not to have autofields
2683 if (m_bCurrentRecordNew
)
2684 toggleAutoFields(false);
2686 // remove bound field listing again
2687 removeBoundFieldListener();
2689 if (m_bDBConnection
&& isListeningForChanges())
2692 Reference
< XPropertySet
> xSet( m_xModelAsIndex
, UNO_QUERY
);
2693 if ( m_bDBConnection
&& xSet
.is() )
2694 stopFormListening( xSet
, false );
2696 m_bDBConnection
= false;
2697 m_bCanInsert
= m_bCanUpdate
= m_bCycle
= false;
2698 m_bCurrentRecordModified
= m_bCurrentRecordNew
= m_bLocked
= false;
2700 m_pColumnInfoCache
.reset();
2704 void FormController::removeBoundFieldListener()
2706 const Reference
< XControl
>* pControls
= m_aControls
.getConstArray();
2707 const Reference
< XControl
>* pControlsEnd
= pControls
+ m_aControls
.getLength();
2708 while ( pControls
!= pControlsEnd
)
2710 Reference
< XPropertySet
> xProp( *pControls
++, UNO_QUERY
);
2712 xProp
->removePropertyChangeListener( FM_PROP_BOUNDFIELD
, this );
2717 void FormController::startFormListening( const Reference
< XPropertySet
>& _rxForm
, bool _bPropertiesOnly
)
2721 if ( m_bCanInsert
|| m_bCanUpdate
) // form can be modified
2723 _rxForm
->addPropertyChangeListener( FM_PROP_ISNEW
, this );
2724 _rxForm
->addPropertyChangeListener( FM_PROP_ISMODIFIED
, this );
2726 if ( !_bPropertiesOnly
)
2728 // set the Listener for UI interaction
2729 Reference
< XRowSetApproveBroadcaster
> xApprove( _rxForm
, UNO_QUERY
);
2730 if ( xApprove
.is() )
2731 xApprove
->addRowSetApproveListener( this );
2733 // listener for row set changes
2734 Reference
< XRowSet
> xRowSet( _rxForm
, UNO_QUERY
);
2736 xRowSet
->addRowSetListener( this );
2740 Reference
< XPropertySetInfo
> xInfo
= _rxForm
->getPropertySetInfo();
2741 if ( xInfo
.is() && xInfo
->hasPropertyByName( FM_PROP_DYNAMIC_CONTROL_BORDER
) )
2742 _rxForm
->addPropertyChangeListener( FM_PROP_DYNAMIC_CONTROL_BORDER
, this );
2744 catch( const Exception
& )
2746 DBG_UNHANDLED_EXCEPTION();
2751 void FormController::stopFormListening( const Reference
< XPropertySet
>& _rxForm
, bool _bPropertiesOnly
)
2755 if ( m_bCanInsert
|| m_bCanUpdate
)
2757 _rxForm
->removePropertyChangeListener( FM_PROP_ISNEW
, this );
2758 _rxForm
->removePropertyChangeListener( FM_PROP_ISMODIFIED
, this );
2760 if ( !_bPropertiesOnly
)
2762 Reference
< XRowSetApproveBroadcaster
> xApprove( _rxForm
, UNO_QUERY
);
2764 xApprove
->removeRowSetApproveListener(this);
2766 Reference
< XRowSet
> xRowSet( _rxForm
, UNO_QUERY
);
2768 xRowSet
->removeRowSetListener( this );
2772 Reference
< XPropertySetInfo
> xInfo
= _rxForm
->getPropertySetInfo();
2773 if ( xInfo
.is() && xInfo
->hasPropertyByName( FM_PROP_DYNAMIC_CONTROL_BORDER
) )
2774 _rxForm
->removePropertyChangeListener( FM_PROP_DYNAMIC_CONTROL_BORDER
, this );
2776 catch( const Exception
& )
2778 DBG_UNHANDLED_EXCEPTION();
2782 // com::sun::star::sdbc::XRowSetListener
2784 void FormController::cursorMoved(const EventObject
& /*event*/) throw( RuntimeException
, std::exception
)
2786 ::osl::MutexGuard
aGuard( m_aMutex
);
2787 impl_checkDisposed_throw();
2789 // toggle the locking ?
2790 if (m_bLocked
!= determineLockState())
2792 m_bLocked
= !m_bLocked
;
2794 if (isListeningForChanges())
2800 // neither the current control nor the current record are modified anymore
2801 m_bCurrentRecordModified
= m_bModified
= false;
2805 void FormController::rowChanged(const EventObject
& /*event*/) throw( RuntimeException
, std::exception
)
2807 // not interested in ...
2810 void FormController::rowSetChanged(const EventObject
& /*event*/) throw( RuntimeException
, std::exception
)
2812 // not interested in ...
2816 // XContainerListener
2818 void SAL_CALL
FormController::elementInserted(const ContainerEvent
& evt
) throw( RuntimeException
, std::exception
)
2820 ::osl::MutexGuard
aGuard( m_aMutex
);
2821 impl_checkDisposed_throw();
2823 Reference
< XControl
> xControl( evt
.Element
, UNO_QUERY
);
2824 if ( !xControl
.is() )
2827 Reference
< XFormComponent
> xModel(xControl
->getModel(), UNO_QUERY
);
2828 if (xModel
.is() && m_xModelAsIndex
== xModel
->getParent())
2830 insertControl(xControl
);
2832 if ( m_aTabActivationIdle
.IsActive() )
2833 m_aTabActivationIdle
.Stop();
2835 m_aTabActivationIdle
.Start();
2837 // are we in filtermode and a XModeSelector has inserted an element
2838 else if (m_bFiltering
&& Reference
< XModeSelector
> (evt
.Source
, UNO_QUERY
).is())
2840 xModel
= Reference
< XFormComponent
> (evt
.Source
, UNO_QUERY
);
2841 if (xModel
.is() && m_xModelAsIndex
== xModel
->getParent())
2843 Reference
< XPropertySet
> xSet(xControl
->getModel(), UNO_QUERY
);
2844 if (xSet
.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD
, xSet
))
2846 // does the model use a bound field ?
2847 Reference
< XPropertySet
> xField
;
2848 xSet
->getPropertyValue(FM_PROP_BOUNDFIELD
) >>= xField
;
2850 Reference
< XTextComponent
> xText(xControl
, UNO_QUERY
);
2851 // may we filter the field?
2852 if (xText
.is() && xField
.is() && ::comphelper::hasProperty(FM_PROP_SEARCHABLE
, xField
) &&
2853 ::comphelper::getBOOL(xField
->getPropertyValue(FM_PROP_SEARCHABLE
)))
2855 m_aFilterComponents
.push_back( xText
);
2856 xText
->addTextListener( this );
2864 void SAL_CALL
FormController::elementReplaced(const ContainerEvent
& evt
) throw( RuntimeException
, std::exception
)
2866 // simulate an elementRemoved
2867 ContainerEvent
aRemoveEvent( evt
);
2868 aRemoveEvent
.Element
= evt
.ReplacedElement
;
2869 aRemoveEvent
.ReplacedElement
= Any();
2870 elementRemoved( aRemoveEvent
);
2872 // simulate an elementInserted
2873 ContainerEvent
aInsertEvent( evt
);
2874 aInsertEvent
.ReplacedElement
= Any();
2875 elementInserted( aInsertEvent
);
2879 void SAL_CALL
FormController::elementRemoved(const ContainerEvent
& evt
) throw( RuntimeException
, std::exception
)
2881 ::osl::MutexGuard
aGuard( m_aMutex
);
2882 impl_checkDisposed_throw();
2884 Reference
< XControl
> xControl
;
2885 evt
.Element
>>= xControl
;
2889 Reference
< XFormComponent
> xModel(xControl
->getModel(), UNO_QUERY
);
2890 if (xModel
.is() && m_xModelAsIndex
== xModel
->getParent())
2892 removeControl(xControl
);
2893 // TabOrder nicht neu berechnen, da das intern schon funktionieren muss!
2895 // are we in filtermode and a XModeSelector has inserted an element
2896 else if (m_bFiltering
&& Reference
< XModeSelector
> (evt
.Source
, UNO_QUERY
).is())
2898 FilterComponents::iterator componentPos
= ::std::find(
2899 m_aFilterComponents
.begin(), m_aFilterComponents
.end(), xControl
);
2900 if ( componentPos
!= m_aFilterComponents
.end() )
2901 m_aFilterComponents
.erase( componentPos
);
2906 Reference
< XControl
> FormController::isInList(const Reference
< XWindowPeer
> & xPeer
) const
2908 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2909 const Reference
< XControl
>* pControls
= m_aControls
.getConstArray();
2911 sal_uInt32 nCtrls
= m_aControls
.getLength();
2912 for ( sal_uInt32 n
= 0; n
< nCtrls
&& xPeer
.is(); ++n
, ++pControls
)
2914 if ( pControls
->is() )
2916 Reference
< XVclWindowPeer
> xCtrlPeer( (*pControls
)->getPeer(), UNO_QUERY
);
2917 if ( ( xCtrlPeer
.get() == xPeer
.get() ) || xCtrlPeer
->isChild( xPeer
) )
2921 return Reference
< XControl
> ();
2925 void FormController::activateFirst() throw( RuntimeException
, std::exception
)
2927 ::osl::MutexGuard
aGuard( m_aMutex
);
2928 impl_checkDisposed_throw();
2930 DBG_ASSERT(m_xTabController
.is(), "FormController::activateFirst : invalid aggregate !");
2931 if (m_xTabController
.is())
2932 m_xTabController
->activateFirst();
2936 void FormController::activateLast() throw( RuntimeException
, std::exception
)
2938 ::osl::MutexGuard
aGuard( m_aMutex
);
2939 impl_checkDisposed_throw();
2941 DBG_ASSERT(m_xTabController
.is(), "FormController::activateLast : invalid aggregate !");
2942 if (m_xTabController
.is())
2943 m_xTabController
->activateLast();
2948 Reference
< XFormOperations
> SAL_CALL
FormController::getFormOperations() throw (RuntimeException
, std::exception
)
2950 ::osl::MutexGuard
aGuard( m_aMutex
);
2951 impl_checkDisposed_throw();
2953 return m_xFormOperations
;
2957 Reference
< XControl
> SAL_CALL
FormController::getCurrentControl() throw( RuntimeException
, std::exception
)
2959 ::osl::MutexGuard
aGuard( m_aMutex
);
2960 impl_checkDisposed_throw();
2961 return m_xCurrentControl
;
2965 void SAL_CALL
FormController::addActivateListener(const Reference
< XFormControllerListener
> & l
) throw( RuntimeException
, std::exception
)
2967 ::osl::MutexGuard
aGuard( m_aMutex
);
2968 impl_checkDisposed_throw();
2969 m_aActivateListeners
.addInterface(l
);
2972 void SAL_CALL
FormController::removeActivateListener(const Reference
< XFormControllerListener
> & l
) throw( RuntimeException
, std::exception
)
2974 ::osl::MutexGuard
aGuard( m_aMutex
);
2975 impl_checkDisposed_throw();
2976 m_aActivateListeners
.removeInterface(l
);
2980 void SAL_CALL
FormController::addChildController( const Reference
< XFormController
>& _ChildController
) throw( RuntimeException
, IllegalArgumentException
, std::exception
)
2982 ::osl::MutexGuard
aGuard( m_aMutex
);
2983 impl_checkDisposed_throw();
2985 if ( !_ChildController
.is() )
2986 throw IllegalArgumentException( OUString(), *this, 1 );
2987 // TODO: (localized) error message
2989 // the parent of our (to-be-)child must be our own model
2990 Reference
< XFormComponent
> xFormOfChild( _ChildController
->getModel(), UNO_QUERY
);
2991 if ( !xFormOfChild
.is() )
2992 throw IllegalArgumentException( OUString(), *this, 1 );
2993 // TODO: (localized) error message
2995 if ( xFormOfChild
->getParent() != m_xModelAsIndex
)
2996 throw IllegalArgumentException( OUString(), *this, 1 );
2997 // TODO: (localized) error message
2999 m_aChildren
.push_back( _ChildController
);
3000 _ChildController
->setParent( *this );
3002 // search the position of the model within the form
3003 sal_uInt32 nPos
= m_xModelAsIndex
->getCount();
3004 Reference
< XFormComponent
> xTemp
;
3007 m_xModelAsIndex
->getByIndex(--nPos
) >>= xTemp
;
3008 if ( xFormOfChild
== xTemp
)
3010 m_xModelAsManager
->attach( nPos
, Reference
<XInterface
>( _ChildController
, UNO_QUERY
), makeAny( _ChildController
) );
3017 Reference
< XFormControllerContext
> SAL_CALL
FormController::getContext() throw (RuntimeException
, std::exception
)
3019 ::osl::MutexGuard
aGuard( m_aMutex
);
3020 impl_checkDisposed_throw();
3021 return m_xFormControllerContext
;
3025 void SAL_CALL
FormController::setContext( const Reference
< XFormControllerContext
>& _context
) throw (RuntimeException
, std::exception
)
3027 ::osl::MutexGuard
aGuard( m_aMutex
);
3028 impl_checkDisposed_throw();
3029 m_xFormControllerContext
= _context
;
3033 Reference
< XInteractionHandler
> SAL_CALL
FormController::getInteractionHandler() throw (RuntimeException
, std::exception
)
3035 ::osl::MutexGuard
aGuard( m_aMutex
);
3036 impl_checkDisposed_throw();
3037 return m_xInteractionHandler
;
3041 void SAL_CALL
FormController::setInteractionHandler( const Reference
< XInteractionHandler
>& _interactionHandler
) throw (RuntimeException
, std::exception
)
3043 ::osl::MutexGuard
aGuard( m_aMutex
);
3044 impl_checkDisposed_throw();
3045 m_xInteractionHandler
= _interactionHandler
;
3049 void FormController::setFilter(::std::vector
<FmFieldInfo
>& rFieldInfos
)
3051 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
3052 // create the composer
3053 Reference
< XRowSet
> xForm(m_xModelAsIndex
, UNO_QUERY
);
3054 Reference
< XConnection
> xConnection(getConnection(xForm
));
3059 Reference
< XMultiServiceFactory
> xFactory( xConnection
, UNO_QUERY_THROW
);
3061 xFactory
->createInstance("com.sun.star.sdb.SingleSelectQueryComposer"),
3064 Reference
< XPropertySet
> xSet( xForm
, UNO_QUERY
);
3065 OUString sStatement
= ::comphelper::getString( xSet
->getPropertyValue( FM_PROP_ACTIVECOMMAND
) );
3066 OUString sFilter
= ::comphelper::getString( xSet
->getPropertyValue( FM_PROP_FILTER
) );
3067 m_xComposer
->setElementaryQuery( sStatement
);
3068 m_xComposer
->setFilter( sFilter
);
3070 catch( const Exception
& )
3072 DBG_UNHANDLED_EXCEPTION();
3076 if (m_xComposer
.is())
3078 Sequence
< Sequence
< PropertyValue
> > aFilterRows
= m_xComposer
->getStructuredFilter();
3080 // ok, we receive the list of filters as sequence of fieldnames, value
3081 // now we have to transform the fieldname into UI names, that could be a label of the field or
3082 // a aliasname or the fieldname itself
3084 // first adjust the field names if necessary
3085 Reference
< XNameAccess
> xQueryColumns
=
3086 Reference
< XColumnsSupplier
>( m_xComposer
, UNO_QUERY_THROW
)->getColumns();
3088 for (::std::vector
<FmFieldInfo
>::iterator iter
= rFieldInfos
.begin();
3089 iter
!= rFieldInfos
.end(); ++iter
)
3091 if ( xQueryColumns
->hasByName((*iter
).aFieldName
) )
3093 if ( (xQueryColumns
->getByName((*iter
).aFieldName
) >>= (*iter
).xField
) && (*iter
).xField
.is() )
3094 (*iter
).xField
->getPropertyValue(FM_PROP_REALNAME
) >>= (*iter
).aFieldName
;
3098 Reference
< XDatabaseMetaData
> xMetaData(xConnection
->getMetaData());
3099 // now transfer the filters into Value/TextComponent pairs
3100 ::comphelper::UStringMixEqual
aCompare(xMetaData
->storesMixedCaseQuotedIdentifiers());
3102 // need to parse criteria localized
3103 Reference
< XNumberFormatsSupplier
> xFormatSupplier( getNumberFormats(xConnection
, true));
3104 Reference
< XNumberFormatter
> xFormatter
= NumberFormatter::create(m_xComponentContext
);
3105 xFormatter
->attachNumberFormatsSupplier(xFormatSupplier
);
3106 Locale aAppLocale
= Application::GetSettings().GetUILanguageTag().getLocale();
3107 const LocaleDataWrapper
& rLocaleWrapper( Application::GetSettings().GetUILocaleDataWrapper() );
3108 /* FIXME: casting this to sal_Char is plain wrong and of course only
3109 * works for ASCII separators, but
3110 * pParseNode->parseNodeToPredicateStr() expects a sal_Char. Fix it
3112 sal_Char cDecimalSeparator
= (sal_Char
)rLocaleWrapper
.getNumDecimalSep()[0];
3113 SAL_WARN_IF( (sal_Unicode
)cDecimalSeparator
!= rLocaleWrapper
.getNumDecimalSep()[0],
3114 "svx.form", "FormController::setFilter: wrong cast of decimal separator to sal_Char!");
3116 // retrieving the filter
3117 const Sequence
< PropertyValue
>* pRow
= aFilterRows
.getConstArray();
3118 for (sal_Int32 i
= 0, nLen
= aFilterRows
.getLength(); i
< nLen
; ++i
)
3122 // search a field for the given name
3123 const PropertyValue
* pRefValues
= pRow
[i
].getConstArray();
3124 for (sal_Int32 j
= 0, nLen1
= pRow
[i
].getLength(); j
< nLen1
; j
++)
3126 // look for the text component
3127 Reference
< XPropertySet
> xField
;
3130 Reference
< XPropertySet
> xSet
;
3133 // first look with the given name
3134 if (xQueryColumns
->hasByName(pRefValues
[j
].Name
))
3136 xQueryColumns
->getByName(pRefValues
[j
].Name
) >>= xSet
;
3139 xSet
->getPropertyValue("RealName") >>= aRealName
;
3141 // compare the condition field name and the RealName
3142 if (aCompare(aRealName
, pRefValues
[j
].Name
))
3147 // no we have to check every column to find the realname
3148 Reference
< XIndexAccess
> xColumnsByIndex(xQueryColumns
, UNO_QUERY
);
3149 for (sal_Int32 n
= 0, nCount
= xColumnsByIndex
->getCount(); n
< nCount
; n
++)
3151 xColumnsByIndex
->getByIndex(n
) >>= xSet
;
3152 xSet
->getPropertyValue("RealName") >>= aRealName
;
3153 if (aCompare(aRealName
, pRefValues
[j
].Name
))
3155 // get the column by its alias
3164 catch (const Exception
&)
3169 // find the text component
3170 for (::std::vector
<FmFieldInfo
>::iterator iter
= rFieldInfos
.begin();
3171 iter
!= rFieldInfos
.end(); ++iter
)
3173 // we found the field so insert a new entry to the filter row
3174 if ((*iter
).xField
== xField
)
3176 // do we already have the control ?
3177 if (aRow
.find((*iter
).xText
) != aRow
.end())
3179 OUString aCompText
= aRow
[(*iter
).xText
];
3181 OString aVal
= m_pParser
->getContext().getIntlKeywordAscii(IParseContext::KEY_AND
);
3182 aCompText
+= OUString(aVal
.getStr(),aVal
.getLength(),RTL_TEXTENCODING_ASCII_US
);
3184 aCompText
+= ::comphelper::getString(pRefValues
[j
].Value
);
3185 aRow
[(*iter
).xText
] = aCompText
;
3189 OUString sPredicate
,sErrorMsg
;
3190 pRefValues
[j
].Value
>>= sPredicate
;
3191 std::shared_ptr
< OSQLParseNode
> pParseNode
= predicateTree(sErrorMsg
, sPredicate
, xFormatter
, xField
);
3192 if ( pParseNode
!= nullptr )
3195 pParseNode
->parseNodeToPredicateStr( sCriteria
3202 ,getParseContext());
3203 aRow
[(*iter
).xText
] = sCriteria
;
3213 impl_addFilterRow( aRow
);
3217 // now set the filter controls
3218 for ( ::std::vector
<FmFieldInfo
>::iterator field
= rFieldInfos
.begin();
3219 field
!= rFieldInfos
.end();
3223 m_aFilterComponents
.push_back( field
->xText
);
3228 void FormController::startFiltering()
3230 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
3232 Reference
< XConnection
> xConnection( getConnection( Reference
< XRowSet
>( m_xModelAsIndex
, UNO_QUERY
) ) );
3233 if ( !xConnection
.is() )
3234 // nothing to do - can't filter a form which is not connected
3237 // stop listening for controls
3238 if (isListeningForChanges())
3241 m_bFiltering
= true;
3243 // as we don't want new controls to be attached to the scripting environment
3244 // we change attach flags
3245 m_bAttachEvents
= false;
3247 // Austauschen der Kontrols fuer das aktuelle Formular
3248 Sequence
< Reference
< XControl
> > aControlsCopy( m_aControls
);
3249 const Reference
< XControl
>* pControls
= aControlsCopy
.getConstArray();
3250 sal_Int32 nControlCount
= aControlsCopy
.getLength();
3252 // the control we have to activate after replacement
3253 Reference
< XDatabaseMetaData
> xMetaData(xConnection
->getMetaData());
3254 Reference
< XNumberFormatsSupplier
> xFormatSupplier
= getNumberFormats(xConnection
, true);
3255 Reference
< XNumberFormatter
> xFormatter
= NumberFormatter::create(m_xComponentContext
);
3256 xFormatter
->attachNumberFormatsSupplier(xFormatSupplier
);
3258 // structure for storing the field info
3259 ::std::vector
<FmFieldInfo
> aFieldInfos
;
3261 for (sal_Int32 i
= nControlCount
; i
> 0;)
3263 Reference
< XControl
> xControl
= pControls
[--i
];
3266 // no events for the control anymore
3267 removeFromEventAttacher(xControl
);
3269 // do we have a mode selector
3270 Reference
< XModeSelector
> xSelector(xControl
, UNO_QUERY
);
3273 xSelector
->setMode( OUString( "FilterMode" ) );
3275 // listening for new controls of the selector
3276 Reference
< XContainer
> xContainer(xSelector
, UNO_QUERY
);
3277 if (xContainer
.is())
3278 xContainer
->addContainerListener(this);
3280 Reference
< XEnumerationAccess
> xElementAccess(xSelector
, UNO_QUERY
);
3281 if (xElementAccess
.is())
3283 Reference
< XEnumeration
> xEnumeration(xElementAccess
->createEnumeration());
3284 Reference
< XControl
> xSubControl
;
3285 while (xEnumeration
->hasMoreElements())
3287 xEnumeration
->nextElement() >>= xSubControl
;
3288 if (xSubControl
.is())
3290 Reference
< XPropertySet
> xSet(xSubControl
->getModel(), UNO_QUERY
);
3291 if (xSet
.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD
, xSet
))
3293 // does the model use a bound field ?
3294 Reference
< XPropertySet
> xField
;
3295 xSet
->getPropertyValue(FM_PROP_BOUNDFIELD
) >>= xField
;
3297 Reference
< XTextComponent
> xText(xSubControl
, UNO_QUERY
);
3298 // may we filter the field?
3299 if (xText
.is() && xField
.is() && ::comphelper::hasProperty(FM_PROP_SEARCHABLE
, xField
) &&
3300 ::comphelper::getBOOL(xField
->getPropertyValue(FM_PROP_SEARCHABLE
)))
3302 aFieldInfos
.push_back(FmFieldInfo(xField
, xText
));
3303 xText
->addTextListener(this);
3312 Reference
< XPropertySet
> xModel( xControl
->getModel(), UNO_QUERY
);
3313 if (xModel
.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD
, xModel
))
3315 // does the model use a bound field ?
3316 Any aVal
= xModel
->getPropertyValue(FM_PROP_BOUNDFIELD
);
3317 Reference
< XPropertySet
> xField
;
3320 // may we filter the field?
3323 && ::comphelper::hasProperty( FM_PROP_SEARCHABLE
, xField
)
3324 && ::comphelper::getBOOL( xField
->getPropertyValue( FM_PROP_SEARCHABLE
) )
3327 // create a filter control
3328 Reference
< XControl
> xFilterControl
= form::control::FilterControl::createWithFormat(
3329 m_xComponentContext
,
3330 VCLUnoHelper::GetInterface( getDialogParentWindow() ),
3334 if ( replaceControl( xControl
, xFilterControl
) )
3336 Reference
< XTextComponent
> xFilterText( xFilterControl
, UNO_QUERY
);
3337 aFieldInfos
.push_back( FmFieldInfo( xField
, xFilterText
) );
3338 xFilterText
->addTextListener(this);
3344 // abmelden vom EventManager
3349 // we have all filter controls now, so the next step is to read the filters from the form
3350 // resolve all aliases and set the current filter to the according structure
3351 setFilter(aFieldInfos
);
3353 Reference
< XPropertySet
> xSet( m_xModelAsIndex
, UNO_QUERY
);
3355 stopFormListening( xSet
, true );
3357 impl_setTextOnAllFilter_throw();
3359 // lock all controls which are not used for filtering
3360 m_bLocked
= determineLockState();
3362 m_bAttachEvents
= true;
3366 void FormController::stopFiltering()
3368 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
3369 if ( !m_bFiltering
) // #104693# OJ
3374 m_bFiltering
= false;
3375 m_bDetachEvents
= false;
3377 ::comphelper::disposeComponent(m_xComposer
);
3379 // Austauschen der Kontrols fuer das aktuelle Formular
3380 Sequence
< Reference
< XControl
> > aControlsCopy( m_aControls
);
3381 const Reference
< XControl
> * pControls
= aControlsCopy
.getConstArray();
3382 sal_Int32 nControlCount
= aControlsCopy
.getLength();
3384 // clear the filter control map
3385 ::std::for_each( m_aFilterComponents
.begin(), m_aFilterComponents
.end(), RemoveComponentTextListener( this ) );
3386 m_aFilterComponents
.clear();
3388 for ( sal_Int32 i
= nControlCount
; i
> 0; )
3390 Reference
< XControl
> xControl
= pControls
[--i
];
3393 // now enable eventhandling again
3394 addToEventAttacher(xControl
);
3396 Reference
< XModeSelector
> xSelector(xControl
, UNO_QUERY
);
3399 xSelector
->setMode( OUString( "DataMode" ) );
3401 // listening for new controls of the selector
3402 Reference
< XContainer
> xContainer(xSelector
, UNO_QUERY
);
3403 if (xContainer
.is())
3404 xContainer
->removeContainerListener(this);
3408 Reference
< XPropertySet
> xSet(xControl
->getModel(), UNO_QUERY
);
3409 if (xSet
.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD
, xSet
))
3411 // does the model use a bound field ?
3412 Reference
< XPropertySet
> xField
;
3413 xSet
->getPropertyValue(FM_PROP_BOUNDFIELD
) >>= xField
;
3415 // may we filter the field?
3417 && ::comphelper::hasProperty( FM_PROP_SEARCHABLE
, xField
)
3418 && ::comphelper::getBOOL( xField
->getPropertyValue( FM_PROP_SEARCHABLE
) )
3421 OUString sServiceName
;
3422 OSL_VERIFY( xSet
->getPropertyValue( FM_PROP_DEFAULTCONTROL
) >>= sServiceName
);
3423 Reference
< XControl
> xNewControl( m_xComponentContext
->getServiceManager()->createInstanceWithContext( sServiceName
, m_xComponentContext
), UNO_QUERY
);
3424 replaceControl( xControl
, xNewControl
);
3430 Reference
< XPropertySet
> xSet( m_xModelAsIndex
, UNO_QUERY
);
3432 startFormListening( xSet
, true );
3434 m_bDetachEvents
= true;
3436 m_aFilterRows
.clear();
3437 m_nCurrentFilterPosition
= -1;
3439 // release the locks if possible
3440 // lock all controls which are not used for filtering
3441 m_bLocked
= determineLockState();
3444 // restart listening for control modifications
3445 if (isListeningForChanges())
3451 void FormController::setMode(const OUString
& Mode
) throw( NoSupportException
, RuntimeException
, std::exception
)
3453 ::osl::MutexGuard
aGuard( m_aMutex
);
3454 impl_checkDisposed_throw();
3456 if (!supportsMode(Mode
))
3457 throw NoSupportException();
3459 if (Mode
== m_aMode
)
3464 if ( Mode
== "FilterMode" )
3469 for (FmFormControllers::const_iterator i
= m_aChildren
.begin();
3470 i
!= m_aChildren
.end(); ++i
)
3472 Reference
< XModeSelector
> xMode(*i
, UNO_QUERY
);
3474 xMode
->setMode(Mode
);
3479 OUString SAL_CALL
FormController::getMode() throw( RuntimeException
, std::exception
)
3481 ::osl::MutexGuard
aGuard( m_aMutex
);
3482 impl_checkDisposed_throw();
3488 Sequence
< OUString
> SAL_CALL
FormController::getSupportedModes() throw( RuntimeException
, std::exception
)
3490 ::osl::MutexGuard
aGuard( m_aMutex
);
3491 impl_checkDisposed_throw();
3493 static Sequence
< OUString
> aModes
;
3494 if (!aModes
.getLength())
3497 aModes
[0] = "DataMode";
3498 aModes
[1] = "FilterMode";
3504 sal_Bool SAL_CALL
FormController::supportsMode(const OUString
& Mode
) throw( RuntimeException
, std::exception
)
3506 ::osl::MutexGuard
aGuard( m_aMutex
);
3507 impl_checkDisposed_throw();
3509 Sequence
< OUString
> aModes(getSupportedModes());
3510 const OUString
* pModes
= aModes
.getConstArray();
3511 for (sal_Int32 i
= aModes
.getLength(); i
> 0; )
3513 if (pModes
[--i
] == Mode
)
3520 vcl::Window
* FormController::getDialogParentWindow()
3522 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
3523 vcl::Window
* pParentWindow
= NULL
;
3526 Reference
< XControl
> xContainerControl( getContainer(), UNO_QUERY_THROW
);
3527 Reference
< XWindowPeer
> xContainerPeer( xContainerControl
->getPeer(), UNO_QUERY_THROW
);
3528 pParentWindow
= VCLUnoHelper::GetWindow( xContainerPeer
);
3530 catch( const Exception
& )
3532 DBG_UNHANDLED_EXCEPTION();
3534 return pParentWindow
;
3537 bool FormController::checkFormComponentValidity( OUString
& /* [out] */ _rFirstInvalidityExplanation
, Reference
< XControlModel
>& /* [out] */ _rxFirstInvalidModel
)
3541 Reference
< XEnumerationAccess
> xControlEnumAcc( getModel(), UNO_QUERY
);
3542 Reference
< XEnumeration
> xControlEnumeration
;
3543 if ( xControlEnumAcc
.is() )
3544 xControlEnumeration
= xControlEnumAcc
->createEnumeration();
3545 OSL_ENSURE( xControlEnumeration
.is(), "FormController::checkFormComponentValidity: cannot enumerate the controls!" );
3546 if ( !xControlEnumeration
.is() )
3550 Reference
< XValidatableFormComponent
> xValidatable
;
3551 while ( xControlEnumeration
->hasMoreElements() )
3553 if ( !( xControlEnumeration
->nextElement() >>= xValidatable
) )
3554 // control does not support validation
3557 if ( xValidatable
->isValid() )
3560 Reference
< XValidator
> xValidator( xValidatable
->getValidator() );
3561 OSL_ENSURE( xValidator
.is(), "FormController::checkFormComponentValidity: invalid, but no validator?" );
3562 if ( !xValidator
.is() )
3563 // this violates the interface definition of css.form.validation.XValidatableFormComponent ...
3566 _rFirstInvalidityExplanation
= xValidator
->explainInvalid( xValidatable
->getCurrentValue() );
3567 _rxFirstInvalidModel
.set(xValidatable
, css::uno::UNO_QUERY
);
3571 catch( const Exception
& )
3573 DBG_UNHANDLED_EXCEPTION();
3579 Reference
< XControl
> FormController::locateControl( const Reference
< XControlModel
>& _rxModel
)
3583 Sequence
< Reference
< XControl
> > aControls( getControls() );
3584 const Reference
< XControl
>* pControls
= aControls
.getConstArray();
3585 const Reference
< XControl
>* pControlsEnd
= aControls
.getConstArray() + aControls
.getLength();
3587 for ( ; pControls
!= pControlsEnd
; ++pControls
)
3589 OSL_ENSURE( pControls
->is(), "FormController::locateControl: NULL-control?" );
3590 if ( pControls
->is() )
3592 if ( ( *pControls
)->getModel() == _rxModel
)
3596 OSL_FAIL( "FormController::locateControl: did not find a control for this model!" );
3598 catch( const Exception
& )
3600 DBG_UNHANDLED_EXCEPTION();
3608 void displayErrorSetFocus( const OUString
& _rMessage
, const Reference
< XControl
>& _rxFocusControl
, vcl::Window
* _pDialogParent
)
3611 aError
.Message
= SVX_RESSTR(RID_STR_WRITEERROR
);
3612 aError
.Details
= _rMessage
;
3613 displayException( aError
, _pDialogParent
);
3615 if ( _rxFocusControl
.is() )
3617 Reference
< XWindow
> xControlWindow( _rxFocusControl
, UNO_QUERY
);
3618 OSL_ENSURE( xControlWindow
.is(), "displayErrorSetFocus: invalid control!" );
3619 if ( xControlWindow
.is() )
3620 xControlWindow
->setFocus();
3624 bool lcl_shouldValidateRequiredFields_nothrow( const Reference
< XInterface
>& _rxForm
)
3628 static const char s_sFormsCheckRequiredFields
[] = "FormsCheckRequiredFields";
3630 // first, check whether the form has a property telling us the answer
3631 // this allows people to use the XPropertyContainer interface of a form to control
3632 // the behaviour on a per-form basis.
3633 Reference
< XPropertySet
> xFormProps( _rxForm
, UNO_QUERY_THROW
);
3634 Reference
< XPropertySetInfo
> xPSI( xFormProps
->getPropertySetInfo() );
3635 if ( xPSI
->hasPropertyByName( s_sFormsCheckRequiredFields
) )
3637 bool bShouldValidate
= true;
3638 OSL_VERIFY( xFormProps
->getPropertyValue( s_sFormsCheckRequiredFields
) >>= bShouldValidate
);
3639 return bShouldValidate
;
3642 // next, check the data source which created the connection
3643 Reference
< XChild
> xConnectionAsChild( xFormProps
->getPropertyValue( FM_PROP_ACTIVE_CONNECTION
), UNO_QUERY_THROW
);
3644 Reference
< XPropertySet
> xDataSource( xConnectionAsChild
->getParent(), UNO_QUERY
);
3645 if ( !xDataSource
.is() )
3646 // seldom (but possible): this is not a connection created by a data source
3649 Reference
< XPropertySet
> xDataSourceSettings(
3650 xDataSource
->getPropertyValue("Settings"),
3653 bool bShouldValidate
= true;
3654 OSL_VERIFY( xDataSourceSettings
->getPropertyValue( s_sFormsCheckRequiredFields
) >>= bShouldValidate
);
3655 return bShouldValidate
;
3657 catch( const Exception
& )
3659 DBG_UNHANDLED_EXCEPTION();
3666 // XRowSetApproveListener
3668 sal_Bool SAL_CALL
FormController::approveRowChange(const RowChangeEvent
& _rEvent
) throw( RuntimeException
, std::exception
)
3670 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
3671 impl_checkDisposed_throw();
3673 ::cppu::OInterfaceIteratorHelper
aIter(m_aRowSetApproveListeners
);
3675 if (aIter
.hasMoreElements())
3677 RowChangeEvent
aEvt( _rEvent
);
3678 aEvt
.Source
= *this;
3679 bValid
= static_cast<XRowSetApproveListener
*>(aIter
.next())->approveRowChange(aEvt
);
3685 if ( ( _rEvent
.Action
!= RowChangeAction::INSERT
)
3686 && ( _rEvent
.Action
!= RowChangeAction::UPDATE
)
3690 // if some of the control models are bound to validators, check them
3691 OUString sInvalidityExplanation
;
3692 Reference
< XControlModel
> xInvalidModel
;
3693 if ( !checkFormComponentValidity( sInvalidityExplanation
, xInvalidModel
) )
3695 Reference
< XControl
> xControl( locateControl( xInvalidModel
) );
3697 displayErrorSetFocus( sInvalidityExplanation
, xControl
, getDialogParentWindow() );
3701 // check values on NULL and required flag
3702 if ( !lcl_shouldValidateRequiredFields_nothrow( _rEvent
.Source
) )
3705 OSL_ENSURE( m_pColumnInfoCache
.get(), "FormController::approveRowChange: no column infos!" );
3706 if ( !m_pColumnInfoCache
.get() )
3711 if ( !m_pColumnInfoCache
->controlsInitialized() )
3712 m_pColumnInfoCache
->initializeControls( getControls() );
3714 size_t colCount
= m_pColumnInfoCache
->getColumnCount();
3715 for ( size_t col
= 0; col
< colCount
; ++col
)
3717 const ColumnInfo
& rColInfo
= m_pColumnInfoCache
->getColumnInfo( col
);
3718 if ( rColInfo
.nNullable
!= ColumnValue::NO_NULLS
)
3721 if ( rColInfo
.bAutoIncrement
)
3724 if ( rColInfo
.bReadOnly
)
3727 if ( !rColInfo
.xFirstControlWithInputRequired
.is() && !rColInfo
.xFirstGridWithInputRequiredColumn
.is() )
3730 // TODO: in case of binary fields, this "getString" below is extremely expensive
3731 if ( !rColInfo
.xColumn
->getString().isEmpty() || !rColInfo
.xColumn
->wasNull() )
3734 OUString
sMessage( SVX_RESSTR( RID_ERR_FIELDREQUIRED
) );
3735 sMessage
= sMessage
.replaceFirst( "#", rColInfo
.sName
);
3737 // the control to focus
3738 Reference
< XControl
> xControl( rColInfo
.xFirstControlWithInputRequired
);
3739 if ( !xControl
.is() )
3740 xControl
.set( rColInfo
.xFirstGridWithInputRequiredColumn
, UNO_QUERY
);
3743 displayErrorSetFocus( sMessage
, rColInfo
.xFirstControlWithInputRequired
, getDialogParentWindow() );
3747 catch( const Exception
& )
3749 DBG_UNHANDLED_EXCEPTION();
3756 sal_Bool SAL_CALL
FormController::approveCursorMove(const EventObject
& event
) throw( RuntimeException
, std::exception
)
3758 ::osl::MutexGuard
aGuard( m_aMutex
);
3759 impl_checkDisposed_throw();
3761 ::cppu::OInterfaceIteratorHelper
aIter(m_aRowSetApproveListeners
);
3762 if (aIter
.hasMoreElements())
3764 EventObject
aEvt(event
);
3765 aEvt
.Source
= *this;
3766 return static_cast<XRowSetApproveListener
*>(aIter
.next())->approveCursorMove(aEvt
);
3773 sal_Bool SAL_CALL
FormController::approveRowSetChange(const EventObject
& event
) throw( RuntimeException
, std::exception
)
3775 ::osl::MutexGuard
aGuard( m_aMutex
);
3776 impl_checkDisposed_throw();
3778 ::cppu::OInterfaceIteratorHelper
aIter(m_aRowSetApproveListeners
);
3779 if (aIter
.hasMoreElements())
3781 EventObject
aEvt(event
);
3782 aEvt
.Source
= *this;
3783 return static_cast<XRowSetApproveListener
*>(aIter
.next())->approveRowSetChange(aEvt
);
3789 // XRowSetApproveBroadcaster
3791 void SAL_CALL
FormController::addRowSetApproveListener(const Reference
< XRowSetApproveListener
> & _rxListener
) throw( RuntimeException
, std::exception
)
3793 ::osl::MutexGuard
aGuard( m_aMutex
);
3794 impl_checkDisposed_throw();
3796 m_aRowSetApproveListeners
.addInterface(_rxListener
);
3800 void SAL_CALL
FormController::removeRowSetApproveListener(const Reference
< XRowSetApproveListener
> & _rxListener
) throw( RuntimeException
, std::exception
)
3802 ::osl::MutexGuard
aGuard( m_aMutex
);
3803 impl_checkDisposed_throw();
3805 m_aRowSetApproveListeners
.removeInterface(_rxListener
);
3810 void SAL_CALL
FormController::errorOccured(const SQLErrorEvent
& aEvent
) throw( RuntimeException
, std::exception
)
3812 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
3813 impl_checkDisposed_throw();
3815 ::cppu::OInterfaceIteratorHelper
aIter(m_aErrorListeners
);
3816 if (aIter
.hasMoreElements())
3818 SQLErrorEvent
aEvt(aEvent
);
3819 aEvt
.Source
= *this;
3820 static_cast<XSQLErrorListener
*>(aIter
.next())->errorOccured(aEvt
);
3825 displayException( aEvent
);
3829 // XErrorBroadcaster
3831 void SAL_CALL
FormController::addSQLErrorListener(const Reference
< XSQLErrorListener
> & aListener
) throw( RuntimeException
, std::exception
)
3833 ::osl::MutexGuard
aGuard( m_aMutex
);
3834 impl_checkDisposed_throw();
3836 m_aErrorListeners
.addInterface(aListener
);
3840 void SAL_CALL
FormController::removeSQLErrorListener(const Reference
< XSQLErrorListener
> & aListener
) throw( RuntimeException
, std::exception
)
3842 ::osl::MutexGuard
aGuard( m_aMutex
);
3843 impl_checkDisposed_throw();
3845 m_aErrorListeners
.removeInterface(aListener
);
3848 // XDatabaseParameterBroadcaster2
3850 void SAL_CALL
FormController::addDatabaseParameterListener(const Reference
< XDatabaseParameterListener
> & aListener
) throw( RuntimeException
, std::exception
)
3852 ::osl::MutexGuard
aGuard( m_aMutex
);
3853 impl_checkDisposed_throw();
3855 m_aParameterListeners
.addInterface(aListener
);
3859 void SAL_CALL
FormController::removeDatabaseParameterListener(const Reference
< XDatabaseParameterListener
> & aListener
) throw( RuntimeException
, std::exception
)
3861 ::osl::MutexGuard
aGuard( m_aMutex
);
3862 impl_checkDisposed_throw();
3864 m_aParameterListeners
.removeInterface(aListener
);
3867 // XDatabaseParameterBroadcaster
3869 void SAL_CALL
FormController::addParameterListener(const Reference
< XDatabaseParameterListener
> & aListener
) throw( RuntimeException
, std::exception
)
3871 FormController::addDatabaseParameterListener( aListener
);
3875 void SAL_CALL
FormController::removeParameterListener(const Reference
< XDatabaseParameterListener
> & aListener
) throw( RuntimeException
, std::exception
)
3877 FormController::removeDatabaseParameterListener( aListener
);
3880 // XDatabaseParameterListener
3882 sal_Bool SAL_CALL
FormController::approveParameter(const DatabaseParameterEvent
& aEvent
) throw( RuntimeException
, std::exception
)
3884 SolarMutexGuard aSolarGuard
;
3885 ::osl::MutexGuard
aGuard( m_aMutex
);
3886 impl_checkDisposed_throw();
3888 ::cppu::OInterfaceIteratorHelper
aIter(m_aParameterListeners
);
3889 if (aIter
.hasMoreElements())
3891 DatabaseParameterEvent
aEvt(aEvent
);
3892 aEvt
.Source
= *this;
3893 return static_cast<XDatabaseParameterListener
*>(aIter
.next())->approveParameter(aEvt
);
3897 // default handling: instantiate an interaction handler and let it handle the parameter request
3900 if ( !ensureInteractionHandler() )
3903 // two continuations allowed: OK and Cancel
3904 OParameterContinuation
* pParamValues
= new OParameterContinuation
;
3905 OInteractionAbort
* pAbort
= new OInteractionAbort
;
3907 ParametersRequest aRequest
;
3908 aRequest
.Parameters
= aEvent
.Parameters
;
3909 aRequest
.Connection
= getConnection(Reference
< XRowSet
>(aEvent
.Source
, UNO_QUERY
));
3910 OInteractionRequest
* pParamRequest
= new OInteractionRequest(makeAny(aRequest
));
3911 Reference
< XInteractionRequest
> xParamRequest(pParamRequest
);
3913 pParamRequest
->addContinuation(pParamValues
);
3914 pParamRequest
->addContinuation(pAbort
);
3916 // handle the request
3917 m_xInteractionHandler
->handle(xParamRequest
);
3919 if (!pParamValues
->wasSelected())
3923 // transfer the values into the parameter supplier
3924 Sequence
< PropertyValue
> aFinalValues
= pParamValues
->getValues();
3925 if (aFinalValues
.getLength() != aRequest
.Parameters
->getCount())
3927 OSL_FAIL("FormController::approveParameter: the InteractionHandler returned nonsense!");
3930 const PropertyValue
* pFinalValues
= aFinalValues
.getConstArray();
3931 for (sal_Int32 i
=0; i
<aFinalValues
.getLength(); ++i
, ++pFinalValues
)
3933 Reference
< XPropertySet
> xParam(
3934 aRequest
.Parameters
->getByIndex(i
), css::uno::UNO_QUERY
);
3939 xParam
->getPropertyValue(FM_PROP_NAME
) >>= sName
;
3940 DBG_ASSERT(sName
.equals(pFinalValues
->Name
), "FormController::approveParameter: suspicious value names!");
3942 try { xParam
->setPropertyValue(FM_PROP_VALUE
, pFinalValues
->Value
); }
3945 OSL_FAIL("FormController::approveParameter: setting one of the properties failed!");
3952 DBG_UNHANDLED_EXCEPTION();
3958 // XConfirmDeleteBroadcaster
3960 void SAL_CALL
FormController::addConfirmDeleteListener(const Reference
< XConfirmDeleteListener
> & aListener
) throw( RuntimeException
, std::exception
)
3962 ::osl::MutexGuard
aGuard( m_aMutex
);
3963 impl_checkDisposed_throw();
3965 m_aDeleteListeners
.addInterface(aListener
);
3969 void SAL_CALL
FormController::removeConfirmDeleteListener(const Reference
< XConfirmDeleteListener
> & aListener
) throw( RuntimeException
, std::exception
)
3971 ::osl::MutexGuard
aGuard( m_aMutex
);
3972 impl_checkDisposed_throw();
3974 m_aDeleteListeners
.removeInterface(aListener
);
3977 // XConfirmDeleteListener
3979 sal_Bool SAL_CALL
FormController::confirmDelete(const RowChangeEvent
& aEvent
) throw( RuntimeException
, std::exception
)
3981 ::osl::MutexGuard
aGuard( m_aMutex
);
3982 impl_checkDisposed_throw();
3984 ::cppu::OInterfaceIteratorHelper
aIter(m_aDeleteListeners
);
3985 if (aIter
.hasMoreElements())
3987 RowChangeEvent
aEvt(aEvent
);
3988 aEvt
.Source
= *this;
3989 return static_cast<XConfirmDeleteListener
*>(aIter
.next())->confirmDelete(aEvt
);
3991 // default handling: instantiate an interaction handler and let it handle the request
3994 sal_Int32 nLength
= aEvent
.Rows
;
3997 sTitle
= SVX_RESSTR( RID_STR_DELETECONFIRM_RECORDS
);
3998 sTitle
= sTitle
.replaceFirst( "#", OUString::number(nLength
) );
4001 sTitle
= SVX_RESSTR( RID_STR_DELETECONFIRM_RECORD
);
4005 if ( !ensureInteractionHandler() )
4008 // two continuations allowed: Yes and No
4009 OInteractionApprove
* pApprove
= new OInteractionApprove
;
4010 OInteractionDisapprove
* pDisapprove
= new OInteractionDisapprove
;
4013 SQLWarning aWarning
;
4014 aWarning
.Message
= sTitle
;
4015 SQLWarning aDetails
;
4016 aDetails
.Message
= SVX_RESSTR(RID_STR_DELETECONFIRM
);
4017 aWarning
.NextException
<<= aDetails
;
4019 OInteractionRequest
* pRequest
= new OInteractionRequest( makeAny( aWarning
) );
4020 Reference
< XInteractionRequest
> xRequest( pRequest
);
4023 pRequest
->addContinuation( pApprove
);
4024 pRequest
->addContinuation( pDisapprove
);
4026 // handle the request
4027 m_xInteractionHandler
->handle( xRequest
);
4029 if ( pApprove
->wasSelected() )
4032 catch( const Exception
& )
4034 DBG_UNHANDLED_EXCEPTION();
4041 void SAL_CALL
FormController::invalidateFeatures( const Sequence
< ::sal_Int16
>& _Features
) throw (RuntimeException
, std::exception
)
4043 ::osl::MutexGuard
aGuard( m_aMutex
);
4044 // for now, just copy the ids of the features, because ....
4045 ::std::copy( _Features
.getConstArray(), _Features
.getConstArray() + _Features
.getLength(),
4046 ::std::insert_iterator
< ::std::set
< sal_Int16
> >( m_aInvalidFeatures
, m_aInvalidFeatures
.begin() )
4049 // ... we will do the real invalidation asynchronously
4050 if ( !m_aFeatureInvalidationTimer
.IsActive() )
4051 m_aFeatureInvalidationTimer
.Start();
4055 void SAL_CALL
FormController::invalidateAllFeatures( ) throw (RuntimeException
, std::exception
)
4057 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
4059 Sequence
< sal_Int16
> aInterceptedFeatures( m_aFeatureDispatchers
.size() );
4061 m_aFeatureDispatchers
.begin(),
4062 m_aFeatureDispatchers
.end(),
4063 aInterceptedFeatures
.getArray(),
4064 ::o3tl::select1st
< DispatcherContainer::value_type
>()
4068 if ( aInterceptedFeatures
.getLength() )
4069 invalidateFeatures( aInterceptedFeatures
);
4073 Reference
< XDispatch
>
4074 FormController::interceptedQueryDispatch( const URL
& aURL
,
4075 const OUString
& /*aTargetFrameName*/, sal_Int32
/*nSearchFlags*/)
4076 throw( RuntimeException
)
4078 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
4079 Reference
< XDispatch
> xReturn
;
4080 // dispatches handled by ourself
4081 if ( ( aURL
.Complete
== FMURL_CONFIRM_DELETION
)
4082 || ( ( aURL
.Complete
== "private:/InteractionHandler" )
4083 && ensureInteractionHandler()
4086 xReturn
= static_cast< XDispatch
* >( this );
4088 // dispatches of FormSlot-URLs we have to translate
4089 if ( !xReturn
.is() && m_xFormOperations
.is() )
4091 // find the slot id which corresponds to the URL
4092 sal_Int32 nFeatureSlotId
= svx::FeatureSlotTranslation::getControllerFeatureSlotIdForURL( aURL
.Main
);
4093 sal_Int16 nFormFeature
= ( nFeatureSlotId
!= -1 ) ? svx::FeatureSlotTranslation::getFormFeatureForSlotId( nFeatureSlotId
) : -1;
4094 if ( nFormFeature
> 0 )
4096 // get the dispatcher for this feature, create if necessary
4097 DispatcherContainer::const_iterator aDispatcherPos
= m_aFeatureDispatchers
.find( nFormFeature
);
4098 if ( aDispatcherPos
== m_aFeatureDispatchers
.end() )
4100 aDispatcherPos
= m_aFeatureDispatchers
.insert(
4101 DispatcherContainer::value_type( nFormFeature
, new svx::OSingleFeatureDispatcher( aURL
, nFormFeature
, m_xFormOperations
, m_aMutex
) )
4105 OSL_ENSURE( aDispatcherPos
->second
.is(), "FormController::interceptedQueryDispatch: should have a dispatcher by now!" );
4106 return aDispatcherPos
->second
;
4115 void SAL_CALL
FormController::dispatch( const URL
& _rURL
, const Sequence
< PropertyValue
>& _rArgs
) throw (RuntimeException
, std::exception
)
4117 if ( _rArgs
.getLength() != 1 )
4119 OSL_FAIL( "FormController::dispatch: no arguments -> no dispatch!" );
4123 if ( _rURL
.Complete
== "private:/InteractionHandler" )
4125 Reference
< XInteractionRequest
> xRequest
;
4126 OSL_VERIFY( _rArgs
[0].Value
>>= xRequest
);
4127 if ( xRequest
.is() )
4132 if ( _rURL
.Complete
== FMURL_CONFIRM_DELETION
)
4134 OSL_FAIL( "FormController::dispatch: How do you expect me to return something via this call?" );
4135 // confirmDelete has a return value - dispatch hasn't
4139 OSL_FAIL( "FormController::dispatch: unknown URL!" );
4143 void SAL_CALL
FormController::addStatusListener( const Reference
< XStatusListener
>& _rxListener
, const URL
& _rURL
) throw (RuntimeException
, std::exception
)
4145 if (_rURL
.Complete
== FMURL_CONFIRM_DELETION
)
4147 if (_rxListener
.is())
4148 { // send an initial statusChanged event
4149 FeatureStateEvent aEvent
;
4150 aEvent
.FeatureURL
= _rURL
;
4151 aEvent
.IsEnabled
= sal_True
;
4152 _rxListener
->statusChanged(aEvent
);
4153 // and don't add the listener at all (the status will never change)
4157 OSL_FAIL("FormController::addStatusListener: invalid (unsupported) URL!");
4161 Reference
< XInterface
> SAL_CALL
FormController::getParent() throw( RuntimeException
, std::exception
)
4167 void SAL_CALL
FormController::setParent( const Reference
< XInterface
>& Parent
) throw( NoSupportException
, RuntimeException
, std::exception
)
4173 void SAL_CALL
FormController::removeStatusListener( const Reference
< XStatusListener
>& /*_rxListener*/, const URL
& _rURL
) throw (RuntimeException
, std::exception
)
4176 OSL_ENSURE(_rURL
.Complete
== FMURL_CONFIRM_DELETION
, "FormController::removeStatusListener: invalid (unsupported) URL!");
4177 // we never really added the listener, so we don't need to remove it
4181 Reference
< XDispatchProviderInterceptor
> FormController::createInterceptor(const Reference
< XDispatchProviderInterception
> & _xInterception
)
4183 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
4185 // check if we already have a interceptor for the given object
4186 for ( Interceptors::const_iterator aIter
= m_aControlDispatchInterceptors
.begin();
4187 aIter
!= m_aControlDispatchInterceptors
.end();
4191 if ((*aIter
)->getIntercepted() == _xInterception
)
4192 OSL_FAIL("FormController::createInterceptor : we already do intercept this objects dispatches !");
4196 DispatchInterceptionMultiplexer
* pInterceptor
= new DispatchInterceptionMultiplexer( _xInterception
, this );
4197 pInterceptor
->acquire();
4198 m_aControlDispatchInterceptors
.insert( m_aControlDispatchInterceptors
.end(), pInterceptor
);
4200 return pInterceptor
;
4204 bool FormController::ensureInteractionHandler()
4206 if ( m_xInteractionHandler
.is() )
4208 if ( m_bAttemptedHandlerCreation
)
4210 m_bAttemptedHandlerCreation
= true;
4212 m_xInteractionHandler
= InteractionHandler::createWithParent(m_xComponentContext
, 0);
4213 return m_xInteractionHandler
.is();
4217 void SAL_CALL
FormController::handle( const Reference
< XInteractionRequest
>& _rRequest
) throw (RuntimeException
, std::exception
)
4219 if ( !ensureInteractionHandler() )
4221 m_xInteractionHandler
->handle( _rRequest
);
4225 void FormController::deleteInterceptor(const Reference
< XDispatchProviderInterception
> & _xInterception
)
4227 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
4228 // search the interceptor responsible for the given object
4229 Interceptors::iterator aIter
;
4230 for ( aIter
= m_aControlDispatchInterceptors
.begin();
4231 aIter
!= m_aControlDispatchInterceptors
.end();
4235 if ((*aIter
)->getIntercepted() == _xInterception
)
4238 if (aIter
== m_aControlDispatchInterceptors
.end())
4243 // log off the interception from it's interception object
4244 DispatchInterceptionMultiplexer
* pInterceptorImpl
= *aIter
;
4245 pInterceptorImpl
->dispose();
4246 pInterceptorImpl
->release();
4248 // remove the interceptor from our array
4249 m_aControlDispatchInterceptors
.erase(aIter
);
4253 void FormController::implInvalidateCurrentControlDependentFeatures()
4255 Sequence
< sal_Int16
> aCurrentControlDependentFeatures(4);
4257 aCurrentControlDependentFeatures
[0] = FormFeature::SortAscending
;
4258 aCurrentControlDependentFeatures
[1] = FormFeature::SortDescending
;
4259 aCurrentControlDependentFeatures
[2] = FormFeature::AutoFilter
;
4260 aCurrentControlDependentFeatures
[3] = FormFeature::RefreshCurrentControl
;
4262 invalidateFeatures( aCurrentControlDependentFeatures
);
4266 void SAL_CALL
FormController::columnChanged( const EventObject
& /*_event*/ ) throw (RuntimeException
, std::exception
)
4268 implInvalidateCurrentControlDependentFeatures();
4273 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */