summaryrefslogtreecommitdiff
path: root/svtools/source/toolpanel/paneltabbar.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'svtools/source/toolpanel/paneltabbar.cxx')
-rw-r--r--svtools/source/toolpanel/paneltabbar.cxx1371
1 files changed, 0 insertions, 1371 deletions
diff --git a/svtools/source/toolpanel/paneltabbar.cxx b/svtools/source/toolpanel/paneltabbar.cxx
deleted file mode 100644
index 93a8f04fd233..000000000000
--- a/svtools/source/toolpanel/paneltabbar.cxx
+++ /dev/null
@@ -1,1371 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * This file incorporates work covered by the following license notice:
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed
- * with this work for additional information regarding copyright
- * ownership. The ASF licenses this file to you under the Apache
- * License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.apache.org/licenses/LICENSE-2.0 .
- */
-
-
-#include <svtools/toolpanel/paneltabbar.hxx>
-#include <svtools/toolpanel/toolpaneldeck.hxx>
-#include <svtools/svtresid.hxx>
-#include <svtools/svtools.hrc>
-
-#include "tabitemdescriptor.hxx"
-#include "paneltabbarpeer.hxx"
-#include "tabbargeometry.hxx"
-
-#include <vcl/button.hxx>
-#include <vcl/help.hxx>
-#include <vcl/virdev.hxx>
-#include <vcl/settings.hxx>
-#include <vcl/tabctrl.hxx>
-#include <tools/diagnose_ex.h>
-
-#include <memory>
-#include <vector>
-
-// space around an item
-#define ITEM_OUTER_SPACE 2 * 3
-// spacing before and after an item's text
-#define ITEM_TEXT_FLOW_SPACE 5
-// space between item icon and icon text
-#define ITEM_ICON_TEXT_DISTANCE 4
-
-
-namespace svt
-{
-
-
- using ::com::sun::star::uno::Reference;
- using ::com::sun::star::awt::XWindowPeer;
-
- typedef sal_uInt16 ItemFlags;
-
- #define ITEM_STATE_NORMAL 0x00
- #define ITEM_STATE_ACTIVE 0x01
- #define ITEM_STATE_HOVERED 0x02
- #define ITEM_STATE_FOCUSED 0x04
- #define ITEM_POSITION_FIRST 0x08
- #define ITEM_POSITION_LAST 0x10
-
-
- //= helper
-
- namespace
- {
- ControlState lcl_ItemToControlState( const ItemFlags i_nItemFlags )
- {
- ControlState nState = ControlState::ENABLED;
- if ( i_nItemFlags & ITEM_STATE_FOCUSED ) nState |= ControlState::FOCUSED | ControlState::PRESSED;
- if ( i_nItemFlags & ITEM_STATE_HOVERED ) nState |= ControlState::ROLLOVER;
- if ( i_nItemFlags & ITEM_STATE_ACTIVE ) nState |= ControlState::SELECTED;
- return nState;
- }
- }
-
-
- //= ITabBarRenderer
-
- class SAL_NO_VTABLE ITabBarRenderer
- {
- public:
- /** fills the background of our target device
- */
- virtual void renderBackground() const = 0;
- virtual Rectangle calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const = 0;
- virtual void preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const = 0;
- virtual void postRenderItem( vcl::Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const = 0;
-
- // TODO: postRenderItem takes the "real" window, i.e. effectively the tab bar. This is because
- // DrawSelectionBackground needs to be applied after everything else is painted, and is available at the Window
- // class, but not at the OutputDevice. This makes the API somewhat weird, as we're now mixing operations on the
- // target device, done in a normalized geometry, with operations on the window, done in a transformed geometry.
- // So, we should get rid of postRenderItem completely.
-
- protected:
- ~ITabBarRenderer() {}
- };
- typedef std::shared_ptr< ITabBarRenderer > PTabBarRenderer;
-
-
- //= VCLItemRenderer - declaration
-
- class VCLItemRenderer : public ITabBarRenderer
- {
- public:
- explicit VCLItemRenderer( OutputDevice& i_rTargetDevice )
- :m_rTargetDevice( i_rTargetDevice )
- {
- }
- virtual ~VCLItemRenderer() {}
-
- // ITabBarRenderer
- virtual void renderBackground() const override;
- virtual Rectangle calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const override;
- virtual void preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const override;
- virtual void postRenderItem( vcl::Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const override;
-
- protected:
- OutputDevice& getTargetDevice() const { return m_rTargetDevice; }
-
- private:
- OutputDevice& m_rTargetDevice;
- };
-
-
- //= VCLItemRenderer - implementation
-
-
- void VCLItemRenderer::renderBackground() const
- {
- getTargetDevice().DrawRect( Rectangle( Point(), getTargetDevice().GetOutputSizePixel() ) );
- }
-
-
- Rectangle VCLItemRenderer::calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const
- {
- (void)i_nItemFlags;
- // no decorations at all
- return i_rContentArea;
- }
-
-
- void VCLItemRenderer::preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const
- {
- (void)i_rContentRect;
- (void)i_nItemFlags;
- }
-
-
- void VCLItemRenderer::postRenderItem( vcl::Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const
- {
- const bool bActive = ( ( i_nItemFlags & ITEM_STATE_ACTIVE ) != 0 );
- const bool bHovered = ( ( i_nItemFlags & ITEM_STATE_HOVERED ) != 0 );
- const bool bFocused = ( ( i_nItemFlags & ITEM_STATE_FOCUSED ) != 0 );
- if ( bActive || bHovered || bFocused )
- {
- 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_rActualWindow.DrawSelectionBackground(
- aSelectionRect,
- ( bHovered || bFocused ) ? ( bActive ? 1 : 2 ) : 0 /* highlight */,
- bActive /* check */,
- true /* border */,
- false /* ext border only */,
- 0 /* corner radius */,
- nullptr,
- nullptr
- );
- }
- }
-
-
- //= NWFToolboxItemRenderer - declaration
-
- class NWFToolboxItemRenderer : public ITabBarRenderer
- {
- public:
- explicit NWFToolboxItemRenderer( OutputDevice& i_rTargetDevice )
- :m_rTargetDevice( i_rTargetDevice )
- {
- }
- virtual ~NWFToolboxItemRenderer() {}
-
- // ITabBarRenderer
- virtual void renderBackground() const override;
- virtual Rectangle calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const override;
- virtual void preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const override;
- virtual void postRenderItem( vcl::Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const override;
-
- protected:
- OutputDevice& getTargetDevice() const { return m_rTargetDevice; }
-
- private:
- OutputDevice& m_rTargetDevice;
- };
-
-
- //= NWFToolboxItemRenderer - implementation
-
-
- void NWFToolboxItemRenderer::renderBackground() const
- {
- getTargetDevice().DrawRect( Rectangle( Point(), getTargetDevice().GetOutputSizePixel() ) );
- }
-
-
- Rectangle NWFToolboxItemRenderer::calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const
- {
- // don't ask GetNativeControlRegion, this will not deliver proper results in all cases.
- // Instead, simply assume that both the content and the bounding region are the same.
-// const ControlState nState( lcl_ItemToControlState( i_nItemFlags );
-// const ImplControlValue aControlValue;
-// bool bNativeOK = m_rTargetWindow.GetNativeControlRegion(
-// CTRL_TOOLBAR, PART_BUTTON,
-// i_rContentArea, nState,
-// aControlValue, OUString(),
-// aBoundingRegion, aContentRegion
-// );
- (void)i_nItemFlags;
- return Rectangle(
- Point( i_rContentArea.Left() - 1, i_rContentArea.Top() - 1 ),
- Size( i_rContentArea.GetWidth() + 2, i_rContentArea.GetHeight() + 2 )
- );
- }
-
-
- void NWFToolboxItemRenderer::preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const
- {
- const ControlState nState = lcl_ItemToControlState( i_nItemFlags );
-
- ImplControlValue aControlValue;
- aControlValue.setTristateVal( ( i_nItemFlags & ITEM_STATE_ACTIVE ) ? BUTTONVALUE_ON : BUTTONVALUE_OFF );
-
- bool bNativeOK = getTargetDevice().DrawNativeControl( CTRL_TOOLBAR, PART_BUTTON, i_rContentRect, nState, aControlValue, OUString() );
- (void)bNativeOK;
- OSL_ENSURE( bNativeOK, "NWFToolboxItemRenderer::preRenderItem: inconsistent NWF implementation!" );
- // IsNativeControlSupported returned true, previously, otherwise we would not be here ...
- }
-
-
- void NWFToolboxItemRenderer::postRenderItem( vcl::Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const
- {
- (void)i_rActualWindow;
- (void)i_rItemRect;
- (void)i_nItemFlags;
- }
-
-
-#if defined WNT
- //= NWFTabItemRenderer - declaration
-
- class NWFTabItemRenderer : public ITabBarRenderer
- {
- public:
- explicit NWFTabItemRenderer( OutputDevice& i_rTargetDevice )
- :m_rTargetDevice( i_rTargetDevice )
- {
- }
-
- virtual ~NWFTabItemRenderer() {}
-
- // ITabBarRenderer
- virtual void renderBackground() const override;
- virtual Rectangle calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const override;
- virtual void preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const override;
- virtual void postRenderItem( vcl::Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const override;
-
- protected:
- OutputDevice& getTargetDevice() const { return m_rTargetDevice; }
-
- private:
- OutputDevice& m_rTargetDevice;
- };
-
-
- //= NWFTabItemRenderer - implementation
-
-
- void NWFTabItemRenderer::renderBackground() const
- {
- Rectangle aBackground( Point(), getTargetDevice().GetOutputSizePixel() );
- getTargetDevice().DrawRect( aBackground );
-
- aBackground.Top() = aBackground.Bottom();
- getTargetDevice().DrawNativeControl( CTRL_TAB_PANE, PART_ENTIRE_CONTROL, aBackground,
- ControlState::ENABLED, ImplControlValue(), OUString() );
- }
-
-
- Rectangle NWFTabItemRenderer::calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const
- {
- const ControlState nState( lcl_ItemToControlState( i_nItemFlags ) );
-
- TabitemValue tiValue(Rectangle(i_rContentArea.Left() + TAB_TABOFFSET_X,
- i_rContentArea.Right() - TAB_TABOFFSET_X,
- i_rContentArea.Top() + TAB_TABOFFSET_Y,
- i_rContentArea.Bottom() - TAB_TABOFFSET_Y));
-
- Rectangle aBoundingRegion, aContentRegion;
- bool bNativeOK = getTargetDevice().GetNativeControlRegion(
- CTRL_TAB_ITEM, PART_ENTIRE_CONTROL,
- i_rContentArea, nState,
- tiValue, OUString(),
- aBoundingRegion, aContentRegion
- );
- (void)bNativeOK;
- OSL_ENSURE( bNativeOK, "NWFTabItemRenderer::calculateDecorations: GetNativeControlRegion not implemented for CTRL_TAB_ITEM?!" );
-
- return aBoundingRegion;
- }
-
-
- void NWFTabItemRenderer::preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const
- {
- const ControlState nState = lcl_ItemToControlState( i_nItemFlags );
-
- TabitemValue tiValue(Rectangle(i_rContentRect.Left() + TAB_TABOFFSET_X,
- i_rContentRect.Right() - TAB_TABOFFSET_X,
- i_rContentRect.Top() + TAB_TABOFFSET_Y,
- i_rContentRect.Bottom() - TAB_TABOFFSET_Y));
-
- if ( i_nItemFlags & ITEM_POSITION_FIRST )
- tiValue.mnAlignment |= TabitemFlags::FirstInGroup;
- if ( i_nItemFlags & ITEM_POSITION_LAST )
- tiValue.mnAlignment |= TabitemFlags::LastInGroup;
-
-
- bool bNativeOK = getTargetDevice().DrawNativeControl( CTRL_TAB_ITEM, PART_ENTIRE_CONTROL, i_rContentRect, nState, tiValue, OUString() );
- (void)bNativeOK;
- OSL_ENSURE( bNativeOK, "NWFTabItemRenderer::preRenderItem: inconsistent NWF implementation!" );
- // IsNativeControlSupported returned true, previously, otherwise we would not be here ...
- }
-
-
- void NWFTabItemRenderer::postRenderItem( vcl::Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const
- {
- (void)i_rActualWindow;
- (void)i_rItemRect;
- (void)i_nItemFlags;
- }
-#endif
-
- //= PanelTabBar_Impl
-
- class PanelTabBar_Impl : public IToolPanelDeckListener
- {
- public:
- PanelTabBar_Impl(PanelTabBar& i_rTabBar, IToolPanelDeck& i_rPanelDeck,
- const TabAlignment i_eAlignment, const TabItemContent i_eItemContent);
-
- virtual ~PanelTabBar_Impl()
- {
- m_rPanelDeck.RemoveListener(*this);
- }
-
- // IToolPanelDeckListener
- virtual void PanelInserted(const PToolPanel& i_pPanel, const size_t i_nPosition) override
- {
- (void) i_pPanel;
- (void) i_nPosition;
- m_bItemsDirty = true;
- m_rTabBar.Invalidate();
-
- Relayout();
- }
-
- virtual void PanelRemoved( const size_t i_nPosition ) override
- {
- m_bItemsDirty = true;
- m_rTabBar.Invalidate();
-
- if ( i_nPosition < m_nScrollPosition )
- --m_nScrollPosition;
-
- Relayout();
- }
-
- virtual void ActivePanelChanged(const boost::optional<size_t>& i_rOldActive,
- const boost::optional<size_t>& i_rNewActive) override;
- virtual void LayouterChanged(const PDeckLayouter& i_rNewLayouter) override;
- virtual void Dying() override;
-
- void UpdateScrollButtons()
- {
- m_aScrollBack->Enable(m_nScrollPosition > 0);
- m_aScrollForward->Enable(m_nScrollPosition < m_aItems.size() - 1);
- }
-
- void Relayout();
- void EnsureItemsCache();
- boost::optional<size_t> FindItemForPoint( const Point& i_rPoint ) const;
- void DrawItem(vcl::RenderContext& rRenderContext, const size_t i_nItemIndex, const Rectangle& i_rBoundaries) const;
- void InvalidateItem( const size_t i_nItemIndex, const ItemFlags i_nAdditionalItemFlags = 0 ) const;
- void CopyFromRenderDevice(vcl::RenderContext& rRenderContext, const Rectangle& i_rLogicalRect) const;
- Rectangle GetActualLogicalItemRect( const Rectangle& i_rLogicalItemRect ) const;
- Rectangle GetItemScreenRect( const size_t i_nItemPos ) const;
-
- void FocusItem( const ::boost::optional< size_t >& i_rItemPos );
-
- inline bool IsVertical() const
- {
- return ( ( m_eTabAlignment == TABS_LEFT )
- || ( m_eTabAlignment == TABS_RIGHT )
- );
- }
-
- protected:
- DECL_LINK_TYPED( OnScroll, Button*, void );
-
- void impl_calcItemRects();
- Size impl_calculateItemContentSize( const PToolPanel& i_pPanel, const TabItemContent i_eItemContent ) const;
- void impl_renderItemContent(vcl::RenderContext& rRenderContext, const PToolPanel& i_pPanel,
- const Rectangle& i_rContentArea, const TabItemContent i_eItemContent) const;
- ItemFlags impl_getItemFlags( const size_t i_nItemIndex ) const;
-
- public:
- PanelTabBar& m_rTabBar;
- TabBarGeometry m_aGeometry;
- NormalizedArea m_aNormalizer;
- TabAlignment m_eTabAlignment;
- IToolPanelDeck& m_rPanelDeck;
-
- ScopedVclPtr<VirtualDevice> m_aRenderDevice;
- PTabBarRenderer m_pRenderer;
-
- boost::optional<size_t> m_aHoveredItem;
- boost::optional<size_t> m_aFocusedItem;
- bool m_bMouseButtonDown;
-
- ItemDescriptors m_aItems;
- bool m_bItemsDirty;
-
- VclPtr<PushButton> m_aScrollBack;
- VclPtr<PushButton> m_aScrollForward;
-
- size_t m_nScrollPosition;
- };
-
-
- //= helper
-
- namespace
- {
-
- #if OSL_DEBUG_LEVEL > 0
- static void lcl_checkConsistency( const PanelTabBar_Impl& i_rImpl )
- {
- if ( !i_rImpl.m_bItemsDirty )
- {
- if ( i_rImpl.m_rPanelDeck.GetPanelCount() != i_rImpl.m_aItems.size() )
- {
- OSL_FAIL( "lcl_checkConsistency: inconsistent array sizes!" );
- return;
- }
- for ( size_t i = 0; i < i_rImpl.m_rPanelDeck.GetPanelCount(); ++i )
- {
- if ( i_rImpl.m_rPanelDeck.GetPanel( i ).get() != i_rImpl.m_aItems[i].pPanel.get() )
- {
- OSL_FAIL( "lcl_checkConsistency: array elements are inconsistent!" );
- return;
- }
- }
- }
- }
-
- #define DBG_CHECK( data ) \
- lcl_checkConsistency( data );
- #else
- #define DBG_CHECK( data ) \
- (void)data;
- #endif
-
-
- class ClipItemRegion
- {
- public:
- explicit ClipItemRegion( const PanelTabBar_Impl& i_rImpl )
- :m_rDevice( i_rImpl.m_rTabBar )
- {
- m_rDevice.Push( PushFlags::CLIPREGION );
- m_rDevice.SetClipRegion(vcl::Region(
- i_rImpl.m_aNormalizer.getTransformed(
- i_rImpl.m_aGeometry.getItemsRect(),
- i_rImpl.m_eTabAlignment )));
- }
-
- ~ClipItemRegion()
- {
- m_rDevice.Pop();
- }
-
- private:
- OutputDevice& m_rDevice;
- };
- }
-
-
- //= PanelTabBar_Impl - implementation
-
-
- PanelTabBar_Impl::PanelTabBar_Impl( PanelTabBar& i_rTabBar, IToolPanelDeck& i_rPanelDeck, const TabAlignment i_eAlignment, const TabItemContent i_eItemContent )
- :m_rTabBar( i_rTabBar )
- ,m_aGeometry( i_eItemContent )
- ,m_aNormalizer()
- ,m_eTabAlignment( i_eAlignment )
- ,m_rPanelDeck( i_rPanelDeck )
- ,m_aRenderDevice( VclPtr<VirtualDevice>::Create(i_rTabBar) )
- ,m_pRenderer()
- ,m_aHoveredItem()
- ,m_aFocusedItem()
- ,m_bMouseButtonDown( false )
- ,m_aItems()
- ,m_bItemsDirty( true )
- ,m_aScrollBack( VclPtr<PushButton>::Create(&i_rTabBar, WB_BEVELBUTTON) )
- ,m_aScrollForward( VclPtr<PushButton>::Create(&i_rTabBar, WB_BEVELBUTTON) )
- ,m_nScrollPosition( 0 )
- {
-#ifdef WNT
- if (m_aRenderDevice->IsNativeControlSupported(CTRL_TAB_ITEM, PART_ENTIRE_CONTROL))
- // this mode requires the NWF framework to be able to render those items onto a virtual
- // device. For some frameworks (some GTK themes, in particular), this is known to fail.
- // So, be on the safe side for the moment.
- m_pRenderer.reset(new NWFTabItemRenderer(*m_aRenderDevice.get()));
- else
-#endif
- if (m_aRenderDevice->IsNativeControlSupported(CTRL_TOOLBAR, PART_BUTTON))
- m_pRenderer.reset(new NWFToolboxItemRenderer(*m_aRenderDevice.get()));
- else
- m_pRenderer.reset(new VCLItemRenderer(*m_aRenderDevice.get()));
-
- m_aRenderDevice->SetLineColor();
-
- m_rPanelDeck.AddListener( *this );
-
- m_aScrollBack->SetSymbol( IsVertical() ? SymbolType::ARROW_UP : SymbolType::ARROW_LEFT );
- m_aScrollBack->Show();
- m_aScrollBack->SetClickHdl( LINK( this, PanelTabBar_Impl, OnScroll ) );
- m_aScrollBack->SetAccessibleDescription( SvtResId( STR_SVT_TOOL_PANEL_BUTTON_FWD ).toString() );
- m_aScrollBack->SetAccessibleName( m_aScrollBack->GetAccessibleDescription() );
-
- m_aScrollForward->SetSymbol( IsVertical() ? SymbolType::ARROW_DOWN : SymbolType::ARROW_RIGHT );
- m_aScrollForward->Show();
- m_aScrollForward->SetClickHdl( LINK( this, PanelTabBar_Impl, OnScroll ) );
- m_aScrollForward->SetAccessibleDescription( SvtResId( STR_SVT_TOOL_PANEL_BUTTON_BACK ).toString() );
- m_aScrollForward->SetAccessibleName( m_aScrollForward->GetAccessibleDescription() );
- }
-
-
- void PanelTabBar_Impl::impl_calcItemRects()
- {
- m_aItems.resize(0);
-
- Point aCompletePos( m_aGeometry.getFirstItemPosition() );
- Point aIconOnlyPos( aCompletePos );
- Point aTextOnlyPos( aCompletePos );
-
- for ( size_t i = 0;
- i < m_rPanelDeck.GetPanelCount();
- ++i
- )
- {
- PToolPanel pPanel( m_rPanelDeck.GetPanel( i ) );
-
- ItemDescriptor aItem;
- aItem.pPanel = pPanel;
-
- const Size aCompleteSize( impl_calculateItemContentSize( pPanel, TABITEM_IMAGE_AND_TEXT ) );
- const Size aIconOnlySize( impl_calculateItemContentSize( pPanel, TABITEM_IMAGE_ONLY ) );
- const Size aTextOnlySize( impl_calculateItemContentSize( pPanel, TABITEM_TEXT_ONLY ) );
-
- // TODO: have one method calculating all sizes?
-
- // remember the three areas
- aItem.aCompleteArea = Rectangle( aCompletePos, aCompleteSize );
- aItem.aIconOnlyArea = Rectangle( aIconOnlyPos, aIconOnlySize );
- aItem.aTextOnlyArea = Rectangle( aTextOnlyPos, aTextOnlySize );
-
- m_aItems.push_back( aItem );
-
- aCompletePos = aItem.aCompleteArea.TopRight();
- aIconOnlyPos = aItem.aIconOnlyArea.TopRight();
- aTextOnlyPos = aItem.aTextOnlyArea.TopRight();
- }
-
- m_bItemsDirty = false;
- }
-
-
- Size PanelTabBar_Impl::impl_calculateItemContentSize( const PToolPanel& i_pPanel, const TabItemContent i_eItemContent ) const
- {
- // calculate the size needed for the content
- OSL_ENSURE( i_eItemContent != TABITEM_AUTO, "PanelTabBar_Impl::impl_calculateItemContentSize: illegal TabItemContent value!" );
-
- const Image aImage( i_pPanel->GetImage() );
- const bool bUseImage = !!aImage && ( i_eItemContent != TABITEM_TEXT_ONLY );
-
- const OUString sItemText( i_pPanel->GetDisplayName() );
- const bool bUseText = ( !sItemText.isEmpty() ) && ( i_eItemContent != TABITEM_IMAGE_ONLY );
-
- Size aItemContentSize;
- if ( bUseImage )
- {
- aItemContentSize = aImage.GetSizePixel();
- }
-
- if ( bUseText )
- {
- if ( bUseImage )
- aItemContentSize.Width() += ITEM_ICON_TEXT_DISTANCE;
-
- // add space for text
- const Size aTextSize( m_rTabBar.GetCtrlTextWidth( sItemText ), m_rTabBar.GetTextHeight() );
- aItemContentSize.Width() += aTextSize.Width();
- aItemContentSize.Height() = ::std::max( aItemContentSize.Height(), aTextSize.Height() );
-
- aItemContentSize.Width() += 2 * ITEM_TEXT_FLOW_SPACE;
- }
-
- if ( !bUseImage && !bUseText )
- {
- // have a minimal size - this is pure heuristics, but if it doesn't suit your needs, then give your panels
- // a name and or image! :)
- aItemContentSize = Size( 16, 16 );
- }
-
- aItemContentSize.Width() += 2 * ITEM_OUTER_SPACE;
- aItemContentSize.Height() += 2 * ITEM_OUTER_SPACE;
-
- return aItemContentSize;
- }
-
-
- void PanelTabBar_Impl::impl_renderItemContent(vcl::RenderContext& rRenderContext, const PToolPanel& i_pPanel, const Rectangle& i_rContentArea, const TabItemContent i_eItemContent) const
- {
- OSL_ENSURE(i_eItemContent != TABITEM_AUTO, "PanelTabBar_Impl::impl_renderItemContent: illegal TabItemContent value!");
-
- Rectangle aRenderArea(i_rContentArea);
- if (IsVertical())
- {
- aRenderArea.Top() += ITEM_OUTER_SPACE;
- }
- else
- {
- aRenderArea.Left() += ITEM_OUTER_SPACE;
- }
-
- // draw the image
- const Image aItemImage(i_pPanel->GetImage());
- const Size aImageSize(aItemImage.GetSizePixel());
- const bool bUseImage = !!aItemImage && (i_eItemContent != TABITEM_TEXT_ONLY);
-
- if (bUseImage)
- {
- Point aImagePos;
- if (IsVertical())
- {
- aImagePos.X() = aRenderArea.Left() + (aRenderArea.GetWidth() - aImageSize.Width()) / 2;
- aImagePos.Y() = aRenderArea.Top();
- }
- else
- {
- aImagePos.X() = aRenderArea.Left();
- aImagePos.Y() = aRenderArea.Top() + (aRenderArea.GetHeight() - aImageSize.Height()) / 2;
- }
- rRenderContext.DrawImage(aImagePos, aItemImage);
- }
-
- const OUString sItemText(i_pPanel->GetDisplayName());
- const bool bUseText = (!sItemText.isEmpty()) && (i_eItemContent != TABITEM_IMAGE_ONLY);
-
- if (bUseText)
- {
- if (IsVertical())
- {
- if (bUseImage)
- aRenderArea.Top() += aImageSize.Height() + ITEM_ICON_TEXT_DISTANCE;
- aRenderArea.Top() += ITEM_TEXT_FLOW_SPACE;
- }
- else
- {
- if (bUseImage)
- aRenderArea.Left() += aImageSize.Width() + ITEM_ICON_TEXT_DISTANCE;
- aRenderArea.Left() += ITEM_TEXT_FLOW_SPACE;
- }
-
- // draw the text
- const Size aTextSize(m_rTabBar.GetCtrlTextWidth(sItemText), rRenderContext.GetTextHeight());
- Point aTextPos(aRenderArea.TopLeft());
- if (IsVertical())
- {
- rRenderContext.Push(PushFlags::FONT);
-
- vcl::Font aFont(rRenderContext.GetFont());
- aFont.SetOrientation(2700);
- aFont.SetVertical(true);
- rRenderContext.SetFont(aFont);
-
- aTextPos.X() += aTextSize.Height();
- aTextPos.X() += (aRenderArea.GetWidth() - aTextSize.Height()) / 2;
- }
- else
- {
- aTextPos.Y() += (aRenderArea.GetHeight() - aTextSize.Height()) / 2;
- }
-
- rRenderContext.DrawText(aTextPos, sItemText);
-
- if (IsVertical())
- {
- rRenderContext.Pop();
- }
- }
- }
-
- void PanelTabBar_Impl::CopyFromRenderDevice(vcl::RenderContext& rRenderContext, const Rectangle& i_rLogicalRect) const
- {
- BitmapEx aBitmap(m_aRenderDevice->GetBitmapEx(i_rLogicalRect.TopLeft(),
- Size(i_rLogicalRect.GetSize().Width(),
- i_rLogicalRect.GetSize().Height())));
- if (IsVertical())
- {
- aBitmap.Rotate(2700, COL_BLACK);
- if (m_eTabAlignment == TABS_LEFT)
- aBitmap.Mirror(BmpMirrorFlags::Horizontal);
- }
- else if (m_eTabAlignment == TABS_BOTTOM)
- {
- aBitmap.Mirror(BmpMirrorFlags::Vertical);
- }
-
- const Rectangle aActualRect(m_aNormalizer.getTransformed(i_rLogicalRect, m_eTabAlignment));
- rRenderContext.DrawBitmapEx(aActualRect.TopLeft(), aBitmap);
- }
-
-
- void PanelTabBar_Impl::InvalidateItem( const size_t i_nItemIndex, const ItemFlags i_nAdditionalItemFlags ) const
- {
- const ItemDescriptor& rItem( m_aItems[ i_nItemIndex ] );
- const ItemFlags nItemFlags( impl_getItemFlags( i_nItemIndex ) | i_nAdditionalItemFlags );
-
- const Rectangle aNormalizedContent( GetActualLogicalItemRect( rItem.GetCurrentRect() ) );
- const Rectangle aNormalizedBounds( m_pRenderer->calculateDecorations( aNormalizedContent, nItemFlags ) );
-
- const Rectangle aActualBounds = m_aNormalizer.getTransformed( aNormalizedBounds, m_eTabAlignment );
- m_rTabBar.Invalidate( aActualBounds );
- }
-
-
- ItemFlags PanelTabBar_Impl::impl_getItemFlags( const size_t i_nItemIndex ) const
- {
- ItemFlags nItemFlags( ITEM_STATE_NORMAL );
- if ( m_aHoveredItem == i_nItemIndex )
- {
- nItemFlags |= ITEM_STATE_HOVERED;
- if ( m_bMouseButtonDown )
- nItemFlags |= ITEM_STATE_ACTIVE;
- }
-
- if ( m_rPanelDeck.GetActivePanel() == i_nItemIndex )
- nItemFlags |= ITEM_STATE_ACTIVE;
-
- if ( m_aFocusedItem == i_nItemIndex )
- nItemFlags |= ITEM_STATE_FOCUSED;
-
- if ( 0 == i_nItemIndex )
- nItemFlags |= ITEM_POSITION_FIRST;
-
- if ( m_rPanelDeck.GetPanelCount() - 1 == i_nItemIndex )
- nItemFlags |= ITEM_POSITION_LAST;
-
- return nItemFlags;
- }
-
-
- void PanelTabBar_Impl::DrawItem(vcl::RenderContext& rRenderContext, const size_t i_nItemIndex, const Rectangle& i_rBoundaries) const
- {
- const ItemDescriptor& rItem(m_aItems[i_nItemIndex]);
- const ItemFlags nItemFlags(impl_getItemFlags(i_nItemIndex));
-
- // the normalized bounding and content rect
- const Rectangle aNormalizedContent(GetActualLogicalItemRect(rItem.GetCurrentRect()));
- const Rectangle aNormalizedBounds(m_pRenderer->calculateDecorations(aNormalizedContent, nItemFlags));
-
- // check whether the item actually overlaps with the painting area
- if (!i_rBoundaries.IsEmpty())
- {
- const Rectangle aItemRect(GetActualLogicalItemRect(rItem.GetCurrentRect()));
- if (!aItemRect.IsOver(i_rBoundaries))
- return;
- }
-
- m_rTabBar.SetUpdateMode(false);
-
- // the aligned bounding and content rect
- const Rectangle aActualBounds = m_aNormalizer.getTransformed( aNormalizedBounds, m_eTabAlignment );
- const Rectangle aActualContent = m_aNormalizer.getTransformed( aNormalizedContent, m_eTabAlignment );
-
- // render item "background" layer
- m_pRenderer->preRenderItem(aNormalizedContent, nItemFlags);
-
- // copy from the virtual device to ourself
- CopyFromRenderDevice(rRenderContext, aNormalizedBounds);
-
- // render the actual item content
- impl_renderItemContent(rRenderContext, rItem.pPanel, aActualContent, rItem.eContent);
-
- // render item "foreground" layer
- m_pRenderer->postRenderItem(m_rTabBar, aActualBounds, nItemFlags);
-
- m_rTabBar.SetUpdateMode(true);
- }
-
-
- void PanelTabBar_Impl::EnsureItemsCache()
- {
- if ( !m_bItemsDirty )
- {
- DBG_CHECK( *this );
- return;
- }
- impl_calcItemRects();
- SAL_WARN_IF( m_bItemsDirty , "svtools", "PanelTabBar_Impl::EnsureItemsCache: cache still dirty!" );
- DBG_CHECK( *this );
- }
-
-
- void PanelTabBar_Impl::Relayout()
- {
- EnsureItemsCache();
-
- const Size aOutputSize( m_rTabBar.GetOutputSizePixel() );
- m_aNormalizer = NormalizedArea( Rectangle( Point(), aOutputSize ), IsVertical() );
- const Size aLogicalOutputSize( m_aNormalizer.getReferenceSize() );
-
- // forward actual output size to our render device
- m_aRenderDevice->SetOutputSizePixel( aLogicalOutputSize );
-
- // re-calculate the size of the scroll buttons and of the items
- m_aGeometry.relayout( aLogicalOutputSize, m_aItems );
-
- if ( m_aGeometry.getButtonBackRect().IsEmpty() )
- {
- m_aScrollBack->Hide();
- }
- else
- {
- const Rectangle aButtonBack( m_aNormalizer.getTransformed( m_aGeometry.getButtonBackRect(), m_eTabAlignment ) );
- m_aScrollBack->SetPosSizePixel( aButtonBack.TopLeft(), aButtonBack.GetSize() );
- m_aScrollBack->Show();
- }
-
- if ( m_aGeometry.getButtonForwardRect().IsEmpty() )
- {
- m_aScrollForward->Hide();
- }
- else
- {
- const Rectangle aButtonForward( m_aNormalizer.getTransformed( m_aGeometry.getButtonForwardRect(), m_eTabAlignment ) );
- m_aScrollForward->SetPosSizePixel( aButtonForward.TopLeft(), aButtonForward.GetSize() );
- m_aScrollForward->Show();
- }
-
- UpdateScrollButtons();
- }
-
-
- ::boost::optional< size_t > PanelTabBar_Impl::FindItemForPoint( const Point& i_rPoint ) const
- {
- Point aPoint( IsVertical() ? i_rPoint.Y() : i_rPoint.X(), IsVertical() ? i_rPoint.X() : i_rPoint.Y() );
-
- if ( !m_aGeometry.getItemsRect().IsInside( aPoint ) )
- return ::boost::optional< size_t >();
-
- size_t i=0;
- for ( ItemDescriptors::const_iterator item = m_aItems.begin();
- item != m_aItems.end();
- ++item, ++i
- )
- {
- Rectangle aItemRect( GetActualLogicalItemRect( item->GetCurrentRect() ) );
- if ( aItemRect.IsInside( aPoint ) )
- {
- return ::boost::optional< size_t >( i );
- }
- }
- return ::boost::optional< size_t >();
- }
-
-
- Rectangle PanelTabBar_Impl::GetItemScreenRect( const size_t i_nItemPos ) const
- {
- ENSURE_OR_RETURN( i_nItemPos < m_aItems.size(), "PanelTabBar_Impl::GetItemScreenRect: invalid item pos!", Rectangle() );
- const ItemDescriptor& rItem( m_aItems[ i_nItemPos ] );
- const Rectangle aItemRect( m_aNormalizer.getTransformed(
- GetActualLogicalItemRect( rItem.GetCurrentRect() ),
- m_eTabAlignment ) );
-
- const Rectangle aTabBarRect( m_rTabBar.GetWindowExtentsRelative( nullptr ) );
- return Rectangle(
- Point( aTabBarRect.Left() + aItemRect.Left(), aTabBarRect.Top() + aItemRect.Top() ),
- aItemRect.GetSize()
- );
- }
-
-
- void PanelTabBar_Impl::FocusItem( const ::boost::optional< size_t >& i_rItemPos )
- {
- // reset old focus item
- if ( !!m_aFocusedItem )
- InvalidateItem( *m_aFocusedItem );
- m_aFocusedItem.reset();
-
- // mark the active icon as focused
- if ( !!i_rItemPos )
- {
- m_aFocusedItem = i_rItemPos;
- InvalidateItem( *m_aFocusedItem );
- }
- }
-
-
- IMPL_LINK_TYPED( PanelTabBar_Impl, OnScroll, Button*, pButton, void )
- {
- PushButton* i_pButton = static_cast<PushButton*>(pButton);
- if ( i_pButton == m_aScrollBack.get() )
- {
- OSL_ENSURE( m_nScrollPosition > 0, "PanelTabBar_Impl::OnScroll: inconsistency!" );
- --m_nScrollPosition;
- m_rTabBar.Invalidate();
- }
- else if ( i_pButton == m_aScrollForward.get() )
- {
- OSL_ENSURE( m_nScrollPosition < m_aItems.size() - 1, "PanelTabBar_Impl::OnScroll: inconsistency!" );
- ++m_nScrollPosition;
- m_rTabBar.Invalidate();
- }
-
- UpdateScrollButtons();
- }
-
-
- Rectangle PanelTabBar_Impl::GetActualLogicalItemRect( const Rectangle& i_rLogicalItemRect ) const
- {
- // care for the offset imposed by our geometry, i.e. whether or not we have scroll buttons
- Rectangle aItemRect( i_rLogicalItemRect );
- aItemRect.Move( m_aGeometry.getItemsRect().Left() - m_aGeometry.getButtonBackRect().Left(), 0 );
-
- // care for the current scroll position
- OSL_ENSURE( m_nScrollPosition < m_aItems.size(), "GetActualLogicalItemRect: invalid scroll position!" );
- if ( ( m_nScrollPosition > 0 ) && ( m_nScrollPosition < m_aItems.size() ) )
- {
- long nOffsetX = m_aItems[ m_nScrollPosition ].GetCurrentRect().Left() - m_aItems[ 0 ].GetCurrentRect().Left();
- long nOffsetY = m_aItems[ m_nScrollPosition ].GetCurrentRect().Top() - m_aItems[ 0 ].GetCurrentRect().Top();
- aItemRect.Move( -nOffsetX, -nOffsetY );
- }
-
- return aItemRect;
- }
-
-
- //= PanelTabBar_Impl
-
-
- void PanelTabBar_Impl::ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive )
- {
- EnsureItemsCache();
-
- if ( !!i_rOldActive )
- InvalidateItem( *i_rOldActive, ITEM_STATE_ACTIVE );
- if ( !!i_rNewActive )
- InvalidateItem( *i_rNewActive );
- }
-
-
- void PanelTabBar_Impl::LayouterChanged( const PDeckLayouter& i_rNewLayouter )
- {
- // not interested in
- (void)i_rNewLayouter;
- }
-
-
- void PanelTabBar_Impl::Dying()
- {
- // not interested in - the notifier is a member of this instance here, so we're dying ourself at the moment
- }
-
-
- //= PanelTabBar
-
-
- PanelTabBar::PanelTabBar( vcl::Window& i_rParentWindow, IToolPanelDeck& i_rPanelDeck, const TabAlignment i_eAlignment, const TabItemContent i_eItemContent )
- :Control( &i_rParentWindow, 0 )
- ,m_pImpl( new PanelTabBar_Impl( *this, i_rPanelDeck, i_eAlignment, i_eItemContent ) )
- {
- DBG_CHECK( *m_pImpl );
- }
-
- PanelTabBar::~PanelTabBar()
- {
- disposeOnce();
- }
-
- void PanelTabBar::dispose()
- {
- Control::dispose();
- }
-
- TabItemContent PanelTabBar::GetTabItemContent() const
- {
- return m_pImpl->m_aGeometry.getItemContent();
- }
-
-
- void PanelTabBar::SetTabItemContent( const TabItemContent& i_eItemContent )
- {
- m_pImpl->m_aGeometry.setItemContent( i_eItemContent );
- m_pImpl->Relayout();
- Invalidate();
- }
-
-
- IToolPanelDeck& PanelTabBar::GetPanelDeck() const
- {
- DBG_CHECK( *m_pImpl );
- return m_pImpl->m_rPanelDeck;
- }
-
-
- Size PanelTabBar::GetOptimalSize() const
- {
- m_pImpl->EnsureItemsCache();
- Size aOptimalSize(m_pImpl->m_aGeometry.getOptimalSize(m_pImpl->m_aItems));
- if ( m_pImpl->IsVertical() )
- ::std::swap( aOptimalSize.Width(), aOptimalSize.Height() );
- return aOptimalSize;
- }
-
-
- void PanelTabBar::Resize()
- {
- Control::Resize();
- m_pImpl->Relayout();
- }
-
-
- void PanelTabBar::Paint(vcl::RenderContext& rRenderContext, const Rectangle& i_rRect)
- {
- m_pImpl->EnsureItemsCache();
-
- // background
- const Rectangle aNormalizedPaintArea(m_pImpl->m_aNormalizer.getNormalized(i_rRect, m_pImpl->m_eTabAlignment));
- m_pImpl->m_aRenderDevice->Push(PushFlags::CLIPREGION);
- m_pImpl->m_aRenderDevice->SetClipRegion(vcl::Region(aNormalizedPaintArea));
- m_pImpl->m_pRenderer->renderBackground();
- m_pImpl->m_aRenderDevice->Pop();
- m_pImpl->CopyFromRenderDevice(rRenderContext, aNormalizedPaintArea);
-
- // ensure the items really paint into their own playground only
- ClipItemRegion aClipItems(*m_pImpl);
-
- const Rectangle aLogicalPaintRect(m_pImpl->m_aNormalizer.getNormalized(i_rRect, m_pImpl->m_eTabAlignment));
-
- const boost::optional<size_t> aActivePanel(m_pImpl->m_rPanelDeck.GetActivePanel());
- const boost::optional<size_t> aHoveredPanel(m_pImpl->m_aHoveredItem);
-
- // items:
- // 1. paint all non-active, non-hovered items
- size_t i = 0;
- ItemDescriptors::const_iterator item;
- for (item = m_pImpl->m_aItems.begin(); item != m_pImpl->m_aItems.end(); ++item, ++i)
- {
- if (i == aActivePanel)
- continue;
-
- if (aHoveredPanel == i)
- continue;
-
- m_pImpl->DrawItem(rRenderContext, i, aLogicalPaintRect);
- }
-
- // 2. paint the item which is hovered, /without/ the mouse button pressed down
- if (!!aHoveredPanel && !m_pImpl->m_bMouseButtonDown)
- m_pImpl->DrawItem(rRenderContext, *aHoveredPanel, aLogicalPaintRect);
-
- // 3. paint the active item
- if (!!aActivePanel)
- m_pImpl->DrawItem(rRenderContext, *aActivePanel, aLogicalPaintRect);
-
- // 4. paint the item which is hovered, /with/ the mouse button pressed down
- if (!!aHoveredPanel && m_pImpl->m_bMouseButtonDown)
- m_pImpl->DrawItem(rRenderContext, *aHoveredPanel, aLogicalPaintRect);
- }
-
-
- void PanelTabBar::MouseMove( const MouseEvent& i_rMouseEvent )
- {
- m_pImpl->EnsureItemsCache();
-
- boost::optional< size_t > aOldItem(m_pImpl->m_aHoveredItem);
- boost::optional< size_t > aNewItem(m_pImpl->FindItemForPoint(i_rMouseEvent.GetPosPixel()));
-
- if (i_rMouseEvent.IsLeaveWindow())
- aNewItem = boost::optional<size_t>();
-
- bool const bChanged(
- ( !aOldItem && aNewItem )
- || ( aOldItem && !aNewItem )
- || ( aOldItem && aNewItem && aOldItem != aNewItem ) );
-
- if (bChanged)
- {
- if (aOldItem)
- m_pImpl->InvalidateItem( *aOldItem );
-
- m_pImpl->m_aHoveredItem = aNewItem;
-
- if (aNewItem)
- m_pImpl->InvalidateItem( *aNewItem );
- }
- }
-
-
- void PanelTabBar::MouseButtonDown( const MouseEvent& i_rMouseEvent )
- {
- Control::MouseButtonDown( i_rMouseEvent );
-
- if ( !i_rMouseEvent.IsLeft() )
- return;
-
- m_pImpl->EnsureItemsCache();
-
- ::boost::optional< size_t > aHitItem( m_pImpl->FindItemForPoint( i_rMouseEvent.GetPosPixel() ) );
- if ( !aHitItem )
- return;
-
- CaptureMouse();
- m_pImpl->m_bMouseButtonDown = true;
-
- m_pImpl->InvalidateItem( *aHitItem );
- }
-
-
- void PanelTabBar::MouseButtonUp( const MouseEvent& i_rMouseEvent )
- {
- Control::MouseButtonUp( i_rMouseEvent );
-
- if ( m_pImpl->m_bMouseButtonDown )
- {
- ::boost::optional< size_t > aHitItem( m_pImpl->FindItemForPoint( i_rMouseEvent.GetPosPixel() ) );
- if ( !!aHitItem )
- {
- // re-draw that item now that we're not in mouse-down mode anymore
- m_pImpl->InvalidateItem( *aHitItem );
- // activate the respective panel
- m_pImpl->m_rPanelDeck.ActivatePanel( *aHitItem );
- }
-
- OSL_ENSURE( IsMouseCaptured(), "PanelTabBar::MouseButtonUp: inconsistency!" );
- if ( IsMouseCaptured() )
- ReleaseMouse();
- m_pImpl->m_bMouseButtonDown = false;
- }
- }
-
-
- void PanelTabBar::RequestHelp( const HelpEvent& i_rHelpEvent )
- {
- m_pImpl->EnsureItemsCache();
-
- ::boost::optional< size_t > aHelpItem( m_pImpl->FindItemForPoint( ScreenToOutputPixel( i_rHelpEvent.GetMousePosPixel() ) ) );
- if ( !aHelpItem )
- return;
-
- const ItemDescriptor& rItem( m_pImpl->m_aItems[ *aHelpItem ] );
- if ( rItem.eContent != TABITEM_IMAGE_ONLY )
- // if the text is displayed for the item, we do not need to show it as tooltip
- return;
-
- const OUString sItemText( rItem.pPanel->GetDisplayName() );
- if ( i_rHelpEvent.GetMode() == HelpEventMode::BALLOON )
- Help::ShowBalloon( this, OutputToScreenPixel( rItem.GetCurrentRect().Center() ), rItem.GetCurrentRect(), sItemText );
- else
- Help::ShowQuickHelp( this, rItem.GetCurrentRect(), sItemText );
- }
-
-
- void PanelTabBar::GetFocus()
- {
- Control::GetFocus();
- if ( !m_pImpl->m_aFocusedItem )
- m_pImpl->FocusItem( m_pImpl->m_rPanelDeck.GetActivePanel() );
- }
-
-
- void PanelTabBar::LoseFocus()
- {
- Control::LoseFocus();
-
- if ( m_pImpl )
- {
- if ( !!m_pImpl->m_aFocusedItem )
- m_pImpl->InvalidateItem( *m_pImpl->m_aFocusedItem );
-
- m_pImpl->m_aFocusedItem.reset();
- }
- }
-
-
- class KeyInputHandler
- {
- public:
- KeyInputHandler( Control& i_rControl, const KeyEvent& i_rKeyEvent )
- :m_rControl( i_rControl )
- ,m_rKeyEvent( i_rKeyEvent )
- ,m_bHandled( false )
- {
- }
-
- ~KeyInputHandler()
- {
- if ( !m_bHandled )
- m_rControl.Control::KeyInput( m_rKeyEvent );
- }
-
- void setHandled()
- {
- m_bHandled = true;
- }
-
- private:
- Control& m_rControl;
- const KeyEvent& m_rKeyEvent;
- bool m_bHandled;
- };
-
-
- void PanelTabBar::KeyInput( const KeyEvent& i_rKeyEvent )
- {
- KeyInputHandler aKeyInputHandler( *this, i_rKeyEvent );
-
- const vcl::KeyCode& rKeyCode( i_rKeyEvent.GetKeyCode() );
- if ( rKeyCode.GetModifier() != 0 )
- // only interested in mere key presses
- return;
-
- // if there are less than 2 panels, we cannot travel them ...
- const size_t nPanelCount( m_pImpl->m_rPanelDeck.GetPanelCount() );
- if ( nPanelCount < 2 )
- return;
-
- OSL_PRECOND( !!m_pImpl->m_aFocusedItem, "PanelTabBar::KeyInput: we should have a focused item here!" );
- // if we get KeyInput events, we should have the focus. In this case, m_aFocusedItem should not be empty,
- // except if there are no panels, but then we bail out of this method here earlier ...
-
- bool bFocusNext = false;
- bool bFocusPrev = false;
-
- switch ( rKeyCode.GetCode() )
- {
- case KEY_UP: bFocusPrev = true; break;
- case KEY_DOWN: bFocusNext = true; break;
- case KEY_LEFT:
- if ( IsRTLEnabled() )
- bFocusNext = true;
- else
- bFocusPrev = true;
- break;
- case KEY_RIGHT:
- if ( IsRTLEnabled() )
- bFocusPrev = true;
- else
- bFocusNext = true;
- break;
- case KEY_RETURN:
- m_pImpl->m_rPanelDeck.ActivatePanel( *m_pImpl->m_aFocusedItem );
- break;
- }
-
- if ( !bFocusNext && !bFocusPrev )
- return;
-
- m_pImpl->InvalidateItem( *m_pImpl->m_aFocusedItem );
- if ( bFocusNext )
- {
- m_pImpl->m_aFocusedItem.reset( ( *m_pImpl->m_aFocusedItem + 1 ) % nPanelCount );
- }
- else
- {
- m_pImpl->m_aFocusedItem.reset( ( *m_pImpl->m_aFocusedItem + nPanelCount - 1 ) % nPanelCount );
- }
- m_pImpl->InvalidateItem( *m_pImpl->m_aFocusedItem );
-
- // don't delegate to base class
- aKeyInputHandler.setHandled();
- }
-
-
- void PanelTabBar::DataChanged( const DataChangedEvent& i_rDataChanedEvent )
- {
- Control::DataChanged( i_rDataChanedEvent );
-
- if ( ( i_rDataChanedEvent.GetType() == DataChangedEventType::SETTINGS )
- && ( i_rDataChanedEvent.GetFlags() & AllSettingsFlags::STYLE )
- )
- {
- Invalidate();
- }
- }
-
-
- bool PanelTabBar::IsVertical() const
- {
- return m_pImpl->IsVertical();
- }
-
-
- PushButton& PanelTabBar::GetScrollButton( const bool i_bForward )
- {
- return i_bForward ? *m_pImpl->m_aScrollForward.get() : *m_pImpl->m_aScrollBack.get();
- }
-
-
- ::boost::optional< size_t > PanelTabBar::GetFocusedPanelItem() const
- {
- return m_pImpl->m_aFocusedItem;
- }
-
-
- void PanelTabBar::FocusPanelItem( const size_t i_nItemPos )
- {
- ENSURE_OR_RETURN_VOID( i_nItemPos < m_pImpl->m_rPanelDeck.GetPanelCount(), "PanelTabBar::FocusPanelItem: illegal item pos!" );
-
- if ( !HasChildPathFocus() )
- GrabFocus();
-
- m_pImpl->FocusItem( i_nItemPos );
- SAL_WARN_IF( !m_pImpl->m_aFocusedItem, "svtools", "PanelTabBar::FocusPanelItem: have the focus, but no focused item?" );
- if ( !!m_pImpl->m_aFocusedItem )
- m_pImpl->InvalidateItem( *m_pImpl->m_aFocusedItem );
- m_pImpl->m_aFocusedItem.reset( i_nItemPos );
- }
-
-
- Rectangle PanelTabBar::GetItemScreenRect( const size_t i_nItemPos ) const
- {
- return m_pImpl->GetItemScreenRect( i_nItemPos );
- }
-
-
- Reference< XWindowPeer > PanelTabBar::GetComponentInterface( bool i_bCreate )
- {
- Reference< XWindowPeer > xWindowPeer( Control::GetComponentInterface( false ) );
- if ( !xWindowPeer.is() && i_bCreate )
- {
- xWindowPeer.set( new PanelTabBarPeer( *this ) );
- SetComponentInterface( xWindowPeer );
- }
- return xWindowPeer;
- }
-
-
-} // namespace svt
-
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */