input panel formatting

This commit is contained in:
Peter Hartmann 2018-03-14 17:30:35 +01:00
parent 2f2d5cf122
commit 2e3834acf9
2 changed files with 193 additions and 124 deletions

View File

@ -38,7 +38,9 @@ namespace
QskInputPanel::KeyData* qskKeyDataAt( KeyTable& table, qreal x, qreal y ) QskInputPanel::KeyData* qskKeyDataAt( KeyTable& table, qreal x, qreal y )
{ {
if( x < 0 || x > 1 || y < 0 || y > 1 ) if( x < 0 || x > 1 || y < 0 || y > 1 )
{
return nullptr; return nullptr;
}
auto rowIndex = size_t( std::floor( y * QskInputPanel::RowCount ) ); auto rowIndex = size_t( std::floor( y * QskInputPanel::RowCount ) );
auto columnIndex = size_t( std::floor( x * QskInputPanel::KeyCount ) ); auto columnIndex = size_t( std::floor( x * QskInputPanel::KeyCount ) );
@ -46,14 +48,19 @@ namespace
Q_FOREVER Q_FOREVER
{ {
const auto rect = table.data[ rowIndex ][ columnIndex ].rect; const auto rect = table.data[ rowIndex ][ columnIndex ].rect;
if( rect.contains( x, y ) ) if( rect.contains( x, y ) )
{
return &table.data[ rowIndex ][ columnIndex ]; return &table.data[ rowIndex ][ columnIndex ];
}
// Look up/down // Look up/down
if( y < rect.top() ) if( y < rect.top() )
{ {
if( rowIndex == 0 ) if( rowIndex == 0 )
{
break; break;
}
rowIndex -= 1; rowIndex -= 1;
continue; continue;
@ -61,7 +68,9 @@ namespace
else if( y > rect.bottom() ) else if( y > rect.bottom() )
{ {
if( rowIndex == QskInputPanel::RowCount - 1 ) if( rowIndex == QskInputPanel::RowCount - 1 )
{
break; break;
}
rowIndex += 1; rowIndex += 1;
continue; continue;
@ -71,7 +80,9 @@ namespace
if( x < rect.left() ) if( x < rect.left() )
{ {
if( columnIndex == 0 ) if( columnIndex == 0 )
{
break; break;
}
columnIndex -= 1; columnIndex -= 1;
continue; continue;
@ -79,7 +90,9 @@ namespace
else if( x > rect.right() ) else if( x > rect.right() )
{ {
if( columnIndex == QskInputPanel::KeyCount - 1 ) if( columnIndex == QskInputPanel::KeyCount - 1 )
{
break; break;
}
columnIndex += 1; columnIndex += 1;
continue; continue;
@ -171,13 +184,17 @@ static qreal qskRowStretch( const QskInputPanel::KeyRow& keyRow )
for( const auto& key : keyRow ) for( const auto& key : keyRow )
{ {
if( !key ) if( !key )
{
continue; continue;
}
stretch += qskKeyStretch( key ); stretch += qskKeyStretch( key );
} }
if( stretch == 0.0 ) if( stretch == 0.0 )
{
stretch = QskInputPanel::KeyCount; stretch = QskInputPanel::KeyCount;
}
return stretch; return stretch;
} }
@ -407,13 +424,17 @@ void QskInputPanel::setPreeditGroups( const QVector< Qt::Key >& groups )
selectGroup( -1 ); selectGroup( -1 );
if( m_data->mode == LowercaseMode ) if( m_data->mode == LowercaseMode )
{
update(); update();
} }
}
void QskInputPanel::setPreeditCandidates( const QVector< Qt::Key >& candidates ) void QskInputPanel::setPreeditCandidates( const QVector< Qt::Key >& candidates )
{ {
if( m_data->candidates == candidates ) if( m_data->candidates == candidates )
{
return; return;
}
m_data->candidates = candidates; m_data->candidates = candidates;
setCandidateOffset( 0 ); setCandidateOffset( 0 );
@ -429,6 +450,7 @@ bool QskInputPanel::advanceFocus( bool forward )
Q_FOREVER Q_FOREVER
{ {
focusKeyIndex += offset; focusKeyIndex += offset;
if( focusKeyIndex < 0 || focusKeyIndex >= RowCount * KeyCount ) if( focusKeyIndex < 0 || focusKeyIndex >= RowCount * KeyCount )
{ {
clearFocusKey(); clearFocusKey();
@ -436,12 +458,17 @@ bool QskInputPanel::advanceFocus( bool forward )
} }
const auto key = keyDataAt( focusKeyIndex ).key; const auto key = keyDataAt( focusKeyIndex ).key;
if( key && key != Qt::Key_unknown ) if( key && key != Qt::Key_unknown )
{
break; break;
} }
}
if( m_data->focusKeyIndex >= 0 ) if( m_data->focusKeyIndex >= 0 )
{
keyDataAt( m_data->focusKeyIndex ).key &= ~KeyFocused; keyDataAt( m_data->focusKeyIndex ).key &= ~KeyFocused;
}
m_data->focusKeyIndex = focusKeyIndex; m_data->focusKeyIndex = focusKeyIndex;
keyDataAt( m_data->focusKeyIndex ).key |= KeyFocused; keyDataAt( m_data->focusKeyIndex ).key |= KeyFocused;
@ -456,9 +483,13 @@ bool QskInputPanel::activateFocusKey()
auto& keyData = keyDataAt( m_data->focusKeyIndex ); auto& keyData = keyDataAt( m_data->focusKeyIndex );
if( keyData.key & KeyPressed ) if( keyData.key & KeyPressed )
{
handleKey( m_data->focusKeyIndex ); handleKey( m_data->focusKeyIndex );
}
else else
{
keyData.key |= KeyPressed; keyData.key |= KeyPressed;
}
update(); update();
return true; return true;
@ -472,6 +503,7 @@ bool QskInputPanel::deactivateFocusKey()
if( m_data->focusKeyIndex > 0 && m_data->focusKeyIndex < RowCount * KeyCount ) if( m_data->focusKeyIndex > 0 && m_data->focusKeyIndex < RowCount * KeyCount )
{ {
auto& keyData = keyDataAt( m_data->focusKeyIndex ); auto& keyData = keyDataAt( m_data->focusKeyIndex );
if( keyData.key & KeyPressed ) if( keyData.key & KeyPressed )
{ {
keyData.key &= ~KeyPressed; keyData.key &= ~KeyPressed;
@ -513,12 +545,18 @@ void QskInputPanel::setCandidateOffset( int candidateOffset )
auto& keyData = topRow[ i + groupCount ]; auto& keyData = topRow[ i + groupCount ];
if( continueLeft && i == 0 ) if( continueLeft && i == 0 )
{
keyData.key = Qt::Key_ApplicationLeft; keyData.key = Qt::Key_ApplicationLeft;
}
else if( continueRight && ( i == KeyCount - groupCount - 1 ) ) else if( continueRight && ( i == KeyCount - groupCount - 1 ) )
{
keyData.key = Qt::Key_ApplicationRight; keyData.key = Qt::Key_ApplicationRight;
}
else else
{
keyData.key = m_data->candidates.at( i + m_data->candidateOffset ); keyData.key = m_data->candidates.at( i + m_data->candidateOffset );
} }
}
for( int i = count; i < KeyCount - groupCount; ++i ) for( int i = count; i < KeyCount - groupCount; ++i )
{ {
@ -527,15 +565,19 @@ void QskInputPanel::setCandidateOffset( int candidateOffset )
} }
if( m_data->mode == LowercaseMode ) if( m_data->mode == LowercaseMode )
{
update(); update();
} }
}
QRectF QskInputPanel::keyboardRect() const QRectF QskInputPanel::keyboardRect() const
{ {
auto keyboardRect = rect(); // ### margins? would eliminate this thing below auto keyboardRect = rect(); // ### margins? would eliminate this thing below
if( QskDialog::instance()->policy() != QskDialog::TopLevelWindow ) if( QskDialog::instance()->policy() != QskDialog::TopLevelWindow )
{
keyboardRect.adjust( 0, keyboardRect.height() * 0.5, 0, 0 ); keyboardRect.adjust( 0, keyboardRect.height() * 0.5, 0, 0 );
}
return keyboardRect; return keyboardRect;
} }
@ -598,13 +640,16 @@ void QskInputPanel::touchEvent( QTouchEvent* e )
if( e->type() == QEvent::TouchCancel ) if( e->type() == QEvent::TouchCancel )
{ {
for( auto& it : m_data->activeKeys ) for( auto& it : m_data->activeKeys )
{
keyDataAt( it.second.keyIndex ).key &= ~KeyPressed; keyDataAt( it.second.keyIndex ).key &= ~KeyPressed;
}
m_data->activeKeys.clear(); m_data->activeKeys.clear();
return; return;
} }
const auto rect = keyboardRect(); const auto rect = keyboardRect();
for( const auto& tp : e->touchPoints() ) for( const auto& tp : e->touchPoints() )
{ {
const auto pos = tp.pos(); const auto pos = tp.pos();
@ -613,11 +658,15 @@ void QskInputPanel::touchEvent( QTouchEvent* e )
const auto y = ( pos.y() - rect.y() ) / rect.height(); const auto y = ( pos.y() - rect.y() ) / rect.height();
auto keyData = qskKeyDataAt( m_data->keyTable[ m_data->mode ], x, y ); auto keyData = qskKeyDataAt( m_data->keyTable[ m_data->mode ], x, y );
if( !keyData || ( !keyData->key || keyData->key == Qt::Key_unknown ) ) if( !keyData || ( !keyData->key || keyData->key == Qt::Key_unknown ) )
{ {
auto it = m_data->activeKeys.find( tp.id() ); auto it = m_data->activeKeys.find( tp.id() );
if( it == m_data->activeKeys.cend() ) if( it == m_data->activeKeys.cend() )
{
continue; continue;
}
keyDataAt( it->second.keyIndex ).key &= ~KeyPressed; keyDataAt( it->second.keyIndex ).key &= ~KeyPressed;
m_data->activeKeys.erase( it ); m_data->activeKeys.erase( it );
@ -636,7 +685,9 @@ void QskInputPanel::touchEvent( QTouchEvent* e )
m_data->activeKeys.erase( it ); m_data->activeKeys.erase( it );
if( repeatCount < 0 ) if( repeatCount < 0 )
{
continue; // Don't compose an accepted held key continue; // Don't compose an accepted held key
}
handleKey( keyIndex ); handleKey( keyIndex );
continue; continue;
@ -702,6 +753,7 @@ void QskInputPanel::timerEvent( QTimerEvent* e )
compose( key & ~KeyStates ); compose( key & ~KeyStates );
} }
} }
++it; ++it;
} }
} }
@ -733,12 +785,19 @@ void QskInputPanel::handleKey( int keyIndex )
} }
const auto groupCount = m_data->groups.length(); const auto groupCount = m_data->groups.length();
if( column < groupCount ) if( column < groupCount )
{
selectGroup( column ); selectGroup( column );
}
else if( column < KeyCount ) else if( column < KeyCount )
{
selectCandidate( column - groupCount + m_data->candidateOffset ); selectCandidate( column - groupCount + m_data->candidateOffset );
}
else else
{
Q_UNREACHABLE(); // Handle the final key... Q_UNREACHABLE(); // Handle the final key...
}
return; return;
} }
@ -779,18 +838,25 @@ void QskInputPanel::compose( Qt::Key key )
void QskInputPanel::selectGroup( int index ) void QskInputPanel::selectGroup( int index )
{ {
auto& topRow = m_data->keyTable[ m_data->mode ].data[ 0 ]; auto& topRow = m_data->keyTable[ m_data->mode ].data[ 0 ];
if( m_data->selectedGroup >= 0 ) if( m_data->selectedGroup >= 0 )
{
topRow[ m_data->selectedGroup ].key &= ~KeyLocked; topRow[ m_data->selectedGroup ].key &= ~KeyLocked;
}
if( m_data->selectedGroup == index ) if( m_data->selectedGroup == index )
{
index = -1; // clear selection index = -1; // clear selection
}
m_data->selectedGroup = index; m_data->selectedGroup = index;
QGuiApplication::inputMethod()->invokeAction( QGuiApplication::inputMethod()->invokeAction(
static_cast< QInputMethod::Action >( SelectGroup ), m_data->selectedGroup + 1 ); static_cast< QInputMethod::Action >( SelectGroup ), m_data->selectedGroup + 1 );
if( m_data->selectedGroup < 0 ) if( m_data->selectedGroup < 0 )
{
return; return;
}
topRow[ m_data->selectedGroup ].key |= KeyLocked; topRow[ m_data->selectedGroup ].key |= KeyLocked;
} }
@ -835,12 +901,15 @@ void QskInputPanel::updateLocale( const QLocale& locale )
case QLocale::UnitedStatesVirginIslands: case QLocale::UnitedStatesVirginIslands:
m_data->currentLayout = &qskInputPanelLayouts.en_US; m_data->currentLayout = &qskInputPanelLayouts.en_US;
break; break;
default: default:
m_data->currentLayout = &qskInputPanelLayouts.en_GB; m_data->currentLayout = &qskInputPanelLayouts.en_GB;
break; break;
} }
break; break;
} }
case QLocale::Spanish: case QLocale::Spanish:
m_data->currentLayout = &qskInputPanelLayouts.es; m_data->currentLayout = &qskInputPanelLayouts.es;
break; break;