Add SwitchButton (#121)
This commit is contained in:
parent
02ad876e14
commit
13faf53495
@ -3,6 +3,7 @@ TEMPLATE = subdirs
|
||||
# c++
|
||||
SUBDIRS += \
|
||||
desktop \
|
||||
switchbuttons \
|
||||
gallery \
|
||||
layouts \
|
||||
listbox \
|
||||
|
54
examples/switchbuttons/main.cpp
Normal file
54
examples/switchbuttons/main.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
#include <QGuiApplication>
|
||||
|
||||
#include <QskLinearBox.h>
|
||||
#include <QskSwitchButton.h>
|
||||
#include <QskTextLabel.h>
|
||||
#include <QskWindow.h>
|
||||
|
||||
#include <SkinnyShortcut.h>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
QGuiApplication app( argc, argv );
|
||||
QskWindow window;
|
||||
|
||||
SkinnyShortcut::enable( SkinnyShortcut::Quit |
|
||||
SkinnyShortcut::DebugShortcuts );
|
||||
|
||||
auto vbox = new QskLinearBox(Qt::Vertical);
|
||||
auto hbox = new QskLinearBox(vbox);
|
||||
new QskTextLabel("Disable the boxes: ", hbox);
|
||||
auto disabler = new QskSwitchButton(hbox);
|
||||
|
||||
auto targets = new QskLinearBox(Qt::Horizontal, vbox);
|
||||
|
||||
auto target1 = new QskSwitchButton(targets);
|
||||
target1->setOrientation(Qt::Vertical);
|
||||
|
||||
auto target2 = new QskSwitchButton(targets);
|
||||
target2->setOrientation(Qt::Horizontal);
|
||||
|
||||
auto target3 = new QskSwitchButton(targets);
|
||||
target3->setChecked(true);
|
||||
target3->setOrientation(Qt::Vertical);
|
||||
|
||||
auto target4 = new QskSwitchButton(targets);
|
||||
target4->setChecked(true);
|
||||
target4->setOrientation(Qt::Horizontal);
|
||||
|
||||
QObject::connect(disabler, &QskSwitchButton::checkedChanged,
|
||||
targets, [target1, target2, target3, target4](bool c){
|
||||
target1->setEnabled(!c);
|
||||
target2->setEnabled(!c);
|
||||
target3->setEnabled(!c);
|
||||
target4->setEnabled(!c);
|
||||
});
|
||||
|
||||
targets->setExtraSpacingAt(Qt::RightEdge);
|
||||
vbox->setExtraSpacingAt(Qt::BottomEdge);
|
||||
|
||||
window.addItem( vbox );
|
||||
window.show();
|
||||
|
||||
return app.exec();
|
||||
}
|
4
examples/switchbuttons/switchbuttons.pro
Normal file
4
examples/switchbuttons/switchbuttons.pro
Normal file
@ -0,0 +1,4 @@
|
||||
CONFIG += qskexample
|
||||
|
||||
SOURCES += \
|
||||
main.cpp\
|
@ -20,6 +20,8 @@
|
||||
#include <QskSeparator.h>
|
||||
#include <QskSlider.h>
|
||||
#include <QskSubWindow.h>
|
||||
#include <QskSwitchButton.h>
|
||||
#include <QskSwitchButtonSkinlet.h>
|
||||
#include <QskTabBar.h>
|
||||
#include <QskTabButton.h>
|
||||
#include <QskTabView.h>
|
||||
@ -123,6 +125,7 @@ namespace
|
||||
void setupSeparator();
|
||||
void setupSubWindow();
|
||||
void setupSlider();
|
||||
void setupSwitchButton();
|
||||
void setupTabButton();
|
||||
void setupTabBar();
|
||||
void setupTabView();
|
||||
@ -152,6 +155,7 @@ void Editor::setup()
|
||||
setupSeparator();
|
||||
setupSlider();
|
||||
setupSubWindow();
|
||||
setupSwitchButton();
|
||||
setupTabButton();
|
||||
setupTabBar();
|
||||
setupTabView();
|
||||
@ -483,6 +487,45 @@ void Editor::setupSlider()
|
||||
setAnimation( Q::Handle | A::Metric | A::Position | Q::Pressed, 0 );
|
||||
}
|
||||
|
||||
void Editor::setupSwitchButton()
|
||||
{
|
||||
using A = QskAspect;
|
||||
using Q = QskSwitchButton;
|
||||
|
||||
const qreal radius = qskDpiScaled( 18 );
|
||||
const qreal knopLength = radius - 4;
|
||||
|
||||
setBoxShape( Q::Groove, radius);
|
||||
setStrutSize(Q::Groove, 3.4 * radius, 2 * radius);
|
||||
setColor( Q::Groove, m_pal.accentColor);
|
||||
setBoxBorderColors(Q::Groove, m_pal.darker200);
|
||||
setColor(Q::Groove | Q::Disabled, m_pal.lighter125);
|
||||
setBoxBorderMetrics(Q::Groove, 2);
|
||||
setBoxBorderColors(Q::Groove | Q::Disabled, m_pal.darker125);
|
||||
|
||||
setBoxShape( Q::Knop, knopLength);
|
||||
setMetric(Q::Knop | A::Size,knopLength);
|
||||
setGradient( Q::Knop, QskGradient(Qt::Vertical, m_pal.lighter150, m_pal.lighter125) );
|
||||
setBoxBorderMetrics(Q::Knop, 2);
|
||||
setColor(Q::Knop | Q::Disabled, m_pal.lighter125);
|
||||
setBoxBorderColors(Q::Knop, m_pal.darker200);
|
||||
setBoxBorderColors(Q::Knop | Q::Disabled, m_pal.darker125);
|
||||
|
||||
for( auto state : { A::NoState, Q::Disabled } )
|
||||
{
|
||||
auto aspect = Q::Knop | state | A::Position;
|
||||
|
||||
setMetric( aspect | Q::Checked, 0 );
|
||||
setMetric( aspect, 1 );
|
||||
|
||||
aspect = Q::Groove | state | A::Color;
|
||||
setColor( aspect | Q::Checked, m_pal.baseColor);
|
||||
}
|
||||
|
||||
setAnimation( Q::Knop | A::Metric, qskDuration );
|
||||
setAnimation( Q::Groove | A::Color, qskDuration );
|
||||
}
|
||||
|
||||
void Editor::setupTabButton()
|
||||
{
|
||||
using A = QskAspect;
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include <QskSeparator.h>
|
||||
#include <QskSlider.h>
|
||||
#include <QskSubWindow.h>
|
||||
#include <QskSwitchButton.h>
|
||||
#include <QskSwitchButtonSkinlet.h>
|
||||
#include <QskTabBar.h>
|
||||
#include <QskTabButton.h>
|
||||
#include <QskTabView.h>
|
||||
@ -143,6 +145,7 @@ namespace
|
||||
void setupSeparator();
|
||||
void setupSlider();
|
||||
void setupSubWindow();
|
||||
void setupSwitchButton();
|
||||
void setupTabButton();
|
||||
void setupTabBar();
|
||||
void setupTabView();
|
||||
@ -260,6 +263,7 @@ void Editor::setup()
|
||||
setupSeparator();
|
||||
setupSlider();
|
||||
setupSubWindow();
|
||||
setupSwitchButton();
|
||||
setupTabButton();
|
||||
setupTabBar();
|
||||
setupTabView();
|
||||
@ -849,6 +853,45 @@ void Editor::setupSubWindow()
|
||||
setAnimation( subControl | A::Color, qskDuration );
|
||||
}
|
||||
|
||||
void Editor::setupSwitchButton()
|
||||
{
|
||||
using A = QskAspect;
|
||||
using Q = QskSwitchButton;
|
||||
|
||||
const qreal radius = qskDpiScaled( 18 );
|
||||
const qreal knopLength = radius - 4;
|
||||
|
||||
setBoxShape( Q::Groove, radius);
|
||||
setStrutSize(Q::Groove, 3.4 * radius, 2 * radius);
|
||||
setColor( Q::Groove, m_pal.highlighted);
|
||||
setBoxBorderColors(Q::Groove | Q::Disabled, m_pal.theme);
|
||||
setColor(Q::Groove | Q::Disabled, m_pal.lighter110);
|
||||
setBoxBorderMetrics(Q::Groove, 2);
|
||||
setBoxBorderColors(Q::Groove, m_pal.darker200);
|
||||
|
||||
setBoxShape( Q::Knop, knopLength);
|
||||
setMetric(Q::Knop | A::Size,knopLength);
|
||||
setGradient( Q::Knop, QskGradient(Qt::Vertical, m_pal.lighter150, m_pal.lighter110) );
|
||||
setBoxBorderMetrics(Q::Knop, 2);
|
||||
setColor(Q::Knop | Q::Disabled, m_pal.lighter110);
|
||||
setBoxBorderColors(Q::Knop, m_pal.darker200);
|
||||
setBoxBorderColors(Q::Knop | Q::Disabled, m_pal.theme);
|
||||
|
||||
for( auto state : { A::NoState, Q::Disabled } )
|
||||
{
|
||||
auto aspect = Q::Knop | state | A::Position;
|
||||
|
||||
setMetric( aspect | Q::Checked, 0 );
|
||||
setMetric( aspect, 1 );
|
||||
|
||||
aspect = Q::Groove | state | A::Color;
|
||||
setColor( aspect | Q::Checked, m_pal.baseActive);
|
||||
}
|
||||
|
||||
setAnimation( Q::Knop | A::Metric, qskDuration );
|
||||
setAnimation( Q::Groove | A::Color, qskDuration );
|
||||
}
|
||||
|
||||
class QskSquiekSkin::PrivateData
|
||||
{
|
||||
public:
|
||||
|
@ -70,6 +70,9 @@ QSK_QT_PRIVATE_END
|
||||
#include "QskSubWindowArea.h"
|
||||
#include "QskSubWindowAreaSkinlet.h"
|
||||
|
||||
#include "QskSwitchButton.h"
|
||||
#include "QskSwitchButtonSkinlet.h"
|
||||
|
||||
#include "QskPageIndicator.h"
|
||||
#include "QskPageIndicatorSkinlet.h"
|
||||
|
||||
@ -149,6 +152,7 @@ QskSkin::QskSkin( QObject* parent )
|
||||
declareSkinlet< QskStatusIndicator, QskStatusIndicatorSkinlet >();
|
||||
declareSkinlet< QskSubWindow, QskSubWindowSkinlet >();
|
||||
declareSkinlet< QskSubWindowArea, QskSubWindowAreaSkinlet >();
|
||||
declareSkinlet< QskSwitchButton, QskSwitchButtonSkinlet >();
|
||||
declareSkinlet< QskTabButton, QskTabButtonSkinlet >();
|
||||
declareSkinlet< QskTabView, QskTabViewSkinlet >();
|
||||
declareSkinlet< QskTextLabel, QskTextLabelSkinlet >();
|
||||
|
57
src/controls/QskSwitchButton.cpp
Normal file
57
src/controls/QskSwitchButton.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
#include "QskSwitchButton.h"
|
||||
|
||||
QSK_SUBCONTROL( QskSwitchButton, Knop )
|
||||
QSK_SUBCONTROL( QskSwitchButton, Groove )
|
||||
|
||||
struct QskSwitchButton::PrivateData
|
||||
{
|
||||
PrivateData()
|
||||
: orientation( Qt::Horizontal )
|
||||
, layoutDirection( Qt::LeftToRight)
|
||||
{
|
||||
}
|
||||
|
||||
Qt::Orientation orientation;
|
||||
Qt::LayoutDirection layoutDirection;
|
||||
};
|
||||
|
||||
QskSwitchButton::QskSwitchButton( QQuickItem* parent )
|
||||
: QskAbstractButton(parent)
|
||||
, m_data( new PrivateData() )
|
||||
{
|
||||
setCheckable( true );
|
||||
}
|
||||
|
||||
QskSwitchButton::~QskSwitchButton() {
|
||||
}
|
||||
|
||||
|
||||
Qt::Orientation QskSwitchButton::orientation() const
|
||||
{
|
||||
return m_data->orientation;
|
||||
}
|
||||
void QskSwitchButton::setOrientation(Qt::Orientation orientation)
|
||||
{
|
||||
if(m_data->orientation != orientation)
|
||||
{
|
||||
m_data->orientation = orientation;
|
||||
update();
|
||||
Q_EMIT orientationChanged( orientation );
|
||||
}
|
||||
}
|
||||
|
||||
Qt::LayoutDirection QskSwitchButton::layoutDirection() const
|
||||
{
|
||||
return m_data->layoutDirection;
|
||||
}
|
||||
void QskSwitchButton::setLayoutDirection(Qt::LayoutDirection layoutDirection)
|
||||
{
|
||||
if(m_data->layoutDirection != layoutDirection)
|
||||
{
|
||||
m_data->layoutDirection = layoutDirection;
|
||||
update();
|
||||
Q_EMIT layoutDirectionChanged( layoutDirection );
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_QskSwitchButton.cpp"
|
39
src/controls/QskSwitchButton.h
Normal file
39
src/controls/QskSwitchButton.h
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef QSK_SWITCH_BUTTON_H
|
||||
#define QSK_SWITCH_BUTTON_H
|
||||
|
||||
|
||||
#include "QskAbstractButton.h"
|
||||
#include "QskNamespace.h"
|
||||
|
||||
class QSK_EXPORT QskSwitchButton : public QskAbstractButton
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
using Inherited = QskAbstractButton;
|
||||
|
||||
Q_PROPERTY( Qt::Orientation orientation READ orientation
|
||||
WRITE setOrientation NOTIFY orientationChanged FINAL )
|
||||
Q_PROPERTY( Qt::LayoutDirection layoutDirection READ layoutDirection
|
||||
WRITE setLayoutDirection NOTIFY layoutDirectionChanged FINAL )
|
||||
|
||||
public:
|
||||
QSK_SUBCONTROLS( Groove, Knop )
|
||||
|
||||
QskSwitchButton( QQuickItem* parent = nullptr );
|
||||
~QskSwitchButton() override;
|
||||
|
||||
Qt::Orientation orientation() const;
|
||||
void setOrientation(Qt::Orientation);
|
||||
|
||||
Qt::LayoutDirection layoutDirection() const;
|
||||
void setLayoutDirection(Qt::LayoutDirection);
|
||||
|
||||
Q_SIGNALS:
|
||||
void orientationChanged( Qt::Orientation );
|
||||
void layoutDirectionChanged(Qt::LayoutDirection);
|
||||
|
||||
private:
|
||||
struct PrivateData;
|
||||
std::unique_ptr< PrivateData > m_data;
|
||||
};
|
||||
#endif
|
120
src/controls/QskSwitchButtonSkinlet.cpp
Normal file
120
src/controls/QskSwitchButtonSkinlet.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
|
||||
#include "QskSwitchButton.h"
|
||||
#include "QskSwitchButtonSkinlet.h"
|
||||
#include "QskSGNode.h"
|
||||
QskSwitchButtonSkinlet::QskSwitchButtonSkinlet(QskSkin* skin)
|
||||
: Inherited( skin )
|
||||
{
|
||||
setNodeRoles( { GrooveRole, KnopRole } );
|
||||
}
|
||||
|
||||
QskSwitchButtonSkinlet::~QskSwitchButtonSkinlet() {}
|
||||
|
||||
QRectF QskSwitchButtonSkinlet::subControlRect( const QskSkinnable* skinnable,
|
||||
const QRectF& contentsRect, QskAspect::Subcontrol subControl) const
|
||||
{
|
||||
using Q = QskSwitchButton;
|
||||
const auto switchButton = static_cast< const Q* >( skinnable );
|
||||
|
||||
if (!switchButton)
|
||||
{
|
||||
return Inherited::subControlRect( skinnable, contentsRect, subControl );
|
||||
}
|
||||
|
||||
if ( subControl == Q::Knop)
|
||||
{
|
||||
const auto diameter = 2 * skinnable->metric(QskSwitchButton::Knop | QskAspect::Size);
|
||||
const auto grooveSize = skinnable->strutSizeHint(QskSwitchButton::Groove);
|
||||
auto position = skinnable->metric( Q::Knop | QskAspect::Position );
|
||||
|
||||
auto rect = QRectF(0, 0, diameter, diameter);
|
||||
|
||||
if(switchButton->layoutDirection() == Qt::RightToLeft)
|
||||
{
|
||||
position = 1 - position;
|
||||
}
|
||||
|
||||
if(switchButton->orientation() == Qt::Vertical)
|
||||
{
|
||||
if(diameter < grooveSize.height() )
|
||||
{
|
||||
rect.moveLeft( ( grooveSize.height() - diameter ) / 2);
|
||||
}
|
||||
rect.moveTop( ( grooveSize.height() - diameter ) / 2
|
||||
+ position * ( grooveSize.width() - diameter
|
||||
- ( grooveSize.height() - diameter ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
if(diameter < grooveSize.height() )
|
||||
{
|
||||
rect.moveTop( ( grooveSize.height() - diameter ) / 2);
|
||||
}
|
||||
rect.moveLeft( ( grooveSize.height() - diameter ) / 2
|
||||
+ position * ( grooveSize.width() - diameter
|
||||
- ( grooveSize.height() - diameter ) ) );
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
else if ( subControl == Q::Groove )
|
||||
{
|
||||
auto diameter = 2 * skinnable->metric(QskSwitchButton::Knop | QskAspect::Size);
|
||||
const auto grooveSize = skinnable->strutSizeHint(QskSwitchButton::Groove);
|
||||
auto result = contentsRect;
|
||||
result.setSize( QSizeF(grooveSize.width(), grooveSize.height() ) );
|
||||
|
||||
if(switchButton->orientation() == Qt::Vertical )
|
||||
{
|
||||
if(grooveSize.height() < diameter)
|
||||
{
|
||||
result.moveLeft( ( diameter - result.height() ) / 2);
|
||||
}
|
||||
return result.transposed();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(grooveSize.height() < diameter)
|
||||
{
|
||||
result.moveTop( ( diameter - result.height() ) / 2);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return Inherited::subControlRect( skinnable, contentsRect, subControl );
|
||||
}
|
||||
|
||||
QSizeF QskSwitchButtonSkinlet::sizeHint( const QskSkinnable* skinnable,
|
||||
Qt::SizeHint, const QSizeF&) const
|
||||
{
|
||||
const auto switchButton = static_cast< const QskSwitchButton* >( skinnable );
|
||||
const auto diameter = 2 * skinnable->metric(QskSwitchButton::Knop | QskAspect::Size);
|
||||
const auto grooveSize = skinnable->strutSizeHint(QskSwitchButton::Groove);
|
||||
|
||||
auto result = QSizeF(qMax(diameter, grooveSize.width() ),
|
||||
qMax(diameter, grooveSize.height() ) );
|
||||
if(switchButton->orientation() == Qt::Vertical)
|
||||
{
|
||||
return result.transposed();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QSGNode* QskSwitchButtonSkinlet::updateSubNode( const QskSkinnable* skinnable,
|
||||
quint8 nodeRole, QSGNode* node) const
|
||||
{
|
||||
const auto switchButton = static_cast< const QskSwitchButton* >( skinnable );
|
||||
|
||||
switch ( nodeRole )
|
||||
{
|
||||
case KnopRole:
|
||||
return updateBoxNode( switchButton, node, QskSwitchButton::Knop );
|
||||
|
||||
case GrooveRole:
|
||||
return updateBoxNode( switchButton, node, QskSwitchButton::Groove );
|
||||
}
|
||||
|
||||
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
||||
}
|
34
src/controls/QskSwitchButtonSkinlet.h
Normal file
34
src/controls/QskSwitchButtonSkinlet.h
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef QSK_SWITCH_BUTTON_SKINLET_H
|
||||
#define QSK_SWITCH_BUTTON_SKINLET_H
|
||||
|
||||
|
||||
#include "QskSkinlet.h"
|
||||
|
||||
class QSK_EXPORT QskSwitchButtonSkinlet : public QskSkinlet
|
||||
{
|
||||
Q_GADGET
|
||||
|
||||
using Inherited = QskSkinlet;
|
||||
|
||||
public:
|
||||
enum NodeRole
|
||||
{
|
||||
KnopRole,
|
||||
GrooveRole
|
||||
};
|
||||
|
||||
Q_INVOKABLE QskSwitchButtonSkinlet( QskSkin* parent = nullptr );
|
||||
~QskSwitchButtonSkinlet() override;
|
||||
|
||||
|
||||
QRectF subControlRect( const QskSkinnable*,
|
||||
const QRectF& rect, QskAspect::Subcontrol ) const override;
|
||||
|
||||
QSizeF sizeHint( const QskSkinnable*,
|
||||
Qt::SizeHint, const QSizeF& ) const override;
|
||||
|
||||
protected:
|
||||
QSGNode* updateSubNode( const QskSkinnable*,
|
||||
quint8 nodeRole, QSGNode* ) const override;
|
||||
};
|
||||
#endif
|
@ -183,6 +183,8 @@ HEADERS += \
|
||||
controls/QskSubWindowAreaSkinlet.h \
|
||||
controls/QskSubWindow.h \
|
||||
controls/QskSubWindowSkinlet.h \
|
||||
controls/QskSwitchButton.h \
|
||||
controls/QskSwitchButtonSkinlet.h \
|
||||
controls/QskTabBar.h \
|
||||
controls/QskTabButton.h \
|
||||
controls/QskTabButtonSkinlet.h \
|
||||
@ -257,6 +259,8 @@ SOURCES += \
|
||||
controls/QskSubWindowAreaSkinlet.cpp \
|
||||
controls/QskSubWindow.cpp \
|
||||
controls/QskSubWindowSkinlet.cpp \
|
||||
controls/QskSwitchButton.cpp \
|
||||
controls/QskSwitchButtonSkinlet.cpp \
|
||||
controls/QskTabBar.cpp \
|
||||
controls/QskTabButton.cpp \
|
||||
controls/QskTabButtonSkinlet.cpp \
|
||||
|
Loading…
x
Reference in New Issue
Block a user