diff --git a/src/controls/QskSpinBox.h b/src/controls/QskSpinBox.h index f0318815..afa4b293 100644 --- a/src/controls/QskSpinBox.h +++ b/src/controls/QskSpinBox.h @@ -6,34 +6,67 @@ #pragma once #include -#include -#include +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// @brief +/// This control allows the user to increment and decrement a floating point value. +/// @details +/// The incement and decrement step size is configurable and the value's range can be limited +/// through an inclusive interval [min,max]. The value is being displayed on a readonly text label +/// surrounded by an increment and decrement button. +/// +/// - The value can be increased by: +/// - clicking the increment button +/// - pressing the plus, right or up key +/// - scrolling up the mouse wheel +/// - focusing the increment button and clicking space or select +/// - The value can be decreased by: +/// - clicking the decrement button +/// - pressing the minus, left or down key +/// - scrolling down the mouse wheel +/// - focusing the decrement button and clicking space or select +//////////////////////////////////////////////////////////////////////////////////////////////////// class QSK_EXPORT QskSpinBox : public QskBoundedValueInput { Q_OBJECT using Inherited = QskBoundedValueInput; public: + /// Focus indeces for the visual subcontrols enum FocusIndeces : int { - Decrement = 0, - Textbox = 1, - Increment = 2, - None = 3 + Decrement = 0, ///< the decrement buttons index + Textbox = 1, ///< the textbox' index + Increment = 2, ///< the increment button's index + None = 3 ///< index for when no subcontrol is focused (e.g. focus in/out ) }; Q_ENUM( FocusIndeces ) + /// The currently focused subcontrol's index Q_PROPERTY( FocusIndeces focusIndex READ focusIndex NOTIFY focusIndexChanged ) - QSK_SUBCONTROLS( - IncrementPanel, DecrementPanel, IncrementText, DecrementText, TextPanel, Text, Layout ) + QSK_SUBCONTROLS( IncrementPanel ) ///< Use this to style the increment button. + QSK_SUBCONTROLS( DecrementPanel ) ///< Use this to style the decrement button. + QSK_SUBCONTROLS( IncrementText ) ///< Use this to style the increment button's text. + QSK_SUBCONTROLS( DecrementText ) ///< Use this to style the decrement button's text. + QSK_SUBCONTROLS( TextPanel ) ///< Use this to style the text's panel. + QSK_SUBCONTROLS( Text ) ///< Use this to style the text (e.g. font role). + QSK_SUBCONTROLS( Layout ) ///< Use this to style the spinbox's controls layout. QSK_STATES( Pressed ) + /// @brief C-TOR + /// @param parent This object's parent explicit QskSpinBox( QQuickItem* parent = nullptr ); + + /// @brief D-TOR defaulted but required for std::unique_ptr ~QskSpinBox() override; + + /// @brief Getter for property focusIndex. + /// @returns Returns the currently focused subcontrol's index. + /// @retval Return FocusIndeces::None if no subcontrol is currently focused. FocusIndeces focusIndex() const; Q_SIGNALS: + /// @brief Emitted when the property @c focusIndex changed. void focusIndexChanged( int index ); private: diff --git a/src/controls/QskSpinBoxSkinlet.cpp b/src/controls/QskSpinBoxSkinlet.cpp index 15c2e1f2..6fcd9618 100644 --- a/src/controls/QskSpinBoxSkinlet.cpp +++ b/src/controls/QskSpinBoxSkinlet.cpp @@ -27,12 +27,13 @@ namespace QskSpinBoxSkinlet::QskSpinBoxSkinlet( QskSkin* ) { - setNodeRoles( { IncPanel, IncText, DecPanel, DecText, TextPanel, TextText } ); + setNodeRoles( + { IncrementPanel, IncrementText, DecrementPanel, DecrementText, TextPanel, TextText } ); } int QskSpinBoxSkinlet::sampleCount( const QskSkinnable*, QskAspect::Subcontrol ) const { - return Count; + return 1; } QRectF QskSpinBoxSkinlet::sampleRect( const QskSkinnable* const skinnable, const QRectF& rect, @@ -253,19 +254,19 @@ QSGNode* QskSpinBoxSkinlet::updateSubNode( const QskSkinnable* const skinnable, const quint8 nodeRole, QSGNode* const node ) const { using S = QskSpinBox; - if ( nodeRole == IncPanel ) + if ( nodeRole == IncrementPanel ) { return updateSeriesNode( skinnable, S::IncrementPanel, node ); } - if ( nodeRole == DecPanel ) + if ( nodeRole == DecrementPanel ) { return updateSeriesNode( skinnable, S::DecrementPanel, node ); } - if ( nodeRole == IncText ) + if ( nodeRole == IncrementText ) { return updateTextNode( skinnable, node, QStringLiteral( "+" ), S::IncrementText ); } - if ( nodeRole == DecText ) + if ( nodeRole == DecrementText ) { return updateTextNode( skinnable, node, QStringLiteral( "-" ), S::DecrementText ); } diff --git a/src/controls/QskSpinBoxSkinlet.h b/src/controls/QskSpinBoxSkinlet.h index 1013d942..dc506693 100644 --- a/src/controls/QskSpinBoxSkinlet.h +++ b/src/controls/QskSpinBoxSkinlet.h @@ -7,34 +7,105 @@ #include +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// @brief +/// This skinlet's purpose is to draw a QskSpinBox instance. +/// @details +/// In order to manage individual subcontrol states this skinlet uses subcontrol sampling. Although +/// it is most usefull when dealing with dynamic or large numbers of subcontrols, it is a strategy +/// to index the subcontrol in order to have individual states instead of one collective state on +/// the skinnable object. +/// @note The placement and dimensions of all subcontrols depend on the following subctrontrol +/// aspects: +/// - QskSpinBox::Layout's alignment hint ( which affects the positions of all controls ) +/// - QskSpinBox::Layout's spacing hint +/// - QskSpinBox::IncrementPanel's strut size hint +/// - QskSpinBox::DecrementPanel's strut size hint +/// - QskSpinBox::TextPanel's strut size hint +//////////////////////////////////////////////////////////////////////////////////////////////////// class QSK_EXPORT QskSpinBoxSkinlet : public QskSkinlet { Q_GADGET using Inherited = QskSkinlet; public: - enum NodeRole - { - IncPanel, - IncText, - DecPanel, - DecText, - TextPanel, - TextText, - RoleCount - }; + /// @brief C-TOR defining the correct node's role order (e.g. panel before text) Q_INVOKABLE QskSpinBoxSkinlet( QskSkin* = nullptr ); + /// @brief Roles for the subcontrols. + enum NodeRole + { + IncrementPanel, ///< Identifier for the increment button's panel. + IncrementText, ///< Identifier for the increment button's text. + DecrementPanel, ///< Identifier for the decrement button's panel. + DecrementText, ///< Identifier for the decrement button's text. + TextPanel, ///< Identifier for the text's panel. + TextText, ///< Identifier for the text's glyphs. + RoleCount ///< Number of all roles in this skinlet. + }; + protected: - int sampleCount( const QskSkinnable*, QskAspect::Subcontrol ) const override; - QRectF sampleRect( - const QskSkinnable*, const QRectF&, QskAspect::Subcontrol, int index ) const override; + /// @brief Getter for the number of samples in this skinlet. + /// @param skinnable The skinnable object. + /// @param subControl The skinnable object's subcontrol. + /// @returns Returns the number of samples. + /// @retval Returns 1 since each subcontrol a sample; + int sampleCount( + const QskSkinnable* skinnable, QskAspect::Subcontrol subControl ) const override; + + /// @brief Getter for a subcontrol's sample rectangle. + /// @param skinnable The skinnable object. + /// @param rect The skinnable object's content rectangle. + /// @param subControl The skinnable object's subcontrol. + /// @param index The skinnable object's subcontrol sample index. + /// @returns Returns the subcontrol's rectangle within the @p skinnable's content rectangle. + QRectF sampleRect( const QskSkinnable* skinnable, const QRectF& rect, + QskAspect::Subcontrol subControl, int index ) const override; + + /// @brief Getter for a subcontrol's sample states. + /// @param skinnable The skinnable object. + /// @param subControl The skinnable object's subcontrol. + /// @param index The skinnable object's subcontrol sample index. + /// @return Returns the states of the subcontrol's sample at the given @p index. + /// @details Sets or unsets the @c pressed, @c hovered, @c focused bits in the returned states + /// object. QskAspect::States sampleStates( const QskSkinnable* skinnable, QskAspect::Subcontrol subControl, int index ) const override; - QSizeF sizeHint( const QskSkinnable*, Qt::SizeHint, const QSizeF& ) const override; - QRectF subControlRect( - const QskSkinnable*, const QRectF&, QskAspect::Subcontrol ) const override; - QSGNode* updateSubNode( const QskSkinnable*, quint8 nodeRole, QSGNode* ) const override; + + /// @brief Getter for the skinnable object's size hints. + /// @param skinnable The skinnable object. + /// @param sizeHint The size hint. + /// @param rect The skinnable object's available rectangle. + /// @details Calculates the minimum, maximum and preferred size of the skinnable. + QSizeF sizeHint( + const QskSkinnable* skinnable, Qt::SizeHint sizeHint, const QSizeF& rect ) const override; + + /// @brief Getter for the subcontrol's rectangle. + /// @param skinnable The skinnable object. + /// @param rect The skinnable object's content rectangle. + /// @param subControl The skinnable object's subcontrol. + /// @returns Returns the subcontrol's rectangle in the skinnable's content rectangle. + QRectF subControlRect( const QskSkinnable* skinnable, const QRectF& rect, + QskAspect::Subcontrol subControl ) const override; + + /// @brief Updates the scene graph @p node for the given @p role + /// @param skinnable The skinnable object. + /// @param role The node's role number ( see: QskSpinBoxSkinlet::NodeRole ). + /// @param node The scene graph node for the given @p role. + /// @returns Returns a new or updated scene graph node for the given @p role. + /// @details This functions updates the text nodes and mediates updates for sampled + /// subcontrols to QskSpinBoxSkinlet::updateSampleNode. + /// @see QskSpinBoxSkinlet::NodeRole + QSGNode* updateSubNode( + const QskSkinnable* skinnable, quint8 role, QSGNode* node ) const override; + + /// @brief Updates the scene graph @p node for the given @p subControl's sample @p index + /// @param skinnable The skinnable object. + /// @param subControl The skinnable object's subcontrol. + /// @param index The skinnable object's subcontrol sample index. + /// @param node The scene graph node for the @p subControl's sample @p index. + /// @returns Returns a new or updated scene graph node for the given @p subControl's sample @p + /// index. QSGNode* updateSampleNode( const QskSkinnable* skinnable, QskAspect::Subcontrol subControl, int index, QSGNode* node ) const override; };