diff --git a/examples/automotive/SpeedometerSkinlet.cpp b/examples/automotive/SpeedometerSkinlet.cpp index 5eff6632..3b3aa6d7 100644 --- a/examples/automotive/SpeedometerSkinlet.cpp +++ b/examples/automotive/SpeedometerSkinlet.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include @@ -164,7 +163,9 @@ QSGNode* SpeedometerSkinlet::updateLabelsNode( const auto radius = 0.5 * scaleRect.width(); const auto spacing = speedometer->spacingHint( Q::TickLabels ); - QFontMetricsF fontMetrics( speedometer->effectiveFont( Q::TickLabels ) ); + + const auto font = speedometer->effectiveFont( Q::TickLabels ); + const QFontMetricsF fontMetrics( font ); auto angle = startAngle; @@ -172,6 +173,9 @@ QSGNode* SpeedometerSkinlet::updateLabelsNode( const auto needleRadius = radius - tickSize.height(); // Create a series of tickmarks from minimum to maximum + + auto labelNode = ticksNode->firstChild(); + for ( int i = 0; i < labels.count(); ++i, angle += step ) { const qreal cos = qFastCos( qDegreesToRadians( angle ) ); @@ -188,11 +192,10 @@ QSGNode* SpeedometerSkinlet::updateLabelsNode( vertexData += 2; - // only create a text node if there is a label for it: - if ( labels.count() > i ) - { - const QString& text = labels.at( i ); + const auto& text = labels.at( i ); + if ( !text.isEmpty() ) + { const auto w = qskHorizontalAdvance( fontMetrics, text ); const auto h = fontMetrics.height(); const auto adjustX = ( -0.5 * cos - 0.5 ) * w; @@ -203,23 +206,17 @@ QSGNode* SpeedometerSkinlet::updateLabelsNode( const QRectF numbersRect( numbersX, numbersY, w, h ); - QskTextNode* numbersNode; + labelNode = QskSkinlet::updateTextNode( + speedometer, labelNode, numbersRect, Qt::AlignCenter | Qt::AlignHCenter, + text, font, QskTextOptions(), QskTextColors( color ), Qsk::Normal ); - if ( ticksNode->childCount() > i ) + if ( labelNode ) { - numbersNode = static_cast< QskTextNode* >( ticksNode->childAtIndex( i ) ); - } - else - { - numbersNode = new QskTextNode(); - } + if ( labelNode->parent() != ticksNode ) + ticksNode->appendChildNode( labelNode ); - const auto font = speedometer->effectiveFont( Q::TickLabels ); - numbersNode->setTextData( speedometer, text, numbersRect, font, QskTextOptions(), - QskTextColors( color ), Qt::AlignCenter | Qt::AlignHCenter, Qsk::Normal ); - - if ( ticksNode->childCount() <= i ) - ticksNode->appendChildNode( numbersNode ); + labelNode = labelNode->nextSibling(); + } } } diff --git a/examples/tabview/CustomSliderSkinlet.cpp b/examples/tabview/CustomSliderSkinlet.cpp index 75a7f990..0766957d 100644 --- a/examples/tabview/CustomSliderSkinlet.cpp +++ b/examples/tabview/CustomSliderSkinlet.cpp @@ -10,11 +10,13 @@ #include #include #include -#include #include +#include +#include #include #include +#include #include @@ -287,40 +289,38 @@ QSGNode* CustomSliderSkinlet::updateDecorationNode( const int tickCount = std::floor( slider->boundaryLength() / slider->stepSize() ) + 1; - auto labelNode = static_cast< QskTextNode* >( decorationNode->firstChild() ); - auto stepStride = slider->stepSize() / slider->boundaryLength() * decorationRect.width(); auto x = decorationRect.x(); const auto y = decorationRect.y(); + auto labelNode = decorationNode->firstChild(); + + const QFontMetrics fm( qskLabelFont ); + for ( int i = 0; i < tickCount; i += 100 ) { - if ( labelNode == nullptr ) + const auto text = QString::number( slider->minimum() + slider->stepSize() * i, 'f', 0 ); + + const auto w = qskHorizontalAdvance( fm, text ); + const auto h = fm.height(); + + labelNode = QskSkinlet::updateTextNode( slider, labelNode, + QRectF( x - 0.5 * w, y, w, h ), Qt::AlignHCenter, text, qskLabelFont, + QskTextOptions(), QskTextColors( QskRgb::Grey700 ), Qsk::Normal ); + + if ( labelNode ) { - labelNode = new QskTextNode; - decorationNode->appendChildNode( labelNode ); + if ( labelNode->parent() != decorationNode ) + decorationNode->appendChildNode( labelNode ); + + labelNode = labelNode->nextSibling(); } - auto labelText = QString::number( slider->minimum() + slider->stepSize() * i, 'f', 0 ); - - labelNode->setTextData( slider, labelText, QRectF( x, y, 0, 0 ), - qskLabelFont, QskTextOptions(), QskTextColors( QskRgb::Grey700 ), - Qt::AlignHCenter, Qsk::Normal ); - - labelNode = static_cast< decltype( labelNode ) >( labelNode->nextSibling() ); x += 100 * stepStride; } - // Remove unused labels - while ( labelNode ) - { - auto sibling = static_cast< decltype( labelNode ) >( labelNode->nextSibling() ); - decorationNode->removeChildNode( labelNode ); - delete labelNode; - labelNode = sibling; - } - + QskSGNode::removeAllChildNodesAfter( decorationNode, labelNode ); return decorationNode; } @@ -344,12 +344,6 @@ QSGNode* CustomSliderSkinlet::updateHandleNode( handleNode->update( handleRect, fillRect.right(), handleColor ); // finally the value label - auto labelNode = static_cast< QskTextNode* >( handleNode->firstChild() ); - if ( labelNode == nullptr ) - { - labelNode = new QskTextNode; - handleNode->appendChildNode( labelNode ); - } QFont font( QStringLiteral( "Roboto" ) ); font.setPixelSize( 26 ); @@ -361,8 +355,12 @@ QSGNode* CustomSliderSkinlet::updateHandleNode( const auto text = QString::number( slider->value(), 'f', 0 ); - labelNode->setTextData( slider, text, textRect, font, QskTextOptions(), - QskTextColors( Qt::white ), Qt::AlignHCenter, Qsk::Normal ); + auto labelNode = QskSkinlet::updateTextNode( slider, handleNode->firstChild(), + textRect, Qt::AlignHCenter, text, font, QskTextOptions(), + QskTextColors( Qt::white ), Qsk::Normal ); + + if ( labelNode->parent() != handleNode ) + handleNode->appendChildNode( labelNode ); return handleNode; } @@ -373,7 +371,7 @@ QSizeF CustomSliderSkinlet::sizeHint( const QskSkinnable* skinnable, auto size = Inherited::sizeHint( skinnable, which, constraint ); if ( which == Qt::PreferredSize && size.height() >= 0 ) - size.rheight() += 40; + size.rheight() += 60; return size; } diff --git a/src/controls/QskMenuSkinlet.cpp b/src/controls/QskMenuSkinlet.cpp index eb975b76..12e8be86 100644 --- a/src/controls/QskMenuSkinlet.cpp +++ b/src/controls/QskMenuSkinlet.cpp @@ -9,8 +9,6 @@ #include "QskBoxNode.h" #include "QskGraphic.h" #include "QskColorFilter.h" -#include "QskGraphicNode.h" -#include "QskTextNode.h" #include "QskTextOptions.h" #include "QskSGNode.h" #include "QskFunctions.h" diff --git a/src/controls/QskSegmentedBarSkinlet.cpp b/src/controls/QskSegmentedBarSkinlet.cpp index fc7c9c83..a7aedc14 100644 --- a/src/controls/QskSegmentedBarSkinlet.cpp +++ b/src/controls/QskSegmentedBarSkinlet.cpp @@ -6,10 +6,8 @@ #include "QskSegmentedBarSkinlet.h" #include "QskSegmentedBar.h" -#include "QskGraphicNode.h" #include "QskGraphic.h" #include "QskColorFilter.h" -#include "QskTextNode.h" #include "QskTextOptions.h" #include "QskSGNode.h" #include "QskFunctions.h" diff --git a/src/controls/QskSkinlet.cpp b/src/controls/QskSkinlet.cpp index 9e2b7a35..61ed5415 100644 --- a/src/controls/QskSkinlet.cpp +++ b/src/controls/QskSkinlet.cpp @@ -62,6 +62,43 @@ static inline QRectF qskSubControlRect( const QskSkinlet* skinlet, return QRectF(); } +static inline QSGNode* qskUpdateTextNode( const QskSkinnable* skinnable, + QSGNode* node, const QRectF& rect, Qt::Alignment alignment, + const QString& text, const QFont& font, const QskTextOptions& textOptions, + const QskTextColors& textColors, Qsk::TextStyle textStyle ) +{ + if ( text.isEmpty() || rect.isEmpty() ) + return nullptr; + + auto textNode = static_cast< QskTextNode* >( node ); + if ( textNode == nullptr ) + textNode = new QskTextNode(); + + auto effectiveFont = font; + switch ( textOptions.fontSizeMode() ) + { + case QskTextOptions::FixedSize: + break; + + case QskTextOptions::HorizontalFit: + Q_UNIMPLEMENTED(); + break; + + case QskTextOptions::VerticalFit: + effectiveFont.setPixelSize( static_cast< int >( rect.height() * 0.5 ) ); + break; + + case QskTextOptions::Fit: + Q_UNIMPLEMENTED(); + break; + } + + textNode->setTextData( skinnable->owningControl(), + text, rect, effectiveFont, textOptions, textColors, alignment, textStyle ); + + return textNode; +} + static inline QSGNode* qskUpdateGraphicNode( const QskSkinnable* skinnable, QSGNode* node, const QskGraphic& graphic, const QskColorFilter& colorFilter, @@ -521,6 +558,15 @@ QSGNode* QskSkinlet::updateBoxClipNode( const QskSkinnable* skinnable, return clipNode; } +QSGNode* QskSkinlet::updateTextNode( const QskSkinnable* skinnable, + QSGNode* node, const QRectF& rect, Qt::Alignment alignment, + const QString& text, const QFont& font, const QskTextOptions& textOptions, + const QskTextColors& textColors, Qsk::TextStyle textStyle ) +{ + return qskUpdateTextNode( skinnable, node, rect, alignment, + text, font, textOptions, textColors, textStyle ); +} + QSGNode* QskSkinlet::updateTextNode( const QskSkinnable* skinnable, QSGNode* node, const QRectF& rect, Qt::Alignment alignment, @@ -530,43 +576,19 @@ QSGNode* QskSkinlet::updateTextNode( if ( text.isEmpty() || rect.isEmpty() ) return nullptr; - auto textNode = static_cast< QskTextNode* >( node ); - if ( textNode == nullptr ) - textNode = new QskTextNode(); - - const auto colors = qskTextColors( skinnable, subControl ); + const auto textColors = qskTextColors( skinnable, subControl ); auto textStyle = Qsk::Normal; - if ( colors.styleColor.alpha() == 0 ) + if ( textColors.styleColor.alpha() == 0 ) { textStyle = skinnable->flagHint< Qsk::TextStyle >( subControl | QskAspect::Style, Qsk::Normal ); } - auto font = skinnable->effectiveFont( subControl ); + const auto font = skinnable->effectiveFont( subControl ); - switch ( textOptions.fontSizeMode() ) - { - case QskTextOptions::FixedSize: - break; - - case QskTextOptions::HorizontalFit: - Q_UNIMPLEMENTED(); - break; - - case QskTextOptions::VerticalFit: - font.setPixelSize( static_cast< int >( rect.height() * 0.5 ) ); - break; - - case QskTextOptions::Fit: - Q_UNIMPLEMENTED(); - break; - } - - textNode->setTextData( skinnable->owningControl(), - text, rect, font, textOptions, colors, alignment, textStyle ); - - return textNode; + return qskUpdateTextNode( skinnable, node, rect, alignment, + text, font, textOptions, textColors, textStyle ); } QSGNode* QskSkinlet::updateTextNode( diff --git a/src/controls/QskSkinlet.h b/src/controls/QskSkinlet.h index 534b00f0..b4e4fc34 100644 --- a/src/controls/QskSkinlet.h +++ b/src/controls/QskSkinlet.h @@ -7,6 +7,7 @@ #define QSK_SKINLET_H #include "QskAspect.h" +#include "QskNamespace.h" #include #include @@ -21,6 +22,7 @@ class QskGradient; class QskColorFilter; class QskGraphic; class QskTextOptions; +class QskTextColors; class QskBoxShapeMetrics; class QskBoxBorderMetrics; class QskBoxBorderColors; @@ -108,6 +110,10 @@ class QSK_EXPORT QskSkinlet const QRectF&, Qt::Alignment, const QString&, const QskTextOptions&, QskAspect::Subcontrol ); + static QSGNode* updateTextNode( const QskSkinnable*, QSGNode*, + const QRectF&, Qt::Alignment, const QString&, const QFont&, + const QskTextOptions&, const QskTextColors&, Qsk::TextStyle ); + // keeping the aspect ratio static QSGNode* updateGraphicNode( const QskSkinnable*, QSGNode*, const QskGraphic&, const QskColorFilter&, const QRectF&, diff --git a/src/nodes/QskScaleRenderer.cpp b/src/nodes/QskScaleRenderer.cpp index f647ad6e..ce12a6d1 100644 --- a/src/nodes/QskScaleRenderer.cpp +++ b/src/nodes/QskScaleRenderer.cpp @@ -8,8 +8,6 @@ #include "QskSkinlet.h" #include "QskSGNode.h" #include "QskTickmarksNode.h" -#include "QskTextNode.h" -#include "QskGraphicNode.h" #include "QskTextOptions.h" #include "QskTextColors.h" #include "QskGraphic.h" @@ -283,18 +281,20 @@ QSGNode* QskScaleRenderer::updateLabelsNode( labelRect = r; } - if ( nextNode == nullptr ) + nextNode = QskSkinlet::updateTextNode( skinnable, nextNode, + r, alignment, text, m_data->font, QskTextOptions(), + m_data->textColors, Qsk::Normal ); + + if ( nextNode ) { - nextNode = new QskTextNode; - QskSGNode::setNodeRole( nextNode, TextNode ); - node->appendChildNode( nextNode ); + if ( nextNode->parent() != node ) + { + QskSGNode::setNodeRole( nextNode, TextNode ); + node->appendChildNode( nextNode ); + } + + nextNode = nextNode->nextSibling(); } - - auto textNode = static_cast< QskTextNode* >( nextNode ); - textNode->setTextData( skinnable->owningControl(), text, r, m_data->font, - QskTextOptions(), m_data->textColors, alignment, Qsk::Normal ); - - nextNode = nextNode->nextSibling(); } else if ( label.canConvert< QskGraphic >() ) { @@ -329,20 +329,19 @@ QSGNode* QskScaleRenderer::updateLabelsNode( nextNode = qskRemoveTraillingNodes( node, nextNode ); } - if ( nextNode == nullptr ) + nextNode = QskSkinlet::updateGraphicNode( + skinnable, nextNode, graphic, m_data->colorFilter, labelRect, alignment ); + + if ( nextNode ) { - nextNode = new QskGraphicNode; - QskSGNode::setNodeRole( nextNode, GraphicNode ); - node->appendChildNode( nextNode ); + if ( nextNode->parent() != node ) + { + QskSGNode::setNodeRole( nextNode, GraphicNode ); + node->appendChildNode( nextNode ); + } + + nextNode = nextNode->nextSibling(); } - - auto graphicNode = static_cast< QskGraphicNode* >( nextNode ); - - QskSkinlet::updateGraphicNode( - skinnable->owningControl(), graphicNode, - graphic, m_data->colorFilter, labelRect, alignment ); - - nextNode = nextNode->nextSibling(); } }