initial commit of QskSpinBox
This commit is contained in:
parent
3262673e40
commit
ba9ec8e783
|
|
@ -42,6 +42,12 @@ HEADERS += \
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
dialog/DialogPage.cpp \
|
dialog/DialogPage.cpp \
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
spinbox/SpinBoxPage.h
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
spinbox/SpinBoxPage.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
Page.h
|
Page.h
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include "textinput/TextInputPage.h"
|
#include "textinput/TextInputPage.h"
|
||||||
#include "selector/SelectorPage.h"
|
#include "selector/SelectorPage.h"
|
||||||
#include "dialog/DialogPage.h"
|
#include "dialog/DialogPage.h"
|
||||||
|
#include "spinbox/SpinBoxPage.h"
|
||||||
|
|
||||||
#include <SkinnyShortcut.h>
|
#include <SkinnyShortcut.h>
|
||||||
#include <SkinnyShapeProvider.h>
|
#include <SkinnyShapeProvider.h>
|
||||||
|
|
@ -199,6 +200,9 @@ namespace
|
||||||
tabView->addTab( "Text\nInputs", new TextInputPage() );
|
tabView->addTab( "Text\nInputs", new TextInputPage() );
|
||||||
tabView->addTab( "Selectors", new SelectorPage() );
|
tabView->addTab( "Selectors", new SelectorPage() );
|
||||||
tabView->addTab( "Dialogs", new DialogPage() );
|
tabView->addTab( "Dialogs", new DialogPage() );
|
||||||
|
tabView->addTab( "SpinBoxes", new SpinBoxPage() );
|
||||||
|
|
||||||
|
tabView->setCurrentIndex(tabView->count() - 1);
|
||||||
|
|
||||||
connect( header, &Header::enabledToggled,
|
connect( header, &Header::enabledToggled,
|
||||||
tabView, &TabView::setTabsEnabled );
|
tabView, &TabView::setTabsEnabled );
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Copyright (C) 2023 Edelhirsch Software GmbH
|
||||||
|
* This file may be used under the terms of the 3-clause BSD License
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "SpinBoxPage.h"
|
||||||
|
#include <QskSpinBox.h>
|
||||||
|
#include <QskGridBox.h>
|
||||||
|
#include <QskTextLabel.h>
|
||||||
|
#include <QskLinearBox.h>
|
||||||
|
|
||||||
|
SpinBoxPage::SpinBoxPage( QQuickItem* parent ) : Page( Qt::Horizontal, parent )
|
||||||
|
{
|
||||||
|
setMargins( 10 );
|
||||||
|
setSpacing( 20 );
|
||||||
|
|
||||||
|
populate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpinBoxPage::populate()
|
||||||
|
{
|
||||||
|
const QMap<Qt::Alignment, QString> layouts =
|
||||||
|
{
|
||||||
|
{ Qt::AlignLeft, QStringLiteral("Qt::AlignLeft") },
|
||||||
|
{ Qt::AlignHCenter, QStringLiteral("Qt::AlignHCenter") },
|
||||||
|
{ Qt::AlignRight, QStringLiteral("Qt::AlignRight") },
|
||||||
|
{ Qt::AlignTop, QStringLiteral("Qt::AlignTop") },
|
||||||
|
{ Qt::AlignVCenter, QStringLiteral("Qt::AlignVCenter") },
|
||||||
|
{ Qt::AlignBottom, QStringLiteral("Qt::AlignBottom") },
|
||||||
|
{ Qt::AlignLeft | Qt::AlignVCenter, QStringLiteral("Qt::AlignLeft | Qt::AlignVCenter") },
|
||||||
|
{ Qt::AlignRight | Qt::AlignVCenter, QStringLiteral("Qt::AlignRight | Qt::AlignVCenter") },
|
||||||
|
{ Qt::AlignTop | Qt::AlignHCenter, QStringLiteral("Qt::AlignTop | Qt::AlignHCenter") },
|
||||||
|
{ Qt::AlignBottom | Qt::AlignHCenter, QStringLiteral("Qt::AlignBottom | Qt::AlignHCenter") }
|
||||||
|
};
|
||||||
|
|
||||||
|
auto* const grid = new QskGridBox(this);
|
||||||
|
constexpr int cols = 5;
|
||||||
|
for(const auto& layout : layouts.keys())
|
||||||
|
{
|
||||||
|
const auto x = grid->elementCount() % cols;
|
||||||
|
const auto y = grid->elementCount() / cols;
|
||||||
|
auto* const column = new QskLinearBox(Qt::Vertical, grid);
|
||||||
|
auto* const label = new QskTextLabel(layouts.value(layout), column); // TODO put label either on top or on the bottom
|
||||||
|
auto* const spinbox = new QskSpinBox( column );
|
||||||
|
spinbox->setAlignmentHint(QskSpinBox::Layout, layout);
|
||||||
|
grid->addItem(column, y, x);
|
||||||
|
column->setStretchFactor(label, 1);
|
||||||
|
column->setStretchFactor(spinbox, 99);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Copyright (C) 2023 Edelhirsch Software GmbH
|
||||||
|
* This file may be used under the terms of the 3-clause BSD License
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Page.h"
|
||||||
|
|
||||||
|
class SpinBoxPage : public Page
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SpinBoxPage( QQuickItem* = nullptr );
|
||||||
|
|
||||||
|
private:
|
||||||
|
void populate();
|
||||||
|
};
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
#include <QskSeparator.h>
|
#include <QskSeparator.h>
|
||||||
#include <QskShadowMetrics.h>
|
#include <QskShadowMetrics.h>
|
||||||
#include <QskSlider.h>
|
#include <QskSlider.h>
|
||||||
|
#include <QskSpinBox.h>
|
||||||
#include <QskStandardSymbol.h>
|
#include <QskStandardSymbol.h>
|
||||||
#include <QskSubWindow.h>
|
#include <QskSubWindow.h>
|
||||||
#include <QskSwitchButton.h>
|
#include <QskSwitchButton.h>
|
||||||
|
|
@ -144,6 +145,7 @@ namespace
|
||||||
void setupSeparator();
|
void setupSeparator();
|
||||||
void setupSubWindow();
|
void setupSubWindow();
|
||||||
void setupSlider();
|
void setupSlider();
|
||||||
|
void setupSpinBox();
|
||||||
void setupSwitchButton();
|
void setupSwitchButton();
|
||||||
void setupTabButton();
|
void setupTabButton();
|
||||||
void setupTabBar();
|
void setupTabBar();
|
||||||
|
|
@ -201,6 +203,7 @@ void Editor::setup()
|
||||||
setupSegmentedBar();
|
setupSegmentedBar();
|
||||||
setupSeparator();
|
setupSeparator();
|
||||||
setupSlider();
|
setupSlider();
|
||||||
|
setupSpinBox();
|
||||||
setupSubWindow();
|
setupSubWindow();
|
||||||
setupSwitchButton();
|
setupSwitchButton();
|
||||||
setupTabButton();
|
setupTabButton();
|
||||||
|
|
@ -672,6 +675,76 @@ void Editor::setupSlider()
|
||||||
setAnimation( Q::Handle | A::Metric | A::Position | Q::Pressed, 0 );
|
setAnimation( Q::Handle | A::Metric | A::Position | Q::Pressed, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Editor::setupSpinBox()
|
||||||
|
{
|
||||||
|
using Q = QskSpinBox;
|
||||||
|
|
||||||
|
setSpacing(QskSpinBox::Layout, 4_dp);
|
||||||
|
|
||||||
|
setStrutSize(QskSpinBox::TextPanel | QskAspect::Size, {80_dp,40_dp});
|
||||||
|
setStrutSize(QskSpinBox::Inc | QskAspect::Size, {40_dp,40_dp});
|
||||||
|
setStrutSize(QskSpinBox::Dec | QskAspect::Size, {40_dp,40_dp});
|
||||||
|
|
||||||
|
setAlignment(QskSpinBox::Layout, Qt::AlignHCenter);
|
||||||
|
setAlignment(Q::Text, Qt::AlignCenter);
|
||||||
|
|
||||||
|
for(const auto& state : {QskSpinBox::Dec, QskSpinBox::Inc, QskSpinBox::TextPanel})
|
||||||
|
{
|
||||||
|
setBoxShape(state, 4_dp);
|
||||||
|
setBoxBorderColors(state, QColor("#79747E"));
|
||||||
|
setBoxBorderMetrics(state, 1_dp);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const auto& state : {QskSpinBox::Dec, QskSpinBox::Inc})
|
||||||
|
{
|
||||||
|
setGradient( state, m_pal.primary );
|
||||||
|
setGradient( state | Q::Disabled, m_pal.onSurface12 );
|
||||||
|
|
||||||
|
const auto focusColor = flattenedColor( m_pal.onPrimary, m_pal.primary, 0.12 );
|
||||||
|
setGradient( state | Q::Focused, focusColor );
|
||||||
|
setGradient( state | Q::Pressed, focusColor );
|
||||||
|
|
||||||
|
const auto hoverColor = flattenedColor( m_pal.onPrimary, m_pal.primary, 0.08 );
|
||||||
|
setGradient( state | Q::Hovered, hoverColor );
|
||||||
|
setShadowMetrics( state | Q::Hovered, m_pal.elevationLight1 );
|
||||||
|
setShadowColor( state | Q::Hovered, m_pal.shadow );
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const auto& state : {QskSpinBox::DecText, QskSpinBox::IncText})
|
||||||
|
{
|
||||||
|
setColor( state, m_pal.onPrimary );
|
||||||
|
setColor( state | Q::Disabled, m_pal.onSurface38 );
|
||||||
|
setAlignment(state, Qt::AlignCenter);
|
||||||
|
setFontRole( state, QskMaterial3Skin::M3LabelLarge );
|
||||||
|
}
|
||||||
|
|
||||||
|
setColor( Q::Text, m_pal.onBackground );
|
||||||
|
setColor( Q::Text | Q::Disabled, m_pal.onSurface38 );
|
||||||
|
|
||||||
|
setPadding( Q::TextPanel, 5_dp );
|
||||||
|
setBoxShape( Q::TextPanel, 4_dp, 4_dp, 0, 0 );
|
||||||
|
setBoxBorderMetrics( Q::TextPanel, 0, 0, 0, 1_dp );
|
||||||
|
setBoxBorderColors( Q::TextPanel, m_pal.onSurface );
|
||||||
|
|
||||||
|
setBoxBorderMetrics( Q::TextPanel | Q::Focused, 0, 0, 0, 2_dp );
|
||||||
|
setBoxBorderColors( Q::TextPanel | Q::Focused, m_pal.primary );
|
||||||
|
|
||||||
|
// setBoxBorderMetrics( Q::TextPanel | Q::Editing, 0, 0, 0, 2_dp );
|
||||||
|
// setBoxBorderColors( Q::TextPanel | Q::Editing, m_pal.primary );
|
||||||
|
|
||||||
|
setBoxBorderMetrics( Q::TextPanel | Q::Hovered, 0, 0, 0, 1_dp );
|
||||||
|
setBoxBorderColors( Q::TextPanel | Q::Hovered, m_pal.onSurface );
|
||||||
|
|
||||||
|
setGradient( Q::TextPanel, m_pal.surfaceVariant );
|
||||||
|
|
||||||
|
const auto c1 = QskRgb::toTransparentF( m_pal.onSurface, 0.04 );
|
||||||
|
setGradient( Q::TextPanel | Q::Disabled, c1 );
|
||||||
|
setBoxBorderMetrics( Q::TextPanel | Q::Disabled, 0, 0, 0, 1_dp );
|
||||||
|
|
||||||
|
setColor( Q::TextPanel | Q::Disabled, m_pal.onSurface38 );
|
||||||
|
setBoxBorderColors( Q::TextPanel | Q::Disabled, m_pal.onSurface38 );
|
||||||
|
}
|
||||||
|
|
||||||
void Editor::setupSwitchButton()
|
void Editor::setupSwitchButton()
|
||||||
{
|
{
|
||||||
using A = QskAspect;
|
using A = QskAspect;
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,9 @@ QSK_QT_PRIVATE_END
|
||||||
#include "QskSlider.h"
|
#include "QskSlider.h"
|
||||||
#include "QskSliderSkinlet.h"
|
#include "QskSliderSkinlet.h"
|
||||||
|
|
||||||
|
#include "QskSpinBox.h"
|
||||||
|
#include "QskSpinBoxSkinlet.h"
|
||||||
|
|
||||||
#include "QskSubWindow.h"
|
#include "QskSubWindow.h"
|
||||||
#include "QskSubWindowSkinlet.h"
|
#include "QskSubWindowSkinlet.h"
|
||||||
|
|
||||||
|
|
@ -161,6 +164,7 @@ QskSkin::QskSkin( QObject* parent )
|
||||||
declareSkinlet< QskSegmentedBar, QskSegmentedBarSkinlet >();
|
declareSkinlet< QskSegmentedBar, QskSegmentedBarSkinlet >();
|
||||||
declareSkinlet< QskSeparator, QskSeparatorSkinlet >();
|
declareSkinlet< QskSeparator, QskSeparatorSkinlet >();
|
||||||
declareSkinlet< QskSlider, QskSliderSkinlet >();
|
declareSkinlet< QskSlider, QskSliderSkinlet >();
|
||||||
|
declareSkinlet< QskSpinBox, QskSpinBoxSkinlet >();
|
||||||
declareSkinlet< QskStatusIndicator, QskStatusIndicatorSkinlet >();
|
declareSkinlet< QskStatusIndicator, QskStatusIndicatorSkinlet >();
|
||||||
declareSkinlet< QskSubWindow, QskSubWindowSkinlet >();
|
declareSkinlet< QskSubWindow, QskSubWindowSkinlet >();
|
||||||
declareSkinlet< QskSubWindowArea, QskSubWindowAreaSkinlet >();
|
declareSkinlet< QskSubWindowArea, QskSubWindowAreaSkinlet >();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,353 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Copyright (C) 2023 Edelhirsch Software GmbH
|
||||||
|
* This file may be used under the terms of the 3-clause BSD License
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "QskSpinBox.h"
|
||||||
|
#include <QskLinearBox.h>
|
||||||
|
#include <QskGridBox.h>
|
||||||
|
#include <QskTextInput.h>
|
||||||
|
#include <QRegExpValidator>
|
||||||
|
#include <QskBoxShapeMetrics.h>
|
||||||
|
#include <QskBoxBorderColors.h>
|
||||||
|
#include <QskBoxBorderMetrics.h>
|
||||||
|
#include <QskSkinlet.h>
|
||||||
|
#include <QskEvent.h>
|
||||||
|
#include <QtMath>
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QStyleHints>
|
||||||
|
#include <QskIntervalF.h>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
QSK_SUBCONTROL(QskSpinBox, Inc)
|
||||||
|
QSK_SUBCONTROL(QskSpinBox, Dec)
|
||||||
|
QSK_SUBCONTROL(QskSpinBox, IncText)
|
||||||
|
QSK_SUBCONTROL(QskSpinBox, DecText)
|
||||||
|
QSK_SUBCONTROL(QskSpinBox, Text)
|
||||||
|
QSK_SUBCONTROL(QskSpinBox, TextPanel)
|
||||||
|
QSK_SUBCONTROL(QskSpinBox, Layout)
|
||||||
|
|
||||||
|
QSK_SYSTEM_STATE(QskSpinBox, Pressed, ( QskAspect::QskAspect::FirstSystemState << 0))
|
||||||
|
|
||||||
|
class QskSpinBox::PrivateData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum FocusIndeces : int { Dec = 0, Text = 1, Inc = 2, None = 3 };
|
||||||
|
|
||||||
|
explicit PrivateData(QskSpinBox* const parent) : q(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void setValue(qreal value)
|
||||||
|
{
|
||||||
|
value = qBound(q->minimum(), value, q->maximum());
|
||||||
|
if(!qFuzzyCompare(m_value, value))
|
||||||
|
{
|
||||||
|
m_value = value;
|
||||||
|
Q_EMIT q->valueChanged(m_value);
|
||||||
|
q->polish();
|
||||||
|
q->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal value() const { return m_value; }
|
||||||
|
|
||||||
|
FocusIndeces defaultFocusIndex() const
|
||||||
|
{
|
||||||
|
const auto layout = q->alignmentHint(QskSpinBox::Layout);
|
||||||
|
|
||||||
|
if(layout == Qt::AlignLeft) return Text;
|
||||||
|
if(layout == Qt::AlignRight) return Dec;
|
||||||
|
if(layout == Qt::AlignHCenter) return Dec;
|
||||||
|
if(layout == Qt::AlignTop) return Text;
|
||||||
|
if(layout == Qt::AlignBottom) return Dec;
|
||||||
|
if(layout == Qt::AlignVCenter) return Inc;
|
||||||
|
if(layout == (Qt::AlignLeft | Qt::AlignVCenter)) return Text;
|
||||||
|
if(layout == (Qt::AlignRight | Qt::AlignVCenter)) return Inc;
|
||||||
|
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
FocusIndeces nextFocusIndex() const
|
||||||
|
{
|
||||||
|
const auto layout = q->alignmentHint(QskSpinBox::Layout);
|
||||||
|
|
||||||
|
// [0 ][1 ][2 ][3 ]
|
||||||
|
// [Dec][Text][Inc][None]
|
||||||
|
using LUT = std::array<FocusIndeces,4>;
|
||||||
|
if(layout == Qt::AlignLeft) return LUT{Inc,Dec,None,Text}[m_focusIndex];
|
||||||
|
if(layout == Qt::AlignRight) return LUT{Inc,None,Text,Dec}[m_focusIndex];
|
||||||
|
if(layout == Qt::AlignHCenter) return LUT{Text,Inc,None,Dec}[m_focusIndex];
|
||||||
|
if(layout == Qt::AlignTop) return LUT{Inc,Dec,None,Text}[m_focusIndex];
|
||||||
|
if(layout == Qt::AlignBottom) return LUT{Inc,None,Text,Dec}[m_focusIndex];
|
||||||
|
if(layout == Qt::AlignVCenter) return LUT{None,Dec,Text,Inc}[m_focusIndex];
|
||||||
|
if(layout == (Qt::AlignLeft | Qt::AlignVCenter)) return LUT{None,Inc,Dec,Text}[m_focusIndex];
|
||||||
|
if(layout == (Qt::AlignRight | Qt::AlignVCenter)) return LUT{Text,None,Dec,Inc}[m_focusIndex];
|
||||||
|
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
FocusIndeces previousFocusIndex() const
|
||||||
|
{
|
||||||
|
const auto layout = q->alignmentHint(QskSpinBox::Layout);
|
||||||
|
|
||||||
|
// [0 ][1 ][2 ][3 ]
|
||||||
|
// [Dec][Text][Inc][None]
|
||||||
|
using LUT = std::array<FocusIndeces,4>;
|
||||||
|
if(layout == Qt::AlignLeft) return LUT{None,Dec,Text,Inc}[m_focusIndex];
|
||||||
|
if(layout == Qt::AlignRight) return LUT{None,Inc,Dec,Text}[m_focusIndex];
|
||||||
|
if(layout == Qt::AlignHCenter) return LUT{None,Dec,Text,Inc}[m_focusIndex];
|
||||||
|
if(layout == Qt::AlignTop) return LUT{Text,None,Dec,Inc}[m_focusIndex];
|
||||||
|
if(layout == Qt::AlignBottom) return LUT{None,Inc,Dec,Text}[m_focusIndex];
|
||||||
|
if(layout == Qt::AlignVCenter) return LUT{Text,Inc,None,Dec}[m_focusIndex];
|
||||||
|
if(layout == (Qt::AlignLeft | Qt::AlignVCenter)) return LUT{Inc,None,Text,Dec}[m_focusIndex];
|
||||||
|
if(layout == (Qt::AlignRight | Qt::AlignVCenter)) return LUT{Inc,Dec,None,Text}[m_focusIndex];
|
||||||
|
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
FocusIndeces focusIndex() const
|
||||||
|
{
|
||||||
|
return m_focusIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void focusNext()
|
||||||
|
{
|
||||||
|
const auto index = nextFocusIndex();
|
||||||
|
setFocus(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void focusPrevious()
|
||||||
|
{
|
||||||
|
const auto index = previousFocusIndex();
|
||||||
|
setFocus(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void focusDefault()
|
||||||
|
{
|
||||||
|
setFocus(defaultFocusIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
void setFocus(const FocusIndeces index)
|
||||||
|
{
|
||||||
|
Q_ASSERT(index == Dec || index == Text || index == Inc || index == None);
|
||||||
|
if(index == Dec || index == Text || index == Inc || index == None)
|
||||||
|
{
|
||||||
|
m_focusIndex = index;
|
||||||
|
Q_EMIT q->focusIndexChanged(m_focusIndex); // TODO register enum
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF focusIndicatorRect() const
|
||||||
|
{
|
||||||
|
switch(m_focusIndex)
|
||||||
|
{
|
||||||
|
case PrivateData::FocusIndeces::Dec:
|
||||||
|
return q->subControlRect(QskSpinBox::Dec);
|
||||||
|
case PrivateData::FocusIndeces::Text:
|
||||||
|
return q->subControlRect(QskSpinBox::TextPanel);
|
||||||
|
case PrivateData::FocusIndeces::Inc:
|
||||||
|
return q->subControlRect(QskSpinBox::Inc);
|
||||||
|
default: return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void saveMousePosition(const QPointF& pos)
|
||||||
|
{
|
||||||
|
q->setSkinHint(QskSpinBox::Layout | QskAspect::Metric | QskAspect::Position, pos );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
qreal m_value{0.0f};
|
||||||
|
QskSpinBox* const q;
|
||||||
|
FocusIndeces m_focusIndex = FocusIndeces::None;
|
||||||
|
};
|
||||||
|
|
||||||
|
using S = QskSpinBox;
|
||||||
|
|
||||||
|
QskSpinBox::QskSpinBox(QQuickItem* const parent)
|
||||||
|
: Inherited(parent)
|
||||||
|
, m_data(std::make_unique<PrivateData>(this))
|
||||||
|
{
|
||||||
|
setBoundaries(0.0,1.0);
|
||||||
|
setAcceptHoverEvents(true);
|
||||||
|
setAcceptedMouseButtons(Qt::LeftButton);
|
||||||
|
setFocusPolicy( Qt::StrongFocus );
|
||||||
|
|
||||||
|
connect( this, &S::focusIndexChanged, this, &S::focusIndicatorRectChanged );
|
||||||
|
connect( this, &S::boundariesChanged, this, [this](const QskIntervalF& interval){ if(!interval.contains(value())) m_data->setValue(minimum()); });
|
||||||
|
connect( this, &S::valueChanged, this, [this](){ polish(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
QskSpinBox::~QskSpinBox() = default;
|
||||||
|
|
||||||
|
void QskSpinBox::hoverEnterEvent(QHoverEvent* event)
|
||||||
|
{
|
||||||
|
m_data->saveMousePosition( qskHoverPosition( event ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskSpinBox::hoverLeaveEvent(QHoverEvent* event)
|
||||||
|
{
|
||||||
|
m_data->saveMousePosition( {} );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskSpinBox::hoverMoveEvent(QHoverEvent *event)
|
||||||
|
{
|
||||||
|
m_data->saveMousePosition( qskHoverPosition( event ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskSpinBox::mouseReleaseEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
m_data->saveMousePosition( qskMousePosition( event ) );
|
||||||
|
|
||||||
|
const auto focus = ( focusPolicy() & Qt::ClickFocus ) == Qt::ClickFocus && !QGuiApplication::styleHints()->setFocusOnTouchRelease();
|
||||||
|
|
||||||
|
if(subControlRect(QskSpinBox::Inc).contains( event->pos() ))
|
||||||
|
{
|
||||||
|
increment(+stepSize());
|
||||||
|
|
||||||
|
if( focus )
|
||||||
|
{
|
||||||
|
m_data->setFocus(PrivateData::Inc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(subControlRect(QskSpinBox::Dec).contains( event->pos() ))
|
||||||
|
{
|
||||||
|
increment(-stepSize());
|
||||||
|
|
||||||
|
if( focus )
|
||||||
|
{
|
||||||
|
m_data->setFocus(PrivateData::Dec);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(subControlRect(QskSpinBox::TextPanel).contains( event->pos() ))
|
||||||
|
{
|
||||||
|
if( focus )
|
||||||
|
{
|
||||||
|
m_data->setFocus(PrivateData::Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event->ignore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskSpinBox::mousePressEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
m_data->saveMousePosition( -1 * qskMousePosition( event ) );
|
||||||
|
|
||||||
|
const auto focus = ( focusPolicy() & Qt::ClickFocus ) == Qt::ClickFocus && !QGuiApplication::styleHints()->setFocusOnTouchRelease();
|
||||||
|
|
||||||
|
if(subControlRect(QskSpinBox::Inc).contains( event->pos() ))
|
||||||
|
{
|
||||||
|
if( focus )
|
||||||
|
{
|
||||||
|
m_data->setFocus(PrivateData::Inc);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(subControlRect(QskSpinBox::Dec).contains( event->pos() ))
|
||||||
|
{
|
||||||
|
if( focus )
|
||||||
|
{
|
||||||
|
m_data->setFocus(PrivateData::Dec);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event->ignore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskSpinBox::keyPressEvent(QKeyEvent *event)
|
||||||
|
{
|
||||||
|
switch( event->key() )
|
||||||
|
{
|
||||||
|
case Qt::Key_Plus:
|
||||||
|
case Qt::Key_Up:
|
||||||
|
case Qt::Key_Right:
|
||||||
|
// TODO increment
|
||||||
|
break;
|
||||||
|
case Qt::Key_Minus:
|
||||||
|
case Qt::Key_Down:
|
||||||
|
case Qt::Key_Left:
|
||||||
|
// TODO decrement
|
||||||
|
break;
|
||||||
|
case Qt::Key_Select:
|
||||||
|
case Qt::Key_Space:
|
||||||
|
// TODO click currently focused -/+
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
const int steps = qskFocusChainIncrement( event );
|
||||||
|
if(steps != 0)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < steps; ++i)
|
||||||
|
{
|
||||||
|
m_data->focusNext();
|
||||||
|
}
|
||||||
|
for(int i = steps; i < 0; ++i)
|
||||||
|
{
|
||||||
|
m_data->focusPrevious();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Inherited::keyPressEvent( event );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskSpinBox::keyReleaseEvent( QKeyEvent* event )
|
||||||
|
{
|
||||||
|
if( event->key() == Qt::Key_Select || event->key() == Qt::Key_Space )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Inherited::keyReleaseEvent( event );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskSpinBox::focusInEvent(QFocusEvent *event)
|
||||||
|
{
|
||||||
|
switch( event->reason() )
|
||||||
|
{
|
||||||
|
case Qt::TabFocusReason:
|
||||||
|
m_data->focusNext();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::BacktabFocusReason:
|
||||||
|
m_data->focusPrevious();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if(m_data->focusIndex() == PrivateData::None)
|
||||||
|
{
|
||||||
|
m_data->focusDefault();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Inherited::focusInEvent( event );
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF QskSpinBox::focusIndicatorRect() const
|
||||||
|
{
|
||||||
|
auto rect = m_data->focusIndicatorRect();
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskSpinBox::increment(qreal offset)
|
||||||
|
{
|
||||||
|
m_data->setValue(m_data->value() + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal QskSpinBox::value() const
|
||||||
|
{
|
||||||
|
return m_data->value();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Copyright (C) 2023 Edelhirsch Software GmbH
|
||||||
|
* This file may be used under the terms of the 3-clause BSD License
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QskControl.h>
|
||||||
|
#include <QskPushButton.h>
|
||||||
|
#include <QskBoundedInput.h>
|
||||||
|
|
||||||
|
class QSK_EXPORT QskSpinBox : public QskBoundedInput
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
using Inherited = QskBoundedInput;
|
||||||
|
public:
|
||||||
|
Q_PROPERTY(qreal value READ value NOTIFY valueChanged)
|
||||||
|
QSK_SUBCONTROLS(Inc, Dec, IncText, DecText, TextPanel, Text, Layout)
|
||||||
|
QSK_STATES( Pressed )
|
||||||
|
|
||||||
|
explicit QskSpinBox( QQuickItem* parent = nullptr );
|
||||||
|
~QskSpinBox() override;
|
||||||
|
|
||||||
|
void increment( qreal offset ) override;
|
||||||
|
qreal value() const;
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void valueChanged(qreal value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Q_SIGNAL void focusIndexChanged(int index);
|
||||||
|
|
||||||
|
void hoverEnterEvent( QHoverEvent* event) override;
|
||||||
|
void hoverLeaveEvent( QHoverEvent* event) override;
|
||||||
|
void hoverMoveEvent( QHoverEvent* event) override;
|
||||||
|
|
||||||
|
void mouseReleaseEvent(QMouseEvent* event) override;
|
||||||
|
void mousePressEvent(QMouseEvent* event) override;
|
||||||
|
|
||||||
|
void keyPressEvent( QKeyEvent* event ) override;
|
||||||
|
void keyReleaseEvent( QKeyEvent* event ) override;
|
||||||
|
|
||||||
|
void focusInEvent(QFocusEvent* event) override;
|
||||||
|
QRectF focusIndicatorRect() const override;
|
||||||
|
|
||||||
|
class PrivateData;
|
||||||
|
std::unique_ptr<PrivateData> m_data;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,221 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Copyright (C) 2023 Edelhirsch Software GmbH
|
||||||
|
* This file may be used under the terms of the 3-clause BSD License
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "QskSpinBoxSkinlet.h"
|
||||||
|
#include "QskSpinBox.h"
|
||||||
|
#include <QFontMetrics>
|
||||||
|
|
||||||
|
const auto INC_TEXT = QStringLiteral("+");
|
||||||
|
const auto DEC_TEXT = QStringLiteral("-");
|
||||||
|
|
||||||
|
enum SampleIndeces { Dec, Txt, Inc, Count };
|
||||||
|
|
||||||
|
QskSpinBoxSkinlet::QskSpinBoxSkinlet(QskSkin *)
|
||||||
|
{
|
||||||
|
setNodeRoles({IncPanel, IncText, DecPanel, DecText, TextPanel, TextText});
|
||||||
|
}
|
||||||
|
|
||||||
|
int QskSpinBoxSkinlet::sampleCount(const QskSkinnable *, QskAspect::Subcontrol) const
|
||||||
|
{
|
||||||
|
return Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF QskSpinBoxSkinlet::sampleRect(const QskSkinnable* const skinnable, const QRectF& rect, QskAspect::Subcontrol subControl, int index) const
|
||||||
|
{
|
||||||
|
if(index == Dec || index == Inc || index == Txt)
|
||||||
|
{
|
||||||
|
return subControlRect(skinnable, rect, subControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Inherited::sampleRect( skinnable, rect, subControl, index );
|
||||||
|
}
|
||||||
|
|
||||||
|
QskAspect::States QskSpinBoxSkinlet::sampleStates(const QskSkinnable* const skinnable, QskAspect::Subcontrol subControl, int index) const
|
||||||
|
{
|
||||||
|
auto states = Inherited::sampleStates( skinnable, subControl, index );
|
||||||
|
|
||||||
|
if ( subControl == QskSpinBox::Dec || subControl == QskSpinBox::Inc || subControl == QskSpinBox::TextPanel)
|
||||||
|
{
|
||||||
|
const auto* const spinbox = static_cast<const QskSpinBox*>(skinnable);
|
||||||
|
const auto cursorPos = spinbox->effectiveSkinHint(QskSpinBox::Layout | QskAspect::Metric | QskAspect::Position).toPointF();
|
||||||
|
const QPointF cursorPosAbs{qAbs(cursorPos.x()), qAbs(cursorPos.y())};
|
||||||
|
const auto contain = !cursorPosAbs.isNull() && spinbox->subControlRect(subControl).contains(cursorPosAbs);
|
||||||
|
const auto pressed = contain && (cursorPos.x() < 0 || cursorPos.y() < 0);
|
||||||
|
const auto hovered = contain && !pressed;
|
||||||
|
states.setFlag(QskControl::Hovered, hovered);
|
||||||
|
states.setFlag(QskSpinBox::Pressed, pressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
return states;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSizeF QskSpinBoxSkinlet::sizeHint(const QskSkinnable* const skinnable, Qt::SizeHint sizeHint, const QSizeF& size) const
|
||||||
|
{
|
||||||
|
using S = QskSpinBox;
|
||||||
|
const auto* const spinbox = static_cast<const S*>(skinnable);
|
||||||
|
const auto layout = spinbox->alignmentHint(QskSpinBox::Layout);
|
||||||
|
const auto spacing = spinbox->spacingHint(QskSpinBox::Layout);
|
||||||
|
|
||||||
|
const auto strutInc = spinbox->strutSizeHint(S::Inc);
|
||||||
|
const auto strutDec = spinbox->strutSizeHint(S::Dec);
|
||||||
|
const auto strutTxt = spinbox->strutSizeHint(S::TextPanel);
|
||||||
|
|
||||||
|
if(sizeHint == Qt::MinimumSize || sizeHint == Qt::MaximumSize || Qt::PreferredSize)
|
||||||
|
{
|
||||||
|
if(layout == Qt::AlignTop || layout == Qt::AlignBottom || layout == Qt::AlignVCenter)
|
||||||
|
{
|
||||||
|
const auto w = qMax(strutDec.width(), qMax( strutTxt.width() , strutInc.width()));
|
||||||
|
const auto h = strutDec.height() + strutTxt.height() + strutInc.height();
|
||||||
|
return {w,h + 2.0 * spacing};
|
||||||
|
}
|
||||||
|
if(layout == Qt::AlignLeft || layout == Qt::AlignRight || layout == Qt::AlignHCenter)
|
||||||
|
{
|
||||||
|
const auto w = strutDec.width() + strutTxt.width() + strutInc.width();
|
||||||
|
const auto h = qMax(strutDec.height(), qMax( strutTxt.height() , strutInc.height()));
|
||||||
|
return {w + 2.0 * spacing,h};
|
||||||
|
}
|
||||||
|
if(layout == (Qt::AlignLeft | Qt::AlignVCenter) || layout == (Qt::AlignRight | Qt::AlignVCenter))
|
||||||
|
{
|
||||||
|
const auto w = strutTxt.width() + qMax(strutInc.width(), strutDec.width());
|
||||||
|
const auto h = qMax(2.0 * qMax(strutInc.height(), strutDec.height()), strutTxt.height());
|
||||||
|
return {w + spacing ,h + spacing};
|
||||||
|
}
|
||||||
|
if(layout == (Qt::AlignTop | Qt::AlignHCenter) || layout == (Qt::AlignTop | Qt::AlignHCenter))
|
||||||
|
{
|
||||||
|
const auto w = qMax(strutTxt.width() , strutInc.width() + strutDec.width());
|
||||||
|
const auto h = strutTxt.height() + qMax(strutInc.height() , strutDec.height());
|
||||||
|
return {w + spacing, h + spacing};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Inherited::sizeHint(skinnable, sizeHint, size);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF QskSpinBoxSkinlet::subControlRect(const QskSkinnable* const skinnable, const QRectF& rect, QskAspect::Subcontrol subControl) const
|
||||||
|
{
|
||||||
|
if(subControl == QskSpinBox::DecText) return subControlRect(skinnable, rect, QskSpinBox::Dec);
|
||||||
|
if(subControl == QskSpinBox::IncText) return subControlRect(skinnable, rect, QskSpinBox::Inc);
|
||||||
|
if(subControl == QskSpinBox::Text) return subControlRect(skinnable, rect, QskSpinBox::TextPanel);
|
||||||
|
|
||||||
|
const auto* const spinbox = static_cast<const QskSpinBox*>(skinnable);
|
||||||
|
const auto layout = spinbox->alignmentHint(QskSpinBox::Layout);
|
||||||
|
const auto spacing = spinbox->spacingHint(QskSpinBox::Layout);
|
||||||
|
|
||||||
|
using S = QskSpinBox;
|
||||||
|
|
||||||
|
QRectF rects[Count] =
|
||||||
|
{
|
||||||
|
{ {}, spinbox->strutSizeHint(S::Dec)},
|
||||||
|
{ {}, spinbox->strutSizeHint(S::TextPanel)},
|
||||||
|
{ {}, spinbox->strutSizeHint(S::Inc)},
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto center = rect.center();
|
||||||
|
|
||||||
|
// TODO center everything
|
||||||
|
|
||||||
|
if(layout == Qt::AlignLeft)
|
||||||
|
{
|
||||||
|
rects[Txt].moveTopLeft({0.0 /************/, center.y() - rects[Txt].height() * 0.5});
|
||||||
|
rects[Dec].moveTopLeft({rects[Txt].right() + spacing, center.y() - rects[Dec].height() * 0.5});
|
||||||
|
rects[Inc].moveTopLeft({rects[Dec].right() + spacing, center.y() - rects[Inc].height() * 0.5});
|
||||||
|
}
|
||||||
|
else if(layout == Qt::AlignRight)
|
||||||
|
{
|
||||||
|
rects[Dec].moveTopLeft({0.0 /************/, center.y() - rects[Dec].height() * 0.5});
|
||||||
|
rects[Inc].moveTopLeft({rects[Dec].right() + spacing, center.y() - rects[Inc].height() * 0.5});
|
||||||
|
rects[Txt].moveTopLeft({rects[Inc].right() + spacing, center.y() - rects[Txt].height() * 0.5});
|
||||||
|
}
|
||||||
|
else if(layout == Qt::AlignTop)
|
||||||
|
{
|
||||||
|
rects[Txt].moveTopLeft({center.x() - rects[Txt].width() * 0.5, 0.0 });
|
||||||
|
rects[Inc].moveTopLeft({center.x() - rects[Inc].width() * 0.5, rects[Txt].bottom() + spacing});
|
||||||
|
rects[Dec].moveTopLeft({center.x() - rects[Dec].width() * 0.5, rects[Inc].bottom() + spacing});
|
||||||
|
}
|
||||||
|
else if(layout == Qt::AlignBottom)
|
||||||
|
{
|
||||||
|
rects[Inc].moveTopLeft({center.x() - rects[Inc].width() * 0.5, 0.0});
|
||||||
|
rects[Dec].moveTopLeft({center.x() - rects[Dec].width() * 0.5, rects[Inc].bottom() + spacing});
|
||||||
|
rects[Txt].moveTopLeft({center.x() - rects[Txt].width() * 0.5, rects[Dec].bottom() + spacing});
|
||||||
|
}
|
||||||
|
else if(layout == Qt::AlignHCenter)
|
||||||
|
{
|
||||||
|
rects[Dec].moveTopLeft({0.0 /************/, center.y() - rects[Dec].height() * 0.5});
|
||||||
|
rects[Txt].moveTopLeft({rects[Dec].right() + spacing, center.y() - rects[Txt].height() * 0.5});
|
||||||
|
rects[Inc].moveTopLeft({rects[Txt].right() + spacing, center.y() - rects[Inc].height() * 0.5});
|
||||||
|
}
|
||||||
|
else if(layout == Qt::AlignVCenter)
|
||||||
|
{
|
||||||
|
rects[Inc].moveTopLeft({center.x() - rects[Inc].width() * 0.5, 0.0});
|
||||||
|
rects[Txt].moveTopLeft({center.x() - rects[Txt].width() * 0.5, rects[Inc].bottom() + spacing});
|
||||||
|
rects[Dec].moveTopLeft({center.x() - rects[Dec].width() * 0.5, rects[Txt].bottom() + spacing});
|
||||||
|
}
|
||||||
|
else if(layout == (Qt::AlignLeft | Qt::AlignVCenter))
|
||||||
|
{
|
||||||
|
rects[Txt].moveTopLeft({0.0 /************/, center.y() - rects[Txt].height() * 0.5 });
|
||||||
|
rects[Inc].moveTopLeft({rects[Txt].right() + spacing, center.y() - spacing * 0.5 - rects[Inc].height()});
|
||||||
|
rects[Dec].moveTopLeft({rects[Txt].right() + spacing, center.y() + spacing * 0.5});
|
||||||
|
}
|
||||||
|
else if(layout == (Qt::AlignRight | Qt::AlignVCenter))
|
||||||
|
{
|
||||||
|
const auto dx = qMax(rects[Inc].width(), rects[Dec].width());
|
||||||
|
rects[Inc].moveTopLeft({dx - rects[Inc].width(), center.y() - spacing * 0.5 - rects[Inc].height()});
|
||||||
|
rects[Dec].moveTopLeft({dx - rects[Dec].width(), center.y() + spacing * 0.5});
|
||||||
|
rects[Txt].moveTopLeft({dx + spacing, center.y() - rects[Txt].height() * 0.5 });
|
||||||
|
}
|
||||||
|
else if(layout == (Qt::AlignTop | Qt::AlignHCenter))
|
||||||
|
{
|
||||||
|
rects[Txt].moveTopLeft({center.x() - rects[Txt].width() * 0.5, 0.0 });
|
||||||
|
rects[Dec].moveTopLeft({rects[Txt].center().x() - spacing * 0.5 - rects[Dec].width(), rects[Txt].bottom() + spacing });
|
||||||
|
rects[Inc].moveTopLeft({rects[Txt].center().x() + spacing * 0.5, rects[Txt].bottom() + spacing });
|
||||||
|
}
|
||||||
|
else if(layout == (Qt::AlignBottom | Qt::AlignHCenter))
|
||||||
|
{
|
||||||
|
const auto dx = qMax(rects[Inc].width(), rects[Dec].width());
|
||||||
|
const auto dy = qMax(rects[Inc].height(), rects[Dec].height());
|
||||||
|
rects[Txt].moveTopLeft({center.x() - rects[Txt].width() * 0.5, center.y() - rects[Txt].height() * 0.5});
|
||||||
|
rects[Dec].moveTopLeft({center.x() - spacing * 0.5 - rects[Dec].width() , rects[Txt].top() - spacing - rects[Dec].height() });
|
||||||
|
rects[Inc].moveTopLeft({center.x() + spacing * 0.5, rects[Txt].top() - spacing - rects[Inc].height() });
|
||||||
|
}
|
||||||
|
|
||||||
|
if(subControl == S::Dec)
|
||||||
|
{
|
||||||
|
return rects[Dec];
|
||||||
|
}
|
||||||
|
if(subControl == S::TextPanel)
|
||||||
|
{
|
||||||
|
return rects[Txt];
|
||||||
|
}
|
||||||
|
if(subControl == S::Inc)
|
||||||
|
{
|
||||||
|
return rects[Inc];
|
||||||
|
}
|
||||||
|
|
||||||
|
return Inherited::subControlRect(skinnable, rect, subControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSGNode* QskSpinBoxSkinlet::updateSubNode(const QskSkinnable* const skinnable, const quint8 nodeRole, QSGNode* const node) const
|
||||||
|
{
|
||||||
|
if(nodeRole == IncPanel) { return updateSeriesNode( skinnable, QskSpinBox::Inc, node); }
|
||||||
|
if(nodeRole == DecPanel) { return updateSeriesNode( skinnable, QskSpinBox::Dec, node ); }
|
||||||
|
if(nodeRole == IncText) { return updateTextNode( skinnable, node, INC_TEXT, QskSpinBox::IncText); }
|
||||||
|
if(nodeRole == DecText) { return updateTextNode( skinnable, node, DEC_TEXT, QskSpinBox::DecText ); }
|
||||||
|
if(nodeRole == TextPanel) { return updateSeriesNode( skinnable, QskSpinBox::TextPanel, node ); }
|
||||||
|
if(nodeRole == TextText) { return updateTextNode( skinnable, node, QString::number(static_cast<const QskSpinBox*>(skinnable)->value()), QskSpinBox::Text ); }
|
||||||
|
return Inherited::updateSubNode(skinnable, nodeRole, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSGNode *QskSpinBoxSkinlet::updateSampleNode(const QskSkinnable* const skinnable, QskAspect::Subcontrol subControl, const int index, QSGNode* const node) const
|
||||||
|
{
|
||||||
|
const auto* const spinbox = static_cast<const QskSpinBox*>(skinnable);
|
||||||
|
|
||||||
|
if ( subControl == QskSpinBox::Dec || subControl == QskSpinBox::Inc || subControl == QskSpinBox::TextPanel )
|
||||||
|
{
|
||||||
|
const auto rect = sampleRect(spinbox, spinbox->contentsRect(), subControl, index);
|
||||||
|
return updateBoxNode( skinnable, node, rect, subControl );
|
||||||
|
}
|
||||||
|
|
||||||
|
return Inherited::updateSampleNode( skinnable, subControl, index, node );
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Copyright (C) 2023 Edelhirsch Software GmbH
|
||||||
|
* This file may be used under the terms of the 3-clause BSD License
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QskSkinlet.h>
|
||||||
|
|
||||||
|
class QSK_EXPORT QskSpinBoxSkinlet : public QskSkinlet
|
||||||
|
{
|
||||||
|
Q_GADGET
|
||||||
|
using Inherited = QskSkinlet;
|
||||||
|
public:
|
||||||
|
enum NodeRole
|
||||||
|
{
|
||||||
|
IncPanel, IncText, DecPanel, DecText, TextPanel, TextText, RoleCount
|
||||||
|
};
|
||||||
|
Q_INVOKABLE QskSpinBoxSkinlet( QskSkin* = nullptr );
|
||||||
|
protected:
|
||||||
|
int sampleCount( const QskSkinnable*, QskAspect::Subcontrol ) const override;
|
||||||
|
QRectF sampleRect( const QskSkinnable*, const QRectF&, QskAspect::Subcontrol, int index ) const override;
|
||||||
|
QskAspect::States sampleStates(const QskSkinnable* skinnable, QskAspect::Subcontrol subControl, int index ) const override;
|
||||||
|
QSizeF sizeHint( const QskSkinnable*, Qt::SizeHint, const QSizeF& ) const override;
|
||||||
|
QRectF subControlRect( const QskSkinnable*, const QRectF&, QskAspect::Subcontrol ) const override;
|
||||||
|
QSGNode* updateSubNode( const QskSkinnable*, quint8 nodeRole, QSGNode* ) const override;
|
||||||
|
QSGNode* updateSampleNode( const QskSkinnable* skinnable, QskAspect::Subcontrol subControl, int index, QSGNode* node ) const override;
|
||||||
|
};
|
||||||
|
|
@ -227,6 +227,8 @@ HEADERS += \
|
||||||
controls/QskSliderSkinlet.h \
|
controls/QskSliderSkinlet.h \
|
||||||
controls/QskStatusIndicator.h \
|
controls/QskStatusIndicator.h \
|
||||||
controls/QskStatusIndicatorSkinlet.h \
|
controls/QskStatusIndicatorSkinlet.h \
|
||||||
|
controls/QskSpinBox.h \
|
||||||
|
controls/QskSpinBoxSkinlet.h \
|
||||||
controls/QskSubWindowArea.h \
|
controls/QskSubWindowArea.h \
|
||||||
controls/QskSubWindowAreaSkinlet.h \
|
controls/QskSubWindowAreaSkinlet.h \
|
||||||
controls/QskSubWindow.h \
|
controls/QskSubWindow.h \
|
||||||
|
|
@ -309,6 +311,8 @@ SOURCES += \
|
||||||
controls/QskSkinnable.cpp \
|
controls/QskSkinnable.cpp \
|
||||||
controls/QskSlider.cpp \
|
controls/QskSlider.cpp \
|
||||||
controls/QskSliderSkinlet.cpp \
|
controls/QskSliderSkinlet.cpp \
|
||||||
|
controls/QskSpinBox.cpp \
|
||||||
|
controls/QskSpinBoxSkinlet.cpp \
|
||||||
controls/QskStatusIndicator.cpp \
|
controls/QskStatusIndicator.cpp \
|
||||||
controls/QskStatusIndicatorSkinlet.cpp \
|
controls/QskStatusIndicatorSkinlet.cpp \
|
||||||
controls/QskSubWindowArea.cpp \
|
controls/QskSubWindowArea.cpp \
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue