QskTextField wip
This commit is contained in:
parent
04fbb2a2a1
commit
edad453505
|
@ -7,15 +7,10 @@ list(APPEND HEADERS
|
||||||
QskFluent2Global.h QskFluent2Theme.h QskFluent2SkinFactory.h
|
QskFluent2Global.h QskFluent2Theme.h QskFluent2SkinFactory.h
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND PRIVATE_HEADERS
|
|
||||||
QskFluent2TextFieldSkinlet.h
|
|
||||||
)
|
|
||||||
|
|
||||||
list(APPEND SOURCES
|
list(APPEND SOURCES
|
||||||
QskFluent2Theme.cpp
|
QskFluent2Theme.cpp
|
||||||
QskFluent2Skin.cpp
|
QskFluent2Skin.cpp
|
||||||
QskFluent2SkinFactory.cpp
|
QskFluent2SkinFactory.cpp
|
||||||
QskFluent2TextFieldSkinlet.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
qt_add_resources(SOURCES QskFluent2Icons.qrc)
|
qt_add_resources(SOURCES QskFluent2Icons.qrc)
|
||||||
|
|
|
@ -47,7 +47,6 @@
|
||||||
*/
|
*/
|
||||||
#include "QskFluent2Skin.h"
|
#include "QskFluent2Skin.h"
|
||||||
#include "QskFluent2Theme.h"
|
#include "QskFluent2Theme.h"
|
||||||
#include "QskFluent2TextFieldSkinlet.h"
|
|
||||||
|
|
||||||
#include <QskTextAreaSkinlet.h>
|
#include <QskTextAreaSkinlet.h>
|
||||||
#include <QskSkinHintTableEditor.h>
|
#include <QskSkinHintTableEditor.h>
|
||||||
|
@ -1854,11 +1853,13 @@ void Editor::setupTextAreaColors(
|
||||||
setBoxBorderGradient( panel, borderColor1, borderColor2, panelColor );
|
setBoxBorderGradient( panel, borderColor1, borderColor2, panelColor );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::setupTextFieldMetrics()
|
void Editor::setupTextFieldMetrics()
|
||||||
{
|
{
|
||||||
using Q = QskTextField;
|
using Q = QskTextField;
|
||||||
|
|
||||||
setFontRole( Q::Text, Fluent2::Body );
|
setFontRole( Q::Header, Fluent2::Body );
|
||||||
|
setFontRole( Q::Footer, Fluent2::Caption );
|
||||||
|
|
||||||
setStrutSize( Q::TextPanel, { -1, 30_px } );
|
setStrutSize( Q::TextPanel, { -1, 30_px } );
|
||||||
setPadding( Q::TextPanel, { 11_px, 0, 11_px, 0 } );
|
setPadding( Q::TextPanel, { 11_px, 0, 11_px, 0 } );
|
||||||
|
@ -1869,15 +1870,14 @@ void Editor::setupTextFieldMetrics()
|
||||||
|
|
||||||
setBoxShape( Q::TextPanel, 3_px );
|
setBoxShape( Q::TextPanel, 3_px );
|
||||||
|
|
||||||
setAlignment( Q::Placeholder, Qt::AlignLeft | Qt::AlignVCenter );
|
for ( const auto subControl : { Q::Text, Q::Placeholder } )
|
||||||
setFontRole( Q::Placeholder, fontRole( Q::Text ) );
|
{
|
||||||
|
setFontRole( subControl, Fluent2::Body );
|
||||||
setStrutSize( Q::Header, { -1, 30_px } );
|
setAlignment( subControl, Qt::AlignLeft | Qt::AlignVCenter );
|
||||||
setFontRole( Q::Header, Fluent2::Body );
|
}
|
||||||
|
|
||||||
setAlignment( Q::Text, Qt::AlignLeft | Qt::AlignVCenter );
|
|
||||||
setFontRole( Q::Text, Fluent2::Body );
|
|
||||||
|
|
||||||
|
//setStrutSize( Q::Header, { -1, 30_px } );
|
||||||
|
//setStrutSize( Q::Footer, { -1, 30_px } );
|
||||||
|
|
||||||
setSymbol( Q::Icon, symbol( "search" ) );
|
setSymbol( Q::Icon, symbol( "search" ) );
|
||||||
setSymbol( Q::Button, symbol( "dismiss" ) );
|
setSymbol( Q::Button, symbol( "dismiss" ) );
|
||||||
|
@ -2141,8 +2141,6 @@ void Editor::setupVirtualKeyboardColors(
|
||||||
QskFluent2Skin::QskFluent2Skin( QObject* parent )
|
QskFluent2Skin::QskFluent2Skin( QObject* parent )
|
||||||
: Inherited( parent )
|
: Inherited( parent )
|
||||||
{
|
{
|
||||||
declareSkinlet< QskTextField, QskFluent2TextFieldSkinlet >();
|
|
||||||
|
|
||||||
setupFonts();
|
setupFonts();
|
||||||
|
|
||||||
Editor editor( &hintTable() );
|
Editor editor( &hintTable() );
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
/******************************************************************************
|
|
||||||
* QSkinny - Copyright (C) The authors
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#include "QskFluent2TextFieldSkinlet.h"
|
|
||||||
#include "QskTextField.h"
|
|
||||||
|
|
||||||
using Q = QskTextField;
|
|
||||||
|
|
||||||
QskFluent2TextFieldSkinlet::QskFluent2TextFieldSkinlet( QskSkin* skin )
|
|
||||||
: Inherited( skin )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QskFluent2TextFieldSkinlet::~QskFluent2TextFieldSkinlet()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QRectF QskFluent2TextFieldSkinlet::subControlRect( const QskSkinnable* skinnable,
|
|
||||||
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
|
|
||||||
{
|
|
||||||
if ( subControl == Q::TextPanel )
|
|
||||||
{
|
|
||||||
auto rect = subControlRect( skinnable, contentsRect, Q::Panel );
|
|
||||||
rect.setY( rect.bottom() - skinnable->strutSizeHint( subControl ).height() );
|
|
||||||
|
|
||||||
return rect;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( subControl == Q::Header )
|
|
||||||
{
|
|
||||||
const auto rect = subControlRect( skinnable, contentsRect, Q::TextPanel );
|
|
||||||
const auto h = skinnable->effectiveFontHeight( Q::Header );
|
|
||||||
|
|
||||||
return QRectF( rect.x(), rect.y() - h, rect.width(), h );
|
|
||||||
}
|
|
||||||
|
|
||||||
return Inherited::subControlRect( skinnable, contentsRect, subControl );
|
|
||||||
}
|
|
||||||
|
|
||||||
QSizeF QskFluent2TextFieldSkinlet::sizeHint( const QskSkinnable* skinnable,
|
|
||||||
Qt::SizeHint which, const QSizeF& constraint ) const
|
|
||||||
{
|
|
||||||
if ( which != Qt::PreferredSize )
|
|
||||||
return QSizeF();
|
|
||||||
|
|
||||||
auto hint = Inherited::sizeHint( skinnable, which, constraint );
|
|
||||||
|
|
||||||
const auto textField = static_cast< const QskTextField* >( skinnable );
|
|
||||||
if ( !textField->headerText().isEmpty() )
|
|
||||||
{
|
|
||||||
// spacing ???
|
|
||||||
hint.rheight() += textField->strutSizeHint( Q::Header ).height();
|
|
||||||
}
|
|
||||||
|
|
||||||
return hint;
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "moc_QskFluent2TextFieldSkinlet.cpp"
|
|
|
@ -1,29 +0,0 @@
|
||||||
/******************************************************************************
|
|
||||||
* QSkinny - Copyright (C) The authors
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#ifndef QSK_FLUENT2_TEXTFIELD_SKINLET_H
|
|
||||||
#define QSK_FLUENT2_TEXTFIELD_SKINLET_H
|
|
||||||
|
|
||||||
#include "QskFluent2Global.h"
|
|
||||||
#include "QskTextFieldSkinlet.h"
|
|
||||||
|
|
||||||
class QSK_FLUENT2_EXPORT QskFluent2TextFieldSkinlet : public QskTextFieldSkinlet
|
|
||||||
{
|
|
||||||
Q_GADGET
|
|
||||||
|
|
||||||
using Inherited = QskTextFieldSkinlet;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Q_INVOKABLE QskFluent2TextFieldSkinlet( QskSkin* = nullptr );
|
|
||||||
~QskFluent2TextFieldSkinlet() override;
|
|
||||||
|
|
||||||
QRectF subControlRect( const QskSkinnable*,
|
|
||||||
const QRectF& rect, QskAspect::Subcontrol ) const override;
|
|
||||||
|
|
||||||
QSizeF sizeHint( const QskSkinnable*,
|
|
||||||
Qt::SizeHint, const QSizeF& ) const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -425,6 +425,9 @@ void Editor::setupTextField()
|
||||||
|
|
||||||
setBoxShape( Q::TextPanel, 2_px );
|
setBoxShape( Q::TextPanel, 2_px );
|
||||||
setPadding( Q::TextPanel, 4_px );
|
setPadding( Q::TextPanel, 4_px );
|
||||||
|
|
||||||
|
setFontRole( Q::Header, QskFontRole::Body );
|
||||||
|
setFontRole( Q::Footer, QskFontRole::Caption );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::setupTextArea()
|
void Editor::setupTextArea()
|
||||||
|
|
|
@ -489,66 +489,55 @@ void Editor::setupTextField()
|
||||||
const auto activeStates = Q::Focused | Q::Editing;
|
const auto activeStates = Q::Focused | Q::Editing;
|
||||||
|
|
||||||
{
|
{
|
||||||
// Text
|
// TextPanel
|
||||||
|
|
||||||
setAnimation( Q::TextPanel | A::Color, qskDuration );
|
setAnimation( Q::TextPanel | A::Color, qskDuration );
|
||||||
setAnimation( Q::TextPanel | A::Metric, qskDuration );
|
setAnimation( Q::TextPanel | A::Metric, qskDuration );
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( const auto variation : { A::NoVariation, Filled, Outlined } )
|
|
||||||
{
|
{
|
||||||
const auto Panel = Q::Panel | variation;
|
const auto aspect = Q::TextPanel | Filled;
|
||||||
|
|
||||||
QskBoxBorderMetrics borderMetrics[2];
|
setBoxBorderColors( aspect, m_pal.onSurfaceVariant );
|
||||||
|
setGradient( aspect, m_pal.surfaceVariant );
|
||||||
|
|
||||||
if ( variation == Filled )
|
setGradient( aspect | Q::Hovered,
|
||||||
{
|
m_pal.hoverColor( m_pal.onSurfaceVariant, m_pal.surfaceVariant ),
|
||||||
setBoxShape( Panel, m_pal.shapeExtraSmallTop );
|
{ QskStateCombination::CombinationNoState, activeStates | Q::Error } );
|
||||||
|
|
||||||
borderMetrics[0].setBottom( 1 );
|
setGradient( aspect | Q::Disabled,
|
||||||
borderMetrics[1].setBottom( 2 );
|
QskRgb::toTransparentF( m_pal.onSurface, 0.04 ) );
|
||||||
|
|
||||||
setBoxBorderColors( Panel, m_pal.onSurfaceVariant );
|
setBoxShape( aspect, m_pal.shapeExtraSmallTop );
|
||||||
|
setBoxBorderMetrics( aspect, { 0, 0, 0, 1 } );
|
||||||
setGradient( Panel, m_pal.surfaceVariant );
|
setBoxBorderMetrics( aspect, { 0, 0, 0, 2 }, activeStates | Q::Hovered );
|
||||||
|
setBoxBorderMetrics( aspect | Q::Error, { 0, 0, 0, 2 }, activeStates | Q::Hovered );
|
||||||
setGradient( Panel | Q::Hovered,
|
|
||||||
m_pal.hoverColor( m_pal.onSurfaceVariant, m_pal.surfaceVariant ),
|
|
||||||
{ QskStateCombination::CombinationNoState, activeStates | Q::Error } );
|
|
||||||
|
|
||||||
setGradient( Panel | Q::Disabled,
|
|
||||||
QskRgb::toTransparentF( m_pal.onSurface, 0.04 ) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
setBoxShape( Panel, m_pal.shapeExtraSmall );
|
|
||||||
|
|
||||||
borderMetrics[0].setWidths( 1 );
|
|
||||||
borderMetrics[1].setWidths( 2 );
|
|
||||||
|
|
||||||
setBoxBorderColors( Panel, m_pal.outline );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( variation != A::NoVariation )
|
|
||||||
{
|
|
||||||
setStrutSize( Panel, -1.0, 56_px );
|
|
||||||
setPadding( Panel, 16_px, 8_px, 16_px, 8_px );
|
|
||||||
}
|
|
||||||
|
|
||||||
setBoxBorderMetrics( Panel, borderMetrics[0] );
|
|
||||||
setBoxBorderMetrics( Panel, borderMetrics[1], activeStates | Q::Hovered );
|
|
||||||
setBoxBorderMetrics( Panel | Q::Error, borderMetrics[1], activeStates | Q::Hovered );
|
|
||||||
|
|
||||||
setBoxBorderColors( Panel, m_pal.primary, activeStates );
|
|
||||||
setBoxBorderColors( Panel | Q::Hovered, m_pal.primary, activeStates );
|
|
||||||
setBoxBorderColors( Panel | Q::Hovered, m_pal.onSurface );
|
|
||||||
setBoxBorderColors( Panel | Q::Disabled, m_pal.onSurface38 );
|
|
||||||
|
|
||||||
setBoxBorderColors( Panel | Q::Error, m_pal.error,
|
|
||||||
{ QskStateCombination::CombinationNoState, activeStates | Q::Hovered } );
|
|
||||||
|
|
||||||
setColor( Q::TextPanel | variation | Q::Selected, m_pal.primary12 );
|
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
const auto aspect = Q::TextPanel | Outlined;
|
||||||
|
|
||||||
|
setBoxBorderColors( aspect, m_pal.outline );
|
||||||
|
|
||||||
|
setBoxShape( aspect, m_pal.shapeExtraSmall );
|
||||||
|
setBoxBorderMetrics( aspect, 1 );
|
||||||
|
setBoxBorderMetrics( aspect, 2, activeStates | Q::Hovered );
|
||||||
|
setBoxBorderMetrics( aspect | Q::Error, 2, activeStates | Q::Hovered );
|
||||||
|
|
||||||
|
setGradient( aspect, QColor() );
|
||||||
|
}
|
||||||
|
|
||||||
|
setStrutSize( Q::TextPanel, -1.0, 56_px );
|
||||||
|
setPadding( Q::TextPanel, 16_px, 8_px, 16_px, 8_px );
|
||||||
|
|
||||||
|
setBoxBorderColors( Q::TextPanel, m_pal.primary, activeStates );
|
||||||
|
setBoxBorderColors( Q::TextPanel | Q::Hovered, m_pal.primary, activeStates );
|
||||||
|
setBoxBorderColors( Q::TextPanel | Q::Hovered, m_pal.onSurface );
|
||||||
|
setBoxBorderColors( Q::TextPanel | Q::Disabled, m_pal.onSurface38 );
|
||||||
|
|
||||||
|
setBoxBorderColors( Q::TextPanel | Q::Error, m_pal.error,
|
||||||
|
{ QskStateCombination::CombinationNoState, activeStates | Q::Hovered } );
|
||||||
|
|
||||||
|
setColor( Q::TextPanel | Q::Selected, m_pal.primary12 );
|
||||||
|
|
||||||
// Icon
|
// Icon
|
||||||
|
|
||||||
|
@ -561,39 +550,6 @@ void Editor::setupTextField()
|
||||||
|
|
||||||
setGraphicRole( Q::Icon | Q::Disabled, M3::GraphicRoleOnSurface38 );
|
setGraphicRole( Q::Icon | Q::Disabled, M3::GraphicRoleOnSurface38 );
|
||||||
|
|
||||||
{
|
|
||||||
setAlignment( Q::Header, Qt::AlignLeft | Qt::AlignVCenter );
|
|
||||||
setFontRole( Q::Header, BodySmall );
|
|
||||||
|
|
||||||
setColor( Q::Header, m_pal.onSurfaceVariant );
|
|
||||||
setColor( Q::Header, m_pal.primary, activeStates );
|
|
||||||
setColor( Q::Header | Q::Error, m_pal.error );
|
|
||||||
setColor( Q::Header | Q::Disabled, m_pal.onSurface38 );
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
setMargin( Q::Header | Outlined, 4_px, 0, 4_px, 0 );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for ( const auto subControl : { Q::Text, Q::Placeholder } )
|
|
||||||
{
|
|
||||||
setAlignment( subControl, Qt::AlignLeft | Qt::AlignVCenter );
|
|
||||||
|
|
||||||
setFontRole( subControl, BodyLarge );
|
|
||||||
|
|
||||||
setColor( subControl | Q::Disabled, m_pal.onSurface38 );
|
|
||||||
|
|
||||||
if ( subControl == Q::Text )
|
|
||||||
{
|
|
||||||
setColor( subControl, m_pal.onSurface );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
setColor( subControl | Q::Error, m_pal.error );
|
|
||||||
setColor( subControl | Q::Error | Q::Hovered, m_pal.onSurface );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Button
|
// Button
|
||||||
|
|
||||||
setStrutSize( Q::Button, { 24_px, 24_px } );
|
setStrutSize( Q::Button, { 24_px, 24_px } );
|
||||||
|
@ -613,24 +569,48 @@ void Editor::setupTextField()
|
||||||
setGradient( Q::ButtonPanel | Q::Hovered, m_pal.onSurface8 );
|
setGradient( Q::ButtonPanel | Q::Hovered, m_pal.onSurface8 );
|
||||||
setBoxShape( Q::ButtonPanel, 100, Qt::RelativeSize );
|
setBoxShape( Q::ButtonPanel, 100, Qt::RelativeSize );
|
||||||
|
|
||||||
|
// Header
|
||||||
|
|
||||||
// SupportingText
|
setAlignment( Q::Header, Qt::AlignLeft | Qt::AlignVCenter );
|
||||||
|
setFontRole( Q::Header, BodySmall );
|
||||||
|
|
||||||
|
setColor( Q::Header, m_pal.onSurfaceVariant );
|
||||||
|
setColor( Q::Header, m_pal.primary, activeStates );
|
||||||
|
setColor( Q::Header | Q::Error, m_pal.error );
|
||||||
|
setColor( Q::Header | Q::Disabled, m_pal.onSurface38 );
|
||||||
|
|
||||||
|
for ( const auto subControl : { Q::Text, Q::Placeholder } )
|
||||||
|
{
|
||||||
|
setAlignment( subControl, Qt::AlignLeft | Qt::AlignVCenter );
|
||||||
|
|
||||||
|
setFontRole( subControl, BodyLarge );
|
||||||
|
|
||||||
|
setColor( subControl | Q::Disabled, m_pal.onSurface38 );
|
||||||
|
|
||||||
|
if ( subControl == Q::Text )
|
||||||
|
{
|
||||||
|
setColor( subControl, m_pal.onSurface );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setColor( subControl | Q::Error, m_pal.error );
|
||||||
|
setColor( subControl | Q::Error | Q::Hovered, m_pal.onSurface );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Footer, CharacterCount
|
||||||
|
for ( const auto subControl : { Q::Footer, Q::CharacterCount } )
|
||||||
|
{
|
||||||
|
setMargin( subControl, { 16_px, 4_px, 16_px, 4_px } );
|
||||||
|
setFontRole( subControl, BodySmall );
|
||||||
|
|
||||||
|
setColor( subControl, m_pal.onSurfaceVariant );
|
||||||
|
setColor( subControl | Q::Error, m_pal.error );
|
||||||
|
setColor( subControl | Q::Disabled, m_pal.onSurface38 );
|
||||||
|
}
|
||||||
|
|
||||||
setMargin( Q::Footer, { 16_px, 4_px, 16_px, 4_px } );
|
|
||||||
setColor( Q::Footer, m_pal.onSurfaceVariant );
|
|
||||||
setColor( Q::Footer | Q::Error, m_pal.error );
|
|
||||||
setFontRole( Q::Footer, BodySmall );
|
|
||||||
setAlignment( Q::Footer, Qt::AlignLeft | Qt::AlignVCenter );
|
setAlignment( Q::Footer, Qt::AlignLeft | Qt::AlignVCenter );
|
||||||
|
|
||||||
setColor( Q::Footer | Q::Disabled, m_pal.onSurface38 );
|
|
||||||
|
|
||||||
// CharacterCount
|
|
||||||
|
|
||||||
setMargin( Q::CharacterCount, margin( Q::Footer ) );
|
|
||||||
setColor( Q::CharacterCount, color( Q::Footer ) );
|
|
||||||
setFontRole( Q::CharacterCount, fontRole( Q::Footer ) );
|
|
||||||
setAlignment( Q::CharacterCount, Qt::AlignRight | Qt::AlignVCenter );
|
setAlignment( Q::CharacterCount, Qt::AlignRight | Qt::AlignVCenter );
|
||||||
setColor( Q::CharacterCount | Q::Disabled, color( Q::Footer | Q::Disabled ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::setupProgressBar()
|
void Editor::setupProgressBar()
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
#include <QskTextField.h>
|
#include <QskTextField.h>
|
||||||
#include <QskBoxBorderColors.h>
|
#include <QskBoxBorderColors.h>
|
||||||
#include <QskBoxBorderMetrics.h>
|
#include <QskBoxHints.h>
|
||||||
#include <QskFunctions.h>
|
#include <QskFunctions.h>
|
||||||
|
|
||||||
#include <QFontMetricsF>
|
#include <QFontMetricsF>
|
||||||
|
@ -19,25 +19,12 @@ namespace
|
||||||
{
|
{
|
||||||
const int spacingV = 0; // skin hint !
|
const int spacingV = 0; // skin hint !
|
||||||
|
|
||||||
QString effectiveHeaderText( const QskTextField* textField )
|
|
||||||
{
|
|
||||||
if ( !textField->isEditing() && textField->text().isEmpty() )
|
|
||||||
return QString();
|
|
||||||
|
|
||||||
return textField->headerText();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool hasCharacterCount( const QskTextField* textField )
|
inline bool hasCharacterCount( const QskTextField* textField )
|
||||||
{
|
{
|
||||||
// magic number hardcoded in qquicktextinput.cpp
|
// magic number hardcoded in qquicktextinput.cpp
|
||||||
return textField->maxLength() < 32767;
|
return textField->maxLength() < 32767;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool hasBottomText( const QskTextField* textField )
|
|
||||||
{
|
|
||||||
return !textField->footerText().isEmpty() || hasCharacterCount( textField );
|
|
||||||
}
|
|
||||||
|
|
||||||
QString maxLengthString( const QskTextField* textField )
|
QString maxLengthString( const QskTextField* textField )
|
||||||
{
|
{
|
||||||
QString s = QString::number( textField->text().length() )
|
QString s = QString::number( textField->text().length() )
|
||||||
|
@ -79,7 +66,7 @@ namespace
|
||||||
QskMaterial3TextFieldSkinlet::QskMaterial3TextFieldSkinlet( QskSkin* skin )
|
QskMaterial3TextFieldSkinlet::QskMaterial3TextFieldSkinlet( QskSkin* skin )
|
||||||
: Inherited( skin )
|
: Inherited( skin )
|
||||||
{
|
{
|
||||||
appendNodeRoles( { SupportingTextRole, CharacterCountRole } );
|
appendNodeRoles( { CharacterCountRole } );
|
||||||
}
|
}
|
||||||
|
|
||||||
QskMaterial3TextFieldSkinlet::~QskMaterial3TextFieldSkinlet()
|
QskMaterial3TextFieldSkinlet::~QskMaterial3TextFieldSkinlet()
|
||||||
|
@ -91,92 +78,47 @@ QRectF QskMaterial3TextFieldSkinlet::subControlRect( const QskSkinnable* skinnab
|
||||||
{
|
{
|
||||||
const auto textField = static_cast< const Q* >( skinnable );
|
const auto textField = static_cast< const Q* >( skinnable );
|
||||||
|
|
||||||
if ( subControl == Q::Panel )
|
|
||||||
{
|
|
||||||
auto rect = contentsRect;
|
|
||||||
|
|
||||||
if( textField->style() == QskTextField::OutlinedStyle )
|
|
||||||
{
|
|
||||||
const auto h = textField->effectiveFontHeight( Q::Header );
|
|
||||||
rect.setTop( rect.top() + 0.5 * h );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( hasBottomText( textField ) )
|
|
||||||
{
|
|
||||||
const auto margins = textField->marginHint( Q::Footer );
|
|
||||||
|
|
||||||
const auto h = textField->effectiveFontHeight( Q::Footer )
|
|
||||||
+ margins.top() + margins.bottom();
|
|
||||||
|
|
||||||
rect.setHeight( rect.height() - h );
|
|
||||||
}
|
|
||||||
|
|
||||||
return rect;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( subControl == Q::Text )
|
|
||||||
{
|
|
||||||
auto rect = Inherited::subControlRect( skinnable, contentsRect, Q::Text );
|
|
||||||
|
|
||||||
if ( !rect.isEmpty() && ( textField->style() == QskTextField::FilledStyle ) )
|
|
||||||
{
|
|
||||||
const auto text = effectiveHeaderText( textField );
|
|
||||||
if ( !text.isEmpty() )
|
|
||||||
{
|
|
||||||
const auto h = skinnable->effectiveFontHeight( Q::Header );
|
|
||||||
rect.translate( 0.0, 0.5 * ( h + spacingV ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rect;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( subControl == Q::Header )
|
if ( subControl == Q::Header )
|
||||||
{
|
{
|
||||||
const auto text = effectiveHeaderText( textField );
|
const auto text = effectiveText( textField, Q::Header );
|
||||||
if( text.isEmpty() )
|
if( text.isEmpty() )
|
||||||
return QRectF();
|
return QRectF();
|
||||||
|
|
||||||
const QFontMetrics fm( textField->effectiveFont( Q::Header ) );
|
const QFontMetrics fm( textField->effectiveFont( Q::Header ) );
|
||||||
const auto textSize = fm.size( Qt::TextSingleLine | Qt::TextExpandTabs, text );
|
const auto textSize = fm.size( Qt::TextSingleLine | Qt::TextExpandTabs, text );
|
||||||
|
|
||||||
qreal x, y;
|
if ( textField->style() == QskTextField::OutlinedStyle )
|
||||||
|
{
|
||||||
|
const auto r = subControlRect( skinnable, contentsRect, Q::TextPanel );
|
||||||
|
|
||||||
if ( textField->style() == QskTextField::FilledStyle )
|
const auto x = r.left() + skinnable->paddingHint( Q::TextPanel ).left();
|
||||||
|
const auto y = r.top() - 0.5 * textSize.height();
|
||||||
|
|
||||||
|
return QRectF( x, y, textSize.width(), textSize.height() );
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
const auto r = subControlRect( skinnable, contentsRect, Q::Text );
|
const auto r = subControlRect( skinnable, contentsRect, Q::Text );
|
||||||
|
|
||||||
x = r.left();
|
return QRectF( r.x(), r.top() - textSize.height(),
|
||||||
y = r.top() - spacingV - textSize.height();
|
textSize.width(), textSize.height() );
|
||||||
}
|
}
|
||||||
else if ( textField->style() == QskTextField::OutlinedStyle )
|
|
||||||
{
|
|
||||||
const auto r = subControlRect( skinnable, contentsRect, Q::Panel );
|
|
||||||
|
|
||||||
x = r.left() + skinnable->paddingHint( Q::Panel ).left();
|
|
||||||
y = r.top() - 0.5 * textSize.height();
|
|
||||||
}
|
|
||||||
|
|
||||||
return QRectF( x, y, textSize.width(), textSize.height() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( subControl == Q::Footer )
|
if ( subControl == Q::TextPanel )
|
||||||
{
|
{
|
||||||
if( !textField->footerText().isEmpty() )
|
auto rect = skinnable->subControlRect( contentsRect, Q::Panel );
|
||||||
|
|
||||||
|
if ( textField->style() == QskTextField::OutlinedStyle )
|
||||||
{
|
{
|
||||||
auto rect = contentsRect;
|
const QFontMetrics fm( textField->effectiveFont( Q::Header ) );
|
||||||
|
rect.setTop( rect.top() + 0.5 * fm.height() );
|
||||||
const auto margins = textField->marginHint( subControl );
|
|
||||||
const auto h = textField->effectiveFontHeight( subControl )
|
|
||||||
+ margins.top() + margins.bottom();
|
|
||||||
|
|
||||||
rect.setTop( rect.bottom() - h );
|
|
||||||
rect.setLeft( rect.left() + margins.left() );
|
|
||||||
|
|
||||||
return rect;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return QRectF();
|
const auto h = skinnable->strutSizeHint( Q::TextPanel ).height();
|
||||||
|
rect.setHeight( h );
|
||||||
|
|
||||||
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( subControl == Q::CharacterCount )
|
if ( subControl == Q::CharacterCount )
|
||||||
|
@ -212,31 +154,23 @@ QSGNode* QskMaterial3TextFieldSkinlet::updateSubNode(
|
||||||
|
|
||||||
switch ( nodeRole )
|
switch ( nodeRole )
|
||||||
{
|
{
|
||||||
case PanelRole:
|
case TextPanelRole:
|
||||||
{
|
{
|
||||||
if( ( textField->style() == QskTextField::OutlinedStyle ) &&
|
const auto rect = textField->subControlRect( Q::TextPanel );
|
||||||
!effectiveHeaderText( textField ).isEmpty() )
|
|
||||||
|
auto hints = textField->boxHints( Q::TextPanel );
|
||||||
|
|
||||||
|
if( textField->style() == QskTextField::OutlinedStyle )
|
||||||
{
|
{
|
||||||
auto clipRect = textField->subControlRect( Q::Header );
|
const auto clipRect = textField->subControlRect( Q::Header );
|
||||||
if ( !clipRect.isEmpty() )
|
if ( !clipRect.isEmpty() )
|
||||||
{
|
{
|
||||||
const auto subControl = Q::Panel;
|
hints.borderColors = outlineColors(
|
||||||
|
hints.borderColors, rect, clipRect );
|
||||||
const auto panelRect = textField->subControlRect( subControl );
|
|
||||||
|
|
||||||
auto borderColors = textField->boxBorderColorsHint( subControl );
|
|
||||||
borderColors = outlineColors( borderColors, panelRect, clipRect );
|
|
||||||
|
|
||||||
return updateBoxNode( skinnable, node,
|
|
||||||
panelRect,
|
|
||||||
skinnable->boxShapeHint( subControl ),
|
|
||||||
skinnable->boxBorderMetricsHint( subControl ),
|
|
||||||
borderColors,
|
|
||||||
skinnable->gradientHint( subControl ) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return updateBoxNode( skinnable, node, Q::Panel );
|
return updateBoxNode( skinnable, node, rect, hints );
|
||||||
}
|
}
|
||||||
|
|
||||||
case CharacterCountRole:
|
case CharacterCountRole:
|
||||||
|
@ -244,12 +178,6 @@ QSGNode* QskMaterial3TextFieldSkinlet::updateSubNode(
|
||||||
return updateTextNode( skinnable, node,
|
return updateTextNode( skinnable, node,
|
||||||
maxLengthString( textField ), Q::CharacterCount );
|
maxLengthString( textField ), Q::CharacterCount );
|
||||||
}
|
}
|
||||||
|
|
||||||
case HeaderRole:
|
|
||||||
{
|
|
||||||
return updateTextNode( skinnable, node,
|
|
||||||
effectiveHeaderText( textField ), Q::Header );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
||||||
|
@ -258,40 +186,68 @@ QSGNode* QskMaterial3TextFieldSkinlet::updateSubNode(
|
||||||
QSizeF QskMaterial3TextFieldSkinlet::sizeHint( const QskSkinnable* skinnable,
|
QSizeF QskMaterial3TextFieldSkinlet::sizeHint( const QskSkinnable* skinnable,
|
||||||
Qt::SizeHint which, const QSizeF& constraint ) const
|
Qt::SizeHint which, const QSizeF& constraint ) const
|
||||||
{
|
{
|
||||||
|
Q_UNUSED( constraint ); // TODO ...
|
||||||
|
|
||||||
if ( which != Qt::PreferredSize )
|
if ( which != Qt::PreferredSize )
|
||||||
return QSizeF();
|
return QSizeF();
|
||||||
|
|
||||||
auto hint = Inherited::sizeHint( skinnable, which, constraint );
|
|
||||||
|
|
||||||
const auto textField = static_cast< const QskTextField* >( skinnable );
|
const auto textField = static_cast< const QskTextField* >( skinnable );
|
||||||
|
|
||||||
if( textField->style() != QskTextField::PlainStyle )
|
auto hint = textField->unwrappedTextSize();
|
||||||
hint.rheight() += textField->effectiveFontHeight( Q::Header ) + spacingV;
|
hint = hint.expandedTo( skinnable->strutSizeHint( Q::TextPanel ) );
|
||||||
|
|
||||||
if( hasBottomText( textField ) )
|
if ( textField->style() == QskTextField::OutlinedStyle )
|
||||||
{
|
{
|
||||||
const auto margins = textField->marginHint( Q::Footer );
|
const QFontMetrics fm( textField->effectiveFont( Q::Header ) );
|
||||||
hint.rheight() += textField->effectiveFontHeight( Q::Footer )
|
hint.rheight() += 0.5 * fm.height();
|
||||||
+ margins.top() + margins.bottom();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hint.rheight() += effectiveFooterHeight( textField );
|
||||||
|
hint = hint.expandedTo( skinnable->strutSizeHint( Q::Panel ) );
|
||||||
|
|
||||||
return hint;
|
return hint;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QskMaterial3TextFieldSkinlet::effectivePlaceholderText(
|
QString QskMaterial3TextFieldSkinlet::effectiveText(
|
||||||
const QskTextField* textField ) const
|
const QskTextField* textField, QskAspect::Subcontrol subControl ) const
|
||||||
{
|
{
|
||||||
if ( textField->text().isEmpty() &&
|
const bool showHeaderAsPlaceholder =
|
||||||
!( textField->isReadOnly() || textField->isEditing() ) )
|
textField->text().isEmpty() && !textField->isEditing();
|
||||||
{
|
|
||||||
auto text = textField->placeholderText();
|
|
||||||
if ( text.isEmpty() )
|
|
||||||
text = textField->headerText();
|
|
||||||
|
|
||||||
return text;
|
if ( subControl == Q::Header )
|
||||||
|
{
|
||||||
|
if ( showHeaderAsPlaceholder )
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
else if ( subControl == Q::Placeholder )
|
||||||
|
{
|
||||||
|
if ( showHeaderAsPlaceholder )
|
||||||
|
{
|
||||||
|
auto text = Inherited::effectiveText( textField, Q::Placeholder );
|
||||||
|
if ( text.isEmpty() )
|
||||||
|
text = Inherited::effectiveText( textField, Q::Header );
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
return QString();
|
return Inherited::effectiveText( textField, subControl );
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal QskMaterial3TextFieldSkinlet::effectiveFooterHeight(
|
||||||
|
const QskTextField* textField ) const
|
||||||
|
{
|
||||||
|
if ( hasCharacterCount( textField ) )
|
||||||
|
{
|
||||||
|
const auto h = textField->effectiveFontHeight( Q::Footer );
|
||||||
|
const auto margins = textField->marginHint( Q::Footer );
|
||||||
|
|
||||||
|
return h + margins.top() + margins.bottom();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Inherited::effectiveFooterHeight( textField );
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "moc_QskMaterial3TextFieldSkinlet.cpp"
|
#include "moc_QskMaterial3TextFieldSkinlet.cpp"
|
||||||
|
|
|
@ -18,8 +18,7 @@ class QSK_MATERIAL3_EXPORT QskMaterial3TextFieldSkinlet : public QskTextFieldSki
|
||||||
public:
|
public:
|
||||||
enum NodeRole : quint8
|
enum NodeRole : quint8
|
||||||
{
|
{
|
||||||
SupportingTextRole = Inherited::RoleCount,
|
CharacterCountRole = Inherited::RoleCount
|
||||||
CharacterCountRole
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_INVOKABLE QskMaterial3TextFieldSkinlet( QskSkin* = nullptr );
|
Q_INVOKABLE QskMaterial3TextFieldSkinlet( QskSkin* = nullptr );
|
||||||
|
@ -35,7 +34,10 @@ class QSK_MATERIAL3_EXPORT QskMaterial3TextFieldSkinlet : public QskTextFieldSki
|
||||||
QSGNode* updateSubNode( const QskSkinnable*,
|
QSGNode* updateSubNode( const QskSkinnable*,
|
||||||
quint8 nodeRole, QSGNode* ) const override;
|
quint8 nodeRole, QSGNode* ) const override;
|
||||||
|
|
||||||
QString effectivePlaceholderText( const QskTextField* ) const override;
|
QString effectiveText( const QskTextField*,
|
||||||
|
QskAspect::Subcontrol ) const override;
|
||||||
|
|
||||||
|
qreal effectiveFooterHeight( const QskTextField* ) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -158,9 +158,8 @@ namespace
|
||||||
StyleComboBox( QQuickItem* parent = nullptr )
|
StyleComboBox( QQuickItem* parent = nullptr )
|
||||||
: QskComboBox( parent )
|
: QskComboBox( parent )
|
||||||
{
|
{
|
||||||
addOption( QString(), "Plain" );
|
|
||||||
addOption( QString(), "Outlined" );
|
|
||||||
addOption( QString(), "Filled" );
|
addOption( QString(), "Filled" );
|
||||||
|
addOption( QString(), "Outlined" );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,12 +51,14 @@ namespace
|
||||||
new QskTextLabel( label, this );
|
new QskTextLabel( label, this );
|
||||||
|
|
||||||
m_textField = new QskTextField( this );
|
m_textField = new QskTextField( this );
|
||||||
|
|
||||||
|
m_textField->setText( "-0.000" );
|
||||||
|
m_textField->setPreferredWidth( m_textField->sizeHint().width() );
|
||||||
|
m_textField->setSizePolicy( Qt::Horizontal, QskSizePolicy::Fixed );
|
||||||
|
|
||||||
m_textField->setValidator( new InputValidator( m_textField ) );
|
m_textField->setValidator( new InputValidator( m_textField ) );
|
||||||
m_textField->setText( QString::number( value ) );
|
m_textField->setText( QString::number( value ) );
|
||||||
|
|
||||||
const QFontMetricsF fm( m_textField->font() );
|
|
||||||
m_textField->setFixedWidth( fm.horizontalAdvance( "-0.000" ) );
|
|
||||||
|
|
||||||
connect( m_textField, &QskTextField::editingChanged,
|
connect( m_textField, &QskTextField::editingChanged,
|
||||||
this, [ this ]( bool on ) { if ( !on ) Q_EMIT valueChanged(); } );
|
this, [ this ]( bool on ) { if ( !on ) Q_EMIT valueChanged(); } );
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ class QskTextField::PrivateData
|
||||||
QString footerText;
|
QString footerText;
|
||||||
QString placeholderText;
|
QString placeholderText;
|
||||||
|
|
||||||
Style style = PlainStyle;
|
Style style = FilledStyle;
|
||||||
QskAspect::States buttonStates;
|
QskAspect::States buttonStates;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -60,6 +60,7 @@ void QskTextField::setStyle( Style style )
|
||||||
m_data->style = style;
|
m_data->style = style;
|
||||||
|
|
||||||
resetImplicitSize();
|
resetImplicitSize();
|
||||||
|
polish();
|
||||||
update();
|
update();
|
||||||
|
|
||||||
Q_EMIT styleChanged( style );
|
Q_EMIT styleChanged( style );
|
||||||
|
|
|
@ -35,10 +35,8 @@ class QSK_EXPORT QskTextField : public QskTextInput
|
||||||
|
|
||||||
enum Style : quint8
|
enum Style : quint8
|
||||||
{
|
{
|
||||||
PlainStyle,
|
FilledStyle,
|
||||||
|
OutlinedStyle
|
||||||
OutlinedStyle,
|
|
||||||
FilledStyle
|
|
||||||
};
|
};
|
||||||
Q_ENUM( Style )
|
Q_ENUM( Style )
|
||||||
|
|
||||||
|
|
|
@ -5,16 +5,27 @@
|
||||||
|
|
||||||
#include "QskTextFieldSkinlet.h"
|
#include "QskTextFieldSkinlet.h"
|
||||||
#include "QskTextField.h"
|
#include "QskTextField.h"
|
||||||
|
#include "QskFunctions.h"
|
||||||
#include <qfontmetrics.h>
|
|
||||||
|
|
||||||
using Q = QskTextField;
|
using Q = QskTextField;
|
||||||
|
|
||||||
|
static qreal qskEffectiveTextHeight( const QskTextField* textField,
|
||||||
|
QskAspect::Subcontrol subControl )
|
||||||
|
{
|
||||||
|
auto h = textField->effectiveFontHeight( subControl );
|
||||||
|
|
||||||
|
const auto margins = textField->marginHint( subControl );
|
||||||
|
h += margins.top() + margins.bottom();
|
||||||
|
|
||||||
|
const auto sz = textField->strutSizeHint( subControl );
|
||||||
|
|
||||||
|
return qMax( h, sz.height() );
|
||||||
|
}
|
||||||
|
|
||||||
QskTextFieldSkinlet::QskTextFieldSkinlet( QskSkin* skin )
|
QskTextFieldSkinlet::QskTextFieldSkinlet( QskSkin* skin )
|
||||||
: Inherited( skin )
|
: Inherited( skin )
|
||||||
{
|
{
|
||||||
setNodeRoles( { PanelRole, TextPanelRole,
|
setNodeRoles( { TextPanelRole, IconRole, ButtonPanelRole, ButtonRole,
|
||||||
IconRole, ButtonPanelRole, ButtonRole,
|
|
||||||
PlaceholderRole, HeaderRole, FooterRole } );
|
PlaceholderRole, HeaderRole, FooterRole } );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,41 +36,68 @@ QskTextFieldSkinlet::~QskTextFieldSkinlet()
|
||||||
QRectF QskTextFieldSkinlet::subControlRect( const QskSkinnable* skinnable,
|
QRectF QskTextFieldSkinlet::subControlRect( const QskSkinnable* skinnable,
|
||||||
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
|
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
|
||||||
{
|
{
|
||||||
|
const auto textField = static_cast< const QskTextField* >( skinnable );
|
||||||
|
|
||||||
if ( subControl == Q::Panel )
|
if ( subControl == Q::Panel )
|
||||||
|
{
|
||||||
return contentsRect;
|
return contentsRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( subControl == Q::Header )
|
||||||
|
{
|
||||||
|
if ( auto h = effectiveHeaderHeight( textField ) )
|
||||||
|
{
|
||||||
|
const auto m = textField->marginHint( Q::Header );
|
||||||
|
const auto r = subControlRect( skinnable, contentsRect, Q::TextPanel );
|
||||||
|
|
||||||
|
return QRectF( r.left() + m.left(),
|
||||||
|
r.top() - m.bottom() - h, r.width() - m.left() - m.right(), h );
|
||||||
|
}
|
||||||
|
|
||||||
|
return QRectF();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( subControl == Q::Footer )
|
||||||
|
{
|
||||||
|
if ( const auto h = effectiveFooterHeight( textField ) )
|
||||||
|
{
|
||||||
|
const auto m = textField->marginHint( Q::Footer );
|
||||||
|
const auto r = subControlRect( skinnable, contentsRect, Q::TextPanel );
|
||||||
|
|
||||||
|
return QRectF( r.left() + m.left(),
|
||||||
|
r.bottom() + m.top(), r.width() - m.left() - m.right(), h );
|
||||||
|
}
|
||||||
|
|
||||||
|
return QRectF();
|
||||||
|
}
|
||||||
|
|
||||||
if ( subControl == Q::TextPanel )
|
if ( subControl == Q::TextPanel )
|
||||||
return skinnable->subControlContentsRect( contentsRect, Q::Panel );
|
{
|
||||||
|
const auto rect = textField->subControlContentsRect( contentsRect, Q::Panel );
|
||||||
|
return inputPanelRect( textField, rect );
|
||||||
|
}
|
||||||
|
|
||||||
if ( subControl == Q::Text )
|
if ( subControl == Q::Text )
|
||||||
{
|
{
|
||||||
auto rect = skinnable->subControlContentsRect( contentsRect, Q::TextPanel );
|
auto rect = textField->subControlContentsRect( contentsRect, Q::TextPanel );
|
||||||
|
|
||||||
if( !skinnable->symbolHint( Q::Icon ).isEmpty() )
|
const auto iconRect = subControlRect( skinnable, contentsRect, Q::Icon );
|
||||||
{
|
if ( !iconRect.isEmpty() )
|
||||||
const auto r = subControlRect( skinnable, contentsRect, Q::Icon );
|
rect.setLeft( iconRect.right() );
|
||||||
if ( !r.isEmpty() )
|
|
||||||
rect.setLeft( r.right() );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !skinnable->symbolHint( Q::Button ).isEmpty() )
|
const auto buttonRect = subControlRect( skinnable, contentsRect, Q::Button );
|
||||||
{
|
if( !buttonRect.isEmpty() )
|
||||||
const auto r = subControlRect( skinnable, contentsRect, Q::Button );
|
rect.setRight( buttonRect.left() );
|
||||||
if( !r.isEmpty() )
|
|
||||||
rect.setRight( r.left() );
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto h = skinnable->effectiveFontHeight( Q::Text );
|
const auto h = skinnable->effectiveFontHeight( Q::Text );
|
||||||
rect.setTop( rect.center().y() - 0.5 * h );
|
rect.setTop( rect.center().y() - 0.5 * h );
|
||||||
rect.setHeight( h );
|
rect.setHeight( h );
|
||||||
rect = rect.marginsAdded( skinnable->marginHint( Q::Text ) );
|
|
||||||
|
|
||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( subControl == Q::Placeholder )
|
if ( subControl == Q::Placeholder )
|
||||||
{
|
{
|
||||||
const auto textField = static_cast< const QskTextField* >( skinnable );
|
|
||||||
if( textField->text().isEmpty() )
|
if( textField->text().isEmpty() )
|
||||||
return subControlRect( skinnable, contentsRect, Q::Text );
|
return subControlRect( skinnable, contentsRect, Q::Text );
|
||||||
|
|
||||||
|
@ -70,15 +108,10 @@ QRectF QskTextFieldSkinlet::subControlRect( const QskSkinnable* skinnable,
|
||||||
{
|
{
|
||||||
if( !skinnable->symbolHint( subControl ).isEmpty() )
|
if( !skinnable->symbolHint( subControl ).isEmpty() )
|
||||||
{
|
{
|
||||||
const auto panelRect = skinnable->subControlContentsRect(
|
const auto rect = textField->subControlContentsRect( contentsRect, Q::TextPanel );
|
||||||
contentsRect, Q::TextPanel );
|
|
||||||
|
|
||||||
auto rect = panelRect;
|
return qskAlignedRectF( rect,
|
||||||
|
skinnable->strutSizeHint( Q::Icon ), Qt::AlignLeft | Qt::AlignVCenter );
|
||||||
rect.setSize( skinnable->strutSizeHint( subControl ) );
|
|
||||||
rect.moveCenter( { rect.center().x(), panelRect.center().y() } );
|
|
||||||
|
|
||||||
return rect;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return QRectF();
|
return QRectF();
|
||||||
|
@ -86,15 +119,18 @@ QRectF QskTextFieldSkinlet::subControlRect( const QskSkinnable* skinnable,
|
||||||
|
|
||||||
if ( subControl == Q::ButtonPanel )
|
if ( subControl == Q::ButtonPanel )
|
||||||
{
|
{
|
||||||
const auto textField = static_cast< const QskTextField* >( skinnable );
|
|
||||||
if ( textField->buttonStates() & Q::Hovered )
|
if ( textField->buttonStates() & Q::Hovered )
|
||||||
{
|
{
|
||||||
const auto r = subControlRect( skinnable, contentsRect, Q::Button );
|
const auto sz = skinnable->strutSizeHint( Q::ButtonPanel );
|
||||||
|
if ( !sz.isEmpty() )
|
||||||
|
{
|
||||||
|
const auto r = subControlRect( skinnable, contentsRect, Q::Button );
|
||||||
|
|
||||||
QRectF rect( QPointF(), skinnable->strutSizeHint( subControl ) );
|
QRectF rect( QPointF(), sz );
|
||||||
rect.moveCenter( r.center() );
|
rect.moveCenter( r.center() );
|
||||||
|
|
||||||
return rect;
|
return rect;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return QRectF();
|
return QRectF();
|
||||||
|
@ -102,19 +138,12 @@ QRectF QskTextFieldSkinlet::subControlRect( const QskSkinnable* skinnable,
|
||||||
|
|
||||||
if ( subControl == Q::Button )
|
if ( subControl == Q::Button )
|
||||||
{
|
{
|
||||||
if( !skinnable->symbolHint( subControl ).isEmpty() )
|
if( !skinnable->symbolHint( Q::Button ).isEmpty() )
|
||||||
{
|
{
|
||||||
const auto panelRect = skinnable->subControlContentsRect(
|
const auto rect = textField->subControlContentsRect( contentsRect, Q::TextPanel );
|
||||||
contentsRect, Q::TextPanel );
|
|
||||||
|
|
||||||
auto rect = panelRect;
|
return qskAlignedRectF( rect,
|
||||||
|
skinnable->strutSizeHint( Q::Icon ), Qt::AlignRight | Qt::AlignVCenter );
|
||||||
const auto size = skinnable->strutSizeHint( subControl );
|
|
||||||
rect.setHeight( size.height() );
|
|
||||||
rect.moveCenter( { rect.center().x(), panelRect.center().y() } );
|
|
||||||
rect.setLeft( rect.right() - size.width() );
|
|
||||||
|
|
||||||
return rect;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return QRectF();
|
return QRectF();
|
||||||
|
@ -130,22 +159,18 @@ QSGNode* QskTextFieldSkinlet::updateSubNode(
|
||||||
|
|
||||||
switch ( nodeRole )
|
switch ( nodeRole )
|
||||||
{
|
{
|
||||||
case PanelRole:
|
|
||||||
{
|
|
||||||
return updateBoxNode( skinnable, node, Q::Panel );
|
|
||||||
}
|
|
||||||
case TextPanelRole:
|
case TextPanelRole:
|
||||||
{
|
{
|
||||||
return updateBoxNode( skinnable, node, Q::TextPanel );
|
return updateBoxNode( skinnable, node, Q::TextPanel );
|
||||||
}
|
}
|
||||||
case PlaceholderRole:
|
case PlaceholderRole:
|
||||||
{
|
{
|
||||||
const auto text = effectivePlaceholderText( textField );
|
const auto subControl = Q::Placeholder;
|
||||||
|
|
||||||
|
const auto text = effectiveText( textField, subControl );
|
||||||
if ( text.isEmpty() )
|
if ( text.isEmpty() )
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
const auto subControl = Q::Placeholder;
|
|
||||||
|
|
||||||
QskSkinHintStatus status;
|
QskSkinHintStatus status;
|
||||||
|
|
||||||
auto options = skinnable->textOptionsHint( subControl, &status );
|
auto options = skinnable->textOptionsHint( subControl, &status );
|
||||||
|
@ -161,13 +186,13 @@ QSGNode* QskTextFieldSkinlet::updateSubNode(
|
||||||
case HeaderRole:
|
case HeaderRole:
|
||||||
{
|
{
|
||||||
return updateTextNode( skinnable, node,
|
return updateTextNode( skinnable, node,
|
||||||
textField->headerText(), Q::Header );
|
effectiveText( textField, Q::Header ), Q::Header );
|
||||||
}
|
}
|
||||||
|
|
||||||
case FooterRole:
|
case FooterRole:
|
||||||
{
|
{
|
||||||
return updateTextNode( skinnable, node,
|
return updateTextNode( skinnable, node,
|
||||||
textField->footerText(), Q::Footer );
|
effectiveText( textField, Q::Footer ), Q::Footer );
|
||||||
}
|
}
|
||||||
|
|
||||||
case IconRole:
|
case IconRole:
|
||||||
|
@ -183,6 +208,37 @@ QSGNode* QskTextFieldSkinlet::updateSubNode(
|
||||||
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRectF QskTextFieldSkinlet::inputPanelRect(
|
||||||
|
const QskTextField* textField, const QRectF& rect ) const
|
||||||
|
{
|
||||||
|
qreal h = textField->effectiveFontHeight( Q::Text );
|
||||||
|
h = textField->outerBoxSize( Q::TextPanel, QSizeF( rect.width(), h ) ).height();
|
||||||
|
h = qMax( h, textField->strutSizeHint( Q::TextPanel ).height() );
|
||||||
|
|
||||||
|
/*
|
||||||
|
when having textfields in horizontal layouts you usually want
|
||||||
|
the text panels being vertically aligned - regardless of having
|
||||||
|
Q::Header/Q::Footer being available.
|
||||||
|
*/
|
||||||
|
|
||||||
|
auto top = qskEffectiveTextHeight( textField, Q::Header );
|
||||||
|
auto bottom = qskEffectiveTextHeight( textField, Q::Footer );
|
||||||
|
|
||||||
|
if ( rect.height() < top + h + bottom )
|
||||||
|
{
|
||||||
|
if ( effectiveText( textField, Q::Footer ).isEmpty() )
|
||||||
|
bottom = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( rect.height() < top + h + bottom )
|
||||||
|
{
|
||||||
|
if ( effectiveText( textField, Q::Header ).isEmpty() )
|
||||||
|
top = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QRectF( rect.left(), rect.top() + top, rect.width(), h );
|
||||||
|
}
|
||||||
|
|
||||||
QSizeF QskTextFieldSkinlet::sizeHint( const QskSkinnable* skinnable,
|
QSizeF QskTextFieldSkinlet::sizeHint( const QskSkinnable* skinnable,
|
||||||
Qt::SizeHint which, const QSizeF& constraint ) const
|
Qt::SizeHint which, const QSizeF& constraint ) const
|
||||||
{
|
{
|
||||||
|
@ -191,13 +247,22 @@ QSizeF QskTextFieldSkinlet::sizeHint( const QskSkinnable* skinnable,
|
||||||
if ( which != Qt::PreferredSize )
|
if ( which != Qt::PreferredSize )
|
||||||
return QSizeF();
|
return QSizeF();
|
||||||
|
|
||||||
const auto input = static_cast< const QskAbstractTextInput* >( skinnable );
|
const auto textField = static_cast< const QskTextField* >( skinnable );
|
||||||
|
|
||||||
auto hint = input->unwrappedTextSize();
|
auto hint = textField->unwrappedTextSize();
|
||||||
hint = hint.grownBy( skinnable->marginHint( Q::Text ) );
|
|
||||||
|
|
||||||
hint = input->outerBoxSize( Q::TextPanel, hint );
|
if( !skinnable->symbolHint( Q::Button ).isEmpty() )
|
||||||
hint = hint.expandedTo( input->strutSizeHint( Q::TextPanel ) );
|
{
|
||||||
|
const auto sz = skinnable->strutSizeHint( Q::Button );
|
||||||
|
if ( sz.width() > 0.0 )
|
||||||
|
hint.rwidth() += sz.width();
|
||||||
|
}
|
||||||
|
|
||||||
|
hint = skinnable->outerBoxSize( Q::TextPanel, hint );
|
||||||
|
hint = hint.expandedTo( skinnable->strutSizeHint( Q::TextPanel ) );
|
||||||
|
|
||||||
|
hint.rheight() += effectiveHeaderHeight( textField );
|
||||||
|
hint.rheight() += effectiveFooterHeight( textField );
|
||||||
|
|
||||||
hint = skinnable->outerBoxSize( Q::Panel, hint );
|
hint = skinnable->outerBoxSize( Q::Panel, hint );
|
||||||
hint = hint.expandedTo( skinnable->strutSizeHint( Q::Panel ) );
|
hint = hint.expandedTo( skinnable->strutSizeHint( Q::Panel ) );
|
||||||
|
@ -205,16 +270,42 @@ QSizeF QskTextFieldSkinlet::sizeHint( const QskSkinnable* skinnable,
|
||||||
return hint;
|
return hint;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QskTextFieldSkinlet::effectivePlaceholderText(
|
QString QskTextFieldSkinlet::effectiveText(
|
||||||
const QskTextField* textField ) const
|
const QskTextField* textField, QskAspect::Subcontrol subcontrol ) const
|
||||||
{
|
{
|
||||||
if ( textField->text().isEmpty() &&
|
if ( subcontrol == Q::Text )
|
||||||
!( textField->isReadOnly() || textField->isEditing() ) )
|
return textField->text();
|
||||||
|
|
||||||
|
if ( subcontrol == Q::Placeholder )
|
||||||
{
|
{
|
||||||
return textField->placeholderText();
|
if ( textField->text().isEmpty() &&
|
||||||
|
!( textField->isReadOnly() || textField->isEditing() ) )
|
||||||
|
{
|
||||||
|
return textField->placeholderText();
|
||||||
|
}
|
||||||
|
|
||||||
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( subcontrol == Q::Header )
|
||||||
|
return textField->headerText();
|
||||||
|
|
||||||
|
if ( subcontrol == Q::Footer )
|
||||||
|
return textField->footerText();
|
||||||
|
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qreal QskTextFieldSkinlet::effectiveHeaderHeight( const QskTextField* textField ) const
|
||||||
|
{
|
||||||
|
const auto text = effectiveText( textField, Q::Header );
|
||||||
|
return text.isEmpty() ? 0.0 : qskEffectiveTextHeight( textField, Q::Header );
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal QskTextFieldSkinlet::effectiveFooterHeight( const QskTextField* textField ) const
|
||||||
|
{
|
||||||
|
const auto text = effectiveText( textField, Q::Footer );
|
||||||
|
return text.isEmpty() ? 0.0 : qskEffectiveTextHeight( textField, Q::Footer );
|
||||||
|
}
|
||||||
|
|
||||||
#include "moc_QskTextFieldSkinlet.cpp"
|
#include "moc_QskTextFieldSkinlet.cpp"
|
||||||
|
|
|
@ -19,7 +19,6 @@ class QSK_EXPORT QskTextFieldSkinlet : public QskSkinlet
|
||||||
public:
|
public:
|
||||||
enum NodeRole : quint8
|
enum NodeRole : quint8
|
||||||
{
|
{
|
||||||
PanelRole,
|
|
||||||
TextPanelRole,
|
TextPanelRole,
|
||||||
|
|
||||||
HeaderRole,
|
HeaderRole,
|
||||||
|
@ -45,7 +44,14 @@ class QSK_EXPORT QskTextFieldSkinlet : public QskSkinlet
|
||||||
QSGNode* updateSubNode( const QskSkinnable*,
|
QSGNode* updateSubNode( const QskSkinnable*,
|
||||||
quint8 nodeRole, QSGNode* ) const override;
|
quint8 nodeRole, QSGNode* ) const override;
|
||||||
|
|
||||||
virtual QString effectivePlaceholderText( const QskTextField* ) const;
|
virtual QString effectiveText( const QskTextField*,
|
||||||
|
QskAspect::Subcontrol ) const;
|
||||||
|
|
||||||
|
qreal effectiveHeaderHeight( const QskTextField* ) const;
|
||||||
|
virtual qreal effectiveFooterHeight( const QskTextField* ) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QRectF inputPanelRect( const QskTextField*, const QRectF& ) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -161,7 +161,7 @@ QskTextInput::QskTextInput( QQuickItem* parent )
|
||||||
setAcceptedMouseButtons( wrappedInput->acceptedMouseButtons() );
|
setAcceptedMouseButtons( wrappedInput->acceptedMouseButtons() );
|
||||||
wrappedInput->setAcceptedMouseButtons( Qt::NoButton );
|
wrappedInput->setAcceptedMouseButtons( Qt::NoButton );
|
||||||
|
|
||||||
initSizePolicy( QskSizePolicy::Expanding, QskSizePolicy::Fixed );
|
initSizePolicy( QskSizePolicy::Expanding, QskSizePolicy::Minimum );
|
||||||
|
|
||||||
setup( wrappedInput );
|
setup( wrappedInput );
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue