<commit_before>#ifndef MJOLNIR_INPUT_READ_EXTERNAL_INTERACTION_HPP
#define MJOLNIR_INPUT_READ_EXTERNAL_INTERACTION_HPP
#include <extlib/toml/toml.hpp>
#include <mjolnir/forcefield/AFMFit/AFMFitInteraction.hpp>
#include <mjolnir/interaction/external/ExternalDistanceInteraction.hpp>
#include <mjolnir/interaction/external/PositionRestraintInteraction.hpp>
#include <mjolnir/core/AxisAlignedPlane.hpp>
#include <mjolnir/util/make_unique.hpp>
#include <mjolnir/util/throw_exception.hpp>
#include <mjolnir/util/logger.hpp>
#include <mjolnir/input/read_external_potential.hpp>
#include <mjolnir/input/read_local_potential.hpp>
#include <memory>

namespace mjolnir
{

// ----------------------------------------------------------------------------
// external interaction
// ----------------------------------------------------------------------------

template<typename traitsT, typename shapeT>
std::unique_ptr<ExternalForceInteractionBase<traitsT>>
read_external_distance_interaction(const toml::value& external, shapeT&& shape)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();
    using real_type = typename traitsT::real_type;

    const auto potential = toml::find<std::string>(external, "potential");
    if(potential == "ImplicitMembrane")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Implicit Membrane.");
        using potential_t   = ImplicitMembranePotential<real_type>;
        using interaction_t = ExternalDistanceInteraction<
                                    traitsT, potential_t, shapeT>;

        return make_unique<interaction_t>(std::move(shape),
             read_implicit_membrane_potential<real_type>(external));
    }
    else if(potential == "LennardJonesWall")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Lennard-Jones.");
        using potential_t   = LennardJonesWallPotential<real_type>;
        using interaction_t = ExternalDistanceInteraction<
                                    traitsT, potential_t, shapeT>;
        return make_unique<interaction_t>(std::move(shape),
             read_lennard_jones_wall_potential<real_type>(external));
    }
    else if(potential == "ExcludedVolumeWall")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Excluded-Volume.");
        using potential_t   = ExcludedVolumeWallPotential<real_type>;
        using interaction_t = ExternalDistanceInteraction<
                                    traitsT, potential_t, shapeT>;
        return make_unique<interaction_t>(std::move(shape),
             read_excluded_volume_wall_potential<real_type>(external));
    }
    else
    {
        throw_exception<std::runtime_error>(toml::format_error("[error] "
            "mjolnir::read_external_distance_interaction: invalid potential",
            toml::find(external, "potential"), "here", {
            "expected value is one of the following.",
            "- \"ExcludedVolumeWall\": repulsive r^12 potential",
            "- \"LennardJonesWall\"  : famous r^12 - r^6 potential",
            "- \"ImplicitMembrane\"  : single-well interaction that models a membrane"
            }));
    }
}

template<typename traitsT>
std::unique_ptr<ExternalForceInteractionBase<traitsT>>
read_external_distance_interaction_shape(const toml::value& external)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();
    using real_type = typename traitsT::real_type;

    const auto shape = toml::find<toml::value>(external, "shape");
    const auto name  = toml::find<std::string>(shape, "name");

    if(name == "AxisAlignedPlane")
    {
        const auto pos    = toml::find<real_type>(shape, "position");
        const auto margin = toml::find<real_type>(shape, "margin");
        MJOLNIR_LOG_INFO("pos    = ", pos);
        MJOLNIR_LOG_INFO("margin = ", margin);

        const auto axis = toml::find<std::string>(shape, "axis");
        MJOLNIR_LOG_INFO("axis   = ", axis);

        if(axis == "X" || axis == "+X")
        {
            MJOLNIR_LOG_NOTICE("-- interaction shape is YZ-Plane (+).");
            using shape_t = AxisAlignedPlane<traitsT, PositiveXDirection<traitsT>>;

            return read_external_distance_interaction<traitsT, shape_t>(
                    external, shape_t(pos, margin));
        }
        else if(axis == "-X")
        {
            MJOLNIR_LOG_NOTICE("-- interaction shape is YZ-Plane (-).");
            using shape_t = AxisAlignedPlane<traitsT, NegativeXDirection<traitsT>>;
            return read_external_distance_interaction<traitsT, shape_t>(
                    external, shape_t(pos, margin));
        }
        else if(axis == "Y" || axis == "+Y")
        {
            MJOLNIR_LOG_NOTICE("-- interaction shape is ZX-Plane (+).");
            using shape_t = AxisAlignedPlane<traitsT, PositiveYDirection<traitsT>>;
            return read_external_distance_interaction<traitsT, shape_t>(
                    external, shape_t(pos, margin));
        }
        else if(axis == "-Y")
        {
            MJOLNIR_LOG_NOTICE("-- interaction shape is ZX-Plane (-).");
            using shape_t = AxisAlignedPlane<traitsT, NegativeYDirection<traitsT>>;
            return read_external_distance_interaction<traitsT, shape_t>(
                    external, shape_t(pos, margin));
        }
        else if(axis == "Z" || axis == "+Z")
        {
            MJOLNIR_LOG_NOTICE("-- interaction shape is XY-Plane (+).");
            using shape_t = AxisAlignedPlane<traitsT, PositiveZDirection<traitsT>>;
            return read_external_distance_interaction<traitsT, shape_t>(
                    external, shape_t(pos, margin));
        }
        else if(axis == "-Z")
        {
            MJOLNIR_LOG_NOTICE("-- interaction shape is XY-Plane (-).");
            using shape_t = AxisAlignedPlane<traitsT, NegativeZDirection<traitsT>>;
            return read_external_distance_interaction<traitsT, shape_t>(
                    external, shape_t(pos, margin));
        }
        else
        {
            throw_exception<std::runtime_error>(toml::format_error("[error] "
                "mjolnir::read_external_distance_interaction_shape: invalid shape",
                toml::find(external, "shape"), "expected [+-]?[XYZ]"));
        }
    }
    else
    {
        throw std::runtime_error("invalid external forcefield shape: " + name);
    }
}

template<typename traitsT>
std::unique_ptr<ExternalForceInteractionBase<traitsT>>
read_external_position_restraint_interaction(const toml::value& external)
{
    // [[forcefields.external]]
    // interaction = "PositionRestraint"
    // potential   = "Harmonic" # ----------------------------------------+
    // parameters  = [                                                    |
    //     {index = 0, position = [0.0, 0.0, 0.0], k = 0.1, v0 = 10.0},   v
    //     #                                       ^^^^^^^^^^^^^^^^^^ Harmonic
    //     # ...
    // ]
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();
    using real_type       = typename traitsT::real_type;
    using coordinate_type = typename traitsT::coordinate_type;

    const auto& env = external.as_table().count("env") == 1 ?
                      external.as_table().at("env") : toml::value{};

    const auto potential = toml::find<std::string>(external, "potential");
    if(potential == "Harmonic")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Harmonic.");
        using potential_t   = HarmonicPotential<real_type>;
        using interaction_t = PositionRestraintInteraction<traitsT, potential_t>;

        // container to put parameters
        typename interaction_t::potential_container_type potentials;

        const auto& parameters = toml::find<toml::array>(external, "parameters");
        potentials.reserve(parameters.size());

        for(auto para : parameters)
        {
            const auto idx = find_parameter<std::size_t>(para, env, "index");
            const auto pos = find_parameter<std::array<real_type, 3>>(para, env, "position");
            const auto crd = math::make_coordinate<coordinate_type>(pos[0], pos[1], pos[2]);

            // suppress warnings in read_harmonic_potential
            para.as_table().erase("index");
            para.as_table().erase("position");

            const auto pot = read_harmonic_potential<real_type>(para, env);
            potentials.emplace_back(idx, crd, pot);
        }
        return make_unique<interaction_t>(std::move(potentials));
    }
    else
    {
        throw_exception<std::runtime_error>(toml::format_error("[error] "
            "mjolnir::read_external_position_restraint_interaction: invalid potential",
            toml::find(external, "potential"), "here", {
            "expected value is one of the following.",
            "- \"Harmonic\": very famous `k(x-x0)^2` potential"
            }));
    }
}

template<typename traitsT>
std::unique_ptr<ExternalForceInteractionBase<traitsT>>
read_afm_flexible_fitting_interaction(const toml::value& external)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();
    using real_type     = typename traitsT::real_type;
    using interaction_t = AFMFitInteraction<traitsT>;

    const auto k        = toml::find<real_type  >(external, "k");
    const auto gamma    = toml::find<real_type  >(external, "gamma");
    const auto z0       = toml::find<real_type  >(external, "z0");
    const auto cutoff   = toml::find<real_type  >(external, "cutoff");
    const auto margin   = toml::find<real_type  >(external, "margin");
    const auto sigma_x  = toml::find<real_type  >(external, "sigma_x");
    const auto sigma_y  = toml::find<real_type  >(external, "sigma_y");
    const auto pixel_x  = toml::find<real_type  >(external, "pixel_x");
    const auto pixel_y  = toml::find<real_type  >(external, "pixel_y");
    const auto length_x = toml::find<std::size_t>(external, "length_x");
    const auto length_y = toml::find<std::size_t>(external, "length_y");

    const auto& env = external.as_table().count("env") != 0 ?
                      external.at("env") : toml::value{};

    // read radius and participants

    const auto& parameters = toml::find<toml::array>(external, "parameters");

    std::vector<std::pair<std::size_t, real_type>> radii;
    radii.reserve(parameters.size());
    for(auto para : parameters)
    {
        const auto idx = find_parameter<std::size_t>(para, env, "index");
        const auto rad = find_parameter<real_type  >(para, env, "radius");
        radii.emplace_back(idx, rad);
    }

    std::vector<real_type> image;
    image.reserve(length_x * length_y);
    for(real_type img : toml::find<std::vector<real_type>>(external, "image"))
    {
        image.push_back(img);
    }
    return make_unique<interaction_t>(k, gamma, z0, cutoff, margin,
        sigma_x, sigma_y, pixel_x, pixel_y, length_x, length_y, radii, image);
}

// ----------------------------------------------------------------------------
// general read_external_interaction function
// ----------------------------------------------------------------------------

template<typename traitsT>
std::unique_ptr<ExternalForceInteractionBase<traitsT>>
read_external_interaction(const toml::value& external)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();
    const auto interaction = toml::find<std::string>(external, "interaction");

    if(interaction == "Distance")
    {
        MJOLNIR_LOG_NOTICE("Distance interaction found.");
        return read_external_distance_interaction_shape<traitsT>(external);
    }
    else if(interaction == "PositionRestraint")
    {
        MJOLNIR_LOG_NOTICE("PositionRestraint interaction found.");
        return read_external_position_restraint_interaction<traitsT>(external);
    }
    else if(interaction == "AFMFlexibleFitting")
    {
        MJOLNIR_LOG_NOTICE("AFMFlexibleFitting interaction found.");
        return read_afm_flexible_fitting_interaction<traitsT>(external);
    }
    else
    {
        throw std::runtime_error(toml::format_error("[error] "
            "mjolnir::read_external_interaction: invalid interaction",
            toml::find(external, "interaction"), "here", {
            "expected value is one of the following.",
            "- \"Distance\":           interaction depending on the distance between a particle and a structure",
            "- \"PositionRestraint\":  interaction depending on the distance between a particle and a fixed point"
            "- \"AFMFlexibleFitting\": interaction depending on the distance between a particle and a fixed point"
            }));
    }
}

#ifdef MJOLNIR_SEPARATE_BUILD
extern template std::unique_ptr<ExternalForceInteractionBase<SimulatorTraits<double, UnlimitedBoundary>       >> read_external_interaction(const toml::value& external);
extern template std::unique_ptr<ExternalForceInteractionBase<SimulatorTraits<float,  UnlimitedBoundary>       >> read_external_interaction(const toml::value& external);
extern template std::unique_ptr<ExternalForceInteractionBase<SimulatorTraits<double, CuboidalPeriodicBoundary>>> read_external_interaction(const toml::value& external);
extern template std::unique_ptr<ExternalForceInteractionBase<SimulatorTraits<float,  CuboidalPeriodicBoundary>>> read_external_interaction(const toml::value& external);

extern template std::unique_ptr<ExternalForceInteractionBase<SimulatorTraits<double, UnlimitedBoundary>       >> read_external_position_restraint_interaction(const toml::value& external);
extern template std::unique_ptr<ExternalForceInteractionBase<SimulatorTraits<float,  UnlimitedBoundary>       >> read_external_position_restraint_interaction(const toml::value& external);
extern template std::unique_ptr<ExternalForceInteractionBase<SimulatorTraits<double, CuboidalPeriodicBoundary>>> read_external_position_restraint_interaction(const toml::value& external);
extern template std::unique_ptr<ExternalForceInteractionBase<SimulatorTraits<float,  CuboidalPeriodicBoundary>>> read_external_position_restraint_interaction(const toml::value& external);

extern template std::unique_ptr<ExternalForceInteractionBase<SimulatorTraits<double, UnlimitedBoundary>       >> read_external_distance_interaction_shape(const toml::value& external);
extern template std::unique_ptr<ExternalForceInteractionBase<SimulatorTraits<float,  UnlimitedBoundary>       >> read_external_distance_interaction_shape(const toml::value& external);
extern template std::unique_ptr<ExternalForceInteractionBase<SimulatorTraits<double, CuboidalPeriodicBoundary>>> read_external_distance_interaction_shape(const toml::value& external);
extern template std::unique_ptr<ExternalForceInteractionBase<SimulatorTraits<float,  CuboidalPeriodicBoundary>>> read_external_distance_interaction_shape(const toml::value& external);
#endif

} // mjolnir
#endif// MJOLNIR_READ_EXTERNAL_INTERACTION_HPP
<commit_msg>fix: fix error message for external forcefield<commit_after>#ifndef MJOLNIR_INPUT_READ_EXTERNAL_INTERACTION_HPP
#define MJOLNIR_INPUT_READ_EXTERNAL_INTERACTION_HPP
#include <extlib/toml/toml.hpp>
#include <mjolnir/forcefield/AFMFit/AFMFitInteraction.hpp>
#include <mjolnir/interaction/external/ExternalDistanceInteraction.hpp>
#include <mjolnir/interaction/external/PositionRestraintInteraction.hpp>
#include <mjolnir/core/AxisAlignedPlane.hpp>
#include <mjolnir/util/make_unique.hpp>
#include <mjolnir/util/throw_exception.hpp>
#include <mjolnir/util/logger.hpp>
#include <mjolnir/input/read_external_potential.hpp>
#include <mjolnir/input/read_local_potential.hpp>
#include <memory>

namespace mjolnir
{

// ----------------------------------------------------------------------------
// external interaction
// ----------------------------------------------------------------------------

template<typename traitsT, typename shapeT>
std::unique_ptr<ExternalForceInteractionBase<traitsT>>
read_external_distance_interaction(const toml::value& external, shapeT&& shape)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();
    using real_type = typename traitsT::real_type;

    const auto potential = toml::find<std::string>(external, "potential");
    if(potential == "ImplicitMembrane")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Implicit Membrane.");
        using potential_t   = ImplicitMembranePotential<real_type>;
        using interaction_t = ExternalDistanceInteraction<
                                    traitsT, potential_t, shapeT>;

        return make_unique<interaction_t>(std::move(shape),
             read_implicit_membrane_potential<real_type>(external));
    }
    else if(potential == "LennardJonesWall")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Lennard-Jones.");
        using potential_t   = LennardJonesWallPotential<real_type>;
        using interaction_t = ExternalDistanceInteraction<
                                    traitsT, potential_t, shapeT>;
        return make_unique<interaction_t>(std::move(shape),
             read_lennard_jones_wall_potential<real_type>(external));
    }
    else if(potential == "ExcludedVolumeWall")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Excluded-Volume.");
        using potential_t   = ExcludedVolumeWallPotential<real_type>;
        using interaction_t = ExternalDistanceInteraction<
                                    traitsT, potential_t, shapeT>;
        return make_unique<interaction_t>(std::move(shape),
             read_excluded_volume_wall_potential<real_type>(external));
    }
    else
    {
        throw_exception<std::runtime_error>(toml::format_error("[error] "
            "mjolnir::read_external_distance_interaction: invalid potential",
            toml::find(external, "potential"), "here", {
            "expected value is one of the following.",
            "- \"ExcludedVolumeWall\": repulsive r^12 potential",
            "- \"LennardJonesWall\"  : famous r^12 - r^6 potential",
            "- \"ImplicitMembrane\"  : single-well interaction that models a membrane"
            }));
    }
}

template<typename traitsT>
std::unique_ptr<ExternalForceInteractionBase<traitsT>>
read_external_distance_interaction_shape(const toml::value& external)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();
    using real_type = typename traitsT::real_type;

    const auto shape = toml::find<toml::value>(external, "shape");
    const auto name  = toml::find<std::string>(shape, "name");

    if(name == "AxisAlignedPlane")
    {
        const auto pos    = toml::find<real_type>(shape, "position");
        const auto margin = toml::find<real_type>(shape, "margin");
        MJOLNIR_LOG_INFO("pos    = ", pos);
        MJOLNIR_LOG_INFO("margin = ", margin);

        const auto axis = toml::find<std::string>(shape, "axis");
        MJOLNIR_LOG_INFO("axis   = ", axis);

        if(axis == "X" || axis == "+X")
        {
            MJOLNIR_LOG_NOTICE("-- interaction shape is YZ-Plane (+).");
            using shape_t = AxisAlignedPlane<traitsT, PositiveXDirection<traitsT>>;

            return read_external_distance_interaction<traitsT, shape_t>(
                    external, shape_t(pos, margin));
        }
        else if(axis == "-X")
        {
            MJOLNIR_LOG_NOTICE("-- interaction shape is YZ-Plane (-).");
            using shape_t = AxisAlignedPlane<traitsT, NegativeXDirection<traitsT>>;
            return read_external_distance_interaction<traitsT, shape_t>(
                    external, shape_t(pos, margin));
        }
        else if(axis == "Y" || axis == "+Y")
        {
            MJOLNIR_LOG_NOTICE("-- interaction shape is ZX-Plane (+).");
            using shape_t = AxisAlignedPlane<traitsT, PositiveYDirection<traitsT>>;
            return read_external_distance_interaction<traitsT, shape_t>(
                    external, shape_t(pos, margin));
        }
        else if(axis == "-Y")
        {
            MJOLNIR_LOG_NOTICE("-- interaction shape is ZX-Plane (-).");
            using shape_t = AxisAlignedPlane<traitsT, NegativeYDirection<traitsT>>;
            return read_external_distance_interaction<traitsT, shape_t>(
                    external, shape_t(pos, margin));
        }
        else if(axis == "Z" || axis == "+Z")
        {
            MJOLNIR_LOG_NOTICE("-- interaction shape is XY-Plane (+).");
            using shape_t = AxisAlignedPlane<traitsT, PositiveZDirection<traitsT>>;
            return read_external_distance_interaction<traitsT, shape_t>(
                    external, shape_t(pos, margin));
        }
        else if(axis == "-Z")
        {
            MJOLNIR_LOG_NOTICE("-- interaction shape is XY-Plane (-).");
            using shape_t = AxisAlignedPlane<traitsT, NegativeZDirection<traitsT>>;
            return read_external_distance_interaction<traitsT, shape_t>(
                    external, shape_t(pos, margin));
        }
        else
        {
            throw_exception<std::runtime_error>(toml::format_error("[error] "
                "mjolnir::read_external_distance_interaction_shape: invalid shape",
                toml::find(external, "shape"), "expected [+-]?[XYZ]"));
        }
    }
    else
    {
        throw std::runtime_error("invalid external forcefield shape: " + name);
    }
}

template<typename traitsT>
std::unique_ptr<ExternalForceInteractionBase<traitsT>>
read_external_position_restraint_interaction(const toml::value& external)
{
    // [[forcefields.external]]
    // interaction = "PositionRestraint"
    // potential   = "Harmonic" # ----------------------------------------+
    // parameters  = [                                                    |
    //     {index = 0, position = [0.0, 0.0, 0.0], k = 0.1, v0 = 10.0},   v
    //     #                                       ^^^^^^^^^^^^^^^^^^ Harmonic
    //     # ...
    // ]
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();
    using real_type       = typename traitsT::real_type;
    using coordinate_type = typename traitsT::coordinate_type;

    const auto& env = external.as_table().count("env") == 1 ?
                      external.as_table().at("env") : toml::value{};

    const auto potential = toml::find<std::string>(external, "potential");
    if(potential == "Harmonic")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Harmonic.");
        using potential_t   = HarmonicPotential<real_type>;
        using interaction_t = PositionRestraintInteraction<traitsT, potential_t>;

        // container to put parameters
        typename interaction_t::potential_container_type potentials;

        const auto& parameters = toml::find<toml::array>(external, "parameters");
        potentials.reserve(parameters.size());

        for(auto para : parameters)
        {
            const auto idx = find_parameter<std::size_t>(para, env, "index");
            const auto pos = find_parameter<std::array<real_type, 3>>(para, env, "position");
            const auto crd = math::make_coordinate<coordinate_type>(pos[0], pos[1], pos[2]);

            // suppress warnings in read_harmonic_potential
            para.as_table().erase("index");
            para.as_table().erase("position");

            const auto pot = read_harmonic_potential<real_type>(para, env);
            potentials.emplace_back(idx, crd, pot);
        }
        return make_unique<interaction_t>(std::move(potentials));
    }
    else
    {
        throw_exception<std::runtime_error>(toml::format_error("[error] "
            "mjolnir::read_external_position_restraint_interaction: invalid potential",
            toml::find(external, "potential"), "here", {
            "expected value is one of the following.",
            "- \"Harmonic\": very famous `k(x-x0)^2` potential"
            }));
    }
}

template<typename traitsT>
std::unique_ptr<ExternalForceInteractionBase<traitsT>>
read_afm_flexible_fitting_interaction(const toml::value& external)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();
    using real_type     = typename traitsT::real_type;
    using interaction_t = AFMFitInteraction<traitsT>;

    const auto k        = toml::find<real_type  >(external, "k");
    const auto gamma    = toml::find<real_type  >(external, "gamma");
    const auto z0       = toml::find<real_type  >(external, "z0");
    const auto cutoff   = toml::find<real_type  >(external, "cutoff");
    const auto margin   = toml::find<real_type  >(external, "margin");
    const auto sigma_x  = toml::find<real_type  >(external, "sigma_x");
    const auto sigma_y  = toml::find<real_type  >(external, "sigma_y");
    const auto pixel_x  = toml::find<real_type  >(external, "pixel_x");
    const auto pixel_y  = toml::find<real_type  >(external, "pixel_y");
    const auto length_x = toml::find<std::size_t>(external, "length_x");
    const auto length_y = toml::find<std::size_t>(external, "length_y");

    const auto& env = external.as_table().count("env") != 0 ?
                      external.at("env") : toml::value{};

    // read radius and participants

    const auto& parameters = toml::find<toml::array>(external, "parameters");

    std::vector<std::pair<std::size_t, real_type>> radii;
    radii.reserve(parameters.size());
    for(const auto& para : parameters)
    {
        const auto idx = find_parameter<std::size_t>(para, env, "index");
        const auto rad = find_parameter<real_type  >(para, env, "radius");
        radii.emplace_back(idx, rad);
    }

    std::vector<real_type> image;
    image.reserve(length_x * length_y);
    for(real_type img : toml::find<std::vector<real_type>>(external, "image"))
    {
        image.push_back(img);
    }
    return make_unique<interaction_t>(k, gamma, z0, cutoff, margin,
        sigma_x, sigma_y, pixel_x, pixel_y, length_x, length_y, radii, image);
}

// ----------------------------------------------------------------------------
// general read_external_interaction function
// ----------------------------------------------------------------------------

template<typename traitsT>
std::unique_ptr<ExternalForceInteractionBase<traitsT>>
read_external_interaction(const toml::value& external)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();
    const auto interaction = toml::find<std::string>(external, "interaction");

    if(interaction == "Distance")
    {
        MJOLNIR_LOG_NOTICE("Distance interaction found.");
        return read_external_distance_interaction_shape<traitsT>(external);
    }
    else if(interaction == "PositionRestraint")
    {
        MJOLNIR_LOG_NOTICE("PositionRestraint interaction found.");
        return read_external_position_restraint_interaction<traitsT>(external);
    }
    else if(interaction == "AFMFlexibleFitting")
    {
        MJOLNIR_LOG_NOTICE("AFMFlexibleFitting interaction found.");
        return read_afm_flexible_fitting_interaction<traitsT>(external);
    }
    else
    {
        throw std::runtime_error(toml::format_error("[error] "
            "mjolnir::read_external_interaction: invalid interaction",
            toml::find(external, "interaction"), "here", {
            "expected value is one of the following.",
            "- \"Distance\":           interaction depending on the distance between a particle and a structure",
            "- \"PositionRestraint\":  interaction depending on the distance between a particle and a fixed point",
            "- \"AFMFlexibleFitting\": interaction that fits molecule to an AFM image"
            }));
    }
}

#ifdef MJOLNIR_SEPARATE_BUILD
extern template std::unique_ptr<ExternalForceInteractionBase<SimulatorTraits<double, UnlimitedBoundary>       >> read_external_interaction(const toml::value& external);
extern template std::unique_ptr<ExternalForceInteractionBase<SimulatorTraits<float,  UnlimitedBoundary>       >> read_external_interaction(const toml::value& external);
extern template std::unique_ptr<ExternalForceInteractionBase<SimulatorTraits<double, CuboidalPeriodicBoundary>>> read_external_interaction(const toml::value& external);
extern template std::unique_ptr<ExternalForceInteractionBase<SimulatorTraits<float,  CuboidalPeriodicBoundary>>> read_external_interaction(const toml::value& external);

extern template std::unique_ptr<ExternalForceInteractionBase<SimulatorTraits<double, UnlimitedBoundary>       >> read_external_position_restraint_interaction(const toml::value& external);
extern template std::unique_ptr<ExternalForceInteractionBase<SimulatorTraits<float,  UnlimitedBoundary>       >> read_external_position_restraint_interaction(const toml::value& external);
extern template std::unique_ptr<ExternalForceInteractionBase<SimulatorTraits<double, CuboidalPeriodicBoundary>>> read_external_position_restraint_interaction(const toml::value& external);
extern template std::unique_ptr<ExternalForceInteractionBase<SimulatorTraits<float,  CuboidalPeriodicBoundary>>> read_external_position_restraint_interaction(const toml::value& external);

extern template std::unique_ptr<ExternalForceInteractionBase<SimulatorTraits<double, UnlimitedBoundary>       >> read_external_distance_interaction_shape(const toml::value& external);
extern template std::unique_ptr<ExternalForceInteractionBase<SimulatorTraits<float,  UnlimitedBoundary>       >> read_external_distance_interaction_shape(const toml::value& external);
extern template std::unique_ptr<ExternalForceInteractionBase<SimulatorTraits<double, CuboidalPeriodicBoundary>>> read_external_distance_interaction_shape(const toml::value& external);
extern template std::unique_ptr<ExternalForceInteractionBase<SimulatorTraits<float,  CuboidalPeriodicBoundary>>> read_external_distance_interaction_shape(const toml::value& external);
#endif

} // mjolnir
#endif// MJOLNIR_READ_EXTERNAL_INTERACTION_HPP
<|endoftext|>


<commit_before>_Pragma("once")
#include <memory>

struct Node;
using sptr = std::shared_ptr<Node>;
using wptr = std::weak_ptr<Node>;
struct Node {
public:
	int data;
	enum class ColorType {RED, BLACK} color;
	sptr left, right;
	wptr parent;
};

class RedBlackBST {
public:
private:
	void right_rotate(sptr x) {
		sptr y{x->left};
		// turn y's right subtree into x's left subtree
		x->left = y->right;
		// TODO: Could we cancel the condition (y->right != nil)?
		y->right->parent = x;
		// link x's parent to y
		y->parent = x->parent;
		sptr parent{x->parent.lock()};
		if (parent == nil) root = y;
		else if (x == parent->left) parent->left = y;
		else parent->right = y;
		y->right = x;
		x->parent = y;
	}

	void left_rotate(sptr x) {
		sptr y{x->right};
		// turn y's left subtree into x's right subtree
		x->right = y->left;
		y->left->parent = x;
		// link x's parent to y
		y->parent = x->parent;
		sptr parent{x->parent.lock()};
		if (parent == nil) root = y;
		else if (x == parent->left) parent->left = y;
		else parent->right = y;
		y->left = x;
		x->parent = y;
	}
	sptr root, nil;
};<commit_msg>finish insert and reblance op<commit_after>_Pragma("once")
#include <memory>

struct Node;
using sptr = std::shared_ptr<Node>;
using wptr = std::weak_ptr<Node>;
enum class ctype {RED, BLACK};
struct Node {
public:
	Node(int d, wptr p, sptr l, sptr r, ctype c = ctype::RED)
		:data{d}, parent{p}, left{l}, right{r}, color{c} {}
	Node(ctype c):color{c} {}
	int data;
	wptr parent;
	sptr left, right;
	ctype color;
};

class RedBlackBST {
public:
	RedBlackBST(): nil{new Node{ctype::BLACK}} {
		root = nil;
	}
	void insert(int d) {
		sptr y{nil}, x{root};
		while (x != nil) {
			y = x;
			if (d < x->data) x = x->left;
			else x = x->right;
		}
		sptr z{new Node{d, y, nil, nil}};
		if (y == nil) root = z;
		else if (z->data < y->data) y->left = z;
		else y->right = z;
		insert_fixup(z);
	}

private:
	void insert_fixup(sptr z) {
		sptr zp{z->parent.lock()};
		while (zp->color == ctype::RED) {
			zp = z->parent.lock();
			sptr zpp{zp->parent.lock()};
			sptr uncle{zpp->right};
			if (zp == zpp->left) {
				// Case 1:the uncle node is red
				if (uncle->color == ctype::RED) {
					uncle->color = zp->color = ctype::BLACK;
					zpp->color = ctype::RED;
					z = zpp;
				} else {
				// Case 2/3:the uncle node of z is black
					if (z == zp->right) {
					// Case 2: ... and z is rightson
						z = zp; left_rotate(z);
					}
					// Case 3: ... and z is leftson
					zp->color = ctype::BLACK;
					zpp->color = ctype::RED;
					right_rotate(zpp);
				}
			} else {
			// same as clause with "right" and "left" exchanged
				// Case 1:the uncle node is red
				if (uncle->color == ctype::RED) {
					uncle->color = zp->color = ctype::BLACK;
					zpp->color = ctype::RED;
					z = zpp;
				} else {
				// Case 2/3:the uncle node of z is black
					if (z == zp->left) {
					// Case 2: ... and z is rightson
						z = zp; right_rotate(z);
					}
					// Case 3: ... and z is leftson
					zp->color = ctype::BLACK;
					zpp->color = ctype::RED;
					left_rotate(zpp);
				}
			}
		}
		root->color = ctype::BLACK;
	}

	void right_rotate(sptr x) {
		sptr y{x->left};
		// turn y's right subtree into x's left subtree
		x->left = y->right;
		// TODO: Could we cancel the condition (y->right != nil)?
		y->right->parent = x;
		// link x's parent to y
		y->parent = x->parent;
		sptr parent{x->parent.lock()};
		if (parent == nil) root = y;
		else if (x == parent->left) parent->left = y;
		else parent->right = y;
		y->right = x;
		x->parent = y;
	}

	void left_rotate(sptr x) {
		sptr y{x->right};
		// turn y's left subtree into x's right subtree
		x->right = y->left;
		y->left->parent = x;
		// link x's parent to y
		y->parent = x->parent;
		sptr parent{x->parent.lock()};
		if (parent == nil) root = y;
		else if (x == parent->left) parent->left = y;
		else parent->right = y;
		y->left = x;
		x->parent = y;
	}
	sptr root, nil;
};<|endoftext|>


<commit_before>//https://code.google.com/p/nya-engine/

#include "texture.h"
#include "platform_specific_gl.h"
#include "render.h"

namespace nya_render
{

bool texture::build_texture(const void *data,unsigned int width,unsigned int height,color_format format)
{
    if(width==0 || height==0)
    {
        get_log()<<"Unable to build texture: invalid width or height\n";
	    release();
        return false;
    }

    if(!m_max_tex_size)
    {
        GLint texSize;
        glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texSize);
        m_max_tex_size=texSize;
    }

    if(width>m_max_tex_size || height>m_max_tex_size)
    {
        get_log()<<"Unable to build texture: width or height is too high, maximum is "<<m_max_tex_size<<"\n";
	    release();
        return false;
    }

    unsigned int source_format=0;
    unsigned int gl_format=0;
    unsigned int precision=GL_UNSIGNED_BYTE;

    switch(format)
    {
        case color_rgb: source_format=GL_RGB; gl_format=GL_RGB; break;
        //case color_bgr: source_format=GL_RGB; gl_format=GL_BGR; break;
        case color_rgba: source_format=GL_RGBA; gl_format=GL_RGBA; break;
        case color_bgra: source_format=GL_RGBA; gl_format=GL_BGRA; break;
        case color_r: source_format=GL_LUMINANCE; gl_format=GL_LUMINANCE; break;
#ifdef OPENGL_ES
        case depth16: source_format=GL_DEPTH_COMPONENT; gl_format=GL_DEPTH_COMPONENT; precision=GL_UNSIGNED_SHORT; break;
        case depth24: source_format=GL_DEPTH_COMPONENT; gl_format=GL_DEPTH_COMPONENT; precision=GL_UNSIGNED_INT; break;
        case depth32: source_format=GL_DEPTH_COMPONENT; gl_format=GL_DEPTH_COMPONENT; precision=GL_UNSIGNED_INT; break;
#else
        case depth16: source_format=GL_DEPTH_COMPONENT16; gl_format=GL_DEPTH_COMPONENT; break;
        case depth24: source_format=GL_DEPTH_COMPONENT24; gl_format=GL_DEPTH_COMPONENT; break;
        case depth32: source_format=GL_DEPTH_COMPONENT32; gl_format=GL_DEPTH_COMPONENT; break;
#endif
    };

    if(!source_format || !gl_format)
    {
        get_log()<<"Unable to build texture: unsuppored color format\n";
	    release();
        return false;
    }

	//bool create_new=(!m_tex_id || m_width!=width || m_height!=height || m_type!=texture_2d || m_format!=format);

