Compare commits

..

35 Commits

Author SHA1 Message Date
Uwe Rathmann f4b7aa33fe Merge branch 'master' into features/menubutton 2025-02-28 09:30:23 +01:00
Uwe Rathmann ed584af5c1 Merge branch 'master' into features/menubutton 2025-02-06 13:52:22 +01:00
Uwe Rathmann 7f67014bef Merge branch 'master' into features/menubutton 2025-02-06 10:25:55 +01:00
Uwe Rathmann 607939a4dc Merge branch 'master' into features/menubutton 2024-12-10 14:11:26 +01:00
Uwe Rathmann aa2a76996d Merge branch 'master' into features/menubutton 2024-12-02 10:13:50 +01:00
Uwe Rathmann a40170159c Merge branch 'master' into features/menubutton 2024-09-17 17:42:39 +02:00
Uwe Rathmann 87ae5efd67 Merge branch 'master' into features/menubutton 2024-09-11 18:51:02 +02:00
Uwe Rathmann 714e47a74c fixed 2024-01-30 17:19:14 +01:00
Uwe Rathmann 0408c70442 Merge branch 'master' into features/menubutton 2024-01-30 17:18:55 +01:00
Uwe Rathmann 8e81db43f1 copyright adjusted 2024-01-17 16:09:11 +01:00
Uwe Rathmann e56c1fae9d Merge branch 'master' into features/menubutton 2024-01-17 16:08:23 +01:00
Uwe Rathmann e620b56d4e Merge branch 'master' into features/menubutton 2023-11-28 15:33:17 +01:00
Uwe Rathmann beec40af06 Merge branch 'master' into features/menubutton 2023-11-15 11:56:57 +01:00
Uwe Rathmann 130bd3f9d2 Merge branch 'master' into features/menubutton 2023-11-03 18:25:29 +01:00
Uwe Rathmann 606de9080a Merge branch 'master' into features/menubutton 2023-10-05 09:40:36 +02:00
Uwe Rathmann b273264629 Merge branch 'master' into features/menubutton 2023-09-27 11:17:07 +02:00
Uwe Rathmann f67ff13f93 Merge branch 'master' into features/menubutton 2023-07-28 08:11:16 +02:00
Uwe Rathmann ee7896e2d4 Merge branch 'master' into features/menubutton 2023-06-20 09:38:15 +02:00
Uwe Rathmann 9060f7cf75 Merge branch 'master' into features/menubutton 2023-05-16 12:55:13 +02:00
Uwe Rathmann 51fd38eb01 handling of menu separators fixed 2023-05-16 12:38:19 +02:00
Uwe Rathmann 78d3a9af9c Merge branch 'master' into features/menubutton 2023-05-16 11:13:48 +02:00
Uwe Rathmann dbe1fad7ec QskMenuButton introduced 2023-05-15 16:58:46 +02:00
Uwe Rathmann 99151186fb Merge branch 'master' into features/menubutton 2023-05-15 15:06:29 +02:00
Uwe Rathmann 260c35f2a4 Merge branch 'master' into features/menubutton 2023-05-15 13:43:09 +02:00
Uwe Rathmann ea36b7da8e wip 2023-05-15 12:53:30 +02:00
Uwe Rathmann b7e4f10f91 wip 2023-05-15 12:50:16 +02:00
Uwe Rathmann a0df814121 wip 2023-05-15 12:38:50 +02:00
Uwe Rathmann defb193387 wip 2023-05-15 12:26:25 +02:00
Uwe Rathmann b7fe24602c wip 2023-05-15 12:22:55 +02:00
Uwe Rathmann b25852ff6f wip 2023-05-15 11:12:15 +02:00
Uwe Rathmann b3ed7f90e4 wip 2023-05-15 10:51:25 +02:00
Uwe Rathmann 329efbb242 wip 2023-05-15 10:40:33 +02:00
Uwe Rathmann b1a816e61e wip 2023-05-15 10:06:01 +02:00
Uwe Rathmann a5a28bebc2 wip 2023-05-15 07:22:54 +02:00
Uwe Rathmann 2a7a68e915 wip 2023-05-12 14:58:40 +02:00
37 changed files with 645 additions and 587 deletions

View File

@ -202,6 +202,7 @@ jobs:
install-deps: "true"
modules: "qtwebengine"
cached: ${{ steps.cache-qt-5-15.outputs.cache-hit }}
setup-python: "false"
tools: ""
set-env: "true"
tools-only: "false"
@ -215,6 +216,7 @@ jobs:
install-deps: "true"
modules: "qtwebengine qtshadertools"
cached: ${{ steps.cache-qt-6-2.outputs.cache-hit }}
setup-python: "false"
tools: ""
set-env: "true"
tools-only: "false"

View File

@ -149,7 +149,7 @@ function(qsk_add_example target)
endfunction()
function(qsk_add_shaders target shader_name)
function(qsk_add_shaders target)
cmake_parse_arguments( arg "" "" "FILES" ${ARGN} )
@ -160,7 +160,7 @@ function(qsk_add_shaders target shader_name)
list(APPEND outfiles "${qsbname}.qsb")
endforeach()
qt6_add_shaders( ${target} ${shader_name} BATCHABLE PRECOMPILE QUIET
qt6_add_shaders( ${target} "qskshaders" BATCHABLE PRECOMPILE QUIET
PREFIX "/qskinny/shaders" ${ARGV} OUTPUTS ${outfiles} )
# pass on OUTPUT_TARGETS to the caller of this function

View File

@ -5,7 +5,9 @@
#include "QskMaterial3ProgressBarSkinlet.h"
#include <QskProgressBar.h>
#include <QskBoxHints.h>
#include <QskBoxShapeMetrics.h>
#include <QskBoxBorderMetrics.h>
#include <QskBoxBorderColors.h>
#include <QskMargins.h>
#include <QskClipNode.h>
#include <QskSGNode.h>
@ -63,11 +65,11 @@ QSGNode* QskMaterial3ProgressBarSkinlet::updateStopIndicatorNode(
else
rect.setBottom( rect.top() + rect.width() );
QskBoxHints hints;
hints.shape = progressBar->boxShapeHint( Q::Fill );
hints.gradient = progressBar->gradientHint( Q::Fill ).endColor();
const auto color = progressBar->gradientHint( Q::Fill ).endColor();
const auto shape = progressBar->boxShapeHint( Q::Fill );
return updateBoxNode( progressBar, node, rect, hints );
return updateBoxNode( progressBar, node, rect, shape,
QskBoxBorderMetrics(), QskBoxBorderColors(), color );
}
QSGNode* QskMaterial3ProgressBarSkinlet::updateGrooveClipNode(

View File

@ -25,7 +25,7 @@
#include <QskPushButton.h>
#include <QskPageIndicator.h>
#include <QskScrollArea.h>
#include <QskMenu.h>
#include <QskMenuButton.h>
#include <QskWindow.h>
#include <QskDialog.h>
#include <QskSkinManager.h>
@ -37,6 +37,8 @@
#include <QskGraphicProvider.h>
#include <QskGraphicIO.h>
#include <QskGraphic.h>
#include <QskLabelData.h>
#include <QskSetup.h>
#include <QGuiApplication>
@ -118,49 +120,29 @@ namespace
}
};
class MenuButton : public QskPushButton
{
public:
MenuButton( const QString& text, QQuickItem* parent = nullptr )
: QskPushButton( text, parent )
{
connect( this, &QskPushButton::pressed, this, &MenuButton::openMenu );
}
private:
void openMenu()
{
auto menu = new QskMenu( window()->contentItem() );
populateMenu( menu );
menu->setOrigin( geometry().bottomLeft() );
menu->open();
}
virtual void populateMenu( QskMenu* ) = 0;
};
class SkinButton final : public MenuButton
class SkinButton final : public QskMenuButton
{
public:
SkinButton( const QString& text, QQuickItem* parent = nullptr )
: MenuButton( text, parent )
{
}
private:
void populateMenu( QskMenu* menu ) override
: QskMenuButton( text, parent )
{
const auto names = qskSkinManager->skinNames();
for ( const auto& name : names )
menu->addOption( QUrl(), name );
setOptions( names );
if ( const auto index = names.indexOf( qskSkinManager->skinName() ) )
menu->setCurrentIndex( index );
setStartIndex( index );
connect( menu, &QskMenu::triggered, this, &SkinButton::changeSkin );
connect( this, &QskMenuButton::triggered,
this, &SkinButton::changeSkin );
}
void openMenu() override
{
const auto names = qskSkinManager->skinNames();
setStartIndex( names.indexOf( qskSkinManager->skinName() ) );
QskMenuButton::openMenu();
}
void changeSkin( int index )
@ -175,26 +157,27 @@ namespace
}
};
class FileButton final : public MenuButton
class FileButton final : public QskMenuButton
{
public:
FileButton( const QString& text, QQuickItem* parent = nullptr )
: MenuButton( text, parent )
: QskMenuButton( text, parent )
{
}
private:
void populateMenu( QskMenu* menu ) override
{
menu->addOption( "image://shapes/Rectangle/White", "Print" );
menu->addOption( "image://shapes/Diamond/Yellow", "Save As" );
menu->addOption( "image://shapes/Ellipse/Red", "Setup" );
menu->addSeparator();
menu->addOption( "image://shapes/Hexagon/PapayaWhip", "Quit" );
addOption( "image://shapes/Rectangle/White", "Print" );
addOption( "image://shapes/Diamond/Yellow", "Save As" );
addOption( "image://shapes/Ellipse/Red", "Setup" );
addSeparator();
addOption( "image://shapes/Hexagon/PapayaWhip", "Quit" );
// see https://github.com/uwerat/qskinny/issues/192
connect( menu, &QskMenu::triggered,
[]( int index ) { if ( index == 4 ) qApp->quit(); } );
connect( this, &QskMenuButton::triggered,
this, &FileButton::activate );
}
private:
void activate( int index )
{
if ( optionAt( index ).text() == "Quit" )
qApp->quit();
}
};

View File

@ -14,8 +14,8 @@ StorageBarSkinlet::StorageBarSkinlet( QskSkin* skin )
setNodeRoles( { Pictures, Music, Videos, Documents, Others, Free } );
}
QRectF StorageBarSkinlet::subControlRect( const QskSkinnable* skinnable,
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
QRectF StorageBarSkinlet::subControlRect( const QskSkinnable* skinnable, const QRectF& contentsRect,
QskAspect::Subcontrol subControl ) const
{
const auto* const bar = static_cast< const S* >( skinnable );
@ -70,29 +70,35 @@ QRectF StorageBarSkinlet::subControlRect( const QskSkinnable* skinnable,
return Inherited::subControlRect( skinnable, contentsRect, subControl );
}
namespace
{
inline QSGNode* updateSegmentBoxNode(
const S* const skinnable, const QskAspect::Subcontrol& subcontrol, QSGNode* const node )
{
return QskSkinlet::updateBoxNode( skinnable, node, skinnable->subControlRect( subcontrol ),
skinnable->gradientHint( subcontrol ), subcontrol );
}
}
QSGNode* StorageBarSkinlet::updateSubNode(
const QskSkinnable* const skinnable, const quint8 nodeRole, QSGNode* const node ) const
{
const auto* const bar = static_cast< const S* >( skinnable );
switch ( nodeRole )
{
case Pictures:
return updateBoxNode( skinnable, node, S::Pictures );
return updateSegmentBoxNode( bar, S::Pictures, node );
case Music:
return updateBoxNode( skinnable, node, S::Music );
return updateSegmentBoxNode( bar, S::Music, node );
case Videos:
return updateBoxNode( skinnable, node, S::Videos );
return updateSegmentBoxNode( bar, S::Videos, node );
case Documents:
return updateBoxNode( skinnable, node, S::Documents );
return updateSegmentBoxNode( bar, S::Documents, node );
case Others:
return updateBoxNode( skinnable, node, S::Others );
return updateSegmentBoxNode( bar, S::Others, node );
case Free:
return updateBoxNode( skinnable, node, S::Free );
return updateSegmentBoxNode( bar, S::Free, node );
default:
return Inherited::updateSubNode( skinnable, nodeRole, node );
}

View File

@ -9,7 +9,6 @@
#include <QskSGNode.h>
#include <QskTextOptions.h>
#include <QskTextColors.h>
#include <QskBoxHints.h>
#include <QskPlotCurve.h>
#include <QskPlotCorridor.h>
@ -144,10 +143,8 @@ QSGNode* PlotCursorSkinlet::updateSampleNode( const QskSkinnable* skinnable,
if ( subControl == Q::LabelPanel )
{
auto hints = skinnable->boxHints( subControl );
hints.gradient = skinnable->gradientHint( aspect );
return updateBoxNode( skinnable, node, rect, hints );
const auto gradient = skinnable->gradientHint( aspect );
return updateBoxNode( skinnable, node, rect, gradient, subControl );
}
if ( subControl == Q::LabelText )

View File

@ -35,6 +35,6 @@ if (QT_VERSION_MAJOR VERSION_GREATER_EQUAL 6)
shaders/arcshadow-vulkan.vert
shaders/arcshadow-vulkan.frag
)
qsk_add_shaders( ${target} "qskArcShaders" FILES ${SHADERS} OUTPUT_TARGETS shader_target)
qsk_add_shaders( ${target} FILES ${SHADERS} OUTPUT_TARGETS shader_target)
endif()

View File

@ -8,7 +8,7 @@
#include <QskSkinlet.h>
#include <QskArcNode.h>
#include <QskArcHints.h>
#include <QskArcMetrics.h>
#include <QskShadowMetrics.h>
#include <QskSGNode.h>
#include <QskRgbValue.h>
@ -107,7 +107,14 @@ namespace
return nullptr;
auto arcNode = QskSGNode::ensureNode< QskArcNode >( node );
arcNode->setArcData( rect, arc->arcHints( Q::Arc ) );
const auto metrics = arc->arcMetricsHint( Q::Arc );
const auto fillGradient = arc->gradientHint( Q::Arc );
const auto borderColor = arc->color( Q::Arc | QskAspect::Border );
const auto borderWidth = arc->metric( Q::Arc | QskAspect::Border );
arcNode->setArcData( rect, metrics, borderWidth, borderColor, fillGradient );
return arcNode;
}

View File

@ -21,7 +21,6 @@ Slider::Slider( const QString& text, qreal min, qreal max,
m_slider->setBoundaries( min, max );
m_slider->setStepSize( step );
m_slider->setSnapping( true );
m_slider->setTickPolicy( Qsk::Never ); // too many steps
m_slider->setValue( value );
m_valueLabel = new QskTextLabel( this );

View File

@ -5,7 +5,6 @@
list(APPEND HEADERS
common/QskArcMetrics.h
common/QskArcHints.h
common/QskAspect.h
common/QskBoxBorderColors.h
common/QskBoxBorderMetrics.h
@ -42,7 +41,6 @@ list(APPEND HEADERS
list(APPEND SOURCES
common/QskArcMetrics.cpp
common/QskArcHints.cpp
common/QskAspect.cpp
common/QskBoxBorderColors.cpp
common/QskBoxBorderMetrics.cpp
@ -235,6 +233,7 @@ list(APPEND HEADERS
controls/QskListViewSkinlet.h
controls/QskMenu.h
controls/QskMenuSkinlet.h
controls/QskMenuButton.h
controls/QskObjectTree.h
controls/QskPageIndicator.h
controls/QskPageIndicatorSkinlet.h
@ -345,8 +344,9 @@ list(APPEND SOURCES
controls/QskItemAnchors.cpp
controls/QskListView.cpp
controls/QskListViewSkinlet.cpp
controls/QskMenuSkinlet.cpp
controls/QskMenu.cpp
controls/QskMenuSkinlet.cpp
controls/QskMenuButton.cpp
controls/QskObjectTree.cpp
controls/QskPageIndicator.cpp
controls/QskPageIndicatorSkinlet.cpp
@ -510,7 +510,7 @@ else()
endif()
if (QT_VERSION_MAJOR VERSION_GREATER_EQUAL 6)
qsk_add_shaders( ${target} "qskshaders" FILES ${SHADERS} OUTPUT_TARGETS shader_target)
qsk_add_shaders( ${target} FILES ${SHADERS} OUTPUT_TARGETS shader_target)
endif()
target_include_directories(${target} PUBLIC

View File

@ -1,69 +0,0 @@
/******************************************************************************
* QSkinny - Copyright (C) The authors
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "QskArcHints.h"
#include "QskRgbValue.h"
static inline qreal qskInterpolated( qreal from, qreal to, qreal ratio )
{
return from + ( to - from ) * ratio;
}
QskArcHints::QskArcHints()
{
}
QskArcHints::QskArcHints( const QskArcMetrics& metrics, qreal borderWidth,
const QColor& borderColor, const QskGradient& gradient )
: metrics( metrics )
, borderWidth( borderWidth )
, borderColor( borderColor )
, gradient( gradient )
{
}
bool QskArcHints::isVisible() const
{
if ( metrics.isNull() )
return false;
if ( borderWidth > 0.0 && borderColor.isValid() && borderColor.alpha() > 0 )
return true;
return gradient.isVisible();
}
QskArcHints QskArcHints::toAbsolute( const QSizeF& size ) const noexcept
{
return QskArcHints( metrics.toAbsolute( size ),
borderWidth, borderColor, gradient );
}
QskArcHints QskArcHints::interpolated(
const QskArcHints& to, qreal value ) const noexcept
{
return QskArcHints(
metrics.interpolated( to.metrics, value ),
qskInterpolated( borderWidth, to.borderWidth, value ),
QskRgb::interpolated( borderColor, to.borderColor, value ),
gradient.interpolated( to.gradient, value )
);
}
#ifndef QT_NO_DEBUG_STREAM
#include <qdebug.h>
QDebug operator<<( QDebug debug, const QskArcHints& hints )
{
debug << hints.metrics << hints.borderWidth
<< hints.borderColor << hints.gradient;
return debug;
}
#endif
#include "moc_QskArcHints.cpp"

View File

@ -1,47 +0,0 @@
/******************************************************************************
* QSkinny - Copyright (C) The authors
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#ifndef QSK_ARC_HINTS_H
#define QSK_ARC_HINTS_H
#include "QskArcMetrics.h"
#include "QskGradient.h"
#include <qcolor.h>
class QSK_EXPORT QskArcHints
{
Q_GADGET
Q_PROPERTY( QskArcMetrics metrics MEMBER metrics )
Q_PROPERTY( qreal borderWidth MEMBER borderWidth )
Q_PROPERTY( QColor borderColor MEMBER borderColor )
public:
QskArcHints();
QskArcHints( const QskArcMetrics&, qreal borderWidth,
const QColor& borderColor, const QskGradient& );
QskArcHints toAbsolute( const QSizeF& ) const noexcept;
QskArcHints interpolated(
const QskArcHints&, qreal value ) const noexcept;
bool isVisible() const;
QskArcMetrics metrics;
qreal borderWidth = 0.0;
QColor borderColor;
QskGradient gradient;
};
#ifndef QT_NO_DEBUG_STREAM
class QDebug;
QSK_EXPORT QDebug operator<<( QDebug, const QskArcHints& );
#endif
#endif

View File

@ -81,7 +81,7 @@ QskGradient::QskGradient( const QColor& color1, const QColor& color2 )
QskGradient::QskGradient( QGradient::Preset preset )
: QskGradient()
{
setStops( qskFromQGradientStops( QGradient( preset ).stops() ) );
setStops( qskBuildGradientStops( QGradient( preset ).stops() ) );
}
QskGradient::QskGradient( const QVector< QskGradientStop >& stops )
@ -165,7 +165,7 @@ QskGradient::QskGradient( const QGradient& qGradient )
}
}
setStops( qskFromQGradientStops( qGradient.stops() ) );
setStops( qskBuildGradientStops( qGradient.stops() ) );
}
QskGradient::QskGradient( const QskGradient& other ) noexcept
@ -305,7 +305,7 @@ void QskGradient::setStops( const QColor& color1, const QColor& color2 )
void QskGradient::setStops( QGradient::Preset preset )
{
const auto stops = qskFromQGradientStops( QGradient( preset ).stops() );
const auto stops = qskBuildGradientStops( QGradient( preset ).stops() );
setStops( stops );
}

View File

@ -23,31 +23,6 @@ static void qskRegisterGradientStop()
Q_CONSTRUCTOR_FUNCTION( qskRegisterGradientStop )
static inline qreal qskBoundedStopPos( qreal pos )
{
if ( ( pos < 0.0 ) || qFuzzyIsNull( pos ) )
return 0.0;
if ( ( pos > 1.0 ) || qFuzzyCompare( pos, 1.0 ) )
return 1.0;
return pos;
}
static inline QVector< QskGradientStop >
qskNormalizedStops( const QVector< QskGradientStop >& stops )
{
auto s = stops;
if ( s.first().position() > 0.0 )
s.prepend( QskGradientStop( 0.0, s.first().color() ) );
if ( s.last().position() < 1.0 )
s.append( QskGradientStop( 1.0, s.last().color() ) );
return s;
}
void QskGradientStop::setPosition( qreal position ) noexcept
{
m_position = position;
@ -81,19 +56,26 @@ QskHashValue QskGradientStop::hash( QskHashValue seed ) const noexcept
return qHashBits( &m_color, sizeof( m_color ), hash );
}
QskGradientStop QskGradientStop::interpolated(
const QskGradientStop& to, qreal ratio ) const
QColor QskGradientStop::interpolated(
const QskGradientStop& s1, const QskGradientStop& s2, qreal position ) noexcept
{
return QskGradientStop(
m_position + ( to.m_position - m_position ) * ratio,
QskRgb::interpolated( m_color, to.m_color, ratio )
);
}
if ( s1.color() == s2.color() )
return s1.color();
QVariant QskGradientStop::interpolate(
const QskGradientStop& from, const QskGradientStop& to, qreal ratio )
{
return QVariant::fromValue( from.interpolated( to, ratio ) );
auto min = &s1;
auto max = &s2;
if ( min->position() > max->position() )
std::swap( min, max );
if ( position <= min->position() )
return min->color();
if ( position >= max->position() )
return max->color();
const qreal r = ( position - min->position() ) / ( max->position() - min->position() );
return QskRgb::interpolated( min->color(), max->color(), r );
}
#ifndef QT_NO_DEBUG_STREAM
@ -113,23 +95,19 @@ QDebug operator<<( QDebug debug, const QskGradientStop& stop )
#endif
#include "moc_QskGradientStop.cpp"
// some helper functions around QskGradientStops
static inline QColor qskColorAtPosition(
const QskGradientStop& s1, const QskGradientStop& s2, qreal pos )
static inline QColor qskInterpolatedColor(
const QskGradientStops& stops, int index1, int index2, qreal position )
{
const auto dp = s2.position() - s1.position();
if ( qFuzzyIsNull( dp ) )
return s1.color();
const auto max = static_cast< int >( stops.count() ) - 1;
return QskRgb::interpolated(
s1.color(), s2.color(), ( pos - s1.position() ) / dp );
}
index1 = qBound( 0, index1, max );
index2 = qBound( 0, index2, max );
static inline QskGradientStop qskCreateStopAtPosition(
const QskGradientStop& s1, const QskGradientStop& s2, qreal pos )
{
return { pos, qskColorAtPosition( s1, s2, pos ) };
return QskGradientStop::interpolated( stops[ index1 ], stops[ index2 ], position );
}
bool qskIsVisible( const QskGradientStops& stops ) noexcept
@ -300,126 +278,43 @@ QColor qskInterpolatedColorAt( const QskGradientStops& stops, qreal pos ) noexce
if ( stops.isEmpty() )
return QColor();
pos = qBound( 0.0, pos, 1.0 );
if ( pos <= stops.first().position() )
return stops.first().color();
for ( int i = 1; i < stops.count(); i++ )
{
if ( pos <= stops[i].position() )
return qskColorAtPosition( stops[ i - 1 ], stops[ i ], pos );
return qskInterpolatedColor( stops, i - 1, i, pos );
}
return stops.last().color();
}
QskGradientStops qskReplacedGradientStops( const QskGradientStops& gradientStops,
const QskGradientStop& stop1, const QskGradientStop& stop2 )
{
if ( stop1.position() >= stop2.position() )
return gradientStops;
const auto s1 = QskGradientStop( qskBoundedStopPos( stop1.position() ), stop1.color() );
const auto s2 = QskGradientStop( qskBoundedStopPos( stop2.position() ), stop2.color() );
QskGradientStops stops;
if ( s1.position() == 0.0 && s2.position() == 1.0 )
{
stops = { s1, s2 };
}
else if ( qskIsMonochrome( gradientStops ) )
{
stops.reserve( 4 );
const auto c = gradientStops.isEmpty()
? QColor::fromRgba( 0 ) : gradientStops.first().color();
if ( s1.position() > 0.0 )
stops += { s1.position(), c };
stops += s1;
stops += s2;
if ( s2.position() < 1.0 )
stops += { s2.position(), c };
}
else
{
// not the most efficient implementation - maybe later TODO ...
const auto stops0 = qskNormalizedStops( gradientStops );
int i = 0;
if ( s1.position() > 0.0 )
{
while ( s1.position() > stops0[i].position() )
stops += stops0[i++];
if ( s1.position() == stops0[i].position() )
stops += stops0[i++];
else
stops += qskCreateStopAtPosition( stops0[i - 1], stops0[i], s1.position() );
}
stops += s1;
while ( s2.position() > stops0[i].position() )
i++;
stops += s2;
if ( s2.position() < 1.0 )
{
while ( stops0[i + 1].position() == s2.position() )
i++;
if ( s2.position() != stops0[i].position() )
stops += qskCreateStopAtPosition( stops0[i - 1], stops0[i], s2.position() );
while( i < stops0.count() )
stops += stops0[i++];
}
}
return stops;
}
QskGradientStops qskClippedGradientStops(
const QskGradientStops& stops, qreal from, qreal to )
{
return qskReplacedGradientStops( stops, { from, 0 }, { to, 0 } );
}
QskGradientStops qskExtractedGradientStops(
const QskGradientStops& stops, qreal from, qreal to )
const QskGradientStops& gradientStops, qreal from, qreal to )
{
if ( ( from > to ) || ( to > 1.0 ) || ( from < 0.0 ) || stops.isEmpty() )
if ( ( from > to ) || ( from > 1.0 ) || gradientStops.isEmpty() )
return QskGradientStops();
from = qskBoundedStopPos( from );
to = qskBoundedStopPos( to );
if ( ( from <= 0.0 ) && ( to >= 1.0 ) )
return gradientStops;
if ( ( from == 0.0 ) && ( to == 1.0 ) )
return stops;
from = qMax( from, 0.0 );
to = qMin( to, 1.0 );
if ( from == to )
{
const auto color = qskInterpolatedColorAt( stops, from );
QVector< QskGradientStop > stops1 = gradientStops;
QVector< QskGradientStop > s;
s.reserve( 2 );
s += QskGradientStop( 0.0, color );
s += QskGradientStop( 1.0, color );
#if 1
// not the most efficient implementation - maybe later TODO ...
return s;
}
if ( stops1.first().position() > 0.0 )
stops1.prepend( QskGradientStop( 0.0, stops1.first().color() ) );
/*
For situations where we have no stops at 0.0 and 1.0 we insert them
manually. Not the most efficient implementation, but we avoid having
to deal with these situations for the moment. TODO ...
*/
const auto stops1 = qskNormalizedStops( stops );
if ( stops1.last().position() < 1.0 )
stops1.append( QskGradientStop( 1.0, stops1.last().color() ) );
#endif
QVector< QskGradientStop > stops2;
stops2.reserve( stops1.count() );
@ -436,26 +331,26 @@ QskGradientStops qskExtractedGradientStops(
{
int i = 0;
if ( from == 0.0 )
for ( ; i < stops1.count(); i++ )
{
stops2 += stops1[i++];
if ( stops1[i].position() > from )
break;
}
else
{
while( stops1[++i].position() <= from ); // skip leading stops
stops2 += QskGradientStop( 0.0,
qskColorAtPosition( stops1[i - 1], stops1[ i ], from ) );
}
qskInterpolatedColor( stops1, i - 1, i, from ) );
while ( stops1[i].position() < to )
for ( ; i < stops1.count(); i++ )
{
if ( stops1[i].position() >= to )
break;
const auto pos = ( stops1[i].position() - from ) / ( to - from );
stops2 += QskGradientStop( pos, stops1[i++].color() );
stops2 += QskGradientStop( pos, stops1[i].color() );
}
stops2 += QskGradientStop( 1.0,
qskColorAtPosition( stops1[i - 1], stops1[ i ], to ) );
qskInterpolatedColor( stops1, i, i + 1, to ) );
}
return stops2;
@ -472,7 +367,7 @@ QskGradientStops qskRevertedGradientStops( const QskGradientStops& stops )
return s;
}
QVector< QskGradientStop > qskFromQGradientStops( const QGradientStops& qtStops )
QVector< QskGradientStop > qskBuildGradientStops( const QGradientStops& qtStops )
{
QVector< QskGradientStop > stops;
stops.reserve( qtStops.count() );
@ -568,5 +463,3 @@ QGradientStops qskToQGradientStops( const QskGradientStops& stops )
return qStops;
}
#include "moc_QskGradientStop.cpp"

View File

@ -45,10 +45,8 @@ class QSK_EXPORT QskGradientStop
void setRgb( QRgb ) noexcept;
QRgb rgb() const noexcept;
QskGradientStop interpolated( const QskGradientStop&, qreal ) const;
static QVariant interpolate( const QskGradientStop&,
const QskGradientStop&, qreal );
static QColor interpolated(
const QskGradientStop&, const QskGradientStop&, qreal position ) noexcept;
QskHashValue hash( QskHashValue seed ) const noexcept;
@ -131,48 +129,27 @@ QSK_EXPORT QskGradientStops qskInterpolatedGradientStops(
const QskGradientStops&, bool, const QskGradientStops&, bool,
qreal ratio );
// interpolating colors in direction of a color.
QSK_EXPORT QskGradientStops qskInterpolatedGradientStops(
const QskGradientStops&, const QColor&, qreal ratio );
// interpolating colors starting from a color.
QSK_EXPORT QskGradientStops qskInterpolatedGradientStops(
const QColor&, const QskGradientStops&, qreal ratio );
// interpolating the opacity of the colors
QSK_EXPORT QskGradientStops qskTransparentGradientStops(
const QskGradientStops&, qreal ratio );
// extracting the colors of [from, to ] and stretching them to [0.0, 1.0]
QSK_EXPORT QskGradientStops qskExtractedGradientStops(
const QskGradientStops&, qreal from, qreal to );
// reverting the color stops
QSK_EXPORT QskGradientStops qskRevertedGradientStops( const QskGradientStops& );
QSK_EXPORT QskGradientStops qskReplacedGradientStops(
const QskGradientStops&, const QskGradientStop&, const QskGradientStop& );
QSK_EXPORT QskGradientStops qskClippedGradientStops(
const QskGradientStops&, qreal from, qreal to );
/*
creating equidistant color stops from a list of colors.
when discrete is true the result will contain 2 stops at each position
one with the previous and one with the following color so that the
interval [pos1-pos2] will be monochrome.
*/
QSK_EXPORT QskGradientStops qskBuildGradientStops(
const QVector< QRgb >&, bool discrete = false );
QSK_EXPORT QskGradientStops qskBuildGradientStops(
const QVector< QColor >&, bool discrete = false );
/*
convert color stops from/to a vector of QGradientStop, that can be
used for QGradients.
*/
QSK_EXPORT QskGradientStops qskFromQGradientStops( const QVector< QGradientStop >& );
QSK_EXPORT QskGradientStops qskRevertedGradientStops( const QskGradientStops& );
QSK_EXPORT QskGradientStops qskBuildGradientStops( const QVector< QGradientStop >& );
QSK_EXPORT QVector< QGradientStop > qskToQGradientStops( const QVector< QskGradientStop >& );
#endif

View File

@ -41,7 +41,7 @@ class QSK_EXPORT QskTextColors
void setLinkColor( QRgb );
void setLinkColor( Qt::GlobalColor );
QskTextColors interpolated( const QskTextColors&, qreal ratio ) const;
QskTextColors interpolated( const QskTextColors&, qreal value ) const;
static QVariant interpolate( const QskTextColors&,
const QskTextColors&, qreal ratio );

View File

@ -0,0 +1,153 @@
/******************************************************************************
* QSkinny - Copyright (C) The authors
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "QskMenuButton.h"
#include "QskMenu.h"
#include "QskLabelData.h"
#include <qpointer.h>
#include <qquickwindow.h>
class QskMenuButton::PrivateData
{
public:
int triggeredIndex = -1;
int startIndex = -1;
QPointer< QskMenu > menu;
QVector< QskLabelData > options;
};
QskMenuButton::QskMenuButton( QQuickItem* parent )
: QskMenuButton( QString(), parent )
{
}
QskMenuButton::QskMenuButton( const QString& text, QQuickItem* parent )
: QskPushButton( text, parent )
, m_data( new PrivateData )
{
connect( this, &QskPushButton::pressed,
this, &QskMenuButton::openMenu );
}
QskMenuButton::~QskMenuButton()
{
}
int QskMenuButton::addOption( const QString& graphicSource, const QString& text )
{
return addOption( QskLabelData( text, graphicSource ) );
}
int QskMenuButton::addOption( const QUrl& graphicSource, const QString& text )
{
return addOption( QskLabelData( text, graphicSource ) );
}
int QskMenuButton::addOption( const QskLabelData& option )
{
const int index = m_data->options.count();
m_data->options += option;
if ( m_data->menu )
m_data->menu->setOptions( m_data->options );
return index;
}
void QskMenuButton::addSeparator()
{
addOption( QskLabelData() );
}
void QskMenuButton::setOptions( const QStringList& options )
{
setOptions( qskCreateLabelData( options ) );
}
void QskMenuButton::setOptions( const QVector< QskLabelData >& options )
{
m_data->options = options;
if ( m_data->menu )
m_data->menu->setOptions( m_data->options );
}
void QskMenuButton::clear()
{
m_data->options.clear();
if ( m_data->menu )
m_data->menu->clear();
}
QVector< QskLabelData > QskMenuButton::options() const
{
return m_data->options;
}
QskLabelData QskMenuButton::optionAt( int index ) const
{
return m_data->options.value( index );
}
int QskMenuButton::optionsCount() const
{
return m_data->options.count();
}
void QskMenuButton::setStartIndex( int index )
{
m_data->startIndex = index;
}
int QskMenuButton::triggeredIndex() const
{
return m_data->triggeredIndex;
}
QString QskMenuButton::triggeredText() const
{
return optionAt( m_data->triggeredIndex ).text();
}
const QskMenu* QskMenuButton::menu() const
{
return m_data->menu;
}
void QskMenuButton::openMenu()
{
if ( m_data->menu || window() == nullptr || m_data->options.isEmpty() )
return;
m_data->triggeredIndex = -1;
auto menu = new QskMenu( window()->contentItem() );
m_data->menu = menu;
menu->setOptions( m_data->options );
if ( m_data->startIndex >= 0 )
menu->setCurrentIndex( m_data->startIndex );
menu->setOrigin( geometry().bottomLeft() );
connect( menu, &QskMenu::triggered,
this, &QskMenuButton::updateTriggeredIndex );
menu->open();
}
void QskMenuButton::updateTriggeredIndex( int index )
{
if ( m_data->triggeredIndex != index )
{
m_data->triggeredIndex = index;
Q_EMIT triggered( index );
}
}
#include "moc_QskMenuButton.cpp"

View File

@ -0,0 +1,67 @@
/******************************************************************************
* QSkinny - Copyright (C) The authors
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#ifndef QSK_MENU_BUTTON_H
#define QSK_MENU_BUTTON_H
#include "QskPushButton.h"
class QskMenu;
class QskLabelData;
class QSK_EXPORT QskMenuButton : public QskPushButton
{
Q_OBJECT
Q_PROPERTY( QVector< QskLabelData > options READ options
WRITE setOptions NOTIFY optionsChanged )
Q_PROPERTY( int optionsCount READ optionsCount )
Q_PROPERTY( int triggeredIndex READ triggeredIndex NOTIFY triggered )
Q_PROPERTY( QString triggeredText READ triggeredText NOTIFY triggered )
public:
QskMenuButton( QQuickItem* parent = nullptr );
QskMenuButton( const QString& text, QQuickItem* parent = nullptr );
~QskMenuButton() override;
int addOption( const QString&, const QString& );
int addOption( const QUrl&, const QString& );
int addOption( const QskLabelData& );
void addSeparator();
void setOptions( const QVector< QskLabelData >& );
void setOptions( const QStringList& );
QVector< QskLabelData > options() const;
QskLabelData optionAt( int ) const;
int optionsCount() const;
const QskMenu* menu() const;
int triggeredIndex() const;
QString triggeredText() const;
public Q_SLOTS:
void setStartIndex( int );
void clear();
Q_SIGNALS:
void triggered( int index );
void optionsChanged();
protected:
virtual void openMenu();
private:
void updateTriggeredIndex( int );
class PrivateData;
std::unique_ptr< PrivateData > m_data;
};
#endif

View File

@ -9,7 +9,6 @@
#include "QskGraphic.h"
#include "QskColorFilter.h"
#include "QskTextOptions.h"
#include "QskBoxHints.h"
#include "QskFunctions.h"
#include "QskMargins.h"
#include "QskFunctions.h"
@ -573,13 +572,11 @@ QSGNode* QskMenuSkinlet::updateSampleNode( const QskSkinnable* skinnable,
if ( subControl == Q::Separator )
{
auto hints = skinnable->boxHints( subControl );
auto& gradient = hints.gradient;
auto gradient = menu->gradientHint( subControl );
if ( ( gradient.type() == QskGradient::Stops ) && !gradient.isMonochrome() )
gradient.setLinearDirection( Qt::Vertical );
return updateBoxNode( menu, node, rect, hints );
return updateBoxNode( menu, node, rect, gradient, subControl );
}
return nullptr;

View File

@ -6,7 +6,6 @@
#include "QskPopupSkinlet.h"
#include "QskPopup.h"
#include "QskRgbValue.h"
#include "QskBoxHints.h"
static inline QRgb qskInterpolatedRgb( QRgb rgb, qreal factor )
{
@ -59,9 +58,7 @@ QSGNode* QskPopupSkinlet::updateOverlayNode(
if ( rect.isEmpty() )
return nullptr;
auto hints = popup->boxHints( Q::Overlay );
auto& gradient = hints.gradient;
auto gradient = popup->gradientHint( Q::Overlay );
if ( gradient.isVisible() && factor != 1.0 )
{
@ -73,7 +70,7 @@ QSGNode* QskPopupSkinlet::updateOverlayNode(
gradient.setStops( stops );
}
return updateBoxNode( popup, node, rect, hints );
return updateBoxNode( popup, node, rect, gradient, QskPopup::Overlay );
}
#include "moc_QskPopupSkinlet.cpp"

View File

@ -6,7 +6,7 @@
#include "QskProgressBarSkinlet.h"
#include "QskProgressBar.h"
#include "QskIntervalF.h"
#include "QskBoxHints.h"
#include "QskBoxBorderMetrics.h"
#include <qeasingcurve.h>
#include <cmath>
@ -50,6 +50,41 @@ static QskIntervalF qskFillInterval( const QskProgressIndicator* indicator )
return QskIntervalF( pos1, pos2 );
}
static QskGradient qskFillGradient( const QskProgressBar* progressBar )
{
auto gradient = progressBar->gradientHint( Q::Fill );
if ( gradient.isVisible() && !gradient.isMonochrome()
&& ( gradient.type() == QskGradient::Stops ) )
{
/*
When having stops only we use a linear gradient,
where the colors are increasing in direction of the
progress value. We interprete the gradient as a
definition for the 100% situation and have to adjust
the stops for smaller bars.
For this situation it would be more convenient to
adjust the start/stop positions, but the box renderer is
not supporting this yet. TODO ...
*/
const auto intv = qskFillInterval( progressBar );
const auto stops = qskExtractedGradientStops(
gradient.stops(), intv.lowerBound(), intv.upperBound() );
gradient.setStops( stops );
gradient.setLinearDirection( progressBar->orientation() );
if ( progressBar->orientation() == Qt::Vertical || progressBar->layoutMirroring() )
gradient.reverse();
}
return gradient;
}
QskProgressBarSkinlet::QskProgressBarSkinlet( QskSkin* skin )
: Inherited( skin )
{
@ -87,40 +122,9 @@ QSGNode* QskProgressBarSkinlet::updateFillNode(
if ( rect.isEmpty() )
return nullptr;
auto hints = indicator->boxHints( Q::Fill );
auto& gradient = hints.gradient;
if ( gradient.isVisible() && !gradient.isMonochrome()
&& ( gradient.type() == QskGradient::Stops ) )
{
/*
When having stops only we use a linear gradient,
where the colors are increasing in direction of the
progress value. We interprete the gradient as a
definition for the 100% situation and have to adjust
the stops for smaller bars.
For this situation it would be more convenient to
adjust the start/stop positions, but the box renderer is
not supporting this yet. TODO ...
*/
const auto intv = qskFillInterval( indicator );
const auto stops = qskExtractedGradientStops(
gradient.stops(), intv.lowerBound(), intv.upperBound() );
gradient.setStops( stops );
const auto orientation = static_cast< const Q* >( indicator )->orientation();
gradient.setLinearDirection( orientation );
if ( orientation == Qt::Vertical || indicator->layoutMirroring() )
gradient.reverse();
}
return updateBoxNode( indicator, node, rect, hints );
const auto progressBar = static_cast< const Q* >( indicator );
return updateBoxNode( indicator, node, rect,
qskFillGradient( progressBar ), Q::Fill );
}
QRectF QskProgressBarSkinlet::grooveRect(

View File

@ -4,7 +4,7 @@
*****************************************************************************/
#include "QskProgressRingSkinlet.h"
#include "QskArcHints.h"
#include "QskArcMetrics.h"
#include "QskProgressRing.h"
#include "QskIntervalF.h"
@ -85,12 +85,8 @@ QSGNode* QskProgressRingSkinlet::updateGrooveNode(
endAngle = fillAngles.first - 360.0 + spacing;
}
auto hints = indicator->arcHints( Q::Groove );
hints.metrics.setStartAngle( startAngle );
hints.metrics.setSpanAngle( endAngle - startAngle );
const auto rect = indicator->subControlRect( Q::Groove );
return updateArcNode( ring, node, rect, hints );
return updateArcNode( ring, node,
startAngle, endAngle - startAngle, Q::Groove );
}
}
@ -108,14 +104,16 @@ QSGNode* QskProgressRingSkinlet::updateFillNode(
if ( rect.isEmpty() )
return nullptr;
auto hints = ring->arcHints( subControl );
if ( !hints.isVisible() )
const auto metrics = ring->arcMetricsHint( subControl );
if ( metrics.isNull() )
return nullptr;
auto gradient = ring->gradientHint( subControl );
if ( !gradient.isVisible() )
return nullptr;
const auto intv = qskFillInterval( ring );
auto& gradient = hints.gradient;
if ( ( gradient.type() == QskGradient::Stops ) && !gradient.isMonochrome() )
{
const auto stops = qskExtractedGradientStops( gradient.stops(),
@ -123,15 +121,14 @@ QSGNode* QskProgressRingSkinlet::updateFillNode(
gradient.setStops( stops );
if ( hints.metrics.spanAngle() < 0.0 )
if ( metrics.spanAngle() < 0.0 )
gradient.reverse();
}
const auto angles = qskFillAngles( hints.metrics, intv );
hints.metrics.setStartAngle( angles.first );
hints.metrics.setSpanAngle( angles.second - angles.first );
const auto angles = qskFillAngles( metrics, intv );
return updateArcNode( ring, node, rect, hints );
return updateArcNode( ring, node, rect, gradient,
angles.first, angles.second - angles.first, subControl );
}
QSizeF QskProgressRingSkinlet::sizeHint( const QskSkinnable* skinnable,

View File

@ -6,7 +6,6 @@
#include "QskSeparatorSkinlet.h"
#include "QskSeparator.h"
#include "QskBoxHints.h"
#include "QskGradientDirection.h"
#include "QskAspect.h"
@ -43,12 +42,8 @@ QSGNode* QskSeparatorSkinlet::updateSubNode(
using Q = QskSeparator;
const auto rect = separator->subControlRect( Q::Panel );
if ( rect.isEmpty() )
return nullptr;
auto hints = separator->boxHints( Q::Panel );
auto& gradient = hints.gradient;
auto gradient = separator->gradientHint( Q::Panel );
if ( ( gradient.type() == QskGradient::Stops ) && !gradient.isMonochrome() )
{
// gradient in opposite orientation
@ -58,7 +53,7 @@ QSGNode* QskSeparatorSkinlet::updateSubNode(
gradient.setLinearDirection( orientation );
}
return updateBoxNode( separator, node, rect, hints );
return updateBoxNode( separator, node, rect, gradient, Q::Panel );
}
}

View File

@ -7,7 +7,9 @@
#include "QskArcNode.h"
#include "QskAspect.h"
#include "QskArcHints.h"
#include "QskArcMetrics.h"
#include "QskBoxBorderColors.h"
#include "QskBoxBorderMetrics.h"
#include "QskBoxNode.h"
#include "QskBoxRectangleNode.h"
#include "QskBoxShapeMetrics.h"
@ -154,6 +156,18 @@ static inline bool qskIsBoxVisible( const QskBoxBorderMetrics& borderMetrics,
return !borderMetrics.isNull() && borderColors.isVisible();
}
static inline bool qskIsArcVisible( const QskArcMetrics& arcMetrics,
qreal borderWidth, const QColor borderColor, const QskGradient& gradient )
{
if ( arcMetrics.isNull() )
return false;
if ( borderWidth > 0.0 && borderColor.isValid() && borderColor.alpha() > 0 )
return true;
return gradient.isVisible();
}
static inline bool qskIsLineVisible( const QColor& lineColor, qreal lineWidth )
{
return ( lineWidth > 0.0 ) && lineColor.isValid() && ( lineColor.alpha() > 0 );
@ -188,18 +202,22 @@ static inline QQuickWindow* qskWindowOfSkinnable( const QskSkinnable* skinnable
return nullptr;
}
static inline QSGNode* qskUpdateBoxNode( const QskSkinnable* skinnable,
QSGNode* node, const QRectF& rect, const QskBoxHints& hints )
static inline QSGNode* qskUpdateBoxNode(
const QskSkinnable* skinnable, QSGNode* node, const QRectF& rect,
const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& borderMetrics,
const QskBoxBorderColors& borderColors, const QskGradient& gradient,
const QskShadowMetrics& shadowMetrics, const QColor& shadowColor )
{
if ( !rect.isEmpty() )
{
if ( qskIsBoxVisible( hints.borderMetrics, hints.borderColors, hints.gradient )
|| qskIsShadowVisible( hints.shadowMetrics, hints.shadowColor ) )
if ( qskIsBoxVisible( borderMetrics, borderColors, gradient )
|| qskIsShadowVisible( shadowMetrics, shadowColor ) )
{
if ( auto window = qskWindowOfSkinnable( skinnable ) )
{
auto boxNode = QskSGNode::ensureNode< QskBoxNode >( node );
boxNode->updateNode( window, rect, hints );
boxNode->updateNode( window, rect, shape, borderMetrics,
borderColors, gradient, shadowMetrics, shadowColor );
return boxNode;
}
@ -209,22 +227,23 @@ static inline QSGNode* qskUpdateBoxNode( const QskSkinnable* skinnable,
return nullptr;
}
static inline QSGNode* qskUpdateArcNode( const QskSkinnable* skinnable,
QSGNode* node, const QRectF& rect, const QskArcHints& hints )
static inline QSGNode* qskUpdateArcNode(
const QskSkinnable*, QSGNode* node, const QRectF& rect,
qreal borderWidth, const QColor borderColor,
const QskGradient& gradient, const QskArcMetrics& metrics )
{
Q_UNUSED( skinnable );
if ( rect.isEmpty() )
return nullptr;
if ( !qskIsArcVisible( metrics, borderWidth, borderColor, gradient ) )
return nullptr;
if ( !rect.isEmpty() && hints.isVisible() )
{
auto arcNode = QskSGNode::ensureNode< QskArcNode >( node );
arcNode->setArcData( rect, hints );
arcNode->setArcData( rect, metrics, borderWidth, borderColor, gradient );
return arcNode;
}
return nullptr;
}
static inline QSGNode* qskUpdateLineNode(
const QskSkinnable*, QSGNode* node, const QColor& lineColor,
qreal lineWidth, QskStippleMetrics& lineStipple, const QLineF& line )
@ -415,30 +434,54 @@ void QskSkinlet::replaceChildNode( quint8 role,
QSGNode* QskSkinlet::updateBoxNode( const QskSkinnable* skinnable,
QSGNode* node, QskAspect::Subcontrol subControl ) const
{
auto r = qskSubControlRect( this, skinnable, subControl );
if ( r.isEmpty() )
return nullptr;
r = r.marginsRemoved( skinnable->marginHint( subControl ) );
return qskUpdateBoxNode( skinnable, node,
r, skinnable->boxHints( subControl ) );
const auto rect = qskSubControlRect( this, skinnable, subControl );
return updateBoxNode( skinnable, node, rect, subControl );
}
QSGNode* QskSkinlet::updateBoxNode( const QskSkinnable* skinnable,
QSGNode* node, const QRectF& rect, QskAspect::Subcontrol subControl )
{
if ( rect.isEmpty() )
const auto fillGradient = skinnable->gradientHint( subControl );
return updateBoxNode( skinnable, node, rect, fillGradient, subControl );
}
QSGNode* QskSkinlet::updateBoxNode( const QskSkinnable* skinnable,
QSGNode* node, const QRectF& rect, const QskGradient& fillGradient,
QskAspect::Subcontrol subControl )
{
const auto margins = skinnable->marginHint( subControl );
const auto boxRect = rect.marginsRemoved( margins );
if ( boxRect.isEmpty() )
return nullptr;
const auto r = rect.marginsRemoved( skinnable->marginHint( subControl ) );
return qskUpdateBoxNode( skinnable, node, r, skinnable->boxHints( subControl ) );
const auto borderMetrics = skinnable->boxBorderMetricsHint( subControl );
const auto borderColors = skinnable->boxBorderColorsHint( subControl );
const auto shape = skinnable->boxShapeHint( subControl );
const auto shadowMetrics = skinnable->shadowMetricsHint( subControl );
const auto shadowColor = skinnable->shadowColorHint( subControl );
return qskUpdateBoxNode( skinnable, node,
boxRect, shape, borderMetrics, borderColors, fillGradient,
shadowMetrics, shadowColor );
}
QSGNode* QskSkinlet::updateBoxNode(
const QskSkinnable* skinnable, QSGNode* node, const QRectF& rect,
const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& borderMetrics,
const QskBoxBorderColors& borderColors, const QskGradient& fillGradient )
{
return qskUpdateBoxNode( skinnable, node,
rect, shape, borderMetrics, borderColors, fillGradient,
QskShadowMetrics(), QColor() );
}
QSGNode* QskSkinlet::updateBoxNode( const QskSkinnable* skinnable,
QSGNode* node, const QRectF& rect, const QskBoxHints& hints )
{
return qskUpdateBoxNode( skinnable, node, rect, hints );
return qskUpdateBoxNode( skinnable, node, rect,
hints.shape, hints.borderMetrics, hints.borderColors, hints.gradient,
hints.shadowMetrics, hints.shadowColor );
}
QSGNode* QskSkinlet::updateInterpolatedBoxNode(
@ -483,24 +526,79 @@ QSGNode* QskSkinlet::updateInterpolatedBoxNode(
QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable,
QSGNode* node, QskAspect::Subcontrol subControl ) const
{
auto rect = qskSubControlRect( this, skinnable, subControl );
rect = rect.marginsRemoved( skinnable->marginHint( subControl ) );
return qskUpdateArcNode( skinnable,
node, rect, skinnable->arcHints( subControl ) );
}
QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable,
QSGNode* node, const QRectF& rect, const QskArcHints& hints )
{
return qskUpdateArcNode( skinnable, node, rect, hints );
const auto rect = qskSubControlRect( this, skinnable, subControl );
return updateArcNode( skinnable, node, rect, subControl );
}
QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable,
QSGNode* node, const QRectF& rect, QskAspect::Subcontrol subControl )
{
const auto fillGradient = skinnable->gradientHint( subControl );
return updateArcNode( skinnable, node, rect, fillGradient, subControl );
}
QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable,
QSGNode* node, const QRectF& rect, const QskGradient& fillGradient,
QskAspect::Subcontrol subControl )
{
const auto metrics = skinnable->arcMetricsHint( subControl );
const auto r = rect.marginsRemoved( skinnable->marginHint( subControl ) );
const qreal borderWidth = skinnable->metric( subControl | QskAspect::Border );
QColor borderColor;
if ( borderWidth > 0.0 )
borderColor = skinnable->color( subControl | QskAspect::Border );
return qskUpdateArcNode( skinnable, node,
rect, skinnable->arcHints( subControl ) );
r, borderWidth, borderColor, fillGradient, metrics );
}
QSGNode* QskSkinlet::updateArcNode(
const QskSkinnable* skinnable, QSGNode* node, const QRectF& rect,
qreal borderWidth, const QColor& borderColor,
const QskGradient& fillGradient, const QskArcMetrics& metrics )
{
return qskUpdateArcNode( skinnable, node, rect,
borderWidth, borderColor, fillGradient, metrics );
}
QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable,
QSGNode* node, qreal startAngle, qreal spanAngle,
QskAspect::Subcontrol subControl ) const
{
const auto rect = qskSubControlRect( this, skinnable, subControl );
return updateArcNode( skinnable, node,
rect, startAngle, spanAngle, subControl );
}
QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable,
QSGNode* node, const QRectF& rect, qreal startAngle, qreal spanAngle,
QskAspect::Subcontrol subControl )
{
const auto fillGradient = skinnable->gradientHint( subControl );
return updateArcNode( skinnable, node, rect,
fillGradient, startAngle, spanAngle, subControl );
}
QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable,
QSGNode* node, const QRectF& rect, const QskGradient& fillGradient,
qreal startAngle, qreal spanAngle, QskAspect::Subcontrol subControl )
{
auto arcMetrics = skinnable->arcMetricsHint( subControl );
arcMetrics.setStartAngle( startAngle );
arcMetrics.setSpanAngle( spanAngle );
const qreal borderWidth = skinnable->metric( subControl | QskAspect::Border );
QColor borderColor;
if ( borderWidth > 0.0 )
borderColor = skinnable->color( subControl | QskAspect::Border );
const auto r = rect.marginsRemoved( skinnable->marginHint( subControl ) );
return updateArcNode( skinnable, node, r,
borderWidth, borderColor, fillGradient, arcMetrics );
}
QSGNode* QskSkinlet::updateLineNode( const QskSkinnable* skinnable,

View File

@ -23,8 +23,10 @@ class QskColorFilter;
class QskGraphic;
class QskTextOptions;
class QskTextColors;
class QskBoxShapeMetrics;
class QskBoxBorderMetrics;
class QskBoxBorderColors;
class QskBoxHints;
class QskArcHints;
class QSGNode;
@ -74,6 +76,13 @@ class QSK_EXPORT QskSkinlet
static QSGNode* updateBoxNode( const QskSkinnable*, QSGNode*,
const QRectF&, QskAspect::Subcontrol );
static QSGNode* updateBoxNode( const QskSkinnable*, QSGNode*,
const QRectF&, const QskGradient&, QskAspect::Subcontrol );
static QSGNode* updateBoxNode( const QskSkinnable*, QSGNode*,
const QRectF&, const QskBoxShapeMetrics&, const QskBoxBorderMetrics&,
const QskBoxBorderColors&, const QskGradient& );
static QSGNode* updateBoxNode( const QskSkinnable*, QSGNode*,
const QRectF&, const QskBoxHints& );
@ -85,7 +94,18 @@ class QSK_EXPORT QskSkinlet
const QRectF&, QskAspect::Subcontrol );
static QSGNode* updateArcNode( const QskSkinnable*, QSGNode*,
const QRectF&, const QskArcHints& );
const QRectF&, const QskGradient&, QskAspect::Subcontrol );
static QSGNode* updateArcNode( const QskSkinnable*, QSGNode*,
const QRectF&, qreal borderWidth, const QColor& borderColor,
const QskGradient&, const QskArcMetrics& );
static QSGNode* updateArcNode( const QskSkinnable*, QSGNode*,
const QRectF&, qreal startAngle, qreal spanAngle, QskAspect::Subcontrol );
static QSGNode* updateArcNode( const QskSkinnable*, QSGNode*,
const QRectF&, const QskGradient&, qreal startAngle, qreal spanAngle,
QskAspect::Subcontrol );
static QSGNode* updateLineNode( const QskSkinnable*, QSGNode*,
const QLineF&, QskAspect::Subcontrol );
@ -136,6 +156,10 @@ class QSK_EXPORT QskSkinlet
QSGNode* updateArcNode( const QskSkinnable*, QSGNode*,
QskAspect::Subcontrol ) const;
QSGNode* updateArcNode( const QskSkinnable*, QSGNode*,
qreal startAngle, qreal spanAngle,
QskAspect::Subcontrol ) const;
QSGNode* updateBoxClipNode( const QskSkinnable*, QSGNode*,
QskAspect::Subcontrol ) const;

View File

@ -6,7 +6,7 @@
#include "QskSkinnable.h"
#include "QskAnimationHint.h"
#include "QskArcHints.h"
#include "QskArcMetrics.h"
#include "QskAspect.h"
#include "QskColorFilter.h"
#include "QskControl.h"
@ -637,23 +637,9 @@ QColor QskSkinnable::shadowColorHint( QskAspect aspect, QskSkinHintStatus* statu
QskBoxHints QskSkinnable::boxHints( QskAspect aspect ) const
{
return QskBoxHints(
boxShapeHint( aspect ),
boxBorderMetricsHint( aspect ),
boxBorderColorsHint( aspect ),
gradientHint( aspect ),
shadowMetricsHint( aspect ),
shadowColorHint( aspect )
);
}
QskArcHints QskSkinnable::arcHints( QskAspect aspect ) const
{
return QskArcHints(
arcMetricsHint( aspect ),
metric( aspect | QskAspect::Border ),
color( aspect | QskAspect::Border ),
gradientHint( aspect )
);
boxShapeHint( aspect ), boxBorderMetricsHint( aspect ),
boxBorderColorsHint( aspect ), gradientHint( aspect ),
shadowMetricsHint( aspect ), shadowColorHint( aspect ) );
}
bool QskSkinnable::setArcMetricsHint(

View File

@ -22,7 +22,6 @@ class QDebug;
class QSGNode;
class QQuickItem;
class QskArcHints;
class QskArcMetrics;
class QskControl;
class QskAnimationHint;
@ -227,7 +226,6 @@ class QSK_EXPORT QskSkinnable
QColor shadowColorHint( QskAspect, QskSkinHintStatus* = nullptr ) const;
QskBoxHints boxHints( QskAspect ) const;
QskArcHints arcHints( QskAspect ) const;
bool setArcMetricsHint( QskAspect, const QskArcMetrics& );
bool resetArcMetricsHint( QskAspect );

View File

@ -197,23 +197,6 @@ bool QskSlider::hasOrigin() const
return m_data->hasOrigin;
}
void QskSlider::setTickPolicy( Qsk::Policy policy )
{
if ( setFlagHint( Tick | QskAspect::Option, policy ) )
Q_EMIT tickPolicyChanged( policy );
}
void QskSlider::resetTickPolicy()
{
if ( resetSkinHint( Tick | QskAspect::Option ) )
Q_EMIT tickPolicyChanged( tickPolicy() );
}
Qsk::Policy QskSlider::tickPolicy() const
{
return flagHint< Qsk::Policy >( Tick | QskAspect::Option, Qsk::Maybe );
}
QskAspect::Variation QskSlider::effectiveVariation() const
{
return static_cast< QskAspect::Variation >( m_data->orientation );

View File

@ -22,9 +22,6 @@ class QSK_EXPORT QskSlider : public QskBoundedValueInput
Q_PROPERTY( bool tracking READ isTracking
WRITE setTracking NOTIFY trackingChanged )
Q_PROPERTY( Qsk::Policy tickPolicy READ tickPolicy
WRITE setTickPolicy RESET resetTickPolicy NOTIFY tickPolicyChanged )
Q_PROPERTY( qreal origin READ origin
WRITE setOrigin RESET resetOrigin NOTIFY originChanged )
@ -42,10 +39,6 @@ class QSK_EXPORT QskSlider : public QskBoundedValueInput
void setOrientation( Qt::Orientation );
Qt::Orientation orientation() const;
void setTickPolicy( Qsk::Policy );
void resetTickPolicy();
Qsk::Policy tickPolicy() const;
void setInverted( bool );
bool isInverted() const;
@ -68,7 +61,6 @@ class QSK_EXPORT QskSlider : public QskBoundedValueInput
void invertedChanged( bool );
void trackingChanged( bool );
void originChanged( qreal );
void tickPolicyChanged( Qsk::Policy );
protected:
void mousePressEvent( QMouseEvent* ) override;

View File

@ -388,7 +388,10 @@ bool QskSliderSkinlet::hasGraduation( const QskSlider* slider ) const
{
if ( slider->stepSize() )
{
switch( slider->tickPolicy() )
const auto policy = slider->flagHint< Qsk::Policy >(
Q::Tick | QskAspect::Option, Qsk::Never );
switch( policy )
{
case Qsk::Always:
return true;

View File

@ -129,7 +129,7 @@ namespace
{
if ( qskIsAncestorOf( this, item ) )
{
const auto pos = mapFromItem( item, QPointF() ) + scrollPos();
const auto pos = mapFromItem( item, QPointF() );
ensureVisible( QRectF( pos.x(), pos.y(), item->width(), item->height() ) );
}
}

View File

@ -13,7 +13,6 @@
#include "QskGraduationMetrics.h"
#include "QskColorFilter.h"
#include "QskGradient.h"
#include "QskGradientStop.h"
#include "QskMargins.h"
#include "QskIntervalF.h"
#include "QskTextColors.h"
@ -44,7 +43,6 @@ static void qskRegisterInterpolator()
qRegisterAnimationInterpolator< QskColorFilter >( QskColorFilter::interpolate );
qRegisterAnimationInterpolator< QskIntervalF >( QskIntervalF::interpolate );
qRegisterAnimationInterpolator< QskMargins >( QskMargins::interpolate );
qRegisterAnimationInterpolator< QskGradientStop >( QskGradientStop::interpolate );
qRegisterAnimationInterpolator< QskGradient >( QskGradient::interpolate );
qRegisterAnimationInterpolator< QskBoxShapeMetrics >( QskBoxShapeMetrics::interpolate );
qRegisterAnimationInterpolator< QskBoxBorderMetrics >( QskBoxBorderMetrics::interpolate );

View File

@ -4,10 +4,11 @@
*****************************************************************************/
#include "QskArcNode.h"
#include "QskArcHints.h"
#include "QskArcMetrics.h"
#include "QskArcRenderNode.h"
#include "QskArcRenderer.h"
#include "QskMargins.h"
#include "QskGradient.h"
#include "QskSGNode.h"
#include "QskRgbValue.h"
@ -57,21 +58,24 @@ QskArcNode::~QskArcNode()
{
}
void QskArcNode::setArcData( const QRectF& rect, const QskArcHints& hints )
void QskArcNode::setArcData( const QRectF& rect,
const QskArcMetrics& arcMetrics, const QskGradient& gradient )
{
setArcData( rect, arcMetrics, 0.0, QColor(), gradient );
}
void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics,
const qreal borderWidth, const QColor& borderColor, const QskGradient& gradient )
{
using namespace QskSGNode;
QskArcRenderNode* arcNode = nullptr;
QskArcRenderNode* fillNode = nullptr;
if ( !rect.isEmpty() && hints.isVisible() )
if ( !( rect.isEmpty() || arcMetrics.isNull() ) )
{
const auto& gradient = hints.gradient;
const auto borderWidth = hints.borderWidth;
const auto borderColor = hints.borderColor;
const bool radial = false;
const auto metricsArc = hints.metrics.toAbsolute( rect.size() );
const auto metricsArc = arcMetrics.toAbsolute( rect.size() );
const auto hasFilling = gradient.isVisible();
const auto hasBorder = ( borderWidth > 0.0 ) && QskRgb::isVisible( borderColor );

View File

@ -9,7 +9,8 @@
#include "QskGlobal.h"
#include <qsgnode.h>
class QskArcHints;
class QskArcMetrics;
class QskGradient;
class QSK_EXPORT QskArcNode : public QSGNode
{
@ -17,7 +18,10 @@ class QSK_EXPORT QskArcNode : public QSGNode
QskArcNode();
~QskArcNode() override;
void setArcData( const QRectF&, const QskArcHints& );
void setArcData( const QRectF&, const QskArcMetrics&, const QskGradient& );
void setArcData( const QRectF&, const QskArcMetrics&,
qreal borderWidth, const QColor& borderColor, const QskGradient& );
};
#endif

View File

@ -8,8 +8,12 @@
#include "QskBoxRectangleNode.h"
#include "QskSGNode.h"
#include "QskBoxHints.h"
#include "QskGradient.h"
#include "QskGradientDirection.h"
#include "QskShadowMetrics.h"
#include "QskBoxBorderMetrics.h"
#include "QskBoxBorderColors.h"
#include "QskBoxShapeMetrics.h"
#include "QskRgbValue.h"
namespace
@ -56,8 +60,10 @@ QskBoxNode::~QskBoxNode()
{
}
void QskBoxNode::updateNode( const QQuickWindow* window,
const QRectF& rect, const QskBoxHints& hints )
void QskBoxNode::updateNode( const QQuickWindow* window, const QRectF& rect,
const QskBoxShapeMetrics& shapeMetrics, const QskBoxBorderMetrics& borderMetrics,
const QskBoxBorderColors& borderColors, const QskGradient& gradient,
const QskShadowMetrics& shadowMetrics, const QColor& shadowColor )
{
using namespace QskSGNode;
@ -68,13 +74,6 @@ void QskBoxNode::updateNode( const QQuickWindow* window,
if ( !rect.isEmpty() )
{
const auto& shapeMetrics = hints.shape;
const auto& borderMetrics = hints.borderMetrics;
const auto& borderColors = hints.borderColors;
const auto& gradient = hints.gradient;
const auto& shadowMetrics = hints.shadowMetrics;
const auto& shadowColor = hints.shadowColor;
const auto hasFilling = gradient.isVisible();
const auto hasBorder = !borderMetrics.isNull() && borderColors.isVisible();
const auto hasShadow = !shadowMetrics.isNull() && QskRgb::isVisible( shadowColor );

View File

@ -9,8 +9,14 @@
#include "QskGlobal.h"
#include <qsgnode.h>
class QskBoxHints;
class QskShadowMetrics;
class QskBoxShapeMetrics;
class QskBoxBorderMetrics;
class QskBoxBorderColors;
class QskGradient;
class QskShadowMetrics;
class QQuickWindow;
class QColor;
class QSK_EXPORT QskBoxNode : public QSGNode
{
@ -18,7 +24,10 @@ class QSK_EXPORT QskBoxNode : public QSGNode
QskBoxNode();
~QskBoxNode() override;
void updateNode( const QQuickWindow*, const QRectF&, const QskBoxHints& );
void updateNode( const QQuickWindow*, const QRectF&,
const QskBoxShapeMetrics&, const QskBoxBorderMetrics&,
const QskBoxBorderColors&, const QskGradient&,
const QskShadowMetrics&, const QColor& shadowColor );
};
#endif

View File

@ -54,16 +54,16 @@ namespace
}
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
// make Qt 5/6 APIs matching
QSGMaterialShader* createShader(
QSGRendererInterface::RenderMode ) const override final
#else
QSGMaterialShader* createShader() const override final
#endif
{
return createMaterialShader();
return createShader();
}
virtual QSGMaterialShader* createMaterialShader() const = 0;
virtual QSGMaterialShader* createShader() const = 0;
#endif
virtual bool setGradient( const QskGradient& ) = 0;
};
@ -217,7 +217,7 @@ namespace
return GradientMaterial::compare( other );
}
QSGMaterialShader* createMaterialShader() const override;
QSGMaterialShader* createShader() const override;
/*
xy: position
@ -299,7 +299,7 @@ namespace
};
#endif
QSGMaterialShader* LinearMaterial::createMaterialShader() const
QSGMaterialShader* LinearMaterial::createShader() const
{
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
if ( !( flags() & QSGMaterial::RhiShaderWanted ) )
@ -371,7 +371,7 @@ namespace
}
}
QSGMaterialShader* createMaterialShader() const override;
QSGMaterialShader* createShader() const override;
QVector2D m_center;
QVector2D m_radius;
@ -465,7 +465,7 @@ namespace
};
#endif
QSGMaterialShader* RadialMaterial::createMaterialShader() const
QSGMaterialShader* RadialMaterial::createShader() const
{
#ifdef SHADER_GL
if ( !( flags() & QSGMaterial::RhiShaderWanted ) )
@ -575,7 +575,7 @@ namespace
return GradientMaterial::compare( other );
}
QSGMaterialShader* createMaterialShader() const override;
QSGMaterialShader* createShader() const override;
QVector2D m_center;
float m_aspectRatio = 1.0;
@ -685,7 +685,7 @@ namespace
};
#endif
QSGMaterialShader* ConicMaterial::createMaterialShader() const
QSGMaterialShader* ConicMaterial::createShader() const
{
#ifdef SHADER_GL
if ( !( flags() & QSGMaterial::RhiShaderWanted ) )