| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_svtools.hxx" |
| |
| #include <com/sun/star/accessibility/AccessibleEventId.hpp> |
| #include <com/sun/star/accessibility/AccessibleStateType.hpp> |
| #include <comphelper/processfactory.hxx> |
| |
| #include <vcl/dockwin.hxx> |
| #include <vcl/decoview.hxx> |
| #include <vcl/image.hxx> |
| #include <vcl/taskpanelist.hxx> |
| #include <vcl/toolbox.hxx> |
| |
| #include "svtools/valueset.hxx" |
| #include "svtools/toolbarmenu.hxx" |
| #include "toolbarmenuimp.hxx" |
| |
| using ::rtl::OUString; |
| using namespace ::com::sun::star::uno; |
| using namespace ::com::sun::star::lang; |
| using namespace ::com::sun::star::frame; |
| using namespace ::com::sun::star::accessibility; |
| |
| namespace svtools { |
| |
| // -------------------------------------------------------------------- |
| |
| static Window* GetTopMostParentSystemWindow( Window* pWindow ) |
| { |
| OSL_ASSERT( pWindow ); |
| if ( pWindow ) |
| { |
| // ->manually search topmost system window |
| // required because there might be another system window between this and the top window |
| pWindow = pWindow->GetParent(); |
| SystemWindow* pTopMostSysWin = NULL; |
| while ( pWindow ) |
| { |
| if ( pWindow->IsSystemWindow() ) |
| pTopMostSysWin = (SystemWindow*)pWindow; |
| pWindow = pWindow->GetParent(); |
| } |
| pWindow = pTopMostSysWin; |
| OSL_ASSERT( pWindow ); |
| return pWindow; |
| } |
| |
| return NULL; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenuEntry::init( int nEntryId, MenuItemBits nBits ) |
| { |
| mnEntryId = nEntryId; |
| mnBits = nBits; |
| |
| mbHasText = false; |
| mbHasImage = false; |
| mbChecked = false; |
| mbEnabled = true; |
| |
| mpControl = NULL; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| ToolbarMenuEntry::ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const String& rText, MenuItemBits nBits ) |
| : mrMenu( rMenu ) |
| { |
| init( nEntryId, nBits ); |
| |
| maText = rText; |
| mbHasText = true; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| ToolbarMenuEntry::ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const Image& rImage, MenuItemBits nBits ) |
| : mrMenu( rMenu ) |
| { |
| init( nEntryId, nBits ); |
| |
| maImage = rImage; |
| mbHasImage = true; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| ToolbarMenuEntry::ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const Image& rImage, const String& rText, MenuItemBits nBits ) |
| : mrMenu( rMenu ) |
| { |
| init( nEntryId, nBits ); |
| |
| maText = rText; |
| mbHasText = true; |
| |
| maImage = rImage; |
| mbHasImage = true; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| ToolbarMenuEntry::ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, Control* pControl, MenuItemBits nBits ) |
| : mrMenu( rMenu ) |
| { |
| init( nEntryId, nBits ); |
| |
| if( pControl ) |
| { |
| mpControl = pControl; |
| mpControl->Show(); |
| } |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| ToolbarMenuEntry::~ToolbarMenuEntry() |
| { |
| if( mxAccContext.is() ) |
| { |
| Reference< XComponent > xComponent( mxAccContext, UNO_QUERY ); |
| if( xComponent.is() ) |
| xComponent->dispose(); |
| mxAccContext.clear(); |
| } |
| delete mpControl; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| const Reference< XAccessibleContext >& ToolbarMenuEntry::GetAccessible( bool bCreate /* = false */ ) |
| { |
| if( !mxAccContext.is() && bCreate ) |
| { |
| if( mpControl ) |
| { |
| mxAccContext = Reference< XAccessibleContext >( mpControl->GetAccessible( sal_True ), UNO_QUERY ); |
| } |
| else |
| { |
| mxAccContext = Reference< XAccessibleContext >( new ToolbarMenuEntryAcc( this ) ); |
| } |
| } |
| |
| return mxAccContext; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| sal_Int32 ToolbarMenuEntry::getAccessibleChildCount() throw (RuntimeException) |
| { |
| if( mpControl ) |
| { |
| const Reference< XAccessibleContext >& xContext = GetAccessible( true ); |
| if( xContext.is() ) |
| { |
| return xContext->getAccessibleChildCount(); |
| } |
| } |
| return 1; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| Reference< XAccessible > ToolbarMenuEntry::getAccessibleChild( sal_Int32 index ) throw (IndexOutOfBoundsException, RuntimeException) |
| { |
| const Reference< XAccessibleContext >& xContext = GetAccessible( true ); |
| if( mpControl ) |
| { |
| if( xContext.is() ) |
| { |
| return xContext->getAccessibleChild(index); |
| } |
| } |
| else if( index == 0 ) |
| { |
| Reference< XAccessible > xRet( xContext, UNO_QUERY ); |
| if( xRet.is() ) |
| return xRet; |
| } |
| |
| throw IndexOutOfBoundsException(); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| ToolbarMenu_Impl::ToolbarMenu_Impl( ToolbarMenu& rMenu, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame ) |
| : mrMenu( rMenu ) |
| , mxFrame( xFrame ) |
| , mxServiceManager( ::comphelper::getProcessServiceFactory() ) |
| , mnCheckPos(0) |
| , mnImagePos(0) |
| , mnTextPos(0) |
| , mnHighlightedEntry(-1) |
| , mnSelectedEntry(-1) |
| , mnLastColumn(0) |
| { |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| ToolbarMenu_Impl::~ToolbarMenu_Impl() |
| { |
| setAccessible( 0 ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu_Impl::setAccessible( ToolbarMenuAcc* pAccessible ) |
| { |
| if( mxAccessible.get() != pAccessible ) |
| { |
| if( mxAccessible.is() ) |
| mxAccessible->dispose(); |
| |
| mxAccessible.set( pAccessible ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ToolbarMenu_Impl::fireAccessibleEvent( short nEventId, const ::com::sun::star::uno::Any& rOldValue, const ::com::sun::star::uno::Any& rNewValue ) |
| { |
| if( mxAccessible.is() ) |
| mxAccessible->FireAccessibleEvent( nEventId, rOldValue, rNewValue ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| bool ToolbarMenu_Impl::hasAccessibleListeners() |
| { |
| return( mxAccessible.is() && mxAccessible->HasAccessibleListeners() ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| sal_Int32 ToolbarMenu_Impl::getAccessibleChildCount() throw (RuntimeException) |
| { |
| sal_Int32 nCount = 0; |
| const int nEntryCount = maEntryVector.size(); |
| for( int nEntry = 0; nEntry < nEntryCount; nEntry++ ) |
| { |
| ToolbarMenuEntry* pEntry = maEntryVector[nEntry]; |
| if( pEntry ) |
| { |
| if( pEntry->mpControl ) |
| { |
| nCount += pEntry->getAccessibleChildCount(); |
| } |
| else |
| { |
| nCount += 1; |
| } |
| } |
| } |
| |
| return nCount; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| Reference< XAccessible > ToolbarMenu_Impl::getAccessibleChild( sal_Int32 index ) throw (IndexOutOfBoundsException, RuntimeException) |
| { |
| const int nEntryCount = maEntryVector.size(); |
| for( int nEntry = 0; nEntry < nEntryCount; nEntry++ ) |
| { |
| ToolbarMenuEntry* pEntry = maEntryVector[nEntry]; |
| if( pEntry ) |
| { |
| const sal_Int32 nCount = pEntry->getAccessibleChildCount(); |
| if( index < nCount ) |
| { |
| return pEntry->getAccessibleChild( index ); |
| } |
| index -= nCount; |
| } |
| } |
| |
| throw IndexOutOfBoundsException(); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| Reference< XAccessible > ToolbarMenu_Impl::getAccessibleChild( Control* pControl, sal_Int32 childIndex ) throw (IndexOutOfBoundsException, RuntimeException) |
| { |
| const int nEntryCount = maEntryVector.size(); |
| for( int nEntry = 0; nEntry < nEntryCount; nEntry++ ) |
| { |
| ToolbarMenuEntry* pEntry = maEntryVector[nEntry]; |
| if( pEntry && (pEntry->mpControl == pControl) ) |
| { |
| return pEntry->getAccessibleChild( childIndex ); |
| } |
| } |
| |
| throw IndexOutOfBoundsException(); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu_Impl::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) |
| { |
| const int nEntryCount = maEntryVector.size(); |
| for( int nEntry = 0; nEntry < nEntryCount; nEntry++ ) |
| { |
| ToolbarMenuEntry* pEntry = maEntryVector[nEntry]; |
| if( pEntry ) |
| { |
| const sal_Int32 nCount = pEntry->getAccessibleChildCount(); |
| if( nChildIndex < nCount ) |
| { |
| if( pEntry->mpControl ) |
| { |
| Reference< XAccessibleSelection > xSel( pEntry->GetAccessible(true), UNO_QUERY_THROW ); |
| xSel->selectAccessibleChild(nChildIndex); |
| } |
| else if( pEntry->mnEntryId != TITLE_ID ) |
| { |
| mrMenu.implSelectEntry( nEntry ); |
| } |
| return; |
| } |
| nChildIndex -= nCount; |
| } |
| } |
| |
| throw IndexOutOfBoundsException(); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| sal_Bool ToolbarMenu_Impl::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) |
| { |
| const int nEntryCount = maEntryVector.size(); |
| for( int nEntry = 0; nEntry < nEntryCount; nEntry++ ) |
| { |
| ToolbarMenuEntry* pEntry = maEntryVector[nEntry]; |
| if( pEntry ) |
| { |
| const sal_Int32 nCount = pEntry->getAccessibleChildCount(); |
| if( nChildIndex < nCount ) |
| { |
| if( mnHighlightedEntry == nEntry ) |
| { |
| if( pEntry->mpControl ) |
| { |
| Reference< XAccessibleSelection > xSel( pEntry->GetAccessible(true), UNO_QUERY_THROW ); |
| xSel->isAccessibleChildSelected(nChildIndex); |
| } |
| return true; |
| } |
| else |
| { |
| return false; |
| } |
| } |
| nChildIndex -= nCount; |
| } |
| } |
| |
| throw IndexOutOfBoundsException(); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu_Impl::clearAccessibleSelection() |
| { |
| if( mnHighlightedEntry != -1 ) |
| { |
| mrMenu.implHighlightEntry( mnHighlightedEntry, false ); |
| mnHighlightedEntry = -1; |
| } |
| } |
| |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu_Impl::notifyHighlightedEntry() |
| { |
| if( hasAccessibleListeners() ) |
| { |
| ToolbarMenuEntry* pEntry = implGetEntry( mnHighlightedEntry ); |
| if( pEntry && pEntry->mbEnabled && (pEntry->mnEntryId != TITLE_ID) ) |
| { |
| Any aNew; |
| Any aOld( mxOldSelection ); |
| if( pEntry->mpControl ) |
| { |
| sal_Int32 nChildIndex = 0; |
| // todo: if other controls than ValueSet are allowed, addapt this code |
| ValueSet* pValueSet = dynamic_cast< ValueSet* >( pEntry->mpControl ); |
| if( pValueSet ) |
| nChildIndex = static_cast< sal_Int32 >( pValueSet->GetItemPos( pValueSet->GetSelectItemId() ) ); |
| |
| if( nChildIndex >= pEntry->getAccessibleChildCount() ) |
| return; |
| |
| aNew <<= getAccessibleChild( pEntry->mpControl, nChildIndex ); |
| } |
| else |
| { |
| aNew <<= pEntry->GetAccessible(true); |
| } |
| |
| fireAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOld, aNew ); |
| fireAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, aOld, aNew ); |
| fireAccessibleEvent( AccessibleEventId::STATE_CHANGED, Any(), Any( AccessibleStateType::FOCUSED ) ); |
| aNew >>= mxOldSelection; |
| } |
| } |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| ToolbarMenuEntry* ToolbarMenu_Impl::implGetEntry( int nEntry ) const |
| { |
| if( (nEntry < 0) || (nEntry >= (int)maEntryVector.size() ) ) |
| return NULL; |
| |
| return maEntryVector[nEntry]; |
| } |
| |
| |
| // -------------------------------------------------------------------- |
| |
| IMPL_LINK( ToolbarMenu, HighlightHdl, Control *, pControl ) |
| { |
| (void)pControl; |
| mpImpl->notifyHighlightedEntry(); |
| return 0; |
| } |
| |
| // ==================================================================== |
| |
| ToolbarMenu::ToolbarMenu( const Reference< XFrame >& rFrame, Window* pParentWindow, WinBits nBits ) |
| : DockingWindow(pParentWindow, nBits) |
| { |
| implInit(rFrame); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| ToolbarMenu::ToolbarMenu( const Reference< XFrame >& rFrame, Window* pParentWindow, const ResId& rResId ) |
| : DockingWindow(pParentWindow, rResId) |
| { |
| implInit(rFrame); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::implInit(const Reference< XFrame >& rFrame) |
| { |
| mpImpl = new ToolbarMenu_Impl( *this, rFrame ); |
| |
| const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); |
| SetControlBackground( rStyleSettings.GetMenuColor() ); |
| |
| initWindow(); |
| |
| Window* pWindow = GetTopMostParentSystemWindow( this ); |
| if ( pWindow ) |
| ((SystemWindow *)pWindow)->GetTaskPaneList()->AddWindow( this ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| ToolbarMenu::~ToolbarMenu() |
| { |
| Window* pWindow = GetTopMostParentSystemWindow( this ); |
| if ( pWindow ) |
| ((SystemWindow *)pWindow)->GetTaskPaneList()->RemoveWindow( this ); |
| |
| if ( mpImpl->mxStatusListener.is() ) |
| { |
| mpImpl->mxStatusListener->dispose(); |
| mpImpl->mxStatusListener.clear(); |
| } |
| |
| // delete all menu entries |
| const int nEntryCount = mpImpl->maEntryVector.size(); |
| int nEntry; |
| for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) |
| { |
| delete mpImpl->maEntryVector[nEntry]; |
| } |
| |
| delete mpImpl; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| int ToolbarMenu::getSelectedEntryId() const |
| { |
| ToolbarMenuEntry* pEntry = implGetEntry( mpImpl->mnSelectedEntry ); |
| return pEntry ? pEntry->mnEntryId : -1; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| int ToolbarMenu::getHighlightedEntryId() const |
| { |
| ToolbarMenuEntry* pEntry = implGetEntry( mpImpl->mnHighlightedEntry ); |
| return pEntry ? pEntry->mnEntryId : -1; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::checkEntry( int nEntryId, bool bChecked ) |
| { |
| ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId ); |
| if( pEntry && pEntry->mbChecked != bChecked ) |
| { |
| pEntry->mbChecked = bChecked; |
| Invalidate(); |
| } |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| bool ToolbarMenu::isEntryChecked( int nEntryId ) const |
| { |
| ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId ); |
| return pEntry && pEntry->mbChecked; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::enableEntry( int nEntryId, bool bEnable ) |
| { |
| ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId ); |
| if( pEntry && pEntry->mbEnabled != bEnable ) |
| { |
| pEntry->mbEnabled = bEnable; |
| if( pEntry->mpControl ) |
| { |
| pEntry->mpControl->Enable( bEnable ); |
| |
| // hack for the valueset to make it paint itself anew |
| pEntry->mpControl->Resize(); |
| } |
| Invalidate(); |
| } |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| bool ToolbarMenu::isEntryEnabled( int nEntryId ) const |
| { |
| ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId ); |
| return pEntry && pEntry->mbEnabled; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::setEntryText( int nEntryId, const String& rStr ) |
| { |
| ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId ); |
| if( pEntry && pEntry->maText != rStr ) |
| { |
| pEntry->maText = rStr; |
| mpImpl->maSize = implCalcSize(); |
| if( IsVisible() ) |
| Invalidate(); |
| } |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| const String& ToolbarMenu::getEntryText( int nEntryId ) const |
| { |
| ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId ); |
| if( pEntry ) |
| return pEntry->maText; |
| else |
| { |
| static String aEmptyStr; |
| return aEmptyStr; |
| } |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::setEntryImage( int nEntryId, const Image& rImage ) |
| { |
| ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId ); |
| if( pEntry && pEntry->maImage != rImage ) |
| { |
| pEntry->maImage = rImage; |
| mpImpl->maSize = implCalcSize(); |
| if( IsVisible() ) |
| Invalidate(); |
| } |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| const Image& ToolbarMenu::getEntryImage( int nEntryId ) const |
| { |
| ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId ); |
| if( pEntry ) |
| return pEntry->maImage; |
| else |
| { |
| static Image aEmptyImage; |
| return aEmptyImage; |
| } |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::initWindow() |
| { |
| const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); |
| |
| SetPointFont( rStyleSettings.GetMenuFont() ); |
| SetBackground( Wallpaper( GetControlBackground() ) ); |
| SetTextColor( rStyleSettings.GetMenuTextColor() ); |
| SetTextFillColor(); |
| SetLineColor(); |
| |
| mpImpl->maSize = implCalcSize(); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| Size ToolbarMenu::implCalcSize() |
| { |
| const long nFontHeight = GetTextHeight(); |
| long nExtra = nFontHeight/4; |
| |
| Size aSz; |
| Size aMaxImgSz; |
| long nMaxTextWidth = 0; |
| long nMinMenuItemHeight = nFontHeight+2; |
| sal_Bool bCheckable = sal_False; |
| |
| const int nEntryCount = mpImpl->maEntryVector.size(); |
| int nEntry; |
| |
| const StyleSettings& rSettings = GetSettings().GetStyleSettings(); |
| const bool bUseImages = rSettings.GetUseImagesInMenus(); |
| |
| // get maximum image size |
| if( bUseImages ) |
| { |
| for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) |
| { |
| ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry]; |
| if( pEntry && pEntry->mbHasImage ) |
| { |
| Size aImgSz( pEntry->maImage.GetSizePixel() ); |
| nMinMenuItemHeight = std::max( nMinMenuItemHeight, aImgSz.Height() + 6 ); |
| aMaxImgSz.Width() = std::max( aMaxImgSz.Width(), aImgSz.Width() ); |
| } |
| } |
| } |
| |
| mpImpl->mnCheckPos = nExtra; |
| mpImpl->mnImagePos = nExtra; |
| mpImpl->mnTextPos = mpImpl->mnImagePos + aMaxImgSz.Width(); |
| |
| if ( aMaxImgSz.Width() ) |
| mpImpl->mnTextPos += std::max( nExtra, 7L ); |
| if ( bCheckable ) |
| mpImpl->mnTextPos += 16; |
| |
| // set heights, calc maximum width |
| for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) |
| { |
| ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry]; |
| |
| if( pEntry ) |
| { |
| if ( ( pEntry->mnBits ) & ( MIB_RADIOCHECK | MIB_CHECKABLE ) ) |
| bCheckable = sal_True; |
| |
| // Text: |
| if( pEntry->mbHasText || pEntry->mbHasImage ) |
| { |
| pEntry->maSize.Height() = nMinMenuItemHeight; |
| |
| if( pEntry->mbHasText ) |
| { |
| long nTextWidth = GetCtrlTextWidth( pEntry->maText ) + mpImpl->mnTextPos + nExtra; |
| nMaxTextWidth = std::max( nTextWidth, nMaxTextWidth ); |
| } |
| } |
| // Control: |
| else if( pEntry->mpControl ) |
| { |
| Size aControlSize( pEntry->mpControl->GetOutputSizePixel() ); |
| |
| nMaxTextWidth = std::max( aControlSize.Width(), nMaxTextWidth ); |
| pEntry->maSize.Height() = aControlSize.Height() + 1; |
| } |
| |
| } |
| } |
| |
| aSz.Width() = nMaxTextWidth + (BORDER_X<<1); |
| |
| // positionate controls |
| int nY = BORDER_Y; |
| for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) |
| { |
| ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry]; |
| |
| if( pEntry ) |
| { |
| pEntry->maSize.Width() = nMaxTextWidth; |
| |
| if( pEntry->mpControl ) |
| { |
| Size aControlSize( pEntry->mpControl->GetOutputSizePixel() ); |
| Point aControlPos( (aSz.Width() - aControlSize.Width())>>1, nY); |
| |
| pEntry->mpControl->SetPosPixel( aControlPos ); |
| |
| pEntry->maRect = Rectangle( aControlPos, aControlSize ); |
| } |
| else |
| { |
| pEntry->maRect = Rectangle( Point( 0, nY ), pEntry->maSize ); |
| } |
| |
| nY += pEntry->maSize.Height(); |
| } |
| else |
| { |
| nY += SEPARATOR_HEIGHT; |
| } |
| } |
| |
| aSz.Height() += nY + BORDER_Y; |
| |
| return aSz; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::highlightFirstEntry() |
| { |
| implChangeHighlightEntry( 0 ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::GetFocus() |
| { |
| if( mpImpl->mnHighlightedEntry == -1 ) |
| implChangeHighlightEntry( 0 ); |
| |
| DockingWindow::GetFocus(); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::LoseFocus() |
| { |
| if( mpImpl->mnHighlightedEntry != -1 ) |
| implChangeHighlightEntry( -1 ); |
| |
| DockingWindow::LoseFocus(); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::appendEntry( int nEntryId, const String& rStr, MenuItemBits nItemBits ) |
| { |
| appendEntry( new ToolbarMenuEntry( *this, nEntryId, rStr, nItemBits ) ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::appendEntry( int nEntryId, const Image& rImage, MenuItemBits nItemBits ) |
| { |
| appendEntry( new ToolbarMenuEntry( *this, nEntryId, rImage, nItemBits ) ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::appendEntry( int nEntryId, const String& rStr, const Image& rImage, MenuItemBits nItemBits ) |
| { |
| appendEntry( new ToolbarMenuEntry( *this, nEntryId, rImage, rStr, nItemBits ) ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::appendEntry( int nEntryId, Control* pControl, MenuItemBits nItemBits ) |
| { |
| appendEntry( new ToolbarMenuEntry( *this, nEntryId, pControl, nItemBits ) ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::appendEntry( ToolbarMenuEntry* pEntry ) |
| { |
| mpImpl->maEntryVector.push_back( pEntry ); |
| mpImpl->maSize = implCalcSize(); |
| if( IsVisible() ) |
| Invalidate(); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::appendSeparator() |
| { |
| appendEntry( 0 ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| /** creates an empty ValueSet that is initialized and can be inserted with appendEntry. */ |
| ValueSet* ToolbarMenu::createEmptyValueSetControl() |
| { |
| ValueSet* pSet = new ValueSet( this, WB_TABSTOP | WB_MENUSTYLEVALUESET | WB_FLATVALUESET | WB_NOBORDER | WB_NO_DIRECTSELECT ); |
| pSet->EnableFullItemMode( sal_False ); |
| pSet->SetColor( GetControlBackground() ); |
| pSet->SetHighlightHdl( LINK( this, ToolbarMenu, HighlightHdl ) ); |
| return pSet; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| ToolbarMenuEntry* ToolbarMenu::implGetEntry( int nEntry ) const |
| { |
| return mpImpl->implGetEntry( nEntry ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| ToolbarMenuEntry* ToolbarMenu::implSearchEntry( int nEntryId ) const |
| { |
| const int nEntryCount = mpImpl->maEntryVector.size(); |
| int nEntry; |
| for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) |
| { |
| ToolbarMenuEntry* p = mpImpl->maEntryVector[nEntry]; |
| if( p && p->mnEntryId == nEntryId ) |
| { |
| return p; |
| } |
| } |
| |
| return NULL; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::implHighlightEntry( int nHighlightEntry, bool bHighlight ) |
| { |
| Size aSz( GetOutputSizePixel() ); |
| long nX = 0, nY = 0; |
| |
| const int nEntryCount = mpImpl->maEntryVector.size(); |
| int nEntry; |
| for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) |
| { |
| ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry]; |
| if( pEntry && (nEntry == nHighlightEntry) ) |
| { |
| // no highlights for controls only items |
| if( pEntry->mpControl ) |
| { |
| if( !bHighlight ) |
| { |
| ValueSet* pValueSet = dynamic_cast< ValueSet* >( pEntry->mpControl ); |
| if( pValueSet ) |
| { |
| pValueSet->SetNoSelection(); |
| } |
| } |
| break; |
| } |
| |
| bool bRestoreLineColor = false; |
| Color oldLineColor; |
| bool bDrawItemRect = true; |
| |
| Rectangle aItemRect( Point( nX, nY ), Size( aSz.Width(), pEntry->maSize.Height() ) ); |
| if ( pEntry->mnBits & MIB_POPUPSELECT ) |
| { |
| long nFontHeight = GetTextHeight(); |
| aItemRect.Right() -= nFontHeight + nFontHeight/4; |
| } |
| |
| if( IsNativeControlSupported( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL ) ) |
| { |
| Size aPxSize( GetOutputSizePixel() ); |
| Push( PUSH_CLIPREGION ); |
| IntersectClipRegion( Rectangle( Point( nX, nY ), Size( aSz.Width(), pEntry->maSize.Height() ) ) ); |
| Rectangle aCtrlRect( Point( nX, 0 ), Size( aPxSize.Width()-nX, aPxSize.Height() ) ); |
| DrawNativeControl( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL, |
| aCtrlRect, |
| CTRL_STATE_ENABLED, |
| ImplControlValue(), |
| OUString() ); |
| if( bHighlight && IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM ) ) |
| { |
| bDrawItemRect = false; |
| if( sal_False == DrawNativeControl( CTRL_MENU_POPUP, PART_MENU_ITEM, |
| aItemRect, |
| CTRL_STATE_SELECTED | ( pEntry->mbEnabled? CTRL_STATE_ENABLED: 0 ), |
| ImplControlValue(), |
| OUString() ) ) |
| { |
| bDrawItemRect = bHighlight; |
| } |
| } |
| else |
| bDrawItemRect = bHighlight; |
| Pop(); |
| } |
| if( bDrawItemRect ) |
| { |
| if ( bHighlight ) |
| { |
| if( pEntry->mbEnabled ) |
| SetFillColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() ); |
| else |
| { |
| SetFillColor(); |
| oldLineColor = GetLineColor(); |
| SetLineColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() ); |
| bRestoreLineColor = true; |
| } |
| } |
| else |
| SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() ); |
| |
| DrawRect( aItemRect ); |
| } |
| implPaint( pEntry, bHighlight ); |
| if( bRestoreLineColor ) |
| SetLineColor( oldLineColor ); |
| break; |
| } |
| |
| nY += pEntry ? pEntry->maSize.Height() : SEPARATOR_HEIGHT; |
| } |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::implSelectEntry( int nSelectedEntry ) |
| { |
| mpImpl->mnSelectedEntry = nSelectedEntry; |
| |
| ToolbarMenuEntry* pEntry = NULL; |
| if( nSelectedEntry != -1 ) |
| pEntry = mpImpl->maEntryVector[ nSelectedEntry ]; |
| |
| if( pEntry ) |
| mpImpl->maSelectHdl.Call( this ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::MouseButtonDown( const MouseEvent& rMEvt ) |
| { |
| implHighlightEntry( rMEvt, true ); |
| |
| implSelectEntry( mpImpl->mnHighlightedEntry ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::MouseButtonUp( const MouseEvent& ) |
| { |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::MouseMove( const MouseEvent& rMEvt ) |
| { |
| if ( !IsVisible() ) |
| return; |
| |
| implHighlightEntry( rMEvt, false ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::implHighlightEntry( const MouseEvent& rMEvt, bool bMBDown ) |
| { |
| long nY = 0; |
| long nMouseY = rMEvt.GetPosPixel().Y(); |
| Size aOutSz = GetOutputSizePixel(); |
| if ( ( nMouseY >= 0 ) && ( nMouseY < aOutSz.Height() ) ) |
| { |
| bool bHighlighted = sal_False; |
| |
| const int nEntryCount = mpImpl->maEntryVector.size(); |
| int nEntry; |
| for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) |
| { |
| ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry]; |
| if( pEntry ) |
| { |
| long nOldY = nY; |
| nY += pEntry->maSize.Height(); |
| |
| if( pEntry->mnEntryId != TITLE_ID ) |
| { |
| if ( ( nOldY <= nMouseY ) && ( nY > nMouseY ) ) |
| { |
| if( bMBDown ) |
| { |
| if( nEntry != mpImpl->mnHighlightedEntry ) |
| { |
| implChangeHighlightEntry( nEntry ); |
| } |
| } |
| else |
| { |
| if ( nEntry != mpImpl->mnHighlightedEntry ) |
| { |
| implChangeHighlightEntry( nEntry ); |
| } |
| } |
| bHighlighted = true; |
| } |
| } |
| } |
| else |
| { |
| nY += SEPARATOR_HEIGHT; |
| } |
| } |
| if ( !bHighlighted ) |
| implChangeHighlightEntry( -1 ); |
| } |
| else |
| { |
| implChangeHighlightEntry( -1 ); |
| } |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::implChangeHighlightEntry( int nEntry ) |
| { |
| if( mpImpl->mnHighlightedEntry != -1 ) |
| { |
| implHighlightEntry( mpImpl->mnHighlightedEntry, false ); |
| } |
| |
| mpImpl->mnHighlightedEntry = nEntry; |
| Invalidate(); |
| |
| if( mpImpl->mnHighlightedEntry != -1 ) |
| { |
| implHighlightEntry( mpImpl->mnHighlightedEntry, true ); |
| } |
| |
| mpImpl->notifyHighlightedEntry(); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| static bool implCheckSubControlCursorMove( Control* pControl, bool bUp, int& nLastColumn ) |
| { |
| ValueSet* pValueSet = dynamic_cast< ValueSet* >( pControl ); |
| if( pValueSet ) |
| { |
| sal_uInt16 nItemPos = pValueSet->GetItemPos( pValueSet->GetSelectItemId() ); |
| if( nItemPos != VALUESET_ITEM_NOTFOUND ) |
| { |
| const sal_uInt16 nColCount = pValueSet->GetColCount(); |
| const sal_uInt16 nLine = nItemPos / nColCount; |
| |
| nLastColumn = nItemPos - (nLine * nColCount); |
| |
| if( bUp ) |
| { |
| return nLine > 0; |
| } |
| else |
| { |
| const sal_uInt16 nLineCount = (pValueSet->GetItemCount() + nColCount - 1) / nColCount; |
| return (nLine+1) < nLineCount; |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| ToolbarMenuEntry* ToolbarMenu::implCursorUpDown( bool bUp, bool bHomeEnd ) |
| { |
| int n = 0, nLoop = 0; |
| if( !bHomeEnd ) |
| { |
| n = mpImpl->mnHighlightedEntry; |
| if( n == -1 ) |
| { |
| if( bUp ) |
| n = 0; |
| else |
| n = mpImpl->maEntryVector.size()-1; |
| } |
| else |
| { |
| // if we have a currently selected entry and |
| // cursor keys are used than check if this entry |
| // has a control that can use those cursor keys |
| ToolbarMenuEntry* pData = mpImpl->maEntryVector[n]; |
| if( pData && pData->mpControl && !pData->mbHasText ) |
| { |
| if( implCheckSubControlCursorMove( pData->mpControl, bUp, mpImpl->mnLastColumn ) ) |
| return pData; |
| } |
| } |
| nLoop = n; |
| } |
| else |
| { |
| // absolute positioning |
| if( bUp ) |
| { |
| n = mpImpl->maEntryVector.size(); |
| nLoop = n-1; |
| } |
| else |
| { |
| n = -1; |
| nLoop = mpImpl->maEntryVector.size()-1; |
| } |
| } |
| |
| do |
| { |
| if( bUp ) |
| { |
| if ( n ) |
| n--; |
| else |
| if( mpImpl->mnHighlightedEntry == -1 ) |
| n = mpImpl->maEntryVector.size()-1; |
| else |
| break; |
| } |
| else |
| { |
| if( n < ((int)mpImpl->maEntryVector.size()-1) ) |
| n++; |
| else |
| if( mpImpl->mnHighlightedEntry == -1 ) |
| n = 0; |
| else |
| break; |
| } |
| |
| ToolbarMenuEntry* pData = mpImpl->maEntryVector[n]; |
| if( pData && (pData->mnEntryId != TITLE_ID) ) |
| { |
| implChangeHighlightEntry( n ); |
| return pData; |
| } |
| } while ( n != nLoop ); |
| |
| return 0; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu_Impl::implHighlightControl( sal_uInt16 nCode, Control* pControl ) |
| { |
| ValueSet* pValueSet = dynamic_cast< ValueSet* >( pControl ); |
| if( pValueSet ) |
| { |
| const sal_uInt16 nItemCount = pValueSet->GetItemCount(); |
| sal_uInt16 nItemPos = VALUESET_ITEM_NOTFOUND; |
| switch( nCode ) |
| { |
| case KEY_UP: |
| { |
| const sal_uInt16 nColCount = pValueSet->GetColCount(); |
| const sal_uInt16 nLastLine = nItemCount / nColCount; |
| nItemPos = std::min( ((nLastLine-1) * nColCount) + mnLastColumn, nItemCount-1 ); |
| break; |
| } |
| case KEY_DOWN: |
| nItemPos = std::min( mnLastColumn, nItemCount-1 ); |
| break; |
| case KEY_END: |
| nItemPos = nItemCount -1; |
| break; |
| case KEY_HOME: |
| nItemPos = 0; |
| break; |
| } |
| pValueSet->SelectItem( pValueSet->GetItemId( nItemPos ) ); |
| notifyHighlightedEntry(); |
| } |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::KeyInput( const KeyEvent& rKEvent ) |
| { |
| Control* pForwardControl = 0; |
| sal_uInt16 nCode = rKEvent.GetKeyCode().GetCode(); |
| switch ( nCode ) |
| { |
| case KEY_UP: |
| case KEY_DOWN: |
| { |
| int nOldEntry = mpImpl->mnHighlightedEntry; |
| ToolbarMenuEntry*p = implCursorUpDown( nCode == KEY_UP, false ); |
| if( p && p->mpControl ) |
| { |
| if( nOldEntry != mpImpl->mnHighlightedEntry ) |
| { |
| mpImpl->implHighlightControl( nCode, p->mpControl ); |
| } |
| else |
| { |
| // in case we are in a system floating window, GrabFocus does not work :-/ |
| pForwardControl = p->mpControl; |
| } |
| } |
| } |
| break; |
| case KEY_END: |
| case KEY_HOME: |
| { |
| ToolbarMenuEntry* p = implCursorUpDown( nCode == KEY_END, true ); |
| if( p && p->mpControl ) |
| { |
| mpImpl->implHighlightControl( nCode, p->mpControl ); |
| } |
| } |
| break; |
| case KEY_F6: |
| case KEY_ESCAPE: |
| { |
| // Ctrl-F6 acts like ESC here, the menu bar however will then put the focus in the document |
| if( nCode == KEY_F6 && !rKEvent.GetKeyCode().IsMod1() ) |
| break; |
| |
| implSelectEntry( -1 ); |
| } |
| break; |
| |
| case KEY_RETURN: |
| { |
| ToolbarMenuEntry* pEntry = implGetEntry( mpImpl->mnHighlightedEntry ); |
| if ( pEntry && pEntry->mbEnabled && (pEntry->mnEntryId != TITLE_ID) ) |
| { |
| if( pEntry->mpControl ) |
| { |
| pForwardControl = pEntry->mpControl; |
| } |
| else |
| { |
| implSelectEntry( mpImpl->mnHighlightedEntry ); |
| } |
| } |
| } |
| break; |
| default: |
| { |
| ToolbarMenuEntry* pEntry = implGetEntry( mpImpl->mnHighlightedEntry ); |
| if ( pEntry && pEntry->mbEnabled && pEntry->mpControl && !pEntry->mbHasText ) |
| { |
| pForwardControl = pEntry->mpControl; |
| } |
| } |
| |
| } |
| if( pForwardControl ) |
| pForwardControl->KeyInput( rKEvent ); |
| |
| } |
| |
| // -------------------------------------------------------------------- |
| static void ImplPaintCheckBackground( Window* i_pWindow, const Rectangle& i_rRect, bool i_bHighlight ) |
| { |
| sal_Bool bNativeOk = sal_False; |
| if( i_pWindow->IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) ) |
| { |
| ImplControlValue aControlValue; |
| ControlState nState = CTRL_STATE_PRESSED | CTRL_STATE_ENABLED; |
| |
| aControlValue.setTristateVal( BUTTONVALUE_ON ); |
| |
| bNativeOk = i_pWindow->DrawNativeControl( CTRL_TOOLBAR, PART_BUTTON, |
| i_rRect, nState, aControlValue, |
| rtl::OUString() ); |
| } |
| |
| if( ! bNativeOk ) |
| { |
| const StyleSettings& rSettings = i_pWindow->GetSettings().GetStyleSettings(); |
| Color aColor( i_bHighlight ? rSettings.GetMenuHighlightTextColor() : rSettings.GetHighlightColor() ); |
| i_pWindow->DrawSelectionBackground( i_rRect, 0, i_bHighlight, sal_True, sal_False, 2, NULL, &aColor ); |
| } |
| } |
| |
| static long ImplGetNativeCheckAndRadioSize( Window* pWin, long& rCheckHeight, long& rRadioHeight, long &rMaxWidth ) |
| { |
| rMaxWidth = rCheckHeight = rRadioHeight = 0; |
| |
| ImplControlValue aVal; |
| Rectangle aNativeBounds; |
| Rectangle aNativeContent; |
| Point tmp( 0, 0 ); |
| Rectangle aCtrlRegion( tmp, Size( 100, 15 ) ); |
| if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM_CHECK_MARK ) ) |
| { |
| if( pWin->GetNativeControlRegion( ControlType(CTRL_MENU_POPUP), |
| ControlPart(PART_MENU_ITEM_CHECK_MARK), |
| aCtrlRegion, |
| ControlState(CTRL_STATE_ENABLED), |
| aVal, |
| OUString(), |
| aNativeBounds, |
| aNativeContent ) |
| ) |
| { |
| rCheckHeight = aNativeBounds.GetHeight(); |
| rMaxWidth = aNativeContent.GetWidth(); |
| } |
| } |
| if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM_RADIO_MARK ) ) |
| { |
| if( pWin->GetNativeControlRegion( ControlType(CTRL_MENU_POPUP), |
| ControlPart(PART_MENU_ITEM_RADIO_MARK), |
| aCtrlRegion, |
| ControlState(CTRL_STATE_ENABLED), |
| aVal, |
| OUString(), |
| aNativeBounds, |
| aNativeContent ) |
| ) |
| { |
| rRadioHeight = aNativeBounds.GetHeight(); |
| rMaxWidth = Max (rMaxWidth, aNativeContent.GetWidth()); |
| } |
| } |
| return (rCheckHeight > rRadioHeight) ? rCheckHeight : rRadioHeight; |
| } |
| |
| void ToolbarMenu::implPaint( ToolbarMenuEntry* pThisOnly, bool bHighlighted ) |
| { |
| sal_uInt16 nBorder = 0; long nStartY = 0; // from Menu implementations, needed when we support native menu background & scrollable menu |
| |
| long nFontHeight = GetTextHeight(); |
| // long nExtra = nFontHeight/4; |
| |
| long nCheckHeight = 0, nRadioHeight = 0, nMaxCheckWidth = 0; |
| ImplGetNativeCheckAndRadioSize( this, nCheckHeight, nRadioHeight, nMaxCheckWidth ); |
| |
| DecorationView aDecoView( this ); |
| const StyleSettings& rSettings = GetSettings().GetStyleSettings(); |
| const bool bUseImages = rSettings.GetUseImagesInMenus(); |
| |
| int nOuterSpace = 0; // ImplGetSVData()->maNWFData.mnMenuFormatExtraBorder; |
| Point aTopLeft( nOuterSpace, nOuterSpace ), aTmpPos; |
| |
| Size aOutSz( GetOutputSizePixel() ); |
| const int nEntryCount = mpImpl->maEntryVector.size(); |
| int nEntry; |
| for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) |
| { |
| ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry]; |
| |
| Point aPos( aTopLeft ); |
| aPos.Y() += nBorder; |
| aPos.Y() += nStartY; |
| |
| |
| if( (pEntry == 0) && !pThisOnly ) |
| { |
| // Separator |
| aTmpPos.Y() = aPos.Y() + ((SEPARATOR_HEIGHT-2)/2); |
| aTmpPos.X() = aPos.X() + 2 + nOuterSpace; |
| SetLineColor( rSettings.GetShadowColor() ); |
| DrawLine( aTmpPos, Point( aOutSz.Width() - 3 - 2*nOuterSpace, aTmpPos.Y() ) ); |
| aTmpPos.Y()++; |
| SetLineColor( rSettings.GetLightColor() ); |
| DrawLine( aTmpPos, Point( aOutSz.Width() - 3 - 2*nOuterSpace, aTmpPos.Y() ) ); |
| SetLineColor(); |
| } |
| else if( !pThisOnly || ( pEntry == pThisOnly ) ) |
| { |
| const bool bTitle = pEntry->mnEntryId == TITLE_ID; |
| |
| if ( pThisOnly && bHighlighted ) |
| SetTextColor( rSettings.GetMenuHighlightTextColor() ); |
| |
| if( aPos.Y() >= 0 ) |
| { |
| long nTextOffsetY = ((pEntry->maSize.Height()-nFontHeight)/2); |
| |
| sal_uInt16 nTextStyle = 0; |
| sal_uInt16 nSymbolStyle = 0; |
| sal_uInt16 nImageStyle = 0; |
| |
| if( !pEntry->mbEnabled ) |
| { |
| nTextStyle |= TEXT_DRAW_DISABLE; |
| nSymbolStyle |= SYMBOL_DRAW_DISABLE; |
| nImageStyle |= IMAGE_DRAW_DISABLE; |
| } |
| |
| Rectangle aOuterCheckRect( Point( aPos.X()+mpImpl->mnCheckPos, aPos.Y() ), Size( pEntry->maSize.Height(), pEntry->maSize.Height() ) ); |
| aOuterCheckRect.Left() += 1; |
| aOuterCheckRect.Right() -= 1; |
| aOuterCheckRect.Top() += 1; |
| aOuterCheckRect.Bottom() -= 1; |
| |
| if( bTitle ) |
| { |
| // fill the background |
| Rectangle aRect( aTopLeft, Size( aOutSz.Width(), pEntry->maSize.Height() ) ); |
| SetFillColor(rSettings.GetDialogColor()); |
| SetLineColor(); |
| DrawRect(aRect); |
| SetLineColor( rSettings.GetLightColor() ); |
| DrawLine( aRect.TopLeft(), aRect.TopRight() ); |
| SetLineColor( rSettings.GetShadowColor() ); |
| DrawLine( aRect.BottomLeft(), aRect.BottomRight() ); |
| } |
| |
| // CheckMark |
| if ( pEntry->HasCheck() ) |
| { |
| // draw selection transparent marker if checked |
| // onto that either a checkmark or the item image |
| // will be painted |
| // however do not do this if native checks will be painted since |
| // the selection color too often does not fit the theme's check and/or radio |
| |
| if( !pEntry->mbHasImage ) |
| { |
| if( this->IsNativeControlSupported( CTRL_MENU_POPUP, |
| (pEntry->mnBits & MIB_RADIOCHECK) |
| ? PART_MENU_ITEM_CHECK_MARK |
| : PART_MENU_ITEM_RADIO_MARK ) ) |
| { |
| ControlPart nPart = ((pEntry->mnBits & MIB_RADIOCHECK) |
| ? PART_MENU_ITEM_RADIO_MARK |
| : PART_MENU_ITEM_CHECK_MARK); |
| |
| ControlState nState = 0; |
| |
| if ( pEntry->mbChecked ) |
| nState |= CTRL_STATE_PRESSED; |
| |
| if ( pEntry->mbEnabled ) |
| nState |= CTRL_STATE_ENABLED; |
| |
| if ( bHighlighted ) |
| nState |= CTRL_STATE_SELECTED; |
| |
| long nCtrlHeight = (pEntry->mnBits & MIB_RADIOCHECK) ? nCheckHeight : nRadioHeight; |
| aTmpPos.X() = aOuterCheckRect.Left() + (aOuterCheckRect.GetWidth() - nCtrlHeight)/2; |
| aTmpPos.Y() = aOuterCheckRect.Top() + (aOuterCheckRect.GetHeight() - nCtrlHeight)/2; |
| |
| Rectangle aCheckRect( aTmpPos, Size( nCtrlHeight, nCtrlHeight ) ); |
| DrawNativeControl( CTRL_MENU_POPUP, nPart, aCheckRect, nState, ImplControlValue(), OUString() ); |
| } |
| else if ( pEntry->mbChecked ) // by default do nothing for unchecked items |
| { |
| ImplPaintCheckBackground( this, aOuterCheckRect, pThisOnly && bHighlighted ); |
| |
| SymbolType eSymbol; |
| Size aSymbolSize; |
| if ( pEntry->mnBits & MIB_RADIOCHECK ) |
| { |
| eSymbol = SYMBOL_RADIOCHECKMARK; |
| aSymbolSize = Size( nFontHeight/2, nFontHeight/2 ); |
| } |
| else |
| { |
| eSymbol = SYMBOL_CHECKMARK; |
| aSymbolSize = Size( (nFontHeight*25)/40, nFontHeight/2 ); |
| } |
| aTmpPos.X() = aOuterCheckRect.Left() + (aOuterCheckRect.GetWidth() - aSymbolSize.Width())/2; |
| aTmpPos.Y() = aOuterCheckRect.Top() + (aOuterCheckRect.GetHeight() - aSymbolSize.Height())/2; |
| Rectangle aRect( aTmpPos, aSymbolSize ); |
| aDecoView.DrawSymbol( aRect, eSymbol, GetTextColor(), nSymbolStyle ); |
| } |
| } |
| } |
| |
| // Image: |
| if( pEntry->mbHasImage && bUseImages ) |
| { |
| // Don't render an image for a check thing |
| /* if((nMenuFlags & MENU_FLAG_SHOWCHECKIMAGES) || !pEntry->HasCheck() )*/ |
| { |
| if( pEntry->mbChecked ) |
| ImplPaintCheckBackground( this, aOuterCheckRect, pThisOnly && bHighlighted ); |
| aTmpPos = aOuterCheckRect.TopLeft(); |
| aTmpPos.X() += (aOuterCheckRect.GetWidth()-pEntry->maImage.GetSizePixel().Width())/2; |
| aTmpPos.Y() += (aOuterCheckRect.GetHeight()-pEntry->maImage.GetSizePixel().Height())/2; |
| DrawImage( aTmpPos, pEntry->maImage, nImageStyle ); |
| } |
| } |
| |
| // Text: |
| if( pEntry->mbHasText ) |
| { |
| aTmpPos.X() = aPos.X() + (bTitle ? 4 : mpImpl->mnTextPos); |
| aTmpPos.Y() = aPos.Y(); |
| aTmpPos.Y() += nTextOffsetY; |
| sal_uInt16 nStyle = nTextStyle|TEXT_DRAW_MNEMONIC; |
| |
| DrawCtrlText( aTmpPos, pEntry->maText, 0, pEntry->maText.Len(), nStyle, NULL, NULL ); // pVector, pDisplayText ); |
| } |
| |
| /* |
| // Accel |
| if ( !bLayout && !bIsMenuBar && pData->aAccelKey.GetCode() && !ImplAccelDisabled() ) |
| { |
| XubString aAccText = pData->aAccelKey.GetName(); |
| aTmpPos.X() = aOutSz.Width() - this->GetTextWidth( aAccText ); |
| aTmpPos.X() -= 4*nExtra; |
| |
| aTmpPos.X() -= nOuterSpace; |
| aTmpPos.Y() = aPos.Y(); |
| aTmpPos.Y() += nTextOffsetY; |
| this->DrawCtrlText( aTmpPos, aAccText, 0, aAccText.Len(), nTextStyle ); |
| } |
| */ |
| |
| /* |
| // SubMenu? |
| if ( !bLayout && !bIsMenuBar && pData->pSubMenu ) |
| { |
| aTmpPos.X() = aOutSz.Width() - nFontHeight + nExtra - nOuterSpace; |
| aTmpPos.Y() = aPos.Y(); |
| aTmpPos.Y() += nExtra/2; |
| aTmpPos.Y() += ( pEntry->maSize.Height() / 2 ) - ( nFontHeight/4 ); |
| if ( pEntry->mnBits & MIB_POPUPSELECT ) |
| { |
| this->SetTextColor( rSettings.GetMenuTextColor() ); |
| Point aTmpPos2( aPos ); |
| aTmpPos2.X() = aOutSz.Width() - nFontHeight - nFontHeight/4; |
| aDecoView.DrawFrame( |
| Rectangle( aTmpPos2, Size( nFontHeight+nFontHeight/4, pEntry->maSize.Height() ) ), FRAME_DRAW_GROUP ); |
| } |
| aDecoView.DrawSymbol( |
| Rectangle( aTmpPos, Size( nFontHeight/2, nFontHeight/2 ) ), |
| SYMBOL_SPIN_RIGHT, this->GetTextColor(), nSymbolStyle ); |
| // if ( pEntry->mnBits & MIB_POPUPSELECT ) |
| // { |
| // aTmpPos.Y() += nFontHeight/2 ; |
| // this->SetLineColor( rSettings.GetShadowColor() ); |
| // this->DrawLine( aTmpPos, Point( aTmpPos.X() + nFontHeight/3, aTmpPos.Y() ) ); |
| // this->SetLineColor( rSettings.GetLightColor() ); |
| // aTmpPos.Y()++; |
| // this->DrawLine( aTmpPos, Point( aTmpPos.X() + nFontHeight/3, aTmpPos.Y() ) ); |
| // this->SetLineColor(); |
| // } |
| } |
| */ |
| |
| if ( pThisOnly && bHighlighted ) |
| { |
| // This restores the normal menu or menu bar text |
| // color for when it is no longer highlighted. |
| SetTextColor( rSettings.GetMenuTextColor() ); |
| } |
| } |
| } |
| |
| aTopLeft.Y() += pEntry ? pEntry->maSize.Height() : SEPARATOR_HEIGHT; |
| } |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::Paint( const Rectangle& ) |
| { |
| SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() ); |
| |
| implPaint(); |
| |
| if( mpImpl->mnHighlightedEntry != -1 ) |
| implHighlightEntry( mpImpl->mnHighlightedEntry, true ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::RequestHelp( const HelpEvent& rHEvt ) |
| { |
| DockingWindow::RequestHelp( rHEvt ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::StateChanged( StateChangedType nType ) |
| { |
| DockingWindow::StateChanged( nType ); |
| |
| if ( ( nType == STATE_CHANGE_CONTROLFOREGROUND ) || ( nType == STATE_CHANGE_CONTROLBACKGROUND ) ) |
| { |
| initWindow(); |
| Invalidate(); |
| } |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::DataChanged( const DataChangedEvent& rDCEvt ) |
| { |
| DockingWindow::DataChanged( rDCEvt ); |
| |
| if ( (rDCEvt.GetType() == DATACHANGED_FONTS) || |
| (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) || |
| ((rDCEvt.GetType() == DATACHANGED_SETTINGS) && |
| (rDCEvt.GetFlags() & SETTINGS_STYLE)) ) |
| { |
| initWindow(); |
| Invalidate(); |
| } |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::Command( const CommandEvent& rCEvt ) |
| { |
| if ( rCEvt.GetCommand() == COMMAND_WHEEL ) |
| { |
| const CommandWheelData* pData = rCEvt.GetWheelData(); |
| if( !pData->GetModifier() && ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) ) |
| { |
| implCursorUpDown( pData->GetDelta() > 0L, false ); |
| } |
| } |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| Reference< ::com::sun::star::accessibility::XAccessible > ToolbarMenu::CreateAccessible() |
| { |
| mpImpl->setAccessible( new ToolbarMenuAcc( *mpImpl ) ); |
| return Reference< XAccessible >( mpImpl->mxAccessible.get() ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| // todo: move to new base class that will replace SfxPopupWindo |
| void ToolbarMenu::AddStatusListener( const rtl::OUString& rCommandURL ) |
| { |
| initStatusListener(); |
| mpImpl->mxStatusListener->addStatusListener( rCommandURL ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::RemoveStatusListener( const rtl::OUString& rCommandURL ) |
| { |
| mpImpl->mxStatusListener->removeStatusListener( rCommandURL ); |
| } |
| // -------------------------------------------------------------------- |
| |
| |
| void ToolbarMenu::UpdateStatus( const rtl::OUString& rCommandURL ) |
| { |
| mpImpl->mxStatusListener->updateStatus( rCommandURL ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| // XStatusListener (subclasses must override this one to get the status updates |
| void SAL_CALL ToolbarMenu::statusChanged( const ::com::sun::star::frame::FeatureStateEvent& /*Event*/ ) throw ( ::com::sun::star::uno::RuntimeException ) |
| { |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| class ToolbarMenuStatusListener : public svt::FrameStatusListener |
| { |
| public: |
| ToolbarMenuStatusListener( const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& xServiceManager, |
| const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame, |
| ToolbarMenu& rToolbarMenu ); |
| |
| virtual void SAL_CALL dispose() throw (::com::sun::star::uno::RuntimeException); |
| virtual void SAL_CALL statusChanged( const ::com::sun::star::frame::FeatureStateEvent& Event ) throw ( ::com::sun::star::uno::RuntimeException ); |
| |
| ToolbarMenu* mpMenu; |
| }; |
| |
| // -------------------------------------------------------------------- |
| |
| ToolbarMenuStatusListener::ToolbarMenuStatusListener( |
| const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& xServiceManager, |
| const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame, |
| ToolbarMenu& rToolbarMenu ) |
| : svt::FrameStatusListener( xServiceManager, xFrame ) |
| , mpMenu( &rToolbarMenu ) |
| { |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void SAL_CALL ToolbarMenuStatusListener::dispose() throw (::com::sun::star::uno::RuntimeException) |
| { |
| mpMenu = 0; |
| svt::FrameStatusListener::dispose(); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void SAL_CALL ToolbarMenuStatusListener::statusChanged( const ::com::sun::star::frame::FeatureStateEvent& Event ) throw ( ::com::sun::star::uno::RuntimeException ) |
| { |
| if( mpMenu ) |
| mpMenu->statusChanged( Event ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::initStatusListener() |
| { |
| if( !mpImpl->mxStatusListener.is() ) |
| mpImpl->mxStatusListener.set( new ToolbarMenuStatusListener( mpImpl->mxServiceManager, mpImpl->mxFrame, *this ) ); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| bool ToolbarMenu::IsInPopupMode() |
| { |
| return GetDockingManager()->IsInPopupMode(this); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::EndPopupMode() |
| { |
| GetDockingManager()->EndPopupMode(this); |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| const Size& ToolbarMenu::getMenuSize() const |
| { |
| return mpImpl->maSize; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| void ToolbarMenu::SetSelectHdl( const Link& rLink ) |
| { |
| mpImpl->maSelectHdl = rLink; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| const Link& ToolbarMenu::GetSelectHdl() const |
| { |
| return mpImpl->maSelectHdl; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| Reference< XFrame > ToolbarMenu::GetFrame() const |
| { |
| return mpImpl->mxFrame; |
| } |
| |
| // -------------------------------------------------------------------- |
| |
| |
| // -------------------------------------------------------------------- |
| |
| } |
| |
| |