summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/vcl/salnativewidgets.hxx26
-rw-r--r--vcl/qt5/Qt5Graphics_Controls.cxx81
-rw-r--r--vcl/source/control/tabctrl.cxx31
-rw-r--r--vcl/source/outdev/nativecontrols.cxx19
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;