mycontrols example added
This commit is contained in:
parent
9989ae85d3
commit
2b789b157b
@ -8,6 +8,7 @@ SUBDIRS += \
|
|||||||
layouts \
|
layouts \
|
||||||
listbox \
|
listbox \
|
||||||
messagebox \
|
messagebox \
|
||||||
|
mycontrols \
|
||||||
sliders \
|
sliders \
|
||||||
thumbnails \
|
thumbnails \
|
||||||
tabview
|
tabview
|
||||||
|
223
examples/mycontrols/MySkin.cpp
Normal file
223
examples/mycontrols/MySkin.cpp
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* This file may be used under the terms of the 3-clause BSD License
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "MySkin.h"
|
||||||
|
|
||||||
|
#include "MyToggleButton.h"
|
||||||
|
#include "MyToggleButtonSkinlet.h"
|
||||||
|
|
||||||
|
#include <QskSkin.h>
|
||||||
|
#include <QskAnimationHint.h>
|
||||||
|
#include <QskSetup.h>
|
||||||
|
|
||||||
|
#include <QskBoxBorderMetrics.h>
|
||||||
|
#include <QskBoxShapeMetrics.h>
|
||||||
|
#include <QskBoxBorderColors.h>
|
||||||
|
#include <QskGradient.h>
|
||||||
|
#include <QskRgbValue.h>
|
||||||
|
#include <QskColorFilter.h>
|
||||||
|
|
||||||
|
#include <QskBox.h>
|
||||||
|
#include <QskBoxSkinlet.h>
|
||||||
|
|
||||||
|
#include <QskFocusIndicator.h>
|
||||||
|
#include <QskFocusIndicatorSkinlet.h>
|
||||||
|
|
||||||
|
class MySkin : public QskSkin
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum GraphicRole
|
||||||
|
{
|
||||||
|
GraphicRoleNormal,
|
||||||
|
GraphicRoleInverted
|
||||||
|
};
|
||||||
|
|
||||||
|
MySkin()
|
||||||
|
{
|
||||||
|
declareSkinlet< QskBox, QskBoxSkinlet >();
|
||||||
|
declareSkinlet< QskFocusIndicator, QskFocusIndicatorSkinlet >();
|
||||||
|
declareSkinlet< MyToggleButton, MyToggleButtonSkinlet >();
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
setGradient( QskAspect::Control, Qt::gray );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void initFocusIndicatorHints(
|
||||||
|
qreal border, qreal radius, qreal padding, QRgb rgb )
|
||||||
|
{
|
||||||
|
const auto subControl = QskFocusIndicator::Panel;
|
||||||
|
|
||||||
|
setBoxBorderMetrics( subControl, border );
|
||||||
|
setBoxShape( subControl, radius );
|
||||||
|
setMargins( subControl | QskAspect::Padding, padding );
|
||||||
|
setGradient( subControl, Qt::transparent );
|
||||||
|
|
||||||
|
setBoxBorderColors( subControl, rgb );
|
||||||
|
}
|
||||||
|
|
||||||
|
void initBoxHints(
|
||||||
|
qreal border, qreal radius,
|
||||||
|
const QskBoxBorderColors& borderColors,
|
||||||
|
const QskGradient& fillColor )
|
||||||
|
{
|
||||||
|
const auto subControl = QskBox::Panel;
|
||||||
|
|
||||||
|
setBoxBorderMetrics( subControl, border );
|
||||||
|
setBoxShape( subControl, radius );
|
||||||
|
setBoxBorderColors( subControl, borderColors );
|
||||||
|
setGradient( subControl, fillColor );
|
||||||
|
setMargins( subControl | QskAspect::Padding, 0.5 * radius );
|
||||||
|
}
|
||||||
|
|
||||||
|
void initToggleButtonHints(
|
||||||
|
qreal width, qreal height, qreal radius,
|
||||||
|
QRgb baseColor, QRgb baseTextColor,
|
||||||
|
QRgb foregroundColor, QRgb foregroundTextColor )
|
||||||
|
{
|
||||||
|
using namespace QskAspect;
|
||||||
|
using Q = MyToggleButton;
|
||||||
|
|
||||||
|
for( auto subControl : { Q::UncheckedLabel, Q::CheckedLabel } )
|
||||||
|
{
|
||||||
|
QColor color1 = foregroundTextColor;
|
||||||
|
QColor color2 = baseTextColor;
|
||||||
|
|
||||||
|
if( subControl == Q::UncheckedLabel )
|
||||||
|
{
|
||||||
|
std::swap( color1, color2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
setColor( subControl | Q::Checked, color1 );
|
||||||
|
setColor( subControl, color2 );
|
||||||
|
|
||||||
|
setSkinHint( subControl | Alignment, Qt::AlignCenter );
|
||||||
|
setAnimation( subControl | Color, animator() );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( auto subControl : { Q::UncheckedIcon, Q::CheckedIcon } )
|
||||||
|
{
|
||||||
|
int role1 = MySkin::GraphicRoleNormal;
|
||||||
|
int role2 = MySkin::GraphicRoleInverted;
|
||||||
|
|
||||||
|
if( subControl == Q::UncheckedIcon )
|
||||||
|
{
|
||||||
|
std::swap( role1, role2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
setGraphicRole( subControl, role1 );
|
||||||
|
setGraphicRole( subControl | Q::Checked, role2 );
|
||||||
|
|
||||||
|
setAnimation( subControl | Flag, animator() );
|
||||||
|
}
|
||||||
|
|
||||||
|
setGradient( Q::Panel, baseColor );
|
||||||
|
setBoxBorderColors( Q::Panel, QColor( baseColor ).dark( 120 ) );
|
||||||
|
|
||||||
|
setGradient( Q::Cursor, foregroundColor );
|
||||||
|
setBoxBorderColors( Q::Cursor, QColor( foregroundColor ).dark( 120 ) );
|
||||||
|
|
||||||
|
for( auto subControl : { Q::Panel, Q::Cursor } )
|
||||||
|
{
|
||||||
|
setMetric( subControl | MinimumWidth, width );
|
||||||
|
setMetric( subControl | MinimumHeight, height );
|
||||||
|
setMargins( subControl | Padding, -4 );
|
||||||
|
|
||||||
|
setBoxShape( subControl, radius );
|
||||||
|
setBoxBorderMetrics( subControl, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
setMargins( Q::CheckedPanel | Padding, 10 );
|
||||||
|
setMargins( Q::UncheckedPanel | Padding, 10 );
|
||||||
|
|
||||||
|
for( auto state : { NoState, Q::Disabled } )
|
||||||
|
{
|
||||||
|
const auto aspect = Q::Cursor | state | Position;
|
||||||
|
|
||||||
|
setMetric( aspect | Q::Checked, 0 );
|
||||||
|
setMetric( aspect, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
setAnimation( Q::Cursor | Metric, animator() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void setGraphicFilter( int role, QRgb rgb )
|
||||||
|
{
|
||||||
|
QskColorFilter filter;
|
||||||
|
filter.addColorSubstitution( QskRgbValue::Khaki, rgb );
|
||||||
|
|
||||||
|
QskSkin::setGraphicFilter( role, filter );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
virtual QskAnimationHint animator() const
|
||||||
|
{
|
||||||
|
return QskAnimationHint( 200 );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class MySkin1 : public MySkin
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MySkin1()
|
||||||
|
{
|
||||||
|
using namespace QskRgbValue;
|
||||||
|
|
||||||
|
setGraphicFilter( GraphicRoleNormal, QskRgbValue::Crimson );
|
||||||
|
setGraphicFilter( GraphicRoleInverted, QskRgbValue::Gold );
|
||||||
|
|
||||||
|
initFocusIndicatorHints( 2, 3, 6, Teal );
|
||||||
|
initBoxHints( 2, 8, DarkCyan, LightCyan );
|
||||||
|
initToggleButtonHints( 150, 120, 6,
|
||||||
|
AliceBlue, Black, CornflowerBlue, White );
|
||||||
|
}
|
||||||
|
|
||||||
|
QskAnimationHint animator() const override
|
||||||
|
{
|
||||||
|
return QskAnimationHint( 200 );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class MySkin2 : public MySkin
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MySkin2()
|
||||||
|
{
|
||||||
|
using namespace QskRgbValue;
|
||||||
|
|
||||||
|
setGraphicFilter( GraphicRoleNormal, QskRgbValue::HotPink );
|
||||||
|
setGraphicFilter( GraphicRoleInverted, QskRgbValue::White );
|
||||||
|
|
||||||
|
initFocusIndicatorHints( 2, 6, 6, Crimson );
|
||||||
|
initBoxHints( 4, 30, LightPink, MistyRose );
|
||||||
|
initToggleButtonHints( 130, 100, 40,
|
||||||
|
Linen, Black, HotPink, White );
|
||||||
|
}
|
||||||
|
|
||||||
|
QskAnimationHint animator() const override
|
||||||
|
{
|
||||||
|
return QskAnimationHint( 100, QEasingCurve::InQuad );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
QStringList MySkinFactory::skinNames() const
|
||||||
|
{
|
||||||
|
return { QStringLiteral( "MySkin1" ), QStringLiteral( "MySkin2" ) };
|
||||||
|
}
|
||||||
|
|
||||||
|
QskSkin* MySkinFactory::createSkin( const QString& skinName )
|
||||||
|
{
|
||||||
|
if ( skinName == QStringLiteral( "MySkin1" ) )
|
||||||
|
return new MySkin1();
|
||||||
|
|
||||||
|
if ( skinName == QStringLiteral( "MySkin2" ) )
|
||||||
|
return new MySkin2();
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "moc_MySkin.cpp"
|
21
examples/mycontrols/MySkin.h
Normal file
21
examples/mycontrols/MySkin.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* This file may be used under the terms of the 3-clause BSD License
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef MY_SKIN_H
|
||||||
|
#define MY_SKIN_H
|
||||||
|
|
||||||
|
#include <QskSkinFactory.h>
|
||||||
|
|
||||||
|
class MySkinFactory : public QskSkinFactory
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
using Inherited = QskSkinFactory;
|
||||||
|
|
||||||
|
public:
|
||||||
|
QStringList skinNames() const override;
|
||||||
|
QskSkin* createSkin( const QString& skinName ) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
236
examples/mycontrols/MyToggleButton.cpp
Normal file
236
examples/mycontrols/MyToggleButton.cpp
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* This file may be used under the terms of the 3-clause BSD License
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "MyToggleButton.h"
|
||||||
|
|
||||||
|
#include <QskAspect.h>
|
||||||
|
#include <QskGraphic.h>
|
||||||
|
#include <QskGraphicProvider.h>
|
||||||
|
#include <QskTextOptions.h>
|
||||||
|
|
||||||
|
QSK_SUBCONTROL( MyToggleButton, Panel )
|
||||||
|
QSK_SUBCONTROL( MyToggleButton, Cursor )
|
||||||
|
QSK_SUBCONTROL( MyToggleButton, CheckedPanel )
|
||||||
|
QSK_SUBCONTROL( MyToggleButton, CheckedLabel )
|
||||||
|
QSK_SUBCONTROL( MyToggleButton, UncheckedPanel )
|
||||||
|
QSK_SUBCONTROL( MyToggleButton, UncheckedLabel )
|
||||||
|
QSK_SUBCONTROL( MyToggleButton, CheckedIcon )
|
||||||
|
QSK_SUBCONTROL( MyToggleButton, UncheckedIcon )
|
||||||
|
|
||||||
|
class MyToggleButton::PrivateData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
QString text;
|
||||||
|
|
||||||
|
QString iconSource;
|
||||||
|
QskGraphic icon;
|
||||||
|
bool iconDirty = false;
|
||||||
|
|
||||||
|
} content[ 2 ];
|
||||||
|
|
||||||
|
QskTextOptions textOptions;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Normal: Checked: left, Unchecked : right
|
||||||
|
Inverted: Checked: right, Unchecked : left
|
||||||
|
*/
|
||||||
|
bool inverted = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
MyToggleButton::MyToggleButton( QQuickItem* parent )
|
||||||
|
: Inherited( parent )
|
||||||
|
, m_data( new PrivateData() )
|
||||||
|
{
|
||||||
|
setCheckable( true );
|
||||||
|
setAcceptHoverEvents( false );
|
||||||
|
|
||||||
|
initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
|
||||||
|
}
|
||||||
|
|
||||||
|
MyToggleButton::MyToggleButton(
|
||||||
|
const QString& checkedIcon, const QString& uncheckedIcon, QQuickItem* parent )
|
||||||
|
: MyToggleButton( parent )
|
||||||
|
{
|
||||||
|
if ( !uncheckedIcon.isEmpty() )
|
||||||
|
{
|
||||||
|
auto& data = m_data->content[ UncheckedSection ];
|
||||||
|
|
||||||
|
data.iconSource = uncheckedIcon;
|
||||||
|
data.iconDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !checkedIcon.isEmpty() )
|
||||||
|
{
|
||||||
|
auto& data = m_data->content[ CheckedSection ];
|
||||||
|
|
||||||
|
data.iconSource = checkedIcon;
|
||||||
|
data.iconDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MyToggleButton::~MyToggleButton()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyToggleButton::setInverted( bool on )
|
||||||
|
{
|
||||||
|
if ( m_data->inverted != on )
|
||||||
|
{
|
||||||
|
m_data->inverted = on;
|
||||||
|
update();
|
||||||
|
|
||||||
|
Q_EMIT invertedChanged( on );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MyToggleButton::isInverted() const
|
||||||
|
{
|
||||||
|
return m_data->inverted;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyToggleButton::setTextOptions( const QskTextOptions& options )
|
||||||
|
{
|
||||||
|
if( options != m_data->textOptions )
|
||||||
|
{
|
||||||
|
m_data->textOptions = options;
|
||||||
|
|
||||||
|
if( !( m_data->content[ 0 ].text.isEmpty() && m_data->content[ 1 ].text.isEmpty() ) )
|
||||||
|
{
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QskTextOptions MyToggleButton::textOptions() const
|
||||||
|
{
|
||||||
|
return m_data->textOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyToggleButton::setTextAt( int index, const QString& text )
|
||||||
|
{
|
||||||
|
if( index < 0 || index > 1 )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& data = m_data->content[ index ];
|
||||||
|
|
||||||
|
if( !data.icon.isNull() )
|
||||||
|
{
|
||||||
|
// we don't support text + graphic
|
||||||
|
data.icon.reset();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
data.iconDirty = false;
|
||||||
|
|
||||||
|
if( text != data.text )
|
||||||
|
{
|
||||||
|
data.text = text;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString MyToggleButton::textAt( int index ) const
|
||||||
|
{
|
||||||
|
if( index < 0 || index > 1 )
|
||||||
|
{
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_data->content[ index ].text;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyToggleButton::setIconAt( int index, const QString& icon )
|
||||||
|
{
|
||||||
|
if( index < 0 || index > 1 )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& data = m_data->content[ index ];
|
||||||
|
|
||||||
|
if( !data.text.isEmpty() )
|
||||||
|
{
|
||||||
|
// we don't support text + graphic
|
||||||
|
data.text.clear();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( icon != data.iconSource )
|
||||||
|
{
|
||||||
|
data.icon.reset();
|
||||||
|
data.iconSource = icon;
|
||||||
|
data.iconDirty = true;
|
||||||
|
|
||||||
|
polish();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString MyToggleButton::iconAt( int index ) const
|
||||||
|
{
|
||||||
|
if( index < 0 || index > 1 )
|
||||||
|
{
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_data->content[ index ].iconSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
QskGraphic MyToggleButton::graphicAt( int index ) const
|
||||||
|
{
|
||||||
|
if( index < 0 || index > 1 )
|
||||||
|
{
|
||||||
|
return QskGraphic();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& data = const_cast< MyToggleButton* >( this )->m_data->content[ index ];
|
||||||
|
|
||||||
|
if( data.iconDirty )
|
||||||
|
{
|
||||||
|
data.icon = Qsk::loadGraphic( data.iconSource );
|
||||||
|
data.iconDirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSizeF MyToggleButton::contentsSizeHint() const
|
||||||
|
{
|
||||||
|
const qreal width = metric( Panel | QskAspect::MinimumWidth );
|
||||||
|
const qreal height = metric( Panel | QskAspect::MinimumHeight );
|
||||||
|
|
||||||
|
return QSizeF( width, height );
|
||||||
|
}
|
||||||
|
|
||||||
|
// better use Minimum Width/Height hints TODO ...
|
||||||
|
|
||||||
|
static constexpr qreal aspectRatio = 4.0 / 3.0;
|
||||||
|
|
||||||
|
qreal MyToggleButton::heightForWidth( qreal width ) const
|
||||||
|
{
|
||||||
|
return width / aspectRatio;
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal MyToggleButton::widthForHeight( qreal height ) const
|
||||||
|
{
|
||||||
|
return height * aspectRatio;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyToggleButton::updateLayout()
|
||||||
|
{
|
||||||
|
for( int i = 0; i < 2; i++ )
|
||||||
|
{
|
||||||
|
if( m_data->content[ i ].iconDirty )
|
||||||
|
{
|
||||||
|
( void )graphicAt( Checked );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "moc_MyToggleButton.cpp"
|
65
examples/mycontrols/MyToggleButton.h
Normal file
65
examples/mycontrols/MyToggleButton.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* This file may be used under the terms of the 3-clause BSD License
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef MY_TOGGLE_BUTTON_H
|
||||||
|
#define MY_TOGGLE_BUTTON_H
|
||||||
|
|
||||||
|
#include <QskAbstractButton.h>
|
||||||
|
|
||||||
|
class QskGraphic;
|
||||||
|
class QskTextOptions;
|
||||||
|
|
||||||
|
class MyToggleButton : public QskAbstractButton
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
using Inherited = QskAbstractButton;
|
||||||
|
|
||||||
|
public:
|
||||||
|
QSK_SUBCONTROLS( Panel, Cursor, CheckedPanel, CheckedLabel, CheckedIcon,
|
||||||
|
UncheckedPanel, UncheckedLabel, UncheckedIcon )
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
UncheckedSection = 0,
|
||||||
|
CheckedSection = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
MyToggleButton( QQuickItem* parent = nullptr );
|
||||||
|
|
||||||
|
MyToggleButton( const QString& ckeckedIcon, const QString& uncheckedIcon,
|
||||||
|
QQuickItem* parent = nullptr );
|
||||||
|
|
||||||
|
~MyToggleButton() override;
|
||||||
|
|
||||||
|
void setTextAt( int index, const QString& );
|
||||||
|
QString textAt( int index ) const;
|
||||||
|
|
||||||
|
void setIconAt( int index, const QString& icon );
|
||||||
|
QString iconAt( int index ) const;
|
||||||
|
|
||||||
|
QSizeF contentsSizeHint() const override;
|
||||||
|
|
||||||
|
qreal heightForWidth( qreal width ) const override;
|
||||||
|
qreal widthForHeight( qreal height ) const override;
|
||||||
|
|
||||||
|
void setTextOptions( const QskTextOptions& );
|
||||||
|
QskTextOptions textOptions() const;
|
||||||
|
|
||||||
|
QskGraphic graphicAt( int index ) const;
|
||||||
|
|
||||||
|
void setInverted( bool );
|
||||||
|
bool isInverted() const;
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void invertedChanged( bool );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void updateLayout() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
class PrivateData;
|
||||||
|
std::unique_ptr< PrivateData > m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
145
examples/mycontrols/MyToggleButtonSkinlet.cpp
Normal file
145
examples/mycontrols/MyToggleButtonSkinlet.cpp
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* This file may be used under the terms of the 3-clause BSD License
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "MyToggleButtonSkinlet.h"
|
||||||
|
#include "MyToggleButton.h"
|
||||||
|
|
||||||
|
#include <QskTextOptions.h>
|
||||||
|
#include <QskGraphic.h>
|
||||||
|
|
||||||
|
static inline QRectF sectionRect( const QRectF& rect, int section )
|
||||||
|
{
|
||||||
|
auto r = rect;
|
||||||
|
|
||||||
|
if ( section == 0 )
|
||||||
|
r.setWidth( 0.5 * rect.width() );
|
||||||
|
else
|
||||||
|
r.setLeft( rect.right() - 0.5 * rect.width() );
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
MyToggleButtonSkinlet::MyToggleButtonSkinlet( QskSkin* skin )
|
||||||
|
: Inherited( skin )
|
||||||
|
{
|
||||||
|
// sorted in stacking order
|
||||||
|
|
||||||
|
setNodeRoles( { PanelRole, CursorRole, UncheckedPanelRole, UncheckedLabelRole,
|
||||||
|
UncheckedIconRole, CheckedPanelRole, CheckedLabelRole, CheckedIconRole
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF MyToggleButtonSkinlet::subControlRect(
|
||||||
|
const QskSkinnable* skinnable, QskAspect::Subcontrol subControl ) const
|
||||||
|
{
|
||||||
|
using Q = MyToggleButton;
|
||||||
|
|
||||||
|
const auto button = static_cast< const MyToggleButton* >( skinnable );
|
||||||
|
|
||||||
|
if( subControl == Q::Panel )
|
||||||
|
{
|
||||||
|
return button->contentsRect();
|
||||||
|
}
|
||||||
|
else if( subControl == Q::UncheckedPanel )
|
||||||
|
{
|
||||||
|
auto rect = innerRect( skinnable, Q::Panel );
|
||||||
|
return sectionRect( rect, button->isInverted() ? 0 : 1 );
|
||||||
|
}
|
||||||
|
else if( subControl == Q::CheckedPanel )
|
||||||
|
{
|
||||||
|
auto rect = innerRect( skinnable, Q::Panel );
|
||||||
|
return sectionRect( rect, button->isInverted() ? 1 : 0 );
|
||||||
|
}
|
||||||
|
else if( subControl == Q::CheckedLabel || subControl == Q::CheckedIcon )
|
||||||
|
{
|
||||||
|
return innerRect( skinnable, Q::CheckedPanel );
|
||||||
|
}
|
||||||
|
else if( subControl == Q::UncheckedLabel || subControl == Q::UncheckedIcon )
|
||||||
|
{
|
||||||
|
return innerRect( skinnable, Q::UncheckedPanel );
|
||||||
|
}
|
||||||
|
else if( subControl == Q::Cursor )
|
||||||
|
{
|
||||||
|
auto position = skinnable->metric( Q::Cursor | QskAspect::Position );
|
||||||
|
if ( button->isInverted() )
|
||||||
|
position = 1.0 - position;
|
||||||
|
|
||||||
|
auto rect = innerRect( skinnable, Q::Panel );
|
||||||
|
|
||||||
|
rect.setWidth( 0.5 * rect.width() );
|
||||||
|
rect.moveLeft( rect.left() + position * rect.width() );
|
||||||
|
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Inherited::subControlRect( skinnable, subControl );
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF MyToggleButtonSkinlet::innerRect(
|
||||||
|
const QskSkinnable* skinnable, QskAspect::Subcontrol subControl ) const
|
||||||
|
{
|
||||||
|
return skinnable->innerBox( subControl, subControlRect( skinnable, subControl ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
QSGNode* MyToggleButtonSkinlet::updateSubNode(
|
||||||
|
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
|
||||||
|
{
|
||||||
|
using Q = MyToggleButton;
|
||||||
|
|
||||||
|
const auto button = static_cast< const Q* >( skinnable );
|
||||||
|
|
||||||
|
switch( nodeRole )
|
||||||
|
{
|
||||||
|
case PanelRole:
|
||||||
|
{
|
||||||
|
return updateBoxNode( button, node, Q::Panel );
|
||||||
|
}
|
||||||
|
|
||||||
|
case CheckedLabelRole:
|
||||||
|
{
|
||||||
|
return updateTextNode(
|
||||||
|
button, node, button->textAt( Q::CheckedSection ),
|
||||||
|
button->textOptions(), Q::CheckedLabel );
|
||||||
|
}
|
||||||
|
|
||||||
|
case UncheckedLabelRole:
|
||||||
|
{
|
||||||
|
return updateTextNode(
|
||||||
|
button, node, button->textAt( Q::UncheckedSection ),
|
||||||
|
button->textOptions(), Q::UncheckedLabel );
|
||||||
|
}
|
||||||
|
|
||||||
|
case CheckedIconRole:
|
||||||
|
{
|
||||||
|
return updateGraphicNode(
|
||||||
|
button, node, button->graphicAt( Q::CheckedSection ), Q::CheckedIcon );
|
||||||
|
}
|
||||||
|
|
||||||
|
case UncheckedIconRole:
|
||||||
|
{
|
||||||
|
return updateGraphicNode(
|
||||||
|
button, node, button->graphicAt( Q::UncheckedSection ), Q::UncheckedIcon );
|
||||||
|
}
|
||||||
|
|
||||||
|
case CheckedPanelRole:
|
||||||
|
case UncheckedPanelRole:
|
||||||
|
{
|
||||||
|
// not implemented
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CursorRole:
|
||||||
|
{
|
||||||
|
return updateBoxNode( button, node, Q::Cursor );
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "moc_MyToggleButtonSkinlet.cpp"
|
46
examples/mycontrols/MyToggleButtonSkinlet.h
Normal file
46
examples/mycontrols/MyToggleButtonSkinlet.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* This file may be used under the terms of the 3-clause BSD License
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef MY_TOGGLE_BUTTON_SKINLET_H
|
||||||
|
#define MY_TOGGLE_BUTTON_SKINLET_H
|
||||||
|
|
||||||
|
#include <QskSkinlet.h>
|
||||||
|
|
||||||
|
class MyToggleButton;
|
||||||
|
|
||||||
|
class MyToggleButtonSkinlet : public QskSkinlet
|
||||||
|
{
|
||||||
|
Q_GADGET
|
||||||
|
|
||||||
|
using Inherited = QskSkinlet;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum NodeRole
|
||||||
|
{
|
||||||
|
PanelRole,
|
||||||
|
CursorRole,
|
||||||
|
|
||||||
|
CheckedPanelRole,
|
||||||
|
CheckedLabelRole,
|
||||||
|
CheckedIconRole,
|
||||||
|
|
||||||
|
UncheckedPanelRole,
|
||||||
|
UncheckedLabelRole,
|
||||||
|
UncheckedIconRole
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_INVOKABLE MyToggleButtonSkinlet( QskSkin* = nullptr );
|
||||||
|
~MyToggleButtonSkinlet() override = default;
|
||||||
|
|
||||||
|
QRectF subControlRect( const QskSkinnable*, QskAspect::Subcontrol ) const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QSGNode* updateSubNode( const QskSkinnable*, quint8 nodeRole, QSGNode* ) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QRectF innerRect( const QskSkinnable*, QskAspect::Subcontrol ) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
145
examples/mycontrols/main.cpp
Normal file
145
examples/mycontrols/main.cpp
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* This file may be used under the terms of the 3-clause BSD License
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "MySkin.h"
|
||||||
|
#include "MyToggleButton.h"
|
||||||
|
|
||||||
|
#include <SkinnyFont.h>
|
||||||
|
#include <SkinnyShapeProvider.h>
|
||||||
|
#include <SkinnyShortcut.h>
|
||||||
|
|
||||||
|
#include <QskWindow.h>
|
||||||
|
#include <QskObjectCounter.h>
|
||||||
|
#include <QskFocusIndicator.h>
|
||||||
|
#include <QskBox.h>
|
||||||
|
#include <QskLinearBox.h>
|
||||||
|
#include <QskSkinManager.h>
|
||||||
|
#include <QskSkinTransition.h>
|
||||||
|
#include <QskSetup.h>
|
||||||
|
#include <QskSkin.h>
|
||||||
|
|
||||||
|
#include <QGuiApplication>
|
||||||
|
|
||||||
|
/*
|
||||||
|
This example is intended to show how to:
|
||||||
|
|
||||||
|
- implement custom controls
|
||||||
|
- set up skins, customizing these controls
|
||||||
|
|
||||||
|
For demonstration purposes we limit the set of controls
|
||||||
|
being used:
|
||||||
|
|
||||||
|
- QskPushButton
|
||||||
|
- QskBox
|
||||||
|
- QskFocusIndicator
|
||||||
|
- MyToggleButton
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ContentBox : public QskBox
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ContentBox( QQuickItem* parent = nullptr )
|
||||||
|
: QskBox( parent )
|
||||||
|
{
|
||||||
|
setAutoLayoutChildren( true );
|
||||||
|
|
||||||
|
auto layout = new QskLinearBox( Qt::Horizontal, 2, this );
|
||||||
|
layout->setMargins( 10 );
|
||||||
|
layout->setSpacing( 10 );
|
||||||
|
layout->setDefaultAlignment( Qt::AlignCenter );
|
||||||
|
layout->setExtraSpacingAt( Qt::BottomEdge );
|
||||||
|
|
||||||
|
{
|
||||||
|
auto button = new MyToggleButton( layout );
|
||||||
|
button->setTextAt( 0, "On" );
|
||||||
|
button->setTextAt( 1, "Off" );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto button = new MyToggleButton( layout );
|
||||||
|
button->setIconAt( 0, "image://shapes/Ring/Khaki" );
|
||||||
|
button->setIconAt( 1, "image://shapes/Diamond/Khaki" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Window : public QskWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
Window()
|
||||||
|
{
|
||||||
|
auto button = new MyToggleButton();
|
||||||
|
button->setTextAt( 0, "Skin 1" );
|
||||||
|
button->setTextAt( 1, "Skin 2" );
|
||||||
|
|
||||||
|
auto box = new QskLinearBox( Qt::Vertical );
|
||||||
|
|
||||||
|
box->setMargins( 20 );
|
||||||
|
box->addItem( button, Qt::AlignRight );
|
||||||
|
box->addItem( new ContentBox() );
|
||||||
|
|
||||||
|
connect( button, &MyToggleButton::toggled,
|
||||||
|
this, &Window::setAlternativeSkin );
|
||||||
|
|
||||||
|
setAlternativeSkin( button->isChecked() );
|
||||||
|
|
||||||
|
addItem( box );
|
||||||
|
addItem( new QskFocusIndicator() );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setAlternativeSkin( bool on )
|
||||||
|
{
|
||||||
|
const auto skinNames = qskSkinManager->skinNames();
|
||||||
|
|
||||||
|
auto oldSkin = qskSetup->skin();
|
||||||
|
if ( oldSkin->parent() == qskSetup )
|
||||||
|
oldSkin->setParent( nullptr ); // otherwise setSkin deletes it
|
||||||
|
|
||||||
|
auto newSkin = qskSetup->setSkin( skinNames[ on ? 1 : 0 ] );
|
||||||
|
|
||||||
|
QskSkinTransition transition;
|
||||||
|
|
||||||
|
transition.setSourceSkin( oldSkin );
|
||||||
|
transition.setTargetSkin( newSkin );
|
||||||
|
transition.setAnimation( 600 );
|
||||||
|
|
||||||
|
transition.process();
|
||||||
|
|
||||||
|
if ( oldSkin->parent() == nullptr )
|
||||||
|
delete oldSkin;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main( int argc, char* argv[] )
|
||||||
|
{
|
||||||
|
#ifdef ITEM_STATISTICS
|
||||||
|
QskObjectCounter counter( true );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QGuiApplication app( argc, argv );
|
||||||
|
|
||||||
|
SkinnyFont::init( &app );
|
||||||
|
SkinnyShortcut::enable( SkinnyShortcut::DebugBackground |
|
||||||
|
SkinnyShortcut::DebugStatistics | SkinnyShortcut::Quit );
|
||||||
|
|
||||||
|
Qsk::addGraphicProvider( "shapes", new SkinnyShapeProvider() );
|
||||||
|
|
||||||
|
qskSkinManager->setPluginPaths( QStringList() ); // no plugins
|
||||||
|
qskSkinManager->registerFactory(
|
||||||
|
QStringLiteral( "MySkinFactory" ), new MySkinFactory() );
|
||||||
|
|
||||||
|
qskSetup->setControlFlag( QskSetup::PreferRasterForTextures, true );
|
||||||
|
|
||||||
|
Window window;
|
||||||
|
window.resize( 480, 360 );
|
||||||
|
window.show();
|
||||||
|
|
||||||
|
return app.exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "main.moc"
|
14
examples/mycontrols/mycontrols.pro
Normal file
14
examples/mycontrols/mycontrols.pro
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
include( $${PWD}/../example.pri )
|
||||||
|
|
||||||
|
TARGET = mycontrols
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
MySkin.cpp \
|
||||||
|
MyToggleButton.cpp \
|
||||||
|
MyToggleButtonSkinlet.cpp \
|
||||||
|
main.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
MyToggleButton.h \
|
||||||
|
MyToggleButtonSkinlet.h \
|
||||||
|
MySkin.h
|
Loading…
x
Reference in New Issue
Block a user