    if(!m_tex_id || m_gl_type!=GL_TEXTURE_2D)
        glGenTextures(1,&m_tex_id);

    m_width=width;
    m_height=height;
	m_gl_type=GL_TEXTURE_2D;
	m_format=format;

    glBindTexture(GL_TEXTURE_2D,m_tex_id);

    /*
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
    */

    const bool pot=((width&(width-1))==0 && (height&(height-1))==0);
    const bool has_mipmap=(data && pot);

#ifdef GL_GENERATE_MIPMAP
    if(has_mipmap)
        glTexParameteri(GL_TEXTURE_2D,GL_GENERATE_MIPMAP,GL_TRUE);
#endif
	//if(create_new)
	    glTexImage2D(GL_TEXTURE_2D,0,source_format,width,height,0,gl_format,precision,data);
	//else
	//	glTexSubImage2D(GL_TEXTURE_2D,0,0,0,width,height,gl_format,precision,data);
#ifndef GL_GENERATE_MIPMAP
    if(has_mipmap)
        glGenerateMipmap(GL_TEXTURE_2D);
#endif

    if(pot)
    {
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
    }
    else
    {
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
    }

    //if(format<depth16)
    {
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

        if(has_mipmap)
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
        else
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    }/*
    else
    {
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
    }*/

    return true;
}

bool texture::build_cubemap(const void *data[6],unsigned int width,unsigned int height,color_format format)
{
    if(!data || width==0 || height==0)
    {
        get_log()<<"Unable to build cube texture: invalid data/width/height\n";
	    release();
        return false;
    }

    if(!m_max_tex_size)
    {
        GLint texSize;
        glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texSize);
        m_max_tex_size=texSize;
    }

    if(width>m_max_tex_size || height>m_max_tex_size)
    {
        get_log()<<"Unable to build cube texture: width or height is too high, maximum is "<<m_max_tex_size<<"\n";
	    release();
        return false;
    }

    unsigned int source_format=0;
    unsigned int gl_format=0;

    switch(format)
    {
        case color_rgb: source_format=GL_RGB; gl_format=GL_RGB; break;
        //case color_bgr: source_format=GL_RGB; gl_format=GL_BGR; break;
        case color_rgba: source_format=GL_RGBA; gl_format=GL_RGBA; break;
        case color_bgra: source_format=GL_RGBA; gl_format=GL_BGRA; break;
        case color_r: source_format=GL_LUMINANCE; gl_format=GL_LUMINANCE; break;
        default: break;
    };

    if(!source_format || !gl_format)
    {
        get_log()<<"Unable to build cube texture: unsuppored color format\n";
	    release();
        return false;
    }

	if(m_format!=format)
		release();

	//bool create_new=(!m_tex_id || m_width!=width || m_height!=height || m_type!=texture_2d || m_format!=format);

    m_width=width;
    m_height=height;
	m_gl_type=GL_TEXTURE_CUBE_MAP;
	m_format=format;

    if(!m_tex_id)
        glGenTextures(1,&m_tex_id);

    glBindTexture(GL_TEXTURE_CUBE_MAP,m_tex_id);

#ifdef GL_GENERATE_MIPMAP
    glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_GENERATE_MIPMAP,GL_TRUE);
#endif

	const unsigned int cube_faces[]={GL_TEXTURE_CUBE_MAP_POSITIVE_X,GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
									 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
									 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,GL_TEXTURE_CUBE_MAP_NEGATIVE_Z};

	for(int i=0;i<sizeof(cube_faces)/sizeof(cube_faces[0]);++i)
		glTexImage2D(cube_faces[i],0,source_format,width,height,0,gl_format,GL_UNSIGNED_BYTE,data[i]);

#ifndef GL_GENERATE_MIPMAP
    glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
#endif

    glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);

    return true;
}

void texture::bind() const
{
	if(!m_gl_type)
	{
		unbind_all();
		return;
	}

    glBindTexture(m_gl_type,m_tex_id);
}

void texture::unbind() const
{
	if(!m_gl_type)
	{
		unbind_all();
		return;
	}

	glBindTexture(m_gl_type,0);
}

void texture::unbind_all()
{
    glBindTexture(GL_TEXTURE_2D,0);
    glBindTexture(GL_TEXTURE_CUBE_MAP,0);
}

void texture::select_multitex_slot(unsigned int idx)
{
#if defined(OPENGL_ES)
    glActiveTexture(GL_TEXTURE0+idx);
#elif defined(NO_EXTENSIONS_INIT)
    glActiveTexture(GL_TEXTURE0+idx);
#else
    static PFNGLACTIVETEXTUREARBPROC tex_glActiveTexture=0;

    static bool initialised=false;
    if(tex_glActiveTexture!=0)
    {
        tex_glActiveTexture(GL_TEXTURE0_ARB+idx);
        return;
    }

    if(initialised)
        return;

    tex_glActiveTexture=(PFNGLACTIVETEXTUREARBPROC)get_extension("glActiveTexture");
    initialised=true;

    select_multitex_slot(idx);
#endif
}

void texture::release()
{
    if(m_tex_id)
	    glDeleteTextures(1,&m_tex_id);

    m_tex_id=0;
    m_width=0;
    m_height=0;
}

}

<commit_msg>cubemap filtering changed<commit_after>//https://code.google.com/p/nya-engine/

#include "texture.h"
#include "platform_specific_gl.h"
#include "render.h"

namespace nya_render
{

bool texture::build_texture(const void *data,unsigned int width,unsigned int height,color_format format)
{
    if(width==0 || height==0)
    {
        get_log()<<"Unable to build texture: invalid width or height\n";
	    release();
        return false;
    }

    if(!m_max_tex_size)
    {
        GLint texSize;
        glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texSize);
        m_max_tex_size=texSize;
    }

    if(width>m_max_tex_size || height>m_max_tex_size)
    {
        get_log()<<"Unable to build texture: width or height is too high, maximum is "<<m_max_tex_size<<"\n";
	    release();
        return false;
    }

    unsigned int source_format=0;
    unsigned int gl_format=0;
    unsigned int precision=GL_UNSIGNED_BYTE;

    switch(format)
    {
        case color_rgb: source_format=GL_RGB; gl_format=GL_RGB; break;
        //case color_bgr: source_format=GL_RGB; gl_format=GL_BGR; break;
        case color_rgba: source_format=GL_RGBA; gl_format=GL_RGBA; break;
        case color_bgra: source_format=GL_RGBA; gl_format=GL_BGRA; break;
        case color_r: source_format=GL_LUMINANCE; gl_format=GL_LUMINANCE; break;
#ifdef OPENGL_ES
        case depth16: source_format=GL_DEPTH_COMPONENT; gl_format=GL_DEPTH_COMPONENT; precision=GL_UNSIGNED_SHORT; break;
        case depth24: source_format=GL_DEPTH_COMPONENT; gl_format=GL_DEPTH_COMPONENT; precision=GL_UNSIGNED_INT; break;
        case depth32: source_format=GL_DEPTH_COMPONENT; gl_format=GL_DEPTH_COMPONENT; precision=GL_UNSIGNED_INT; break;
#else
        case depth16: source_format=GL_DEPTH_COMPONENT16; gl_format=GL_DEPTH_COMPONENT; break;
        case depth24: source_format=GL_DEPTH_COMPONENT24; gl_format=GL_DEPTH_COMPONENT; break;
        case depth32: source_format=GL_DEPTH_COMPONENT32; gl_format=GL_DEPTH_COMPONENT; break;
#endif
    };

    if(!source_format || !gl_format)
    {
        get_log()<<"Unable to build texture: unsuppored color format\n";
	    release();
        return false;
    }

	//bool create_new=(!m_tex_id || m_width!=width || m_height!=height || m_type!=texture_2d || m_format!=format);

    if(!m_tex_id || m_gl_type!=GL_TEXTURE_2D)
        glGenTextures(1,&m_tex_id);

    m_width=width;
    m_height=height;
	m_gl_type=GL_TEXTURE_2D;
	m_format=format;

    glBindTexture(GL_TEXTURE_2D,m_tex_id);

    /*
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
    */

    const bool pot=((width&(width-1))==0 && (height&(height-1))==0);
    const bool has_mipmap=(data && pot);

#ifdef GL_GENERATE_MIPMAP
    if(has_mipmap)
        glTexParameteri(GL_TEXTURE_2D,GL_GENERATE_MIPMAP,GL_TRUE);
#endif
	//if(create_new)
	    glTexImage2D(GL_TEXTURE_2D,0,source_format,width,height,0,gl_format,precision,data);
	//else
	//	glTexSubImage2D(GL_TEXTURE_2D,0,0,0,width,height,gl_format,precision,data);
#ifndef GL_GENERATE_MIPMAP
    if(has_mipmap)
        glGenerateMipmap(GL_TEXTURE_2D);
#endif

    if(pot)
    {
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
    }
    else
    {
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
    }

    //if(format<depth16)
    {
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

        if(has_mipmap)
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
        else
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    }/*
    else
    {
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
    }*/

    return true;
}

bool texture::build_cubemap(const void *data[6],unsigned int width,unsigned int height,color_format format)
{
    if(!data || width==0 || height==0)
    {
        get_log()<<"Unable to build cube texture: invalid data/width/height\n";
	    release();
        return false;
    }

    if(!m_max_tex_size)
    {
        GLint texSize;
        glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texSize);
        m_max_tex_size=texSize;
    }

    if(width>m_max_tex_size || height>m_max_tex_size)
    {
        get_log()<<"Unable to build cube texture: width or height is too high, maximum is "<<m_max_tex_size<<"\n";
	    release();
        return false;
    }

    unsigned int source_format=0;
    unsigned int gl_format=0;

    switch(format)
    {
        case color_rgb: source_format=GL_RGB; gl_format=GL_RGB; break;
        //case color_bgr: source_format=GL_RGB; gl_format=GL_BGR; break;
        case color_rgba: source_format=GL_RGBA; gl_format=GL_RGBA; break;
        case color_bgra: source_format=GL_RGBA; gl_format=GL_BGRA; break;
        case color_r: source_format=GL_LUMINANCE; gl_format=GL_LUMINANCE; break;
        default: break;
    };

    if(!source_format || !gl_format)
    {
        get_log()<<"Unable to build cube texture: unsuppored color format\n";
	    release();
        return false;
    }

	if(m_format!=format)
		release();

	//bool create_new=(!m_tex_id || m_width!=width || m_height!=height || m_type!=texture_2d || m_format!=format);

    m_width=width;
    m_height=height;
	m_gl_type=GL_TEXTURE_CUBE_MAP;
	m_format=format;

    if(!m_tex_id)
        glGenTextures(1,&m_tex_id);

    glBindTexture(GL_TEXTURE_CUBE_MAP,m_tex_id);

#ifdef GL_GENERATE_MIPMAP
    glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_GENERATE_MIPMAP,GL_TRUE);
#endif

	const unsigned int cube_faces[]={GL_TEXTURE_CUBE_MAP_POSITIVE_X,GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
									 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
									 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,GL_TEXTURE_CUBE_MAP_NEGATIVE_Z};

	for(int i=0;i<sizeof(cube_faces)/sizeof(cube_faces[0]);++i)
		glTexImage2D(cube_faces[i],0,source_format,width,height,0,gl_format,GL_UNSIGNED_BYTE,data[i]);

#ifndef GL_GENERATE_MIPMAP
    glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
#endif

    glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);

    return true;
}

void texture::bind() const
{
	if(!m_gl_type)
	{
		unbind_all();
		return;
	}

    glBindTexture(m_gl_type,m_tex_id);
}

void texture::unbind() const
{
	if(!m_gl_type)
	{
		unbind_all();
		return;
	}

	glBindTexture(m_gl_type,0);
}

void texture::unbind_all()
{
    glBindTexture(GL_TEXTURE_2D,0);
    glBindTexture(GL_TEXTURE_CUBE_MAP,0);
}

void texture::select_multitex_slot(unsigned int idx)
{
#if defined(OPENGL_ES)
    glActiveTexture(GL_TEXTURE0+idx);
#elif defined(NO_EXTENSIONS_INIT)
    glActiveTexture(GL_TEXTURE0+idx);
#else
    static PFNGLACTIVETEXTUREARBPROC tex_glActiveTexture=0;

    static bool initialised=false;
    if(tex_glActiveTexture!=0)
    {
        tex_glActiveTexture(GL_TEXTURE0_ARB+idx);
        return;
    }

    if(initialised)
        return;

    tex_glActiveTexture=(PFNGLACTIVETEXTUREARBPROC)get_extension("glActiveTexture");
    initialised=true;

    select_multitex_slot(idx);
#endif
}

void texture::release()
{
    if(m_tex_id)
	    glDeleteTextures(1,&m_tex_id);

    m_tex_id=0;
    m_width=0;
    m_height=0;
}

}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: dstribut.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 15:09:00 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifdef SVX_DLLIMPLEMENTATION
#undef SVX_DLLIMPLEMENTATION
#endif

#ifndef _BASEDLGS_HXX
#include <sfx2/basedlgs.hxx>
#endif

#include "dialogs.hrc"
#include "dstribut.hxx"
#include "dstribut.hrc"

#include "svddef.hxx"
#include "dialmgr.hxx"

#ifndef _SHL_HXX
#include <tools/shl.hxx>
#endif

static USHORT pRanges[] =
{
    SDRATTR_MEASURE_FIRST,
    SDRATTR_MEASURE_LAST,
    0
};

/*************************************************************************
|*
|* Dialog
|*
\************************************************************************/

SvxDistributeDialog::SvxDistributeDialog(
    Window* pParent,
    const SfxItemSet& rInAttrs,
    SvxDistributeHorizontal eHor,
    SvxDistributeVertical eVer)
:   SfxSingleTabDialog(pParent, rInAttrs, RID_SVXPAGE_DISTRIBUTE ),
    mpPage(0L)
{
    mpPage = new SvxDistributePage(this, rInAttrs, eHor, eVer);
    SetTabPage(mpPage);
    SetText(mpPage->GetText());
}

/*************************************************************************
|*
|* Dtor
|*
\************************************************************************/

SvxDistributeDialog::~SvxDistributeDialog()
{
}

/*************************************************************************
|*
|* Tabpage
|*
\************************************************************************/

SvxDistributePage::SvxDistributePage(
    Window* pWindow,
    const SfxItemSet& rInAttrs,
    SvxDistributeHorizontal eHor,
    SvxDistributeVertical eVer)
:   SvxTabPage(pWindow, ResId(RID_SVXPAGE_DISTRIBUTE, DIALOG_MGR()), rInAttrs),
    meDistributeHor(eHor),
    meDistributeVer(eVer),
    maFlHorizontal      (this, ResId(FL_HORIZONTAL      )),
    maBtnHorNone        (this, ResId(BTN_HOR_NONE       )),
    maBtnHorLeft        (this, ResId(BTN_HOR_LEFT       )),
    maBtnHorCenter      (this, ResId(BTN_HOR_CENTER     )),
    maBtnHorDistance    (this, ResId(BTN_HOR_DISTANCE   )),
    maBtnHorRight       (this, ResId(BTN_HOR_RIGHT      )),
    maHorLow            (this, ResId(IMG_HOR_LOW        )),
    maHorCenter         (this, ResId(IMG_HOR_CENTER     )),
    maHorDistance       (this, ResId(IMG_HOR_DISTANCE   )),
    maHorHigh           (this, ResId(IMG_HOR_HIGH       )),
    maFlVertical        (this, ResId(FL_VERTICAL        )),
    maBtnVerNone        (this, ResId(BTN_VER_NONE       )),
    maBtnVerTop         (this, ResId(BTN_VER_TOP        )),
    maBtnVerCenter      (this, ResId(BTN_VER_CENTER     )),
    maBtnVerDistance    (this, ResId(BTN_VER_DISTANCE   )),
    maBtnVerBottom      (this, ResId(BTN_VER_BOTTOM     )),
    maVerLow            (this, ResId(IMG_VER_LOW        )),
    maVerCenter         (this, ResId(IMG_VER_CENTER     )),
    maVerDistance       (this, ResId(IMG_VER_DISTANCE   )),
    maVerHigh           (this, ResId(IMG_VER_HIGH       ))
{
    maHorLow.SetModeImage( Image( ResId( IMG_HOR_LOW_H ) ), BMP_COLOR_HIGHCONTRAST );
    maHorCenter.SetModeImage( Image( ResId( IMG_HOR_CENTER_H ) ), BMP_COLOR_HIGHCONTRAST );
    maHorDistance.SetModeImage( Image( ResId( IMG_HOR_DISTANCE_H ) ), BMP_COLOR_HIGHCONTRAST );
    maHorHigh.SetModeImage( Image( ResId( IMG_HOR_HIGH_H ) ), BMP_COLOR_HIGHCONTRAST );
    maVerDistance.SetModeImage( Image( ResId( IMG_VER_DISTANCE_H ) ), BMP_COLOR_HIGHCONTRAST );
    maVerLow.SetModeImage( Image( ResId( IMG_VER_LOW_H ) ), BMP_COLOR_HIGHCONTRAST );
    maVerCenter.SetModeImage( Image( ResId( IMG_VER_CENTER_H ) ), BMP_COLOR_HIGHCONTRAST );
    maVerHigh.SetModeImage( Image( ResId( IMG_VER_HIGH_H ) ), BMP_COLOR_HIGHCONTRAST );

    FreeResource();
}

/*************************************************************************
|*
|* Dtor
|*
\************************************************************************/

SvxDistributePage::~SvxDistributePage()
{
}

/*************************************************************************
|*
|* create the tabpage
|*
\************************************************************************/

SfxTabPage* SvxDistributePage::Create(Window* pWindow, const SfxItemSet& rAttrs,
    SvxDistributeHorizontal eHor, SvxDistributeVertical eVer)
{
    return(new SvxDistributePage(pWindow, rAttrs, eHor, eVer));
}

/*************************************************************************
|*
|*
|*
\************************************************************************/

UINT16* SvxDistributePage::GetRanges()
{
    return(pRanges);
}

/*************************************************************************
|*
|*
|*
\************************************************************************/

void SvxDistributePage::PointChanged(Window* /*pWindow*/, RECT_POINT /*eRP*/)
{
}

/*************************************************************************
|*
|* read the delivered Item-Set
|*
\************************************************************************/

void __EXPORT SvxDistributePage::Reset(const SfxItemSet& )
{
    maBtnHorNone.SetState(FALSE);
    maBtnHorLeft.SetState(FALSE);
    maBtnHorCenter.SetState(FALSE);
    maBtnHorDistance.SetState(FALSE);
    maBtnHorRight.SetState(FALSE);

    switch(meDistributeHor)
    {
        case SvxDistributeHorizontalNone : maBtnHorNone.SetState(TRUE); break;
        case SvxDistributeHorizontalLeft : maBtnHorLeft.SetState(TRUE); break;
        case SvxDistributeHorizontalCenter : maBtnHorCenter.SetState(TRUE); break;
        case SvxDistributeHorizontalDistance : maBtnHorDistance.SetState(TRUE); break;
        case SvxDistributeHorizontalRight : maBtnHorRight.SetState(TRUE); break;
    }

    maBtnVerNone.SetState(FALSE);
    maBtnVerTop.SetState(FALSE);
    maBtnVerCenter.SetState(FALSE);
    maBtnVerDistance.SetState(FALSE);
    maBtnVerBottom.SetState(FALSE);

    switch(meDistributeVer)
    {
        case SvxDistributeVerticalNone : maBtnVerNone.SetState(TRUE); break;
        case SvxDistributeVerticalTop : maBtnVerTop.SetState(TRUE); break;
        case SvxDistributeVerticalCenter : maBtnVerCenter.SetState(TRUE); break;
        case SvxDistributeVerticalDistance : maBtnVerDistance.SetState(TRUE); break;
        case SvxDistributeVerticalBottom : maBtnVerBottom.SetState(TRUE); break;
    }
}

/*************************************************************************
|*
|* Fill the delivered Item-Set with dialogbox-attributes
|*
\************************************************************************/

BOOL SvxDistributePage::FillItemSet( SfxItemSet& )
{
    SvxDistributeHorizontal eDistributeHor(SvxDistributeHorizontalNone);
    SvxDistributeVertical eDistributeVer(SvxDistributeVerticalNone);

    if(maBtnHorLeft.IsChecked())
        eDistributeHor = SvxDistributeHorizontalLeft;
    else if(maBtnHorCenter.IsChecked())
        eDistributeHor = SvxDistributeHorizontalCenter;
    else if(maBtnHorDistance.IsChecked())
        eDistributeHor = SvxDistributeHorizontalDistance;
    else if(maBtnHorRight.IsChecked())
        eDistributeHor = SvxDistributeHorizontalRight;

    if(maBtnVerTop.IsChecked())
        eDistributeVer = SvxDistributeVerticalTop;
    else if(maBtnVerCenter.IsChecked())
        eDistributeVer = SvxDistributeVerticalCenter;
    else if(maBtnVerDistance.IsChecked())
        eDistributeVer = SvxDistributeVerticalDistance;
    else if(maBtnVerBottom.IsChecked())
        eDistributeVer = SvxDistributeVerticalBottom;

    if(eDistributeHor != meDistributeHor || eDistributeVer != meDistributeVer)
    {
        meDistributeHor = eDistributeHor;
        meDistributeVer = eDistributeVer;
        return TRUE;
    }

    return FALSE;
}

<commit_msg>INTEGRATION: CWS pchfix02 (1.8.116); FILE MERGED 2006/09/01 17:46:10 kaib 1.8.116.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: dstribut.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 04:19:04 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"

#ifdef SVX_DLLIMPLEMENTATION
#undef SVX_DLLIMPLEMENTATION
#endif

#ifndef _BASEDLGS_HXX
#include <sfx2/basedlgs.hxx>
#endif

#include "dialogs.hrc"
#include "dstribut.hxx"
#include "dstribut.hrc"

#include "svddef.hxx"
#include "dialmgr.hxx"

#ifndef _SHL_HXX
#include <tools/shl.hxx>
#endif

static USHORT pRanges[] =
{
    SDRATTR_MEASURE_FIRST,
    SDRATTR_MEASURE_LAST,
    0
};

/*************************************************************************
|*
|* Dialog
|*
\************************************************************************/

SvxDistributeDialog::SvxDistributeDialog(
    Window* pParent,
    const SfxItemSet& rInAttrs,
    SvxDistributeHorizontal eHor,
    SvxDistributeVertical eVer)
:   SfxSingleTabDialog(pParent, rInAttrs, RID_SVXPAGE_DISTRIBUTE ),
    mpPage(0L)
{
    mpPage = new SvxDistributePage(this, rInAttrs, eHor, eVer);
    SetTabPage(mpPage);
    SetText(mpPage->GetText());
}

/*************************************************************************
|*
|* Dtor
|*
\************************************************************************/

SvxDistributeDialog::~SvxDistributeDialog()
{
}

/*************************************************************************
|*
|* Tabpage
|*
\************************************************************************/

