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