diff options
author | Frank Schoenheit [fs] <frank.schoenheit@sun.com> | 2010-03-01 13:23:12 +0100 |
---|---|---|
committer | Frank Schoenheit [fs] <frank.schoenheit@sun.com> | 2010-03-01 13:23:12 +0100 |
commit | d648e087014684dd4a930f9f49becb28d28f0560 (patch) | |
tree | 3b7a5c27d546409cab54ac4cf4150a223bfb45e9 /svtools/source/toolpanel | |
parent | e786c55dfdaf2f4fede00113ab0b32c867c13437 (diff) |
slidecopy: initial version of the tab bar layout
still quite some work ahead, but we have a tab bar now, and can click the tabs to select panes
Diffstat (limited to 'svtools/source/toolpanel')
-rw-r--r-- | svtools/source/toolpanel/dummypanel.cxx | 15 | ||||
-rw-r--r-- | svtools/source/toolpanel/dummypanel.hxx | 8 | ||||
-rw-r--r-- | svtools/source/toolpanel/makefile.mk | 5 | ||||
-rw-r--r-- | svtools/source/toolpanel/paneltabbar.cxx | 595 | ||||
-rw-r--r-- | svtools/source/toolpanel/paneltabbar.hxx | 75 | ||||
-rw-r--r-- | svtools/source/toolpanel/refbase.cxx | 56 | ||||
-rw-r--r-- | svtools/source/toolpanel/refbase.hxx | 78 | ||||
-rw-r--r-- | svtools/source/toolpanel/tablayouter.cxx | 77 | ||||
-rw-r--r-- | svtools/source/toolpanel/toolpanelcollection.cxx | 43 | ||||
-rw-r--r-- | svtools/source/toolpanel/toolpanelcollection.hxx | 70 | ||||
-rw-r--r-- | svtools/source/toolpanel/toolpaneldeck.cxx | 86 |
11 files changed, 1071 insertions, 37 deletions
diff --git a/svtools/source/toolpanel/dummypanel.cxx b/svtools/source/toolpanel/dummypanel.cxx index 52c89be24b99..405f103d9713 100644 --- a/svtools/source/toolpanel/dummypanel.cxx +++ b/svtools/source/toolpanel/dummypanel.cxx @@ -47,6 +47,9 @@ namespace svt } //-------------------------------------------------------------------- + IMPLEMENT_IREFERENCE( DummyPanel ) + + //-------------------------------------------------------------------- void DummyPanel::Show() { } @@ -61,6 +64,18 @@ namespace svt { } + //-------------------------------------------------------------------- + ::rtl::OUString DummyPanel::GetDisplayName() const + { + return ::rtl::OUString(); + } + + //-------------------------------------------------------------------- + Image DummyPanel::GetImage() const + { + return Image(); + } + //........................................................................ } // namespace svt //........................................................................ diff --git a/svtools/source/toolpanel/dummypanel.hxx b/svtools/source/toolpanel/dummypanel.hxx index 425467641077..46b1218abe93 100644 --- a/svtools/source/toolpanel/dummypanel.hxx +++ b/svtools/source/toolpanel/dummypanel.hxx @@ -28,6 +28,7 @@ #define DUMMYPANEL_HXX #include "svtools/toolpanel/toolpanel.hxx" +#include "refbase.hxx" //........................................................................ namespace svt @@ -38,7 +39,8 @@ namespace svt //= DummyPanel //==================================================================== /// is a dummy implementation of the IToolPanel interface - class DummyPanel : public IToolPanel + class DummyPanel :public RefBase + ,public IToolPanel { public: DummyPanel(); @@ -48,6 +50,10 @@ namespace svt virtual void Show(); virtual void Hide(); virtual void SetPosSizePixel( const Rectangle& i_rPanelPlayground ); + virtual ::rtl::OUString GetDisplayName() const; + virtual Image GetImage() const; + + DECLARE_IREFERENCE() }; //........................................................................ diff --git a/svtools/source/toolpanel/makefile.mk b/svtools/source/toolpanel/makefile.mk index 23a3186bdcef..576db7c84ee5 100644 --- a/svtools/source/toolpanel/makefile.mk +++ b/svtools/source/toolpanel/makefile.mk @@ -45,13 +45,12 @@ ENABLE_EXCEPTIONS=TRUE SLOFILES=\ $(SLO)$/dummypanel.obj \ + $(SLO)$/paneltabbar.obj \ + $(SLO)$/refbase.obj \ $(SLO)$/tablayouter.obj \ $(SLO)$/toolpanelcollection.obj \ $(SLO)$/toolpaneldeck.obj \ -#LIB1TARGET= $(SLB)$/$(TARGET).lib -#LIB1OBJFILES= $(SLOFILES) - # --- Targets ------------------------------------------------------ .INCLUDE : target.mk diff --git a/svtools/source/toolpanel/paneltabbar.cxx b/svtools/source/toolpanel/paneltabbar.cxx new file mode 100644 index 000000000000..0229ce664560 --- /dev/null +++ b/svtools/source/toolpanel/paneltabbar.cxx @@ -0,0 +1,595 @@ +/************************************************************************* + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +#include "precompiled_svtools.hxx" + +#include "svtools/toolpanel/toolpaneldeck.hxx" +#include "paneltabbar.hxx" + +#include <vcl/help.hxx> + +#include <boost/optional.hpp> +#include <vector> + +// space around an item +#define ITEM_OUTER_SPACE 2 * 3 +// distance between two items +#define ITEM_DISTANCE_PIXEL 2 +// space between item icon and icon text +#define ITEM_ICON_TEXT_DISTANCE 4 +// outer space (aka margin) of the complete tab bar control +#define TAB_BAR_OUTER_SPACE 2 + +//........................................................................ +namespace svt +{ +//........................................................................ + + typedef sal_uInt16 ItemFlags; + + #define ITEM_STATE_NORMAL 0x00 + #define ITEM_STATE_ACTIVE 0x01 + #define ITEM_STATE_HOVERED 0x02 + + //================================================================================================================== + //= IItemsLayout + //================================================================================================================== + class IItemsLayout + { + public: + /** calculates the size of the area occupied by the item representing the given tool panel + */ + virtual Size CalculateItemSize( const PToolPanel& i_pPanel, const OutputDevice& i_rReferenceDevice, const bool i_bMinimum ) const = 0; + + /** returns the position where the next item should start, assuming the previous item occupies a given area + */ + virtual Point GetNextItemPosition( const Rectangle& i_rPreviousItemArea ) const = 0; + + /** draws the item onto the given device, in the givem area + @param i_pPanel + the panel whose item representation is to be drawn + @param i_rTargetWindow + the window onto which to drawa + @param i_rItemRect + the area to paint the item into. The caller is responsible for ensuring that is has a size sufficient to + hold the item (which can be determined by calling CalculateItemSize beforehand). + @param i_nItemFlags + defines in which state to draw the item + @param i_bDrawMinimal + defines whether the minimal version of the item should be drawn + */ + virtual void DrawItem( const PToolPanel& i_pPanel, Window& i_rTargetWindow, const Rectangle& i_rItemRect, + const ItemFlags i_nItemFlags, const bool i_bDrawMinimal ) = 0; + }; + + typedef ::boost::shared_ptr< IItemsLayout > PItemsLayout; + + //================================================================================================================== + //= VerticalItemLayout + //================================================================================================================== + class VerticalItemLayout : public IItemsLayout + { + public: + VerticalItemLayout() + { + } + + // IItemsLayout overridables + virtual Size CalculateItemSize( const PToolPanel& i_pPanel, const OutputDevice& i_rReferenceDevice, const bool i_bMinimum ) const; + virtual Point GetNextItemPosition( const Rectangle& i_rPreviousItemArea ) const; + virtual void DrawItem( const PToolPanel& i_pPanel, Window& i_rTargetWindow, const Rectangle& i_rItemRect, + const ItemFlags i_nItemFlags, const bool i_bDrawMinimal ); + }; + + //------------------------------------------------------------------------------------------------------------------ + Size VerticalItemLayout::CalculateItemSize( const PToolPanel& i_pPanel, const OutputDevice& i_rReferenceDevice, const bool i_bMinimum ) const + { + const Image aImage( i_pPanel->GetImage() ); + const ::rtl::OUString sItemText( i_pPanel->GetDisplayName() ); + + // for the moment, we display the icons only + Size aItemSize; + if ( !!aImage ) + { + aItemSize = aImage.GetSizePixel(); + } + + if ( !i_bMinimum && sItemText.getLength() ) + { + if ( !!aImage ) + aItemSize.Height() += ITEM_ICON_TEXT_DISTANCE; + + // add space for vertical text + const Size aTextSize( i_rReferenceDevice.GetCtrlTextWidth( sItemText ), i_rReferenceDevice.GetTextHeight() ); + aItemSize.Height() += aTextSize.Width(); + aItemSize.Width() = ::std::max( aItemSize.Width(), aTextSize.Height() ); + } + + aItemSize.Width() += 2 * ITEM_OUTER_SPACE; + aItemSize.Height() += 2 * ITEM_OUTER_SPACE; + + return aItemSize; + } + + //------------------------------------------------------------------------------------------------------------------ + Point VerticalItemLayout::GetNextItemPosition( const Rectangle& i_rPreviousItemArea ) const + { + Point aNewPos( i_rPreviousItemArea.BottomLeft() ); + aNewPos.Y() += ITEM_DISTANCE_PIXEL; + return aNewPos; + } + + //------------------------------------------------------------------------------------------------------------------ + void VerticalItemLayout::DrawItem( const PToolPanel& i_pPanel, Window& i_rTargetWindow, const Rectangle& i_rItemRect, + const ItemFlags i_nItemFlags, const bool i_bDrawMinimal ) + { + const Size aItemSize( CalculateItemSize( i_pPanel, i_rTargetWindow, i_bDrawMinimal ) ); + + Point aDrawPos( i_rItemRect.TopLeft() ); + aDrawPos.Y() += ITEM_OUTER_SPACE; + + // draw the image + const Image aItemImage( i_pPanel->GetImage() ); + if ( !!aItemImage ) + { + const Size aImageSize( aItemImage.GetSizePixel() ); + i_rTargetWindow.DrawImage( + Point( aDrawPos.X() + ( aItemSize.Width() - aImageSize.Width() ) / 2, aDrawPos.Y() ), + aItemImage + ); + aDrawPos.Y() += aImageSize.Height() + ITEM_ICON_TEXT_DISTANCE; + } + + if ( !i_bDrawMinimal ) + { + // draw the text + i_rTargetWindow.Push( PUSH_FONT ); + + Font aFont( i_rTargetWindow.GetFont() ); + aFont.SetOrientation( 2700 ); + aFont.SetVertical( TRUE ); + i_rTargetWindow.SetFont( aFont ); + + const ::rtl::OUString sItemText( i_pPanel->GetDisplayName() ); + const Size aTextSize( i_rTargetWindow.GetCtrlTextWidth( sItemText ), i_rTargetWindow.GetTextHeight() ); + + Point aTextPos( aDrawPos ); + aTextPos.X() += aTextSize.Height(); + aTextPos.X() += ( i_rItemRect.GetWidth() - aTextSize.Height() ) / 2; + + i_rTargetWindow.DrawText( aTextPos, sItemText ); + + i_rTargetWindow.Pop(); + } + + const bool bActive = ( ( i_nItemFlags & ITEM_STATE_ACTIVE ) != 0 ); + const bool bHovered = ( ( i_nItemFlags & ITEM_STATE_HOVERED ) != 0 ); + if ( bActive || bHovered ) + { + Rectangle aSelectionRect( i_rItemRect ); + aSelectionRect.Left() += ITEM_OUTER_SPACE / 2; + aSelectionRect.Top() += ITEM_OUTER_SPACE / 2; + aSelectionRect.Right() -= ITEM_OUTER_SPACE / 2; + aSelectionRect.Bottom() -= ITEM_OUTER_SPACE / 2; + i_rTargetWindow.DrawSelectionBackground( + aSelectionRect, + bHovered ? ( bActive ? 1 : 2 ) : 0 /* hilight */, + FALSE /* check */, + TRUE /* border */, + FALSE /* ext border only */, + 0 /* corner radius */, + NULL, + NULL + ); + } + } + + //================================================================================================================== + //= ItemDescriptor + //================================================================================================================== + struct ItemDescriptor + { + PToolPanel pPanel; + Rectangle aMinArea; + Rectangle aPrefArea; + bool bUseMinimal; + + ItemDescriptor() + :pPanel() + ,aMinArea() + ,aPrefArea() + ,bUseMinimal( false ) + { + } + + const Rectangle& GetCurrentRect() const + { + return bUseMinimal ? aMinArea : aPrefArea; + } + }; + + typedef ::std::vector< ItemDescriptor > ItemDescriptors; + + //================================================================================================================== + //= PanelTabBar_Data + //================================================================================================================== + class PanelTabBar_Data :public IToolPanelContainerListener + ,public IToolPanelDeckListener + { + public: + PanelTabBar_Data( PanelTabBar& i_rTabBar ) + :rTabBar( i_rTabBar ) + ,rPanelDeck( dynamic_cast< ToolPanelDeck& >( *i_rTabBar.GetParent() ) ) + ,pLayout( new VerticalItemLayout ) + ,aHoveredItem() + ,bMouseButtonDown( false ) + ,aItems() + ,bItemsDirty( true ) + { + rPanelDeck.AddListener( *this ); + rPanelDeck.GetPanels()->AddListener( *this ); + } + + ~PanelTabBar_Data() + { + rPanelDeck.GetPanels()->RemoveListener( *this ); + rPanelDeck.RemoveListener( *this ); + } + + // IToolPanelContainerListener + virtual void PanelInserted( const PToolPanel& i_pPanel, const size_t i_nPosition ) + { + bItemsDirty = true; + } + + // IToolPanelDeckListener + virtual void ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const size_t i_nNewActive ); + + public: + PanelTabBar& rTabBar; + ToolPanelDeck& rPanelDeck; + const PItemsLayout pLayout; + ::boost::optional< size_t > aHoveredItem; + bool bMouseButtonDown; + + ItemDescriptors aItems; + bool bItemsDirty; + }; + + //================================================================================================================== + //= helper + //================================================================================================================== + namespace + { + //-------------------------------------------------------------------------------------------------------------- + #if OSL_DEBUG_LEVEL > 0 + static void lcl_checkConsistency( const PanelTabBar_Data& i_rData ) + { + if ( !i_rData.rPanelDeck.GetPanels().get() ) + { + OSL_ENSURE( false, "lcl_checkConsistency: NULL panels?!" ); + return; + } + if ( !i_rData.bItemsDirty ) + { + if ( i_rData.rPanelDeck.GetPanels()->GetPanelCount() != i_rData.aItems.size() ) + { + OSL_ENSURE( false, "lcl_checkConsistency: inconsistent array sizes!" ); + return; + } + for ( size_t i = 0; i < i_rData.rPanelDeck.GetPanels()->GetPanelCount(); ++i ) + { + if ( i_rData.rPanelDeck.GetPanels()->GetPanel( i ).get() != i_rData.aItems[i].pPanel.get() ) + { + OSL_ENSURE( false, "lcl_checkConsistency: array elements are inconsistent!" ); + return; + } + } + } + } + + #define DBG_CHECK( data ) \ + lcl_checkConsistency( data ); + #else + #define DBG_CHECK( data ) \ + (void)data; + #endif + + //-------------------------------------------------------------------------------------------------------------- + static void lcl_calcItemRects( PanelTabBar_Data& io_rData, const OutputDevice& i_rReferenceDevice ) + { + io_rData.aItems.resize(0); + + Point aMinItemPos( TAB_BAR_OUTER_SPACE, TAB_BAR_OUTER_SPACE ); + Point aPrefItemPos( TAB_BAR_OUTER_SPACE, TAB_BAR_OUTER_SPACE ); + + for ( size_t i = 0; + i < io_rData.rPanelDeck.GetPanels()->GetPanelCount(); + ++i + ) + { + PToolPanel pPanel( io_rData.rPanelDeck.GetPanels()->GetPanel( i ) ); + + ItemDescriptor aItem; + aItem.pPanel = pPanel; + + const Size aMinItemSize = io_rData.pLayout->CalculateItemSize( pPanel, i_rReferenceDevice, true ); + const Size aPrefItemSize = io_rData.pLayout->CalculateItemSize( pPanel, i_rReferenceDevice, false ); + // TODO: have one method calculating both sizes + + aItem.aMinArea = Rectangle( aMinItemPos, aMinItemSize ); + aItem.aPrefArea = Rectangle( aPrefItemPos, aPrefItemSize ); + + io_rData.aItems.push_back( aItem ); + + aMinItemPos = io_rData.pLayout->GetNextItemPosition( aItem.aMinArea ); + aPrefItemPos = io_rData.pLayout->GetNextItemPosition( aItem.aPrefArea ); + } + + io_rData.bItemsDirty = false; + } + + //-------------------------------------------------------------------------------------------------------------- + static void lcl_ensureItemsCache( PanelTabBar_Data& io_rData, const OutputDevice& i_rReferenceDevice ) + { + if ( io_rData.bItemsDirty == false ) + { + DBG_CHECK( io_rData ); + return; + } + lcl_calcItemRects( io_rData, i_rReferenceDevice ); + OSL_POSTCOND( io_rData.bItemsDirty == false, "lcl_ensureItemsCache: cache still dirty!" ); + DBG_CHECK( io_rData ); + } + + //-------------------------------------------------------------------------------------------------------------- + static ::boost::optional< size_t > lcl_findItemForPoint( const PanelTabBar_Data& i_rData, const Point& i_rPoint ) + { + size_t i=0; + for ( ItemDescriptors::const_iterator item = i_rData.aItems.begin(); + item != i_rData.aItems.end(); + ++item, ++i + ) + { + const Rectangle& rItemRect( item->GetCurrentRect() ); + if ( rItemRect.IsInside( i_rPoint ) ) + { + return ::boost::optional< size_t >( i ); + } + } + return ::boost::optional< size_t >(); + } + + //-------------------------------------------------------------------------------------------------------------- + static void lcl_drawItem( const PanelTabBar_Data& i_rData, const size_t i_nItemIndex ) + { + const ItemDescriptor& rItem( i_rData.aItems[ i_nItemIndex ] ); + + ItemFlags nItemFlags( ITEM_STATE_NORMAL ); + if ( i_rData.aHoveredItem == i_nItemIndex ) + { + nItemFlags |= ITEM_STATE_HOVERED; + if ( i_rData.bMouseButtonDown ) + nItemFlags |= ITEM_STATE_ACTIVE; + } + + if ( i_rData.rPanelDeck.GetActivePanel() == i_nItemIndex ) + nItemFlags |= ITEM_STATE_ACTIVE; + + i_rData.rTabBar.DrawRect( rItem.GetCurrentRect() ); + i_rData.pLayout->DrawItem( rItem.pPanel, i_rData.rTabBar, rItem.GetCurrentRect(), nItemFlags, rItem.bUseMinimal ); + } + + //-------------------------------------------------------------------------------------------------------------- + static void lcl_drawItems( const PanelTabBar_Data& i_rData, PanelTabBar& i_rTabBar, const Rectangle& i_rTargetArea ) + { + size_t i=0; + for ( ItemDescriptors::const_iterator item = i_rData.aItems.begin(); + item != i_rData.aItems.end(); + ++item, ++i + ) + { + const Rectangle& rItemRect( item->GetCurrentRect() ); + if ( rItemRect.IsOver( i_rTargetArea ) ) + { + lcl_drawItem( i_rData, i ); + } + } + } + } + + //================================================================================================================== + //= PanelTabBar_Data + //================================================================================================================== + void PanelTabBar_Data::ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const size_t i_nNewActive ) + { + lcl_ensureItemsCache( *this, rTabBar ); + + if ( !!i_rOldActive ) + lcl_drawItem( *this, *i_rOldActive ); + lcl_drawItem( *this, i_nNewActive ); + } + + //================================================================================================================== + //= PanelTabBar + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + PanelTabBar::PanelTabBar( ToolPanelDeck& i_rPanelDeck ) + :Control( &i_rPanelDeck, 0 ) + ,m_pData( new PanelTabBar_Data( *this ) ) + { + DBG_CHECK( *m_pData ); + + SetLineColor(); + SetFillColor( GetSettings().GetStyleSettings().GetDialogColor() ); + } + + //------------------------------------------------------------------------------------------------------------------ + PanelTabBar::~PanelTabBar() + { + } + + //------------------------------------------------------------------------------------------------------------------ + Size PanelTabBar::GetOptimalSize( WindowSizeType i_eType ) const + { + lcl_ensureItemsCache( *m_pData, *this ); + + if ( m_pData->aItems.empty() ) + return Size( 2 * TAB_BAR_OUTER_SPACE, 2 * TAB_BAR_OUTER_SPACE ); + + const bool nMinimalSize = ( i_eType == WINDOWSIZE_MINIMUM ); + // the rect of the last item + const Rectangle& rLastItemRect( nMinimalSize ? m_pData->aItems.rbegin()->aMinArea : m_pData->aItems.rbegin()->aPrefArea ); + const Point aBottomRight( rLastItemRect.BottomRight() ); + return Size( aBottomRight.X() + TAB_BAR_OUTER_SPACE, aBottomRight.Y() + TAB_BAR_OUTER_SPACE ); + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar::Resize() + { + Control::Resize(); + + // decide whether we should use the minimal or the prefered version of the items + const Size aPreferredSize( GetOptimalSize( WINDOWSIZE_PREFERRED ) ); + const Size aOutputSize( GetOutputSizePixel() ); + const bool bDrawMinimal( aPreferredSize.Height() >= aOutputSize.Height() ); + + for ( ItemDescriptors::iterator item = m_pData->aItems.begin(); + item != m_pData->aItems.end(); + ++item + ) + { + item->bUseMinimal = bDrawMinimal; + } + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar::Paint( const Rectangle& i_rRect ) + { + lcl_ensureItemsCache( *m_pData, *this ); + + // background + DrawRect( Rectangle( Point(), GetOutputSizePixel() ) ); + + // items + lcl_drawItems( *m_pData, *this, i_rRect ); + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar::MouseMove( const MouseEvent& i_rMouseEvent ) + { + lcl_ensureItemsCache( *m_pData, *this ); + + ::boost::optional< size_t > aOldItem( m_pData->aHoveredItem ); + ::boost::optional< size_t > aNewItem( lcl_findItemForPoint( *m_pData, i_rMouseEvent.GetPosPixel() ) ); + + if ( i_rMouseEvent.IsLeaveWindow() ) + aNewItem.reset(); + + if ( aOldItem != aNewItem ) + { + m_pData->aHoveredItem = aNewItem; + + if ( !!aOldItem ) + { + lcl_drawItem( *m_pData, *aOldItem ); + } + + if ( !!aNewItem ) + { + lcl_drawItem( *m_pData, *aNewItem ); + } + } + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar::MouseButtonDown( const MouseEvent& i_rMouseEvent ) + { + Control::MouseButtonDown( i_rMouseEvent ); + + if ( !i_rMouseEvent.IsLeft() ) + return; + + lcl_ensureItemsCache( *m_pData, *this ); + + ::boost::optional< size_t > aHitItem( lcl_findItemForPoint( *m_pData, i_rMouseEvent.GetPosPixel() ) ); + if ( !aHitItem ) + return; + + CaptureMouse(); + m_pData->bMouseButtonDown = true; + + lcl_drawItem( *m_pData, *aHitItem ); + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar::MouseButtonUp( const MouseEvent& i_rMouseEvent ) + { + Control::MouseButtonUp( i_rMouseEvent ); + + if ( m_pData->bMouseButtonDown ) + { + OSL_ENSURE( IsMouseCaptured(), "PanelTabBar::MouseButtonUp: inconsistency!" ); + if ( IsMouseCaptured() ) + ReleaseMouse(); + m_pData->bMouseButtonDown = false; + + ::boost::optional< size_t > aHitItem( lcl_findItemForPoint( *m_pData, i_rMouseEvent.GetPosPixel() ) ); + if ( !!aHitItem ) + { + // re-draw that item now that we're not in mouse-down mode anymore + lcl_drawItem( *m_pData, *aHitItem ); + // activate the respective panel + m_pData->rPanelDeck.ActivatePanel( *aHitItem ); + } + } + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar::RequestHelp( const HelpEvent& i_rHelpEvent ) + { + lcl_ensureItemsCache( *m_pData, *this ); + + ::boost::optional< size_t > aHelpItem( lcl_findItemForPoint( *m_pData, ScreenToOutputPixel( i_rHelpEvent.GetMousePosPixel() ) ) ); + if ( !aHelpItem ) + return; + + const ItemDescriptor& rItem( m_pData->aItems[ *aHelpItem ] ); + if ( !rItem.bUseMinimal ) + // if we do not use the minimal representation of the item, then the text is completely drawn - no + // need to show it as tooltip, too + return; + + const ::rtl::OUString sItemText( rItem.pPanel->GetDisplayName() ); + if ( i_rHelpEvent.GetMode() == HELPMODE_BALLOON ) + Help::ShowBalloon( this, OutputToScreenPixel( rItem.GetCurrentRect().Center() ), rItem.GetCurrentRect(), sItemText ); + else + Help::ShowQuickHelp( this, rItem.GetCurrentRect(), sItemText ); + } + +//........................................................................ +} // namespace svt +//........................................................................ diff --git a/svtools/source/toolpanel/paneltabbar.hxx b/svtools/source/toolpanel/paneltabbar.hxx new file mode 100644 index 000000000000..abbc82173c57 --- /dev/null +++ b/svtools/source/toolpanel/paneltabbar.hxx @@ -0,0 +1,75 @@ +/************************************************************************* + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ +#ifndef PANELTABBAR_HXX +#define PANELTABBAR_HXX + +#include "svtools/toolpanel/toolpanelcontainer.hxx" + +#include <vcl/ctrl.hxx> + +#include <memory> + +//........................................................................ +namespace svt +{ +//........................................................................ + + class ToolPanelDeck; + class PanelTabBar_Data; + + //==================================================================== + //= PanelTabBar + //==================================================================== + /** a tab bar for selecting panels + + At the moment, this control aligns the tabs vertically, this might be extended to also support a horizontal + layout in the future. + */ + class PanelTabBar : public Control + { + public: + PanelTabBar( ToolPanelDeck& i_rParent ); + ~PanelTabBar(); + + // Window overridables + virtual Size GetOptimalSize( WindowSizeType i_eType ) const; + virtual void Paint( const Rectangle& i_rRect ); + virtual void Resize(); + virtual void MouseMove( const MouseEvent& i_rMouseEvent ); + virtual void MouseButtonDown( const MouseEvent& i_rMouseEvent ); + virtual void MouseButtonUp( const MouseEvent& i_rMouseEvent ); + virtual void RequestHelp( const HelpEvent& i_rHelpEvent ); + + private: + ::std::auto_ptr< PanelTabBar_Data > m_pData; + }; + +//........................................................................ +} // namespace svt +//........................................................................ + +#endif // PANELTABBAR_HXX + diff --git a/svtools/source/toolpanel/refbase.cxx b/svtools/source/toolpanel/refbase.cxx new file mode 100644 index 000000000000..cd4433045b33 --- /dev/null +++ b/svtools/source/toolpanel/refbase.cxx @@ -0,0 +1,56 @@ +/************************************************************************* + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +#include "precompiled_svtools.hxx" + +#include "refbase.hxx" + +//........................................................................ +namespace svt +{ +//........................................................................ + + //==================================================================== + //= RefBase + //==================================================================== + //-------------------------------------------------------------------- + oslInterlockedCount SAL_CALL RefBase::acquire() + { + return osl_incrementInterlockedCount( &m_refCount ); + } + + //-------------------------------------------------------------------- + oslInterlockedCount SAL_CALL RefBase::release() + { + oslInterlockedCount newCount = osl_decrementInterlockedCount( &m_refCount ); + if ( 0 == newCount ) + delete this; + return newCount; + } + +//........................................................................ +} // namespace svt +//........................................................................ diff --git a/svtools/source/toolpanel/refbase.hxx b/svtools/source/toolpanel/refbase.hxx new file mode 100644 index 000000000000..4cbcc41ffd2a --- /dev/null +++ b/svtools/source/toolpanel/refbase.hxx @@ -0,0 +1,78 @@ +/************************************************************************* + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +#ifndef REFBASE_HXX +#define REFBASE_HXX + +#include <osl/interlck.h> + +//........................................................................ +namespace svt +{ +//........................................................................ + + //==================================================================== + //= RefBase + //==================================================================== + class RefBase + { + protected: + RefBase() + :m_refCount( 0 ) + { + } + + virtual ~RefBase() + { + } + + virtual oslInterlockedCount SAL_CALL acquire(); + virtual oslInterlockedCount SAL_CALL release(); + + private: + oslInterlockedCount m_refCount; + }; + +#define DECLARE_IREFERENCE() \ + virtual oslInterlockedCount SAL_CALL acquire(); \ + virtual oslInterlockedCount SAL_CALL release(); + + +#define IMPLEMENT_IREFERENCE( classname ) \ + oslInterlockedCount classname::acquire() \ + { \ + return RefBase::acquire(); \ + } \ + oslInterlockedCount classname::release() \ + { \ + return RefBase::release(); \ + } + +//........................................................................ +} // namespace svt +//........................................................................ + +#endif // REFBASE_HXX diff --git a/svtools/source/toolpanel/tablayouter.cxx b/svtools/source/toolpanel/tablayouter.cxx index 3f6f57453356..7b237e8f09f6 100644 --- a/svtools/source/toolpanel/tablayouter.cxx +++ b/svtools/source/toolpanel/tablayouter.cxx @@ -27,6 +27,8 @@ #include "precompiled_svtools.hxx" #include "svtools/toolpanel/tablayouter.hxx" +#include "svtools/toolpanel/toolpaneldeck.hxx" +#include "paneltabbar.hxx" #include <tools/gen.hxx> @@ -40,17 +42,39 @@ namespace svt //==================================================================== struct TabDeckLayouter_Data { - TabAlignment eAlignment; + TabAlignment eAlignment; + PToolPanelContainer pPanels; + ::std::auto_ptr< PanelTabBar > + pTabBar; + + TabDeckLayouter_Data( const TabAlignment i_eAlignment, ToolPanelDeck& i_rPanelDeck ) + :eAlignment( i_eAlignment ) + ,pPanels( i_rPanelDeck.GetPanels() ) + ,pTabBar( new PanelTabBar( i_rPanelDeck ) ) + { + pTabBar->Show(); + } }; //==================================================================== + //= helper + //==================================================================== + namespace + { + static bool lcl_isVerticalTabBar( const TabAlignment i_eAlignment ) + { + return ( i_eAlignment == TABS_RIGHT ) + || ( i_eAlignment == TABS_LEFT ); + } + } + + //==================================================================== //= TabDeckLayouter //==================================================================== //-------------------------------------------------------------------- - TabDeckLayouter::TabDeckLayouter( const TabAlignment i_eAlignment ) - :m_pData( new TabDeckLayouter_Data ) + TabDeckLayouter::TabDeckLayouter( const TabAlignment i_eAlignment, ToolPanelDeck& i_rPanelDeck ) + :m_pData( new TabDeckLayouter_Data( i_eAlignment, i_rPanelDeck ) ) { - m_pData->eAlignment = i_eAlignment; } //-------------------------------------------------------------------- @@ -59,12 +83,55 @@ namespace svt } //-------------------------------------------------------------------- + IMPLEMENT_IREFERENCE( TabDeckLayouter ) + + //-------------------------------------------------------------------- Rectangle TabDeckLayouter::Layout( const Rectangle& i_rDeckPlayground ) { - // TODO + if ( !m_pData->pTabBar.get() ) + { + OSL_ENSURE( false, "TabDeckLayouter::Layout: disposed!" ); + return i_rDeckPlayground; + } + + if ( lcl_isVerticalTabBar( m_pData->eAlignment ) ) + { + const Size aPreferredSize( m_pData->pTabBar->GetOptimalSize( WINDOWSIZE_PREFERRED ) ); + Size aTabBarSize = ( aPreferredSize.Width() < i_rDeckPlayground.GetWidth() ) + ? aPreferredSize + : m_pData->pTabBar->GetOptimalSize( WINDOWSIZE_MINIMUM ); + aTabBarSize.Height() = i_rDeckPlayground.GetHeight(); + + Rectangle aPanelRect( i_rDeckPlayground ); + if ( m_pData->eAlignment == TABS_RIGHT ) + { + aPanelRect.Right() -= aTabBarSize.Width(); + Point aTabBarTopLeft( aPanelRect.TopRight() ); + aTabBarTopLeft.X() += 1; + m_pData->pTabBar->SetPosSizePixel( aTabBarTopLeft, aTabBarSize ); + } + else + { + m_pData->pTabBar->SetPosSizePixel( aPanelRect.TopLeft(), aTabBarSize ); + aPanelRect.Left() += aTabBarSize.Width(); + } + if ( aPanelRect.Left() >= aPanelRect.Right() ) + aPanelRect = Rectangle(); + + return aPanelRect; + } + + OSL_ENSURE( false, "TabDeckLayouter::Layout: unreachable!" ); + // currently there do not even exist enum values for other alignments ... return i_rDeckPlayground; } + //-------------------------------------------------------------------- + void TabDeckLayouter::Destroy() + { + m_pData->pTabBar.reset(); + } + //........................................................................ } // namespace svt //........................................................................ diff --git a/svtools/source/toolpanel/toolpanelcollection.cxx b/svtools/source/toolpanel/toolpanelcollection.cxx index ff274075f108..b0a2571fc71e 100644 --- a/svtools/source/toolpanel/toolpanelcollection.cxx +++ b/svtools/source/toolpanel/toolpanelcollection.cxx @@ -26,7 +26,7 @@ #include "precompiled_svtools.hxx" -#include "svtools/toolpanel/toolpanelcollection.hxx" +#include "toolpanelcollection.hxx" #include <tools/diagnose_ex.h> @@ -42,7 +42,8 @@ namespace svt //==================================================================== struct ToolPanelCollection_Data { - ::std::vector< PToolPanel > aPanels; + ::std::vector< PToolPanel > aPanels; + ::std::vector< IToolPanelContainerListener* > aListeners; }; //==================================================================== @@ -60,6 +61,9 @@ namespace svt } //-------------------------------------------------------------------- + IMPLEMENT_IREFERENCE( ToolPanelCollection ) + + //-------------------------------------------------------------------- size_t ToolPanelCollection::GetPanelCount() const { return m_pData->aPanels.size(); @@ -75,20 +79,49 @@ namespace svt } //-------------------------------------------------------------------- - size_t ToolPanelCollection::InsertPanel( const PToolPanel& i_pPanel, const size_t i_pPosition ) + size_t ToolPanelCollection::InsertPanel( const PToolPanel& i_pPanel, const size_t i_nPosition ) { OSL_ENSURE( i_pPanel.get(), "ToolPanelCollection::InsertPanel: illegal panel!" ); if ( !i_pPanel.get() ) return 0; - const size_t position = i_pPosition < m_pData->aPanels.size() ? i_pPosition : m_pData->aPanels.size(); + const size_t position = i_nPosition < m_pData->aPanels.size() ? i_nPosition : m_pData->aPanels.size(); m_pData->aPanels.insert( m_pData->aPanels.begin() + position, i_pPanel ); - // TODO: notification. The tool panel deck which owns us is certainly interested in this event ... + // notifications + for ( ::std::vector< IToolPanelContainerListener* >::const_iterator loop = m_pData->aListeners.begin(); + loop != m_pData->aListeners.end(); + ++loop + ) + { + (*loop)->PanelInserted( i_pPanel, i_nPosition ); + } return position; } + //-------------------------------------------------------------------- + void ToolPanelCollection::AddListener( IToolPanelContainerListener& i_rListener ) + { + m_pData->aListeners.push_back( &i_rListener ); + } + + //-------------------------------------------------------------------- + void ToolPanelCollection::RemoveListener( IToolPanelContainerListener& i_rListener ) + { + for ( ::std::vector< IToolPanelContainerListener* >::iterator lookup = m_pData->aListeners.begin(); + lookup != m_pData->aListeners.end(); + ++lookup + ) + { + if ( *lookup == &i_rListener ) + { + m_pData->aListeners.erase( lookup ); + return; + } + } + } + //........................................................................ } // namespace svt //........................................................................ diff --git a/svtools/source/toolpanel/toolpanelcollection.hxx b/svtools/source/toolpanel/toolpanelcollection.hxx new file mode 100644 index 000000000000..3eb5ea7fb44e --- /dev/null +++ b/svtools/source/toolpanel/toolpanelcollection.hxx @@ -0,0 +1,70 @@ +/************************************************************************* + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +#ifndef TOOLPANELCOLLECTION_HXX +#define TOOLPANELCOLLECTION_HXX + +#include "svtools/toolpanel/toolpanelcontainer.hxx" +#include "refbase.hxx" + +#include <memory> + +//........................................................................ +namespace svt +{ +//........................................................................ + + struct ToolPanelCollection_Data; + + //==================================================================== + //= ToolPanelCollection + //==================================================================== + class ToolPanelCollection :public RefBase + ,public IToolPanelContainer + { + public: + ToolPanelCollection(); + ~ToolPanelCollection(); + + // IToolPanelContainer + virtual size_t GetPanelCount() const; + virtual PToolPanel GetPanel( const size_t i_nPos ) const; + virtual size_t InsertPanel( const PToolPanel& i_pPanel, const size_t i_pPosition ); + virtual void AddListener( IToolPanelContainerListener& i_rListener ); + virtual void RemoveListener( IToolPanelContainerListener& i_rListener ); + + // IReference + DECLARE_IREFERENCE() + + private: + ::std::auto_ptr< ToolPanelCollection_Data > m_pData; + }; + +//........................................................................ +} // namespace svt +//........................................................................ + +#endif // TOOLPANELCOLLECTION_HXX diff --git a/svtools/source/toolpanel/toolpaneldeck.cxx b/svtools/source/toolpanel/toolpaneldeck.cxx index 12f85794576e..8bd521689a8a 100644 --- a/svtools/source/toolpanel/toolpaneldeck.cxx +++ b/svtools/source/toolpanel/toolpaneldeck.cxx @@ -27,6 +27,7 @@ #include "precompiled_svtools.hxx" #include "dummypanel.hxx" +#include "toolpanelcollection.hxx" #include "svtools/toolpanel/toolpaneldeck.hxx" #include "svtools/toolpanel/tablayouter.hxx" @@ -46,28 +47,26 @@ namespace svt public: ToolPanelDeck_Impl( ToolPanelDeck& i_rDeck ) :m_rDeck( i_rDeck ) - ,m_aPanels() + ,m_pPanels( new( ToolPanelCollection ) ) ,m_pDummyPanel( new DummyPanel ) ,m_aActivePanel() ,m_pLayouter() ,m_aPanelPlayground() { - // use a default layouter - m_pLayouter.reset( new TabDeckLayouter( TABS_RIGHT ) ); - - // add as listener to the panels collection - we're interested in panels - // being added and removed - // TODO + // TODO: add as listener to the panels collection - we're interested in panels + // being added and removed, as we need to re-layout then } - const ToolPanelCollection& GetPanels() const { return m_aPanels; } - ToolPanelCollection& GetPanels() { return m_aPanels; } + PToolPanelContainer GetPanels() const { return m_pPanels; } + + size_t GetActivePanel() const; + void ActivatePanel( const size_t i_nPanel ); - size_t GetActivePanel() const; - void ActivatePanel( const size_t i_nPanel ); + PDeckLayouter GetLayouter() const { return m_pLayouter; } + void SetLayouter( const PDeckLayouter& i_pNewLayouter ); - PDeckLayouter GetLayouter() const { return m_pLayouter; } - void SetLayouter( const PDeckLayouter& i_pNewLayouter ); + void AddListener( IToolPanelDeckListener& i_rListener ); + void RemoveListener( IToolPanelDeckListener& i_rListener ); /// re-layouts everything void LayoutAll() { ImplDoLayout(); } @@ -81,13 +80,16 @@ namespace svt private: ToolPanelDeck& m_rDeck; - ToolPanelCollection m_aPanels; + PToolPanelContainer m_pPanels; PToolPanel m_pDummyPanel; ::boost::optional< size_t > m_aActivePanel; PDeckLayouter m_pLayouter; Rectangle m_aPanelPlayground; + + ::std::vector< IToolPanelDeckListener* > + m_aListeners; }; //-------------------------------------------------------------------- @@ -95,7 +97,7 @@ namespace svt { if ( !m_aActivePanel ) return m_pDummyPanel; - return m_aPanels.GetPanel( *m_aActivePanel ); + return m_pPanels->GetPanel( *m_aActivePanel ); } //-------------------------------------------------------------------- @@ -121,17 +123,18 @@ namespace svt //-------------------------------------------------------------------- void ToolPanelDeck_Impl::ActivatePanel( const size_t i_nPanel ) { - OSL_ENSURE( i_nPanel < m_aPanels.GetPanelCount(), "ToolPanelDeck_Impl::ActivatePanel: illegal panel no.!" ); - if ( i_nPanel >= m_aPanels.GetPanelCount() ) + OSL_ENSURE( i_nPanel < m_pPanels->GetPanelCount(), "ToolPanelDeck_Impl::ActivatePanel: illegal panel no.!" ); + if ( i_nPanel >= m_pPanels->GetPanelCount() ) return; - if ( !!m_aActivePanel && ( *m_aActivePanel == i_nPanel ) ) + if ( m_aActivePanel == i_nPanel ) return; // hide the old panel const PToolPanel pOldActive( GetActiveOrDummyPanel_Impl() ); pOldActive->Hide(); + const ::boost::optional< size_t > aOldPanel( m_aActivePanel ); m_aActivePanel = i_nPanel; // position and show the new panel @@ -139,8 +142,14 @@ namespace svt pNewActive->SetPosSizePixel( m_aPanelPlayground ); pNewActive->Show(); - // tell the layouter - it might need to adjust its visuals to the new situation - // TODO + // notify listeners + for ( ::std::vector< IToolPanelDeckListener* >::iterator loop = m_aListeners.begin(); + loop != m_aListeners.end(); + ++loop + ) + { + (*loop)->ActivePanelChanged( aOldPanel, *m_aActivePanel ); + } } //-------------------------------------------------------------------- @@ -159,6 +168,28 @@ namespace svt pActive->SetPosSizePixel( m_aPanelPlayground ); } + //-------------------------------------------------------------------- + void ToolPanelDeck_Impl::AddListener( IToolPanelDeckListener& i_rListener ) + { + m_aListeners.push_back( &i_rListener ); + } + + //-------------------------------------------------------------------- + void ToolPanelDeck_Impl::RemoveListener( IToolPanelDeckListener& i_rListener ) + { + for ( ::std::vector< IToolPanelDeckListener* >::iterator lookup = m_aListeners.begin(); + lookup != m_aListeners.end(); + ++lookup + ) + { + if ( *lookup == &i_rListener ) + { + m_aListeners.erase( lookup ); + return; + } + } + } + //==================================================================== //= ToolPanelDeck //==================================================================== @@ -167,11 +198,14 @@ namespace svt :Control( &i_rParent, i_nStyle ) ,m_pImpl( new ToolPanelDeck_Impl( *this ) ) { + // use a default layouter + SetLayouter( PDeckLayouter( new TabDeckLayouter( TABS_RIGHT, *this ) ) ); } //-------------------------------------------------------------------- ToolPanelDeck::~ToolPanelDeck() { + GetLayouter()->Destroy(); } //-------------------------------------------------------------------- @@ -199,15 +233,21 @@ namespace svt } //-------------------------------------------------------------------- - const ToolPanelCollection& ToolPanelDeck::GetPanels() const + PToolPanelContainer ToolPanelDeck::GetPanels() const { return m_pImpl->GetPanels(); } //-------------------------------------------------------------------- - ToolPanelCollection& ToolPanelDeck::GetPanels() + void ToolPanelDeck::AddListener( IToolPanelDeckListener& i_rListener ) { - return m_pImpl->GetPanels(); + m_pImpl->AddListener( i_rListener ); + } + + //-------------------------------------------------------------------- + void ToolPanelDeck::RemoveListener( IToolPanelDeckListener& i_rListener ) + { + m_pImpl->RemoveListener( i_rListener ); } //-------------------------------------------------------------------- |