Uing RGB values instead of colors. QskSkinTransition reimplemented.

Ongoing work
This commit is contained in:
Uwe Rathmann 2022-03-31 18:29:39 +02:00
parent 5284880eaa
commit 570d3d2d51
41 changed files with 1178 additions and 929 deletions

View File

@ -4,29 +4,11 @@
*****************************************************************************/ *****************************************************************************/
#include "Page.h" #include "Page.h"
#include <QskRgbValue.h>
Page::Page( Qt::Orientation orientation, QQuickItem* parent ) Page::Page( Qt::Orientation orientation, QQuickItem* parent )
: QskLinearBox( orientation, parent ) : QskLinearBox( orientation, parent )
, m_gradient( QskRgb::GhostWhite )
{ {
setMargins( 20 ); setMargins( 20 );
setPadding( 10 ); setPadding( 10 );
setSpacing( 10 ); setSpacing( 10 );
} }
void Page::setGradient( const QskGradient& gradient )
{
if ( gradient != m_gradient )
{
m_gradient = gradient;
if ( parentItem() && isVisibleToParent() )
parentItem()->update();
}
}
QskGradient Page::gradient() const
{
return m_gradient;
}

View File

@ -6,16 +6,9 @@
#pragma once #pragma once
#include <QskLinearBox.h> #include <QskLinearBox.h>
#include <QskGradient.h>
class Page : public QskLinearBox class Page : public QskLinearBox
{ {
public: public:
Page( Qt::Orientation, QQuickItem* parent = nullptr ); Page( Qt::Orientation, QQuickItem* parent = nullptr );
void setGradient( const QskGradient& );
QskGradient gradient() const;
private:
QskGradient m_gradient;
}; };

View File

@ -67,7 +67,6 @@ namespace
LabelPage::LabelPage( QQuickItem* parent ) LabelPage::LabelPage( QQuickItem* parent )
: Page( Qt::Vertical, parent ) : Page( Qt::Vertical, parent )
{ {
setGradient( QskRgb::AliceBlue );
setSpacing( 40 ); setSpacing( 40 );
(void) new TextBox( this ); (void) new TextBox( this );

View File

@ -30,27 +30,6 @@ namespace
setMargins( 10 ); setMargins( 10 );
setTabPosition( Qsk::Left ); setTabPosition( Qsk::Left );
setAutoFitTabs( true ); setAutoFitTabs( true );
connect( this, &QskTabView::currentIndexChanged,
this, &TabView::updateViewPanel );
}
protected:
void aboutToShow() override
{
updateViewPanel();
}
private:
void updateViewPanel()
{
/*
We should have a better way to set individual colors
for each tab page background
*/
if ( auto page = dynamic_cast< const ::Page* >( currentItem() ) )
setGradientHint( QskTabView::Page, page->gradient() );
} }
}; };
} }

View File

@ -45,9 +45,7 @@ namespace
ProgressBarPage::ProgressBarPage( QQuickItem* parent ) ProgressBarPage::ProgressBarPage( QQuickItem* parent )
: Page( Qt::Horizontal, parent ) : Page( Qt::Horizontal, parent )
{ {
setGradient( QskRgb::AliceBlue );
setSpacing( 40 ); setSpacing( 40 );
populate(); populate();
} }

View File

