Merge branch 'master' into features/menubutton

This commit is contained in:
Uwe Rathmann 2023-09-27 11:17:07 +02:00
commit b273264629
57 changed files with 1771 additions and 687 deletions

View File

@ -108,6 +108,6 @@ SpacesInSquareBrackets: true
Standard: Cpp11
TabWidth: 4
UseTab: Never
UseCRLF: Always
UseCRLF: true
...

View File

@ -4,13 +4,18 @@
*****************************************************************************/
#include "ProgressBarPage.h"
#include <QskProgressBar.h>
#include <QskAnimator.h>
#include <QskGraphicProvider.h>
#include <QskGraphic.h>
#include <QskGradient.h>
#include <QskHctColor.h>
#include <QskProgressBar.h>
#include <QskProgressRing.h>
#include <QskRgbValue.h>
#include <QQuickWindow>
namespace
{
class ProgressBar : public QskProgressBar
@ -35,9 +40,32 @@ namespace
colors += hctColor.toned( 45 ).rgb();
colors += hctColor.toned( 30 ).rgb();
setBarGradient( qskBuildGradientStops( colors, true ) );
setFillGradient( qskBuildGradientStops( colors, true ) );
}
};
class DeterminateIndicatorsAnimator : public QskAnimator
{
public:
DeterminateIndicatorsAnimator( const QVector< QskProgressIndicator* >& indicators )
: QskAnimator()
, m_indicators( indicators )
{
setAutoRepeat( true );
setDuration( 3000 );
}
void advance( qreal value ) override
{
for( auto* indicator : m_indicators )
{
indicator->setValueAsRatio( value );
}
}
private:
const QVector< QskProgressIndicator* > m_indicators;
};
}
ProgressBarPage::ProgressBarPage( QQuickItem* parent )
@ -53,10 +81,7 @@ void ProgressBarPage::populate()
hBox->setSizePolicy( Qt::Horizontal, QskSizePolicy::Fixed );
hBox->setSpacing( 20 );
{
auto bar = new ProgressBar( hBox );
bar->setValue( 35 );
}
QVector< QskProgressIndicator* > determinateIndicators;
{
auto bar = new ProgressBar( hBox );
@ -77,6 +102,11 @@ void ProgressBarPage::populate()
bar->setValue( 25 );
}
{
auto bar = new ProgressBar( hBox );
determinateIndicators.append( bar );
}
{
auto bar = new ProgressBar( hBox );
bar->setIndeterminate( true );
@ -106,8 +136,55 @@ void ProgressBarPage::populate()
bar->setValue( 10 );
}
{
auto bar = new ProgressBar( vBox );
determinateIndicators.append( bar );
}
{
auto bar = new ProgressBar( vBox );
bar->setIndeterminate( true );
}
const auto sizes = { QskProgressRing::SmallSize, QskProgressRing::NormalSize,
QskProgressRing::LargeSize };
auto determinateRingsHBox = new QskLinearBox( Qt::Horizontal, vBox );
auto indeterminateRingsHBox = new QskLinearBox( Qt::Horizontal, vBox );
for( const auto size : sizes )
{
for( const auto indeterminate : { true, false } )
{
auto* ring = new QskProgressRing( determinateRingsHBox );
ring->setSize( size );
QQuickItem* parentItem;
if( indeterminate )
{
parentItem = indeterminateRingsHBox;
ring->setIndeterminate( true );
}
else
{
parentItem = determinateRingsHBox;
determinateIndicators.append( ring );
}
ring->setParent( parentItem );
ring->setParentItem( parentItem );
}
}
connect( this, &QskQuickItem::windowChanged, this, [this, determinateIndicators]( QQuickWindow* window )
{
if( window )
{
m_determinateIndicatorsAnimator.reset( new DeterminateIndicatorsAnimator( determinateIndicators ) );
m_determinateIndicatorsAnimator->setWindow( window );
m_determinateIndicatorsAnimator->start();
}
} );
}

View File

@ -7,6 +7,8 @@
#include "Page.h"
class QskAnimator;
class ProgressBarPage : public Page
{
public:
@ -14,4 +16,6 @@ class ProgressBarPage : public Page
private:
void populate();
std::unique_ptr< QskAnimator > m_determinateIndicatorsAnimator;
};

View File

@ -193,35 +193,6 @@ void Cube::switchToPosition( const Position position )
doSwitch( direction, nextPosition );
}
void Cube::keyPressEvent( QKeyEvent* event )
{
Qsk::Direction direction;
switch( event->key() )
{
case Qt::Key_Up:
direction = Qsk::TopToBottom;
break;
case Qt::Key_Down:
direction = Qsk::BottomToTop;
break;
case Qt::Key_Left:
direction = Qsk::LeftToRight;
break;
case Qt::Key_Right:
direction = Qsk::RightToLeft;
break;
default:
return;
}
switchPosition( direction );
}
Cube::Position Cube::currentPosition() const
{
return static_cast< Position >( currentIndex() );
@ -304,8 +275,6 @@ MainItem::MainItem( QQuickItem* parent )
// the current item needs to be the one at the Front:
m_cube->setCurrentItem( dashboardPage );
installEventFilter( this );
}
void MainItem::gestureEvent( QskGestureEvent* event )
@ -332,34 +301,49 @@ void MainItem::gestureEvent( QskGestureEvent* event )
}
}
bool MainItem::eventFilter( QObject* object, QEvent* event )
void MainItem::keyPressEvent( QKeyEvent* event )
{
if ( event->type() == QEvent::KeyPress )
// maybe using shortcuts ?
Qsk::Direction direction;
switch( event->key() )
{
QCoreApplication::sendEvent( m_cube, event );
return true;
}
else
{
return QObject::eventFilter( object, event );
}
case Qt::Key_Up:
direction = Qsk::TopToBottom;
break;
case Qt::Key_Down:
direction = Qsk::BottomToTop;
break;
case Qt::Key_Left:
direction = Qsk::LeftToRight;
break;
case Qt::Key_Right:
direction = Qsk::RightToLeft;
break;
default:
return;
}
bool MainItem::gestureFilter( QQuickItem* item, QEvent* event )
m_cube->switchPosition( direction );
}
bool MainItem::gestureFilter( const QQuickItem* item, const QEvent* event )
{
auto& recognizer = m_panRecognizer;
if( event->type() == QEvent::MouseButtonPress )
{
const auto mouseEvent = static_cast< QMouseEvent* >( event );
auto mouseEvent = static_cast< const QMouseEvent* >( event );
if( ( item != this ) || ( recognizer.timeout() < 0 ) )
{
if( recognizer.hasProcessedBefore( mouseEvent ) )
{
return false;
}
}
recognizer.setTimeout( ( item == this ) ? -1 : 100 );
}

View File

@ -40,22 +40,19 @@ class Cube : public QskStackBox
explicit Cube( QQuickItem* parent = nullptr );
public Q_SLOTS:
void switchPosition( const Qsk::Direction direction );
void switchToPosition( const Cube::Position position );
void switchPosition( const Qsk::Direction );
void switchToPosition( const Cube::Position );
Q_SIGNALS:
// might be different from indexChanged:
void cubeIndexChanged( const int index );
protected:
void keyPressEvent( QKeyEvent* event ) override;
private:
Position currentPosition() const;
Position neighbor( const Position position, const Qsk::Direction direction ) const;
Position neighbor( const Position, const Qsk::Direction ) const;
Qsk::Direction direction( const Position from, const Position to ) const;
void updateEdge( Qsk::Direction direction, Position position );
void doSwitch( Qsk::Direction direction, Position position );
void updateEdge( Qsk::Direction, Position );
void doSwitch( Qsk::Direction, Position );
Position m_destination;
Edge m_currentEdge;
@ -73,8 +70,9 @@ class MainItem : public QskControl
MainItem( QQuickItem* parent = nullptr );
protected:
bool eventFilter(QObject* obj, QEvent* event) override final;
bool gestureFilter( QQuickItem*, QEvent* ) override final;
void keyPressEvent( QKeyEvent* ) override final;
bool gestureFilter( const QQuickItem*, const QEvent* ) override final;
void gestureEvent( QskGestureEvent* ) override final;
private:

View File

@ -33,7 +33,6 @@
#include <QskBoxShapeMetrics.h>
#include <QskColorFilter.h>
#include <QskFunctions.h>
#include <QskProgressBar.h>
#include <QskShadowMetrics.h>
#include <QskSkinHintTableEditor.h>
#include <QskStateCombination.h>

View File

@ -5,9 +5,6 @@
#include "StoragePage.h"
#include "Box.h"
#include "CircularProgressBar.h"
#include "Diagram.h"
#include "EnergyMeter.h"
#include "StorageBar.h"
#include "StorageMeter.h"
#include <QTimer>
@ -17,7 +14,6 @@
#include <QskGradient.h>
#include <QskGradientStop.h>
#include <QskGraphicLabel.h>
#include <QskProgressBar.h>
#include <QskPushButton.h>
#include <QskSkin.h>
#include <QskStackBox.h>

View File

@ -11,6 +11,7 @@ set(SOURCES
LinearLayoutPage.h LinearLayoutPage.cpp
DynamicConstraintsPage.h DynamicConstraintsPage.cpp
StackLayoutPage.h StackLayoutPage.cpp
SwipeViewPage.h SwipeViewPage.cpp
main.cpp
)
qt_add_resources(SOURCES layouts.qrc)

View File

@ -101,7 +101,7 @@ namespace
void incrementScrolling( Qt::Orientation orientation, int offset )
{
auto animator = dynamic_cast< QskStackBoxAnimator1* >( this->animator() );
auto animator = qobject_cast< QskStackBoxAnimator1* >( this->animator() );
if ( animator == nullptr )
{
@ -109,7 +109,11 @@ namespace
animator->setDuration( 1000 );
}
animator->setOrientation( orientation );
if ( orientation == Qt::Horizontal )
animator->setDirection( offset > 0 ? Qsk::LeftToRight : Qsk::RightToLeft );
else
animator->setDirection( offset > 0 ? Qsk::TopToBottom : Qsk::BottomToTop );
setAnimator( animator );
setCurrentIndex( incrementedIndex( offset ) );

View File

@ -0,0 +1,62 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "SwipeViewPage.h"
#include "TestRectangle.h"
#include <QskRgbValue.h>
#include <QskSwipeView.h>
namespace
{
class SwipeView : public QskSwipeView
{
Q_OBJECT
public:
SwipeView( QQuickItem* parent = nullptr )
: QskSwipeView( parent )
{
setObjectName( "SwipeView" );
setBackgroundColor( Qt::white );
setDefaultAlignment( Qt::AlignCenter );
setOrientation( Qt::Horizontal );
addRectangle( "Gold" );
addRectangle( "SeaGreen" );
addRectangle( "SlateBlue" );
addRectangle( "Peru" );
for ( int i = 0; i < itemCount(); i += 2 )
{
if ( auto control = qskControlCast( itemAtIndex( i ) ) )
control->setFixedSize( 200, 200 );
}
}
private:
void addRectangle( const char* colorName )
{
auto rect = new TestRectangle( colorName );
rect->setText( QString::number( itemCount() + 1 ) );
addItem( rect );
}
};
}
SwipeViewPage::SwipeViewPage( QQuickItem* parent )
: QskLinearBox( Qt::Vertical, parent )
{
setObjectName( "SwipeViewPage" );
setMargins( 10 );
setBackgroundColor( QskRgb::LightSteelBlue );
auto swipeView = new SwipeView();
addItem( swipeView );
}
#include "SwipeViewPage.moc"

View File

@ -0,0 +1,14 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#pragma once
#include <QskLinearBox.h>
class SwipeViewPage : public QskLinearBox
{
public:
SwipeViewPage( QQuickItem* parent = nullptr );
};

View File

@ -8,6 +8,7 @@
#include "LinearLayoutPage.h"
#include "GridLayoutPage.h"
#include "StackLayoutPage.h"
#include "SwipeViewPage.h"
#include "TestRectangle.h"
#include <SkinnyShortcut.h>
@ -37,6 +38,7 @@ namespace
addTab( "Linear Layout", new LinearLayoutPage() );
addTab( "Dynamic\nConstraints", new DynamicConstraintsPage() );
addTab( "Stack Layout", new StackLayoutPage() );
addTab( "Swipe View", new SwipeViewPage() );
setCurrentIndex( 0 );
}

View File

@ -79,6 +79,17 @@ class Thumbnail : public QskPushButton
setStrutSizeHint( QskPushButton::Icon, -1, -1 );
}
#if 0
void mousePressEvent( QMouseEvent* event ) override
{
/*
rgnore events: to check if the pae gesture recoognizer of the scroll
area becomes active without timeout ( see QskScrollBox::mousePressEvent )
*/
event->setAccepted( false );
}
#endif
private:
QskGraphic thumbnailGraphic( const QColor& color,
int shape, const QSizeF& size ) const

View File

@ -105,6 +105,6 @@ inline void ChartSample::setSample(
#ifndef QT_NO_DEBUG_STREAM
class QDebug;
QSK_EXPORT QDebug operator<<( QDebug, const ChartSample& );
QDebug operator<<( QDebug, const ChartSample& );
#endif

View File

@ -33,6 +33,7 @@
#include <QskPlacementPolicy.h>
#include <QskPopup.h>
#include <QskProgressBar.h>
#include <QskProgressRing.h>
#include <QskPushButton.h>
#include <QskRadioBox.h>
#include <QskScrollArea.h>
@ -220,6 +221,7 @@ void QskQml::registerTypes()
registerObject< QskFocusIndicator >();
registerObject< QskSeparator >();
registerObject< QskProgressBar >();
registerObject< QskProgressRing >();
registerObject< QskPushButton >();
registerObject< QskScrollView >();
registerObject< QskScrollArea >();

View File

@ -73,6 +73,7 @@
#include <QskCheckBox.h>
#include <QskComboBox.h>
#include <QskDialogButtonBox.h>
#include <QskDrawer.h>
#include <QskFocusIndicator.h>
#include <QskGraphicLabel.h>
#include <QskListView.h>
@ -80,6 +81,7 @@
#include <QskPageIndicator.h>
#include <QskPushButton.h>
#include <QskProgressBar.h>
#include <QskProgressRing.h>
#include <QskRadioBox.h>
#include <QskScrollView.h>
#include <QskSegmentedBar.h>
@ -194,6 +196,9 @@ namespace
void setupDialogButtonBoxMetrics();
void setupDialogButtonBoxColors( QskAspect::Section, const QskFluent2Theme& );
void setupDrawerMetrics();
void setupDrawerColors( QskAspect::Section, const QskFluent2Theme& );
void setupFocusIndicatorMetrics();
void setupFocusIndicatorColors( QskAspect::Section, const QskFluent2Theme& );
@ -212,6 +217,9 @@ namespace
void setupProgressBarMetrics();
void setupProgressBarColors( QskAspect::Section, const QskFluent2Theme& );
void setupProgressRingMetrics();
void setupProgressRingColors( QskAspect::Section, const QskFluent2Theme& );
void setupPushButtonMetrics();
void setupPushButtonColors( QskAspect::Section, const QskFluent2Theme& );
@ -285,12 +293,14 @@ void Editor::setupMetrics()
setupCheckBoxMetrics();
setupComboBoxMetrics();
setupDialogButtonBoxMetrics();
setupDrawerMetrics();
setupFocusIndicatorMetrics();
setupGraphicLabelMetrics();
setupListViewMetrics();
setupMenuMetrics();
setupPageIndicatorMetrics();
setupProgressBarMetrics();
setupProgressRingMetrics();
setupPushButtonMetrics();
setupRadioBoxMetrics();
setupScrollViewMetrics();
@ -320,6 +330,7 @@ void Editor::setupColors( QskAspect::Section section, const QskFluent2Theme& the
setupCheckBoxColors( section, theme );
setupComboBoxColors( section, theme );
setupDialogButtonBoxColors( section, theme );
setupDrawerColors( section, theme );
setupFocusIndicatorColors( section, theme );
setupGraphicLabelColors( section, theme );
setupGraphicLabelMetrics();
@ -327,6 +338,7 @@ void Editor::setupColors( QskAspect::Section section, const QskFluent2Theme& the
setupMenuColors( section, theme );
setupPageIndicatorColors( section, theme );
setupProgressBarColors( section, theme );
setupProgressRingColors( section, theme );
setupPushButtonColors( section, theme );
setupRadioBoxColors( section, theme );
setupScrollViewColors( section, theme );
@ -591,6 +603,26 @@ void Editor::setupDialogButtonBoxColors(
theme.palette.background.solid.base );
}
void Editor::setupDrawerMetrics()
{
using Q = QskDrawer;
setPadding( Q::Panel, 5 );
setHint( Q::Overlay | QskAspect::Style, false );
#if 1
setAnimation( Q::Panel | QskAspect::Position, 200 );
#endif
}
void Editor::setupDrawerColors(
QskAspect::Section section, const QskFluent2Theme& theme )
{
using Q = QskDrawer;
setGradient( Q::Panel | section, theme.palette.background.solid.base );
}
void Editor::setupFocusIndicatorMetrics()
{
using Q = QskFocusIndicator;
@ -612,8 +644,10 @@ void Editor::setupFocusIndicatorColors(
void Editor::setupListViewMetrics()
{
using Q = QskListView;
using A = QskAspect;
setBoxBorderMetrics( Q::Cell | Q::Selected, { 3, 0, 0, 0 } );
for ( auto state : { A::NoState, Q::Hovered, Q::Pressed } )
setBoxBorderMetrics( Q::Cell | state | Q::Selected, { 3, 0, 0, 0 } );
#if 1
// taken from M3 - what are the actual values, TODO ...
setPadding( Q::Cell, { 16, 12, 16, 12 } );
@ -637,7 +671,7 @@ void Editor::setupListViewColors(
textColor = pal.fillColor.text.disabled;
indicatorColor = pal.fillColor.accent.disabled;
}
if ( state1 == Q::Pressed )
else if ( state1 == Q::Pressed )
{
textColor = pal.fillColor.text.secondary;
indicatorColor = pal.fillColor.accent.defaultColor;
@ -693,6 +727,9 @@ void Editor::setupListViewColors(
setColor( text, textColor );
}
}
setAnimation( Q::Cell | A::Color, 100 );
setAnimation( Q::Text | A::Color, 100 );
}
void Editor::setupMenuMetrics()
@ -834,8 +871,8 @@ void Editor::setupProgressBarMetrics()
setMetric( Q::Groove | A::Size, 1 );
setBoxShape( Q::Groove, 100, Qt::RelativeSize );
setMetric( Q::Bar | A::Size, 3 );
setBoxShape( Q::Bar, 100, Qt::RelativeSize );
setMetric( Q::Fill | A::Size, 3 );
setBoxShape( Q::Fill, 100, Qt::RelativeSize );
}
void Editor::setupProgressBarColors(
@ -846,7 +883,36 @@ void Editor::setupProgressBarColors(
const auto& pal = theme.palette;
setGradient( Q::Groove | section, pal.strokeColor.controlStrong.defaultColor );
setGradient( Q::Bar | section, pal.fillColor.accent.defaultColor );
setGradient( Q::Fill | section, pal.fillColor.accent.defaultColor );
}
void Editor::setupProgressRingMetrics()
{
using Q = QskProgressRing;
using A = QskAspect;
static constexpr QskAspect::Variation SmallSize = A::Small;
static constexpr QskAspect::Variation NormalSize = A::NoVariation;
static constexpr QskAspect::Variation LargeSize = A::Large;
setStrutSize( Q::Fill | SmallSize, { 16, 16 } );
setStrutSize( Q::Fill | NormalSize, { 32, 32 } );
setStrutSize( Q::Fill | LargeSize, { 64, 64 } );
const auto startAngle = 90, spanAngle = -360;
setArcMetrics( Q::Fill | SmallSize, startAngle, spanAngle, 1.5 );
setArcMetrics( Q::Fill | NormalSize, startAngle, spanAngle, 3 );
setArcMetrics( Q::Fill | LargeSize, startAngle, spanAngle, 6 );
}
void Editor::setupProgressRingColors(
QskAspect::Section section, const QskFluent2Theme& theme )
{
using Q = QskProgressRing;
const auto& pal = theme.palette;
setGradient( Q::Fill | section, pal.fillColor.accent.defaultColor );
}
void Editor::setupPushButtonMetrics()

View File

@ -23,6 +23,7 @@
#include <QskPageIndicator.h>
#include <QskPushButton.h>
#include <QskProgressBar.h>
#include <QskProgressRing.h>
#include <QskRadioBox.h>
#include <QskScrollView.h>
#include <QskSegmentedBar.h>
@ -94,6 +95,7 @@ namespace
void setupPageIndicator();
void setupPopup();
void setupProgressBar();
void setupProgressRing();
void setupRadioBox();
void setupPushButton();
void setupScrollView();
@ -161,6 +163,7 @@ void Editor::setup()
setupPageIndicator();
setupPopup();
setupProgressBar();
setupProgressRing();
setupPushButton();
setupRadioBox();
setupScrollView();
@ -431,9 +434,9 @@ void Editor::setupProgressBar()
using A = QskAspect;
using Q = QskProgressBar;
auto size = 5_dp;
auto size = 4_dp;
for ( auto subControl : { Q::Groove, Q::Bar } )
for ( auto subControl : { Q::Groove, Q::Fill } )
{
setMetric( subControl | A::Size, size );
setPadding( subControl, 0 );
@ -443,12 +446,21 @@ void Editor::setupProgressBar()
}
setMetric( Q::Groove | A::Size, size );
setGradient( Q::Groove, m_pal.primaryContainer );
setGradient( Q::Groove, m_pal.surfaceContainerHighest );
setGradient( Q::Groove | Q::Disabled, m_pal.onSurface12 );
setGradient( Q::Bar, m_pal.primary );
setGradient( Q::Bar | Q::Disabled, m_pal.onSurface38 );
setGradient( Q::Fill, m_pal.primary );
setGradient( Q::Fill | Q::Disabled, m_pal.onSurface38 );
}
void Editor::setupProgressRing()
{
using Q = QskProgressRing;
setStrutSize( Q::Fill, { 48_dp, 48_dp } );
setGradient( Q::Fill, m_pal.primary );
setArcMetrics( Q::Fill, 90, -360, 4_dp );
}
void Editor::setupRadioBox()
@ -800,8 +812,9 @@ void Editor::setupDrawer()
setPadding( Q::Panel, 5_dp );
setGradient( Q::Panel, m_pal.background );
setAnimation( Q::Panel | QskAspect::Position, qskDuration );
setHint( Q::Overlay | QskAspect::Style, false );
setAnimation( Q::Panel | QskAspect::Position, qskDuration );
}
void Editor::setupSlider()
@ -1151,15 +1164,71 @@ void Editor::setupScrollView()
void Editor::setupListView()
{
using Q = QskListView;
using A = QskAspect;
setStrutSize( Q::Cell, { -1, 56 } );
setPadding( Q::Cell, { 16_dp, 12_dp, 16_dp, 12_dp } );
setStrutSize( Q::Cell, { -1, 56_dp } );
setPadding( Q::Cell, { 16_dp, 8_dp, 24_dp, 8_dp } );
setBoxBorderColors( Q::Cell, m_pal.outline );
setGradient( Q::Cell, m_pal.surface );
setGradient( Q::Cell | Q::Selected, m_pal.primary12 );
for ( const auto state1 : { A::NoState, Q::Hovered, Q::Focused, Q::Pressed, Q::Disabled } )
{
for ( const auto state2 : { A::NoState, Q::Selected } )
{
QRgb cellColor;
if ( state2 == A::NoState )
{
if ( state1 == Q::Hovered )
{
cellColor = flattenedColor( m_pal.onSurface,
m_pal.surface, m_pal.hoverOpacity );
}
else if ( state1 == Q::Pressed )
{
cellColor = flattenedColor( m_pal.onSurface,
m_pal.primary12, m_pal.pressedOpacity );
}
else
{
cellColor = m_pal.surface;
}
}
else
{
if ( state1 == Q::Hovered )
{
cellColor = flattenedColor( m_pal.onSurface,
m_pal.primary12, m_pal.focusOpacity );
}
else if ( state1 == Q::Focused )
{
cellColor = flattenedColor( m_pal.onSurface,
m_pal.primary12, m_pal.focusOpacity );
}
else if ( state1 == Q::Disabled )
{
cellColor = m_pal.surfaceVariant;
}
else
{
cellColor = m_pal.primary12;
}
}
setGradient( Q::Cell | state1 | state2, cellColor );
}
}
setFontRole( Q::Text, QskMaterial3Skin::M3BodyMedium );
setColor( Q::Text, m_pal.onSurface );
setColor( Q::Text | Q::Disabled, m_pal.onSurface38 );
#if 1
setAnimation( Q::Cell | A::Color, 100 );
setAnimation( Q::Text | A::Color, 100 );
#endif
}
void Editor::setupSubWindow()
@ -1246,6 +1315,8 @@ QskMaterial3Theme::QskMaterial3Theme( QskSkin::ColorScheme colorScheme,
outline = m_palettes[ NeutralVariant ].toned( 50 ).rgb();
outlineVariant = m_palettes[ NeutralVariant ].toned( 80 ).rgb();
surfaceContainerHighest = m_palettes[ NeutralVariant ].toned( 90 ).rgb();
shadow = m_palettes[ Neutral ].toned( 0 ).rgb();
}
else if ( colorScheme == QskSkin::DarkScheme )
@ -1280,6 +1351,8 @@ QskMaterial3Theme::QskMaterial3Theme( QskSkin::ColorScheme colorScheme,
outline = m_palettes[ NeutralVariant ].toned( 60 ).rgb();
outlineVariant = m_palettes[ NeutralVariant ].toned( 30 ).rgb();
surfaceContainerHighest = m_palettes[ NeutralVariant ].toned( 22 ).rgb();
shadow = m_palettes[ Neutral ].toned( 0 ).rgb();
}

View File

@ -79,6 +79,8 @@ class QSK_MATERIAL3_EXPORT QskMaterial3Theme
QRgb outline;
QRgb outlineVariant;
QRgb surfaceContainerHighest;
QRgb shadow;
QskShadowMetrics elevation0;

View File

@ -20,6 +20,7 @@
#include <QskPageIndicator.h>
#include <QskPopup.h>
#include <QskProgressBar.h>
#include <QskProgressRing.h>
#include <QskPushButton.h>
#include <QskRadioBox.h>
#include <QskScrollView.h>
@ -162,6 +163,7 @@ namespace
void setupPageIndicator();
void setupPopup();
void setupProgressBar();
void setupProgressRing();
void setupPushButton();
void setupRadioBox();
void setupScrollView();
@ -287,6 +289,7 @@ void Editor::setup()
setupPageIndicator();
setupPopup();
setupProgressBar();
setupProgressRing();
setupPushButton();
setupRadioBox();
setupScrollView();
@ -521,15 +524,35 @@ void Editor::setupProgressBar()
using A = QskAspect;
using Q = QskProgressBar;
for ( auto subControl : { Q::Groove, Q::Bar } )
for ( auto subControl : { Q::Groove, Q::Fill } )
{
setMetric( subControl | A::Size, 6 );
setPadding( subControl, 0 );
setBoxShape( subControl, 4 );
}
setGradient( Q::Groove, m_pal.darker200 );
setGradient( Q::Bar, m_pal.highlighted );
setGradient( Q::Groove, m_pal.lighter110 );
setGradient( Q::Fill, m_pal.highlighted );
}
void Editor::setupProgressRing()
{
using A = QskAspect;
using Q = QskProgressRing;
for ( auto subControl : { Q::Groove, Q::Fill } )
{
setMetric( subControl | A::Size, 6 );
setPadding( subControl, 0 );
setBoxShape( subControl, 4 );
}
setArcMetrics( Q::Groove, 90, -360, 6 );
setGradient( Q::Groove, m_pal.lighter110 );
setStrutSize( Q::Fill, { 60, 60 } );
setGradient( Q::Fill, m_pal.highlighted );
setArcMetrics( Q::Fill, 90, -360, 6 );
}
void Editor::setupFocusIndicator()
@ -1054,15 +1077,13 @@ void Editor::setupListView()
setPadding( Q::Cell, QskMargins( 4, 8 ) );
setColor( Q::Text, m_pal.themeForeground );
setColor( Q::Cell, Qt::white );
// alternating row colors
setColor( Q::Cell | A::Lower, Qt::white );
setColor( Q::Cell | Q::Selected | A::Lower, m_pal.highlighted );
setColor( Q::Cell | A::Upper, m_pal.contrasted );
setColor( Q::Cell | Q::Selected | A::Upper, m_pal.highlighted );
setColor( Q::Text | Q::Selected, m_pal.highlightedText );
for ( auto state : { A::NoState, Q::Hovered, Q::Pressed } )
{
setColor( Q::Cell | state | Q::Selected, m_pal.highlighted );
setColor( Q::Text | state | Q::Selected, m_pal.highlightedText );
}
}
void Editor::setupSubWindow()

