tabbars for all edges ( left, right, top, bottom )

This commit is contained in:
Uwe Rathmann 2019-04-17 16:33:17 +02:00
parent 53b4395db9
commit 9ba37738af
21 changed files with 286 additions and 162 deletions

View File

@ -363,7 +363,7 @@ class TabView : public QskTabView
{ {
public: public:
TabView( QQuickItem* parentItem = nullptr ) TabView( QQuickItem* parentItem = nullptr )
: QskTabView( Qt::Vertical, parentItem ) : QskTabView( parentItem )
{ {
setMargins( 10 ); setMargins( 10 );

View File

@ -53,7 +53,7 @@ int main( int argc, char* argv[] )
auto tabView = new QskTabView(); auto tabView = new QskTabView();
tabView->setMargins( 10 ); tabView->setMargins( 10 );
tabView->setOrientation( Qt::Horizontal ); tabView->setTabPosition( Qsk::Left );
tabView->addTab( "Grid Layout", new DummyLabel( "Grid Layout - TODO ..." ) ); tabView->addTab( "Grid Layout", new DummyLabel( "Grid Layout - TODO ..." ) );
tabView->addTab( "Flow Layout", new FlowLayoutPage() ); tabView->addTab( "Flow Layout", new FlowLayoutPage() );
tabView->addTab( "Linear Layout", new LinearLayoutPage() ); tabView->addTab( "Linear Layout", new LinearLayoutPage() );

View File

@ -75,7 +75,7 @@ class GraphicLabel : public QskGraphicLabel
MainWindow::MainWindow() MainWindow::MainWindow()
{ {
m_tabView = new QskTabView( Qt::Horizontal ); m_tabView = new QskTabView( Qsk::Left );
const QString resourceDir( ":/qvg" ); const QString resourceDir( ":/qvg" );
const QStringList icons = QDir( resourceDir ).entryList(); const QStringList icons = QDir( resourceDir ).entryList();

View File

@ -27,10 +27,7 @@
class OtherSlider : public QskSlider class OtherSlider : public QskSlider
{ {
public: public:
/* // Slider overriding many hints from the skin.
Slider overriding many hints from the skin.
"Preserved" is for horizontal, "Transposed" for vertical orientation
*/
OtherSlider( QQuickItem* parentItem = nullptr ) OtherSlider( QQuickItem* parentItem = nullptr )
: QskSlider( parentItem ) : QskSlider( parentItem )
@ -44,7 +41,7 @@ class OtherSlider : public QskSlider
// Panel // Panel
for ( auto placement : { Preserved, Transposed } ) for ( auto placement : { Horizontal, Vertical } )
{ {
const Aspect aspect = Panel | placement; const Aspect aspect = Panel | placement;
@ -54,7 +51,7 @@ class OtherSlider : public QskSlider
setBoxBorderColorsHint( aspect, Grey900 ); setBoxBorderColorsHint( aspect, Grey900 );
setGradientHint( aspect, Grey400 ); setGradientHint( aspect, Grey400 );
if ( placement == Preserved ) if ( placement == Horizontal )
setMarginsHint( aspect | Padding, QMarginsF( paddingW, 0, paddingW, 0 ) ); setMarginsHint( aspect | Padding, QMarginsF( paddingW, 0, paddingW, 0 ) );
else else
setMarginsHint( aspect | Padding, QMarginsF( 0, paddingW, 0, paddingW ) ); setMarginsHint( aspect | Padding, QMarginsF( 0, paddingW, 0, paddingW ) );
@ -62,7 +59,7 @@ class OtherSlider : public QskSlider
// Groove // Groove
for ( auto placement : { Preserved, Transposed } ) for ( auto placement : { Horizontal, Vertical } )
{ {
const Aspect aspect = Groove | placement; const Aspect aspect = Groove | placement;
@ -74,7 +71,7 @@ class OtherSlider : public QskSlider
} }
// no Fill // no Fill
for ( auto placement : { Preserved, Transposed } ) for ( auto placement : { Horizontal, Vertical } )
{ {
const Aspect aspect = Fill | placement; const Aspect aspect = Fill | placement;
setMetric( aspect | Size, 0 ); setMetric( aspect | Size, 0 );
@ -82,7 +79,7 @@ class OtherSlider : public QskSlider
// Handle // Handle
for ( auto placement : { Preserved, Transposed } ) for ( auto placement : { Horizontal, Vertical } )
{ {
const Aspect aspect = Handle | placement; const Aspect aspect = Handle | placement;
@ -91,7 +88,7 @@ class OtherSlider : public QskSlider
const qreal m = 0.5 * qCeil( 0.5 * ( w - h ) ) + 1; const qreal m = 0.5 * qCeil( 0.5 * ( w - h ) ) + 1;
if ( placement == Preserved ) if ( placement == Horizontal )
setMarginsHint( aspect | Margin, QMarginsF( -m, 0, -m, 0 ) ); setMarginsHint( aspect | Margin, QMarginsF( -m, 0, -m, 0 ) );
else else
setMarginsHint( aspect | Margin, QMarginsF( 0, -m, 0, -m ) ); setMarginsHint( aspect | Margin, QMarginsF( 0, -m, 0, -m ) );

View File

@ -53,12 +53,18 @@ class TabView : public QskTabView
buttonAt( 2 )->setEnabled( false ); buttonAt( 2 )->setEnabled( false );
} }
void flip() void rotate()
{ {
if ( orientation() == Qt::Vertical ) const Qsk::Position pos[] = { Qsk::Top, Qsk::Right, Qsk::Bottom, Qsk::Left };
setOrientation( Qt::Horizontal );
else for ( int i = 0; i < 4; i++ )
setOrientation( Qt::Vertical ); {
if ( tabPosition() == pos[i] )
{
setTabPosition( pos[ ( i + 1 ) % 4 ] );
break;
}
}
} }
}; };
@ -75,15 +81,15 @@ int main( int argc, char* argv[] )
auto tabView = new TabView(); auto tabView = new TabView();
auto flipButton = new QskPushButton( "Flip" ); auto rotateButton = new QskPushButton( "Rotate" );
flipButton->setSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed ); rotateButton->setSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
flipButton->setFocus( true ); rotateButton->setFocus( true );
QObject::connect( flipButton, &QskPushButton::clicked, tabView, &TabView::flip ); QObject::connect( rotateButton, &QskPushButton::clicked, tabView, &TabView::rotate );
auto layoutBox = new QskLinearBox( Qt::Vertical ); auto layoutBox = new QskLinearBox( Qt::Vertical );
layoutBox->setMargins( 5 ); layoutBox->setMargins( 5 );
layoutBox->setSpacing( 10 ); layoutBox->setSpacing( 10 );
layoutBox->addItem( flipButton, Qt::AlignLeft ); layoutBox->addItem( rotateButton, Qt::AlignLeft );
layoutBox->addItem( tabView ); layoutBox->addItem( tabView );
auto focusIndicator = new QskFocusIndicator(); auto focusIndicator = new QskFocusIndicator();

View File

@ -235,7 +235,7 @@ void QskMaterialSkin::initSeparatorHints()
const ColorPalette& pal = m_data->palette; const ColorPalette& pal = m_data->palette;
for ( auto placement : { Preserved, Transposed } ) for ( auto placement : { Horizontal, Vertical } )
{ {
const Aspect aspect = Q::Panel | placement; const Aspect aspect = Q::Panel | placement;
@ -419,8 +419,8 @@ void QskMaterialSkin::initSliderHints()
setBoxBorderMetrics( Q::Panel, 0 ); setBoxBorderMetrics( Q::Panel, 0 );
setGradient( Q::Panel, QskGradient() ); setGradient( Q::Panel, QskGradient() );
setMargins( Q::Panel | Preserved | Padding, QskMargins( 0.5 * dim, 0 ) ); setMargins( Q::Panel | Horizontal | Padding, QskMargins( 0.5 * dim, 0 ) );
setMargins( Q::Panel | Transposed | Padding, QskMargins( 0, 0.5 * dim ) ); setMargins( Q::Panel | Vertical | Padding, QskMargins( 0, 0.5 * dim ) );
// Groove, Fill // Groove, Fill
@ -485,15 +485,37 @@ void QskMaterialSkin::initTabButtonHints()
setMetric( Q::Panel | MinimumWidth, 30 ); setMetric( Q::Panel | MinimumWidth, 30 );
setMetric( Q::Panel | MinimumHeight, 16 ); setMetric( Q::Panel | MinimumHeight, 16 );
for ( auto placement : { Preserved, Transposed } ) for ( auto placement : { Left, Right, Top, Bottom } )
{ {
const Aspect aspect = Q::Panel | placement; const Aspect aspect = Q::Panel | placement;
const Qt::Edge edge = ( placement == Preserved ) ? Qt::BottomEdge : Qt::RightEdge;
Qt::Edge edge;
switch( placement )
{
case Left:
edge = Qt::RightEdge;
break;
case Right:
edge = Qt::LeftEdge;
break;
case Top:
edge = Qt::BottomEdge;
break;
case Bottom:
edge = Qt::TopEdge;
break;
default:
break;
}
setGradient( aspect, QskRgbValue::White ); setGradient( aspect, QskRgbValue::White );
// The highlighted button has a accented bar at the bottom/right edge // The highlighted button has a accented bar at one edge
setBoxShape( aspect, 0 ); setBoxShape( aspect, 0 );
QskBoxBorderMetrics border; QskBoxBorderMetrics border;
@ -501,7 +523,7 @@ void QskMaterialSkin::initTabButtonHints()
setBoxBorderMetrics( aspect, border ); setBoxBorderMetrics( aspect, border );
QskBoxBorderColors borderColors( QskRgbValue::White ); QskBoxBorderColors borderColors( QskRgbValue::White );
setBoxBorderColors( placement, borderColors ); setBoxBorderColors( aspect, borderColors );
borderColors.setColorsAt( edge, pal.accentColor ); borderColors.setColorsAt( edge, pal.accentColor );
for ( auto state : { Q::Checked, Q::Pressed, Q::Checkable | Q::Hovered } ) for ( auto state : { Q::Checked, Q::Pressed, Q::Checkable | Q::Hovered } )

View File

@ -128,14 +128,13 @@ QskSquiekSkin::~QskSquiekSkin()
{ {
} }
void QskSquiekSkin::setSeparator( void QskSquiekSkin::setSeparator( QskAspect::Aspect aspect )
QskAspect::Aspect aspect, Qt::Orientation orientation )
{ {
const ColorPalette& pal = m_data->palette; const ColorPalette& pal = m_data->palette;
QskGradient gradient( QskGradient::Vertical, pal.lighter110, pal.darker125 ); QskGradient gradient( QskGradient::Vertical, pal.lighter110, pal.darker125 );
if ( orientation == Qt::Vertical ) if ( aspect.placement() == QskAspect::Vertical )
gradient.setOrientation( QskGradient::Horizontal ); gradient.setOrientation( QskGradient::Horizontal );
setGradient( aspect, gradient ); setGradient( aspect, gradient );
@ -208,7 +207,7 @@ void QskSquiekSkin::setPanel( QskAspect::Aspect aspect, PanelStyle style )
setButton( aspect, style, 1 ); setButton( aspect, style, 1 );
} }
void QskSquiekSkin::setTab( QskAspect::Aspect aspect, Qt::Orientation orientation ) void QskSquiekSkin::setTab( QskAspect::Aspect aspect )
{ {
const ColorPalette& pal = m_data->palette; const ColorPalette& pal = m_data->palette;
@ -219,17 +218,29 @@ void QskSquiekSkin::setTab( QskAspect::Aspect aspect, Qt::Orientation orientatio
QskBoxBorderMetrics border( 1 ); QskBoxBorderMetrics border( 1 );
QskBoxShapeMetrics shape( 4 ); QskBoxShapeMetrics shape( 4 );
if ( orientation == Qt::Horizontal ) if ( aspect.placement() == QskAspect::Top )
{
border.setWidthAt( Qt::BottomEdge, 0 );
shape.setRadius( Qt::BottomLeftCorner, 0 );
shape.setRadius( Qt::BottomRightCorner, 0 );
}
else if ( aspect.placement() == QskAspect::Bottom )
{
border.setWidthAt( Qt::TopEdge, 0 );
shape.setRadius( Qt::TopLeftCorner, 0 );
shape.setRadius( Qt::TopRightCorner, 0 );
}
else if ( aspect.placement() == QskAspect::Left )
{ {
border.setWidthAt( Qt::RightEdge, 0 ); border.setWidthAt( Qt::RightEdge, 0 );
shape.setRadius( Qt::TopRightCorner, 0 ); shape.setRadius( Qt::TopRightCorner, 0 );
shape.setRadius( Qt::BottomRightCorner, 0 ); shape.setRadius( Qt::BottomRightCorner, 0 );
} }
else else if ( aspect.placement() == QskAspect::Right )
{ {
border.setWidthAt( Qt::BottomEdge, 0 ); border.setWidthAt( Qt::LeftEdge, 0 );
shape.setRadius( Qt::TopLeftCorner, 0 );
shape.setRadius( Qt::BottomLeftCorner, 0 ); shape.setRadius( Qt::BottomLeftCorner, 0 );
shape.setRadius( Qt::BottomRightCorner, 0 );
} }
setBoxBorderMetrics( aspect, border ); setBoxBorderMetrics( aspect, border );
@ -370,8 +381,8 @@ void QskSquiekSkin::initSeparatorHints()
setMetric( Q::Panel | Size, 4 ); setMetric( Q::Panel | Size, 4 );
setSeparator( Q::Panel, Qt::Horizontal ); setSeparator( Q::Panel | Horizontal );
setSeparator( Q::Panel | Transposed, Qt::Vertical ); setSeparator( Q::Panel | Vertical );
} }
void QskSquiekSkin::initPageIndicatorHints() void QskSquiekSkin::initPageIndicatorHints()
@ -496,30 +507,44 @@ void QskSquiekSkin::initTabButtonHints()
const QskMargins padding( 10, 4 ); const QskMargins padding( 10, 4 );
for ( auto placement : { Preserved, Transposed } ) for ( auto placement : { Left, Right, Top, Bottom } )
{ {
const Aspect aspect = Q::Panel | placement; const Aspect aspect = Q::Panel | placement;
if ( placement == Preserved ) QskMargins margins0, margins1, padding;
if ( placement == Top )
{ {
setMargins( aspect | Margin, QskMargins( -1, 2, -1, -2 ) ); margins0 = QskMargins( -1, 2, -1, -2 );
margins1 = QskMargins( -1, 0, -1, -3 );
for ( const auto state : { Q::Checked, Q::Checked | Q::Pressed } ) padding = padding.rotated();
setMargins( aspect | Margin | state, QskMargins( -1, 0, -1, -3 ) );
setMargins( aspect | Padding, padding );
setTab( aspect, Qt::Vertical );
} }
else else if ( placement == Bottom )
{ {
setMargins( aspect | Margin, QskMargins( 2, -1, -2, -1 ) ); margins0 = QskMargins( -1, -2, -1, 2 );
margins1 = QskMargins( -1, -3, -1, 0 );
for ( const auto state : { Q::Checked, Q::Checked | Q::Pressed } ) padding = padding.rotated();
setMargins( aspect | Margin | state, QskMargins( 0, -1, -3, 0 ) );
setMargins( aspect | Padding, padding.rotated() );
setTab( aspect, Qt::Horizontal );
} }
else if ( placement == Left )
{
margins0 = QskMargins( 2, -1, -2, -1 );
margins1 = QskMargins( 0, -1, -3, 0 );
}
else if ( placement == Right )
{
margins0 = QskMargins( -2, -1, 2, -1 );
margins1 = QskMargins( -3, -1, 0, 0 );
}
setMargins( aspect | Margin, margins0 );
for ( const auto state : { Q::Checked, Q::Checked | Q::Pressed } )
setMargins( aspect | Margin | state, margins1 );
setMargins( aspect | Padding, padding );
setTab( aspect );
} }
setAnimation( Q::Panel | Color, qskDuration ); setAnimation( Q::Panel | Color, qskDuration );
@ -542,7 +567,7 @@ void QskSquiekSkin::initSliderHints()
// Panel // Panel
for ( auto placement : { Preserved, Transposed } ) for ( auto placement : { Horizontal, Vertical } )
{ {
const auto aspect = Q::Panel | placement; const auto aspect = Q::Panel | placement;
@ -552,12 +577,12 @@ void QskSquiekSkin::initSliderHints()
setGradient( aspect, QskGradient() ); setGradient( aspect, QskGradient() );
} }
setMargins( Q::Panel | Preserved | Padding, QskMargins( 0.5 * dim, 0 ) ); setMargins( Q::Panel | Horizontal | Padding, QskMargins( 0.5 * dim, 0 ) );
setMargins( Q::Panel | Transposed | Padding, QskMargins( 0, 0.5 * dim ) ); setMargins( Q::Panel | Vertical | Padding, QskMargins( 0, 0.5 * dim ) );
// Groove, Fill // Groove, Fill
for ( auto placement : { Preserved, Transposed } ) for ( auto placement : { Horizontal, Vertical } )
{ {
for ( auto subControl : { Q::Groove, Q::Fill } ) for ( auto subControl : { Q::Groove, Q::Fill } )
{ {
@ -578,7 +603,7 @@ void QskSquiekSkin::initSliderHints()
// Handle // Handle
for ( auto placement : { Preserved, Transposed } ) for ( auto placement : { Horizontal, Vertical } )
{ {
Aspect aspect = Q::Handle | placement; Aspect aspect = Q::Handle | placement;

View File

@ -56,10 +56,10 @@ class QSK_SQUIEK_EXPORT QskSquiekSkin : public QskSkin
Flat Flat
}; };
void setSeparator( QskAspect::Aspect, Qt::Orientation ); void setSeparator( QskAspect::Aspect );
void setButton( QskAspect::Aspect, PanelStyle, qreal border = 2.0 ); void setButton( QskAspect::Aspect, PanelStyle, qreal border = 2.0 );
void setPanel( QskAspect::Aspect, PanelStyle ); void setPanel( QskAspect::Aspect, PanelStyle );
void setTab( QskAspect::Aspect, Qt::Orientation ); void setTab( QskAspect::Aspect );
class PrivateData; class PrivateData;
std::unique_ptr< PrivateData > m_data; std::unique_ptr< PrivateData > m_data;

View File

@ -305,7 +305,7 @@ void qskDebugAspect( QDebug debug, const QMetaObject* metaObject, QskAspect::Asp
} }
} }
if ( aspect.placement() != QskAspect::Preserved ) if ( aspect.placement() != QskAspect::NoPlacement )
debug << ", " << qskEnumString( "Placement", aspect.placement() ); debug << ", " << qskEnumString( "Placement", aspect.placement() );
if ( aspect.state() ) if ( aspect.state() )

View File

@ -8,8 +8,10 @@
#include "QskGlobal.h" #include "QskGlobal.h"
#include "QskFlags.h" #include "QskFlags.h"
#include "QskNamespace.h"
#include <qmetaobject.h> #include <qmetaobject.h>
#include <qnamespace.h>
#include <functional> #include <functional>
/* /*
@ -101,8 +103,15 @@ QSK_NAMESPACE( QskAspect )
enum Placement : quint8 enum Placement : quint8
{ {
Preserved = 0, NoPlacement = 0,
Transposed = 1
Vertical = Qt::Vertical,
Horizontal = Qt::Horizontal,
Top = 1,
Left = 2,
Right = 3,
Bottom = 4
}; };
QSK_ENUM( Placement ) QSK_ENUM( Placement )
@ -199,8 +208,8 @@ namespace QskAspect
uint isAnimator : 1; uint isAnimator : 1;
uint primitive : 7; uint primitive : 7;
uint placement : 1; uint placement : 3;
uint reserved1 : 8; uint reserved1 : 6;
uint states : 16; uint states : 16;
uint reserved2 : 16; uint reserved2 : 16;
@ -214,17 +223,17 @@ namespace QskAspect
}; };
inline constexpr Aspect::Aspect() inline constexpr Aspect::Aspect()
: Aspect( Control, Flag, Preserved ) : Aspect( Control, Flag, NoPlacement )
{ {
} }
inline constexpr Aspect::Aspect( Subcontrol subControl ) inline constexpr Aspect::Aspect( Subcontrol subControl )
: Aspect( subControl, Flag, Preserved ) : Aspect( subControl, Flag, NoPlacement )
{ {
} }
inline constexpr Aspect::Aspect( Type type ) inline constexpr Aspect::Aspect( Type type )
: Aspect( Control, type, Preserved ) : Aspect( Control, type, NoPlacement )
{ {
} }

View File

@ -82,8 +82,7 @@ QSizeF QskSeparator::contentsSizeHint() const
QskAspect::Placement QskSeparator::effectivePlacement() const QskAspect::Placement QskSeparator::effectivePlacement() const
{ {
using namespace QskAspect; return static_cast< QskAspect::Placement >( m_orientation );
return ( m_orientation == Qt::Horizontal ) ? Preserved : Transposed;
} }
#include "moc_QskSeparator.cpp" #include "moc_QskSeparator.cpp"

View File

@ -32,9 +32,9 @@ inline const QVariant* qskResolvedHint( QskAspect::Aspect aspect,
if ( aspect.placement() ) if ( aspect.placement() )
{ {
// clear the placement bit and restart // clear the placement bits and restart
aspect = a; aspect = a;
aspect.setPlacement( static_cast< QskAspect::Placement >( 0 ) ); aspect.setPlacement( QskAspect::NoPlacement );
continue; continue;
} }

View File

@ -77,15 +77,15 @@ static inline bool qskCompareResolvedStates(
if ( s1 == 0 ) if ( s1 == 0 )
{ {
if ( aspect1.placement() == 0 ) if ( aspect1.placement() == QskAspect::NoPlacement )
return true; return true;
// clear the placement bit and restart with the initial state // clear the placement bits and restart with the initial state
aspect1 = a1; aspect1 = a1;
aspect1.setPlacement( static_cast< QskAspect::Placement >( 0 ) ); aspect1.setPlacement( QskAspect::NoPlacement );
aspect2 = a2; aspect2 = a2;
aspect2.setPlacement( static_cast< QskAspect::Placement >( 0 ) ); aspect2.setPlacement( QskAspect::NoPlacement );
} }
} }
else else

View File

@ -185,7 +185,7 @@ inline T QskSkinnable::flagHint( QskAspect::Aspect aspect, T defaultValue ) cons
inline QskAspect::Placement QskSkinnable::effectivePlacement() const inline QskAspect::Placement QskSkinnable::effectivePlacement() const
{ {
return QskAspect::Preserved; return QskAspect::NoPlacement;
} }
#endif #endif

View File

@ -91,8 +91,7 @@ Qt::Orientation QskSlider::orientation() const
QskAspect::Placement QskSlider::effectivePlacement() const QskAspect::Placement QskSlider::effectivePlacement() const
{ {
using namespace QskAspect; return static_cast< QskAspect::Placement >( m_data->orientation );
return ( m_data->orientation == Qt::Horizontal ) ? Preserved : Transposed;
} }
void QskSlider::setTracking( bool on ) void QskSlider::setTracking( bool on )

View File

@ -11,6 +11,14 @@
QSK_SUBCONTROL( QskTabBar, Panel ) QSK_SUBCONTROL( QskTabBar, Panel )
static inline Qt::Orientation qskOrientation( int position )
{
if ( ( position == Qsk::Top ) || ( position == Qsk::Bottom ) )
return Qt::Horizontal;
else
return Qt::Vertical;
}
namespace namespace
{ {
class ButtonBox : public QskLinearBox class ButtonBox : public QskLinearBox
@ -47,9 +55,8 @@ namespace
class QskTabBar::PrivateData class QskTabBar::PrivateData
{ {
public: public:
PrivateData() PrivateData( Qsk::Position position )
: currentIndex( -1 ) : position( position )
, buttonBox( nullptr )
{ {
} }
@ -67,22 +74,26 @@ class QskTabBar::PrivateData
} }
} }
int currentIndex; ButtonBox* buttonBox = nullptr;
int currentIndex = -1;
QskTextOptions textOptions; QskTextOptions textOptions;
ButtonBox* buttonBox; uint position : 2;
}; };
QskTabBar::QskTabBar( QQuickItem* parent ) QskTabBar::QskTabBar( QQuickItem* parent )
: QskTabBar( Qt::Horizontal, parent ) : QskTabBar( Qsk::Top, parent )
{ {
} }
QskTabBar::QskTabBar( Qt::Orientation orientation, QQuickItem* parent ) QskTabBar::QskTabBar( Qsk::Position position, QQuickItem* parent )
: Inherited( parent ) : Inherited( parent )
, m_data( new PrivateData() ) , m_data( new PrivateData( position ) )
{ {
setAutoLayoutChildren( true ); setAutoLayoutChildren( true );
const auto orientation = qskOrientation( position );
if ( orientation == Qt::Horizontal ) if ( orientation == Qt::Horizontal )
initSizePolicy( QskSizePolicy::Preferred, QskSizePolicy::Fixed ); initSizePolicy( QskSizePolicy::Preferred, QskSizePolicy::Fixed );
else else
@ -98,25 +109,36 @@ QskTabBar::~QskTabBar()
{ {
} }
void QskTabBar::setOrientation( Qt::Orientation orientation ) void QskTabBar::setPosition( Qsk::Position position )
{ {
if ( orientation == m_data->buttonBox->orientation() ) if ( position == m_data->position )
return; return;
setSizePolicy( sizePolicy( Qt::Vertical ), sizePolicy( Qt::Horizontal ) ); m_data->position = position;
m_data->buttonBox->setOrientation( orientation );
const auto orientation = qskOrientation( position );
if ( orientation != m_data->buttonBox->orientation() )
{
setSizePolicy( sizePolicy( Qt::Vertical ), sizePolicy( Qt::Horizontal ) );
m_data->buttonBox->setOrientation( orientation );
}
resetImplicitSize(); resetImplicitSize();
for ( int i = 0; i < count(); i++ ) for ( int i = 0; i < count(); i++ )
buttonAt( i )->update(); buttonAt( i )->update();
Q_EMIT orientationChanged(); Q_EMIT positionChanged( position );
}
Qsk::Position QskTabBar::position() const
{
return static_cast< Qsk::Position >( m_data->position );
} }
Qt::Orientation QskTabBar::orientation() const Qt::Orientation QskTabBar::orientation() const
{ {
return m_data->buttonBox->orientation(); return qskOrientation( m_data->position );
} }
void QskTabBar::setTextOptions( const QskTextOptions& options ) void QskTabBar::setTextOptions( const QskTextOptions& options )
@ -127,7 +149,7 @@ void QskTabBar::setTextOptions( const QskTextOptions& options )
// QskControl - maybe added to the propagation system ??? // QskControl - maybe added to the propagation system ???
m_data->textOptions = options; m_data->textOptions = options;
Q_EMIT textOptionsChanged(); Q_EMIT textOptionsChanged( options );
for ( int i = 0; i < count(); i++ ) for ( int i = 0; i < count(); i++ )
buttonAt( i )->setTextOptions( options ); buttonAt( i )->setTextOptions( options );
@ -178,7 +200,7 @@ int QskTabBar::insertTab( int index, QskTabButton* button )
m_data->connectButton( button, this, true ); m_data->connectButton( button, this, true );
Q_EMIT countChanged(); Q_EMIT countChanged( count() );
return index; return index;
} }
@ -193,13 +215,13 @@ void QskTabBar::removeTab( int index )
if ( index > m_data->currentIndex ) if ( index > m_data->currentIndex )
{ {
Q_EMIT countChanged(); Q_EMIT countChanged( count() );
} }
else if ( index < m_data->currentIndex ) else if ( index < m_data->currentIndex )
{ {
m_data->currentIndex--; m_data->currentIndex--;
Q_EMIT countChanged(); Q_EMIT countChanged( count() );
Q_EMIT currentIndexChanged( m_data->currentIndex ); Q_EMIT currentIndexChanged( m_data->currentIndex );
} }
else else
@ -243,7 +265,7 @@ void QskTabBar::removeTab( int index )
m_data->currentIndex = nextIndex; m_data->currentIndex = nextIndex;
Q_EMIT countChanged(); Q_EMIT countChanged( count() );
Q_EMIT currentIndexChanged( nextIndex ); Q_EMIT currentIndexChanged( nextIndex );
} }
} }
@ -256,7 +278,7 @@ void QskTabBar::clear()
const int idx = currentIndex(); const int idx = currentIndex();
m_data->buttonBox->clear(); m_data->buttonBox->clear();
Q_EMIT countChanged(); Q_EMIT countChanged( count() );
if ( idx >= 0 ) if ( idx >= 0 )
Q_EMIT currentIndexChanged( -1 ); Q_EMIT currentIndexChanged( -1 );

View File

@ -15,8 +15,10 @@ class QSK_EXPORT QskTabBar : public QskBox
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY( Qt::Orientation orientation READ orientation Q_PROPERTY( Qsk::Position position READ position
WRITE setOrientation NOTIFY orientationChanged FINAL ) WRITE setPosition NOTIFY positionChanged FINAL )
Q_PROPERTY( Qt::Orientation orientation READ orientation )
Q_PROPERTY( int count READ count NOTIFY countChanged FINAL ) Q_PROPERTY( int count READ count NOTIFY countChanged FINAL )
@ -32,11 +34,13 @@ class QSK_EXPORT QskTabBar : public QskBox
QSK_SUBCONTROLS( Panel ) QSK_SUBCONTROLS( Panel )
QskTabBar( QQuickItem* parent = nullptr ); QskTabBar( QQuickItem* parent = nullptr );
QskTabBar( Qt::Orientation, QQuickItem* parent = nullptr ); QskTabBar( Qsk::Position, QQuickItem* parent = nullptr );
~QskTabBar() override; ~QskTabBar() override;
void setOrientation( Qt::Orientation ); void setPosition( Qsk::Position );
Qsk::Position position() const;
Qt::Orientation orientation() const; Qt::Orientation orientation() const;
void setTextOptions( const QskTextOptions& ); void setTextOptions( const QskTextOptions& );
@ -77,9 +81,9 @@ class QSK_EXPORT QskTabBar : public QskBox
Q_SIGNALS: Q_SIGNALS:
void currentIndexChanged( int index ); void currentIndexChanged( int index );
void countChanged(); void countChanged( int );
void textOptionsChanged(); void textOptionsChanged( const QskTextOptions& );
void orientationChanged(); void positionChanged( Qsk::Position );
protected: protected:
void componentComplete() override; void componentComplete() override;

View File

@ -101,15 +101,27 @@ QRectF QskTabButton::layoutRect() const
QskAspect::Placement QskTabButton::effectivePlacement() const QskAspect::Placement QskTabButton::effectivePlacement() const
{ {
using namespace QskAspect;
if ( m_data->tabBar ) if ( m_data->tabBar )
{ {
const auto o = m_data->tabBar->orientation(); const auto pos = m_data->tabBar->position();
return ( o == Qt::Horizontal ) ? Preserved : Transposed;
switch ( pos )
{
case Qsk::Left:
return QskAspect::Left;
case Qsk::Right:
return QskAspect::Right;
case Qsk::Top:
return QskAspect::Top;
case Qsk::Bottom:
return QskAspect::Bottom;
}
} }
return Preserved; return QskAspect::NoPlacement;
} }
QskTabBar* QskTabButton::tabBar() const QskTabBar* QskTabButton::tabBar() const

View File

@ -24,28 +24,22 @@ static inline Qt::Orientation qskTransposed( Qt::Orientation orientation )
class QskTabView::PrivateData class QskTabView::PrivateData
{ {
public: public:
PrivateData() QskTabBar* tabBar = nullptr;
: tabBar( nullptr ) QskStackBox* stackBox = nullptr;
, stackBox( nullptr )
{
}
QskTabBar* tabBar;
QskStackBox* stackBox;
}; };
QskTabView::QskTabView( QQuickItem* parent ) QskTabView::QskTabView( QQuickItem* parent )
: QskTabView( Qt::Vertical, parent ) : QskTabView( Qsk::Top, parent )
{ {
} }
QskTabView::QskTabView( Qt::Orientation orientation, QQuickItem* parent ) QskTabView::QskTabView( Qsk::Position tabPosition, QQuickItem* parent )
: Inherited( parent ) : Inherited( parent )
, m_data( new PrivateData() ) , m_data( new PrivateData() )
{ {
setPolishOnResize( true ); setPolishOnResize( true );
m_data->tabBar = new QskTabBar( qskTransposed( orientation ), this ); m_data->tabBar = new QskTabBar( tabPosition, this );
m_data->tabBar->setZ( 1 ); m_data->tabBar->setZ( 1 );
m_data->stackBox = new QskStackBox( this ); m_data->stackBox = new QskStackBox( this );
@ -71,6 +65,9 @@ QskTabView::QskTabView( Qt::Orientation orientation, QQuickItem* parent )
connect( m_data->tabBar, &QskTabBar::currentIndexChanged, connect( m_data->tabBar, &QskTabBar::currentIndexChanged,
this, &QskTabView::currentIndexChanged ); this, &QskTabView::currentIndexChanged );
connect( m_data->tabBar, &QskTabBar::positionChanged,
this, &QskTabView::tabPositionChanged );
} }
QskTabView::~QskTabView() QskTabView::~QskTabView()
@ -82,18 +79,20 @@ const QskTabBar* QskTabView::tabBar() const
return m_data->tabBar; return m_data->tabBar;
} }
void QskTabView::setOrientation( Qt::Orientation orientation ) void QskTabView::setTabPosition( Qsk::Position position )
{ {
const Qt::Orientation o = qskTransposed( orientation ); if ( position == tabPosition() )
if ( o != m_data->tabBar->orientation() ) return;
{
m_data->tabBar->setOrientation( o );
polish(); m_data->tabBar->setPosition( position );
update();
Q_EMIT orientationChanged(); polish();
} update();
}
Qsk::Position QskTabView::tabPosition() const
{
return m_data->tabBar->position();
} }
Qt::Orientation QskTabView::orientation() const Qt::Orientation QskTabView::orientation() const
@ -205,10 +204,20 @@ QSizeF QskTabView::contentsSizeHint() const
return Inherited::contentsSizeHint(); return Inherited::contentsSizeHint();
const QSizeF barHint = m_data->tabBar->sizeHint(); const QSizeF barHint = m_data->tabBar->sizeHint();
const QSizeF itemHint = m_data->stackBox->sizeHint(); const QSizeF boxHint = m_data->stackBox->sizeHint();
const qreal w = qMax( barHint.width(), itemHint.width() ); qreal w, h;
const qreal h = barHint.height() + itemHint.height();
if ( orientation() == Qt::Vertical )
{
w = qMax( barHint.width(), boxHint.width() );
h = barHint.height() + boxHint.height();
}
else
{
w = barHint.width() + boxHint.width();
h = qMax( barHint.height(), boxHint.height() );
}
return QSizeF( w, h ); return QSizeF( w, h );
} }

View File

@ -7,6 +7,7 @@
#define QSK_TAB_VIEW_H #define QSK_TAB_VIEW_H
#include "QskControl.h" #include "QskControl.h"
#include "QskNamespace.h"
class QskTabBar; class QskTabBar;
class QskTabButton; class QskTabButton;
@ -15,8 +16,10 @@ class QSK_EXPORT QskTabView : public QskControl
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY( Qt::Orientation orientation READ orientation Q_PROPERTY( Qsk::Position tabPosition READ tabPosition
WRITE setOrientation NOTIFY orientationChanged ) WRITE setTabPosition NOTIFY tabPositionChanged FINAL )
Q_PROPERTY( Qt::Orientation orientation READ orientation )
Q_PROPERTY( int count READ count NOTIFY countChanged FINAL ) Q_PROPERTY( int count READ count NOTIFY countChanged FINAL )
@ -29,13 +32,15 @@ class QSK_EXPORT QskTabView : public QskControl
QSK_SUBCONTROLS( TabBar, Page ) QSK_SUBCONTROLS( TabBar, Page )
QskTabView( QQuickItem* parent = nullptr ); QskTabView( QQuickItem* parent = nullptr );
QskTabView( Qt::Orientation, QQuickItem* parent = nullptr ); QskTabView( Qsk::Position tabPosition, QQuickItem* parent = nullptr );
~QskTabView() override; ~QskTabView() override;
const QskTabBar* tabBar() const; const QskTabBar* tabBar() const;
void setOrientation( Qt::Orientation ); void setTabPosition( Qsk::Position );
Qsk::Position tabPosition() const;
Qt::Orientation orientation() const; Qt::Orientation orientation() const;
int addTab( QskTabButton*, QQuickItem* ); int addTab( QskTabButton*, QQuickItem* );
@ -68,8 +73,8 @@ class QSK_EXPORT QskTabView : public QskControl
Q_SIGNALS: Q_SIGNALS:
void currentIndexChanged( int index ); void currentIndexChanged( int index );
void countChanged(); void countChanged( int );
void orientationChanged(); void tabPositionChanged( Qsk::Position );
protected: protected:
bool event( QEvent* event ) override; bool event( QEvent* event ) override;

View File

@ -52,18 +52,25 @@ QRectF QskTabViewSkinlet::pageRect( const QskTabView* tabView ) const
{ {
const QRectF barRect = subControlRect( tabView, QskTabView::TabBar ); const QRectF barRect = subControlRect( tabView, QskTabView::TabBar );
QRectF r = tabView->contentsRect(); QRectF r = tabView->layoutRect();
if ( tabView->orientation() == Qt::Vertical ) switch( tabView->tabPosition() )
{ {
r.setTop( barRect.bottom() ); case Qsk::Top:
} r.setTop( barRect.bottom() );
else break;
{
if ( tabView->layoutMirroring() ) case Qsk::Bottom:
r.setRight( r.right() - barRect.left() ); r.setBottom( barRect.top() );
else break;
case Qsk::Left:
r.setLeft( barRect.right() ); r.setLeft( barRect.right() );
break;
case Qsk::Right:
r.setRight( barRect.left() );
break;
} }
return r; return r;
@ -71,19 +78,27 @@ QRectF QskTabViewSkinlet::pageRect( const QskTabView* tabView ) const
QRectF QskTabViewSkinlet::tabBarRect( const QskTabView* tabView ) const QRectF QskTabViewSkinlet::tabBarRect( const QskTabView* tabView ) const
{ {
QRectF r = tabView->layoutRect();
const QSizeF hint = tabView->tabBar()->sizeHint(); const QSizeF hint = tabView->tabBar()->sizeHint();
if ( tabView->orientation() == Qt::Vertical ) QRectF r = tabView->layoutRect();
{
r.setHeight( hint.height() );
}
else
{
r.setWidth( hint.width() );
if ( tabView->layoutMirroring() ) switch( tabView->tabPosition() )
r.moveLeft( r.right() - r.width() ); {
case Qsk::Top:
r.setBottom( hint.height() );
break;
case Qsk::Bottom:
r.setTop( r.bottom() - hint.height() );
break;
case Qsk::Left:
r.setRight( hint.width() );
break;
case Qsk::Right:
r.setLeft( r.right() - hint.width() );
break;
} }
return r; return r;