Use proper sizes and positions

This commit is contained in:
Aleix Pol 2014-07-14 20:02:47 +02:00
parent f9d1bb3452
commit 83895d8e26
5 changed files with 106 additions and 63 deletions

View File

@ -24,12 +24,49 @@
#include <QSGTexture>
#include <QDebug>
#include <plasma/private/framesvg_p.h>
#include "svgtexturenode.h"
#include <cmath> //floor()
namespace Plasma
{
class FrameItemNode : public SVGTextureNode
{
public:
FrameItemNode(FrameSvgItem* frameSvg, FrameSvg::EnabledBorders borders, const QString& prefix)
: SVGTextureNode()
, m_frameSvg(frameSvg)
, m_border(borders)
{
setPrefix(prefix);
}
void setPrefix(const QString& prefix)
{
QString elementId = prefix % FrameSvgPrivate::borderToElementId(m_border);
QSize someSize = m_frameSvg->frameSvg()->elementSize(elementId);
QImage image = m_frameSvg->frameSvg()->image(someSize, elementId);
auto texture = m_frameSvg->window()->createTextureFromImage(image);
texture->setFiltering(QSGTexture::Nearest);
setTexture(texture);
}
void reposition(const QRect& geometry) {
FrameData* frameData = m_frameSvg->frameData();
QRect newGeometry = FrameSvgPrivate::sectionRect(frameData, m_border, geometry);
qDebug() << "repositioning" << newGeometry << m_border;
setRect(newGeometry);
}
private:
FrameSvgItem* m_frameSvg;
FrameSvg::EnabledBorders m_border;
};
FrameSvgItemMargins::FrameSvgItemMargins(Plasma::FrameSvg *frameSvg, QObject *parent)
: QObject(parent),
@ -271,15 +308,6 @@ Plasma::FrameSvg *FrameSvgItem::frameSvg() const
return m_frameSvg;
}
SVGTextureNode* FrameSvgItem::createNode(QImage image)
{
auto node = new SVGTextureNode;
auto texture = window()->createTextureFromImage(image);
texture->setFiltering(QSGTexture::Nearest);
node->setTexture(texture);
return node;
}
QSGNode *FrameSvgItem::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
{
if (!window() || !m_frameSvg || !m_frameSvg->hasElementPrefix(m_prefix)) {
@ -293,49 +321,28 @@ QSGNode *FrameSvgItem::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaint
//we're abusing transformOrigin enum here to get access to values
//these MUST be uploaded in the same order
auto topLeft = createNode(m_frameSvg->image(QSize(5,5), "topleft"));
oldNode->appendChildNode(topLeft);
auto top = createNode(m_frameSvg->image(QSize(5,5), "top"));
oldNode->appendChildNode(top);
auto topRight = createNode(m_frameSvg->image(QSize(5,5), "topright"));
oldNode->appendChildNode(topRight);
auto left = createNode(m_frameSvg->image(QSize(5,5), "left"));
oldNode->appendChildNode(left);
auto center = createNode(m_frameSvg->image(QSize(5,5), "center"));
oldNode->appendChildNode(center);
auto right = createNode(m_frameSvg->image(QSize(5,5), "right"));
oldNode->appendChildNode(right);
auto bottomLeft = createNode(m_frameSvg->image(QSize(5,5), "bottomleft"));
oldNode->appendChildNode(bottomLeft);
auto bottom = createNode(m_frameSvg->image(QSize(5,5), "bottom"));
oldNode->appendChildNode(bottom);
auto bottomRight = createNode(m_frameSvg->image(QSize(5,5), "bottomright"));
oldNode->appendChildNode(bottomRight);
oldNode->appendChildNode(new FrameItemNode(this, FrameSvg::TopBorder | FrameSvg::LeftBorder, m_prefix));
oldNode->appendChildNode(new FrameItemNode(this, FrameSvg::TopBorder | FrameSvg::RightBorder, m_prefix));
oldNode->appendChildNode(new FrameItemNode(this, FrameSvg::TopBorder, m_prefix));
oldNode->appendChildNode(new FrameItemNode(this, FrameSvg::BottomBorder, m_prefix));
oldNode->appendChildNode(new FrameItemNode(this, FrameSvg::BottomBorder | FrameSvg::LeftBorder, m_prefix));
oldNode->appendChildNode(new FrameItemNode(this, FrameSvg::BottomBorder | FrameSvg::RightBorder, m_prefix));
oldNode->appendChildNode(new FrameItemNode(this, FrameSvg::LeftBorder, m_prefix));
oldNode->appendChildNode(new FrameItemNode(this, FrameSvg::RightBorder, m_prefix));
oldNode->appendChildNode(new FrameItemNode(this, FrameSvg::NoBorder, m_prefix));
//set sizeDirty=true
}
//FIXME if (m_sizeDirty)
{
// QRect geometry = m_frameSvg->contentsRect().toRect();
QRect geometry = m_frameSvg->d->contentGeometry(frameData(), QSize(width(), height()));
//TODO cast root node add a convenience method on it?
static_cast<SVGTextureNode*>(oldNode->childAtIndex(Top))->setRect(5,0,width()-10, 5);
static_cast<SVGTextureNode*>(oldNode->childAtIndex(Left))->setRect(0,5, 5,height()-10);
static_cast<SVGTextureNode*>(oldNode->childAtIndex(Right))->setRect(width()-5,5,5,height()-10);
static_cast<SVGTextureNode*>(oldNode->childAtIndex(Bottom))->setRect(5,height()-5,width()-10,5);
static_cast<SVGTextureNode*>(oldNode->childAtIndex(TopLeft))->setRect(0,0,5,5);
static_cast<SVGTextureNode*>(oldNode->childAtIndex(TopRight))->setRect(width()-5,0,5,5);
static_cast<SVGTextureNode*>(oldNode->childAtIndex(BottomLeft))->setRect(0,height()-5, 5,5);
static_cast<SVGTextureNode*>(oldNode->childAtIndex(BottomRight))->setRect(width()-5,height()-5, 5, 5);
static_cast<SVGTextureNode*>(oldNode->childAtIndex(Center))->setRect(5,5, width()-10, height()-10);
for(int i = 0; i<oldNode->childCount(); ++i) {
FrameItemNode* it = static_cast<FrameItemNode*>(oldNode->childAtIndex(i));
it->reposition(geometry);
}
//TODO sizeDirty = false
@ -375,6 +382,11 @@ void FrameSvgItem::updateDevicePixelRatio()
m_textureChanged = true;
}
FrameData* FrameSvgItem::frameData() const
{
return m_frameSvg->d->frames.value(m_prefix);
}
} // Plasma namespace
#include "framesvgitem.moc"

