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