<commit_before>/**
    For conditions of distribution and use, see copyright notice in LICENSE

    @file   UndoCommands.h
    @brief  A collection of classes which apply to the operations in EC Editor and Scene Structure windows. */

#pragma once

#include "ECEditorModuleApi.h"
#include "SceneFwd.h"
#include "Entity.h"
#include "IComponent.h"
#include "IAttribute.h"
#include "Color.h"
#include "Math/float3.h"
#include "Math/float3x4.h"

#include <QDomDocument>
#include <QDomElement>
#include <QUndoCommand>

typedef QList<entity_id_t> EntityIdList;
typedef QList<TransformAttributeWeakPtr> TransformAttributeWeakPtrList;

class EntityIdChangeTracker;

/// EditAttributeCommandBase exposes basi
class IEditAttributeCommand : public QUndoCommand
{
public:
    /// Internal QUndoCommand unique ID
    enum { Id = 100 };
   
    IEditAttributeCommand(QUndoCommand *parent) : QUndoCommand(parent) {}

    AttributeWeakPtr attribute;
    QString attributeName;
    QString attributeTypeName;
    entity_id_t parentId;
};

/// EditAttributeCommand representing an "Edit" operation to the attributes
template <typename T>
class EditAttributeCommand : public IEditAttributeCommand
{
public:
    /** Current value of the attribute will be read as the undo() applied value.
        When redo() is triggered this command does nothing and it will read the redo value once undo() is applied.
        @param attr The attribute that is being edited.
        @param parent The parent command of this command (optional). */
    EditAttributeCommand(IAttribute *attr, QUndoCommand *parent = 0);
    
    /** Current value of the attribute will be read as the undo() applied value.
        Given valueToApply will be applied immediately when redo() is triggered (eg. added to a QUndoStack).
        @param attr The attribute that is being edited.
        @param valueToApply The new attribute value. Gets applied immediately when this actions redo() it triggered.
        @param parent The parent command of this command (optional). */
    EditAttributeCommand(IAttribute *attr, const T &valueToApply, QUndoCommand *parent = 0);

    /// Returns this command's ID
    int id() const { return Id; }

    /// QUndoCommand override
    void undo()
    {
        if (!attribute.Expired())
        {
            redoValue = static_cast<Attribute<T> *>(attribute.Get())->Get();
            static_cast<Attribute<T> *>(attribute.Get())->Set(undoValue, AttributeChange::Default);
        }
    }

    /// QUndoCommand override
    void redo()
    {
        if (noAutoRedo)
            noAutoRedo = false;
        else if (!attribute.Expired())
            static_cast<Attribute<T> *>(attribute.Get())->Set(redoValue, AttributeChange::Default);
    }

    /// QUndoCommand override
    /** @todo Should we make a specialization for certain types of attributes that their 'Edit attribute' commands are merged,
            or should we keep each atomic change to the attributes in the stack?
            (e.g. if 'Transform' attribute for each of the components of each pos, rot, and scale float3s are edited, it 
            will push 9 commands into the undo stack) */
    bool mergeWith(const QUndoCommand * UNUSED_PARAM(other))
    {
        // Don't merge commands yet. This is only for the 'Color' attribute specialization
        return false;

        /*
        if (id() != other->id())
            return false;

        const EditAttributeCommand<T> *otherCommand = dynamic_cast<const EditAttributeCommand<T> *>(other);
        if (!otherCommand)
            return false;

        return true;
        */
    }

private:
    void Initialize(IAttribute *attr, bool autoRedo)
    {
        attribute = AttributeWeakPtr(attr->Owner()->shared_from_this(), attr);
        attributeName = attr->Name();
        attributeTypeName = attr->TypeName(),
        parentId = attr->Owner()->ParentEntity()->Id();
        noAutoRedo = false;
        setText("* Edited " + attr->Name() + " Attribute");
    }
    
    T redoValue;
    T undoValue;
    bool noAutoRedo;
};

#include "UndoCommands.inl"

/// Represents adding an attribute to a dynamic component<commit_msg>EditAttributeCommand<T>::Initialize: use the bool autoRedo parameter as it should.<commit_after>/**
    For conditions of distribution and use, see copyright notice in LICENSE

    @file   UndoCommands.h
    @brief  A collection of classes which apply to the operations in EC Editor and Scene Structure windows. */

#pragma once

#include "ECEditorModuleApi.h"
#include "SceneFwd.h"
#include "Entity.h"
#include "IComponent.h"
#include "IAttribute.h"
#include "Color.h"
#include "Math/float3.h"
#include "Math/float3x4.h"

#include <QDomDocument>
#include <QDomElement>
#include <QUndoCommand>

typedef QList<entity_id_t> EntityIdList;
typedef QList<TransformAttributeWeakPtr> TransformAttributeWeakPtrList;

class EntityIdChangeTracker;

/// EditAttributeCommandBase exposes basi
class IEditAttributeCommand : public QUndoCommand
{
public:
    /// Internal QUndoCommand unique ID
    enum { Id = 100 };
   
    IEditAttributeCommand(QUndoCommand *parent) : QUndoCommand(parent) {}

    AttributeWeakPtr attribute;
    QString attributeName;
    QString attributeTypeName;
    entity_id_t parentId;
};

/// EditAttributeCommand representing an "Edit" operation to the attributes
template <typename T>
class EditAttributeCommand : public IEditAttributeCommand
{
public:
    /** Current value of the attribute will be read as the undo() applied value.
        When redo() is triggered this command does nothing and it will read the redo value once undo() is applied.
        @param attr The attribute that is being edited.
        @param parent The parent command of this command (optional). */
    EditAttributeCommand(IAttribute *attr, QUndoCommand *parent = 0);
    
    /** Current value of the attribute will be read as the undo() applied value.
        Given valueToApply will be applied immediately when redo() is triggered (eg. added to a QUndoStack).
        @param attr The attribute that is being edited.
        @param valueToApply The new attribute value. Gets applied immediately when this actions redo() it triggered.
        @param parent The parent command of this command (optional). */
    EditAttributeCommand(IAttribute *attr, const T &valueToApply, QUndoCommand *parent = 0);

    /// Returns this command's ID
    int id() const { return Id; }

    /// QUndoCommand override
    void undo()
    {
        if (!attribute.Expired())
        {
            redoValue = static_cast<Attribute<T> *>(attribute.Get())->Get();
            static_cast<Attribute<T> *>(attribute.Get())->Set(undoValue, AttributeChange::Default);
        }
    }

    /// QUndoCommand override
    void redo()
    {
        if (noAutoRedo)
            noAutoRedo = false;
        else if (!attribute.Expired())
            static_cast<Attribute<T> *>(attribute.Get())->Set(redoValue, AttributeChange::Default);
    }

    /// QUndoCommand override
    /** @todo Should we make a specialization for certain types of attributes that their 'Edit attribute' commands are merged,
            or should we keep each atomic change to the attributes in the stack?
            (e.g. if 'Transform' attribute for each of the components of each pos, rot, and scale float3s are edited, it 
            will push 9 commands into the undo stack) */
    bool mergeWith(const QUndoCommand * UNUSED_PARAM(other))
    {
        // Don't merge commands yet. This is only for the 'Color' attribute specialization
        return false;

        /*
        if (id() != other->id())
            return false;

        const EditAttributeCommand<T> *otherCommand = dynamic_cast<const EditAttributeCommand<T> *>(other);
        if (!otherCommand)
            return false;

        return true;
        */
    }

private:
    void Initialize(IAttribute *attr, bool autoRedo)
    {
        attribute = AttributeWeakPtr(attr->Owner()->shared_from_this(), attr);
        attributeName = attr->Name();
        attributeTypeName = attr->TypeName(),
        parentId = attr->Owner()->ParentEntity()->Id();
        noAutoRedo = autoRedo;
        setText("* Edited " + attr->Name() + " Attribute");
    }
    
    T redoValue;
    T undoValue;
    bool noAutoRedo;
};

#include "UndoCommands.inl"

/// Represents adding an attribute to a dynamic component
{'fraction_non_alphanumeric': 0.0955002393489708, 'fraction_numerical': 0.0023934897079942556, 'mean_word_length': 3.0646887159533076, 'pattern_counts': {'":': 0, '<': 34, '<?xml version=': 0, '>': 58, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3615390', 'n_tokens_mistral': 2314, 'n_tokens_neox': 2246, 'n_words': 795}