1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <svtools/tabbar.hxx>
22 #include <tools/time.hxx>
23 #include <tools/poly.hxx>
25 #include <vcl/InterimItemWindow.hxx>
26 #include <vcl/bitmapex.hxx>
27 #include <vcl/svapp.hxx>
28 #include <vcl/help.hxx>
29 #include <vcl/decoview.hxx>
30 #include <vcl/event.hxx>
31 #include <vcl/settings.hxx>
32 #include <vcl/commandevent.hxx>
33 #include <vcl/svtaccessiblefactory.hxx>
34 #include <vcl/accessiblefactory.hxx>
35 #include <vcl/ptrstyle.hxx>
36 #include <vcl/weldutils.hxx>
37 #include <svtools/svtresid.hxx>
38 #include <svtools/strings.hrc>
42 #include <vcl/idle.hxx>
43 #include <bitmaps.hlst>
48 constexpr sal_uInt16 TABBAR_DRAG_SCROLLOFF
= 5;
49 constexpr sal_uInt16 TABBAR_MINSIZE
= 5;
51 constexpr sal_uInt16 ADDNEWPAGE_AREAWIDTH
= 10;
56 vcl::RenderContext
& mrRenderContext
;
57 const StyleSettings
& mrStyleSettings
;
59 tools::Rectangle maRect
;
60 tools::Rectangle maLineRect
;
62 Color maSelectedColor
;
67 bool mbCustomColored
:1;
71 explicit TabDrawer(vcl::RenderContext
& rRenderContext
)
72 : mrRenderContext(rRenderContext
)
73 , mrStyleSettings(rRenderContext
.GetSettings().GetStyleSettings())
75 , mbCustomColored(false)
84 // set correct FillInBrush depending on status
87 // Currently selected Tab
88 mrRenderContext
.SetFillColor(maSelectedColor
);
89 mrRenderContext
.SetLineColor(maSelectedColor
);
90 mrRenderContext
.DrawRect(maRect
);
91 mrRenderContext
.SetLineColor(mrStyleSettings
.GetDarkShadowColor());
93 else if (mbCustomColored
)
95 mrRenderContext
.SetFillColor(maCustomColor
);
96 mrRenderContext
.SetLineColor(maCustomColor
);
97 mrRenderContext
.DrawRect(maRect
);
98 mrRenderContext
.SetLineColor(mrStyleSettings
.GetDarkShadowColor());
102 void drawText(const OUString
& aText
)
104 tools::Rectangle aRect
= maRect
;
105 tools::Long nTextWidth
= mrRenderContext
.GetTextWidth(aText
);
106 tools::Long nTextHeight
= mrRenderContext
.GetTextHeight();
107 Point aPos
= aRect
.TopLeft();
108 aPos
.AdjustX((aRect
.getOpenWidth() - nTextWidth
) / 2 );
109 aPos
.AdjustY((aRect
.getOpenHeight() - nTextHeight
) / 2 );
112 mrRenderContext
.DrawText(aPos
, aText
);
114 mrRenderContext
.DrawCtrlText(aPos
, aText
, 0, aText
.getLength(), (DrawTextFlags::Disable
| DrawTextFlags::Mnemonic
));
117 void drawOverTopBorder()
119 Point aTopLeft
= maRect
.TopLeft() + Point(1, 0);
120 Point aTopRight
= maRect
.TopRight() + Point(-1, 0);
122 tools::Rectangle
aDelRect(aTopLeft
, aTopRight
);
123 mrRenderContext
.DrawRect(aDelRect
);
131 // tdf#141396: the color must be different from the rest of the selected tab
132 Color aLineColor
= (mbCustomColored
&& maCustomColor
!= maSelectedColor
)
134 : mrStyleSettings
.GetDarkShadowColor();
135 mrRenderContext
.SetFillColor(aLineColor
);
136 mrRenderContext
.SetLineColor(aLineColor
);
137 mrRenderContext
.DrawRect(maLineRect
);
142 const tools::Long cMargin
= 5;
143 const tools::Long
aRight( maRect
.Right() - 1 );
144 mrRenderContext
.SetLineColor(mrStyleSettings
.GetShadowColor());
145 mrRenderContext
.DrawLine(Point(aRight
, maRect
.Top() + cMargin
),
146 Point(aRight
, maRect
.Bottom() - cMargin
));
153 if (!mbSelected
&& !mbCustomColored
)
157 BitmapEx
aBitmap(BMP_TAB_LOCK
);
158 Point aPosition
= maRect
.TopLeft();
159 aPosition
.AdjustX(2);
160 aPosition
.AdjustY((maRect
.getOpenHeight() - aBitmap
.GetSizePixel().Height()) / 2);
161 mrRenderContext
.DrawBitmapEx(aPosition
, aBitmap
);
165 void setRect(const tools::Rectangle
& rRect
)
167 maLineRect
= tools::Rectangle(rRect
.BottomLeft(), rRect
.BottomRight());
168 maLineRect
.AdjustTop(-2);
172 void setSelected(bool bSelected
)
174 mbSelected
= bSelected
;
177 void setCustomColored(bool bCustomColored
)
179 mbCustomColored
= bCustomColored
;
182 void setEnabled(bool bEnabled
)
184 mbEnabled
= bEnabled
;
187 void setSelectedFillColor(const Color
& rColor
)
189 maSelectedColor
= rColor
;
192 void setCustomColor(const Color
& rColor
)
194 maCustomColor
= rColor
;
198 } // anonymous namespace
200 struct ImplTabBarItem
203 TabBarPageBits mnBits
;
206 OUString maAuxiliaryText
; // used in LayerTabBar for real layer name
207 tools::Rectangle maRect
;
214 Color maTabTextColor
;
216 ImplTabBarItem(sal_uInt16 nItemId
, OUString aText
, TabBarPageBits nPageBits
)
219 , maText(std::move(aText
))
224 , maTabBgColor(COL_AUTO
)
225 , maTabTextColor(COL_AUTO
)
229 bool IsDefaultTabBgColor() const
231 return maTabBgColor
== COL_AUTO
;
234 bool IsSelected(ImplTabBarItem
const * pCurItem
) const
236 return mbSelect
|| (pCurItem
== this);
239 OUString
const & GetRenderText() const
245 class ImplTabSizer
: public vcl::Window
248 ImplTabSizer( TabBar
* pParent
, WinBits nWinStyle
);
250 TabBar
* GetParent() const { return static_cast<TabBar
*>(Window::GetParent()); }
253 void ImplTrack( const Point
& rScreenPos
);
255 virtual void MouseButtonDown( const MouseEvent
& rMEvt
) override
;
256 virtual void Tracking( const TrackingEvent
& rTEvt
) override
;
257 virtual void Paint( vcl::RenderContext
& /*rRenderContext*/, const tools::Rectangle
& rRect
) override
;
260 tools::Long mnStartWidth
;
263 ImplTabSizer::ImplTabSizer( TabBar
* pParent
, WinBits nWinStyle
)
264 : Window( pParent
, nWinStyle
& WB_3DLOOK
)
267 SetPointer(PointerStyle::HSizeBar
);
268 SetSizePixel(Size(7 * GetDPIScaleFactor(), 0));
271 void ImplTabSizer::ImplTrack( const Point
& rScreenPos
)
273 TabBar
* pParent
= GetParent();
274 tools::Long nDiff
= rScreenPos
.X() - maStartPos
.X();
275 pParent
->mnSplitSize
= mnStartWidth
+ (pParent
->IsMirrored() ? -nDiff
: nDiff
);
276 if ( pParent
->mnSplitSize
< TABBAR_MINSIZE
)
277 pParent
->mnSplitSize
= TABBAR_MINSIZE
;
279 pParent
->PaintImmediately();
282 void ImplTabSizer::MouseButtonDown( const MouseEvent
& rMEvt
)
284 if ( GetParent()->IsInEditMode() )
286 GetParent()->EndEditMode();
290 if ( rMEvt
.IsLeft() )
292 maStartPos
= OutputToScreenPixel( rMEvt
.GetPosPixel() );
293 mnStartWidth
= GetParent()->GetSizePixel().Width();
298 void ImplTabSizer::Tracking( const TrackingEvent
& rTEvt
)
300 if ( rTEvt
.IsTrackingEnded() )
302 if ( rTEvt
.IsTrackingCanceled() )
303 ImplTrack( maStartPos
);
304 GetParent()->mnSplitSize
= 0;
307 ImplTrack( OutputToScreenPixel( rTEvt
.GetMouseEvent().GetPosPixel() ) );
310 void ImplTabSizer::Paint( vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& )
312 DecorationView
aDecoView(&rRenderContext
);
313 tools::Rectangle
aOutputRect(Point(0, 0), GetOutputSizePixel());
314 aDecoView
.DrawHandle(aOutputRect
);
319 // Is not named Impl. as it may be both instantiated and derived from
320 class TabBarEdit final
: public InterimItemWindow
323 std::unique_ptr
<weld::Entry
> m_xEntry
;
324 Idle maLoseFocusIdle
;
327 DECL_LINK( ImplEndEditHdl
, void*, void );
328 DECL_LINK( ImplEndTimerHdl
, Timer
*, void );
329 DECL_LINK( ActivatedHdl
, weld::Entry
&, bool );
330 DECL_LINK( KeyInputHdl
, const KeyEvent
&, bool );
331 DECL_LINK( FocusOutHdl
, weld::Widget
&, void );
334 TabBarEdit(TabBar
* pParent
);
335 virtual void dispose() override
;
337 TabBar
* GetParent() const { return static_cast<TabBar
*>(Window::GetParent()); }
339 weld::Entry
& get_widget() { return *m_xEntry
; }
341 void SetPostEvent() { mbPostEvt
= true; }
342 void ResetPostEvent() { mbPostEvt
= false; }
347 TabBarEdit::TabBarEdit(TabBar
* pParent
)
348 : InterimItemWindow(pParent
, "svt/ui/tabbaredit.ui", "TabBarEdit")
349 , m_xEntry(m_xBuilder
->weld_entry("entry"))
350 , maLoseFocusIdle( "svtools::TabBarEdit maLoseFocusIdle" )
352 InitControlBase(m_xEntry
.get());
355 maLoseFocusIdle
.SetPriority( TaskPriority::REPAINT
);
356 maLoseFocusIdle
.SetInvokeHandler( LINK( this, TabBarEdit
, ImplEndTimerHdl
) );
358 m_xEntry
->connect_activate(LINK(this, TabBarEdit
, ActivatedHdl
));
359 m_xEntry
->connect_key_press(LINK(this, TabBarEdit
, KeyInputHdl
));
360 m_xEntry
->connect_focus_out(LINK(this, TabBarEdit
, FocusOutHdl
));
363 void TabBarEdit::dispose()
366 InterimItemWindow::dispose();
369 IMPL_LINK_NOARG(TabBarEdit
, ActivatedHdl
, weld::Entry
&, bool)
373 if ( PostUserEvent( LINK( this, TabBarEdit
, ImplEndEditHdl
), reinterpret_cast<void*>(false), true ) )
379 IMPL_LINK(TabBarEdit
, KeyInputHdl
, const KeyEvent
&, rKEvt
, bool)
381 if (!rKEvt
.GetKeyCode().GetModifier() && rKEvt
.GetKeyCode().GetCode() == KEY_ESCAPE
)
385 if ( PostUserEvent( LINK( this, TabBarEdit
, ImplEndEditHdl
), reinterpret_cast<void*>(true), true ) )
393 IMPL_LINK_NOARG(TabBarEdit
, FocusOutHdl
, weld::Widget
&, void)
397 if ( PostUserEvent( LINK( this, TabBarEdit
, ImplEndEditHdl
), reinterpret_cast<void*>(false), true ) )
402 IMPL_LINK( TabBarEdit
, ImplEndEditHdl
, void*, pCancel
, void )
405 maLoseFocusIdle
.Stop();
407 // tdf#156958: when renaming and clicking on canvas, LO goes into GetParent()->EndEditMode first time
408 // then it calls TabBarEdit::dispose method which resets m_xEntry BUT, on the same thread, LO comes here again
409 // so return if already disposed to avoid a crash
413 // We need this query, because the edit gets a losefocus event,
414 // when it shows the context menu or the insert symbol dialog
415 if (!m_xEntry
->has_focus() && m_xEntry
->has_child_focus())
416 maLoseFocusIdle
.Start();
418 GetParent()->EndEditMode( pCancel
!= nullptr );
421 IMPL_LINK_NOARG(TabBarEdit
, ImplEndTimerHdl
, Timer
*, void)
423 if (m_xEntry
->has_focus())
426 // We need this query, because the edit gets a losefocus event,
427 // when it shows the context menu or the insert symbol dialog
428 if (m_xEntry
->has_child_focus())
429 maLoseFocusIdle
.Start();
431 GetParent()->EndEditMode( true );
436 class TabButtons final
: public InterimItemWindow
439 std::unique_ptr
<weld::Button
> m_xFirstButton
;
440 std::unique_ptr
<weld::Button
> m_xPrevButton
;
441 std::unique_ptr
<weld::Button
> m_xNextButton
;
442 std::unique_ptr
<weld::Button
> m_xLastButton
;
443 std::unique_ptr
<weld::Button
> m_xAddButton
;
444 std::shared_ptr
<weld::ButtonPressRepeater
> m_xAddRepeater
;
445 std::shared_ptr
<weld::ButtonPressRepeater
> m_xPrevRepeater
;
446 std::shared_ptr
<weld::ButtonPressRepeater
> m_xNextRepeater
;
448 TabButtons(TabBar
* pParent
, bool bSheets
)
449 : InterimItemWindow(pParent
,
450 pParent
->IsMirrored() ? OUString("svt/ui/tabbuttonsmirrored.ui")
451 : OUString("svt/ui/tabbuttons.ui"),
453 , m_xFirstButton(m_xBuilder
->weld_button("first"))
454 , m_xPrevButton(m_xBuilder
->weld_button("prev"))
455 , m_xNextButton(m_xBuilder
->weld_button("next"))
456 , m_xLastButton(m_xBuilder
->weld_button("last"))
457 , m_xAddButton(m_xBuilder
->weld_button("add"))
459 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
460 SetPaintTransparent(false);
461 SetBackground(rStyleSettings
.GetFaceColor());
463 m_xFirstButton
->set_accessible_name(SvtResId(STR_TABBAR_PUSHBUTTON_MOVET0HOME
));
464 m_xPrevButton
->set_accessible_name(SvtResId(STR_TABBAR_PUSHBUTTON_MOVELEFT
));
465 m_xNextButton
->set_accessible_name(SvtResId(STR_TABBAR_PUSHBUTTON_MOVERIGHT
));
466 m_xLastButton
->set_accessible_name(SvtResId(STR_TABBAR_PUSHBUTTON_MOVETOEND
));
467 m_xAddButton
->set_accessible_name(SvtResId(STR_TABBAR_PUSHBUTTON_ADDTAB
));
471 m_xFirstButton
->set_tooltip_text(SvtResId(STR_TABBAR_HINT_MOVETOHOME_SHEETS
));
472 m_xPrevButton
->set_tooltip_text(SvtResId(STR_TABBAR_HINT_MOVELEFT_SHEETS
));
473 m_xNextButton
->set_tooltip_text(SvtResId(STR_TABBAR_HINT_MOVERIGHT_SHEETS
));
474 m_xLastButton
->set_tooltip_text(SvtResId(STR_TABBAR_HINT_MOVETOEND_SHEETS
));
475 m_xAddButton
->set_tooltip_text(SvtResId(STR_TABBAR_HINT_ADDTAB_SHEETS
));
479 void AdaptToHeight(int nHeight
)
481 if (m_xFirstButton
->get_preferred_size() == Size(nHeight
, nHeight
))
483 m_xFirstButton
->set_size_request(nHeight
, nHeight
);
484 m_xPrevButton
->set_size_request(nHeight
, nHeight
);
485 m_xNextButton
->set_size_request(nHeight
, nHeight
);
486 m_xLastButton
->set_size_request(nHeight
, nHeight
);
487 m_xAddButton
->set_size_request(nHeight
, nHeight
);
488 InvalidateChildSizeCache();
491 virtual void dispose() override
493 m_xNextRepeater
.reset();
494 m_xPrevRepeater
.reset();
495 m_xAddRepeater
.reset();
496 m_xAddButton
.reset();
497 m_xLastButton
.reset();
498 m_xNextButton
.reset();
499 m_xPrevButton
.reset();
500 m_xFirstButton
.reset();
501 InterimItemWindow::dispose();
509 ScopedVclPtr
<ImplTabSizer
> mpSizer
;
510 ScopedVclPtr
<TabButtons
> mxButtonBox
;
511 ScopedVclPtr
<TabBarEdit
> mxEdit
;
512 std::vector
<ImplTabBarItem
> maItemList
;
514 vcl::AccessibleFactoryAccess maAccessibleFactory
;
516 sal_uInt16
getItemSize() const
518 return static_cast<sal_uInt16
>(maItemList
.size());
522 TabBar::TabBar( vcl::Window
* pParent
, WinBits nWinStyle
, bool bSheets
) :
523 Window( pParent
, (nWinStyle
& WB_3DLOOK
) | WB_CLIPCHILDREN
)
525 ImplInit( nWinStyle
, bSheets
);
526 maCurrentItemList
= 0;
534 void TabBar::dispose()
541 const sal_uInt16
TabBar::APPEND
= ::std::numeric_limits
<sal_uInt16
>::max();
542 const sal_uInt16
TabBar::PAGE_NOT_FOUND
= ::std::numeric_limits
<sal_uInt16
>::max();
544 void TabBar::ImplInit( WinBits nWinStyle
, bool bSheets
)
546 mpImpl
.reset(new TabBar_Impl
);
555 mnWinStyle
= nWinStyle
;
562 mbFirstFormat
= true;
564 mbAutoEditMode
= false;
565 mbEditCanceled
= false;
569 mbScrollAlwaysEnabled
= false;
574 SetSizePixel( Size( 100, CalcWindowSizePixel().Height() ) );
575 ImplInitSettings( true, true );
578 ImplTabBarItem
* TabBar::seek( size_t i
)
580 if ( i
< mpImpl
->maItemList
.size() )
582 maCurrentItemList
= i
;
583 return &mpImpl
->maItemList
[maCurrentItemList
];
588 ImplTabBarItem
* TabBar::prev()
590 if ( maCurrentItemList
> 0 )
592 return &mpImpl
->maItemList
[--maCurrentItemList
];
597 ImplTabBarItem
* TabBar::next()
599 if ( maCurrentItemList
+ 1 < mpImpl
->maItemList
.size() )
601 return &mpImpl
->maItemList
[++maCurrentItemList
];
606 void TabBar::ImplInitSettings( bool bFont
, bool bBackground
)
608 // FIXME RenderContext
610 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
614 vcl::Font aToolFont
= rStyleSettings
.GetToolFont();
615 aToolFont
.SetWeight( WEIGHT_BOLD
);
616 ApplyControlFont(*GetOutDev(), aToolFont
);
618 // Adapt font size if window too small?
619 while (GetTextHeight() > (GetOutputSizePixel().Height() - 1))
621 vcl::Font aFont
= GetFont();
622 if (aFont
.GetFontHeight() <= 6)
624 aFont
.SetFontHeight(aFont
.GetFontHeight() - 1);
631 ApplyControlBackground(*GetOutDev(), rStyleSettings
.GetFaceColor());
635 void TabBar::ImplGetColors(const StyleSettings
& rStyleSettings
,
636 Color
& rFaceColor
, Color
& rFaceTextColor
,
637 Color
& rSelectColor
, Color
& rSelectTextColor
)
639 if (IsControlBackground())
640 rFaceColor
= GetControlBackground();
642 rFaceColor
= rStyleSettings
.GetInactiveTabColor();
643 if (IsControlForeground())
644 rFaceTextColor
= GetControlForeground();
646 rFaceTextColor
= rStyleSettings
.GetButtonTextColor();
647 rSelectColor
= rStyleSettings
.GetActiveTabColor();
648 rSelectTextColor
= rStyleSettings
.GetWindowTextColor();
651 bool TabBar::ImplCalcWidth()
653 // Sizes should only be retrieved if the text or the font was changed
657 // retrieve width of tabs with bold font
658 vcl::Font aFont
= GetFont();
659 if (aFont
.GetWeight() != WEIGHT_BOLD
)
661 aFont
.SetWeight(WEIGHT_BOLD
);
666 mnCurMaxWidth
= mnMaxPageWidth
;
669 mnCurMaxWidth
= mnLastOffX
- mnOffX
;
670 if (mnCurMaxWidth
< 1)
674 bool bChanged
= false;
675 for (auto& rItem
: mpImpl
->maItemList
)
677 tools::Long nNewWidth
= GetTextWidth(rItem
.GetRenderText());
678 if (mnCurMaxWidth
&& (nNewWidth
> mnCurMaxWidth
))
680 rItem
.mbShort
= true;
681 nNewWidth
= mnCurMaxWidth
;
685 rItem
.mbShort
= false;
688 // Padding is dependent on font height - bigger font = bigger padding
689 tools::Long nFontWidth
= aFont
.GetFontHeight();
692 nNewWidth
+= nFontWidth
* 2;
694 if (rItem
.mnWidth
!= nNewWidth
)
696 rItem
.mnWidth
= nNewWidth
;
697 if (!rItem
.maRect
.IsEmpty())
701 mbSizeFormat
= false;
706 void TabBar::ImplFormat()
713 tools::Long x
= mnOffX
;
715 const size_t nItemListSize
= mpImpl
->maItemList
.size();
716 for (size_t nItemIndex
= 0; nItemIndex
< nItemListSize
; nItemIndex
++)
718 auto& rItem
= mpImpl
->maItemList
[nItemIndex
];
720 // At all non-visible tabs an empty rectangle is set
721 if ((nItemIndex
+ 1 < mnFirstPos
) || (x
> mnLastOffX
))
722 rItem
.maRect
.SetEmpty();
725 // Slightly before the tab before the first visible page
726 // should also be visible
727 if (nItemIndex
+ 1 == mnFirstPos
)
729 rItem
.maRect
.SetLeft(x
- rItem
.mnWidth
);
733 rItem
.maRect
.SetLeft(x
);
736 rItem
.maRect
.SetRight(x
);
737 rItem
.maRect
.SetBottom(maWinSize
.Height() - 1);
741 tools::Long nNewLeft
= mnOffX
+ mnLastOffX
- rItem
.maRect
.Right();
742 tools::Long nNewRight
= mnOffX
+ mnLastOffX
- rItem
.maRect
.Left();
743 rItem
.maRect
.SetRight(nNewRight
);
744 rItem
.maRect
.SetLeft(nNewLeft
);
751 // enable/disable button
752 ImplEnableControls();
755 sal_uInt16
TabBar::ImplGetLastFirstPos()
757 sal_uInt16 nCount
= mpImpl
->getItemSize();
758 if (!nCount
|| mbSizeFormat
|| mbFormat
)
761 sal_uInt16 nLastFirstPos
= nCount
- 1;
762 tools::Long nWinWidth
= mnLastOffX
- mnOffX
- ADDNEWPAGE_AREAWIDTH
;
763 tools::Long nWidth
= mpImpl
->maItemList
[nLastFirstPos
].mnWidth
;
765 while (nLastFirstPos
&& (nWidth
< nWinWidth
))
768 nWidth
+= mpImpl
->maItemList
[nLastFirstPos
].mnWidth
;
770 if ((nLastFirstPos
!= static_cast<sal_uInt16
>(mpImpl
->maItemList
.size() - 1)) && (nWidth
> nWinWidth
))
772 return nLastFirstPos
;
775 IMPL_LINK(TabBar
, ContextMenuHdl
, const CommandEvent
&, rCommandEvent
, void)
777 maScrollAreaContextHdl
.Call(rCommandEvent
);
780 IMPL_LINK(TabBar
, MousePressHdl
, const MouseEvent
&, rMouseEvent
, bool)
782 if (rMouseEvent
.IsRight())
783 ContextMenuHdl(CommandEvent(rMouseEvent
.GetPosPixel(), CommandEventId::ContextMenu
, true));
787 void TabBar::ImplInitControls()
789 if (mnWinStyle
& WB_SIZEABLE
)
791 if (!mpImpl
->mpSizer
)
793 mpImpl
->mpSizer
.disposeAndReset(VclPtr
<ImplTabSizer
>::Create( this, mnWinStyle
& (WB_DRAG
| WB_3DLOOK
)));
795 mpImpl
->mpSizer
->Show();
799 mpImpl
->mpSizer
.disposeAndClear();
802 mpImpl
->mxButtonBox
.disposeAndReset(VclPtr
<TabButtons
>::Create(this, mbSheets
));
804 Link
<const CommandEvent
&, void> aContextLink
= LINK( this, TabBar
, ContextMenuHdl
);
806 if (mnWinStyle
& WB_INSERTTAB
)
808 Link
<weld::Button
&,void> aLink
= LINK(this, TabBar
, ImplAddClickHandler
);
809 mpImpl
->mxButtonBox
->m_xAddRepeater
= std::make_shared
<weld::ButtonPressRepeater
>(
810 *mpImpl
->mxButtonBox
->m_xAddButton
, aLink
, aContextLink
);
811 mpImpl
->mxButtonBox
->m_xAddButton
->show();
814 Link
<weld::Button
&,void> aLink
= LINK( this, TabBar
, ImplClickHdl
);
816 if (mnWinStyle
& (WB_MINSCROLL
| WB_SCROLL
))
818 mpImpl
->mxButtonBox
->m_xPrevRepeater
= std::make_shared
<weld::ButtonPressRepeater
>(
819 *mpImpl
->mxButtonBox
->m_xPrevButton
, aLink
, aContextLink
);
820 mpImpl
->mxButtonBox
->m_xPrevButton
->show();
821 mpImpl
->mxButtonBox
->m_xNextRepeater
= std::make_shared
<weld::ButtonPressRepeater
>(
822 *mpImpl
->mxButtonBox
->m_xNextButton
, aLink
, aContextLink
);
823 mpImpl
->mxButtonBox
->m_xNextButton
->show();
826 if (mnWinStyle
& WB_SCROLL
)
828 Link
<const MouseEvent
&, bool> aBtnContextLink
= LINK(this, TabBar
, MousePressHdl
);
830 mpImpl
->mxButtonBox
->m_xFirstButton
->connect_clicked(aLink
);
831 mpImpl
->mxButtonBox
->m_xFirstButton
->connect_mouse_press(aBtnContextLink
);
832 mpImpl
->mxButtonBox
->m_xFirstButton
->show();
833 mpImpl
->mxButtonBox
->m_xLastButton
->connect_clicked(aLink
);
834 mpImpl
->mxButtonBox
->m_xLastButton
->connect_mouse_press(aBtnContextLink
);
835 mpImpl
->mxButtonBox
->m_xLastButton
->show();
838 mpImpl
->mxButtonBox
->Show();
841 void TabBar::ImplEnableControls()
843 if (mbSizeFormat
|| mbFormat
)
846 // enable/disable buttons
847 bool bEnableBtn
= mbScrollAlwaysEnabled
|| mnFirstPos
> 0;
848 mpImpl
->mxButtonBox
->m_xFirstButton
->set_sensitive(bEnableBtn
);
849 mpImpl
->mxButtonBox
->m_xPrevButton
->set_sensitive(bEnableBtn
);
850 if (!bEnableBtn
&& mpImpl
->mxButtonBox
->m_xPrevRepeater
)
851 mpImpl
->mxButtonBox
->m_xPrevRepeater
->Stop();
852 bEnableBtn
= mbScrollAlwaysEnabled
|| mnFirstPos
< ImplGetLastFirstPos();
853 mpImpl
->mxButtonBox
->m_xLastButton
->set_sensitive(bEnableBtn
);
854 mpImpl
->mxButtonBox
->m_xNextButton
->set_sensitive(bEnableBtn
);
855 if (!bEnableBtn
&& mpImpl
->mxButtonBox
->m_xNextRepeater
)
856 mpImpl
->mxButtonBox
->m_xNextRepeater
->Stop();
859 void TabBar::SetScrollAlwaysEnabled(bool bScrollAlwaysEnabled
)
861 mbScrollAlwaysEnabled
= bScrollAlwaysEnabled
;
862 ImplEnableControls();
865 void TabBar::ImplShowPage( sal_uInt16 nPos
)
867 if (nPos
>= mpImpl
->getItemSize())
871 tools::Long nWidth
= GetOutputSizePixel().Width();
873 auto& rItem
= mpImpl
->maItemList
[nPos
];
874 if (nPos
< mnFirstPos
)
875 SetFirstPageId( rItem
.mnId
);
876 else if (rItem
.maRect
.Right() > nWidth
)
878 while (rItem
.maRect
.Right() > nWidth
)
880 sal_uInt16 nNewPos
= mnFirstPos
+ 1;
881 SetFirstPageId(GetPageId(nNewPos
));
883 if (nNewPos
!= mnFirstPos
)
889 IMPL_LINK( TabBar
, ImplClickHdl
, weld::Button
&, rBtn
, void )
891 if (&rBtn
!= mpImpl
->mxButtonBox
->m_xFirstButton
.get() && &rBtn
!= mpImpl
->mxButtonBox
->m_xLastButton
.get())
893 if ((GetPointerState().mnState
& (MOUSE_LEFT
| MOUSE_MIDDLE
| MOUSE_RIGHT
)) == 0)
895 // like tdf#149482 if we didn't see a mouse up, but find that the mouse is no
896 // longer pressed at this point, then bail
897 mpImpl
->mxButtonBox
->m_xPrevRepeater
->Stop();
898 mpImpl
->mxButtonBox
->m_xNextRepeater
->Stop();
905 sal_uInt16 nNewPos
= mnFirstPos
;
907 if (&rBtn
== mpImpl
->mxButtonBox
->m_xFirstButton
.get() || (&rBtn
== mpImpl
->mxButtonBox
->m_xPrevButton
.get() &&
908 mpImpl
->mxButtonBox
->m_xPrevRepeater
->IsModKeyPressed()))
912 else if (&rBtn
== mpImpl
->mxButtonBox
->m_xLastButton
.get() || (&rBtn
== mpImpl
->mxButtonBox
->m_xNextButton
.get() &&
913 mpImpl
->mxButtonBox
->m_xNextRepeater
->IsModKeyPressed()))
915 sal_uInt16 nCount
= GetPageCount();
917 nNewPos
= nCount
- 1;
919 else if (&rBtn
== mpImpl
->mxButtonBox
->m_xPrevButton
.get())
922 nNewPos
= mnFirstPos
- 1;
924 else if (&rBtn
== mpImpl
->mxButtonBox
->m_xNextButton
.get())
926 sal_uInt16 nCount
= GetPageCount();
927 if (mnFirstPos
< nCount
)
928 nNewPos
= mnFirstPos
+1;
935 if (nNewPos
!= mnFirstPos
)
936 SetFirstPageId(GetPageId(nNewPos
));
939 IMPL_LINK_NOARG(TabBar
, ImplAddClickHandler
, weld::Button
&, void)
941 if ((GetPointerState().mnState
& (MOUSE_LEFT
| MOUSE_MIDDLE
| MOUSE_RIGHT
)) == 0)
943 // tdf#149482 if we didn't see a mouse up, but find that the mouse is no
944 // longer pressed at this point, then bail
945 mpImpl
->mxButtonBox
->m_xAddRepeater
->Stop();
953 void TabBar::MouseMove(const MouseEvent
& rMEvt
)
955 if (rMEvt
.IsLeaveWindow())
958 Window::MouseMove(rMEvt
);
961 void TabBar::MouseButtonDown(const MouseEvent
& rMEvt
)
963 // Only terminate EditMode and do not execute click
964 // if clicked inside our window,
971 sal_uInt16 nSelId
= GetPageId(rMEvt
.GetPosPixel());
975 Window::MouseButtonDown(rMEvt
);
976 if (nSelId
> 0 && nSelId
!= mnCurPageId
)
978 if (ImplDeactivatePage())
980 SetCurPageId(nSelId
);
990 if (rMEvt
.IsMod2() && mbAutoEditMode
&& nSelId
)
992 if (StartEditMode(nSelId
))
996 if ((rMEvt
.GetMode() & (MouseEventModifiers::MULTISELECT
| MouseEventModifiers::RANGESELECT
)) && (rMEvt
.GetClicks() == 1))
1000 sal_uInt16 nPos
= GetPagePos(nSelId
);
1002 bool bSelectTab
= false;
1004 if ((rMEvt
.GetMode() & MouseEventModifiers::MULTISELECT
) && (mnWinStyle
& WB_MULTISELECT
))
1006 if (nSelId
!= mnCurPageId
)
1008 SelectPage(nSelId
, !IsPageSelected(nSelId
));
1012 else if (mnWinStyle
& (WB_MULTISELECT
| WB_RANGESELECT
))
1017 sal_uInt16 nCurPos
= GetPagePos(mnCurPageId
);
1018 if (nPos
<= nCurPos
)
1020 // Deselect all tabs till the clicked tab
1021 // and select all tabs from the clicked tab
1022 // 'till the actual position
1026 auto& rItem
= mpImpl
->maItemList
[n
];
1027 bSelect
= n
>= nPos
;
1029 if (rItem
.mbSelect
!= bSelect
)
1031 rItem
.mbSelect
= bSelect
;
1032 if (!rItem
.maRect
.IsEmpty())
1033 Invalidate(rItem
.maRect
);
1040 if (nPos
>= nCurPos
)
1042 // Select all tabs from the actual position till the clicked tab
1043 // and deselect all tabs from the actual position
1044 // till the last tab
1045 sal_uInt16 nCount
= mpImpl
->getItemSize();
1049 auto& rItem
= mpImpl
->maItemList
[n
];
1051 bSelect
= n
<= nPos
;
1053 if (rItem
.mbSelect
!= bSelect
)
1055 rItem
.mbSelect
= bSelect
;
1056 if (!rItem
.maRect
.IsEmpty())
1057 Invalidate(rItem
.maRect
);
1065 // scroll the selected tab if required
1078 else if (rMEvt
.GetClicks() == 2)
1080 // call double-click-handler if required
1081 if (!rMEvt
.GetModifier() && (!nSelId
|| (nSelId
== mnCurPageId
)))
1083 sal_uInt16 nOldCurId
= mnCurPageId
;
1084 mnCurPageId
= nSelId
;
1086 // check, as actual page could be switched inside
1087 // the doubleclick-handler
1088 if (mnCurPageId
== nSelId
)
1089 mnCurPageId
= nOldCurId
;
1098 // execute Select if not actual page
1099 if (nSelId
!= mnCurPageId
)
1101 sal_uInt16 nPos
= GetPagePos(nSelId
);
1102 auto& rItem
= mpImpl
->maItemList
[nPos
];
1104 if (!rItem
.mbSelect
)
1107 bool bUpdate
= false;
1108 if (IsReallyVisible() && IsUpdateMode())
1111 // deselect all selected items
1112 for (auto& xItem
: mpImpl
->maItemList
)
1114 if (xItem
.mbSelect
|| (xItem
.mnId
== mnCurPageId
))
1116 xItem
.mbSelect
= false;
1118 Invalidate(xItem
.maRect
);
1123 if (ImplDeactivatePage())
1125 SetCurPageId(nSelId
);
1138 Window::MouseButtonDown(rMEvt
);
1141 void TabBar::MouseButtonUp(const MouseEvent
& rMEvt
)
1144 Window::MouseButtonUp(rMEvt
);
1147 void TabBar::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& rect
)
1149 if (rRenderContext
.IsNativeControlSupported(ControlType::WindowBackground
,ControlPart::Entire
))
1151 rRenderContext
.DrawNativeControl(ControlType::WindowBackground
,ControlPart::Entire
,rect
,
1152 ControlState::ENABLED
,ImplControlValue(0),OUString());
1154 // calculate items and emit
1155 sal_uInt16 nItemCount
= mpImpl
->getItemSize();
1161 Color aFaceColor
, aSelectColor
, aFaceTextColor
, aSelectTextColor
;
1162 const StyleSettings
& rStyleSettings
= rRenderContext
.GetSettings().GetStyleSettings();
1163 ImplGetColors(rStyleSettings
, aFaceColor
, aFaceTextColor
, aSelectColor
, aSelectTextColor
);
1165 rRenderContext
.Push(vcl::PushFlags::FONT
| vcl::PushFlags::CLIPREGION
);
1166 rRenderContext
.SetClipRegion(vcl::Region(GetPageArea()));
1169 vcl::Font aFont
= rRenderContext
.GetFont();
1170 vcl::Font aLightFont
= aFont
;
1171 aLightFont
.SetWeight(WEIGHT_NORMAL
);
1173 TabDrawer
aDrawer(rRenderContext
);
1175 aDrawer
.setSelectedFillColor(aSelectColor
);
1177 // Now, start drawing the tabs.
1179 ImplTabBarItem
* pItem
= ImplGetLastTabBarItem(nItemCount
);
1180 ImplTabBarItem
* pCurItem
= nullptr;
1183 // emit CurrentItem last, as it covers all others
1184 if (!pCurItem
&& (pItem
->mnId
== mnCurPageId
))
1193 bool bCurrent
= pItem
== pCurItem
;
1195 if (!pItem
->maRect
.IsEmpty())
1197 tools::Rectangle aRect
= pItem
->maRect
;
1198 bool bSelected
= pItem
->IsSelected(pCurItem
);
1199 // We disable custom background color in high contrast mode.
1200 bool bCustomBgColor
= !pItem
->IsDefaultTabBgColor() && !rStyleSettings
.GetHighContrastMode();
1201 OUString aText
= pItem
->mbShort
?
1202 rRenderContext
.GetEllipsisString(pItem
->GetRenderText(), mnCurMaxWidth
) :
1203 pItem
->GetRenderText();
1205 aDrawer
.setRect(aRect
);
1206 aDrawer
.setSelected(bSelected
);
1207 aDrawer
.setCustomColored(bCustomBgColor
);
1208 aDrawer
.setEnabled(true);
1209 aDrawer
.setCustomColor(pItem
->maTabBgColor
);
1210 aDrawer
.mbProtect
= pItem
->mbProtect
;
1213 // currently visible sheet is drawn using a bold font
1215 rRenderContext
.SetFont(aFont
);
1217 rRenderContext
.SetFont(aLightFont
);
1219 // Set the correct FillInBrush depending on status
1222 rRenderContext
.SetTextColor(aSelectTextColor
);
1223 else if (bCustomBgColor
)
1224 rRenderContext
.SetTextColor(pItem
->maTabTextColor
);
1226 rRenderContext
.SetTextColor(aFaceTextColor
);
1228 // Special display of tab name depending on page bits
1230 if (pItem
->mnBits
& TabBarPageBits::Blue
)
1232 rRenderContext
.SetTextColor(COL_LIGHTBLUE
);
1234 if (pItem
->mnBits
& TabBarPageBits::Italic
)
1236 vcl::Font aSpecialFont
= rRenderContext
.GetFont();
1237 aSpecialFont
.SetItalic(FontItalic::ITALIC_NORMAL
);
1238 rRenderContext
.SetFont(aSpecialFont
);
1240 if (pItem
->mnBits
& TabBarPageBits::Underline
)
1242 vcl::Font aSpecialFont
= rRenderContext
.GetFont();
1243 aSpecialFont
.SetUnderline(LINESTYLE_SINGLE
);
1244 rRenderContext
.SetFont(aSpecialFont
);
1247 aDrawer
.drawText(aText
);
1251 rRenderContext
.SetLineColor();
1252 rRenderContext
.SetFillColor(aSelectColor
);
1253 aDrawer
.drawOverTopBorder();
1270 rRenderContext
.Pop();
1273 void TabBar::Resize()
1275 Size aNewSize
= GetOutputSizePixel();
1277 tools::Long nSizerWidth
= 0;
1280 if ( mpImpl
->mpSizer
)
1282 Size aSizerSize
= mpImpl
->mpSizer
->GetSizePixel();
1283 Point
aNewSizerPos( mbMirrored
? 0 : (aNewSize
.Width()-aSizerSize
.Width()), 0 );
1284 Size
aNewSizerSize( aSizerSize
.Width(), aNewSize
.Height() );
1285 mpImpl
->mpSizer
->SetPosSizePixel( aNewSizerPos
, aNewSizerSize
);
1286 nSizerWidth
= aSizerSize
.Width();
1289 // order the scroll buttons
1290 tools::Long
const nHeight
= aNewSize
.Height();
1291 // adapt font height?
1292 ImplInitSettings( true, false );
1294 mpImpl
->mxButtonBox
->AdaptToHeight(nHeight
);
1295 Size
const aBtnsSize(mpImpl
->mxButtonBox
->get_preferred_size().Width(), nHeight
);
1296 Point
aPos(mbMirrored
? (aNewSize
.Width() - aBtnsSize
.Width()) : 0, 0);
1297 mpImpl
->mxButtonBox
->SetPosSizePixel(aPos
, aBtnsSize
);
1298 auto nButtonWidth
= aBtnsSize
.Width();
1301 maWinSize
= aNewSize
;
1305 mnOffX
= nSizerWidth
;
1306 mnLastOffX
= maWinSize
.Width() - nButtonWidth
- 1;
1310 mnOffX
= nButtonWidth
;
1311 mnLastOffX
= maWinSize
.Width() - nSizerWidth
- 1;
1315 mbSizeFormat
= true;
1316 if ( IsReallyVisible() )
1318 if ( ImplCalcWidth() )
1323 // Ensure as many tabs as possible are visible:
1324 sal_uInt16 nLastFirstPos
= ImplGetLastFirstPos();
1325 if ( mnFirstPos
> nLastFirstPos
)
1327 mnFirstPos
= nLastFirstPos
;
1331 // Ensure the currently selected page is visible
1332 ImplShowPage(GetPagePos(mnCurPageId
));
1337 // enable/disable button
1338 ImplEnableControls();
1341 bool TabBar::PreNotify(NotifyEvent
& rNEvt
)
1343 if (rNEvt
.GetType() == NotifyEventType::COMMAND
)
1345 if (rNEvt
.GetCommandEvent()->GetCommand() == CommandEventId::Wheel
)
1347 const CommandWheelData
* pData
= rNEvt
.GetCommandEvent()->GetWheelData();
1348 sal_uInt16 nNewPos
= mnFirstPos
;
1349 if (pData
->GetNotchDelta() > 0)
1352 nNewPos
= mnFirstPos
- 1;
1354 else if (pData
->GetNotchDelta() < 0)
1356 sal_uInt16 nCount
= GetPageCount();
1357 if (mnFirstPos
< nCount
)
1358 nNewPos
= mnFirstPos
+ 1;
1360 if (nNewPos
!= mnFirstPos
)
1361 SetFirstPageId(GetPageId(nNewPos
));
1364 return Window::PreNotify(rNEvt
);
1367 void TabBar::RequestHelp(const HelpEvent
& rHEvt
)
1369 sal_uInt16 nItemId
= GetPageId(ScreenToOutputPixel(rHEvt
.GetMousePosPixel()));
1372 if (rHEvt
.GetMode() & HelpEventMode::BALLOON
)
1374 OUString aStr
= GetHelpText(nItemId
);
1375 if (!aStr
.isEmpty())
1377 tools::Rectangle aItemRect
= GetPageRect(nItemId
);
1378 Point aPt
= OutputToScreenPixel(aItemRect
.TopLeft());
1379 aItemRect
.SetLeft( aPt
.X() );
1380 aItemRect
.SetTop( aPt
.Y() );
1381 aPt
= OutputToScreenPixel(aItemRect
.BottomRight());
1382 aItemRect
.SetRight( aPt
.X() );
1383 aItemRect
.SetBottom( aPt
.Y() );
1384 Help::ShowBalloon(this, aItemRect
.Center(), aItemRect
, aStr
);
1389 // show text for quick- or balloon-help
1390 // if this is isolated or not fully visible
1391 if (rHEvt
.GetMode() & (HelpEventMode::QUICK
| HelpEventMode::BALLOON
))
1393 sal_uInt16 nPos
= GetPagePos(nItemId
);
1394 auto& rItem
= mpImpl
->maItemList
[nPos
];
1395 if (rItem
.mbShort
|| (rItem
.maRect
.Right() - 5 > mnLastOffX
))
1397 tools::Rectangle aItemRect
= GetPageRect(nItemId
);
1398 Point aPt
= OutputToScreenPixel(aItemRect
.TopLeft());
1399 aItemRect
.SetLeft( aPt
.X() );
1400 aItemRect
.SetTop( aPt
.Y() );
1401 aPt
= OutputToScreenPixel(aItemRect
.BottomRight());
1402 aItemRect
.SetRight( aPt
.X() );
1403 aItemRect
.SetBottom( aPt
.Y() );
1404 OUString aStr
= mpImpl
->maItemList
[nPos
].maText
;
1405 if (!aStr
.isEmpty())
1407 if (rHEvt
.GetMode() & HelpEventMode::BALLOON
)
1408 Help::ShowBalloon(this, aItemRect
.Center(), aItemRect
, aStr
);
1410 Help::ShowQuickHelp(this, aItemRect
, aStr
);
1417 Window::RequestHelp(rHEvt
);
1420 void TabBar::StateChanged(StateChangedType nType
)
1422 Window::StateChanged(nType
);
1424 if (nType
== StateChangedType::InitShow
)
1426 if ( (mbSizeFormat
|| mbFormat
) && !mpImpl
->maItemList
.empty() )
1429 else if (nType
== StateChangedType::Zoom
||
1430 nType
== StateChangedType::ControlFont
)
1432 ImplInitSettings(true, false);
1435 else if (nType
== StateChangedType::ControlForeground
)
1437 else if (nType
== StateChangedType::ControlBackground
)
1439 ImplInitSettings(false, true);
1442 else if (nType
== StateChangedType::Mirroring
)
1444 bool bIsRTLEnabled
= IsRTLEnabled();
1445 // reacts on calls of EnableRTL, have to mirror all child controls
1446 if (mpImpl
->mpSizer
)
1447 mpImpl
->mpSizer
->EnableRTL(bIsRTLEnabled
);
1448 if (mpImpl
->mxButtonBox
)
1450 mpImpl
->mxButtonBox
->m_xFirstButton
->set_direction(bIsRTLEnabled
);
1451 mpImpl
->mxButtonBox
->m_xPrevButton
->set_direction(bIsRTLEnabled
);
1452 mpImpl
->mxButtonBox
->m_xNextButton
->set_direction(bIsRTLEnabled
);
1453 mpImpl
->mxButtonBox
->m_xLastButton
->set_direction(bIsRTLEnabled
);
1454 mpImpl
->mxButtonBox
->m_xAddButton
->set_direction(bIsRTLEnabled
);
1458 weld::Entry
& rEntry
= mpImpl
->mxEdit
->get_widget();
1459 rEntry
.set_direction(bIsRTLEnabled
);
1464 void TabBar::DataChanged(const DataChangedEvent
& rDCEvt
)
1466 Window::DataChanged(rDCEvt
);
1468 if (rDCEvt
.GetType() == DataChangedEventType::FONTS
1469 || rDCEvt
.GetType() == DataChangedEventType::FONTSUBSTITUTION
1470 || (rDCEvt
.GetType() == DataChangedEventType::SETTINGS
1471 && rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
))
1473 ImplInitSettings(true, true);
1478 void TabBar::ImplSelect()
1481 CallEventListeners(VclEventId::TabbarPageSelected
, reinterpret_cast<void*>(sal::static_int_cast
<sal_IntPtr
>(mnCurPageId
)));
1484 void TabBar::Select()
1486 maSelectHdl
.Call(this);
1489 void TabBar::DoubleClick()
1493 void TabBar::Split()
1495 maSplitHdl
.Call(this);
1498 void TabBar::ImplActivatePage()
1502 CallEventListeners(VclEventId::TabbarPageActivated
, reinterpret_cast<void*>(sal::static_int_cast
<sal_IntPtr
>(mnCurPageId
)));
1505 void TabBar::ActivatePage()
1508 bool TabBar::ImplDeactivatePage()
1510 bool bRet
= DeactivatePage();
1512 CallEventListeners(VclEventId::TabbarPageDeactivated
, reinterpret_cast<void*>(sal::static_int_cast
<sal_IntPtr
>(mnCurPageId
)));
1517 void TabBar::ImplPrePaint()
1519 sal_uInt16 nItemCount
= mpImpl
->getItemSize();
1523 // tabbar should be formatted
1526 // assure the actual tabpage becomes visible at first format
1530 mbFirstFormat
= false;
1532 if (!mnCurPageId
|| (mnFirstPos
!= 0) || mbDropPos
)
1535 auto& rItem
= mpImpl
->maItemList
[GetPagePos(mnCurPageId
)];
1536 if (rItem
.maRect
.IsEmpty())
1538 // set mbDropPos (or misuse) to prevent Invalidate()
1540 SetFirstPageId(mnCurPageId
);
1542 if (mnFirstPos
!= 0)
1547 ImplTabBarItem
* TabBar::ImplGetLastTabBarItem( sal_uInt16 nItemCount
)
1549 // find last visible entry
1550 sal_uInt16 n
= mnFirstPos
+ 1;
1551 if (n
>= nItemCount
)
1553 ImplTabBarItem
* pItem
= seek(n
);
1556 if (!pItem
->maRect
.IsEmpty())
1565 // draw all tabs (from back to front and actual last)
1568 else if (n
>= nItemCount
)
1574 bool TabBar::DeactivatePage()
1579 bool TabBar::StartRenaming()
1584 TabBarAllowRenamingReturnCode
TabBar::AllowRenaming()
1586 return TABBAR_RENAMING_YES
;
1589 void TabBar::EndRenaming()
1593 void TabBar::Mirror()
1598 void TabBar::AddTabClick()
1603 void TabBar::InsertPage(sal_uInt16 nPageId
, const OUString
& rText
,
1604 TabBarPageBits nBits
, sal_uInt16 nPos
)
1606 assert (nPageId
&& "TabBar::InsertPage(): PageId must not be 0");
1607 assert ((GetPagePos(nPageId
) == PAGE_NOT_FOUND
) && "TabBar::InsertPage(): Page already exists");
1608 assert ((nBits
<= TPB_DISPLAY_NAME_ALLFLAGS
) && "TabBar::InsertPage(): Invalid flag set in nBits");
1610 // create PageItem and insert in the item list
1611 ImplTabBarItem
aItem( nPageId
, rText
, nBits
);
1612 if (nPos
< mpImpl
->maItemList
.size())
1614 auto it
= mpImpl
->maItemList
.begin();
1616 mpImpl
->maItemList
.insert(it
, aItem
);
1620 mpImpl
->maItemList
.push_back(aItem
);
1622 mbSizeFormat
= true;
1624 // set CurPageId if required
1626 mnCurPageId
= nPageId
;
1629 if (IsReallyVisible() && IsUpdateMode())
1632 CallEventListeners(VclEventId::TabbarPageInserted
, reinterpret_cast<void*>(sal::static_int_cast
<sal_IntPtr
>(nPageId
)));
1635 Color
TabBar::GetTabBgColor(sal_uInt16 nPageId
) const
1637 sal_uInt16 nPos
= GetPagePos(nPageId
);
1639 if (nPos
!= PAGE_NOT_FOUND
)
1640 return mpImpl
->maItemList
[nPos
].maTabBgColor
;
1645 void TabBar::SetTabBgColor(sal_uInt16 nPageId
, const Color
& aTabBgColor
)
1647 sal_uInt16 nPos
= GetPagePos(nPageId
);
1648 if (nPos
== PAGE_NOT_FOUND
)
1651 auto& rItem
= mpImpl
->maItemList
[nPos
];
1652 if (aTabBgColor
!= COL_AUTO
)
1654 rItem
.maTabBgColor
= aTabBgColor
;
1655 if (aTabBgColor
.GetLuminance() <= 128) //Do not use aTabBgColor.IsDark(), because that threshold is way too low...
1656 rItem
.maTabTextColor
= COL_WHITE
;
1658 rItem
.maTabTextColor
= COL_BLACK
;
1662 rItem
.maTabBgColor
= COL_AUTO
;
1663 rItem
.maTabTextColor
= COL_AUTO
;
1667 void TabBar::RemovePage(sal_uInt16 nPageId
)
1669 sal_uInt16 nPos
= GetPagePos(nPageId
);
1672 if (nPos
== PAGE_NOT_FOUND
)
1675 if (mnCurPageId
== nPageId
)
1678 // check if first visible page should be moved
1679 if (mnFirstPos
> nPos
)
1683 auto it
= mpImpl
->maItemList
.begin();
1685 mpImpl
->maItemList
.erase(it
);
1688 if (IsReallyVisible() && IsUpdateMode())
1691 CallEventListeners(VclEventId::TabbarPageRemoved
, reinterpret_cast<void*>(sal::static_int_cast
<sal_IntPtr
>(nPageId
)));
1694 void TabBar::MovePage(sal_uInt16 nPageId
, sal_uInt16 nNewPos
)
1696 sal_uInt16 nPos
= GetPagePos(nPageId
);
1697 Pair
aPair(nPos
, nNewPos
);
1702 if (nPos
== nNewPos
)
1706 if (nPos
== PAGE_NOT_FOUND
)
1709 // move tabbar item in the list
1710 auto it
= mpImpl
->maItemList
.begin();
1712 ImplTabBarItem aItem
= std::move(*it
);
1713 mpImpl
->maItemList
.erase(it
);
1714 if (nNewPos
< mpImpl
->maItemList
.size())
1716 it
= mpImpl
->maItemList
.begin();
1718 mpImpl
->maItemList
.insert(it
, aItem
);
1722 mpImpl
->maItemList
.push_back(aItem
);
1726 if (IsReallyVisible() && IsUpdateMode())
1729 CallEventListeners( VclEventId::TabbarPageMoved
, static_cast<void*>(&aPair
) );
1732 void TabBar::Clear()
1735 mpImpl
->maItemList
.clear();
1737 // remove items from the list
1738 mbSizeFormat
= true;
1741 maCurrentItemList
= 0;
1744 if (IsReallyVisible() && IsUpdateMode())
1747 CallEventListeners(VclEventId::TabbarPageRemoved
, reinterpret_cast<void*>(sal::static_int_cast
<sal_IntPtr
>(PAGE_NOT_FOUND
)));
1750 bool TabBar::IsPageEnabled(sal_uInt16 nPageId
) const
1754 sal_uInt16 nPos
= GetPagePos(nPageId
);
1756 return nPos
!= PAGE_NOT_FOUND
;
1759 void TabBar::SetPageBits(sal_uInt16 nPageId
, TabBarPageBits nBits
)
1761 sal_uInt16 nPos
= GetPagePos(nPageId
);
1763 if (nPos
== PAGE_NOT_FOUND
)
1766 auto& rItem
= mpImpl
->maItemList
[nPos
];
1768 if (rItem
.mnBits
!= nBits
)
1770 rItem
.mnBits
= nBits
;
1773 if (IsReallyVisible() && IsUpdateMode())
1774 Invalidate(rItem
.maRect
);
1778 TabBarPageBits
TabBar::GetPageBits(sal_uInt16 nPageId
) const
1780 sal_uInt16 nPos
= GetPagePos(nPageId
);
1782 if (nPos
!= PAGE_NOT_FOUND
)
1783 return mpImpl
->maItemList
[nPos
].mnBits
;
1785 return TabBarPageBits::NONE
;
1788 sal_uInt16
TabBar::GetPageCount() const
1790 return mpImpl
->getItemSize();
1793 sal_uInt16
TabBar::GetPageId(sal_uInt16 nPos
) const
1795 return nPos
< mpImpl
->maItemList
.size() ? mpImpl
->maItemList
[nPos
].mnId
: 0;
1798 sal_uInt16
TabBar::GetPagePos(sal_uInt16 nPageId
) const
1800 for (size_t i
= 0; i
< mpImpl
->maItemList
.size(); ++i
)
1802 if (mpImpl
->maItemList
[i
].mnId
== nPageId
)
1804 return static_cast<sal_uInt16
>(i
);
1807 return PAGE_NOT_FOUND
;
1810 sal_uInt16
TabBar::GetPageId(const Point
& rPos
) const
1812 for (const auto& rItem
: mpImpl
->maItemList
)
1814 if (rItem
.maRect
.Contains(rPos
))
1821 tools::Rectangle
TabBar::GetPageRect(sal_uInt16 nPageId
) const
1823 sal_uInt16 nPos
= GetPagePos(nPageId
);
1825 if (nPos
!= PAGE_NOT_FOUND
)
1826 return mpImpl
->maItemList
[nPos
].maRect
;
1828 return tools::Rectangle();
1831 void TabBar::SetCurPageId(sal_uInt16 nPageId
)
1833 sal_uInt16 nPos
= GetPagePos(nPageId
);
1835 // do nothing if item does not exit
1836 if (nPos
== PAGE_NOT_FOUND
)
1839 // do nothing if the actual page did not change
1840 if (nPageId
== mnCurPageId
)
1844 bool bUpdate
= false;
1845 if (IsReallyVisible() && IsUpdateMode())
1848 auto& rItem
= mpImpl
->maItemList
[nPos
];
1849 ImplTabBarItem
* pOldItem
;
1852 pOldItem
= &mpImpl
->maItemList
[GetPagePos(mnCurPageId
)];
1856 // deselect previous page if page was not selected, if this is the
1857 // only selected page
1858 if (!rItem
.mbSelect
&& pOldItem
)
1860 sal_uInt16 nSelPageCount
= GetSelectPageCount();
1861 if (nSelPageCount
== 1)
1862 pOldItem
->mbSelect
= false;
1863 rItem
.mbSelect
= true;
1866 mnCurPageId
= nPageId
;
1869 // assure the actual page becomes visible
1870 if (IsReallyVisible())
1872 if (nPos
< mnFirstPos
)
1873 SetFirstPageId(nPageId
);
1876 // calculate visible width
1877 tools::Long nWidth
= mnLastOffX
;
1878 if (nWidth
> ADDNEWPAGE_AREAWIDTH
)
1879 nWidth
-= ADDNEWPAGE_AREAWIDTH
;
1881 if (rItem
.maRect
.IsEmpty())
1884 while ((mbMirrored
? (rItem
.maRect
.Left() < mnOffX
) : (rItem
.maRect
.Right() > nWidth
)) ||
1885 rItem
.maRect
.IsEmpty())
1887 sal_uInt16 nNewPos
= mnFirstPos
+ 1;
1888 // assure at least the actual tabpages are visible as first tabpage
1889 if (nNewPos
>= nPos
)
1891 SetFirstPageId(nPageId
);
1895 SetFirstPageId(GetPageId(nNewPos
));
1897 // abort if first page is not forwarded
1898 if (nNewPos
!= mnFirstPos
)
1907 Invalidate(rItem
.maRect
);
1909 Invalidate(pOldItem
->maRect
);
1913 void TabBar::MakeVisible(sal_uInt16 nPageId
)
1915 if (!IsReallyVisible())
1918 sal_uInt16 nPos
= GetPagePos(nPageId
);
1920 // do nothing if item does not exist
1921 if (nPos
== PAGE_NOT_FOUND
)
1924 if (nPos
< mnFirstPos
)
1925 SetFirstPageId(nPageId
);
1928 auto& rItem
= mpImpl
->maItemList
[nPos
];
1930 // calculate visible area
1931 tools::Long nWidth
= mnLastOffX
;
1933 if (mbFormat
|| rItem
.maRect
.IsEmpty())
1939 while ((rItem
.maRect
.Right() > nWidth
) ||
1940 rItem
.maRect
.IsEmpty())
1942 sal_uInt16 nNewPos
= mnFirstPos
+1;
1943 // assure at least the actual tabpages are visible as first tabpage
1944 if (nNewPos
>= nPos
)
1946 SetFirstPageId(nPageId
);
1950 SetFirstPageId(GetPageId(nNewPos
));
1952 // abort if first page is not forwarded
1953 if (nNewPos
!= mnFirstPos
)
1959 void TabBar::SetFirstPageId(sal_uInt16 nPageId
)
1961 sal_uInt16 nPos
= GetPagePos(nPageId
);
1963 // return false if item does not exist
1964 if (nPos
== PAGE_NOT_FOUND
)
1967 if (nPos
== mnFirstPos
)
1970 // assure as much pages are visible as possible
1972 sal_uInt16 nLastFirstPos
= ImplGetLastFirstPos();
1974 if (nPos
> nLastFirstPos
)
1975 nNewPos
= nLastFirstPos
;
1979 if (nNewPos
!= mnFirstPos
)
1981 mnFirstPos
= nNewPos
;
1984 // redraw bar (attention: check mbDropPos,
1985 // as if this flag was set, we do not re-paint immediately
1986 if (IsReallyVisible() && IsUpdateMode() && !mbDropPos
)
1991 void TabBar::SelectPage(sal_uInt16 nPageId
, bool bSelect
)
1993 sal_uInt16 nPos
= GetPagePos(nPageId
);
1995 if (nPos
== PAGE_NOT_FOUND
)
1998 auto& rItem
= mpImpl
->maItemList
[nPos
];
2000 if (rItem
.mbSelect
!= bSelect
)
2002 rItem
.mbSelect
= bSelect
;
2005 if (IsReallyVisible() && IsUpdateMode())
2006 Invalidate(rItem
.maRect
);
2010 sal_uInt16
TabBar::GetSelectPageCount() const
2012 sal_uInt16 nSelected
= 0;
2013 for (const auto& rItem
: mpImpl
->maItemList
)
2022 bool TabBar::IsPageSelected(sal_uInt16 nPageId
) const
2024 sal_uInt16 nPos
= GetPagePos(nPageId
);
2025 if (nPos
!= PAGE_NOT_FOUND
)
2026 return mpImpl
->maItemList
[nPos
].mbSelect
;
2031 void TabBar::SetProtectionSymbol(sal_uInt16 nPageId
, bool bProtection
)
2033 sal_uInt16 nPos
= GetPagePos(nPageId
);
2034 if (nPos
!= PAGE_NOT_FOUND
)
2036 if (mpImpl
->maItemList
[nPos
].mbProtect
!= bProtection
)
2038 mpImpl
->maItemList
[nPos
].mbProtect
= bProtection
;
2039 mbSizeFormat
= true; // render text width changes, thus bar width
2042 if (IsReallyVisible() && IsUpdateMode())
2048 bool TabBar::StartEditMode(sal_uInt16 nPageId
)
2050 sal_uInt16 nPos
= GetPagePos( nPageId
);
2051 if (mpImpl
->mxEdit
|| (nPos
== PAGE_NOT_FOUND
) || (mnLastOffX
< 8))
2055 if (StartRenaming())
2061 mpImpl
->mxEdit
.disposeAndReset(VclPtr
<TabBarEdit
>::Create(this));
2062 tools::Rectangle aRect
= GetPageRect( mnEditId
);
2063 tools::Long nX
= aRect
.Left();
2064 tools::Long nWidth
= aRect
.GetWidth();
2065 if (mnEditId
!= GetCurPageId())
2067 if (nX
+ nWidth
> mnLastOffX
)
2068 nWidth
= mnLastOffX
-nX
;
2072 nWidth
= aRect
.GetWidth();
2074 weld::Entry
& rEntry
= mpImpl
->mxEdit
->get_widget();
2075 rEntry
.set_text(GetPageText(mnEditId
));
2076 mpImpl
->mxEdit
->SetPosSizePixel(Point(nX
, aRect
.Top() + mnOffY
+ 1), Size(nWidth
, aRect
.GetHeight() - 3));
2077 vcl::Font aFont
= GetPointFont(*GetOutDev()); // FIXME RenderContext
2079 Color aForegroundColor
;
2080 Color aBackgroundColor
;
2083 Color aFaceTextColor
;
2084 Color aSelectTextColor
;
2086 ImplGetColors(Application::GetSettings().GetStyleSettings(), aFaceColor
, aFaceTextColor
, aSelectColor
, aSelectTextColor
);
2088 if (mnEditId
!= GetCurPageId())
2090 aFont
.SetWeight(WEIGHT_LIGHT
);
2092 if (IsPageSelected(mnEditId
) || mnEditId
== GetCurPageId())
2094 aForegroundColor
= aSelectTextColor
;
2095 aBackgroundColor
= aSelectColor
;
2099 aForegroundColor
= aFaceTextColor
;
2100 aBackgroundColor
= aFaceColor
;
2102 if (GetPageBits( mnEditId
) & TabBarPageBits::Blue
)
2104 aForegroundColor
= COL_LIGHTBLUE
;
2106 rEntry
.set_font(aFont
);
2107 rEntry
.set_font_color(aForegroundColor
);
2108 mpImpl
->mxEdit
->SetControlBackground(aBackgroundColor
);
2109 rEntry
.grab_focus();
2110 rEntry
.select_region(0, -1);
2111 mpImpl
->mxEdit
->Show();
2121 bool TabBar::IsInEditMode() const
2123 return bool(mpImpl
->mxEdit
);
2126 void TabBar::EndEditMode(bool bCancel
)
2128 if (!mpImpl
->mxEdit
)
2133 mbEditCanceled
= bCancel
;
2134 weld::Entry
& rEntry
= mpImpl
->mxEdit
->get_widget();
2135 maEditText
= rEntry
.get_text();
2136 mpImpl
->mxEdit
->SetPostEvent();
2139 TabBarAllowRenamingReturnCode nAllowRenaming
= AllowRenaming();
2140 if (nAllowRenaming
== TABBAR_RENAMING_YES
)
2141 SetPageText(mnEditId
, maEditText
);
2142 else if (nAllowRenaming
== TABBAR_RENAMING_NO
)
2144 else // nAllowRenaming == TABBAR_RENAMING_CANCEL
2145 mbEditCanceled
= true;
2148 // renaming not allowed, then reset edit data
2151 mpImpl
->mxEdit
->ResetPostEvent();
2152 rEntry
.grab_focus();
2156 // close edit and call end hdl
2157 mpImpl
->mxEdit
.disposeAndClear();
2165 mbEditCanceled
= false;
2168 void TabBar::SetMirrored(bool bMirrored
)
2170 if (mbMirrored
!= bMirrored
)
2172 mbMirrored
= bMirrored
;
2173 mbSizeFormat
= true;
2174 ImplInitControls(); // for button images
2175 Resize(); // recalculates control positions
2180 void TabBar::SetEffectiveRTL(bool bRTL
)
2182 SetMirrored( bRTL
!= AllSettings::GetLayoutRTL() );
2185 bool TabBar::IsEffectiveRTL() const
2187 return IsMirrored() != AllSettings::GetLayoutRTL();
2190 void TabBar::SetMaxPageWidth(tools::Long nMaxWidth
)
2192 if (mnMaxPageWidth
!= nMaxWidth
)
2194 mnMaxPageWidth
= nMaxWidth
;
2195 mbSizeFormat
= true;
2198 if (IsReallyVisible() && IsUpdateMode())
2203 void TabBar::SetPageText(sal_uInt16 nPageId
, const OUString
& rText
)
2205 sal_uInt16 nPos
= GetPagePos(nPageId
);
2206 if (nPos
!= PAGE_NOT_FOUND
)
2208 mpImpl
->maItemList
[nPos
].maText
= rText
;
2209 mbSizeFormat
= true;
2212 if (IsReallyVisible() && IsUpdateMode())
2215 CallEventListeners(VclEventId::TabbarPageTextChanged
, reinterpret_cast<void*>(sal::static_int_cast
<sal_IntPtr
>(nPageId
)));
2219 OUString
TabBar::GetPageText(sal_uInt16 nPageId
) const
2221 sal_uInt16 nPos
= GetPagePos(nPageId
);
2222 if (nPos
!= PAGE_NOT_FOUND
)
2223 return mpImpl
->maItemList
[nPos
].maText
;
2227 OUString
TabBar::GetAuxiliaryText(sal_uInt16 nPageId
) const
2229 sal_uInt16 nPos
= GetPagePos(nPageId
);
2230 if (nPos
!= PAGE_NOT_FOUND
)
2231 return mpImpl
->maItemList
[nPos
].maAuxiliaryText
;
2235 void TabBar::SetAuxiliaryText(sal_uInt16 nPageId
, const OUString
& rText
)
2237 sal_uInt16 nPos
= GetPagePos(nPageId
);
2238 if (nPos
!= PAGE_NOT_FOUND
)
2240 mpImpl
->maItemList
[nPos
].maAuxiliaryText
= rText
;
2241 // no redraw bar, no CallEventListener, internal use in LayerTabBar
2245 OUString
TabBar::GetHelpText(sal_uInt16 nPageId
) const
2247 sal_uInt16 nPos
= GetPagePos(nPageId
);
2248 if (nPos
!= PAGE_NOT_FOUND
)
2250 auto& rItem
= mpImpl
->maItemList
[nPos
];
2251 if (rItem
.maHelpText
.isEmpty() && !rItem
.maHelpId
.isEmpty())
2253 Help
* pHelp
= Application::GetHelp();
2255 rItem
.maHelpText
= pHelp
->GetHelpText(OStringToOUString(rItem
.maHelpId
, RTL_TEXTENCODING_UTF8
), this);
2258 return rItem
.maHelpText
;
2263 bool TabBar::StartDrag(const CommandEvent
& rCEvt
, vcl::Region
& rRegion
)
2265 if (!(mnWinStyle
& WB_DRAG
) || (rCEvt
.GetCommand() != CommandEventId::StartDrag
))
2268 // Check if the clicked page was selected. If this is not the case
2269 // set it as actual entry. We check for this only at a mouse action
2270 // if Drag and Drop can be triggered from the keyboard.
2271 // We only do this, if Select() was not triggered, as the Select()
2272 // could have scrolled the area
2273 if (rCEvt
.IsMouseEvent() && !mbInSelect
)
2275 sal_uInt16 nSelId
= GetPageId(rCEvt
.GetMousePosPixel());
2277 // do not start dragging if no entry was clicked
2281 // check if page was selected. If not set it as actual
2282 // page and call Select()
2283 if (!IsPageSelected(nSelId
))
2285 if (ImplDeactivatePage())
2287 SetCurPageId(nSelId
);
2298 vcl::Region aRegion
;
2306 sal_uInt16
TabBar::ShowDropPos(const Point
& rPos
)
2308 sal_uInt16 nNewDropPos
;
2309 sal_uInt16 nItemCount
= mpImpl
->getItemSize();
2310 sal_Int16 nScroll
= 0;
2312 if (rPos
.X() > mnLastOffX
-TABBAR_DRAG_SCROLLOFF
)
2314 auto& rItem
= mpImpl
->maItemList
[mpImpl
->maItemList
.size() - 1];
2315 if (!rItem
.maRect
.IsEmpty() && (rPos
.X() > rItem
.maRect
.Right()))
2316 nNewDropPos
= mpImpl
->getItemSize();
2319 nNewDropPos
= mnFirstPos
+ 1;
2323 else if ((rPos
.X() <= mnOffX
) ||
2324 (!mnOffX
&& (rPos
.X() <= TABBAR_DRAG_SCROLLOFF
)))
2328 nNewDropPos
= mnFirstPos
;
2336 sal_uInt16 nDropId
= GetPageId(rPos
);
2339 nNewDropPos
= GetPagePos(nDropId
);
2340 if (mnFirstPos
&& (nNewDropPos
== mnFirstPos
- 1))
2344 nNewDropPos
= nItemCount
;
2347 if (mbDropPos
&& (nNewDropPos
== mnDropPos
) && !nScroll
)
2353 mnDropPos
= nNewDropPos
;
2357 sal_uInt16 nOldFirstPos
= mnFirstPos
;
2358 SetFirstPageId(GetPageId(mnFirstPos
+ nScroll
));
2360 // draw immediately, as Paint not possible during Drag and Drop
2361 if (nOldFirstPos
!= mnFirstPos
)
2363 tools::Rectangle
aRect(mnOffX
, 0, mnLastOffX
, maWinSize
.Height());
2364 GetOutDev()->SetFillColor(GetBackground().GetColor());
2365 GetOutDev()->DrawRect(aRect
);
2370 // draw drop position arrows
2371 const StyleSettings
& rStyles
= Application::GetSettings().GetStyleSettings();
2372 const Color aTextColor
= rStyles
.GetLabelTextColor();
2374 tools::Long nY
= (maWinSize
.Height() / 2) - 1;
2375 sal_uInt16 nCurPos
= GetPagePos(mnCurPageId
);
2377 sal_Int32 nTriangleWidth
= 3 * GetDPIScaleFactor();
2379 if (mnDropPos
< nItemCount
)
2381 GetOutDev()->SetLineColor(aTextColor
);
2382 GetOutDev()->SetFillColor(aTextColor
);
2384 auto& rItem
= mpImpl
->maItemList
[mnDropPos
];
2385 nX
= rItem
.maRect
.Left();
2386 if ( mnDropPos
== nCurPos
)
2391 if (!rItem
.IsDefaultTabBgColor() && !rItem
.mbSelect
)
2393 GetOutDev()->SetLineColor(rItem
.maTabTextColor
);
2394 GetOutDev()->SetFillColor(rItem
.maTabTextColor
);
2397 tools::Polygon
aPoly(3);
2398 aPoly
.SetPoint(Point(nX
, nY
), 0);
2399 aPoly
.SetPoint(Point(nX
+ nTriangleWidth
, nY
- nTriangleWidth
), 1);
2400 aPoly
.SetPoint(Point(nX
+ nTriangleWidth
, nY
+ nTriangleWidth
), 2);
2401 GetOutDev()->DrawPolygon(aPoly
);
2403 if (mnDropPos
> 0 && mnDropPos
< nItemCount
+ 1)
2405 GetOutDev()->SetLineColor(aTextColor
);
2406 GetOutDev()->SetFillColor(aTextColor
);
2408 auto& rItem
= mpImpl
->maItemList
[mnDropPos
- 1];
2409 nX
= rItem
.maRect
.Right();
2410 if (mnDropPos
== nCurPos
)
2412 if (!rItem
.IsDefaultTabBgColor() && !rItem
.mbSelect
)
2414 GetOutDev()->SetLineColor(rItem
.maTabTextColor
);
2415 GetOutDev()->SetFillColor(rItem
.maTabTextColor
);
2417 tools::Polygon
aPoly(3);
2418 aPoly
.SetPoint(Point(nX
, nY
), 0);
2419 aPoly
.SetPoint(Point(nX
- nTriangleWidth
, nY
- nTriangleWidth
), 1);
2420 aPoly
.SetPoint(Point(nX
- nTriangleWidth
, nY
+ nTriangleWidth
), 2);
2421 GetOutDev()->DrawPolygon(aPoly
);
2427 void TabBar::HideDropPos()
2433 tools::Long nY1
= (maWinSize
.Height() / 2) - 3;
2434 tools::Long nY2
= nY1
+ 5;
2435 sal_uInt16 nItemCount
= mpImpl
->getItemSize();
2437 if (mnDropPos
< nItemCount
)
2439 auto& rItem
= mpImpl
->maItemList
[mnDropPos
];
2440 nX
= rItem
.maRect
.Left();
2441 // immediately call Paint, as it is not possible during drag and drop
2442 tools::Rectangle
aRect( nX
-1, nY1
, nX
+3, nY2
);
2443 vcl::Region
aRegion( aRect
);
2444 GetOutDev()->SetClipRegion( aRegion
);
2446 GetOutDev()->SetClipRegion();
2448 if (mnDropPos
> 0 && mnDropPos
< nItemCount
+ 1)
2450 auto& rItem
= mpImpl
->maItemList
[mnDropPos
- 1];
2451 nX
= rItem
.maRect
.Right();
2452 // immediately call Paint, as it is not possible during drag and drop
2453 tools::Rectangle
aRect(nX
- 2, nY1
, nX
+ 1, nY2
);
2454 vcl::Region
aRegion(aRect
);
2455 GetOutDev()->SetClipRegion(aRegion
);
2457 GetOutDev()->SetClipRegion();
2464 void TabBar::SwitchPage(const Point
& rPos
)
2466 sal_uInt16 nSwitchId
= GetPageId(rPos
);
2471 if (nSwitchId
!= mnSwitchId
)
2473 mnSwitchId
= nSwitchId
;
2474 mnSwitchTime
= tools::Time::GetSystemTicks();
2478 // change only after 500 ms
2479 if (mnSwitchId
!= GetCurPageId())
2481 if (tools::Time::GetSystemTicks() > mnSwitchTime
+ 500)
2483 if (ImplDeactivatePage())
2485 SetCurPageId( mnSwitchId
);
2496 void TabBar::EndSwitchPage()
2502 void TabBar::SetStyle(WinBits nStyle
)
2504 if (mnWinStyle
== nStyle
)
2506 mnWinStyle
= nStyle
;
2508 // order possible controls
2509 if (IsReallyVisible() && IsUpdateMode())
2513 Size
TabBar::CalcWindowSizePixel() const
2515 tools::Long nWidth
= 0;
2517 if (!mpImpl
->maItemList
.empty())
2519 const_cast<TabBar
*>(this)->ImplCalcWidth();
2520 for (const auto& rItem
: mpImpl
->maItemList
)
2522 nWidth
+= rItem
.mnWidth
;
2526 return Size(nWidth
, GetSettings().GetStyleSettings().GetScrollBarSize());
2529 tools::Rectangle
TabBar::GetPageArea() const
2531 return tools::Rectangle(Point(mnOffX
, mnOffY
),
2532 Size(mnLastOffX
- mnOffX
+ 1, GetSizePixel().Height() - mnOffY
));
2535 void TabBar::SetAddButtonEnabled(bool bAddButtonEnabled
)
2537 mpImpl
->mxButtonBox
->m_xAddButton
->set_sensitive(bAddButtonEnabled
);
2540 css::uno::Reference
<css::accessibility::XAccessible
> TabBar::CreateAccessible()
2542 return mpImpl
->maAccessibleFactory
.getFactory().createAccessibleTabBar(*this);
2545 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */