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