SvxDistributePage::SvxDistributePage(
    Window* pWindow,
    const SfxItemSet& rInAttrs,
    SvxDistributeHorizontal eHor,
    SvxDistributeVertical eVer)
:   SvxTabPage(pWindow, ResId(RID_SVXPAGE_DISTRIBUTE, DIALOG_MGR()), rInAttrs),
    meDistributeHor(eHor),
    meDistributeVer(eVer),
    maFlHorizontal      (this, ResId(FL_HORIZONTAL      )),
    maBtnHorNone        (this, ResId(BTN_HOR_NONE       )),
    maBtnHorLeft        (this, ResId(BTN_HOR_LEFT       )),
    maBtnHorCenter      (this, ResId(BTN_HOR_CENTER     )),
    maBtnHorDistance    (this, ResId(BTN_HOR_DISTANCE   )),
    maBtnHorRight       (this, ResId(BTN_HOR_RIGHT      )),
    maHorLow            (this, ResId(IMG_HOR_LOW        )),
    maHorCenter         (this, ResId(IMG_HOR_CENTER     )),
    maHorDistance       (this, ResId(IMG_HOR_DISTANCE   )),
    maHorHigh           (this, ResId(IMG_HOR_HIGH       )),
    maFlVertical        (this, ResId(FL_VERTICAL        )),
    maBtnVerNone        (this, ResId(BTN_VER_NONE       )),
    maBtnVerTop         (this, ResId(BTN_VER_TOP        )),
    maBtnVerCenter      (this, ResId(BTN_VER_CENTER     )),
    maBtnVerDistance    (this, ResId(BTN_VER_DISTANCE   )),
    maBtnVerBottom      (this, ResId(BTN_VER_BOTTOM     )),
    maVerLow            (this, ResId(IMG_VER_LOW        )),
    maVerCenter         (this, ResId(IMG_VER_CENTER     )),
    maVerDistance       (this, ResId(IMG_VER_DISTANCE   )),
    maVerHigh           (this, ResId(IMG_VER_HIGH       ))
{
    maHorLow.SetModeImage( Image( ResId( IMG_HOR_LOW_H ) ), BMP_COLOR_HIGHCONTRAST );
    maHorCenter.SetModeImage( Image( ResId( IMG_HOR_CENTER_H ) ), BMP_COLOR_HIGHCONTRAST );
    maHorDistance.SetModeImage( Image( ResId( IMG_HOR_DISTANCE_H ) ), BMP_COLOR_HIGHCONTRAST );
    maHorHigh.SetModeImage( Image( ResId( IMG_HOR_HIGH_H ) ), BMP_COLOR_HIGHCONTRAST );
    maVerDistance.SetModeImage( Image( ResId( IMG_VER_DISTANCE_H ) ), BMP_COLOR_HIGHCONTRAST );
    maVerLow.SetModeImage( Image( ResId( IMG_VER_LOW_H ) ), BMP_COLOR_HIGHCONTRAST );
    maVerCenter.SetModeImage( Image( ResId( IMG_VER_CENTER_H ) ), BMP_COLOR_HIGHCONTRAST );
    maVerHigh.SetModeImage( Image( ResId( IMG_VER_HIGH_H ) ), BMP_COLOR_HIGHCONTRAST );

    FreeResource();
}

/*************************************************************************
|*
|* Dtor
|*
\************************************************************************/

SvxDistributePage::~SvxDistributePage()
{
}

/*************************************************************************
|*
|* create the tabpage
|*
\************************************************************************/

SfxTabPage* SvxDistributePage::Create(Window* pWindow, const SfxItemSet& rAttrs,
    SvxDistributeHorizontal eHor, SvxDistributeVertical eVer)
{
    return(new SvxDistributePage(pWindow, rAttrs, eHor, eVer));
}

/*************************************************************************
|*
|*
|*
\************************************************************************/

UINT16* SvxDistributePage::GetRanges()
{
    return(pRanges);
}

/*************************************************************************
|*
|*
|*
\************************************************************************/

void SvxDistributePage::PointChanged(Window* /*pWindow*/, RECT_POINT /*eRP*/)
{
}

/*************************************************************************
|*
|* read the delivered Item-Set
|*
\************************************************************************/

void __EXPORT SvxDistributePage::Reset(const SfxItemSet& )
{
    maBtnHorNone.SetState(FALSE);
    maBtnHorLeft.SetState(FALSE);
    maBtnHorCenter.SetState(FALSE);
    maBtnHorDistance.SetState(FALSE);
    maBtnHorRight.SetState(FALSE);

    switch(meDistributeHor)
    {
        case SvxDistributeHorizontalNone : maBtnHorNone.SetState(TRUE); break;
        case SvxDistributeHorizontalLeft : maBtnHorLeft.SetState(TRUE); break;
        case SvxDistributeHorizontalCenter : maBtnHorCenter.SetState(TRUE); break;
        case SvxDistributeHorizontalDistance : maBtnHorDistance.SetState(TRUE); break;
        case SvxDistributeHorizontalRight : maBtnHorRight.SetState(TRUE); break;
    }

    maBtnVerNone.SetState(FALSE);
    maBtnVerTop.SetState(FALSE);
    maBtnVerCenter.SetState(FALSE);
    maBtnVerDistance.SetState(FALSE);
    maBtnVerBottom.SetState(FALSE);

    switch(meDistributeVer)
    {
        case SvxDistributeVerticalNone : maBtnVerNone.SetState(TRUE); break;
        case SvxDistributeVerticalTop : maBtnVerTop.SetState(TRUE); break;
        case SvxDistributeVerticalCenter : maBtnVerCenter.SetState(TRUE); break;
        case SvxDistributeVerticalDistance : maBtnVerDistance.SetState(TRUE); break;
        case SvxDistributeVerticalBottom : maBtnVerBottom.SetState(TRUE); break;
    }
}

/*************************************************************************
|*
|* Fill the delivered Item-Set with dialogbox-attributes
|*
\************************************************************************/

BOOL SvxDistributePage::FillItemSet( SfxItemSet& )
{
    SvxDistributeHorizontal eDistributeHor(SvxDistributeHorizontalNone);
    SvxDistributeVertical eDistributeVer(SvxDistributeVerticalNone);

    if(maBtnHorLeft.IsChecked())
        eDistributeHor = SvxDistributeHorizontalLeft;
    else if(maBtnHorCenter.IsChecked())
        eDistributeHor = SvxDistributeHorizontalCenter;
    else if(maBtnHorDistance.IsChecked())
        eDistributeHor = SvxDistributeHorizontalDistance;
    else if(maBtnHorRight.IsChecked())
        eDistributeHor = SvxDistributeHorizontalRight;

    if(maBtnVerTop.IsChecked())
        eDistributeVer = SvxDistributeVerticalTop;
    else if(maBtnVerCenter.IsChecked())
        eDistributeVer = SvxDistributeVerticalCenter;
    else if(maBtnVerDistance.IsChecked())
        eDistributeVer = SvxDistributeVerticalDistance;
    else if(maBtnVerBottom.IsChecked())
        eDistributeVer = SvxDistributeVerticalBottom;

    if(eDistributeHor != meDistributeHor || eDistributeVer != meDistributeVer)
    {
        meDistributeHor = eDistributeHor;
        meDistributeVer = eDistributeVer;
        return TRUE;
    }

    return FALSE;
}

<|endoftext|>


<commit_before>#include "compiler.h"

#include <QString>
#include <QList>
#include <QSet>
#include <QVector>

using namespace std;

/* Implementation note: wire naming convention
 *
 * All wire names must be unique. To ensure uniqueness, their names are a
 * combination of the block number and pin name of the pin that drives it,
 * as follows:
 *
 * wire_<blocknumber>_<pinname>
 */

QString generatePicCode(FlowChart flow) {
    QSet<QString> blockNames = extractUniqueBlockNames(flow);
    QString mainFile = "int main() {\n\n";
    QSet<int> expanded;
    QList<int> toBeExpanded = extractInputBlocks(flow);
    QSet<QString> wires = extractWireNames(flow);
    QList<QString> structInstances;
    // directed graph traversal: write the sequence of functions
    while(!toBeExpanded.empty()) {
        int blockIndex = toBeExpanded.front();
        toBeExpanded.pop_front();
        // if this block has not been expanded yet
        if (expanded.find(blockIndex) == expanded.end()) {
            Block block = flow.block(blockIndex);
            // check if all this block's inputs have been expanded
            bool found_all = isExpandable(block, expanded);
            if(found_all) {
                // mark this node as expanded
                expanded.insert(blockIndex);
                // add all of this node's outputs to the front of the queue
                for(auto output : block.outputConnections().values()) {
                    for(BlockPin element : output){
                      int outIndex = element.blockNum();
                      if (!expanded.contains(outIndex)) {
                        toBeExpanded.push_front(outIndex);
                      }
                    }
                }
                // write this node's function call
                QVector<BlockPin> wireBlockPins;
                for (QString inputPinName : block.blockType().inputs().keys()) {
                    if (!block.inputIsConnected(inputPinName)) {
                        // error: bad structure
                        return "";
                    } else {
                        BlockPin wireSource = block.inputConnections()[inputPinName];
                        wireBlockPins.push_back(wireSource);
                    }
                }
                for (QString outputPinName : block.blockType().outputs().keys()) {
                    BlockPin outputBlockPin(blockIndex, outputPinName);
                    wireBlockPins.push_back(outputBlockPin);
                }
                QString funcCall = block.blockType().name();
                funcCall += "(";
                funcCall += "block_options_";
                funcCall += QString::number(blockIndex);
                if (0 < wireBlockPins.size()) {
                    funcCall += ",";
                }
                for (int i = 0; i < wireBlockPins.size(); i++) {
                    BlockPin wireSource = wireBlockPins[i];
                    funcCall += "&wire_";
                    funcCall += QString::number(wireSource.blockNum());
                    funcCall += "_";
                    funcCall += wireSource.pinName();
                    if (i < wireBlockPins.size() - 1) {
                        funcCall += ",";
                    }
                }
                funcCall += ");";
                mainFile += funcCall;
                mainFile += "\n";
                // write this node's struct instance
                QString structInstance = "struct ";
                structInstance += block.blockType().name();
                structInstance += "_options ";
                structInstance += "block_options_";
                structInstance += QString::number(blockIndex);
                structInstance += ";\n";
                for (QString optionName : block.blockType().options().keys()) {
                    QString optionValue = block.optionValues()[optionName];
                    structInstance += "block_options_";
                    structInstance += QString::number(blockIndex);
                    structInstance += ".";
                    structInstance += optionName;
                    structInstance += " = ";
                    structInstance += optionValue; // TODO: factor in data type
                    structInstance += ";\n";
                }
                structInstances.append(structInstance);
            } else {
               toBeExpanded.push_back(blockIndex);
            }
        }
    }
    mainFile += "\nreturn 0;\n\n}";

    QString includesFile = "#include <avr/io.h>\n";
    for (QString blockName : blockNames) {
        includesFile += "#include \"blocks/";
        includesFile += blockName;
        includesFile += ".h\"\n";
    }
    includesFile += "\n";

    QString structInstancesFile;
    for (QString structInstance : structInstances) {
        structInstancesFile += structInstance;
    }
    structInstancesFile += "\n";

    QString declarationsFile = "";
    for (QString wireName : wires) {
        declarationsFile += "int ";
        declarationsFile += wireName;
        declarationsFile += ";\n";
    }
    declarationsFile += "\n";

    return includesFile + structInstancesFile + declarationsFile + mainFile;
}

