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 32 #include "filtnav.hxx" 33 #include "fmexch.hxx" 34 #include "fmhelp.hrc" 35 #include "fmitems.hxx" 36 #include "fmprop.hrc" 37 #include "svx/fmresids.hrc" 38 #include "gridcell.hxx" 39 40 /** === begin UNO includes === **/ 41 #include <com/sun/star/form/runtime/XFormController.hpp> 42 #include <com/sun/star/lang/XUnoTunnel.hpp> 43 #include <com/sun/star/util/XNumberFormatter.hpp> 44 /** === end UNO includes === **/ 45 46 #include <comphelper/processfactory.hxx> 47 #include <svx/fmtools.hxx> 48 #include <comphelper/property.hxx> 49 #include <comphelper/sequence.hxx> 50 #include <comphelper/uno3.hxx> 51 #include <connectivity/dbtools.hxx> 52 #include <cppuhelper/implbase1.hxx> 53 #include <fmservs.hxx> 54 #include <fmshimp.hxx> 55 #include <rtl/logfile.hxx> 56 #include <sfx2/dispatch.hxx> 57 #include <sfx2/objitem.hxx> 58 #include <sfx2/objsh.hxx> 59 #include <sfx2/request.hxx> 60 #include <svx/dialmgr.hxx> 61 #include <svx/fmshell.hxx> 62 #include <svx/svxids.hrc> 63 #include <tools/shl.hxx> 64 #include <vcl/wrkwin.hxx> 65 66 #include <functional> 67 68 #define SYNC_DELAY 200 69 #define DROP_ACTION_TIMER_INITIAL_TICKS 10 70 // solange dauert es, bis das Scrollen anspringt 71 #define DROP_ACTION_TIMER_SCROLL_TICKS 3 72 // in diesen Intervallen wird jeweils eine Zeile gescrollt 73 #define DROP_ACTION_TIMER_TICK_BASE 10 74 // das ist die Basis, mit der beide Angaben multipliziert werden (in ms) 75 76 using namespace ::svxform; 77 using namespace ::connectivity::simple; 78 using namespace ::connectivity; 79 80 81 //........................................................................ 82 namespace svxform 83 { 84 //........................................................................ 85 86 /** === begin UNO using === **/ 87 using ::com::sun::star::uno::Reference; 88 using ::com::sun::star::lang::XMultiServiceFactory; 89 using ::com::sun::star::awt::TextEvent; 90 using ::com::sun::star::container::XIndexAccess; 91 using ::com::sun::star::uno::UNO_QUERY; 92 using ::com::sun::star::beans::XPropertySet; 93 using ::com::sun::star::form::runtime::XFormController; 94 using ::com::sun::star::form::runtime::XFilterController; 95 using ::com::sun::star::form::runtime::XFilterControllerListener; 96 using ::com::sun::star::form::runtime::FilterEvent; 97 using ::com::sun::star::lang::EventObject; 98 using ::com::sun::star::uno::RuntimeException; 99 using ::com::sun::star::form::XForm; 100 using ::com::sun::star::container::XChild; 101 using ::com::sun::star::awt::XControl; 102 using ::com::sun::star::sdbc::XConnection; 103 using ::com::sun::star::util::XNumberFormatsSupplier; 104 using ::com::sun::star::beans::XPropertySet; 105 using ::com::sun::star::util::XNumberFormatter; 106 using ::com::sun::star::sdbc::XRowSet; 107 using ::com::sun::star::lang::Locale; 108 using ::com::sun::star::sdb::SQLContext; 109 using ::com::sun::star::uno::XInterface; 110 using ::com::sun::star::uno::UNO_QUERY_THROW; 111 using ::com::sun::star::uno::UNO_SET_THROW; 112 using ::com::sun::star::uno::Exception; 113 using ::com::sun::star::awt::XTextComponent; 114 using ::com::sun::star::uno::Sequence; 115 /** === end UNO using === **/ 116 117 //======================================================================== 118 OFilterItemExchange::OFilterItemExchange() 119 { 120 } 121 122 //------------------------------------------------------------------------ 123 void OFilterItemExchange::AddSupportedFormats() 124 { 125 AddFormat(getFormatId()); 126 } 127 128 //------------------------------------------------------------------------ 129 sal_uInt32 OFilterItemExchange::getFormatId() 130 { 131 static sal_uInt32 s_nFormat = (sal_uInt32)-1; 132 if ((sal_uInt32)-1 == s_nFormat) 133 { 134 s_nFormat = SotExchange::RegisterFormatName(String::CreateFromAscii("application/x-openoffice;windows_formatname=\"form.FilterControlExchange\"")); 135 DBG_ASSERT((sal_uInt32)-1 != s_nFormat, "OFilterExchangeHelper::getFormatId: bad exchange id!"); 136 } 137 return s_nFormat; 138 } 139 140 //------------------------------------------------------------------------ 141 OLocalExchange* OFilterExchangeHelper::createExchange() const 142 { 143 return new OFilterItemExchange; 144 } 145 146 //======================================================================== 147 TYPEINIT0(FmFilterData); 148 Image FmFilterData::GetImage( BmpColorMode /*_eMode*/ ) const 149 { 150 return Image(); 151 } 152 153 //======================================================================== 154 TYPEINIT1(FmParentData, FmFilterData); 155 //------------------------------------------------------------------------ 156 FmParentData::~FmParentData() 157 { 158 for (::std::vector<FmFilterData*>::const_iterator i = m_aChildren.begin(); 159 i != m_aChildren.end(); i++) 160 delete (*i); 161 } 162 163 //======================================================================== 164 TYPEINIT1(FmFormItem, FmParentData); 165 //------------------------------------------------------------------------ 166 Image FmFormItem::GetImage( BmpColorMode _eMode ) const 167 { 168 static Image aImage; 169 static Image aImage_HC; 170 171 if (!aImage) 172 { 173 ImageList aNavigatorImages( SVX_RES( RID_SVXIMGLIST_FMEXPL ) ); 174 ImageList aNavigatorImages_HC( SVX_RES( RID_SVXIMGLIST_FMEXPL_HC ) ); 175 176 aImage = aNavigatorImages.GetImage( RID_SVXIMG_FORM ); 177 aImage_HC = aNavigatorImages_HC.GetImage( RID_SVXIMG_FORM ); 178 } 179 return ( BMP_COLOR_HIGHCONTRAST == _eMode ) ? aImage_HC : aImage; 180 } 181 182 //======================================================================== 183 TYPEINIT1(FmFilterItems, FmParentData); 184 //------------------------------------------------------------------------ 185 FmFilterItem* FmFilterItems::Find( const ::sal_Int32 _nFilterComponentIndex ) const 186 { 187 for ( ::std::vector< FmFilterData* >::const_iterator i = m_aChildren.begin(); 188 i != m_aChildren.end(); 189 ++i 190 ) 191 { 192 FmFilterItem* pCondition = PTR_CAST( FmFilterItem, *i ); 193 DBG_ASSERT( pCondition, "FmFilterItems::Find: Wrong element in container!" ); 194 if ( _nFilterComponentIndex == pCondition->GetComponentIndex() ) 195 return pCondition; 196 } 197 return NULL; 198 } 199 200 //------------------------------------------------------------------------ 201 Image FmFilterItems::GetImage( BmpColorMode _eMode ) const 202 { 203 static Image aImage; 204 static Image aImage_HC; 205 206 if (!aImage) 207 { 208 ImageList aNavigatorImages( SVX_RES( RID_SVXIMGLIST_FMEXPL ) ); 209 ImageList aNavigatorImages_HC( SVX_RES( RID_SVXIMGLIST_FMEXPL_HC ) ); 210 211 aImage = aNavigatorImages.GetImage( RID_SVXIMG_FILTER ); 212 aImage_HC = aNavigatorImages_HC.GetImage( RID_SVXIMG_FILTER ); 213 } 214 return ( BMP_COLOR_HIGHCONTRAST == _eMode ) ? aImage_HC : aImage; 215 } 216 217 //======================================================================== 218 TYPEINIT1(FmFilterItem, FmFilterData); 219 //------------------------------------------------------------------------ 220 FmFilterItem::FmFilterItem( const Reference< XMultiServiceFactory >& _rxFactory, 221 FmFilterItems* pParent, 222 const ::rtl::OUString& aFieldName, 223 const ::rtl::OUString& aText, 224 const sal_Int32 _nComponentIndex ) 225 :FmFilterData(_rxFactory,pParent, aText) 226 ,m_aFieldName(aFieldName) 227 ,m_nComponentIndex( _nComponentIndex ) 228 { 229 } 230 231 //------------------------------------------------------------------------ 232 Image FmFilterItem::GetImage( BmpColorMode _eMode ) const 233 { 234 static Image aImage; 235 static Image aImage_HC; 236 237 if (!aImage) 238 { 239 ImageList aNavigatorImages( SVX_RES( RID_SVXIMGLIST_FMEXPL ) ); 240 ImageList aNavigatorImages_HC( SVX_RES( RID_SVXIMGLIST_FMEXPL_HC ) ); 241 242 aImage = aNavigatorImages.GetImage( RID_SVXIMG_FIELD ); 243 aImage_HC = aNavigatorImages_HC.GetImage( RID_SVXIMG_FIELD ); 244 } 245 return ( BMP_COLOR_HIGHCONTRAST == _eMode ) ? aImage_HC : aImage; 246 } 247 248 //======================================================================== 249 // Hints for communicatition between model and view 250 //======================================================================== 251 class FmFilterHint : public SfxHint 252 { 253 FmFilterData* m_pData; 254 255 public: 256 TYPEINFO(); 257 FmFilterHint(FmFilterData* pData):m_pData(pData){} 258 FmFilterData* GetData() const { return m_pData; } 259 }; 260 TYPEINIT1( FmFilterHint, SfxHint ); 261 262 //======================================================================== 263 class FmFilterInsertedHint : public FmFilterHint 264 { 265 sal_Int32 m_nPos; // Position relative to the parent of the data 266 267 public: 268 TYPEINFO(); 269 FmFilterInsertedHint(FmFilterData* pData, sal_Int32 nRelPos) 270 :FmFilterHint(pData) 271 ,m_nPos(nRelPos){} 272 273 sal_Int32 GetPos() const { return m_nPos; } 274 }; 275 TYPEINIT1( FmFilterInsertedHint, FmFilterHint ); 276 277 //======================================================================== 278 class FmFilterRemovedHint : public FmFilterHint 279 { 280 public: 281 TYPEINFO(); 282 FmFilterRemovedHint(FmFilterData* pData) 283 :FmFilterHint(pData){} 284 285 }; 286 TYPEINIT1( FmFilterRemovedHint, FmFilterHint ); 287 288 //======================================================================== 289 class FmFilterTextChangedHint : public FmFilterHint 290 { 291 public: 292 TYPEINFO(); 293 FmFilterTextChangedHint(FmFilterData* pData) 294 :FmFilterHint(pData){} 295 296 }; 297 TYPEINIT1( FmFilterTextChangedHint, FmFilterHint ); 298 299 //======================================================================== 300 class FilterClearingHint : public SfxHint 301 { 302 public: 303 TYPEINFO(); 304 FilterClearingHint(){} 305 }; 306 TYPEINIT1( FilterClearingHint, SfxHint ); 307 308 //======================================================================== 309 class FmFilterCurrentChangedHint : public SfxHint 310 { 311 public: 312 TYPEINFO(); 313 FmFilterCurrentChangedHint(){} 314 }; 315 TYPEINIT1( FmFilterCurrentChangedHint, SfxHint ); 316 317 //======================================================================== 318 // class FmFilterAdapter, Listener an den FilterControls 319 //======================================================================== 320 class FmFilterAdapter : public ::cppu::WeakImplHelper1< XFilterControllerListener > 321 { 322 FmFilterModel* m_pModel; 323 Reference< XIndexAccess > m_xControllers; 324 325 public: 326 FmFilterAdapter(FmFilterModel* pModel, const Reference< XIndexAccess >& xControllers); 327 328 // XEventListener 329 virtual void SAL_CALL disposing(const EventObject& Source) throw( RuntimeException ); 330 331 // XFilterControllerListener 332 virtual void SAL_CALL predicateExpressionChanged( const FilterEvent& _Event ) throw (RuntimeException); 333 virtual void SAL_CALL disjunctiveTermRemoved( const FilterEvent& _Event ) throw (RuntimeException); 334 virtual void SAL_CALL disjunctiveTermAdded( const FilterEvent& _Event ) throw (RuntimeException); 335 336 // helpers 337 void dispose() throw( RuntimeException ); 338 339 void AddOrRemoveListener( const Reference< XIndexAccess >& _rxControllers, const bool _bAdd ); 340 341 void setText(sal_Int32 nPos, 342 const FmFilterItem* pFilterItem, 343 const ::rtl::OUString& rText); 344 }; 345 346 //------------------------------------------------------------------------ 347 FmFilterAdapter::FmFilterAdapter(FmFilterModel* pModel, const Reference< XIndexAccess >& xControllers) 348 :m_pModel( pModel ) 349 ,m_xControllers( xControllers ) 350 { 351 AddOrRemoveListener( m_xControllers, true ); 352 } 353 354 //------------------------------------------------------------------------ 355 void FmFilterAdapter::dispose() throw( RuntimeException ) 356 { 357 AddOrRemoveListener( m_xControllers, false ); 358 } 359 360 //------------------------------------------------------------------------ 361 void FmFilterAdapter::AddOrRemoveListener( const Reference< XIndexAccess >& _rxControllers, const bool _bAdd ) 362 { 363 for (sal_Int32 i = 0, nLen = _rxControllers->getCount(); i < nLen; ++i) 364 { 365 Reference< XIndexAccess > xElement( _rxControllers->getByIndex(i), UNO_QUERY ); 366 367 // step down 368 AddOrRemoveListener( xElement, _bAdd ); 369 370 // handle this particular controller 371 Reference< XFilterController > xController( xElement, UNO_QUERY ); 372 OSL_ENSURE( xController.is(), "FmFilterAdapter::InsertElements: no XFilterController, cannot sync data!" ); 373 if ( xController.is() ) 374 { 375 if ( _bAdd ) 376 xController->addFilterControllerListener( this ); 377 else 378 xController->removeFilterControllerListener( this ); 379 } 380 } 381 } 382 383 //------------------------------------------------------------------------ 384 void FmFilterAdapter::setText(sal_Int32 nRowPos, 385 const FmFilterItem* pFilterItem, 386 const ::rtl::OUString& rText) 387 { 388 FmFormItem* pFormItem = PTR_CAST( FmFormItem, pFilterItem->GetParent()->GetParent() ); 389 390 try 391 { 392 Reference< XFilterController > xController( pFormItem->GetController(), UNO_QUERY_THROW ); 393 xController->setPredicateExpression( pFilterItem->GetComponentIndex(), nRowPos, rText ); 394 } 395 catch( const Exception& ) 396 { 397 DBG_UNHANDLED_EXCEPTION(); 398 } 399 } 400 401 402 // XEventListener 403 //------------------------------------------------------------------------ 404 void SAL_CALL FmFilterAdapter::disposing(const EventObject& /*e*/) throw( RuntimeException ) 405 { 406 } 407 408 //------------------------------------------------------------------------ 409 namespace 410 { 411 ::rtl::OUString lcl_getLabelName_nothrow( const Reference< XControl >& _rxControl ) 412 { 413 ::rtl::OUString sLabelName; 414 try 415 { 416 Reference< XControl > xControl( _rxControl, UNO_SET_THROW ); 417 Reference< XPropertySet > xModel( xControl->getModel(), UNO_QUERY_THROW ); 418 sLabelName = getLabelName( xModel ); 419 } 420 catch( const Exception& ) 421 { 422 DBG_UNHANDLED_EXCEPTION(); 423 } 424 return sLabelName; 425 } 426 427 Reference< XPropertySet > lcl_getBoundField_nothrow( const Reference< XControl >& _rxControl ) 428 { 429 Reference< XPropertySet > xField; 430 try 431 { 432 Reference< XControl > xControl( _rxControl, UNO_SET_THROW ); 433 Reference< XPropertySet > xModelProps( xControl->getModel(), UNO_QUERY_THROW ); 434 xField.set( xModelProps->getPropertyValue( FM_PROP_BOUNDFIELD ), UNO_QUERY_THROW ); 435 } 436 catch( const Exception& ) 437 { 438 DBG_UNHANDLED_EXCEPTION(); 439 } 440 return xField; 441 } 442 } 443 444 // XFilterControllerListener 445 //------------------------------------------------------------------------ 446 void FmFilterAdapter::predicateExpressionChanged( const FilterEvent& _Event ) throw( RuntimeException ) 447 { 448 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 449 450 if ( !m_pModel ) 451 return; 452 453 // the controller which sent the event 454 Reference< XFormController > xController( _Event.Source, UNO_QUERY_THROW ); 455 Reference< XFilterController > xFilterController( _Event.Source, UNO_QUERY_THROW ); 456 Reference< XForm > xForm( xController->getModel(), UNO_QUERY_THROW ); 457 458 FmFormItem* pFormItem = m_pModel->Find( m_pModel->m_aChildren, xForm ); 459 OSL_ENSURE( pFormItem, "FmFilterAdapter::predicateExpressionChanged: don't know this form!" ); 460 if ( !pFormItem ) 461 return; 462 463 const sal_Int32 nActiveTerm( xFilterController->getActiveTerm() ); 464 465 FmFilterItems* pFilter = PTR_CAST( FmFilterItems, pFormItem->GetChildren()[ nActiveTerm ] ); 466 FmFilterItem* pFilterItem = pFilter->Find( _Event.FilterComponent ); 467 if ( pFilterItem ) 468 { 469 if ( _Event.PredicateExpression.getLength()) 470 { 471 pFilterItem->SetText( _Event.PredicateExpression ); 472 // UI benachrichtigen 473 FmFilterTextChangedHint aChangeHint(pFilterItem); 474 m_pModel->Broadcast( aChangeHint ); 475 } 476 else 477 { 478 // no text anymore so remove the condition 479 m_pModel->Remove(pFilterItem); 480 } 481 } 482 else 483 { 484 // searching the component by field name 485 ::rtl::OUString aFieldName( lcl_getLabelName_nothrow( xFilterController->getFilterComponent( _Event.FilterComponent ) ) ); 486 487 pFilterItem = new FmFilterItem( m_pModel->getORB(), pFilter, aFieldName, _Event.PredicateExpression, _Event.FilterComponent ); 488 m_pModel->Insert(pFilter->GetChildren().end(), pFilterItem); 489 } 490 491 // ensure there's one empty term in the filter, just in case the active term was previously empty 492 m_pModel->EnsureEmptyFilterRows( *pFormItem ); 493 } 494 495 //------------------------------------------------------------------------ 496 void SAL_CALL FmFilterAdapter::disjunctiveTermRemoved( const FilterEvent& _Event ) throw (RuntimeException) 497 { 498 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 499 500 Reference< XFormController > xController( _Event.Source, UNO_QUERY_THROW ); 501 Reference< XFilterController > xFilterController( _Event.Source, UNO_QUERY_THROW ); 502 Reference< XForm > xForm( xController->getModel(), UNO_QUERY_THROW ); 503 504 FmFormItem* pFormItem = m_pModel->Find( m_pModel->m_aChildren, xForm ); 505 OSL_ENSURE( pFormItem, "FmFilterAdapter::disjunctiveTermRemoved: don't know this form!" ); 506 if ( !pFormItem ) 507 return; 508 509 ::std::vector< FmFilterData* >& rTermItems = pFormItem->GetChildren(); 510 const bool bValidIndex = ( _Event.DisjunctiveTerm >= 0 ) && ( (size_t)_Event.DisjunctiveTerm < rTermItems.size() ); 511 OSL_ENSURE( bValidIndex, "FmFilterAdapter::disjunctiveTermRemoved: invalid term index!" ); 512 if ( !bValidIndex ) 513 return; 514 515 // if the first term was removed, then the to-be first term needs its text updated 516 if ( _Event.DisjunctiveTerm == 0 ) 517 { 518 rTermItems[1]->SetText( String( SVX_RES( RID_STR_FILTER_FILTER_FOR ) ) ); 519 FmFilterTextChangedHint aChangeHint( rTermItems[1] ); 520 m_pModel->Broadcast( aChangeHint ); 521 } 522 523 // finally remove the entry from the model 524 m_pModel->Remove( rTermItems.begin() + _Event.DisjunctiveTerm ); 525 526 // ensure there's one empty term in the filter, just in case the currently removed one was the last empty one 527 m_pModel->EnsureEmptyFilterRows( *pFormItem ); 528 } 529 530 //------------------------------------------------------------------------ 531 void SAL_CALL FmFilterAdapter::disjunctiveTermAdded( const FilterEvent& _Event ) throw (RuntimeException) 532 { 533 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 534 535 Reference< XFormController > xController( _Event.Source, UNO_QUERY_THROW ); 536 Reference< XFilterController > xFilterController( _Event.Source, UNO_QUERY_THROW ); 537 Reference< XForm > xForm( xController->getModel(), UNO_QUERY_THROW ); 538 539 FmFormItem* pFormItem = m_pModel->Find( m_pModel->m_aChildren, xForm ); 540 OSL_ENSURE( pFormItem, "FmFilterAdapter::disjunctiveTermAdded: don't know this form!" ); 541 if ( !pFormItem ) 542 return; 543 544 const sal_Int32 nInsertPos = _Event.DisjunctiveTerm; 545 bool bValidIndex = ( nInsertPos >= 0 ) && ( (size_t)nInsertPos <= pFormItem->GetChildren().size() ); 546 if ( !bValidIndex ) 547 { 548 OSL_ENSURE( false, "FmFilterAdapter::disjunctiveTermAdded: invalid index!" ); 549 return; 550 } 551 552 const ::std::vector< FmFilterData* >::iterator insertPos = pFormItem->GetChildren().begin() + nInsertPos; 553 554 FmFilterItems* pFilterItems = new FmFilterItems( m_pModel->getORB(), pFormItem, String( SVX_RES( RID_STR_FILTER_FILTER_OR ) ) ); 555 m_pModel->Insert( insertPos, pFilterItems ); 556 } 557 558 //======================================================================== 559 // class FmFilterModel 560 //======================================================================== 561 TYPEINIT1(FmFilterModel, FmParentData); 562 //------------------------------------------------------------------------ 563 FmFilterModel::FmFilterModel(const Reference< XMultiServiceFactory >& _rxFactory) 564 :FmParentData(_rxFactory,NULL, ::rtl::OUString()) 565 ,OSQLParserClient(_rxFactory) 566 ,m_xORB(_rxFactory) 567 ,m_pAdapter(NULL) 568 ,m_pCurrentItems(NULL) 569 { 570 } 571 572 //------------------------------------------------------------------------ 573 FmFilterModel::~FmFilterModel() 574 { 575 Clear(); 576 } 577 578 //------------------------------------------------------------------------ 579 void FmFilterModel::Clear() 580 { 581 // notify 582 FilterClearingHint aClearedHint; 583 Broadcast( aClearedHint ); 584 585 // loose endings 586 if (m_pAdapter) 587 { 588 m_pAdapter->dispose(); 589 m_pAdapter->release(); 590 m_pAdapter= NULL; 591 } 592 593 m_pCurrentItems = NULL; 594 m_xController = NULL; 595 m_xControllers = NULL; 596 597 for (::std::vector<FmFilterData*>::const_iterator i = m_aChildren.begin(); 598 i != m_aChildren.end(); i++) 599 delete (*i); 600 601 m_aChildren.clear(); 602 } 603 604 //------------------------------------------------------------------------ 605 void FmFilterModel::Update(const Reference< XIndexAccess > & xControllers, const Reference< XFormController > & xCurrent) 606 { 607 if ( xCurrent == m_xController ) 608 return; 609 610 if (!xControllers.is()) 611 { 612 Clear(); 613 return; 614 } 615 616 // there is only a new current controller 617 if ( m_xControllers != xControllers ) 618 { 619 Clear(); 620 621 m_xControllers = xControllers; 622 Update(m_xControllers, this); 623 624 DBG_ASSERT(xCurrent.is(), "FmFilterModel::Update(...) no current controller"); 625 626 // Listening for TextChanges 627 m_pAdapter = new FmFilterAdapter(this, xControllers); 628 m_pAdapter->acquire(); 629 630 SetCurrentController(xCurrent); 631 EnsureEmptyFilterRows( *this ); 632 } 633 else 634 SetCurrentController(xCurrent); 635 } 636 637 //------------------------------------------------------------------------ 638 void FmFilterModel::Update(const Reference< XIndexAccess > & xControllers, FmParentData* pParent) 639 { 640 try 641 { 642 sal_Int32 nCount = xControllers->getCount(); 643 for ( sal_Int32 i = 0; i < nCount; ++i ) 644 { 645 Reference< XFormController > xController( xControllers->getByIndex(i), UNO_QUERY_THROW ); 646 647 Reference< XPropertySet > xFormProperties( xController->getModel(), UNO_QUERY_THROW ); 648 ::rtl::OUString aName; 649 OSL_VERIFY( xFormProperties->getPropertyValue( FM_PROP_NAME ) >>= aName ); 650 651 // Insert a new item for the form 652 FmFormItem* pFormItem = new FmFormItem( m_xORB, pParent, xController, aName ); 653 Insert( pParent->GetChildren().end(), pFormItem ); 654 655 Reference< XFilterController > xFilterController( pFormItem->GetFilterController(), UNO_SET_THROW ); 656 657 // insert the existing filters for the form 658 String aTitle( SVX_RES( RID_STR_FILTER_FILTER_FOR ) ); 659 660 Sequence< Sequence< ::rtl::OUString > > aExpressions = xFilterController->getPredicateExpressions(); 661 for ( const Sequence< ::rtl::OUString >* pConjunctionTerm = aExpressions.getConstArray(); 662 pConjunctionTerm != aExpressions.getConstArray() + aExpressions.getLength(); 663 ++pConjunctionTerm 664 ) 665 { 666 // we always display one row, even if there's no term to be displayed 667 FmFilterItems* pFilterItems = new FmFilterItems( m_xORB, pFormItem, aTitle ); 668 Insert( pFormItem->GetChildren().end(), pFilterItems ); 669 670 const Sequence< ::rtl::OUString >& rDisjunction( *pConjunctionTerm ); 671 for ( const ::rtl::OUString* pDisjunctiveTerm = rDisjunction.getConstArray(); 672 pDisjunctiveTerm != rDisjunction.getConstArray() + rDisjunction.getLength(); 673 ++pDisjunctiveTerm 674 ) 675 { 676 if ( pDisjunctiveTerm->getLength() == 0 ) 677 // no condition for this particular component in this particular conjunction term 678 continue; 679 680 const sal_Int32 nComponentIndex = pDisjunctiveTerm - rDisjunction.getConstArray(); 681 682 // determine the display name of the control 683 const Reference< XControl > xFilterControl( xFilterController->getFilterComponent( nComponentIndex ) ); 684 const ::rtl::OUString sDisplayName( lcl_getLabelName_nothrow( xFilterControl ) ); 685 686 // insert a new entry 687 FmFilterItem* pANDCondition = new FmFilterItem( m_xORB, pFilterItems, sDisplayName, *pDisjunctiveTerm, nComponentIndex ); 688 Insert( pFilterItems->GetChildren().end(), pANDCondition ); 689 } 690 691 // title for the next conditions 692 aTitle = SVX_RES( RID_STR_FILTER_FILTER_OR ); 693 } 694 695 // now add dependent controllers 696 Reference< XIndexAccess > xControllerAsIndex( xController, UNO_QUERY ); 697 Update( xControllerAsIndex, pFormItem ); 698 } 699 } 700 catch( const Exception& ) 701 { 702 DBG_UNHANDLED_EXCEPTION(); 703 } 704 } 705 706 //------------------------------------------------------------------------ 707 FmFormItem* FmFilterModel::Find(const ::std::vector<FmFilterData*>& rItems, const Reference< XFormController > & xController) const 708 { 709 for (::std::vector<FmFilterData*>::const_iterator i = rItems.begin(); 710 i != rItems.end(); i++) 711 { 712 FmFormItem* pForm = PTR_CAST(FmFormItem,*i); 713 if (pForm) 714 { 715 if ( xController == pForm->GetController() ) 716 return pForm; 717 else 718 { 719 pForm = Find(pForm->GetChildren(), xController); 720 if (pForm) 721 return pForm; 722 } 723 } 724 } 725 return NULL; 726 } 727 728 //------------------------------------------------------------------------ 729 FmFormItem* FmFilterModel::Find(const ::std::vector<FmFilterData*>& rItems, const Reference< XForm >& xForm) const 730 { 731 for (::std::vector<FmFilterData*>::const_iterator i = rItems.begin(); 732 i != rItems.end(); i++) 733 { 734 FmFormItem* pForm = PTR_CAST(FmFormItem,*i); 735 if (pForm) 736 { 737 if (xForm == pForm->GetController()->getModel()) 738 return pForm; 739 else 740 { 741 pForm = Find(pForm->GetChildren(), xForm); 742 if (pForm) 743 return pForm; 744 } 745 } 746 } 747 return NULL; 748 } 749 750 //------------------------------------------------------------------------ 751 void FmFilterModel::SetCurrentController(const Reference< XFormController > & xCurrent) 752 { 753 if ( xCurrent == m_xController ) 754 return; 755 756 m_xController = xCurrent; 757 758 FmFormItem* pItem = Find( m_aChildren, xCurrent ); 759 if ( !pItem ) 760 return; 761 762 try 763 { 764 Reference< XFilterController > xFilterController( m_xController, UNO_QUERY_THROW ); 765 const sal_Int32 nActiveTerm( xFilterController->getActiveTerm() ); 766 if ( pItem->GetChildren().size() > (size_t)nActiveTerm ) 767 { 768 SetCurrentItems( static_cast< FmFilterItems* >( pItem->GetChildren()[ nActiveTerm ] ) ); 769 } 770 } 771 catch( const Exception& ) 772 { 773 DBG_UNHANDLED_EXCEPTION(); 774 } 775 } 776 777 //------------------------------------------------------------------------ 778 void FmFilterModel::AppendFilterItems( FmFormItem& _rFormItem ) 779 { 780 // insert the condition behind the last filter items 781 ::std::vector<FmFilterData*>::reverse_iterator iter; 782 for ( iter = _rFormItem.GetChildren().rbegin(); 783 iter != _rFormItem.GetChildren().rend(); 784 ++iter 785 ) 786 { 787 if ((*iter)->ISA(FmFilterItems)) 788 break; 789 } 790 791 sal_Int32 nInsertPos = iter.base() - _rFormItem.GetChildren().begin(); 792 // delegate this to the FilterController, it will notify us, which will let us update our model 793 try 794 { 795 Reference< XFilterController > xFilterController( _rFormItem.GetFilterController(), UNO_SET_THROW ); 796 if ( nInsertPos >= xFilterController->getDisjunctiveTerms() ) 797 xFilterController->appendEmptyDisjunctiveTerm(); 798 } 799 catch( const Exception& ) 800 { 801 DBG_UNHANDLED_EXCEPTION(); 802 } 803 } 804 805 //------------------------------------------------------------------------ 806 void FmFilterModel::Insert(const ::std::vector<FmFilterData*>::iterator& rPos, FmFilterData* pData) 807 { 808 ::std::vector<FmFilterData*>& rItems = pData->GetParent()->GetChildren(); 809 sal_Int32 nPos = rPos == rItems.end() ? LIST_APPEND : rPos - rItems.begin(); 810 rItems.insert(rPos, pData); 811 812 // UI benachrichtigen 813 FmFilterInsertedHint aInsertedHint(pData, nPos); 814 Broadcast( aInsertedHint ); 815 } 816 817 //------------------------------------------------------------------------ 818 void FmFilterModel::Remove(FmFilterData* pData) 819 { 820 FmParentData* pParent = pData->GetParent(); 821 ::std::vector<FmFilterData*>& rItems = pParent->GetChildren(); 822 823 // erase the item from the model 824 ::std::vector<FmFilterData*>::iterator i = ::std::find(rItems.begin(), rItems.end(), pData); 825 DBG_ASSERT(i != rItems.end(), "FmFilterModel::Remove(): unknown Item"); 826 // position within the parent 827 sal_Int32 nPos = i - rItems.begin(); 828 if (pData->ISA(FmFilterItems)) 829 { 830 FmFormItem* pFormItem = (FmFormItem*)pParent; 831 832 try 833 { 834 Reference< XFilterController > xFilterController( pFormItem->GetFilterController(), UNO_SET_THROW ); 835 836 bool bEmptyLastTerm = ( ( nPos == 0 ) && xFilterController->getDisjunctiveTerms() == 1 ); 837 if ( bEmptyLastTerm ) 838 { 839 // remove all children (by setting an empty predicate expression) 840 ::std::vector< FmFilterData* >& rChildren = ((FmFilterItems*)pData)->GetChildren(); 841 while ( !rChildren.empty() ) 842 { 843 ::std::vector< FmFilterData* >::iterator removePos = rChildren.end() - 1; 844 FmFilterItem* pFilterItem = PTR_CAST( FmFilterItem, *removePos ); 845 m_pAdapter->setText( nPos, pFilterItem, ::rtl::OUString() ); 846 Remove( removePos ); 847 } 848 } 849 else 850 { 851 xFilterController->removeDisjunctiveTerm( nPos ); 852 } 853 } 854 catch( const Exception& ) 855 { 856 DBG_UNHANDLED_EXCEPTION(); 857 } 858 } 859 else // FormItems can not be deleted 860 { 861 FmFilterItem* pFilterItem = PTR_CAST(FmFilterItem, pData); 862 863 // if its the last condition remove the parent 864 if (rItems.size() == 1) 865 Remove(pFilterItem->GetParent()); 866 else 867 { 868 // find the position of the father within his father 869 ::std::vector<FmFilterData*>& rParentParentItems = pData->GetParent()->GetParent()->GetChildren(); 870 ::std::vector<FmFilterData*>::iterator j = ::std::find(rParentParentItems.begin(), rParentParentItems.end(), pFilterItem->GetParent()); 871 DBG_ASSERT(j != rParentParentItems.end(), "FmFilterModel::Remove(): unknown Item"); 872 sal_Int32 nParentPos = j - rParentParentItems.begin(); 873 874 // EmptyText removes the filter 875 m_pAdapter->setText(nParentPos, pFilterItem, ::rtl::OUString()); 876 Remove( i ); 877 } 878 } 879 } 880 881 //------------------------------------------------------------------------ 882 void FmFilterModel::Remove( const ::std::vector<FmFilterData*>::iterator& rPos ) 883 { 884 // remove from parent's child list 885 FmFilterData* pData = *rPos; 886 pData->GetParent()->GetChildren().erase( rPos ); 887 888 // notify the view, this will remove the actual SvLBoxEntry 889 FmFilterRemovedHint aRemoveHint( pData ); 890 Broadcast( aRemoveHint ); 891 892 delete pData; 893 } 894 895 //------------------------------------------------------------------------ 896 sal_Bool FmFilterModel::ValidateText(FmFilterItem* pItem, UniString& rText, UniString& rErrorMsg) const 897 { 898 FmFormItem* pFormItem = PTR_CAST( FmFormItem, pItem->GetParent()->GetParent() ); 899 try 900 { 901 Reference< XFormController > xFormController( pFormItem->GetController() ); 902 // obtain the connection of the form belonging to the controller 903 OStaticDataAccessTools aStaticTools; 904 Reference< XRowSet > xRowSet( xFormController->getModel(), UNO_QUERY_THROW ); 905 Reference< XConnection > xConnection( aStaticTools.getRowSetConnection( xRowSet ) ); 906 907 // obtain a number formatter for this connection 908 // TODO: shouldn't this be cached? 909 Reference< XNumberFormatsSupplier > xFormatSupplier = aStaticTools.getNumberFormats( xConnection, sal_True ); 910 Reference< XNumberFormatter > xFormatter( m_xORB->createInstance( FM_NUMBER_FORMATTER ), UNO_QUERY ); 911 xFormatter->attachNumberFormatsSupplier( xFormatSupplier ); 912 913 // get the field (database column) which the item is responsible for 914 Reference< XFilterController > xFilterController( xFormController, UNO_QUERY_THROW ); 915 Reference< XPropertySet > xField( lcl_getBoundField_nothrow( xFilterController->getFilterComponent( pItem->GetComponentIndex() ) ), UNO_SET_THROW ); 916 917 // parse the given text as filter predicate 918 ::rtl::OUString aErr, aTxt( rText ); 919 ::rtl::Reference< ISQLParseNode > xParseNode = predicateTree( aErr, aTxt, xFormatter, xField ); 920 rErrorMsg = aErr; 921 rText = aTxt; 922 if ( xParseNode.is() ) 923 { 924 ::rtl::OUString aPreparedText; 925 Locale aAppLocale = Application::GetSettings().GetUILocale(); 926 xParseNode->parseNodeToPredicateStr( 927 aPreparedText, xConnection, xFormatter, xField, aAppLocale, '.', getParseContext() ); 928 rText = aPreparedText; 929 return sal_True; 930 } 931 } 932 catch( const Exception& ) 933 { 934 DBG_UNHANDLED_EXCEPTION(); 935 } 936 937 return sal_False; 938 } 939 940 //------------------------------------------------------------------------ 941 void FmFilterModel::Append(FmFilterItems* pItems, FmFilterItem* pFilterItem) 942 { 943 Insert(pItems->GetChildren().end(), pFilterItem); 944 } 945 946 //------------------------------------------------------------------------ 947 void FmFilterModel::SetTextForItem(FmFilterItem* pItem, const ::rtl::OUString& rText) 948 { 949 ::std::vector<FmFilterData*>& rItems = pItem->GetParent()->GetParent()->GetChildren(); 950 ::std::vector<FmFilterData*>::iterator i = ::std::find(rItems.begin(), rItems.end(), pItem->GetParent()); 951 sal_Int32 nParentPos = i - rItems.begin(); 952 953 m_pAdapter->setText(nParentPos, pItem, rText); 954 955 if (!rText) 956 Remove(pItem); 957 else 958 { 959 // Change the text 960 pItem->SetText(rText); 961 FmFilterTextChangedHint aChangeHint(pItem); 962 Broadcast( aChangeHint ); 963 } 964 } 965 966 //------------------------------------------------------------------------ 967 void FmFilterModel::SetCurrentItems(FmFilterItems* pCurrent) 968 { 969 if (m_pCurrentItems == pCurrent) 970 return; 971 972 // search for the condition 973 if (pCurrent) 974 { 975 FmFormItem* pFormItem = (FmFormItem*)pCurrent->GetParent(); 976 ::std::vector<FmFilterData*>& rItems = pFormItem->GetChildren(); 977 ::std::vector<FmFilterData*>::const_iterator i = ::std::find(rItems.begin(), rItems.end(), pCurrent); 978 979 if (i != rItems.end()) 980 { 981 // determine the filter position 982 sal_Int32 nPos = i - rItems.begin(); 983 try 984 { 985 Reference< XFilterController > xFilterController( pFormItem->GetFilterController(), UNO_SET_THROW ); 986 xFilterController->setActiveTerm( nPos ); 987 } 988 catch( const Exception& ) 989 { 990 DBG_UNHANDLED_EXCEPTION(); 991 } 992 993 if ( m_xController != pFormItem->GetController() ) 994 // calls SetCurrentItems again 995 SetCurrentController( pFormItem->GetController() ); 996 else 997 m_pCurrentItems = pCurrent; 998 } 999 else 1000 m_pCurrentItems = NULL; 1001 } 1002 else 1003 m_pCurrentItems = NULL; 1004 1005 1006 // UI benachrichtigen 1007 FmFilterCurrentChangedHint aHint; 1008 Broadcast( aHint ); 1009 } 1010 1011 //------------------------------------------------------------------------ 1012 void FmFilterModel::EnsureEmptyFilterRows( FmParentData& _rItem ) 1013 { 1014 // checks whether for each form there's one free level for input 1015 ::std::vector< FmFilterData* >& rChildren = _rItem.GetChildren(); 1016 sal_Bool bAppendLevel = _rItem.ISA( FmFormItem ); 1017 1018 for ( ::std::vector<FmFilterData*>::iterator i = rChildren.begin(); 1019 i != rChildren.end(); 1020 ++i 1021 ) 1022 { 1023 FmFilterItems* pItems = PTR_CAST(FmFilterItems, *i); 1024 if ( pItems && pItems->GetChildren().empty() ) 1025 { 1026 bAppendLevel = sal_False; 1027 break; 1028 } 1029 1030 FmFormItem* pFormItem = PTR_CAST(FmFormItem, *i); 1031 if (pFormItem) 1032 { 1033 EnsureEmptyFilterRows( *pFormItem ); 1034 continue; 1035 } 1036 } 1037 1038 if ( bAppendLevel ) 1039 { 1040 FmFormItem* pFormItem = PTR_CAST( FmFormItem, &_rItem ); 1041 OSL_ENSURE( pFormItem, "FmFilterModel::EnsureEmptyFilterRows: no FmFormItem, but a FmFilterItems child?" ); 1042 if ( pFormItem ) 1043 AppendFilterItems( *pFormItem ); 1044 } 1045 } 1046 1047 //======================================================================== 1048 // class FmFilterItemsString 1049 //======================================================================== 1050 class FmFilterItemsString : public SvLBoxString 1051 { 1052 public: 1053 FmFilterItemsString( SvLBoxEntry* pEntry, sal_uInt16 nFlags, const XubString& rStr ) 1054 :SvLBoxString(pEntry,nFlags,rStr){} 1055 1056 virtual void Paint(const Point& rPos, SvLBox& rDev, sal_uInt16 nFlags, SvLBoxEntry* pEntry); 1057 virtual void InitViewData( SvLBox* pView,SvLBoxEntry* pEntry, SvViewDataItem* pViewData); 1058 }; 1059 1060 const int nxDBmp = 12; 1061 //------------------------------------------------------------------------ 1062 void FmFilterItemsString::Paint(const Point& rPos, SvLBox& rDev, sal_uInt16 /*nFlags*/, SvLBoxEntry* pEntry ) 1063 { 1064 FmFilterItems* pRow = (FmFilterItems*)pEntry->GetUserData(); 1065 FmFormItem* pForm = (FmFormItem*)pRow->GetParent(); 1066 1067 // current filter is significant painted 1068 const bool bIsCurrentFilter = pForm->GetChildren()[ pForm->GetFilterController()->getActiveTerm() ] == pRow; 1069 if ( bIsCurrentFilter ) 1070 { 1071 rDev.Push( PUSH_LINECOLOR ); 1072 1073 rDev.SetLineColor( rDev.GetTextColor() ); 1074 1075 Rectangle aRect( rPos, GetSize( &rDev, pEntry ) ); 1076 Point aFirst( rPos.X(), aRect.Bottom() - 6 ); 1077 Point aSecond(aFirst .X() + 2, aFirst.Y() + 3 ); 1078 1079 rDev.DrawLine( aFirst, aSecond ); 1080 1081 aFirst = aSecond; 1082 aFirst.X() += 1; 1083 aSecond.X() += 6; 1084 aSecond.Y() -= 5; 1085 1086 rDev.DrawLine( aFirst, aSecond ); 1087 1088 rDev.Pop(); 1089 } 1090 1091 rDev.DrawText( Point(rPos.X() + nxDBmp, rPos.Y()), GetText() ); 1092 } 1093 1094 //------------------------------------------------------------------------ 1095 void FmFilterItemsString::InitViewData( SvLBox* pView,SvLBoxEntry* pEntry, SvViewDataItem* pViewData) 1096 { 1097 if( !pViewData ) 1098 pViewData = pView->GetViewDataItem( pEntry, this ); 1099 1100 Size aSize(pView->GetTextWidth(GetText()), pView->GetTextHeight()); 1101 aSize.Width() += nxDBmp; 1102 pViewData->aSize = aSize; 1103 } 1104 1105 //======================================================================== 1106 // class FmFilterString 1107 //======================================================================== 1108 class FmFilterString : public SvLBoxString 1109 { 1110 UniString m_aName; 1111 1112 public: 1113 FmFilterString( SvLBoxEntry* pEntry, sal_uInt16 nFlags, const XubString& rStr, const UniString& aName) 1114 :SvLBoxString(pEntry,nFlags,rStr) 1115 ,m_aName(aName) 1116 { 1117 m_aName.AppendAscii(": "); 1118 } 1119 1120 virtual void Paint(const Point& rPos, SvLBox& rDev, sal_uInt16 nFlags, SvLBoxEntry* pEntry); 1121 virtual void InitViewData( SvLBox* pView,SvLBoxEntry* pEntry, SvViewDataItem* pViewData); 1122 }; 1123 1124 const int nxD = 4; 1125 1126 //------------------------------------------------------------------------ 1127 void FmFilterString::InitViewData( SvLBox* pView,SvLBoxEntry* pEntry, SvViewDataItem* pViewData) 1128 { 1129 if( !pViewData ) 1130 pViewData = pView->GetViewDataItem( pEntry, this ); 1131 1132 Font aOldFont( pView->GetFont()); 1133 Font aFont( aOldFont ); 1134 aFont.SetWeight(WEIGHT_BOLD); 1135 pView->SetFont( aFont ); 1136 1137 Size aSize(pView->GetTextWidth(m_aName), pView->GetTextHeight()); 1138 pView->SetFont( aOldFont ); 1139 aSize.Width() += pView->GetTextWidth(GetText()) + nxD; 1140 pViewData->aSize = aSize; 1141 } 1142 1143 //------------------------------------------------------------------------ 1144 void FmFilterString::Paint(const Point& rPos, SvLBox& rDev, sal_uInt16 /*nFlags*/, SvLBoxEntry* /*pEntry*/ ) 1145 { 1146 Font aOldFont( rDev.GetFont()); 1147 Font aFont( aOldFont ); 1148 aFont.SetWeight(WEIGHT_BOLD); 1149 rDev.SetFont( aFont ); 1150 1151 Point aPos(rPos); 1152 rDev.DrawText( aPos, m_aName ); 1153 1154 // position for the second text 1155 aPos.X() += rDev.GetTextWidth(m_aName) + nxD; 1156 rDev.SetFont( aOldFont ); 1157 rDev.DrawText( aPos, GetText() ); 1158 } 1159 1160 //======================================================================== 1161 // class FmFilterNavigator 1162 //======================================================================== 1163 FmFilterNavigator::FmFilterNavigator( Window* pParent ) 1164 :SvTreeListBox( pParent, WB_HASBUTTONS|WB_HASLINES|WB_BORDER|WB_HASBUTTONSATROOT ) 1165 ,m_pModel( NULL ) 1166 ,m_pEditingCurrently( NULL ) 1167 ,m_aControlExchange( this ) 1168 ,m_aTimerCounter( 0 ) 1169 ,m_aDropActionType( DA_SCROLLUP ) 1170 { 1171 SetHelpId( HID_FILTER_NAVIGATOR ); 1172 1173 { 1174 { 1175 ImageList aNavigatorImages( SVX_RES( RID_SVXIMGLIST_FMEXPL ) ); 1176 SetNodeBitmaps( 1177 aNavigatorImages.GetImage( RID_SVXIMG_COLLAPSEDNODE ), 1178 aNavigatorImages.GetImage( RID_SVXIMG_EXPANDEDNODE ), 1179 BMP_COLOR_NORMAL 1180 ); 1181 } 1182 { 1183 ImageList aNavigatorImages( SVX_RES( RID_SVXIMGLIST_FMEXPL_HC ) ); 1184 SetNodeBitmaps( 1185 aNavigatorImages.GetImage( RID_SVXIMG_COLLAPSEDNODE ), 1186 aNavigatorImages.GetImage( RID_SVXIMG_EXPANDEDNODE ), 1187 BMP_COLOR_HIGHCONTRAST 1188 ); 1189 } 1190 } 1191 1192 m_pModel = new FmFilterModel(comphelper::getProcessServiceFactory()); 1193 StartListening( *m_pModel ); 1194 1195 EnableInplaceEditing( sal_True ); 1196 SetSelectionMode(MULTIPLE_SELECTION); 1197 1198 SetDragDropMode(0xFFFF); 1199 1200 m_aDropActionTimer.SetTimeoutHdl(LINK(this, FmFilterNavigator, OnDropActionTimer)); 1201 } 1202 1203 //------------------------------------------------------------------------ 1204 FmFilterNavigator::~FmFilterNavigator() 1205 { 1206 EndListening( *m_pModel ); 1207 delete m_pModel; 1208 } 1209 1210 //------------------------------------------------------------------------ 1211 void FmFilterNavigator::Clear() 1212 { 1213 m_pModel->Clear(); 1214 } 1215 1216 //------------------------------------------------------------------------ 1217 void FmFilterNavigator::UpdateContent(const Reference< XIndexAccess > & xControllers, const Reference< XFormController > & xCurrent) 1218 { 1219 if (xCurrent == m_pModel->GetCurrentController()) 1220 return; 1221 1222 m_pModel->Update(xControllers, xCurrent); 1223 1224 // expand the filters for the current controller 1225 SvLBoxEntry* pEntry = FindEntry(m_pModel->GetCurrentForm()); 1226 if (pEntry && !IsExpanded(pEntry)) 1227 { 1228 SelectAll(sal_False); 1229 1230 if (!IsExpanded(pEntry)) 1231 Expand(pEntry); 1232 1233 pEntry = FindEntry(m_pModel->GetCurrentItems()); 1234 if (pEntry) 1235 { 1236 if (!IsExpanded(pEntry)) 1237 Expand(pEntry); 1238 Select(pEntry, sal_True); 1239 } 1240 } 1241 } 1242 1243 //------------------------------------------------------------------------ 1244 sal_Bool FmFilterNavigator::EditingEntry( SvLBoxEntry* pEntry, Selection& rSelection ) 1245 { 1246 m_pEditingCurrently = pEntry; 1247 if (!SvTreeListBox::EditingEntry( pEntry, rSelection )) 1248 return sal_False; 1249 1250 return pEntry && ((FmFilterData*)pEntry->GetUserData())->ISA(FmFilterItem); 1251 } 1252 1253 //------------------------------------------------------------------------ 1254 sal_Bool FmFilterNavigator::EditedEntry( SvLBoxEntry* pEntry, const XubString& rNewText ) 1255 { 1256 DBG_ASSERT(pEntry == m_pEditingCurrently, "FmFilterNavigator::EditedEntry: suspicious entry!"); 1257 m_pEditingCurrently = NULL; 1258 1259 if (EditingCanceled()) 1260 return sal_True; 1261 1262 DBG_ASSERT(((FmFilterData*)pEntry->GetUserData())->ISA(FmFilterItem), 1263 "FmFilterNavigator::EditedEntry() wrong entry"); 1264 1265 UniString aText(rNewText); 1266 aText.EraseTrailingChars(); 1267 aText.EraseLeadingChars(); 1268 if (aText.Len() == 0) 1269 { 1270 // deleting the entry asynchron 1271 sal_uLong nEvent; 1272 PostUserEvent(nEvent, LINK(this, FmFilterNavigator, OnRemove), pEntry); 1273 } 1274 else 1275 { 1276 UniString aErrorMsg; 1277 1278 if (m_pModel->ValidateText((FmFilterItem*)pEntry->GetUserData(), aText, aErrorMsg)) 1279 { 1280 GrabFocus(); 1281 // this will set the text at the FmFilterItem, as well as update any filter controls 1282 // which are connected to this particular entry 1283 m_pModel->SetTextForItem( static_cast< FmFilterItem* >( pEntry->GetUserData() ), aText ); 1284 1285 SetCursor( pEntry, sal_True ); 1286 SetEntryText( pEntry, aText ); 1287 } 1288 else 1289 { 1290 // display the error and return sal_False 1291 SQLContext aError; 1292 aError.Message = String(SVX_RES(RID_STR_SYNTAXERROR)); 1293 aError.Details = aErrorMsg; 1294 displayException(aError, this); 1295 1296 return sal_False; 1297 } 1298 } 1299 return sal_True; 1300 } 1301 1302 //------------------------------------------------------------------------ 1303 IMPL_LINK( FmFilterNavigator, OnRemove, SvLBoxEntry*, pEntry ) 1304 { 1305 // now remove the entry 1306 m_pModel->Remove((FmFilterData*) pEntry->GetUserData()); 1307 return 0L; 1308 } 1309 1310 //------------------------------------------------------------------------ 1311 IMPL_LINK( FmFilterNavigator, OnDropActionTimer, void*, EMPTYARG ) 1312 { 1313 if (--m_aTimerCounter > 0) 1314 return 0L; 1315 1316 switch (m_aDropActionType) 1317 { 1318 case DA_SCROLLUP : 1319 ScrollOutputArea(1); 1320 m_aTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS; 1321 break; 1322 case DA_SCROLLDOWN : 1323 ScrollOutputArea(-1); 1324 m_aTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS; 1325 break; 1326 case DA_EXPANDNODE: 1327 { 1328 SvLBoxEntry* pToExpand = GetEntry(m_aTimerTriggered); 1329 if (pToExpand && (GetChildCount(pToExpand) > 0) && !IsExpanded(pToExpand)) 1330 // tja, eigentlich muesste ich noch testen, ob die Node nicht schon expandiert ist, aber ich 1331 // habe dazu weder in den Basisklassen noch im Model eine Methode gefunden ... 1332 // aber ich denke, die BK sollte es auch so vertragen 1333 Expand(pToExpand); 1334 1335 // nach dem Expand habe ich im Gegensatz zum Scrollen natuerlich nix mehr zu tun 1336 m_aDropActionTimer.Stop(); 1337 } 1338 break; 1339 } 1340 return 0L; 1341 } 1342 1343 1344 //------------------------------------------------------------------------ 1345 sal_Int8 FmFilterNavigator::AcceptDrop( const AcceptDropEvent& rEvt ) 1346 { 1347 Point aDropPos = rEvt.maPosPixel; 1348 1349 // kuemmern wir uns erst mal um moeglich DropActions (Scrollen und Aufklappen) 1350 if (rEvt.mbLeaving) 1351 { 1352 if (m_aDropActionTimer.IsActive()) 1353 m_aDropActionTimer.Stop(); 1354 } 1355 else 1356 { 1357 sal_Bool bNeedTrigger = sal_False; 1358 // auf dem ersten Eintrag ? 1359 if ((aDropPos.Y() >= 0) && (aDropPos.Y() < GetEntryHeight())) 1360 { 1361 m_aDropActionType = DA_SCROLLUP; 1362 bNeedTrigger = sal_True; 1363 } 1364 else 1365 { 1366 // auf dem letzten (bzw. in dem Bereich, den ein Eintrag einnehmen wuerde, wenn er unten genau buendig 1367 // abschliessen wuerde) ? 1368 if ((aDropPos.Y() < GetSizePixel().Height()) && (aDropPos.Y() >= GetSizePixel().Height() - GetEntryHeight())) 1369 { 1370 m_aDropActionType = DA_SCROLLDOWN; 1371 bNeedTrigger = sal_True; 1372 } 1373 else 1374 { // is it an entry whith children, and not yet expanded? 1375 SvLBoxEntry* pDropppedOn = GetEntry(aDropPos); 1376 if (pDropppedOn && (GetChildCount(pDropppedOn) > 0) && !IsExpanded(pDropppedOn)) 1377 { 1378 // -> aufklappen 1379 m_aDropActionType = DA_EXPANDNODE; 1380 bNeedTrigger = sal_True; 1381 } 1382 } 1383 } 1384 if (bNeedTrigger && (m_aTimerTriggered != aDropPos)) 1385 { 1386 // neu anfangen zu zaehlen 1387 m_aTimerCounter = DROP_ACTION_TIMER_INITIAL_TICKS; 1388 // die Pos merken, da ich auch QueryDrops bekomme, wenn sich die Maus gar nicht bewegt hat 1389 m_aTimerTriggered = aDropPos; 1390 // und den Timer los 1391 if (!m_aDropActionTimer.IsActive()) // gibt es den Timer schon ? 1392 { 1393 m_aDropActionTimer.SetTimeout(DROP_ACTION_TIMER_TICK_BASE); 1394 m_aDropActionTimer.Start(); 1395 } 1396 } 1397 else if (!bNeedTrigger) 1398 m_aDropActionTimer.Stop(); 1399 } 1400 1401 1402 // Hat das Object das richtige Format? 1403 if (!m_aControlExchange.isDragSource()) 1404 return DND_ACTION_NONE; 1405 1406 if (!m_aControlExchange->hasFormat(GetDataFlavorExVector())) 1407 return DND_ACTION_NONE; 1408 1409 // do we conain the formitem? 1410 if (!FindEntry(m_aControlExchange->getFormItem())) 1411 return DND_ACTION_NONE; 1412 1413 SvLBoxEntry* pDropTarget = GetEntry(aDropPos); 1414 if (!pDropTarget) 1415 return DND_ACTION_NONE; 1416 1417 FmFilterData* pData = (FmFilterData*)pDropTarget->GetUserData(); 1418 FmFormItem* pForm = NULL; 1419 if (pData->ISA(FmFilterItem)) 1420 { 1421 pForm = PTR_CAST(FmFormItem,pData->GetParent()->GetParent()); 1422 if (pForm != m_aControlExchange->getFormItem()) 1423 return DND_ACTION_NONE; 1424 } 1425 else if (pData->ISA(FmFilterItems)) 1426 { 1427 pForm = PTR_CAST(FmFormItem,pData->GetParent()); 1428 if (pForm != m_aControlExchange->getFormItem()) 1429 return DND_ACTION_NONE; 1430 } 1431 else 1432 return DND_ACTION_NONE; 1433 1434 return rEvt.mnAction; 1435 } 1436 // ----------------------------------------------------------------------------- 1437 namespace 1438 { 1439 FmFilterItems* getTargetItems(SvLBoxEntry* _pTarget) 1440 { 1441 FmFilterData* pData = static_cast<FmFilterData*>(_pTarget->GetUserData()); 1442 FmFilterItems* pTargetItems = pData->ISA(FmFilterItems) 1443 ? 1444 PTR_CAST(FmFilterItems,pData) 1445 : 1446 PTR_CAST(FmFilterItems,pData->GetParent()); 1447 return pTargetItems; 1448 } 1449 } 1450 //------------------------------------------------------------------------ 1451 sal_Int8 FmFilterNavigator::ExecuteDrop( const ExecuteDropEvent& rEvt ) 1452 { 1453 // ware schlecht, wenn nach dem Droppen noch gescrollt wird ... 1454 if (m_aDropActionTimer.IsActive()) 1455 m_aDropActionTimer.Stop(); 1456 1457 // Format-Ueberpruefung 1458 if (!m_aControlExchange.isDragSource()) 1459 return DND_ACTION_NONE; 1460 1461 // das Ziel des Drop sowie einige Daten darueber 1462 Point aDropPos = rEvt.maPosPixel; 1463 SvLBoxEntry* pDropTarget = GetEntry( aDropPos ); 1464 if (!pDropTarget) 1465 return DND_ACTION_NONE; 1466 1467 // search the container where to add the items 1468 FmFilterItems* pTargetItems = getTargetItems(pDropTarget); 1469 SelectAll(sal_False); 1470 SvLBoxEntry* pEntry = FindEntry(pTargetItems); 1471 Select(pEntry, sal_True); 1472 SetCurEntry(pEntry); 1473 1474 insertFilterItem(m_aControlExchange->getDraggedEntries(),pTargetItems,DND_ACTION_COPY == rEvt.mnAction); 1475 1476 return sal_True; 1477 } 1478 1479 //------------------------------------------------------------------------ 1480 void FmFilterNavigator::InitEntry(SvLBoxEntry* pEntry, 1481 const XubString& rStr, 1482 const Image& rImg1, 1483 const Image& rImg2, 1484 SvLBoxButtonKind eButtonKind) 1485 { 1486 SvTreeListBox::InitEntry( pEntry, rStr, rImg1, rImg2, eButtonKind ); 1487 SvLBoxString* pString = NULL; 1488 1489 if (((FmFilterData*)pEntry->GetUserData())->ISA(FmFilterItem)) 1490 pString = new FmFilterString(pEntry, 0, rStr, ((FmFilterItem*)pEntry->GetUserData())->GetFieldName()); 1491 else if (((FmFilterData*)pEntry->GetUserData())->ISA(FmFilterItems)) 1492 pString = new FmFilterItemsString(pEntry, 0, rStr ); 1493 1494 if (pString) 1495 pEntry->ReplaceItem( pString, 1 ); 1496 } 1497 1498 //------------------------------------------------------------------------ 1499 sal_Bool FmFilterNavigator::Select( SvLBoxEntry* pEntry, sal_Bool bSelect ) 1500 { 1501 if (bSelect == IsSelected(pEntry)) // das passiert manchmal, ich glaube, die Basisklasse geht zu sehr auf Nummer sicher ;) 1502 return sal_True; 1503 1504 if (SvTreeListBox::Select(pEntry, bSelect)) 1505 { 1506 if (bSelect) 1507 { 1508 FmFormItem* pFormItem = NULL; 1509 if (((FmFilterData*)pEntry->GetUserData())->ISA(FmFilterItem)) 1510 pFormItem = (FmFormItem*)((FmFilterItem*)pEntry->GetUserData())->GetParent()->GetParent(); 1511 else if (((FmFilterData*)pEntry->GetUserData())->ISA(FmFilterItems)) 1512 pFormItem = (FmFormItem*)((FmFilterItem*)pEntry->GetUserData())->GetParent()->GetParent(); 1513 else if (((FmFilterData*)pEntry->GetUserData())->ISA(FmFormItem)) 1514 pFormItem = (FmFormItem*)pEntry->GetUserData(); 1515 1516 if (pFormItem) 1517 { 1518 // will the controller be exchanged? 1519 if (((FmFilterData*)pEntry->GetUserData())->ISA(FmFilterItem)) 1520 m_pModel->SetCurrentItems((FmFilterItems*)((FmFilterItem*)pEntry->GetUserData())->GetParent()); 1521 else if (((FmFilterData*)pEntry->GetUserData())->ISA(FmFilterItems)) 1522 m_pModel->SetCurrentItems((FmFilterItems*)pEntry->GetUserData()); 1523 else if (((FmFilterData*)pEntry->GetUserData())->ISA(FmFormItem)) 1524 m_pModel->SetCurrentController(((FmFormItem*)pEntry->GetUserData())->GetController()); 1525 } 1526 } 1527 return sal_True; 1528 } 1529 else 1530 return sal_False; 1531 } 1532 1533 //------------------------------------------------------------------------ 1534 void FmFilterNavigator::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint ) 1535 { 1536 if (rHint.ISA(FmFilterInsertedHint)) 1537 { 1538 FmFilterInsertedHint* pHint = (FmFilterInsertedHint*)&rHint; 1539 Insert(pHint->GetData(), pHint->GetPos()); 1540 } 1541 else if( rHint.ISA(FilterClearingHint) ) 1542 { 1543 SvTreeListBox::Clear(); 1544 } 1545 else if( rHint.ISA(FmFilterRemovedHint) ) 1546 { 1547 FmFilterRemovedHint* pHint = (FmFilterRemovedHint*)&rHint; 1548 Remove(pHint->GetData()); 1549 } 1550 else if( rHint.ISA(FmFilterTextChangedHint) ) 1551 { 1552 FmFilterTextChangedHint* pHint = (FmFilterTextChangedHint*)&rHint; 1553 SvLBoxEntry* pEntry = FindEntry(pHint->GetData()); 1554 if (pEntry) 1555 SetEntryText( pEntry, pHint->GetData()->GetText()); 1556 } 1557 else if( rHint.ISA(FmFilterCurrentChangedHint) ) 1558 { 1559 // invalidate the entries 1560 for (SvLBoxEntry* pEntry = First(); pEntry != NULL; 1561 pEntry = Next(pEntry)) 1562 GetModel()->InvalidateEntry( pEntry ); 1563 } 1564 } 1565 1566 //------------------------------------------------------------------------ 1567 SvLBoxEntry* FmFilterNavigator::FindEntry(const FmFilterData* pItem) const 1568 { 1569 SvLBoxEntry* pEntry = NULL; 1570 if (pItem) 1571 { 1572 for (pEntry = First(); pEntry != NULL; pEntry = Next( pEntry )) 1573 { 1574 FmFilterData* pEntryItem = (FmFilterData*)pEntry->GetUserData(); 1575 if (pEntryItem == pItem) 1576 break; 1577 } 1578 } 1579 return pEntry; 1580 } 1581 1582 //------------------------------------------------------------------------ 1583 void FmFilterNavigator::Insert(FmFilterData* pItem, sal_Int32 nPos) 1584 { 1585 const FmParentData* pParent = pItem->GetParent() ? pItem->GetParent() : GetFilterModel(); 1586 1587 // insert the item 1588 SvLBoxEntry* pParentEntry = FindEntry( pParent ); 1589 SvLBoxEntry* pNewEntry = InsertEntry(pItem->GetText(), pItem->GetImage(), pItem->GetImage(), pParentEntry, sal_False, nPos, pItem ); 1590 if ( pNewEntry ) 1591 { 1592 SetExpandedEntryBmp( pNewEntry, pItem->GetImage( BMP_COLOR_HIGHCONTRAST ), BMP_COLOR_HIGHCONTRAST ); 1593 SetCollapsedEntryBmp( pNewEntry, pItem->GetImage( BMP_COLOR_HIGHCONTRAST ), BMP_COLOR_HIGHCONTRAST ); 1594 } 1595 if ( pParentEntry ) 1596 Expand( pParentEntry ); 1597 } 1598 1599 //------------------------------------------------------------------------ 1600 void FmFilterNavigator::Remove(FmFilterData* pItem) 1601 { 1602 // der Entry zu den Daten 1603 SvLBoxEntry* pEntry = FindEntry(pItem); 1604 1605 if (pEntry == m_pEditingCurrently) 1606 // cancel editing 1607 EndEditing(sal_True); 1608 1609 if (pEntry) 1610 GetModel()->Remove( pEntry ); 1611 } 1612 // ----------------------------------------------------------------------------- 1613 FmFormItem* FmFilterNavigator::getSelectedFilterItems(::std::vector<FmFilterItem*>& _rItemList) 1614 { 1615 // be sure that the data is only used within only one form! 1616 FmFormItem* pFirstItem = NULL; 1617 1618 sal_Bool bHandled = sal_True; 1619 sal_Bool bFoundSomething = sal_False; 1620 for (SvLBoxEntry* pEntry = FirstSelected(); 1621 bHandled && pEntry != NULL; 1622 pEntry = NextSelected(pEntry)) 1623 { 1624 FmFilterItem* pFilter = PTR_CAST(FmFilterItem, (FmFilterData*)pEntry->GetUserData()); 1625 if (pFilter) 1626 { 1627 FmFormItem* pForm = PTR_CAST(FmFormItem,pFilter->GetParent()->GetParent()); 1628 if (!pForm) 1629 bHandled = sal_False; 1630 else if (!pFirstItem) 1631 pFirstItem = pForm; 1632 else if (pFirstItem != pForm) 1633 bHandled = sal_False; 1634 1635 if (bHandled) 1636 { 1637 _rItemList.push_back(pFilter); 1638 bFoundSomething = sal_True; 1639 } 1640 } 1641 } 1642 if ( !bHandled || !bFoundSomething ) 1643 pFirstItem = NULL; 1644 return pFirstItem; 1645 } 1646 // ----------------------------------------------------------------------------- 1647 void FmFilterNavigator::insertFilterItem(const ::std::vector<FmFilterItem*>& _rFilterList,FmFilterItems* _pTargetItems,sal_Bool _bCopy) 1648 { 1649 ::std::vector<FmFilterItem*>::const_iterator aEnd = _rFilterList.end(); 1650 for ( ::std::vector< FmFilterItem* >::const_iterator i = _rFilterList.begin(); 1651 i != aEnd; 1652 ++i 1653 ) 1654 { 1655 FmFilterItem* pLookupItem( *i ); 1656 if ( pLookupItem->GetParent() == _pTargetItems ) 1657 continue; 1658 1659 FmFilterItem* pFilterItem = _pTargetItems->Find( pLookupItem->GetComponentIndex() ); 1660 String aText = pLookupItem->GetText(); 1661 if ( !pFilterItem ) 1662 { 1663 pFilterItem = new FmFilterItem( m_pModel->getORB(), _pTargetItems, pLookupItem->GetFieldName(), aText, pLookupItem->GetComponentIndex() ); 1664 m_pModel->Append( _pTargetItems, pFilterItem ); 1665 } 1666 1667 if ( !_bCopy ) 1668 m_pModel->Remove( pLookupItem ); 1669 1670 // now set the text for the new dragged item 1671 m_pModel->SetTextForItem( pFilterItem, aText ); 1672 } 1673 1674 m_pModel->EnsureEmptyFilterRows( *_pTargetItems->GetParent() ); 1675 } 1676 1677 //------------------------------------------------------------------------------ 1678 void FmFilterNavigator::StartDrag( sal_Int8 /*_nAction*/, const Point& /*_rPosPixel*/ ) 1679 { 1680 EndSelection(); 1681 1682 // be sure that the data is only used within a only one form! 1683 m_aControlExchange.prepareDrag(); 1684 1685 ::std::vector<FmFilterItem*> aItemList; 1686 if ( FmFormItem* pFirstItem = getSelectedFilterItems(aItemList) ) 1687 { 1688 m_aControlExchange->setDraggedEntries(aItemList); 1689 m_aControlExchange->setFormItem(pFirstItem); 1690 m_aControlExchange.startDrag( DND_ACTION_COPYMOVE ); 1691 } 1692 } 1693 1694 //------------------------------------------------------------------------------ 1695 void FmFilterNavigator::Command( const CommandEvent& rEvt ) 1696 { 1697 sal_Bool bHandled = sal_False; 1698 switch (rEvt.GetCommand()) 1699 { 1700 case COMMAND_CONTEXTMENU: 1701 { 1702 // die Stelle, an der geklickt wurde 1703 Point aWhere; 1704 SvLBoxEntry* pClicked = NULL; 1705 if (rEvt.IsMouseEvent()) 1706 { 1707 aWhere = rEvt.GetMousePosPixel(); 1708 pClicked = GetEntry(aWhere); 1709 if (pClicked == NULL) 1710 break; 1711 1712 if (!IsSelected(pClicked)) 1713 { 1714 SelectAll(sal_False); 1715 Select(pClicked, sal_True); 1716 SetCurEntry(pClicked); 1717 } 1718 } 1719 else 1720 { 1721 pClicked = GetCurEntry(); 1722 if (!pClicked) 1723 break; 1724 aWhere = GetEntryPosition( pClicked ); 1725 } 1726 1727 ::std::vector<FmFilterData*> aSelectList; 1728 for (SvLBoxEntry* pEntry = FirstSelected(); 1729 pEntry != NULL; 1730 pEntry = NextSelected(pEntry)) 1731 { 1732 // don't delete forms 1733 FmFormItem* pForm = PTR_CAST(FmFormItem, (FmFilterData*)pEntry->GetUserData()); 1734 if (!pForm) 1735 aSelectList.push_back((FmFilterData*)pEntry->GetUserData()); 1736 } 1737 if (aSelectList.size() == 1) 1738 { 1739 // don't delete the only empty row of a form 1740 FmFilterItems* pFilterItems = PTR_CAST(FmFilterItems, aSelectList[0]); 1741 if (pFilterItems && pFilterItems->GetChildren().empty() 1742 && pFilterItems->GetParent()->GetChildren().size() == 1) 1743 aSelectList.clear(); 1744 } 1745 1746 PopupMenu aContextMenu(SVX_RES(RID_FM_FILTER_MENU)); 1747 1748 // every condition could be deleted except the first one if its the only one 1749 aContextMenu.EnableItem( SID_FM_DELETE, !aSelectList.empty() ); 1750 1751 // 1752 sal_Bool bEdit = PTR_CAST(FmFilterItem, (FmFilterData*)pClicked->GetUserData()) != NULL && 1753 IsSelected(pClicked) && GetSelectionCount() == 1; 1754 1755 aContextMenu.EnableItem( SID_FM_FILTER_EDIT, 1756 bEdit ); 1757 aContextMenu.EnableItem( SID_FM_FILTER_IS_NULL, 1758 bEdit ); 1759 aContextMenu.EnableItem( SID_FM_FILTER_IS_NOT_NULL, 1760 bEdit ); 1761 1762 aContextMenu.RemoveDisabledEntries(sal_True, sal_True); 1763 sal_uInt16 nSlotId = aContextMenu.Execute( this, aWhere ); 1764 switch( nSlotId ) 1765 { 1766 case SID_FM_FILTER_EDIT: 1767 { 1768 EditEntry( pClicked ); 1769 } break; 1770 case SID_FM_FILTER_IS_NULL: 1771 case SID_FM_FILTER_IS_NOT_NULL: 1772 { 1773 UniString aErrorMsg; 1774 UniString aText; 1775 if (nSlotId == SID_FM_FILTER_IS_NULL) 1776 aText.AssignAscii("IS NULL"); 1777 else 1778 aText.AssignAscii("IS NOT NULL"); 1779 1780 m_pModel->ValidateText((FmFilterItem*)pClicked->GetUserData(), 1781 aText, aErrorMsg); 1782 m_pModel->SetTextForItem((FmFilterItem*)pClicked->GetUserData(), aText); 1783 } break; 1784 case SID_FM_DELETE: 1785 { 1786 DeleteSelection(); 1787 } break; 1788 } 1789 bHandled = sal_True; 1790 } break; 1791 } 1792 1793 if (!bHandled) 1794 SvTreeListBox::Command( rEvt ); 1795 } 1796 // ----------------------------------------------------------------------------- 1797 SvLBoxEntry* FmFilterNavigator::getNextEntry(SvLBoxEntry* _pStartWith) 1798 { 1799 SvLBoxEntry* pEntry = _pStartWith ? _pStartWith : LastSelected(); 1800 pEntry = Next(pEntry); 1801 // we need the next filter entry 1802 while( pEntry && GetChildCount( pEntry ) == 0 && pEntry != Last() ) 1803 pEntry = Next(pEntry); 1804 return pEntry; 1805 } 1806 // ----------------------------------------------------------------------------- 1807 SvLBoxEntry* FmFilterNavigator::getPrevEntry(SvLBoxEntry* _pStartWith) 1808 { 1809 SvLBoxEntry* pEntry = _pStartWith ? _pStartWith : FirstSelected(); 1810 pEntry = Prev(pEntry); 1811 // check if the previous entry is a filter, if so get the next prev 1812 if ( pEntry && GetChildCount( pEntry ) != 0 ) 1813 { 1814 pEntry = Prev(pEntry); 1815 // if the entry is still no leaf return 1816 if ( pEntry && GetChildCount( pEntry ) != 0 ) 1817 pEntry = NULL; 1818 } 1819 return pEntry; 1820 } 1821 //------------------------------------------------------------------------ 1822 void FmFilterNavigator::KeyInput(const KeyEvent& rKEvt) 1823 { 1824 const KeyCode& rKeyCode = rKEvt.GetKeyCode(); 1825 1826 switch ( rKeyCode.GetCode() ) 1827 { 1828 case KEY_UP: 1829 case KEY_DOWN: 1830 { 1831 if ( !rKeyCode.IsMod1() || !rKeyCode.IsMod2() || rKeyCode.IsShift() ) 1832 break; 1833 1834 ::std::vector<FmFilterItem*> aItemList; 1835 if ( !getSelectedFilterItems( aItemList ) ) 1836 break; 1837 1838 ::std::mem_fun1_t<SvLBoxEntry*,FmFilterNavigator,SvLBoxEntry*> getter = ::std::mem_fun(&FmFilterNavigator::getNextEntry); 1839 if ( rKeyCode.GetCode() == KEY_UP ) 1840 getter = ::std::mem_fun(&FmFilterNavigator::getPrevEntry); 1841 1842 SvLBoxEntry* pTarget = getter( this, NULL ); 1843 if ( !pTarget ) 1844 break; 1845 1846 FmFilterItems* pTargetItems = getTargetItems( pTarget ); 1847 if ( !pTargetItems ) 1848 break; 1849 1850 ::std::vector<FmFilterItem*>::const_iterator aEnd = aItemList.end(); 1851 sal_Bool bNextTargetItem = sal_True; 1852 while ( bNextTargetItem ) 1853 { 1854 ::std::vector<FmFilterItem*>::const_iterator i = aItemList.begin(); 1855 for (; i != aEnd; ++i) 1856 { 1857 if ( (*i)->GetParent() == pTargetItems ) 1858 { 1859 pTarget = getter(this,pTarget); 1860 if ( !pTarget ) 1861 return; 1862 pTargetItems = getTargetItems( pTarget ); 1863 break; 1864 } 1865 else 1866 { 1867 FmFilterItem* pFilterItem = pTargetItems->Find( (*i)->GetComponentIndex() ); 1868 // we found the text component so jump above 1869 if ( pFilterItem ) 1870 { 1871 pTarget = getter( this, pTarget ); 1872 if ( !pTarget ) 1873 return; 1874 1875 pTargetItems = getTargetItems( pTarget ); 1876 break; 1877 } 1878 } 1879 } 1880 bNextTargetItem = i != aEnd && pTargetItems; 1881 } 1882 1883 if ( pTargetItems ) 1884 { 1885 insertFilterItem( aItemList, pTargetItems ); 1886 return; 1887 } 1888 } 1889 break; 1890 1891 case KEY_DELETE: 1892 { 1893 if ( rKeyCode.GetModifier() ) 1894 break; 1895 1896 if ( !IsSelected( First() ) || GetEntryCount() > 1 ) 1897 DeleteSelection(); 1898 return; 1899 } 1900 } 1901 1902 SvTreeListBox::KeyInput(rKEvt); 1903 } 1904 1905 //------------------------------------------------------------------------------ 1906 void FmFilterNavigator::DeleteSelection() 1907 { 1908 // to avoid the deletion of an entry twice (e.g. deletion of a parent and afterward 1909 // the deletion of it's child, i have to shrink the selecton list 1910 ::std::vector<SvLBoxEntry*> aEntryList; 1911 for (SvLBoxEntry* pEntry = FirstSelected(); 1912 pEntry != NULL; 1913 pEntry = NextSelected(pEntry)) 1914 { 1915 FmFilterItem* pFilterItem = PTR_CAST(FmFilterItem, (FmFilterData*)pEntry->GetUserData()); 1916 if (pFilterItem && IsSelected(GetParent(pEntry))) 1917 continue; 1918 1919 FmFormItem* pForm = PTR_CAST(FmFormItem, (FmFilterData*)pEntry->GetUserData()); 1920 if (!pForm) 1921 aEntryList.push_back(pEntry); 1922 } 1923 1924 // Remove the selection 1925 SelectAll(sal_False); 1926 1927 for (::std::vector<SvLBoxEntry*>::reverse_iterator i = aEntryList.rbegin(); 1928 // link problems with operator == 1929 i.base() != aEntryList.rend().base(); i++) 1930 { 1931 m_pModel->Remove((FmFilterData*)(*i)->GetUserData()); 1932 } 1933 } 1934 // ----------------------------------------------------------------------------- 1935 1936 //======================================================================== 1937 // class FmFilterNavigatorWin 1938 //======================================================================== 1939 FmFilterNavigatorWin::FmFilterNavigatorWin( SfxBindings* _pBindings, SfxChildWindow* _pMgr, 1940 Window* _pParent ) 1941 :SfxDockingWindow( _pBindings, _pMgr, _pParent, WinBits(WB_STDMODELESS|WB_SIZEABLE|WB_ROLLABLE|WB_3DLOOK|WB_DOCKABLE) ) 1942 ,SfxControllerItem( SID_FM_FILTER_NAVIGATOR_CONTROL, *_pBindings ) 1943 { 1944 SetHelpId( HID_FILTER_NAVIGATOR_WIN ); 1945 1946 m_pNavigator = new FmFilterNavigator( this ); 1947 m_pNavigator->Show(); 1948 SetText( SVX_RES(RID_STR_FILTER_NAVIGATOR) ); 1949 SfxDockingWindow::SetFloatingSize( Size(200,200) ); 1950 } 1951 1952 //------------------------------------------------------------------------ 1953 FmFilterNavigatorWin::~FmFilterNavigatorWin() 1954 { 1955 delete m_pNavigator; 1956 } 1957 1958 //----------------------------------------------------------------------- 1959 void FmFilterNavigatorWin::UpdateContent(FmFormShell* pFormShell) 1960 { 1961 if (!pFormShell) 1962 m_pNavigator->UpdateContent( NULL, NULL ); 1963 else 1964 { 1965 Reference< XFormController > xController(pFormShell->GetImpl()->getActiveInternalController()); 1966 Reference< XIndexAccess > xContainer; 1967 if (xController.is()) 1968 { 1969 Reference< XChild > xChild(xController, UNO_QUERY); 1970 for (Reference< XInterface > xParent(xChild->getParent()); 1971 xParent.is(); 1972 xParent = xChild.is() ? xChild->getParent() : Reference< XInterface > ()) 1973 { 1974 xContainer = Reference< XIndexAccess > (xParent, UNO_QUERY); 1975 xChild = Reference< XChild > (xParent, UNO_QUERY); 1976 } 1977 } 1978 m_pNavigator->UpdateContent(xContainer, xController); 1979 } 1980 } 1981 1982 //----------------------------------------------------------------------- 1983 void FmFilterNavigatorWin::StateChanged( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState ) 1984 { 1985 if( !pState || SID_FM_FILTER_NAVIGATOR_CONTROL != nSID ) 1986 return; 1987 1988 if( eState >= SFX_ITEM_AVAILABLE ) 1989 { 1990 FmFormShell* pShell = PTR_CAST( FmFormShell,((SfxObjectItem*)pState)->GetShell() ); 1991 UpdateContent( pShell ); 1992 } 1993 else 1994 UpdateContent( NULL ); 1995 } 1996 1997 //----------------------------------------------------------------------- 1998 sal_Bool FmFilterNavigatorWin::Close() 1999 { 2000 if ( m_pNavigator && m_pNavigator->IsEditingActive() ) 2001 m_pNavigator->EndEditing(); 2002 2003 if ( m_pNavigator && m_pNavigator->IsEditingActive() ) 2004 // the EndEditing was vetoed (perhaps of an syntax error or such) 2005 return sal_False; 2006 2007 UpdateContent( NULL ); 2008 return SfxDockingWindow::Close(); 2009 } 2010 2011 //----------------------------------------------------------------------- 2012 void FmFilterNavigatorWin::FillInfo( SfxChildWinInfo& rInfo ) const 2013 { 2014 SfxDockingWindow::FillInfo( rInfo ); 2015 rInfo.bVisible = sal_False; 2016 } 2017 2018 //----------------------------------------------------------------------- 2019 Size FmFilterNavigatorWin::CalcDockingSize( SfxChildAlignment eAlign ) 2020 { 2021 if ( ( eAlign == SFX_ALIGN_TOP ) || ( eAlign == SFX_ALIGN_BOTTOM ) ) 2022 return Size(); 2023 2024 return SfxDockingWindow::CalcDockingSize( eAlign ); 2025 } 2026 2027 //----------------------------------------------------------------------- 2028 SfxChildAlignment FmFilterNavigatorWin::CheckAlignment( SfxChildAlignment eActAlign, SfxChildAlignment eAlign ) 2029 { 2030 switch (eAlign) 2031 { 2032 case SFX_ALIGN_LEFT: 2033 case SFX_ALIGN_RIGHT: 2034 case SFX_ALIGN_NOALIGNMENT: 2035 return (eAlign); 2036 default: 2037 break; 2038 } 2039 2040 return (eActAlign); 2041 } 2042 2043 //------------------------------------------------------------------------ 2044 void FmFilterNavigatorWin::Resize() 2045 { 2046 SfxDockingWindow::Resize(); 2047 2048 Size aLogOutputSize = PixelToLogic( GetOutputSizePixel(), MAP_APPFONT ); 2049 Size aLogExplSize = aLogOutputSize; 2050 aLogExplSize.Width() -= 6; 2051 aLogExplSize.Height() -= 6; 2052 2053 Point aExplPos = LogicToPixel( Point(3,3), MAP_APPFONT ); 2054 Size aExplSize = LogicToPixel( aLogExplSize, MAP_APPFONT ); 2055 2056 m_pNavigator->SetPosSizePixel( aExplPos, aExplSize ); 2057 } 2058 // ----------------------------------------------------------------------------- 2059 void FmFilterNavigatorWin::GetFocus() 2060 { 2061 // oj #97405# 2062 if ( m_pNavigator ) 2063 m_pNavigator->GrabFocus(); 2064 } 2065 // ----------------------------------------------------------------------------- 2066 2067 2068 //======================================================================== 2069 // class FmFilterNavigatorWinMgr 2070 //======================================================================== 2071 SFX_IMPL_DOCKINGWINDOW( FmFilterNavigatorWinMgr, SID_FM_FILTER_NAVIGATOR ) 2072 2073 //----------------------------------------------------------------------- 2074 FmFilterNavigatorWinMgr::FmFilterNavigatorWinMgr( Window *_pParent, sal_uInt16 _nId, 2075 SfxBindings *_pBindings, SfxChildWinInfo* _pInfo ) 2076 :SfxChildWindow( _pParent, _nId ) 2077 { 2078 pWindow = new FmFilterNavigatorWin( _pBindings, this, _pParent ); 2079 eChildAlignment = SFX_ALIGN_NOALIGNMENT; 2080 ((SfxDockingWindow*)pWindow)->Initialize( _pInfo ); 2081 } 2082 2083 //........................................................................ 2084 } // namespace svxform 2085 //........................................................................ 2086