segmented bar: Support focus
This commit is contained in:
parent
acb225bb82
commit
caba0d5735
|
@ -500,7 +500,6 @@ void Editor::setupFocusIndicator()
|
||||||
|
|
||||||
void Editor::setupSegmentedBar()
|
void Editor::setupSegmentedBar()
|
||||||
{
|
{
|
||||||
// copied from Squiek: we need something similar to a tab bar here. TODO ...
|
|
||||||
using A = QskAspect;
|
using A = QskAspect;
|
||||||
using Q = QskSegmentedBar;
|
using Q = QskSegmentedBar;
|
||||||
|
|
||||||
|
@ -518,6 +517,7 @@ void Editor::setupSegmentedBar()
|
||||||
|
|
||||||
setBoxBorderMetrics( Q::Panel, 1_dp );
|
setBoxBorderMetrics( Q::Panel, 1_dp );
|
||||||
setBoxBorderColors( Q::Panel, m_pal.outline );
|
setBoxBorderColors( Q::Panel, m_pal.outline );
|
||||||
|
|
||||||
setBoxBorderColors( Q::Panel | Q::Disabled, m_pal.onSurface12 );
|
setBoxBorderColors( Q::Panel | Q::Disabled, m_pal.onSurface12 );
|
||||||
|
|
||||||
setStrutSize( Q::Panel | A::Horizontal, panelStrutSize );
|
setStrutSize( Q::Panel | A::Horizontal, panelStrutSize );
|
||||||
|
@ -529,13 +529,40 @@ void Editor::setupSegmentedBar()
|
||||||
|
|
||||||
setStrutSize( Q::Segment | A::Horizontal, segmentStrutSize );
|
setStrutSize( Q::Segment | A::Horizontal, segmentStrutSize );
|
||||||
setStrutSize( Q::Segment | A::Vertical, segmentStrutSize.transposed() );
|
setStrutSize( Q::Segment | A::Vertical, segmentStrutSize.transposed() );
|
||||||
setGradient( Q::Segment, Qt::transparent );
|
|
||||||
setGradient( Q::Segment | Q::Hovered, m_pal.onSurface12,
|
setBoxBorderMetrics( Q::Segment | A::Horizontal, { 0, 1_dp, 0, 1_dp } );
|
||||||
{ QskStateCombination::CombinationNoState, Q::Minimum | Q::Maximum | Q::Selected } );
|
setBoxBorderMetrics( Q::Segment | Q::Minimum | A::Horizontal, { 1_dp, 1_dp, 0, 1_dp } );
|
||||||
|
setBoxBorderMetrics( Q::Segment | Q::Maximum | A::Horizontal, { 0, 1_dp, 1_dp, 1_dp } );
|
||||||
|
|
||||||
|
setBoxBorderMetrics( Q::Segment | A::Vertical, { 1_dp, 0, 1_dp, 0 } );
|
||||||
|
setBoxBorderMetrics( Q::Segment | Q::Minimum | A::Vertical, { 1_dp, 1_dp, 1_dp, 0 } );
|
||||||
|
setBoxBorderMetrics( Q::Segment | Q::Maximum | A::Vertical, { 1_dp, 0, 1_dp, 1_dp } );
|
||||||
|
|
||||||
|
setBoxBorderColors( Q::Segment, Qt::transparent );
|
||||||
|
|
||||||
|
setGradient( Q::Segment | Q::Hovered, m_pal.onSurface8,
|
||||||
|
{ QskStateCombination::CombinationNoState, Q::Minimum | Q::Maximum } );
|
||||||
|
|
||||||
|
setGradient( Q::Segment | Q::Focused, m_pal.onSurface12,
|
||||||
|
{ QskStateCombination::CombinationNoState, Q::Minimum | Q::Maximum } );
|
||||||
|
|
||||||
|
setGradient( Q::Segment | Q::Selected, m_pal.secondaryContainer,
|
||||||
|
{ QskStateCombination::CombinationNoState, Q::Minimum | Q::Maximum } );
|
||||||
|
setGradient( Q::Segment | Q::Selected | Q::Hovered,
|
||||||
|
flattenedColor( m_pal.onSurface, m_pal.secondaryContainer, m_pal.hoverOpacity ),
|
||||||
|
{ QskStateCombination::CombinationNoState, Q::Minimum | Q::Maximum } );
|
||||||
|
setGradient( Q::Segment | Q::Selected | Q::Focused,
|
||||||
|
flattenedColor( m_pal.onSurface, m_pal.secondaryContainer, m_pal.focusOpacity ),
|
||||||
|
{ QskStateCombination::CombinationNoState, Q::Minimum | Q::Maximum } );
|
||||||
|
|
||||||
|
setGradient( Q::Segment | Q::Selected | Q::Disabled, m_pal.onSurface12,
|
||||||
|
{ QskStateCombination::CombinationNoState, Q::Minimum | Q::Maximum } );
|
||||||
|
|
||||||
setPadding( Q::Segment | A::Horizontal, 12_dp, 0, 12_dp, 0 );
|
setPadding( Q::Segment | A::Horizontal, 12_dp, 0, 12_dp, 0 );
|
||||||
setPadding( Q::Segment | A::Vertical, 0, 12_dp, 0, 12_dp );
|
setPadding( Q::Segment | A::Vertical, 0, 12_dp, 0, 12_dp );
|
||||||
|
|
||||||
setBoxShape( Q::Segment, 0 );
|
setBoxShape( Q::Segment, 0 );
|
||||||
|
|
||||||
setBoxShape( Q::Segment | Q::Minimum | A::Horizontal,
|
setBoxShape( Q::Segment | Q::Minimum | A::Horizontal,
|
||||||
{ 100, 0, 100, 0, Qt::RelativeSize },
|
{ 100, 0, 100, 0, Qt::RelativeSize },
|
||||||
{ QskStateCombination::CombinationNoState, Q::Disabled } );
|
{ QskStateCombination::CombinationNoState, Q::Disabled } );
|
||||||
|
@ -561,34 +588,6 @@ void Editor::setupSegmentedBar()
|
||||||
setColor( Q::Separator | Q::Disabled, m_pal.onSurface12 );
|
setColor( Q::Separator | Q::Disabled, m_pal.onSurface12 );
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
// Cursor
|
|
||||||
setBoxShape( Q::Cursor, 0 );
|
|
||||||
|
|
||||||
setBoxShape( Q::Cursor | Q::Minimum | A::Horizontal,
|
|
||||||
{ 100, 0, 100, 0, Qt::RelativeSize },
|
|
||||||
{ QskStateCombination::CombinationNoState, Q::Disabled } );
|
|
||||||
|
|
||||||
setBoxShape( Q::Cursor | Q::Maximum | A::Horizontal,
|
|
||||||
{ 0, 100, 0, 100, Qt::RelativeSize },
|
|
||||||
{ QskStateCombination::CombinationNoState, Q::Disabled } );
|
|
||||||
|
|
||||||
setBoxShape( Q::Cursor | Q::Minimum | A::Vertical,
|
|
||||||
{ 100, 100, 0, 0, Qt::RelativeSize },
|
|
||||||
{ QskStateCombination::CombinationNoState, Q::Disabled } );
|
|
||||||
|
|
||||||
setBoxShape( Q::Cursor | Q::Maximum | A::Vertical,
|
|
||||||
{ 0, 0, 100, 100, Qt::RelativeSize },
|
|
||||||
{ QskStateCombination::CombinationNoState, Q::Disabled } );
|
|
||||||
|
|
||||||
setGradient( Q::Cursor, m_pal.secondaryContainer );
|
|
||||||
setGradient( Q::Cursor | Q::Disabled, m_pal.onSurface12 );
|
|
||||||
setGradient( Q::Cursor | Q::Hovered, stateLayerColor( m_pal.onSurface, m_pal.hoverOpacity ) );
|
|
||||||
|
|
||||||
setBoxBorderMetrics( Q::Cursor, 1_dp );
|
|
||||||
setBoxBorderColors( Q::Cursor, Qt::transparent );
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
// Splash
|
// Splash
|
||||||
setBoxShape( Q::Splash, 20_dp );
|
setBoxShape( Q::Splash, 20_dp );
|
||||||
|
|
|
@ -111,7 +111,7 @@ class QSK_EXPORT QskAspect
|
||||||
NoState = 0,
|
NoState = 0,
|
||||||
|
|
||||||
FirstSystemState = 1 << 0,
|
FirstSystemState = 1 << 0,
|
||||||
FirstUserState = 1 << 4,
|
FirstUserState = 1 << 5,
|
||||||
LastUserState = 1 << 11,
|
LastUserState = 1 << 11,
|
||||||
LastSystemState = 1 << 15,
|
LastSystemState = 1 << 15,
|
||||||
|
|
||||||
|
|
|
@ -24,10 +24,10 @@ QSK_SUBCONTROL( QskSegmentedBar, Cursor )
|
||||||
QSK_SUBCONTROL( QskSegmentedBar, Text )
|
QSK_SUBCONTROL( QskSegmentedBar, Text )
|
||||||
QSK_SUBCONTROL( QskSegmentedBar, Icon )
|
QSK_SUBCONTROL( QskSegmentedBar, Icon )
|
||||||
|
|
||||||
QSK_SYSTEM_STATE( QskSegmentedBar, Selected, QskAspect::FirstSystemState )
|
QSK_SYSTEM_STATE( QskSegmentedBar, Minimum, QskAspect::FirstSystemState << 1 )
|
||||||
QSK_SYSTEM_STATE( QskSegmentedBar, Pressed, QskAspect::FirstSystemState << 1 )
|
QSK_SYSTEM_STATE( QskSegmentedBar, Maximum, QskAspect::FirstSystemState << 2 )
|
||||||
QSK_SYSTEM_STATE( QskSegmentedBar, Minimum, QskAspect::FirstSystemState << 2 )
|
QSK_SYSTEM_STATE( QskSegmentedBar, Selected, QskAspect::FirstSystemState << 3 )
|
||||||
QSK_SYSTEM_STATE( QskSegmentedBar, Maximum, QskAspect::FirstSystemState << 3 )
|
QSK_SYSTEM_STATE( QskSegmentedBar, Pressed, QskAspect::FirstSystemState << 4 )
|
||||||
|
|
||||||
class QskSegmentedBar::PrivateData
|
class QskSegmentedBar::PrivateData
|
||||||
{
|
{
|
||||||
|
@ -42,6 +42,7 @@ class QskSegmentedBar::PrivateData
|
||||||
|
|
||||||
int selectedIndex = -1;
|
int selectedIndex = -1;
|
||||||
int currentIndex = -1;
|
int currentIndex = -1;
|
||||||
|
int focusedIndex = -1;
|
||||||
|
|
||||||
Qt::Orientation orientation;
|
Qt::Orientation orientation;
|
||||||
bool isPressed = false;
|
bool isPressed = false;
|
||||||
|
@ -166,7 +167,10 @@ void QskSegmentedBar::mousePressEvent( QMouseEvent* event )
|
||||||
if( !QGuiApplication::styleHints()->setFocusOnTouchRelease() )
|
if( !QGuiApplication::styleHints()->setFocusOnTouchRelease() )
|
||||||
{
|
{
|
||||||
if( index != m_data->currentIndex )
|
if( index != m_data->currentIndex )
|
||||||
|
{
|
||||||
setCurrentIndex( index );
|
setCurrentIndex( index );
|
||||||
|
setFocusedIndex( index );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,11 +230,12 @@ void QskSegmentedBar::keyPressEvent( QKeyEvent* event )
|
||||||
else
|
else
|
||||||
forwards = ( event->key() == Qt::Key_Right );
|
forwards = ( event->key() == Qt::Key_Right );
|
||||||
|
|
||||||
const int index = nextIndex( m_data->selectedIndex, forwards );
|
const int index = nextIndex( m_data->focusedIndex, forwards );
|
||||||
if ( index != m_data->selectedIndex )
|
|
||||||
|
if ( index != m_data->focusedIndex )
|
||||||
{
|
{
|
||||||
if ( index >= 0 && index < count() )
|
if ( index >= 0 && index < count() )
|
||||||
setSelectedIndex( index );
|
setFocusedIndex( index );
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -238,9 +243,11 @@ void QskSegmentedBar::keyPressEvent( QKeyEvent* event )
|
||||||
|
|
||||||
case Qt::Key_Select:
|
case Qt::Key_Select:
|
||||||
case Qt::Key_Space:
|
case Qt::Key_Space:
|
||||||
|
{
|
||||||
|
setCurrentIndex( m_data->focusedIndex );
|
||||||
// stop further processing
|
// stop further processing
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
@ -248,10 +255,10 @@ void QskSegmentedBar::keyPressEvent( QKeyEvent* event )
|
||||||
|
|
||||||
if( steps != 0 )
|
if( steps != 0 )
|
||||||
{
|
{
|
||||||
const int index = nextIndex( m_data->currentIndex, steps > 0 );
|
const int index = nextIndex( m_data->focusedIndex, steps > 0 );
|
||||||
|
|
||||||
if( index != m_data->currentIndex )
|
if( index != m_data->focusedIndex )
|
||||||
setCurrentIndex( index );
|
setFocusedIndex( index );
|
||||||
|
|
||||||
if( index >= 0 )
|
if( index >= 0 )
|
||||||
return;
|
return;
|
||||||
|
@ -279,7 +286,7 @@ void QskSegmentedBar::hoverEnterEvent( QHoverEvent* event )
|
||||||
{
|
{
|
||||||
using A = QskAspect;
|
using A = QskAspect;
|
||||||
|
|
||||||
setSkinHint( Segment | A::Metric | A::Position, qskHoverPosition( event ) );
|
setSkinHint( Segment | Hovered | A::Metric | A::Position, qskHoverPosition( event ) );
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,21 +294,21 @@ void QskSegmentedBar::hoverMoveEvent( QHoverEvent* event )
|
||||||
{
|
{
|
||||||
using A = QskAspect;
|
using A = QskAspect;
|
||||||
|
|
||||||
setSkinHint( Segment | A::Metric | A::Position, qskHoverPosition( event ) );
|
setSkinHint( Segment | Hovered | A::Metric | A::Position, qskHoverPosition( event ) );
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskSegmentedBar::hoverLeaveEvent( QHoverEvent* event )
|
void QskSegmentedBar::hoverLeaveEvent( QHoverEvent* )
|
||||||
{
|
{
|
||||||
using A = QskAspect;
|
using A = QskAspect;
|
||||||
|
|
||||||
setSkinHint( Segment | A::Metric | A::Position, QPointF() );
|
setSkinHint( Segment | Hovered | A::Metric | A::Position, QPointF() );
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskSegmentedBar::focusInEvent( QFocusEvent* event )
|
void QskSegmentedBar::focusInEvent( QFocusEvent* event )
|
||||||
{
|
{
|
||||||
int index = m_data->currentIndex;
|
int index = m_data->focusedIndex;
|
||||||
|
|
||||||
switch( event->reason() )
|
switch( event->reason() )
|
||||||
{
|
{
|
||||||
|
@ -324,12 +331,20 @@ void QskSegmentedBar::focusInEvent( QFocusEvent* event )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( index != m_data->currentIndex )
|
if( index != m_data->focusedIndex )
|
||||||
setCurrentIndex( index );
|
setFocusedIndex( index );
|
||||||
|
|
||||||
Inherited::focusInEvent( event );
|
Inherited::focusInEvent( event );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QskSegmentedBar::focusOutEvent( QFocusEvent* event )
|
||||||
|
{
|
||||||
|
setFocusedIndex( -1 );
|
||||||
|
update();
|
||||||
|
|
||||||
|
Inherited::focusOutEvent( event );
|
||||||
|
}
|
||||||
|
|
||||||
void QskSegmentedBar::clear()
|
void QskSegmentedBar::clear()
|
||||||
{
|
{
|
||||||
if( count() == 0 )
|
if( count() == 0 )
|
||||||
|
@ -495,4 +510,17 @@ QRectF QskSegmentedBar::focusIndicatorRect() const
|
||||||
return Inherited::focusIndicatorRect();
|
return Inherited::focusIndicatorRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QskSegmentedBar::setFocusedIndex( int index )
|
||||||
|
{
|
||||||
|
if ( m_data->focusedIndex == index )
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_data->focusedIndex = index;
|
||||||
|
setPositionHint( Segment | Focused, index );
|
||||||
|
|
||||||
|
update();
|
||||||
|
|
||||||
|
Q_EMIT focusIndicatorRectChanged();
|
||||||
|
}
|
||||||
|
|
||||||
#include "moc_QskSegmentedBar.cpp"
|
#include "moc_QskSegmentedBar.cpp"
|
||||||
|
|
|
@ -99,9 +99,11 @@ class QSK_EXPORT QskSegmentedBar : public QskControl
|
||||||
void hoverLeaveEvent( QHoverEvent* ) override;
|
void hoverLeaveEvent( QHoverEvent* ) override;
|
||||||
|
|
||||||
void focusInEvent( QFocusEvent* ) override;
|
void focusInEvent( QFocusEvent* ) override;
|
||||||
|
void focusOutEvent( QFocusEvent* ) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int nextIndex( int index, bool forward ) const;
|
int nextIndex( int index, bool forward ) const;
|
||||||
|
void setFocusedIndex( int );
|
||||||
|
|
||||||
class PrivateData;
|
class PrivateData;
|
||||||
std::unique_ptr< PrivateData > m_data;
|
std::unique_ptr< PrivateData > m_data;
|
||||||
|
|
|
@ -196,7 +196,7 @@ QRectF QskSegmentedBarSkinlet::separatorRect(
|
||||||
|
|
||||||
if( bar->orientation() == Qt::Horizontal )
|
if( bar->orientation() == Qt::Horizontal )
|
||||||
{
|
{
|
||||||
rect.setLeft( rect.right() ); // ### *0.5 or so?
|
rect.setLeft( rect.right() );
|
||||||
rect.setSize( { strutSize.width(), sh.height() } );
|
rect.setSize( { strutSize.width(), sh.height() } );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -361,9 +361,19 @@ QskAspect::States QskSegmentedBarSkinlet::sampleStates(
|
||||||
|
|
||||||
const auto* bar = static_cast< const QskSegmentedBar* >( skinnable );
|
const auto* bar = static_cast< const QskSegmentedBar* >( skinnable );
|
||||||
|
|
||||||
if ( subControl == Q::Segment )
|
if ( subControl == Q::Segment || subControl == Q::Cursor )
|
||||||
{
|
{
|
||||||
const auto cursorPos = bar->effectiveSkinHint( Q::Segment | A::Metric | A::Position ).toPointF();
|
if ( bar->isSegmentEnabled( index ) )
|
||||||
|
{
|
||||||
|
if ( bar->selectedIndex() == index )
|
||||||
|
states |= Q::Selected;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
states |= Q::Disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto cursorPos = bar->effectiveSkinHint( Q::Segment | Q::Hovered | A::Metric | A::Position ).toPointF();
|
||||||
|
|
||||||
if( !cursorPos.isNull() && bar->indexAtPosition( cursorPos ) == index )
|
if( !cursorPos.isNull() && bar->indexAtPosition( cursorPos ) == index )
|
||||||
{
|
{
|
||||||
|
@ -374,6 +384,20 @@ QskAspect::States QskSegmentedBarSkinlet::sampleStates(
|
||||||
states &= ~Q::Hovered;
|
states &= ~Q::Hovered;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto focusIndex = bar->positionHint( Q::Segment | Q::Focused );
|
||||||
|
|
||||||
|
if( focusIndex >= 0 && focusIndex < bar->count() )
|
||||||
|
{
|
||||||
|
if( focusIndex == index )
|
||||||
|
{
|
||||||
|
states |= Q::Focused;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
states &= ~Q::Focused;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if( bar->count() > 0 )
|
if( bar->count() > 0 )
|
||||||
{
|
{
|
||||||
if( index == 0 )
|
if( index == 0 )
|
||||||
|
@ -393,7 +417,7 @@ QskAspect::States QskSegmentedBarSkinlet::sampleStates(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( subControl == Q::Icon || subControl == Q::Text || subControl == Q::Cursor )
|
else if( subControl == Q::Icon || subControl == Q::Text )
|
||||||
{
|
{
|
||||||
if ( bar->isSegmentEnabled( index ) )
|
if ( bar->isSegmentEnabled( index ) )
|
||||||
{
|
{
|
||||||
|
@ -418,7 +442,7 @@ QSGNode* QskSegmentedBarSkinlet::updateSampleNode( const QskSkinnable* skinnable
|
||||||
|
|
||||||
const auto rect = sampleRect( bar, bar->contentsRect(), subControl, index );
|
const auto rect = sampleRect( bar, bar->contentsRect(), subControl, index );
|
||||||
|
|
||||||
if ( subControl == Q::Segment || subControl == Q::Separator )
|
if ( subControl == Q::Segment || subControl == Q::Separator || subControl == Q::Cursor )
|
||||||
{
|
{
|
||||||
return updateBoxNode( skinnable, node, rect, subControl );
|
return updateBoxNode( skinnable, node, rect, subControl );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue