#ifndef CActionNode_HPP_INCLUDED #define CActionNode_HPP_INCLUDED /* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (c) 2018-2021 3Dconnexion. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ /** * @file CActionNode.hpp * @brief SiActionNodeEx_t wrapper. */ // 3dxware #include // stdlib #include #include #include #ifndef NOEXCEPT #if defined(_MSC_VER) && _MSC_VER < 1800 #ifdef _NOEXCEPT #define NOEXCEPT _NOEXCEPT #else #define NOEXCEPT #endif #else #define NOEXCEPT noexcept #endif #endif #if !_MSC_VER #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wshadow" #pragma GCC diagnostic ignored "-Wmissing-field-initializers" #endif /// /// The TDx namespace provides support for the types used in the 3DxWare interface. /// namespace TDx { /// /// Wrapper class for the structure. /// class CActionNode : private SiActionNodeEx_t { typedef SiActionNodeEx_t base_type; public: /// /// Initializes a new instance of the class. /// #if defined(_MSC_VER) && _MSC_VER < 1800 CActionNode() : base_type() { base_type::size = sizeof(base_type); } #else CActionNode() : base_type{sizeof(base_type)} { } #endif /// /// Constructor a with a label. /// /// The unique node identifier. /// Text to display to the user in the user interface. /// The of the node. explicit CActionNode(std::string id, std::string label, SiActionNodeType_t type) #if defined(_MSC_VER) && _MSC_VER < 1800 : base_type(), m_id(std::move(id)), m_label(std::move(label)) { base_type::size = sizeof(base_type); base_type::type = type; #else : base_type({sizeof(base_type), type}), m_id(std::move(id)), m_label(std::move(label)) { #endif if (!m_id.empty()) { base_type::id = m_id.c_str(); } if (!m_label.empty()) { base_type::label = m_label.c_str(); } } /// /// Constructor a with a label and a description for a tooltip. /// /// The unique node identifier /// Text to display to the user in the user interface. /// Text to display in a tooltip. /// The of the node. explicit CActionNode(std::string id, std::string label, std::string description, SiActionNodeType_t type) #if defined(_MSC_VER) && _MSC_VER < 1800 : base_type(), m_id(std::move(id)), m_label(std::move(label)), m_description(std::move(description)) { base_type::size = sizeof(base_type); base_type::type = type; #else : base_type({sizeof(base_type), type}), m_id(std::move(id)), m_label(std::move(label)), m_description(std::move(description)) { #endif if (!m_id.empty()) { base_type::id = m_id.c_str(); } if (!m_label.empty()) { base_type::label = m_label.c_str(); } if (!m_description.empty()) { base_type::description = m_description.c_str(); } } virtual ~CActionNode() { Tidy(); } /// /// Move constructor /// /// The to use for construction. CActionNode(CActionNode &&other) NOEXCEPT : base_type(other), m_id(std::move(other.m_id)), m_label(std::move(other.m_label)), m_description(std::move(other.m_description)) { base_type zero = {sizeof(base_type)}; static_cast(other) = zero; base_type::id = !m_id.empty() ? m_id.c_str() : nullptr; base_type::label = !m_label.empty() ? m_label.c_str() : nullptr; base_type::description = !m_description.empty() ? m_description.c_str() : nullptr; } /// /// Move assignment /// /// The to use for construction. CActionNode &operator=(CActionNode &&other) NOEXCEPT { static_cast(*this) = static_cast(other); m_id = std::move(other.m_id); m_label = std::move(other.m_label); m_description = std::move(other.m_description); base_type zero = {sizeof(base_type)}; static_cast(other) = zero; base_type::id = !m_id.empty() ? m_id.c_str() : nullptr; base_type::label = !m_label.empty() ? m_label.c_str() : nullptr; base_type::description = !m_description.empty() ? m_description.c_str() : nullptr; return *this; } #if !defined(_MSC_VER) || _MSC_VER > 1700 CActionNode(const CActionNode &) = delete; CActionNode &operator=(const CActionNode &) = delete; #else private: CActionNode(const CActionNode &); CActionNode &operator=(const CActionNode &); #endif public: /// /// Set the child node. /// /// The child node. template void PutChild(_Ty &&child) { if (base_type::children) { delete static_cast(base_type::children); } base_type::children = child.release(); } /// /// Set the next node. /// /// The next node. template void PutNext(_Ty &&next) { if (base_type::next) { delete static_cast(base_type::next); } base_type::next = next.release(); } #if USE_DECLSPEC_PROPERTY /// /// The properties. /// __declspec(property(get = GetId, put = PutId)) std::string Id; __declspec(property(get = GetDescription, put = PutDescription)) std::string Description; __declspec(property(get = GetLabel, put = PutLabel)) std::string Label; __declspec(property(get = GetType, put = PutType)) SiActionNodeType_t Type; #endif void PutType(const SiActionNodeType_t value) { base_type::type = value; } void PutId(std::string value) { m_id = std::move(value); base_type::id = m_id.c_str(); } void PutLabel(std::string value) { m_label = std::move(value); base_type::label = m_label.c_str(); } void PutDescription(std::string value) { m_description = std::move(value); base_type::description = m_description.c_str(); } CActionNode *DetachChild() { CActionNode *p = static_cast(base_type::children); base_type::children = nullptr; return p; } CActionNode *DetachNext() { CActionNode *p = static_cast(base_type::next); base_type::next = nullptr; return p; } CActionNode *GetChild() { return static_cast(base_type::children); } const CActionNode *GetChild() const { return static_cast(base_type::children); } CActionNode *GetNext() { return static_cast(base_type::next); } const CActionNode *GetNext() const { return static_cast(base_type::next); } std::string GetId() const { return m_id; } std::string GetLabel() const { return m_label; } std::string GetDescription() const { return m_description; } const SiActionNodeType_t GetType() const { return base_type::type; } const SiActionNodeEx_t &GetSiActionNode() const { return *this; } /// /// Clears this and the linked nodes. /// void clear() { base_type::id = base_type::label = base_type::description = nullptr; m_id.clear(); m_label.clear(); m_description.clear(); Tidy(); } /// /// Returns true if the node is empty and has no linked nodes /// /// bool empty() const { return m_id.empty() && base_type::next == nullptr && base_type::children == nullptr && m_label.empty() && m_description.empty(); } private: void AssignBaseDataValues() { base_type::id = !m_id.empty() ? m_id.c_str() : nullptr; base_type::label = !m_label.empty() ? m_label.c_str() : nullptr; base_type::description = !m_description.empty() ? m_description.c_str() : nullptr; } void Tidy() { if (base_type::next == 0 && base_type::children == 0) { return; } CActionNode *nextNode = static_cast(base_type::next); CActionNode *childrenNodes = static_cast(base_type::children); base_type::next = 0; base_type::children = 0; // Fix to avoid a stack overflow when destructing large lists // This traverses to the end of the list and deletes from there std::vector vnodes; if (nextNode) { vnodes.push_back(nextNode); } if (childrenNodes) { vnodes.push_back(childrenNodes); } size_t i; for (i = 0; i < vnodes.size(); ++i) { nextNode = static_cast(vnodes[i]->next); childrenNodes = static_cast(vnodes[i]->children); if (nextNode) { vnodes[i]->next = 0; vnodes.push_back(nextNode); } if (childrenNodes) { vnodes[i]->children = 0; vnodes.push_back(childrenNodes); } } std::vector::reverse_iterator riter; for (riter = vnodes.rbegin(); riter != vnodes.rend(); ++riter) { delete (*riter); } } private: std::string m_id; std::string m_label; std::string m_description; }; } // namespace TDx #if !_MSC_VER #pragma GCC diagnostic pop #endif #endif // CActionNode_HPP_INCLUDED