qskinny/examples/automotive/SoundControl.cpp

412 lines
11 KiB
C++
Raw Normal View History

2017-07-25 07:24:27 +02:00
#include "SoundControl.h"
#include "SkinFactory.h"
2017-07-25 07:24:27 +02:00
2018-08-03 08:15:28 +02:00
#include <QskBox.h>
2017-07-25 07:24:27 +02:00
#include <QskGraphic.h>
2017-07-25 21:34:27 +02:00
#include <QskGraphicIO.h>
2018-08-03 08:15:28 +02:00
#include <QskGraphicLabel.h>
2017-07-25 07:24:27 +02:00
#include <QskGridBox.h>
#include <QskLinearBox.h>
2018-08-03 08:15:28 +02:00
#include <QskNamespace.h>
2017-07-25 07:24:27 +02:00
#include <QskPushButton.h>
2018-08-03 08:15:28 +02:00
#include <QskSeparator.h>
2017-07-25 07:24:27 +02:00
#include <QskSlider.h>
#include <QskTextLabel.h>
QSK_SUBCONTROL( SoundControl, Overlay )
2017-07-25 21:34:27 +02:00
QSK_SUBCONTROL( SoundControl, CrossHair )
QSK_SUBCONTROL( SoundControl, Marker )
QSK_SUBCONTROL( SoundControl, MarkerControl )
QSK_SUBCONTROL( SoundControl, Vehicle )
2017-07-25 21:34:27 +02:00
QSK_SUBCONTROL( SoundControl, SliderControl )
2017-07-25 07:24:27 +02:00
2018-07-31 17:32:25 +02:00
class VehicleLabel final : public QskGraphicLabel
{
2018-08-03 08:15:28 +02:00
public:
VehicleLabel( QQuickItem* parentItem = nullptr )
: QskGraphicLabel( parentItem )
{
setGraphic( QskGraphicIO::read( QString( ":/qvg/car.qvg" ) ) );
}
2018-07-31 17:32:25 +02:00
QskAspect::Subcontrol effectiveSubcontrol(
QskAspect::Subcontrol subControl ) const override
{
// so that we can set specific colors in the skin
if ( subControl == QskGraphicLabel::Graphic )
return SoundControl::Vehicle;
return subControl;
}
};
2018-07-31 17:32:25 +02:00
class CrossHairLine final : public QskBox
2017-07-25 21:34:27 +02:00
{
2018-08-03 08:15:28 +02:00
public:
CrossHairLine( QQuickItem* parent )
: QskBox( parent )
2017-07-25 21:34:27 +02:00
{
}
2018-07-31 17:32:25 +02:00
QskAspect::Subcontrol effectiveSubcontrol(
QskAspect::Subcontrol subControl ) const override
2017-07-25 21:34:27 +02:00
{
if ( subControl == QskBox::Panel )
return SoundControl::CrossHair;
return subControl;
}
};
2017-07-25 07:24:27 +02:00
2018-07-31 17:32:25 +02:00
class BalanceFadeMarker final : public QskBox
2017-07-25 07:24:27 +02:00
{
2018-08-03 08:15:28 +02:00
public:
BalanceFadeMarker( QQuickItem* parent )
: QskBox( parent )
2017-07-25 21:34:27 +02:00
{
}
2017-07-25 07:24:27 +02:00
2018-07-31 17:32:25 +02:00
QskAspect::Subcontrol effectiveSubcontrol(
QskAspect::Subcontrol subControl ) const override
2017-07-25 21:34:27 +02:00
{
if ( subControl == QskBox::Panel )
return SoundControl::Marker;
2017-07-25 07:24:27 +02:00
2017-07-25 21:34:27 +02:00
return subControl;
}
};
2017-07-25 07:24:27 +02:00
2018-07-31 17:32:25 +02:00
class MarkerControlButton final : public QskPushButton
2017-07-25 07:24:27 +02:00
{
2018-08-03 08:15:28 +02:00
public:
MarkerControlButton( Qsk::Direction direction, QQuickItem* parentItem = nullptr )
: QskPushButton( parentItem )
, m_direction( direction )
2017-07-25 21:34:27 +02:00
{
const char* svgList[] = { "right", "left", "down", "up" };
2017-07-25 07:24:27 +02:00
2017-07-25 21:34:27 +02:00
const QString fileName = QString( ":/qvg/%1.qvg" ).arg( svgList[ direction ] );
setGraphic( QskGraphicIO::read( fileName ) );
setAutoRepeat( true );
setSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
}
QPointF offset() const
{
const qreal off = 5.0;
2018-08-03 08:15:28 +02:00
switch ( m_direction )
2017-07-25 21:34:27 +02:00
{
case Qsk::LeftToRight:
return QPointF( off, 0.0 );
case Qsk::RightToLeft:
return QPointF( -off, 0.0 );
case Qsk::TopToBottom:
return QPointF( 0.0, off );
case Qsk::BottomToTop:
return QPointF( 0.0, -off );
}
return QPointF();
}
2018-07-31 17:32:25 +02:00
QskAspect::Subcontrol effectiveSubcontrol(
QskAspect::Subcontrol subControl ) const override
{
// so that we can set specific colors in the skin
if ( subControl == QskPushButton::Graphic )
return SoundControl::MarkerControl;
return subControl;
}
2018-08-03 08:15:28 +02:00
protected:
2018-07-31 17:32:25 +02:00
QSizeF contentsSizeHint() const override
2017-07-25 21:34:27 +02:00
{
const qreal dim = 100;
if ( m_direction == Qsk::LeftToRight || m_direction == Qsk::RightToLeft )
return QSizeF( 0.5 * dim, dim );
else
return QSizeF( dim, 0.5 * dim );
}
2018-08-03 08:15:28 +02:00
private:
2017-07-25 21:34:27 +02:00
const Qsk::Direction m_direction;
};
2017-07-25 07:24:27 +02:00
2018-07-31 17:32:25 +02:00
class ControlButton final : public QskPushButton
2017-07-25 21:34:27 +02:00
{
2018-08-03 08:15:28 +02:00
public:
ControlButton( const char symbol, QQuickItem* parentItem = nullptr )
: QskPushButton( parentItem )
2017-07-25 21:34:27 +02:00
{
setText( QChar( symbol ) );
setSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
setAutoRepeat( true );
}
2018-07-31 17:32:25 +02:00
QskAspect::Subcontrol effectiveSubcontrol(
2017-07-25 21:34:27 +02:00
QskAspect::Subcontrol subControl ) const override
{
if ( subControl == QskPushButton::Panel )
return SoundControl::SliderControl;
return QskPushButton::effectiveSubcontrol( subControl );
}
2018-07-31 17:32:25 +02:00
QSizeF contentsSizeHint() const override
2017-07-25 21:34:27 +02:00
{
qreal h = QskPushButton::contentsSizeHint().height();
return QSizeF( h, h );
}
};
2018-07-31 17:32:25 +02:00
class StackedControl final : public QskControl
2017-07-25 21:34:27 +02:00
{
2018-08-03 08:15:28 +02:00
public:
StackedControl( QQuickItem* parent = nullptr )
: QskControl( parent )
, m_offset( 0.0, 0.0 )
2017-07-25 07:24:27 +02:00
{
2017-07-25 21:34:27 +02:00
setPolishOnResize( true ); // we have t re-layout the crosshair
setSizePolicy( QskSizePolicy::Expanding, QskSizePolicy::Expanding );
auto horizontalCarRectangle = new CrossHairLine( this );
horizontalCarRectangle->setObjectName( "horizontalBar" );
auto verticalCarRectangle = new CrossHairLine( this );
verticalCarRectangle->setObjectName( "verticalBar" );
2018-08-03 08:15:28 +02:00
( void ) new VehicleLabel( this );
2017-07-25 21:34:27 +02:00
auto marker = new BalanceFadeMarker( this );
marker->setObjectName( "marker" );
2017-07-25 07:24:27 +02:00
}
QPointF offset() const
{
return m_offset;
}
void setOffset( const QPointF& offset )
{
m_offset = offset;
2017-07-25 21:34:27 +02:00
polish();
2017-07-25 07:24:27 +02:00
}
2018-08-03 08:15:28 +02:00
protected:
2018-07-31 17:32:25 +02:00
void updateLayout() override
2017-07-25 07:24:27 +02:00
{
const QRectF cr = contentsRect();
2017-07-25 21:34:27 +02:00
const qreal crossHairSize = 3;
2017-07-25 07:24:27 +02:00
for ( int a = 0; a < children().count(); a++ )
{
2019-02-26 21:49:39 +01:00
auto control = static_cast< QskControl* >( children().at( a ) );
2017-07-25 07:24:27 +02:00
if ( control->objectName() == "verticalBar" )
{
2017-07-25 21:34:27 +02:00
control->setGeometry( cr.center().x(), cr.top(), crossHairSize, cr.height() );
2017-07-25 07:24:27 +02:00
control->setZ( 1 );
}
else if ( control->objectName() == "horizontalBar" )
{
2017-07-25 21:34:27 +02:00
control->setGeometry( cr.left(), cr.center().y(), cr.width(), crossHairSize );
2017-07-25 07:24:27 +02:00
control->setZ( 1 );
}
2017-07-25 21:34:27 +02:00
else if ( control->objectName() == "marker" )
2017-07-25 07:24:27 +02:00
{
2017-07-25 21:34:27 +02:00
qreal size = 31;
control->setPosition(
cr.center() - 0.5 * QPointF( size, size ) + m_offset + QPointF( 1, 1 ) );
2017-07-25 07:24:27 +02:00
control->setSize( QSizeF( size, size ) );
2017-07-25 21:34:27 +02:00
control->setZ( 1 );
2017-07-25 07:24:27 +02:00
}
else
{
2017-07-25 21:34:27 +02:00
control->setGeometry( cr );
2017-07-25 07:24:27 +02:00
}
}
}
2018-08-03 08:15:28 +02:00
private:
2017-07-25 07:24:27 +02:00
QPointF m_offset;
};
2018-07-31 17:32:25 +02:00
class SectionTitleBar final : public QskLinearBox
2017-07-25 21:34:27 +02:00
{
2018-08-03 08:15:28 +02:00
public:
SectionTitleBar( const char* title, QQuickItem* parentItem = nullptr )
: QskLinearBox( Qt::Horizontal, parentItem )
2017-07-25 21:34:27 +02:00
{
setSpacing( 10 );
2019-02-26 21:49:39 +01:00
auto label = new QskTextLabel( title );
2017-07-25 21:34:27 +02:00
label->setSizePolicy( Qt::Horizontal, QskSizePolicy::Fixed );
addItem( new QskSeparator() );
addItem( label );
addItem( new QskSeparator() );
setStretchFactor( 0, 1 );
setStretchFactor( 2, 5 );
}
};
2018-07-31 17:32:25 +02:00
class SliderBox final : public QskLinearBox
2017-07-25 21:34:27 +02:00
{
2018-08-03 08:15:28 +02:00
public:
SliderBox( const char* title, qreal min, qreal max, QQuickItem* parentItem = nullptr )
: QskLinearBox( Qt::Vertical, parentItem )
2017-07-25 21:34:27 +02:00
{
auto label = new QskTextLabel( title );
m_numberLabel = new QskTextLabel();
// don't stretch the labels, so that the layout centers them
label->setSizePolicy( Qt::Horizontal, QskSizePolicy::Fixed );
m_numberLabel->setSizePolicy( Qt::Horizontal, QskSizePolicy::Fixed );
2019-02-26 21:49:39 +01:00
auto plusButton = new ControlButton( '+' );
2017-07-25 21:34:27 +02:00
auto minusButton = new ControlButton( '-' );
m_slider = new QskSlider( Qt::Vertical );
m_slider->setMinimum( min );
m_slider->setMaximum( max );
m_slider->setStepSize( 10 );
2017-07-25 21:34:27 +02:00
// layout
addItem( label );
addItem( m_numberLabel );
addItem( plusButton );
addSpacer( 10 );
addItem( m_slider );
addSpacer( 10 );
addItem( minusButton );
setDefaultAlignment( Qt::AlignCenter );
// finally connect buttons/slider/labels
connect( plusButton, &QskPushButton::pressed,
2017-10-30 14:38:30 +01:00
this, [ this ]() { increment( 1 ); } );
2017-07-25 21:34:27 +02:00
connect( minusButton, &QskPushButton::pressed,
2017-10-30 14:38:30 +01:00
this, [ this ]() { increment( -1 ); } );
2017-07-25 21:34:27 +02:00
connect( m_slider, &QskSlider::valueChanged,
this, &SliderBox::setValue );
}
2018-08-03 08:15:28 +02:00
public Q_SLOTS:
2017-07-25 21:34:27 +02:00
void setValue( qreal value )
{
m_slider->setValue( value );
QString txt;
txt.setNum( m_slider->value(), 'f', 1 );
m_numberLabel->setText( txt );
}
2018-08-03 08:15:28 +02:00
private:
2017-07-25 21:34:27 +02:00
void increment( qreal offset )
{
setValue( m_slider->value() + offset );
}
QskTextLabel* m_numberLabel;
QskSlider* m_slider;
};
2018-07-31 17:32:25 +02:00
class ToneControlBox final : public QskLinearBox
2017-07-25 21:34:27 +02:00
{
2018-08-03 08:15:28 +02:00
public:
ToneControlBox( QQuickItem* parentItem = nullptr )
: QskLinearBox( Qt::Horizontal, parentItem )
2017-07-25 21:34:27 +02:00
{
auto bassControl = new SliderBox( "Bass", 0.0, 40.0, this );
auto treebleControl = new SliderBox( "Treeble", 0.0, 40.0, this );
auto subControl = new SliderBox( "Sub", 0.0, 40.0, this );
bassControl->setValue( 30 );
treebleControl->setValue( 11 );
subControl->setValue( 18 );
}
};
2018-07-31 17:32:25 +02:00
class BalanceFadeControlBox final : public QskGridBox
2017-07-25 21:34:27 +02:00
{
2018-08-03 08:15:28 +02:00
public:
BalanceFadeControlBox( QQuickItem* parentItem = nullptr )
: QskGridBox( parentItem )
2017-07-25 21:34:27 +02:00
{
2018-08-03 08:15:28 +02:00
MarkerControlButton* buttons[ 4 ];
2017-07-25 21:34:27 +02:00
for ( int i = 0; i < 4; i++ )
2018-08-03 08:15:28 +02:00
buttons[ i ] = new MarkerControlButton( static_cast< Qsk::Direction >( i ) );
2017-07-25 21:34:27 +02:00
m_carControl = new StackedControl();
addItem( buttons[ Qsk::RightToLeft ], 1, 0 );
addItem( buttons[ Qsk::BottomToTop ], 0, 0, 1, 3 );
addItem( buttons[ Qsk::LeftToRight ], 1, 2 );
addItem( buttons[ Qsk::TopToBottom ], 2, 0, 1, 3 );
addItem( m_carControl, 1, 1 );
for ( int i = 0; i < 4; i++ )
{
2018-08-03 08:15:28 +02:00
const auto button = buttons[ i ];
2017-07-25 21:34:27 +02:00
setAlignment( button, Qt::AlignCenter );
connect( button, &QskPushButton::pressed,
2017-12-14 09:41:41 +01:00
this, [ this, button ]() { shift( button->offset() ); } );
2017-07-25 21:34:27 +02:00
}
}
void shift( const QPointF& offset )
{
m_carControl->setOffset( m_carControl->offset() + offset );
}
StackedControl* m_carControl;
};
2018-08-03 08:15:28 +02:00
SoundControl::SoundControl( QQuickItem* parent )
: QskBox( parent )
2017-07-25 07:24:27 +02:00
{
setAutoLayoutChildren( true );
auto layout = new QskGridBox( this );
layout->setMargins( QMarginsF( 40, 20, 40, 20 ) );
layout->setVerticalSpacing( 10 );
layout->setHorizontalSpacing( 60 );
layout->setColumnStretchFactor( 0, 1 );
layout->setColumnStretchFactor( 1, 2 );
layout->addItem( new SectionTitleBar( "Tone" ), 0, 0 );
layout->addItem( new ToneControlBox(), 1, 0 );
layout->addItem( new SectionTitleBar( "Balance / Fade" ), 0, 1 );
layout->addItem( new BalanceFadeControlBox(), 1, 1 );
}
2017-07-25 21:34:27 +02:00
QskAspect::Subcontrol SoundControl::effectiveSubcontrol(
QskAspect::Subcontrol subControl ) const
{
if ( subControl == QskBox::Panel )
return SoundControl::Overlay;
2017-07-25 21:34:27 +02:00
return subControl;
2017-07-25 07:24:27 +02:00
}