xref: /AOO41X/main/svtools/source/toolpanel/paneltabbar.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3*cdf0e10cSrcweir  *
4*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
5*cdf0e10cSrcweir  *
6*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
7*cdf0e10cSrcweir  *
8*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
9*cdf0e10cSrcweir  *
10*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
11*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
12*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
13*cdf0e10cSrcweir  *
14*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
15*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
18*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
19*cdf0e10cSrcweir  *
20*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
21*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
22*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
23*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
24*cdf0e10cSrcweir  *
25*cdf0e10cSrcweir ************************************************************************/
26*cdf0e10cSrcweir 
27*cdf0e10cSrcweir #include "precompiled_svtools.hxx"
28*cdf0e10cSrcweir 
29*cdf0e10cSrcweir #include "svtools/toolpanel/paneltabbar.hxx"
30*cdf0e10cSrcweir #include "svtools/toolpanel/toolpaneldeck.hxx"
31*cdf0e10cSrcweir #include "svtools/svtdata.hxx"
32*cdf0e10cSrcweir #include "svtools/svtools.hrc"
33*cdf0e10cSrcweir 
34*cdf0e10cSrcweir #include "tabitemdescriptor.hxx"
35*cdf0e10cSrcweir #include "paneltabbarpeer.hxx"
36*cdf0e10cSrcweir #include "tabbargeometry.hxx"
37*cdf0e10cSrcweir 
38*cdf0e10cSrcweir #include <vcl/button.hxx>
39*cdf0e10cSrcweir #include <vcl/help.hxx>
40*cdf0e10cSrcweir #include <vcl/virdev.hxx>
41*cdf0e10cSrcweir #include <tools/diagnose_ex.h>
42*cdf0e10cSrcweir 
43*cdf0e10cSrcweir #include <boost/optional.hpp>
44*cdf0e10cSrcweir #include <vector>
45*cdf0e10cSrcweir 
46*cdf0e10cSrcweir // space around an item
47*cdf0e10cSrcweir #define ITEM_OUTER_SPACE        2 * 3
48*cdf0e10cSrcweir // spacing before and after an item's text
49*cdf0e10cSrcweir #define ITEM_TEXT_FLOW_SPACE    5
50*cdf0e10cSrcweir // space between item icon and icon text
51*cdf0e10cSrcweir #define ITEM_ICON_TEXT_DISTANCE 4
52*cdf0e10cSrcweir 
53*cdf0e10cSrcweir //........................................................................
54*cdf0e10cSrcweir namespace svt
55*cdf0e10cSrcweir {
56*cdf0e10cSrcweir //........................................................................
57*cdf0e10cSrcweir 
58*cdf0e10cSrcweir     using ::com::sun::star::uno::Reference;
59*cdf0e10cSrcweir     using ::com::sun::star::awt::XWindowPeer;
60*cdf0e10cSrcweir 
61*cdf0e10cSrcweir     typedef sal_uInt16  ItemFlags;
62*cdf0e10cSrcweir 
63*cdf0e10cSrcweir     #define ITEM_STATE_NORMAL   0x00
64*cdf0e10cSrcweir     #define ITEM_STATE_ACTIVE   0x01
65*cdf0e10cSrcweir     #define ITEM_STATE_HOVERED  0x02
66*cdf0e10cSrcweir     #define ITEM_STATE_FOCUSED  0x04
67*cdf0e10cSrcweir     #define ITEM_POSITION_FIRST 0x08
68*cdf0e10cSrcweir     #define ITEM_POSITION_LAST  0x10
69*cdf0e10cSrcweir 
70*cdf0e10cSrcweir 	//==================================================================================================================
71*cdf0e10cSrcweir 	//= helper
72*cdf0e10cSrcweir 	//==================================================================================================================
73*cdf0e10cSrcweir     namespace
74*cdf0e10cSrcweir     {
75*cdf0e10cSrcweir         ControlState lcl_ItemToControlState( const ItemFlags i_nItemFlags )
76*cdf0e10cSrcweir         {
77*cdf0e10cSrcweir             ControlState nState = CTRL_STATE_ENABLED;
78*cdf0e10cSrcweir             if ( i_nItemFlags & ITEM_STATE_FOCUSED )    nState |= CTRL_STATE_FOCUSED | CTRL_STATE_PRESSED;
79*cdf0e10cSrcweir             if ( i_nItemFlags & ITEM_STATE_HOVERED )    nState |= CTRL_STATE_ROLLOVER;
80*cdf0e10cSrcweir             if ( i_nItemFlags & ITEM_STATE_ACTIVE )     nState |= CTRL_STATE_SELECTED;
81*cdf0e10cSrcweir             return nState;
82*cdf0e10cSrcweir         }
83*cdf0e10cSrcweir     }
84*cdf0e10cSrcweir 
85*cdf0e10cSrcweir 	//==================================================================================================================
86*cdf0e10cSrcweir 	//= ITabBarRenderer
87*cdf0e10cSrcweir 	//==================================================================================================================
88*cdf0e10cSrcweir     class SAL_NO_VTABLE ITabBarRenderer
89*cdf0e10cSrcweir     {
90*cdf0e10cSrcweir     public:
91*cdf0e10cSrcweir         /** fills the background of our target device
92*cdf0e10cSrcweir         */
93*cdf0e10cSrcweir         virtual void        renderBackground() const = 0;
94*cdf0e10cSrcweir         virtual Rectangle   calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const = 0;
95*cdf0e10cSrcweir         virtual void        preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const = 0;
96*cdf0e10cSrcweir         virtual void        postRenderItem( Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const = 0;
97*cdf0e10cSrcweir 
98*cdf0e10cSrcweir         // TODO: postRenderItem takes the "real" window, i.e. effectively the tab bar. This is because
99*cdf0e10cSrcweir         // DrawSelectionBackground needs to be applied after everything else is painted, and is available at the Window
100*cdf0e10cSrcweir         // class, but not at the OutputDevice. This makes the API somewhat weird, as we're now mixing operations on the
101*cdf0e10cSrcweir         // target device, done in a normalized geometry, with operations on the window, done in a transformed geometry.
102*cdf0e10cSrcweir         // So, we should get rid of postRenderItem completely.
103*cdf0e10cSrcweir     };
104*cdf0e10cSrcweir     typedef ::boost::shared_ptr< ITabBarRenderer >  PTabBarRenderer;
105*cdf0e10cSrcweir 
106*cdf0e10cSrcweir 	//==================================================================================================================
107*cdf0e10cSrcweir 	//= VCLItemRenderer - declaration
108*cdf0e10cSrcweir 	//==================================================================================================================
109*cdf0e10cSrcweir     class VCLItemRenderer : public ITabBarRenderer
110*cdf0e10cSrcweir     {
111*cdf0e10cSrcweir     public:
112*cdf0e10cSrcweir         VCLItemRenderer( OutputDevice& i_rTargetDevice )
113*cdf0e10cSrcweir             :m_rTargetDevice( i_rTargetDevice )
114*cdf0e10cSrcweir         {
115*cdf0e10cSrcweir         }
116*cdf0e10cSrcweir 
117*cdf0e10cSrcweir         // ITabBarRenderer
118*cdf0e10cSrcweir         virtual void        renderBackground() const;
119*cdf0e10cSrcweir         virtual Rectangle   calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const;
120*cdf0e10cSrcweir         virtual void        preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const;
121*cdf0e10cSrcweir         virtual void        postRenderItem( Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const;
122*cdf0e10cSrcweir 
123*cdf0e10cSrcweir     protected:
124*cdf0e10cSrcweir         OutputDevice&   getTargetDevice() const { return m_rTargetDevice; }
125*cdf0e10cSrcweir 
126*cdf0e10cSrcweir     private:
127*cdf0e10cSrcweir         OutputDevice&   m_rTargetDevice;
128*cdf0e10cSrcweir     };
129*cdf0e10cSrcweir 
130*cdf0e10cSrcweir 	//==================================================================================================================
131*cdf0e10cSrcweir 	//= VCLItemRenderer - implementation
132*cdf0e10cSrcweir 	//==================================================================================================================
133*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
134*cdf0e10cSrcweir     void VCLItemRenderer::renderBackground() const
135*cdf0e10cSrcweir     {
136*cdf0e10cSrcweir         getTargetDevice().DrawRect( Rectangle( Point(), getTargetDevice().GetOutputSizePixel() ) );
137*cdf0e10cSrcweir     }
138*cdf0e10cSrcweir 
139*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
140*cdf0e10cSrcweir     Rectangle VCLItemRenderer::calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const
141*cdf0e10cSrcweir     {
142*cdf0e10cSrcweir         (void)i_nItemFlags;
143*cdf0e10cSrcweir         // no decorations at all
144*cdf0e10cSrcweir         return i_rContentArea;
145*cdf0e10cSrcweir     }
146*cdf0e10cSrcweir 
147*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
148*cdf0e10cSrcweir     void VCLItemRenderer::preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const
149*cdf0e10cSrcweir     {
150*cdf0e10cSrcweir         (void)i_rContentRect;
151*cdf0e10cSrcweir         (void)i_nItemFlags;
152*cdf0e10cSrcweir     }
153*cdf0e10cSrcweir 
154*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
155*cdf0e10cSrcweir     void VCLItemRenderer::postRenderItem( Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const
156*cdf0e10cSrcweir     {
157*cdf0e10cSrcweir         const bool bActive = ( ( i_nItemFlags & ITEM_STATE_ACTIVE ) != 0 );
158*cdf0e10cSrcweir         const bool bHovered = ( ( i_nItemFlags & ITEM_STATE_HOVERED ) != 0 );
159*cdf0e10cSrcweir         const bool bFocused = ( ( i_nItemFlags & ITEM_STATE_FOCUSED ) != 0 );
160*cdf0e10cSrcweir         if ( bActive || bHovered || bFocused )
161*cdf0e10cSrcweir         {
162*cdf0e10cSrcweir             Rectangle aSelectionRect( i_rItemRect );
163*cdf0e10cSrcweir             aSelectionRect.Left() += ITEM_OUTER_SPACE / 2;
164*cdf0e10cSrcweir             aSelectionRect.Top() += ITEM_OUTER_SPACE / 2;
165*cdf0e10cSrcweir             aSelectionRect.Right() -= ITEM_OUTER_SPACE / 2;
166*cdf0e10cSrcweir             aSelectionRect.Bottom() -= ITEM_OUTER_SPACE / 2;
167*cdf0e10cSrcweir             i_rActualWindow.DrawSelectionBackground(
168*cdf0e10cSrcweir                 aSelectionRect,
169*cdf0e10cSrcweir                 ( bHovered || bFocused ) ? ( bActive ? 1 : 2 ) : 0 /* hilight */,
170*cdf0e10cSrcweir                 bActive /* check */,
171*cdf0e10cSrcweir                 sal_True /* border */,
172*cdf0e10cSrcweir                 sal_False /* ext border only */,
173*cdf0e10cSrcweir                 0 /* corner radius */,
174*cdf0e10cSrcweir                 NULL,
175*cdf0e10cSrcweir                 NULL
176*cdf0e10cSrcweir             );
177*cdf0e10cSrcweir         }
178*cdf0e10cSrcweir     }
179*cdf0e10cSrcweir 
180*cdf0e10cSrcweir 	//==================================================================================================================
181*cdf0e10cSrcweir 	//= NWFToolboxItemRenderer - declaration
182*cdf0e10cSrcweir 	//==================================================================================================================
183*cdf0e10cSrcweir     class NWFToolboxItemRenderer : public ITabBarRenderer
184*cdf0e10cSrcweir     {
185*cdf0e10cSrcweir     public:
186*cdf0e10cSrcweir         NWFToolboxItemRenderer( OutputDevice& i_rTargetDevice )
187*cdf0e10cSrcweir             :m_rTargetDevice( i_rTargetDevice )
188*cdf0e10cSrcweir         {
189*cdf0e10cSrcweir         }
190*cdf0e10cSrcweir 
191*cdf0e10cSrcweir         // ITabBarRenderer
192*cdf0e10cSrcweir         virtual void        renderBackground() const;
193*cdf0e10cSrcweir         virtual Rectangle   calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const;
194*cdf0e10cSrcweir         virtual void        preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const;
195*cdf0e10cSrcweir         virtual void        postRenderItem( Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const;
196*cdf0e10cSrcweir 
197*cdf0e10cSrcweir     protected:
198*cdf0e10cSrcweir         OutputDevice&   getTargetDevice() const { return m_rTargetDevice; }
199*cdf0e10cSrcweir 
200*cdf0e10cSrcweir     private:
201*cdf0e10cSrcweir         OutputDevice&   m_rTargetDevice;
202*cdf0e10cSrcweir     };
203*cdf0e10cSrcweir 
204*cdf0e10cSrcweir 	//==================================================================================================================
205*cdf0e10cSrcweir 	//= NWFToolboxItemRenderer - implementation
206*cdf0e10cSrcweir 	//==================================================================================================================
207*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
208*cdf0e10cSrcweir     void NWFToolboxItemRenderer::renderBackground() const
209*cdf0e10cSrcweir     {
210*cdf0e10cSrcweir         getTargetDevice().DrawRect( Rectangle( Point(), getTargetDevice().GetOutputSizePixel() ) );
211*cdf0e10cSrcweir     }
212*cdf0e10cSrcweir 
213*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
214*cdf0e10cSrcweir     Rectangle NWFToolboxItemRenderer::calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const
215*cdf0e10cSrcweir     {
216*cdf0e10cSrcweir         // don't ask GetNativeControlRegion, this will not deliver proper results in all cases.
217*cdf0e10cSrcweir         // Instead, simply assume that both the content and the bounding region are the same.
218*cdf0e10cSrcweir //        const ControlState nState( lcl_ItemToControlState( i_nItemFlags );
219*cdf0e10cSrcweir //        const ImplControlValue aControlValue;
220*cdf0e10cSrcweir //        bool bNativeOK = m_rTargetWindow.GetNativeControlRegion(
221*cdf0e10cSrcweir //            CTRL_TOOLBAR, PART_BUTTON,
222*cdf0e10cSrcweir //            i_rContentArea, nState,
223*cdf0e10cSrcweir //            aControlValue, ::rtl::OUString(),
224*cdf0e10cSrcweir //            aBoundingRegion, aContentRegion
225*cdf0e10cSrcweir //        );
226*cdf0e10cSrcweir         (void)i_nItemFlags;
227*cdf0e10cSrcweir         return Rectangle(
228*cdf0e10cSrcweir             Point( i_rContentArea.Left() - 1, i_rContentArea.Top() - 1 ),
229*cdf0e10cSrcweir             Size( i_rContentArea.GetWidth() + 2, i_rContentArea.GetHeight() + 2 )
230*cdf0e10cSrcweir         );
231*cdf0e10cSrcweir     }
232*cdf0e10cSrcweir 
233*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
234*cdf0e10cSrcweir     void NWFToolboxItemRenderer::preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const
235*cdf0e10cSrcweir     {
236*cdf0e10cSrcweir         const ControlState nState = lcl_ItemToControlState( i_nItemFlags );
237*cdf0e10cSrcweir 
238*cdf0e10cSrcweir         ImplControlValue aControlValue;
239*cdf0e10cSrcweir         aControlValue.setTristateVal( ( i_nItemFlags & ITEM_STATE_ACTIVE ) ? BUTTONVALUE_ON : BUTTONVALUE_OFF );
240*cdf0e10cSrcweir 
241*cdf0e10cSrcweir         bool bNativeOK = getTargetDevice().DrawNativeControl( CTRL_TOOLBAR, PART_BUTTON, i_rContentRect, nState, aControlValue, rtl::OUString() );
242*cdf0e10cSrcweir         (void)bNativeOK;
243*cdf0e10cSrcweir         OSL_ENSURE( bNativeOK, "NWFToolboxItemRenderer::preRenderItem: inconsistent NWF implementation!" );
244*cdf0e10cSrcweir             // IsNativeControlSupported returned true, previously, otherwise we would not be here ...
245*cdf0e10cSrcweir     }
246*cdf0e10cSrcweir 
247*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
248*cdf0e10cSrcweir     void NWFToolboxItemRenderer::postRenderItem( Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const
249*cdf0e10cSrcweir     {
250*cdf0e10cSrcweir         (void)i_rActualWindow;
251*cdf0e10cSrcweir         (void)i_rItemRect;
252*cdf0e10cSrcweir         (void)i_nItemFlags;
253*cdf0e10cSrcweir     }
254*cdf0e10cSrcweir 
255*cdf0e10cSrcweir 	//==================================================================================================================
256*cdf0e10cSrcweir 	//= NWFTabItemRenderer - declaration
257*cdf0e10cSrcweir 	//==================================================================================================================
258*cdf0e10cSrcweir     class NWFTabItemRenderer : public ITabBarRenderer
259*cdf0e10cSrcweir     {
260*cdf0e10cSrcweir     public:
261*cdf0e10cSrcweir         NWFTabItemRenderer( OutputDevice& i_rTargetDevice )
262*cdf0e10cSrcweir             :m_rTargetDevice( i_rTargetDevice )
263*cdf0e10cSrcweir         {
264*cdf0e10cSrcweir         }
265*cdf0e10cSrcweir 
266*cdf0e10cSrcweir         // ITabBarRenderer
267*cdf0e10cSrcweir         virtual void        renderBackground() const;
268*cdf0e10cSrcweir         virtual Rectangle   calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const;
269*cdf0e10cSrcweir         virtual void        preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const;
270*cdf0e10cSrcweir         virtual void        postRenderItem( Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const;
271*cdf0e10cSrcweir 
272*cdf0e10cSrcweir     protected:
273*cdf0e10cSrcweir         OutputDevice&   getTargetDevice() const { return m_rTargetDevice; }
274*cdf0e10cSrcweir 
275*cdf0e10cSrcweir     private:
276*cdf0e10cSrcweir         OutputDevice&   m_rTargetDevice;
277*cdf0e10cSrcweir     };
278*cdf0e10cSrcweir 
279*cdf0e10cSrcweir 	//==================================================================================================================
280*cdf0e10cSrcweir 	//= NWFTabItemRenderer - implementation
281*cdf0e10cSrcweir 	//==================================================================================================================
282*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
283*cdf0e10cSrcweir     void NWFTabItemRenderer::renderBackground() const
284*cdf0e10cSrcweir     {
285*cdf0e10cSrcweir         Rectangle aBackground( Point(), getTargetDevice().GetOutputSizePixel() );
286*cdf0e10cSrcweir         getTargetDevice().DrawRect( aBackground );
287*cdf0e10cSrcweir 
288*cdf0e10cSrcweir         aBackground.Top() = aBackground.Bottom();
289*cdf0e10cSrcweir         getTargetDevice().DrawNativeControl( CTRL_TAB_PANE, PART_ENTIRE_CONTROL, aBackground,
290*cdf0e10cSrcweir             CTRL_STATE_ENABLED, ImplControlValue(), ::rtl::OUString() );
291*cdf0e10cSrcweir     }
292*cdf0e10cSrcweir 
293*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
294*cdf0e10cSrcweir     Rectangle NWFTabItemRenderer::calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const
295*cdf0e10cSrcweir     {
296*cdf0e10cSrcweir         const ControlState nState( lcl_ItemToControlState( i_nItemFlags ) );
297*cdf0e10cSrcweir 
298*cdf0e10cSrcweir         TabitemValue tiValue;
299*cdf0e10cSrcweir 
300*cdf0e10cSrcweir         Rectangle aBoundingRegion, aContentRegion;
301*cdf0e10cSrcweir         bool bNativeOK = getTargetDevice().GetNativeControlRegion(
302*cdf0e10cSrcweir             CTRL_TAB_ITEM, PART_ENTIRE_CONTROL,
303*cdf0e10cSrcweir             i_rContentArea, nState,
304*cdf0e10cSrcweir             tiValue, ::rtl::OUString(),
305*cdf0e10cSrcweir             aBoundingRegion, aContentRegion
306*cdf0e10cSrcweir         );
307*cdf0e10cSrcweir         (void)bNativeOK;
308*cdf0e10cSrcweir         OSL_ENSURE( bNativeOK, "NWFTabItemRenderer::calculateDecorations: GetNativeControlRegion not implemented for CTRL_TAB_ITEM?!" );
309*cdf0e10cSrcweir 
310*cdf0e10cSrcweir         return aBoundingRegion;
311*cdf0e10cSrcweir     }
312*cdf0e10cSrcweir 
313*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
314*cdf0e10cSrcweir     void NWFTabItemRenderer::preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const
315*cdf0e10cSrcweir     {
316*cdf0e10cSrcweir         const ControlState nState = lcl_ItemToControlState( i_nItemFlags );
317*cdf0e10cSrcweir 
318*cdf0e10cSrcweir         TabitemValue tiValue;
319*cdf0e10cSrcweir         if ( i_nItemFlags & ITEM_POSITION_FIRST )
320*cdf0e10cSrcweir             tiValue.mnAlignment |= TABITEM_FIRST_IN_GROUP;
321*cdf0e10cSrcweir         if ( i_nItemFlags & ITEM_POSITION_LAST )
322*cdf0e10cSrcweir             tiValue.mnAlignment |= TABITEM_LAST_IN_GROUP;
323*cdf0e10cSrcweir 
324*cdf0e10cSrcweir 
325*cdf0e10cSrcweir         bool bNativeOK = getTargetDevice().DrawNativeControl( CTRL_TAB_ITEM, PART_ENTIRE_CONTROL, i_rContentRect, nState, tiValue, rtl::OUString() );
326*cdf0e10cSrcweir         (void)bNativeOK;
327*cdf0e10cSrcweir         OSL_ENSURE( bNativeOK, "NWFTabItemRenderer::preRenderItem: inconsistent NWF implementation!" );
328*cdf0e10cSrcweir             // IsNativeControlSupported returned true, previously, otherwise we would not be here ...
329*cdf0e10cSrcweir     }
330*cdf0e10cSrcweir 
331*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
332*cdf0e10cSrcweir     void NWFTabItemRenderer::postRenderItem( Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const
333*cdf0e10cSrcweir     {
334*cdf0e10cSrcweir         (void)i_rActualWindow;
335*cdf0e10cSrcweir         (void)i_rItemRect;
336*cdf0e10cSrcweir         (void)i_nItemFlags;
337*cdf0e10cSrcweir     }
338*cdf0e10cSrcweir 
339*cdf0e10cSrcweir     //==================================================================================================================
340*cdf0e10cSrcweir 	//= PanelTabBar_Impl
341*cdf0e10cSrcweir 	//==================================================================================================================
342*cdf0e10cSrcweir     class PanelTabBar_Impl : public IToolPanelDeckListener
343*cdf0e10cSrcweir     {
344*cdf0e10cSrcweir     public:
345*cdf0e10cSrcweir         PanelTabBar_Impl( PanelTabBar& i_rTabBar, IToolPanelDeck& i_rPanelDeck, const TabAlignment i_eAlignment, const TabItemContent i_eItemContent );
346*cdf0e10cSrcweir 
347*cdf0e10cSrcweir         ~PanelTabBar_Impl()
348*cdf0e10cSrcweir         {
349*cdf0e10cSrcweir             m_rPanelDeck.RemoveListener( *this );
350*cdf0e10cSrcweir         }
351*cdf0e10cSrcweir 
352*cdf0e10cSrcweir         // IToolPanelDeckListener
353*cdf0e10cSrcweir         virtual void PanelInserted( const PToolPanel& i_pPanel, const size_t i_nPosition )
354*cdf0e10cSrcweir         {
355*cdf0e10cSrcweir             (void)i_pPanel;
356*cdf0e10cSrcweir             (void)i_nPosition;
357*cdf0e10cSrcweir             m_bItemsDirty = true;
358*cdf0e10cSrcweir             m_rTabBar.Invalidate();
359*cdf0e10cSrcweir 
360*cdf0e10cSrcweir             Relayout();
361*cdf0e10cSrcweir         }
362*cdf0e10cSrcweir 
363*cdf0e10cSrcweir         virtual void PanelRemoved( const size_t i_nPosition )
364*cdf0e10cSrcweir         {
365*cdf0e10cSrcweir             m_bItemsDirty = true;
366*cdf0e10cSrcweir             m_rTabBar.Invalidate();
367*cdf0e10cSrcweir 
368*cdf0e10cSrcweir             if ( i_nPosition < m_nScrollPosition )
369*cdf0e10cSrcweir                 --m_nScrollPosition;
370*cdf0e10cSrcweir 
371*cdf0e10cSrcweir             Relayout();
372*cdf0e10cSrcweir         }
373*cdf0e10cSrcweir 
374*cdf0e10cSrcweir         virtual void ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive );
375*cdf0e10cSrcweir         virtual void LayouterChanged( const PDeckLayouter& i_rNewLayouter );
376*cdf0e10cSrcweir         virtual void Dying();
377*cdf0e10cSrcweir 
378*cdf0e10cSrcweir         void    UpdateScrollButtons()
379*cdf0e10cSrcweir         {
380*cdf0e10cSrcweir             m_aScrollBack.Enable( m_nScrollPosition > 0 );
381*cdf0e10cSrcweir             m_aScrollForward.Enable( m_nScrollPosition < m_aItems.size() - 1 );
382*cdf0e10cSrcweir         }
383*cdf0e10cSrcweir 
384*cdf0e10cSrcweir         void                        Relayout();
385*cdf0e10cSrcweir         void                        EnsureItemsCache();
386*cdf0e10cSrcweir         ::boost::optional< size_t > FindItemForPoint( const Point& i_rPoint ) const;
387*cdf0e10cSrcweir         void                        DrawItem( const size_t i_nItemIndex, const Rectangle& i_rBoundaries ) const;
388*cdf0e10cSrcweir         void                        InvalidateItem( const size_t i_nItemIndex, const ItemFlags i_nAdditionalItemFlags = 0 ) const;
389*cdf0e10cSrcweir         void                        CopyFromRenderDevice( const Rectangle& i_rLogicalRect ) const;
390*cdf0e10cSrcweir         Rectangle                   GetActualLogicalItemRect( const Rectangle& i_rLogicalItemRect ) const;
391*cdf0e10cSrcweir         Rectangle                   GetItemScreenRect( const size_t i_nItemPos ) const;
392*cdf0e10cSrcweir 
393*cdf0e10cSrcweir         void                        FocusItem( const ::boost::optional< size_t >& i_rItemPos );
394*cdf0e10cSrcweir 
395*cdf0e10cSrcweir         inline bool                 IsVertical() const
396*cdf0e10cSrcweir         {
397*cdf0e10cSrcweir             return  (   ( m_eTabAlignment == TABS_LEFT )
398*cdf0e10cSrcweir                     ||  ( m_eTabAlignment == TABS_RIGHT )
399*cdf0e10cSrcweir                     );
400*cdf0e10cSrcweir         }
401*cdf0e10cSrcweir 
402*cdf0e10cSrcweir     protected:
403*cdf0e10cSrcweir         DECL_LINK( OnScroll, const PushButton* );
404*cdf0e10cSrcweir 
405*cdf0e10cSrcweir         void        impl_calcItemRects();
406*cdf0e10cSrcweir         Size        impl_calculateItemContentSize( const PToolPanel& i_pPanel, const TabItemContent i_eItemContent ) const;
407*cdf0e10cSrcweir         void        impl_renderItemContent( const PToolPanel& i_pPanel, const Rectangle& i_rContentArea, const TabItemContent i_eItemContent ) const;
408*cdf0e10cSrcweir         ItemFlags   impl_getItemFlags( const size_t i_nItemIndex ) const;
409*cdf0e10cSrcweir 
410*cdf0e10cSrcweir     public:
411*cdf0e10cSrcweir         PanelTabBar&                m_rTabBar;
412*cdf0e10cSrcweir         TabBarGeometry              m_aGeometry;
413*cdf0e10cSrcweir         NormalizedArea              m_aNormalizer;
414*cdf0e10cSrcweir         TabAlignment                m_eTabAlignment;
415*cdf0e10cSrcweir         IToolPanelDeck&             m_rPanelDeck;
416*cdf0e10cSrcweir 
417*cdf0e10cSrcweir         VirtualDevice               m_aRenderDevice;
418*cdf0e10cSrcweir         PTabBarRenderer             m_pRenderer;
419*cdf0e10cSrcweir 
420*cdf0e10cSrcweir         ::boost::optional< size_t > m_aHoveredItem;
421*cdf0e10cSrcweir         ::boost::optional< size_t > m_aFocusedItem;
422*cdf0e10cSrcweir         bool                        m_bMouseButtonDown;
423*cdf0e10cSrcweir 
424*cdf0e10cSrcweir         ItemDescriptors             m_aItems;
425*cdf0e10cSrcweir         bool                        m_bItemsDirty;
426*cdf0e10cSrcweir 
427*cdf0e10cSrcweir         PushButton                  m_aScrollBack;
428*cdf0e10cSrcweir         PushButton                  m_aScrollForward;
429*cdf0e10cSrcweir 
430*cdf0e10cSrcweir         size_t                      m_nScrollPosition;
431*cdf0e10cSrcweir     };
432*cdf0e10cSrcweir 
433*cdf0e10cSrcweir     //==================================================================================================================
434*cdf0e10cSrcweir 	//= helper
435*cdf0e10cSrcweir 	//==================================================================================================================
436*cdf0e10cSrcweir     namespace
437*cdf0e10cSrcweir     {
438*cdf0e10cSrcweir 	    //--------------------------------------------------------------------------------------------------------------
439*cdf0e10cSrcweir     #if OSL_DEBUG_LEVEL > 0
440*cdf0e10cSrcweir         static void lcl_checkConsistency( const PanelTabBar_Impl& i_rImpl )
441*cdf0e10cSrcweir         {
442*cdf0e10cSrcweir             if ( !i_rImpl.m_bItemsDirty )
443*cdf0e10cSrcweir             {
444*cdf0e10cSrcweir                 if ( i_rImpl.m_rPanelDeck.GetPanelCount() != i_rImpl.m_aItems.size() )
445*cdf0e10cSrcweir                 {
446*cdf0e10cSrcweir                     OSL_ENSURE( false, "lcl_checkConsistency: inconsistent array sizes!" );
447*cdf0e10cSrcweir                     return;
448*cdf0e10cSrcweir                 }
449*cdf0e10cSrcweir                 for ( size_t i = 0; i < i_rImpl.m_rPanelDeck.GetPanelCount(); ++i )
450*cdf0e10cSrcweir                 {
451*cdf0e10cSrcweir                     if ( i_rImpl.m_rPanelDeck.GetPanel( i ).get() != i_rImpl.m_aItems[i].pPanel.get() )
452*cdf0e10cSrcweir                     {
453*cdf0e10cSrcweir                         OSL_ENSURE( false, "lcl_checkConsistency: array elements are inconsistent!" );
454*cdf0e10cSrcweir                         return;
455*cdf0e10cSrcweir                     }
456*cdf0e10cSrcweir                 }
457*cdf0e10cSrcweir             }
458*cdf0e10cSrcweir         }
459*cdf0e10cSrcweir 
460*cdf0e10cSrcweir         #define DBG_CHECK( data ) \
461*cdf0e10cSrcweir             lcl_checkConsistency( data );
462*cdf0e10cSrcweir     #else
463*cdf0e10cSrcweir         #define DBG_CHECK( data ) \
464*cdf0e10cSrcweir             (void)data;
465*cdf0e10cSrcweir     #endif
466*cdf0e10cSrcweir 
467*cdf0e10cSrcweir         //--------------------------------------------------------------------------------------------------------------
468*cdf0e10cSrcweir         class ClipItemRegion
469*cdf0e10cSrcweir         {
470*cdf0e10cSrcweir         public:
471*cdf0e10cSrcweir             ClipItemRegion( const PanelTabBar_Impl& i_rImpl )
472*cdf0e10cSrcweir                 :m_rDevice( i_rImpl.m_rTabBar )
473*cdf0e10cSrcweir             {
474*cdf0e10cSrcweir                 m_rDevice.Push( PUSH_CLIPREGION );
475*cdf0e10cSrcweir                 m_rDevice.SetClipRegion( i_rImpl.m_aNormalizer.getTransformed( i_rImpl.m_aGeometry.getItemsRect(), i_rImpl.m_eTabAlignment ) );
476*cdf0e10cSrcweir             }
477*cdf0e10cSrcweir 
478*cdf0e10cSrcweir             ~ClipItemRegion()
479*cdf0e10cSrcweir             {
480*cdf0e10cSrcweir                 m_rDevice.Pop();
481*cdf0e10cSrcweir             }
482*cdf0e10cSrcweir 
483*cdf0e10cSrcweir         private:
484*cdf0e10cSrcweir             OutputDevice&   m_rDevice;
485*cdf0e10cSrcweir         };
486*cdf0e10cSrcweir     }
487*cdf0e10cSrcweir 
488*cdf0e10cSrcweir 	//==================================================================================================================
489*cdf0e10cSrcweir 	//= PanelTabBar_Impl - implementation
490*cdf0e10cSrcweir 	//==================================================================================================================
491*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
492*cdf0e10cSrcweir     PanelTabBar_Impl::PanelTabBar_Impl( PanelTabBar& i_rTabBar, IToolPanelDeck& i_rPanelDeck, const TabAlignment i_eAlignment, const TabItemContent i_eItemContent )
493*cdf0e10cSrcweir         :m_rTabBar( i_rTabBar )
494*cdf0e10cSrcweir         ,m_aGeometry( i_eItemContent )
495*cdf0e10cSrcweir         ,m_aNormalizer()
496*cdf0e10cSrcweir         ,m_eTabAlignment( i_eAlignment )
497*cdf0e10cSrcweir         ,m_rPanelDeck( i_rPanelDeck )
498*cdf0e10cSrcweir         ,m_aRenderDevice( i_rTabBar )
499*cdf0e10cSrcweir         ,m_pRenderer()
500*cdf0e10cSrcweir         ,m_aHoveredItem()
501*cdf0e10cSrcweir         ,m_aFocusedItem()
502*cdf0e10cSrcweir         ,m_bMouseButtonDown( false )
503*cdf0e10cSrcweir         ,m_aItems()
504*cdf0e10cSrcweir         ,m_bItemsDirty( true )
505*cdf0e10cSrcweir         ,m_aScrollBack( &i_rTabBar, WB_BEVELBUTTON )
506*cdf0e10cSrcweir         ,m_aScrollForward( &i_rTabBar, WB_BEVELBUTTON )
507*cdf0e10cSrcweir         ,m_nScrollPosition( 0 )
508*cdf0e10cSrcweir     {
509*cdf0e10cSrcweir #ifdef WNT
510*cdf0e10cSrcweir         if ( m_aRenderDevice.IsNativeControlSupported( CTRL_TAB_ITEM, PART_ENTIRE_CONTROL ) )
511*cdf0e10cSrcweir             // this mode requires the NWF framework to be able to render those items onto a virtual
512*cdf0e10cSrcweir             // device. For some frameworks (some GTK themes, in particular), this is known to fail.
513*cdf0e10cSrcweir             // So, be on the safe side for the moment.
514*cdf0e10cSrcweir             m_pRenderer.reset( new NWFTabItemRenderer( m_aRenderDevice ) );
515*cdf0e10cSrcweir         else
516*cdf0e10cSrcweir #endif
517*cdf0e10cSrcweir         if ( m_aRenderDevice.IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) )
518*cdf0e10cSrcweir             m_pRenderer.reset( new NWFToolboxItemRenderer( m_aRenderDevice ) );
519*cdf0e10cSrcweir         else
520*cdf0e10cSrcweir             m_pRenderer.reset( new VCLItemRenderer( m_aRenderDevice ) );
521*cdf0e10cSrcweir 
522*cdf0e10cSrcweir         m_aRenderDevice.SetLineColor();
523*cdf0e10cSrcweir 
524*cdf0e10cSrcweir         m_rPanelDeck.AddListener( *this );
525*cdf0e10cSrcweir 
526*cdf0e10cSrcweir         m_aScrollBack.SetSymbol( IsVertical() ? SYMBOL_ARROW_UP : SYMBOL_ARROW_LEFT );
527*cdf0e10cSrcweir         m_aScrollBack.Show();
528*cdf0e10cSrcweir         m_aScrollBack.SetClickHdl( LINK( this, PanelTabBar_Impl, OnScroll ) );
529*cdf0e10cSrcweir         m_aScrollBack.SetAccessibleDescription( String( SvtResId( STR_SVT_TOOL_PANEL_BUTTON_FWD ) ) );
530*cdf0e10cSrcweir         m_aScrollBack.SetAccessibleName( m_aScrollBack.GetAccessibleDescription() );
531*cdf0e10cSrcweir 
532*cdf0e10cSrcweir         m_aScrollForward.SetSymbol( IsVertical() ? SYMBOL_ARROW_DOWN : SYMBOL_ARROW_RIGHT );
533*cdf0e10cSrcweir         m_aScrollForward.Show();
534*cdf0e10cSrcweir         m_aScrollForward.SetClickHdl( LINK( this, PanelTabBar_Impl, OnScroll ) );
535*cdf0e10cSrcweir         m_aScrollForward.SetAccessibleDescription( String( SvtResId( STR_SVT_TOOL_PANEL_BUTTON_BACK ) ) );
536*cdf0e10cSrcweir         m_aScrollForward.SetAccessibleName( m_aScrollForward.GetAccessibleDescription() );
537*cdf0e10cSrcweir     }
538*cdf0e10cSrcweir 
539*cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
540*cdf0e10cSrcweir     void PanelTabBar_Impl::impl_calcItemRects()
541*cdf0e10cSrcweir     {
542*cdf0e10cSrcweir         m_aItems.resize(0);
543*cdf0e10cSrcweir 
544*cdf0e10cSrcweir         Point aCompletePos( m_aGeometry.getFirstItemPosition() );
545*cdf0e10cSrcweir         Point aIconOnlyPos( aCompletePos );
546*cdf0e10cSrcweir         Point aTextOnlyPos( aCompletePos );
547*cdf0e10cSrcweir 
548*cdf0e10cSrcweir         for (   size_t i = 0;
549*cdf0e10cSrcweir                 i < m_rPanelDeck.GetPanelCount();
550*cdf0e10cSrcweir                 ++i
551*cdf0e10cSrcweir             )
552*cdf0e10cSrcweir         {
553*cdf0e10cSrcweir             PToolPanel pPanel( m_rPanelDeck.GetPanel( i ) );
554*cdf0e10cSrcweir 
555*cdf0e10cSrcweir             ItemDescriptor aItem;
556*cdf0e10cSrcweir             aItem.pPanel = pPanel;
557*cdf0e10cSrcweir 
558*cdf0e10cSrcweir             Rectangle aContentArea;
559*cdf0e10cSrcweir 
560*cdf0e10cSrcweir             const Size aCompleteSize( impl_calculateItemContentSize( pPanel, TABITEM_IMAGE_AND_TEXT ) );
561*cdf0e10cSrcweir             const Size aIconOnlySize( impl_calculateItemContentSize( pPanel, TABITEM_IMAGE_ONLY ) );
562*cdf0e10cSrcweir             const Size aTextOnlySize( impl_calculateItemContentSize( pPanel, TABITEM_TEXT_ONLY ) );
563*cdf0e10cSrcweir 
564*cdf0e10cSrcweir             // TODO: have one method calculating all sizes?
565*cdf0e10cSrcweir 
566*cdf0e10cSrcweir             // remember the three areas
567*cdf0e10cSrcweir             aItem.aCompleteArea = Rectangle( aCompletePos, aCompleteSize );
568*cdf0e10cSrcweir             aItem.aIconOnlyArea = Rectangle( aIconOnlyPos, aIconOnlySize );
569*cdf0e10cSrcweir             aItem.aTextOnlyArea = Rectangle( aTextOnlyPos, aTextOnlySize );
570*cdf0e10cSrcweir 
571*cdf0e10cSrcweir             m_aItems.push_back( aItem );
572*cdf0e10cSrcweir 
573*cdf0e10cSrcweir             aCompletePos = aItem.aCompleteArea.TopRight();
574*cdf0e10cSrcweir             aIconOnlyPos = aItem.aIconOnlyArea.TopRight();
575*cdf0e10cSrcweir             aTextOnlyPos = aItem.aTextOnlyArea.TopRight();
576*cdf0e10cSrcweir         }
577*cdf0e10cSrcweir 
578*cdf0e10cSrcweir         m_bItemsDirty = false;
579*cdf0e10cSrcweir     }
580*cdf0e10cSrcweir 
581*cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
582*cdf0e10cSrcweir     Size PanelTabBar_Impl::impl_calculateItemContentSize( const PToolPanel& i_pPanel, const TabItemContent i_eItemContent ) const
583*cdf0e10cSrcweir     {
584*cdf0e10cSrcweir         // calculate the size needed for the content
585*cdf0e10cSrcweir         OSL_ENSURE( i_eItemContent != TABITEM_AUTO, "PanelTabBar_Impl::impl_calculateItemContentSize: illegal TabItemContent value!" );
586*cdf0e10cSrcweir 
587*cdf0e10cSrcweir         const Image aImage( i_pPanel->GetImage() );
588*cdf0e10cSrcweir         const bool bUseImage = !!aImage && ( i_eItemContent != TABITEM_TEXT_ONLY );
589*cdf0e10cSrcweir 
590*cdf0e10cSrcweir         const ::rtl::OUString sItemText( i_pPanel->GetDisplayName() );
591*cdf0e10cSrcweir         const bool bUseText = ( sItemText.getLength() != 0 ) && ( i_eItemContent != TABITEM_IMAGE_ONLY );
592*cdf0e10cSrcweir 
593*cdf0e10cSrcweir         Size aItemContentSize;
594*cdf0e10cSrcweir         if ( bUseImage )
595*cdf0e10cSrcweir         {
596*cdf0e10cSrcweir             aItemContentSize = aImage.GetSizePixel();
597*cdf0e10cSrcweir         }
598*cdf0e10cSrcweir 
599*cdf0e10cSrcweir         if ( bUseText )
600*cdf0e10cSrcweir         {
601*cdf0e10cSrcweir             if ( bUseImage )
602*cdf0e10cSrcweir                 aItemContentSize.Width() += ITEM_ICON_TEXT_DISTANCE;
603*cdf0e10cSrcweir 
604*cdf0e10cSrcweir             // add space for text
605*cdf0e10cSrcweir             const Size aTextSize( m_rTabBar.GetCtrlTextWidth( sItemText ), m_rTabBar.GetTextHeight() );
606*cdf0e10cSrcweir             aItemContentSize.Width() += aTextSize.Width();
607*cdf0e10cSrcweir             aItemContentSize.Height() = ::std::max( aItemContentSize.Height(), aTextSize.Height() );
608*cdf0e10cSrcweir 
609*cdf0e10cSrcweir             aItemContentSize.Width() += 2 * ITEM_TEXT_FLOW_SPACE;
610*cdf0e10cSrcweir         }
611*cdf0e10cSrcweir 
612*cdf0e10cSrcweir         if ( !bUseImage && !bUseText )
613*cdf0e10cSrcweir         {
614*cdf0e10cSrcweir             // have a minimal size - this is pure heuristics, but if it doesn't suit your needs, then give your panels
615*cdf0e10cSrcweir             // a name and or image! :)
616*cdf0e10cSrcweir             aItemContentSize = Size( 16, 16 );
617*cdf0e10cSrcweir         }
618*cdf0e10cSrcweir 
619*cdf0e10cSrcweir         aItemContentSize.Width() += 2 * ITEM_OUTER_SPACE;
620*cdf0e10cSrcweir         aItemContentSize.Height() += 2 * ITEM_OUTER_SPACE;
621*cdf0e10cSrcweir 
622*cdf0e10cSrcweir         return aItemContentSize;
623*cdf0e10cSrcweir     }
624*cdf0e10cSrcweir 
625*cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
626*cdf0e10cSrcweir     void PanelTabBar_Impl::impl_renderItemContent( const PToolPanel& i_pPanel, const Rectangle& i_rContentArea, const TabItemContent i_eItemContent ) const
627*cdf0e10cSrcweir     {
628*cdf0e10cSrcweir         OSL_ENSURE( i_eItemContent != TABITEM_AUTO, "PanelTabBar_Impl::impl_renderItemContent: illegal TabItemContent value!" );
629*cdf0e10cSrcweir 
630*cdf0e10cSrcweir         Rectangle aRenderArea( i_rContentArea );
631*cdf0e10cSrcweir         if ( IsVertical() )
632*cdf0e10cSrcweir         {
633*cdf0e10cSrcweir             aRenderArea.Top() += ITEM_OUTER_SPACE;
634*cdf0e10cSrcweir         }
635*cdf0e10cSrcweir         else
636*cdf0e10cSrcweir         {
637*cdf0e10cSrcweir             aRenderArea.Left() += ITEM_OUTER_SPACE;
638*cdf0e10cSrcweir         }
639*cdf0e10cSrcweir 
640*cdf0e10cSrcweir         // draw the image
641*cdf0e10cSrcweir         const Image aItemImage( i_pPanel->GetImage() );
642*cdf0e10cSrcweir         const Size aImageSize( aItemImage.GetSizePixel() );
643*cdf0e10cSrcweir         const bool bUseImage = !!aItemImage && ( i_eItemContent != TABITEM_TEXT_ONLY );
644*cdf0e10cSrcweir 
645*cdf0e10cSrcweir         if ( bUseImage )
646*cdf0e10cSrcweir         {
647*cdf0e10cSrcweir             Point aImagePos;
648*cdf0e10cSrcweir             if ( IsVertical() )
649*cdf0e10cSrcweir             {
650*cdf0e10cSrcweir                 aImagePos.X() = aRenderArea.Left() + ( aRenderArea.GetWidth() - aImageSize.Width() ) / 2;
651*cdf0e10cSrcweir                 aImagePos.Y() = aRenderArea.Top();
652*cdf0e10cSrcweir             }
653*cdf0e10cSrcweir             else
654*cdf0e10cSrcweir             {
655*cdf0e10cSrcweir                 aImagePos.X() = aRenderArea.Left();
656*cdf0e10cSrcweir                 aImagePos.Y() = aRenderArea.Top() + ( aRenderArea.GetHeight() - aImageSize.Height() ) / 2;
657*cdf0e10cSrcweir             }
658*cdf0e10cSrcweir             m_rTabBar.DrawImage( aImagePos, aItemImage );
659*cdf0e10cSrcweir         }
660*cdf0e10cSrcweir 
661*cdf0e10cSrcweir         const ::rtl::OUString sItemText( i_pPanel->GetDisplayName() );
662*cdf0e10cSrcweir         const bool bUseText = ( sItemText.getLength() != 0 ) && ( i_eItemContent != TABITEM_IMAGE_ONLY );
663*cdf0e10cSrcweir 
664*cdf0e10cSrcweir         if ( bUseText )
665*cdf0e10cSrcweir         {
666*cdf0e10cSrcweir             if ( IsVertical() )
667*cdf0e10cSrcweir             {
668*cdf0e10cSrcweir                 if ( bUseImage )
669*cdf0e10cSrcweir                     aRenderArea.Top() += aImageSize.Height() + ITEM_ICON_TEXT_DISTANCE;
670*cdf0e10cSrcweir                 aRenderArea.Top() += ITEM_TEXT_FLOW_SPACE;
671*cdf0e10cSrcweir             }
672*cdf0e10cSrcweir             else
673*cdf0e10cSrcweir             {
674*cdf0e10cSrcweir                 if ( bUseImage )
675*cdf0e10cSrcweir                     aRenderArea.Left() += aImageSize.Width() + ITEM_ICON_TEXT_DISTANCE;
676*cdf0e10cSrcweir                 aRenderArea.Left() += ITEM_TEXT_FLOW_SPACE;
677*cdf0e10cSrcweir             }
678*cdf0e10cSrcweir 
679*cdf0e10cSrcweir             // draw the text
680*cdf0e10cSrcweir             const Size aTextSize( m_rTabBar.GetCtrlTextWidth( sItemText ), m_rTabBar.GetTextHeight() );
681*cdf0e10cSrcweir             Point aTextPos( aRenderArea.TopLeft() );
682*cdf0e10cSrcweir             if ( IsVertical() )
683*cdf0e10cSrcweir             {
684*cdf0e10cSrcweir                 m_rTabBar.Push( PUSH_FONT );
685*cdf0e10cSrcweir 
686*cdf0e10cSrcweir                 Font aFont( m_rTabBar.GetFont() );
687*cdf0e10cSrcweir                 aFont.SetOrientation( 2700 );
688*cdf0e10cSrcweir                 aFont.SetVertical( sal_True );
689*cdf0e10cSrcweir                 m_rTabBar.SetFont( aFont );
690*cdf0e10cSrcweir 
691*cdf0e10cSrcweir                 aTextPos.X() += aTextSize.Height();
692*cdf0e10cSrcweir                 aTextPos.X() += ( aRenderArea.GetWidth() - aTextSize.Height() ) / 2;
693*cdf0e10cSrcweir             }
694*cdf0e10cSrcweir             else
695*cdf0e10cSrcweir             {
696*cdf0e10cSrcweir                 aTextPos.Y() += ( aRenderArea.GetHeight() - aTextSize.Height() ) / 2;
697*cdf0e10cSrcweir             }
698*cdf0e10cSrcweir 
699*cdf0e10cSrcweir             m_rTabBar.DrawText( aTextPos, sItemText );
700*cdf0e10cSrcweir 
701*cdf0e10cSrcweir             if ( IsVertical() )
702*cdf0e10cSrcweir             {
703*cdf0e10cSrcweir                 m_rTabBar.Pop();
704*cdf0e10cSrcweir             }
705*cdf0e10cSrcweir         }
706*cdf0e10cSrcweir     }
707*cdf0e10cSrcweir 
708*cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
709*cdf0e10cSrcweir     void PanelTabBar_Impl::CopyFromRenderDevice( const Rectangle& i_rLogicalRect ) const
710*cdf0e10cSrcweir     {
711*cdf0e10cSrcweir         BitmapEx aBitmap( m_aRenderDevice.GetBitmapEx(
712*cdf0e10cSrcweir             i_rLogicalRect.TopLeft(),
713*cdf0e10cSrcweir             Size(
714*cdf0e10cSrcweir                 i_rLogicalRect.GetSize().Width(),
715*cdf0e10cSrcweir                 i_rLogicalRect.GetSize().Height()
716*cdf0e10cSrcweir             )
717*cdf0e10cSrcweir         ) );
718*cdf0e10cSrcweir         if ( IsVertical() )
719*cdf0e10cSrcweir         {
720*cdf0e10cSrcweir             aBitmap.Rotate( 2700, COL_BLACK );
721*cdf0e10cSrcweir             if ( m_eTabAlignment == TABS_LEFT )
722*cdf0e10cSrcweir                 aBitmap.Mirror( BMP_MIRROR_HORZ );
723*cdf0e10cSrcweir         }
724*cdf0e10cSrcweir         else if ( m_eTabAlignment == TABS_BOTTOM )
725*cdf0e10cSrcweir         {
726*cdf0e10cSrcweir             aBitmap.Mirror( BMP_MIRROR_VERT );
727*cdf0e10cSrcweir         }
728*cdf0e10cSrcweir 
729*cdf0e10cSrcweir         const Rectangle aActualRect( m_aNormalizer.getTransformed( i_rLogicalRect, m_eTabAlignment ) );
730*cdf0e10cSrcweir         m_rTabBar.DrawBitmapEx( aActualRect.TopLeft(), aBitmap );
731*cdf0e10cSrcweir     }
732*cdf0e10cSrcweir 
733*cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
734*cdf0e10cSrcweir     void PanelTabBar_Impl::InvalidateItem( const size_t i_nItemIndex, const ItemFlags i_nAdditionalItemFlags ) const
735*cdf0e10cSrcweir     {
736*cdf0e10cSrcweir         const ItemDescriptor& rItem( m_aItems[ i_nItemIndex ] );
737*cdf0e10cSrcweir         const ItemFlags nItemFlags( impl_getItemFlags( i_nItemIndex ) | i_nAdditionalItemFlags );
738*cdf0e10cSrcweir 
739*cdf0e10cSrcweir         const Rectangle aNormalizedContent( GetActualLogicalItemRect( rItem.GetCurrentRect() ) );
740*cdf0e10cSrcweir         const Rectangle aNormalizedBounds( m_pRenderer->calculateDecorations( aNormalizedContent, nItemFlags ) );
741*cdf0e10cSrcweir 
742*cdf0e10cSrcweir         const Rectangle aActualBounds = m_aNormalizer.getTransformed( aNormalizedBounds, m_eTabAlignment );
743*cdf0e10cSrcweir         m_rTabBar.Invalidate( aActualBounds );
744*cdf0e10cSrcweir     }
745*cdf0e10cSrcweir 
746*cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
747*cdf0e10cSrcweir     ItemFlags PanelTabBar_Impl::impl_getItemFlags( const size_t i_nItemIndex ) const
748*cdf0e10cSrcweir     {
749*cdf0e10cSrcweir         ItemFlags nItemFlags( ITEM_STATE_NORMAL );
750*cdf0e10cSrcweir         if ( m_aHoveredItem == i_nItemIndex )
751*cdf0e10cSrcweir         {
752*cdf0e10cSrcweir             nItemFlags |= ITEM_STATE_HOVERED;
753*cdf0e10cSrcweir             if ( m_bMouseButtonDown )
754*cdf0e10cSrcweir                 nItemFlags |= ITEM_STATE_ACTIVE;
755*cdf0e10cSrcweir         }
756*cdf0e10cSrcweir 
757*cdf0e10cSrcweir         if ( m_rPanelDeck.GetActivePanel() == i_nItemIndex )
758*cdf0e10cSrcweir             nItemFlags |= ITEM_STATE_ACTIVE;
759*cdf0e10cSrcweir 
760*cdf0e10cSrcweir         if ( m_aFocusedItem == i_nItemIndex )
761*cdf0e10cSrcweir             nItemFlags |= ITEM_STATE_FOCUSED;
762*cdf0e10cSrcweir 
763*cdf0e10cSrcweir         if ( 0 == i_nItemIndex )
764*cdf0e10cSrcweir             nItemFlags |= ITEM_POSITION_FIRST;
765*cdf0e10cSrcweir 
766*cdf0e10cSrcweir         if ( m_rPanelDeck.GetPanelCount() - 1 == i_nItemIndex )
767*cdf0e10cSrcweir             nItemFlags |= ITEM_POSITION_LAST;
768*cdf0e10cSrcweir 
769*cdf0e10cSrcweir         return nItemFlags;
770*cdf0e10cSrcweir     }
771*cdf0e10cSrcweir 
772*cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
773*cdf0e10cSrcweir     void PanelTabBar_Impl::DrawItem( const size_t i_nItemIndex, const Rectangle& i_rBoundaries ) const
774*cdf0e10cSrcweir     {
775*cdf0e10cSrcweir         const ItemDescriptor& rItem( m_aItems[ i_nItemIndex ] );
776*cdf0e10cSrcweir         const ItemFlags nItemFlags( impl_getItemFlags( i_nItemIndex ) );
777*cdf0e10cSrcweir 
778*cdf0e10cSrcweir         // the normalized bounding and content rect
779*cdf0e10cSrcweir         const Rectangle aNormalizedContent( GetActualLogicalItemRect( rItem.GetCurrentRect() ) );
780*cdf0e10cSrcweir         const Rectangle aNormalizedBounds( m_pRenderer->calculateDecorations( aNormalizedContent, nItemFlags ) );
781*cdf0e10cSrcweir 
782*cdf0e10cSrcweir         // check whether the item actually overlaps with the painting area
783*cdf0e10cSrcweir         if ( !i_rBoundaries.IsEmpty() )
784*cdf0e10cSrcweir         {
785*cdf0e10cSrcweir             const Rectangle aItemRect( GetActualLogicalItemRect( rItem.GetCurrentRect() ) );
786*cdf0e10cSrcweir             if ( !aItemRect.IsOver( i_rBoundaries ) )
787*cdf0e10cSrcweir                 return;
788*cdf0e10cSrcweir         }
789*cdf0e10cSrcweir 
790*cdf0e10cSrcweir         m_rTabBar.SetUpdateMode( sal_False );
791*cdf0e10cSrcweir 
792*cdf0e10cSrcweir         // the aligned bounding and content rect
793*cdf0e10cSrcweir         const Rectangle aActualBounds = m_aNormalizer.getTransformed( aNormalizedBounds, m_eTabAlignment );
794*cdf0e10cSrcweir         const Rectangle aActualContent = m_aNormalizer.getTransformed( aNormalizedContent, m_eTabAlignment );
795*cdf0e10cSrcweir 
796*cdf0e10cSrcweir         // render item "background" layer
797*cdf0e10cSrcweir         m_pRenderer->preRenderItem( aNormalizedContent, nItemFlags );
798*cdf0e10cSrcweir 
799*cdf0e10cSrcweir         // copy from the virtual device to ourself
800*cdf0e10cSrcweir         CopyFromRenderDevice( aNormalizedBounds );
801*cdf0e10cSrcweir 
802*cdf0e10cSrcweir         // render the actual item content
803*cdf0e10cSrcweir         impl_renderItemContent( rItem.pPanel, aActualContent, rItem.eContent );
804*cdf0e10cSrcweir 
805*cdf0e10cSrcweir         // render item "foreground" layer
806*cdf0e10cSrcweir         m_pRenderer->postRenderItem( m_rTabBar, aActualBounds, nItemFlags );
807*cdf0e10cSrcweir 
808*cdf0e10cSrcweir         m_rTabBar.SetUpdateMode( sal_True );
809*cdf0e10cSrcweir     }
810*cdf0e10cSrcweir 
811*cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
812*cdf0e10cSrcweir     void PanelTabBar_Impl::EnsureItemsCache()
813*cdf0e10cSrcweir     {
814*cdf0e10cSrcweir         if ( m_bItemsDirty == false )
815*cdf0e10cSrcweir         {
816*cdf0e10cSrcweir             DBG_CHECK( *this );
817*cdf0e10cSrcweir             return;
818*cdf0e10cSrcweir         }
819*cdf0e10cSrcweir         impl_calcItemRects();
820*cdf0e10cSrcweir         OSL_POSTCOND( m_bItemsDirty == false, "PanelTabBar_Impl::EnsureItemsCache: cache still dirty!" );
821*cdf0e10cSrcweir         DBG_CHECK( *this );
822*cdf0e10cSrcweir     }
823*cdf0e10cSrcweir 
824*cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
825*cdf0e10cSrcweir     void PanelTabBar_Impl::Relayout()
826*cdf0e10cSrcweir     {
827*cdf0e10cSrcweir         EnsureItemsCache();
828*cdf0e10cSrcweir 
829*cdf0e10cSrcweir         const Size aOutputSize( m_rTabBar.GetOutputSizePixel() );
830*cdf0e10cSrcweir         m_aNormalizer = NormalizedArea( Rectangle( Point(), aOutputSize ), IsVertical() );
831*cdf0e10cSrcweir         const Size aLogicalOutputSize( m_aNormalizer.getReferenceSize() );
832*cdf0e10cSrcweir 
833*cdf0e10cSrcweir         // forward actual output size to our render device
834*cdf0e10cSrcweir         m_aRenderDevice.SetOutputSizePixel( aLogicalOutputSize );
835*cdf0e10cSrcweir 
836*cdf0e10cSrcweir         // re-calculate the size of the scroll buttons and of the items
837*cdf0e10cSrcweir         m_aGeometry.relayout( aLogicalOutputSize, m_aItems );
838*cdf0e10cSrcweir 
839*cdf0e10cSrcweir         if ( m_aGeometry.getButtonBackRect().IsEmpty() )
840*cdf0e10cSrcweir         {
841*cdf0e10cSrcweir             m_aScrollBack.Hide();
842*cdf0e10cSrcweir         }
843*cdf0e10cSrcweir         else
844*cdf0e10cSrcweir         {
845*cdf0e10cSrcweir             const Rectangle aButtonBack( m_aNormalizer.getTransformed( m_aGeometry.getButtonBackRect(), m_eTabAlignment ) );
846*cdf0e10cSrcweir             m_aScrollBack.SetPosSizePixel( aButtonBack.TopLeft(), aButtonBack.GetSize() );
847*cdf0e10cSrcweir             m_aScrollBack.Show();
848*cdf0e10cSrcweir         }
849*cdf0e10cSrcweir 
850*cdf0e10cSrcweir         if ( m_aGeometry.getButtonForwardRect().IsEmpty() )
851*cdf0e10cSrcweir         {
852*cdf0e10cSrcweir             m_aScrollForward.Hide();
853*cdf0e10cSrcweir         }
854*cdf0e10cSrcweir         else
855*cdf0e10cSrcweir         {
856*cdf0e10cSrcweir             const Rectangle aButtonForward( m_aNormalizer.getTransformed( m_aGeometry.getButtonForwardRect(), m_eTabAlignment ) );
857*cdf0e10cSrcweir             m_aScrollForward.SetPosSizePixel( aButtonForward.TopLeft(), aButtonForward.GetSize() );
858*cdf0e10cSrcweir             m_aScrollForward.Show();
859*cdf0e10cSrcweir         }
860*cdf0e10cSrcweir 
861*cdf0e10cSrcweir         UpdateScrollButtons();
862*cdf0e10cSrcweir     }
863*cdf0e10cSrcweir 
864*cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
865*cdf0e10cSrcweir     ::boost::optional< size_t > PanelTabBar_Impl::FindItemForPoint( const Point& i_rPoint ) const
866*cdf0e10cSrcweir     {
867*cdf0e10cSrcweir         Point aPoint( IsVertical() ? i_rPoint.Y() : i_rPoint.X(), IsVertical() ? i_rPoint.X() : i_rPoint.Y() );
868*cdf0e10cSrcweir 
869*cdf0e10cSrcweir         if ( !m_aGeometry.getItemsRect().IsInside( aPoint ) )
870*cdf0e10cSrcweir             return ::boost::optional< size_t >();
871*cdf0e10cSrcweir 
872*cdf0e10cSrcweir         size_t i=0;
873*cdf0e10cSrcweir         for (   ItemDescriptors::const_iterator item = m_aItems.begin();
874*cdf0e10cSrcweir                 item != m_aItems.end();
875*cdf0e10cSrcweir                 ++item, ++i
876*cdf0e10cSrcweir             )
877*cdf0e10cSrcweir         {
878*cdf0e10cSrcweir             Rectangle aItemRect( GetActualLogicalItemRect( item->GetCurrentRect() ) );
879*cdf0e10cSrcweir             if ( aItemRect.IsInside( aPoint ) )
880*cdf0e10cSrcweir             {
881*cdf0e10cSrcweir                 return ::boost::optional< size_t >( i );
882*cdf0e10cSrcweir             }
883*cdf0e10cSrcweir         }
884*cdf0e10cSrcweir         return ::boost::optional< size_t >();
885*cdf0e10cSrcweir     }
886*cdf0e10cSrcweir 
887*cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
888*cdf0e10cSrcweir     Rectangle PanelTabBar_Impl::GetItemScreenRect( const size_t i_nItemPos ) const
889*cdf0e10cSrcweir     {
890*cdf0e10cSrcweir         ENSURE_OR_RETURN( i_nItemPos < m_aItems.size(), "PanelTabBar_Impl::GetItemScreenRect: invalid item pos!", Rectangle() );
891*cdf0e10cSrcweir         const ItemDescriptor& rItem( m_aItems[ i_nItemPos ] );
892*cdf0e10cSrcweir         const Rectangle aItemRect( m_aNormalizer.getTransformed(
893*cdf0e10cSrcweir             GetActualLogicalItemRect( rItem.GetCurrentRect() ),
894*cdf0e10cSrcweir             m_eTabAlignment ) );
895*cdf0e10cSrcweir 
896*cdf0e10cSrcweir 		const Rectangle aTabBarRect( m_rTabBar.GetWindowExtentsRelative( NULL ) );
897*cdf0e10cSrcweir         return Rectangle(
898*cdf0e10cSrcweir             Point( aTabBarRect.Left() + aItemRect.Left(), aTabBarRect.Top() + aItemRect.Top() ),
899*cdf0e10cSrcweir             aItemRect.GetSize()
900*cdf0e10cSrcweir         );
901*cdf0e10cSrcweir     }
902*cdf0e10cSrcweir 
903*cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
904*cdf0e10cSrcweir     void PanelTabBar_Impl::FocusItem( const ::boost::optional< size_t >& i_rItemPos )
905*cdf0e10cSrcweir     {
906*cdf0e10cSrcweir         // reset old focus item
907*cdf0e10cSrcweir         if ( !!m_aFocusedItem )
908*cdf0e10cSrcweir             InvalidateItem( *m_aFocusedItem );
909*cdf0e10cSrcweir         m_aFocusedItem.reset();
910*cdf0e10cSrcweir 
911*cdf0e10cSrcweir         // mark the active icon as focused
912*cdf0e10cSrcweir         if ( !!i_rItemPos )
913*cdf0e10cSrcweir         {
914*cdf0e10cSrcweir             m_aFocusedItem = i_rItemPos;
915*cdf0e10cSrcweir             InvalidateItem( *m_aFocusedItem );
916*cdf0e10cSrcweir         }
917*cdf0e10cSrcweir     }
918*cdf0e10cSrcweir 
919*cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
920*cdf0e10cSrcweir     IMPL_LINK( PanelTabBar_Impl, OnScroll, const PushButton*, i_pButton )
921*cdf0e10cSrcweir     {
922*cdf0e10cSrcweir         if ( i_pButton == &m_aScrollBack )
923*cdf0e10cSrcweir         {
924*cdf0e10cSrcweir             OSL_ENSURE( m_nScrollPosition > 0, "PanelTabBar_Impl::OnScroll: inconsistency!" );
925*cdf0e10cSrcweir             --m_nScrollPosition;
926*cdf0e10cSrcweir             m_rTabBar.Invalidate();
927*cdf0e10cSrcweir         }
928*cdf0e10cSrcweir         else if ( i_pButton == &m_aScrollForward )
929*cdf0e10cSrcweir         {
930*cdf0e10cSrcweir             OSL_ENSURE( m_nScrollPosition < m_aItems.size() - 1, "PanelTabBar_Impl::OnScroll: inconsistency!" );
931*cdf0e10cSrcweir             ++m_nScrollPosition;
932*cdf0e10cSrcweir             m_rTabBar.Invalidate();
933*cdf0e10cSrcweir         }
934*cdf0e10cSrcweir 
935*cdf0e10cSrcweir         UpdateScrollButtons();
936*cdf0e10cSrcweir 
937*cdf0e10cSrcweir         return 0L;
938*cdf0e10cSrcweir     }
939*cdf0e10cSrcweir 
940*cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
941*cdf0e10cSrcweir     Rectangle PanelTabBar_Impl::GetActualLogicalItemRect( const Rectangle& i_rLogicalItemRect ) const
942*cdf0e10cSrcweir     {
943*cdf0e10cSrcweir         // care for the offset imposed by our geometry, i.e. whether or not we have scroll buttons
944*cdf0e10cSrcweir         Rectangle aItemRect( i_rLogicalItemRect );
945*cdf0e10cSrcweir         aItemRect.Move( m_aGeometry.getItemsRect().Left() - m_aGeometry.getButtonBackRect().Left(), 0 );
946*cdf0e10cSrcweir 
947*cdf0e10cSrcweir         // care for the current scroll position
948*cdf0e10cSrcweir         OSL_ENSURE( m_nScrollPosition < m_aItems.size(), "GetActualLogicalItemRect: invalid scroll position!" );
949*cdf0e10cSrcweir         if ( ( m_nScrollPosition > 0 ) && ( m_nScrollPosition < m_aItems.size() ) )
950*cdf0e10cSrcweir         {
951*cdf0e10cSrcweir             long nOffsetX = m_aItems[ m_nScrollPosition ].GetCurrentRect().Left() - m_aItems[ 0 ].GetCurrentRect().Left();
952*cdf0e10cSrcweir             long nOffsetY = m_aItems[ m_nScrollPosition ].GetCurrentRect().Top() - m_aItems[ 0 ].GetCurrentRect().Top();
953*cdf0e10cSrcweir             aItemRect.Move( -nOffsetX, -nOffsetY );
954*cdf0e10cSrcweir         }
955*cdf0e10cSrcweir 
956*cdf0e10cSrcweir         return aItemRect;
957*cdf0e10cSrcweir     }
958*cdf0e10cSrcweir 
959*cdf0e10cSrcweir 	//==================================================================================================================
960*cdf0e10cSrcweir 	//= PanelTabBar_Impl
961*cdf0e10cSrcweir 	//==================================================================================================================
962*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
963*cdf0e10cSrcweir     void PanelTabBar_Impl::ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive )
964*cdf0e10cSrcweir     {
965*cdf0e10cSrcweir         EnsureItemsCache();
966*cdf0e10cSrcweir 
967*cdf0e10cSrcweir         if ( !!i_rOldActive )
968*cdf0e10cSrcweir             InvalidateItem( *i_rOldActive, ITEM_STATE_ACTIVE );
969*cdf0e10cSrcweir         if ( !!i_rNewActive )
970*cdf0e10cSrcweir             InvalidateItem( *i_rNewActive );
971*cdf0e10cSrcweir     }
972*cdf0e10cSrcweir 
973*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
974*cdf0e10cSrcweir     void PanelTabBar_Impl::LayouterChanged( const PDeckLayouter& i_rNewLayouter )
975*cdf0e10cSrcweir     {
976*cdf0e10cSrcweir         // not interested in
977*cdf0e10cSrcweir         (void)i_rNewLayouter;
978*cdf0e10cSrcweir     }
979*cdf0e10cSrcweir 
980*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
981*cdf0e10cSrcweir     void PanelTabBar_Impl::Dying()
982*cdf0e10cSrcweir     {
983*cdf0e10cSrcweir         // not interested in - the notifier is a member of this instance here, so we're dying ourself at the moment
984*cdf0e10cSrcweir     }
985*cdf0e10cSrcweir 
986*cdf0e10cSrcweir 	//==================================================================================================================
987*cdf0e10cSrcweir 	//= PanelTabBar
988*cdf0e10cSrcweir 	//==================================================================================================================
989*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
990*cdf0e10cSrcweir     PanelTabBar::PanelTabBar( Window& i_rParentWindow, IToolPanelDeck& i_rPanelDeck, const TabAlignment i_eAlignment, const TabItemContent i_eItemContent )
991*cdf0e10cSrcweir         :Control( &i_rParentWindow, 0 )
992*cdf0e10cSrcweir         ,m_pImpl( new PanelTabBar_Impl( *this, i_rPanelDeck, i_eAlignment, i_eItemContent ) )
993*cdf0e10cSrcweir     {
994*cdf0e10cSrcweir         DBG_CHECK( *m_pImpl );
995*cdf0e10cSrcweir     }
996*cdf0e10cSrcweir 
997*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
998*cdf0e10cSrcweir     PanelTabBar::~PanelTabBar()
999*cdf0e10cSrcweir     {
1000*cdf0e10cSrcweir     }
1001*cdf0e10cSrcweir 
1002*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
1003*cdf0e10cSrcweir     TabItemContent PanelTabBar::GetTabItemContent() const
1004*cdf0e10cSrcweir     {
1005*cdf0e10cSrcweir         return m_pImpl->m_aGeometry.getItemContent();
1006*cdf0e10cSrcweir     }
1007*cdf0e10cSrcweir 
1008*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
1009*cdf0e10cSrcweir     void PanelTabBar::SetTabItemContent( const TabItemContent& i_eItemContent )
1010*cdf0e10cSrcweir     {
1011*cdf0e10cSrcweir         m_pImpl->m_aGeometry.setItemContent( i_eItemContent );
1012*cdf0e10cSrcweir         m_pImpl->Relayout();
1013*cdf0e10cSrcweir         Invalidate();
1014*cdf0e10cSrcweir     }
1015*cdf0e10cSrcweir 
1016*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
1017*cdf0e10cSrcweir     IToolPanelDeck& PanelTabBar::GetPanelDeck() const
1018*cdf0e10cSrcweir     {
1019*cdf0e10cSrcweir         DBG_CHECK( *m_pImpl );
1020*cdf0e10cSrcweir         return m_pImpl->m_rPanelDeck;
1021*cdf0e10cSrcweir     }
1022*cdf0e10cSrcweir 
1023*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
1024*cdf0e10cSrcweir     Size PanelTabBar::GetOptimalSize( WindowSizeType i_eType ) const
1025*cdf0e10cSrcweir     {
1026*cdf0e10cSrcweir         m_pImpl->EnsureItemsCache();
1027*cdf0e10cSrcweir         Size aOptimalSize( m_pImpl->m_aGeometry.getOptimalSize( m_pImpl->m_aItems, i_eType == WINDOWSIZE_MINIMUM ) );
1028*cdf0e10cSrcweir         if ( m_pImpl->IsVertical() )
1029*cdf0e10cSrcweir             ::std::swap( aOptimalSize.Width(), aOptimalSize.Height() );
1030*cdf0e10cSrcweir         return aOptimalSize;
1031*cdf0e10cSrcweir     }
1032*cdf0e10cSrcweir 
1033*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
1034*cdf0e10cSrcweir     void PanelTabBar::Resize()
1035*cdf0e10cSrcweir     {
1036*cdf0e10cSrcweir         Control::Resize();
1037*cdf0e10cSrcweir         m_pImpl->Relayout();
1038*cdf0e10cSrcweir     }
1039*cdf0e10cSrcweir 
1040*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
1041*cdf0e10cSrcweir     void PanelTabBar::Paint( const Rectangle& i_rRect )
1042*cdf0e10cSrcweir     {
1043*cdf0e10cSrcweir         m_pImpl->EnsureItemsCache();
1044*cdf0e10cSrcweir 
1045*cdf0e10cSrcweir         // background
1046*cdf0e10cSrcweir         const Rectangle aNormalizedPaintArea( m_pImpl->m_aNormalizer.getNormalized( i_rRect, m_pImpl->m_eTabAlignment ) );
1047*cdf0e10cSrcweir         m_pImpl->m_aRenderDevice.Push( PUSH_CLIPREGION );
1048*cdf0e10cSrcweir         m_pImpl->m_aRenderDevice.SetClipRegion( aNormalizedPaintArea );
1049*cdf0e10cSrcweir         m_pImpl->m_pRenderer->renderBackground();
1050*cdf0e10cSrcweir         m_pImpl->m_aRenderDevice.Pop();
1051*cdf0e10cSrcweir         m_pImpl->CopyFromRenderDevice( aNormalizedPaintArea );
1052*cdf0e10cSrcweir 
1053*cdf0e10cSrcweir         // ensure the items really paint into their own playground only
1054*cdf0e10cSrcweir         ClipItemRegion aClipItems( *m_pImpl );
1055*cdf0e10cSrcweir 
1056*cdf0e10cSrcweir         const Rectangle aLogicalPaintRect( m_pImpl->m_aNormalizer.getNormalized( i_rRect, m_pImpl->m_eTabAlignment ) );
1057*cdf0e10cSrcweir 
1058*cdf0e10cSrcweir         const ::boost::optional< size_t > aActivePanel( m_pImpl->m_rPanelDeck.GetActivePanel() );
1059*cdf0e10cSrcweir         const ::boost::optional< size_t > aHoveredPanel( m_pImpl->m_aHoveredItem );
1060*cdf0e10cSrcweir 
1061*cdf0e10cSrcweir         // items:
1062*cdf0e10cSrcweir         // 1. paint all non-active, non-hovered items
1063*cdf0e10cSrcweir         size_t i=0;
1064*cdf0e10cSrcweir         for (   ItemDescriptors::const_iterator item = m_pImpl->m_aItems.begin();
1065*cdf0e10cSrcweir                 item != m_pImpl->m_aItems.end();
1066*cdf0e10cSrcweir                 ++item, ++i
1067*cdf0e10cSrcweir             )
1068*cdf0e10cSrcweir         {
1069*cdf0e10cSrcweir             if ( i == aActivePanel )
1070*cdf0e10cSrcweir                 continue;
1071*cdf0e10cSrcweir 
1072*cdf0e10cSrcweir             if ( aHoveredPanel == i )
1073*cdf0e10cSrcweir                 continue;
1074*cdf0e10cSrcweir 
1075*cdf0e10cSrcweir             m_pImpl->DrawItem( i, aLogicalPaintRect );
1076*cdf0e10cSrcweir         }
1077*cdf0e10cSrcweir 
1078*cdf0e10cSrcweir         // 2. paint the item which is hovered, /without/ the mouse button pressed down
1079*cdf0e10cSrcweir         if ( !!aHoveredPanel && !m_pImpl->m_bMouseButtonDown )
1080*cdf0e10cSrcweir             m_pImpl->DrawItem( *aHoveredPanel, aLogicalPaintRect );
1081*cdf0e10cSrcweir 
1082*cdf0e10cSrcweir         // 3. paint the active item
1083*cdf0e10cSrcweir         if ( !!aActivePanel )
1084*cdf0e10cSrcweir             m_pImpl->DrawItem( *aActivePanel, aLogicalPaintRect );
1085*cdf0e10cSrcweir 
1086*cdf0e10cSrcweir         // 4. paint the item which is hovered, /with/ the mouse button pressed down
1087*cdf0e10cSrcweir         if ( !!aHoveredPanel && m_pImpl->m_bMouseButtonDown )
1088*cdf0e10cSrcweir             m_pImpl->DrawItem( *aHoveredPanel, aLogicalPaintRect );
1089*cdf0e10cSrcweir     }
1090*cdf0e10cSrcweir 
1091*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
1092*cdf0e10cSrcweir     void PanelTabBar::MouseMove( const MouseEvent& i_rMouseEvent )
1093*cdf0e10cSrcweir     {
1094*cdf0e10cSrcweir         m_pImpl->EnsureItemsCache();
1095*cdf0e10cSrcweir 
1096*cdf0e10cSrcweir         ::boost::optional< size_t > aOldItem( m_pImpl->m_aHoveredItem );
1097*cdf0e10cSrcweir         ::boost::optional< size_t > aNewItem( m_pImpl->FindItemForPoint( i_rMouseEvent.GetPosPixel() ) );
1098*cdf0e10cSrcweir 
1099*cdf0e10cSrcweir         if  ( i_rMouseEvent.IsLeaveWindow() )
1100*cdf0e10cSrcweir             aNewItem.reset();
1101*cdf0e10cSrcweir 
1102*cdf0e10cSrcweir         if ( aOldItem != aNewItem )
1103*cdf0e10cSrcweir         {
1104*cdf0e10cSrcweir             if ( !!aOldItem )
1105*cdf0e10cSrcweir                 m_pImpl->InvalidateItem( *aOldItem );
1106*cdf0e10cSrcweir 
1107*cdf0e10cSrcweir             m_pImpl->m_aHoveredItem = aNewItem;
1108*cdf0e10cSrcweir 
1109*cdf0e10cSrcweir             if ( !!aNewItem )
1110*cdf0e10cSrcweir                 m_pImpl->InvalidateItem( *aNewItem );
1111*cdf0e10cSrcweir         }
1112*cdf0e10cSrcweir     }
1113*cdf0e10cSrcweir 
1114*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
1115*cdf0e10cSrcweir     void PanelTabBar::MouseButtonDown( const MouseEvent& i_rMouseEvent )
1116*cdf0e10cSrcweir     {
1117*cdf0e10cSrcweir         Control::MouseButtonDown( i_rMouseEvent );
1118*cdf0e10cSrcweir 
1119*cdf0e10cSrcweir         if ( !i_rMouseEvent.IsLeft() )
1120*cdf0e10cSrcweir             return;
1121*cdf0e10cSrcweir 
1122*cdf0e10cSrcweir         m_pImpl->EnsureItemsCache();
1123*cdf0e10cSrcweir 
1124*cdf0e10cSrcweir         ::boost::optional< size_t > aHitItem( m_pImpl->FindItemForPoint( i_rMouseEvent.GetPosPixel() ) );
1125*cdf0e10cSrcweir         if ( !aHitItem )
1126*cdf0e10cSrcweir             return;
1127*cdf0e10cSrcweir 
1128*cdf0e10cSrcweir         CaptureMouse();
1129*cdf0e10cSrcweir         m_pImpl->m_bMouseButtonDown = true;
1130*cdf0e10cSrcweir 
1131*cdf0e10cSrcweir         m_pImpl->InvalidateItem( *aHitItem );
1132*cdf0e10cSrcweir     }
1133*cdf0e10cSrcweir 
1134*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
1135*cdf0e10cSrcweir     void PanelTabBar::MouseButtonUp( const MouseEvent& i_rMouseEvent )
1136*cdf0e10cSrcweir     {
1137*cdf0e10cSrcweir         Control::MouseButtonUp( i_rMouseEvent );
1138*cdf0e10cSrcweir 
1139*cdf0e10cSrcweir         if ( m_pImpl->m_bMouseButtonDown )
1140*cdf0e10cSrcweir         {
1141*cdf0e10cSrcweir             ::boost::optional< size_t > aHitItem( m_pImpl->FindItemForPoint( i_rMouseEvent.GetPosPixel() ) );
1142*cdf0e10cSrcweir             if ( !!aHitItem )
1143*cdf0e10cSrcweir             {
1144*cdf0e10cSrcweir                 // re-draw that item now that we're not in mouse-down mode anymore
1145*cdf0e10cSrcweir                 m_pImpl->InvalidateItem( *aHitItem );
1146*cdf0e10cSrcweir                 // activate the respective panel
1147*cdf0e10cSrcweir                 m_pImpl->m_rPanelDeck.ActivatePanel( *aHitItem );
1148*cdf0e10cSrcweir             }
1149*cdf0e10cSrcweir 
1150*cdf0e10cSrcweir             OSL_ENSURE( IsMouseCaptured(), "PanelTabBar::MouseButtonUp: inconsistency!" );
1151*cdf0e10cSrcweir             if ( IsMouseCaptured() )
1152*cdf0e10cSrcweir                 ReleaseMouse();
1153*cdf0e10cSrcweir             m_pImpl->m_bMouseButtonDown = false;
1154*cdf0e10cSrcweir         }
1155*cdf0e10cSrcweir     }
1156*cdf0e10cSrcweir 
1157*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
1158*cdf0e10cSrcweir     void PanelTabBar::RequestHelp( const HelpEvent& i_rHelpEvent )
1159*cdf0e10cSrcweir     {
1160*cdf0e10cSrcweir         m_pImpl->EnsureItemsCache();
1161*cdf0e10cSrcweir 
1162*cdf0e10cSrcweir         ::boost::optional< size_t > aHelpItem( m_pImpl->FindItemForPoint( ScreenToOutputPixel( i_rHelpEvent.GetMousePosPixel() ) ) );
1163*cdf0e10cSrcweir         if ( !aHelpItem )
1164*cdf0e10cSrcweir             return;
1165*cdf0e10cSrcweir 
1166*cdf0e10cSrcweir         const ItemDescriptor& rItem( m_pImpl->m_aItems[ *aHelpItem ] );
1167*cdf0e10cSrcweir         if ( rItem.eContent != TABITEM_IMAGE_ONLY )
1168*cdf0e10cSrcweir             // if the text is displayed for the item, we do not need to show it as tooltip
1169*cdf0e10cSrcweir             return;
1170*cdf0e10cSrcweir 
1171*cdf0e10cSrcweir         const ::rtl::OUString sItemText( rItem.pPanel->GetDisplayName() );
1172*cdf0e10cSrcweir 		if ( i_rHelpEvent.GetMode() == HELPMODE_BALLOON )
1173*cdf0e10cSrcweir 			Help::ShowBalloon( this, OutputToScreenPixel( rItem.GetCurrentRect().Center() ), rItem.GetCurrentRect(), sItemText );
1174*cdf0e10cSrcweir 		else
1175*cdf0e10cSrcweir 			Help::ShowQuickHelp( this, rItem.GetCurrentRect(), sItemText );
1176*cdf0e10cSrcweir     }
1177*cdf0e10cSrcweir 
1178*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
1179*cdf0e10cSrcweir     void PanelTabBar::GetFocus()
1180*cdf0e10cSrcweir     {
1181*cdf0e10cSrcweir         Control::GetFocus();
1182*cdf0e10cSrcweir         if ( !m_pImpl->m_aFocusedItem )
1183*cdf0e10cSrcweir             m_pImpl->FocusItem( m_pImpl->m_rPanelDeck.GetActivePanel() );
1184*cdf0e10cSrcweir     }
1185*cdf0e10cSrcweir 
1186*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
1187*cdf0e10cSrcweir     void PanelTabBar::LoseFocus()
1188*cdf0e10cSrcweir     {
1189*cdf0e10cSrcweir         Control::LoseFocus();
1190*cdf0e10cSrcweir 
1191*cdf0e10cSrcweir         if ( !!m_pImpl->m_aFocusedItem )
1192*cdf0e10cSrcweir         {
1193*cdf0e10cSrcweir             m_pImpl->InvalidateItem( *m_pImpl->m_aFocusedItem );
1194*cdf0e10cSrcweir         }
1195*cdf0e10cSrcweir 
1196*cdf0e10cSrcweir         m_pImpl->m_aFocusedItem.reset();
1197*cdf0e10cSrcweir     }
1198*cdf0e10cSrcweir 
1199*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
1200*cdf0e10cSrcweir     class KeyInputHandler
1201*cdf0e10cSrcweir     {
1202*cdf0e10cSrcweir     public:
1203*cdf0e10cSrcweir         KeyInputHandler( Control& i_rControl, const KeyEvent& i_rKeyEvent )
1204*cdf0e10cSrcweir             :m_rControl( i_rControl )
1205*cdf0e10cSrcweir             ,m_rKeyEvent( i_rKeyEvent )
1206*cdf0e10cSrcweir             ,m_bHandled( false )
1207*cdf0e10cSrcweir         {
1208*cdf0e10cSrcweir         }
1209*cdf0e10cSrcweir 
1210*cdf0e10cSrcweir         ~KeyInputHandler()
1211*cdf0e10cSrcweir         {
1212*cdf0e10cSrcweir             if ( !m_bHandled )
1213*cdf0e10cSrcweir                 m_rControl.Control::KeyInput( m_rKeyEvent );
1214*cdf0e10cSrcweir         }
1215*cdf0e10cSrcweir 
1216*cdf0e10cSrcweir         void   setHandled()
1217*cdf0e10cSrcweir         {
1218*cdf0e10cSrcweir             m_bHandled = true;
1219*cdf0e10cSrcweir         }
1220*cdf0e10cSrcweir 
1221*cdf0e10cSrcweir     private:
1222*cdf0e10cSrcweir         Control&        m_rControl;
1223*cdf0e10cSrcweir         const KeyEvent& m_rKeyEvent;
1224*cdf0e10cSrcweir         bool            m_bHandled;
1225*cdf0e10cSrcweir     };
1226*cdf0e10cSrcweir 
1227*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
1228*cdf0e10cSrcweir     void PanelTabBar::KeyInput( const KeyEvent& i_rKeyEvent )
1229*cdf0e10cSrcweir     {
1230*cdf0e10cSrcweir         KeyInputHandler aKeyInputHandler( *this, i_rKeyEvent );
1231*cdf0e10cSrcweir 
1232*cdf0e10cSrcweir         const KeyCode& rKeyCode( i_rKeyEvent.GetKeyCode() );
1233*cdf0e10cSrcweir         if ( rKeyCode.GetModifier() != 0 )
1234*cdf0e10cSrcweir             // only interested in mere key presses
1235*cdf0e10cSrcweir             return;
1236*cdf0e10cSrcweir 
1237*cdf0e10cSrcweir         // if there are less than 2 panels, we cannot travel them ...
1238*cdf0e10cSrcweir         const size_t nPanelCount( m_pImpl->m_rPanelDeck.GetPanelCount() );
1239*cdf0e10cSrcweir         if ( nPanelCount < 2 )
1240*cdf0e10cSrcweir             return;
1241*cdf0e10cSrcweir 
1242*cdf0e10cSrcweir         OSL_PRECOND( !!m_pImpl->m_aFocusedItem, "PanelTabBar::KeyInput: we should have a focused item here!" );
1243*cdf0e10cSrcweir             // if we get KeyInput events, we should have the focus. In this case, m_aFocusedItem should not be empty,
1244*cdf0e10cSrcweir             // except if there are no panels, but then we bail out of this method here earlier ...
1245*cdf0e10cSrcweir 
1246*cdf0e10cSrcweir         bool bFocusNext = false;
1247*cdf0e10cSrcweir         bool bFocusPrev = false;
1248*cdf0e10cSrcweir 
1249*cdf0e10cSrcweir         switch ( rKeyCode.GetCode() )
1250*cdf0e10cSrcweir         {
1251*cdf0e10cSrcweir         case KEY_UP:    bFocusPrev = true; break;
1252*cdf0e10cSrcweir         case KEY_DOWN:  bFocusNext = true; break;
1253*cdf0e10cSrcweir         case KEY_LEFT:
1254*cdf0e10cSrcweir             if ( IsRTLEnabled() )
1255*cdf0e10cSrcweir                 bFocusNext = true;
1256*cdf0e10cSrcweir             else
1257*cdf0e10cSrcweir                 bFocusPrev = true;
1258*cdf0e10cSrcweir             break;
1259*cdf0e10cSrcweir         case KEY_RIGHT:
1260*cdf0e10cSrcweir             if ( IsRTLEnabled() )
1261*cdf0e10cSrcweir                 bFocusPrev = true;
1262*cdf0e10cSrcweir             else
1263*cdf0e10cSrcweir                 bFocusNext = true;
1264*cdf0e10cSrcweir             break;
1265*cdf0e10cSrcweir         case KEY_RETURN:
1266*cdf0e10cSrcweir             m_pImpl->m_rPanelDeck.ActivatePanel( *m_pImpl->m_aFocusedItem );
1267*cdf0e10cSrcweir             break;
1268*cdf0e10cSrcweir         }
1269*cdf0e10cSrcweir 
1270*cdf0e10cSrcweir         if ( !bFocusNext && !bFocusPrev )
1271*cdf0e10cSrcweir             return;
1272*cdf0e10cSrcweir 
1273*cdf0e10cSrcweir         m_pImpl->InvalidateItem( *m_pImpl->m_aFocusedItem );
1274*cdf0e10cSrcweir         if ( bFocusNext )
1275*cdf0e10cSrcweir         {
1276*cdf0e10cSrcweir             m_pImpl->m_aFocusedItem.reset( ( *m_pImpl->m_aFocusedItem + 1 ) % nPanelCount );
1277*cdf0e10cSrcweir         }
1278*cdf0e10cSrcweir         else
1279*cdf0e10cSrcweir         {
1280*cdf0e10cSrcweir             m_pImpl->m_aFocusedItem.reset( ( *m_pImpl->m_aFocusedItem + nPanelCount - 1 ) % nPanelCount );
1281*cdf0e10cSrcweir         }
1282*cdf0e10cSrcweir         m_pImpl->InvalidateItem( *m_pImpl->m_aFocusedItem );
1283*cdf0e10cSrcweir 
1284*cdf0e10cSrcweir         // don't delegate to base class
1285*cdf0e10cSrcweir         aKeyInputHandler.setHandled();
1286*cdf0e10cSrcweir     }
1287*cdf0e10cSrcweir 
1288*cdf0e10cSrcweir 	//------------------------------------------------------------------------------------------------------------------
1289*cdf0e10cSrcweir     void PanelTabBar::DataChanged( const DataChangedEvent& i_rDataChanedEvent )
1290*cdf0e10cSrcweir     {
1291*cdf0e10cSrcweir         Control::DataChanged( i_rDataChanedEvent );
1292*cdf0e10cSrcweir 
1293*cdf0e10cSrcweir         if  (   ( i_rDataChanedEvent.GetType() == DATACHANGED_SETTINGS )
1294*cdf0e10cSrcweir             &&  ( ( i_rDataChanedEvent.GetFlags() & SETTINGS_STYLE ) != 0 )
1295*cdf0e10cSrcweir             )
1296*cdf0e10cSrcweir         {
1297*cdf0e10cSrcweir             Invalidate();
1298*cdf0e10cSrcweir         }
1299*cdf0e10cSrcweir     }
1300*cdf0e10cSrcweir 
1301*cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
1302*cdf0e10cSrcweir     bool PanelTabBar::IsVertical() const
1303*cdf0e10cSrcweir     {
1304*cdf0e10cSrcweir         return m_pImpl->IsVertical();
1305*cdf0e10cSrcweir     }
1306*cdf0e10cSrcweir 
1307*cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
1308*cdf0e10cSrcweir     PushButton& PanelTabBar::GetScrollButton( const bool i_bForward )
1309*cdf0e10cSrcweir     {
1310*cdf0e10cSrcweir         return i_bForward ? m_pImpl->m_aScrollForward : m_pImpl->m_aScrollBack;
1311*cdf0e10cSrcweir     }
1312*cdf0e10cSrcweir 
1313*cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
1314*cdf0e10cSrcweir     ::boost::optional< size_t > PanelTabBar::GetFocusedPanelItem() const
1315*cdf0e10cSrcweir     {
1316*cdf0e10cSrcweir         return m_pImpl->m_aFocusedItem;
1317*cdf0e10cSrcweir     }
1318*cdf0e10cSrcweir 
1319*cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
1320*cdf0e10cSrcweir     void PanelTabBar::FocusPanelItem( const size_t i_nItemPos )
1321*cdf0e10cSrcweir     {
1322*cdf0e10cSrcweir         ENSURE_OR_RETURN_VOID( i_nItemPos < m_pImpl->m_rPanelDeck.GetPanelCount(), "PanelTabBar::FocusPanelItem: illegal item pos!" );
1323*cdf0e10cSrcweir 
1324*cdf0e10cSrcweir         if ( !HasChildPathFocus() )
1325*cdf0e10cSrcweir             GrabFocus();
1326*cdf0e10cSrcweir 
1327*cdf0e10cSrcweir         m_pImpl->FocusItem( i_nItemPos );
1328*cdf0e10cSrcweir         OSL_POSTCOND( !!m_pImpl->m_aFocusedItem, "PanelTabBar::FocusPanelItem: have the focus, but no focused item?" );
1329*cdf0e10cSrcweir         if ( !!m_pImpl->m_aFocusedItem )
1330*cdf0e10cSrcweir             m_pImpl->InvalidateItem( *m_pImpl->m_aFocusedItem );
1331*cdf0e10cSrcweir         m_pImpl->m_aFocusedItem.reset( i_nItemPos );
1332*cdf0e10cSrcweir     }
1333*cdf0e10cSrcweir 
1334*cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
1335*cdf0e10cSrcweir     Rectangle PanelTabBar::GetItemScreenRect( const size_t i_nItemPos ) const
1336*cdf0e10cSrcweir     {
1337*cdf0e10cSrcweir         return m_pImpl->GetItemScreenRect( i_nItemPos );
1338*cdf0e10cSrcweir     }
1339*cdf0e10cSrcweir 
1340*cdf0e10cSrcweir     //------------------------------------------------------------------------------------------------------------------
1341*cdf0e10cSrcweir     Reference< XWindowPeer > PanelTabBar::GetComponentInterface( sal_Bool i_bCreate )
1342*cdf0e10cSrcweir     {
1343*cdf0e10cSrcweir         Reference< XWindowPeer > xWindowPeer( Control::GetComponentInterface( sal_False ) );
1344*cdf0e10cSrcweir         if ( !xWindowPeer.is() && i_bCreate )
1345*cdf0e10cSrcweir         {
1346*cdf0e10cSrcweir             xWindowPeer.set( new PanelTabBarPeer( *this ) );
1347*cdf0e10cSrcweir             SetComponentInterface( xWindowPeer );
1348*cdf0e10cSrcweir         }
1349*cdf0e10cSrcweir         return xWindowPeer;
1350*cdf0e10cSrcweir     }
1351*cdf0e10cSrcweir 
1352*cdf0e10cSrcweir //........................................................................
1353*cdf0e10cSrcweir } // namespace svt
1354*cdf0e10cSrcweir //........................................................................
1355