flickable tabbars
This commit is contained in:
parent
3c7308e23f
commit
53e924a999
@ -39,7 +39,7 @@ class TabView : public QskTabView
|
||||
TabView( QQuickItem* parent = nullptr )
|
||||
: QskTabView( parent )
|
||||
{
|
||||
for ( int i = 0; i < 6; i++ )
|
||||
for ( int i = 0; i < 10; i++ )
|
||||
{
|
||||
QString text;
|
||||
if ( i == 4 )
|
||||
|
@ -569,6 +569,9 @@ void QskMaterialSkin::initTabBarHints()
|
||||
setBoxShape( Q::Panel, 0 );
|
||||
setBoxBorderMetrics( Q::Panel, 0 );
|
||||
setGradient( Q::Panel, QskGradient() );
|
||||
|
||||
// when flicking
|
||||
setAnimation( Q::Panel | Metric, QskAnimationHint( 200, QEasingCurve::InCubic ) );
|
||||
}
|
||||
|
||||
void QskMaterialSkin::initTabViewHints()
|
||||
|
@ -641,6 +641,9 @@ void QskSquiekSkin::initTabBarHints()
|
||||
setMargins( Q::Panel | Padding, 0 );
|
||||
setMargins( Q::Panel | Margin, 0 );
|
||||
setPanel( Q::Panel, NoPanel );
|
||||
|
||||
// when flicking
|
||||
setAnimation( Q::Panel | Metric, QskAnimationHint( 200, QEasingCurve::OutCubic ) );
|
||||
}
|
||||
|
||||
void QskSquiekSkin::initTabViewHints()
|
||||
|
@ -959,6 +959,15 @@ QRectF QskControl::focusIndicatorRect() const
|
||||
return contentsRect();
|
||||
}
|
||||
|
||||
bool QskControl::hasFocusIndicatorClip() const
|
||||
{
|
||||
/*
|
||||
Often we want to clip the focus indicator,
|
||||
when the control is clipped.
|
||||
*/
|
||||
return clip();
|
||||
}
|
||||
|
||||
void QskControl::updateLayout()
|
||||
{
|
||||
}
|
||||
|
@ -91,7 +91,9 @@ class QSK_EXPORT QskControl : public QskQuickItem, public QskSkinnable
|
||||
|
||||
virtual QRectF layoutRectForSize( const QSizeF& ) const;
|
||||
virtual QRectF gestureRect() const;
|
||||
|
||||
virtual QRectF focusIndicatorRect() const;
|
||||
virtual bool hasFocusIndicatorClip() const;
|
||||
|
||||
QRectF subControlRect( QskAspect::Subcontrol ) const;
|
||||
QRectF subControlRect( const QSizeF&, QskAspect::Subcontrol ) const;
|
||||
|
@ -103,17 +103,26 @@ void QskFocusIndicator::onFocusItemChanged()
|
||||
{
|
||||
auto itemParent = item->parentItem();
|
||||
|
||||
if ( itemParent == window()->contentItem() || itemParent->clip() )
|
||||
bool doReparent = ( itemParent == window()->contentItem() );
|
||||
|
||||
if ( !doReparent )
|
||||
{
|
||||
/*
|
||||
When the focus item is clipped - maybe because of being at the
|
||||
border of a scrollarea - the focus indicator needs to be
|
||||
border of a scrollarea - the focus indicator might need to be
|
||||
clipped as well. The easiest way to have this is to put us
|
||||
below the item having the clip.
|
||||
*/
|
||||
setParentItem( itemParent );
|
||||
|
||||
if ( auto control = qskControlCast( itemParent ) )
|
||||
doReparent = control->hasFocusIndicatorClip();
|
||||
else
|
||||
doReparent = itemParent->clip();
|
||||
}
|
||||
|
||||
if ( doReparent )
|
||||
setParentItem( itemParent );
|
||||
|
||||
if ( itemParent == parentItem() )
|
||||
{
|
||||
// We want to be on top, but do we cover all corner cases ???
|
||||
|
@ -124,9 +124,13 @@ class QskScrollAreaClipItem final : public QskControl, public QQuickItemChangeLi
|
||||
return scrollArea()->subControlRect( QskScrollView::Viewport );
|
||||
}
|
||||
|
||||
bool hasFocusIndicatorClip() const override
|
||||
{
|
||||
return scrollArea()->hasFocusIndicatorClip();
|
||||
}
|
||||
|
||||
protected:
|
||||
bool event( QEvent* event ) override;
|
||||
void windowChangeEvent( QskWindowChangeEvent* ) override;
|
||||
|
||||
void itemChange( ItemChange, const ItemChangeData& ) override;
|
||||
void geometryChanged( const QRectF&, const QRectF& ) override;
|
||||
@ -151,9 +155,6 @@ class QskScrollAreaClipItem final : public QskControl, public QQuickItemChangeLi
|
||||
void updateNode( QSGNode* ) override;
|
||||
|
||||
private:
|
||||
void connectWindow( const QQuickWindow*, bool on );
|
||||
void onFocusItemChanged();
|
||||
|
||||
inline QskScrollArea* scrollArea()
|
||||
{
|
||||
return static_cast< QskScrollArea* >( parentItem() );
|
||||
@ -172,8 +173,6 @@ QskScrollAreaClipItem::QskScrollAreaClipItem( QskScrollArea* scrollArea )
|
||||
{
|
||||
setObjectName( QStringLiteral( "QskScrollAreaClipItem" ) );
|
||||
setClip( true );
|
||||
|
||||
connectWindow( window(), true );
|
||||
}
|
||||
|
||||
QskScrollAreaClipItem::~QskScrollAreaClipItem()
|
||||
@ -181,23 +180,6 @@ QskScrollAreaClipItem::~QskScrollAreaClipItem()
|
||||
enableGeometryListener( false );
|
||||
}
|
||||
|
||||
void QskScrollAreaClipItem::connectWindow( const QQuickWindow* window, bool on )
|
||||
{
|
||||
if ( window == nullptr )
|
||||
return;
|
||||
|
||||
if ( on )
|
||||
{
|
||||
connect( window, &QQuickWindow::activeFocusItemChanged,
|
||||
this, &QskScrollAreaClipItem::onFocusItemChanged );
|
||||
}
|
||||
else
|
||||
{
|
||||
disconnect( window, &QQuickWindow::activeFocusItemChanged,
|
||||
this, &QskScrollAreaClipItem::onFocusItemChanged );
|
||||
}
|
||||
}
|
||||
|
||||
void QskScrollAreaClipItem::updateNode( QSGNode* )
|
||||
{
|
||||
auto* d = QQuickItemPrivate::get( this );
|
||||
@ -310,20 +292,6 @@ void QskScrollAreaClipItem::enableGeometryListener( bool on )
|
||||
}
|
||||
}
|
||||
|
||||
void QskScrollAreaClipItem::onFocusItemChanged()
|
||||
{
|
||||
if ( window() == nullptr || !scrollArea()->autoScrollFocusItem() )
|
||||
return;
|
||||
|
||||
const auto focusItem = window()->activeFocusItem();
|
||||
if ( focusItem )
|
||||
{
|
||||
auto reason = QQuickWindowPrivate::get( window() )->lastFocusReason;
|
||||
if ( reason == Qt::TabFocusReason || reason == Qt::BacktabFocusReason )
|
||||
scrollArea()->ensureItemVisible( focusItem );
|
||||
}
|
||||
}
|
||||
|
||||
bool QskScrollAreaClipItem::event( QEvent* event )
|
||||
{
|
||||
if ( event->type() == QEvent::LayoutRequest )
|
||||
@ -335,20 +303,11 @@ bool QskScrollAreaClipItem::event( QEvent* event )
|
||||
return Inherited::event( event );
|
||||
}
|
||||
|
||||
void QskScrollAreaClipItem::windowChangeEvent( QskWindowChangeEvent* event )
|
||||
{
|
||||
Inherited::windowChangeEvent( event );
|
||||
|
||||
connectWindow( event->oldWindow(), false );
|
||||
connectWindow( event->window(), true );
|
||||
}
|
||||
|
||||
class QskScrollArea::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData()
|
||||
: isItemResizable( true )
|
||||
, autoScrollFocusItem( true )
|
||||
{
|
||||
}
|
||||
|
||||
@ -369,7 +328,6 @@ class QskScrollArea::PrivateData
|
||||
QskScrollAreaClipItem* clipItem = nullptr;
|
||||
|
||||
bool isItemResizable : 1;
|
||||
bool autoScrollFocusItem : 1;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -401,16 +359,6 @@ QskScrollArea::~QskScrollArea()
|
||||
delete m_data->clipItem;
|
||||
}
|
||||
|
||||
void QskScrollArea::ensureItemVisible( const QQuickItem* item )
|
||||
{
|
||||
const QQuickItem* scrolledItem = this->scrolledItem();
|
||||
if ( scrolledItem && qskIsAncestorOf( scrolledItem, item ) )
|
||||
{
|
||||
const auto pos = scrolledItem->mapFromItem( item, QPointF() );
|
||||
ensureVisible( QRectF( pos.x(), pos.y(), item->width(), item->height() ) );
|
||||
}
|
||||
}
|
||||
|
||||
void QskScrollArea::updateLayout()
|
||||
{
|
||||
Inherited::updateLayout();
|
||||
@ -457,18 +405,9 @@ void QskScrollArea::adjustItem()
|
||||
}
|
||||
}
|
||||
|
||||
void QskScrollArea::setAutoScrollFocusedItem( bool on )
|
||||
bool QskScrollArea::hasFocusIndicatorClip() const
|
||||
{
|
||||
if ( m_data->autoScrollFocusItem != on )
|
||||
{
|
||||
m_data->autoScrollFocusItem = on;
|
||||
Q_EMIT autoScrollFocusedItemChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool QskScrollArea::autoScrollFocusItem() const
|
||||
{
|
||||
return m_data->autoScrollFocusItem;
|
||||
return true;
|
||||
}
|
||||
|
||||
void QskScrollArea::setItemResizable( bool on )
|
||||
@ -476,7 +415,7 @@ void QskScrollArea::setItemResizable( bool on )
|
||||
if ( on != m_data->isItemResizable )
|
||||
{
|
||||
m_data->isItemResizable = on;
|
||||
Q_EMIT itemResizableChanged();
|
||||
Q_EMIT itemResizableChanged( on );
|
||||
|
||||
if ( m_data->isItemResizable )
|
||||
polish();
|
||||
@ -520,8 +459,7 @@ QQuickItem* QskScrollArea::scrolledItem() const
|
||||
|
||||
void QskScrollArea::translateItem()
|
||||
{
|
||||
auto item = m_data->clipItem->scrolledItem();
|
||||
if ( item )
|
||||
if ( auto item = m_data->clipItem->scrolledItem() )
|
||||
{
|
||||
const QPointF pos = viewContentsRect().topLeft() - scrollPos();
|
||||
item->setPosition( pos );
|
||||
|
@ -18,9 +18,6 @@ class QSK_EXPORT QskScrollArea : public QskScrollView
|
||||
Q_PROPERTY( bool itemResizable READ isItemResizable
|
||||
WRITE setItemResizable NOTIFY itemResizableChanged FINAL )
|
||||
|
||||
Q_PROPERTY( bool autoScrollFocusedItem READ autoScrollFocusItem
|
||||
WRITE setAutoScrollFocusedItem NOTIFY autoScrollFocusedItemChanged FINAL )
|
||||
|
||||
using Inherited = QskScrollView;
|
||||
|
||||
public:
|
||||
@ -33,15 +30,11 @@ class QSK_EXPORT QskScrollArea : public QskScrollView
|
||||
void setItemResizable( bool on );
|
||||
bool isItemResizable() const;
|
||||
|
||||
void setAutoScrollFocusedItem( bool on );
|
||||
bool autoScrollFocusItem() const;
|
||||
|
||||
void ensureItemVisible( const QQuickItem* );
|
||||
bool hasFocusIndicatorClip() const override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void itemResizableChanged();
|
||||
void scrolledItemChanged();
|
||||
void autoScrollFocusedItemChanged();
|
||||
void itemResizableChanged( bool );
|
||||
|
||||
protected:
|
||||
void updateLayout() override;
|
||||
|
@ -9,6 +9,11 @@
|
||||
#include "QskFlickAnimator.h"
|
||||
#include "QskGesture.h"
|
||||
#include "QskPanGestureRecognizer.h"
|
||||
#include "QskQuick.h"
|
||||
|
||||
QSK_QT_PRIVATE_BEGIN
|
||||
#include <private/qquickwindow_p.h>
|
||||
QSK_QT_PRIVATE_END
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -95,6 +100,11 @@ namespace
|
||||
class QskScrollBox::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData()
|
||||
: autoScrollFocusItem( true )
|
||||
{
|
||||
}
|
||||
|
||||
QPointF scrollPos;
|
||||
QSizeF scrollableSize = QSize( 0.0, 0.0 );
|
||||
|
||||
@ -105,6 +115,8 @@ class QskScrollBox::PrivateData
|
||||
ScrollAnimator scroller;
|
||||
|
||||
const qreal viewportPadding = 10;
|
||||
|
||||
bool autoScrollFocusItem : 1;
|
||||
};
|
||||
|
||||
QskScrollBox::QskScrollBox( QQuickItem* parent )
|
||||
@ -119,14 +131,52 @@ QskScrollBox::QskScrollBox( QQuickItem* parent )
|
||||
|
||||
setFiltersChildMouseEvents( true );
|
||||
|
||||
setAcceptedMouseButtons( Qt::LeftButton );
|
||||
setWheelEnabled( true );
|
||||
|
||||
setFocusPolicy( Qt::StrongFocus );
|
||||
|
||||
connectWindow( window(), true );
|
||||
}
|
||||
|
||||
QskScrollBox::~QskScrollBox()
|
||||
{
|
||||
}
|
||||
|
||||
void QskScrollBox::setAutoScrollFocusedItem( bool on )
|
||||
{
|
||||
if ( m_data->autoScrollFocusItem != on )
|
||||
{
|
||||
m_data->autoScrollFocusItem = on;
|
||||
connectWindow( window(), true );
|
||||
Q_EMIT autoScrollFocusedItemChanged( on );
|
||||
}
|
||||
}
|
||||
|
||||
bool QskScrollBox::autoScrollFocusItem() const
|
||||
{
|
||||
return m_data->autoScrollFocusItem;
|
||||
}
|
||||
|
||||
void QskScrollBox::onFocusItemChanged()
|
||||
{
|
||||
if ( window() )
|
||||
{
|
||||
auto reason = QQuickWindowPrivate::get( window() )->lastFocusReason;
|
||||
if ( reason == Qt::TabFocusReason || reason == Qt::BacktabFocusReason )
|
||||
ensureFocusItemVisible();
|
||||
}
|
||||
}
|
||||
|
||||
void QskScrollBox::ensureFocusItemVisible()
|
||||
{
|
||||
if ( window() == nullptr )
|
||||
return;
|
||||
|
||||
if ( const auto focusItem = window()->activeFocusItem() )
|
||||
ensureItemVisible( focusItem );
|
||||
}
|
||||
|
||||
void QskScrollBox::setFlickRecognizerTimeout( int timeout )
|
||||
{
|
||||
if ( timeout < 0 )
|
||||
@ -202,6 +252,17 @@ QRectF QskScrollBox::gestureRect() const
|
||||
return viewContentsRect();
|
||||
}
|
||||
|
||||
void QskScrollBox::ensureItemVisible( const QQuickItem* item )
|
||||
{
|
||||
if ( qskIsAncestorOf( this, item ) )
|
||||
{
|
||||
auto pos = scrollPos() - viewContentsRect().topLeft();
|
||||
pos += mapFromItem( item, QPointF() );
|
||||
|
||||
ensureVisible( QRectF( pos.x(), pos.y(), item->width(), item->height() ) );
|
||||
}
|
||||
}
|
||||
|
||||
void QskScrollBox::ensureVisible( const QPointF& pos )
|
||||
{
|
||||
const qreal margin = m_data->viewportPadding;
|
||||
@ -282,6 +343,14 @@ void QskScrollBox::ensureVisible( const QRectF& itemRect )
|
||||
setScrollPos( newPos );
|
||||
}
|
||||
|
||||
void QskScrollBox::windowChangeEvent( QskWindowChangeEvent* event )
|
||||
{
|
||||
Inherited::windowChangeEvent( event );
|
||||
|
||||
connectWindow( event->oldWindow(), false );
|
||||
connectWindow( event->window(), true );
|
||||
}
|
||||
|
||||
void QskScrollBox::geometryChangeEvent( QskGeometryChangeEvent* event )
|
||||
{
|
||||
if ( event->isResized() )
|
||||
@ -443,4 +512,21 @@ QPointF QskScrollBox::boundedScrollPos( const QPointF& pos ) const
|
||||
return QPointF( qBound( 0.0, pos.x(), maxX ), qBound( 0.0, pos.y(), maxY ) );
|
||||
}
|
||||
|
||||
void QskScrollBox::connectWindow( const QQuickWindow* window, bool on )
|
||||
{
|
||||
if ( ( window == nullptr ) || ( on && !autoScrollFocusItem() ) )
|
||||
return;
|
||||
|
||||
if ( on )
|
||||
{
|
||||
QObject::connect( window, &QQuickWindow::activeFocusItemChanged,
|
||||
this, &QskScrollBox::onFocusItemChanged, Qt::UniqueConnection );
|
||||
}
|
||||
else
|
||||
{
|
||||
QObject::disconnect( window, &QQuickWindow::activeFocusItemChanged,
|
||||
this, &QskScrollBox::onFocusItemChanged );
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_QskScrollBox.cpp"
|
||||
|
@ -18,12 +18,18 @@ class QSK_EXPORT QskScrollBox : public QskControl
|
||||
Q_PROPERTY( Qt::Orientations flickableOrientations READ flickableOrientations
|
||||
WRITE setFlickableOrientations NOTIFY flickableOrientationsChanged FINAL )
|
||||
|
||||
Q_PROPERTY( bool autoScrollFocusedItem READ autoScrollFocusItem
|
||||
WRITE setAutoScrollFocusedItem NOTIFY autoScrollFocusedItemChanged FINAL )
|
||||
|
||||
using Inherited = QskControl;
|
||||
|
||||
public:
|
||||
QskScrollBox( QQuickItem* parent = nullptr );
|
||||
~QskScrollBox() override;
|
||||
|
||||
void setAutoScrollFocusedItem( bool on );
|
||||
bool autoScrollFocusItem() const;
|
||||
|
||||
void setFlickableOrientations( Qt::Orientations );
|
||||
Qt::Orientations flickableOrientations() const;
|
||||
|
||||
@ -43,17 +49,21 @@ class QSK_EXPORT QskScrollBox : public QskControl
|
||||
void scrollPosChanged();
|
||||
void scrollableSizeChanged( const QSizeF& );
|
||||
|
||||
void autoScrollFocusedItemChanged( bool );
|
||||
void flickableOrientationsChanged();
|
||||
|
||||
public Q_SLOTS:
|
||||
void setScrollPos( const QPointF& );
|
||||
void scrollTo( const QPointF& );
|
||||
|
||||
void ensureItemVisible( const QQuickItem* );
|
||||
void ensureFocusItemVisible();
|
||||
void ensureVisible( const QPointF& );
|
||||
void ensureVisible( const QRectF& );
|
||||
|
||||
protected:
|
||||
void geometryChangeEvent( QskGeometryChangeEvent* ) override;
|
||||
void windowChangeEvent( QskWindowChangeEvent* ) override;
|
||||
void gestureEvent( QskGestureEvent* ) override;
|
||||
|
||||
#ifndef QT_NO_WHEELEVENT
|
||||
@ -66,6 +76,8 @@ class QSK_EXPORT QskScrollBox : public QskControl
|
||||
|
||||
private:
|
||||
QPointF boundedScrollPos( const QPointF& ) const;
|
||||
void onFocusItemChanged();
|
||||
void connectWindow( const QQuickWindow*, bool on );
|
||||
|
||||
class PrivateData;
|
||||
std::unique_ptr< PrivateData > m_data;
|
||||
|
@ -38,7 +38,6 @@ QskScrollView::QskScrollView( QQuickItem* parent )
|
||||
: Inherited( parent )
|
||||
, m_data( new PrivateData() )
|
||||
{
|
||||
setAcceptedMouseButtons( Qt::LeftButton );
|
||||
}
|
||||
|
||||
QskScrollView::~QskScrollView()
|
||||
|
@ -5,9 +5,12 @@
|
||||
|
||||
#include "QskTabBar.h"
|
||||
#include "QskAspect.h"
|
||||
#include "QskScrollBox.h"
|
||||
#include "QskLinearBox.h"
|
||||
#include "QskTabButton.h"
|
||||
#include "QskTextOptions.h"
|
||||
#include "QskAnimationHint.h"
|
||||
#include "QskQuick.h"
|
||||
|
||||
QSK_SUBCONTROL( QskTabBar, Panel )
|
||||
|
||||
@ -21,8 +24,10 @@ static inline Qt::Orientation qskOrientation( int position )
|
||||
|
||||
namespace
|
||||
{
|
||||
class ButtonBox : public QskLinearBox
|
||||
class ButtonBox final : public QskLinearBox
|
||||
{
|
||||
using Inherited = QskLinearBox;
|
||||
|
||||
public:
|
||||
ButtonBox( Qt::Orientation orientation, QQuickItem* parent )
|
||||
: QskLinearBox( orientation, parent )
|
||||
@ -48,6 +53,142 @@ namespace
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class ScrollBox final : public QskScrollBox
|
||||
{
|
||||
using Inherited = QskScrollBox;
|
||||
|
||||
public:
|
||||
ScrollBox( QQuickItem* parent )
|
||||
: QskScrollBox( parent )
|
||||
{
|
||||
setPolishOnResize( true );
|
||||
enableAutoTranslation( true );
|
||||
|
||||
setFocusPolicy( Qt::NoFocus );
|
||||
}
|
||||
|
||||
bool hasFocusIndicatorClip() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QskAnimationHint flickHint() const override
|
||||
{
|
||||
if ( auto tabBar = qobject_cast< const QskTabBar* >( parentItem() ) )
|
||||
{
|
||||
return tabBar->effectiveAnimation( QskAspect::Metric,
|
||||
QskTabBar::Panel, QskAspect::NoState );
|
||||
}
|
||||
|
||||
return QskAnimationHint( 200, QEasingCurve::OutCubic );
|
||||
}
|
||||
|
||||
QRectF viewContentsRect() const override
|
||||
{
|
||||
return layoutRect();
|
||||
}
|
||||
|
||||
void setOrientation( Qt::Orientation orientation )
|
||||
{
|
||||
setFlickableOrientations( orientation );
|
||||
|
||||
if ( orientation == Qt::Horizontal )
|
||||
setSizePolicy( QskSizePolicy::Ignored, QskSizePolicy::MinimumExpanding );
|
||||
else
|
||||
setSizePolicy( QskSizePolicy::MinimumExpanding, QskSizePolicy::Ignored );
|
||||
}
|
||||
|
||||
void ensureItemVisible( const QQuickItem* item )
|
||||
{
|
||||
if ( qskIsAncestorOf( this, item ) )
|
||||
{
|
||||
const auto pos = mapFromItem( item, QPointF() );
|
||||
ensureVisible( QRectF( pos.x(), pos.y(), item->width(), item->height() ) );
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
bool event( QEvent* event ) override
|
||||
{
|
||||
if ( event->type() == QEvent::LayoutRequest )
|
||||
{
|
||||
resetImplicitSize();
|
||||
polish();
|
||||
}
|
||||
|
||||
return Inherited::event( event );
|
||||
}
|
||||
|
||||
void updateLayout() override
|
||||
{
|
||||
auto scrolledItem = this->scrolledItem();
|
||||
|
||||
auto itemSize = viewContentsRect().size();
|
||||
itemSize = qskConstrainedItemSize( scrolledItem, itemSize );
|
||||
|
||||
scrolledItem->setSize( itemSize );
|
||||
|
||||
enableAutoTranslation( false );
|
||||
|
||||
setScrollableSize( itemSize );
|
||||
setScrollPos( scrollPos() );
|
||||
|
||||
enableAutoTranslation( true );
|
||||
|
||||
translateItem();
|
||||
|
||||
setClip( size().width() < itemSize.width()
|
||||
|| size().height() < itemSize.height() );
|
||||
}
|
||||
|
||||
QSizeF layoutSizeHint( Qt::SizeHint which, const QSizeF& constraint ) const override
|
||||
{
|
||||
auto hint = scrolledItem()->sizeConstraint( which, constraint );
|
||||
|
||||
if ( which == Qt::MinimumSize )
|
||||
{
|
||||
if ( sizePolicy().horizontalPolicy() & QskSizePolicy::ShrinkFlag )
|
||||
hint.setWidth( -1 );
|
||||
|
||||
if ( sizePolicy().verticalPolicy() & QskSizePolicy::ShrinkFlag )
|
||||
hint.setHeight( -1 );
|
||||
}
|
||||
|
||||
return hint;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
inline QskControl* scrolledItem() const
|
||||
{
|
||||
return qskControlCast( childItems().first() );
|
||||
}
|
||||
|
||||
void enableAutoTranslation( bool on )
|
||||
{
|
||||
if ( on )
|
||||
{
|
||||
connect( this, &QskScrollBox::scrollPosChanged,
|
||||
this, &ScrollBox::translateItem );
|
||||
}
|
||||
else
|
||||
{
|
||||
disconnect( this, &QskScrollBox::scrollPosChanged,
|
||||
this, &ScrollBox::translateItem );
|
||||
}
|
||||
}
|
||||
|
||||
void translateItem()
|
||||
{
|
||||
if ( auto item = this->scrolledItem() )
|
||||
{
|
||||
const QPointF pos = viewContentsRect().topLeft() - scrollPos();
|
||||
item->setPosition( pos );
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class QskTabBar::PrivateData
|
||||
@ -72,6 +213,7 @@ class QskTabBar::PrivateData
|
||||
}
|
||||
}
|
||||
|
||||
ScrollBox* scrollBox = nullptr;
|
||||
ButtonBox* buttonBox = nullptr;
|
||||
int currentIndex = -1;
|
||||
|
||||
@ -97,9 +239,17 @@ QskTabBar::QskTabBar( Qsk::Position position, QQuickItem* parent )
|
||||
else
|
||||
initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Preferred );
|
||||
|
||||
m_data->buttonBox = new ButtonBox( orientation, this );
|
||||
m_data->scrollBox = new ScrollBox( this );
|
||||
m_data->scrollBox->setOrientation( orientation );
|
||||
|
||||
m_data->buttonBox = new ButtonBox( orientation, m_data->scrollBox );
|
||||
m_data->buttonBox->setSpacing( metric( QskTabBar::Panel | QskAspect::Spacing ) );
|
||||
|
||||
#if 1
|
||||
// We might want to have a mode, where the buttons are stretched: TODO ...
|
||||
m_data->buttonBox->setSizePolicy( QskSizePolicy::Maximum, QskSizePolicy::Maximum );
|
||||
#endif
|
||||
|
||||
connect( this, &QskTabBar::currentIndexChanged,
|
||||
m_data->buttonBox, &ButtonBox::restack, Qt::QueuedConnection );
|
||||
}
|
||||
@ -120,6 +270,7 @@ void QskTabBar::setPosition( Qsk::Position position )
|
||||
{
|
||||
setSizePolicy( sizePolicy( Qt::Vertical ), sizePolicy( Qt::Horizontal ) );
|
||||
m_data->buttonBox->setOrientation( orientation );
|
||||
m_data->scrollBox->setOrientation( orientation );
|
||||
}
|
||||
|
||||
resetImplicitSize();
|
||||
@ -140,6 +291,20 @@ Qt::Orientation QskTabBar::orientation() const
|
||||
return qskOrientation( m_data->position );
|
||||
}
|
||||
|
||||
void QskTabBar::setAutoScrollFocusedButton( bool on )
|
||||
{
|
||||
if ( m_data->scrollBox->autoScrollFocusItem() != on )
|
||||
{
|
||||
m_data->scrollBox->setAutoScrollFocusedItem( on );
|
||||
Q_EMIT autoScrollFocusedButtonChanged( on );
|
||||
}
|
||||
}
|
||||
|
||||
bool QskTabBar::autoScrollFocusButton() const
|
||||
{
|
||||
return m_data->scrollBox->autoScrollFocusItem();
|
||||
}
|
||||
|
||||
void QskTabBar::setTextOptions( const QskTextOptions& options )
|
||||
{
|
||||
if ( options != m_data->textOptions )
|
||||
@ -366,6 +531,11 @@ int QskTabBar::indexOf( QskTabButton* button ) const
|
||||
return m_data->buttonBox->indexOf( button );
|
||||
}
|
||||
|
||||
void QskTabBar::ensureButtonVisible( const QskTabButton* button )
|
||||
{
|
||||
m_data->scrollBox->ensureItemVisible( button );
|
||||
}
|
||||
|
||||
void QskTabBar::componentComplete()
|
||||
{
|
||||
Inherited::componentComplete();
|
||||
|
@ -20,6 +20,9 @@ class QSK_EXPORT QskTabBar : public QskBox
|
||||
|
||||
Q_PROPERTY( Qt::Orientation orientation READ orientation )
|
||||
|
||||
Q_PROPERTY( bool autoScrollFocusButton READ autoScrollFocusButton
|
||||
WRITE setAutoScrollFocusedButton NOTIFY autoScrollFocusedButtonChanged FINAL )
|
||||
|
||||
Q_PROPERTY( int count READ count NOTIFY countChanged FINAL )
|
||||
|
||||
Q_PROPERTY( int currentIndex READ currentIndex
|
||||
@ -43,6 +46,11 @@ class QSK_EXPORT QskTabBar : public QskBox
|
||||
|
||||
Qt::Orientation orientation() const;
|
||||
|
||||
void setAutoScrollFocusedButton( bool on );
|
||||
bool autoScrollFocusButton() const;
|
||||
|
||||
void ensureButtonVisible( const QskTabButton* );
|
||||
|
||||
void setTextOptions( const QskTextOptions& );
|
||||
QskTextOptions textOptions() const;
|
||||
|
||||
@ -86,6 +94,7 @@ class QSK_EXPORT QskTabBar : public QskBox
|
||||
void countChanged( int );
|
||||
void textOptionsChanged( const QskTextOptions& );
|
||||
void positionChanged( Qsk::Position );
|
||||
void autoScrollFocusedButtonChanged( bool );
|
||||
|
||||
protected:
|
||||
void componentComplete() override;
|
||||
|
@ -210,12 +210,22 @@ QSizeF QskTabView::layoutSizeHint(
|
||||
const auto& tabBar = m_data->tabBar;
|
||||
const auto& stackBox = m_data->stackBox;
|
||||
|
||||
const auto barHint = tabBar->sizeConstraint( which );
|
||||
auto barHint = tabBar->sizeConstraint( which );
|
||||
|
||||
#if 1
|
||||
/*
|
||||
How to limit the constribution of the tabbar in a reasonable way ?
|
||||
QTabWidget uses 200x200 - what is kind of random. TODO ...
|
||||
*/
|
||||
const qreal minBarSize = 200;
|
||||
#endif
|
||||
|
||||
QSizeF hint;
|
||||
|
||||
if ( orientation() == Qt::Vertical )
|
||||
{
|
||||
barHint.setWidth( qMin( barHint.width(), minBarSize ) );
|
||||
|
||||
if ( constraint.width() >= 0.0 )
|
||||
{
|
||||
qreal w = qMax( constraint.width(), barHint.width() );
|
||||
@ -240,6 +250,8 @@ QSizeF QskTabView::layoutSizeHint(
|
||||
}
|
||||
else
|
||||
{
|
||||
barHint.setHeight( qMin( barHint.height(), minBarSize ) );
|
||||
|
||||
if ( constraint.width() >= 0.0 )
|
||||
{
|
||||
qreal w = constraint.width() - barHint.width();
|
||||
|
Loading…
x
Reference in New Issue
Block a user