progress bars: Introduce progress ring and refactor
Most of the code between rings and bars can be shared with a common superclass QskProgressIndicator. Resolves #98
This commit is contained in:
parent
2d5db67e79
commit
ec61c11ab6
|
@ -4,13 +4,18 @@
|
|||
*****************************************************************************/
|
||||
|
||||
#include "ProgressBarPage.h"
|
||||
#include <QskProgressBar.h>
|
||||
|
||||
#include <QskAnimator.h>
|
||||
#include <QskGraphicProvider.h>
|
||||
#include <QskGraphic.h>
|
||||
#include <QskGradient.h>
|
||||
#include <QskHctColor.h>
|
||||
#include <QskProgressBar.h>
|
||||
#include <QskProgressRing.h>
|
||||
#include <QskRgbValue.h>
|
||||
|
||||
#include <QQuickWindow>
|
||||
|
||||
namespace
|
||||
{
|
||||
class ProgressBar : public QskProgressBar
|
||||
|
@ -35,9 +40,32 @@ namespace
|
|||
colors += hctColor.toned( 45 ).rgb();
|
||||
colors += hctColor.toned( 30 ).rgb();
|
||||
|
||||
setBarGradient( qskBuildGradientStops( colors, true ) );
|
||||
setFillGradient( qskBuildGradientStops( colors, true ) );
|
||||
}
|
||||
};
|
||||
|
||||
class DeterminateIndicatorsAnimator : public QskAnimator
|
||||
{
|
||||
public:
|
||||
DeterminateIndicatorsAnimator( const QVector< QskProgressIndicator* >& indicators )
|
||||
: QskAnimator()
|
||||
, m_indicators( indicators )
|
||||
{
|
||||
setAutoRepeat( true );
|
||||
setDuration( 3000 );
|
||||
}
|
||||
|
||||
void advance( qreal value ) override
|
||||
{
|
||||
for( auto* indicator : m_indicators )
|
||||
{
|
||||
indicator->setValueAsRatio( value );
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const QVector< QskProgressIndicator* > m_indicators;
|
||||
};
|
||||
}
|
||||
|
||||
ProgressBarPage::ProgressBarPage( QQuickItem* parent )
|
||||
|
@ -53,10 +81,7 @@ void ProgressBarPage::populate()
|
|||
hBox->setSizePolicy( Qt::Horizontal, QskSizePolicy::Fixed );
|
||||
hBox->setSpacing( 20 );
|
||||
|
||||
{
|
||||
auto bar = new ProgressBar( hBox );
|
||||
bar->setValue( 35 );
|
||||
}
|
||||
QVector< QskProgressIndicator* > determinateIndicators;
|
||||
|
||||
{
|
||||
auto bar = new ProgressBar( hBox );
|
||||
|
@ -77,6 +102,11 @@ void ProgressBarPage::populate()
|
|||
bar->setValue( 25 );
|
||||
}
|
||||
|
||||
{
|
||||
auto bar = new ProgressBar( hBox );
|
||||
determinateIndicators.append( bar );
|
||||
}
|
||||
|
||||
{
|
||||
auto bar = new ProgressBar( hBox );
|
||||
bar->setIndeterminate( true );
|
||||
|
@ -106,8 +136,55 @@ void ProgressBarPage::populate()
|
|||
bar->setValue( 10 );
|
||||
}
|
||||
|
||||
{
|
||||
auto bar = new ProgressBar( vBox );
|
||||
determinateIndicators.append( bar );
|
||||
}
|
||||
|
||||
{
|
||||
auto bar = new ProgressBar( vBox );
|
||||
bar->setIndeterminate( true );
|
||||
}
|
||||
|
||||
const auto sizes = { QskProgressRing::SmallSize, QskProgressRing::NormalSize,
|
||||
QskProgressRing::LargeSize };
|
||||
|
||||
auto determinateRingsHBox = new QskLinearBox( Qt::Horizontal, vBox );
|
||||
|
||||
auto indeterminateRingsHBox = new QskLinearBox( Qt::Horizontal, vBox );
|
||||
|
||||
for( const auto size : sizes )
|
||||
{
|
||||
for( const auto indeterminate : { true, false } )
|
||||
{
|
||||
auto* ring = new QskProgressRing( determinateRingsHBox );
|
||||
ring->setSize( size );
|
||||
|
||||
QQuickItem* parentItem;
|
||||
|
||||
if( indeterminate )
|
||||
{
|
||||
parentItem = indeterminateRingsHBox;
|
||||
ring->setIndeterminate( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
parentItem = determinateRingsHBox;
|
||||
determinateIndicators.append( ring );
|
||||
}
|
||||
|
||||
ring->setParent( parentItem );
|
||||
ring->setParentItem( parentItem );
|
||||
}
|
||||
}
|
||||
|
||||
connect( this, &QskQuickItem::windowChanged, this, [this, determinateIndicators]( QQuickWindow* window )
|
||||
{
|
||||
if( window )
|
||||
{
|
||||
m_determinateIndicatorsAnimator.reset( new DeterminateIndicatorsAnimator( determinateIndicators ) );
|
||||
m_determinateIndicatorsAnimator->setWindow( window );
|
||||
m_determinateIndicatorsAnimator->start();
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#include "Page.h"
|
||||
|
||||
class QskAnimator;
|
||||
|
||||
class ProgressBarPage : public Page
|
||||
{
|
||||
public:
|
||||
|
@ -14,4 +16,6 @@ class ProgressBarPage : public Page
|
|||
|
||||
private:
|
||||
void populate();
|
||||
|
||||
std::unique_ptr< QskAnimator > m_determinateIndicatorsAnimator;
|
||||
};
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include <QskBoxShapeMetrics.h>
|
||||
#include <QskColorFilter.h>
|
||||
#include <QskFunctions.h>
|
||||
#include <QskProgressBar.h>
|
||||
#include <QskShadowMetrics.h>
|
||||
#include <QskSkinHintTableEditor.h>
|
||||
#include <QskStateCombination.h>
|
||||
|
|
|
@ -5,9 +5,6 @@
|
|||
|
||||
#include "StoragePage.h"
|
||||
#include "Box.h"
|
||||
#include "CircularProgressBar.h"
|
||||
#include "Diagram.h"
|
||||
#include "EnergyMeter.h"
|
||||
#include "StorageBar.h"
|
||||
#include "StorageMeter.h"
|
||||
#include <QTimer>
|
||||
|
@ -17,7 +14,6 @@
|
|||
#include <QskGradient.h>
|
||||
#include <QskGradientStop.h>
|
||||
#include <QskGraphicLabel.h>
|
||||
#include <QskProgressBar.h>
|
||||
#include <QskPushButton.h>
|
||||
#include <QskSkin.h>
|
||||
#include <QskStackBox.h>
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <QskPlacementPolicy.h>
|
||||
#include <QskPopup.h>
|
||||
#include <QskProgressBar.h>
|
||||
#include <QskProgressRing.h>
|
||||
#include <QskPushButton.h>
|
||||
#include <QskRadioBox.h>
|
||||
#include <QskScrollArea.h>
|
||||
|
@ -220,6 +221,7 @@ void QskQml::registerTypes()
|
|||
registerObject< QskFocusIndicator >();
|
||||
registerObject< QskSeparator >();
|
||||
registerObject< QskProgressBar >();
|
||||
registerObject< QskProgressRing >();
|
||||
registerObject< QskPushButton >();
|
||||
registerObject< QskScrollView >();
|
||||
registerObject< QskScrollArea >();
|
||||
|
|
|
@ -80,6 +80,7 @@
|
|||
#include <QskPageIndicator.h>
|
||||
#include <QskPushButton.h>
|
||||
#include <QskProgressBar.h>
|
||||
#include <QskProgressRing.h>
|
||||
#include <QskRadioBox.h>
|
||||
#include <QskScrollView.h>
|
||||
#include <QskSegmentedBar.h>
|
||||
|
@ -212,6 +213,9 @@ namespace
|
|||
void setupProgressBarMetrics();
|
||||
void setupProgressBarColors( QskAspect::Section, const QskFluent2Theme& );
|
||||
|
||||
void setupProgressRingMetrics();
|
||||
void setupProgressRingColors( QskAspect::Section, const QskFluent2Theme& );
|
||||
|
||||
void setupPushButtonMetrics();
|
||||
void setupPushButtonColors( QskAspect::Section, const QskFluent2Theme& );
|
||||
|
||||
|
@ -291,6 +295,7 @@ void Editor::setupMetrics()
|
|||
setupMenuMetrics();
|
||||
setupPageIndicatorMetrics();
|
||||
setupProgressBarMetrics();
|
||||
setupProgressRingMetrics();
|
||||
setupPushButtonMetrics();
|
||||
setupRadioBoxMetrics();
|
||||
setupScrollViewMetrics();
|
||||
|
@ -327,6 +332,7 @@ void Editor::setupColors( QskAspect::Section section, const QskFluent2Theme& the
|
|||
setupMenuColors( section, theme );
|
||||
setupPageIndicatorColors( section, theme );
|
||||
setupProgressBarColors( section, theme );
|
||||
setupProgressRingColors( section, theme );
|
||||
setupPushButtonColors( section, theme );
|
||||
setupRadioBoxColors( section, theme );
|
||||
setupScrollViewColors( section, theme );
|
||||
|
@ -839,8 +845,8 @@ void Editor::setupProgressBarMetrics()
|
|||
setMetric( Q::Groove | A::Size, 1 );
|
||||
setBoxShape( Q::Groove, 100, Qt::RelativeSize );
|
||||
|
||||
setMetric( Q::Bar | A::Size, 3 );
|
||||
setBoxShape( Q::Bar, 100, Qt::RelativeSize );
|
||||
setMetric( Q::Fill | A::Size, 3 );
|
||||
setBoxShape( Q::Fill, 100, Qt::RelativeSize );
|
||||
}
|
||||
|
||||
void Editor::setupProgressBarColors(
|
||||
|
@ -851,7 +857,36 @@ void Editor::setupProgressBarColors(
|
|||
const auto& pal = theme.palette;
|
||||
|
||||
setGradient( Q::Groove | section, pal.strokeColor.controlStrong.defaultColor );
|
||||
setGradient( Q::Bar | section, pal.fillColor.accent.defaultColor );
|
||||
setGradient( Q::Fill | section, pal.fillColor.accent.defaultColor );
|
||||
}
|
||||
|
||||
void Editor::setupProgressRingMetrics()
|
||||
{
|
||||
using Q = QskProgressRing;
|
||||
using A = QskAspect;
|
||||
|
||||
static constexpr QskAspect::Variation SmallSize = A::Small;
|
||||
static constexpr QskAspect::Variation NormalSize = A::NoVariation;
|
||||
static constexpr QskAspect::Variation LargeSize = A::Large;
|
||||
|
||||
setStrutSize( Q::Fill | SmallSize, { 16, 16 } );
|
||||
setStrutSize( Q::Fill | NormalSize, { 32, 32 } );
|
||||
setStrutSize( Q::Fill | LargeSize, { 64, 64 } );
|
||||
|
||||
const auto startAngle = 90, spanAngle = -360;
|
||||
setArcMetrics( Q::Fill | SmallSize, startAngle, spanAngle, 1.5 );
|
||||
setArcMetrics( Q::Fill | NormalSize, startAngle, spanAngle, 3 );
|
||||
setArcMetrics( Q::Fill | LargeSize, startAngle, spanAngle, 6 );
|
||||
}
|
||||
|
||||
void Editor::setupProgressRingColors(
|
||||
QskAspect::Section section, const QskFluent2Theme& theme )
|
||||
{
|
||||
using Q = QskProgressRing;
|
||||
|
||||
const auto& pal = theme.palette;
|
||||
|
||||
setGradient( Q::Fill | section, pal.fillColor.accent.defaultColor );
|
||||
}
|
||||
|
||||
void Editor::setupPushButtonMetrics()
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <QskPageIndicator.h>
|
||||
#include <QskPushButton.h>
|
||||
#include <QskProgressBar.h>
|
||||
#include <QskProgressRing.h>
|
||||
#include <QskRadioBox.h>
|
||||
#include <QskScrollView.h>
|
||||
#include <QskSegmentedBar.h>
|
||||
|
@ -94,6 +95,7 @@ namespace
|
|||
void setupPageIndicator();
|
||||
void setupPopup();
|
||||
void setupProgressBar();
|
||||
void setupProgressRing();
|
||||
void setupRadioBox();
|
||||
void setupPushButton();
|
||||
void setupScrollView();
|
||||
|
@ -161,6 +163,7 @@ void Editor::setup()
|
|||
setupPageIndicator();
|
||||
setupPopup();
|
||||
setupProgressBar();
|
||||
setupProgressRing();
|
||||
setupPushButton();
|
||||
setupRadioBox();
|
||||
setupScrollView();
|
||||
|
@ -431,9 +434,9 @@ void Editor::setupProgressBar()
|
|||
using A = QskAspect;
|
||||
using Q = QskProgressBar;
|
||||
|
||||
auto size = 5_dp;
|
||||
auto size = 4_dp;
|
||||
|
||||
for ( auto subControl : { Q::Groove, Q::Bar } )
|
||||
for ( auto subControl : { Q::Groove, Q::Fill } )
|
||||
{
|
||||
setMetric( subControl | A::Size, size );
|
||||
setPadding( subControl, 0 );
|
||||
|
@ -443,12 +446,21 @@ void Editor::setupProgressBar()
|
|||
}
|
||||
|
||||
setMetric( Q::Groove | A::Size, size );
|
||||
setGradient( Q::Groove, m_pal.primaryContainer );
|
||||
setGradient( Q::Groove, m_pal.surfaceContainerHighest );
|
||||
|
||||
setGradient( Q::Groove | Q::Disabled, m_pal.onSurface12 );
|
||||
|
||||
setGradient( Q::Bar, m_pal.primary );
|
||||
setGradient( Q::Bar | Q::Disabled, m_pal.onSurface38 );
|
||||
setGradient( Q::Fill, m_pal.primary );
|
||||
setGradient( Q::Fill | Q::Disabled, m_pal.onSurface38 );
|
||||
}
|
||||
|
||||
void Editor::setupProgressRing()
|
||||
{
|
||||
using Q = QskProgressRing;
|
||||
|
||||
setStrutSize( Q::Fill, { 48_dp, 48_dp } );
|
||||
setGradient( Q::Fill, m_pal.primary );
|
||||
setArcMetrics( Q::Fill, 90, -360, 4_dp );
|
||||
}
|
||||
|
||||
void Editor::setupRadioBox()
|
||||
|
@ -1302,6 +1314,8 @@ QskMaterial3Theme::QskMaterial3Theme( QskSkin::ColorScheme colorScheme,
|
|||
outline = m_palettes[ NeutralVariant ].toned( 50 ).rgb();
|
||||
outlineVariant = m_palettes[ NeutralVariant ].toned( 80 ).rgb();
|
||||
|
||||
surfaceContainerHighest = m_palettes[ NeutralVariant ].toned( 90 ).rgb();
|
||||
|
||||
shadow = m_palettes[ Neutral ].toned( 0 ).rgb();
|
||||
}
|
||||
else if ( colorScheme == QskSkin::DarkScheme )
|
||||
|
@ -1336,6 +1350,8 @@ QskMaterial3Theme::QskMaterial3Theme( QskSkin::ColorScheme colorScheme,
|
|||
outline = m_palettes[ NeutralVariant ].toned( 60 ).rgb();
|
||||
outlineVariant = m_palettes[ NeutralVariant ].toned( 30 ).rgb();
|
||||
|
||||
surfaceContainerHighest = m_palettes[ NeutralVariant ].toned( 22 ).rgb();
|
||||
|
||||
shadow = m_palettes[ Neutral ].toned( 0 ).rgb();
|
||||
}
|
||||
|
||||
|
|
|
@ -79,6 +79,8 @@ class QSK_MATERIAL3_EXPORT QskMaterial3Theme
|
|||
QRgb outline;
|
||||
QRgb outlineVariant;
|
||||
|
||||
QRgb surfaceContainerHighest;
|
||||
|
||||
QRgb shadow;
|
||||
|
||||
QskShadowMetrics elevation0;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <QskPageIndicator.h>
|
||||
#include <QskPopup.h>
|
||||
#include <QskProgressBar.h>
|
||||
#include <QskProgressRing.h>
|
||||
#include <QskPushButton.h>
|
||||
#include <QskRadioBox.h>
|
||||
#include <QskScrollView.h>
|
||||
|
@ -162,6 +163,7 @@ namespace
|
|||
void setupPageIndicator();
|
||||
void setupPopup();
|
||||
void setupProgressBar();
|
||||
void setupProgressRing();
|
||||
void setupPushButton();
|
||||
void setupRadioBox();
|
||||
void setupScrollView();
|
||||
|
@ -287,6 +289,7 @@ void Editor::setup()
|
|||
setupPageIndicator();
|
||||
setupPopup();
|
||||
setupProgressBar();
|
||||
setupProgressRing();
|
||||
setupPushButton();
|
||||
setupRadioBox();
|
||||
setupScrollView();
|
||||
|
@ -521,15 +524,35 @@ void Editor::setupProgressBar()
|
|||
using A = QskAspect;
|
||||
using Q = QskProgressBar;
|
||||
|
||||
for ( auto subControl : { Q::Groove, Q::Bar } )
|
||||
for ( auto subControl : { Q::Groove, Q::Fill } )
|
||||
{
|
||||
setMetric( subControl | A::Size, 6 );
|
||||
setPadding( subControl, 0 );
|
||||
setBoxShape( subControl, 4 );
|
||||
}
|
||||
|
||||
setGradient( Q::Groove, m_pal.darker200 );
|
||||
setGradient( Q::Bar, m_pal.highlighted );
|
||||
setGradient( Q::Groove, m_pal.lighter110 );
|
||||
setGradient( Q::Fill, m_pal.highlighted );
|
||||
}
|
||||
|
||||
void Editor::setupProgressRing()
|
||||
{
|
||||
using A = QskAspect;
|
||||
using Q = QskProgressRing;
|
||||
|
||||
for ( auto subControl : { Q::Groove, Q::Fill } )
|
||||
{
|
||||
setMetric( subControl | A::Size, 6 );
|
||||
setPadding( subControl, 0 );
|
||||
setBoxShape( subControl, 4 );
|
||||
}
|
||||
|
||||
setArcMetrics( Q::Groove, 90, -360, 6 );
|
||||
setGradient( Q::Groove, m_pal.lighter110 );
|
||||
|
||||
setStrutSize( Q::Fill, { 60, 60 } );
|
||||
setGradient( Q::Fill, m_pal.highlighted );
|
||||
setArcMetrics( Q::Fill, 90, -360, 6 );
|
||||
}
|
||||
|
||||
void Editor::setupFocusIndicator()
|
||||
|
|
|
@ -196,10 +196,14 @@ list(APPEND HEADERS
|
|||
controls/QskPanGestureRecognizer.h
|
||||
controls/QskPopup.h
|
||||
controls/QskPopupSkinlet.h
|
||||
controls/QskPushButton.h
|
||||
controls/QskPushButtonSkinlet.h
|
||||
controls/QskProgressBar.h
|
||||
controls/QskProgressBarSkinlet.h
|
||||
controls/QskProgressIndicator.h
|
||||
controls/QskProgressIndicatorSkinlet.h
|
||||
controls/QskProgressRing.h
|
||||
controls/QskProgressRingSkinlet.h
|
||||
controls/QskPushButton.h
|
||||
controls/QskPushButtonSkinlet.h
|
||||
controls/QskQuick.h
|
||||
controls/QskQuickItem.h
|
||||
controls/QskRadioBox.h
|
||||
|
@ -294,10 +298,14 @@ list(APPEND SOURCES
|
|||
controls/QskPanGestureRecognizer.cpp
|
||||
controls/QskPopup.cpp
|
||||
controls/QskPopupSkinlet.cpp
|
||||
controls/QskPushButton.cpp
|
||||
controls/QskPushButtonSkinlet.cpp
|
||||
controls/QskProgressBar.cpp
|
||||
controls/QskProgressBarSkinlet.cpp
|
||||
controls/QskProgressIndicator.cpp
|
||||
controls/QskProgressIndicatorSkinlet.cpp
|
||||
controls/QskProgressRing.cpp
|
||||
controls/QskProgressRingSkinlet.cpp
|
||||
controls/QskPushButton.cpp
|
||||
controls/QskPushButtonSkinlet.cpp
|
||||
controls/QskQuick.cpp
|
||||
controls/QskQuickItem.cpp
|
||||
controls/QskQuickItemPrivate.cpp
|
||||
|
|
|
@ -6,91 +6,30 @@
|
|||
#include "QskProgressBar.h"
|
||||
|
||||
#include "QskIntervalF.h"
|
||||
#include "QskFunctions.h"
|
||||
#include "QskAnimator.h"
|
||||
#include "QskAspect.h"
|
||||
|
||||
QSK_SUBCONTROL( QskProgressBar, Groove )
|
||||
QSK_SUBCONTROL( QskProgressBar, Bar )
|
||||
|
||||
namespace
|
||||
{
|
||||
class PositionAnimator : public QskAnimator
|
||||
{
|
||||
public:
|
||||
PositionAnimator( QskProgressBar* progressBar )
|
||||
: m_progressBar( progressBar )
|
||||
{
|
||||
setAutoRepeat( true );
|
||||
setDuration( 1300 );
|
||||
|
||||
setWindow( progressBar->window() );
|
||||
}
|
||||
|
||||
void advance( qreal value ) override
|
||||
{
|
||||
if ( m_progressBar->setPositionHint( QskProgressBar::Bar, value ) )
|
||||
m_progressBar->update();
|
||||
}
|
||||
|
||||
private:
|
||||
QskProgressBar* m_progressBar;
|
||||
};
|
||||
}
|
||||
QSK_SUBCONTROL( QskProgressBar, Fill )
|
||||
|
||||
class QskProgressBar::PrivateData
|
||||
{
|
||||
public:
|
||||
void updateIndeterminateAnimator( QskProgressBar* progressBar )
|
||||
{
|
||||
if ( !isIndeterminate )
|
||||
{
|
||||
delete animator;
|
||||
animator = nullptr;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( progressBar->window() && progressBar->isVisible() )
|
||||
{
|
||||
if ( animator == nullptr )
|
||||
animator = new PositionAnimator( progressBar );
|
||||
|
||||
animator->start();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( animator )
|
||||
animator->stop();
|
||||
}
|
||||
}
|
||||
|
||||
PositionAnimator* animator = nullptr;
|
||||
|
||||
qreal value = 0.0;
|
||||
qreal origin = 0.0;
|
||||
|
||||
bool hasOrigin = false;
|
||||
bool isIndeterminate = false;
|
||||
|
||||
Qt::Orientation orientation;
|
||||
};
|
||||
|
||||
QskProgressBar::QskProgressBar( Qt::Orientation orientation,
|
||||
qreal min, qreal max, QQuickItem* parent )
|
||||
: QskBoundedControl( min, max, parent )
|
||||
: Inherited( min, max, parent )
|
||||
, m_data( new PrivateData )
|
||||
{
|
||||
m_data->orientation = orientation;
|
||||
m_data->value = minimum();
|
||||
|
||||
if ( orientation == Qt::Horizontal )
|
||||
initSizePolicy( QskSizePolicy::MinimumExpanding, QskSizePolicy::Fixed );
|
||||
else
|
||||
initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::MinimumExpanding );
|
||||
|
||||
connect( this, &QskBoundedControl::boundariesChanged,
|
||||
this, &QskProgressBar::adjustValue );
|
||||
setSubcontrolProxy( Inherited::Groove, Groove );
|
||||
setSubcontrolProxy( Inherited::Fill, Fill );
|
||||
}
|
||||
|
||||
QskProgressBar::QskProgressBar( Qt::Orientation orientation, QQuickItem* parent )
|
||||
|
@ -115,7 +54,12 @@ QskProgressBar::QskProgressBar( QQuickItem* parent )
|
|||
|
||||
QskProgressBar::~QskProgressBar()
|
||||
{
|
||||
delete m_data->animator;
|
||||
}
|
||||
|
||||
QskAspect::Variation QskProgressBar::effectiveVariation() const
|
||||
{
|
||||
// so you can define different hints depending on the orientation
|
||||
return static_cast< QskAspect::Variation >( m_data->orientation );
|
||||
}
|
||||
|
||||
Qt::Orientation QskProgressBar::orientation() const
|
||||
|
@ -137,163 +81,4 @@ void QskProgressBar::setOrientation( Qt::Orientation orientation )
|
|||
}
|
||||
}
|
||||
|
||||
bool QskProgressBar::isIndeterminate() const
|
||||
{
|
||||
return m_data->isIndeterminate;
|
||||
}
|
||||
|
||||
void QskProgressBar::setIndeterminate( bool on )
|
||||
{
|
||||
if ( on == m_data->isIndeterminate )
|
||||
return;
|
||||
|
||||
m_data->isIndeterminate = on;
|
||||
m_data->updateIndeterminateAnimator( this );
|
||||
|
||||
update();
|
||||
Q_EMIT indeterminateChanged( on );
|
||||
}
|
||||
|
||||
QskAspect::Variation QskProgressBar::effectiveVariation() const
|
||||
{
|
||||
// so you can define different hints depending on the orientation
|
||||
return static_cast< QskAspect::Variation >( m_data->orientation );
|
||||
}
|
||||
|
||||
void QskProgressBar::setBarGradient( const QskGradient& gradient )
|
||||
{
|
||||
setGradientHint( Bar, gradient );
|
||||
}
|
||||
|
||||
void QskProgressBar::resetBarGradient()
|
||||
{
|
||||
resetColor( Bar );
|
||||
}
|
||||
|
||||
QskGradient QskProgressBar::barGradient() const
|
||||
{
|
||||
return gradientHint( QskProgressBar::Bar );
|
||||
}
|
||||
|
||||
void QskProgressBar::setExtent( qreal extent )
|
||||
{
|
||||
if ( extent < 0.0 )
|
||||
extent = 0.0;
|
||||
|
||||
if ( setMetric( Groove | QskAspect::Size, extent ) )
|
||||
Q_EMIT extentChanged( extent );
|
||||
}
|
||||
|
||||
void QskProgressBar::resetExtent()
|
||||
{
|
||||
if ( resetMetric( Groove | QskAspect::Size ) )
|
||||
Q_EMIT extentChanged( extent() );
|
||||
}
|
||||
|
||||
qreal QskProgressBar::extent() const
|
||||
{
|
||||
auto grooveSize = metric( Groove | QskAspect::Size );
|
||||
auto barSize = metric( Bar | QskAspect::Size );
|
||||
return qMax( grooveSize, barSize );
|
||||
}
|
||||
|
||||
void QskProgressBar::setOrigin( qreal origin )
|
||||
{
|
||||
if ( isComponentComplete() )
|
||||
origin = boundedValue( origin );
|
||||
|
||||
if( !m_data->hasOrigin || !qskFuzzyCompare( m_data->origin, origin ) )
|
||||
{
|
||||
m_data->hasOrigin = true;
|
||||
m_data->origin = origin;
|
||||
|
||||
update();
|
||||
Q_EMIT originChanged( origin );
|
||||
}
|
||||
}
|
||||
|
||||
void QskProgressBar::resetOrigin()
|
||||
{
|
||||
if ( m_data->hasOrigin )
|
||||
{
|
||||
m_data->hasOrigin = false;
|
||||
|
||||
update();
|
||||
Q_EMIT originChanged( origin() );
|
||||
}
|
||||
}
|
||||
|
||||
qreal QskProgressBar::origin() const
|
||||
{
|
||||
if ( m_data->hasOrigin )
|
||||
{
|
||||
return boundedValue( m_data->origin );
|
||||
}
|
||||
|
||||
return minimum();
|
||||
}
|
||||
|
||||
void QskProgressBar::setValue( qreal value )
|
||||
{
|
||||
if ( isComponentComplete() )
|
||||
value = boundedValue( value );
|
||||
|
||||
setValueInternal( value );
|
||||
}
|
||||
|
||||
qreal QskProgressBar::value() const
|
||||
{
|
||||
return m_data->value;
|
||||
}
|
||||
|
||||
void QskProgressBar::setValueAsRatio( qreal ratio )
|
||||
{
|
||||
ratio = qBound( 0.0, ratio, 1.0 );
|
||||
setValue( minimum() + ratio * boundaryLength() );
|
||||
}
|
||||
|
||||
qreal QskProgressBar::valueAsRatio() const
|
||||
{
|
||||
return valueAsRatio( m_data->value );
|
||||
}
|
||||
|
||||
void QskProgressBar::componentComplete()
|
||||
{
|
||||
Inherited::componentComplete();
|
||||
adjustValue();
|
||||
}
|
||||
|
||||
void QskProgressBar::adjustValue()
|
||||
{
|
||||
if ( isComponentComplete() )
|
||||
setValueInternal( boundedValue( m_data->value ) );
|
||||
}
|
||||
|
||||
void QskProgressBar::setValueInternal( qreal value )
|
||||
{
|
||||
if ( !qskFuzzyCompare( value, m_data->value ) )
|
||||
{
|
||||
m_data->value = value;
|
||||
Q_EMIT valueChanged( value );
|
||||
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void QskProgressBar::itemChange( QQuickItem::ItemChange change,
|
||||
const QQuickItem::ItemChangeData& value )
|
||||
{
|
||||
switch( static_cast< int >( change ) )
|
||||
{
|
||||
case QQuickItem::ItemVisibleHasChanged:
|
||||
case QQuickItem::ItemSceneChange:
|
||||
{
|
||||
m_data->updateIndeterminateAnimator( this );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Inherited::itemChange( change, value );
|
||||
}
|
||||
|
||||
#include "moc_QskProgressBar.cpp"
|
||||
|
|
|
@ -6,34 +6,19 @@
|
|||
#ifndef QSK_PROGRESS_BAR_H
|
||||
#define QSK_PROGRESS_BAR_H
|
||||
|
||||
#include "QskBoundedControl.h"
|
||||
#include "QskProgressIndicator.h"
|
||||
|
||||
class QskIntervalF;
|
||||
|
||||
class QSK_EXPORT QskProgressBar : public QskBoundedControl
|
||||
class QSK_EXPORT QskProgressBar : public QskProgressIndicator
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY( Qt::Orientation orientation READ orientation
|
||||
WRITE setOrientation NOTIFY orientationChanged )
|
||||
|
||||
Q_PROPERTY( qreal extent READ extent
|
||||
WRITE setExtent RESET resetExtent NOTIFY extentChanged )
|
||||
|
||||
Q_PROPERTY( bool indeterminate READ isIndeterminate
|
||||
WRITE setIndeterminate NOTIFY indeterminateChanged )
|
||||
|
||||
Q_PROPERTY( qreal origin READ origin
|
||||
WRITE setOrigin RESET resetOrigin NOTIFY originChanged )
|
||||
|
||||
Q_PROPERTY( qreal value READ value WRITE setValue NOTIFY valueChanged )
|
||||
Q_PROPERTY( qreal valueAsRatio READ valueAsRatio
|
||||
WRITE setValueAsRatio NOTIFY valueChanged )
|
||||
|
||||
using Inherited = QskBoundedControl;
|
||||
using Inherited = QskProgressIndicator;
|
||||
|
||||
public:
|
||||
QSK_SUBCONTROLS( Groove, Bar )
|
||||
QSK_SUBCONTROLS( Groove, Fill )
|
||||
|
||||
QskProgressBar( Qt::Orientation, QQuickItem* parent = nullptr );
|
||||
QskProgressBar( Qt::Orientation, qreal min, qreal max, QQuickItem* parent = nullptr );
|
||||
|
@ -43,50 +28,15 @@ class QSK_EXPORT QskProgressBar : public QskBoundedControl
|
|||
|
||||
~QskProgressBar() override;
|
||||
|
||||
QskAspect::Variation effectiveVariation() const override;
|
||||
|
||||
Qt::Orientation orientation() const;
|
||||
void setOrientation( Qt::Orientation orientation );
|
||||
|
||||
bool isIndeterminate() const;
|
||||
void setIndeterminate( bool on = true );
|
||||
|
||||
QskAspect::Variation effectiveVariation() const override;
|
||||
|
||||
void setBarGradient( const QskGradient& );
|
||||
void resetBarGradient();
|
||||
QskGradient barGradient() const;
|
||||
|
||||
void setExtent( qreal );
|
||||
void resetExtent();
|
||||
qreal extent() const;
|
||||
|
||||
void resetOrigin();
|
||||
qreal origin() const;
|
||||
|
||||
qreal value() const;
|
||||
qreal valueAsRatio() const; // [0.0, 1.0]
|
||||
using QskBoundedControl::valueAsRatio;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setValue( qreal );
|
||||
void setValueAsRatio( qreal );
|
||||
void setOrigin( qreal );
|
||||
|
||||
Q_SIGNALS:
|
||||
void orientationChanged( Qt::Orientation );
|
||||
void extentChanged( qreal );
|
||||
void indeterminateChanged( bool );
|
||||
void valueChanged( qreal );
|
||||
void originChanged( qreal );
|
||||
|
||||
protected:
|
||||
void componentComplete() override;
|
||||
void itemChange( ItemChange, const ItemChangeData& ) override;
|
||||
|
||||
private:
|
||||
void setValueInternal( qreal value );
|
||||
void adjustBoundaries( bool increasing );
|
||||
void adjustValue();
|
||||
|
||||
class PrivateData;
|
||||
std::unique_ptr< PrivateData > m_data;
|
||||
};
|
||||
|
|
|
@ -7,51 +7,54 @@
|
|||
#include "QskProgressBar.h"
|
||||
#include "QskIntervalF.h"
|
||||
#include "QskBoxBorderMetrics.h"
|
||||
#include "QskGradientDirection.h"
|
||||
|
||||
#include <qeasingcurve.h>
|
||||
#include <cmath>
|
||||
|
||||
static inline QskIntervalF qskBarInterval( const QskProgressBar* bar )
|
||||
using Q = QskProgressBar;
|
||||
|
||||
namespace
|
||||
{
|
||||
qreal pos1, pos2;
|
||||
|
||||
if ( bar->isIndeterminate() )
|
||||
QskIntervalF qskFillInterval( const Q* bar )
|
||||
{
|
||||
const auto pos = bar->positionHint( QskProgressBar::Bar );
|
||||
qreal pos1, pos2;
|
||||
|
||||
static const QEasingCurve curve( QEasingCurve::InOutCubic );
|
||||
|
||||
const qreal off = 0.15;
|
||||
|
||||
pos1 = curve.valueForProgress( qMax( pos - off, 0.0 ) );
|
||||
pos2 = curve.valueForProgress( qMin( pos + off, 1.0 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
pos1 = bar->valueAsRatio( bar->origin() );
|
||||
pos2 = bar->valueAsRatio( bar->value() );
|
||||
}
|
||||
|
||||
if( bar->orientation() == Qt::Horizontal )
|
||||
{
|
||||
if ( bar->layoutMirroring() )
|
||||
if ( bar->isIndeterminate() )
|
||||
{
|
||||
pos1 = 1.0 - pos1;
|
||||
pos2 = 1.0 - pos2;
|
||||
const auto pos = bar->positionHint( QskProgressIndicator::Fill );
|
||||
|
||||
static const QEasingCurve curve( QEasingCurve::InOutCubic );
|
||||
|
||||
const qreal off = 0.15;
|
||||
|
||||
pos1 = curve.valueForProgress( qMax( pos - off, 0.0 ) );
|
||||
pos2 = curve.valueForProgress( qMin( pos + off, 1.0 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
pos1 = bar->valueAsRatio( bar->origin() );
|
||||
pos2 = bar->valueAsRatio( bar->value() );
|
||||
}
|
||||
|
||||
if( bar->orientation() == Qt::Horizontal )
|
||||
{
|
||||
if ( bar->layoutMirroring() )
|
||||
{
|
||||
pos1 = 1.0 - pos1;
|
||||
pos2 = 1.0 - pos2;
|
||||
}
|
||||
}
|
||||
|
||||
if ( pos1 > pos2 )
|
||||
std::swap( pos1, pos2 );
|
||||
|
||||
return QskIntervalF( pos1, pos2 );
|
||||
}
|
||||
|
||||
if ( pos1 > pos2 )
|
||||
std::swap( pos1, pos2 );
|
||||
|
||||
return QskIntervalF( pos1, pos2 );
|
||||
}
|
||||
|
||||
QskProgressBarSkinlet::QskProgressBarSkinlet( QskSkin* skin )
|
||||
: QskSkinlet( skin )
|
||||
: Inherited( skin )
|
||||
{
|
||||
setNodeRoles( { GrooveRole, BarRole } );
|
||||
}
|
||||
|
||||
QskProgressBarSkinlet::~QskProgressBarSkinlet()
|
||||
|
@ -62,7 +65,6 @@ QRectF QskProgressBarSkinlet::subControlRect(
|
|||
const QskSkinnable* skinnable, const QRectF& contentsRect,
|
||||
QskAspect::Subcontrol subControl ) const
|
||||
{
|
||||
using Q = QskProgressBar;
|
||||
const auto bar = static_cast< const Q* >( skinnable );
|
||||
|
||||
if( subControl == Q::Groove )
|
||||
|
@ -84,7 +86,7 @@ QRectF QskProgressBarSkinlet::subControlRect(
|
|||
return rect;
|
||||
}
|
||||
|
||||
if( subControl == Q::Bar )
|
||||
if( subControl == Q::Fill )
|
||||
{
|
||||
return barRect( bar );
|
||||
}
|
||||
|
@ -92,30 +94,18 @@ QRectF QskProgressBarSkinlet::subControlRect(
|
|||
return Inherited::subControlRect( skinnable, contentsRect, subControl );
|
||||
}
|
||||
|
||||
QSGNode* QskProgressBarSkinlet::updateSubNode(
|
||||
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
|
||||
QSGNode* QskProgressBarSkinlet::updateGrooveNode(
|
||||
const QskProgressIndicator* indicator, QSGNode* node ) const
|
||||
{
|
||||
switch( nodeRole )
|
||||
{
|
||||
case GrooveRole:
|
||||
{
|
||||
return updateBoxNode( skinnable, node, QskProgressBar::Groove );
|
||||
}
|
||||
|
||||
case BarRole:
|
||||
{
|
||||
const auto bar = static_cast< const QskProgressBar* >( skinnable );
|
||||
return updateBarNode( bar, node );
|
||||
}
|
||||
}
|
||||
|
||||
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
||||
return updateBoxNode( indicator, node, Q::Groove );
|
||||
}
|
||||
|
||||
QSGNode* QskProgressBarSkinlet::updateBarNode(
|
||||
const QskProgressBar* bar, QSGNode* node ) const
|
||||
QSGNode* QskProgressBarSkinlet::updateFillNode(
|
||||
const QskProgressIndicator* indicator, QSGNode* node ) const
|
||||
{
|
||||
const auto subControl = QskProgressBar::Bar;
|
||||
const auto bar = static_cast< const Q* >( indicator );
|
||||
|
||||
const auto subControl = Q::Fill;
|
||||
|
||||
const auto rect = bar->subControlRect( subControl );
|
||||
if ( rect.isEmpty() )
|
||||
|
@ -139,26 +129,27 @@ QSGNode* QskProgressBarSkinlet::updateBarNode(
|
|||
not supporting this yet. TODO ...
|
||||
*/
|
||||
|
||||
const auto intv = qskBarInterval( bar );
|
||||
const auto intv = qskFillInterval( bar );
|
||||
|
||||
const auto stops = qskExtractedGradientStops( gradient.stops(),
|
||||
intv.lowerBound(), intv.upperBound() );
|
||||
|
||||
gradient.setStops( stops );
|
||||
gradient.setLinearDirection( bar->orientation() );
|
||||
|
||||
gradient.setLinearDirection( static_cast< Qt::Orientation >( bar->orientation() ) );
|
||||
|
||||
if ( bar->orientation() == Qt::Vertical || bar->layoutMirroring() )
|
||||
gradient.reverse();
|
||||
}
|
||||
|
||||
return updateBoxNode( bar, node, rect, gradient, subControl );
|
||||
return updateBoxNode( indicator, node, rect, gradient, subControl );
|
||||
}
|
||||
|
||||
QRectF QskProgressBarSkinlet::barRect( const QskProgressBar* bar ) const
|
||||
QRectF QskProgressBarSkinlet::barRect( const Q* bar ) const
|
||||
{
|
||||
using Q = QskProgressBar;
|
||||
const auto subControl = Q::Groove;
|
||||
|
||||
const auto barSize = bar->metric( Q::Bar | QskAspect::Size );
|
||||
const auto barSize = bar->metric( Q::Fill | QskAspect::Size );
|
||||
auto rect = bar->subControlRect( subControl );
|
||||
|
||||
if ( bar->orientation() == Qt::Horizontal )
|
||||
|
@ -179,7 +170,7 @@ QRectF QskProgressBarSkinlet::barRect( const QskProgressBar* bar ) const
|
|||
|
||||
rect = rect.marginsRemoved( m );
|
||||
|
||||
const auto intv = qskBarInterval( bar );
|
||||
const auto intv = qskFillInterval( bar );
|
||||
|
||||
if( bar->orientation() == Qt::Horizontal )
|
||||
{
|
||||
|
@ -205,7 +196,7 @@ QSizeF QskProgressBarSkinlet::sizeHint( const QskSkinnable* skinnable,
|
|||
if ( which != Qt::PreferredSize )
|
||||
return QSizeF();
|
||||
|
||||
const auto bar = static_cast< const QskProgressBar* >( skinnable );
|
||||
const auto bar = static_cast< const Q* >( skinnable );
|
||||
|
||||
const auto extent = bar->extent();
|
||||
|
||||
|
|
|
@ -6,25 +6,17 @@
|
|||
#ifndef QSK_PROGRESS_BAR_SKINLET_H
|
||||
#define QSK_PROGRESS_BAR_SKINLET_H
|
||||
|
||||
#include "QskSkinlet.h"
|
||||
#include "QskProgressIndicatorSkinlet.h"
|
||||
|
||||
class QskProgressBar;
|
||||
|
||||
class QSK_EXPORT QskProgressBarSkinlet : public QskSkinlet
|
||||
class QSK_EXPORT QskProgressBarSkinlet : public QskProgressIndicatorSkinlet
|
||||
{
|
||||
Q_GADGET
|
||||
|
||||
using Inherited = QskSkinlet;
|
||||
using Inherited = QskProgressIndicatorSkinlet;
|
||||
|
||||
public:
|
||||
enum NodeRole
|
||||
{
|
||||
GrooveRole,
|
||||
BarRole,
|
||||
|
||||
RoleCount
|
||||
};
|
||||
|
||||
Q_INVOKABLE QskProgressBarSkinlet( QskSkin* = nullptr );
|
||||
~QskProgressBarSkinlet() override;
|
||||
|
||||
|
@ -35,11 +27,10 @@ class QSK_EXPORT QskProgressBarSkinlet : public QskSkinlet
|
|||
Qt::SizeHint, const QSizeF& ) const override;
|
||||
|
||||
protected:
|
||||
QSGNode* updateSubNode( const QskSkinnable*,
|
||||
quint8 nodeRole, QSGNode* ) const override;
|
||||
QSGNode* updateGrooveNode( const QskProgressIndicator*, QSGNode* ) const override;
|
||||
QSGNode* updateFillNode( const QskProgressIndicator*, QSGNode* ) const override;
|
||||
|
||||
private:
|
||||
QSGNode* updateBarNode( const QskProgressBar*, QSGNode* ) const;
|
||||
QRectF barRect( const QskProgressBar* ) const;
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,255 @@
|
|||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#include "QskProgressIndicator.h"
|
||||
|
||||
#include "QskIntervalF.h"
|
||||
#include "QskFunctions.h"
|
||||
#include "QskAnimator.h"
|
||||
#include "QskAspect.h"
|
||||
|
||||
QSK_SUBCONTROL( QskProgressIndicator, Groove )
|
||||
QSK_SUBCONTROL( QskProgressIndicator, Fill )
|
||||
|
||||
namespace
|
||||
{
|
||||
class PositionAnimator : public QskAnimator
|
||||
{
|
||||
public:
|
||||
PositionAnimator( QskProgressIndicator* indicator )
|
||||
: m_indicator( indicator )
|
||||
{
|
||||
setAutoRepeat( true );
|
||||
setDuration( 1300 );
|
||||
|
||||
setWindow( indicator->window() );
|
||||
}
|
||||
|
||||
void advance( qreal value ) override
|
||||
{
|
||||
if ( m_indicator->setPositionHint( QskProgressIndicator::Fill, value ) )
|
||||
m_indicator->update();
|
||||
}
|
||||
|
||||
private:
|
||||
QskProgressIndicator* m_indicator;
|
||||
};
|
||||
}
|
||||
|
||||
class QskProgressIndicator::PrivateData
|
||||
{
|
||||
public:
|
||||
void updateIndeterminateAnimator( QskProgressIndicator* indicator )
|
||||
{
|
||||
if ( !isIndeterminate )
|
||||
{
|
||||
delete animator;
|
||||
animator = nullptr;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( indicator->window() && indicator->isVisible() )
|
||||
{
|
||||
if ( animator == nullptr )
|
||||
animator = new PositionAnimator( indicator );
|
||||
|
||||
animator->start();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( animator )
|
||||
animator->stop();
|
||||
}
|
||||
}
|
||||
|
||||
PositionAnimator* animator = nullptr;
|
||||
|
||||
qreal value = 0.0;
|
||||
qreal origin = 0.0;
|
||||
|
||||
bool hasOrigin = false;
|
||||
bool isIndeterminate = false;
|
||||
};
|
||||
|
||||
QskProgressIndicator::QskProgressIndicator( qreal min, qreal max, QQuickItem* parent )
|
||||
: QskBoundedControl( min, max, parent )
|
||||
, m_data( new PrivateData )
|
||||
{
|
||||
m_data->value = minimum();
|
||||
|
||||
connect( this, &QskBoundedControl::boundariesChanged,
|
||||
this, &QskProgressIndicator::adjustValue );
|
||||
}
|
||||
|
||||
QskProgressIndicator::QskProgressIndicator( QQuickItem* parent )
|
||||
: QskProgressIndicator( 0.0, 100.0, parent )
|
||||
{
|
||||
}
|
||||
|
||||
QskProgressIndicator::QskProgressIndicator( const QskIntervalF& boundaries, QQuickItem* parent )
|
||||
: QskProgressIndicator( boundaries.lowerBound(), boundaries.upperBound(), parent )
|
||||
{
|
||||
}
|
||||
|
||||
QskProgressIndicator::~QskProgressIndicator()
|
||||
{
|
||||
delete m_data->animator;
|
||||
}
|
||||
|
||||
bool QskProgressIndicator::isIndeterminate() const
|
||||
{
|
||||
return m_data->isIndeterminate;
|
||||
}
|
||||
|
||||
void QskProgressIndicator::setIndeterminate( bool on )
|
||||
{
|
||||
if ( on == m_data->isIndeterminate )
|
||||
return;
|
||||
|
||||
m_data->isIndeterminate = on;
|
||||
m_data->updateIndeterminateAnimator( this );
|
||||
|
||||
update();
|
||||
Q_EMIT indeterminateChanged( on );
|
||||
}
|
||||
|
||||
void QskProgressIndicator::setFillGradient( const QskGradient& gradient )
|
||||
{
|
||||
setGradientHint( Fill, gradient );
|
||||
}
|
||||
|
||||
void QskProgressIndicator::resetFillGradient()
|
||||
{
|
||||
resetColor( Fill );
|
||||
}
|
||||
|
||||
QskGradient QskProgressIndicator::fillGradient() const
|
||||
{
|
||||
return gradientHint( Fill );
|
||||
}
|
||||
|
||||
void QskProgressIndicator::setExtent( qreal extent )
|
||||
{
|
||||
if ( extent < 0.0 )
|
||||
extent = 0.0;
|
||||
|
||||
if ( setMetric( Groove | QskAspect::Size, extent ) )
|
||||
Q_EMIT extentChanged( extent );
|
||||
}
|
||||
|
||||
void QskProgressIndicator::resetExtent()
|
||||
{
|
||||
if ( resetMetric( Groove | QskAspect::Size ) )
|
||||
Q_EMIT extentChanged( extent() );
|
||||
}
|
||||
|
||||
qreal QskProgressIndicator::extent() const
|
||||
{
|
||||
auto grooveSize = metric( Groove | QskAspect::Size );
|
||||
auto fillSize = metric( Fill | QskAspect::Size );
|
||||
return qMax( grooveSize, fillSize );
|
||||
}
|
||||
|
||||
void QskProgressIndicator::setOrigin( qreal origin )
|
||||
{
|
||||
if ( isComponentComplete() )
|
||||
origin = boundedValue( origin );
|
||||
|
||||
if( !m_data->hasOrigin || !qskFuzzyCompare( m_data->origin, origin ) )
|
||||
{
|
||||
m_data->hasOrigin = true;
|
||||
m_data->origin = origin;
|
||||
|
||||
update();
|
||||
Q_EMIT originChanged( origin );
|
||||
}
|
||||
}
|
||||
|
||||
void QskProgressIndicator::resetOrigin()
|
||||
{
|
||||
if ( m_data->hasOrigin )
|
||||
{
|
||||
m_data->hasOrigin = false;
|
||||
|
||||
update();
|
||||
Q_EMIT originChanged( origin() );
|
||||
}
|
||||
}
|
||||
|
||||
qreal QskProgressIndicator::origin() const
|
||||
{
|
||||
if ( m_data->hasOrigin )
|
||||
{
|
||||
return boundedValue( m_data->origin );
|
||||
}
|
||||
|
||||
return minimum();
|
||||
}
|
||||
|
||||
void QskProgressIndicator::setValue( qreal value )
|
||||
{
|
||||
if ( isComponentComplete() )
|
||||
value = boundedValue( value );
|
||||
|
||||
setValueInternal( value );
|
||||
}
|
||||
|
||||
qreal QskProgressIndicator::value() const
|
||||
{
|
||||
return m_data->value;
|
||||
}
|
||||
|
||||
void QskProgressIndicator::setValueAsRatio( qreal ratio )
|
||||
{
|
||||
ratio = qBound( 0.0, ratio, 1.0 );
|
||||
setValue( minimum() + ratio * boundaryLength() );
|
||||
}
|
||||
|
||||
qreal QskProgressIndicator::valueAsRatio() const
|
||||
{
|
||||
return valueAsRatio( m_data->value );
|
||||
}
|
||||
|
||||
void QskProgressIndicator::componentComplete()
|
||||
{
|
||||
Inherited::componentComplete();
|
||||
adjustValue();
|
||||
}
|
||||
|
||||
void QskProgressIndicator::adjustValue()
|
||||
{
|
||||
if ( isComponentComplete() )
|
||||
setValueInternal( boundedValue( m_data->value ) );
|
||||
}
|
||||
|
||||
void QskProgressIndicator::setValueInternal( qreal value )
|
||||
{
|
||||
if ( !qskFuzzyCompare( value, m_data->value ) )
|
||||
{
|
||||
m_data->value = value;
|
||||
Q_EMIT valueChanged( value );
|
||||
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void QskProgressIndicator::itemChange( QQuickItem::ItemChange change,
|
||||
const QQuickItem::ItemChangeData& value )
|
||||
{
|
||||
switch( static_cast< int >( change ) )
|
||||
{
|
||||
case QQuickItem::ItemVisibleHasChanged:
|
||||
case QQuickItem::ItemSceneChange:
|
||||
{
|
||||
m_data->updateIndeterminateAnimator( this );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Inherited::itemChange( change, value );
|
||||
}
|
||||
|
||||
#include "moc_QskProgressIndicator.cpp"
|
|
@ -0,0 +1,83 @@
|
|||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QSK_PROGRESS_INDICATOR_H
|
||||
#define QSK_PROGRESS_INDICATOR_H
|
||||
|
||||
#include "QskBoundedControl.h"
|
||||
|
||||
class QskIntervalF;
|
||||
|
||||
class QSK_EXPORT QskProgressIndicator : public QskBoundedControl
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY( qreal extent READ extent
|
||||
WRITE setExtent RESET resetExtent NOTIFY extentChanged )
|
||||
|
||||
Q_PROPERTY( bool indeterminate READ isIndeterminate
|
||||
WRITE setIndeterminate NOTIFY indeterminateChanged )
|
||||
|
||||
Q_PROPERTY( qreal origin READ origin
|
||||
WRITE setOrigin RESET resetOrigin NOTIFY originChanged )
|
||||
|
||||
Q_PROPERTY( qreal value READ value WRITE setValue NOTIFY valueChanged )
|
||||
Q_PROPERTY( qreal valueAsRatio READ valueAsRatio
|
||||
WRITE setValueAsRatio NOTIFY valueChanged )
|
||||
|
||||
using Inherited = QskBoundedControl;
|
||||
|
||||
public:
|
||||
QSK_SUBCONTROLS( Groove, Fill )
|
||||
|
||||
QskProgressIndicator( QQuickItem* parent = nullptr );
|
||||
QskProgressIndicator( qreal min, qreal max, QQuickItem* parent = nullptr );
|
||||
QskProgressIndicator( const QskIntervalF&, QQuickItem* parent = nullptr );
|
||||
|
||||
~QskProgressIndicator() override;
|
||||
|
||||
bool isIndeterminate() const;
|
||||
void setIndeterminate( bool on = true );
|
||||
|
||||
void setFillGradient( const QskGradient& );
|
||||
void resetFillGradient();
|
||||
QskGradient fillGradient() const;
|
||||
|
||||
void setExtent( qreal );
|
||||
void resetExtent();
|
||||
qreal extent() const;
|
||||
|
||||
void resetOrigin();
|
||||
qreal origin() const;
|
||||
|
||||
qreal value() const;
|
||||
qreal valueAsRatio() const; // [0.0, 1.0]
|
||||
using QskBoundedControl::valueAsRatio;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setValue( qreal );
|
||||
void setValueAsRatio( qreal );
|
||||
void setOrigin( qreal );
|
||||
|
||||
Q_SIGNALS:
|
||||
void extentChanged( qreal );
|
||||
void indeterminateChanged( bool );
|
||||
void valueChanged( qreal );
|
||||
void originChanged( qreal );
|
||||
|
||||
protected:
|
||||
void componentComplete() override;
|
||||
void itemChange( ItemChange, const ItemChangeData& ) override;
|
||||
|
||||
private:
|
||||
void setValueInternal( qreal value );
|
||||
void adjustBoundaries( bool increasing );
|
||||
void adjustValue();
|
||||
|
||||
class PrivateData;
|
||||
std::unique_ptr< PrivateData > m_data;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,40 @@
|
|||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#include "QskProgressIndicatorSkinlet.h"
|
||||
#include "QskProgressIndicator.h"
|
||||
|
||||
QskProgressIndicatorSkinlet::QskProgressIndicatorSkinlet( QskSkin* skin )
|
||||
: Inherited( skin )
|
||||
{
|
||||
setNodeRoles( { GrooveRole, FillRole } );
|
||||
}
|
||||
|
||||
QskProgressIndicatorSkinlet::~QskProgressIndicatorSkinlet()
|
||||
{
|
||||
}
|
||||
|
||||
QSGNode* QskProgressIndicatorSkinlet::updateSubNode(
|
||||
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
|
||||
{
|
||||
const auto indicator = static_cast< const QskProgressIndicator* >( skinnable );
|
||||
|
||||
switch( nodeRole )
|
||||
{
|
||||
case GrooveRole:
|
||||
{
|
||||
return updateGrooveNode( indicator, node );
|
||||
}
|
||||
|
||||
case FillRole:
|
||||
{
|
||||
return updateFillNode( indicator, node );
|
||||
}
|
||||
}
|
||||
|
||||
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
||||
}
|
||||
|
||||
#include "moc_QskProgressIndicatorSkinlet.cpp"
|
|
@ -0,0 +1,37 @@
|
|||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QSK_PROGRESS_INDICATOR_SKINLET_H
|
||||
#define QSK_PROGRESS_INDICATOR_SKINLET_H
|
||||
|
||||
#include "QskSkinlet.h"
|
||||
|
||||
class QskProgressIndicator;
|
||||
|
||||
class QSK_EXPORT QskProgressIndicatorSkinlet : public QskSkinlet
|
||||
{
|
||||
using Inherited = QskSkinlet;
|
||||
|
||||
public:
|
||||
enum NodeRole
|
||||
{
|
||||
GrooveRole,
|
||||
FillRole,
|
||||
|
||||
RoleCount
|
||||
};
|
||||
|
||||
QskProgressIndicatorSkinlet( QskSkin* = nullptr );
|
||||
~QskProgressIndicatorSkinlet() override;
|
||||
|
||||
protected:
|
||||
QSGNode* updateSubNode( const QskSkinnable*,
|
||||
quint8 nodeRole, QSGNode* ) const override;
|
||||
|
||||
virtual QSGNode* updateGrooveNode( const QskProgressIndicator*, QSGNode* ) const = 0;
|
||||
virtual QSGNode* updateFillNode( const QskProgressIndicator*, QSGNode* ) const = 0;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,76 @@
|
|||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2023 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#include "QskProgressRing.h"
|
||||
|
||||
#include "QskIntervalF.h"
|
||||
|
||||
QSK_SUBCONTROL( QskProgressRing, Groove )
|
||||
QSK_SUBCONTROL( QskProgressRing, Fill )
|
||||
|
||||
class QskProgressRing::PrivateData
|
||||
{
|
||||
public:
|
||||
int size : 2;
|
||||
};
|
||||
|
||||
QskProgressRing::QskProgressRing( qreal min, qreal max, QQuickItem* parent )
|
||||
: Inherited( min, max, parent )
|
||||
, m_data( new PrivateData )
|
||||
{
|
||||
m_data->size = NormalSize;
|
||||
|
||||
setSubcontrolProxy( Inherited::Groove, Groove );
|
||||
setSubcontrolProxy( Inherited::Fill, Fill );
|
||||
}
|
||||
|
||||
QskProgressRing::QskProgressRing( QQuickItem* parent )
|
||||
: QskProgressRing( 0.0, 100.0, parent )
|
||||
{
|
||||
}
|
||||
|
||||
QskProgressRing::QskProgressRing( const QskIntervalF& boundaries, QQuickItem* parent )
|
||||
: QskProgressRing( boundaries.lowerBound(), boundaries.upperBound(), parent )
|
||||
{
|
||||
}
|
||||
|
||||
QskProgressRing::~QskProgressRing()
|
||||
{
|
||||
}
|
||||
|
||||
QskAspect::Variation QskProgressRing::effectiveVariation() const
|
||||
{
|
||||
switch( size() )
|
||||
{
|
||||
case SmallSize:
|
||||
return QskAspect::Small;
|
||||
|
||||
case LargeSize:
|
||||
return QskAspect::Large;
|
||||
|
||||
default:
|
||||
return QskAspect::NoVariation;
|
||||
}
|
||||
}
|
||||
|
||||
void QskProgressRing::setSize( Size size )
|
||||
{
|
||||
if ( size != m_data->size )
|
||||
{
|
||||
m_data->size = size;
|
||||
|
||||
resetImplicitSize();
|
||||
update();
|
||||
|
||||
Q_EMIT sizeChanged( size );
|
||||
}
|
||||
}
|
||||
|
||||
QskProgressRing::Size QskProgressRing::size() const
|
||||
{
|
||||
return static_cast< Size >( m_data->size );
|
||||
}
|
||||
|
||||
#include "moc_QskProgressRing.cpp"
|
|
@ -0,0 +1,50 @@
|
|||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2023 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QSK_PROGRESS_RING_H
|
||||
#define QSK_PROGRESS_RING_H
|
||||
|
||||
#include "QskProgressIndicator.h"
|
||||
|
||||
class QSK_EXPORT QskProgressRing : public QskProgressIndicator
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY( Size size READ size
|
||||
WRITE setSize NOTIFY sizeChanged )
|
||||
|
||||
using Inherited = QskProgressIndicator;
|
||||
|
||||
public:
|
||||
QSK_SUBCONTROLS( Groove, Fill )
|
||||
|
||||
enum Size
|
||||
{
|
||||
SmallSize = -1,
|
||||
NormalSize = 0,
|
||||
LargeSize = 1
|
||||
};
|
||||
Q_ENUM( Size )
|
||||
|
||||
QskProgressRing( QQuickItem* parent = nullptr );
|
||||
QskProgressRing( qreal min, qreal max, QQuickItem* parent = nullptr );
|
||||
QskProgressRing( const QskIntervalF&, QQuickItem* parent = nullptr );
|
||||
|
||||
~QskProgressRing() override;
|
||||
|
||||
QskAspect::Variation effectiveVariation() const override;
|
||||
|
||||
void setSize( Size );
|
||||
Size size() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void sizeChanged( Size );
|
||||
|
||||
private:
|
||||
class PrivateData;
|
||||
std::unique_ptr< PrivateData > m_data;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,125 @@
|
|||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2023 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#include "QskProgressRingSkinlet.h"
|
||||
#include "QskArcMetrics.h"
|
||||
#include "QskProgressRing.h"
|
||||
#include "QskIntervalF.h"
|
||||
|
||||
using Q = QskProgressRing;
|
||||
|
||||
namespace
|
||||
{
|
||||
QskIntervalF qskFillInterval( const Q* ring )
|
||||
{
|
||||
qreal pos1, pos2;
|
||||
|
||||
if ( ring->isIndeterminate() )
|
||||
{
|
||||
const auto pos = ring->positionHint( QskProgressIndicator::Fill );
|
||||
|
||||
pos1 = pos2 = pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos1 = ring->valueAsRatio( ring->origin() );
|
||||
pos2 = ring->valueAsRatio( ring->value() );
|
||||
}
|
||||
|
||||
if ( pos1 > pos2 )
|
||||
std::swap( pos1, pos2 );
|
||||
|
||||
return QskIntervalF( pos1, pos2 );
|
||||
}
|
||||
}
|
||||
|
||||
QskProgressRingSkinlet::QskProgressRingSkinlet( QskSkin* skin )
|
||||
: Inherited( skin )
|
||||
{
|
||||
}
|
||||
|
||||
QskProgressRingSkinlet::~QskProgressRingSkinlet()
|
||||
{
|
||||
}
|
||||
|
||||
QRectF QskProgressRingSkinlet::subControlRect(
|
||||
const QskSkinnable* skinnable, const QRectF& contentsRect,
|
||||
QskAspect::Subcontrol subControl ) const
|
||||
{
|
||||
const auto ring = static_cast< const Q* >( skinnable );
|
||||
|
||||
if( subControl == Q::Groove || subControl == Q::Fill )
|
||||
{
|
||||
auto rect = contentsRect;
|
||||
const auto size = ring->strutSizeHint( Q::Fill );
|
||||
|
||||
if( ring->layoutMirroring() )
|
||||
{
|
||||
rect.setLeft( rect.right() - size.width() );
|
||||
}
|
||||
else
|
||||
{
|
||||
rect.setWidth( size.width() );
|
||||
}
|
||||
|
||||
rect.setTop( rect.top() + 0.5 * ( rect.height() - size.height() ) );
|
||||
rect.setHeight( size.height() );
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
return Inherited::subControlRect( skinnable, contentsRect, subControl );
|
||||
}
|
||||
|
||||
QSGNode* QskProgressRingSkinlet::updateGrooveNode(
|
||||
const QskProgressIndicator* indicator, QSGNode* node ) const
|
||||
{
|
||||
return updateArcNode( indicator, node, Q::Groove );
|
||||
}
|
||||
|
||||
QSGNode* QskProgressRingSkinlet::updateFillNode(
|
||||
const QskProgressIndicator* indicator, QSGNode* node ) const
|
||||
{
|
||||
const auto ring = static_cast< const Q* >( indicator );
|
||||
|
||||
const auto subControl = Q::Fill;
|
||||
|
||||
const auto rect = ring->subControlRect( subControl );
|
||||
if ( rect.isEmpty() )
|
||||
return nullptr;
|
||||
|
||||
auto gradient = ring->gradientHint( subControl );
|
||||
if ( !gradient.isVisible() )
|
||||
return nullptr;
|
||||
|
||||
if ( ( gradient.type() == QskGradient::Stops ) && !gradient.isMonochrome() )
|
||||
{
|
||||
const auto center = rect.center();
|
||||
const auto arcMetrics = ring->arcMetricsHint( Q::Fill );
|
||||
gradient.setConicDirection( center.x(), center.y(), arcMetrics.startAngle(), arcMetrics.spanAngle() );
|
||||
}
|
||||
|
||||
const auto interval = qskFillInterval( ring );
|
||||
const auto arcMetrics = ring->arcMetricsHint( subControl );
|
||||
|
||||
const auto startAngle = arcMetrics.startAngle() + interval.lowerBound() * arcMetrics.spanAngle();
|
||||
const auto spanAngle = interval.upperBound() * arcMetrics.spanAngle();
|
||||
|
||||
return updateArcNode( ring, node, rect, gradient, startAngle, spanAngle, subControl );
|
||||
}
|
||||
|
||||
QSizeF QskProgressRingSkinlet::sizeHint( const QskSkinnable* skinnable,
|
||||
Qt::SizeHint which, const QSizeF& ) const
|
||||
{
|
||||
if ( which != Qt::PreferredSize )
|
||||
return QSizeF();
|
||||
|
||||
const auto ring = static_cast< const Q* >( skinnable );
|
||||
|
||||
const auto r = ring->strutSizeHint( Q::Fill );
|
||||
return r;
|
||||
}
|
||||
|
||||
#include "moc_QskProgressRingSkinlet.cpp"
|
|
@ -0,0 +1,34 @@
|
|||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2023 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QSK_PROGRESS_RING_SKINLET_H
|
||||
#define QSK_PROGRESS_RING_SKINLET_H
|
||||
|
||||
#include "QskProgressIndicatorSkinlet.h"
|
||||
|
||||
class QskProgressRing;
|
||||
|
||||
class QSK_EXPORT QskProgressRingSkinlet : public QskProgressIndicatorSkinlet
|
||||
{
|
||||
Q_GADGET
|
||||
|
||||
using Inherited = QskProgressIndicatorSkinlet;
|
||||
|
||||
public:
|
||||
Q_INVOKABLE QskProgressRingSkinlet( QskSkin* = nullptr );
|
||||
~QskProgressRingSkinlet() override;
|
||||
|
||||
QRectF subControlRect( const QskSkinnable*,
|
||||
const QRectF&, QskAspect::Subcontrol ) const override;
|
||||
|
||||
QSizeF sizeHint( const QskSkinnable*,
|
||||
Qt::SizeHint, const QSizeF& ) const override;
|
||||
|
||||
protected:
|
||||
QSGNode* updateGrooveNode( const QskProgressIndicator*, QSGNode* ) const override;
|
||||
QSGNode* updateFillNode( const QskProgressIndicator*, QSGNode* ) const override;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -53,6 +53,9 @@
|
|||
#include "QskProgressBar.h"
|
||||
#include "QskProgressBarSkinlet.h"
|
||||
|
||||
#include "QskProgressRing.h"
|
||||
#include "QskProgressRingSkinlet.h"
|
||||
|
||||
#include "QskRadioBox.h"
|
||||
#include "QskRadioBoxSkinlet.h"
|
||||
|
||||
|
@ -178,6 +181,7 @@ QskSkin::QskSkin( QObject* parent )
|
|||
declareSkinlet< QskTextLabel, QskTextLabelSkinlet >();
|
||||
declareSkinlet< QskTextInput, QskTextInputSkinlet >();
|
||||
declareSkinlet< QskProgressBar, QskProgressBarSkinlet >();
|
||||
declareSkinlet< QskProgressRing, QskProgressRingSkinlet >();
|
||||
declareSkinlet< QskRadioBox, QskRadioBoxSkinlet >();
|
||||
|
||||
const QFont font = QGuiApplication::font();
|
||||
|
|
Loading…
Reference in New Issue