Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add QskTickmarksMetrics / QskGraduationMetrics #347

Closed
wants to merge 16 commits into from
Closed
147 changes: 130 additions & 17 deletions examples/mycontrols/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,19 @@
#include <QskSkinTransition.h>
#include <QskSetup.h>
#include <QskSkin.h>
#include <QskSkinlet.h>
#include <QskSGNode.h>
#include <QskGraduationMetrics.h>
#include <QskTickmarksNode.h>
#include <QskScaleTickmarks.h>
#include <QskTextLabel.h>
#include <QskAnimator.h>
#include <QskGraduationMetrics.h>

#include <QGuiApplication>

#include <qmath.h>

/*
This example is intended to show how to:

Expand Down Expand Up @@ -72,31 +82,132 @@ class ContentBox : public QskBox
}
};

class Window : public QskWindow
struct Tickmarks final : public QskControl
{
public:
Window()
{
auto button = new MyToggleButton();
QSK_SUBCONTROLS(Ticks)
using QskControl::QskControl;
};

QSK_SUBCONTROL(Tickmarks, Ticks)

button->setText( false, alternativeSkin( false ) );
button->setText( true, alternativeSkin( true ) );
button->setLayoutAlignmentHint( Qt::AlignRight );
class TickmarksSkinlet final : public QskSkinlet
{
Q_GADGET
public:
enum NodeRoles
{
TickmarksRole
};

auto box = new QskLinearBox( Qt::Vertical );
Q_INVOKABLE TickmarksSkinlet(QskSkin* skin = nullptr) : QskSkinlet(skin)
{
setNodeRoles( { TickmarksRole } );
}

box->setMargins( 20 );
box->addItem( button );
box->addSpacer( 10 );
box->addItem( new ContentBox() );
QSGNode* updateSubNode( const QskSkinnable* const skinnable, const quint8 nodeRole, QSGNode* const node ) const override
{
const auto* const q = static_cast< const Tickmarks* >( skinnable );

connect( button, &MyToggleButton::toggled,
this, &Window::setAlternativeSkin );
if(nodeRole == TickmarksRole)
{
auto* const tickmarksNode = QskSGNode::ensureNode<QskTickmarksNode>(node);

const auto rect = q->contentsRect();

QskScaleTickmarks tickmarks;
QVector<qreal> major, medium, minor;
for ( int i = -100; i <= +100; ++i )
{
if(i % 50 == 0) major << i;
else if(i % 10 == 0) medium << i;
else minor << i;
}
tickmarks.setMajorTicks(major);
tickmarks.setMediumTicks(medium);
tickmarks.setMinorTicks(minor);

const auto metric = q->graduationMetricsHint(Tickmarks::Ticks);
tickmarksNode->update(
Qt::darkGray, rect, { -100, +100 }, tickmarks, 1, Qt::Horizontal, Qt::AlignBottom, metric );

return tickmarksNode;
}

setAlternativeSkin( button->isChecked() );
return nullptr;
}
};

addItem( box );
addItem( new QskFocusIndicator() );
class Window : public QskWindow
{
public:
Window()
{
auto* const layout = new QskLinearBox(Qt::Vertical, contentItem());
{
(void) new QskTextLabel("Default", layout);
auto* const tickmarks = new Tickmarks(layout);
auto* const skinlet = new TickmarksSkinlet;
tickmarks->setSkinlet(skinlet);
skinlet->setOwnedBySkinnable(true);
}
{
(void) new QskTextLabel("Custom", layout);
auto* const tickmarks = new Tickmarks(layout);
tickmarks->setGraduationMetricsHint(Tickmarks::Ticks, { 0.2, 0.5, 1.0 } );
auto* const skinlet = new TickmarksSkinlet;
tickmarks->setSkinlet(skinlet);
skinlet->setOwnedBySkinnable(true);
}
{
(void) new QskTextLabel("Custom (Major only)", layout);
auto* const tickmarks = new Tickmarks(layout);
tickmarks->setGraduationMetricsHint(Tickmarks::Ticks, { 0.0, 0.0, 1.0 } );
auto* const skinlet = new TickmarksSkinlet;
tickmarks->setSkinlet(skinlet);
skinlet->setOwnedBySkinnable(true);
}
{
(void) new QskTextLabel("Custom (Major + Minor only)", layout);
auto* const tickmarks = new Tickmarks(layout);
tickmarks->setGraduationMetricsHint(Tickmarks::Ticks, { 0.2, 0.0, 1.0 } );
auto* const skinlet = new TickmarksSkinlet;
tickmarks->setSkinlet(skinlet);
skinlet->setOwnedBySkinnable(true);
}
{
(void) new QskTextLabel("Custom (Animated)", layout);
auto* const tickmarks = new Tickmarks(layout);
auto* const skinlet = new TickmarksSkinlet;
tickmarks->setSkinlet(skinlet);
skinlet->setOwnedBySkinnable(true);

class Animator final : public QskAnimator
{
public:
explicit Animator(Tickmarks& tickmarks) : tickmarks(tickmarks)
{
setAutoRepeat(true);
setDuration(2000);
}

void advance( qreal value ) override
{
const QskGraduationMetrics metrics {
( 0.1 + 0.1 * qFastSin( value * 2 * M_PI ) ),
( 0.25 + 0.25 * qFastSin( value * 2 * M_PI ) ),
( 0.5 + 0.5 * qFastSin( value * 2 * M_PI ) )
};
tickmarks.setGraduationMetricsHint(Tickmarks::Ticks, metrics);
}

Tickmarks& tickmarks;
};

auto* const animator = new Animator(*tickmarks);
animator->setWindow(this);
animator->start();
}
}

private:
Expand Down Expand Up @@ -154,3 +265,5 @@ int main( int argc, char* argv[] )

return app.exec();
}

#include "main.moc"
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ list(APPEND HEADERS
nodes/QskTextRenderer.h
nodes/QskTextureRenderer.h
nodes/QskTickmarksNode.h
nodes/QskGraduationMetrics.h
nodes/QskVertex.h
)

Expand Down Expand Up @@ -154,6 +155,7 @@ list(APPEND SOURCES
nodes/QskTextRenderer.cpp
nodes/QskTextureRenderer.cpp
nodes/QskTickmarksNode.cpp
nodes/QskGraduationMetrics.cpp
nodes/QskVertex.cpp
)

Expand Down
4 changes: 3 additions & 1 deletion src/common/QskAspect.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ class QSK_EXPORT QskAspect

Shadow,
Shape,
Border
Border,

Tickmarks
};
Q_ENUM( Primitive )

Expand Down
7 changes: 6 additions & 1 deletion src/common/QskFunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ inline QMarginsF qskMargins( const QRectF& rect, const QRectF& innerRect )
rect.bottom() - innerRect.bottom() );
}

inline bool qskFuzzyCompare( qreal value1, qreal value2 )
inline constexpr bool qskFuzzyCompare( qreal value1, qreal value2 )
uwerat marked this conversation as resolved.
Show resolved Hide resolved
{
if ( qFuzzyIsNull( value1 ) )
return qFuzzyIsNull( value2 );
Expand All @@ -69,6 +69,11 @@ inline bool qskFuzzyCompare( qreal value1, qreal value2 )
return qFuzzyCompare( value1, value2 );
}

inline constexpr qreal qskConstrainedRatio( qreal ratio )
{
return qBound( 0.0, ratio, 1.0 );
}

QSK_EXPORT qreal qskFuzzyFloor( qreal value, qreal stepSize );
QSK_EXPORT qreal qskFuzzyCeil( qreal value, qreal stepSize );

Expand Down
18 changes: 18 additions & 0 deletions src/controls/QskSkinnable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "QskBoxBorderColors.h"
#include "QskShadowMetrics.h"
#include "QskStippleMetrics.h"
#include "QskGraduationMetrics.h"
#include "QskBoxHints.h"
#include "QskGradient.h"
#include "QskTextOptions.h"
Expand Down Expand Up @@ -766,6 +767,23 @@ QskGraphic QskSkinnable::symbolHint(
aspect | QskAspect::Symbol, status ).value< QskGraphic >();
}

bool QskSkinnable::setGraduationMetricsHint( const QskAspect aspect, const QskGraduationMetrics& metrics )
{
return setSkinHint( aspect | QskAspect::Tickmarks,
QVariant::fromValue( metrics ) );
}

bool QskSkinnable::resetGraduationMetricsHint( const QskAspect aspect )
{
return resetSkinHint( aspect | QskAspect::Tickmarks );
}

QskGraduationMetrics QskSkinnable::graduationMetricsHint( const QskAspect aspect, QskSkinHintStatus* status) const
{
return effectiveSkinHint(
aspect | QskAspect::Tickmarks, status ).value< QskGraduationMetrics >();
}


QskColorFilter QskSkinnable::effectiveGraphicFilter(
const QskAspect::Subcontrol subControl ) const
Expand Down
5 changes: 5 additions & 0 deletions src/controls/QskSkinnable.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class QskBoxBorderMetrics;
class QskBoxBorderColors;
class QskShadowMetrics;
class QskStippleMetrics;
class QskGraduationMetrics;
class QskTextOptions;
class QskBoxHints;
class QskGradient;
Expand Down Expand Up @@ -257,6 +258,10 @@ class QSK_EXPORT QskSkinnable
bool resetSymbolHint( const QskAspect );
QskGraphic symbolHint( const QskAspect, QskSkinHintStatus* = nullptr ) const;

bool setGraduationMetricsHint( const QskAspect, const QskGraduationMetrics& );
bool resetGraduationMetricsHint( const QskAspect );
QskGraduationMetrics graduationMetricsHint( const QskAspect, QskSkinHintStatus* = nullptr ) const;

const QskSkinHintTable& hintTable() const;

bool startHintTransitions( QskAspect::States, QskAspect::States, int index = -1 );
Expand Down
2 changes: 2 additions & 0 deletions src/controls/QskVariantAnimator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "QskBoxShapeMetrics.h"
#include "QskShadowMetrics.h"
#include "QskStippleMetrics.h"
#include "QskGraduationMetrics.h"
#include "QskColorFilter.h"
#include "QskGradient.h"
#include "QskMargins.h"
Expand Down Expand Up @@ -49,6 +50,7 @@ static void qskRegisterInterpolator()
qRegisterAnimationInterpolator< QskShadowMetrics >( QskShadowMetrics::interpolate );
qRegisterAnimationInterpolator< QskStippleMetrics >( QskStippleMetrics::interpolate );
qRegisterAnimationInterpolator< QskArcMetrics >( QskArcMetrics::interpolate );
qRegisterAnimationInterpolator< QskGraduationMetrics >( QskGraduationMetrics::interpolate );
}

Q_CONSTRUCTOR_FUNCTION( qskRegisterInterpolator )
Expand Down
64 changes: 64 additions & 0 deletions src/nodes/QskGraduationMetrics.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "QskGraduationMetrics.h"

#include <qvariant.h>

static void qskRegisterGraduationMetrics()
{
qRegisterMetaType< QskGraduationMetrics >();

#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
QMetaType::registerEqualsComparator< QskGraduationMetrics >();
#endif
}

Q_CONSTRUCTOR_FUNCTION( qskRegisterGraduationMetrics )

static inline qreal qskInterpolated( qreal from, qreal to, qreal ratio )
{
return from + ( to - from ) * ratio;
}

QskGraduationMetrics QskGraduationMetrics::interpolated(
const QskGraduationMetrics& to, const qreal ratio ) const noexcept
{
if ( ( *this == to ) ) // TODO QskGraduationMetrics::sizeMode
{
return to;
}

return { qskInterpolated( m_minorRatio, to.m_minorRatio, ratio ),
qskInterpolated( m_mediumRatio, to.m_mediumRatio, ratio ),
qskInterpolated( m_majorRatio, to.m_majorRatio, ratio ) };
}

QVariant QskGraduationMetrics::interpolate(
const QskGraduationMetrics& from, const QskGraduationMetrics& to, const qreal progress )
{
return QVariant::fromValue( from.interpolated( to, progress ) );
}

#ifndef QT_NO_DEBUG_STREAM

#include <qdebug.h>

QDebug operator<<( QDebug debug, const QskGraduationMetrics& metrics )
{
QDebugStateSaver saver( debug );
debug.nospace();

debug << "QskGraduationMetrics";
debug << '(';
debug << "minor: ";
debug << metrics.minorRatio();
debug << ',';
debug << "medium: ";
debug << metrics.mediumRatio();
debug << ',';
debug << "major: ";
debug << metrics.majorRatio();
debug << ')';

return debug;
}

#endif
Loading
Loading