<commit_before>/*********************************************************************
* Software License Agreement (BSD License)
*
*  Copyright (c) 2009, Willow Garage, Inc.
*  All rights reserved.
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of Willow Garage, Inc. nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
*  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
*  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
*  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
*  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
*  POSSIBILITY OF SUCH DAMAGE.
********************************************************************/

// Bring in my package's API, which is what I'm testing
#include "ros/ros.h"
#include "topic_tools/shape_shifter.h"
#include "std_msgs/String.h"
#include "std_msgs/Int32.h"

// Bring in gtest
#include <gtest/gtest.h>

class ShapeShifterSubscriber : public testing::Test
{
  public:

  bool success;

  void messageCallbackInt(const topic_tools::ShapeShifter::ConstPtr& msg)
  {
    try {
      std_msgs::Int32::Ptr s = msg->instantiate<std_msgs::Int32>();
    } catch (topic_tools::ShapeShifterException& e)
    {
      success = true;
    }
  }

  void messageCallbackString(const topic_tools::ShapeShifter::ConstPtr& msg)
  {
    try {
      std_msgs::String::Ptr s = msg->instantiate<std_msgs::String>();
      if (s->data == "chatter")
        success = true;
    } catch (topic_tools::ShapeShifterException& e)
    {

    }
  }

protected:
  ShapeShifterSubscriber() {}

  void SetUp()
  {
    success = false;
  }

  void TearDown()  {}
};

TEST_F(ShapeShifterSubscriber, testInstantiateString)
{
  ros::NodeHandle nh;
  ros::Subscriber sub = nh.subscribe<topic_tools::ShapeShifter>("input",1,&ShapeShifterSubscriber::messageCallbackString, (ShapeShifterSubscriber*)this);

  ros::Time t1(ros::Time::now()+ros::Duration(10.0));

  while(ros::Time::now() < t1 && !success)
  {
    ros::WallDuration(0.01).sleep();
    ros::spinOnce();
  }

  if(success)
    SUCCEED();
  else
    FAIL();
}

TEST_F(ShapeShifterSubscriber, testInstantiateInt)
{
  ros::NodeHandle nh;
  ros::Subscriber sub = nh.subscribe<topic_tools::ShapeShifter>("input",1,&ShapeShifterSubscriber::messageCallbackInt, (ShapeShifterSubscriber*)this);

  ros::Time t1(ros::Time::now()+ros::Duration(10.0));

  while(ros::Time::now() < t1 && !success)
  {
    ros::WallDuration(0.01).sleep();
    ros::spinOnce();
  }

  if(success)
    SUCCEED();
  else
    FAIL();
}

int main(int argc, char **argv){
    ros::init(argc, argv, "test_shapeshifter");

    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<commit_msg>Adding loopback test for shapeshifter<commit_after>/*********************************************************************
* Software License Agreement (BSD License)
*
*  Copyright (c) 2009, Willow Garage, Inc.
*  All rights reserved.
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of Willow Garage, Inc. nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
*  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
*  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
*  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
*  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
*  POSSIBILITY OF SUCH DAMAGE.
********************************************************************/

// Bring in my package's API, which is what I'm testing
#include "ros/ros.h"
#include "topic_tools/shape_shifter.h"
#include "std_msgs/String.h"
#include "std_msgs/Int32.h"

// Bring in gtest
#include <gtest/gtest.h>

class ShapeShifterSubscriber : public testing::Test
{
  public:

  bool success;

  void messageCallbackInt(const topic_tools::ShapeShifter::ConstPtr& msg)
  {
    try {
      std_msgs::Int32::Ptr s = msg->instantiate<std_msgs::Int32>();
    } catch (topic_tools::ShapeShifterException& e)
    {
      success = true;
    }
  }

  void messageCallbackString(const topic_tools::ShapeShifter::ConstPtr& msg)
  {
    try {
      std_msgs::String::Ptr s = msg->instantiate<std_msgs::String>();
      if (s->data == "chatter")
        success = true;
    } catch (topic_tools::ShapeShifterException& e)
    {

    }
  }

  void messageCallbackLoopback(const topic_tools::ShapeShifter::ConstPtr& msg)
  {
    try {
      std_msgs::String::Ptr s = msg->instantiate<std_msgs::String>();
      printf("Got data: %s", s->data.c_str());
      if (s->data == "abc123")
        success = true;
    } catch (topic_tools::ShapeShifterException& e)
    {
        printf("Instantiate failed!\n");
    }
  }

protected:
  ShapeShifterSubscriber() {}

  void SetUp()
  {
    success = false;
  }

  void TearDown()  {}
};

TEST_F(ShapeShifterSubscriber, testInstantiateString)
{
  ros::NodeHandle nh;
  ros::Subscriber sub = nh.subscribe<topic_tools::ShapeShifter>("input",1,&ShapeShifterSubscriber::messageCallbackString, (ShapeShifterSubscriber*)this);

  ros::Time t1(ros::Time::now()+ros::Duration(10.0));

  while(ros::Time::now() < t1 && !success)
  {
    ros::WallDuration(0.01).sleep();
    ros::spinOnce();
  }

  if(success)
    SUCCEED();
  else
    FAIL();
}

TEST_F(ShapeShifterSubscriber, testInstantiateInt)
{
  ros::NodeHandle nh;
  ros::Subscriber sub = nh.subscribe<topic_tools::ShapeShifter>("input",1,&ShapeShifterSubscriber::messageCallbackInt, (ShapeShifterSubscriber*)this);

  ros::Time t1(ros::Time::now()+ros::Duration(10.0));

  while(ros::Time::now() < t1 && !success)
  {
    ros::WallDuration(0.01).sleep();
    ros::spinOnce();
  }

  if(success)
    SUCCEED();
  else
    FAIL();
}

TEST_F(ShapeShifterSubscriber, testLoopback)
{
  ros::NodeHandle nh;
  ros::Subscriber sub = nh.subscribe<topic_tools::ShapeShifter>("loopback",1,&ShapeShifterSubscriber::messageCallbackLoopback, (ShapeShifterSubscriber*)this);

  ros::Time t1(ros::Time::now()+ros::Duration(10.0));

  ros::Publisher pub = nh.advertise<std_msgs::String>("loopback", 1);
  std_msgs::String s;
  s.data = "abc123";
  pub.publish(s);

  while(ros::Time::now() < t1 && !success)
  {
    ros::WallDuration(0.01).sleep();
    ros::spinOnce();
  }

  if(success)
    SUCCEED();
  else
    FAIL();
}

int main(int argc, char **argv){
    ros::init(argc, argv, "test_shapeshifter");

    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors

// 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.

#ifndef SOL_FUNCTION_TYPES_HPP
#define SOL_FUNCTION_TYPES_HPP

#include "function_types_core.hpp"
#include "function_types_templated.hpp"
#include "function_types_basic.hpp"
#include "function_types_allocator.hpp"
#include "function_types_member.hpp"
#include "function_types_usertype.hpp"
#include "function_types_overload.hpp"
#include "function_types_allocator.hpp"
#include "resolve.hpp"

namespace sol {

template <typename Sig, typename... Ps>
struct function_arguments {
    std::tuple<Ps...> params;
    template <typename... Args>
    function_arguments(Args&&... args) : params(std::forward<Args>(args)...) {}
};

template <typename Sig = function_sig<>, typename... Args>
function_arguments<Sig, Args...> function_args( Args&&... args ) {
    return function_arguments<Sig, Args...>(std::forward<Args>(args)...);
}

namespace stack {
template<typename... Sigs>
struct pusher<function_sig<Sigs...>> {
    template <typename... Sig, typename Fx, typename... Args>
    static void select_convertible(std::false_type, types<Sig...>, lua_State* L, Fx&& fx, Args&&... args) {
        typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
        std::unique_ptr<function_detail::base_function> sptr = std::make_unique<function_detail::functor_function<clean_fx>>(std::forward<Fx>(fx), std::forward<Args>(args)...);
        set_fx(L, std::move(sptr));
    }

    template <typename R, typename... A, typename Fx, typename... Args>
    static void select_convertible(std::true_type, types<R(A...)>, lua_State* L, Fx&& fx, Args&&... args) {
        using fx_ptr_t = R(*)(A...);
        fx_ptr_t fxptr = detail::unwrap(std::forward<Fx>(fx));
        select_function(std::true_type(), L, fxptr, std::forward<Args>(args)...);
    }

    template <typename R, typename... A, typename Fx, typename... Args>
    static void select_convertible(types<R(A...)> t, lua_State* L, Fx&& fx, Args&&... args) {
        typedef std::decay_t<meta::Unwrapped<meta::Unqualified<Fx>>> raw_fx_t;
        typedef R(* fx_ptr_t)(A...);
        typedef std::is_convertible<raw_fx_t, fx_ptr_t> is_convertible;
        select_convertible(is_convertible(), t, L, std::forward<Fx>(fx), std::forward<Args>(args)...);
    }

    template <typename Fx, typename... Args>
    static void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) {
        typedef meta::function_signature_t<meta::Unwrapped<meta::Unqualified<Fx>>> Sig;
        select_convertible(types<Sig>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
    }

    template <typename Fx, typename T, typename... Args>
    static void select_reference_member_variable(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
        typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
        std::unique_ptr<function_detail::base_function> sptr = std::make_unique<function_detail::member_variable<meta::Unqualified<T>, clean_fx>>(std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)... );
        set_fx(L, std::move(sptr));
    }

    template <typename Fx, typename T, typename... Args>
    static void select_reference_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
        typedef std::decay_t<Fx> dFx;
        dFx memfxptr(std::forward<Fx>(fx));
        auto userptr = detail::ptr(std::forward<T>(obj));
        lua_CFunction freefunc = &function_detail::upvalue_member_variable<std::decay_t<decltype(*userptr)>, meta::Unqualified<Fx>>::call;

        int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr);
        upvalues += stack::push(L, light_userdata_value(static_cast<void*>(userptr)));
        stack::push(L, c_closure(freefunc, upvalues));
    }

    template <typename Fx, typename... Args>
    static void select_member_variable(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
        select_convertible(types<Sigs...>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
    }

    template <typename Fx, typename T, typename... Args>
    static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
        typedef meta::Bool<meta::is_specialization_of<meta::Unqualified<T>, std::reference_wrapper>::value || std::is_pointer<T>::value> is_reference;
        select_reference_member_variable(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
    }

    template <typename Fx, typename... Args>
    static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) {
        typedef typename meta::bind_traits<meta::Unqualified<Fx>>::object_type C;
        lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx>::call;
        int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
        stack::push(L, c_closure(freefunc, upvalues));
    }

    template <typename Fx, typename T, typename... Args>
    static void select_reference_member_function(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
        typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
        std::unique_ptr<function_detail::base_function> sptr = std::make_unique<function_detail::member_function<meta::Unwrapped<meta::Unqualified<T>>, clean_fx>>(std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)... );
        set_fx(L, std::move(sptr));
    }

    template <typename Fx, typename T, typename... Args>
    static void select_reference_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
        typedef std::decay_t<Fx> dFx;
        dFx memfxptr(std::forward<Fx>(fx));
        auto userptr = detail::ptr(std::forward<T>(obj));
        lua_CFunction freefunc = &function_detail::upvalue_member_function<std::decay_t<decltype(*userptr)>, meta::Unqualified<Fx>>::call;

        int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr);
        upvalues += stack::push(L, light_userdata_value(static_cast<void*>(userptr)));
        stack::push(L, c_closure(freefunc, upvalues));
    }

    template <typename Fx, typename... Args>
    static void select_member_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
        select_member_variable(std::is_member_object_pointer<meta::Unqualified<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
    }

    template <typename Fx, typename T, typename... Args>
    static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
        typedef meta::Bool<meta::is_specialization_of<meta::Unqualified<T>, std::reference_wrapper>::value || std::is_pointer<T>::value> is_reference;
        select_reference_member_function(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
    }

    template <typename Fx, typename... Args>
    static void select_member_function(std::true_type, lua_State* L, Fx&& fx) {
        typedef typename meta::bind_traits<meta::Unqualified<Fx>>::object_type C;
        lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, Fx>::call;
        int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
        stack::push(L, c_closure(freefunc, upvalues));
    }

    template <typename Fx, typename... Args>
    static void select_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
        select_member_function(std::is_member_function_pointer<meta::Unqualified<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
    }

    template <typename Fx, typename... Args>
    static void select_function(std::true_type, lua_State* L, Fx&& fx, Args&&... args) {
        std::decay_t<Fx> target(std::forward<Fx>(fx), std::forward<Args>(args)...);
        lua_CFunction freefunc = &function_detail::upvalue_free_function<Fx>::call;

        int upvalues = stack::stack_detail::push_as_upvalues(L, target);
        stack::push(L, freefunc, upvalues);
    }

    static void select_function(std::true_type, lua_State* L, lua_CFunction f) {
        stack::push(L, f);
    }

    template <typename Fx, typename... Args>
    static void select(lua_State* L, Fx&& fx, Args&&... args) {
        select_function(std::is_function<meta::Unqualified<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
    }

    static void set_fx(lua_State* L, std::unique_ptr<function_detail::base_function> luafunc) {
        function_detail::base_function* target = luafunc.release();
        void* targetdata = static_cast<void*>(target);
        lua_CFunction freefunc = function_detail::call;

        stack::push(L, userdata_value(targetdata));
        function_detail::free_function_cleanup(L);
        lua_setmetatable(L, -2);
        stack::push(L, freefunc, 1);
    }

    template<typename... Args>
    static int push(lua_State* L, Args&&... args) {
        // Set will always place one thing (function) on the stack
        select(L, std::forward<Args>(args)...);
        return 1;
    }
};

template<typename T, typename... Args>
struct pusher<function_arguments<T, Args...>> {
    template <std::size_t... I, typename FP>
    static int push_func(std::index_sequence<I...>, lua_State* L, FP&& fp) {
        return stack::push<T>(L, detail::forward_get<I>(fp.params)...);
    }

    template <typename FP>
    static int push(lua_State* L, FP&& fp) {
        return push_func(std::index_sequence_for<Args...>(), L, std::forward<FP>(fp));
    }
};

template<typename Signature>
struct pusher<std::function<Signature>> {
    static int push(lua_State* L, std::function<Signature> fx) {
        return pusher<function_sig<>>{}.push(L, std::move(fx));
    }
};

template<typename... Functions>
struct pusher<overload_set<Functions...>> {
    static int push(lua_State* L, overload_set<Functions...>&& set) {
        pusher<function_sig<>>{}.set_fx(L, std::make_unique<function_detail::overloaded_function<Functions...>>(std::move(set.set)));
        return 1;
    }

    static int push(lua_State* L, const overload_set<Functions...>& set) {
        pusher<function_sig<>>{}.set_fx(L, std::make_unique<function_detail::overloaded_function<Functions...>>(set.set));
        return 1;
    }
};

} // stack
} // sol

#endif // SOL_FUNCTION_TYPES_HPP
<commit_msg>More unused parameters. .-.<commit_after>// The MIT License (MIT)

// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors

// 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.

#ifndef SOL_FUNCTION_TYPES_HPP
#define SOL_FUNCTION_TYPES_HPP

#include "function_types_core.hpp"
#include "function_types_templated.hpp"
#include "function_types_basic.hpp"
#include "function_types_allocator.hpp"
#include "function_types_member.hpp"
#include "function_types_usertype.hpp"
#include "function_types_overload.hpp"
#include "function_types_allocator.hpp"
#include "resolve.hpp"

namespace sol {

template <typename Sig, typename... Ps>
struct function_arguments {
    std::tuple<Ps...> params;
    template <typename... Args>
    function_arguments(Args&&... args) : params(std::forward<Args>(args)...) {}
};

template <typename Sig = function_sig<>, typename... Args>
function_arguments<Sig, Args...> function_args( Args&&... args ) {
    return function_arguments<Sig, Args...>(std::forward<Args>(args)...);
}

namespace stack {
template<typename... Sigs>
struct pusher<function_sig<Sigs...>> {
    template <typename... Sig, typename Fx, typename... Args>
    static void select_convertible(std::false_type, types<Sig...>, lua_State* L, Fx&& fx, Args&&... args) {
        typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
        std::unique_ptr<function_detail::base_function> sptr = std::make_unique<function_detail::functor_function<clean_fx>>(std::forward<Fx>(fx), std::forward<Args>(args)...);
        set_fx(L, std::move(sptr));
    }

    template <typename R, typename... A, typename Fx, typename... Args>
    static void select_convertible(std::true_type, types<R(A...)>, lua_State* L, Fx&& fx, Args&&... args) {
        using fx_ptr_t = R(*)(A...);
        fx_ptr_t fxptr = detail::unwrap(std::forward<Fx>(fx));
        select_function(std::true_type(), L, fxptr, std::forward<Args>(args)...);
    }

    template <typename R, typename... A, typename Fx, typename... Args>
    static void select_convertible(types<R(A...)> t, lua_State* L, Fx&& fx, Args&&... args) {
        typedef std::decay_t<meta::Unwrapped<meta::Unqualified<Fx>>> raw_fx_t;
        typedef R(* fx_ptr_t)(A...);
        typedef std::is_convertible<raw_fx_t, fx_ptr_t> is_convertible;
        select_convertible(is_convertible(), t, L, std::forward<Fx>(fx), std::forward<Args>(args)...);
    }

    template <typename Fx, typename... Args>
    static void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) {
        typedef meta::function_signature_t<meta::Unwrapped<meta::Unqualified<Fx>>> Sig;
        select_convertible(types<Sig>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
    }

    template <typename Fx, typename T, typename... Args>
    static void select_reference_member_variable(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
        typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
        std::unique_ptr<function_detail::base_function> sptr = std::make_unique<function_detail::member_variable<meta::Unqualified<T>, clean_fx>>(std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)... );
        set_fx(L, std::move(sptr));
    }

    template <typename Fx, typename T, typename... Args>
    static void select_reference_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
        typedef std::decay_t<Fx> dFx;
        dFx memfxptr(std::forward<Fx>(fx));
        auto userptr = detail::ptr(std::forward<T>(obj), std::forward<Args>(args)...);
        lua_CFunction freefunc = &function_detail::upvalue_member_variable<std::decay_t<decltype(*userptr)>, meta::Unqualified<Fx>>::call;

        int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr);
        upvalues += stack::push(L, light_userdata_value(static_cast<void*>(userptr)));
        stack::push(L, c_closure(freefunc, upvalues));
    }

    template <typename Fx, typename... Args>
    static void select_member_variable(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
        select_convertible(types<Sigs...>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
    }

    template <typename Fx, typename T, typename... Args>
    static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
        typedef meta::Bool<meta::is_specialization_of<meta::Unqualified<T>, std::reference_wrapper>::value || std::is_pointer<T>::value> is_reference;
        select_reference_member_variable(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
    }

    template <typename Fx, typename... Args>
    static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) {
        typedef typename meta::bind_traits<meta::Unqualified<Fx>>::object_type C;
        lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx>::call;
        int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
        stack::push(L, c_closure(freefunc, upvalues));
    }

    template <typename Fx, typename T, typename... Args>
    static void select_reference_member_function(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
        typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx;
        std::unique_ptr<function_detail::base_function> sptr = std::make_unique<function_detail::member_function<meta::Unwrapped<meta::Unqualified<T>>, clean_fx>>(std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)... );
        set_fx(L, std::move(sptr));
    }

    template <typename Fx, typename T, typename... Args>
    static void select_reference_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
        typedef std::decay_t<Fx> dFx;
        dFx memfxptr(std::forward<Fx>(fx));
        auto userptr = detail::ptr(std::forward<T>(obj));
        lua_CFunction freefunc = &function_detail::upvalue_member_function<std::decay_t<decltype(*userptr)>, meta::Unqualified<Fx>>::call;

        int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr);
        upvalues += stack::push(L, light_userdata_value(static_cast<void*>(userptr)));
        stack::push(L, c_closure(freefunc, upvalues));
    }

    template <typename Fx, typename... Args>
    static void select_member_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
        select_member_variable(std::is_member_object_pointer<meta::Unqualified<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
    }

    template <typename Fx, typename T, typename... Args>
    static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
        typedef meta::Bool<meta::is_specialization_of<meta::Unqualified<T>, std::reference_wrapper>::value || std::is_pointer<T>::value> is_reference;
        select_reference_member_function(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
    }

    template <typename Fx, typename... Args>
    static void select_member_function(std::true_type, lua_State* L, Fx&& fx) {
        typedef typename meta::bind_traits<meta::Unqualified<Fx>>::object_type C;
        lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, Fx>::call;
        int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
        stack::push(L, c_closure(freefunc, upvalues));
    }

    template <typename Fx, typename... Args>
    static void select_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) {
        select_member_function(std::is_member_function_pointer<meta::Unqualified<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
    }

    template <typename Fx, typename... Args>
    static void select_function(std::true_type, lua_State* L, Fx&& fx, Args&&... args) {
        std::decay_t<Fx> target(std::forward<Fx>(fx), std::forward<Args>(args)...);
        lua_CFunction freefunc = &function_detail::upvalue_free_function<Fx>::call;

        int upvalues = stack::stack_detail::push_as_upvalues(L, target);
        stack::push(L, freefunc, upvalues);
    }

    static void select_function(std::true_type, lua_State* L, lua_CFunction f) {
        stack::push(L, f);
    }

    template <typename Fx, typename... Args>
    static void select(lua_State* L, Fx&& fx, Args&&... args) {
        select_function(std::is_function<meta::Unqualified<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
    }

    static void set_fx(lua_State* L, std::unique_ptr<function_detail::base_function> luafunc) {
        function_detail::base_function* target = luafunc.release();
        void* targetdata = static_cast<void*>(target);
        lua_CFunction freefunc = function_detail::call;

        stack::push(L, userdata_value(targetdata));
        function_detail::free_function_cleanup(L);
        lua_setmetatable(L, -2);
        stack::push(L, freefunc, 1);
    }

    template<typename... Args>
    static int push(lua_State* L, Args&&... args) {
        // Set will always place one thing (function) on the stack
        select(L, std::forward<Args>(args)...);
        return 1;
    }
};

template<typename T, typename... Args>
struct pusher<function_arguments<T, Args...>> {
    template <std::size_t... I, typename FP>
    static int push_func(std::index_sequence<I...>, lua_State* L, FP&& fp) {
        return stack::push<T>(L, detail::forward_get<I>(fp.params)...);
    }

    template <typename FP>
    static int push(lua_State* L, FP&& fp) {
        return push_func(std::index_sequence_for<Args...>(), L, std::forward<FP>(fp));
    }
};

template<typename Signature>
struct pusher<std::function<Signature>> {
    static int push(lua_State* L, std::function<Signature> fx) {
        return pusher<function_sig<>>{}.push(L, std::move(fx));
    }
};

template<typename... Functions>
struct pusher<overload_set<Functions...>> {
    static int push(lua_State* L, overload_set<Functions...>&& set) {
        pusher<function_sig<>>{}.set_fx(L, std::make_unique<function_detail::overloaded_function<Functions...>>(std::move(set.set)));
        return 1;
    }

    static int push(lua_State* L, const overload_set<Functions...>& set) {
        pusher<function_sig<>>{}.set_fx(L, std::make_unique<function_detail::overloaded_function<Functions...>>(set.set));
        return 1;
    }
};

} // stack
} // sol

#endif // SOL_FUNCTION_TYPES_HPP
<|endoftext|>


<commit_before>/*
 * Copyright 2015 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "FiberManagerMap.h"

#include <cassert>
#include <memory>
#include <unordered_map>

#include <folly/ThreadLocal.h>

namespace folly { namespace fibers {

namespace {

// Leak these intentionally.  During shutdown, we may call getFiberManager, and
// want access to the fiber managers during that time.
class LocalFiberManagerMapTag;
typedef folly::ThreadLocal<
    std::unordered_map<folly::EventBase*, FiberManager*>,
    LocalFiberManagerMapTag>
  LocalMapType;
LocalMapType* localFiberManagerMap() {
  static auto ret = new LocalMapType();
  return ret;
}

typedef
  std::unordered_map<folly::EventBase*, std::unique_ptr<FiberManager>>
  MapType;
MapType* fiberManagerMap() {
  static auto ret = new MapType();
  return ret;
}

std::mutex* fiberManagerMapMutex() {
  static auto ret = new std::mutex();
  return ret;
}

class OnEventBaseDestructionCallback : public folly::EventBase::LoopCallback {
 public:
  explicit OnEventBaseDestructionCallback(folly::EventBase& evb)
           : evb_(&evb) {}
  void runLoopCallback() noexcept override {
    for (auto& localMap : localFiberManagerMap()->accessAllThreads()) {
      localMap.erase(evb_);
    }
    std::unique_ptr<FiberManager> fm;
    {
      std::lock_guard<std::mutex> lg(*fiberManagerMapMutex());
      auto it = fiberManagerMap()->find(evb_);
      assert(it != fiberManagerMap()->end());
      fm = std::move(it->second);
      fiberManagerMap()->erase(it);
    }
    assert(fm.get() != nullptr);
    fm->loopUntilNoReady();
    delete this;
  }
 private:
  folly::EventBase* evb_;
};

FiberManager* getFiberManagerThreadSafe(folly::EventBase& evb,
                                        const FiberManager::Options& opts) {
  std::lock_guard<std::mutex> lg(*fiberManagerMapMutex());

  auto it = fiberManagerMap()->find(&evb);
  if (LIKELY(it != fiberManagerMap()->end())) {
    return it->second.get();
  }

  auto loopController = folly::make_unique<EventBaseLoopController>();
  loopController->attachEventBase(evb);
  auto fiberManager =
      folly::make_unique<FiberManager>(std::move(loopController), opts);
  auto result = fiberManagerMap()->emplace(&evb, std::move(fiberManager));
  evb.runOnDestruction(new OnEventBaseDestructionCallback(evb));
  return result.first->second.get();
}

} // namespace

FiberManager& getFiberManager(folly::EventBase& evb,
                              const FiberManager::Options& opts) {
  auto it = (*localFiberManagerMap())->find(&evb);
  if (LIKELY(it != (*localFiberManagerMap())->end())) {
    return *(it->second);
  }

  auto fm = getFiberManagerThreadSafe(evb, opts);
  (*localFiberManagerMap())->emplace(&evb, fm);
  return *fm;
}

}}
<commit_msg>Fix EventBase destruction race in FiberManagerMap<commit_after>/*
 * Copyright 2015 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "FiberManagerMap.h"

#include <memory>
#include <unordered_map>

#include <folly/AtomicLinkedList.h>
#include <folly/ThreadLocal.h>
#include <folly/Synchronized.h>

namespace folly { namespace fibers {

namespace {

class EventBaseOnDestructionCallback : public EventBase::LoopCallback {
 public:
  explicit EventBaseOnDestructionCallback(EventBase& evb) : evb_(evb) {}
  void runLoopCallback() noexcept override;

 private:
  EventBase& evb_;
};

class GlobalCache {
 public:
  static FiberManager& get(EventBase& evb, const FiberManager::Options& opts) {
    return instance().getImpl(evb, opts);
  }

  static std::unique_ptr<FiberManager> erase(EventBase& evb) {
    return instance().eraseImpl(evb);
  }

 private:
  GlobalCache() {}

  // Leak this intentionally. During shutdown, we may call getFiberManager,
  // and want access to the fiber managers during that time.
  static GlobalCache& instance() {
    static auto ret = new GlobalCache();
    return *ret;
  }

  FiberManager& getImpl(EventBase& evb, const FiberManager::Options& opts) {
    std::lock_guard<std::mutex> lg(mutex_);

    auto& fmPtrRef = map_[&evb];

    if (!fmPtrRef) {
      auto loopController = make_unique<EventBaseLoopController>();
      loopController->attachEventBase(evb);
      evb.runOnDestruction(new EventBaseOnDestructionCallback(evb));

      fmPtrRef = make_unique<FiberManager>(std::move(loopController), opts);
    }

    return *fmPtrRef;
  }

  std::unique_ptr<FiberManager> eraseImpl(EventBase& evb) {
    std::lock_guard<std::mutex> lg(mutex_);

    DCHECK_EQ(1, map_.count(&evb));

    auto ret = std::move(map_[&evb]);
    map_.erase(&evb);
    return ret;
  }

  std::mutex mutex_;
  std::unordered_map<EventBase*, std::unique_ptr<FiberManager>> map_;
};

constexpr size_t kEraseListMaxSize = 64;

class ThreadLocalCache {
 public:
  static FiberManager& get(EventBase& evb, const FiberManager::Options& opts) {
    return instance()->getImpl(evb, opts);
  }

  static void erase(EventBase& evb) {
    for (auto& localInstance : instance().accessAllThreads()) {
      SYNCHRONIZED(info, localInstance.eraseInfo_) {
        if (info.eraseList.size() >= kEraseListMaxSize) {
          info.eraseAll = true;
        } else {
          info.eraseList.push_back(&evb);
        }
        localInstance.eraseRequested_ = true;
      }
    }
  }

 private:
  ThreadLocalCache() {}

  struct ThreadLocalCacheTag {};
  using ThreadThreadLocalCache = ThreadLocal<ThreadLocalCache, ThreadLocalCacheTag>;

  // Leak this intentionally. During shutdown, we may call getFiberManager,
  // and want access to the fiber managers during that time.
  static ThreadThreadLocalCache& instance() {
    static auto ret = new ThreadThreadLocalCache([]() { return new ThreadLocalCache(); });
    return *ret;
  }

  FiberManager& getImpl(EventBase& evb, const FiberManager::Options& opts) {
    eraseImpl();

    auto& fmPtrRef = map_[&evb];
    if (!fmPtrRef) {
      fmPtrRef = &GlobalCache::get(evb, opts);
    }

    DCHECK(fmPtrRef != nullptr);

    return *fmPtrRef;
  }

  void eraseImpl() {
    if (!eraseRequested_.load()) {
      return;
    }

    SYNCHRONIZED(info, eraseInfo_) {
      if (info.eraseAll) {
        map_.clear();
      } else {
        for (auto evbPtr : info.eraseList) {
          map_.erase(evbPtr);
        }
      }

      info.eraseList.clear();
      info.eraseAll = false;
      eraseRequested_ = false;
    }
  }

  std::unordered_map<EventBase*, FiberManager*> map_;
  std::atomic<bool> eraseRequested_{false};

  struct EraseInfo {
    bool eraseAll{false};
    std::vector<EventBase*> eraseList;
  };

  folly::Synchronized<EraseInfo> eraseInfo_;
};

void EventBaseOnDestructionCallback::runLoopCallback() noexcept {
  auto fm = GlobalCache::erase(evb_);
  DCHECK(fm.get() != nullptr);
  ThreadLocalCache::erase(evb_);

  fm->loopUntilNoReady();

  delete this;
}

} // namespace

FiberManager& getFiberManager(EventBase& evb,
                              const FiberManager::Options& opts) {
  return ThreadLocalCache::get(evb, opts);
}

}}
<|endoftext|>


<commit_before>#include "FiltersWindow.hpp"

#include <Engine/Hymn.hpp>
#include <imgui.h>

using namespace GUI;

void FiltersWindow::Show() {
    // Configure filters.
    if (ImGui::Begin("Filters", &visible, ImGuiWindowFlags_ShowBorders)) {
        // Color
        if (ImGui::CollapsingHeader("Color")) {
            ImGui::Checkbox("Enable##Color", &Hymn().filterSettings.color);

            if (Hymn().filterSettings.color) {
                ImGui::ColorEdit3("Color##Color", &Hymn().filterSettings.colorColor[0]);
            }
        }

        // Fog
        if (ImGui::CollapsingHeader("Fog")) {
            ImGui::Checkbox("Enable##Fog", &Hymn().filterSettings.fog);

            if (Hymn().filterSettings.fog) {
                ImGui::InputFloat("Density", &Hymn().filterSettings.fogDensity);
                ImGui::ColorEdit3("Color##Fog", &Hymn().filterSettings.fogColor[0]);
            }
        }

        // FXAA
        if (ImGui::CollapsingHeader("FXAA")) {
            ImGui::Checkbox("Enable##FXAA", &Hymn().filterSettings.fxaa);
        }

        // Glow
        if (ImGui::CollapsingHeader("Glow")) {
            ImGui::Checkbox("Enable##Glow", &Hymn().filterSettings.glow);

            if (Hymn().filterSettings.glow) {
                ImGui::InputInt("Blur amount", &Hymn().filterSettings.glowBlurAmount);
            }
        }
    }
    ImGui::End();
}

bool FiltersWindow::IsVisible() const {
    return visible;
}

void FiltersWindow::SetVisible(bool visible) {
    this->visible = visible;
}
<commit_msg>Texts explaining the different filters<commit_after>#include "FiltersWindow.hpp"

#include <Engine/Hymn.hpp>
#include <imgui.h>

using namespace GUI;

void FiltersWindow::Show() {
    // Configure filters.
    if (ImGui::Begin("Filters", &visible, ImGuiWindowFlags_ShowBorders)) {
        // Color
        if (ImGui::CollapsingHeader("Color")) {
            ImGui::TextWrapped("Color blending filter.");

            ImGui::Checkbox("Enable##Color", &Hymn().filterSettings.color);

            if (Hymn().filterSettings.color) {
                ImGui::ColorEdit3("Color##Color", &Hymn().filterSettings.colorColor[0]);
            }
        }

        // Fog
        if (ImGui::CollapsingHeader("Fog")) {
            ImGui::TextWrapped("Screen-space fog based on the depth buffer.");

            ImGui::Checkbox("Enable##Fog", &Hymn().filterSettings.fog);

            if (Hymn().filterSettings.fog) {
                ImGui::InputFloat("Density", &Hymn().filterSettings.fogDensity);
                ImGui::ColorEdit3("Color##Fog", &Hymn().filterSettings.fogColor[0]);
            }
        }

        // FXAA
        if (ImGui::CollapsingHeader("FXAA")) {
            ImGui::TextWrapped("Cheap anti-aliasing.");

            ImGui::Checkbox("Enable##FXAA", &Hymn().filterSettings.fxaa);
        }

        // Glow
        if (ImGui::CollapsingHeader("Glow")) {
            ImGui::TextWrapped("Blur the glow buffer and render it using additive blending.");

            ImGui::Checkbox("Enable##Glow", &Hymn().filterSettings.glow);

            if (Hymn().filterSettings.glow) {
                ImGui::InputInt("Blur amount", &Hymn().filterSettings.glowBlurAmount);
            }
        }
    }
    ImGui::End();
}

bool FiltersWindow::IsVisible() const {
    return visible;
}

void FiltersWindow::SetVisible(bool visible) {
    this->visible = visible;
}
<|endoftext|>


<commit_before>#include "WMSTimeDimension.h"
#include <boost/algorithm/string/join.hpp>
#include <macgyver/StringConversion.h>
#include <macgyver/TimeParser.h>

namespace SmartMet
{
namespace Plugin
{
namespace WMS
{
namespace
{
boost::posix_time::ptime parse_time(const std::string& time_string)
{
  if (time_string == "now")
    return boost::posix_time::second_clock::universal_time();

  return Fmi::TimeParser::parse(time_string);
}
}  // namespace

void WMSTimeDimension::addTimestep(const boost::posix_time::ptime& timestep)
{
  try
  {
    itsTimesteps.insert(timestep);
  }
  catch (...)
  {
    throw Spine::Exception::Trace(BCP, "Failed to add time step!");
  }
}

void WMSTimeDimension::removeTimestep(const boost::posix_time::ptime& timestep)
{
  try
  {
    itsTimesteps.erase(timestep);
  }
  catch (...)
  {
    throw Spine::Exception::Trace(BCP, "Failed to remove time step!");
  }
}

bool WMSTimeDimension::isValidTime(const boost::posix_time::ptime& theTime) const
{
  // Allow any time within the range

  if (itsTimesteps.empty())
    return false;

  return (theTime >= *itsTimesteps.cbegin() && theTime <= *itsTimesteps.crbegin());

#if 0
  // Allow only listed times
  try
  {
    auto res = itsTimesteps.find(theTime);

    if (res == itsTimesteps.end())
    {
      return false;
    }
    else
    {
      return true;
    }
  }
  catch (...)
  {
    throw Spine::Exception::Trace(BCP, "Failed to validate time!");
  }
#endif
}

std::set<boost::posix_time::ptime> WMSTimeDimension::getTimeSteps() const
{
  return itsTimesteps;
}
boost::posix_time::ptime WMSTimeDimension::mostCurrentTime() const
{
  try
  {
    if (itsTimesteps.size() == 0)
      return boost::posix_time::not_a_date_time;

    boost::posix_time::ptime current_time = boost::posix_time::second_clock::universal_time();

    // if current time is earlier than first timestep -> return first timestep
    if (current_time <= *(itsTimesteps.begin()))
      return *(itsTimesteps.begin());

    auto itLastTimestep = itsTimesteps.end();
    itLastTimestep--;
    // if current time is later than last timestep -> return last timestep
    if (current_time >= *itLastTimestep)
      return *itLastTimestep;

    // otherwise iterate timesteps ans find the closest one
    auto itPrevious = itsTimesteps.begin();
    for (auto it = itsTimesteps.begin(); it != itsTimesteps.end(); ++it)
    {
      if (*it >= current_time)
      {
        // perfect match: current timestep is equal to current time
        if (*it == current_time)
          return *it;

        // check which is closer to current time: current timestep or previous timestep
        boost::posix_time::time_duration duration_tonext(*it - current_time);
        boost::posix_time::time_duration duration_toprevious(current_time - *itPrevious);

        if (duration_toprevious.total_seconds() <= duration_tonext.total_seconds())
          return *itPrevious;
        else
          return *it;
      }

      itPrevious = it;
    }

    return boost::posix_time::not_a_date_time;
  }
  catch (...)
  {
    throw Spine::Exception::Trace(BCP, "Failed to establish most current time!");
  }
}

std::string StepTimeDimension::getCapabilities(const boost::optional<std::string>& starttime,
                                               const boost::optional<std::string>& endtime) const
{
  try
  {
    std::ostringstream os;

    std::vector<std::string> ret;
    ret.reserve(itsTimesteps.size());

    boost::posix_time::ptime startt =
        (starttime ? parse_time(*starttime) : boost::posix_time::min_date_time);
    boost::posix_time::ptime endt =
        (endtime ? parse_time(*endtime) : boost::posix_time::max_date_time);

    for (auto& step : itsTimesteps)
    {
      if (step >= startt && step <= endt)
        ret.push_back(Fmi::to_iso_extended_string(step) + "Z");
      if (step > endt)
        break;
    }

    return boost::algorithm::join(ret, ",");
  }
  catch (...)
  {
    throw Spine::Exception::Trace(BCP, "Failed to extract time dimension capabilities!");
  }
}

IntervalTimeDimension::IntervalTimeDimension(const boost::posix_time::ptime& begin,
                                             const boost::posix_time::ptime& end,
                                             const boost::posix_time::time_duration& step)
    : itsInterval(begin, end, step)
{
}

boost::posix_time::ptime IntervalTimeDimension::mostCurrentTime() const
{
  return itsInterval.endTime;
}

bool IntervalTimeDimension::isValidTime(const boost::posix_time::ptime& theTime) const
{
  return (theTime >= itsInterval.startTime && theTime <= itsInterval.endTime);
}

IntervalTimeDimension::tag_interval IntervalTimeDimension::getInterval() const
{
  return itsInterval;
}

std::string IntervalTimeDimension::getCapabilities(
    const boost::optional<std::string>& starttime,
    const boost::optional<std::string>& endtime) const
{
  try
  {
    if ((starttime && endtime) && parse_time(*starttime) > parse_time(*endtime))
      throw Spine::Exception::Trace(BCP,
                                    "Requested starttime must be earlier than requested endtime!");

    boost::posix_time::ptime startt = itsInterval.startTime;
    boost::posix_time::ptime endt = itsInterval.endTime;
    boost::posix_time::ptime requested_startt =
        (starttime ? parse_time(*starttime) : itsInterval.startTime);
    boost::posix_time::ptime requested_endt =
        (endtime ? parse_time(*endtime) : itsInterval.endTime);

    if (requested_startt > endt || requested_endt < startt)
      return "";

    if (startt < requested_startt)
    {
      startt = boost::posix_time::ptime(requested_startt.date(), startt.time_of_day());
      boost::posix_time::time_duration resolution =
          (itsInterval.resolution.total_seconds() == 0 ? boost::posix_time::minutes(1)
                                                       : itsInterval.resolution);
      if (startt < requested_startt)
      {
        while (startt < requested_startt)
          startt += resolution;
      }
      else if (startt > requested_startt)
      {
        while (startt - resolution >= requested_startt)
          startt -= resolution;
      }
    }

    if (requested_endt < endt)
    {
      endt = requested_endt;
    }

    std::ostringstream os;

    os << Fmi::to_iso_extended_string(startt) << "Z/" << Fmi::to_iso_extended_string(endt)
       << "Z/PT";
    if (itsInterval.resolution.hours() == 0 && itsInterval.resolution.minutes() <= 60)
      os << itsInterval.resolution.minutes() << "M";
    else
    {
      os << itsInterval.resolution.hours() << "H";
      if (itsInterval.resolution.minutes() > 0)
        os << itsInterval.resolution.minutes() << "M";
    }

    return os.str();
  }
  catch (...)
  {
    throw Spine::Exception::Trace(BCP, "Failed to generate time dimension capabilities!");
  }
}

std::ostream& operator<<(std::ostream& ost, const StepTimeDimension& timeDimension)
{
  try
  {
    auto timesteps = timeDimension.getTimeSteps();

    for (auto& step : timesteps)
    {
      ost << step << " ";
    }

    ost << std::endl;

    return ost;
  }
  catch (...)
  {
    throw Spine::Exception::Trace(BCP, "Failed to print step time dimension data!");
  }
}

std::ostream& operator<<(std::ostream& ost, const IntervalTimeDimension& timeDimension)
{
  try
  {
    auto interval = timeDimension.getInterval();
    ost << interval.startTime << " - " << interval.endTime << " : " << interval.resolution << " ";
    ost << std::endl;

    return ost;
  }
  catch (...)
  {
    throw Spine::Exception::Trace(BCP, "Failed to print time dimension data!");
  }
}

}  // namespace WMS
}  // namespace Plugin
}  // namespace SmartMet
<commit_msg>Removed unnecessary ostringstream object<commit_after>#include "WMSTimeDimension.h"
#include <boost/algorithm/string/join.hpp>
#include <macgyver/StringConversion.h>
#include <macgyver/TimeParser.h>

namespace SmartMet
{
namespace Plugin
{
namespace WMS
{
namespace
{
boost::posix_time::ptime parse_time(const std::string& time_string)
{
  if (time_string == "now")
    return boost::posix_time::second_clock::universal_time();

  return Fmi::TimeParser::parse(time_string);
}
}  // namespace

void WMSTimeDimension::addTimestep(const boost::posix_time::ptime& timestep)
{
  try
  {
    itsTimesteps.insert(timestep);
  }
  catch (...)
  {
    throw Spine::Exception::Trace(BCP, "Failed to add time step!");
  }
}

void WMSTimeDimension::removeTimestep(const boost::posix_time::ptime& timestep)
{
  try
  {
    itsTimesteps.erase(timestep);
  }
  catch (...)
  {
    throw Spine::Exception::Trace(BCP, "Failed to remove time step!");
  }
}

bool WMSTimeDimension::isValidTime(const boost::posix_time::ptime& theTime) const
{
  // Allow any time within the range

  if (itsTimesteps.empty())
    return false;

  return (theTime >= *itsTimesteps.cbegin() && theTime <= *itsTimesteps.crbegin());

#if 0
  // Allow only listed times
  try
  {
    auto res = itsTimesteps.find(theTime);

    if (res == itsTimesteps.end())
    {
      return false;
    }
    else
    {
      return true;
    }
  }
  catch (...)
  {
    throw Spine::Exception::Trace(BCP, "Failed to validate time!");
  }
#endif
}

std::set<boost::posix_time::ptime> WMSTimeDimension::getTimeSteps() const
{
  return itsTimesteps;
}
boost::posix_time::ptime WMSTimeDimension::mostCurrentTime() const
{
  try
  {
    if (itsTimesteps.size() == 0)
      return boost::posix_time::not_a_date_time;

    boost::posix_time::ptime current_time = boost::posix_time::second_clock::universal_time();

    // if current time is earlier than first timestep -> return first timestep
    if (current_time <= *(itsTimesteps.begin()))
      return *(itsTimesteps.begin());

    auto itLastTimestep = itsTimesteps.end();
    itLastTimestep--;
    // if current time is later than last timestep -> return last timestep
    if (current_time >= *itLastTimestep)
      return *itLastTimestep;

    // otherwise iterate timesteps ans find the closest one
    auto itPrevious = itsTimesteps.begin();
    for (auto it = itsTimesteps.begin(); it != itsTimesteps.end(); ++it)
    {
      if (*it >= current_time)
      {
        // perfect match: current timestep is equal to current time
        if (*it == current_time)
          return *it;

        // check which is closer to current time: current timestep or previous timestep
        boost::posix_time::time_duration duration_tonext(*it - current_time);
        boost::posix_time::time_duration duration_toprevious(current_time - *itPrevious);

        if (duration_toprevious.total_seconds() <= duration_tonext.total_seconds())
          return *itPrevious;
        else
          return *it;
      }

      itPrevious = it;
    }

    return boost::posix_time::not_a_date_time;
  }
  catch (...)
  {
    throw Spine::Exception::Trace(BCP, "Failed to establish most current time!");
  }
}

std::string StepTimeDimension::getCapabilities(const boost::optional<std::string>& starttime,
                                               const boost::optional<std::string>& endtime) const
{
  try
  {
    std::vector<std::string> ret;
    ret.reserve(itsTimesteps.size());

    boost::posix_time::ptime startt =
        (starttime ? parse_time(*starttime) : boost::posix_time::min_date_time);
    boost::posix_time::ptime endt =
        (endtime ? parse_time(*endtime) : boost::posix_time::max_date_time);

    for (auto& step : itsTimesteps)
    {
      if (step >= startt && step <= endt)
        ret.push_back(Fmi::to_iso_extended_string(step) + "Z");
      if (step > endt)
        break;
    }

    return boost::algorithm::join(ret, ",");
  }
  catch (...)
  {
    throw Spine::Exception::Trace(BCP, "Failed to extract time dimension capabilities!");
  }
}

IntervalTimeDimension::IntervalTimeDimension(const boost::posix_time::ptime& begin,
                                             const boost::posix_time::ptime& end,
                                             const boost::posix_time::time_duration& step)
    : itsInterval(begin, end, step)
{
}

boost::posix_time::ptime IntervalTimeDimension::mostCurrentTime() const
{
  return itsInterval.endTime;
}

bool IntervalTimeDimension::isValidTime(const boost::posix_time::ptime& theTime) const
{
  return (theTime >= itsInterval.startTime && theTime <= itsInterval.endTime);
}

IntervalTimeDimension::tag_interval IntervalTimeDimension::getInterval() const
{
  return itsInterval;
}

std::string IntervalTimeDimension::getCapabilities(
    const boost::optional<std::string>& starttime,
    const boost::optional<std::string>& endtime) const
{
  try
  {
    if ((starttime && endtime) && parse_time(*starttime) > parse_time(*endtime))
      throw Spine::Exception::Trace(BCP,
                                    "Requested starttime must be earlier than requested endtime!");

    boost::posix_time::ptime startt = itsInterval.startTime;
    boost::posix_time::ptime endt = itsInterval.endTime;
    boost::posix_time::ptime requested_startt =
        (starttime ? parse_time(*starttime) : itsInterval.startTime);
    boost::posix_time::ptime requested_endt =
        (endtime ? parse_time(*endtime) : itsInterval.endTime);

    if (requested_startt > endt || requested_endt < startt)
      return "";

    if (startt < requested_startt)
    {
      startt = boost::posix_time::ptime(requested_startt.date(), startt.time_of_day());
      boost::posix_time::time_duration resolution =
          (itsInterval.resolution.total_seconds() == 0 ? boost::posix_time::minutes(1)
                                                       : itsInterval.resolution);
      if (startt < requested_startt)
      {
        while (startt < requested_startt)
          startt += resolution;
      }
      else if (startt > requested_startt)
      {
        while (startt - resolution >= requested_startt)
          startt -= resolution;
      }
    }

    if (requested_endt < endt)
    {
      endt = requested_endt;
    }

    std::ostringstream os;

    os << Fmi::to_iso_extended_string(startt) << "Z/" << Fmi::to_iso_extended_string(endt)
       << "Z/PT";
    if (itsInterval.resolution.hours() == 0 && itsInterval.resolution.minutes() <= 60)
      os << itsInterval.resolution.minutes() << "M";
    else
    {
      os << itsInterval.resolution.hours() << "H";
      if (itsInterval.resolution.minutes() > 0)
        os << itsInterval.resolution.minutes() << "M";
    }

    return os.str();
  }
  catch (...)
  {
    throw Spine::Exception::Trace(BCP, "Failed to generate time dimension capabilities!");
  }
}

std::ostream& operator<<(std::ostream& ost, const StepTimeDimension& timeDimension)
{
  try
  {
    auto timesteps = timeDimension.getTimeSteps();

    for (auto& step : timesteps)
    {
      ost << step << " ";
    }

    ost << std::endl;

    return ost;
  }
  catch (...)
  {
    throw Spine::Exception::Trace(BCP, "Failed to print step time dimension data!");
  }
}

std::ostream& operator<<(std::ostream& ost, const IntervalTimeDimension& timeDimension)
{
  try
  {
    auto interval = timeDimension.getInterval();
    ost << interval.startTime << " - " << interval.endTime << " : " << interval.resolution << " ";
    ost << std::endl;

    return ost;
  }
  catch (...)
  {
    throw Spine::Exception::Trace(BCP, "Failed to print time dimension data!");
  }
}

}  // namespace WMS
}  // namespace Plugin
}  // namespace SmartMet
<|endoftext|>


<commit_before>#pragma once

namespace GUI {
    /// A window where filters is configured.
    class FiltersWindow {
        public:
            /// Show the window
            void Show();

            /// Get whether the window is visible.
            /**
             * @return Whether the window is visible.
             */
            bool IsVisible() const;

            /// Set whether the window should be visible.
            /**
             * @param visible Whether the window should be visible.
             */
            void SetVisible(bool visible);

        private:
            bool visible = false;
    };
}
<commit_msg>Fix grammar error<commit_after>#pragma once

namespace GUI {
    /// A window where filters are configured.
    class FiltersWindow {
        public:
            /// Show the window
            void Show();

            /// Get whether the window is visible.
            /**
             * @return Whether the window is visible.
             */
            bool IsVisible() const;

            /// Set whether the window should be visible.
            /**
             * @param visible Whether the window should be visible.
             */
            void SetVisible(bool visible);

        private:
            bool visible = false;
    };
}
<|endoftext|>


<commit_before>#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0601

#undef WINVER
#define WINVER 0x0601

#define SPACE_SCAN_CODE 0x0039

#include "keyboard-layout-manager.h"

#include <string>
#include <cctype>
#include <windows.h>

using namespace v8;

std::string ToUTF8(const std::wstring& string) {
  if (string.length() < 1) {
    return std::string();
  }

  // NB: In the pathological case, each character could expand up
  // to 4 bytes in UTF8.
  int cbLen = (string.length()+1) * sizeof(char) * 4;
  char* buf = new char[cbLen];
  int retLen = WideCharToMultiByte(CP_UTF8, 0, string.c_str(), string.length(), buf, cbLen, NULL, NULL);
  buf[retLen] = 0;

  std::string ret;
  ret.assign(buf);
  return ret;
}

void KeyboardLayoutManager::Init(Handle<Object> exports, Handle<Object> module) {
  Nan::HandleScope scope;
  Local<FunctionTemplate> newTemplate = Nan::New<FunctionTemplate>(KeyboardLayoutManager::New);
  newTemplate->SetClassName(Nan::New<String>("KeyboardLayoutManager").ToLocalChecked());
  newTemplate->InstanceTemplate()->SetInternalFieldCount(1);
  Local<ObjectTemplate> proto = newTemplate->PrototypeTemplate();

  Nan::SetMethod(proto, "getCurrentKeyboardLayout", KeyboardLayoutManager::GetCurrentKeyboardLayout);
  Nan::SetMethod(proto, "getCurrentKeyboardLanguage", KeyboardLayoutManager::GetCurrentKeyboardLanguage);
  Nan::SetMethod(proto, "getInstalledKeyboardLanguages", KeyboardLayoutManager::GetInstalledKeyboardLanguages);
  Nan::SetMethod(proto, "getCurrentKeymap", KeyboardLayoutManager::GetCurrentKeymap);

  module->Set(Nan::New("exports").ToLocalChecked(), newTemplate->GetFunction());
}

NODE_MODULE(keyboard_layout_manager, KeyboardLayoutManager::Init)

NAN_METHOD(KeyboardLayoutManager::New) {
  Nan::HandleScope scope;

  Local<Function> callbackHandle = info[0].As<Function>();
  Nan::Callback *callback = new Nan::Callback(callbackHandle);

  KeyboardLayoutManager *manager = new KeyboardLayoutManager(callback);
  manager->Wrap(info.This());
  return;
}

KeyboardLayoutManager::KeyboardLayoutManager(Nan::Callback *callback) : callback(callback) {
}

KeyboardLayoutManager::~KeyboardLayoutManager() {
  delete callback;
};

void KeyboardLayoutManager::HandleKeyboardLayoutChanged() {
}

NAN_METHOD(KeyboardLayoutManager::GetCurrentKeyboardLayout) {
  Nan::HandleScope scope;

  char layoutName[KL_NAMELENGTH];
  if (::GetKeyboardLayoutName(layoutName))
    info.GetReturnValue().Set(Nan::New(layoutName).ToLocalChecked());
  else
    info.GetReturnValue().Set(Nan::Undefined());
}

NAN_METHOD(KeyboardLayoutManager::GetCurrentKeyboardLanguage) {
  Nan::HandleScope scope;

  HKL layout;
  DWORD dwThreadId = 0;
  HWND hWnd = GetForegroundWindow();

  if (hWnd != NULL) {
    dwThreadId = GetWindowThreadProcessId(hWnd, NULL);
  }

  layout = GetKeyboardLayout(dwThreadId);

  wchar_t buf[LOCALE_NAME_MAX_LENGTH];
  std::wstring wstr;
  LCIDToLocaleName(MAKELCID((UINT)layout & 0xFFFF, SORT_DEFAULT), buf, LOCALE_NAME_MAX_LENGTH, 0);
  wstr.assign(buf);

  std::string str = ToUTF8(wstr);
  info.GetReturnValue().Set(Nan::New<String>(str.data(), str.size()).ToLocalChecked());
}

NAN_METHOD(KeyboardLayoutManager::GetInstalledKeyboardLanguages) {
  Nan::HandleScope scope;

  int layoutCount = GetKeyboardLayoutList(0, NULL);
  HKL* layouts = new HKL[layoutCount];
  GetKeyboardLayoutList(layoutCount, layouts);

  Local<Array> result = Nan::New<Array>(layoutCount);
  wchar_t buf[LOCALE_NAME_MAX_LENGTH];

  for (int i=0; i < layoutCount; i++) {
    std::wstring wstr;
    LCIDToLocaleName(MAKELCID((UINT)layouts[i] & 0xFFFF, SORT_DEFAULT), buf, LOCALE_NAME_MAX_LENGTH, 0);
    wstr.assign(buf);

    std::string str = ToUTF8(wstr);
    result->Set(i, Nan::New<String>(str.data(), str.size()).ToLocalChecked());
  }

  delete[] layouts;
  info.GetReturnValue().Set(result);
}

struct KeycodeMapEntry {
  UINT scanCode;
  const char *dom3Code;
};

#define USB_KEYMAP_DECLARATION static const KeycodeMapEntry keyCodeMap[] =
#define USB_KEYMAP(usb, evdev, xkb, win, mac, code, id) {win, code}

#include "keycode_converter_data.inc"

