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

Generated by: LCOV version 1.10