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