@ -13,8 +13,6 @@
SliderPage::SliderPage( QQuickItem* parentItem ) SliderPage::SliderPage( QQuickItem* parentItem )
: Page( Qt::Vertical, parentItem ) : Page( Qt::Vertical, parentItem )
{ {
setGradient( QskRgb::PeachPuff );
setMargins( 10 ); setMargins( 10 );
setSpacing( 20 ); setSpacing( 20 );

View File

@ -15,9 +15,7 @@
SwitchButtonPage::SwitchButtonPage( QQuickItem* parent ) SwitchButtonPage::SwitchButtonPage( QQuickItem* parent )
: Page( Qt::Horizontal, parent ) : Page( Qt::Horizontal, parent )
{ {
setGradient( QskRgb::AliceBlue );
setSpacing( 40 ); setSpacing( 40 );
populate(); populate();
} }

View File

@ -47,20 +47,12 @@ static const int ButtonFontRole = QskSkin::HugeFont + 77;
static const int qskDuration = 150; static const int qskDuration = 150;
static inline QColor qskShadedColor( const QColor color, qreal opacity )
{
QColor c = color;
c.setAlphaF( opacity );
return c;
}
namespace namespace
{ {
class Editor : private QskSkinHintTableEditor class Editor : private QskSkinHintTableEditor
{ {
public: public:
Editor( QskSkinHintTable* table, const ColorPalette& palette ) Editor( QskSkinHintTable* table, const QskMaterialPalette& palette )
: QskSkinHintTableEditor( table ) : QskSkinHintTableEditor( table )
, m_pal( palette ) , m_pal( palette )
{ {
@ -93,7 +85,7 @@ namespace
void setupTextInput(); void setupTextInput();
void setupTextLabel(); void setupTextLabel();
const ColorPalette& m_pal; const QskMaterialPalette& m_pal;
const uint rippleSize = 30; const uint rippleSize = 30;
}; };
} }
@ -135,7 +127,7 @@ void Editor::setupControl()
setGradient( A::Control, m_pal.background ); setGradient( A::Control, m_pal.background );
setColor( A::Control | A::StyleColor, m_pal.onBackground ); setColor( A::Control | A::StyleColor, m_pal.onBackground );
setColor( A::Control | A::StyleColor | Q::Disabled, setColor( A::Control | A::StyleColor | Q::Disabled,
qskShadedColor( m_pal.onBackground, 0.6 ) ); QskRgb::toTransparentF( m_pal.onBackground, 0.6 ) );
} }
void Editor::setupBox() void Editor::setupBox()
@ -155,8 +147,8 @@ void Editor::setupPopup()
setFlagHint( Q::Overlay | A::Style, true ); setFlagHint( Q::Overlay | A::Style, true );
const QskGradient gradient( QskGradient::Vertical, const QskGradient gradient( QskGradient::Vertical,
qskShadedColor( m_pal.secondary, 0.45 ), QskRgb::toTransparentF( m_pal.secondary, 0.45 ),
qskShadedColor( m_pal.secondary, 0.7 ) ); QskRgb::toTransparentF( m_pal.secondary, 0.7 ) );
setGradient( Q::Overlay, gradient ); setGradient( Q::Overlay, gradient );
} }
@ -196,20 +188,16 @@ void Editor::setupTextInput()
setBoxBorderColors( Q::Panel | Q::Focused, m_pal.primary ); setBoxBorderColors( Q::Panel | Q::Focused, m_pal.primary );
setColor( Q::Panel, setColor( Q::Panel, m_pal.elevated( m_pal.background, 1 ) );
m_pal.elevated( m_pal.background, 1 ) ); setColor( Q::Panel | Q::Hovered, m_pal.elevated( m_pal.background, 2 ) );
setColor( Q::Panel | Q::Hovered, setColor( Q::Panel | Q::Focused, m_pal.elevated( m_pal.background, 3 ) );
m_pal.elevated( m_pal.background, 2 ) ); setColor( Q::Panel | Q::Editing, m_pal.elevated( m_pal.background, 4 ) );
setColor( Q::Panel | Q::Focused,
m_pal.elevated( m_pal.background, 3 ) );
setColor( Q::Panel | Q::Editing,
m_pal.elevated( m_pal.background, 4 ) );
setColor( Q::Panel | Q::Disabled, setColor( Q::Panel | Q::Disabled,
qskShadedColor( m_pal.secondaryVariantNoSaturation, m_pal.disabled ) ); QskRgb::toTransparentF( m_pal.secondaryVariantNoSaturation, m_pal.disabled ) );
setColor( Q::Text | Q::Disabled, qskShadedColor( m_pal.onBackground, m_pal.disabled ) ); setColor( Q::Text | Q::Disabled, QskRgb::toTransparentF( m_pal.onBackground, m_pal.disabled ) );
setBoxBorderColors( Q::Panel, setBoxBorderColors( Q::Panel,
qskShadedColor( m_pal.onBackground, m_pal.disabled ) ); QskRgb::toTransparentF( m_pal.onBackground, m_pal.disabled ) );
} }
void Editor::setupProgressBar() void Editor::setupProgressBar()
@ -233,9 +221,9 @@ void Editor::setupProgressBar()
setGradient( Q::Bar, m_pal.secondary ); setGradient( Q::Bar, m_pal.secondary );
setGradient( Q::Groove | Q::Disabled, setGradient( Q::Groove | Q::Disabled,
qskShadedColor( m_pal.secondaryNoSaturation, m_pal.disabled ) ); QskRgb::toTransparentF( m_pal.secondaryNoSaturation, m_pal.disabled ) );
setGradient( Q::Bar | Q::Disabled, setGradient( Q::Bar | Q::Disabled,
qskShadedColor( m_pal.secondary, m_pal.disabled ) ); QskRgb::toTransparentF( m_pal.secondary, m_pal.disabled ) );
} }
void Editor::setupFocusIndicator() void Editor::setupFocusIndicator()
@ -275,9 +263,9 @@ void Editor::setupPageIndicator()
setGradient( Q::Bullet | Q::Selected, m_pal.secondary ); setGradient( Q::Bullet | Q::Selected, m_pal.secondary );
setGradient( Q::Bullet | Q::Disabled, setGradient( Q::Bullet | Q::Disabled,
qskShadedColor( m_pal.secondaryNoSaturation, m_pal.disabled ) ); QskRgb::toTransparentF( m_pal.secondaryNoSaturation, m_pal.disabled ) );
setGradient( Q::Bullet | Q::Selected | Q::Disabled, setGradient( Q::Bullet | Q::Selected | Q::Disabled,
qskShadedColor( m_pal.secondary, m_pal.disabled ) ); QskRgb::toTransparentF( m_pal.secondary, m_pal.disabled ) );
setSpacing( Q::Panel, qskDpiScaled( 3 ) ); setSpacing( Q::Panel, qskDpiScaled( 3 ) );
setPadding( Q::Panel, 0 ); setPadding( Q::Panel, 0 );
@ -304,19 +292,19 @@ void Editor::setupPushButton()
setGradient( Q::Panel | Q::Flat, White & ColorMask ); setGradient( Q::Panel | Q::Flat, White & ColorMask );
setColor( Q::Text, m_pal.primary ); setColor( Q::Text, m_pal.primary );
setColor( Q::Text | Q::Disabled, qskShadedColor( m_pal.primary, 0.6 ) ); setColor( Q::Text | Q::Disabled, QskRgb::toTransparentF( m_pal.primary, 0.6 ) );
setFontRole( Q::Text, ButtonFontRole ); setFontRole( Q::Text, ButtonFontRole );
setAlignment( Q::Text, Qt::AlignCenter ); setAlignment( Q::Text, Qt::AlignCenter );
setBoxBorderMetrics( Q::Panel, 1 ); setBoxBorderMetrics( Q::Panel, 1 );
setBoxBorderColors( Q::Panel, m_pal.primary ); setBoxBorderColors( Q::Panel, m_pal.primary );
setBoxBorderColors( Q::Panel | Q::Disabled, qskShadedColor( m_pal.onBackground, m_pal.disabled ) ); setBoxBorderColors( Q::Panel | Q::Disabled, QskRgb::toTransparentF( m_pal.onBackground, m_pal.disabled ) );
setColor( Q::Text | Q::Disabled, qskShadedColor( m_pal.onBackground, m_pal.disabled ) ); setColor( Q::Text | Q::Disabled, QskRgb::toTransparentF( m_pal.onBackground, m_pal.disabled ) );
setColor( Q::Panel | Q::Hovered, qskShadedColor( m_pal.primary, m_pal.hover ) ); setColor( Q::Panel | Q::Hovered, QskRgb::toTransparentF( m_pal.primary, m_pal.hover ) );
setColor( Q::Panel | Q::Focused, qskShadedColor( m_pal.primary, m_pal.focused ) ); setColor( Q::Panel | Q::Focused, QskRgb::toTransparentF( m_pal.primary, m_pal.focused ) );
setColor( Q::Panel | Q::Pressed, qskShadedColor( m_pal.primary, m_pal.pressed ) ); setColor( Q::Panel | Q::Pressed, QskRgb::toTransparentF( m_pal.primary, m_pal.pressed ) );
setAnimation( Q::Panel | A::Color, qskDuration ); setAnimation( Q::Panel | A::Color, qskDuration );
setAnimation( Q::Panel | A::Metric, qskDuration ); setAnimation( Q::Panel | A::Metric, qskDuration );
@ -339,7 +327,7 @@ void Editor::setupDialogButton()
setGradient( Q::Panel, m_pal.primary ); setGradient( Q::Panel, m_pal.primary );
setColor( Q::Text, m_pal.onBackground ); setColor( Q::Text, m_pal.onBackground );
setColor( Q::Text | Q::Disabled, qskShadedColor( m_pal.onPrimary, 0.6 ) ); setColor( Q::Text | Q::Disabled, QskRgb::toTransparentF( m_pal.onPrimary, 0.6 ) );
setFontRole( Q::Text, ButtonFontRole ); setFontRole( Q::Text, ButtonFontRole );
setAlignment( Q::Text, Qt::AlignCenter ); setAlignment( Q::Text, Qt::AlignCenter );
@ -385,7 +373,7 @@ void Editor::setupSlider()
setMetric( Q::Panel | A::Size, extent ); setMetric( Q::Panel | A::Size, extent );
setBoxShape( Q::Panel, 0 ); setBoxShape( Q::Panel, 0 );
setBoxBorderMetrics( Q::Panel, 0 ); setBoxBorderMetrics( Q::Panel, 0 );
setGradient( Q::Panel, m_pal.background ); setGradient( Q::Panel, QskGradient() );
setPadding( Q::Panel | A::Horizontal, QskMargins( 0.5 * extent, 0 ) ); setPadding( Q::Panel | A::Horizontal, QskMargins( 0.5 * extent, 0 ) );
setPadding( Q::Panel | A::Vertical, QskMargins( 0, 0.5 * extent ) ); setPadding( Q::Panel | A::Vertical, QskMargins( 0, 0.5 * extent ) );
@ -399,17 +387,17 @@ void Editor::setupSlider()
setBoxShape( subControl, 0 ); setBoxShape( subControl, 0 );
setBoxBorderMetrics( subControl, 0 ); setBoxBorderMetrics( subControl, 0 );
} }
setMetric( Q::Groove | A::Size, qskDpiScaled( 4 ) ); setMetric( Q::Groove | A::Size, qskDpiScaled( 4 ) );
setMetric( Q::Fill | A::Size, qskDpiScaled( 6 ) ); setMetric( Q::Fill | A::Size, qskDpiScaled( 6 ) );
setGradient( Q::Groove, QskRgb::toTransparentF( m_pal.secondary, .38 ) );
setGradient( Q::Groove, qskShadedColor( m_pal.secondary, .38 ) );
setGradient( Q::Groove | Q::Disabled, setGradient( Q::Groove | Q::Disabled,
qskShadedColor( m_pal.secondaryNoSaturation, m_pal.disabled ) ); QskRgb::toTransparentF( m_pal.secondaryNoSaturation, m_pal.disabled ) );
setGradient( Q::Fill, m_pal.secondary ); setGradient( Q::Fill, m_pal.secondary );
setGradient( Q::Fill | Q::Disabled, setGradient( Q::Fill | Q::Disabled,
qskShadedColor( m_pal.secondaryNoSaturation, m_pal.disabled ) ); QskRgb::toTransparentF( m_pal.secondaryNoSaturation, m_pal.disabled ) );
setBoxShape( Q::Handle, 100, Qt::RelativeSize ); setBoxShape( Q::Handle, 100, Qt::RelativeSize );
setBoxBorderMetrics( Q::Handle, 0 ); setBoxBorderMetrics( Q::Handle, 0 );
@ -425,11 +413,13 @@ void Editor::setupSlider()
setBoxBorderMetrics( Q::Handle, qskDpiScaled( rippleSize / 2 ) ); setBoxBorderMetrics( Q::Handle, qskDpiScaled( rippleSize / 2 ) );
setBoxBorderColors( Q::Handle | Q::Hovered, setBoxBorderColors( Q::Handle | Q::Hovered,
qskShadedColor( m_pal.secondary, m_pal.hover ) ); QskRgb::toTransparentF( m_pal.secondary, m_pal.hover ) );
setBoxBorderColors( Q::Handle | Q::Focused, setBoxBorderColors( Q::Handle | Q::Focused,
qskShadedColor( m_pal.secondary, m_pal.focused ) ); QskRgb::toTransparentF( m_pal.secondary, m_pal.focused ) );
setBoxBorderColors( Q::Handle | Q::Pressed, setBoxBorderColors( Q::Handle | Q::Pressed,
qskShadedColor( m_pal.secondary, m_pal.pressed ) ); QskRgb::toTransparentF( m_pal.secondary, m_pal.pressed ) );
// move the handle smoothly, when using keys // move the handle smoothly, when using keys
setAnimation( Q::Handle | A::Metric | A::Position, 2 * qskDuration ); setAnimation( Q::Handle | A::Metric | A::Position, 2 * qskDuration );
@ -451,17 +441,17 @@ void Editor::setupSwitchButton()
setColor( Q::Groove, m_pal.secondaryNoSaturation ); setColor( Q::Groove, m_pal.secondaryNoSaturation );
setGradient( Q::Groove | Q::Disabled, setGradient( Q::Groove | Q::Disabled,
qskShadedColor( m_pal.secondaryNoSaturation, m_pal.disabled ) ); QskRgb::toTransparentF( m_pal.secondaryNoSaturation, m_pal.disabled ) );
setGradient( Q::Groove | Q::Checked, setGradient( Q::Groove | Q::Checked,
m_pal.secondaryVariant ); m_pal.secondaryVariant );
setGradient( Q::Groove | Q::Checked | Q::Disabled, setGradient( Q::Groove | Q::Checked | Q::Disabled,
qskShadedColor( m_pal.secondaryVariant, m_pal.disabledOccupancy ) ); QskRgb::toTransparentF( m_pal.secondaryVariant, m_pal.disabledOccupancy ) );
setBoxShape( Q::Handle, 100, Qt::RelativeSize ); setBoxShape( Q::Handle, 100, Qt::RelativeSize );
setStrutSize( Q::Handle, qskDpiScaled( 2 * radius + rippleSize ), setStrutSize( Q::Handle, qskDpiScaled( 2 * radius + rippleSize ),
qskDpiScaled( 2 * radius + rippleSize ) ); qskDpiScaled( 2 * radius + rippleSize ) );
setGradient( Q::Handle, m_pal.background.lighter( 900 ) ); setGradient( Q::Handle, QskRgb::lighter( m_pal.background, 900 ) );
setGradient( Q::Handle | Q::Checked, m_pal.secondary ); setGradient( Q::Handle | Q::Checked, m_pal.secondary );
@ -474,20 +464,20 @@ void Editor::setupSwitchButton()
setBoxBorderMetrics( Q::Handle, qskDpiScaled( rippleSize / 2 ) ); setBoxBorderMetrics( Q::Handle, qskDpiScaled( rippleSize / 2 ) );
setBoxBorderColors( Q::Handle | Q::Checked | Q::Hovered, setBoxBorderColors( Q::Handle | Q::Checked | Q::Hovered,
qskShadedColor( m_pal.secondary, m_pal.hover ) ); QskRgb::toTransparentF( m_pal.secondary, m_pal.hover ) );
setBoxBorderColors( Q::Handle | Q::Checked | Q::Focused, setBoxBorderColors( Q::Handle | Q::Checked | Q::Focused,
qskShadedColor( m_pal.secondary, m_pal.focused ) ); QskRgb::toTransparentF( m_pal.secondary, m_pal.focused ) );
setBoxBorderColors( Q::Handle | Q::Checked | Q::Pressed, setBoxBorderColors( Q::Handle | Q::Checked | Q::Pressed,
qskShadedColor( m_pal.secondary, m_pal.pressed ) ); QskRgb::toTransparentF( m_pal.secondary, m_pal.pressed ) );
setBoxBorderColors( Q::Handle | Q::Hovered, setBoxBorderColors( Q::Handle | Q::Hovered,
qskShadedColor( m_pal.secondaryVariantNoSaturation, QskRgb::toTransparentF( m_pal.secondaryVariantNoSaturation,
m_pal.hover ) ); m_pal.hover ) );
setBoxBorderColors( Q::Handle | Q::Focused, setBoxBorderColors( Q::Handle | Q::Focused,
qskShadedColor( m_pal.secondaryVariantNoSaturation, QskRgb::toTransparentF( m_pal.secondaryVariantNoSaturation,
m_pal.focused ) ); m_pal.focused ) );
setBoxBorderColors( Q::Handle | Q::Pressed, setBoxBorderColors( Q::Handle | Q::Pressed,
qskShadedColor( m_pal.secondaryVariantNoSaturation, QskRgb::toTransparentF( m_pal.secondaryVariantNoSaturation,
m_pal.pressed ) ); m_pal.pressed ) );
for ( auto state : { A::NoState, Q::Disabled } ) for ( auto state : { A::NoState, Q::Disabled } )
@ -556,15 +546,15 @@ void Editor::setupTabButton()
setColor( Q::Text, m_pal.onBackground ); setColor( Q::Text, m_pal.onBackground );
setColor( Q::Text | Q::Disabled, setColor( Q::Text | Q::Disabled,
qskShadedColor( m_pal.onBackground, QskRgb::toTransparentF( m_pal.onBackground,
m_pal.widgetBackgroundDisabled ) ); m_pal.widgetBackgroundDisabled ) );
setColor( Q::Text | Q::Checked, m_pal.primary ); setColor( Q::Text | Q::Checked, m_pal.primary );
setColor( Q::Text | Q::Hovered, m_pal.primary ); setColor( Q::Text | Q::Hovered, m_pal.primary );
setColor( Q::Panel, m_pal.elevated( m_pal.background ) ); setColor( Q::Panel, m_pal.elevated( m_pal.background ) );
setColor( Q::Panel | Q::Hovered, qskShadedColor( m_pal.primary, m_pal.hover ) ); setColor( Q::Panel | Q::Hovered, QskRgb::toTransparentF( m_pal.primary, m_pal.hover ) );
setColor( Q::Panel | Q::Focused, qskShadedColor( m_pal.primary, m_pal.focused ) ); setColor( Q::Panel | Q::Focused, QskRgb::toTransparentF( m_pal.primary, m_pal.focused ) );
setColor( Q::Panel | Q::Pressed, qskShadedColor( m_pal.primary, m_pal.pressed ) ); setColor( Q::Panel | Q::Pressed, QskRgb::toTransparentF( m_pal.primary, m_pal.pressed ) );
setAnimation( Q::Panel | A::Color, qskDuration ); setAnimation( Q::Panel | A::Color, qskDuration );
@ -587,9 +577,11 @@ void Editor::setupTabBar()
setAnimation( Q::Panel | A::Metric, QskAnimationHint( 200, QEasingCurve::InCubic ) ); setAnimation( Q::Panel | A::Metric, QskAnimationHint( 200, QEasingCurve::InCubic ) );
} }
void Editor::setupTabView() { void Editor::setupTabView()
{
using Q = QskTabView; using Q = QskTabView;
setGradient( Q::Page, m_pal.background );
setAnimation( Q::Page, qskDuration ); setAnimation( Q::Page, qskDuration );
} }
@ -654,7 +646,7 @@ void Editor::setupScrollView()
{ {
setBoxShape( subControl, 3 ); setBoxShape( subControl, 3 );
setBoxBorderMetrics( subControl, 0 ); setBoxBorderMetrics( subControl, 0 );
setColor( subControl, qskShadedColor( m_pal.onBackground, m_pal.hover ) ); setColor( subControl, QskRgb::toTransparentF( m_pal.onBackground, m_pal.hover ) );
setAnimation( subControl | A::Color, qskDuration ); setAnimation( subControl | A::Color, qskDuration );
} }
@ -663,7 +655,7 @@ void Editor::setupScrollView()
Q::VerticalScrollHandle | Q::VerticalHandlePressed } ) Q::VerticalScrollHandle | Q::VerticalHandlePressed } )
{ {
setColor( subControl, setColor( subControl,
qskShadedColor( m_pal.onBackground, m_pal.pressed ) ); QskRgb::toTransparentF( m_pal.onBackground, m_pal.pressed ) );
} }
// when changing the position by QskScrollView::scrollTo // when changing the position by QskScrollView::scrollTo
@ -679,7 +671,7 @@ void Editor::setupListView()
setColor( Q::Cell, m_pal.background ); setColor( Q::Cell, m_pal.background );
setColor( Q::Text, m_pal.onBackground ); setColor( Q::Text, m_pal.onBackground );
setColor( Q::Cell | Q::Selected, qskShadedColor( m_pal.onBackground, m_pal.focused ) ); setColor( Q::Cell | Q::Selected, QskRgb::toTransparentF( m_pal.onBackground, m_pal.focused ) );
setColor( Q::Text | Q::Selected, m_pal.onBackground ); setColor( Q::Text | Q::Selected, m_pal.onBackground );
} }
@ -713,15 +705,8 @@ void Editor::setupSubWindow()
} }
class QskMaterialSkin::PrivateData QskMaterialSkin::QskMaterialSkin( const QskMaterialPalette& palette, QObject* parent )
{
public:
ColorPalette palette;
};
QskMaterialSkin::QskMaterialSkin( ColorPalette colors, QObject* parent )
: Inherited( parent ) : Inherited( parent )
, m_data( new PrivateData { colors } )
{ {
// Default theme colors // Default theme colors
setupFonts( QStringLiteral( "Roboto" ) ); setupFonts( QStringLiteral( "Roboto" ) );
@ -730,7 +715,7 @@ QskMaterialSkin::QskMaterialSkin( ColorPalette colors, QObject* parent )
buttonFont.setCapitalization( QFont::AllUppercase ); buttonFont.setCapitalization( QFont::AllUppercase );
setFont( ButtonFontRole, buttonFont ); setFont( ButtonFontRole, buttonFont );
Editor editor( &hintTable(), m_data->palette ); Editor editor( &hintTable(), palette );
editor.setup(); editor.setup();
} }