QSet<QString> extractUniqueBlockNames(FlowChart flow) {
    QSet<QString> blockNames;
    for(Block block : flow.blocks().values()) {
        // make sure this block's name is in the blockNames set
        blockNames.insert(block.blockType().name());
    }
    return blockNames;
}

QList<int> extractInputBlocks(FlowChart flow) {
    QList<int> inputBlocks;
    for(int blockIndex : flow.blocks().keys()) {
        Block block = flow.block(blockIndex);
        // If this is an input block, make sure it's expanded first
        if(block.inputConnections().empty()) {
            inputBlocks.push_back(blockIndex);
        }
    }
    return inputBlocks;
}

QSet<QString> extractWireNames(FlowChart flow) {
    QSet<QString> wireNames;
    for(int blockIndex : flow.blocks().keys()) {
        Block block = flow.block(blockIndex);
        // for each output connection
        for (QString pinName : block.outputConnections().keys()) {
            // construct wire name
            QString wireName = "wire_";
            wireName += QString::number(blockIndex);
            wireName += "_";
            wireName += pinName;
            wireNames.insert(wireName);
        }
    }
    return wireNames;
}

bool isExpandable(Block block, QSet<int> expanded) {
    bool found_all = true;
    for(BlockPin bp : block.inputConnections().values()) {
        int blockNum = bp.blockNum();
        if(expanded.find(blockNum) == expanded.end()) {
            found_all = false;
            break;
        }
    }
    return found_all;
}
<commit_msg>Fix compiler typo<commit_after>#include "compiler.h"

#include <QString>
#include <QList>
#include <QSet>
#include <QVector>

using namespace std;

/* Implementation note: wire naming convention
 *
 * All wire names must be unique. To ensure uniqueness, their names are a
 * combination of the block number and pin name of the pin that drives it,
 * as follows:
 *
 * wire_<blocknumber>_<pinname>
 */

QString generatePicCode(FlowChart flow) {
    QSet<QString> blockNames = extractUniqueBlockNames(flow);
    QString mainFile = "int main() {\n\n";
    QSet<int> expanded;
    QList<int> toBeExpanded = extractInputBlocks(flow);
    QSet<QString> wires = extractWireNames(flow);
    QList<QString> structInstances;
    // directed graph traversal: write the sequence of functions
    while(!toBeExpanded.empty()) {
        int blockIndex = toBeExpanded.front();
        toBeExpanded.pop_front();
        // if this block has not been expanded yet
        if (expanded.find(blockIndex) == expanded.end()) {
            Block block = flow.block(blockIndex);
            // check if all this block's inputs have been expanded
            bool found_all = isExpandable(block, expanded);
            if(found_all) {
                // mark this node as expanded
                expanded.insert(blockIndex);
                // add all of this node's outputs to the front of the queue
                for(auto output : block.outputConnections().values()) {
                    for(BlockPin element : output){
                      int outIndex = element.blockNum();
                      if (!expanded.contains(outIndex)) {
                        toBeExpanded.push_front(outIndex);
                      }
                    }
                }
                // write this node's function call
                QVector<BlockPin> wireBlockPins;
                for (QString inputPinName : block.blockType().inputs().keys()) {
                    if (!block.inputIsConnected(inputPinName)) {
                        // error: bad structure
                        return "";
                    } else {
                        BlockPin wireSource = block.inputConnections()[inputPinName];
                        wireBlockPins.push_back(wireSource);
                    }
                }
                for (QString outputPinName : block.blockType().outputs().keys()) {
                    BlockPin outputBlockPin(blockIndex, outputPinName);
                    wireBlockPins.push_back(outputBlockPin);
                }
                QString funcCall = block.blockType().name();
                funcCall += "(";
                funcCall += "&block_options_";
                funcCall += QString::number(blockIndex);
                if (0 < wireBlockPins.size()) {
                    funcCall += ",";
                }
                for (int i = 0; i < wireBlockPins.size(); i++) {
                    BlockPin wireSource = wireBlockPins[i];
                    funcCall += "&wire_";
                    funcCall += QString::number(wireSource.blockNum());
                    funcCall += "_";
                    funcCall += wireSource.pinName();
                    if (i < wireBlockPins.size() - 1) {
                        funcCall += ",";
                    }
                }
                funcCall += ");";
                mainFile += funcCall;
                mainFile += "\n";
                // write this node's struct instance
                QString structInstance = "struct ";
                structInstance += block.blockType().name();
                structInstance += "_options ";
                structInstance += "block_options_";
                structInstance += QString::number(blockIndex);
                structInstance += ";\n";
                for (QString optionName : block.blockType().options().keys()) {
                    QString optionValue = block.optionValues()[optionName];
                    structInstance += "block_options_";
                    structInstance += QString::number(blockIndex);
                    structInstance += ".";
                    structInstance += optionName;
                    structInstance += " = ";
                    structInstance += optionValue; // TODO: factor in data type
                    structInstance += ";\n";
                }
                structInstances.append(structInstance);
            } else {
               toBeExpanded.push_back(blockIndex);
            }
        }
    }
    mainFile += "\nreturn 0;\n\n}";

    QString includesFile = "#include <avr/io.h>\n";
    for (QString blockName : blockNames) {
        includesFile += "#include \"blocks/";
        includesFile += blockName;
        includesFile += ".h\"\n";
    }
    includesFile += "\n";

    QString structInstancesFile;
    for (QString structInstance : structInstances) {
        structInstancesFile += structInstance;
    }
    structInstancesFile += "\n";

    QString declarationsFile = "";
    for (QString wireName : wires) {
        declarationsFile += "int ";
        declarationsFile += wireName;
        declarationsFile += ";\n";
    }
    declarationsFile += "\n";

    return includesFile + structInstancesFile + declarationsFile + mainFile;
}

QSet<QString> extractUniqueBlockNames(FlowChart flow) {
    QSet<QString> blockNames;
    for(Block block : flow.blocks().values()) {
        // make sure this block's name is in the blockNames set
        blockNames.insert(block.blockType().name());
    }
    return blockNames;
}

QList<int> extractInputBlocks(FlowChart flow) {
    QList<int> inputBlocks;
    for(int blockIndex : flow.blocks().keys()) {
        Block block = flow.block(blockIndex);
        // If this is an input block, make sure it's expanded first
        if(block.inputConnections().empty()) {
            inputBlocks.push_back(blockIndex);
        }
    }
    return inputBlocks;
}

QSet<QString> extractWireNames(FlowChart flow) {
    QSet<QString> wireNames;
    for(int blockIndex : flow.blocks().keys()) {
        Block block = flow.block(blockIndex);
        // for each output connection
        for (QString pinName : block.outputConnections().keys()) {
            // construct wire name
            QString wireName = "wire_";
            wireName += QString::number(blockIndex);
            wireName += "_";
            wireName += pinName;
            wireNames.insert(wireName);
        }
    }
    return wireNames;
}

bool isExpandable(Block block, QSet<int> expanded) {
    bool found_all = true;
    for(BlockPin bp : block.inputConnections().values()) {
        int blockNum = bp.blockNum();
        if(expanded.find(blockNum) == expanded.end()) {
            found_all = false;
            break;
        }
    }
    return found_all;
}
<|endoftext|>


<commit_before>// Copyright (C) 2012 - 2013 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

#include <QtCore/QString>

#include "CQTabWidget.h"

#include "CQMessageBox.h"
#include "qtUtilities.h"
#include "CQNotes.h"

#include "MIRIAMUI/CQMiriamWidget.h"
#include "MIRIAMUI/CQRDFTreeView.h"

#include "CopasiDataModel/CCopasiDataModel.h"
#include "report/CCopasiRootContainer.h"
#include "function/CFunction.h"
#include "UI/CQCompartment.h"
#include "UI/CQSpeciesDetail.h"
#include "UI/ReactionsWidget1.h"

