From 81d3e5624bf44c7226e7041de093805b272a0dca Mon Sep 17 00:00:00 2001 From: Christian Lippka Date: Sun, 6 Dec 2009 19:11:23 +0100 Subject: [PATCH 01/18] renaissance01: #i107213# ignore grip on mouse move --- vcl/source/window/dockmgr.cxx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/vcl/source/window/dockmgr.cxx b/vcl/source/window/dockmgr.cxx index c587b7ad8441..940f2423e696 100644 --- a/vcl/source/window/dockmgr.cxx +++ b/vcl/source/window/dockmgr.cxx @@ -518,6 +518,7 @@ private: ImplDockingWindowWrapper* mpDockingWin; BOOL mbHighlight; BOOL mbMoving; + bool mbTrackingEnabled; Point maDelta; Point maTearOffPosition; void ImplSetBorder(); @@ -550,6 +551,7 @@ ImplPopupFloatWin::ImplPopupFloatWin( Window* pParent, ImplDockingWindowWrapper* mpDockingWin = pDockingWin; mbHighlight = FALSE; mbMoving = FALSE; + mbTrackingEnabled = FALSE; ImplSetBorder(); } @@ -736,7 +738,7 @@ void ImplPopupFloatWin::MouseMove( const MouseEvent& rMEvt ) if( !ToolBox::AlwaysLocked() ) // no tear off if locking is enabled { - if( rMEvt.IsLeft() && GetDragRect().IsInside( aMousePos ) ) + if( mbTrackingEnabled && rMEvt.IsLeft() && GetDragRect().IsInside( aMousePos ) ) { // start window move mbMoving = TRUE; @@ -758,6 +760,7 @@ void ImplPopupFloatWin::MouseMove( const MouseEvent& rMEvt ) void ImplPopupFloatWin::MouseButtonUp( const MouseEvent& rMEvt ) { + mbTrackingEnabled = false; FloatingWindow::MouseButtonUp( rMEvt ); } @@ -772,6 +775,11 @@ void ImplPopupFloatWin::MouseButtonDown( const MouseEvent& rMEvt ) ImplMirrorFramePos(aState.maPos); maTearOffPosition = GetWindow( WINDOW_BORDER )->GetPosPixel(); maDelta = aState.maPos - maTearOffPosition; + mbTrackingEnabled = true; + } + else + { + mbTrackingEnabled = false; } } From 0750c39411ea0d9dfcfe3d760b175958987aff97 Mon Sep 17 00:00:00 2001 From: Christian Lippka Date: Sun, 17 Jan 2010 18:15:22 +0100 Subject: [PATCH 02/18] added DockingManager::EndPopupMode( const Window *pWin ) --- vcl/inc/vcl/dockwin.hxx | 1 + vcl/source/window/dockmgr.cxx | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/vcl/inc/vcl/dockwin.hxx b/vcl/inc/vcl/dockwin.hxx index 376308a8b27b..982180e945fd 100644 --- a/vcl/inc/vcl/dockwin.hxx +++ b/vcl/inc/vcl/dockwin.hxx @@ -238,6 +238,7 @@ public: void StartPopupMode( ToolBox *pParentToolBox, const Window *pWin ); BOOL IsInPopupMode( const Window *pWin ); + void EndPopupMode( const Window *pWin ); // required because those methods are not virtual in Window (!!!) and must // be availbale from the toolkit diff --git a/vcl/source/window/dockmgr.cxx b/vcl/source/window/dockmgr.cxx index 940f2423e696..24b2da8e85bf 100644 --- a/vcl/source/window/dockmgr.cxx +++ b/vcl/source/window/dockmgr.cxx @@ -445,6 +445,17 @@ BOOL DockingManager::IsInPopupMode( const Window *pWindow ) return FALSE; } +// ----------------------------------------------------------------------- + +void DockingManager::EndPopupMode( const Window *pWin ) +{ + ImplDockingWindowWrapper *pWrapper = GetDockingWindowWrapper( pWin ); + if( pWrapper && pWrapper->GetFloatingWindow() && pWrapper->GetFloatingWindow()->IsInPopupMode() ) + pWrapper->GetFloatingWindow()->EndPopupMode(); +} + +// ----------------------------------------------------------------------- + void DockingManager::AddWindow( const Window *pWindow ) { ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow ); @@ -1350,7 +1361,7 @@ void ImplDockingWindowWrapper::SetFloatingMode( BOOL bFloatMode ) aSettings.SetStyleSettings( aStyleSettings ); pWin->SetSettings( aSettings );*/ - mpFloatWin = pWin; +// mpFloatWin = pWin; GetWindow()->mpWindowImpl->mpBorderWindow = NULL; @@ -1385,6 +1396,8 @@ void ImplDockingWindowWrapper::SetFloatingMode( BOOL bFloatMode ) pWin->SetMinOutputSizePixel( maMinOutSize ); pWin->SetMaxOutputSizePixel( maMaxOutSize ); + mpFloatWin = pWin; + if ( bVisible ) GetWindow()->Show( TRUE, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE ); From fbb946815b14c1eb50791a9338950ff29ebe8479 Mon Sep 17 00:00:00 2001 From: Christian Lippka Date: Mon, 18 Jan 2010 20:46:53 +0100 Subject: [PATCH 03/18] put drag grip at the bottom --- vcl/source/window/dockmgr.cxx | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/vcl/source/window/dockmgr.cxx b/vcl/source/window/dockmgr.cxx index 24b2da8e85bf..5b028e511e24 100644 --- a/vcl/source/window/dockmgr.cxx +++ b/vcl/source/window/dockmgr.cxx @@ -532,6 +532,7 @@ private: bool mbTrackingEnabled; Point maDelta; Point maTearOffPosition; + bool mbGripAtBottom; void ImplSetBorder(); public: @@ -563,6 +564,7 @@ ImplPopupFloatWin::ImplPopupFloatWin( Window* pParent, ImplDockingWindowWrapper* mbHighlight = FALSE; mbMoving = FALSE; mbTrackingEnabled = FALSE; + mbGripAtBottom = TRUE; ImplSetBorder(); } @@ -612,13 +614,22 @@ void ImplPopupFloatWin::Resize() Rectangle ImplPopupFloatWin::GetDragRect() const { - return Rectangle( 1, 1, GetOutputSizePixel().Width()-1, 2+POPUP_DRAGHEIGHT ); + Rectangle aRect( 1,1, GetOutputSizePixel().Width()-1, 2+POPUP_DRAGHEIGHT ); + if( mbGripAtBottom ) + { + int height = GetOutputSizePixel().Height(); + aRect.Top() = height - 3 - POPUP_DRAGHEIGHT; + aRect.Bottom() = aRect.Top() + 1 + POPUP_DRAGHEIGHT; + } + + return aRect; } Point ImplPopupFloatWin::GetToolboxPosition() const { // return inner position where a toolbox could be placed - Point aPt( 1, 1+GetDragRect().getHeight() ); // grip + border + Point aPt( 1, 1 + (mbGripAtBottom ? 0 : GetDragRect().getHeight()) ); // grip + border + return aPt; } From 61664303ef9f75e30a109f114a5e10348eb5b8ec Mon Sep 17 00:00:00 2001 From: Christian Lippka Date: Thu, 11 Mar 2010 18:15:22 +0100 Subject: [PATCH 04/18] allow popup windows without tear off --- vcl/inc/vcl/dockwin.hxx | 4 ++- vcl/source/window/dockmgr.cxx | 62 ++++++++++++++++++++++------------- 2 files changed, 43 insertions(+), 23 deletions(-) diff --git a/vcl/inc/vcl/dockwin.hxx b/vcl/inc/vcl/dockwin.hxx index 982180e945fd..f99f774a18be 100644 --- a/vcl/inc/vcl/dockwin.hxx +++ b/vcl/inc/vcl/dockwin.hxx @@ -155,7 +155,7 @@ public: void Unlock(); BOOL IsLocked() const; - void StartPopupMode( ToolBox* pParentToolBox ); + void StartPopupMode( ToolBox* pParentToolBox, ULONG nPopupModeFlags ); BOOL IsInPopupMode() const; void TitleButtonClick( USHORT nButton ); @@ -237,6 +237,8 @@ public: BOOL IsLocked( const Window *pWin ); void StartPopupMode( ToolBox *pParentToolBox, const Window *pWin ); + void StartPopupMode( ToolBox *pParentToolBox, const Window *pWin, ULONG nPopupModeFlags ); + BOOL IsInPopupMode( const Window *pWin ); void EndPopupMode( const Window *pWin ); diff --git a/vcl/source/window/dockmgr.cxx b/vcl/source/window/dockmgr.cxx index 5b028e511e24..f8dcb0265c81 100644 --- a/vcl/source/window/dockmgr.cxx +++ b/vcl/source/window/dockmgr.cxx @@ -429,11 +429,19 @@ void DockingManager::SetFloatingMode( const Window *pWindow, BOOL bFloating ) pWrapper->SetFloatingMode( bFloating ); } -void DockingManager::StartPopupMode( ToolBox *pParentToolBox, const Window *pWindow ) +void DockingManager::StartPopupMode( ToolBox *pParentToolBox, const Window *pWindow, ULONG nFlags ) { ImplDockingWindowWrapper* pWrapper = GetDockingWindowWrapper( pWindow ); if( pWrapper ) - pWrapper->StartPopupMode( pParentToolBox ); + pWrapper->StartPopupMode( pParentToolBox, nFlags ); +} + +void DockingManager::StartPopupMode( ToolBox *pParentToolBox, const Window *pWindow ) +{ + StartPopupMode( pParentToolBox, pWindow, FLOATWIN_POPUPMODE_ALLOWTEAROFF | + FLOATWIN_POPUPMODE_NOFOCUSCLOSE | + FLOATWIN_POPUPMODE_ALLMOUSEBUTTONCLOSE | + FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE ); } BOOL DockingManager::IsInPopupMode( const Window *pWindow ) @@ -533,10 +541,11 @@ private: Point maDelta; Point maTearOffPosition; bool mbGripAtBottom; + bool mbHasGrip; void ImplSetBorder(); public: - ImplPopupFloatWin( Window* pParent, ImplDockingWindowWrapper* pDockingWin ); + ImplPopupFloatWin( Window* pParent, ImplDockingWindowWrapper* pDockingWin, bool bHasGrip ); ~ImplPopupFloatWin(); virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible(); @@ -553,9 +562,11 @@ public: Point GetTearOffPosition() const; void DrawGrip(); void DrawBorder(); + + bool hasGrip() const { return mbHasGrip; } }; -ImplPopupFloatWin::ImplPopupFloatWin( Window* pParent, ImplDockingWindowWrapper* pDockingWin ) : +ImplPopupFloatWin::ImplPopupFloatWin( Window* pParent, ImplDockingWindowWrapper* pDockingWin, bool bHasGrip ) : FloatingWindow( pParent, WB_NOBORDER | WB_SYSTEMWINDOW | WB_NOSHADOW) { mpWindowImpl->mbToolbarFloatingWindow = TRUE; // indicate window type, required for accessibility @@ -565,6 +576,7 @@ ImplPopupFloatWin::ImplPopupFloatWin( Window* pParent, ImplDockingWindowWrapper* mbMoving = FALSE; mbTrackingEnabled = FALSE; mbGripAtBottom = TRUE; + mbHasGrip = bHasGrip; ImplSetBorder(); } @@ -600,7 +612,9 @@ void ImplPopupFloatWin::ImplSetBorder() // we're using a special border for the grip // by setting those members the method SetOutputSizePixel() can // be used to set the proper window size - mpWindowImpl->mnTopBorder = 1 + POPUP_DRAGHEIGHT+2; + mpWindowImpl->mnTopBorder = 1; + if( hasGrip() ) + mpWindowImpl->mnTopBorder += POPUP_DRAGHEIGHT+2; mpWindowImpl->mnBottomBorder = 1; mpWindowImpl->mnLeftBorder = 1; mpWindowImpl->mnRightBorder = 1; @@ -614,21 +628,24 @@ void ImplPopupFloatWin::Resize() Rectangle ImplPopupFloatWin::GetDragRect() const { - Rectangle aRect( 1,1, GetOutputSizePixel().Width()-1, 2+POPUP_DRAGHEIGHT ); - if( mbGripAtBottom ) + Rectangle aRect; + if( hasGrip() ) { - int height = GetOutputSizePixel().Height(); - aRect.Top() = height - 3 - POPUP_DRAGHEIGHT; - aRect.Bottom() = aRect.Top() + 1 + POPUP_DRAGHEIGHT; + aRect = Rectangle( 1,1, GetOutputSizePixel().Width()-1, 2+POPUP_DRAGHEIGHT ); + if( mbGripAtBottom ) + { + int height = GetOutputSizePixel().Height(); + aRect.Top() = height - 3 - POPUP_DRAGHEIGHT; + aRect.Bottom() = aRect.Top() + 1 + POPUP_DRAGHEIGHT; + } } - return aRect; } Point ImplPopupFloatWin::GetToolboxPosition() const { // return inner position where a toolbox could be placed - Point aPt( 1, 1 + (mbGripAtBottom ? 0 : GetDragRect().getHeight()) ); // grip + border + Point aPt( 1, 1 + ((mbGripAtBottom || !hasGrip()) ? 0 : GetDragRect().getHeight()) ); // grip + border return aPt; } @@ -643,7 +660,6 @@ Point ImplPopupFloatWin::GetTearOffPosition() const void ImplPopupFloatWin::DrawBorder() { SetFillColor(); - SetLineColor( GetSettings().GetStyleSettings().GetShadowColor() ); Point aPt; Rectangle aRect( aPt, GetOutputSizePixel() ); @@ -653,9 +669,16 @@ void ImplPopupFloatWin::DrawBorder() if( !aItemClipRect.IsEmpty() ) { aItemClipRect.SetPos( AbsoluteScreenToOutputPixel( aItemClipRect.TopLeft() ) ); + + // draw the excluded border part with the background color of a toolbox + SetClipRegion( Region( aItemClipRect ) ); + SetLineColor( GetSettings().GetStyleSettings().GetFaceColor() ); + DrawRect( aRect ); + aClipRgn.Exclude( aItemClipRect ); SetClipRegion( aClipRgn ); } + SetLineColor( GetSettings().GetStyleSettings().GetShadowColor() ); DrawRect( aRect ); SetClipRegion( oldClipRgn ); } @@ -751,7 +774,8 @@ void ImplPopupFloatWin::Paint( const Rectangle& ) Rectangle aRect( aPt, GetOutputSizePixel() ); DrawWallpaper( aRect, Wallpaper( GetSettings().GetStyleSettings().GetFaceGradientColor() ) ); DrawBorder(); - DrawGrip(); + if( hasGrip() ) + DrawGrip(); } void ImplPopupFloatWin::MouseMove( const MouseEvent& rMEvt ) @@ -1220,7 +1244,7 @@ BOOL ImplDockingWindowWrapper::IsTitleButtonVisible( USHORT nButton ) const // ----------------------------------------------------------------------- -void ImplDockingWindowWrapper::StartPopupMode( ToolBox *pParentToolBox ) +void ImplDockingWindowWrapper::StartPopupMode( ToolBox *pParentToolBox, ULONG nFlags ) { // do nothing if window is floating if( IsFloatingMode() ) @@ -1235,7 +1259,7 @@ void ImplDockingWindowWrapper::StartPopupMode( ToolBox *pParentToolBox ) mpOldBorderWin = NULL; // no border window found // the new parent for popup mode - ImplPopupFloatWin* pWin = new ImplPopupFloatWin( mpParent, this ); + ImplPopupFloatWin* pWin = new ImplPopupFloatWin( mpParent, this, (nFlags & FLOATWIN_POPUPMODE_ALLOWTEAROFF) != 0 ); pWin->SetPopupModeEndHdl( LINK( this, ImplDockingWindowWrapper, PopupModeEnd ) ); pWin->SetText( GetWindow()->GetText() ); @@ -1265,12 +1289,6 @@ void ImplDockingWindowWrapper::StartPopupMode( ToolBox *pParentToolBox ) // (SetPosPixel etc. check for valid mpFloatWin pointer) mpFloatWin = pWin; - ULONG nFlags = FLOATWIN_POPUPMODE_ALLOWTEAROFF | - FLOATWIN_POPUPMODE_NOFOCUSCLOSE | - FLOATWIN_POPUPMODE_ALLMOUSEBUTTONCLOSE | - FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE; -// |FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE; - // if the subtoolbar was opened via keyboard make sure that key events // will go into subtoolbar if( pParentToolBox->IsKeyEvent() ) From d701c3f7c839d146790c1f63d705330a1668ab01 Mon Sep 17 00:00:00 2001 From: Christian Lippka Date: Thu, 11 Mar 2010 18:18:08 +0100 Subject: [PATCH 05/18] moved toolbarmenu to svtools and reworked to non sfx2 code --- svtools/inc/svtools/popupwindowcontroller.hxx | 83 + svtools/inc/svtools/toolbarmenu.hxx | 153 ++ svtools/inc/svtools/toolboxcontroller.hxx | 4 + svtools/inc/svtools/valueset.hxx | 3 + svtools/source/control/makefile.mk | 10 +- svtools/source/control/toolbarmenu.cxx | 1652 +++++++++++++++++ svtools/source/control/toolbarmenuacc.cxx | 956 ++++++++++ svtools/source/control/toolbarmenuimp.hxx | 307 +++ svtools/source/control/valueimp.hxx | 1 + svtools/source/control/valueset.cxx | 28 +- svtools/source/uno/makefile.mk | 9 +- svtools/source/uno/popupwindowcontroller.cxx | 215 +++ svtools/source/uno/toolboxcontroller.cxx | 21 + 13 files changed, 3426 insertions(+), 16 deletions(-) create mode 100644 svtools/inc/svtools/popupwindowcontroller.hxx create mode 100644 svtools/inc/svtools/toolbarmenu.hxx create mode 100644 svtools/source/control/toolbarmenu.cxx create mode 100644 svtools/source/control/toolbarmenuacc.cxx create mode 100644 svtools/source/control/toolbarmenuimp.hxx create mode 100644 svtools/source/uno/popupwindowcontroller.cxx diff --git a/svtools/inc/svtools/popupwindowcontroller.hxx b/svtools/inc/svtools/popupwindowcontroller.hxx new file mode 100644 index 000000000000..e9f586724bc4 --- /dev/null +++ b/svtools/inc/svtools/popupwindowcontroller.hxx @@ -0,0 +1,83 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef __SVTOOLS_POPUPWINDOWCONTROLLER_HXX_ +#define __SVTOOLS_POPUPWINDOWCONTROLLER_HXX_ + +#include "svtools/svtdllapi.h" + +#include + +#include "svtools/toolboxcontroller.hxx" +#include "boost/scoped_ptr.hpp" + +class Window; + +namespace svt +{ +class PopupWindowControllerImpl; + +class SVT_DLLPUBLIC PopupWindowController : public svt::ToolboxController, public ::com::sun::star::lang::XServiceInfo +{ +public: + PopupWindowController( const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& rServiceManager, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame, + const rtl::OUString& aCommandURL ); + ~PopupWindowController(); + + virtual ::Window* createPopupWindow( ::Window* pParent ) = 0; + + // XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type& aType ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw (); + virtual void SAL_CALL release() throw (); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() throw( ::com::sun::star::uno::RuntimeException ) = 0; + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw( ::com::sun::star::uno::RuntimeException ) = 0; + + // XComponent + virtual void SAL_CALL dispose() throw (::com::sun::star::uno::RuntimeException); + + // XStatusListener + virtual void SAL_CALL statusChanged( const ::com::sun::star::frame::FeatureStateEvent& Event ) throw ( ::com::sun::star::uno::RuntimeException ); + + // XToolbarController + virtual void SAL_CALL execute( sal_Int16 KeyModifier ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL click() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL doubleClick() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > SAL_CALL createPopupWindow() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > SAL_CALL createItemWindow( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow >& Parent ) throw (::com::sun::star::uno::RuntimeException); + +private: + boost::scoped_ptr< PopupWindowControllerImpl > mpImpl; +}; + +} // namespace svt + +#endif // __SVTOOLS_POPUPWINDOWCONTROLLER_HXX_ diff --git a/svtools/inc/svtools/toolbarmenu.hxx b/svtools/inc/svtools/toolbarmenu.hxx new file mode 100644 index 000000000000..943f714b0097 --- /dev/null +++ b/svtools/inc/svtools/toolbarmenu.hxx @@ -0,0 +1,153 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SVTOOLS_TOOLBARMENU_HXX_ +#define _SVTOOLS_TOOLBARMENU_HXX_ + +#include "svtools/svtdllapi.h" + +#include +#include +#include + +#include + +#include + +#include +#include +#include + +class ValueSet; + +namespace svtools { + +class ToolbarMenuEntry; +struct ToolbarMenu_Impl; + +class SVT_DLLPUBLIC ToolbarMenu : public DockingWindow +{ + friend class ToolbarMenuStatusListener; + friend struct ToolbarMenu_Impl; +public: + ToolbarMenu( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame, + Window* pParentWindow, + WinBits nBits ); + + ToolbarMenu( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame, + Window* pParentWindow, + const ResId& rResId ); + + ~ToolbarMenu(); + + virtual void MouseMove( const MouseEvent& rMEvt ); + virtual void MouseButtonDown( const MouseEvent& rMEvt ); + virtual void MouseButtonUp( const MouseEvent& rMEvt ); + virtual void KeyInput( const KeyEvent& rKEvent ); + virtual void Command( const CommandEvent& rCEvt ); + virtual void Paint( const Rectangle& rRect ); + virtual void RequestHelp( const HelpEvent& rHEvt ); + virtual void GetFocus(); + virtual void LoseFocus(); + + void appendEntry( int nEntryId, const String& rStr, MenuItemBits nItemBits = 0 ); + void appendEntry( int nEntryId, const Image& rImage, MenuItemBits nItemBits = 0 ); + void appendEntry( int nEntryId, const String& rStr, const Image& rImage, MenuItemBits nItemBits = 0 ); + void appendEntry( int nEntryId, Control* pControl, MenuItemBits nItemBits = 0 ); + void appendSeparator(); + + /** creates an empty ValueSet that is initialized and can be inserted with appendEntry. */ + ValueSet* createEmptyValueSetControl(); + + void checkEntry( int nEntryId, bool bCheck = true ); + bool isEntryChecked( int nEntryId ) const; + + void enableEntry( int nEntryId, bool bEnable = true ); + bool isEntryEnabled( int nEntryId ) const; + + void setEntryText( int nEntryId, const String& rStr ); + const String& getEntryText( int nEntryId ) const; + + void setEntryImage( int nEntryId, const Image& rImage ); + const Image& getEntryImage( int nEntryId ) const; + + const Size& getMenuSize() const; + + void SetSelectHdl( const Link& rLink ); + const Link& GetSelectHdl() const; + + int getSelectedEntryId() const; + int getHighlightedEntryId() const; + +protected: + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible(); + + // todo: move to new base class that will replace SfxPopupWindow + void AddStatusListener( const rtl::OUString& rCommandURL ); + void RemoveStatusListener( const rtl::OUString& rCommandURL ); + void UpdateStatus( const rtl::OUString& rCommandURL ); + + bool IsInPopupMode(); + void EndPopupMode(); + + // XStatusListener (subclasses must override this one to get the status updates + virtual void SAL_CALL statusChanged( const ::com::sun::star::frame::FeatureStateEvent& Event ) throw ( ::com::sun::star::uno::RuntimeException ); + + void StateChanged( StateChangedType nType ); + void DataChanged( const DataChangedEvent& rDCEvt ); + + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > GetFrame() const; +private: + DECL_LINK( HighlightHdl, Control * ); + + void initStatusListener(); + + void implInit( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame ); + void initWindow(); + + Size implCalcSize(); + + void appendEntry( ToolbarMenuEntry* pEntry ); + + void implPaint( ToolbarMenuEntry* pThisOnly = NULL, bool bHighlight = false ); + + void implHighlightEntry( int nHighlightEntry, bool bHighlight ); + void implHighlightEntry( const MouseEvent& rMEvt, bool bMBDown ); + + void implChangeHighlightEntry( int nEntry ); + void implSelectEntry( int nSelectedEntry ); + + ToolbarMenuEntry* implCursorUpDown( bool bUp, bool bHomeEnd ); + ToolbarMenuEntry* implGetEntry( int nEntry ) const; + ToolbarMenuEntry* implSearchEntry( int nEntryId ) const; + + ToolbarMenu_Impl* mpImpl; +}; + +} // namespace svtools + +#endif diff --git a/svtools/inc/svtools/toolboxcontroller.hxx b/svtools/inc/svtools/toolboxcontroller.hxx index 740c6999f909..2253d6bf0806 100644 --- a/svtools/inc/svtools/toolboxcontroller.hxx +++ b/svtools/inc/svtools/toolboxcontroller.hxx @@ -106,6 +106,10 @@ class SVT_DLLPUBLIC ToolboxController : public ::com::sun::star::frame::XStatusL virtual ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > SAL_CALL createPopupWindow() throw (::com::sun::star::uno::RuntimeException); virtual ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > SAL_CALL createItemWindow( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow >& Parent ) throw (::com::sun::star::uno::RuntimeException); + const rtl::OUString& getCommandURL() const { return m_aCommandURL; } + + void dispatchCommand( const ::rtl::OUString& sCommandURL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rArgs ); + protected: struct Listener { diff --git a/svtools/inc/svtools/valueset.hxx b/svtools/inc/svtools/valueset.hxx index fc12f9517b6d..7beffc5eb34a 100644 --- a/svtools/inc/svtools/valueset.hxx +++ b/svtools/inc/svtools/valueset.hxx @@ -429,6 +429,9 @@ public: void SetDoubleClickHdl( const Link& rLink ) { maDoubleClickHdl = rLink; } const Link& GetDoubleClickHdl() const { return maDoubleClickHdl; } + void SetHighlightHdl( const Link& rLink ); + const Link& GetHighlightHdl() const; + private: /** Determine whether RTL (right to left writing) is active. For this method to return two conditions have to be fullfilled: diff --git a/svtools/source/control/makefile.mk b/svtools/source/control/makefile.mk index eecf983ab756..08764b3f60af 100644 --- a/svtools/source/control/makefile.mk +++ b/svtools/source/control/makefile.mk @@ -2,14 +2,10 @@ # # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # -# Copyright 2008 by Sun Microsystems, Inc. +# Copyright 2000, 2010 Oracle and/or its affiliates. # # OpenOffice.org - a multi-platform office productivity suite # -# $RCSfile: makefile.mk,v $ -# -# $Revision: 1.19 $ -# # This file is part of OpenOffice.org. # # OpenOffice.org is free software: you can redistribute it and/or modify @@ -54,7 +50,9 @@ EXCEPTIONSFILES=\ $(SLO)$/scriptedtext.obj\ $(SLO)$/fmtfield.obj \ $(SLO)$/inettbc.obj \ - $(SLO)$/valueacc.obj + $(SLO)$/valueacc.obj \ + $(SLO)$/toolbarmenu.obj \ + $(SLO)$/toolbarmenuacc.obj SLOFILES=\ $(EXCEPTIONSFILES) \ diff --git a/svtools/source/control/toolbarmenu.cxx b/svtools/source/control/toolbarmenu.cxx new file mode 100644 index 000000000000..a16f60bc5822 --- /dev/null +++ b/svtools/source/control/toolbarmenu.cxx @@ -0,0 +1,1652 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svtools.hxx" + +#include +#include + +#include +#include +#include +#include + +#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 their 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; + mbHasControl = 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( 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(); +} + +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; + } +} + +// -------------------------------------------------------------------- + +IMPL_LINK( ToolbarMenu, HighlightHdl, Control *, pControl ) +{ + (void)pControl; + if( mpImpl->hasAccessibleListeners() ) + mpImpl->fireAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() ); + 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 ); + + 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(); + + SetControlBackground( GetSettings().GetStyleSettings().GetFaceGradientColor() ); + + 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; + sal_Bool bCheckable = sal_False; + + const int nEntryCount = mpImpl->maEntryVector.size(); + int nEntry; + + const StyleSettings& rSettings = GetSettings().GetStyleSettings(); + if ( rSettings.GetUseImagesInMenus() ) + { + nMinMenuItemHeight = 16; + + for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) + { + ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry]; + if( pEntry && pEntry->mbHasImage ) + { + Size aImgSz = pEntry->maImage.GetSizePixel(); + if ( aImgSz.Height() > aMaxImgSz.Height() ) + aMaxImgSz.Height() = aImgSz.Height(); + if ( aImgSz.Height() > nMinMenuItemHeight ) + nMinMenuItemHeight = aImgSz.Height(); + break; + } + } + } + + for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) + { + ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry]; + + if( pEntry ) + { + pEntry->maSize.Height() = 0; + pEntry->maSize.Width() = 0; + + + if ( ( pEntry->mnBits ) & ( MIB_RADIOCHECK | MIB_CHECKABLE ) ) + bCheckable = sal_True; + + // Image: + if( pEntry->mbHasImage ) + { + Size aImgSz = pEntry->maImage.GetSizePixel(); + if ( (aImgSz.Width() + 4) > aMaxImgSz.Width() ) + aMaxImgSz.Width() = aImgSz.Width() + 4; + if ( (aImgSz.Height() + 4) > aMaxImgSz.Height() ) + aMaxImgSz.Height() = aImgSz.Height() + 4; + if ( (aImgSz.Height() + 4) > pEntry->maSize.Height() ) + pEntry->maSize.Height() = aImgSz.Height() + 4; + } + } + } + + int gfxExtra = Max( nExtra, 7L ); + + if ( aMaxImgSz.Width() ) + mpImpl->mnTextPos += gfxExtra; + if ( bCheckable ) + mpImpl->mnTextPos += 16; + + mpImpl->mnCheckPos = nExtra; + mpImpl->mnImagePos = nExtra; + mpImpl->mnTextPos = mpImpl->mnImagePos + aMaxImgSz.Width(); + + for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) + { + ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry]; + + if( pEntry ) + { + // Text: + if( pEntry->mbHasText ) + { + long nTextWidth = GetCtrlTextWidth( pEntry->maText ) + mpImpl->mnTextPos; + nMaxTextWidth = Max( nTextWidth, nMaxTextWidth ); + + pEntry->maSize.Height() = Max( Max( GetTextHeight(), pEntry->maSize.Height() ), nMinMenuItemHeight ); + } + // Control: + else if( pEntry->mpControl ) + { + Size aControlSize( pEntry->mpControl->GetOutputSizePixel() ); + + nMaxTextWidth = Max( aControlSize.Width(), nMaxTextWidth ); + pEntry->maSize.Height() = Max( aControlSize.Height(), pEntry->maSize.Height() ) + 1; + } + aSz.Height() += pEntry->maSize.Height(); + } + else + { + aSz.Height() += SEPARATOR_HEIGHT; + } + } + + aSz.Width() = nMaxTextWidth + (BORDER_X<<1); + aSz.Height() += BORDER_Y<<1; + + // positionate controls + int nY = BORDER_Y; + for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) + { + ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry]; + + if( pEntry ) + { + if( pEntry->mpControl ) + { + Size aControlSize( pEntry->mpControl->GetOutputSizePixel() ); + Point aControlPos( (aSz.Width() - aControlSize.Width())>>1, nY); + if( pEntry->mbHasText ) + aControlPos.X() += GetCtrlTextWidth( pEntry->maText ) + 4*gfxExtra; + + 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; + } + } + + return aSz; +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::GetFocus() +{ + if( mpImpl->mnHighlightedEntry == -1 ) + implChangeHighlightEntry( 0 ); + + DockingWindow::GetFocus(); + + // Tell the accessible object that we got the focus. + if( mpImpl->mxAccessible.is() ) + mpImpl->mxAccessible->GetFocus(); +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::LoseFocus() +{ + if( mpImpl->mnHighlightedEntry != -1 ) + implChangeHighlightEntry( -1 ); + + DockingWindow::LoseFocus(); + + // Tell the accessible object that we lost the focus. + if( mpImpl->mxAccessible.is() ) + mpImpl->mxAccessible->LoseFocus(); +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::appendEntry( int nEntryId, const String& rStr, MenuItemBits nItemBits ) +{ + appendEntry( new ToolbarMenuEntry( *this, nEntryId, rStr, nItemBits ) ); +} + + +#if 0 +todo acc selectentry? + if( ImplHasAccessibleListeners() ) + { + // focus event (deselect) + if( nOldItem ) + { + const USHORT nPos = GetItemPos( nItemId ); + + if( nPos != VALUESET_ITEM_NOTFOUND ) + { + ValueItemAcc* pItemAcc = ValueItemAcc::getImplementation( + mpImpl->mpItemList->GetObject( nPos )->GetAccessible( mpImpl->mbIsTransientChildrenDisabled ) ); + + if( pItemAcc ) + { + ::com::sun::star::uno::Any aOldAny, aNewAny; + if( !mpImpl->mbIsTransientChildrenDisabled) + { + aOldAny <<= ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >( + static_cast< ::cppu::OWeakObject* >( pItemAcc )); + ImplFireAccessibleEvent (::com::sun::star::accessibility::AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldAny, aNewAny ); + } + else + { + aOldAny <<= ::com::sun::star::accessibility::AccessibleStateType::FOCUSED; + pItemAcc->FireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::STATE_CHANGED, aOldAny, aNewAny ); + } + } + } + } + + // focus event (select) + const USHORT nPos = GetItemPos( mnSelItemId ); + + ValueSetItem* pItem; + if( nPos != VALUESET_ITEM_NOTFOUND ) + pItem = mpImpl->mpItemList->GetObject(nPos); + else + pItem = mpNoneItem; + + ValueItemAcc* pItemAcc = NULL; + if (pItem != NULL) + pItemAcc = ValueItemAcc::getImplementation(pItem->GetAccessible( mpImpl->mbIsTransientChildrenDisabled ) ); + + if( pItemAcc ) + { + ::com::sun::star::uno::Any aOldAny, aNewAny; + if( !mpImpl->mbIsTransientChildrenDisabled) + { + aNewAny <<= ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >( + static_cast< ::cppu::OWeakObject* >( pItemAcc )); + ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldAny, aNewAny ); + } + else + { + aNewAny <<= ::com::sun::star::accessibility::AccessibleStateType::FOCUSED; + pItemAcc->FireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::STATE_CHANGED, aOldAny, aNewAny ); + } + } + + // selection event + ::com::sun::star::uno::Any aOldAny, aNewAny; + ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::SELECTION_CHANGED, aOldAny, aNewAny ); + } + } +} + +#endif + +// -------------------------------------------------------------------- + +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( FALSE ); + pSet->SetColor( GetControlBackground() ); + pSet->SetHighlightHdl( LINK( this, ToolbarMenu, HighlightHdl ) ); + return pSet; +} + +// -------------------------------------------------------------------- + +ToolbarMenuEntry* ToolbarMenu::implGetEntry( int nEntry ) const +{ + if( (nEntry < 0) || (nEntry >= (int)mpImpl->maEntryVector.size() ) ) + return NULL; + + return mpImpl->maEntryVector[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; +} + +// -------------------------------------------------------------------- + +static void implDeselectControl( Control* pControl ) +{ + ValueSet* pValueSet = dynamic_cast< ValueSet* >( pControl ); + if( pValueSet ) + { + pValueSet->SetNoSelection(); + pValueSet->Invalidate(); + } +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::implHighlightEntry( int nHighlightEntry, bool bHighlight ) +{ + Size aSz = GetOutputSizePixel(); + long nY = BORDER_Y; + long nX = BORDER_X; + + const int nEntryCount = mpImpl->maEntryVector.size(); + int nEntry; + for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) + { + ToolbarMenuEntry* p = mpImpl->maEntryVector[nEntry]; + if( p ) + { + if(nEntry == nHighlightEntry) + { + if( p->mpControl == NULL ) + { + Rectangle aRect( Point( nX, nY ), Size( aSz.Width()-(BORDER_X<<1), p->maSize.Height() ) ); + SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() ); + SetLineColor(); + DrawRect( aRect ); + + if( bHighlight ) + { + aRect.nLeft += 1; + aRect.nTop += 1; + aRect.nBottom -= 1; + aRect.nRight -= 1; + DrawSelectionBackground( aRect, true, false, TRUE, TRUE ); + } + } + else + { + if( !bHighlight ) + implDeselectControl( p->mpControl ); + } + + implPaint( p, bHighlight ); + break; + } + + nY += p->maSize.Height(); + } + else + { + nY += 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 = 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 ); + } + + if( mpImpl->hasAccessibleListeners() ) + mpImpl->fireAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() ); +} + +// -------------------------------------------------------------------- + +static bool implCheckSubControlCursorMove( Control* pControl, bool bUp, int& nLastColumn ) +{ + ValueSet* pValueSet = dynamic_cast< ValueSet* >( pControl ); + if( pValueSet ) + { + USHORT nItemPos = pValueSet->GetItemPos( pValueSet->GetSelectItemId() ); + if( nItemPos != VALUESET_ITEM_NOTFOUND ) + { + const USHORT nColCount = pValueSet->GetColCount(); + const USHORT nLine = nItemPos / nColCount; + + nLastColumn = nItemPos - (nLine * nColCount); + + if( bUp ) + { + return nLine > 0; + } + else + { + const USHORT 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; +} + +// -------------------------------------------------------------------- + +static void implHighlightControl( USHORT nCode, Control* pControl, int nLastColumn ) +{ + ValueSet* pValueSet = dynamic_cast< ValueSet* >( pControl ); + if( pValueSet ) + { + const USHORT nItemCount = pValueSet->GetItemCount(); + USHORT nItemPos = VALUESET_ITEM_NOTFOUND; + switch( nCode ) + { + case KEY_UP: + { + const USHORT nColCount = pValueSet->GetColCount(); + const USHORT nLastLine = nItemCount / nColCount; + nItemPos = std::min( ((nLastLine-1) * nColCount) + nLastColumn, nItemCount-1 ); + break; + } + case KEY_DOWN: + nItemPos = std::min( nLastColumn, nItemCount-1 ); + break; + case KEY_END: + nItemPos = nItemCount -1; + break; + case KEY_HOME: + nItemPos = 0; + break; + } + pValueSet->SelectItem( pValueSet->GetItemId( nItemPos ) ); + } +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::KeyInput( const KeyEvent& rKEvent ) +{ + Control* pForwardControl = 0; + USHORT 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 ) + { + implHighlightControl( nCode, p->mpControl, mpImpl->mnLastColumn ); + } + 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 ) + { + implHighlightControl( nCode, p->mpControl, mpImpl->mnLastColumn ); + } + } + 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 ); + +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::implPaint( ToolbarMenuEntry* pThisOnly, bool bHighlighted ) +{ + const long nFontHeight = GetTextHeight(); + const long nExtra = nFontHeight/4; + + DecorationView aDecoView( this ); + const StyleSettings& rSettings = GetSettings().GetStyleSettings(); + + const Size aOutSz( GetOutputSizePixel() ); + + Point aTopLeft( BORDER_X, BORDER_Y ), aTmpPos; + + const int nEntryCount = mpImpl->maEntryVector.size(); + int nEntry; + for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) + { + ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry]; + Point aPos( aTopLeft ); + + USHORT nTextStyle = 0; + USHORT nSymbolStyle = 0; + USHORT nImageStyle = 0; + if( pEntry && !pEntry->mbEnabled ) + { + nTextStyle |= TEXT_DRAW_DISABLE; + nSymbolStyle |= SYMBOL_DRAW_DISABLE; + nImageStyle |= IMAGE_DRAW_DISABLE; + } + + // Separator + if( pEntry == NULL ) + { + if( pThisOnly == NULL ) + { + aTmpPos.Y() = aPos.Y() + ((SEPARATOR_HEIGHT-2)/2); + + SetLineColor( rSettings.GetShadowColor() ); + DrawLine( aTmpPos, Point( aOutSz.Width() - 3, aTmpPos.Y() ) ); + aTmpPos.Y()++; + SetLineColor( rSettings.GetLightColor() ); + DrawLine( aTmpPos, Point( aOutSz.Width() - 3, aTmpPos.Y() ) ); + SetLineColor(); + } + + aTopLeft.Y() += SEPARATOR_HEIGHT; + } + else + { + if( !pThisOnly || ( pEntry == pThisOnly ) ) + { + const bool bTitle = pEntry->mnEntryId == TITLE_ID; + + if( pThisOnly && bHighlighted ) + SetTextColor( rSettings.GetMenuHighlightTextColor() ); + else + SetTextColor( rSettings.GetMenuTextColor() ); + + Rectangle aRect( aTopLeft, Size( aOutSz.Width(), pEntry->maSize.Height() ) ); + if( bTitle ) + { + // fill the background + SetFillColor(rSettings.GetDialogColor()); + SetLineColor(); + DrawRect(aRect); + SetLineColor( rSettings.GetLightColor() ); + DrawLine( aRect.TopLeft(), aRect.TopRight() ); + SetLineColor( rSettings.GetShadowColor() ); + DrawLine( aRect.BottomLeft(), aRect.BottomRight() ); + } + else if( pEntry->mpControl ) + { + SetLineColor( rSettings.GetShadowColor() ); + DrawLine( aRect.BottomLeft(), aRect.BottomRight() ); + } + + long nTextOffsetY = ((pEntry->maSize.Height()-nFontHeight)/2); + + // Image + if( pEntry->mbHasImage ) + { + aTmpPos.X() = aPos.X() + mpImpl->mnImagePos; + aTmpPos.Y() = aPos.Y(); + aTmpPos.Y() += (pEntry->maSize.Height()-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; + USHORT nStyle = nTextStyle|TEXT_DRAW_MNEMONIC; + + DrawCtrlText( aTmpPos, pEntry->maText, 0, pEntry->maText.Len(), nStyle ); + } + + // CheckMark + if( pEntry->mbChecked ) + { + if( pEntry->mbHasImage ) + { + aTmpPos.X() = aPos.X() + mpImpl->mnImagePos; + aTmpPos.Y() = aPos.Y(); + aTmpPos.Y() += (pEntry->maSize.Height()-pEntry->maImage.GetSizePixel().Height())/2; + + Rectangle aSelRect( aTmpPos, pEntry->maImage.GetSizePixel() ); + aSelRect.nLeft -= 2; + aSelRect.nTop -= 2; + aSelRect.nRight += 2; + aSelRect.nBottom += 2; + DrawSelectionBackground( aSelRect, false, true, TRUE, TRUE ); + } + else + { + Rectangle aSelRect; + SymbolType eSymbol; + aTmpPos.Y() = aPos.Y(); + aTmpPos.Y() += nExtra/2; + aTmpPos.Y() += pEntry->maSize.Height() / 2; + if ( pEntry->mnBits & MIB_RADIOCHECK ) + { + aTmpPos.X() = aPos.X() + mpImpl->mnCheckPos; + eSymbol = SYMBOL_RADIOCHECKMARK; + aTmpPos.Y() -= nFontHeight/4; + aSelRect = Rectangle( aTmpPos, Size( nFontHeight/2, nFontHeight/2 ) ); + } + else + { + aTmpPos.X() = aPos.X() + mpImpl->mnCheckPos; + eSymbol = SYMBOL_CHECKMARK; + aTmpPos.Y() -= nFontHeight/4; + aSelRect = Rectangle( aTmpPos, Size( (nFontHeight*25)/40, nFontHeight/2 ) ); + } + aDecoView.DrawSymbol( aSelRect, eSymbol, GetTextColor(), nSymbolStyle ); + } + } + } + + aTopLeft.Y() += pEntry->maSize.Height(); + } + } +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::Paint( const Rectangle& ) +{ + 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; +} + +// -------------------------------------------------------------------- + + +// -------------------------------------------------------------------- + +} + + diff --git a/svtools/source/control/toolbarmenuacc.cxx b/svtools/source/control/toolbarmenuacc.cxx new file mode 100644 index 000000000000..702c1f72b83d --- /dev/null +++ b/svtools/source/control/toolbarmenuacc.cxx @@ -0,0 +1,956 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svtools.hxx" + +#include +#include +#include + +#include + +#include + +#include "svtools/toolbarmenu.hxx" + +#include "toolbarmenuimp.hxx" + +using ::rtl::OUString; + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::accessibility; + +namespace svtools { + +// ------------------ +// - ToolbarMenuAcc - +// ------------------ + +ToolbarMenuAcc::ToolbarMenuAcc( ToolbarMenu_Impl& rParent ) +: ToolbarMenuAccComponentBase(m_aMutex) +, mpParent( &rParent ) +, mbIsFocused(false) +{ +} + +// ----------------------------------------------------------------------------- + +ToolbarMenuAcc::~ToolbarMenuAcc() +{ +} + +// ----------------------------------------------------------------------- + +void ToolbarMenuAcc::FireAccessibleEvent( short nEventId, const Any& rOldValue, const Any& rNewValue ) +{ + if( nEventId ) + { + EventListenerVector aTmpListeners( mxEventListeners ); + EventListenerVector::const_iterator aIter( aTmpListeners.begin() ); + AccessibleEventObject aEvtObject; + + aEvtObject.EventId = nEventId; + aEvtObject.Source = static_cast(this); + aEvtObject.NewValue = rNewValue; + aEvtObject.OldValue = rOldValue; + + while( aIter != aTmpListeners.end() ) + { + try + { + (*aIter)->notifyEvent( aEvtObject ); + } + catch( Exception& ) + { + } + + aIter++; + } + } +} + +// ----------------------------------------------------------------------------- + +void ToolbarMenuAcc::GetFocus (void) +{ + mbIsFocused = true; + FireAccessibleEvent( AccessibleEventId::STATE_CHANGED, Any(), Any( AccessibleStateType::FOCUSED ) ); +} + +// ----------------------------------------------------------------------------- + +void ToolbarMenuAcc::LoseFocus (void) +{ + mbIsFocused = false; + FireAccessibleEvent( AccessibleEventId::STATE_CHANGED, Any( AccessibleStateType::FOCUSED ), Any() ); +} + +// ----------------------------------------------------------------------------- + +Reference< XAccessibleContext > SAL_CALL ToolbarMenuAcc::getAccessibleContext() throw (RuntimeException) +{ + ThrowIfDisposed(); + return this; +} + +// ----------------------------------------------------------------------------- + +sal_Int32 SAL_CALL ToolbarMenuAcc::getAccessibleChildCount() throw (RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ThrowIfDisposed(); + + return mpParent->getAccessibleChildCount(); +} + +// ----------------------------------------------------------------------------- + +Reference< XAccessible > SAL_CALL ToolbarMenuAcc::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException, RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ThrowIfDisposed(); + + return mpParent->getAccessibleChild(i); +} + +// ----------------------------------------------------------------------------- + +Reference< XAccessible > SAL_CALL ToolbarMenuAcc::getAccessibleParent() throw (RuntimeException) +{ + ThrowIfDisposed(); + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + + Reference< XAccessible > xRet; + + Window* pParent = mpParent->mrMenu.GetParent(); + if( pParent ) + xRet = pParent->GetAccessible(); + + return xRet; +} + +// ----------------------------------------------------------------------------- + +sal_Int32 SAL_CALL ToolbarMenuAcc::getAccessibleIndexInParent() throw (RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ThrowIfDisposed(); + + Window* pParent = mpParent->mrMenu.GetParent(); + if( pParent ) + { + for( USHORT i = 0, nCount = pParent->GetChildCount(); i < nCount ; i++ ) + { + if( pParent->GetChild( i ) == &mpParent->mrMenu ) + return i; + } + } + + return 0; +} + +// ----------------------------------------------------------------------------- + +sal_Int16 SAL_CALL ToolbarMenuAcc::getAccessibleRole() throw (RuntimeException) +{ + ThrowIfDisposed(); + return AccessibleRole::LIST; +} + +// ----------------------------------------------------------------------------- + +OUString SAL_CALL ToolbarMenuAcc::getAccessibleDescription() throw (RuntimeException) +{ + ThrowIfDisposed(); + return OUString( RTL_CONSTASCII_USTRINGPARAM( "ToolbarMenu" ) ); +} + +// ----------------------------------------------------------------------------- + +OUString SAL_CALL ToolbarMenuAcc::getAccessibleName() throw (RuntimeException) +{ + ThrowIfDisposed(); + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + OUString aRet; + + if( mpParent ) + aRet = mpParent->mrMenu.GetAccessibleName(); + + if( !aRet.getLength() ) + { + Window* pLabel = mpParent->mrMenu.GetLabeledBy(); + if( pLabel && pLabel != &mpParent->mrMenu ) + aRet = OutputDevice::GetNonMnemonicString( pLabel->GetText() ); + } + + return aRet; +} + +// ----------------------------------------------------------------------------- + +Reference< XAccessibleRelationSet > SAL_CALL ToolbarMenuAcc::getAccessibleRelationSet() throw (RuntimeException) +{ + ThrowIfDisposed(); + return Reference< XAccessibleRelationSet >(); +} + +// ----------------------------------------------------------------------------- + +Reference< XAccessibleStateSet > SAL_CALL ToolbarMenuAcc::getAccessibleStateSet() throw (RuntimeException) +{ + ThrowIfDisposed(); + ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper(); + + // Set some states. + pStateSet->AddState (AccessibleStateType::ENABLED); + pStateSet->AddState (AccessibleStateType::SENSITIVE); + pStateSet->AddState (AccessibleStateType::SHOWING); + pStateSet->AddState (AccessibleStateType::VISIBLE); + pStateSet->AddState (AccessibleStateType::MANAGES_DESCENDANTS); + pStateSet->AddState (AccessibleStateType::FOCUSABLE); + if (mbIsFocused) + pStateSet->AddState (AccessibleStateType::FOCUSED); + + return pStateSet; +} + +// ----------------------------------------------------------------------------- + +Locale SAL_CALL ToolbarMenuAcc::getLocale() throw (IllegalAccessibleComponentStateException, RuntimeException) +{ + ThrowIfDisposed(); + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + const ::rtl::OUString aEmptyStr; + Reference< XAccessible > xParent( getAccessibleParent() ); + Locale aRet( aEmptyStr, aEmptyStr, aEmptyStr ); + + if( xParent.is() ) + { + Reference< XAccessibleContext > xParentContext( xParent->getAccessibleContext() ); + + if( xParentContext.is() ) + aRet = xParentContext->getLocale (); + } + + return aRet; +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuAcc::addEventListener( const Reference< XAccessibleEventListener >& rxListener ) throw (RuntimeException) +{ + ThrowIfDisposed(); + ::osl::MutexGuard aGuard(m_aMutex); + + if( rxListener.is() ) + { + EventListenerVector::const_iterator aIter = mxEventListeners.begin(); + bool bFound = false; + + while( !bFound && ( aIter != mxEventListeners.end() ) ) + { + if( *aIter == rxListener ) + bFound = true; + else + aIter++; + } + + if (!bFound) + mxEventListeners.push_back( rxListener ); + } +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuAcc::removeEventListener( const Reference< XAccessibleEventListener >& rxListener ) throw (RuntimeException) +{ + ThrowIfDisposed(); + ::osl::MutexGuard aGuard(m_aMutex); + + if( rxListener.is() ) + { + EventListenerVector::iterator aIter = mxEventListeners.begin(); + bool bFound = false; + + while( !bFound && ( aIter != mxEventListeners.end() ) ) + { + if( *aIter == rxListener ) + { + mxEventListeners.erase( aIter ); + bFound = true; + } + else + aIter++; + } + } +} + +// ----------------------------------------------------------------------------- + +sal_Bool SAL_CALL ToolbarMenuAcc::containsPoint( const awt::Point& aPoint ) throw (RuntimeException) +{ + ThrowIfDisposed(); + const awt::Rectangle aRect( getBounds() ); + const Point aSize( aRect.Width, aRect.Height ); + const Point aNullPoint, aTestPoint( aPoint.X, aPoint.Y ); + + return Rectangle( aNullPoint, aSize ).IsInside( aTestPoint ); +} + +// ----------------------------------------------------------------------------- + +Reference< XAccessible > SAL_CALL ToolbarMenuAcc::getAccessibleAtPoint( const awt::Point& aPoint ) throw (RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ThrowIfDisposed(); + + Reference< XAccessible > xRet; + + const Point aVclPoint( aPoint.X, aPoint.Y ); + + const int nEntryCount = mpParent->maEntryVector.size(); + for( int nEntry = 0; (nEntry < nEntryCount) && !xRet.is(); nEntry++ ) + { + ToolbarMenuEntry* pEntry = mpParent->maEntryVector[nEntry]; + if( pEntry && pEntry->maRect.IsInside( aVclPoint ) ) + { + if( pEntry->mpControl ) + { + awt::Point aChildPoint( aPoint.X - pEntry->maRect.Left(), aPoint.Y - pEntry->maRect.Top() ); + Reference< XAccessibleComponent > xComp( pEntry->GetAccessible(true), UNO_QUERY_THROW ); + xRet = xComp->getAccessibleAtPoint(aChildPoint); + } + else + { + xRet = Reference< XAccessible >( pEntry->GetAccessible(true), UNO_QUERY ); + } + } + } + return xRet; +} + +// ----------------------------------------------------------------------------- + +awt::Rectangle SAL_CALL ToolbarMenuAcc::getBounds() throw (RuntimeException) +{ + ThrowIfDisposed(); + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + const Point aOutPos( mpParent->mrMenu.GetPosPixel() ); + const Size aOutSize( mpParent->mrMenu.GetOutputSizePixel() ); + awt::Rectangle aRet; + + aRet.X = aOutPos.X(); + aRet.Y = aOutPos.Y(); + aRet.Width = aOutSize.Width(); + aRet.Height = aOutSize.Height(); + + return aRet; +} + +// ----------------------------------------------------------------------------- + +awt::Point SAL_CALL ToolbarMenuAcc::getLocation() throw (RuntimeException) +{ + ThrowIfDisposed(); + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + const Point aOutPos( mpParent->mrMenu.GetPosPixel() ); + return awt::Point( aOutPos.X(), aOutPos.Y() ); +} + +// ----------------------------------------------------------------------------- + +awt::Point SAL_CALL ToolbarMenuAcc::getLocationOnScreen() throw (RuntimeException) +{ + ThrowIfDisposed(); + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + const Point aScreenPos( mpParent->mrMenu.OutputToAbsoluteScreenPixel( Point() ) ); + return awt::Point( aScreenPos.X(), aScreenPos.Y() ); +} + +// ----------------------------------------------------------------------------- + +awt::Size SAL_CALL ToolbarMenuAcc::getSize() throw (RuntimeException) +{ + ThrowIfDisposed(); + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + const Size aOutSize( mpParent->mrMenu.GetOutputSizePixel() ); + return awt::Size( aOutSize.Width(), aOutSize.Height() ); +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuAcc::grabFocus() throw (RuntimeException) +{ + ThrowIfDisposed(); + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + mpParent->mrMenu.GrabFocus(); +} + +// ----------------------------------------------------------------------------- + +Any SAL_CALL ToolbarMenuAcc::getAccessibleKeyBinding() throw (RuntimeException) +{ + ThrowIfDisposed(); + return Any(); +} + +// ----------------------------------------------------------------------------- + +sal_Int32 SAL_CALL ToolbarMenuAcc::getForeground() throw (RuntimeException) +{ + ThrowIfDisposed(); + UINT32 nColor = Application::GetSettings().GetStyleSettings().GetMenuTextColor().GetColor(); + return static_cast(nColor); +} + +// ----------------------------------------------------------------------------- + +sal_Int32 SAL_CALL ToolbarMenuAcc::getBackground() throw (RuntimeException) +{ + ThrowIfDisposed(); + UINT32 nColor = Application::GetSettings().GetStyleSettings().GetMenuColor().GetColor(); + return static_cast(nColor); +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuAcc::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ThrowIfDisposed(); + + mpParent->selectAccessibleChild( nChildIndex ); +} + +// ----------------------------------------------------------------------------- + +sal_Bool SAL_CALL ToolbarMenuAcc::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ThrowIfDisposed(); + return mpParent->isAccessibleChildSelected( nChildIndex ); +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuAcc::clearAccessibleSelection() throw (RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ThrowIfDisposed(); + mpParent->clearAccessibleSelection(); +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuAcc::selectAllAccessibleChildren() throw (RuntimeException) +{ + ThrowIfDisposed(); + // unsupported due to single selection only +} + +// ----------------------------------------------------------------------------- + +sal_Int32 SAL_CALL ToolbarMenuAcc::getSelectedAccessibleChildCount() throw (RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ThrowIfDisposed(); + + return mpParent->mnHighlightedEntry != -1 ? 1 : 0; +} + +// ----------------------------------------------------------------------------- + +Reference< XAccessible > SAL_CALL ToolbarMenuAcc::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) +{ + ThrowIfDisposed(); + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + + if( (mpParent->mnHighlightedEntry != -1) && (nSelectedChildIndex == 0) ) + { + ToolbarMenuEntry* pEntry = mpParent->maEntryVector[ mpParent->mnHighlightedEntry ]; + if( pEntry ) + { + if( pEntry->mpControl ) + { + Reference< XAccessibleSelection > xSel( pEntry->GetAccessible(true), UNO_QUERY_THROW ); + return xSel->getSelectedAccessibleChild(0); + } + else + return Reference< XAccessible >( pEntry->GetAccessible(true), UNO_QUERY ); + } + } + + throw IndexOutOfBoundsException(); +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuAcc::deselectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) +{ + ThrowIfDisposed(); + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + // Because of the single selection we can reset the whole selection when + // the specified child is currently selected. + if (isAccessibleChildSelected(nChildIndex)) + mpParent->clearAccessibleSelection(); +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuAcc::disposing (void) +{ + EventListenerVector aListenerListCopy; + + { + // Make a copy of the list and clear the original. + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard (m_aMutex); + aListenerListCopy = mxEventListeners; + mxEventListeners.clear(); + + // Reset the pointer to the parent. It has to be the one who has + // disposed us because he is dying. + mpParent = NULL; + } + + // Inform all listeners that this objects is disposing. + EventListenerVector::const_iterator aListenerIterator (aListenerListCopy.begin()); + EventObject aEvent (static_cast(this)); + while(aListenerIterator != aListenerListCopy.end()) + { + try + { + (*aListenerIterator)->disposing (aEvent); + } + catch( Exception& ) + { + // Ignore exceptions. + } + + ++aListenerIterator; + } +} + +void ToolbarMenuAcc::ThrowIfDisposed (void) throw (DisposedException) +{ + if(rBHelper.bDisposed || rBHelper.bInDispose) + { + throw DisposedException ( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("object has been already disposed")), static_cast(this)); + } +} + +// ----------------------- +// - ToolbarMenuEntryAcc - +// ----------------------- + +ToolbarMenuEntryAcc::ToolbarMenuEntryAcc( ToolbarMenuEntry* pParent ) +: ToolbarMenuEntryAccBase( m_aMutex ) +, mpParent( pParent ) +{ +} + +// ----------------------------------------------------------------------------- + +ToolbarMenuEntryAcc::~ToolbarMenuEntryAcc() +{ +} + +// ----------------------------------------------------------------------- + +void ToolbarMenuEntryAcc::FireAccessibleEvent( short nEventId, const Any& rOldValue, const Any& rNewValue ) +{ + if( nEventId ) + { + EventListenerVector aTmpListeners( mxEventListeners ); + ::std::vector< Reference< XAccessibleEventListener > >::const_iterator aIter( aTmpListeners.begin() ); + AccessibleEventObject aEvtObject; + + aEvtObject.EventId = nEventId; + aEvtObject.Source = static_cast(this); + aEvtObject.NewValue = rNewValue; + aEvtObject.OldValue = rOldValue; + + while( aIter != aTmpListeners.end() ) + { + (*aIter)->notifyEvent( aEvtObject ); + aIter++; + } + } +} + + +// ----------------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuEntryAcc::disposing (void) +{ + EventListenerVector aListenerListCopy; + + { + // Make a copy of the list and clear the original. + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard (m_aMutex); + aListenerListCopy = mxEventListeners; + mxEventListeners.clear(); + + // Reset the pointer to the parent. It has to be the one who has + // disposed us because he is dying. + mpParent = NULL; + } + + // Inform all listeners that this objects is disposing. + EventListenerVector::const_iterator aListenerIterator (aListenerListCopy.begin()); + EventObject aEvent (static_cast(this)); + while(aListenerIterator != aListenerListCopy.end()) + { + try + { + (*aListenerIterator)->disposing (aEvent); + } + catch( Exception& ) + { + // Ignore exceptions. + } + + ++aListenerIterator; + } +} +// ----------------------------------------------------------------------------- + +Reference< XAccessibleContext > SAL_CALL ToolbarMenuEntryAcc::getAccessibleContext() throw (RuntimeException) +{ + return this; +} + +// ----------------------------------------------------------------------------- + +sal_Int32 SAL_CALL ToolbarMenuEntryAcc::getAccessibleChildCount() throw (RuntimeException) +{ + return 0; +} + +// ----------------------------------------------------------------------------- + +Reference< XAccessible > SAL_CALL ToolbarMenuEntryAcc::getAccessibleChild( sal_Int32 ) throw (IndexOutOfBoundsException, RuntimeException) +{ + throw IndexOutOfBoundsException(); +} + +// ----------------------------------------------------------------------------- + +Reference< XAccessible > SAL_CALL ToolbarMenuEntryAcc::getAccessibleParent() throw (RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + Reference< XAccessible > xRet; + + if( mpParent ) + xRet = mpParent->mrMenu.GetAccessible(); + + return xRet; +} + +// ----------------------------------------------------------------------------- + +sal_Int32 SAL_CALL ToolbarMenuEntryAcc::getAccessibleIndexInParent() throw (RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + // The index defaults to -1 to indicate the child does not belong to its + // parent. + sal_Int32 nIndexInParent = -1; + + if( mpParent ) + { + Reference< XAccessibleContext > xParent( mpParent->mrMenu.GetAccessible(), UNO_QUERY ); + + if( xParent.is() ) + { + Reference< XAccessible > xThis( this ); + + const sal_Int32 nCount = xParent->getAccessibleChildCount(); + for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ ) + { + if( xParent->getAccessibleChild(nIndex) == xThis ) + { + nIndexInParent = nIndex; + break; + } + } + } + } + + return nIndexInParent; +} + +// ----------------------------------------------------------------------------- + +sal_Int16 SAL_CALL ToolbarMenuEntryAcc::getAccessibleRole() throw (RuntimeException) +{ + return AccessibleRole::LIST_ITEM; +} + +// ----------------------------------------------------------------------------- + +::rtl::OUString SAL_CALL ToolbarMenuEntryAcc::getAccessibleDescription() throw (RuntimeException) +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( "ToolbarMenu item" ) ); +} + +// ----------------------------------------------------------------------------- + +::rtl::OUString SAL_CALL ToolbarMenuEntryAcc::getAccessibleName() throw (RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + String aRet; + + if( mpParent ) + { + aRet = mpParent->maText; + + if( !aRet.Len() ) + { + aRet = String( RTL_CONSTASCII_USTRINGPARAM( "Item " ) ); + aRet += String::CreateFromInt32( mpParent->mnEntryId ); + } + } + + return aRet; +} + +// ----------------------------------------------------------------------------- + +Reference< XAccessibleRelationSet > SAL_CALL ToolbarMenuEntryAcc::getAccessibleRelationSet() throw (RuntimeException) +{ + return Reference< XAccessibleRelationSet >(); +} + +// ----------------------------------------------------------------------------- + +Reference< XAccessibleStateSet > SAL_CALL ToolbarMenuEntryAcc::getAccessibleStateSet() throw (RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper; + + if( mpParent ) + { + pStateSet->AddState (AccessibleStateType::ENABLED); + pStateSet->AddState (AccessibleStateType::SENSITIVE); + pStateSet->AddState (AccessibleStateType::SHOWING); + pStateSet->AddState (AccessibleStateType::VISIBLE); + pStateSet->AddState (AccessibleStateType::TRANSIENT); + if( mpParent->mnEntryId != TITLE_ID ) + { + pStateSet->AddState( AccessibleStateType::SELECTABLE ); + + // SELECTED + if( mpParent->mrMenu.getHighlightedEntryId() == mpParent->mnEntryId ) + pStateSet->AddState( AccessibleStateType::SELECTED ); + } + } + + return pStateSet; +} + +// ----------------------------------------------------------------------------- + +Locale SAL_CALL ToolbarMenuEntryAcc::getLocale() throw (IllegalAccessibleComponentStateException, RuntimeException) +{ + const ::rtl::OUString aEmptyStr; + Locale aRet( aEmptyStr, aEmptyStr, aEmptyStr ); + + Reference< XAccessible > xParent( getAccessibleParent() ); + if( xParent.is() ) + { + Reference< XAccessibleContext > xParentContext( xParent->getAccessibleContext() ); + + if( xParentContext.is() ) + aRet = xParentContext->getLocale(); + } + + return aRet; +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuEntryAcc::addEventListener( const Reference< XAccessibleEventListener >& rxListener ) throw (RuntimeException) +{ + const ::vos::OGuard aGuard( maMutex ); + + if( rxListener.is() ) + { + EventListenerVector::const_iterator aIter( mxEventListeners.begin() ); + bool bFound = false; + + while( !bFound && ( aIter != mxEventListeners.end() ) ) + { + if( *aIter == rxListener ) + bFound = true; + else + aIter++; + } + + if (!bFound) + mxEventListeners.push_back( rxListener ); + } +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuEntryAcc::removeEventListener( const Reference< XAccessibleEventListener >& rxListener ) throw (RuntimeException) +{ + const ::vos::OGuard aGuard( maMutex ); + + if( rxListener.is() ) + { + EventListenerVector::iterator aIter = mxEventListeners.begin(); + bool bFound = false; + + while( !bFound && ( aIter != mxEventListeners.end() ) ) + { + if( *aIter == rxListener ) + { + mxEventListeners.erase( aIter ); + bFound = true; + } + else + aIter++; + } + } +} + +// ----------------------------------------------------------------------------- + +sal_Bool SAL_CALL ToolbarMenuEntryAcc::containsPoint( const awt::Point& aPoint ) throw (RuntimeException) +{ + const awt::Rectangle aRect( getBounds() ); + const Point aSize( aRect.Width, aRect.Height ); + const Point aNullPoint, aTestPoint( aPoint.X, aPoint.Y ); + + return Rectangle( aNullPoint, aSize ).IsInside( aTestPoint ); +} + +// ----------------------------------------------------------------------------- + +Reference< XAccessible > SAL_CALL ToolbarMenuEntryAcc::getAccessibleAtPoint( const awt::Point& ) throw (RuntimeException) +{ + Reference< XAccessible > xRet; + return xRet; +} + +// ----------------------------------------------------------------------------- + +awt::Rectangle SAL_CALL ToolbarMenuEntryAcc::getBounds() throw (RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + awt::Rectangle aRet; + + if( mpParent ) + { + Rectangle aRect( mpParent->maRect ); + Point aOrigin; + Rectangle aParentRect( aOrigin, mpParent->mrMenu.GetOutputSizePixel() ); + + aRect.Intersection( aParentRect ); + + aRet.X = aRect.Left(); + aRet.Y = aRect.Top(); + aRet.Width = aRect.GetWidth(); + aRet.Height = aRect.GetHeight(); + } + + return aRet; +} + +// ----------------------------------------------------------------------------- + +awt::Point SAL_CALL ToolbarMenuEntryAcc::getLocation() throw (RuntimeException) +{ + const awt::Rectangle aRect( getBounds() ); + return awt::Point( aRect.X, aRect.Y ); +} + +// ----------------------------------------------------------------------------- + +awt::Point SAL_CALL ToolbarMenuEntryAcc::getLocationOnScreen() throw (RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + awt::Point aRet; + + if( mpParent ) + { + const Point aScreenPos( mpParent->mrMenu.OutputToAbsoluteScreenPixel( mpParent->maRect.TopLeft() ) ); + + aRet.X = aScreenPos.X(); + aRet.Y = aScreenPos.Y(); + } + + return aRet; +} + +// ----------------------------------------------------------------------------- + +awt::Size SAL_CALL ToolbarMenuEntryAcc::getSize() throw (RuntimeException) +{ + const awt::Rectangle aRect( getBounds() ); + awt::Size aRet; + + aRet.Width = aRect.Width; + aRet.Height = aRect.Height; + + return aRet; +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuEntryAcc::grabFocus() throw (RuntimeException) +{ + // nothing to do +} + +// ----------------------------------------------------------------------------- + +Any SAL_CALL ToolbarMenuEntryAcc::getAccessibleKeyBinding() throw (RuntimeException) +{ + return Any(); +} + +// ----------------------------------------------------------------------------- + +sal_Int32 SAL_CALL ToolbarMenuEntryAcc::getForeground( ) throw (RuntimeException) +{ + return static_cast(Application::GetSettings().GetStyleSettings().GetMenuTextColor().GetColor()); +} + +// ----------------------------------------------------------------------------- + +sal_Int32 SAL_CALL ToolbarMenuEntryAcc::getBackground( ) throw (RuntimeException) +{ + return static_cast(Application::GetSettings().GetStyleSettings().GetMenuColor().GetColor()); +} + +} diff --git a/svtools/source/control/toolbarmenuimp.hxx b/svtools/source/control/toolbarmenuimp.hxx new file mode 100644 index 000000000000..96ad5070671d --- /dev/null +++ b/svtools/source/control/toolbarmenuimp.hxx @@ -0,0 +1,307 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "svtools/framestatuslistener.hxx" + +#include "svtools/valueset.hxx" + +namespace svtools { + +struct ToolbarMenu_Impl; +class ToolbarMenu; +class ToolbarMenuEntry; + +typedef ::std::vector< ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener > > EventListenerVector; +typedef std::vector< ToolbarMenuEntry * > ToolbarMenuEntryVector; + +const int EXTRAITEMHEIGHT = 0; // 4; +const int SEPARATOR_HEIGHT = 4; +const int TITLE_ID = -1; +const int BORDER_X = 0; +const int BORDER_Y = 0; + +// -------------------- +// - ToolbarMenuEntry - +// -------------------- + +class ToolbarMenuEntry +{ +public: + ToolbarMenu& mrMenu; + + int mnEntryId; + MenuItemBits mnBits; + Size maSize; + + bool mbHasText; + bool mbHasImage; + bool mbHasControl; + bool mbChecked; + bool mbEnabled; + + String maText; + Image maImage; + Control* mpControl; + Rectangle maRect; + + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > mxAccContext; + +public: + ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const String& rText, MenuItemBits nBits ); + ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const Image& rImage, MenuItemBits nBits ); + ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const Image& rImage, const String& rText, MenuItemBits nBits ); + ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, Control* pControl, MenuItemBits nBits ); + ~ToolbarMenuEntry(); + + void init( int nEntryId, MenuItemBits nBits ); + + const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >& GetAccessible( bool bCreate = false ); + + sal_Int32 getAccessibleChildCount() throw (::com::sun::star::uno::RuntimeException); + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > getAccessibleChild( sal_Int32 index ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + void selectAccessibleChild( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); +}; + +// --------------- +// - ToolbarMenuAcc - +// --------------- + +typedef ::cppu::WeakComponentImplHelper5< + ::com::sun::star::accessibility::XAccessible, + ::com::sun::star::accessibility::XAccessibleEventBroadcaster, + ::com::sun::star::accessibility::XAccessibleContext, + ::com::sun::star::accessibility::XAccessibleComponent, + ::com::sun::star::accessibility::XAccessibleSelection > + ToolbarMenuAccComponentBase; + +class ToolbarMenuAcc : + public ::comphelper::OBaseMutex, + public ToolbarMenuAccComponentBase +{ +public: + + ToolbarMenuAcc( ToolbarMenu_Impl& rParent ); + ~ToolbarMenuAcc(); + + void FireAccessibleEvent( short nEventId, const ::com::sun::star::uno::Any& rOldValue, const ::com::sun::star::uno::Any& rNewValue ); + bool HasAccessibleListeners() const { return( mxEventListeners.size() > 0 ); } + +public: + + /** Called by the corresponding ToolbarMenu when it gets the focus. + Stores the new focus state and broadcasts a state change event. + */ + void GetFocus (void); + + /** Called by the corresponding ToolbarMenu when it loses the focus. + Stores the new focus state and broadcasts a state change event. + */ + void LoseFocus (void); + + + // XAccessible + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleEventBroadcaster + using cppu::WeakComponentImplHelper5::addEventListener; + virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + using cppu::WeakComponentImplHelper5::removeEventListener; + virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleContext + virtual sal_Int32 SAL_CALL getAccessibleChildCount( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleParent( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getAccessibleIndexInParent( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getAccessibleRole( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getAccessibleDescription( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getAccessibleName( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::lang::Locale SAL_CALL getLocale( ) throw (::com::sun::star::accessibility::IllegalAccessibleComponentStateException, ::com::sun::star::uno::RuntimeException); + + // XAccessibleComponent + virtual sal_Bool SAL_CALL containsPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Rectangle SAL_CALL getBounds( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Point SAL_CALL getLocation( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Point SAL_CALL getLocationOnScreen( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Size SAL_CALL getSize( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL grabFocus( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleKeyBinding( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getForeground( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getBackground( ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleSelection + virtual void SAL_CALL selectAccessibleChild( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL clearAccessibleSelection( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL selectAllAccessibleChildren( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getSelectedAccessibleChildCount( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + +private: + EventListenerVector mxEventListeners; + ToolbarMenu_Impl* mpParent; + /// The current FOCUSED state. + bool mbIsFocused; + + /** Tell all listeners that the object is dying. This callback is + usually called from the WeakComponentImplHelper class. + */ + virtual void SAL_CALL disposing (void); + + /** Check whether or not the object has been disposed (or is in the + state of beeing disposed). If that is the case then + DisposedException is thrown to inform the (indirect) caller of the + foul deed. + */ + void ThrowIfDisposed (void) throw (::com::sun::star::lang::DisposedException); +}; + +// ----------------------- +// - ToolbarMenuEntryAcc - +// ----------------------- + +typedef ::cppu::WeakComponentImplHelper4< ::com::sun::star::accessibility::XAccessible, + ::com::sun::star::accessibility::XAccessibleEventBroadcaster, + ::com::sun::star::accessibility::XAccessibleContext, + ::com::sun::star::accessibility::XAccessibleComponent > ToolbarMenuEntryAccBase; + +class ToolbarMenuEntryAcc : public ::comphelper::OBaseMutex, + public ToolbarMenuEntryAccBase +{ +public: + ToolbarMenuEntryAcc( ToolbarMenuEntry* pParent ); + ~ToolbarMenuEntryAcc(); + + void FireAccessibleEvent( short nEventId, const ::com::sun::star::uno::Any& rOldValue, const ::com::sun::star::uno::Any& rNewValue ); + bool HasAccessibleListeners() const { return( mxEventListeners.size() > 0 ); } + + // XAccessible + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleEventBroadcaster + virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleContext + virtual sal_Int32 SAL_CALL getAccessibleChildCount( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleParent( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getAccessibleIndexInParent( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getAccessibleRole( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getAccessibleDescription( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getAccessibleName( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::lang::Locale SAL_CALL getLocale( ) throw (::com::sun::star::accessibility::IllegalAccessibleComponentStateException, ::com::sun::star::uno::RuntimeException); + + // XAccessibleComponent + virtual sal_Bool SAL_CALL containsPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Rectangle SAL_CALL getBounds( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Point SAL_CALL getLocation( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Point SAL_CALL getLocationOnScreen( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Size SAL_CALL getSize( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL grabFocus( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleKeyBinding( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getForeground( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getBackground( ) throw (::com::sun::star::uno::RuntimeException); + +private: + EventListenerVector mxEventListeners; + ::vos::OMutex maMutex; + ToolbarMenuEntry* mpParent; + + /** Tell all listeners that the object is dying. This callback is + usually called from the WeakComponentImplHelper class. + */ + virtual void SAL_CALL disposing (void); +}; + +// ----------------------------------------------------------------------------- + +struct ToolbarMenu_Impl +{ + ToolbarMenu& mrMenu; + + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > mxFrame; + rtl::Reference< svt::FrameStatusListener > mxStatusListener; + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxServiceManager; + rtl::Reference< ToolbarMenuAcc > mxAccessible; + ToolbarMenuEntryVector maEntryVector; + + int mnCheckPos; + int mnImagePos; + int mnTextPos; + + int mnHighlightedEntry; + int mnSelectedEntry; + int mnLastColumn; + + Size maSize; + + Link maSelectHdl; + + ToolbarMenu_Impl( ToolbarMenu& rMenu, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame ); + ~ToolbarMenu_Impl(); + + void setAccessible( ToolbarMenuAcc* pAccessible ); + + void fireAccessibleEvent( short nEventId, const ::com::sun::star::uno::Any& rOldValue, const ::com::sun::star::uno::Any& rNewValue ); + bool hasAccessibleListeners(); + + sal_Int32 getAccessibleChildCount() throw (::com::sun::star::uno::RuntimeException); + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > getAccessibleChild( sal_Int32 index ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + void selectAccessibleChild( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + sal_Bool isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + void clearAccessibleSelection(); +}; + +} diff --git a/svtools/source/control/valueimp.hxx b/svtools/source/control/valueimp.hxx index c176629953ae..65f6b8ffaccb 100644 --- a/svtools/source/control/valueimp.hxx +++ b/svtools/source/control/valueimp.hxx @@ -114,6 +114,7 @@ struct ValueSet_Impl { ::std::auto_ptr< ValueItemList > mpItemList; bool mbIsTransientChildrenDisabled; + Link maHighlightHdl; ValueSet_Impl() : mpItemList( ::std::auto_ptr< ValueItemList >( new ValueItemList() ) ), mbIsTransientChildrenDisabled( false ) diff --git a/svtools/source/control/valueset.cxx b/svtools/source/control/valueset.cxx index 4033a9df7bb5..dffc155901c3 100644 --- a/svtools/source/control/valueset.cxx +++ b/svtools/source/control/valueset.cxx @@ -1421,7 +1421,7 @@ void ValueSet::KeyInput( const KeyEvent& rKEvt ) { USHORT nLastItem = (USHORT)mpImpl->mpItemList->Count(); USHORT nItemPos = VALUESET_ITEM_NOTFOUND; - USHORT nCurPos; + USHORT nCurPos = VALUESET_ITEM_NONEITEM; USHORT nCalcPos; if ( !nLastItem || !ImplGetFirstItem() ) @@ -1434,8 +1434,6 @@ void ValueSet::KeyInput( const KeyEvent& rKEvt ) if ( mnSelItemId ) nCurPos = GetItemPos( mnSelItemId ); - else - nCurPos = VALUESET_ITEM_NONEITEM; nCalcPos = nCurPos; //switch off selection mode if key travelling is used @@ -1531,6 +1529,7 @@ void ValueSet::KeyInput( const KeyEvent& rKEvt ) nCalcPos - ( nLineCount * mnCols )); else { +#if 0 if( (KEY_UP == rKEvt.GetKeyCode().GetCode() ) && (GetStyle() & WB_MENUSTYLEVALUESET) ) { Window* pParent = GetParent(); @@ -1539,6 +1538,7 @@ void ValueSet::KeyInput( const KeyEvent& rKEvt ) break; } else +#endif { if ( mpNoneItem ) { @@ -1583,6 +1583,7 @@ void ValueSet::KeyInput( const KeyEvent& rKEvt ) nCalcPos + ( nLineCount * mnCols )); else { +#if 0 if( (KEY_DOWN == rKEvt.GetKeyCode().GetCode() ) && (GetStyle() & WB_MENUSTYLEVALUESET) ) { Window* pParent = GetParent(); @@ -1591,6 +1592,7 @@ void ValueSet::KeyInput( const KeyEvent& rKEvt ) break; } else +#endif { if ( mpNoneItem ) { @@ -1623,7 +1625,6 @@ void ValueSet::KeyInput( const KeyEvent& rKEvt ) bDefault = TRUE; break; } - if(!bDefault) EndSelection(); if ( nItemPos != VALUESET_ITEM_NOTFOUND ) @@ -1633,6 +1634,7 @@ void ValueSet::KeyInput( const KeyEvent& rKEvt ) nItemId = GetItemId( nItemPos ); else nItemId = 0; + if ( nItemId != mnSelItemId ) { SelectItem( nItemId ); @@ -2280,6 +2282,8 @@ void ValueSet::SelectItem( USHORT nItemId ) // selection event ::com::sun::star::uno::Any aOldAny, aNewAny; ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::SELECTION_CHANGED, aOldAny, aNewAny ); + + mpImpl->maHighlightHdl.Call(this); } } } @@ -2752,3 +2756,19 @@ bool ValueSet::IsRTLActive (void) return Application::GetSettings().GetLayoutRTL() && IsRTLEnabled(); } +// ----------------------------------------------------------------------- + +void ValueSet::SetHighlightHdl( const Link& rLink ) +{ + mpImpl->maHighlightHdl = rLink; +} + +// ----------------------------------------------------------------------- + +const Link& ValueSet::GetHighlightHdl() const +{ + return mpImpl->maHighlightHdl; +} + +// ----------------------------------------------------------------------- + diff --git a/svtools/source/uno/makefile.mk b/svtools/source/uno/makefile.mk index 82e509f1ce08..0081d4a5fd9e 100644 --- a/svtools/source/uno/makefile.mk +++ b/svtools/source/uno/makefile.mk @@ -2,14 +2,10 @@ # # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # -# Copyright 2008 by Sun Microsystems, Inc. +# Copyright 2000, 2010 Oracle and/or its affiliates. # # OpenOffice.org - a multi-platform office productivity suite # -# $RCSfile: makefile.mk,v $ -# -# $Revision: 1.21 $ -# # This file is part of OpenOffice.org. # # OpenOffice.org is free software: you can redistribute it and/or modify @@ -59,7 +55,8 @@ SLOFILES= \ $(SLO)$/unoevent.obj \ $(SLO)$/unoiface.obj \ $(SLO)$/unoimap.obj \ - $(SLO)$/svtxgridcontrol.obj + $(SLO)$/svtxgridcontrol.obj \ + $(SLO)$/popupwindowcontroller.obj # --- Targets ------------------------------------------------------ diff --git a/svtools/source/uno/popupwindowcontroller.cxx b/svtools/source/uno/popupwindowcontroller.cxx new file mode 100644 index 000000000000..e83c76c0182e --- /dev/null +++ b/svtools/source/uno/popupwindowcontroller.cxx @@ -0,0 +1,215 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svtools.hxx" + +#include + +#include +#include + +#include + +#include "svtools/popupwindowcontroller.hxx" + +using rtl::OUString; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; + + +namespace svt +{ + +class PopupWindowControllerImpl +{ +public: + PopupWindowControllerImpl(); + ~PopupWindowControllerImpl(); + + void SetPopupWindow( ::Window* pPopupWindow ); + + DECL_LINK( WindowEventListener, VclSimpleEvent* ); + DECL_STATIC_LINK( PopupWindowControllerImpl, AsyncDeleteWindowHdl, Window* ); + +private: + ::Window* mpPopupWindow; +}; + +PopupWindowControllerImpl::PopupWindowControllerImpl() +: mpPopupWindow( 0 ) +{ +} + +PopupWindowControllerImpl::~PopupWindowControllerImpl() +{ + if( mpPopupWindow ) + SetPopupWindow(0); +} + +void PopupWindowControllerImpl::SetPopupWindow( ::Window* pPopupWindow ) +{ + if( mpPopupWindow ) + { + mpPopupWindow->RemoveEventListener( LINK( this, PopupWindowControllerImpl, WindowEventListener ) ); + Application::PostUserEvent( STATIC_LINK( this, PopupWindowControllerImpl, AsyncDeleteWindowHdl ), mpPopupWindow ); + } + mpPopupWindow = pPopupWindow; + if( mpPopupWindow ) + { + mpPopupWindow->AddEventListener( LINK( this, PopupWindowControllerImpl, WindowEventListener )); + } +} + +IMPL_LINK( PopupWindowControllerImpl, WindowEventListener, VclSimpleEvent*, pEvent ) +{ + VclWindowEvent* pWindowEvent = dynamic_cast< VclWindowEvent* >( pEvent ); + if( pWindowEvent ) + { + switch( pWindowEvent->GetId() ) + { + case VCLEVENT_WINDOW_CLOSE: + case VCLEVENT_WINDOW_ENDPOPUPMODE: + SetPopupWindow(0); + break; + } + } + return 1; +} + +//-------------------------------------------------------------------- + +IMPL_STATIC_LINK( PopupWindowControllerImpl, AsyncDeleteWindowHdl, Window*, pWindow ) +{ + (void)*pThis; + delete pWindow; + return 0; +} + +//======================================================================== +// class PopupWindowController +//======================================================================== + +PopupWindowController::PopupWindowController( const Reference< lang::XMultiServiceFactory >& rServiceManager, + const Reference< frame::XFrame >& xFrame, + const OUString& aCommandURL ) +: svt::ToolboxController( rServiceManager, xFrame, aCommandURL ) +, mpImpl( new PopupWindowControllerImpl() ) +{ +} + +PopupWindowController::~PopupWindowController() +{ +} + +// XInterface +Any SAL_CALL PopupWindowController::queryInterface( const Type& aType ) +throw (RuntimeException) +{ + Any a( ToolboxController::queryInterface( aType ) ); + if ( a.hasValue() ) + return a; + + return ::cppu::queryInterface( aType, static_cast< lang::XServiceInfo* >( this )); +} + +void SAL_CALL PopupWindowController::acquire() throw () +{ + ToolboxController::acquire(); +} + +void SAL_CALL PopupWindowController::release() throw () +{ + ToolboxController::release(); +} + +// XServiceInfo +sal_Bool SAL_CALL PopupWindowController::supportsService( const OUString& ServiceName ) throw(RuntimeException) +{ + const Sequence< OUString > aSNL( getSupportedServiceNames() ); + const OUString * pArray = aSNL.getConstArray(); + + for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) + if( pArray[i] == ServiceName ) + return true; + + return false; +} + +// XComponent +void SAL_CALL PopupWindowController::dispose() throw (RuntimeException) +{ + svt::ToolboxController::dispose(); +} + +// XStatusListener +void SAL_CALL PopupWindowController::statusChanged( const frame::FeatureStateEvent& rEvent ) throw ( RuntimeException ) +{ + svt::ToolboxController::statusChanged(rEvent); +} + +// XToolbarController +void SAL_CALL PopupWindowController::execute( sal_Int16 KeyModifier ) throw (RuntimeException) +{ + svt::ToolboxController::execute( KeyModifier ); +} + +void SAL_CALL PopupWindowController::click() throw (RuntimeException) +{ + svt::ToolboxController::click(); +} + +void SAL_CALL PopupWindowController::doubleClick() throw (RuntimeException) +{ + svt::ToolboxController::doubleClick(); +} + +Reference< awt::XWindow > SAL_CALL PopupWindowController::createPopupWindow() throw (RuntimeException) +{ + ToolBox* pToolBox = dynamic_cast< ToolBox* >( VCLUnoHelper::GetWindow( getParent() ) ); + if( pToolBox ) + { + ::Window* pWin = createPopupWindow(pToolBox); + if( pWin ) + { + pWin->EnableDocking(true); + mpImpl->SetPopupWindow(pWin); + ::Window::GetDockingManager()->StartPopupMode( pToolBox, pWin, FLOATWIN_POPUPMODE_NOFOCUSCLOSE|FLOATWIN_POPUPMODE_ALLMOUSEBUTTONCLOSE |FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE ); + } + } + return Reference< awt::XWindow >(); +} + +Reference< awt::XWindow > SAL_CALL PopupWindowController::createItemWindow( const Reference< awt::XWindow >& Parent ) + throw (RuntimeException) +{ + return Reference< awt::XWindow >(); +} + +} + diff --git a/svtools/source/uno/toolboxcontroller.cxx b/svtools/source/uno/toolboxcontroller.cxx index a8d05c49a7ae..b2b60f7ec623 100644 --- a/svtools/source/uno/toolboxcontroller.cxx +++ b/svtools/source/uno/toolboxcontroller.cxx @@ -46,6 +46,8 @@ #endif #include +using ::rtl::OUString; + using namespace ::cppu; using namespace ::com::sun::star::awt; using namespace ::com::sun::star::uno; @@ -707,4 +709,23 @@ Reference< ::com::sun::star::awt::XWindow > ToolboxController::getParent() const { return m_pImpl->m_xParentWindow; } + + +void ToolboxController::dispatchCommand( const OUString& sCommandURL, const Sequence< PropertyValue >& rArgs ) +{ + try + { + Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY_THROW ); + URL aURL; + aURL.Complete = sCommandURL; + getURLTransformer()->parseStrict( aURL ); + + Reference< XDispatch > xDispatch( xDispatchProvider->queryDispatch( aURL, OUString(), 0 ), UNO_QUERY_THROW ); + xDispatch->dispatch( aURL, rArgs ); + } + catch( Exception& ) + { + } +} + } // svt From c10f069c3385a7c55a9042315f7fe3a83fc56fd3 Mon Sep 17 00:00:00 2001 From: Christian Lippka Date: Sun, 21 Mar 2010 20:01:33 +0100 Subject: [PATCH 06/18] Adding PopupMenuController to allow PopupMenuControllerBase dervivates to be used in toolbars --- .../inc/svtools/popupmenucontrollerbase.hxx | 141 ++++++ svtools/inc/svtools/popupwindowcontroller.hxx | 4 +- svtools/inc/svtools/toolboxcontroller.hxx | 7 + svtools/source/uno/makefile.mk | 3 +- .../source/uno/popupmenucontrollerbase.cxx | 421 ++++++++++++++++++ svtools/source/uno/popupwindowcontroller.cxx | 13 + svtools/source/uno/toolboxcontroller.cxx | 90 +++- 7 files changed, 667 insertions(+), 12 deletions(-) create mode 100644 svtools/inc/svtools/popupmenucontrollerbase.hxx create mode 100644 svtools/source/uno/popupmenucontrollerbase.cxx diff --git a/svtools/inc/svtools/popupmenucontrollerbase.hxx b/svtools/inc/svtools/popupmenucontrollerbase.hxx new file mode 100644 index 000000000000..706ce076be02 --- /dev/null +++ b/svtools/inc/svtools/popupmenucontrollerbase.hxx @@ -0,0 +1,141 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef __SVTOOLS_POPUPMENUCONTROLLERBASE_HXX_ +#define __SVTOOLS_POPUPMENUCONTROLLERBASE_HXX_ + +#include "svtools/svtdllapi.h" + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//_________________________________________________________________________________________________________________ +// includes of other projects +//_________________________________________________________________________________________________________________ +#include +#include +#include +#include +#include + +namespace svt +{ + struct PopupMenuControllerBaseDispatchInfo; + + typedef public ::cppu::WeakComponentImplHelper7< + com::sun::star::lang::XServiceInfo , + com::sun::star::frame::XPopupMenuController , + com::sun::star::lang::XInitialization , + com::sun::star::frame::XStatusListener , + com::sun::star::awt::XMenuListener , + com::sun::star::frame::XDispatchProvider , + com::sun::star::frame::XDispatch > PopupMenuControllerBaseType; + + class SVT_DLLPUBLIC PopupMenuControllerBase : protected ::comphelper::OBaseMutex, // Struct for right initalization of mutex member! Must be first of baseclasses. + public PopupMenuControllerBaseType + { + public: + PopupMenuControllerBase( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager ); + virtual ~PopupMenuControllerBase(); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException) = 0; + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException) = 0; + + // XPopupMenuController + virtual void SAL_CALL setPopupMenu( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XPopupMenu >& PopupMenu ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updatePopupMenu() throw (::com::sun::star::uno::RuntimeException); + + // XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XStatusListener + virtual void SAL_CALL statusChanged( const ::com::sun::star::frame::FeatureStateEvent& Event ) throw ( ::com::sun::star::uno::RuntimeException ) = 0; + + // XMenuListener + virtual void SAL_CALL highlight( const ::com::sun::star::awt::MenuEvent& rEvent ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL select( const ::com::sun::star::awt::MenuEvent& rEvent ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL activate( const ::com::sun::star::awt::MenuEvent& rEvent ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL deactivate( const ::com::sun::star::awt::MenuEvent& rEvent ) throw (::com::sun::star::uno::RuntimeException); + + // XDispatchProvider + virtual ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > SAL_CALL queryDispatch( const ::com::sun::star::util::URL& aURL, const ::rtl::OUString& sTarget, sal_Int32 nFlags ) throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > > SAL_CALL queryDispatches( const ::com::sun::star::uno::Sequence< ::com::sun::star::frame::DispatchDescriptor >& lDescriptor ) throw( ::com::sun::star::uno::RuntimeException ); + + // XDispatch + virtual void SAL_CALL dispatch( const ::com::sun::star::util::URL& aURL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& seqProperties ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL addStatusListener( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener >& xControl, const ::com::sun::star::util::URL& aURL ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL removeStatusListener( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener >& xControl, const ::com::sun::star::util::URL& aURL ) throw( ::com::sun::star::uno::RuntimeException ); + + // XEventListener + virtual void SAL_CALL disposing( const com::sun::star::lang::EventObject& Source ) throw ( ::com::sun::star::uno::RuntimeException ); + + void dispatchCommand( const ::rtl::OUString& sCommandURL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rArgs ); + + protected: + void throwIfDisposed() throw ( ::com::sun::star::uno::RuntimeException ); + + /** helper method to cause statusChanged is called once for the given command url */ + void SAL_CALL updateCommand( const rtl::OUString& rCommandURL ); + + /** this function is called upon disposing the component + */ + virtual void SAL_CALL disposing(); + + virtual void resetPopupMenu( com::sun::star::uno::Reference< com::sun::star::awt::XPopupMenu >& rPopupMenu ); + virtual void impl_setPopupMenu(); + virtual void impl_select(const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch >& _xDispatch,const ::com::sun::star::util::URL& aURL); + ::rtl::OUString determineBaseURL( const ::rtl::OUString& aURL ); + + DECL_STATIC_LINK( PopupMenuControllerBase, ExecuteHdl_Impl, PopupMenuControllerBaseDispatchInfo* ); + + + bool m_bInitialized; + rtl::OUString m_aCommandURL; + rtl::OUString m_aBaseURL; + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > m_xDispatch; + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > m_xFrame; + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xServiceManager; + ::com::sun::star::uno::Reference< ::com::sun::star::util::XURLTransformer > m_xURLTransformer; + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XPopupMenu > m_xPopupMenu; + }; +} + +#endif // __SVTOOLS_POPUPMENUCONTROLLERBASE_HXX_ diff --git a/svtools/inc/svtools/popupwindowcontroller.hxx b/svtools/inc/svtools/popupwindowcontroller.hxx index e9f586724bc4..4877d0184318 100644 --- a/svtools/inc/svtools/popupwindowcontroller.hxx +++ b/svtools/inc/svtools/popupwindowcontroller.hxx @@ -61,6 +61,9 @@ public: virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw( ::com::sun::star::uno::RuntimeException ); virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw( ::com::sun::star::uno::RuntimeException ) = 0; + // XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + // XComponent virtual void SAL_CALL dispose() throw (::com::sun::star::uno::RuntimeException); @@ -73,7 +76,6 @@ public: virtual void SAL_CALL doubleClick() throw (::com::sun::star::uno::RuntimeException); virtual ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > SAL_CALL createPopupWindow() throw (::com::sun::star::uno::RuntimeException); virtual ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > SAL_CALL createItemWindow( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow >& Parent ) throw (::com::sun::star::uno::RuntimeException); - private: boost::scoped_ptr< PopupWindowControllerImpl > mpImpl; }; diff --git a/svtools/inc/svtools/toolboxcontroller.hxx b/svtools/inc/svtools/toolboxcontroller.hxx index 749099aaf639..96e48a399831 100644 --- a/svtools/inc/svtools/toolboxcontroller.hxx +++ b/svtools/inc/svtools/toolboxcontroller.hxx @@ -48,6 +48,8 @@ #define INCLUDED_HASH_MAP #endif +class ToolBox; + namespace svt { struct ToolboxController_Impl; @@ -104,10 +106,15 @@ class SVT_DLLPUBLIC ToolboxController : public ::com::sun::star::frame::XStatusL virtual ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > SAL_CALL createItemWindow( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow >& Parent ) throw (::com::sun::star::uno::RuntimeException); const rtl::OUString& getCommandURL() const { return m_aCommandURL; } + const rtl::OUString& getModuleName() const; void dispatchCommand( const ::rtl::OUString& sCommandURL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rArgs ); + void enable( bool bEnable ); + protected: + bool getToolboxId( sal_uInt16& rItemId, ToolBox** ppToolBox ); + struct Listener { Listener( const ::com::sun::star::util::URL& rURL, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch >& rDispatch ) : diff --git a/svtools/source/uno/makefile.mk b/svtools/source/uno/makefile.mk index 0081d4a5fd9e..665301e9112d 100644 --- a/svtools/source/uno/makefile.mk +++ b/svtools/source/uno/makefile.mk @@ -56,7 +56,8 @@ SLOFILES= \ $(SLO)$/unoiface.obj \ $(SLO)$/unoimap.obj \ $(SLO)$/svtxgridcontrol.obj \ - $(SLO)$/popupwindowcontroller.obj + $(SLO)$/popupwindowcontroller.obj \ + $(SLO)$/popupmenucontrollerbase.obj # --- Targets ------------------------------------------------------ diff --git a/svtools/source/uno/popupmenucontrollerbase.cxx b/svtools/source/uno/popupmenucontrollerbase.cxx new file mode 100644 index 000000000000..457207d317b4 --- /dev/null +++ b/svtools/source/uno/popupmenucontrollerbase.cxx @@ -0,0 +1,421 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svtools.hxx" + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include "svtools/popupmenucontrollerbase.hxx" + + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include +#include +#include +#include +#include +#include + +//_________________________________________________________________________________________________________________ +// includes of other projects +//_________________________________________________________________________________________________________________ + +#ifndef _VCL_MENU_HXX_ +#include +#endif +#include +#include +#include +#include + +//_________________________________________________________________________________________________________________ +// Defines +//_________________________________________________________________________________________________________________ +// + +using ::rtl::OUString; + +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::frame; +using namespace com::sun::star::beans; +using namespace com::sun::star::util; + +namespace svt +{ + +struct PopupMenuControllerBaseDispatchInfo +{ + Reference< XDispatch > mxDispatch; + const URL maURL; + const Sequence< PropertyValue > maArgs; + + PopupMenuControllerBaseDispatchInfo( const Reference< XDispatch >& xDispatch, const URL& rURL, const Sequence< PropertyValue >& rArgs ) + : mxDispatch( xDispatch ), maURL( rURL ), maArgs( rArgs ) {} +}; + +PopupMenuControllerBase::PopupMenuControllerBase( const Reference< XMultiServiceFactory >& xServiceManager ) : + ::comphelper::OBaseMutex(), + PopupMenuControllerBaseType(m_aMutex), + m_bInitialized( false ), + m_xServiceManager( xServiceManager ) +{ + if ( m_xServiceManager.is() ) + m_xURLTransformer.set( m_xServiceManager->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer"))),UNO_QUERY ); +} + +PopupMenuControllerBase::~PopupMenuControllerBase() +{ +} + +// protected function +void PopupMenuControllerBase::throwIfDisposed() throw ( RuntimeException ) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + throw com::sun::star::lang::DisposedException(); +} + +// protected function +void PopupMenuControllerBase::resetPopupMenu( com::sun::star::uno::Reference< com::sun::star::awt::XPopupMenu >& rPopupMenu ) +{ + VCLXPopupMenu* pPopupMenu = 0; + if ( rPopupMenu.is() && rPopupMenu->getItemCount() > 0 ) + { + pPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( rPopupMenu ); + if ( pPopupMenu ) + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + PopupMenu* pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu(); + pVCLPopupMenu->Clear(); + } + } +} + +void SAL_CALL PopupMenuControllerBase::disposing() +throw (::com::sun::star::uno::RuntimeException) +{ + // Reset our members and set disposed flag + osl::MutexGuard aLock( m_aMutex ); + m_xFrame.clear(); + m_xDispatch.clear(); + m_xPopupMenu.clear(); + m_xServiceManager.clear(); +} + +// XServiceInfo + +sal_Bool SAL_CALL PopupMenuControllerBase::supportsService( const ::rtl::OUString& ServiceName ) throw (RuntimeException) +{ + const Sequence< rtl::OUString > aSNL( getSupportedServiceNames() ); + const rtl::OUString * pArray = aSNL.getConstArray(); + + for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) + if( pArray[i] == ServiceName ) + return true; + + return false; +} + +// XEventListener +void SAL_CALL PopupMenuControllerBase::disposing( const EventObject& ) throw ( RuntimeException ) +{ + osl::MutexGuard aLock( m_aMutex ); + m_xFrame.clear(); + m_xDispatch.clear(); + m_xPopupMenu.clear(); +} + +// XMenuListener +void SAL_CALL PopupMenuControllerBase::highlight( const awt::MenuEvent& ) throw (RuntimeException) +{ +} + +void PopupMenuControllerBase::impl_select(const Reference< XDispatch >& _xDispatch,const URL& aURL) +{ + Sequence aArgs; + OSL_ENSURE(_xDispatch.is(),"PopupMenuControllerBase::impl_select: No dispatch"); + if ( _xDispatch.is() ) + _xDispatch->dispatch( aURL, aArgs ); +} + +void SAL_CALL PopupMenuControllerBase::select( const awt::MenuEvent& rEvent ) throw (RuntimeException) +{ + throwIfDisposed(); + + osl::MutexGuard aLock( m_aMutex ); + + Reference< awt::XMenuExtended > xExtMenu( m_xPopupMenu, UNO_QUERY ); + if( xExtMenu.is() ) + { + Sequence aArgs; + dispatchCommand( xExtMenu->getCommand( rEvent.MenuId ), aArgs ); + } +} + +void PopupMenuControllerBase::dispatchCommand( const ::rtl::OUString& sCommandURL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rArgs ) +{ + osl::MutexGuard aLock( m_aMutex ); + + throwIfDisposed(); + + try + { + Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY_THROW ); + URL aURL; + aURL.Complete = sCommandURL; + m_xURLTransformer->parseStrict( aURL ); + + Reference< XDispatch > xDispatch( xDispatchProvider->queryDispatch( aURL, OUString(), 0 ), UNO_QUERY_THROW ); + + Application::PostUserEvent( STATIC_LINK(0, PopupMenuControllerBase, ExecuteHdl_Impl), new PopupMenuControllerBaseDispatchInfo( xDispatch, aURL, rArgs ) ); + + } + catch( Exception& ) + { + } + +} + +IMPL_STATIC_LINK_NOINSTANCE( PopupMenuControllerBase, ExecuteHdl_Impl, PopupMenuControllerBaseDispatchInfo*, pDispatchInfo ) +{ + pDispatchInfo->mxDispatch->dispatch( pDispatchInfo->maURL, pDispatchInfo->maArgs ); + delete pDispatchInfo; + return 0; +} + +void SAL_CALL PopupMenuControllerBase::activate( const awt::MenuEvent& ) throw (RuntimeException) +{ +} + +void SAL_CALL PopupMenuControllerBase::deactivate( const awt::MenuEvent& ) throw (RuntimeException) +{ +} + +void SAL_CALL PopupMenuControllerBase::updatePopupMenu() throw ( ::com::sun::star::uno::RuntimeException ) +{ + osl::ClearableMutexGuard aLock( m_aMutex ); + throwIfDisposed(); + aLock.clear(); + + updateCommand( m_aCommandURL ); +} + +void SAL_CALL PopupMenuControllerBase::updateCommand( const rtl::OUString& rCommandURL ) +{ + osl::ClearableMutexGuard aLock( m_aMutex ); + Reference< XStatusListener > xStatusListener( static_cast< OWeakObject* >( this ), UNO_QUERY ); + Reference< XDispatch > xDispatch( m_xDispatch ); + URL aTargetURL; + aTargetURL.Complete = rCommandURL; + m_xURLTransformer->parseStrict( aTargetURL ); + aLock.clear(); + + // Add/remove status listener to get a status update once + if ( xDispatch.is() ) + { + xDispatch->addStatusListener( xStatusListener, aTargetURL ); + xDispatch->removeStatusListener( xStatusListener, aTargetURL ); + } +} + + +// XDispatchProvider +Reference< XDispatch > SAL_CALL +PopupMenuControllerBase::queryDispatch( + const URL& /*aURL*/, + const rtl::OUString& /*sTarget*/, + sal_Int32 /*nFlags*/ ) +throw( RuntimeException ) +{ + // must be implemented by subclass + osl::MutexGuard aLock( m_aMutex ); + throwIfDisposed(); + + return Reference< XDispatch >(); +} + +Sequence< Reference< XDispatch > > SAL_CALL PopupMenuControllerBase::queryDispatches( const Sequence< DispatchDescriptor >& lDescriptor ) throw( RuntimeException ) +{ + // Create return list - which must have same size then the given descriptor + // It's not allowed to pack it! + osl::ClearableMutexGuard aLock( m_aMutex ); + throwIfDisposed(); + aLock.clear(); + + sal_Int32 nCount = lDescriptor.getLength(); + uno::Sequence< uno::Reference< frame::XDispatch > > lDispatcher( nCount ); + + // Step over all descriptors and try to get any dispatcher for it. + for( sal_Int32 i=0; i& /*seqProperties*/ ) +throw( ::com::sun::star::uno::RuntimeException ) +{ + // must be implemented by subclass + osl::MutexGuard aLock( m_aMutex ); + throwIfDisposed(); +} + +void SAL_CALL +PopupMenuControllerBase::addStatusListener( + const Reference< XStatusListener >& xControl, + const URL& aURL ) +throw( ::com::sun::star::uno::RuntimeException ) +{ + osl::ResettableMutexGuard aLock( m_aMutex ); + throwIfDisposed(); + aLock.clear(); + + bool bStatusUpdate( false ); + rBHelper.addListener( ::getCppuType( &xControl ), xControl ); + + aLock.reset(); + if ( aURL.Complete.indexOf( m_aBaseURL ) == 0 ) + bStatusUpdate = true; + aLock.clear(); + + if ( bStatusUpdate ) + { + // Dummy update for popup menu controllers + FeatureStateEvent aEvent; + aEvent.FeatureURL = aURL; + aEvent.IsEnabled = sal_True; + aEvent.Requery = sal_False; + aEvent.State = Any(); + xControl->statusChanged( aEvent ); + } +} + +void SAL_CALL PopupMenuControllerBase::removeStatusListener( + const Reference< XStatusListener >& xControl, + const URL& /*aURL*/ ) +throw( ::com::sun::star::uno::RuntimeException ) +{ + rBHelper.removeListener( ::getCppuType( &xControl ), xControl ); +} + +::rtl::OUString PopupMenuControllerBase::determineBaseURL( const ::rtl::OUString& aURL ) +{ + // Just use the main part of the URL for popup menu controllers + sal_Int32 nQueryPart( 0 ); + sal_Int32 nSchemePart( 0 ); + rtl::OUString aMainURL( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.popup:" )); + + nSchemePart = aURL.indexOf( ':' ); + if (( nSchemePart > 0 ) && + ( aURL.getLength() > ( nSchemePart+1 ))) + { + nQueryPart = aURL.indexOf( '?', nSchemePart ); + if ( nQueryPart > 0 ) + aMainURL += aURL.copy( nSchemePart, nQueryPart-nSchemePart ); + else if ( nQueryPart == -1 ) + aMainURL += aURL.copy( nSchemePart+1 ); + } + + return aMainURL; +} + +// XInitialization +void SAL_CALL PopupMenuControllerBase::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException ) +{ + osl::MutexGuard aLock( m_aMutex ); + + sal_Bool bInitalized( m_bInitialized ); + if ( !bInitalized ) + { + PropertyValue aPropValue; + rtl::OUString aCommandURL; + Reference< XFrame > xFrame; + + for ( int i = 0; i < aArguments.getLength(); i++ ) + { + if ( aArguments[i] >>= aPropValue ) + { + if ( aPropValue.Name.equalsAscii( "Frame" )) + aPropValue.Value >>= xFrame; + else if ( aPropValue.Name.equalsAscii( "CommandURL" )) + aPropValue.Value >>= aCommandURL; + } + } + + if ( xFrame.is() && aCommandURL.getLength() ) + { + m_xFrame = xFrame; + m_aCommandURL = aCommandURL; + m_aBaseURL = determineBaseURL( aCommandURL ); + m_bInitialized = true; + } + } +} +// XPopupMenuController +void SAL_CALL PopupMenuControllerBase::setPopupMenu( const Reference< awt::XPopupMenu >& xPopupMenu ) throw ( RuntimeException ) +{ + osl::MutexGuard aLock( m_aMutex ); + throwIfDisposed(); + + if ( m_xFrame.is() && !m_xPopupMenu.is() ) + { + // Create popup menu on demand + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + m_xPopupMenu = xPopupMenu; + m_xPopupMenu->addMenuListener( Reference< awt::XMenuListener >( (OWeakObject*)this, UNO_QUERY )); + + Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY ); + + URL aTargetURL; + aTargetURL.Complete = m_aCommandURL; + m_xURLTransformer->parseStrict( aTargetURL ); + m_xDispatch = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 ); + + impl_setPopupMenu(); + + updatePopupMenu(); + } +} +void PopupMenuControllerBase::impl_setPopupMenu() +{ +} +} diff --git a/svtools/source/uno/popupwindowcontroller.cxx b/svtools/source/uno/popupwindowcontroller.cxx index ef5ad6e76967..9d5285250d20 100644 --- a/svtools/source/uno/popupwindowcontroller.cxx +++ b/svtools/source/uno/popupwindowcontroller.cxx @@ -159,16 +159,29 @@ sal_Bool SAL_CALL PopupWindowController::supportsService( const OUString& Servic return false; } +// XInitialization +void SAL_CALL PopupWindowController::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + svt::ToolboxController::initialize( aArguments ); + if( m_aCommandURL.getLength() ) + addStatusListener( m_aCommandURL ); +} + // XComponent void SAL_CALL PopupWindowController::dispose() throw (RuntimeException) { + if( m_aCommandURL.getLength() ) + removeStatusListener( m_aCommandURL ); + svt::ToolboxController::dispose(); } + // XStatusListener void SAL_CALL PopupWindowController::statusChanged( const frame::FeatureStateEvent& rEvent ) throw ( RuntimeException ) { svt::ToolboxController::statusChanged(rEvent); + enable( rEvent.IsEnabled ); } // XToolbarController diff --git a/svtools/source/uno/toolboxcontroller.cxx b/svtools/source/uno/toolboxcontroller.cxx index ee12b8f78d49..d9b84aa2e356 100644 --- a/svtools/source/uno/toolboxcontroller.cxx +++ b/svtools/source/uno/toolboxcontroller.cxx @@ -56,10 +56,29 @@ using namespace ::com::sun::star::frame; namespace svt { + +struct DispatchInfo +{ + Reference< XDispatch > mxDispatch; + const URL maURL; + const Sequence< PropertyValue > maArgs; + + DispatchInfo( const Reference< XDispatch >& xDispatch, const URL& rURL, const Sequence< PropertyValue >& rArgs ) + : mxDispatch( xDispatch ), maURL( rURL ), maArgs( rArgs ) {} +}; + struct ToolboxController_Impl { ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > m_xParentWindow; ::com::sun::star::uno::Reference< ::com::sun::star::util::XURLTransformer > m_xUrlTransformer; + rtl::OUString m_sModuleName; + sal_uInt16 m_nToolBoxId; + + DECL_STATIC_LINK( ToolboxController_Impl, ExecuteHdl_Impl, DispatchInfo* ); + + ToolboxController_Impl() + : m_nToolBoxId( SAL_MAX_UINT16 ) + {} }; ToolboxController::ToolboxController( @@ -168,11 +187,6 @@ void SAL_CALL ToolboxController::release() throw () void SAL_CALL ToolboxController::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException ) { - const rtl::OUString aFrameName( RTL_CONSTASCII_USTRINGPARAM( "Frame" )); - const rtl::OUString aCommandURLName( RTL_CONSTASCII_USTRINGPARAM( "CommandURL" )); - const rtl::OUString aServiceManagerName( RTL_CONSTASCII_USTRINGPARAM( "ServiceManager" )); - const rtl::OUString aParentWindow( RTL_CONSTASCII_USTRINGPARAM( "ParentWindow" )); - bool bInitialized( true ); { @@ -194,14 +208,16 @@ throw ( Exception, RuntimeException ) { if ( aArguments[i] >>= aPropValue ) { - if ( aPropValue.Name.equalsAscii( "Frame" )) + if ( aPropValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Frame") )) m_xFrame.set(aPropValue.Value,UNO_QUERY); - else if ( aPropValue.Name.equalsAscii( "CommandURL" )) + else if ( aPropValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CommandURL") )) aPropValue.Value >>= m_aCommandURL; - else if ( aPropValue.Name.equalsAscii( "ServiceManager" )) + else if ( aPropValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("ServiceManager") )) m_xServiceManager.set(aPropValue.Value,UNO_QUERY); - else if ( aPropValue.Name.equalsAscii( "ParentWindow" )) + else if ( aPropValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("ParentWindow") )) m_pImpl->m_xParentWindow.set(aPropValue.Value,UNO_QUERY); + else if ( aPropValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("ModuleName" ) ) ) + aPropValue.Value >>= m_pImpl->m_sModuleName; } } @@ -707,6 +723,10 @@ Reference< ::com::sun::star::awt::XWindow > ToolboxController::getParent() const return m_pImpl->m_xParentWindow; } +const rtl::OUString& ToolboxController::getModuleName() const +{ + return m_pImpl->m_sModuleName; +} void ToolboxController::dispatchCommand( const OUString& sCommandURL, const Sequence< PropertyValue >& rArgs ) { @@ -718,11 +738,61 @@ void ToolboxController::dispatchCommand( const OUString& sCommandURL, const Sequ getURLTransformer()->parseStrict( aURL ); Reference< XDispatch > xDispatch( xDispatchProvider->queryDispatch( aURL, OUString(), 0 ), UNO_QUERY_THROW ); - xDispatch->dispatch( aURL, rArgs ); + + Application::PostUserEvent( STATIC_LINK(0, ToolboxController_Impl, ExecuteHdl_Impl), new DispatchInfo( xDispatch, aURL, rArgs ) ); + } catch( Exception& ) { } } +//-------------------------------------------------------------------- + +IMPL_STATIC_LINK_NOINSTANCE( ToolboxController_Impl, ExecuteHdl_Impl, DispatchInfo*, pDispatchInfo ) +{ + pDispatchInfo->mxDispatch->dispatch( pDispatchInfo->maURL, pDispatchInfo->maArgs ); + delete pDispatchInfo; + return 0; +} + +void ToolboxController::enable( bool bEnable ) +{ + ToolBox* pToolBox = 0; + sal_uInt16 nItemId = 0; + if( getToolboxId( nItemId, &pToolBox ) ) + { + pToolBox->EnableItem( nItemId, bEnable ? TRUE : FALSE ); + } +} + +bool ToolboxController::getToolboxId( sal_uInt16& rItemId, ToolBox** ppToolBox ) +{ + if( (m_pImpl->m_nToolBoxId != SAL_MAX_UINT16) && (ppToolBox == 0) ) + return m_pImpl->m_nToolBoxId; + + ToolBox* pToolBox = static_cast< ToolBox* >( VCLUnoHelper::GetWindow( getParent() ) ); + + if( (m_pImpl->m_nToolBoxId == SAL_MAX_UINT16) && pToolBox ) + { + const sal_uInt16 nCount = pToolBox->GetItemCount(); + for ( sal_uInt16 nPos = 0; nPos < nCount; ++nPos ) + { + const sal_uInt16 nItemId = pToolBox->GetItemId( nPos ); + if ( pToolBox->GetItemCommand( nItemId ) == String( m_aCommandURL ) ) + { + m_pImpl->m_nToolBoxId = nItemId; + break; + } + } + } + + if( ppToolBox ) + *ppToolBox = pToolBox; + + rItemId = m_pImpl->m_nToolBoxId; + + return (rItemId != SAL_MAX_UINT16) && (( ppToolBox == 0) || (*ppToolBox != 0) ); +} + } // svt From 43bd6eb856b003dcc31df1a5b7c612b53984868c Mon Sep 17 00:00:00 2001 From: Christian Lippka Date: Tue, 23 Mar 2010 13:35:44 +0100 Subject: [PATCH 07/18] fixing build problems on unix --- svtools/source/control/toolbarmenuimp.hxx | 2 ++ svtools/source/uno/popupwindowcontroller.cxx | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/svtools/source/control/toolbarmenuimp.hxx b/svtools/source/control/toolbarmenuimp.hxx index d1c574da4d33..c69944ec0999 100644 --- a/svtools/source/control/toolbarmenuimp.hxx +++ b/svtools/source/control/toolbarmenuimp.hxx @@ -227,7 +227,9 @@ public: virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) throw (::com::sun::star::uno::RuntimeException); // XAccessibleEventBroadcaster + using ToolbarMenuEntryAccBase::addEventListener; virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + using ToolbarMenuEntryAccBase::removeEventListener; virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); // XAccessibleContext diff --git a/svtools/source/uno/popupwindowcontroller.cxx b/svtools/source/uno/popupwindowcontroller.cxx index 9d5285250d20..d431dd7911a8 100644 --- a/svtools/source/uno/popupwindowcontroller.cxx +++ b/svtools/source/uno/popupwindowcontroller.cxx @@ -216,7 +216,7 @@ Reference< awt::XWindow > SAL_CALL PopupWindowController::createPopupWindow() th return Reference< awt::XWindow >(); } -Reference< awt::XWindow > SAL_CALL PopupWindowController::createItemWindow( const Reference< awt::XWindow >& Parent ) +Reference< awt::XWindow > SAL_CALL PopupWindowController::createItemWindow( const Reference< awt::XWindow >& /*Parent*/ ) throw (RuntimeException) { return Reference< awt::XWindow >(); From e95181408ebf1a010c9286e0059cccfeb6425619 Mon Sep 17 00:00:00 2001 From: Christian Lippka Date: Tue, 23 Mar 2010 13:56:35 +0100 Subject: [PATCH 08/18] adjusted spacing of menu items --- svtools/source/control/toolbarmenu.cxx | 101 ++++++++-------------- svtools/source/control/toolbarmenuimp.hxx | 4 +- 2 files changed, 39 insertions(+), 66 deletions(-) diff --git a/svtools/source/control/toolbarmenu.cxx b/svtools/source/control/toolbarmenu.cxx index a16f60bc5822..47c95ecb0038 100644 --- a/svtools/source/control/toolbarmenu.cxx +++ b/svtools/source/control/toolbarmenu.cxx @@ -591,102 +591,73 @@ Size ToolbarMenu::implCalcSize() Size aSz; Size aMaxImgSz; long nMaxTextWidth = 0; - long nMinMenuItemHeight = nFontHeight; + long nMinMenuItemHeight = nFontHeight+2; sal_Bool bCheckable = sal_False; const int nEntryCount = mpImpl->maEntryVector.size(); int nEntry; const StyleSettings& rSettings = GetSettings().GetStyleSettings(); - if ( rSettings.GetUseImagesInMenus() ) - { - nMinMenuItemHeight = 16; + 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(); - if ( aImgSz.Height() > aMaxImgSz.Height() ) - aMaxImgSz.Height() = aImgSz.Height(); - if ( aImgSz.Height() > nMinMenuItemHeight ) - nMinMenuItemHeight = aImgSz.Height(); - break; + Size aImgSz( pEntry->maImage.GetSizePixel() ); + nMinMenuItemHeight = std::max( nMinMenuItemHeight, aImgSz.Height() + 6 ); + aMaxImgSz.Width() = std::max( aMaxImgSz.Width(), aImgSz.Width() ); } } } - for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) - { - ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry]; - - if( pEntry ) - { - pEntry->maSize.Height() = 0; - pEntry->maSize.Width() = 0; - - - if ( ( pEntry->mnBits ) & ( MIB_RADIOCHECK | MIB_CHECKABLE ) ) - bCheckable = sal_True; - - // Image: - if( pEntry->mbHasImage ) - { - Size aImgSz = pEntry->maImage.GetSizePixel(); - if ( (aImgSz.Width() + 4) > aMaxImgSz.Width() ) - aMaxImgSz.Width() = aImgSz.Width() + 4; - if ( (aImgSz.Height() + 4) > aMaxImgSz.Height() ) - aMaxImgSz.Height() = aImgSz.Height() + 4; - if ( (aImgSz.Height() + 4) > pEntry->maSize.Height() ) - pEntry->maSize.Height() = aImgSz.Height() + 4; - } - } - } - - int gfxExtra = Max( nExtra, 7L ); - - if ( aMaxImgSz.Width() ) - mpImpl->mnTextPos += gfxExtra; - if ( bCheckable ) - mpImpl->mnTextPos += 16; - 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 ) { - // Text: - if( pEntry->mbHasText ) - { - long nTextWidth = GetCtrlTextWidth( pEntry->maText ) + mpImpl->mnTextPos; - nMaxTextWidth = Max( nTextWidth, nMaxTextWidth ); + if ( ( pEntry->mnBits ) & ( MIB_RADIOCHECK | MIB_CHECKABLE ) ) + bCheckable = sal_True; - pEntry->maSize.Height() = Max( Max( GetTextHeight(), pEntry->maSize.Height() ), nMinMenuItemHeight ); + // 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 = Max( aControlSize.Width(), nMaxTextWidth ); - pEntry->maSize.Height() = Max( aControlSize.Height(), pEntry->maSize.Height() ) + 1; + nMaxTextWidth = std::max( aControlSize.Width(), nMaxTextWidth ); + pEntry->maSize.Height() = aControlSize.Height() + 1; } - aSz.Height() += pEntry->maSize.Height(); - } - else - { - aSz.Height() += SEPARATOR_HEIGHT; + } } aSz.Width() = nMaxTextWidth + (BORDER_X<<1); - aSz.Height() += BORDER_Y<<1; // positionate controls int nY = BORDER_Y; @@ -696,12 +667,12 @@ Size ToolbarMenu::implCalcSize() if( pEntry ) { + pEntry->maSize.Width() = nMaxTextWidth; + if( pEntry->mpControl ) { Size aControlSize( pEntry->mpControl->GetOutputSizePixel() ); Point aControlPos( (aSz.Width() - aControlSize.Width())>>1, nY); - if( pEntry->mbHasText ) - aControlPos.X() += GetCtrlTextWidth( pEntry->maText ) + 4*gfxExtra; pEntry->mpControl->SetPosPixel( aControlPos ); @@ -720,6 +691,8 @@ Size ToolbarMenu::implCalcSize() } } + aSz.Height() += nY + BORDER_Y; + return aSz; } @@ -1415,10 +1388,10 @@ void ToolbarMenu::implPaint( ToolbarMenuEntry* pThisOnly, bool bHighlighted ) aTmpPos.Y() += (pEntry->maSize.Height()-pEntry->maImage.GetSizePixel().Height())/2; Rectangle aSelRect( aTmpPos, pEntry->maImage.GetSizePixel() ); - aSelRect.nLeft -= 2; - aSelRect.nTop -= 2; - aSelRect.nRight += 2; - aSelRect.nBottom += 2; + aSelRect.nLeft -= 1; + aSelRect.nTop -= 1; + aSelRect.nRight += 1; + aSelRect.nBottom += 1; DrawSelectionBackground( aSelRect, false, true, TRUE, TRUE ); } else diff --git a/svtools/source/control/toolbarmenuimp.hxx b/svtools/source/control/toolbarmenuimp.hxx index d1c574da4d33..9e30ac24666c 100644 --- a/svtools/source/control/toolbarmenuimp.hxx +++ b/svtools/source/control/toolbarmenuimp.hxx @@ -61,8 +61,8 @@ typedef std::vector< ToolbarMenuEntry * > ToolbarMenuEntryVector; const int EXTRAITEMHEIGHT = 0; // 4; const int SEPARATOR_HEIGHT = 4; const int TITLE_ID = -1; -const int BORDER_X = 0; -const int BORDER_Y = 0; +const int BORDER_X = 2; +const int BORDER_Y = 2; // -------------------- // - ToolbarMenuEntry - From f071b37411cf41a23d1364a37fc43135ca2dba85 Mon Sep 17 00:00:00 2001 From: Christian Lippka Date: Thu, 25 Mar 2010 12:29:31 +0100 Subject: [PATCH 09/18] reworked toolbar menu painting --- svtools/source/control/toolbarmenu.cxx | 423 ++++++++++++++++------ svtools/source/control/toolbarmenuimp.hxx | 10 +- 2 files changed, 312 insertions(+), 121 deletions(-) diff --git a/svtools/source/control/toolbarmenu.cxx b/svtools/source/control/toolbarmenu.cxx index 47c95ecb0038..bdd302f0839e 100644 --- a/svtools/source/control/toolbarmenu.cxx +++ b/svtools/source/control/toolbarmenu.cxx @@ -83,7 +83,6 @@ void ToolbarMenuEntry::init( int nEntryId, MenuItemBits nBits ) mbHasText = false; mbHasImage = false; - mbHasControl = false; mbChecked = false; mbEnabled = true; @@ -896,51 +895,84 @@ static void implDeselectControl( Control* pControl ) void ToolbarMenu::implHighlightEntry( int nHighlightEntry, bool bHighlight ) { - Size aSz = GetOutputSizePixel(); - long nY = BORDER_Y; - long nX = BORDER_X; + Size aSz( GetOutputSizePixel() ); + long nX = 0, nY = 0; const int nEntryCount = mpImpl->maEntryVector.size(); int nEntry; for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) { - ToolbarMenuEntry* p = mpImpl->maEntryVector[nEntry]; - if( p ) + ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry]; + if( pEntry && (nEntry == nHighlightEntry) ) { - if(nEntry == nHighlightEntry) - { - if( p->mpControl == NULL ) - { - Rectangle aRect( Point( nX, nY ), Size( aSz.Width()-(BORDER_X<<1), p->maSize.Height() ) ); - SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() ); - SetLineColor(); - DrawRect( aRect ); + // no highlights for controls only items + if( pEntry->mpControl ) + break; - if( bHighlight ) + 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, + Region( aCtrlRect ), + CTRL_STATE_ENABLED, + ImplControlValue(), + OUString() ); + if( bHighlight && IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM ) ) + { + bDrawItemRect = false; + if( FALSE == DrawNativeControl( CTRL_MENU_POPUP, PART_MENU_ITEM, + Region( aItemRect ), + CTRL_STATE_SELECTED | ( pEntry->mbEnabled? CTRL_STATE_ENABLED: 0 ), + ImplControlValue(), + OUString() ) ) { - aRect.nLeft += 1; - aRect.nTop += 1; - aRect.nBottom -= 1; - aRect.nRight -= 1; - DrawSelectionBackground( aRect, true, false, TRUE, TRUE ); + bDrawItemRect = bHighlight; } } else - { - if( !bHighlight ) - implDeselectControl( p->mpControl ); - } - - implPaint( p, bHighlight ); - break; + 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() ); - nY += p->maSize.Height(); - } - else - { - nY += SEPARATOR_HEIGHT; + DrawRect( aItemRect ); + } + implPaint( pEntry, bHighlight ); + if( bRestoreLineColor ) + SetLineColor( oldLineColor ); + break; } + + nY += pEntry ? pEntry->maSize.Height() : SEPARATOR_HEIGHT; } } @@ -1281,68 +1313,146 @@ void ToolbarMenu::KeyInput( const KeyEvent& rKEvent ) } // -------------------------------------------------------------------- +static void ImplPaintCheckBackground( Window* i_pWindow, const Rectangle& i_rRect, bool i_bHighlight ) +{ + BOOL bNativeOk = FALSE; + if( i_pWindow->IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) ) + { + ImplControlValue aControlValue; + Region aCtrlRegion( i_rRect ); + ControlState nState = CTRL_STATE_PRESSED | CTRL_STATE_ENABLED; + + aControlValue.setTristateVal( BUTTONVALUE_ON ); + + bNativeOk = i_pWindow->DrawNativeControl( CTRL_TOOLBAR, PART_BUTTON, + aCtrlRegion, 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, TRUE, FALSE, 2, NULL, &aColor ); + } +} + +static long ImplGetNativeCheckAndRadioSize( Window* pWin, long& rCheckHeight, long& rRadioHeight, long &rMaxWidth ) +{ + rMaxWidth = rCheckHeight = rRadioHeight = 0; + + ImplControlValue aVal; + Region aNativeBounds; + Region aNativeContent; + Point tmp( 0, 0 ); + Region aCtrlRegion( Rectangle( 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.GetBoundRect().GetHeight(); + rMaxWidth = aNativeContent.GetBoundRect().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.GetBoundRect().GetHeight(); + rMaxWidth = Max (rMaxWidth, aNativeContent.GetBoundRect().GetWidth()); + } + } + return (rCheckHeight > rRadioHeight) ? rCheckHeight : rRadioHeight; +} void ToolbarMenu::implPaint( ToolbarMenuEntry* pThisOnly, bool bHighlighted ) { - const long nFontHeight = GetTextHeight(); - const long nExtra = nFontHeight/4; + USHORT 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 Size aOutSz( GetOutputSizePixel() ); - - Point aTopLeft( BORDER_X, BORDER_Y ), aTmpPos; + 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; - USHORT nTextStyle = 0; - USHORT nSymbolStyle = 0; - USHORT nImageStyle = 0; - if( pEntry && !pEntry->mbEnabled ) + + if( (pEntry == 0) && !pThisOnly ) { - nTextStyle |= TEXT_DRAW_DISABLE; - nSymbolStyle |= SYMBOL_DRAW_DISABLE; - nImageStyle |= IMAGE_DRAW_DISABLE; + // 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(); } - - // Separator - if( pEntry == NULL ) + else if( !pThisOnly || ( pEntry == pThisOnly ) ) { - if( pThisOnly == NULL ) + const bool bTitle = pEntry->mnEntryId == TITLE_ID; + + if ( pThisOnly && bHighlighted ) + SetTextColor( rSettings.GetMenuHighlightTextColor() ); + + if( aPos.Y() >= 0 ) { - aTmpPos.Y() = aPos.Y() + ((SEPARATOR_HEIGHT-2)/2); + long nTextOffsetY = ((pEntry->maSize.Height()-nFontHeight)/2); - SetLineColor( rSettings.GetShadowColor() ); - DrawLine( aTmpPos, Point( aOutSz.Width() - 3, aTmpPos.Y() ) ); - aTmpPos.Y()++; - SetLineColor( rSettings.GetLightColor() ); - DrawLine( aTmpPos, Point( aOutSz.Width() - 3, aTmpPos.Y() ) ); - SetLineColor(); - } + USHORT nTextStyle = 0; + USHORT nSymbolStyle = 0; + USHORT nImageStyle = 0; - aTopLeft.Y() += SEPARATOR_HEIGHT; - } - else - { - if( !pThisOnly || ( pEntry == pThisOnly ) ) - { - const bool bTitle = pEntry->mnEntryId == TITLE_ID; + if( !pEntry->mbEnabled ) + { + nTextStyle |= TEXT_DRAW_DISABLE; + nSymbolStyle |= SYMBOL_DRAW_DISABLE; + nImageStyle |= IMAGE_DRAW_DISABLE; + } - if( pThisOnly && bHighlighted ) - SetTextColor( rSettings.GetMenuHighlightTextColor() ); - else - SetTextColor( rSettings.GetMenuTextColor() ); + 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; - Rectangle aRect( aTopLeft, Size( aOutSz.Width(), pEntry->maSize.Height() ) ); if( bTitle ) { // fill the background + Rectangle aRect( aTopLeft, Size( aOutSz.Width(), pEntry->maSize.Height() ) ); SetFillColor(rSettings.GetDialogColor()); SetLineColor(); DrawRect(aRect); @@ -1351,22 +1461,84 @@ void ToolbarMenu::implPaint( ToolbarMenuEntry* pThisOnly, bool bHighlighted ) SetLineColor( rSettings.GetShadowColor() ); DrawLine( aRect.BottomLeft(), aRect.BottomRight() ); } - else if( pEntry->mpControl ) + + // CheckMark + if ( pEntry->HasCheck() ) { - SetLineColor( rSettings.GetShadowColor() ); - DrawLine( aRect.BottomLeft(), aRect.BottomRight() ); + // 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, Region( 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 ); + } + } } - long nTextOffsetY = ((pEntry->maSize.Height()-nFontHeight)/2); - - // Image + // Image: if( pEntry->mbHasImage ) { - aTmpPos.X() = aPos.X() + mpImpl->mnImagePos; - aTmpPos.Y() = aPos.Y(); - aTmpPos.Y() += (pEntry->maSize.Height()-pEntry->maImage.GetSizePixel().Height())/2; - DrawImage( aTmpPos, pEntry->maImage, nImageStyle ); + // 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 ) { @@ -1375,53 +1547,66 @@ void ToolbarMenu::implPaint( ToolbarMenuEntry* pThisOnly, bool bHighlighted ) aTmpPos.Y() += nTextOffsetY; USHORT nStyle = nTextStyle|TEXT_DRAW_MNEMONIC; - DrawCtrlText( aTmpPos, pEntry->maText, 0, pEntry->maText.Len(), nStyle ); + DrawCtrlText( aTmpPos, pEntry->maText, 0, pEntry->maText.Len(), nStyle, NULL, NULL ); // pVector, pDisplayText ); } - // CheckMark - if( pEntry->mbChecked ) +/* + // Accel + if ( !bLayout && !bIsMenuBar && pData->aAccelKey.GetCode() && !ImplAccelDisabled() ) { - if( pEntry->mbHasImage ) - { - aTmpPos.X() = aPos.X() + mpImpl->mnImagePos; - aTmpPos.Y() = aPos.Y(); - aTmpPos.Y() += (pEntry->maSize.Height()-pEntry->maImage.GetSizePixel().Height())/2; + XubString aAccText = pData->aAccelKey.GetName(); + aTmpPos.X() = aOutSz.Width() - this->GetTextWidth( aAccText ); + aTmpPos.X() -= 4*nExtra; - Rectangle aSelRect( aTmpPos, pEntry->maImage.GetSizePixel() ); - aSelRect.nLeft -= 1; - aSelRect.nTop -= 1; - aSelRect.nRight += 1; - aSelRect.nBottom += 1; - DrawSelectionBackground( aSelRect, false, true, TRUE, TRUE ); - } - else - { - Rectangle aSelRect; - SymbolType eSymbol; - aTmpPos.Y() = aPos.Y(); - aTmpPos.Y() += nExtra/2; - aTmpPos.Y() += pEntry->maSize.Height() / 2; - if ( pEntry->mnBits & MIB_RADIOCHECK ) - { - aTmpPos.X() = aPos.X() + mpImpl->mnCheckPos; - eSymbol = SYMBOL_RADIOCHECKMARK; - aTmpPos.Y() -= nFontHeight/4; - aSelRect = Rectangle( aTmpPos, Size( nFontHeight/2, nFontHeight/2 ) ); - } - else - { - aTmpPos.X() = aPos.X() + mpImpl->mnCheckPos; - eSymbol = SYMBOL_CHECKMARK; - aTmpPos.Y() -= nFontHeight/4; - aSelRect = Rectangle( aTmpPos, Size( (nFontHeight*25)/40, nFontHeight/2 ) ); - } - aDecoView.DrawSymbol( aSelRect, eSymbol, GetTextColor(), nSymbolStyle ); - } + aTmpPos.X() -= nOuterSpace; + aTmpPos.Y() = aPos.Y(); + aTmpPos.Y() += nTextOffsetY; + this->DrawCtrlText( aTmpPos, aAccText, 0, aAccText.Len(), nTextStyle ); } - } +*/ - aTopLeft.Y() += pEntry->maSize.Height(); +/* + // 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; } } @@ -1429,6 +1614,8 @@ void ToolbarMenu::implPaint( ToolbarMenuEntry* pThisOnly, bool bHighlighted ) void ToolbarMenu::Paint( const Rectangle& ) { + SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() ); + implPaint(); if( mpImpl->mnHighlightedEntry != -1 ) diff --git a/svtools/source/control/toolbarmenuimp.hxx b/svtools/source/control/toolbarmenuimp.hxx index 94215fc96681..1d9037b61dc5 100644 --- a/svtools/source/control/toolbarmenuimp.hxx +++ b/svtools/source/control/toolbarmenuimp.hxx @@ -61,8 +61,8 @@ typedef std::vector< ToolbarMenuEntry * > ToolbarMenuEntryVector; const int EXTRAITEMHEIGHT = 0; // 4; const int SEPARATOR_HEIGHT = 4; const int TITLE_ID = -1; -const int BORDER_X = 2; -const int BORDER_Y = 2; +const int BORDER_X = 0; +const int BORDER_Y = 0; // -------------------- // - ToolbarMenuEntry - @@ -79,7 +79,6 @@ public: bool mbHasText; bool mbHasImage; - bool mbHasControl; bool mbChecked; bool mbEnabled; @@ -104,6 +103,11 @@ public: sal_Int32 getAccessibleChildCount() throw (::com::sun::star::uno::RuntimeException); ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > getAccessibleChild( sal_Int32 index ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); void selectAccessibleChild( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + + bool HasCheck() const + { + return mbChecked || ( mnBits & ( MIB_RADIOCHECK | MIB_CHECKABLE | MIB_AUTOCHECK ) ); + } }; // --------------- From c08d3ab80afcf5e483ed3aa0b9255939e3013514 Mon Sep 17 00:00:00 2001 From: Christian Lippka Date: Thu, 25 Mar 2010 13:20:29 +0100 Subject: [PATCH 10/18] fixed unix compile warning --- svtools/source/control/toolbarmenu.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/svtools/source/control/toolbarmenu.cxx b/svtools/source/control/toolbarmenu.cxx index bdd302f0839e..65bcaf63a912 100644 --- a/svtools/source/control/toolbarmenu.cxx +++ b/svtools/source/control/toolbarmenu.cxx @@ -1386,7 +1386,7 @@ void ToolbarMenu::implPaint( ToolbarMenuEntry* pThisOnly, bool bHighlighted ) USHORT 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 nExtra = nFontHeight/4; long nCheckHeight = 0, nRadioHeight = 0, nMaxCheckWidth = 0; ImplGetNativeCheckAndRadioSize( this, nCheckHeight, nRadioHeight, nMaxCheckWidth ); From 2b9102ab6fbbd9c681ff4db2b31076210d04ba55 Mon Sep 17 00:00:00 2001 From: Christian Lippka Date: Fri, 26 Mar 2010 15:38:07 +0100 Subject: [PATCH 11/18] removed unused code --- svtools/source/control/toolbarmenu.cxx | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/svtools/source/control/toolbarmenu.cxx b/svtools/source/control/toolbarmenu.cxx index 65bcaf63a912..5c93f730a02f 100644 --- a/svtools/source/control/toolbarmenu.cxx +++ b/svtools/source/control/toolbarmenu.cxx @@ -881,18 +881,6 @@ ToolbarMenuEntry* ToolbarMenu::implSearchEntry( int nEntryId ) const // -------------------------------------------------------------------- -static void implDeselectControl( Control* pControl ) -{ - ValueSet* pValueSet = dynamic_cast< ValueSet* >( pControl ); - if( pValueSet ) - { - pValueSet->SetNoSelection(); - pValueSet->Invalidate(); - } -} - -// -------------------------------------------------------------------- - void ToolbarMenu::implHighlightEntry( int nHighlightEntry, bool bHighlight ) { Size aSz( GetOutputSizePixel() ); From 919bcccd3267e1e6537d7ef93bf333d2fe934c4b Mon Sep 17 00:00:00 2001 From: Christian Lippka Date: Tue, 30 Mar 2010 10:07:55 +0200 Subject: [PATCH 12/18] fixed compile warnings --- svtools/inc/svtools/popupmenucontrollerbase.hxx | 2 +- svtools/source/control/toolbarmenu.cxx | 2 +- svtools/source/uno/popupmenucontrollerbase.cxx | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/svtools/inc/svtools/popupmenucontrollerbase.hxx b/svtools/inc/svtools/popupmenucontrollerbase.hxx index 706ce076be02..b062234a512e 100644 --- a/svtools/inc/svtools/popupmenucontrollerbase.hxx +++ b/svtools/inc/svtools/popupmenucontrollerbase.hxx @@ -58,7 +58,7 @@ namespace svt { struct PopupMenuControllerBaseDispatchInfo; - typedef public ::cppu::WeakComponentImplHelper7< + typedef ::cppu::WeakComponentImplHelper7< com::sun::star::lang::XServiceInfo , com::sun::star::frame::XPopupMenuController , com::sun::star::lang::XInitialization , diff --git a/svtools/source/control/toolbarmenu.cxx b/svtools/source/control/toolbarmenu.cxx index 5c93f730a02f..bb332c77cc49 100644 --- a/svtools/source/control/toolbarmenu.cxx +++ b/svtools/source/control/toolbarmenu.cxx @@ -268,7 +268,7 @@ sal_Int32 ToolbarMenu_Impl::getAccessibleChildCount() throw (RuntimeException) for( int nEntry = 0; nEntry < nEntryCount; nEntry++ ) { ToolbarMenuEntry* pEntry = maEntryVector[nEntry]; - if( pEntry ); + if( pEntry ) { if( pEntry->mpControl ) { diff --git a/svtools/source/uno/popupmenucontrollerbase.cxx b/svtools/source/uno/popupmenucontrollerbase.cxx index 457207d317b4..ac75a1b9a24b 100644 --- a/svtools/source/uno/popupmenucontrollerbase.cxx +++ b/svtools/source/uno/popupmenucontrollerbase.cxx @@ -122,7 +122,6 @@ void PopupMenuControllerBase::resetPopupMenu( com::sun::star::uno::Reference< co } void SAL_CALL PopupMenuControllerBase::disposing() -throw (::com::sun::star::uno::RuntimeException) { // Reset our members and set disposed flag osl::MutexGuard aLock( m_aMutex ); From 61604da6e03327792dded05f18afd8cae35cf8c1 Mon Sep 17 00:00:00 2001 From: Christian Lippka Date: Mon, 19 Apr 2010 17:46:40 +0200 Subject: [PATCH 13/18] do not show icons in menu if this is disabled --- svtools/source/control/asynclink.cxx | 0 svtools/source/control/calendar.cxx | 0 svtools/source/control/calendar.src | 0 svtools/source/control/collatorres.cxx | 0 svtools/source/control/ctrlbox.cxx | 0 svtools/source/control/ctrlbox.src | 0 svtools/source/control/ctrldll.cxx | 0 svtools/source/control/ctrltool.cxx | 0 svtools/source/control/ctrltool.src | 0 svtools/source/control/filectrl.cxx | 0 svtools/source/control/filectrl.src | 0 svtools/source/control/filectrl2.cxx | 0 svtools/source/control/fileurlbox.cxx | 0 svtools/source/control/fixedhyper.cxx | 0 svtools/source/control/fmtfield.cxx | 0 svtools/source/control/headbar.cxx | 0 svtools/source/control/hyperlabel.cxx | 0 svtools/source/control/indexentryres.cxx | 0 svtools/source/control/inettbc.cxx | 0 svtools/source/control/makefile.mk | 0 svtools/source/control/prgsbar.cxx | 0 svtools/source/control/roadmap.cxx | 0 svtools/source/control/ruler.cxx | 0 svtools/source/control/scriptedtext.cxx | 0 svtools/source/control/scrwin.cxx | 0 svtools/source/control/stdctrl.cxx | 0 svtools/source/control/stdmenu.cxx | 0 svtools/source/control/svxbox.cxx | 0 svtools/source/control/tabbar.cxx | 0 svtools/source/control/taskbar.cxx | 0 svtools/source/control/taskbox.cxx | 0 svtools/source/control/taskmisc.cxx | 0 svtools/source/control/taskstat.cxx | 0 svtools/source/control/toolbarmenu.cxx | 3 ++- svtools/source/control/toolbarmenuacc.cxx | 0 svtools/source/control/toolbarmenuimp.hxx | 0 svtools/source/control/urlcontrol.cxx | 0 svtools/source/control/valueacc.cxx | 0 svtools/source/control/valueimp.hxx | 0 svtools/source/control/valueset.cxx | 0 40 files changed, 2 insertions(+), 1 deletion(-) mode change 100644 => 100755 svtools/source/control/asynclink.cxx mode change 100644 => 100755 svtools/source/control/calendar.cxx mode change 100644 => 100755 svtools/source/control/calendar.src mode change 100644 => 100755 svtools/source/control/collatorres.cxx mode change 100644 => 100755 svtools/source/control/ctrlbox.cxx mode change 100644 => 100755 svtools/source/control/ctrlbox.src mode change 100644 => 100755 svtools/source/control/ctrldll.cxx mode change 100644 => 100755 svtools/source/control/ctrltool.cxx mode change 100644 => 100755 svtools/source/control/ctrltool.src mode change 100644 => 100755 svtools/source/control/filectrl.cxx mode change 100644 => 100755 svtools/source/control/filectrl.src mode change 100644 => 100755 svtools/source/control/filectrl2.cxx mode change 100644 => 100755 svtools/source/control/fileurlbox.cxx mode change 100644 => 100755 svtools/source/control/fixedhyper.cxx mode change 100644 => 100755 svtools/source/control/fmtfield.cxx mode change 100644 => 100755 svtools/source/control/headbar.cxx mode change 100644 => 100755 svtools/source/control/hyperlabel.cxx mode change 100644 => 100755 svtools/source/control/indexentryres.cxx mode change 100644 => 100755 svtools/source/control/inettbc.cxx mode change 100644 => 100755 svtools/source/control/makefile.mk mode change 100644 => 100755 svtools/source/control/prgsbar.cxx mode change 100644 => 100755 svtools/source/control/roadmap.cxx mode change 100644 => 100755 svtools/source/control/ruler.cxx mode change 100644 => 100755 svtools/source/control/scriptedtext.cxx mode change 100644 => 100755 svtools/source/control/scrwin.cxx mode change 100644 => 100755 svtools/source/control/stdctrl.cxx mode change 100644 => 100755 svtools/source/control/stdmenu.cxx mode change 100644 => 100755 svtools/source/control/svxbox.cxx mode change 100644 => 100755 svtools/source/control/tabbar.cxx mode change 100644 => 100755 svtools/source/control/taskbar.cxx mode change 100644 => 100755 svtools/source/control/taskbox.cxx mode change 100644 => 100755 svtools/source/control/taskmisc.cxx mode change 100644 => 100755 svtools/source/control/taskstat.cxx mode change 100644 => 100755 svtools/source/control/toolbarmenuacc.cxx mode change 100644 => 100755 svtools/source/control/toolbarmenuimp.hxx mode change 100644 => 100755 svtools/source/control/urlcontrol.cxx mode change 100644 => 100755 svtools/source/control/valueacc.cxx mode change 100644 => 100755 svtools/source/control/valueimp.hxx mode change 100644 => 100755 svtools/source/control/valueset.cxx diff --git a/svtools/source/control/asynclink.cxx b/svtools/source/control/asynclink.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/calendar.cxx b/svtools/source/control/calendar.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/calendar.src b/svtools/source/control/calendar.src old mode 100644 new mode 100755 diff --git a/svtools/source/control/collatorres.cxx b/svtools/source/control/collatorres.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/ctrlbox.cxx b/svtools/source/control/ctrlbox.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/ctrlbox.src b/svtools/source/control/ctrlbox.src old mode 100644 new mode 100755 diff --git a/svtools/source/control/ctrldll.cxx b/svtools/source/control/ctrldll.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/ctrltool.cxx b/svtools/source/control/ctrltool.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/ctrltool.src b/svtools/source/control/ctrltool.src old mode 100644 new mode 100755 diff --git a/svtools/source/control/filectrl.cxx b/svtools/source/control/filectrl.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/filectrl.src b/svtools/source/control/filectrl.src old mode 100644 new mode 100755 diff --git a/svtools/source/control/filectrl2.cxx b/svtools/source/control/filectrl2.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/fileurlbox.cxx b/svtools/source/control/fileurlbox.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/fixedhyper.cxx b/svtools/source/control/fixedhyper.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/fmtfield.cxx b/svtools/source/control/fmtfield.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/headbar.cxx b/svtools/source/control/headbar.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/hyperlabel.cxx b/svtools/source/control/hyperlabel.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/indexentryres.cxx b/svtools/source/control/indexentryres.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/inettbc.cxx b/svtools/source/control/inettbc.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/makefile.mk b/svtools/source/control/makefile.mk old mode 100644 new mode 100755 diff --git a/svtools/source/control/prgsbar.cxx b/svtools/source/control/prgsbar.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/roadmap.cxx b/svtools/source/control/roadmap.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/ruler.cxx b/svtools/source/control/ruler.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/scriptedtext.cxx b/svtools/source/control/scriptedtext.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/scrwin.cxx b/svtools/source/control/scrwin.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/stdctrl.cxx b/svtools/source/control/stdctrl.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/stdmenu.cxx b/svtools/source/control/stdmenu.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/svxbox.cxx b/svtools/source/control/svxbox.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/tabbar.cxx b/svtools/source/control/tabbar.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/taskbar.cxx b/svtools/source/control/taskbar.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/taskbox.cxx b/svtools/source/control/taskbox.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/taskmisc.cxx b/svtools/source/control/taskmisc.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/taskstat.cxx b/svtools/source/control/taskstat.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/toolbarmenu.cxx b/svtools/source/control/toolbarmenu.cxx index bb332c77cc49..6a6edcc41f57 100644 --- a/svtools/source/control/toolbarmenu.cxx +++ b/svtools/source/control/toolbarmenu.cxx @@ -1381,6 +1381,7 @@ void ToolbarMenu::implPaint( ToolbarMenuEntry* pThisOnly, bool bHighlighted ) DecorationView aDecoView( this ); const StyleSettings& rSettings = GetSettings().GetStyleSettings(); + const bool bUseImages = rSettings.GetUseImagesInMenus(); int nOuterSpace = 0; // ImplGetSVData()->maNWFData.mnMenuFormatExtraBorder; Point aTopLeft( nOuterSpace, nOuterSpace ), aTmpPos; @@ -1513,7 +1514,7 @@ void ToolbarMenu::implPaint( ToolbarMenuEntry* pThisOnly, bool bHighlighted ) } // Image: - if( pEntry->mbHasImage ) + if( pEntry->mbHasImage && bUseImages ) { // Don't render an image for a check thing /* if((nMenuFlags & MENU_FLAG_SHOWCHECKIMAGES) || !pEntry->HasCheck() )*/ diff --git a/svtools/source/control/toolbarmenuacc.cxx b/svtools/source/control/toolbarmenuacc.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/toolbarmenuimp.hxx b/svtools/source/control/toolbarmenuimp.hxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/urlcontrol.cxx b/svtools/source/control/urlcontrol.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/valueacc.cxx b/svtools/source/control/valueacc.cxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/valueimp.hxx b/svtools/source/control/valueimp.hxx old mode 100644 new mode 100755 diff --git a/svtools/source/control/valueset.cxx b/svtools/source/control/valueset.cxx old mode 100644 new mode 100755 From b11f2df4d42f03c896b09b5c93ca4fcb63a407b9 Mon Sep 17 00:00:00 2001 From: Christian Lippka Date: Tue, 27 Apr 2010 13:30:46 +0200 Subject: [PATCH 14/18] #i107213# notify a11y api if a toolbar popup window is opened --- svtools/source/control/toolbarmenu.cxx | 1 + svtools/source/uno/popupwindowcontroller.cxx | 36 +++++++++++++++++--- vcl/inc/vcl/window.hxx | 4 +++ 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/svtools/source/control/toolbarmenu.cxx b/svtools/source/control/toolbarmenu.cxx index 6a6edcc41f57..3a3c8bb885ab 100644 --- a/svtools/source/control/toolbarmenu.cxx +++ b/svtools/source/control/toolbarmenu.cxx @@ -36,6 +36,7 @@ #include #include #include +#include #include "svtools/valueset.hxx" #include "svtools/toolbarmenu.hxx" diff --git a/svtools/source/uno/popupwindowcontroller.cxx b/svtools/source/uno/popupwindowcontroller.cxx index d431dd7911a8..97f03ba3320a 100644 --- a/svtools/source/uno/popupwindowcontroller.cxx +++ b/svtools/source/uno/popupwindowcontroller.cxx @@ -50,27 +50,29 @@ public: PopupWindowControllerImpl(); ~PopupWindowControllerImpl(); - void SetPopupWindow( ::Window* pPopupWindow ); + void SetPopupWindow( ::Window* pPopupWindow, ToolBox* pToolBox ); DECL_LINK( WindowEventListener, VclSimpleEvent* ); DECL_STATIC_LINK( PopupWindowControllerImpl, AsyncDeleteWindowHdl, Window* ); private: ::Window* mpPopupWindow; + ToolBox* mpToolBox; }; PopupWindowControllerImpl::PopupWindowControllerImpl() : mpPopupWindow( 0 ) +, mpToolBox( 0 ) { } PopupWindowControllerImpl::~PopupWindowControllerImpl() { if( mpPopupWindow ) - SetPopupWindow(0); + SetPopupWindow(0,0); } -void PopupWindowControllerImpl::SetPopupWindow( ::Window* pPopupWindow ) +void PopupWindowControllerImpl::SetPopupWindow( ::Window* pPopupWindow, ToolBox* pToolBox ) { if( mpPopupWindow ) { @@ -78,6 +80,8 @@ void PopupWindowControllerImpl::SetPopupWindow( ::Window* pPopupWindow ) Application::PostUserEvent( STATIC_LINK( this, PopupWindowControllerImpl, AsyncDeleteWindowHdl ), mpPopupWindow ); } mpPopupWindow = pPopupWindow; + mpToolBox = pToolBox; + if( mpPopupWindow ) { mpPopupWindow->AddEventListener( LINK( this, PopupWindowControllerImpl, WindowEventListener )); @@ -93,8 +97,30 @@ IMPL_LINK( PopupWindowControllerImpl, WindowEventListener, VclSimpleEvent*, pEve { case VCLEVENT_WINDOW_CLOSE: case VCLEVENT_WINDOW_ENDPOPUPMODE: - SetPopupWindow(0); + SetPopupWindow(0,0); break; + + case VCLEVENT_WINDOW_SHOW: + { + if( mpPopupWindow ) + { + if( mpToolBox ) + mpToolBox->CallEventListeners( VCLEVENT_DROPDOWN_OPEN, (void*)mpPopupWindow ); + mpPopupWindow->CallEventListeners( VCLEVENT_WINDOW_GETFOCUS, 0 ); + break; + } + break; + } + case VCLEVENT_WINDOW_HIDE: + { + if( mpPopupWindow ) + { + mpPopupWindow->CallEventListeners( VCLEVENT_WINDOW_LOSEFOCUS, 0 ); + if( mpToolBox ) + mpToolBox->CallEventListeners( VCLEVENT_DROPDOWN_CLOSE, (void*)mpPopupWindow ); + } + break; + } } } return 1; @@ -209,7 +235,7 @@ Reference< awt::XWindow > SAL_CALL PopupWindowController::createPopupWindow() th if( pWin ) { pWin->EnableDocking(true); - mpImpl->SetPopupWindow(pWin); + mpImpl->SetPopupWindow(pWin,pToolBox); ::Window::GetDockingManager()->StartPopupMode( pToolBox, pWin, FLOATWIN_POPUPMODE_NOFOCUSCLOSE|FLOATWIN_POPUPMODE_ALLMOUSEBUTTONCLOSE |FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE ); } } diff --git a/vcl/inc/vcl/window.hxx b/vcl/inc/vcl/window.hxx index 3d1cc91ee468..66f67ec4ac92 100644 --- a/vcl/inc/vcl/window.hxx +++ b/vcl/inc/vcl/window.hxx @@ -124,6 +124,8 @@ namespace dnd { namespace vcl { struct ControlLayoutData; } +namespace svt { class PopupWindowControllerImpl; } + // --------------- // - WindowTypes - // --------------- @@ -362,6 +364,8 @@ class VCL_DLLPUBLIC Window : public OutputDevice friend class ImplPopupFloatWin; friend class MenuFloatingWindow; + friend class svt::PopupWindowControllerImpl; + private: // NOTE: to remove many dependencies of other modules // to this central file, all members are now hidden From d282c98c9218f4abbd815d5309e3449045a366e3 Mon Sep 17 00:00:00 2001 From: Christian Lippka Date: Wed, 28 Apr 2010 13:42:24 +0200 Subject: [PATCH 15/18] #i107213# use toolbox item window as parent for popup menu --- svtools/source/control/valueacc.cxx | 2 +- svtools/source/uno/popupwindowcontroller.cxx | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/svtools/source/control/valueacc.cxx b/svtools/source/control/valueacc.cxx index 6712e75aa9b4..52fa40fcf00e 100755 --- a/svtools/source/control/valueacc.cxx +++ b/svtools/source/control/valueacc.cxx @@ -1239,7 +1239,7 @@ sal_Int32 SAL_CALL ValueItemAcc::getBackground( ) throw (uno::RuntimeException) { UINT32 nColor; - if (mpParent->meType == VALUESETITEM_COLOR) + if (mpParent && mpParent->meType == VALUESETITEM_COLOR) nColor = mpParent->maColor.GetColor(); else nColor = Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor(); diff --git a/svtools/source/uno/popupwindowcontroller.cxx b/svtools/source/uno/popupwindowcontroller.cxx index 97f03ba3320a..52a636017806 100644 --- a/svtools/source/uno/popupwindowcontroller.cxx +++ b/svtools/source/uno/popupwindowcontroller.cxx @@ -231,7 +231,8 @@ Reference< awt::XWindow > SAL_CALL PopupWindowController::createPopupWindow() th ToolBox* pToolBox = dynamic_cast< ToolBox* >( VCLUnoHelper::GetWindow( getParent() ) ); if( pToolBox ) { - ::Window* pWin = createPopupWindow(pToolBox); + ::Window* pItemWindow = pToolBox->GetItemWindow( pToolBox->GetDownItemId() ); + ::Window* pWin = createPopupWindow( pItemWindow ? pItemWindow : pToolBox ); if( pWin ) { pWin->EnableDocking(true); From d22c384fac4fbf9977010da0b1348c1ab9d565e8 Mon Sep 17 00:00:00 2001 From: Christian Lippka Date: Wed, 28 Apr 2010 16:04:47 +0200 Subject: [PATCH 16/18] #i107213# possible solution for the missing a11y focus --- svtools/source/control/toolbarmenu.cxx | 8 --- svtools/source/control/toolbarmenuacc.cxx | 87 ++++++++++++++++++----- svtools/source/control/toolbarmenuimp.hxx | 16 ++--- 3 files changed, 74 insertions(+), 37 deletions(-) diff --git a/svtools/source/control/toolbarmenu.cxx b/svtools/source/control/toolbarmenu.cxx index 3a3c8bb885ab..6f7be376266e 100644 --- a/svtools/source/control/toolbarmenu.cxx +++ b/svtools/source/control/toolbarmenu.cxx @@ -704,10 +704,6 @@ void ToolbarMenu::GetFocus() implChangeHighlightEntry( 0 ); DockingWindow::GetFocus(); - - // Tell the accessible object that we got the focus. - if( mpImpl->mxAccessible.is() ) - mpImpl->mxAccessible->GetFocus(); } // -------------------------------------------------------------------- @@ -718,10 +714,6 @@ void ToolbarMenu::LoseFocus() implChangeHighlightEntry( -1 ); DockingWindow::LoseFocus(); - - // Tell the accessible object that we lost the focus. - if( mpImpl->mxAccessible.is() ) - mpImpl->mxAccessible->LoseFocus(); } // -------------------------------------------------------------------- diff --git a/svtools/source/control/toolbarmenuacc.cxx b/svtools/source/control/toolbarmenuacc.cxx index 702c1f72b83d..f227a4cb2558 100755 --- a/svtools/source/control/toolbarmenuacc.cxx +++ b/svtools/source/control/toolbarmenuacc.cxx @@ -58,12 +58,81 @@ ToolbarMenuAcc::ToolbarMenuAcc( ToolbarMenu_Impl& rParent ) , mpParent( &rParent ) , mbIsFocused(false) { + mpParent->mrMenu.AddEventListener( LINK( this, ToolbarMenuAcc, WindowEventListener ) ); } // ----------------------------------------------------------------------------- ToolbarMenuAcc::~ToolbarMenuAcc() { + if( mpParent ) + mpParent->mrMenu.RemoveEventListener( LINK( this, ToolbarMenuAcc, WindowEventListener ) ); +} + +// ----------------------------------------------------------------------- + +IMPL_LINK( ToolbarMenuAcc, WindowEventListener, VclSimpleEvent*, pEvent ) +{ + DBG_ASSERT( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" ); + + /* Ignore VCLEVENT_WINDOW_ENDPOPUPMODE, because the UNO accessibility wrapper + * might have been destroyed by the previous VCLEventListener (if no AT tool + * is running), e.g. sub-toolbars in impress. + */ + if ( mpParent && pEvent && pEvent->ISA( VclWindowEvent ) && (pEvent->GetId() != VCLEVENT_WINDOW_ENDPOPUPMODE) ) + { + DBG_ASSERT( ((VclWindowEvent*)pEvent)->GetWindow(), "Window???" ); + if( !((VclWindowEvent*)pEvent)->GetWindow()->IsAccessibilityEventsSuppressed() || ( pEvent->GetId() == VCLEVENT_OBJECT_DYING ) ) + { + ProcessWindowEvent( *(VclWindowEvent*)pEvent ); + } + } + return 0; +} + +// ----------------------------------------------------------------------- + +void ToolbarMenuAcc::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) +{ + Any aOldValue, aNewValue; + + Window* pAccWindow = rVclWindowEvent.GetWindow(); + DBG_ASSERT( pAccWindow, "VCLXAccessibleComponent::ProcessWindowEvent - Window?" ); + + switch ( rVclWindowEvent.GetId() ) + { + case VCLEVENT_OBJECT_DYING: + { + mpParent->mrMenu.RemoveEventListener( LINK( this, ToolbarMenuAcc, WindowEventListener ) ); + mpParent = 0; + } + break; + + case VCLEVENT_WINDOW_GETFOCUS: + { + if( !mbIsFocused ) + { + aNewValue <<= accessibility::AccessibleStateType::FOCUSED; + FireAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); + mbIsFocused = true; + } + } + break; + case VCLEVENT_WINDOW_LOSEFOCUS: + { + if( mbIsFocused ) + { + aOldValue <<= accessibility::AccessibleStateType::FOCUSED; + FireAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); + mbIsFocused = false; + } + } + break; + default: + { + } + break; + } } // ----------------------------------------------------------------------- @@ -98,22 +167,6 @@ void ToolbarMenuAcc::FireAccessibleEvent( short nEventId, const Any& rOldValue, // ----------------------------------------------------------------------------- -void ToolbarMenuAcc::GetFocus (void) -{ - mbIsFocused = true; - FireAccessibleEvent( AccessibleEventId::STATE_CHANGED, Any(), Any( AccessibleStateType::FOCUSED ) ); -} - -// ----------------------------------------------------------------------------- - -void ToolbarMenuAcc::LoseFocus (void) -{ - mbIsFocused = false; - FireAccessibleEvent( AccessibleEventId::STATE_CHANGED, Any( AccessibleStateType::FOCUSED ), Any() ); -} - -// ----------------------------------------------------------------------------- - Reference< XAccessibleContext > SAL_CALL ToolbarMenuAcc::getAccessibleContext() throw (RuntimeException) { ThrowIfDisposed(); @@ -560,7 +613,7 @@ void SAL_CALL ToolbarMenuAcc::disposing (void) void ToolbarMenuAcc::ThrowIfDisposed (void) throw (DisposedException) { - if(rBHelper.bDisposed || rBHelper.bInDispose) + if(rBHelper.bDisposed || rBHelper.bInDispose || !mpParent) { throw DisposedException ( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("object has been already disposed")), static_cast(this)); } diff --git a/svtools/source/control/toolbarmenuimp.hxx b/svtools/source/control/toolbarmenuimp.hxx index 1d9037b61dc5..051fe23883a4 100755 --- a/svtools/source/control/toolbarmenuimp.hxx +++ b/svtools/source/control/toolbarmenuimp.hxx @@ -135,18 +135,6 @@ public: bool HasAccessibleListeners() const { return( mxEventListeners.size() > 0 ); } public: - - /** Called by the corresponding ToolbarMenu when it gets the focus. - Stores the new focus state and broadcasts a state change event. - */ - void GetFocus (void); - - /** Called by the corresponding ToolbarMenu when it loses the focus. - Stores the new focus state and broadcasts a state change event. - */ - void LoseFocus (void); - - // XAccessible virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) throw (::com::sun::star::uno::RuntimeException); @@ -189,12 +177,16 @@ public: virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); virtual void SAL_CALL deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + DECL_LINK( WindowEventListener, VclSimpleEvent* ); + private: EventListenerVector mxEventListeners; ToolbarMenu_Impl* mpParent; /// The current FOCUSED state. bool mbIsFocused; + void ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ); + /** Tell all listeners that the object is dying. This callback is usually called from the WeakComponentImplHelper class. */ From cfc9c68d07db4275041ee52e977f53c9b614934e Mon Sep 17 00:00:00 2001 From: Christian Lippka Date: Wed, 28 Apr 2010 18:43:47 +0200 Subject: [PATCH 17/18] #i107213# finaly got orca to read the toolbar menu! --- svtools/source/control/toolbarmenu.cxx | 170 +++++++++++----------- svtools/source/control/toolbarmenuacc.cxx | 8 +- svtools/source/control/toolbarmenuimp.hxx | 9 ++ svtools/source/control/valueset.cxx | 31 ++-- 4 files changed, 105 insertions(+), 113 deletions(-) mode change 100755 => 100644 svtools/source/control/toolbarmenuacc.cxx mode change 100755 => 100644 svtools/source/control/toolbarmenuimp.hxx mode change 100755 => 100644 svtools/source/control/valueset.cxx diff --git a/svtools/source/control/toolbarmenu.cxx b/svtools/source/control/toolbarmenu.cxx index 6f7be376266e..8ff327f26731 100644 --- a/svtools/source/control/toolbarmenu.cxx +++ b/svtools/source/control/toolbarmenu.cxx @@ -307,6 +307,25 @@ Reference< XAccessible > ToolbarMenu_Impl::getAccessibleChild( sal_Int32 index ) 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(); @@ -381,13 +400,60 @@ void ToolbarMenu_Impl::clearAccessibleSelection() } } + +// -------------------------------------------------------------------- + +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 ); + 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; - if( mpImpl->hasAccessibleListeners() ) - mpImpl->fireAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() ); + mpImpl->notifyHighlightedEntry(); return 0; } @@ -723,77 +789,6 @@ void ToolbarMenu::appendEntry( int nEntryId, const String& rStr, MenuItemBits nI appendEntry( new ToolbarMenuEntry( *this, nEntryId, rStr, nItemBits ) ); } - -#if 0 -todo acc selectentry? - if( ImplHasAccessibleListeners() ) - { - // focus event (deselect) - if( nOldItem ) - { - const USHORT nPos = GetItemPos( nItemId ); - - if( nPos != VALUESET_ITEM_NOTFOUND ) - { - ValueItemAcc* pItemAcc = ValueItemAcc::getImplementation( - mpImpl->mpItemList->GetObject( nPos )->GetAccessible( mpImpl->mbIsTransientChildrenDisabled ) ); - - if( pItemAcc ) - { - ::com::sun::star::uno::Any aOldAny, aNewAny; - if( !mpImpl->mbIsTransientChildrenDisabled) - { - aOldAny <<= ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >( - static_cast< ::cppu::OWeakObject* >( pItemAcc )); - ImplFireAccessibleEvent (::com::sun::star::accessibility::AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldAny, aNewAny ); - } - else - { - aOldAny <<= ::com::sun::star::accessibility::AccessibleStateType::FOCUSED; - pItemAcc->FireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::STATE_CHANGED, aOldAny, aNewAny ); - } - } - } - } - - // focus event (select) - const USHORT nPos = GetItemPos( mnSelItemId ); - - ValueSetItem* pItem; - if( nPos != VALUESET_ITEM_NOTFOUND ) - pItem = mpImpl->mpItemList->GetObject(nPos); - else - pItem = mpNoneItem; - - ValueItemAcc* pItemAcc = NULL; - if (pItem != NULL) - pItemAcc = ValueItemAcc::getImplementation(pItem->GetAccessible( mpImpl->mbIsTransientChildrenDisabled ) ); - - if( pItemAcc ) - { - ::com::sun::star::uno::Any aOldAny, aNewAny; - if( !mpImpl->mbIsTransientChildrenDisabled) - { - aNewAny <<= ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >( - static_cast< ::cppu::OWeakObject* >( pItemAcc )); - ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldAny, aNewAny ); - } - else - { - aNewAny <<= ::com::sun::star::accessibility::AccessibleStateType::FOCUSED; - pItemAcc->FireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::STATE_CHANGED, aOldAny, aNewAny ); - } - } - - // selection event - ::com::sun::star::uno::Any aOldAny, aNewAny; - ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::SELECTION_CHANGED, aOldAny, aNewAny ); - } - } -} - -#endif - // -------------------------------------------------------------------- void ToolbarMenu::appendEntry( int nEntryId, const Image& rImage, MenuItemBits nItemBits ) @@ -848,10 +843,7 @@ ValueSet* ToolbarMenu::createEmptyValueSetControl() ToolbarMenuEntry* ToolbarMenu::implGetEntry( int nEntry ) const { - if( (nEntry < 0) || (nEntry >= (int)mpImpl->maEntryVector.size() ) ) - return NULL; - - return mpImpl->maEntryVector[nEntry]; + return mpImpl->implGetEntry( nEntry ); } // -------------------------------------------------------------------- @@ -888,7 +880,17 @@ void ToolbarMenu::implHighlightEntry( int nHighlightEntry, bool bHighlight ) { // 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; @@ -1070,8 +1072,7 @@ void ToolbarMenu::implChangeHighlightEntry( int nEntry ) implHighlightEntry( mpImpl->mnHighlightedEntry, true ); } - if( mpImpl->hasAccessibleListeners() ) - mpImpl->fireAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() ); + mpImpl->notifyHighlightedEntry(); } // -------------------------------------------------------------------- @@ -1184,7 +1185,7 @@ ToolbarMenuEntry* ToolbarMenu::implCursorUpDown( bool bUp, bool bHomeEnd ) // -------------------------------------------------------------------- -static void implHighlightControl( USHORT nCode, Control* pControl, int nLastColumn ) +void ToolbarMenu_Impl::implHighlightControl( USHORT nCode, Control* pControl ) { ValueSet* pValueSet = dynamic_cast< ValueSet* >( pControl ); if( pValueSet ) @@ -1197,11 +1198,11 @@ static void implHighlightControl( USHORT nCode, Control* pControl, int nLastColu { const USHORT nColCount = pValueSet->GetColCount(); const USHORT nLastLine = nItemCount / nColCount; - nItemPos = std::min( ((nLastLine-1) * nColCount) + nLastColumn, nItemCount-1 ); + nItemPos = std::min( ((nLastLine-1) * nColCount) + mnLastColumn, nItemCount-1 ); break; } case KEY_DOWN: - nItemPos = std::min( nLastColumn, nItemCount-1 ); + nItemPos = std::min( mnLastColumn, nItemCount-1 ); break; case KEY_END: nItemPos = nItemCount -1; @@ -1211,6 +1212,7 @@ static void implHighlightControl( USHORT nCode, Control* pControl, int nLastColu break; } pValueSet->SelectItem( pValueSet->GetItemId( nItemPos ) ); + notifyHighlightedEntry(); } } @@ -1231,7 +1233,7 @@ void ToolbarMenu::KeyInput( const KeyEvent& rKEvent ) { if( nOldEntry != mpImpl->mnHighlightedEntry ) { - implHighlightControl( nCode, p->mpControl, mpImpl->mnLastColumn ); + mpImpl->implHighlightControl( nCode, p->mpControl ); } else { @@ -1247,7 +1249,7 @@ void ToolbarMenu::KeyInput( const KeyEvent& rKEvent ) ToolbarMenuEntry* p = implCursorUpDown( nCode == KEY_END, true ); if( p && p->mpControl ) { - implHighlightControl( nCode, p->mpControl, mpImpl->mnLastColumn ); + mpImpl->implHighlightControl( nCode, p->mpControl ); } } break; diff --git a/svtools/source/control/toolbarmenuacc.cxx b/svtools/source/control/toolbarmenuacc.cxx old mode 100755 new mode 100644 index f227a4cb2558..14586ecd422b --- a/svtools/source/control/toolbarmenuacc.cxx +++ b/svtools/source/control/toolbarmenuacc.cxx @@ -96,9 +96,6 @@ void ToolbarMenuAcc::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) { Any aOldValue, aNewValue; - Window* pAccWindow = rVclWindowEvent.GetWindow(); - DBG_ASSERT( pAccWindow, "VCLXAccessibleComponent::ProcessWindowEvent - Window?" ); - switch ( rVclWindowEvent.GetId() ) { case VCLEVENT_OBJECT_DYING: @@ -112,8 +109,7 @@ void ToolbarMenuAcc::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) { if( !mbIsFocused ) { - aNewValue <<= accessibility::AccessibleStateType::FOCUSED; - FireAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); + mpParent->notifyHighlightedEntry(); mbIsFocused = true; } } @@ -122,8 +118,6 @@ void ToolbarMenuAcc::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) { if( mbIsFocused ) { - aOldValue <<= accessibility::AccessibleStateType::FOCUSED; - FireAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); mbIsFocused = false; } } diff --git a/svtools/source/control/toolbarmenuimp.hxx b/svtools/source/control/toolbarmenuimp.hxx old mode 100755 new mode 100644 index 051fe23883a4..d1de4f704b76 --- a/svtools/source/control/toolbarmenuimp.hxx +++ b/svtools/source/control/toolbarmenuimp.hxx @@ -273,6 +273,8 @@ struct ToolbarMenu_Impl rtl::Reference< svt::FrameStatusListener > mxStatusListener; ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxServiceManager; rtl::Reference< ToolbarMenuAcc > mxAccessible; + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > mxOldSelection; + ToolbarMenuEntryVector maEntryVector; int mnCheckPos; @@ -297,9 +299,16 @@ struct ToolbarMenu_Impl sal_Int32 getAccessibleChildCount() throw (::com::sun::star::uno::RuntimeException); ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > getAccessibleChild( sal_Int32 index ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > getAccessibleChild( Control* pControl, sal_Int32 childIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + void selectAccessibleChild( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); sal_Bool isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); void clearAccessibleSelection(); + + ToolbarMenuEntry* implGetEntry( int nEntry ) const; + void notifyHighlightedEntry(); + + void implHighlightControl( USHORT nCode, Control* pControl ); }; } diff --git a/svtools/source/control/valueset.cxx b/svtools/source/control/valueset.cxx old mode 100755 new mode 100644 index 92c51bd6640e..62193eadf735 --- a/svtools/source/control/valueset.cxx +++ b/svtools/source/control/valueset.cxx @@ -1526,32 +1526,20 @@ void ValueSet::KeyInput( const KeyEvent& rKEvt ) nCalcPos - ( nLineCount * mnCols )); else { -#if 0 - if( (KEY_UP == rKEvt.GetKeyCode().GetCode() ) && (GetStyle() & WB_MENUSTYLEVALUESET) ) + if ( mpNoneItem ) { - Window* pParent = GetParent(); - pParent->GrabFocus(); - pParent->KeyInput( rKEvt ); - break; + mnCurCol = nCalcPos%mnCols; + nItemPos = VALUESET_ITEM_NONEITEM; } else -#endif { - if ( mpNoneItem ) - { - mnCurCol = nCalcPos%mnCols; - nItemPos = VALUESET_ITEM_NONEITEM; - } + if ( nLastItem+1 <= mnCols ) + nItemPos = nCalcPos; else { - if ( nLastItem+1 <= mnCols ) - nItemPos = nCalcPos; - else - { - nItemPos = ((((nLastItem+1)/mnCols)-1)*mnCols)+(nCalcPos%mnCols); - if ( nItemPos+mnCols <= nLastItem ) - nItemPos = nItemPos + mnCols; - } + nItemPos = ((((nLastItem+1)/mnCols)-1)*mnCols)+(nCalcPos%mnCols); + if ( nItemPos+mnCols <= nLastItem ) + nItemPos = nItemPos + mnCols; } } } @@ -2279,9 +2267,8 @@ void ValueSet::SelectItem( USHORT nItemId ) // selection event ::com::sun::star::uno::Any aOldAny, aNewAny; ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::SELECTION_CHANGED, aOldAny, aNewAny ); - - mpImpl->maHighlightHdl.Call(this); } + mpImpl->maHighlightHdl.Call(this); } } From d24b570e7db3127356f0807d765c0be1fcb3ba19 Mon Sep 17 00:00:00 2001 From: Christian Lippka Date: Mon, 10 May 2010 14:25:18 +0200 Subject: [PATCH 18/18] #i107213# enable reading of toolbar menu entries on mac --- svtools/inc/svtools/toolbarmenu.hxx | 2 ++ svtools/source/control/toolbarmenu.cxx | 9 +++++++++ svtools/source/control/toolbarmenuacc.cxx | 2 +- svtools/source/control/valueacc.cxx | 5 +---- svtools/source/uno/popupwindowcontroller.cxx | 5 +++++ 5 files changed, 18 insertions(+), 5 deletions(-) mode change 100755 => 100644 svtools/source/control/valueacc.cxx diff --git a/svtools/inc/svtools/toolbarmenu.hxx b/svtools/inc/svtools/toolbarmenu.hxx index 943f714b0097..92b873158a98 100644 --- a/svtools/inc/svtools/toolbarmenu.hxx +++ b/svtools/inc/svtools/toolbarmenu.hxx @@ -103,6 +103,8 @@ public: int getSelectedEntryId() const; int getHighlightedEntryId() const; + void highlightFirstEntry(); + protected: virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible(); diff --git a/svtools/source/control/toolbarmenu.cxx b/svtools/source/control/toolbarmenu.cxx index 8ff327f26731..f07ebd7fe8cd 100644 --- a/svtools/source/control/toolbarmenu.cxx +++ b/svtools/source/control/toolbarmenu.cxx @@ -30,6 +30,7 @@ #include "precompiled_svtools.hxx" #include +#include #include #include @@ -432,6 +433,7 @@ void ToolbarMenu_Impl::notifyHighlightedEntry() fireAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOld, aNew ); fireAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, aOld, aNew ); + fireAccessibleEvent( AccessibleEventId::STATE_CHANGED, Any(), Any( AccessibleStateType::FOCUSED ) ); aNew >>= mxOldSelection; } } @@ -764,6 +766,13 @@ Size ToolbarMenu::implCalcSize() // -------------------------------------------------------------------- +void ToolbarMenu::highlightFirstEntry() +{ + implChangeHighlightEntry( 0 ); +} + +// -------------------------------------------------------------------- + void ToolbarMenu::GetFocus() { if( mpImpl->mnHighlightedEntry == -1 ) diff --git a/svtools/source/control/toolbarmenuacc.cxx b/svtools/source/control/toolbarmenuacc.cxx index 14586ecd422b..020467084748 100644 --- a/svtools/source/control/toolbarmenuacc.cxx +++ b/svtools/source/control/toolbarmenuacc.cxx @@ -765,7 +765,7 @@ sal_Int16 SAL_CALL ToolbarMenuEntryAcc::getAccessibleRole() throw (RuntimeExcept ::rtl::OUString SAL_CALL ToolbarMenuEntryAcc::getAccessibleDescription() throw (RuntimeException) { - return OUString( RTL_CONSTASCII_USTRINGPARAM( "ToolbarMenu item" ) ); + return ::rtl::OUString(); } // ----------------------------------------------------------------------------- diff --git a/svtools/source/control/valueacc.cxx b/svtools/source/control/valueacc.cxx old mode 100755 new mode 100644 index 52fa40fcf00e..66da5636d89c --- a/svtools/source/control/valueacc.cxx +++ b/svtools/source/control/valueacc.cxx @@ -976,10 +976,7 @@ sal_Int16 SAL_CALL ValueItemAcc::getAccessibleRole() ::rtl::OUString SAL_CALL ValueItemAcc::getAccessibleDescription() throw (uno::RuntimeException) { - const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); - String aRet( RTL_CONSTASCII_USTRINGPARAM( "ValueSet item" ) ); - - return aRet; + return ::rtl::OUString(); } // ----------------------------------------------------------------------------- diff --git a/svtools/source/uno/popupwindowcontroller.cxx b/svtools/source/uno/popupwindowcontroller.cxx index 52a636017806..4fbaff23714d 100644 --- a/svtools/source/uno/popupwindowcontroller.cxx +++ b/svtools/source/uno/popupwindowcontroller.cxx @@ -34,6 +34,7 @@ #include #include "svtools/popupwindowcontroller.hxx" +#include "svtools/toolbarmenu.hxx" using rtl::OUString; using namespace ::com::sun::star; @@ -107,6 +108,10 @@ IMPL_LINK( PopupWindowControllerImpl, WindowEventListener, VclSimpleEvent*, pEve if( mpToolBox ) mpToolBox->CallEventListeners( VCLEVENT_DROPDOWN_OPEN, (void*)mpPopupWindow ); mpPopupWindow->CallEventListeners( VCLEVENT_WINDOW_GETFOCUS, 0 ); + + svtools::ToolbarMenu* pToolbarMenu = dynamic_cast< svtools::ToolbarMenu* >( mpPopupWindow ); + if( pToolbarMenu ) + pToolbarMenu->highlightFirstEntry(); break; } break;