QskValueBar added

This commit is contained in:
Uwe Rathmann 2020-07-31 16:57:22 +02:00
parent c66d2044a9
commit 7cd4b940aa
10 changed files with 515 additions and 0 deletions

View File

@ -22,6 +22,7 @@
#include <QskTabView.h> #include <QskTabView.h>
#include <QskTextInput.h> #include <QskTextInput.h>
#include <QskTextLabel.h> #include <QskTextLabel.h>
#include <QskValueBar.h>
#include <QskVirtualKeyboard.h> #include <QskVirtualKeyboard.h>
#include <QskSkinlet.h> #include <QskSkinlet.h>
@ -144,6 +145,7 @@ void QskMaterialSkin::initHints()
initTabViewHints(); initTabViewHints();
initTextLabelHints(); initTextLabelHints();
initTextInputHints(); initTextInputHints();
initValueBarHints();
} }
void QskMaterialSkin::resetColors( const QColor& accent ) void QskMaterialSkin::resetColors( const QColor& accent )
@ -234,6 +236,19 @@ void QskMaterialSkin::initTextInputHints()
setGradient( Q::Panel, pal.baseColor ); setGradient( Q::Panel, pal.baseColor );
} }
void QskMaterialSkin::initValueBarHints()
{
using namespace QskAspect;
using Q = QskValueBar;
const ColorPalette& pal = m_data->palette;
setGradient( Q::Groove, Qt::white );
setMetric( Q::Groove | Size, 10 );
setGradient( Q::ValueFill, pal.accentColor );
}
void QskMaterialSkin::initFocusIndicatorHints() void QskMaterialSkin::initFocusIndicatorHints()
{ {
using namespace QskAspect; using namespace QskAspect;

View File

@ -46,6 +46,7 @@ class QSK_MATERIAL_EXPORT QskMaterialSkin : public QskSkin
void initTabViewHints(); void initTabViewHints();
void initTextInputHints(); void initTextInputHints();
void initTextLabelHints(); void initTextLabelHints();
void initValueBarHints();
class PrivateData; class PrivateData;
std::unique_ptr< PrivateData > m_data; std::unique_ptr< PrivateData > m_data;

View File

@ -23,6 +23,7 @@
#include <QskTabView.h> #include <QskTabView.h>
#include <QskTextInput.h> #include <QskTextInput.h>
#include <QskTextLabel.h> #include <QskTextLabel.h>
#include <QskValueBar.h>
#include <QskVirtualKeyboard.h> #include <QskVirtualKeyboard.h>
#include <QskSkinlet.h> #include <QskSkinlet.h>
@ -272,6 +273,7 @@ void QskSquiekSkin::initHints()
initTabViewHints(); initTabViewHints();
initTextLabelHints(); initTextLabelHints();
initTextInputHints(); initTextInputHints();
initValueBarInputHints();
} }
void QskSquiekSkin::resetColors( const QColor& accent ) void QskSquiekSkin::resetColors( const QColor& accent )
@ -380,6 +382,19 @@ void QskSquiekSkin::initTextInputHints()
setAnimation( Q::Panel | Color, qskDuration ); setAnimation( Q::Panel | Color, qskDuration );
} }
void QskSquiekSkin::initValueBarInputHints()
{
using namespace QskAspect;
using Q = QskValueBar;
const ColorPalette& pal = m_data->palette;
setGradient( Q::Groove, Qt::white );
setMetric( Q::Groove | Size, 10 );
setGradient( Q::ValueFill, pal.highlighted );
}
void QskSquiekSkin::initFocusIndicatorHints() void QskSquiekSkin::initFocusIndicatorHints()
{ {
using namespace QskAspect; using namespace QskAspect;

View File

@ -47,6 +47,7 @@ class QSK_SQUIEK_EXPORT QskSquiekSkin : public QskSkin
void initTabViewHints(); void initTabViewHints();
void initTextLabelHints(); void initTextLabelHints();
void initTextInputHints(); void initTextInputHints();
void initValueBarInputHints();
enum PanelStyle enum PanelStyle
{ {

View File

@ -74,6 +74,9 @@ QSK_QT_PRIVATE_END
#include "QskStatusIndicator.h" #include "QskStatusIndicator.h"
#include "QskStatusIndicatorSkinlet.h" #include "QskStatusIndicatorSkinlet.h"
#include "QskValueBar.h"
#include "QskValueBarSkinlet.h"
static inline QskSkinlet* qskNewSkinlet( const QMetaObject* metaObject, QskSkin* skin ) static inline QskSkinlet* qskNewSkinlet( const QMetaObject* metaObject, QskSkin* skin )
{ {
const QByteArray signature = metaObject->className() + QByteArrayLiteral( "(QskSkin*)" ); const QByteArray signature = metaObject->className() + QByteArrayLiteral( "(QskSkin*)" );
@ -148,6 +151,7 @@ QskSkin::QskSkin( QObject* parent )
declareSkinlet< QskTabView, QskTabViewSkinlet >(); declareSkinlet< QskTabView, QskTabViewSkinlet >();
declareSkinlet< QskTextLabel, QskTextLabelSkinlet >(); declareSkinlet< QskTextLabel, QskTextLabelSkinlet >();
declareSkinlet< QskTextInput, QskTextInputSkinlet >(); declareSkinlet< QskTextInput, QskTextInputSkinlet >();
declareSkinlet< QskValueBar, QskValueBarSkinlet >();
const QFont font = QGuiApplication::font(); const QFont font = QGuiApplication::font();
setupFonts( font.family(), font.weight(), font.italic() ); setupFonts( font.family(), font.weight(), font.italic() );

View File

@ -0,0 +1,215 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#include "QskValueBar.h"
#include "QskIntervalF.h"
#include "QskGradient.h"
#include "QskFunctions.h"
#include "QskAspect.h"
QSK_SUBCONTROL( QskValueBar, Groove )
QSK_SUBCONTROL( QskValueBar, ValueFill )
class QskValueBar::PrivateData
{
public:
qreal value = 0.0;
qreal origin = 0.0;
bool hasOrigin = false;
Qt::Orientation orientation;
};
QskValueBar::QskValueBar( Qt::Orientation orientation,
qreal min, qreal max, QQuickItem* parent )
: QskBoundedControl( 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, &QskValueBar::adjustValue );
}
QskValueBar::QskValueBar( Qt::Orientation orientation, QQuickItem* parent )
: QskValueBar( orientation, 0.0, 100.0, parent )
{
}
QskValueBar::QskValueBar( const QskIntervalF& boundaries, QQuickItem* parent )
: QskValueBar( boundaries.lowerBound(), boundaries.upperBound(), parent )
{
}
QskValueBar::QskValueBar( qreal min, qreal max, QQuickItem* parent )
: QskValueBar( Qt::Horizontal, min, max, parent )
{
}
QskValueBar::QskValueBar( QQuickItem* parent )
: QskValueBar( Qt::Horizontal, parent )
{
}
QskValueBar::~QskValueBar()
{
}
Qt::Orientation QskValueBar::orientation() const
{
return m_data->orientation;
}
void QskValueBar::setOrientation( Qt::Orientation orientation )
{
if ( orientation != m_data->orientation )
{
m_data->orientation = orientation;
setSizePolicy( sizePolicy( Qt::Vertical ), sizePolicy( Qt::Horizontal ) );
resetImplicitSize();
update();
Q_EMIT orientationChanged( m_data->orientation );
}
}
QskAspect::Placement QskValueBar::effectivePlacement() const
{
// so you can define different hints depending on the orientation
return static_cast< QskAspect::Placement >( m_data->orientation );
}
void QskValueBar::setFillGradient( const QskGradient& gradient )
{
setGradientHint( QskValueBar::ValueFill, gradient );
}
QskGradient QskValueBar::fillGradient() const
{
return gradientHint( QskValueBar::ValueFill );
}
void QskValueBar::setThickness( qreal thickness )
{
// effectiveSubcontrol( QskValueBar::Groove ) ???
const auto aspect = QskValueBar::Groove | QskAspect::Size;
if ( thickness != metric( aspect ) )
{
setMetric( aspect, thickness );
resetImplicitSize();
update();
}
}
qreal QskValueBar::thickness() const
{
return metric( Groove | QskAspect::Size );
}
void QskValueBar::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 QskValueBar::resetOrigin()
{
if ( m_data->hasOrigin )
{
m_data->hasOrigin = false;
update();
Q_EMIT originChanged( origin() );
}
}
qreal QskValueBar::origin() const
{
if ( m_data->hasOrigin )
{
return boundedValue( m_data->origin );
}
return minimum();
}
void QskValueBar::setValue( qreal value )
{
if ( isComponentComplete() )
value = boundedValue( value );
setValueInternal( value );
}
qreal QskValueBar::value() const
{
return m_data->value;
}
void QskValueBar::setValueAsRatio( qreal ratio )
{
ratio = qBound( 0.0, ratio, 1.0 );
setValue( minimum() + ratio * boundaryLength() );
}
qreal QskValueBar::valueAsRatio() const
{
return valueAsRatio( m_data->value );
}
QSizeF QskValueBar::contentsSizeHint( Qt::SizeHint which, const QSizeF& ) const
{
if ( which != Qt::PreferredSize )
return QSizeF();
if ( orientation() == Qt::Horizontal )
return QSizeF( -1, thickness() );
else
return QSizeF( thickness(), -1 );
}
void QskValueBar::componentComplete()
{
Inherited::componentComplete();
adjustValue();
}
void QskValueBar::adjustValue()
{
if ( isComponentComplete() )
setValueInternal( boundedValue( m_data->value ) );
}
void QskValueBar::setValueInternal( qreal value )
{
if ( !qskFuzzyCompare( value, m_data->value ) )
{
m_data->value = value;
Q_EMIT valueChanged( value );
update();
}
}
#include "moc_QskValueBar.cpp"

View File

@ -0,0 +1,81 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#ifndef QSK_VALUE_BAR_H
#define QSK_VALUE_BAR_H
#include "QskBoundedControl.h"
class QskIntervalF;
class QSK_EXPORT QskValueBar : public QskBoundedControl
{
Q_OBJECT
Q_PROPERTY( Qt::Orientation orientation READ orientation
WRITE setOrientation NOTIFY orientationChanged )
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, ValueFill )
QskValueBar( Qt::Orientation, QQuickItem* parent = nullptr );
QskValueBar( Qt::Orientation, qreal min, qreal max, QQuickItem* parent = nullptr );
QskValueBar( const QskIntervalF&, QQuickItem* parent = nullptr );
QskValueBar( qreal min, qreal max, QQuickItem* parent = nullptr );
QskValueBar( QQuickItem* parent = nullptr );
~QskValueBar() override;
Qt::Orientation orientation() const;
void setOrientation( Qt::Orientation orientation );
QskAspect::Placement effectivePlacement() const override;
void setFillGradient( const QskGradient& );
QskGradient fillGradient() const;
void setThickness( qreal );
qreal thickness() 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 valueChanged( qreal );
void originChanged( qreal );
protected:
QSizeF contentsSizeHint( Qt::SizeHint, const QSizeF& ) const override;
void componentComplete() override;
private:
void setValueInternal( qreal value );
void adjustBoundaries( bool increasing );
void adjustValue();
class PrivateData;
std::unique_ptr< PrivateData > m_data;
};
#endif

View File

@ -0,0 +1,136 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#include "QskValueBarSkinlet.h"
#include "QskValueBar.h"
#include <cmath>
QskValueBarSkinlet::QskValueBarSkinlet( QskSkin* skin )
: QskSkinlet( skin )
{
setNodeRoles( { GrooveRole, ValueFillRole } );
}
QskValueBarSkinlet::~QskValueBarSkinlet()
{
}
QRectF QskValueBarSkinlet::subControlRect(
const QskSkinnable* skinnable, const QRectF& contentsRect,
QskAspect::Subcontrol subControl ) const
{
const auto bar = static_cast< const QskValueBar* >( skinnable );
if( ( subControl == QskValueBar::Groove ) )
{
const auto dim = bar->thickness();
auto rect = contentsRect;
if ( bar->orientation() == Qt::Horizontal )
{
rect.setY( rect.y() + 0.5 * ( rect.height() - dim ) );
rect.setHeight( dim );
}
else
{
rect.setX( rect.x() + 0.5 * ( rect.width() - dim ) );
rect.setWidth( dim );
}
return rect;
}
if( subControl == QskValueBar::ValueFill )
{
const auto bar = static_cast< const QskValueBar* >( skinnable );
return fillRect( bar );
}
return Inherited::subControlRect( skinnable, contentsRect, subControl );
}
QSGNode* QskValueBarSkinlet::updateSubNode(
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
{
switch( nodeRole )
{
case GrooveRole:
{
return updateBoxNode( skinnable, node, QskValueBar::Groove );
}
case ValueFillRole:
{
const auto bar = static_cast< const QskValueBar* >( skinnable );
return updateFillNode( bar, node );
}
}
return Inherited::updateSubNode( skinnable, nodeRole, node );
}
QSGNode* QskValueBarSkinlet::updateFillNode(
const QskValueBar* bar, QSGNode* node ) const
{
const auto subControl = QskValueBar::ValueFill;
const auto rect = bar->subControlRect( subControl );
if ( rect.isEmpty() )
return nullptr;
auto gradient = bar->gradientHint( subControl );
if ( !gradient.isVisible() )
return nullptr;
gradient.setOrientation( bar->orientation() );
if ( !gradient.isMonochrome() )
{
qreal pos1 = bar->valueAsRatio( bar->origin() );
qreal pos2 = bar->valueAsRatio( bar->value() );
if ( pos2 < pos1 )
std::swap( pos1, pos2 );
gradient = gradient.extracted( pos1, pos2 );
if ( bar->orientation() == Qt::Vertical )
gradient.reverse();
}
return updateBoxNode( bar, node, rect, gradient, subControl );
}
QRectF QskValueBarSkinlet::fillRect( const QskValueBar* bar ) const
{
auto rect = bar->subControlRect( QskValueBar::Groove );
rect = bar->innerBox( QskValueBar::Groove, rect );
auto pos1 = bar->valueAsRatio( bar->origin() );
auto pos2 = bar->valueAsRatio( bar->value() );
if ( pos1 > pos2 )
std::swap( pos1, pos2 );
if( bar->orientation() == Qt::Horizontal )
{
const auto w = rect.width();
rect.setRight( rect.left() + pos2 * w );
rect.setLeft( rect.left() + pos1 * w );
}
else
{
const auto h = rect.height();
rect.setTop( rect.bottom() - h * pos2 );
rect.setBottom( rect.bottom() - h * pos1 );
}
return rect;
}
#include "moc_QskValueBarSkinlet.cpp"

View File

@ -0,0 +1,43 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#ifndef QSK_VALUE_BAR_SKINLET_H
#define QSK_VALUE_BAR_SKINLET_H
#include "QskSkinlet.h"
class QskValueBar;
class QSK_EXPORT QskValueBarSkinlet : public QskSkinlet
{
Q_GADGET
using Inherited = QskSkinlet;
public:
enum NodeRole
{
GrooveRole,
ValueFillRole,
RoleCount,
};
Q_INVOKABLE QskValueBarSkinlet( QskSkin* = nullptr );
~QskValueBarSkinlet() override;
QRectF subControlRect( const QskSkinnable*,
const QRectF&, QskAspect::Subcontrol ) const override;
protected:
QSGNode* updateSubNode( const QskSkinnable*,
quint8 nodeRole, QSGNode* ) const override;
private:
QSGNode* updateFillNode( const QskValueBar*, QSGNode* ) const;
QRectF fillRect( const QskValueBar* ) const;
};
#endif

View File

@ -177,6 +177,8 @@ HEADERS += \
controls/QskTextInputSkinlet.h \ controls/QskTextInputSkinlet.h \
controls/QskTextLabel.h \ controls/QskTextLabel.h \
controls/QskTextLabelSkinlet.h \ controls/QskTextLabelSkinlet.h \
controls/QskValueBar.h \
controls/QskValueBarSkinlet.h \
controls/QskVariantAnimator.h \ controls/QskVariantAnimator.h \
controls/QskWindow.h controls/QskWindow.h
@ -248,6 +250,8 @@ SOURCES += \
controls/QskTextInputSkinlet.cpp \ controls/QskTextInputSkinlet.cpp \
controls/QskTextLabel.cpp \ controls/QskTextLabel.cpp \
controls/QskTextLabelSkinlet.cpp \ controls/QskTextLabelSkinlet.cpp \
controls/QskValueBar.cpp \
controls/QskValueBarSkinlet.cpp \
controls/QskVariantAnimator.cpp \ controls/QskVariantAnimator.cpp \
controls/QskWindow.cpp controls/QskWindow.cpp