View File

@ -9,86 +9,56 @@
#include "QskMaterialGlobal.h" #include "QskMaterialGlobal.h"
#include <QskSkin.h> #include <QskSkin.h>
#include <QskRgbValue.h> #include <QskRgbValue.h>
#include <memory>
struct ColorPalette class QSK_MATERIAL_EXPORT QskMaterialPalette
{ {
enum Lightness { light, dark } lightness; public:
enum Lightness
QColor primary;
QColor primaryVariant;
QColor onPrimary;
QColor secondary;
QColor secondaryVariant;
QColor onSecondary;
QColor background;
QColor onBackground;
QColor error;
QColor onError;
QColor primaryNoSaturation = QColor::fromHsl( primary.hslHue(), 0,
primary.lightness() );
QColor secondaryNoSaturation =
QColor::fromHsl( secondary.hslHue(), 0,
secondary.lightness() );
QColor secondaryVariantNoSaturation =
QColor::fromHsl( secondaryVariant.hslHue(), 0,
secondaryVariant.lightness() +
secondaryVariant.hslSaturation() );
qreal disabledOccupancy = 0.2;
qreal widgetBackgroundDisabled = 0.6;
qreal hover = 0.1;
qreal focused = 0.4;
qreal pressed = 0.5;
qreal disabled = 0.3;
ColorPalette(
Lightness lightness = light,
QColor primary = QColor::fromRgb( 0x6200EE ),
QColor primaryVariant = QColor::fromRgb( 0x3700B3 ),
QColor onPrimary = Qt::white,
QColor secondary = QColor::fromRgb( 0x03DAC6 ),
QColor secondaryVariant = QColor::fromRgb( 0x018786 ),
QColor onSecondary = Qt::white,
QColor background = QColor::fromRgba( QskRgb::Grey100 ),
QColor onBackground = Qt::black,
QColor error = QColor::fromRgb( 0xB00020 ),
QColor onError = Qt::white ):
lightness( lightness ),
primary( primary ),
primaryVariant( primaryVariant ),
onPrimary( onPrimary ),
secondary( secondary ),
secondaryVariant( secondaryVariant ),
onSecondary( onSecondary ),
background( background ),
onBackground( onBackground ),
error( error ),
onError( onError )
{ {
primaryNoSaturation = QColor::fromHsl( primary.hslHue(), 0, Light,
primary.lightness() ); Dark
};
secondaryNoSaturation = QColor::fromHsl( secondary.hslHue(), QskMaterialPalette( Lightness lightness )
0, : m_lightness( lightness )
secondary.lightness() ); {
secondaryVariantNoSaturation =
QColor::fromHsl( secondaryVariant.hslHue(), 0,
secondaryVariant.lightness() );
} }
inline QColor elevated( const QColor target, const float level = 1 ) const { inline QRgb elevated( const QRgb rgb, const float level = 1 ) const
return ( lightness == light ) ? target.darker( 100 + level * 15 ) {
: target.lighter( 130 + level * 30 ); return ( m_lightness == Light )
? QskRgb::darker( rgb, 100 + level * 15 )
: QskRgb::lighter( rgb, 130 + level * 30 );
} }
public:
QRgb primary;
QRgb primaryVariant;
QRgb onPrimary;
QRgb secondary;
QRgb secondaryVariant;
QRgb onSecondary;
QRgb background;
QRgb onBackground;
QRgb error;
QRgb onError;
QRgb primaryNoSaturation;
QRgb secondaryNoSaturation;
QRgb secondaryVariantNoSaturation;
const qreal disabledOccupancy = 0.2;
const qreal widgetBackgroundDisabled = 0.6;
const qreal hover = 0.1;
const qreal focused = 0.4;
const qreal pressed = 0.5;
const qreal disabled = 0.3;
const Lightness m_lightness;
}; };
class QSK_MATERIAL_EXPORT QskMaterialSkin : public QskSkin class QSK_MATERIAL_EXPORT QskMaterialSkin : public QskSkin
@ -98,12 +68,8 @@ class QSK_MATERIAL_EXPORT QskMaterialSkin : public QskSkin
using Inherited = QskSkin; using Inherited = QskSkin;
public: public:
QskMaterialSkin( ColorPalette, QObject* parent = nullptr ); QskMaterialSkin( const QskMaterialPalette&, QObject* parent = nullptr );
~QskMaterialSkin() override; ~QskMaterialSkin() override;
private:
class PrivateData;
std::unique_ptr< PrivateData > m_data;
}; };
#endif #endif

View File

