fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / svtools / source / control / tabbar.cxx
blobaebebd3617b754056db6233d5db1ccc022e77d1e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <svtools/tabbar.hxx>
22 #include <tools/time.hxx>
23 #include <tools/debug.hxx>
24 #include <tools/poly.hxx>
25 #include <vcl/svapp.hxx>
26 #include <vcl/help.hxx>
27 #include <vcl/decoview.hxx>
28 #include <vcl/button.hxx>
29 #include <vcl/edit.hxx>
30 #include <vcl/image.hxx>
31 #include <vcl/settings.hxx>
32 #include "svtaccessiblefactory.hxx"
33 #include <filectrl.hrc>
34 #include <svtools/svtresid.hxx>
35 #include <svtools/svtools.hrc>
36 #include <limits>
37 #include <utility>
39 namespace
42 #define TABBAR_DRAG_SCROLLOFF 5
43 #define TABBAR_MINSIZE 5
45 const sal_uInt16 ADDNEWPAGE_AREAWIDTH = 10;
46 const sal_uInt16 BUTTON_MARGIN = 6;
48 class TabDrawer
50 private:
51 TabBar& mrParent;
52 vcl::RenderContext& mrRenderContext;
53 const StyleSettings& mrStyleSettings;
55 Rectangle maRect;
57 Color maSelectedColor;
58 Color maCustomColor;
59 Color maUnselectedColor;
61 bool mbSelected:1;
62 bool mbCustomColored:1;
63 bool mbSpecialTab:1;
64 bool mbEnabled:1;
66 public:
67 explicit TabDrawer(TabBar& rParent, vcl::RenderContext& rRenderContext)
68 : mrParent(rParent)
69 , mrRenderContext(rRenderContext)
70 , mrStyleSettings(rRenderContext.GetSettings().GetStyleSettings())
71 , mbSelected(false)
72 , mbCustomColored(false)
73 , mbSpecialTab(false)
74 , mbEnabled(false)
78 void drawOutputAreaBorder()
80 WinBits nWinStyle = mrParent.GetStyle();
82 // draw extra line if above and below border
83 if ((nWinStyle & WB_BORDER) || (nWinStyle & WB_TOPBORDER))
85 Size aOutputSize(mrParent.GetOutputSizePixel());
86 Rectangle aOutRect = mrParent.GetPageArea();
88 // also draw border in 3D for 3D-tabs
89 if (nWinStyle & WB_3DTAB)
91 mrRenderContext.SetLineColor(mrStyleSettings.GetShadowColor());
92 mrRenderContext.DrawLine(Point(aOutRect.Left(), 0), Point(aOutputSize.Width(), 0));
95 // draw border (line above and line below)
96 mrRenderContext.SetLineColor(mrStyleSettings.GetDarkShadowColor());
97 mrRenderContext.DrawLine(aOutRect.TopLeft(), Point(aOutputSize.Width() - 1, aOutRect.Top()));
101 void drawOuterFrame()
103 mrRenderContext.SetLineColor(mrStyleSettings.GetDarkShadowColor());
105 // set correct FillInBrush depending on status
106 if (mbSelected)
108 // Currently selected Tab
109 mrRenderContext.SetFillColor(maSelectedColor);
111 else if (mbCustomColored)
113 mrRenderContext.SetFillColor(maCustomColor);
115 else
117 mrRenderContext.SetFillColor(maUnselectedColor);
120 mrRenderContext.DrawRect(maRect);
123 void drawText(const OUString& aText)
125 Rectangle aRect = maRect;
126 long nTextWidth = mrRenderContext.GetTextWidth(aText);
127 long nTextHeight = mrRenderContext.GetTextHeight();
128 Point aPos = aRect.TopLeft();
129 aPos.X() += (aRect.getWidth() - nTextWidth) / 2;
130 aPos.Y() += (aRect.getHeight() - nTextHeight) / 2;
132 if (mbEnabled)
133 mrRenderContext.DrawText(aPos, aText);
134 else
135 mrRenderContext.DrawCtrlText(aPos, aText, 0, aText.getLength(), (DrawTextFlags::Disable | DrawTextFlags::Mnemonic));
138 void drawOverTopBorder()
140 Point aTopLeft = maRect.TopLeft() + Point(1, 0);
141 Point aTopRight = maRect.TopRight() + Point(-1, 0);
143 Rectangle aDelRect(aTopLeft, aTopRight);
144 mrRenderContext.DrawRect(aDelRect);
147 void drawColorLine()
149 mrRenderContext.SetFillColor(maCustomColor);
150 mrRenderContext.SetLineColor(maCustomColor);
152 Rectangle aLineRect(maRect.BottomLeft(), maRect.BottomRight());
153 aLineRect.Top() -= 3;
155 mrRenderContext.DrawRect(aLineRect);
158 void drawTab()
160 drawOuterFrame();
162 if (mbCustomColored && mbSelected)
164 drawColorLine();
168 void setRect(const Rectangle& rRect)
170 maRect = rRect;
173 void setSelected(bool bSelected)
175 mbSelected = bSelected;
178 void setCustomColored(bool bCustomColored)
180 mbCustomColored = bCustomColored;
183 void setSpecialTab(bool bSpecialTab)
185 mbSpecialTab = bSpecialTab;
188 void setEnabled(bool bEnabled)
190 mbEnabled = bEnabled;
193 void setSelectedFillColor(const Color& rColor)
195 maSelectedColor = rColor;
198 void setUnselectedFillColor(const Color& rColor)
200 maUnselectedColor = rColor;
203 void setCustomColor(const Color& rColor)
205 maCustomColor = rColor;
209 } // anonymous namespace
211 struct ImplTabBarItem
213 sal_uInt16 mnId;
214 TabBarPageBits mnBits;
215 OUString maText;
216 OUString maHelpText;
217 Rectangle maRect;
218 long mnWidth;
219 OString maHelpId;
220 bool mbShort : 1;
221 bool mbSelect : 1;
222 bool mbEnable : 1;
223 Color maTabBgColor;
224 Color maTabTextColor;
226 ImplTabBarItem(sal_uInt16 nItemId, const OUString& rText, TabBarPageBits nPageBits)
227 : mnId(nItemId)
228 , mnBits(nPageBits)
229 , maText(rText)
230 , mnWidth(0)
231 , mbShort(false)
232 , mbSelect(false)
233 , mbEnable(true)
234 , maTabBgColor(Color(COL_AUTO))
235 , maTabTextColor(Color(COL_AUTO))
239 bool IsDefaultTabBgColor() const
241 return maTabBgColor == Color(COL_AUTO);
244 bool IsSelected(ImplTabBarItem* pCurItem) const
246 return mbSelect || (pCurItem == this);
250 class ImplTabButton : public PushButton
252 bool mbModKey : 1;
254 public:
255 ImplTabButton(TabBar* pParent, WinBits nWinStyle = 0)
256 : PushButton(pParent, nWinStyle | WB_FLATBUTTON | WB_RECTSTYLE | WB_SMALLSTYLE | WB_NOLIGHTBORDER | WB_NOPOINTERFOCUS)
257 , mbModKey(false)
260 TabBar* GetParent() const
262 return static_cast<TabBar*>(Window::GetParent());
265 bool isModKeyPressed()
267 return mbModKey;
270 virtual bool PreNotify(NotifyEvent& rNotifyEvent) SAL_OVERRIDE;
271 virtual void MouseButtonDown(const MouseEvent& rMouseEvent) SAL_OVERRIDE;
272 virtual void MouseButtonUp(const MouseEvent& rMouseEvent) SAL_OVERRIDE;
273 virtual void Command(const CommandEvent& rCommandEvent) SAL_OVERRIDE;
276 void ImplTabButton::MouseButtonDown(const MouseEvent& rMouseEvent)
278 mbModKey = rMouseEvent.IsMod1();
279 PushButton::MouseButtonDown(rMouseEvent);
282 void ImplTabButton::MouseButtonUp(const MouseEvent& rMouseEvent)
284 mbModKey = false;
285 PushButton::MouseButtonUp(rMouseEvent);
288 void ImplTabButton::Command(const CommandEvent& rCommandEvent)
290 if (rCommandEvent.GetCommand() == CommandEventId::ContextMenu)
292 TabBar* pParent = GetParent();
293 pParent->maScrollAreaContextHdl.Call((void*)&rCommandEvent);
295 PushButton::Command(rCommandEvent);
298 bool ImplTabButton::PreNotify(NotifyEvent& rNotifyEvent)
300 if (rNotifyEvent.GetType() == MouseNotifyEvent::MOUSEBUTTONDOWN)
302 if (GetParent()->IsInEditMode())
304 GetParent()->EndEditMode();
305 return true;
309 return PushButton::PreNotify(rNotifyEvent);
312 class ImplTabSizer : public vcl::Window
314 public:
315 ImplTabSizer( TabBar* pParent, WinBits nWinStyle = 0 );
317 TabBar* GetParent() const { return static_cast<TabBar*>(Window::GetParent()); }
319 private:
320 void ImplTrack( const Point& rScreenPos );
322 virtual void dispose() SAL_OVERRIDE;
323 virtual void MouseButtonDown( const MouseEvent& rMEvt ) SAL_OVERRIDE;
324 virtual void Tracking( const TrackingEvent& rTEvt ) SAL_OVERRIDE;
325 virtual void Paint( vcl::RenderContext& /*rRenderContext*/, const Rectangle& rRect ) SAL_OVERRIDE;
327 Point maStartPos;
328 long mnStartWidth;
331 ImplTabSizer::ImplTabSizer( TabBar* pParent, WinBits nWinStyle )
332 : Window( pParent, nWinStyle & WB_3DLOOK )
333 , mnStartWidth(0)
335 sal_Int32 nScaleFactor = GetDPIScaleFactor();
336 SetPointer(Pointer(PointerStyle::HSizeBar));
337 SetSizePixel(Size(7 * nScaleFactor, 0));
340 void ImplTabSizer::dispose()
342 vcl::Window::dispose();
345 void ImplTabSizer::ImplTrack( const Point& rScreenPos )
347 TabBar* pParent = GetParent();
348 long nDiff = rScreenPos.X() - maStartPos.X();
349 pParent->mnSplitSize = mnStartWidth + (pParent->IsMirrored() ? -nDiff : nDiff);
350 if ( pParent->mnSplitSize < TABBAR_MINSIZE )
351 pParent->mnSplitSize = TABBAR_MINSIZE;
352 pParent->Split();
353 pParent->Update();
356 void ImplTabSizer::MouseButtonDown( const MouseEvent& rMEvt )
358 if ( GetParent()->IsInEditMode() )
360 GetParent()->EndEditMode();
361 return;
364 if ( rMEvt.IsLeft() )
366 maStartPos = OutputToScreenPixel( rMEvt.GetPosPixel() );
367 mnStartWidth = GetParent()->GetSizePixel().Width();
368 StartTracking();
372 void ImplTabSizer::Tracking( const TrackingEvent& rTEvt )
374 if ( rTEvt.IsTrackingEnded() )
376 if ( rTEvt.IsTrackingCanceled() )
377 ImplTrack( maStartPos );
378 GetParent()->mnSplitSize = 0;
380 else
381 ImplTrack( OutputToScreenPixel( rTEvt.GetMouseEvent().GetPosPixel() ) );
384 void ImplTabSizer::Paint( vcl::RenderContext& rRenderContext, const Rectangle& )
386 DecorationView aDecoView(&rRenderContext);
387 Rectangle aOutputRect(Point(0, 0), GetOutputSizePixel());
388 aDecoView.DrawHandle(aOutputRect, true);
391 // Is not named Impl. as it may be both instantiated and derived from
392 class TabBarEdit : public Edit
394 private:
395 Idle maLoseFocusIdle;
396 bool mbPostEvt;
398 DECL_LINK( ImplEndEditHdl, void* );
399 DECL_LINK_TYPED( ImplEndTimerHdl, Idle*, void );
401 public:
402 TabBarEdit( TabBar* pParent, WinBits nWinStyle = 0 );
404 TabBar* GetParent() const { return static_cast<TabBar*>(Window::GetParent()); }
406 void SetPostEvent() { mbPostEvt = true; }
407 void ResetPostEvent() { mbPostEvt = false; }
409 virtual bool PreNotify( NotifyEvent& rNEvt ) SAL_OVERRIDE;
410 virtual void LoseFocus() SAL_OVERRIDE;
413 TabBarEdit::TabBarEdit( TabBar* pParent, WinBits nWinStyle ) :
414 Edit( pParent, nWinStyle )
416 mbPostEvt = false;
419 bool TabBarEdit::PreNotify( NotifyEvent& rNEvt )
421 if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
423 const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
424 if ( !pKEvt->GetKeyCode().GetModifier() )
426 if ( pKEvt->GetKeyCode().GetCode() == KEY_RETURN )
428 if ( !mbPostEvt )
430 if ( PostUserEvent( LINK( this, TabBarEdit, ImplEndEditHdl ), reinterpret_cast<void*>(sal_False), true ) )
431 mbPostEvt = true;
433 return true;
435 else if ( pKEvt->GetKeyCode().GetCode() == KEY_ESCAPE )
437 if ( !mbPostEvt )
439 if ( PostUserEvent( LINK( this, TabBarEdit, ImplEndEditHdl ), reinterpret_cast<void*>(sal_True), true ) )
440 mbPostEvt = true;
442 return true;
447 return Edit::PreNotify( rNEvt );
450 void TabBarEdit::LoseFocus()
452 if ( !mbPostEvt )
454 if ( PostUserEvent( LINK( this, TabBarEdit, ImplEndEditHdl ), reinterpret_cast<void*>(sal_False), true ) )
455 mbPostEvt = true;
458 Edit::LoseFocus();
461 IMPL_LINK( TabBarEdit, ImplEndEditHdl, void*, pCancel )
463 ResetPostEvent();
464 maLoseFocusIdle.Stop();
466 // We need this query, because the edit gets a losefocus event,
467 // when it shows the context menu or the insert symbol dialog
468 if ( !HasFocus() && HasChildPathFocus( true ) )
470 maLoseFocusIdle.SetPriority( SchedulerPriority::REPAINT );
471 maLoseFocusIdle.SetIdleHdl( LINK( this, TabBarEdit, ImplEndTimerHdl ) );
472 maLoseFocusIdle.Start();
474 else
475 GetParent()->EndEditMode( pCancel != 0 );
477 return 0;
480 IMPL_LINK_NOARG_TYPED(TabBarEdit, ImplEndTimerHdl, Idle *, void)
482 if ( HasFocus() )
483 return;
485 // We need this query, because the edit gets a losefocus event,
486 // when it shows the context menu or the insert symbol dialog
487 if ( HasChildPathFocus( true ) )
488 maLoseFocusIdle.Start();
489 else
490 GetParent()->EndEditMode( true );
493 struct TabBar_Impl
495 ScopedVclPtr<ImplTabSizer> mpSizer;
496 ScopedVclPtr<ImplTabButton> mpFirstButton;
497 ScopedVclPtr<ImplTabButton> mpPrevButton;
498 ScopedVclPtr<ImplTabButton> mpNextButton;
499 ScopedVclPtr<ImplTabButton> mpLastButton;
500 ScopedVclPtr<ImplTabButton> mpAddButton;
501 ScopedVclPtr<TabBarEdit> mpEdit;
502 ImplTabBarList mpItemList;
504 svt::AccessibleFactoryAccess maAccessibleFactory;
506 TabBar_Impl() {}
508 ~TabBar_Impl()
510 for (size_t i = 0; i < mpItemList.size(); ++i)
512 delete mpItemList[i];
514 mpItemList.clear();
517 sal_uInt16 getItemSize()
519 return static_cast<sal_uInt16>(mpItemList.size());
523 TabBar::TabBar( vcl::Window* pParent, WinBits nWinStyle ) :
524 Window( pParent, (nWinStyle & WB_3DLOOK) | WB_CLIPCHILDREN )
526 ImplInit( nWinStyle );
527 maCurrentItemList = 0;
530 TabBar::~TabBar()
532 disposeOnce();
535 void TabBar::dispose()
537 EndEditMode( true );
538 mpImpl.reset();
539 Window::dispose();
542 const sal_uInt16 TabBar::APPEND = ::std::numeric_limits<sal_uInt16>::max();
543 const sal_uInt16 TabBar::PAGE_NOT_FOUND = ::std::numeric_limits<sal_uInt16>::max();
545 void TabBar::ImplInit( WinBits nWinStyle )
547 mpImpl.reset(new TabBar_Impl);
549 mnMaxPageWidth = 0;
550 mnCurMaxWidth = 0;
551 mnOffX = 0;
552 mnOffY = 0;
553 mnLastOffX = 0;
554 mnSplitSize = 0;
555 mnSwitchTime = 0;
556 mnWinStyle = nWinStyle;
557 mnCurPageId = 0;
558 mnFirstPos = 0;
559 mnDropPos = 0;
560 mnSwitchId = 0;
561 mnEditId = 0;
562 mbFormat = true;
563 mbFirstFormat = true;
564 mbSizeFormat = true;
565 mbAutoMaxWidth = true;
566 mbInSwitching = false;
567 mbAutoEditMode = false;
568 mbEditCanceled = false;
569 mbDropPos = false;
570 mbInSelect = false;
571 mbSelColor = false;
572 mbSelTextColor = false;
573 mbMirrored = false;
574 mbScrollAlwaysEnabled = false;
576 if ( nWinStyle & WB_3DTAB )
577 mnOffY++;
579 ImplInitControls();
581 if (mpImpl->mpFirstButton)
582 mpImpl->mpFirstButton->SetAccessibleName(SVT_RESSTR(STR_TABBAR_PUSHBUTTON_MOVET0HOME));
583 if (mpImpl->mpPrevButton)
584 mpImpl->mpPrevButton->SetAccessibleName(SVT_RESSTR(STR_TABBAR_PUSHBUTTON_MOVELEFT));
585 if (mpImpl->mpNextButton)
586 mpImpl->mpNextButton->SetAccessibleName(SVT_RESSTR(STR_TABBAR_PUSHBUTTON_MOVERIGHT));
587 if (mpImpl->mpLastButton)
588 mpImpl->mpLastButton->SetAccessibleName(SVT_RESSTR(STR_TABBAR_PUSHBUTTON_MOVETOEND));
590 if (mpImpl->mpAddButton)
591 mpImpl->mpAddButton->SetAccessibleName(SVT_RESSTR(STR_TABBAR_PUSHBUTTON_ADDTAB));
593 SetSizePixel( Size( 100, CalcWindowSizePixel().Height() ) );
594 ImplInitSettings( true, true );
597 ImplTabBarItem* TabBar::seek( size_t i )
599 if ( i < mpImpl->mpItemList.size() )
601 maCurrentItemList = i;
602 return mpImpl->mpItemList[maCurrentItemList];
604 return NULL;
607 ImplTabBarItem* TabBar::prev()
609 if ( maCurrentItemList > 0 )
611 return mpImpl->mpItemList[--maCurrentItemList];
613 return NULL;
616 ImplTabBarItem* TabBar::next()
618 if ( maCurrentItemList + 1 < mpImpl->mpItemList.size() )
620 return mpImpl->mpItemList[++maCurrentItemList];
622 return NULL;
625 void TabBar::ImplInitSettings( bool bFont, bool bBackground )
627 // FIXME RenderContext
629 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
631 if (bFont)
633 vcl::Font aToolFont;
634 aToolFont = rStyleSettings.GetToolFont();
635 aToolFont.SetWeight( WEIGHT_BOLD );
636 ApplyControlFont(*this, aToolFont);
638 // Adapt font size if window too small?
639 while (GetTextHeight() > (GetOutputSizePixel().Height() - 1))
641 vcl::Font aFont = GetFont();
642 if (aFont.GetHeight() <= 6)
643 break;
644 aFont.SetHeight(aFont.GetHeight() - 1);
645 SetFont(aFont);
649 if (bBackground)
651 ApplyControlBackground(*this, rStyleSettings.GetFaceColor());
655 void TabBar::ImplGetColors(const StyleSettings& rStyleSettings,
656 Color& rFaceColor, Color& rFaceTextColor,
657 Color& rSelectColor, Color& rSelectTextColor)
659 if (IsControlBackground())
660 rFaceColor = GetControlBackground();
661 else
662 rFaceColor = rStyleSettings.GetInactiveTabColor();
663 if (IsControlForeground())
664 rFaceTextColor = GetControlForeground();
665 else
666 rFaceTextColor = rStyleSettings.GetButtonTextColor();
667 if (mbSelColor)
668 rSelectColor = maSelColor;
669 else
670 rSelectColor = rStyleSettings.GetActiveTabColor();
671 if (mbSelTextColor)
672 rSelectTextColor = maSelTextColor;
673 else
674 rSelectTextColor = rStyleSettings.GetWindowTextColor();
676 // For 3D-tabs the selection- and face-colours are swapped,
677 // as the selected tabs should appear in 3D
678 if (mnWinStyle & WB_3DTAB)
680 using std::swap;
681 swap(rFaceColor, rSelectColor);
682 swap(rFaceTextColor, rSelectTextColor);
686 bool TabBar::ImplCalcWidth()
688 // Sizes should only be retrieved if the text or the font was changed
689 if (!mbSizeFormat)
690 return false;
692 // retrieve width of tabs with bold font
693 vcl::Font aFont = GetFont();
694 if (aFont.GetWeight() != WEIGHT_BOLD)
696 aFont.SetWeight(WEIGHT_BOLD);
697 SetFont(aFont);
700 if (mnMaxPageWidth)
701 mnCurMaxWidth = mnMaxPageWidth;
702 else if (mbAutoMaxWidth)
704 mnCurMaxWidth = mnLastOffX - mnOffX;
705 if (mnCurMaxWidth < 1)
706 mnCurMaxWidth = 1;
708 else
709 mnCurMaxWidth = 0;
711 bool bChanged = false;
712 for (size_t i = 0; i < mpImpl->mpItemList.size(); ++i)
714 ImplTabBarItem* pItem = mpImpl->mpItemList[i];
715 long nNewWidth = GetTextWidth(pItem->maText);
716 if (mnCurMaxWidth && (nNewWidth > mnCurMaxWidth))
718 pItem->mbShort = true;
719 nNewWidth = mnCurMaxWidth;
721 else
723 pItem->mbShort = false;
726 // Padding is dependent on font height - bigger font = bigger padding
727 long nFontWidth = aFont.GetHeight();
728 nNewWidth += nFontWidth * 2;
730 if (pItem->mnWidth != nNewWidth)
732 pItem->mnWidth = nNewWidth;
733 if (!pItem->maRect.IsEmpty())
734 bChanged = true;
737 mbSizeFormat = false;
738 mbFormat = true;
739 return bChanged;
742 void TabBar::ImplFormat()
744 ImplCalcWidth();
746 if (!mbFormat)
747 return;
749 sal_uInt16 n = 0;
750 long x = mnOffX;
751 for (size_t i = 0; i < mpImpl->mpItemList.size(); ++i)
753 ImplTabBarItem* pItem = mpImpl->mpItemList[i];
754 // At all non-visible tabs an empty rectangle is set
755 if ((n + 1 < mnFirstPos) || (x > mnLastOffX))
756 pItem->maRect.SetEmpty();
757 else
759 // Slightly before the tab before the first visible page
760 // should also be visible
761 if (n + 1 == mnFirstPos)
762 pItem->maRect.Left() = x-pItem->mnWidth;
763 else
765 pItem->maRect.Left() = x;
766 x += pItem->mnWidth;
768 pItem->maRect.Right() = x;
769 pItem->maRect.Bottom() = maWinSize.Height() - 1;
771 if (mbMirrored)
773 long nTmp = mnOffX + mnLastOffX - pItem->maRect.Right();
774 pItem->maRect.Right() = mnOffX + mnLastOffX - pItem->maRect.Left();
775 pItem->maRect.Left() = nTmp;
779 n++;
782 mbFormat = false;
784 // enable/disable button
785 ImplEnableControls();
788 sal_uInt16 TabBar::ImplGetLastFirstPos()
790 sal_uInt16 nCount = mpImpl->getItemSize();
791 if (!nCount || mbSizeFormat || mbFormat)
792 return 0;
794 sal_uInt16 nLastFirstPos = nCount - 1;
795 long nWinWidth = mnLastOffX - mnOffX - ADDNEWPAGE_AREAWIDTH;
796 long nWidth = mpImpl->mpItemList[nLastFirstPos]->mnWidth;
798 while (nLastFirstPos && (nWidth < nWinWidth))
800 nLastFirstPos--;
801 nWidth += mpImpl->mpItemList[nLastFirstPos]->mnWidth;
803 if ((nLastFirstPos != static_cast<sal_uInt16>(mpImpl->mpItemList.size() - 1)) && (nWidth > nWinWidth))
804 nLastFirstPos++;
805 return nLastFirstPos;
808 void TabBar::ImplInitControls()
810 if (mnWinStyle & WB_SIZEABLE)
812 if (!mpImpl->mpSizer)
814 mpImpl->mpSizer.reset(VclPtr<ImplTabSizer>::Create( this, mnWinStyle & (WB_DRAG | WB_3DLOOK)));
816 mpImpl->mpSizer->Show();
818 else
820 mpImpl->mpSizer.disposeAndClear();
823 if ((mnWinStyle & WB_INSERTTAB) && !mpImpl->mpAddButton)
825 Link<> aLink = LINK(this, TabBar, ImplAddClickHandler);
826 mpImpl->mpAddButton.reset(VclPtr<ImplTabButton>::Create(this, WB_REPEAT));
827 mpImpl->mpAddButton->SetClickHdl(aLink);
828 mpImpl->mpAddButton->SetSymbol(SymbolType::PLUS);
829 mpImpl->mpAddButton->Show();
832 Link<> aLink = LINK( this, TabBar, ImplClickHdl );
834 if (mnWinStyle & (WB_MINSCROLL | WB_SCROLL))
836 if (!mpImpl->mpPrevButton)
838 mpImpl->mpPrevButton.reset(VclPtr<ImplTabButton>::Create(this, WB_REPEAT));
839 mpImpl->mpPrevButton->SetClickHdl(aLink);
841 mpImpl->mpPrevButton->SetSymbol(mbMirrored ? SymbolType::NEXT : SymbolType::PREV);
842 mpImpl->mpPrevButton->Show();
844 if (!mpImpl->mpNextButton)
846 mpImpl->mpNextButton.reset(VclPtr<ImplTabButton>::Create(this, WB_REPEAT));
847 mpImpl->mpNextButton->SetClickHdl(aLink);
849 mpImpl->mpNextButton->SetSymbol(mbMirrored ? SymbolType::PREV : SymbolType::NEXT);
850 mpImpl->mpNextButton->Show();
852 else
854 mpImpl->mpPrevButton.disposeAndClear();
855 mpImpl->mpNextButton.disposeAndClear();
858 if (mnWinStyle & WB_SCROLL)
860 if (!mpImpl->mpFirstButton)
862 mpImpl->mpFirstButton.reset(VclPtr<ImplTabButton>::Create(this));
863 mpImpl->mpFirstButton->SetClickHdl(aLink);
865 mpImpl->mpFirstButton->SetSymbol(mbMirrored ? SymbolType::LAST : SymbolType::FIRST);
866 mpImpl->mpFirstButton->Show();
868 if (!mpImpl->mpLastButton)
870 mpImpl->mpLastButton.reset(VclPtr<ImplTabButton>::Create(this));
871 mpImpl->mpLastButton->SetClickHdl(aLink);
873 mpImpl->mpLastButton->SetSymbol(mbMirrored ? SymbolType::FIRST : SymbolType::LAST);
874 mpImpl->mpLastButton->Show();
876 else
878 mpImpl->mpFirstButton.disposeAndClear();
879 mpImpl->mpLastButton.disposeAndClear();
883 void TabBar::ImplEnableControls()
885 if (mbSizeFormat || mbFormat)
886 return;
888 // enable/disable buttons
889 bool bEnableBtn = mbScrollAlwaysEnabled || mnFirstPos > 0;
890 if (mpImpl->mpFirstButton)
891 mpImpl->mpFirstButton->Enable(bEnableBtn);
892 if (mpImpl->mpPrevButton)
893 mpImpl->mpPrevButton->Enable(bEnableBtn);
895 bEnableBtn = mbScrollAlwaysEnabled || mnFirstPos < ImplGetLastFirstPos();
896 if (mpImpl->mpNextButton)
897 mpImpl->mpNextButton->Enable(bEnableBtn);
898 if (mpImpl->mpLastButton)
899 mpImpl->mpLastButton->Enable(bEnableBtn);
902 void TabBar::SetScrollAlwaysEnabled(bool bScrollAlwaysEnabled)
904 mbScrollAlwaysEnabled = bScrollAlwaysEnabled;
905 ImplEnableControls();
908 void TabBar::ImplShowPage( sal_uInt16 nPos )
910 if (nPos >= mpImpl->getItemSize())
911 return;
913 // calculate width
914 long nWidth = GetOutputSizePixel().Width();
916 ImplTabBarItem* pItem = mpImpl->mpItemList[nPos];
917 if (nPos < mnFirstPos)
918 SetFirstPageId( pItem->mnId );
919 else if (pItem->maRect.Right() > nWidth)
921 while (pItem->maRect.Right() > nWidth)
923 sal_uInt16 nNewPos = mnFirstPos + 1;
924 SetFirstPageId(GetPageId(nNewPos));
925 ImplFormat();
926 if (nNewPos != mnFirstPos)
927 break;
932 IMPL_LINK( TabBar, ImplClickHdl, ImplTabButton*, pBtn )
934 EndEditMode();
936 sal_uInt16 nNewPos = mnFirstPos;
938 if (pBtn == mpImpl->mpFirstButton.get() || (pBtn == mpImpl->mpPrevButton.get() && pBtn->isModKeyPressed()))
940 nNewPos = 0;
942 else if (pBtn == mpImpl->mpLastButton.get() || (pBtn == mpImpl->mpNextButton.get() && pBtn->isModKeyPressed()))
944 sal_uInt16 nCount = GetPageCount();
945 if (nCount)
946 nNewPos = nCount - 1;
948 else if (pBtn == mpImpl->mpPrevButton.get())
950 if (mnFirstPos)
951 nNewPos = mnFirstPos - 1;
953 else if (pBtn == mpImpl->mpNextButton.get())
955 sal_uInt16 nCount = GetPageCount();
956 if (mnFirstPos < nCount)
957 nNewPos = mnFirstPos+1;
959 else
961 return 0;
964 if (nNewPos != mnFirstPos)
965 SetFirstPageId(GetPageId(nNewPos));
967 return 0;
970 IMPL_LINK_NOARG(TabBar, ImplAddClickHandler)
972 AddTabClick();
973 return 0;
976 void TabBar::MouseMove(const MouseEvent& rMEvt)
978 if (rMEvt.IsLeaveWindow())
979 mbInSelect = false;
981 Window::MouseMove(rMEvt);
984 void TabBar::MouseButtonDown(const MouseEvent& rMEvt)
986 // Only terminate EditModus and do not execute click
987 // if clicked inside our window,
988 if (IsInEditMode())
990 EndEditMode();
991 return;
994 ImplTabBarItem* pItem;
995 sal_uInt16 nSelId = GetPageId(rMEvt.GetPosPixel());
997 if (!rMEvt.IsLeft())
999 Window::MouseButtonDown(rMEvt);
1000 if (nSelId > 0 && nSelId != mnCurPageId)
1002 sal_uInt16 nPos = GetPagePos( nSelId );
1003 pItem = mpImpl->mpItemList[nPos];
1005 if (pItem->mbEnable)
1007 if (ImplDeactivatePage())
1009 SetCurPageId(nSelId);
1010 Update();
1011 ImplActivatePage();
1012 ImplSelect();
1014 mbInSelect = true;
1017 return;
1020 if (rMEvt.IsMod2() && mbAutoEditMode && nSelId)
1022 if (StartEditMode(nSelId))
1023 return;
1026 if ((rMEvt.GetMode() & (MouseEventModifiers::MULTISELECT | MouseEventModifiers::RANGESELECT)) && (rMEvt.GetClicks() == 1))
1028 if (nSelId)
1030 sal_uInt16 nPos = GetPagePos(nSelId);
1031 pItem = mpImpl->mpItemList[nPos];
1033 if (pItem->mbEnable)
1035 bool bSelectTab = false;
1037 if ((rMEvt.GetMode() & MouseEventModifiers::MULTISELECT) && (mnWinStyle & WB_MULTISELECT))
1039 if (nSelId != mnCurPageId)
1041 SelectPage(nSelId, !IsPageSelected(nSelId));
1042 bSelectTab = true;
1045 else if (mnWinStyle & (WB_MULTISELECT | WB_RANGESELECT))
1047 bSelectTab = true;
1048 sal_uInt16 n;
1049 bool bSelect;
1050 sal_uInt16 nCurPos = GetPagePos(mnCurPageId);
1051 if (nPos <= nCurPos)
1053 // Deselect all tabs till the clicked tab
1054 // and select all tabs from the clicked tab
1055 // 'till the actual position
1056 n = 0;
1057 while (n < nCurPos)
1059 pItem = mpImpl->mpItemList[n];
1060 if (n < nPos)
1061 bSelect = false;
1062 else
1063 bSelect = true;
1065 if (pItem->mbSelect != bSelect)
1067 pItem->mbSelect = bSelect;
1068 if (!pItem->maRect.IsEmpty())
1069 Invalidate(pItem->maRect);
1072 n++;
1076 if (nPos >= nCurPos)
1078 // Select all tabs from the actual position till the clicked tab
1079 // and deselect all tabs from the actual position
1080 // till the last tab
1081 sal_uInt16 nCount = mpImpl->getItemSize();
1082 n = nCurPos;
1083 while (n < nCount)
1085 pItem = mpImpl->mpItemList[n];
1087 if (n <= nPos)
1088 bSelect = true;
1089 else
1090 bSelect = false;
1092 if (pItem->mbSelect != bSelect)
1094 pItem->mbSelect = bSelect;
1095 if (!pItem->maRect.IsEmpty())
1096 Invalidate(pItem->maRect);
1099 n++;
1104 // scroll the selected tab if required
1105 if (bSelectTab)
1107 ImplShowPage(nPos);
1108 Update();
1109 ImplSelect();
1112 else
1113 ImplShowPage(nPos);
1114 mbInSelect = true;
1116 return;
1119 else if (rMEvt.GetClicks() == 2)
1121 // call double-click-handler if required
1122 if (!rMEvt.GetModifier() && (!nSelId || (nSelId == mnCurPageId)))
1124 sal_uInt16 nOldCurId = mnCurPageId;
1125 mnCurPageId = nSelId;
1126 DoubleClick();
1127 // check, as actual page could be switched inside
1128 // the doubleclick-handler
1129 if (mnCurPageId == nSelId)
1130 mnCurPageId = nOldCurId;
1133 return;
1135 else
1137 if (nSelId)
1139 // execute Select if not actual page
1140 if (nSelId != mnCurPageId)
1142 sal_uInt16 nPos = GetPagePos(nSelId);
1143 pItem = mpImpl->mpItemList[nPos];
1145 if (pItem->mbEnable)
1147 if (!pItem->mbSelect)
1149 // make not valid
1150 bool bUpdate = false;
1151 if (IsReallyVisible() && IsUpdateMode())
1152 bUpdate = true;
1154 // deselect all selected items
1155 for (size_t i = 0; i < mpImpl->mpItemList.size(); ++i)
1157 pItem = mpImpl->mpItemList[i];
1158 if (pItem->mbSelect || (pItem->mnId == mnCurPageId))
1160 pItem->mbSelect = false;
1161 if (bUpdate)
1162 Invalidate(pItem->maRect);
1167 if (ImplDeactivatePage())
1169 SetCurPageId(nSelId);
1170 Update();
1171 ImplActivatePage();
1172 ImplSelect();
1175 else
1176 ImplShowPage(nPos);
1177 mbInSelect = true;
1180 return;
1184 Window::MouseButtonDown(rMEvt);
1187 void TabBar::MouseButtonUp(const MouseEvent& rMEvt)
1189 mbInSelect = false;
1190 Window::MouseButtonUp(rMEvt);
1193 void TabBar::Paint(vcl::RenderContext& rRenderContext, const Rectangle& rect)
1195 if (rRenderContext.IsNativeControlSupported(CTRL_WINDOW_BACKGROUND,PART_ENTIRE_CONTROL))
1197 rRenderContext.DrawNativeControl(CTRL_WINDOW_BACKGROUND,PART_ENTIRE_CONTROL,rect,
1198 ControlState::ENABLED,ImplControlValue(0),OUString());
1200 // calculate items and emit
1201 sal_uInt16 nItemCount = mpImpl->getItemSize();
1202 if (!nItemCount)
1203 return;
1205 ImplPrePaint(rRenderContext);
1207 Color aFaceColor, aSelectColor, aFaceTextColor, aSelectTextColor;
1208 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
1209 ImplGetColors(rStyleSettings, aFaceColor, aFaceTextColor, aSelectColor, aSelectTextColor);
1211 rRenderContext.Push(PushFlags::FONT | PushFlags::CLIPREGION);
1212 rRenderContext.SetClipRegion(vcl::Region(GetPageArea()));
1214 // select font
1215 vcl::Font aFont = rRenderContext.GetFont();
1216 vcl::Font aLightFont = aFont;
1217 aLightFont.SetWeight(WEIGHT_NORMAL);
1219 TabDrawer aDrawer(*this, rRenderContext);
1221 aDrawer.setSelectedFillColor(aSelectColor);
1222 aDrawer.setUnselectedFillColor(aFaceColor);
1224 aDrawer.drawOutputAreaBorder();
1226 // Now, start drawing the tabs.
1228 ImplTabBarItem* pItem = ImplGetLastTabBarItem(nItemCount);
1229 ImplTabBarItem* pCurItem = NULL;
1230 while (pItem)
1232 // emit CurrentItem last, as it covers all others
1233 if (!pCurItem && (pItem->mnId == mnCurPageId))
1235 pCurItem = pItem;
1236 pItem = prev();
1237 if (!pItem)
1238 pItem = pCurItem;
1239 continue;
1242 bool bCurrent = pItem == pCurItem;
1244 if (!pItem->maRect.IsEmpty())
1246 Rectangle aRect = pItem->maRect;
1247 bool bSelected = pItem->IsSelected(pCurItem);
1248 // We disable custom background color in high contrast mode.
1249 bool bCustomBgColor = !pItem->IsDefaultTabBgColor() && !rStyleSettings.GetHighContrastMode();
1250 bool bSpecialTab = (pItem->mnBits & TPB_SPECIAL);
1251 bool bEnabled = pItem->mbEnable;
1252 OUString aText = pItem->mbShort ? rRenderContext.GetEllipsisString(pItem->maText, mnCurMaxWidth, DrawTextFlags::EndEllipsis) : pItem->maText;
1254 aDrawer.setRect(aRect);
1255 aDrawer.setSelected(bSelected);
1256 aDrawer.setCustomColored(bCustomBgColor);
1257 aDrawer.setSpecialTab(bSpecialTab);
1258 aDrawer.setEnabled(bEnabled);
1259 aDrawer.setCustomColor(pItem->maTabBgColor);
1260 aDrawer.drawTab();
1262 // actual page is drawn using a bold font
1263 if (bCurrent)
1264 rRenderContext.SetFont(aFont);
1265 else
1266 rRenderContext.SetFont(aLightFont);
1268 // Set the correct FillInBrush depending on status
1270 if (bSelected)
1271 rRenderContext.SetTextColor(aSelectTextColor);
1272 else if (bCustomBgColor)
1273 rRenderContext.SetTextColor(pItem->maTabTextColor);
1274 else
1275 rRenderContext.SetTextColor(aFaceTextColor);
1277 // This tab is "special", and a special tab needs a blue text.
1278 if (bSpecialTab)
1279 rRenderContext.SetTextColor(Color(COL_LIGHTBLUE));
1281 aDrawer.drawText(aText);
1283 if (bCurrent)
1285 rRenderContext.SetLineColor();
1286 rRenderContext.SetFillColor(aSelectColor);
1287 aDrawer.drawOverTopBorder();
1288 break;
1291 pItem = prev();
1293 else
1295 if (bCurrent)
1296 break;
1298 pItem = NULL;
1301 if (!pItem)
1302 pItem = pCurItem;
1304 rRenderContext.Pop();
1307 void TabBar::Resize()
1309 Size aNewSize = GetOutputSizePixel();
1311 long nSizerWidth = 0;
1312 long nButtonWidth = 0;
1314 // Sizer anordnen
1315 if ( mpImpl->mpSizer )
1317 Size aSizerSize = mpImpl->mpSizer->GetSizePixel();
1318 Point aNewSizerPos( mbMirrored ? 0 : (aNewSize.Width()-aSizerSize.Width()), 0 );
1319 Size aNewSizerSize( aSizerSize.Width(), aNewSize.Height() );
1320 mpImpl->mpSizer->SetPosSizePixel( aNewSizerPos, aNewSizerSize );
1321 nSizerWidth = aSizerSize.Width();
1324 // order the scroll buttons
1325 long nHeight = aNewSize.Height();
1326 // adapt font height?
1327 ImplInitSettings( true, false );
1329 long nButtonMargin = BUTTON_MARGIN * GetDPIScaleFactor();
1331 long nX = mbMirrored ? (aNewSize.Width() - nHeight - nButtonMargin) : nButtonMargin;
1332 long nXDiff = mbMirrored ? -nHeight : nHeight;
1334 nButtonWidth += nButtonMargin;
1336 Size aBtnSize( nHeight, nHeight );
1337 if (mpImpl->mpFirstButton)
1339 mpImpl->mpFirstButton->SetPosSizePixel( Point( nX, 0 ), aBtnSize );
1340 nX += nXDiff;
1341 nButtonWidth += nHeight;
1343 if (mpImpl->mpPrevButton)
1345 mpImpl->mpPrevButton->SetPosSizePixel( Point( nX, 0 ), aBtnSize );
1346 nX += nXDiff;
1347 nButtonWidth += nHeight;
1349 if (mpImpl->mpNextButton)
1351 mpImpl->mpNextButton->SetPosSizePixel( Point( nX, 0 ), aBtnSize );
1352 nX += nXDiff;
1353 nButtonWidth += nHeight;
1355 if (mpImpl->mpLastButton)
1357 mpImpl->mpLastButton->SetPosSizePixel( Point( nX, 0 ), aBtnSize );
1358 nX += nXDiff;
1359 nButtonWidth += nHeight;
1362 nButtonWidth += nButtonMargin;
1363 nX += mbMirrored ? -nButtonMargin : nButtonMargin;
1365 if (mpImpl->mpAddButton)
1367 mpImpl->mpAddButton->SetPosSizePixel( Point( nX, 0 ), aBtnSize );
1368 nX += nXDiff;
1369 nButtonWidth += nHeight;
1372 nButtonWidth += nButtonMargin;
1374 // store size
1375 maWinSize = aNewSize;
1377 if( mbMirrored )
1379 mnOffX = nSizerWidth;
1380 mnLastOffX = maWinSize.Width() - nButtonWidth - 1;
1382 else
1384 mnOffX = nButtonWidth;
1385 mnLastOffX = maWinSize.Width() - nSizerWidth - 1;
1388 // reformat
1389 mbSizeFormat = true;
1390 if ( IsReallyVisible() )
1392 if ( ImplCalcWidth() )
1393 Invalidate();
1395 ImplFormat();
1397 // Ensure as many tabs as possible are visible:
1398 sal_uInt16 nLastFirstPos = ImplGetLastFirstPos();
1399 if ( mnFirstPos > nLastFirstPos )
1401 mnFirstPos = nLastFirstPos;
1402 mbFormat = true;
1403 Invalidate();
1405 // Ensure the currently selected page is visible
1406 ImplShowPage(GetPagePos(mnCurPageId));
1408 ImplFormat();
1411 // enable/disable button
1412 ImplEnableControls();
1415 bool TabBar::PreNotify(NotifyEvent& rNEvt)
1417 if (rNEvt.GetType() == MouseNotifyEvent::COMMAND)
1419 if (rNEvt.GetCommandEvent()->GetCommand() == CommandEventId::Wheel)
1421 const CommandWheelData* pData = rNEvt.GetCommandEvent()->GetWheelData();
1422 sal_uInt16 nNewPos = mnFirstPos;
1423 if (pData->GetNotchDelta() > 0)
1425 if (mnFirstPos)
1426 nNewPos = mnFirstPos - 1;
1428 else if (pData->GetNotchDelta() < 0)
1430 sal_uInt16 nCount = GetPageCount();
1431 if (mnFirstPos < nCount)
1432 nNewPos = mnFirstPos + 1;
1434 if (nNewPos != mnFirstPos)
1435 SetFirstPageId(GetPageId(nNewPos));
1438 return Window::PreNotify(rNEvt);
1441 void TabBar::RequestHelp(const HelpEvent& rHEvt)
1443 sal_uInt16 nItemId = GetPageId(ScreenToOutputPixel(rHEvt.GetMousePosPixel()));
1444 if (nItemId)
1446 if (rHEvt.GetMode() & HelpEventMode::BALLOON)
1448 OUString aStr = GetHelpText(nItemId);
1449 if (!aStr.isEmpty())
1451 Rectangle aItemRect = GetPageRect(nItemId);
1452 Point aPt = OutputToScreenPixel(aItemRect.TopLeft());
1453 aItemRect.Left() = aPt.X();
1454 aItemRect.Top() = aPt.Y();
1455 aPt = OutputToScreenPixel(aItemRect.BottomRight());
1456 aItemRect.Right() = aPt.X();
1457 aItemRect.Bottom() = aPt.Y();
1458 Help::ShowBalloon(this, aItemRect.Center(), aItemRect, aStr);
1459 return;
1462 else if (rHEvt.GetMode() & HelpEventMode::EXTENDED)
1464 OUString aHelpId(OStringToOUString(GetHelpId(nItemId), RTL_TEXTENCODING_UTF8));
1465 if ( !aHelpId.isEmpty() )
1467 // trigger Help if available
1468 Help* pHelp = Application::GetHelp();
1469 if (pHelp)
1470 pHelp->Start(aHelpId, this);
1471 return;
1475 // show text for quick- or balloon-help
1476 // if this is isolated or not fully visible
1477 if (rHEvt.GetMode() & (HelpEventMode::QUICK | HelpEventMode::BALLOON))
1479 sal_uInt16 nPos = GetPagePos(nItemId);
1480 ImplTabBarItem* pItem = mpImpl->mpItemList[nPos];
1481 if (pItem->mbShort || (pItem->maRect.Right() - 5 > mnLastOffX))
1483 Rectangle aItemRect = GetPageRect(nItemId);
1484 Point aPt = OutputToScreenPixel(aItemRect.TopLeft());
1485 aItemRect.Left() = aPt.X();
1486 aItemRect.Top() = aPt.Y();
1487 aPt = OutputToScreenPixel(aItemRect.BottomRight());
1488 aItemRect.Right() = aPt.X();
1489 aItemRect.Bottom() = aPt.Y();
1490 OUString aStr = mpImpl->mpItemList[nPos]->maText;
1491 if (!aStr.isEmpty())
1493 if (rHEvt.GetMode() & HelpEventMode::BALLOON)
1494 Help::ShowBalloon(this, aItemRect.Center(), aItemRect, aStr);
1495 else
1496 Help::ShowQuickHelp(this, aItemRect, aStr);
1497 return;
1503 Window::RequestHelp(rHEvt);
1506 void TabBar::StateChanged(StateChangedType nType)
1508 Window::StateChanged(nType);
1510 if (nType == StateChangedType::InitShow)
1512 if ( (mbSizeFormat || mbFormat) && !mpImpl->mpItemList.empty() )
1513 ImplFormat();
1515 else if (nType == StateChangedType::Zoom ||
1516 nType == StateChangedType::ControlFont)
1518 ImplInitSettings(true, false);
1519 Invalidate();
1521 else if (nType == StateChangedType::ControlForeground)
1522 Invalidate();
1523 else if (nType == StateChangedType::ControlBackground)
1525 ImplInitSettings(false, true);
1526 Invalidate();
1528 else if (nType == StateChangedType::Mirroring)
1530 // reacts on calls of EnableRTL, have to mirror all child controls
1531 if (mpImpl->mpFirstButton)
1532 mpImpl->mpFirstButton->EnableRTL(IsRTLEnabled());
1533 if (mpImpl->mpPrevButton)
1534 mpImpl->mpPrevButton->EnableRTL(IsRTLEnabled());
1535 if (mpImpl->mpNextButton)
1536 mpImpl->mpNextButton->EnableRTL(IsRTLEnabled());
1537 if (mpImpl->mpLastButton)
1538 mpImpl->mpLastButton->EnableRTL(IsRTLEnabled());
1539 if (mpImpl->mpSizer)
1540 mpImpl->mpSizer->EnableRTL(IsRTLEnabled());
1541 if (mpImpl->mpAddButton)
1542 mpImpl->mpAddButton->EnableRTL(IsRTLEnabled());
1543 if (mpImpl->mpEdit)
1544 mpImpl->mpEdit->EnableRTL(IsRTLEnabled());
1548 void TabBar::DataChanged(const DataChangedEvent& rDCEvt)
1550 Window::DataChanged(rDCEvt);
1552 if (rDCEvt.GetType() == DataChangedEventType::FONTS
1553 || rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION
1554 || (rDCEvt.GetType() == DataChangedEventType::SETTINGS
1555 && rDCEvt.GetFlags() & AllSettingsFlags::STYLE))
1557 ImplInitSettings(true, true);
1558 Invalidate();
1562 void TabBar::ImplSelect()
1564 Select();
1565 CallEventListeners(VCLEVENT_TABBAR_PAGESELECTED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(mnCurPageId)));
1568 void TabBar::Select()
1570 maSelectHdl.Call(this);
1573 void TabBar::DoubleClick()
1577 void TabBar::Split()
1579 maSplitHdl.Call(this);
1582 void TabBar::ImplActivatePage()
1584 ActivatePage();
1586 CallEventListeners(VCLEVENT_TABBAR_PAGEACTIVATED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(mnCurPageId)));
1589 void TabBar::ActivatePage()
1592 bool TabBar::ImplDeactivatePage()
1594 bool nRet = DeactivatePage();
1596 CallEventListeners(VCLEVENT_TABBAR_PAGEDEACTIVATED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(mnCurPageId)));
1598 return nRet;
1601 void TabBar::ImplPrePaint(vcl::RenderContext& /*rRenderContext*/)
1603 sal_uInt16 nItemCount = mpImpl->getItemSize();
1604 if (!nItemCount)
1605 return;
1607 // tabbar should be formatted
1608 ImplFormat();
1610 // assure the actual tabpage becomes visible at first format
1611 if (mbFirstFormat)
1613 mbFirstFormat = false;
1615 if (mnCurPageId && (mnFirstPos == 0) && !mbDropPos)
1617 ImplTabBarItem* pItem = mpImpl->mpItemList[GetPagePos(mnCurPageId)];
1618 if (pItem->maRect.IsEmpty())
1620 // set mbDropPos (or misuse) to prevent Invalidate()
1621 mbDropPos = true;
1622 SetFirstPageId(mnCurPageId);
1623 mbDropPos = false;
1624 if (mnFirstPos != 0)
1625 ImplFormat();
1631 ImplTabBarItem* TabBar::ImplGetLastTabBarItem( sal_uInt16 nItemCount )
1633 // find last visible entry
1634 sal_uInt16 n = mnFirstPos + 1;
1635 if (n >= nItemCount)
1636 n = nItemCount-1;
1637 ImplTabBarItem* pItem = seek(n);
1638 while (pItem)
1640 if (!pItem->maRect.IsEmpty())
1642 n++;
1643 pItem = next();
1645 else
1646 break;
1649 // draw all tabs (from back to front and actual last)
1650 if (pItem)
1651 n--;
1652 else if (n >= nItemCount)
1653 n = nItemCount-1;
1654 pItem = seek(n);
1655 return pItem;
1658 bool TabBar::DeactivatePage()
1660 return true;
1663 bool TabBar::StartRenaming()
1665 return true;
1668 TabBarAllowRenamingReturnCode TabBar::AllowRenaming()
1670 return TABBAR_RENAMING_YES;
1673 void TabBar::EndRenaming()
1677 void TabBar::Mirror()
1682 void TabBar::AddTabClick()
1687 void TabBar::InsertPage(sal_uInt16 nPageId, const OUString& rText,
1688 TabBarPageBits nBits, sal_uInt16 nPos)
1690 DBG_ASSERT( nPageId, "TabBar::InsertPage(): PageId == 0" );
1691 DBG_ASSERT( GetPagePos( nPageId ) == PAGE_NOT_FOUND,
1692 "TabBar::InsertPage(): PageId already exists" );
1693 DBG_ASSERT( nBits <= TPB_SPECIAL, "TabBar::InsertPage(): nBits is wrong" );
1695 // create PageItem and insert in the item list
1696 ImplTabBarItem* pItem = new ImplTabBarItem( nPageId, rText, nBits );
1697 if (nPos < mpImpl->mpItemList.size())
1699 ImplTabBarList::iterator it = mpImpl->mpItemList.begin();
1700 std::advance(it, nPos);
1701 mpImpl->mpItemList.insert(it, pItem);
1703 else
1705 mpImpl->mpItemList.push_back(pItem);
1707 mbSizeFormat = true;
1709 // set CurPageId if required
1710 if (!mnCurPageId)
1711 mnCurPageId = nPageId;
1713 // redraw bar
1714 if (IsReallyVisible() && IsUpdateMode())
1715 Invalidate();
1717 CallEventListeners(VCLEVENT_TABBAR_PAGEINSERTED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(nPageId)));
1720 Color TabBar::GetTabBgColor(sal_uInt16 nPageId) const
1722 sal_uInt16 nPos = GetPagePos(nPageId);
1724 if (nPos != PAGE_NOT_FOUND)
1725 return mpImpl->mpItemList[nPos]->maTabBgColor;
1726 else
1727 return Color(COL_AUTO);
1730 void TabBar::SetTabBgColor(sal_uInt16 nPageId, const Color& aTabBgColor)
1732 sal_uInt16 nPos = GetPagePos(nPageId);
1733 if (nPos != PAGE_NOT_FOUND)
1735 ImplTabBarItem* pItem = mpImpl->mpItemList[nPos];
1736 if (aTabBgColor != Color(COL_AUTO))
1738 pItem->maTabBgColor = aTabBgColor;
1739 if (aTabBgColor.GetLuminance() <= 128) //Do not use aTabBgColor.IsDark(), because that threshold is way too low...
1740 pItem->maTabTextColor = Color(COL_WHITE);
1741 else
1742 pItem->maTabTextColor = Color(COL_BLACK);
1744 else
1746 pItem->maTabBgColor = Color(COL_AUTO);
1747 pItem->maTabTextColor = Color(COL_AUTO);
1752 void TabBar::RemovePage(sal_uInt16 nPageId)
1754 sal_uInt16 nPos = GetPagePos(nPageId);
1756 // does item exist
1757 if (nPos != PAGE_NOT_FOUND)
1759 if (mnCurPageId == nPageId)
1760 mnCurPageId = 0;
1762 // check if first visibale page should be moved
1763 if (mnFirstPos > nPos)
1764 mnFirstPos--;
1766 // delete item data
1767 ImplTabBarList::iterator it = mpImpl->mpItemList.begin();
1768 std::advance(it, nPos);
1769 delete *it;
1770 mpImpl->mpItemList.erase(it);
1772 // redraw bar
1773 if (IsReallyVisible() && IsUpdateMode())
1774 Invalidate();
1776 CallEventListeners(VCLEVENT_TABBAR_PAGEREMOVED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(nPageId)));
1780 void TabBar::MovePage(sal_uInt16 nPageId, sal_uInt16 nNewPos)
1782 sal_uInt16 nPos = GetPagePos(nPageId);
1783 Pair aPair(nPos, nNewPos);
1785 if (nPos < nNewPos)
1786 nNewPos--;
1788 if (nPos == nNewPos)
1789 return;
1791 // does item exit
1792 if (nPos != PAGE_NOT_FOUND)
1794 // move tabbar item in the list
1795 ImplTabBarList::iterator it = mpImpl->mpItemList.begin();
1796 std::advance(it, nPos);
1797 ImplTabBarItem* pItem = *it;
1798 mpImpl->mpItemList.erase(it);
1799 if (nNewPos < mpImpl->mpItemList.size())
1801 it = mpImpl->mpItemList.begin();
1802 std::advance(it, nNewPos);
1803 mpImpl->mpItemList.insert(it, pItem);
1805 else
1807 mpImpl->mpItemList.push_back(pItem);
1810 // redraw bar
1811 if (IsReallyVisible() && IsUpdateMode())
1812 Invalidate();
1814 CallEventListeners( VCLEVENT_TABBAR_PAGEMOVED, (void*) &aPair );
1818 void TabBar::Clear()
1820 // delete all items
1821 for (size_t i = 0; i < mpImpl->mpItemList.size(); ++i)
1823 delete mpImpl->mpItemList[i];
1825 mpImpl->mpItemList.clear();
1827 // remove items from the list
1828 mbSizeFormat = true;
1829 mnCurPageId = 0;
1830 mnFirstPos = 0;
1831 maCurrentItemList = 0;
1833 // redraw bar
1834 if (IsReallyVisible() && IsUpdateMode())
1835 Invalidate();
1837 CallEventListeners(VCLEVENT_TABBAR_PAGEREMOVED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(PAGE_NOT_FOUND)));
1840 bool TabBar::IsPageEnabled(sal_uInt16 nPageId) const
1842 sal_uInt16 nPos = GetPagePos(nPageId);
1844 if (nPos != PAGE_NOT_FOUND)
1845 return mpImpl->mpItemList[nPos]->mbEnable;
1846 else
1847 return false;
1850 void TabBar::SetPageBits(sal_uInt16 nPageId, TabBarPageBits nBits)
1852 sal_uInt16 nPos = GetPagePos(nPageId);
1854 if (nPos != PAGE_NOT_FOUND)
1856 ImplTabBarItem* pItem = mpImpl->mpItemList[nPos];
1858 if (pItem->mnBits != nBits)
1860 pItem->mnBits = nBits;
1862 // redraw bar
1863 if (IsReallyVisible() && IsUpdateMode())
1864 Invalidate(pItem->maRect);
1869 TabBarPageBits TabBar::GetPageBits(sal_uInt16 nPageId) const
1871 sal_uInt16 nPos = GetPagePos(nPageId);
1873 if (nPos != PAGE_NOT_FOUND)
1874 return mpImpl->mpItemList[nPos]->mnBits;
1875 else
1876 return 0;
1879 sal_uInt16 TabBar::GetPageCount() const
1881 return mpImpl->getItemSize();
1884 sal_uInt16 TabBar::GetPageId(sal_uInt16 nPos) const
1886 return nPos < mpImpl->mpItemList.size() ? mpImpl->mpItemList[nPos]->mnId : 0;
1889 sal_uInt16 TabBar::GetPagePos(sal_uInt16 nPageId) const
1891 for (size_t i = 0; i < mpImpl->mpItemList.size(); ++i)
1893 if (mpImpl->mpItemList[i]->mnId == nPageId)
1895 return static_cast<sal_uInt16>(i);
1898 return PAGE_NOT_FOUND;
1901 sal_uInt16 TabBar::GetPageId(const Point& rPos) const
1903 for (size_t i = 0; i < mpImpl->mpItemList.size(); ++i)
1905 ImplTabBarItem* pItem = mpImpl->mpItemList[i];
1906 if (pItem->maRect.IsInside(rPos))
1907 return pItem->mnId;
1910 return 0;
1913 Rectangle TabBar::GetPageRect(sal_uInt16 nPageId) const
1915 sal_uInt16 nPos = GetPagePos(nPageId);
1917 if (nPos != PAGE_NOT_FOUND)
1918 return mpImpl->mpItemList[nPos]->maRect;
1919 else
1920 return Rectangle();
1923 void TabBar::SetCurPageId(sal_uInt16 nPageId)
1925 sal_uInt16 nPos = GetPagePos(nPageId);
1927 // do nothing if item does not exit
1928 if (nPos != PAGE_NOT_FOUND)
1930 // do nothing if the actual page did not change
1931 if (nPageId == mnCurPageId)
1932 return;
1934 // make invalide
1935 bool bUpdate = false;
1936 if (IsReallyVisible() && IsUpdateMode())
1937 bUpdate = true;
1939 ImplTabBarItem* pItem = mpImpl->mpItemList[nPos];
1940 ImplTabBarItem* pOldItem;
1942 if (mnCurPageId)
1943 pOldItem = mpImpl->mpItemList[GetPagePos(mnCurPageId)];
1944 else
1945 pOldItem = NULL;
1947 // deselect previous page if page was not selected, if this is the
1948 // only selected page
1949 if (!pItem->mbSelect && pOldItem)
1951 sal_uInt16 nSelPageCount = GetSelectPageCount();
1952 if (nSelPageCount == 1)
1953 pOldItem->mbSelect = false;
1954 pItem->mbSelect = true;
1957 mnCurPageId = nPageId;
1958 mbFormat = true;
1960 // assure the actual page becomes visible
1961 if (IsReallyVisible())
1963 if (nPos < mnFirstPos)
1964 SetFirstPageId(nPageId);
1965 else
1967 // calculate visible width
1968 long nWidth = mnLastOffX;
1969 if (nWidth > ADDNEWPAGE_AREAWIDTH)
1970 nWidth -= ADDNEWPAGE_AREAWIDTH;
1972 if (pItem->maRect.IsEmpty())
1973 ImplFormat();
1975 while ((mbMirrored ? (pItem->maRect.Left() < mnOffX) : (pItem->maRect.Right() > nWidth)) ||
1976 pItem->maRect.IsEmpty())
1978 sal_uInt16 nNewPos = mnFirstPos + 1;
1979 // assure at least the actual tabpages are visible as first tabpage
1980 if (nNewPos >= nPos)
1982 SetFirstPageId(nPageId);
1983 break;
1985 else
1986 SetFirstPageId(GetPageId(nNewPos));
1987 ImplFormat();
1988 // abort if first page is not forwarded
1989 if (nNewPos != mnFirstPos)
1990 break;
1995 // redraw bar
1996 if (bUpdate)
1998 Invalidate(pItem->maRect);
1999 if (pOldItem)
2000 Invalidate(pOldItem->maRect);
2005 void TabBar::MakeVisible(sal_uInt16 nPageId)
2007 if (!IsReallyVisible())
2008 return;
2010 sal_uInt16 nPos = GetPagePos(nPageId);
2012 // do nothing if item does not exist
2013 if (nPos != PAGE_NOT_FOUND)
2015 if (nPos < mnFirstPos)
2016 SetFirstPageId(nPageId);
2017 else
2019 ImplTabBarItem* pItem = mpImpl->mpItemList[nPos];
2021 // calculate visible area
2022 long nWidth = mnLastOffX;
2024 if (mbFormat || pItem->maRect.IsEmpty())
2026 mbFormat = true;
2027 ImplFormat();
2030 while ((pItem->maRect.Right() > nWidth) ||
2031 pItem->maRect.IsEmpty())
2033 sal_uInt16 nNewPos = mnFirstPos+1;
2034 // assure at least the actual tabpages are visible as first tabpage
2035 if (nNewPos >= nPos)
2037 SetFirstPageId(nPageId);
2038 break;
2040 else
2041 SetFirstPageId(GetPageId(nNewPos));
2042 ImplFormat();
2043 // abort if first page is not forwarded
2044 if (nNewPos != mnFirstPos)
2045 break;
2051 void TabBar::SetFirstPageId(sal_uInt16 nPageId)
2053 sal_uInt16 nPos = GetPagePos(nPageId);
2055 // return false if item does not exist
2056 if (nPos != PAGE_NOT_FOUND)
2058 if (nPos != mnFirstPos)
2060 // assure as much pages are visible as possible
2061 ImplFormat();
2062 sal_uInt16 nLastFirstPos = ImplGetLastFirstPos();
2063 sal_uInt16 nNewPos;
2064 if (nPos > nLastFirstPos)
2065 nNewPos = nLastFirstPos;
2066 else
2067 nNewPos = nPos;
2069 if (nNewPos != mnFirstPos)
2071 mnFirstPos = nNewPos;
2072 mbFormat = true;
2074 // redraw bar (attention: check mbDropPos,
2075 // as if this flag was set, we do not re-paint immediately
2076 if (IsReallyVisible() && IsUpdateMode() && !mbDropPos)
2077 Invalidate();
2083 void TabBar::SelectPage(sal_uInt16 nPageId, bool bSelect)
2085 sal_uInt16 nPos = GetPagePos(nPageId);
2087 if (nPos != PAGE_NOT_FOUND)
2089 ImplTabBarItem* pItem = mpImpl->mpItemList[nPos];
2091 if (pItem->mbSelect != bSelect)
2093 pItem->mbSelect = bSelect;
2095 // redraw bar
2096 if (IsReallyVisible() && IsUpdateMode())
2097 Invalidate(pItem->maRect);
2102 sal_uInt16 TabBar::GetSelectPageCount() const
2104 sal_uInt16 nSelected = 0;
2105 for (size_t i = 0; i < mpImpl->mpItemList.size(); ++i)
2107 ImplTabBarItem* pItem = mpImpl->mpItemList[i];
2108 if (pItem->mbSelect)
2109 nSelected++;
2112 return nSelected;
2115 bool TabBar::IsPageSelected(sal_uInt16 nPageId) const
2117 sal_uInt16 nPos = GetPagePos(nPageId);
2118 if (nPos != PAGE_NOT_FOUND)
2119 return mpImpl->mpItemList[nPos]->mbSelect;
2120 else
2121 return false;
2124 bool TabBar::StartEditMode(sal_uInt16 nPageId)
2126 sal_uInt16 nPos = GetPagePos( nPageId );
2127 if (mpImpl->mpEdit || (nPos == PAGE_NOT_FOUND) || (mnLastOffX < 8))
2128 return false;
2130 mnEditId = nPageId;
2131 if (StartRenaming())
2133 ImplShowPage(nPos);
2134 ImplFormat();
2135 Update();
2137 mpImpl->mpEdit.reset(VclPtr<TabBarEdit>::Create(this, WB_CENTER));
2138 Rectangle aRect = GetPageRect( mnEditId );
2139 long nX = aRect.Left();
2140 long nWidth = aRect.GetWidth();
2141 if (mnEditId != GetCurPageId())
2142 nX += 1;
2143 if (nX + nWidth > mnLastOffX)
2144 nWidth = mnLastOffX-nX;
2145 if (nWidth < 3)
2147 nX = aRect.Left();
2148 nWidth = aRect.GetWidth();
2150 mpImpl->mpEdit->SetText(GetPageText(mnEditId));
2151 mpImpl->mpEdit->setPosSizePixel(nX, aRect.Top() + mnOffY + 1, nWidth, aRect.GetHeight() - 3);
2152 vcl::Font aFont = GetPointFont(*this); // FIXME RenderContext
2154 Color aForegroundColor;
2155 Color aBackgroundColor;
2156 Color aFaceColor;
2157 Color aSelectColor;
2158 Color aFaceTextColor;
2159 Color aSelectTextColor;
2161 ImplGetColors(Application::GetSettings().GetStyleSettings(), aFaceColor, aFaceTextColor, aSelectColor, aSelectTextColor);
2163 if (mnEditId != GetCurPageId())
2165 aFont.SetWeight(WEIGHT_LIGHT);
2167 if (IsPageSelected(mnEditId) || mnEditId == GetCurPageId())
2169 aForegroundColor = aSelectTextColor;
2170 aBackgroundColor = aSelectColor;
2172 else
2174 aForegroundColor = aFaceTextColor;
2175 aBackgroundColor = aFaceColor;
2177 if (GetPageBits( mnEditId ) & TPB_SPECIAL)
2179 aForegroundColor = Color(COL_LIGHTBLUE);
2181 mpImpl->mpEdit->SetControlFont(aFont);
2182 mpImpl->mpEdit->SetControlForeground(aForegroundColor);
2183 mpImpl->mpEdit->SetControlBackground(aBackgroundColor);
2184 mpImpl->mpEdit->GrabFocus();
2185 mpImpl->mpEdit->SetSelection(Selection(0, mpImpl->mpEdit->GetText().getLength()));
2186 mpImpl->mpEdit->Show();
2187 return true;
2189 else
2191 mnEditId = 0;
2192 return false;
2196 bool TabBar::IsInEditMode() const
2198 return mpImpl->mpEdit.get() != NULL;
2201 void TabBar::EndEditMode(bool bCancel)
2203 if (mpImpl->mpEdit)
2205 // call hdl
2206 bool bEnd = true;
2207 mbEditCanceled = bCancel;
2208 maEditText = mpImpl->mpEdit->GetText();
2209 mpImpl->mpEdit->SetPostEvent();
2210 if (!bCancel)
2212 TabBarAllowRenamingReturnCode nAllowRenaming = AllowRenaming();
2213 if (nAllowRenaming == TABBAR_RENAMING_YES)
2214 SetPageText(mnEditId, maEditText);
2215 else if (nAllowRenaming == TABBAR_RENAMING_NO)
2216 bEnd = false;
2217 else // nAllowRenaming == TABBAR_RENAMING_CANCEL
2218 mbEditCanceled = true;
2221 // renaming not allowed, than reset edit data
2222 if (!bEnd)
2224 mpImpl->mpEdit->ResetPostEvent();
2225 mpImpl->mpEdit->GrabFocus();
2227 else
2229 // close edit and call end hdl
2230 mpImpl->mpEdit.disposeAndClear();
2232 EndRenaming();
2233 mnEditId = 0;
2236 // reset
2237 maEditText.clear();
2238 mbEditCanceled = false;
2242 void TabBar::SetMirrored(bool bMirrored)
2244 if (mbMirrored != bMirrored)
2246 mbMirrored = bMirrored;
2247 mbSizeFormat = true;
2248 ImplInitControls(); // for button images
2249 Resize(); // recalculates control positions
2250 Mirror();
2254 void TabBar::SetEffectiveRTL(bool bRTL)
2256 SetMirrored( bRTL != AllSettings::GetLayoutRTL() );
2259 bool TabBar::IsEffectiveRTL() const
2261 return IsMirrored() != AllSettings::GetLayoutRTL();
2264 void TabBar::SetMaxPageWidth(long nMaxWidth)
2266 if (mnMaxPageWidth != nMaxWidth)
2268 mnMaxPageWidth = nMaxWidth;
2269 mbSizeFormat = true;
2271 // redraw bar
2272 if (IsReallyVisible() && IsUpdateMode())
2273 Invalidate();
2277 void TabBar::SetPageText(sal_uInt16 nPageId, const OUString& rText)
2279 sal_uInt16 nPos = GetPagePos(nPageId);
2280 if (nPos != PAGE_NOT_FOUND)
2282 mpImpl->mpItemList[nPos]->maText = rText;
2283 mbSizeFormat = true;
2285 // redraw bar
2286 if (IsReallyVisible() && IsUpdateMode())
2287 Invalidate();
2289 CallEventListeners(VCLEVENT_TABBAR_PAGETEXTCHANGED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(nPageId)));
2293 OUString TabBar::GetPageText(sal_uInt16 nPageId) const
2295 sal_uInt16 nPos = GetPagePos(nPageId);
2296 if (nPos != PAGE_NOT_FOUND)
2297 return mpImpl->mpItemList[nPos]->maText;
2298 return OUString();
2301 OUString TabBar::GetHelpText(sal_uInt16 nPageId) const
2303 sal_uInt16 nPos = GetPagePos(nPageId);
2304 if (nPos != PAGE_NOT_FOUND)
2306 ImplTabBarItem* pItem = mpImpl->mpItemList[nPos];
2307 if (pItem->maHelpText.isEmpty() && !pItem->maHelpId.isEmpty())
2309 Help* pHelp = Application::GetHelp();
2310 if (pHelp)
2311 pItem->maHelpText = pHelp->GetHelpText(OStringToOUString(pItem->maHelpId, RTL_TEXTENCODING_UTF8), this);
2314 return pItem->maHelpText;
2316 return OUString();
2319 OString TabBar::GetHelpId(sal_uInt16 nPageId) const
2321 sal_uInt16 nPos = GetPagePos(nPageId);
2322 OString aRet;
2323 if (nPos != PAGE_NOT_FOUND)
2324 return mpImpl->mpItemList[nPos]->maHelpId;
2325 return aRet;
2328 bool TabBar::StartDrag(const CommandEvent& rCEvt, vcl::Region& rRegion)
2330 if (!(mnWinStyle & WB_DRAG) || (rCEvt.GetCommand() != CommandEventId::StartDrag))
2331 return false;
2333 // Check if the clicked page was selected. If this is not the case
2334 // set it as actual entry. We check for this only at a mouse action
2335 // if Drag and Drop can be triggered from the keyboard.
2336 // We only do this, if Select() was not triggered, as the Select()
2337 // could have scrolled the area
2338 if (rCEvt.IsMouseEvent() && !mbInSelect)
2340 sal_uInt16 nSelId = GetPageId(rCEvt.GetMousePosPixel());
2342 // do not start dragging if no entry was clicked
2343 if (!nSelId)
2344 return false;
2346 // check if page was selected. If not set it as actual
2347 // page and call Select()
2348 if (!IsPageSelected(nSelId))
2350 if (ImplDeactivatePage())
2352 SetCurPageId(nSelId);
2353 Update();
2354 ImplActivatePage();
2355 ImplSelect();
2357 else
2358 return false;
2361 mbInSelect = false;
2363 vcl::Region aRegion;
2365 // assign region
2366 rRegion = aRegion;
2368 return true;
2371 sal_uInt16 TabBar::ShowDropPos(const Point& rPos)
2373 ImplTabBarItem* pItem;
2374 sal_uInt16 nDropId;
2375 sal_uInt16 nNewDropPos;
2376 sal_uInt16 nItemCount = mpImpl->getItemSize();
2377 sal_Int16 nScroll = 0;
2379 if (rPos.X() > mnLastOffX-TABBAR_DRAG_SCROLLOFF)
2381 pItem = mpImpl->mpItemList[mpImpl->mpItemList.size() - 1];
2382 if (!pItem->maRect.IsEmpty() && (rPos.X() > pItem->maRect.Right()))
2383 nNewDropPos = mpImpl->getItemSize();
2384 else
2386 nNewDropPos = mnFirstPos + 1;
2387 nScroll = 1;
2390 else if ((rPos.X() <= mnOffX) ||
2391 (!mnOffX && (rPos.X() <= TABBAR_DRAG_SCROLLOFF)))
2393 if (mnFirstPos)
2395 nNewDropPos = mnFirstPos;
2396 nScroll = -1;
2398 else
2399 nNewDropPos = 0;
2401 else
2403 nDropId = GetPageId(rPos);
2404 if (nDropId)
2406 nNewDropPos = GetPagePos(nDropId);
2407 if (mnFirstPos && (nNewDropPos == mnFirstPos - 1))
2408 nScroll = -1;
2410 else
2411 nNewDropPos = nItemCount;
2414 if (mbDropPos && (nNewDropPos == mnDropPos) && !nScroll)
2415 return mnDropPos;
2417 if (mbDropPos)
2418 HideDropPos();
2419 mbDropPos = true;
2420 mnDropPos = nNewDropPos;
2422 if (nScroll)
2424 sal_uInt16 nOldFirstPos = mnFirstPos;
2425 SetFirstPageId(GetPageId(mnFirstPos + nScroll));
2427 // draw immediately, as Paint not possible during Drag and Drop
2428 if (nOldFirstPos != mnFirstPos)
2430 Rectangle aRect(mnOffX, 0, mnLastOffX, maWinSize.Height());
2431 SetFillColor(GetBackground().GetColor());
2432 DrawRect(aRect);
2433 Invalidate(aRect);
2437 // draw drop position arrows
2438 Color aBlackColor(COL_BLACK);
2439 long nX;
2440 long nY = (maWinSize.Height() / 2) - 1;
2441 sal_uInt16 nCurPos = GetPagePos(mnCurPageId);
2443 sal_Int32 nTriangleWidth = 3 * GetDPIScaleFactor();
2445 if (mnDropPos < nItemCount)
2447 SetLineColor(aBlackColor);
2448 SetFillColor(aBlackColor);
2450 pItem = mpImpl->mpItemList[mnDropPos];
2451 nX = pItem->maRect.Left();
2452 if ( mnDropPos == nCurPos )
2453 nX--;
2454 else
2455 nX++;
2457 if (!pItem->IsDefaultTabBgColor() && !pItem->mbSelect)
2459 SetLineColor(pItem->maTabTextColor);
2460 SetFillColor(pItem->maTabTextColor);
2463 Polygon aPoly(3);
2464 aPoly.SetPoint(Point(nX, nY), 0);
2465 aPoly.SetPoint(Point(nX + nTriangleWidth, nY - nTriangleWidth), 1);
2466 aPoly.SetPoint(Point(nX + nTriangleWidth, nY + nTriangleWidth), 2);
2467 DrawPolygon(aPoly);
2469 if (mnDropPos > 0 && mnDropPos < nItemCount + 1)
2471 SetLineColor(aBlackColor);
2472 SetFillColor(aBlackColor);
2474 pItem = mpImpl->mpItemList[mnDropPos - 1];
2475 nX = pItem->maRect.Right();
2476 if (mnDropPos == nCurPos)
2477 nX++;
2478 if (!pItem->IsDefaultTabBgColor() && !pItem->mbSelect)
2480 SetLineColor(pItem->maTabTextColor);
2481 SetFillColor(pItem->maTabTextColor);
2483 Polygon aPoly(3);
2484 aPoly.SetPoint(Point(nX, nY), 0);
2485 aPoly.SetPoint(Point(nX - nTriangleWidth, nY - nTriangleWidth), 1);
2486 aPoly.SetPoint(Point(nX - nTriangleWidth, nY + nTriangleWidth), 2);
2487 DrawPolygon(aPoly);
2490 return mnDropPos;
2493 void TabBar::HideDropPos()
2495 if (mbDropPos)
2497 ImplTabBarItem* pItem;
2498 long nX;
2499 long nY1 = (maWinSize.Height() / 2) - 3;
2500 long nY2 = nY1 + 5;
2501 sal_uInt16 nItemCount = mpImpl->getItemSize();
2503 if (mnDropPos < nItemCount)
2505 pItem = mpImpl->mpItemList[mnDropPos];
2506 nX = pItem->maRect.Left();
2507 // immediately call Paint, as it is not possible during drag and drop
2508 Rectangle aRect( nX-1, nY1, nX+3, nY2 );
2509 vcl::Region aRegion( aRect );
2510 SetClipRegion( aRegion );
2511 Invalidate(aRect);
2512 SetClipRegion();
2514 if (mnDropPos > 0 && mnDropPos < nItemCount + 1)
2516 pItem = mpImpl->mpItemList[mnDropPos - 1];
2517 nX = pItem->maRect.Right();
2518 // immediately call Paint, as it is not possible during drag and drop
2519 Rectangle aRect(nX - 2, nY1, nX + 1, nY2);
2520 vcl::Region aRegion(aRect);
2521 SetClipRegion(aRegion);
2522 Invalidate(aRect);
2523 SetClipRegion();
2526 mbDropPos = false;
2527 mnDropPos = 0;
2531 bool TabBar::SwitchPage(const Point& rPos)
2533 bool bSwitch = false;
2534 sal_uInt16 nSwitchId = GetPageId(rPos);
2535 if (!nSwitchId)
2536 EndSwitchPage();
2537 else
2539 if (nSwitchId != mnSwitchId)
2541 mnSwitchId = nSwitchId;
2542 mnSwitchTime = tools::Time::GetSystemTicks();
2544 else
2546 // change only after 500 ms
2547 if (mnSwitchId != GetCurPageId())
2549 if (tools::Time::GetSystemTicks() > mnSwitchTime + 500)
2551 mbInSwitching = true;
2552 if (ImplDeactivatePage())
2554 SetCurPageId( mnSwitchId );
2555 Update();
2556 ImplActivatePage();
2557 ImplSelect();
2558 bSwitch = true;
2560 mbInSwitching = false;
2566 return bSwitch;
2569 void TabBar::EndSwitchPage()
2571 mnSwitchTime = 0;
2572 mnSwitchId = 0;
2575 void TabBar::SetStyle(WinBits nStyle)
2577 mnWinStyle = nStyle;
2578 ImplInitControls();
2579 // order possible controls
2580 if (IsReallyVisible() && IsUpdateMode())
2581 Resize();
2584 Size TabBar::CalcWindowSizePixel() const
2586 long nWidth = 0;
2588 if (mpImpl->mpItemList.size() > 0)
2590 const_cast<TabBar*>(this)->ImplCalcWidth();
2591 for (size_t i = 0; i < mpImpl->mpItemList.size(); ++i)
2593 ImplTabBarItem* pItem = mpImpl->mpItemList[i];
2594 nWidth += pItem->mnWidth;
2598 return Size(nWidth, GetSettings().GetStyleSettings().GetScrollBarSize());
2601 Rectangle TabBar::GetPageArea() const
2603 return Rectangle(Point(mnOffX, mnOffY),
2604 Size(mnLastOffX - mnOffX + 1, GetSizePixel().Height() - mnOffY));
2607 css::uno::Reference<css::accessibility::XAccessible> TabBar::CreateAccessible()
2609 return mpImpl->maAccessibleFactory.getFactory().createAccessibleTabBar(*this);
2612 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */