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