@ -9,6 +9,42 @@
static const QString materialLightSkinName = QStringLiteral( "materialLight" ); static const QString materialLightSkinName = QStringLiteral( "materialLight" );
static const QString materialDarkSkinName = QStringLiteral( "materialDark" ); static const QString materialDarkSkinName = QStringLiteral( "materialDark" );
namespace
{
inline int lightnessRgb( QRgb rgb )
{
const int red = qRed( rgb );
const int green = qGreen( rgb );
const int blue = qBlue( rgb );
int min, max;
if ( red > green )
{
max = qMax( red, blue );
min = qMin( green, blue );
}
else
{
max = qMax( green, blue );
min = qMin( red, blue );
}
return ( max + min ) / 2;
}
inline QRgb toUnsaturated( QRgb rgb )
{
/*
a saturation of 0 results in having the lightness as r,g,b
Is this intended ?
*/
const auto l = lightnessRgb( rgb );
return qRgba( l, l, l, qAlpha( rgb ) );
}
}
QskMaterialSkinFactory::QskMaterialSkinFactory( QObject* parent ) QskMaterialSkinFactory::QskMaterialSkinFactory( QObject* parent )
: QskSkinFactory( parent ) : QskSkinFactory( parent )
{ {
@ -25,24 +61,48 @@ QStringList QskMaterialSkinFactory::skinNames() const
QskSkin* QskMaterialSkinFactory::createSkin( const QString& skinName ) QskSkin* QskMaterialSkinFactory::createSkin( const QString& skinName )
{ {
if ( QString::compare( skinName, materialLightSkinName, Qt::CaseInsensitive ) ) if ( QString::compare( skinName, materialLightSkinName, Qt::CaseInsensitive ) == 0 )
return new QskMaterialSkin( ColorPalette() );
if ( QString::compare( skinName, materialDarkSkinName, Qt::CaseInsensitive ) )
{ {
return new QskMaterialSkin( ColorPalette( QskMaterialPalette pal( QskMaterialPalette::Light );;
ColorPalette::dark, // lightness
QColor::fromRgb( 0xBB86FC ), // primary pal.primary = 0xff6200ee;
QColor::fromRgb( 0x3700B3 ), // primaryVariant pal.primaryVariant = 0xff3700b3;
Qt::black, // onPrimary pal.onPrimary = QskRgb::White;
QColor::fromRgb( 0x03DAC6 ), // secondary pal.secondary = 0xff03dac6;
QColor::fromRgb( 0x018786 ), // secondaryVariant pal.secondaryVariant = 0xff018786;
Qt::black, // onSecondary pal.onSecondary = QskRgb::White;
QColor::fromRgb( 0x121212 ), // background pal.background = QskRgb::Grey100;
Qt::white, // onBackground pal.onBackground = QskRgb::Black;
QColor::fromRgb( 0xCF6679 ), // error pal.error = 0xffb00020;
Qt::black // onError pal.onError = QskRgb::White;
) );
pal.primaryNoSaturation = toUnsaturated( pal.primary );
pal.secondaryNoSaturation = toUnsaturated( pal.secondary );
pal.secondaryVariantNoSaturation = toUnsaturated( pal.secondaryVariant );
return new QskMaterialSkin( pal );
}
if ( QString::compare( skinName, materialDarkSkinName, Qt::CaseInsensitive ) == 0 )
{
QskMaterialPalette pal( QskMaterialPalette::Dark );
pal.primary = 0xffbb86fc;
pal.primaryVariant = 0xff3700b3;
pal.onPrimary = QskRgb::Black;
pal.secondary = 0xff03dac6;
pal.secondaryVariant = 0xff018786;
pal.onSecondary = QskRgb::Black;
pal.background = 0xff121212;
pal.onBackground = QskRgb::White;
pal.error = 0xffcf6679;
pal.onError = QskRgb::Black;
pal.primaryNoSaturation = toUnsaturated( pal.primary );
pal.secondaryNoSaturation = toUnsaturated( pal.secondary );
pal.secondaryVariantNoSaturation = toUnsaturated( pal.secondaryVariant );
return new QskMaterialSkin( pal );
} }
return nullptr; return nullptr;

View File

@ -647,51 +647,38 @@ void Editor::setupSlider()
// Panel // Panel
for ( auto placement : { A::Horizontal, A::Vertical } ) setMetric( Q::Panel | A::Size, extent );
{ setBoxBorderMetrics( Q::Panel, 0 );
const auto aspect = Q::Panel | placement; setBoxShape( Q::Panel, 0 );
setGradient( Q::Panel, QskGradient() );
setMetric( aspect | A::Size, extent );
setBoxBorderMetrics( aspect, 0 );
setBoxShape( aspect, 0 );
setGradient( aspect, QskGradient() );
}
setPadding( Q::Panel | A::Horizontal, QskMargins( 0.5 * extent, 0 ) ); setPadding( Q::Panel | A::Horizontal, QskMargins( 0.5 * extent, 0 ) );
setPadding( Q::Panel | A::Vertical, QskMargins( 0, 0.5 * extent ) ); setPadding( Q::Panel | A::Vertical, QskMargins( 0, 0.5 * extent ) );
// Groove, Fill // Groove, Fill
for ( auto placement : { A::Horizontal, A::Vertical } ) for ( auto subControl : { Q::Groove, Q::Fill } )
{ {
for ( auto subControl : { Q::Groove, Q::Fill } ) const auto aspect = subControl;
{
const auto aspect = subControl | placement;
setMetric( aspect | A::Size, 0.3 * extent ); setMetric( aspect | A::Size, 0.3 * extent );
setPadding( aspect, 0 ); setPadding( aspect, 0 );
setBoxBorderMetrics( aspect, 0 ); setBoxBorderMetrics( aspect, 0 );
setBoxShape( aspect, 0.1 * extent ); setBoxShape( aspect, 0.1 * extent );
}
setGradient( Q::Groove | placement, m_pal.darker200 );
setGradient( Q::Fill | placement, QskGradient() ); // no filling
} }
setGradient( Q::Groove, m_pal.darker200 );
setGradient( Q::Fill, QskGradient() ); // no filling
// Handle // Handle
for ( auto placement : { A::Horizontal, A::Vertical } ) setButton( Q::Handle, Raised, 1 );
{ setBoxShape( Q::Handle, 20.0, Qt::RelativeSize );
const auto aspect = Q::Handle | placement; setButton( Q::Handle | Q::Pressed, Sunken, 1 );
setButton( aspect, Raised, 1 ); const qreal sz = 0.75 * extent;
setBoxShape( aspect, 20.0, Qt::RelativeSize ); setStrutSize( Q::Handle, sz, sz );
setButton( aspect | Q::Pressed, Sunken, 1 );
const qreal sz = 0.75 * extent;
setStrutSize( aspect, sz, sz );
}
setAnimation( Q::Handle | A::Color, qskDuration ); setAnimation( Q::Handle | A::Color, qskDuration );
} }

View File

@ -24,7 +24,7 @@ QStringList QskSquiekSkinFactory::skinNames() const
QskSkin* QskSquiekSkinFactory::createSkin( const QString& skinName ) QskSkin* QskSquiekSkinFactory::createSkin( const QString& skinName )
{ {
if ( skinName.toLower() == squiekSkinName ) if ( QString::compare( skinName, squiekSkinName, Qt::CaseInsensitive ) == 0 )
return new QskSquiekSkin(); return new QskSquiekSkin();
return nullptr; return nullptr;

View File

@ -11,6 +11,10 @@
static void qskRegisterArcMetrics() static void qskRegisterArcMetrics()
{ {
qRegisterMetaType< QskArcMetrics >(); qRegisterMetaType< QskArcMetrics >();
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
QMetaType::registerEqualsComparator< QskArcMetrics >();
#endif
} }
Q_CONSTRUCTOR_FUNCTION( qskRegisterArcMetrics ) Q_CONSTRUCTOR_FUNCTION( qskRegisterArcMetrics )

View File

@ -109,8 +109,18 @@ class QSK_EXPORT QskAspect
constexpr QskAspect operator|( Type ) const noexcept; constexpr QskAspect operator|( Type ) const noexcept;
constexpr QskAspect operator|( Primitive ) const noexcept; constexpr QskAspect operator|( Primitive ) const noexcept;
constexpr QskAspect operator|( Placement ) const noexcept; constexpr QskAspect operator|( Placement ) const noexcept;
constexpr QskAspect operator|( State ) const noexcept; constexpr QskAspect operator|( State ) const noexcept;
QskAspect& operator|=( State ) noexcept;
constexpr QskAspect operator&( State ) const noexcept;
QskAspect& operator&=( State ) noexcept;
constexpr QskAspect operator|( States ) const noexcept; constexpr QskAspect operator|( States ) const noexcept;
QskAspect& operator|=( States ) noexcept;
constexpr QskAspect operator&( States ) const noexcept;
QskAspect& operator&=( States ) noexcept;
constexpr QskAspect stateless() const noexcept; constexpr QskAspect stateless() const noexcept;
constexpr QskAspect trunk() const noexcept; constexpr QskAspect trunk() const noexcept;
@ -283,12 +293,48 @@ inline constexpr QskAspect QskAspect::operator|( State state ) const noexcept
m_bits.primitive, m_bits.placement, m_bits.states | state ); m_bits.primitive, m_bits.placement, m_bits.states | state );
} }
inline QskAspect& QskAspect::operator|=( State state ) noexcept
{
m_bits.states |= state;
return *this;
}
inline constexpr QskAspect QskAspect::operator&( State state ) const noexcept
{
return QskAspect( m_bits.subControl, m_bits.type, m_bits.isAnimator,
m_bits.primitive, m_bits.placement, m_bits.states & state );
}
inline QskAspect& QskAspect::operator&=( State state ) noexcept
{
m_bits.states &= state;
return *this;
}
inline constexpr QskAspect QskAspect::operator|( States states ) const noexcept inline constexpr QskAspect QskAspect::operator|( States states ) const noexcept
{ {
return QskAspect( m_bits.subControl, m_bits.type, m_bits.isAnimator, return QskAspect( m_bits.subControl, m_bits.type, m_bits.isAnimator,
m_bits.primitive, m_bits.placement, m_bits.states | states ); m_bits.primitive, m_bits.placement, m_bits.states | states );
} }
inline QskAspect& QskAspect::operator|=( States states ) noexcept
{
m_bits.states |= states;
return *this;
}
inline constexpr QskAspect QskAspect::operator&( States states ) const noexcept
{
return QskAspect( m_bits.subControl, m_bits.type, m_bits.isAnimator,
m_bits.primitive, m_bits.placement, m_bits.states & states );
}
inline QskAspect& QskAspect::operator&=( States states ) noexcept
{
m_bits.states &= states;
return *this;
}
inline constexpr QskAspect QskAspect::stateless() const noexcept inline constexpr QskAspect QskAspect::stateless() const noexcept
{ {
return QskAspect( m_bits.subControl, m_bits.type, m_bits.isAnimator, return QskAspect( m_bits.subControl, m_bits.type, m_bits.isAnimator,
@ -538,6 +584,11 @@ namespace std
}; };
} }
inline QskHashValue qHash( const QskAspect aspect, QskHashValue seed = 0 ) noexcept
{
return qHash( aspect.value(), seed );
}
#ifndef QT_NO_DEBUG_STREAM #ifndef QT_NO_DEBUG_STREAM
class QDebug; class QDebug;

View File

@ -13,6 +13,10 @@ static void qskRegisterBoxBorderColors()
{ {
qRegisterMetaType< QskBoxBorderColors >(); qRegisterMetaType< QskBoxBorderColors >();
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
QMetaType::registerEqualsComparator< QskBoxBorderColors >();
#endif
QMetaType::registerConverter< QColor, QskBoxBorderColors >( QMetaType::registerConverter< QColor, QskBoxBorderColors >(
[]( const QColor& color ) { return QskBoxBorderColors( color ); } ); []( const QColor& color ) { return QskBoxBorderColors( color ); } );
@ -110,6 +114,26 @@ void QskBoxBorderColors::setGradientAt( Qt::Edges edges, const QskGradient& grad
m_gradients[ Qsk::Bottom ] = gradient; m_gradients[ Qsk::Bottom ] = gradient;
} }
void QskBoxBorderColors::setLeft( const QskGradient& gradient )
{
m_gradients[ Qsk::Left ] = gradient;
}
void QskBoxBorderColors::setTop( const QskGradient& gradient )
{
m_gradients[ Qsk::Top ] = gradient;
}
void QskBoxBorderColors::setRight( const QskGradient& gradient )
{
m_gradients[ Qsk::Right ] = gradient;
}
void QskBoxBorderColors::setBottom( const QskGradient& gradient )
{
m_gradients[ Qsk::Bottom ] = gradient;
}
const QskGradient& QskBoxBorderColors::gradientAt( Qt::Edge edge ) const const QskGradient& QskBoxBorderColors::gradientAt( Qt::Edge edge ) const
{ {
switch ( edge ) switch ( edge )
@ -165,6 +189,14 @@ bool QskBoxBorderColors::isMonochrome() const
&& m_gradients[ 3 ].isMonochrome(); && m_gradients[ 3 ].isMonochrome();
} }
bool QskBoxBorderColors::isValid() const
{
return m_gradients[ 0 ].isValid()
|| m_gradients[ 1 ].isValid()
|| m_gradients[ 2 ].isValid()
|| m_gradients[ 3 ].isValid();
}
QskBoxBorderColors QskBoxBorderColors::interpolated( QskBoxBorderColors QskBoxBorderColors::interpolated(
const QskBoxBorderColors& to, qreal ratio ) const const QskBoxBorderColors& to, qreal ratio ) const
{ {
@ -172,8 +204,14 @@ QskBoxBorderColors QskBoxBorderColors::interpolated(
for ( size_t i = 0; i < 4; i++ ) for ( size_t i = 0; i < 4; i++ )
{ {
colors.m_gradients[ i ] = colors.m_gradients[ i ].interpolated( #if 1
to.m_gradients[ i ], ratio ); /*
When one border has a width of 0 we would prefer to ignore
the color and use always use the other color. TODO ...
*/
#endif
auto& gradient = colors.m_gradients[ i ];
gradient = gradient.interpolated( to.m_gradients[ i ], ratio );
} }
return colors; return colors;
@ -204,14 +242,44 @@ QDebug operator<<( QDebug debug, const QskBoxBorderColors& colors )
QDebugStateSaver saver( debug ); QDebugStateSaver saver( debug );
debug.nospace(); debug.nospace();
debug << "BoxBorderColors" << '('; debug << "BoxBorderColors";
debug << " L" << colors.gradient( Qsk::Left ); if ( !colors.isValid() )
debug << ", T" << colors.gradient( Qsk::Top ); {
debug << ", R" << colors.gradient( Qsk::Right ); debug << "()";
debug << ", B" << colors.gradient( Qsk::Bottom ); }
else
{
debug << "( ";
debug << " )"; if ( colors.isMonochrome() )
{
const auto& gradient = colors.gradient( Qsk::Left );
QskRgb::debugColor( debug, gradient.startColor() );
}
else
{
const char prompts[] = { 'L', 'T', 'R', 'B' };
for ( int i = 0; i <= Qsk::Bottom; i++ )
{
if ( i != 0 )
debug << ", ";
const auto& gradient = colors.gradient(
static_cast< Qsk::Position >( i ) );
debug << prompts[ i ] << ": ";
if ( gradient.isValid() && gradient.isMonochrome() )
QskRgb::debugColor( debug, gradient.startColor() );
else
debug << gradient;
}
}
debug << " )";
}
return debug; return debug;
} }

View File

@ -12,10 +12,15 @@
#include <qcolor.h> #include <qcolor.h>
#include <qmetatype.h> #include <qmetatype.h>
class QDebug;
class QSK_EXPORT QskBoxBorderColors class QSK_EXPORT QskBoxBorderColors
{ {
Q_GADGET
Q_PROPERTY( QskGradient left READ left WRITE setLeft )
Q_PROPERTY( QskGradient top READ top WRITE setTop )
Q_PROPERTY( QskGradient right READ right WRITE setRight )
Q_PROPERTY( QskGradient bottom READ bottom WRITE setBottom )
public: public:
QskBoxBorderColors(); QskBoxBorderColors();
@ -44,6 +49,18 @@ class QSK_EXPORT QskBoxBorderColors
void setGradientAt( Qt::Edges, const QskGradient& ); void setGradientAt( Qt::Edges, const QskGradient& );
const QskGradient& gradientAt( Qt::Edge ) const; const QskGradient& gradientAt( Qt::Edge ) const;
void setLeft( const QskGradient& );
const QskGradient& left() const;
void setTop( const QskGradient& );
const QskGradient& top() const;
void setRight( const QskGradient& );
const QskGradient& right() const;
void setBottom( const QskGradient& );
const QskGradient& bottom() const;
QskBoxBorderColors interpolated( const QskBoxBorderColors&, qreal value ) const; QskBoxBorderColors interpolated( const QskBoxBorderColors&, qreal value ) const;
static QVariant interpolate( const QskBoxBorderColors&, static QVariant interpolate( const QskBoxBorderColors&,
@ -53,6 +70,7 @@ class QSK_EXPORT QskBoxBorderColors
bool isMonochrome() const; bool isMonochrome() const;
bool isVisible() const; bool isVisible() const;
bool isValid() const;
private: private:
QskGradient m_gradients[ 4 ]; QskGradient m_gradients[ 4 ];
@ -78,8 +96,29 @@ inline const QskGradient& QskBoxBorderColors::gradient( Qsk::Position position )
return m_gradients[ position ]; return m_gradients[ position ];
} }
inline const QskGradient& QskBoxBorderColors::left() const
{
return m_gradients[ Qsk::Left ];
}
inline const QskGradient& QskBoxBorderColors::top() const
{
return m_gradients[ Qsk::Top ];
}
inline const QskGradient& QskBoxBorderColors::right() const
{
return m_gradients[ Qsk::Right ];
}
inline const QskGradient& QskBoxBorderColors::bottom() const
{
return m_gradients[ Qsk::Bottom ];
}
#ifndef QT_NO_DEBUG_STREAM #ifndef QT_NO_DEBUG_STREAM
class QDebug;
QSK_EXPORT QDebug operator<<( QDebug, const QskBoxBorderColors& ); QSK_EXPORT QDebug operator<<( QDebug, const QskBoxBorderColors& );
#endif #endif

View File

@ -12,6 +12,10 @@ static void qskRegisterBoxBorderMetrics()
{ {
qRegisterMetaType< QskBoxBorderMetrics >(); qRegisterMetaType< QskBoxBorderMetrics >();
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
QMetaType::registerEqualsComparator< QskBoxBorderMetrics >();
#endif
QMetaType::registerConverter< QskMargins, QskBoxBorderMetrics >( QMetaType::registerConverter< QskMargins, QskBoxBorderMetrics >(
[]( const QskMargins& margins ) { return QskBoxBorderMetrics( margins ); } ); []( const QskMargins& margins ) { return QskBoxBorderMetrics( margins ); } );
@ -109,9 +113,24 @@ QDebug operator<<( QDebug debug, const QskBoxBorderMetrics& metrics )
QDebugStateSaver saver( debug ); QDebugStateSaver saver( debug );
debug.nospace(); debug.nospace();
debug << "BoxBorder" << '('; debug << "BoxBorder" << "( ";
debug << metrics.sizeMode() << ',' << metrics.widths();
debug << ')'; if ( metrics.sizeMode() != Qt::AbsoluteSize )
debug << metrics.sizeMode() << ", ";
const auto& w = metrics.widths();
if ( metrics.isEquidistant() )
{
debug << w.left();
}
else
{
const char s[] = ", ";
debug << w.left() << s << w.top() << s << w.right() << s << w.bottom();
}
debug << " )";
return debug; return debug;
} }

View File

@ -60,6 +60,8 @@ class QSK_EXPORT QskBoxBorderMetrics
static QVariant interpolate( const QskBoxBorderMetrics&, static QVariant interpolate( const QskBoxBorderMetrics&,
const QskBoxBorderMetrics&, qreal progress ); const QskBoxBorderMetrics&, qreal progress );
constexpr bool isEquidistant() const noexcept;
private: private:
QskMargins m_widths; QskMargins m_widths;
Qt::SizeMode m_sizeMode; Qt::SizeMode m_sizeMode;
@ -115,6 +117,11 @@ inline constexpr bool QskBoxBorderMetrics::isNull() const noexcept
return m_widths.isNull(); return m_widths.isNull();
} }
inline constexpr bool QskBoxBorderMetrics::isEquidistant() const noexcept
{
return m_widths.isEquidistant();
}
inline constexpr const QskMargins& QskBoxBorderMetrics::widths() const noexcept inline constexpr const QskMargins& QskBoxBorderMetrics::widths() const noexcept
{ {
return m_widths; return m_widths;

View File

@ -14,6 +14,10 @@ static void qskRegisterBoxShapeMetrics()
{ {
qRegisterMetaType< QskBoxShapeMetrics >(); qRegisterMetaType< QskBoxShapeMetrics >();
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
QMetaType::registerEqualsComparator< QskBoxShapeMetrics >();
#endif
QMetaType::registerConverter< int, QskBoxShapeMetrics >( QMetaType::registerConverter< int, QskBoxShapeMetrics >(
[]( int radius ) { return QskBoxShapeMetrics( radius ); } ); []( int radius ) { return QskBoxShapeMetrics( radius ); } );

View File

@ -15,6 +15,10 @@ static void qskRegisterGradient()
{ {
qRegisterMetaType< QskGradient >(); qRegisterMetaType< QskGradient >();
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
QMetaType::registerEqualsComparator< QskGradient >();
#endif
QMetaType::registerConverter< QColor, QskGradient >( QMetaType::registerConverter< QColor, QskGradient >(
[]( const QColor& color ) { return QskGradient( color ); } ); []( const QColor& color ) { return QskGradient( color ); } );
} }
@ -229,6 +233,11 @@ QskGradient::QskGradient( Orientation orientation, const QskGradientStops& stops
setStops( stops ); setStops( stops );
} }
QskGradient::QskGradient( Qt::Orientation orientation, QGradient::Preset preset )
: QskGradient( qskOrientation( orientation ), preset )
{
}
QskGradient::QskGradient( Orientation orientation, QGradient::Preset preset ) QskGradient::QskGradient( Orientation orientation, QGradient::Preset preset )
: QskGradient( orientation ) : QskGradient( orientation )
{ {
@ -499,6 +508,14 @@ QskGradient QskGradient::interpolated(
return QskGradient( gradient->orientation(), stops ); return QskGradient( gradient->orientation(), stops );
} }
if ( isMonochrome() && to.isMonochrome() )
{
const auto c = QskRgb::interpolated(
m_stops[ 0 ].color(), to.m_stops[ 0 ].color(), value );
return QskGradient( to.orientation(), c, c );
}
if ( isMonochrome() ) if ( isMonochrome() )
{ {
// we can ignore our stops // we can ignore our stops
@ -624,7 +641,49 @@ void QskGradient::updateStatusBits() const
QDebug operator<<( QDebug debug, const QskGradient& gradient ) QDebug operator<<( QDebug debug, const QskGradient& gradient )
{ {
debug << "GR:" << gradient.orientation() << gradient.stops().count(); QDebugStateSaver saver( debug );
debug.nospace();
debug << "Gradient";
if ( !gradient.isValid() )
{
debug << "()";
}
else
{
debug << "( ";
if ( gradient.isMonochrome() )
{
QskRgb::debugColor( debug, gradient.startColor() );
}
else
{
const char o[] = { 'H', 'V', 'D' };
debug << o[ gradient.orientation() ] << ", ";
if ( gradient.stops().count() == 2 )
{
QskRgb::debugColor( debug, gradient.startColor() );
debug << ", ";
QskRgb::debugColor( debug, gradient.endColor() );
}
else
{
const auto& s = gradient.stops();
for ( int i = 0; i < s.count(); i++ )
{
if ( i != 0 )
debug << ", ";
debug << s[i];
}
}
}
debug << " )";
}
return debug; return debug;
} }

View File

@ -52,6 +52,7 @@ class QSK_EXPORT QskGradient
QskGradient( Qt::Orientation, const QVector< QskGradientStop >& ); QskGradient( Qt::Orientation, const QVector< QskGradientStop >& );
QskGradient( Qt::Orientation, const QColor&, const QColor& ); QskGradient( Qt::Orientation, const QColor&, const QColor& );
QskGradient( Qt::Orientation, QGradient::Preset );
QskGradient( Orientation, const QVector< QskGradientStop >& ); QskGradient( Orientation, const QVector< QskGradientStop >& );
QskGradient( Orientation, const QColor&, const QColor& ); QskGradient( Orientation, const QColor&, const QColor& );

View File

@ -14,6 +14,10 @@
static void qskRegisterGradientStop() static void qskRegisterGradientStop()
{ {
qRegisterMetaType< QskGradientStop >(); qRegisterMetaType< QskGradientStop >();
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
QMetaType::registerEqualsComparator< QskGradientStop >();
#endif
} }
Q_CONSTRUCTOR_FUNCTION( qskRegisterGradientStop ) Q_CONSTRUCTOR_FUNCTION( qskRegisterGradientStop )
@ -78,7 +82,12 @@ QColor QskGradientStop::interpolated(
QDebug operator<<( QDebug debug, const QskGradientStop& stop ) QDebug operator<<( QDebug debug, const QskGradientStop& stop )
{ {
debug << stop.position() << ": " << stop.color(); QDebugStateSaver saver( debug );
debug.nospace();
debug << stop.position() << ": ";
QskRgb::debugColor( debug, stop.color() );
return debug; return debug;
} }

View File

@ -12,6 +12,10 @@
static void qskRegisterIntervalF() static void qskRegisterIntervalF()
{ {
qRegisterMetaType< QskIntervalF >(); qRegisterMetaType< QskIntervalF >();
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
QMetaType::registerEqualsComparator< QskIntervalF >();
#endif
} }
Q_CONSTRUCTOR_FUNCTION( qskRegisterIntervalF ) Q_CONSTRUCTOR_FUNCTION( qskRegisterIntervalF )

View File

@ -61,6 +61,7 @@ class QSK_EXPORT QskMargins : public QMarginsF
QskMargins interpolated( const QskMargins&, qreal progress ) const noexcept; QskMargins interpolated( const QskMargins&, qreal progress ) const noexcept;
constexpr bool isExpanding() const noexcept; constexpr bool isExpanding() const noexcept;
constexpr bool isEquidistant() const noexcept;
static QVariant interpolate( const QskMargins&, static QVariant interpolate( const QskMargins&,
const QskMargins&, qreal progress ) noexcept; const QskMargins&, qreal progress ) noexcept;
@ -181,6 +182,11 @@ constexpr inline qreal QskMargins::height() const noexcept
return top() + bottom(); return top() + bottom();
} }
inline constexpr bool QskMargins::isEquidistant() const noexcept
{
return ( left() == top() ) && ( left() == right() ) && ( left() == bottom() );
}
Q_DECLARE_TYPEINFO( QskMargins, Q_MOVABLE_TYPE ); Q_DECLARE_TYPEINFO( QskMargins, Q_MOVABLE_TYPE );
Q_DECLARE_METATYPE( QskMargins ) Q_DECLARE_METATYPE( QskMargins )

View File

@ -172,3 +172,29 @@ QRgb QskRgb::darker( QRgb rgb, int factor ) noexcept
return QColor::fromRgba( rgb ).darker( factor ).rgba(); return QColor::fromRgba( rgb ).darker( factor ).rgba();
} }
#ifndef QT_NO_DEBUG_STREAM
#include <qdebug.h>
void QskRgb::debugColor( QDebug debug, const QColor& color )
{
debugColor( debug, color.rgba() );
}
void QskRgb::debugColor( QDebug debug, QRgb rgb )
{
QDebugStateSaver saver( debug );
debug.nospace();
debug << '[';
debug << qRed( rgb ) << "r," << qGreen( rgb ) << "g,"
<< qBlue( rgb ) << 'b';
if ( qAlpha( rgb ) != 255 )
debug << ',' << qAlpha( rgb ) << 'a';
debug << ']';
}
#endif

View File

@ -461,23 +461,35 @@ namespace QskRgb
return ( rgb & ColorMask ) | ( ( static_cast< uint >( alpha ) & 0xffu ) << 24 ); return ( rgb & ColorMask ) | ( ( static_cast< uint >( alpha ) & 0xffu ) << 24 );
} }
inline QColor toTransparentF( const QColor& color, qreal alpha ) inline QColor toTransparentF( const QColor& color, qreal opacity )
{ {
return toTransparent( color, qRound( alpha * 255 ) ); return toTransparent( color, qRound( opacity * 255 ) );
} }
inline QColor toTransparentF( Qt::GlobalColor color, qreal alpha ) inline QColor toTransparentF( Qt::GlobalColor color, qreal opacity )
{ {
return toTransparent( QColor( color ), qRound( alpha * 255 ) ); return toTransparent( QColor( color ), qRound( opacity * 255 ) );
} }
inline constexpr QRgb toTransparentF( QRgb rgb, qreal alpha ) noexcept inline constexpr QRgb toTransparentF( QRgb rgb, qreal opacity ) noexcept
{ {
return toTransparent( rgb, qRound( alpha * 255 ) ); return toTransparent( rgb, qRound( opacity * 255 ) );
} }
QSK_EXPORT QRgb lighter( QRgb, int factor = 150 ) noexcept; QSK_EXPORT QRgb lighter( QRgb, int factor = 150 ) noexcept;
QSK_EXPORT QRgb darker( QRgb, int factor = 200 ) noexcept; QSK_EXPORT QRgb darker( QRgb, int factor = 200 ) noexcept;
} }
#ifndef QT_NO_DEBUG_STREAM
class QDebug;
namespace QskRgb
{
QSK_EXPORT void debugColor( QDebug, const QColor& );
QSK_EXPORT void debugColor( QDebug, QRgb );
}
#endif
#endif #endif

View File

@ -9,6 +9,10 @@
static void qskRegisterTickmarks() static void qskRegisterTickmarks()
{ {
qRegisterMetaType< QskScaleTickmarks >(); qRegisterMetaType< QskScaleTickmarks >();
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
QMetaType::registerEqualsComparator< QskScaleTickmarks >();
#endif
} }
Q_CONSTRUCTOR_FUNCTION( qskRegisterTickmarks ) Q_CONSTRUCTOR_FUNCTION( qskRegisterTickmarks )

View File

@ -12,6 +12,10 @@
static void qskRegisterShadowMetrics() static void qskRegisterShadowMetrics()
{ {
qRegisterMetaType< QskShadowMetrics >(); qRegisterMetaType< QskShadowMetrics >();
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
QMetaType::registerEqualsComparator< QskShadowMetrics >();
#endif
} }
Q_CONSTRUCTOR_FUNCTION( qskRegisterShadowMetrics ) Q_CONSTRUCTOR_FUNCTION( qskRegisterShadowMetrics )

View File

@ -1,14 +0,0 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#include "QskStateCombination.h"
static void qskRegisterStateCombination()
{
qRegisterMetaType< QskStateCombination >();
}
Q_CONSTRUCTOR_FUNCTION( qskRegisterStateCombination )

View File

@ -21,6 +21,9 @@ class QSK_EXPORT QskStateCombination
constexpr QskStateCombination( QskAspect::States = QskAspect::States() ) noexcept; constexpr QskStateCombination( QskAspect::States = QskAspect::States() ) noexcept;
constexpr QskStateCombination( Type, QskAspect::States = QskAspect::States() ) noexcept; constexpr QskStateCombination( Type, QskAspect::States = QskAspect::States() ) noexcept;
constexpr bool operator==( QskStateCombination ) const noexcept;
constexpr bool operator!=( QskStateCombination ) const noexcept;
constexpr bool isNull() const noexcept; constexpr bool isNull() const noexcept;
void setType( Type ) noexcept; void setType( Type ) noexcept;
@ -36,7 +39,6 @@ class QSK_EXPORT QskStateCombination
}; };
Q_DECLARE_TYPEINFO( QskStateCombination, Q_MOVABLE_TYPE ); Q_DECLARE_TYPEINFO( QskStateCombination, Q_MOVABLE_TYPE );
Q_DECLARE_METATYPE( QskStateCombination )
constexpr inline QskStateCombination::QskStateCombination( constexpr inline QskStateCombination::QskStateCombination(
QskAspect::State state ) noexcept QskAspect::State state ) noexcept
@ -90,4 +92,14 @@ constexpr inline QskAspect::States QskStateCombination::states() const noexcept
return m_states; return m_states;
} }
constexpr bool QskStateCombination::operator==( QskStateCombination other ) const noexcept
{
return ( m_type == other.m_type ) && ( m_states == other.m_states );
}
constexpr bool QskStateCombination::operator!=( QskStateCombination other ) const noexcept
{
return !( *this == other );
}
#endif #endif

View File

@ -128,7 +128,6 @@ class QskSkin::PrivateData
std::unordered_map< const QMetaObject*, SkinletData > skinletMap; std::unordered_map< const QMetaObject*, SkinletData > skinletMap;
QskSkinHintTable hintTable; QskSkinHintTable hintTable;
QskAspect::States stateMask = QskAspect::AllStates;
std::unordered_map< int, QFont > fonts; std::unordered_map< int, QFont > fonts;
std::unordered_map< int, QskColorFilter > graphicFilters; std::unordered_map< int, QskColorFilter > graphicFilters;
@ -345,22 +344,6 @@ const int* QskSkin::dialogButtonLayout( Qt::Orientation orientation ) const
return QPlatformDialogHelper::buttonLayout( orientation, policy ); return QPlatformDialogHelper::buttonLayout( orientation, policy );
} }
void QskSkin::setStateMask( QskAspect::States mask )
{
for ( auto state : { QskControl::Disabled, QskControl::Hovered, QskControl::Focused } )
{
if ( mask & state )
m_data->stateMask |= state;
else
m_data->stateMask &= ~state;
}
}
QskAspect::States QskSkin::stateMask() const
{
return m_data->stateMask;
}
QskSkinlet* QskSkin::skinlet( const QMetaObject* metaObject ) QskSkinlet* QskSkin::skinlet( const QMetaObject* metaObject )
{ {
while ( metaObject ) while ( metaObject )

View File

@ -77,9 +77,6 @@ class QSK_EXPORT QskSkin : public QObject
virtual const int* dialogButtonLayout( Qt::Orientation ) const; virtual const int* dialogButtonLayout( Qt::Orientation ) const;
virtual QString dialogButtonText( int button ) const; virtual QString dialogButtonText( int button ) const;
void setStateMask( QskAspect::States );
QskAspect::States stateMask() const;
QskSkinlet* skinlet( const QMetaObject* ); QskSkinlet* skinlet( const QMetaObject* );
const QskSkinHintTable& hintTable() const; const QskSkinHintTable& hintTable() const;

View File

@ -64,41 +64,11 @@ QskSkinHintTable::QskSkinHintTable()
{ {
} }
QskSkinHintTable::QskSkinHintTable( const QskSkinHintTable& other )
: m_hints( nullptr )
, m_animatorCount( other.m_animatorCount )
, m_statefulCount( other.m_statefulCount )
{
if ( other.m_hints )
m_hints = new HintMap( *( other.m_hints ) );
}
QskSkinHintTable::~QskSkinHintTable() QskSkinHintTable::~QskSkinHintTable()
{ {
delete m_hints; delete m_hints;
} }
QskSkinHintTable& QskSkinHintTable::operator=( const QskSkinHintTable& other )
{
m_animatorCount = other.m_animatorCount;
m_statefulCount = other.m_statefulCount;
if ( other.m_hints )
{
if ( m_hints == nullptr )
m_hints = new HintMap();
*m_hints = *other.m_hints;
}
else
{
delete m_hints;
m_hints = nullptr;
}
return *this;
}
const std::unordered_map< QskAspect, QVariant >& QskSkinHintTable::hints() const const std::unordered_map< QskAspect, QVariant >& QskSkinHintTable::hints() const
{ {
if ( m_hints ) if ( m_hints )
@ -126,11 +96,7 @@ bool QskSkinHintTable::setHint( QskAspect aspect, const QVariant& skinHint )
QSK_ASSERT_COUNTER( m_animatorCount ); QSK_ASSERT_COUNTER( m_animatorCount );
} }
if ( aspect.hasStates() ) m_states |= aspect.states();
{
m_statefulCount++;
QSK_ASSERT_COUNTER( m_statefulCount );
}
return true; return true;
} }
@ -158,8 +124,7 @@ bool QskSkinHintTable::removeHint( QskAspect aspect )
if ( aspect.isAnimator() ) if ( aspect.isAnimator() )
m_animatorCount--; m_animatorCount--;
if ( aspect.hasStates() ) // how to clear m_states ? TODO ...
m_statefulCount--;
if ( m_hints->empty() ) if ( m_hints->empty() )
{ {
@ -184,8 +149,7 @@ QVariant QskSkinHintTable::takeHint( QskAspect aspect )
if ( aspect.isAnimator() ) if ( aspect.isAnimator() )
m_animatorCount--; m_animatorCount--;
if ( aspect.hasStates() ) // how to clear m_states ? TODO ...
m_statefulCount--;
if ( m_hints->empty() ) if ( m_hints->empty() )
{ {
@ -206,14 +170,14 @@ void QskSkinHintTable::clear()
m_hints = nullptr; m_hints = nullptr;
m_animatorCount = 0; m_animatorCount = 0;
m_statefulCount = 0; m_states = QskAspect::NoState;
} }
const QVariant* QskSkinHintTable::resolvedHint( const QVariant* QskSkinHintTable::resolvedHint(
QskAspect aspect, QskAspect* resolvedAspect ) const QskAspect aspect, QskAspect* resolvedAspect ) const
{ {
if ( m_hints != nullptr ) if ( m_hints != nullptr )
return qskResolvedHint( aspect, *m_hints, resolvedAspect ); return qskResolvedHint( aspect & m_states, *m_hints, resolvedAspect );
return nullptr; return nullptr;
} }
@ -223,7 +187,7 @@ QskAspect QskSkinHintTable::resolvedAspect( QskAspect aspect ) const
QskAspect a; QskAspect a;
if ( m_hints != nullptr ) if ( m_hints != nullptr )
qskResolvedHint( aspect, *m_hints, &a ); qskResolvedHint( aspect & m_states, *m_hints, &a );
return a; return a;
} }
@ -233,6 +197,8 @@ QskAspect QskSkinHintTable::resolvedAnimator(
{ {
if ( m_hints && m_animatorCount > 0 ) if ( m_hints && m_animatorCount > 0 )
{ {
aspect &= m_states;
Q_FOREVER Q_FOREVER
{ {
auto it = m_hints->find( aspect ); auto it = m_hints->find( aspect );
@ -268,15 +234,16 @@ bool QskSkinHintTable::setAnimation(
bool QskSkinHintTable::isResolutionMatching( bool QskSkinHintTable::isResolutionMatching(
QskAspect aspect1, QskAspect aspect2 ) const QskAspect aspect1, QskAspect aspect2 ) const
{ {
// remove states we do not have early
aspect1 &= m_states;
aspect2 &= m_states;
if ( aspect1 == aspect2 ) if ( aspect1 == aspect2 )
return true; return true;
if ( aspect1.trunk() != aspect2.trunk() ) if ( aspect1.trunk() != aspect2.trunk() )
return false; return false;
if ( !hasStates() )
return false;
const auto a1 = aspect1; const auto a1 = aspect1;
const auto a2 = aspect2; const auto a2 = aspect2;

View File

@ -17,12 +17,8 @@ class QSK_EXPORT QskSkinHintTable
{ {
public: public:
QskSkinHintTable(); QskSkinHintTable();
QskSkinHintTable( const QskSkinHintTable& other );
~QskSkinHintTable(); ~QskSkinHintTable();
QskSkinHintTable& operator=( const QskSkinHintTable& );
bool setAnimation( QskAspect, QskAnimationHint ); bool setAnimation( QskAspect, QskAnimationHint );
QskAnimationHint animation( QskAspect ) const; QskAnimationHint animation( QskAspect ) const;
@ -40,9 +36,10 @@ class QSK_EXPORT QskSkinHintTable
const std::unordered_map< QskAspect, QVariant >& hints() const; const std::unordered_map< QskAspect, QVariant >& hints() const;
bool hasAnimators() const; bool hasAnimators() const;
bool hasStates() const;
bool hasHints() const; bool hasHints() const;
QskAspect::States states() const;
void clear(); void clear();
const QVariant* resolvedHint( QskAspect, const QVariant* resolvedHint( QskAspect,
@ -56,13 +53,15 @@ class QSK_EXPORT QskSkinHintTable
bool isResolutionMatching( QskAspect, QskAspect ) const; bool isResolutionMatching( QskAspect, QskAspect ) const;
private: private:
Q_DISABLE_COPY( QskSkinHintTable )
static const QVariant invalidHint; static const QVariant invalidHint;
typedef std::unordered_map< QskAspect, QVariant > HintMap; typedef std::unordered_map< QskAspect, QVariant > HintMap;
HintMap* m_hints = nullptr; HintMap* m_hints = nullptr;
unsigned short m_animatorCount = 0; unsigned short m_animatorCount = 0;
unsigned short m_statefulCount = 0; QskAspect::States m_states;
}; };
inline bool QskSkinHintTable::hasHints() const inline bool QskSkinHintTable::hasHints() const
@ -70,9 +69,9 @@ inline bool QskSkinHintTable::hasHints() const
return m_hints != nullptr; return m_hints != nullptr;
} }
inline bool QskSkinHintTable::hasStates() const inline QskAspect::States QskSkinHintTable::states() const
{ {
return m_statefulCount > 0; return m_states;
} }
inline bool QskSkinHintTable::hasAnimators() const inline bool QskSkinHintTable::hasAnimators() const

File diff suppressed because it is too large Load Diff

View File

@ -38,17 +38,6 @@ static inline bool qskIsControl( const QskSkinnable* skinnable )
return skinnable->metaObject()->inherits( &QskControl::staticMetaObject ); return skinnable->metaObject()->inherits( &QskControl::staticMetaObject );
} }
static inline QVariant qskTypedNullValue( const QVariant& value )
{
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
const auto vType = static_cast< QMetaType >( value.userType() );
#else
const auto vType = value.userType();
#endif
return QVariant( vType, nullptr );
}
static inline bool qskSetFlag( QskSkinnable* skinnable, static inline bool qskSetFlag( QskSkinnable* skinnable,
const QskAspect aspect, int flag ) const QskAspect aspect, int flag )
{ {
@ -940,23 +929,12 @@ const QVariant& QskSkinnable::storedHint(
{ {
const auto skin = effectiveSkin(); const auto skin = effectiveSkin();
// clearing all state bits not being handled from the skin
aspect.clearStates( ~skin->stateMask() );
QskAspect resolvedAspect; QskAspect resolvedAspect;
const auto& localTable = m_data->hintTable; const auto& localTable = m_data->hintTable;
if ( localTable.hasHints() ) if ( localTable.hasHints() )
{ {
auto a = aspect; if ( const auto value = localTable.resolvedHint( aspect, &resolvedAspect ) )
if ( !localTable.hasStates() )
{
// we don't need to clear the state bits stepwise
a.clearStates();
}
if ( const QVariant* value = localTable.resolvedHint( a, &resolvedAspect ) )
{ {
if ( status ) if ( status )
{ {
@ -972,10 +950,7 @@ const QVariant& QskSkinnable::storedHint(
const auto& skinTable = skin->hintTable(); const auto& skinTable = skin->hintTable();
if ( skinTable.hasHints() ) if ( skinTable.hasHints() )
{ {
auto a = aspect; if ( const auto value = skinTable.resolvedHint( aspect, &resolvedAspect ) )
const QVariant* value = skinTable.resolvedHint( a, &resolvedAspect );
if ( value )
{ {
if ( status ) if ( status )
{ {
@ -993,8 +968,7 @@ const QVariant& QskSkinnable::storedHint(
aspect.setSubControl( QskAspect::Control ); aspect.setSubControl( QskAspect::Control );
aspect.clearStates(); aspect.clearStates();
value = skinTable.resolvedHint( aspect, &resolvedAspect ); if ( const auto value = skinTable.resolvedHint( aspect, &resolvedAspect ) )
if ( value )
{ {
if ( status ) if ( status )
{ {
@ -1171,27 +1145,11 @@ void QskSkinnable::startHintTransition( QskAspect aspect,
if ( control->window() == nullptr || !isTransitionAccepted( aspect ) ) if ( control->window() == nullptr || !isTransitionAccepted( aspect ) )
return; return;
/*
We might be invalid for one of the values, when an aspect
has not been defined for all states ( f.e. metrics are expected
to fallback to 0.0 ). In this case we create a default one.
*/
auto v1 = from; auto v1 = from;
auto v2 = to; auto v2 = to;
if ( !v1.isValid() ) if ( !QskVariantAnimator::convertValues( v1, v2 ) )
{
v1 = qskTypedNullValue( v2 );
}
else if ( !v2.isValid() )
{
v2 = qskTypedNullValue( v1 );
}
else if ( v1.userType() != v2.userType() )
{
return; return;
}
if ( aspect.flagPrimitive() == QskAspect::GraphicRole ) if ( aspect.flagPrimitive() == QskAspect::GraphicRole )
{ {
@ -1257,7 +1215,8 @@ void QskSkinnable::setSkinStates( QskAspect::States newStates )
if ( skin ) if ( skin )
{ {
const auto mask = skin->stateMask(); const auto mask = skin->hintTable().states() | m_data->hintTable.states();
if ( ( newStates & mask ) == ( m_data->skinStates & mask ) ) if ( ( newStates & mask ) == ( m_data->skinStates & mask ) )
{ {
// the modified bits are not handled by the skin // the modified bits are not handled by the skin
@ -1297,24 +1256,13 @@ void QskSkinnable::setSkinStates( QskAspect::States newStates )
const auto primitive = static_cast< QskAspect::Primitive >( i ); const auto primitive = static_cast< QskAspect::Primitive >( i );
aspect.setPrimitive( type, primitive ); aspect.setPrimitive( type, primitive );
auto a1 = aspect | m_data->skinStates; const auto a1 = aspect | m_data->skinStates;
auto a2 = aspect | newStates; const auto a2 = aspect | newStates;
bool doTransition = true; bool doTransition = true;
if ( !m_data->hintTable.hasStates() ) if ( m_data->hintTable.states() == QskAspect::NoState )
{
/*
The hints are found by stripping the state bits one by
one until a lookup into the hint table is successful.
So for deciding whether two aspects lead to the same hint
we can stop as soon as the aspects have the same state bits.
This way we can reduce the number of lookups significantly
for skinnables with many state bits.
*/
doTransition = !skinTable.isResolutionMatching( a1, a2 ); doTransition = !skinTable.isResolutionMatching( a1, a2 );
}
if ( doTransition ) if ( doTransition )
{ {
@ -1343,12 +1291,7 @@ QskSkin* QskSkinnable::effectiveSkin() const
if ( skin == nullptr ) if ( skin == nullptr )
{ {
if ( const auto control = owningControl() ) if ( const auto control = owningControl() )
{ skin = qskEffectiveSkin( control->window() );
if ( auto window = qobject_cast< const QskWindow* >( control->window() ) )
{
skin = window->skin();
}
}
} }
return skin ? skin : qskSetup->skin(); return skin ? skin : qskSetup->skin();

View File

@ -230,6 +230,8 @@ class QSK_EXPORT QskSkinnable
bool resetGraphicRoleHint( QskAspect ); bool resetGraphicRoleHint( QskAspect );
int graphicRoleHint( QskAspect, QskSkinHintStatus* = nullptr ) const; int graphicRoleHint( QskAspect, QskSkinHintStatus* = nullptr ) const;
const QskSkinHintTable& hintTable() const;
protected: protected:
virtual void updateNode( QSGNode* ); virtual void updateNode( QSGNode* );
virtual bool isTransitionAccepted( QskAspect ) const; virtual bool isTransitionAccepted( QskAspect ) const;
@ -237,7 +239,6 @@ class QSK_EXPORT QskSkinnable
virtual QskAspect::Subcontrol substitutedSubcontrol( QskAspect::Subcontrol ) const; virtual QskAspect::Subcontrol substitutedSubcontrol( QskAspect::Subcontrol ) const;
QskSkinHintTable& hintTable(); QskSkinHintTable& hintTable();
const QskSkinHintTable& hintTable() const;
private: private:
Q_DISABLE_COPY( QskSkinnable ) Q_DISABLE_COPY( QskSkinnable )

View File

@ -76,6 +76,31 @@ QSK_DECL_INSANE static inline QVariant qskInterpolate(
return f( from.constData(), to.constData(), progress ); return f( from.constData(), to.constData(), progress );
} }
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
using QskMetaType = int;
static inline QskMetaType qskMetaType( const QVariant& v ) { return v.userType(); }
#else
using QskMetaType = QMetaType;
static inline QskMetaType qskMetaType( const QVariant& v ) { return v.metaType(); }
#endif
static inline QVariant qskDefaultVariant( QskMetaType type )
{
return QVariant( type, nullptr );
}
static inline QVariant qskConvertedVariant( const QVariant& from, QskMetaType type )
{
auto v = from;
v.convert( type );
return v;
}
QskVariantAnimator::QskVariantAnimator() QskVariantAnimator::QskVariantAnimator()
: m_interpolator( nullptr ) : m_interpolator( nullptr )
{ {
@ -100,16 +125,60 @@ void QskVariantAnimator::setCurrentValue( const QVariant& value )
m_currentValue = value; m_currentValue = value;
} }
bool QskVariantAnimator::convertValues( QVariant& v1, QVariant& v2 )
{
if ( !v1.isValid() && !v2.isValid() )
return false;
const auto type1 = qskMetaType( v1 );
const auto type2 = qskMetaType( v2 );
if ( !v1.isValid() )
{
v1 = qskDefaultVariant( type2 );
return true;
}
if ( !v2.isValid() )
{
v2 = qskDefaultVariant( type1 );
return true;
}
if ( type1 != type2 )
{
if ( v1.canConvert( type2 ) )
{
v1.convert( type2 );
return true;
}
if ( v2.canConvert( type1 ) )
{
v2.convert( type1 );
return true;
}
return false;
}
return true;
}
void QskVariantAnimator::setup() void QskVariantAnimator::setup()
{ {
m_interpolator = nullptr; m_interpolator = nullptr;
const auto type = m_startValue.userType(); if ( convertValues( m_startValue, m_endValue ) )
if ( type == m_endValue.userType() )
{ {
// all what has been registered by qRegisterAnimationInterpolator if ( m_startValue != m_endValue )
m_interpolator = reinterpret_cast< void ( * )() >( {
QVariantAnimationPrivate::getInterpolator( type ) ); const auto id = m_startValue.userType();
// all what has been registered by qRegisterAnimationInterpolator
m_interpolator = reinterpret_cast< void ( * )() >(
QVariantAnimationPrivate::getInterpolator( id ) );
}
} }
m_currentValue = m_interpolator ? m_startValue : m_endValue; m_currentValue = m_interpolator ? m_startValue : m_endValue;
@ -131,3 +200,32 @@ void QskVariantAnimator::done()
{ {
m_interpolator = nullptr; m_interpolator = nullptr;
} }
bool QskVariantAnimator::maybeInterpolate(
const QVariant& value1, const QVariant& value2 )
{
if ( !value1.isValid() && !value2.isValid() )
return false;
const auto type1 = qskMetaType( value1 );
const auto type2 = qskMetaType( value2 );
if ( !value1.isValid() )
return value2 != qskDefaultVariant( type2 );
if ( !value2.isValid() )
return value1 != qskDefaultVariant( type1 );
if ( type1 != type2 )
{
if ( value1.canConvert( type2 ) )
return value2 != qskConvertedVariant( value1, type2 );
if ( value2.canConvert( type1 ) )
return value1 != qskConvertedVariant( value2, type1 );
return false;
}
return value1 != value2;
}

View File

@ -24,6 +24,9 @@ class QSK_EXPORT QskVariantAnimator : public QskAnimator
void setEndValue( const QVariant& ); void setEndValue( const QVariant& );
QVariant endValue() const; QVariant endValue() const;
static bool maybeInterpolate( const QVariant&, const QVariant& );
static bool convertValues( QVariant&, QVariant& );
protected: protected:
void setup() override; void setup() override;
void advance( qreal value ) override; void advance( qreal value ) override;

View File

@ -63,7 +63,6 @@ SOURCES += \
common/QskScaleTickmarks.cpp \ common/QskScaleTickmarks.cpp \
common/QskShadowMetrics.cpp \ common/QskShadowMetrics.cpp \
common/QskSizePolicy.cpp \ common/QskSizePolicy.cpp \
common/QskStateCombination.cpp \
common/QskTextColors.cpp \ common/QskTextColors.cpp \
common/QskTextOptions.cpp common/QskTextOptions.cpp

View File

@ -77,30 +77,31 @@ void SkinnyShortcut::enable( Types types )
void SkinnyShortcut::rotateSkin() void SkinnyShortcut::rotateSkin()
{ {
const QStringList names = qskSkinManager->skinNames(); const auto names = qskSkinManager->skinNames();
if ( names.size() <= 1 ) if ( names.size() <= 1 )
return; return;
int index = names.indexOf( qskSetup->skinName() ); int index = names.indexOf( qskSetup->skinName() );
index = ( index + 1 ) % names.size(); index = ( index + 1 ) % names.size();
QskSkin* oldSkin = qskSetup->skin(); auto oldSkin = qskSetup->skin();
if ( oldSkin->parent() == qskSetup ) if ( oldSkin->parent() == qskSetup )
oldSkin->setParent( nullptr ); // otherwise setSkin deletes it oldSkin->setParent( nullptr ); // otherwise setSkin deletes it
QskSkin* newSkin = qskSetup->setSkin( names[ index ] ); if ( auto newSkin = qskSetup->setSkin( names[ index ] ) )
{
QskSkinTransition transition;
QskSkinTransition transition; //transition.setMask( QskAspect::Color ); // Metrics are flickering -> TODO
transition.setSourceSkin( oldSkin );
transition.setTargetSkin( newSkin );
transition.setAnimation( 500 );
//transition.setMask( QskAspect::Color ); // Metrics are flickering -> TODO transition.process();
transition.setSourceSkin( oldSkin );
transition.setTargetSkin( newSkin );
transition.setAnimation( 500 );
transition.process(); if ( oldSkin->parent() == nullptr )
delete oldSkin;
if ( oldSkin->parent() == nullptr ) }
delete oldSkin;
} }
void SkinnyShortcut::showBackground() void SkinnyShortcut::showBackground()