Merge branch 'master' into features/drawer

This commit is contained in:
Uwe Rathmann 2023-10-23 10:45:51 +02:00
commit 2013338dd4
6 changed files with 89 additions and 48 deletions

View File

@ -4,7 +4,7 @@
*****************************************************************************/ *****************************************************************************/
/* /*
Definitions ( where possible ) taken from Definitions ( where possible ) taken from
https://www.figma.com/file/NAWMapFlXnoOb86Q2H5GKr/Windows-UI-(Community) https://www.figma.com/file/NAWMapFlXnoOb86Q2H5GKr/Windows-UI-(Community)
*/ */
@ -35,35 +35,18 @@
*/ */
/* /*
The palette is made of a specific configurable colors and The palette is made of a couple of configurable base/accent colors and a
predefined semitransparent shades of gray. Both need to predefined set of semitransparent shades of gray. These grays are used
be resolved to opaque colors with the base colors of the sections. to create darkened/lightend colors from the configurable colors that can
be used for borders etc.
Resolving the colors can be done in 2 ways: However borders need to be darkened for light base colors and lightened for
dark ones. So we actually have 2 different sets of grays for light/dark
colors schemes.
- render time The main advantage of this concept is, that a working color schemes
can be defined by setting the accent/base colors only.
This actually means, that we do not create opaque colors and
create the scene graph nodes with semitransparent colors.
- definition time
We create opaque colors for the base colors of the sections
and set them as skin hints.
Resolving at render time sounds like the right solution as we
background colors set in application code will just work.
Unfortunately we have 2 different sets of grays for light/dark
base colors and when applications are setting a light color, where a
dark color ( or v.v ) is expected we might end up with unacceptable
results: ( white on light or black on dark ).
So there are pros and cons and we do not have a final opinion
about waht to do. For the moment we implement resolving at definition
time as an option to be able to play with both solutions.
*/ */
#include "QskFluent2Skin.h" #include "QskFluent2Skin.h"
#include "QskFluent2Theme.h" #include "QskFluent2Theme.h"
@ -139,9 +122,30 @@ namespace
return qRgba( value, value, value, qRound( opacity * 255 ) ); return qRgba( value, value, value, qRound( opacity * 255 ) );
} }
/*
When application code is manipulating base colors manually the colors of
the borders will be lightened/darkened from it like expected - as long
as the application color matches the color scheme. Otherwise we end
up with lightened borders on light backgrounds or v.v.
To avoid this problem we could resolve the grays with the background
colors of the sections at definition time. This solves the problem with
applications using backgrounds from the "wrong" color scheme, but requires
more work for customizing controls hen using the "correct" scheme
( -> border colors need to be set as well ).
When enabling QSK_RESOLVE_COLORS a code path is enabled that is intended
to play with resolving the grays at definition time. But I'm not decided
if it is worth to make a feature from it. TODO ...
*/
#define QSK_RESOLVE_COLORS 0
#if QSK_RESOLVE_COLORS
inline constexpr QRgb rgbFlattened( QRgb foreground, QRgb background ) inline constexpr QRgb rgbFlattened( QRgb foreground, QRgb background )
{ {
//Q_ASSERT( qAlpha( background ) == 255 ); Q_ASSERT( qAlpha( background ) == 255 );
const auto r2 = qAlpha( foreground ) / 255.0; const auto r2 = qAlpha( foreground ) / 255.0;
const auto r1 = 1.0 - r2; const auto r1 = 1.0 - r2;
@ -160,15 +164,25 @@ namespace
or without resolving the foreground alpha value or without resolving the foreground alpha value
*/ */
#if 0
return rgbFlattened( foreground, background ); return rgbFlattened( foreground, background );
#else }
//Q_ASSERT( qAlpha( background ) == 255 );
#else // !QSK_RESOLVE_COLORS
inline QRgb rgbFlattened( QRgb foreground, QRgb background )
{
const auto alpha = qAlpha( foreground ) / 255.0;
return QskRgb::interpolated( background, foreground, alpha );
}
inline constexpr QRgb rgbSolid( QRgb foreground, QRgb background )
{
Q_UNUSED( background ); Q_UNUSED( background );
return foreground; return foreground;
#endif
} }
#endif
class Editor : private QskSkinHintTableEditor class Editor : private QskSkinHintTableEditor
{ {
public: public:
@ -521,7 +535,8 @@ void Editor::setupComboBoxColors(
const auto& pal = theme.palette; const auto& pal = theme.palette;
for ( const auto state : { QskAspect::NoState, Q::Hovered, Q::Focused, Q::Pressed, Q::Disabled } ) for ( const auto state :
{ QskAspect::NoState, Q::Hovered, Q::Focused, Q::Pressed, Q::Disabled } )
{ {
QRgb panelColor, borderColor1, borderColor2, textColor; QRgb panelColor, borderColor1, borderColor2, textColor;
@ -693,7 +708,7 @@ void Editor::setupListViewColors(
{ {
if ( state1 == Q::Hovered ) if ( state1 == Q::Hovered )
cellColor = pal.fillColor.subtle.tertiary; cellColor = pal.fillColor.subtle.tertiary;
else else
cellColor = pal.fillColor.subtle.secondary; cellColor = pal.fillColor.subtle.secondary;
} }
@ -793,7 +808,8 @@ void Editor::setupMenuColors(
setColor( Q::Text | Q::Selected | Q::Pressed, pal.fillColor.text.secondary ); setColor( Q::Text | Q::Selected | Q::Pressed, pal.fillColor.text.secondary );
setGraphicRole( Q::Icon, QskFluent2Skin::GraphicRoleFillColorTextPrimary ); setGraphicRole( Q::Icon, QskFluent2Skin::GraphicRoleFillColorTextPrimary );
setGraphicRole( Q::Icon | Q::Selected | Q::Pressed, QskFluent2Skin::GraphicRoleFillColorTextSecondary ); setGraphicRole( Q::Icon | Q::Selected | Q::Pressed,
QskFluent2Skin::GraphicRoleFillColorTextSecondary );
} }
void Editor::setupPageIndicatorMetrics() void Editor::setupPageIndicatorMetrics()
@ -811,7 +827,7 @@ void Editor::setupPageIndicatorMetrics()
/* /*
Pressed/Hovered are not yet implemented. Pressed/Hovered are not yet implemented.
Sizes would be: Sizes would be:
- Q::Pressed : 3 - Q::Pressed : 3
- Q::Pressed | Q::Selected : 5 - Q::Pressed | Q::Selected : 5
@ -1048,7 +1064,7 @@ void Editor::setupRadioBoxMetrics()
However the colors of the inner side of the border are not solid for However the colors of the inner side of the border are not solid for
the selected states and we use a dummy indicator to get this done. the selected states and we use a dummy indicator to get this done.
How to solve this in a better way, TODO ... How to solve this in a better way, TODO ...
*/ */
setBoxShape( Q::CheckIndicator, 100, Qt::RelativeSize ); setBoxShape( Q::CheckIndicator, 100, Qt::RelativeSize );
@ -1098,7 +1114,7 @@ void Editor::setupRadioBoxColors(
if ( states & Q::Disabled ) if ( states & Q::Disabled )
textColor = pal.fillColor.text.disabled; textColor = pal.fillColor.text.disabled;
QRgb panelBorderColor; QRgb panelBorderColor;
if ( states & ( Q::Disabled | Q::Pressed ) ) if ( states & ( Q::Disabled | Q::Pressed ) )
panelBorderColor = pal.strokeColor.controlStrong.disabled; panelBorderColor = pal.strokeColor.controlStrong.disabled;
else else
@ -1411,7 +1427,7 @@ void Editor::setupSliderColors(
setBoxBorderGradient( Q::Handle, pal.elevation.circle.border, handleColor ); setBoxBorderGradient( Q::Handle, pal.elevation.circle.border, handleColor );
} }
for ( auto state : { A::NoState , Q::Pressed , Q::Disabled } ) for ( auto state : { A::NoState, Q::Pressed, Q::Disabled } )
{ {
QRgb grooveColor, fillColor, rippleColor; QRgb grooveColor, fillColor, rippleColor;
@ -1571,7 +1587,7 @@ void Editor::setupTabButtonColors(
using Q = QskTabButton; using Q = QskTabButton;
const auto& pal = theme.palette; const auto& pal = theme.palette;
for ( const auto state : { QskAspect::NoState, for ( const auto state : { QskAspect::NoState,
Q::Checked, Q::Hovered, Q::Pressed, Q::Disabled } ) Q::Checked, Q::Hovered, Q::Pressed, Q::Disabled } )
{ {
QRgb panelColor, textColor; QRgb panelColor, textColor;

View File

@ -141,7 +141,7 @@ void QskHintAnimator::advance( qreal progress )
{ {
if ( m_updateFlags == QskAnimationHint::UpdateAuto ) if ( m_updateFlags == QskAnimationHint::UpdateAuto )
{ {
if ( m_aspect.isMetric() ) if ( !m_aspect.isColor() )
{ {
m_control->resetImplicitSize(); m_control->resetImplicitSize();

View File

@ -10,6 +10,7 @@
#include "QskWindow.h" #include "QskWindow.h"
#include "QskEvent.h" #include "QskEvent.h"
#include "QskPlatform.h" #include "QskPlatform.h"
#include "QskHintAnimator.h"
#include <qpa/qplatformintegration.h> #include <qpa/qplatformintegration.h>
@ -239,13 +240,7 @@ bool QskPopup::isOpen() const
bool QskPopup::isTransitioning() const bool QskPopup::isTransitioning() const
{ {
if ( m_data->transitionAspect.value() == 0 ) return runningHintAnimator( m_data->transitionAspect ) != nullptr;
return false;
QskSkinHintStatus status;
(void) effectiveSkinHint( m_data->transitionAspect, &status );
return status.source == QskSkinHintStatus::Animator;
} }
QRectF QskPopup::overlayRect() const QRectF QskPopup::overlayRect() const

View File

@ -988,6 +988,23 @@ bool QskSkinnable::moveSkinHint( QskAspect aspect, const QVariant& value )
return moveSkinHint( aspect, effectiveSkinHint( aspect ), value ); return moveSkinHint( aspect, effectiveSkinHint( aspect ), value );
} }
const QskHintAnimator* QskSkinnable::runningHintAnimator(
QskAspect aspect, int index ) const
{
const auto& animators = m_data->animators;
if ( animators.isEmpty() )
return nullptr;
aspect = qskAnimatorAspect( aspect );
auto animator = animators.animator( aspect, index );
if ( animator == nullptr && index >= 0 )
animator = animators.animator( aspect, -1 );
return animator;
}
QVariant QskSkinnable::animatedHint( QVariant QskSkinnable::animatedHint(
QskAspect aspect, QskSkinHintStatus* status ) const QskAspect aspect, QskSkinHintStatus* status ) const
{ {

View File

@ -25,6 +25,7 @@ class QQuickItem;
class QskArcMetrics; class QskArcMetrics;
class QskControl; class QskControl;
class QskAnimationHint; class QskAnimationHint;
class QskHintAnimator;
class QskColorFilter; class QskColorFilter;
class QskBoxShapeMetrics; class QskBoxShapeMetrics;
class QskBoxBorderMetrics; class QskBoxBorderMetrics;
@ -262,6 +263,8 @@ class QSK_EXPORT QskSkinnable
bool startHintTransitions( const QVector< QskAspect::Subcontrol >&, bool startHintTransitions( const QVector< QskAspect::Subcontrol >&,
QskAspect::States, QskAspect::States, int index = -1 ); QskAspect::States, QskAspect::States, int index = -1 );
const QskHintAnimator* runningHintAnimator( QskAspect, int index = -1 ) const;
protected: protected:
virtual void updateNode( QSGNode* ); virtual void updateNode( QSGNode* );
virtual bool isTransitionAccepted( QskAspect ) const; virtual bool isTransitionAccepted( QskAspect ) const;

View File

@ -424,8 +424,18 @@ void QskWindow::exposeEvent( QExposeEvent* event )
void QskWindow::resizeEvent( QResizeEvent* event ) void QskWindow::resizeEvent( QResizeEvent* event )
{ {
auto rootItem = contentItem();
const auto oldRect = qskItemGeometry( rootItem );
Inherited::resizeEvent( event ); Inherited::resizeEvent( event );
const auto newRect = qskItemGeometry( rootItem );
if ( newRect != oldRect )
{
QskGeometryChangeEvent event( newRect, oldRect );
QCoreApplication::sendEvent( rootItem, &event );
}
if ( isExposed() ) if ( isExposed() )
layoutItems(); layoutItems();
} }