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