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.
o3de/Code/Sandbox/Plugins/EditorCommon/QPropertyTree/PropertyRowPointer.cpp

347 lines
9.1 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "EditorCommon_precompiled.h"
#include "PropertyRowPointer.h"
#include "QPropertyTree.h"
#include "PropertyTreeModel.h"
#include "PropertyDrawContext.h"
#include "Serialization.h"
#include "Unicode.h"
#include <QMenu>
// ---------------------------------------------------------------------------
void ClassMenuItemAdder::generateMenu(QMenu& createItem, const StringList& comboStrings)
{
StringList::const_iterator it;
int index = 0;
for (it = comboStrings.begin(); it != comboStrings.end(); ++it)
{
StringList path;
splitStringList(&path, it->c_str(), '\\');
QMenu* item = &createItem;
//createItem.addMenu(
for (int level2 = 0; level2 < int(path.size()); ++level2)
{
const char* leaf = path[level2].c_str();
if (level2 == path.size() - 1)
{
addAction(*item, leaf, index++);
}
else
{
if (QMenu* menu = item->findChild<QMenu*>(leaf))
{
item = menu;
}
else
{
item = addMenu(*item, leaf); //&item->add(leaf);
}
}
}
}
}
void ClassMenuItemAdder::addAction(QMenu& menu, const char* text, [[maybe_unused]] int index)
{
menu.addAction(text)->setEnabled(false);
}
QMenu* ClassMenuItemAdder::addMenu(QMenu& menu, const char* text)
{
QMenu* result = menu.addMenu(text);
result->setObjectName(text);
return result;
}
// ---------------------------------------------------------------------------
SERIALIZATION_CLASS_NAME(PropertyRow, PropertyRowPointer, "PropertyRowPointer", "SharedPtr");
PropertyRowPointer::PropertyRowPointer()
: factory_(0)
, searchHandle_(0)
, colorOverride_(0, 0, 0, 0)
{
}
void PropertyRowPointer::setDerivedType(const char* typeName, Serialization::IClassFactory* factory)
{
if (!factory)
{
derivedTypeName_.clear();
return;
}
derivedTypeName_ = typeName;
}
bool PropertyRowPointer::assignTo(Serialization::IPointer& ptr)
{
if (derivedTypeName_ != ptr.registeredTypeName())
{
ptr.create(derivedTypeName_.c_str());
}
return true;
}
void CreatePointerMenuHandler::onMenuCreateByIndex()
{
tree->model()->rowAboutToBeChanged(row);
if (index < 0) // NULL value
{
row->setDerivedType("", 0);
row->clear();
}
else
{
const PropertyDefaultDerivedTypeValue* defaultValue = tree->model()->defaultType(row->baseType(), index);
SharedPtr<PropertyRow> clonedDefault = defaultValue->root->clone(tree->model()->constStrings());
if (defaultValue && defaultValue->root)
{
YASLI_ASSERT(defaultValue->root->refCount() == 1);
if (useDefaultValue)
{
row->clear();
row->swapChildren(clonedDefault, 0);
}
row->setDerivedType(defaultValue->registeredName.c_str(), row->factory());
row->setLabelChanged();
row->setLabelChangedToChildren();
tree->expandRow(row);
}
else
{
row->setDerivedType("", 0);
row->clear();
}
}
tree->model()->rowChanged(row);
}
string PropertyRowPointer::valueAsString() const
{
string result;
const Serialization::TypeDescription* desc = 0;
if (factory_)
{
desc = factory_->descriptionByRegisteredName(derivedTypeName_.c_str());
}
if (desc)
{
result = desc->label();
}
else
{
result = derivedTypeName_;
}
return result;
}
wstring PropertyRowPointer::generateLabel() const
{
if (multiValue())
{
return L"...";
}
wstring str;
if (!derivedTypeName_.empty())
{
const char* textStart = derivedTypeName_.c_str();
if (factory_)
{
const Serialization::TypeDescription* desc = factory_->descriptionByRegisteredName(derivedTypeName_.c_str());
if (desc)
{
textStart = desc->label();
}
}
const char* p = textStart + strlen(textStart);
while (p > textStart)
{
if (*(p - 1) == '\\')
{
break;
}
--p;
}
str = toWideChar(p);
if (p != textStart)
{
str += L" (";
str += toWideChar(string(textStart, p - 1).c_str());
str += L")";
}
}
else
{
if (factory_)
{
str = toWideChar(factory_->nullLabel() ? factory_->nullLabel() : "[ null ]");
}
else
{
str = L"[ null ]";
}
}
return str;
}
void PropertyRowPointer::redraw(const PropertyDrawContext& context)
{
QRect widgetRect = context.widgetRect;
QRect rt = widgetRect;
rt.adjust(-1, 0, 0, 1);
wstring str = generateLabel();
const QFont* font = derivedTypeName_.empty() ? &context.tree->font() : &context.tree->_boldFont();
int buttonFlags = BUTTON_POPUP_ARROW;
if (userReadOnly())
{
buttonFlags |= BUTTON_DISABLED;
}
if (context.m_pressed)
{
buttonFlags |= BUTTON_PRESSED;
}
context.drawButton(rt, str.c_str(), buttonFlags, font, colorOverride_.a != 0 ? &colorOverride_ : 0);
}
struct ClassMenuItemAdderRowPointer
: ClassMenuItemAdder
{
ClassMenuItemAdderRowPointer(PropertyRowPointer* row, QPropertyTree* tree)
: row_(row)
, tree_(tree) {}
void addAction(QMenu& menu, const char* text, int index)
{
CreatePointerMenuHandler* handler = new CreatePointerMenuHandler;
tree_->addMenuHandler(handler);
handler->row = row_;
handler->tree = tree_;
handler->index = index;
handler->useDefaultValue = !tree_->immediateUpdate();
QAction* action = menu.addAction(text);
QObject::connect(action, SIGNAL(triggered()), handler, SLOT(onMenuCreateByIndex()));
}
protected:
PropertyRowPointer* row_;
QPropertyTree* tree_;
};
bool PropertyRowPointer::onActivate(QPropertyTree* tree, [[maybe_unused]] bool force)
{
if (userReadOnly())
{
return false;
}
QMenu menu;
ClassMenuItemAdderRowPointer(this, tree).generateMenu(menu, tree->model()->typeStringList(baseType()));
tree->_setPressedRow(this);
menu.exec(tree->_toScreen(QPoint(widgetPos_, pos_.y() + tree->_defaultRowHeight())));
tree->_setPressedRow(0);
return true;
}
bool PropertyRowPointer::onMouseDown(QPropertyTree* tree, QPoint point, bool& changed)
{
if (widgetRect(tree).contains(point))
{
if (onActivate(tree, false))
{
changed = true;
}
}
return false;
}
bool PropertyRowPointer::onContextMenu(QMenu& menu, QPropertyTree* tree)
{
if (!menu.isEmpty())
{
menu.addSeparator();
}
if (!userReadOnly())
{
QMenu* createItem = menu.addMenu("Set");
ClassMenuItemAdderRowPointer(this, tree).generateMenu(*createItem, tree->model()->typeStringList(baseType()));
}
return PropertyRow::onContextMenu(menu, tree);
}
void PropertyRowPointer::serializeValue(IArchive& ar)
{
ar(derivedTypeName_, "derivedTypeName", "Derived Type Name");
}
int PropertyRowPointer::widgetSizeMin(const QPropertyTree* tree) const
{
QFontMetrics fm(tree->_boldFont());
QString str(fromWideChar(generateLabel().c_str()).c_str());
return fm.horizontalAdvance(str) + 24;
}
static Color parseColorString(const char* str)
{
unsigned int color = 0;
if (azsscanf(str, "%x", &color) != 1)
{
return Color(0, 0, 0, 0);
}
Color result((color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff, 255);
return result;
}
void PropertyRowPointer::setValueAndContext(const Serialization::IPointer& ptr, [[maybe_unused]] Serialization::IArchive& ar)
{
baseType_ = ptr.baseType();
factory_ = ptr.factory();
serializer_ = ptr.serializer();
pointerType_ = ptr.pointerType();
searchHandle_ = ptr.handle();
const char* colorString = factory_->findAnnotation(ptr.registeredTypeName(), "color");
if (colorString[0] != '\0')
{
colorOverride_ = parseColorString(colorString);
}
else
{
colorOverride_ = Color(0, 0, 0, 0);
}
const Serialization::TypeDescription* desc = factory_->descriptionByRegisteredName(ptr.registeredTypeName());
if (desc)
{
derivedTypeName_ = desc->name();
}
else
{
derivedTypeName_.clear();
}
}
#include <QPropertyTree/moc_PropertyRowPointer.cpp>
// vim:ts=4 sw=4: