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

#include <QApplication>
#include <QTimer>

#include <boost/program_options.hpp>

#include <OgreMaterialManager.h>
#include <OgreGpuProgramManager.h>
#include <OgreHighLevelGpuProgramManager.h>
#include <std_srvs/Empty.h>

#ifdef Q_OS_MAC
#include <ApplicationServices/ApplicationServices.h>
// Apparently OSX #defines 'check' to be an empty string somewhere.
// That was fun to figure out.
#undef check
#endif

#include <ros/console.h>
#include <ros/ros.h>

#include "rviz/selection/selection_manager.h"
#include "rviz/env_config.h"
#include "rviz/ogre_helpers/ogre_logging.h"
#include "rviz/visualization_frame.h"
#include "rviz/visualization_manager.h"
#include "rviz/wait_for_master_dialog.h"
#include "rviz/ogre_helpers/render_system.h"

#include "rviz/visualizer_app.h"

#define CATCH_EXCEPTIONS 0

namespace po = boost::program_options;

namespace rviz
{

bool reloadShaders(std_srvs::Empty::Request&, std_srvs::Empty::Response&)
{
  ROS_INFO("Reloading materials.");
  {
  Ogre::ResourceManager::ResourceMapIterator it = Ogre::MaterialManager::getSingleton().getResourceIterator();
  while (it.hasMoreElements())
  {
    Ogre::ResourcePtr resource = it.getNext();
    resource->reload();
  }
  }
  ROS_INFO("Reloading high-level gpu shaders.");
  {
  Ogre::ResourceManager::ResourceMapIterator it = Ogre::HighLevelGpuProgramManager::getSingleton().getResourceIterator();
  while (it.hasMoreElements())
  {
    Ogre::ResourcePtr resource = it.getNext();
    resource->reload();
  }
  }
  ROS_INFO("Reloading gpu shaders.");
  {
  Ogre::ResourceManager::ResourceMapIterator it = Ogre::GpuProgramManager::getSingleton().getResourceIterator();
  while (it.hasMoreElements())
  {
    Ogre::ResourcePtr resource = it.getNext();
    resource->reload();
  }
  }
  return true;
}

VisualizerApp::VisualizerApp()
  : app_( 0 )
  , continue_timer_( 0 )
  , frame_( 0 )
{
}

void VisualizerApp::setApp( QApplication * app )
{
  app_ = app;
}

bool VisualizerApp::init( int argc, char** argv )
{
  ROS_INFO( "rviz version %s", get_version().c_str() );
  ROS_INFO( "compiled against Qt version " QT_VERSION_STR );
  ROS_INFO( "compiled against OGRE version %d.%d.%d%s (%s)",
            OGRE_VERSION_MAJOR, OGRE_VERSION_MINOR, OGRE_VERSION_PATCH,
            OGRE_VERSION_SUFFIX, OGRE_VERSION_NAME );

#ifdef Q_OS_MAC
  ProcessSerialNumber PSN;
  GetCurrentProcess(&PSN);
  TransformProcessType(&PSN,kProcessTransformToForegroundApplication);
  SetFrontProcess(&PSN);
#endif

#if CATCH_EXCEPTIONS
  try
  {
#endif
    ros::init( argc, argv, "rviz", ros::init_options::AnonymousName );

    startContinueChecker();

    po::options_description options;
    options.add_options()
      ("help,h", "Produce this help message")
      ("splash-screen,s", po::value<std::string>(), "A custom splash-screen image to display")
      ("help-file", po::value<std::string>(), "A custom html file to show as the help screen")
      ("display-config,d", po::value<std::string>(), "A display config file (.rviz) to load")
      ("fixed-frame,f", po::value<std::string>(), "Set the fixed frame")
      ("ogre-log,l", "Enable the Ogre.log file (output in cwd) and console output.")
      ("in-mc-wrapper", "Signal that this is running inside a master-chooser wrapper")
      ("opengl", po::value<int>(), "Force OpenGL version (use '--opengl 210' for OpenGL 2.1 compatibility mode)")
      ("disable-anti-aliasing", "Prevent rviz from trying to use anti-aliasing when rendering.")
      ("no-stereo", "Disable the use of stereo rendering.")
      ("verbose,v", "Enable debug visualizations")
      ("log-level-debug", "Sets the ROS logger level to debug.");
    po::variables_map vm;
    std::string display_config, fixed_frame, splash_path, help_path;
    bool enable_ogre_log = false;
    bool in_mc_wrapper = false;
    bool verbose = false;
    int force_gl_version = 0;
    bool disable_anti_aliasing = false;
    bool disable_stereo = false;
    try
    {
      po::store( po::parse_command_line( argc, argv, options ), vm );
      po::notify( vm );

      if( vm.count( "help" ))
      {
        std::cout << "rviz command line options:\n" << options;
        return false;
      }

      if( vm.count( "in-mc-wrapper" ))
      {
        in_mc_wrapper = true;
      }

      if (vm.count("display-config"))
      {
        display_config = vm["display-config"].as<std::string>();
        if( display_config.substr( display_config.size() - 4, 4 ) == ".vcg" )
        {
          std::cerr << "ERROR: the config file '" << display_config << "' is a .vcg file, which is the old rviz config format." << std::endl;
          std::cerr << "       New config files have a .rviz extension and use YAML formatting.  The format changed" << std::endl;
          std::cerr << "       between Fuerte and Groovy.  There is not (yet) an automated conversion program." << std::endl;
          return false;
        }
      }

      if (vm.count("splash-screen"))
      {
        splash_path = vm["splash-screen"].as<std::string>();
      }

      if (vm.count("help-file"))
      {
        help_path = vm["help-file"].as<std::string>();
      }

      if (vm.count("fixed-frame"))
      {
        fixed_frame = vm["fixed-frame"].as<std::string>();
      }

      if (vm.count("ogre-log"))
      {
        enable_ogre_log = true;
      }

      if (vm.count("no-stereo"))
      {
        disable_stereo = true;
      }

      if (vm.count("opengl"))
      {
        //std::cout << vm["opengl"].as<std::string>() << std::endl;
        force_gl_version = vm["opengl"].as<int>();
      }

      if (vm.count("disable-anti-aliasing"))
      {
        disable_anti_aliasing = true;
      }

      if (vm.count("verbose"))
      {
        verbose = true;
      }

      if (vm.count("log-level-debug"))
      {
        if( ros::console::set_logger_level(ROSCONSOLE_DEFAULT_NAME, ros::console::levels::Debug) )
        {
          ros::console::notifyLoggerLevelsChanged();
        }
      }
    }
    catch (std::exception& e)
    {
      ROS_ERROR("Error parsing command line: %s", e.what());
      return false;
    }

    if( !ros::master::check() )
    {
      WaitForMasterDialog* dialog = new WaitForMasterDialog;
      if( dialog->exec() != QDialog::Accepted )
      {
        return false;
      }
    }

    nh_.reset( new ros::NodeHandle );

    if( enable_ogre_log )
    {
      OgreLogging::useRosLog();
    }

    if ( force_gl_version )
    {
      RenderSystem::forceGlVersion( force_gl_version );
    }

    if (disable_anti_aliasing)
    {
      RenderSystem::disableAntiAliasing();
    }

    if ( disable_stereo )
    {
      RenderSystem::forceNoStereo();
    }

    frame_ = new VisualizationFrame();
    frame_->setApp( this->app_ );
    if( help_path != "" )
    {
      frame_->setHelpPath( QString::fromStdString( help_path ));
    }
    frame_->setShowChooseNewMaster( in_mc_wrapper );
    if( splash_path != "" )
    {
      frame_->setSplashPath( QString::fromStdString( splash_path ));
    }
    frame_->initialize( QString::fromStdString( display_config ));
    if( !fixed_frame.empty() )
    {
      frame_->getManager()->setFixedFrame( QString::fromStdString( fixed_frame ));
    }

    frame_->getManager()->getSelectionManager()->setDebugMode( verbose );

    frame_->show();

    ros::NodeHandle private_nh("~");
    reload_shaders_service_ = private_nh.advertiseService("reload_shaders", reloadShaders);

#if CATCH_EXCEPTIONS
  }
  catch (std::exception& e)
  {
    ROS_ERROR("Caught exception while loading: %s", e.what());
    return false;
  }
#endif
  return true;
}

VisualizerApp::~VisualizerApp()
{
  delete continue_timer_;
  delete frame_;
}

void VisualizerApp::startContinueChecker()
{
  continue_timer_ = new QTimer( this );
  connect( continue_timer_, SIGNAL( timeout() ), this, SLOT( checkContinue() ));
  continue_timer_->start( 100 );
}

void VisualizerApp::checkContinue()
{
  if( !ros::ok() )
  {
    if( frame_ )
    {
      // Make sure the window doesn't ask if we want to save first.
      frame_->setWindowModified( false );
    }
    QApplication::closeAllWindows();
  }
}

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

#include <QApplication>
#include <QTimer>

#include <boost/program_options.hpp>

#include <OgreMaterialManager.h>
#include <OgreGpuProgramManager.h>
#include <OgreHighLevelGpuProgramManager.h>
#include <std_srvs/Empty.h>

#ifdef Q_OS_MAC
#include <ApplicationServices/ApplicationServices.h>
// Apparently OSX #defines 'check' to be an empty string somewhere.
// That was fun to figure out.
#undef check
#endif

#include <ros/console.h>
#include <ros/ros.h>

#include "rviz/selection/selection_manager.h"
#include "rviz/env_config.h"
#include "rviz/ogre_helpers/ogre_logging.h"
#include "rviz/visualization_frame.h"
#include "rviz/visualization_manager.h"
#include "rviz/wait_for_master_dialog.h"
#include "rviz/ogre_helpers/render_system.h"

#include "rviz/visualizer_app.h"

#define CATCH_EXCEPTIONS 0

namespace po = boost::program_options;

namespace rviz
{

bool reloadShaders(std_srvs::Empty::Request&, std_srvs::Empty::Response&)
{
  ROS_INFO("Reloading materials.");
  {
  Ogre::ResourceManager::ResourceMapIterator it = Ogre::MaterialManager::getSingleton().getResourceIterator();
  while (it.hasMoreElements())
  {
    Ogre::ResourcePtr resource = it.getNext();
    resource->reload();
  }
  }
  ROS_INFO("Reloading high-level gpu shaders.");
  {
  Ogre::ResourceManager::ResourceMapIterator it = Ogre::HighLevelGpuProgramManager::getSingleton().getResourceIterator();
  while (it.hasMoreElements())
  {
    Ogre::ResourcePtr resource = it.getNext();
    resource->reload();
  }
  }
  ROS_INFO("Reloading gpu shaders.");
  {
  Ogre::ResourceManager::ResourceMapIterator it = Ogre::GpuProgramManager::getSingleton().getResourceIterator();
  while (it.hasMoreElements())
  {
    Ogre::ResourcePtr resource = it.getNext();
    resource->reload();
  }
  }
  return true;
}

VisualizerApp::VisualizerApp()
  : app_( 0 )
  , continue_timer_( 0 )
  , frame_( 0 )
{
}

void VisualizerApp::setApp( QApplication * app )
{
  app_ = app;
}

bool VisualizerApp::init( int argc, char** argv )
{
  ROS_INFO( "rviz version %s", get_version().c_str() );
  ROS_INFO( "compiled against Qt version " QT_VERSION_STR );
  ROS_INFO( "compiled against OGRE version %d.%d.%d%s (%s)",
            OGRE_VERSION_MAJOR, OGRE_VERSION_MINOR, OGRE_VERSION_PATCH,
            OGRE_VERSION_SUFFIX, OGRE_VERSION_NAME );

#ifdef Q_OS_MAC
  ProcessSerialNumber PSN;
  GetCurrentProcess(&PSN);
  TransformProcessType(&PSN,kProcessTransformToForegroundApplication);
  SetFrontProcess(&PSN);
#endif

#if CATCH_EXCEPTIONS
  try
  {
#endif
    ros::init( argc, argv, "rviz", ros::init_options::AnonymousName );

    startContinueChecker();

    po::options_description options;
    options.add_options()
      ("help,h", "Produce this help message")
      ("splash-screen,s", po::value<std::string>(), "A custom splash-screen image to display")
      ("help-file", po::value<std::string>(), "A custom html file to show as the help screen")
      ("display-config,d", po::value<std::string>(), "A display config file (.rviz) to load")
      ("fixed-frame,f", po::value<std::string>(), "Set the fixed frame")
      ("ogre-log,l", "Enable the Ogre.log file (output in cwd) and console output.")
      ("in-mc-wrapper", "Signal that this is running inside a master-chooser wrapper")
      ("opengl", po::value<int>(), "Force OpenGL version (use '--opengl 210' for OpenGL 2.1 compatibility mode)")
      ("disable-anti-aliasing", "Prevent rviz from trying to use anti-aliasing when rendering.")
      ("no-stereo", "Disable the use of stereo rendering.")
      ("verbose,v", "Enable debug visualizations")
      ("log-level-debug", "Sets the ROS logger level to debug.");
    po::variables_map vm;
    std::string display_config, fixed_frame, splash_path, help_path;
    bool enable_ogre_log = false;
    bool in_mc_wrapper = false;
    bool verbose = false;
    int force_gl_version = 0;
    bool disable_anti_aliasing = false;
    bool disable_stereo = false;
    try
    {
      po::store( po::parse_command_line( argc, argv, options ), vm );
      po::notify( vm );

      if( vm.count( "help" ))
      {
        std::cout << "rviz command line options:\n" << options;
        return false;
      }

      if( vm.count( "in-mc-wrapper" ))
      {
        in_mc_wrapper = true;
      }

      if (vm.count("display-config"))
      {
        display_config = vm["display-config"].as<std::string>();
        if( display_config.substr( display_config.size() - 4, 4 ) == ".vcg" )
        {
          std::cerr << "ERROR: the config file '" << display_config << "' is a .vcg file, which is the old rviz config format." << std::endl;
          std::cerr << "       New config files have a .rviz extension and use YAML formatting.  The format changed" << std::endl;
          std::cerr << "       between Fuerte and Groovy.  There is not (yet) an automated conversion program." << std::endl;
          return false;
        }
      }

      if (vm.count("splash-screen"))
      {
        splash_path = vm["splash-screen"].as<std::string>();
      }

      if (vm.count("help-file"))
      {
        help_path = vm["help-file"].as<std::string>();
      }

      if (vm.count("fixed-frame"))
      {
        fixed_frame = vm["fixed-frame"].as<std::string>();
      }

      if (vm.count("ogre-log"))
      {
        enable_ogre_log = true;
      }

      if (vm.count("no-stereo"))
      {
        disable_stereo = true;
      }

      if (vm.count("opengl"))
      {
        //std::cout << vm["opengl"].as<std::string>() << std::endl;
        force_gl_version = vm["opengl"].as<int>();
      }

      if (vm.count("disable-anti-aliasing"))
      {
        disable_anti_aliasing = true;
      }

      if (vm.count("verbose"))
      {
        verbose = true;
      }

      if (vm.count("log-level-debug"))
      {
        if( ros::console::set_logger_level(ROSCONSOLE_DEFAULT_NAME, ros::console::levels::Debug) )
        {
          ros::console::notifyLoggerLevelsChanged();
        }
      }
    }
    catch (std::exception& e)
    {
      ROS_ERROR("Error parsing command line: %s", e.what());
      return false;
    }

    if( !ros::master::check() )
    {
      WaitForMasterDialog* dialog = new WaitForMasterDialog;
      if( dialog->exec() != QDialog::Accepted )
      {
        return false;
      }
    }

    nh_.reset( new ros::NodeHandle );

    if( enable_ogre_log )
    {
      OgreLogging::useRosLog();
    }

    if ( force_gl_version )
    {
      RenderSystem::forceGlVersion( force_gl_version );
    }

    if (disable_anti_aliasing)
    {
      RenderSystem::disableAntiAliasing();
    }

    if ( disable_stereo )
    {
      RenderSystem::forceNoStereo();
    }

    frame_ = new VisualizationFrame();
    frame_->setApp( this->app_ );
    if( help_path != "" )
    {
      frame_->setHelpPath( QString::fromStdString( help_path ));
    }
    frame_->setShowChooseNewMaster( in_mc_wrapper );
    if( vm.count("splash-screen") )
    {
      frame_->setSplashPath( QString::fromStdString( splash_path ));
    }
    frame_->initialize( QString::fromStdString( display_config ));
    if( !fixed_frame.empty() )
    {
      frame_->getManager()->setFixedFrame( QString::fromStdString( fixed_frame ));
    }

    frame_->getManager()->getSelectionManager()->setDebugMode( verbose );

    frame_->show();

    ros::NodeHandle private_nh("~");
    reload_shaders_service_ = private_nh.advertiseService("reload_shaders", reloadShaders);

#if CATCH_EXCEPTIONS
  }
  catch (std::exception& e)
  {
    ROS_ERROR("Caught exception while loading: %s", e.what());
    return false;
  }
#endif
  return true;
}

VisualizerApp::~VisualizerApp()
{
  delete continue_timer_;
  delete frame_;
}

void VisualizerApp::startContinueChecker()
{
  continue_timer_ = new QTimer( this );
  connect( continue_timer_, SIGNAL( timeout() ), this, SLOT( checkContinue() ));
  continue_timer_->start( 100 );
}

void VisualizerApp::checkContinue()
{
  if( !ros::ok() )
  {
    if( frame_ )
    {
      // Make sure the window doesn't ask if we want to save first.
      frame_->setWindowModified( false );
    }
    QApplication::closeAllWindows();
  }
}

} // namespace rviz
<|endoftext|>


<commit_before>/* /////////////////////////////////////////////////////////////////////////
 * File:        main_entry_point_Cpp.cpp
 *
 * Purpose:     Implementation of main for C++-clients. The implementation
 *              employs call-around for diagnostic logging (Pantheios) and
 *              command-line argument handling (CLASP).
 *
 * Created:     13th July 2015
 * Updated:     13th October 2015
 *
 * Home:        http://synesissoftware.com/software/libclimate/
 *
 * Copyright (c) 2015, Matthew Wilson and Synesis Software
 * 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(s) of Matthew Wilson and Synesis Software nor the names
 *   of any 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.
 *
 * ////////////////////////////////////////////////////////////////////// */

/* /////////////////////////////////////////////////////////////////////////
 * includes
 */

#include <libclimate/main/api.h>

#include "quiet_program_termination_exception.hpp"

#include <libclimate/internal/clasp.main.hpp>

#include <libclimate/internal/pantheios.extras.diagutil.hpp>

#include <libclimate/internal/pantheios.extras.main.hpp>

#include <libclimate/internal/pantheios.pantheios.h>

#include <stdarg.h>

/* /////////////////////////////////////////////////////////////////////////
 * feature discrimination
 */

/* /////////////////////////////////////////////////////////////////////////
 * implementation
 */

static
int
main_CLASP_inner_(
  clasp::arguments_t const* args
)
{
  try
  {
    return libCLImate_program_main_Cpp(args);
  }
  // 2. CLASP
  catch(clasp::unused_argument_exception& x)
  {
    pantheios::logprintf(
      PANTHEIOS_SEV_ALERT
    , PANTHEIOS_LITERAL_STRING("unrecognised command-line argument: ")
    , x.optionName.c_str()
    );

    fprintf(
      stderr
    , "%s: invalid argument '%.*s'\n"
    , pantheios::getProcessIdentity()
    , int(x.optionName.size()), x.optionName.data()
    );
  }
  catch(clasp::clasp_exception &x)
  {
    pantheios::logprintf(
      PANTHEIOS_SEV_ALERT
    , PANTHEIOS_LITERAL_STRING("invalid command-line: ")
    , x.what()
    );

    fprintf(
      stderr
    , "%s: invalid command-line: %s\n"
    , pantheios::getProcessIdentity()
    , x.what()
    );
  }

  return EXIT_FAILURE;
}

static
int
main_CLASP_outer_(
  int               argc
, clasp_char_t**    argv
)
{
  unsigned const  flags = 0
                        | CLASP_F_TREAT_SINGLEHYPHEN_AS_VALUE
                        ;

  struct CLASP_Pantheios_log
  {
    static void
    CLASP_CALLCONV          fn(
      void*                 context
    , int                   severity
    , clasp_char_t const*   fmt
    , va_list               args
    )
    {
      STLSOFT_SUPPRESS_UNUSED(context);

#if defined(PANTHEIOS_USE_WIDE_STRINGS) && \
    !defined(CLASP_USE_WIDE_STRINGS)
      STLSOFT_SUPPRESS_UNUSED(severity);
      STLSOFT_SUPPRESS_UNUSED(fmt);
      STLSOFT_SUPPRESS_UNUSED(args);
#else
      ::pantheios::logvprintf(severity, fmt, args);
#endif
    }
  };

  clasp_diagnostic_context_t  ctxt(NULL, &CLASP_Pantheios_log::fn, NULL);

  try
  {
    return clasp::main::invoke(
              argc
            , argv
            , main_CLASP_inner_
            , NULL
            , libCLImate_aliases
            , flags
            , &ctxt
//            , ST_USAGE_HELP_SUFFIX
            );
  }
  // 1. OOM failures caught by Pantheios.Extras.Main

  // 2. Some part of the program wants to finish
  catch(quiet_program_termination_exception &x)
  {
    return x.ExitCode;
  }
}

static
int
main_memory_leak_trace_(
#ifdef LIBCLIMATE_USE_wmain
  int       argc
, wchar_t** argv
#else /* ? LIBCLIMATE_USE_wmain */
  int       argc
, char**    argv
#endif /* LIBCLIMATE_USE_wmain */
)
{
  return ::pantheios::extras::diagutil::main_leak_trace::invoke(argc, argv, main_CLASP_outer_);
}

/* /////////////////////////////////////////////////////////////////////////
 * API functions
 */

extern "C"
#ifdef LIBCLIMATE_USE_wmain
int
libCLImate_wmain_entry_point_Cpp(
  int       argc
, wchar_t** argv
, void*     reserved
)
#else /* ? LIBCLIMATE_USE_wmain */
int
libCLImate_main_entry_point_Cpp(
  int       argc
, char**    argv
, void*  /* reserved */
)
#endif /* LIBCLIMATE_USE_wmain */
{
  return ::pantheios::extras::main::invoke(argc, argv, main_memory_leak_trace_);
}

/* ///////////////////////////// end of file //////////////////////////// */
<commit_msg>~ format defect<commit_after>/* /////////////////////////////////////////////////////////////////////////
 * File:        main_entry_point_Cpp.cpp
 *
 * Purpose:     Implementation of main for C++-clients. The implementation
 *              employs call-around for diagnostic logging (Pantheios) and
 *              command-line argument handling (CLASP).
 *
 * Created:     13th July 2015
 * Updated:     27th January 2017
 *
 * Home:        http://synesissoftware.com/software/libclimate/
 *
 * Copyright (c) 2015-2017, Matthew Wilson and Synesis Software
 * 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(s) of Matthew Wilson and Synesis Software nor the names
 *   of any 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.
 *
 * ////////////////////////////////////////////////////////////////////// */

/* /////////////////////////////////////////////////////////////////////////
 * includes
 */

#include <libclimate/main/api.h>

#include "quiet_program_termination_exception.hpp"

#include <libclimate/internal/clasp.main.hpp>

#include <libclimate/internal/pantheios.extras.diagutil.hpp>

#include <libclimate/internal/pantheios.extras.main.hpp>

#include <libclimate/internal/pantheios.pantheios.h>

#include <stdarg.h>

/* /////////////////////////////////////////////////////////////////////////
 * feature discrimination
 */

/* /////////////////////////////////////////////////////////////////////////
 * implementation
 */

static
int
main_CLASP_inner_(
  clasp::arguments_t const* args
)
{
  try
  {
    return libCLImate_program_main_Cpp(args);
  }
  // 2. CLASP
  catch(clasp::unused_argument_exception& x)
  {
    pantheios::logprintf(
      PANTHEIOS_SEV_ALERT
    , PANTHEIOS_LITERAL_STRING("unrecognised command-line argument: %s")
    , x.optionName.c_str()
    );

    fprintf(
      stderr
    , "%s: invalid argument '%.*s'\n"
    , pantheios::getProcessIdentity()
    , int(x.optionName.size()), x.optionName.data()
    );
  }
  catch(clasp::clasp_exception &x)
  {
    pantheios::logprintf(
      PANTHEIOS_SEV_ALERT
    , PANTHEIOS_LITERAL_STRING("invalid command-line: %s")
    , x.what()
    );

    fprintf(
      stderr
    , "%s: invalid command-line: %s\n"
    , pantheios::getProcessIdentity()
    , x.what()
    );
  }

  return EXIT_FAILURE;
}

static
int
main_CLASP_outer_(
  int               argc
, clasp_char_t**    argv
)
{
  unsigned const  flags = 0
                        | CLASP_F_TREAT_SINGLEHYPHEN_AS_VALUE
                        ;

  struct CLASP_Pantheios_log
  {
    static void
    CLASP_CALLCONV          fn(
      void*                 context
    , int                   severity
    , clasp_char_t const*   fmt
    , va_list               args
    )
    {
      STLSOFT_SUPPRESS_UNUSED(context);

#if defined(PANTHEIOS_USE_WIDE_STRINGS) && \
    !defined(CLASP_USE_WIDE_STRINGS)
      STLSOFT_SUPPRESS_UNUSED(severity);
      STLSOFT_SUPPRESS_UNUSED(fmt);
      STLSOFT_SUPPRESS_UNUSED(args);
#else
      ::pantheios::logvprintf(severity, fmt, args);
#endif
    }
  };

  clasp_diagnostic_context_t  ctxt(NULL, &CLASP_Pantheios_log::fn, NULL);

  try
  {
    return clasp::main::invoke(
              argc
            , argv
            , main_CLASP_inner_
            , NULL
            , libCLImate_aliases
            , flags
            , &ctxt
//            , ST_USAGE_HELP_SUFFIX
            );
  }
  // 1. OOM failures caught by Pantheios.Extras.Main

  // 2. Some part of the program wants to finish
  catch(quiet_program_termination_exception &x)
  {
    return x.ExitCode;
  }
}

static
int
main_memory_leak_trace_(
#ifdef LIBCLIMATE_USE_wmain
  int       argc
, wchar_t** argv
#else /* ? LIBCLIMATE_USE_wmain */
  int       argc
, char**    argv
#endif /* LIBCLIMATE_USE_wmain */
)
{
  return ::pantheios::extras::diagutil::main_leak_trace::invoke(argc, argv, main_CLASP_outer_);
}

/* /////////////////////////////////////////////////////////////////////////
 * API functions
 */

extern "C"
#ifdef LIBCLIMATE_USE_wmain
int
libCLImate_wmain_entry_point_Cpp(
  int       argc
, wchar_t** argv
, void*     reserved
)
#else /* ? LIBCLIMATE_USE_wmain */
int
libCLImate_main_entry_point_Cpp(
  int       argc
, char**    argv
, void*  /* reserved */
)
#endif /* LIBCLIMATE_USE_wmain */
{
  return ::pantheios::extras::main::invoke(argc, argv, main_memory_leak_trace_);
}

/* ///////////////////////////// end of file //////////////////////////// */
<|endoftext|>


<commit_before>// Copyright (c) 2015, Karsten Heinze <karsten.heinze@sidenotes.de>
// 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.
//
// 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 <clocale>
#include <locale>
#include <iostream>
#include <stdexcept>
#include "sesame/utils/string.hpp"
#include "sesame/utils/Transcoder.hpp"

namespace
{
   void stripIfEmpty( String& string )
   {
      if ( string.find_first_not_of( " \t\n" ) == String::npos )
      {
         string = "";
      }
   }
}

namespace sesame { namespace utils {

const Vector<String> tokenize( const String& string )
{
   StringStream stream;
   stream << string;
   Vector<String> result;

   while ( stream.good() )
   {
      String tmp;
      std::getline( stream, tmp, ' ' );
      tmp = strip( tmp );
      if ( ! tmp.empty() )
      {
         result.push_back( tmp );
      }
   }

   return result;
}

String lstrip( const String& string )
{
   String tmp( string );
   String::size_type hit;

   hit = tmp.find_first_not_of( " \t" );
   if ( hit != String::npos )
   {
      tmp.erase( 0, hit );
   }
   stripIfEmpty( tmp );

   return tmp;
}

String rstrip( const String& string )
{
   String tmp( string );
   String::size_type hit;

   hit = tmp.find_last_not_of( " \t\n" );
   if ( hit != String::npos && ( hit + 1 ) < tmp.size() )
   {
      tmp.erase( hit + 1 );
   }
   stripIfEmpty( tmp );

   return tmp;
}

String strip( const String& string )
{
   String tmp( string );

   tmp = lstrip( tmp );
   tmp = rstrip( tmp );

   return tmp;
}

String reduce( const String& string )
{
   String::size_type hit;
   String tmp( string );

   while ( ( hit = tmp.find( "  " ) ) != String::npos )
   {
      tmp.replace( hit, 2, " " );
   }

   return tmp;
}

String normalize( const String& string )
{
   String tmp( string );
   tmp = strip( tmp );
   tmp = reduce( tmp );
   return tmp;
}

std::pair<String,String> split( const String& string )
{
   String left( string );
   String right;

   // Line does not end with whitespace? Split line.
   if ( ! ( left.empty() || left.back() == ' ' ) )
   {
      String::size_type leftStart( string.find_first_not_of( " " ) );
      String::size_type hit( left.rfind( " " ) );
      if ( hit != String::npos && hit > leftStart )
      {
         right = left.substr( hit + 1 );
         left.erase( hit );
         rstrip( left );
         left += " ";
      }
   }

   return std::make_pair( left, right );
}

String toUtf8( const char* text, const std::size_t length )
{
   static Transcoder transcoder( getEncoding(), "UTF-8" );

   return transcoder.transcode( text, length );
}

String toUtf8( const String& text )
{
   return toUtf8( text.data(), text.size() );
}

String fromUtf8( const char* text, const std::size_t length )
{
   static Transcoder transcoder( "UTF-8", getEncoding() );

   return transcoder.transcode( text, length );
}

String fromUtf8( const String& text )
{
   return fromUtf8( text.data(), text.size() );
}

void setLocale()
{
   char* currentLocaleName( std::setlocale( LC_ALL, "" ) );
   if ( ! currentLocaleName )
   {
      throw std::runtime_error( "failed to set locale" );
   }
   std::locale currentLocale( currentLocaleName );
   std::cout.imbue( currentLocale );
   std::cerr.imbue( currentLocale );
   std::cin.imbue( currentLocale );
}

String getEncoding()
{
   String curLoc( std::cin.getloc().name().c_str() );
   if ( curLoc == "*" )
   {
      throw std::runtime_error( "locale is unnamed" );
   }

   String::size_type dot( curLoc.find( "." ) );
   if ( dot == String::npos || ( dot + 1 ) >= curLoc.size() )
   {
      throw std::runtime_error( "encoding unknown" );
   }
   return curLoc.substr( dot + 1 );
}

} }
<commit_msg>Assume UTF-8 encoding on non Linux systems.<commit_after>// Copyright (c) 2015, Karsten Heinze <karsten.heinze@sidenotes.de>
// 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.
//
// 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 <clocale>
#include <locale>
#include <iostream>
#include <stdexcept>
#include "sesame/utils/string.hpp"
#include "sesame/utils/Transcoder.hpp"

namespace
{
   void stripIfEmpty( String& string )
   {
      if ( string.find_first_not_of( " \t\n" ) == String::npos )
      {
         string = "";
      }
   }
}

namespace sesame { namespace utils {

const Vector<String> tokenize( const String& string )
{
   StringStream stream;
   stream << string;
   Vector<String> result;

   while ( stream.good() )
   {
      String tmp;
      std::getline( stream, tmp, ' ' );
      tmp = strip( tmp );
      if ( ! tmp.empty() )
      {
         result.push_back( tmp );
      }
   }

   return result;
}

String lstrip( const String& string )
{
   String tmp( string );
   String::size_type hit;

   hit = tmp.find_first_not_of( " \t" );
   if ( hit != String::npos )
   {
      tmp.erase( 0, hit );
   }
   stripIfEmpty( tmp );

   return tmp;
}

String rstrip( const String& string )
{
   String tmp( string );
   String::size_type hit;

   hit = tmp.find_last_not_of( " \t\n" );
   if ( hit != String::npos && ( hit + 1 ) < tmp.size() )
   {
      tmp.erase( hit + 1 );
   }
   stripIfEmpty( tmp );

   return tmp;
}

String strip( const String& string )
{
   String tmp( string );

   tmp = lstrip( tmp );
   tmp = rstrip( tmp );

   return tmp;
}

String reduce( const String& string )
{
   String::size_type hit;
   String tmp( string );

   while ( ( hit = tmp.find( "  " ) ) != String::npos )
   {
      tmp.replace( hit, 2, " " );
   }

   return tmp;
}

String normalize( const String& string )
{
   String tmp( string );
   tmp = strip( tmp );
   tmp = reduce( tmp );
   return tmp;
}

std::pair<String,String> split( const String& string )
{
   String left( string );
   String right;

   // Line does not end with whitespace? Split line.
   if ( ! ( left.empty() || left.back() == ' ' ) )
   {
      String::size_type leftStart( string.find_first_not_of( " " ) );
      String::size_type hit( left.rfind( " " ) );
      if ( hit != String::npos && hit > leftStart )
      {
         right = left.substr( hit + 1 );
         left.erase( hit );
         rstrip( left );
         left += " ";
      }
   }

   return std::make_pair( left, right );
}

String toUtf8( const char* text, const std::size_t length )
{
   static Transcoder transcoder( getEncoding(), "UTF-8" );

   return transcoder.transcode( text, length );
}

String toUtf8( const String& text )
{
   return toUtf8( text.data(), text.size() );
}

String fromUtf8( const char* text, const std::size_t length )
{
   static Transcoder transcoder( "UTF-8", getEncoding() );

   return transcoder.transcode( text, length );
}

String fromUtf8( const String& text )
{
   return fromUtf8( text.data(), text.size() );
}

void setLocale()
{
   char* currentLocaleName( std::setlocale( LC_ALL, "" ) );
   if ( ! currentLocaleName )
   {
      throw std::runtime_error( "failed to set locale" );
   }
   std::locale currentLocale( currentLocaleName );
   std::cout.imbue( currentLocale );
   std::cerr.imbue( currentLocale );
   std::cin.imbue( currentLocale );
}

String getEncoding()
{
#ifdef __gnu_linux__
   String curLoc( std::cin.getloc().name().c_str() );
   if ( curLoc == "*" )
   {
      throw std::runtime_error( "locale is unnamed" );
   }

   String::size_type dot( curLoc.find( "." ) );
   if ( dot == String::npos || ( dot + 1 ) >= curLoc.size() )
   {
      throw std::runtime_error( "encoding unknown" );
   }
   return curLoc.substr( dot + 1 );
#else
   // Assume UTF-8 encoding on non Linux systems.
   return "UTF-8";
#endif
}

} }
<|endoftext|>


<commit_before>#ifndef slic3r_Notebook_hpp_
#define slic3r_Notebook_hpp_

#ifdef _WIN32

#include <wx/bookctrl.h>

class ModeSizer;
class ScalableButton;

// custom message the ButtonsListCtrl sends to its parent (Notebook) to notify a selection change:
wxDECLARE_EVENT(wxCUSTOMEVT_NOTEBOOK_SEL_CHANGED, wxCommandEvent);

class ButtonsListCtrl : public wxControl
{
public:
    ButtonsListCtrl(wxWindow* parent, bool add_mode_buttons = false);
    ~ButtonsListCtrl() {}

    void OnPaint(wxPaintEvent&);
    void SetSelection(int sel);
    void UpdateMode();
    void Rescale();
    bool InsertPage(size_t n, const wxString& text, bool bSelect = false, const std::string& bmp_name = "");
    void RemovePage(size_t n);
    bool SetPageImage(size_t n, const std::string& bmp_name) const;
    void SetPageText(size_t n, const wxString& strText);
    wxString GetPageText(size_t n) const;

private:
    wxWindow*                       m_parent;
    wxFlexGridSizer*                m_buttons_sizer;
    wxBoxSizer*                     m_sizer;
    std::vector<ScalableButton*>    m_pageButtons;
    int                             m_selection {-1};
    int                             m_btn_margin;
    int                             m_line_margin;
    ModeSizer*                      m_mode_sizer {nullptr};
};

class Notebook: public wxBookCtrlBase
{
public:
    Notebook(wxWindow * parent,
                 wxWindowID winid = wxID_ANY,
                 const wxPoint & pos = wxDefaultPosition,
                 const wxSize & size = wxDefaultSize,
                 long style = 0,
                 bool add_mode_buttons = false)
    {
        Init();
        Create(parent, winid, pos, size, style, add_mode_buttons);
    }

    bool Create(wxWindow * parent,
                wxWindowID winid = wxID_ANY,
                const wxPoint & pos = wxDefaultPosition,
                const wxSize & size = wxDefaultSize,
                long style = 0,
                bool add_mode_buttons = false)
    {
        if (!wxBookCtrlBase::Create(parent, winid, pos, size, style | wxBK_TOP))
            return false;

        m_bookctrl = new ButtonsListCtrl(this, add_mode_buttons);

        wxSizer* mainSizer = new wxBoxSizer(IsVertical() ? wxVERTICAL : wxHORIZONTAL);

        if (style & wxBK_RIGHT || style & wxBK_BOTTOM)
            mainSizer->Add(0, 0, 1, wxEXPAND, 0);

        m_controlSizer = new wxBoxSizer(IsVertical() ? wxHORIZONTAL : wxVERTICAL);
        m_controlSizer->Add(m_bookctrl, wxSizerFlags(1).Expand());
        wxSizerFlags flags;
        if (IsVertical())
            flags.Expand();
        else
            flags.CentreVertical();
        mainSizer->Add(m_controlSizer, flags.Border(wxALL, m_controlMargin));
        SetSizer(mainSizer);

        this->Bind(wxCUSTOMEVT_NOTEBOOK_SEL_CHANGED, [this](wxCommandEvent& evt)
        {
            if (int page_idx = evt.GetId(); page_idx >= 0)
                SetSelection(page_idx);
        });
        return true;
    }

    // Methods specific to this class.

    // A method allowing to add a new page without any label (which is unused
    // by this control) and show it immediately.
    bool ShowNewPage(wxWindow * page)
    {
        return AddPage(page, wxString(), ""/*true *//* select it */);
    }

    // Set effect to use for showing/hiding pages.
    void SetEffects(wxShowEffect showEffect, wxShowEffect hideEffect)
    {
        m_showEffect = showEffect;
        m_hideEffect = hideEffect;
    }

    // Or the same effect for both of them.
    void SetEffect(wxShowEffect effect)
    {
        SetEffects(effect, effect);
    }

    // And the same for time outs.
    void SetEffectsTimeouts(unsigned showTimeout, unsigned hideTimeout)
    {
        m_showTimeout = showTimeout;
        m_hideTimeout = hideTimeout;
    }

    void SetEffectTimeout(unsigned timeout)
    {
        SetEffectsTimeouts(timeout, timeout);
    }

    // Implement base class pure virtual methods.

    // adds a new page to the control
    bool AddPage(wxWindow* page,
                 const wxString& text,
                 const std::string& bmp_name,
                 bool bSelect = false)
    {
        DoInvalidateBestSize();
        return InsertPage(GetPageCount(), page, text, bmp_name, bSelect);
    }

    // Page management
    virtual bool InsertPage(size_t n,
                            wxWindow * page,
                            const wxString & text,
                            bool bSelect = false,
                            int imageId = NO_IMAGE) override
    {
        if (!wxBookCtrlBase::InsertPage(n, page, text, bSelect, imageId))
            return false;

        GetBtnsListCtrl()->InsertPage(n, text, bSelect);

        if (!DoSetSelectionAfterInsertion(n, bSelect))
            page->Hide();

        return true;
    }

    bool InsertPage(size_t n,
                    wxWindow * page,
                    const wxString & text,
                    const std::string& bmp_name = "",
                    bool bSelect = false)
    {
        if (!wxBookCtrlBase::InsertPage(n, page, text, bSelect))
            return false;

        GetBtnsListCtrl()->InsertPage(n, text, bSelect, bmp_name);

        if (bSelect)
            SetSelection(n);

        return true;
    }

    virtual int SetSelection(size_t n) override
    {
        GetBtnsListCtrl()->SetSelection(n);
        int ret = DoSetSelection(n, SetSelection_SendEvent);

        // check that only the selected page is visible and others are hidden:
        for (size_t page = 0; page < m_pages.size(); page++)
            if (page != n)
                m_pages[page]->Hide();

        return ret;
    }

    virtual int ChangeSelection(size_t n) override
    {
        GetBtnsListCtrl()->SetSelection(n);
        return DoSetSelection(n);
    }

    // Neither labels nor images are supported but we still store the labels
    // just in case the user code attaches some importance to them.
    virtual bool SetPageText(size_t n, const wxString & strText) override
    {
        wxCHECK_MSG(n < GetPageCount(), false, wxS("Invalid page"));

        GetBtnsListCtrl()->SetPageText(n, strText);

        return true;
    }

    virtual wxString GetPageText(size_t n) const override
    {
        wxCHECK_MSG(n < GetPageCount(), wxString(), wxS("Invalid page"));
        return GetBtnsListCtrl()->GetPageText(n);
    }

    virtual bool SetPageImage(size_t WXUNUSED(n), int WXUNUSED(imageId)) override
    {
        return false;
    }

    virtual int GetPageImage(size_t WXUNUSED(n)) const override
    {
        return NO_IMAGE;
    }

    bool SetPageImage(size_t n, const std::string& bmp_name)
    {
        return GetBtnsListCtrl()->SetPageImage(n, bmp_name);
    }

    // Override some wxWindow methods too.
    virtual void SetFocus() override
    {
        wxWindow* const page = GetCurrentPage();
        if (page)
            page->SetFocus();
    }

    ButtonsListCtrl* GetBtnsListCtrl() const { return static_cast<ButtonsListCtrl*>(m_bookctrl); }

    void UpdateMode()
    {
        GetBtnsListCtrl()->UpdateMode();
    }

    void Rescale()
    {
        GetBtnsListCtrl()->Rescale();
    }

protected:
    virtual void UpdateSelectedPage(size_t WXUNUSED(newsel)) override
    {
        // Nothing to do here, but must be overridden to avoid the assert in
        // the base class version.
    }

    virtual wxBookCtrlEvent * CreatePageChangingEvent() const override
    {
        return new wxBookCtrlEvent(wxEVT_BOOKCTRL_PAGE_CHANGING,
                                   GetId());
    }

    virtual void MakeChangedEvent(wxBookCtrlEvent & event) override
    {
        event.SetEventType(wxEVT_BOOKCTRL_PAGE_CHANGED);
    }

    virtual wxWindow * DoRemovePage(size_t page) override
    {
        wxWindow* const win = wxBookCtrlBase::DoRemovePage(page);
        if (win)
        {
            GetBtnsListCtrl()->RemovePage(page);
            DoSetSelectionAfterRemoval(page);
        }

        return win;
    }

    virtual void DoSize() override
    {
        wxWindow* const page = GetCurrentPage();
        if (page)
            page->SetSize(GetPageRect());
    }

    virtual void DoShowPage(wxWindow * page, bool show) override
    {
        if (show)
            page->ShowWithEffect(m_showEffect, m_showTimeout);
        else
            page->HideWithEffect(m_hideEffect, m_hideTimeout);
    }

private:
    void Init()
    {
        // We don't need any border as we don't have anything to separate the
        // page contents from.
        SetInternalBorder(0);

        // No effects by default.
        m_showEffect =
        m_hideEffect = wxSHOW_EFFECT_NONE;

        m_showTimeout =
        m_hideTimeout = 0;
    }

    wxShowEffect m_showEffect,
                 m_hideEffect;

    unsigned m_showTimeout,
             m_hideTimeout;

    ButtonsListCtrl* m_ctrl{ nullptr };

};
#endif // _WIN32
#endif // slic3r_Notebook_hpp_
<commit_msg>MSW specific: Fix for #6938 - Cycling through tabs using Ctrl+PageUp/Down doesn't work OnNavigationKey() function is copied from wxNotebook to Notebook<commit_after>#ifndef slic3r_Notebook_hpp_
#define slic3r_Notebook_hpp_

#ifdef _WIN32

#include <wx/bookctrl.h>

class ModeSizer;
class ScalableButton;

// custom message the ButtonsListCtrl sends to its parent (Notebook) to notify a selection change:
wxDECLARE_EVENT(wxCUSTOMEVT_NOTEBOOK_SEL_CHANGED, wxCommandEvent);

class ButtonsListCtrl : public wxControl
{
public:
    ButtonsListCtrl(wxWindow* parent, bool add_mode_buttons = false);
    ~ButtonsListCtrl() {}

    void OnPaint(wxPaintEvent&);
    void SetSelection(int sel);
    void UpdateMode();
    void Rescale();
    bool InsertPage(size_t n, const wxString& text, bool bSelect = false, const std::string& bmp_name = "");
    void RemovePage(size_t n);
    bool SetPageImage(size_t n, const std::string& bmp_name) const;
    void SetPageText(size_t n, const wxString& strText);
    wxString GetPageText(size_t n) const;

private:
    wxWindow*                       m_parent;
    wxFlexGridSizer*                m_buttons_sizer;
    wxBoxSizer*                     m_sizer;
    std::vector<ScalableButton*>    m_pageButtons;
    int                             m_selection {-1};
    int                             m_btn_margin;
    int                             m_line_margin;
    ModeSizer*                      m_mode_sizer {nullptr};
};

class Notebook: public wxBookCtrlBase
{
public:
    Notebook(wxWindow * parent,
                 wxWindowID winid = wxID_ANY,
                 const wxPoint & pos = wxDefaultPosition,
                 const wxSize & size = wxDefaultSize,
                 long style = 0,
                 bool add_mode_buttons = false)
    {
        Init();
        Create(parent, winid, pos, size, style, add_mode_buttons);
    }

    bool Create(wxWindow * parent,
                wxWindowID winid = wxID_ANY,
                const wxPoint & pos = wxDefaultPosition,
                const wxSize & size = wxDefaultSize,
                long style = 0,
                bool add_mode_buttons = false)
    {
        if (!wxBookCtrlBase::Create(parent, winid, pos, size, style | wxBK_TOP))
            return false;

        m_bookctrl = new ButtonsListCtrl(this, add_mode_buttons);

        wxSizer* mainSizer = new wxBoxSizer(IsVertical() ? wxVERTICAL : wxHORIZONTAL);

        if (style & wxBK_RIGHT || style & wxBK_BOTTOM)
            mainSizer->Add(0, 0, 1, wxEXPAND, 0);

        m_controlSizer = new wxBoxSizer(IsVertical() ? wxHORIZONTAL : wxVERTICAL);
        m_controlSizer->Add(m_bookctrl, wxSizerFlags(1).Expand());
        wxSizerFlags flags;
        if (IsVertical())
            flags.Expand();
        else
            flags.CentreVertical();
        mainSizer->Add(m_controlSizer, flags.Border(wxALL, m_controlMargin));
        SetSizer(mainSizer);

        this->Bind(wxCUSTOMEVT_NOTEBOOK_SEL_CHANGED, [this](wxCommandEvent& evt)
        {
            if (int page_idx = evt.GetId(); page_idx >= 0)
                SetSelection(page_idx);
        });

        this->Bind(wxEVT_NAVIGATION_KEY, &Notebook::OnNavigationKey, this);

        return true;
    }

    // Methods specific to this class.

    // A method allowing to add a new page without any label (which is unused
    // by this control) and show it immediately.
    bool ShowNewPage(wxWindow * page)
    {
        return AddPage(page, wxString(), ""/*true *//* select it */);
    }

    // Set effect to use for showing/hiding pages.
    void SetEffects(wxShowEffect showEffect, wxShowEffect hideEffect)
    {
        m_showEffect = showEffect;
        m_hideEffect = hideEffect;
    }

    // Or the same effect for both of them.
    void SetEffect(wxShowEffect effect)
    {
        SetEffects(effect, effect);
    }

    // And the same for time outs.
    void SetEffectsTimeouts(unsigned showTimeout, unsigned hideTimeout)
    {
        m_showTimeout = showTimeout;
        m_hideTimeout = hideTimeout;
    }

    void SetEffectTimeout(unsigned timeout)
    {
        SetEffectsTimeouts(timeout, timeout);
    }

    // Implement base class pure virtual methods.

    // adds a new page to the control
    bool AddPage(wxWindow* page,
                 const wxString& text,
                 const std::string& bmp_name,
                 bool bSelect = false)
    {
        DoInvalidateBestSize();
        return InsertPage(GetPageCount(), page, text, bmp_name, bSelect);
    }

    // Page management
    virtual bool InsertPage(size_t n,
                            wxWindow * page,
                            const wxString & text,
                            bool bSelect = false,
                            int imageId = NO_IMAGE) override
    {
        if (!wxBookCtrlBase::InsertPage(n, page, text, bSelect, imageId))
            return false;

        GetBtnsListCtrl()->InsertPage(n, text, bSelect);

        if (!DoSetSelectionAfterInsertion(n, bSelect))
            page->Hide();

        return true;
    }

    bool InsertPage(size_t n,
                    wxWindow * page,
                    const wxString & text,
                    const std::string& bmp_name = "",
                    bool bSelect = false)
    {
        if (!wxBookCtrlBase::InsertPage(n, page, text, bSelect))
            return false;

        GetBtnsListCtrl()->InsertPage(n, text, bSelect, bmp_name);

        if (bSelect)
            SetSelection(n);

        return true;
    }

    virtual int SetSelection(size_t n) override
    {
        GetBtnsListCtrl()->SetSelection(n);
        int ret = DoSetSelection(n, SetSelection_SendEvent);

        // check that only the selected page is visible and others are hidden:
        for (size_t page = 0; page < m_pages.size(); page++)
            if (page != n)
                m_pages[page]->Hide();

        return ret;
    }

    virtual int ChangeSelection(size_t n) override
    {
        GetBtnsListCtrl()->SetSelection(n);
        return DoSetSelection(n);
    }

    // Neither labels nor images are supported but we still store the labels
    // just in case the user code attaches some importance to them.
    virtual bool SetPageText(size_t n, const wxString & strText) override
    {
        wxCHECK_MSG(n < GetPageCount(), false, wxS("Invalid page"));

        GetBtnsListCtrl()->SetPageText(n, strText);

        return true;
    }

    virtual wxString GetPageText(size_t n) const override
    {
        wxCHECK_MSG(n < GetPageCount(), wxString(), wxS("Invalid page"));
        return GetBtnsListCtrl()->GetPageText(n);
    }

    virtual bool SetPageImage(size_t WXUNUSED(n), int WXUNUSED(imageId)) override
    {
        return false;
    }

    virtual int GetPageImage(size_t WXUNUSED(n)) const override
    {
        return NO_IMAGE;
    }

    bool SetPageImage(size_t n, const std::string& bmp_name)
    {
        return GetBtnsListCtrl()->SetPageImage(n, bmp_name);
    }

    // Override some wxWindow methods too.
    virtual void SetFocus() override
    {
        wxWindow* const page = GetCurrentPage();
        if (page)
            page->SetFocus();
    }

    ButtonsListCtrl* GetBtnsListCtrl() const { return static_cast<ButtonsListCtrl*>(m_bookctrl); }

    void UpdateMode()
    {
        GetBtnsListCtrl()->UpdateMode();
    }

    void Rescale()
    {
        GetBtnsListCtrl()->Rescale();
    }

    void Notebook::OnNavigationKey(wxNavigationKeyEvent& event)
    {
        if (event.IsWindowChange()) {
            // change pages
            AdvanceSelection(event.GetDirection());
        }
        else {
            // we get this event in 3 cases
            //
            // a) one of our pages might have generated it because the user TABbed
            // out from it in which case we should propagate the event upwards and
            // our parent will take care of setting the focus to prev/next sibling
            //
            // or
            //
            // b) the parent panel wants to give the focus to us so that we
            // forward it to our selected page. We can't deal with this in
            // OnSetFocus() because we don't know which direction the focus came
            // from in this case and so can't choose between setting the focus to
            // first or last panel child
            //
            // or
            //
            // c) we ourselves (see MSWTranslateMessage) generated the event
            //
            wxWindow* const parent = GetParent();

            // the wxObject* casts are required to avoid MinGW GCC 2.95.3 ICE
            const bool isFromParent = event.GetEventObject() == (wxObject*)parent;
            const bool isFromSelf = event.GetEventObject() == (wxObject*)this;
            const bool isForward = event.GetDirection();

            if (isFromSelf && !isForward)
            {
                // focus is currently on notebook tab and should leave
                // it backwards (Shift-TAB)
                event.SetCurrentFocus(this);
                parent->HandleWindowEvent(event);
            }
            else if (isFromParent || isFromSelf)
            {
                // no, it doesn't come from child, case (b) or (c): forward to a
                // page but only if entering notebook page (i.e. direction is
                // backwards (Shift-TAB) comething from out-of-notebook, or
                // direction is forward (TAB) from ourselves),
                if (m_selection != wxNOT_FOUND &&
                    (!event.GetDirection() || isFromSelf))
                {
                    // so that the page knows that the event comes from it's parent
                    // and is being propagated downwards
                    event.SetEventObject(this);

                    wxWindow* page = m_pages[m_selection];
                    if (!page->HandleWindowEvent(event))
                    {
                        page->SetFocus();
                    }
                    //else: page manages focus inside it itself
                }
                else // otherwise set the focus to the notebook itself
                {
                    SetFocus();
                }
            }
            else
            {
                // it comes from our child, case (a), pass to the parent, but only
                // if the direction is forwards. Otherwise set the focus to the
                // notebook itself. The notebook is always the 'first' control of a
                // page.
                if (!isForward)
                {
                    SetFocus();
                }
                else if (parent)
                {
                    event.SetCurrentFocus(this);
                    parent->HandleWindowEvent(event);
                }
            }
        }
    }

protected:
    virtual void UpdateSelectedPage(size_t WXUNUSED(newsel)) override
    {
        // Nothing to do here, but must be overridden to avoid the assert in
        // the base class version.
    }

    virtual wxBookCtrlEvent * CreatePageChangingEvent() const override
    {
        return new wxBookCtrlEvent(wxEVT_BOOKCTRL_PAGE_CHANGING,
                                   GetId());
    }

    virtual void MakeChangedEvent(wxBookCtrlEvent & event) override
    {
        event.SetEventType(wxEVT_BOOKCTRL_PAGE_CHANGED);
    }

    virtual wxWindow * DoRemovePage(size_t page) override
    {
        wxWindow* const win = wxBookCtrlBase::DoRemovePage(page);
        if (win)
        {
            GetBtnsListCtrl()->RemovePage(page);
            DoSetSelectionAfterRemoval(page);
        }

        return win;
    }

    virtual void DoSize() override
    {
        wxWindow* const page = GetCurrentPage();
        if (page)
            page->SetSize(GetPageRect());
    }

    virtual void DoShowPage(wxWindow * page, bool show) override
    {
        if (show)
            page->ShowWithEffect(m_showEffect, m_showTimeout);
        else
            page->HideWithEffect(m_hideEffect, m_hideTimeout);
    }

private:
    void Init()
    {
        // We don't need any border as we don't have anything to separate the
        // page contents from.
        SetInternalBorder(0);

        // No effects by default.
        m_showEffect =
        m_hideEffect = wxSHOW_EFFECT_NONE;

        m_showTimeout =
        m_hideTimeout = 0;
    }

    wxShowEffect m_showEffect,
                 m_hideEffect;

    unsigned m_showTimeout,
             m_hideTimeout;

    ButtonsListCtrl* m_ctrl{ nullptr };

};
#endif // _WIN32
#endif // slic3r_Notebook_hpp_
<|endoftext|>


<commit_before>
#include "swganh/object/object.h"

#include "anh/crc.h"
#include "anh/observer/observer_interface.h"
#include "swganh/messages/base_baselines_message.h"
#include "swganh/messages/scene_create_object_by_crc.h"
#include "swganh/messages/scene_end_baselines.h"
#include "swganh/messages/update_containment_message.h"
#include "swganh/object/object_message_builder.h"
#include "swganh/network/remote_client.h"

using namespace anh::observer;
using namespace std;
using namespace swganh::object;
using namespace swganh::messages;
using boost::optional;

Object::Object()
    : object_id_(0)
    , template_string_("")
    , position_(glm::vec3(0,0,0))
    , orientation_(glm::quat(0,0,0,0))
    , complexity_(0)
    , stf_name_file_("")
    , stf_name_string_("")
    , custom_name_(L"")
    , volume_(0)
{
	AddBaselinesBuilders_();
}

bool Object::HasController()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    return controller_;
}

const shared_ptr<ObjectController>& Object::GetController()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    return controller_;
}

void Object::SetController(const shared_ptr<ObjectController>& controller)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    controller_ = controller;
    Subscribe(controller_);
}

void Object::ClearController()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    Unsubscribe(controller_);
    controller_.reset();
}

void Object::AddContainedObject(const shared_ptr<Object>& object, uint32_t containment_type)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    if (contained_objects_.find(object->GetObjectId()) != contained_objects_.end())
    {
        // @TODO consider whether encountering this scenario is an error
        return;
    }

    contained_objects_.insert(make_pair(object->GetObjectId(), object));
    object->SetContainer(shared_from_this());

    if (HasController())
    {
        object->Subscribe(GetController());
    }
}

bool Object::IsContainerForObject(const shared_ptr<Object>& object)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    return contained_objects_.find(object->GetObjectId()) != contained_objects_.end();
}

void Object::RemoveContainedObject(const shared_ptr<Object>& object)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    auto find_iter = contained_objects_.find(object->GetObjectId());

    if (find_iter == contained_objects_.end())
    {
        // @TODO consider whether encountering this scenario is an error
        return;
    }

    contained_objects_.erase(find_iter);

    if (HasController())
    {
        object->Unsubscribe(GetController());
    }
}

Object::ObjectMap Object::GetContainedObjects()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    return contained_objects_;
}

void Object::AddAwareObject(const shared_ptr<Object>& object)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    if (aware_objects_.find(object->GetObjectId()) != aware_objects_.end())
    {
        // @TODO consider whether encountering this scenario is an error
		// someone could be logging back in and we want to make them aware again, so we'll send clean baselines.
		if (object->HasController()) {
			MakeClean(object->GetController());
		}
        return;
    }

    aware_objects_.insert(make_pair(object->GetObjectId(), object));

    if (object->HasController()) {
        Subscribe(object->GetController());
        MakeClean(object->GetController());
    }
}

bool Object::IsAwareOfObject(const shared_ptr<Object>& object)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    return aware_objects_.find(object->GetObjectId()) != aware_objects_.end();
}

void Object::RemoveAwareObject(const shared_ptr<Object>& object)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    auto find_iter = aware_objects_.find(object->GetObjectId());

    if (find_iter == aware_objects_.end())
    {
        // @TODO consider whether encountering this scenario is an error
        return;
    }

    aware_objects_.erase(find_iter);

    if (HasController())
    {
        object->Unsubscribe(GetController());
    }
}
const string& Object::GetTemplate()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	return template_string_;
}
void Object::SetTemplate(const string& template_string)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	template_string_ = template_string;
}
void Object::SetObjectId(uint64_t object_id)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	object_id_ = object_id;
}
uint64_t Object::GetObjectId()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    return object_id_;
}

const wstring& Object::GetCustomName()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    return custom_name_;
}

void Object::SetCustomName(wstring custom_name)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    custom_name_ = custom_name;

    // Only build a message if there are observers.
    if (HasObservers())
    {
        DeltasMessage message = CreateDeltasMessage(Object::VIEW_3, 2);
        message.data.write(custom_name);

        AddDeltasUpdate(message);
    }
}

BaselinesMessage Object::CreateBaselinesMessage(uint16_t view_type, uint16_t opcount)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    BaselinesMessage message;
    message.object_id = GetObjectId();
    message.object_type = GetType();
    message.view_type = view_type;
    message.object_opcount = opcount;

    return message;
}

DeltasMessage Object::CreateDeltasMessage(uint16_t view_type, uint16_t update_type, uint16_t update_count)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    DeltasMessage message;
    message.object_id = GetObjectId();
    message.object_type = GetType();
    message.view_type = view_type;
    message.update_count = update_count;
    message.update_type = update_type;
    return message;
}

bool Object::HasObservers()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    return !observers_.empty();
}

void Object::Subscribe(const shared_ptr<ObserverInterface>& observer)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    auto find_iter = std::find_if(
        observers_.begin(),
        observers_.end(),
        [&observer] (const std::shared_ptr<ObserverInterface>& stored_observer)
    {
        return observer == stored_observer;
    });

    if (find_iter != observers_.end())
    {
        return;
    }

    observers_.push_back(observer);
}

void Object::Unsubscribe(const shared_ptr<ObserverInterface>& observer)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    auto find_iter = std::find_if(
        observers_.begin(),
        observers_.end(),
        [&observer] (const std::shared_ptr<ObserverInterface>& stored_observer)
    {
        return observer == stored_observer;
    });

    if (find_iter == observers_.end())
    {
        return;
    }

    observers_.erase(find_iter);
}

void Object::NotifyObservers(const anh::ByteBuffer& message)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    NotifyObservers<anh::ByteBuffer>(message);
}

bool Object::IsDirty()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    return !deltas_.empty();
}

void Object::MakeClean(std::shared_ptr<swganh::object::ObjectController> controller)
{
    boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    baselines_.clear();
    deltas_.clear();

    // SceneCreateObjectByCrc
    swganh::messages::SceneCreateObjectByCrc scene_object;
    scene_object.object_id = GetObjectId();
    scene_object.object_crc = anh::memcrc(GetTemplate());
    scene_object.position = GetPosition();
	scene_object.orientation = GetOrientation();
    controller->Notify(scene_object);

    if (GetContainer())
    {
        UpdateContainmentMessage containment_message;
        containment_message.container_id = GetContainer()->GetObjectId();
        containment_message.object_id = GetObjectId();
        containment_message.containment_type = 4;

        controller->Notify(containment_message);
    }

    // Baselines
    optional<BaselinesMessage> message;
    for_each(begin(baselines_builders_), end(baselines_builders_),
        [this, &message, &controller] (BaselinesBuilder& builder)
    {
        if (!(message = builder()))
        {
            return;
        }

        controller->Notify(*message);
        baselines_.push_back(*message);
    });

    // SceneEndBaselines
    swganh::messages::SceneEndBaselines scene_end_baselines;
    scene_end_baselines.object_id = GetObjectId();
    controller->Notify(scene_end_baselines);
}

const BaselinesCacheContainer& Object::GetBaselines(uint64_t viewer_id)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    return baselines_;
}

const DeltasCacheContainer& Object::GetDeltas(uint64_t viewer_id)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    return deltas_;
}

void Object::AddDeltasUpdate(DeltasMessage message)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    NotifyObservers(message);
    deltas_.push_back(move(message));
}

void Object::AddBaselinesBuilders_()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    baselines_builders_.push_back([this] () {
        return GetBaseline1();
    });

    baselines_builders_.push_back([this] () {
        return GetBaseline2();
    });

    baselines_builders_.push_back([this] () {
        return GetBaseline3();
    });

    baselines_builders_.push_back([this] () {
        return GetBaseline4();
    });

    baselines_builders_.push_back([this] () {
        return GetBaseline5();
    });

    baselines_builders_.push_back([this] () {
        return GetBaseline6();
    });

    baselines_builders_.push_back([this] () {
        return GetBaseline7();
    });

    baselines_builders_.push_back([this] () {
        return GetBaseline8();
    });

    baselines_builders_.push_back([this] () {
        return GetBaseline9();
    });
}

void Object::SetPosition(glm::vec3 position)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    position_ = position;
}
glm::vec3 Object::GetPosition()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	return position_;
}
void Object::SetOrientation(glm::quat orientation)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    orientation_ = orientation;
}
glm::quat Object::GetOrientation()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	return orientation_;
}

uint8_t Object::GetHeading()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    glm::quat tmp = orientation_;

    if (tmp.y < 0.0f && tmp.w > 0.0f) {
        tmp.w *= -1;
    }

    return static_cast<uint8_t>((glm::angle(tmp) / 6.283f) * 100);
}

void Object::SetContainer(const std::shared_ptr<Object>& container)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    container_ = container;
}
const shared_ptr<Object>& Object::GetContainer()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	return container_;
}
void Object::SetComplexity(float complexity)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    complexity_ = complexity;
    ObjectMessageBuilder::BuildComplexityDelta(this);
}
float Object::GetComplexity()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	return complexity_;
}
void Object::SetStfNameFile(const string& stf_name_file)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    stf_name_file_ = stf_name_file;
    ObjectMessageBuilder::BuildStfNameDelta(this);
}
const string& Object::GetStfNameFile()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	return stf_name_file_;
}
void Object::SetStfNameString(const string& stf_name_string)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    stf_name_string_ = stf_name_string;
    ObjectMessageBuilder::BuildStfNameDelta(this);
}
const string& Object::GetStfNameString()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	return stf_name_string_;
}
void Object::SetVolume(uint32_t volume)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    volume_ = volume;
    ObjectMessageBuilder::BuildVolumeDelta(this);
}
uint32_t Object::GetVolume()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	return volume_;
}
void Object::SetSceneId(uint32_t scene_id)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	scene_id_ = scene_id;
}
uint32_t Object::GetSceneId()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	return scene_id_;
}
optional<BaselinesMessage> Object::GetBaseline3()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	return move(ObjectMessageBuilder::BuildBaseline3(this));
}

optional<BaselinesMessage> Object::GetBaseline6()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	return move(ObjectMessageBuilder::BuildBaseline6(this));
}
<commit_msg>Corrected null check<commit_after>
#include "swganh/object/object.h"

#include "anh/crc.h"
#include "anh/observer/observer_interface.h"
#include "swganh/messages/base_baselines_message.h"
#include "swganh/messages/scene_create_object_by_crc.h"
#include "swganh/messages/scene_end_baselines.h"
#include "swganh/messages/update_containment_message.h"
#include "swganh/object/object_message_builder.h"
#include "swganh/network/remote_client.h"

using namespace anh::observer;
using namespace std;
using namespace swganh::object;
using namespace swganh::messages;
using boost::optional;

