GPU-Calc: remove Alloc_Host_Ptr for clmem of NAN vector
[LibreOffice.git] / svtools / source / toolpanel / paneltabbar.cxx
blobc4cb2d5163eedadc9e9af3b4edeed76233842db2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
36 #include <vector>
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 //........................................................................
46 namespace svt
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 //==================================================================================================================
63 //= helper
64 //==================================================================================================================
65 namespace
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;
73 return nState;
77 //==================================================================================================================
78 //= ITabBarRenderer
79 //==================================================================================================================
80 class SAL_NO_VTABLE ITabBarRenderer
82 public:
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.
96 protected:
97 ~ITabBarRenderer() {}
99 typedef ::boost::shared_ptr< ITabBarRenderer > PTabBarRenderer;
101 //==================================================================================================================
102 //= VCLItemRenderer - declaration
103 //==================================================================================================================
104 class VCLItemRenderer : public ITabBarRenderer
106 public:
107 VCLItemRenderer( OutputDevice& i_rTargetDevice )
108 :m_rTargetDevice( i_rTargetDevice )
111 virtual ~VCLItemRenderer() {}
113 // ITabBarRenderer
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;
119 protected:
120 OutputDevice& getTargetDevice() const { return m_rTargetDevice; }
122 private:
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
138 (void)i_nItemFlags;
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;
147 (void)i_nItemFlags;
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(
164 aSelectionRect,
165 ( bHovered || bFocused ) ? ( bActive ? 1 : 2 ) : 0 /* hilight */,
166 bActive /* check */,
167 sal_True /* border */,
168 sal_False /* ext border only */,
169 0 /* corner radius */,
170 NULL,
171 NULL
176 //==================================================================================================================
177 //= NWFToolboxItemRenderer - declaration
178 //==================================================================================================================
179 class NWFToolboxItemRenderer : public ITabBarRenderer
181 public:
182 NWFToolboxItemRenderer( OutputDevice& i_rTargetDevice )
183 :m_rTargetDevice( i_rTargetDevice )
186 virtual ~NWFToolboxItemRenderer() {}
188 // ITabBarRenderer
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;
194 protected:
195 OutputDevice& getTargetDevice() const { return m_rTargetDevice; }
197 private:
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
222 // );
223 (void)i_nItemFlags;
224 return Rectangle(
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() );
239 (void)bNativeOK;
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;
248 (void)i_rItemRect;
249 (void)i_nItemFlags;
252 //==================================================================================================================
253 //= NWFTabItemRenderer - declaration
254 //==================================================================================================================
255 class NWFTabItemRenderer : public ITabBarRenderer
257 public:
258 NWFTabItemRenderer( OutputDevice& i_rTargetDevice )
259 :m_rTargetDevice( i_rTargetDevice )
263 virtual ~NWFTabItemRenderer() {}
265 // ITabBarRenderer
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;
271 protected:
272 OutputDevice& getTargetDevice() const { return m_rTargetDevice; }
274 private:
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,
303 tiValue, OUString(),
304 aBoundingRegion, aContentRegion
306 (void)bNativeOK;
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() );
325 (void)bNativeOK;
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;
334 (void)i_rItemRect;
335 (void)i_nItemFlags;
338 //==================================================================================================================
339 //= PanelTabBar_Impl
340 //==================================================================================================================
341 class PanelTabBar_Impl : public IToolPanelDeckListener
343 public:
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 )
354 (void)i_pPanel;
355 (void)i_nPosition;
356 m_bItemsDirty = true;
357 m_rTabBar.Invalidate();
359 Relayout();
362 virtual void PanelRemoved( const size_t i_nPosition )
364 m_bItemsDirty = true;
365 m_rTabBar.Invalidate();
367 if ( i_nPosition < m_nScrollPosition )
368 --m_nScrollPosition;
370 Relayout();
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 );
383 void Relayout();
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 )
401 protected:
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;
409 public:
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;
424 bool m_bItemsDirty;
426 PushButton m_aScrollBack;
427 PushButton m_aScrollForward;
429 size_t m_nScrollPosition;
432 //==================================================================================================================
433 //= helper
434 //==================================================================================================================
435 namespace
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!" );
446 return;
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!" );
453 return;
459 #define DBG_CHECK( data ) \
460 lcl_checkConsistency( data );
461 #else
462 #define DBG_CHECK( data ) \
463 (void)data;
464 #endif
466 //--------------------------------------------------------------------------------------------------------------
467 class ClipItemRegion
469 public:
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 )));
480 ~ClipItemRegion()
482 m_rDevice.Pop();
485 private:
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 )
497 ,m_aNormalizer()
498 ,m_eTabAlignment( i_eAlignment )
499 ,m_rPanelDeck( i_rPanelDeck )
500 ,m_aRenderDevice( i_rTabBar )
501 ,m_pRenderer()
502 ,m_aHoveredItem()
503 ,m_aFocusedItem()
504 ,m_bMouseButtonDown( false )
505 ,m_aItems()
506 ,m_bItemsDirty( true )
507 ,m_aScrollBack( &i_rTabBar, WB_BEVELBUTTON )
508 ,m_aScrollForward( &i_rTabBar, WB_BEVELBUTTON )
509 ,m_nScrollPosition( 0 )
511 #ifdef WNT
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 ) );
517 else
518 #endif
519 if ( m_aRenderDevice.IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) )
520 m_pRenderer.reset( new NWFToolboxItemRenderer( m_aRenderDevice ) );
521 else
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()
544 m_aItems.resize(0);
546 Point aCompletePos( m_aGeometry.getFirstItemPosition() );
547 Point aIconOnlyPos( aCompletePos );
548 Point aTextOnlyPos( aCompletePos );
550 for ( size_t i = 0;
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;
594 if ( bUseImage )
596 aItemContentSize = aImage.GetSizePixel();
599 if ( bUseText )
601 if ( bUseImage )
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 );
631 if ( IsVertical() )
633 aRenderArea.Top() += ITEM_OUTER_SPACE;
635 else
637 aRenderArea.Left() += ITEM_OUTER_SPACE;
640 // draw the image
641 const Image aItemImage( i_pPanel->GetImage() );
642 const Size aImageSize( aItemImage.GetSizePixel() );
643 const bool bUseImage = !!aItemImage && ( i_eItemContent != TABITEM_TEXT_ONLY );
645 if ( bUseImage )
647 Point aImagePos;
648 if ( IsVertical() )
650 aImagePos.X() = aRenderArea.Left() + ( aRenderArea.GetWidth() - aImageSize.Width() ) / 2;
651 aImagePos.Y() = aRenderArea.Top();
653 else
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 );
664 if ( bUseText )
666 if ( IsVertical() )
668 if ( bUseImage )
669 aRenderArea.Top() += aImageSize.Height() + ITEM_ICON_TEXT_DISTANCE;
670 aRenderArea.Top() += ITEM_TEXT_FLOW_SPACE;
672 else
674 if ( bUseImage )
675 aRenderArea.Left() += aImageSize.Width() + ITEM_ICON_TEXT_DISTANCE;
676 aRenderArea.Left() += ITEM_TEXT_FLOW_SPACE;
679 // draw the text
680 const Size aTextSize( m_rTabBar.GetCtrlTextWidth( sItemText ), m_rTabBar.GetTextHeight() );
681 Point aTextPos( aRenderArea.TopLeft() );
682 if ( IsVertical() )
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;
694 else
696 aTextPos.Y() += ( aRenderArea.GetHeight() - aTextSize.Height() ) / 2;
699 m_rTabBar.DrawText( aTextPos, sItemText );
701 if ( IsVertical() )
703 m_rTabBar.Pop();
708 //------------------------------------------------------------------------------------------------------------------
709 void PanelTabBar_Impl::CopyFromRenderDevice( const Rectangle& i_rLogicalRect ) const
711 BitmapEx aBitmap( m_aRenderDevice.GetBitmapEx(
712 i_rLogicalRect.TopLeft(),
713 Size(
714 i_rLogicalRect.GetSize().Width(),
715 i_rLogicalRect.GetSize().Height()
717 ) );
718 if ( IsVertical() )
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;
769 return nItemFlags;
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 ) )
787 return;
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 )
816 DBG_CHECK( *this );
817 return;
819 impl_calcItemRects();
820 OSL_POSTCOND( m_bItemsDirty == false, "PanelTabBar_Impl::EnsureItemsCache: cache still dirty!" );
821 DBG_CHECK( *this );
824 //------------------------------------------------------------------------------------------------------------------
825 void PanelTabBar_Impl::Relayout()
827 EnsureItemsCache();
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();
843 else
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();
854 else
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 >();
872 size_t i=0;
873 for ( ItemDescriptors::const_iterator item = m_aItems.begin();
874 item != m_aItems.end();
875 ++item, ++i
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() ),
894 m_eTabAlignment ) );
896 const Rectangle aTabBarRect( m_rTabBar.GetWindowExtentsRelative( NULL ) );
897 return Rectangle(
898 Point( aTabBarRect.Left() + aItemRect.Left(), aTabBarRect.Top() + aItemRect.Top() ),
899 aItemRect.GetSize()
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
912 if ( !!i_rItemPos )
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!" );
925 --m_nScrollPosition;
926 m_rTabBar.Invalidate();
928 else if ( i_pButton == &m_aScrollForward )
930 OSL_ENSURE( m_nScrollPosition < m_aItems.size() - 1, "PanelTabBar_Impl::OnScroll: inconsistency!" );
931 ++m_nScrollPosition;
932 m_rTabBar.Invalidate();
935 UpdateScrollButtons();
937 return 0L;
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 );
956 return aItemRect;
959 //==================================================================================================================
960 //= PanelTabBar_Impl
961 //==================================================================================================================
962 //------------------------------------------------------------------------------------------------------------------
963 void PanelTabBar_Impl::ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive )
965 EnsureItemsCache();
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 )
976 // not interested in
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 //==================================================================================================================
987 //= PanelTabBar
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();
1013 Invalidate();
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()
1036 Control::Resize();
1037 m_pImpl->Relayout();
1040 //------------------------------------------------------------------------------------------------------------------
1041 void PanelTabBar::Paint( const Rectangle& i_rRect )
1043 m_pImpl->EnsureItemsCache();
1045 // background
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 );
1061 // items:
1062 // 1. paint all non-active, non-hovered items
1063 size_t i=0;
1064 for ( ItemDescriptors::const_iterator item = m_pImpl->m_aItems.begin();
1065 item != m_pImpl->m_aItems.end();
1066 ++item, ++i
1069 if ( i == aActivePanel )
1070 continue;
1072 if ( aHoveredPanel == i )
1073 continue;
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 ) )
1107 if ( bChanged )
1109 if ( aOldItem )
1110 m_pImpl->InvalidateItem( *aOldItem );
1112 m_pImpl->m_aHoveredItem = aNewItem;
1114 if ( 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() )
1125 return;
1127 m_pImpl->EnsureItemsCache();
1129 ::boost::optional< size_t > aHitItem( m_pImpl->FindItemForPoint( i_rMouseEvent.GetPosPixel() ) );
1130 if ( !aHitItem )
1131 return;
1133 CaptureMouse();
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() ) );
1147 if ( !!aHitItem )
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() )
1157 ReleaseMouse();
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() ) ) );
1168 if ( !aHelpItem )
1169 return;
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
1174 return;
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 );
1179 else
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
1207 public:
1208 KeyInputHandler( Control& i_rControl, const KeyEvent& i_rKeyEvent )
1209 :m_rControl( i_rControl )
1210 ,m_rKeyEvent( i_rKeyEvent )
1211 ,m_bHandled( false )
1215 ~KeyInputHandler()
1217 if ( !m_bHandled )
1218 m_rControl.Control::KeyInput( m_rKeyEvent );
1221 void setHandled()
1223 m_bHandled = true;
1226 private:
1227 Control& m_rControl;
1228 const KeyEvent& m_rKeyEvent;
1229 bool m_bHandled;
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
1240 return;
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 )
1245 return;
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;
1258 case KEY_LEFT:
1259 if ( IsRTLEnabled() )
1260 bFocusNext = true;
1261 else
1262 bFocusPrev = true;
1263 break;
1264 case KEY_RIGHT:
1265 if ( IsRTLEnabled() )
1266 bFocusPrev = true;
1267 else
1268 bFocusNext = true;
1269 break;
1270 case KEY_RETURN:
1271 m_pImpl->m_rPanelDeck.ActivatePanel( *m_pImpl->m_aFocusedItem );
1272 break;
1275 if ( !bFocusNext && !bFocusPrev )
1276 return;
1278 m_pImpl->InvalidateItem( *m_pImpl->m_aFocusedItem );
1279 if ( bFocusNext )
1281 m_pImpl->m_aFocusedItem.reset( ( *m_pImpl->m_aFocusedItem + 1 ) % nPanelCount );
1283 else
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 )
1302 Invalidate();
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() )
1330 GrabFocus();
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 );
1354 return xWindowPeer;
1357 //........................................................................
1358 } // namespace svt
1359 //........................................................................
1361 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */