diff options
author | Frank Schoenheit [fs] <frank.schoenheit@sun.com> | 2010-04-07 22:36:26 +0200 |
---|---|---|
committer | Frank Schoenheit [fs] <frank.schoenheit@sun.com> | 2010-04-07 22:36:26 +0200 |
commit | 1cf2a482871ba237ec9470b88da074b97a2dbf41 (patch) | |
tree | c9b0520fa86bf4512a198524483f970525da9843 /sfx2/source/dialog/taskpane.cxx | |
parent | f0cd4535a2d40ce66c346596bedbc7eac97a0b63 (diff) |
slidecopy: improved the generic TaskPane, now filled from the configuration, including a small sample extension
still some way to go .... open items include:
- add to all affected applications
- respect the ImageURL property of the config data
- clarify how this interacts with SD's Drawing Framework, and Impress' TaskPane
- re-activate the previously-active tool panel when opening the pane again
- obtain the XAccessible from the tool panel
- title when docked
- proper TAB handling when multiple panel/drawers exist
Diffstat (limited to 'sfx2/source/dialog/taskpane.cxx')
-rw-r--r-- | sfx2/source/dialog/taskpane.cxx | 481 |
1 files changed, 441 insertions, 40 deletions
diff --git a/sfx2/source/dialog/taskpane.cxx b/sfx2/source/dialog/taskpane.cxx index 80273f5e517a..383306da42e8 100644 --- a/sfx2/source/dialog/taskpane.cxx +++ b/sfx2/source/dialog/taskpane.cxx @@ -28,11 +28,28 @@ #include "sfx2/taskpane.hxx" #include "sfx2/sfxsids.hrc" +#include "sfx2/bindings.hxx" +#include "sfx2/dispatch.hxx" #include "sfxresid.hxx" #include "helpid.hrc" +/** === begin UNO includes === **/ +#include <com/sun/star/frame/XModuleManager.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/view/XToolPanel.hpp> +#include <com/sun/star/ui/XUIElementFactory.hpp> +#include <com/sun/star/awt/XWindowPeer.hpp> +#include <com/sun/star/awt/PosSize.hpp> +#include <com/sun/star/frame/XModuleManager.hpp> +/** === end UNO includes === **/ + +#include <comphelper/componentcontext.hxx> +#include <comphelper/namedvaluecollection.hxx> +#include <comphelper/types.hxx> +#include <comphelper/processfactory.hxx> #include <tools/diagnose_ex.h> #include <svtools/toolpanel/toolpaneldeck.hxx> +#include <unotools/confignode.hxx> #if OSL_DEBUG_LEVEL > 0 #include <com/sun/star/accessibility/XAccessible.hpp> @@ -46,7 +63,31 @@ namespace sfx2 { //...................................................................................................................... -#define USE_DUMMY_PANEL + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Type; + using ::com::sun::star::frame::XModuleManager; + using ::com::sun::star::container::XNameAccess; + using ::com::sun::star::view::XToolPanel; + using ::com::sun::star::ui::XUIElementFactory; + using ::com::sun::star::ui::XUIElement; + using ::com::sun::star::awt::XWindow; + using ::com::sun::star::frame::XModuleManager; + using ::com::sun::star::frame::XFrame; + using ::com::sun::star::lang::XComponent; + /** === end UNO using === **/ + namespace PosSize = ::com::sun::star::awt::PosSize; + +//#define USE_DUMMY_PANEL #if OSL_DEBUG_LEVEL > 0 //================================================================================================================== @@ -168,69 +209,76 @@ namespace sfx2 #endif //================================================================================================================== - //= TaskPane_Impl + //= helpers //================================================================================================================== - class TaskPane_Impl : public ::boost::noncopyable + namespace { - public: - TaskPane_Impl( TaskPane& i_rAntiImpl ) - :m_rAntiImpl( i_rAntiImpl ) - ,m_aToolPanels( i_rAntiImpl, 0 ) + ::rtl::OUString lcl_identifyModule( const Reference< XFrame >& i_rDocumentFrame ) { - m_aToolPanels.Show(); -#if ( OSL_DEBUG_LEVEL > 0 ) && defined ( USE_DUMMY_PANEL ) - m_aToolPanels.InsertPanel( ::svt::PToolPanel( new DummyPanel( m_aToolPanels.GetPanelWindowAnchor() ) ), m_aToolPanels.GetPanelCount() ); -#endif - OnResize(); + ::rtl::OUString sModuleName; + try + { + const ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() ); + const Reference< XModuleManager > xModuleManager( aContext.createComponent( "com.sun.star.frame.ModuleManager" ), UNO_QUERY_THROW ); + sModuleName = xModuleManager->identify( i_rDocumentFrame ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return sModuleName; } - ~TaskPane_Impl() + ::rtl::OUString lcl_identifyModule( const SfxBindings* i_pBindings ) { + const SfxViewFrame* pViewFrame = i_pBindings->GetDispatcher()->GetFrame(); + const SfxFrame* pFrame = pViewFrame->GetFrame(); + const Reference< XFrame > xFrame( pFrame->GetFrameInterface() ); + return lcl_identifyModule( xFrame ); } - - void OnResize(); - void OnGetFocus(); - - private: - TaskPane& m_rAntiImpl; - ::svt::ToolPanelDeck m_aToolPanels; - }; - - //------------------------------------------------------------------------------------------------------------------ - void TaskPane_Impl::OnResize() - { - m_aToolPanels.SetPosSizePixel( Point(), m_rAntiImpl.GetOutputSizePixel() ); - } - - //------------------------------------------------------------------------------------------------------------------ - void TaskPane_Impl::OnGetFocus() - { - m_aToolPanels.GrabFocus(); } //================================================================================================================== - //= TaskPane + //= TaskPaneDockingWindow //================================================================================================================== //------------------------------------------------------------------------------------------------------------------ - TaskPane::TaskPane( SfxBindings* i_pBindings, TaskPaneWrapper& i_rWrapper, Window* i_pParent, WinBits i_nBits ) + TaskPaneDockingWindow::TaskPaneDockingWindow( SfxBindings* i_pBindings, TaskPaneWrapper& i_rWrapper, Window* i_pParent, WinBits i_nBits ) :SfxDockingWindow( i_pBindings, &i_rWrapper, i_pParent, i_nBits ) - ,m_pImpl( new TaskPane_Impl( *this ) ) + ,m_aTaskPane( *this, lcl_identifyModule( i_pBindings ) ) { + m_aTaskPane.Show(); SetText( String( SfxResId( SID_TASKPANE ) ) ); } //------------------------------------------------------------------------------------------------------------------ - void TaskPane::GetFocus() + void TaskPaneDockingWindow::GetFocus() { SfxDockingWindow::GetFocus(); - m_pImpl->OnGetFocus(); + m_aTaskPane.GrabFocus(); } //------------------------------------------------------------------------------------------------------------------ - void TaskPane::Resize() + void TaskPaneDockingWindow::Resize() { SfxDockingWindow::Resize(); - m_pImpl->OnResize(); + m_aTaskPane.SetPosSizePixel( Point(), GetOutputSizePixel() ); + } + + //------------------------------------------------------------------------------------------------------------------ + long TaskPaneDockingWindow::Notify( NotifyEvent& i_rNotifyEvent ) + { + // in case this is a MouseButtonDown event, consume it - VCL's DockingWindow would otherwise + // start undocking, no matter which window this event was intended for + if ( i_rNotifyEvent.GetType() == EVENT_MOUSEBUTTONDOWN ) + { + const MouseEvent& rMouseEvent = *i_rNotifyEvent.GetMouseEvent(); + if ( rMouseEvent.IsLeft() && ( rMouseEvent.GetClicks() == 1 ) && !rMouseEvent.IsMod1() ) + { + if ( m_aTaskPane.IsWindowOrChild( i_rNotifyEvent.GetWindow() ) ) + return TRUE; + } + } + return SfxDockingWindow::Notify( i_rNotifyEvent ); } //================================================================================================================== @@ -243,7 +291,7 @@ namespace sfx2 TaskPaneWrapper::TaskPaneWrapper( Window* i_pParent, USHORT i_nId, SfxBindings* i_pBindings, SfxChildWinInfo* i_pInfo ) :SfxChildWindow( i_pParent, i_nId ) { - pWindow = new TaskPane( i_pBindings, *this, i_pParent, + pWindow = new TaskPaneDockingWindow( i_pBindings, *this, i_pParent, WB_STDDOCKWIN | WB_CLIPCHILDREN | WB_SIZEABLE | WB_3DLOOK | WB_ROLLABLE); eChildAlignment = SFX_ALIGN_RIGHT; @@ -255,6 +303,359 @@ namespace sfx2 SetHideNotDelete( TRUE ); } + //================================================================================================================== + //= CustomPanelUIElement + //================================================================================================================== + class CustomPanelUIElement + { + public: + CustomPanelUIElement() + :m_xUIElement() + ,m_xToolPanel() + ,m_xPanelWindow() + { + } + + CustomPanelUIElement( const Reference< XUIElement >& i_rUIElement ) + :m_xUIElement( i_rUIElement, UNO_SET_THROW ) + ,m_xToolPanel( i_rUIElement->getRealInterface(), UNO_QUERY_THROW ) + ,m_xPanelWindow( m_xToolPanel->getWindow(), UNO_SET_THROW ) + { + } + + bool is() const { return m_xPanelWindow.is(); } + + const Reference< XUIElement >& getUIElement() const { return m_xUIElement; } + const Reference< XToolPanel >& getToolPanel() const { return m_xToolPanel; } + const Reference< XWindow >& getPanelWindow() const { return m_xPanelWindow; } + + private: + Reference< XUIElement > m_xUIElement; + Reference< XToolPanel > m_xToolPanel; + Reference< XWindow > m_xPanelWindow; + }; + + //================================================================================================================== + //= CustomToolPanel + //================================================================================================================== + class CustomToolPanel : public ::svt::ToolPanelBase + { + public: + CustomToolPanel( const ::utl::OConfigurationNode& i_rPanelWindowState ); + + virtual ::rtl::OUString GetDisplayName() const; + virtual Image GetImage() const; + virtual void Activate( Window& i_rParentWindow ); + virtual void Deactivate(); + virtual void SetSizePixel( const Size& i_rPanelWindowSize ); + virtual void GrabFocus(); + virtual void Dispose(); + virtual Reference< XAccessible > + CreatePanelAccessible( const Reference< XAccessible >& i_rParentAccessible ); + + protected: + ~CustomToolPanel(); + + private: + bool impl_ensureToolPanelWindow( Window& i_rPanelParentWindow ); + + private: + const ::rtl::OUString m_sUIName; + const ::rtl::OUString m_sResourceURL; + CustomPanelUIElement m_aCustomPanel; + bool m_bAttemptedCreation; + }; + + //------------------------------------------------------------------------------------------------------------------ + CustomToolPanel::CustomToolPanel( const ::utl::OConfigurationNode& i_rPanelWindowState ) + :m_sUIName( ::comphelper::getString( i_rPanelWindowState.getNodeValue( "UIName" ) ) ) + ,m_sResourceURL( i_rPanelWindowState.getLocalName() ) + ,m_aCustomPanel() + ,m_bAttemptedCreation( false ) + { + } + + //------------------------------------------------------------------------------------------------------------------ + CustomToolPanel::~CustomToolPanel() + { + } + + //------------------------------------------------------------------------------------------------------------------ + bool CustomToolPanel::impl_ensureToolPanelWindow( Window& i_rPanelParentWindow ) + { + if ( m_bAttemptedCreation ) + return m_aCustomPanel.is(); + + m_bAttemptedCreation = true; + try + { + const ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() ); + const Reference< XUIElementFactory > xFactory( aContext.createComponent( "com.sun.star.ui.UIElementFactoryManager" ), UNO_QUERY_THROW ); + + ::comphelper::NamedValueCollection aCreationArgs; + aCreationArgs.put( "ParentWindow", makeAny( i_rPanelParentWindow.GetComponentInterface() ) ); + + const Reference< XUIElement > xElement( + xFactory->createUIElement( m_sResourceURL, aCreationArgs.getPropertyValues() ), + UNO_SET_THROW ); + + m_aCustomPanel = CustomPanelUIElement( xElement ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return m_aCustomPanel.is(); + } + + //------------------------------------------------------------------------------------------------------------------ + ::rtl::OUString CustomToolPanel::GetDisplayName() const + { + return m_sUIName; + } + + //------------------------------------------------------------------------------------------------------------------ + Image CustomToolPanel::GetImage() const + { + // TODO: read from configuration + return Image(); + } + + //------------------------------------------------------------------------------------------------------------------ + void CustomToolPanel::Activate( Window& i_rParentWindow ) + { + ENSURE_OR_RETURN_VOID( impl_ensureToolPanelWindow( i_rParentWindow ), "no panel to activate!" ); + + // TODO: we might need a mechanism to decide whether the panel should be destroyed/re-created, or (as it is + // done now) hidden/shown + m_aCustomPanel.getPanelWindow()->setVisible( sal_True ); + } + + //------------------------------------------------------------------------------------------------------------------ + void CustomToolPanel::Deactivate() + { + ENSURE_OR_RETURN_VOID( m_aCustomPanel.is(), "no panel to deactivate!" ); + + m_aCustomPanel.getPanelWindow()->setVisible( sal_False ); + } + + //------------------------------------------------------------------------------------------------------------------ + void CustomToolPanel::SetSizePixel( const Size& i_rPanelWindowSize ) + { + ENSURE_OR_RETURN_VOID( m_aCustomPanel.is(), "no panel/window to position!" ); + + try + { + m_aCustomPanel.getPanelWindow()->setPosSize( 0, 0, i_rPanelWindowSize.Width(), i_rPanelWindowSize.Height(), + PosSize::POSSIZE ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //------------------------------------------------------------------------------------------------------------------ + void CustomToolPanel::GrabFocus() + { + ENSURE_OR_RETURN_VOID( m_aCustomPanel.is(), "no panel/window to focus!" ); + + m_aCustomPanel.getPanelWindow()->setFocus(); + } + + //------------------------------------------------------------------------------------------------------------------ + void CustomToolPanel::Dispose() + { + if ( !m_bAttemptedCreation ) + // nothing to dispose + return; + + ENSURE_OR_RETURN_VOID( m_aCustomPanel.is(), "no panel to destroy!" ); + try + { + Reference< XComponent > xUIElementComponent( m_aCustomPanel.getUIElement(), UNO_QUERY_THROW ); + xUIElementComponent->dispose(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //------------------------------------------------------------------------------------------------------------------ + Reference< XAccessible > CustomToolPanel::CreatePanelAccessible( const Reference< XAccessible >& i_rParentAccessible ) + { + // TODO + (void)i_rParentAccessible; + return NULL; + } + + //================================================================================================================== + //= ModuleTaskPane_Impl + //================================================================================================================== + class ModuleTaskPane_Impl : public ::boost::noncopyable + { + public: + ModuleTaskPane_Impl( ModuleTaskPane& i_rAntiImpl, const ::rtl::OUString& i_rModuleIdentifier ) + :m_rAntiImpl( i_rAntiImpl ) + ,m_sModuleIdentifier( i_rModuleIdentifier ) + ,m_aPanels( i_rAntiImpl, 0 ) + { + m_aPanels.Show(); + #if ( OSL_DEBUG_LEVEL > 0 ) && defined ( USE_DUMMY_PANEL ) + m_aPanels.InsertPanel( ::svt::PToolPanel( new DummyPanel( m_aPanels.GetPanelWindowAnchor() ) ), m_aPanels.GetPanelCount() ); + #endif + OnResize(); + impl_initFromConfiguration(); + } + + ~ModuleTaskPane_Impl() + { + } + + void OnResize(); + void OnGetFocus(); + + static bool ModuleHasToolPanels( const ::rtl::OUString& i_rModuleIdentifier ); + + private: + void impl_initFromConfiguration(); + + static ::utl::OConfigurationTreeRoot + impl_getModuleUIElementStatesConfig( const ::rtl::OUString& i_rModuleIdentifier ); + static bool + impl_isToolPanelResource( const ::rtl::OUString& i_rResourceURL ); + + private: + ModuleTaskPane& m_rAntiImpl; + ::rtl::OUString m_sModuleIdentifier; + ::svt::ToolPanelDeck m_aPanels; + }; + + //------------------------------------------------------------------------------------------------------------------ + void ModuleTaskPane_Impl::OnResize() + { + m_aPanels.SetPosSizePixel( Point(), m_rAntiImpl.GetOutputSizePixel() ); + } + + //------------------------------------------------------------------------------------------------------------------ + void ModuleTaskPane_Impl::OnGetFocus() + { + m_aPanels.GrabFocus(); + } + + //------------------------------------------------------------------------------------------------------------------ + ::utl::OConfigurationTreeRoot ModuleTaskPane_Impl::impl_getModuleUIElementStatesConfig( const ::rtl::OUString& i_rModuleIdentifier ) + { + const ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() ); + ::rtl::OUStringBuffer aPathComposer; + try + { + const Reference< XNameAccess > xModuleAccess( aContext.createComponent( "com.sun.star.frame.ModuleManager" ), UNO_QUERY_THROW ); + const ::comphelper::NamedValueCollection aModuleProps( xModuleAccess->getByName( i_rModuleIdentifier ) ); + + const ::rtl::OUString sWindowStateRef( aModuleProps.getOrDefault( "ooSetupFactoryWindowStateConfigRef", ::rtl::OUString() ) ); + + aPathComposer.appendAscii( "org.openoffice.Office.UI." ); + aPathComposer.append( sWindowStateRef ); + aPathComposer.appendAscii( "/UIElements/States" ); + + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return ::utl::OConfigurationTreeRoot( aContext, aPathComposer.makeStringAndClear(), false ); + } + + //------------------------------------------------------------------------------------------------------------------ + bool ModuleTaskPane_Impl::impl_isToolPanelResource( const ::rtl::OUString& i_rResourceURL ) + { + return i_rResourceURL.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "private:resource/toolpanel/" ) ); + } + + //------------------------------------------------------------------------------------------------------------------ + void ModuleTaskPane_Impl::impl_initFromConfiguration() + { + const ::utl::OConfigurationTreeRoot aWindowStateConfig( impl_getModuleUIElementStatesConfig( m_sModuleIdentifier ) ); + if ( !aWindowStateConfig.isValid() ) + return; + + const Sequence< ::rtl::OUString > aUIElements( aWindowStateConfig.getNodeNames() ); + for ( const ::rtl::OUString* resource = aUIElements.getConstArray(); + resource != aUIElements.getConstArray() + aUIElements.getLength(); + ++resource + ) + { + if ( !impl_isToolPanelResource( *resource ) ) + continue; + + ::utl::OConfigurationNode aResourceNode( aWindowStateConfig.openNode( *resource ) ); + ::svt::PToolPanel pCustomPanel( new CustomToolPanel( aResourceNode ) ); + m_aPanels.InsertPanel( pCustomPanel, m_aPanels.GetPanelCount() ); + } + } + + //------------------------------------------------------------------------------------------------------------------ + bool ModuleTaskPane_Impl::ModuleHasToolPanels( const ::rtl::OUString& i_rModuleIdentifier ) + { + const ::utl::OConfigurationTreeRoot aWindowStateConfig( impl_getModuleUIElementStatesConfig( i_rModuleIdentifier ) ); + if ( !aWindowStateConfig.isValid() ) + return false; + + const Sequence< ::rtl::OUString > aUIElements( aWindowStateConfig.getNodeNames() ); + for ( const ::rtl::OUString* resource = aUIElements.getConstArray(); + resource != aUIElements.getConstArray() + aUIElements.getLength(); + ++resource + ) + { + if ( impl_isToolPanelResource( *resource ) ) + return true; + } + return false; + } + + //================================================================================================================== + //= ModuleTaskPane + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + ModuleTaskPane::ModuleTaskPane( Window& i_rParentWindow, const ::rtl::OUString& i_rModuleIdentifier ) + :Window( &i_rParentWindow, 0 ) + ,m_pImpl( new ModuleTaskPane_Impl( *this, i_rModuleIdentifier ) ) + { + } + + //------------------------------------------------------------------------------------------------------------------ + ModuleTaskPane::~ModuleTaskPane() + { + } + + //------------------------------------------------------------------------------------------------------------------ + bool ModuleTaskPane::ModuleHasToolPanels( const ::rtl::OUString& i_rModuleIdentifier ) + { + return ModuleTaskPane_Impl::ModuleHasToolPanels( i_rModuleIdentifier ); + } + + //------------------------------------------------------------------------------------------------------------------ + bool ModuleTaskPane::ModuleHasToolPanels( const Reference< XFrame >& i_rDocumentFrame ) + { + return ModuleTaskPane_Impl::ModuleHasToolPanels( lcl_identifyModule( i_rDocumentFrame ) ); + } + + //------------------------------------------------------------------------------------------------------------------ + void ModuleTaskPane::Resize() + { + Window::Resize(); + m_pImpl->OnResize(); + } + + //------------------------------------------------------------------------------------------------------------------ + void ModuleTaskPane::GetFocus() + { + Window::GetFocus(); + m_pImpl->OnGetFocus(); + } + //...................................................................................................................... } // namespace sfx2 //...................................................................................................................... |