qskinny/src/dialogs/QskColorPickerSkinlet.cpp

182 lines
4.9 KiB
C++

/******************************************************************************
* QSkinny - Copyright (C) The authors
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "QskColorPickerSkinlet.h"
#include "QskColorPicker.h"
#include "QskSGNode.h"
#include "QskPaintedNode.h"
#include <QPainter>
using Q = QskColorPicker;
namespace
{
class ColorPaneNode : public QskPaintedNode
{
public:
ColorPaneNode()
{
}
void paint( QPainter* p, const QSize& size, const void* nodeData ) override
{
if( m_image.size() != size )
{
m_image = QImage( size.width(), size.height(), QImage::Format_RGB32 );
}
QColor color;
float h, s;
const float v = *reinterpret_cast< const int* >( nodeData ) / 255.0;
for( int x = 0; x < m_image.width(); x++ )
{
h = ( float ) x / m_image.width();
for( int y = 0; y < m_image.height(); y++ )
{
s = 1.0 - ( float ) y / m_image.height();
color.setHsvF( h, s, v );
m_image.setPixel( x, y, color.rgb() );
}
}
p->drawImage( QPointF( 0, 0 ), m_image );
}
void updateNode( QQuickWindow* window, const QRectF& rect, int value )
{
update( window, rect, QSizeF(), &value );
}
QColor selectedColor( const QPointF& p ) const
{
return m_image.pixelColor( p.toPoint() );
}
protected:
QskHashValue hash( const void* nodeData ) const override
{
const auto* value = reinterpret_cast< const int* >( nodeData );
return *value;
}
private:
QImage m_image;
};
}
class QskColorPickerSkinlet::PrivateData
{
public:
QColor selectedColor;
ColorPaneNode* colorPaneNode = nullptr;
};
QskColorPickerSkinlet::QskColorPickerSkinlet( QskSkin* skin )
: Inherited( skin )
, m_data( new PrivateData )
{
setNodeRoles( { PanelRole, ColorPaneRole, SelectorRole } );
}
QskColorPickerSkinlet::~QskColorPickerSkinlet() = default;
QSGNode* QskColorPickerSkinlet::updateSubNode(
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
{
const auto q = static_cast< const Q* >( skinnable );
switch ( nodeRole )
{
case PanelRole:
{
return updateBoxNode( skinnable, node, Q::Panel );
}
case ColorPaneRole:
{
return updateColorPaneNode( q, node );
}
case SelectorRole:
{
auto* n = updateBoxNode( skinnable, node, Q::Selector );
updateSelectedColor( q );
return n;
}
}
return Inherited::updateSubNode( skinnable, nodeRole, node );
}
QRectF QskColorPickerSkinlet::subControlRect(
const QskSkinnable* skinnable, const QRectF& contentsRect,
QskAspect::Subcontrol subControl ) const
{
const auto q = static_cast< const Q* >( skinnable );
if( subControl == Q::Panel || subControl == Q::ColorPane )
{
return contentsRect;
}
if( subControl == Q::Selector )
{
const auto size = q->strutSizeHint( Q::Selector );
const auto x = q->positionHint( Q::Selector | QskAspect::Horizontal );
const auto y = q->positionHint( Q::Selector | QskAspect::Vertical );
QRectF r( { x - size.width() / 2.0, y - size.height() / 2.0 }, size );
return r;
}
return Inherited::subControlRect( skinnable, contentsRect, subControl );
}
QColor QskColorPickerSkinlet::selectedColor() const
{
return m_data->selectedColor;
}
QSGNode* QskColorPickerSkinlet::updateColorPaneNode(
const QskColorPicker* q, QSGNode* node ) const
{
m_data->colorPaneNode = QskSGNode::ensureNode< ColorPaneNode >( node );
const auto rect = q->subControlRect( Q::ColorPane );
m_data->colorPaneNode->updateNode( q->window(), rect, q->value() );
updateSelectedColor( q );
return m_data->colorPaneNode;
}
QPointF QskColorPickerSkinlet::selectorPos( const Q* q ) const
{
const auto x = q->positionHint( Q::Selector | QskAspect::Horizontal );
const auto y = q->positionHint( Q::Selector | QskAspect::Vertical );
QPointF p( x, y );
const auto rect = q->subControlRect( Q::ColorPane );
p.rx() = qBound( rect.x(), p.x(), rect.right() );
p.ry() = qBound( rect.y(), p.y(), rect.bottom() );
return p;
}
void QskColorPickerSkinlet::updateSelectedColor( const Q* q ) const
{
const auto color = m_data->colorPaneNode->selectedColor( selectorPos( q ) );
m_data->selectedColor = color;
auto* e = new QEvent( static_cast< QEvent::Type >( q->colorChangedEventType() ) );
QCoreApplication::postEvent( const_cast< Q* >( q ), e );
}
#include "moc_QskColorPickerSkinlet.cpp"