1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_svx.hxx" 30 31 #include "svx/fmgridif.hxx" 32 #include "fmprop.hrc" 33 #include "fmservs.hxx" 34 #include "svx/fmtools.hxx" 35 #include "fmurl.hxx" 36 #include "formcontrolfactory.hxx" 37 #include "gridcell.hxx" 38 #include "sdbdatacolumn.hxx" 39 #include "svx/fmgridcl.hxx" 40 #include "svx/svxids.hrc" 41 #include <tools/urlobj.hxx> 42 43 /** === begin UNO includes === **/ 44 #include <com/sun/star/awt/PosSize.hpp> 45 #include <com/sun/star/beans/PropertyAttribute.hpp> 46 #include <com/sun/star/form/FormComponentType.hpp> 47 #include <com/sun/star/form/XFormComponent.hpp> 48 #include <com/sun/star/form/XLoadable.hpp> 49 #include <com/sun/star/lang/DisposedException.hpp> 50 #include <com/sun/star/sdbc/ResultSetType.hpp> 51 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp> 52 #include <com/sun/star/util/XURLTransformer.hpp> 53 #include <com/sun/star/view/XSelectionSupplier.hpp> 54 #include <com/sun/star/sdbcx/XRowLocate.hpp> 55 /** === end UNO includes === **/ 56 57 #include <comphelper/container.hxx> 58 #include <comphelper/enumhelper.hxx> 59 #include <comphelper/extract.hxx> 60 #include <comphelper/processfactory.hxx> 61 #include <comphelper/property.hxx> 62 #include <comphelper/sequence.hxx> 63 #include <comphelper/types.hxx> 64 #include <cppuhelper/typeprovider.hxx> 65 #include <toolkit/helper/vclunohelper.hxx> 66 #include <tools/diagnose_ex.h> 67 68 using namespace ::svxform; 69 using namespace ::com::sun::star::container; 70 using namespace ::com::sun::star::sdb; 71 using namespace ::com::sun::star::sdbc; 72 using namespace ::com::sun::star::uno; 73 using namespace ::com::sun::star::view; 74 using namespace ::com::sun::star::beans; 75 using namespace ::com::sun::star::lang; 76 using namespace ::com::sun::star::form; 77 using namespace ::com::sun::star::util; 78 using namespace ::com::sun::star; 79 80 using ::com::sun::star::sdbcx::XColumnsSupplier; 81 using ::com::sun::star::frame::XDispatchProviderInterceptor; 82 using ::com::sun::star::frame::XDispatchProvider; 83 using ::com::sun::star::accessibility::XAccessible; 84 using ::com::sun::star::accessibility::XAccessibleContext; 85 using ::com::sun::star::sdb::XRowSetSupplier; 86 using ::com::sun::star::awt::XVclWindowPeer; 87 88 89 //------------------------------------------------------------------ 90 ::com::sun::star::awt::FontDescriptor ImplCreateFontDescriptor( const Font& rFont ) 91 { 92 ::com::sun::star::awt::FontDescriptor aFD; 93 aFD.Name = rFont.GetName(); 94 aFD.StyleName = rFont.GetStyleName(); 95 aFD.Height = (sal_Int16)rFont.GetSize().Height(); 96 aFD.Width = (sal_Int16)rFont.GetSize().Width(); 97 aFD.Family = (sal_Int16)rFont.GetFamily(); 98 aFD.CharSet = rFont.GetCharSet(); 99 aFD.Pitch = (sal_Int16)rFont.GetPitch(); 100 aFD.CharacterWidth = VCLUnoHelper::ConvertFontWidth( rFont.GetWidthType() ); 101 aFD.Weight= VCLUnoHelper::ConvertFontWeight( rFont.GetWeight() ); 102 aFD.Slant = (::com::sun::star::awt::FontSlant)rFont.GetItalic(); 103 aFD.Underline = (sal_Int16)rFont.GetUnderline(); 104 aFD.Strikeout = (sal_Int16)rFont.GetStrikeout(); 105 aFD.Orientation = rFont.GetOrientation(); 106 aFD.Kerning = rFont.IsKerning(); 107 aFD.WordLineMode = rFont.IsWordLineMode(); 108 aFD.Type = 0; // ??? => Nur an Metric... 109 return aFD; 110 } 111 112 //------------------------------------------------------------------ 113 Font ImplCreateFont( const ::com::sun::star::awt::FontDescriptor& rDescr ) 114 { 115 Font aFont; 116 aFont.SetName( rDescr.Name ); 117 aFont.SetStyleName( rDescr.StyleName ); 118 aFont.SetSize( ::Size( rDescr.Width, rDescr.Height ) ); 119 aFont.SetFamily( (FontFamily)rDescr.Family ); 120 aFont.SetCharSet( (CharSet)rDescr.CharSet ); 121 aFont.SetPitch( (FontPitch)rDescr.Pitch ); 122 aFont.SetWidthType( VCLUnoHelper::ConvertFontWidth( rDescr.CharacterWidth ) ); 123 aFont.SetWeight( VCLUnoHelper::ConvertFontWeight( rDescr.Weight ) ); 124 aFont.SetItalic( (FontItalic)rDescr.Slant ); 125 aFont.SetUnderline( (::FontUnderline)rDescr.Underline ); 126 aFont.SetStrikeout( (::FontStrikeout)rDescr.Strikeout ); 127 aFont.SetOrientation( (sal_Int16)rDescr.Orientation ); 128 aFont.SetKerning( rDescr.Kerning ); 129 aFont.SetWordLineMode( rDescr.WordLineMode ); 130 return aFont; 131 } 132 133 //================================================================== 134 //= FmXModifyMultiplexer 135 //================================================================== 136 //------------------------------------------------------------------ 137 FmXModifyMultiplexer::FmXModifyMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex ) 138 :OWeakSubObject( rSource ) 139 ,OInterfaceContainerHelper( _rMutex ) 140 { 141 } 142 143 //------------------------------------------------------------------ 144 Any SAL_CALL FmXModifyMultiplexer::queryInterface(const Type& _rType) throw (RuntimeException) 145 { 146 Any aReturn; 147 aReturn = ::cppu::queryInterface(_rType, 148 static_cast< ::com::sun::star::util::XModifyListener*>(this), 149 static_cast< XEventListener*>(this) 150 ); 151 152 if (!aReturn.hasValue()) 153 aReturn = OWeakSubObject::queryInterface( _rType ); 154 155 return aReturn; 156 } 157 158 //------------------------------------------------------------------ 159 void FmXModifyMultiplexer::disposing(const EventObject& ) throw( RuntimeException ) 160 { 161 } 162 163 //------------------------------------------------------------------ 164 void FmXModifyMultiplexer::modified(const EventObject& e) throw( RuntimeException ) 165 { 166 EventObject aMulti( e); 167 aMulti.Source = &m_rParent; 168 notifyEach( &XModifyListener::modified, aMulti ); 169 } 170 171 //================================================================== 172 //= FmXUpdateMultiplexer 173 //================================================================== 174 //------------------------------------------------------------------ 175 FmXUpdateMultiplexer::FmXUpdateMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex ) 176 :OWeakSubObject( rSource ) 177 ,OInterfaceContainerHelper( _rMutex ) 178 { 179 } 180 181 //------------------------------------------------------------------ 182 Any SAL_CALL FmXUpdateMultiplexer::queryInterface(const Type& _rType) throw (RuntimeException) 183 { 184 Any aReturn; 185 aReturn = ::cppu::queryInterface(_rType, 186 static_cast< XUpdateListener*>(this), 187 static_cast< XEventListener*>(this) 188 ); 189 190 if (!aReturn.hasValue()) 191 aReturn = OWeakSubObject::queryInterface( _rType ); 192 193 return aReturn; 194 } 195 196 //------------------------------------------------------------------ 197 void FmXUpdateMultiplexer::disposing(const EventObject& ) throw( RuntimeException ) 198 { 199 } 200 201 //------------------------------------------------------------------ 202 sal_Bool FmXUpdateMultiplexer::approveUpdate(const EventObject &e) throw( RuntimeException ) 203 { 204 EventObject aMulti( e ); 205 aMulti.Source = &m_rParent; 206 207 sal_Bool bResult = sal_True; 208 if (getLength()) 209 { 210 ::cppu::OInterfaceIteratorHelper aIter(*this); 211 while ( bResult && aIter.hasMoreElements() ) 212 bResult = static_cast< XUpdateListener* >( aIter.next() )->approveUpdate( aMulti ); 213 } 214 215 return bResult; 216 } 217 218 //------------------------------------------------------------------ 219 void FmXUpdateMultiplexer::updated(const EventObject &e) throw( RuntimeException ) 220 { 221 EventObject aMulti( e ); 222 aMulti.Source = &m_rParent; 223 notifyEach( &XUpdateListener::updated, aMulti ); 224 } 225 226 227 //================================================================== 228 //= FmXSelectionMultiplexer 229 //================================================================== 230 //------------------------------------------------------------------ 231 FmXSelectionMultiplexer::FmXSelectionMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex ) 232 :OWeakSubObject( rSource ) 233 ,OInterfaceContainerHelper( _rMutex ) 234 { 235 } 236 237 //------------------------------------------------------------------ 238 Any SAL_CALL FmXSelectionMultiplexer::queryInterface(const Type& _rType) throw (RuntimeException) 239 { 240 Any aReturn; 241 aReturn = ::cppu::queryInterface(_rType, 242 static_cast< XSelectionChangeListener*>(this), 243 static_cast< XEventListener*>(this) 244 ); 245 246 if (!aReturn.hasValue()) 247 aReturn = OWeakSubObject::queryInterface( _rType ); 248 249 return aReturn; 250 } 251 252 //------------------------------------------------------------------ 253 void FmXSelectionMultiplexer::disposing(const EventObject& ) throw( RuntimeException ) 254 { 255 } 256 257 //------------------------------------------------------------------ 258 void SAL_CALL FmXSelectionMultiplexer::selectionChanged( const EventObject& _rEvent ) throw (RuntimeException) 259 { 260 EventObject aMulti(_rEvent); 261 aMulti.Source = &m_rParent; 262 notifyEach( &XSelectionChangeListener::selectionChanged, aMulti ); 263 } 264 265 //================================================================== 266 //= FmXContainerMultiplexer 267 //================================================================== 268 //------------------------------------------------------------------ 269 FmXContainerMultiplexer::FmXContainerMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex ) 270 :OWeakSubObject( rSource ) 271 ,OInterfaceContainerHelper( _rMutex ) 272 { 273 } 274 275 //------------------------------------------------------------------ 276 Any SAL_CALL FmXContainerMultiplexer::queryInterface(const Type& _rType) throw (RuntimeException) 277 { 278 Any aReturn; 279 aReturn = ::cppu::queryInterface(_rType, 280 static_cast< XContainerListener*>(this), 281 static_cast< XEventListener*>(this) 282 ); 283 284 if (!aReturn.hasValue()) 285 aReturn = OWeakSubObject::queryInterface( _rType ); 286 287 return aReturn; 288 } 289 290 //------------------------------------------------------------------ 291 void FmXContainerMultiplexer::disposing(const EventObject& ) throw( RuntimeException ) 292 { 293 } 294 //------------------------------------------------------------------ 295 void FmXContainerMultiplexer::elementInserted(const ContainerEvent& e) throw( RuntimeException ) 296 { 297 ContainerEvent aMulti( e ); 298 aMulti.Source = &m_rParent; 299 notifyEach( &XContainerListener::elementInserted, aMulti ); 300 } 301 302 //------------------------------------------------------------------ 303 void FmXContainerMultiplexer::elementRemoved(const ContainerEvent& e) throw( RuntimeException ) 304 { 305 ContainerEvent aMulti( e ); 306 aMulti.Source = &m_rParent; 307 notifyEach( &XContainerListener::elementRemoved, aMulti ); 308 } 309 310 311 //------------------------------------------------------------------ 312 void FmXContainerMultiplexer::elementReplaced(const ContainerEvent& e) throw( RuntimeException ) 313 { 314 ContainerEvent aMulti( e ); 315 aMulti.Source = &m_rParent; 316 notifyEach( &XContainerListener::elementReplaced, aMulti ); 317 } 318 319 //================================================================== 320 //= FmXGridControlMultiplexer 321 //================================================================== 322 //------------------------------------------------------------------ 323 FmXGridControlMultiplexer::FmXGridControlMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex ) 324 :OWeakSubObject( rSource ) 325 ,OInterfaceContainerHelper( _rMutex ) 326 { 327 } 328 329 //------------------------------------------------------------------ 330 Any SAL_CALL FmXGridControlMultiplexer::queryInterface(const Type& _rType) throw (RuntimeException) 331 { 332 Any aReturn; 333 aReturn = ::cppu::queryInterface( _rType, 334 static_cast< XGridControlListener*>(this) 335 ); 336 337 if (!aReturn.hasValue()) 338 aReturn = OWeakSubObject::queryInterface( _rType ); 339 340 return aReturn; 341 } 342 343 //------------------------------------------------------------------ 344 void FmXGridControlMultiplexer::disposing( const EventObject& ) throw( RuntimeException ) 345 { 346 } 347 348 //------------------------------------------------------------------ 349 void SAL_CALL FmXGridControlMultiplexer::columnChanged( const EventObject& _event ) throw (RuntimeException) 350 { 351 EventObject aForwardedEvent( _event ); 352 aForwardedEvent.Source = &m_rParent; 353 notifyEach( &XGridControlListener::columnChanged, aForwardedEvent ); 354 } 355 356 //================================================================== 357 //= FmXGridControl 358 //================================================================== 359 360 //------------------------------------------------------------------ 361 Reference< XInterface > SAL_CALL FmXGridControl_NewInstance_Impl(const Reference< XMultiServiceFactory>& _rxFactory) 362 { 363 return *(new FmXGridControl(_rxFactory)); 364 } 365 DBG_NAME(FmXGridControl ) 366 //------------------------------------------------------------------------------ 367 FmXGridControl::FmXGridControl(const Reference< XMultiServiceFactory >& _rxFactory) 368 :UnoControl( _rxFactory) 369 ,m_aModifyListeners(*this, GetMutex()) 370 ,m_aUpdateListeners(*this, GetMutex()) 371 ,m_aContainerListeners(*this, GetMutex()) 372 ,m_aSelectionListeners(*this, GetMutex()) 373 ,m_aGridControlListeners(*this, GetMutex()) 374 ,m_nPeerCreationLevel(0) 375 ,m_bInDraw(sal_False) 376 ,m_xServiceFactory(_rxFactory) 377 { 378 DBG_CTOR(FmXGridControl ,NULL); 379 } 380 381 //------------------------------------------------------------------------------ 382 FmXGridControl::~FmXGridControl() 383 { 384 DBG_DTOR(FmXGridControl ,NULL); 385 } 386 387 //------------------------------------------------------------------ 388 Any SAL_CALL FmXGridControl::queryAggregation(const Type& _rType) throw (RuntimeException) 389 { 390 Any aReturn = FmXGridControl_BASE::queryInterface(_rType); 391 392 if (!aReturn.hasValue()) 393 aReturn = UnoControl::queryAggregation( _rType ); 394 return aReturn; 395 } 396 397 //------------------------------------------------------------------ 398 Sequence< Type> SAL_CALL FmXGridControl::getTypes( ) throw(RuntimeException) 399 { 400 return comphelper::concatSequences(UnoControl::getTypes(),FmXGridControl_BASE::getTypes()); 401 } 402 403 //------------------------------------------------------------------ 404 Sequence<sal_Int8> SAL_CALL FmXGridControl::getImplementationId( ) throw(RuntimeException) 405 { 406 static ::cppu::OImplementationId* pId = 0; 407 if (! pId) 408 { 409 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 410 if (! pId) 411 { 412 static ::cppu::OImplementationId aId; 413 pId = &aId; 414 } 415 } 416 return pId->getImplementationId(); 417 } 418 419 // XServiceInfo 420 //------------------------------------------------------------------------------ 421 sal_Bool SAL_CALL FmXGridControl::supportsService(const ::rtl::OUString& ServiceName) throw() 422 { 423 ::comphelper::StringSequence aSupported = getSupportedServiceNames(); 424 const ::rtl::OUString * pArray = aSupported.getConstArray(); 425 for( sal_Int32 i = 0; i < aSupported.getLength(); i++ ) 426 if( pArray[i] == ServiceName ) 427 return sal_True; 428 return sal_False; 429 } 430 431 //------------------------------------------------------------------------------ 432 ::rtl::OUString SAL_CALL FmXGridControl::getImplementationName() throw() 433 { 434 return ::rtl::OUString::createFromAscii("com.sun.star.form.FmXGridControl"); 435 } 436 437 //------------------------------------------------------------------------------ 438 ::comphelper::StringSequence SAL_CALL FmXGridControl::getSupportedServiceNames() throw() 439 { 440 Sequence< ::rtl::OUString > aServiceNames(2); 441 aServiceNames[0] = FM_SUN_CONTROL_GRIDCONTROL; 442 aServiceNames[1] = ::rtl::OUString::createFromAscii("com.sun.star.awt.UnoControl"); 443 return aServiceNames; 444 } 445 446 //------------------------------------------------------------------------------ 447 void SAL_CALL FmXGridControl::dispose() throw( RuntimeException ) 448 { 449 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 450 451 EventObject aEvt; 452 aEvt.Source = static_cast< ::cppu::OWeakObject* >(this); 453 m_aModifyListeners.disposeAndClear(aEvt); 454 m_aUpdateListeners.disposeAndClear(aEvt); 455 m_aContainerListeners.disposeAndClear(aEvt); 456 457 UnoControl::dispose(); 458 } 459 460 //------------------------------------------------------------------------------ 461 ::rtl::OUString FmXGridControl::GetComponentServiceName() 462 { 463 ::rtl::OUString aName = ::rtl::OUString::createFromAscii("DBGrid"); 464 return aName; 465 } 466 467 //------------------------------------------------------------------------------ 468 sal_Bool SAL_CALL FmXGridControl::setModel(const Reference< ::com::sun::star::awt::XControlModel >& rModel) throw( RuntimeException ) 469 { 470 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 471 472 if (!UnoControl::setModel(rModel)) 473 return sal_False; 474 475 Reference< XGridPeer > xGridPeer(getPeer(), UNO_QUERY); 476 if (xGridPeer.is()) 477 { 478 Reference< XIndexContainer > xCols(mxModel, UNO_QUERY); 479 xGridPeer->setColumns(xCols); 480 } 481 return sal_True; 482 } 483 484 //------------------------------------------------------------------------------ 485 FmXGridPeer* FmXGridControl::imp_CreatePeer(Window* pParent) 486 { 487 FmXGridPeer* pReturn = new FmXGridPeer(m_xServiceFactory); 488 489 // translate properties into WinBits 490 WinBits nStyle = WB_TABSTOP; 491 Reference< XPropertySet > xModelSet(getModel(), UNO_QUERY); 492 if (xModelSet.is()) 493 { 494 try 495 { 496 if (::comphelper::getINT16(xModelSet->getPropertyValue(FM_PROP_BORDER))) 497 nStyle |= WB_BORDER; 498 } 499 catch(const Exception&) 500 { 501 OSL_ASSERT(!"Can not get style"); 502 } 503 } 504 505 pReturn->Create(pParent, nStyle); 506 return pReturn; 507 } 508 509 //------------------------------------------------------------------------------ 510 void SAL_CALL FmXGridControl::createPeer(const Reference< ::com::sun::star::awt::XToolkit >& /*rToolkit*/, const Reference< ::com::sun::star::awt::XWindowPeer >& rParentPeer) throw( RuntimeException ) 511 { 512 if ( !mxModel.is() ) 513 throw DisposedException( ::rtl::OUString(), *this ); 514 515 DBG_ASSERT(/*(0 == m_nPeerCreationLevel) && */!mbCreatingPeer, "FmXGridControl::createPeer : recursion!"); 516 // I think this should never assert, now that we're using the base class' mbCreatingPeer in addition to 517 // our own m_nPeerCreationLevel 518 // But I'm not sure as I don't _fully_ understand the underlying toolkit implementations .... 519 // (if this asserts, we still need m_nPeerCreationLevel. If not, we could omit it ....) 520 // 14.05.2001 - 86836 - frank.schoenheit@germany.sun.com 521 522 // TODO: why the hell this whole class does not use any mutex? 523 524 if (!getPeer().is()) 525 { 526 mbCreatingPeer = sal_True; 527 // mbCreatingPeer is virtually the same as m_nPeerCreationLevel, but it's the base class' method 528 // to prevent recursion. 529 530 Window* pParentWin = NULL; 531 if (rParentPeer.is()) 532 { 533 VCLXWindow* pParent = VCLXWindow::GetImplementation(rParentPeer); 534 if (pParent) 535 pParentWin = pParent->GetWindow(); 536 } 537 538 FmXGridPeer* pPeer = imp_CreatePeer(pParentWin); 539 DBG_ASSERT(pPeer != NULL, "FmXGridControl::createPeer : imp_CreatePeer didn't return a peer !"); 540 setPeer( pPeer ); 541 542 // lesen der properties aus dem model 543 // ++m_nPeerCreationLevel; 544 updateFromModel(); 545 546 // folgendes unschoene Szenario : updateFromModel fuehrt zu einem propertiesChanged am Control, 547 // das stellt fest, dass sich eine 'kritische' Property geaendert hat (zum Beispiel "Border") und 548 // legt daraufhin eine neue Peer an, was wieder hier im createPeer landet, wir legen also eine 549 // zweite FmXGridPeer an und initialisieren die. Dann kommen wir in der ersten Inkarnation aus 550 // dem updsateFromModel raus und arbeiten dort weiter mit dem pPeer, das jetzt eigentlich schon 551 // veraltet ist (da ja in der zweiten Inkarnation eine andere Peer angelegt wurde). 552 // Deswegen also der Aufwand mit dem PeerCreationLevel, das stellt sicher, dass wir die in dem 553 // tiefsten Level angelegte Peer wirklich verwenden, sie aber erst im top-level 554 // initialisieren. 555 // if (--m_nPeerCreationLevel == 0) 556 { 557 DBG_ASSERT(getPeer().is(), "FmXGridControl::createPeer : something went wrong ... no top level peer !"); 558 pPeer = FmXGridPeer::getImplementation(getPeer()); 559 560 setPosSize( maComponentInfos.nX, maComponentInfos.nY, maComponentInfos.nWidth, maComponentInfos.nHeight, ::com::sun::star::awt::PosSize::POSSIZE ); 561 562 Reference< XIndexContainer > xColumns(getModel(), UNO_QUERY); 563 if (xColumns.is()) 564 pPeer->setColumns(xColumns); 565 566 if (maComponentInfos.bVisible) 567 pPeer->setVisible(sal_True); 568 569 if (!maComponentInfos.bEnable) 570 pPeer->setEnable(sal_False); 571 572 if (maWindowListeners.getLength()) 573 pPeer->addWindowListener( &maWindowListeners ); 574 575 if (maFocusListeners.getLength()) 576 pPeer->addFocusListener( &maFocusListeners ); 577 578 if (maKeyListeners.getLength()) 579 pPeer->addKeyListener( &maKeyListeners ); 580 581 if (maMouseListeners.getLength()) 582 pPeer->addMouseListener( &maMouseListeners ); 583 584 if (maMouseMotionListeners.getLength()) 585 pPeer->addMouseMotionListener( &maMouseMotionListeners ); 586 587 if (maPaintListeners.getLength()) 588 pPeer->addPaintListener( &maPaintListeners ); 589 590 if (m_aModifyListeners.getLength()) 591 pPeer->addModifyListener( &m_aModifyListeners ); 592 593 if (m_aUpdateListeners.getLength()) 594 pPeer->addUpdateListener( &m_aUpdateListeners ); 595 596 if (m_aContainerListeners.getLength()) 597 pPeer->addContainerListener( &m_aContainerListeners ); 598 599 // forward the design mode 600 sal_Bool bForceAlivePeer = m_bInDraw && !maComponentInfos.bVisible; 601 // (we force a alive-mode peer if we're in "draw", cause in this case the peer will be used for drawing in 602 // foreign devices. We ensure this with the visibility check as an living peer is assumed to be noncritical 603 // only if invisible) 604 Any aOldCursorBookmark; 605 if (!mbDesignMode || bForceAlivePeer) 606 { 607 Reference< XFormComponent > xComp(getModel(), UNO_QUERY); 608 if (xComp.is()) 609 { 610 Reference< XRowSet > xForm(xComp->getParent(), UNO_QUERY); 611 // is the form alive? 612 // we can see that if the form contains columns 613 Reference< ::com::sun::star::sdbcx::XColumnsSupplier > xColumnsSupplier(xForm, UNO_QUERY); 614 if (xColumnsSupplier.is()) 615 { 616 if (Reference< XIndexAccess > (xColumnsSupplier->getColumns(),UNO_QUERY)->getCount()) 617 { 618 // we get only a new bookmark if the resultset is not forwardonly 619 if (::comphelper::getINT32(Reference< XPropertySet > (xForm, UNO_QUERY)->getPropertyValue(FM_PROP_RESULTSET_TYPE)) != ResultSetType::FORWARD_ONLY) 620 { 621 // as the FmGridControl touches the data source it is connected to we have to remember the current 622 // cursor position (and restore afterwards) 623 // OJ: but only when we stand on a valid row 624 Reference< XResultSet > xResultSet(xForm, UNO_QUERY); 625 if ( !xResultSet->isBeforeFirst() && !xResultSet->isAfterLast() ) 626 { 627 try 628 { 629 aOldCursorBookmark = Reference< ::com::sun::star::sdbcx::XRowLocate > (xForm, UNO_QUERY)->getBookmark(); 630 } 631 catch( const Exception& e ) 632 { 633 DBG_UNHANDLED_EXCEPTION(); 634 (void)e; 635 } 636 } 637 } 638 } 639 } 640 pPeer->setRowSet(xForm); 641 } 642 } 643 pPeer->setDesignMode(mbDesignMode && !bForceAlivePeer); 644 645 try 646 { 647 if (aOldCursorBookmark.hasValue()) 648 { // we have a valid bookmark, so we have to restore the cursor's position 649 Reference< XFormComponent > xComp(getModel(), UNO_QUERY); 650 Reference< ::com::sun::star::sdbcx::XRowLocate > xLocate(xComp->getParent(), UNO_QUERY); 651 xLocate->moveToBookmark(aOldCursorBookmark); 652 } 653 } 654 catch( const Exception& e ) 655 { 656 DBG_UNHANDLED_EXCEPTION(); 657 (void)e; 658 } 659 660 Reference< ::com::sun::star::awt::XView > xPeerView(getPeer(), UNO_QUERY); 661 xPeerView->setZoom( maComponentInfos.nZoomX, maComponentInfos.nZoomY ); 662 xPeerView->setGraphics( mxGraphics ); 663 } 664 mbCreatingPeer = sal_False; 665 } 666 } 667 668 //------------------------------------------------------------------------------ 669 void FmXGridControl::addModifyListener(const Reference< ::com::sun::star::util::XModifyListener >& l) throw( RuntimeException ) 670 { 671 m_aModifyListeners.addInterface( l ); 672 if( getPeer().is() && m_aModifyListeners.getLength() == 1 ) 673 { 674 Reference< ::com::sun::star::util::XModifyBroadcaster > xGrid(getPeer(), UNO_QUERY); 675 xGrid->addModifyListener( &m_aModifyListeners); 676 } 677 } 678 679 //------------------------------------------------------------------------------ 680 sal_Bool SAL_CALL FmXGridControl::select( const Any& _rSelection ) throw (IllegalArgumentException, RuntimeException) 681 { 682 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 683 Reference< XSelectionSupplier > xPeer(getPeer(), UNO_QUERY); 684 return xPeer->select(_rSelection); 685 } 686 687 //------------------------------------------------------------------------------ 688 Any SAL_CALL FmXGridControl::getSelection( ) throw (RuntimeException) 689 { 690 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 691 Reference< XSelectionSupplier > xPeer(getPeer(), UNO_QUERY); 692 return xPeer->getSelection(); 693 } 694 695 //------------------------------------------------------------------------------ 696 void SAL_CALL FmXGridControl::addSelectionChangeListener( const Reference< XSelectionChangeListener >& _rxListener ) throw (RuntimeException) 697 { 698 m_aSelectionListeners.addInterface( _rxListener ); 699 if( getPeer().is() && 1 == m_aSelectionListeners.getLength() ) 700 { 701 Reference< XSelectionSupplier > xGrid(getPeer(), UNO_QUERY); 702 xGrid->addSelectionChangeListener( &m_aSelectionListeners); 703 } 704 } 705 706 //------------------------------------------------------------------------------ 707 void SAL_CALL FmXGridControl::removeSelectionChangeListener( const Reference< XSelectionChangeListener >& _rxListener ) throw (RuntimeException) 708 { 709 if( getPeer().is() && 1 == m_aSelectionListeners.getLength() ) 710 { 711 Reference< XSelectionSupplier > xGrid(getPeer(), UNO_QUERY); 712 xGrid->removeSelectionChangeListener( &m_aSelectionListeners); 713 } 714 m_aSelectionListeners.removeInterface( _rxListener ); 715 } 716 717 //------------------------------------------------------------------------------ 718 Sequence< sal_Bool > SAL_CALL FmXGridControl::queryFieldDataType( const Type& xType ) throw(RuntimeException) 719 { 720 if (getPeer().is()) 721 { 722 Reference< XGridFieldDataSupplier > xPeerSupplier(getPeer(), UNO_QUERY); 723 if (xPeerSupplier.is()) 724 return xPeerSupplier->queryFieldDataType(xType); 725 } 726 727 return Sequence<sal_Bool>(); 728 } 729 730 //------------------------------------------------------------------------------ 731 Sequence< Any > SAL_CALL FmXGridControl::queryFieldData( sal_Int32 nRow, const Type& xType ) throw(RuntimeException) 732 { 733 if (getPeer().is()) 734 { 735 Reference< XGridFieldDataSupplier > xPeerSupplier(getPeer(), UNO_QUERY); 736 if (xPeerSupplier.is()) 737 return xPeerSupplier->queryFieldData(nRow, xType); 738 } 739 740 return Sequence< Any>(); 741 } 742 743 //------------------------------------------------------------------------------ 744 void SAL_CALL FmXGridControl::removeModifyListener(const Reference< ::com::sun::star::util::XModifyListener >& l) throw( RuntimeException ) 745 { 746 if( getPeer().is() && m_aModifyListeners.getLength() == 1 ) 747 { 748 Reference< ::com::sun::star::util::XModifyBroadcaster > xGrid(getPeer(), UNO_QUERY); 749 xGrid->removeModifyListener( &m_aModifyListeners); 750 } 751 m_aModifyListeners.removeInterface( l ); 752 } 753 754 //------------------------------------------------------------------------------ 755 void SAL_CALL FmXGridControl::draw( sal_Int32 x, sal_Int32 y ) throw( RuntimeException ) 756 { 757 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 758 m_bInDraw = sal_True; 759 UnoControl::draw(x, y); 760 m_bInDraw = sal_False; 761 } 762 763 //------------------------------------------------------------------------------ 764 void SAL_CALL FmXGridControl::setDesignMode(sal_Bool bOn) throw( RuntimeException ) 765 { 766 ::com::sun::star::util::ModeChangeEvent aModeChangeEvent; 767 768 // --- <mutex_lock> --- 769 { 770 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 771 772 Reference< XRowSetSupplier > xGrid(getPeer(), UNO_QUERY); 773 774 if (xGrid.is() && (bOn != mbDesignMode || (!bOn && !xGrid->getRowSet().is()))) 775 { 776 if (bOn) 777 { 778 xGrid->setRowSet(Reference< XRowSet > ()); 779 } 780 else 781 { 782 Reference< XFormComponent > xComp(getModel(), UNO_QUERY); 783 if (xComp.is()) 784 { 785 Reference< XRowSet > xForm(xComp->getParent(), UNO_QUERY); 786 xGrid->setRowSet(xForm); 787 } 788 } 789 790 mbDesignMode = bOn; 791 792 Reference< XVclWindowPeer > xVclWindowPeer( getPeer(), UNO_QUERY ); 793 if (xVclWindowPeer.is()) 794 xVclWindowPeer->setDesignMode(bOn); 795 } 796 mbDesignMode = bOn; 797 798 // dispose our current AccessibleContext, if we have one 799 // (changing the design mode implies having a new implementation for this context, 800 // so the old one must be declared DEFUNC) 801 disposeAccessibleContext(); 802 803 // prepare firing an event 804 aModeChangeEvent.Source = *this; 805 aModeChangeEvent.NewMode = ::rtl::OUString::createFromAscii( mbDesignMode ? "design" : "alive" ); 806 } 807 808 // --- </mutex_lock> --- 809 maModeChangeListeners.notifyEach( &XModeChangeListener::modeChanged, aModeChangeEvent ); 810 } 811 812 // XBoundComponent 813 //------------------------------------------------------------------------------ 814 void SAL_CALL FmXGridControl::addUpdateListener(const Reference< XUpdateListener >& l) throw( RuntimeException ) 815 { 816 m_aUpdateListeners.addInterface( l ); 817 if( getPeer().is() && m_aUpdateListeners.getLength() == 1 ) 818 { 819 Reference< XBoundComponent > xBound(getPeer(), UNO_QUERY); 820 xBound->addUpdateListener( &m_aUpdateListeners); 821 } 822 } 823 824 //------------------------------------------------------------------------------ 825 void SAL_CALL FmXGridControl::removeUpdateListener(const Reference< XUpdateListener >& l) throw( RuntimeException ) 826 { 827 if( getPeer().is() && m_aUpdateListeners.getLength() == 1 ) 828 { 829 Reference< XBoundComponent > xBound(getPeer(), UNO_QUERY); 830 xBound->removeUpdateListener( &m_aUpdateListeners); 831 } 832 m_aUpdateListeners.removeInterface( l ); 833 } 834 835 //------------------------------------------------------------------------------ 836 sal_Bool SAL_CALL FmXGridControl::commit() throw( RuntimeException ) 837 { 838 Reference< XBoundComponent > xBound(getPeer(), UNO_QUERY); 839 if (xBound.is()) 840 return xBound->commit(); 841 else 842 return sal_True; 843 } 844 845 // XContainer 846 //------------------------------------------------------------------------------ 847 void SAL_CALL FmXGridControl::addContainerListener(const Reference< XContainerListener >& l) throw( RuntimeException ) 848 { 849 m_aContainerListeners.addInterface( l ); 850 if( getPeer().is() && m_aContainerListeners.getLength() == 1 ) 851 { 852 Reference< XContainer > xContainer(getPeer(), UNO_QUERY); 853 xContainer->addContainerListener( &m_aContainerListeners); 854 } 855 } 856 857 //------------------------------------------------------------------------------ 858 void SAL_CALL FmXGridControl::removeContainerListener(const Reference< XContainerListener >& l) throw( RuntimeException ) 859 { 860 if( getPeer().is() && m_aContainerListeners.getLength() == 1 ) 861 { 862 Reference< XContainer > xContainer(getPeer(), UNO_QUERY); 863 xContainer->removeContainerListener( &m_aContainerListeners); 864 } 865 m_aContainerListeners.removeInterface( l ); 866 } 867 868 //------------------------------------------------------------------------------ 869 Reference< ::com::sun::star::frame::XDispatch > SAL_CALL FmXGridControl::queryDispatch(const ::com::sun::star::util::URL& aURL, const ::rtl::OUString& aTargetFrameName, sal_Int32 nSearchFlags) throw( RuntimeException ) 870 { 871 Reference< ::com::sun::star::frame::XDispatchProvider > xPeerProvider(getPeer(), UNO_QUERY); 872 if (xPeerProvider.is()) 873 return xPeerProvider->queryDispatch(aURL, aTargetFrameName, nSearchFlags); 874 else 875 return Reference< ::com::sun::star::frame::XDispatch > (); 876 } 877 878 //------------------------------------------------------------------------------ 879 Sequence< Reference< ::com::sun::star::frame::XDispatch > > SAL_CALL FmXGridControl::queryDispatches(const Sequence< ::com::sun::star::frame::DispatchDescriptor>& aDescripts) throw( RuntimeException ) 880 { 881 Reference< ::com::sun::star::frame::XDispatchProvider > xPeerProvider(getPeer(), UNO_QUERY); 882 if (xPeerProvider.is()) 883 return xPeerProvider->queryDispatches(aDescripts); 884 else 885 return Sequence< Reference< ::com::sun::star::frame::XDispatch > >(); 886 } 887 888 //------------------------------------------------------------------------------ 889 void SAL_CALL FmXGridControl::registerDispatchProviderInterceptor(const Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& _xInterceptor) throw( RuntimeException ) 890 { 891 Reference< ::com::sun::star::frame::XDispatchProviderInterception > xPeerInterception(getPeer(), UNO_QUERY); 892 if (xPeerInterception.is()) 893 xPeerInterception->registerDispatchProviderInterceptor(_xInterceptor); 894 } 895 896 //------------------------------------------------------------------------------ 897 void SAL_CALL FmXGridControl::releaseDispatchProviderInterceptor(const Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& _xInterceptor) throw( RuntimeException ) 898 { 899 Reference< ::com::sun::star::frame::XDispatchProviderInterception > xPeerInterception(getPeer(), UNO_QUERY); 900 if (xPeerInterception.is()) 901 xPeerInterception->releaseDispatchProviderInterceptor(_xInterceptor); 902 } 903 904 //------------------------------------------------------------------------------ 905 void SAL_CALL FmXGridControl::addGridControlListener( const Reference< XGridControlListener >& _listener ) throw( RuntimeException ) 906 { 907 ::osl::MutexGuard aGuard( GetMutex() ); 908 909 m_aGridControlListeners.addInterface( _listener ); 910 if ( getPeer().is() && 1 == m_aGridControlListeners.getLength() ) 911 { 912 Reference< XGridControl > xPeerGrid( getPeer(), UNO_QUERY ); 913 if ( xPeerGrid.is() ) 914 xPeerGrid->addGridControlListener( &m_aGridControlListeners ); 915 } 916 } 917 918 //------------------------------------------------------------------------------ 919 void SAL_CALL FmXGridControl::removeGridControlListener( const Reference< XGridControlListener >& _listener ) throw( RuntimeException ) 920 { 921 ::osl::MutexGuard aGuard( GetMutex() ); 922 923 if( getPeer().is() && 1 == m_aGridControlListeners.getLength() ) 924 { 925 Reference< XGridControl > xPeerGrid( getPeer(), UNO_QUERY ); 926 if ( xPeerGrid.is() ) 927 xPeerGrid->removeGridControlListener( &m_aGridControlListeners ); 928 } 929 930 m_aGridControlListeners.removeInterface( _listener ); 931 } 932 933 //------------------------------------------------------------------------------ 934 sal_Int16 SAL_CALL FmXGridControl::getCurrentColumnPosition() throw( RuntimeException ) 935 { 936 Reference< XGridControl > xGrid( getPeer(), UNO_QUERY ); 937 return xGrid.is() ? xGrid->getCurrentColumnPosition() : -1; 938 } 939 940 //------------------------------------------------------------------------------ 941 void SAL_CALL FmXGridControl::setCurrentColumnPosition(sal_Int16 nPos) throw( RuntimeException ) 942 { 943 Reference< XGridControl > xGrid( getPeer(), UNO_QUERY ); 944 if ( xGrid.is() ) 945 { 946 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 947 xGrid->setCurrentColumnPosition( nPos ); 948 } 949 } 950 951 // XElementAccess 952 //------------------------------------------------------------------------------ 953 sal_Bool SAL_CALL FmXGridControl::hasElements() throw( RuntimeException ) 954 { 955 Reference< XElementAccess > xPeer(getPeer(), UNO_QUERY); 956 return xPeer.is() ? xPeer->hasElements() : 0; 957 } 958 959 //------------------------------------------------------------------------------ 960 Type SAL_CALL FmXGridControl::getElementType( ) throw(RuntimeException) 961 { 962 return ::getCppuType((const Reference< ::com::sun::star::awt::XTextComponent >*)NULL); 963 } 964 965 // XEnumerationAccess 966 //------------------------------------------------------------------------------ 967 Reference< XEnumeration > SAL_CALL FmXGridControl::createEnumeration() throw( RuntimeException ) 968 { 969 Reference< XEnumerationAccess > xPeer(getPeer(), UNO_QUERY); 970 if (xPeer.is()) 971 return xPeer->createEnumeration(); 972 else 973 return new ::comphelper::OEnumerationByIndex(this); 974 } 975 976 // XIndexAccess 977 //------------------------------------------------------------------------------ 978 sal_Int32 SAL_CALL FmXGridControl::getCount() throw( RuntimeException ) 979 { 980 Reference< XIndexAccess > xPeer(getPeer(), UNO_QUERY); 981 return xPeer.is() ? xPeer->getCount() : 0; 982 } 983 984 //------------------------------------------------------------------------------ 985 Any SAL_CALL FmXGridControl::getByIndex(sal_Int32 _nIndex) throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) 986 { 987 Reference< XIndexAccess > xPeer(getPeer(), UNO_QUERY); 988 if (!xPeer.is()) 989 throw IndexOutOfBoundsException(); 990 991 return xPeer->getByIndex(_nIndex); 992 } 993 994 // ::com::sun::star::util::XModeSelector 995 //------------------------------------------------------------------------------ 996 void SAL_CALL FmXGridControl::setMode(const ::rtl::OUString& Mode) throw( NoSupportException, RuntimeException ) 997 { 998 Reference< ::com::sun::star::util::XModeSelector > xPeer(getPeer(), UNO_QUERY); 999 if (!xPeer.is()) 1000 throw NoSupportException(); 1001 1002 xPeer->setMode(Mode); 1003 } 1004 1005 //------------------------------------------------------------------------------ 1006 ::rtl::OUString SAL_CALL FmXGridControl::getMode() throw( RuntimeException ) 1007 { 1008 Reference< ::com::sun::star::util::XModeSelector > xPeer(getPeer(), UNO_QUERY); 1009 return xPeer.is() ? xPeer->getMode() : ::rtl::OUString(); 1010 } 1011 1012 //------------------------------------------------------------------------------ 1013 ::comphelper::StringSequence SAL_CALL FmXGridControl::getSupportedModes() throw( RuntimeException ) 1014 { 1015 Reference< ::com::sun::star::util::XModeSelector > xPeer(getPeer(), UNO_QUERY); 1016 return xPeer.is() ? xPeer->getSupportedModes() : ::comphelper::StringSequence(); 1017 } 1018 1019 //------------------------------------------------------------------------------ 1020 sal_Bool SAL_CALL FmXGridControl::supportsMode(const ::rtl::OUString& Mode) throw( RuntimeException ) 1021 { 1022 Reference< ::com::sun::star::util::XModeSelector > xPeer(getPeer(), UNO_QUERY); 1023 return xPeer.is() ? xPeer->supportsMode(Mode) : sal_False; 1024 } 1025 1026 //============================================================================== 1027 //= FmXGridPeer 1028 //============================================================================== 1029 // helper class which prevents that in the peer's header the FmGridListener must be known 1030 class FmXGridPeer::GridListenerDelegator : public FmGridListener 1031 { 1032 protected: 1033 FmXGridPeer* m_pPeer; 1034 1035 public: 1036 GridListenerDelegator( FmXGridPeer* _pPeer ); 1037 1038 protected: 1039 virtual void selectionChanged(); 1040 virtual void columnChanged(); 1041 }; 1042 1043 //------------------------------------------------------------------ 1044 FmXGridPeer::GridListenerDelegator::GridListenerDelegator(FmXGridPeer* _pPeer) 1045 :m_pPeer(_pPeer) 1046 { 1047 DBG_ASSERT(m_pPeer, "GridListenerDelegator::GridListenerDelegator"); 1048 } 1049 1050 //------------------------------------------------------------------ 1051 void FmXGridPeer::GridListenerDelegator::selectionChanged() 1052 { 1053 m_pPeer->selectionChanged(); 1054 } 1055 1056 //------------------------------------------------------------------ 1057 void FmXGridPeer::GridListenerDelegator::columnChanged() 1058 { 1059 m_pPeer->columnChanged(); 1060 } 1061 1062 //============================================================================== 1063 //------------------------------------------------------------------ 1064 Reference< XInterface > FmXGridPeer_CreateInstance(const Reference< XMultiServiceFactory>& _rxFactory) 1065 { 1066 FmXGridPeer* pNewObject = new FmXGridPeer(_rxFactory); 1067 pNewObject->Create(NULL, WB_TABSTOP); 1068 return *pNewObject; 1069 } 1070 1071 //------------------------------------------------------------------ 1072 Sequence< Type> SAL_CALL FmXGridPeer::getTypes( ) throw(RuntimeException) 1073 { 1074 return comphelper::concatSequences( VCLXWindow::getTypes(), FmXGridPeer_BASE::getTypes() ); 1075 } 1076 1077 //------------------------------------------------------------------ 1078 Sequence<sal_Int8> SAL_CALL FmXGridPeer::getImplementationId( ) throw(RuntimeException) 1079 { 1080 static ::cppu::OImplementationId* pId = 0; 1081 if (! pId) 1082 { 1083 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 1084 if (! pId) 1085 { 1086 static ::cppu::OImplementationId aId; 1087 pId = &aId; 1088 } 1089 } 1090 return pId->getImplementationId(); 1091 } 1092 1093 //------------------------------------------------------------------ 1094 Any SAL_CALL FmXGridPeer::queryInterface(const Type& _rType) throw (RuntimeException) 1095 { 1096 Any aReturn = FmXGridPeer_BASE::queryInterface(_rType); 1097 1098 if (!aReturn.hasValue()) 1099 aReturn = VCLXWindow::queryInterface( _rType ); 1100 1101 return aReturn; 1102 } 1103 1104 //------------------------------------------------------------------ 1105 void FmXGridPeer::selectionChanged() 1106 { 1107 EventObject aSource; 1108 aSource.Source = static_cast< ::cppu::OWeakObject* >(this); 1109 m_aSelectionListeners.notifyEach( &XSelectionChangeListener::selectionChanged, aSource); 1110 } 1111 1112 //------------------------------------------------------------------ 1113 void FmXGridPeer::columnChanged() 1114 { 1115 EventObject aEvent( *this ); 1116 m_aGridControlListeners.notifyEach( &XGridControlListener::columnChanged, aEvent ); 1117 } 1118 1119 //------------------------------------------------------------------ 1120 namespace fmgridif 1121 { 1122 const ::rtl::OUString getDataModeIdentifier() 1123 { 1124 static ::rtl::OUString s_sDataModeIdentifier = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DataMode" ) ); 1125 return s_sDataModeIdentifier; 1126 } 1127 } 1128 using namespace fmgridif; 1129 1130 //------------------------------------------------------------------ 1131 FmXGridPeer::FmXGridPeer(const Reference< XMultiServiceFactory >& _rxFactory) 1132 :m_aModifyListeners(m_aMutex) 1133 ,m_aUpdateListeners(m_aMutex) 1134 ,m_aContainerListeners(m_aMutex) 1135 ,m_aSelectionListeners(m_aMutex) 1136 ,m_aGridControlListeners(m_aMutex) 1137 ,m_aMode( getDataModeIdentifier() ) 1138 ,m_nCursorListening(0) 1139 ,m_bInterceptingDispatch(sal_False) 1140 ,m_pStateCache(NULL) 1141 ,m_pDispatchers(NULL) 1142 ,m_pGridListener(NULL) 1143 ,m_xServiceFactory(_rxFactory) 1144 { 1145 // nach diesem Constructor muss Create gerufen werden ! 1146 m_pGridListener = new GridListenerDelegator( this ); 1147 } 1148 1149 //------------------------------------------------------------------------------ 1150 FmGridControl* FmXGridPeer::imp_CreateControl(Window* pParent, WinBits nStyle) 1151 { 1152 return new FmGridControl(m_xServiceFactory, pParent, this, nStyle); 1153 } 1154 1155 //------------------------------------------------------------------------------ 1156 void FmXGridPeer::Create(Window* pParent, WinBits nStyle) 1157 { 1158 FmGridControl* pWin = imp_CreateControl(pParent, nStyle); 1159 DBG_ASSERT(pWin != NULL, "FmXGridPeer::Create : imp_CreateControl didn't return a control !"); 1160 1161 pWin->SetStateProvider(LINK(this, FmXGridPeer, OnQueryGridSlotState)); 1162 pWin->SetSlotExecutor(LINK(this, FmXGridPeer, OnExecuteGridSlot)); 1163 1164 // want to hear about row selections 1165 pWin->setGridListener( m_pGridListener ); 1166 1167 // Init mu� immer aufgerufen werden 1168 pWin->Init(); 1169 pWin->SetComponentInterface(this); 1170 1171 getSupportedURLs(); 1172 } 1173 1174 //------------------------------------------------------------------------------ 1175 FmXGridPeer::~FmXGridPeer() 1176 { 1177 setRowSet(Reference< XRowSet > ()); 1178 setColumns(Reference< XIndexContainer > ()); 1179 1180 delete m_pGridListener; 1181 } 1182 1183 //------------------------------------------------------------------------------ 1184 const Sequence< sal_Int8 >& FmXGridPeer::getUnoTunnelImplementationId() throw() 1185 { 1186 static Sequence< sal_Int8 > * pSeq = 0; 1187 if( !pSeq ) 1188 { 1189 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 1190 if( !pSeq ) 1191 { 1192 static Sequence< sal_Int8 > aSeq( 16 ); 1193 rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); 1194 pSeq = &aSeq; 1195 } 1196 } 1197 return *pSeq; 1198 } 1199 1200 //------------------------------------------------------------------------------ 1201 FmXGridPeer* FmXGridPeer::getImplementation( const Reference< XInterface >& _rxIFace ) throw() 1202 { 1203 FmXGridPeer* pReturn = NULL; 1204 Reference< XUnoTunnel > xTunnel(_rxIFace, UNO_QUERY); 1205 if (xTunnel.is()) 1206 pReturn = reinterpret_cast<FmXGridPeer*>(xTunnel->getSomething(getUnoTunnelImplementationId())); 1207 1208 return pReturn; 1209 } 1210 1211 //------------------------------------------------------------------------------ 1212 sal_Int64 SAL_CALL FmXGridPeer::getSomething( const Sequence< sal_Int8 >& _rIdentifier ) throw(RuntimeException) 1213 { 1214 sal_Int64 nReturn(0); 1215 1216 if ( (_rIdentifier.getLength() == 16) 1217 && (0 == rtl_compareMemory( getUnoTunnelImplementationId().getConstArray(), _rIdentifier.getConstArray(), 16 )) 1218 ) 1219 { 1220 nReturn = reinterpret_cast<sal_Int64>(this); 1221 } 1222 else 1223 nReturn = VCLXWindow::getSomething(_rIdentifier); 1224 1225 return nReturn; 1226 } 1227 1228 // XEventListener 1229 //------------------------------------------------------------------------------ 1230 void FmXGridPeer::disposing(const EventObject& e) throw( RuntimeException ) 1231 { 1232 using namespace ::com::sun::star::util; 1233 bool bKnownSender = false; 1234 1235 Reference< XIndexContainer > xCols( e.Source, UNO_QUERY ); 1236 if ( xCols.is() ) 1237 { 1238 setColumns(Reference< XIndexContainer > ()); 1239 bKnownSender = true; 1240 } 1241 1242 Reference< XRowSet > xCursor(e.Source, UNO_QUERY); 1243 if (xCursor.is()) 1244 { 1245 setRowSet( m_xCursor ); 1246 m_xCursor = NULL; 1247 bKnownSender = true; 1248 } 1249 1250 1251 if ( !bKnownSender && m_pDispatchers ) 1252 { 1253 const Sequence< URL>& aSupportedURLs = getSupportedURLs(); 1254 const URL* pSupportedURLs = aSupportedURLs.getConstArray(); 1255 for ( sal_uInt16 i=0; i < ( aSupportedURLs.getLength() ) && !bKnownSender; ++i, ++pSupportedURLs ) 1256 { 1257 if ( m_pDispatchers[i] == e.Source ) 1258 { 1259 m_pDispatchers[i]->removeStatusListener( static_cast< ::com::sun::star::frame::XStatusListener* >( this ), *pSupportedURLs ); 1260 m_pDispatchers[i] = NULL; 1261 m_pStateCache[i] = 0; 1262 bKnownSender = true; 1263 } 1264 } 1265 } 1266 1267 if ( !bKnownSender ) 1268 VCLXWindow::disposing(e); 1269 } 1270 1271 //------------------------------------------------------------------------------ 1272 void FmXGridPeer::addModifyListener(const Reference< ::com::sun::star::util::XModifyListener >& l) throw( RuntimeException ) 1273 { 1274 m_aModifyListeners.addInterface( l ); 1275 } 1276 1277 //------------------------------------------------------------------------------ 1278 void FmXGridPeer::removeModifyListener(const Reference< ::com::sun::star::util::XModifyListener >& l) throw( RuntimeException ) 1279 { 1280 m_aModifyListeners.removeInterface( l ); 1281 } 1282 1283 //------------------------------------------------------------------------------ 1284 #define LAST_KNOWN_TYPE FormComponentType::PATTERNFIELD 1285 Sequence< sal_Bool > SAL_CALL FmXGridPeer::queryFieldDataType( const Type& xType ) throw(RuntimeException) 1286 { 1287 // eine 'Konvertierungstabelle' 1288 static sal_Bool bCanConvert[LAST_KNOWN_TYPE][4] = 1289 { 1290 { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::CONTROL 1291 { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::COMMANDBUTTON 1292 { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::RADIOBUTTON 1293 { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::IMAGEBUTTON 1294 { sal_False, sal_False, sal_False, sal_True }, // FormComponentType::CHECKBOX 1295 { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::LISTBOX 1296 { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::COMBOBOX 1297 { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::GROUPBOX 1298 { sal_True , sal_False, sal_False, sal_False }, // FormComponentType::TEXTFIELD 1299 { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::FIXEDTEXT 1300 { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::GRIDCONTROL 1301 { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::FILECONTROL 1302 { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::HIDDENCONTROL 1303 { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::IMAGECONTROL 1304 { sal_True , sal_True , sal_True , sal_False }, // FormComponentType::DATEFIELD 1305 { sal_True , sal_True , sal_False, sal_False }, // FormComponentType::TIMEFIELD 1306 { sal_True , sal_True , sal_False, sal_False }, // FormComponentType::NUMERICFIELD 1307 { sal_True , sal_True , sal_False, sal_False }, // FormComponentType::CURRENCYFIELD 1308 { sal_True , sal_False, sal_False, sal_False } // FormComponentType::PATTERNFIELD 1309 }; 1310 1311 1312 sal_Int16 nMapColumn = -1; 1313 switch (xType.getTypeClass()) 1314 { 1315 case TypeClass_STRING : nMapColumn = 0; break; 1316 case TypeClass_FLOAT: 1317 case TypeClass_DOUBLE : nMapColumn = 1; break; 1318 case TypeClass_SHORT: 1319 case TypeClass_LONG: 1320 case TypeClass_UNSIGNED_LONG: 1321 case TypeClass_UNSIGNED_SHORT : nMapColumn = 2; break; 1322 case TypeClass_BOOLEAN : nMapColumn = 3; break; 1323 default: 1324 break; 1325 } 1326 1327 Reference< XIndexContainer > xColumns = getColumns(); 1328 1329 FmGridControl* pGrid = (FmGridControl*) GetWindow(); 1330 sal_Int32 nColumns = pGrid->GetViewColCount(); 1331 1332 DbGridColumns aColumns = pGrid->GetColumns(); 1333 1334 Sequence<sal_Bool> aReturnSequence(nColumns); 1335 sal_Bool* pReturnArray = aReturnSequence.getArray(); 1336 1337 sal_Bool bRequestedAsAny = (xType.getTypeClass() == TypeClass_ANY); 1338 1339 DbGridColumn* pCol; 1340 Reference< ::com::sun::star::sdb::XColumn > xFieldContent; 1341 Reference< XPropertySet > xCurrentColumn; 1342 for (sal_Int32 i=0; i<nColumns; ++i) 1343 { 1344 if (bRequestedAsAny) 1345 { 1346 pReturnArray[i] = sal_True; 1347 continue; 1348 } 1349 1350 pReturnArray[i] = sal_False; 1351 1352 sal_uInt16 nModelPos = pGrid->GetModelColumnPos(pGrid->GetColumnIdFromViewPos((sal_uInt16)i)); 1353 DBG_ASSERT(nModelPos != (sal_uInt16)-1, "FmXGridPeer::queryFieldDataType : no model pos !"); 1354 1355 pCol = aColumns.GetObject(nModelPos); 1356 const DbGridRowRef xRow = pGrid->GetSeekRow(); 1357 xFieldContent = (xRow.Is() && xRow->HasField(pCol->GetFieldPos())) ? xRow->GetField(pCol->GetFieldPos()).getColumn() : Reference< ::com::sun::star::sdb::XColumn > (); 1358 if (!xFieldContent.is()) 1359 // can't supply anything without a field content 1360 // FS - 07.12.99 - 54391 1361 continue; 1362 1363 xColumns->getByIndex(nModelPos) >>= xCurrentColumn; 1364 if (!::comphelper::hasProperty(FM_PROP_CLASSID, xCurrentColumn)) 1365 continue; 1366 1367 sal_Int16 nClassId = sal_Int16(); 1368 xCurrentColumn->getPropertyValue(FM_PROP_CLASSID) >>= nClassId; 1369 if (nClassId>LAST_KNOWN_TYPE) 1370 continue; 1371 DBG_ASSERT(nClassId>0, "FmXGridPeer::queryFieldDataType : somebody changed the definition of the FormComponentType enum !"); 1372 1373 if (nMapColumn != -1) 1374 pReturnArray[i] = bCanConvert[nClassId-1][nMapColumn]; 1375 } 1376 1377 return aReturnSequence; 1378 } 1379 1380 //------------------------------------------------------------------------------ 1381 Sequence< Any > SAL_CALL FmXGridPeer::queryFieldData( sal_Int32 nRow, const Type& xType ) throw(RuntimeException) 1382 { 1383 FmGridControl* pGrid = (FmGridControl*) GetWindow(); 1384 DBG_ASSERT(pGrid && pGrid->IsOpen(), "FmXGridPeer::queryFieldData : have no valid grid window !"); 1385 if (!pGrid || !pGrid->IsOpen()) 1386 return Sequence< Any>(); 1387 1388 // das Control zur angegebenen Row fahren 1389 if (!pGrid->SeekRow(nRow)) 1390 { 1391 throw IllegalArgumentException(); 1392 } 1393 1394 // don't use GetCurrentRow as this isn't affected by the above SeekRow 1395 // FS - 30.09.99 - 68644 1396 DbGridRowRef xPaintRow = pGrid->GetPaintRow(); 1397 ENSURE_OR_THROW( xPaintRow.Is(), "invalid paint row" ); 1398 1399 // die Columns des Controls brauche ich fuer GetFieldText 1400 DbGridColumns aColumns = pGrid->GetColumns(); 1401 1402 // und durch alle Spalten durch 1403 sal_Int32 nColumnCount = pGrid->GetViewColCount(); 1404 1405 Sequence< Any> aReturnSequence(nColumnCount); 1406 Any* pReturnArray = aReturnSequence.getArray(); 1407 1408 sal_Bool bRequestedAsAny = (xType.getTypeClass() == TypeClass_ANY); 1409 Reference< ::com::sun::star::sdb::XColumn > xFieldContent; 1410 DbGridColumn* pCol; 1411 for (sal_Int32 i=0; i < nColumnCount; ++i) 1412 { 1413 sal_uInt16 nModelPos = pGrid->GetModelColumnPos(pGrid->GetColumnIdFromViewPos((sal_uInt16)i)); 1414 DBG_ASSERT(nModelPos != (sal_uInt16)-1, "FmXGridPeer::queryFieldData : invalid model pos !"); 1415 1416 // don't use GetCurrentFieldValue to determine the field content as this isn't affected by the above SeekRow 1417 // FS - 30.09.99 - 68644 1418 pCol = aColumns.GetObject(nModelPos); 1419 xFieldContent = xPaintRow->HasField( pCol->GetFieldPos() ) 1420 ? xPaintRow->GetField( pCol->GetFieldPos() ).getColumn() 1421 : Reference< XColumn > (); 1422 1423 if ( !xFieldContent.is() ) 1424 continue; 1425 1426 if (bRequestedAsAny) 1427 { 1428 Reference< XPropertySet > xFieldSet(xFieldContent, UNO_QUERY); 1429 pReturnArray[i] = xFieldSet->getPropertyValue(FM_PROP_VALUE); 1430 } 1431 else 1432 { 1433 switch (xType.getTypeClass()) 1434 { 1435 // Strings werden direkt ueber das GetFieldText abgehandelt 1436 case TypeClass_STRING : 1437 { 1438 String sText = aColumns.GetObject(nModelPos)->GetCellText( xPaintRow, pGrid->getNumberFormatter() ); 1439 pReturnArray[i] <<= ::rtl::OUString(sText); 1440 } 1441 break; 1442 // alles andere wird an der DatabaseVariant erfragt 1443 case TypeClass_FLOAT : pReturnArray[i] <<= xFieldContent->getFloat(); break; 1444 case TypeClass_DOUBLE : pReturnArray[i] <<= xFieldContent->getDouble(); break; 1445 case TypeClass_SHORT : pReturnArray[i] <<= (sal_Int16)xFieldContent->getShort(); break; 1446 case TypeClass_LONG : pReturnArray[i] <<= (sal_Int32)xFieldContent->getLong(); break; 1447 case TypeClass_UNSIGNED_SHORT : pReturnArray[i] <<= (sal_uInt16)xFieldContent->getShort(); break; 1448 case TypeClass_UNSIGNED_LONG : pReturnArray[i] <<= (sal_uInt32)xFieldContent->getLong(); break; 1449 case TypeClass_BOOLEAN : ::comphelper::setBOOL(pReturnArray[i],xFieldContent->getBoolean()); break; 1450 default: 1451 { 1452 throw IllegalArgumentException(); 1453 } 1454 } 1455 } 1456 } 1457 return aReturnSequence; 1458 } 1459 1460 //------------------------------------------------------------------------------ 1461 void FmXGridPeer::CellModified() 1462 { 1463 EventObject aEvt; 1464 aEvt.Source = static_cast< ::cppu::OWeakObject* >(this); 1465 m_aModifyListeners.notifyEach( &XModifyListener::modified, aEvt ); 1466 } 1467 1468 // XPropertyChangeListener 1469 //------------------------------------------------------------------------------ 1470 void FmXGridPeer::propertyChange(const PropertyChangeEvent& evt) throw( RuntimeException ) 1471 { 1472 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 1473 // want to do a lot of VCL stuff here ... 1474 // this should not be (deadlock) critical, as by definition, every component should release 1475 // any own mutexes before notifying 1476 1477 FmGridControl* pGrid = (FmGridControl*) GetWindow(); 1478 if (!pGrid) 1479 return; 1480 1481 // DatenbankEvent 1482 Reference< XRowSet > xCursor(evt.Source, UNO_QUERY); 1483 if (evt.PropertyName == FM_PROP_VALUE || m_xCursor == evt.Source) 1484 pGrid->propertyChange(evt); 1485 else if (pGrid && m_xColumns.is() && m_xColumns->hasElements()) 1486 { 1487 // zunaechst raussuchen welche Column sich geaendert hat 1488 ::comphelper::InterfaceRef xCurrent; 1489 sal_Int32 i; 1490 1491 for ( i = 0; i < m_xColumns->getCount(); i++) 1492 { 1493 ::cppu::extractInterface(xCurrent, m_xColumns->getByIndex(i)); 1494 if (evt.Source == xCurrent) 1495 break; 1496 } 1497 1498 if (i >= m_xColumns->getCount()) 1499 // this is valid because we are listening at the cursor, too (RecordCount, -status, edit mode) 1500 return; 1501 1502 sal_uInt16 nId = pGrid->GetColumnIdFromModelPos((sal_uInt16)i); 1503 sal_Bool bInvalidateColumn = sal_False; 1504 1505 if (evt.PropertyName == FM_PROP_LABEL) 1506 { 1507 String aName = ::comphelper::getString(evt.NewValue); 1508 if (aName != pGrid->GetColumnTitle(nId)) 1509 pGrid->SetColumnTitle(nId, aName); 1510 } 1511 else if (evt.PropertyName == FM_PROP_WIDTH) 1512 { 1513 sal_Int32 nWidth = 0; 1514 if (evt.NewValue.getValueType().getTypeClass() == TypeClass_VOID) 1515 nWidth = pGrid->GetDefaultColumnWidth(pGrid->GetColumnTitle(nId)); 1516 // GetDefaultColumnWidth already considerd the zoom factor 1517 else 1518 { 1519 sal_Int32 nTest = 0; 1520 if (evt.NewValue >>= nTest) 1521 { 1522 nWidth = pGrid->LogicToPixel(Point(nTest,0),MAP_10TH_MM).X(); 1523 // take the zoom factor into account 1524 nWidth = pGrid->CalcZoom(nWidth); 1525 } 1526 } 1527 if (nWidth != (sal_Int32(pGrid->GetColumnWidth(nId)))) 1528 { 1529 if (pGrid->IsEditing()) 1530 { 1531 pGrid->DeactivateCell(); 1532 pGrid->ActivateCell(); 1533 } 1534 pGrid->SetColumnWidth(nId, nWidth); 1535 } 1536 } 1537 else if (evt.PropertyName == FM_PROP_HIDDEN) 1538 { 1539 DBG_ASSERT(evt.NewValue.getValueType().getTypeClass() == TypeClass_BOOLEAN, 1540 "FmXGridPeer::propertyChange : the property 'hidden' should be of type boolean !"); 1541 if (::comphelper::getBOOL(evt.NewValue)) 1542 pGrid->HideColumn(nId); 1543 else 1544 pGrid->ShowColumn(nId); 1545 } 1546 else if (evt.PropertyName == FM_PROP_ALIGN) 1547 { 1548 // it design mode it doesn't matter 1549 if (!isDesignMode()) 1550 { 1551 DbGridColumn* pCol = pGrid->GetColumns().GetObject(i); 1552 1553 pCol->SetAlignmentFromModel(-1); 1554 bInvalidateColumn = sal_True; 1555 } 1556 } 1557 else if (evt.PropertyName == FM_PROP_FORMATKEY) 1558 { 1559 if (!isDesignMode()) 1560 bInvalidateColumn = sal_True; 1561 } 1562 1563 // need to invalidate the affected column ? 1564 if (bInvalidateColumn) 1565 { 1566 sal_Bool bWasEditing = pGrid->IsEditing(); 1567 if (bWasEditing) 1568 pGrid->DeactivateCell(); 1569 1570 ::Rectangle aColRect = pGrid->GetFieldRect(nId); 1571 aColRect.Top() = 0; 1572 aColRect.Bottom() = pGrid->GetSizePixel().Height(); 1573 pGrid->Invalidate(aColRect); 1574 1575 if (bWasEditing) 1576 pGrid->ActivateCell(); 1577 } 1578 } 1579 } 1580 1581 // XBoundComponent 1582 //------------------------------------------------------------------------------ 1583 void FmXGridPeer::addUpdateListener(const Reference< XUpdateListener >& l) throw( RuntimeException ) 1584 { 1585 m_aUpdateListeners.addInterface(l); 1586 } 1587 1588 //------------------------------------------------------------------------------ 1589 void FmXGridPeer::removeUpdateListener(const Reference< XUpdateListener >& l) throw( RuntimeException ) 1590 { 1591 m_aUpdateListeners.removeInterface(l); 1592 } 1593 1594 //------------------------------------------------------------------------------ 1595 sal_Bool FmXGridPeer::commit() throw( RuntimeException ) 1596 { 1597 FmGridControl* pGrid = (FmGridControl*) GetWindow(); 1598 if (!m_xCursor.is() || !pGrid) 1599 return sal_True; 1600 1601 EventObject aEvt(static_cast< ::cppu::OWeakObject* >(this)); 1602 ::cppu::OInterfaceIteratorHelper aIter(m_aUpdateListeners); 1603 sal_Bool bCancel = sal_False; 1604 while (aIter.hasMoreElements() && !bCancel) 1605 if ( !static_cast< XUpdateListener* >( aIter.next() )->approveUpdate( aEvt ) ) 1606 bCancel = sal_True; 1607 1608 if (!bCancel) 1609 bCancel = !pGrid->commit(); 1610 1611 if (!bCancel) 1612 m_aUpdateListeners.notifyEach( &XUpdateListener::updated, aEvt ); 1613 return !bCancel; 1614 } 1615 1616 1617 //------------------------------------------------------------------------------ 1618 void FmXGridPeer::cursorMoved(const EventObject& _rEvent) throw( RuntimeException ) 1619 { 1620 FmGridControl* pGrid = (FmGridControl*) GetWindow(); 1621 // we are not interested in move to insert row only in the resetted event 1622 // which is fired after positioning an the insert row 1623 if (pGrid && pGrid->IsOpen() && !::comphelper::getBOOL(Reference< XPropertySet > (_rEvent.Source, UNO_QUERY)->getPropertyValue(FM_PROP_ISNEW))) 1624 pGrid->positioned(_rEvent); 1625 } 1626 1627 //------------------------------------------------------------------------------ 1628 void FmXGridPeer::rowChanged(const EventObject& _rEvent) throw( RuntimeException ) 1629 { 1630 FmGridControl* pGrid = (FmGridControl*) GetWindow(); 1631 if (pGrid && pGrid->IsOpen()) 1632 { 1633 if (m_xCursor->rowUpdated() && !pGrid->IsCurrentAppending()) 1634 pGrid->RowModified(pGrid->GetCurrentPos()); 1635 else if (m_xCursor->rowInserted()) 1636 pGrid->inserted(_rEvent); 1637 } 1638 } 1639 1640 //------------------------------------------------------------------------------ 1641 void FmXGridPeer::rowSetChanged(const EventObject& /*event*/) throw( RuntimeException ) 1642 { 1643 // not interested in ... 1644 // (our parent is a form which means we get a loaded or reloaded after this rowSetChanged) 1645 } 1646 1647 // XLoadListener 1648 //------------------------------------------------------------------------------ 1649 void FmXGridPeer::loaded(const EventObject& /*rEvent*/) throw( RuntimeException ) 1650 { 1651 updateGrid(m_xCursor); 1652 } 1653 1654 //------------------------------------------------------------------------------ 1655 void FmXGridPeer::unloaded(const EventObject& /*rEvent*/) throw( RuntimeException ) 1656 { 1657 updateGrid( Reference< XRowSet > (NULL) ); 1658 } 1659 1660 //------------------------------------------------------------------------------ 1661 void FmXGridPeer::reloading(const EventObject& /*aEvent*/) throw( RuntimeException ) 1662 { 1663 // empty the grid 1664 updateGrid( Reference< XRowSet > (NULL) ); 1665 } 1666 1667 //------------------------------------------------------------------------------ 1668 void FmXGridPeer::unloading(const EventObject& /*aEvent*/) throw( RuntimeException ) 1669 { 1670 // empty the grid 1671 updateGrid( Reference< XRowSet > (NULL) ); 1672 } 1673 1674 //------------------------------------------------------------------------------ 1675 void FmXGridPeer::reloaded(const EventObject& /*aEvent*/) throw( RuntimeException ) 1676 { 1677 updateGrid(m_xCursor); 1678 } 1679 1680 // XGridPeer 1681 //------------------------------------------------------------------------------ 1682 Reference< XIndexContainer > FmXGridPeer::getColumns() throw( RuntimeException ) 1683 { 1684 return m_xColumns; 1685 } 1686 1687 //------------------------------------------------------------------------------ 1688 void FmXGridPeer::addColumnListeners(const Reference< XPropertySet >& xCol) 1689 { 1690 static const ::rtl::OUString aPropsListenedTo[] = 1691 { 1692 FM_PROP_LABEL, FM_PROP_WIDTH, FM_PROP_HIDDEN, FM_PROP_ALIGN, FM_PROP_FORMATKEY 1693 }; 1694 1695 // as not all properties have to be supported by all columns we have to check this 1696 // before adding a listener 1697 Reference< XPropertySetInfo > xInfo = xCol->getPropertySetInfo(); 1698 Property aPropDesc; 1699 const ::rtl::OUString* pProps = aPropsListenedTo; 1700 const ::rtl::OUString* pPropsEnd = pProps + sizeof( aPropsListenedTo ) / sizeof( aPropsListenedTo[ 0 ] ); 1701 for (; pProps != pPropsEnd; ++pProps) 1702 { 1703 if ( xInfo->hasPropertyByName( *pProps ) ) 1704 { 1705 aPropDesc = xInfo->getPropertyByName( *pProps ); 1706 if ( 0 != ( aPropDesc.Attributes & PropertyAttribute::BOUND ) ) 1707 xCol->addPropertyChangeListener( *pProps, this ); 1708 } 1709 } 1710 } 1711 1712 //------------------------------------------------------------------------------ 1713 void FmXGridPeer::removeColumnListeners(const Reference< XPropertySet >& xCol) 1714 { 1715 // the same props as in addColumnListeners ... linux has problems with global static UStrings, so 1716 // we have to do it this way .... 1717 static ::rtl::OUString aPropsListenedTo[] = 1718 { 1719 FM_PROP_LABEL, FM_PROP_WIDTH, FM_PROP_HIDDEN, FM_PROP_ALIGN, FM_PROP_FORMATKEY 1720 }; 1721 1722 Reference< XPropertySetInfo > xInfo = xCol->getPropertySetInfo(); 1723 for (sal_uInt16 i=0; i<sizeof(aPropsListenedTo)/sizeof(aPropsListenedTo[0]); ++i) 1724 if (xInfo->hasPropertyByName(aPropsListenedTo[i])) 1725 xCol->removePropertyChangeListener(aPropsListenedTo[i], this); 1726 } 1727 1728 //------------------------------------------------------------------------------ 1729 void FmXGridPeer::setColumns(const Reference< XIndexContainer >& Columns) throw( RuntimeException ) 1730 { 1731 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 1732 1733 FmGridControl* pGrid = static_cast< FmGridControl* >( GetWindow() ); 1734 1735 if (m_xColumns.is()) 1736 { 1737 Reference< XPropertySet > xCol; 1738 for (sal_Int32 i = 0; i < m_xColumns->getCount(); i++) 1739 { 1740 ::cppu::extractInterface(xCol, m_xColumns->getByIndex(i)); 1741 removeColumnListeners(xCol); 1742 } 1743 Reference< XContainer > xContainer(m_xColumns, UNO_QUERY); 1744 xContainer->removeContainerListener(this); 1745 1746 Reference< XSelectionSupplier > xSelSupplier(m_xColumns, UNO_QUERY); 1747 xSelSupplier->removeSelectionChangeListener(this); 1748 1749 Reference< XReset > xColumnReset(m_xColumns, UNO_QUERY); 1750 if (xColumnReset.is()) 1751 xColumnReset->removeResetListener((XResetListener*)this); 1752 } 1753 if (Columns.is()) 1754 { 1755 Reference< XContainer > xContainer(Columns, UNO_QUERY); 1756 xContainer->addContainerListener(this); 1757 1758 Reference< XSelectionSupplier > xSelSupplier(Columns, UNO_QUERY); 1759 xSelSupplier->addSelectionChangeListener(this); 1760 1761 Reference< XPropertySet > xCol; 1762 for (sal_Int32 i = 0; i < Columns->getCount(); i++) 1763 { 1764 ::cppu::extractInterface(xCol, Columns->getByIndex(i)); 1765 addColumnListeners(xCol); 1766 } 1767 1768 Reference< XReset > xColumnReset(Columns, UNO_QUERY); 1769 if (xColumnReset.is()) 1770 xColumnReset->addResetListener((XResetListener*)this); 1771 } 1772 m_xColumns = Columns; 1773 if (pGrid) 1774 { 1775 pGrid->InitColumnsByModels(m_xColumns); 1776 1777 if (m_xColumns.is()) 1778 { 1779 EventObject aEvt(m_xColumns); 1780 selectionChanged(aEvt); 1781 } 1782 } 1783 } 1784 1785 //------------------------------------------------------------------------------ 1786 void FmXGridPeer::setDesignMode(sal_Bool bOn) throw( RuntimeException ) 1787 { 1788 if (bOn != isDesignMode()) 1789 { 1790 Window* pWin = GetWindow(); 1791 if (pWin) 1792 ((FmGridControl*) pWin)->SetDesignMode(bOn); 1793 } 1794 1795 if (bOn) 1796 DisConnectFromDispatcher(); 1797 else 1798 UpdateDispatches(); // will connect if not already connected and just update else 1799 } 1800 1801 //------------------------------------------------------------------------------ 1802 sal_Bool FmXGridPeer::isDesignMode() throw( RuntimeException ) 1803 { 1804 Window* pWin = GetWindow(); 1805 if (pWin) 1806 return ((FmGridControl*) pWin)->IsDesignMode(); 1807 else 1808 return sal_False; 1809 } 1810 1811 //------------------------------------------------------------------------------ 1812 void FmXGridPeer::elementInserted(const ContainerEvent& evt) throw( RuntimeException ) 1813 { 1814 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 1815 1816 FmGridControl* pGrid = (FmGridControl*) GetWindow(); 1817 // Handle Column beruecksichtigen 1818 if (!pGrid || !m_xColumns.is() || pGrid->IsInColumnMove() || m_xColumns->getCount() == ((sal_Int32)pGrid->GetModelColCount())) 1819 return; 1820 1821 Reference< XPropertySet > xSet; 1822 ::cppu::extractInterface(xSet, evt.Element); 1823 addColumnListeners(xSet); 1824 1825 Reference< XPropertySet > xNewColumn(xSet); 1826 String aName = ::comphelper::getString(xNewColumn->getPropertyValue(FM_PROP_LABEL)); 1827 Any aWidth = xNewColumn->getPropertyValue(FM_PROP_WIDTH); 1828 sal_Int32 nWidth = 0; 1829 if (aWidth >>= nWidth) 1830 nWidth = pGrid->LogicToPixel(Point(nWidth,0),MAP_10TH_MM).X(); 1831 1832 pGrid->AppendColumn(aName, (sal_uInt16)nWidth, (sal_Int16)::comphelper::getINT32(evt.Accessor)); 1833 1834 // jetzt die Spalte setzen 1835 DbGridColumn* pCol = pGrid->GetColumns().GetObject(::comphelper::getINT32(evt.Accessor)); 1836 pCol->setModel(xNewColumn); 1837 1838 Any aHidden = xNewColumn->getPropertyValue(FM_PROP_HIDDEN); 1839 if (::comphelper::getBOOL(aHidden)) 1840 pGrid->HideColumn(pCol->GetId()); 1841 1842 FormControlFactory( m_xServiceFactory ).initializeTextFieldLineEnds( xNewColumn ); 1843 } 1844 1845 //------------------------------------------------------------------------------ 1846 void FmXGridPeer::elementReplaced(const ContainerEvent& evt) throw( RuntimeException ) 1847 { 1848 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 1849 1850 FmGridControl* pGrid = (FmGridControl*) GetWindow(); 1851 1852 // Handle Column beruecksichtigen 1853 if (!pGrid || !m_xColumns.is() || pGrid->IsInColumnMove()) 1854 return; 1855 1856 Reference< XPropertySet > xNewColumn; 1857 Reference< XPropertySet > xOldColumn; 1858 ::cppu::extractInterface(xNewColumn, evt.Element); 1859 ::cppu::extractInterface(xOldColumn, evt.ReplacedElement); 1860 1861 sal_Bool bWasEditing = pGrid->IsEditing(); 1862 if (bWasEditing) 1863 pGrid->DeactivateCell(); 1864 1865 pGrid->RemoveColumn(pGrid->GetColumnIdFromModelPos((sal_uInt16)::comphelper::getINT32(evt.Accessor))); 1866 1867 removeColumnListeners(xOldColumn); 1868 addColumnListeners(xNewColumn); 1869 1870 String aName = ::comphelper::getString(xNewColumn->getPropertyValue(FM_PROP_LABEL)); 1871 Any aWidth = xNewColumn->getPropertyValue(FM_PROP_WIDTH); 1872 sal_Int32 nWidth = 0; 1873 if (aWidth >>= nWidth) 1874 nWidth = pGrid->LogicToPixel(Point(nWidth,0),MAP_10TH_MM).X(); 1875 sal_uInt16 nNewId = pGrid->AppendColumn(aName, (sal_uInt16)nWidth, (sal_Int16)::comphelper::getINT32(evt.Accessor)); 1876 sal_uInt16 nNewPos = pGrid->GetModelColumnPos(nNewId); 1877 1878 // set the model of the new column 1879 DbGridColumn* pCol = pGrid->GetColumns().GetObject(nNewPos); 1880 1881 // for initializong this grid column, we need the fields of the grid's data source 1882 Reference< XColumnsSupplier > xSuppColumns; 1883 CursorWrapper* pGridDataSource = pGrid->getDataSource(); 1884 if ( pGridDataSource ) 1885 xSuppColumns = xSuppColumns.query( (Reference< XInterface >)( *pGridDataSource ) ); 1886 Reference< XNameAccess > xColumnsByName; 1887 if ( xSuppColumns.is() ) 1888 xColumnsByName = xSuppColumns->getColumns(); 1889 Reference< XIndexAccess > xColumnsByIndex( xColumnsByName, UNO_QUERY ); 1890 1891 if ( xColumnsByIndex.is() ) 1892 pGrid->InitColumnByField( pCol, xNewColumn, xColumnsByName, xColumnsByIndex ); 1893 else 1894 // the simple version, applies when the grid is not yet connected to a data source 1895 pCol->setModel(xNewColumn); 1896 1897 if (bWasEditing) 1898 pGrid->ActivateCell(); 1899 } 1900 1901 //------------------------------------------------------------------------------ 1902 void FmXGridPeer::elementRemoved(const ContainerEvent& evt) throw( RuntimeException ) 1903 { 1904 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 1905 1906 FmGridControl* pGrid = (FmGridControl*) GetWindow(); 1907 1908 // Handle Column beruecksichtigen 1909 if (!pGrid || !m_xColumns.is() || pGrid->IsInColumnMove() || m_xColumns->getCount() == ((sal_Int32)pGrid->GetModelColCount())) 1910 return; 1911 1912 pGrid->RemoveColumn(pGrid->GetColumnIdFromModelPos((sal_uInt16)::comphelper::getINT32(evt.Accessor))); 1913 1914 Reference< XPropertySet > xOldColumn; 1915 ::cppu::extractInterface(xOldColumn, evt.Element); 1916 removeColumnListeners(xOldColumn); 1917 } 1918 1919 //------------------------------------------------------------------------------ 1920 void FmXGridPeer::setProperty( const ::rtl::OUString& PropertyName, const Any& Value) throw( RuntimeException ) 1921 { 1922 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 1923 1924 FmGridControl* pGrid = (FmGridControl*) GetWindow(); 1925 1926 sal_Bool bVoid = !Value.hasValue(); 1927 1928 if ( 0 == PropertyName.compareTo( FM_PROP_TEXTLINECOLOR ) ) 1929 { 1930 ::Color aTextLineColor( bVoid ? COL_TRANSPARENT : ::comphelper::getINT32( Value ) ); 1931 if (bVoid) 1932 { 1933 pGrid->SetTextLineColor(); 1934 pGrid->GetDataWindow().SetTextLineColor(); 1935 } 1936 else 1937 { 1938 pGrid->SetTextLineColor(aTextLineColor); 1939 pGrid->GetDataWindow().SetTextLineColor(aTextLineColor); 1940 } 1941 1942 // need to forward this to the columns 1943 DbGridColumns& rColumns = const_cast<DbGridColumns&>(pGrid->GetColumns()); 1944 DbGridColumn* pLoop = rColumns.First(); 1945 while (pLoop) 1946 { 1947 FmXGridCell* pXCell = pLoop->GetCell(); 1948 if (pXCell) 1949 { 1950 if (bVoid) 1951 pXCell->SetTextLineColor(); 1952 else 1953 pXCell->SetTextLineColor(aTextLineColor); 1954 } 1955 1956 pLoop = rColumns.Next(); 1957 } 1958 1959 if (isDesignMode()) 1960 pGrid->Invalidate(); 1961 } 1962 else if ( 0 == PropertyName.compareTo( FM_PROP_FONTEMPHASISMARK ) ) 1963 { 1964 Font aGridFont = pGrid->GetControlFont(); 1965 sal_Int16 nValue = ::comphelper::getINT16(Value); 1966 aGridFont.SetEmphasisMark( nValue ); 1967 pGrid->SetControlFont( aGridFont ); 1968 } 1969 else if ( 0 == PropertyName.compareTo( FM_PROP_FONTRELIEF ) ) 1970 { 1971 Font aGridFont = pGrid->GetControlFont(); 1972 sal_Int16 nValue = ::comphelper::getINT16(Value); 1973 aGridFont.SetRelief( (FontRelief)nValue ); 1974 pGrid->SetControlFont( aGridFont ); 1975 } 1976 else if ( 0 == PropertyName.compareTo( FM_PROP_HELPURL ) ) 1977 { 1978 ::rtl::OUString sHelpURL; 1979 OSL_VERIFY( Value >>= sHelpURL ); 1980 INetURLObject aHID( sHelpURL ); 1981 if ( aHID.GetProtocol() == INET_PROT_HID ) 1982 sHelpURL = aHID.GetURLPath(); 1983 pGrid->SetHelpId( rtl::OUStringToOString( sHelpURL, RTL_TEXTENCODING_UTF8 ) ); 1984 } 1985 else if ( 0 == PropertyName.compareTo( FM_PROP_DISPLAYSYNCHRON ) ) 1986 { 1987 pGrid->setDisplaySynchron(::comphelper::getBOOL(Value)); 1988 } 1989 else if ( 0 == PropertyName.compareTo( FM_PROP_CURSORCOLOR ) ) 1990 { 1991 if (bVoid) 1992 pGrid->SetCursorColor(COL_TRANSPARENT); 1993 else 1994 pGrid->SetCursorColor( ::Color(::comphelper::getINT32(Value))); 1995 if (isDesignMode()) 1996 pGrid->Invalidate(); 1997 } 1998 else if ( 0 == PropertyName.compareTo( FM_PROP_ALWAYSSHOWCURSOR ) ) 1999 { 2000 pGrid->EnablePermanentCursor(::comphelper::getBOOL(Value)); 2001 if (isDesignMode()) 2002 pGrid->Invalidate(); 2003 } 2004 else if ( 0 == PropertyName.compareTo( FM_PROP_FONT ) ) 2005 { 2006 if ( bVoid ) 2007 pGrid->SetControlFont( Font() ); 2008 else 2009 { 2010 ::com::sun::star::awt::FontDescriptor aFont; 2011 if (Value >>= aFont) 2012 { 2013 Font aNewVclFont; 2014 if (::comphelper::operator!=(aFont, ::comphelper::getDefaultFont())) // ist das der Default 2015 aNewVclFont = ImplCreateFont( aFont ); 2016 2017 // need to add relief and emphasis (they're stored in a VCL-Font, but not in a FontDescriptor 2018 Font aOldVclFont = pGrid->GetControlFont(); 2019 aNewVclFont.SetRelief( aOldVclFont.GetRelief() ); 2020 aNewVclFont.SetEmphasisMark( aOldVclFont.GetEmphasisMark() ); 2021 2022 // now set it ... 2023 pGrid->SetControlFont( aNewVclFont ); 2024 2025 // if our row-height property is void (which means "calculate it font-dependent") we have 2026 // to adjust the control's row height 2027 Reference< XPropertySet > xModelSet(getColumns(), UNO_QUERY); 2028 if (xModelSet.is() && ::comphelper::hasProperty(FM_PROP_ROWHEIGHT, xModelSet)) 2029 { 2030 Any aHeight = xModelSet->getPropertyValue(FM_PROP_ROWHEIGHT); 2031 if (!aHeight.hasValue()) 2032 pGrid->SetDataRowHeight(0); 2033 } 2034 2035 } 2036 } 2037 } 2038 else if ( 0 == PropertyName.compareTo( FM_PROP_BACKGROUNDCOLOR ) ) 2039 { 2040 if ( bVoid ) 2041 { 2042 pGrid->SetControlBackground(); 2043 } 2044 else 2045 { 2046 ::Color aColor( ::comphelper::getINT32(Value) ); 2047 pGrid->SetBackground( aColor ); 2048 pGrid->SetControlBackground( aColor ); 2049 } 2050 } 2051 else if ( 0 == PropertyName.compareTo( FM_PROP_TEXTCOLOR ) ) 2052 { 2053 if ( bVoid ) 2054 { 2055 pGrid->SetControlForeground(); 2056 } 2057 else 2058 { 2059 ::Color aColor( ::comphelper::getINT32(Value) ); 2060 pGrid->SetTextColor( aColor ); 2061 pGrid->SetControlForeground( aColor ); 2062 } 2063 } 2064 else if ( 0 == PropertyName.compareTo( FM_PROP_ROWHEIGHT ) ) 2065 { 2066 sal_Int32 nLogHeight(0); 2067 if (Value >>= nLogHeight) 2068 { 2069 sal_Int32 nHeight = pGrid->LogicToPixel(Point(0,nLogHeight),MAP_10TH_MM).Y(); 2070 // take the zoom factor into account 2071 nHeight = pGrid->CalcZoom(nHeight); 2072 pGrid->SetDataRowHeight(nHeight); 2073 } 2074 else if (bVoid) 2075 pGrid->SetDataRowHeight(0); 2076 } 2077 else if ( 0 == PropertyName.compareTo( FM_PROP_HASNAVIGATION ) ) 2078 { 2079 sal_Bool bValue( sal_True ); 2080 OSL_VERIFY( Value >>= bValue ); 2081 pGrid->EnableNavigationBar( bValue ); 2082 } 2083 else if ( 0 == PropertyName.compareTo( FM_PROP_RECORDMARKER ) ) 2084 { 2085 sal_Bool bValue( sal_True ); 2086 OSL_VERIFY( Value >>= bValue ); 2087 pGrid->EnableHandle( bValue ); 2088 } 2089 else if ( 0 == PropertyName.compareTo( FM_PROP_ENABLED ) ) 2090 { 2091 sal_Bool bValue( sal_True ); 2092 OSL_VERIFY( Value >>= bValue ); 2093 pGrid->EnableHandle( bValue ); 2094 2095 // Im DesignModus nur das Datenfenster disablen 2096 // Sonst kann das Control nicht mehr konfiguriert werden 2097 if (isDesignMode()) 2098 pGrid->GetDataWindow().Enable( bValue ); 2099 else 2100 pGrid->Enable( bValue ); 2101 } 2102 else 2103 VCLXWindow::setProperty( PropertyName, Value ); 2104 } 2105 2106 //------------------------------------------------------------------------------ 2107 Reference< XAccessibleContext > FmXGridPeer::CreateAccessibleContext() 2108 { 2109 Reference< XAccessibleContext > xContext; 2110 2111 // use the AccessibleContext provided by the VCL window 2112 Window* pGrid = GetWindow(); 2113 if ( pGrid ) 2114 { 2115 Reference< XAccessible > xAcc( pGrid->GetAccessible( sal_True ) ); 2116 if ( xAcc.is() ) 2117 xContext = xAcc->getAccessibleContext(); 2118 // TODO: this has a slight conceptual problem: 2119 // 2120 // We know that the XAccessible and XAccessibleContext implementation of the browse 2121 // box is the same (the class implements both interfaces), which, speaking strictly, 2122 // is bad here (means when a browse box acts as UnoControl): We (the FmXGridPeer) are 2123 // the XAccessible here, and the browse box should be able to provide us an XAccessibleContext, 2124 // but it should _not_ be the XAccessible itself. 2125 // However, as long as no client implementation uses dirty hacks such as querying an 2126 // XAccessibleContext for XAccessible, this should not be a problem. 2127 } 2128 2129 if ( !xContext.is() ) 2130 xContext = VCLXWindow::CreateAccessibleContext( ); 2131 2132 return xContext; 2133 } 2134 2135 //------------------------------------------------------------------------------ 2136 Any FmXGridPeer::getProperty( const ::rtl::OUString& _rPropertyName ) throw( RuntimeException ) 2137 { 2138 Any aProp; 2139 if (GetWindow()) 2140 { 2141 FmGridControl* pGrid = (FmGridControl*) GetWindow(); 2142 Window* pDataWindow = &pGrid->GetDataWindow(); 2143 2144 if ( 0 == _rPropertyName.compareTo( FM_PROP_NAME ) ) 2145 { 2146 Font aFont = pDataWindow->GetControlFont(); 2147 aProp <<= ImplCreateFontDescriptor( aFont ); 2148 } 2149 else if ( 0 == _rPropertyName.compareTo( FM_PROP_TEXTCOLOR ) ) 2150 { 2151 aProp <<= (sal_Int32)pDataWindow->GetControlForeground().GetColor(); 2152 } 2153 else if ( 0 == _rPropertyName.compareTo( FM_PROP_BACKGROUNDCOLOR ) ) 2154 { 2155 aProp <<= (sal_Int32)pDataWindow->GetControlBackground().GetColor(); 2156 } 2157 else if ( 0 == _rPropertyName.compareTo( FM_PROP_ROWHEIGHT ) ) 2158 { 2159 sal_Int32 nPixelHeight = pGrid->GetDataRowHeight(); 2160 // take the zoom factor into account 2161 nPixelHeight = pGrid->CalcReverseZoom(nPixelHeight); 2162 aProp <<= (sal_Int32)pGrid->PixelToLogic(Point(0,nPixelHeight),MAP_10TH_MM).Y(); 2163 } 2164 else if ( 0 == _rPropertyName.compareTo( FM_PROP_HASNAVIGATION ) ) 2165 { 2166 sal_Bool bHasNavBar = pGrid->HasNavigationBar(); 2167 aProp <<= (sal_Bool)bHasNavBar; 2168 } 2169 else if ( 0 == _rPropertyName.compareTo( FM_PROP_RECORDMARKER ) ) 2170 { 2171 sal_Bool bHasHandle = pGrid->HasHandle(); 2172 aProp <<= (sal_Bool)bHasHandle; 2173 } 2174 else if ( 0 == _rPropertyName.compareTo( FM_PROP_ENABLED ) ) 2175 { 2176 aProp <<= (sal_Bool)pDataWindow->IsEnabled(); 2177 } 2178 else 2179 aProp = VCLXWindow::getProperty( _rPropertyName ); 2180 } 2181 return aProp; 2182 } 2183 2184 //------------------------------------------------------------------------------ 2185 void FmXGridPeer::dispose() throw( RuntimeException ) 2186 { 2187 EventObject aEvt; 2188 aEvt.Source = static_cast< ::cppu::OWeakObject* >(this); 2189 m_aModifyListeners.disposeAndClear(aEvt); 2190 m_aUpdateListeners.disposeAndClear(aEvt); 2191 m_aContainerListeners.disposeAndClear(aEvt); 2192 VCLXWindow::dispose(); 2193 2194 // release all interceptors 2195 // discovered during #100312# - 2002-10-23 - fs@openoffice.org 2196 Reference< XDispatchProviderInterceptor > xInterceptor( m_xFirstDispatchInterceptor ); 2197 m_xFirstDispatchInterceptor.clear(); 2198 while ( xInterceptor.is() ) 2199 { 2200 // tell the interceptor it has a new (means no) predecessor 2201 xInterceptor->setMasterDispatchProvider( NULL ); 2202 2203 // ask for it's successor 2204 Reference< XDispatchProvider > xSlave = xInterceptor->getSlaveDispatchProvider(); 2205 // and give it the new (means no) successoert 2206 xInterceptor->setSlaveDispatchProvider( NULL ); 2207 2208 // start over with the next chain element 2209 xInterceptor = xInterceptor.query( xSlave ); 2210 } 2211 2212 DisConnectFromDispatcher(); 2213 setRowSet(Reference< XRowSet > ()); 2214 } 2215 2216 // XContainer 2217 //------------------------------------------------------------------------------ 2218 void FmXGridPeer::addContainerListener(const Reference< XContainerListener >& l) throw( RuntimeException ) 2219 { 2220 m_aContainerListeners.addInterface( l ); 2221 } 2222 //------------------------------------------------------------------------------ 2223 void FmXGridPeer::removeContainerListener(const Reference< XContainerListener >& l) throw( RuntimeException ) 2224 { 2225 m_aContainerListeners.removeInterface( l ); 2226 } 2227 2228 // ::com::sun::star::data::XDatabaseCursorSupplier 2229 //------------------------------------------------------------------------------ 2230 void FmXGridPeer::startCursorListening() 2231 { 2232 if (!m_nCursorListening) 2233 { 2234 Reference< XRowSet > xRowSet(m_xCursor, UNO_QUERY); 2235 if (xRowSet.is()) 2236 xRowSet->addRowSetListener(this); 2237 2238 Reference< XReset > xReset(m_xCursor, UNO_QUERY); 2239 if (xReset.is()) 2240 xReset->addResetListener(this); 2241 2242 // alle Listener anmelden 2243 Reference< XPropertySet > xSet(m_xCursor, UNO_QUERY); 2244 if (xSet.is()) 2245 { 2246 xSet->addPropertyChangeListener(FM_PROP_ISMODIFIED, this); 2247 xSet->addPropertyChangeListener(FM_PROP_ROWCOUNT, this); 2248 } 2249 } 2250 m_nCursorListening++; 2251 } 2252 2253 //------------------------------------------------------------------------------ 2254 void FmXGridPeer::stopCursorListening() 2255 { 2256 if (!--m_nCursorListening) 2257 { 2258 Reference< XRowSet > xRowSet(m_xCursor, UNO_QUERY); 2259 if (xRowSet.is()) 2260 xRowSet->removeRowSetListener(this); 2261 2262 Reference< XReset > xReset(m_xCursor, UNO_QUERY); 2263 if (xReset.is()) 2264 xReset->removeResetListener(this); 2265 2266 Reference< XPropertySet > xSet(m_xCursor, UNO_QUERY); 2267 if (xSet.is()) 2268 { 2269 xSet->removePropertyChangeListener(FM_PROP_ISMODIFIED, this); 2270 xSet->removePropertyChangeListener(FM_PROP_ROWCOUNT, this); 2271 } 2272 } 2273 } 2274 2275 //------------------------------------------------------------------------------ 2276 void FmXGridPeer::updateGrid(const Reference< XRowSet >& _rxCursor) 2277 { 2278 FmGridControl* pGrid = (FmGridControl*)GetWindow(); 2279 if (pGrid) 2280 pGrid->setDataSource(_rxCursor); 2281 } 2282 2283 //------------------------------------------------------------------------------ 2284 Reference< XRowSet > FmXGridPeer::getRowSet() throw( RuntimeException ) 2285 { 2286 return m_xCursor; 2287 } 2288 2289 //------------------------------------------------------------------------------ 2290 void FmXGridPeer::setRowSet(const Reference< XRowSet >& _rDatabaseCursor) throw( RuntimeException ) 2291 { 2292 FmGridControl* pGrid = (FmGridControl*) GetWindow(); 2293 if (!pGrid || !m_xColumns.is() || !m_xColumns->getCount()) 2294 return; 2295 // alle Listener abmelden 2296 if (m_xCursor.is()) 2297 { 2298 Reference< XLoadable > xLoadable(m_xCursor, UNO_QUERY); 2299 // only if the form is loaded we set the rowset 2300 if (xLoadable.is()) 2301 { 2302 stopCursorListening(); 2303 xLoadable->removeLoadListener(this); 2304 } 2305 } 2306 2307 m_xCursor = _rDatabaseCursor; 2308 2309 if (pGrid) 2310 { 2311 Reference< XLoadable > xLoadable(m_xCursor, UNO_QUERY); 2312 // only if the form is loaded we set the rowset 2313 if (xLoadable.is() && xLoadable->isLoaded()) 2314 pGrid->setDataSource(m_xCursor); 2315 else 2316 pGrid->setDataSource(Reference< XRowSet > ()); 2317 2318 if (xLoadable.is()) 2319 { 2320 startCursorListening(); 2321 xLoadable->addLoadListener(this); 2322 } 2323 } 2324 } 2325 2326 //------------------------------------------------------------------------------ 2327 void SAL_CALL FmXGridPeer::addGridControlListener( const Reference< XGridControlListener >& _listener ) throw( RuntimeException ) 2328 { 2329 m_aGridControlListeners.addInterface( _listener ); 2330 } 2331 2332 //------------------------------------------------------------------------------ 2333 void SAL_CALL FmXGridPeer::removeGridControlListener( const Reference< XGridControlListener >& _listener ) throw( RuntimeException ) 2334 { 2335 m_aGridControlListeners.removeInterface( _listener ); 2336 } 2337 2338 //------------------------------------------------------------------------------ 2339 sal_Int16 FmXGridPeer::getCurrentColumnPosition() throw( RuntimeException ) 2340 { 2341 FmGridControl* pGrid = (FmGridControl*) GetWindow(); 2342 return pGrid ? pGrid->GetViewColumnPos(pGrid->GetCurColumnId()) : -1; 2343 } 2344 2345 //------------------------------------------------------------------------------ 2346 void FmXGridPeer::setCurrentColumnPosition(sal_Int16 nPos) throw( RuntimeException ) 2347 { 2348 FmGridControl* pGrid = (FmGridControl*) GetWindow(); 2349 if (pGrid) 2350 pGrid->GoToColumnId(pGrid->GetColumnIdFromViewPos(nPos)); 2351 } 2352 2353 //------------------------------------------------------------------------------ 2354 void FmXGridPeer::selectionChanged(const EventObject& evt) throw( RuntimeException ) 2355 { 2356 ::vos::OGuard aGuard(Application::GetSolarMutex()); 2357 2358 FmGridControl* pGrid = (FmGridControl*) GetWindow(); 2359 if (pGrid) 2360 { 2361 Reference< ::com::sun::star::view::XSelectionSupplier > xSelSupplier(evt.Source, UNO_QUERY); 2362 Any aSelection = xSelSupplier->getSelection(); 2363 DBG_ASSERT(aSelection.getValueType().getTypeClass() == TypeClass_INTERFACE, "FmXGridPeer::selectionChanged : invalid selection !"); 2364 Reference< XPropertySet > xSelection; 2365 aSelection >>= xSelection; 2366 if (xSelection.is()) 2367 { 2368 Reference< XPropertySet > xCol; 2369 sal_Int32 i = 0; 2370 sal_Int32 nColCount = m_xColumns->getCount(); 2371 2372 for (; i < nColCount; ++i) 2373 { 2374 m_xColumns->getByIndex(i) >>= xCol; 2375 if ( xCol == xSelection ) 2376 { 2377 pGrid->markColumn(pGrid->GetColumnIdFromModelPos((sal_uInt16)i)); 2378 break; 2379 } 2380 } 2381 // fuer das VCL-Control muessen die Columns 1-basiert sein 2382 // die Selektion an das VCL-Control weiterreichen, wenn noetig 2383 if ( i != pGrid->GetSelectedColumn() ) 2384 { // (wenn das nicht greift, wurde das selectionChanged implizit von dem Control selber ausgeloest 2385 if ( i < nColCount ) 2386 { 2387 pGrid->SelectColumnPos(pGrid->GetViewColumnPos(pGrid->GetColumnIdFromModelPos( (sal_uInt16)i )) + 1, sal_True); 2388 // SelectColumnPos hat wieder zu einem impliziten ActivateCell gefuehrt 2389 if (pGrid->IsEditing()) 2390 pGrid->DeactivateCell(); 2391 } 2392 else 2393 pGrid->SetNoSelection(); 2394 } 2395 } 2396 else 2397 pGrid->markColumn(USHRT_MAX); 2398 } 2399 } 2400 2401 // XElementAccess 2402 //------------------------------------------------------------------------------ 2403 sal_Bool FmXGridPeer::hasElements() throw( RuntimeException ) 2404 { 2405 return getCount() != 0; 2406 } 2407 2408 //------------------------------------------------------------------------------ 2409 Type SAL_CALL FmXGridPeer::getElementType( ) throw(RuntimeException) 2410 { 2411 return ::getCppuType((Reference< ::com::sun::star::awt::XControl> *)NULL); 2412 } 2413 2414 // XEnumerationAccess 2415 //------------------------------------------------------------------------------ 2416 Reference< XEnumeration > FmXGridPeer::createEnumeration() throw( RuntimeException ) 2417 { 2418 return new ::comphelper::OEnumerationByIndex(this); 2419 } 2420 2421 // XIndexAccess 2422 //------------------------------------------------------------------------------ 2423 sal_Int32 FmXGridPeer::getCount() throw( RuntimeException ) 2424 { 2425 FmGridControl* pGrid = (FmGridControl*) GetWindow(); 2426 if (pGrid) 2427 return pGrid->GetViewColCount(); 2428 else 2429 return 0; 2430 } 2431 2432 //------------------------------------------------------------------------------ 2433 Any FmXGridPeer::getByIndex(sal_Int32 _nIndex) throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) 2434 { 2435 FmGridControl* pGrid = (FmGridControl*) GetWindow(); 2436 if (_nIndex < 0 || 2437 _nIndex >= getCount() || !pGrid) 2438 throw IndexOutOfBoundsException(); 2439 2440 Any aElement; 2441 // get the columnid 2442 sal_uInt16 nId = pGrid->GetColumnIdFromViewPos((sal_uInt16)_nIndex); 2443 // get the list position 2444 sal_uInt16 nPos = pGrid->GetModelColumnPos(nId); 2445 2446 DbGridColumn* pCol = pGrid->GetColumns().GetObject(nPos); 2447 // DBG_ASSERT(pCol && pCol->GetCell(), "FmXGridPeer::getByIndex(): Invalid cell"); 2448 Reference< ::com::sun::star::awt::XControl > xControl(pCol->GetCell()); 2449 aElement <<= xControl; 2450 2451 return aElement; 2452 } 2453 2454 // ::com::sun::star::util::XModeSelector 2455 //------------------------------------------------------------------------------ 2456 void FmXGridPeer::setMode(const ::rtl::OUString& Mode) throw( NoSupportException, RuntimeException ) 2457 { 2458 if (!supportsMode(Mode)) 2459 throw NoSupportException(); 2460 2461 if (Mode == m_aMode) 2462 return; 2463 2464 m_aMode = Mode; 2465 2466 FmGridControl* pGrid = (FmGridControl*) GetWindow(); 2467 if ( Mode == ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterMode" ) ) ) 2468 pGrid->SetFilterMode(sal_True); 2469 else 2470 { 2471 pGrid->SetFilterMode(sal_False); 2472 pGrid->setDataSource(m_xCursor); 2473 } 2474 } 2475 2476 //------------------------------------------------------------------------------ 2477 ::rtl::OUString FmXGridPeer::getMode() throw( RuntimeException ) 2478 { 2479 return m_aMode; 2480 } 2481 2482 //------------------------------------------------------------------------------ 2483 ::comphelper::StringSequence FmXGridPeer::getSupportedModes() throw( RuntimeException ) 2484 { 2485 static ::comphelper::StringSequence aModes; 2486 if (!aModes.getLength()) 2487 { 2488 aModes.realloc(2); 2489 ::rtl::OUString* pModes = aModes.getArray(); 2490 pModes[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DataMode" ) ); 2491 pModes[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterMode" ) ); 2492 } 2493 return aModes; 2494 } 2495 2496 //------------------------------------------------------------------------------ 2497 sal_Bool FmXGridPeer::supportsMode(const ::rtl::OUString& Mode) throw( RuntimeException ) 2498 { 2499 ::comphelper::StringSequence aModes(getSupportedModes()); 2500 const ::rtl::OUString* pModes = aModes.getConstArray(); 2501 for (sal_Int32 i = aModes.getLength(); i > 0; ) 2502 { 2503 if (pModes[--i] == Mode) 2504 return sal_True; 2505 } 2506 return sal_False; 2507 } 2508 2509 //------------------------------------------------------------------------------ 2510 void FmXGridPeer::columnVisible(DbGridColumn* pColumn) 2511 { 2512 FmGridControl* pGrid = (FmGridControl*) GetWindow(); 2513 2514 sal_Int32 _nIndex = pGrid->GetModelColumnPos(pColumn->GetId()); 2515 Reference< ::com::sun::star::awt::XControl > xControl(pColumn->GetCell()); 2516 ContainerEvent aEvt; 2517 aEvt.Source = (XContainer*)this; 2518 aEvt.Accessor <<= _nIndex; 2519 aEvt.Element <<= xControl; 2520 2521 m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvt ); 2522 } 2523 2524 //------------------------------------------------------------------------------ 2525 void FmXGridPeer::columnHidden(DbGridColumn* pColumn) 2526 { 2527 FmGridControl* pGrid = (FmGridControl*) GetWindow(); 2528 2529 sal_Int32 _nIndex = pGrid->GetModelColumnPos(pColumn->GetId()); 2530 Reference< ::com::sun::star::awt::XControl > xControl(pColumn->GetCell()); 2531 ContainerEvent aEvt; 2532 aEvt.Source = (XContainer*)this; 2533 aEvt.Accessor <<= _nIndex; 2534 aEvt.Element <<= xControl; 2535 2536 m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, aEvt ); 2537 } 2538 2539 //------------------------------------------------------------------------------ 2540 void FmXGridPeer::draw( sal_Int32 x, sal_Int32 y ) throw( RuntimeException ) 2541 { 2542 FmGridControl* pGrid = (FmGridControl*) GetWindow(); 2543 sal_Int32 nOldFlags = pGrid->GetBrowserFlags(); 2544 pGrid->SetBrowserFlags(nOldFlags | EBBF_NOROWPICTURE); 2545 2546 VCLXWindow::draw(x, y); 2547 2548 pGrid->SetBrowserFlags(nOldFlags); 2549 } 2550 2551 //------------------------------------------------------------------------------ 2552 Reference< ::com::sun::star::frame::XDispatch > FmXGridPeer::queryDispatch(const ::com::sun::star::util::URL& aURL, const ::rtl::OUString& aTargetFrameName, sal_Int32 nSearchFlags) throw( RuntimeException ) 2553 { 2554 Reference< ::com::sun::star::frame::XDispatch > xResult; 2555 2556 // first ask our interceptor chain 2557 if (m_xFirstDispatchInterceptor.is() && !m_bInterceptingDispatch) 2558 { 2559 m_bInterceptingDispatch = sal_True; 2560 // safety against recursion : as we are master of the first chain element and slave of the last one we would 2561 // have an infinite loop without this if no dispatcher can fullfill the rewuest) 2562 xResult = m_xFirstDispatchInterceptor->queryDispatch(aURL, aTargetFrameName, nSearchFlags); 2563 m_bInterceptingDispatch = sal_False; 2564 } 2565 2566 // then ask ourself : we don't have any dispatches 2567 return xResult; 2568 } 2569 2570 //------------------------------------------------------------------------------ 2571 Sequence< Reference< ::com::sun::star::frame::XDispatch > > FmXGridPeer::queryDispatches(const Sequence< ::com::sun::star::frame::DispatchDescriptor>& aDescripts) throw( RuntimeException ) 2572 { 2573 if (m_xFirstDispatchInterceptor.is()) 2574 return m_xFirstDispatchInterceptor->queryDispatches(aDescripts); 2575 2576 // then ask ourself : we don't have any dispatches 2577 return Sequence< Reference< ::com::sun::star::frame::XDispatch > >(); 2578 } 2579 2580 //------------------------------------------------------------------------------ 2581 void FmXGridPeer::registerDispatchProviderInterceptor(const Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& _xInterceptor) throw( RuntimeException ) 2582 { 2583 if (_xInterceptor.is()) 2584 { 2585 if (m_xFirstDispatchInterceptor.is()) 2586 { 2587 Reference< ::com::sun::star::frame::XDispatchProvider > xFirstProvider(m_xFirstDispatchInterceptor, UNO_QUERY); 2588 // there is already an interceptor; the new one will become its master 2589 _xInterceptor->setSlaveDispatchProvider(xFirstProvider); 2590 m_xFirstDispatchInterceptor->setMasterDispatchProvider(xFirstProvider); 2591 } 2592 else 2593 { 2594 // it is the first interceptor; set ourself as slave 2595 _xInterceptor->setSlaveDispatchProvider((::com::sun::star::frame::XDispatchProvider*)this); 2596 } 2597 2598 // we are the master of the chain's first interceptor 2599 m_xFirstDispatchInterceptor = _xInterceptor; 2600 m_xFirstDispatchInterceptor->setMasterDispatchProvider((::com::sun::star::frame::XDispatchProvider*)this); 2601 2602 // we have a new interceptor and we're alive ? 2603 if (!isDesignMode()) 2604 // -> check for new dispatchers 2605 UpdateDispatches(); 2606 } 2607 } 2608 2609 //------------------------------------------------------------------------------ 2610 void FmXGridPeer::releaseDispatchProviderInterceptor(const Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& _xInterceptor) throw( RuntimeException ) 2611 { 2612 if (!_xInterceptor.is()) 2613 return; 2614 2615 Reference< ::com::sun::star::frame::XDispatchProviderInterceptor > xChainWalk(m_xFirstDispatchInterceptor); 2616 2617 if (m_xFirstDispatchInterceptor == _xInterceptor) 2618 { // our chain will have a new first element 2619 Reference< ::com::sun::star::frame::XDispatchProviderInterceptor > xSlave(m_xFirstDispatchInterceptor->getSlaveDispatchProvider(), UNO_QUERY); 2620 m_xFirstDispatchInterceptor = xSlave; 2621 } 2622 // do this before removing the interceptor from the chain as we won't know it's slave afterwards) 2623 2624 while (xChainWalk.is()) 2625 { 2626 // walk along the chain of interceptors and look for the interceptor that has to be removed 2627 Reference< ::com::sun::star::frame::XDispatchProviderInterceptor > xSlave(xChainWalk->getSlaveDispatchProvider(), UNO_QUERY); 2628 2629 if (xChainWalk == _xInterceptor) 2630 { 2631 // old master may be an interceptor too 2632 Reference< ::com::sun::star::frame::XDispatchProviderInterceptor > xMaster(xChainWalk->getMasterDispatchProvider(), UNO_QUERY); 2633 2634 // unchain the interceptor that has to be removed 2635 xChainWalk->setSlaveDispatchProvider(Reference< ::com::sun::star::frame::XDispatchProvider > ()); 2636 xChainWalk->setMasterDispatchProvider(Reference< ::com::sun::star::frame::XDispatchProvider > ()); 2637 2638 // reconnect the chain 2639 if (xMaster.is()) 2640 { 2641 if (xSlave.is()) 2642 xMaster->setSlaveDispatchProvider(Reference< ::com::sun::star::frame::XDispatchProvider >::query(xSlave)); 2643 else 2644 // it's the first interceptor of the chain, set ourself as slave 2645 xMaster->setSlaveDispatchProvider((::com::sun::star::frame::XDispatchProvider*)this); 2646 } 2647 else 2648 { 2649 // the chain's first element was removed, set ourself as new master of the second one 2650 if (xSlave.is()) 2651 xSlave->setMasterDispatchProvider((::com::sun::star::frame::XDispatchProvider*)this); 2652 } 2653 } 2654 2655 xChainWalk = xSlave; 2656 } 2657 // our interceptor chain has changed and we're alive ? 2658 if (!isDesignMode()) 2659 // -> check the dispatchers 2660 UpdateDispatches(); 2661 } 2662 2663 //------------------------------------------------------------------------------ 2664 void FmXGridPeer::statusChanged(const ::com::sun::star::frame::FeatureStateEvent& Event) throw( RuntimeException ) 2665 { 2666 DBG_ASSERT(m_pStateCache, "FmXGridPeer::statusChanged : invalid call !"); 2667 DBG_ASSERT(m_pDispatchers, "FmXGridPeer::statusChanged : invalid call !"); 2668 2669 Sequence< ::com::sun::star::util::URL>& aUrls = getSupportedURLs(); 2670 const ::com::sun::star::util::URL* pUrls = aUrls.getConstArray(); 2671 2672 Sequence<sal_uInt16> aSlots = getSupportedGridSlots(); 2673 const sal_uInt16* pSlots = aSlots.getConstArray(); 2674 2675 sal_uInt16 i; 2676 for (i=0; i<aUrls.getLength(); ++i, ++pUrls, ++pSlots) 2677 { 2678 if (pUrls->Main == Event.FeatureURL.Main) 2679 { 2680 DBG_ASSERT(m_pDispatchers[i] == Event.Source, "FmXGridPeer::statusChanged : the event source is a little bit suspect !"); 2681 m_pStateCache[i] = Event.IsEnabled; 2682 FmGridControl* pGrid = (FmGridControl*) GetWindow(); 2683 if (*pSlots != SID_FM_RECORD_UNDO) 2684 pGrid->GetNavigationBar().InvalidateState(*pSlots); 2685 break; 2686 } 2687 } 2688 DBG_ASSERT(i<aUrls.getLength(), "FmXGridPeer::statusChanged : got a call for an unknown url !"); 2689 } 2690 2691 //------------------------------------------------------------------------------ 2692 sal_Bool FmXGridPeer::approveReset(const EventObject& /*rEvent*/) throw( RuntimeException ) 2693 { 2694 return sal_True; 2695 } 2696 2697 //------------------------------------------------------------------------------ 2698 sal_Bool SAL_CALL FmXGridPeer::select( const Any& _rSelection ) throw (IllegalArgumentException, RuntimeException) 2699 { 2700 Sequence< Any > aBookmarks; 2701 if ( !( _rSelection >>= aBookmarks ) ) 2702 throw IllegalArgumentException(); 2703 2704 FmGridControl* pVclControl = static_cast<FmGridControl*>(GetWindow()); 2705 return pVclControl->selectBookmarks(aBookmarks); 2706 2707 // TODO: 2708 // speaking strictly, we would have to adjust our model, as our ColumnSelection may have changed. 2709 // Our model is a XSelectionSupplier, too, it handles the selection of single columns. 2710 // This is somewhat strange, as selection should be a view (not a model) aspect. 2711 // So for a clean solution, we should handle column selection ourself, and the model shouldn't 2712 // deal with selection at all. 2713 } 2714 2715 //------------------------------------------------------------------------------ 2716 Any SAL_CALL FmXGridPeer::getSelection( ) throw (RuntimeException) 2717 { 2718 FmGridControl* pVclControl = static_cast<FmGridControl*>(GetWindow()); 2719 Sequence< Any > aSelectionBookmarks = pVclControl->getSelectionBookmarks(); 2720 return makeAny(aSelectionBookmarks); 2721 } 2722 2723 //------------------------------------------------------------------------------ 2724 void SAL_CALL FmXGridPeer::addSelectionChangeListener( const Reference< XSelectionChangeListener >& _rxListener ) throw (RuntimeException) 2725 { 2726 m_aSelectionListeners.addInterface( _rxListener ); 2727 } 2728 2729 //------------------------------------------------------------------------------ 2730 void SAL_CALL FmXGridPeer::removeSelectionChangeListener( const Reference< XSelectionChangeListener >& _rxListener ) throw (RuntimeException) 2731 { 2732 m_aSelectionListeners.removeInterface( _rxListener ); 2733 } 2734 2735 //------------------------------------------------------------------------------ 2736 void FmXGridPeer::resetted(const EventObject& rEvent) throw( RuntimeException ) 2737 { 2738 if (m_xColumns == rEvent.Source) 2739 { // my model was reset -> refresh the grid content 2740 FmGridControl* pGrid = (FmGridControl*)GetWindow(); 2741 if (!pGrid) 2742 return; 2743 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 2744 pGrid->resetCurrentRow(); 2745 } 2746 // if the cursor fired a reset event we seem to be on the insert row 2747 else if (m_xCursor == rEvent.Source) 2748 { 2749 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 2750 FmGridControl* pGrid = (FmGridControl*) GetWindow(); 2751 if (pGrid && pGrid->IsOpen()) 2752 pGrid->positioned(rEvent); 2753 } 2754 } 2755 2756 //------------------------------------------------------------------------------ 2757 Sequence<sal_uInt16>& FmXGridPeer::getSupportedGridSlots() 2758 { 2759 static Sequence<sal_uInt16> aSupported; 2760 if (aSupported.getLength() == 0) 2761 { 2762 sal_uInt16 nSupported[] = { 2763 DbGridControl::NavigationBar::RECORD_FIRST, 2764 DbGridControl::NavigationBar::RECORD_PREV, 2765 DbGridControl::NavigationBar::RECORD_NEXT, 2766 DbGridControl::NavigationBar::RECORD_LAST, 2767 DbGridControl::NavigationBar::RECORD_NEW, 2768 SID_FM_RECORD_UNDO 2769 }; 2770 aSupported.realloc(sizeof(nSupported)/sizeof(nSupported[0])); 2771 sal_uInt16* pSupported = aSupported.getArray(); 2772 for (sal_uInt16 i=0; i<aSupported.getLength(); ++i, ++pSupported) 2773 *pSupported = nSupported[i]; 2774 } 2775 return aSupported; 2776 } 2777 2778 //------------------------------------------------------------------------------ 2779 Sequence< ::com::sun::star::util::URL>& FmXGridPeer::getSupportedURLs() 2780 { 2781 static Sequence< ::com::sun::star::util::URL> aSupported; 2782 if (aSupported.getLength() == 0) 2783 { 2784 static ::rtl::OUString sSupported[] = { 2785 FMURL_RECORD_MOVEFIRST, 2786 FMURL_RECORD_MOVEPREV, 2787 FMURL_RECORD_MOVENEXT, 2788 FMURL_RECORD_MOVELAST, 2789 FMURL_RECORD_MOVETONEW, 2790 FMURL_RECORD_UNDO 2791 }; 2792 aSupported.realloc(sizeof(sSupported)/sizeof(sSupported[0])); 2793 ::com::sun::star::util::URL* pSupported = aSupported.getArray(); 2794 sal_uInt16 i; 2795 2796 for ( i = 0; i < aSupported.getLength(); ++i, ++pSupported) 2797 pSupported->Complete = sSupported[i]; 2798 2799 // let an ::com::sun::star::util::URL-transformer normalize the URLs 2800 Reference< ::com::sun::star::util::XURLTransformer > xTransformer( 2801 ::comphelper::getProcessServiceFactory()->createInstance( 2802 ::rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer")), 2803 UNO_QUERY); 2804 pSupported = aSupported.getArray(); 2805 if (xTransformer.is()) 2806 { 2807 for (i=0; i<aSupported.getLength(); ++i) 2808 xTransformer->parseStrict(pSupported[i]); 2809 } 2810 } 2811 2812 return aSupported; 2813 } 2814 2815 //------------------------------------------------------------------------------ 2816 void FmXGridPeer::UpdateDispatches() 2817 { 2818 if (!m_pStateCache) 2819 { // we don't have any dispatchers yet -> do the initial connect 2820 ConnectToDispatcher(); 2821 return; 2822 } 2823 2824 sal_uInt16 nDispatchersGot = 0; 2825 const Sequence< ::com::sun::star::util::URL>& aSupportedURLs = getSupportedURLs(); 2826 const ::com::sun::star::util::URL* pSupportedURLs = aSupportedURLs.getConstArray(); 2827 Reference< ::com::sun::star::frame::XDispatch > xNewDispatch; 2828 for (sal_uInt16 i=0; i<aSupportedURLs.getLength(); ++i, ++pSupportedURLs) 2829 { 2830 xNewDispatch = queryDispatch(*pSupportedURLs, rtl::OUString(), 0); 2831 if (xNewDispatch != m_pDispatchers[i]) 2832 { 2833 if (m_pDispatchers[i].is()) 2834 m_pDispatchers[i]->removeStatusListener((::com::sun::star::frame::XStatusListener*)this, *pSupportedURLs); 2835 m_pDispatchers[i] = xNewDispatch; 2836 if (m_pDispatchers[i].is()) 2837 m_pDispatchers[i]->addStatusListener((::com::sun::star::frame::XStatusListener*)this, *pSupportedURLs); 2838 } 2839 if (m_pDispatchers[i].is()) 2840 ++nDispatchersGot; 2841 } 2842 2843 if (!nDispatchersGot) 2844 { 2845 delete[] m_pStateCache; 2846 delete[] m_pDispatchers; 2847 m_pStateCache = NULL; 2848 m_pDispatchers = NULL; 2849 } 2850 } 2851 2852 //------------------------------------------------------------------------------ 2853 void FmXGridPeer::ConnectToDispatcher() 2854 { 2855 DBG_ASSERT((m_pStateCache != NULL) == (m_pDispatchers != NULL), "FmXGridPeer::ConnectToDispatcher : inconsistent !"); 2856 if (m_pStateCache) 2857 { // already connected -> just do an update 2858 UpdateDispatches(); 2859 return; 2860 } 2861 2862 const Sequence< ::com::sun::star::util::URL>& aSupportedURLs = getSupportedURLs(); 2863 2864 // _before_ adding the status listeners (as the add should result in a statusChanged-call) ! 2865 m_pStateCache = new sal_Bool[aSupportedURLs.getLength()]; 2866 m_pDispatchers = new Reference< ::com::sun::star::frame::XDispatch > [aSupportedURLs.getLength()]; 2867 2868 sal_uInt16 nDispatchersGot = 0; 2869 const ::com::sun::star::util::URL* pSupportedURLs = aSupportedURLs.getConstArray(); 2870 for (sal_uInt16 i=0; i<aSupportedURLs.getLength(); ++i, ++pSupportedURLs) 2871 { 2872 m_pStateCache[i] = 0; 2873 m_pDispatchers[i] = queryDispatch(*pSupportedURLs, rtl::OUString(), 0); 2874 if (m_pDispatchers[i].is()) 2875 { 2876 m_pDispatchers[i]->addStatusListener((::com::sun::star::frame::XStatusListener*)this, *pSupportedURLs); 2877 ++nDispatchersGot; 2878 } 2879 } 2880 2881 if (!nDispatchersGot) 2882 { 2883 delete[] m_pStateCache; 2884 delete[] m_pDispatchers; 2885 m_pStateCache = NULL; 2886 m_pDispatchers = NULL; 2887 } 2888 } 2889 2890 //------------------------------------------------------------------------------ 2891 void FmXGridPeer::DisConnectFromDispatcher() 2892 { 2893 if (!m_pStateCache || !m_pDispatchers) 2894 return; 2895 // we're not connected 2896 2897 const Sequence< ::com::sun::star::util::URL>& aSupportedURLs = getSupportedURLs(); 2898 const ::com::sun::star::util::URL* pSupportedURLs = aSupportedURLs.getConstArray(); 2899 for (sal_uInt16 i=0; i<aSupportedURLs.getLength(); ++i, ++pSupportedURLs) 2900 { 2901 if (m_pDispatchers[i].is()) 2902 m_pDispatchers[i]->removeStatusListener((::com::sun::star::frame::XStatusListener*)this, *pSupportedURLs); 2903 } 2904 2905 delete[] m_pStateCache; 2906 delete[] m_pDispatchers; 2907 m_pStateCache = NULL; 2908 m_pDispatchers = NULL; 2909 } 2910 2911 //------------------------------------------------------------------------------ 2912 IMPL_LINK(FmXGridPeer, OnQueryGridSlotState, void*, pSlot) 2913 { 2914 if (!m_pStateCache) 2915 return -1; // unspecified 2916 2917 sal_uInt16 nSlot = (sal_uInt16)(sal_uIntPtr)pSlot; 2918 2919 // search the given slot with our supported sequence 2920 Sequence<sal_uInt16>& aSupported = getSupportedGridSlots(); 2921 const sal_uInt16* pSlots = aSupported.getConstArray(); 2922 for (sal_uInt16 i=0; i<aSupported.getLength(); ++i) 2923 { 2924 if (pSlots[i] == nSlot) 2925 { 2926 if (!m_pDispatchers[i].is()) 2927 return -1; // nothing known about this slot 2928 else 2929 return m_pStateCache[i]; 2930 } 2931 } 2932 2933 return -1; 2934 } 2935 2936 //------------------------------------------------------------------------------ 2937 IMPL_LINK(FmXGridPeer, OnExecuteGridSlot, void*, pSlot) 2938 { 2939 if (!m_pDispatchers) 2940 return 0; // not handled 2941 2942 Sequence< ::com::sun::star::util::URL>& aUrls = getSupportedURLs(); 2943 const ::com::sun::star::util::URL* pUrls = aUrls.getConstArray(); 2944 2945 Sequence<sal_uInt16> aSlots = getSupportedGridSlots(); 2946 const sal_uInt16* pSlots = aSlots.getConstArray(); 2947 2948 DBG_ASSERT(aSlots.getLength() == aUrls.getLength(), "FmXGridPeer::OnExecuteGridSlot : inconstent data returned by getSupportedURLs/getSupportedGridSlots !"); 2949 2950 sal_uInt16 nSlot = (sal_uInt16)(sal_uIntPtr)pSlot; 2951 for (sal_uInt16 i=0; i<aSlots.getLength(); ++i, ++pUrls, ++pSlots) 2952 { 2953 if (*pSlots == nSlot) 2954 { 2955 if (m_pDispatchers[i].is()) 2956 { 2957 // commit any changes done so far, if it's not the undoRecord URL 2958 if ( 0 == pUrls->Complete.compareTo( FMURL_RECORD_UNDO ) || commit() ) 2959 m_pDispatchers[i]->dispatch(*pUrls, Sequence< PropertyValue>()); 2960 2961 return 1; // handled 2962 } 2963 } 2964 } 2965 2966 return 0; // not handled 2967 } 2968 2969