248 lines
5.8 KiB
C++
248 lines
5.8 KiB
C++
|
#include "fgcanvasgroup.h"
|
||
|
|
||
|
#include <QDebug>
|
||
|
|
||
|
#include "canvasitem.h"
|
||
|
#include "localprop.h"
|
||
|
#include "fgcanvaspaintcontext.h"
|
||
|
#include "fgcanvaspath.h"
|
||
|
#include "fgcanvastext.h"
|
||
|
#include "fgqcanvasmap.h"
|
||
|
#include "fgqcanvasimage.h"
|
||
|
|
||
|
class ChildOrderingFunction
|
||
|
{
|
||
|
public:
|
||
|
bool operator()(const FGCanvasElement* a, FGCanvasElement* b)
|
||
|
{
|
||
|
if (a->zIndex() == b->zIndex()) {
|
||
|
// use prop node positions in the parent
|
||
|
return a->property()->position() < b->property()->position();
|
||
|
}
|
||
|
|
||
|
return a->zIndex() < b->zIndex();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
FGCanvasGroup::FGCanvasGroup(FGCanvasGroup* pr, LocalProp* prop) :
|
||
|
FGCanvasElement(pr, prop)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
const FGCanvasElementVec &FGCanvasGroup::children() const
|
||
|
{
|
||
|
return _children;
|
||
|
}
|
||
|
|
||
|
void FGCanvasGroup::markChildZIndicesDirty() const
|
||
|
{
|
||
|
_zIndicesDirty = true;
|
||
|
}
|
||
|
|
||
|
bool FGCanvasGroup::hasChilden() const
|
||
|
{
|
||
|
return !_children.empty();
|
||
|
}
|
||
|
|
||
|
unsigned int FGCanvasGroup::childCount() const
|
||
|
{
|
||
|
return _children.size();
|
||
|
}
|
||
|
|
||
|
FGCanvasElement *FGCanvasGroup::childAt(unsigned int index) const
|
||
|
{
|
||
|
return _children.at(index);
|
||
|
}
|
||
|
|
||
|
unsigned int FGCanvasGroup::indexOfChild(const FGCanvasElement *e) const
|
||
|
{
|
||
|
auto it = std::find(_children.begin(), _children.end(), e);
|
||
|
if (it == _children.end()) {
|
||
|
qWarning() << Q_FUNC_INFO << "not found";
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return std::distance(_children.begin(), it);
|
||
|
}
|
||
|
|
||
|
CanvasItem *FGCanvasGroup::createQuickItem(QQuickItem *parent)
|
||
|
{
|
||
|
_quick = new CanvasItem(parent);
|
||
|
|
||
|
for (auto e : _children) {
|
||
|
e->createQuickItem(_quick);
|
||
|
}
|
||
|
|
||
|
return _quick;
|
||
|
}
|
||
|
|
||
|
void FGCanvasGroup::doPaint(FGCanvasPaintContext *context) const
|
||
|
{
|
||
|
for (FGCanvasElement* element : _children) {
|
||
|
element->paint(context);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void FGCanvasGroup::doPolish()
|
||
|
{
|
||
|
if (_cachedSymbolDirty) {
|
||
|
qDebug() << _propertyRoot->path() << "should use symbol cache:" << _propertyRoot->value("symbol-type", QVariant()).toByteArray();
|
||
|
_cachedSymbolDirty = false;
|
||
|
}
|
||
|
|
||
|
if (_zIndicesDirty) {
|
||
|
std::sort(_children.begin(), _children.end(), ChildOrderingFunction());
|
||
|
_zIndicesDirty = false;
|
||
|
resetChildQuickItemZValues();
|
||
|
}
|
||
|
|
||
|
for (FGCanvasElement* element : _children) {
|
||
|
element->polish();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void FGCanvasGroup::resetChildQuickItemZValues()
|
||
|
{
|
||
|
int counter = 0;
|
||
|
for (auto e : _children) {
|
||
|
auto qq = e->quickItem();
|
||
|
if (qq) {
|
||
|
qq->setZ(counter++);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool FGCanvasGroup::onChildAdded(LocalProp *prop)
|
||
|
{
|
||
|
const bool isRootGroup = (_parent == nullptr);
|
||
|
int newChildCount = 0;
|
||
|
|
||
|
if (FGCanvasElement::onChildAdded(prop)) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
const QByteArray nm = prop->name();
|
||
|
if (nm == "group") {
|
||
|
_children.push_back(new FGCanvasGroup(this, prop));
|
||
|
newChildCount++;
|
||
|
} else if (nm == "path") {
|
||
|
_children.push_back(new FGCanvasPath(this, prop));
|
||
|
newChildCount++;
|
||
|
} else if (nm == "text") {
|
||
|
_children.push_back(new FGCanvasText(this, prop));
|
||
|
newChildCount++;
|
||
|
} else if (nm == "image") {
|
||
|
_children.push_back(new FGQCanvasImage(this, prop));
|
||
|
newChildCount++;
|
||
|
} else if (nm == "map") {
|
||
|
_children.push_back(new FGQCanvasMap(this, prop));
|
||
|
newChildCount++;
|
||
|
} else if (nm == "symbol-type") {
|
||
|
connect(prop, &LocalProp::valueChanged, this, &FGCanvasGroup::markCachedSymbolDirty);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (isRootGroup) {
|
||
|
// ignore all of these, handled by the enclosing canvas view
|
||
|
if (nm == "size") {
|
||
|
connect(prop, &LocalProp::valueChanged, this, &FGCanvasGroup::canvasSizeChanged);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if ((nm == "view") || nm.startsWith("status") || (nm == "name") || (nm == "mipmapping") || (nm == "placement")) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (newChildCount > 0) {
|
||
|
markChildZIndicesDirty();
|
||
|
|
||
|
if (_quick) {
|
||
|
_children.back()->createQuickItem(_quick);
|
||
|
}
|
||
|
|
||
|
emit childAdded();
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
qDebug() << "saw unknown group child" << prop->name();
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool FGCanvasGroup::onChildRemoved(LocalProp *prop)
|
||
|
{
|
||
|
if (FGCanvasElement::onChildRemoved(prop)) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
const QByteArray nm = prop->name();
|
||
|
if ((nm == "group") || (nm == "image") || (nm == "path") || (nm == "text") || (nm == "map")) {
|
||
|
int removedChildIndex = indexOfChildWithProp(prop);
|
||
|
if (removedChildIndex >= 0) {
|
||
|
auto it = _children.begin() + removedChildIndex;
|
||
|
delete *it;
|
||
|
_children.erase(it);
|
||
|
emit childRemoved(removedChildIndex);
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void FGCanvasGroup::removeChild(FGCanvasElement *child)
|
||
|
{
|
||
|
auto it = std::find(_children.begin(), _children.end(), child);
|
||
|
if (it != _children.end()) {
|
||
|
int index = std::distance(_children.begin(), it);
|
||
|
_children.erase(it);
|
||
|
emit childRemoved(index);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void FGCanvasGroup::dumpElement()
|
||
|
{
|
||
|
qDebug() << "Group at" << _propertyRoot->path();
|
||
|
for (auto c : _children) {
|
||
|
c->dumpElement();
|
||
|
}
|
||
|
qDebug() << "End-group at" << _propertyRoot->path();
|
||
|
}
|
||
|
|
||
|
int FGCanvasGroup::indexOfChildWithProp(LocalProp* prop) const
|
||
|
{
|
||
|
auto it = std::find_if(_children.begin(), _children.end(), [prop](FGCanvasElement* child)
|
||
|
{
|
||
|
return (child->property() == prop);
|
||
|
});
|
||
|
|
||
|
if (it == _children.end()) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return std::distance(_children.begin(), it);
|
||
|
}
|
||
|
|
||
|
void FGCanvasGroup::markStyleDirty()
|
||
|
{
|
||
|
for (FGCanvasElement* element : _children) {
|
||
|
element->markStyleDirty();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void FGCanvasGroup::doDestroy()
|
||
|
{
|
||
|
delete _quick;
|
||
|
|
||
|
FGCanvasElementVec children = std::move(_children);
|
||
|
_children.clear();
|
||
|
for (auto c : children) {
|
||
|
delete c;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void FGCanvasGroup::markCachedSymbolDirty()
|
||
|
{
|
||
|
_cachedSymbolDirty = true;
|
||
|
}
|