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