diff options
author | Jan-Marek Glogowski <glogow@fbihome.de> | 2019-06-16 21:41:31 +0000 |
---|---|---|
committer | Jan-Marek Glogowski <glogow@fbihome.de> | 2019-06-21 16:47:47 +0200 |
commit | 6540912ae1a570fd8c2318f77b757e07b87c0707 (patch) | |
tree | f2da76bb78e4d785915be2ceb282d519600f49f2 | |
parent | d25e5069176ab53cdc917e3501a81e9546ec46f7 (diff) |
VCL merge most of NotebookbarTabControlBase
NotebookbarTabControlBase (NBBTCB) tried to be clever and save
a bool per TabControl page, by not adding a mbVisible to the
ImplTabItem and misuse mbEnabled.
The result is not only a bug with tab highlighting in notebook
bars, but also a lot of duplicate code and additional virtual
functions. Normal TabControls highlight correct.
I'm not 100% sure about the dropped Resize()s, but the code in
ImplPaint() and calculateRequisition() differs by three lines;
which can be merged by adding the TabControl feature to hide
tabs and not just disable them. I first tried to additionally
merge ImplPlaceTabs() too, but the NBBTCB version differs much
more and I didn't want to touch larger parts of TabControl.
Change-Id: Ie6e18fb03b76b46e3627923eb1ac0f674c3eb7e8
Reviewed-on: https://gerrit.libreoffice.org/74126
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
-rw-r--r-- | include/vcl/tabctrl.hxx | 21 | ||||
-rw-r--r-- | toolkit/source/awt/vclxtabpagecontainer.cxx | 2 | ||||
-rw-r--r-- | vcl/source/control/tabctrl.cxx | 569 |
3 files changed, 154 insertions, 438 deletions
diff --git a/include/vcl/tabctrl.hxx b/include/vcl/tabctrl.hxx index cf64e66efc64..956c5ece7a6b 100644 --- a/include/vcl/tabctrl.hxx +++ b/include/vcl/tabctrl.hxx @@ -64,8 +64,10 @@ protected: using Control::ImplInitSettings; SAL_DLLPRIVATE void ImplInitSettings( bool bBackground ); SAL_DLLPRIVATE ImplTabItem* ImplGetItem( sal_uInt16 nId ) const; + SAL_DLLPRIVATE ImplTabItem* ImplGetItem(const Point& rPt) const; SAL_DLLPRIVATE Size ImplGetItemSize( ImplTabItem* pItem, long nMaxWidth ); SAL_DLLPRIVATE tools::Rectangle ImplGetTabRect( sal_uInt16 nPos, long nWidth = -1, long nHeight = -1 ); + SAL_DLLPRIVATE tools::Rectangle ImplGetTabRect(const ImplTabItem*, long nWidth = -1, long nHeight = -1); SAL_DLLPRIVATE void ImplChangeTabPage( sal_uInt16 nId, sal_uInt16 nOldId ); SAL_DLLPRIVATE bool ImplPosCurTabPage(); virtual void ImplActivateTabPage( bool bNext ); @@ -85,9 +87,8 @@ protected: virtual void FillLayoutData() const override; virtual const vcl::Font& GetCanonicalFont( const StyleSettings& _rStyle ) const override; virtual const Color& GetCanonicalTextColor( const StyleSettings& _rStyle ) const override; - SAL_DLLPRIVATE tools::Rectangle* ImplFindPartRect( const Point& rPt ); virtual bool ImplPlaceTabs( long nWidth ); - virtual void ImplPaint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect); + SAL_DLLPRIVATE Size ImplCalculateRequisition(sal_uInt16& nHeaderHeight) const; public: TabControl( vcl::Window* pParent, @@ -124,21 +125,23 @@ public: sal_uInt16 nPos = TAB_APPEND ); void RemovePage( sal_uInt16 nPageId ); void Clear(); - void EnablePage( sal_uInt16 nPageId, bool bEnable = true ); + + void SetPageEnabled(sal_uInt16 nPageId, bool bEnable = true); + void SetPageVisible(sal_uInt16 nPageId, bool bVisible = true); sal_uInt16 GetPagePos( sal_uInt16 nPageId ) const; sal_uInt16 GetPageCount() const; sal_uInt16 GetPageId( sal_uInt16 nPos ) const; - virtual sal_uInt16 GetPageId( const Point& rPos ) const; + sal_uInt16 GetPageId(const Point& rPos) const; sal_uInt16 GetPageId( const TabPage& rPage ) const; sal_uInt16 GetPageId( const OString& rName ) const; - virtual void SetCurPageId( sal_uInt16 nPageId ); + void SetCurPageId(sal_uInt16 nPageId); sal_uInt16 GetCurPageId() const; - virtual void SelectTabPage( sal_uInt16 nPageId ); + void SelectTabPage( sal_uInt16 nPageId ); - void SetTabPage( sal_uInt16 nPageId, TabPage* pPage ); + void SetTabPage(sal_uInt16 nPageId, TabPage* pPage); TabPage* GetTabPage( sal_uInt16 nPageId ) const; void SetPageText( sal_uInt16 nPageId, const OUString& rText ); @@ -203,15 +206,11 @@ public: ToolBox* GetToolBox() { return m_pShortcuts; } PushButton* GetOpenMenu() { return m_pOpenMenu; } - virtual sal_uInt16 GetPageId( const Point& rPos ) const override; - virtual void SelectTabPage( sal_uInt16 nPageId ) override; - virtual void SetCurPageId( sal_uInt16 nPageId ) override; virtual Size calculateRequisition() const override; static sal_uInt16 GetHeaderHeight(); protected: virtual bool ImplPlaceTabs( long nWidth ) override; - virtual void ImplPaint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override; virtual void ImplActivateTabPage( bool bNext ) override; private: diff --git a/toolkit/source/awt/vclxtabpagecontainer.cxx b/toolkit/source/awt/vclxtabpagecontainer.cxx index 56e492ea8069..25ff686c5466 100644 --- a/toolkit/source/awt/vclxtabpagecontainer.cxx +++ b/toolkit/source/awt/vclxtabpagecontainer.cxx @@ -190,7 +190,7 @@ void SAL_CALL VCLXTabPageContainer::elementInserted( const css::container::Conta pTabCtrl->SetHelpText(nPageID,xP->getToolTip()); pTabCtrl->SetPageImage(nPageID,TkResMgr::getImageFromURL(xP->getImageURL())); pTabCtrl->SelectTabPage(nPageID); - pTabCtrl->EnablePage(nPageID,xP->getEnabled()); + pTabCtrl->SetPageEnabled(nPageID,xP->getEnabled()); m_aTabPages.push_back(xTabPage); } diff --git a/vcl/source/control/tabctrl.cxx b/vcl/source/control/tabctrl.cxx index d5b9eeeeacfa..d23db1eaf9cf 100644 --- a/vcl/source/control/tabctrl.cxx +++ b/vcl/source/control/tabctrl.cxx @@ -56,12 +56,15 @@ struct ImplTabItem tools::Rectangle maRect; sal_uInt16 mnLine; bool mbFullVisible; - bool mbEnabled; + bool m_bEnabled; ///< the tab / page is selectable + bool m_bVisible; ///< the tab / page can be visible Image maTabImage; ImplTabItem() : mnId( 0 ), mpTabPage( nullptr ), - mnLine( 0 ), mbFullVisible( false ), mbEnabled( true ) + mnLine( 0 ), mbFullVisible( false ) + , m_bEnabled(true) + , m_bVisible(true) {} }; @@ -400,6 +403,9 @@ bool TabControl::ImplPlaceTabs( long nWidth ) for (auto & item : mpTabCtrlData->maItemList) { + if (!item.m_bVisible) + continue; + Size aSize = ImplGetItemSize( &item, nMaxWidth ); bool bNewLine = false; @@ -531,8 +537,8 @@ tools::Rectangle TabControl::ImplGetTabRect( sal_uInt16 nItemPos, long nWidth, l long nW = nWidth-TAB_OFFSET*2; long nH = nHeight-TAB_OFFSET*2; return (nW > 0 && nH > 0) - ? tools::Rectangle( Point( TAB_OFFSET, TAB_OFFSET ), Size( nW, nH ) ) - : tools::Rectangle(); + ? tools::Rectangle(Point(TAB_OFFSET, TAB_OFFSET), Size(nW, nH)) + : tools::Rectangle(); } if ( nItemPos == TAB_PAGERECT ) @@ -546,19 +552,26 @@ tools::Rectangle TabControl::ImplGetTabRect( sal_uInt16 nItemPos, long nWidth, l tools::Rectangle aRect = ImplGetTabRect( nLastPos, nWidth, nHeight ); if (aRect.IsEmpty()) return aRect; + long nW = nWidth-TAB_OFFSET*2; long nH = nHeight-aRect.Bottom()-TAB_OFFSET*2; - aRect = (nW > 0 && nH > 0) + return (nW > 0 && nH > 0) ? tools::Rectangle( Point( TAB_OFFSET, aRect.Bottom()+TAB_OFFSET ), Size( nW, nH ) ) : tools::Rectangle(); - return aRect; } - nWidth -= 1; + ImplTabItem* const pItem = (nItemPos < mpTabCtrlData->maItemList.size()) + ? &mpTabCtrlData->maItemList[nItemPos] : nullptr; + return ImplGetTabRect(pItem, nWidth, nHeight); +} - if ( (nWidth <= 0) || (nHeight <= 0) ) +tools::Rectangle TabControl::ImplGetTabRect(const ImplTabItem* pItem, long nWidth, long nHeight) +{ + if ((nWidth <= 1) || (nHeight <= 0) || !pItem || !pItem->m_bVisible) return tools::Rectangle(); + nWidth -= 1; + if ( mbFormat || (mnLastWidth != nWidth) || (mnLastHeight != nHeight) ) { vcl::Font aFont( GetFont() ); @@ -574,7 +587,7 @@ tools::Rectangle TabControl::ImplGetTabRect( sal_uInt16 nItemPos, long nWidth, l mbFormat = false; } - return size_t(nItemPos) < mpTabCtrlData->maItemList.size() ? mpTabCtrlData->maItemList[nItemPos].maRect : tools::Rectangle(); + return pItem->maRect; } void TabControl::ImplChangeTabPage( sal_uInt16 nId, sal_uInt16 nOldId ) @@ -763,7 +776,7 @@ void TabControl::ImplShowFocus() void TabControl::ImplDrawItem(vcl::RenderContext& rRenderContext, ImplTabItem const * pItem, const tools::Rectangle& rCurRect, bool bFirstInGroup, bool bLastInGroup ) { - if (pItem->maRect.IsEmpty()) + if (!pItem->m_bVisible || pItem->maRect.IsEmpty()) return; const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings(); @@ -827,13 +840,12 @@ void TabControl::ImplDrawItem(vcl::RenderContext& rRenderContext, ImplTabItem co { nState |= ControlState::ROLLOVER; for (auto const& item : mpTabCtrlData->maItemList) - { - if( (&item != pItem) && (item.maRect.IsInside(GetPointerPosPixel()))) + if ((&item != pItem) && item.m_bVisible && item.maRect.IsInside(GetPointerPosPixel())) { nState &= ~ControlState::ROLLOVER; // avoid multiple highlighted tabs break; } - } + assert(nState & ControlState::ROLLOVER); } bNativeOK = rRenderContext.IsNativeControlSupported(ControlType::TabItem, ControlPart::Entire); @@ -923,7 +935,7 @@ void TabControl::ImplDrawItem(vcl::RenderContext& rRenderContext, ImplTabItem co if (!pItem->maFormatText.isEmpty()) { DrawTextFlags nStyle = DrawTextFlags::Mnemonic; - if (!pItem->mbEnabled) + if (!pItem->m_bEnabled) nStyle |= DrawTextFlags::Disable; Color aColor(rStyleSettings.GetTabTextColor()); @@ -948,7 +960,7 @@ void TabControl::ImplDrawItem(vcl::RenderContext& rRenderContext, ImplTabItem co Point aImgTL( nXPos, aRect.Top() ); if (aImageSize.Height() < aRect.GetHeight()) aImgTL.AdjustY((aRect.GetHeight() - aImageSize.Height()) / 2 ); - rRenderContext.DrawImage(aImgTL, pItem->maTabImage, pItem->mbEnabled ? DrawImageFlags::NONE : DrawImageFlags::Disable ); + rRenderContext.DrawImage(aImgTL, pItem->maTabImage, pItem->m_bEnabled ? DrawImageFlags::NONE : DrawImageFlags::Disable ); } } @@ -1005,16 +1017,12 @@ IMPL_LINK( TabControl, ImplWindowEventListener, VclWindowEvent&, rEvent, void ) void TabControl::MouseButtonDown( const MouseEvent& rMEvt ) { - if( mpTabCtrlData->mpListBox.get() == nullptr ) - { - if( rMEvt.IsLeft() ) - { - sal_uInt16 nPageId = GetPageId( rMEvt.GetPosPixel() ); - ImplTabItem* pItem = ImplGetItem( nPageId ); - if( pItem && pItem->mbEnabled ) - SelectTabPage( nPageId ); - } - } + if (mpTabCtrlData->mpListBox.get() != nullptr || !rMEvt.IsLeft()) + return; + + ImplTabItem *pItem = ImplGetItem(rMEvt.GetPosPixel()); + if (pItem && pItem->m_bEnabled) + SelectTabPage(pItem->mnId); } void TabControl::KeyInput( const KeyEvent& rKEvt ) @@ -1036,14 +1044,21 @@ void TabControl::KeyInput( const KeyEvent& rKEvt ) Control::KeyInput( rKEvt ); } -void TabControl::Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) +static bool lcl_canPaint(const vcl::RenderContext& rRenderContext, const tools::Rectangle& rDrawRect, + const tools::Rectangle& rItemRect) { - if (!(GetStyle() & WB_NOBORDER)) - ImplPaint(rRenderContext, rRect); + vcl::Region aClipRgn(rRenderContext.GetActiveClipRegion()); + aClipRgn.Intersect(rItemRect); + if (!rDrawRect.IsEmpty()) + aClipRgn.Intersect(rDrawRect); + return !aClipRgn.IsEmpty(); } -void TabControl::ImplPaint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) +void TabControl::Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) { + if (GetStyle() & WB_NOBORDER) + return; + HideFocus(); // reformat if needed @@ -1091,31 +1106,16 @@ void TabControl::ImplPaint(vcl::RenderContext& rRenderContext, const tools::Rect if (HasFocus()) nState |= ControlState::FOCUSED; - vcl::Region aClipRgn(rRenderContext.GetActiveClipRegion()); - aClipRgn.Intersect(aRect); - if (!rRect.IsEmpty()) - aClipRgn.Intersect(rRect); - - if (!aClipRgn.IsEmpty()) - { + if (lcl_canPaint(rRenderContext, rRect, aRect)) rRenderContext.DrawNativeControl(ControlType::TabPane, ControlPart::Entire, aRect, nState, aControlValue, OUString()); - } if (rRenderContext.IsNativeControlSupported(ControlType::TabHeader, ControlPart::Entire)) { tools::Rectangle aHeaderRect(aRect.Left(), 0, aRect.Right(), aRect.Top()); - - aClipRgn = rRenderContext.GetActiveClipRegion(); - aClipRgn.Intersect(aHeaderRect); - if (!rRect.IsEmpty()) - aClipRgn.Intersect(rRect); - - if (!aClipRgn.IsEmpty()) - { + if (lcl_canPaint(rRenderContext, rRect, aHeaderRect)) rRenderContext.DrawNativeControl(ControlType::TabHeader, ControlPart::Entire, aHeaderRect, nState, aControlValue, OUString()); - } } } else @@ -1195,18 +1195,8 @@ void TabControl::ImplPaint(vcl::RenderContext& rRenderContext, const tools::Rect { ImplTabItem* pItem = &mpTabCtrlData->maItemList[idx]; - if (pItem != pCurItem) - { - vcl::Region aClipRgn(rRenderContext.GetActiveClipRegion()); - aClipRgn.Intersect(pItem->maRect); - if (!rRect.IsEmpty()) - aClipRgn.Intersect(rRect); - if (!aClipRgn.IsEmpty()) - { - ImplDrawItem(rRenderContext, pItem, aCurRect, - pItem == pFirstTab, pItem == pLastTab); - } - } + if (pItem != pCurItem && pItem->m_bVisible && lcl_canPaint(rRenderContext, rRect, pItem->maRect)) + ImplDrawItem(rRenderContext, pItem, aCurRect, pItem == pFirstTab, pItem == pLastTab); if (bDrawTabsRTL) idx--; @@ -1214,24 +1204,16 @@ void TabControl::ImplPaint(vcl::RenderContext& rRenderContext, const tools::Rect idx++; } - if (pCurItem) - { - vcl::Region aClipRgn(rRenderContext.GetActiveClipRegion()); - aClipRgn.Intersect(pCurItem->maRect); - if (!rRect.IsEmpty()) - aClipRgn.Intersect(rRect); - if (!aClipRgn.IsEmpty()) - { - ImplDrawItem(rRenderContext, pCurItem, aCurRect, - pCurItem == pFirstTab, pCurItem == pLastTab); - } - } + if (pCurItem && lcl_canPaint(rRenderContext, rRect, pCurItem->maRect)) + ImplDrawItem(rRenderContext, pCurItem, aCurRect, pCurItem == pFirstTab, pCurItem == pLastTab); } if (HasFocus()) ImplShowFocus(); mbSmallInvalidate = true; + + Control::Paint(rRenderContext, rRect); } void TabControl::setAllocation(const Size &rAllocation) @@ -1263,8 +1245,9 @@ void TabControl::setAllocation(const Size &rAllocation) long nNewWidth = aNewSize.Width(); for (auto const& item : mpTabCtrlData->maItemList) { - if ( !item.mbFullVisible || - (item.maRect.Right()-2 >= nNewWidth) ) + if (!item.m_bVisible) + continue; + if (!item.mbFullVisible || (item.maRect.Right()-2 >= nNewWidth)) { mbSmallInvalidate = false; break; @@ -1501,21 +1484,22 @@ void TabControl::DataChanged( const DataChangedEvent& rDCEvt ) } } -tools::Rectangle* TabControl::ImplFindPartRect( const Point& rPt ) +ImplTabItem* TabControl::ImplGetItem(const Point& rPt) const { ImplTabItem* pFoundItem = nullptr; int nFound = 0; for (auto & item : mpTabCtrlData->maItemList) { - if ( item.maRect.IsInside( rPt ) ) + if (item.m_bVisible && item.maRect.IsInside(rPt)) { - // assure that only one tab is highlighted at a time nFound++; pFoundItem = &item; } } + // assure that only one tab is highlighted at a time - return nFound == 1 ? &pFoundItem->maRect : nullptr; + assert(nFound <= 1); + return nFound == 1 ? pFoundItem : nullptr; } bool TabControl::PreNotify( NotifyEvent& rNEvt ) @@ -1529,33 +1513,35 @@ bool TabControl::PreNotify( NotifyEvent& rNEvt ) // trigger redraw if mouse over state has changed if( IsNativeControlSupported(ControlType::TabItem, ControlPart::Entire) ) { - tools::Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() ); - tools::Rectangle* pLastRect = ImplFindPartRect( GetLastPointerPosPixel() ); - if( pRect != pLastRect || (pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow()) ) + ImplTabItem *pItem = ImplGetItem(GetPointerPosPixel()); + ImplTabItem *pLastItem = ImplGetItem(GetLastPointerPosPixel()); + if ((pItem != pLastItem) || pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow()) { vcl::Region aClipRgn; - if( pLastRect ) + if (pLastItem) { // allow for slightly bigger tabitems // as used by gtk // TODO: query for the correct sizes - tools::Rectangle aRect(*pLastRect); + tools::Rectangle aRect(pLastItem->maRect); aRect.AdjustLeft( -2 ); aRect.AdjustRight(2 ); aRect.AdjustTop( -3 ); aClipRgn.Union( aRect ); } - if( pRect ) + + if (pItem) { // allow for slightly bigger tabitems // as used by gtk // TODO: query for the correct sizes - tools::Rectangle aRect(*pRect); + tools::Rectangle aRect(pItem->maRect); aRect.AdjustLeft( -2 ); aRect.AdjustRight(2 ); aRect.AdjustTop( -3 ); aClipRgn.Union( aRect ); } + if( !aClipRgn.IsEmpty() ) Invalidate( aClipRgn ); } @@ -1719,27 +1705,46 @@ void TabControl::Clear() CallEventListeners( VclEventId::TabpageRemovedAll ); } -void TabControl::EnablePage( sal_uInt16 i_nPageId, bool i_bEnable ) +void TabControl::SetPageEnabled( sal_uInt16 i_nPageId, bool i_bEnable ) { ImplTabItem* pItem = ImplGetItem( i_nPageId ); - if ( pItem && pItem->mbEnabled != i_bEnable ) + if (pItem && pItem->m_bEnabled != i_bEnable) { - pItem->mbEnabled = i_bEnable; + pItem->m_bEnabled = i_bEnable; + if (!pItem->m_bVisible) + return; + mbFormat = true; if( mpTabCtrlData->mpListBox ) mpTabCtrlData->mpListBox->SetEntryFlags( GetPagePos( i_nPageId ), i_bEnable ? ListBoxEntryFlags::NONE : (ListBoxEntryFlags::DisableSelection | ListBoxEntryFlags::DrawDisabled) ); - if( pItem->mnId == mnCurPageId ) - { - // SetCurPageId will change to an enabled page + + // SetCurPageId will change to a valid page + if (pItem->mnId == mnCurPageId) SetCurPageId( mnCurPageId ); - } else if ( IsUpdateMode() ) Invalidate(); } } +void TabControl::SetPageVisible( sal_uInt16 nPageId, bool bVisible ) +{ + ImplTabItem* pItem = ImplGetItem( nPageId ); + if (!pItem || pItem->m_bVisible == bVisible) + return; + + pItem->m_bVisible = bVisible; + pItem->maRect.SetEmpty(); + mbFormat = true; + + // SetCurPageId will change to a valid page + if (pItem->mnId == mnCurPageId) + SetCurPageId(mnCurPageId); + else if (IsUpdateMode()) + Invalidate(); +} + sal_uInt16 TabControl::GetPageCount() const { return static_cast<sal_uInt16>(mpTabCtrlData->maItemList.size()); @@ -1767,42 +1772,32 @@ sal_uInt16 TabControl::GetPagePos( sal_uInt16 nPageId ) const sal_uInt16 TabControl::GetPageId( const Point& rPos ) const { - for( size_t i = 0; i < mpTabCtrlData->maItemList.size(); ++i ) - { - if ( const_cast<TabControl*>(this)->ImplGetTabRect( static_cast<sal_uInt16>(i) ).IsInside( rPos ) ) - return mpTabCtrlData->maItemList[ i ].mnId; - } - - return 0; + const auto &rList = mpTabCtrlData->maItemList; + const auto it = std::find_if(rList.begin(), rList.end(), [&rPos, this](const auto &item) { + return const_cast<TabControl*>(this)->ImplGetTabRect(&item).IsInside(rPos); }); + return (it != rList.end()) ? it->mnId : 0; } sal_uInt16 TabControl::GetPageId( const TabPage& rPage ) const { - for (auto const& item : mpTabCtrlData->maItemList) - { - if ( item.mpTabPage == &rPage ) - return item.mnId; - } - - return 0; + const auto &rList = mpTabCtrlData->maItemList; + const auto it = std::find_if(rList.begin(), rList.end(), [&rPage](const auto &item) { + return item.mpTabPage == &rPage; }); + return (it != rList.end()) ? it->mnId : 0; } sal_uInt16 TabControl::GetPageId( const OString& rName ) const { - for (auto const& item : mpTabCtrlData->maItemList) - { - if ( item.maTabName == rName ) - return item.mnId; - } - - return 0; + const auto &rList = mpTabCtrlData->maItemList; + const auto it = std::find_if(rList.begin(), rList.end(), [&rName](const auto &item) { + return item.maTabName == rName; }); + return (it != rList.end()) ? it->mnId : 0; } void TabControl::SetCurPageId( sal_uInt16 nPageId ) { sal_uInt16 nPos = GetPagePos( nPageId ); - while( nPos != TAB_PAGE_NOTFOUND && - ! mpTabCtrlData->maItemList[nPos].mbEnabled ) + while (nPos != TAB_PAGE_NOTFOUND && !mpTabCtrlData->maItemList[nPos].m_bEnabled) { nPos++; if( size_t(nPos) >= mpTabCtrlData->maItemList.size() ) @@ -2055,7 +2050,7 @@ tools::Rectangle TabControl::GetTabBounds( sal_uInt16 nPageId ) const tools::Rectangle aRet; ImplTabItem* pItem = ImplGetItem( nPageId ); - if(pItem) + if (pItem && pItem->m_bVisible) aRet = pItem->maRect; return aRet; @@ -2075,7 +2070,7 @@ Point TabControl::GetItemsOffset() const return Point(); } -Size TabControl::calculateRequisition() const +Size TabControl::ImplCalculateRequisition(sal_uInt16& nHeaderHeight) const { Size aOptimalPageSize(0, 0); @@ -2122,8 +2117,11 @@ Size TabControl::calculateRequisition() const tools::Rectangle aTabRect = pThis->ImplGetTabRect(nPos, aOptimalPageSize.Width(), LONG_MAX); if (aTabRect.Bottom() > nTabLabelsBottom) + { nTabLabelsBottom = aTabRect.Bottom(); - if (aTabRect.Right() > nTabLabelsRight) + nHeaderHeight = nTabLabelsBottom; + } + if (!aTabRect.IsEmpty() && aTabRect.Right() > nTabLabelsRight) nTabLabelsRight = aTabRect.Right(); } @@ -2137,6 +2135,12 @@ Size TabControl::calculateRequisition() const return aOptimalSize; } +Size TabControl::calculateRequisition() const +{ + sal_uInt16 nHeaderHeight; + return ImplCalculateRequisition(nHeaderHeight); +} + Size TabControl::GetOptimalSize() const { return calculateRequisition(); @@ -2201,10 +2205,7 @@ void NotebookbarTabControlBase::SetContext( vcl::EnumContext::Context eContext ) if (pPage) { - if (pPage->HasContext(eContext) || pPage->HasContext(vcl::EnumContext::Context::Any)) - EnablePage(nPageId); - else - EnablePage(nPageId, false); + SetPageVisible(nPageId, pPage->HasContext(eContext) || pPage->HasContext(vcl::EnumContext::Context::Any)); if (!bHandled && bLastContextWasSupported && pPage->HasContext(vcl::EnumContext::Context::Default)) @@ -2244,62 +2245,34 @@ void NotebookbarTabControlBase::SetIconClickHdl( Link<NotebookBar*, void> aHdl ) m_aIconClickHdl = aHdl; } -sal_uInt16 NotebookbarTabControlBase::GetPageId( const Point& rPos ) const +static bool lcl_isValidPage(const ImplTabItem& rItem, bool& bFound) { - for( size_t i = 0; i < mpTabCtrlData->maItemList.size(); ++i ) - { - if ( const_cast<NotebookbarTabControlBase*>(this)->ImplGetTabRect( static_cast<sal_uInt16>(i) ).IsInside( rPos ) ) - if ( mpTabCtrlData->maItemList[ i ].mbEnabled ) - return mpTabCtrlData->maItemList[ i ].mnId; - } - - return 0; -} - -void NotebookbarTabControlBase::SelectTabPage( sal_uInt16 nPageId ) -{ - TabControl::SelectTabPage( nPageId ); - Resize(); -} - -void NotebookbarTabControlBase::SetCurPageId( sal_uInt16 nPageId ) -{ - TabControl::SetCurPageId( nPageId ); - Resize(); - if ( nPageId == GetPageCount() ) - ImplActivateTabPage( true ); + if (rItem.m_bVisible && rItem.m_bEnabled) + bFound = true; + return bFound; } void NotebookbarTabControlBase::ImplActivateTabPage( bool bNext ) { - sal_uInt16 nCurPos = GetPagePos( GetCurPageId() ); + const sal_uInt16 nOldPos = GetPagePos(GetCurPageId()); + bool bFound = false; + sal_Int32 nCurPos = nOldPos; - if ( bNext && nCurPos + 1 < GetPageCount() ) + if (bNext) { - sal_uInt16 nOldPos = nCurPos; - nCurPos++; - - ImplTabItem* pItem = &mpTabCtrlData->maItemList[nCurPos]; - while ( !pItem->mbEnabled && nCurPos + 1 < GetPageCount()) - { - nCurPos++; - pItem = &mpTabCtrlData->maItemList[nCurPos]; - } - - if ( !pItem->mbEnabled ) - nCurPos = nOldPos; + for (nCurPos++; nCurPos < GetPageCount(); nCurPos++) + if (lcl_isValidPage(mpTabCtrlData->maItemList[nCurPos], bFound)) + break; } - else if ( !bNext && nCurPos ) + else { - nCurPos--; - ImplTabItem* pItem = &mpTabCtrlData->maItemList[nCurPos]; - while ( nCurPos && !pItem->mbEnabled ) - { - nCurPos--; - pItem = &mpTabCtrlData->maItemList[nCurPos]; - } + for (nCurPos--; nCurPos >= 0; nCurPos--) + if (lcl_isValidPage(mpTabCtrlData->maItemList[nCurPos], bFound)) + break; } + if (!bFound) + nCurPos = nOldPos; SelectTabPage( TabControl::GetPageId( nCurPos ) ); } @@ -2331,7 +2304,7 @@ bool NotebookbarTabControlBase::ImplPlaceTabs( long nWidth ) std::vector<sal_Int32> aWidths; for (auto & item : mpTabCtrlData->maItemList) { - if( item.mbEnabled ) + if (item.m_bVisible) { long aSize = ImplGetItemSize( &item, nMaxWidth ).getWidth(); if( !item.maText.isEmpty() && aSize < 100) @@ -2358,12 +2331,10 @@ bool NotebookbarTabControlBase::ImplPlaceTabs( long nWidth ) for (auto & item : mpTabCtrlData->maItemList) { - Size aSize = ImplGetItemSize( &item, nMaxWidth ); - - if ( !item.mbEnabled ) - { + if (!item.m_bVisible) continue; - } + + Size aSize = ImplGetItemSize( &item, nMaxWidth ); // set minimum tab size if( nFullWidth < nMaxWidth && !item.maText.isEmpty() && aSize.getWidth() < 100) @@ -2409,263 +2380,9 @@ bool NotebookbarTabControlBase::ImplPlaceTabs( long nWidth ) return true; } -void NotebookbarTabControlBase::ImplPaint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) -{ - HideFocus(); - - // reformat if needed - tools::Rectangle aRect = ImplGetTabRect(TAB_PAGERECT); - - // find current item - ImplTabItem* pCurItem = nullptr; - for (auto & item : mpTabCtrlData->maItemList) - { - if (item.mnId == mnCurPageId) - { - pCurItem = &item; - break; - } - } - - // Draw the TabPage border - const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings(); - tools::Rectangle aCurRect; - aRect.AdjustLeft( -(TAB_OFFSET) ); - aRect.AdjustTop( -(TAB_OFFSET) ); - aRect.AdjustRight(TAB_OFFSET ); - aRect.AdjustBottom(TAB_OFFSET ); - - // if we have an invisible tabpage or no tabpage at all the tabpage rect should be - // increased to avoid round corners that might be drawn by a theme - // in this case we're only interested in the top border of the tabpage because the tabitems are used - // standalone (eg impress) - bool bNoTabPage = false; - TabPage* pCurPage = pCurItem ? pCurItem->mpTabPage.get() : nullptr; - if (!pCurPage || !pCurPage->IsVisible()) - { - bNoTabPage = true; - aRect.AdjustLeft( -10 ); - aRect.AdjustRight(10 ); - } - - if (rRenderContext.IsNativeControlSupported(ControlType::TabPane, ControlPart::Entire)) - { - const ImplControlValue aControlValue; - - ControlState nState = ControlState::ENABLED; - if (!IsEnabled()) - nState &= ~ControlState::ENABLED; - if (HasFocus()) - nState |= ControlState::FOCUSED; - - vcl::Region aClipRgn(rRenderContext.GetActiveClipRegion()); - aClipRgn.Intersect(aRect); - if (!rRect.IsEmpty()) - aClipRgn.Intersect(rRect); - - if (!aClipRgn.IsEmpty()) - { - rRenderContext.DrawNativeControl(ControlType::TabPane, ControlPart::Entire, - aRect, nState, aControlValue, OUString()); - } - - if (rRenderContext.IsNativeControlSupported(ControlType::TabHeader, ControlPart::Entire)) - { - tools::Rectangle aHeaderRect(aRect.Left(), 0, aRect.Right(), aRect.Top()); - - aClipRgn = rRenderContext.GetActiveClipRegion(); - aClipRgn.Intersect(aHeaderRect); - if (!rRect.IsEmpty()) - aClipRgn.Intersect(rRect); - - if (!aClipRgn.IsEmpty()) - { - rRenderContext.DrawNativeControl(ControlType::TabHeader, ControlPart::Entire, - aHeaderRect, nState, aControlValue, OUString()); - } - } - } - else - { - long nTopOff = 1; - if (!(rStyleSettings.GetOptions() & StyleSettingsOptions::Mono)) - rRenderContext.SetLineColor(rStyleSettings.GetLightColor()); - else - rRenderContext.SetLineColor(COL_BLACK); - if (pCurItem && !pCurItem->maRect.IsEmpty()) - { - aCurRect = pCurItem->maRect; - rRenderContext.DrawLine(aRect.TopLeft(), Point(aCurRect.Left() - 2, aRect.Top())); - if (aCurRect.Right() + 1 < aRect.Right()) - { - rRenderContext.DrawLine(Point(aCurRect.Right(), aRect.Top()), aRect.TopRight()); - } - else - { - nTopOff = 0; - } - } - else - rRenderContext.DrawLine(aRect.TopLeft(), aRect.TopRight()); - - rRenderContext.DrawLine(aRect.TopLeft(), aRect.BottomLeft()); - - if (!(rStyleSettings.GetOptions() & StyleSettingsOptions::Mono)) - { - // if we have not tab page the bottom line of the tab page - // directly touches the tab items, so choose a color that fits seamlessly - if (bNoTabPage) - rRenderContext.SetLineColor(rStyleSettings.GetDialogColor()); - else - rRenderContext.SetLineColor(rStyleSettings.GetShadowColor()); - rRenderContext.DrawLine(Point(1, aRect.Bottom() - 1), Point(aRect.Right() - 1, aRect.Bottom() - 1)); - rRenderContext.DrawLine(Point(aRect.Right() - 1, aRect.Top() + nTopOff), Point(aRect.Right() - 1, aRect.Bottom() - 1)); - if (bNoTabPage) - rRenderContext.SetLineColor(rStyleSettings.GetDialogColor()); - else - rRenderContext.SetLineColor(rStyleSettings.GetDarkShadowColor()); - rRenderContext.DrawLine(Point(0, aRect.Bottom()), Point(aRect.Right(), aRect.Bottom())); - rRenderContext.DrawLine(Point(aRect.Right(), aRect.Top() + nTopOff), Point(aRect.Right(), aRect.Bottom())); - } - else - { - rRenderContext.DrawLine(aRect.TopRight(), aRect.BottomRight()); - rRenderContext.DrawLine(aRect.BottomLeft(), aRect.BottomRight()); - } - } - - if (!mpTabCtrlData->maItemList.empty() && mpTabCtrlData->mpListBox == nullptr) - { - // Some native toolkits (GTK+) draw tabs right-to-left, with an - // overlap between adjacent tabs - bool bDrawTabsRTL = rRenderContext.IsNativeControlSupported(ControlType::TabItem, ControlPart::TabsDrawRtl); - ImplTabItem* pFirstTab = nullptr; - ImplTabItem* pLastTab = nullptr; - size_t idx; - - // Event though there is a tab overlap with GTK+, the first tab is not - // overlapped on the left side. Other toolkits ignore this option. - if (bDrawTabsRTL) - { - pFirstTab = mpTabCtrlData->maItemList.data(); - pLastTab = pFirstTab + mpTabCtrlData->maItemList.size() - 1; - idx = mpTabCtrlData->maItemList.size() - 1; - } - else - { - pLastTab = mpTabCtrlData->maItemList.data(); - pFirstTab = pLastTab + mpTabCtrlData->maItemList.size() - 1; - idx = 0; - } - - while (idx < mpTabCtrlData->maItemList.size()) - { - ImplTabItem* pItem = &mpTabCtrlData->maItemList[idx]; - - if ((pItem != pCurItem) && (pItem->mbEnabled)) - { - vcl::Region aClipRgn(rRenderContext.GetActiveClipRegion()); - aClipRgn.Intersect(pItem->maRect); - if (!rRect.IsEmpty()) - aClipRgn.Intersect(rRect); - if (!aClipRgn.IsEmpty()) - { - ImplDrawItem(rRenderContext, pItem, aCurRect, - pItem == pFirstTab, pItem == pLastTab); - } - } - - if (bDrawTabsRTL) - idx--; - else - idx++; - } - - if (pCurItem) - { - vcl::Region aClipRgn(rRenderContext.GetActiveClipRegion()); - aClipRgn.Intersect(pCurItem->maRect); - if (!rRect.IsEmpty()) - aClipRgn.Intersect(rRect); - if (!aClipRgn.IsEmpty()) - { - ImplDrawItem(rRenderContext, pCurItem, aCurRect, - pCurItem == pFirstTab, pCurItem == pLastTab); - } - } - } - - if (HasFocus()) - ImplShowFocus(); - - mbSmallInvalidate = true; - - Control::Paint(rRenderContext, rRect); -} - Size NotebookbarTabControlBase::calculateRequisition() const { - Size aOptimalPageSize(0, 0); - - sal_uInt16 nOrigPageId = GetCurPageId(); - for (auto const& item : mpTabCtrlData->maItemList) - { - const TabPage *pPage = item.mpTabPage; - //it's a real nuisance if the page is not inserted yet :-( - //We need to force all tabs to exist to get overall optimal size for dialog - if (!pPage) - { - NotebookbarTabControlBase *pThis = const_cast<NotebookbarTabControlBase*>(this); - pThis->SetCurPageId(item.mnId); - pThis->ActivatePage(); - pPage = item.mpTabPage; - } - - if (!pPage) - continue; - - Size aPageSize(VclContainer::getLayoutRequisition(*pPage)); - - if (aPageSize.Width() > aOptimalPageSize.Width()) - aOptimalPageSize.setWidth( aPageSize.Width() ); - if (aPageSize.Height() > aOptimalPageSize.Height()) - aOptimalPageSize.setHeight( aPageSize.Height() ); - } - - //fdo#61940 If we were forced to activate pages in order to on-demand - //create them to get their optimal size, then switch back to the original - //page and re-activate it - if (nOrigPageId != GetCurPageId()) - { - NotebookbarTabControlBase *pThis = const_cast<NotebookbarTabControlBase*>(this); - pThis->SetCurPageId(nOrigPageId); - pThis->ActivatePage(); - } - - long nTabLabelsBottom = 0, nTabLabelsRight = 0; - for (sal_uInt16 nPos(0), sizeList(static_cast <sal_uInt16> (mpTabCtrlData->maItemList.size())); - nPos < sizeList; ++nPos) - { - NotebookbarTabControlBase* pThis = const_cast<NotebookbarTabControlBase*>(this); - - tools::Rectangle aTabRect = pThis->ImplGetTabRect(nPos, aOptimalPageSize.Width(), LONG_MAX); - if (aTabRect.Bottom() > nTabLabelsBottom) - { - nTabLabelsBottom = aTabRect.Bottom(); - m_nHeaderHeight = aTabRect.Bottom(); - } - if (aTabRect.Right() > nTabLabelsRight) - nTabLabelsRight = aTabRect.Right(); - } - - Size aOptimalSize(aOptimalPageSize); - aOptimalSize.AdjustHeight(nTabLabelsBottom ); - aOptimalSize.setWidth( std::max(nTabLabelsRight, aOptimalSize.Width()) ); - - aOptimalSize.AdjustWidth(TAB_OFFSET * 2 ); - aOptimalSize.AdjustHeight(TAB_OFFSET * 2 ); - - return aOptimalSize; + return TabControl::ImplCalculateRequisition(m_nHeaderHeight); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |