1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "svtools/toolpanel/paneltabbar.hxx"
22 #include "svtools/toolpanel/toolpaneldeck.hxx"
23 #include "svtools/svtresid.hxx"
24 #include "svtools/svtools.hrc"
26 #include "tabitemdescriptor.hxx"
27 #include "paneltabbarpeer.hxx"
28 #include "tabbargeometry.hxx"
30 #include <vcl/button.hxx>
31 #include <vcl/help.hxx>
32 #include <vcl/virdev.hxx>
33 #include <tools/diagnose_ex.h>
35 #include <boost/optional.hpp>
38 // space around an item
39 #define ITEM_OUTER_SPACE 2 * 3
40 // spacing before and after an item's text
41 #define ITEM_TEXT_FLOW_SPACE 5
42 // space between item icon and icon text
43 #define ITEM_ICON_TEXT_DISTANCE 4
45 //........................................................................
48 //........................................................................
50 using ::com::sun::star::uno::Reference
;
51 using ::com::sun::star::awt::XWindowPeer
;
53 typedef sal_uInt16 ItemFlags
;
55 #define ITEM_STATE_NORMAL 0x00
56 #define ITEM_STATE_ACTIVE 0x01
57 #define ITEM_STATE_HOVERED 0x02
58 #define ITEM_STATE_FOCUSED 0x04
59 #define ITEM_POSITION_FIRST 0x08
60 #define ITEM_POSITION_LAST 0x10
62 //==================================================================================================================
64 //==================================================================================================================
67 ControlState
lcl_ItemToControlState( const ItemFlags i_nItemFlags
)
69 ControlState nState
= CTRL_STATE_ENABLED
;
70 if ( i_nItemFlags
& ITEM_STATE_FOCUSED
) nState
|= CTRL_STATE_FOCUSED
| CTRL_STATE_PRESSED
;
71 if ( i_nItemFlags
& ITEM_STATE_HOVERED
) nState
|= CTRL_STATE_ROLLOVER
;
72 if ( i_nItemFlags
& ITEM_STATE_ACTIVE
) nState
|= CTRL_STATE_SELECTED
;
77 //==================================================================================================================
79 //==================================================================================================================
80 class SAL_NO_VTABLE ITabBarRenderer
83 /** fills the background of our target device
85 virtual void renderBackground() const = 0;
86 virtual Rectangle
calculateDecorations( const Rectangle
& i_rContentArea
, const ItemFlags i_nItemFlags
) const = 0;
87 virtual void preRenderItem( const Rectangle
& i_rContentRect
, const ItemFlags i_nItemFlags
) const = 0;
88 virtual void postRenderItem( Window
& i_rActualWindow
, const Rectangle
& i_rItemRect
, const ItemFlags i_nItemFlags
) const = 0;
90 // TODO: postRenderItem takes the "real" window, i.e. effectively the tab bar. This is because
91 // DrawSelectionBackground needs to be applied after everything else is painted, and is available at the Window
92 // class, but not at the OutputDevice. This makes the API somewhat weird, as we're now mixing operations on the
93 // target device, done in a normalized geometry, with operations on the window, done in a transformed geometry.
94 // So, we should get rid of postRenderItem completely.
99 typedef ::boost::shared_ptr
< ITabBarRenderer
> PTabBarRenderer
;
101 //==================================================================================================================
102 //= VCLItemRenderer - declaration
103 //==================================================================================================================
104 class VCLItemRenderer
: public ITabBarRenderer
107 VCLItemRenderer( OutputDevice
& i_rTargetDevice
)
108 :m_rTargetDevice( i_rTargetDevice
)
111 virtual ~VCLItemRenderer() {}
114 virtual void renderBackground() const;
115 virtual Rectangle
calculateDecorations( const Rectangle
& i_rContentArea
, const ItemFlags i_nItemFlags
) const;
116 virtual void preRenderItem( const Rectangle
& i_rContentRect
, const ItemFlags i_nItemFlags
) const;
117 virtual void postRenderItem( Window
& i_rActualWindow
, const Rectangle
& i_rItemRect
, const ItemFlags i_nItemFlags
) const;
120 OutputDevice
& getTargetDevice() const { return m_rTargetDevice
; }
123 OutputDevice
& m_rTargetDevice
;
126 //==================================================================================================================
127 //= VCLItemRenderer - implementation
128 //==================================================================================================================
129 //------------------------------------------------------------------------------------------------------------------
130 void VCLItemRenderer::renderBackground() const
132 getTargetDevice().DrawRect( Rectangle( Point(), getTargetDevice().GetOutputSizePixel() ) );
135 //------------------------------------------------------------------------------------------------------------------
136 Rectangle
VCLItemRenderer::calculateDecorations( const Rectangle
& i_rContentArea
, const ItemFlags i_nItemFlags
) const
139 // no decorations at all
140 return i_rContentArea
;
143 //------------------------------------------------------------------------------------------------------------------
144 void VCLItemRenderer::preRenderItem( const Rectangle
& i_rContentRect
, const ItemFlags i_nItemFlags
) const
146 (void)i_rContentRect
;
150 //------------------------------------------------------------------------------------------------------------------
151 void VCLItemRenderer::postRenderItem( Window
& i_rActualWindow
, const Rectangle
& i_rItemRect
, const ItemFlags i_nItemFlags
) const
153 const bool bActive
= ( ( i_nItemFlags
& ITEM_STATE_ACTIVE
) != 0 );
154 const bool bHovered
= ( ( i_nItemFlags
& ITEM_STATE_HOVERED
) != 0 );
155 const bool bFocused
= ( ( i_nItemFlags
& ITEM_STATE_FOCUSED
) != 0 );
156 if ( bActive
|| bHovered
|| bFocused
)
158 Rectangle
aSelectionRect( i_rItemRect
);
159 aSelectionRect
.Left() += ITEM_OUTER_SPACE
/ 2;
160 aSelectionRect
.Top() += ITEM_OUTER_SPACE
/ 2;
161 aSelectionRect
.Right() -= ITEM_OUTER_SPACE
/ 2;
162 aSelectionRect
.Bottom() -= ITEM_OUTER_SPACE
/ 2;
163 i_rActualWindow
.DrawSelectionBackground(
165 ( bHovered
|| bFocused
) ? ( bActive
? 1 : 2 ) : 0 /* hilight */,
167 sal_True
/* border */,
168 sal_False
/* ext border only */,
169 0 /* corner radius */,
176 //==================================================================================================================
177 //= NWFToolboxItemRenderer - declaration
178 //==================================================================================================================
179 class NWFToolboxItemRenderer
: public ITabBarRenderer
182 NWFToolboxItemRenderer( OutputDevice
& i_rTargetDevice
)
183 :m_rTargetDevice( i_rTargetDevice
)
186 virtual ~NWFToolboxItemRenderer() {}
189 virtual void renderBackground() const;
190 virtual Rectangle
calculateDecorations( const Rectangle
& i_rContentArea
, const ItemFlags i_nItemFlags
) const;
191 virtual void preRenderItem( const Rectangle
& i_rContentRect
, const ItemFlags i_nItemFlags
) const;
192 virtual void postRenderItem( Window
& i_rActualWindow
, const Rectangle
& i_rItemRect
, const ItemFlags i_nItemFlags
) const;
195 OutputDevice
& getTargetDevice() const { return m_rTargetDevice
; }
198 OutputDevice
& m_rTargetDevice
;
201 //==================================================================================================================
202 //= NWFToolboxItemRenderer - implementation
203 //==================================================================================================================
204 //------------------------------------------------------------------------------------------------------------------
205 void NWFToolboxItemRenderer::renderBackground() const
207 getTargetDevice().DrawRect( Rectangle( Point(), getTargetDevice().GetOutputSizePixel() ) );
210 //------------------------------------------------------------------------------------------------------------------
211 Rectangle
NWFToolboxItemRenderer::calculateDecorations( const Rectangle
& i_rContentArea
, const ItemFlags i_nItemFlags
) const
213 // don't ask GetNativeControlRegion, this will not deliver proper results in all cases.
214 // Instead, simply assume that both the content and the bounding region are the same.
215 // const ControlState nState( lcl_ItemToControlState( i_nItemFlags );
216 // const ImplControlValue aControlValue;
217 // bool bNativeOK = m_rTargetWindow.GetNativeControlRegion(
218 // CTRL_TOOLBAR, PART_BUTTON,
219 // i_rContentArea, nState,
220 // aControlValue, OUString(),
221 // aBoundingRegion, aContentRegion
225 Point( i_rContentArea
.Left() - 1, i_rContentArea
.Top() - 1 ),
226 Size( i_rContentArea
.GetWidth() + 2, i_rContentArea
.GetHeight() + 2 )
230 //------------------------------------------------------------------------------------------------------------------
231 void NWFToolboxItemRenderer::preRenderItem( const Rectangle
& i_rContentRect
, const ItemFlags i_nItemFlags
) const
233 const ControlState nState
= lcl_ItemToControlState( i_nItemFlags
);
235 ImplControlValue aControlValue
;
236 aControlValue
.setTristateVal( ( i_nItemFlags
& ITEM_STATE_ACTIVE
) ? BUTTONVALUE_ON
: BUTTONVALUE_OFF
);
238 bool bNativeOK
= getTargetDevice().DrawNativeControl( CTRL_TOOLBAR
, PART_BUTTON
, i_rContentRect
, nState
, aControlValue
, OUString() );
240 OSL_ENSURE( bNativeOK
, "NWFToolboxItemRenderer::preRenderItem: inconsistent NWF implementation!" );
241 // IsNativeControlSupported returned true, previously, otherwise we would not be here ...
244 //------------------------------------------------------------------------------------------------------------------
245 void NWFToolboxItemRenderer::postRenderItem( Window
& i_rActualWindow
, const Rectangle
& i_rItemRect
, const ItemFlags i_nItemFlags
) const
247 (void)i_rActualWindow
;
252 //==================================================================================================================
253 //= NWFTabItemRenderer - declaration
254 //==================================================================================================================
255 class NWFTabItemRenderer
: public ITabBarRenderer
258 NWFTabItemRenderer( OutputDevice
& i_rTargetDevice
)
259 :m_rTargetDevice( i_rTargetDevice
)
263 virtual ~NWFTabItemRenderer() {}
266 virtual void renderBackground() const;
267 virtual Rectangle
calculateDecorations( const Rectangle
& i_rContentArea
, const ItemFlags i_nItemFlags
) const;
268 virtual void preRenderItem( const Rectangle
& i_rContentRect
, const ItemFlags i_nItemFlags
) const;
269 virtual void postRenderItem( Window
& i_rActualWindow
, const Rectangle
& i_rItemRect
, const ItemFlags i_nItemFlags
) const;
272 OutputDevice
& getTargetDevice() const { return m_rTargetDevice
; }
275 OutputDevice
& m_rTargetDevice
;
278 //==================================================================================================================
279 //= NWFTabItemRenderer - implementation
280 //==================================================================================================================
281 //------------------------------------------------------------------------------------------------------------------
282 void NWFTabItemRenderer::renderBackground() const
284 Rectangle
aBackground( Point(), getTargetDevice().GetOutputSizePixel() );
285 getTargetDevice().DrawRect( aBackground
);
287 aBackground
.Top() = aBackground
.Bottom();
288 getTargetDevice().DrawNativeControl( CTRL_TAB_PANE
, PART_ENTIRE_CONTROL
, aBackground
,
289 CTRL_STATE_ENABLED
, ImplControlValue(), OUString() );
292 //------------------------------------------------------------------------------------------------------------------
293 Rectangle
NWFTabItemRenderer::calculateDecorations( const Rectangle
& i_rContentArea
, const ItemFlags i_nItemFlags
) const
295 const ControlState
nState( lcl_ItemToControlState( i_nItemFlags
) );
297 TabitemValue tiValue
;
299 Rectangle aBoundingRegion
, aContentRegion
;
300 bool bNativeOK
= getTargetDevice().GetNativeControlRegion(
301 CTRL_TAB_ITEM
, PART_ENTIRE_CONTROL
,
302 i_rContentArea
, nState
,
304 aBoundingRegion
, aContentRegion
307 OSL_ENSURE( bNativeOK
, "NWFTabItemRenderer::calculateDecorations: GetNativeControlRegion not implemented for CTRL_TAB_ITEM?!" );
309 return aBoundingRegion
;
312 //------------------------------------------------------------------------------------------------------------------
313 void NWFTabItemRenderer::preRenderItem( const Rectangle
& i_rContentRect
, const ItemFlags i_nItemFlags
) const
315 const ControlState nState
= lcl_ItemToControlState( i_nItemFlags
);
317 TabitemValue tiValue
;
318 if ( i_nItemFlags
& ITEM_POSITION_FIRST
)
319 tiValue
.mnAlignment
|= TABITEM_FIRST_IN_GROUP
;
320 if ( i_nItemFlags
& ITEM_POSITION_LAST
)
321 tiValue
.mnAlignment
|= TABITEM_LAST_IN_GROUP
;
324 bool bNativeOK
= getTargetDevice().DrawNativeControl( CTRL_TAB_ITEM
, PART_ENTIRE_CONTROL
, i_rContentRect
, nState
, tiValue
, OUString() );
326 OSL_ENSURE( bNativeOK
, "NWFTabItemRenderer::preRenderItem: inconsistent NWF implementation!" );
327 // IsNativeControlSupported returned true, previously, otherwise we would not be here ...
330 //------------------------------------------------------------------------------------------------------------------
331 void NWFTabItemRenderer::postRenderItem( Window
& i_rActualWindow
, const Rectangle
& i_rItemRect
, const ItemFlags i_nItemFlags
) const
333 (void)i_rActualWindow
;
338 //==================================================================================================================
340 //==================================================================================================================
341 class PanelTabBar_Impl
: public IToolPanelDeckListener
344 PanelTabBar_Impl( PanelTabBar
& i_rTabBar
, IToolPanelDeck
& i_rPanelDeck
, const TabAlignment i_eAlignment
, const TabItemContent i_eItemContent
);
346 virtual ~PanelTabBar_Impl()
348 m_rPanelDeck
.RemoveListener( *this );
351 // IToolPanelDeckListener
352 virtual void PanelInserted( const PToolPanel
& i_pPanel
, const size_t i_nPosition
)
356 m_bItemsDirty
= true;
357 m_rTabBar
.Invalidate();
362 virtual void PanelRemoved( const size_t i_nPosition
)
364 m_bItemsDirty
= true;
365 m_rTabBar
.Invalidate();
367 if ( i_nPosition
< m_nScrollPosition
)
373 virtual void ActivePanelChanged( const ::boost::optional
< size_t >& i_rOldActive
, const ::boost::optional
< size_t >& i_rNewActive
);
374 virtual void LayouterChanged( const PDeckLayouter
& i_rNewLayouter
);
375 virtual void Dying();
377 void UpdateScrollButtons()
379 m_aScrollBack
.Enable( m_nScrollPosition
> 0 );
380 m_aScrollForward
.Enable( m_nScrollPosition
< m_aItems
.size() - 1 );
384 void EnsureItemsCache();
385 ::boost::optional
< size_t > FindItemForPoint( const Point
& i_rPoint
) const;
386 void DrawItem( const size_t i_nItemIndex
, const Rectangle
& i_rBoundaries
) const;
387 void InvalidateItem( const size_t i_nItemIndex
, const ItemFlags i_nAdditionalItemFlags
= 0 ) const;
388 void CopyFromRenderDevice( const Rectangle
& i_rLogicalRect
) const;
389 Rectangle
GetActualLogicalItemRect( const Rectangle
& i_rLogicalItemRect
) const;
390 Rectangle
GetItemScreenRect( const size_t i_nItemPos
) const;
392 void FocusItem( const ::boost::optional
< size_t >& i_rItemPos
);
394 inline bool IsVertical() const
396 return ( ( m_eTabAlignment
== TABS_LEFT
)
397 || ( m_eTabAlignment
== TABS_RIGHT
)
402 DECL_LINK( OnScroll
, const PushButton
* );
404 void impl_calcItemRects();
405 Size
impl_calculateItemContentSize( const PToolPanel
& i_pPanel
, const TabItemContent i_eItemContent
) const;
406 void impl_renderItemContent( const PToolPanel
& i_pPanel
, const Rectangle
& i_rContentArea
, const TabItemContent i_eItemContent
) const;
407 ItemFlags
impl_getItemFlags( const size_t i_nItemIndex
) const;
410 PanelTabBar
& m_rTabBar
;
411 TabBarGeometry m_aGeometry
;
412 NormalizedArea m_aNormalizer
;
413 TabAlignment m_eTabAlignment
;
414 IToolPanelDeck
& m_rPanelDeck
;
416 VirtualDevice m_aRenderDevice
;
417 PTabBarRenderer m_pRenderer
;
419 ::boost::optional
< size_t > m_aHoveredItem
;
420 ::boost::optional
< size_t > m_aFocusedItem
;
421 bool m_bMouseButtonDown
;
423 ItemDescriptors m_aItems
;
426 PushButton m_aScrollBack
;
427 PushButton m_aScrollForward
;
429 size_t m_nScrollPosition
;
432 //==================================================================================================================
434 //==================================================================================================================
437 //--------------------------------------------------------------------------------------------------------------
438 #if OSL_DEBUG_LEVEL > 0
439 static void lcl_checkConsistency( const PanelTabBar_Impl
& i_rImpl
)
441 if ( !i_rImpl
.m_bItemsDirty
)
443 if ( i_rImpl
.m_rPanelDeck
.GetPanelCount() != i_rImpl
.m_aItems
.size() )
445 OSL_FAIL( "lcl_checkConsistency: inconsistent array sizes!" );
448 for ( size_t i
= 0; i
< i_rImpl
.m_rPanelDeck
.GetPanelCount(); ++i
)
450 if ( i_rImpl
.m_rPanelDeck
.GetPanel( i
).get() != i_rImpl
.m_aItems
[i
].pPanel
.get() )
452 OSL_FAIL( "lcl_checkConsistency: array elements are inconsistent!" );
459 #define DBG_CHECK( data ) \
460 lcl_checkConsistency( data );
462 #define DBG_CHECK( data ) \
466 //--------------------------------------------------------------------------------------------------------------
470 ClipItemRegion( const PanelTabBar_Impl
& i_rImpl
)
471 :m_rDevice( i_rImpl
.m_rTabBar
)
473 m_rDevice
.Push( PUSH_CLIPREGION
);
474 m_rDevice
.SetClipRegion(Region(
475 i_rImpl
.m_aNormalizer
.getTransformed(
476 i_rImpl
.m_aGeometry
.getItemsRect(),
477 i_rImpl
.m_eTabAlignment
)));
486 OutputDevice
& m_rDevice
;
490 //==================================================================================================================
491 //= PanelTabBar_Impl - implementation
492 //==================================================================================================================
493 //------------------------------------------------------------------------------------------------------------------
494 PanelTabBar_Impl::PanelTabBar_Impl( PanelTabBar
& i_rTabBar
, IToolPanelDeck
& i_rPanelDeck
, const TabAlignment i_eAlignment
, const TabItemContent i_eItemContent
)
495 :m_rTabBar( i_rTabBar
)
496 ,m_aGeometry( i_eItemContent
)
498 ,m_eTabAlignment( i_eAlignment
)
499 ,m_rPanelDeck( i_rPanelDeck
)
500 ,m_aRenderDevice( i_rTabBar
)
504 ,m_bMouseButtonDown( false )
506 ,m_bItemsDirty( true )
507 ,m_aScrollBack( &i_rTabBar
, WB_BEVELBUTTON
)
508 ,m_aScrollForward( &i_rTabBar
, WB_BEVELBUTTON
)
509 ,m_nScrollPosition( 0 )
512 if ( m_aRenderDevice
.IsNativeControlSupported( CTRL_TAB_ITEM
, PART_ENTIRE_CONTROL
) )
513 // this mode requires the NWF framework to be able to render those items onto a virtual
514 // device. For some frameworks (some GTK themes, in particular), this is known to fail.
515 // So, be on the safe side for the moment.
516 m_pRenderer
.reset( new NWFTabItemRenderer( m_aRenderDevice
) );
519 if ( m_aRenderDevice
.IsNativeControlSupported( CTRL_TOOLBAR
, PART_BUTTON
) )
520 m_pRenderer
.reset( new NWFToolboxItemRenderer( m_aRenderDevice
) );
522 m_pRenderer
.reset( new VCLItemRenderer( m_aRenderDevice
) );
524 m_aRenderDevice
.SetLineColor();
526 m_rPanelDeck
.AddListener( *this );
528 m_aScrollBack
.SetSymbol( IsVertical() ? SYMBOL_ARROW_UP
: SYMBOL_ARROW_LEFT
);
529 m_aScrollBack
.Show();
530 m_aScrollBack
.SetClickHdl( LINK( this, PanelTabBar_Impl
, OnScroll
) );
531 m_aScrollBack
.SetAccessibleDescription( SvtResId( STR_SVT_TOOL_PANEL_BUTTON_FWD
).toString() );
532 m_aScrollBack
.SetAccessibleName( m_aScrollBack
.GetAccessibleDescription() );
534 m_aScrollForward
.SetSymbol( IsVertical() ? SYMBOL_ARROW_DOWN
: SYMBOL_ARROW_RIGHT
);
535 m_aScrollForward
.Show();
536 m_aScrollForward
.SetClickHdl( LINK( this, PanelTabBar_Impl
, OnScroll
) );
537 m_aScrollForward
.SetAccessibleDescription( SvtResId( STR_SVT_TOOL_PANEL_BUTTON_BACK
).toString() );
538 m_aScrollForward
.SetAccessibleName( m_aScrollForward
.GetAccessibleDescription() );
541 //------------------------------------------------------------------------------------------------------------------
542 void PanelTabBar_Impl::impl_calcItemRects()
546 Point
aCompletePos( m_aGeometry
.getFirstItemPosition() );
547 Point
aIconOnlyPos( aCompletePos
);
548 Point
aTextOnlyPos( aCompletePos
);
551 i
< m_rPanelDeck
.GetPanelCount();
555 PToolPanel
pPanel( m_rPanelDeck
.GetPanel( i
) );
557 ItemDescriptor aItem
;
558 aItem
.pPanel
= pPanel
;
560 const Size
aCompleteSize( impl_calculateItemContentSize( pPanel
, TABITEM_IMAGE_AND_TEXT
) );
561 const Size
aIconOnlySize( impl_calculateItemContentSize( pPanel
, TABITEM_IMAGE_ONLY
) );
562 const Size
aTextOnlySize( impl_calculateItemContentSize( pPanel
, TABITEM_TEXT_ONLY
) );
564 // TODO: have one method calculating all sizes?
566 // remember the three areas
567 aItem
.aCompleteArea
= Rectangle( aCompletePos
, aCompleteSize
);
568 aItem
.aIconOnlyArea
= Rectangle( aIconOnlyPos
, aIconOnlySize
);
569 aItem
.aTextOnlyArea
= Rectangle( aTextOnlyPos
, aTextOnlySize
);
571 m_aItems
.push_back( aItem
);
573 aCompletePos
= aItem
.aCompleteArea
.TopRight();
574 aIconOnlyPos
= aItem
.aIconOnlyArea
.TopRight();
575 aTextOnlyPos
= aItem
.aTextOnlyArea
.TopRight();
578 m_bItemsDirty
= false;
581 //------------------------------------------------------------------------------------------------------------------
582 Size
PanelTabBar_Impl::impl_calculateItemContentSize( const PToolPanel
& i_pPanel
, const TabItemContent i_eItemContent
) const
584 // calculate the size needed for the content
585 OSL_ENSURE( i_eItemContent
!= TABITEM_AUTO
, "PanelTabBar_Impl::impl_calculateItemContentSize: illegal TabItemContent value!" );
587 const Image
aImage( i_pPanel
->GetImage() );
588 const bool bUseImage
= !!aImage
&& ( i_eItemContent
!= TABITEM_TEXT_ONLY
);
590 const OUString
sItemText( i_pPanel
->GetDisplayName() );
591 const bool bUseText
= ( !sItemText
.isEmpty() ) && ( i_eItemContent
!= TABITEM_IMAGE_ONLY
);
593 Size aItemContentSize
;
596 aItemContentSize
= aImage
.GetSizePixel();
602 aItemContentSize
.Width() += ITEM_ICON_TEXT_DISTANCE
;
604 // add space for text
605 const Size
aTextSize( m_rTabBar
.GetCtrlTextWidth( sItemText
), m_rTabBar
.GetTextHeight() );
606 aItemContentSize
.Width() += aTextSize
.Width();
607 aItemContentSize
.Height() = ::std::max( aItemContentSize
.Height(), aTextSize
.Height() );
609 aItemContentSize
.Width() += 2 * ITEM_TEXT_FLOW_SPACE
;
612 if ( !bUseImage
&& !bUseText
)
614 // have a minimal size - this is pure heuristics, but if it doesn't suit your needs, then give your panels
615 // a name and or image! :)
616 aItemContentSize
= Size( 16, 16 );
619 aItemContentSize
.Width() += 2 * ITEM_OUTER_SPACE
;
620 aItemContentSize
.Height() += 2 * ITEM_OUTER_SPACE
;
622 return aItemContentSize
;
625 //------------------------------------------------------------------------------------------------------------------
626 void PanelTabBar_Impl::impl_renderItemContent( const PToolPanel
& i_pPanel
, const Rectangle
& i_rContentArea
, const TabItemContent i_eItemContent
) const
628 OSL_ENSURE( i_eItemContent
!= TABITEM_AUTO
, "PanelTabBar_Impl::impl_renderItemContent: illegal TabItemContent value!" );
630 Rectangle
aRenderArea( i_rContentArea
);
633 aRenderArea
.Top() += ITEM_OUTER_SPACE
;
637 aRenderArea
.Left() += ITEM_OUTER_SPACE
;
641 const Image
aItemImage( i_pPanel
->GetImage() );
642 const Size
aImageSize( aItemImage
.GetSizePixel() );
643 const bool bUseImage
= !!aItemImage
&& ( i_eItemContent
!= TABITEM_TEXT_ONLY
);
650 aImagePos
.X() = aRenderArea
.Left() + ( aRenderArea
.GetWidth() - aImageSize
.Width() ) / 2;
651 aImagePos
.Y() = aRenderArea
.Top();
655 aImagePos
.X() = aRenderArea
.Left();
656 aImagePos
.Y() = aRenderArea
.Top() + ( aRenderArea
.GetHeight() - aImageSize
.Height() ) / 2;
658 m_rTabBar
.DrawImage( aImagePos
, aItemImage
);
661 const OUString
sItemText( i_pPanel
->GetDisplayName() );
662 const bool bUseText
= ( !sItemText
.isEmpty() ) && ( i_eItemContent
!= TABITEM_IMAGE_ONLY
);
669 aRenderArea
.Top() += aImageSize
.Height() + ITEM_ICON_TEXT_DISTANCE
;
670 aRenderArea
.Top() += ITEM_TEXT_FLOW_SPACE
;
675 aRenderArea
.Left() += aImageSize
.Width() + ITEM_ICON_TEXT_DISTANCE
;
676 aRenderArea
.Left() += ITEM_TEXT_FLOW_SPACE
;
680 const Size
aTextSize( m_rTabBar
.GetCtrlTextWidth( sItemText
), m_rTabBar
.GetTextHeight() );
681 Point
aTextPos( aRenderArea
.TopLeft() );
684 m_rTabBar
.Push( PUSH_FONT
);
686 Font
aFont( m_rTabBar
.GetFont() );
687 aFont
.SetOrientation( 2700 );
688 aFont
.SetVertical( sal_True
);
689 m_rTabBar
.SetFont( aFont
);
691 aTextPos
.X() += aTextSize
.Height();
692 aTextPos
.X() += ( aRenderArea
.GetWidth() - aTextSize
.Height() ) / 2;
696 aTextPos
.Y() += ( aRenderArea
.GetHeight() - aTextSize
.Height() ) / 2;
699 m_rTabBar
.DrawText( aTextPos
, sItemText
);
708 //------------------------------------------------------------------------------------------------------------------
709 void PanelTabBar_Impl::CopyFromRenderDevice( const Rectangle
& i_rLogicalRect
) const
711 BitmapEx
aBitmap( m_aRenderDevice
.GetBitmapEx(
712 i_rLogicalRect
.TopLeft(),
714 i_rLogicalRect
.GetSize().Width(),
715 i_rLogicalRect
.GetSize().Height()
720 aBitmap
.Rotate( 2700, COL_BLACK
);
721 if ( m_eTabAlignment
== TABS_LEFT
)
722 aBitmap
.Mirror( BMP_MIRROR_HORZ
);
724 else if ( m_eTabAlignment
== TABS_BOTTOM
)
726 aBitmap
.Mirror( BMP_MIRROR_VERT
);
729 const Rectangle
aActualRect( m_aNormalizer
.getTransformed( i_rLogicalRect
, m_eTabAlignment
) );
730 m_rTabBar
.DrawBitmapEx( aActualRect
.TopLeft(), aBitmap
);
733 //------------------------------------------------------------------------------------------------------------------
734 void PanelTabBar_Impl::InvalidateItem( const size_t i_nItemIndex
, const ItemFlags i_nAdditionalItemFlags
) const
736 const ItemDescriptor
& rItem( m_aItems
[ i_nItemIndex
] );
737 const ItemFlags
nItemFlags( impl_getItemFlags( i_nItemIndex
) | i_nAdditionalItemFlags
);
739 const Rectangle
aNormalizedContent( GetActualLogicalItemRect( rItem
.GetCurrentRect() ) );
740 const Rectangle
aNormalizedBounds( m_pRenderer
->calculateDecorations( aNormalizedContent
, nItemFlags
) );
742 const Rectangle aActualBounds
= m_aNormalizer
.getTransformed( aNormalizedBounds
, m_eTabAlignment
);
743 m_rTabBar
.Invalidate( aActualBounds
);
746 //------------------------------------------------------------------------------------------------------------------
747 ItemFlags
PanelTabBar_Impl::impl_getItemFlags( const size_t i_nItemIndex
) const
749 ItemFlags
nItemFlags( ITEM_STATE_NORMAL
);
750 if ( m_aHoveredItem
== i_nItemIndex
)
752 nItemFlags
|= ITEM_STATE_HOVERED
;
753 if ( m_bMouseButtonDown
)
754 nItemFlags
|= ITEM_STATE_ACTIVE
;
757 if ( m_rPanelDeck
.GetActivePanel() == i_nItemIndex
)
758 nItemFlags
|= ITEM_STATE_ACTIVE
;
760 if ( m_aFocusedItem
== i_nItemIndex
)
761 nItemFlags
|= ITEM_STATE_FOCUSED
;
763 if ( 0 == i_nItemIndex
)
764 nItemFlags
|= ITEM_POSITION_FIRST
;
766 if ( m_rPanelDeck
.GetPanelCount() - 1 == i_nItemIndex
)
767 nItemFlags
|= ITEM_POSITION_LAST
;
772 //------------------------------------------------------------------------------------------------------------------
773 void PanelTabBar_Impl::DrawItem( const size_t i_nItemIndex
, const Rectangle
& i_rBoundaries
) const
775 const ItemDescriptor
& rItem( m_aItems
[ i_nItemIndex
] );
776 const ItemFlags
nItemFlags( impl_getItemFlags( i_nItemIndex
) );
778 // the normalized bounding and content rect
779 const Rectangle
aNormalizedContent( GetActualLogicalItemRect( rItem
.GetCurrentRect() ) );
780 const Rectangle
aNormalizedBounds( m_pRenderer
->calculateDecorations( aNormalizedContent
, nItemFlags
) );
782 // check whether the item actually overlaps with the painting area
783 if ( !i_rBoundaries
.IsEmpty() )
785 const Rectangle
aItemRect( GetActualLogicalItemRect( rItem
.GetCurrentRect() ) );
786 if ( !aItemRect
.IsOver( i_rBoundaries
) )
790 m_rTabBar
.SetUpdateMode( sal_False
);
792 // the aligned bounding and content rect
793 const Rectangle aActualBounds
= m_aNormalizer
.getTransformed( aNormalizedBounds
, m_eTabAlignment
);
794 const Rectangle aActualContent
= m_aNormalizer
.getTransformed( aNormalizedContent
, m_eTabAlignment
);
796 // render item "background" layer
797 m_pRenderer
->preRenderItem( aNormalizedContent
, nItemFlags
);
799 // copy from the virtual device to ourself
800 CopyFromRenderDevice( aNormalizedBounds
);
802 // render the actual item content
803 impl_renderItemContent( rItem
.pPanel
, aActualContent
, rItem
.eContent
);
805 // render item "foreground" layer
806 m_pRenderer
->postRenderItem( m_rTabBar
, aActualBounds
, nItemFlags
);
808 m_rTabBar
.SetUpdateMode( sal_True
);
811 //------------------------------------------------------------------------------------------------------------------
812 void PanelTabBar_Impl::EnsureItemsCache()
814 if ( m_bItemsDirty
== false )
819 impl_calcItemRects();
820 OSL_POSTCOND( m_bItemsDirty
== false, "PanelTabBar_Impl::EnsureItemsCache: cache still dirty!" );
824 //------------------------------------------------------------------------------------------------------------------
825 void PanelTabBar_Impl::Relayout()
829 const Size
aOutputSize( m_rTabBar
.GetOutputSizePixel() );
830 m_aNormalizer
= NormalizedArea( Rectangle( Point(), aOutputSize
), IsVertical() );
831 const Size
aLogicalOutputSize( m_aNormalizer
.getReferenceSize() );
833 // forward actual output size to our render device
834 m_aRenderDevice
.SetOutputSizePixel( aLogicalOutputSize
);
836 // re-calculate the size of the scroll buttons and of the items
837 m_aGeometry
.relayout( aLogicalOutputSize
, m_aItems
);
839 if ( m_aGeometry
.getButtonBackRect().IsEmpty() )
841 m_aScrollBack
.Hide();
845 const Rectangle
aButtonBack( m_aNormalizer
.getTransformed( m_aGeometry
.getButtonBackRect(), m_eTabAlignment
) );
846 m_aScrollBack
.SetPosSizePixel( aButtonBack
.TopLeft(), aButtonBack
.GetSize() );
847 m_aScrollBack
.Show();
850 if ( m_aGeometry
.getButtonForwardRect().IsEmpty() )
852 m_aScrollForward
.Hide();
856 const Rectangle
aButtonForward( m_aNormalizer
.getTransformed( m_aGeometry
.getButtonForwardRect(), m_eTabAlignment
) );
857 m_aScrollForward
.SetPosSizePixel( aButtonForward
.TopLeft(), aButtonForward
.GetSize() );
858 m_aScrollForward
.Show();
861 UpdateScrollButtons();
864 //------------------------------------------------------------------------------------------------------------------
865 ::boost::optional
< size_t > PanelTabBar_Impl::FindItemForPoint( const Point
& i_rPoint
) const
867 Point
aPoint( IsVertical() ? i_rPoint
.Y() : i_rPoint
.X(), IsVertical() ? i_rPoint
.X() : i_rPoint
.Y() );
869 if ( !m_aGeometry
.getItemsRect().IsInside( aPoint
) )
870 return ::boost::optional
< size_t >();
873 for ( ItemDescriptors::const_iterator item
= m_aItems
.begin();
874 item
!= m_aItems
.end();
878 Rectangle
aItemRect( GetActualLogicalItemRect( item
->GetCurrentRect() ) );
879 if ( aItemRect
.IsInside( aPoint
) )
881 return ::boost::optional
< size_t >( i
);
884 return ::boost::optional
< size_t >();
887 //------------------------------------------------------------------------------------------------------------------
888 Rectangle
PanelTabBar_Impl::GetItemScreenRect( const size_t i_nItemPos
) const
890 ENSURE_OR_RETURN( i_nItemPos
< m_aItems
.size(), "PanelTabBar_Impl::GetItemScreenRect: invalid item pos!", Rectangle() );
891 const ItemDescriptor
& rItem( m_aItems
[ i_nItemPos
] );
892 const Rectangle
aItemRect( m_aNormalizer
.getTransformed(
893 GetActualLogicalItemRect( rItem
.GetCurrentRect() ),
896 const Rectangle
aTabBarRect( m_rTabBar
.GetWindowExtentsRelative( NULL
) );
898 Point( aTabBarRect
.Left() + aItemRect
.Left(), aTabBarRect
.Top() + aItemRect
.Top() ),
903 //------------------------------------------------------------------------------------------------------------------
904 void PanelTabBar_Impl::FocusItem( const ::boost::optional
< size_t >& i_rItemPos
)
906 // reset old focus item
907 if ( !!m_aFocusedItem
)
908 InvalidateItem( *m_aFocusedItem
);
909 m_aFocusedItem
.reset();
911 // mark the active icon as focused
914 m_aFocusedItem
= i_rItemPos
;
915 InvalidateItem( *m_aFocusedItem
);
919 //------------------------------------------------------------------------------------------------------------------
920 IMPL_LINK( PanelTabBar_Impl
, OnScroll
, const PushButton
*, i_pButton
)
922 if ( i_pButton
== &m_aScrollBack
)
924 OSL_ENSURE( m_nScrollPosition
> 0, "PanelTabBar_Impl::OnScroll: inconsistency!" );
926 m_rTabBar
.Invalidate();
928 else if ( i_pButton
== &m_aScrollForward
)
930 OSL_ENSURE( m_nScrollPosition
< m_aItems
.size() - 1, "PanelTabBar_Impl::OnScroll: inconsistency!" );
932 m_rTabBar
.Invalidate();
935 UpdateScrollButtons();
940 //------------------------------------------------------------------------------------------------------------------
941 Rectangle
PanelTabBar_Impl::GetActualLogicalItemRect( const Rectangle
& i_rLogicalItemRect
) const
943 // care for the offset imposed by our geometry, i.e. whether or not we have scroll buttons
944 Rectangle
aItemRect( i_rLogicalItemRect
);
945 aItemRect
.Move( m_aGeometry
.getItemsRect().Left() - m_aGeometry
.getButtonBackRect().Left(), 0 );
947 // care for the current scroll position
948 OSL_ENSURE( m_nScrollPosition
< m_aItems
.size(), "GetActualLogicalItemRect: invalid scroll position!" );
949 if ( ( m_nScrollPosition
> 0 ) && ( m_nScrollPosition
< m_aItems
.size() ) )
951 long nOffsetX
= m_aItems
[ m_nScrollPosition
].GetCurrentRect().Left() - m_aItems
[ 0 ].GetCurrentRect().Left();
952 long nOffsetY
= m_aItems
[ m_nScrollPosition
].GetCurrentRect().Top() - m_aItems
[ 0 ].GetCurrentRect().Top();
953 aItemRect
.Move( -nOffsetX
, -nOffsetY
);
959 //==================================================================================================================
961 //==================================================================================================================
962 //------------------------------------------------------------------------------------------------------------------
963 void PanelTabBar_Impl::ActivePanelChanged( const ::boost::optional
< size_t >& i_rOldActive
, const ::boost::optional
< size_t >& i_rNewActive
)
967 if ( !!i_rOldActive
)
968 InvalidateItem( *i_rOldActive
, ITEM_STATE_ACTIVE
);
969 if ( !!i_rNewActive
)
970 InvalidateItem( *i_rNewActive
);
973 //------------------------------------------------------------------------------------------------------------------
974 void PanelTabBar_Impl::LayouterChanged( const PDeckLayouter
& i_rNewLayouter
)
977 (void)i_rNewLayouter
;
980 //------------------------------------------------------------------------------------------------------------------
981 void PanelTabBar_Impl::Dying()
983 // not interested in - the notifier is a member of this instance here, so we're dying ourself at the moment
986 //==================================================================================================================
988 //==================================================================================================================
989 //------------------------------------------------------------------------------------------------------------------
990 PanelTabBar::PanelTabBar( Window
& i_rParentWindow
, IToolPanelDeck
& i_rPanelDeck
, const TabAlignment i_eAlignment
, const TabItemContent i_eItemContent
)
991 :Control( &i_rParentWindow
, 0 )
992 ,m_pImpl( new PanelTabBar_Impl( *this, i_rPanelDeck
, i_eAlignment
, i_eItemContent
) )
994 DBG_CHECK( *m_pImpl
);
997 //------------------------------------------------------------------------------------------------------------------
998 PanelTabBar::~PanelTabBar()
1002 //------------------------------------------------------------------------------------------------------------------
1003 TabItemContent
PanelTabBar::GetTabItemContent() const
1005 return m_pImpl
->m_aGeometry
.getItemContent();
1008 //------------------------------------------------------------------------------------------------------------------
1009 void PanelTabBar::SetTabItemContent( const TabItemContent
& i_eItemContent
)
1011 m_pImpl
->m_aGeometry
.setItemContent( i_eItemContent
);
1012 m_pImpl
->Relayout();
1016 //------------------------------------------------------------------------------------------------------------------
1017 IToolPanelDeck
& PanelTabBar::GetPanelDeck() const
1019 DBG_CHECK( *m_pImpl
);
1020 return m_pImpl
->m_rPanelDeck
;
1023 //------------------------------------------------------------------------------------------------------------------
1024 Size
PanelTabBar::GetOptimalSize() const
1026 m_pImpl
->EnsureItemsCache();
1027 Size
aOptimalSize(m_pImpl
->m_aGeometry
.getOptimalSize(m_pImpl
->m_aItems
));
1028 if ( m_pImpl
->IsVertical() )
1029 ::std::swap( aOptimalSize
.Width(), aOptimalSize
.Height() );
1030 return aOptimalSize
;
1033 //------------------------------------------------------------------------------------------------------------------
1034 void PanelTabBar::Resize()
1037 m_pImpl
->Relayout();
1040 //------------------------------------------------------------------------------------------------------------------
1041 void PanelTabBar::Paint( const Rectangle
& i_rRect
)
1043 m_pImpl
->EnsureItemsCache();
1046 const Rectangle
aNormalizedPaintArea( m_pImpl
->m_aNormalizer
.getNormalized( i_rRect
, m_pImpl
->m_eTabAlignment
) );
1047 m_pImpl
->m_aRenderDevice
.Push( PUSH_CLIPREGION
);
1048 m_pImpl
->m_aRenderDevice
.SetClipRegion(Region(aNormalizedPaintArea
));
1049 m_pImpl
->m_pRenderer
->renderBackground();
1050 m_pImpl
->m_aRenderDevice
.Pop();
1051 m_pImpl
->CopyFromRenderDevice( aNormalizedPaintArea
);
1053 // ensure the items really paint into their own playground only
1054 ClipItemRegion
aClipItems( *m_pImpl
);
1056 const Rectangle
aLogicalPaintRect( m_pImpl
->m_aNormalizer
.getNormalized( i_rRect
, m_pImpl
->m_eTabAlignment
) );
1058 const ::boost::optional
< size_t > aActivePanel( m_pImpl
->m_rPanelDeck
.GetActivePanel() );
1059 const ::boost::optional
< size_t > aHoveredPanel( m_pImpl
->m_aHoveredItem
);
1062 // 1. paint all non-active, non-hovered items
1064 for ( ItemDescriptors::const_iterator item
= m_pImpl
->m_aItems
.begin();
1065 item
!= m_pImpl
->m_aItems
.end();
1069 if ( i
== aActivePanel
)
1072 if ( aHoveredPanel
== i
)
1075 m_pImpl
->DrawItem( i
, aLogicalPaintRect
);
1078 // 2. paint the item which is hovered, /without/ the mouse button pressed down
1079 if ( !!aHoveredPanel
&& !m_pImpl
->m_bMouseButtonDown
)
1080 m_pImpl
->DrawItem( *aHoveredPanel
, aLogicalPaintRect
);
1082 // 3. paint the active item
1083 if ( !!aActivePanel
)
1084 m_pImpl
->DrawItem( *aActivePanel
, aLogicalPaintRect
);
1086 // 4. paint the item which is hovered, /with/ the mouse button pressed down
1087 if ( !!aHoveredPanel
&& m_pImpl
->m_bMouseButtonDown
)
1088 m_pImpl
->DrawItem( *aHoveredPanel
, aLogicalPaintRect
);
1091 //------------------------------------------------------------------------------------------------------------------
1092 void PanelTabBar::MouseMove( const MouseEvent
& i_rMouseEvent
)
1094 m_pImpl
->EnsureItemsCache();
1096 ::boost::optional
< size_t > aOldItem( m_pImpl
->m_aHoveredItem
);
1097 ::boost::optional
< size_t > aNewItem( m_pImpl
->FindItemForPoint( i_rMouseEvent
.GetPosPixel() ) );
1099 if ( i_rMouseEvent
.IsLeaveWindow() )
1100 aNewItem
= ::boost::optional
< size_t >();
1102 bool const bChanged(
1103 ( !aOldItem
&& aNewItem
)
1104 || ( aOldItem
&& !aNewItem
)
1105 || ( aOldItem
&& aNewItem
&& aOldItem
!= aNewItem
) )
1110 m_pImpl
->InvalidateItem( *aOldItem
);
1112 m_pImpl
->m_aHoveredItem
= aNewItem
;
1115 m_pImpl
->InvalidateItem( *aNewItem
);
1119 //------------------------------------------------------------------------------------------------------------------
1120 void PanelTabBar::MouseButtonDown( const MouseEvent
& i_rMouseEvent
)
1122 Control::MouseButtonDown( i_rMouseEvent
);
1124 if ( !i_rMouseEvent
.IsLeft() )
1127 m_pImpl
->EnsureItemsCache();
1129 ::boost::optional
< size_t > aHitItem( m_pImpl
->FindItemForPoint( i_rMouseEvent
.GetPosPixel() ) );
1134 m_pImpl
->m_bMouseButtonDown
= true;
1136 m_pImpl
->InvalidateItem( *aHitItem
);
1139 //------------------------------------------------------------------------------------------------------------------
1140 void PanelTabBar::MouseButtonUp( const MouseEvent
& i_rMouseEvent
)
1142 Control::MouseButtonUp( i_rMouseEvent
);
1144 if ( m_pImpl
->m_bMouseButtonDown
)
1146 ::boost::optional
< size_t > aHitItem( m_pImpl
->FindItemForPoint( i_rMouseEvent
.GetPosPixel() ) );
1149 // re-draw that item now that we're not in mouse-down mode anymore
1150 m_pImpl
->InvalidateItem( *aHitItem
);
1151 // activate the respective panel
1152 m_pImpl
->m_rPanelDeck
.ActivatePanel( *aHitItem
);
1155 OSL_ENSURE( IsMouseCaptured(), "PanelTabBar::MouseButtonUp: inconsistency!" );
1156 if ( IsMouseCaptured() )
1158 m_pImpl
->m_bMouseButtonDown
= false;
1162 //------------------------------------------------------------------------------------------------------------------
1163 void PanelTabBar::RequestHelp( const HelpEvent
& i_rHelpEvent
)
1165 m_pImpl
->EnsureItemsCache();
1167 ::boost::optional
< size_t > aHelpItem( m_pImpl
->FindItemForPoint( ScreenToOutputPixel( i_rHelpEvent
.GetMousePosPixel() ) ) );
1171 const ItemDescriptor
& rItem( m_pImpl
->m_aItems
[ *aHelpItem
] );
1172 if ( rItem
.eContent
!= TABITEM_IMAGE_ONLY
)
1173 // if the text is displayed for the item, we do not need to show it as tooltip
1176 const OUString
sItemText( rItem
.pPanel
->GetDisplayName() );
1177 if ( i_rHelpEvent
.GetMode() == HELPMODE_BALLOON
)
1178 Help::ShowBalloon( this, OutputToScreenPixel( rItem
.GetCurrentRect().Center() ), rItem
.GetCurrentRect(), sItemText
);
1180 Help::ShowQuickHelp( this, rItem
.GetCurrentRect(), sItemText
);
1183 //------------------------------------------------------------------------------------------------------------------
1184 void PanelTabBar::GetFocus()
1186 Control::GetFocus();
1187 if ( !m_pImpl
->m_aFocusedItem
)
1188 m_pImpl
->FocusItem( m_pImpl
->m_rPanelDeck
.GetActivePanel() );
1191 //------------------------------------------------------------------------------------------------------------------
1192 void PanelTabBar::LoseFocus()
1194 Control::LoseFocus();
1196 if ( !!m_pImpl
->m_aFocusedItem
)
1198 m_pImpl
->InvalidateItem( *m_pImpl
->m_aFocusedItem
);
1201 m_pImpl
->m_aFocusedItem
.reset();
1204 //------------------------------------------------------------------------------------------------------------------
1205 class KeyInputHandler
1208 KeyInputHandler( Control
& i_rControl
, const KeyEvent
& i_rKeyEvent
)
1209 :m_rControl( i_rControl
)
1210 ,m_rKeyEvent( i_rKeyEvent
)
1211 ,m_bHandled( false )
1218 m_rControl
.Control::KeyInput( m_rKeyEvent
);
1227 Control
& m_rControl
;
1228 const KeyEvent
& m_rKeyEvent
;
1232 //------------------------------------------------------------------------------------------------------------------
1233 void PanelTabBar::KeyInput( const KeyEvent
& i_rKeyEvent
)
1235 KeyInputHandler
aKeyInputHandler( *this, i_rKeyEvent
);
1237 const KeyCode
& rKeyCode( i_rKeyEvent
.GetKeyCode() );
1238 if ( rKeyCode
.GetModifier() != 0 )
1239 // only interested in mere key presses
1242 // if there are less than 2 panels, we cannot travel them ...
1243 const size_t nPanelCount( m_pImpl
->m_rPanelDeck
.GetPanelCount() );
1244 if ( nPanelCount
< 2 )
1247 OSL_PRECOND( !!m_pImpl
->m_aFocusedItem
, "PanelTabBar::KeyInput: we should have a focused item here!" );
1248 // if we get KeyInput events, we should have the focus. In this case, m_aFocusedItem should not be empty,
1249 // except if there are no panels, but then we bail out of this method here earlier ...
1251 bool bFocusNext
= false;
1252 bool bFocusPrev
= false;
1254 switch ( rKeyCode
.GetCode() )
1256 case KEY_UP
: bFocusPrev
= true; break;
1257 case KEY_DOWN
: bFocusNext
= true; break;
1259 if ( IsRTLEnabled() )
1265 if ( IsRTLEnabled() )
1271 m_pImpl
->m_rPanelDeck
.ActivatePanel( *m_pImpl
->m_aFocusedItem
);
1275 if ( !bFocusNext
&& !bFocusPrev
)
1278 m_pImpl
->InvalidateItem( *m_pImpl
->m_aFocusedItem
);
1281 m_pImpl
->m_aFocusedItem
.reset( ( *m_pImpl
->m_aFocusedItem
+ 1 ) % nPanelCount
);
1285 m_pImpl
->m_aFocusedItem
.reset( ( *m_pImpl
->m_aFocusedItem
+ nPanelCount
- 1 ) % nPanelCount
);
1287 m_pImpl
->InvalidateItem( *m_pImpl
->m_aFocusedItem
);
1289 // don't delegate to base class
1290 aKeyInputHandler
.setHandled();
1293 //------------------------------------------------------------------------------------------------------------------
1294 void PanelTabBar::DataChanged( const DataChangedEvent
& i_rDataChanedEvent
)
1296 Control::DataChanged( i_rDataChanedEvent
);
1298 if ( ( i_rDataChanedEvent
.GetType() == DATACHANGED_SETTINGS
)
1299 && ( ( i_rDataChanedEvent
.GetFlags() & SETTINGS_STYLE
) != 0 )
1306 //------------------------------------------------------------------------------------------------------------------
1307 bool PanelTabBar::IsVertical() const
1309 return m_pImpl
->IsVertical();
1312 //------------------------------------------------------------------------------------------------------------------
1313 PushButton
& PanelTabBar::GetScrollButton( const bool i_bForward
)
1315 return i_bForward
? m_pImpl
->m_aScrollForward
: m_pImpl
->m_aScrollBack
;
1318 //------------------------------------------------------------------------------------------------------------------
1319 ::boost::optional
< size_t > PanelTabBar::GetFocusedPanelItem() const
1321 return m_pImpl
->m_aFocusedItem
;
1324 //------------------------------------------------------------------------------------------------------------------
1325 void PanelTabBar::FocusPanelItem( const size_t i_nItemPos
)
1327 ENSURE_OR_RETURN_VOID( i_nItemPos
< m_pImpl
->m_rPanelDeck
.GetPanelCount(), "PanelTabBar::FocusPanelItem: illegal item pos!" );
1329 if ( !HasChildPathFocus() )
1332 m_pImpl
->FocusItem( i_nItemPos
);
1333 OSL_POSTCOND( !!m_pImpl
->m_aFocusedItem
, "PanelTabBar::FocusPanelItem: have the focus, but no focused item?" );
1334 if ( !!m_pImpl
->m_aFocusedItem
)
1335 m_pImpl
->InvalidateItem( *m_pImpl
->m_aFocusedItem
);
1336 m_pImpl
->m_aFocusedItem
.reset( i_nItemPos
);
1339 //------------------------------------------------------------------------------------------------------------------
1340 Rectangle
PanelTabBar::GetItemScreenRect( const size_t i_nItemPos
) const
1342 return m_pImpl
->GetItemScreenRect( i_nItemPos
);
1345 //------------------------------------------------------------------------------------------------------------------
1346 Reference
< XWindowPeer
> PanelTabBar::GetComponentInterface( sal_Bool i_bCreate
)
1348 Reference
< XWindowPeer
> xWindowPeer( Control::GetComponentInterface( sal_False
) );
1349 if ( !xWindowPeer
.is() && i_bCreate
)
1351 xWindowPeer
.set( new PanelTabBarPeer( *this ) );
1352 SetComponentInterface( xWindowPeer
);
1357 //........................................................................
1359 //........................................................................
1361 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */