<commit_before>/*************************************************
* X.509 Public Key Source File                   *
* (C) 1999-2006 The Botan Project                *
*************************************************/

#include <botan/x509_key.h>
#include <botan/filters.h>
#include <botan/asn1_obj.h>
#include <botan/der_enc.h>
#include <botan/ber_dec.h>
#include <botan/pk_algs.h>
#include <botan/oids.h>
#include <botan/pem.h>
#include <memory>

namespace Botan {

/*************************************************
* Compute the key id                             *
*************************************************/
u64bit X509_PublicKey::key_id() const
   {
   Pipe pipe(new Hash_Filter("SHA-1", 8));

   std::auto_ptr<X509_Encoder> encoder(x509_encoder());
   if(!encoder.get())
      throw Internal_Error("X509_PublicKey:key_id: No encoder found");

   pipe.start_msg();
   pipe.write(algo_name());
   pipe.write(encoder->alg_id().parameters);
   pipe.write(encoder->key_bits());
   //pipe.write(DER_encode_pub());
   //pipe.write(DER_encode_params());
   pipe.end_msg();

   SecureVector<byte> output = pipe.read_all();

   if(output.size() != 8)
      throw Internal_Error("X509_PublicKey::key_id: Incorrect output size");

   u64bit id = 0;
   for(u32bit j = 0; j != 8; ++j)
      id = (id << 8) | output[j];
   return id;
   }

/*************************************************
* Return an encoder for this key                 *
*************************************************/
/*
X509_Encoder* X509_PublicKey::x509_encoder() const
   {
   class X509_Default_Encoder : public X509_Encoder
      {
      public:
         AlgorithmIdentifier alg_id() const { return id; }
         MemoryVector<byte> key_bits() const { return bits; }

         X509_Default_Encoder(const X509_PublicKey* key)
            {
            id = AlgorithmIdentifier(key->get_oid(), key->DER_encode_params());
            bits = key->DER_encode_pub();
            }
      private:
         AlgorithmIdentifier id;
         MemoryVector<byte> bits;
      };

   return new X509_Default_Encoder(this);
   }
*/

/*
X509_Decoder* X509_PublicKey::x509_decoder()
   {
   class X509_Default_Decoder : public X509_Decoder
      {
      public:
         void alg_id(const AlgorithmIdentifier& alg_id)
            {
            DataSource_Memory params(alg_id.parameters);
            key->BER_decode_params(params);
            }
         void key_bits(const MemoryRegion<byte>& bits)
            {
            DataSource_Memory key_bits(bits);
            key->BER_decode_pub(key_bits);
            }

         X509_Default_Decoder(X509_PublicKey* k) : key(k) {}
      private:
         X509_PublicKey* key;
      };

   return new X509_Default_Decoder(this);
   }
*/

namespace X509 {

/*************************************************
* DER or PEM encode a X.509 public key           *
*************************************************/
void encode(const X509_PublicKey& key, Pipe& pipe, X509_Encoding encoding)
   {
   std::auto_ptr<X509_Encoder> encoder(key.x509_encoder());
   if(!encoder.get())
      throw Encoding_Error("X509::encode: Key does not support encoding");

   MemoryVector<byte> der =
      DER_Encoder()
         .start_cons(SEQUENCE)
            .encode(encoder->alg_id())
            .encode(encoder->key_bits(), BIT_STRING)
         .end_cons()
      .get_contents();

   if(encoding == PEM)
      pipe.write(PEM_Code::encode(der, "PUBLIC KEY"));
   else
      pipe.write(der);
   }

/*************************************************
* PEM encode a X.509 public key                  *
*************************************************/
std::string PEM_encode(const X509_PublicKey& key)
   {
   Pipe pem;
   pem.start_msg();
   encode(key, pem, PEM);
   pem.end_msg();
   return pem.read_all_as_string();
   }

/*************************************************
* Extract a public key and return it             *
*************************************************/
X509_PublicKey* load_key(DataSource& source)
   {
   try {
      AlgorithmIdentifier alg_id;
      MemoryVector<byte> key_bits;

      if(ASN1::maybe_BER(source) && !PEM_Code::matches(source))
         {
         BER_Decoder(source)
            .start_cons(SEQUENCE)
            .decode(alg_id)
            .decode(key_bits, BIT_STRING)
            .verify_end()
         .end_cons();
         }
      else
         {
         DataSource_Memory ber(
            PEM_Code::decode_check_label(source, "PUBLIC KEY")
            );

         BER_Decoder(ber)
            .start_cons(SEQUENCE)
            .decode(alg_id)
            .decode(key_bits, BIT_STRING)
            .verify_end()
         .end_cons();
         }

      if(key_bits.is_empty())
         throw Decoding_Error("X.509 public key decoding failed");

      const std::string alg_name = OIDS::lookup(alg_id.oid);
      if(alg_name == "")
         throw Decoding_Error("Unknown algorithm OID: " +
                              alg_id.oid.as_string());

      std::auto_ptr<X509_PublicKey> key_obj(get_public_key(alg_name));
      if(!key_obj.get())
         throw Decoding_Error("Unknown PK algorithm/OID: " + alg_name + ", " +
                              alg_id.oid.as_string());

      std::auto_ptr<X509_Decoder> decoder(key_obj->x509_decoder());
      if(!decoder.get())
         throw Decoding_Error("Key does not support X.509 decoding");

      decoder->alg_id(alg_id);
      decoder->key_bits(key_bits);

      return key_obj.release();
      }
   catch(Decoding_Error)
      {
      throw Decoding_Error("X.509 public key decoding failed");
      }
   }

/*************************************************
* Extract a public key and return it             *
*************************************************/
X509_PublicKey* load_key(const std::string& fsname)
   {
   DataSource_Stream source(fsname, true);
   return X509::load_key(source);
   }

/*************************************************
* Extract a public key and return it             *
*************************************************/
X509_PublicKey* load_key(const MemoryRegion<byte>& mem)
   {
   DataSource_Memory source(mem);
   return X509::load_key(source);
   }

/*************************************************
* Make a copy of this public key                 *
*************************************************/
X509_PublicKey* copy_key(const X509_PublicKey& key)
   {
   Pipe bits;
   bits.start_msg();
   X509::encode(key, bits, RAW_BER);
   bits.end_msg();
   DataSource_Memory source(bits.read_all());
   return X509::load_key(source);
   }

/*************************************************
* Find the allowable key constraints             *
*************************************************/
Key_Constraints find_constraints(const X509_PublicKey& pub_key,
                                 Key_Constraints limits)
   {
   const X509_PublicKey* key = &pub_key;
   u32bit constraints = 0;

   if(dynamic_cast<const PK_Encrypting_Key*>(key))
      constraints |= KEY_ENCIPHERMENT;

   if(dynamic_cast<const PK_Key_Agreement_Key*>(key))
      constraints |= KEY_AGREEMENT;

   if(dynamic_cast<const PK_Verifying_wo_MR_Key*>(key) ||
      dynamic_cast<const PK_Verifying_with_MR_Key*>(key))
      constraints |= DIGITAL_SIGNATURE | NON_REPUDIATION;

   if(limits)
      constraints &= limits;

   return Key_Constraints(constraints);
   }

}

}
<commit_msg>Remove some old commented out test code.<commit_after>/*************************************************
* X.509 Public Key Source File                   *
* (C) 1999-2006 The Botan Project                *
*************************************************/

#include <botan/x509_key.h>
#include <botan/filters.h>
#include <botan/asn1_obj.h>
#include <botan/der_enc.h>
#include <botan/ber_dec.h>
#include <botan/pk_algs.h>
#include <botan/oids.h>
#include <botan/pem.h>
#include <memory>

namespace Botan {

/*************************************************
* Compute the key id                             *
*************************************************/
u64bit X509_PublicKey::key_id() const
   {
   Pipe pipe(new Hash_Filter("SHA-1", 8));

   std::auto_ptr<X509_Encoder> encoder(x509_encoder());
   if(!encoder.get())
      throw Internal_Error("X509_PublicKey:key_id: No encoder found");

   pipe.start_msg();
   pipe.write(algo_name());
   pipe.write(encoder->alg_id().parameters);
   pipe.write(encoder->key_bits());
   pipe.end_msg();

   SecureVector<byte> output = pipe.read_all();

   if(output.size() != 8)
      throw Internal_Error("X509_PublicKey::key_id: Incorrect output size");

   u64bit id = 0;
   for(u32bit j = 0; j != 8; ++j)
      id = (id << 8) | output[j];
   return id;
   }

namespace X509 {

/*************************************************
* DER or PEM encode a X.509 public key           *
*************************************************/
void encode(const X509_PublicKey& key, Pipe& pipe, X509_Encoding encoding)
   {
   std::auto_ptr<X509_Encoder> encoder(key.x509_encoder());
   if(!encoder.get())
      throw Encoding_Error("X509::encode: Key does not support encoding");

   MemoryVector<byte> der =
      DER_Encoder()
         .start_cons(SEQUENCE)
            .encode(encoder->alg_id())
            .encode(encoder->key_bits(), BIT_STRING)
         .end_cons()
      .get_contents();

   if(encoding == PEM)
      pipe.write(PEM_Code::encode(der, "PUBLIC KEY"));
   else
      pipe.write(der);
   }

/*************************************************
* PEM encode a X.509 public key                  *
*************************************************/
std::string PEM_encode(const X509_PublicKey& key)
   {
   Pipe pem;
   pem.start_msg();
   encode(key, pem, PEM);
   pem.end_msg();
   return pem.read_all_as_string();
   }

/*************************************************
* Extract a public key and return it             *
*************************************************/
X509_PublicKey* load_key(DataSource& source)
   {
   try {
      AlgorithmIdentifier alg_id;
      MemoryVector<byte> key_bits;

      if(ASN1::maybe_BER(source) && !PEM_Code::matches(source))
         {
         BER_Decoder(source)
            .start_cons(SEQUENCE)
            .decode(alg_id)
            .decode(key_bits, BIT_STRING)
            .verify_end()
         .end_cons();
         }
      else
         {
         DataSource_Memory ber(
            PEM_Code::decode_check_label(source, "PUBLIC KEY")
            );

         BER_Decoder(ber)
            .start_cons(SEQUENCE)
            .decode(alg_id)
            .decode(key_bits, BIT_STRING)
            .verify_end()
         .end_cons();
         }

      if(key_bits.is_empty())
         throw Decoding_Error("X.509 public key decoding failed");

      const std::string alg_name = OIDS::lookup(alg_id.oid);
      if(alg_name == "")
         throw Decoding_Error("Unknown algorithm OID: " +
                              alg_id.oid.as_string());

      std::auto_ptr<X509_PublicKey> key_obj(get_public_key(alg_name));
      if(!key_obj.get())
         throw Decoding_Error("Unknown PK algorithm/OID: " + alg_name + ", " +
                              alg_id.oid.as_string());

      std::auto_ptr<X509_Decoder> decoder(key_obj->x509_decoder());
      if(!decoder.get())
         throw Decoding_Error("Key does not support X.509 decoding");

      decoder->alg_id(alg_id);
      decoder->key_bits(key_bits);

      return key_obj.release();
      }
   catch(Decoding_Error)
      {
      throw Decoding_Error("X.509 public key decoding failed");
      }
   }

/*************************************************
* Extract a public key and return it             *
*************************************************/
X509_PublicKey* load_key(const std::string& fsname)
   {
   DataSource_Stream source(fsname, true);
   return X509::load_key(source);
   }

/*************************************************
* Extract a public key and return it             *
*************************************************/
X509_PublicKey* load_key(const MemoryRegion<byte>& mem)
   {
   DataSource_Memory source(mem);
   return X509::load_key(source);
   }

/*************************************************
* Make a copy of this public key                 *
*************************************************/
X509_PublicKey* copy_key(const X509_PublicKey& key)
   {
   Pipe bits;
   bits.start_msg();
   X509::encode(key, bits, RAW_BER);
   bits.end_msg();
   DataSource_Memory source(bits.read_all());
   return X509::load_key(source);
   }

/*************************************************
* Find the allowable key constraints             *
*************************************************/
Key_Constraints find_constraints(const X509_PublicKey& pub_key,
                                 Key_Constraints limits)
   {
   const X509_PublicKey* key = &pub_key;
   u32bit constraints = 0;

   if(dynamic_cast<const PK_Encrypting_Key*>(key))
      constraints |= KEY_ENCIPHERMENT;

   if(dynamic_cast<const PK_Key_Agreement_Key*>(key))
      constraints |= KEY_AGREEMENT;

   if(dynamic_cast<const PK_Verifying_wo_MR_Key*>(key) ||
      dynamic_cast<const PK_Verifying_with_MR_Key*>(key))
      constraints |= DIGITAL_SIGNATURE | NON_REPUDIATION;

   if(limits)
      constraints &= limits;

   return Key_Constraints(constraints);
   }

}

}
<|endoftext|>


<commit_before>// vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:
/*
Copyright (c) 2008 Aristid Breitkreuz, Ruediger Sonderfeld

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated textation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include "flusspferd/xml/text.hpp"
#include "flusspferd/xml/node.hpp"
#include "flusspferd/local_root_scope.hpp"
#include "flusspferd/string.hpp"
#include "flusspferd/exception.hpp"
#include "flusspferd/tracer.hpp"

using namespace flusspferd;
using namespace flusspferd::xml;

template<typename Tag>
general_text<Tag>::general_text(xmlNodePtr ptr)
  : node(ptr)
{}

static xmlNodePtr new_text(text_tag, xmlChar const *text) {
  return xmlNewText(text);
}

static xmlNodePtr new_text(comment_tag, xmlChar const *text) {
  return xmlNewComment(text);
}

static xmlNodePtr new_text(cdata_section_tag, xmlChar const *text) {
  xmlNodePtr node = xmlNewCDataBlock(0, text, xmlStrlen(text));
  node->name = xmlStrdup((xmlChar const *) "cdata");
  return node;
}

template<typename Tag>
static xmlNodePtr new_text(Tag tag, call_context &x) {
  value text_v = x.arg[0];
  string text;
  if (!text_v.is_void() && !text_v.is_null())
    text = text_v.to_string();
  xmlChar const *unencoded = (xmlChar const *) text.c_str();
  return new_text(tag, unencoded);
}

template<typename Tag>
general_text<Tag>::general_text(call_context &x)
  : node(new_text(Tag(), x))
{}

template<typename Tag>
general_text<Tag>::~general_text()
{}

template<typename Tag>
void general_text<Tag>::post_initialize() {
  node::post_initialize();
}

template<typename Tag>
object general_text<Tag>::class_info::create_prototype() {
  local_root_scope scope;

  object proto = node::class_info::create_prototype();

  return proto;
}

template<typename Tag>
char const *general_text<Tag>::class_info::constructor_name() {
  return Tag::name();
}

template<typename Tag>
std::size_t general_text<Tag>::class_info::constructor_arity() {
  return 1;
}

template class general_text<text_tag>;
template class general_text<comment_tag>;
template class general_text<cdata_section_tag>;
<commit_msg>remove unnecessary include<commit_after>// vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:
/*
Copyright (c) 2008 Aristid Breitkreuz, Ruediger Sonderfeld

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated textation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include "flusspferd/xml/text.hpp"
#include "flusspferd/xml/node.hpp"
#include "flusspferd/local_root_scope.hpp"
#include "flusspferd/string.hpp"
#include "flusspferd/exception.hpp"

using namespace flusspferd;
using namespace flusspferd::xml;

template<typename Tag>
general_text<Tag>::general_text(xmlNodePtr ptr)
  : node(ptr)
{}

static xmlNodePtr new_text(text_tag, xmlChar const *text) {
  return xmlNewText(text);
}

static xmlNodePtr new_text(comment_tag, xmlChar const *text) {
  return xmlNewComment(text);
}

static xmlNodePtr new_text(cdata_section_tag, xmlChar const *text) {
  xmlNodePtr node = xmlNewCDataBlock(0, text, xmlStrlen(text));
  node->name = xmlStrdup((xmlChar const *) "cdata");
  return node;
}

template<typename Tag>
static xmlNodePtr new_text(Tag tag, call_context &x) {
  value text_v = x.arg[0];
  string text;
  if (!text_v.is_void() && !text_v.is_null())
    text = text_v.to_string();
  xmlChar const *unencoded = (xmlChar const *) text.c_str();
  return new_text(tag, unencoded);
}

template<typename Tag>
general_text<Tag>::general_text(call_context &x)
  : node(new_text(Tag(), x))
{}

template<typename Tag>
general_text<Tag>::~general_text()
{}

template<typename Tag>
void general_text<Tag>::post_initialize() {
  node::post_initialize();
}

template<typename Tag>
object general_text<Tag>::class_info::create_prototype() {
  local_root_scope scope;

  object proto = node::class_info::create_prototype();

  return proto;
}

template<typename Tag>
char const *general_text<Tag>::class_info::constructor_name() {
  return Tag::name();
}

template<typename Tag>
std::size_t general_text<Tag>::class_info::constructor_arity() {
  return 1;
}

template class general_text<text_tag>;
template class general_text<comment_tag>;
template class general_text<cdata_section_tag>;
<|endoftext|>


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

#include "server_binary.h"

#ifdef HAVE_REMOTE_PROTOCOL

#include "binary.h"
#include "client_binary.h"

BinaryServer::BinaryServer(const std::shared_ptr<XapiandServer>& server_, ev::loop_ref *loop_, const std::shared_ptr<Binary> &binary_)
	: BaseServer(server_, loop_, binary_->sock),
	  binary(binary_),
	  async_signal(*loop_)
{
	async_signal.set<BinaryServer, &BinaryServer::async_signal_cb>(this);
	async_signal.start();
	LOG_EV(this, "\tStart binary async signal event\n");

	LOG_EV(this, "Start binary accept event (sock=%d)\n", binary->sock);
	LOG_OBJ(this, "CREATED BINARY SERVER!\n");
}

BinaryServer::~BinaryServer()
{
	LOG_OBJ(this, "DELETED BINARY SERVER!\n");
}

void
BinaryServer::async_signal_cb(ev::async &watcher, int revents)
{
	while (binary->tasks.call(share_this<BinaryServer>())) {}
}

void
BinaryServer::io_accept(ev::io &watcher, int revents)
{
	if (EV_ERROR & revents) {
		LOG_EV(this, "ERROR: got invalid binary event (sock=%d): %s\n", binary->sock, strerror(errno));
		return;
	}

	assert(binary->sock == watcher.fd || binary->sock == -1);

	int client_sock;
	if ((client_sock = binary->accept()) < 0) {
		if (!ignored_errorno(errno, false)) {
			LOG_ERR(this, "ERROR: accept binary error (sock=%d): %s\n", binary->sock, strerror(errno));
		}
	} else {
		auto client = Worker::create<BinaryClient>(share_this<BinaryServer>(), loop, client_sock, active_timeout, idle_timeout);

		if (!client->init_remote()) {
			client->detach();
		}
	}
}

bool
BinaryServer::trigger_replication(const Endpoint &src_endpoint, const Endpoint &dst_endpoint)
{
	int client_sock = binary->connection_socket();
	if (client_sock  < 0) {
		return false;
	}

	auto client = Worker::create<BinaryClient>(share_this<BinaryServer>(), loop, client_sock, active_timeout, idle_timeout);

	if (!client->init_replication(src_endpoint, dst_endpoint)) {
		return false;
	}

	INFO(this, "Database being synchronized from %s...\n", src_endpoint.as_string().c_str());

	return true;
}

bool
BinaryServer::store(const Endpoints &endpoints, const Xapian::docid &did, const std::string &filename)
{
	int client_sock = binary->connection_socket();
	if (client_sock < 0) {
		return false;
	}

	auto client = Worker::create<BinaryClient>(share_this<BinaryServer>(), loop, client_sock, active_timeout, idle_timeout);

	if (!client->init_storing(endpoints, did, filename)) {
		return false;
	}

	return true;
}

#endif /* HAVE_REMOTE_PROTOCOL */
<commit_msg>Normalized callbacks (and clients destroyed on error)<commit_after>/*
 * Copyright (C) 2015 deipi.com LLC and contributors. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "server_binary.h"

#ifdef HAVE_REMOTE_PROTOCOL

#include "binary.h"
#include "client_binary.h"

BinaryServer::BinaryServer(const std::shared_ptr<XapiandServer>& server_, ev::loop_ref *loop_, const std::shared_ptr<Binary> &binary_)
	: BaseServer(server_, loop_, binary_->sock),
	  binary(binary_),
	  async_signal(*loop_)
{
	async_signal.set<BinaryServer, &BinaryServer::async_signal_cb>(this);
	async_signal.start();
	LOG_EV(this, "\tStart binary async signal event\n");

	LOG_EV(this, "Start binary accept event (sock=%d)\n", binary->sock);
	LOG_OBJ(this, "CREATED BINARY SERVER!\n");
}

BinaryServer::~BinaryServer()
{
	LOG_OBJ(this, "DELETED BINARY SERVER!\n");
}

void
BinaryServer::async_signal_cb(ev::async &watcher, int revents)
{
	while (binary->tasks.call(share_this<BinaryServer>())) {}
}

void
BinaryServer::io_accept(ev::io &watcher, int revents)
{
	if (EV_ERROR & revents) {
		LOG_EV(this, "ERROR: got invalid binary event (sock=%d): %s\n", binary->sock, strerror(errno));
		return;
	}

	assert(binary->sock == watcher.fd || binary->sock == -1);

	int client_sock = binary->accept();
	if (client_sock < 0) {
		if (!ignored_errorno(errno, false)) {
			LOG_ERR(this, "ERROR: accept binary error (sock=%d): %s\n", binary->sock, strerror(errno));
		}
		return;
	}

	auto client = Worker::create<BinaryClient>(share_this<BinaryServer>(), loop, client_sock, active_timeout, idle_timeout);

	if (!client->init_remote()) {
		client->destroy();
	}
}

bool
BinaryServer::trigger_replication(const Endpoint &src_endpoint, const Endpoint &dst_endpoint)
{
	int client_sock = binary->connection_socket();
	if (client_sock  < 0) {
		return false;
	}

	auto client = Worker::create<BinaryClient>(share_this<BinaryServer>(), loop, client_sock, active_timeout, idle_timeout);

	if (!client->init_replication(src_endpoint, dst_endpoint)) {
		client->destroy();
		return false;
	}

	INFO(this, "Database being synchronized from %s...\n", src_endpoint.as_string().c_str());

	return true;
}

bool
BinaryServer::store(const Endpoints &endpoints, const Xapian::docid &did, const std::string &filename)
{
	int client_sock = binary->connection_socket();
	if (client_sock < 0) {
		return false;
	}

	auto client = Worker::create<BinaryClient>(share_this<BinaryServer>(), loop, client_sock, active_timeout, idle_timeout);

	if (!client->init_storing(endpoints, did, filename)) {
		client->destroy();
		return false;
	}

	return true;
}

#endif /* HAVE_REMOTE_PROTOCOL */
<|endoftext|>


<commit_before>#pragma once

#include "boost_defs.hpp"

#include <boost/lexical_cast.hpp>
#include <boost/optional.hpp>
#include <iomanip>

class spdlog_utility final {
public:
  static boost::optional<uint64_t> get_sort_key(const std::string& line) {
    // line == "[2016-09-22 20:18:37.649] [grabber] [info] version 0.90.36"
    // return 20160922201837649

    // We can parse time strictly by using boost::posix_time::time_from_string.
    // But we cannot use it with boost header only.
    // So we use this rough way.

    if (line.size() < strlen("[0000-00-00 00:00:00.000]")) {
      return boost::none;
    }

    if (line.empty()) {
      return boost::none;
    }

    if (line[0] != '[') {
      return boost::none;
    }

    std::string result_string(4 + 2 + 2 +     // years,months,days
                                  2 + 2 + 2 + // hours,minutes,seconds
                                  3,          // milliseconds
                              '0');
    size_t line_pos = 1;
    size_t result_pos = 0;

    // years
    result_string[result_pos++] = line[line_pos++];
    result_string[result_pos++] = line[line_pos++];
    result_string[result_pos++] = line[line_pos++];
    result_string[result_pos++] = line[line_pos++];

    // months
    ++line_pos;
    result_string[result_pos++] = line[line_pos++];
    result_string[result_pos++] = line[line_pos++];

    // days
    ++line_pos;
    result_string[result_pos++] = line[line_pos++];
    result_string[result_pos++] = line[line_pos++];

    // hours
    ++line_pos;
    result_string[result_pos++] = line[line_pos++];
    result_string[result_pos++] = line[line_pos++];

    // minutes
    ++line_pos;
    result_string[result_pos++] = line[line_pos++];
    result_string[result_pos++] = line[line_pos++];

    // seconds
    ++line_pos;
    result_string[result_pos++] = line[line_pos++];
    result_string[result_pos++] = line[line_pos++];

    // milliseconds
    ++line_pos;
    result_string[result_pos++] = line[line_pos++];
    result_string[result_pos++] = line[line_pos++];
    result_string[result_pos++] = line[line_pos++];

    try {
      return boost::lexical_cast<uint64_t>(result_string);
    } catch (...) {
    }
    return boost::none;
  }
};
<commit_msg>add spdlog_utility::get_pattern<commit_after>#pragma once

#include "boost_defs.hpp"

#include <boost/lexical_cast.hpp>
#include <boost/optional.hpp>
#include <iomanip>

class spdlog_utility final {
public:
  static std::string get_pattern(void) {
    return "[%Y-%m-%d %H:%M:%S.%e] [%l] [%n] %v";
  }

  static boost::optional<uint64_t> get_sort_key(const std::string& line) {
    // line == "[2016-09-22 20:18:37.649] [info] [grabber] version 0.90.36"
    // return 20160922201837649

    // We can parse time strictly by using boost::posix_time::time_from_string.
    // But we cannot use it with boost header only.
    // So we use this rough way.

    if (line.size() < strlen("[0000-00-00 00:00:00.000]")) {
      return boost::none;
    }

    if (line.empty()) {
      return boost::none;
    }

    if (line[0] != '[') {
      return boost::none;
    }

    std::string result_string(4 + 2 + 2 +     // years,months,days
                                  2 + 2 + 2 + // hours,minutes,seconds
                                  3,          // milliseconds
                              '0');
    size_t line_pos = 1;
    size_t result_pos = 0;

    // years
    result_string[result_pos++] = line[line_pos++];
    result_string[result_pos++] = line[line_pos++];
    result_string[result_pos++] = line[line_pos++];
    result_string[result_pos++] = line[line_pos++];

    // months
    ++line_pos;
    result_string[result_pos++] = line[line_pos++];
    result_string[result_pos++] = line[line_pos++];

    // days
    ++line_pos;
    result_string[result_pos++] = line[line_pos++];
    result_string[result_pos++] = line[line_pos++];

    // hours
    ++line_pos;
    result_string[result_pos++] = line[line_pos++];
    result_string[result_pos++] = line[line_pos++];

    // minutes
    ++line_pos;
    result_string[result_pos++] = line[line_pos++];
    result_string[result_pos++] = line[line_pos++];

    // seconds
    ++line_pos;
    result_string[result_pos++] = line[line_pos++];
    result_string[result_pos++] = line[line_pos++];

    // milliseconds
    ++line_pos;
    result_string[result_pos++] = line[line_pos++];
    result_string[result_pos++] = line[line_pos++];
    result_string[result_pos++] = line[line_pos++];

    try {
      return boost::lexical_cast<uint64_t>(result_string);
    } catch (...) {
    }
    return boost::none;
  }
};
<|endoftext|>


<commit_before>#ifndef slic3r_GLToolbar_hpp_
#define slic3r_GLToolbar_hpp_

#include <functional>
#include <string>
#include <vector>

#include "GLTexture.hpp"
#include "Event.hpp"

class wxEvtHandler;

namespace Slic3r {
namespace GUI {

class GLCanvas3D;

wxDECLARE_EVENT(EVT_GLTOOLBAR_ADD, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_ARRANGE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_MORE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_FEWER, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_SPLIT_OBJECTS, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_SPLIT_VOLUMES, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_LAYERSEDITING, SimpleEvent);

wxDECLARE_EVENT(EVT_GLVIEWTOOLBAR_3D, SimpleEvent);
wxDECLARE_EVENT(EVT_GLVIEWTOOLBAR_PREVIEW, SimpleEvent);

class GLToolbarItem
{
public:
    typedef std::function<void()> ActionCallback;
    typedef std::function<bool()> VisibilityCallback;
    typedef std::function<bool()> EnabledStateCallback;

    enum EType : unsigned char
    {
        Action,
        Separator,
        Num_Types
    };

    enum EState : unsigned char
    {
        Normal,
        Pressed,
        Disabled,
        Hover,
        HoverPressed,
        Num_States
    };

    struct Data
    {
        std::string name;
#if ENABLE_SVG_ICONS
        std::string icon_filename;
#endif // ENABLE_SVG_ICONS
        std::string tooltip;
        unsigned int sprite_id;
        bool is_toggable;
        bool visible;
        ActionCallback action_callback;
        VisibilityCallback visibility_callback;
        EnabledStateCallback enabled_state_callback;

        Data();
    };

    static const ActionCallback Default_Action_Callback;
    static const VisibilityCallback Default_Visibility_Callback;
    static const EnabledStateCallback Default_Enabled_State_Callback;

private:
    EType m_type;
    EState m_state;
    Data m_data;

public:
    GLToolbarItem(EType type, const Data& data);

    EState get_state() const { return m_state; }
    void set_state(EState state) { m_state = state; }

    const std::string& get_name() const { return m_data.name; }
#if ENABLE_SVG_ICONS
    const std::string& get_icon_filename() const { return m_data.icon_filename; }
#endif // ENABLE_SVG_ICONS
    const std::string& get_tooltip() const { return m_data.tooltip; }

    void do_action() { m_data.action_callback(); }

    bool is_enabled() const { return m_state != Disabled; }
    bool is_disabled() const { return m_state == Disabled; }
    bool is_hovered() const { return (m_state == Hover) || (m_state == HoverPressed); }
    bool is_pressed() const { return (m_state == Pressed) || (m_state == HoverPressed); }

    bool is_toggable() const { return m_data.is_toggable; }
    bool is_visible() const { return m_data.visible; }
    bool is_separator() const { return m_type == Separator; }

    // returns true if the state changes
    bool update_visibility();
    // returns true if the state changes
    bool update_enabled_state();

    void render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const;

private:
    GLTexture::Quad_UVs get_uvs(unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const;
    void set_visible(bool visible) { m_data.visible = visible; }

    friend class GLToolbar;
};

#if !ENABLE_SVG_ICONS
// items icon textures are assumed to be square and all with the same size in pixels, no internal check is done
// icons are layed-out into the texture starting from the top-left corner in the same order as enum GLToolbarItem::EState
// from left to right
struct ItemsIconsTexture
{
    struct Metadata
    {
        // path of the file containing the icons' texture
        std::string filename;
        // size of the square icons, in pixels
        unsigned int icon_size;

        Metadata();
    };

    GLTexture texture;
    Metadata metadata;
};
#endif // !ENABLE_SVG_ICONS

struct BackgroundTexture
{
    struct Metadata
    {
        // path of the file containing the background texture
        std::string filename;
        // size of the left edge, in pixels
        unsigned int left;
        // size of the right edge, in pixels
        unsigned int right;
        // size of the top edge, in pixels
        unsigned int top;
        // size of the bottom edge, in pixels
        unsigned int bottom;

        Metadata();
    };

    GLTexture texture;
    Metadata metadata;
};

class GLToolbar
{
public:
#if ENABLE_SVG_ICONS
    static const float Default_Icons_Size;
#endif // ENABLE_SVG_ICONS

    enum EType : unsigned char
    {
        Normal,
        Radio,
        Num_Types
    };

    struct Layout
    {
        enum EType : unsigned char
        {
            Horizontal,
            Vertical,
            Num_Types
        };

        enum EOrientation : unsigned int
        {
            Top,
            Bottom,
            Left,
            Right,
            Center,
            Num_Locations
        };

        EType type;
        EOrientation orientation;
        float top;
        float left;
        float border;
        float separator_size;
        float gap_size;
#if ENABLE_SVG_ICONS
        float icons_size;
        float scale;
#else
        float icons_scale;
#endif // ENABLE_SVG_ICONS

        float width;
        float height;
        bool dirty;

        Layout();
    };

private:
    typedef std::vector<GLToolbarItem*> ItemsList;

    EType m_type;
#if ENABLE_SVG_ICONS
    std::string m_name;
#endif // ENABLE_SVG_ICONS
    bool m_enabled;
#if ENABLE_SVG_ICONS
    mutable GLTexture m_icons_texture;
    mutable bool m_icons_texture_dirty;
#else
    ItemsIconsTexture m_icons_texture;
#endif // ENABLE_SVG_ICONS
    BackgroundTexture m_background_texture;
    mutable Layout m_layout;

    ItemsList m_items;

    struct MouseCapture
    {
        bool left;
        bool middle;
        bool right;

        bool any() const { return left || middle || right; }
    };

    MouseCapture m_mouse_capture;
    std::string m_tooltip;

public:
#if ENABLE_SVG_ICONS
    GLToolbar(EType type, const std::string& name);
#else
    explicit GLToolbar(EType type);
#endif // ENABLE_SVG_ICONS
    ~GLToolbar();

#if ENABLE_SVG_ICONS
    bool init(const BackgroundTexture::Metadata& background_texture);
#else
    bool init(const ItemsIconsTexture::Metadata& icons_texture, const BackgroundTexture::Metadata& background_texture);
#endif // ENABLE_SVG_ICONS

    Layout::EType get_layout_type() const;
    void set_layout_type(Layout::EType type);
    Layout::EOrientation get_layout_orientation() const;
    void set_layout_orientation(Layout::EOrientation orientation);

    void set_position(float top, float left);
    void set_border(float border);
    void set_separator_size(float size);
    void set_gap_size(float size);
#if ENABLE_SVG_ICONS
    void set_icons_size(float size);
    void set_scale(float scale);
#else
    void set_icons_scale(float scale);
#endif // ENABLE_SVG_ICONS

    bool is_enabled() const;
    void set_enabled(bool enable);

    bool add_item(const GLToolbarItem::Data& data);
    bool add_separator();

    float get_width() const;
    float get_height() const;

    void select_item(const std::string& name);

    bool is_item_pressed(const std::string& name) const;
    bool is_item_disabled(const std::string& name) const;
    bool is_item_visible(const std::string& name) const;

    const std::string& get_tooltip() const { return m_tooltip; }

    // returns true if any item changed its state
    bool update_items_state();

    void render(const GLCanvas3D& parent) const;

    bool on_mouse(wxMouseEvent& evt, GLCanvas3D& parent);

private:
    void calc_layout() const;
    float get_width_horizontal() const;
    float get_width_vertical() const;
    float get_height_horizontal() const;
    float get_height_vertical() const;
    float get_main_size() const;
    void do_action(unsigned int item_id, GLCanvas3D& parent);
    std::string update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent);
    std::string update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D& parent);
    std::string update_hover_state_vertical(const Vec2d& mouse_pos, GLCanvas3D& parent);
    // returns the id of the item under the given mouse position or -1 if none
    int contains_mouse(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
    int contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
    int contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;

    void render_horizontal(const GLCanvas3D& parent) const;
    void render_vertical(const GLCanvas3D& parent) const;

#if ENABLE_SVG_ICONS
    bool generate_icons_texture() const;
#endif // ENABLE_SVG_ICONS

    // returns true if any item changed its state
    bool update_items_visibility();
    // returns true if any item changed its state
    bool update_items_enabled_state();
};

} // namespace GUI
} // namespace Slic3r

#endif // slic3r_GLToolbar_hpp_
<commit_msg>Added missing include<commit_after>#ifndef slic3r_GLToolbar_hpp_
#define slic3r_GLToolbar_hpp_

#include <functional>
#include <string>
#include <vector>

#include "GLTexture.hpp"
#include "Event.hpp"
#include "libslic3r/Point.hpp"

class wxEvtHandler;

namespace Slic3r {
namespace GUI {

class GLCanvas3D;

wxDECLARE_EVENT(EVT_GLTOOLBAR_ADD, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_ARRANGE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_MORE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_FEWER, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_SPLIT_OBJECTS, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_SPLIT_VOLUMES, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_LAYERSEDITING, SimpleEvent);

wxDECLARE_EVENT(EVT_GLVIEWTOOLBAR_3D, SimpleEvent);
wxDECLARE_EVENT(EVT_GLVIEWTOOLBAR_PREVIEW, SimpleEvent);

class GLToolbarItem
{
public:
    typedef std::function<void()> ActionCallback;
    typedef std::function<bool()> VisibilityCallback;
    typedef std::function<bool()> EnabledStateCallback;

    enum EType : unsigned char
    {
        Action,
        Separator,
        Num_Types
    };

    enum EState : unsigned char
    {
        Normal,
        Pressed,
        Disabled,
        Hover,
        HoverPressed,
        Num_States
    };

    struct Data
    {
        std::string name;
#if ENABLE_SVG_ICONS
        std::string icon_filename;
#endif // ENABLE_SVG_ICONS
        std::string tooltip;
        unsigned int sprite_id;
        bool is_toggable;
        bool visible;
        ActionCallback action_callback;
        VisibilityCallback visibility_callback;
        EnabledStateCallback enabled_state_callback;

        Data();
    };

    static const ActionCallback Default_Action_Callback;
    static const VisibilityCallback Default_Visibility_Callback;
    static const EnabledStateCallback Default_Enabled_State_Callback;

private:
    EType m_type;
    EState m_state;
    Data m_data;

public:
    GLToolbarItem(EType type, const Data& data);

    EState get_state() const { return m_state; }
    void set_state(EState state) { m_state = state; }

    const std::string& get_name() const { return m_data.name; }
#if ENABLE_SVG_ICONS
    const std::string& get_icon_filename() const { return m_data.icon_filename; }
#endif // ENABLE_SVG_ICONS
    const std::string& get_tooltip() const { return m_data.tooltip; }

    void do_action() { m_data.action_callback(); }

    bool is_enabled() const { return m_state != Disabled; }
    bool is_disabled() const { return m_state == Disabled; }
    bool is_hovered() const { return (m_state == Hover) || (m_state == HoverPressed); }
    bool is_pressed() const { return (m_state == Pressed) || (m_state == HoverPressed); }

    bool is_toggable() const { return m_data.is_toggable; }
    bool is_visible() const { return m_data.visible; }
    bool is_separator() const { return m_type == Separator; }

    // returns true if the state changes
    bool update_visibility();
    // returns true if the state changes
    bool update_enabled_state();

    void render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const;

private:
    GLTexture::Quad_UVs get_uvs(unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const;
    void set_visible(bool visible) { m_data.visible = visible; }

    friend class GLToolbar;
};

#if !ENABLE_SVG_ICONS
// items icon textures are assumed to be square and all with the same size in pixels, no internal check is done
// icons are layed-out into the texture starting from the top-left corner in the same order as enum GLToolbarItem::EState
// from left to right
struct ItemsIconsTexture
{
    struct Metadata
    {
        // path of the file containing the icons' texture
        std::string filename;
        // size of the square icons, in pixels
        unsigned int icon_size;

        Metadata();
    };

    GLTexture texture;
    Metadata metadata;
};
#endif // !ENABLE_SVG_ICONS

struct BackgroundTexture
{
    struct Metadata
    {
        // path of the file containing the background texture
        std::string filename;
        // size of the left edge, in pixels
        unsigned int left;
        // size of the right edge, in pixels
        unsigned int right;
        // size of the top edge, in pixels
        unsigned int top;
        // size of the bottom edge, in pixels
        unsigned int bottom;

        Metadata();
    };

    GLTexture texture;
    Metadata metadata;
};

class GLToolbar
{
public:
#if ENABLE_SVG_ICONS
    static const float Default_Icons_Size;
#endif // ENABLE_SVG_ICONS

    enum EType : unsigned char
    {
        Normal,
        Radio,
        Num_Types
    };

    struct Layout
    {
        enum EType : unsigned char
        {
            Horizontal,
            Vertical,
            Num_Types
        };

        enum EOrientation : unsigned int
        {
            Top,
            Bottom,
            Left,
            Right,
            Center,
            Num_Locations
        };

        EType type;
        EOrientation orientation;
        float top;
        float left;
        float border;
        float separator_size;
        float gap_size;
#if ENABLE_SVG_ICONS
        float icons_size;
        float scale;
#else
        float icons_scale;
#endif // ENABLE_SVG_ICONS

        float width;
        float height;
        bool dirty;

        Layout();
    };

private:
    typedef std::vector<GLToolbarItem*> ItemsList;

    EType m_type;
#if ENABLE_SVG_ICONS
    std::string m_name;
#endif // ENABLE_SVG_ICONS
    bool m_enabled;
#if ENABLE_SVG_ICONS
    mutable GLTexture m_icons_texture;
    mutable bool m_icons_texture_dirty;
#else
    ItemsIconsTexture m_icons_texture;
#endif // ENABLE_SVG_ICONS
    BackgroundTexture m_background_texture;
    mutable Layout m_layout;

    ItemsList m_items;

    struct MouseCapture
    {
        bool left;
        bool middle;
        bool right;

        bool any() const { return left || middle || right; }
    };

    MouseCapture m_mouse_capture;
    std::string m_tooltip;

public:
#if ENABLE_SVG_ICONS
    GLToolbar(EType type, const std::string& name);
#else
    explicit GLToolbar(EType type);
#endif // ENABLE_SVG_ICONS
    ~GLToolbar();

#if ENABLE_SVG_ICONS
    bool init(const BackgroundTexture::Metadata& background_texture);
#else
    bool init(const ItemsIconsTexture::Metadata& icons_texture, const BackgroundTexture::Metadata& background_texture);
#endif // ENABLE_SVG_ICONS

    Layout::EType get_layout_type() const;
    void set_layout_type(Layout::EType type);
    Layout::EOrientation get_layout_orientation() const;
    void set_layout_orientation(Layout::EOrientation orientation);

    void set_position(float top, float left);
    void set_border(float border);
    void set_separator_size(float size);
    void set_gap_size(float size);
#if ENABLE_SVG_ICONS
    void set_icons_size(float size);
    void set_scale(float scale);
#else
    void set_icons_scale(float scale);
#endif // ENABLE_SVG_ICONS

    bool is_enabled() const;
    void set_enabled(bool enable);

    bool add_item(const GLToolbarItem::Data& data);
    bool add_separator();

    float get_width() const;
    float get_height() const;

    void select_item(const std::string& name);

    bool is_item_pressed(const std::string& name) const;
    bool is_item_disabled(const std::string& name) const;
    bool is_item_visible(const std::string& name) const;

    const std::string& get_tooltip() const { return m_tooltip; }

    // returns true if any item changed its state
    bool update_items_state();

    void render(const GLCanvas3D& parent) const;

    bool on_mouse(wxMouseEvent& evt, GLCanvas3D& parent);

private:
    void calc_layout() const;
    float get_width_horizontal() const;
    float get_width_vertical() const;
    float get_height_horizontal() const;
    float get_height_vertical() const;
    float get_main_size() const;
    void do_action(unsigned int item_id, GLCanvas3D& parent);
    std::string update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent);
    std::string update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D& parent);
    std::string update_hover_state_vertical(const Vec2d& mouse_pos, GLCanvas3D& parent);
    // returns the id of the item under the given mouse position or -1 if none
    int contains_mouse(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
    int contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
    int contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;

    void render_horizontal(const GLCanvas3D& parent) const;
    void render_vertical(const GLCanvas3D& parent) const;

#if ENABLE_SVG_ICONS
    bool generate_icons_texture() const;
#endif // ENABLE_SVG_ICONS

    // returns true if any item changed its state
    bool update_items_visibility();
    // returns true if any item changed its state
    bool update_items_enabled_state();
};

} // namespace GUI
} // namespace Slic3r

#endif // slic3r_GLToolbar_hpp_
<|endoftext|>


<commit_before>#ifndef slic3r_GUI_Utils_hpp_
#define slic3r_GUI_Utils_hpp_

#include <memory>
#include <string>
#include <ostream>
#include <functional>

#include <boost/optional.hpp>

#include <wx/frame.h>
#include <wx/dialog.h>
#include <wx/event.h>
#include <wx/filedlg.h>
#include <wx/gdicmn.h>
#include <wx/panel.h>
#include <wx/dcclient.h>
#include <wx/debug.h>
#include <wx/settings.h>

#include "Event.hpp"

class wxCheckBox;
class wxTopLevelWindow;
class wxRect;

#if ENABLE_WX_3_1_3_DPI_CHANGED_EVENT
#define wxVERSION_EQUAL_OR_GREATER_THAN(major, minor, release) ((wxMAJOR_VERSION > major) || ((wxMAJOR_VERSION == major) && (wxMINOR_VERSION > minor)) || ((wxMAJOR_VERSION == major) && (wxMINOR_VERSION == minor) && (wxRELEASE_NUMBER >= release)))
#else
#define wxVERSION_EQUAL_OR_GREATER_THAN(major, minor, release) 0
#endif // ENABLE_WX_3_1_3_DPI_CHANGED_EVENT

namespace Slic3r {
namespace GUI {

#ifdef _WIN32
// USB HID attach / detach events from Windows OS.
using HIDDeviceAttachedEvent = Event<std::string>;
using HIDDeviceDetachedEvent = Event<std::string>;
wxDECLARE_EVENT(EVT_HID_DEVICE_ATTACHED, HIDDeviceAttachedEvent);
wxDECLARE_EVENT(EVT_HID_DEVICE_DETACHED, HIDDeviceDetachedEvent);

// Disk aka Volume attach / detach events from Windows OS.
using VolumeAttachedEvent = SimpleEvent;
using VolumeDetachedEvent = SimpleEvent;
wxDECLARE_EVENT(EVT_VOLUME_ATTACHED, VolumeAttachedEvent);
wxDECLARE_EVENT(EVT_VOLUME_DETACHED, VolumeDetachedEvent);
#endif /* _WIN32 */

wxTopLevelWindow* find_toplevel_parent(wxWindow *window);

void on_window_geometry(wxTopLevelWindow *tlw, std::function<void()> callback);

enum { DPI_DEFAULT = 96 };

int get_dpi_for_window(wxWindow *window);
wxFont get_default_font_for_dpi(int dpi);

#if !wxVERSION_EQUAL_OR_GREATER_THAN(3,1,3)
struct DpiChangedEvent : public wxEvent {
    int dpi;
    wxRect rect;

    DpiChangedEvent(wxEventType eventType, int dpi, wxRect rect)
        : wxEvent(0, eventType), dpi(dpi), rect(rect)
    {}

    virtual wxEvent *Clone() const
    {
        return new DpiChangedEvent(*this);
    }
};

wxDECLARE_EVENT(EVT_DPI_CHANGED_SLICER, DpiChangedEvent);
#endif // !wxVERSION_EQUAL_OR_GREATER_THAN

template<class P> class DPIAware : public P
{
public:
    DPIAware(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &pos=wxDefaultPosition,
        const wxSize &size=wxDefaultSize, long style=wxDEFAULT_FRAME_STYLE, const wxString &name=wxFrameNameStr)
        : P(parent, id, title, pos, size, style, name)
    {
        int dpi = get_dpi_for_window(this);
        m_scale_factor = (float)dpi / (float)DPI_DEFAULT;
        m_prev_scale_factor = m_scale_factor;
		m_normal_font = get_default_font_for_dpi(dpi);

        /* Because of default window font is a primary display font,
         * We should set correct font for window before getting em_unit value.
         */
#ifndef __WXOSX__ // Don't call SetFont under OSX to avoid name cutting in ObjectList
        this->SetFont(m_normal_font);
#endif
        // initialize default width_unit according to the width of the one symbol ("m") of the currently active font of this window.
#if ENABLE_WX_3_1_3_DPI_CHANGED_EVENT
        m_em_unit = std::max<size_t>(10, 10.0f * m_scale_factor);
#else
        m_em_unit = std::max<size_t>(10, this->GetTextExtent("m").x - 1);
#endif // ENABLE_WX_3_1_3_DPI_CHANGED_EVENT

//        recalc_font();

#if wxVERSION_EQUAL_OR_GREATER_THAN(3,1,3)
        this->Bind(wxEVT_DPI_CHANGED, [this](wxDPIChangedEvent& evt) {
            m_scale_factor = (float)evt.GetNewDPI().x / (float)DPI_DEFAULT;

            m_new_font_point_size = get_default_font_for_dpi(evt.GetNewDPI().x).GetPointSize();

            if (!m_can_rescale)
                return;

#if ENABLE_LAYOUT_NO_RESTART
            if (m_force_rescale || is_new_scale_factor())
                rescale(wxRect());
#else
            if (is_new_scale_factor())
                rescale(wxRect());
#endif // ENABLE_LAYOUT_NO_RESTART
            });
#else
        this->Bind(EVT_DPI_CHANGED_SLICER, [this](const DpiChangedEvent& evt) {
            m_scale_factor = (float)evt.dpi / (float)DPI_DEFAULT;

            m_new_font_point_size = get_default_font_for_dpi(evt.dpi).GetPointSize();

            if (!m_can_rescale)
                return;

#if ENABLE_LAYOUT_NO_RESTART
            if (m_force_rescale || is_new_scale_factor())
                rescale(evt.rect);
#else
            if (is_new_scale_factor())
                rescale(evt.rect);
#endif // ENABLE_LAYOUT_NO_RESTART
            });
#endif // wxVERSION_EQUAL_OR_GREATER_THAN

        this->Bind(wxEVT_MOVE_START, [this](wxMoveEvent& event)
        {
            event.Skip();

            // Suppress application rescaling, when a MainFrame moving is not ended
            m_can_rescale = false;
        });

        this->Bind(wxEVT_MOVE_END, [this](wxMoveEvent& event)
        {
            event.Skip();

            m_can_rescale = is_new_scale_factor();

            // If scale factor is different after moving of MainFrame ...
            if (m_can_rescale)
                // ... rescale application
                rescale(event.GetRect());
            else
            // set value to _true_ in purpose of possibility of a display dpi changing from System Settings
                m_can_rescale = true;
        });

        this->Bind(wxEVT_SYS_COLOUR_CHANGED, [this](wxSysColourChangedEvent& event)
        {
            event.Skip();
            on_sys_color_changed();
        });
    }

    virtual ~DPIAware() {}

    float   scale_factor() const        { return m_scale_factor; }
    float   prev_scale_factor() const   { return m_prev_scale_factor; }

    int     em_unit() const             { return m_em_unit; }
//    int     font_size() const           { return m_font_size; }
    const wxFont& normal_font() const   { return m_normal_font; }
#if ENABLE_LAYOUT_NO_RESTART
    void enable_force_rescale()         { m_force_rescale = true; }
#endif // ENABLE_LAYOUT_NO_RESTART

protected:
    virtual void on_dpi_changed(const wxRect &suggested_rect) = 0;
    virtual void on_sys_color_changed() {};

private:
    float m_scale_factor;
    int m_em_unit;
//    int m_font_size;

    wxFont m_normal_font;
    float m_prev_scale_factor;
    bool  m_can_rescale{ true };
#if ENABLE_LAYOUT_NO_RESTART
    bool m_force_rescale{ false };
#endif // ENABLE_LAYOUT_NO_RESTART

    int   m_new_font_point_size;

//    void recalc_font()
//    {
//        wxClientDC dc(this);
//        const auto metrics = dc.GetFontMetrics();
//        m_font_size = metrics.height;
//         m_em_unit = metrics.averageWidth;
//    }

    // check if new scale is differ from previous
    bool    is_new_scale_factor() const { return fabs(m_scale_factor - m_prev_scale_factor) > 0.001; }

    // function for a font scaling of the window
    void    scale_win_font(wxWindow *window, const int font_point_size)
    {
        wxFont new_font(window->GetFont());
        new_font.SetPointSize(font_point_size);
        window->SetFont(new_font);
    }

    // recursive function for scaling fonts for all controls in Window
    void    scale_controls_fonts(wxWindow *window, const int font_point_size)
    {
        auto children = window->GetChildren();

        for (auto child : children) {
            scale_controls_fonts(child, font_point_size);
            scale_win_font(child, font_point_size);
        }

        window->Layout();
    }

    void    rescale(const wxRect &suggested_rect)
    {
        this->Freeze();

#if ENABLE_LAYOUT_NO_RESTART
        if (m_force_rescale) {
#endif // ENABLE_LAYOUT_NO_RESTART
            // rescale fonts of all controls
            scale_controls_fonts(this, m_new_font_point_size);
            // rescale current window font
            scale_win_font(this, m_new_font_point_size);
#if ENABLE_LAYOUT_NO_RESTART
            m_force_rescale = false;
        }
#endif // ENABLE_LAYOUT_NO_RESTART

        // set normal application font as a current window font
        m_normal_font = this->GetFont();

        // update em_unit value for new window font
#if ENABLE_WX_3_1_3_DPI_CHANGED_EVENT
        m_em_unit = std::max<int>(10, 10.0f * m_scale_factor);
#else
        m_em_unit = std::max<size_t>(10, this->GetTextExtent("m").x - 1);
#endif // ENABLE_WX_3_1_3_DPI_CHANGED_EVENT

        // rescale missed controls sizes and images
        on_dpi_changed(suggested_rect);

        this->Layout();
        this->Thaw();

        // reset previous scale factor from current scale factor value
        m_prev_scale_factor = m_scale_factor;
    }

};

typedef DPIAware<wxFrame> DPIFrame;
typedef DPIAware<wxDialog> DPIDialog;

class EventGuard
{
    // This is a RAII-style smart-ptr-like guard that will bind any event to any event handler
    // and unbind it as soon as it goes out of scope or unbind() is called.
    // This can be used to solve the annoying problem of wx events being delivered to freed objects.

private:
    // This is a way to type-erase both the event type as well as the handler:

    struct EventStorageBase {
        virtual ~EventStorageBase() {}
    };

    template<class EvTag, class Fun>
    struct EventStorageFun : EventStorageBase {
        wxEvtHandler *emitter;
        EvTag tag;
        Fun fun;

        EventStorageFun(wxEvtHandler *emitter, const EvTag &tag, Fun fun)
            : emitter(emitter)
            , tag(tag)
            , fun(std::move(fun))
        {
            emitter->Bind(this->tag, this->fun);
        }

        virtual ~EventStorageFun() { emitter->Unbind(tag, fun); }
    };

    template<typename EvTag, typename Class, typename EvArg, typename EvHandler>
    struct EventStorageMethod : EventStorageBase {
        typedef void(Class::* MethodPtr)(EvArg &);

        wxEvtHandler *emitter;
        EvTag tag;
        MethodPtr method;
        EvHandler *handler;

        EventStorageMethod(wxEvtHandler *emitter, const EvTag &tag, MethodPtr method, EvHandler *handler)
            : emitter(emitter)
            , tag(tag)
            , method(method)
            , handler(handler)
        {
            emitter->Bind(tag, method, handler);
        }

        virtual ~EventStorageMethod() { emitter->Unbind(tag, method, handler); }
    };

    std::unique_ptr<EventStorageBase> event_storage;
public:
    EventGuard() {}
    EventGuard(const EventGuard&) = delete;
    EventGuard(EventGuard &&other) : event_storage(std::move(other.event_storage)) {}

    template<class EvTag, class Fun>
    EventGuard(wxEvtHandler *emitter, const EvTag &tag, Fun fun)
        :event_storage(new EventStorageFun<EvTag, Fun>(emitter, tag, std::move(fun)))
    {}

    template<typename EvTag, typename Class, typename EvArg, typename EvHandler>
    EventGuard(wxEvtHandler *emitter, const EvTag &tag, void(Class::* method)(EvArg &), EvHandler *handler)
        :event_storage(new EventStorageMethod<EvTag, Class, EvArg, EvHandler>(emitter, tag, method, handler))
    {}

    EventGuard& operator=(const EventGuard&) = delete;
    EventGuard& operator=(EventGuard &&other)
    {
        event_storage = std::move(other.event_storage);
        return *this;
    }

    void unbind() { event_storage.reset(nullptr); }
    explicit operator bool() const { return !!event_storage; }
};

class CheckboxFileDialog : public wxFileDialog
{
public:
    CheckboxFileDialog(wxWindow *parent,
        const wxString &checkbox_label,
        bool checkbox_value,
        const wxString &message = wxFileSelectorPromptStr,
        const wxString &default_dir = wxEmptyString,
        const wxString &default_file = wxEmptyString,
        const wxString &wildcard = wxFileSelectorDefaultWildcardStr,
        long style = wxFD_DEFAULT_STYLE,
        const wxPoint &pos = wxDefaultPosition,
        const wxSize &size = wxDefaultSize,
        const wxString &name = wxFileDialogNameStr
    );

    bool get_checkbox_value() const;

private:
    struct ExtraPanel : public wxPanel
    {
        wxCheckBox *cbox;

        ExtraPanel(wxWindow *parent);
        static wxWindow* ctor(wxWindow *parent);
    };

    wxString checkbox_label;
};

class WindowMetrics
{
private:
    wxRect rect;
    bool maximized;

    WindowMetrics() : maximized(false) {}
public:
    static WindowMetrics from_window(wxTopLevelWindow *window);
    static boost::optional<WindowMetrics> deserialize(const std::string &str);

    const wxRect& get_rect() const { return rect; }
    bool get_maximized() const { return maximized; }

    void sanitize_for_display(const wxRect &screen_rect);
    std::string serialize() const;
};

std::ostream& operator<<(std::ostream &os, const WindowMetrics& metrics);

}}

#endif
<commit_msg>Follow-up of e782d34ec81c3f45d1500b8fcc7b82e788047475 -> Fix in DPIAware::rescale()<commit_after>#ifndef slic3r_GUI_Utils_hpp_
#define slic3r_GUI_Utils_hpp_

#include <memory>
#include <string>
#include <ostream>
#include <functional>

#include <boost/optional.hpp>

#include <wx/frame.h>
#include <wx/dialog.h>
#include <wx/event.h>
#include <wx/filedlg.h>
#include <wx/gdicmn.h>
#include <wx/panel.h>
#include <wx/dcclient.h>
#include <wx/debug.h>
#include <wx/settings.h>

#include "Event.hpp"

class wxCheckBox;
class wxTopLevelWindow;
class wxRect;

#if ENABLE_WX_3_1_3_DPI_CHANGED_EVENT
#define wxVERSION_EQUAL_OR_GREATER_THAN(major, minor, release) ((wxMAJOR_VERSION > major) || ((wxMAJOR_VERSION == major) && (wxMINOR_VERSION > minor)) || ((wxMAJOR_VERSION == major) && (wxMINOR_VERSION == minor) && (wxRELEASE_NUMBER >= release)))
#else
#define wxVERSION_EQUAL_OR_GREATER_THAN(major, minor, release) 0
#endif // ENABLE_WX_3_1_3_DPI_CHANGED_EVENT

namespace Slic3r {
namespace GUI {

#ifdef _WIN32
// USB HID attach / detach events from Windows OS.
using HIDDeviceAttachedEvent = Event<std::string>;
using HIDDeviceDetachedEvent = Event<std::string>;
wxDECLARE_EVENT(EVT_HID_DEVICE_ATTACHED, HIDDeviceAttachedEvent);
wxDECLARE_EVENT(EVT_HID_DEVICE_DETACHED, HIDDeviceDetachedEvent);

// Disk aka Volume attach / detach events from Windows OS.
using VolumeAttachedEvent = SimpleEvent;
using VolumeDetachedEvent = SimpleEvent;
wxDECLARE_EVENT(EVT_VOLUME_ATTACHED, VolumeAttachedEvent);
wxDECLARE_EVENT(EVT_VOLUME_DETACHED, VolumeDetachedEvent);
#endif /* _WIN32 */

wxTopLevelWindow* find_toplevel_parent(wxWindow *window);

void on_window_geometry(wxTopLevelWindow *tlw, std::function<void()> callback);

enum { DPI_DEFAULT = 96 };

int get_dpi_for_window(wxWindow *window);
wxFont get_default_font_for_dpi(int dpi);

#if !wxVERSION_EQUAL_OR_GREATER_THAN(3,1,3)
struct DpiChangedEvent : public wxEvent {
    int dpi;
    wxRect rect;

    DpiChangedEvent(wxEventType eventType, int dpi, wxRect rect)
        : wxEvent(0, eventType), dpi(dpi), rect(rect)
    {}

    virtual wxEvent *Clone() const
    {
        return new DpiChangedEvent(*this);
    }
};

wxDECLARE_EVENT(EVT_DPI_CHANGED_SLICER, DpiChangedEvent);
#endif // !wxVERSION_EQUAL_OR_GREATER_THAN

template<class P> class DPIAware : public P
{
public:
    DPIAware(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &pos=wxDefaultPosition,
        const wxSize &size=wxDefaultSize, long style=wxDEFAULT_FRAME_STYLE, const wxString &name=wxFrameNameStr)
        : P(parent, id, title, pos, size, style, name)
    {
        int dpi = get_dpi_for_window(this);
        m_scale_factor = (float)dpi / (float)DPI_DEFAULT;
        m_prev_scale_factor = m_scale_factor;
		m_normal_font = get_default_font_for_dpi(dpi);

        /* Because of default window font is a primary display font,
         * We should set correct font for window before getting em_unit value.
         */
#ifndef __WXOSX__ // Don't call SetFont under OSX to avoid name cutting in ObjectList
        this->SetFont(m_normal_font);
#endif
        // initialize default width_unit according to the width of the one symbol ("m") of the currently active font of this window.
#if ENABLE_WX_3_1_3_DPI_CHANGED_EVENT
        m_em_unit = std::max<size_t>(10, 10.0f * m_scale_factor);
#else
        m_em_unit = std::max<size_t>(10, this->GetTextExtent("m").x - 1);
#endif // ENABLE_WX_3_1_3_DPI_CHANGED_EVENT

//        recalc_font();

#if wxVERSION_EQUAL_OR_GREATER_THAN(3,1,3)
        this->Bind(wxEVT_DPI_CHANGED, [this](wxDPIChangedEvent& evt) {
            m_scale_factor = (float)evt.GetNewDPI().x / (float)DPI_DEFAULT;

            m_new_font_point_size = get_default_font_for_dpi(evt.GetNewDPI().x).GetPointSize();

            if (!m_can_rescale)
                return;

#if ENABLE_LAYOUT_NO_RESTART
            if (m_force_rescale || is_new_scale_factor())
                rescale(wxRect());
#else
            if (is_new_scale_factor())
                rescale(wxRect());
#endif // ENABLE_LAYOUT_NO_RESTART
            });
#else
        this->Bind(EVT_DPI_CHANGED_SLICER, [this](const DpiChangedEvent& evt) {
            m_scale_factor = (float)evt.dpi / (float)DPI_DEFAULT;

            m_new_font_point_size = get_default_font_for_dpi(evt.dpi).GetPointSize();

            if (!m_can_rescale)
                return;

#if ENABLE_LAYOUT_NO_RESTART
            if (m_force_rescale || is_new_scale_factor())
                rescale(evt.rect);
#else
            if (is_new_scale_factor())
                rescale(evt.rect);
#endif // ENABLE_LAYOUT_NO_RESTART
            });
#endif // wxVERSION_EQUAL_OR_GREATER_THAN

        this->Bind(wxEVT_MOVE_START, [this](wxMoveEvent& event)
        {
            event.Skip();

            // Suppress application rescaling, when a MainFrame moving is not ended
            m_can_rescale = false;
        });

        this->Bind(wxEVT_MOVE_END, [this](wxMoveEvent& event)
        {
            event.Skip();

            m_can_rescale = is_new_scale_factor();

            // If scale factor is different after moving of MainFrame ...
            if (m_can_rescale)
                // ... rescale application
                rescale(event.GetRect());
            else
            // set value to _true_ in purpose of possibility of a display dpi changing from System Settings
                m_can_rescale = true;
        });

        this->Bind(wxEVT_SYS_COLOUR_CHANGED, [this](wxSysColourChangedEvent& event)
        {
            event.Skip();
            on_sys_color_changed();
        });
    }

    virtual ~DPIAware() {}

    float   scale_factor() const        { return m_scale_factor; }
    float   prev_scale_factor() const   { return m_prev_scale_factor; }

    int     em_unit() const             { return m_em_unit; }
//    int     font_size() const           { return m_font_size; }
    const wxFont& normal_font() const   { return m_normal_font; }
#if ENABLE_LAYOUT_NO_RESTART
    void enable_force_rescale()         { m_force_rescale = true; }
#endif // ENABLE_LAYOUT_NO_RESTART

protected:
    virtual void on_dpi_changed(const wxRect &suggested_rect) = 0;
    virtual void on_sys_color_changed() {};

private:
    float m_scale_factor;
    int m_em_unit;
//    int m_font_size;

    wxFont m_normal_font;
    float m_prev_scale_factor;
    bool  m_can_rescale{ true };
#if ENABLE_LAYOUT_NO_RESTART
    bool m_force_rescale{ false };
#endif // ENABLE_LAYOUT_NO_RESTART

    int   m_new_font_point_size;

//    void recalc_font()
//    {
//        wxClientDC dc(this);
//        const auto metrics = dc.GetFontMetrics();
//        m_font_size = metrics.height;
//         m_em_unit = metrics.averageWidth;
//    }

    // check if new scale is differ from previous
    bool    is_new_scale_factor() const { return fabs(m_scale_factor - m_prev_scale_factor) > 0.001; }

    // function for a font scaling of the window
    void    scale_win_font(wxWindow *window, const int font_point_size)
    {
        wxFont new_font(window->GetFont());
        new_font.SetPointSize(font_point_size);
        window->SetFont(new_font);
    }

    // recursive function for scaling fonts for all controls in Window
    void    scale_controls_fonts(wxWindow *window, const int font_point_size)
    {
        auto children = window->GetChildren();

        for (auto child : children) {
            scale_controls_fonts(child, font_point_size);
            scale_win_font(child, font_point_size);
        }

        window->Layout();
    }

    void    rescale(const wxRect &suggested_rect)
    {
        this->Freeze();

#if ENABLE_LAYOUT_NO_RESTART && wxVERSION_EQUAL_OR_GREATER_THAN(3,1,3)
        if (m_force_rescale) {
#endif // ENABLE_LAYOUT_NO_RESTART
            // rescale fonts of all controls
            scale_controls_fonts(this, m_new_font_point_size);
            // rescale current window font
            scale_win_font(this, m_new_font_point_size);
#if ENABLE_LAYOUT_NO_RESTART && wxVERSION_EQUAL_OR_GREATER_THAN(3,1,3)
            m_force_rescale = false;
        }
#endif // ENABLE_LAYOUT_NO_RESTART

        // set normal application font as a current window font
        m_normal_font = this->GetFont();

        // update em_unit value for new window font
#if ENABLE_WX_3_1_3_DPI_CHANGED_EVENT
        m_em_unit = std::max<int>(10, 10.0f * m_scale_factor);
#else
        m_em_unit = std::max<size_t>(10, this->GetTextExtent("m").x - 1);
#endif // ENABLE_WX_3_1_3_DPI_CHANGED_EVENT

        // rescale missed controls sizes and images
        on_dpi_changed(suggested_rect);

        this->Layout();
        this->Thaw();

        // reset previous scale factor from current scale factor value
        m_prev_scale_factor = m_scale_factor;
    }

};

typedef DPIAware<wxFrame> DPIFrame;
typedef DPIAware<wxDialog> DPIDialog;

class EventGuard
{
    // This is a RAII-style smart-ptr-like guard that will bind any event to any event handler
    // and unbind it as soon as it goes out of scope or unbind() is called.
    // This can be used to solve the annoying problem of wx events being delivered to freed objects.

private:
    // This is a way to type-erase both the event type as well as the handler:

    struct EventStorageBase {
        virtual ~EventStorageBase() {}
    };

    template<class EvTag, class Fun>
    struct EventStorageFun : EventStorageBase {
        wxEvtHandler *emitter;
        EvTag tag;
        Fun fun;

        EventStorageFun(wxEvtHandler *emitter, const EvTag &tag, Fun fun)
            : emitter(emitter)
            , tag(tag)
            , fun(std::move(fun))
        {
            emitter->Bind(this->tag, this->fun);
        }

        virtual ~EventStorageFun() { emitter->Unbind(tag, fun); }
    };

    template<typename EvTag, typename Class, typename EvArg, typename EvHandler>
    struct EventStorageMethod : EventStorageBase {
        typedef void(Class::* MethodPtr)(EvArg &);

        wxEvtHandler *emitter;
        EvTag tag;
        MethodPtr method;
        EvHandler *handler;

        EventStorageMethod(wxEvtHandler *emitter, const EvTag &tag, MethodPtr method, EvHandler *handler)
            : emitter(emitter)
            , tag(tag)
            , method(method)
            , handler(handler)
        {
            emitter->Bind(tag, method, handler);
        }

        virtual ~EventStorageMethod() { emitter->Unbind(tag, method, handler); }
    };

    std::unique_ptr<EventStorageBase> event_storage;
public:
    EventGuard() {}
    EventGuard(const EventGuard&) = delete;
    EventGuard(EventGuard &&other) : event_storage(std::move(other.event_storage)) {}

    template<class EvTag, class Fun>
    EventGuard(wxEvtHandler *emitter, const EvTag &tag, Fun fun)
        :event_storage(new EventStorageFun<EvTag, Fun>(emitter, tag, std::move(fun)))
    {}

    template<typename EvTag, typename Class, typename EvArg, typename EvHandler>
    EventGuard(wxEvtHandler *emitter, const EvTag &tag, void(Class::* method)(EvArg &), EvHandler *handler)
        :event_storage(new EventStorageMethod<EvTag, Class, EvArg, EvHandler>(emitter, tag, method, handler))
    {}

    EventGuard& operator=(const EventGuard&) = delete;
    EventGuard& operator=(EventGuard &&other)
    {
        event_storage = std::move(other.event_storage);
        return *this;
    }

    void unbind() { event_storage.reset(nullptr); }
    explicit operator bool() const { return !!event_storage; }
};

class CheckboxFileDialog : public wxFileDialog
{
public:
    CheckboxFileDialog(wxWindow *parent,
        const wxString &checkbox_label,
        bool checkbox_value,
        const wxString &message = wxFileSelectorPromptStr,
        const wxString &default_dir = wxEmptyString,
        const wxString &default_file = wxEmptyString,
        const wxString &wildcard = wxFileSelectorDefaultWildcardStr,
        long style = wxFD_DEFAULT_STYLE,
        const wxPoint &pos = wxDefaultPosition,
        const wxSize &size = wxDefaultSize,
        const wxString &name = wxFileDialogNameStr
    );

    bool get_checkbox_value() const;

private:
    struct ExtraPanel : public wxPanel
    {
        wxCheckBox *cbox;

        ExtraPanel(wxWindow *parent);
        static wxWindow* ctor(wxWindow *parent);
    };

    wxString checkbox_label;
};

class WindowMetrics
{
private:
    wxRect rect;
    bool maximized;

    WindowMetrics() : maximized(false) {}
public:
    static WindowMetrics from_window(wxTopLevelWindow *window);
    static boost::optional<WindowMetrics> deserialize(const std::string &str);

    const wxRect& get_rect() const { return rect; }
    bool get_maximized() const { return maximized; }

    void sanitize_for_display(const wxRect &screen_rect);
    std::string serialize() const;
};

std::ostream& operator<<(std::ostream &os, const WindowMetrics& metrics);

}}

#endif
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
// BSD 3-Clause License
//
// Copyright (c) 2018, The Regents of the University of California
// 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 the copyright holder 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 HOLDER 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.
///////////////////////////////////////////////////////////////////////////////

#include "node.h"

namespace pdr {

Node::Node(int _idx, int _x, int _y) :
  idx(_idx),
  x(_x),
  y(_y),
  // magic number alert -cherry
  nn_edge_detcost(8, 10000),
  nn_sw_cost(8, 10000),
  maxPLToChild(0)
{
  parent = 0;
  min_dist = 0;
  path_length = 0;
  detcost_edgePToNode = -1;
  detcost_edgeNodeToP = -1;
  src_to_sink_dist = 0;
  K_t = 1;
  level = 0;
  conn_to_par = false;
  // magic number alert -cherry
  idx_of_cn_x = 105;
  idx_of_cn_y = 105;
};

void Node::report(ostream& os,
                  int level) const
{
  os << idx << " (" << x << ", " << y << ")";
  if (level > 1) {
    os << " parent: " << parent << " children: ";
    for (int i = 0; i < children.size(); ++i) {
      os << children[i] << " ";
    }
  }
  if (level > 2) {
    os << " N: ";
    for (int i = 0; i < N.size(); ++i) {
      os << N[i] << " ";
    }
    os << " S: ";
    for (int i = 0; i < S.size(); ++i) {
      os << S[i] << " ";
    }
    os << " E: ";
    for (int i = 0; i < E.size(); ++i) {
      os << E[i] << " ";
    }
    os << " W: ";
    for (int i = 0; i < W.size(); ++i) {
      os << W[i] << " ";
    }
    os << "PL: " << src_to_sink_dist << " MaxPLToChild: " << maxPLToChild;
  }
}

ostream& operator<<(ostream& os, const Node& n)
{
  n.report(os, 1);
  return os;
}

Node1::Node1(int _idx, int _x, int _y)
{
  idx = _idx;
  x = _x;
  y = _y;
  parent = 0;
}

} // namespace
<commit_msg>pdr::node rm pointless array inits<commit_after>///////////////////////////////////////////////////////////////////////////////
// BSD 3-Clause License
//
// Copyright (c) 2018, The Regents of the University of California
// 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 the copyright holder 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 HOLDER 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.
///////////////////////////////////////////////////////////////////////////////

#include "node.h"

namespace pdr {

Node::Node(int _idx, int _x, int _y) :
  idx(_idx),
  x(_x),
  y(_y),
  maxPLToChild(0)
{
  parent = 0;
  min_dist = 0;
  path_length = 0;
  detcost_edgePToNode = -1;
  detcost_edgeNodeToP = -1;
  src_to_sink_dist = 0;
  K_t = 1;
  level = 0;
  conn_to_par = false;
  // magic number alert -cherry
  idx_of_cn_x = 105;
  idx_of_cn_y = 105;
};

void Node::report(ostream& os,
                  int level) const
{
  os << idx << " (" << x << ", " << y << ")";
  if (level > 1) {
    os << " parent: " << parent << " children: ";
    for (int i = 0; i < children.size(); ++i) {
      os << children[i] << " ";
    }
  }
  if (level > 2) {
    os << " N: ";
    for (int i = 0; i < N.size(); ++i) {
      os << N[i] << " ";
    }
    os << " S: ";
    for (int i = 0; i < S.size(); ++i) {
      os << S[i] << " ";
    }
    os << " E: ";
    for (int i = 0; i < E.size(); ++i) {
      os << E[i] << " ";
    }
    os << " W: ";
    for (int i = 0; i < W.size(); ++i) {
      os << W[i] << " ";
    }
    os << "PL: " << src_to_sink_dist << " MaxPLToChild: " << maxPLToChild;
  }
}

ostream& operator<<(ostream& os, const Node& n)
{
  n.report(os, 1);
  return os;
}

Node1::Node1(int _idx, int _x, int _y)
{
  idx = _idx;
  x = _x;
  y = _y;
  parent = 0;
}

} // namespace
<|endoftext|>


<commit_before>#include "OpenGLSystem.h"
#include "GLSLShader.h"
#include "GLSixDOFView.h"
#include "../components/GLSprite.h"
#include "../components/GLIcoSphere.h"
#include "../components/GLCubeSphere.h"
#include "../components/GLMesh.h"

OpenGLSystem::OpenGLSystem() : windowWidth(800), windowHeight(600), deltaAccumulator(0.0) {
	this->view = new GLSixDOFView();
}

OpenGLSystem::~OpenGLSystem() {
	delete this->view;
}

std::map<std::string,IFactory::FactoryFunction>
        OpenGLSystem::getFactoryFunctions()
{
    using namespace std::placeholders;
    std::map<std::string,IFactory::FactoryFunction> retval;
	retval["GLSprite"] = std::bind(&OpenGLSystem::createGLSprite,this,_1,_2,_3);
    retval["GLIcoSphere"] = std::bind(&OpenGLSystem::createGLIcoSphere,this,_1,_2,_3);
    retval["GLCubeSphere"] = std::bind(&OpenGLSystem::createGLCubeSphere,this,_1,_2,_3);
    retval["GLMesh"] = std::bind(&OpenGLSystem::createGLMesh,this,_1,_2,_3);

	// Not supported in VS2012
    /*{
        {"GLSprite",std::bind(&OpenGLSystem::createGLSprite,this,_1,_2,_3)},
        {"GLIcoSphere",std::bind(&OpenGLSystem::createGLIcoSphere,this,_1,_2,_3)},
        {"GLCubeSphere",std::bind(&OpenGLSystem::createGLCubeSphere,this,_1,_2,_3)},
        {"GLMesh",std::bind(&OpenGLSystem::createGLMesh,this,_1,_2,_3)}
    };*/
    return retval;
}

void OpenGLSystem::createGLSprite(const std::string type, const unsigned int entityID, std::vector<Property> &properties) {
		GLSprite* spr = new GLSprite(entityID);
		spr->InitializeBuffers();
		if (entityID == 2) {
			spr->Transform()->Translate(2,2,0);
		}
		spr->Transform()->Translate(0,0,0);
		this->addComponent(entityID,spr);
}

void OpenGLSystem::createGLIcoSphere(const std::string type, const unsigned int entityID, std::vector<Property> &properties) {
		GLIcoSphere* sphere = new GLIcoSphere(entityID);
		sphere->InitializeBuffers();
		float scale = 1.0f;
		float x = 0.0f;
		float y = 0.0f;
		float z = 0.0f;
		int componentID = 0;
		for (auto propitr = properties.begin(); propitr != properties.end(); ++propitr) {
			Property*  p = &(*propitr);
			if (p->GetName() == "scale") {
				scale = p->Get<float>();
				continue;
			} else if (p->GetName() == "x") {
				x = p->Get<float>();
				continue;
			} else if (p->GetName() == "y") {
				y = p->Get<float>();
				continue;
			} else if (p->GetName() == "z") {
				z = p->Get<float>();
				continue;
			} else if (p->GetName() == "id") {
				componentID = p->Get<int>();
			}
		}
		sphere->Transform()->Scale(scale,scale,scale);
		sphere->Transform()->Translate(x,y,z);
		this->addComponent(entityID,sphere);
}

void OpenGLSystem::createGLCubeSphere(const std::string type, const unsigned int entityID, std::vector<Property> &properties) {
		GLCubeSphere* sphere = new GLCubeSphere(entityID);

		std::string texture_name = "";
		std::string shader_name = "";
		std::string cull_face = "back";
		int subdivision_levels = 1;
		float rotation_speed = 0.0f;
		bool fix_to_camera = false;

		float scale = 1.0f;
		float x = 0.0f;
		float y = 0.0f;
		float z = 0.0f;
		int componentID = 0;
		for (auto propitr = properties.begin(); propitr != properties.end(); ++propitr) {
			Property*  p = &(*propitr);
			if (p->GetName() == "scale") {
				scale = p->Get<float>();
				continue;
			} else if (p->GetName() == "x") {
				x = p->Get<float>();
				continue;
			} else if (p->GetName() == "y") {
				y = p->Get<float>();
				continue;
			} else if (p->GetName() == "z") {
				z = p->Get<float>();
				continue;
			} else if (p->GetName() == "subdivision_levels") {
				subdivision_levels = p->Get<int>();
			} else if (p->GetName() == "texture_name") {
				texture_name = p->Get<std::string>();
			} else if (p->GetName() == "shader") {
				shader_name = p->Get<std::string>();
			} else if (p->GetName() == "id") {
				componentID = p->Get<int>();
			} else if (p->GetName() == "cullface") {
				cull_face = p->Get<std::string>();
			} else if (p->GetName() == "rotation_speed") {
				rotation_speed = p->Get<float>();
			} else if (p->GetName() == "fix_to_camera") {
				fix_to_camera = p->Get<bool>();
			}
		}

		sphere->SetFixToCamera(fix_to_camera);
		sphere->SetRotationSpeed(rotation_speed);
		sphere->SetCullFace(cull_face);
		sphere->SetSubdivisions(subdivision_levels);
		sphere->LoadShader(shader_name);
		sphere->InitializeBuffers();
		sphere->LoadTexture(texture_name);

		sphere->Transform()->Scale(scale,scale,scale);
		sphere->Transform()->Translate(x,y,z);
		this->addComponent(entityID,sphere);
}
void OpenGLSystem::createGLMesh(const std::string type, const unsigned int entityID, std::vector<Property> &properties) {
        GLMesh* mesh = new GLMesh(entityID);

		float scale = 1.0f;
		float x = 0.0f;
		float y = 0.0f;
		float z = 0.0f;
		float rx = 0.0f;
		float ry = 0.0f;
		float rz = 0.0f;
		int componentID = 0;
		std::string cull_face = "back";

		for (auto propitr = properties.begin(); propitr != properties.end(); ++propitr) {
			Property*  p = &*propitr;
			if (p->GetName() == "scale") {
				scale = p->Get<float>();
				continue;
			} else if (p->GetName() == "x") {
				x = p->Get<float>();
				continue;
			} else if (p->GetName() == "y") {
				y = p->Get<float>();
				continue;
			} else if (p->GetName() == "z") {
				z = p->Get<float>();
				continue;
			} else if (p->GetName() == "rx") {
				rx = p->Get<float>();
				continue;
			} else if (p->GetName() == "ry") {
				ry = p->Get<float>();
				continue;
			} else if (p->GetName() == "rz") {
				rz = p->Get<float>();
				continue;
			} else if (p->GetName() == "meshFile") {
				mesh->LoadMesh(p->Get<std::string>());
			} else if (p->GetName() == "id") {
				componentID = p->Get<int>();
			} else if (p->GetName() == "cullface") {
				cull_face = p->Get<std::string>();
			}
		}

		mesh->InitializeBuffers();
		mesh->SetCullFace(cull_face);
		mesh->Transform()->Scale(scale,scale,scale);
		mesh->Transform()->Translate(x,y,z);
		mesh->Transform()->Rotate(rx,ry,rz);
		this->addComponent(entityID,mesh);
}

bool OpenGLSystem::Update(const double delta) {
	this->deltaAccumulator += delta;
	this->view->UpdateViewMatrix();

	// Check if the deltaAccumulator is greater than 1/60 of a second.
	if (deltaAccumulator > 16.7) {
		this->view->UpdateViewMatrix();
		// Set up the scene to a "clean" state.
		glClearColor(0.0f,0.0f,0.0f,0.0f);
		glViewport(0, 0, windowWidth, windowHeight); // Set the viewport size to fill the window
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // Clear required buffers

		// Set the ViewProjection matrix to be used in the shader.
		// Loop through and draw each component.
		for (auto eitr = this->_Components.begin(); eitr != this->_Components.end(); ++eitr) {
			for (auto citr = eitr->second.begin(); citr != eitr->second.end(); ++citr) {
				citr->second->Render(&this->view->ViewMatrix[0][0], &this->ProjectionMatrix[0][0]);
			}
		}

		this->deltaAccumulator = 0.0;
		return true;
	}
	return false;
}

const int* OpenGLSystem::Start() {
	//Checking GL version
	const GLubyte *GLVersionString = glGetString(GL_VERSION);

	//Or better yet, use the GL3 way to get the version number
	glGetIntegerv(GL_MAJOR_VERSION, &OpenGLVersion[0]);
	glGetIntegerv(GL_MINOR_VERSION, &OpenGLVersion[1]);

	// Now that GL is up and running load the shaders
	GLSprite::LoadShader();
	GLIcoSphere::LoadShader();

	// Generates a floatly hard-to-read matrix, but a normal, standard 4x4 matrix nonetheless
	this->ProjectionMatrix = glm::perspective(
		45.0f,
		(float)this->windowWidth / (float)this->windowHeight,
		0.1f,
		10000.0f
		);

	this->view->Move(4.0f,3.0f,-10.f);

	// App specific global gl settings
	glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
	glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
	glEnable(GL_MULTISAMPLE_ARB);
	glEnable(GL_CULL_FACE);
	glCullFace(GL_BACK);

	return OpenGLVersion;
}

void OpenGLSystem::Move(float x, float y, float z) {
	this->view->Move(x,y,z);
}

void OpenGLSystem::Rotate(float x, float y, float z) {
	this->view->Rotate(x,y,z);
}

void OpenGLSystem::SetViewportSize(const unsigned int width, const unsigned int height) {
	this->windowHeight = height;
	this->windowWidth = width;
	this->ProjectionMatrix = glm::perspective(
		45.0f,
		(float)this->windowWidth / (float)this->windowHeight,
		0.1f,
		10000.0f
		);
}
<commit_msg>Moved camera start height higher<commit_after>#include "OpenGLSystem.h"
#include "GLSLShader.h"
#include "GLSixDOFView.h"
#include "../components/GLSprite.h"
#include "../components/GLIcoSphere.h"
#include "../components/GLCubeSphere.h"
#include "../components/GLMesh.h"

OpenGLSystem::OpenGLSystem() : windowWidth(800), windowHeight(600), deltaAccumulator(0.0) {
	this->view = new GLSixDOFView();
}

OpenGLSystem::~OpenGLSystem() {
	delete this->view;
}

std::map<std::string,IFactory::FactoryFunction>
        OpenGLSystem::getFactoryFunctions()
{
    using namespace std::placeholders;
    std::map<std::string,IFactory::FactoryFunction> retval;
	retval["GLSprite"] = std::bind(&OpenGLSystem::createGLSprite,this,_1,_2,_3);
    retval["GLIcoSphere"] = std::bind(&OpenGLSystem::createGLIcoSphere,this,_1,_2,_3);
    retval["GLCubeSphere"] = std::bind(&OpenGLSystem::createGLCubeSphere,this,_1,_2,_3);
    retval["GLMesh"] = std::bind(&OpenGLSystem::createGLMesh,this,_1,_2,_3);

	// Not supported in VS2012
    /*{
        {"GLSprite",std::bind(&OpenGLSystem::createGLSprite,this,_1,_2,_3)},
        {"GLIcoSphere",std::bind(&OpenGLSystem::createGLIcoSphere,this,_1,_2,_3)},
        {"GLCubeSphere",std::bind(&OpenGLSystem::createGLCubeSphere,this,_1,_2,_3)},
        {"GLMesh",std::bind(&OpenGLSystem::createGLMesh,this,_1,_2,_3)}
    };*/
    return retval;
}

void OpenGLSystem::createGLSprite(const std::string type, const unsigned int entityID, std::vector<Property> &properties) {
		GLSprite* spr = new GLSprite(entityID);
		spr->InitializeBuffers();
		if (entityID == 2) {
			spr->Transform()->Translate(2,2,0);
		}
		spr->Transform()->Translate(0,0,0);
		this->addComponent(entityID,spr);
}

void OpenGLSystem::createGLIcoSphere(const std::string type, const unsigned int entityID, std::vector<Property> &properties) {
		GLIcoSphere* sphere = new GLIcoSphere(entityID);
		sphere->InitializeBuffers();
		float scale = 1.0f;
		float x = 0.0f;
		float y = 0.0f;
		float z = 0.0f;
		int componentID = 0;
		for (auto propitr = properties.begin(); propitr != properties.end(); ++propitr) {
			Property*  p = &(*propitr);
			if (p->GetName() == "scale") {
				scale = p->Get<float>();
				continue;
			} else if (p->GetName() == "x") {
				x = p->Get<float>();
				continue;
			} else if (p->GetName() == "y") {
				y = p->Get<float>();
				continue;
			} else if (p->GetName() == "z") {
				z = p->Get<float>();
				continue;
			} else if (p->GetName() == "id") {
				componentID = p->Get<int>();
			}
		}
		sphere->Transform()->Scale(scale,scale,scale);
		sphere->Transform()->Translate(x,y,z);
		this->addComponent(entityID,sphere);
}

void OpenGLSystem::createGLCubeSphere(const std::string type, const unsigned int entityID, std::vector<Property> &properties) {
		GLCubeSphere* sphere = new GLCubeSphere(entityID);

		std::string texture_name = "";
		std::string shader_name = "";
		std::string cull_face = "back";
		int subdivision_levels = 1;
		float rotation_speed = 0.0f;
		bool fix_to_camera = false;

		float scale = 1.0f;
		float x = 0.0f;
		float y = 0.0f;
		float z = 0.0f;
		int componentID = 0;
		for (auto propitr = properties.begin(); propitr != properties.end(); ++propitr) {
			Property*  p = &(*propitr);
			if (p->GetName() == "scale") {
				scale = p->Get<float>();
				continue;
			} else if (p->GetName() == "x") {
				x = p->Get<float>();
				continue;
			} else if (p->GetName() == "y") {
				y = p->Get<float>();
				continue;
			} else if (p->GetName() == "z") {
				z = p->Get<float>();
				continue;
			} else if (p->GetName() == "subdivision_levels") {
				subdivision_levels = p->Get<int>();
			} else if (p->GetName() == "texture_name") {
				texture_name = p->Get<std::string>();
			} else if (p->GetName() == "shader") {
				shader_name = p->Get<std::string>();
			} else if (p->GetName() == "id") {
				componentID = p->Get<int>();
			} else if (p->GetName() == "cullface") {
				cull_face = p->Get<std::string>();
			} else if (p->GetName() == "rotation_speed") {
				rotation_speed = p->Get<float>();
			} else if (p->GetName() == "fix_to_camera") {
				fix_to_camera = p->Get<bool>();
			}
		}

		sphere->SetFixToCamera(fix_to_camera);
		sphere->SetRotationSpeed(rotation_speed);
		sphere->SetCullFace(cull_face);
		sphere->SetSubdivisions(subdivision_levels);
		sphere->LoadShader(shader_name);
		sphere->InitializeBuffers();
		sphere->LoadTexture(texture_name);

		sphere->Transform()->Scale(scale,scale,scale);
		sphere->Transform()->Translate(x,y,z);
		this->addComponent(entityID,sphere);
}
void OpenGLSystem::createGLMesh(const std::string type, const unsigned int entityID, std::vector<Property> &properties) {
        GLMesh* mesh = new GLMesh(entityID);

		float scale = 1.0f;
		float x = 0.0f;
		float y = 0.0f;
		float z = 0.0f;
		float rx = 0.0f;
		float ry = 0.0f;
		float rz = 0.0f;
		int componentID = 0;
		std::string cull_face = "back";

		for (auto propitr = properties.begin(); propitr != properties.end(); ++propitr) {
			Property*  p = &*propitr;
			if (p->GetName() == "scale") {
				scale = p->Get<float>();
				continue;
			} else if (p->GetName() == "x") {
				x = p->Get<float>();
				continue;
			} else if (p->GetName() == "y") {
				y = p->Get<float>();
				continue;
			} else if (p->GetName() == "z") {
				z = p->Get<float>();
				continue;
			} else if (p->GetName() == "rx") {
				rx = p->Get<float>();
				continue;
			} else if (p->GetName() == "ry") {
				ry = p->Get<float>();
				continue;
			} else if (p->GetName() == "rz") {
				rz = p->Get<float>();
				continue;
			} else if (p->GetName() == "meshFile") {
				mesh->LoadMesh(p->Get<std::string>());
			} else if (p->GetName() == "id") {
				componentID = p->Get<int>();
			} else if (p->GetName() == "cullface") {
				cull_face = p->Get<std::string>();
			}
		}

		mesh->InitializeBuffers();
		mesh->SetCullFace(cull_face);
		mesh->Transform()->Scale(scale,scale,scale);
		mesh->Transform()->Translate(x,y,z);
		mesh->Transform()->Rotate(rx,ry,rz);
		this->addComponent(entityID,mesh);
}

bool OpenGLSystem::Update(const double delta) {
	this->deltaAccumulator += delta;
	this->view->UpdateViewMatrix();

	// Check if the deltaAccumulator is greater than 1/60 of a second.
	if (deltaAccumulator > 16.7) {
		this->view->UpdateViewMatrix();
		// Set up the scene to a "clean" state.
		glClearColor(0.0f,0.0f,0.0f,0.0f);
		glViewport(0, 0, windowWidth, windowHeight); // Set the viewport size to fill the window
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // Clear required buffers

		// Set the ViewProjection matrix to be used in the shader.
		// Loop through and draw each component.
		for (auto eitr = this->_Components.begin(); eitr != this->_Components.end(); ++eitr) {
			for (auto citr = eitr->second.begin(); citr != eitr->second.end(); ++citr) {
				citr->second->Render(&this->view->ViewMatrix[0][0], &this->ProjectionMatrix[0][0]);
			}
		}

		this->deltaAccumulator = 0.0;
		return true;
	}
	return false;
}

const int* OpenGLSystem::Start() {
	//Checking GL version
	const GLubyte *GLVersionString = glGetString(GL_VERSION);

	//Or better yet, use the GL3 way to get the version number
	glGetIntegerv(GL_MAJOR_VERSION, &OpenGLVersion[0]);
	glGetIntegerv(GL_MINOR_VERSION, &OpenGLVersion[1]);

	// Now that GL is up and running load the shaders
	GLSprite::LoadShader();
	GLIcoSphere::LoadShader();

	// Generates a floatly hard-to-read matrix, but a normal, standard 4x4 matrix nonetheless
	this->ProjectionMatrix = glm::perspective(
		45.0f,
		(float)this->windowWidth / (float)this->windowHeight,
		0.1f,
		10000.0f
		);

	this->view->Move(4.0f,50.0f,-10.f);

	// App specific global gl settings
	glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
	glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
	glEnable(GL_MULTISAMPLE_ARB);
	glEnable(GL_CULL_FACE);
	glCullFace(GL_BACK);

	return OpenGLVersion;
}

void OpenGLSystem::Move(float x, float y, float z) {
	this->view->Move(x,y,z);
}

void OpenGLSystem::Rotate(float x, float y, float z) {
	this->view->Rotate(x,y,z);
}

void OpenGLSystem::SetViewportSize(const unsigned int width, const unsigned int height) {
	this->windowHeight = height;
	this->windowWidth = width;
	this->ProjectionMatrix = glm::perspective(
		45.0f,
		(float)this->windowWidth / (float)this->windowHeight,
		0.1f,
		10000.0f
		);
}
<|endoftext|>