Local<Value> CharacterForNativeCode(HKL keyboardLayout, UINT keyCode, UINT scanCode,
                                     BYTE *keyboardState, bool shift, bool altGraph) {
  memset(keyboardState, 0, 256);
  if (shift) {
    keyboardState[VK_SHIFT] = 0x80;
  }

  if (altGraph) {
    keyboardState[VK_MENU] = 0x80;
    keyboardState[VK_CONTROL] = 0x80;
  }

  wchar_t characters[5];
  int count = ToUnicodeEx(keyCode, scanCode, keyboardState, characters, 5, 0, keyboardLayout);

  if (count == -1) { // Dead key
    Local<String> result = Nan::New<String>(reinterpret_cast<const uint16_t *>(characters), count).ToLocalChecked();
    // Clear dead key out of kernel-mode keyboard buffer so subsequent translations are not affected
    UINT spaceKeyCode = MapVirtualKeyEx(SPACE_SCAN_CODE, MAPVK_VSC_TO_VK, keyboardLayout);
    ToUnicodeEx(spaceKeyCode, SPACE_SCAN_CODE, keyboardState, characters, 5, 0, keyboardLayout);
    return result;
  }

  if (count > 0 && !std::iscntrl(characters[0])) {
    return Nan::New<String>(reinterpret_cast<const uint16_t *>(characters), count).ToLocalChecked();
  } else {
    return Nan::Null();
  }
}

NAN_METHOD(KeyboardLayoutManager::GetCurrentKeymap) {
  BYTE keyboardState[256];
  HKL keyboardLayout = GetKeyboardLayout(0);

  Handle<Object> result = Nan::New<Object>();
  Local<String> unmodifiedKey = Nan::New("unmodified").ToLocalChecked();
  Local<String> withShiftKey = Nan::New("withShift").ToLocalChecked();
  Local<String> withAltGraphKey = Nan::New("withAltGraph").ToLocalChecked();
  Local<String> withAltGraphShiftKey = Nan::New("withAltGraphShift").ToLocalChecked();

  size_t keyCodeMapSize = sizeof(keyCodeMap) / sizeof(keyCodeMap[0]);
  for (size_t i = 0; i < keyCodeMapSize; i++) {
    const char *dom3Code = keyCodeMap[i].dom3Code;
    UINT scanCode = keyCodeMap[i].scanCode;

    if (dom3Code && scanCode > 0x0000) {
      UINT keyCode = MapVirtualKeyEx(scanCode, MAPVK_VSC_TO_VK, keyboardLayout);

      Local<String> dom3CodeKey = Nan::New(dom3Code).ToLocalChecked();
      Local<Value> unmodified = CharacterForNativeCode(keyboardLayout, keyCode, scanCode, keyboardState, false, false);
      Local<Value> withShift = CharacterForNativeCode(keyboardLayout, keyCode, scanCode, keyboardState, true, false);
      Local<Value> withAltGraph = CharacterForNativeCode(keyboardLayout, keyCode, scanCode, keyboardState, false, true);
      Local<Value> withAltGraphShift = CharacterForNativeCode(keyboardLayout, keyCode, scanCode, keyboardState, true, true);

      if (unmodified->IsString() || withShift->IsString() || withAltGraph->IsString() || withAltGraphShift->IsString()) {
        Local<Object> entry = Nan::New<Object>();
        entry->Set(unmodifiedKey, unmodified);
        entry->Set(withShiftKey, withShift);
        entry->Set(withAltGraphKey, withAltGraph);
        entry->Set(withAltGraphShiftKey, withAltGraphShift);

        result->Set(dom3CodeKey, entry);
      }
    }
  }

  info.GetReturnValue().Set(result);

}
<commit_msg>Don’t map dead keys on Windows to avoid dropping dead key state<commit_after>#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0601

#undef WINVER
#define WINVER 0x0601

#define SPACE_SCAN_CODE 0x0039

#include "keyboard-layout-manager.h"

#include <string>
#include <cctype>
#include <windows.h>

using namespace v8;

std::string ToUTF8(const std::wstring& string) {
  if (string.length() < 1) {
    return std::string();
  }

  // NB: In the pathological case, each character could expand up
  // to 4 bytes in UTF8.
  int cbLen = (string.length()+1) * sizeof(char) * 4;
  char* buf = new char[cbLen];
  int retLen = WideCharToMultiByte(CP_UTF8, 0, string.c_str(), string.length(), buf, cbLen, NULL, NULL);
  buf[retLen] = 0;

  std::string ret;
  ret.assign(buf);
  return ret;
}

void KeyboardLayoutManager::Init(Handle<Object> exports, Handle<Object> module) {
  Nan::HandleScope scope;
  Local<FunctionTemplate> newTemplate = Nan::New<FunctionTemplate>(KeyboardLayoutManager::New);
  newTemplate->SetClassName(Nan::New<String>("KeyboardLayoutManager").ToLocalChecked());
  newTemplate->InstanceTemplate()->SetInternalFieldCount(1);
  Local<ObjectTemplate> proto = newTemplate->PrototypeTemplate();

  Nan::SetMethod(proto, "getCurrentKeyboardLayout", KeyboardLayoutManager::GetCurrentKeyboardLayout);
  Nan::SetMethod(proto, "getCurrentKeyboardLanguage", KeyboardLayoutManager::GetCurrentKeyboardLanguage);
  Nan::SetMethod(proto, "getInstalledKeyboardLanguages", KeyboardLayoutManager::GetInstalledKeyboardLanguages);
  Nan::SetMethod(proto, "getCurrentKeymap", KeyboardLayoutManager::GetCurrentKeymap);

  module->Set(Nan::New("exports").ToLocalChecked(), newTemplate->GetFunction());
}

NODE_MODULE(keyboard_layout_manager, KeyboardLayoutManager::Init)

NAN_METHOD(KeyboardLayoutManager::New) {
  Nan::HandleScope scope;

  Local<Function> callbackHandle = info[0].As<Function>();
  Nan::Callback *callback = new Nan::Callback(callbackHandle);

  KeyboardLayoutManager *manager = new KeyboardLayoutManager(callback);
  manager->Wrap(info.This());
  return;
}

KeyboardLayoutManager::KeyboardLayoutManager(Nan::Callback *callback) : callback(callback) {
}

KeyboardLayoutManager::~KeyboardLayoutManager() {
  delete callback;
};

void KeyboardLayoutManager::HandleKeyboardLayoutChanged() {
}

NAN_METHOD(KeyboardLayoutManager::GetCurrentKeyboardLayout) {
  Nan::HandleScope scope;

  char layoutName[KL_NAMELENGTH];
  if (::GetKeyboardLayoutName(layoutName))
    info.GetReturnValue().Set(Nan::New(layoutName).ToLocalChecked());
  else
    info.GetReturnValue().Set(Nan::Undefined());
}

NAN_METHOD(KeyboardLayoutManager::GetCurrentKeyboardLanguage) {
  Nan::HandleScope scope;

  HKL layout;
  DWORD dwThreadId = 0;
  HWND hWnd = GetForegroundWindow();

  if (hWnd != NULL) {
    dwThreadId = GetWindowThreadProcessId(hWnd, NULL);
  }

  layout = GetKeyboardLayout(dwThreadId);

  wchar_t buf[LOCALE_NAME_MAX_LENGTH];
  std::wstring wstr;
  LCIDToLocaleName(MAKELCID((UINT)layout & 0xFFFF, SORT_DEFAULT), buf, LOCALE_NAME_MAX_LENGTH, 0);
  wstr.assign(buf);

  std::string str = ToUTF8(wstr);
  info.GetReturnValue().Set(Nan::New<String>(str.data(), str.size()).ToLocalChecked());
}

NAN_METHOD(KeyboardLayoutManager::GetInstalledKeyboardLanguages) {
  Nan::HandleScope scope;

  int layoutCount = GetKeyboardLayoutList(0, NULL);
  HKL* layouts = new HKL[layoutCount];
  GetKeyboardLayoutList(layoutCount, layouts);

  Local<Array> result = Nan::New<Array>(layoutCount);
  wchar_t buf[LOCALE_NAME_MAX_LENGTH];

  for (int i=0; i < layoutCount; i++) {
    std::wstring wstr;
    LCIDToLocaleName(MAKELCID((UINT)layouts[i] & 0xFFFF, SORT_DEFAULT), buf, LOCALE_NAME_MAX_LENGTH, 0);
    wstr.assign(buf);

    std::string str = ToUTF8(wstr);
    result->Set(i, Nan::New<String>(str.data(), str.size()).ToLocalChecked());
  }

  delete[] layouts;
  info.GetReturnValue().Set(result);
}

struct KeycodeMapEntry {
  UINT scanCode;
  const char *dom3Code;
};

#define USB_KEYMAP_DECLARATION static const KeycodeMapEntry keyCodeMap[] =
#define USB_KEYMAP(usb, evdev, xkb, win, mac, code, id) {win, code}

#include "keycode_converter_data.inc"

Local<Value> CharacterForNativeCode(HKL keyboardLayout, UINT keyCode, UINT scanCode,
                                     BYTE *keyboardState, bool shift, bool altGraph) {
  memset(keyboardState, 0, 256);
  if (shift) {
    keyboardState[VK_SHIFT] = 0x80;
  }

  if (altGraph) {
    keyboardState[VK_MENU] = 0x80;
    keyboardState[VK_CONTROL] = 0x80;
  }

  wchar_t characters[5];
  int count = ToUnicodeEx(keyCode, scanCode, keyboardState, characters, 5, 0, keyboardLayout);

  if (count > 0 && !std::iscntrl(characters[0])) {
    return Nan::New<String>(reinterpret_cast<const uint16_t *>(characters), count).ToLocalChecked();
  } else {
    return Nan::Null();
  }
}

NAN_METHOD(KeyboardLayoutManager::GetCurrentKeymap) {
  BYTE keyboardState[256];
  HKL keyboardLayout = GetKeyboardLayout(0);

  Handle<Object> result = Nan::New<Object>();
  Local<String> unmodifiedKey = Nan::New("unmodified").ToLocalChecked();
  Local<String> withShiftKey = Nan::New("withShift").ToLocalChecked();
  Local<String> withAltGraphKey = Nan::New("withAltGraph").ToLocalChecked();
  Local<String> withAltGraphShiftKey = Nan::New("withAltGraphShift").ToLocalChecked();

  size_t keyCodeMapSize = sizeof(keyCodeMap) / sizeof(keyCodeMap[0]);
  for (size_t i = 0; i < keyCodeMapSize; i++) {
    const char *dom3Code = keyCodeMap[i].dom3Code;
    UINT scanCode = keyCodeMap[i].scanCode;

    if (dom3Code && scanCode > 0x0000) {
      UINT keyCode = MapVirtualKeyEx(scanCode, MAPVK_VSC_TO_VK, keyboardLayout);

      // Detect and skip dead keys. If the most significant bit of the returned
      // character value is 1, this is a dead key. Trying to translate it to a
      // character will mutate the Windows keyboard buffer and blow away pending
      // dead keys. To avoid this bug, we just refuse to map dead keys to
      // characters.
      if ((MapVirtualKeyEx(keyCode, MAPVK_VK_TO_CHAR, keyboardLayout) >> (sizeof(UINT) * 8 - 1))) continue;

      Local<String> dom3CodeKey = Nan::New(dom3Code).ToLocalChecked();
      Local<Value> unmodified = CharacterForNativeCode(keyboardLayout, keyCode, scanCode, keyboardState, false, false);
      Local<Value> withShift = CharacterForNativeCode(keyboardLayout, keyCode, scanCode, keyboardState, true, false);
      Local<Value> withAltGraph = CharacterForNativeCode(keyboardLayout, keyCode, scanCode, keyboardState, false, true);
      Local<Value> withAltGraphShift = CharacterForNativeCode(keyboardLayout, keyCode, scanCode, keyboardState, true, true);

      if (unmodified->IsString() || withShift->IsString() || withAltGraph->IsString() || withAltGraphShift->IsString()) {
        Local<Object> entry = Nan::New<Object>();
        entry->Set(unmodifiedKey, unmodified);
        entry->Set(withShiftKey, withShift);
        entry->Set(withAltGraphKey, withAltGraph);
        entry->Set(withAltGraphShiftKey, withAltGraphShift);

        result->Set(dom3CodeKey, entry);
      }
    }
  }

  info.GetReturnValue().Set(result);

}
<|endoftext|>


<commit_before>#ifndef PRESETEDITOR_HPP
#define PRESETEDITOR_HPP

// stdlib
#include <string>
#include <functional>

// Libslic3r
#include "libslic3r.h"
#include "ConfigBase.hpp"
#include "Config.hpp"

// GUI
#include "misc_ui.hpp"

// Wx
#include <wx/treectrl.h>
#include <wx/imaglist.h>
#include <wx/panel.h>

using namespace std::string_literals;
namespace Slic3r { namespace GUI {

class PresetPage;

class PresetEditor : public wxPanel {

public:
    /// Member function to retrieve a list of options
    /// that this preset governs. Subclasses should
    /// call their own static method.
    virtual t_config_option_keys my_options() = 0;
    static t_config_option_keys options() { return t_config_option_keys {}; }

    static t_config_option_keys overridable_options() { return t_config_option_keys {}; };
    static t_config_option_keys overriding_options() { return t_config_option_keys {}; };

    virtual t_config_option_keys my_overridable_options() = 0;
    virtual t_config_option_keys my_overriding_options() = 0;

    wxSizer* sizer() { return _sizer; };
    PresetEditor(wxWindow* parent, t_config_option_keys options = {});
    PresetEditor() : PresetEditor(nullptr, {}) {};
    std::shared_ptr<Preset> current_preset;

    /// Check if there is a dirty config that is different than the loaded config.
    bool prompt_unsaved_changes();
    void select_preset_by_name(const wxString& name, bool force = false);

    /// suppress the callback when the tree selection is changed.
    bool disable_tree_sel_changed_event {false};

    void save_preset();
    std::function<void ()> on_save_preset {};
    std::function<void ()> on_value_change {};

    config_ptr config;
    PresetPage* add_options_page(const wxString& _title, const wxString& _icon = "");

    virtual wxString title() = 0;
    virtual std::string name() = 0;
protected:
    // Main sizer
    wxSizer* _sizer {nullptr};
    wxString presets;
    wxImageList* _icons {nullptr};
    wxTreeCtrl* _treectrl {nullptr};
    wxBitmapButton* _btn_save_preset {nullptr};
    wxBitmapButton* _btn_delete_preset {nullptr};
    wxChoice* _presets_choice {nullptr};
    int _iconcount {-1};

    /// Vector of PresetPage pointers; trust wxWidgets RTTI to avoid leaks
    std::vector<PresetPage*> _pages {};

    const unsigned int left_col_width {150};
    void _update_tree();
    void load_presets();

    virtual void _build() = 0;
    virtual void _update() = 0;
    virtual void _on_preset_loaded() = 0;
    void set_tooltips() {
        this->_btn_save_preset->SetToolTip(wxString(_("Save current ")) + this->title());
        this->_btn_delete_preset->SetToolTip(_("Delete this preset."));
    }
};

class PrintEditor : public PresetEditor {
public:

    PrintEditor(wxWindow* parent, t_config_option_keys options = {});
    PrintEditor() : PrintEditor(nullptr, {}) {};

    wxString title() override { return _("Print Settings"); }
    std::string name() override { return "print"s; }

    t_config_option_keys my_overridable_options() override { return PresetEditor::overridable_options(); };
    static t_config_option_keys overridable_options() { return PresetEditor::overridable_options(); };

    t_config_option_keys my_overriding_options() override { return PresetEditor::overriding_options(); };
    static t_config_option_keys overriding_options() { return PresetEditor::overriding_options(); };

    /// Static method to retrieve list of options that this preset governs.
    static t_config_option_keys options() {
        return t_config_option_keys
        {
            "layer_height"s, "first_layer_height"s,
            "adaptive_slicing"s, "adaptive_slicing_quality"s, "match_horizontal_surfaces"s,
            "perimeters"s, "spiral_vase"s,
            "top_solid_layers"s, "bottom_solid_layers"s,
            "extra_perimeters"s, "avoid_crossing_perimeters"s, "thin_walls"s, "overhangs"s,
            "seam_position"s, "external_perimeters_first"s,
            "fill_density"s, "fill_pattern"s, "top_infill_pattern"s, "bottom_infill_pattern"s, "fill_gaps"s,
            "infill_every_layers"s, "infill_only_where_needed"s,
            "solid_infill_every_layers"s, "fill_angle"s, "solid_infill_below_area"s, ""s,
            "only_retract_when_crossing_perimeters"s, "infill_first"s,
            "max_print_speed"s, "max_volumetric_speed"s,
            "perimeter_speed"s, "small_perimeter_speed"s, "external_perimeter_speed"s, "infill_speed"s, ""s,
            "solid_infill_speed"s, "top_solid_infill_speed"s, "support_material_speed"s,
            "support_material_interface_speed"s, "bridge_speed"s, "gap_fill_speed"s,
            "travel_speed"s,
            "first_layer_speed"s,
            "perimeter_acceleration"s, "infill_acceleration"s, "bridge_acceleration"s,
            "first_layer_acceleration"s, "default_acceleration"s,
            "skirts"s, "skirt_distance"s, "skirt_height"s, "min_skirt_length"s,
            "brim_connections_width"s, "brim_width"s, "interior_brim_width"s,
            "support_material"s, "support_material_threshold"s, "support_material_max_layers"s, "support_material_enforce_layers"s,
            "raft_layers"s,
            "support_material_pattern"s, "support_material_spacing"s, "support_material_angle"s, ""s,
            "support_material_interface_layers"s, "support_material_interface_spacing"s,
            "support_material_contact_distance"s, "support_material_buildplate_only"s, "dont_support_bridges"s,
            "notes"s,
            "complete_objects"s, "extruder_clearance_radius"s, "extruder_clearance_height"s,
            "gcode_comments"s, "output_filename_format"s,
            "post_process"s,
            "perimeter_extruder"s, "infill_extruder"s, "solid_infill_extruder"s,
            "support_material_extruder"s, "support_material_interface_extruder"s,
            "ooze_prevention"s, "standby_temperature_delta"s,
            "interface_shells"s, "regions_overlap"s,
            "extrusion_width"s, "first_layer_extrusion_width"s, "perimeter_extrusion_width"s, ""s,
            "external_perimeter_extrusion_width"s, "infill_extrusion_width"s, "solid_infill_extrusion_width"s,
            "top_infill_extrusion_width"s, "support_material_extrusion_width"s,
            "support_material_interface_extrusion_width"s, "infill_overlap"s, "bridge_flow_ratio"s,
            "xy_size_compensation"s, "resolution"s, "shortcuts"s, "compatible_printers"s,
            "print_settings_id"s
        };
    }

    t_config_option_keys my_options() override { return PrintEditor::options(); }

protected:
    void _update() override;
    void _build() override;
};

class PrinterEditor : public PresetEditor {
public:
    PrinterEditor(wxWindow* parent, t_config_option_keys options = {});
    PrinterEditor() : PrinterEditor(nullptr, {}) {};

    wxString title() override { return _("Printer Settings"); }
    std::string name() override { return "printer"s; }
    static t_config_option_keys overridable_options() { return t_config_option_keys
    {
        "pressure_advance"s,
        "retract_length"s, "retract_lift"s, "retract_speed"s, "retract_restart_extra"s,
        "retract_before_travel"s, "retract_layer_change"s, "wipe"s
    }; };
    static t_config_option_keys overriding_options() { return PresetEditor::overriding_options(); };

    t_config_option_keys my_overridable_options() override { return PrinterEditor::overridable_options(); };
    t_config_option_keys my_overriding_options() override { return PrinterEditor::overriding_options(); };

    static t_config_option_keys options() {
        return t_config_option_keys
        {
            "bed_shape"s, "z_offset"s, "z_steps_per_mm"s, "has_heatbed"s,
            "gcode_flavor"s, "use_relative_e_distances"s,
            "serial_port"s, "serial_speed"s,
            "host_type"s, "print_host"s, "octoprint_apikey"s,
            "use_firmware_retraction"s, "pressure_advance"s, "vibration_limit"s,
            "use_volumetric_e"s,
            "start_gcode"s, "end_gcode"s, "before_layer_gcode"s, "layer_gcode"s, "toolchange_gcode"s, "between_objects_gcode"s,
            "nozzle_diameter"s, "extruder_offset"s, "min_layer_height"s, "max_layer_height"s,
            "retract_length"s, "retract_lift"s, "retract_speed"s, "retract_restart_extra"s, "retract_before_travel"s, "retract_layer_change"s, "wipe"s,
            "retract_length_toolchange"s, "retract_restart_extra_toolchange"s, "retract_lift_above"s, "retract_lift_below"s,
            "printer_settings_id"s,
            "printer_notes"s,
            "use_set_and_wait_bed"s, "use_set_and_wait_extruder"s
        };
    }

    t_config_option_keys my_options() override { return PrinterEditor::options(); }
protected:
    void _update() override;
    void _build() override;
    const std::string LogChannel() override {return "PrinterEditor"s;} //< Which log these messages should go to.
};

class MaterialEditor : public PresetEditor {
public:

    wxString title() override { return _("Material Settings"); }
    std::string name() override { return "material"s; }
    preset_t type() override  { return preset_t::Material; };
    int typeId() override  { return static_cast<int>(preset_t::Material); };
    MaterialEditor(wxWindow* parent, t_config_option_keys options = {});
    MaterialEditor() : MaterialEditor(nullptr, {}) {};

    t_config_option_keys my_overridable_options() override { return PresetEditor::overridable_options(); };
    t_config_option_keys my_overriding_options() override { return PrinterEditor::overridable_options(); };

    static t_config_option_keys overriding_options() { return PrinterEditor::overridable_options(); };
    static t_config_option_keys overridable_options() { return PresetEditor::overridable_options(); };

    static t_config_option_keys options() {
        return t_config_option_keys
        {
            "filament_colour"s, "filament_diameter"s, "filament_notes"s, "filament_max_volumetric_speed"s, "extrusion_multiplier"s, "filament_density"s, "filament_cost"s,
            "temperature"s, "first_layer_temperature"s, "bed_temperature"s, "first_layer_bed_temperature"s,
            "fan_always_on"s, "cooling"s, "compatible_printers"s,
            "min_fan_speed"s, "max_fan_speed"s, "bridge_fan_speed"s, "disable_fan_first_layers"s,
            "fan_below_layer_time"s, "slowdown_below_layer_time"s, "min_print_speed"s,
            "start_filament_gcode"s, "end_filament_gcode"s,
            "filament_settings_id"s
        };
    }

    t_config_option_keys my_options() override { return MaterialEditor::options(); }
protected:
    void _update() override;
    void _build() override;
    const std::string LogChannel() override {return "MaterialEditor"s;} //< Which log these messages should go to.
};

class PresetPage : wxScrolledWindow {
public:
    PresetPage(wxWindow* parent, wxString _title, int _iconID) :
        wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL),
        title(_title), iconID(_iconID) {
            this->vsizer = new wxBoxSizer(wxVERTICAL);
            this->SetSizer(this->vsizer);
            this->SetScrollRate(ui_settings->scroll_step(), ui_settings->scroll_step());
        }
protected:
    wxSizer* vsizer {nullptr};
    wxString title {""};
    int iconID {0};
};

}} // namespace Slic3r::GUI
#endif // PRESETEDITOR_HPP
<commit_msg>Bring in Preset reference file<commit_after>#ifndef PRESETEDITOR_HPP
#define PRESETEDITOR_HPP

// stdlib
#include <string>
#include <functional>

// Libslic3r
#include "libslic3r.h"
#include "ConfigBase.hpp"
#include "Config.hpp"

// GUI
#include "misc_ui.hpp"
#include "Preset.hpp"

// Wx
#include <wx/treectrl.h>
#include <wx/imaglist.h>
#include <wx/panel.h>
#include <wx/scrolwin.h>

using namespace std::string_literals;
namespace Slic3r { namespace GUI {

class PresetPage;

class PresetEditor : public wxPanel {

public:
    /// Member function to retrieve a list of options
    /// that this preset governs. Subclasses should
    /// call their own static method.
    virtual t_config_option_keys my_options() = 0;
    static t_config_option_keys options() { return t_config_option_keys {}; }

    static t_config_option_keys overridable_options() { return t_config_option_keys {}; };
    static t_config_option_keys overriding_options() { return t_config_option_keys {}; };

    virtual t_config_option_keys my_overridable_options() = 0;
    virtual t_config_option_keys my_overriding_options() = 0;

    wxSizer* sizer() { return _sizer; };
    PresetEditor(wxWindow* parent, t_config_option_keys options = {});
    PresetEditor() : PresetEditor(nullptr, {}) {};
    std::shared_ptr<Preset> current_preset;

    /// Check if there is a dirty config that is different than the loaded config.
    bool prompt_unsaved_changes();
    void select_preset_by_name(const wxString& name, bool force = false);

    /// suppress the callback when the tree selection is changed.
    bool disable_tree_sel_changed_event {false};

    void save_preset();
    std::function<void ()> on_save_preset {};
    std::function<void ()> on_value_change {};

    config_ptr config;
    PresetPage* add_options_page(const wxString& _title, const wxString& _icon = "");

    virtual wxString title() = 0;
    virtual std::string name() = 0;
protected:
    // Main sizer
    wxSizer* _sizer {nullptr};
    wxString presets;
    wxImageList* _icons {nullptr};
    wxTreeCtrl* _treectrl {nullptr};
    wxBitmapButton* _btn_save_preset {nullptr};
    wxBitmapButton* _btn_delete_preset {nullptr};
    wxChoice* _presets_choice {nullptr};
    int _iconcount {-1};

    /// Vector of PresetPage pointers; trust wxWidgets RTTI to avoid leaks
    std::vector<PresetPage*> _pages {};

    const unsigned int left_col_width {150};
    void _update_tree();
    void load_presets();

    virtual void _build() = 0;
    virtual void _update() = 0;
    virtual void _on_preset_loaded() = 0;
    void set_tooltips() {
        this->_btn_save_preset->SetToolTip(wxString(_("Save current ")) + this->title());
        this->_btn_delete_preset->SetToolTip(_("Delete this preset."));
    }
};

class PrintEditor : public PresetEditor {
public:

    PrintEditor(wxWindow* parent, t_config_option_keys options = {});
    PrintEditor() : PrintEditor(nullptr, {}) {};

    wxString title() override { return _("Print Settings"); }
    std::string name() override { return "print"s; }

    t_config_option_keys my_overridable_options() override { return PresetEditor::overridable_options(); };
    static t_config_option_keys overridable_options() { return PresetEditor::overridable_options(); };

    t_config_option_keys my_overriding_options() override { return PresetEditor::overriding_options(); };
    static t_config_option_keys overriding_options() { return PresetEditor::overriding_options(); };

    /// Static method to retrieve list of options that this preset governs.
    static t_config_option_keys options() {
        return t_config_option_keys
        {
            "layer_height"s, "first_layer_height"s,
            "adaptive_slicing"s, "adaptive_slicing_quality"s, "match_horizontal_surfaces"s,
            "perimeters"s, "spiral_vase"s,
            "top_solid_layers"s, "bottom_solid_layers"s,
            "extra_perimeters"s, "avoid_crossing_perimeters"s, "thin_walls"s, "overhangs"s,
            "seam_position"s, "external_perimeters_first"s,
            "fill_density"s, "fill_pattern"s, "top_infill_pattern"s, "bottom_infill_pattern"s, "fill_gaps"s,
            "infill_every_layers"s, "infill_only_where_needed"s,
            "solid_infill_every_layers"s, "fill_angle"s, "solid_infill_below_area"s, ""s,
            "only_retract_when_crossing_perimeters"s, "infill_first"s,
            "max_print_speed"s, "max_volumetric_speed"s,
            "perimeter_speed"s, "small_perimeter_speed"s, "external_perimeter_speed"s, "infill_speed"s, ""s,
            "solid_infill_speed"s, "top_solid_infill_speed"s, "support_material_speed"s,
            "support_material_interface_speed"s, "bridge_speed"s, "gap_fill_speed"s,
            "travel_speed"s,
            "first_layer_speed"s,
            "perimeter_acceleration"s, "infill_acceleration"s, "bridge_acceleration"s,
            "first_layer_acceleration"s, "default_acceleration"s,
            "skirts"s, "skirt_distance"s, "skirt_height"s, "min_skirt_length"s,
            "brim_connections_width"s, "brim_width"s, "interior_brim_width"s,
            "support_material"s, "support_material_threshold"s, "support_material_max_layers"s, "support_material_enforce_layers"s,
            "raft_layers"s,
            "support_material_pattern"s, "support_material_spacing"s, "support_material_angle"s, ""s,
            "support_material_interface_layers"s, "support_material_interface_spacing"s,
            "support_material_contact_distance"s, "support_material_buildplate_only"s, "dont_support_bridges"s,
            "notes"s,
            "complete_objects"s, "extruder_clearance_radius"s, "extruder_clearance_height"s,
            "gcode_comments"s, "output_filename_format"s,
            "post_process"s,
            "perimeter_extruder"s, "infill_extruder"s, "solid_infill_extruder"s,
            "support_material_extruder"s, "support_material_interface_extruder"s,
            "ooze_prevention"s, "standby_temperature_delta"s,
            "interface_shells"s, "regions_overlap"s,
            "extrusion_width"s, "first_layer_extrusion_width"s, "perimeter_extrusion_width"s, ""s,
            "external_perimeter_extrusion_width"s, "infill_extrusion_width"s, "solid_infill_extrusion_width"s,
            "top_infill_extrusion_width"s, "support_material_extrusion_width"s,
            "support_material_interface_extrusion_width"s, "infill_overlap"s, "bridge_flow_ratio"s,
            "xy_size_compensation"s, "resolution"s, "shortcuts"s, "compatible_printers"s,
            "print_settings_id"s
        };
    }

    t_config_option_keys my_options() override { return PrintEditor::options(); }

protected:
    void _update() override;
    void _build() override;
};

class PrinterEditor : public PresetEditor {
public:
    PrinterEditor(wxWindow* parent, t_config_option_keys options = {});
    PrinterEditor() : PrinterEditor(nullptr, {}) {};

    wxString title() override { return _("Printer Settings"); }
    std::string name() override { return "printer"s; }
    static t_config_option_keys overridable_options() { return t_config_option_keys
    {
        "pressure_advance"s,
        "retract_length"s, "retract_lift"s, "retract_speed"s, "retract_restart_extra"s,
        "retract_before_travel"s, "retract_layer_change"s, "wipe"s
    }; };
    static t_config_option_keys overriding_options() { return PresetEditor::overriding_options(); };

    t_config_option_keys my_overridable_options() override { return PrinterEditor::overridable_options(); };
    t_config_option_keys my_overriding_options() override { return PrinterEditor::overriding_options(); };

    static t_config_option_keys options() {
        return t_config_option_keys
        {
            "bed_shape"s, "z_offset"s, "z_steps_per_mm"s, "has_heatbed"s,
            "gcode_flavor"s, "use_relative_e_distances"s,
            "serial_port"s, "serial_speed"s,
            "host_type"s, "print_host"s, "octoprint_apikey"s,
            "use_firmware_retraction"s, "pressure_advance"s, "vibration_limit"s,
            "use_volumetric_e"s,
            "start_gcode"s, "end_gcode"s, "before_layer_gcode"s, "layer_gcode"s, "toolchange_gcode"s, "between_objects_gcode"s,
            "nozzle_diameter"s, "extruder_offset"s, "min_layer_height"s, "max_layer_height"s,
            "retract_length"s, "retract_lift"s, "retract_speed"s, "retract_restart_extra"s, "retract_before_travel"s, "retract_layer_change"s, "wipe"s,
            "retract_length_toolchange"s, "retract_restart_extra_toolchange"s, "retract_lift_above"s, "retract_lift_below"s,
            "printer_settings_id"s,
            "printer_notes"s,
            "use_set_and_wait_bed"s, "use_set_and_wait_extruder"s
        };
    }

    t_config_option_keys my_options() override { return PrinterEditor::options(); }
protected:
    void _update() override;
    void _build() override;
    const std::string LogChannel() override {return "PrinterEditor"s;} //< Which log these messages should go to.
};

class MaterialEditor : public PresetEditor {
public:

    wxString title() override { return _("Material Settings"); }
    std::string name() override { return "material"s; }
    preset_t type() override  { return preset_t::Material; };
    int typeId() override  { return static_cast<int>(preset_t::Material); };
    MaterialEditor(wxWindow* parent, t_config_option_keys options = {});
    MaterialEditor() : MaterialEditor(nullptr, {}) {};

    t_config_option_keys my_overridable_options() override { return PresetEditor::overridable_options(); };
    t_config_option_keys my_overriding_options() override { return PrinterEditor::overridable_options(); };

    static t_config_option_keys overriding_options() { return PrinterEditor::overridable_options(); };
    static t_config_option_keys overridable_options() { return PresetEditor::overridable_options(); };

    static t_config_option_keys options() {
        return t_config_option_keys
        {
            "filament_colour"s, "filament_diameter"s, "filament_notes"s, "filament_max_volumetric_speed"s, "extrusion_multiplier"s, "filament_density"s, "filament_cost"s,
            "temperature"s, "first_layer_temperature"s, "bed_temperature"s, "first_layer_bed_temperature"s,
            "fan_always_on"s, "cooling"s, "compatible_printers"s,
            "min_fan_speed"s, "max_fan_speed"s, "bridge_fan_speed"s, "disable_fan_first_layers"s,
            "fan_below_layer_time"s, "slowdown_below_layer_time"s, "min_print_speed"s,
            "start_filament_gcode"s, "end_filament_gcode"s,
            "filament_settings_id"s
        };
    }

    t_config_option_keys my_options() override { return MaterialEditor::options(); }
protected:
    void _update() override;
    void _build() override;
    const std::string LogChannel() override {return "MaterialEditor"s;} //< Which log these messages should go to.
};

class PresetPage : wxScrolledWindow {
public:
    PresetPage(wxWindow* parent, wxString _title, int _iconID) :
        wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL),
        title(_title), iconID(_iconID) {
            this->vsizer = new wxBoxSizer(wxVERTICAL);
            this->SetSizer(this->vsizer);
            this->SetScrollRate(ui_settings->scroll_step(), ui_settings->scroll_step());
        }
protected:
    wxSizer* vsizer {nullptr};
    wxString title {""};
    int iconID {0};
};

}} // namespace Slic3r::GUI
#endif // PRESETEDITOR_HPP
<|endoftext|>