LCOV - code coverage report
Current view: top level - dbaccess/source/ui/control - dbtreelistbox.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 71 320 22.2 %
Date: 2014-11-03 Functions: 15 47 31.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10