<commit_before>// Ylikuutio - A 3D game and simulation engine.
//
// Copyright (C) 2015-2020 Antti Nuortimo.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

#ifndef PI
#define PI 3.14159265359f
#endif

#include "brain_snippets.hpp"
#include "code/ylikuutio/common/datatype.hpp"
#include "code/ylikuutio/common/any_value.hpp"
#include "code/ylikuutio/config/setting_master.hpp"
#include "code/ylikuutio/ontology/movable.hpp"

// Include standard headers
#include <iostream> // std::cout, std::cin, std::cerr
#include <memory>   // std::make_shared, std::shared_ptr
#include <variant>  // std::variant
#include <vector>   // std::vector

namespace yli::callback
{
    class CallbackEngine;
    class CallbackObject;
    class CallbackParameter;
}

namespace yli::common
{
    class AnyValue;
}

namespace yli::ontology
{
    class Universe;
}

namespace yli::snippets
{
    std::shared_ptr<yli::common::AnyValue> rest(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        // Do nothing.
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> go_east(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value->type != yli::common::Datatype::MOVABLE_POINTER)
        {
            std::cerr << "ERROR: `yli::snippets::go_east`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->cartesian_coordinates.x += 1.0f;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> go_west(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value->type != yli::common::Datatype::MOVABLE_POINTER)
        {
            std::cerr << "ERROR: `yli::snippets::go_west`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->cartesian_coordinates.x -= 1.0f;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> go_north(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value->type != yli::common::Datatype::MOVABLE_POINTER)
        {
            std::cerr << "ERROR: `yli::snippets::go_north`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->cartesian_coordinates.z -= 1.0f;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> go_south(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value->type != yli::common::Datatype::MOVABLE_POINTER)
        {
            std::cerr << "ERROR: `yli::snippets::go_south`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->cartesian_coordinates.z += 1.0f;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> orient_to_east(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value->type != yli::common::Datatype::MOVABLE_POINTER)
        {
            std::cerr << "ERROR: `yli::snippets::orient_to_east`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->horizontal_angle = 1.5f * PI;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> orient_to_west(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value->type != yli::common::Datatype::MOVABLE_POINTER)
        {
            std::cerr << "ERROR: `yli::snippets::orient_to_west`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->horizontal_angle = 0.5f * PI;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> orient_to_north(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value->type != yli::common::Datatype::MOVABLE_POINTER)
        {
            std::cerr << "ERROR: `yli::snippets::orient_to_north`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->horizontal_angle = 0.0f;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> orient_to_south(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value->type != yli::common::Datatype::MOVABLE_POINTER)
        {
            std::cerr << "ERROR: `yli::snippets::orient_to_south`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->horizontal_angle = 1.0f * PI;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> orient_and_go_east(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value->type != yli::common::Datatype::MOVABLE_POINTER)
        {
            std::cerr << "ERROR: `yli::snippets::orient_and_go_east`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->horizontal_angle = 1.5f * PI;
        movable->cartesian_coordinates.x += 1.0f;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> orient_and_go_west(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value->type != yli::common::Datatype::MOVABLE_POINTER)
        {
            std::cerr << "ERROR: `yli::snippets::orient_and_go_west`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->horizontal_angle = 0.5f * PI;
        movable->cartesian_coordinates.x -= 1.0f;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> orient_and_go_north(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value->type != yli::common::Datatype::MOVABLE_POINTER)
        {
            std::cerr << "ERROR: `yli::snippets::orient_and_go_north`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->horizontal_angle = 0.0f;
        movable->cartesian_coordinates.z -= 1.0f;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> orient_and_go_south(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value->type != yli::common::Datatype::MOVABLE_POINTER)
        {
            std::cerr << "ERROR: `yli::snippets::orient_and_go_south`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->horizontal_angle = 1.0f * PI;
        movable->cartesian_coordinates.z += 1.0f;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> rotate_clockwise(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value->type != yli::common::Datatype::MOVABLE_POINTER)
        {
            std::cerr << "ERROR: `yli::snippets::rotate_clockwise`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->horizontal_angle -= 0.1f * PI;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> rotate_counterclockwise(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value->type != yli::common::Datatype::MOVABLE_POINTER)
        {
            std::cerr << "ERROR: `yli::snippets::rotate_counterclockwise`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->horizontal_angle += 0.1f * PI;
        return nullptr;
    }
}
<commit_msg>`Brain` snippets: use `std::holds_alternative`.<commit_after>// Ylikuutio - A 3D game and simulation engine.
//
// Copyright (C) 2015-2020 Antti Nuortimo.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

#ifndef PI
#define PI 3.14159265359f
#endif

#include "brain_snippets.hpp"
#include "code/ylikuutio/common/any_value.hpp"
#include "code/ylikuutio/config/setting_master.hpp"
#include "code/ylikuutio/ontology/movable.hpp"

// Include standard headers
#include <iostream> // std::cout, std::cin, std::cerr
#include <memory>   // std::make_shared, std::shared_ptr
#include <variant>  // std::variant
#include <vector>   // std::vector

namespace yli::callback
{
    class CallbackEngine;
    class CallbackObject;
    class CallbackParameter;
}

namespace yli::common
{
    class AnyValue;
}

namespace yli::ontology
{
    class Universe;
}

namespace yli::snippets
{
    std::shared_ptr<yli::common::AnyValue> rest(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        // Do nothing.
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> go_east(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value == nullptr || !std::holds_alternative<yli::ontology::Movable*>(any_value->data))
        {
            std::cerr << "ERROR: `yli::snippets::go_east`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->cartesian_coordinates.x += 1.0f;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> go_west(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value == nullptr || !std::holds_alternative<yli::ontology::Movable*>(any_value->data))
        {
            std::cerr << "ERROR: `yli::snippets::go_west`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->cartesian_coordinates.x -= 1.0f;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> go_north(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value == nullptr || !std::holds_alternative<yli::ontology::Movable*>(any_value->data))
        {
            std::cerr << "ERROR: `yli::snippets::go_north`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->cartesian_coordinates.z -= 1.0f;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> go_south(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value == nullptr || !std::holds_alternative<yli::ontology::Movable*>(any_value->data))
        {
            std::cerr << "ERROR: `yli::snippets::go_south`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->cartesian_coordinates.z += 1.0f;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> orient_to_east(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value == nullptr || !std::holds_alternative<yli::ontology::Movable*>(any_value->data))
        {
            std::cerr << "ERROR: `yli::snippets::orient_to_east`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->horizontal_angle = 1.5f * PI;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> orient_to_west(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value == nullptr || !std::holds_alternative<yli::ontology::Movable*>(any_value->data))
        {
            std::cerr << "ERROR: `yli::snippets::orient_to_west`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->horizontal_angle = 0.5f * PI;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> orient_to_north(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value == nullptr || !std::holds_alternative<yli::ontology::Movable*>(any_value->data))
        {
            std::cerr << "ERROR: `yli::snippets::orient_to_north`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->horizontal_angle = 0.0f;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> orient_to_south(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value == nullptr || !std::holds_alternative<yli::ontology::Movable*>(any_value->data))
        {
            std::cerr << "ERROR: `yli::snippets::orient_to_south`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->horizontal_angle = 1.0f * PI;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> orient_and_go_east(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value == nullptr || !std::holds_alternative<yli::ontology::Movable*>(any_value->data))
        {
            std::cerr << "ERROR: `yli::snippets::orient_and_go_east`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->horizontal_angle = 1.5f * PI;
        movable->cartesian_coordinates.x += 1.0f;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> orient_and_go_west(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value == nullptr || !std::holds_alternative<yli::ontology::Movable*>(any_value->data))
        {
            std::cerr << "ERROR: `yli::snippets::orient_and_go_west`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->horizontal_angle = 0.5f * PI;
        movable->cartesian_coordinates.x -= 1.0f;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> orient_and_go_north(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value == nullptr || !std::holds_alternative<yli::ontology::Movable*>(any_value->data))
        {
            std::cerr << "ERROR: `yli::snippets::orient_and_go_north`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->horizontal_angle = 0.0f;
        movable->cartesian_coordinates.z -= 1.0f;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> orient_and_go_south(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value == nullptr || !std::holds_alternative<yli::ontology::Movable*>(any_value->data))
        {
            std::cerr << "ERROR: `yli::snippets::orient_and_go_south`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->horizontal_angle = 1.0f * PI;
        movable->cartesian_coordinates.z += 1.0f;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> rotate_clockwise(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value == nullptr || !std::holds_alternative<yli::ontology::Movable*>(any_value->data))
        {
            std::cerr << "ERROR: `yli::snippets::rotate_clockwise`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->horizontal_angle -= 0.1f * PI;
        return nullptr;
    }

    std::shared_ptr<yli::common::AnyValue> rotate_counterclockwise(
            yli::ontology::Universe*,
            yli::callback::CallbackEngine*,
            yli::callback::CallbackObject*,
            std::vector<yli::callback::CallbackParameter*>& input_parameters,
            std::shared_ptr<yli::common::AnyValue> any_value)
    {
        if (any_value == nullptr || !std::holds_alternative<yli::ontology::Movable*>(any_value->data))
        {
            std::cerr << "ERROR: `yli::snippets::rotate_counterclockwise`: `any_value->type` is not `yli::common::Datatype::MOVABLE_POINTER`.\n";
            return nullptr;
        }

        yli::ontology::Movable* const movable = std::get<yli::ontology::Movable*>(any_value->data);

        if (movable == nullptr)
        {
            return nullptr;
        }

        movable->horizontal_angle += 0.1f * PI;
        return nullptr;
    }
}
<|endoftext|>


<commit_before><commit_msg>fdo#52540 refix graphite layout generally<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: cppuoptions.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: vg $ $Date: 2006-03-15 09:13:20 $
 *
 *  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
 *
 ************************************************************************/

#ifndef INCLUDED_CODEMAKER_SOURCE_CPPUMAKER_CPPUOPTIONS_HXX
#define INCLUDED_CODEMAKER_SOURCE_CPPUMAKER_CPPUOPTIONS_HXX

#ifndef INCLUDED_CODEMAKER_OPTIONS_HXX
#include "codemaker/options.hxx"
#endif

class CppuOptions : public Options
{
public:
    CppuOptions()
        : Options() {}

    ~CppuOptions() {}

    sal_Bool initOptions(int ac, char* av[], sal_Bool bCmdFile=sal_False)
            throw( IllegalArgument );

    ::rtl::OString  prepareHelp();

    ::rtl::OString  prepareVersion();

protected:
};

#endif // INCLUDED_CODEMAKER_SOURCE_CPPUMAKER_CPPUOPTIONS_HXX
<commit_msg>INTEGRATION: CWS changefileheader (1.3.56); FILE MERGED 2008/04/01 12:26:07 thb 1.3.56.2: #i85898# Stripping all external header guards 2008/03/31 07:22:53 rt 1.3.56.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: cppuoptions.hxx,v $
 * $Revision: 1.4 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef INCLUDED_CODEMAKER_SOURCE_CPPUMAKER_CPPUOPTIONS_HXX
#define INCLUDED_CODEMAKER_SOURCE_CPPUMAKER_CPPUOPTIONS_HXX

#include "codemaker/options.hxx"

class CppuOptions : public Options
{
public:
    CppuOptions()
        : Options() {}

    ~CppuOptions() {}

    sal_Bool initOptions(int ac, char* av[], sal_Bool bCmdFile=sal_False)
            throw( IllegalArgument );

    ::rtl::OString  prepareHelp();

    ::rtl::OString  prepareVersion();

protected:
};

#endif // INCLUDED_CODEMAKER_SOURCE_CPPUMAKER_CPPUOPTIONS_HXX
<|endoftext|>


<commit_before>/**************************************************************************
 * The MIT License                                                        *
 * Copyright (c) 2013 Antony Arciuolo.                                    *
 * arciuolo@gmail.com                                                     *
 *                                                                        *
 * Permission is hereby granted, free of charge, to any person obtaining  *
 * a copy of this software and associated documentation files (the        *
 * "Software"), to deal in the Software without restriction, including    *
 * without limitation the rights to use, copy, modify, merge, publish,    *
 * distribute, sublicense, and/or sell copies of the Software, and to     *
 * permit persons to whom the Software is furnished to do so, subject to  *
 * the following conditions:                                              *
 *                                                                        *
 * The above copyright notice and this permission notice shall be         *
 * included in all copies or substantial portions of the Software.        *
 *                                                                        *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        *
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     *
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND                  *
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE *
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION *
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION  *
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        *
 **************************************************************************/
#include <oGUI/oGUIMenu.h>
#include <oBase/assert.h>
#include <oCore/windows/win_error.h>
#include <oBasis/oError.h> // @tony fixme

using namespace ouro;

#if 0
// not in use (yet?)
static int oGUIMenuFindPosition(ouro::menu_handle _hParentMenu, int _ItemID)
{
	const int n = oGUIMenuGetNumItems(_hParentMenu);
	for (int i = 0; i < n; i++)
	{
		int ID = GetMenuItemID(_hParentMenu, i);
		if (ID == _ItemID)
			return i;
	}
	return oInvalid;
}
#endif

static int oGUIMenuFindPosition(ouro::menu_handle _hParentMenu, ouro::menu_handle _hSubmenu)
{
	const int n = GetMenuItemCount((HMENU)_hParentMenu);
	for (int i = 0; i < n; i++)
	{
		ouro::menu_handle hSubmenu = (ouro::menu_handle)GetSubMenu((HMENU)_hParentMenu, i);
		if (hSubmenu == _hSubmenu)
			return i;
	}
	return oInvalid;
}

#ifdef oENABLE_ASSERTS
// Returns true if the specified menu contains all IDs [first,last]
static bool oGUIMenuContainsRange(ouro::menu_handle _hMenu, int _ItemIDRangeFirst, int _ItemIDRangeLast)
{
	MENUITEMINFO mii;
	mii.cbSize = sizeof(MENUITEMINFO);
	mii.fMask = MIIM_ID;

	int nFound = 0;
	const int n = oGUIMenuGetNumItems(_hMenu);
	for (int i = 0; i < n; i++)
	{
		UINT uID = GetMenuItemID((HMENU)_hMenu, i);
		if (uID == oInvalid)
			return false;
		int ID = oInt(uID);
		if (ID >= _ItemIDRangeFirst && ID <= _ItemIDRangeLast)
			nFound++;
	}

	return nFound == (_ItemIDRangeLast - _ItemIDRangeFirst + 1);
}
#endif

char* oGUIMenuGetTextByPosition(char* _StrDestination, size_t _SizeofStrDestination, ouro::menu_handle _hMenu, int _MenuItemPosition)
{
	if (!GetMenuStringA((HMENU)_hMenu, _MenuItemPosition, _StrDestination, oInt(_SizeofStrDestination), MF_BYPOSITION))
		return nullptr;
	return _StrDestination;
}

ouro::menu_handle oGUIMenuCreate(bool _IsTopLevelMenu)
{
	return (ouro::menu_handle)(_IsTopLevelMenu ? CreateMenu() : CreatePopupMenu());
}

void oGUIMenuDestroy(ouro::menu_handle _hMenu)
{
	if (IsMenu((HMENU)_hMenu))
		oVB(DestroyMenu((HMENU)_hMenu));
}

void oGUIMenuAttach(ouro::window_handle _hWindow, ouro::menu_handle _hMenu)
{
	oVB(SetMenu((HWND)_hWindow, (HMENU)_hMenu));
}

int oGUIMenuGetNumItems(ouro::menu_handle _hMenu)
{
	return oInt(GetMenuItemCount((HMENU)_hMenu));
}

void oGUIMenuAppendSubmenu(ouro::menu_handle _hParentMenu, ouro::menu_handle _hSubmenu, const char* _Text)
{
	oVB(AppendMenu((HMENU)_hParentMenu, MF_STRING|MF_POPUP, (UINT_PTR)_hSubmenu, _Text));
}

void oGUIMenuRemoveSubmenu(ouro::menu_handle _hParentMenu, ouro::menu_handle _hSubmenu)
{
	int p = oGUIMenuFindPosition(_hParentMenu, _hSubmenu);
	if (p != oInvalid && !RemoveMenu((HMENU)_hParentMenu, p, MF_BYPOSITION))
	{
		DWORD hr = GetLastError();
		if (GetLastError() != ERROR_RESOURCE_TYPE_NOT_FOUND)
			oV(hr);
	}
}

void oGUIMenuAppendItem(ouro::menu_handle _hParentMenu, int _ItemID, const char* _Text)
{
	oVB(AppendMenu((HMENU)_hParentMenu, MF_STRING, (UINT_PTR)_ItemID, _Text));
}

void oGUIMenuRemoveItem(ouro::menu_handle _hParentMenu, int _ItemID)
{
	if (!RemoveMenu((HMENU)_hParentMenu, _ItemID, MF_BYCOMMAND))
	{
		DWORD hr = GetLastError();
		if (GetLastError() != ERROR_RESOURCE_TYPE_NOT_FOUND)
			oV(hr);
	}
}

void oGUIMenuRemoveAllItems(ouro::menu_handle _hMenu)
{
	int n = GetMenuItemCount((HMENU)_hMenu);
	while (n)
	{
		DeleteMenu((HMENU)_hMenu, n-1, MF_BYPOSITION);
		n = GetMenuItemCount((HMENU)_hMenu);
	}
}

void oGUIMenuItemToSubmenu(ouro::menu_handle _hParentMenu, int _ItemID, ouro::menu_handle _hSubmenu)
{
	mstring text;
	oVERIFY(oGUIMenuGetText(text, _hParentMenu, _ItemID));
	oVB(RemoveMenu((HMENU)_hParentMenu, _ItemID, MF_BYCOMMAND));
	oVB(InsertMenu((HMENU)_hParentMenu, _ItemID, MF_STRING|MF_POPUP, (UINT_PTR)_hSubmenu, text));
}

void oGUIMenuSubmenuToItem(ouro::menu_handle _hParentMenu, ouro::menu_handle _hSubmenu, int _ItemID, bool _Enabled)
{
	int p = oGUIMenuFindPosition(_hParentMenu, _hSubmenu);
	oASSERT(p != oInvalid, "the specified submenu is not under the specified parent menu");

	mstring text;
	oVERIFY(oGUIMenuGetTextByPosition(text, text.capacity(), _hParentMenu, p));
	oVB(DeleteMenu((HMENU)_hParentMenu, p, MF_BYPOSITION));

	UINT uFlags = MF_BYPOSITION|MF_STRING;
	if (!_Enabled)
		uFlags |= MF_GRAYED;

	oVB(InsertMenu((HMENU)_hParentMenu, p, uFlags, (UINT_PTR)_ItemID, text.c_str()));
}

void oGUIMenuAppendSeparator(ouro::menu_handle _hParentMenu)
{
	oVB(AppendMenu((HMENU)_hParentMenu, MF_SEPARATOR, 0, nullptr));
}

void oGUIMenuCheck(ouro::menu_handle _hMenu, int _ItemID, bool _Checked)
{
	if (-1 == CheckMenuItem((HMENU)_hMenu, oUInt(_ItemID), MF_BYCOMMAND | (_Checked ? MF_CHECKED : MF_UNCHECKED)))
		oASSERT(false, "MenuItemID not found in the specified menu");
}

bool oGUIMenuIsChecked(ouro::menu_handle _hMenu, int _ItemID)
{
	MENUITEMINFO mii;
	ZeroMemory(&mii, sizeof(mii));
	mii.cbSize = sizeof(mii);
	mii.fMask = MIIM_STATE;
	if (!GetMenuItemInfo((HMENU)_hMenu, oUInt(_ItemID), FALSE, &mii))
		return false;

	if (mii.fState & MFS_CHECKED)
		return true;

	oErrorSetLast(0);
	return false;
}

void oGUIMenuCheckRadio(ouro::menu_handle _hMenu, int _ItemIDRadioRangeFirst, int _ItemIDRadioRangeLast, int _ItemIDToCheck)
{
	// CheckMenuRadioItem returns false if the menu is wrong, but doesn't set a
	// useful last error (S_OK is returned when I ran into this) so add our own
	// check here.
	oASSERT(oGUIMenuGetNumItems(_hMenu) >= (_ItemIDRadioRangeLast-_ItemIDRadioRangeFirst+1), "A radio range was specified that is larger than the number of elements in the list (menu count=%d, range implies %d items)", oGUIMenuGetNumItems(_hMenu), (_ItemIDRadioRangeLast-_ItemIDRadioRangeFirst+1));
	oASSERT(oGUIMenuContainsRange(_hMenu, _ItemIDRadioRangeFirst, _ItemIDRadioRangeLast), "The specified menu 0x%p does not include the specified range [%d,%d] with selected %d. Most API works with an ancestor menu but this requires the immediate parent, so if the ranges look correct check the specified _hMenu.", _hMenu, _ItemIDRadioRangeFirst, _ItemIDRadioRangeLast, _ItemIDToCheck);
	oVB(CheckMenuRadioItem((HMENU)_hMenu, _ItemIDRadioRangeFirst, _ItemIDRadioRangeLast, _ItemIDToCheck, MF_BYCOMMAND));
}

int oGUIMenuGetCheckedRadio(ouro::menu_handle _hMenu, int _ItemIDRadioRangeFirst, int _ItemIDRadioRangeLast)
{
	for (int i = _ItemIDRadioRangeFirst; i <= _ItemIDRadioRangeLast; i++)
		if (oGUIMenuIsChecked(_hMenu, i))
			return i;
	return oInvalid;
}

void oGUIMenuEnable(ouro::menu_handle _hMenu, int _ItemID, bool _Enabled)
{
	if (-1 == EnableMenuItem((HMENU)_hMenu, oUInt(_ItemID), MF_BYCOMMAND | (_Enabled ? MF_ENABLED : MF_GRAYED)))
		oASSERT(false, "MenuItemID not found in the specified menu");
}

bool oGUIMenuIsEnabled(ouro::menu_handle _hMenu, int _ItemID)
{
	MENUITEMINFO mii;
	ZeroMemory(&mii, sizeof(mii));
	mii.cbSize = sizeof(mii);
	mii.fMask = MIIM_STATE;
	oVB(GetMenuItemInfo((HMENU)_hMenu, oUInt(_ItemID), FALSE, &mii));
	if (mii.fState & (MF_GRAYED|MF_DISABLED))
		return false;
	return true;
}

char* oGUIMenuGetText(char* _StrDestination, size_t _SizeofStrDestination, ouro::menu_handle _hMenu, int _ItemID)
{
	if (!GetMenuStringA((HMENU)_hMenu, _ItemID, _StrDestination, oInt(_SizeofStrDestination), MF_BYCOMMAND))
		return nullptr;
	return _StrDestination;
}

char* oGUIMenuGetText(char* _StrDestination, size_t _SizeofStrDestination, ouro::menu_handle _hParentMenu, ouro::menu_handle _hSubmenu)
{
	int pos = oGUIMenuFindPosition(_hParentMenu, _hSubmenu);
	if (pos == oInvalid)
		return nullptr;
	return oGUIMenuGetTextByPosition(_StrDestination, _SizeofStrDestination, _hParentMenu, pos);
}
<commit_msg>Forgot this file.. Prep for VS2012 upgrade: better std::error_category compat, don't use SafeInt3 - favor a simpler assert in the few places it matters. Thus also get rid of oInt and reduce the usage of oInvalid.<commit_after>/**************************************************************************
 * The MIT License                                                        *
 * Copyright (c) 2013 Antony Arciuolo.                                    *
 * arciuolo@gmail.com                                                     *
 *                                                                        *
 * Permission is hereby granted, free of charge, to any person obtaining  *
 * a copy of this software and associated documentation files (the        *
 * "Software"), to deal in the Software without restriction, including    *
 * without limitation the rights to use, copy, modify, merge, publish,    *
 * distribute, sublicense, and/or sell copies of the Software, and to     *
 * permit persons to whom the Software is furnished to do so, subject to  *
 * the following conditions:                                              *
 *                                                                        *
 * The above copyright notice and this permission notice shall be         *
 * included in all copies or substantial portions of the Software.        *
 *                                                                        *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        *
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     *
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND                  *
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE *
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION *
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION  *
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        *
 **************************************************************************/
#include <oGUI/oGUIMenu.h>
#include <oBase/assert.h>
#include <oCore/windows/win_error.h>
#include <oBasis/oError.h> // @tony fixme

using namespace ouro;

#if 0
// not in use (yet?)
static int oGUIMenuFindPosition(ouro::menu_handle _hParentMenu, int _ItemID)
{
	const int n = oGUIMenuGetNumItems(_hParentMenu);
	for (int i = 0; i < n; i++)
	{
		int ID = GetMenuItemID(_hParentMenu, i);
		if (ID == _ItemID)
			return i;
	}
	return oInvalid;
}
#endif

static int oGUIMenuFindPosition(ouro::menu_handle _hParentMenu, ouro::menu_handle _hSubmenu)
{
	const int n = GetMenuItemCount((HMENU)_hParentMenu);
	for (int i = 0; i < n; i++)
	{
		ouro::menu_handle hSubmenu = (ouro::menu_handle)GetSubMenu((HMENU)_hParentMenu, i);
		if (hSubmenu == _hSubmenu)
			return i;
	}
	return -1;
}

#ifdef oENABLE_ASSERTS
// Returns true if the specified menu contains all IDs [first,last]
static bool oGUIMenuContainsRange(ouro::menu_handle _hMenu, int _ItemIDRangeFirst, int _ItemIDRangeLast)
{
	MENUITEMINFO mii;
	mii.cbSize = sizeof(MENUITEMINFO);
	mii.fMask = MIIM_ID;

	int nFound = 0;
	const int n = oGUIMenuGetNumItems(_hMenu);
	for (int i = 0; i < n; i++)
	{
		UINT uID = GetMenuItemID((HMENU)_hMenu, i);
		oCHECK_SIZE(int, uID);
		if (uID == ~0u)
			return false;
		int ID = static_cast<int>(uID);
		if (ID >= _ItemIDRangeFirst && ID <= _ItemIDRangeLast)
			nFound++;
	}

	return nFound == (_ItemIDRangeLast - _ItemIDRangeFirst + 1);
}
#endif

char* oGUIMenuGetTextByPosition(char* _StrDestination, size_t _SizeofStrDestination, ouro::menu_handle _hMenu, int _MenuItemPosition)
{
	oCHECK_SIZE(int, _SizeofStrDestination);
	if (!GetMenuStringA((HMENU)_hMenu, _MenuItemPosition, _StrDestination, static_cast<int>(_SizeofStrDestination), MF_BYPOSITION))
		return nullptr;
	return _StrDestination;
}

ouro::menu_handle oGUIMenuCreate(bool _IsTopLevelMenu)
{
	return (ouro::menu_handle)(_IsTopLevelMenu ? CreateMenu() : CreatePopupMenu());
}

void oGUIMenuDestroy(ouro::menu_handle _hMenu)
{
	if (IsMenu((HMENU)_hMenu))
		oVB(DestroyMenu((HMENU)_hMenu));
}

void oGUIMenuAttach(ouro::window_handle _hWindow, ouro::menu_handle _hMenu)
{
	oVB(SetMenu((HWND)_hWindow, (HMENU)_hMenu));
}

int oGUIMenuGetNumItems(ouro::menu_handle _hMenu)
{

	return GetMenuItemCount((HMENU)_hMenu);
}

void oGUIMenuAppendSubmenu(ouro::menu_handle _hParentMenu, ouro::menu_handle _hSubmenu, const char* _Text)
{
	oVB(AppendMenu((HMENU)_hParentMenu, MF_STRING|MF_POPUP, (UINT_PTR)_hSubmenu, _Text));
}

void oGUIMenuRemoveSubmenu(ouro::menu_handle _hParentMenu, ouro::menu_handle _hSubmenu)
{
	int p = oGUIMenuFindPosition(_hParentMenu, _hSubmenu);
	if (p != -1 && !RemoveMenu((HMENU)_hParentMenu, p, MF_BYPOSITION))
	{
		DWORD hr = GetLastError();
		if (GetLastError() != ERROR_RESOURCE_TYPE_NOT_FOUND)
			oV(hr);
	}
}

void oGUIMenuAppendItem(ouro::menu_handle _hParentMenu, int _ItemID, const char* _Text)
{
	oVB(AppendMenu((HMENU)_hParentMenu, MF_STRING, (UINT_PTR)_ItemID, _Text));
}

void oGUIMenuRemoveItem(ouro::menu_handle _hParentMenu, int _ItemID)
{
	if (!RemoveMenu((HMENU)_hParentMenu, _ItemID, MF_BYCOMMAND))
	{
		DWORD hr = GetLastError();
		if (GetLastError() != ERROR_RESOURCE_TYPE_NOT_FOUND)
			oV(hr);
	}
}

void oGUIMenuRemoveAllItems(ouro::menu_handle _hMenu)
{
	int n = GetMenuItemCount((HMENU)_hMenu);
	while (n)
	{
		DeleteMenu((HMENU)_hMenu, n-1, MF_BYPOSITION);
		n = GetMenuItemCount((HMENU)_hMenu);
	}
}

void oGUIMenuItemToSubmenu(ouro::menu_handle _hParentMenu, int _ItemID, ouro::menu_handle _hSubmenu)
{
	mstring text;
	oVERIFY(oGUIMenuGetText(text, _hParentMenu, _ItemID));
	oVB(RemoveMenu((HMENU)_hParentMenu, _ItemID, MF_BYCOMMAND));
	oVB(InsertMenu((HMENU)_hParentMenu, _ItemID, MF_STRING|MF_POPUP, (UINT_PTR)_hSubmenu, text));
}

void oGUIMenuSubmenuToItem(ouro::menu_handle _hParentMenu, ouro::menu_handle _hSubmenu, int _ItemID, bool _Enabled)
{
	int p = oGUIMenuFindPosition(_hParentMenu, _hSubmenu);
	oASSERT(p != -1, "the specified submenu is not under the specified parent menu");

	mstring text;
	oVERIFY(oGUIMenuGetTextByPosition(text, text.capacity(), _hParentMenu, p));
	oVB(DeleteMenu((HMENU)_hParentMenu, p, MF_BYPOSITION));

	UINT uFlags = MF_BYPOSITION|MF_STRING;
	if (!_Enabled)
		uFlags |= MF_GRAYED;

	oVB(InsertMenu((HMENU)_hParentMenu, p, uFlags, (UINT_PTR)_ItemID, text.c_str()));
}

void oGUIMenuAppendSeparator(ouro::menu_handle _hParentMenu)
{
	oVB(AppendMenu((HMENU)_hParentMenu, MF_SEPARATOR, 0, nullptr));
}

void oGUIMenuCheck(ouro::menu_handle _hMenu, int _ItemID, bool _Checked)
{
	oASSERT(_ItemID >= 0, "");
	if (-1 == CheckMenuItem((HMENU)_hMenu, static_cast<unsigned int>(_ItemID), MF_BYCOMMAND | (_Checked ? MF_CHECKED : MF_UNCHECKED)))
		oASSERT(false, "MenuItemID not found in the specified menu");
}

bool oGUIMenuIsChecked(ouro::menu_handle _hMenu, int _ItemID)
{
	MENUITEMINFO mii;
	ZeroMemory(&mii, sizeof(mii));
	mii.cbSize = sizeof(mii);
	mii.fMask = MIIM_STATE;
	oASSERT(_ItemID >= 0, "");
	if (!GetMenuItemInfo((HMENU)_hMenu, static_cast<unsigned int>(_ItemID), FALSE, &mii))
		return false;

	if (mii.fState & MFS_CHECKED)
		return true;

	oErrorSetLast(0);
	return false;
}

void oGUIMenuCheckRadio(ouro::menu_handle _hMenu, int _ItemIDRadioRangeFirst, int _ItemIDRadioRangeLast, int _ItemIDToCheck)
{
	// CheckMenuRadioItem returns false if the menu is wrong, but doesn't set a
	// useful last error (S_OK is returned when I ran into this) so add our own
	// check here.
	oASSERT(oGUIMenuGetNumItems(_hMenu) >= (_ItemIDRadioRangeLast-_ItemIDRadioRangeFirst+1), "A radio range was specified that is larger than the number of elements in the list (menu count=%d, range implies %d items)", oGUIMenuGetNumItems(_hMenu), (_ItemIDRadioRangeLast-_ItemIDRadioRangeFirst+1));
	oASSERT(oGUIMenuContainsRange(_hMenu, _ItemIDRadioRangeFirst, _ItemIDRadioRangeLast), "The specified menu 0x%p does not include the specified range [%d,%d] with selected %d. Most API works with an ancestor menu but this requires the immediate parent, so if the ranges look correct check the specified _hMenu.", _hMenu, _ItemIDRadioRangeFirst, _ItemIDRadioRangeLast, _ItemIDToCheck);
	oVB(CheckMenuRadioItem((HMENU)_hMenu, _ItemIDRadioRangeFirst, _ItemIDRadioRangeLast, _ItemIDToCheck, MF_BYCOMMAND));
}

int oGUIMenuGetCheckedRadio(ouro::menu_handle _hMenu, int _ItemIDRadioRangeFirst, int _ItemIDRadioRangeLast)
{
	for (int i = _ItemIDRadioRangeFirst; i <= _ItemIDRadioRangeLast; i++)
		if (oGUIMenuIsChecked(_hMenu, i))
			return i;
	return -1;
}

void oGUIMenuEnable(ouro::menu_handle _hMenu, int _ItemID, bool _Enabled)
{
	oASSERT(_ItemID >= 0, "");
	if (-1 == EnableMenuItem((HMENU)_hMenu, static_cast<unsigned int>(_ItemID), MF_BYCOMMAND | (_Enabled ? MF_ENABLED : MF_GRAYED)))
		oASSERT(false, "MenuItemID not found in the specified menu");
}

bool oGUIMenuIsEnabled(ouro::menu_handle _hMenu, int _ItemID)
{
	MENUITEMINFO mii;
	ZeroMemory(&mii, sizeof(mii));
	mii.cbSize = sizeof(mii);
	mii.fMask = MIIM_STATE;
	oASSERT(_ItemID >= 0, "");
	oVB(GetMenuItemInfo((HMENU)_hMenu, static_cast<unsigned int>(_ItemID), FALSE, &mii));
	if (mii.fState & (MF_GRAYED|MF_DISABLED))
		return false;
	return true;
}

char* oGUIMenuGetText(char* _StrDestination, size_t _SizeofStrDestination, ouro::menu_handle _hMenu, int _ItemID)
{
	oCHECK_SIZE(int, _SizeofStrDestination);
	if (!GetMenuStringA((HMENU)_hMenu, _ItemID, _StrDestination, static_cast<int>(_SizeofStrDestination), MF_BYCOMMAND))
		return nullptr;
	return _StrDestination;
}

char* oGUIMenuGetText(char* _StrDestination, size_t _SizeofStrDestination, ouro::menu_handle _hParentMenu, ouro::menu_handle _hSubmenu)
{
	int pos = oGUIMenuFindPosition(_hParentMenu, _hSubmenu);
	if (pos == -1)
		return nullptr;
	return oGUIMenuGetTextByPosition(_StrDestination, _SizeofStrDestination, _hParentMenu, pos);
}
<|endoftext|>


<commit_before>#pragma once

#include "EntityManager.hpp"
#include "Color.hpp"
#include "components/SelectedComponent.hpp"
#include "reflection/Reflectible.hpp"
#include "functions/ImGuiEditor.hpp"
#include "imgui.h"
#include "magic_enum.hpp"
#include "lengthof.hpp"

namespace kengine {
	template<typename Comp>
	void registerComponentEditor(kengine::EntityManager & em);

	template<typename ... Comps>
	void registerComponentEditors(kengine::EntityManager & em);
}

namespace kengine {
	namespace detail {
		namespace imguiEditor {
			putils_member_detector(c_str);
			putils_member_detector(emplace_back);
			inline kengine::EntityManager * g_em = nullptr;
		}

		template<typename F>
		static void displayInColumns(const char * name, F && f) {
			ImGui::Columns(2);
			ImGui::Text(name);
			ImGui::NextColumn();
			f();
			ImGui::Columns();
		}

		template<typename Member>
		static void displayAttribute(const char * name, const Member & member) {
			if constexpr (imguiEditor::has_member_c_str<Member>::value) {
				displayInColumns(name, [&] {
					ImGui::Text(member.c_str());
				});
			}
			// else if constexpr (std::is_same_v<Member, const char *>::value)
			// 	ImGui::LabelText(name, member);

			else if constexpr (putils::is_iterable<Member>::value) {
				if (ImGui::TreeNode(name)) {
					int i = 0;
					for (const auto & val : member)
						displayAttribute(putils::string<64>("%d", i++), val);
					ImGui::TreePop();
				}
			}

			else if constexpr (std::is_same_v<Member, putils::Color>) {
				displayInColumns(name, [&] {
					const auto normalized = putils::toNormalizedColor(member);
					const ImVec4 col = { normalized.r, normalized.g, normalized.b, normalized.a };
					ImGui::ColorButton(putils::string<64>(name) + "#" + (intptr_t)& member, col);
				});
			}
			else if constexpr (std::is_same_v<Member, putils::NormalizedColor>) {
				displayInColumns(name, [&] {
					const ImVec4 col = { member.r, member.g, member.b, member.a };
					ImGui::ColorButton(putils::string<64>(name) + "#" + (intptr_t)& member, col);
				});
			}

			else if constexpr (putils::has_member_get_attributes<Member>::value) {
				if (ImGui::TreeNode(name)) {
					putils::for_each_attribute(Member::get_attributes(), [&member](const char * name, const auto attr) {
						displayAttribute(name, member.*attr);
					});
					ImGui::TreePop();
				}
			}
			else {
				displayInColumns(name, [&] {
					if constexpr (std::is_same_v<Member, kengine::Entity::ID>) {
						if (ImGui::Button("Select"))
							imguiEditor::g_em->getEntity(member).attach<kengine::SelectedComponent>();
						ImGui::SameLine();
						ImGui::Text("%zu", member);
					}
					else if constexpr (std::is_enum_v<Member>)
						ImGui::Text(putils::magic_enum::enum_name(member).data());
					else if constexpr (std::is_same_v<Member, bool>)
						ImGui::Text(member ? "true" : "false");
					else if constexpr (std::is_same_v<Member, int>)
						ImGui::Text("%d", member);
					else if constexpr (std::is_same_v<Member, unsigned int>)
						ImGui::Text("%zu", member);
					else if constexpr (std::is_same_v<Member, float>)
						ImGui::Text("%f", member);
					else if constexpr (std::is_same_v<Member, double>)
						ImGui::Text("%d", member);
				});
			}
		}

		template<typename Comp>
		static void displayComponent(const kengine::Entity & e) {
			if constexpr (putils::has_member_get_attributes<Comp>::value) {
				const auto & comp = e.get<Comp>();
				putils::for_each_attribute(Comp::get_attributes(), [&comp](const char * name, const auto member) {
					displayAttribute(name, comp.*member);
				});
			}
		}

		template<typename Member>
		putils::string<64> getID(const char * name, Member && member) {
			return putils::string<64>("##%s", name) + (intptr_t)&member;
		}

		template<typename MemberRef>
		static void editAttribute(const char * name, MemberRef && member) {
			using Member = std::decay_t<MemberRef>;

			if constexpr (imguiEditor::has_member_c_str<Member>::value) {
				displayInColumns(name, [&] {
					putils::string<1024> s = member.c_str();
					ImGui::PushItemWidth(-1.f);
					if (ImGui::InputText(getID(name, member), s.begin(), s.max_size))
						member = s.c_str();
					ImGui::PopItemWidth();
				});
			}
			// else if constexpr (std::is_same_v<Member, const char *>::value)
			// 	ImGui::LabelText(name, member);

			else if constexpr (putils::is_iterable<Member>::value) {
				if (ImGui::TreeNode(name)) {
					if constexpr (imguiEditor::has_member_emplace_back<Member>::value)
						if (ImGui::Button("Add"))
							member.emplace_back();
					int i = 0;
					for (auto & val : member)
						editAttribute(putils::string<64>("%d", i++), val);
					ImGui::TreePop();
				}
			}

			else if constexpr (std::is_same_v<Member, putils::Color>) {
				displayInColumns(name, [&] {
					auto normalized = putils::toNormalizedColor(member);
					const ImVec4 col = { normalized.r, normalized.g, normalized.b, normalized.a };

					if (ImGui::ColorButton(getID(name, member), col))
						ImGui::OpenPopup(name);

					if (ImGui::BeginPopup(name)) {
						if (ImGui::ColorPicker4(name, normalized.attributes))
							member = putils::toColor(normalized);
						ImGui::EndPopup();
					}
				});
			}
			else if constexpr (std::is_same_v<Member, putils::NormalizedColor>) {
				displayInColumns(name, [&] {
					const ImVec4 col = { member.r, member.g, member.b, member.a };
					if (ImGui::ColorButton(getID(name, member), col))
						ImGui::OpenPopup(name);

					if (ImGui::BeginPopup(name)) {
						ImGui::ColorPicker4(name, member.attributes);
						ImGui::EndPopup();
					}
				});
			}

			else if constexpr (putils::has_member_get_attributes<Member>::value) {
				if (ImGui::TreeNode(name)) {
					putils::for_each_attribute(Member::get_attributes(), [&member](const char * name, const auto attr) {
						editAttribute(name, member.*attr);
					});
					ImGui::TreePop();
				}
			}

			else if constexpr (std::is_same_v<Member, kengine::Entity::ID>) {
				displayInColumns(name, [&] {
					if (ImGui::Button("Select"))
						imguiEditor::g_em->getEntity(member).attach<kengine::SelectedComponent>();
					ImGui::SameLine();
					ImGui::PushItemWidth(-1.f);
					ImGui::InputScalar(getID(name, member), sizeof(Member) == 64 ? ImGuiDataType_U64 : ImGuiDataType_U32, &member);
					ImGui::PopItemWidth();
				});
			}
			else if constexpr (std::is_enum_v<Member>) {
				displayInColumns(name, [&] {
					static putils::string<64> names[putils::magic_enum::enum_count<Member>()];
					static bool first = true;
					if (first) {
						for (int i = 0; i < lengthof(names); ++i)
							names[i] = putils::magic_enum::enum_names<Member>()[i];
						first = false;
					}
					ImGui::Combo(getID(name, member), (int *)& member, [](void *, int idx, const char ** out) { *out = names[idx].c_str(); return true; }, nullptr, lengthof(names));
				});
			}
			else if constexpr (std::is_same_v<Member, bool>) {
				displayInColumns(name, [&] {
					ImGui::Checkbox(getID(name, member), &member);
				});
			}
			else if constexpr (std::is_same_v<Member, int>) {
				displayInColumns(name, [&] {
					ImGui::PushItemWidth(-1.f);
					ImGui::InputInt(getID(name, member), &member);
					ImGui::PopItemWidth();
				});
			}
			else if constexpr (std::is_same_v<Member, unsigned int>) {
				displayInColumns(name, [&] {
					ImGui::PushItemWidth(-1.f);
					ImGui::InputScalar(getID(name, member), sizeof(Member) == 64 ? ImGuiDataType_U64 : ImGuiDataType_U32, &member);
					ImGui::PopItemWidth();
				});
			}
			else if constexpr (std::is_same_v<Member, float>) {
				displayInColumns(name, [&] {
					ImGui::PushItemWidth(-1.f);
					ImGui::InputFloat(getID(name, member), &member);
					ImGui::PopItemWidth();
				});
			}
			else if constexpr (std::is_same_v<Member, double>) {
				displayInColumns(name, [&] {
					ImGui::PushItemWidth(-1.f);
					ImGui::InputDouble(getID(name, member), &member);
					ImGui::PopItemWidth();
				});
			}
			else {
				displayInColumns(name, [&] {
					ImGui::Text("Unknown type");
				});
			}
		}

		template<typename Comp>
		static void editComponent(kengine::Entity & e) {
			if constexpr (putils::has_member_get_attributes<Comp>::value) {
				auto & comp = e.get<Comp>();
				putils::for_each_attribute(Comp::get_attributes(), [&comp](const char * name, const auto member) {
					editAttribute(name, comp.*member);
				});
			}
		}
	}

	template<typename Comp>
	void registerComponentEditor(kengine::EntityManager & em) {
		detail::imguiEditor::g_em = &em;
		em.registerComponentFunction<Comp>(functions::DisplayImGui{ detail::displayComponent<Comp> });
		em.registerComponentFunction<Comp>(functions::EditImGui{ detail::editComponent<Comp> });
	}

	template<typename ... Comps>
	void registerComponentEditors(kengine::EntityManager & em) {
		pmeta_for_each(Comps, [&](auto type) {
			using Type = pmeta_wrapped(type);
			registerComponentEditor<Type>(em);
		});
	}
}<commit_msg>add assert to registerComponentEditor<commit_after>#pragma once

#include "EntityManager.hpp"
#include "Color.hpp"
#include "components/SelectedComponent.hpp"
#include "reflection/Reflectible.hpp"
#include "functions/ImGuiEditor.hpp"
#include "imgui.h"
#include "magic_enum.hpp"
#include "lengthof.hpp"

namespace kengine {
	template<typename Comp>
	void registerComponentEditor(kengine::EntityManager & em);

	template<typename ... Comps>
	void registerComponentEditors(kengine::EntityManager & em);
}

namespace kengine {
	namespace detail {
		namespace imguiEditor {
			putils_member_detector(c_str);
			putils_member_detector(emplace_back);
			inline kengine::EntityManager * g_em = nullptr;
		}

		template<typename F>
		static void displayInColumns(const char * name, F && f) {
			ImGui::Columns(2);
			ImGui::Text(name);
			ImGui::NextColumn();
			f();
			ImGui::Columns();
		}

		template<typename Member>
		static void displayAttribute(const char * name, const Member & member) {
			if constexpr (imguiEditor::has_member_c_str<Member>::value) {
				displayInColumns(name, [&] {
					ImGui::Text(member.c_str());
				});
			}
			// else if constexpr (std::is_same_v<Member, const char *>::value)
			// 	ImGui::LabelText(name, member);

			else if constexpr (putils::is_iterable<Member>::value) {
				if (ImGui::TreeNode(name)) {
					int i = 0;
					for (const auto & val : member)
						displayAttribute(putils::string<64>("%d", i++), val);
					ImGui::TreePop();
				}
			}

			else if constexpr (std::is_same_v<Member, putils::Color>) {
				displayInColumns(name, [&] {
					const auto normalized = putils::toNormalizedColor(member);
					const ImVec4 col = { normalized.r, normalized.g, normalized.b, normalized.a };
					ImGui::ColorButton(putils::string<64>(name) + "#" + (intptr_t)& member, col);
				});
			}
			else if constexpr (std::is_same_v<Member, putils::NormalizedColor>) {
				displayInColumns(name, [&] {
					const ImVec4 col = { member.r, member.g, member.b, member.a };
					ImGui::ColorButton(putils::string<64>(name) + "#" + (intptr_t)& member, col);
				});
			}

			else if constexpr (putils::has_member_get_attributes<Member>::value) {
				if (ImGui::TreeNode(name)) {
					putils::for_each_attribute(Member::get_attributes(), [&member](const char * name, const auto attr) {
						displayAttribute(name, member.*attr);
					});
					ImGui::TreePop();
				}
			}
			else {
				displayInColumns(name, [&] {
					if constexpr (std::is_same_v<Member, kengine::Entity::ID>) {
						if (ImGui::Button("Select"))
							imguiEditor::g_em->getEntity(member).attach<kengine::SelectedComponent>();
						ImGui::SameLine();
						ImGui::Text("%zu", member);
					}
					else if constexpr (std::is_enum_v<Member>)
						ImGui::Text(putils::magic_enum::enum_name(member).data());
					else if constexpr (std::is_same_v<Member, bool>)
						ImGui::Text(member ? "true" : "false");
					else if constexpr (std::is_same_v<Member, int>)
						ImGui::Text("%d", member);
					else if constexpr (std::is_same_v<Member, unsigned int>)
						ImGui::Text("%zu", member);
					else if constexpr (std::is_same_v<Member, float>)
						ImGui::Text("%f", member);
					else if constexpr (std::is_same_v<Member, double>)
						ImGui::Text("%d", member);
				});
			}
		}

		template<typename Comp>
		static void displayComponent(const kengine::Entity & e) {
			if constexpr (putils::has_member_get_attributes<Comp>::value) {
				const auto & comp = e.get<Comp>();
				putils::for_each_attribute(Comp::get_attributes(), [&comp](const char * name, const auto member) {
					displayAttribute(name, comp.*member);
				});
			}
		}

		template<typename Member>
		putils::string<64> getID(const char * name, Member && member) {
			return putils::string<64>("##%s", name) + (intptr_t)&member;
		}

		template<typename MemberRef>
		static void editAttribute(const char * name, MemberRef && member) {
			using Member = std::decay_t<MemberRef>;

			if constexpr (imguiEditor::has_member_c_str<Member>::value) {
				displayInColumns(name, [&] {
					putils::string<1024> s = member.c_str();
					ImGui::PushItemWidth(-1.f);
					if (ImGui::InputText(getID(name, member), s.begin(), s.max_size))
						member = s.c_str();
					ImGui::PopItemWidth();
				});
			}
			// else if constexpr (std::is_same_v<Member, const char *>::value)
			// 	ImGui::LabelText(name, member);

			else if constexpr (putils::is_iterable<Member>::value) {
				if (ImGui::TreeNode(name)) {
					if constexpr (imguiEditor::has_member_emplace_back<Member>::value)
						if (ImGui::Button("Add"))
							member.emplace_back();
					int i = 0;
					for (auto & val : member)
						editAttribute(putils::string<64>("%d", i++), val);
					ImGui::TreePop();
				}
			}

			else if constexpr (std::is_same_v<Member, putils::Color>) {
				displayInColumns(name, [&] {
					auto normalized = putils::toNormalizedColor(member);
					const ImVec4 col = { normalized.r, normalized.g, normalized.b, normalized.a };

					if (ImGui::ColorButton(getID(name, member), col))
						ImGui::OpenPopup(name);

					if (ImGui::BeginPopup(name)) {
						if (ImGui::ColorPicker4(name, normalized.attributes))
							member = putils::toColor(normalized);
						ImGui::EndPopup();
					}
				});
			}
			else if constexpr (std::is_same_v<Member, putils::NormalizedColor>) {
				displayInColumns(name, [&] {
					const ImVec4 col = { member.r, member.g, member.b, member.a };
					if (ImGui::ColorButton(getID(name, member), col))
						ImGui::OpenPopup(name);

					if (ImGui::BeginPopup(name)) {
						ImGui::ColorPicker4(name, member.attributes);
						ImGui::EndPopup();
					}
				});
			}

			else if constexpr (putils::has_member_get_attributes<Member>::value) {
				if (ImGui::TreeNode(name)) {
					putils::for_each_attribute(Member::get_attributes(), [&member](const char * name, const auto attr) {
						editAttribute(name, member.*attr);
					});
					ImGui::TreePop();
				}
			}

			else if constexpr (std::is_same_v<Member, kengine::Entity::ID>) {
				displayInColumns(name, [&] {
					if (ImGui::Button("Select"))
						imguiEditor::g_em->getEntity(member).attach<kengine::SelectedComponent>();
					ImGui::SameLine();
					ImGui::PushItemWidth(-1.f);
					ImGui::InputScalar(getID(name, member), sizeof(Member) == 64 ? ImGuiDataType_U64 : ImGuiDataType_U32, &member);
					ImGui::PopItemWidth();
				});
			}
			else if constexpr (std::is_enum_v<Member>) {
				static_assert(std::is_same_v<std::underlying_type_t<Member>, int>);

				displayInColumns(name, [&] {
					static putils::string<64> names[putils::magic_enum::enum_count<Member>()];
					static bool first = true;
					if (first) {
						for (int i = 0; i < lengthof(names); ++i)
							names[i] = putils::magic_enum::enum_names<Member>()[i];
						first = false;
					}
					ImGui::Combo(getID(name, member), (int *)& member, [](void *, int idx, const char ** out) { *out = names[idx].c_str(); return true; }, nullptr, lengthof(names));
				});
			}
			else if constexpr (std::is_same_v<Member, bool>) {
				displayInColumns(name, [&] {
					ImGui::Checkbox(getID(name, member), &member);
				});
			}
			else if constexpr (std::is_same_v<Member, int>) {
				displayInColumns(name, [&] {
					ImGui::PushItemWidth(-1.f);
					ImGui::InputInt(getID(name, member), &member);
					ImGui::PopItemWidth();
				});
			}
			else if constexpr (std::is_same_v<Member, unsigned int>) {
				displayInColumns(name, [&] {
					ImGui::PushItemWidth(-1.f);
					ImGui::InputScalar(getID(name, member), sizeof(Member) == 64 ? ImGuiDataType_U64 : ImGuiDataType_U32, &member);
					ImGui::PopItemWidth();
				});
			}
			else if constexpr (std::is_same_v<Member, float>) {
				displayInColumns(name, [&] {
					ImGui::PushItemWidth(-1.f);
					ImGui::InputFloat(getID(name, member), &member);
					ImGui::PopItemWidth();
				});
			}
			else if constexpr (std::is_same_v<Member, double>) {
				displayInColumns(name, [&] {
					ImGui::PushItemWidth(-1.f);
					ImGui::InputDouble(getID(name, member), &member);
					ImGui::PopItemWidth();
				});
			}
			else {
				displayInColumns(name, [&] {
					ImGui::Text("Unknown type");
				});
			}
		}

		template<typename Comp>
		static void editComponent(kengine::Entity & e) {
			if constexpr (putils::has_member_get_attributes<Comp>::value) {
				auto & comp = e.get<Comp>();
				putils::for_each_attribute(Comp::get_attributes(), [&comp](const char * name, const auto member) {
					editAttribute(name, comp.*member);
				});
			}
		}
	}

	template<typename Comp>
	void registerComponentEditor(kengine::EntityManager & em) {
		detail::imguiEditor::g_em = &em;
		em.registerComponentFunction<Comp>(functions::DisplayImGui{ detail::displayComponent<Comp> });
		em.registerComponentFunction<Comp>(functions::EditImGui{ detail::editComponent<Comp> });
	}

	template<typename ... Comps>
	void registerComponentEditors(kengine::EntityManager & em) {
		pmeta_for_each(Comps, [&](auto type) {
			using Type = pmeta_wrapped(type);
			registerComponentEditor<Type>(em);
		});
	}
}<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of meegotouch-controlpanelsoundsettingsapplet.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** 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
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/
#include "alerttonebrowser.h"
#include "alerttonedefaults.h"
#include "alerttoneappletmaps.h"
#include "trackerconnection.h"
#include "drilldownitem.h"

#include <QtTracker/Tracker>
#include <QGraphicsLinearLayout>

#ifdef HAVE_CONTENT_MANAGER
/*
 * Defining this for now...
 * it seems it crashes somehow..
 * and i couldn't get any usable backtrace as
 * gdb is crashes too :-S
 */
#define SINGLE_CONTENTITEM
#include <SelectSingleContentItemPage.h>
#include <ContentItemsPage.h>
#endif

#include <MList>
#include <MListFilter>
#include <MApplication>
#include <MApplicationPage>
#include <MApplicationWindow>
#include <MWindow>
#include <MAction>
#include <MTextEdit>
#include <MImageWidget>
#include <MContentItem>

//#define DEBUG
#define WARNING
#include "../debug.h"

static const int filterEditorPosition = 2;

class MCustomContentItem: public MContentItem
{
public:
    MCustomContentItem (MContentItem::ContentItemStyle itemStyle=MContentItem::IconAndTwoTextLabels, QGraphicsItem *parent=0)
    :MContentItem(itemStyle,parent),fullPath("") {}

    QString fullPath;
};

/******************************************************************************
 * AlertToneBrowser implementation.
 */
AlertToneBrowser::AlertToneBrowser(AlertTone *tone, QGraphicsWidget *parent):
    AlertToneToplevel (parent),
    m_tone (tone),
    m_defaults (0),
    m_preview (0),
    m_MusicBrowser (0),
    m_DoneAction (0),
    m_CancelAction (0)
{
    /*
     * FIXME: Why do we need to set the title?
     */
    setProperty ("title", AlertToneAppletMaps::mapToUiString (m_tone->key ()));

    createContent();
}

AlertToneBrowser::~AlertToneBrowser()
{
    SYS_DEBUG ("");
    stopPlayingSound ();
}

void
AlertToneBrowser::createContent()
{
    m_MainLayout = new QGraphicsLinearLayout (Qt::Vertical);
    m_MainLayout->setContentsMargins (0., 0., 0., 0.);
    m_MainLayout->setSpacing (0.);
    setLayout (m_MainLayout);

#ifdef HAVE_CONTENT_MANAGER
    // "Pick from My Music"
    m_my_music = new DrillDownItem;
    m_my_music->setLayoutPosition (M::VerticalTopPosition);
    m_my_music->imageWidget()->setImage("icon-l-music");
    m_my_music->setObjectName("MContentItem_pickFromMyMusic");
    m_MainLayout->addItem (m_my_music);
    connect (m_my_music, SIGNAL (clicked ()), SLOT (launchMusicBrowser ()));
#endif

    // "Get more from Ovi store"
    m_ovi_store = new DrillDownItem;
    m_ovi_store->setLayoutPosition (M::VerticalBottomPosition);
    m_ovi_store->imageWidget()->setImage("icon-m-common-ovi");
    m_ovi_store->setObjectName("MContentItem_getMoreFromOviStore");
    m_MainLayout->addItem (m_ovi_store);
    connect (m_ovi_store, SIGNAL (clicked ()), SLOT (launchOviStore ()));

    /*
     * The list with the available sound files.
     */
    m_defaults = new AlertToneDefaults(m_tone, 0);
    m_defaults->filtering()->setEnabled (true);
    m_defaults->filtering()->setFilterMode (
            MListFilter::FilterAsBeginningOfLine);
    m_LiveFilterEditor = m_defaults->filtering()->editor();
    m_MainLayout->addItem(m_defaults);
    connect (m_defaults, SIGNAL (displayEntered ()),
             SLOT (defaultsDisplayEntered ()));

    // We need this stretch to keep the widgets growing in size when too much
    // lines are filtered out from the list.
    m_MainLayout->addStretch ();

    retranslateUi();

    m_defaults->selectAndScroll (m_tone->fileName(), m_tone->niceName());

    connect (m_LiveFilterEditor, SIGNAL(textChanged()),
            this, SLOT(textChanged ()));

    connect(m_defaults, SIGNAL(defaultItemClicked(const QString &)),
            this, SLOT(defaultItemClicked(const QString &)));
}

void
AlertToneBrowser::defaultsDisplayEntered()
{
    SYS_DEBUG ("");

    /*
     * A fix for the NB#198788 - Live filtering text editor loses focus in
     * this scenario
     */
    if (!m_LiveFilterEditor || !m_LiveFilterEditor->isOnDisplay())
        m_defaults->setFocus();
}

void
AlertToneBrowser::retranslateUi()
{
#ifdef HAVE_CONTENT_MANAGER
    m_my_music->setProperty ("title", qtTrId("qtn_sond_pick_music"));
#endif
    m_ovi_store->setProperty("title", qtTrId("qtn_sond_store"));

    if (m_DoneAction)
        //% "Done"
        m_DoneAction->setText (qtTrId("qtn_comm_command_done"));

    if (m_CancelAction)
        //% "Cancel"
        m_CancelAction->setText (qtTrId("qtn_comm_cancel"));
}

void
AlertToneBrowser::cancel()
{
    SYS_DEBUG ("");
    m_defaults->toneChanged ();
    emit closePage();
}

void
AlertToneBrowser::accept()
{
    SYS_DEBUG ("");
    if (!currSelectedFile.isEmpty())
        m_tone->set(currSelectedFile);

    emit closePage();
}

void
AlertToneBrowser::launchMusicBrowser()
{
#ifdef HAVE_CONTENT_MANAGER
    SYS_DEBUG ("launching content picker...");

    if (! m_MusicBrowser)
    {
#ifdef SINGLE_CONTENTITEM
        SelectSingleContentItemPage *page =
            = new SelectSingleContentItemPage (
                QString (),
                QStringList () <<
                  "http://www.tracker-project.org/temp/nmm#MusicPiece",
                m_tone->trackerId ());

        m_MusicBrowser = page;

        page->setObjectName ("SelectSingleContentItemPage_musicBrowser");
        connect (page, SIGNAL (backButtonClicked ()),
                 SLOT (browserBackButtonClicked ()));
        connect (page, SIGNAL (contentItemSelected (const QString&)),
                 SLOT (selectingMusicItem (const QString&)));
#else
        ContentItemsPage *page = new ContentItemsPage;
        page->setCommonLayoutSuffix ("Inverted");
        page->setContentTypes (
                QStringList () <<
                  "http://www.tracker-project.org/temp/nmm#MusicPiece");
        page->selectItem (m_tone->trackerId ());

        m_MusicBrowser = page;

        page->setObjectName ("SelectSingleContentItemPage_musicBrowser");
        connect (page, SIGNAL (backButtonClicked ()),
                 SLOT (browserBackButtonClicked ()));
        connect (page, SIGNAL (itemClicked (const QString&)),
                 SLOT (selectingMusicItem (const QString&)));
#endif
    }

    m_MusicBrowser->appear (MSceneWindow::DestroyWhenDismissed);
#endif
}

void
AlertToneBrowser::launchOviStore()
{
    QString cmdline = "webwidgetrunner /usr/share/webwidgets/applications/d34177b1c241ea44cb132005b63ee6527c9f6040-wrt-widget.desktop -widgetparameter ringtones " /* + m_tone->key() */ + QString("&");
    qDebug() << "AlertToneBrowser(" << m_tone->key() << ")::launchOviStore:" << cmdline;
    system(cmdline.toUtf8().constData());
}

static QString
trackerIdToFilename(const QString &trackerId)
{
    const QString query = "select ?u where { <" + trackerId + "> nie:url ?u }";

    QVector<QStringList> result = ::tracker()->rawSparqlQuery(query);

    SYS_DEBUG ("*** query         = %s", SYS_STR(query));
    SYS_DEBUG ("*** result.size() = %d", result.size());
    for (int Nix = 0; Nix < result.size() ; Nix++) {
        for (int Nix1 = 0 ; Nix1 < result[Nix].size() ; Nix1++) {
            QUrl url(result[Nix][Nix1]);
            SYS_DEBUG ("*** result[%d][%d] = %s",
                    Nix, Nix1, SYS_STR(result[Nix][Nix1]));
            if (url.isValid() && url.scheme() == "file")
                return QUrl::fromPercentEncoding(url.path().toUtf8());
        }
    }

    return QString("");
}

/*
 * NOTE: This method will not start the playing of the sound file any more.
 */
void
AlertToneBrowser::setAlertTone (
        const QString &fname,
        bool           setGui)
{
    SYS_DEBUG ("*** fname  = %s", SYS_STR(fname));
    SYS_DEBUG ("*** setGui = %s", SYS_BOOL(setGui));

    currSelectedFile = fname;

    if (setGui) {
        /*
         * The nice name is most probably already in the cache. If not the model
         * will do receive a signal.
         * FIXME: how could we test this? Do we need to teszt what happens when
         * this item is not cached yet?
         */
        m_defaults->selectAndScroll (fname,
                TrackerConnection::instance()->niceNameFromFileName(fname));
    }
}

/*!
 * This slot is called when the text in the live filtering text editor has been
 * changed.
 */
void
AlertToneBrowser::textChanged ()
{
    bool     visible;
    QString  text;

    visible = m_LiveFilterEditor->isOnDisplay();
    if (!m_MainLayout)
        return;

    text = m_LiveFilterEditor->text();

    if (visible && text.isEmpty()) {
         /*
          * Removing the filter editor from the layout.
          */
        m_defaults->setFocus();
        m_LiveFilterEditor->setVisible (false);
        m_MainLayout->removeItem (m_LiveFilterEditor);
    } else if (!visible && !text.isEmpty()) {
        /*
         * Adding the filter editor widget to the layout.
         */
        m_MainLayout->insertItem (filterEditorPosition, m_LiveFilterEditor);
        m_LiveFilterEditor->setVisible (true);
        m_LiveFilterEditor->setFocus();
    }

    m_MainLayout->invalidate ();
    m_defaults->setFilterText (m_LiveFilterEditor->text());
    update ();
}

/*
 * This method will start the playback of a given file. If the player is already
 * playing the very same file the playback will be started.
 */
void
AlertToneBrowser::startPlayingSound (
        const QString &filename)
{
    bool playingTheSame = m_preview && m_preview->fname() == filename;

    SYS_DEBUG ("playingTheSame = %s", SYS_BOOL(playingTheSame));
    /*
     * If we are already playing the same sound we stop the playback. This is
     * coming from the UI specification: "Second tap of the item will stop the
     * preview while the sound is playing.
     */
    if (playingTheSame) {
        delete m_preview;
    } else {
        if (m_preview)
            delete m_preview;
        m_preview = new AlertTonePreview(filename);
    }
}

/*
 * This method will stop the playback unconditionaly.
 */
void
AlertToneBrowser::stopPlayingSound ()
{
    if (m_preview)
        delete m_preview;
}

/*
 * This slot is activated when the user clicks on a sound file in the default
 * sound list.
 */
void
AlertToneBrowser::defaultItemClicked (
        const QString &filename)
{
    SYS_DEBUG ("*** filename = %s", SYS_STR(filename));
    // We don't need to set the UI, this signal came from the UI already.
    setAlertTone (filename, false);
    startPlayingSound (filename);
}

/*
 * This slot is activated when the browser back button is clicked. Stopping the
 * playback will fix NB#199653 - Music preview doesn't stop when leaving from
 * "Select from My music" view.
 *
 * FIXME: Maybe watching the back button signal is not robus enough, the
 * playback will not be stopped when some other method is used to page back...
 */
void
AlertToneBrowser::browserBackButtonClicked ()
{
    SYS_DEBUG ("");
    stopPlayingSound ();
#ifdef HAVE_CONTENT_MANAGER
    m_MusicBrowser->dismiss ();
    m_MusicBrowser = 0;
#endif
}

/*
 * This slot is activated when the user selects one item from the content
 * picker.
 */
void
AlertToneBrowser::selectingMusicItem (
        const QString &item)
{
    QString fname = trackerIdToFilename(item);

    if (fname.isEmpty()) {
        SYS_WARNING ("TrackerID '%s' is not valid.", SYS_STR(item));
        stopPlayingSound ();
        return;
    }

    SYS_DEBUG ("*** trackerID = %s", SYS_STR(item));
    SYS_DEBUG ("*** fname     = %s", SYS_STR(fname));

    #ifndef SINGLE_CONTENTITEM
    m_MusicBrowser->dismiss ();
    #endif

    setAlertTone (fname, true);
    startPlayingSound (fname);
}

/*
 * This virtual method is called when the MApplicationPage for the widget is
 * already there, so we can initialize it.
 */
void
AlertToneBrowser::polishEvent ()
{
    QGraphicsWidget  *parent;
    MApplicationPage *page = 0;

    SYS_DEBUG ("");
    /*
     * Just a protection about double adding the actions.
     */
    if (m_DoneAction)
        return;

    MWindow *win = MApplication::activeWindow ();
    if (win) {
        connect (win, SIGNAL(displayExited()),
                this, SLOT(stopPlayingSound()));
        connect (win, SIGNAL(switcherEntered()),
                this, SLOT(stopPlayingSound()));
    }

    /*
     * We need to find the MApplicationPage among our parents.
     */
    parent = parentWidget();
    while (parent) {
        page = qobject_cast <MApplicationPage *>(parent);
        if (page)
            break;
        parent = parent->parentWidget();
    }

    if (!page)
        return;

    /**************************************************************************
     * Hiding the home button and the escape button from the page.
     */
    page->setComponentsDisplayMode (
            MApplicationPage::EscapeButton,
            MApplicationPageModel::Hide);
    page->setComponentsDisplayMode (
            MApplicationPage::HomeButton,
            MApplicationPageModel::Hide);

    //% "Done"
    m_DoneAction = new MAction(qtTrId("qtn_comm_command_done"), this);
    m_DoneAction->setLocation(MAction::ToolBarLocation);
    page->addAction(m_DoneAction);
    connect(m_DoneAction, SIGNAL(triggered()), SLOT(accept()));

    //% "Cancel"
    m_CancelAction = new MAction(qtTrId("qtn_comm_cancel"), this);
    m_CancelAction->setLocation(MAction::ToolBarLocation);
    page->addAction(m_CancelAction);
    connect(m_CancelAction, SIGNAL(triggered()), SLOT(cancel()));
}

<commit_msg>Fixes: a typo<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of meegotouch-controlpanelsoundsettingsapplet.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** 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
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/
#include "alerttonebrowser.h"
#include "alerttonedefaults.h"
#include "alerttoneappletmaps.h"
#include "trackerconnection.h"
#include "drilldownitem.h"

#include <QtTracker/Tracker>
#include <QGraphicsLinearLayout>

#ifdef HAVE_CONTENT_MANAGER
/*
 * Defining this for now...
 * it seems it crashes somehow..
 * and i couldn't get any usable backtrace as
 * gdb is crashes too :-S
 */
#define SINGLE_CONTENTITEM
#include <SelectSingleContentItemPage.h>
#include <ContentItemsPage.h>
#endif

#include <MList>
#include <MListFilter>
#include <MApplication>
#include <MApplicationPage>
#include <MApplicationWindow>
#include <MWindow>
#include <MAction>
#include <MTextEdit>
#include <MImageWidget>
#include <MContentItem>

//#define DEBUG
#define WARNING
#include "../debug.h"

static const int filterEditorPosition = 2;

class MCustomContentItem: public MContentItem
{
public:
    MCustomContentItem (MContentItem::ContentItemStyle itemStyle=MContentItem::IconAndTwoTextLabels, QGraphicsItem *parent=0)
    :MContentItem(itemStyle,parent),fullPath("") {}

    QString fullPath;
};

/******************************************************************************
 * AlertToneBrowser implementation.
 */
AlertToneBrowser::AlertToneBrowser(AlertTone *tone, QGraphicsWidget *parent):
    AlertToneToplevel (parent),
    m_tone (tone),
    m_defaults (0),
    m_preview (0),
    m_MusicBrowser (0),
    m_DoneAction (0),
    m_CancelAction (0)
{
    /*
     * FIXME: Why do we need to set the title?
     */
    setProperty ("title", AlertToneAppletMaps::mapToUiString (m_tone->key ()));

    createContent();
}

AlertToneBrowser::~AlertToneBrowser()
{
    SYS_DEBUG ("");
    stopPlayingSound ();
}

void
AlertToneBrowser::createContent()
{
    m_MainLayout = new QGraphicsLinearLayout (Qt::Vertical);
    m_MainLayout->setContentsMargins (0., 0., 0., 0.);
    m_MainLayout->setSpacing (0.);
    setLayout (m_MainLayout);

#ifdef HAVE_CONTENT_MANAGER
    // "Pick from My Music"
    m_my_music = new DrillDownItem;
    m_my_music->setLayoutPosition (M::VerticalTopPosition);
    m_my_music->imageWidget()->setImage("icon-l-music");
    m_my_music->setObjectName("MContentItem_pickFromMyMusic");
    m_MainLayout->addItem (m_my_music);
    connect (m_my_music, SIGNAL (clicked ()), SLOT (launchMusicBrowser ()));
#endif

    // "Get more from Ovi store"
    m_ovi_store = new DrillDownItem;
    m_ovi_store->setLayoutPosition (M::VerticalBottomPosition);
    m_ovi_store->imageWidget()->setImage("icon-m-common-ovi");
    m_ovi_store->setObjectName("MContentItem_getMoreFromOviStore");
    m_MainLayout->addItem (m_ovi_store);
    connect (m_ovi_store, SIGNAL (clicked ()), SLOT (launchOviStore ()));

    /*
     * The list with the available sound files.
     */
    m_defaults = new AlertToneDefaults(m_tone, 0);
    m_defaults->filtering()->setEnabled (true);
    m_defaults->filtering()->setFilterMode (
            MListFilter::FilterAsBeginningOfLine);
    m_LiveFilterEditor = m_defaults->filtering()->editor();
    m_MainLayout->addItem(m_defaults);
    connect (m_defaults, SIGNAL (displayEntered ()),
             SLOT (defaultsDisplayEntered ()));

    // We need this stretch to keep the widgets growing in size when too much
    // lines are filtered out from the list.
    m_MainLayout->addStretch ();

    retranslateUi();

    m_defaults->selectAndScroll (m_tone->fileName(), m_tone->niceName());

    connect (m_LiveFilterEditor, SIGNAL(textChanged()),
            this, SLOT(textChanged ()));

    connect(m_defaults, SIGNAL(defaultItemClicked(const QString &)),
            this, SLOT(defaultItemClicked(const QString &)));
}

void
AlertToneBrowser::defaultsDisplayEntered()
{
    SYS_DEBUG ("");

    /*
     * A fix for the NB#198788 - Live filtering text editor loses focus in
     * this scenario
     */
    if (!m_LiveFilterEditor || !m_LiveFilterEditor->isOnDisplay())
        m_defaults->setFocus();
}

void
AlertToneBrowser::retranslateUi()
{
#ifdef HAVE_CONTENT_MANAGER
    m_my_music->setProperty ("title", qtTrId("qtn_sond_pick_music"));
#endif
    m_ovi_store->setProperty("title", qtTrId("qtn_sond_store"));

    if (m_DoneAction)
        //% "Done"
        m_DoneAction->setText (qtTrId("qtn_comm_command_done"));

    if (m_CancelAction)
        //% "Cancel"
        m_CancelAction->setText (qtTrId("qtn_comm_cancel"));
}

void
AlertToneBrowser::cancel()
{
    SYS_DEBUG ("");
    m_defaults->toneChanged ();
    emit closePage();
}

void
AlertToneBrowser::accept()
{
    SYS_DEBUG ("");
    if (!currSelectedFile.isEmpty())
        m_tone->set(currSelectedFile);

    emit closePage();
}

void
AlertToneBrowser::launchMusicBrowser()
{
#ifdef HAVE_CONTENT_MANAGER
    SYS_DEBUG ("launching content picker...");

    if (! m_MusicBrowser)
    {
#ifdef SINGLE_CONTENTITEM
        SelectSingleContentItemPage *page =
            new SelectSingleContentItemPage (
                QString (),
                QStringList () <<
                  "http://www.tracker-project.org/temp/nmm#MusicPiece",
                m_tone->trackerId ());

        m_MusicBrowser = page;

        page->setObjectName ("SelectSingleContentItemPage_musicBrowser");
        connect (page, SIGNAL (backButtonClicked ()),
                 SLOT (browserBackButtonClicked ()));
        connect (page, SIGNAL (contentItemSelected (const QString&)),
                 SLOT (selectingMusicItem (const QString&)));
#else
        ContentItemsPage *page = new ContentItemsPage;
        page->setCommonLayoutSuffix ("Inverted");
        page->setContentTypes (
                QStringList () <<
                  "http://www.tracker-project.org/temp/nmm#MusicPiece");
        page->selectItem (m_tone->trackerId ());

        m_MusicBrowser = page;

        page->setObjectName ("SelectSingleContentItemPage_musicBrowser");
        connect (page, SIGNAL (backButtonClicked ()),
                 SLOT (browserBackButtonClicked ()));
        connect (page, SIGNAL (itemClicked (const QString&)),
                 SLOT (selectingMusicItem (const QString&)));
#endif
    }

    m_MusicBrowser->appear (MSceneWindow::DestroyWhenDismissed);
#endif
}

void
AlertToneBrowser::launchOviStore()
{
    QString cmdline = "webwidgetrunner /usr/share/webwidgets/applications/d34177b1c241ea44cb132005b63ee6527c9f6040-wrt-widget.desktop -widgetparameter ringtones " /* + m_tone->key() */ + QString("&");
    qDebug() << "AlertToneBrowser(" << m_tone->key() << ")::launchOviStore:" << cmdline;
    system(cmdline.toUtf8().constData());
}

static QString
trackerIdToFilename(const QString &trackerId)
{
    const QString query = "select ?u where { <" + trackerId + "> nie:url ?u }";

    QVector<QStringList> result = ::tracker()->rawSparqlQuery(query);

    SYS_DEBUG ("*** query         = %s", SYS_STR(query));
    SYS_DEBUG ("*** result.size() = %d", result.size());
    for (int Nix = 0; Nix < result.size() ; Nix++) {
        for (int Nix1 = 0 ; Nix1 < result[Nix].size() ; Nix1++) {
            QUrl url(result[Nix][Nix1]);
            SYS_DEBUG ("*** result[%d][%d] = %s",
                    Nix, Nix1, SYS_STR(result[Nix][Nix1]));
            if (url.isValid() && url.scheme() == "file")
                return QUrl::fromPercentEncoding(url.path().toUtf8());
        }
    }

    return QString("");
}

/*
 * NOTE: This method will not start the playing of the sound file any more.
 */
void
AlertToneBrowser::setAlertTone (
        const QString &fname,
        bool           setGui)
{
    SYS_DEBUG ("*** fname  = %s", SYS_STR(fname));
    SYS_DEBUG ("*** setGui = %s", SYS_BOOL(setGui));

    currSelectedFile = fname;

    if (setGui) {
        /*
         * The nice name is most probably already in the cache. If not the model
         * will do receive a signal.
         * FIXME: how could we test this? Do we need to teszt what happens when
         * this item is not cached yet?
         */
        m_defaults->selectAndScroll (fname,
                TrackerConnection::instance()->niceNameFromFileName(fname));
    }
}

/*!
 * This slot is called when the text in the live filtering text editor has been
 * changed.
 */
void
AlertToneBrowser::textChanged ()
{
    bool     visible;
    QString  text;

    visible = m_LiveFilterEditor->isOnDisplay();
    if (!m_MainLayout)
        return;

    text = m_LiveFilterEditor->text();

    if (visible && text.isEmpty()) {
         /*
          * Removing the filter editor from the layout.
          */
        m_defaults->setFocus();
        m_LiveFilterEditor->setVisible (false);
        m_MainLayout->removeItem (m_LiveFilterEditor);
    } else if (!visible && !text.isEmpty()) {
        /*
         * Adding the filter editor widget to the layout.
         */
        m_MainLayout->insertItem (filterEditorPosition, m_LiveFilterEditor);
        m_LiveFilterEditor->setVisible (true);
        m_LiveFilterEditor->setFocus();
    }

    m_MainLayout->invalidate ();
    m_defaults->setFilterText (m_LiveFilterEditor->text());
    update ();
}

/*
 * This method will start the playback of a given file. If the player is already
 * playing the very same file the playback will be started.
 */
void
AlertToneBrowser::startPlayingSound (
        const QString &filename)
{
    bool playingTheSame = m_preview && m_preview->fname() == filename;

    SYS_DEBUG ("playingTheSame = %s", SYS_BOOL(playingTheSame));
    /*
     * If we are already playing the same sound we stop the playback. This is
     * coming from the UI specification: "Second tap of the item will stop the
     * preview while the sound is playing.
     */
    if (playingTheSame) {
        delete m_preview;
    } else {
        if (m_preview)
            delete m_preview;
        m_preview = new AlertTonePreview(filename);
    }
}

/*
 * This method will stop the playback unconditionaly.
 */
void
AlertToneBrowser::stopPlayingSound ()
{
    if (m_preview)
        delete m_preview;
}

/*
 * This slot is activated when the user clicks on a sound file in the default
 * sound list.
 */
void
AlertToneBrowser::defaultItemClicked (
        const QString &filename)
{
    SYS_DEBUG ("*** filename = %s", SYS_STR(filename));
    // We don't need to set the UI, this signal came from the UI already.
    setAlertTone (filename, false);
    startPlayingSound (filename);
}

/*
 * This slot is activated when the browser back button is clicked. Stopping the
 * playback will fix NB#199653 - Music preview doesn't stop when leaving from
 * "Select from My music" view.
 *
 * FIXME: Maybe watching the back button signal is not robus enough, the
 * playback will not be stopped when some other method is used to page back...
 */
void
AlertToneBrowser::browserBackButtonClicked ()
{
    SYS_DEBUG ("");
    stopPlayingSound ();
#ifdef HAVE_CONTENT_MANAGER
    m_MusicBrowser->dismiss ();
    m_MusicBrowser = 0;
#endif
}

/*
 * This slot is activated when the user selects one item from the content
 * picker.
 */
void
AlertToneBrowser::selectingMusicItem (
        const QString &item)
{
    QString fname = trackerIdToFilename(item);

    if (fname.isEmpty()) {
        SYS_WARNING ("TrackerID '%s' is not valid.", SYS_STR(item));
        stopPlayingSound ();
        return;
    }

    SYS_DEBUG ("*** trackerID = %s", SYS_STR(item));
    SYS_DEBUG ("*** fname     = %s", SYS_STR(fname));

    #ifndef SINGLE_CONTENTITEM
    m_MusicBrowser->dismiss ();
    #endif

    setAlertTone (fname, true);
    startPlayingSound (fname);
}

/*
 * This virtual method is called when the MApplicationPage for the widget is
 * already there, so we can initialize it.
 */
void
AlertToneBrowser::polishEvent ()
{
    QGraphicsWidget  *parent;
    MApplicationPage *page = 0;

    SYS_DEBUG ("");
    /*
     * Just a protection about double adding the actions.
     */
    if (m_DoneAction)
        return;

    MWindow *win = MApplication::activeWindow ();
    if (win) {
        connect (win, SIGNAL(displayExited()),
                this, SLOT(stopPlayingSound()));
        connect (win, SIGNAL(switcherEntered()),
                this, SLOT(stopPlayingSound()));
    }

    /*
     * We need to find the MApplicationPage among our parents.
     */
    parent = parentWidget();
    while (parent) {
        page = qobject_cast <MApplicationPage *>(parent);
        if (page)
            break;
        parent = parent->parentWidget();
    }

    if (!page)
        return;

    /**************************************************************************
     * Hiding the home button and the escape button from the page.
     */
    page->setComponentsDisplayMode (
            MApplicationPage::EscapeButton,
            MApplicationPageModel::Hide);
    page->setComponentsDisplayMode (
            MApplicationPage::HomeButton,
            MApplicationPageModel::Hide);

    //% "Done"
    m_DoneAction = new MAction(qtTrId("qtn_comm_command_done"), this);
    m_DoneAction->setLocation(MAction::ToolBarLocation);
    page->addAction(m_DoneAction);
    connect(m_DoneAction, SIGNAL(triggered()), SLOT(accept()));

    //% "Cancel"
    m_CancelAction = new MAction(qtTrId("qtn_comm_cancel"), this);
    m_CancelAction->setLocation(MAction::ToolBarLocation);
    page->addAction(m_CancelAction);
    connect(m_CancelAction, SIGNAL(triggered()), SLOT(cancel()));
}

<|endoftext|>