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 .
20 #include "accessibletabbar.hxx"
22 #include <svtools/tabbar.hxx>
23 #include <tools/time.hxx>
24 #include <tools/poly.hxx>
26 #include <vcl/InterimItemWindow.hxx>
27 #include <vcl/bitmapex.hxx>
28 #include <vcl/svapp.hxx>
29 #include <vcl/help.hxx>
30 #include <vcl/decoview.hxx>
31 #include <vcl/event.hxx>
32 #include <vcl/settings.hxx>
33 #include <vcl/commandevent.hxx>
34 #include <vcl/ptrstyle.hxx>
35 #include <vcl/weldutils.hxx>
36 #include <svtools/svtresid.hxx>
37 #include <svtools/strings.hrc>
41 #include <vcl/idle.hxx>
42 #include <bitmaps.hlst>
47 constexpr sal_uInt16 TABBAR_DRAG_SCROLLOFF
= 5;
48 constexpr sal_uInt16 TABBAR_MINSIZE
= 5;
50 constexpr sal_uInt16 ADDNEWPAGE_AREAWIDTH
= 10;
55 vcl::RenderContext
& mrRenderContext
;
56 const StyleSettings
& mrStyleSettings
;
58 tools::Rectangle maRect
;
59 tools::Rectangle maLineRect
;
61 Color maSelectedColor
;
66 bool mbCustomColored
:1;
70 explicit TabDrawer(vcl::RenderContext
& rRenderContext
)
71 : mrRenderContext(rRenderContext
)
72 , mrStyleSettings(rRenderContext
.GetSettings().GetStyleSettings())
74 , mbCustomColored(false)
83 // set correct FillInBrush depending on status
86 // Currently selected Tab
87 mrRenderContext
.SetFillColor(maSelectedColor
);
88 mrRenderContext
.SetLineColor(maSelectedColor
);
89 mrRenderContext
.DrawRect(maRect
);
90 mrRenderContext
.SetLineColor(mrStyleSettings
.GetDarkShadowColor());
92 else if (mbCustomColored
)
94 mrRenderContext
.SetFillColor(maCustomColor
);
95 mrRenderContext
.SetLineColor(maCustomColor
);
96 mrRenderContext
.DrawRect(maRect
);
97 mrRenderContext
.SetLineColor(mrStyleSettings
.GetDarkShadowColor());
101 void drawText(const OUString
& aText
)
103 tools::Rectangle aRect
= maRect
;
104 tools::Long nTextWidth
= mrRenderContext
.GetTextWidth(aText
);
105 tools::Long nTextHeight
= mrRenderContext
.GetTextHeight();
106 Point aPos
= aRect
.TopLeft();
107 aPos
.AdjustX((aRect
.getOpenWidth() - nTextWidth
) / 2 );
108 aPos
.AdjustY((aRect
.getOpenHeight() - nTextHeight
) / 2 );
111 mrRenderContext
.DrawText(aPos
, aText
);
113 mrRenderContext
.DrawCtrlText(aPos
, aText
, 0, aText
.getLength(), (DrawTextFlags::Disable
| DrawTextFlags::Mnemonic
));
116 void drawOverTopBorder()
118 Point aTopLeft
= maRect
.TopLeft() + Point(1, 0);
119 Point aTopRight
= maRect
.TopRight() + Point(-1, 0);
121 tools::Rectangle
aDelRect(aTopLeft
, aTopRight
);
122 mrRenderContext
.DrawRect(aDelRect
);
130 // tdf#141396: the color must be different from the rest of the selected tab
131 Color aLineColor
= (mbCustomColored
&& maCustomColor
!= maSelectedColor
)
133 : mrStyleSettings
.GetDarkShadowColor();
134 mrRenderContext
.SetFillColor(aLineColor
);
135 mrRenderContext
.SetLineColor(aLineColor
);
136 mrRenderContext
.DrawRect(maLineRect
);
141 const tools::Long cMargin
= 5;
142 const tools::Long
aRight( maRect
.Right() - 1 );
143 mrRenderContext
.SetLineColor(mrStyleSettings
.GetShadowColor());
144 mrRenderContext
.DrawLine(Point(aRight
, maRect
.Top() + cMargin
),
145 Point(aRight
, maRect
.Bottom() - cMargin
));
152 if (!mbSelected
&& !mbCustomColored
)
156 BitmapEx
aBitmap(BMP_TAB_LOCK
);
157 Point aPosition
= maRect
.TopLeft();
158 aPosition
.AdjustX(2);
159 aPosition
.AdjustY((maRect
.getOpenHeight() - aBitmap
.GetSizePixel().Height()) / 2);
160 mrRenderContext
.DrawBitmapEx(aPosition
, aBitmap
);
164 void setRect(const tools::Rectangle
& rRect
)
166 maLineRect
= tools::Rectangle(rRect
.BottomLeft(), rRect
.BottomRight());
167 maLineRect
.AdjustTop(-2);
171 void setSelected(bool bSelected
)
173 mbSelected
= bSelected
;
176 void setCustomColored(bool bCustomColored
)
178 mbCustomColored
= bCustomColored
;
181 void setEnabled(bool bEnabled
)
183 mbEnabled
= bEnabled
;
186 void setSelectedFillColor(const Color
& rColor
)
188 maSelectedColor
= rColor
;
191 void setCustomColor(const Color
& rColor
)
193 maCustomColor
= rColor
;
197 } // anonymous namespace
199 struct ImplTabBarItem
202 TabBarPageBits mnBits
;
205 OUString maAuxiliaryText
; // used in LayerTabBar for real layer name
206 tools::Rectangle maRect
;
213 Color maTabTextColor
;
215 ImplTabBarItem(sal_uInt16 nItemId
, OUString aText
, TabBarPageBits nPageBits
)
218 , maText(std::move(aText
))
223 , maTabBgColor(COL_AUTO
)
224 , maTabTextColor(COL_AUTO
)
228 bool IsDefaultTabBgColor() const
230 return maTabBgColor
== COL_AUTO
;
233 bool IsSelected(ImplTabBarItem
const * pCurItem
) const
235 return mbSelect
|| (pCurItem
== this);
238 OUString
const & GetRenderText() const
244 class ImplTabSizer
: public vcl::Window
247 ImplTabSizer( TabBar
* pParent
, WinBits nWinStyle
);
249 TabBar
* GetParent() const { return static_cast<TabBar
*>(Window::GetParent()); }
252 void ImplTrack( const Point
& rScreenPos
);
254 virtual void MouseButtonDown( const MouseEvent
& rMEvt
) override
;
255 virtual void Tracking( const TrackingEvent
& rTEvt
) override
;
256 virtual void Paint( vcl::RenderContext
& /*rRenderContext*/, const tools::Rectangle
& rRect
) override
;
259 tools::Long mnStartWidth
;
262 ImplTabSizer::ImplTabSizer( TabBar
* pParent
, WinBits nWinStyle
)
263 : Window( pParent
, nWinStyle
& WB_3DLOOK
)
266 SetPointer(PointerStyle::HSizeBar
);
267 SetSizePixel(Size(7 * GetDPIScaleFactor(), 0));
270 void ImplTabSizer::ImplTrack( const Point
& rScreenPos
)
272 TabBar
* pParent
= GetParent();
273 tools::Long nDiff
= rScreenPos
.X() - maStartPos
.X();
274 pParent
->mnSplitSize
= mnStartWidth
+ (pParent
->IsMirrored() ? -nDiff
: nDiff
);
275 if ( pParent
->mnSplitSize
< TABBAR_MINSIZE
)
276 pParent
->mnSplitSize
= TABBAR_MINSIZE
;
278 pParent
->PaintImmediately();
281 void ImplTabSizer::MouseButtonDown( const MouseEvent
& rMEvt
)
283 if ( GetParent()->IsInEditMode() )
285 GetParent()->EndEditMode();
289 if ( rMEvt
.IsLeft() )
291 maStartPos
= OutputToScreenPixel( rMEvt
.GetPosPixel() );
292 mnStartWidth
= GetParent()->GetSizePixel().Width();
297 void ImplTabSizer::Tracking( const TrackingEvent
& rTEvt
)
299 if ( rTEvt
.IsTrackingEnded() )
301 if ( rTEvt
.IsTrackingCanceled() )
302 ImplTrack( maStartPos
);
303 GetParent()->mnSplitSize
= 0;
306 ImplTrack( OutputToScreenPixel( rTEvt
.GetMouseEvent().GetPosPixel() ) );
309 void ImplTabSizer::Paint( vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& )
311 DecorationView
aDecoView(&rRenderContext
);
312 tools::Rectangle
aOutputRect(Point(0, 0), GetOutputSizePixel());
313 aDecoView
.DrawHandle(aOutputRect
);
318 // Is not named Impl. as it may be both instantiated and derived from
319 class TabBarEdit final
: public InterimItemWindow
322 std::unique_ptr
<weld::Entry
> m_xEntry
;
323 Idle maLoseFocusIdle
;
326 DECL_LINK( ImplEndEditHdl
, void*, void );
327 DECL_LINK( ImplEndTimerHdl
, Timer
*, void );
328 DECL_LINK( ActivatedHdl
, weld::Entry
&, bool );
329 DECL_LINK( KeyInputHdl
, const KeyEvent
&, bool );
330 DECL_LINK( FocusOutHdl
, weld::Widget
&, void );
333 TabBarEdit(TabBar
* pParent
);
334 virtual void dispose() override
;
336 TabBar
* GetParent() const { return static_cast<TabBar
*>(Window::GetParent()); }
338 weld::Entry
& get_widget() { return *m_xEntry
; }
340 void SetPostEvent() { mbPostEvt
= true; }
341 void ResetPostEvent() { mbPostEvt
= false; }
346 TabBarEdit::TabBarEdit(TabBar
* pParent
)
347 : InterimItemWindow(pParent
, u
"svt/ui/tabbaredit.ui"_ustr
, u
"TabBarEdit"_ustr
)
348 , m_xEntry(m_xBuilder
->weld_entry(u
"entry"_ustr
))
349 , maLoseFocusIdle( "svtools::TabBarEdit maLoseFocusIdle" )
351 InitControlBase(m_xEntry
.get());
354 maLoseFocusIdle
.SetPriority( TaskPriority::REPAINT
);
355 maLoseFocusIdle
.SetInvokeHandler( LINK( this, TabBarEdit
, ImplEndTimerHdl
) );
357 m_xEntry
->connect_activate(LINK(this, TabBarEdit
, ActivatedHdl
));
358 m_xEntry
->connect_key_press(LINK(this, TabBarEdit
, KeyInputHdl
));
359 m_xEntry
->connect_focus_out(LINK(this, TabBarEdit
, FocusOutHdl
));
362 void TabBarEdit::dispose()
365 InterimItemWindow::dispose();
368 IMPL_LINK_NOARG(TabBarEdit
, ActivatedHdl
, weld::Entry
&, bool)
372 if ( PostUserEvent( LINK( this, TabBarEdit
, ImplEndEditHdl
), reinterpret_cast<void*>(false), true ) )
378 IMPL_LINK(TabBarEdit
, KeyInputHdl
, const KeyEvent
&, rKEvt
, bool)
380 if (!rKEvt
.GetKeyCode().GetModifier() && rKEvt
.GetKeyCode().GetCode() == KEY_ESCAPE
)
384 if ( PostUserEvent( LINK( this, TabBarEdit
, ImplEndEditHdl
), reinterpret_cast<void*>(true), true ) )
392 IMPL_LINK_NOARG(TabBarEdit
, FocusOutHdl
, weld::Widget
&, void)
396 if ( PostUserEvent( LINK( this, TabBarEdit
, ImplEndEditHdl
), reinterpret_cast<void*>(false), true ) )
401 IMPL_LINK( TabBarEdit
, ImplEndEditHdl
, void*, pCancel
, void )
404 maLoseFocusIdle
.Stop();
406 // tdf#156958: when renaming and clicking on canvas, LO goes into GetParent()->EndEditMode first time
407 // then it calls TabBarEdit::dispose method which resets m_xEntry BUT, on the same thread, LO comes here again
408 // so return if already disposed to avoid a crash
412 // We need this query, because the edit gets a losefocus event,
413 // when it shows the context menu or the insert symbol dialog
414 if (!m_xEntry
->has_focus() && m_xEntry
->has_child_focus())
415 maLoseFocusIdle
.Start();
417 GetParent()->EndEditMode( pCancel
!= nullptr );
420 IMPL_LINK_NOARG(TabBarEdit
, ImplEndTimerHdl
, Timer
*, void)
422 if (m_xEntry
->has_focus())
425 // We need this query, because the edit gets a losefocus event,
426 // when it shows the context menu or the insert symbol dialog
427 if (m_xEntry
->has_child_focus())
428 maLoseFocusIdle
.Start();
430 GetParent()->EndEditMode( true );
435 class TabButtons final
: public InterimItemWindow
438 std::unique_ptr
<weld::Button
> m_xFirstButton
;
439 std::unique_ptr
<weld::Button
> m_xPrevButton
;
440 std::unique_ptr
<weld::Button
> m_xNextButton
;
441 std::unique_ptr
<weld::Button
> m_xLastButton
;
442 std::unique_ptr
<weld::Button
> m_xAddButton
;
443 std::shared_ptr
<weld::ButtonPressRepeater
> m_xAddRepeater
;
444 std::shared_ptr
<weld::ButtonPressRepeater
> m_xPrevRepeater
;
445 std::shared_ptr
<weld::ButtonPressRepeater
> m_xNextRepeater
;
447 TabButtons(TabBar
* pParent
, bool bSheets
)
448 : InterimItemWindow(pParent
,
449 pParent
->IsMirrored() ? u
"svt/ui/tabbuttonsmirrored.ui"_ustr
450 : u
"svt/ui/tabbuttons.ui"_ustr
,
452 , m_xFirstButton(m_xBuilder
->weld_button(u
"first"_ustr
))
453 , m_xPrevButton(m_xBuilder
->weld_button(u
"prev"_ustr
))
454 , m_xNextButton(m_xBuilder
->weld_button(u
"next"_ustr
))
455 , m_xLastButton(m_xBuilder
->weld_button(u
"last"_ustr
))
456 , m_xAddButton(m_xBuilder
->weld_button(u
"add"_ustr
))
458 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
459 SetPaintTransparent(false);
460 SetBackground(rStyleSettings
.GetFaceColor());
462 m_xFirstButton
->set_accessible_name(SvtResId(STR_TABBAR_PUSHBUTTON_MOVET0HOME
));
463 m_xPrevButton
->set_accessible_name(SvtResId(STR_TABBAR_PUSHBUTTON_MOVELEFT
));
464 m_xNextButton
->set_accessible_name(SvtResId(STR_TABBAR_PUSHBUTTON_MOVERIGHT
));
465 m_xLastButton
->set_accessible_name(SvtResId(STR_TABBAR_PUSHBUTTON_MOVETOEND
));
466 m_xAddButton
->set_accessible_name(SvtResId(STR_TABBAR_PUSHBUTTON_ADDTAB
));
470 m_xFirstButton
->set_tooltip_text(SvtResId(STR_TABBAR_HINT_MOVETOHOME_SHEETS
));
471 m_xPrevButton
->set_tooltip_text(SvtResId(STR_TABBAR_HINT_MOVELEFT_SHEETS
));
472 m_xNextButton
->set_tooltip_text(SvtResId(STR_TABBAR_HINT_MOVERIGHT_SHEETS
));
473 m_xLastButton
->set_tooltip_text(SvtResId(STR_TABBAR_HINT_MOVETOEND_SHEETS
));
474 m_xAddButton
->set_tooltip_text(SvtResId(STR_TABBAR_HINT_ADDTAB_SHEETS
));
478 void AdaptToHeight(int nHeight
)
480 if (m_xFirstButton
->get_preferred_size() == Size(nHeight
, nHeight
))
482 m_xFirstButton
->set_size_request(nHeight
, nHeight
);
483 m_xPrevButton
->set_size_request(nHeight
, nHeight
);
484 m_xNextButton
->set_size_request(nHeight
, nHeight
);
485 m_xLastButton
->set_size_request(nHeight
, nHeight
);
486 m_xAddButton
->set_size_request(nHeight
, nHeight
);
487 InvalidateChildSizeCache();
490 virtual void dispose() override
492 m_xNextRepeater
.reset();
493 m_xPrevRepeater
.reset();
494 m_xAddRepeater
.reset();
495 m_xAddButton
.reset();
496 m_xLastButton
.reset();
497 m_xNextButton
.reset();
498 m_xPrevButton
.reset();
499 m_xFirstButton
.reset();
500 InterimItemWindow::dispose();
508 ScopedVclPtr
<ImplTabSizer
> mpSizer
;
509 ScopedVclPtr
<TabButtons
> mxButtonBox
;
510 ScopedVclPtr
<TabBarEdit
> mxEdit
;
511 std::vector
<ImplTabBarItem
> maItemList
;
513 sal_uInt16
getItemSize() const
515 return static_cast<sal_uInt16
>(maItemList
.size());
519 TabBar::TabBar( vcl::Window
* pParent
, WinBits nWinStyle
, bool bSheets
) :
520 Window( pParent
, (nWinStyle
& WB_3DLOOK
) | WB_CLIPCHILDREN
)
522 ImplInit( nWinStyle
, bSheets
);
523 maCurrentItemList
= 0;
531 void TabBar::dispose()
538 const sal_uInt16
TabBar::APPEND
= ::std::numeric_limits
<sal_uInt16
>::max();
539 const sal_uInt16
TabBar::PAGE_NOT_FOUND
= ::std::numeric_limits
<sal_uInt16
>::max();
541 void TabBar::ImplInit( WinBits nWinStyle
, bool bSheets
)
543 mpImpl
.reset(new TabBar_Impl
);
552 mnWinStyle
= nWinStyle
;
559 mbFirstFormat
= true;
561 mbAutoEditMode
= false;
562 mbEditCanceled
= false;
566 mbScrollAlwaysEnabled
= false;
571 SetSizePixel( Size( 100, CalcWindowSizePixel().Height() ) );
572 ImplInitSettings( true, true );
575 ImplTabBarItem
* TabBar::seek( size_t i
)
577 if ( i
< mpImpl
->maItemList
.size() )
579 maCurrentItemList
= i
;
580 return &mpImpl
->maItemList
[maCurrentItemList
];
585 ImplTabBarItem
* TabBar::prev()
587 if ( maCurrentItemList
> 0 )
589 return &mpImpl
->maItemList
[--maCurrentItemList
];
594 ImplTabBarItem
* TabBar::next()
596 if ( maCurrentItemList
+ 1 < mpImpl
->maItemList
.size() )
598 return &mpImpl
->maItemList
[++maCurrentItemList
];
603 void TabBar::ImplInitSettings( bool bFont
, bool bBackground
)
605 // FIXME RenderContext
607 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
611 vcl::Font aToolFont
= rStyleSettings
.GetToolFont();
612 aToolFont
.SetWeight( WEIGHT_BOLD
);
613 ApplyControlFont(*GetOutDev(), aToolFont
);
615 // Adapt font size if window too small?
616 while (GetTextHeight() > (GetOutputSizePixel().Height() - 1))
618 vcl::Font aFont
= GetFont();
619 if (aFont
.GetFontHeight() <= 6)
621 aFont
.SetFontHeight(aFont
.GetFontHeight() - 1);
628 ApplyControlBackground(*GetOutDev(), rStyleSettings
.GetFaceColor());
632 void TabBar::ImplGetColors(const StyleSettings
& rStyleSettings
,
633 Color
& rFaceColor
, Color
& rFaceTextColor
,
634 Color
& rSelectColor
, Color
& rSelectTextColor
)
636 if (IsControlBackground())
637 rFaceColor
= GetControlBackground();
639 rFaceColor
= rStyleSettings
.GetInactiveTabColor();
640 if (IsControlForeground())
641 rFaceTextColor
= GetControlForeground();
643 rFaceTextColor
= rStyleSettings
.GetButtonTextColor();
644 rSelectColor
= rStyleSettings
.GetActiveTabColor();
645 rSelectTextColor
= rStyleSettings
.GetWindowTextColor();
648 bool TabBar::ImplCalcWidth()
650 // Sizes should only be retrieved if the text or the font was changed
654 // retrieve width of tabs with bold font
655 vcl::Font aFont
= GetFont();
656 if (aFont
.GetWeight() != WEIGHT_BOLD
)
658 aFont
.SetWeight(WEIGHT_BOLD
);
663 mnCurMaxWidth
= mnMaxPageWidth
;
666 mnCurMaxWidth
= mnLastOffX
- mnOffX
;
667 if (mnCurMaxWidth
< 1)
671 bool bChanged
= false;
672 for (auto& rItem
: mpImpl
->maItemList
)
674 tools::Long nNewWidth
= GetTextWidth(rItem
.GetRenderText());
675 if (mnCurMaxWidth
&& (nNewWidth
> mnCurMaxWidth
))
677 rItem
.mbShort
= true;
678 nNewWidth
= mnCurMaxWidth
;
682 rItem
.mbShort
= false;
685 // Padding is dependent on font height - bigger font = bigger padding
686 tools::Long nFontWidth
= aFont
.GetFontHeight();
689 nNewWidth
+= nFontWidth
* 2;
691 if (rItem
.mnWidth
!= nNewWidth
)
693 rItem
.mnWidth
= nNewWidth
;
694 if (!rItem
.maRect
.IsEmpty())
698 mbSizeFormat
= false;
703 void TabBar::ImplFormat()
710 sal_uInt16 nItemIndex
= 0;
711 tools::Long x
= mnOffX
;
712 for (auto & rItem
: mpImpl
->maItemList
)
714 // At all non-visible tabs an empty rectangle is set
715 if ((nItemIndex
+ 1 < mnFirstPos
) || (x
> mnLastOffX
))
716 rItem
.maRect
.SetEmpty();
719 // Slightly before the tab before the first visible page
720 // should also be visible
721 if (nItemIndex
+ 1 == mnFirstPos
)
723 rItem
.maRect
.SetLeft(x
- rItem
.mnWidth
);
727 rItem
.maRect
.SetLeft(x
);
730 rItem
.maRect
.SetRight(x
);
731 rItem
.maRect
.SetBottom(maWinSize
.Height() - 1);
735 tools::Long nNewLeft
= mnOffX
+ mnLastOffX
- rItem
.maRect
.Right();
736 tools::Long nNewRight
= mnOffX
+ mnLastOffX
- rItem
.maRect
.Left();
737 rItem
.maRect
.SetRight(nNewRight
);
738 rItem
.maRect
.SetLeft(nNewLeft
);
747 // enable/disable button
748 ImplEnableControls();
751 sal_uInt16
TabBar::ImplGetLastFirstPos()
753 sal_uInt16 nCount
= mpImpl
->getItemSize();
754 if (!nCount
|| mbSizeFormat
|| mbFormat
)
757 sal_uInt16 nLastFirstPos
= nCount
- 1;
758 tools::Long nWinWidth
= mnLastOffX
- mnOffX
- ADDNEWPAGE_AREAWIDTH
;
759 tools::Long nWidth
= mpImpl
->maItemList
[nLastFirstPos
].mnWidth
;
761 while (nLastFirstPos
&& (nWidth
< nWinWidth
))
764 nWidth
+= mpImpl
->maItemList
[nLastFirstPos
].mnWidth
;
766 if ((nLastFirstPos
!= static_cast<sal_uInt16
>(mpImpl
->maItemList
.size() - 1)) && (nWidth
> nWinWidth
))
768 return nLastFirstPos
;
771 IMPL_LINK(TabBar
, ContextMenuHdl
, const CommandEvent
&, rCommandEvent
, void)
773 maScrollAreaContextHdl
.Call(rCommandEvent
);
776 IMPL_LINK(TabBar
, MousePressHdl
, const MouseEvent
&, rMouseEvent
, bool)
778 if (rMouseEvent
.IsRight())
779 ContextMenuHdl(CommandEvent(rMouseEvent
.GetPosPixel(), CommandEventId::ContextMenu
, true));
783 void TabBar::ImplInitControls()
785 if (mnWinStyle
& WB_SIZEABLE
)
787 if (!mpImpl
->mpSizer
)
789 mpImpl
->mpSizer
.disposeAndReset(VclPtr
<ImplTabSizer
>::Create( this, mnWinStyle
& (WB_DRAG
| WB_3DLOOK
)));
791 mpImpl
->mpSizer
->Show();
795 mpImpl
->mpSizer
.disposeAndClear();
798 mpImpl
->mxButtonBox
.disposeAndReset(VclPtr
<TabButtons
>::Create(this, mbSheets
));
800 Link
<const CommandEvent
&, void> aContextLink
= LINK( this, TabBar
, ContextMenuHdl
);
802 if (mnWinStyle
& WB_INSERTTAB
)
804 Link
<weld::Button
&,void> aLink
= LINK(this, TabBar
, ImplAddClickHandler
);
805 mpImpl
->mxButtonBox
->m_xAddRepeater
= std::make_shared
<weld::ButtonPressRepeater
>(
806 *mpImpl
->mxButtonBox
->m_xAddButton
, aLink
, aContextLink
);
807 mpImpl
->mxButtonBox
->m_xAddButton
->show();
810 Link
<weld::Button
&,void> aLink
= LINK( this, TabBar
, ImplClickHdl
);
812 if (mnWinStyle
& (WB_MINSCROLL
| WB_SCROLL
))
814 mpImpl
->mxButtonBox
->m_xPrevRepeater
= std::make_shared
<weld::ButtonPressRepeater
>(
815 *mpImpl
->mxButtonBox
->m_xPrevButton
, aLink
, aContextLink
);
816 mpImpl
->mxButtonBox
->m_xPrevButton
->show();
817 mpImpl
->mxButtonBox
->m_xNextRepeater
= std::make_shared
<weld::ButtonPressRepeater
>(
818 *mpImpl
->mxButtonBox
->m_xNextButton
, aLink
, aContextLink
);
819 mpImpl
->mxButtonBox
->m_xNextButton
->show();
822 if (mnWinStyle
& WB_SCROLL
)
824 Link
<const MouseEvent
&, bool> aBtnContextLink
= LINK(this, TabBar
, MousePressHdl
);
826 mpImpl
->mxButtonBox
->m_xFirstButton
->connect_clicked(aLink
);
827 mpImpl
->mxButtonBox
->m_xFirstButton
->connect_mouse_press(aBtnContextLink
);
828 mpImpl
->mxButtonBox
->m_xFirstButton
->show();
829 mpImpl
->mxButtonBox
->m_xLastButton
->connect_clicked(aLink
);
830 mpImpl
->mxButtonBox
->m_xLastButton
->connect_mouse_press(aBtnContextLink
);
831 mpImpl
->mxButtonBox
->m_xLastButton
->show();
834 mpImpl
->mxButtonBox
->Show();
837 void TabBar::ImplEnableControls()
839 if (mbSizeFormat
|| mbFormat
)
842 // enable/disable buttons
843 bool bEnableBtn
= mbScrollAlwaysEnabled
|| mnFirstPos
> 0;
844 mpImpl
->mxButtonBox
->m_xFirstButton
->set_sensitive(bEnableBtn
);
845 mpImpl
->mxButtonBox
->m_xPrevButton
->set_sensitive(bEnableBtn
);
846 if (!bEnableBtn
&& mpImpl
->mxButtonBox
->m_xPrevRepeater
)
847 mpImpl
->mxButtonBox
->m_xPrevRepeater
->Stop();
848 bEnableBtn
= mbScrollAlwaysEnabled
|| mnFirstPos
< ImplGetLastFirstPos();
849 mpImpl
->mxButtonBox
->m_xLastButton
->set_sensitive(bEnableBtn
);
850 mpImpl
->mxButtonBox
->m_xNextButton
->set_sensitive(bEnableBtn
);
851 if (!bEnableBtn
&& mpImpl
->mxButtonBox
->m_xNextRepeater
)
852 mpImpl
->mxButtonBox
->m_xNextRepeater
->Stop();
855 void TabBar::SetScrollAlwaysEnabled(bool bScrollAlwaysEnabled
)
857 mbScrollAlwaysEnabled
= bScrollAlwaysEnabled
;
858 ImplEnableControls();
861 void TabBar::ImplShowPage( sal_uInt16 nPos
)
863 if (nPos
>= mpImpl
->getItemSize())
867 tools::Long nWidth
= GetOutputSizePixel().Width();
869 auto& rItem
= mpImpl
->maItemList
[nPos
];
870 if (nPos
< mnFirstPos
)
871 SetFirstPageId( rItem
.mnId
);
872 else if (rItem
.maRect
.Right() > nWidth
)
874 while (rItem
.maRect
.Right() > nWidth
)
876 sal_uInt16 nNewPos
= mnFirstPos
+ 1;
877 SetFirstPageId(GetPageId(nNewPos
));
879 if (nNewPos
!= mnFirstPos
)
885 IMPL_LINK( TabBar
, ImplClickHdl
, weld::Button
&, rBtn
, void )
887 if (&rBtn
!= mpImpl
->mxButtonBox
->m_xFirstButton
.get() && &rBtn
!= mpImpl
->mxButtonBox
->m_xLastButton
.get())
889 if ((GetPointerState().mnState
& (MOUSE_LEFT
| MOUSE_MIDDLE
| MOUSE_RIGHT
)) == 0)
891 // like tdf#149482 if we didn't see a mouse up, but find that the mouse is no
892 // longer pressed at this point, then bail
893 mpImpl
->mxButtonBox
->m_xPrevRepeater
->Stop();
894 mpImpl
->mxButtonBox
->m_xNextRepeater
->Stop();
901 sal_uInt16 nNewPos
= mnFirstPos
;
903 if (&rBtn
== mpImpl
->mxButtonBox
->m_xFirstButton
.get() || (&rBtn
== mpImpl
->mxButtonBox
->m_xPrevButton
.get() &&
904 mpImpl
->mxButtonBox
->m_xPrevRepeater
->IsModKeyPressed()))
908 else if (&rBtn
== mpImpl
->mxButtonBox
->m_xLastButton
.get() || (&rBtn
== mpImpl
->mxButtonBox
->m_xNextButton
.get() &&
909 mpImpl
->mxButtonBox
->m_xNextRepeater
->IsModKeyPressed()))
911 sal_uInt16 nCount
= GetPageCount();
913 nNewPos
= nCount
- 1;
915 else if (&rBtn
== mpImpl
->mxButtonBox
->m_xPrevButton
.get())
918 nNewPos
= mnFirstPos
- 1;
920 else if (&rBtn
== mpImpl
->mxButtonBox
->m_xNextButton
.get())
922 sal_uInt16 nCount
= GetPageCount();
923 if (mnFirstPos
< nCount
)
924 nNewPos
= mnFirstPos
+1;
931 if (nNewPos
!= mnFirstPos
)
932 SetFirstPageId(GetPageId(nNewPos
));
935 IMPL_LINK_NOARG(TabBar
, ImplAddClickHandler
, weld::Button
&, void)
937 if ((GetPointerState().mnState
& (MOUSE_LEFT
| MOUSE_MIDDLE
| MOUSE_RIGHT
)) == 0)
939 // tdf#149482 if we didn't see a mouse up, but find that the mouse is no
940 // longer pressed at this point, then bail
941 mpImpl
->mxButtonBox
->m_xAddRepeater
->Stop();
949 void TabBar::MouseMove(const MouseEvent
& rMEvt
)
951 if (rMEvt
.IsLeaveWindow())
954 Window::MouseMove(rMEvt
);
957 void TabBar::MouseButtonDown(const MouseEvent
& rMEvt
)
959 // Only terminate EditMode and do not execute click
960 // if clicked inside our window,
967 sal_uInt16 nSelId
= GetPageId(rMEvt
.GetPosPixel());
971 Window::MouseButtonDown(rMEvt
);
972 if (nSelId
> 0 && nSelId
!= mnCurPageId
)
974 if (ImplDeactivatePage())
976 SetCurPageId(nSelId
);
986 if (rMEvt
.IsMod2() && mbAutoEditMode
&& nSelId
)
988 if (StartEditMode(nSelId
))
992 if ((rMEvt
.GetMode() & (MouseEventModifiers::MULTISELECT
| MouseEventModifiers::RANGESELECT
)) && (rMEvt
.GetClicks() == 1))
996 sal_uInt16 nPos
= GetPagePos(nSelId
);
998 bool bSelectTab
= false;
1000 if ((rMEvt
.GetMode() & MouseEventModifiers::MULTISELECT
) && (mnWinStyle
& WB_MULTISELECT
))
1002 if (nSelId
!= mnCurPageId
)
1004 SelectPage(nSelId
, !IsPageSelected(nSelId
));
1008 else if (mnWinStyle
& (WB_MULTISELECT
| WB_RANGESELECT
))
1013 sal_uInt16 nCurPos
= GetPagePos(mnCurPageId
);
1014 if (nPos
<= nCurPos
)
1016 // Deselect all tabs till the clicked tab
1017 // and select all tabs from the clicked tab
1018 // 'till the actual position
1022 auto& rItem
= mpImpl
->maItemList
[n
];
1023 bSelect
= n
>= nPos
;
1025 if (rItem
.mbSelect
!= bSelect
)
1027 rItem
.mbSelect
= bSelect
;
1028 if (!rItem
.maRect
.IsEmpty())
1029 Invalidate(rItem
.maRect
);
1036 if (nPos
>= nCurPos
)
1038 // Select all tabs from the actual position till the clicked tab
1039 // and deselect all tabs from the actual position
1040 // till the last tab
1041 sal_uInt16 nCount
= mpImpl
->getItemSize();
1045 auto& rItem
= mpImpl
->maItemList
[n
];
1047 bSelect
= n
<= nPos
;
1049 if (rItem
.mbSelect
!= bSelect
)
1051 rItem
.mbSelect
= bSelect
;
1052 if (!rItem
.maRect
.IsEmpty())
1053 Invalidate(rItem
.maRect
);
1061 // scroll the selected tab if required
1074 else if (rMEvt
.GetClicks() == 2)
1076 // call double-click-handler if required
1077 if (!rMEvt
.GetModifier() && (!nSelId
|| (nSelId
== mnCurPageId
)))
1079 sal_uInt16 nOldCurId
= mnCurPageId
;
1080 mnCurPageId
= nSelId
;
1082 // check, as actual page could be switched inside
1083 // the doubleclick-handler
1084 if (mnCurPageId
== nSelId
)
1085 mnCurPageId
= nOldCurId
;
1094 // execute Select if not actual page
1095 if (nSelId
!= mnCurPageId
)
1097 sal_uInt16 nPos
= GetPagePos(nSelId
);
1098 auto& rItem
= mpImpl
->maItemList
[nPos
];
1100 if (!rItem
.mbSelect
)
1103 bool bUpdate
= false;
1104 if (IsReallyVisible() && IsUpdateMode())
1107 // deselect all selected items
1108 for (auto& xItem
: mpImpl
->maItemList
)
1110 if (xItem
.mbSelect
|| (xItem
.mnId
== mnCurPageId
))
1112 xItem
.mbSelect
= false;
1114 Invalidate(xItem
.maRect
);
1119 if (ImplDeactivatePage())
1121 SetCurPageId(nSelId
);
1134 Window::MouseButtonDown(rMEvt
);
1137 void TabBar::MouseButtonUp(const MouseEvent
& rMEvt
)
1140 Window::MouseButtonUp(rMEvt
);
1143 void TabBar::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& rect
)
1145 if (rRenderContext
.IsNativeControlSupported(ControlType::WindowBackground
,ControlPart::Entire
))
1147 rRenderContext
.DrawNativeControl(ControlType::WindowBackground
,ControlPart::Entire
,rect
,
1148 ControlState::ENABLED
,ImplControlValue(0),OUString());
1150 // calculate items and emit
1151 sal_uInt16 nItemCount
= mpImpl
->getItemSize();
1157 Color aFaceColor
, aSelectColor
, aFaceTextColor
, aSelectTextColor
;
1158 const StyleSettings
& rStyleSettings
= rRenderContext
.GetSettings().GetStyleSettings();
1159 ImplGetColors(rStyleSettings
, aFaceColor
, aFaceTextColor
, aSelectColor
, aSelectTextColor
);
1161 rRenderContext
.Push(vcl::PushFlags::FONT
| vcl::PushFlags::CLIPREGION
);
1162 rRenderContext
.SetClipRegion(vcl::Region(GetPageArea()));
1165 vcl::Font aFont
= rRenderContext
.GetFont();
1166 vcl::Font aLightFont
= aFont
;
1167 aLightFont
.SetWeight(WEIGHT_NORMAL
);
1169 TabDrawer
aDrawer(rRenderContext
);
1171 aDrawer
.setSelectedFillColor(aSelectColor
);
1173 // Now, start drawing the tabs.
1175 ImplTabBarItem
* pItem
= ImplGetLastTabBarItem(nItemCount
);
1176 ImplTabBarItem
* pCurItem
= nullptr;
1179 // emit CurrentItem last, as it covers all others
1180 if (!pCurItem
&& (pItem
->mnId
== mnCurPageId
))
1189 bool bCurrent
= pItem
== pCurItem
;
1191 if (!pItem
->maRect
.IsEmpty())
1193 tools::Rectangle aRect
= pItem
->maRect
;
1194 bool bSelected
= pItem
->IsSelected(pCurItem
);
1195 // We disable custom background color in high contrast mode.
1196 bool bCustomBgColor
= !pItem
->IsDefaultTabBgColor() && !rStyleSettings
.GetHighContrastMode();
1197 OUString aText
= pItem
->mbShort
?
1198 rRenderContext
.GetEllipsisString(pItem
->GetRenderText(), mnCurMaxWidth
) :
1199 pItem
->GetRenderText();
1201 aDrawer
.setRect(aRect
);
1202 aDrawer
.setSelected(bSelected
);
1203 aDrawer
.setCustomColored(bCustomBgColor
);
1204 aDrawer
.setEnabled(true);
1205 aDrawer
.setCustomColor(pItem
->maTabBgColor
);
1206 aDrawer
.mbProtect
= pItem
->mbProtect
;
1209 // currently visible sheet is drawn using a bold font
1211 rRenderContext
.SetFont(aFont
);
1213 rRenderContext
.SetFont(aLightFont
);
1215 // Set the correct FillInBrush depending on status
1218 rRenderContext
.SetTextColor(aSelectTextColor
);
1219 else if (bCustomBgColor
)
1220 rRenderContext
.SetTextColor(pItem
->maTabTextColor
);
1222 rRenderContext
.SetTextColor(aFaceTextColor
);
1224 // Special display of tab name depending on page bits
1226 if (pItem
->mnBits
& TabBarPageBits::Blue
)
1228 rRenderContext
.SetTextColor(COL_LIGHTBLUE
);
1230 if (pItem
->mnBits
& TabBarPageBits::Italic
)
1232 vcl::Font aSpecialFont
= rRenderContext
.GetFont();
1233 aSpecialFont
.SetItalic(FontItalic::ITALIC_NORMAL
);
1234 rRenderContext
.SetFont(aSpecialFont
);
1236 if (pItem
->mnBits
& TabBarPageBits::Underline
)
1238 vcl::Font aSpecialFont
= rRenderContext
.GetFont();
1239 aSpecialFont
.SetUnderline(LINESTYLE_SINGLE
);
1240 rRenderContext
.SetFont(aSpecialFont
);
1243 aDrawer
.drawText(aText
);
1247 rRenderContext
.SetLineColor();
1248 rRenderContext
.SetFillColor(aSelectColor
);
1249 aDrawer
.drawOverTopBorder();
1266 rRenderContext
.Pop();
1269 void TabBar::Resize()
1271 Size aNewSize
= GetOutputSizePixel();
1273 tools::Long nSizerWidth
= 0;
1276 if ( mpImpl
->mpSizer
)
1278 Size aSizerSize
= mpImpl
->mpSizer
->GetSizePixel();
1279 Point
aNewSizerPos( mbMirrored
? 0 : (aNewSize
.Width()-aSizerSize
.Width()), 0 );
1280 Size
aNewSizerSize( aSizerSize
.Width(), aNewSize
.Height() );
1281 mpImpl
->mpSizer
->SetPosSizePixel( aNewSizerPos
, aNewSizerSize
);
1282 nSizerWidth
= aSizerSize
.Width();
1285 // order the scroll buttons
1286 tools::Long
const nHeight
= aNewSize
.Height();
1287 // adapt font height?
1288 ImplInitSettings( true, false );
1290 mpImpl
->mxButtonBox
->AdaptToHeight(nHeight
);
1291 Size
const aBtnsSize(mpImpl
->mxButtonBox
->get_preferred_size().Width(), nHeight
);
1292 Point
aPos(mbMirrored
? (aNewSize
.Width() - aBtnsSize
.Width()) : 0, 0);
1293 mpImpl
->mxButtonBox
->SetPosSizePixel(aPos
, aBtnsSize
);
1294 auto nButtonWidth
= aBtnsSize
.Width();
1297 maWinSize
= aNewSize
;
1301 mnOffX
= nSizerWidth
;
1302 mnLastOffX
= maWinSize
.Width() - nButtonWidth
- 1;
1306 mnOffX
= nButtonWidth
;
1307 mnLastOffX
= maWinSize
.Width() - nSizerWidth
- 1;
1311 mbSizeFormat
= true;
1312 if ( IsReallyVisible() )
1314 if ( ImplCalcWidth() )
1319 // Ensure as many tabs as possible are visible:
1320 sal_uInt16 nLastFirstPos
= ImplGetLastFirstPos();
1321 if ( mnFirstPos
> nLastFirstPos
)
1323 mnFirstPos
= nLastFirstPos
;
1327 // Ensure the currently selected page is visible
1328 ImplShowPage(GetPagePos(mnCurPageId
));
1333 // enable/disable button
1334 ImplEnableControls();
1337 bool TabBar::PreNotify(NotifyEvent
& rNEvt
)
1339 if (rNEvt
.GetType() == NotifyEventType::COMMAND
)
1341 if (rNEvt
.GetCommandEvent()->GetCommand() == CommandEventId::Wheel
)
1343 const CommandWheelData
* pData
= rNEvt
.GetCommandEvent()->GetWheelData();
1344 sal_uInt16 nNewPos
= mnFirstPos
;
1345 if (pData
->GetNotchDelta() > 0)
1348 nNewPos
= mnFirstPos
- 1;
1350 else if (pData
->GetNotchDelta() < 0)
1352 sal_uInt16 nCount
= GetPageCount();
1353 if (mnFirstPos
< nCount
)
1354 nNewPos
= mnFirstPos
+ 1;
1356 if (nNewPos
!= mnFirstPos
)
1357 SetFirstPageId(GetPageId(nNewPos
));
1360 return Window::PreNotify(rNEvt
);
1363 void TabBar::RequestHelp(const HelpEvent
& rHEvt
)
1365 sal_uInt16 nItemId
= GetPageId(ScreenToOutputPixel(rHEvt
.GetMousePosPixel()));
1368 if (rHEvt
.GetMode() & HelpEventMode::BALLOON
)
1370 OUString aStr
= GetHelpText(nItemId
);
1371 if (!aStr
.isEmpty())
1373 tools::Rectangle aItemRect
= GetPageRect(nItemId
);
1374 Point aPt
= OutputToScreenPixel(aItemRect
.TopLeft());
1375 aItemRect
.SetLeft( aPt
.X() );
1376 aItemRect
.SetTop( aPt
.Y() );
1377 aPt
= OutputToScreenPixel(aItemRect
.BottomRight());
1378 aItemRect
.SetRight( aPt
.X() );
1379 aItemRect
.SetBottom( aPt
.Y() );
1380 Help::ShowBalloon(this, aItemRect
.Center(), aItemRect
, aStr
);
1385 // show text for quick- or balloon-help
1386 // if this is isolated or not fully visible
1387 if (rHEvt
.GetMode() & (HelpEventMode::QUICK
| HelpEventMode::BALLOON
))
1389 sal_uInt16 nPos
= GetPagePos(nItemId
);
1390 auto& rItem
= mpImpl
->maItemList
[nPos
];
1391 if (rItem
.mbShort
|| (rItem
.maRect
.Right() - 5 > mnLastOffX
))
1393 tools::Rectangle aItemRect
= GetPageRect(nItemId
);
1394 Point aPt
= OutputToScreenPixel(aItemRect
.TopLeft());
1395 aItemRect
.SetLeft( aPt
.X() );
1396 aItemRect
.SetTop( aPt
.Y() );
1397 aPt
= OutputToScreenPixel(aItemRect
.BottomRight());
1398 aItemRect
.SetRight( aPt
.X() );
1399 aItemRect
.SetBottom( aPt
.Y() );
1400 OUString aStr
= mpImpl
->maItemList
[nPos
].maText
;
1401 if (!aStr
.isEmpty())
1403 if (rHEvt
.GetMode() & HelpEventMode::BALLOON
)
1404 Help::ShowBalloon(this, aItemRect
.Center(), aItemRect
, aStr
);
1406 Help::ShowQuickHelp(this, aItemRect
, aStr
);
1413 Window::RequestHelp(rHEvt
);
1416 void TabBar::StateChanged(StateChangedType nType
)
1418 Window::StateChanged(nType
);
1420 if (nType
== StateChangedType::InitShow
)
1422 if ( (mbSizeFormat
|| mbFormat
) && !mpImpl
->maItemList
.empty() )
1425 else if (nType
== StateChangedType::Zoom
||
1426 nType
== StateChangedType::ControlFont
)
1428 ImplInitSettings(true, false);
1431 else if (nType
== StateChangedType::ControlForeground
)
1433 else if (nType
== StateChangedType::ControlBackground
)
1435 ImplInitSettings(false, true);
1438 else if (nType
== StateChangedType::Mirroring
)
1440 bool bIsRTLEnabled
= IsRTLEnabled();
1441 // reacts on calls of EnableRTL, have to mirror all child controls
1442 if (mpImpl
->mpSizer
)
1443 mpImpl
->mpSizer
->EnableRTL(bIsRTLEnabled
);
1444 if (mpImpl
->mxButtonBox
)
1446 mpImpl
->mxButtonBox
->m_xFirstButton
->set_direction(bIsRTLEnabled
);
1447 mpImpl
->mxButtonBox
->m_xPrevButton
->set_direction(bIsRTLEnabled
);
1448 mpImpl
->mxButtonBox
->m_xNextButton
->set_direction(bIsRTLEnabled
);
1449 mpImpl
->mxButtonBox
->m_xLastButton
->set_direction(bIsRTLEnabled
);
1450 mpImpl
->mxButtonBox
->m_xAddButton
->set_direction(bIsRTLEnabled
);
1454 weld::Entry
& rEntry
= mpImpl
->mxEdit
->get_widget();
1455 rEntry
.set_direction(bIsRTLEnabled
);
1460 void TabBar::DataChanged(const DataChangedEvent
& rDCEvt
)
1462 Window::DataChanged(rDCEvt
);
1464 if (rDCEvt
.GetType() == DataChangedEventType::FONTS
1465 || rDCEvt
.GetType() == DataChangedEventType::FONTSUBSTITUTION
1466 || (rDCEvt
.GetType() == DataChangedEventType::SETTINGS
1467 && rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
))
1469 ImplInitSettings(true, true);
1474 void TabBar::ImplSelect()
1477 CallEventListeners(VclEventId::TabbarPageSelected
, reinterpret_cast<void*>(sal::static_int_cast
<sal_IntPtr
>(mnCurPageId
)));
1480 void TabBar::Select()
1482 maSelectHdl
.Call(this);
1485 void TabBar::DoubleClick()
1489 void TabBar::Split()
1491 maSplitHdl
.Call(this);
1494 void TabBar::ImplActivatePage()
1498 CallEventListeners(VclEventId::TabbarPageActivated
, reinterpret_cast<void*>(sal::static_int_cast
<sal_IntPtr
>(mnCurPageId
)));
1501 void TabBar::ActivatePage()
1504 bool TabBar::ImplDeactivatePage()
1506 bool bRet
= DeactivatePage();
1508 CallEventListeners(VclEventId::TabbarPageDeactivated
, reinterpret_cast<void*>(sal::static_int_cast
<sal_IntPtr
>(mnCurPageId
)));
1513 void TabBar::ImplPrePaint()
1515 sal_uInt16 nItemCount
= mpImpl
->getItemSize();
1519 // tabbar should be formatted
1522 // assure the actual tabpage becomes visible at first format
1526 mbFirstFormat
= false;
1528 if (!mnCurPageId
|| (mnFirstPos
!= 0) || mbDropPos
)
1531 auto& rItem
= mpImpl
->maItemList
[GetPagePos(mnCurPageId
)];
1532 if (rItem
.maRect
.IsEmpty())
1534 // set mbDropPos (or misuse) to prevent Invalidate()
1536 SetFirstPageId(mnCurPageId
);
1538 if (mnFirstPos
!= 0)
1543 ImplTabBarItem
* TabBar::ImplGetLastTabBarItem( sal_uInt16 nItemCount
)
1545 // find last visible entry
1546 sal_uInt16 n
= mnFirstPos
+ 1;
1547 if (n
>= nItemCount
)
1549 ImplTabBarItem
* pItem
= seek(n
);
1552 if (!pItem
->maRect
.IsEmpty())
1561 // draw all tabs (from back to front and actual last)
1564 else if (n
>= nItemCount
)
1570 bool TabBar::DeactivatePage()
1575 bool TabBar::StartRenaming()
1580 TabBarAllowRenamingReturnCode
TabBar::AllowRenaming()
1582 return TABBAR_RENAMING_YES
;
1585 void TabBar::EndRenaming()
1589 void TabBar::Mirror()
1594 void TabBar::AddTabClick()
1599 void TabBar::InsertPage(sal_uInt16 nPageId
, const OUString
& rText
,
1600 TabBarPageBits nBits
, sal_uInt16 nPos
)
1602 assert (nPageId
&& "TabBar::InsertPage(): PageId must not be 0");
1603 assert ((GetPagePos(nPageId
) == PAGE_NOT_FOUND
) && "TabBar::InsertPage(): Page already exists");
1604 assert ((nBits
<= TPB_DISPLAY_NAME_ALLFLAGS
) && "TabBar::InsertPage(): Invalid flag set in nBits");
1606 // create PageItem and insert in the item list
1607 ImplTabBarItem
aItem( nPageId
, rText
, nBits
);
1608 if (nPos
< mpImpl
->maItemList
.size())
1610 auto it
= mpImpl
->maItemList
.begin();
1612 mpImpl
->maItemList
.insert(it
, aItem
);
1616 mpImpl
->maItemList
.push_back(aItem
);
1618 mbSizeFormat
= true;
1620 // set CurPageId if required
1622 mnCurPageId
= nPageId
;
1625 if (IsReallyVisible() && IsUpdateMode())
1628 CallEventListeners(VclEventId::TabbarPageInserted
, reinterpret_cast<void*>(sal::static_int_cast
<sal_IntPtr
>(nPageId
)));
1631 Color
TabBar::GetTabBgColor(sal_uInt16 nPageId
) const
1633 sal_uInt16 nPos
= GetPagePos(nPageId
);
1635 if (nPos
!= PAGE_NOT_FOUND
)
1636 return mpImpl
->maItemList
[nPos
].maTabBgColor
;
1641 void TabBar::SetTabBgColor(sal_uInt16 nPageId
, const Color
& aTabBgColor
)
1643 sal_uInt16 nPos
= GetPagePos(nPageId
);
1644 if (nPos
== PAGE_NOT_FOUND
)
1647 auto& rItem
= mpImpl
->maItemList
[nPos
];
1648 if (aTabBgColor
!= COL_AUTO
)
1650 rItem
.maTabBgColor
= aTabBgColor
;
1651 if (aTabBgColor
.GetLuminance() <= 128) //Do not use aTabBgColor.IsDark(), because that threshold is way too low...
1652 rItem
.maTabTextColor
= COL_WHITE
;
1654 rItem
.maTabTextColor
= COL_BLACK
;
1658 rItem
.maTabBgColor
= COL_AUTO
;
1659 rItem
.maTabTextColor
= COL_AUTO
;
1663 void TabBar::RemovePage(sal_uInt16 nPageId
)
1665 sal_uInt16 nPos
= GetPagePos(nPageId
);
1668 if (nPos
== PAGE_NOT_FOUND
)
1671 if (mnCurPageId
== nPageId
)
1674 // check if first visible page should be moved
1675 if (mnFirstPos
> nPos
)
1679 auto it
= mpImpl
->maItemList
.begin();
1681 mpImpl
->maItemList
.erase(it
);
1684 if (IsReallyVisible() && IsUpdateMode())
1687 CallEventListeners(VclEventId::TabbarPageRemoved
, reinterpret_cast<void*>(sal::static_int_cast
<sal_IntPtr
>(nPageId
)));
1690 void TabBar::MovePage(sal_uInt16 nPageId
, sal_uInt16 nNewPos
)
1692 sal_uInt16 nPos
= GetPagePos(nPageId
);
1693 Pair
aPair(nPos
, nNewPos
);
1698 if (nPos
== nNewPos
)
1702 if (nPos
== PAGE_NOT_FOUND
)
1705 // move tabbar item in the list
1706 auto it
= mpImpl
->maItemList
.begin();
1708 ImplTabBarItem aItem
= std::move(*it
);
1709 mpImpl
->maItemList
.erase(it
);
1710 if (nNewPos
< mpImpl
->maItemList
.size())
1712 it
= mpImpl
->maItemList
.begin();
1714 mpImpl
->maItemList
.insert(it
, aItem
);
1718 mpImpl
->maItemList
.push_back(aItem
);
1722 if (IsReallyVisible() && IsUpdateMode())
1725 CallEventListeners( VclEventId::TabbarPageMoved
, static_cast<void*>(&aPair
) );
1728 void TabBar::Clear()
1731 mpImpl
->maItemList
.clear();
1733 // remove items from the list
1734 mbSizeFormat
= true;
1737 maCurrentItemList
= 0;
1740 if (IsReallyVisible() && IsUpdateMode())
1743 CallEventListeners(VclEventId::TabbarPageRemoved
, reinterpret_cast<void*>(sal::static_int_cast
<sal_IntPtr
>(PAGE_NOT_FOUND
)));
1746 bool TabBar::IsPageEnabled(sal_uInt16 nPageId
) const
1750 sal_uInt16 nPos
= GetPagePos(nPageId
);
1752 return nPos
!= PAGE_NOT_FOUND
;
1755 void TabBar::SetPageBits(sal_uInt16 nPageId
, TabBarPageBits nBits
)
1757 sal_uInt16 nPos
= GetPagePos(nPageId
);
1759 if (nPos
== PAGE_NOT_FOUND
)
1762 auto& rItem
= mpImpl
->maItemList
[nPos
];
1764 if (rItem
.mnBits
!= nBits
)
1766 rItem
.mnBits
= nBits
;
1769 if (IsReallyVisible() && IsUpdateMode())
1770 Invalidate(rItem
.maRect
);
1774 TabBarPageBits
TabBar::GetPageBits(sal_uInt16 nPageId
) const
1776 sal_uInt16 nPos
= GetPagePos(nPageId
);
1778 if (nPos
!= PAGE_NOT_FOUND
)
1779 return mpImpl
->maItemList
[nPos
].mnBits
;
1781 return TabBarPageBits::NONE
;
1784 sal_uInt16
TabBar::GetPageCount() const
1786 return mpImpl
->getItemSize();
1789 sal_uInt16
TabBar::GetPageId(sal_uInt16 nPos
) const
1791 return nPos
< mpImpl
->maItemList
.size() ? mpImpl
->maItemList
[nPos
].mnId
: 0;
1794 sal_uInt16
TabBar::GetPagePos(sal_uInt16 nPageId
) const
1796 for (size_t i
= 0; i
< mpImpl
->maItemList
.size(); ++i
)
1798 if (mpImpl
->maItemList
[i
].mnId
== nPageId
)
1800 return static_cast<sal_uInt16
>(i
);
1803 return PAGE_NOT_FOUND
;
1806 sal_uInt16
TabBar::GetPageId(const Point
& rPos
) const
1808 for (const auto& rItem
: mpImpl
->maItemList
)
1810 if (rItem
.maRect
.Contains(rPos
))
1817 tools::Rectangle
TabBar::GetPageRect(sal_uInt16 nPageId
) const
1819 sal_uInt16 nPos
= GetPagePos(nPageId
);
1821 if (nPos
!= PAGE_NOT_FOUND
)
1822 return mpImpl
->maItemList
[nPos
].maRect
;
1824 return tools::Rectangle();
1827 void TabBar::SetCurPageId(sal_uInt16 nPageId
)
1829 sal_uInt16 nPos
= GetPagePos(nPageId
);
1831 // do nothing if item does not exit
1832 if (nPos
== PAGE_NOT_FOUND
)
1835 // do nothing if the actual page did not change
1836 if (nPageId
== mnCurPageId
)
1840 bool bUpdate
= false;
1841 if (IsReallyVisible() && IsUpdateMode())
1844 auto& rItem
= mpImpl
->maItemList
[nPos
];
1845 ImplTabBarItem
* pOldItem
;
1848 pOldItem
= &mpImpl
->maItemList
[GetPagePos(mnCurPageId
)];
1852 // deselect previous page if page was not selected, if this is the
1853 // only selected page
1854 if (!rItem
.mbSelect
&& pOldItem
)
1856 sal_uInt16 nSelPageCount
= GetSelectPageCount();
1857 if (nSelPageCount
== 1)
1858 pOldItem
->mbSelect
= false;
1859 rItem
.mbSelect
= true;
1862 mnCurPageId
= nPageId
;
1865 // assure the actual page becomes visible
1866 if (IsReallyVisible())
1868 if (nPos
< mnFirstPos
)
1869 SetFirstPageId(nPageId
);
1872 // calculate visible width
1873 tools::Long nWidth
= mnLastOffX
;
1874 if (nWidth
> ADDNEWPAGE_AREAWIDTH
)
1875 nWidth
-= ADDNEWPAGE_AREAWIDTH
;
1877 if (rItem
.maRect
.IsEmpty())
1880 while ((mbMirrored
? (rItem
.maRect
.Left() < mnOffX
) : (rItem
.maRect
.Right() > nWidth
)) ||
1881 rItem
.maRect
.IsEmpty())
1883 sal_uInt16 nNewPos
= mnFirstPos
+ 1;
1884 // assure at least the actual tabpages are visible as first tabpage
1885 if (nNewPos
>= nPos
)
1887 SetFirstPageId(nPageId
);
1891 SetFirstPageId(GetPageId(nNewPos
));
1893 // abort if first page is not forwarded
1894 if (nNewPos
!= mnFirstPos
)
1903 Invalidate(rItem
.maRect
);
1905 Invalidate(pOldItem
->maRect
);
1909 void TabBar::MakeVisible(sal_uInt16 nPageId
)
1911 if (!IsReallyVisible())
1914 sal_uInt16 nPos
= GetPagePos(nPageId
);
1916 // do nothing if item does not exist
1917 if (nPos
== PAGE_NOT_FOUND
)
1920 if (nPos
< mnFirstPos
)
1921 SetFirstPageId(nPageId
);
1924 auto& rItem
= mpImpl
->maItemList
[nPos
];
1926 // calculate visible area
1927 tools::Long nWidth
= mnLastOffX
;
1929 if (mbFormat
|| rItem
.maRect
.IsEmpty())
1935 while ((rItem
.maRect
.Right() > nWidth
) ||
1936 rItem
.maRect
.IsEmpty())
1938 sal_uInt16 nNewPos
= mnFirstPos
+1;
1939 // assure at least the actual tabpages are visible as first tabpage
1940 if (nNewPos
>= nPos
)
1942 SetFirstPageId(nPageId
);
1946 SetFirstPageId(GetPageId(nNewPos
));
1948 // abort if first page is not forwarded
1949 if (nNewPos
!= mnFirstPos
)
1955 void TabBar::SetFirstPageId(sal_uInt16 nPageId
)
1957 sal_uInt16 nPos
= GetPagePos(nPageId
);
1959 // return false if item does not exist
1960 if (nPos
== PAGE_NOT_FOUND
)
1963 if (nPos
== mnFirstPos
)
1966 // assure as much pages are visible as possible
1968 sal_uInt16 nLastFirstPos
= ImplGetLastFirstPos();
1970 if (nPos
> nLastFirstPos
)
1971 nNewPos
= nLastFirstPos
;
1975 if (nNewPos
!= mnFirstPos
)
1977 mnFirstPos
= nNewPos
;
1980 // redraw bar (attention: check mbDropPos,
1981 // as if this flag was set, we do not re-paint immediately
1982 if (IsReallyVisible() && IsUpdateMode() && !mbDropPos
)
1987 void TabBar::SelectPage(sal_uInt16 nPageId
, bool bSelect
)
1989 sal_uInt16 nPos
= GetPagePos(nPageId
);
1991 if (nPos
== PAGE_NOT_FOUND
)
1994 auto& rItem
= mpImpl
->maItemList
[nPos
];
1996 if (rItem
.mbSelect
!= bSelect
)
1998 rItem
.mbSelect
= bSelect
;
2001 if (IsReallyVisible() && IsUpdateMode())
2002 Invalidate(rItem
.maRect
);
2006 sal_uInt16
TabBar::GetSelectPageCount() const
2008 sal_uInt16 nSelected
= 0;
2009 for (const auto& rItem
: mpImpl
->maItemList
)
2018 bool TabBar::IsPageSelected(sal_uInt16 nPageId
) const
2020 sal_uInt16 nPos
= GetPagePos(nPageId
);
2021 if (nPos
!= PAGE_NOT_FOUND
)
2022 return mpImpl
->maItemList
[nPos
].mbSelect
;
2027 void TabBar::SetProtectionSymbol(sal_uInt16 nPageId
, bool bProtection
)
2029 sal_uInt16 nPos
= GetPagePos(nPageId
);
2030 if (nPos
!= PAGE_NOT_FOUND
)
2032 if (mpImpl
->maItemList
[nPos
].mbProtect
!= bProtection
)
2034 mpImpl
->maItemList
[nPos
].mbProtect
= bProtection
;
2035 mbSizeFormat
= true; // render text width changes, thus bar width
2038 if (IsReallyVisible() && IsUpdateMode())
2044 bool TabBar::StartEditMode(sal_uInt16 nPageId
)
2046 sal_uInt16 nPos
= GetPagePos( nPageId
);
2047 if (mpImpl
->mxEdit
|| (nPos
== PAGE_NOT_FOUND
) || (mnLastOffX
< 8))
2051 if (StartRenaming())
2057 mpImpl
->mxEdit
.disposeAndReset(VclPtr
<TabBarEdit
>::Create(this));
2058 tools::Rectangle aRect
= GetPageRect( mnEditId
);
2059 tools::Long nX
= aRect
.Left();
2060 tools::Long nWidth
= aRect
.GetWidth();
2061 if (mnEditId
!= GetCurPageId())
2063 if (nX
+ nWidth
> mnLastOffX
)
2064 nWidth
= mnLastOffX
-nX
;
2068 nWidth
= aRect
.GetWidth();
2070 weld::Entry
& rEntry
= mpImpl
->mxEdit
->get_widget();
2071 rEntry
.set_text(GetPageText(mnEditId
));
2072 mpImpl
->mxEdit
->SetPosSizePixel(Point(nX
, aRect
.Top() + mnOffY
+ 1), Size(nWidth
, aRect
.GetHeight() - 3));
2073 vcl::Font aFont
= GetPointFont(*GetOutDev()); // FIXME RenderContext
2075 Color aForegroundColor
;
2076 Color aBackgroundColor
;
2079 Color aFaceTextColor
;
2080 Color aSelectTextColor
;
2082 ImplGetColors(Application::GetSettings().GetStyleSettings(), aFaceColor
, aFaceTextColor
, aSelectColor
, aSelectTextColor
);
2084 if (mnEditId
!= GetCurPageId())
2086 aFont
.SetWeight(WEIGHT_LIGHT
);
2088 if (IsPageSelected(mnEditId
) || mnEditId
== GetCurPageId())
2090 aForegroundColor
= aSelectTextColor
;
2091 aBackgroundColor
= aSelectColor
;
2095 aForegroundColor
= aFaceTextColor
;
2096 aBackgroundColor
= aFaceColor
;
2098 if (GetPageBits( mnEditId
) & TabBarPageBits::Blue
)
2100 aForegroundColor
= COL_LIGHTBLUE
;
2102 rEntry
.set_font(aFont
);
2103 rEntry
.set_font_color(aForegroundColor
);
2104 mpImpl
->mxEdit
->SetControlBackground(aBackgroundColor
);
2105 rEntry
.grab_focus();
2106 rEntry
.select_region(0, -1);
2107 mpImpl
->mxEdit
->Show();
2117 bool TabBar::IsInEditMode() const
2119 return bool(mpImpl
->mxEdit
);
2122 void TabBar::EndEditMode(bool bCancel
)
2124 if (!mpImpl
->mxEdit
)
2129 mbEditCanceled
= bCancel
;
2130 weld::Entry
& rEntry
= mpImpl
->mxEdit
->get_widget();
2131 maEditText
= rEntry
.get_text();
2132 mpImpl
->mxEdit
->SetPostEvent();
2135 TabBarAllowRenamingReturnCode nAllowRenaming
= AllowRenaming();
2136 if (nAllowRenaming
== TABBAR_RENAMING_YES
)
2137 SetPageText(mnEditId
, maEditText
);
2138 else if (nAllowRenaming
== TABBAR_RENAMING_NO
)
2140 else // nAllowRenaming == TABBAR_RENAMING_CANCEL
2141 mbEditCanceled
= true;
2144 // renaming not allowed, then reset edit data
2147 mpImpl
->mxEdit
->ResetPostEvent();
2148 rEntry
.grab_focus();
2152 // close edit and call end hdl
2153 mpImpl
->mxEdit
.disposeAndClear();
2161 mbEditCanceled
= false;
2164 void TabBar::SetMirrored(bool bMirrored
)
2166 if (mbMirrored
!= bMirrored
)
2168 mbMirrored
= bMirrored
;
2169 mbSizeFormat
= true;
2170 ImplInitControls(); // for button images
2171 Resize(); // recalculates control positions
2176 void TabBar::SetEffectiveRTL(bool bRTL
)
2178 SetMirrored( bRTL
!= AllSettings::GetLayoutRTL() );
2181 bool TabBar::IsEffectiveRTL() const
2183 return IsMirrored() != AllSettings::GetLayoutRTL();
2186 void TabBar::SetMaxPageWidth(tools::Long nMaxWidth
)
2188 if (mnMaxPageWidth
!= nMaxWidth
)
2190 mnMaxPageWidth
= nMaxWidth
;
2191 mbSizeFormat
= true;
2194 if (IsReallyVisible() && IsUpdateMode())
2199 void TabBar::SetPageText(sal_uInt16 nPageId
, const OUString
& rText
)
2201 sal_uInt16 nPos
= GetPagePos(nPageId
);
2202 if (nPos
!= PAGE_NOT_FOUND
)
2204 mpImpl
->maItemList
[nPos
].maText
= rText
;
2205 mbSizeFormat
= true;
2208 if (IsReallyVisible() && IsUpdateMode())
2211 CallEventListeners(VclEventId::TabbarPageTextChanged
, reinterpret_cast<void*>(sal::static_int_cast
<sal_IntPtr
>(nPageId
)));
2215 const OUString
& TabBar::GetPageText(sal_uInt16 nPageId
) const
2217 sal_uInt16 nPos
= GetPagePos(nPageId
);
2218 if (nPos
!= PAGE_NOT_FOUND
)
2219 return mpImpl
->maItemList
[nPos
].maText
;
2220 return EMPTY_OUSTRING
;
2223 const OUString
& TabBar::GetAuxiliaryText(sal_uInt16 nPageId
) const
2225 sal_uInt16 nPos
= GetPagePos(nPageId
);
2226 if (nPos
!= PAGE_NOT_FOUND
)
2227 return mpImpl
->maItemList
[nPos
].maAuxiliaryText
;
2228 return EMPTY_OUSTRING
;
2231 void TabBar::SetAuxiliaryText(sal_uInt16 nPageId
, const OUString
& rText
)
2233 sal_uInt16 nPos
= GetPagePos(nPageId
);
2234 if (nPos
!= PAGE_NOT_FOUND
)
2236 mpImpl
->maItemList
[nPos
].maAuxiliaryText
= rText
;
2237 // no redraw bar, no CallEventListener, internal use in LayerTabBar
2241 OUString
TabBar::GetHelpText(sal_uInt16 nPageId
) const
2243 sal_uInt16 nPos
= GetPagePos(nPageId
);
2244 if (nPos
!= PAGE_NOT_FOUND
)
2246 auto& rItem
= mpImpl
->maItemList
[nPos
];
2247 if (rItem
.maHelpText
.isEmpty() && !rItem
.maHelpId
.isEmpty())
2249 Help
* pHelp
= Application::GetHelp();
2251 rItem
.maHelpText
= pHelp
->GetHelpText(OStringToOUString(rItem
.maHelpId
, RTL_TEXTENCODING_UTF8
));
2254 return rItem
.maHelpText
;
2259 bool TabBar::StartDrag(const CommandEvent
& rCEvt
, vcl::Region
& rRegion
)
2261 if (!(mnWinStyle
& WB_DRAG
) || (rCEvt
.GetCommand() != CommandEventId::StartDrag
))
2264 // Check if the clicked page was selected. If this is not the case
2265 // set it as actual entry. We check for this only at a mouse action
2266 // if Drag and Drop can be triggered from the keyboard.
2267 // We only do this, if Select() was not triggered, as the Select()
2268 // could have scrolled the area
2269 if (rCEvt
.IsMouseEvent() && !mbInSelect
)
2271 sal_uInt16 nSelId
= GetPageId(rCEvt
.GetMousePosPixel());
2273 // do not start dragging if no entry was clicked
2277 // check if page was selected. If not set it as actual
2278 // page and call Select()
2279 if (!IsPageSelected(nSelId
))
2281 if (ImplDeactivatePage())
2283 SetCurPageId(nSelId
);
2295 rRegion
= vcl::Region();
2300 sal_uInt16
TabBar::ShowDropPos(const Point
& rPos
)
2302 sal_uInt16 nNewDropPos
;
2303 sal_uInt16 nItemCount
= mpImpl
->getItemSize();
2304 sal_Int16 nScroll
= 0;
2306 if (rPos
.X() > mnLastOffX
-TABBAR_DRAG_SCROLLOFF
)
2308 auto& rItem
= mpImpl
->maItemList
[mpImpl
->maItemList
.size() - 1];
2309 if (!rItem
.maRect
.IsEmpty() && (rPos
.X() > rItem
.maRect
.Right()))
2310 nNewDropPos
= mpImpl
->getItemSize();
2313 nNewDropPos
= mnFirstPos
+ 1;
2317 else if ((rPos
.X() <= mnOffX
) ||
2318 (!mnOffX
&& (rPos
.X() <= TABBAR_DRAG_SCROLLOFF
)))
2322 nNewDropPos
= mnFirstPos
;
2330 sal_uInt16 nDropId
= GetPageId(rPos
);
2333 nNewDropPos
= GetPagePos(nDropId
);
2334 if (mnFirstPos
&& (nNewDropPos
== mnFirstPos
- 1))
2338 nNewDropPos
= nItemCount
;
2341 if (mbDropPos
&& (nNewDropPos
== mnDropPos
) && !nScroll
)
2347 mnDropPos
= nNewDropPos
;
2351 sal_uInt16 nOldFirstPos
= mnFirstPos
;
2352 SetFirstPageId(GetPageId(mnFirstPos
+ nScroll
));
2354 // draw immediately, as Paint not possible during Drag and Drop
2355 if (nOldFirstPos
!= mnFirstPos
)
2357 tools::Rectangle
aRect(mnOffX
, 0, mnLastOffX
, maWinSize
.Height());
2358 GetOutDev()->SetFillColor(GetBackground().GetColor());
2359 GetOutDev()->DrawRect(aRect
);
2364 // draw drop position arrows
2365 const StyleSettings
& rStyles
= Application::GetSettings().GetStyleSettings();
2366 const Color aTextColor
= rStyles
.GetLabelTextColor();
2368 tools::Long nY
= (maWinSize
.Height() / 2) - 1;
2369 sal_uInt16 nCurPos
= GetPagePos(mnCurPageId
);
2371 sal_Int32 nTriangleWidth
= 3 * GetDPIScaleFactor();
2373 if (mnDropPos
< nItemCount
)
2375 GetOutDev()->SetLineColor(aTextColor
);
2376 GetOutDev()->SetFillColor(aTextColor
);
2378 auto& rItem
= mpImpl
->maItemList
[mnDropPos
];
2379 nX
= rItem
.maRect
.Left();
2380 if ( mnDropPos
== nCurPos
)
2385 if (!rItem
.IsDefaultTabBgColor() && !rItem
.mbSelect
)
2387 GetOutDev()->SetLineColor(rItem
.maTabTextColor
);
2388 GetOutDev()->SetFillColor(rItem
.maTabTextColor
);
2391 tools::Polygon
aPoly(3);
2392 aPoly
.SetPoint(Point(nX
, nY
), 0);
2393 aPoly
.SetPoint(Point(nX
+ nTriangleWidth
, nY
- nTriangleWidth
), 1);
2394 aPoly
.SetPoint(Point(nX
+ nTriangleWidth
, nY
+ nTriangleWidth
), 2);
2395 GetOutDev()->DrawPolygon(aPoly
);
2397 if (mnDropPos
> 0 && mnDropPos
< nItemCount
+ 1)
2399 GetOutDev()->SetLineColor(aTextColor
);
2400 GetOutDev()->SetFillColor(aTextColor
);
2402 auto& rItem
= mpImpl
->maItemList
[mnDropPos
- 1];
2403 nX
= rItem
.maRect
.Right();
2404 if (mnDropPos
== nCurPos
)
2406 if (!rItem
.IsDefaultTabBgColor() && !rItem
.mbSelect
)
2408 GetOutDev()->SetLineColor(rItem
.maTabTextColor
);
2409 GetOutDev()->SetFillColor(rItem
.maTabTextColor
);
2411 tools::Polygon
aPoly(3);
2412 aPoly
.SetPoint(Point(nX
, nY
), 0);
2413 aPoly
.SetPoint(Point(nX
- nTriangleWidth
, nY
- nTriangleWidth
), 1);
2414 aPoly
.SetPoint(Point(nX
- nTriangleWidth
, nY
+ nTriangleWidth
), 2);
2415 GetOutDev()->DrawPolygon(aPoly
);
2421 void TabBar::HideDropPos()
2427 tools::Long nY1
= (maWinSize
.Height() / 2) - 3;
2428 tools::Long nY2
= nY1
+ 5;
2429 sal_uInt16 nItemCount
= mpImpl
->getItemSize();
2431 if (mnDropPos
< nItemCount
)
2433 auto& rItem
= mpImpl
->maItemList
[mnDropPos
];
2434 nX
= rItem
.maRect
.Left();
2435 // immediately call Paint, as it is not possible during drag and drop
2436 tools::Rectangle
aRect( nX
-1, nY1
, nX
+3, nY2
);
2437 vcl::Region
aRegion( aRect
);
2438 GetOutDev()->SetClipRegion( aRegion
);
2440 GetOutDev()->SetClipRegion();
2442 if (mnDropPos
> 0 && mnDropPos
< nItemCount
+ 1)
2444 auto& rItem
= mpImpl
->maItemList
[mnDropPos
- 1];
2445 nX
= rItem
.maRect
.Right();
2446 // immediately call Paint, as it is not possible during drag and drop
2447 tools::Rectangle
aRect(nX
- 2, nY1
, nX
+ 1, nY2
);
2448 vcl::Region
aRegion(aRect
);
2449 GetOutDev()->SetClipRegion(aRegion
);
2451 GetOutDev()->SetClipRegion();
2458 void TabBar::SwitchPage(const Point
& rPos
)
2460 sal_uInt16 nSwitchId
= GetPageId(rPos
);
2465 if (nSwitchId
!= mnSwitchId
)
2467 mnSwitchId
= nSwitchId
;
2468 mnSwitchTime
= tools::Time::GetSystemTicks();
2472 // change only after 500 ms
2473 if (mnSwitchId
!= GetCurPageId())
2475 if (tools::Time::GetSystemTicks() > mnSwitchTime
+ 500)
2477 if (ImplDeactivatePage())
2479 SetCurPageId( mnSwitchId
);
2490 void TabBar::EndSwitchPage()
2496 void TabBar::SetStyle(WinBits nStyle
)
2498 if (mnWinStyle
== nStyle
)
2500 mnWinStyle
= nStyle
;
2502 // order possible controls
2503 if (IsReallyVisible() && IsUpdateMode())
2507 Size
TabBar::CalcWindowSizePixel() const
2509 tools::Long nWidth
= 0;
2511 if (!mpImpl
->maItemList
.empty())
2513 const_cast<TabBar
*>(this)->ImplCalcWidth();
2514 for (const auto& rItem
: mpImpl
->maItemList
)
2516 nWidth
+= rItem
.mnWidth
;
2520 return Size(nWidth
, GetSettings().GetStyleSettings().GetScrollBarSize());
2523 tools::Rectangle
TabBar::GetPageArea() const
2525 return tools::Rectangle(Point(mnOffX
, mnOffY
),
2526 Size(mnLastOffX
- mnOffX
+ 1, GetSizePixel().Height() - mnOffY
));
2529 void TabBar::SetAddButtonEnabled(bool bAddButtonEnabled
)
2531 mpImpl
->mxButtonBox
->m_xAddButton
->set_sensitive(bAddButtonEnabled
);
2534 css::uno::Reference
<css::accessibility::XAccessible
> TabBar::CreateAccessible()
2536 return new accessibility::AccessibleTabBar(this);
2539 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */