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