View File

@ -197,10 +197,14 @@ list(APPEND HEADERS
controls/QskPanGestureRecognizer.h
controls/QskPopup.h
controls/QskPopupSkinlet.h
controls/QskPushButton.h
controls/QskPushButtonSkinlet.h
controls/QskProgressBar.h
controls/QskProgressBarSkinlet.h
controls/QskProgressIndicator.h
controls/QskProgressIndicatorSkinlet.h
controls/QskProgressRing.h
controls/QskProgressRingSkinlet.h
controls/QskPushButton.h
controls/QskPushButtonSkinlet.h
controls/QskQuick.h
controls/QskQuickItem.h
controls/QskRadioBox.h
@ -237,6 +241,7 @@ list(APPEND HEADERS
controls/QskSubWindowSkinlet.h
controls/QskSwitchButton.h
controls/QskSwitchButtonSkinlet.h
controls/QskSwipeView.h
controls/QskTabBar.h
controls/QskTabButton.h
controls/QskTabButtonSkinlet.h
@ -296,10 +301,14 @@ list(APPEND SOURCES
controls/QskPanGestureRecognizer.cpp
controls/QskPopup.cpp
controls/QskPopupSkinlet.cpp
controls/QskPushButton.cpp
controls/QskPushButtonSkinlet.cpp
controls/QskProgressBar.cpp
controls/QskProgressBarSkinlet.cpp
controls/QskProgressIndicator.cpp
controls/QskProgressIndicatorSkinlet.cpp
controls/QskProgressRing.cpp
controls/QskProgressRingSkinlet.cpp
controls/QskPushButton.cpp
controls/QskPushButtonSkinlet.cpp
controls/QskQuick.cpp
controls/QskQuickItem.cpp
controls/QskQuickItemPrivate.cpp
@ -336,6 +345,7 @@ list(APPEND SOURCES
controls/QskSubWindowSkinlet.cpp
controls/QskSwitchButton.cpp
controls/QskSwitchButtonSkinlet.cpp
controls/QskSwipeView.cpp
controls/QskTabBar.cpp
controls/QskTabButton.cpp
controls/QskTabButtonSkinlet.cpp

View File

@ -31,6 +31,20 @@ static inline void qskSendEventTo( QObject* object, QEvent::Type type )
QCoreApplication::sendEvent( object, &event );
}
static inline bool qskMaybeGesture( QQuickItem* item,
const QQuickItem* child, const QEvent* event )
{
if ( qskIsTouchOrMouseEvent( event->type() ) )
{
QskGestureFilterEvent ev( child, event );
QCoreApplication::sendEvent( item, &ev );
return ev.maybeGesture();
}
return false;
}
QskControl::QskControl( QQuickItem* parent )
: QskQuickItem( *( new QskControlPrivate() ), parent )
{
@ -791,6 +805,33 @@ bool QskControl::event( QEvent* event )
break;
}
case QskEvent::GestureFilter:
{
/*
qskMaybeGesture is sending an event, so that it can be manipulated
by event filters. F.e QskDrawer wants to add a gesture to
some other control to initiate its appearance.
*/
auto ev = static_cast< QskGestureFilterEvent* >( event );
if ( ev->event()->type() == QEvent::MouseButtonPress )
{
auto mouseEvent = static_cast< const QMouseEvent* >( ev->event() );
const auto pos =
mapFromItem( ev->item(), qskMousePosition( mouseEvent ) );
if ( !gestureRect().contains( pos ) )
{
ev->setMaybeGesture( false );
break;
}
}
ev->setMaybeGesture( gestureFilter( ev->item(), ev->event() ) );
break;
}
case QskEvent::Gesture:
{
gestureEvent( static_cast< QskGestureEvent* >( event ) );
@ -798,18 +839,18 @@ bool QskControl::event( QEvent* event )
}
}
if ( d_func()->maybeGesture( this, event ) )
if ( qskMaybeGesture( this, this, event ) )
return true;
return Inherited::event( event );
}
bool QskControl::childMouseEventFilter( QQuickItem* item, QEvent* event )
bool QskControl::childMouseEventFilter( QQuickItem* child, QEvent* event )
{
return d_func()->maybeGesture( item, event );
return qskMaybeGesture( this, child, event );
}
bool QskControl::gestureFilter( QQuickItem*, QEvent* )
bool QskControl::gestureFilter( const QQuickItem*, const QEvent* )
{
return false;
}

View File

@ -196,7 +196,7 @@ class QSK_EXPORT QskControl : public QskQuickItem, public QskSkinnable
void hoverLeaveEvent( QHoverEvent* ) override;
bool childMouseEventFilter( QQuickItem*, QEvent* ) override;
virtual bool gestureFilter( QQuickItem*, QEvent* );
virtual bool gestureFilter( const QQuickItem*, const QEvent* );
void itemChange( ItemChange, const ItemChangeData& ) override;
void geometryChange( const QRectF&, const QRectF& ) override;

View File

@ -8,6 +8,7 @@
#include "QskLayoutMetrics.h"
#include "QskObjectTree.h"
#include "QskWindow.h"
#include "QskEvent.h"
static inline void qskSendEventTo( QObject* object, QEvent::Type type )
{
@ -15,15 +16,6 @@ static inline void qskSendEventTo( QObject* object, QEvent::Type type )
QCoreApplication::sendEvent( object, &event );
}
static inline QPointF qskScenePosition( const QMouseEvent* event )
{
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
return event->scenePosition();
#else
return event->windowPos();
#endif
}
extern bool qskInheritLocale( QskWindow*, const QLocale& );
namespace
@ -309,41 +301,6 @@ QSizeF QskControlPrivate::explicitSizeHint( Qt::SizeHint whichHint ) const
return QSizeF();
}
bool QskControlPrivate::maybeGesture( QQuickItem* child, QEvent* event )
{
Q_Q( QskControl );
switch ( event->type() )
{
case QEvent::MouseButtonPress:
{
const auto mouseEvent = static_cast< const QMouseEvent* >( event );
auto pos = qskScenePosition( mouseEvent );
pos = q->mapFromScene( pos );
if ( !q->gestureRect().contains( pos ) )
return false;
break;
}
case QEvent::MouseMove:
case QEvent::MouseButtonRelease:
case QEvent::MouseButtonDblClick:
case QEvent::UngrabMouse:
case QEvent::TouchBegin:
case QEvent::TouchCancel:
case QEvent::TouchUpdate:
break;
default:
return false;
}
return q->gestureFilter( child, event );
}
bool QskControlPrivate::inheritLocale( QskControl* control, const QLocale& locale )
{
auto d = static_cast< QskControlPrivate* >( QQuickItemPrivate::get( control ) );

View File

@ -36,8 +36,6 @@ class QskControlPrivate : public QskQuickItemPrivate
void implicitSizeChanged() override final;
void layoutConstraintChanged() override final;
bool maybeGesture( QQuickItem*, QEvent* );
QskPlacementPolicy::Policy placementPolicy( bool visible ) const noexcept;
void setPlacementPolicy( bool visible, QskPlacementPolicy::Policy );

View File

@ -15,15 +15,15 @@ class QSK_EXPORT QskDrawer : public QskPopup
public:
QSK_SUBCONTROLS( Panel, Overlay )
QskDrawer( QQuickItem* parentItem = nullptr );
QskDrawer( QQuickItem* = nullptr );
~QskDrawer() override;
void setEdge( Qt::Edge edge );
void setEdge( Qt::Edge );
Qt::Edge edge() const;
void updateLayout() override;
void setContent( QskControl* t );
void setContent( QskControl* );
Q_SIGNALS:
void edgeChanged( Qt::Edge );

View File

@ -154,6 +154,28 @@ bool qskIsButtonPressKey( const QKeyEvent* event )
#endif
}
bool qskIsTouchOrMouseEvent( QEvent::Type type )
{
switch ( type )
{
case QEvent::MouseButtonPress:
case QEvent::MouseMove:
case QEvent::MouseButtonRelease:
case QEvent::MouseButtonDblClick:
case QEvent::UngrabMouse:
case QEvent::TouchBegin:
case QEvent::TouchCancel:
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
return true;
default:
return false;
}
}
QskEvent::QskEvent( QskEvent::Type type )
: QEvent( static_cast< QEvent::Type >( type ) )
{
@ -249,3 +271,19 @@ QskAnimatorEvent* QskAnimatorEvent::clone() const
{
return new QskAnimatorEvent( *this );
}
// -- QskGestureFilterEvent
QskGestureFilterEvent::QskGestureFilterEvent(
const QQuickItem* item, const QEvent* event )
: QskEvent( QskEvent::GestureFilter )
, m_item( item )
, m_event( event )
, m_maybeGesture( false )
{
}
QskGestureFilterEvent* QskGestureFilterEvent::clone() const
{
return new QskGestureFilterEvent( *this );
}

View File

@ -47,6 +47,7 @@ class QSK_EXPORT QskEvent : public QEvent
PopupRemoved,
Gesture,
GestureFilter,
Animator,
@ -118,6 +119,29 @@ class QSK_EXPORT QskPopupEvent : public QskEvent
QskPopup* m_popup;
};
class QSK_EXPORT QskGestureFilterEvent : public QskEvent
{
public:
QskGestureFilterEvent( const QQuickItem*, const QEvent* );
inline const QQuickItem* item() const { return m_item; }
inline const QEvent* event() const { return m_event; }
inline void setMaybeGesture( bool on ) { m_maybeGesture = on; }
inline bool maybeGesture() const { return m_maybeGesture; }
QskGestureFilterEvent* clone() const override;
protected:
QSK_EVENT_DISABLE_COPY( QskGestureFilterEvent )
private:
const QQuickItem* m_item;
const QEvent* m_event;
bool m_maybeGesture;
};
class QSK_EXPORT QskGestureEvent : public QskEvent
{
public:
@ -178,4 +202,6 @@ QSK_EXPORT qreal qskWheelIncrement( const QWheelEvent* );
QSK_EXPORT bool qskIsStandardKeyInput( const QKeyEvent*, QKeySequence::StandardKey );
QSK_EXPORT bool qskIsButtonPressKey( const QKeyEvent* );
QSK_EXPORT bool qskIsTouchOrMouseEvent( QEvent::Type );
#endif

View File

@ -295,7 +295,7 @@ QskGestureRecognizer::State QskGestureRecognizer::state() const
}
bool QskGestureRecognizer::processEvent(
QQuickItem* item, QEvent* event, bool blockReplayedEvents )
const QQuickItem* item, const QEvent* event, bool blockReplayedEvents )
{
if ( m_data->isReplayingEvents && blockReplayedEvents )
{
@ -331,7 +331,7 @@ bool QskGestureRecognizer::processEvent(
if ( buttons == Qt::NoButton )
buttons = watchedItem->acceptedMouseButtons();
auto mouseEvent = static_cast< QMouseEvent* >( event );
auto mouseEvent = static_cast< const QMouseEvent* >( event );
if ( !( buttons & mouseEvent->button() ) )
return false;
@ -383,7 +383,7 @@ bool QskGestureRecognizer::processEvent(
{
case QEvent::MouseButtonPress:
{
auto mouseEvent = static_cast< QMouseEvent* >( event );
auto mouseEvent = static_cast< const QMouseEvent* >( event );
m_data->pendingEvents += qskClonedMouseEvent( mouseEvent );
pressEvent( mouseEvent );
@ -392,7 +392,7 @@ bool QskGestureRecognizer::processEvent(
case QEvent::MouseMove:
{
auto mouseEvent = static_cast< QMouseEvent* >( event );
auto mouseEvent = static_cast< const QMouseEvent* >( event );
m_data->pendingEvents += qskClonedMouseEvent( mouseEvent );
moveEvent( mouseEvent );
@ -401,7 +401,7 @@ bool QskGestureRecognizer::processEvent(
case QEvent::MouseButtonRelease:
{
auto mouseEvent = static_cast< QMouseEvent* >( event );
auto mouseEvent = static_cast< const QMouseEvent* >( event );
m_data->pendingEvents += qskClonedMouseEvent( mouseEvent );
if ( m_data->state == Pending )

View File

@ -41,7 +41,7 @@ class QSK_EXPORT QskGestureRecognizer
// timestamp, when the Idle state had been left
ulong timestamp() const;
bool processEvent( QQuickItem*, QEvent*, bool blockReplayedEvents = true );
bool processEvent( const QQuickItem*, const QEvent*, bool blockReplayedEvents = true );
void reject();
void accept();

View File

@ -46,6 +46,43 @@ class QskListView::PrivateData
{
}
void setRowState( QskListView* listView, int row, QskAspect::State state )
{
using Q = QskListView;
auto& storedRow = ( state == Q::Hovered )
? hoveredRow : ( ( state == Q::Pressed ) ? pressedRow : selectedRow );
if ( row == storedRow )
return;
if ( storedRow >= 0 )
{
const auto states = listView->rowStates( storedRow );
startTransitions( listView, storedRow, states, states & ~state );
}
if ( row >= 0 )
{
const auto states = listView->rowStates( row );
startTransitions( listView, row, states, states | state );
}
storedRow = row;
listView->update();
}
private:
inline void startTransitions( QskListView* listView, int row,
QskAspect::States oldStates, QskAspect::States newStates )
{
using Q = QskListView;
listView->startHintTransitions(
{ Q::Cell, Q::Text }, oldStates, newStates, row );
}
public:
/*
Currently we only support single selection. We can't navigate
the current item ( = focus ) without changing the selection.
@ -55,6 +92,8 @@ class QskListView::PrivateData
bool preferredWidthFromColumns : 1;
SelectionMode selectionMode : 4;
int hoveredRow = -1;
int pressedRow = -1;
int selectedRow = -1;
};
@ -131,7 +170,8 @@ void QskListView::setSelectedRow( int row )
if ( row != m_data->selectedRow )
{
m_data->selectedRow = row;
m_data->setRowState( this, row, Selected );
Q_EMIT selectedRowChanged( row );
Q_EMIT focusIndicatorRectChanged();
@ -280,6 +320,7 @@ void QskListView::mousePressEvent( QMouseEvent* event )
const int row = qskRowAt( this, qskMousePosition( event ) );
if ( row >= 0 )
{
m_data->setRowState( this, row, Pressed );
setSelectedRow( row );
return;
}
@ -290,9 +331,44 @@ void QskListView::mousePressEvent( QMouseEvent* event )
void QskListView::mouseReleaseEvent( QMouseEvent* event )
{
m_data->setRowState( this, -1, Pressed );
Inherited::mouseReleaseEvent( event );
}
void QskListView::mouseUngrabEvent()
{
m_data->setRowState( this, -1, Pressed );
Inherited::mouseUngrabEvent();
}
void QskListView::hoverEnterEvent( QHoverEvent* event )
{
if ( m_data->selectionMode != NoSelection )
{
const int row = qskRowAt( this, qskHoverPosition( event ) );
m_data->setRowState( this, row, Hovered );
}
Inherited::hoverEnterEvent( event );
}
void QskListView::hoverMoveEvent( QHoverEvent* event )
{
if ( m_data->selectionMode != NoSelection )
{
const int row = qskRowAt( this, qskHoverPosition( event ) );
m_data->setRowState( this, row, Hovered );
}
Inherited::hoverMoveEvent( event );
}
void QskListView::hoverLeaveEvent( QHoverEvent* event )
{
m_data->setRowState( this, -1, Hovered );
Inherited::hoverLeaveEvent( event );
}
void QskListView::changeEvent( QEvent* event )
{
if ( event->type() == QEvent::StyleChange )
@ -301,6 +377,25 @@ void QskListView::changeEvent( QEvent* event )
Inherited::changeEvent( event );
}
QskAspect::States QskListView::rowStates( int row ) const
{
auto states = skinStates();
if ( row >= 0 )
{
if ( row == m_data->selectedRow )
states |= Selected;
if ( row == m_data->hoveredRow )
states |= Hovered;
if ( row == m_data->pressedRow )
states |= Pressed;
}
return states;
}
#ifndef QT_NO_WHEELEVENT
static qreal qskAlignedToRows( const qreal y0, qreal dy,

View File

@ -54,6 +54,7 @@ class QSK_EXPORT QskListView : public QskScrollView
QskTextOptions textOptions() const;
Q_INVOKABLE int selectedRow() const;
QskAspect::States rowStates( int ) const;
virtual int rowCount() const = 0;
virtual int columnCount() const = 0;
@ -83,6 +84,11 @@ class QSK_EXPORT QskListView : public QskScrollView
void mousePressEvent( QMouseEvent* ) override;
void mouseReleaseEvent( QMouseEvent* ) override;
void mouseUngrabEvent() override;
void hoverEnterEvent( QHoverEvent* ) override;
void hoverMoveEvent( QHoverEvent* ) override;
void hoverLeaveEvent( QHoverEvent* ) override;
#ifndef QT_NO_WHEELEVENT
virtual QPointF scrollOffset( const QWheelEvent* ) const override;

View File

@ -196,7 +196,6 @@ void QskListViewSkinlet::updateBackgroundNodes(
const QskListView* listView, QSGNode* backgroundNode ) const
{
using Q = QskListView;
using A = QskAspect;
auto listViewNode = static_cast< const ListViewNode* >( backgroundNode->parent() );
@ -205,14 +204,11 @@ void QskListViewSkinlet::updateBackgroundNodes(
for ( int row = listViewNode->rowMin(); row <= listViewNode->rowMax(); row++ )
{
QskSkinStateChanger stateChanger( listView );
stateChanger.setStates( sampleStates( listView, Q::Cell, row ) );
stateChanger.setStates( sampleStates( listView, Q::Cell, row ), row );
const auto rect = sampleRect( listView, listView->contentsRect(), Q::Cell, row );
const QskAspect aspect = Q::Cell | ( ( row % 2 ) ? A::Upper : A::Lower );
const auto boxHints = listView->boxHints( aspect );
auto newNode = updateBoxNode( listView, rowNode, rect, boxHints );
auto newNode = updateBoxNode( listView, rowNode, rect, Q::Cell );
if ( newNode )
{
if ( newNode->parent() != backgroundNode )
@ -395,7 +391,7 @@ QSGNode* QskListViewSkinlet::updateCellNode( const QskListView* listView,
using namespace QskSGNode;
QskSkinStateChanger stateChanger( listView );
stateChanger.setStates( sampleStates( listView, Q::Cell, row ) );
stateChanger.setStates( sampleStates( listView, Q::Cell, row ), row );
QSGNode* newNode = nullptr;
@ -470,12 +466,7 @@ QskAspect::States QskListViewSkinlet::sampleStates( const QskSkinnable* skinnabl
if ( subControl == Q::Cell || subControl == Q::Text || subControl == Q::Graphic )
{
const auto listView = static_cast< const QskListView* >( skinnable );
auto states = listView->skinStates();
if ( index == listView->selectedRow() )
states |= Q::Selected;
return states;
return listView->rowStates( index );
}
return Inherited::sampleStates( skinnable, subControl, index );

View File

@ -6,91 +6,30 @@
#include "QskProgressBar.h"
#include "QskIntervalF.h"
#include "QskFunctions.h"
#include "QskAnimator.h"
#include "QskAspect.h"
QSK_SUBCONTROL( QskProgressBar, Groove )
QSK_SUBCONTROL( QskProgressBar, Bar )
namespace
{
class PositionAnimator : public QskAnimator
{
public:
PositionAnimator( QskProgressBar* progressBar )
: m_progressBar( progressBar )
{
setAutoRepeat( true );
setDuration( 1300 );
setWindow( progressBar->window() );
}
void advance( qreal value ) override
{
if ( m_progressBar->setPositionHint( QskProgressBar::Bar, value ) )
m_progressBar->update();
}
private:
QskProgressBar* m_progressBar;
};
}
QSK_SUBCONTROL( QskProgressBar, Fill )
class QskProgressBar::PrivateData
{
public:
void updateIndeterminateAnimator( QskProgressBar* progressBar )
{
if ( !isIndeterminate )
{
delete animator;
animator = nullptr;
return;
}
if ( progressBar->window() && progressBar->isVisible() )
{
if ( animator == nullptr )
animator = new PositionAnimator( progressBar );
animator->start();
}
else
{
if ( animator )
animator->stop();
}
}
PositionAnimator* animator = nullptr;
qreal value = 0.0;
qreal origin = 0.0;
bool hasOrigin = false;
bool isIndeterminate = false;
Qt::Orientation orientation;
};
QskProgressBar::QskProgressBar( Qt::Orientation orientation,
qreal min, qreal max, QQuickItem* parent )
: QskBoundedControl( min, max, parent )
: Inherited( min, max, parent )
, m_data( new PrivateData )
{
m_data->orientation = orientation;
m_data->value = minimum();
if ( orientation == Qt::Horizontal )
initSizePolicy( QskSizePolicy::MinimumExpanding, QskSizePolicy::Fixed );
else
initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::MinimumExpanding );
connect( this, &QskBoundedControl::boundariesChanged,
this, &QskProgressBar::adjustValue );
setSubcontrolProxy( Inherited::Groove, Groove );
setSubcontrolProxy( Inherited::Fill, Fill );
}
QskProgressBar::QskProgressBar( Qt::Orientation orientation, QQuickItem* parent )
@ -115,7 +54,12 @@ QskProgressBar::QskProgressBar( QQuickItem* parent )
QskProgressBar::~QskProgressBar()
{
delete m_data->animator;
}
QskAspect::Variation QskProgressBar::effectiveVariation() const
{
// so you can define different hints depending on the orientation
return static_cast< QskAspect::Variation >( m_data->orientation );
}
Qt::Orientation QskProgressBar::orientation() const
@ -137,163 +81,4 @@ void QskProgressBar::setOrientation( Qt::Orientation orientation )
}
}
bool QskProgressBar::isIndeterminate() const
{
return m_data->isIndeterminate;
}
void QskProgressBar::setIndeterminate( bool on )
{
if ( on == m_data->isIndeterminate )
return;
m_data->isIndeterminate = on;
m_data->updateIndeterminateAnimator( this );
update();
Q_EMIT indeterminateChanged( on );
}
QskAspect::Variation QskProgressBar::effectiveVariation() const
{
// so you can define different hints depending on the orientation
return static_cast< QskAspect::Variation >( m_data->orientation );
}
void QskProgressBar::setBarGradient( const QskGradient& gradient )
{
setGradientHint( Bar, gradient );
}
void QskProgressBar::resetBarGradient()
{
resetColor( Bar );
}
QskGradient QskProgressBar::barGradient() const
{
return gradientHint( QskProgressBar::Bar );
}
void QskProgressBar::setExtent( qreal extent )
{
if ( extent < 0.0 )
extent = 0.0;
if ( setMetric( Groove | QskAspect::Size, extent ) )
Q_EMIT extentChanged( extent );
}
void QskProgressBar::resetExtent()
{
if ( resetMetric( Groove | QskAspect::Size ) )
Q_EMIT extentChanged( extent() );
}
qreal QskProgressBar::extent() const
{
auto grooveSize = metric( Groove | QskAspect::Size );
auto barSize = metric( Bar | QskAspect::Size );
return qMax( grooveSize, barSize );
}
void QskProgressBar::setOrigin( qreal origin )
{
if ( isComponentComplete() )
origin = boundedValue( origin );
if( !m_data->hasOrigin || !qskFuzzyCompare( m_data->origin, origin ) )
{
m_data->hasOrigin = true;
m_data->origin = origin;
update();
Q_EMIT originChanged( origin );
}
}
void QskProgressBar::resetOrigin()
{
if ( m_data->hasOrigin )
{
m_data->hasOrigin = false;
update();
Q_EMIT originChanged( origin() );
}
}
qreal QskProgressBar::origin() const
{
if ( m_data->hasOrigin )
{
return boundedValue( m_data->origin );
}
return minimum();
}
void QskProgressBar::setValue( qreal value )
{
if ( isComponentComplete() )
value = boundedValue( value );
setValueInternal( value );
}
qreal QskProgressBar::value() const
{
return m_data->value;
}
void QskProgressBar::setValueAsRatio( qreal ratio )
{
ratio = qBound( 0.0, ratio, 1.0 );
setValue( minimum() + ratio * boundaryLength() );
}
qreal QskProgressBar::valueAsRatio() const
{
return valueAsRatio( m_data->value );
}
void QskProgressBar::componentComplete()
{
Inherited::componentComplete();
adjustValue();
}
void QskProgressBar::adjustValue()
{
if ( isComponentComplete() )
setValueInternal( boundedValue( m_data->value ) );
}
void QskProgressBar::setValueInternal( qreal value )
{
if ( !qskFuzzyCompare( value, m_data->value ) )
{
m_data->value = value;
Q_EMIT valueChanged( value );
update();
}
}
void QskProgressBar::itemChange( QQuickItem::ItemChange change,
const QQuickItem::ItemChangeData& value )
{
switch( static_cast< int >( change ) )
{
case QQuickItem::ItemVisibleHasChanged:
case QQuickItem::ItemSceneChange:
{
m_data->updateIndeterminateAnimator( this );
break;
}
}
Inherited::itemChange( change, value );
}
#include "moc_QskProgressBar.cpp"

View File

@ -6,34 +6,19 @@
#ifndef QSK_PROGRESS_BAR_H
#define QSK_PROGRESS_BAR_H
#include "QskBoundedControl.h"
#include "QskProgressIndicator.h"
class QskIntervalF;
class QSK_EXPORT QskProgressBar : public QskBoundedControl
class QSK_EXPORT QskProgressBar : public QskProgressIndicator
{
Q_OBJECT
Q_PROPERTY( Qt::Orientation orientation READ orientation
WRITE setOrientation NOTIFY orientationChanged )
Q_PROPERTY( qreal extent READ extent
WRITE setExtent RESET resetExtent NOTIFY extentChanged )
Q_PROPERTY( bool indeterminate READ isIndeterminate
WRITE setIndeterminate NOTIFY indeterminateChanged )
Q_PROPERTY( qreal origin READ origin
WRITE setOrigin RESET resetOrigin NOTIFY originChanged )
Q_PROPERTY( qreal value READ value WRITE setValue NOTIFY valueChanged )
Q_PROPERTY( qreal valueAsRatio READ valueAsRatio
WRITE setValueAsRatio NOTIFY valueChanged )
using Inherited = QskBoundedControl;
using Inherited = QskProgressIndicator;
public:
QSK_SUBCONTROLS( Groove, Bar )
QSK_SUBCONTROLS( Groove, Fill )
QskProgressBar( Qt::Orientation, QQuickItem* parent = nullptr );
QskProgressBar( Qt::Orientation, qreal min, qreal max, QQuickItem* parent = nullptr );
@ -43,50 +28,15 @@ class QSK_EXPORT QskProgressBar : public QskBoundedControl
~QskProgressBar() override;
QskAspect::Variation effectiveVariation() const override;
Qt::Orientation orientation() const;
void setOrientation( Qt::Orientation orientation );
bool isIndeterminate() const;
void setIndeterminate( bool on = true );
QskAspect::Variation effectiveVariation() const override;
void setBarGradient( const QskGradient& );
void resetBarGradient();
QskGradient barGradient() const;
void setExtent( qreal );
void resetExtent();
qreal extent() const;
void resetOrigin();
qreal origin() const;
qreal value() const;
qreal valueAsRatio() const; // [0.0, 1.0]
using QskBoundedControl::valueAsRatio;
public Q_SLOTS:
void setValue( qreal );
void setValueAsRatio( qreal );
void setOrigin( qreal );
Q_SIGNALS:
void orientationChanged( Qt::Orientation );
void extentChanged( qreal );
void indeterminateChanged( bool );
void valueChanged( qreal );
void originChanged( qreal );
protected:
void componentComplete() override;
void itemChange( ItemChange, const ItemChangeData& ) override;
private:
void setValueInternal( qreal value );
void adjustBoundaries( bool increasing );
void adjustValue();
class PrivateData;
std::unique_ptr< PrivateData > m_data;
};

View File

@ -7,18 +7,21 @@
#include "QskProgressBar.h"
#include "QskIntervalF.h"
#include "QskBoxBorderMetrics.h"
#include "QskGradientDirection.h"
#include <qeasingcurve.h>
#include <cmath>
static inline QskIntervalF qskBarInterval( const QskProgressBar* bar )
using Q = QskProgressBar;
namespace
{
QskIntervalF qskFillInterval( const Q* bar )
{
qreal pos1, pos2;
if ( bar->isIndeterminate() )
{
const auto pos = bar->positionHint( QskProgressBar::Bar );
const auto pos = bar->positionHint( QskProgressIndicator::Fill );
static const QEasingCurve curve( QEasingCurve::InOutCubic );
@ -47,11 +50,11 @@ static inline QskIntervalF qskBarInterval( const QskProgressBar* bar )
return QskIntervalF( pos1, pos2 );
}
}
QskProgressBarSkinlet::QskProgressBarSkinlet( QskSkin* skin )
: QskSkinlet( skin )
: Inherited( skin )
{
setNodeRoles( { GrooveRole, BarRole } );
}
QskProgressBarSkinlet::~QskProgressBarSkinlet()
@ -62,7 +65,6 @@ QRectF QskProgressBarSkinlet::subControlRect(
const QskSkinnable* skinnable, const QRectF& contentsRect,
QskAspect::Subcontrol subControl ) const
{
using Q = QskProgressBar;
const auto bar = static_cast< const Q* >( skinnable );
if( subControl == Q::Groove )
@ -84,7 +86,7 @@ QRectF QskProgressBarSkinlet::subControlRect(
return rect;
}
if( subControl == Q::Bar )
if( subControl == Q::Fill )
{
return barRect( bar );
}
@ -92,30 +94,18 @@ QRectF QskProgressBarSkinlet::subControlRect(
return Inherited::subControlRect( skinnable, contentsRect, subControl );
}
QSGNode* QskProgressBarSkinlet::updateSubNode(
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
QSGNode* QskProgressBarSkinlet::updateGrooveNode(
const QskProgressIndicator* indicator, QSGNode* node ) const
{
switch( nodeRole )
{
case GrooveRole:
{
return updateBoxNode( skinnable, node, QskProgressBar::Groove );
return updateBoxNode( indicator, node, Q::Groove );
}
case BarRole:
QSGNode* QskProgressBarSkinlet::updateFillNode(
const QskProgressIndicator* indicator, QSGNode* node ) const
{
const auto bar = static_cast< const QskProgressBar* >( skinnable );
return updateBarNode( bar, node );
}
}
const auto bar = static_cast< const Q* >( indicator );
return Inherited::updateSubNode( skinnable, nodeRole, node );
}
QSGNode* QskProgressBarSkinlet::updateBarNode(
const QskProgressBar* bar, QSGNode* node ) const
{
const auto subControl = QskProgressBar::Bar;
const auto subControl = Q::Fill;
const auto rect = bar->subControlRect( subControl );
if ( rect.isEmpty() )
@ -139,26 +129,27 @@ QSGNode* QskProgressBarSkinlet::updateBarNode(
not supporting this yet. TODO ...
*/
const auto intv = qskBarInterval( bar );
const auto intv = qskFillInterval( bar );
const auto stops = qskExtractedGradientStops( gradient.stops(),
intv.lowerBound(), intv.upperBound() );
gradient.setStops( stops );
gradient.setLinearDirection( bar->orientation() );
gradient.setLinearDirection( static_cast< Qt::Orientation >( bar->orientation() ) );
if ( bar->orientation() == Qt::Vertical || bar->layoutMirroring() )
gradient.reverse();
}
return updateBoxNode( bar, node, rect, gradient, subControl );
return updateBoxNode( indicator, node, rect, gradient, subControl );
}
QRectF QskProgressBarSkinlet::barRect( const QskProgressBar* bar ) const
QRectF QskProgressBarSkinlet::barRect( const Q* bar ) const
{
using Q = QskProgressBar;
const auto subControl = Q::Groove;
const auto barSize = bar->metric( Q::Bar | QskAspect::Size );
const auto barSize = bar->metric( Q::Fill | QskAspect::Size );
auto rect = bar->subControlRect( subControl );
if ( bar->orientation() == Qt::Horizontal )
@ -179,7 +170,7 @@ QRectF QskProgressBarSkinlet::barRect( const QskProgressBar* bar ) const
rect = rect.marginsRemoved( m );
const auto intv = qskBarInterval( bar );
const auto intv = qskFillInterval( bar );
if( bar->orientation() == Qt::Horizontal )
{
@ -205,7 +196,7 @@ QSizeF QskProgressBarSkinlet::sizeHint( const QskSkinnable* skinnable,
if ( which != Qt::PreferredSize )
return QSizeF();
const auto bar = static_cast< const QskProgressBar* >( skinnable );
const auto bar = static_cast< const Q* >( skinnable );
const auto extent = bar->extent();

View File

@ -6,25 +6,17 @@
#ifndef QSK_PROGRESS_BAR_SKINLET_H
#define QSK_PROGRESS_BAR_SKINLET_H
#include "QskSkinlet.h"
#include "QskProgressIndicatorSkinlet.h"
class QskProgressBar;
class QSK_EXPORT QskProgressBarSkinlet : public QskSkinlet
class QSK_EXPORT QskProgressBarSkinlet : public QskProgressIndicatorSkinlet
{
Q_GADGET
using Inherited = QskSkinlet;
using Inherited = QskProgressIndicatorSkinlet;
public:
enum NodeRole
{
GrooveRole,
BarRole,
RoleCount
};
Q_INVOKABLE QskProgressBarSkinlet( QskSkin* = nullptr );
~QskProgressBarSkinlet() override;
@ -35,11 +27,10 @@ class QSK_EXPORT QskProgressBarSkinlet : public QskSkinlet
Qt::SizeHint, const QSizeF& ) const override;
protected:
QSGNode* updateSubNode( const QskSkinnable*,
quint8 nodeRole, QSGNode* ) const override;
QSGNode* updateGrooveNode( const QskProgressIndicator*, QSGNode* ) const override;
QSGNode* updateFillNode( const QskProgressIndicator*, QSGNode* ) const override;
private:
QSGNode* updateBarNode( const QskProgressBar*, QSGNode* ) const;
QRectF barRect( const QskProgressBar* ) const;
};

View File

@ -0,0 +1,255 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "QskProgressIndicator.h"
#include "QskIntervalF.h"
#include "QskFunctions.h"
#include "QskAnimator.h"
#include "QskAspect.h"
QSK_SUBCONTROL( QskProgressIndicator, Groove )
QSK_SUBCONTROL( QskProgressIndicator, Fill )
namespace
{
class PositionAnimator : public QskAnimator
{
public:
PositionAnimator( QskProgressIndicator* indicator )
: m_indicator( indicator )
{
setAutoRepeat( true );
setDuration( 1300 );
setWindow( indicator->window() );
}
void advance( qreal value ) override
{
if ( m_indicator->setPositionHint( QskProgressIndicator::Fill, value ) )
m_indicator->update();
}
private:
QskProgressIndicator* m_indicator;
};
}
class QskProgressIndicator::PrivateData
{
public:
void updateIndeterminateAnimator( QskProgressIndicator* indicator )
{
if ( !isIndeterminate )
{
delete animator;
animator = nullptr;
return;
}
if ( indicator->window() && indicator->isVisible() )
{
if ( animator == nullptr )
animator = new PositionAnimator( indicator );
animator->start();
}
else
{
if ( animator )
animator->stop();
}
}
PositionAnimator* animator = nullptr;
qreal value = 0.0;
qreal origin = 0.0;
bool hasOrigin = false;
bool isIndeterminate = false;
};
QskProgressIndicator::QskProgressIndicator( qreal min, qreal max, QQuickItem* parent )
: QskBoundedControl( min, max, parent )
, m_data( new PrivateData )
{
m_data->value = minimum();
connect( this, &QskBoundedControl::boundariesChanged,
this, &QskProgressIndicator::adjustValue );
}
QskProgressIndicator::QskProgressIndicator( QQuickItem* parent )
: QskProgressIndicator( 0.0, 100.0, parent )
{
}
QskProgressIndicator::QskProgressIndicator( const QskIntervalF& boundaries, QQuickItem* parent )
: QskProgressIndicator( boundaries.lowerBound(), boundaries.upperBound(), parent )
{
}
QskProgressIndicator::~QskProgressIndicator()
{
delete m_data->animator;
}
bool QskProgressIndicator::isIndeterminate() const
{
return m_data->isIndeterminate;
}
void QskProgressIndicator::setIndeterminate( bool on )
{
if ( on == m_data->isIndeterminate )
return;
m_data->isIndeterminate = on;
m_data->updateIndeterminateAnimator( this );
update();
Q_EMIT indeterminateChanged( on );
}
void QskProgressIndicator::setFillGradient( const QskGradient& gradient )
{
setGradientHint( Fill, gradient );
}
void QskProgressIndicator::resetFillGradient()
{
resetColor( Fill );
}
QskGradient QskProgressIndicator::fillGradient() const
{
return gradientHint( Fill );
}
void QskProgressIndicator::setExtent( qreal extent )
{
if ( extent < 0.0 )
extent = 0.0;
if ( setMetric( Groove | QskAspect::Size, extent ) )
Q_EMIT extentChanged( extent );
}
void QskProgressIndicator::resetExtent()
{
if ( resetMetric( Groove | QskAspect::Size ) )
Q_EMIT extentChanged( extent() );
}
qreal QskProgressIndicator::extent() const
{
auto grooveSize = metric( Groove | QskAspect::Size );
auto fillSize = metric( Fill | QskAspect::Size );
return qMax( grooveSize, fillSize );
}
void QskProgressIndicator::setOrigin( qreal origin )
{
if ( isComponentComplete() )
origin = boundedValue( origin );
if( !m_data->hasOrigin || !qskFuzzyCompare( m_data->origin, origin ) )
{
m_data->hasOrigin = true;
m_data->origin = origin;
update();
Q_EMIT originChanged( origin );
}
}
void QskProgressIndicator::resetOrigin()
{
if ( m_data->hasOrigin )
{
m_data->hasOrigin = false;
update();
Q_EMIT originChanged( origin() );
}
}
qreal QskProgressIndicator::origin() const
{
if ( m_data->hasOrigin )
{
return boundedValue( m_data->origin );
}
return minimum();
}
void QskProgressIndicator::setValue( qreal value )
{
if ( isComponentComplete() )
value = boundedValue( value );
setValueInternal( value );
}
qreal QskProgressIndicator::value() const
{
return m_data->value;
}
void QskProgressIndicator::setValueAsRatio( qreal ratio )
{
ratio = qBound( 0.0, ratio, 1.0 );
setValue( minimum() + ratio * boundaryLength() );
}
qreal QskProgressIndicator::valueAsRatio() const
{
return valueAsRatio( m_data->value );
}
void QskProgressIndicator::componentComplete()
{
Inherited::componentComplete();
adjustValue();
}
void QskProgressIndicator::adjustValue()
{
if ( isComponentComplete() )
setValueInternal( boundedValue( m_data->value ) );
}
void QskProgressIndicator::setValueInternal( qreal value )
{
if ( !qskFuzzyCompare( value, m_data->value ) )
{
m_data->value = value;
Q_EMIT valueChanged( value );
update();
}
}
void QskProgressIndicator::itemChange( QQuickItem::ItemChange change,
const QQuickItem::ItemChangeData& value )
{
switch( static_cast< int >( change ) )
{
case QQuickItem::ItemVisibleHasChanged:
case QQuickItem::ItemSceneChange:
{
m_data->updateIndeterminateAnimator( this );
break;
}
}
Inherited::itemChange( change, value );
}
#include "moc_QskProgressIndicator.cpp"

View File

@ -0,0 +1,83 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#ifndef QSK_PROGRESS_INDICATOR_H
#define QSK_PROGRESS_INDICATOR_H
#include "QskBoundedControl.h"
class QskIntervalF;
class QSK_EXPORT QskProgressIndicator : public QskBoundedControl
{
Q_OBJECT
Q_PROPERTY( qreal extent READ extent
WRITE setExtent RESET resetExtent NOTIFY extentChanged )
Q_PROPERTY( bool indeterminate READ isIndeterminate
WRITE setIndeterminate NOTIFY indeterminateChanged )
Q_PROPERTY( qreal origin READ origin
WRITE setOrigin RESET resetOrigin NOTIFY originChanged )
Q_PROPERTY( qreal value READ value WRITE setValue NOTIFY valueChanged )
Q_PROPERTY( qreal valueAsRatio READ valueAsRatio
WRITE setValueAsRatio NOTIFY valueChanged )
using Inherited = QskBoundedControl;
public:
QSK_SUBCONTROLS( Groove, Fill )
QskProgressIndicator( QQuickItem* parent = nullptr );
QskProgressIndicator( qreal min, qreal max, QQuickItem* parent = nullptr );
QskProgressIndicator( const QskIntervalF&, QQuickItem* parent = nullptr );
~QskProgressIndicator() override;
bool isIndeterminate() const;
void setIndeterminate( bool on = true );
void setFillGradient( const QskGradient& );
void resetFillGradient();
QskGradient fillGradient() const;
void setExtent( qreal );
void resetExtent();
qreal extent() const;
void resetOrigin();
qreal origin() const;
qreal value() const;
qreal valueAsRatio() const; // [0.0, 1.0]
using QskBoundedControl::valueAsRatio;
public Q_SLOTS:
void setValue( qreal );
void setValueAsRatio( qreal );
void setOrigin( qreal );
Q_SIGNALS:
void extentChanged( qreal );
void indeterminateChanged( bool );
void valueChanged( qreal );
void originChanged( qreal );
protected:
void componentComplete() override;
void itemChange( ItemChange, const ItemChangeData& ) override;
private:
void setValueInternal( qreal value );
void adjustBoundaries( bool increasing );
void adjustValue();
class PrivateData;
std::unique_ptr< PrivateData > m_data;
};
#endif

View File

@ -0,0 +1,38 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "QskProgressIndicatorSkinlet.h"
#include "QskProgressIndicator.h"
QskProgressIndicatorSkinlet::QskProgressIndicatorSkinlet( QskSkin* skin )
: Inherited( skin )
{
setNodeRoles( { GrooveRole, FillRole } );
}
QskProgressIndicatorSkinlet::~QskProgressIndicatorSkinlet()
{
}
QSGNode* QskProgressIndicatorSkinlet::updateSubNode(
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
{
const auto indicator = static_cast< const QskProgressIndicator* >( skinnable );
switch( nodeRole )
{
case GrooveRole:
{
return updateGrooveNode( indicator, node );
}
case FillRole:
{
return updateFillNode( indicator, node );
}
}
return Inherited::updateSubNode( skinnable, nodeRole, node );
}

View File

@ -0,0 +1,38 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#ifndef QSK_PROGRESS_INDICATOR_SKINLET_H
#define QSK_PROGRESS_INDICATOR_SKINLET_H
#include "QskSkinlet.h"
class QskProgressIndicator;
class QSK_EXPORT QskProgressIndicatorSkinlet : public QskSkinlet
{
using Inherited = QskSkinlet;
public:
enum NodeRole
{
GrooveRole,
FillRole,
RoleCount
};
~QskProgressIndicatorSkinlet() override;
protected:
QskProgressIndicatorSkinlet( QskSkin* = nullptr );
QSGNode* updateSubNode( const QskSkinnable*,
quint8 nodeRole, QSGNode* ) const override;
virtual QSGNode* updateGrooveNode( const QskProgressIndicator*, QSGNode* ) const = 0;
virtual QSGNode* updateFillNode( const QskProgressIndicator*, QSGNode* ) const = 0;
};
#endif

View File

@ -0,0 +1,76 @@
/******************************************************************************
* QSkinny - Copyright (C) 2023 Uwe Rathmann
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "QskProgressRing.h"
#include "QskIntervalF.h"
QSK_SUBCONTROL( QskProgressRing, Groove )
QSK_SUBCONTROL( QskProgressRing, Fill )
class QskProgressRing::PrivateData
{
public:
int size : 2;
};
QskProgressRing::QskProgressRing( qreal min, qreal max, QQuickItem* parent )
: Inherited( min, max, parent )
, m_data( new PrivateData )
{
m_data->size = NormalSize;
setSubcontrolProxy( Inherited::Groove, Groove );
setSubcontrolProxy( Inherited::Fill, Fill );
}
QskProgressRing::QskProgressRing( QQuickItem* parent )
: QskProgressRing( 0.0, 100.0, parent )
{
}
QskProgressRing::QskProgressRing( const QskIntervalF& boundaries, QQuickItem* parent )
: QskProgressRing( boundaries.lowerBound(), boundaries.upperBound(), parent )
{
}
QskProgressRing::~QskProgressRing()
{
}
QskAspect::Variation QskProgressRing::effectiveVariation() const
{
switch( size() )
{
case SmallSize:
return QskAspect::Small;
case LargeSize:
return QskAspect::Large;
default:
return QskAspect::NoVariation;
}
}
void QskProgressRing::setSize( Size size )
{
if ( size != m_data->size )
{
m_data->size = size;
resetImplicitSize();
update();
Q_EMIT sizeChanged( size );
}
}
QskProgressRing::Size QskProgressRing::size() const
{
return static_cast< Size >( m_data->size );
}
#include "moc_QskProgressRing.cpp"

View File

@ -0,0 +1,50 @@
/******************************************************************************
* QSkinny - Copyright (C) 2023 Uwe Rathmann
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#ifndef QSK_PROGRESS_RING_H
#define QSK_PROGRESS_RING_H
#include "QskProgressIndicator.h"
class QSK_EXPORT QskProgressRing : public QskProgressIndicator
{
Q_OBJECT
Q_PROPERTY( Size size READ size
WRITE setSize NOTIFY sizeChanged )
using Inherited = QskProgressIndicator;
public:
QSK_SUBCONTROLS( Groove, Fill )
enum Size
{
SmallSize = -1,
NormalSize = 0,
LargeSize = 1
};
Q_ENUM( Size )
QskProgressRing( QQuickItem* parent = nullptr );
QskProgressRing( qreal min, qreal max, QQuickItem* parent = nullptr );
QskProgressRing( const QskIntervalF&, QQuickItem* parent = nullptr );
~QskProgressRing() override;
QskAspect::Variation effectiveVariation() const override;
void setSize( Size );
Size size() const;
Q_SIGNALS:
void sizeChanged( Size );
private:
class PrivateData;
std::unique_ptr< PrivateData > m_data;
};
#endif

View File

@ -0,0 +1,125 @@
/******************************************************************************
* QSkinny - Copyright (C) 2023 Uwe Rathmann
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "QskProgressRingSkinlet.h"
#include "QskArcMetrics.h"
#include "QskProgressRing.h"
#include "QskIntervalF.h"
using Q = QskProgressRing;
namespace
{
QskIntervalF qskFillInterval( const Q* ring )
{
qreal pos1, pos2;
if ( ring->isIndeterminate() )
{
const auto pos = ring->positionHint( QskProgressIndicator::Fill );
pos1 = pos2 = pos;
}
else
{
pos1 = ring->valueAsRatio( ring->origin() );
pos2 = ring->valueAsRatio( ring->value() );
}
if ( pos1 > pos2 )
std::swap( pos1, pos2 );
return QskIntervalF( pos1, pos2 );
}
}
QskProgressRingSkinlet::QskProgressRingSkinlet( QskSkin* skin )
: Inherited( skin )
{
}
QskProgressRingSkinlet::~QskProgressRingSkinlet()
{
}
QRectF QskProgressRingSkinlet::subControlRect(
const QskSkinnable* skinnable, const QRectF& contentsRect,
QskAspect::Subcontrol subControl ) const
{
const auto ring = static_cast< const Q* >( skinnable );
if( subControl == Q::Groove || subControl == Q::Fill )
{
auto rect = contentsRect;
const auto size = ring->strutSizeHint( Q::Fill );
if( ring->layoutMirroring() )
{
rect.setLeft( rect.right() - size.width() );
}
else
{
rect.setWidth( size.width() );
}
rect.setTop( rect.top() + 0.5 * ( rect.height() - size.height() ) );
rect.setHeight( size.height() );
return rect;
}
return Inherited::subControlRect( skinnable, contentsRect, subControl );
}
QSGNode* QskProgressRingSkinlet::updateGrooveNode(
const QskProgressIndicator* indicator, QSGNode* node ) const
{
return updateArcNode( indicator, node, Q::Groove );
}
QSGNode* QskProgressRingSkinlet::updateFillNode(
const QskProgressIndicator* indicator, QSGNode* node ) const
{
const auto ring = static_cast< const Q* >( indicator );
const auto subControl = Q::Fill;
const auto rect = ring->subControlRect( subControl );
if ( rect.isEmpty() )
return nullptr;
auto gradient = ring->gradientHint( subControl );
if ( !gradient.isVisible() )
return nullptr;
if ( ( gradient.type() == QskGradient::Stops ) && !gradient.isMonochrome() )
{
const auto center = rect.center();
const auto arcMetrics = ring->arcMetricsHint( Q::Fill );
gradient.setConicDirection( center.x(), center.y(), arcMetrics.startAngle(), arcMetrics.spanAngle() );
}
const auto interval = qskFillInterval( ring );
const auto arcMetrics = ring->arcMetricsHint( subControl );
const auto startAngle = arcMetrics.startAngle() + interval.lowerBound() * arcMetrics.spanAngle();
const auto spanAngle = interval.upperBound() * arcMetrics.spanAngle();
return updateArcNode( ring, node, rect, gradient, startAngle, spanAngle, subControl );
}
QSizeF QskProgressRingSkinlet::sizeHint( const QskSkinnable* skinnable,
Qt::SizeHint which, const QSizeF& ) const
{
if ( which != Qt::PreferredSize )
return QSizeF();
const auto ring = static_cast< const Q* >( skinnable );
const auto r = ring->strutSizeHint( Q::Fill );
return r;
}
#include "moc_QskProgressRingSkinlet.cpp"

View File

@ -0,0 +1,34 @@
/******************************************************************************
* QSkinny - Copyright (C) 2023 Uwe Rathmann
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#ifndef QSK_PROGRESS_RING_SKINLET_H
#define QSK_PROGRESS_RING_SKINLET_H
#include "QskProgressIndicatorSkinlet.h"
class QskProgressRing;
class QSK_EXPORT QskProgressRingSkinlet : public QskProgressIndicatorSkinlet
{
Q_GADGET
using Inherited = QskProgressIndicatorSkinlet;
public:
Q_INVOKABLE QskProgressRingSkinlet( QskSkin* = nullptr );
~QskProgressRingSkinlet() override;
QRectF subControlRect( const QskSkinnable*,
const QRectF&, QskAspect::Subcontrol ) const override;
QSizeF sizeHint( const QskSkinnable*,
Qt::SizeHint, const QSizeF& ) const override;
protected:
QSGNode* updateGrooveNode( const QskProgressIndicator*, QSGNode* ) const override;
QSGNode* updateFillNode( const QskProgressIndicator*, QSGNode* ) const override;
};
#endif

View File

@ -540,7 +540,6 @@ void qskUngrabMouse( QQuickItem* item )
if ( qskIsMouseGrabber( item ) )
item->ungrabMouse();
}
}

View File

@ -362,6 +362,25 @@ void QskScrollBox::geometryChangeEvent( QskGeometryChangeEvent* event )
Inherited::geometryChangeEvent( event );
}
void QskScrollBox::mousePressEvent( QMouseEvent* event )
{
auto& recognizer = m_data->panRecognizer;
if ( recognizer.hasProcessedBefore( event ) )
{
if ( m_data->panRecognizerTimeout != 0 )
{
recognizer.abort();
recognizer.setTimeout( -1 );
recognizer.processEvent( this, event, false );
}
return;
}
return Inherited::mousePressEvent( event );
}
void QskScrollBox::gestureEvent( QskGestureEvent* event )
{
if ( event->gesture()->type() == QskGesture::Pan )
@ -427,7 +446,7 @@ void QskScrollBox::wheelEvent( QWheelEvent* event )
#endif
bool QskScrollBox::gestureFilter( QQuickItem* item, QEvent* event )
bool QskScrollBox::gestureFilter( const QQuickItem* item, const QEvent* event )
{
if ( event->type() == QEvent::MouseButtonPress )
{
@ -458,6 +477,12 @@ bool QskScrollBox::gestureFilter( QQuickItem* item, QEvent* event )
return false;
}
auto& recognizer = m_data->panRecognizer;
recognizer.setTimeout( m_data->panRecognizerTimeout );
if ( event->type() == QEvent::MouseButtonPress )
{
/*
This code is a bit tricky as the filter is called in different situations:
@ -472,24 +497,19 @@ bool QskScrollBox::gestureFilter( QQuickItem* item, QEvent* event )
could be made the recognizer aborts and replays the mouse events, so
that the children can process them.
But if a child does not accept a mouse event it will be sent to
its parent. So we might finally receive the reposted events, but then
we can proceed as in b).
But if a child does not accept the mouse event it will be sent to
its parent, finally ending up here for a second time.
*/
auto& recognizer = m_data->panRecognizer;
if ( event->type() == QEvent::MouseButtonPress )
{
if ( ( item != this ) && ( recognizer.timeout() < 0 ) )
{
const auto mouseEvent = static_cast< QMouseEvent* >( event );
auto mouseEvent = static_cast< const QMouseEvent* >( event );
if ( recognizer.hasProcessedBefore( mouseEvent ) )
{
/*
Note that the recognizer will be restarted without timout if the
event ends up in in mousePressEvent ( = nobody else was interested )
*/
return false;
}
recognizer.setTimeout( ( item == this ) ? -1 : m_data->panRecognizerTimeout );
}
return recognizer.processEvent( item, event );

View File

@ -64,6 +64,8 @@ class QSK_EXPORT QskScrollBox : public QskControl
protected:
void geometryChangeEvent( QskGeometryChangeEvent* ) override;
void windowChangeEvent( QskWindowChangeEvent* ) override;
void mousePressEvent( QMouseEvent* ) override;
void gestureEvent( QskGestureEvent* ) override;
#ifndef QT_NO_WHEELEVENT
@ -71,7 +73,7 @@ class QSK_EXPORT QskScrollBox : public QskControl
virtual QPointF scrollOffset( const QWheelEvent* ) const;
#endif
bool gestureFilter( QQuickItem*, QEvent* ) override;
bool gestureFilter( const QQuickItem*, const QEvent* ) override;
void setScrollableSize( const QSizeF& );
private:

View File

@ -53,6 +53,9 @@
#include "QskProgressBar.h"
#include "QskProgressBarSkinlet.h"
#include "QskProgressRing.h"
#include "QskProgressRingSkinlet.h"
#include "QskRadioBox.h"
#include "QskRadioBoxSkinlet.h"
@ -178,6 +181,7 @@ QskSkin::QskSkin( QObject* parent )
declareSkinlet< QskTextLabel, QskTextLabelSkinlet >();
declareSkinlet< QskTextInput, QskTextInputSkinlet >();
declareSkinlet< QskProgressBar, QskProgressBarSkinlet >();
declareSkinlet< QskProgressRing, QskProgressRingSkinlet >();
declareSkinlet< QskRadioBox, QskRadioBoxSkinlet >();
const QFont font = QGuiApplication::font();

View File

@ -15,7 +15,7 @@ class QskSkinStateChanger
QskSkinStateChanger( const QskSkinnable* );
~QskSkinStateChanger();
void setStates( QskAspect::States );
void setStates( QskAspect::States, int sampleIndex = -1 );
void resetStates();
private:
@ -34,16 +34,15 @@ inline QskSkinStateChanger::~QskSkinStateChanger()
resetStates();
}
inline void QskSkinStateChanger::setStates( QskAspect::States states )
inline void QskSkinStateChanger::setStates(
QskAspect::States states, int sampleIndex )
{
if ( states != m_skinnable->skinStates() )
m_skinnable->replaceSkinStates( states );
m_skinnable->replaceSkinStates( states, sampleIndex );
}
inline void QskSkinStateChanger::resetStates()
{
if ( m_oldStates != m_skinnable->skinStates() )
m_skinnable->replaceSkinStates( m_oldStates );
m_skinnable->replaceSkinStates( m_oldStates, -1 );
}
#endif

View File

@ -282,8 +282,6 @@ class QskSkinlet::PrivateData
QskSkin* skin;
QVector< quint8 > nodeRoles;
int animatorIndex = -1;
bool ownedBySkinnable : 1;
};
@ -311,21 +309,6 @@ bool QskSkinlet::isOwnedBySkinnable() const
return m_data->ownedBySkinnable;
}
void QskSkinlet::setAnimatorIndex( int index )
{
m_data->animatorIndex = index;
}
void QskSkinlet::resetAnimatorIndex()
{
m_data->animatorIndex = -1;
}
int QskSkinlet::animatorIndex() const
{
return m_data->animatorIndex;
}
void QskSkinlet::setNodeRoles( const QVector< quint8 >& nodeRoles )
{
m_data->nodeRoles = nodeRoles;
@ -796,26 +779,7 @@ QSGNode* QskSkinlet::updateSeriesNode( const QskSkinnable* skinnable,
const auto newStates = sampleStates( skinnable, subControl, i );
QskSkinStateChanger stateChanger( skinnable );
stateChanger.setStates( newStates );
class IndexChanger
{
public:
inline IndexChanger( const QskSkinlet* skinlet, int index )
: m_skinlet( const_cast< QskSkinlet* >( skinlet ) )
{
m_skinlet->setAnimatorIndex( index );
}
inline ~IndexChanger()
{
m_skinlet->resetAnimatorIndex();
}
private:
QskSkinlet* m_skinlet;
};
IndexChanger indexChanger( this, i );
stateChanger.setStates( newStates, i );
newNode = updateSampleNode( skinnable, subControl, i, node );
}

View File

@ -71,10 +71,6 @@ class QSK_EXPORT QskSkinlet
void setOwnedBySkinnable( bool on );
bool isOwnedBySkinnable() const;
void setAnimatorIndex( int );
void resetAnimatorIndex();
int animatorIndex() const;
// Helper functions for creating nodes
static QSGNode* updateBoxNode( const QskSkinnable*, QSGNode*,

View File

@ -122,6 +122,16 @@ static inline T qskColor( const QskSkinnable* skinnable,
aspect | QskAspect::Color, status ).value< T >();
}
static inline constexpr QskAspect qskAnimatorAspect( const QskAspect aspect )
{
/*
We do not need the extra bits that would slow down resolving
the effective aspect in animatedHint.
*/
return aspect.type() | aspect.subControl() | aspect.primitive();
}
static inline void qskTriggerUpdates( QskAspect aspect, QQuickItem* item )
{
/*
@ -238,6 +248,8 @@ class QskSkinnable::PrivateData
QskSkinHintTable hintTable;
QskHintAnimatorTable animators;
int sampleIndex = -1; // for the ugly QskSkinStateChanger hack
typedef std::map< QskAspect::Subcontrol, QskAspect::Subcontrol > ProxyMap;
ProxyMap* subcontrolProxies = nullptr;
@ -983,11 +995,11 @@ QVariant QskSkinnable::animatedHint(
if ( !m_data->animators.isEmpty() )
{
const int index = effectiveSkinlet()->animatorIndex();
const auto a = qskAnimatorAspect( aspect );
v = m_data->animators.currentValue( aspect, index );
if ( !v.isValid() && index >= 0 )
v = m_data->animators.currentValue( aspect, -1 );
v = m_data->animators.currentValue( a, m_data->sampleIndex );
if ( !v.isValid() && m_data->sampleIndex >= 0 )
v = m_data->animators.currentValue( a, -1 );
}
if ( status && v.isValid() )
@ -1296,18 +1308,10 @@ void QskSkinnable::startHintTransition( QskAspect aspect, int index,
v2.setValue( skin->graphicFilter( v2.toInt() ) );
}
/*
We do not need the extra bits that would slow down resolving
the effective aspect in animatedHint.
*/
aspect.clearStates();
aspect.setSection( QskAspect::Body );
aspect.setVariation( QskAspect::NoVariation );
aspect.setAnimator( false );
aspect = qskAnimatorAspect( aspect );
#if DEBUG_ANIMATOR
qDebug() << aspect << animationHint.duration;
qDebug() << aspect << index << animationHint.duration;
#endif
auto animator = m_data->animators.animator( aspect, index );
@ -1326,9 +1330,20 @@ void QskSkinnable::setSkinStateFlag( QskAspect::State stateFlag, bool on )
setSkinStates( newState );
}
void QskSkinnable::replaceSkinStates( QskAspect::States newStates )
void QskSkinnable::replaceSkinStates(
QskAspect::States newStates, int sampleIndex )
{
/*
Hack time: we might need different hints for a specific instance
of a subcontrol ( f.e the selected row in a list box ), what is not
supported by QskAspect.
As a workaround we use QskSkinStateChanger, that sets/restores this state/index
while retrieving the skin hints.
*/
m_data->skinStates = newStates;
m_data->sampleIndex = sampleIndex; // needed to find specific animators
}
void QskSkinnable::addSkinStates( QskAspect::States states )

View File

@ -39,6 +39,7 @@ class QskGraphic;
class QskSkin;
class QskSkinlet;
class QskSkinHintTable;
class QskSkinStateChanger;
class QSK_EXPORT QskSkinHintStatus
{
@ -149,8 +150,6 @@ class QSK_EXPORT QskSkinnable
void addSkinStates( QskAspect::States );
void clearSkinStates( QskAspect::States );
void replaceSkinStates( QskAspect::States );
bool hasSkinState( QskAspect::State ) const;
QskAspect::States skinStates() const;
@ -281,6 +280,9 @@ class QSK_EXPORT QskSkinnable
QVariant interpolatedHint( QskAspect, QskSkinHintStatus* ) const;
const QVariant& storedHint( QskAspect, QskSkinHintStatus* = nullptr ) const;
friend class QskSkinStateChanger;
void replaceSkinStates( QskAspect::States, int sampleIndex = -1 );
class PrivateData;
std::unique_ptr< PrivateData > m_data;
};

View File

@ -0,0 +1,168 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "QskSwipeView.h"
#include "QskEvent.h"
#include "QskGesture.h"
#include "QskPanGestureRecognizer.h"
#include "QskStackBoxAnimator.h"
#include "QskPlatform.h"
class QskSwipeView::PrivateData
{
public:
QskPanGestureRecognizer panRecognizer;
int duration = -1; // should be a skinHint
};
QSK_SUBCONTROL( QskSwipeView, Panel )
QskSwipeView::QskSwipeView( QQuickItem* parent )
: Inherited( parent )
, m_data( new PrivateData() )
{
setFiltersChildMouseEvents( true );
setAcceptedMouseButtons( Qt::LeftButton );
auto& recognizer = m_data->panRecognizer;
recognizer.setWatchedItem( this );
// should be skin hints, TODO
recognizer.setOrientations( Qt::Horizontal );
recognizer.setTimeout( 100 );
resetSwipeDistance();
resetDuration();
}
QskSwipeView::~QskSwipeView()
{
}
void QskSwipeView::setOrientation( Qt::Orientation orientation )
{
if ( orientation != this->orientation() )
{
m_data->panRecognizer.setOrientations( orientation );
Q_EMIT orientationChanged( orientation );
}
}
Qt::Orientation QskSwipeView::orientation() const
{
return ( m_data->panRecognizer.orientations() == Qt::Vertical )
? Qt::Vertical : Qt::Horizontal;
}
int QskSwipeView::swipeDistance() const
{
return m_data->panRecognizer.minDistance();
}
void QskSwipeView::setSwipeDistance( int distance )
{
const auto oldDistance = m_data->panRecognizer.minDistance();
m_data->panRecognizer.setMinDistance( distance );
if ( oldDistance != m_data->panRecognizer.minDistance() )
Q_EMIT swipeDistanceChanged( m_data->panRecognizer.minDistance() );
}
void QskSwipeView::resetSwipeDistance()
{
setSwipeDistance( qRound( qskDpToPixels( 40 ) ) );
}
int QskSwipeView::duration() const
{
return m_data->duration;
}
void QskSwipeView::setDuration( int duration )
{
if ( duration != m_data->duration )
{
m_data->duration = duration;
Q_EMIT durationChanged( duration );
}
}
void QskSwipeView::resetDuration()
{
setDuration( 500 );
}
bool QskSwipeView::gestureFilter( const QQuickItem* item, const QEvent* event )
{
// see QskScrollBox.cpp
auto& recognizer = m_data->panRecognizer;
if ( event->type() == QEvent::MouseButtonPress )
{
auto mouseEvent = static_cast< const QMouseEvent* >( event );
if ( recognizer.hasProcessedBefore( mouseEvent ) )
return false;
}
return recognizer.processEvent( item, event );
}
void QskSwipeView::gestureEvent( QskGestureEvent* event )
{
const auto gesture = static_cast< const QskPanGesture* >( event->gesture().get() );
if( gesture->type() == QskGesture::Pan && gesture->state() == QskGesture::Started )
{
if ( itemCount() <= 1 )
return;
bool forwards;
if ( orientation() == Qt::Horizontal )
forwards = gesture->angle() >= 90.0 && gesture->angle() <= 270.0;
else
forwards = gesture->angle() >= 180.0;
auto animator = qobject_cast< QskStackBoxAnimator1* >( this->animator() );
if ( animator == nullptr )
animator = new QskStackBoxAnimator1( this );
if ( orientation() == Qt::Horizontal )
animator->setDirection( forwards ? Qsk::LeftToRight : Qsk::RightToLeft );
else
animator->setDirection( forwards ? Qsk::TopToBottom : Qsk::BottomToTop );
animator->setDuration( m_data->duration );
QskStackBox::setAnimator( animator );
auto newIndex = forwards ? currentIndex() + 1 : currentIndex() - 1;
if( newIndex < 0 )
newIndex += itemCount();
newIndex %= itemCount();
setCurrentIndex( newIndex );
return;
}
Inherited::gestureEvent( event );
}
QskAspect::Subcontrol QskSwipeView::effectiveSubcontrol(
QskAspect::Subcontrol subControl ) const
{
if ( subControl == QskBox::Panel )
return QskSwipeView::Panel;
return Inherited::effectiveSubcontrol( subControl );
}
#include "moc_QskSwipeView.cpp"

View File

@ -0,0 +1,70 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#ifndef QSK_SWIPE_VIEW_H
#define QSK_SWIPE_VIEW_H
#include "QskStackBox.h"
class QSK_EXPORT QskSwipeView : public QskStackBox
{
Q_OBJECT
Q_PROPERTY( int duration READ duration
WRITE setDuration RESET resetDuration NOTIFY durationChanged )
Q_PROPERTY( int swipeDistance READ swipeDistance
WRITE setSwipeDistance RESET resetSwipeDistance NOTIFY swipeDistanceChanged )
Q_PROPERTY( Qt::Orientation orientation READ orientation
WRITE setOrientation NOTIFY orientationChanged )
using Inherited = QskStackBox;
public:
QSK_SUBCONTROLS( Panel )
QskSwipeView( QQuickItem* parent = nullptr );
~QskSwipeView() override;
void setOrientation( Qt::Orientation );
Qt::Orientation orientation() const;
// Duration is the time ( in ms ) used for changing between pages
int duration() const;
void setDuration( int );
void resetDuration();
/*
Even if called "swipe view" we use a pan - no swipe - gesture.
( = pages are moved before the gesture has been confirmed )
The swipe distance is the minimum distance in pixels of the pan gesture
*/
int swipeDistance() const;
void setSwipeDistance( int );
void resetSwipeDistance();
QskAspect::Subcontrol effectiveSubcontrol( QskAspect::Subcontrol ) const;
Q_SIGNALS:
void orientationChanged( Qt::Orientation );
void durationChanged( int );
void swipeDistanceChanged( int );
protected:
bool gestureFilter( const QQuickItem*, const QEvent* ) override;
void gestureEvent( QskGestureEvent* ) override;
private:
void setAnimator( QskStackBoxAnimator* ) = delete;
class PrivateData;
std::unique_ptr< PrivateData > m_data;
};
#endif

View File

@ -13,53 +13,6 @@ QSK_QT_PRIVATE_BEGIN
#include <private/qquickitem_p.h>
QSK_QT_PRIVATE_END
static Qsk::Direction qskDirection(
Qt::Orientation orientation, int from, int to, int itemCount )
{
Qsk::Direction direction;
if ( orientation == Qt::Horizontal )
{
direction = Qsk::RightToLeft;
if ( to > from )
{
const bool isWrapping = ( from == 0 ) && ( to == itemCount - 1 );
if ( !isWrapping )
direction = Qsk::LeftToRight;
}
else
{
const bool isWrapping = ( to == 0 ) && ( from == itemCount - 1 );
if ( isWrapping )
direction = Qsk::LeftToRight;
}
}
else
{
direction = Qsk::BottomToTop;
if ( to > from )
{
const bool isWrapping = ( from == 0 ) && ( to == itemCount - 1 );
if ( !isWrapping )
direction = Qsk::TopToBottom;
}
else
{
const bool isWrapping = ( to == 0 ) && ( from == itemCount - 1 );
if ( isWrapping )
direction = Qsk::TopToBottom;
}
}
return direction;
}
namespace
{
class RotationTransform : public QQuickTransform
@ -240,7 +193,7 @@ void QskStackBoxAnimator::advance( qreal progress )
QskStackBoxAnimator1::QskStackBoxAnimator1( QskStackBox* parent )
: QskStackBoxAnimator( parent )
, m_orientation( Qt::Horizontal )
, m_direction( Qsk::LeftToRight )
, m_isDirty( false )
, m_hasClip( false )
{
@ -251,27 +204,24 @@ QskStackBoxAnimator1::~QskStackBoxAnimator1()
{
}
void QskStackBoxAnimator1::setOrientation( Qt::Orientation orientation )
void QskStackBoxAnimator1::setDirection( Qsk::Direction direction )
{
if ( m_orientation != orientation )
if ( m_direction != direction )
{
stop();
m_orientation = orientation;
m_direction = direction;
}
}
Qt::Orientation QskStackBoxAnimator1::orientation() const
Qsk::Direction QskStackBoxAnimator1::direction() const
{
return m_orientation;
return m_direction;
}
void QskStackBoxAnimator1::setup()
{
auto stackBox = this->stackBox();
m_direction = qskDirection( m_orientation,
startIndex(), endIndex(), stackBox->itemCount() );
m_hasClip = stackBox->clip();
if ( !m_hasClip )
stackBox->setClip( true );
@ -283,7 +233,9 @@ void QskStackBoxAnimator1::setup()
void QskStackBoxAnimator1::advanceIndex( qreal value )
{
auto stackBox = this->stackBox();
const bool isHorizontal = m_orientation == Qt::Horizontal;
const bool isHorizontal = ( m_direction == Qsk::LeftToRight )
|| ( m_direction == Qsk::RightToLeft );
for ( int i = 0; i < 2; i++ )
{

View File

@ -49,14 +49,14 @@ class QSK_EXPORT QskStackBoxAnimator1 : public QskStackBoxAnimator
{
Q_OBJECT
Q_PROPERTY( Qt::Orientation orientation READ orientation WRITE setOrientation )
Q_PROPERTY( Qsk::Direction direction READ direction WRITE setDirection )
public:
QskStackBoxAnimator1( QskStackBox* );
~QskStackBoxAnimator1() override;
void setOrientation( Qt::Orientation );
Qt::Orientation orientation() const;
void setDirection( Qsk::Direction );
Qsk::Direction direction() const;
protected:
bool eventFilter( QObject*, QEvent* ) override;
@ -68,7 +68,6 @@ class QSK_EXPORT QskStackBoxAnimator1 : public QskStackBoxAnimator
private:
qreal m_itemOffset[ 2 ];
Qt::Orientation m_orientation : 2;
Qsk::Direction m_direction : 4;
bool m_isDirty : 1;
bool m_hasClip : 1;