xref: /trunk/main/svx/source/form/formcontroller.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 
27 #include "fmcontrolbordermanager.hxx"
28 #include "fmcontrollayout.hxx"
29 #include "formcontroller.hxx"
30 #include "formfeaturedispatcher.hxx"
31 #include "fmdocumentclassification.hxx"
32 #include "formcontrolling.hxx"
33 #include "fmprop.hrc"
34 #include "svx/dialmgr.hxx"
35 #include "svx/fmresids.hrc"
36 #include "fmservs.hxx"
37 #include "svx/fmtools.hxx"
38 #include "fmurl.hxx"
39 
40 /** === begin UNO includes === **/
41 #include <com/sun/star/awt/FocusChangeReason.hpp>
42 #include <com/sun/star/awt/XCheckBox.hpp>
43 #include <com/sun/star/awt/XComboBox.hpp>
44 #include <com/sun/star/awt/XListBox.hpp>
45 #include <com/sun/star/awt/XVclWindowPeer.hpp>
46 #include <com/sun/star/beans/NamedValue.hpp>
47 #include <com/sun/star/beans/PropertyAttribute.hpp>
48 #include <com/sun/star/container/XIdentifierReplace.hpp>
49 #include <com/sun/star/form/TabulatorCycle.hpp>
50 #include <com/sun/star/form/validation/XValidatableFormComponent.hpp>
51 #include <com/sun/star/form/XBoundComponent.hpp>
52 #include <com/sun/star/form/XBoundControl.hpp>
53 #include <com/sun/star/form/XGridControl.hpp>
54 #include <com/sun/star/form/XLoadable.hpp>
55 #include <com/sun/star/form/XReset.hpp>
56 #include <com/sun/star/frame/XController.hpp>
57 #include <com/sun/star/sdb/ParametersRequest.hpp>
58 #include <com/sun/star/sdb/RowChangeAction.hpp>
59 #include <com/sun/star/sdb/XInteractionSupplyParameters.hpp>
60 #include <com/sun/star/sdbc/ColumnValue.hpp>
61 #include <com/sun/star/sdbc/DataType.hpp>
62 #include <com/sun/star/util/XURLTransformer.hpp>
63 #include <com/sun/star/form/runtime/FormOperations.hpp>
64 #include <com/sun/star/form/runtime/FormFeature.hpp>
65 #include <com/sun/star/container/XContainer.hpp>
66 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
67 #include <com/sun/star/util/XNumberFormatter.hpp>
68 #include <com/sun/star/sdb/SQLContext.hpp>
69 #include <com/sun/star/sdb/XColumn.hpp>
70 /** === end UNO includes === **/
71 
72 #include <comphelper/enumhelper.hxx>
73 #include <comphelper/extract.hxx>
74 #include <comphelper/interaction.hxx>
75 #include <comphelper/namedvaluecollection.hxx>
76 #include <comphelper/propagg.hxx>
77 #include <comphelper/property.hxx>
78 #include <comphelper/sequence.hxx>
79 #include <comphelper/uno3.hxx>
80 #include <comphelper/flagguard.hxx>
81 #include <cppuhelper/queryinterface.hxx>
82 #include <cppuhelper/typeprovider.hxx>
83 #include <toolkit/controls/unocontrol.hxx>
84 #include <toolkit/helper/vclunohelper.hxx>
85 #include <tools/debug.hxx>
86 #include <tools/diagnose_ex.h>
87 #include <tools/shl.hxx>
88 #include <vcl/msgbox.hxx>
89 #include <vcl/svapp.hxx>
90 #include <vos/mutex.hxx>
91 #include <rtl/logfile.hxx>
92 
93 #include <algorithm>
94 #include <functional>
95 #include <iterator>
96 
97 using namespace ::com::sun::star;
98 using namespace ::comphelper;
99 using namespace ::connectivity;
100 using namespace ::connectivity::simple;
101 
102 //------------------------------------------------------------------
103 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL
FormController_NewInstance_Impl(const::com::sun::star::uno::Reference<::com::sun::star::lang::XMultiServiceFactory> & _rxORB)104     FormController_NewInstance_Impl( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & _rxORB )
105 {
106     return *( new ::svxform::FormController( _rxORB ) );
107 }
108 
109 namespace svxform
110 {
111 
112     /** === begin UNO using === **/
113     using ::com::sun::star::sdb::XColumn;
114     using ::com::sun::star::awt::XControl;
115     using ::com::sun::star::awt::XTabController;
116     using ::com::sun::star::awt::XToolkit;
117     using ::com::sun::star::awt::XWindowPeer;
118     using ::com::sun::star::form::XGrid;
119     using ::com::sun::star::beans::XPropertySet;
120     using ::com::sun::star::uno::UNO_SET_THROW;
121     using ::com::sun::star::uno::UNO_QUERY_THROW;
122     using ::com::sun::star::container::XIndexAccess;
123     using ::com::sun::star::uno::Exception;
124     using ::com::sun::star::uno::XInterface;
125     using ::com::sun::star::uno::UNO_QUERY;
126     using ::com::sun::star::uno::Sequence;
127     using ::com::sun::star::uno::Reference;
128     using ::com::sun::star::beans::XPropertySetInfo;
129     using ::com::sun::star::beans::PropertyValue;
130     using ::com::sun::star::uno::RuntimeException;
131     using ::com::sun::star::lang::IndexOutOfBoundsException;
132     using ::com::sun::star::sdb::XInteractionSupplyParameters;
133     using ::com::sun::star::awt::XTextComponent;
134     using ::com::sun::star::awt::XTextListener;
135     using ::com::sun::star::uno::Any;
136     using ::com::sun::star::frame::XDispatch;
137     using ::com::sun::star::lang::XMultiServiceFactory;
138     using ::com::sun::star::uno::XAggregation;
139     using ::com::sun::star::uno::Type;
140     using ::com::sun::star::lang::IllegalArgumentException;
141     using ::com::sun::star::sdbc::XConnection;
142     using ::com::sun::star::sdbc::XRowSet;
143     using ::com::sun::star::sdbc::XDatabaseMetaData;
144     using ::com::sun::star::util::XNumberFormatsSupplier;
145     using ::com::sun::star::util::XNumberFormatter;
146     using ::com::sun::star::sdbcx::XColumnsSupplier;
147     using ::com::sun::star::container::XNameAccess;
148     using ::com::sun::star::lang::EventObject;
149     using ::com::sun::star::beans::Property;
150     using ::com::sun::star::container::XEnumeration;
151     using ::com::sun::star::form::XFormComponent;
152     using ::com::sun::star::form::runtime::XFormOperations;
153     using ::com::sun::star::form::runtime::FilterEvent;
154     using ::com::sun::star::form::runtime::XFilterControllerListener;
155     using ::com::sun::star::awt::XControlContainer;
156     using ::com::sun::star::container::XIdentifierReplace;
157     using ::com::sun::star::lang::WrappedTargetException;
158     using ::com::sun::star::form::XFormControllerListener;
159     using ::com::sun::star::awt::XWindow;
160     using ::com::sun::star::sdbc::XResultSet;
161     using ::com::sun::star::awt::XControlModel;
162     using ::com::sun::star::awt::XTabControllerModel;
163     using ::com::sun::star::beans::PropertyChangeEvent;
164     using ::com::sun::star::form::validation::XValidatableFormComponent;
165     using ::com::sun::star::form::XLoadable;
166     using ::com::sun::star::script::XEventAttacherManager;
167     using ::com::sun::star::form::XBoundControl;
168     using ::com::sun::star::beans::XPropertyChangeListener;
169     using ::com::sun::star::awt::TextEvent;
170     using ::com::sun::star::form::XBoundComponent;
171     using ::com::sun::star::awt::XCheckBox;
172     using ::com::sun::star::awt::XComboBox;
173     using ::com::sun::star::awt::XListBox;
174     using ::com::sun::star::awt::ItemEvent;
175     using ::com::sun::star::util::XModifyListener;
176     using ::com::sun::star::form::XReset;
177     using ::com::sun::star::frame::XDispatchProviderInterception;
178     using ::com::sun::star::form::XGridControl;
179     using ::com::sun::star::awt::XVclWindowPeer;
180     using ::com::sun::star::form::validation::XValidator;
181     using ::com::sun::star::awt::FocusEvent;
182     using ::com::sun::star::sdb::SQLContext;
183     using ::com::sun::star::container::XChild;
184     using ::com::sun::star::form::TabulatorCycle_RECORDS;
185     using ::com::sun::star::container::ContainerEvent;
186     using ::com::sun::star::lang::DisposedException;
187     using ::com::sun::star::lang::Locale;
188     using ::com::sun::star::beans::NamedValue;
189     using ::com::sun::star::lang::NoSupportException;
190     using ::com::sun::star::sdb::RowChangeEvent;
191     using ::com::sun::star::frame::XStatusListener;
192     using ::com::sun::star::frame::XDispatchProviderInterceptor;
193     using ::com::sun::star::sdb::SQLErrorEvent;
194     using ::com::sun::star::form::DatabaseParameterEvent;
195     using ::com::sun::star::sdb::ParametersRequest;
196     using ::com::sun::star::task::XInteractionRequest;
197     using ::com::sun::star::util::URL;
198     using ::com::sun::star::frame::FeatureStateEvent;
199     using ::com::sun::star::form::runtime::XFormControllerContext;
200     using ::com::sun::star::task::XInteractionHandler;
201     using ::com::sun::star::form::runtime::FormOperations;
202     using ::com::sun::star::container::XContainer;
203     using ::com::sun::star::sdbc::SQLWarning;
204     /** === end UNO using === **/
205     namespace ColumnValue = ::com::sun::star::sdbc::ColumnValue;
206     namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute;
207     namespace FocusChangeReason = ::com::sun::star::awt::FocusChangeReason;
208     namespace RowChangeAction = ::com::sun::star::sdb::RowChangeAction;
209     namespace FormFeature = ::com::sun::star::form::runtime::FormFeature;
210     namespace DataType = ::com::sun::star::sdbc::DataType;
211 
212 //==============================================================================
213 // ColumnInfo
214 //==============================================================================
215 struct ColumnInfo
216 {
217     // information about the column itself
218     Reference< XColumn >    xColumn;
219     sal_Int32               nNullable;
220     sal_Bool                bAutoIncrement;
221     sal_Bool                bReadOnly;
222     ::rtl::OUString         sName;
223 
224     // information about the control(s) bound to this column
225 
226     /// the first control which is bound to the given column, and which requires input
227     Reference< XControl >   xFirstControlWithInputRequired;
228     /** the first grid control which contains a column which is bound to the given database column, and requires
229         input
230     */
231     Reference< XGrid >      xFirstGridWithInputRequiredColumn;
232     /** if xFirstControlWithInputRequired is a grid control, then nRequiredGridColumn specifies the position
233         of the grid column which is actually bound
234     */
235     sal_Int32               nRequiredGridColumn;
236 
ColumnInfosvxform::ColumnInfo237     ColumnInfo()
238         :xColumn()
239         ,nNullable( ColumnValue::NULLABLE_UNKNOWN )
240         ,bAutoIncrement( sal_False )
241         ,bReadOnly( sal_False )
242         ,sName()
243         ,xFirstControlWithInputRequired()
244         ,xFirstGridWithInputRequiredColumn()
245         ,nRequiredGridColumn( -1 )
246     {
247     }
248 };
249 
250 //==============================================================================
251 //= ColumnInfoCache
252 //==============================================================================
253 class ColumnInfoCache
254 {
255 public:
256     ColumnInfoCache( const Reference< XColumnsSupplier >& _rxColSupplier );
257 
getColumnCount() const258     size_t        getColumnCount() const { return m_aColumns.size(); }
259     const ColumnInfo&   getColumnInfo( size_t _pos );
260 
controlsInitialized() const261     bool    controlsInitialized() const { return m_bControlsInitialized; }
262     void    initializeControls( const Sequence< Reference< XControl > >& _rControls );
263     void    deinitializeControls();
264 
265 private:
266     typedef ::std::vector< ColumnInfo > ColumnInfos;
267     ColumnInfos                         m_aColumns;
268     bool                                m_bControlsInitialized;
269 };
270 
271 //------------------------------------------------------------------------------
ColumnInfoCache(const Reference<XColumnsSupplier> & _rxColSupplier)272 ColumnInfoCache::ColumnInfoCache( const Reference< XColumnsSupplier >& _rxColSupplier )
273     :m_aColumns()
274     ,m_bControlsInitialized( false )
275 {
276     try
277     {
278         m_aColumns.clear();
279 
280         Reference< XColumnsSupplier > xSupplyCols( _rxColSupplier, UNO_SET_THROW );
281         Reference< XIndexAccess > xColumns( xSupplyCols->getColumns(), UNO_QUERY_THROW );
282         sal_Int32 nColumnCount = xColumns->getCount();
283         m_aColumns.reserve( nColumnCount );
284 
285         Reference< XPropertySet >   xColumnProps;
286         for ( sal_Int32 i = 0; i < nColumnCount; ++i )
287         {
288             ColumnInfo aColInfo;
289             aColInfo.xColumn.set( xColumns->getByIndex(i), UNO_QUERY_THROW );
290 
291             xColumnProps.set( aColInfo.xColumn, UNO_QUERY_THROW );
292             OSL_VERIFY( xColumnProps->getPropertyValue( FM_PROP_ISNULLABLE ) >>= aColInfo.nNullable );
293             OSL_VERIFY( xColumnProps->getPropertyValue( FM_PROP_AUTOINCREMENT ) >>= aColInfo.bAutoIncrement );
294             OSL_VERIFY( xColumnProps->getPropertyValue( FM_PROP_NAME ) >>= aColInfo.sName );
295             OSL_VERIFY( xColumnProps->getPropertyValue( FM_PROP_ISREADONLY ) >>= aColInfo.bReadOnly );
296 
297             m_aColumns.push_back( aColInfo );
298         }
299     }
300     catch( const Exception& )
301     {
302         DBG_UNHANDLED_EXCEPTION();
303     }
304 }
305 
306 //------------------------------------------------------------------------------
307 namespace
308 {
lcl_isBoundTo(const Reference<XPropertySet> & _rxControlModel,const Reference<XInterface> & _rxNormDBField)309     bool lcl_isBoundTo( const Reference< XPropertySet >& _rxControlModel, const Reference< XInterface >& _rxNormDBField )
310     {
311         Reference< XInterface > xNormBoundField( _rxControlModel->getPropertyValue( FM_PROP_BOUNDFIELD ), UNO_QUERY );
312         return ( xNormBoundField.get() == _rxNormDBField.get() );
313     }
314 
lcl_isInputRequired(const Reference<XPropertySet> & _rxControlModel)315     bool lcl_isInputRequired( const Reference< XPropertySet >& _rxControlModel )
316     {
317         sal_Bool bInputRequired = sal_True;
318         OSL_VERIFY( _rxControlModel->getPropertyValue( FM_PROP_INPUT_REQUIRED ) >>= bInputRequired );
319         return ( bInputRequired != sal_False );
320     }
321 
lcl_resetColumnControlInfo(ColumnInfo & _rColInfo)322     void lcl_resetColumnControlInfo( ColumnInfo& _rColInfo )
323     {
324         _rColInfo.xFirstControlWithInputRequired.clear();
325         _rColInfo.xFirstGridWithInputRequiredColumn.clear();
326         _rColInfo.nRequiredGridColumn = -1;
327     }
328 }
329 
330 //------------------------------------------------------------------------------
deinitializeControls()331 void ColumnInfoCache::deinitializeControls()
332 {
333     for (   ColumnInfos::iterator col = m_aColumns.begin();
334             col != m_aColumns.end();
335             ++col
336         )
337     {
338         lcl_resetColumnControlInfo( *col );
339     }
340 }
341 
342 //------------------------------------------------------------------------------
initializeControls(const Sequence<Reference<XControl>> & _rControls)343 void ColumnInfoCache::initializeControls( const Sequence< Reference< XControl > >& _rControls )
344 {
345     try
346     {
347         // for every of our known columns, find the controls which are bound to this column
348         for (   ColumnInfos::iterator col = m_aColumns.begin();
349                 col != m_aColumns.end();
350                 ++col
351             )
352         {
353             OSL_ENSURE( !col->xFirstControlWithInputRequired.is() && !col->xFirstGridWithInputRequiredColumn.is()
354                 && ( col->nRequiredGridColumn == -1 ), "ColumnInfoCache::initializeControls: called me twice?" );
355 
356             lcl_resetColumnControlInfo( *col );
357 
358             Reference< XInterface > xNormColumn( col->xColumn, UNO_QUERY_THROW );
359 
360             const Reference< XControl >* pControl( _rControls.getConstArray() );
361             const Reference< XControl >* pControlEnd( pControl + _rControls.getLength() );
362             for ( ; pControl != pControlEnd; ++pControl )
363             {
364                 if ( !pControl->is() )
365                     continue;
366 
367                 Reference< XPropertySet > xModel( (*pControl)->getModel(), UNO_QUERY_THROW );
368                 Reference< XPropertySetInfo > xModelPSI( xModel->getPropertySetInfo(), UNO_SET_THROW );
369 
370                 // special handling for grid controls
371                 Reference< XGrid > xGrid( *pControl, UNO_QUERY );
372                 if ( xGrid.is() )
373                 {
374                     Reference< XIndexAccess > xGridColAccess( xModel, UNO_QUERY_THROW );
375                     sal_Int32 gridColCount = xGridColAccess->getCount();
376                     sal_Int32 gridCol = 0;
377                     for ( gridCol = 0; gridCol < gridColCount; ++gridCol )
378                     {
379                         Reference< XPropertySet > xGridColumnModel( xGridColAccess->getByIndex( gridCol ), UNO_QUERY_THROW );
380 
381                         if  (   !lcl_isBoundTo( xGridColumnModel, xNormColumn )
382                             ||  !lcl_isInputRequired( xGridColumnModel )
383                             )
384                             continue;   // with next grid column
385 
386                         break;
387                     }
388 
389                     if ( gridCol < gridColCount )
390                     {
391                         // found a grid column which is bound to the given
392                         col->xFirstGridWithInputRequiredColumn = xGrid;
393                         col->nRequiredGridColumn = gridCol;
394                         break;
395                     }
396 
397                     continue;   // with next control
398                 }
399 
400                 if  (   !xModelPSI->hasPropertyByName( FM_PROP_BOUNDFIELD )
401                     ||  !lcl_isBoundTo( xModel, xNormColumn )
402                     ||  !lcl_isInputRequired( xModel )
403                     )
404                     continue;   // with next control
405 
406                 break;
407             }
408 
409             if ( pControl == pControlEnd )
410                 // did not find a control which is bound to this particular column, and for which the input is required
411                 continue;   // with next DB column
412 
413             col->xFirstControlWithInputRequired = *pControl;
414         }
415     }
416     catch( const Exception& )
417     {
418         DBG_UNHANDLED_EXCEPTION();
419     }
420 
421     m_bControlsInitialized = true;
422 }
423 
424 //------------------------------------------------------------------------------
getColumnInfo(size_t _pos)425 const ColumnInfo& ColumnInfoCache::getColumnInfo( size_t _pos )
426 {
427     if ( _pos >= m_aColumns.size() )
428         throw IndexOutOfBoundsException();
429 
430     return m_aColumns[ _pos ];
431 }
432 
433 //==================================================================
434 // OParameterContinuation
435 //==================================================================
436 class OParameterContinuation : public OInteraction< XInteractionSupplyParameters >
437 {
438     Sequence< PropertyValue >       m_aValues;
439 
440 public:
OParameterContinuation()441     OParameterContinuation() { }
442 
getValues() const443     Sequence< PropertyValue >   getValues() const { return m_aValues; }
444 
445 // XInteractionSupplyParameters
446     virtual void SAL_CALL setParameters( const Sequence< PropertyValue >& _rValues );
447 };
448 
449 //------------------------------------------------------------------
setParameters(const Sequence<PropertyValue> & _rValues)450 void SAL_CALL OParameterContinuation::setParameters( const Sequence< PropertyValue >& _rValues )
451 {
452     m_aValues = _rValues;
453 }
454 
455 //==================================================================
456 // FmXAutoControl
457 //==================================================================
458 struct FmFieldInfo
459 {
460     rtl::OUString       aFieldName;
461     Reference< XPropertySet >   xField;
462     Reference< XTextComponent >  xText;
463 
FmFieldInfosvxform::FmFieldInfo464     FmFieldInfo(const Reference< XPropertySet >& _xField, const Reference< XTextComponent >& _xText)
465         :xField(_xField)
466         ,xText(_xText)
467     {xField->getPropertyValue(FM_PROP_NAME) >>= aFieldName;}
468 };
469 
470 //==================================================================
471 // FmXAutoControl
472 //==================================================================
473 class FmXAutoControl: public UnoControl
474 
475 {
476     friend Reference< XInterface > SAL_CALL FmXAutoControl_NewInstance_Impl();
477 
478 public:
FmXAutoControl(const::comphelper::ComponentContext & i_context)479     FmXAutoControl( const ::comphelper::ComponentContext& i_context )
480         :UnoControl( i_context.getLegacyServiceFactory() )
481     {
482     }
483 
GetComponentServiceName()484     virtual ::rtl::OUString GetComponentServiceName() {return ::rtl::OUString::createFromAscii("Edit");}
485     virtual void SAL_CALL createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer >  & rParentPeer );
486 
487 protected:
488     virtual void ImplSetPeerProperty( const ::rtl::OUString& rPropName, const Any& rVal );
489 };
490 
491 //------------------------------------------------------------------------------
createPeer(const Reference<XToolkit> & rxToolkit,const Reference<XWindowPeer> & rParentPeer)492 void FmXAutoControl::createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer >  & rParentPeer )
493 {
494     UnoControl::createPeer( rxToolkit, rParentPeer );
495 
496     Reference< XTextComponent >  xText(getPeer() , UNO_QUERY);
497     if (xText.is())
498     {
499         xText->setText(::rtl::OUString(String(SVX_RES(RID_STR_AUTOFIELD))));
500         xText->setEditable(sal_False);
501     }
502 }
503 
504 //------------------------------------------------------------------------------
ImplSetPeerProperty(const::rtl::OUString & rPropName,const Any & rVal)505 void FmXAutoControl::ImplSetPeerProperty( const ::rtl::OUString& rPropName, const Any& rVal )
506 {
507     // these properties are ignored
508     if (rPropName == FM_PROP_TEXT)
509         return;
510 
511     UnoControl::ImplSetPeerProperty( rPropName, rVal );
512 }
513 
514 //------------------------------------------------------------------------------
515 IMPL_LINK( FormController, OnActivateTabOrder, void*, /*EMPTYTAG*/ )
516 {
517     activateTabOrder();
518     return 1;
519 }
520 
521 //------------------------------------------------------------------------------
522 struct UpdateAllListeners : public ::std::unary_function< Reference< XDispatch >, bool >
523 {
operator ()svxform::UpdateAllListeners524     bool operator()( const Reference< XDispatch >& _rxDispatcher ) const
525     {
526         static_cast< ::svx::OSingleFeatureDispatcher* >( _rxDispatcher.get() )->updateAllListeners();
527         // the return is a dummy only so we can use this struct in a std::compose1 call
528         return true;
529     }
530 };
531 //..............................................................................
532 IMPL_LINK( FormController, OnInvalidateFeatures, void*, /*_pNotInterestedInThisParam*/ )
533 {
534     ::osl::MutexGuard aGuard( m_aMutex );
535     for ( ::std::set< sal_Int16 >::const_iterator aLoop = m_aInvalidFeatures.begin();
536           aLoop != m_aInvalidFeatures.end();
537           ++aLoop
538         )
539     {
540         DispatcherContainer::const_iterator aDispatcherPos = m_aFeatureDispatchers.find( *aLoop );
541         if ( aDispatcherPos != m_aFeatureDispatchers.end() )
542         {
543             // TODO: for the real and actual listener notifications, we should release
544             // our mutex
545             UpdateAllListeners( )( aDispatcherPos->second );
546         }
547     }
548     return 1;
549 }
550 
551 /*************************************************************************/
552 
DBG_NAME(FormController)553 DBG_NAME( FormController )
554 //------------------------------------------------------------------
555 FormController::FormController(const Reference< XMultiServiceFactory > & _rxORB )
556                   :FormController_BASE( m_aMutex )
557                   ,OPropertySetHelper( FormController_BASE::rBHelper )
558                   ,OSQLParserClient( _rxORB )
559                   ,m_aContext( _rxORB )
560                   ,m_aActivateListeners(m_aMutex)
561                   ,m_aModifyListeners(m_aMutex)
562                   ,m_aErrorListeners(m_aMutex)
563                   ,m_aDeleteListeners(m_aMutex)
564                   ,m_aRowSetApproveListeners(m_aMutex)
565                   ,m_aParameterListeners(m_aMutex)
566                   ,m_aFilterListeners(m_aMutex)
567                   ,m_pControlBorderManager( new ::svxform::ControlBorderManager )
568                   ,m_xFormOperations()
569                   ,m_aMode( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DataMode" ) ) )
570                   ,m_aLoadEvent( LINK( this, FormController, OnLoad ) )
571                   ,m_aToggleEvent( LINK( this, FormController, OnToggleAutoFields ) )
572                   ,m_aActivationEvent( LINK( this, FormController, OnActivated ) )
573                   ,m_aDeactivationEvent( LINK( this, FormController, OnDeactivated ) )
574                   ,m_nCurrentFilterPosition(-1)
575                   ,m_bCurrentRecordModified(sal_False)
576                   ,m_bCurrentRecordNew(sal_False)
577                   ,m_bLocked(sal_False)
578                   ,m_bDBConnection(sal_False)
579                   ,m_bCycle(sal_False)
580                   ,m_bCanInsert(sal_False)
581                   ,m_bCanUpdate(sal_False)
582                   ,m_bCommitLock(sal_False)
583                   ,m_bModified(sal_False)
584                   ,m_bControlsSorted(sal_False)
585                   ,m_bFiltering(sal_False)
586                   ,m_bAttachEvents(sal_True)
587                   ,m_bDetachEvents(sal_True)
588                   ,m_bAttemptedHandlerCreation( false )
589                   ,m_bSuspendFilterTextListening( false )
590 {
591     DBG_CTOR( FormController, NULL );
592 
593     ::comphelper::increment(m_refCount);
594     {
595         {
596             m_xAggregate = Reference< XAggregation >(
597                 m_aContext.createComponent( "com.sun.star.awt.TabController" ),
598                 UNO_QUERY
599             );
600             DBG_ASSERT( m_xAggregate.is(), "FormController::FormController : could not create my aggregate !" );
601             m_xTabController = Reference< XTabController >( m_xAggregate, UNO_QUERY );
602         }
603 
604         if ( m_xAggregate.is() )
605             m_xAggregate->setDelegator( *this );
606     }
607     ::comphelper::decrement(m_refCount);
608 
609     m_aTabActivationTimer.SetTimeout( 500 );
610     m_aTabActivationTimer.SetTimeoutHdl( LINK( this, FormController, OnActivateTabOrder ) );
611 
612     m_aFeatureInvalidationTimer.SetTimeout( 200 );
613     m_aFeatureInvalidationTimer.SetTimeoutHdl( LINK( this, FormController, OnInvalidateFeatures ) );
614 }
615 
616 //------------------------------------------------------------------
~FormController()617 FormController::~FormController()
618 {
619     {
620         ::osl::MutexGuard aGuard( m_aMutex );
621 
622         m_aLoadEvent.CancelPendingCall();
623         m_aToggleEvent.CancelPendingCall();
624         m_aActivationEvent.CancelPendingCall();
625         m_aDeactivationEvent.CancelPendingCall();
626 
627         if ( m_aTabActivationTimer.IsActive() )
628             m_aTabActivationTimer.Stop();
629     }
630 
631     if ( m_aFeatureInvalidationTimer.IsActive() )
632         m_aFeatureInvalidationTimer.Stop();
633 
634     disposeAllFeaturesAndDispatchers();
635 
636     if ( m_xFormOperations.is() )
637         m_xFormOperations->dispose();
638     m_xFormOperations.clear();
639 
640     // Freigeben der Aggregation
641     if ( m_xAggregate.is() )
642     {
643         m_xAggregate->setDelegator( NULL );
644         m_xAggregate.clear();
645     }
646 
647     DELETEZ( m_pControlBorderManager );
648 
649     DBG_DTOR( FormController, NULL );
650 }
651 
652 // -----------------------------------------------------------------------------
acquire()653 void SAL_CALL FormController::acquire() throw ()
654 {
655     FormController_BASE::acquire();
656 }
657 
658 // -----------------------------------------------------------------------------
release()659 void SAL_CALL FormController::release() throw ()
660 {
661     FormController_BASE::release();
662 }
663 
664 //------------------------------------------------------------------
queryInterface(const Type & _rType)665 Any SAL_CALL FormController::queryInterface( const Type& _rType )
666 {
667     Any aRet = FormController_BASE::queryInterface( _rType );
668     if ( !aRet.hasValue() )
669         aRet = OPropertySetHelper::queryInterface( _rType );
670     if ( !aRet.hasValue() )
671         aRet = m_xAggregate->queryAggregation( _rType );
672     return aRet;
673 }
674 
675 //------------------------------------------------------------------------------
getImplementationId()676 Sequence< sal_Int8 > SAL_CALL FormController::getImplementationId()
677 {
678     static ::cppu::OImplementationId* pId = NULL;
679     if  ( !pId )
680     {
681         ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
682         if ( !pId )
683         {
684             static ::cppu::OImplementationId aId;
685             pId = &aId;
686         }
687     }
688     return pId->getImplementationId();
689 }
690 
691 //------------------------------------------------------------------------------
getTypes()692 Sequence< Type > SAL_CALL FormController::getTypes(  )
693 {
694     return comphelper::concatSequences(
695         FormController_BASE::getTypes(),
696         ::cppu::OPropertySetHelper::getTypes()
697     );
698 }
699 
700 // XServiceInfo
701 //------------------------------------------------------------------------------
supportsService(const::rtl::OUString & ServiceName)702 sal_Bool SAL_CALL FormController::supportsService(const ::rtl::OUString& ServiceName)
703 {
704     Sequence< ::rtl::OUString> aSNL(getSupportedServiceNames());
705     const ::rtl::OUString * pArray = aSNL.getConstArray();
706     for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
707         if( pArray[i] == ServiceName )
708             return sal_True;
709     return sal_False;
710 }
711 
712 //------------------------------------------------------------------------------
getImplementationName()713 ::rtl::OUString SAL_CALL FormController::getImplementationName()
714 {
715     return ::rtl::OUString::createFromAscii( "org.openoffice.comp.svx.FormController" );
716 }
717 
718 //------------------------------------------------------------------------------
getSupportedServiceNames(void)719 Sequence< ::rtl::OUString> SAL_CALL FormController::getSupportedServiceNames(void)
720 {
721     // service names which are supported only, but cannot be used to created an
722     // instance at a service factory
723     Sequence< ::rtl::OUString > aNonCreatableServiceNames( 1 );
724     aNonCreatableServiceNames[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.FormControllerDispatcher" ) );
725 
726     // services which can be used to created an instance at a service factory
727     Sequence< ::rtl::OUString > aCreatableServiceNames( getSupportedServiceNames_Static() );
728     return ::comphelper::concatSequences( aCreatableServiceNames, aNonCreatableServiceNames );
729 }
730 
731 //------------------------------------------------------------------------------
approveReset(const EventObject &)732 sal_Bool SAL_CALL FormController::approveReset(const EventObject& /*rEvent*/)
733 {
734     return sal_True;
735 }
736 
737 //------------------------------------------------------------------------------
resetted(const EventObject & rEvent)738 void SAL_CALL FormController::resetted(const EventObject& rEvent)
739 {
740     ::osl::MutexGuard aGuard(m_aMutex);
741     if (getCurrentControl().is() &&  (getCurrentControl()->getModel() == rEvent.Source))
742         m_bModified = sal_False;
743 }
744 
745 //------------------------------------------------------------------------------
getSupportedServiceNames_Static(void)746 Sequence< ::rtl::OUString> FormController::getSupportedServiceNames_Static(void)
747 {
748     static Sequence< ::rtl::OUString> aServices;
749     if (!aServices.getLength())
750     {
751         aServices.realloc(2);
752         aServices.getArray()[0] = FM_FORM_CONTROLLER;
753         aServices.getArray()[1] = ::rtl::OUString::createFromAscii("com.sun.star.awt.control.TabController");
754     }
755     return aServices;
756 }
757 
758 // -----------------------------------------------------------------------------
759 namespace
760 {
761     struct ResetComponentText : public ::std::unary_function< Reference< XTextComponent >, void >
762     {
operator ()svxform::__anon3c3089620211::ResetComponentText763         void operator()( const Reference< XTextComponent >& _rxText )
764         {
765             _rxText->setText( ::rtl::OUString() );
766         }
767     };
768 
769     struct RemoveComponentTextListener : public ::std::unary_function< Reference< XTextComponent >, void >
770     {
RemoveComponentTextListenersvxform::__anon3c3089620211::RemoveComponentTextListener771         RemoveComponentTextListener( const Reference< XTextListener >& _rxListener )
772             :m_xListener( _rxListener )
773         {
774         }
775 
operator ()svxform::__anon3c3089620211::RemoveComponentTextListener776         void operator()( const Reference< XTextComponent >& _rxText )
777         {
778             _rxText->removeTextListener( m_xListener );
779         }
780 
781     private:
782         Reference< XTextListener >  m_xListener;
783     };
784 }
785 
786 // -----------------------------------------------------------------------------
impl_setTextOnAllFilter_throw()787 void FormController::impl_setTextOnAllFilter_throw()
788 {
789     m_bSuspendFilterTextListening = true;
790     ::comphelper::FlagGuard aResetFlag( m_bSuspendFilterTextListening );
791 
792     // reset the text for all controls
793     ::std::for_each( m_aFilterComponents.begin(), m_aFilterComponents.end(), ResetComponentText() );
794 
795     if ( m_aFilterRows.empty() )
796         // nothing to do anymore
797         return;
798 
799     if ( m_nCurrentFilterPosition < 0 )
800         return;
801 
802     // set the text for all filters
803     OSL_ENSURE( m_aFilterRows.size() > (size_t)m_nCurrentFilterPosition,
804         "FormController::impl_setTextOnAllFilter_throw: m_nCurrentFilterPosition too big" );
805 
806     if ( (size_t)m_nCurrentFilterPosition < m_aFilterRows.size() )
807     {
808         FmFilterRow& rRow = m_aFilterRows[ m_nCurrentFilterPosition ];
809         for (   FmFilterRow::const_iterator iter2 = rRow.begin();
810                 iter2 != rRow.end();
811                 ++iter2
812             )
813         {
814             iter2->first->setText( iter2->second );
815         }
816     }
817 }
818 // OPropertySetHelper
819 //------------------------------------------------------------------------------
convertFastPropertyValue(Any &,Any &,sal_Int32,const Any &)820 sal_Bool FormController::convertFastPropertyValue( Any & /*rConvertedValue*/, Any & /*rOldValue*/,
821                                             sal_Int32 /*nHandle*/, const Any& /*rValue*/ )
822 {
823     return sal_False;
824 }
825 
826 //------------------------------------------------------------------------------
setFastPropertyValue_NoBroadcast(sal_Int32,const Any &)827 void FormController::setFastPropertyValue_NoBroadcast( sal_Int32 /*nHandle*/, const Any& /*rValue*/ )
828 {
829 }
830 
831 //------------------------------------------------------------------------------
getFastPropertyValue(Any & rValue,sal_Int32 nHandle) const832 void FormController::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
833 {
834     switch (nHandle)
835     {
836         case FM_ATTR_FILTER:
837         {
838             ::rtl::OUStringBuffer aFilter;
839             OStaticDataAccessTools aStaticTools;
840             Reference<XConnection> xConnection(aStaticTools.getRowSetConnection(Reference< XRowSet>(m_xModelAsIndex, UNO_QUERY)));
841             if (xConnection.is())
842             {
843                 Reference< XDatabaseMetaData> xMetaData(xConnection->getMetaData());
844                 Reference< XNumberFormatsSupplier> xFormatSupplier( aStaticTools.getNumberFormats( xConnection, sal_True ) );
845                 Reference< XNumberFormatter> xFormatter( m_aContext.createComponent( "com.sun.star.util.NumberFormatter" ), UNO_QUERY_THROW );
846                 xFormatter->attachNumberFormatsSupplier(xFormatSupplier);
847 
848                 Reference< XColumnsSupplier> xSupplyCols(m_xModelAsIndex, UNO_QUERY);
849                 Reference< XNameAccess> xFields(xSupplyCols->getColumns(), UNO_QUERY);
850 
851                 ::rtl::OUString aQuote( xMetaData->getIdentifierQuoteString() );
852 
853                 // now add the filter rows
854                 try
855                 {
856                     for ( FmFilterRows::const_iterator row = m_aFilterRows.begin(); row != m_aFilterRows.end(); ++row )
857                     {
858                         const FmFilterRow& rRow = *row;
859 
860                         if ( rRow.empty() )
861                             continue;
862 
863                         ::rtl::OUStringBuffer aRowFilter;
864                         for ( FmFilterRow::const_iterator condition = rRow.begin(); condition != rRow.end(); ++condition )
865                         {
866                             // get the field of the controls map
867                             Reference< XControl > xControl( condition->first, UNO_QUERY_THROW );
868                             Reference< XPropertySet > xModelProps( xControl->getModel(), UNO_QUERY_THROW );
869                             Reference< XPropertySet > xField( xModelProps->getPropertyValue( FM_PROP_BOUNDFIELD ), UNO_QUERY_THROW );
870 
871                             ::rtl::OUString sFilterValue( condition->second );
872 
873                             ::rtl::OUString sErrorMsg, sCriteria;
874                             const ::rtl::Reference< ISQLParseNode > xParseNode =
875                                 predicateTree( sErrorMsg, sFilterValue, xFormatter, xField );
876                             OSL_ENSURE( xParseNode.is(), "FormController::getFastPropertyValue: could not parse the field value predicate!" );
877                             if ( xParseNode.is() )
878                             {
879                                 // don't use a parse context here, we need it unlocalized
880                                 xParseNode->parseNodeToStr( sCriteria, xConnection, NULL );
881                                 if ( condition != rRow.begin() )
882                                     aRowFilter.appendAscii( " AND " );
883                                 aRowFilter.append( sCriteria );
884                             }
885                         }
886                         if ( aRowFilter.getLength() > 0 )
887                         {
888                             if ( aFilter.getLength() )
889                                 aFilter.appendAscii( " OR " );
890 
891                             aFilter.appendAscii( "( " );
892                             aFilter.append( aRowFilter.makeStringAndClear() );
893                             aFilter.appendAscii( " )" );
894                         }
895                     }
896                 }
897                 catch( const Exception& )
898                 {
899                     DBG_UNHANDLED_EXCEPTION();
900                     aFilter.setLength(0);
901                 }
902             }
903             rValue <<= aFilter.makeStringAndClear();
904         }
905         break;
906 
907         case FM_ATTR_FORM_OPERATIONS:
908             rValue <<= m_xFormOperations;
909             break;
910     }
911 }
912 
913 //------------------------------------------------------------------------------
getPropertySetInfo()914 Reference< XPropertySetInfo >  FormController::getPropertySetInfo()
915 {
916     static Reference< XPropertySetInfo >  xInfo( createPropertySetInfo( getInfoHelper() ) );
917     return xInfo;
918 }
919 
920 //------------------------------------------------------------------------------
921 #define DECL_PROP_CORE(varname, type) \
922 pDesc[nPos++] = Property(FM_PROP_##varname, FM_ATTR_##varname, ::getCppuType((const type*)0),
923 
924 
925 #define DECL_PROP1(varname, type, attrib1)  \
926     DECL_PROP_CORE(varname, type) PropertyAttribute::attrib1)
927 
928 //------------------------------------------------------------------------------
fillProperties(Sequence<Property> & _rProps,Sequence<Property> &) const929 void FormController::fillProperties(
930         Sequence< Property >& /* [out] */ _rProps,
931         Sequence< Property >& /* [out] */ /*_rAggregateProps*/
932         ) const
933 {
934     _rProps.realloc(2);
935     sal_Int32 nPos = 0;
936     Property* pDesc = _rProps.getArray();
937     DECL_PROP1(FILTER, rtl::OUString, READONLY);
938     DECL_PROP1(FORM_OPERATIONS, Reference< XFormOperations >, READONLY);
939 }
940 
941 //------------------------------------------------------------------------------
getInfoHelper()942 ::cppu::IPropertyArrayHelper& FormController::getInfoHelper()
943 {
944     return *getArrayHelper();
945 }
946 
947 // XFilterController
948 //------------------------------------------------------------------------------
addFilterControllerListener(const Reference<XFilterControllerListener> & _Listener)949 void SAL_CALL FormController::addFilterControllerListener( const Reference< XFilterControllerListener >& _Listener )
950 {
951     m_aFilterListeners.addInterface( _Listener );
952 }
953 
954 //------------------------------------------------------------------------------
removeFilterControllerListener(const Reference<XFilterControllerListener> & _Listener)955 void SAL_CALL FormController::removeFilterControllerListener( const Reference< XFilterControllerListener >& _Listener )
956 {
957     m_aFilterListeners.removeInterface( _Listener );
958 }
959 
960 //------------------------------------------------------------------------------
getFilterComponents()961 ::sal_Int32 SAL_CALL FormController::getFilterComponents()
962 {
963     ::osl::MutexGuard aGuard( m_aMutex );
964     impl_checkDisposed_throw();
965 
966     return m_aFilterComponents.size();
967 }
968 
969 //------------------------------------------------------------------------------
getDisjunctiveTerms()970 ::sal_Int32 SAL_CALL FormController::getDisjunctiveTerms()
971 {
972     ::osl::MutexGuard aGuard( m_aMutex );
973     impl_checkDisposed_throw();
974 
975     return m_aFilterRows.size();
976 }
977 
978 //------------------------------------------------------------------------------
setPredicateExpression(::sal_Int32 _Component,::sal_Int32 _Term,const::rtl::OUString & _PredicateExpression)979 void SAL_CALL FormController::setPredicateExpression( ::sal_Int32 _Component, ::sal_Int32 _Term, const ::rtl::OUString& _PredicateExpression )
980 {
981     ::osl::MutexGuard aGuard( m_aMutex );
982     impl_checkDisposed_throw();
983 
984     if ( ( _Component < 0 ) || ( _Component >= getFilterComponents() ) || ( _Term < 0 ) || ( _Term >= getDisjunctiveTerms() ) )
985         throw IndexOutOfBoundsException( ::rtl::OUString(), *this );
986 
987     Reference< XTextComponent > xText( m_aFilterComponents[ _Component ] );
988     xText->setText( _PredicateExpression );
989 
990     FmFilterRow& rFilterRow = m_aFilterRows[ _Term ];
991     if ( _PredicateExpression.getLength() )
992         rFilterRow[ xText ] = _PredicateExpression;
993     else
994         rFilterRow.erase( xText );
995 }
996 
997 //------------------------------------------------------------------------------
getFilterComponent(::sal_Int32 _Component)998 Reference< XControl > FormController::getFilterComponent( ::sal_Int32 _Component )
999 {
1000     ::osl::MutexGuard aGuard( m_aMutex );
1001     impl_checkDisposed_throw();
1002 
1003     if ( ( _Component < 0 ) || ( _Component >= getFilterComponents() ) )
1004         throw IndexOutOfBoundsException( ::rtl::OUString(), *this );
1005 
1006     return Reference< XControl >( m_aFilterComponents[ _Component ], UNO_QUERY );
1007 }
1008 
1009 //------------------------------------------------------------------------------
getPredicateExpressions()1010 Sequence< Sequence< ::rtl::OUString > > FormController::getPredicateExpressions()
1011 {
1012     ::osl::MutexGuard aGuard( m_aMutex );
1013     impl_checkDisposed_throw();
1014 
1015     Sequence< Sequence< ::rtl::OUString > > aExpressions( m_aFilterRows.size() );
1016     sal_Int32 termIndex = 0;
1017     for (   FmFilterRows::const_iterator row = m_aFilterRows.begin();
1018             row != m_aFilterRows.end();
1019             ++row, ++termIndex
1020         )
1021     {
1022         const FmFilterRow& rRow( *row );
1023 
1024         Sequence< ::rtl::OUString > aConjunction( m_aFilterComponents.size() );
1025         sal_Int32 componentIndex = 0;
1026         for (   FilterComponents::const_iterator comp = m_aFilterComponents.begin();
1027                 comp != m_aFilterComponents.end();
1028                 ++comp, ++componentIndex
1029             )
1030         {
1031             FmFilterRow::const_iterator predicate = rRow.find( *comp );
1032             if ( predicate != rRow.end() )
1033                 aConjunction[ componentIndex ] = predicate->second;
1034         }
1035 
1036         aExpressions[ termIndex ] = aConjunction;
1037     }
1038 
1039     return aExpressions;
1040 }
1041 
1042 //------------------------------------------------------------------------------
removeDisjunctiveTerm(::sal_Int32 _Term)1043 void SAL_CALL FormController::removeDisjunctiveTerm( ::sal_Int32 _Term )
1044 {
1045     // SYNCHRONIZED -->
1046     ::osl::ClearableMutexGuard aGuard( m_aMutex );
1047     impl_checkDisposed_throw();
1048 
1049     if ( ( _Term < 0 ) || ( _Term >= getDisjunctiveTerms() ) )
1050         throw IndexOutOfBoundsException( ::rtl::OUString(), *this );
1051 
1052     // if the to-be-deleted row is our current row, we need to shift
1053     if ( _Term == m_nCurrentFilterPosition )
1054     {
1055         if ( m_nCurrentFilterPosition < sal_Int32( m_aFilterRows.size() - 1 ) )
1056             ++m_nCurrentFilterPosition;
1057         else
1058             --m_nCurrentFilterPosition;
1059     }
1060 
1061     FmFilterRows::iterator pos = m_aFilterRows.begin() + _Term;
1062     m_aFilterRows.erase( pos );
1063 
1064     // adjust m_nCurrentFilterPosition if the removed row preceded it
1065     if ( _Term < m_nCurrentFilterPosition )
1066         --m_nCurrentFilterPosition;
1067 
1068     OSL_POSTCOND( ( m_nCurrentFilterPosition < 0 ) == ( m_aFilterRows.empty() ),
1069         "FormController::removeDisjunctiveTerm: inconsistency!" );
1070 
1071     // update the texts in the filter controls
1072     impl_setTextOnAllFilter_throw();
1073 
1074     FilterEvent aEvent;
1075     aEvent.Source = *this;
1076     aEvent.DisjunctiveTerm = _Term;
1077     aGuard.clear();
1078     // <-- SYNCHRONIZED
1079 
1080     m_aFilterListeners.notifyEach( &XFilterControllerListener::disjunctiveTermRemoved, aEvent );
1081 }
1082 
1083 //------------------------------------------------------------------------------
appendEmptyDisjunctiveTerm()1084 void SAL_CALL FormController::appendEmptyDisjunctiveTerm()
1085 {
1086     // SYNCHRONIZED -->
1087     ::osl::ClearableMutexGuard aGuard( m_aMutex );
1088     impl_checkDisposed_throw();
1089 
1090     impl_appendEmptyFilterRow( aGuard );
1091     // <-- SYNCHRONIZED
1092 }
1093 
1094 //------------------------------------------------------------------------------
getActiveTerm()1095 ::sal_Int32 SAL_CALL FormController::getActiveTerm()
1096 {
1097     ::osl::MutexGuard aGuard( m_aMutex );
1098     impl_checkDisposed_throw();
1099 
1100     return m_nCurrentFilterPosition;
1101 }
1102 
1103 //------------------------------------------------------------------------------
setActiveTerm(::sal_Int32 _ActiveTerm)1104 void SAL_CALL FormController::setActiveTerm( ::sal_Int32 _ActiveTerm )
1105 {
1106     ::osl::MutexGuard aGuard( m_aMutex );
1107     impl_checkDisposed_throw();
1108 
1109     if ( ( _ActiveTerm < 0 ) || ( _ActiveTerm >= getDisjunctiveTerms() ) )
1110         throw IndexOutOfBoundsException( ::rtl::OUString(), *this );
1111 
1112     if ( _ActiveTerm == getActiveTerm() )
1113         return;
1114 
1115     m_nCurrentFilterPosition = _ActiveTerm;
1116     impl_setTextOnAllFilter_throw();
1117 }
1118 
1119 // XElementAccess
1120 //------------------------------------------------------------------------------
hasElements(void)1121 sal_Bool SAL_CALL FormController::hasElements(void)
1122 {
1123     ::osl::MutexGuard aGuard( m_aMutex );
1124     return !m_aChilds.empty();
1125 }
1126 
1127 //------------------------------------------------------------------------------
getElementType(void)1128 Type SAL_CALL  FormController::getElementType(void)
1129 {
1130     return ::getCppuType((const Reference< XFormController>*)0);
1131 
1132 }
1133 
1134 // XEnumerationAccess
1135 //------------------------------------------------------------------------------
createEnumeration(void)1136 Reference< XEnumeration > SAL_CALL  FormController::createEnumeration(void)
1137 {
1138     ::osl::MutexGuard aGuard( m_aMutex );
1139     return new ::comphelper::OEnumerationByIndex(this);
1140 }
1141 
1142 // XIndexAccess
1143 //------------------------------------------------------------------------------
getCount(void)1144 sal_Int32 SAL_CALL FormController::getCount(void)
1145 {
1146     ::osl::MutexGuard aGuard( m_aMutex );
1147     return m_aChilds.size();
1148 }
1149 
1150 //------------------------------------------------------------------------------
getByIndex(sal_Int32 Index)1151 Any SAL_CALL FormController::getByIndex(sal_Int32 Index)
1152 {
1153     ::osl::MutexGuard aGuard( m_aMutex );
1154     if (Index < 0 ||
1155         Index >= (sal_Int32)m_aChilds.size())
1156         throw IndexOutOfBoundsException();
1157 
1158     return makeAny( m_aChilds[ Index ] );
1159 }
1160 
1161 //  EventListener
1162 //------------------------------------------------------------------------------
disposing(const EventObject & e)1163 void SAL_CALL FormController::disposing(const EventObject& e)
1164 {
1165     // Ist der Container disposed worden
1166     ::osl::MutexGuard aGuard( m_aMutex );
1167     Reference< XControlContainer >  xContainer(e.Source, UNO_QUERY);
1168     if (xContainer.is())
1169     {
1170         setContainer(Reference< XControlContainer > ());
1171     }
1172     else
1173     {
1174         // ist ein Control disposed worden
1175         Reference< XControl >  xControl(e.Source, UNO_QUERY);
1176         if (xControl.is())
1177         {
1178             if (getContainer().is())
1179                 removeControl(xControl);
1180         }
1181     }
1182 }
1183 
1184 // OComponentHelper
1185 //-----------------------------------------------------------------------------
disposeAllFeaturesAndDispatchers()1186 void FormController::disposeAllFeaturesAndDispatchers() SAL_THROW(())
1187 {
1188     for ( DispatcherContainer::iterator aDispatcher = m_aFeatureDispatchers.begin();
1189           aDispatcher != m_aFeatureDispatchers.end();
1190           ++aDispatcher
1191         )
1192     {
1193         try
1194         {
1195             ::comphelper::disposeComponent( aDispatcher->second );
1196         }
1197         catch( const Exception& )
1198         {
1199             DBG_UNHANDLED_EXCEPTION();
1200         }
1201     }
1202     m_aFeatureDispatchers.clear();
1203 }
1204 
1205 //-----------------------------------------------------------------------------
disposing(void)1206 void FormController::disposing(void)
1207 {
1208     EventObject aEvt( *this );
1209 
1210     // if we're still active, simulate a "deactivated" event
1211     if ( m_xActiveControl.is() )
1212         m_aActivateListeners.notifyEach( &XFormControllerListener::formDeactivated, aEvt );
1213 
1214     // notify all our listeners
1215     m_aActivateListeners.disposeAndClear(aEvt);
1216     m_aModifyListeners.disposeAndClear(aEvt);
1217     m_aErrorListeners.disposeAndClear(aEvt);
1218     m_aDeleteListeners.disposeAndClear(aEvt);
1219     m_aRowSetApproveListeners.disposeAndClear(aEvt);
1220     m_aParameterListeners.disposeAndClear(aEvt);
1221     m_aFilterListeners.disposeAndClear(aEvt);
1222 
1223     removeBoundFieldListener();
1224     stopFiltering();
1225 
1226     m_pControlBorderManager->restoreAll();
1227 
1228     m_aFilterRows.clear();
1229 
1230     ::osl::MutexGuard aGuard( m_aMutex );
1231     m_xActiveControl = NULL;
1232     implSetCurrentControl( NULL );
1233 
1234     // clean up our children
1235     for (FmFormControllers::const_iterator i = m_aChilds.begin();
1236         i != m_aChilds.end(); i++)
1237     {
1238         // search the position of the model within the form
1239         Reference< XFormComponent >  xForm((*i)->getModel(), UNO_QUERY);
1240         sal_uInt32 nPos = m_xModelAsIndex->getCount();
1241         Reference< XFormComponent > xTemp;
1242         for( ; nPos; )
1243         {
1244 
1245             m_xModelAsIndex->getByIndex( --nPos ) >>= xTemp;
1246             if ( xForm.get() == xTemp.get() )
1247             {
1248                 Reference< XInterface > xIfc( *i, UNO_QUERY );
1249                 m_xModelAsManager->detach( nPos, xIfc );
1250                 break;
1251             }
1252         }
1253 
1254         Reference< XComponent > (*i, UNO_QUERY)->dispose();
1255     }
1256     m_aChilds.clear();
1257 
1258     disposeAllFeaturesAndDispatchers();
1259 
1260     if ( m_xFormOperations.is() )
1261         m_xFormOperations->dispose();
1262     m_xFormOperations.clear();
1263 
1264     if (m_bDBConnection)
1265         unload();
1266 
1267     setContainer( NULL );
1268     setModel( NULL );
1269     setParent( NULL );
1270 
1271     ::comphelper::disposeComponent( m_xComposer );
1272 
1273     m_bDBConnection = sal_False;
1274 }
1275 
1276 //------------------------------------------------------------------------------
1277 namespace
1278 {
lcl_shouldUseDynamicControlBorder(const Reference<XInterface> & _rxForm,const Any & _rDynamicColorProp)1279     static bool lcl_shouldUseDynamicControlBorder( const Reference< XInterface >& _rxForm, const Any& _rDynamicColorProp )
1280     {
1281         bool bDoUse = false;
1282         if ( !( _rDynamicColorProp >>= bDoUse ) )
1283         {
1284             DocumentType eDocType = DocumentClassification::classifyHostDocument( _rxForm );
1285             return ControlLayouter::useDynamicBorderColor( eDocType );
1286         }
1287         return bDoUse;
1288     }
1289 }
1290 
1291 //------------------------------------------------------------------------------
propertyChange(const PropertyChangeEvent & evt)1292 void SAL_CALL FormController::propertyChange(const PropertyChangeEvent& evt)
1293 {
1294     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1295     if ( evt.PropertyName == FM_PROP_BOUNDFIELD )
1296     {
1297         Reference<XPropertySet> xOldBound;
1298         evt.OldValue >>= xOldBound;
1299         if ( !xOldBound.is() && evt.NewValue.hasValue() )
1300         {
1301             Reference< XControlModel > xControlModel(evt.Source,UNO_QUERY);
1302             Reference< XControl > xControl = findControl(m_aControls,xControlModel,sal_False,sal_False);
1303             if ( xControl.is() )
1304             {
1305                 startControlModifyListening( xControl );
1306                 Reference<XPropertySet> xProp(xControlModel,UNO_QUERY);
1307                 if ( xProp.is() )
1308                     xProp->removePropertyChangeListener(FM_PROP_BOUNDFIELD, this);
1309             }
1310         }
1311     }
1312     else
1313     {
1314         sal_Bool bModifiedChanged = (evt.PropertyName == FM_PROP_ISMODIFIED);
1315         sal_Bool bNewChanged = (evt.PropertyName == FM_PROP_ISNEW);
1316         if (bModifiedChanged || bNewChanged)
1317         {
1318             ::osl::MutexGuard aGuard( m_aMutex );
1319             if (bModifiedChanged)
1320                 m_bCurrentRecordModified = ::comphelper::getBOOL(evt.NewValue);
1321             else
1322                 m_bCurrentRecordNew = ::comphelper::getBOOL(evt.NewValue);
1323 
1324             // toggle the locking
1325             if (m_bLocked != determineLockState())
1326             {
1327                 m_bLocked = !m_bLocked;
1328                 setLocks();
1329                 if (isListeningForChanges())
1330                     startListening();
1331                 else
1332                     stopListening();
1333             }
1334 
1335             if ( bNewChanged )
1336                 m_aToggleEvent.Call();
1337 
1338             if (!m_bCurrentRecordModified)
1339                 m_bModified = sal_False;
1340         }
1341         else if ( evt.PropertyName == FM_PROP_DYNAMIC_CONTROL_BORDER )
1342         {
1343             bool bEnable = lcl_shouldUseDynamicControlBorder( evt.Source, evt.NewValue );
1344             if ( bEnable )
1345             {
1346                 m_pControlBorderManager->enableDynamicBorderColor();
1347                 if ( m_xActiveControl.is() )
1348                     m_pControlBorderManager->focusGained( m_xActiveControl.get() );
1349             }
1350             else
1351             {
1352                 m_pControlBorderManager->disableDynamicBorderColor();
1353             }
1354         }
1355     }
1356 }
1357 
1358 //------------------------------------------------------------------------------
replaceControl(const Reference<XControl> & _rxExistentControl,const Reference<XControl> & _rxNewControl)1359 bool FormController::replaceControl( const Reference< XControl >& _rxExistentControl, const Reference< XControl >& _rxNewControl )
1360 {
1361     bool bSuccess = false;
1362     try
1363     {
1364         Reference< XIdentifierReplace > xContainer( getContainer(), UNO_QUERY );
1365         DBG_ASSERT( xContainer.is(), "FormController::replaceControl: yes, it's not required by the service description, but XItentifierReplaces would be nice!" );
1366         if ( xContainer.is() )
1367         {
1368             // look up the ID of _rxExistentControl
1369             Sequence< sal_Int32 > aIdentifiers( xContainer->getIdentifiers() );
1370             const sal_Int32* pIdentifiers = aIdentifiers.getConstArray();
1371             const sal_Int32* pIdentifiersEnd = aIdentifiers.getConstArray() + aIdentifiers.getLength();
1372             for ( ; pIdentifiers != pIdentifiersEnd; ++pIdentifiers )
1373             {
1374                 Reference< XControl > xCheck( xContainer->getByIdentifier( *pIdentifiers ), UNO_QUERY );
1375                 if ( xCheck == _rxExistentControl )
1376                     break;
1377             }
1378             DBG_ASSERT( pIdentifiers != pIdentifiersEnd, "FormController::replaceControl: did not find the control in the container!" );
1379             if ( pIdentifiers != pIdentifiersEnd )
1380             {
1381                 bool bReplacedWasActive = ( m_xActiveControl.get() == _rxExistentControl.get() );
1382                 bool bReplacedWasCurrent = ( m_xCurrentControl.get() == _rxExistentControl.get() );
1383 
1384                 if ( bReplacedWasActive )
1385                 {
1386                     m_xActiveControl = NULL;
1387                     implSetCurrentControl( NULL );
1388                 }
1389                 else if ( bReplacedWasCurrent )
1390                 {
1391                     implSetCurrentControl( _rxNewControl );
1392                 }
1393 
1394                 // carry over the model
1395                 _rxNewControl->setModel( _rxExistentControl->getModel() );
1396 
1397                 xContainer->replaceByIdentifer( *pIdentifiers, makeAny( _rxNewControl ) );
1398                 bSuccess = true;
1399 
1400                 if ( bReplacedWasActive )
1401                 {
1402                     Reference< XWindow > xControlWindow( _rxNewControl, UNO_QUERY );
1403                     if ( xControlWindow.is() )
1404                         xControlWindow->setFocus();
1405                 }
1406             }
1407         }
1408     }
1409     catch( const Exception& )
1410     {
1411         DBG_UNHANDLED_EXCEPTION();
1412     }
1413 
1414     Reference< XControl > xDisposeIt( bSuccess ? _rxExistentControl : _rxNewControl );
1415     ::comphelper::disposeComponent( xDisposeIt );
1416     return bSuccess;
1417 }
1418 
1419 //------------------------------------------------------------------------------
toggleAutoFields(sal_Bool bAutoFields)1420 void FormController::toggleAutoFields(sal_Bool bAutoFields)
1421 {
1422     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1423 
1424 
1425     Sequence< Reference< XControl > > aControlsCopy( m_aControls );
1426     const Reference< XControl >* pControls = aControlsCopy.getConstArray();
1427     sal_Int32 nControls = aControlsCopy.getLength();
1428 
1429     if (bAutoFields)
1430     {
1431         // as we don't want new controls to be attached to the scripting environment
1432         // we change attach flags
1433         m_bAttachEvents = sal_False;
1434         for (sal_Int32 i = nControls; i > 0;)
1435         {
1436             Reference< XControl > xControl = pControls[--i];
1437             if (xControl.is())
1438             {
1439                 Reference< XPropertySet >  xSet(xControl->getModel(), UNO_QUERY);
1440                 if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
1441                 {
1442                     // does the model use a bound field ?
1443                     Reference< XPropertySet >  xField;
1444                     xSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
1445 
1446                     // is it a autofield?
1447                     if  (   xField.is()
1448                         &&  ::comphelper::hasProperty( FM_PROP_AUTOINCREMENT, xField )
1449                         &&  ::comphelper::getBOOL( xField->getPropertyValue( FM_PROP_AUTOINCREMENT ) )
1450                         )
1451                     {
1452                         replaceControl( xControl, new FmXAutoControl( m_aContext ) );
1453                     }
1454                 }
1455             }
1456         }
1457         m_bAttachEvents = sal_True;
1458     }
1459     else
1460     {
1461         m_bDetachEvents = sal_False;
1462         for (sal_Int32 i = nControls; i > 0;)
1463         {
1464             Reference< XControl > xControl = pControls[--i];
1465             if (xControl.is())
1466             {
1467                 Reference< XPropertySet >  xSet(xControl->getModel(), UNO_QUERY);
1468                 if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
1469                 {
1470                     // does the model use a bound field ?
1471                     Reference< XPropertySet >  xField;
1472                     xSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
1473 
1474                     // is it a autofield?
1475                     if  (   xField.is()
1476                         &&  ::comphelper::hasProperty( FM_PROP_AUTOINCREMENT, xField )
1477                         &&  ::comphelper::getBOOL( xField->getPropertyValue(FM_PROP_AUTOINCREMENT ) )
1478                         )
1479                     {
1480                         ::rtl::OUString sServiceName;
1481                         OSL_VERIFY( xSet->getPropertyValue( FM_PROP_DEFAULTCONTROL ) >>= sServiceName );
1482                         Reference< XControl > xNewControl( m_aContext.createComponent( sServiceName ), UNO_QUERY );
1483                         replaceControl( xControl, xNewControl );
1484                     }
1485                 }
1486             }
1487         }
1488         m_bDetachEvents = sal_True;
1489     }
1490 }
1491 
1492 //------------------------------------------------------------------------------
IMPL_LINK(FormController,OnToggleAutoFields,void *,EMPTYARG)1493 IMPL_LINK(FormController, OnToggleAutoFields, void*, EMPTYARG)
1494 {
1495     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1496 
1497     toggleAutoFields(m_bCurrentRecordNew);
1498     return 1L;
1499 }
1500 
1501 // XTextListener
1502 //------------------------------------------------------------------------------
textChanged(const TextEvent & e)1503 void SAL_CALL FormController::textChanged(const TextEvent& e)
1504 {
1505     // SYNCHRONIZED -->
1506     ::osl::ClearableMutexGuard aGuard( m_aMutex );
1507     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1508     if ( !m_bFiltering )
1509     {
1510         impl_onModify();
1511         return;
1512     }
1513 
1514     if ( m_bSuspendFilterTextListening )
1515         return;
1516 
1517     Reference< XTextComponent >  xText(e.Source,UNO_QUERY);
1518     ::rtl::OUString aText = xText->getText();
1519 
1520     if ( m_aFilterRows.empty() )
1521         appendEmptyDisjunctiveTerm();
1522 
1523     // Suchen der aktuellen Row
1524     if ( ( (size_t)m_nCurrentFilterPosition >= m_aFilterRows.size() ) || ( m_nCurrentFilterPosition < 0 ) )
1525     {
1526         OSL_ENSURE( false, "FormController::textChanged: m_nCurrentFilterPosition is wrong!" );
1527         return;
1528     }
1529 
1530     FmFilterRow& rRow = m_aFilterRows[ m_nCurrentFilterPosition ];
1531 
1532     // do we have a new filter
1533     if (aText.getLength())
1534         rRow[xText] = aText;
1535     else
1536     {
1537         // do we have the control in the row
1538         FmFilterRow::iterator iter = rRow.find(xText);
1539         // erase the entry out of the row
1540         if (iter != rRow.end())
1541             rRow.erase(iter);
1542     }
1543 
1544     // multiplex the event to our FilterControllerListeners
1545     FilterEvent aEvent;
1546     aEvent.Source = *this;
1547     aEvent.FilterComponent = ::std::find( m_aFilterComponents.begin(), m_aFilterComponents.end(), xText ) - m_aFilterComponents.begin();
1548     aEvent.DisjunctiveTerm = getActiveTerm();
1549     aEvent.PredicateExpression = aText;
1550 
1551     aGuard.clear();
1552     // <-- SYNCHRONIZED
1553 
1554     // notify the changed filter expression
1555     m_aFilterListeners.notifyEach( &XFilterControllerListener::predicateExpressionChanged, aEvent );
1556 }
1557 
1558 // XItemListener
1559 //------------------------------------------------------------------------------
itemStateChanged(const ItemEvent &)1560 void SAL_CALL FormController::itemStateChanged(const ItemEvent& /*rEvent*/)
1561 {
1562     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1563     impl_onModify();
1564 }
1565 
1566 // XModificationBroadcaster
1567 //------------------------------------------------------------------------------
addModifyListener(const Reference<XModifyListener> & l)1568 void SAL_CALL FormController::addModifyListener(const Reference< XModifyListener > & l)
1569 {
1570     ::osl::MutexGuard aGuard( m_aMutex );
1571     impl_checkDisposed_throw();
1572     m_aModifyListeners.addInterface( l );
1573 }
1574 
1575 //------------------------------------------------------------------------------
removeModifyListener(const Reference<XModifyListener> & l)1576 void FormController::removeModifyListener(const Reference< XModifyListener > & l)
1577 {
1578     ::osl::MutexGuard aGuard( m_aMutex );
1579     impl_checkDisposed_throw();
1580     m_aModifyListeners.removeInterface( l );
1581 }
1582 
1583 // XModificationListener
1584 //------------------------------------------------------------------------------
modified(const EventObject & _rEvent)1585 void FormController::modified( const EventObject& _rEvent )
1586 {
1587     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1588 
1589     try
1590     {
1591         if ( _rEvent.Source != m_xActiveControl )
1592         {   // let this control grab the focus
1593             // (this case may happen if somebody moves the scroll wheel of the mouse over a control
1594             // which does not have the focus)
1595             // 85511 - 29.05.2001 - frank.schoenheit@germany.sun.com
1596             //
1597             // also, it happens when an image control gets a new image by double-clicking it
1598             // #i88458# / 2009-01-12 / frank.schoenheit@sun.com
1599             Reference< XWindow > xControlWindow( _rEvent.Source, UNO_QUERY_THROW );
1600             xControlWindow->setFocus();
1601         }
1602     }
1603     catch( const Exception& )
1604     {
1605         DBG_UNHANDLED_EXCEPTION();
1606     }
1607 
1608     impl_onModify();
1609 }
1610 
1611 //------------------------------------------------------------------------------
impl_checkDisposed_throw() const1612 void FormController::impl_checkDisposed_throw() const
1613 {
1614     if ( impl_isDisposed_nofail() )
1615         throw DisposedException( ::rtl::OUString(), *const_cast< FormController* >( this ) );
1616 }
1617 
1618 //------------------------------------------------------------------------------
impl_onModify()1619 void FormController::impl_onModify()
1620 {
1621     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1622 
1623     {
1624         ::osl::MutexGuard aGuard( m_aMutex );
1625         if ( !m_bModified )
1626             m_bModified = sal_True;
1627     }
1628 
1629     EventObject aEvt(static_cast<cppu::OWeakObject*>(this));
1630     m_aModifyListeners.notifyEach( &XModifyListener::modified, aEvt );
1631 }
1632 
1633 //------------------------------------------------------------------------------
impl_addFilterRow(const FmFilterRow & _row)1634 void FormController::impl_addFilterRow( const FmFilterRow& _row )
1635 {
1636     m_aFilterRows.push_back( _row );
1637 
1638     if ( m_aFilterRows.size() == 1 )
1639     {   // that's the first row ever
1640         OSL_ENSURE( m_nCurrentFilterPosition == -1, "FormController::impl_addFilterRow: inconsistency!" );
1641         m_nCurrentFilterPosition = 0;
1642     }
1643 }
1644 
1645 //------------------------------------------------------------------------------
impl_appendEmptyFilterRow(::osl::ClearableMutexGuard & _rClearBeforeNotify)1646 void FormController::impl_appendEmptyFilterRow( ::osl::ClearableMutexGuard& _rClearBeforeNotify )
1647 {
1648     // SYNCHRONIZED -->
1649     impl_addFilterRow( FmFilterRow() );
1650 
1651     // notify the listeners
1652     FilterEvent aEvent;
1653     aEvent.Source = *this;
1654     aEvent.DisjunctiveTerm = (sal_Int32)m_aFilterRows.size() - 1;
1655     _rClearBeforeNotify.clear();
1656     // <-- SYNCHRONIZED
1657     m_aFilterListeners.notifyEach( &XFilterControllerListener::disjunctiveTermAdded, aEvent );
1658 }
1659 
1660 //------------------------------------------------------------------------------
determineLockState() const1661 sal_Bool FormController::determineLockState() const
1662 {
1663     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1664     // a.) in filter mode we are always locked
1665     // b.) if we have no valid model or our model (a result set) is not alive -> we're locked
1666     // c.) if we are inserting everything is OK and we are not locked
1667     // d.) if are not updatable or on invalid position
1668     Reference< XResultSet >  xResultSet(m_xModelAsIndex, UNO_QUERY);
1669     if (m_bFiltering || !xResultSet.is() || !isRowSetAlive(xResultSet))
1670         return sal_True;
1671     else
1672         return (m_bCanInsert && m_bCurrentRecordNew) ? sal_False
1673         :  xResultSet->isBeforeFirst() || xResultSet->isAfterLast() || xResultSet->rowDeleted() || !m_bCanUpdate;
1674 }
1675 
1676 //  FocusListener
1677 //------------------------------------------------------------------------------
focusGained(const FocusEvent & e)1678 void FormController::focusGained(const FocusEvent& e)
1679 {
1680     // SYNCHRONIZED -->
1681     ::osl::ClearableMutexGuard aGuard( m_aMutex );
1682     impl_checkDisposed_throw();
1683 
1684     m_pControlBorderManager->focusGained( e.Source );
1685 
1686     Reference< XControl >  xControl(e.Source, UNO_QUERY);
1687     if (m_bDBConnection)
1688     {
1689         // do we need to keep the locking of the commit
1690         // we hold the lock as long as the control differs from the current
1691         // otherwise we disabled the lock
1692         m_bCommitLock = m_bCommitLock && (XControl*)xControl.get() != (XControl*)m_xCurrentControl.get();
1693         if (m_bCommitLock)
1694             return;
1695 
1696         // when do we have to commit a value to form or a filter
1697         // a.) if the current value is modified
1698         // b.) there must be a current control
1699         // c.) and it must be different from the new focus owning control or
1700         // d.) the focus is moving around (so we have only one control)
1701 
1702         if  (   ( m_bModified || m_bFiltering )
1703             &&  m_xCurrentControl.is()
1704             &&  (   ( xControl.get() != m_xCurrentControl.get() )
1705                 ||  (   ( e.FocusFlags & FocusChangeReason::AROUND )
1706                     &&  ( m_bCycle || m_bFiltering )
1707                     )
1708                 )
1709             )
1710         {
1711             // check the old control if the content is ok
1712 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
1713             Reference< XBoundControl >  xLockingTest(m_xCurrentControl, UNO_QUERY);
1714             sal_Bool bControlIsLocked = xLockingTest.is() && xLockingTest->getLock();
1715             OSL_ENSURE(!bControlIsLocked, "FormController::Gained: I'm modified and the current control is locked ? How this ?");
1716             // normalerweise sollte ein gelocktes Control nicht modified sein, also muss wohl mein bModified aus einem anderen Kontext
1717             // gesetzt worden sein, was ich nicht verstehen wuerde ...
1718 #endif
1719             DBG_ASSERT(m_xCurrentControl.is(), "kein CurrentControl gesetzt");
1720             // zunaechst das Control fragen ob es das IFace unterstuetzt
1721             Reference< XBoundComponent >  xBound(m_xCurrentControl, UNO_QUERY);
1722             if (!xBound.is() && m_xCurrentControl.is())
1723                 xBound  = Reference< XBoundComponent > (m_xCurrentControl->getModel(), UNO_QUERY);
1724 
1725             // lock if we lose the focus during commit
1726             m_bCommitLock = sal_True;
1727 
1728             // Commit nicht erfolgreich, Focus zuruecksetzen
1729             if (xBound.is() && !xBound->commit())
1730             {
1731                 // the commit failed and we don't commit again until the current control
1732                 // which couldn't be commit gains the focus again
1733                 Reference< XWindow >  xWindow(m_xCurrentControl, UNO_QUERY);
1734                 if (xWindow.is())
1735                     xWindow->setFocus();
1736                 return;
1737             }
1738             else
1739             {
1740                 m_bModified = sal_False;
1741                 m_bCommitLock = sal_False;
1742             }
1743         }
1744 
1745         if (!m_bFiltering && m_bCycle && (e.FocusFlags & FocusChangeReason::AROUND) && m_xCurrentControl.is())
1746         {
1747             SQLErrorEvent aErrorEvent;
1748             OSL_ENSURE( m_xFormOperations.is(), "FormController::focusGained: hmm?" );
1749                 // should have been created in setModel
1750             try
1751             {
1752                 if ( e.FocusFlags & FocusChangeReason::FORWARD )
1753                 {
1754                     if ( m_xFormOperations.is() && m_xFormOperations->isEnabled( FormFeature::MoveToNext ) )
1755                         m_xFormOperations->execute( FormFeature::MoveToNext );
1756                 }
1757                 else // backward
1758                 {
1759                     if ( m_xFormOperations.is() && m_xFormOperations->isEnabled( FormFeature::MoveToPrevious ) )
1760                         m_xFormOperations->execute( FormFeature::MoveToPrevious );
1761                 }
1762             }
1763             catch ( const Exception& )
1764             {
1765                 // don't handle this any further. That's an ... admissible error.
1766                 DBG_UNHANDLED_EXCEPTION();
1767             }
1768         }
1769     }
1770 
1771     // Immer noch ein und dasselbe Control
1772     if  (   ( m_xActiveControl == xControl )
1773         &&  ( xControl == m_xCurrentControl )
1774         )
1775     {
1776         DBG_ASSERT(m_xCurrentControl.is(), "Kein CurrentControl selektiert");
1777         return;
1778     }
1779 
1780     sal_Bool bActivated = !m_xActiveControl.is() && xControl.is();
1781 
1782     m_xActiveControl  = xControl;
1783 
1784     implSetCurrentControl( xControl );
1785     OSL_POSTCOND( m_xCurrentControl.is(), "implSetCurrentControl did nonsense!" );
1786 
1787     if ( bActivated )
1788     {
1789         // (asynchronously) call activation handlers
1790         m_aActivationEvent.Call();
1791 
1792         // call modify listeners
1793         if ( m_bModified )
1794             m_aModifyListeners.notifyEach( &XModifyListener::modified, EventObject( *this ) );
1795     }
1796 
1797     // invalidate all features which depend on the currently focused control
1798     if ( m_bDBConnection && !m_bFiltering )
1799         implInvalidateCurrentControlDependentFeatures();
1800 
1801     if ( !m_xCurrentControl.is() )
1802         return;
1803 
1804     // Control erhaelt Focus, dann eventuell in den sichtbaren Bereich
1805     Reference< XFormControllerContext > xContext( m_xContext );
1806     Reference< XControl > xCurrentControl( m_xCurrentControl );
1807     aGuard.clear();
1808     // <-- SYNCHRONIZED
1809 
1810     if ( xContext.is() )
1811         xContext->makeVisible( xCurrentControl );
1812 }
1813 
1814 //------------------------------------------------------------------------------
1815 IMPL_LINK( FormController, OnActivated, void*, /**/ )
1816 {
1817     EventObject aEvent;
1818     aEvent.Source = *this;
1819     m_aActivateListeners.notifyEach( &XFormControllerListener::formActivated, aEvent );
1820 
1821     return 0L;
1822 }
1823 
1824 //------------------------------------------------------------------------------
1825 IMPL_LINK( FormController, OnDeactivated, void*, /**/ )
1826 {
1827     EventObject aEvent;
1828     aEvent.Source = *this;
1829     m_aActivateListeners.notifyEach( &XFormControllerListener::formDeactivated, aEvent );
1830 
1831     return 0L;
1832 }
1833 
1834 //------------------------------------------------------------------------------
focusLost(const FocusEvent & e)1835 void FormController::focusLost(const FocusEvent& e)
1836 {
1837     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
1838 
1839     m_pControlBorderManager->focusLost( e.Source );
1840 
1841     Reference< XControl >  xControl(e.Source, UNO_QUERY);
1842     Reference< XWindowPeer >  xNext(e.NextFocus, UNO_QUERY);
1843     Reference< XControl >  xNextControl = isInList(xNext);
1844     if (!xNextControl.is())
1845     {
1846         m_xActiveControl = NULL;
1847         m_aDeactivationEvent.Call();
1848     }
1849 }
1850 
1851 //--------------------------------------------------------------------
mousePressed(const awt::MouseEvent &)1852 void SAL_CALL FormController::mousePressed( const awt::MouseEvent& /*_rEvent*/ )
1853 {
1854     // not interested in
1855 }
1856 
1857 //--------------------------------------------------------------------
mouseReleased(const awt::MouseEvent &)1858 void SAL_CALL FormController::mouseReleased( const awt::MouseEvent& /*_rEvent*/ )
1859 {
1860     // not interested in
1861 }
1862 
1863 //--------------------------------------------------------------------
mouseEntered(const awt::MouseEvent & _rEvent)1864 void SAL_CALL FormController::mouseEntered( const awt::MouseEvent& _rEvent )
1865 {
1866     m_pControlBorderManager->mouseEntered( _rEvent.Source );
1867 }
1868 
1869 //--------------------------------------------------------------------
mouseExited(const awt::MouseEvent & _rEvent)1870 void SAL_CALL FormController::mouseExited( const awt::MouseEvent& _rEvent )
1871 {
1872     m_pControlBorderManager->mouseExited( _rEvent.Source );
1873 }
1874 
1875 //--------------------------------------------------------------------
componentValidityChanged(const EventObject & _rSource)1876 void SAL_CALL FormController::componentValidityChanged( const EventObject& _rSource )
1877 {
1878     Reference< XControl > xControl( findControl( m_aControls, Reference< XControlModel >( _rSource.Source, UNO_QUERY ), sal_False, sal_False ) );
1879     Reference< XValidatableFormComponent > xValidatable( _rSource.Source, UNO_QUERY );
1880 
1881     OSL_ENSURE( xControl.is() && xValidatable.is(), "FormController::componentValidityChanged: huh?" );
1882 
1883     if ( xControl.is() && xValidatable.is() )
1884         m_pControlBorderManager->validityChanged( xControl, xValidatable );
1885 }
1886 
1887 //--------------------------------------------------------------------
setModel(const Reference<XTabControllerModel> & Model)1888 void FormController::setModel(const Reference< XTabControllerModel > & Model)
1889 {
1890     ::osl::MutexGuard aGuard( m_aMutex );
1891     impl_checkDisposed_throw();
1892 
1893     DBG_ASSERT(m_xTabController.is(), "FormController::setModel : invalid aggregate !");
1894 
1895     try
1896     {
1897         // disconnect from the old model
1898         if (m_xModelAsIndex.is())
1899         {
1900             if (m_bDBConnection)
1901             {
1902                 // we are currently working on the model
1903                 EventObject aEvt(m_xModelAsIndex);
1904                 unloaded(aEvt);
1905             }
1906 
1907             Reference< XLoadable >  xForm(m_xModelAsIndex, UNO_QUERY);
1908             if (xForm.is())
1909                 xForm->removeLoadListener(this);
1910 
1911             Reference< XSQLErrorBroadcaster >  xBroadcaster(m_xModelAsIndex, UNO_QUERY);
1912             if (xBroadcaster.is())
1913                 xBroadcaster->removeSQLErrorListener(this);
1914 
1915             Reference< XDatabaseParameterBroadcaster >  xParamBroadcaster(m_xModelAsIndex, UNO_QUERY);
1916             if (xParamBroadcaster.is())
1917                 xParamBroadcaster->removeParameterListener(this);
1918 
1919         }
1920 
1921         disposeAllFeaturesAndDispatchers();
1922 
1923         if ( m_xFormOperations.is() )
1924             m_xFormOperations->dispose();
1925         m_xFormOperations.clear();
1926 
1927         // set the new model wait for the load event
1928         if (m_xTabController.is())
1929             m_xTabController->setModel(Model);
1930         m_xModelAsIndex = Reference< XIndexAccess > (Model, UNO_QUERY);
1931         m_xModelAsManager = Reference< XEventAttacherManager > (Model, UNO_QUERY);
1932 
1933         // only if both ifaces exit, the controller will work successful
1934         if (!m_xModelAsIndex.is() || !m_xModelAsManager.is())
1935         {
1936             m_xModelAsManager = NULL;
1937             m_xModelAsIndex = NULL;
1938         }
1939 
1940         if (m_xModelAsIndex.is())
1941         {
1942             // re-create m_xFormOperations
1943             m_xFormOperations.set( FormOperations::createWithFormController( m_aContext.getUNOContext(), this ), UNO_SET_THROW );
1944             m_xFormOperations->setFeatureInvalidation( this );
1945 
1946             // adding load and ui interaction listeners
1947             Reference< XLoadable >  xForm(Model, UNO_QUERY);
1948             if (xForm.is())
1949                 xForm->addLoadListener(this);
1950 
1951             Reference< XSQLErrorBroadcaster >  xBroadcaster(Model, UNO_QUERY);
1952             if (xBroadcaster.is())
1953                 xBroadcaster->addSQLErrorListener(this);
1954 
1955             Reference< XDatabaseParameterBroadcaster >  xParamBroadcaster(Model, UNO_QUERY);
1956             if (xParamBroadcaster.is())
1957                 xParamBroadcaster->addParameterListener(this);
1958 
1959             // well, is the database already loaded?
1960             // then we have to simulate a load event
1961             Reference< XLoadable >  xCursor(m_xModelAsIndex, UNO_QUERY);
1962             if (xCursor.is() && xCursor->isLoaded())
1963             {
1964                 EventObject aEvt(xCursor);
1965                 loaded(aEvt);
1966             }
1967 
1968             Reference< XPropertySet > xModelProps( m_xModelAsIndex, UNO_QUERY );
1969             Reference< XPropertySetInfo > xPropInfo( xModelProps->getPropertySetInfo() );
1970             if (  xPropInfo.is()
1971                && xPropInfo->hasPropertyByName( FM_PROP_DYNAMIC_CONTROL_BORDER )
1972                && xPropInfo->hasPropertyByName( FM_PROP_CONTROL_BORDER_COLOR_FOCUS )
1973                && xPropInfo->hasPropertyByName( FM_PROP_CONTROL_BORDER_COLOR_MOUSE )
1974                && xPropInfo->hasPropertyByName( FM_PROP_CONTROL_BORDER_COLOR_INVALID )
1975                )
1976             {
1977                 bool bEnableDynamicControlBorder = lcl_shouldUseDynamicControlBorder(
1978                     xModelProps.get(), xModelProps->getPropertyValue( FM_PROP_DYNAMIC_CONTROL_BORDER ) );
1979                 if ( bEnableDynamicControlBorder )
1980                     m_pControlBorderManager->enableDynamicBorderColor();
1981                 else
1982                     m_pControlBorderManager->disableDynamicBorderColor();
1983 
1984                 sal_Int32 nColor = 0;
1985                 if ( xModelProps->getPropertyValue( FM_PROP_CONTROL_BORDER_COLOR_FOCUS ) >>= nColor )
1986                     m_pControlBorderManager->setStatusColor( CONTROL_STATUS_FOCUSED, nColor );
1987                 if ( xModelProps->getPropertyValue( FM_PROP_CONTROL_BORDER_COLOR_MOUSE ) >>= nColor )
1988                     m_pControlBorderManager->setStatusColor( CONTROL_STATUS_MOUSE_HOVER, nColor );
1989                 if ( xModelProps->getPropertyValue( FM_PROP_CONTROL_BORDER_COLOR_INVALID ) >>= nColor )
1990                     m_pControlBorderManager->setStatusColor( CONTROL_STATUS_INVALID, nColor );
1991             }
1992         }
1993     }
1994     catch( const Exception& )
1995     {
1996         DBG_UNHANDLED_EXCEPTION();
1997     }
1998 }
1999 
2000 //------------------------------------------------------------------------------
getModel()2001 Reference< XTabControllerModel >  FormController::getModel()
2002 {
2003     ::osl::MutexGuard aGuard( m_aMutex );
2004     impl_checkDisposed_throw();
2005 
2006     DBG_ASSERT(m_xTabController.is(), "FormController::getModel : invalid aggregate !");
2007     if (!m_xTabController.is())
2008         return Reference< XTabControllerModel > ();
2009     return m_xTabController->getModel();
2010 }
2011 
2012 //------------------------------------------------------------------------------
addToEventAttacher(const Reference<XControl> & xControl)2013 void FormController::addToEventAttacher(const Reference< XControl > & xControl)
2014 {
2015     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2016     OSL_ENSURE( xControl.is(), "FormController::addToEventAttacher: invalid control - how did you reach this?" );
2017     if ( !xControl.is() )
2018         return; /* throw IllegalArgumentException(); */
2019 
2020     // anmelden beim Eventattacher
2021     Reference< XFormComponent >  xComp(xControl->getModel(), UNO_QUERY);
2022     if (xComp.is() && m_xModelAsIndex.is())
2023     {
2024         // Und die Position des ControlModel darin suchen
2025         sal_uInt32 nPos = m_xModelAsIndex->getCount();
2026         Reference< XFormComponent > xTemp;
2027         for( ; nPos; )
2028         {
2029             m_xModelAsIndex->getByIndex(--nPos) >>= xTemp;
2030             if ((XFormComponent*)xComp.get() == (XFormComponent*)xTemp.get())
2031             {
2032                 Reference< XInterface >  xIfc(xControl, UNO_QUERY);
2033                 m_xModelAsManager->attach( nPos, xIfc, makeAny(xControl) );
2034                 break;
2035             }
2036         }
2037     }
2038 }
2039 
2040 //------------------------------------------------------------------------------
removeFromEventAttacher(const Reference<XControl> & xControl)2041 void FormController::removeFromEventAttacher(const Reference< XControl > & xControl)
2042 {
2043     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2044     OSL_ENSURE( xControl.is(), "FormController::removeFromEventAttacher: invalid control - how did you reach this?" );
2045     if ( !xControl.is() )
2046         return; /* throw IllegalArgumentException(); */
2047 
2048     // abmelden beim Eventattacher
2049     Reference< XFormComponent >  xComp(xControl->getModel(), UNO_QUERY);
2050     if ( xComp.is() && m_xModelAsIndex.is() )
2051     {
2052         // Und die Position des ControlModel darin suchen
2053         sal_uInt32 nPos = m_xModelAsIndex->getCount();
2054         Reference< XFormComponent > xTemp;
2055         for( ; nPos; )
2056         {
2057             m_xModelAsIndex->getByIndex(--nPos) >>= xTemp;
2058             if ((XFormComponent*)xComp.get() == (XFormComponent*)xTemp.get())
2059             {
2060                 Reference< XInterface >  xIfc(xControl, UNO_QUERY);
2061                 m_xModelAsManager->detach( nPos, xIfc );
2062                 break;
2063             }
2064         }
2065     }
2066 }
2067 
2068 //------------------------------------------------------------------------------
setContainer(const Reference<XControlContainer> & xContainer)2069 void FormController::setContainer(const Reference< XControlContainer > & xContainer)
2070 {
2071     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2072     Reference< XTabControllerModel >  xTabModel(getModel());
2073     DBG_ASSERT(xTabModel.is() || !xContainer.is(), "No Model defined");
2074         // if we have a new container we need a model
2075     DBG_ASSERT(m_xTabController.is(), "FormController::setContainer : invalid aggregate !");
2076 
2077     ::osl::MutexGuard aGuard( m_aMutex );
2078     Reference< XContainer >  xCurrentContainer;
2079     if (m_xTabController.is())
2080         xCurrentContainer = Reference< XContainer > (m_xTabController->getContainer(), UNO_QUERY);
2081     if (xCurrentContainer.is())
2082     {
2083         xCurrentContainer->removeContainerListener(this);
2084 
2085         if ( m_aTabActivationTimer.IsActive() )
2086             m_aTabActivationTimer.Stop();
2087 
2088         // clear the filter map
2089         ::std::for_each( m_aFilterComponents.begin(), m_aFilterComponents.end(), RemoveComponentTextListener( this ) );
2090         m_aFilterComponents.clear();
2091 
2092         // einsammeln der Controls
2093         const Reference< XControl >* pControls = m_aControls.getConstArray();
2094         const Reference< XControl >* pControlsEnd = pControls + m_aControls.getLength();
2095         while ( pControls != pControlsEnd )
2096             implControlRemoved( *pControls++, true );
2097 
2098         // Datenbank spezifische Dinge vornehmen
2099         if (m_bDBConnection && isListeningForChanges())
2100             stopListening();
2101 
2102         m_aControls.realloc( 0 );
2103     }
2104 
2105     if (m_xTabController.is())
2106         m_xTabController->setContainer(xContainer);
2107 
2108     // Welche Controls gehoeren zum Container ?
2109     if (xContainer.is() && xTabModel.is())
2110     {
2111         Sequence< Reference< XControlModel > > aModels = xTabModel->getControlModels();
2112         const Reference< XControlModel > * pModels = aModels.getConstArray();
2113         Sequence< Reference< XControl > > aAllControls = xContainer->getControls();
2114 
2115         sal_Int32 nCount = aModels.getLength();
2116         m_aControls = Sequence< Reference< XControl > >( nCount );
2117         Reference< XControl > * pControls = m_aControls.getArray();
2118 
2119         // einsammeln der Controls
2120         sal_Int32 i, j;
2121         for (i = 0, j = 0; i < nCount; ++i, ++pModels )
2122         {
2123             Reference< XControl > xControl = findControl( aAllControls, *pModels, sal_False, sal_True );
2124             if ( xControl.is() )
2125             {
2126                 pControls[j++] = xControl;
2127                 implControlInserted( xControl, true );
2128             }
2129         }
2130 
2131         // not every model had an associated control
2132         if (j != i)
2133             m_aControls.realloc(j);
2134 
2135         // am Container horchen
2136         Reference< XContainer >  xNewContainer(xContainer, UNO_QUERY);
2137         if (xNewContainer.is())
2138             xNewContainer->addContainerListener(this);
2139 
2140         // Datenbank spezifische Dinge vornehmen
2141         if (m_bDBConnection)
2142         {
2143             m_bLocked = determineLockState();
2144             setLocks();
2145             if (!isLocked())
2146                 startListening();
2147         }
2148     }
2149     // befinden sich die Controls in der richtigen Reihenfolge
2150     m_bControlsSorted = sal_True;
2151 }
2152 
2153 //------------------------------------------------------------------------------
getContainer()2154 Reference< XControlContainer >  FormController::getContainer()
2155 {
2156     ::osl::MutexGuard aGuard( m_aMutex );
2157     impl_checkDisposed_throw();
2158 
2159     DBG_ASSERT(m_xTabController.is(), "FormController::getContainer : invalid aggregate !");
2160     if (!m_xTabController.is())
2161         return Reference< XControlContainer > ();
2162     return m_xTabController->getContainer();
2163 }
2164 
2165 //------------------------------------------------------------------------------
getControls(void)2166 Sequence< Reference< XControl > > FormController::getControls(void)
2167 {
2168     ::osl::MutexGuard aGuard( m_aMutex );
2169     impl_checkDisposed_throw();
2170 
2171     if (!m_bControlsSorted)
2172     {
2173         Reference< XTabControllerModel >  xModel = getModel();
2174         if (!xModel.is())
2175             return m_aControls;
2176 
2177         Sequence< Reference< XControlModel > > aControlModels = xModel->getControlModels();
2178         const Reference< XControlModel > * pModels = aControlModels.getConstArray();
2179         sal_Int32 nModels = aControlModels.getLength();
2180 
2181         Sequence< Reference< XControl > > aNewControls(nModels);
2182 
2183         Reference< XControl > * pControls = aNewControls.getArray();
2184         Reference< XControl >  xControl;
2185 
2186         // Umsortieren der Controls entsprechend der TabReihenfolge
2187         sal_Int32 j = 0;
2188         for (sal_Int32 i = 0; i < nModels; ++i, ++pModels )
2189         {
2190             xControl = findControl( m_aControls, *pModels, sal_True, sal_True );
2191             if ( xControl.is() )
2192                 pControls[j++] = xControl;
2193         }
2194 
2195         // not every model had an associated control
2196         if ( j != nModels )
2197             aNewControls.realloc( j );
2198 
2199         m_aControls = aNewControls;
2200         m_bControlsSorted = sal_True;
2201     }
2202     return m_aControls;
2203 }
2204 
2205 //------------------------------------------------------------------------------
autoTabOrder()2206 void FormController::autoTabOrder()
2207 {
2208     ::osl::MutexGuard aGuard( m_aMutex );
2209     impl_checkDisposed_throw();
2210 
2211     DBG_ASSERT(m_xTabController.is(), "FormController::autoTabOrder : invalid aggregate !");
2212     if (m_xTabController.is())
2213         m_xTabController->autoTabOrder();
2214 }
2215 
2216 //------------------------------------------------------------------------------
activateTabOrder()2217 void FormController::activateTabOrder()
2218 {
2219     ::osl::MutexGuard aGuard( m_aMutex );
2220     impl_checkDisposed_throw();
2221 
2222     DBG_ASSERT(m_xTabController.is(), "FormController::activateTabOrder : invalid aggregate !");
2223     if (m_xTabController.is())
2224         m_xTabController->activateTabOrder();
2225 }
2226 
2227 //------------------------------------------------------------------------------
setControlLock(const Reference<XControl> & xControl)2228 void FormController::setControlLock(const Reference< XControl > & xControl)
2229 {
2230     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2231     sal_Bool bLocked = isLocked();
2232 
2233     // es wird gelockt
2234     // a.) wenn der ganze Datensatz gesperrt ist
2235     // b.) wenn das zugehoerige Feld gespeert ist
2236     Reference< XBoundControl >  xBound(xControl, UNO_QUERY);
2237     if (xBound.is() && (( (bLocked && bLocked != xBound->getLock()) ||
2238                          !bLocked)))    // beim entlocken immer einzelne Felder ueberpr�fen
2239     {
2240         // gibt es eine Datenquelle
2241         Reference< XPropertySet >  xSet(xControl->getModel(), UNO_QUERY);
2242         if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
2243         {
2244             // wie sieht mit den Properties ReadOnly und Enable aus
2245             sal_Bool bTouch = sal_True;
2246             if (::comphelper::hasProperty(FM_PROP_ENABLED, xSet))
2247                 bTouch = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ENABLED));
2248             if (::comphelper::hasProperty(FM_PROP_READONLY, xSet))
2249                 bTouch = !::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_READONLY));
2250 
2251             if (bTouch)
2252             {
2253                 Reference< XPropertySet >  xField;
2254                 xSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
2255                 if (xField.is())
2256                 {
2257                     if (bLocked)
2258                         xBound->setLock(bLocked);
2259                     else
2260                     {
2261                         try
2262                         {
2263                             Any aVal = xField->getPropertyValue(FM_PROP_ISREADONLY);
2264                             if (aVal.hasValue() && ::comphelper::getBOOL(aVal))
2265                                 xBound->setLock(sal_True);
2266                             else
2267                                 xBound->setLock(bLocked);
2268                         }
2269                         catch( const Exception& )
2270                         {
2271                             DBG_UNHANDLED_EXCEPTION();
2272                         }
2273 
2274                     }
2275                 }
2276             }
2277         }
2278     }
2279 }
2280 
2281 //------------------------------------------------------------------------------
setLocks()2282 void FormController::setLocks()
2283 {
2284     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2285     // alle Controls, die mit einer Datenquelle verbunden sind locken/unlocken
2286     const Reference< XControl >* pControls = m_aControls.getConstArray();
2287     const Reference< XControl >* pControlsEnd = pControls + m_aControls.getLength();
2288     while ( pControls != pControlsEnd )
2289         setControlLock( *pControls++ );
2290 }
2291 
2292 //------------------------------------------------------------------------------
2293 namespace
2294 {
lcl_shouldListenForModifications(const Reference<XControl> & _rxControl,const Reference<XPropertyChangeListener> & _rxBoundFieldListener)2295     bool lcl_shouldListenForModifications( const Reference< XControl >& _rxControl, const Reference< XPropertyChangeListener >& _rxBoundFieldListener )
2296     {
2297         bool bShould = false;
2298 
2299         Reference< XBoundComponent > xBound( _rxControl, UNO_QUERY );
2300         if ( xBound.is() )
2301         {
2302             bShould = true;
2303         }
2304         else if ( _rxControl.is() )
2305         {
2306             Reference< XPropertySet > xModelProps( _rxControl->getModel(), UNO_QUERY );
2307             if ( xModelProps.is() && ::comphelper::hasProperty( FM_PROP_BOUNDFIELD, xModelProps ) )
2308             {
2309                 Reference< XPropertySet > xField;
2310                 xModelProps->getPropertyValue( FM_PROP_BOUNDFIELD ) >>= xField;
2311                 bShould = xField.is();
2312 
2313                 if ( !bShould && _rxBoundFieldListener.is() )
2314                     xModelProps->addPropertyChangeListener( FM_PROP_BOUNDFIELD, _rxBoundFieldListener );
2315             }
2316         }
2317 
2318         return bShould;
2319     }
2320 }
2321 
2322 //------------------------------------------------------------------------------
startControlModifyListening(const Reference<XControl> & xControl)2323 void FormController::startControlModifyListening(const Reference< XControl > & xControl)
2324 {
2325     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2326 
2327     bool bModifyListening = lcl_shouldListenForModifications( xControl, this );
2328 
2329     // artificial while
2330     while ( bModifyListening )
2331     {
2332         Reference< XModifyBroadcaster >  xMod(xControl, UNO_QUERY);
2333         if (xMod.is())
2334         {
2335             xMod->addModifyListener(this);
2336             break;
2337         }
2338 
2339         // alle die Text um vorzeitig ein modified zu erkennen
2340         Reference< XTextComponent >  xText(xControl, UNO_QUERY);
2341         if (xText.is())
2342         {
2343             xText->addTextListener(this);
2344             break;
2345         }
2346 
2347         Reference< XCheckBox >  xBox(xControl, UNO_QUERY);
2348         if (xBox.is())
2349         {
2350             xBox->addItemListener(this);
2351             break;
2352         }
2353 
2354         Reference< XComboBox >  xCbBox(xControl, UNO_QUERY);
2355         if (xCbBox.is())
2356         {
2357             xCbBox->addItemListener(this);
2358             break;
2359         }
2360 
2361         Reference< XListBox >  xListBox(xControl, UNO_QUERY);
2362         if (xListBox.is())
2363         {
2364             xListBox->addItemListener(this);
2365             break;
2366         }
2367         break;
2368     }
2369 }
2370 
2371 //------------------------------------------------------------------------------
stopControlModifyListening(const Reference<XControl> & xControl)2372 void FormController::stopControlModifyListening(const Reference< XControl > & xControl)
2373 {
2374     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2375 
2376     bool bModifyListening = lcl_shouldListenForModifications( xControl, NULL );
2377 
2378     // kuenstliches while
2379     while (bModifyListening)
2380     {
2381         Reference< XModifyBroadcaster >  xMod(xControl, UNO_QUERY);
2382         if (xMod.is())
2383         {
2384             xMod->removeModifyListener(this);
2385             break;
2386         }
2387         // alle die Text um vorzeitig ein modified zu erkennen
2388         Reference< XTextComponent >  xText(xControl, UNO_QUERY);
2389         if (xText.is())
2390         {
2391             xText->removeTextListener(this);
2392             break;
2393         }
2394 
2395         Reference< XCheckBox >  xBox(xControl, UNO_QUERY);
2396         if (xBox.is())
2397         {
2398             xBox->removeItemListener(this);
2399             break;
2400         }
2401 
2402         Reference< XComboBox >  xCbBox(xControl, UNO_QUERY);
2403         if (xCbBox.is())
2404         {
2405             xCbBox->removeItemListener(this);
2406             break;
2407         }
2408 
2409         Reference< XListBox >  xListBox(xControl, UNO_QUERY);
2410         if (xListBox.is())
2411         {
2412             xListBox->removeItemListener(this);
2413             break;
2414         }
2415         break;
2416     }
2417 }
2418 
2419 //------------------------------------------------------------------------------
startListening()2420 void FormController::startListening()
2421 {
2422     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2423     m_bModified  = sal_False;
2424 
2425     // jetzt anmelden bei gebundenen feldern
2426     const Reference< XControl >* pControls = m_aControls.getConstArray();
2427     const Reference< XControl >* pControlsEnd = pControls + m_aControls.getLength();
2428     while ( pControls != pControlsEnd )
2429         startControlModifyListening( *pControls++ );
2430 }
2431 
2432 //------------------------------------------------------------------------------
stopListening()2433 void FormController::stopListening()
2434 {
2435     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2436     m_bModified  = sal_False;
2437 
2438     // jetzt anmelden bei gebundenen feldern
2439     const Reference< XControl >* pControls = m_aControls.getConstArray();
2440     const Reference< XControl >* pControlsEnd = pControls + m_aControls.getLength();
2441     while ( pControls != pControlsEnd )
2442         stopControlModifyListening( *pControls++ );
2443 }
2444 
2445 
2446 //------------------------------------------------------------------------------
findControl(Sequence<Reference<XControl>> & _rControls,const Reference<XControlModel> & xCtrlModel,sal_Bool _bRemove,sal_Bool _bOverWrite) const2447 Reference< XControl >  FormController::findControl(Sequence< Reference< XControl > >& _rControls, const Reference< XControlModel > & xCtrlModel ,sal_Bool _bRemove,sal_Bool _bOverWrite) const
2448 {
2449     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2450     DBG_ASSERT( xCtrlModel.is(), "findControl - welches ?!" );
2451 
2452     Reference< XControl >* pControls = _rControls.getArray();
2453     Reference< XControlModel >  xModel;
2454     for ( sal_Int32 i = 0, nCount = _rControls.getLength(); i < nCount; ++i, ++pControls )
2455     {
2456         if ( pControls->is() )
2457         {
2458             xModel = (*pControls)->getModel();
2459             if ( xModel.get() == xCtrlModel.get() )
2460             {
2461                 Reference< XControl > xControl( *pControls );
2462                 if ( _bRemove )
2463                     ::comphelper::removeElementAt( _rControls, i );
2464                 else if ( _bOverWrite )
2465                     *pControls = Reference< XControl >();
2466                 return xControl;
2467             }
2468         }
2469     }
2470     return Reference< XControl > ();
2471 }
2472 
2473 //------------------------------------------------------------------------------
implControlInserted(const Reference<XControl> & _rxControl,bool _bAddToEventAttacher)2474 void FormController::implControlInserted( const Reference< XControl>& _rxControl, bool _bAddToEventAttacher )
2475 {
2476     Reference< XWindow > xWindow( _rxControl, UNO_QUERY );
2477     if ( xWindow.is() )
2478     {
2479         xWindow->addFocusListener( this );
2480         xWindow->addMouseListener( this );
2481 
2482         if ( _bAddToEventAttacher )
2483             addToEventAttacher( _rxControl );
2484     }
2485 
2486     // add a dispatch interceptor to the control (if supported)
2487     Reference< XDispatchProviderInterception > xInterception( _rxControl, UNO_QUERY );
2488     if ( xInterception.is() )
2489         createInterceptor( xInterception );
2490 
2491     if ( _rxControl.is() )
2492     {
2493         Reference< XControlModel > xModel( _rxControl->getModel() );
2494 
2495         // we want to know about the reset of the model of our controls
2496         // (for correctly resetting m_bModified)
2497         Reference< XReset >  xReset( xModel, UNO_QUERY );
2498         if ( xReset.is() )
2499             xReset->addResetListener( this );
2500 
2501         // and we want to know about the validity, to visually indicate it
2502         Reference< XValidatableFormComponent > xValidatable( xModel, UNO_QUERY );
2503         if ( xValidatable.is() )
2504         {
2505             xValidatable->addFormComponentValidityListener( this );
2506             m_pControlBorderManager->validityChanged( _rxControl, xValidatable );
2507         }
2508     }
2509 
2510 }
2511 
2512 //------------------------------------------------------------------------------
implControlRemoved(const Reference<XControl> & _rxControl,bool _bRemoveFromEventAttacher)2513 void FormController::implControlRemoved( const Reference< XControl>& _rxControl, bool _bRemoveFromEventAttacher )
2514 {
2515     Reference< XWindow > xWindow( _rxControl, UNO_QUERY );
2516     if ( xWindow.is() )
2517     {
2518         xWindow->removeFocusListener( this );
2519         xWindow->removeMouseListener( this );
2520 
2521         if ( _bRemoveFromEventAttacher )
2522             removeFromEventAttacher( _rxControl );
2523     }
2524 
2525     Reference< XDispatchProviderInterception > xInterception( _rxControl, UNO_QUERY);
2526     if ( xInterception.is() )
2527         deleteInterceptor( xInterception );
2528 
2529     if ( _rxControl.is() )
2530     {
2531         Reference< XControlModel > xModel( _rxControl->getModel() );
2532 
2533         Reference< XReset >  xReset( xModel, UNO_QUERY );
2534         if ( xReset.is() )
2535             xReset->removeResetListener( this );
2536 
2537         Reference< XValidatableFormComponent > xValidatable( xModel, UNO_QUERY );
2538         if ( xValidatable.is() )
2539             xValidatable->removeFormComponentValidityListener( this );
2540     }
2541 }
2542 
2543 //------------------------------------------------------------------------------
implSetCurrentControl(const Reference<XControl> & _rxControl)2544 void FormController::implSetCurrentControl( const Reference< XControl >& _rxControl )
2545 {
2546     if ( m_xCurrentControl.get() == _rxControl.get() )
2547         return;
2548 
2549     Reference< XGridControl > xGridControl( m_xCurrentControl, UNO_QUERY );
2550     if ( xGridControl.is() )
2551         xGridControl->removeGridControlListener( this );
2552 
2553     m_xCurrentControl = _rxControl;
2554 
2555     xGridControl.set( m_xCurrentControl, UNO_QUERY );
2556     if ( xGridControl.is() )
2557         xGridControl->addGridControlListener( this );
2558 }
2559 
2560 //------------------------------------------------------------------------------
insertControl(const Reference<XControl> & xControl)2561 void FormController::insertControl(const Reference< XControl > & xControl)
2562 {
2563     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2564     m_bControlsSorted = sal_False;
2565     m_aControls.realloc(m_aControls.getLength() + 1);
2566     m_aControls.getArray()[m_aControls.getLength() - 1] = xControl;
2567 
2568     if ( m_pColumnInfoCache.get() )
2569         m_pColumnInfoCache->deinitializeControls();
2570 
2571     implControlInserted( xControl, m_bAttachEvents );
2572 
2573     if (m_bDBConnection && !m_bFiltering)
2574         setControlLock(xControl);
2575 
2576     if (isListeningForChanges() && m_bAttachEvents)
2577         startControlModifyListening( xControl );
2578 }
2579 
2580 //------------------------------------------------------------------------------
removeControl(const Reference<XControl> & xControl)2581 void FormController::removeControl(const Reference< XControl > & xControl)
2582 {
2583     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2584     const Reference< XControl >* pControls = m_aControls.getConstArray();
2585     const Reference< XControl >* pControlsEnd = pControls + m_aControls.getLength();
2586     while ( pControls != pControlsEnd )
2587     {
2588         if ( xControl.get() == (*pControls++).get() )
2589         {
2590             ::comphelper::removeElementAt( m_aControls, pControls - m_aControls.getConstArray() - 1 );
2591             break;
2592         }
2593     }
2594 
2595     FilterComponents::iterator componentPos = ::std::find( m_aFilterComponents.begin(), m_aFilterComponents.end(), xControl );
2596     if ( componentPos != m_aFilterComponents.end() )
2597         m_aFilterComponents.erase( componentPos );
2598 
2599     implControlRemoved( xControl, m_bDetachEvents );
2600 
2601     if ( isListeningForChanges() && m_bDetachEvents )
2602         stopControlModifyListening( xControl );
2603 }
2604 
2605 // XLoadListener
2606 //------------------------------------------------------------------------------
loaded(const EventObject & rEvent)2607 void FormController::loaded(const EventObject& rEvent)
2608 {
2609     OSL_ENSURE( rEvent.Source == m_xModelAsIndex, "FormController::loaded: where did this come from?" );
2610 
2611     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2612     ::osl::MutexGuard aGuard( m_aMutex );
2613     Reference< XRowSet >  xForm(rEvent.Source, UNO_QUERY);
2614     // do we have a connected data source
2615     OStaticDataAccessTools aStaticTools;
2616     if (xForm.is() && aStaticTools.getRowSetConnection(xForm).is())
2617     {
2618         Reference< XPropertySet >  xSet(xForm, UNO_QUERY);
2619         if (xSet.is())
2620         {
2621             Any aVal        = xSet->getPropertyValue(FM_PROP_CYCLE);
2622             sal_Int32 aVal2 = 0;
2623             ::cppu::enum2int(aVal2,aVal);
2624             m_bCycle        = !aVal.hasValue() || aVal2 == TabulatorCycle_RECORDS;
2625             m_bCanUpdate    = aStaticTools.canUpdate(xSet);
2626             m_bCanInsert    = aStaticTools.canInsert(xSet);
2627             m_bCurrentRecordModified = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ISMODIFIED));
2628             m_bCurrentRecordNew      = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ISNEW));
2629 
2630             startFormListening( xSet, sal_False );
2631 
2632             // set the locks for the current controls
2633             if (getContainer().is())
2634             {
2635                 m_aLoadEvent.Call();
2636             }
2637         }
2638         else
2639         {
2640             m_bCanInsert = m_bCanUpdate = m_bCycle = sal_False;
2641             m_bCurrentRecordModified = sal_False;
2642             m_bCurrentRecordNew = sal_False;
2643             m_bLocked = sal_False;
2644         }
2645         m_bDBConnection = sal_True;
2646     }
2647     else
2648     {
2649         m_bDBConnection = sal_False;
2650         m_bCanInsert = m_bCanUpdate = m_bCycle = sal_False;
2651         m_bCurrentRecordModified = sal_False;
2652         m_bCurrentRecordNew = sal_False;
2653         m_bLocked = sal_False;
2654     }
2655 
2656     Reference< XColumnsSupplier > xFormColumns( xForm, UNO_QUERY );
2657     m_pColumnInfoCache.reset( xFormColumns.is() ? new ColumnInfoCache( xFormColumns ) : NULL );
2658 
2659     updateAllDispatchers();
2660 }
2661 
2662 //------------------------------------------------------------------------------
updateAllDispatchers() const2663 void FormController::updateAllDispatchers() const
2664 {
2665     ::std::for_each(
2666         m_aFeatureDispatchers.begin(),
2667         m_aFeatureDispatchers.end(),
2668         ::std::compose1(
2669             UpdateAllListeners(),
2670             ::std::select2nd< DispatcherContainer::value_type >()
2671         )
2672     );
2673 }
2674 
2675 //------------------------------------------------------------------------------
IMPL_LINK(FormController,OnLoad,void *,EMPTYARG)2676 IMPL_LINK(FormController, OnLoad, void*, EMPTYARG)
2677 {
2678     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2679     m_bLocked = determineLockState();
2680 
2681     setLocks();
2682 
2683     if (!m_bLocked)
2684         startListening();
2685 
2686     // just one exception toggle the auto values
2687     if (m_bCurrentRecordNew)
2688         toggleAutoFields(sal_True);
2689 
2690     return 1L;
2691 }
2692 
2693 //------------------------------------------------------------------------------
unloaded(const EventObject &)2694 void FormController::unloaded(const EventObject& /*rEvent*/)
2695 {
2696     ::osl::MutexGuard aGuard( m_aMutex );
2697     impl_checkDisposed_throw();
2698 
2699     updateAllDispatchers();
2700 }
2701 
2702 //------------------------------------------------------------------------------
reloading(const EventObject &)2703 void FormController::reloading(const EventObject& /*aEvent*/)
2704 {
2705     ::osl::MutexGuard aGuard( m_aMutex );
2706     impl_checkDisposed_throw();
2707 
2708     // do the same like in unloading
2709     // just one exception toggle the auto values
2710     m_aToggleEvent.CancelPendingCall();
2711     unload();
2712 }
2713 
2714 //------------------------------------------------------------------------------
reloaded(const EventObject & aEvent)2715 void FormController::reloaded(const EventObject& aEvent)
2716 {
2717     ::osl::MutexGuard aGuard( m_aMutex );
2718     impl_checkDisposed_throw();
2719 
2720     loaded(aEvent);
2721 }
2722 
2723 //------------------------------------------------------------------------------
unloading(const EventObject &)2724 void FormController::unloading(const EventObject& /*aEvent*/)
2725 {
2726     ::osl::MutexGuard aGuard( m_aMutex );
2727     impl_checkDisposed_throw();
2728 
2729     unload();
2730 }
2731 
2732 //------------------------------------------------------------------------------
unload()2733 void FormController::unload()
2734 {
2735     ::osl::MutexGuard aGuard( m_aMutex );
2736     impl_checkDisposed_throw();
2737 
2738     m_aLoadEvent.CancelPendingCall();
2739 
2740     // be sure not to have autofields
2741     if (m_bCurrentRecordNew)
2742         toggleAutoFields(sal_False);
2743 
2744     // remove bound field listing again
2745     removeBoundFieldListener();
2746 
2747     if (m_bDBConnection && isListeningForChanges())
2748         stopListening();
2749 
2750     Reference< XPropertySet >  xSet( m_xModelAsIndex, UNO_QUERY );
2751     if ( m_bDBConnection && xSet.is() )
2752         stopFormListening( xSet, sal_False );
2753 
2754     m_bDBConnection = sal_False;
2755     m_bCanInsert = m_bCanUpdate = m_bCycle = sal_False;
2756     m_bCurrentRecordModified = m_bCurrentRecordNew = m_bLocked = sal_False;
2757 
2758     m_pColumnInfoCache.reset();
2759 }
2760 
2761 // -----------------------------------------------------------------------------
removeBoundFieldListener()2762 void FormController::removeBoundFieldListener()
2763 {
2764     const Reference< XControl >* pControls = m_aControls.getConstArray();
2765     const Reference< XControl >* pControlsEnd = pControls + m_aControls.getLength();
2766     while ( pControls != pControlsEnd )
2767     {
2768         Reference< XPropertySet > xProp( *pControls++, UNO_QUERY );
2769         if ( xProp.is() )
2770             xProp->removePropertyChangeListener( FM_PROP_BOUNDFIELD, this );
2771     }
2772 }
2773 
2774 //------------------------------------------------------------------------------
startFormListening(const Reference<XPropertySet> & _rxForm,sal_Bool _bPropertiesOnly)2775 void FormController::startFormListening( const Reference< XPropertySet >& _rxForm, sal_Bool _bPropertiesOnly )
2776 {
2777     try
2778     {
2779         if ( m_bCanInsert || m_bCanUpdate )   // form can be modified
2780         {
2781             _rxForm->addPropertyChangeListener( FM_PROP_ISNEW, this );
2782             _rxForm->addPropertyChangeListener( FM_PROP_ISMODIFIED, this );
2783 
2784             if ( !_bPropertiesOnly )
2785             {
2786                 // set the Listener for UI interaction
2787                 Reference< XRowSetApproveBroadcaster > xApprove( _rxForm, UNO_QUERY );
2788                 if ( xApprove.is() )
2789                     xApprove->addRowSetApproveListener( this );
2790 
2791                 // listener for row set changes
2792                 Reference< XRowSet > xRowSet( _rxForm, UNO_QUERY );
2793                 if ( xRowSet.is() )
2794                     xRowSet->addRowSetListener( this );
2795             }
2796         }
2797 
2798         Reference< XPropertySetInfo > xInfo = _rxForm->getPropertySetInfo();
2799         if ( xInfo.is() && xInfo->hasPropertyByName( FM_PROP_DYNAMIC_CONTROL_BORDER ) )
2800             _rxForm->addPropertyChangeListener( FM_PROP_DYNAMIC_CONTROL_BORDER, this );
2801     }
2802     catch( const Exception& )
2803     {
2804         DBG_UNHANDLED_EXCEPTION();
2805     }
2806 }
2807 
2808 //------------------------------------------------------------------------------
stopFormListening(const Reference<XPropertySet> & _rxForm,sal_Bool _bPropertiesOnly)2809 void FormController::stopFormListening( const Reference< XPropertySet >& _rxForm, sal_Bool _bPropertiesOnly )
2810 {
2811     try
2812     {
2813         if ( m_bCanInsert || m_bCanUpdate )
2814         {
2815             _rxForm->removePropertyChangeListener( FM_PROP_ISNEW, this );
2816             _rxForm->removePropertyChangeListener( FM_PROP_ISMODIFIED, this );
2817 
2818             if ( !_bPropertiesOnly )
2819             {
2820                 Reference< XRowSetApproveBroadcaster > xApprove( _rxForm, UNO_QUERY );
2821                 if (xApprove.is())
2822                     xApprove->removeRowSetApproveListener(this);
2823 
2824                 Reference< XRowSet > xRowSet( _rxForm, UNO_QUERY );
2825                 if ( xRowSet.is() )
2826                     xRowSet->removeRowSetListener( this );
2827             }
2828         }
2829 
2830         Reference< XPropertySetInfo > xInfo = _rxForm->getPropertySetInfo();
2831         if ( xInfo.is() && xInfo->hasPropertyByName( FM_PROP_DYNAMIC_CONTROL_BORDER ) )
2832             _rxForm->removePropertyChangeListener( FM_PROP_DYNAMIC_CONTROL_BORDER, this );
2833     }
2834     catch( const Exception& )
2835     {
2836         DBG_UNHANDLED_EXCEPTION();
2837     }
2838 }
2839 
2840 // com::sun::star::sdbc::XRowSetListener
2841 //------------------------------------------------------------------------------
cursorMoved(const EventObject &)2842 void FormController::cursorMoved(const EventObject& /*event*/)
2843 {
2844     ::osl::MutexGuard aGuard( m_aMutex );
2845     impl_checkDisposed_throw();
2846 
2847     // toggle the locking ?
2848     if (m_bLocked != determineLockState())
2849     {
2850         m_bLocked = !m_bLocked;
2851         setLocks();
2852         if (isListeningForChanges())
2853             startListening();
2854         else
2855             stopListening();
2856     }
2857 
2858     // neither the current control nor the current record are modified anymore
2859     m_bCurrentRecordModified = m_bModified = sal_False;
2860 }
2861 
2862 //------------------------------------------------------------------------------
rowChanged(const EventObject &)2863 void FormController::rowChanged(const EventObject& /*event*/)
2864 {
2865     // not interested in ...
2866 }
2867 //------------------------------------------------------------------------------
rowSetChanged(const EventObject &)2868 void FormController::rowSetChanged(const EventObject& /*event*/)
2869 {
2870     // not interested in ...
2871 }
2872 
2873 
2874 // XContainerListener
2875 //------------------------------------------------------------------------------
elementInserted(const ContainerEvent & evt)2876 void SAL_CALL FormController::elementInserted(const ContainerEvent& evt)
2877 {
2878     ::osl::MutexGuard aGuard( m_aMutex );
2879     impl_checkDisposed_throw();
2880 
2881     Reference< XControl > xControl( evt.Element, UNO_QUERY );
2882     if ( !xControl.is() )
2883         return;
2884 
2885     Reference< XFormComponent >  xModel(xControl->getModel(), UNO_QUERY);
2886     if (xModel.is() && m_xModelAsIndex == xModel->getParent())
2887     {
2888         insertControl(xControl);
2889 
2890         if ( m_aTabActivationTimer.IsActive() )
2891             m_aTabActivationTimer.Stop();
2892 
2893         m_aTabActivationTimer.Start();
2894     }
2895     // are we in filtermode and a XModeSelector has inserted an element
2896     else if (m_bFiltering && Reference< XModeSelector > (evt.Source, UNO_QUERY).is())
2897     {
2898         xModel = Reference< XFormComponent > (evt.Source, UNO_QUERY);
2899         if (xModel.is() && m_xModelAsIndex == xModel->getParent())
2900         {
2901             Reference< XPropertySet >  xSet(xControl->getModel(), UNO_QUERY);
2902             if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
2903             {
2904                 // does the model use a bound field ?
2905                 Reference< XPropertySet >  xField;
2906                 xSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
2907 
2908                 Reference< XTextComponent >  xText(xControl, UNO_QUERY);
2909                 // may we filter the field?
2910                 if (xText.is() && xField.is() && ::comphelper::hasProperty(FM_PROP_SEARCHABLE, xField) &&
2911                     ::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_SEARCHABLE)))
2912                 {
2913                     m_aFilterComponents.push_back( xText );
2914                     xText->addTextListener( this );
2915                 }
2916             }
2917         }
2918     }
2919 }
2920 
2921 //------------------------------------------------------------------------------
elementReplaced(const ContainerEvent & evt)2922 void SAL_CALL FormController::elementReplaced(const ContainerEvent& evt)
2923 {
2924     // simulate an elementRemoved
2925     ContainerEvent aRemoveEvent( evt );
2926     aRemoveEvent.Element = evt.ReplacedElement;
2927     aRemoveEvent.ReplacedElement = Any();
2928     elementRemoved( aRemoveEvent );
2929 
2930     // simulate an elementInserted
2931     ContainerEvent aInsertEvent( evt );
2932     aInsertEvent.ReplacedElement = Any();
2933     elementInserted( aInsertEvent );
2934 }
2935 
2936 //------------------------------------------------------------------------------
elementRemoved(const ContainerEvent & evt)2937 void SAL_CALL FormController::elementRemoved(const ContainerEvent& evt)
2938 {
2939     ::osl::MutexGuard aGuard( m_aMutex );
2940     impl_checkDisposed_throw();
2941 
2942     Reference< XControl >  xControl;
2943     evt.Element >>= xControl;
2944     if (!xControl.is())
2945         return;
2946 
2947     Reference< XFormComponent >  xModel(xControl->getModel(), UNO_QUERY);
2948     if (xModel.is() && m_xModelAsIndex == xModel->getParent())
2949     {
2950         removeControl(xControl);
2951         // TabOrder nicht neu berechnen, da das intern schon funktionieren mu�!
2952     }
2953     // are we in filtermode and a XModeSelector has inserted an element
2954     else if (m_bFiltering && Reference< XModeSelector > (evt.Source, UNO_QUERY).is())
2955     {
2956         FilterComponents::iterator componentPos = ::std::find(
2957             m_aFilterComponents.begin(), m_aFilterComponents.end(), xControl );
2958         if ( componentPos != m_aFilterComponents.end() )
2959             m_aFilterComponents.erase( componentPos );
2960     }
2961 }
2962 
2963 //------------------------------------------------------------------------------
isInList(const Reference<XWindowPeer> & xPeer) const2964 Reference< XControl >  FormController::isInList(const Reference< XWindowPeer > & xPeer) const
2965 {
2966     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
2967     const Reference< XControl >* pControls = m_aControls.getConstArray();
2968 
2969     sal_uInt32 nCtrls = m_aControls.getLength();
2970     for ( sal_uInt32 n = 0; n < nCtrls && xPeer.is(); ++n, ++pControls )
2971     {
2972         if ( pControls->is() )
2973         {
2974             Reference< XVclWindowPeer >  xCtrlPeer( (*pControls)->getPeer(), UNO_QUERY);
2975             if ( ( xCtrlPeer.get() == xPeer.get() ) || xCtrlPeer->isChild( xPeer ) )
2976                 return *pControls;
2977         }
2978     }
2979     return Reference< XControl > ();
2980 }
2981 
2982 //------------------------------------------------------------------------------
activateFirst()2983 void FormController::activateFirst()
2984 {
2985     ::osl::MutexGuard aGuard( m_aMutex );
2986     impl_checkDisposed_throw();
2987 
2988     DBG_ASSERT(m_xTabController.is(), "FormController::activateFirst : invalid aggregate !");
2989     if (m_xTabController.is())
2990         m_xTabController->activateFirst();
2991 }
2992 
2993 //------------------------------------------------------------------------------
activateLast()2994 void FormController::activateLast()
2995 {
2996     ::osl::MutexGuard aGuard( m_aMutex );
2997     impl_checkDisposed_throw();
2998 
2999     DBG_ASSERT(m_xTabController.is(), "FormController::activateLast : invalid aggregate !");
3000     if (m_xTabController.is())
3001         m_xTabController->activateLast();
3002 }
3003 
3004 // XFormController
3005 //------------------------------------------------------------------------------
getFormOperations()3006 Reference< XFormOperations > SAL_CALL FormController::getFormOperations()
3007 {
3008     ::osl::MutexGuard aGuard( m_aMutex );
3009     impl_checkDisposed_throw();
3010 
3011     return m_xFormOperations;
3012 }
3013 
3014 //------------------------------------------------------------------------------
getCurrentControl(void)3015 Reference< XControl> SAL_CALL FormController::getCurrentControl(void)
3016 {
3017     ::osl::MutexGuard aGuard( m_aMutex );
3018     impl_checkDisposed_throw();
3019     return m_xCurrentControl;
3020 }
3021 
3022 //------------------------------------------------------------------------------
addActivateListener(const Reference<XFormControllerListener> & l)3023 void SAL_CALL FormController::addActivateListener(const Reference< XFormControllerListener > & l)
3024 {
3025     ::osl::MutexGuard aGuard( m_aMutex );
3026     impl_checkDisposed_throw();
3027     m_aActivateListeners.addInterface(l);
3028 }
3029 //------------------------------------------------------------------------------
removeActivateListener(const Reference<XFormControllerListener> & l)3030 void SAL_CALL FormController::removeActivateListener(const Reference< XFormControllerListener > & l)
3031 {
3032     ::osl::MutexGuard aGuard( m_aMutex );
3033     impl_checkDisposed_throw();
3034     m_aActivateListeners.removeInterface(l);
3035 }
3036 
3037 //------------------------------------------------------------------------------
addChildController(const Reference<XFormController> & _ChildController)3038 void SAL_CALL FormController::addChildController( const Reference< XFormController >& _ChildController )
3039 {
3040     ::osl::MutexGuard aGuard( m_aMutex );
3041     impl_checkDisposed_throw();
3042 
3043     if ( !_ChildController.is() )
3044         throw IllegalArgumentException( ::rtl::OUString(), *this, 1 );
3045         // TODO: (localized) error message
3046 
3047     // the parent of our (to-be-)child must be our own model
3048     Reference< XFormComponent > xFormOfChild( _ChildController->getModel(), UNO_QUERY );
3049     if ( !xFormOfChild.is() )
3050         throw IllegalArgumentException( ::rtl::OUString(), *this, 1 );
3051         // TODO: (localized) error message
3052 
3053     if ( xFormOfChild->getParent() != m_xModelAsIndex )
3054         throw IllegalArgumentException( ::rtl::OUString(), *this, 1 );
3055         // TODO: (localized) error message
3056 
3057     m_aChilds.push_back( _ChildController );
3058     _ChildController->setParent( *this );
3059 
3060     // search the position of the model within the form
3061     sal_uInt32 nPos = m_xModelAsIndex->getCount();
3062     Reference< XFormComponent > xTemp;
3063     for( ; nPos; )
3064     {
3065         m_xModelAsIndex->getByIndex(--nPos) >>= xTemp;
3066         if ( xFormOfChild == xTemp )
3067         {
3068             Reference< XInterface >  xIfc( _ChildController, UNO_QUERY );
3069             m_xModelAsManager->attach( nPos, xIfc, makeAny( _ChildController) );
3070             break;
3071         }
3072     }
3073 }
3074 
3075 //------------------------------------------------------------------------------
getContext()3076 Reference< XFormControllerContext > SAL_CALL FormController::getContext()
3077 {
3078     ::osl::MutexGuard aGuard( m_aMutex );
3079     impl_checkDisposed_throw();
3080     return m_xContext;
3081 }
3082 
3083 //------------------------------------------------------------------------------
setContext(const Reference<XFormControllerContext> & _context)3084 void SAL_CALL FormController::setContext( const Reference< XFormControllerContext >& _context )
3085 {
3086     ::osl::MutexGuard aGuard( m_aMutex );
3087     impl_checkDisposed_throw();
3088     m_xContext = _context;
3089 }
3090 
3091 //------------------------------------------------------------------------------
getInteractionHandler()3092 Reference< XInteractionHandler > SAL_CALL FormController::getInteractionHandler()
3093 {
3094     ::osl::MutexGuard aGuard( m_aMutex );
3095     impl_checkDisposed_throw();
3096     return m_xInteractionHandler;
3097 }
3098 
3099 //------------------------------------------------------------------------------
setInteractionHandler(const Reference<XInteractionHandler> & _interactionHandler)3100 void SAL_CALL FormController::setInteractionHandler( const Reference< XInteractionHandler >& _interactionHandler )
3101 {
3102     ::osl::MutexGuard aGuard( m_aMutex );
3103     impl_checkDisposed_throw();
3104     m_xInteractionHandler = _interactionHandler;
3105 }
3106 
3107 //------------------------------------------------------------------------------
setFilter(::std::vector<FmFieldInfo> & rFieldInfos)3108 void FormController::setFilter(::std::vector<FmFieldInfo>& rFieldInfos)
3109 {
3110     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
3111     // create the composer
3112     Reference< XRowSet > xForm(m_xModelAsIndex, UNO_QUERY);
3113     Reference< XConnection > xConnection(OStaticDataAccessTools().getRowSetConnection(xForm));
3114     if (xForm.is())
3115     {
3116         try
3117         {
3118             Reference< XMultiServiceFactory > xFactory( xConnection, UNO_QUERY_THROW );
3119             m_xComposer.set(
3120                 xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.SingleSelectQueryComposer" ) ) ),
3121                 UNO_QUERY_THROW );
3122 
3123             Reference< XPropertySet > xSet( xForm, UNO_QUERY );
3124             ::rtl::OUString sStatement  = ::comphelper::getString( xSet->getPropertyValue( FM_PROP_ACTIVECOMMAND ) );
3125             ::rtl::OUString sFilter     = ::comphelper::getString( xSet->getPropertyValue( FM_PROP_FILTER ) );
3126             m_xComposer->setElementaryQuery( sStatement );
3127             m_xComposer->setFilter( sFilter );
3128         }
3129         catch( const Exception& )
3130         {
3131             DBG_UNHANDLED_EXCEPTION();
3132         }
3133     }
3134 
3135     if (m_xComposer.is())
3136     {
3137         Sequence < PropertyValue> aLevel;
3138         Sequence< Sequence < PropertyValue > > aFilterRows = m_xComposer->getStructuredFilter();
3139 
3140         // ok, we receive the list of filters as sequence of fieldnames, value
3141         // now we have to transform the fieldname into UI names, that could be a label of the field or
3142         // a aliasname or the fieldname itself
3143 
3144         // first adjust the field names if necessary
3145         Reference< XNameAccess > xQueryColumns =
3146             Reference< XColumnsSupplier >( m_xComposer, UNO_QUERY_THROW )->getColumns();
3147 
3148         for (::std::vector<FmFieldInfo>::iterator iter = rFieldInfos.begin();
3149             iter != rFieldInfos.end(); iter++)
3150         {
3151             if ( xQueryColumns->hasByName((*iter).aFieldName) )
3152             {
3153                 if ( (xQueryColumns->getByName((*iter).aFieldName) >>= (*iter).xField) && (*iter).xField.is() )
3154                     (*iter).xField->getPropertyValue(FM_PROP_REALNAME) >>= (*iter).aFieldName;
3155             }
3156         }
3157 
3158         Reference< XDatabaseMetaData> xMetaData(xConnection->getMetaData());
3159         // now transfer the filters into Value/TextComponent pairs
3160         ::comphelper::UStringMixEqual aCompare(xMetaData->storesMixedCaseQuotedIdentifiers());
3161 
3162         // need to parse criteria localized
3163         OStaticDataAccessTools aStaticTools;
3164         Reference< XNumberFormatsSupplier> xFormatSupplier( aStaticTools.getNumberFormats(xConnection, sal_True));
3165         Reference< XNumberFormatter> xFormatter( m_aContext.createComponent( "com.sun.star.util.NumberFormatter" ), UNO_QUERY );
3166         xFormatter->attachNumberFormatsSupplier(xFormatSupplier);
3167         Locale aAppLocale = Application::GetSettings().GetUILocale();
3168         LocaleDataWrapper aLocaleWrapper( m_aContext.getLegacyServiceFactory(), aAppLocale );
3169 
3170         // retrieving the filter
3171         const Sequence < PropertyValue >* pRow = aFilterRows.getConstArray();
3172         for (sal_Int32 i = 0, nLen = aFilterRows.getLength(); i < nLen; ++i)
3173         {
3174             FmFilterRow aRow;
3175 
3176             // search a field for the given name
3177             const PropertyValue* pRefValues = pRow[i].getConstArray();
3178             for (sal_Int32 j = 0, nLen1 = pRow[i].getLength(); j < nLen1; j++)
3179             {
3180                 // look for the text component
3181                 Reference< XPropertySet > xField;
3182                 try
3183                 {
3184                     Reference< XPropertySet > xSet;
3185                     ::rtl::OUString aRealName;
3186 
3187                     // first look with the given name
3188                     if (xQueryColumns->hasByName(pRefValues[j].Name))
3189                     {
3190                         xQueryColumns->getByName(pRefValues[j].Name) >>= xSet;
3191 
3192                         // get the RealName
3193                         xSet->getPropertyValue(::rtl::OUString::createFromAscii("RealName")) >>= aRealName;
3194 
3195                         // compare the condition field name and the RealName
3196                         if (aCompare(aRealName, pRefValues[j].Name))
3197                             xField = xSet;
3198                     }
3199                     if (!xField.is())
3200                     {
3201                         // no we have to check every column to find the realname
3202                         Reference< XIndexAccess > xColumnsByIndex(xQueryColumns, UNO_QUERY);
3203                         for (sal_Int32 n = 0, nCount = xColumnsByIndex->getCount(); n < nCount; n++)
3204                         {
3205                             xColumnsByIndex->getByIndex(n) >>= xSet;
3206                             xSet->getPropertyValue(::rtl::OUString::createFromAscii("RealName")) >>= aRealName;
3207                             if (aCompare(aRealName, pRefValues[j].Name))
3208                             {
3209                                 // get the column by its alias
3210                                 xField = xSet;
3211                                 break;
3212                             }
3213                         }
3214                     }
3215                     if (!xField.is())
3216                         continue;
3217                 }
3218                 catch (const Exception&)
3219                 {
3220                     continue;
3221                 }
3222 
3223                 // find the text component
3224                 for (::std::vector<FmFieldInfo>::iterator iter = rFieldInfos.begin();
3225                     iter != rFieldInfos.end(); iter++)
3226                 {
3227                     // we found the field so insert a new entry to the filter row
3228                     if ((*iter).xField == xField)
3229                     {
3230                         // do we already have the control ?
3231                         if (aRow.find((*iter).xText) != aRow.end())
3232                         {
3233                             ::rtl::OUString aCompText = aRow[(*iter).xText];
3234                             aCompText += ::rtl::OUString::createFromAscii(" ");
3235                             ::rtl::OString aVal = m_xParser->getContext().getIntlKeywordAscii(OParseContext::KEY_AND);
3236                             aCompText += ::rtl::OUString(aVal.getStr(),aVal.getLength(),RTL_TEXTENCODING_ASCII_US);
3237                             aCompText += ::rtl::OUString::createFromAscii(" ");
3238                             aCompText += ::comphelper::getString(pRefValues[j].Value);
3239                             aRow[(*iter).xText] = aCompText;
3240                         }
3241                         else
3242                         {
3243                             ::rtl::OUString sPredicate,sErrorMsg;
3244                             pRefValues[j].Value >>= sPredicate;
3245                             ::rtl::Reference< ISQLParseNode > xParseNode = predicateTree(sErrorMsg, sPredicate, xFormatter, xField);
3246                             if ( xParseNode.is() )
3247                             {
3248                                 ::rtl::OUString sCriteria;
3249                                 xParseNode->parseNodeToPredicateStr( sCriteria
3250                                                                     ,xConnection
3251                                                                     ,xFormatter
3252                                                                     ,xField
3253                                                                     ,aAppLocale
3254                                                                     ,(sal_Char)aLocaleWrapper.getNumDecimalSep().GetChar(0)
3255                                                                     ,getParseContext());
3256                                 aRow[(*iter).xText] = sCriteria;
3257                             }
3258                         }
3259                     }
3260                 }
3261             }
3262 
3263             if (aRow.empty())
3264                 continue;
3265 
3266             impl_addFilterRow( aRow );
3267         }
3268     }
3269 
3270     // now set the filter controls
3271     for (   ::std::vector<FmFieldInfo>::iterator field = rFieldInfos.begin();
3272             field != rFieldInfos.end();
3273             ++field
3274         )
3275     {
3276         m_aFilterComponents.push_back( field->xText );
3277     }
3278 }
3279 
3280 //------------------------------------------------------------------------------
startFiltering()3281 void FormController::startFiltering()
3282 {
3283     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
3284 
3285     OStaticDataAccessTools aStaticTools;
3286     Reference< XConnection >  xConnection( aStaticTools.getRowSetConnection( Reference< XRowSet >( m_xModelAsIndex, UNO_QUERY ) ) );
3287     if ( !xConnection.is() )
3288         // nothing to do - can't filter a form which is not connected
3289         // 98023 - 19.03.2002 - fs@openoffice.org
3290         return;
3291 
3292     // stop listening for controls
3293     if (isListeningForChanges())
3294         stopListening();
3295 
3296     m_bFiltering = sal_True;
3297 
3298     // as we don't want new controls to be attached to the scripting environment
3299     // we change attach flags
3300     m_bAttachEvents = sal_False;
3301 
3302     // Austauschen der Kontrols fuer das aktuelle Formular
3303     Sequence< Reference< XControl > > aControlsCopy( m_aControls );
3304     const Reference< XControl >* pControls = aControlsCopy.getConstArray();
3305     sal_Int32 nControlCount = aControlsCopy.getLength();
3306 
3307     // the control we have to activate after replacement
3308     Reference< XDatabaseMetaData >  xMetaData(xConnection->getMetaData());
3309     Reference< XNumberFormatsSupplier >  xFormatSupplier = aStaticTools.getNumberFormats(xConnection, sal_True);
3310     Reference< XNumberFormatter >  xFormatter( m_aContext.createComponent( "com.sun.star.util.NumberFormatter" ), UNO_QUERY );
3311     xFormatter->attachNumberFormatsSupplier(xFormatSupplier);
3312 
3313     // structure for storing the field info
3314     ::std::vector<FmFieldInfo> aFieldInfos;
3315 
3316     for (sal_Int32 i = nControlCount; i > 0;)
3317     {
3318         Reference< XControl > xControl = pControls[--i];
3319         if (xControl.is())
3320         {
3321             // no events for the control anymore
3322             removeFromEventAttacher(xControl);
3323 
3324             // do we have a mode selector
3325             Reference< XModeSelector >  xSelector(xControl, UNO_QUERY);
3326             if (xSelector.is())
3327             {
3328                 xSelector->setMode( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterMode" ) ) );
3329 
3330                 // listening for new controls of the selector
3331                 Reference< XContainer >  xContainer(xSelector, UNO_QUERY);
3332                 if (xContainer.is())
3333                     xContainer->addContainerListener(this);
3334 
3335                 Reference< XEnumerationAccess >  xElementAccess(xSelector, UNO_QUERY);
3336                 if (xElementAccess.is())
3337                 {
3338                     Reference< XEnumeration >  xEnumeration(xElementAccess->createEnumeration());
3339                     Reference< XControl >  xSubControl;
3340                     while (xEnumeration->hasMoreElements())
3341                     {
3342                         xEnumeration->nextElement() >>= xSubControl;
3343                         if (xSubControl.is())
3344                         {
3345                             Reference< XPropertySet >  xSet(xSubControl->getModel(), UNO_QUERY);
3346                             if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
3347                             {
3348                                 // does the model use a bound field ?
3349                                 Reference< XPropertySet >  xField;
3350                                 xSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
3351 
3352                                 Reference< XTextComponent >  xText(xSubControl, UNO_QUERY);
3353                                 // may we filter the field?
3354                                 if (xText.is() && xField.is() && ::comphelper::hasProperty(FM_PROP_SEARCHABLE, xField) &&
3355                                     ::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_SEARCHABLE)))
3356                                 {
3357                                     aFieldInfos.push_back(FmFieldInfo(xField, xText));
3358                                     xText->addTextListener(this);
3359                                 }
3360                             }
3361                         }
3362                     }
3363                 }
3364                 continue;
3365             }
3366 
3367             Reference< XPropertySet >  xModel( xControl->getModel(), UNO_QUERY );
3368             if (xModel.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xModel))
3369             {
3370                 // does the model use a bound field ?
3371                 Any aVal = xModel->getPropertyValue(FM_PROP_BOUNDFIELD);
3372                 Reference< XPropertySet >  xField;
3373                 aVal >>= xField;
3374 
3375                 // may we filter the field?
3376 
3377                 if  (   xField.is()
3378                     &&  ::comphelper::hasProperty( FM_PROP_SEARCHABLE, xField )
3379                     && ::comphelper::getBOOL( xField->getPropertyValue( FM_PROP_SEARCHABLE ) )
3380                     )
3381                 {
3382                     // create a filter control
3383                     Sequence< Any > aCreationArgs( 3 );
3384                     aCreationArgs[ 0 ] <<= NamedValue( ::rtl::OUString::createFromAscii( "MessageParent" ), makeAny( VCLUnoHelper::GetInterface( getDialogParentWindow() ) ) );
3385                     aCreationArgs[ 1 ] <<= NamedValue( ::rtl::OUString::createFromAscii( "NumberFormatter" ), makeAny( xFormatter ) );
3386                     aCreationArgs[ 2 ] <<= NamedValue( ::rtl::OUString::createFromAscii( "ControlModel" ), makeAny( xModel ) );
3387                     Reference< XControl > xFilterControl(
3388                         m_aContext.createComponentWithArguments( "com.sun.star.form.control.FilterControl", aCreationArgs ),
3389                         UNO_QUERY
3390                     );
3391                     DBG_ASSERT( xFilterControl.is(), "FormController::startFiltering: could not create a filter control!" );
3392 
3393                     if ( replaceControl( xControl, xFilterControl ) )
3394                     {
3395                         Reference< XTextComponent > xFilterText( xFilterControl, UNO_QUERY );
3396                         aFieldInfos.push_back( FmFieldInfo( xField, xFilterText ) );
3397                         xFilterText->addTextListener(this);
3398                     }
3399                 }
3400             }
3401             else
3402             {
3403                 // abmelden vom EventManager
3404             }
3405         }
3406     }
3407 
3408     // we have all filter controls now, so the next step is to read the filters from the form
3409     // resolve all aliases and set the current filter to the according structure
3410     setFilter(aFieldInfos);
3411 
3412     Reference< XPropertySet > xSet( m_xModelAsIndex, UNO_QUERY );
3413     if ( xSet.is() )
3414         stopFormListening( xSet, sal_True );
3415 
3416     impl_setTextOnAllFilter_throw();
3417 
3418     // lock all controls which are not used for filtering
3419     m_bLocked = determineLockState();
3420     setLocks();
3421     m_bAttachEvents = sal_True;
3422 }
3423 
3424 //------------------------------------------------------------------------------
stopFiltering()3425 void FormController::stopFiltering()
3426 {
3427     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
3428     if ( !m_bFiltering ) // #104693# OJ
3429     {   // nothing to do
3430         return;
3431     }
3432 
3433     m_bFiltering = sal_False;
3434     m_bDetachEvents = sal_False;
3435 
3436     ::comphelper::disposeComponent(m_xComposer);
3437 
3438     // Austauschen der Kontrols fuer das aktuelle Formular
3439     Sequence< Reference< XControl > > aControlsCopy( m_aControls );
3440     const Reference< XControl > * pControls = aControlsCopy.getConstArray();
3441     sal_Int32 nControlCount = aControlsCopy.getLength();
3442 
3443     // clear the filter control map
3444     ::std::for_each( m_aFilterComponents.begin(), m_aFilterComponents.end(), RemoveComponentTextListener( this ) );
3445     m_aFilterComponents.clear();
3446 
3447     for ( sal_Int32 i = nControlCount; i > 0; )
3448     {
3449         Reference< XControl > xControl = pControls[--i];
3450         if (xControl.is())
3451         {
3452             // now enable eventhandling again
3453             addToEventAttacher(xControl);
3454 
3455             Reference< XModeSelector >  xSelector(xControl, UNO_QUERY);
3456             if (xSelector.is())
3457             {
3458                 xSelector->setMode( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DataMode" ) ) );
3459 
3460                 // listening for new controls of the selector
3461                 Reference< XContainer >  xContainer(xSelector, UNO_QUERY);
3462                 if (xContainer.is())
3463                     xContainer->removeContainerListener(this);
3464                 continue;
3465             }
3466 
3467             Reference< XPropertySet >  xSet(xControl->getModel(), UNO_QUERY);
3468             if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet))
3469             {
3470                 // does the model use a bound field ?
3471                 Reference< XPropertySet >  xField;
3472                 xSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField;
3473 
3474                 // may we filter the field?
3475                 if  (   xField.is()
3476                     &&  ::comphelper::hasProperty( FM_PROP_SEARCHABLE, xField )
3477                     &&  ::comphelper::getBOOL( xField->getPropertyValue( FM_PROP_SEARCHABLE ) )
3478                     )
3479                 {
3480                     ::rtl::OUString sServiceName;
3481                     OSL_VERIFY( xSet->getPropertyValue( FM_PROP_DEFAULTCONTROL ) >>= sServiceName );
3482                     Reference< XControl > xNewControl( m_aContext.createComponent( sServiceName ), UNO_QUERY );
3483                     replaceControl( xControl, xNewControl );
3484                 }
3485             }
3486         }
3487     }
3488 
3489     Reference< XPropertySet >  xSet( m_xModelAsIndex, UNO_QUERY );
3490     if ( xSet.is() )
3491         startFormListening( xSet, sal_True );
3492 
3493     m_bDetachEvents = sal_True;
3494 
3495     m_aFilterRows.clear();
3496     m_nCurrentFilterPosition = -1;
3497 
3498     // release the locks if possible
3499     // lock all controls which are not used for filtering
3500     m_bLocked = determineLockState();
3501     setLocks();
3502 
3503     // restart listening for control modifications
3504     if (isListeningForChanges())
3505         startListening();
3506 }
3507 
3508 // XModeSelector
3509 //------------------------------------------------------------------------------
setMode(const::rtl::OUString & Mode)3510 void FormController::setMode(const ::rtl::OUString& Mode)
3511 {
3512     ::osl::MutexGuard aGuard( m_aMutex );
3513     impl_checkDisposed_throw();
3514 
3515     if (!supportsMode(Mode))
3516         throw NoSupportException();
3517 
3518     if (Mode == m_aMode)
3519         return;
3520 
3521     m_aMode = Mode;
3522 
3523     if ( Mode.equalsAscii( "FilterMode" ) )
3524         startFiltering();
3525     else
3526         stopFiltering();
3527 
3528     for (FmFormControllers::const_iterator i = m_aChilds.begin();
3529         i != m_aChilds.end(); ++i)
3530     {
3531         Reference< XModeSelector > xMode(*i, UNO_QUERY);
3532         if ( xMode.is() )
3533             xMode->setMode(Mode);
3534     }
3535 }
3536 
3537 //------------------------------------------------------------------------------
getMode(void)3538 ::rtl::OUString SAL_CALL FormController::getMode(void)
3539 {
3540     ::osl::MutexGuard aGuard( m_aMutex );
3541     impl_checkDisposed_throw();
3542 
3543     return m_aMode;
3544 }
3545 
3546 //------------------------------------------------------------------------------
getSupportedModes(void)3547 Sequence< ::rtl::OUString > SAL_CALL FormController::getSupportedModes(void)
3548 {
3549     ::osl::MutexGuard aGuard( m_aMutex );
3550     impl_checkDisposed_throw();
3551 
3552     static Sequence< ::rtl::OUString > aModes;
3553     if (!aModes.getLength())
3554     {
3555         aModes.realloc(2);
3556         ::rtl::OUString* pModes = aModes.getArray();
3557         pModes[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DataMode" ) );
3558         pModes[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterMode" ) );
3559     }
3560     return aModes;
3561 }
3562 
3563 //------------------------------------------------------------------------------
supportsMode(const::rtl::OUString & Mode)3564 sal_Bool SAL_CALL FormController::supportsMode(const ::rtl::OUString& Mode)
3565 {
3566     ::osl::MutexGuard aGuard( m_aMutex );
3567     impl_checkDisposed_throw();
3568 
3569     Sequence< ::rtl::OUString > aModes(getSupportedModes());
3570     const ::rtl::OUString* pModes = aModes.getConstArray();
3571     for (sal_Int32 i = aModes.getLength(); i > 0; )
3572     {
3573         if (pModes[--i] == Mode)
3574             return sal_True;
3575     }
3576     return sal_False;
3577 }
3578 
3579 //------------------------------------------------------------------------------
getDialogParentWindow()3580 Window* FormController::getDialogParentWindow()
3581 {
3582     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
3583     Window* pParentWindow = NULL;
3584     try
3585     {
3586         Reference< XControl > xContainerControl( getContainer(), UNO_QUERY_THROW );
3587         Reference< XWindowPeer > xContainerPeer( xContainerControl->getPeer(), UNO_QUERY_THROW );
3588         pParentWindow = VCLUnoHelper::GetWindow( xContainerPeer );
3589     }
3590     catch( const Exception& )
3591     {
3592         DBG_UNHANDLED_EXCEPTION();
3593     }
3594     return pParentWindow;
3595 }
3596 //------------------------------------------------------------------------------
checkFormComponentValidity(::rtl::OUString & _rFirstInvalidityExplanation,Reference<XControlModel> & _rxFirstInvalidModel)3597 bool FormController::checkFormComponentValidity( ::rtl::OUString& /* [out] */ _rFirstInvalidityExplanation, Reference< XControlModel >& /* [out] */ _rxFirstInvalidModel ) SAL_THROW(())
3598 {
3599     try
3600     {
3601         Reference< XEnumerationAccess > xControlEnumAcc( getModel(), UNO_QUERY );
3602         Reference< XEnumeration > xControlEnumeration;
3603         if ( xControlEnumAcc.is() )
3604             xControlEnumeration = xControlEnumAcc->createEnumeration();
3605         OSL_ENSURE( xControlEnumeration.is(), "FormController::checkFormComponentValidity: cannot enumerate the controls!" );
3606         if ( !xControlEnumeration.is() )
3607             // assume all valid
3608             return true;
3609 
3610         Reference< XValidatableFormComponent > xValidatable;
3611         while ( xControlEnumeration->hasMoreElements() )
3612         {
3613             if ( !( xControlEnumeration->nextElement() >>= xValidatable ) )
3614                 // control does not support validation
3615                 continue;
3616 
3617             if ( xValidatable->isValid() )
3618                 continue;
3619 
3620             Reference< XValidator > xValidator( xValidatable->getValidator() );
3621             OSL_ENSURE( xValidator.is(), "FormController::checkFormComponentValidity: invalid, but no validator?" );
3622             if ( !xValidator.is() )
3623                 // this violates the interface definition of css.form.validation.XValidatableFormComponent ...
3624                 continue;
3625 
3626             _rFirstInvalidityExplanation = xValidator->explainInvalid( xValidatable->getCurrentValue() );
3627             _rxFirstInvalidModel = _rxFirstInvalidModel.query( xValidatable );
3628             return false;
3629         }
3630     }
3631     catch( const Exception& )
3632     {
3633         DBG_UNHANDLED_EXCEPTION();
3634     }
3635     return true;
3636 }
3637 
3638 //------------------------------------------------------------------------------
locateControl(const Reference<XControlModel> & _rxModel)3639 Reference< XControl > FormController::locateControl( const Reference< XControlModel >& _rxModel ) SAL_THROW(())
3640 {
3641     try
3642     {
3643         Sequence< Reference< XControl > > aControls( getControls() );
3644         const Reference< XControl >* pControls = aControls.getConstArray();
3645         const Reference< XControl >* pControlsEnd = aControls.getConstArray() + aControls.getLength();
3646 
3647         for ( ; pControls != pControlsEnd; ++pControls )
3648         {
3649             OSL_ENSURE( pControls->is(), "FormController::locateControl: NULL-control?" );
3650             if ( pControls->is() )
3651             {
3652                 if ( ( *pControls)->getModel() == _rxModel )
3653                     return *pControls;
3654             }
3655         }
3656         OSL_ENSURE( sal_False, "FormController::locateControl: did not find a control for this model!" );
3657     }
3658     catch( const Exception& )
3659     {
3660         DBG_UNHANDLED_EXCEPTION();
3661     }
3662     return NULL;
3663 }
3664 
3665 //------------------------------------------------------------------------------
3666 namespace
3667 {
displayErrorSetFocus(const String & _rMessage,const Reference<XControl> & _rxFocusControl,Window * _pDialogParent)3668     void displayErrorSetFocus( const String& _rMessage, const Reference< XControl >& _rxFocusControl, Window* _pDialogParent )
3669     {
3670         SQLContext aError;
3671         aError.Message = String( SVX_RES( RID_STR_WRITEERROR ) );
3672         aError.Details = _rMessage;
3673         displayException( aError, _pDialogParent );
3674 
3675         if ( _rxFocusControl.is() )
3676         {
3677             Reference< XWindow > xControlWindow( _rxFocusControl, UNO_QUERY );
3678             OSL_ENSURE( xControlWindow.is(), "displayErrorSetFocus: invalid control!" );
3679             if ( xControlWindow.is() )
3680                 xControlWindow->setFocus();
3681         }
3682     }
3683 
lcl_shouldValidateRequiredFields_nothrow(const Reference<XInterface> & _rxForm)3684     sal_Bool lcl_shouldValidateRequiredFields_nothrow( const Reference< XInterface >& _rxForm )
3685     {
3686         try
3687         {
3688             static ::rtl::OUString s_sFormsCheckRequiredFields( RTL_CONSTASCII_USTRINGPARAM( "FormsCheckRequiredFields" ) );
3689 
3690             // first, check whether the form has a property telling us the answer
3691             // this allows people to use the XPropertyContainer interface of a form to control
3692             // the behaviour on a per-form basis.
3693             Reference< XPropertySet > xFormProps( _rxForm, UNO_QUERY_THROW );
3694             Reference< XPropertySetInfo > xPSI( xFormProps->getPropertySetInfo() );
3695             if ( xPSI->hasPropertyByName( s_sFormsCheckRequiredFields ) )
3696             {
3697                 sal_Bool bShouldValidate = true;
3698                 OSL_VERIFY( xFormProps->getPropertyValue( s_sFormsCheckRequiredFields ) >>= bShouldValidate );
3699                 return bShouldValidate;
3700             }
3701 
3702             // next, check the data source which created the connection
3703             Reference< XChild > xConnectionAsChild( xFormProps->getPropertyValue( FM_PROP_ACTIVE_CONNECTION ), UNO_QUERY_THROW );
3704             Reference< XPropertySet > xDataSource( xConnectionAsChild->getParent(), UNO_QUERY );
3705             if ( !xDataSource.is() )
3706                 // seldom (but possible): this is not a connection created by a data source
3707                 return sal_True;
3708 
3709             Reference< XPropertySet > xDataSourceSettings(
3710                 xDataSource->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Settings" ) ) ),
3711                 UNO_QUERY_THROW );
3712 
3713             sal_Bool bShouldValidate = true;
3714             OSL_VERIFY( xDataSourceSettings->getPropertyValue( s_sFormsCheckRequiredFields ) >>= bShouldValidate );
3715             return bShouldValidate;
3716         }
3717         catch( const Exception& )
3718         {
3719             DBG_UNHANDLED_EXCEPTION();
3720         }
3721 
3722         return sal_True;
3723     }
3724 }
3725 
3726 // XRowSetApproveListener
3727 //------------------------------------------------------------------------------
approveRowChange(const RowChangeEvent & _rEvent)3728 sal_Bool SAL_CALL FormController::approveRowChange(const RowChangeEvent& _rEvent)
3729 {
3730     ::osl::ClearableMutexGuard aGuard( m_aMutex );
3731     impl_checkDisposed_throw();
3732 
3733     ::cppu::OInterfaceIteratorHelper aIter(m_aRowSetApproveListeners);
3734     sal_Bool bValid = sal_True;
3735     if (aIter.hasMoreElements())
3736     {
3737         RowChangeEvent aEvt( _rEvent );
3738         aEvt.Source = *this;
3739         bValid = ((XRowSetApproveListener*)aIter.next())->approveRowChange(aEvt);
3740     }
3741 
3742     if ( !bValid )
3743         return bValid;
3744 
3745     if  (   ( _rEvent.Action != RowChangeAction::INSERT )
3746         &&  ( _rEvent.Action != RowChangeAction::UPDATE )
3747         )
3748         return bValid;
3749 
3750     // if some of the control models are bound to validators, check them
3751     ::rtl::OUString sInvalidityExplanation;
3752     Reference< XControlModel > xInvalidModel;
3753     if ( !checkFormComponentValidity( sInvalidityExplanation, xInvalidModel ) )
3754     {
3755         Reference< XControl > xControl( locateControl( xInvalidModel ) );
3756         aGuard.clear();
3757         displayErrorSetFocus( sInvalidityExplanation, xControl, getDialogParentWindow() );
3758         return false;
3759     }
3760 
3761     // check values on NULL and required flag
3762     if ( !lcl_shouldValidateRequiredFields_nothrow( _rEvent.Source ) )
3763         return sal_True;
3764 
3765     OSL_ENSURE( m_pColumnInfoCache.get(), "FormController::approveRowChange: no column infos!" );
3766     if ( !m_pColumnInfoCache.get() )
3767         return sal_True;
3768 
3769     try
3770     {
3771         if ( !m_pColumnInfoCache->controlsInitialized() )
3772             m_pColumnInfoCache->initializeControls( getControls() );
3773 
3774         size_t colCount = m_pColumnInfoCache->getColumnCount();
3775         for ( size_t col = 0; col < colCount; ++col )
3776         {
3777             const ColumnInfo& rColInfo = m_pColumnInfoCache->getColumnInfo( col );
3778             if ( rColInfo.nNullable != ColumnValue::NO_NULLS )
3779                 continue;
3780 
3781             if ( rColInfo.bAutoIncrement )
3782                 continue;
3783 
3784             if ( rColInfo.bReadOnly )
3785                 continue;
3786 
3787             if ( !rColInfo.xFirstControlWithInputRequired.is() && !rColInfo.xFirstGridWithInputRequiredColumn.is() )
3788                 continue;
3789 
3790             // TODO: in case of binary fields, this "getString" below is extremely expensive
3791             if ( rColInfo.xColumn->getString().getLength() || !rColInfo.xColumn->wasNull() )
3792                 continue;
3793 
3794             String sMessage( SVX_RES( RID_ERR_FIELDREQUIRED ) );
3795             sMessage.SearchAndReplace( '#', rColInfo.sName );
3796 
3797             // the control to focus
3798             Reference< XControl > xControl( rColInfo.xFirstControlWithInputRequired );
3799             if ( !xControl.is() )
3800                 xControl.set( rColInfo.xFirstGridWithInputRequiredColumn, UNO_QUERY );
3801 
3802             aGuard.clear();
3803             displayErrorSetFocus( sMessage, rColInfo.xFirstControlWithInputRequired, getDialogParentWindow() );
3804             return sal_False;
3805         }
3806     }
3807     catch( const Exception& )
3808     {
3809         DBG_UNHANDLED_EXCEPTION();
3810     }
3811 
3812     return true;
3813 }
3814 
3815 //------------------------------------------------------------------------------
approveCursorMove(const EventObject & event)3816 sal_Bool SAL_CALL FormController::approveCursorMove(const EventObject& event)
3817 {
3818     ::osl::MutexGuard aGuard( m_aMutex );
3819     impl_checkDisposed_throw();
3820 
3821     ::cppu::OInterfaceIteratorHelper aIter(m_aRowSetApproveListeners);
3822     if (aIter.hasMoreElements())
3823     {
3824         EventObject aEvt(event);
3825         aEvt.Source = *this;
3826         return ((XRowSetApproveListener*)aIter.next())->approveCursorMove(aEvt);
3827     }
3828 
3829     return sal_True;
3830 }
3831 
3832 //------------------------------------------------------------------------------
approveRowSetChange(const EventObject & event)3833 sal_Bool SAL_CALL FormController::approveRowSetChange(const EventObject& event)
3834 {
3835     ::osl::MutexGuard aGuard( m_aMutex );
3836     impl_checkDisposed_throw();
3837 
3838     ::cppu::OInterfaceIteratorHelper aIter(m_aRowSetApproveListeners);
3839     if (aIter.hasMoreElements())
3840     {
3841         EventObject aEvt(event);
3842         aEvt.Source = *this;
3843         return ((XRowSetApproveListener*)aIter.next())->approveRowSetChange(aEvt);
3844     }
3845 
3846     return sal_True;
3847 }
3848 
3849 // XRowSetApproveBroadcaster
3850 //------------------------------------------------------------------------------
addRowSetApproveListener(const Reference<XRowSetApproveListener> & _rxListener)3851 void SAL_CALL FormController::addRowSetApproveListener(const Reference< XRowSetApproveListener > & _rxListener)
3852 {
3853     ::osl::MutexGuard aGuard( m_aMutex );
3854     impl_checkDisposed_throw();
3855 
3856     m_aRowSetApproveListeners.addInterface(_rxListener);
3857 }
3858 
3859 //------------------------------------------------------------------------------
removeRowSetApproveListener(const Reference<XRowSetApproveListener> & _rxListener)3860 void SAL_CALL FormController::removeRowSetApproveListener(const Reference< XRowSetApproveListener > & _rxListener)
3861 {
3862     ::osl::MutexGuard aGuard( m_aMutex );
3863     impl_checkDisposed_throw();
3864 
3865     m_aRowSetApproveListeners.removeInterface(_rxListener);
3866 }
3867 
3868 // XErrorListener
3869 //------------------------------------------------------------------------------
errorOccured(const SQLErrorEvent & aEvent)3870 void SAL_CALL FormController::errorOccured(const SQLErrorEvent& aEvent)
3871 {
3872     ::osl::ClearableMutexGuard aGuard( m_aMutex );
3873     impl_checkDisposed_throw();
3874 
3875     ::cppu::OInterfaceIteratorHelper aIter(m_aErrorListeners);
3876     if (aIter.hasMoreElements())
3877     {
3878         SQLErrorEvent aEvt(aEvent);
3879         aEvt.Source = *this;
3880         ((XSQLErrorListener*)aIter.next())->errorOccured(aEvt);
3881     }
3882     else
3883     {
3884         aGuard.clear();
3885         displayException( aEvent );
3886     }
3887 }
3888 
3889 // XErrorBroadcaster
3890 //------------------------------------------------------------------------------
addSQLErrorListener(const Reference<XSQLErrorListener> & aListener)3891 void SAL_CALL FormController::addSQLErrorListener(const Reference< XSQLErrorListener > & aListener)
3892 {
3893     ::osl::MutexGuard aGuard( m_aMutex );
3894     impl_checkDisposed_throw();
3895 
3896     m_aErrorListeners.addInterface(aListener);
3897 }
3898 
3899 //------------------------------------------------------------------------------
removeSQLErrorListener(const Reference<XSQLErrorListener> & aListener)3900 void SAL_CALL FormController::removeSQLErrorListener(const Reference< XSQLErrorListener > & aListener)
3901 {
3902     ::osl::MutexGuard aGuard( m_aMutex );
3903     impl_checkDisposed_throw();
3904 
3905     m_aErrorListeners.removeInterface(aListener);
3906 }
3907 
3908 // XDatabaseParameterBroadcaster2
3909 //------------------------------------------------------------------------------
addDatabaseParameterListener(const Reference<XDatabaseParameterListener> & aListener)3910 void SAL_CALL FormController::addDatabaseParameterListener(const Reference< XDatabaseParameterListener > & aListener)
3911 {
3912     ::osl::MutexGuard aGuard( m_aMutex );
3913     impl_checkDisposed_throw();
3914 
3915     m_aParameterListeners.addInterface(aListener);
3916 }
3917 
3918 //------------------------------------------------------------------------------
removeDatabaseParameterListener(const Reference<XDatabaseParameterListener> & aListener)3919 void SAL_CALL FormController::removeDatabaseParameterListener(const Reference< XDatabaseParameterListener > & aListener)
3920 {
3921     ::osl::MutexGuard aGuard( m_aMutex );
3922     impl_checkDisposed_throw();
3923 
3924     m_aParameterListeners.removeInterface(aListener);
3925 }
3926 
3927 // XDatabaseParameterBroadcaster
3928 //------------------------------------------------------------------------------
addParameterListener(const Reference<XDatabaseParameterListener> & aListener)3929 void SAL_CALL FormController::addParameterListener(const Reference< XDatabaseParameterListener > & aListener)
3930 {
3931     FormController::addDatabaseParameterListener( aListener );
3932 }
3933 
3934 //------------------------------------------------------------------------------
removeParameterListener(const Reference<XDatabaseParameterListener> & aListener)3935 void SAL_CALL FormController::removeParameterListener(const Reference< XDatabaseParameterListener > & aListener)
3936 {
3937     FormController::removeDatabaseParameterListener( aListener );
3938 }
3939 
3940 // XDatabaseParameterListener
3941 //------------------------------------------------------------------------------
approveParameter(const DatabaseParameterEvent & aEvent)3942 sal_Bool SAL_CALL FormController::approveParameter(const DatabaseParameterEvent& aEvent)
3943 {
3944     ::vos::OGuard aSolarGuard(Application::GetSolarMutex());
3945     ::osl::MutexGuard aGuard( m_aMutex );
3946     impl_checkDisposed_throw();
3947 
3948     ::cppu::OInterfaceIteratorHelper aIter(m_aParameterListeners);
3949     if (aIter.hasMoreElements())
3950     {
3951         DatabaseParameterEvent aEvt(aEvent);
3952         aEvt.Source = *this;
3953         return ((XDatabaseParameterListener*)aIter.next())->approveParameter(aEvt);
3954     }
3955     else
3956     {
3957         // default handling: instantiate an interaction handler and let it handle the parameter request
3958         try
3959         {
3960             if ( !ensureInteractionHandler() )
3961                 return sal_False;
3962 
3963             // two continuations allowed: OK and Cancel
3964             OParameterContinuation* pParamValues = new OParameterContinuation;
3965             OInteractionAbort* pAbort = new OInteractionAbort;
3966             // the request
3967             ParametersRequest aRequest;
3968             aRequest.Parameters = aEvent.Parameters;
3969             aRequest.Connection = OStaticDataAccessTools().getRowSetConnection(Reference< XRowSet >(aEvent.Source, UNO_QUERY));
3970             OInteractionRequest* pParamRequest = new OInteractionRequest(makeAny(aRequest));
3971             Reference< XInteractionRequest > xParamRequest(pParamRequest);
3972             // some knittings
3973             pParamRequest->addContinuation(pParamValues);
3974             pParamRequest->addContinuation(pAbort);
3975 
3976             // handle the request
3977             m_xInteractionHandler->handle(xParamRequest);
3978 
3979             if (!pParamValues->wasSelected())
3980                 // canceled
3981                 return sal_False;
3982 
3983             // transfer the values into the parameter supplier
3984             Sequence< PropertyValue > aFinalValues = pParamValues->getValues();
3985             if (aFinalValues.getLength() != aRequest.Parameters->getCount())
3986             {
3987                 DBG_ERROR("FormController::approveParameter: the InteractionHandler returned nonsense!");
3988                 return sal_False;
3989             }
3990             const PropertyValue* pFinalValues = aFinalValues.getConstArray();
3991             for (sal_Int32 i=0; i<aFinalValues.getLength(); ++i, ++pFinalValues)
3992             {
3993                 Reference< XPropertySet > xParam;
3994                 ::cppu::extractInterface(xParam, aRequest.Parameters->getByIndex(i));
3995                 if (xParam.is())
3996                 {
3997 #ifdef DBG_UTIL
3998                     ::rtl::OUString sName;
3999                     xParam->getPropertyValue(FM_PROP_NAME) >>= sName;
4000                     DBG_ASSERT(sName.equals(pFinalValues->Name), "FormController::approveParameter: suspicious value names!");
4001 #endif
4002                     try { xParam->setPropertyValue(FM_PROP_VALUE, pFinalValues->Value); }
4003                     catch(Exception&)
4004                     {
4005                         DBG_ERROR("FormController::approveParameter: setting one of the properties failed!");
4006                     }
4007                 }
4008             }
4009         }
4010         catch(Exception&)
4011         {
4012             DBG_UNHANDLED_EXCEPTION();
4013         }
4014     }
4015     return sal_True;
4016 }
4017 
4018 // XConfirmDeleteBroadcaster
4019 //------------------------------------------------------------------------------
addConfirmDeleteListener(const Reference<XConfirmDeleteListener> & aListener)4020 void SAL_CALL FormController::addConfirmDeleteListener(const Reference< XConfirmDeleteListener > & aListener)
4021 {
4022     ::osl::MutexGuard aGuard( m_aMutex );
4023     impl_checkDisposed_throw();
4024 
4025     m_aDeleteListeners.addInterface(aListener);
4026 }
4027 
4028 //------------------------------------------------------------------------------
removeConfirmDeleteListener(const Reference<XConfirmDeleteListener> & aListener)4029 void SAL_CALL FormController::removeConfirmDeleteListener(const Reference< XConfirmDeleteListener > & aListener)
4030 {
4031     ::osl::MutexGuard aGuard( m_aMutex );
4032     impl_checkDisposed_throw();
4033 
4034     m_aDeleteListeners.removeInterface(aListener);
4035 }
4036 
4037 // XConfirmDeleteListener
4038 //------------------------------------------------------------------------------
confirmDelete(const RowChangeEvent & aEvent)4039 sal_Bool SAL_CALL FormController::confirmDelete(const RowChangeEvent& aEvent)
4040 {
4041     ::osl::MutexGuard aGuard( m_aMutex );
4042     impl_checkDisposed_throw();
4043 
4044     ::cppu::OInterfaceIteratorHelper aIter(m_aDeleteListeners);
4045     if (aIter.hasMoreElements())
4046     {
4047         RowChangeEvent aEvt(aEvent);
4048         aEvt.Source = *this;
4049         return ((XConfirmDeleteListener*)aIter.next())->confirmDelete(aEvt);
4050     }
4051     // default handling: instantiate an interaction handler and let it handle the request
4052 
4053     String sTitle;
4054     sal_Int32 nLength = aEvent.Rows;
4055     if ( nLength > 1 )
4056     {
4057         sTitle = SVX_RES( RID_STR_DELETECONFIRM_RECORDS );
4058         sTitle.SearchAndReplace( '#', String::CreateFromInt32( nLength ) );
4059     }
4060     else
4061         sTitle = SVX_RES( RID_STR_DELETECONFIRM_RECORD );
4062 
4063     try
4064     {
4065         if ( !ensureInteractionHandler() )
4066             return sal_False;
4067 
4068         // two continuations allowed: Yes and No
4069         OInteractionApprove* pApprove = new OInteractionApprove;
4070         OInteractionDisapprove* pDisapprove = new OInteractionDisapprove;
4071 
4072         // the request
4073         SQLWarning aWarning;
4074         aWarning.Message = sTitle;
4075         SQLWarning aDetails;
4076         aDetails.Message = String( SVX_RES( RID_STR_DELETECONFIRM ) );
4077         aWarning.NextException <<= aDetails;
4078 
4079         OInteractionRequest* pRequest = new OInteractionRequest( makeAny( aWarning ) );
4080         Reference< XInteractionRequest > xRequest( pRequest );
4081 
4082         // some knittings
4083         pRequest->addContinuation( pApprove );
4084         pRequest->addContinuation( pDisapprove );
4085 
4086         // handle the request
4087         m_xInteractionHandler->handle( xRequest );
4088 
4089         if ( pApprove->wasSelected() )
4090             return sal_True;
4091     }
4092     catch( const Exception& )
4093     {
4094         DBG_UNHANDLED_EXCEPTION();
4095     }
4096 
4097     return sal_False;
4098 }
4099 
4100 //------------------------------------------------------------------------------
invalidateFeatures(const Sequence<::sal_Int16> & _Features)4101 void SAL_CALL FormController::invalidateFeatures( const Sequence< ::sal_Int16 >& _Features )
4102 {
4103     ::osl::MutexGuard aGuard( m_aMutex );
4104     // for now, just copy the ids of the features, because ....
4105     ::std::copy( _Features.getConstArray(), _Features.getConstArray() + _Features.getLength(),
4106         ::std::insert_iterator< ::std::set< sal_Int16 > >( m_aInvalidFeatures, m_aInvalidFeatures.begin() )
4107     );
4108 
4109     // ... we will do the real invalidation asynchronously
4110     if ( !m_aFeatureInvalidationTimer.IsActive() )
4111         m_aFeatureInvalidationTimer.Start();
4112 }
4113 
4114 //------------------------------------------------------------------------------
invalidateAllFeatures()4115 void SAL_CALL FormController::invalidateAllFeatures(  )
4116 {
4117     ::osl::ClearableMutexGuard aGuard( m_aMutex );
4118 
4119     Sequence< sal_Int16 > aInterceptedFeatures( m_aFeatureDispatchers.size() );
4120     ::std::transform(
4121         m_aFeatureDispatchers.begin(),
4122         m_aFeatureDispatchers.end(),
4123         aInterceptedFeatures.getArray(),
4124         ::std::select1st< DispatcherContainer::value_type >()
4125     );
4126 
4127     aGuard.clear();
4128     if ( aInterceptedFeatures.getLength() )
4129         invalidateFeatures( aInterceptedFeatures );
4130 }
4131 
4132 //------------------------------------------------------------------------------
4133 Reference< XDispatch >
interceptedQueryDispatch(const URL & aURL,const::rtl::OUString &,sal_Int32)4134 FormController::interceptedQueryDispatch( const URL& aURL,
4135                                             const ::rtl::OUString& /*aTargetFrameName*/, sal_Int32 /*nSearchFlags*/)
4136 {
4137     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
4138     Reference< XDispatch >  xReturn;
4139     // dispatches handled by ourself
4140     if  (   ( aURL.Complete == FMURL_CONFIRM_DELETION )
4141         ||  (   ( aURL.Complete.equalsAscii( "private:/InteractionHandler" ) )
4142             &&  ensureInteractionHandler()
4143             )
4144         )
4145         xReturn = static_cast< XDispatch* >( this );
4146 
4147     // dispatches of FormSlot-URLs we have to translate
4148     if ( !xReturn.is() && m_xFormOperations.is() )
4149     {
4150         // find the slot id which corresponds to the URL
4151         sal_Int32 nFeatureSlotId = ::svx::FeatureSlotTranslation::getControllerFeatureSlotIdForURL( aURL.Main );
4152         sal_Int16 nFormFeature = ( nFeatureSlotId != -1 ) ? ::svx::FeatureSlotTranslation::getFormFeatureForSlotId( nFeatureSlotId ) : -1;
4153         if ( nFormFeature > 0 )
4154         {
4155             // get the dispatcher for this feature, create if necessary
4156             DispatcherContainer::const_iterator aDispatcherPos = m_aFeatureDispatchers.find( nFormFeature );
4157             if ( aDispatcherPos == m_aFeatureDispatchers.end() )
4158             {
4159                 aDispatcherPos = m_aFeatureDispatchers.insert(
4160                     DispatcherContainer::value_type( nFormFeature, new ::svx::OSingleFeatureDispatcher( aURL, nFormFeature, m_xFormOperations, m_aMutex ) )
4161                 ).first;
4162             }
4163 
4164             OSL_ENSURE( aDispatcherPos->second.is(), "FormController::interceptedQueryDispatch: should have a dispatcher by now!" );
4165             return aDispatcherPos->second;
4166         }
4167     }
4168 
4169     // no more to offer
4170     return xReturn;
4171 }
4172 
4173 //------------------------------------------------------------------------------
dispatch(const URL & _rURL,const Sequence<PropertyValue> & _rArgs)4174 void SAL_CALL FormController::dispatch( const URL& _rURL, const Sequence< PropertyValue >& _rArgs )
4175 {
4176     if ( _rArgs.getLength() != 1 )
4177     {
4178         DBG_ERROR( "FormController::dispatch: no arguments -> no dispatch!" );
4179         return;
4180     }
4181 
4182     if ( _rURL.Complete.equalsAscii( "private:/InteractionHandler" ) )
4183     {
4184         Reference< XInteractionRequest > xRequest;
4185         OSL_VERIFY( _rArgs[0].Value >>= xRequest );
4186         if ( xRequest.is() )
4187             handle( xRequest );
4188         return;
4189     }
4190 
4191     if  ( _rURL.Complete == FMURL_CONFIRM_DELETION )
4192     {
4193         DBG_ERROR( "FormController::dispatch: How do you expect me to return something via this call?" );
4194             // confirmDelete has a return value - dispatch hasn't
4195         return;
4196     }
4197 
4198     DBG_ERROR( "FormController::dispatch: unknown URL!" );
4199 }
4200 
4201 //------------------------------------------------------------------------------
addStatusListener(const Reference<XStatusListener> & _rxListener,const URL & _rURL)4202 void SAL_CALL FormController::addStatusListener( const Reference< XStatusListener >& _rxListener, const URL& _rURL )
4203 {
4204     if (_rURL.Complete == FMURL_CONFIRM_DELETION)
4205     {
4206         if (_rxListener.is())
4207         {   // send an initial statusChanged event
4208             FeatureStateEvent aEvent;
4209             aEvent.FeatureURL = _rURL;
4210             aEvent.IsEnabled = sal_True;
4211             _rxListener->statusChanged(aEvent);
4212             // and don't add the listener at all (the status will never change)
4213         }
4214     }
4215     else
4216         OSL_ENSURE(sal_False, "FormController::addStatusListener: invalid (unsupported) URL!");
4217 }
4218 
4219 //------------------------------------------------------------------------------
getParent()4220 Reference< XInterface > SAL_CALL FormController::getParent()
4221 {
4222     return m_xParent;
4223 }
4224 
4225 //------------------------------------------------------------------------------
setParent(const Reference<XInterface> & Parent)4226 void SAL_CALL FormController::setParent( const Reference< XInterface >& Parent)
4227 {
4228     m_xParent = Parent;
4229 }
4230 
4231 //------------------------------------------------------------------------------
removeStatusListener(const Reference<XStatusListener> &,const URL & _rURL)4232 void SAL_CALL FormController::removeStatusListener( const Reference< XStatusListener >& /*_rxListener*/, const URL& _rURL )
4233 {
4234     (void)_rURL;
4235     OSL_ENSURE(_rURL.Complete == FMURL_CONFIRM_DELETION, "FormController::removeStatusListener: invalid (unsupported) URL!");
4236     // we never really added the listener, so we don't need to remove it
4237 }
4238 
4239 //------------------------------------------------------------------------------
createInterceptor(const Reference<XDispatchProviderInterception> & _xInterception)4240 Reference< XDispatchProviderInterceptor >  FormController::createInterceptor(const Reference< XDispatchProviderInterception > & _xInterception)
4241 {
4242     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
4243 #ifdef DBG_UTIL
4244     // check if we already have a interceptor for the given object
4245     for (   ConstInterceptorsIterator aIter = m_aControlDispatchInterceptors.begin();
4246             aIter != m_aControlDispatchInterceptors.end();
4247             ++aIter
4248         )
4249     {
4250         if ((*aIter)->getIntercepted() == _xInterception)
4251             DBG_ERROR("FormController::createInterceptor : we already do intercept this objects dispatches !");
4252     }
4253 #endif
4254 
4255     DispatchInterceptionMultiplexer* pInterceptor = new DispatchInterceptionMultiplexer( _xInterception, this );
4256     pInterceptor->acquire();
4257     m_aControlDispatchInterceptors.insert( m_aControlDispatchInterceptors.end(), pInterceptor );
4258 
4259     return pInterceptor;
4260 }
4261 
4262 //------------------------------------------------------------------------------
ensureInteractionHandler()4263 bool FormController::ensureInteractionHandler()
4264 {
4265     if ( m_xInteractionHandler.is() )
4266         return true;
4267     if ( m_bAttemptedHandlerCreation )
4268         return false;
4269     m_bAttemptedHandlerCreation = true;
4270 
4271     m_xInteractionHandler.set( m_aContext.createComponent( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.InteractionHandler" ) ) ), UNO_QUERY );
4272     OSL_ENSURE( m_xInteractionHandler.is(), "FormController::ensureInteractionHandler: could not create an interaction handler!" );
4273     return m_xInteractionHandler.is();
4274 }
4275 
4276 //------------------------------------------------------------------------------
handle(const Reference<XInteractionRequest> & _rRequest)4277 void SAL_CALL FormController::handle( const Reference< XInteractionRequest >& _rRequest )
4278 {
4279     if ( !ensureInteractionHandler() )
4280         return;
4281     m_xInteractionHandler->handle( _rRequest );
4282 }
4283 
4284 //------------------------------------------------------------------------------
deleteInterceptor(const Reference<XDispatchProviderInterception> & _xInterception)4285 void FormController::deleteInterceptor(const Reference< XDispatchProviderInterception > & _xInterception)
4286 {
4287     OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" );
4288     // search the interceptor responsible for the given object
4289     InterceptorsIterator aIter;
4290     for (   aIter = m_aControlDispatchInterceptors.begin();
4291             aIter != m_aControlDispatchInterceptors.end();
4292             ++aIter
4293         )
4294     {
4295         if ((*aIter)->getIntercepted() == _xInterception)
4296             break;
4297     }
4298     if (aIter == m_aControlDispatchInterceptors.end())
4299     {
4300         return;
4301     }
4302 
4303     // log off the interception from it's interception object
4304     DispatchInterceptionMultiplexer* pInterceptorImpl = *aIter;
4305     pInterceptorImpl->dispose();
4306     pInterceptorImpl->release();
4307 
4308     // remove the interceptor from our array
4309     m_aControlDispatchInterceptors.erase(aIter);
4310 }
4311 
4312 //--------------------------------------------------------------------
implInvalidateCurrentControlDependentFeatures()4313 void FormController::implInvalidateCurrentControlDependentFeatures()
4314 {
4315     Sequence< sal_Int16 > aCurrentControlDependentFeatures(4);
4316 
4317     aCurrentControlDependentFeatures[0] = FormFeature::SortAscending;
4318     aCurrentControlDependentFeatures[1] = FormFeature::SortDescending;
4319     aCurrentControlDependentFeatures[2] = FormFeature::AutoFilter;
4320     aCurrentControlDependentFeatures[3] = FormFeature::RefreshCurrentControl;
4321 
4322     invalidateFeatures( aCurrentControlDependentFeatures );
4323 }
4324 
4325 //--------------------------------------------------------------------
columnChanged(const EventObject &)4326 void SAL_CALL FormController::columnChanged( const EventObject& /*_event*/ )
4327 {
4328     implInvalidateCurrentControlDependentFeatures();
4329 }
4330 
4331 }   // namespace svxform
4332