diff options
-rw-r--r-- | include/vcl/salnativewidgets.hxx | 26 | ||||
-rw-r--r-- | vcl/qt5/Qt5Graphics_Controls.cxx | 81 | ||||
-rw-r--r-- | vcl/source/control/tabctrl.cxx | 31 | ||||
-rw-r--r-- | vcl/source/outdev/nativecontrols.cxx | 19 |
4 files changed, 145 insertions, 12 deletions
diff --git a/include/vcl/salnativewidgets.hxx b/include/vcl/salnativewidgets.hxx index 03d9a0eee00e..2a67ceb47b24 100644 --- a/include/vcl/salnativewidgets.hxx +++ b/include/vcl/salnativewidgets.hxx @@ -181,6 +181,9 @@ enum class ControlPart // hardcoded 2 pixel overlap between adjacent tabs TabsDrawRtl = 3000, +// Qt doesn't have a separate header to draw + TabPaneWithHeader = 3001, + // For themes that do not want to have the focus // rectangle part drawn by VCL but take care of the // whole inner control part by themselves @@ -340,6 +343,29 @@ class VCL_DLLPUBLIC SliderValue : public ImplControlValue SliderValue & operator =(SliderValue &&) = delete; // due to ImplControlValue }; +class VCL_DLLPUBLIC TabPaneValue : public ImplControlValue +{ +public: + tools::Rectangle m_aTabHeaderRect; + tools::Rectangle m_aSelectedTabRect; + // increased tab size, so it'll overlab the frame rect when draing + // static value, as there is currently no sane way to return additional data + static int m_nOverlap; + + TabPaneValue(const tools::Rectangle &rTabHeaderRect, const tools::Rectangle &rSelectedTabRect) + : ImplControlValue(ControlType::TabPane, 0) + , m_aTabHeaderRect(rTabHeaderRect) + , m_aSelectedTabRect(rSelectedTabRect) + { + } + TabPaneValue* clone() const override; + + TabPaneValue(TabPaneValue const &) = default; + TabPaneValue(TabPaneValue &&) = default; + TabPaneValue & operator =(TabPaneValue const &) = delete; + TabPaneValue & operator =(TabPaneValue &&) = delete; +}; + /* TabitemValue: * * Value container for tabitems. diff --git a/vcl/qt5/Qt5Graphics_Controls.cxx b/vcl/qt5/Qt5Graphics_Controls.cxx index 6cefef623a73..73a47e5e5ffa 100644 --- a/vcl/qt5/Qt5Graphics_Controls.cxx +++ b/vcl/qt5/Qt5Graphics_Controls.cxx @@ -105,6 +105,10 @@ bool Qt5Graphics_Controls::isNativeControlSupported(ControlType type, ControlPar case ControlType::Slider: return (part == ControlPart::TrackHorzArea || part == ControlPart::TrackVertArea); + case ControlType::TabItem: + case ControlType::TabPane: + return ((part == ControlPart::Entire) || part == ControlPart::TabPaneWithHeader); + default: break; } @@ -112,7 +116,6 @@ bool Qt5Graphics_Controls::isNativeControlSupported(ControlType type, ControlPar return false; } -/// helper drawing methods namespace { void draw(QStyle::ControlElement element, QStyleOption* option, QImage* image, @@ -163,6 +166,27 @@ void lcl_drawFrame(QStyle::PrimitiveElement element, QImage* image, QStyle::Stat painter.setClipRegion(QRegion(aRect).subtracted(aRect.adjusted(fw, fw, -fw, -fw))); QApplication::style()->drawPrimitive(element, &option, &painter); } + +void lcl_fillQStyleOptionTab(const ImplControlValue& value, QStyleOptionTab& sot) +{ + const TabitemValue& rValue = static_cast<const TabitemValue&>(value); + if (rValue.isFirst()) + sot.position = rValue.isLast() ? QStyleOptionTab::OnlyOneTab : QStyleOptionTab::Beginning; + else if (rValue.isLast()) + sot.position = rValue.isFirst() ? QStyleOptionTab::OnlyOneTab : QStyleOptionTab::End; + else + sot.position = QStyleOptionTab::Middle; +} + +void lcl_fullQStyleOptionTabWidgetFrame(QStyleOptionTabWidgetFrame& option) +{ + option.state = QStyle::State_Enabled; + option.rightCornerWidgetSize = QSize(0, 0); + option.leftCornerWidgetSize = QSize(0, 0); + option.lineWidth = QApplication::style()->pixelMetric(QStyle::PM_DefaultFrameWidth); + option.midLineWidth = 0; + option.shape = QTabBar::RoundedNorth; +} } bool Qt5Graphics_Controls::drawNativeControl(ControlType type, ControlPart part, @@ -609,6 +633,34 @@ bool Qt5Graphics_Controls::drawNativeControl(ControlType type, ControlPart part, draw(QStyle::CE_ProgressBar, &option, m_image.get(), vclStateValue2StateFlag(nControlState, value)); } + else if (type == ControlType::TabItem && part == ControlPart::Entire) + { + QStyleOptionTab sot; + lcl_fillQStyleOptionTab(value, sot); + draw(QStyle::CE_TabBarTabShape, &sot, m_image.get(), + vclStateValue2StateFlag(nControlState, value)); + } + else if (type == ControlType::TabPane && part == ControlPart::Entire) + { + const TabPaneValue& rValue = static_cast<const TabPaneValue&>(value); + + // get the overlap size for the tabs, so they will overlap the frame + QStyleOptionTab tabOverlap; + tabOverlap.shape = QTabBar::RoundedNorth; + TabPaneValue::m_nOverlap + = QApplication::style()->pixelMetric(QStyle::PM_TabBarBaseOverlap, &tabOverlap); + + QStyleOptionTabWidgetFrame option; + lcl_fullQStyleOptionTabWidgetFrame(option); + option.tabBarRect = toQRect(rValue.m_aTabHeaderRect); + option.selectedTabRect + = rValue.m_aSelectedTabRect.IsEmpty() ? QRect() : toQRect(rValue.m_aSelectedTabRect); + option.tabBarSize = toQSize(rValue.m_aTabHeaderRect.GetSize()); + option.rect = m_image->rect(); + QRect aRect = QApplication::style()->subElementRect(QStyle::SE_TabWidgetTabPane, &option); + draw(QStyle::PE_FrameTabWidget, &option, m_image.get(), + vclStateValue2StateFlag(nControlState, value), aRect); + } else { returnVal = false; @@ -818,7 +870,7 @@ bool Qt5Graphics_Controls::getNativeControlRegion(ControlType type, ControlPart auto nStyle = static_cast<DrawFrameFlags>(val.getNumericVal() & 0xFFF0); if (nStyle & DrawFrameFlags::NoDraw) { - int nFrameWidth + const int nFrameWidth = QApplication::style()->pixelMetric(QStyle::PM_DefaultFrameWidth); contentRect.adjust(nFrameWidth, nFrameWidth, -nFrameWidth, -nFrameWidth); } @@ -912,6 +964,31 @@ bool Qt5Graphics_Controls::getNativeControlRegion(ControlType type, ControlPart } break; } + case ControlType::TabItem: + { + QStyleOptionTab sot; + lcl_fillQStyleOptionTab(val, sot); + QSize aMinSize = QApplication::style()->sizeFromContents(QStyle::CT_TabBarTab, &sot, + contentRect.size()); + contentRect.setSize(aMinSize); + boundingRect = contentRect; + retVal = true; + break; + } + case ControlType::TabPane: + { + const TabPaneValue& rValue = static_cast<const TabPaneValue&>(val); + QStyleOptionTabWidgetFrame sotwf; + lcl_fullQStyleOptionTabWidgetFrame(sotwf); + QSize aMinSize = QApplication::style()->sizeFromContents( + QStyle::CT_TabWidget, &sotwf, + QSize(std::max(rValue.m_aTabHeaderRect.GetWidth(), controlRegion.GetWidth()), + rValue.m_aTabHeaderRect.GetHeight() + controlRegion.GetHeight())); + contentRect.setSize(aMinSize); + boundingRect = contentRect; + retVal = true; + break; + } default: break; } diff --git a/vcl/source/control/tabctrl.cxx b/vcl/source/control/tabctrl.cxx index d23db1eaf9cf..9b269e8ef66c 100644 --- a/vcl/source/control/tabctrl.cxx +++ b/vcl/source/control/tabctrl.cxx @@ -865,6 +865,7 @@ void TabControl::ImplDrawItem(vcl::RenderContext& rRenderContext, ImplTabItem co tiValue.mnAlignment |= TabitemFlags::LastInGroup; tools::Rectangle aCtrlRegion( pItem->maRect ); + aCtrlRegion.AdjustBottom(TabPaneValue::m_nOverlap); bNativeOK = rRenderContext.DrawNativeControl(ControlType::TabItem, ControlPart::Entire, aCtrlRegion, nState, tiValue, OUString() ); } @@ -1098,7 +1099,22 @@ void TabControl::Paint( vcl::RenderContext& rRenderContext, const tools::Rectang if (rRenderContext.IsNativeControlSupported(ControlType::TabPane, ControlPart::Entire)) { - const ImplControlValue aControlValue; + const bool bPaneWithHeader = rRenderContext.IsNativeControlSupported(ControlType::TabPane, ControlPart::TabPaneWithHeader); + tools::Rectangle aHeaderRect(aRect.Left(), 0, aRect.Right(), aRect.Top()); + if (bPaneWithHeader) + { + aRect.SetTop(0); + if (mpTabCtrlData->maItemList.size()) + { + long nRight = 0; + for (auto &item : mpTabCtrlData->maItemList) + if (item.m_bVisible) + nRight = item.maRect.Right(); + assert(nRight); + aHeaderRect.SetRight(nRight); + } + } + const TabPaneValue aTabPaneValue(aHeaderRect, pCurItem ? pCurItem->maRect : tools::Rectangle()); ControlState nState = ControlState::ENABLED; if (!IsEnabled()) @@ -1108,15 +1124,12 @@ void TabControl::Paint( vcl::RenderContext& rRenderContext, const tools::Rectang if (lcl_canPaint(rRenderContext, rRect, aRect)) rRenderContext.DrawNativeControl(ControlType::TabPane, ControlPart::Entire, - aRect, nState, aControlValue, OUString()); + aRect, nState, aTabPaneValue, OUString()); - if (rRenderContext.IsNativeControlSupported(ControlType::TabHeader, ControlPart::Entire)) - { - tools::Rectangle aHeaderRect(aRect.Left(), 0, aRect.Right(), aRect.Top()); - if (lcl_canPaint(rRenderContext, rRect, aHeaderRect)) - rRenderContext.DrawNativeControl(ControlType::TabHeader, ControlPart::Entire, - aHeaderRect, nState, aControlValue, OUString()); - } + if (!bPaneWithHeader && rRenderContext.IsNativeControlSupported(ControlType::TabHeader, ControlPart::Entire) + && lcl_canPaint(rRenderContext, rRect, aHeaderRect)) + rRenderContext.DrawNativeControl(ControlType::TabHeader, ControlPart::Entire, + aHeaderRect, nState, aTabPaneValue, OUString()); } else { diff --git a/vcl/source/outdev/nativecontrols.cxx b/vcl/source/outdev/nativecontrols.cxx index ef2295808a6d..00218344ff7d 100644 --- a/vcl/source/outdev/nativecontrols.cxx +++ b/vcl/source/outdev/nativecontrols.cxx @@ -95,6 +95,14 @@ SliderValue* SliderValue::clone() const return new SliderValue( *this ); } +int TabPaneValue::m_nOverlap = 0; + +TabPaneValue* TabPaneValue::clone() const +{ + assert(typeid(const TabPaneValue) == typeid(*this)); + return new TabPaneValue(*this); +} + TabitemValue::~TabitemValue() { } @@ -229,6 +237,15 @@ static std::shared_ptr< ImplControlValue > TransformControlValue( const ImplCont pNew->maGripRect = rDev.ImplLogicToDevicePixel( pTVal->maGripRect ); } break; + case ControlType::TabPane: + { + const TabPaneValue* pTIVal = static_cast<const TabPaneValue*>(&rVal); + TabPaneValue* pNew = new TabPaneValue(*pTIVal); + pNew->m_aTabHeaderRect = rDev.ImplLogicToDevicePixel(pTIVal->m_aTabHeaderRect); + pNew->m_aSelectedTabRect = rDev.ImplLogicToDevicePixel(pTIVal->m_aSelectedTabRect); + aResult.reset(pNew); + } + break; case ControlType::TabItem: { const TabitemValue* pTIVal = static_cast<const TabitemValue*>(&rVal); @@ -263,7 +280,7 @@ static std::shared_ptr< ImplControlValue > TransformControlValue( const ImplCont } break; default: - OSL_FAIL( "unknown ImplControlValue type !" ); + std::abort(); break; } return aResult; |