/*************************************************************************** BionxControl © 2025 -2026 christoph holzheuer christoph.holzheuer@gmail.com Using: mhs_can_drv.c © 2011 - 2023 by MHS-Elektronik GmbH & Co. KG, Germany Klaus Demlehner, klaus@mhs-elektronik.de @see www.mhs-elektronik.de Based on Bionx data type descriptions from: BigXionFlasher USB V 0.2.4 rev. 97 © 2011-2013 by Thomas Koenig @see www.bigxionflasher.org Bionx Bike Info © 2018 Thorsten Schmidt (tschmidt@ts-soft.de) @see www.ts-soft.de This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. @see https://github.com/bikemike/bionx-bikeinfo ***************************************************************************/ #ifndef BCSLIDERSTYLE_H #define BCSLIDERSTYLE_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Fluent Design Slider Style class FluentSliderStyle : public QProxyStyle { public: FluentSliderStyle() : QProxyStyle() {} // Wichtig: Genug Platz für Handle reservieren int pixelMetric(PixelMetric metric, const QStyleOption* option = nullptr, const QWidget* widget = nullptr) const override { switch (metric) { case PM_SliderThickness: return 32; // Höhe für horizontalen Slider case PM_SliderLength: return 20; // Handle-Größe case PM_SliderControlThickness: return 20; case PM_SliderSpaceAvailable: if (option) { if (const QStyleOptionSlider* sliderOpt = qstyleoption_cast(option)) { if (sliderOpt->orientation == Qt::Horizontal) { return sliderOpt->rect.width() - 20; } else { return sliderOpt->rect.height() - 20; } } } return QProxyStyle::pixelMetric(metric, option, widget); default: return QProxyStyle::pixelMetric(metric, option, widget); } } QRect subControlRect(ComplexControl cc, const QStyleOptionComplex* opt,SubControl sc, const QWidget* widget) const override { if (cc == CC_Slider) { if (const QStyleOptionSlider* slider = qstyleoption_cast(opt)) { QRect rect = slider->rect; int handleSize = 20; if (sc == SC_SliderHandle) { // Handle Position korrekt berechnen if (slider->orientation == Qt::Horizontal) { int range = slider->maximum - slider->minimum; int pos = slider->sliderPosition - slider->minimum; int pixelRange = rect.width() - handleSize; int pixelPos = (range != 0) ? (pos * pixelRange) / range : 0; return QRect(rect.x() + pixelPos, rect.center().y() - handleSize / 2, handleSize, handleSize); } else { int range = slider->maximum - slider->minimum; int pos = slider->sliderPosition - slider->minimum; int pixelRange = rect.height() - handleSize; int pixelPos = (range != 0) ? (pos * pixelRange) / range : 0; return QRect(rect.center().x() - handleSize / 2, rect.bottom() - pixelPos - handleSize, handleSize, handleSize); } } } } return QProxyStyle::subControlRect(cc, opt, sc, widget); } void drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const override { if (control == CC_Slider) { if (const QStyleOptionSlider* slider = qstyleoption_cast(option)) { painter->setRenderHint(QPainter::Antialiasing); // Fluent Colors QColor accentColor(0, 120, 212); // #0078D4 QColor inactiveColor(138, 136, 134); // #8A8886 QColor bgColor(255, 255, 255); // White background if (slider->orientation == Qt::Horizontal) { drawHorizontalFluentSlider(painter, slider, accentColor, inactiveColor, bgColor); } else { drawVerticalFluentSlider(painter, slider, accentColor, inactiveColor, bgColor); } return; } } QProxyStyle::drawComplexControl(control, option, painter, widget); } private: void drawHorizontalFluentSlider(QPainter* painter, const QStyleOptionSlider* slider, const QColor& activeColor, const QColor& inactiveColor, const QColor& bgColor) const { QRect groove = slider->rect; QRect handle = subControlRect(CC_Slider, slider, SC_SliderHandle, nullptr); int grooveHeight = 4; // Track sollte im Widget-Zentrum sein, nicht im groove-Zentrum int grooveY = slider->rect.center().y() - grooveHeight / 2; // Full background track QRect fullTrack(groove.left(), grooveY, groove.width(), grooveHeight); painter->setPen(Qt::NoPen); painter->setBrush(inactiveColor.lighter(150)); painter->drawRoundedRect(fullTrack, grooveHeight / 2, grooveHeight / 2); // Active track (filled portion) int activeWidth = handle.center().x() - groove.left(); QRect activeTrack(groove.left(), grooveY, activeWidth, grooveHeight); painter->setBrush(activeColor); painter->drawRoundedRect(activeTrack, grooveHeight / 2, grooveHeight / 2); // Handle (Thumb) - Fluent style is more subtle int handleSize = 20; QRect thumbRect(handle.center().x() - handleSize / 2, handle.center().y() - handleSize / 2, handleSize, handleSize); // Hover effect - subtle glow if (slider->state & State_MouseOver) { painter->setBrush(QColor(activeColor.red(), activeColor.green(), activeColor.blue(), 30)); int glowSize = 32; QRect glow(handle.center().x() - glowSize / 2, handle.center().y() - glowSize / 2, glowSize, glowSize); painter->drawEllipse(glow); } // Thumb painter->setBrush(bgColor); painter->setPen(QPen(activeColor, 2)); painter->drawEllipse(thumbRect); // Inner circle for pressed state if (slider->state & State_Sunken) { int innerSize = 8; QRect inner(handle.center().x() - innerSize / 2, handle.center().y() - innerSize / 2, innerSize, innerSize); painter->setPen(Qt::NoPen); painter->setBrush(activeColor); painter->drawEllipse(inner); } } void drawVerticalFluentSlider(QPainter* painter, const QStyleOptionSlider* slider, const QColor& activeColor, const QColor& inactiveColor, const QColor& bgColor) const { QRect groove = slider->rect; QRect handle = subControlRect(CC_Slider, slider, SC_SliderHandle, nullptr); int grooveWidth = 4; // Track sollte im Widget-Zentrum sein int grooveX = slider->rect.center().x() - grooveWidth / 2; // Full background track QRect fullTrack(grooveX, groove.top(), grooveWidth, groove.height()); painter->setPen(Qt::NoPen); painter->setBrush(inactiveColor.lighter(150)); painter->drawRoundedRect(fullTrack, grooveWidth / 2, grooveWidth / 2); // Active track int activeHeight = groove.bottom() - handle.center().y(); QRect activeTrack(grooveX, handle.center().y(), grooveWidth, activeHeight); painter->setBrush(activeColor); painter->drawRoundedRect(activeTrack, grooveWidth / 2, grooveWidth / 2); // Handle int handleSize = 20; QRect thumbRect(handle.center().x() - handleSize / 2, handle.center().y() - handleSize / 2, handleSize, handleSize); if (slider->state & State_MouseOver) { painter->setBrush(QColor(activeColor.red(), activeColor.green(), activeColor.blue(), 30)); int glowSize = 32; QRect glow(handle.center().x() - glowSize / 2, handle.center().y() - glowSize / 2, glowSize, glowSize); painter->drawEllipse(glow); } painter->setBrush(bgColor); painter->setPen(QPen(activeColor, 2)); painter->drawEllipse(thumbRect); if (slider->state & State_Sunken) { int innerSize = 8; QRect inner(handle.center().x() - innerSize / 2, handle.center().y() - innerSize / 2, innerSize, innerSize); painter->setPen(Qt::NoPen); painter->setBrush(activeColor); painter->drawEllipse(inner); } } }; #endif // BCSLIDERSTYLE_H