diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index f1d1f523..632d8313 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -388,7 +388,7 @@ jobs: env: QT_DEBUG_PLUGINS: "1" run: | - $env:Path += ";./qskinny_install/bin;./qskinny_install/lib;./qskinny_install/plugins/skins;./qskinny_build/skins/material3/Release;./qskinny_build/skins/squiek/Release" + $env:Path += ";./qskinny_install/bin;./qskinny_install/lib;./qskinny_install/plugins/skins;./qskinny_build/skins/material3/Release;./qskinny_build/skins/windows/Release;./qskinny_build/skins/squiek/Release" echo "starting iotdashboard" Start-Process qskinny_build\examples\bin\Release\iotdashboard.exe -ArgumentList "-qwindowgeometry 1024x600+0+0 --screenshot ${{ matrix.config.screenshot_filename }}" Start-Sleep -Seconds 10 diff --git a/examples/iotdashboard/main.cpp b/examples/iotdashboard/main.cpp index e51259a7..a1b7562e 100644 --- a/examples/iotdashboard/main.cpp +++ b/examples/iotdashboard/main.cpp @@ -69,9 +69,9 @@ int main( int argc, char* argv[] ) // disable default skins qskSkinManager->setPluginPaths( QStringList() ); // no plugins - qskSkinManager->unregisterFactory( "materialfactory" ); qskSkinManager->unregisterFactory( "material3factory" ); qskSkinManager->unregisterFactory( "squiekfactory" ); + qskSkinManager->unregisterFactory( "windowsfactory" ); qskSkinManager->registerFactory( QStringLiteral( "SampleSkinFactory" ), new SkinFactory() ); diff --git a/skins/CMakeLists.txt b/skins/CMakeLists.txt index 37ca7925..5039716b 100644 --- a/skins/CMakeLists.txt +++ b/skins/CMakeLists.txt @@ -1,2 +1,3 @@ add_subdirectory(squiek) -add_subdirectory(material3) \ No newline at end of file +add_subdirectory(material3) +add_subdirectory(windows) diff --git a/skins/windows/CMakeLists.txt b/skins/windows/CMakeLists.txt new file mode 100644 index 00000000..b5a7146a --- /dev/null +++ b/skins/windows/CMakeLists.txt @@ -0,0 +1,13 @@ +############################################################################ +# QSkinny - Copyright (C) 2016 Uwe Rathmann +# SPDX-License-Identifier: BSD-3-Clause +############################################################################ + +set(SOURCES + QskWindowsGlobal.h QskWindowsSkin.h QskWindowsSkin.cpp + QskWindowsSkinFactory.h QskWindowsSkinFactory.cpp +) +qt_add_resources(SOURCES icons.qrc) + +qsk_add_plugin(windowsskin skins QskWindowsSkinFactory ${SOURCES}) +set_target_properties(windowsskin PROPERTIES DEFINE_SYMBOL QSK_Windows_MAKEDLL ) diff --git a/skins/windows/QskWindowsGlobal.h b/skins/windows/QskWindowsGlobal.h new file mode 100644 index 00000000..62a1080f --- /dev/null +++ b/skins/windows/QskWindowsGlobal.h @@ -0,0 +1,25 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#ifndef QSK_WINDOWS_GLOBAL_H +#define QSK_WINDOWS_GLOBAL_H + +#include "QskGlobal.h" + +#ifdef QSK_DLL + +#if defined( QSK_WINDOWS_MAKEDLL ) // create a DLL library +#define QSK_WINDOWS_EXPORT Q_DECL_EXPORT +#else // use a DLL library +#define QSK_WINDOWS_EXPORT Q_DECL_IMPORT +#endif + +#endif // QSK_DLL + +#ifndef QSK_WINDOWS_EXPORT +#define QSK_WINDOWS_EXPORT +#endif + +#endif diff --git a/skins/windows/QskWindowsSkin.cpp b/skins/windows/QskWindowsSkin.cpp new file mode 100644 index 00000000..a15790d9 --- /dev/null +++ b/skins/windows/QskWindowsSkin.cpp @@ -0,0 +1,490 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2022 Edelhirsch Software GmbH + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#include "QskWindowsSkin.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +static const int qskDuration = 150; + +namespace +{ + class Editor : private QskSkinHintTableEditor + { + public: + Editor( QskSkinHintTable* table, const QskWindowsTheme& palette ) + : QskSkinHintTableEditor( table ) + , theme( palette ) + { + } + + void setup(); + + private: + void setupBox(); + void setupCheckBox(); + void setupComboBox(); + void setupDialogButtonBox(); + void setupFocusIndicator(); + void setupInputPanel(); + void setupListView(); + void setupMenu(); + void setupPageIndicator(); + void setupPopup(); + void setupProgressBar(); + void setupPushButton(); + void setupRadioBox(); + void setupScrollView(); + void setupSegmentedBar(); + void setupSeparator(); + void setupSlider(); + void setupSpinBox(); + void setupSubWindow(); + void setupSwitchButton(); + void setupTabButton(); + void setupTabBar(); + void setupTabView(); + void setupTextInput(); + void setupTextLabel(); + void setupVirtualKeyboard(); + + QskGraphic symbol( const char* name ) const + { + const QString path = QStringLiteral( ":windows/icons/qvg/" ) + + name + QStringLiteral( ".qvg" ); + + return QskGraphicIO::read( path ); + } + + const QskWindowsTheme& theme; + }; + + QFont createFont( const QString& name, qreal lineHeight, + qreal size, qreal tracking, QFont::Weight weight ) + { + QFont font( name, qRound( size ) ); + font.setPixelSize( qRound( lineHeight ) ); + + if( !qskFuzzyCompare( tracking, 0.0 ) ) + font.setLetterSpacing( QFont::AbsoluteSpacing, tracking ); + + font.setWeight( weight ); + + return font; + } + + inline QRgb flattenedColor( QRgb foregroundColor, QRgb backgroundColor ) + { + const qreal alphaRatio = ( ( foregroundColor & QskRgb::AlphaMask ) >> 24 ) / 255.0; + return QskRgb::interpolated( backgroundColor, foregroundColor, alphaRatio ); + } +} + +void Editor::setup() +{ + setupBox(); + setupCheckBox(); + setupComboBox(); + setupDialogButtonBox(); + setupFocusIndicator(); + setupInputPanel(); + setupListView(); + setupMenu(); + setupPageIndicator(); + setupPopup(); + setupProgressBar(); + setupPushButton(); + setupRadioBox(); + setupScrollView(); + setupSegmentedBar(); + setupSeparator(); + setupSlider(); + setupSpinBox(); + setupSubWindow(); + setupSwitchButton(); + setupTabButton(); + setupTabBar(); + setupTabView(); + setupTextInput(); + setupTextLabel(); + setupVirtualKeyboard(); +} + +void Editor::setupBox() +{ +} + +void Editor::setupCheckBox() +{ +} + +void Editor::setupComboBox() +{ +} + +void Editor::setupDialogButtonBox() +{ +} + +void Editor::setupFocusIndicator() +{ +} + +void Editor::setupInputPanel() +{ +} + +void Editor::setupListView() +{ +} + +void Editor::setupMenu() +{ +} + +void Editor::setupPageIndicator() +{ +} + +void Editor::setupPopup() +{ +} + +void Editor::setupProgressBar() +{ +} + +void Editor::setupPushButton() +{ + using Q = QskPushButton; + + setStrutSize( Q::Panel, { 120, 32 } ); + setGradient( Q::Panel, theme.palette.fillColor.accent.defaultColor ); + setBoxShape( Q::Panel, 4 ); + setBoxBorderMetrics( Q::Panel, 1 ); + + QColor restBorderColor1, restBorderColor2; + + restBorderColor1 = flattenedColor( theme.palette.elevation.accentControl.border[ 0 ], + theme.palette.fillColor.accent.defaultColor ); + + restBorderColor2 = flattenedColor( theme.palette.elevation.accentControl.border[ 1 ], + theme.palette.fillColor.accent.defaultColor ); + + setBoxBorderColors( Q::Panel, { restBorderColor1, restBorderColor1, restBorderColor1, restBorderColor2 } ); + + setStrutSize( Q::Icon, { 0, 0 } ); + + setFontRole( Q::Text, QskWindowsSkin::Body ); + setColor( Q::Text, theme.palette.fillColor.textOnAccent.primary ); +} + +void Editor::setupRadioBox() +{ +} + +void Editor::setupScrollView() +{ +} + +void Editor::setupSegmentedBar() +{ +} + +void Editor::setupSeparator() +{ +} + +void Editor::setupSlider() +{ +} + +void Editor::setupSpinBox() +{ +} + +void Editor::setupTabBar() +{ +} + +void Editor::setupTabButton() +{ +} + +void Editor::setupTabView() +{ +} + +void Editor::setupTextLabel() +{ +} + + +void Editor::setupTextInput() +{ +} + +void Editor::setupSwitchButton() +{ +} + +void Editor::setupSubWindow() +{ +} + +void Editor::setupVirtualKeyboard() +{ +} + +QskWindowsTheme::QskWindowsTheme( Theme lightness ) + : QskWindowsTheme( lightness, + { // default Windows accent colors: + 0xff98ecfe, + 0xff60ccfe, + 0xff0093f9, + 0xff0078d4, + 0xff005eb7, + 0xff003d92, + 0xff001968 + } ) +{ +} + +QskWindowsTheme::QskWindowsTheme( Theme theme, std::array< QRgb, NumAccentColors > accentColors ) +{ + if( theme == Light ) + { + // Fill color: + + palette.fillColor.text.primary = QskRgb::toTransparentF( 0xff000000, 0.8956 ); + palette.fillColor.text.secondary = QskRgb::toTransparentF( 0xff000000, 0.6063 ); + palette.fillColor.text.tertiary = QskRgb::toTransparentF( 0xff000000, 0.4458 ); + palette.fillColor.text.disabled = QskRgb::toTransparentF( 0xff000000, 0.3614 ); + + palette.fillColor.accentText.primary = accentColors[ AccentDark2 ]; + palette.fillColor.accentText.secondary = accentColors[ AccentDark3 ]; + palette.fillColor.accentText.tertiary = accentColors[ AccentDark1 ]; + palette.fillColor.accentText.disabled = QskRgb::toTransparentF( 0xff000000, 0.3614 ); + + palette.fillColor.textOnAccent.primary = 0xffffffff; + palette.fillColor.textOnAccent.secondary = QskRgb::toTransparentF( 0xff000000, 0.70 ); + palette.fillColor.textOnAccent.disabled = 0xffffffff; + palette.fillColor.textOnAccent.selectedText = 0xffffffff; + + palette.fillColor.control.transparent = Qt::transparent; + palette.fillColor.control.defaultColor = QskRgb::toTransparentF( 0xff000000, 0.70 ); + palette.fillColor.control.secondary = QskRgb::toTransparentF( 0xff000000, 0.50 ); + palette.fillColor.control.tertiary = QskRgb::toTransparentF( 0xff000000, 0.30 ); + palette.fillColor.control.inputActive = 0xffffffff; + palette.fillColor.control.disabled = QskRgb::toTransparentF( 0xfff9f9f9, 0.30 ); + + palette.fillColor.controlStrong.defaultColor = QskRgb::toTransparentF( 0xff000000, 0.4458 ); + palette.fillColor.controlStrong.disabled = QskRgb::toTransparentF( 0xff000000, 0.3173 ); + + palette.fillColor.subtle.transparent = Qt::transparent; + palette.fillColor.subtle.secondary =QskRgb::toTransparentF( 0xff000000, 0.0373 ); + palette.fillColor.subtle.tertiary = QskRgb::toTransparentF( 0xff000000, 0.0241 ); + palette.fillColor.subtle.disabled = Qt::transparent; + + palette.fillColor.controlSolid.defaultColor = 0xffffffff; + + palette.fillColor.controlAlt.transparent = Qt::transparent; + palette.fillColor.controlAlt.secondary = QskRgb::toTransparentF( 0xff000000, 0.0241 ); + palette.fillColor.controlAlt.tertiary = QskRgb::toTransparentF( 0xff000000, 0.0578 ); + palette.fillColor.controlAlt.quaternary = QskRgb::toTransparentF( 0xff000000, 0.0924 ); + palette.fillColor.controlAlt.disabled = Qt::transparent; + + palette.fillColor.accent.defaultColor = accentColors[ AccentDark1 ]; + palette.fillColor.accent.secondary = QskRgb::toTransparentF( accentColors[ AccentDark1 ], 0.90 ); + palette.fillColor.accent.tertiary = QskRgb::toTransparentF( accentColors[ AccentDark1 ], 0.80 ); + palette.fillColor.accent.disabled = QskRgb::toTransparentF( 0xff000000, 0.2169 ); + palette.fillColor.accent.selectedTextBackground = accentColors[ AccentBase ]; + + palette.fillColor.system.critical = 0xffC42B1C; + palette.fillColor.system.success = 0xff0F7B0F; + palette.fillColor.system.attention = 0xff005FB7; + palette.fillColor.system.caution = 0xff9D5D00; + palette.fillColor.system.attentionBackground = QskRgb::toTransparentF( 0xffF6F6F6, 0.50 ); + palette.fillColor.system.successBackground = 0xffDFF6DD; + palette.fillColor.system.cautionBackground = 0xffFFF4CE; + palette.fillColor.system.criticalBackground = 0xffFDE7E9; + palette.fillColor.system.neutral = QskRgb::toTransparentF( 0xff000000, 0.4458 ); + palette.fillColor.system.neutralBackground = QskRgb::toTransparentF( 0xff000000, 0.0241 ); + palette.fillColor.system.solidNeutral = 0xff8A8A8A; + palette.fillColor.system.solidAttentionBackground = 0xffF7F7F7; + palette.fillColor.system.solidNeutralBackground = 0xffF3F3F3; + + // Elevation: + + palette.elevation.control.border = { QskRgb::toTransparentF( 0xff000000, 0.0578 ), + QskRgb::toTransparentF( 0xff000000, 0.1622 ) }; + + palette.elevation.circle.border = { QskRgb::toTransparentF( 0xff000000, 0.0578 ), + QskRgb::toTransparentF( 0xff000000, 0.1622 ) }; + + palette.elevation.textControl.border = { QskRgb::toTransparentF( 0xff000000, 0.0578 ), + QskRgb::toTransparentF( 0xff000000, 0.0578 ) }; + + palette.elevation.textControl.borderFocused = { QskRgb::toTransparentF( 0xff000000, 0.0578 ), + QskRgb::toTransparentF( 0xff000000, 0.0578 ) }; + + palette.elevation.accentControl.border = { QskRgb::toTransparentF( 0xffffffff, 0.08 ), + QskRgb::toTransparentF( 0xff000000, 0.40 ) }; + + // Stroke color: + + palette.strokeColor.controlStroke.defaultColor = QskRgb::toTransparentF( 0xff000000, 0.0578 ); + palette.strokeColor.controlStroke.secondary = QskRgb::toTransparentF( 0xff000000, 0.1622 ); + palette.strokeColor.controlStroke.onAccentDefault = QskRgb::toTransparentF( 0xffffffff, 0.08 ); + palette.strokeColor.controlStroke.onAccentSecondary = QskRgb::toTransparentF( 0xff000000, 0.40 ); + palette.strokeColor.controlStroke.onAccentTertiary = QskRgb::toTransparentF( 0xff000000, 0.2169 ); + palette.strokeColor.controlStroke.onAccentDisabled = QskRgb::toTransparentF( 0xff000000, 0.0578 ); + palette.strokeColor.controlStroke.forStrongFillWhenOnImage = QskRgb::toTransparentF( 0xffffffff, 0.35 ); + + palette.strokeColor.controlStrongStroke.defaultColor = QskRgb::toTransparentF( 0xff000000, 0.4458 ); + palette.strokeColor.controlStrongStroke.disabled = QskRgb::toTransparentF( 0xff000000, 0.2169 ); + + palette.strokeColor.cardStroke.defaultColor = QskRgb::toTransparentF( 0xff000000, 0.0578 ); + palette.strokeColor.cardStroke.defaultSolid = 0xffEBEBEB; + + palette.strokeColor.dividerStroke.defaultColor = QskRgb::toTransparentF( 0xff000000, 0.0803 ); + + palette.strokeColor.surfaceStroke.defaultColor = QskRgb::toTransparentF( 0xff757575, 0.40 ); + palette.strokeColor.surfaceStroke.flyout = QskRgb::toTransparentF( 0xff000000, 0.0578 ); + + palette.strokeColor.focusStroke.outer = QskRgb::toTransparentF( 0xff000000, 0.8956 ); + palette.strokeColor.focusStroke.inner = 0xffffffff; + + // Background: + + palette.background.fillColor.cardBackground.defaultColor = QskRgb::toTransparentF( 0xffffffff, 0.70 ); + palette.background.fillColor.cardBackground.secondary = QskRgb::toTransparentF( 0xffF6F6F6, 0.50 ); + palette.background.fillColor.cardBackground.tertiary = 0xffffffff; + + palette.background.fillColor.stroke.defaultColor = QskRgb::toTransparentF( 0xff000000, 0.30 ); + + palette.background.fillColor.layer.defaultColor = QskRgb::toTransparentF( 0xffffffff, 0.50 ); + palette.background.fillColor.layer.alt = 0xffffffff; + + palette.background.fillColor.layerOnAcrylic.defaultColor = QskRgb::toTransparentF( 0xffffffff, 0.25 ); + + palette.background.fillColor.layerOnAccentAcrylic.defaultColor = QskRgb::toTransparentF( 0xffffffff, 0.25 ); + + palette.background.fillColor.acrylicBackground.defaultColor = QskRgb::toTransparentF( 0xffFCFCFC, 0.85 ); + palette.background.fillColor.acrylicBackground.base = QskRgb::toTransparentF( 0xffF3F3F3, 0.90 ); + + palette.background.fillColor.accentAcrylicBackground.base = QskRgb::toTransparentF( accentColors[ AccentLight3 ], 0.90 ); + palette.background.fillColor.accentAcrylicBackground.defaultColor = QskRgb::toTransparentF( accentColors[ AccentLight3 ], 0.90 ); + + palette.background.fillColor.micaBackground.base = QskRgb::toTransparentF( 0xffffffff, 0.50 ); + + palette.background.fillColor.solidBackground.base = 0xffF3F3F3; + palette.background.fillColor.solidBackground.secondary = 0xffEEEEEE; + palette.background.fillColor.solidBackground.tertiary = 0xffF9F9F9; + palette.background.fillColor.solidBackground.quaternary = 0xffffffff; + } + else if( theme == Dark ) + { + } +} + +QskWindowsSkin::QskWindowsSkin( const QskWindowsTheme& palette, QObject* parent ) + : Inherited( parent ) +{ + setupFonts(); + setupGraphicFilters( palette ); + + Editor editor( &hintTable(), palette ); + editor.setup(); +} + +QskWindowsSkin::~QskWindowsSkin() +{ +} + +void QskWindowsSkin::setupFonts() +{ + static QString fontName( QStringLiteral( "Segoe UI Variable" ) ); + Inherited::setupFonts( fontName ); + + setFont( Caption, createFont( fontName, 12, 16, 0.0, QFont::Normal ) ); + setFont( Body, createFont( fontName, 14, 20, 0.0, QFont::Normal ) ); + setFont( BodyStrong, createFont( fontName, 14, 20, 0.0, QFont::DemiBold ) ); + setFont( BodyLarge, createFont( fontName, 18, 24, 0.0, QFont::Medium ) ); + setFont( Subtitle, createFont( fontName, 20, 28, 0.0, QFont::DemiBold ) ); + setFont( Title, createFont( fontName, 28, 36, 0.0, QFont::DemiBold ) ); + setFont( TitleLarge, createFont( fontName, 40, 52, 0.0, QFont::DemiBold ) ); + setFont( Display, createFont( fontName, 68, 92, 0.0, QFont::DemiBold ) ); +} + +void QskWindowsSkin::setGraphicColor( GraphicRole role, QRgb rgb ) +{ + QskColorFilter colorFilter; + colorFilter.setMask( QskRgb::RGBAMask ); + colorFilter.addColorSubstitution( QskRgb::Black, rgb ); + + setGraphicFilter( role, colorFilter ); +} + +void QskWindowsSkin::setupGraphicFilters( const QskWindowsTheme& theme ) +{ +// setGraphicColor( GraphicRoleOnPrimary, palette.onPrimary ); +// setGraphicColor( GraphicRoleOnSecondaryContainer, palette.onSecondaryContainer ); +// setGraphicColor( GraphicRoleOnError, palette.onError ); +// setGraphicColor( GraphicRoleOnSurface, palette.onSurface ); +// setGraphicColor( GraphicRoleOnSurface38, palette.onSurface38 ); +// setGraphicColor( GraphicRoleOnSurfaceVariant, palette.onSurfaceVariant ); +// setGraphicColor( GraphicRolePrimary, palette.primary ); +// setGraphicColor( GraphicRoleSurface, palette.surface ); +} + +#include "moc_QskWindowsSkin.cpp" diff --git a/skins/windows/QskWindowsSkin.h b/skins/windows/QskWindowsSkin.h new file mode 100644 index 00000000..45b9bcea --- /dev/null +++ b/skins/windows/QskWindowsSkin.h @@ -0,0 +1,357 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2022 Edelhirsch Software GmbH + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#ifndef QSK_WINDOWS_SKIN_H +#define QSK_WINDOWS_SKIN_H + +#include "QskWindowsGlobal.h" + +#include +#include +#include +#include + +#include + +class QSK_WINDOWS_EXPORT QskWindowsTheme +{ + public: + enum Theme + { + Light, + Dark + }; + + enum AccentColors + { + AccentLight3, + AccentLight2, + AccentLight1, + AccentBase, + AccentDark1, + AccentDark2, + AccentDark3, + + NumAccentColors + }; + + QskWindowsTheme( Theme ); + QskWindowsTheme( Theme, std::array< QRgb, NumAccentColors > ); + + struct FillColor + { + struct Text + { + QRgb primary; + QRgb secondary; + QRgb tertiary; + QRgb disabled; + }; + + struct AccentText + { + QRgb primary; + QRgb secondary; + QRgb tertiary; + QRgb disabled; + }; + + struct TextOnAccent + { + QRgb primary; + QRgb secondary; + QRgb tertiary; + QRgb disabled; + QRgb selectedText; + }; + + struct Control + { + QRgb transparent; + QRgb defaultColor; + QRgb secondary; + QRgb tertiary; + QRgb inputActive; + QRgb disabled; + }; + + struct ControlStrong + { + QRgb defaultColor; + QRgb disabled; + }; + + struct Subtle + { + QRgb transparent; + QRgb secondary; + QRgb tertiary; + QRgb disabled; + }; + + struct ControlSolid + { + QRgb defaultColor; + }; + + struct ControlAlt + { + QRgb transparent; + QRgb secondary; + QRgb tertiary; + QRgb quaternary; + QRgb disabled; + }; + + struct Accent + { + QRgb defaultColor; + QRgb secondary; + QRgb tertiary; + QRgb disabled; + QRgb selectedTextBackground; + }; + + struct System + { + QRgb critical; + QRgb success; + QRgb attention; + QRgb caution; + QRgb attentionBackground; + QRgb successBackground; + QRgb cautionBackground; + QRgb criticalBackground; + QRgb neutral; + QRgb neutralBackground; + QRgb solidNeutral; + QRgb solidAttentionBackground; + QRgb solidNeutralBackground; + }; + + struct ControlOnImage + { + QRgb defaultColor; + QRgb secondary; + QRgb tertiary; + QRgb disabled; + }; + + Text text; + AccentText accentText; + TextOnAccent textOnAccent; + Control control; + ControlStrong controlStrong; + Subtle subtle; + ControlSolid controlSolid; + ControlAlt controlAlt; + Accent accent; + System system; + ControlOnImage controlOnImage; + }; + + struct Elevation + { + struct Control + { + std::array< QRgb, 2 > border; + }; + + struct Circle + { + std::array< QRgb, 2 > border; + }; + + struct TextControl + { + std::array< QRgb, 2 > border; + std::array< QRgb, 2 > borderFocused; + }; + + struct AccentControl + { + std::array< QRgb, 2 > border; + }; + + Control control; + Circle circle; + TextControl textControl; + AccentControl accentControl; + }; + + struct StrokeColor + { + struct ControlStroke + { + QRgb defaultColor; + QRgb secondary; + QRgb onAccentDefault; + QRgb onAccentSecondary; + QRgb onAccentTertiary; + QRgb onAccentDisabled; + QRgb forStrongFillWhenOnImage; + }; + + struct ControlStrongStroke + { + QRgb defaultColor; + QRgb disabled; + }; + + struct CardStroke + { + QRgb defaultColor; + QRgb defaultSolid; + }; + + struct DividerStroke + { + QRgb defaultColor; + }; + + struct SurfaceStroke + { + QRgb defaultColor; + QRgb flyout; + }; + + struct FocusStroke + { + QRgb outer; + QRgb inner; + }; + + ControlStroke controlStroke; + ControlStrongStroke controlStrongStroke; + CardStroke cardStroke; + DividerStroke dividerStroke; + SurfaceStroke surfaceStroke; + FocusStroke focusStroke; + }; + + struct Background + { + struct FillColor + { + struct CardBackground + { + QRgb defaultColor; + QRgb secondary; + QRgb tertiary; + }; + + struct Stroke + { + QRgb defaultColor; + }; + + struct Layer + { + QRgb defaultColor; + QRgb alt; + }; + + struct LayerOnAcrylic + { + QRgb defaultColor; + }; + + struct LayerOnAccentAcrylic + { + QRgb defaultColor; + }; + + struct AcrylicBackground + { + QRgb defaultColor; + QRgb base; + }; + + struct AccentAcrylicBackground + { + QRgb base; + QRgb defaultColor; + }; + + struct MicaBackground + { + QRgb base; + }; + + struct SolidBackground + { + QRgb base; + QRgb secondary; + QRgb tertiary; + QRgb quaternary; + }; + + CardBackground cardBackground; + Stroke stroke; + Layer layer; + LayerOnAcrylic layerOnAcrylic; + LayerOnAccentAcrylic layerOnAccentAcrylic; + AcrylicBackground acrylicBackground; + AccentAcrylicBackground accentAcrylicBackground; + MicaBackground micaBackground; + SolidBackground solidBackground; + }; + + FillColor fillColor; + }; + + + struct Palette + { + FillColor fillColor; + Elevation elevation; + StrokeColor strokeColor; + Background background; + }; + + Palette palette; +}; + +class QSK_WINDOWS_EXPORT QskWindowsSkin : public QskSkin +{ + Q_OBJECT + + using Inherited = QskSkin; + + public: + QskWindowsSkin( const QskWindowsTheme&, QObject* parent = nullptr ); + ~QskWindowsSkin() override; + + enum GraphicRole + { + GraphicRoleOnError, + GraphicRoleOnPrimary, + GraphicRoleOnSecondaryContainer, + GraphicRoleOnSurface, + GraphicRoleOnSurface38, + GraphicRoleOnSurfaceVariant, + GraphicRolePrimary, + GraphicRoleSurface, + }; + + enum FontRole + { + Caption = QskSkin::HugeFont + 1, // ### define QskSkin enums + Body, + BodyStrong, + BodyLarge, + Subtitle, + Title, + TitleLarge, + Display + }; + + private: + void setupFonts(); + void setupGraphicFilters( const QskWindowsTheme& palette ); + void setGraphicColor( GraphicRole, QRgb ); +}; + +#endif diff --git a/skins/windows/QskWindowsSkinFactory.cpp b/skins/windows/QskWindowsSkinFactory.cpp new file mode 100644 index 00000000..1a2091a1 --- /dev/null +++ b/skins/windows/QskWindowsSkinFactory.cpp @@ -0,0 +1,42 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#include "QskWindowsSkinFactory.h" +#include "QskWindowsSkin.h" + +static const QString windowsLightSkinName = QStringLiteral( "Windows Light" ); +static const QString windowsDarkSkinName = QStringLiteral( "Windows Dark" ); + +QskWindowsSkinFactory::QskWindowsSkinFactory( QObject* parent ) + : QskSkinFactory( parent ) +{ +} + +QskWindowsSkinFactory::~QskWindowsSkinFactory() +{ +} + +QStringList QskWindowsSkinFactory::skinNames() const +{ + return { windowsLightSkinName, windowsDarkSkinName }; +} + +QskSkin* QskWindowsSkinFactory::createSkin( const QString& skinName ) +{ + if ( QString::compare( skinName, windowsLightSkinName, Qt::CaseInsensitive ) == 0 ) + { + QskWindowsTheme theme( QskWindowsTheme::Light ); + return new QskWindowsSkin( theme ); + } + else if ( QString::compare( skinName, windowsDarkSkinName, Qt::CaseInsensitive ) == 0 ) + { + QskWindowsTheme theme( QskWindowsTheme::Dark ); + return new QskWindowsSkin( theme ); + } + + return nullptr; +} + +#include "moc_QskWindowsSkinFactory.cpp" diff --git a/skins/windows/QskWindowsSkinFactory.h b/skins/windows/QskWindowsSkinFactory.h new file mode 100644 index 00000000..917db0a0 --- /dev/null +++ b/skins/windows/QskWindowsSkinFactory.h @@ -0,0 +1,28 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#ifndef QSK_WINDOWS_SKIN_FACTORY_H +#define QSK_WINDOWS_SKIN_FACTORY_H + +#include "QskWindowsGlobal.h" +#include + +class QSK_WINDOWS_EXPORT QskWindowsSkinFactory : public QskSkinFactory +{ + Q_OBJECT +#if defined( QSK_Windows_MAKEDLL ) + Q_PLUGIN_METADATA( IID QskSkinFactoryIID FILE "metadata.json" ) + Q_INTERFACES( QskSkinFactory ) +#endif + + public: + QskWindowsSkinFactory( QObject* parent = nullptr ); + ~QskWindowsSkinFactory() override; + + QStringList skinNames() const override; + QskSkin* createSkin( const QString& skinName ) override; +}; + +#endif diff --git a/skins/windows/icons.qrc b/skins/windows/icons.qrc new file mode 100644 index 00000000..ab149d96 --- /dev/null +++ b/skins/windows/icons.qrc @@ -0,0 +1,8 @@ + + + icons/qvg/check_small.qvg + icons/qvg/combo-box-arrow-closed.qvg + icons/qvg/combo-box-arrow-open.qvg + icons/qvg/segmented-button-check.qvg + + diff --git a/skins/windows/icons/check_small.svg b/skins/windows/icons/check_small.svg new file mode 100644 index 00000000..e7a84071 --- /dev/null +++ b/skins/windows/icons/check_small.svg @@ -0,0 +1,4 @@ + + + + diff --git a/skins/windows/icons/combo-box-arrow-closed.svg b/skins/windows/icons/combo-box-arrow-closed.svg new file mode 100644 index 00000000..c288b426 --- /dev/null +++ b/skins/windows/icons/combo-box-arrow-closed.svg @@ -0,0 +1,4 @@ + + + + diff --git a/skins/windows/icons/combo-box-arrow-open.svg b/skins/windows/icons/combo-box-arrow-open.svg new file mode 100644 index 00000000..4138c2cd --- /dev/null +++ b/skins/windows/icons/combo-box-arrow-open.svg @@ -0,0 +1,4 @@ + + + + diff --git a/skins/windows/icons/qvg/check_small.qvg b/skins/windows/icons/qvg/check_small.qvg new file mode 100644 index 00000000..ea738b86 Binary files /dev/null and b/skins/windows/icons/qvg/check_small.qvg differ diff --git a/skins/windows/icons/qvg/combo-box-arrow-closed.qvg b/skins/windows/icons/qvg/combo-box-arrow-closed.qvg new file mode 100644 index 00000000..2585b892 Binary files /dev/null and b/skins/windows/icons/qvg/combo-box-arrow-closed.qvg differ diff --git a/skins/windows/icons/qvg/combo-box-arrow-open.qvg b/skins/windows/icons/qvg/combo-box-arrow-open.qvg new file mode 100644 index 00000000..6ddcf6c0 Binary files /dev/null and b/skins/windows/icons/qvg/combo-box-arrow-open.qvg differ diff --git a/skins/windows/icons/qvg/segmented-button-check.qvg b/skins/windows/icons/qvg/segmented-button-check.qvg new file mode 100644 index 00000000..fa0e1ce2 Binary files /dev/null and b/skins/windows/icons/qvg/segmented-button-check.qvg differ diff --git a/skins/windows/icons/segmented-button-check.svg b/skins/windows/icons/segmented-button-check.svg new file mode 100644 index 00000000..b0b66ac9 --- /dev/null +++ b/skins/windows/icons/segmented-button-check.svg @@ -0,0 +1,4 @@ + + + + diff --git a/skins/windows/metadata.json b/skins/windows/metadata.json new file mode 100644 index 00000000..3ff46a6b --- /dev/null +++ b/skins/windows/metadata.json @@ -0,0 +1,4 @@ +{ + "FactoryId": "WindowsFactory", + "Skins": [ "Windows Light", "Windows Dark" ] +} diff --git a/support/CMakeLists.txt b/support/CMakeLists.txt index b8524692..f89ac309 100644 --- a/support/CMakeLists.txt +++ b/support/CMakeLists.txt @@ -33,7 +33,7 @@ target_include_directories(${target} PUBLIC ${CMAKE_CURRENT_LIST_DIR}) if(ENABLE_ENSURE_SKINS) target_include_directories(${target} PRIVATE ${CMAKE_SOURCE_DIR}/skins) target_compile_definitions(${target} PRIVATE ENSURE_SKINS) - target_link_libraries(${target} PRIVATE squiekskin material3skin) + target_link_libraries(${target} PRIVATE squiekskin material3skin windowsskin) endif() set(HIDE_SYSTEM_FONTS ON) diff --git a/support/SkinnyNamespace.cpp b/support/SkinnyNamespace.cpp index 4a243c16..0d103125 100644 --- a/support/SkinnyNamespace.cpp +++ b/support/SkinnyNamespace.cpp @@ -51,6 +51,7 @@ static bool pluginPath = initPluginPath(); #include #include + #include static void initSkins() { @@ -63,6 +64,7 @@ static bool pluginPath = initPluginPath(); qskSkinManager->registerFactory( "SquiekFactory", new QskSquiekSkinFactory() ); qskSkinManager->registerFactory( "Material3Factory", new QskMaterial3SkinFactory() ); + qskSkinManager->registerFactory( "WindowsFactory", new QskWindowsSkinFactory() ); qWarning() << "Couldn't find skin plugins, adding some manually."; }