299void QWindows11Style::drawComplexControl(ComplexControl control,
const QStyleOptionComplex *option,
300 QPainter *painter,
const QWidget *widget)
const
304 const auto drawTitleBarButton = [&](ComplexControl control, SubControl sc,
const QString &str) {
306 const QRect buttonRect = proxy()->subControlRect(control, option, sc, widget);
307 if (buttonRect.isValid()) {
308 const bool hover = option->activeSubControls == sc && isHover(option);
311 painter->setPen(option->palette.color(QPalette::WindowText));
312 painter->drawText(buttonRect, Qt::AlignCenter, str);
315 const auto drawTitleBarCloseButton = [&](ComplexControl control, SubControl sc,
const QString &str) {
317 const QRect buttonRect = proxy()->subControlRect(control, option, sc, widget);
318 if (buttonRect.isValid()) {
319 const auto state = (option->activeSubControls == sc) ? calcControlState(option)
320 : ControlState::Normal;
324 painter->fillRect(buttonRect, shellCaptionCloseFillColorPrimary);
325 pen = shellCaptionCloseTextFillColorPrimary;
328 painter->fillRect(buttonRect, shellCaptionCloseFillColorSecondary);
329 pen = shellCaptionCloseTextFillColorSecondary;
331 case ControlState::Disabled:
332 case ControlState::Normal:
333 pen = option->palette.color(QPalette::WindowText);
337 painter->drawText(buttonRect, Qt::AlignCenter, str);
342 State state = option->state;
343 SubControls sub = option->subControls;
344 State flags = option->state;
345 if (widget && widget->testAttribute(Qt::WA_UnderMouse) && widget->isActiveWindow())
346 flags |= State_MouseOver;
349 painter->setRenderHint(QPainter::Antialiasing);
350 if (d->transitionsEnabled() && option->styleObject) {
351 if (control == CC_Slider) {
352 if (
const auto *slider = qstyleoption_cast<
const QStyleOptionSlider *>(option)) {
353 QObject *styleObject = option->styleObject;
355 QRectF thumbRect = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
356 const qreal outerRadius = qMin(8.0, (slider->orientation == Qt::Horizontal ? thumbRect.height() / 2.0 : thumbRect.width() / 2.0) - 1);
357 bool isInsideHandle = option->activeSubControls == SC_SliderHandle;
359 bool oldIsInsideHandle = styleObject->property(
"_q_insidehandle").toBool();
360 State oldState = State(styleObject->property(
"_q_stylestate").toInt());
361 SubControls oldActiveControls = SubControls(styleObject->property(
"_q_stylecontrols").toInt());
363 QRectF oldRect = styleObject->property(
"_q_stylerect").toRect();
364 styleObject->setProperty(
"_q_insidehandle", isInsideHandle);
365 styleObject->setProperty(
"_q_stylestate",
int(state));
366 styleObject->setProperty(
"_q_stylecontrols",
int(option->activeSubControls));
367 styleObject->setProperty(
"_q_stylerect", option->rect);
368 if (option->styleObject->property(
"_q_end_radius").isNull())
369 option->styleObject->setProperty(
"_q_end_radius", outerRadius * 0.43);
371 bool doTransition = (((state & State_Sunken) != (oldState & State_Sunken)
372 || (oldIsInsideHandle != isInsideHandle)
373 || (oldActiveControls != option->activeSubControls))
374 && state & State_Enabled);
376 if (oldRect != option->rect) {
377 doTransition =
false;
378 d->stopAnimation(styleObject);
379 styleObject->setProperty(
"_q_inner_radius", outerRadius * 0.43);
383 QNumberStyleAnimation *t =
new QNumberStyleAnimation(styleObject);
384 t->setStartValue(styleObject->property(
"_q_inner_radius").toFloat());
385 t->setEndValue(outerRadius * sliderInnerRadius(state, isInsideHandle));
386 styleObject->setProperty(
"_q_end_radius", t->endValue());
388 t->setStartTime(d->animationTime());
390 d->startAnimation(t);
397#if QT_CONFIG(spinbox)
399 if (
const QStyleOptionSpinBox *sb = qstyleoption_cast<
const QStyleOptionSpinBox *>(option)) {
400 QCachedPainter cp(painter, QLatin1StringView(
"win11_spinbox") % HexString<uint8_t>(colorSchemeIndex),
401 sb, sb->rect.size());
402 if (cp.needsPainting()) {
403 const auto frameRect = QRectF(option->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5));
404 drawRoundedRect(cp.painter(), frameRect, Qt::NoPen, option->palette.brush(QPalette::Base));
406 if (sb->frame && (sub & SC_SpinBoxFrame))
407 drawLineEditFrame(cp.painter(), frameRect, option);
409 const bool isMouseOver = state & State_MouseOver;
410 const bool hasFocus = state & State_HasFocus;
411 if (isMouseOver && !hasFocus && !highContrastTheme)
412 drawRoundedRect(cp.painter(), frameRect, Qt::NoPen, winUI3Color(subtleHighlightColor));
414 const auto drawUpDown = [&](QStyle::SubControl sc) {
415 const bool isUp = sc == SC_SpinBoxUp;
416 const QRect rect = proxy()->subControlRect(CC_SpinBox, option, sc, widget);
417 if (sb->activeSubControls & sc)
418 drawRoundedRect(cp.painter(), rect.adjusted(1, 1, -1, -2), Qt::NoPen,
419 winUI3Color(subtleHighlightColor));
421 cp->setFont(d->assetFont);
422 cp->setPen(sb->palette.buttonText().color());
423 cp->setBrush(Qt::NoBrush);
424 cp->drawText(rect, Qt::AlignCenter, isUp ? ChevronUp : ChevronDown);
426 if (sub & SC_SpinBoxUp) drawUpDown(SC_SpinBoxUp);
427 if (sub & SC_SpinBoxDown) drawUpDown(SC_SpinBoxDown);
428 if (state & State_KeyboardFocusChange && state & State_HasFocus) {
429 QStyleOptionFocusRect fropt;
430 fropt.QStyleOption::operator=(*option);
431 proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, cp.painter(), widget);
439 if (
const auto *slider = qstyleoption_cast<
const QStyleOptionSlider *>(option)) {
440 const auto &slrect = slider->rect;
441 const bool isHorizontal = slider->orientation == Qt::Horizontal;
442 const QRectF handleRect(proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget));
443 const QPointF handleCenter(handleRect.center());
445 if (sub & SC_SliderGroove) {
446 QRectF rect = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
451 rect = QRectF(rect.left() + 2, rect.center().y() - 2, rect.width() - 2, 4);
452 leftRect = QRectF(rect.left(), rect.top(), handleCenter.x() - rect.left(),
454 rightRect = QRectF(handleCenter.x(), rect.top(),
455 rect.width() - handleCenter.x(),
458 rect = QRect(rect.center().x() - 2, rect.top() + 2, 4, rect.height() - 2);
459 leftRect = QRectF(rect.left(), rect.top(), rect.width(),
460 handleCenter.y() - rect.top());
461 rightRect = QRectF(rect.left(), handleCenter.y(), rect.width(),
462 rect.height() - handleCenter.y());
464 if (slider->upsideDown)
465 qSwap(leftRect, rightRect);
467 painter->setPen(Qt::NoPen);
468 painter->setBrush(calculateAccentColor(option));
469 painter->drawRoundedRect(leftRect,1,1);
470 painter->setBrush(WINUI3Colors[colorSchemeIndex][controlStrongFill]);
471 painter->drawRoundedRect(rightRect,1,1);
473 if (sub & SC_SliderTickmarks) {
474 int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget);
475 int ticks = slider->tickPosition;
476 int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget);
477 int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
478 int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget);
479 int interval = slider->tickInterval;
481 interval = slider->singleStep;
482 if (QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, interval,
484 - QStyle::sliderPositionFromValue(slider->minimum, slider->maximum,
486 interval = slider->pageStep;
491 painter->setPen(slider->palette.text().color());
492 QVarLengthArray<QLineF, 32> lines;
493 int v = slider->minimum;
494 while (v <= slider->maximum + 1) {
495 if (v == slider->maximum + 1 && interval == 1)
497 const int v_ = qMin(v, slider->maximum);
498 int tickLength = (v_ == slider->minimum || v_ >= slider->maximum) ? 4 : 3;
499 int pos = QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, v_,
500 available, slider->upsideDown);
503 if (ticks & QSlider::TicksAbove) {
504 lines.append(QLineF(pos, tickOffset - 0.5,
505 pos, tickOffset - tickLength - 0.5));
508 if (ticks & QSlider::TicksBelow) {
509 lines.append(QLineF(pos, tickOffset + thickness + 0.5,
510 pos, tickOffset + thickness + tickLength + 0.5));
513 if (ticks & QSlider::TicksAbove) {
514 lines.append(QLineF(tickOffset - 0.5, pos,
515 tickOffset - tickLength - 0.5, pos));
518 if (ticks & QSlider::TicksBelow) {
519 lines.append(QLineF(tickOffset + thickness + 0.5, pos,
520 tickOffset + thickness + tickLength + 0.5, pos));
524 int nextInterval = v + interval;
525 if (nextInterval < v)
529 if (!lines.isEmpty()) {
531 painter->translate(slrect.topLeft());
532 painter->drawLines(lines.constData(), lines.size());
536 if (sub & SC_SliderHandle) {
537 const qreal outerRadius = qMin(8.0, (isHorizontal ? handleRect.height() / 2.0 : handleRect.width() / 2.0) - 1);
538 float innerRadius = outerRadius * 0.43;
540 if (option->styleObject) {
541 const QNumberStyleAnimation* animation = qobject_cast<QNumberStyleAnimation *>(d->animation(option->styleObject));
542 if (animation !=
nullptr) {
543 innerRadius = animation->currentValue();
544 option->styleObject->setProperty(
"_q_inner_radius", innerRadius);
546 bool isInsideHandle = option->activeSubControls == SC_SliderHandle;
547 innerRadius = outerRadius * sliderInnerRadius(state, isInsideHandle);
551 painter->setPen(Qt::NoPen);
552 painter->setBrush(winUI3Color(controlFillSolid));
553 painter->drawEllipse(handleCenter, outerRadius, outerRadius);
554 painter->setBrush(calculateAccentColor(option));
555 painter->drawEllipse(handleCenter, innerRadius, innerRadius);
557 painter->setPen(winUI3Color(controlStrokeSecondary));
558 painter->setBrush(Qt::NoBrush);
559 painter->drawEllipse(handleCenter, outerRadius + 0.5, outerRadius + 0.5);
561 if (slider->state & State_HasFocus) {
562 QStyleOptionFocusRect fropt;
563 fropt.QStyleOption::operator=(*slider);
564 fropt.rect = subElementRect(SE_SliderFocusRect, slider, widget);
565 proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
570#if QT_CONFIG(combobox)
572 if (
const QStyleOptionComboBox *combobox = qstyleoption_cast<
const QStyleOptionComboBox *>(option)) {
573 const auto frameRect = QRectF(option->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5));
574 drawRoundedRect(painter, frameRect, Qt::NoPen, option->palette.brush(QPalette::Base));
577 drawLineEditFrame(painter, frameRect, combobox, combobox->editable);
579 const bool isMouseOver = state & State_MouseOver;
580 const bool hasFocus = state & State_HasFocus;
581 if (isMouseOver && !hasFocus && !highContrastTheme)
582 drawRoundedRect(painter, frameRect, Qt::NoPen, winUI3Color(subtleHighlightColor));
584 if (sub & SC_ComboBoxArrow) {
585 QRectF rect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget).adjusted(4, 0, -4, 1);
586 painter->setFont(d->assetFont);
587 painter->setPen(combobox->palette.text().color());
588 painter->drawText(rect, Qt::AlignCenter, ChevronDownMed);
590 if (state & State_HasFocus) {
591 drawPrimitive(PE_FrameFocusRect, option, painter, widget);
593 if (state & State_KeyboardFocusChange && state & State_HasFocus) {
594 QStyleOptionFocusRect fropt;
595 fropt.QStyleOption::operator=(*option);
596 proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
602 if (
const QStyleOptionSlider *scrollbar = qstyleoption_cast<
const QStyleOptionSlider *>(option)) {
603 QCachedPainter cp(painter, QLatin1StringView(
"win11_scrollbar")
604 % HexString<uint8_t>(colorSchemeIndex)
605 % HexString<
int>(scrollbar->minimum)
606 % HexString<
int>(scrollbar->maximum)
607 % HexString<
int>(scrollbar->sliderPosition),
608 scrollbar, scrollbar->rect.size());
609 if (cp.needsPainting()) {
610 const bool vertical = scrollbar->orientation == Qt::Vertical;
611 const bool horizontal = scrollbar->orientation == Qt::Horizontal;
612 const bool isMouseOver = state & State_MouseOver;
613 const bool isRtl = option->direction == Qt::RightToLeft;
616 QRectF rect = scrollbar->rect;
617 const QPointF center = rect.center();
618 if (vertical && rect.width() > 24) {
619 rect.marginsRemoved(QMargins(0, 2, 2, 2));
620 rect.setWidth(rect.width() / 2);
621 }
else if (horizontal && rect.height() > 24) {
622 rect.marginsRemoved(QMargins(2, 0, 2, 2));
623 rect.setHeight(rect.height() / 2);
625 rect.moveCenter(center);
626 cp->setBrush(scrollbar->palette.base());
627 cp->setPen(Qt::NoPen);
628 cp->drawRoundedRect(rect, topLevelRoundingRadius, topLevelRoundingRadius);
629 rect = rect.marginsRemoved(QMarginsF(0.5, 0.5, 0.5, 0.5));
630 cp->setBrush(Qt::NoBrush);
631 cp->setPen(WINUI3Colors[colorSchemeIndex][frameColorLight]);
632 cp->drawRoundedRect(rect, topLevelRoundingRadius + 0.5, topLevelRoundingRadius + 0.5);
634 if (sub & SC_ScrollBarSlider) {
635 QRectF rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
636 const QPointF center = rect.center();
638 rect.setWidth(isMouseOver ? rect.width() / 2 : 1);
640 rect.setHeight(isMouseOver ? rect.height() / 2 : 1);
641 rect.moveCenter(center);
642 cp->setBrush(Qt::gray);
643 cp->setPen(Qt::NoPen);
644 cp->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
646 if (sub & SC_ScrollBarAddLine) {
648 const QRectF rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddLine, widget);
649 QFont f = QFont(d->assetFont);
652 cp->setPen(Qt::gray);
655 cp->drawText(rect, Qt::AlignCenter, str);
658 if (sub & SC_ScrollBarSubLine) {
660 const QRectF rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubLine, widget);
661 QFont f = QFont(d->assetFont);
664 cp->setPen(Qt::gray);
667 cp->drawText(rect, Qt::AlignCenter, str);
673 case CC_MdiControls:{
674 QFont buttonFont = QFont(d->assetFont);
675 buttonFont.setPointSize(8);
676 painter->setFont(buttonFont);
677 drawTitleBarCloseButton(CC_MdiControls, SC_MdiCloseButton,
ChromeClose);
678 drawTitleBarButton(CC_MdiControls, SC_MdiNormalButton,
ChromeRestore);
679 drawTitleBarButton(CC_MdiControls, SC_MdiMinButton,
ChromeMinimize);
683 if (
const auto* titlebar = qstyleoption_cast<
const QStyleOptionTitleBar*>(option)) {
684 painter->setPen(Qt::NoPen);
685 painter->setPen(WINUI3Colors[colorSchemeIndex][surfaceStroke]);
686 painter->setBrush(titlebar->palette.button());
687 painter->drawRect(titlebar->rect);
690 QRect textRect = proxy()->subControlRect(CC_TitleBar, titlebar, SC_TitleBarLabel, widget);
691 QColor textColor = titlebar->palette.color(titlebar->titleBarState & Qt::WindowActive ? QPalette::Active : QPalette::Disabled,QPalette::WindowText);
692 painter->setPen(textColor);
694 QString title = painter->fontMetrics().elidedText(titlebar->text, Qt::ElideRight, textRect.width() - 14);
695 painter->drawText(textRect.adjusted(1, 1, -1, -1), title, QTextOption(Qt::AlignHCenter | Qt::AlignVCenter));
697 QFont buttonFont = QFont(d->assetFont);
698 buttonFont.setPointSize(8);
699 painter->setFont(buttonFont);
700 auto shouldDrawButton = [titlebar](SubControl sc, Qt::WindowType flag) {
701 return (titlebar->subControls & sc) && (titlebar->titleBarFlags & flag);
705 if (shouldDrawButton(SC_TitleBarMinButton, Qt::WindowMinimizeButtonHint) &&
706 !(titlebar->titleBarState & Qt::WindowMinimized)) {
707 drawTitleBarButton(CC_TitleBar, SC_TitleBarMinButton,
ChromeMinimize);
711 if (shouldDrawButton(SC_TitleBarMaxButton, Qt::WindowMaximizeButtonHint) &&
712 !(titlebar->titleBarState & Qt::WindowMaximized)) {
713 drawTitleBarButton(CC_TitleBar, SC_TitleBarMaxButton,
ChromeMaximize);
717 if (shouldDrawButton(SC_TitleBarCloseButton, Qt::WindowSystemMenuHint))
718 drawTitleBarCloseButton(CC_TitleBar, SC_TitleBarCloseButton,
ChromeClose);
721 if ((titlebar->subControls & SC_TitleBarNormalButton) &&
722 (((titlebar->titleBarFlags & Qt::WindowMinimizeButtonHint) &&
723 (titlebar->titleBarState & Qt::WindowMinimized)) ||
724 ((titlebar->titleBarFlags & Qt::WindowMaximizeButtonHint) &&
725 (titlebar->titleBarState & Qt::WindowMaximized)))) {
726 drawTitleBarButton(CC_TitleBar, SC_TitleBarNormalButton,
ChromeRestore);
730 if (shouldDrawButton(SC_TitleBarContextHelpButton, Qt::WindowContextHelpButtonHint))
731 drawTitleBarButton(CC_TitleBar, SC_TitleBarContextHelpButton,
Help);
734 if (shouldDrawButton(SC_TitleBarShadeButton, Qt::WindowShadeButtonHint))
735 drawTitleBarButton(CC_TitleBar, SC_TitleBarShadeButton,
ChevronUpSmall);
738 if (shouldDrawButton(SC_TitleBarUnshadeButton, Qt::WindowShadeButtonHint))
739 drawTitleBarButton(CC_TitleBar, SC_TitleBarUnshadeButton,
ChevronDownSmall);
742 if (shouldDrawButton(SC_TitleBarSysMenu, Qt::WindowSystemMenuHint)) {
743 const QRect iconRect = proxy()->subControlRect(CC_TitleBar, titlebar, SC_TitleBarSysMenu, widget);
744 if (iconRect.isValid()) {
745 if (!titlebar->icon.isNull()) {
746 titlebar->icon.paint(painter, iconRect);
748 QStyleOption tool = *titlebar;
749 const auto extent = proxy()->pixelMetric(PM_SmallIconSize, &tool, widget);
750 const auto dpr = QStyleHelper::getDpr(widget);
751 const auto icon = proxy()->standardIcon(SP_TitleBarMenuButton, &tool, widget);
752 const auto pm = icon.pixmap(QSize(extent, extent), dpr);
753 proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pm);
760 QWindowsVistaStyle::drawComplexControl(control, option, painter, widget);
765void QWindows11Style::drawPrimitive(PrimitiveElement element,
const QStyleOption *option,
767 const QWidget *widget)
const {
770 int state = option->state;
772 painter->setRenderHint(QPainter::Antialiasing);
773 if (d->transitionsEnabled() && option->styleObject && (element == PE_IndicatorCheckBox || element == PE_IndicatorRadioButton)) {
774 QObject *styleObject = option->styleObject;
775 int oldState = styleObject->property(
"_q_stylestate").toInt();
776 styleObject->setProperty(
"_q_stylestate",
int(option->state));
777 styleObject->setProperty(
"_q_stylerect", option->rect);
778 bool doTransition = (((state & State_Sunken) != (oldState & State_Sunken)
779 || ((state & State_MouseOver) != (oldState & State_MouseOver))
780 || (state & State_On) != (oldState & State_On))
781 && state & State_Enabled);
783 if (element == PE_IndicatorRadioButton) {
784 QNumberStyleAnimation *t =
new QNumberStyleAnimation(styleObject);
785 t->setStartValue(styleObject->property(
"_q_inner_radius").toFloat());
786 t->setEndValue(radioButtonInnerRadius(state));
787 styleObject->setProperty(
"_q_end_radius", t->endValue());
788 t->setStartTime(d->animationTime());
790 d->startAnimation(t);
792 else if (element == PE_IndicatorCheckBox) {
793 if ((oldState & State_Off && state & State_On) || (oldState & State_NoChange && state & State_On)) {
794 QNumberStyleAnimation *t =
new QNumberStyleAnimation(styleObject);
795 t->setStartValue(0.0f);
796 t->setEndValue(1.0f);
797 t->setStartTime(d->animationTime());
799 d->startAnimation(t);
806 case PE_FrameFocusRect: {
807 if (
const QStyleOptionFocusRect *fropt = qstyleoption_cast<
const QStyleOptionFocusRect *>(option)) {
808 if (!(fropt->state & State_KeyboardFocusChange))
810 QRectF focusRect = option->rect;
811 focusRect = focusRect.marginsRemoved(QMarginsF(1.5,1.5,1.5,1.5));
812 painter->setPen(winUI3Color(focusFrameInnerStroke));
813 painter->drawRoundedRect(focusRect,4,4);
815 focusRect = focusRect.marginsAdded(QMarginsF(1.0,1.0,1.0,1.0));
816 painter->setPen(QPen(winUI3Color(focusFrameOuterStroke),1));
817 painter->drawRoundedRect(focusRect,4,4);
821 case PE_PanelTipLabel: {
822 const auto rect = QRectF(option->rect).marginsRemoved(QMarginsF(0.5, 0.5, 0.5, 0.5));
823 const auto pen = highContrastTheme ? option->palette.buttonText().color()
824 : winUI3Color(frameColorLight);
825 drawRoundedRect(painter, rect, pen, option->palette.toolTipBase());
828 case PE_FrameTabWidget:
829#if QT_CONFIG(tabwidget)
830 if (
const QStyleOptionTabWidgetFrame *frame = qstyleoption_cast<
const QStyleOptionTabWidgetFrame *>(option)) {
831 const auto rect = QRectF(option->rect).marginsRemoved(QMarginsF(0.5, 0.5, 0.5, 0.5));
832 const auto pen = highContrastTheme ? frame->palette.buttonText().color()
833 : winUI3Color(frameColorLight);
834 drawRoundedRect(painter, rect, pen, frame->palette.base());
838 case PE_FrameGroupBox:
839 if (
const QStyleOptionFrame *frame = qstyleoption_cast<
const QStyleOptionFrame *>(option)) {
840 const auto pen = highContrastTheme ? frame->palette.buttonText().color()
841 : winUI3Color(frameColorStrong);
842 if (frame->features & QStyleOptionFrame::Flat) {
843 painter->setBrush(Qt::NoBrush);
844 painter->setPen(pen);
845 const QRect &fr = frame->rect;
846 QPoint p1(fr.x(), fr.y() + 1);
847 QPoint p2(fr.x() + fr.width(), p1.y());
848 painter->drawLine(p1, p2);
850 const auto frameRect = QRectF(frame->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5));
851 drawRoundedRect(painter, frameRect, pen, Qt::NoBrush);
855 case PE_IndicatorHeaderArrow:
856 if (
const QStyleOptionHeader *header = qstyleoption_cast<
const QStyleOptionHeader *>(option)) {
857 QFont f(d->assetFont);
860 painter->setPen(header->palette.text().color());
861 QRectF rect = option->rect;
862 if (header->sortIndicator & QStyleOptionHeader::SortUp) {
864 }
else if (header->sortIndicator & QStyleOptionHeader::SortDown) {
869 case PE_IndicatorCheckBox: {
870 const bool isRtl = option->direction == Qt::RightToLeft;
871 const bool isOn = option->state & State_On;
872 const bool isPartial = option->state & State_NoChange;
874 QRectF rect = isRtl ? option->rect.adjusted(0, 0, -2, 0) : option->rect.adjusted(2, 0, 0, 0);
875 const QPointF center = rect.center();
878 rect.moveCenter(center);
880 drawRoundedRect(painter, rect, borderPenControlAlt(option),
881 controlFillBrush(option, ControlType::ControlAlt));
884 painter->setFont(d->assetFont);
885 painter->setPen(controlTextColor(option, QPalette::Window));
886 qreal clipWidth = 1.0;
887 QFontMetrics fm(d->assetFont);
889 if (d->transitionsEnabled() && option->styleObject) {
890 QNumberStyleAnimation *animation = qobject_cast<QNumberStyleAnimation *>(
891 d->animation(option->styleObject));
893 clipWidth = animation->currentValue();
896 clipRect.moveCenter(center);
897 clipRect.setLeft(rect.x() + (rect.width() - clipRect.width()) / 2.0 + 0.5);
898 clipRect.setWidth(clipWidth * clipRect.width());
899 painter->drawText(clipRect, Qt::AlignVCenter | Qt::AlignLeft,
AcceptMedium);
900 }
else if (isPartial) {
901 QFont f(d->assetFont);
904 painter->setPen(controlTextColor(option, QPalette::Window));
905 painter->drawText(rect, Qt::AlignCenter,
Dash12);
909 case PE_IndicatorBranch: {
910 if (option->state & State_Children) {
911 const bool isReverse = option->direction == Qt::RightToLeft;
912 const bool isOpen = option->state & QStyle::State_Open;
913 QFont f(d->assetFont);
916 painter->setPen(option->palette.color(isOpen ? QPalette::Active : QPalette::Disabled,
917 QPalette::WindowText));
919 painter->drawText(option->rect, Qt::AlignCenter, str);
923 case PE_IndicatorRadioButton: {
924 const bool isRtl = option->direction == Qt::RightToLeft;
925 const bool isOn = option->state & State_On;
926 qreal innerRadius = 7.0f;
927 if (d->transitionsEnabled() && option->styleObject) {
928 if (option->styleObject->property(
"_q_end_radius").isNull())
929 option->styleObject->setProperty(
"_q_end_radius", innerRadius);
930 QNumberStyleAnimation *animation = qobject_cast<QNumberStyleAnimation *>(d->animation(option->styleObject));
931 innerRadius = animation ? animation->currentValue() : option->styleObject->property(
"_q_end_radius").toFloat();
932 option->styleObject->setProperty(
"_q_inner_radius", innerRadius);
934 innerRadius = radioButtonInnerRadius(state);
937 QRectF rect = isRtl ? option->rect.adjusted(0, 0, -2, 0) : option->rect.adjusted(2, 0, 0, 0);
938 const QPointF center = rect.center();
940 painter->setPen(borderPenControlAlt(option));
941 painter->setBrush(controlFillBrush(option, ControlType::ControlAlt));
944 path.addEllipse(center, 7.5, 7.5);
945 path.addEllipse(center, innerRadius, innerRadius);
946 painter->drawPath(path);
948 painter->setBrush(option->palette.window().color());
949 painter->drawEllipse(center, innerRadius, innerRadius);
951 painter->drawEllipse(center, 7.5, 7.5);
955 case PE_PanelButtonTool:
956 case PE_PanelButtonBevel:{
957 const bool isEnabled = state & QStyle::State_Enabled;
958 const bool isMouseOver = state & QStyle::State_MouseOver;
959 const bool isRaised = state & QStyle::State_Raised;
960 const QRectF rect = option->rect.marginsRemoved(QMargins(2,2,2,2));
961 if (element == PE_PanelButtonTool && ((!isMouseOver && !isRaised) || !isEnabled))
962 painter->setPen(Qt::NoPen);
964 painter->setPen(WINUI3Colors[colorSchemeIndex][controlStrokePrimary]);
965 painter->setBrush(controlFillBrush(option, ControlType::Control));
966 painter->drawRoundedRect(rect,
967 secondLevelRoundingRadius, secondLevelRoundingRadius);
971 painter->setPen(WINUI3Colors[colorSchemeIndex][controlStrokeSecondary]);
972 painter->drawLine(rect.bottomLeft() + QPointF(sublineOffset, 0.5), rect.bottomRight() + QPointF(-sublineOffset, 0.5));
976 case PE_FrameDefaultButton:
977 painter->setPen(option->palette.accent().color());
978 painter->setBrush(Qt::NoBrush);
979 painter->drawRoundedRect(option->rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
984 const QRect rect = option->rect.marginsRemoved(QMargins(2, 2, 2, 2));
985 painter->setPen(highContrastTheme ? QPen(option->palette.windowText().color(), 2)
986 : winUI3Color(frameColorLight));
987 painter->setBrush(winUI3Color(menuPanelFill));
988 painter->drawRoundedRect(rect, topLevelRoundingRadius, topLevelRoundingRadius);
991 case PE_PanelLineEdit:
992 if (
const auto *panel = qstyleoption_cast<
const QStyleOptionFrame *>(option)) {
993 const auto frameRect = QRectF(option->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5));
994 drawRoundedRect(painter, frameRect, Qt::NoPen, option->palette.brush(QPalette::Base));
996 if (panel->lineWidth > 0)
997 proxy()->drawPrimitive(PE_FrameLineEdit, panel, painter, widget);
999 const bool isMouseOver = state & State_MouseOver;
1000 const bool hasFocus = state & State_HasFocus;
1001 if (isMouseOver && !hasFocus && !highContrastTheme)
1002 drawRoundedRect(painter, frameRect, Qt::NoPen, winUI3Color(subtleHighlightColor));
1005 case PE_FrameLineEdit: {
1006 const auto frameRect = QRectF(option->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5));
1007 drawLineEditFrame(painter, frameRect, option);
1008 if (state & State_KeyboardFocusChange && state & State_HasFocus) {
1009 QStyleOptionFocusRect fropt;
1010 fropt.QStyleOption::operator=(*option);
1011 proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
1016 if (
const auto *frame = qstyleoption_cast<
const QStyleOptionFrame *>(option)) {
1017 const auto rect = QRectF(option->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5));
1018 if (qobject_cast<
const QComboBoxPrivateContainer *>(widget)) {
1020 if (highContrastTheme)
1021 pen = QPen(option->palette.windowText().color(), 2);
1024 drawRoundedRect(painter, rect, pen, WINUI3Colors[colorSchemeIndex][menuPanelFill]);
1026 drawRoundedRect(painter, rect, Qt::NoPen, option->palette.brush(QPalette::Base));
1028 if (frame->frameShape == QFrame::NoFrame)
1031 drawLineEditFrame(painter, rect, option, qobject_cast<
const QTextEdit *>(widget) !=
nullptr);
1035 case PE_PanelItemViewItem:
1036 if (
const QStyleOptionViewItem *vopt = qstyleoption_cast<
const QStyleOptionViewItem *>(option)) {
1037 if (vopt->backgroundBrush.style() != Qt::NoBrush) {
1038 QPainterStateGuard psg(
painter);
1039 painter->setBrushOrigin(vopt->rect.topLeft());
1040 painter->fillRect(vopt->rect, vopt->backgroundBrush);
1044 case PE_PanelItemViewRow:
1045 if (
const QStyleOptionViewItem *vopt = qstyleoption_cast<
const QStyleOptionViewItem *>(option)) {
1049 const QRect &rect = vopt->rect;
1050 const bool isRtl = option->direction == Qt::RightToLeft;
1051 if (rect.width() <= 0)
1054 painter->setPen(Qt::NoPen);
1055 if (vopt->features & QStyleOptionViewItem::Alternate)
1056 painter->setBrush(vopt->palette.alternateBase());
1058 painter->setBrush(vopt->palette.base());
1059 painter->drawRect(rect);
1061 const bool isTreeDecoration = vopt->features.testFlag(
1062 QStyleOptionViewItem::IsDecorationForRootColumn);
1063 if (isTreeDecoration && vopt->state.testAnyFlags(State_Selected | State_MouseOver) &&
1064 vopt->showDecorationSelected) {
1065 const bool onlyOne = vopt->viewItemPosition == QStyleOptionViewItem::OnlyOne ||
1066 vopt->viewItemPosition == QStyleOptionViewItem::Invalid;
1067 bool isFirst = vopt->viewItemPosition == QStyleOptionViewItem::Beginning;
1068 bool isLast = vopt->viewItemPosition == QStyleOptionViewItem::End;
1078 const QAbstractItemView *view = qobject_cast<
const QAbstractItemView *>(widget);
1079 painter->setBrush(view->alternatingRowColors() ? vopt->palette.highlight() : WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
1080 painter->setPen(Qt::NoPen);
1083 painter->setClipRect(rect);
1084 painter->drawRoundedRect(rect.marginsRemoved(QMargins(2, 2, -secondLevelRoundingRadius, 2)),
1085 secondLevelRoundingRadius, secondLevelRoundingRadius);
1087 }
else if (isLast) {
1089 painter->setClipRect(rect);
1090 painter->drawRoundedRect(rect.marginsRemoved(QMargins(-secondLevelRoundingRadius, 2, 2, 2)),
1091 secondLevelRoundingRadius, secondLevelRoundingRadius);
1094 painter->drawRect(vopt->rect.marginsRemoved(QMargins(0, 2, 0, 2)));
1099 case QStyle::PE_Widget: {
1100 if (widget && widget->palette().isBrushSet(QPalette::Active, widget->backgroundRole())) {
1101 const QBrush bg = widget->palette().brush(widget->backgroundRole());
1102 auto wp = QWidgetPrivate::get(widget);
1103 QPainterStateGuard psg(
painter);
1104 wp->updateBrushOrigin(painter, bg);
1105 painter->fillRect(option->rect, bg);
1109 case QStyle::PE_FrameWindow:
1110 if (
const auto *frm = qstyleoption_cast<
const QStyleOptionFrame *>(option)) {
1112 QRectF rect= option->rect;
1113 int fwidth =
int((frm->lineWidth + frm->midLineWidth) / QWindowsStylePrivate::nativeMetricScaleFactor(widget));
1115 QRectF bottomLeftCorner = QRectF(rect.left() + 1.0,
1116 rect.bottom() - 1.0 - secondLevelRoundingRadius,
1117 secondLevelRoundingRadius,
1118 secondLevelRoundingRadius);
1119 QRectF bottomRightCorner = QRectF(rect.right() - 1.0 - secondLevelRoundingRadius,
1120 rect.bottom() - 1.0 - secondLevelRoundingRadius,
1121 secondLevelRoundingRadius,
1122 secondLevelRoundingRadius);
1125 if (widget !=
nullptr) {
1126 QBitmap mask(widget->width(), widget->height());
1130 maskPainter.setRenderHint(QPainter::Antialiasing);
1131 maskPainter.setBrush(Qt::color1);
1132 maskPainter.setPen(Qt::NoPen);
1133 maskPainter.drawRoundedRect(option->rect,secondLevelRoundingRadius,secondLevelRoundingRadius);
1134 const_cast<QWidget*>(widget)->setMask(mask);
1138 painter->setPen(QPen(frm->palette.base(), fwidth));
1139 painter->drawLine(QPointF(rect.left(), rect.top()),
1140 QPointF(rect.left(), rect.bottom() - fwidth));
1141 painter->drawLine(QPointF(rect.left() + fwidth, rect.bottom()),
1142 QPointF(rect.right() - fwidth, rect.bottom()));
1143 painter->drawLine(QPointF(rect.right(), rect.top()),
1144 QPointF(rect.right(), rect.bottom() - fwidth));
1146 painter->setPen(WINUI3Colors[colorSchemeIndex][surfaceStroke]);
1147 painter->drawLine(QPointF(rect.left() + 0.5, rect.top() + 0.5),
1148 QPointF(rect.left() + 0.5, rect.bottom() - 0.5 - secondLevelRoundingRadius));
1149 painter->drawLine(QPointF(rect.left() + 0.5 + secondLevelRoundingRadius, rect.bottom() - 0.5),
1150 QPointF(rect.right() - 0.5 - secondLevelRoundingRadius, rect.bottom() - 0.5));
1151 painter->drawLine(QPointF(rect.right() - 0.5, rect.top() + 1.5),
1152 QPointF(rect.right() - 0.5, rect.bottom() - 0.5 - secondLevelRoundingRadius));
1154 painter->setPen(Qt::NoPen);
1155 painter->setBrush(frm->palette.base());
1156 painter->drawPie(bottomRightCorner.marginsAdded(QMarginsF(2.5,2.5,0.0,0.0)),
1158 painter->drawPie(bottomLeftCorner.marginsAdded(QMarginsF(0.0,2.5,2.5,0.0)),
1161 painter->setPen(WINUI3Colors[colorSchemeIndex][surfaceStroke]);
1162 painter->setBrush(Qt::NoBrush);
1163 painter->drawArc(bottomRightCorner,
1165 painter->drawArc(bottomLeftCorner,
1170 QWindowsVistaStyle::drawPrimitive(element, option, painter, widget);
1178void QWindows11Style::drawControl(ControlElement element,
const QStyleOption *option,
1179 QPainter *painter,
const QWidget *widget)
const
1181 Q_D(
const QWindows11Style);
1182 State flags = option->state;
1185 painter->setRenderHint(QPainter::Antialiasing);
1187 case QStyle::CE_ComboBoxLabel:
1188 if (
const QStyleOptionComboBox *cb = qstyleoption_cast<
const QStyleOptionComboBox *>(option)) {
1189 QStyleOptionComboBox newOption = *cb;
1190 newOption.rect.adjust(4,0,-4,0);
1191 QCommonStyle::drawControl(element, &newOption, painter, widget);
1194 case QStyle::CE_TabBarTabShape:
1195#if QT_CONFIG(tabbar)
1196 if (
const QStyleOptionTab *tab = qstyleoption_cast<
const QStyleOptionTab *>(option)) {
1197 QRectF tabRect = tab->rect.marginsRemoved(QMargins(2,2,0,0));
1198 painter->setPen(Qt::NoPen);
1199 painter->setBrush(tab->palette.base());
1200 if (tab->state & State_MouseOver){
1201 painter->setBrush(WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
1202 }
else if (tab->state & State_Selected) {
1203 painter->setBrush(tab->palette.base());
1205 painter->setBrush(tab->palette.window());
1207 painter->drawRoundedRect(tabRect,2,2);
1209 painter->setBrush(Qt::NoBrush);
1210 painter->setPen(highContrastTheme ==
true ? tab->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorLight]);
1211 painter->drawRoundedRect(tabRect.adjusted(0.5,0.5,-0.5,-0.5),2,2);
1216 case CE_ToolButtonLabel:
1217#if QT_CONFIG(toolbutton)
1218 if (
const QStyleOptionToolButton *toolbutton
1219 = qstyleoption_cast<
const QStyleOptionToolButton *>(option)) {
1220 QRect rect = toolbutton->rect;
1223 if (toolbutton->state & (State_Sunken | State_On)) {
1224 shiftX = proxy()->pixelMetric(PM_ButtonShiftHorizontal, toolbutton, widget);
1225 shiftY = proxy()->pixelMetric(PM_ButtonShiftVertical, toolbutton, widget);
1228 bool hasArrow = toolbutton->features & QStyleOptionToolButton::Arrow;
1229 if (((!hasArrow && toolbutton->icon.isNull()) && !toolbutton->text.isEmpty())
1230 || toolbutton->toolButtonStyle == Qt::ToolButtonTextOnly) {
1231 int alignment = Qt::AlignCenter | Qt::TextShowMnemonic;
1232 if (!proxy()->styleHint(SH_UnderlineShortcut, toolbutton, widget))
1233 alignment |= Qt::TextHideMnemonic;
1234 rect.translate(shiftX, shiftY);
1235 painter->setFont(toolbutton->font);
1236 const QString text = d->toolButtonElideText(toolbutton, rect, alignment);
1238 painter->setPen(controlTextColor(option));
1239 proxy()->drawItemText(painter, rect, alignment, toolbutton->palette,
1240 toolbutton->state & State_Enabled, text);
1243 QSize pmSize = toolbutton->iconSize;
1244 if (!toolbutton->icon.isNull()) {
1245 QIcon::State state = toolbutton->state & State_On ? QIcon::On : QIcon::Off;
1247 if (!(toolbutton->state & State_Enabled))
1248 mode = QIcon::Disabled;
1249 else if ((toolbutton->state & State_MouseOver) && (toolbutton->state & State_AutoRaise))
1250 mode = QIcon::Active;
1252 mode = QIcon::Normal;
1253 pm = toolbutton->icon.pixmap(toolbutton->rect.size().boundedTo(toolbutton->iconSize), painter->device()->devicePixelRatio(),
1255 pmSize = pm.size() / pm.devicePixelRatio();
1258 if (toolbutton->toolButtonStyle != Qt::ToolButtonIconOnly) {
1259 painter->setFont(toolbutton->font);
1262 int alignment = Qt::TextShowMnemonic;
1263 if (!proxy()->styleHint(SH_UnderlineShortcut, toolbutton, widget))
1264 alignment |= Qt::TextHideMnemonic;
1266 if (toolbutton->toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
1267 pr.setHeight(pmSize.height() + 4);
1268 tr.adjust(0, pr.height() - 1, 0, -1);
1269 pr.translate(shiftX, shiftY);
1271 proxy()->drawItemPixmap(painter, pr, Qt::AlignCenter, pm);
1273 drawArrow(proxy(), toolbutton, pr, painter, widget);
1275 alignment |= Qt::AlignCenter;
1277 pr.setWidth(pmSize.width() + 4);
1278 tr.adjust(pr.width(), 0, 0, 0);
1279 pr.translate(shiftX, shiftY);
1281 proxy()->drawItemPixmap(painter, QStyle::visualRect(toolbutton->direction, rect, pr), Qt::AlignCenter, pm);
1283 drawArrow(proxy(), toolbutton, pr, painter, widget);
1285 alignment |= Qt::AlignLeft | Qt::AlignVCenter;
1287 tr.translate(shiftX, shiftY);
1288 const QString text = d->toolButtonElideText(toolbutton, tr, alignment);
1289 painter->setPen(controlTextColor(option));
1290 proxy()->drawItemText(painter, QStyle::visualRect(toolbutton->direction, rect, tr), alignment, toolbutton->palette,
1291 toolbutton->state & State_Enabled, text);
1293 rect.translate(shiftX, shiftY);
1295 drawArrow(proxy(), toolbutton, rect, painter, widget);
1297 proxy()->drawItemPixmap(painter, rect, Qt::AlignCenter, pm);
1304 case QStyle::CE_ShapedFrame:
1305 if (
const QStyleOptionFrame *f = qstyleoption_cast<
const QStyleOptionFrame *>(option)) {
1306 int frameShape = f->frameShape;
1307 int frameShadow = QFrame::Plain;
1308 if (f->state & QStyle::State_Sunken)
1309 frameShadow = QFrame::Sunken;
1310 else if (f->state & QStyle::State_Raised)
1311 frameShadow = QFrame::Raised;
1313 int lw = f->lineWidth;
1314 int mlw = f->midLineWidth;
1316 switch (frameShape) {
1318 if (frameShadow == QFrame::Plain)
1319 qDrawPlainRoundedRect(painter, f->rect, secondLevelRoundingRadius, secondLevelRoundingRadius, highContrastTheme ==
true ? f->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorStrong], lw);
1321 qDrawShadeRect(painter, f->rect, f->palette, frameShadow == QFrame::Sunken, lw, mlw);
1324 if (frameShadow == QFrame::Plain)
1325 qDrawPlainRoundedRect(painter, f->rect, secondLevelRoundingRadius, secondLevelRoundingRadius, highContrastTheme ==
true ? f->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorStrong], lw);
1327 qDrawShadePanel(painter, f->rect, f->palette, frameShadow == QFrame::Sunken, lw);
1330 QWindowsVistaStyle::drawControl(element, option, painter, widget);
1334 case QStyle::CE_ProgressBarGroove:{
1335 if (
const QStyleOptionProgressBar* progbaropt = qstyleoption_cast<
const QStyleOptionProgressBar*>(option)) {
1336 QRect rect = subElementRect(SE_ProgressBarContents, progbaropt, widget);
1337 QPointF center = rect.center();
1338 if (progbaropt->state & QStyle::State_Horizontal) {
1340 rect.moveTop(center.y());
1343 rect.moveLeft(center.x());
1345 painter->setPen(Qt::NoPen);
1346 painter->setBrush(Qt::gray);
1347 painter->drawRect(rect);
1351 case QStyle::CE_ProgressBarContents:
1352 if (
const auto baropt = qstyleoption_cast<
const QStyleOptionProgressBar *>(option)) {
1353 QPainterStateGuard psg(
painter);
1354 QRectF rect = subElementRect(SE_ProgressBarContents, baropt, widget);
1355 painter->translate(rect.topLeft());
1356 rect.translate(-rect.topLeft());
1358 constexpr qreal progressBarThickness = 3;
1359 constexpr qreal progressBarHalfThickness = progressBarThickness / 2.0;
1361 const auto isIndeterminate = baropt->maximum == 0 && baropt->minimum == 0;
1362 const auto orientation =
1363 (baropt->state & QStyle::State_Horizontal) ? Qt::Horizontal : Qt::Vertical;
1364 const auto inverted = baropt->invertedAppearance;
1365 const auto reverse = (baropt->direction == Qt::RightToLeft) ^ inverted;
1369 if (orientation == Qt::Vertical) {
1370 rect = QRectF(rect.left(), rect.top(), rect.height(),
1375 m.translate(0, -rect.height() + 1);
1378 m.translate(-rect.width(), 0);
1380 painter->setTransform(m,
true);
1381 }
else if (reverse) {
1382 QTransform m = QTransform::fromScale(-1, 1);
1383 m.translate(-rect.width(), 0);
1384 painter->setTransform(m,
true);
1386 const qreal offset = (
int(rect.height()) % 2 == 0) ? 0.5f : 0.0f;
1388 if (isIndeterminate) {
1389 constexpr auto loopDurationMSec = 4000;
1390 const auto elapsedTime =
std::chrono::time_point_cast<
std::chrono::milliseconds>(
1391 std::chrono::system_clock::now());
1392 const auto elapsed = elapsedTime.time_since_epoch().count();
1393 const auto handleCenter = (elapsed % loopDurationMSec) /
float(loopDurationMSec);
1394 const auto isLongHandle = (elapsed / loopDurationMSec) % 2 == 0;
1395 const auto lengthFactor = (isLongHandle ? 33.0f : 25.0f) / 100.0f;
1396 const auto begin = qMax(handleCenter * (1 + lengthFactor) - lengthFactor, 0.0f);
1397 const auto end = qMin(handleCenter * (1 + lengthFactor), 1.0f);
1398 const auto barBegin = begin * rect.width();
1399 const auto barEnd = end * rect.width();
1400 rect = QRectF(QPointF(rect.left() + barBegin, rect.top()),
1401 QPointF(rect.left() + barEnd, rect.bottom()));
1402 const_cast<QWidget *>(widget)->update();
1404 const auto fillPercentage = (
float(baropt->progress - baropt->minimum))
1405 / (
float(baropt->maximum - baropt->minimum));
1406 rect.setWidth(rect.width() * fillPercentage);
1408 const QPointF center = rect.center();
1409 rect.setHeight(progressBarThickness);
1410 rect.moveTop(center.y() - progressBarHalfThickness - offset);
1411 drawRoundedRect(painter, rect, Qt::NoPen, baropt->palette.accent());
1414 case QStyle::CE_ProgressBarLabel:
1415 if (
const QStyleOptionProgressBar* progbaropt = qstyleoption_cast<
const QStyleOptionProgressBar*>(option)) {
1416 const bool vertical = !(progbaropt->state & QStyle::State_Horizontal);
1418 QRect rect = subElementRect(SE_ProgressBarLabel, progbaropt, widget);
1419 painter->setPen(progbaropt->palette.text().color());
1420 painter->drawText(rect, progbaropt->text, progbaropt->textAlignment);
1424 case CE_PushButtonLabel:
1425 if (
const QStyleOptionButton *btn = qstyleoption_cast<
const QStyleOptionButton *>(option)) {
1426 QRect textRect = btn->rect;
1428 int tf = Qt::AlignVCenter|Qt::TextShowMnemonic;
1429 if (!proxy()->styleHint(SH_UnderlineShortcut, btn, widget))
1430 tf |= Qt::TextHideMnemonic;
1432 if (btn->features & QStyleOptionButton::HasMenu) {
1433 int indicatorSize = proxy()->pixelMetric(PM_MenuButtonIndicator, btn, widget);
1434 QLineF menuSplitter;
1435 QRectF indicatorRect;
1437 painter->setFont(d->assetFont);
1439 if (btn->direction == Qt::LeftToRight) {
1440 indicatorRect = QRect(textRect.x() + textRect.width() - indicatorSize - 4, textRect.y(),2 * 4 + indicatorSize, textRect.height());
1441 indicatorRect.adjust(0.5,-0.5,0.5,0.5);
1442 menuSplitter = QLineF(indicatorRect.topLeft(),indicatorRect.bottomLeft());
1443 textRect = textRect.adjusted(0, 0, -indicatorSize, 0);
1445 indicatorRect = QRect(textRect.x(), textRect.y(), textRect.x() + indicatorSize + 4, textRect.height());
1446 indicatorRect.adjust(-0.5,-0.5,-0.5,0.5);
1447 menuSplitter = QLineF(indicatorRect.topRight(),indicatorRect.bottomRight());
1448 textRect = textRect.adjusted(indicatorSize, 0, 0, 0);
1450 painter->drawText(indicatorRect, Qt::AlignCenter,
ChevronDownMed);
1451 painter->setPen(WINUI3Colors[colorSchemeIndex][controlStrokePrimary]);
1452 painter->drawLine(menuSplitter);
1455 if (!btn->icon.isNull()) {
1457 QIcon::Mode mode = btn->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
1458 if (mode == QIcon::Normal && btn->state & State_HasFocus)
1459 mode = QIcon::Active;
1460 QIcon::State state = QIcon::Off;
1461 if (btn->state & State_On)
1464 QPixmap pixmap = btn->icon.pixmap(btn->iconSize, painter->device()->devicePixelRatio(), mode, state);
1465 int pixmapWidth = pixmap.width() / pixmap.devicePixelRatio();
1466 int pixmapHeight = pixmap.height() / pixmap.devicePixelRatio();
1467 int labelWidth = pixmapWidth;
1468 int labelHeight = pixmapHeight;
1469 int iconSpacing = 4;
1470 if (!btn->text.isEmpty()) {
1471 int textWidth = btn->fontMetrics.boundingRect(option->rect, tf, btn->text).width();
1472 labelWidth += (textWidth + iconSpacing);
1475 QRect iconRect = QRect(textRect.x() + (textRect.width() - labelWidth) / 2,
1476 textRect.y() + (textRect.height() - labelHeight) / 2,
1477 pixmapWidth, pixmapHeight);
1479 iconRect = visualRect(btn->direction, textRect, iconRect);
1481 if (btn->direction == Qt::RightToLeft) {
1482 tf |= Qt::AlignRight;
1483 textRect.setRight(iconRect.left() - iconSpacing / 2);
1485 tf |= Qt::AlignLeft;
1486 textRect.setLeft(iconRect.left() + iconRect.width() + iconSpacing / 2);
1489 if (btn->state & (State_On | State_Sunken))
1490 iconRect.translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, option, widget),
1491 proxy()->pixelMetric(PM_ButtonShiftVertical, option, widget));
1492 painter->drawPixmap(iconRect, pixmap);
1494 tf |= Qt::AlignHCenter;
1497 painter->setPen(controlTextColor(option));
1498 proxy()->drawItemText(painter, textRect, tf, option->palette,btn->state & State_Enabled, btn->text);
1501 case CE_PushButtonBevel:
1502 if (
const QStyleOptionButton *btn = qstyleoption_cast<
const QStyleOptionButton *>(option)) {
1503 QRectF rect = btn->rect.marginsRemoved(QMargins(2, 2, 2, 2));
1504 painter->setPen(Qt::NoPen);
1505 if (btn->features.testFlag(QStyleOptionButton::Flat)) {
1506 painter->setBrush(btn->palette.button());
1507 painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
1508 if (flags & (State_Sunken | State_On)) {
1509 painter->setBrush(WINUI3Colors[colorSchemeIndex][subtlePressedColor]);
1511 else if (flags & State_MouseOver) {
1512 painter->setBrush(WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
1514 painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
1516 painter->setBrush(controlFillBrush(option, ControlType::Control));
1517 painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
1519 rect.adjust(0.5,0.5,-0.5,-0.5);
1520 const bool defaultButton = btn->features.testFlag(QStyleOptionButton::DefaultButton);
1521 painter->setBrush(Qt::NoBrush);
1522 painter->setPen(defaultButton ? option->palette.accent().color()
1523 : WINUI3Colors[colorSchemeIndex][controlStrokePrimary]);
1524 painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
1526 painter->setPen(defaultButton ? WINUI3Colors[colorSchemeIndex][controlStrokeOnAccentSecondary]
1527 : WINUI3Colors[colorSchemeIndex][controlStrokeSecondary]);
1528 if (flags & State_Raised)
1529 painter->drawLine(rect.bottomLeft() + QPointF(4.0,0.0), rect.bottomRight() + QPointF(-4,0.0));
1533 case CE_MenuBarItem:
1534 if (
const auto *mbi = qstyleoption_cast<
const QStyleOptionMenuItem *>(option)) {
1535 constexpr int hPadding = 11;
1536 constexpr int topPadding = 4;
1537 constexpr int bottomPadding = 6;
1538 bool active = mbi->state & State_Selected;
1539 bool hasFocus = mbi->state & State_HasFocus;
1540 bool down = mbi->state & State_Sunken;
1541 bool enabled = mbi->state & State_Enabled;
1542 QStyleOptionMenuItem newMbi = *mbi;
1543 newMbi.font.setPointSize(10);
1544 if (enabled && active) {
1546 painter->setBrushOrigin(painter->brushOriginF() + QPoint(1, 1));
1548 if (highContrastTheme)
1549 painter->setPen(QPen(newMbi.palette.highlight().color(), 2));
1551 painter->setPen(Qt::NoPen);
1552 painter->setBrush(highContrastTheme ? newMbi.palette.window().color() : WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
1553 QRect rect = mbi->rect.marginsRemoved(QMargins(5,0,5,0));
1554 painter->drawRoundedRect(rect,secondLevelRoundingRadius,secondLevelRoundingRadius, Qt::AbsoluteSize);
1556 }
else if (enabled && highContrastTheme) {
1557 painter->setPen(QPen(newMbi.palette.windowText().color(), 2));
1558 painter->setBrush(newMbi.palette.window().color());
1559 QRect rect = mbi->rect.marginsRemoved(QMargins(5,0,5,0));
1560 painter->drawRoundedRect(rect,secondLevelRoundingRadius,secondLevelRoundingRadius, Qt::AbsoluteSize);
1562 newMbi.rect.adjust(hPadding,topPadding,-hPadding,-bottomPadding);
1563 painter->setFont(newMbi.font);
1564 QCommonStyle::drawControl(element, &newMbi, painter, widget);
1569 case CE_MenuEmptyArea:
1573 if (
const auto *menuitem = qstyleoption_cast<
const QStyleOptionMenuItem *>(option)) {
1575 menuitem->rect.getRect(&x, &y, &w, &h);
1576 int tab = menuitem->reservedShortcutWidth;
1577 bool dis = !(menuitem->state & State_Enabled);
1578 bool checked = menuitem->checkType != QStyleOptionMenuItem::NotCheckable
1579 ? menuitem->checked :
false;
1580 bool act = menuitem->state & State_Selected;
1583 int checkcol = qMax<
int>(menuitem->maxIconWidth, 32);
1585 QBrush fill = (act ==
true && dis ==
false) ? (highContrastTheme ? menuitem->palette.brush(QPalette::Highlight) : QBrush(WINUI3Colors[colorSchemeIndex][subtleHighlightColor])) : menuitem->palette.brush(QPalette::Button);
1586 painter->setBrush(fill);
1587 painter->setPen(Qt::NoPen);
1588 const QRect rect = menuitem->rect.marginsRemoved(QMargins(2,2,2,2));
1589 if (act && dis ==
false)
1590 painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius, Qt::AbsoluteSize);
1592 if (menuitem->menuItemType == QStyleOptionMenuItem::Separator){
1594 painter->setPen(highContrastTheme ==
true ? menuitem->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorLight]);
1595 painter->drawLine(x, y + yoff, x + w, y + yoff );
1599 QRect vCheckRect = visualRect(option->direction, menuitem->rect, QRect(menuitem->rect.x(), menuitem->rect.y(), checkcol, menuitem->rect.height()));
1600 if (!menuitem->icon.isNull() && checked) {
1602 qDrawShadePanel(painter, vCheckRect,
1603 menuitem->palette,
true, 1,
1604 &menuitem->palette.brush(QPalette::Button));
1606 QBrush fill(menuitem->palette.light().color(), Qt::Dense4Pattern);
1607 qDrawShadePanel(painter, vCheckRect, menuitem->palette,
true, 1, &fill);
1613 if (!menuitem->icon.isNull()) {
1614 QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal;
1616 mode = QIcon::Active;
1617 const auto size = proxy()->pixelMetric(PM_SmallIconSize, option, widget);
1618 QRect pmr(QPoint(0, 0), QSize(size, size));
1619 pmr.moveCenter(vCheckRect.center());
1620 menuitem->icon.paint(painter, pmr, Qt::AlignCenter, mode,
1621 checked ? QIcon::On : QIcon::Off);
1622 }
else if (checked) {
1625 painter->setPen(menuitem->palette.text().color());
1626 painter->setFont(d->assetFont);
1627 const int text_flags = Qt::AlignVCenter | Qt::AlignHCenter | Qt::TextDontClip | Qt::TextSingleLine;
1628 painter->setPen(option->palette.text().color());
1629 painter->drawText(vCheckRect, text_flags, CheckMark);
1632 painter->setPen(act ? menuitem->palette.highlightedText().color() : menuitem->palette.buttonText().color());
1634 QColor discol = menuitem->palette.text().color();
1636 discol = menuitem->palette.color(QPalette::Disabled, QPalette::WindowText);
1638 QStringView s(menuitem->text);
1640 int xm = QWindowsStylePrivate::windowsItemFrame + checkcol + QWindowsStylePrivate::windowsItemHMargin;
1641 int xpos = menuitem->rect.x() + xm;
1642 QRect textRect(xpos, y + QWindowsStylePrivate::windowsItemVMargin,
1643 w - xm - QWindowsStylePrivate::windowsRightBorder - tab + 1, h - 2 * QWindowsStylePrivate::windowsItemVMargin);
1644 QRect vTextRect = visualRect(option->direction, menuitem->rect, textRect);
1647 qsizetype t = s.indexOf(u'\t');
1648 int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
1649 if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget))
1650 text_flags |= Qt::TextHideMnemonic;
1651 text_flags |= Qt::AlignLeft;
1653 QRect vShortcutRect = visualRect(option->direction, menuitem->rect,
1654 QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom())));
1655 const QString textToDraw = s.mid(t + 1).toString();
1656 if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) {
1657 painter->setPen(menuitem->palette.light().color());
1658 painter->drawText(vShortcutRect.adjusted(1, 1, 1, 1), text_flags, textToDraw);
1660 if (highContrastTheme)
1661 painter->setPen(act ? menuitem->palette.highlightedText().color() : menuitem->palette.buttonText().color());
1663 painter->setPen(menuitem->palette.color(QPalette::Disabled, QPalette::Text));
1664 painter->drawText(vShortcutRect, text_flags, textToDraw);
1667 QFont font = menuitem->font;
1668 if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem)
1670 painter->setFont(font);
1671 const QString textToDraw = s.left(t).toString();
1672 painter->setPen(highContrastTheme && act ? menuitem->palette.highlightedText().color() : discol);
1673 painter->drawText(vTextRect, text_flags, textToDraw);
1676 if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) {
1677 int dim = (h - 2 * QWindowsStylePrivate::windowsItemFrame) / 2;
1678 int xpos = x + w - QWindowsStylePrivate::windowsArrowHMargin - QWindowsStylePrivate::windowsItemFrame - dim;
1679 QRect vSubMenuRect = visualRect(option->direction, menuitem->rect, QRect(xpos, y + h / 2 - dim / 2, dim, dim));
1680 QStyleOptionMenuItem newMI = *menuitem;
1681 newMI.rect = vSubMenuRect;
1682 newMI.state = dis ? State_None : State_Enabled;
1684 newMI.palette.setColor(QPalette::ButtonText,
1685 newMI.palette.highlightedText().color());
1687 painter->setFont(d->assetFont);
1688 int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
1689 if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget))
1690 text_flags |= Qt::TextHideMnemonic;
1691 text_flags |= Qt::AlignLeft;
1692 painter->setPen(option->palette.text().color());
1693 const bool isReverse = option->direction == Qt::RightToLeft;
1694 const auto str = isReverse ? ChevronLeftMed : ChevronRightMed;
1695 painter->drawText(vSubMenuRect, Qt::AlignCenter, str);
1701 case CE_MenuBarEmptyArea: {
1704 case CE_HeaderEmptyArea:
1706 case CE_HeaderSection: {
1707 if (
const QStyleOptionHeader *header = qstyleoption_cast<
const QStyleOptionHeader *>(option)) {
1708 painter->setPen(Qt::NoPen);
1709 painter->setBrush(header->palette.button());
1710 painter->drawRect(header->rect);
1712 painter->setPen(highContrastTheme ==
true ? header->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorLight]);
1713 painter->setBrush(Qt::NoBrush);
1715 if (header->position == QStyleOptionHeader::OnlyOneSection) {
1718 else if (header->position == QStyleOptionHeader::Beginning) {
1719 painter->drawLine(QPointF(option->rect.topRight()) + QPointF(0.5,0.0),
1720 QPointF(option->rect.bottomRight()) + QPointF(0.5,0.0));
1722 else if (header->position == QStyleOptionHeader::End) {
1723 painter->drawLine(QPointF(option->rect.topLeft()) - QPointF(0.5,0.0),
1724 QPointF(option->rect.bottomLeft()) - QPointF(0.5,0.0));
1726 painter->drawLine(QPointF(option->rect.topRight()) + QPointF(0.5,0.0),
1727 QPointF(option->rect.bottomRight()) + QPointF(0.5,0.0));
1728 painter->drawLine(QPointF(option->rect.topLeft()) - QPointF(0.5,0.0),
1729 QPointF(option->rect.bottomLeft()) - QPointF(0.5,0.0));
1731 painter->drawLine(QPointF(option->rect.bottomLeft()) + QPointF(0.0,0.5),
1732 QPointF(option->rect.bottomRight()) + QPointF(0.0,0.5));
1736 case CE_ItemViewItem: {
1737 if (
const QStyleOptionViewItem *vopt = qstyleoption_cast<
const QStyleOptionViewItem *>(option)) {
1738 QRect checkRect = proxy()->subElementRect(SE_ItemViewItemCheckIndicator, vopt, widget);
1739 QRect iconRect = proxy()->subElementRect(SE_ItemViewItemDecoration, vopt, widget);
1740 QRect textRect = proxy()->subElementRect(SE_ItemViewItemText, vopt, widget);
1743 proxy()->drawPrimitive(PE_PanelItemViewItem, option, painter, widget);
1745 const QRect &rect = vopt->rect;
1746 const bool isRtl = option->direction == Qt::RightToLeft;
1747 bool onlyOne = vopt->viewItemPosition == QStyleOptionViewItem::OnlyOne ||
1748 vopt->viewItemPosition == QStyleOptionViewItem::Invalid;
1749 bool isFirst = vopt->viewItemPosition == QStyleOptionViewItem::Beginning;
1750 bool isLast = vopt->viewItemPosition == QStyleOptionViewItem::End;
1753 if (vopt->features.testFlag(QStyleOptionViewItem::IsDecoratedRootColumn) &&
1754 vopt->showDecorationSelected) {
1766 }
else if (isLast) {
1771 const bool highlightCurrent = vopt->state.testAnyFlags(State_Selected | State_MouseOver);
1772 if (highlightCurrent) {
1773 if (highContrastTheme) {
1774 painter->setBrush(vopt->palette.highlight());
1776 const QAbstractItemView *view = qobject_cast<
const QAbstractItemView *>(widget);
1777 painter->setBrush(view && view->alternatingRowColors()
1778 ? vopt->palette.highlight()
1779 : winUI3Color(subtleHighlightColor));
1782 painter->setBrush(vopt->backgroundBrush);
1784 painter->setPen(Qt::NoPen);
1787 painter->drawRoundedRect(rect.marginsRemoved(QMargins(2, 2, 2, 2)),
1788 secondLevelRoundingRadius, secondLevelRoundingRadius);
1789 }
else if (isFirst) {
1791 painter->setClipRect(rect);
1792 painter->drawRoundedRect(rect.marginsRemoved(QMargins(2, 2, -secondLevelRoundingRadius, 2)),
1793 secondLevelRoundingRadius, secondLevelRoundingRadius);
1795 }
else if (isLast) {
1797 painter->setClipRect(rect);
1798 painter->drawRoundedRect(rect.marginsRemoved(QMargins(-secondLevelRoundingRadius, 2, 2, 2)),
1799 secondLevelRoundingRadius, secondLevelRoundingRadius);
1802 painter->drawRect(rect.marginsRemoved(QMargins(0, 2, 0, 2)));
1806 if (vopt->features & QStyleOptionViewItem::HasCheckIndicator) {
1807 QStyleOptionViewItem option(*vopt);
1808 option.rect = checkRect;
1809 option.state = option.state & ~QStyle::State_HasFocus;
1811 switch (vopt->checkState) {
1813 option.state |= QStyle::State_Off;
1815 case Qt::PartiallyChecked:
1816 option.state |= QStyle::State_NoChange;
1819 option.state |= QStyle::State_On;
1822 proxy()->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &option, painter, widget);
1826 if (iconRect.isValid()) {
1827 QIcon::Mode mode = QIcon::Normal;
1828 if (!(vopt->state & QStyle::State_Enabled))
1829 mode = QIcon::Disabled;
1830 else if (vopt->state & QStyle::State_Selected)
1831 mode = QIcon::Selected;
1832 QIcon::State state = vopt->state & QStyle::State_Open ? QIcon::On : QIcon::Off;
1833 vopt->icon.paint(painter, iconRect, vopt->decorationAlignment, mode, state);
1836 painter->setPen(highlightCurrent && highContrastTheme ? vopt->palette.base().color()
1837 : vopt->palette.text().color());
1838 d->viewItemDrawText(painter, vopt, textRect);
1841 if (vopt->state & State_Selected) {
1842 if (
const QListView *lv = qobject_cast<
const QListView *>(widget);
1843 lv && lv->viewMode() != QListView::IconMode && !highContrastTheme) {
1844 painter->setPen(vopt->palette.accent().color());
1845 const auto xPos = isRtl ? rect.right() - 1 : rect.left();
1846 const QLineF lines[2] = {
1847 QLineF(xPos, rect.y() + 2, xPos, rect.y() + rect.height() - 2),
1848 QLineF(xPos + 1, rect.y() + 2, xPos + 1, rect.y() + rect.height() - 2),
1850 painter->drawLines(lines, 2);
1857 QWindowsVistaStyle::drawControl(element, option, painter, widget);