308void QWindows11Style::drawComplexControl(ComplexControl control,
const QStyleOptionComplex *option,
309 QPainter *painter,
const QWidget *widget)
const
313 const auto drawTitleBarButton = [&](ComplexControl control, SubControl sc, Icon ico) {
315 const QRect buttonRect = proxy()->subControlRect(control, option, sc, widget);
316 if (buttonRect.isValid()) {
317 const bool hover = option->activeSubControls == sc && isHover(option);
320 painter->setPen(option->palette.color(QPalette::WindowText));
321 painter->drawText(buttonRect, Qt::AlignCenter, fluentIcon(ico));
324 const auto drawTitleBarCloseButton = [&](ComplexControl control, SubControl sc, Icon ico) {
326 const QRect buttonRect = proxy()->subControlRect(control, option, sc, widget);
327 if (buttonRect.isValid()) {
328 const auto state = (option->activeSubControls == sc) ? calcControlState(option)
329 : ControlState::Normal;
333 painter->fillRect(buttonRect, shellCaptionCloseFillColorPrimary);
334 pen = shellCaptionCloseTextFillColorPrimary;
337 painter->fillRect(buttonRect, shellCaptionCloseFillColorSecondary);
338 pen = shellCaptionCloseTextFillColorSecondary;
340 case ControlState::Disabled:
341 case ControlState::Normal:
342 pen = option->palette.color(QPalette::WindowText);
346 painter->drawText(buttonRect, Qt::AlignCenter, fluentIcon(ico));
351 State state = option->state;
352 SubControls sub = option->subControls;
353 State flags = option->state;
354 if (widget && widget->testAttribute(Qt::WA_UnderMouse) && widget->isActiveWindow())
355 flags |= State_MouseOver;
357 QPainterStateGuard psg(
painter);
358 painter->setRenderHint(QPainter::Antialiasing);
359 if (d->transitionsEnabled() && option->styleObject) {
360 if (control == CC_Slider) {
361 if (
const auto *slider = qstyleoption_cast<
const QStyleOptionSlider *>(option)) {
362 QObject *styleObject = option->styleObject;
364 QRectF thumbRect = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
365 const qreal outerRadius = qMin(8.0, (slider->orientation == Qt::Horizontal ? thumbRect.height() / 2.0 : thumbRect.width() / 2.0) - 1);
366 bool isInsideHandle = option->activeSubControls == SC_SliderHandle;
368 bool oldIsInsideHandle = styleObject->property(
"_q_insidehandle").toBool();
369 State oldState = State(styleObject->property(
"_q_stylestate").toInt());
370 SubControls oldActiveControls = SubControls(styleObject->property(
"_q_stylecontrols").toInt());
372 QRectF oldRect = styleObject->property(
"_q_stylerect").toRect();
373 styleObject->setProperty(
"_q_insidehandle", isInsideHandle);
374 styleObject->setProperty(
"_q_stylestate",
int(state));
375 styleObject->setProperty(
"_q_stylecontrols",
int(option->activeSubControls));
376 styleObject->setProperty(
"_q_stylerect", option->rect);
377 if (option->styleObject->property(
"_q_end_radius").isNull())
378 option->styleObject->setProperty(
"_q_end_radius", outerRadius * 0.43);
380 bool doTransition = (((state & State_Sunken) != (oldState & State_Sunken)
381 || (oldIsInsideHandle != isInsideHandle)
382 || (oldActiveControls != option->activeSubControls))
383 && state & State_Enabled);
385 if (oldRect != option->rect) {
386 doTransition =
false;
387 d->stopAnimation(styleObject);
388 styleObject->setProperty(
"_q_inner_radius", outerRadius * 0.43);
392 QNumberStyleAnimation *t =
new QNumberStyleAnimation(styleObject);
393 t->setStartValue(styleObject->property(
"_q_inner_radius").toFloat());
394 t->setEndValue(outerRadius * sliderInnerRadius(state, isInsideHandle));
395 styleObject->setProperty(
"_q_end_radius", t->endValue());
397 t->setStartTime(d->animationTime());
399 d->startAnimation(t);
402 }
else if (control == CC_ScrollBar) {
403 QObject *styleObject = option->styleObject;
404 State oldState = State(styleObject->property(
"_q_stylestate").toInt());
405 const bool wasMouseOver = oldState.testFlag(State_MouseOver);
406 const bool isMouseOver = state.testFlag(State_MouseOver);
408 if (wasMouseOver != isMouseOver) {
409 styleObject->setProperty(
"_q_stylestate",
int(state));
410 auto anim = qobject_cast<QNumberStyleAnimation *>(d->animation(styleObject));
411 constexpr int durationMS = 100;
412 qreal startValue = isMouseOver ? 0 : 1;
413 int curDurationMS = durationMS;
415 startValue = anim->currentValue();
416 curDurationMS = durationMS - (anim->duration() - anim->currentLoopTime());
417 d->stopAnimation(option->styleObject);
419 anim =
new QNumberStyleAnimation(styleObject);
420 anim->setStartValue(startValue);
421 anim->setEndValue(isMouseOver ? 1 : 0);
422 anim->setDuration(curDurationMS);
423 d->startAnimation(anim);
429#if QT_CONFIG(spinbox)
431 if (
const QStyleOptionSpinBox *sb = qstyleoption_cast<
const QStyleOptionSpinBox *>(option)) {
432 QCachedPainter cp(painter, QLatin1StringView(
"win11_spinbox") % HexString<uint8_t>(colorSchemeIndex),
433 sb, sb->rect.size());
434 if (cp.needsPainting()) {
435 const auto frameRect = QRectF(option->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5));
436 drawRoundedRect(cp.painter(), frameRect, Qt::NoPen, inputFillBrush(option, widget));
438 if (sb->frame && (sub & SC_SpinBoxFrame))
439 drawLineEditFrame(cp.painter(), frameRect, option);
441 const auto drawUpDown = [&](QStyle::SubControl sc) {
442 const bool isEnabled = state & QStyle::State_Enabled;
443 const bool isUp = sc == SC_SpinBoxUp;
444 const QRect rect = proxy()->subControlRect(CC_SpinBox, option, sc, widget);
445 if (isEnabled && sb->activeSubControls & sc)
446 drawRoundedRect(cp.painter(), rect.adjusted(1, 1, -1, -2), Qt::NoPen,
447 winUI3Color(subtleHighlightColor));
449 cp->setFont(d->assetFont);
450 cp->setPen(sb->palette.buttonText().color());
451 cp->setBrush(Qt::NoBrush);
452 cp->drawText(rect, Qt::AlignCenter, fluentIcon(isUp ? Icon::ChevronUp : Icon::ChevronDown));
454 if (sub & SC_SpinBoxUp) drawUpDown(SC_SpinBoxUp);
455 if (sub & SC_SpinBoxDown) drawUpDown(SC_SpinBoxDown);
456 if (state & State_KeyboardFocusChange && state & State_HasFocus) {
457 QStyleOptionFocusRect fropt;
458 fropt.QStyleOption::operator=(*option);
459 proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, cp.painter(), widget);
467 if (
const auto *slider = qstyleoption_cast<
const QStyleOptionSlider *>(option)) {
468 const auto &slrect = slider->rect;
469 const bool isHorizontal = slider->orientation == Qt::Horizontal;
470 const QRectF handleRect(proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget));
471 const QPointF handleCenter(handleRect.center());
473 if (sub & SC_SliderGroove) {
474 QRectF rect = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
479 rect = QRectF(rect.left() + 2, rect.center().y() - 2, rect.width() - 2, 4);
480 leftRect = QRectF(rect.left(), rect.top(), handleCenter.x() - rect.left(),
482 rightRect = QRectF(handleCenter.x(), rect.top(),
483 rect.width() - handleCenter.x(),
486 rect = QRect(rect.center().x() - 2, rect.top() + 2, 4, rect.height() - 2);
487 leftRect = QRectF(rect.left(), rect.top(), rect.width(),
488 handleCenter.y() - rect.top());
489 rightRect = QRectF(rect.left(), handleCenter.y(), rect.width(),
490 rect.height() - handleCenter.y());
492 if (slider->upsideDown)
493 qSwap(leftRect, rightRect);
495 painter->setPen(Qt::NoPen);
496 painter->setBrush(calculateAccentColor(option));
497 painter->drawRoundedRect(leftRect,1,1);
498 painter->setBrush(WINUI3Colors[colorSchemeIndex][controlStrongFill]);
499 painter->drawRoundedRect(rightRect,1,1);
501 if (sub & SC_SliderTickmarks) {
502 int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget);
503 int ticks = slider->tickPosition;
504 int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget);
505 int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
506 int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget);
507 int interval = slider->tickInterval;
509 interval = slider->singleStep;
510 if (QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, interval,
512 - QStyle::sliderPositionFromValue(slider->minimum, slider->maximum,
514 interval = slider->pageStep;
519 painter->setPen(slider->palette.text().color());
520 QVarLengthArray<QLineF, 32> lines;
521 int v = slider->minimum;
522 while (v <= slider->maximum + 1) {
523 if (v == slider->maximum + 1 && interval == 1)
525 const int v_ = qMin(v, slider->maximum);
526 int tickLength = (v_ == slider->minimum || v_ >= slider->maximum) ? 4 : 3;
527 int pos = QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, v_,
528 available, slider->upsideDown);
531 if (ticks & QSlider::TicksAbove) {
532 lines.append(QLineF(pos, tickOffset - 0.5,
533 pos, tickOffset - tickLength - 0.5));
536 if (ticks & QSlider::TicksBelow) {
537 lines.append(QLineF(pos, tickOffset + thickness + 0.5,
538 pos, tickOffset + thickness + tickLength + 0.5));
541 if (ticks & QSlider::TicksAbove) {
542 lines.append(QLineF(tickOffset - 0.5, pos,
543 tickOffset - tickLength - 0.5, pos));
546 if (ticks & QSlider::TicksBelow) {
547 lines.append(QLineF(tickOffset + thickness + 0.5, pos,
548 tickOffset + thickness + tickLength + 0.5, pos));
552 int nextInterval = v + interval;
553 if (nextInterval < v)
557 if (!lines.isEmpty()) {
558 QPainterStateGuard psg(painter);
559 painter->translate(slrect.topLeft());
560 painter->drawLines(lines.constData(), lines.size());
563 if (sub & SC_SliderHandle) {
564 const qreal outerRadius = qMin(8.0, (isHorizontal ? handleRect.height() / 2.0 : handleRect.width() / 2.0) - 1);
565 float innerRadius = outerRadius * 0.43;
567 if (option->styleObject) {
568 const QNumberStyleAnimation* animation = qobject_cast<QNumberStyleAnimation *>(d->animation(option->styleObject));
569 if (animation !=
nullptr) {
570 innerRadius = animation->currentValue();
571 option->styleObject->setProperty(
"_q_inner_radius", innerRadius);
573 bool isInsideHandle = option->activeSubControls == SC_SliderHandle;
574 innerRadius = outerRadius * sliderInnerRadius(state, isInsideHandle);
578 painter->setPen(Qt::NoPen);
579 painter->setBrush(winUI3Color(controlFillSolid));
580 painter->drawEllipse(handleCenter, outerRadius, outerRadius);
581 painter->setBrush(calculateAccentColor(option));
582 painter->drawEllipse(handleCenter, innerRadius, innerRadius);
584 painter->setPen(winUI3Color(controlStrokeSecondary));
585 painter->setBrush(Qt::NoBrush);
586 painter->drawEllipse(handleCenter, outerRadius + 0.5, outerRadius + 0.5);
588 if (slider->state & State_HasFocus) {
589 QStyleOptionFocusRect fropt;
590 fropt.QStyleOption::operator=(*slider);
591 fropt.rect = subElementRect(SE_SliderFocusRect, slider, widget);
592 proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
597#if QT_CONFIG(combobox)
599 if (
const QStyleOptionComboBox *combobox = qstyleoption_cast<
const QStyleOptionComboBox *>(option)) {
600 const auto frameRect = QRectF(option->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5));
601 QStyleOption opt(*option);
602 opt.state.setFlag(QStyle::State_On,
false);
603 drawRoundedRect(painter, frameRect, Qt::NoPen,
604 combobox->editable ? inputFillBrush(option, widget)
605 : controlFillBrush(&opt, ControlType::Control));
608 drawLineEditFrame(painter, frameRect, combobox, combobox->editable);
610 const bool hasFocus = state & State_HasFocus;
612 if (sub & SC_ComboBoxArrow) {
613 QRectF rect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget);
614 painter->setFont(d->assetFont);
615 painter->setPen(controlTextColor(option,
true));
616 painter->drawText(rect, Qt::AlignCenter, fluentIcon(Icon::ChevronDownMed));
618 if (state & State_KeyboardFocusChange && hasFocus) {
619 QStyleOptionFocusRect fropt;
620 fropt.QStyleOption::operator=(*option);
621 proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
627 if (
const QStyleOptionSlider *scrollbar = qstyleoption_cast<
const QStyleOptionSlider *>(option)) {
628 const bool vertical = scrollbar->orientation == Qt::Vertical;
629 const bool isMouseOver = state & State_MouseOver;
630 const auto prx = proxy();
632 QPainterStateGuard psg(
painter);
634 const auto anim = qobject_cast<QNumberStyleAnimation *>(d->animation(option->styleObject));
635 qreal widthFactor = isMouseOver ? 1.0 : 0.0;
637 widthFactor = anim->currentValue();
639 if (widthFactor > 0.6) {
640 const bool isRtl = option->direction == Qt::RightToLeft;
642 QFont f = QFont(d->assetFont);
645 painter->setPen(winUI3Color(controlStrongFill));
647 const QRectF rectAdd =
648 prx->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddLine, widget);
649 const auto strAdd = vertical
650 ? Icon::CaretDownSolid8
651 : (isRtl ? Icon::CaretLeftSolid8 : Icon::CaretRightSolid8);
652 painter->drawText(rectAdd, Qt::AlignCenter, fluentIcon(strAdd));
654 const QRectF rectSub =
655 prx->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubLine, widget);
656 const auto strSub = vertical
657 ? Icon::CaretUpSolid8
658 : (isRtl ? Icon::CaretRightSolid8 : Icon::CaretLeftSolid8);
659 painter->drawText(rectSub, Qt::AlignCenter, fluentIcon(strSub));
661 if (sub & SC_ScrollBarSlider) {
662 QRectF rect = prx->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
663 const QPointF center = rect.center();
665 auto w = rect.width() / 2. * widthFactor;
668 const auto ofs = rect.width() / 2 - w;
670 rect.moveCenter(QPointF(center.x() + ofs, center.y()));
673 auto h = rect.height() / 2. * widthFactor;
676 const auto ofs = rect.height() / 2 - h;
678 rect.moveCenter(QPointF(center.x(), center.y() + ofs));
680 drawRoundedRect(painter, rect, Qt::NoPen, winUI3Color(controlStrongFill), 3);
684 case CC_MdiControls:{
685 QFont buttonFont = QFont(d->assetFont);
686 buttonFont.setPointSize(8);
687 painter->setFont(buttonFont);
688 drawTitleBarCloseButton(CC_MdiControls, SC_MdiCloseButton, Icon::ChromeClose);
689 drawTitleBarButton(CC_MdiControls, SC_MdiNormalButton, Icon::ChromeRestore);
690 drawTitleBarButton(CC_MdiControls, SC_MdiMinButton, Icon::ChromeMinimize);
694 if (
const auto* titlebar = qstyleoption_cast<
const QStyleOptionTitleBar*>(option)) {
695 painter->setPen(Qt::NoPen);
696 painter->setPen(WINUI3Colors[colorSchemeIndex][surfaceStroke]);
697 painter->setBrush(titlebar->palette.button());
698 painter->drawRect(titlebar->rect);
701 QRect textRect = proxy()->subControlRect(CC_TitleBar, titlebar, SC_TitleBarLabel, widget);
702 QColor textColor = titlebar->palette.color(titlebar->titleBarState & Qt::WindowActive ? QPalette::Active : QPalette::Disabled,QPalette::WindowText);
703 painter->setPen(textColor);
705 QString title = painter->fontMetrics().elidedText(titlebar->text, Qt::ElideRight, textRect.width() - 14);
706 painter->drawText(textRect.adjusted(1, 1, -1, -1), title, QTextOption(Qt::AlignHCenter | Qt::AlignVCenter));
708 QFont buttonFont = QFont(d->assetFont);
709 buttonFont.setPointSize(8);
710 painter->setFont(buttonFont);
711 auto shouldDrawButton = [titlebar](SubControl sc, Qt::WindowType flag) {
712 return (titlebar->subControls & sc) && (titlebar->titleBarFlags & flag);
716 if (shouldDrawButton(SC_TitleBarMinButton, Qt::WindowMinimizeButtonHint) &&
717 !(titlebar->titleBarState & Qt::WindowMinimized)) {
718 drawTitleBarButton(CC_TitleBar, SC_TitleBarMinButton, Icon::ChromeMinimize);
722 if (shouldDrawButton(SC_TitleBarMaxButton, Qt::WindowMaximizeButtonHint) &&
723 !(titlebar->titleBarState & Qt::WindowMaximized)) {
724 drawTitleBarButton(CC_TitleBar, SC_TitleBarMaxButton, Icon::ChromeMaximize);
728 if (shouldDrawButton(SC_TitleBarCloseButton, Qt::WindowSystemMenuHint))
729 drawTitleBarCloseButton(CC_TitleBar, SC_TitleBarCloseButton, Icon::ChromeClose);
732 if ((titlebar->subControls & SC_TitleBarNormalButton) &&
733 (((titlebar->titleBarFlags & Qt::WindowMinimizeButtonHint) &&
734 (titlebar->titleBarState & Qt::WindowMinimized)) ||
735 ((titlebar->titleBarFlags & Qt::WindowMaximizeButtonHint) &&
736 (titlebar->titleBarState & Qt::WindowMaximized)))) {
737 drawTitleBarButton(CC_TitleBar, SC_TitleBarNormalButton, Icon::ChromeRestore);
741 if (shouldDrawButton(SC_TitleBarContextHelpButton, Qt::WindowContextHelpButtonHint))
742 drawTitleBarButton(CC_TitleBar, SC_TitleBarContextHelpButton, Icon::Help);
745 if (shouldDrawButton(SC_TitleBarShadeButton, Qt::WindowShadeButtonHint))
746 drawTitleBarButton(CC_TitleBar, SC_TitleBarShadeButton, Icon::ChevronUpSmall);
749 if (shouldDrawButton(SC_TitleBarUnshadeButton, Qt::WindowShadeButtonHint))
750 drawTitleBarButton(CC_TitleBar, SC_TitleBarUnshadeButton, Icon::ChevronDownSmall);
753 if (shouldDrawButton(SC_TitleBarSysMenu, Qt::WindowSystemMenuHint)) {
754 const QRect iconRect = proxy()->subControlRect(CC_TitleBar, titlebar, SC_TitleBarSysMenu, widget);
755 if (iconRect.isValid()) {
756 if (!titlebar->icon.isNull()) {
757 titlebar->icon.paint(painter, iconRect);
759 QStyleOption tool = *titlebar;
760 const auto extent = proxy()->pixelMetric(PM_SmallIconSize, &tool, widget);
761 const auto dpr = QStyleHelper::getDpr(widget);
762 const auto icon = proxy()->standardIcon(SP_TitleBarMenuButton, &tool, widget);
763 const auto pm = icon.pixmap(QSize(extent, extent), dpr);
764 proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pm);
770#if QT_CONFIG(toolbutton)
772 if (
const auto toolbutton = qstyleoption_cast<
const QStyleOptionToolButton *>(option)) {
774 const bool isSplitButton =
775 toolbutton->features.testFlag(QStyleOptionToolButton::MenuButtonPopup);
776 const auto fw = prx->pixelMetric(PM_DefaultFrameWidth, option, widget);
777 const auto buttonRect = prx->subControlRect(control, toolbutton, SC_ToolButton, widget);
778 const auto menuareaRect = isSplitButton
779 ? prx->subControlRect(control, toolbutton, SC_ToolButtonMenu, widget)
782 State bflags = toolbutton->state;
783 State mflags = toolbutton->state;
784 if (toolbutton->activeSubControls.testFlag(SC_ToolButton)) {
785 mflags &= ~(State_Sunken | State_MouseOver);
786 if (bflags.testFlag(State_Sunken))
787 mflags |= State_Raised;
789 if (toolbutton->activeSubControls.testFlag(SC_ToolButtonMenu)) {
790 bflags &= ~(State_Sunken | State_MouseOver);
791 if (mflags.testFlag(State_Sunken))
792 bflags |= State_Raised;
795 QStyleOption tool = *toolbutton;
796 if (toolbutton->subControls.testFlag(SC_ToolButton)) {
797 QPainterStateGuard psg(painter);
799 painter->setClipRect(buttonRect);
801 prx->drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
803 if (state.testFlag(State_Enabled)) {
804 painter->setPen(winUI3Color(controlStrokePrimary));
805 const auto top = buttonRect.topRight() + QPoint(0, fw + 1);
806 const auto btm = buttonRect.bottomRight() - QPoint(0, fw);
807 painter->drawLine(top, btm);
812 if (toolbutton->state.testFlag(State_HasFocus)) {
813 QStyleOptionFocusRect fr;
814 fr.QStyleOption::operator=(*toolbutton);
815 prx->drawPrimitive(PE_FrameFocusRect, &fr, painter, widget);
817 QStyleOptionToolButton label = *toolbutton;
818 label.state = bflags;
819 label.rect = buttonRect.marginsRemoved(QMargins(fw, fw, fw, fw));
820 prx->drawControl(CE_ToolButtonLabel, &label, painter, widget);
822 if (toolbutton->subControls.testFlag(SC_ToolButtonMenu)) {
823 QPainterStateGuard psg(painter);
824 painter->setClipRect(menuareaRect);
826 prx->drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
828 const int fontSize = painter->font().pointSize();
829 QFont f(d->assetFont);
830 f.setPointSize(qRound(fontSize * 0.9f));
832 painter->setPen(controlTextColor(option));
833 const QRect textRect(menuareaRect.topLeft(), menuareaRect.size() - QSize(fw, 0));
834 painter->drawText(textRect, Qt::AlignCenter, fluentIcon(Icon::ChevronDownMed));
836 }
else if (toolbutton->features.testFlag(QStyleOptionToolButton::HasMenu)) {
837 const int mbi = prx->pixelMetric(PM_MenuButtonIndicator, toolbutton, widget);
838 const QRect &ir = toolbutton->rect;
839 QRect rect(ir.right() + 5 - mbi, ir.y() + ir.height() - mbi + 4, mbi - 6 - fw,
841 rect = visualRect(toolbutton->direction, buttonRect, rect);
842 painter->setFont(QFont(d->assetFont));
843 painter->setPen(controlTextColor(option));
844 painter->drawText(rect, Qt::AlignCenter, fluentIcon(Icon::ChevronDownMed));
850 QWindowsVistaStyle::drawComplexControl(control, option, painter, widget);
854void QWindows11Style::drawPrimitive(PrimitiveElement element,
const QStyleOption *option,
856 const QWidget *widget)
const {
859 const State state = option->state;
860 QPainterStateGuard psg(
painter);
861 painter->setRenderHint(QPainter::Antialiasing);
862 if (d->transitionsEnabled() && option->styleObject && (element == PE_IndicatorCheckBox || element == PE_IndicatorRadioButton)) {
863 QObject *styleObject = option->styleObject;
864 int oldState = styleObject->property(
"_q_stylestate").toInt();
865 styleObject->setProperty(
"_q_stylestate",
int(option->state));
866 styleObject->setProperty(
"_q_stylerect", option->rect);
867 bool doTransition = (((state & State_Sunken) != (oldState & State_Sunken)
868 || ((state & State_MouseOver) != (oldState & State_MouseOver))
869 || (state & State_On) != (oldState & State_On))
870 && state & State_Enabled);
872 if (element == PE_IndicatorRadioButton) {
873 QNumberStyleAnimation *t =
new QNumberStyleAnimation(styleObject);
874 t->setStartValue(styleObject->property(
"_q_inner_radius").toFloat());
875 t->setEndValue(radioButtonInnerRadius(state));
876 styleObject->setProperty(
"_q_end_radius", t->endValue());
877 t->setStartTime(d->animationTime());
879 d->startAnimation(t);
881 else if (element == PE_IndicatorCheckBox) {
882 if ((oldState & State_Off && state & State_On) || (oldState & State_NoChange && state & State_On)) {
883 QNumberStyleAnimation *t =
new QNumberStyleAnimation(styleObject);
884 t->setStartValue(0.0f);
885 t->setEndValue(1.0f);
886 t->setStartTime(d->animationTime());
888 d->startAnimation(t);
895 case PE_IndicatorArrowUp:
896 case PE_IndicatorArrowDown:
897 case PE_IndicatorArrowRight:
898 case PE_IndicatorArrowLeft: {
899 const QRect &r = option->rect;
900 if (r.width() <= 1 || r.height() <= 1)
902 Icon ico = Icon::Help;
904 case PE_IndicatorArrowUp:
905 ico = Icon::ChevronUpMed;
907 case PE_IndicatorArrowDown:
908 ico = Icon::ChevronDownMed;
910 case PE_IndicatorArrowLeft:
911 ico = Icon::ChevronLeftMed;
913 case PE_IndicatorArrowRight:
914 ico = Icon::ChevronRightMed;
919 QPainterStateGuard psg(
painter);
920 if (option->state.testFlag(State_Sunken)) {
921 const auto bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal, option, widget);
922 const auto bsy = proxy()->pixelMetric(PM_ButtonShiftVertical, option, widget);
923 if (bsx != 0 || bsy != 0)
924 painter->translate(bsx, bsy);
926 painter->setFont(d->assetFont);
927 painter->setPen(option->palette.buttonText().color());
928 painter->setBrush(option->palette.buttonText());
929 painter->drawText(option->rect, Qt::AlignCenter, fluentIcon(ico));
932 case PE_FrameFocusRect: {
933 if (
const QStyleOptionFocusRect *fropt = qstyleoption_cast<
const QStyleOptionFocusRect *>(option)) {
934 if (!(fropt->state & State_KeyboardFocusChange))
936 QRectF focusRect = option->rect;
937 focusRect = focusRect.marginsRemoved(QMarginsF(1.5,1.5,1.5,1.5));
938 painter->setPen(winUI3Color(focusFrameInnerStroke));
939 painter->drawRoundedRect(focusRect,4,4);
941 focusRect = focusRect.marginsAdded(QMarginsF(1.0,1.0,1.0,1.0));
942 painter->setPen(QPen(winUI3Color(focusFrameOuterStroke),1));
943 painter->drawRoundedRect(focusRect,4,4);
947 case PE_PanelTipLabel: {
948 const auto rect = QRectF(option->rect).marginsRemoved(QMarginsF(0.5, 0.5, 0.5, 0.5));
949 const auto pen = highContrastTheme ? option->palette.buttonText().color()
950 : winUI3Color(frameColorLight);
951 drawRoundedRect(painter, rect, pen, option->palette.toolTipBase());
954 case PE_FrameTabWidget:
955#if QT_CONFIG(tabwidget)
956 if (
const QStyleOptionTabWidgetFrame *frame = qstyleoption_cast<
const QStyleOptionTabWidgetFrame *>(option)) {
957 QPainterStateGuard psg(painter);
958 const auto clipRegion = painter->clipRegion();
960 painter->setPen(highContrastTheme ? frame->palette.buttonText().color()
961 : winUI3Color(frameColorLight));
962 painter->setBrush(frame->palette.base());
964 const auto &rect = option->rect;
965 QRect upperRect = rect;
966 upperRect.setHeight(rect.height() / 2);
967 QRect lowerRect = rect;
968 lowerRect.setY(lowerRect.y() + rect.height() / 2);
969 painter->setClipRegion(clipRegion.isNull() ? upperRect : clipRegion & upperRect);
970 painter->drawRect(rect);
971 painter->setClipRegion(clipRegion.isNull() ? lowerRect : clipRegion & lowerRect);
972 painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
977 case PE_FrameGroupBox:
978 if (
const QStyleOptionFrame *frame = qstyleoption_cast<
const QStyleOptionFrame *>(option)) {
979 const auto pen = highContrastTheme ? frame->palette.buttonText().color()
980 : winUI3Color(frameColorStrong);
981 if (frame->features & QStyleOptionFrame::Flat) {
982 painter->setBrush(Qt::NoBrush);
983 painter->setPen(pen);
984 const QRect &fr = frame->rect;
985 QPoint p1(fr.x(), fr.y() + 1);
986 QPoint p2(fr.x() + fr.width(), p1.y());
987 painter->drawLine(p1, p2);
989 const auto frameRect = QRectF(frame->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5));
990 drawRoundedRect(painter, frameRect, pen, Qt::NoBrush);
994 case PE_IndicatorHeaderArrow:
995 if (
const QStyleOptionHeader *header = qstyleoption_cast<
const QStyleOptionHeader *>(option)) {
996 const auto indicator = header->sortIndicator;
997 if (indicator != QStyleOptionHeader::None) {
998 QPainterStateGuard psg(
painter);
999 QFont f(d->assetFont);
1001 painter->setFont(f);
1002 painter->setPen(header->palette.text().color());
1003 const auto ico = indicator == QStyleOptionHeader::SortUp ? Icon::ChevronDown
1005 painter->drawText(option->rect, Qt::AlignCenter, fluentIcon(ico));
1009 case PE_IndicatorCheckBox: {
1010 const bool isOn = option->state & State_On;
1011 const bool isPartial = option->state & State_NoChange;
1013 const QRectF rect = option->rect;
1014 const QPointF center = rect.center();
1016 drawRoundedRect(painter, option->rect, borderPenControlAlt(option),
1017 controlFillBrush(option, ControlType::ControlAlt));
1020 painter->setFont(d->assetFont);
1021 painter->setPen(controlTextColor(option));
1022 const auto *animation =
1023 qobject_cast<QNumberStyleAnimation *>(d->animation(option->styleObject));
1024 const qreal clipWidth = animation ? animation->currentValue() : 1.0;
1025 const QString str = fluentIcon(Icon::AcceptMedium);
1026 QFontMetrics fm(d->assetFont);
1027 QRectF clipRect = fm.boundingRect(str);
1028 clipRect.moveCenter(center);
1029 clipRect.setLeft(rect.x() + (rect.width() - clipRect.width()) / 2.0 + 0.5);
1030 clipRect.setWidth(clipWidth * clipRect.width());
1031 painter->drawText(clipRect, Qt::AlignVCenter | Qt::AlignLeft, str);
1032 }
else if (isPartial) {
1033 QFont f(d->assetFont);
1035 painter->setFont(f);
1036 painter->setPen(controlTextColor(option));
1037 painter->drawText(rect, Qt::AlignCenter, fluentIcon(Icon::Dash12));
1041 case PE_IndicatorBranch: {
1042 if (option->state & State_Children) {
1043 const QStyleOptionViewItem *vopt = qstyleoption_cast<
const QStyleOptionViewItem *>(option);
1044 const bool isReverse = option->direction == Qt::RightToLeft;
1045 const bool isOpen = option->state & QStyle::State_Open;
1046 const QAbstractItemView *view = qobject_cast<
const QAbstractItemView *>(widget);
1047 QFont f(d->assetFont);
1049 painter->setFont(f);
1050 if (view && view->alternatingRowColors() && vopt && vopt->state & State_Selected)
1051 painter->setPen(winUI3Color(textOnAccentPrimary));
1053 painter->setPen(option->palette.color(isOpen ? QPalette::Active : QPalette::Disabled,
1054 QPalette::WindowText));
1055 const auto ico = isOpen ? Icon::ChevronDownMed
1056 : (isReverse ? Icon::ChevronLeftMed
1057 : Icon::ChevronRightMed);
1058 painter->drawText(option->rect, Qt::AlignCenter, fluentIcon(ico));
1062 case PE_IndicatorRadioButton: {
1063 const auto *animation =
1064 qobject_cast<QNumberStyleAnimation *>(d->animation(option->styleObject));
1065 const qreal innerRadius =
1066 animation ? animation->currentValue() : radioButtonInnerRadius(state);
1067 const QRectF rect = option->rect;
1068 const QPointF center = rect.center();
1070 if (option->styleObject)
1071 option->styleObject->setProperty(
"_q_inner_radius", innerRadius);
1072 painter->setPen(borderPenControlAlt(option));
1073 painter->setBrush(controlFillBrush(option, ControlType::ControlAlt));
1074 if (option->state.testFlag(State_On)) {
1076 path.addEllipse(center, 7.5, 7.5);
1077 path.addEllipse(center, innerRadius, innerRadius);
1078 painter->drawPath(path);
1080 painter->setBrush(option->palette.window().color());
1081 painter->drawEllipse(center, innerRadius, innerRadius);
1083 painter->drawEllipse(center, 7.5, 7.5);
1087 case PE_PanelButtonTool:
1088 case PE_PanelButtonBevel:{
1089 const bool isEnabled = state & QStyle::State_Enabled;
1090 const bool isMouseOver = state & QStyle::State_MouseOver;
1091 const bool isRaised = state & QStyle::State_Raised;
1092 const int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget);
1093 const QRectF rect = option->rect.marginsRemoved(QMargins(fw, fw, fw, fw));
1094 if (element == PE_PanelButtonTool && ((!isMouseOver && !isRaised) || !isEnabled))
1095 painter->setPen(Qt::NoPen);
1097 painter->setPen(winUI3Color(controlStrokePrimary));
1098 painter->setBrush(controlFillBrush(option, ControlType::Control));
1099 if (element == PE_PanelButtonTool && widget) {
1100 const auto name = widget->objectName();
1101 if (name ==
"ScrollLeftButton"_L1 || name ==
"ScrollRightButton"_L1) {
1102 painter->setPen(Qt::NoPen);
1104 painter->setBrush(controlFillBrush(option, ControlType::ControlAlt));
1106 painter->setBrush(Qt::NoBrush);
1109 painter->drawRoundedRect(rect,
1110 secondLevelRoundingRadius, secondLevelRoundingRadius);
1113 case PE_FrameDefaultButton:
1114 painter->setPen(option->palette.accent().color());
1115 painter->setBrush(Qt::NoBrush);
1116 painter->drawRoundedRect(option->rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
1120 case PE_PanelMenu: {
1121 if (!d->nativeRoundedTopLevelWindows) {
1122 const QRect rect = option->rect.marginsRemoved(QMargins(2, 2, 2, 2));
1123 painter->setPen(highContrastTheme ? QPen(option->palette.windowText().color(), 2)
1124 : winUI3Color(frameColorLight));
1125 painter->setBrush(winUI3Color(menuPanelFill));
1126 painter->drawRoundedRect(rect, topLevelRoundingRadius, topLevelRoundingRadius);
1130 case PE_PanelLineEdit:
1131 if (
const auto *panel = qstyleoption_cast<
const QStyleOptionFrame *>(option)) {
1132 const bool isInSpinBox =
1133 widget && qobject_cast<
const QAbstractSpinBox *>(widget->parent()) !=
nullptr;
1134 const bool isInComboBox =
1135 widget && qobject_cast<
const QComboBox *>(widget->parent()) !=
nullptr;
1136 if (!isInSpinBox && !isInComboBox) {
1137 const auto frameRect =
1138 QRectF(option->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5));
1139 drawRoundedRect(painter, frameRect, Qt::NoPen, inputFillBrush(option, widget));
1140 if (panel->lineWidth > 0)
1141 proxy()->drawPrimitive(PE_FrameLineEdit, panel, painter, widget);
1145 case PE_FrameLineEdit: {
1146 const auto frameRect = QRectF(option->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5));
1147 drawLineEditFrame(painter, frameRect, option);
1148 if (state & State_KeyboardFocusChange && state & State_HasFocus) {
1149 QStyleOptionFocusRect fropt;
1150 fropt.QStyleOption::operator=(*option);
1151 proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
1156 if (
const auto *frame = qstyleoption_cast<
const QStyleOptionFrame *>(option)) {
1157 const auto rect = QRectF(option->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5));
1158 if (qobject_cast<
const QComboBoxPrivateContainer *>(widget)) {
1159 if (d->nativeRoundedTopLevelWindows)
1162 if (highContrastTheme)
1163 pen = QPen(option->palette.windowText().color(), 2);
1166 drawRoundedRect(painter, rect, pen, WINUI3Colors[colorSchemeIndex][menuPanelFill]);
1168 drawRoundedRect(painter, rect, Qt::NoPen, option->palette.brush(QPalette::Base));
1170 if (frame->frameShape == QFrame::NoFrame)
1173 const bool isEditable = qobject_cast<
const QTextEdit *>(widget) !=
nullptr
1174 || qobject_cast<
const QPlainTextEdit *>(widget) !=
nullptr;
1175 drawLineEditFrame(painter, rect, option, isEditable);
1179 case PE_PanelItemViewItem:
1180 if (
const QStyleOptionViewItem *vopt = qstyleoption_cast<
const QStyleOptionViewItem *>(option)) {
1181 if (vopt->backgroundBrush.style() != Qt::NoBrush) {
1182 QPainterStateGuard psg(
painter);
1183 painter->setBrushOrigin(vopt->rect.topLeft());
1184 painter->fillRect(vopt->rect, vopt->backgroundBrush);
1188 case PE_PanelItemViewRow:
1189 if (
const QStyleOptionViewItem *vopt = qstyleoption_cast<
const QStyleOptionViewItem *>(option)) {
1193 const QRect &rect = vopt->rect;
1194 const bool isRtl = option->direction == Qt::RightToLeft;
1195 if (rect.width() <= 0)
1198 if (vopt->features & QStyleOptionViewItem::Alternate) {
1199 QPalette::ColorGroup cg =
1200 (widget ? widget->isEnabled() : (vopt->state & QStyle::State_Enabled))
1202 : QPalette::Disabled;
1203 if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active))
1204 cg = QPalette::Inactive;
1205 painter->fillRect(rect, option->palette.brush(cg, QPalette::AlternateBase));
1208 if (option->state & State_Selected && !highContrastTheme) {
1210 if (!qobject_cast<
const QTableView *>(widget)) {
1211 const auto col = option->palette.accent().color();
1212 painter->setBrush(col);
1213 painter->setPen(col);
1214 const auto xPos = isRtl ? rect.right() - 4.5f : rect.left() + 3.5f;
1215 const auto yOfs = rect.height() / 4.;
1216 QRectF r(
QPointF(xPos, rect.y() + yOfs),
1217 QPointF(xPos + 1, rect.y() + rect.height() - yOfs));
1218 painter->drawRoundedRect(r, 1, 1);
1222 const bool isTreeDecoration = vopt->features.testFlag(
1223 QStyleOptionViewItem::IsDecorationForRootColumn);
1224 if (isTreeDecoration && vopt->state.testAnyFlags(State_Selected | State_MouseOver) &&
1225 vopt->showDecorationSelected) {
1226 const bool onlyOne = vopt->viewItemPosition == QStyleOptionViewItem::OnlyOne ||
1227 vopt->viewItemPosition == QStyleOptionViewItem::Invalid;
1228 bool isFirst = vopt->viewItemPosition == QStyleOptionViewItem::Beginning;
1229 bool isLast = vopt->viewItemPosition == QStyleOptionViewItem::End;
1239 const QAbstractItemView *view = qobject_cast<
const QAbstractItemView *>(widget);
1240 painter->setBrush(view->alternatingRowColors() && state & State_Selected ? calculateAccentColor(option) : WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
1241 painter->setPen(Qt::NoPen);
1243 QPainterStateGuard psg(
painter);
1244 painter->setClipRect(rect);
1245 painter->drawRoundedRect(rect.marginsRemoved(QMargins(2, 2, -secondLevelRoundingRadius, 2)),
1246 secondLevelRoundingRadius, secondLevelRoundingRadius);
1247 }
else if (isLast) {
1248 QPainterStateGuard psg(
painter);
1249 painter->setClipRect(rect);
1250 painter->drawRoundedRect(rect.marginsRemoved(QMargins(-secondLevelRoundingRadius, 2, 2, 2)),
1251 secondLevelRoundingRadius, secondLevelRoundingRadius);
1253 painter->drawRect(vopt->rect.marginsRemoved(QMargins(0, 2, 0, 2)));
1258 case QStyle::PE_Widget: {
1259 if (widget && widget->palette().isBrushSet(QPalette::Active, widget->backgroundRole())) {
1260 const QBrush bg = widget->palette().brush(widget->backgroundRole());
1261 auto wp = QWidgetPrivate::get(widget);
1262 QPainterStateGuard psg(
painter);
1263 wp->updateBrushOrigin(painter, bg);
1264 painter->fillRect(option->rect, bg);
1268 case QStyle::PE_FrameWindow:
1269 if (
const auto *frm = qstyleoption_cast<
const QStyleOptionFrame *>(option)) {
1271 QRectF rect= option->rect;
1272 int fwidth =
int((frm->lineWidth + frm->midLineWidth) / QWindowsStylePrivate::nativeMetricScaleFactor(widget));
1274 QRectF bottomLeftCorner = QRectF(rect.left() + 1.0,
1275 rect.bottom() - 1.0 - secondLevelRoundingRadius,
1276 secondLevelRoundingRadius,
1277 secondLevelRoundingRadius);
1278 QRectF bottomRightCorner = QRectF(rect.right() - 1.0 - secondLevelRoundingRadius,
1279 rect.bottom() - 1.0 - secondLevelRoundingRadius,
1280 secondLevelRoundingRadius,
1281 secondLevelRoundingRadius);
1284 if (widget !=
nullptr) {
1285 QBitmap mask(widget->width(), widget->height());
1289 maskPainter.setRenderHint(QPainter::Antialiasing);
1290 maskPainter.setBrush(Qt::color1);
1291 maskPainter.setPen(Qt::NoPen);
1292 maskPainter.drawRoundedRect(option->rect,secondLevelRoundingRadius,secondLevelRoundingRadius);
1293 const_cast<QWidget*>(widget)->setMask(mask);
1297 painter->setPen(QPen(frm->palette.base(), fwidth));
1298 painter->drawLine(QPointF(rect.left(), rect.top()),
1299 QPointF(rect.left(), rect.bottom() - fwidth));
1300 painter->drawLine(QPointF(rect.left() + fwidth, rect.bottom()),
1301 QPointF(rect.right() - fwidth, rect.bottom()));
1302 painter->drawLine(QPointF(rect.right(), rect.top()),
1303 QPointF(rect.right(), rect.bottom() - fwidth));
1305 painter->setPen(WINUI3Colors[colorSchemeIndex][surfaceStroke]);
1306 painter->drawLine(QPointF(rect.left() + 0.5, rect.top() + 0.5),
1307 QPointF(rect.left() + 0.5, rect.bottom() - 0.5 - secondLevelRoundingRadius));
1308 painter->drawLine(QPointF(rect.left() + 0.5 + secondLevelRoundingRadius, rect.bottom() - 0.5),
1309 QPointF(rect.right() - 0.5 - secondLevelRoundingRadius, rect.bottom() - 0.5));
1310 painter->drawLine(QPointF(rect.right() - 0.5, rect.top() + 1.5),
1311 QPointF(rect.right() - 0.5, rect.bottom() - 0.5 - secondLevelRoundingRadius));
1313 painter->setPen(Qt::NoPen);
1314 painter->setBrush(frm->palette.base());
1315 painter->drawPie(bottomRightCorner.marginsAdded(QMarginsF(2.5,2.5,0.0,0.0)),
1317 painter->drawPie(bottomLeftCorner.marginsAdded(QMarginsF(0.0,2.5,2.5,0.0)),
1320 painter->setPen(WINUI3Colors[colorSchemeIndex][surfaceStroke]);
1321 painter->setBrush(Qt::NoBrush);
1322 painter->drawArc(bottomRightCorner,
1324 painter->drawArc(bottomLeftCorner,
1328#if QT_CONFIG(tabbar)
1329 case PE_FrameTabBarBase:
1330 if (
const auto *tab = qstyleoption_cast<
const QStyleOptionTabBarBase *>(option)) {
1331 QPainterStateGuard psg(painter, QPainterStateGuard::InitialState::NoSave);
1332 const auto clipRegion = painter->clipRegion();
1334 painter->setPen(highContrastTheme ? tab->palette.buttonText().color()
1335 : winUI3Color(frameColorLight));
1336 painter->setBrush(tab->palette.base());
1337 QRect upperRect = tab->rect;
1338 upperRect.setHeight(tab->rect.height() / 2);
1339 QRect lowerRect = tab->rect;
1340 lowerRect.setY(lowerRect.y() + tab->rect.height() / 2);
1341 painter->setClipRegion(clipRegion.isNull() ? upperRect : clipRegion & upperRect);
1342 painter->drawRoundedRect(tab->rect, secondLevelRoundingRadius,
1343 secondLevelRoundingRadius);
1344 painter->setClipRegion(clipRegion.isNull() ? lowerRect : clipRegion & lowerRect);
1345 painter->drawRect(tab->rect);
1349 case PE_IndicatorTabTearLeft:
1350 case PE_IndicatorTabTearRight:
1353 QWindowsVistaStyle::drawPrimitive(element, option, painter, widget);
1360void QWindows11Style::drawControl(ControlElement element,
const QStyleOption *option,
1361 QPainter *painter,
const QWidget *widget)
const
1363 Q_D(
const QWindows11Style);
1364 State flags = option->state;
1366 QPainterStateGuard psg(
painter);
1367 painter->setRenderHint(QPainter::Antialiasing);
1369 case QStyle::CE_ComboBoxLabel:
1370#if QT_CONFIG(combobox)
1371 if (
const QStyleOptionComboBox *cb = qstyleoption_cast<
const QStyleOptionComboBox *>(option)) {
1372 painter->setPen(controlTextColor(option,
true));
1373 QStyleOptionComboBox newOption = *cb;
1374 newOption.rect.adjust(4,0,-4,0);
1375 QCommonStyle::drawControl(element, &newOption, painter, widget);
1379#if QT_CONFIG(tabbar)
1380 case CE_TabBarTabShape:
1381 if (
const QStyleOptionTab *tab = qstyleoption_cast<
const QStyleOptionTab *>(option)) {
1382 QPainterStateGuard psg(painter, QPainterStateGuard::InitialState::NoSave);
1383 const bool isSelected = tab->state.testFlag(State_Selected);
1384 const auto clipRegion = painter->clipRegion();
1385 const bool onlyOne = tab->position == QStyleOptionTab::OnlyOneTab
1386 || tab->position == QStyleOptionTab::Moving;
1387 auto leftMargin = (tab->position == QStyleOptionTab::Beginning || onlyOne) ? 1 : 0;
1388 auto rightMargin = (tab->position == QStyleOptionTab::End || onlyOne) ? 1 : 0;
1389 if (QCommonStylePrivate::rtl(option))
1390 std::swap(leftMargin, rightMargin);
1392 QRectF tabRect = tab->rect.marginsRemoved(QMargins(leftMargin, 1, rightMargin, -3));
1393 painter->setPen(highContrastTheme ? tab->palette.buttonText().color() : winUI3Color(frameColorLight));
1394 painter->setBrush(tab->palette.base());
1396 painter->setBrush(winUI3Color(fillMicaAltDefault));
1398 if (tab->state.testFlag(State_Sunken))
1399 painter->setBrush(winUI3Color(fillMicaAltDefault));
1400 else if (tab->state.testFlag(State_MouseOver))
1401 painter->setBrush(winUI3Color(fillMicaAltSecondary));
1403 painter->setBrush(winUI3Color(fillMicaAltTransparent));
1405 QRect upperRect = tab->rect;
1406 upperRect.setHeight(tab->rect.height() / 2.);
1407 QRect lowerRect = tab->rect;
1408 lowerRect.setY(lowerRect.y() + tab->rect.height() / 2.);
1409 painter->setClipRegion(clipRegion.isNull() ? upperRect : clipRegion & upperRect);
1410 painter->drawRoundedRect(tabRect, secondLevelRoundingRadius, secondLevelRoundingRadius);
1411 painter->setClipRegion(clipRegion.isNull() ? lowerRect : clipRegion & lowerRect);
1412 painter->drawRect(tabRect);
1415 case CE_TabBarTabLabel:
1416 if (
const QStyleOptionTab *tab = qstyleoption_cast<
const QStyleOptionTab *>(option)) {
1417 const bool isEnabled = tab->state.testFlags(State_Enabled);
1418 const bool isSelected = tab->state.testFlags(State_Selected);
1420 QRect tr = tab->rect;
1421 bool verticalTabs = tab->shape == QTabBar::RoundedEast
1422 || tab->shape == QTabBar::RoundedWest || tab->shape == QTabBar::TriangularEast
1423 || tab->shape == QTabBar::TriangularWest;
1425 int alignment = Qt::AlignCenter | Qt::TextShowMnemonic;
1426 if (!proxy()->styleHint(SH_UnderlineShortcut, option, widget))
1427 alignment |= Qt::TextHideMnemonic;
1429 QPainterStateGuard psg(painter, QPainterStateGuard::InitialState::NoSave);
1432 int newX, newY, newRot;
1433 if (tab->shape == QTabBar::RoundedEast || tab->shape == QTabBar::TriangularEast) {
1434 newX = tr.width() + tr.x();
1439 newY = tr.y() + tr.height();
1442 QTransform m = QTransform::fromTranslate(newX, newY);
1444 painter->setTransform(m,
true);
1447 d->tabLayout(tab, widget, &tr, &iconRect);
1450 if (tab->position != QStyleOptionTab::TabPosition::Moving)
1451 tr = proxy()->subElementRect(SE_TabBarTabText, option, widget);
1453 if (!tab->icon.isNull()) {
1454 const auto mode = isEnabled ? QIcon::Normal : QIcon::Disabled;
1455 const auto state = isSelected ? QIcon::On : QIcon::Off;
1456 tab->icon.paint(painter, iconRect, Qt::AlignCenter, mode, state);
1459 painter->setPen(winUI3Color(isSelected ? textPrimary : textSecondary));
1460 proxy()->drawItemText(painter, tr, alignment, tab->palette, isEnabled, tab->text);
1464 case CE_ToolButtonLabel:
1465#if QT_CONFIG(toolbutton)
1466 if (
const QStyleOptionToolButton *toolbutton
1467 = qstyleoption_cast<
const QStyleOptionToolButton *>(option)) {
1468 QRect rect = toolbutton->rect;
1471 if (toolbutton->state & (State_Sunken | State_On)) {
1472 shiftX = proxy()->pixelMetric(PM_ButtonShiftHorizontal, toolbutton, widget);
1473 shiftY = proxy()->pixelMetric(PM_ButtonShiftVertical, toolbutton, widget);
1476 bool hasArrow = toolbutton->features & QStyleOptionToolButton::Arrow;
1477 if (((!hasArrow && toolbutton->icon.isNull()) && !toolbutton->text.isEmpty())
1478 || toolbutton->toolButtonStyle == Qt::ToolButtonTextOnly) {
1479 int alignment = Qt::AlignCenter | Qt::TextShowMnemonic;
1480 if (!proxy()->styleHint(SH_UnderlineShortcut, toolbutton, widget))
1481 alignment |= Qt::TextHideMnemonic;
1482 rect.translate(shiftX, shiftY);
1483 painter->setFont(toolbutton->font);
1484 const QString text = d->toolButtonElideText(toolbutton, rect, alignment);
1485 painter->setPen(controlTextColor(option));
1486 proxy()->drawItemText(painter, rect, alignment, toolbutton->palette,
1487 toolbutton->state & State_Enabled, text);
1490 QSize pmSize = toolbutton->iconSize;
1491 if (!toolbutton->icon.isNull()) {
1492 QIcon::State state = toolbutton->state & State_On ? QIcon::On : QIcon::Off;
1494 if (!(toolbutton->state & State_Enabled))
1495 mode = QIcon::Disabled;
1496 else if ((toolbutton->state & State_MouseOver) && (toolbutton->state & State_AutoRaise))
1497 mode = QIcon::Active;
1499 mode = QIcon::Normal;
1500 pm = toolbutton->icon.pixmap(toolbutton->rect.size().boundedTo(toolbutton->iconSize), painter->device()->devicePixelRatio(),
1502 pmSize = pm.size() / pm.devicePixelRatio();
1505 if (toolbutton->toolButtonStyle != Qt::ToolButtonIconOnly) {
1506 painter->setFont(toolbutton->font);
1509 int alignment = Qt::TextShowMnemonic;
1510 if (!proxy()->styleHint(SH_UnderlineShortcut, toolbutton, widget))
1511 alignment |= Qt::TextHideMnemonic;
1513 if (toolbutton->toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
1514 pr.setHeight(pmSize.height() + 4);
1515 tr.adjust(0, pr.height() - 1, 0, -1);
1516 pr.translate(shiftX, shiftY);
1518 proxy()->drawItemPixmap(painter, pr, Qt::AlignCenter, pm);
1520 drawArrow(proxy(), toolbutton, pr, painter, widget);
1522 alignment |= Qt::AlignCenter;
1524 pr.setWidth(pmSize.width() + 4);
1525 tr.adjust(pr.width(), 0, 0, 0);
1526 pr.translate(shiftX, shiftY);
1528 proxy()->drawItemPixmap(painter, QStyle::visualRect(toolbutton->direction, rect, pr), Qt::AlignCenter, pm);
1530 drawArrow(proxy(), toolbutton, pr, painter, widget);
1532 alignment |= Qt::AlignLeft | Qt::AlignVCenter;
1534 tr.translate(shiftX, shiftY);
1535 const QString text = d->toolButtonElideText(toolbutton, tr, alignment);
1536 painter->setPen(controlTextColor(option));
1537 proxy()->drawItemText(painter, QStyle::visualRect(toolbutton->direction, rect, tr), alignment, toolbutton->palette,
1538 toolbutton->state & State_Enabled, text);
1540 rect.translate(shiftX, shiftY);
1542 drawArrow(proxy(), toolbutton, rect, painter, widget);
1544 proxy()->drawItemPixmap(painter, rect, Qt::AlignCenter, pm);
1551 case QStyle::CE_ShapedFrame:
1552 if (
const QStyleOptionFrame *f = qstyleoption_cast<
const QStyleOptionFrame *>(option)) {
1553 int frameShape = f->frameShape;
1554 int frameShadow = QFrame::Plain;
1555 if (f->state & QStyle::State_Sunken)
1556 frameShadow = QFrame::Sunken;
1557 else if (f->state & QStyle::State_Raised)
1558 frameShadow = QFrame::Raised;
1560 int lw = f->lineWidth;
1561 int mlw = f->midLineWidth;
1563 switch (frameShape) {
1565 if (frameShadow == QFrame::Plain)
1566 qDrawPlainRoundedRect(painter, f->rect, secondLevelRoundingRadius, secondLevelRoundingRadius, highContrastTheme ==
true ? f->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorStrong], lw);
1568 qDrawShadeRect(painter, f->rect, f->palette, frameShadow == QFrame::Sunken, lw, mlw);
1571 if (frameShadow == QFrame::Plain)
1572 qDrawPlainRoundedRect(painter, f->rect, secondLevelRoundingRadius, secondLevelRoundingRadius, highContrastTheme ==
true ? f->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorStrong], lw);
1574 qDrawShadePanel(painter, f->rect, f->palette, frameShadow == QFrame::Sunken, lw);
1577 QWindowsVistaStyle::drawControl(element, option, painter, widget);
1581#if QT_CONFIG(progressbar)
1582 case CE_ProgressBarGroove:
1583 if (
const auto baropt = qstyleoption_cast<
const QStyleOptionProgressBar*>(option)) {
1584 QRect rect = option->rect;
1585 QPointF center = rect.center();
1586 if (baropt->state & QStyle::State_Horizontal) {
1588 rect.moveTop(center.y());
1591 rect.moveLeft(center.x());
1593 painter->setPen(Qt::NoPen);
1594 painter->setBrush(Qt::gray);
1595 painter->drawRect(rect);
1598 case CE_ProgressBarContents:
1599 if (
const auto baropt = qstyleoption_cast<
const QStyleOptionProgressBar *>(option)) {
1600 QPainterStateGuard psg(painter);
1601 QRectF rect = option->rect;
1602 painter->translate(rect.topLeft());
1603 rect.translate(-rect.topLeft());
1605 constexpr qreal progressBarThickness = 3;
1606 constexpr qreal progressBarHalfThickness = progressBarThickness / 2.0;
1608 const auto isIndeterminate = baropt->maximum == 0 && baropt->minimum == 0;
1609 const auto orientation =
1610 (baropt->state & QStyle::State_Horizontal) ? Qt::Horizontal : Qt::Vertical;
1611 const auto inverted = baropt->invertedAppearance;
1612 const auto reverse = (baropt->direction == Qt::RightToLeft) ^ inverted;
1616 if (orientation == Qt::Vertical) {
1617 rect = QRectF(rect.left(), rect.top(), rect.height(),
1622 m.translate(0, -rect.height() + 1);
1625 m.translate(-rect.width(), 0);
1627 painter->setTransform(m,
true);
1628 }
else if (reverse) {
1629 QTransform m = QTransform::fromScale(-1, 1);
1630 m.translate(-rect.width(), 0);
1631 painter->setTransform(m,
true);
1633 const qreal offset = (
int(rect.height()) % 2 == 0) ? 0.5f : 0.0f;
1635 if (isIndeterminate) {
1636#if QT_CONFIG(animation)
1637 auto anim = d->animation(option->styleObject);
1639 auto anim =
new QStyleAnimation(option->styleObject);
1640 anim->setFrameRate(QStyleAnimation::SixtyFps);
1641 d->startAnimation(anim);
1643 constexpr auto loopDurationMSec = 4000;
1644 const auto elapsedTime = std::chrono::time_point_cast<std::chrono::milliseconds>(
1645 std::chrono::system_clock::now());
1646 const auto elapsed = elapsedTime.time_since_epoch().count();
1647 const auto handleCenter = (elapsed % loopDurationMSec) /
float(loopDurationMSec);
1648 const auto isLongHandle = (elapsed / loopDurationMSec) % 2 == 0;
1649 const auto lengthFactor = (isLongHandle ? 33.0f : 25.0f) / 100.0f;
1651 constexpr auto handleCenter = 0.5f;
1652 constexpr auto lengthFactor = 1;
1654 const auto begin = qMax(handleCenter * (1 + lengthFactor) - lengthFactor, 0.0f);
1655 const auto end = qMin(handleCenter * (1 + lengthFactor), 1.0f);
1656 const auto barBegin = begin * rect.width();
1657 const auto barEnd = end * rect.width();
1658 rect = QRectF(QPointF(rect.left() + barBegin, rect.top()),
1659 QPointF(rect.left() + barEnd, rect.bottom()));
1661#if QT_CONFIG(animation)
1662 d->stopAnimation(option->styleObject);
1664 const auto fillPercentage = (
float(baropt->progress - baropt->minimum))
1665 / (
float(baropt->maximum - baropt->minimum));
1666 rect.setWidth(rect.width() * fillPercentage);
1668 const QPointF center = rect.center();
1669 rect.setHeight(progressBarThickness);
1670 rect.moveTop(center.y() - progressBarHalfThickness - offset);
1671 drawRoundedRect(painter, rect, Qt::NoPen, baropt->palette.accent());
1674 case CE_ProgressBarLabel:
1675 if (
const auto baropt = qstyleoption_cast<
const QStyleOptionProgressBar *>(option)) {
1676 const bool vertical = !(baropt->state & QStyle::State_Horizontal);
1678 proxy()->drawItemText(painter, baropt->rect, Qt::AlignCenter | Qt::TextSingleLine,
1679 baropt->palette, baropt->state & State_Enabled, baropt->text,
1685 case CE_PushButtonLabel:
1686 if (
const QStyleOptionButton *btn = qstyleoption_cast<
const QStyleOptionButton *>(option)) {
1687 QStyleOptionButton btnCopy(*btn);
1688 btnCopy.rect = btn->rect.marginsRemoved(QMargins(contentHMargin, 0, contentHMargin, 0));
1689 btnCopy.palette.setBrush(QPalette::ButtonText, controlTextColor(option));
1690 QCommonStyle::drawControl(element, &btnCopy, painter, widget);
1693 case CE_PushButtonBevel:
1694 if (
const QStyleOptionButton *btn = qstyleoption_cast<
const QStyleOptionButton *>(option)) {
1695 using namespace StyleOptionHelper;
1697 QRectF rect = btn->rect.marginsRemoved(QMargins(2, 2, 2, 2));
1698 painter->setPen(Qt::NoPen);
1699 if (btn->features.testFlag(QStyleOptionButton::Flat)) {
1700 painter->setBrush(btn->palette.button());
1701 painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
1702 if (flags & (State_Sunken | State_On)) {
1703 painter->setBrush(WINUI3Colors[colorSchemeIndex][subtlePressedColor]);
1705 else if (flags & State_MouseOver) {
1706 painter->setBrush(WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
1708 painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
1710 painter->setBrush(controlFillBrush(option, ControlType::Control));
1711 painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
1713 rect.adjust(0.5,0.5,-0.5,-0.5);
1714 const bool defaultButton = btn->features.testFlag(QStyleOptionButton::DefaultButton);
1715 painter->setBrush(Qt::NoBrush);
1716 painter->setPen(defaultButton ? option->palette.accent().color()
1717 : WINUI3Colors[colorSchemeIndex][controlStrokePrimary]);
1718 painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
1720 painter->setPen(defaultButton ? WINUI3Colors[colorSchemeIndex][controlStrokeOnAccentSecondary]
1721 : WINUI3Colors[colorSchemeIndex][controlStrokeSecondary]);
1723 if (btn->features.testFlag(QStyleOptionButton::HasMenu)) {
1724 QPainterStateGuard psg(
painter);
1727 const auto indSize = proxy()->pixelMetric(PM_MenuButtonIndicator, btn, widget);
1728 const auto indRect =
1731 const auto vindRect = visualRect(btn->direction, btn->rect, indRect);
1732 textRect.setWidth(textRect.width() - indSize);
1734 int fontSize = painter->font().pointSize();
1735 QFont f(d->assetFont);
1736 f.setPointSize(qRound(fontSize * 0.9f));
1737 painter->setFont(f);
1738 painter->setPen(controlTextColor(option));
1739 painter->drawText(vindRect, Qt::AlignCenter, fluentIcon(Icon::ChevronDownMed));
1743 case CE_MenuBarItem:
1744 if (
const auto *mbi = qstyleoption_cast<
const QStyleOptionMenuItem *>(option)) {
1745 using namespace StyleOptionHelper;
1747 constexpr int hPadding = 11;
1748 constexpr int topPadding = 4;
1749 constexpr int bottomPadding = 6;
1750 QStyleOptionMenuItem newMbi = *mbi;
1752 if (
auto mbiV2 = qstyleoption_cast<
const QStyleOptionMenuItemV2 *>(option))
1753 newMbi.state.setFlag(State_Sunken, mbiV2->mouseDown);
1755 newMbi.font.setPointSize(10);
1756 newMbi.palette.setColor(QPalette::ButtonText, controlTextColor(&newMbi));
1757 if (!isDisabled(&newMbi)) {
1758 QPen pen(Qt::NoPen);
1759 QBrush brush(Qt::NoBrush);
1760 if (highContrastTheme) {
1761 pen = QPen(newMbi.palette.highlight().color(), 2);
1762 brush = newMbi.palette.window();
1763 }
else if (isPressed(&newMbi)) {
1764 brush = winUI3Color(subtlePressedColor);
1765 }
else if (isHover(&newMbi)) {
1766 brush = winUI3Color(subtleHighlightColor);
1768 if (pen != Qt::NoPen || brush != Qt::NoBrush) {
1769 const QRect rect = mbi->rect.marginsRemoved(QMargins(5, 0, 5, 0));
1770 drawRoundedRect(painter, rect, pen, brush);
1773 newMbi.rect.adjust(hPadding,topPadding,-hPadding,-bottomPadding);
1774 painter->setFont(newMbi.font);
1775 QCommonStyle::drawControl(element, &newMbi, painter, widget);
1780 case CE_MenuEmptyArea:
1784 if (
const auto *menuitem = qstyleoption_cast<
const QStyleOptionMenuItem *>(option)) {
1785 const auto visualMenuRect = [&](
const QRect &rect) {
1786 return visualRect(option->direction, menuitem->rect, rect);
1788 bool dis = !(menuitem->state & State_Enabled);
1789 bool checked = menuitem->checkType != QStyleOptionMenuItem::NotCheckable
1790 ? menuitem->checked :
false;
1791 bool act = menuitem->state & State_Selected;
1793 const QRect rect = menuitem->rect.marginsRemoved(QMargins(2,2,2,2));
1794 if (act && dis ==
false) {
1795 drawRoundedRect(painter, rect, Qt::NoPen, highContrastTheme ? menuitem->palette.brush(QPalette::Highlight)
1796 : QBrush(winUI3Color(subtleHighlightColor)));
1798 if (menuitem->menuItemType == QStyleOptionMenuItem::Separator) {
1799 constexpr int yoff = 1;
1800 painter->setPen(highContrastTheme ? menuitem->palette.buttonText().color() : winUI3Color(dividerStrokeDefault));
1801 painter->drawLine(menuitem->rect.topLeft() + QPoint(0, yoff),
1802 menuitem->rect.topRight() + QPoint(0, yoff));
1806 int xOffset = contentHMargin;
1808 const auto checkMarkWidth = proxy()->pixelMetric(PM_IndicatorWidth, option, widget);
1810 QRect vRect(visualMenuRect(QRect(rect.x() + xOffset, rect.y(),
1811 checkMarkWidth, rect.height())));
1812 QPainterStateGuard psg(painter);
1813 painter->setFont(d->assetFont);
1814 painter->setPen(option->palette.text().color());
1815 painter->drawText(vRect, Qt::AlignCenter, fluentIcon(Icon::CheckMark));
1817 if (menuitem->menuHasCheckableItems)
1818 xOffset += checkMarkWidth + contentItemHMargin;
1819 if (!menuitem->icon.isNull()) {
1821 QRect vRect(visualMenuRect(QRect(rect.x() + xOffset,
1823 menuitem->maxIconWidth - 4,
1825 QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal;
1827 mode = QIcon::Active;
1828 const auto size = proxy()->pixelMetric(PM_SmallIconSize, option, widget);
1829 QRect pmr(QPoint(0, 0), QSize(size, size));
1830 pmr.moveCenter(vRect.center());
1831 menuitem->icon.paint(painter, pmr, Qt::AlignCenter, mode,
1832 checked ? QIcon::On : QIcon::Off);
1834 if (menuitem->maxIconWidth > 0)
1835 xOffset += menuitem->maxIconWidth - 4 + contentItemHMargin;
1837 QStringView s(menuitem->text);
1839 QPoint tl(rect.left() + xOffset, rect.top());
1840 QPoint br(rect.right() - menuitem->reservedShortcutWidth - contentHMargin,
1842 QRect textRect(tl, br);
1843 QRect vRect(visualMenuRect(textRect));
1846 if (highContrastTheme) {
1847 penColor = menuitem->palette.color(act ? QPalette::HighlightedText
1850 penColor = controlTextColor(option);
1852 painter->setPen(penColor);
1854 qsizetype t = s.indexOf(u'\t');
1855 int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
1856 if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget))
1857 text_flags |= Qt::TextHideMnemonic;
1858 text_flags |= Qt::AlignLeft;
1860 if (t >= 0 && menuitem->menuItemType != QStyleOptionMenuItem::SubMenu) {
1861 QRect shortcutRect(QPoint(textRect.right(), textRect.top()),
1862 QPoint(rect.right(), textRect.bottom()));
1863 QRect vShortcutRect(visualMenuRect(shortcutRect));
1864 const QString textToDraw = s.mid(t + 1).toString();
1865 painter->drawText(vShortcutRect, text_flags, textToDraw);
1868 QFont font = menuitem->font;
1869 if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem)
1871 painter->setFont(font);
1872 const QString textToDraw = s.left(t).toString();
1873 painter->drawText(vRect, text_flags, textToDraw);
1875 if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) {
1876 int fontSize = menuitem->font.pointSize();
1877 QFont f(d->assetFont);
1878 f.setPointSize(qRound(fontSize * 0.9f));
1879 painter->setFont(f);
1880 int yOfs = qRound(fontSize / 3.0f);
1881 QPoint tl(rect.right() - 2 * QWindowsStylePrivate::windowsArrowHMargin - contentItemHMargin,
1883 QRect submenuRect(tl, rect.bottomRight());
1884 QRect vSubMenuRect = visualMenuRect(submenuRect);
1885 painter->setPen(option->palette.text().color());
1886 const bool isReverse = option->direction == Qt::RightToLeft;
1887 const auto ico = isReverse ? Icon::ChevronLeftMed : Icon::ChevronRightMed;
1888 painter->drawText(vSubMenuRect, Qt::AlignCenter, fluentIcon(ico));
1893 case CE_MenuBarEmptyArea: {
1896 case CE_HeaderEmptyArea:
1898 case CE_HeaderSection: {
1899 if (
const QStyleOptionHeader *header = qstyleoption_cast<
const QStyleOptionHeader *>(option)) {
1900 painter->setPen(Qt::NoPen);
1901 painter->setBrush(header->palette.button());
1902 painter->drawRect(header->rect);
1904 painter->setPen(highContrastTheme ==
true ? header->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorLight]);
1905 painter->setBrush(Qt::NoBrush);
1907 if (header->position == QStyleOptionHeader::OnlyOneSection) {
1910 else if (header->position == QStyleOptionHeader::Beginning) {
1911 painter->drawLine(QPointF(option->rect.topRight()) + QPointF(0.5,0.0),
1912 QPointF(option->rect.bottomRight()) + QPointF(0.5,0.0));
1914 else if (header->position == QStyleOptionHeader::End) {
1915 painter->drawLine(QPointF(option->rect.topLeft()) - QPointF(0.5,0.0),
1916 QPointF(option->rect.bottomLeft()) - QPointF(0.5,0.0));
1918 painter->drawLine(QPointF(option->rect.topRight()) + QPointF(0.5,0.0),
1919 QPointF(option->rect.bottomRight()) + QPointF(0.5,0.0));
1920 painter->drawLine(QPointF(option->rect.topLeft()) - QPointF(0.5,0.0),
1921 QPointF(option->rect.bottomLeft()) - QPointF(0.5,0.0));
1923 painter->drawLine(QPointF(option->rect.bottomLeft()) + QPointF(0.0,0.5),
1924 QPointF(option->rect.bottomRight()) + QPointF(0.0,0.5));
1928 case CE_ItemViewItem: {
1929 if (
const QStyleOptionViewItem *vopt = qstyleoption_cast<
const QStyleOptionViewItem *>(option)) {
1930 const auto p = proxy();
1931 QRect checkRect = p->subElementRect(SE_ItemViewItemCheckIndicator, vopt, widget);
1932 QRect iconRect = p->subElementRect(SE_ItemViewItemDecoration, vopt, widget);
1933 QRect textRect = p->subElementRect(SE_ItemViewItemText, vopt, widget);
1936 proxy()->drawPrimitive(PE_PanelItemViewItem, option, painter, widget);
1938 const QRect &rect = vopt->rect;
1939 const bool isRtl = option->direction == Qt::RightToLeft;
1940 bool onlyOne = vopt->viewItemPosition == QStyleOptionViewItem::OnlyOne ||
1941 vopt->viewItemPosition == QStyleOptionViewItem::Invalid;
1942 bool isFirst = vopt->viewItemPosition == QStyleOptionViewItem::Beginning;
1943 bool isLast = vopt->viewItemPosition == QStyleOptionViewItem::End;
1945 const QAbstractItemView *view = qobject_cast<
const QAbstractItemView *>(widget);
1946 if (qobject_cast<
const QTableView *>(view)) {
1950 if (vopt->features.testFlag(QStyleOptionViewItem::IsDecoratedRootColumn) &&
1951 vopt->showDecorationSelected) {
1963 }
else if (isLast) {
1970 const bool highlightCurrent = vopt->state.testAnyFlags(State_Selected | State_MouseOver);
1971 if (highlightCurrent) {
1972 if (highContrastTheme) {
1973 painter->setBrush(vopt->palette.highlight());
1975 painter->setBrush(view && view->alternatingRowColors() && vopt->state & State_Selected
1976 ? calculateAccentColor(option)
1977 : winUI3Color(subtleHighlightColor));
1980 painter->setBrush(vopt->backgroundBrush);
1982 painter->setPen(Qt::NoPen);
1985 painter->drawRoundedRect(rect.marginsRemoved(QMargins(2, 2, 2, 2)),
1986 secondLevelRoundingRadius, secondLevelRoundingRadius);
1987 }
else if (isFirst) {
1988 QPainterStateGuard psg(
painter);
1989 painter->setClipRect(rect);
1990 painter->drawRoundedRect(rect.marginsRemoved(QMargins(2, 2, -secondLevelRoundingRadius, 2)),
1991 secondLevelRoundingRadius, secondLevelRoundingRadius);
1992 }
else if (isLast) {
1993 QPainterStateGuard psg(
painter);
1994 painter->setClipRect(rect);
1995 painter->drawRoundedRect(rect.marginsRemoved(QMargins(-secondLevelRoundingRadius, 2, 2, 2)),
1996 secondLevelRoundingRadius, secondLevelRoundingRadius);
1998 painter->drawRect(rect.marginsRemoved(QMargins(0, 2, 0, 2)));
2002 if (vopt->features & QStyleOptionViewItem::HasCheckIndicator) {
2003 QStyleOptionViewItem option(*vopt);
2004 option.rect = checkRect;
2005 option.state = option.state & ~QStyle::State_HasFocus;
2007 switch (vopt->checkState) {
2009 option.state |= QStyle::State_Off;
2011 case Qt::PartiallyChecked:
2012 option.state |= QStyle::State_NoChange;
2015 option.state |= QStyle::State_On;
2018 proxy()->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &option, painter, widget);
2022 if (iconRect.isValid()) {
2023 QIcon::Mode mode = QIcon::Normal;
2024 if (!(vopt->state & QStyle::State_Enabled))
2025 mode = QIcon::Disabled;
2026 else if (vopt->state & QStyle::State_Selected)
2027 mode = QIcon::Selected;
2028 QIcon::State state = vopt->state & QStyle::State_Open ? QIcon::On : QIcon::Off;
2029 vopt->icon.paint(painter, iconRect, vopt->decorationAlignment, mode, state);
2032 if (highlightCurrent && highContrastTheme) {
2033 painter->setPen(vopt->palette.base().color());
2034 }
else if ((view && view->alternatingRowColors() && highlightCurrent && vopt->state & State_Selected)) {
2035 painter->setPen(winUI3Color(textOnAccentPrimary));
2037 painter->setPen(vopt->palette.text().color());
2039 d->viewItemDrawText(painter, vopt, textRect);
2042 if (vopt->state & State_Selected && !highContrastTheme) {
2043 if (
const QListView *lv = qobject_cast<
const QListView *>(widget);
2044 lv && lv->viewMode() != QListView::IconMode) {
2045 const auto col = vopt->palette.accent().color();
2046 painter->setBrush(col);
2047 painter->setPen(col);
2048 const auto xPos = isRtl ? rect.right() - 4.5f : rect.left() + 3.5f;
2049 const auto yOfs = rect.height() / 4.;
2050 QRectF r(
QPointF(xPos, rect.y() + yOfs),
2051 QPointF(xPos + 1, rect.y() + rect.height() - yOfs));
2052 painter->drawRoundedRect(r, 1, 1);
2059 QWindowsVistaStyle::drawControl(element, option, painter, widget);
2217QRect QWindows11Style::subControlRect(ComplexControl control,
const QStyleOptionComplex *option,
2218 SubControl subControl,
const QWidget *widget)
const
2223#if QT_CONFIG(spinbox)
2225 if (
const QStyleOptionSpinBox *spinbox = qstyleoption_cast<
const QStyleOptionSpinBox *>(option)) {
2226 const bool hasButtons = spinbox->buttonSymbols != QAbstractSpinBox::NoButtons;
2227 const int fw = spinbox->frame
2228 ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget)
2230 const int buttonHeight = hasButtons
2231 ? qMin(spinbox->rect.height() - 3 * fw, spinbox->fontMetrics.height() * 5 / 4)
2233 const QSize buttonSize(buttonHeight * 6 / 5, buttonHeight);
2234 const int textFieldLength = spinbox->rect.width() - 2 * fw - 2 * buttonSize.width();
2235 const QPoint topLeft(spinbox->rect.topLeft() + QPoint(fw, fw));
2236 switch (subControl) {
2238 case SC_SpinBoxDown: {
2241 const int yOfs = ((spinbox->rect.height() - 2 * fw) - buttonSize.height()) / 2;
2242 ret = QRect(topLeft.x() + textFieldLength, topLeft.y() + yOfs, buttonSize.width(),
2243 buttonSize.height());
2244 if (subControl == SC_SpinBoxDown)
2245 ret.moveRight(ret.right() + buttonSize.width());
2248 case SC_SpinBoxEditField:
2249 ret = QRect(topLeft,
2250 spinbox->rect.bottomRight() - QPoint(fw + 2 * buttonSize.width(), fw));
2252 case SC_SpinBoxFrame:
2253 ret = spinbox->rect;
2257 ret = visualRect(spinbox->direction, spinbox->rect, ret);
2261 if (
const QStyleOptionTitleBar *titlebar = qstyleoption_cast<
const QStyleOptionTitleBar *>(option)) {
2262 SubControl sc = subControl;
2263 ret = QCommonStyle::subControlRect(control, option, subControl, widget);
2264 static constexpr int indent = 3;
2265 static constexpr int controlWidthMargin = 2;
2266 const int controlHeight = titlebar->rect.height();
2267 const int controlWidth = 46;
2268 const int iconSize = proxy()->pixelMetric(QStyle::PM_TitleBarButtonIconSize, option, widget);
2269 int offset = -(controlWidthMargin + indent);
2271 bool isMinimized = titlebar->titleBarState & Qt::WindowMinimized;
2272 bool isMaximized = titlebar->titleBarState & Qt::WindowMaximized;
2275 case SC_TitleBarLabel:
2276 if (titlebar->titleBarFlags & (Qt::WindowTitleHint | Qt::WindowSystemMenuHint)) {
2277 ret = titlebar->rect;
2278 if (titlebar->titleBarFlags & Qt::WindowSystemMenuHint)
2279 ret.adjust(iconSize + controlWidthMargin + indent, 0, -controlWidth, 0);
2280 if (titlebar->titleBarFlags & Qt::WindowMinimizeButtonHint)
2281 ret.adjust(0, 0, -controlWidth, 0);
2282 if (titlebar->titleBarFlags & Qt::WindowMaximizeButtonHint)
2283 ret.adjust(0, 0, -controlWidth, 0);
2284 if (titlebar->titleBarFlags & Qt::WindowShadeButtonHint)
2285 ret.adjust(0, 0, -controlWidth, 0);
2286 if (titlebar->titleBarFlags & Qt::WindowContextHelpButtonHint)
2287 ret.adjust(0, 0, -controlWidth, 0);
2290 case SC_TitleBarContextHelpButton:
2291 if (titlebar->titleBarFlags & Qt::WindowContextHelpButtonHint)
2292 offset += controlWidth;
2294 case SC_TitleBarMinButton:
2295 if (!isMinimized && (titlebar->titleBarFlags & Qt::WindowMinimizeButtonHint))
2296 offset += controlWidth;
2297 else if (sc == SC_TitleBarMinButton)
2300 case SC_TitleBarNormalButton:
2301 if (isMinimized && (titlebar->titleBarFlags & Qt::WindowMinimizeButtonHint))
2302 offset += controlWidth;
2303 else if (isMaximized && (titlebar->titleBarFlags & Qt::WindowMaximizeButtonHint))
2304 offset += controlWidth;
2305 else if (sc == SC_TitleBarNormalButton)
2308 case SC_TitleBarMaxButton:
2309 if (!isMaximized && (titlebar->titleBarFlags & Qt::WindowMaximizeButtonHint))
2310 offset += controlWidth;
2311 else if (sc == SC_TitleBarMaxButton)
2314 case SC_TitleBarShadeButton:
2315 if (!isMinimized && (titlebar->titleBarFlags & Qt::WindowShadeButtonHint))
2316 offset += controlWidth;
2317 else if (sc == SC_TitleBarShadeButton)
2320 case SC_TitleBarUnshadeButton:
2321 if (isMinimized && (titlebar->titleBarFlags & Qt::WindowShadeButtonHint))
2322 offset += controlWidth;
2323 else if (sc == SC_TitleBarUnshadeButton)
2326 case SC_TitleBarCloseButton:
2327 if (titlebar->titleBarFlags & Qt::WindowSystemMenuHint)
2328 offset += controlWidth;
2329 else if (sc == SC_TitleBarCloseButton)
2331 ret.setRect(titlebar->rect.right() - offset, titlebar->rect.top(),
2332 controlWidth, controlHeight);
2334 case SC_TitleBarSysMenu:
2335 if (titlebar->titleBarFlags & Qt::WindowSystemMenuHint) {
2336 const auto yOfs = titlebar->rect.top() + (titlebar->rect.height() - iconSize) / 2;
2337 ret.setRect(titlebar->rect.left() + controlWidthMargin + indent, yOfs, iconSize,
2344 if (widget && isMinimized && titlebar->rect.width() < offset)
2345 const_cast<QWidget*>(widget)->resize(controlWidthMargin + indent + offset + iconSize + controlWidthMargin, controlWidth);
2346 ret = visualRect(titlebar->direction, titlebar->rect, ret);
2352 ret = QCommonStyle::subControlRect(control, option, subControl, widget);
2354 if (subControl == SC_ScrollBarAddLine || subControl == SC_ScrollBarSubLine) {
2355 if (
const QStyleOptionSlider *scrollbar = qstyleoption_cast<
const QStyleOptionSlider *>(option)) {
2356 if (scrollbar->orientation == Qt::Vertical)
2357 ret = ret.adjusted(2,2,-2,-3);
2359 ret = ret.adjusted(3,2,-2,-2);
2365 if (
const auto *cb = qstyleoption_cast<
const QStyleOptionComboBox *>(option)) {
2366 const auto indicatorWidth =
2367 proxy()->pixelMetric(PM_MenuButtonIndicator, option, widget);
2368 switch (subControl) {
2369 case SC_ComboBoxArrow: {
2371 cb->frame ? proxy()->pixelMetric(PM_ComboBoxFrameWidth, cb, widget) : 0;
2372 const int buttonHeight =
2373 qMin(cb->rect.height() - 3 * fw, cb->fontMetrics.height() * 5 / 4);
2374 const QSize buttonSize(buttonHeight * 6 / 5, buttonHeight);
2375 const int textFieldLength = cb->rect.width() - 2 * fw - buttonSize.width();
2376 const QPoint topLeft(cb->rect.topLeft() + QPoint(fw, fw));
2377 const int yOfs = ((cb->rect.height() - 2 * fw) - buttonSize.height()) / 2;
2378 ret = QRect(topLeft.x() + textFieldLength, topLeft.y() + yOfs, buttonSize.width(),
2379 buttonSize.height());
2380 ret = visualRect(option->direction, option->rect, ret);
2383 case SC_ComboBoxEditField: {
2386 const int fw = proxy()->pixelMetric(PM_ComboBoxFrameWidth, cb, widget);
2387 ret = ret.marginsRemoved(QMargins(fw, fw, fw, fw));
2389 ret.setWidth(ret.width() - indicatorWidth - contentHMargin * 2);
2390 ret = visualRect(option->direction, option->rect, ret);
2394 ret = QWindowsVistaStyle::subControlRect(control, option, subControl, widget);
2400#if QT_CONFIG(groupbox)
2402 ret = QWindowsVistaStyle::subControlRect(control, option, subControl, widget);
2403 switch (subControl) {
2404 case SC_GroupBoxCheckBox:
2414 ret = QWindowsVistaStyle::subControlRect(control, option, subControl, widget);
2422QSize QWindows11Style::sizeFromContents(ContentsType type,
const QStyleOption *option,
2423 const QSize &size,
const QWidget *widget)
const
2425 QSize contentSize(size);
2429#if QT_CONFIG(menubar)
2430 case CT_MenuBarItem:
2431 if (!contentSize.isEmpty()) {
2432 constexpr int hMargin = 2 * 6;
2433 constexpr int hPadding = 2 * 11;
2434 constexpr int itemHeight = 32;
2435 contentSize.setWidth(contentSize.width() + hMargin + hPadding);
2436#if QT_CONFIG(tabwidget)
2437 if (widget->parent() && !qobject_cast<
const QTabWidget *>(widget->parent()))
2439 contentSize.setHeight(itemHeight);
2445 if (
const auto *menuItem = qstyleoption_cast<
const QStyleOptionMenuItem *>(option)) {
2446 int width = size.width();
2448 if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
2452 height = menuItem->fontMetrics.height() + 8;
2453 if (!menuItem->icon.isNull()) {
2454 int iconExtent = proxy()->pixelMetric(PM_SmallIconSize, option, widget);
2455 height = qMax(height,
2456 menuItem->icon.actualSize(QSize(iconExtent, iconExtent)).height() + 4);
2459 if (menuItem->text.contains(u'\t'))
2460 width += contentItemHMargin;
2461 if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu)
2462 width += 2 * QWindowsStylePrivate::windowsArrowHMargin + contentItemHMargin;
2463 if (menuItem->menuItemType == QStyleOptionMenuItem::DefaultItem) {
2464 const QFontMetrics fm(menuItem->font);
2465 QFont fontBold = menuItem->font;
2466 fontBold.setBold(
true);
2467 const QFontMetrics fmBold(fontBold);
2468 width += fmBold.horizontalAdvance(menuItem->text) - fm.horizontalAdvance(menuItem->text);
2471 if (menuItem->menuHasCheckableItems) {
2472 const auto checkMarkWidth = proxy()->pixelMetric(PM_IndicatorWidth, option, widget);
2473 width += checkMarkWidth + contentItemHMargin * 2;
2477 if (menuItem->maxIconWidth > 0)
2478 width += contentItemHMargin * 2 + menuItem->maxIconWidth - 4;
2480 width += 2 * contentHMargin;
2483 contentSize = QSize(width, height);
2487#if QT_CONFIG(spinbox)
2489 if (
const auto *spinBoxOpt = qstyleoption_cast<
const QStyleOptionSpinBox *>(option)) {
2491 const bool hasButtons = (spinBoxOpt->buttonSymbols != QAbstractSpinBox::NoButtons);
2492 const int margins = 8;
2493 const int buttonWidth = hasButtons ? 16 + contentItemHMargin : 0;
2494 const int frameWidth = spinBoxOpt->frame
2495 ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget)
2498 contentSize += QSize(2 * buttonWidth + 2 * frameWidth + 2 * margins, 2 * frameWidth);
2503#if QT_CONFIG(combobox)
2505 if (
const auto *comboBoxOpt = qstyleoption_cast<
const QStyleOptionComboBox *>(option)) {
2506 contentSize = QWindowsStyle::sizeFromContents(type, option, size, widget);
2507 contentSize += QSize(0, 4);
2508 if (comboBoxOpt->subControls & SC_ComboBoxArrow) {
2509 const auto w = proxy()->pixelMetric(PM_MenuButtonIndicator, option, widget);
2510 contentSize.rwidth() += w + contentItemHMargin;
2516 if (qstyleoption_cast<
const QStyleOptionFrame *>(option)) {
2517 contentSize = QWindowsStyle::sizeFromContents(type, option, size, widget);
2518 contentSize += QSize(0, 4);
2522 case CT_HeaderSection:
2525 contentSize = QWindowsStyle::sizeFromContents(type, option, size, widget);
2527 case CT_RadioButton:
2529 if (
const auto *buttonOpt = qstyleoption_cast<
const QStyleOptionButton *>(option)) {
2530 const auto p = proxy();
2531 const bool isRadio = (type == CT_RadioButton);
2533 const int width = p->pixelMetric(
2534 isRadio ? PM_ExclusiveIndicatorWidth : PM_IndicatorWidth, option, widget);
2535 const int height = p->pixelMetric(
2536 isRadio ? PM_ExclusiveIndicatorHeight : PM_IndicatorHeight, option, widget);
2539 if (!buttonOpt->icon.isNull() || !buttonOpt->text.isEmpty()) {
2540 margins += p->pixelMetric(isRadio ? PM_RadioButtonLabelSpacing
2541 : PM_CheckBoxLabelSpacing,
2545 contentSize += QSize(width + margins, 4);
2546 contentSize.setHeight(qMax(size.height(), height + 2 * contentItemHMargin));
2552 contentSize = QWindowsVistaStyle::sizeFromContents(type, option, size, widget);
2553 if (size.width() == 0)
2554 contentSize.rwidth() += 2;
2556 case CT_PushButton: {
2557 contentSize = QWindowsVistaStyle::sizeFromContents(type, option, size, widget);
2559 const int oldMargin = proxy()->pixelMetric(PM_ButtonMargin, option, widget);
2560 contentSize.rwidth() += 2 * contentHMargin - oldMargin;
2563 case CT_ToolButton: {
2564 contentSize = QWindowsVistaStyle::sizeFromContents(type, option, size, widget);
2566 const int oldMargin = proxy()->pixelMetric(PM_ButtonMargin, option, widget);
2567 contentSize.rwidth() += 2 * contentHMargin - oldMargin;
2568 if (
const auto toolbutton = qstyleoption_cast<
const QStyleOptionToolButton *>(option)) {
2569 if (toolbutton->features.testFlag(QStyleOptionToolButton::HasMenu))
2570 contentSize.rwidth() += size.height();
2574 case CT_ItemViewItem: {
2575 if (
const auto *viewItemOpt = qstyleoption_cast<
const QStyleOptionViewItem *>(option)) {
2576 if (
const QListView *lv = qobject_cast<
const QListView *>(widget);
2577 lv && lv->viewMode() != QListView::IconMode) {
2578 QStyleOptionViewItem vOpt(*viewItemOpt);
2582 vOpt.rect.setRight(vOpt.rect.right() - contentHMargin);
2583 contentSize = QWindowsVistaStyle::sizeFromContents(type, &vOpt, size, widget);
2584 contentSize.rwidth() += contentHMargin;
2585 contentSize.rheight() += 2 * contentHMargin;
2588 contentSize = QWindowsVistaStyle::sizeFromContents(type, option, size, widget);
2594 contentSize = QWindowsVistaStyle::sizeFromContents(type, option, size, widget);