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_dbaccess.hxx" 30 31 #ifndef DBAUI_DBTREELISTBOX_HXX 32 #include "dbtreelistbox.hxx" 33 #endif 34 #ifndef _DBU_RESOURCE_HRC_ 35 #include "dbu_resource.hrc" 36 #endif 37 #ifndef DBACCESS_UI_BROWSER_ID_HXX 38 #include "browserids.hxx" 39 #endif 40 #ifndef _DBAUI_LISTVIEWITEMS_HXX_ 41 #include "listviewitems.hxx" 42 #endif 43 #ifndef _DBACCESS_UI_CALLBACKS_HXX_ 44 #include "callbacks.hxx" 45 #endif 46 47 #ifndef _COM_SUN_STAR_DATATRANSFER_DND_XDRAGGESTURELISTENER_HDL_ 48 #include <com/sun/star/datatransfer/dnd/XDragGestureListener.hdl> 49 #endif 50 #ifndef _COM_SUN_STAR_DATATRANSFER_DND_XDRAGGESTURERECOGNIZER_HPP_ 51 #include <com/sun/star/datatransfer/dnd/XDragGestureRecognizer.hpp> 52 #endif 53 #ifndef _COM_SUN_STAR_UI_XCONTEXTMENUINTERCEPTOR_HPP_ 54 #include <com/sun/star/ui/XContextMenuInterceptor.hpp> 55 #endif 56 #include <com/sun/star/frame/XFrame.hpp> 57 #ifndef _COM_SUN_STAR_UTIL_URL_HPP_ 58 #include <com/sun/star/util/URL.hpp> 59 #endif 60 #ifndef _CPPUHELPER_IMPLBASE1_HXX_ 61 #include <cppuhelper/implbase1.hxx> 62 #endif 63 #ifndef _CPPUHELPER_INTERFACECONTAINER_HXX_ 64 #include <cppuhelper/interfacecontainer.hxx> 65 #endif 66 #ifndef _SV_HELP_HXX 67 #include <vcl/help.hxx> 68 #endif 69 #ifndef _DBAUI_TABLETREE_HRC_ 70 #include "tabletree.hrc" 71 #endif 72 #ifndef DBAUI_ICONTROLLER_HXX 73 #include "IController.hxx" 74 #endif 75 #ifndef __FRAMEWORK_HELPER_ACTIONTRIGGERHELPER_HXX_ 76 #include <framework/actiontriggerhelper.hxx> 77 #endif 78 #ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_ 79 #include <toolkit/helper/vclunohelper.hxx> 80 #endif 81 #include <framework/imageproducer.hxx> 82 #include <vcl/svapp.hxx> 83 #include <memory> 84 85 // ......................................................................... 86 namespace dbaui 87 { 88 // ......................................................................... 89 90 using namespace ::com::sun::star; 91 using namespace ::com::sun::star::uno; 92 using namespace ::com::sun::star::beans; 93 using namespace ::com::sun::star::lang; 94 using namespace ::com::sun::star::datatransfer; 95 using namespace ::com::sun::star::frame; 96 using namespace ::com::sun::star::ui; 97 using namespace ::com::sun::star::view; 98 99 DBG_NAME(DBTreeListBox) 100 #define SPACEBETWEENENTRIES 4 101 //======================================================================== 102 // class DBTreeListBox 103 //======================================================================== 104 //------------------------------------------------------------------------ 105 DBTreeListBox::DBTreeListBox( Window* pParent, const Reference< XMultiServiceFactory >& _rxORB, WinBits nWinStyle ,sal_Bool _bHandleEnterKey) 106 :SvTreeListBox(pParent,nWinStyle) 107 ,m_pDragedEntry(NULL) 108 ,m_pActionListener(NULL) 109 ,m_pContextMenuProvider( NULL ) 110 ,m_bHandleEnterKey(_bHandleEnterKey) 111 ,m_xORB(_rxORB) 112 { 113 DBG_CTOR(DBTreeListBox,NULL); 114 init(); 115 } 116 // ----------------------------------------------------------------------------- 117 DBTreeListBox::DBTreeListBox( Window* pParent, const Reference< XMultiServiceFactory >& _rxORB, const ResId& rResId,sal_Bool _bHandleEnterKey) 118 :SvTreeListBox(pParent,rResId) 119 ,m_pDragedEntry(NULL) 120 ,m_pActionListener(NULL) 121 ,m_pContextMenuProvider( NULL ) 122 ,m_bHandleEnterKey(_bHandleEnterKey) 123 ,m_xORB(_rxORB) 124 { 125 DBG_CTOR(DBTreeListBox,NULL); 126 init(); 127 } 128 // ----------------------------------------------------------------------------- 129 void DBTreeListBox::init() 130 { 131 sal_uInt16 nSize = SPACEBETWEENENTRIES; 132 SetSpaceBetweenEntries(nSize); 133 134 m_aTimer.SetTimeout(900); 135 m_aTimer.SetTimeoutHdl(LINK(this, DBTreeListBox, OnTimeOut)); 136 137 m_aScrollHelper.setUpScrollMethod( LINK(this, DBTreeListBox, ScrollUpHdl) ); 138 m_aScrollHelper.setDownScrollMethod( LINK(this, DBTreeListBox, ScrollDownHdl) ); 139 140 SetNodeDefaultImages( ); 141 142 EnableContextMenuHandling(); 143 144 SetStyle( GetStyle() | WB_QUICK_SEARCH ); 145 } 146 //------------------------------------------------------------------------ 147 DBTreeListBox::~DBTreeListBox() 148 { 149 DBG_DTOR(DBTreeListBox,NULL); 150 implStopSelectionTimer(); 151 } 152 //------------------------------------------------------------------------ 153 SvLBoxEntry* DBTreeListBox::GetEntryPosByName( const String& aName, SvLBoxEntry* pStart, const IEntryFilter* _pFilter ) const 154 { 155 SvLBoxTreeList* myModel = GetModel(); 156 SvTreeEntryList* pChilds = myModel->GetChildList(pStart); 157 SvLBoxEntry* pEntry = NULL; 158 if ( pChilds ) 159 { 160 sal_uLong nCount = pChilds->Count(); 161 for (sal_uLong i=0; i < nCount; ++i) 162 { 163 pEntry = static_cast<SvLBoxEntry*>(pChilds->GetObject(i)); 164 SvLBoxString* pItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING)); 165 if ( pItem->GetText().Equals(aName) ) 166 { 167 if ( !_pFilter || _pFilter->includeEntry( pEntry ) ) 168 // found 169 break; 170 } 171 pEntry = NULL; 172 } 173 } 174 175 return pEntry; 176 } 177 178 // ------------------------------------------------------------------------- 179 void DBTreeListBox::EnableExpandHandler(SvLBoxEntry* _pEntry) 180 { 181 LINK(this, DBTreeListBox, OnResetEntry).Call(_pEntry); 182 } 183 184 // ------------------------------------------------------------------------- 185 void DBTreeListBox::RequestingChilds( SvLBoxEntry* pParent ) 186 { 187 if (m_aPreExpandHandler.IsSet()) 188 { 189 if (!m_aPreExpandHandler.Call(pParent)) 190 { 191 // an error occured. The method calling us will reset the entry flags, so it can't be expanded again. 192 // But we want that the user may do a second try (i.e. because he misstypes a password in this try), so 193 // we have to reset these flags controlling the expand ability 194 PostUserEvent(LINK(this, DBTreeListBox, OnResetEntry), pParent); 195 } 196 } 197 } 198 199 // ------------------------------------------------------------------------- 200 void DBTreeListBox::InitEntry( SvLBoxEntry* _pEntry, const XubString& aStr, const Image& _rCollEntryBmp, const Image& _rExpEntryBmp, SvLBoxButtonKind eButtonKind) 201 { 202 SvTreeListBox::InitEntry( _pEntry, aStr, _rCollEntryBmp,_rExpEntryBmp, eButtonKind); 203 SvLBoxItem* pTextItem(_pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING)); 204 SvLBoxString* pString = new OBoldListboxString( _pEntry, 0, aStr ); 205 _pEntry->ReplaceItem( pString,_pEntry->GetPos(pTextItem)); 206 } 207 208 // ------------------------------------------------------------------------- 209 void DBTreeListBox::implStopSelectionTimer() 210 { 211 if ( m_aTimer.IsActive() ) 212 m_aTimer.Stop(); 213 } 214 215 // ------------------------------------------------------------------------- 216 void DBTreeListBox::implStartSelectionTimer() 217 { 218 implStopSelectionTimer(); 219 m_aTimer.Start(); 220 } 221 222 // ----------------------------------------------------------------------------- 223 224 void DBTreeListBox::DeselectHdl() 225 { 226 m_aSelectedEntries.erase( GetHdlEntry() ); 227 SvTreeListBox::DeselectHdl(); 228 implStartSelectionTimer(); 229 } 230 // ------------------------------------------------------------------------- 231 void DBTreeListBox::SelectHdl() 232 { 233 m_aSelectedEntries.insert( GetHdlEntry() ); 234 SvTreeListBox::SelectHdl(); 235 implStartSelectionTimer(); 236 } 237 238 // ------------------------------------------------------------------------- 239 void DBTreeListBox::MouseButtonDown( const MouseEvent& rMEvt ) 240 { 241 sal_Bool bHitEmptySpace = (NULL == GetEntry(rMEvt.GetPosPixel(), sal_True)); 242 if (bHitEmptySpace && (rMEvt.GetClicks() == 2) && rMEvt.IsMod1()) 243 Control::MouseButtonDown(rMEvt); 244 else 245 SvTreeListBox::MouseButtonDown(rMEvt); 246 } 247 248 // ------------------------------------------------------------------------- 249 IMPL_LINK(DBTreeListBox, OnResetEntry, SvLBoxEntry*, pEntry) 250 { 251 // set the flag which allows if the entry can be expanded 252 pEntry->SetFlags( (pEntry->GetFlags() & ~(SV_ENTRYFLAG_NO_NODEBMP | SV_ENTRYFLAG_HAD_CHILDREN)) | SV_ENTRYFLAG_CHILDS_ON_DEMAND ); 253 // redraw the entry 254 GetModel()->InvalidateEntry( pEntry ); 255 return 0L; 256 } 257 // ----------------------------------------------------------------------------- 258 void DBTreeListBox::ModelHasEntryInvalidated( SvListEntry* _pEntry ) 259 { 260 SvTreeListBox::ModelHasEntryInvalidated( _pEntry ); 261 262 if ( m_aSelectedEntries.find( _pEntry ) != m_aSelectedEntries.end() ) 263 { 264 SvLBoxItem* pTextItem = static_cast< SvLBoxEntry* >( _pEntry )->GetFirstItem( SV_ITEM_ID_BOLDLBSTRING ); 265 if ( pTextItem && !static_cast< OBoldListboxString* >( pTextItem )->isEmphasized() ) 266 { 267 implStopSelectionTimer(); 268 m_aSelectedEntries.erase( _pEntry ); 269 // ehm - why? 270 } 271 } 272 } 273 // ------------------------------------------------------------------------- 274 void DBTreeListBox::ModelHasRemoved( SvListEntry* _pEntry ) 275 { 276 SvTreeListBox::ModelHasRemoved(_pEntry); 277 if ( m_aSelectedEntries.find( _pEntry ) != m_aSelectedEntries.end() ) 278 { 279 implStopSelectionTimer(); 280 m_aSelectedEntries.erase( _pEntry ); 281 } 282 } 283 284 // ------------------------------------------------------------------------- 285 sal_Int8 DBTreeListBox::AcceptDrop( const AcceptDropEvent& _rEvt ) 286 { 287 sal_Int8 nDropOption = DND_ACTION_NONE; 288 if ( m_pActionListener ) 289 { 290 SvLBoxEntry* pDroppedEntry = GetEntry(_rEvt.maPosPixel); 291 // check if drag is on child entry, which is not allowed 292 SvLBoxEntry* pParent = NULL; 293 if ( _rEvt.mnAction & DND_ACTION_MOVE ) 294 { 295 if ( !m_pDragedEntry ) // no entry to move 296 { 297 nDropOption = m_pActionListener->queryDrop( _rEvt, GetDataFlavorExVector() ); 298 m_aMousePos = _rEvt.maPosPixel; 299 m_aScrollHelper.scroll(m_aMousePos,GetOutputSizePixel()); 300 return nDropOption; 301 } 302 303 pParent = pDroppedEntry ? GetParent(pDroppedEntry) : NULL; 304 while ( pParent && pParent != m_pDragedEntry ) 305 pParent = GetParent(pParent); 306 } 307 308 if ( !pParent ) 309 { 310 nDropOption = m_pActionListener->queryDrop( _rEvt, GetDataFlavorExVector() ); 311 // check if move is allowed 312 if ( nDropOption & DND_ACTION_MOVE ) 313 { 314 if ( m_pDragedEntry == pDroppedEntry || GetEntryPosByName(GetEntryText(m_pDragedEntry),pDroppedEntry) ) 315 nDropOption = nDropOption & ~DND_ACTION_MOVE;//DND_ACTION_NONE; 316 } 317 m_aMousePos = _rEvt.maPosPixel; 318 m_aScrollHelper.scroll(m_aMousePos,GetOutputSizePixel()); 319 } 320 } 321 322 return nDropOption; 323 } 324 325 // ------------------------------------------------------------------------- 326 sal_Int8 DBTreeListBox::ExecuteDrop( const ExecuteDropEvent& _rEvt ) 327 { 328 if ( m_pActionListener ) 329 return m_pActionListener->executeDrop( _rEvt ); 330 331 return DND_ACTION_NONE; 332 } 333 334 // ------------------------------------------------------------------------- 335 void DBTreeListBox::StartDrag( sal_Int8 _nAction, const Point& _rPosPixel ) 336 { 337 if ( m_pActionListener ) 338 { 339 m_pDragedEntry = GetEntry(_rPosPixel); 340 if ( m_pDragedEntry && m_pActionListener->requestDrag( _nAction, _rPosPixel ) ) 341 { 342 // if the (asynchronous) drag started, stop the selection timer 343 implStopSelectionTimer(); 344 // and stop selecting entries by simply moving the mouse 345 EndSelection(); 346 } 347 } 348 } 349 350 // ------------------------------------------------------------------------- 351 void DBTreeListBox::RequestHelp( const HelpEvent& rHEvt ) 352 { 353 if ( !m_pActionListener ) 354 { 355 SvTreeListBox::RequestHelp( rHEvt ); 356 return; 357 } 358 359 if( rHEvt.GetMode() & HELPMODE_QUICK ) 360 { 361 Point aPos( ScreenToOutputPixel( rHEvt.GetMousePosPixel() )); 362 SvLBoxEntry* pEntry = GetEntry( aPos ); 363 if( pEntry ) 364 { 365 String sQuickHelpText; 366 if ( m_pActionListener->requestQuickHelp( pEntry, sQuickHelpText ) ) 367 { 368 Size aSize( GetOutputSizePixel().Width(), GetEntryHeight() ); 369 Rectangle aScreenRect( OutputToScreenPixel( GetEntryPosition( pEntry ) ), aSize ); 370 371 Help::ShowQuickHelp( this, aScreenRect, 372 sQuickHelpText, QUICKHELP_LEFT | QUICKHELP_VCENTER ); 373 return; 374 } 375 } 376 } 377 378 SvTreeListBox::RequestHelp( rHEvt ); 379 } 380 381 // ----------------------------------------------------------------------------- 382 void DBTreeListBox::KeyInput( const KeyEvent& rKEvt ) 383 { 384 KeyFuncType eFunc = rKEvt.GetKeyCode().GetFunction(); 385 sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); 386 sal_Bool bHandled = sal_False; 387 388 if(eFunc != KEYFUNC_DONTKNOW) 389 { 390 switch(eFunc) 391 { 392 case KEYFUNC_CUT: 393 bHandled = ( m_aCutHandler.IsSet() && !m_aSelectedEntries.empty() ); 394 if ( bHandled ) 395 m_aCutHandler.Call( NULL ); 396 break; 397 case KEYFUNC_COPY: 398 bHandled = ( m_aCopyHandler.IsSet() && !m_aSelectedEntries.empty() ); 399 if ( bHandled ) 400 m_aCopyHandler.Call( NULL ); 401 break; 402 case KEYFUNC_PASTE: 403 bHandled = ( m_aPasteHandler.IsSet() && !m_aSelectedEntries.empty() ); 404 if ( bHandled ) 405 m_aPasteHandler.Call( NULL ); 406 break; 407 case KEYFUNC_DELETE: 408 bHandled = ( m_aDeleteHandler.IsSet() && !m_aSelectedEntries.empty() ); 409 if ( bHandled ) 410 m_aDeleteHandler.Call( NULL ); 411 break; 412 default: 413 break; 414 } 415 } 416 417 if ( KEY_RETURN == nCode ) 418 { 419 bHandled = m_bHandleEnterKey; 420 if ( m_aEnterKeyHdl.IsSet() ) 421 m_aEnterKeyHdl.Call(this); 422 // this is a HACK. If the data source browser is opened in the "beamer", while the main frame 423 // contains a writer document, then pressing enter in the DSB would be rerouted to the writer 424 // document if we would not do this hack here. 425 // The problem is that the Writer uses RETURN as _accelerator_ (which is quite weird itself), 426 // so the SFX framework is _obligated_ to pass it to the Writer if nobody else handled it. There 427 // is no chance to distinguish between 428 // "accelerators which are to be executed if the main document has the focus" 429 // and 430 // "accelerators which are always to be executed" 431 // 432 // Thus we cannot prevent the handling of this key in the writer without declaring the key event 433 // as "handled" herein. 434 // 435 // The bad thing about this approach is that it does not scale. Every other accelerator which 436 // is used by the document will raise a similar bug once somebody discovers it. 437 // If this is the case, we should discuss a real solution with the framework (SFX) and the 438 // applications. 439 // 440 // 2002-12-02 - 105831 - fs@openoffice.org 441 } 442 443 if ( !bHandled ) 444 SvTreeListBox::KeyInput(rKEvt); 445 } 446 // ----------------------------------------------------------------------------- 447 sal_Bool DBTreeListBox::EditingEntry( SvLBoxEntry* pEntry, Selection& /*_aSelection*/) 448 { 449 return m_aEditingHandler.Call(pEntry) != 0; 450 } 451 // ----------------------------------------------------------------------------- 452 sal_Bool DBTreeListBox::EditedEntry( SvLBoxEntry* pEntry, const XubString& rNewText ) 453 { 454 DBTreeEditedEntry aEntry; 455 aEntry.pEntry = pEntry; 456 aEntry.aNewText =rNewText; 457 if(m_aEditedHandler.Call(&aEntry) != 0) 458 { 459 implStopSelectionTimer(); 460 m_aSelectedEntries.erase( pEntry ); 461 } 462 SetEntryText(pEntry,aEntry.aNewText); 463 464 return sal_False; // we never want that the base change our text 465 } 466 467 // ----------------------------------------------------------------------------- 468 sal_Bool DBTreeListBox::DoubleClickHdl() 469 { 470 long nResult = aDoubleClickHdl.Call( this ); 471 // continue default processing if the DoubleClickHandler didn't handle it 472 return nResult == 0; 473 } 474 475 // ----------------------------------------------------------------------------- 476 void scrollWindow(DBTreeListBox* _pListBox, const Point& _rPos,sal_Bool _bUp) 477 { 478 SvLBoxEntry* pEntry = _pListBox->GetEntry( _rPos ); 479 if( pEntry && pEntry != _pListBox->Last() ) 480 { 481 _pListBox->ScrollOutputArea( _bUp ? -1 : 1 ); 482 } 483 } 484 // ----------------------------------------------------------------------------- 485 IMPL_LINK( DBTreeListBox, ScrollUpHdl, SvTreeListBox*, /*pBox*/ ) 486 { 487 scrollWindow(this,m_aMousePos,sal_True); 488 return 0; 489 } 490 491 //------------------------------------------------------------------------------ 492 IMPL_LINK( DBTreeListBox, ScrollDownHdl, SvTreeListBox*, /*pBox*/ ) 493 { 494 scrollWindow(this,m_aMousePos,sal_False); 495 return 0; 496 } 497 // ----------------------------------------------------------------------------- 498 namespace 499 { 500 void lcl_enableEntries( PopupMenu* _pPopup, IController& _rController ) 501 { 502 if ( !_pPopup ) 503 return; 504 505 sal_uInt16 nCount = _pPopup->GetItemCount(); 506 for (sal_uInt16 i=0; i < nCount; ++i) 507 { 508 if ( _pPopup->GetItemType(i) != MENUITEM_SEPARATOR ) 509 { 510 sal_uInt16 nId = _pPopup->GetItemId(i); 511 PopupMenu* pSubPopUp = _pPopup->GetPopupMenu(nId); 512 if ( pSubPopUp ) 513 { 514 lcl_enableEntries( pSubPopUp, _rController ); 515 _pPopup->EnableItem(nId,pSubPopUp->HasValidEntries()); 516 } 517 else 518 { 519 ::rtl::OUString sCommandURL( _pPopup->GetItemCommand( nId ) ); 520 bool bEnabled = ( sCommandURL.getLength() ) 521 ? _rController.isCommandEnabled( sCommandURL ) 522 : _rController.isCommandEnabled( nId ); 523 _pPopup->EnableItem( nId, bEnabled ); 524 } 525 } 526 } 527 528 _pPopup->RemoveDisabledEntries(); 529 } 530 } 531 532 // ----------------------------------------------------------------------------- 533 namespace 534 { 535 void lcl_adjustMenuItemIDs( Menu& _rMenu, IController& _rCommandController ) 536 { 537 sal_uInt16 nCount = _rMenu.GetItemCount(); 538 for ( sal_uInt16 pos = 0; pos < nCount; ++pos ) 539 { 540 // do not adjust separators 541 if ( _rMenu.GetItemType( pos ) == MENUITEM_SEPARATOR ) 542 continue; 543 544 sal_uInt16 nId = _rMenu.GetItemId(pos); 545 String aCommand = _rMenu.GetItemCommand( nId ); 546 PopupMenu* pPopup = _rMenu.GetPopupMenu( nId ); 547 if ( pPopup ) 548 { 549 lcl_adjustMenuItemIDs( *pPopup, _rCommandController ); 550 continue; 551 } // if ( pPopup ) 552 553 const sal_uInt16 nCommandId = _rCommandController.registerCommandURL( aCommand ); 554 _rMenu.InsertItem( nCommandId, _rMenu.GetItemText( nId ), _rMenu.GetItemImage( nId ), 555 _rMenu.GetItemBits( nId ), pos ); 556 557 // more things to preserve: 558 // - the help command 559 ::rtl::OUString sHelpURL = _rMenu.GetHelpCommand( nId ); 560 if ( sHelpURL.getLength() ) 561 _rMenu.SetHelpCommand( nCommandId, sHelpURL ); 562 563 // remove the "old" item 564 _rMenu.RemoveItem( pos+1 ); 565 } 566 } 567 void lcl_insertMenuItemImages( Menu& _rMenu, IController& _rCommandController ) 568 { 569 const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); 570 const sal_Bool bHiContrast = rSettings.GetHighContrastMode(); 571 uno::Reference< frame::XController > xController = _rCommandController.getXController(); 572 uno::Reference< frame::XFrame> xFrame; 573 if ( xController.is() ) 574 xFrame = xController->getFrame(); 575 sal_uInt16 nCount = _rMenu.GetItemCount(); 576 for ( sal_uInt16 pos = 0; pos < nCount; ++pos ) 577 { 578 // do not adjust separators 579 if ( _rMenu.GetItemType( pos ) == MENUITEM_SEPARATOR ) 580 continue; 581 582 sal_uInt16 nId = _rMenu.GetItemId(pos); 583 String aCommand = _rMenu.GetItemCommand( nId ); 584 PopupMenu* pPopup = _rMenu.GetPopupMenu( nId ); 585 if ( pPopup ) 586 { 587 lcl_insertMenuItemImages( *pPopup, _rCommandController ); 588 continue; 589 } // if ( pPopup ) 590 591 if ( xFrame.is() ) 592 _rMenu.SetItemImage(nId,framework::GetImageFromURL(xFrame,aCommand,sal_False,bHiContrast)); 593 } 594 } 595 // ========================================================================= 596 // = SelectionSupplier 597 // ========================================================================= 598 typedef ::cppu::WeakImplHelper1 < XSelectionSupplier 599 > SelectionSupplier_Base; 600 class SelectionSupplier : public SelectionSupplier_Base 601 { 602 public: 603 SelectionSupplier( const Any& _rSelection ) 604 :m_aSelection( _rSelection ) 605 { 606 } 607 608 virtual ::sal_Bool SAL_CALL select( const Any& xSelection ) throw (IllegalArgumentException, RuntimeException); 609 virtual Any SAL_CALL getSelection( ) throw (RuntimeException); 610 virtual void SAL_CALL addSelectionChangeListener( const Reference< XSelectionChangeListener >& xListener ) throw (RuntimeException); 611 virtual void SAL_CALL removeSelectionChangeListener( const Reference< XSelectionChangeListener >& xListener ) throw (RuntimeException); 612 613 protected: 614 virtual ~SelectionSupplier() 615 { 616 } 617 618 private: 619 Any m_aSelection; 620 }; 621 622 //-------------------------------------------------------------------- 623 ::sal_Bool SAL_CALL SelectionSupplier::select( const Any& /*_Selection*/ ) throw (IllegalArgumentException, RuntimeException) 624 { 625 throw IllegalArgumentException(); 626 // API bug: this should be a NoSupportException 627 } 628 629 //-------------------------------------------------------------------- 630 Any SAL_CALL SelectionSupplier::getSelection( ) throw (RuntimeException) 631 { 632 return m_aSelection; 633 } 634 635 //-------------------------------------------------------------------- 636 void SAL_CALL SelectionSupplier::addSelectionChangeListener( const Reference< XSelectionChangeListener >& /*_Listener*/ ) throw (RuntimeException) 637 { 638 OSL_ENSURE( false, "SelectionSupplier::removeSelectionChangeListener: no support!" ); 639 // API bug: this should be a NoSupportException 640 } 641 642 //-------------------------------------------------------------------- 643 void SAL_CALL SelectionSupplier::removeSelectionChangeListener( const Reference< XSelectionChangeListener >& /*_Listener*/ ) throw (RuntimeException) 644 { 645 OSL_ENSURE( false, "SelectionSupplier::removeSelectionChangeListener: no support!" ); 646 // API bug: this should be a NoSupportException 647 } 648 } 649 650 // ----------------------------------------------------------------------------- 651 PopupMenu* DBTreeListBox::CreateContextMenu( void ) 652 { 653 ::std::auto_ptr< PopupMenu > pContextMenu; 654 655 if ( !m_pContextMenuProvider ) 656 return pContextMenu.release(); 657 658 // the basic context menu 659 pContextMenu.reset( m_pContextMenuProvider->getContextMenu( *this ) ); 660 // disable what is not available currently 661 lcl_enableEntries( pContextMenu.get(), m_pContextMenuProvider->getCommandController() ); 662 // set images 663 lcl_insertMenuItemImages( *pContextMenu, m_pContextMenuProvider->getCommandController() ); 664 // allow context menu interception 665 ::cppu::OInterfaceContainerHelper* pInterceptors = m_pContextMenuProvider->getContextMenuInterceptors(); 666 if ( !pInterceptors || !pInterceptors->getLength() ) 667 return pContextMenu.release(); 668 669 ContextMenuExecuteEvent aEvent; 670 aEvent.SourceWindow = VCLUnoHelper::GetInterface( this ); 671 aEvent.ExecutePosition.X = -1; 672 aEvent.ExecutePosition.Y = -1; 673 aEvent.ActionTriggerContainer = ::framework::ActionTriggerHelper::CreateActionTriggerContainerFromMenu( 674 m_xORB, pContextMenu.get(), 0 ); 675 aEvent.Selection = new SelectionSupplier( m_pContextMenuProvider->getCurrentSelection( *this ) ); 676 677 ::cppu::OInterfaceIteratorHelper aIter( *pInterceptors ); 678 bool bModifiedMenu = false; 679 bool bAskInterceptors = true; 680 while ( aIter.hasMoreElements() && bAskInterceptors ) 681 { 682 Reference< XContextMenuInterceptor > xInterceptor( aIter.next(), UNO_QUERY ); 683 if ( !xInterceptor.is() ) 684 continue; 685 686 try 687 { 688 ContextMenuInterceptorAction eAction = xInterceptor->notifyContextMenuExecute( aEvent ); 689 switch ( eAction ) 690 { 691 case ContextMenuInterceptorAction_CANCELLED: 692 return NULL; 693 694 case ContextMenuInterceptorAction_EXECUTE_MODIFIED: 695 bModifiedMenu = true; 696 bAskInterceptors = false; 697 break; 698 699 case ContextMenuInterceptorAction_CONTINUE_MODIFIED: 700 bModifiedMenu = true; 701 bAskInterceptors = true; 702 break; 703 704 default: 705 DBG_ERROR( "DBTreeListBox::CreateContextMenu: unexpected return value of the interceptor call!" ); 706 707 case ContextMenuInterceptorAction_IGNORED: 708 break; 709 } 710 } 711 catch( const DisposedException& e ) 712 { 713 if ( e.Context == xInterceptor ) 714 aIter.remove(); 715 } 716 } 717 718 if ( bModifiedMenu ) 719 { 720 // the interceptor(s) modified the menu description => create a new PopupMenu 721 PopupMenu* pModifiedMenu = new PopupMenu; 722 ::framework::ActionTriggerHelper::CreateMenuFromActionTriggerContainer( 723 pModifiedMenu, aEvent.ActionTriggerContainer ); 724 aEvent.ActionTriggerContainer.clear(); 725 pContextMenu.reset( pModifiedMenu ); 726 727 // the interceptors only know command URLs, but our menus primarily work 728 // with IDs -> we need to translate the commands to IDs 729 lcl_adjustMenuItemIDs( *pModifiedMenu, m_pContextMenuProvider->getCommandController() ); 730 } // if ( bModifiedMenu ) 731 732 return pContextMenu.release(); 733 } 734 735 // ----------------------------------------------------------------------------- 736 void DBTreeListBox::ExcecuteContextMenuAction( sal_uInt16 _nSelectedPopupEntry ) 737 { 738 if ( m_pContextMenuProvider && _nSelectedPopupEntry ) 739 m_pContextMenuProvider->getCommandController().executeChecked( _nSelectedPopupEntry, Sequence< PropertyValue >() ); 740 } 741 742 // ----------------------------------------------------------------------------- 743 IMPL_LINK(DBTreeListBox, OnTimeOut, void*, /*EMPTY_ARG*/) 744 { 745 implStopSelectionTimer(); 746 747 m_aSelChangeHdl.Call( NULL ); 748 return 0L; 749 } 750 // ----------------------------------------------------------------------------- 751 void DBTreeListBox::StateChanged( StateChangedType nStateChange ) 752 { 753 if ( nStateChange == STATE_CHANGE_VISIBLE ) 754 implStopSelectionTimer(); 755 } 756 // ......................................................................... 757 } // namespace dbaui 758 // ......................................................................... 759