CQTabWidget::CQTabWidget(const ListViews::ObjectType & objectType, CopasiWidget * pCopasiWidget,
                         QWidget * parent, Qt::WindowFlags f) :
  CopasiWidget(parent, NULL, f),
  mPages(),
  mObjectType(objectType),
  mIgnoreLeave(false)
{
  setupUi(this);

  mpLblName->setText("
" + FROM_UTF8(ListViews::ObjectTypeName[mObjectType]) + "
");

  mpTabWidget->addTab(pCopasiWidget, "Details");
  mPages.push_back(pCopasiWidget);

  switch (mObjectType)
    {
      case  ListViews::MODEL:
        mpBtnNew->hide();
        mpBtnCopy->hide();
        mpBtnDelete->hide();
        break;

      case ListViews::MODELPARAMETERSET:
        mpBtnNew->setText("Apply");
        mpBtnNew->setToolTip("Apply the current parameters to the model.");

        // The break statement is intentionally missing

      default:
        CQNotes* pNotes = new CQNotes(mpTabWidget);
        mPages.push_back(pNotes);
        mpTabWidget->addTab(pNotes, "Notes");

        connect(this, SIGNAL(newClicked()), pCopasiWidget, SLOT(slotBtnNew()));
        connect(this, SIGNAL(copyClicked()), pCopasiWidget, SLOT(slotBtnCopy()));
        connect(this, SIGNAL(deleteClicked()), pCopasiWidget, SLOT(slotBtnDelete()));
        connect(this, SIGNAL(copyClicked()), pNotes, SLOT(slotBtnCopy()));
        break;
    }

  CQMiriamWidget* pMIRIAMWidget = new CQMiriamWidget(mpTabWidget);
  mPages.push_back(pMIRIAMWidget);
  mpTabWidget->addTab(pMIRIAMWidget, "Annotation");
  connect(this, SIGNAL(copyClicked()), pMIRIAMWidget, SLOT(slotBtnCopy()));

  CQRDFTreeView* pRDFTreeView = new CQRDFTreeView(mpTabWidget);
  mPages.push_back(pRDFTreeView);
  mpTabWidget->addTab(pRDFTreeView, "RDF Browser");
}

CQTabWidget::~CQTabWidget()
{
  // TODO Auto-generated destructor stub
}

bool CQTabWidget::leave()
{
  if (mIgnoreLeave) return true;

  bool success = save();

  std::vector< CopasiWidget * >::iterator it = mPages.begin();
  std::vector< CopasiWidget * >::iterator end = mPages.end();

  for (; it != end; ++it)
    success &= (*it)->leave();

  return true;
}

bool CQTabWidget::enterProtected()
{
  load();

  std::vector< CopasiWidget * >::iterator it = mPages.begin();
  std::vector< CopasiWidget * >::iterator end = mPages.end();

  for (; it != end; ++it)
    (*it)->enter(mKey);

  return true;
}

bool CQTabWidget::update(ListViews::ObjectType objectType, ListViews::Action action, const std::string & key)
{
  if (mIgnoreUpdates) return true;

  if (objectType == mObjectType &&
      key == mKey)
    {
      switch (action)
        {
          case ListViews::RENAME:
            load();
            break;

          case ListViews::DELETE:
            mpObject = NULL;
            break;

          default:
            break;
        }
    }

  // We do not need to update the child pages as they are directly called from listviews.
  return true;
}

void CQTabWidget::selectTab(int index) const
{
  mpTabWidget->setCurrentIndex(index);
}

void CQTabWidget::load()
{
  // mpObject can not be trusted
  mpObject = CCopasiRootContainer::getKeyFactory()->get(mKey);

  if (mpObject != NULL)
    {
      mpEditName->setText(FROM_UTF8(mpObject->getObjectName()));

      if (mObjectType == ListViews::FUNCTION)
        {
          const CFunction * pFunction = static_cast< const CFunction * >(mpObject);

          bool readOnly =
            (pFunction->getType() == CFunction::PreDefined ||
             pFunction->getType() == CFunction::MassAction);

          mpEditName->setReadOnly(readOnly);
          mpBtnCommit->setEnabled(!readOnly);
          mpBtnRevert->setEnabled(!readOnly);
          mpBtnDelete->setEnabled(!readOnly);
        }
    }
  else
    {
      mpEditName->setText("");
    }
}

bool CQTabWidget::save()
{
  // mpObject can not be trusted
  mpObject = CCopasiRootContainer::getKeyFactory()->get(mKey);

  if (mpObject == NULL) return false;

  if (mpObject->getObjectName() != TO_UTF8(mpEditName->text()))
    {
      if (!mpObject->setObjectName(TO_UTF8(mpEditName->text())))
        {
          QString msg;
          msg = "Unable to rename " + FROM_UTF8(ListViews::ObjectTypeName[mObjectType]).toLower() + " '" + FROM_UTF8(mpObject->getObjectName()) + "'\n"
                + "to '" + mpEditName->text() + "' since a " + FROM_UTF8(ListViews::ObjectTypeName[mObjectType]).toLower() + " with that name already exists.\n";

          CQMessageBox::information(this,
                                    "Unable to rename " + FROM_UTF8(ListViews::ObjectTypeName[mObjectType]),
                                    msg,
                                    QMessageBox::Ok, QMessageBox::Ok);

          mpEditName->setText(FROM_UTF8(mpObject->getObjectName()));
        }
      else
        {
          protectedNotify(mObjectType, ListViews::RENAME, mKey);

          if (mpDataModel != NULL)
            {
              mpDataModel->changed();
            }
        }
    }

  return true;
}

void CQTabWidget::slotBtnCommit()
{
  mpBtnCommit->setFocus();

  leave();
  enterProtected();
}

void CQTabWidget::slotBtnRevert()
{
  enterProtected();
}

void CQTabWidget::slotBtnDelete()
{
  mIgnoreLeave = true;
  emit deleteClicked();
  mIgnoreLeave = false;
}

void CQTabWidget::slotBtnNew()
{
  mpBtnNew->setFocus();

  leave();

  mIgnoreLeave = true;
  emit newClicked();
  mIgnoreLeave = false;
}

void CQTabWidget::slotBtnCopy()
{
  mpBtnCopy->setFocus();

  leave();

  mIgnoreLeave = true;

  // CQCompartments and CQSpecies have copy options, use CModelExpansion, and do their own switching.
  if (QString(mPages[0]->metaObject()->className()) == "CQCompartment")
    {
      CQCompartment * pQCompartment = dynamic_cast< CQCompartment * >(mPages[0]);
      pQCompartment->copy();
    }
  else if (QString(mPages[0]->metaObject()->className()) == "CQSpeciesDetail")
    {
      CQSpeciesDetail * pQSpeciesDetail = dynamic_cast< CQSpeciesDetail * >(mPages[0]);
      pQSpeciesDetail->copy();
    }
  else if (QString(mPages[0]->metaObject()->className()) == "ReactionsWidget1")
    {
      ReactionsWidget1 * pReactionsWidget1 = dynamic_cast< ReactionsWidget1 * >(mPages[0]);
      pReactionsWidget1->copy();
    }
  else
    {
      emit copyClicked();
      emit newClicked();
    }

  mIgnoreLeave = false;
}
<commit_msg>Changes in a page of the tab widgets no longer effect changes in other pages caused by change notifications.<commit_after>// Copyright (C) 2012 - 2014 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

#include <QtCore/QString>

#include "CQTabWidget.h"

#include "CQMessageBox.h"
#include "qtUtilities.h"
#include "CQNotes.h"

#include "MIRIAMUI/CQMiriamWidget.h"
#include "MIRIAMUI/CQRDFTreeView.h"

#include "CopasiDataModel/CCopasiDataModel.h"
#include "report/CCopasiRootContainer.h"
#include "function/CFunction.h"
#include "UI/CQCompartment.h"
#include "UI/CQSpeciesDetail.h"
#include "UI/ReactionsWidget1.h"

CQTabWidget::CQTabWidget(const ListViews::ObjectType & objectType, CopasiWidget * pCopasiWidget,
                         QWidget * parent, Qt::WindowFlags f) :
  CopasiWidget(parent, NULL, f),
  mPages(),
  mObjectType(objectType),
  mIgnoreLeave(false)
{
  setupUi(this);

  mpLblName->setText("
" + FROM_UTF8(ListViews::ObjectTypeName[mObjectType]) + "
");

  mpTabWidget->addTab(pCopasiWidget, "Details");
  mPages.push_back(pCopasiWidget);

  switch (mObjectType)
    {
      case  ListViews::MODEL:
        mpBtnNew->hide();
        mpBtnCopy->hide();
        mpBtnDelete->hide();
        break;

      case ListViews::MODELPARAMETERSET:
        mpBtnNew->setText("Apply");
        mpBtnNew->setToolTip("Apply the current parameters to the model.");

        // The break statement is intentionally missing

      default:
        CQNotes* pNotes = new CQNotes(mpTabWidget);
        mPages.push_back(pNotes);
        mpTabWidget->addTab(pNotes, "Notes");

        connect(this, SIGNAL(newClicked()), pCopasiWidget, SLOT(slotBtnNew()));
        connect(this, SIGNAL(copyClicked()), pCopasiWidget, SLOT(slotBtnCopy()));
        connect(this, SIGNAL(deleteClicked()), pCopasiWidget, SLOT(slotBtnDelete()));
        connect(this, SIGNAL(copyClicked()), pNotes, SLOT(slotBtnCopy()));
        break;
    }

  CQMiriamWidget* pMIRIAMWidget = new CQMiriamWidget(mpTabWidget);
  mPages.push_back(pMIRIAMWidget);
  mpTabWidget->addTab(pMIRIAMWidget, "Annotation");
  connect(this, SIGNAL(copyClicked()), pMIRIAMWidget, SLOT(slotBtnCopy()));

  CQRDFTreeView* pRDFTreeView = new CQRDFTreeView(mpTabWidget);
  mPages.push_back(pRDFTreeView);
  mpTabWidget->addTab(pRDFTreeView, "RDF Browser");
}

CQTabWidget::~CQTabWidget()
{
  // TODO Auto-generated destructor stub
}

bool CQTabWidget::leave()
{
  if (mIgnoreLeave) return true;

  bool success = save();

  std::vector< CopasiWidget * >::iterator it = mPages.begin();
  std::vector< CopasiWidget * >::iterator end = mPages.end();

  for (; it != end; ++it)
    success &= (*it)->leave();

  return true;
}

bool CQTabWidget::enterProtected()
{
  load();

  std::vector< CopasiWidget * >::iterator it = mPages.begin();
  std::vector< CopasiWidget * >::iterator end = mPages.end();

  for (; it != end; ++it)
    (*it)->enter(mKey);

  return true;
}

bool CQTabWidget::update(ListViews::ObjectType objectType, ListViews::Action action, const std::string & key)
{
  if (mIgnoreUpdates) return true;

  if (objectType == mObjectType &&
      key == mKey)
    {
      switch (action)
        {
          case ListViews::RENAME:
            load();
            break;

          case ListViews::DELETE:
            mpObject = NULL;
            break;

          default:
            break;
        }
    }

  // We do not need to update the child pages as they are directly called from listviews.
  return true;
}

void CQTabWidget::selectTab(int index) const
{
  mpTabWidget->setCurrentIndex(index);
}

void CQTabWidget::load()
{
  // mpObject can not be trusted
  mpObject = CCopasiRootContainer::getKeyFactory()->get(mKey);

  if (mpObject != NULL)
    {
      mpEditName->setText(FROM_UTF8(mpObject->getObjectName()));

      if (mObjectType == ListViews::FUNCTION)
        {
          const CFunction * pFunction = static_cast< const CFunction * >(mpObject);

          bool readOnly =
            (pFunction->getType() == CFunction::PreDefined ||
             pFunction->getType() == CFunction::MassAction);

          mpEditName->setReadOnly(readOnly);
          mpBtnCommit->setEnabled(!readOnly);
          mpBtnRevert->setEnabled(!readOnly);
          mpBtnDelete->setEnabled(!readOnly);
        }
    }
  else
    {
      mpEditName->setText("");
    }
}

bool CQTabWidget::save()
{
  // mpObject can not be trusted
  mpObject = CCopasiRootContainer::getKeyFactory()->get(mKey);

  if (mpObject == NULL) return false;

  // We need to tell the sub-widgets to ignore all notifications
  std::vector< CopasiWidget * >::iterator it = mPages.begin();
  std::vector< CopasiWidget * >::iterator end = mPages.end();

  for (; it != end; ++it)
    (*it)->setIgnoreUpdates(true);

  if (mpObject->getObjectName() != TO_UTF8(mpEditName->text()))
    {
      if (!mpObject->setObjectName(TO_UTF8(mpEditName->text())))
        {
          QString msg;
          msg = "Unable to rename " + FROM_UTF8(ListViews::ObjectTypeName[mObjectType]).toLower() + " '" + FROM_UTF8(mpObject->getObjectName()) + "'\n"
                + "to '" + mpEditName->text() + "' since a " + FROM_UTF8(ListViews::ObjectTypeName[mObjectType]).toLower() + " with that name already exists.\n";

          CQMessageBox::information(this,
                                    "Unable to rename " + FROM_UTF8(ListViews::ObjectTypeName[mObjectType]),
                                    msg,
                                    QMessageBox::Ok, QMessageBox::Ok);

          mpEditName->setText(FROM_UTF8(mpObject->getObjectName()));
        }
      else
        {
          protectedNotify(mObjectType, ListViews::RENAME, mKey);

          if (mpDataModel != NULL)
            {
              mpDataModel->changed();
            }
        }
    }

  // We need to tell the sub-widgets to accept notifications again
  it = mPages.begin();
  end = mPages.end();

  for (; it != end; ++it)
    (*it)->setIgnoreUpdates(false);

  return true;
}

void CQTabWidget::slotBtnCommit()
{
  mpBtnCommit->setFocus();

  leave();
  enterProtected();
}

void CQTabWidget::slotBtnRevert()
{
  enterProtected();
}

void CQTabWidget::slotBtnDelete()
{
  mIgnoreLeave = true;
  emit deleteClicked();
  mIgnoreLeave = false;
}

void CQTabWidget::slotBtnNew()
{
  mpBtnNew->setFocus();

  leave();

  mIgnoreLeave = true;
  emit newClicked();
  mIgnoreLeave = false;
}

void CQTabWidget::slotBtnCopy()
{
  mpBtnCopy->setFocus();

  leave();

  mIgnoreLeave = true;

  // CQCompartments and CQSpecies have copy options, use CModelExpansion, and do their own switching.
  if (QString(mPages[0]->metaObject()->className()) == "CQCompartment")
    {
      CQCompartment * pQCompartment = dynamic_cast< CQCompartment * >(mPages[0]);
      pQCompartment->copy();
    }
  else if (QString(mPages[0]->metaObject()->className()) == "CQSpeciesDetail")
    {
      CQSpeciesDetail * pQSpeciesDetail = dynamic_cast< CQSpeciesDetail * >(mPages[0]);
      pQSpeciesDetail->copy();
    }
  else if (QString(mPages[0]->metaObject()->className()) == "ReactionsWidget1")
    {
      ReactionsWidget1 * pReactionsWidget1 = dynamic_cast< ReactionsWidget1 * >(mPages[0]);
      pReactionsWidget1->copy();
    }
  else
    {
      emit copyClicked();
      emit newClicked();
    }

  mIgnoreLeave = false;
}
<|endoftext|>