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