QskValueBar added
This commit is contained in:
parent
c66d2044a9
commit
7cd4b940aa
|
@ -22,6 +22,7 @@
|
|||
#include <QskTabView.h>
|
||||
#include <QskTextInput.h>
|
||||
#include <QskTextLabel.h>
|
||||
#include <QskValueBar.h>
|
||||
#include <QskVirtualKeyboard.h>
|
||||
|
||||
#include <QskSkinlet.h>
|
||||
|
@ -144,6 +145,7 @@ void QskMaterialSkin::initHints()
|
|||
initTabViewHints();
|
||||
initTextLabelHints();
|
||||
initTextInputHints();
|
||||
initValueBarHints();
|
||||
}
|
||||
|
||||
void QskMaterialSkin::resetColors( const QColor& accent )
|
||||
|
@ -234,6 +236,19 @@ void QskMaterialSkin::initTextInputHints()
|
|||
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()
|
||||
{
|
||||
using namespace QskAspect;
|
||||
|
|
|
@ -46,6 +46,7 @@ class QSK_MATERIAL_EXPORT QskMaterialSkin : public QskSkin
|
|||
void initTabViewHints();
|
||||
void initTextInputHints();
|
||||
void initTextLabelHints();
|
||||
void initValueBarHints();
|
||||
|
||||
class PrivateData;
|
||||
std::unique_ptr< PrivateData > m_data;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <QskTabView.h>
|
||||
#include <QskTextInput.h>
|
||||
#include <QskTextLabel.h>
|
||||
#include <QskValueBar.h>
|
||||
#include <QskVirtualKeyboard.h>
|
||||
|
||||
#include <QskSkinlet.h>
|
||||
|
@ -272,6 +273,7 @@ void QskSquiekSkin::initHints()
|
|||
initTabViewHints();
|
||||
initTextLabelHints();
|
||||
initTextInputHints();
|
||||
initValueBarInputHints();
|
||||
}
|
||||
|
||||
void QskSquiekSkin::resetColors( const QColor& accent )
|
||||
|
@ -380,6 +382,19 @@ void QskSquiekSkin::initTextInputHints()
|
|||
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()
|
||||
{
|
||||
using namespace QskAspect;
|
||||
|
|
|
@ -47,6 +47,7 @@ class QSK_SQUIEK_EXPORT QskSquiekSkin : public QskSkin
|
|||
void initTabViewHints();
|
||||
void initTextLabelHints();
|
||||
void initTextInputHints();
|
||||
void initValueBarInputHints();
|
||||
|
||||
enum PanelStyle
|
||||
{
|
||||
|
|
|
@ -74,6 +74,9 @@ QSK_QT_PRIVATE_END
|
|||
#include "QskStatusIndicator.h"
|
||||
#include "QskStatusIndicatorSkinlet.h"
|
||||
|
||||
#include "QskValueBar.h"
|
||||
#include "QskValueBarSkinlet.h"
|
||||
|
||||
static inline QskSkinlet* qskNewSkinlet( const QMetaObject* metaObject, QskSkin* skin )
|
||||
{
|
||||
const QByteArray signature = metaObject->className() + QByteArrayLiteral( "(QskSkin*)" );
|
||||
|
@ -148,6 +151,7 @@ QskSkin::QskSkin( QObject* parent )
|
|||
declareSkinlet< QskTabView, QskTabViewSkinlet >();
|
||||
declareSkinlet< QskTextLabel, QskTextLabelSkinlet >();
|
||||
declareSkinlet< QskTextInput, QskTextInputSkinlet >();
|
||||
declareSkinlet< QskValueBar, QskValueBarSkinlet >();
|
||||
|
||||
const QFont font = QGuiApplication::font();
|
||||
setupFonts( font.family(), font.weight(), font.italic() );
|
||||
|
|
|
@ -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"
|
|
@ -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
|
|
@ -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"
|
|
@ -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
|
|
@ -177,6 +177,8 @@ HEADERS += \
|
|||
controls/QskTextInputSkinlet.h \
|
||||
controls/QskTextLabel.h \
|
||||
controls/QskTextLabelSkinlet.h \
|
||||
controls/QskValueBar.h \
|
||||
controls/QskValueBarSkinlet.h \
|
||||
controls/QskVariantAnimator.h \
|
||||
controls/QskWindow.h
|
||||
|
||||
|
@ -248,6 +250,8 @@ SOURCES += \
|
|||
controls/QskTextInputSkinlet.cpp \
|
||||
controls/QskTextLabel.cpp \
|
||||
controls/QskTextLabelSkinlet.cpp \
|
||||
controls/QskValueBar.cpp \
|
||||
controls/QskValueBarSkinlet.cpp \
|
||||
controls/QskVariantAnimator.cpp \
|
||||
controls/QskWindow.cpp
|
||||
|
||||
|
|
Loading…
Reference in New Issue