View File

@ -31,6 +31,7 @@ namespace Plasma
{
class FrameSvg;
class FrameData;
class SVGTextureNode;
class FrameSvgItemMargins : public QObject
@ -167,6 +168,7 @@ public:
Q_INVOKABLE bool hasElementPrefix(const QString &prefix) const;
virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
FrameData* frameData() const;
protected:
virtual void componentComplete();
@ -183,7 +185,6 @@ private Q_SLOTS:
void updateDevicePixelRatio();
private:
SVGTextureNode *createNode(QImage image);
Plasma::FrameSvg *m_frameSvg;
FrameSvgItemMargins *m_margins;

View File

@ -816,19 +816,47 @@ void FrameSvgPrivate::generateFrameBackground(FrameData *frame)
QRect contentRect = contentGeometry(frame, size);
paintCenter(p, frame, contentRect.size(), size);
paintCorner(p, frame, FrameSvg::LeftBorder|FrameSvg::TopBorder, QRect(QPoint(0, 0), QSize(frame->leftWidth, frame->topHeight)));
paintCorner(p, frame, FrameSvg::RightBorder|FrameSvg::TopBorder, QRect(QPoint(contentRect.right(), 0), QSize(frame->rightWidth, frame->topHeight)));
paintCorner(p, frame, FrameSvg::LeftBorder|FrameSvg::BottomBorder, QRect(QPoint(0, contentRect.bottom()), QSize(frame->leftWidth, frame->bottomHeight)));
paintCorner(p, frame, FrameSvg::RightBorder|FrameSvg::BottomBorder, QRect(contentRect.bottomRight(), QSize(frame->rightWidth, frame->bottomHeight)));
paintCorner(p, frame, FrameSvg::LeftBorder|FrameSvg::TopBorder, contentRect);
paintCorner(p, frame, FrameSvg::RightBorder|FrameSvg::TopBorder, contentRect);
paintCorner(p, frame, FrameSvg::LeftBorder|FrameSvg::BottomBorder, contentRect);
paintCorner(p, frame, FrameSvg::RightBorder|FrameSvg::BottomBorder, contentRect);
// Sides
const int leftHeight = q->elementSize(prefix % "left").height();
paintBorder(p, frame, FrameSvg::LeftBorder, QSize(frame->leftWidth, leftHeight), QRect(QPoint(0, contentRect.top()), QSize(frame->leftWidth, contentRect.height())));
paintBorder(p, frame, FrameSvg::RightBorder, QSize(frame->rightWidth, leftHeight), QRect(contentRect.topRight(), QSize(frame->rightWidth, contentRect.height())));
paintBorder(p, frame, FrameSvg::LeftBorder, QSize(frame->leftWidth, leftHeight), contentRect);
paintBorder(p, frame, FrameSvg::RightBorder, QSize(frame->rightWidth, leftHeight), contentRect);
const int topWidth = q->elementSize(prefix % "top").width();
paintBorder(p, frame, FrameSvg::TopBorder, QSize(topWidth, frame->topHeight), QRect(QPoint(contentRect.left(), 0), QSize(contentRect.width(), frame->topHeight)));
paintBorder(p, frame, FrameSvg::BottomBorder, QSize(topWidth, frame->bottomHeight), QRect(contentRect.bottomLeft(), QSize(contentRect.width(), frame->bottomHeight)));
paintBorder(p, frame, FrameSvg::TopBorder, QSize(topWidth, frame->topHeight), contentRect);
paintBorder(p, frame, FrameSvg::BottomBorder, QSize(topWidth, frame->bottomHeight), contentRect);
}
QRect FrameSvgPrivate::sectionRect(FrameData* frame, Plasma::FrameSvg::EnabledBorders borders, const QRect& contentRect)
{
switch(borders) {
case FrameSvg::NoBorder:
return contentRect;
case FrameSvg::TopBorder:
return QRect(QPoint(contentRect.left(), 0), QSize(contentRect.width(), frame->topHeight));
case FrameSvg::BottomBorder:
return QRect(contentRect.bottomLeft(), QSize(contentRect.width(), frame->bottomHeight));
case FrameSvg::LeftBorder:
return QRect(QPoint(0, contentRect.top()), QSize(frame->leftWidth, contentRect.height()));
case FrameSvg::RightBorder:
return QRect(contentRect.topRight(), QSize(frame->rightWidth, contentRect.height()));
case FrameSvg::TopBorder | FrameSvg::LeftBorder:
return QRect(QPoint(0, 0), QSize(frame->leftWidth, frame->topHeight));
case FrameSvg::TopBorder | FrameSvg::RightBorder:
return QRect(QPoint(contentRect.right(), 0), QSize(frame->rightWidth, frame->topHeight));
case FrameSvg::BottomBorder | FrameSvg::LeftBorder:
return QRect(QPoint(0, contentRect.bottom()), QSize(frame->leftWidth, frame->bottomHeight));
case FrameSvg::BottomBorder | FrameSvg::RightBorder:
return QRect(contentRect.bottomRight(), QSize(frame->rightWidth, frame->bottomHeight));
default:
qWarning() << "unrecognized border" << borders;
return QRect();
}
return QRect();
}
QRect FrameSvgPrivate::contentGeometry(FrameData* frame, const QSize& size) const
@ -882,12 +910,12 @@ void FrameSvgPrivate::paintCenter(QPainter& p, FrameData* frame, const QSize& co
}
}
void FrameSvgPrivate::paintBorder(QPainter& p, FrameData* frame, const FrameSvg::EnabledBorders borders, const QSize& size, const QRect& output) const
void FrameSvgPrivate::paintBorder(QPainter& p, FrameData* frame, const FrameSvg::EnabledBorders borders, const QSize& size, const QRect& contentRect) const
{
QString side = prefix % borderToElementId(borders);
if (frame->enabledBorders & borders && q->hasElement(side) && !size.isEmpty()) {
if (frame->stretchBorders) {
q->paint(&p, output, side);
q->paint(&p, sectionRect(frame, borders, contentRect), side);
} else {
QPixmap px(size);
px.fill(Qt::transparent);
@ -896,16 +924,16 @@ void FrameSvgPrivate::paintBorder(QPainter& p, FrameData* frame, const FrameSvg:
sidePainter.setCompositionMode(QPainter::CompositionMode_Source);
q->paint(&sidePainter, QRect(QPoint(0, 0), size), side);
p.drawTiledPixmap(output, px);
p.drawTiledPixmap(sectionRect(frame, borders, contentRect), px);
}
}
}
void FrameSvgPrivate::paintCorner(QPainter& p, FrameData* frame, Plasma::FrameSvg::EnabledBorders border, const QRect& output) const
void FrameSvgPrivate::paintCorner(QPainter& p, FrameData* frame, Plasma::FrameSvg::EnabledBorders border, const QRect& contentRect) const
{
QString corner = prefix % borderToElementId(border);
if (frame->enabledBorders & border && q->hasElement(corner)) {
q->paint(&p, output, corner);
q->paint(&p, sectionRect(frame, border, contentRect), corner);
}
}
@ -913,7 +941,7 @@ QString FrameSvgPrivate::borderToElementId(FrameSvg::EnabledBorders borders)
{
switch(borders) {
case FrameSvg::NoBorder:
return QString();
return QStringLiteral("center");
case FrameSvg::TopBorder:
return QStringLiteral("top");
case FrameSvg::BottomBorder:

View File

@ -287,9 +287,10 @@ public:
*/
Q_INVOKABLE void paintFrame(QPainter *painter, const QPointF &pos = QPointF(0, 0));
private:
protected:
FrameSvgPrivate *const d;
friend class FrameData;
friend class FrameSvgItem;
Q_PRIVATE_SLOT(d, void updateSizes())
Q_PRIVATE_SLOT(d, void updateNeeded())

View File

@ -32,7 +32,7 @@
namespace Plasma
{
class FrameData
class PLASMA_EXPORT FrameData
{
public:
FrameData(FrameSvg *svg, const QString &p)
@ -126,7 +126,7 @@ public:
QHash<FrameSvg *, int> references;
};
class FrameSvgPrivate
class PLASMA_EXPORT FrameSvgPrivate
{
public:
FrameSvgPrivate(FrameSvg *psvg)
@ -152,6 +152,7 @@ public:
void paintCorner(QPainter& p, FrameData* frame, Plasma::FrameSvg::EnabledBorders border, const QRect& output) const;
void paintCenter(QPainter& p, FrameData* frame, const QSize& contentSize, const QSize& fullSize);
static QString borderToElementId(Plasma::FrameSvg::EnabledBorders borders);
static QRect sectionRect(FrameData* frame, Plasma::FrameSvg::EnabledBorders borders, const QRect& contentRect);
QRect contentGeometry(FrameData* frame, const QSize& size) const;
Types::Location location;