You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
576 lines
22 KiB
C++
576 lines
22 KiB
C++
/**
|
|
* wWidgets - Lightweight UI Toolkit.
|
|
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
|
|
* Alexander Kotliar <alexander.kotliar@gmail.com>
|
|
*
|
|
* This code is distributed under the MIT License:
|
|
* http://www.opensource.org/licenses/MIT
|
|
*/
|
|
// Modifications copyright Amazon.com, Inc. or its affiliates.
|
|
|
|
#pragma once
|
|
|
|
#if !defined(Q_MOC_RUN)
|
|
#include <typeinfo>
|
|
#include <algorithm>
|
|
#include "Serialization/Serializer.h"
|
|
#include "Serialization/StringList.h"
|
|
#include <Serialization/Pointers.h>
|
|
#include "Factory.h"
|
|
#include "ConstStringList.h"
|
|
#include "Strings.h"
|
|
#include "../EditorCommonAPI.h"
|
|
#include "Serialization/ClassFactory.h"
|
|
|
|
#include <QObject>
|
|
#include <QPoint>
|
|
#include <QRect>
|
|
#include <QCursor>
|
|
#endif
|
|
|
|
namespace Serialization { struct ICallback; }
|
|
|
|
class QWidget;
|
|
class QFont;
|
|
class QPainter;
|
|
class QMenu;
|
|
class QKeyEvent;
|
|
|
|
using std::vector;
|
|
class QPropertyTree;
|
|
class PropertyRow;
|
|
class PropertyTreeModel;
|
|
class PopupMenuItem;
|
|
struct PropertyDrawContext;
|
|
struct EDITOR_COMMON_API ContainerMenuHandler;
|
|
class PropertyRowContainer;
|
|
|
|
enum ScanResult {
|
|
SCAN_FINISHED,
|
|
SCAN_CHILDREN,
|
|
SCAN_SIBLINGS,
|
|
SCAN_CHILDREN_SIBLINGS,
|
|
};
|
|
|
|
struct EDITOR_COMMON_API PropertyRowMenuHandler : QObject
|
|
{
|
|
public:
|
|
virtual ~PropertyRowMenuHandler() {}
|
|
|
|
};
|
|
|
|
struct PropertyActivationEvent
|
|
{
|
|
enum Reason
|
|
{
|
|
REASON_PRESS,
|
|
REASON_RELEASE,
|
|
REASON_DOUBLECLICK,
|
|
REASON_KEYBOARD,
|
|
REASON_NEW_ELEMENT
|
|
};
|
|
|
|
QPropertyTree* tree;
|
|
Reason reason;
|
|
bool force;
|
|
QPoint clickPoint;
|
|
|
|
PropertyActivationEvent()
|
|
: force(false)
|
|
, clickPoint(0, 0)
|
|
, tree(0)
|
|
, reason(REASON_PRESS)
|
|
{
|
|
}
|
|
};
|
|
|
|
struct PropertyDragEvent
|
|
{
|
|
QPropertyTree* tree;
|
|
QPoint pos;
|
|
QPoint start;
|
|
QPoint lastDelta;
|
|
QPoint totalDelta;
|
|
};
|
|
|
|
struct PropertyHoverInfo
|
|
{
|
|
QCursor cursor;
|
|
QString toolTip;
|
|
|
|
PropertyHoverInfo()
|
|
: cursor()
|
|
{
|
|
}
|
|
};
|
|
|
|
enum DragCheckBegin {
|
|
DRAG_CHECK_IGNORE,
|
|
DRAG_CHECK_SET,
|
|
DRAG_CHECK_UNSET
|
|
};
|
|
|
|
class PropertyRowWidget : public QObject
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
PropertyRowWidget(PropertyRow* row, QPropertyTree* tree);
|
|
virtual ~PropertyRowWidget();
|
|
virtual QWidget* actualWidget() { return 0; }
|
|
virtual void showPopup() {}
|
|
virtual void commit() = 0;
|
|
PropertyRow* row() { return row_; }
|
|
PropertyTreeModel* model() { return model_; }
|
|
protected:
|
|
PropertyRow* row_;
|
|
QPropertyTree* tree_;
|
|
PropertyTreeModel* model_;
|
|
};
|
|
|
|
class PropertyTreeTransaction;
|
|
|
|
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
|
class EDITOR_COMMON_API PropertyRow : public Serialization::RefCounter
|
|
{
|
|
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
|
public:
|
|
enum WidgetPlacement {
|
|
WIDGET_NONE,
|
|
WIDGET_ICON,
|
|
WIDGET_AFTER_NAME,
|
|
WIDGET_VALUE,
|
|
WIDGET_AFTER_PULLED,
|
|
WIDGET_INSTEAD_OF_TEXT
|
|
};
|
|
|
|
typedef std::vector< Serialization::SharedPtr<PropertyRow> > Rows;
|
|
typedef Rows::iterator iterator;
|
|
typedef Rows::const_iterator const_iterator;
|
|
|
|
PropertyRow();
|
|
virtual ~PropertyRow();
|
|
|
|
void setNames(const char* name, const char* label, const char* typeName);
|
|
|
|
bool selected() const{ return selected_; }
|
|
void setSelected(bool selected) { selected_ = selected; }
|
|
bool expanded() const{ return expanded_; }
|
|
void _setExpanded(bool expanded); // use QPropertyTree::expandRow
|
|
void setExpandedRecursive(QPropertyTree* tree, bool expanded);
|
|
|
|
void setMatchFilter(bool matchFilter) { matchFilter_ = matchFilter; }
|
|
bool matchFilter() const { return matchFilter_; }
|
|
|
|
void setBelongsToFilteredRow(bool belongs) { belongsToFilteredRow_ = belongs; }
|
|
bool belongsToFilteredRow() const { return belongsToFilteredRow_; }
|
|
|
|
bool visible(const QPropertyTree* tree) const;
|
|
bool hasVisibleChildren(const QPropertyTree* tree, bool internalCall = false) const;
|
|
|
|
const PropertyRow* hit(const QPropertyTree* tree, QPoint point) const;
|
|
PropertyRow* hit(const QPropertyTree* tree, QPoint point);
|
|
PropertyRow* parent() { return parent_; }
|
|
const PropertyRow* parent() const{ return parent_; }
|
|
void setParent(PropertyRow* row) { parent_ = row; }
|
|
bool isRoot() const { return !parent_; }
|
|
int level() const;
|
|
|
|
void add(PropertyRow* row);
|
|
void addAfter(PropertyRow* row, PropertyRow* after);
|
|
void addBefore(PropertyRow* row, PropertyRow* before);
|
|
|
|
template<class Op> bool scanChildren(Op& op);
|
|
template<class Op> bool scanChildren(Op& op, QPropertyTree* tree);
|
|
template<class Op> bool scanChildrenReverse(Op& op, QPropertyTree* tree);
|
|
template<class Op> bool scanChildrenBottomUp(Op& op, QPropertyTree* tree);
|
|
|
|
PropertyRow* childByIndex(int index);
|
|
const PropertyRow* childByIndex(int index) const;
|
|
int childIndex(const PropertyRow* row) const;
|
|
bool isChildOf(const PropertyRow* row) const;
|
|
|
|
bool empty() const{ return children_.empty(); }
|
|
iterator find(PropertyRow* row) { return std::find(children_.begin(), children_.end(), row); }
|
|
PropertyRow* findFromIndex(int* outIndex, const char* name, const char* typeName, int startIndex) const;
|
|
PropertyRow* findByAddress(const void* handle);
|
|
virtual const void* searchHandle() const;
|
|
iterator begin() { return children_.begin(); }
|
|
iterator end() { return children_.end(); }
|
|
const_iterator begin() const{ return children_.begin(); }
|
|
const_iterator end() const{ return children_.end(); }
|
|
std::size_t count() const{ return children_.size(); }
|
|
iterator erase(iterator it){ return children_.erase(it); }
|
|
void clear(){ children_.clear(); }
|
|
void erase(PropertyRow* row);
|
|
void swapChildren(PropertyRow* row, PropertyTreeModel* model);
|
|
|
|
void assignRowState(const PropertyRow& row, bool recurse);
|
|
void assignRowProperties(PropertyRow* row);
|
|
void replaceAndPreserveState(PropertyRow* oldRow, PropertyRow* newRow, PropertyTreeModel* model);
|
|
|
|
const char* name() const{ return name_; }
|
|
void setName(const char* name) { name_ = name; }
|
|
const char* label() const { return label_; }
|
|
const char* labelUndecorated() const { return labelUndecorated_; }
|
|
void setLabel(const char* label);
|
|
void setLabelChanged();
|
|
void setTooltip(const char* tooltip);
|
|
bool setValidatorEntry(int index, int count);
|
|
int validatorCount() const{ return validatorCount_; }
|
|
int validatorIndex() const{ return validatorIndex_; }
|
|
void resetValidatorIcons();
|
|
void addValidatorIcons(bool hasWarnings, bool hasErrors);
|
|
const char* tooltip() const { return tooltip_; }
|
|
void setLayoutChanged();
|
|
void setLabelChangedToChildren();
|
|
void setLayoutChangedToChildren();
|
|
void setHideChildren(bool hideChildren) { hideChildren_ = hideChildren; }
|
|
bool hideChildren() const { return hideChildren_; }
|
|
void updateLabel(const QPropertyTree* tree, int index, bool parentHidesNonInlineChildren);
|
|
void updateTextSizeInitial(const QPropertyTree* tree, int index, bool force);
|
|
virtual void labelChanged() {}
|
|
void parseControlCodes(const QPropertyTree* tree, const char* label, bool changeLabel);
|
|
const char* typeName() const{ return typeName_; }
|
|
virtual const char* typeNameForFilter(QPropertyTree* tree) const;
|
|
void setTypeName(const char* typeName) { typeName_ = typeName; }
|
|
const char* rowText(char* containerLabelBuffer, size_t bufsiz, const QPropertyTree* tree, int rowIndex) const;
|
|
|
|
PropertyRow* findSelected();
|
|
PropertyRow* find(const char* name, const char* nameAlt, const char* typeName);
|
|
const PropertyRow* find(const char* name, const char* nameAlt, const char* typeName) const;
|
|
void intersect(const PropertyRow* row);
|
|
|
|
int verticalIndex(QPropertyTree* tree, PropertyRow* row);
|
|
PropertyRow* rowByVerticalIndex(QPropertyTree* tree, int index);
|
|
int horizontalIndex(QPropertyTree* tree, PropertyRow* row);
|
|
PropertyRow* rowByHorizontalIndex(QPropertyTree* tree, int index);
|
|
|
|
virtual bool assignToPrimitive([[maybe_unused]] void* object, [[maybe_unused]] size_t size) const{ return false; }
|
|
virtual bool assignTo([[maybe_unused]] const Serialization::SStruct& ser) const{ return false; }
|
|
virtual bool assignToByPointer(void* instance, const Serialization::TypeID& type) const{ return assignTo(Serialization::SStruct(type, instance, type.sizeOf(), 0)); }
|
|
virtual void setValueAndContext(const Serialization::SStruct& ser, [[maybe_unused]] Serialization::IArchive& ar) { serializer_ = ser; }
|
|
virtual void handleChildrenChange() {}
|
|
virtual string valueAsString() const;
|
|
virtual wstring valueAsWString() const;
|
|
|
|
int height() const{ return size_.y(); }
|
|
|
|
virtual int widgetSizeMin(const QPropertyTree*) const { return userWidgetSize() >= 0 ? userWidgetSize() : 0; }
|
|
virtual int floorHeight() const{ return 0; }
|
|
|
|
void calcPulledRows(int* minTextSize, int* freePulledChildren, int* minimalWidth, const QPropertyTree* tree, int index);
|
|
void calculateMinimalSize(const QPropertyTree* tree, int posX, int availableWidth, bool force, int* extraSizeRemainder, int* _extraSize, int index);
|
|
void setTextSize(const QPropertyTree* tree, int rowIndex, float multiplier);
|
|
void calculateTotalSizes(int* minTextSize);
|
|
void adjustVerticalPosition(const QPropertyTree* tree, int& totalHeight);
|
|
|
|
virtual bool isWidgetFixed() const{ return userFixedWidget_ || (widgetPlacement() != WIDGET_VALUE && widgetPlacement() != WIDGET_INSTEAD_OF_TEXT); }
|
|
|
|
virtual WidgetPlacement widgetPlacement() const{ return WIDGET_NONE; }
|
|
|
|
QRect rect() const{ return QRect(pos_.x(), pos_.y(), size_.x(), size_.y()); }
|
|
QRect rectIncludingChildren(const QPropertyTree* tree) const;
|
|
QRect textRect(const QPropertyTree* tree) const;
|
|
QRect widgetRect(const QPropertyTree* tree) const;
|
|
QRect plusRect(const QPropertyTree* tree) const;
|
|
QRect floorRect(const QPropertyTree* tree) const;
|
|
QRect validatorRect(const QPropertyTree* tree) const;
|
|
QRect validatorWarningIconRect(const QPropertyTree* tree) const;
|
|
QRect validatorErrorIconRect(const QPropertyTree* tree) const;
|
|
void adjustHoveredRect(QRect& hoveredRect);
|
|
int heightIncludingChildren() const{ return heightIncludingChildren_; }
|
|
const QFont* rowFont(const QPropertyTree* tree) const;
|
|
|
|
void drawRow(QPainter& painter, const QPropertyTree* tree, int rowIndex, bool selectionPass);
|
|
void drawPlus(QPainter& p, const QPropertyTree* tree, const QRect& rect, bool expanded, bool selected, bool grayed) const;
|
|
void drawStaticText(QPainter& p, const QRect& widgetRect);
|
|
|
|
virtual void redraw(const PropertyDrawContext& context);
|
|
virtual PropertyRowWidget* createWidget([[maybe_unused]] QPropertyTree* tree) { return 0; }
|
|
|
|
virtual bool isContainer() const{ return false; }
|
|
virtual bool isPointer() const{ return false; }
|
|
virtual bool isObject() const{ return false; }
|
|
|
|
virtual bool isLeaf() const{ return false; }
|
|
virtual void closeNonLeaf([[maybe_unused]] const Serialization::SStruct& ser, [[maybe_unused]] Serialization::IArchive& ar) {}
|
|
virtual bool isStatic() const{ return pulledContainer_ == 0; }
|
|
virtual bool isSelectable() const{ return (!userReadOnly() && !userReadOnlyRecurse()) || (!pulledUp() && !pulledBefore()); }
|
|
virtual bool activateOnAdd() const{ return false; }
|
|
virtual bool inlineInShortArrays() const{ return false; }
|
|
|
|
bool canBeToggled(const QPropertyTree* tree) const;
|
|
bool canBeDragged() const;
|
|
bool canBeDroppedOn(const PropertyRow* parentRow, const PropertyRow* beforeChild, const QPropertyTree* tree) const;
|
|
void dropInto(PropertyRow* parentRow, PropertyRow* cursorRow, QPropertyTree* tree, bool before);
|
|
virtual bool getHoverInfo(PropertyHoverInfo* hit, [[maybe_unused]] const QPoint& cursorPos, [[maybe_unused]] const QPropertyTree* tree) const {
|
|
hit->toolTip = QString::fromUtf8(tooltip_);
|
|
return true;
|
|
}
|
|
|
|
virtual bool onActivate(const PropertyActivationEvent& e);
|
|
virtual bool processesKey(QPropertyTree* tree, const QKeyEvent* ev); // returns true if it wants to process key events; otherwise, they will get processed by shortcuts in some cases, like delete
|
|
virtual bool onKeyDown(QPropertyTree* tree, const QKeyEvent* ev);
|
|
virtual bool onMouseDown([[maybe_unused]] QPropertyTree* tree, [[maybe_unused]] QPoint point, [[maybe_unused]] bool& changed) { return false; }
|
|
virtual void onMouseDrag([[maybe_unused]] const PropertyDragEvent& e) {}
|
|
virtual void onMouseStill([[maybe_unused]] const PropertyDragEvent& e) {}
|
|
virtual void onMouseUp([[maybe_unused]] QPropertyTree* tree, [[maybe_unused]] QPoint point) {}
|
|
// "drag check" allows you to "paint" with the mouse through checkboxes to set all values at once
|
|
virtual DragCheckBegin onMouseDragCheckBegin() { return DRAG_CHECK_IGNORE; }
|
|
virtual bool onMouseDragCheck([[maybe_unused]] QPropertyTree* tree, [[maybe_unused]] bool value) { return false; }
|
|
virtual bool onContextMenu(QMenu &menu, QPropertyTree* tree);
|
|
virtual ContainerMenuHandler* createMenuHandler(QPropertyTree* tree, PropertyRowContainer* container);
|
|
|
|
virtual bool isFullRow(const QPropertyTree* tree) const;
|
|
|
|
// User states.
|
|
// Assigned using control codes (characters in the beginning of label)
|
|
// fixed widget doesn't expand automatically to occupy all available place
|
|
bool userFixedWidget() const{ return userFixedWidget_; }
|
|
bool userFullRow() const { return userFullRow_; }
|
|
void setUserReadOnly(bool userReadOnly) { userReadOnly_ = userReadOnly; }
|
|
virtual bool userReadOnly() const { return userReadOnly_; }
|
|
void propagateFlagsTopToBottom();
|
|
virtual bool userReadOnlyRecurse() const { return userReadOnlyRecurse_; }
|
|
bool userWidgetToContent() const { return userWidgetToContent_; }
|
|
int userWidgetSize() const{ return userWidgetSize_; }
|
|
bool userNonCopyable() const { return userNonCopyable_; }
|
|
|
|
// multiValue is used to edit properties of multiple objects simulateneously
|
|
bool multiValue() const { return multiValue_; }
|
|
void setMultiValue(bool multiValue) { multiValue_ = multiValue; }
|
|
|
|
// pulledRow - is the one that is pulled up to the parents row
|
|
// (created with ^ in the beginning of label)
|
|
bool pulledUp() const { return pulledUp_; }
|
|
bool pulledBefore() const { return pulledBefore_; }
|
|
bool hasPulled() const { return hasPulled_; }
|
|
bool packedAfterPreviousRow() const { return packedAfterPreviousRow_; }
|
|
bool pulledSelected() const;
|
|
PropertyRow* nonPulledParent();
|
|
void setPulledContainer(PropertyRow* container){ pulledContainer_ = container; }
|
|
PropertyRow* pulledContainer() { return pulledContainer_; }
|
|
const PropertyRow* pulledContainer() const{ return pulledContainer_; }
|
|
|
|
Serialization::SharedPtr<PropertyRow> clone(ConstStringList* constStrings) const;
|
|
|
|
Serialization::SStruct serializer() const{ return serializer_; }
|
|
virtual Serialization::TypeID typeId() const{ return serializer_.type(); }
|
|
void setSerializer(const Serialization::SStruct& ser) { serializer_ = ser; }
|
|
virtual void serializeValue([[maybe_unused]] Serialization::IArchive& ar) {}
|
|
void setCallback(Serialization::ICallback* callback);
|
|
Serialization::ICallback* callback() { return callback_; }
|
|
virtual void Serialize(Serialization::IArchive& ar);
|
|
|
|
static void setConstStrings(ConstStringList* constStrings){ constStrings_ = constStrings; }
|
|
|
|
protected:
|
|
void init(const char* name, const char* nameAlt, const char* typeName);
|
|
PropertyRow* findChildFromDescendant(PropertyRow* row) const;
|
|
|
|
virtual void overrideTextColor([[maybe_unused]] QColor& textColor) {}
|
|
|
|
const char* name_;
|
|
const char* label_;
|
|
const char* labelUndecorated_;
|
|
const char* typeName_;
|
|
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
|
Serialization::SStruct serializer_;
|
|
PropertyRow* parent_;
|
|
Serialization::ICallback* callback_;
|
|
const char* tooltip_;
|
|
Rows children_;
|
|
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
|
|
|
unsigned int textHash_;
|
|
|
|
// do we really need QPoint here?
|
|
QPoint pos_;
|
|
QPoint size_;
|
|
short int textPos_;
|
|
short int textSizeInitial_;
|
|
short int textSize_;
|
|
short int widgetPos_; // widget == icon!
|
|
short int widgetSize_;
|
|
short int userWidgetSize_;
|
|
unsigned short heightIncludingChildren_;
|
|
unsigned short validatorIndex_;
|
|
unsigned short validatorsHeight_;
|
|
unsigned char validatorCount_;
|
|
unsigned char plusSize_;
|
|
bool visible_ : 1;
|
|
bool matchFilter_ : 1;
|
|
bool belongsToFilteredRow_ : 1;
|
|
bool expanded_ : 1;
|
|
bool selected_ : 1;
|
|
bool labelChanged_ : 1;
|
|
bool layoutChanged_ : 1;
|
|
bool userReadOnly_ : 1;
|
|
bool userReadOnlyRecurse_ : 1;
|
|
bool userFixedWidget_ : 1;
|
|
bool userFullRow_ : 1;
|
|
bool userPackCheckboxes_ : 1;
|
|
bool userWidgetToContent_ : 1;
|
|
bool pulledUp_ : 1;
|
|
bool pulledBefore_ : 1;
|
|
bool packedAfterPreviousRow_ : 1;
|
|
bool hasPulled_ : 1;
|
|
bool multiValue_ : 1;
|
|
bool hideChildren_ : 1;
|
|
bool validatorHasErrors_ : 1;
|
|
bool validatorHasWarnings_ : 1;
|
|
bool userNonCopyable_ : 1;
|
|
enum class FontWeight
|
|
{
|
|
Undefined,
|
|
Bold,
|
|
Regular
|
|
};
|
|
FontWeight fontWeight_;
|
|
|
|
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
|
Serialization::SharedPtr<PropertyRow> pulledContainer_;
|
|
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
|
static ConstStringList* constStrings_;
|
|
friend class PropertyOArchive;
|
|
friend class PropertyIArchive;
|
|
};
|
|
|
|
inline unsigned int calculateHash(const char* str, unsigned hash = 5381)
|
|
{
|
|
while(*str)
|
|
hash = hash * 33 + (unsigned char)*str++;
|
|
return hash;
|
|
}
|
|
|
|
template<class T>
|
|
inline unsigned int calculateHash(const T& t, unsigned hash = 5381)
|
|
{
|
|
for (int i = 0; i < sizeof(T); i++)
|
|
hash = hash * 33 + ((unsigned char*)&t)[i];
|
|
return hash;
|
|
}
|
|
|
|
struct RowWidthCache
|
|
{
|
|
unsigned int valueHash;
|
|
int width;
|
|
|
|
RowWidthCache() : valueHash(0), width(-1) {}
|
|
int getOrUpdate(const QPropertyTree* tree, const PropertyRow* rowForValue, int extraSpace);
|
|
};
|
|
|
|
typedef vector<Serialization::SharedPtr<PropertyRow> > PropertyRows;
|
|
|
|
template<bool value>
|
|
struct StaticBool{
|
|
enum { Value = value };
|
|
};
|
|
|
|
struct LessStrCmp
|
|
{
|
|
bool operator()(const char* a, const char* b) const {
|
|
return strcmp(a, b) < 0;
|
|
}
|
|
};
|
|
|
|
typedef Factory<const char*, PropertyRow, LessStrCmp> PropertyRowFactory;
|
|
|
|
template<class Op>
|
|
bool PropertyRow::scanChildren(Op& op)
|
|
{
|
|
Rows::iterator it;
|
|
|
|
for(it = children_.begin(); it != children_.end(); ++it){
|
|
ScanResult result = op(*it);
|
|
if(result == SCAN_FINISHED)
|
|
return false;
|
|
if(result == SCAN_CHILDREN || result == SCAN_CHILDREN_SIBLINGS){
|
|
if(!(*it)->scanChildren(op))
|
|
return false;
|
|
if(result == SCAN_CHILDREN)
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
template<class Op>
|
|
bool PropertyRow::scanChildren(Op& op, QPropertyTree* tree)
|
|
{
|
|
int numChildren = int(children_.size());
|
|
for(int index = 0; index < numChildren; ++index){
|
|
PropertyRow* child = children_[index];
|
|
ScanResult result = op(child, tree, index);
|
|
if(result == SCAN_FINISHED)
|
|
return false;
|
|
if(result == SCAN_CHILDREN || result == SCAN_CHILDREN_SIBLINGS){
|
|
if(!child->scanChildren(op, tree))
|
|
return false;
|
|
if(result == SCAN_CHILDREN)
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
template<class Op>
|
|
bool PropertyRow::scanChildrenReverse(Op& op, QPropertyTree* tree)
|
|
{
|
|
int numChildren = (int)children_.size();
|
|
for(int index = numChildren - 1; index >= 0; --index){
|
|
PropertyRow* child = children_[index];
|
|
ScanResult result = op(child, tree, index);
|
|
if(result == SCAN_FINISHED)
|
|
return false;
|
|
if(result == SCAN_CHILDREN || result == SCAN_CHILDREN_SIBLINGS){
|
|
if(!child->scanChildrenReverse(op, tree))
|
|
return false;
|
|
if(result == SCAN_CHILDREN)
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
template<class Op>
|
|
bool PropertyRow::scanChildrenBottomUp(Op& op, QPropertyTree* tree)
|
|
{
|
|
size_t numChildren = children_.size();
|
|
for(size_t i = 0; i < numChildren; ++i)
|
|
{
|
|
PropertyRow* child = children_[i];
|
|
if(!child->scanChildrenBottomUp(op, tree))
|
|
return false;
|
|
ScanResult result = op(child, tree);
|
|
if(result == SCAN_FINISHED)
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
EDITOR_COMMON_API PropertyRowFactory& GlobalPropertyRowFactory();
|
|
EDITOR_COMMON_API Serialization::ClassFactory<PropertyRow>& GlobalPropertyRowClassFactory();
|
|
|
|
struct PropertyRowPtrSerializer : Serialization::SharedPtrSerializer<PropertyRow>
|
|
{
|
|
PropertyRowPtrSerializer(Serialization::SharedPtr<PropertyRow>& ptr) : SharedPtrSerializer(ptr) {}
|
|
Serialization::ClassFactory<PropertyRow>* factory() const override { return &GlobalPropertyRowClassFactory(); }
|
|
};
|
|
|
|
inline bool Serialize(Serialization::IArchive& ar, Serialization::SharedPtr<PropertyRow>& ptr, const char* name, const char* label)
|
|
{
|
|
PropertyRowPtrSerializer serializer(ptr);
|
|
return ar(static_cast<Serialization::IPointer&>(serializer), name, label);
|
|
}
|
|
|
|
#define REGISTER_PROPERTY_ROW(DataType, RowType) \
|
|
PropertyRow* _Factory_For_##RowType() {return new RowType; }; \
|
|
REGISTER_IN_FACTORY(PropertyRowFactory, Serialization::TypeID::get<DataType>().name(), RowType, _Factory_For_##RowType); \
|
|
SERIALIZATION_CLASS_NAME_FOR_FACTORY(GlobalPropertyRowClassFactory(), PropertyRow, RowType, #DataType, #DataType);
|
|
|
|
// Exposes the necessary class factories to extend the property tree
|
|
// Exposes the necessary class factories to extend the property tree
|
|
EDITOR_COMMON_API Serialization::ClassFactory<PropertyRow>& GetPropertyRowClassFactory();
|
|
EDITOR_COMMON_API PropertyRowFactory& GetPropertyRowFactory();
|