Object::Object()
    : object_id_(0)
    , template_string_("")
    , position_(glm::vec3(0,0,0))
    , orientation_(glm::quat(0,0,0,0))
    , complexity_(0)
    , stf_name_file_("")
    , stf_name_string_("")
    , custom_name_(L"")
    , volume_(0)
{
	AddBaselinesBuilders_();
}

bool Object::HasController()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    return controller_ != nullptr;
}

const shared_ptr<ObjectController>& Object::GetController()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    return controller_;
}

void Object::SetController(const shared_ptr<ObjectController>& controller)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    controller_ = controller;
    Subscribe(controller_);
}

void Object::ClearController()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    Unsubscribe(controller_);
    controller_.reset();
}

void Object::AddContainedObject(const shared_ptr<Object>& object, uint32_t containment_type)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    if (contained_objects_.find(object->GetObjectId()) != contained_objects_.end())
    {
        // @TODO consider whether encountering this scenario is an error
        return;
    }

    contained_objects_.insert(make_pair(object->GetObjectId(), object));
    object->SetContainer(shared_from_this());

    if (HasController())
    {
        object->Subscribe(GetController());
    }
}

bool Object::IsContainerForObject(const shared_ptr<Object>& object)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    return contained_objects_.find(object->GetObjectId()) != contained_objects_.end();
}

void Object::RemoveContainedObject(const shared_ptr<Object>& object)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    auto find_iter = contained_objects_.find(object->GetObjectId());

    if (find_iter == contained_objects_.end())
    {
        // @TODO consider whether encountering this scenario is an error
        return;
    }

    contained_objects_.erase(find_iter);

    if (HasController())
    {
        object->Unsubscribe(GetController());
    }
}

Object::ObjectMap Object::GetContainedObjects()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    return contained_objects_;
}

void Object::AddAwareObject(const shared_ptr<Object>& object)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    if (aware_objects_.find(object->GetObjectId()) != aware_objects_.end())
    {
        // @TODO consider whether encountering this scenario is an error
		// someone could be logging back in and we want to make them aware again, so we'll send clean baselines.
		if (object->HasController()) {
			MakeClean(object->GetController());
		}
        return;
    }

    aware_objects_.insert(make_pair(object->GetObjectId(), object));

    if (object->HasController()) {
        Subscribe(object->GetController());
        MakeClean(object->GetController());
    }
}

bool Object::IsAwareOfObject(const shared_ptr<Object>& object)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    return aware_objects_.find(object->GetObjectId()) != aware_objects_.end();
}

void Object::RemoveAwareObject(const shared_ptr<Object>& object)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    auto find_iter = aware_objects_.find(object->GetObjectId());

    if (find_iter == aware_objects_.end())
    {
        // @TODO consider whether encountering this scenario is an error
        return;
    }

    aware_objects_.erase(find_iter);

    if (HasController())
    {
        object->Unsubscribe(GetController());
    }
}
const string& Object::GetTemplate()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	return template_string_;
}
void Object::SetTemplate(const string& template_string)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	template_string_ = template_string;
}
void Object::SetObjectId(uint64_t object_id)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	object_id_ = object_id;
}
uint64_t Object::GetObjectId()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    return object_id_;
}

const wstring& Object::GetCustomName()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    return custom_name_;
}

void Object::SetCustomName(wstring custom_name)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    custom_name_ = custom_name;

    // Only build a message if there are observers.
    if (HasObservers())
    {
        DeltasMessage message = CreateDeltasMessage(Object::VIEW_3, 2);
        message.data.write(custom_name);

        AddDeltasUpdate(message);
    }
}

BaselinesMessage Object::CreateBaselinesMessage(uint16_t view_type, uint16_t opcount)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    BaselinesMessage message;
    message.object_id = GetObjectId();
    message.object_type = GetType();
    message.view_type = view_type;
    message.object_opcount = opcount;

    return message;
}

DeltasMessage Object::CreateDeltasMessage(uint16_t view_type, uint16_t update_type, uint16_t update_count)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    DeltasMessage message;
    message.object_id = GetObjectId();
    message.object_type = GetType();
    message.view_type = view_type;
    message.update_count = update_count;
    message.update_type = update_type;
    return message;
}

bool Object::HasObservers()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    return !observers_.empty();
}

void Object::Subscribe(const shared_ptr<ObserverInterface>& observer)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    auto find_iter = std::find_if(
        observers_.begin(),
        observers_.end(),
        [&observer] (const std::shared_ptr<ObserverInterface>& stored_observer)
    {
        return observer == stored_observer;
    });

    if (find_iter != observers_.end())
    {
        return;
    }

    observers_.push_back(observer);
}

void Object::Unsubscribe(const shared_ptr<ObserverInterface>& observer)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    auto find_iter = std::find_if(
        observers_.begin(),
        observers_.end(),
        [&observer] (const std::shared_ptr<ObserverInterface>& stored_observer)
    {
        return observer == stored_observer;
    });

    if (find_iter == observers_.end())
    {
        return;
    }

    observers_.erase(find_iter);
}

void Object::NotifyObservers(const anh::ByteBuffer& message)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    NotifyObservers<anh::ByteBuffer>(message);
}

bool Object::IsDirty()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    return !deltas_.empty();
}

void Object::MakeClean(std::shared_ptr<swganh::object::ObjectController> controller)
{
    boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    baselines_.clear();
    deltas_.clear();

    // SceneCreateObjectByCrc
    swganh::messages::SceneCreateObjectByCrc scene_object;
    scene_object.object_id = GetObjectId();
    scene_object.object_crc = anh::memcrc(GetTemplate());
    scene_object.position = GetPosition();
	scene_object.orientation = GetOrientation();
    controller->Notify(scene_object);

    if (GetContainer())
    {
        UpdateContainmentMessage containment_message;
        containment_message.container_id = GetContainer()->GetObjectId();
        containment_message.object_id = GetObjectId();
        containment_message.containment_type = 4;

        controller->Notify(containment_message);
    }

    // Baselines
    optional<BaselinesMessage> message;
    for_each(begin(baselines_builders_), end(baselines_builders_),
        [this, &message, &controller] (BaselinesBuilder& builder)
    {
        if (!(message = builder()))
        {
            return;
        }

        controller->Notify(*message);
        baselines_.push_back(*message);
    });

    // SceneEndBaselines
    swganh::messages::SceneEndBaselines scene_end_baselines;
    scene_end_baselines.object_id = GetObjectId();
    controller->Notify(scene_end_baselines);
}

const BaselinesCacheContainer& Object::GetBaselines(uint64_t viewer_id)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    return baselines_;
}

const DeltasCacheContainer& Object::GetDeltas(uint64_t viewer_id)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    return deltas_;
}

void Object::AddDeltasUpdate(DeltasMessage message)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    NotifyObservers(message);
    deltas_.push_back(move(message));
}

void Object::AddBaselinesBuilders_()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    baselines_builders_.push_back([this] () {
        return GetBaseline1();
    });

    baselines_builders_.push_back([this] () {
        return GetBaseline2();
    });

    baselines_builders_.push_back([this] () {
        return GetBaseline3();
    });

    baselines_builders_.push_back([this] () {
        return GetBaseline4();
    });

    baselines_builders_.push_back([this] () {
        return GetBaseline5();
    });

    baselines_builders_.push_back([this] () {
        return GetBaseline6();
    });

    baselines_builders_.push_back([this] () {
        return GetBaseline7();
    });

    baselines_builders_.push_back([this] () {
        return GetBaseline8();
    });

    baselines_builders_.push_back([this] () {
        return GetBaseline9();
    });
}

void Object::SetPosition(glm::vec3 position)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    position_ = position;
}
glm::vec3 Object::GetPosition()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	return position_;
}
void Object::SetOrientation(glm::quat orientation)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    orientation_ = orientation;
}
glm::quat Object::GetOrientation()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	return orientation_;
}

uint8_t Object::GetHeading()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    glm::quat tmp = orientation_;

    if (tmp.y < 0.0f && tmp.w > 0.0f) {
        tmp.w *= -1;
    }

    return static_cast<uint8_t>((glm::angle(tmp) / 6.283f) * 100);
}

void Object::SetContainer(const std::shared_ptr<Object>& container)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    container_ = container;
}
const shared_ptr<Object>& Object::GetContainer()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	return container_;
}
void Object::SetComplexity(float complexity)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    complexity_ = complexity;
    ObjectMessageBuilder::BuildComplexityDelta(this);
}
float Object::GetComplexity()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	return complexity_;
}
void Object::SetStfNameFile(const string& stf_name_file)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    stf_name_file_ = stf_name_file;
    ObjectMessageBuilder::BuildStfNameDelta(this);
}
const string& Object::GetStfNameFile()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	return stf_name_file_;
}
void Object::SetStfNameString(const string& stf_name_string)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    stf_name_string_ = stf_name_string;
    ObjectMessageBuilder::BuildStfNameDelta(this);
}
const string& Object::GetStfNameString()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	return stf_name_string_;
}
void Object::SetVolume(uint32_t volume)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
    volume_ = volume;
    ObjectMessageBuilder::BuildVolumeDelta(this);
}
uint32_t Object::GetVolume()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	return volume_;
}
void Object::SetSceneId(uint32_t scene_id)
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	scene_id_ = scene_id;
}
uint32_t Object::GetSceneId()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	return scene_id_;
}
optional<BaselinesMessage> Object::GetBaseline3()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	return move(ObjectMessageBuilder::BuildBaseline3(this));
}

optional<BaselinesMessage> Object::GetBaseline6()
{
	boost::lock_guard<boost::recursive_mutex> lock(mutex_);
	return move(ObjectMessageBuilder::BuildBaseline6(this));
}
<|endoftext|>