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/extract.hxx>
69 #include <comphelper/interaction.hxx>
70 #include <comphelper/namedvaluecollection.hxx>
71 #include <comphelper/processfactory.hxx>
72 #include <comphelper/propagg.hxx>
73 #include <comphelper/property.hxx>
74 #include <comphelper/sequence.hxx>
75 #include <comphelper/uno3.hxx>
76 #include <comphelper/flagguard.hxx>
77 #include <cppuhelper/queryinterface.hxx>
78 #include <cppuhelper/typeprovider.hxx>
79 #include <connectivity/IParseContext.hxx>
80 #include <toolkit/controls/unocontrol.hxx>
81 #include <toolkit/helper/vclunohelper.hxx>
82 #include <tools/debug.hxx>
83 #include <tools/diagnose_ex.h>
84 #include <tools/shl.hxx>
85 #include <vcl/msgbox.hxx>
86 #include <vcl/svapp.hxx>
87 #include <osl/mutex.hxx>
88 #include <rtl/logfile.hxx>
92 #include <o3tl/compat_functional.hxx>
94 using namespace ::com::sun::star
;
95 using namespace ::comphelper
;
96 using namespace ::connectivity
;
97 using namespace ::connectivity::simple
;
99 //------------------------------------------------------------------
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
)
103 return *( new ::svxform::FormController( _rxORB
) );
109 using ::com::sun::star::sdb::XColumn
;
110 using ::com::sun::star::awt::XControl
;
111 using ::com::sun::star::awt::XTabController
;
112 using ::com::sun::star::awt::TabController
;
113 using ::com::sun::star::awt::XToolkit
;
114 using ::com::sun::star::awt::XWindowPeer
;
115 using ::com::sun::star::form::XGrid
;
116 using ::com::sun::star::beans::XPropertySet
;
117 using ::com::sun::star::uno::UNO_SET_THROW
;
118 using ::com::sun::star::uno::UNO_QUERY_THROW
;
119 using ::com::sun::star::container::XIndexAccess
;
120 using ::com::sun::star::uno::Exception
;
121 using ::com::sun::star::uno::XInterface
;
122 using ::com::sun::star::uno::UNO_QUERY
;
123 using ::com::sun::star::uno::Sequence
;
124 using ::com::sun::star::uno::Reference
;
125 using ::com::sun::star::beans::XPropertySetInfo
;
126 using ::com::sun::star::beans::PropertyValue
;
127 using ::com::sun::star::uno::RuntimeException
;
128 using ::com::sun::star::lang::IndexOutOfBoundsException
;
129 using ::com::sun::star::sdb::XInteractionSupplyParameters
;
130 using ::com::sun::star::awt::XTextComponent
;
131 using ::com::sun::star::awt::XTextListener
;
132 using ::com::sun::star::uno::Any
;
133 using ::com::sun::star::frame::XDispatch
;
134 using ::com::sun::star::lang::XMultiServiceFactory
;
135 using ::com::sun::star::uno::XAggregation
;
136 using ::com::sun::star::uno::Type
;
137 using ::com::sun::star::lang::IllegalArgumentException
;
138 using ::com::sun::star::sdbc::XConnection
;
139 using ::com::sun::star::sdbc::XRowSet
;
140 using ::com::sun::star::sdbc::XDatabaseMetaData
;
141 using ::com::sun::star::util::XNumberFormatsSupplier
;
142 using ::com::sun::star::util::NumberFormatter
;
143 using ::com::sun::star::util::XNumberFormatter
;
144 using ::com::sun::star::sdbcx::XColumnsSupplier
;
145 using ::com::sun::star::container::XNameAccess
;
146 using ::com::sun::star::lang::EventObject
;
147 using ::com::sun::star::beans::Property
;
148 using ::com::sun::star::container::XEnumeration
;
149 using ::com::sun::star::form::XFormComponent
;
150 using ::com::sun::star::form::runtime::XFormOperations
;
151 using ::com::sun::star::form::runtime::FilterEvent
;
152 using ::com::sun::star::form::runtime::XFilterControllerListener
;
153 using ::com::sun::star::awt::XControlContainer
;
154 using ::com::sun::star::container::XIdentifierReplace
;
155 using ::com::sun::star::lang::WrappedTargetException
;
156 using ::com::sun::star::form::XFormControllerListener
;
157 using ::com::sun::star::awt::XWindow
;
158 using ::com::sun::star::sdbc::XResultSet
;
159 using ::com::sun::star::awt::XControlModel
;
160 using ::com::sun::star::awt::XTabControllerModel
;
161 using ::com::sun::star::beans::PropertyChangeEvent
;
162 using ::com::sun::star::form::validation::XValidatableFormComponent
;
163 using ::com::sun::star::form::XLoadable
;
164 using ::com::sun::star::script::XEventAttacherManager
;
165 using ::com::sun::star::form::XBoundControl
;
166 using ::com::sun::star::beans::XPropertyChangeListener
;
167 using ::com::sun::star::awt::TextEvent
;
168 using ::com::sun::star::form::XBoundComponent
;
169 using ::com::sun::star::awt::XCheckBox
;
170 using ::com::sun::star::awt::XComboBox
;
171 using ::com::sun::star::awt::XListBox
;
172 using ::com::sun::star::awt::ItemEvent
;
173 using ::com::sun::star::util::XModifyListener
;
174 using ::com::sun::star::form::XReset
;
175 using ::com::sun::star::frame::XDispatchProviderInterception
;
176 using ::com::sun::star::form::XGridControl
;
177 using ::com::sun::star::awt::XVclWindowPeer
;
178 using ::com::sun::star::form::validation::XValidator
;
179 using ::com::sun::star::awt::FocusEvent
;
180 using ::com::sun::star::sdb::SQLContext
;
181 using ::com::sun::star::container::XChild
;
182 using ::com::sun::star::form::TabulatorCycle_RECORDS
;
183 using ::com::sun::star::container::ContainerEvent
;
184 using ::com::sun::star::lang::DisposedException
;
185 using ::com::sun::star::lang::Locale
;
186 using ::com::sun::star::beans::NamedValue
;
187 using ::com::sun::star::lang::NoSupportException
;
188 using ::com::sun::star::sdb::RowChangeEvent
;
189 using ::com::sun::star::frame::XStatusListener
;
190 using ::com::sun::star::frame::XDispatchProviderInterceptor
;
191 using ::com::sun::star::sdb::SQLErrorEvent
;
192 using ::com::sun::star::form::DatabaseParameterEvent
;
193 using ::com::sun::star::sdb::ParametersRequest
;
194 using ::com::sun::star::task::XInteractionRequest
;
195 using ::com::sun::star::util::URL
;
196 using ::com::sun::star::frame::FeatureStateEvent
;
197 using ::com::sun::star::form::runtime::XFormControllerContext
;
198 using ::com::sun::star::task::InteractionHandler
;
199 using ::com::sun::star::task::XInteractionHandler
;
200 using ::com::sun::star::form::runtime::FormOperations
;
201 using ::com::sun::star::container::XContainer
;
202 using ::com::sun::star::sdbc::SQLWarning
;
204 namespace ColumnValue
= ::com::sun::star::sdbc::ColumnValue
;
205 namespace PropertyAttribute
= ::com::sun::star::beans::PropertyAttribute
;
206 namespace FocusChangeReason
= ::com::sun::star::awt::FocusChangeReason
;
207 namespace RowChangeAction
= ::com::sun::star::sdb::RowChangeAction
;
208 namespace FormFeature
= ::com::sun::star::form::runtime::FormFeature
;
209 namespace DataType
= ::com::sun::star::sdbc::DataType
;
211 //==============================================================================
213 //==============================================================================
216 // information about the column itself
217 Reference
< XColumn
> xColumn
;
219 sal_Bool bAutoIncrement
;
223 // information about the control(s) bound to this column
225 /// the first control which is bound to the given column, and which requires input
226 Reference
< XControl
> xFirstControlWithInputRequired
;
227 /** the first grid control which contains a column which is bound to the given database column, and requires
230 Reference
< XGrid
> xFirstGridWithInputRequiredColumn
;
231 /** if xFirstControlWithInputRequired is a grid control, then nRequiredGridColumn specifies the position
232 of the grid column which is actually bound
234 sal_Int32 nRequiredGridColumn
;
238 ,nNullable( ColumnValue::NULLABLE_UNKNOWN
)
239 ,bAutoIncrement( sal_False
)
240 ,bReadOnly( sal_False
)
242 ,xFirstControlWithInputRequired()
243 ,xFirstGridWithInputRequiredColumn()
244 ,nRequiredGridColumn( -1 )
249 //==============================================================================
251 //==============================================================================
252 class ColumnInfoCache
255 ColumnInfoCache( const Reference
< XColumnsSupplier
>& _rxColSupplier
);
257 size_t getColumnCount() const { return m_aColumns
.size(); }
258 const ColumnInfo
& getColumnInfo( size_t _pos
);
260 bool controlsInitialized() const { return m_bControlsInitialized
; }
261 void initializeControls( const Sequence
< Reference
< XControl
> >& _rControls
);
262 void deinitializeControls();
265 typedef ::std::vector
< ColumnInfo
> ColumnInfos
;
266 ColumnInfos m_aColumns
;
267 bool m_bControlsInitialized
;
270 //------------------------------------------------------------------------------
271 ColumnInfoCache::ColumnInfoCache( const Reference
< XColumnsSupplier
>& _rxColSupplier
)
273 ,m_bControlsInitialized( false )
279 Reference
< XColumnsSupplier
> xSupplyCols( _rxColSupplier
, UNO_SET_THROW
);
280 Reference
< XIndexAccess
> xColumns( xSupplyCols
->getColumns(), UNO_QUERY_THROW
);
281 sal_Int32 nColumnCount
= xColumns
->getCount();
282 m_aColumns
.reserve( nColumnCount
);
284 Reference
< XPropertySet
> xColumnProps
;
285 for ( sal_Int32 i
= 0; i
< nColumnCount
; ++i
)
288 aColInfo
.xColumn
.set( xColumns
->getByIndex(i
), UNO_QUERY_THROW
);
290 xColumnProps
.set( aColInfo
.xColumn
, UNO_QUERY_THROW
);
291 OSL_VERIFY( xColumnProps
->getPropertyValue( FM_PROP_ISNULLABLE
) >>= aColInfo
.nNullable
);
292 OSL_VERIFY( xColumnProps
->getPropertyValue( FM_PROP_AUTOINCREMENT
) >>= aColInfo
.bAutoIncrement
);
293 OSL_VERIFY( xColumnProps
->getPropertyValue( FM_PROP_NAME
) >>= aColInfo
.sName
);
294 OSL_VERIFY( xColumnProps
->getPropertyValue( FM_PROP_ISREADONLY
) >>= aColInfo
.bReadOnly
);
296 m_aColumns
.push_back( aColInfo
);
299 catch( const Exception
& )
301 DBG_UNHANDLED_EXCEPTION();
305 //------------------------------------------------------------------------------
308 bool lcl_isBoundTo( const Reference
< XPropertySet
>& _rxControlModel
, const Reference
< XInterface
>& _rxNormDBField
)
310 Reference
< XInterface
> xNormBoundField( _rxControlModel
->getPropertyValue( FM_PROP_BOUNDFIELD
), UNO_QUERY
);
311 return ( xNormBoundField
.get() == _rxNormDBField
.get() );
314 bool lcl_isInputRequired( const Reference
< XPropertySet
>& _rxControlModel
)
316 sal_Bool bInputRequired
= sal_True
;
317 OSL_VERIFY( _rxControlModel
->getPropertyValue( FM_PROP_INPUT_REQUIRED
) >>= bInputRequired
);
318 return ( bInputRequired
!= sal_False
);
321 void lcl_resetColumnControlInfo( ColumnInfo
& _rColInfo
)
323 _rColInfo
.xFirstControlWithInputRequired
.clear();
324 _rColInfo
.xFirstGridWithInputRequiredColumn
.clear();
325 _rColInfo
.nRequiredGridColumn
= -1;
329 //------------------------------------------------------------------------------
330 void ColumnInfoCache::deinitializeControls()
332 for ( ColumnInfos::iterator col
= m_aColumns
.begin();
333 col
!= m_aColumns
.end();
337 lcl_resetColumnControlInfo( *col
);
341 //------------------------------------------------------------------------------
342 void ColumnInfoCache::initializeControls( const Sequence
< Reference
< XControl
> >& _rControls
)
346 // for every of our known columns, find the controls which are bound to this column
347 for ( ColumnInfos::iterator col
= m_aColumns
.begin();
348 col
!= m_aColumns
.end();
352 OSL_ENSURE( !col
->xFirstControlWithInputRequired
.is() && !col
->xFirstGridWithInputRequiredColumn
.is()
353 && ( col
->nRequiredGridColumn
== -1 ), "ColumnInfoCache::initializeControls: called me twice?" );
355 lcl_resetColumnControlInfo( *col
);
357 Reference
< XInterface
> xNormColumn( col
->xColumn
, UNO_QUERY_THROW
);
359 const Reference
< XControl
>* pControl( _rControls
.getConstArray() );
360 const Reference
< XControl
>* pControlEnd( pControl
+ _rControls
.getLength() );
361 for ( ; pControl
!= pControlEnd
; ++pControl
)
363 if ( !pControl
->is() )
366 Reference
< XPropertySet
> xModel( (*pControl
)->getModel(), UNO_QUERY_THROW
);
367 Reference
< XPropertySetInfo
> xModelPSI( xModel
->getPropertySetInfo(), UNO_SET_THROW
);
369 // special handling for grid controls
370 Reference
< XGrid
> xGrid( *pControl
, UNO_QUERY
);
373 Reference
< XIndexAccess
> xGridColAccess( xModel
, UNO_QUERY_THROW
);
374 sal_Int32 gridColCount
= xGridColAccess
->getCount();
375 sal_Int32 gridCol
= 0;
376 for ( gridCol
= 0; gridCol
< gridColCount
; ++gridCol
)
378 Reference
< XPropertySet
> xGridColumnModel( xGridColAccess
->getByIndex( gridCol
), UNO_QUERY_THROW
);
380 if ( !lcl_isBoundTo( xGridColumnModel
, xNormColumn
)
381 || !lcl_isInputRequired( xGridColumnModel
)
383 continue; // with next grid column
388 if ( gridCol
< gridColCount
)
390 // found a grid column which is bound to the given
391 col
->xFirstGridWithInputRequiredColumn
= xGrid
;
392 col
->nRequiredGridColumn
= gridCol
;
396 continue; // with next control
399 if ( !xModelPSI
->hasPropertyByName( FM_PROP_BOUNDFIELD
)
400 || !lcl_isBoundTo( xModel
, xNormColumn
)
401 || !lcl_isInputRequired( xModel
)
403 continue; // with next control
408 if ( pControl
== pControlEnd
)
409 // did not find a control which is bound to this particular column, and for which the input is required
410 continue; // with next DB column
412 col
->xFirstControlWithInputRequired
= *pControl
;
415 catch( const Exception
& )
417 DBG_UNHANDLED_EXCEPTION();
420 m_bControlsInitialized
= true;
423 //------------------------------------------------------------------------------
424 const ColumnInfo
& ColumnInfoCache::getColumnInfo( size_t _pos
)
426 if ( _pos
>= m_aColumns
.size() )
427 throw IndexOutOfBoundsException();
429 return m_aColumns
[ _pos
];
432 //==================================================================
433 // OParameterContinuation
434 //==================================================================
435 class OParameterContinuation
: public OInteraction
< XInteractionSupplyParameters
>
437 Sequence
< PropertyValue
> m_aValues
;
440 OParameterContinuation() { }
442 Sequence
< PropertyValue
> getValues() const { return m_aValues
; }
444 // XInteractionSupplyParameters
445 virtual void SAL_CALL
setParameters( const Sequence
< PropertyValue
>& _rValues
) throw(RuntimeException
);
448 //------------------------------------------------------------------
449 void SAL_CALL
OParameterContinuation::setParameters( const Sequence
< PropertyValue
>& _rValues
) throw(RuntimeException
)
451 m_aValues
= _rValues
;
454 //==================================================================
456 //==================================================================
460 Reference
< XPropertySet
> xField
;
461 Reference
< XTextComponent
> xText
;
463 FmFieldInfo(const Reference
< XPropertySet
>& _xField
, const Reference
< XTextComponent
>& _xText
)
466 {xField
->getPropertyValue(FM_PROP_NAME
) >>= aFieldName
;}
469 //==================================================================
471 //==================================================================
472 class FmXAutoControl
: public UnoControl
475 friend Reference
< XInterface
> SAL_CALL
FmXAutoControl_NewInstance_Impl();
478 FmXAutoControl() :UnoControl()
482 virtual OUString
GetComponentServiceName() {return OUString("Edit");}
483 virtual void SAL_CALL
createPeer( const Reference
< XToolkit
> & rxToolkit
, const Reference
< XWindowPeer
> & rParentPeer
) throw( RuntimeException
);
486 virtual void ImplSetPeerProperty( const OUString
& rPropName
, const Any
& rVal
);
489 //------------------------------------------------------------------------------
490 void FmXAutoControl::createPeer( const Reference
< XToolkit
> & rxToolkit
, const Reference
< XWindowPeer
> & rParentPeer
) throw( RuntimeException
)
492 UnoControl::createPeer( rxToolkit
, rParentPeer
);
494 Reference
< XTextComponent
> xText(getPeer() , UNO_QUERY
);
497 xText
->setText(OUString(String(SVX_RES(RID_STR_AUTOFIELD
))));
498 xText
->setEditable(sal_False
);
502 //------------------------------------------------------------------------------
503 void FmXAutoControl::ImplSetPeerProperty( const OUString
& rPropName
, const Any
& rVal
)
505 // these properties are ignored
506 if (rPropName
== FM_PROP_TEXT
)
509 UnoControl::ImplSetPeerProperty( rPropName
, rVal
);
512 //------------------------------------------------------------------------------
513 IMPL_LINK( FormController
, OnActivateTabOrder
, void*, /*EMPTYTAG*/ )
519 //------------------------------------------------------------------------------
520 struct UpdateAllListeners
: public ::std::unary_function
< Reference
< XDispatch
>, bool >
522 bool operator()( const Reference
< XDispatch
>& _rxDispatcher
) const
524 static_cast< ::svx::OSingleFeatureDispatcher
* >( _rxDispatcher
.get() )->updateAllListeners();
525 // the return is a dummy only so we can use this struct in a o3tl::compose1 call
529 //..............................................................................
530 IMPL_LINK( FormController
, OnInvalidateFeatures
, void*, /*_pNotInterestedInThisParam*/ )
532 ::osl::MutexGuard
aGuard( m_aMutex
);
533 for ( ::std::set
< sal_Int16
>::const_iterator aLoop
= m_aInvalidFeatures
.begin();
534 aLoop
!= m_aInvalidFeatures
.end();
538 DispatcherContainer::const_iterator aDispatcherPos
= m_aFeatureDispatchers
.find( *aLoop
);
539 if ( aDispatcherPos
!= m_aFeatureDispatchers
.end() )
541 // TODO: for the real and actual listener notifications, we should release
543 UpdateAllListeners( )( aDispatcherPos
->second
);
549 /*************************************************************************/
551 DBG_NAME( FormController
)
552 //------------------------------------------------------------------
553 FormController::FormController(const Reference
< XMultiServiceFactory
> & _rxORB
)
554 :FormController_BASE( m_aMutex
)
555 ,OPropertySetHelper( FormController_BASE::rBHelper
)
556 ,OSQLParserClient( comphelper::getComponentContext(_rxORB
) )
557 ,m_aContext( _rxORB
)
558 ,m_aActivateListeners(m_aMutex
)
559 ,m_aModifyListeners(m_aMutex
)
560 ,m_aErrorListeners(m_aMutex
)
561 ,m_aDeleteListeners(m_aMutex
)
562 ,m_aRowSetApproveListeners(m_aMutex
)
563 ,m_aParameterListeners(m_aMutex
)
564 ,m_aFilterListeners(m_aMutex
)
565 ,m_pControlBorderManager( new ::svxform::ControlBorderManager
)
567 ,m_aMode( OUString( "DataMode" ) )
568 ,m_aLoadEvent( LINK( this, FormController
, OnLoad
) )
569 ,m_aToggleEvent( LINK( this, FormController
, OnToggleAutoFields
) )
570 ,m_aActivationEvent( LINK( this, FormController
, OnActivated
) )
571 ,m_aDeactivationEvent( LINK( this, FormController
, OnDeactivated
) )
572 ,m_nCurrentFilterPosition(-1)
573 ,m_bCurrentRecordModified(sal_False
)
574 ,m_bCurrentRecordNew(sal_False
)
575 ,m_bLocked(sal_False
)
576 ,m_bDBConnection(sal_False
)
578 ,m_bCanInsert(sal_False
)
579 ,m_bCanUpdate(sal_False
)
580 ,m_bCommitLock(sal_False
)
581 ,m_bModified(sal_False
)
582 ,m_bControlsSorted(sal_False
)
583 ,m_bFiltering(sal_False
)
584 ,m_bAttachEvents(sal_True
)
585 ,m_bDetachEvents(sal_True
)
586 ,m_bAttemptedHandlerCreation( false )
587 ,m_bSuspendFilterTextListening( false )
589 DBG_CTOR( FormController
, NULL
);
591 ::comphelper::increment(m_refCount
);
593 m_xTabController
= TabController::create( m_aContext
.getUNOContext() );
594 m_xAggregate
= Reference
< XAggregation
>( m_xTabController
, UNO_QUERY_THROW
);
595 m_xAggregate
->setDelegator( *this );
597 ::comphelper::decrement(m_refCount
);
599 m_aTabActivationTimer
.SetTimeout( 500 );
600 m_aTabActivationTimer
.SetTimeoutHdl( LINK( this, FormController
, OnActivateTabOrder
) );
602 m_aFeatureInvalidationTimer
.SetTimeout( 200 );
603 m_aFeatureInvalidationTimer
.SetTimeoutHdl( LINK( this, FormController
, OnInvalidateFeatures
) );
606 //------------------------------------------------------------------
607 FormController::~FormController()
610 ::osl::MutexGuard
aGuard( m_aMutex
);
612 m_aLoadEvent
.CancelPendingCall();
613 m_aToggleEvent
.CancelPendingCall();
614 m_aActivationEvent
.CancelPendingCall();
615 m_aDeactivationEvent
.CancelPendingCall();
617 if ( m_aTabActivationTimer
.IsActive() )
618 m_aTabActivationTimer
.Stop();
621 if ( m_aFeatureInvalidationTimer
.IsActive() )
622 m_aFeatureInvalidationTimer
.Stop();
624 disposeAllFeaturesAndDispatchers();
626 if ( m_xFormOperations
.is() )
627 m_xFormOperations
->dispose();
628 m_xFormOperations
.clear();
630 // Freigeben der Aggregation
631 if ( m_xAggregate
.is() )
633 m_xAggregate
->setDelegator( NULL
);
634 m_xAggregate
.clear();
637 DELETEZ( m_pControlBorderManager
);
639 DBG_DTOR( FormController
, NULL
);
642 // -----------------------------------------------------------------------------
643 void SAL_CALL
FormController::acquire() throw ()
645 FormController_BASE::acquire();
648 // -----------------------------------------------------------------------------
649 void SAL_CALL
FormController::release() throw ()
651 FormController_BASE::release();
654 //------------------------------------------------------------------
655 Any SAL_CALL
FormController::queryInterface( const Type
& _rType
) throw(RuntimeException
)
657 Any aRet
= FormController_BASE::queryInterface( _rType
);
658 if ( !aRet
.hasValue() )
659 aRet
= OPropertySetHelper::queryInterface( _rType
);
660 if ( !aRet
.hasValue() )
661 aRet
= m_xAggregate
->queryAggregation( _rType
);
665 //------------------------------------------------------------------------------
666 Sequence
< sal_Int8
> SAL_CALL
FormController::getImplementationId() throw( RuntimeException
)
668 static ::cppu::OImplementationId
* pId
= NULL
;
671 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
674 static ::cppu::OImplementationId aId
;
678 return pId
->getImplementationId();
681 //------------------------------------------------------------------------------
682 Sequence
< Type
> SAL_CALL
FormController::getTypes( ) throw(RuntimeException
)
684 return comphelper::concatSequences(
685 FormController_BASE::getTypes(),
686 ::cppu::OPropertySetHelper::getTypes()
691 //------------------------------------------------------------------------------
692 sal_Bool SAL_CALL
FormController::supportsService(const OUString
& ServiceName
) throw( RuntimeException
)
694 Sequence
< OUString
> aSNL(getSupportedServiceNames());
695 const OUString
* pArray
= aSNL
.getConstArray();
696 for( sal_Int32 i
= 0; i
< aSNL
.getLength(); i
++ )
697 if( pArray
[i
] == ServiceName
)
702 //------------------------------------------------------------------------------
703 OUString SAL_CALL
FormController::getImplementationName() throw( RuntimeException
)
705 return OUString("org.openoffice.comp.svx.FormController");
708 //------------------------------------------------------------------------------
709 Sequence
< OUString
> SAL_CALL
FormController::getSupportedServiceNames(void) throw( RuntimeException
)
711 // service names which are supported only, but cannot be used to created an
712 // instance at a service factory
713 Sequence
< OUString
> aNonCreatableServiceNames( 1 );
714 aNonCreatableServiceNames
[ 0 ] = OUString( "com.sun.star.form.FormControllerDispatcher" );
716 // services which can be used to created an instance at a service factory
717 Sequence
< OUString
> aCreatableServiceNames( getSupportedServiceNames_Static() );
718 return ::comphelper::concatSequences( aCreatableServiceNames
, aNonCreatableServiceNames
);
721 //------------------------------------------------------------------------------
722 sal_Bool SAL_CALL
FormController::approveReset(const EventObject
& /*rEvent*/) throw( RuntimeException
)
727 //------------------------------------------------------------------------------
728 void SAL_CALL
FormController::resetted(const EventObject
& rEvent
) throw( RuntimeException
)
730 ::osl::MutexGuard
aGuard(m_aMutex
);
731 if (getCurrentControl().is() && (getCurrentControl()->getModel() == rEvent
.Source
))
732 m_bModified
= sal_False
;
735 //------------------------------------------------------------------------------
736 Sequence
< OUString
> FormController::getSupportedServiceNames_Static(void)
738 static Sequence
< OUString
> aServices
;
739 if (!aServices
.getLength())
741 aServices
.realloc(2);
742 aServices
.getArray()[0] = OUString( "com.sun.star.form.runtime.FormController" );
743 aServices
.getArray()[1] = OUString("com.sun.star.awt.control.TabController");
748 // -----------------------------------------------------------------------------
751 struct ResetComponentText
: public ::std::unary_function
< Reference
< XTextComponent
>, void >
753 void operator()( const Reference
< XTextComponent
>& _rxText
)
755 _rxText
->setText( OUString() );
759 struct RemoveComponentTextListener
: public ::std::unary_function
< Reference
< XTextComponent
>, void >
761 RemoveComponentTextListener( const Reference
< XTextListener
>& _rxListener
)
762 :m_xListener( _rxListener
)
766 void operator()( const Reference
< XTextComponent
>& _rxText
)
768 _rxText
->removeTextListener( m_xListener
);
772 Reference
< XTextListener
> m_xListener
;
776 // -----------------------------------------------------------------------------
777 void FormController::impl_setTextOnAllFilter_throw()
779 m_bSuspendFilterTextListening
= true;
780 ::comphelper::FlagGuard
aResetFlag( m_bSuspendFilterTextListening
);
782 // reset the text for all controls
783 ::std::for_each( m_aFilterComponents
.begin(), m_aFilterComponents
.end(), ResetComponentText() );
785 if ( m_aFilterRows
.empty() )
786 // nothing to do anymore
789 if ( m_nCurrentFilterPosition
< 0 )
792 // set the text for all filters
793 OSL_ENSURE( m_aFilterRows
.size() > (size_t)m_nCurrentFilterPosition
,
794 "FormController::impl_setTextOnAllFilter_throw: m_nCurrentFilterPosition too big" );
796 if ( (size_t)m_nCurrentFilterPosition
< m_aFilterRows
.size() )
798 FmFilterRow
& rRow
= m_aFilterRows
[ m_nCurrentFilterPosition
];
799 for ( FmFilterRow::const_iterator iter2
= rRow
.begin();
804 iter2
->first
->setText( iter2
->second
);
808 // OPropertySetHelper
809 //------------------------------------------------------------------------------
810 sal_Bool
FormController::convertFastPropertyValue( Any
& /*rConvertedValue*/, Any
& /*rOldValue*/,
811 sal_Int32
/*nHandle*/, const Any
& /*rValue*/ )
812 throw( IllegalArgumentException
)
817 //------------------------------------------------------------------------------
818 void FormController::setFastPropertyValue_NoBroadcast( sal_Int32
/*nHandle*/, const Any
& /*rValue*/ )
823 //------------------------------------------------------------------------------
824 void FormController::getFastPropertyValue( Any
& rValue
, sal_Int32 nHandle
) const
830 OUStringBuffer aFilter
;
831 OStaticDataAccessTools aStaticTools
;
832 Reference
<XConnection
> xConnection(aStaticTools
.getRowSetConnection(Reference
< XRowSet
>(m_xModelAsIndex
, UNO_QUERY
)));
833 if (xConnection
.is())
835 Reference
< XDatabaseMetaData
> xMetaData(xConnection
->getMetaData());
836 Reference
< XNumberFormatsSupplier
> xFormatSupplier( aStaticTools
.getNumberFormats( xConnection
, sal_True
) );
837 Reference
< XNumberFormatter
> xFormatter( NumberFormatter::create(m_aContext
.getUNOContext()), UNO_QUERY_THROW
);
838 xFormatter
->attachNumberFormatsSupplier(xFormatSupplier
);
840 Reference
< XColumnsSupplier
> xSupplyCols(m_xModelAsIndex
, UNO_QUERY
);
841 Reference
< XNameAccess
> xFields(xSupplyCols
->getColumns(), UNO_QUERY
);
843 // now add the filter rows
846 for ( FmFilterRows::const_iterator row
= m_aFilterRows
.begin(); row
!= m_aFilterRows
.end(); ++row
)
848 const FmFilterRow
& rRow
= *row
;
853 OUStringBuffer aRowFilter
;
854 for ( FmFilterRow::const_iterator condition
= rRow
.begin(); condition
!= rRow
.end(); ++condition
)
856 // get the field of the controls map
857 Reference
< XControl
> xControl( condition
->first
, UNO_QUERY_THROW
);
858 Reference
< XPropertySet
> xModelProps( xControl
->getModel(), UNO_QUERY_THROW
);
859 Reference
< XPropertySet
> xField( xModelProps
->getPropertyValue( FM_PROP_BOUNDFIELD
), UNO_QUERY_THROW
);
861 OUString
sFilterValue( condition
->second
);
863 OUString sErrorMsg
, sCriteria
;
864 const ::rtl::Reference
< ISQLParseNode
> xParseNode
=
865 predicateTree( sErrorMsg
, sFilterValue
, xFormatter
, xField
);
866 OSL_ENSURE( xParseNode
.is(), "FormController::getFastPropertyValue: could not parse the field value predicate!" );
867 if ( xParseNode
.is() )
869 // don't use a parse context here, we need it unlocalized
870 xParseNode
->parseNodeToStr( sCriteria
, xConnection
, NULL
);
871 if ( condition
!= rRow
.begin() )
872 aRowFilter
.appendAscii( " AND " );
873 aRowFilter
.append( sCriteria
);
876 if ( aRowFilter
.getLength() > 0 )
878 if ( aFilter
.getLength() )
879 aFilter
.appendAscii( " OR " );
881 aFilter
.appendAscii( "( " );
882 aFilter
.append( aRowFilter
.makeStringAndClear() );
883 aFilter
.appendAscii( " )" );
887 catch( const Exception
& )
889 DBG_UNHANDLED_EXCEPTION();
890 aFilter
.setLength(0);
893 rValue
<<= aFilter
.makeStringAndClear();
897 case FM_ATTR_FORM_OPERATIONS
:
898 rValue
<<= m_xFormOperations
;
903 //------------------------------------------------------------------------------
904 Reference
< XPropertySetInfo
> FormController::getPropertySetInfo() throw( RuntimeException
)
906 static Reference
< XPropertySetInfo
> xInfo( createPropertySetInfo( getInfoHelper() ) );
910 //------------------------------------------------------------------------------
911 #define DECL_PROP_CORE(varname, type) \
912 pDesc[nPos++] = Property(FM_PROP_##varname, FM_ATTR_##varname, ::getCppuType((const type*)0),
915 #define DECL_PROP1(varname, type, attrib1) \
916 DECL_PROP_CORE(varname, type) PropertyAttribute::attrib1)
918 //------------------------------------------------------------------------------
919 void FormController::fillProperties(
920 Sequence
< Property
>& /* [out] */ _rProps
,
921 Sequence
< Property
>& /* [out] */ /*_rAggregateProps*/
926 Property
* pDesc
= _rProps
.getArray();
927 DECL_PROP1(FILTER
, OUString
, READONLY
);
928 DECL_PROP1(FORM_OPERATIONS
, Reference
< XFormOperations
>, READONLY
);
931 //------------------------------------------------------------------------------
932 ::cppu::IPropertyArrayHelper
& FormController::getInfoHelper()
934 return *getArrayHelper();
938 //------------------------------------------------------------------------------
939 void SAL_CALL
FormController::addFilterControllerListener( const Reference
< XFilterControllerListener
>& _Listener
) throw( RuntimeException
)
941 m_aFilterListeners
.addInterface( _Listener
);
944 //------------------------------------------------------------------------------
945 void SAL_CALL
FormController::removeFilterControllerListener( const Reference
< XFilterControllerListener
>& _Listener
) throw( RuntimeException
)
947 m_aFilterListeners
.removeInterface( _Listener
);
950 //------------------------------------------------------------------------------
951 ::sal_Int32 SAL_CALL
FormController::getFilterComponents() throw( ::com::sun::star::uno::RuntimeException
)
953 ::osl::MutexGuard
aGuard( m_aMutex
);
954 impl_checkDisposed_throw();
956 return m_aFilterComponents
.size();
959 //------------------------------------------------------------------------------
960 ::sal_Int32 SAL_CALL
FormController::getDisjunctiveTerms() throw( ::com::sun::star::uno::RuntimeException
)
962 ::osl::MutexGuard
aGuard( m_aMutex
);
963 impl_checkDisposed_throw();
965 return m_aFilterRows
.size();
968 //------------------------------------------------------------------------------
969 void SAL_CALL
FormController::setPredicateExpression( ::sal_Int32 _Component
, ::sal_Int32 _Term
, const OUString
& _PredicateExpression
) throw( RuntimeException
, IndexOutOfBoundsException
)
971 ::osl::MutexGuard
aGuard( m_aMutex
);
972 impl_checkDisposed_throw();
974 if ( ( _Component
< 0 ) || ( _Component
>= getFilterComponents() ) || ( _Term
< 0 ) || ( _Term
>= getDisjunctiveTerms() ) )
975 throw IndexOutOfBoundsException( OUString(), *this );
977 Reference
< XTextComponent
> xText( m_aFilterComponents
[ _Component
] );
978 xText
->setText( _PredicateExpression
);
980 FmFilterRow
& rFilterRow
= m_aFilterRows
[ _Term
];
981 if ( !_PredicateExpression
.isEmpty() )
982 rFilterRow
[ xText
] = _PredicateExpression
;
984 rFilterRow
.erase( xText
);
987 //------------------------------------------------------------------------------
988 Reference
< XControl
> FormController::getFilterComponent( ::sal_Int32 _Component
) throw( RuntimeException
, IndexOutOfBoundsException
)
990 ::osl::MutexGuard
aGuard( m_aMutex
);
991 impl_checkDisposed_throw();
993 if ( ( _Component
< 0 ) || ( _Component
>= getFilterComponents() ) )
994 throw IndexOutOfBoundsException( OUString(), *this );
996 return Reference
< XControl
>( m_aFilterComponents
[ _Component
], UNO_QUERY
);
999 //------------------------------------------------------------------------------
1000 Sequence
< Sequence
< OUString
> > FormController::getPredicateExpressions() throw( RuntimeException
)
1002 ::osl::MutexGuard
aGuard( m_aMutex
);
1003 impl_checkDisposed_throw();
1005 Sequence
< Sequence
< OUString
> > aExpressions( m_aFilterRows
.size() );
1006 sal_Int32 termIndex
= 0;
1007 for ( FmFilterRows::const_iterator row
= m_aFilterRows
.begin();
1008 row
!= m_aFilterRows
.end();
1012 const FmFilterRow
& rRow( *row
);
1014 Sequence
< OUString
> aConjunction( m_aFilterComponents
.size() );
1015 sal_Int32 componentIndex
= 0;
1016 for ( FilterComponents::const_iterator comp
= m_aFilterComponents
.begin();
1017 comp
!= m_aFilterComponents
.end();
1018 ++comp
, ++componentIndex
1021 FmFilterRow::const_iterator predicate
= rRow
.find( *comp
);
1022 if ( predicate
!= rRow
.end() )
1023 aConjunction
[ componentIndex
] = predicate
->second
;
1026 aExpressions
[ termIndex
] = aConjunction
;
1029 return aExpressions
;
1032 //------------------------------------------------------------------------------
1033 void SAL_CALL
FormController::removeDisjunctiveTerm( ::sal_Int32 _Term
) throw (IndexOutOfBoundsException
, RuntimeException
)
1036 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
1037 impl_checkDisposed_throw();
1039 if ( ( _Term
< 0 ) || ( _Term
>= getDisjunctiveTerms() ) )
1040 throw IndexOutOfBoundsException( OUString(), *this );
1042 // if the to-be-deleted row is our current row, we need to shift
1043 if ( _Term
== m_nCurrentFilterPosition
)
1045 if ( m_nCurrentFilterPosition
< sal_Int32( m_aFilterRows
.size() - 1 ) )
1046 ++m_nCurrentFilterPosition
;
1048 --m_nCurrentFilterPosition
;
1051 FmFilterRows::iterator pos
= m_aFilterRows
.begin() + _Term
;
1052 m_aFilterRows
.erase( pos
);
1054 // adjust m_nCurrentFilterPosition if the removed row preceeded it
1055 if ( _Term
< m_nCurrentFilterPosition
)
1056 --m_nCurrentFilterPosition
;
1058 OSL_POSTCOND( ( m_nCurrentFilterPosition
< 0 ) == ( m_aFilterRows
.empty() ),
1059 "FormController::removeDisjunctiveTerm: inconsistency!" );
1061 // update the texts in the filter controls
1062 impl_setTextOnAllFilter_throw();
1065 aEvent
.Source
= *this;
1066 aEvent
.DisjunctiveTerm
= _Term
;
1070 m_aFilterListeners
.notifyEach( &XFilterControllerListener::disjunctiveTermRemoved
, aEvent
);
1073 //------------------------------------------------------------------------------
1074 void SAL_CALL
FormController::appendEmptyDisjunctiveTerm() throw (RuntimeException
)
1077 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
1078 impl_checkDisposed_throw();
1080 impl_appendEmptyFilterRow( aGuard
);
1084 //------------------------------------------------------------------------------
1085 ::sal_Int32 SAL_CALL
FormController::getActiveTerm() throw (RuntimeException
)
1087 ::osl::MutexGuard
aGuard( m_aMutex
);
1088 impl_checkDisposed_throw();
1090 return m_nCurrentFilterPosition
;
1093 //------------------------------------------------------------------------------
1094 void SAL_CALL
FormController::setActiveTerm( ::sal_Int32 _ActiveTerm
) throw (IndexOutOfBoundsException
, RuntimeException
)
1096 ::osl::MutexGuard
aGuard( m_aMutex
);
1097 impl_checkDisposed_throw();
1099 if ( ( _ActiveTerm
< 0 ) || ( _ActiveTerm
>= getDisjunctiveTerms() ) )
1100 throw IndexOutOfBoundsException( OUString(), *this );
1102 if ( _ActiveTerm
== getActiveTerm() )
1105 m_nCurrentFilterPosition
= _ActiveTerm
;
1106 impl_setTextOnAllFilter_throw();
1110 //------------------------------------------------------------------------------
1111 sal_Bool SAL_CALL
FormController::hasElements(void) throw( RuntimeException
)
1113 ::osl::MutexGuard
aGuard( m_aMutex
);
1114 return !m_aChildren
.empty();
1117 //------------------------------------------------------------------------------
1118 Type SAL_CALL
FormController::getElementType(void) throw( RuntimeException
)
1120 return ::getCppuType((const Reference
< XFormController
>*)0);
1124 // XEnumerationAccess
1125 //------------------------------------------------------------------------------
1126 Reference
< XEnumeration
> SAL_CALL
FormController::createEnumeration(void) throw( RuntimeException
)
1128 ::osl::MutexGuard
aGuard( m_aMutex
);
1129 return new ::comphelper::OEnumerationByIndex(this);
1133 //------------------------------------------------------------------------------
1134 sal_Int32 SAL_CALL
FormController::getCount(void) throw( RuntimeException
)
1136 ::osl::MutexGuard
aGuard( m_aMutex
);
1137 return m_aChildren
.size();
1140 //------------------------------------------------------------------------------
1141 Any SAL_CALL
FormController::getByIndex(sal_Int32 Index
) throw( IndexOutOfBoundsException
, WrappedTargetException
, RuntimeException
)
1143 ::osl::MutexGuard
aGuard( m_aMutex
);
1145 Index
>= (sal_Int32
)m_aChildren
.size())
1146 throw IndexOutOfBoundsException();
1148 return makeAny( m_aChildren
[ Index
] );
1152 //------------------------------------------------------------------------------
1153 void SAL_CALL
FormController::disposing(const EventObject
& e
) throw( RuntimeException
)
1155 // Ist der Container disposed worden
1156 ::osl::MutexGuard
aGuard( m_aMutex
);
1157 Reference
< XControlContainer
> xContainer(e
.Source
, UNO_QUERY
);
1158 if (xContainer
.is())
1160 setContainer(Reference
< XControlContainer
> ());
1164 // ist ein Control disposed worden
1165 Reference
< XControl
> xControl(e
.Source
, UNO_QUERY
);
1168 if (getContainer().is())
1169 removeControl(xControl
);
1175 //-----------------------------------------------------------------------------
1176 void FormController::disposeAllFeaturesAndDispatchers() SAL_THROW(())
1178 for ( DispatcherContainer::iterator aDispatcher
= m_aFeatureDispatchers
.begin();
1179 aDispatcher
!= m_aFeatureDispatchers
.end();
1185 ::comphelper::disposeComponent( aDispatcher
->second
);
1187 catch( const Exception
& )
1189 DBG_UNHANDLED_EXCEPTION();
1192 m_aFeatureDispatchers
.clear();
1195 //-----------------------------------------------------------------------------
1196 void FormController::disposing(void)
1198 EventObject
aEvt( *this );
1200 // if we're still active, simulate a "deactivated" event
1201 if ( m_xActiveControl
.is() )
1202 m_aActivateListeners
.notifyEach( &XFormControllerListener::formDeactivated
, aEvt
);
1204 // notify all our listeners
1205 m_aActivateListeners
.disposeAndClear(aEvt
);
1206 m_aModifyListeners
.disposeAndClear(aEvt
);
1207 m_aErrorListeners
.disposeAndClear(aEvt
);
1208 m_aDeleteListeners
.disposeAndClear(aEvt
);
1209 m_aRowSetApproveListeners
.disposeAndClear(aEvt
);
1210 m_aParameterListeners
.disposeAndClear(aEvt
);
1211 m_aFilterListeners
.disposeAndClear(aEvt
);
1213 removeBoundFieldListener();
1216 m_pControlBorderManager
->restoreAll();
1218 m_aFilterRows
.clear();
1220 ::osl::MutexGuard
aGuard( m_aMutex
);
1221 m_xActiveControl
= NULL
;
1222 implSetCurrentControl( NULL
);
1224 // clean up our children
1225 for (FmFormControllers::const_iterator i
= m_aChildren
.begin();
1226 i
!= m_aChildren
.end(); ++i
)
1228 // search the position of the model within the form
1229 Reference
< XFormComponent
> xForm((*i
)->getModel(), UNO_QUERY
);
1230 sal_uInt32 nPos
= m_xModelAsIndex
->getCount();
1231 Reference
< XFormComponent
> xTemp
;
1235 m_xModelAsIndex
->getByIndex( --nPos
) >>= xTemp
;
1236 if ( xForm
.get() == xTemp
.get() )
1238 Reference
< XInterface
> xIfc( *i
, UNO_QUERY
);
1239 m_xModelAsManager
->detach( nPos
, xIfc
);
1244 Reference
< XComponent
> (*i
, UNO_QUERY
)->dispose();
1246 m_aChildren
.clear();
1248 disposeAllFeaturesAndDispatchers();
1250 if ( m_xFormOperations
.is() )
1251 m_xFormOperations
->dispose();
1252 m_xFormOperations
.clear();
1254 if (m_bDBConnection
)
1257 setContainer( NULL
);
1261 ::comphelper::disposeComponent( m_xComposer
);
1263 m_bDBConnection
= sal_False
;
1266 //------------------------------------------------------------------------------
1269 static bool lcl_shouldUseDynamicControlBorder( const Reference
< XInterface
>& _rxForm
, const Any
& _rDynamicColorProp
)
1271 bool bDoUse
= false;
1272 if ( !( _rDynamicColorProp
>>= bDoUse
) )
1274 DocumentType eDocType
= DocumentClassification::classifyHostDocument( _rxForm
);
1275 return ControlLayouter::useDynamicBorderColor( eDocType
);
1281 //------------------------------------------------------------------------------
1282 void SAL_CALL
FormController::propertyChange(const PropertyChangeEvent
& evt
) throw( RuntimeException
)
1284 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1285 if ( evt
.PropertyName
== FM_PROP_BOUNDFIELD
)
1287 Reference
<XPropertySet
> xOldBound
;
1288 evt
.OldValue
>>= xOldBound
;
1289 if ( !xOldBound
.is() && evt
.NewValue
.hasValue() )
1291 Reference
< XControlModel
> xControlModel(evt
.Source
,UNO_QUERY
);
1292 Reference
< XControl
> xControl
= findControl(m_aControls
,xControlModel
,sal_False
,sal_False
);
1293 if ( xControl
.is() )
1295 startControlModifyListening( xControl
);
1296 Reference
<XPropertySet
> xProp(xControlModel
,UNO_QUERY
);
1298 xProp
->removePropertyChangeListener(FM_PROP_BOUNDFIELD
, this);
1304 sal_Bool bModifiedChanged
= (evt
.PropertyName
== FM_PROP_ISMODIFIED
);
1305 sal_Bool bNewChanged
= (evt
.PropertyName
== FM_PROP_ISNEW
);
1306 if (bModifiedChanged
|| bNewChanged
)
1308 ::osl::MutexGuard
aGuard( m_aMutex
);
1309 if (bModifiedChanged
)
1310 m_bCurrentRecordModified
= ::comphelper::getBOOL(evt
.NewValue
);
1312 m_bCurrentRecordNew
= ::comphelper::getBOOL(evt
.NewValue
);
1314 // toggle the locking
1315 if (m_bLocked
!= determineLockState())
1317 m_bLocked
= !m_bLocked
;
1319 if (isListeningForChanges())
1326 m_aToggleEvent
.Call();
1328 if (!m_bCurrentRecordModified
)
1329 m_bModified
= sal_False
;
1331 else if ( evt
.PropertyName
== FM_PROP_DYNAMIC_CONTROL_BORDER
)
1333 bool bEnable
= lcl_shouldUseDynamicControlBorder( evt
.Source
, evt
.NewValue
);
1336 m_pControlBorderManager
->enableDynamicBorderColor();
1337 if ( m_xActiveControl
.is() )
1338 m_pControlBorderManager
->focusGained( m_xActiveControl
.get() );
1342 m_pControlBorderManager
->disableDynamicBorderColor();
1348 //------------------------------------------------------------------------------
1349 bool FormController::replaceControl( const Reference
< XControl
>& _rxExistentControl
, const Reference
< XControl
>& _rxNewControl
)
1351 bool bSuccess
= false;
1354 Reference
< XIdentifierReplace
> xContainer( getContainer(), UNO_QUERY
);
1355 DBG_ASSERT( xContainer
.is(), "FormController::replaceControl: yes, it's not required by the service description, but XItentifierReplaces would be nice!" );
1356 if ( xContainer
.is() )
1358 // look up the ID of _rxExistentControl
1359 Sequence
< sal_Int32
> aIdentifiers( xContainer
->getIdentifiers() );
1360 const sal_Int32
* pIdentifiers
= aIdentifiers
.getConstArray();
1361 const sal_Int32
* pIdentifiersEnd
= aIdentifiers
.getConstArray() + aIdentifiers
.getLength();
1362 for ( ; pIdentifiers
!= pIdentifiersEnd
; ++pIdentifiers
)
1364 Reference
< XControl
> xCheck( xContainer
->getByIdentifier( *pIdentifiers
), UNO_QUERY
);
1365 if ( xCheck
== _rxExistentControl
)
1368 DBG_ASSERT( pIdentifiers
!= pIdentifiersEnd
, "FormController::replaceControl: did not find the control in the container!" );
1369 if ( pIdentifiers
!= pIdentifiersEnd
)
1371 bool bReplacedWasActive
= ( m_xActiveControl
.get() == _rxExistentControl
.get() );
1372 bool bReplacedWasCurrent
= ( m_xCurrentControl
.get() == _rxExistentControl
.get() );
1374 if ( bReplacedWasActive
)
1376 m_xActiveControl
= NULL
;
1377 implSetCurrentControl( NULL
);
1379 else if ( bReplacedWasCurrent
)
1381 implSetCurrentControl( _rxNewControl
);
1384 // carry over the model
1385 _rxNewControl
->setModel( _rxExistentControl
->getModel() );
1387 xContainer
->replaceByIdentifer( *pIdentifiers
, makeAny( _rxNewControl
) );
1390 if ( bReplacedWasActive
)
1392 Reference
< XWindow
> xControlWindow( _rxNewControl
, UNO_QUERY
);
1393 if ( xControlWindow
.is() )
1394 xControlWindow
->setFocus();
1399 catch( const Exception
& )
1401 DBG_UNHANDLED_EXCEPTION();
1404 Reference
< XControl
> xDisposeIt( bSuccess
? _rxExistentControl
: _rxNewControl
);
1405 ::comphelper::disposeComponent( xDisposeIt
);
1409 //------------------------------------------------------------------------------
1410 void FormController::toggleAutoFields(sal_Bool bAutoFields
)
1412 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1415 Sequence
< Reference
< XControl
> > aControlsCopy( m_aControls
);
1416 const Reference
< XControl
>* pControls
= aControlsCopy
.getConstArray();
1417 sal_Int32 nControls
= aControlsCopy
.getLength();
1421 // as we don't want new controls to be attached to the scripting environment
1422 // we change attach flags
1423 m_bAttachEvents
= sal_False
;
1424 for (sal_Int32 i
= nControls
; i
> 0;)
1426 Reference
< XControl
> xControl
= pControls
[--i
];
1429 Reference
< XPropertySet
> xSet(xControl
->getModel(), UNO_QUERY
);
1430 if (xSet
.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD
, xSet
))
1432 // does the model use a bound field ?
1433 Reference
< XPropertySet
> xField
;
1434 xSet
->getPropertyValue(FM_PROP_BOUNDFIELD
) >>= xField
;
1436 // is it a autofield?
1438 && ::comphelper::hasProperty( FM_PROP_AUTOINCREMENT
, xField
)
1439 && ::comphelper::getBOOL( xField
->getPropertyValue( FM_PROP_AUTOINCREMENT
) )
1442 replaceControl( xControl
, new FmXAutoControl() );
1447 m_bAttachEvents
= sal_True
;
1451 m_bDetachEvents
= sal_False
;
1452 for (sal_Int32 i
= nControls
; i
> 0;)
1454 Reference
< XControl
> xControl
= pControls
[--i
];
1457 Reference
< XPropertySet
> xSet(xControl
->getModel(), UNO_QUERY
);
1458 if (xSet
.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD
, xSet
))
1460 // does the model use a bound field ?
1461 Reference
< XPropertySet
> xField
;
1462 xSet
->getPropertyValue(FM_PROP_BOUNDFIELD
) >>= xField
;
1464 // is it a autofield?
1466 && ::comphelper::hasProperty( FM_PROP_AUTOINCREMENT
, xField
)
1467 && ::comphelper::getBOOL( xField
->getPropertyValue(FM_PROP_AUTOINCREMENT
) )
1470 OUString sServiceName
;
1471 OSL_VERIFY( xSet
->getPropertyValue( FM_PROP_DEFAULTCONTROL
) >>= sServiceName
);
1472 Reference
< XControl
> xNewControl( m_aContext
.createComponent( sServiceName
), UNO_QUERY
);
1473 replaceControl( xControl
, xNewControl
);
1478 m_bDetachEvents
= sal_True
;
1482 //------------------------------------------------------------------------------
1483 IMPL_LINK_NOARG(FormController
, OnToggleAutoFields
)
1485 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1487 toggleAutoFields(m_bCurrentRecordNew
);
1492 //------------------------------------------------------------------------------
1493 void SAL_CALL
FormController::textChanged(const TextEvent
& e
) throw( RuntimeException
)
1496 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
1497 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1498 if ( !m_bFiltering
)
1504 if ( m_bSuspendFilterTextListening
)
1507 Reference
< XTextComponent
> xText(e
.Source
,UNO_QUERY
);
1508 OUString aText
= xText
->getText();
1510 if ( m_aFilterRows
.empty() )
1511 appendEmptyDisjunctiveTerm();
1513 // Suchen der aktuellen Row
1514 if ( ( (size_t)m_nCurrentFilterPosition
>= m_aFilterRows
.size() ) || ( m_nCurrentFilterPosition
< 0 ) )
1516 OSL_ENSURE( false, "FormController::textChanged: m_nCurrentFilterPosition is wrong!" );
1520 FmFilterRow
& rRow
= m_aFilterRows
[ m_nCurrentFilterPosition
];
1522 // do we have a new filter
1523 if (!aText
.isEmpty())
1524 rRow
[xText
] = aText
;
1527 // do we have the control in the row
1528 FmFilterRow::iterator iter
= rRow
.find(xText
);
1529 // erase the entry out of the row
1530 if (iter
!= rRow
.end())
1534 // multiplex the event to our FilterControllerListeners
1536 aEvent
.Source
= *this;
1537 aEvent
.FilterComponent
= ::std::find( m_aFilterComponents
.begin(), m_aFilterComponents
.end(), xText
) - m_aFilterComponents
.begin();
1538 aEvent
.DisjunctiveTerm
= getActiveTerm();
1539 aEvent
.PredicateExpression
= aText
;
1544 // notify the changed filter expression
1545 m_aFilterListeners
.notifyEach( &XFilterControllerListener::predicateExpressionChanged
, aEvent
);
1549 //------------------------------------------------------------------------------
1550 void SAL_CALL
FormController::itemStateChanged(const ItemEvent
& /*rEvent*/) throw( RuntimeException
)
1552 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1556 // XModificationBroadcaster
1557 //------------------------------------------------------------------------------
1558 void SAL_CALL
FormController::addModifyListener(const Reference
< XModifyListener
> & l
) throw( RuntimeException
)
1560 ::osl::MutexGuard
aGuard( m_aMutex
);
1561 impl_checkDisposed_throw();
1562 m_aModifyListeners
.addInterface( l
);
1565 //------------------------------------------------------------------------------
1566 void FormController::removeModifyListener(const Reference
< XModifyListener
> & l
) throw( RuntimeException
)
1568 ::osl::MutexGuard
aGuard( m_aMutex
);
1569 impl_checkDisposed_throw();
1570 m_aModifyListeners
.removeInterface( l
);
1573 // XModificationListener
1574 //------------------------------------------------------------------------------
1575 void FormController::modified( const EventObject
& _rEvent
) throw( RuntimeException
)
1577 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1581 if ( _rEvent
.Source
!= m_xActiveControl
)
1582 { // let this control grab the focus
1583 // (this case may happen if somebody moves the scroll wheel of the mouse over a control
1584 // which does not have the focus)
1585 // 85511 - 29.05.2001 - frank.schoenheit@germany.sun.com
1587 // also, it happens when an image control gets a new image by double-clicking it
1588 // #i88458# / 2009-01-12 / frank.schoenheit@sun.com
1589 Reference
< XWindow
> xControlWindow( _rEvent
.Source
, UNO_QUERY_THROW
);
1590 xControlWindow
->setFocus();
1593 catch( const Exception
& )
1595 DBG_UNHANDLED_EXCEPTION();
1601 //------------------------------------------------------------------------------
1602 void FormController::impl_checkDisposed_throw() const
1604 if ( impl_isDisposed_nofail() )
1605 throw DisposedException( OUString(), *const_cast< FormController
* >( this ) );
1608 //------------------------------------------------------------------------------
1609 void FormController::impl_onModify()
1611 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1614 ::osl::MutexGuard
aGuard( m_aMutex
);
1616 m_bModified
= sal_True
;
1619 EventObject
aEvt(static_cast<cppu::OWeakObject
*>(this));
1620 m_aModifyListeners
.notifyEach( &XModifyListener::modified
, aEvt
);
1623 //------------------------------------------------------------------------------
1624 void FormController::impl_addFilterRow( const FmFilterRow
& _row
)
1626 m_aFilterRows
.push_back( _row
);
1628 if ( m_aFilterRows
.size() == 1 )
1629 { // that's the first row ever
1630 OSL_ENSURE( m_nCurrentFilterPosition
== -1, "FormController::impl_addFilterRow: inconsistency!" );
1631 m_nCurrentFilterPosition
= 0;
1635 //------------------------------------------------------------------------------
1636 void FormController::impl_appendEmptyFilterRow( ::osl::ClearableMutexGuard
& _rClearBeforeNotify
)
1639 impl_addFilterRow( FmFilterRow() );
1641 // notify the listeners
1643 aEvent
.Source
= *this;
1644 aEvent
.DisjunctiveTerm
= (sal_Int32
)m_aFilterRows
.size() - 1;
1645 _rClearBeforeNotify
.clear();
1647 m_aFilterListeners
.notifyEach( &XFilterControllerListener::disjunctiveTermAdded
, aEvent
);
1650 //------------------------------------------------------------------------------
1651 sal_Bool
FormController::determineLockState() const
1653 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1654 // a.) in filter mode we are always locked
1655 // b.) if we have no valid model or our model (a result set) is not alive -> we're locked
1656 // c.) if we are inserting everything is OK and we are not locked
1657 // d.) if are not updatable or on invalid position
1658 Reference
< XResultSet
> xResultSet(m_xModelAsIndex
, UNO_QUERY
);
1659 if (m_bFiltering
|| !xResultSet
.is() || !isRowSetAlive(xResultSet
))
1662 return (m_bCanInsert
&& m_bCurrentRecordNew
) ? sal_False
1663 : xResultSet
->isBeforeFirst() || xResultSet
->isAfterLast() || xResultSet
->rowDeleted() || !m_bCanUpdate
;
1667 //------------------------------------------------------------------------------
1668 void FormController::focusGained(const FocusEvent
& e
) throw( RuntimeException
)
1671 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
1672 impl_checkDisposed_throw();
1674 m_pControlBorderManager
->focusGained( e
.Source
);
1676 Reference
< XControl
> xControl(e
.Source
, UNO_QUERY
);
1677 if (m_bDBConnection
)
1679 // do we need to keep the locking of the commit
1680 // we hold the lock as long as the control differs from the current
1681 // otherwise we disabled the lock
1682 m_bCommitLock
= m_bCommitLock
&& (XControl
*)xControl
.get() != (XControl
*)m_xCurrentControl
.get();
1686 // when do we have to commit a value to form or a filter
1687 // a.) if the current value is modified
1688 // b.) there must be a current control
1689 // c.) and it must be different from the new focus owning control or
1690 // d.) the focus is moving around (so we have only one control)
1692 if ( ( m_bModified
|| m_bFiltering
)
1693 && m_xCurrentControl
.is()
1694 && ( ( xControl
.get() != m_xCurrentControl
.get() )
1695 || ( ( e
.FocusFlags
& FocusChangeReason::AROUND
)
1696 && ( m_bCycle
|| m_bFiltering
)
1701 // check the old control if the content is ok
1702 #if OSL_DEBUG_LEVEL > 1
1703 Reference
< XBoundControl
> xLockingTest(m_xCurrentControl
, UNO_QUERY
);
1704 sal_Bool bControlIsLocked
= xLockingTest
.is() && xLockingTest
->getLock();
1705 OSL_ENSURE(!bControlIsLocked
, "FormController::Gained: I'm modified and the current control is locked ? How this ?");
1706 // normalerweise sollte ein gelocktes Control nicht modified sein, also muss wohl mein bModified aus einem anderen Kontext
1707 // gesetzt worden sein, was ich nicht verstehen wuerde ...
1709 DBG_ASSERT(m_xCurrentControl
.is(), "kein CurrentControl gesetzt");
1710 // zunaechst das Control fragen ob es das IFace unterstuetzt
1711 Reference
< XBoundComponent
> xBound(m_xCurrentControl
, UNO_QUERY
);
1712 if (!xBound
.is() && m_xCurrentControl
.is())
1713 xBound
= Reference
< XBoundComponent
> (m_xCurrentControl
->getModel(), UNO_QUERY
);
1715 // lock if we lose the focus during commit
1716 m_bCommitLock
= sal_True
;
1718 // Commit nicht erfolgreich, Focus zuruecksetzen
1719 if (xBound
.is() && !xBound
->commit())
1721 // the commit failed and we don't commit again until the current control
1722 // which couldn't be commit gains the focus again
1723 Reference
< XWindow
> xWindow(m_xCurrentControl
, UNO_QUERY
);
1725 xWindow
->setFocus();
1730 m_bModified
= sal_False
;
1731 m_bCommitLock
= sal_False
;
1735 if (!m_bFiltering
&& m_bCycle
&& (e
.FocusFlags
& FocusChangeReason::AROUND
) && m_xCurrentControl
.is())
1737 SQLErrorEvent aErrorEvent
;
1738 OSL_ENSURE( m_xFormOperations
.is(), "FormController::focusGained: hmm?" );
1739 // should have been created in setModel
1742 if ( e
.FocusFlags
& FocusChangeReason::FORWARD
)
1744 if ( m_xFormOperations
.is() && m_xFormOperations
->isEnabled( FormFeature::MoveToNext
) )
1745 m_xFormOperations
->execute( FormFeature::MoveToNext
);
1749 if ( m_xFormOperations
.is() && m_xFormOperations
->isEnabled( FormFeature::MoveToPrevious
) )
1750 m_xFormOperations
->execute( FormFeature::MoveToPrevious
);
1753 catch ( const Exception
& )
1755 // don't handle this any further. That's an ... admissible error.
1756 DBG_UNHANDLED_EXCEPTION();
1761 // Immer noch ein und dasselbe Control
1762 if ( ( m_xActiveControl
== xControl
)
1763 && ( xControl
== m_xCurrentControl
)
1766 DBG_ASSERT(m_xCurrentControl
.is(), "Kein CurrentControl selektiert");
1770 sal_Bool bActivated
= !m_xActiveControl
.is() && xControl
.is();
1772 m_xActiveControl
= xControl
;
1774 implSetCurrentControl( xControl
);
1775 OSL_POSTCOND( m_xCurrentControl
.is(), "implSetCurrentControl did nonsense!" );
1779 // (asynchronously) call activation handlers
1780 m_aActivationEvent
.Call();
1782 // call modify listeners
1784 m_aModifyListeners
.notifyEach( &XModifyListener::modified
, EventObject( *this ) );
1787 // invalidate all features which depend on the currently focused control
1788 if ( m_bDBConnection
&& !m_bFiltering
)
1789 implInvalidateCurrentControlDependentFeatures();
1791 if ( !m_xCurrentControl
.is() )
1794 // Control erhaelt Focus, dann eventuell in den sichtbaren Bereich
1795 Reference
< XFormControllerContext
> xContext( m_xContext
);
1796 Reference
< XControl
> xCurrentControl( m_xCurrentControl
);
1800 if ( xContext
.is() )
1801 xContext
->makeVisible( xCurrentControl
);
1804 //------------------------------------------------------------------------------
1805 IMPL_LINK( FormController
, OnActivated
, void*, /**/ )
1808 aEvent
.Source
= *this;
1809 m_aActivateListeners
.notifyEach( &XFormControllerListener::formActivated
, aEvent
);
1814 //------------------------------------------------------------------------------
1815 IMPL_LINK( FormController
, OnDeactivated
, void*, /**/ )
1818 aEvent
.Source
= *this;
1819 m_aActivateListeners
.notifyEach( &XFormControllerListener::formDeactivated
, aEvent
);
1824 //------------------------------------------------------------------------------
1825 void FormController::focusLost(const FocusEvent
& e
) throw( RuntimeException
)
1827 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1829 m_pControlBorderManager
->focusLost( e
.Source
);
1831 Reference
< XControl
> xControl(e
.Source
, UNO_QUERY
);
1832 Reference
< XWindowPeer
> xNext(e
.NextFocus
, UNO_QUERY
);
1833 Reference
< XControl
> xNextControl
= isInList(xNext
);
1834 if (!xNextControl
.is())
1836 m_xActiveControl
= NULL
;
1837 m_aDeactivationEvent
.Call();
1841 //--------------------------------------------------------------------
1842 void SAL_CALL
FormController::mousePressed( const awt::MouseEvent
& /*_rEvent*/ ) throw (RuntimeException
)
1844 // not interested in
1847 //--------------------------------------------------------------------
1848 void SAL_CALL
FormController::mouseReleased( const awt::MouseEvent
& /*_rEvent*/ ) throw (RuntimeException
)
1850 // not interested in
1853 //--------------------------------------------------------------------
1854 void SAL_CALL
FormController::mouseEntered( const awt::MouseEvent
& _rEvent
) throw (RuntimeException
)
1856 m_pControlBorderManager
->mouseEntered( _rEvent
.Source
);
1859 //--------------------------------------------------------------------
1860 void SAL_CALL
FormController::mouseExited( const awt::MouseEvent
& _rEvent
) throw (RuntimeException
)
1862 m_pControlBorderManager
->mouseExited( _rEvent
.Source
);
1865 //--------------------------------------------------------------------
1866 void SAL_CALL
FormController::componentValidityChanged( const EventObject
& _rSource
) throw (RuntimeException
)
1868 Reference
< XControl
> xControl( findControl( m_aControls
, Reference
< XControlModel
>( _rSource
.Source
, UNO_QUERY
), sal_False
, sal_False
) );
1869 Reference
< XValidatableFormComponent
> xValidatable( _rSource
.Source
, UNO_QUERY
);
1871 OSL_ENSURE( xControl
.is() && xValidatable
.is(), "FormController::componentValidityChanged: huh?" );
1873 if ( xControl
.is() && xValidatable
.is() )
1874 m_pControlBorderManager
->validityChanged( xControl
, xValidatable
);
1877 //--------------------------------------------------------------------
1878 void FormController::setModel(const Reference
< XTabControllerModel
> & Model
) throw( RuntimeException
)
1880 ::osl::MutexGuard
aGuard( m_aMutex
);
1881 impl_checkDisposed_throw();
1883 DBG_ASSERT(m_xTabController
.is(), "FormController::setModel : invalid aggregate !");
1887 // disconnect from the old model
1888 if (m_xModelAsIndex
.is())
1890 if (m_bDBConnection
)
1892 // we are currently working on the model
1893 EventObject
aEvt(m_xModelAsIndex
);
1897 Reference
< XLoadable
> xForm(m_xModelAsIndex
, UNO_QUERY
);
1899 xForm
->removeLoadListener(this);
1901 Reference
< XSQLErrorBroadcaster
> xBroadcaster(m_xModelAsIndex
, UNO_QUERY
);
1902 if (xBroadcaster
.is())
1903 xBroadcaster
->removeSQLErrorListener(this);
1905 Reference
< XDatabaseParameterBroadcaster
> xParamBroadcaster(m_xModelAsIndex
, UNO_QUERY
);
1906 if (xParamBroadcaster
.is())
1907 xParamBroadcaster
->removeParameterListener(this);
1911 disposeAllFeaturesAndDispatchers();
1913 if ( m_xFormOperations
.is() )
1914 m_xFormOperations
->dispose();
1915 m_xFormOperations
.clear();
1917 // set the new model wait for the load event
1918 if (m_xTabController
.is())
1919 m_xTabController
->setModel(Model
);
1920 m_xModelAsIndex
= Reference
< XIndexAccess
> (Model
, UNO_QUERY
);
1921 m_xModelAsManager
= Reference
< XEventAttacherManager
> (Model
, UNO_QUERY
);
1923 // only if both ifaces exit, the controller will work successful
1924 if (!m_xModelAsIndex
.is() || !m_xModelAsManager
.is())
1926 m_xModelAsManager
= NULL
;
1927 m_xModelAsIndex
= NULL
;
1930 if (m_xModelAsIndex
.is())
1932 // re-create m_xFormOperations
1933 m_xFormOperations
.set( FormOperations::createWithFormController( m_aContext
.getUNOContext(), this ), UNO_SET_THROW
);
1934 m_xFormOperations
->setFeatureInvalidation( this );
1936 // adding load and ui interaction listeners
1937 Reference
< XLoadable
> xForm(Model
, UNO_QUERY
);
1939 xForm
->addLoadListener(this);
1941 Reference
< XSQLErrorBroadcaster
> xBroadcaster(Model
, UNO_QUERY
);
1942 if (xBroadcaster
.is())
1943 xBroadcaster
->addSQLErrorListener(this);
1945 Reference
< XDatabaseParameterBroadcaster
> xParamBroadcaster(Model
, UNO_QUERY
);
1946 if (xParamBroadcaster
.is())
1947 xParamBroadcaster
->addParameterListener(this);
1949 // well, is the database already loaded?
1950 // then we have to simulate a load event
1951 Reference
< XLoadable
> xCursor(m_xModelAsIndex
, UNO_QUERY
);
1952 if (xCursor
.is() && xCursor
->isLoaded())
1954 EventObject
aEvt(xCursor
);
1958 Reference
< XPropertySet
> xModelProps( m_xModelAsIndex
, UNO_QUERY
);
1959 Reference
< XPropertySetInfo
> xPropInfo( xModelProps
->getPropertySetInfo() );
1961 && xPropInfo
->hasPropertyByName( FM_PROP_DYNAMIC_CONTROL_BORDER
)
1962 && xPropInfo
->hasPropertyByName( FM_PROP_CONTROL_BORDER_COLOR_FOCUS
)
1963 && xPropInfo
->hasPropertyByName( FM_PROP_CONTROL_BORDER_COLOR_MOUSE
)
1964 && xPropInfo
->hasPropertyByName( FM_PROP_CONTROL_BORDER_COLOR_INVALID
)
1967 bool bEnableDynamicControlBorder
= lcl_shouldUseDynamicControlBorder(
1968 xModelProps
.get(), xModelProps
->getPropertyValue( FM_PROP_DYNAMIC_CONTROL_BORDER
) );
1969 if ( bEnableDynamicControlBorder
)
1970 m_pControlBorderManager
->enableDynamicBorderColor();
1972 m_pControlBorderManager
->disableDynamicBorderColor();
1974 sal_Int32 nColor
= 0;
1975 if ( xModelProps
->getPropertyValue( FM_PROP_CONTROL_BORDER_COLOR_FOCUS
) >>= nColor
)
1976 m_pControlBorderManager
->setStatusColor( CONTROL_STATUS_FOCUSED
, nColor
);
1977 if ( xModelProps
->getPropertyValue( FM_PROP_CONTROL_BORDER_COLOR_MOUSE
) >>= nColor
)
1978 m_pControlBorderManager
->setStatusColor( CONTROL_STATUS_MOUSE_HOVER
, nColor
);
1979 if ( xModelProps
->getPropertyValue( FM_PROP_CONTROL_BORDER_COLOR_INVALID
) >>= nColor
)
1980 m_pControlBorderManager
->setStatusColor( CONTROL_STATUS_INVALID
, nColor
);
1984 catch( const Exception
& )
1986 DBG_UNHANDLED_EXCEPTION();
1990 //------------------------------------------------------------------------------
1991 Reference
< XTabControllerModel
> FormController::getModel() throw( RuntimeException
)
1993 ::osl::MutexGuard
aGuard( m_aMutex
);
1994 impl_checkDisposed_throw();
1996 DBG_ASSERT(m_xTabController
.is(), "FormController::getModel : invalid aggregate !");
1997 if (!m_xTabController
.is())
1998 return Reference
< XTabControllerModel
> ();
1999 return m_xTabController
->getModel();
2002 //------------------------------------------------------------------------------
2003 void FormController::addToEventAttacher(const Reference
< XControl
> & xControl
)
2005 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2006 OSL_ENSURE( xControl
.is(), "FormController::addToEventAttacher: invalid control - how did you reach this?" );
2007 if ( !xControl
.is() )
2008 return; /* throw IllegalArgumentException(); */
2010 // anmelden beim Eventattacher
2011 Reference
< XFormComponent
> xComp(xControl
->getModel(), UNO_QUERY
);
2012 if (xComp
.is() && m_xModelAsIndex
.is())
2014 // Und die Position des ControlModel darin suchen
2015 sal_uInt32 nPos
= m_xModelAsIndex
->getCount();
2016 Reference
< XFormComponent
> xTemp
;
2019 m_xModelAsIndex
->getByIndex(--nPos
) >>= xTemp
;
2020 if ((XFormComponent
*)xComp
.get() == (XFormComponent
*)xTemp
.get())
2022 Reference
< XInterface
> xIfc(xControl
, UNO_QUERY
);
2023 m_xModelAsManager
->attach( nPos
, xIfc
, makeAny(xControl
) );
2030 //------------------------------------------------------------------------------
2031 void FormController::removeFromEventAttacher(const Reference
< XControl
> & xControl
)
2033 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2034 OSL_ENSURE( xControl
.is(), "FormController::removeFromEventAttacher: invalid control - how did you reach this?" );
2035 if ( !xControl
.is() )
2036 return; /* throw IllegalArgumentException(); */
2038 // abmelden beim Eventattacher
2039 Reference
< XFormComponent
> xComp(xControl
->getModel(), UNO_QUERY
);
2040 if ( xComp
.is() && m_xModelAsIndex
.is() )
2042 // Und die Position des ControlModel darin suchen
2043 sal_uInt32 nPos
= m_xModelAsIndex
->getCount();
2044 Reference
< XFormComponent
> xTemp
;
2047 m_xModelAsIndex
->getByIndex(--nPos
) >>= xTemp
;
2048 if ((XFormComponent
*)xComp
.get() == (XFormComponent
*)xTemp
.get())
2050 Reference
< XInterface
> xIfc(xControl
, UNO_QUERY
);
2051 m_xModelAsManager
->detach( nPos
, xIfc
);
2058 //------------------------------------------------------------------------------
2059 void FormController::setContainer(const Reference
< XControlContainer
> & xContainer
) throw( RuntimeException
)
2061 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2062 Reference
< XTabControllerModel
> xTabModel(getModel());
2063 DBG_ASSERT(xTabModel
.is() || !xContainer
.is(), "No Model defined");
2064 // if we have a new container we need a model
2065 DBG_ASSERT(m_xTabController
.is(), "FormController::setContainer : invalid aggregate !");
2067 ::osl::MutexGuard
aGuard( m_aMutex
);
2068 Reference
< XContainer
> xCurrentContainer
;
2069 if (m_xTabController
.is())
2070 xCurrentContainer
= Reference
< XContainer
> (m_xTabController
->getContainer(), UNO_QUERY
);
2071 if (xCurrentContainer
.is())
2073 xCurrentContainer
->removeContainerListener(this);
2075 if ( m_aTabActivationTimer
.IsActive() )
2076 m_aTabActivationTimer
.Stop();
2078 // clear the filter map
2079 ::std::for_each( m_aFilterComponents
.begin(), m_aFilterComponents
.end(), RemoveComponentTextListener( this ) );
2080 m_aFilterComponents
.clear();
2082 // einsammeln der Controls
2083 const Reference
< XControl
>* pControls
= m_aControls
.getConstArray();
2084 const Reference
< XControl
>* pControlsEnd
= pControls
+ m_aControls
.getLength();
2085 while ( pControls
!= pControlsEnd
)
2086 implControlRemoved( *pControls
++, true );
2088 // Datenbank spezifische Dinge vornehmen
2089 if (m_bDBConnection
&& isListeningForChanges())
2092 m_aControls
.realloc( 0 );
2095 if (m_xTabController
.is())
2096 m_xTabController
->setContainer(xContainer
);
2098 // Welche Controls gehoeren zum Container ?
2099 if (xContainer
.is() && xTabModel
.is())
2101 Sequence
< Reference
< XControlModel
> > aModels
= xTabModel
->getControlModels();
2102 const Reference
< XControlModel
> * pModels
= aModels
.getConstArray();
2103 Sequence
< Reference
< XControl
> > aAllControls
= xContainer
->getControls();
2105 sal_Int32 nCount
= aModels
.getLength();
2106 m_aControls
= Sequence
< Reference
< XControl
> >( nCount
);
2107 Reference
< XControl
> * pControls
= m_aControls
.getArray();
2109 // einsammeln der Controls
2111 for (i
= 0, j
= 0; i
< nCount
; ++i
, ++pModels
)
2113 Reference
< XControl
> xControl
= findControl( aAllControls
, *pModels
, sal_False
, sal_True
);
2114 if ( xControl
.is() )
2116 pControls
[j
++] = xControl
;
2117 implControlInserted( xControl
, true );
2121 // not every model had an associated control
2123 m_aControls
.realloc(j
);
2125 // am Container horchen
2126 Reference
< XContainer
> xNewContainer(xContainer
, UNO_QUERY
);
2127 if (xNewContainer
.is())
2128 xNewContainer
->addContainerListener(this);
2130 // Datenbank spezifische Dinge vornehmen
2131 if (m_bDBConnection
)
2133 m_bLocked
= determineLockState();
2139 // befinden sich die Controls in der richtigen Reihenfolge
2140 m_bControlsSorted
= sal_True
;
2143 //------------------------------------------------------------------------------
2144 Reference
< XControlContainer
> FormController::getContainer() throw( RuntimeException
)
2146 ::osl::MutexGuard
aGuard( m_aMutex
);
2147 impl_checkDisposed_throw();
2149 DBG_ASSERT(m_xTabController
.is(), "FormController::getContainer : invalid aggregate !");
2150 if (!m_xTabController
.is())
2151 return Reference
< XControlContainer
> ();
2152 return m_xTabController
->getContainer();
2155 //------------------------------------------------------------------------------
2156 Sequence
< Reference
< XControl
> > FormController::getControls(void) throw( RuntimeException
)
2158 ::osl::MutexGuard
aGuard( m_aMutex
);
2159 impl_checkDisposed_throw();
2161 if (!m_bControlsSorted
)
2163 Reference
< XTabControllerModel
> xModel
= getModel();
2167 Sequence
< Reference
< XControlModel
> > aControlModels
= xModel
->getControlModels();
2168 const Reference
< XControlModel
> * pModels
= aControlModels
.getConstArray();
2169 sal_Int32 nModels
= aControlModels
.getLength();
2171 Sequence
< Reference
< XControl
> > aNewControls(nModels
);
2173 Reference
< XControl
> * pControls
= aNewControls
.getArray();
2174 Reference
< XControl
> xControl
;
2176 // Umsortieren der Controls entsprechend der TabReihenfolge
2178 for (sal_Int32 i
= 0; i
< nModels
; ++i
, ++pModels
)
2180 xControl
= findControl( m_aControls
, *pModels
, sal_True
, sal_True
);
2181 if ( xControl
.is() )
2182 pControls
[j
++] = xControl
;
2185 // not every model had an associated control
2187 aNewControls
.realloc( j
);
2189 m_aControls
= aNewControls
;
2190 m_bControlsSorted
= sal_True
;
2195 //------------------------------------------------------------------------------
2196 void FormController::autoTabOrder() throw( RuntimeException
)
2198 ::osl::MutexGuard
aGuard( m_aMutex
);
2199 impl_checkDisposed_throw();
2201 DBG_ASSERT(m_xTabController
.is(), "FormController::autoTabOrder : invalid aggregate !");
2202 if (m_xTabController
.is())
2203 m_xTabController
->autoTabOrder();
2206 //------------------------------------------------------------------------------
2207 void FormController::activateTabOrder() throw( RuntimeException
)
2209 ::osl::MutexGuard
aGuard( m_aMutex
);
2210 impl_checkDisposed_throw();
2212 DBG_ASSERT(m_xTabController
.is(), "FormController::activateTabOrder : invalid aggregate !");
2213 if (m_xTabController
.is())
2214 m_xTabController
->activateTabOrder();
2217 //------------------------------------------------------------------------------
2218 void FormController::setControlLock(const Reference
< XControl
> & xControl
)
2220 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2221 sal_Bool bLocked
= isLocked();
2224 // a.) wenn der ganze Datensatz gesperrt ist
2225 // b.) wenn das zugehoerige Feld gespeert ist
2226 Reference
< XBoundControl
> xBound(xControl
, UNO_QUERY
);
2227 if (xBound
.is() && (( (bLocked
&& bLocked
!= xBound
->getLock()) ||
2228 !bLocked
))) // beim entlocken immer einzelne Felder ueberpr�fen
2230 // gibt es eine Datenquelle
2231 Reference
< XPropertySet
> xSet(xControl
->getModel(), UNO_QUERY
);
2232 if (xSet
.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD
, xSet
))
2234 // wie sieht mit den Properties ReadOnly und Enable aus
2235 sal_Bool bTouch
= sal_True
;
2236 if (::comphelper::hasProperty(FM_PROP_ENABLED
, xSet
))
2237 bTouch
= ::comphelper::getBOOL(xSet
->getPropertyValue(FM_PROP_ENABLED
));
2238 if (::comphelper::hasProperty(FM_PROP_READONLY
, xSet
))
2239 bTouch
= !::comphelper::getBOOL(xSet
->getPropertyValue(FM_PROP_READONLY
));
2243 Reference
< XPropertySet
> xField
;
2244 xSet
->getPropertyValue(FM_PROP_BOUNDFIELD
) >>= xField
;
2248 xBound
->setLock(bLocked
);
2253 Any aVal
= xField
->getPropertyValue(FM_PROP_ISREADONLY
);
2254 if (aVal
.hasValue() && ::comphelper::getBOOL(aVal
))
2255 xBound
->setLock(sal_True
);
2257 xBound
->setLock(bLocked
);
2259 catch( const Exception
& )
2261 DBG_UNHANDLED_EXCEPTION();
2271 //------------------------------------------------------------------------------
2272 void FormController::setLocks()
2274 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2275 // alle Controls, die mit einer Datenquelle verbunden sind locken/unlocken
2276 const Reference
< XControl
>* pControls
= m_aControls
.getConstArray();
2277 const Reference
< XControl
>* pControlsEnd
= pControls
+ m_aControls
.getLength();
2278 while ( pControls
!= pControlsEnd
)
2279 setControlLock( *pControls
++ );
2282 //------------------------------------------------------------------------------
2285 bool lcl_shouldListenForModifications( const Reference
< XControl
>& _rxControl
, const Reference
< XPropertyChangeListener
>& _rxBoundFieldListener
)
2287 bool bShould
= false;
2289 Reference
< XBoundComponent
> xBound( _rxControl
, UNO_QUERY
);
2294 else if ( _rxControl
.is() )
2296 Reference
< XPropertySet
> xModelProps( _rxControl
->getModel(), UNO_QUERY
);
2297 if ( xModelProps
.is() && ::comphelper::hasProperty( FM_PROP_BOUNDFIELD
, xModelProps
) )
2299 Reference
< XPropertySet
> xField
;
2300 xModelProps
->getPropertyValue( FM_PROP_BOUNDFIELD
) >>= xField
;
2301 bShould
= xField
.is();
2303 if ( !bShould
&& _rxBoundFieldListener
.is() )
2304 xModelProps
->addPropertyChangeListener( FM_PROP_BOUNDFIELD
, _rxBoundFieldListener
);
2312 //------------------------------------------------------------------------------
2313 void FormController::startControlModifyListening(const Reference
< XControl
> & xControl
)
2315 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2317 bool bModifyListening
= lcl_shouldListenForModifications( xControl
, this );
2320 while ( bModifyListening
)
2322 Reference
< XModifyBroadcaster
> xMod(xControl
, UNO_QUERY
);
2325 xMod
->addModifyListener(this);
2329 // alle die Text um vorzeitig ein modified zu erkennen
2330 Reference
< XTextComponent
> xText(xControl
, UNO_QUERY
);
2333 xText
->addTextListener(this);
2337 Reference
< XCheckBox
> xBox(xControl
, UNO_QUERY
);
2340 xBox
->addItemListener(this);
2344 Reference
< XComboBox
> xCbBox(xControl
, UNO_QUERY
);
2347 xCbBox
->addItemListener(this);
2351 Reference
< XListBox
> xListBox(xControl
, UNO_QUERY
);
2354 xListBox
->addItemListener(this);
2361 //------------------------------------------------------------------------------
2362 void FormController::stopControlModifyListening(const Reference
< XControl
> & xControl
)
2364 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2366 bool bModifyListening
= lcl_shouldListenForModifications( xControl
, NULL
);
2368 // kuenstliches while
2369 while (bModifyListening
)
2371 Reference
< XModifyBroadcaster
> xMod(xControl
, UNO_QUERY
);
2374 xMod
->removeModifyListener(this);
2377 // alle die Text um vorzeitig ein modified zu erkennen
2378 Reference
< XTextComponent
> xText(xControl
, UNO_QUERY
);
2381 xText
->removeTextListener(this);
2385 Reference
< XCheckBox
> xBox(xControl
, UNO_QUERY
);
2388 xBox
->removeItemListener(this);
2392 Reference
< XComboBox
> xCbBox(xControl
, UNO_QUERY
);
2395 xCbBox
->removeItemListener(this);
2399 Reference
< XListBox
> xListBox(xControl
, UNO_QUERY
);
2402 xListBox
->removeItemListener(this);
2409 //------------------------------------------------------------------------------
2410 void FormController::startListening()
2412 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2413 m_bModified
= sal_False
;
2415 // jetzt anmelden bei gebundenen feldern
2416 const Reference
< XControl
>* pControls
= m_aControls
.getConstArray();
2417 const Reference
< XControl
>* pControlsEnd
= pControls
+ m_aControls
.getLength();
2418 while ( pControls
!= pControlsEnd
)
2419 startControlModifyListening( *pControls
++ );
2422 //------------------------------------------------------------------------------
2423 void FormController::stopListening()
2425 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2426 m_bModified
= sal_False
;
2428 // jetzt anmelden bei gebundenen feldern
2429 const Reference
< XControl
>* pControls
= m_aControls
.getConstArray();
2430 const Reference
< XControl
>* pControlsEnd
= pControls
+ m_aControls
.getLength();
2431 while ( pControls
!= pControlsEnd
)
2432 stopControlModifyListening( *pControls
++ );
2436 //------------------------------------------------------------------------------
2437 Reference
< XControl
> FormController::findControl(Sequence
< Reference
< XControl
> >& _rControls
, const Reference
< XControlModel
> & xCtrlModel
,sal_Bool _bRemove
,sal_Bool _bOverWrite
) const
2439 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2440 DBG_ASSERT( xCtrlModel
.is(), "findControl - welches ?!" );
2442 Reference
< XControl
>* pControls
= _rControls
.getArray();
2443 Reference
< XControlModel
> xModel
;
2444 for ( sal_Int32 i
= 0, nCount
= _rControls
.getLength(); i
< nCount
; ++i
, ++pControls
)
2446 if ( pControls
->is() )
2448 xModel
= (*pControls
)->getModel();
2449 if ( xModel
.get() == xCtrlModel
.get() )
2451 Reference
< XControl
> xControl( *pControls
);
2453 ::comphelper::removeElementAt( _rControls
, i
);
2454 else if ( _bOverWrite
)
2455 *pControls
= Reference
< XControl
>();
2460 return Reference
< XControl
> ();
2463 //------------------------------------------------------------------------------
2464 void FormController::implControlInserted( const Reference
< XControl
>& _rxControl
, bool _bAddToEventAttacher
)
2466 Reference
< XWindow
> xWindow( _rxControl
, UNO_QUERY
);
2469 xWindow
->addFocusListener( this );
2470 xWindow
->addMouseListener( this );
2472 if ( _bAddToEventAttacher
)
2473 addToEventAttacher( _rxControl
);
2476 // add a dispatch interceptor to the control (if supported)
2477 Reference
< XDispatchProviderInterception
> xInterception( _rxControl
, UNO_QUERY
);
2478 if ( xInterception
.is() )
2479 createInterceptor( xInterception
);
2481 if ( _rxControl
.is() )
2483 Reference
< XControlModel
> xModel( _rxControl
->getModel() );
2485 // we want to know about the reset of the model of our controls
2486 // (for correctly resetting m_bModified)
2487 Reference
< XReset
> xReset( xModel
, UNO_QUERY
);
2489 xReset
->addResetListener( this );
2491 // and we want to know about the validity, to visually indicate it
2492 Reference
< XValidatableFormComponent
> xValidatable( xModel
, UNO_QUERY
);
2493 if ( xValidatable
.is() )
2495 xValidatable
->addFormComponentValidityListener( this );
2496 m_pControlBorderManager
->validityChanged( _rxControl
, xValidatable
);
2502 //------------------------------------------------------------------------------
2503 void FormController::implControlRemoved( const Reference
< XControl
>& _rxControl
, bool _bRemoveFromEventAttacher
)
2505 Reference
< XWindow
> xWindow( _rxControl
, UNO_QUERY
);
2508 xWindow
->removeFocusListener( this );
2509 xWindow
->removeMouseListener( this );
2511 if ( _bRemoveFromEventAttacher
)
2512 removeFromEventAttacher( _rxControl
);
2515 Reference
< XDispatchProviderInterception
> xInterception( _rxControl
, UNO_QUERY
);
2516 if ( xInterception
.is() )
2517 deleteInterceptor( xInterception
);
2519 if ( _rxControl
.is() )
2521 Reference
< XControlModel
> xModel( _rxControl
->getModel() );
2523 Reference
< XReset
> xReset( xModel
, UNO_QUERY
);
2525 xReset
->removeResetListener( this );
2527 Reference
< XValidatableFormComponent
> xValidatable( xModel
, UNO_QUERY
);
2528 if ( xValidatable
.is() )
2529 xValidatable
->removeFormComponentValidityListener( this );
2533 //------------------------------------------------------------------------------
2534 void FormController::implSetCurrentControl( const Reference
< XControl
>& _rxControl
)
2536 if ( m_xCurrentControl
.get() == _rxControl
.get() )
2539 Reference
< XGridControl
> xGridControl( m_xCurrentControl
, UNO_QUERY
);
2540 if ( xGridControl
.is() )
2541 xGridControl
->removeGridControlListener( this );
2543 m_xCurrentControl
= _rxControl
;
2545 xGridControl
.set( m_xCurrentControl
, UNO_QUERY
);
2546 if ( xGridControl
.is() )
2547 xGridControl
->addGridControlListener( this );
2550 //------------------------------------------------------------------------------
2551 void FormController::insertControl(const Reference
< XControl
> & xControl
)
2553 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2554 m_bControlsSorted
= sal_False
;
2555 m_aControls
.realloc(m_aControls
.getLength() + 1);
2556 m_aControls
.getArray()[m_aControls
.getLength() - 1] = xControl
;
2558 if ( m_pColumnInfoCache
.get() )
2559 m_pColumnInfoCache
->deinitializeControls();
2561 implControlInserted( xControl
, m_bAttachEvents
);
2563 if (m_bDBConnection
&& !m_bFiltering
)
2564 setControlLock(xControl
);
2566 if (isListeningForChanges() && m_bAttachEvents
)
2567 startControlModifyListening( xControl
);
2570 //------------------------------------------------------------------------------
2571 void FormController::removeControl(const Reference
< XControl
> & xControl
)
2573 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2574 const Reference
< XControl
>* pControls
= m_aControls
.getConstArray();
2575 const Reference
< XControl
>* pControlsEnd
= pControls
+ m_aControls
.getLength();
2576 while ( pControls
!= pControlsEnd
)
2578 if ( xControl
.get() == (*pControls
++).get() )
2580 ::comphelper::removeElementAt( m_aControls
, pControls
- m_aControls
.getConstArray() - 1 );
2585 FilterComponents::iterator componentPos
= ::std::find( m_aFilterComponents
.begin(), m_aFilterComponents
.end(), xControl
);
2586 if ( componentPos
!= m_aFilterComponents
.end() )
2587 m_aFilterComponents
.erase( componentPos
);
2589 implControlRemoved( xControl
, m_bDetachEvents
);
2591 if ( isListeningForChanges() && m_bDetachEvents
)
2592 stopControlModifyListening( xControl
);
2596 //------------------------------------------------------------------------------
2597 void FormController::loaded(const EventObject
& rEvent
) throw( RuntimeException
)
2599 OSL_ENSURE( rEvent
.Source
== m_xModelAsIndex
, "FormController::loaded: where did this come from?" );
2601 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2602 ::osl::MutexGuard
aGuard( m_aMutex
);
2603 Reference
< XRowSet
> xForm(rEvent
.Source
, UNO_QUERY
);
2604 // do we have a connected data source
2605 OStaticDataAccessTools aStaticTools
;
2606 if (xForm
.is() && aStaticTools
.getRowSetConnection(xForm
).is())
2608 Reference
< XPropertySet
> xSet(xForm
, UNO_QUERY
);
2611 Any aVal
= xSet
->getPropertyValue(FM_PROP_CYCLE
);
2612 sal_Int32 aVal2
= 0;
2613 ::cppu::enum2int(aVal2
,aVal
);
2614 m_bCycle
= !aVal
.hasValue() || aVal2
== TabulatorCycle_RECORDS
;
2615 m_bCanUpdate
= aStaticTools
.canUpdate(xSet
);
2616 m_bCanInsert
= aStaticTools
.canInsert(xSet
);
2617 m_bCurrentRecordModified
= ::comphelper::getBOOL(xSet
->getPropertyValue(FM_PROP_ISMODIFIED
));
2618 m_bCurrentRecordNew
= ::comphelper::getBOOL(xSet
->getPropertyValue(FM_PROP_ISNEW
));
2620 startFormListening( xSet
, sal_False
);
2622 // set the locks for the current controls
2623 if (getContainer().is())
2625 m_aLoadEvent
.Call();
2630 m_bCanInsert
= m_bCanUpdate
= m_bCycle
= sal_False
;
2631 m_bCurrentRecordModified
= sal_False
;
2632 m_bCurrentRecordNew
= sal_False
;
2633 m_bLocked
= sal_False
;
2635 m_bDBConnection
= sal_True
;
2639 m_bDBConnection
= sal_False
;
2640 m_bCanInsert
= m_bCanUpdate
= m_bCycle
= sal_False
;
2641 m_bCurrentRecordModified
= sal_False
;
2642 m_bCurrentRecordNew
= sal_False
;
2643 m_bLocked
= sal_False
;
2646 Reference
< XColumnsSupplier
> xFormColumns( xForm
, UNO_QUERY
);
2647 m_pColumnInfoCache
.reset( xFormColumns
.is() ? new ColumnInfoCache( xFormColumns
) : NULL
);
2649 updateAllDispatchers();
2652 //------------------------------------------------------------------------------
2653 void FormController::updateAllDispatchers() const
2656 m_aFeatureDispatchers
.begin(),
2657 m_aFeatureDispatchers
.end(),
2659 UpdateAllListeners(),
2660 ::o3tl::select2nd
< DispatcherContainer::value_type
>()
2665 //------------------------------------------------------------------------------
2666 IMPL_LINK_NOARG(FormController
, OnLoad
)
2668 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2669 m_bLocked
= determineLockState();
2676 // just one exception toggle the auto values
2677 if (m_bCurrentRecordNew
)
2678 toggleAutoFields(sal_True
);
2683 //------------------------------------------------------------------------------
2684 void FormController::unloaded(const EventObject
& /*rEvent*/) throw( RuntimeException
)
2686 ::osl::MutexGuard
aGuard( m_aMutex
);
2687 impl_checkDisposed_throw();
2689 updateAllDispatchers();
2692 //------------------------------------------------------------------------------
2693 void FormController::reloading(const EventObject
& /*aEvent*/) throw( RuntimeException
)
2695 ::osl::MutexGuard
aGuard( m_aMutex
);
2696 impl_checkDisposed_throw();
2698 // do the same like in unloading
2699 // just one exception toggle the auto values
2700 m_aToggleEvent
.CancelPendingCall();
2704 //------------------------------------------------------------------------------
2705 void FormController::reloaded(const EventObject
& aEvent
) throw( RuntimeException
)
2707 ::osl::MutexGuard
aGuard( m_aMutex
);
2708 impl_checkDisposed_throw();
2713 //------------------------------------------------------------------------------
2714 void FormController::unloading(const EventObject
& /*aEvent*/) throw( RuntimeException
)
2716 ::osl::MutexGuard
aGuard( m_aMutex
);
2717 impl_checkDisposed_throw();
2722 //------------------------------------------------------------------------------
2723 void FormController::unload() throw( RuntimeException
)
2725 ::osl::MutexGuard
aGuard( m_aMutex
);
2726 impl_checkDisposed_throw();
2728 m_aLoadEvent
.CancelPendingCall();
2730 // be sure not to have autofields
2731 if (m_bCurrentRecordNew
)
2732 toggleAutoFields(sal_False
);
2734 // remove bound field listing again
2735 removeBoundFieldListener();
2737 if (m_bDBConnection
&& isListeningForChanges())
2740 Reference
< XPropertySet
> xSet( m_xModelAsIndex
, UNO_QUERY
);
2741 if ( m_bDBConnection
&& xSet
.is() )
2742 stopFormListening( xSet
, sal_False
);
2744 m_bDBConnection
= sal_False
;
2745 m_bCanInsert
= m_bCanUpdate
= m_bCycle
= sal_False
;
2746 m_bCurrentRecordModified
= m_bCurrentRecordNew
= m_bLocked
= sal_False
;
2748 m_pColumnInfoCache
.reset( NULL
);
2751 // -----------------------------------------------------------------------------
2752 void FormController::removeBoundFieldListener()
2754 const Reference
< XControl
>* pControls
= m_aControls
.getConstArray();
2755 const Reference
< XControl
>* pControlsEnd
= pControls
+ m_aControls
.getLength();
2756 while ( pControls
!= pControlsEnd
)
2758 Reference
< XPropertySet
> xProp( *pControls
++, UNO_QUERY
);
2760 xProp
->removePropertyChangeListener( FM_PROP_BOUNDFIELD
, this );
2764 //------------------------------------------------------------------------------
2765 void FormController::startFormListening( const Reference
< XPropertySet
>& _rxForm
, sal_Bool _bPropertiesOnly
)
2769 if ( m_bCanInsert
|| m_bCanUpdate
) // form can be modified
2771 _rxForm
->addPropertyChangeListener( FM_PROP_ISNEW
, this );
2772 _rxForm
->addPropertyChangeListener( FM_PROP_ISMODIFIED
, this );
2774 if ( !_bPropertiesOnly
)
2776 // set the Listener for UI interaction
2777 Reference
< XRowSetApproveBroadcaster
> xApprove( _rxForm
, UNO_QUERY
);
2778 if ( xApprove
.is() )
2779 xApprove
->addRowSetApproveListener( this );
2781 // listener for row set changes
2782 Reference
< XRowSet
> xRowSet( _rxForm
, UNO_QUERY
);
2784 xRowSet
->addRowSetListener( this );
2788 Reference
< XPropertySetInfo
> xInfo
= _rxForm
->getPropertySetInfo();
2789 if ( xInfo
.is() && xInfo
->hasPropertyByName( FM_PROP_DYNAMIC_CONTROL_BORDER
) )
2790 _rxForm
->addPropertyChangeListener( FM_PROP_DYNAMIC_CONTROL_BORDER
, this );
2792 catch( const Exception
& )
2794 DBG_UNHANDLED_EXCEPTION();
2798 //------------------------------------------------------------------------------
2799 void FormController::stopFormListening( const Reference
< XPropertySet
>& _rxForm
, sal_Bool _bPropertiesOnly
)
2803 if ( m_bCanInsert
|| m_bCanUpdate
)
2805 _rxForm
->removePropertyChangeListener( FM_PROP_ISNEW
, this );
2806 _rxForm
->removePropertyChangeListener( FM_PROP_ISMODIFIED
, this );
2808 if ( !_bPropertiesOnly
)
2810 Reference
< XRowSetApproveBroadcaster
> xApprove( _rxForm
, UNO_QUERY
);
2812 xApprove
->removeRowSetApproveListener(this);
2814 Reference
< XRowSet
> xRowSet( _rxForm
, UNO_QUERY
);
2816 xRowSet
->removeRowSetListener( this );
2820 Reference
< XPropertySetInfo
> xInfo
= _rxForm
->getPropertySetInfo();
2821 if ( xInfo
.is() && xInfo
->hasPropertyByName( FM_PROP_DYNAMIC_CONTROL_BORDER
) )
2822 _rxForm
->removePropertyChangeListener( FM_PROP_DYNAMIC_CONTROL_BORDER
, this );
2824 catch( const Exception
& )
2826 DBG_UNHANDLED_EXCEPTION();
2830 // com::sun::star::sdbc::XRowSetListener
2831 //------------------------------------------------------------------------------
2832 void FormController::cursorMoved(const EventObject
& /*event*/) throw( RuntimeException
)
2834 ::osl::MutexGuard
aGuard( m_aMutex
);
2835 impl_checkDisposed_throw();
2837 // toggle the locking ?
2838 if (m_bLocked
!= determineLockState())
2840 m_bLocked
= !m_bLocked
;
2842 if (isListeningForChanges())
2848 // neither the current control nor the current record are modified anymore
2849 m_bCurrentRecordModified
= m_bModified
= sal_False
;
2852 //------------------------------------------------------------------------------
2853 void FormController::rowChanged(const EventObject
& /*event*/) throw( RuntimeException
)
2855 // not interested in ...
2857 //------------------------------------------------------------------------------
2858 void FormController::rowSetChanged(const EventObject
& /*event*/) throw( RuntimeException
)
2860 // not interested in ...
2864 // XContainerListener
2865 //------------------------------------------------------------------------------
2866 void SAL_CALL
FormController::elementInserted(const ContainerEvent
& evt
) throw( RuntimeException
)
2868 ::osl::MutexGuard
aGuard( m_aMutex
);
2869 impl_checkDisposed_throw();
2871 Reference
< XControl
> xControl( evt
.Element
, UNO_QUERY
);
2872 if ( !xControl
.is() )
2875 Reference
< XFormComponent
> xModel(xControl
->getModel(), UNO_QUERY
);
2876 if (xModel
.is() && m_xModelAsIndex
== xModel
->getParent())
2878 insertControl(xControl
);
2880 if ( m_aTabActivationTimer
.IsActive() )
2881 m_aTabActivationTimer
.Stop();
2883 m_aTabActivationTimer
.Start();
2885 // are we in filtermode and a XModeSelector has inserted an element
2886 else if (m_bFiltering
&& Reference
< XModeSelector
> (evt
.Source
, UNO_QUERY
).is())
2888 xModel
= Reference
< XFormComponent
> (evt
.Source
, UNO_QUERY
);
2889 if (xModel
.is() && m_xModelAsIndex
== xModel
->getParent())
2891 Reference
< XPropertySet
> xSet(xControl
->getModel(), UNO_QUERY
);
2892 if (xSet
.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD
, xSet
))
2894 // does the model use a bound field ?
2895 Reference
< XPropertySet
> xField
;
2896 xSet
->getPropertyValue(FM_PROP_BOUNDFIELD
) >>= xField
;
2898 Reference
< XTextComponent
> xText(xControl
, UNO_QUERY
);
2899 // may we filter the field?
2900 if (xText
.is() && xField
.is() && ::comphelper::hasProperty(FM_PROP_SEARCHABLE
, xField
) &&
2901 ::comphelper::getBOOL(xField
->getPropertyValue(FM_PROP_SEARCHABLE
)))
2903 m_aFilterComponents
.push_back( xText
);
2904 xText
->addTextListener( this );
2911 //------------------------------------------------------------------------------
2912 void SAL_CALL
FormController::elementReplaced(const ContainerEvent
& evt
) throw( RuntimeException
)
2914 // simulate an elementRemoved
2915 ContainerEvent
aRemoveEvent( evt
);
2916 aRemoveEvent
.Element
= evt
.ReplacedElement
;
2917 aRemoveEvent
.ReplacedElement
= Any();
2918 elementRemoved( aRemoveEvent
);
2920 // simulate an elementInserted
2921 ContainerEvent
aInsertEvent( evt
);
2922 aInsertEvent
.ReplacedElement
= Any();
2923 elementInserted( aInsertEvent
);
2926 //------------------------------------------------------------------------------
2927 void SAL_CALL
FormController::elementRemoved(const ContainerEvent
& evt
) throw( RuntimeException
)
2929 ::osl::MutexGuard
aGuard( m_aMutex
);
2930 impl_checkDisposed_throw();
2932 Reference
< XControl
> xControl
;
2933 evt
.Element
>>= xControl
;
2937 Reference
< XFormComponent
> xModel(xControl
->getModel(), UNO_QUERY
);
2938 if (xModel
.is() && m_xModelAsIndex
== xModel
->getParent())
2940 removeControl(xControl
);
2941 // TabOrder nicht neu berechnen, da das intern schon funktionieren mu�!
2943 // are we in filtermode and a XModeSelector has inserted an element
2944 else if (m_bFiltering
&& Reference
< XModeSelector
> (evt
.Source
, UNO_QUERY
).is())
2946 FilterComponents::iterator componentPos
= ::std::find(
2947 m_aFilterComponents
.begin(), m_aFilterComponents
.end(), xControl
);
2948 if ( componentPos
!= m_aFilterComponents
.end() )
2949 m_aFilterComponents
.erase( componentPos
);
2953 //------------------------------------------------------------------------------
2954 Reference
< XControl
> FormController::isInList(const Reference
< XWindowPeer
> & xPeer
) const
2956 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2957 const Reference
< XControl
>* pControls
= m_aControls
.getConstArray();
2959 sal_uInt32 nCtrls
= m_aControls
.getLength();
2960 for ( sal_uInt32 n
= 0; n
< nCtrls
&& xPeer
.is(); ++n
, ++pControls
)
2962 if ( pControls
->is() )
2964 Reference
< XVclWindowPeer
> xCtrlPeer( (*pControls
)->getPeer(), UNO_QUERY
);
2965 if ( ( xCtrlPeer
.get() == xPeer
.get() ) || xCtrlPeer
->isChild( xPeer
) )
2969 return Reference
< XControl
> ();
2972 //------------------------------------------------------------------------------
2973 void FormController::activateFirst() throw( RuntimeException
)
2975 ::osl::MutexGuard
aGuard( m_aMutex
);
2976 impl_checkDisposed_throw();
2978 DBG_ASSERT(m_xTabController
.is(), "FormController::activateFirst : invalid aggregate !");
2979 if (m_xTabController
.is())
2980 m_xTabController
->activateFirst();
2983 //------------------------------------------------------------------------------
2984 void FormController::activateLast() throw( RuntimeException
)
2986 ::osl::MutexGuard
aGuard( m_aMutex
);
2987 impl_checkDisposed_throw();
2989 DBG_ASSERT(m_xTabController
.is(), "FormController::activateLast : invalid aggregate !");
2990 if (m_xTabController
.is())
2991 m_xTabController
->activateLast();
2995 //------------------------------------------------------------------------------
2996 Reference
< XFormOperations
> SAL_CALL
FormController::getFormOperations() throw (RuntimeException
)
2998 ::osl::MutexGuard
aGuard( m_aMutex
);
2999 impl_checkDisposed_throw();
3001 return m_xFormOperations
;
3004 //------------------------------------------------------------------------------
3005 Reference
< XControl
> SAL_CALL
FormController::getCurrentControl(void) throw( RuntimeException
)
3007 ::osl::MutexGuard
aGuard( m_aMutex
);
3008 impl_checkDisposed_throw();
3009 return m_xCurrentControl
;
3012 //------------------------------------------------------------------------------
3013 void SAL_CALL
FormController::addActivateListener(const Reference
< XFormControllerListener
> & l
) throw( RuntimeException
)
3015 ::osl::MutexGuard
aGuard( m_aMutex
);
3016 impl_checkDisposed_throw();
3017 m_aActivateListeners
.addInterface(l
);
3019 //------------------------------------------------------------------------------
3020 void SAL_CALL
FormController::removeActivateListener(const Reference
< XFormControllerListener
> & l
) throw( RuntimeException
)
3022 ::osl::MutexGuard
aGuard( m_aMutex
);
3023 impl_checkDisposed_throw();
3024 m_aActivateListeners
.removeInterface(l
);
3027 //------------------------------------------------------------------------------
3028 void SAL_CALL
FormController::addChildController( const Reference
< XFormController
>& _ChildController
) throw( RuntimeException
, IllegalArgumentException
)
3030 ::osl::MutexGuard
aGuard( m_aMutex
);
3031 impl_checkDisposed_throw();
3033 if ( !_ChildController
.is() )
3034 throw IllegalArgumentException( OUString(), *this, 1 );
3035 // TODO: (localized) error message
3037 // the parent of our (to-be-)child must be our own model
3038 Reference
< XFormComponent
> xFormOfChild( _ChildController
->getModel(), UNO_QUERY
);
3039 if ( !xFormOfChild
.is() )
3040 throw IllegalArgumentException( OUString(), *this, 1 );
3041 // TODO: (localized) error message
3043 if ( xFormOfChild
->getParent() != m_xModelAsIndex
)
3044 throw IllegalArgumentException( OUString(), *this, 1 );
3045 // TODO: (localized) error message
3047 m_aChildren
.push_back( _ChildController
);
3048 _ChildController
->setParent( *this );
3050 // search the position of the model within the form
3051 sal_uInt32 nPos
= m_xModelAsIndex
->getCount();
3052 Reference
< XFormComponent
> xTemp
;
3055 m_xModelAsIndex
->getByIndex(--nPos
) >>= xTemp
;
3056 if ( xFormOfChild
== xTemp
)
3058 Reference
< XInterface
> xIfc( _ChildController
, UNO_QUERY
);
3059 m_xModelAsManager
->attach( nPos
, xIfc
, makeAny( _ChildController
) );
3065 //------------------------------------------------------------------------------
3066 Reference
< XFormControllerContext
> SAL_CALL
FormController::getContext() throw (RuntimeException
)
3068 ::osl::MutexGuard
aGuard( m_aMutex
);
3069 impl_checkDisposed_throw();
3073 //------------------------------------------------------------------------------
3074 void SAL_CALL
FormController::setContext( const Reference
< XFormControllerContext
>& _context
) throw (RuntimeException
)
3076 ::osl::MutexGuard
aGuard( m_aMutex
);
3077 impl_checkDisposed_throw();
3078 m_xContext
= _context
;
3081 //------------------------------------------------------------------------------
3082 Reference
< XInteractionHandler
> SAL_CALL
FormController::getInteractionHandler() throw (RuntimeException
)
3084 ::osl::MutexGuard
aGuard( m_aMutex
);
3085 impl_checkDisposed_throw();
3086 return m_xInteractionHandler
;
3089 //------------------------------------------------------------------------------
3090 void SAL_CALL
FormController::setInteractionHandler( const Reference
< XInteractionHandler
>& _interactionHandler
) throw (RuntimeException
)
3092 ::osl::MutexGuard
aGuard( m_aMutex
);
3093 impl_checkDisposed_throw();
3094 m_xInteractionHandler
= _interactionHandler
;
3097 //------------------------------------------------------------------------------
3098 void FormController::setFilter(::std::vector
<FmFieldInfo
>& rFieldInfos
)
3100 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
3101 // create the composer
3102 Reference
< XRowSet
> xForm(m_xModelAsIndex
, UNO_QUERY
);
3103 Reference
< XConnection
> xConnection(OStaticDataAccessTools().getRowSetConnection(xForm
));
3108 Reference
< XMultiServiceFactory
> xFactory( xConnection
, UNO_QUERY_THROW
);
3110 xFactory
->createInstance( OUString( "com.sun.star.sdb.SingleSelectQueryComposer" ) ),
3113 Reference
< XPropertySet
> xSet( xForm
, UNO_QUERY
);
3114 OUString sStatement
= ::comphelper::getString( xSet
->getPropertyValue( FM_PROP_ACTIVECOMMAND
) );
3115 OUString sFilter
= ::comphelper::getString( xSet
->getPropertyValue( FM_PROP_FILTER
) );
3116 m_xComposer
->setElementaryQuery( sStatement
);
3117 m_xComposer
->setFilter( sFilter
);
3119 catch( const Exception
& )
3121 DBG_UNHANDLED_EXCEPTION();
3125 if (m_xComposer
.is())
3127 Sequence
< PropertyValue
> aLevel
;
3128 Sequence
< Sequence
< PropertyValue
> > aFilterRows
= m_xComposer
->getStructuredFilter();
3130 // ok, we receive the list of filters as sequence of fieldnames, value
3131 // now we have to transform the fieldname into UI names, that could be a label of the field or
3132 // a aliasname or the fieldname itself
3134 // first adjust the field names if necessary
3135 Reference
< XNameAccess
> xQueryColumns
=
3136 Reference
< XColumnsSupplier
>( m_xComposer
, UNO_QUERY_THROW
)->getColumns();
3138 for (::std::vector
<FmFieldInfo
>::iterator iter
= rFieldInfos
.begin();
3139 iter
!= rFieldInfos
.end(); ++iter
)
3141 if ( xQueryColumns
->hasByName((*iter
).aFieldName
) )
3143 if ( (xQueryColumns
->getByName((*iter
).aFieldName
) >>= (*iter
).xField
) && (*iter
).xField
.is() )
3144 (*iter
).xField
->getPropertyValue(FM_PROP_REALNAME
) >>= (*iter
).aFieldName
;
3148 Reference
< XDatabaseMetaData
> xMetaData(xConnection
->getMetaData());
3149 // now transfer the filters into Value/TextComponent pairs
3150 ::comphelper::UStringMixEqual
aCompare(xMetaData
->storesMixedCaseQuotedIdentifiers());
3152 // need to parse criteria localized
3153 OStaticDataAccessTools aStaticTools
;
3154 Reference
< XNumberFormatsSupplier
> xFormatSupplier( aStaticTools
.getNumberFormats(xConnection
, sal_True
));
3155 Reference
< XNumberFormatter
> xFormatter( NumberFormatter::create(m_aContext
.getUNOContext()), UNO_QUERY_THROW
);
3156 xFormatter
->attachNumberFormatsSupplier(xFormatSupplier
);
3157 Locale aAppLocale
= Application::GetSettings().GetUILanguageTag().getLocale();
3158 const LocaleDataWrapper
& rLocaleWrapper( Application::GetSettings().GetUILocaleDataWrapper() );
3159 /* FIXME: casting this to sal_Char is plain wrong and of course only
3160 * works for ASCII separators, but
3161 * xParseNode->parseNodeToPredicateStr() expects a sal_Char. Fix it
3163 sal_Char cDecimalSeparator
= (sal_Char
)rLocaleWrapper
.getNumDecimalSep()[0];
3164 SAL_WARN_IF( (sal_Unicode
)cDecimalSeparator
!= rLocaleWrapper
.getNumDecimalSep()[0],
3165 "svx.form", "FormController::setFilter: wrong cast of decimal separator to sal_Char!");
3167 // retrieving the filter
3168 const Sequence
< PropertyValue
>* pRow
= aFilterRows
.getConstArray();
3169 for (sal_Int32 i
= 0, nLen
= aFilterRows
.getLength(); i
< nLen
; ++i
)
3173 // search a field for the given name
3174 const PropertyValue
* pRefValues
= pRow
[i
].getConstArray();
3175 for (sal_Int32 j
= 0, nLen1
= pRow
[i
].getLength(); j
< nLen1
; j
++)
3177 // look for the text component
3178 Reference
< XPropertySet
> xField
;
3181 Reference
< XPropertySet
> xSet
;
3184 // first look with the given name
3185 if (xQueryColumns
->hasByName(pRefValues
[j
].Name
))
3187 xQueryColumns
->getByName(pRefValues
[j
].Name
) >>= xSet
;
3190 xSet
->getPropertyValue(OUString("RealName")) >>= aRealName
;
3192 // compare the condition field name and the RealName
3193 if (aCompare(aRealName
, pRefValues
[j
].Name
))
3198 // no we have to check every column to find the realname
3199 Reference
< XIndexAccess
> xColumnsByIndex(xQueryColumns
, UNO_QUERY
);
3200 for (sal_Int32 n
= 0, nCount
= xColumnsByIndex
->getCount(); n
< nCount
; n
++)
3202 xColumnsByIndex
->getByIndex(n
) >>= xSet
;
3203 xSet
->getPropertyValue(OUString("RealName")) >>= aRealName
;
3204 if (aCompare(aRealName
, pRefValues
[j
].Name
))
3206 // get the column by its alias
3215 catch (const Exception
&)
3220 // find the text component
3221 for (::std::vector
<FmFieldInfo
>::iterator iter
= rFieldInfos
.begin();
3222 iter
!= rFieldInfos
.end(); ++iter
)
3224 // we found the field so insert a new entry to the filter row
3225 if ((*iter
).xField
== xField
)
3227 // do we already have the control ?
3228 if (aRow
.find((*iter
).xText
) != aRow
.end())
3230 OUString aCompText
= aRow
[(*iter
).xText
];
3231 aCompText
+= OUString(" ");
3232 OString aVal
= m_xParser
->getContext().getIntlKeywordAscii(IParseContext::KEY_AND
);
3233 aCompText
+= OUString(aVal
.getStr(),aVal
.getLength(),RTL_TEXTENCODING_ASCII_US
);
3234 aCompText
+= OUString(" ");
3235 aCompText
+= ::comphelper::getString(pRefValues
[j
].Value
);
3236 aRow
[(*iter
).xText
] = aCompText
;
3240 OUString sPredicate
,sErrorMsg
;
3241 pRefValues
[j
].Value
>>= sPredicate
;
3242 ::rtl::Reference
< ISQLParseNode
> xParseNode
= predicateTree(sErrorMsg
, sPredicate
, xFormatter
, xField
);
3243 if ( xParseNode
.is() )
3246 xParseNode
->parseNodeToPredicateStr( sCriteria
3253 ,getParseContext());
3254 aRow
[(*iter
).xText
] = sCriteria
;
3264 impl_addFilterRow( aRow
);
3268 // now set the filter controls
3269 for ( ::std::vector
<FmFieldInfo
>::iterator field
= rFieldInfos
.begin();
3270 field
!= rFieldInfos
.end();
3274 m_aFilterComponents
.push_back( field
->xText
);
3278 //------------------------------------------------------------------------------
3279 void FormController::startFiltering()
3281 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
3283 OStaticDataAccessTools aStaticTools
;
3284 Reference
< XConnection
> xConnection( aStaticTools
.getRowSetConnection( Reference
< XRowSet
>( m_xModelAsIndex
, UNO_QUERY
) ) );
3285 if ( !xConnection
.is() )
3286 // nothing to do - can't filter a form which is not connected
3289 // stop listening for controls
3290 if (isListeningForChanges())
3293 m_bFiltering
= sal_True
;
3295 // as we don't want new controls to be attached to the scripting environment
3296 // we change attach flags
3297 m_bAttachEvents
= sal_False
;
3299 // Austauschen der Kontrols fuer das aktuelle Formular
3300 Sequence
< Reference
< XControl
> > aControlsCopy( m_aControls
);
3301 const Reference
< XControl
>* pControls
= aControlsCopy
.getConstArray();
3302 sal_Int32 nControlCount
= aControlsCopy
.getLength();
3304 // the control we have to activate after replacement
3305 Reference
< XDatabaseMetaData
> xMetaData(xConnection
->getMetaData());
3306 Reference
< XNumberFormatsSupplier
> xFormatSupplier
= aStaticTools
.getNumberFormats(xConnection
, sal_True
);
3307 Reference
< XNumberFormatter
> xFormatter( NumberFormatter::create(m_aContext
.getUNOContext()), UNO_QUERY_THROW
);
3308 xFormatter
->attachNumberFormatsSupplier(xFormatSupplier
);
3310 // structure for storing the field info
3311 ::std::vector
<FmFieldInfo
> aFieldInfos
;
3313 for (sal_Int32 i
= nControlCount
; i
> 0;)
3315 Reference
< XControl
> xControl
= pControls
[--i
];
3318 // no events for the control anymore
3319 removeFromEventAttacher(xControl
);
3321 // do we have a mode selector
3322 Reference
< XModeSelector
> xSelector(xControl
, UNO_QUERY
);
3325 xSelector
->setMode( OUString( "FilterMode" ) );
3327 // listening for new controls of the selector
3328 Reference
< XContainer
> xContainer(xSelector
, UNO_QUERY
);
3329 if (xContainer
.is())
3330 xContainer
->addContainerListener(this);
3332 Reference
< XEnumerationAccess
> xElementAccess(xSelector
, UNO_QUERY
);
3333 if (xElementAccess
.is())
3335 Reference
< XEnumeration
> xEnumeration(xElementAccess
->createEnumeration());
3336 Reference
< XControl
> xSubControl
;
3337 while (xEnumeration
->hasMoreElements())
3339 xEnumeration
->nextElement() >>= xSubControl
;
3340 if (xSubControl
.is())
3342 Reference
< XPropertySet
> xSet(xSubControl
->getModel(), UNO_QUERY
);
3343 if (xSet
.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD
, xSet
))
3345 // does the model use a bound field ?
3346 Reference
< XPropertySet
> xField
;
3347 xSet
->getPropertyValue(FM_PROP_BOUNDFIELD
) >>= xField
;
3349 Reference
< XTextComponent
> xText(xSubControl
, UNO_QUERY
);
3350 // may we filter the field?
3351 if (xText
.is() && xField
.is() && ::comphelper::hasProperty(FM_PROP_SEARCHABLE
, xField
) &&
3352 ::comphelper::getBOOL(xField
->getPropertyValue(FM_PROP_SEARCHABLE
)))
3354 aFieldInfos
.push_back(FmFieldInfo(xField
, xText
));
3355 xText
->addTextListener(this);
3364 Reference
< XPropertySet
> xModel( xControl
->getModel(), UNO_QUERY
);
3365 if (xModel
.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD
, xModel
))
3367 // does the model use a bound field ?
3368 Any aVal
= xModel
->getPropertyValue(FM_PROP_BOUNDFIELD
);
3369 Reference
< XPropertySet
> xField
;
3372 // may we filter the field?
3375 && ::comphelper::hasProperty( FM_PROP_SEARCHABLE
, xField
)
3376 && ::comphelper::getBOOL( xField
->getPropertyValue( FM_PROP_SEARCHABLE
) )
3379 // create a filter control
3380 Reference
< XControl
> xFilterControl
= form::control::FilterControl::createWithFormat(
3381 m_aContext
.getUNOContext(),
3382 VCLUnoHelper::GetInterface( getDialogParentWindow() ),
3386 if ( replaceControl( xControl
, xFilterControl
) )
3388 Reference
< XTextComponent
> xFilterText( xFilterControl
, UNO_QUERY
);
3389 aFieldInfos
.push_back( FmFieldInfo( xField
, xFilterText
) );
3390 xFilterText
->addTextListener(this);
3396 // abmelden vom EventManager
3401 // we have all filter controls now, so the next step is to read the filters from the form
3402 // resolve all aliases and set the current filter to the according structure
3403 setFilter(aFieldInfos
);
3405 Reference
< XPropertySet
> xSet( m_xModelAsIndex
, UNO_QUERY
);
3407 stopFormListening( xSet
, sal_True
);
3409 impl_setTextOnAllFilter_throw();
3411 // lock all controls which are not used for filtering
3412 m_bLocked
= determineLockState();
3414 m_bAttachEvents
= sal_True
;
3417 //------------------------------------------------------------------------------
3418 void FormController::stopFiltering()
3420 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
3421 if ( !m_bFiltering
) // #104693# OJ
3426 m_bFiltering
= sal_False
;
3427 m_bDetachEvents
= sal_False
;
3429 ::comphelper::disposeComponent(m_xComposer
);
3431 // Austauschen der Kontrols fuer das aktuelle Formular
3432 Sequence
< Reference
< XControl
> > aControlsCopy( m_aControls
);
3433 const Reference
< XControl
> * pControls
= aControlsCopy
.getConstArray();
3434 sal_Int32 nControlCount
= aControlsCopy
.getLength();
3436 // clear the filter control map
3437 ::std::for_each( m_aFilterComponents
.begin(), m_aFilterComponents
.end(), RemoveComponentTextListener( this ) );
3438 m_aFilterComponents
.clear();
3440 for ( sal_Int32 i
= nControlCount
; i
> 0; )
3442 Reference
< XControl
> xControl
= pControls
[--i
];
3445 // now enable eventhandling again
3446 addToEventAttacher(xControl
);
3448 Reference
< XModeSelector
> xSelector(xControl
, UNO_QUERY
);
3451 xSelector
->setMode( OUString( "DataMode" ) );
3453 // listening for new controls of the selector
3454 Reference
< XContainer
> xContainer(xSelector
, UNO_QUERY
);
3455 if (xContainer
.is())
3456 xContainer
->removeContainerListener(this);
3460 Reference
< XPropertySet
> xSet(xControl
->getModel(), UNO_QUERY
);
3461 if (xSet
.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD
, xSet
))
3463 // does the model use a bound field ?
3464 Reference
< XPropertySet
> xField
;
3465 xSet
->getPropertyValue(FM_PROP_BOUNDFIELD
) >>= xField
;
3467 // may we filter the field?
3469 && ::comphelper::hasProperty( FM_PROP_SEARCHABLE
, xField
)
3470 && ::comphelper::getBOOL( xField
->getPropertyValue( FM_PROP_SEARCHABLE
) )
3473 OUString sServiceName
;
3474 OSL_VERIFY( xSet
->getPropertyValue( FM_PROP_DEFAULTCONTROL
) >>= sServiceName
);
3475 Reference
< XControl
> xNewControl( m_aContext
.createComponent( sServiceName
), UNO_QUERY
);
3476 replaceControl( xControl
, xNewControl
);
3482 Reference
< XPropertySet
> xSet( m_xModelAsIndex
, UNO_QUERY
);
3484 startFormListening( xSet
, sal_True
);
3486 m_bDetachEvents
= sal_True
;
3488 m_aFilterRows
.clear();
3489 m_nCurrentFilterPosition
= -1;
3491 // release the locks if possible
3492 // lock all controls which are not used for filtering
3493 m_bLocked
= determineLockState();
3496 // restart listening for control modifications
3497 if (isListeningForChanges())
3502 //------------------------------------------------------------------------------
3503 void FormController::setMode(const OUString
& Mode
) throw( NoSupportException
, RuntimeException
)
3505 ::osl::MutexGuard
aGuard( m_aMutex
);
3506 impl_checkDisposed_throw();
3508 if (!supportsMode(Mode
))
3509 throw NoSupportException();
3511 if (Mode
== m_aMode
)
3516 if ( Mode
== "FilterMode" )
3521 for (FmFormControllers::const_iterator i
= m_aChildren
.begin();
3522 i
!= m_aChildren
.end(); ++i
)
3524 Reference
< XModeSelector
> xMode(*i
, UNO_QUERY
);
3526 xMode
->setMode(Mode
);
3530 //------------------------------------------------------------------------------
3531 OUString SAL_CALL
FormController::getMode(void) throw( RuntimeException
)
3533 ::osl::MutexGuard
aGuard( m_aMutex
);
3534 impl_checkDisposed_throw();
3539 //------------------------------------------------------------------------------
3540 Sequence
< OUString
> SAL_CALL
FormController::getSupportedModes(void) throw( RuntimeException
)
3542 ::osl::MutexGuard
aGuard( m_aMutex
);
3543 impl_checkDisposed_throw();
3545 static Sequence
< OUString
> aModes
;
3546 if (!aModes
.getLength())
3549 OUString
* pModes
= aModes
.getArray();
3550 pModes
[0] = OUString( "DataMode" );
3551 pModes
[1] = OUString( "FilterMode" );
3556 //------------------------------------------------------------------------------
3557 sal_Bool SAL_CALL
FormController::supportsMode(const OUString
& Mode
) throw( RuntimeException
)
3559 ::osl::MutexGuard
aGuard( m_aMutex
);
3560 impl_checkDisposed_throw();
3562 Sequence
< OUString
> aModes(getSupportedModes());
3563 const OUString
* pModes
= aModes
.getConstArray();
3564 for (sal_Int32 i
= aModes
.getLength(); i
> 0; )
3566 if (pModes
[--i
] == Mode
)
3572 //------------------------------------------------------------------------------
3573 Window
* FormController::getDialogParentWindow()
3575 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
3576 Window
* pParentWindow
= NULL
;
3579 Reference
< XControl
> xContainerControl( getContainer(), UNO_QUERY_THROW
);
3580 Reference
< XWindowPeer
> xContainerPeer( xContainerControl
->getPeer(), UNO_QUERY_THROW
);
3581 pParentWindow
= VCLUnoHelper::GetWindow( xContainerPeer
);
3583 catch( const Exception
& )
3585 DBG_UNHANDLED_EXCEPTION();
3587 return pParentWindow
;
3589 //------------------------------------------------------------------------------
3590 bool FormController::checkFormComponentValidity( OUString
& /* [out] */ _rFirstInvalidityExplanation
, Reference
< XControlModel
>& /* [out] */ _rxFirstInvalidModel
) SAL_THROW(())
3594 Reference
< XEnumerationAccess
> xControlEnumAcc( getModel(), UNO_QUERY
);
3595 Reference
< XEnumeration
> xControlEnumeration
;
3596 if ( xControlEnumAcc
.is() )
3597 xControlEnumeration
= xControlEnumAcc
->createEnumeration();
3598 OSL_ENSURE( xControlEnumeration
.is(), "FormController::checkFormComponentValidity: cannot enumerate the controls!" );
3599 if ( !xControlEnumeration
.is() )
3603 Reference
< XValidatableFormComponent
> xValidatable
;
3604 while ( xControlEnumeration
->hasMoreElements() )
3606 if ( !( xControlEnumeration
->nextElement() >>= xValidatable
) )
3607 // control does not support validation
3610 if ( xValidatable
->isValid() )
3613 Reference
< XValidator
> xValidator( xValidatable
->getValidator() );
3614 OSL_ENSURE( xValidator
.is(), "FormController::checkFormComponentValidity: invalid, but no validator?" );
3615 if ( !xValidator
.is() )
3616 // this violates the interface definition of css.form.validation.XValidatableFormComponent ...
3619 _rFirstInvalidityExplanation
= xValidator
->explainInvalid( xValidatable
->getCurrentValue() );
3620 _rxFirstInvalidModel
= _rxFirstInvalidModel
.query( xValidatable
);
3624 catch( const Exception
& )
3626 DBG_UNHANDLED_EXCEPTION();
3631 //------------------------------------------------------------------------------
3632 Reference
< XControl
> FormController::locateControl( const Reference
< XControlModel
>& _rxModel
) SAL_THROW(())
3636 Sequence
< Reference
< XControl
> > aControls( getControls() );
3637 const Reference
< XControl
>* pControls
= aControls
.getConstArray();
3638 const Reference
< XControl
>* pControlsEnd
= aControls
.getConstArray() + aControls
.getLength();
3640 for ( ; pControls
!= pControlsEnd
; ++pControls
)
3642 OSL_ENSURE( pControls
->is(), "FormController::locateControl: NULL-control?" );
3643 if ( pControls
->is() )
3645 if ( ( *pControls
)->getModel() == _rxModel
)
3649 OSL_FAIL( "FormController::locateControl: did not find a control for this model!" );
3651 catch( const Exception
& )
3653 DBG_UNHANDLED_EXCEPTION();
3658 //------------------------------------------------------------------------------
3661 void displayErrorSetFocus( const String
& _rMessage
, const Reference
< XControl
>& _rxFocusControl
, Window
* _pDialogParent
)
3664 aError
.Message
= String( SVX_RES( RID_STR_WRITEERROR
) );
3665 aError
.Details
= _rMessage
;
3666 displayException( aError
, _pDialogParent
);
3668 if ( _rxFocusControl
.is() )
3670 Reference
< XWindow
> xControlWindow( _rxFocusControl
, UNO_QUERY
);
3671 OSL_ENSURE( xControlWindow
.is(), "displayErrorSetFocus: invalid control!" );
3672 if ( xControlWindow
.is() )
3673 xControlWindow
->setFocus();
3677 sal_Bool
lcl_shouldValidateRequiredFields_nothrow( const Reference
< XInterface
>& _rxForm
)
3681 static OUString
s_sFormsCheckRequiredFields( "FormsCheckRequiredFields" );
3683 // first, check whether the form has a property telling us the answer
3684 // this allows people to use the XPropertyContainer interface of a form to control
3685 // the behaviour on a per-form basis.
3686 Reference
< XPropertySet
> xFormProps( _rxForm
, UNO_QUERY_THROW
);
3687 Reference
< XPropertySetInfo
> xPSI( xFormProps
->getPropertySetInfo() );
3688 if ( xPSI
->hasPropertyByName( s_sFormsCheckRequiredFields
) )
3690 sal_Bool bShouldValidate
= true;
3691 OSL_VERIFY( xFormProps
->getPropertyValue( s_sFormsCheckRequiredFields
) >>= bShouldValidate
);
3692 return bShouldValidate
;
3695 // next, check the data source which created the connection
3696 Reference
< XChild
> xConnectionAsChild( xFormProps
->getPropertyValue( FM_PROP_ACTIVE_CONNECTION
), UNO_QUERY_THROW
);
3697 Reference
< XPropertySet
> xDataSource( xConnectionAsChild
->getParent(), UNO_QUERY
);
3698 if ( !xDataSource
.is() )
3699 // seldom (but possible): this is not a connection created by a data source
3702 Reference
< XPropertySet
> xDataSourceSettings(
3703 xDataSource
->getPropertyValue( OUString( "Settings" ) ),
3706 sal_Bool bShouldValidate
= true;
3707 OSL_VERIFY( xDataSourceSettings
->getPropertyValue( s_sFormsCheckRequiredFields
) >>= bShouldValidate
);
3708 return bShouldValidate
;
3710 catch( const Exception
& )
3712 DBG_UNHANDLED_EXCEPTION();
3719 // XRowSetApproveListener
3720 //------------------------------------------------------------------------------
3721 sal_Bool SAL_CALL
FormController::approveRowChange(const RowChangeEvent
& _rEvent
) throw( RuntimeException
)
3723 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
3724 impl_checkDisposed_throw();
3726 ::cppu::OInterfaceIteratorHelper
aIter(m_aRowSetApproveListeners
);
3727 sal_Bool bValid
= sal_True
;
3728 if (aIter
.hasMoreElements())
3730 RowChangeEvent
aEvt( _rEvent
);
3731 aEvt
.Source
= *this;
3732 bValid
= ((XRowSetApproveListener
*)aIter
.next())->approveRowChange(aEvt
);
3738 if ( ( _rEvent
.Action
!= RowChangeAction::INSERT
)
3739 && ( _rEvent
.Action
!= RowChangeAction::UPDATE
)
3743 // if some of the control models are bound to validators, check them
3744 OUString sInvalidityExplanation
;
3745 Reference
< XControlModel
> xInvalidModel
;
3746 if ( !checkFormComponentValidity( sInvalidityExplanation
, xInvalidModel
) )
3748 Reference
< XControl
> xControl( locateControl( xInvalidModel
) );
3750 displayErrorSetFocus( sInvalidityExplanation
, xControl
, getDialogParentWindow() );
3754 // check values on NULL and required flag
3755 if ( !lcl_shouldValidateRequiredFields_nothrow( _rEvent
.Source
) )
3758 OSL_ENSURE( m_pColumnInfoCache
.get(), "FormController::approveRowChange: no column infos!" );
3759 if ( !m_pColumnInfoCache
.get() )
3764 if ( !m_pColumnInfoCache
->controlsInitialized() )
3765 m_pColumnInfoCache
->initializeControls( getControls() );
3767 size_t colCount
= m_pColumnInfoCache
->getColumnCount();
3768 for ( size_t col
= 0; col
< colCount
; ++col
)
3770 const ColumnInfo
& rColInfo
= m_pColumnInfoCache
->getColumnInfo( col
);
3771 if ( rColInfo
.nNullable
!= ColumnValue::NO_NULLS
)
3774 if ( rColInfo
.bAutoIncrement
)
3777 if ( rColInfo
.bReadOnly
)
3780 if ( !rColInfo
.xFirstControlWithInputRequired
.is() && !rColInfo
.xFirstGridWithInputRequiredColumn
.is() )
3783 // TODO: in case of binary fields, this "getString" below is extremely expensive
3784 if ( !rColInfo
.xColumn
->getString().isEmpty() || !rColInfo
.xColumn
->wasNull() )
3787 String
sMessage( SVX_RES( RID_ERR_FIELDREQUIRED
) );
3788 sMessage
.SearchAndReplace( OUString('#'), rColInfo
.sName
);
3790 // the control to focus
3791 Reference
< XControl
> xControl( rColInfo
.xFirstControlWithInputRequired
);
3792 if ( !xControl
.is() )
3793 xControl
.set( rColInfo
.xFirstGridWithInputRequiredColumn
, UNO_QUERY
);
3796 displayErrorSetFocus( sMessage
, rColInfo
.xFirstControlWithInputRequired
, getDialogParentWindow() );
3800 catch( const Exception
& )
3802 DBG_UNHANDLED_EXCEPTION();
3808 //------------------------------------------------------------------------------
3809 sal_Bool SAL_CALL
FormController::approveCursorMove(const EventObject
& event
) throw( RuntimeException
)
3811 ::osl::MutexGuard
aGuard( m_aMutex
);
3812 impl_checkDisposed_throw();
3814 ::cppu::OInterfaceIteratorHelper
aIter(m_aRowSetApproveListeners
);
3815 if (aIter
.hasMoreElements())
3817 EventObject
aEvt(event
);
3818 aEvt
.Source
= *this;
3819 return ((XRowSetApproveListener
*)aIter
.next())->approveCursorMove(aEvt
);
3825 //------------------------------------------------------------------------------
3826 sal_Bool SAL_CALL
FormController::approveRowSetChange(const EventObject
& event
) throw( RuntimeException
)
3828 ::osl::MutexGuard
aGuard( m_aMutex
);
3829 impl_checkDisposed_throw();
3831 ::cppu::OInterfaceIteratorHelper
aIter(m_aRowSetApproveListeners
);
3832 if (aIter
.hasMoreElements())
3834 EventObject
aEvt(event
);
3835 aEvt
.Source
= *this;
3836 return ((XRowSetApproveListener
*)aIter
.next())->approveRowSetChange(aEvt
);
3842 // XRowSetApproveBroadcaster
3843 //------------------------------------------------------------------------------
3844 void SAL_CALL
FormController::addRowSetApproveListener(const Reference
< XRowSetApproveListener
> & _rxListener
) throw( RuntimeException
)
3846 ::osl::MutexGuard
aGuard( m_aMutex
);
3847 impl_checkDisposed_throw();
3849 m_aRowSetApproveListeners
.addInterface(_rxListener
);
3852 //------------------------------------------------------------------------------
3853 void SAL_CALL
FormController::removeRowSetApproveListener(const Reference
< XRowSetApproveListener
> & _rxListener
) throw( RuntimeException
)
3855 ::osl::MutexGuard
aGuard( m_aMutex
);
3856 impl_checkDisposed_throw();
3858 m_aRowSetApproveListeners
.removeInterface(_rxListener
);
3862 //------------------------------------------------------------------------------
3863 void SAL_CALL
FormController::errorOccured(const SQLErrorEvent
& aEvent
) throw( RuntimeException
)
3865 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
3866 impl_checkDisposed_throw();
3868 ::cppu::OInterfaceIteratorHelper
aIter(m_aErrorListeners
);
3869 if (aIter
.hasMoreElements())
3871 SQLErrorEvent
aEvt(aEvent
);
3872 aEvt
.Source
= *this;
3873 ((XSQLErrorListener
*)aIter
.next())->errorOccured(aEvt
);
3878 displayException( aEvent
);
3882 // XErrorBroadcaster
3883 //------------------------------------------------------------------------------
3884 void SAL_CALL
FormController::addSQLErrorListener(const Reference
< XSQLErrorListener
> & aListener
) throw( RuntimeException
)
3886 ::osl::MutexGuard
aGuard( m_aMutex
);
3887 impl_checkDisposed_throw();
3889 m_aErrorListeners
.addInterface(aListener
);
3892 //------------------------------------------------------------------------------
3893 void SAL_CALL
FormController::removeSQLErrorListener(const Reference
< XSQLErrorListener
> & aListener
) throw( RuntimeException
)
3895 ::osl::MutexGuard
aGuard( m_aMutex
);
3896 impl_checkDisposed_throw();
3898 m_aErrorListeners
.removeInterface(aListener
);
3901 // XDatabaseParameterBroadcaster2
3902 //------------------------------------------------------------------------------
3903 void SAL_CALL
FormController::addDatabaseParameterListener(const Reference
< XDatabaseParameterListener
> & aListener
) throw( RuntimeException
)
3905 ::osl::MutexGuard
aGuard( m_aMutex
);
3906 impl_checkDisposed_throw();
3908 m_aParameterListeners
.addInterface(aListener
);
3911 //------------------------------------------------------------------------------
3912 void SAL_CALL
FormController::removeDatabaseParameterListener(const Reference
< XDatabaseParameterListener
> & aListener
) throw( RuntimeException
)
3914 ::osl::MutexGuard
aGuard( m_aMutex
);
3915 impl_checkDisposed_throw();
3917 m_aParameterListeners
.removeInterface(aListener
);
3920 // XDatabaseParameterBroadcaster
3921 //------------------------------------------------------------------------------
3922 void SAL_CALL
FormController::addParameterListener(const Reference
< XDatabaseParameterListener
> & aListener
) throw( RuntimeException
)
3924 FormController::addDatabaseParameterListener( aListener
);
3927 //------------------------------------------------------------------------------
3928 void SAL_CALL
FormController::removeParameterListener(const Reference
< XDatabaseParameterListener
> & aListener
) throw( RuntimeException
)
3930 FormController::removeDatabaseParameterListener( aListener
);
3933 // XDatabaseParameterListener
3934 //------------------------------------------------------------------------------
3935 sal_Bool SAL_CALL
FormController::approveParameter(const DatabaseParameterEvent
& aEvent
) throw( RuntimeException
)
3937 SolarMutexGuard aSolarGuard
;
3938 ::osl::MutexGuard
aGuard( m_aMutex
);
3939 impl_checkDisposed_throw();
3941 ::cppu::OInterfaceIteratorHelper
aIter(m_aParameterListeners
);
3942 if (aIter
.hasMoreElements())
3944 DatabaseParameterEvent
aEvt(aEvent
);
3945 aEvt
.Source
= *this;
3946 return ((XDatabaseParameterListener
*)aIter
.next())->approveParameter(aEvt
);
3950 // default handling: instantiate an interaction handler and let it handle the parameter request
3953 if ( !ensureInteractionHandler() )
3956 // two continuations allowed: OK and Cancel
3957 OParameterContinuation
* pParamValues
= new OParameterContinuation
;
3958 OInteractionAbort
* pAbort
= new OInteractionAbort
;
3960 ParametersRequest aRequest
;
3961 aRequest
.Parameters
= aEvent
.Parameters
;
3962 aRequest
.Connection
= OStaticDataAccessTools().getRowSetConnection(Reference
< XRowSet
>(aEvent
.Source
, UNO_QUERY
));
3963 OInteractionRequest
* pParamRequest
= new OInteractionRequest(makeAny(aRequest
));
3964 Reference
< XInteractionRequest
> xParamRequest(pParamRequest
);
3966 pParamRequest
->addContinuation(pParamValues
);
3967 pParamRequest
->addContinuation(pAbort
);
3969 // handle the request
3970 m_xInteractionHandler
->handle(xParamRequest
);
3972 if (!pParamValues
->wasSelected())
3976 // transfer the values into the parameter supplier
3977 Sequence
< PropertyValue
> aFinalValues
= pParamValues
->getValues();
3978 if (aFinalValues
.getLength() != aRequest
.Parameters
->getCount())
3980 OSL_FAIL("FormController::approveParameter: the InteractionHandler returned nonsense!");
3983 const PropertyValue
* pFinalValues
= aFinalValues
.getConstArray();
3984 for (sal_Int32 i
=0; i
<aFinalValues
.getLength(); ++i
, ++pFinalValues
)
3986 Reference
< XPropertySet
> xParam
;
3987 ::cppu::extractInterface(xParam
, aRequest
.Parameters
->getByIndex(i
));
3992 xParam
->getPropertyValue(FM_PROP_NAME
) >>= sName
;
3993 DBG_ASSERT(sName
.equals(pFinalValues
->Name
), "FormController::approveParameter: suspicious value names!");
3995 try { xParam
->setPropertyValue(FM_PROP_VALUE
, pFinalValues
->Value
); }
3998 OSL_FAIL("FormController::approveParameter: setting one of the properties failed!");
4005 DBG_UNHANDLED_EXCEPTION();
4011 // XConfirmDeleteBroadcaster
4012 //------------------------------------------------------------------------------
4013 void SAL_CALL
FormController::addConfirmDeleteListener(const Reference
< XConfirmDeleteListener
> & aListener
) throw( RuntimeException
)
4015 ::osl::MutexGuard
aGuard( m_aMutex
);
4016 impl_checkDisposed_throw();
4018 m_aDeleteListeners
.addInterface(aListener
);
4021 //------------------------------------------------------------------------------
4022 void SAL_CALL
FormController::removeConfirmDeleteListener(const Reference
< XConfirmDeleteListener
> & aListener
) throw( RuntimeException
)
4024 ::osl::MutexGuard
aGuard( m_aMutex
);
4025 impl_checkDisposed_throw();
4027 m_aDeleteListeners
.removeInterface(aListener
);
4030 // XConfirmDeleteListener
4031 //------------------------------------------------------------------------------
4032 sal_Bool SAL_CALL
FormController::confirmDelete(const RowChangeEvent
& aEvent
) throw( RuntimeException
)
4034 ::osl::MutexGuard
aGuard( m_aMutex
);
4035 impl_checkDisposed_throw();
4037 ::cppu::OInterfaceIteratorHelper
aIter(m_aDeleteListeners
);
4038 if (aIter
.hasMoreElements())
4040 RowChangeEvent
aEvt(aEvent
);
4041 aEvt
.Source
= *this;
4042 return ((XConfirmDeleteListener
*)aIter
.next())->confirmDelete(aEvt
);
4044 // default handling: instantiate an interaction handler and let it handle the request
4047 sal_Int32 nLength
= aEvent
.Rows
;
4050 sTitle
= SVX_RESSTR( RID_STR_DELETECONFIRM_RECORDS
);
4051 sTitle
.SearchAndReplace( OUString('#'), OUString::valueOf(nLength
) );
4054 sTitle
= SVX_RESSTR( RID_STR_DELETECONFIRM_RECORD
);
4058 if ( !ensureInteractionHandler() )
4061 // two continuations allowed: Yes and No
4062 OInteractionApprove
* pApprove
= new OInteractionApprove
;
4063 OInteractionDisapprove
* pDisapprove
= new OInteractionDisapprove
;
4066 SQLWarning aWarning
;
4067 aWarning
.Message
= sTitle
;
4068 SQLWarning aDetails
;
4069 aDetails
.Message
= String( SVX_RES( RID_STR_DELETECONFIRM
) );
4070 aWarning
.NextException
<<= aDetails
;
4072 OInteractionRequest
* pRequest
= new OInteractionRequest( makeAny( aWarning
) );
4073 Reference
< XInteractionRequest
> xRequest( pRequest
);
4076 pRequest
->addContinuation( pApprove
);
4077 pRequest
->addContinuation( pDisapprove
);
4079 // handle the request
4080 m_xInteractionHandler
->handle( xRequest
);
4082 if ( pApprove
->wasSelected() )
4085 catch( const Exception
& )
4087 DBG_UNHANDLED_EXCEPTION();
4093 //------------------------------------------------------------------------------
4094 void SAL_CALL
FormController::invalidateFeatures( const Sequence
< ::sal_Int16
>& _Features
) throw (RuntimeException
)
4096 ::osl::MutexGuard
aGuard( m_aMutex
);
4097 // for now, just copy the ids of the features, because ....
4098 ::std::copy( _Features
.getConstArray(), _Features
.getConstArray() + _Features
.getLength(),
4099 ::std::insert_iterator
< ::std::set
< sal_Int16
> >( m_aInvalidFeatures
, m_aInvalidFeatures
.begin() )
4102 // ... we will do the real invalidation asynchronously
4103 if ( !m_aFeatureInvalidationTimer
.IsActive() )
4104 m_aFeatureInvalidationTimer
.Start();
4107 //------------------------------------------------------------------------------
4108 void SAL_CALL
FormController::invalidateAllFeatures( ) throw (RuntimeException
)
4110 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
4112 Sequence
< sal_Int16
> aInterceptedFeatures( m_aFeatureDispatchers
.size() );
4114 m_aFeatureDispatchers
.begin(),
4115 m_aFeatureDispatchers
.end(),
4116 aInterceptedFeatures
.getArray(),
4117 ::o3tl::select1st
< DispatcherContainer::value_type
>()
4121 if ( aInterceptedFeatures
.getLength() )
4122 invalidateFeatures( aInterceptedFeatures
);
4125 //------------------------------------------------------------------------------
4126 Reference
< XDispatch
>
4127 FormController::interceptedQueryDispatch( const URL
& aURL
,
4128 const OUString
& /*aTargetFrameName*/, sal_Int32
/*nSearchFlags*/)
4129 throw( RuntimeException
)
4131 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
4132 Reference
< XDispatch
> xReturn
;
4133 // dispatches handled by ourself
4134 if ( ( aURL
.Complete
== FMURL_CONFIRM_DELETION
)
4135 || ( ( aURL
.Complete
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "private:/InteractionHandler" ) ) )
4136 && ensureInteractionHandler()
4139 xReturn
= static_cast< XDispatch
* >( this );
4141 // dispatches of FormSlot-URLs we have to translate
4142 if ( !xReturn
.is() && m_xFormOperations
.is() )
4144 // find the slot id which corresponds to the URL
4145 sal_Int32 nFeatureSlotId
= ::svx::FeatureSlotTranslation::getControllerFeatureSlotIdForURL( aURL
.Main
);
4146 sal_Int16 nFormFeature
= ( nFeatureSlotId
!= -1 ) ? ::svx::FeatureSlotTranslation::getFormFeatureForSlotId( nFeatureSlotId
) : -1;
4147 if ( nFormFeature
> 0 )
4149 // get the dispatcher for this feature, create if necessary
4150 DispatcherContainer::const_iterator aDispatcherPos
= m_aFeatureDispatchers
.find( nFormFeature
);
4151 if ( aDispatcherPos
== m_aFeatureDispatchers
.end() )
4153 aDispatcherPos
= m_aFeatureDispatchers
.insert(
4154 DispatcherContainer::value_type( nFormFeature
, new ::svx::OSingleFeatureDispatcher( aURL
, nFormFeature
, m_xFormOperations
, m_aMutex
) )
4158 OSL_ENSURE( aDispatcherPos
->second
.is(), "FormController::interceptedQueryDispatch: should have a dispatcher by now!" );
4159 return aDispatcherPos
->second
;
4167 //------------------------------------------------------------------------------
4168 void SAL_CALL
FormController::dispatch( const URL
& _rURL
, const Sequence
< PropertyValue
>& _rArgs
) throw (RuntimeException
)
4170 if ( _rArgs
.getLength() != 1 )
4172 OSL_FAIL( "FormController::dispatch: no arguments -> no dispatch!" );
4176 if ( _rURL
.Complete
== "private:/InteractionHandler" )
4178 Reference
< XInteractionRequest
> xRequest
;
4179 OSL_VERIFY( _rArgs
[0].Value
>>= xRequest
);
4180 if ( xRequest
.is() )
4185 if ( _rURL
.Complete
== FMURL_CONFIRM_DELETION
)
4187 OSL_FAIL( "FormController::dispatch: How do you expect me to return something via this call?" );
4188 // confirmDelete has a return value - dispatch hasn't
4192 OSL_FAIL( "FormController::dispatch: unknown URL!" );
4195 //------------------------------------------------------------------------------
4196 void SAL_CALL
FormController::addStatusListener( const Reference
< XStatusListener
>& _rxListener
, const URL
& _rURL
) throw (RuntimeException
)
4198 if (_rURL
.Complete
== FMURL_CONFIRM_DELETION
)
4200 if (_rxListener
.is())
4201 { // send an initial statusChanged event
4202 FeatureStateEvent aEvent
;
4203 aEvent
.FeatureURL
= _rURL
;
4204 aEvent
.IsEnabled
= sal_True
;
4205 _rxListener
->statusChanged(aEvent
);
4206 // and don't add the listener at all (the status will never change)
4210 OSL_FAIL("FormController::addStatusListener: invalid (unsupported) URL!");
4213 //------------------------------------------------------------------------------
4214 Reference
< XInterface
> SAL_CALL
FormController::getParent() throw( RuntimeException
)
4219 //------------------------------------------------------------------------------
4220 void SAL_CALL
FormController::setParent( const Reference
< XInterface
>& Parent
) throw( NoSupportException
, RuntimeException
)
4225 //------------------------------------------------------------------------------
4226 void SAL_CALL
FormController::removeStatusListener( const Reference
< XStatusListener
>& /*_rxListener*/, const URL
& _rURL
) throw (RuntimeException
)
4229 OSL_ENSURE(_rURL
.Complete
== FMURL_CONFIRM_DELETION
, "FormController::removeStatusListener: invalid (unsupported) URL!");
4230 // we never really added the listener, so we don't need to remove it
4233 //------------------------------------------------------------------------------
4234 Reference
< XDispatchProviderInterceptor
> FormController::createInterceptor(const Reference
< XDispatchProviderInterception
> & _xInterception
)
4236 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
4238 // check if we already have a interceptor for the given object
4239 for ( ConstInterceptorsIterator aIter
= m_aControlDispatchInterceptors
.begin();
4240 aIter
!= m_aControlDispatchInterceptors
.end();
4244 if ((*aIter
)->getIntercepted() == _xInterception
)
4245 OSL_FAIL("FormController::createInterceptor : we already do intercept this objects dispatches !");
4249 DispatchInterceptionMultiplexer
* pInterceptor
= new DispatchInterceptionMultiplexer( _xInterception
, this );
4250 pInterceptor
->acquire();
4251 m_aControlDispatchInterceptors
.insert( m_aControlDispatchInterceptors
.end(), pInterceptor
);
4253 return pInterceptor
;
4256 //------------------------------------------------------------------------------
4257 bool FormController::ensureInteractionHandler()
4259 if ( m_xInteractionHandler
.is() )
4261 if ( m_bAttemptedHandlerCreation
)
4263 m_bAttemptedHandlerCreation
= true;
4265 m_xInteractionHandler
.set( InteractionHandler::createWithParent(m_aContext
.getUNOContext(), 0), UNO_QUERY
);
4266 OSL_ENSURE( m_xInteractionHandler
.is(), "FormController::ensureInteractionHandler: could not create an interaction handler!" );
4267 return m_xInteractionHandler
.is();
4270 //------------------------------------------------------------------------------
4271 void SAL_CALL
FormController::handle( const Reference
< XInteractionRequest
>& _rRequest
) throw (RuntimeException
)
4273 if ( !ensureInteractionHandler() )
4275 m_xInteractionHandler
->handle( _rRequest
);
4278 //------------------------------------------------------------------------------
4279 void FormController::deleteInterceptor(const Reference
< XDispatchProviderInterception
> & _xInterception
)
4281 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
4282 // search the interceptor responsible for the given object
4283 InterceptorsIterator aIter
;
4284 for ( aIter
= m_aControlDispatchInterceptors
.begin();
4285 aIter
!= m_aControlDispatchInterceptors
.end();
4289 if ((*aIter
)->getIntercepted() == _xInterception
)
4292 if (aIter
== m_aControlDispatchInterceptors
.end())
4297 // log off the interception from it's interception object
4298 DispatchInterceptionMultiplexer
* pInterceptorImpl
= *aIter
;
4299 pInterceptorImpl
->dispose();
4300 pInterceptorImpl
->release();
4302 // remove the interceptor from our array
4303 m_aControlDispatchInterceptors
.erase(aIter
);
4306 //--------------------------------------------------------------------
4307 void FormController::implInvalidateCurrentControlDependentFeatures()
4309 Sequence
< sal_Int16
> aCurrentControlDependentFeatures(4);
4311 aCurrentControlDependentFeatures
[0] = FormFeature::SortAscending
;
4312 aCurrentControlDependentFeatures
[1] = FormFeature::SortDescending
;
4313 aCurrentControlDependentFeatures
[2] = FormFeature::AutoFilter
;
4314 aCurrentControlDependentFeatures
[3] = FormFeature::RefreshCurrentControl
;
4316 invalidateFeatures( aCurrentControlDependentFeatures
);
4319 //--------------------------------------------------------------------
4320 void SAL_CALL
FormController::columnChanged( const EventObject
& /*_event*/ ) throw (RuntimeException
)
4322 implInvalidateCurrentControlDependentFeatures();
4325 } // namespace svxform
4327 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */