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