<commit_before>/*
 *    Copyright (c) 2017, The OpenThread Authors.
 *    All rights reserved.
 *
 *    Redistribution and use in source and binary forms, with or without
 *    modification, are permitted provided that the following conditions are met:
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *    2. 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.
 *    3. 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.
 */

/**
 * @file
 *   This file implements a spinel encoder.
 */

#include "spinel_encoder.hpp"

#include "common/code_utils.hpp"

namespace ot {
namespace Ncp {

otError SpinelEncoder::BeginFrame(NcpFrameBuffer::Priority aPriority)
{
    mNumOpenStructs = 0;
    return mNcpBuffer.InFrameBegin(aPriority);
}

otError SpinelEncoder::BeginFrame(uint8_t aHeader, unsigned int aCommand)
{
    otError error = OT_ERROR_NONE;

    // Non-zero TID indicates this is a response to a spinel command.

    if (SPINEL_HEADER_GET_TID(aHeader) != 0)
    {
        SuccessOrExit(error = BeginFrame(NcpFrameBuffer::kPriorityHigh));
    }
    else
    {
        SuccessOrExit(error = BeginFrame(NcpFrameBuffer::kPriorityLow));
    }

    SuccessOrExit(error = WriteUint8(aHeader));
    SuccessOrExit(error = WriteUintPacked(aCommand));

exit:
    return error;
}

otError SpinelEncoder::BeginFrame(uint8_t aHeader, unsigned int aCommand, spinel_prop_key_t aKey)
{
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error = BeginFrame(aHeader, aCommand));

    // The write position is saved before writing the property key,
    // so that if fetching the property fails and we need to
    // reply with a `LAST_STATUS` error we can get back to
    // this saved write position and update the property key.
    // (Also see `OverwriteWithLastStatusError()`).

    SuccessOrExit(error = SavePosition());
    SuccessOrExit(error = WriteUintPacked(aKey));

exit:
    return error;
}

otError SpinelEncoder::OverwriteWithLastStatusError(spinel_status_t aStatus)
{
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error = ResetToSaved());
    SuccessOrExit(error = WriteUintPacked(SPINEL_PROP_LAST_STATUS));
    SuccessOrExit(error = WriteUintPacked(aStatus));

exit:
    return error;
}

otError SpinelEncoder::EndFrame(void)
{
    otError error = OT_ERROR_NONE;

    while (mNumOpenStructs > 0)
    {
        SuccessOrExit(error = CloseStruct());
    }

    error = mNcpBuffer.InFrameEnd();

exit:
    return error;
}

otError SpinelEncoder::WriteUint16(uint16_t aUint16)
{
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint16 >> 0) & 0xff));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint16 >> 8) & 0xff));

exit:
    return error;
}

otError SpinelEncoder::WriteUint32(uint32_t aUint32)
{
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint32 >>  0) & 0xff));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint32 >>  8) & 0xff));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint32 >> 16) & 0xff));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint32 >> 24) & 0xff));

exit:
    return error;
}

otError SpinelEncoder::WriteUint64(uint64_t aUint64)
{
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint64 >>  0) & 0xff));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint64 >>  8) & 0xff));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint64 >> 16) & 0xff));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint64 >> 24) & 0xff));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint64 >> 32) & 0xff));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint64 >> 40) & 0xff));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint64 >> 48) & 0xff));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint64 >> 56) & 0xff));

exit:
    return error;
}

otError SpinelEncoder::WriteUintPacked(unsigned int aUint)
{
    uint8_t buffer[6];
    spinel_ssize_t len;

    len = spinel_packed_uint_encode(buffer, sizeof(buffer), aUint);

    return WriteData(buffer, static_cast<uint16_t>(len));
}

otError SpinelEncoder::WriteDataWithLen(const uint8_t *aData, uint16_t aDataLen)
{
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error = WriteUint16(aDataLen));
    SuccessOrExit(error = WriteData(aData, aDataLen));

exit:
    return error;
}

otError SpinelEncoder::WriteUtf8(const char *aUtf8)
{
    otError error;
    size_t len = strlen(aUtf8);

    if (len >= 0xffff)
    {
        len = 0xffff;
    }

    SuccessOrExit(error = WriteData(reinterpret_cast<const uint8_t *>(aUtf8), static_cast<uint16_t>(len)));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte(0));

exit:
    return error;
}

otError SpinelEncoder::OpenStruct(void)
{
    otError error = OT_ERROR_NONE;

    VerifyOrExit(mNumOpenStructs < kMaxNestedStructs, error = OT_ERROR_INVALID_STATE);
    SuccessOrExit(error = mNcpBuffer.InFrameGetPosition(mStructPosition[mNumOpenStructs]));

    // Reserve bytes for the length to be filled when the struct gets closed.
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte(0));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte(0));

    mNumOpenStructs++;

exit:
    return error;
}

otError SpinelEncoder::CloseStruct(void)
{
    otError error = OT_ERROR_NONE;
    uint16_t len;
    uint8_t buffer[sizeof(uint16_t)];

    VerifyOrExit(mNumOpenStructs > 0, error = OT_ERROR_INVALID_STATE);

    mNumOpenStructs--;

    len = mNcpBuffer.InFrameGetDistance(mStructPosition[mNumOpenStructs]);
    VerifyOrExit(len >= sizeof(uint16_t), error = OT_ERROR_INVALID_STATE);

    len -= sizeof(uint16_t);

    buffer[0] = (len >> 0 & 0xff);
    buffer[1] = (len >> 8 & 0xff);

    SuccessOrExit(error = mNcpBuffer.InFrameOverwrite(mStructPosition[mNumOpenStructs], buffer, sizeof(buffer)));

exit:
    return error;
}

otError SpinelEncoder::SavePosition(void)
{
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error = mNcpBuffer.InFrameGetPosition(mSavedPosition));
    mSavedNumOpenStructs = mNumOpenStructs;

exit:
    return error;
}

otError SpinelEncoder::ResetToSaved(void)
{
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error =  mNcpBuffer.InFrameReset(mSavedPosition));
    mNumOpenStructs = mSavedNumOpenStructs;

exit:
    return error;
}

otError SpinelEncoder::WritePacked(const char *aPackFormat, ...)
{
    uint8_t buf[kPackFormatBufferSize];
    otError error = OT_ERROR_NONE;
    spinel_ssize_t packedLen;
    va_list args;

    va_start(args, aPackFormat);

    packedLen = spinel_datatype_vpack(buf, sizeof(buf), aPackFormat, args);
    VerifyOrExit((packedLen > 0) && (packedLen <= static_cast<spinel_ssize_t>(sizeof(buf))), error = OT_ERROR_NO_BUFS);

    error = mNcpBuffer.InFrameFeedData(buf, static_cast<uint16_t>(packedLen));

    va_end(args);

exit:
    return error;
}

otError SpinelEncoder::WriteVPacked(const char *aPackFormat, va_list aArgs)
{
    uint8_t buf[kPackFormatBufferSize];
    otError error = OT_ERROR_NONE;
    spinel_ssize_t packedLen;

    packedLen = spinel_datatype_vpack(buf, sizeof(buf), aPackFormat, aArgs);
    VerifyOrExit((packedLen > 0) && (packedLen <= static_cast<spinel_ssize_t>(sizeof(buf))), error = OT_ERROR_NO_BUFS);

    error = mNcpBuffer.InFrameFeedData(buf, static_cast<uint16_t>(packedLen));

exit:
    return error;
}

}  // namespace Ncp
}  // namespace ot
<commit_msg>[spinel] move call to va_end to exit path (#2390)<commit_after>/*
 *    Copyright (c) 2017, The OpenThread Authors.
 *    All rights reserved.
 *
 *    Redistribution and use in source and binary forms, with or without
 *    modification, are permitted provided that the following conditions are met:
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *    2. 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.
 *    3. 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.
 */

/**
 * @file
 *   This file implements a spinel encoder.
 */

#include "spinel_encoder.hpp"

#include "common/code_utils.hpp"

namespace ot {
namespace Ncp {

otError SpinelEncoder::BeginFrame(NcpFrameBuffer::Priority aPriority)
{
    mNumOpenStructs = 0;
    return mNcpBuffer.InFrameBegin(aPriority);
}

otError SpinelEncoder::BeginFrame(uint8_t aHeader, unsigned int aCommand)
{
    otError error = OT_ERROR_NONE;

    // Non-zero TID indicates this is a response to a spinel command.

    if (SPINEL_HEADER_GET_TID(aHeader) != 0)
    {
        SuccessOrExit(error = BeginFrame(NcpFrameBuffer::kPriorityHigh));
    }
    else
    {
        SuccessOrExit(error = BeginFrame(NcpFrameBuffer::kPriorityLow));
    }

    SuccessOrExit(error = WriteUint8(aHeader));
    SuccessOrExit(error = WriteUintPacked(aCommand));

exit:
    return error;
}

otError SpinelEncoder::BeginFrame(uint8_t aHeader, unsigned int aCommand, spinel_prop_key_t aKey)
{
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error = BeginFrame(aHeader, aCommand));

    // The write position is saved before writing the property key,
    // so that if fetching the property fails and we need to
    // reply with a `LAST_STATUS` error we can get back to
    // this saved write position and update the property key.
    // (Also see `OverwriteWithLastStatusError()`).

    SuccessOrExit(error = SavePosition());
    SuccessOrExit(error = WriteUintPacked(aKey));

exit:
    return error;
}

otError SpinelEncoder::OverwriteWithLastStatusError(spinel_status_t aStatus)
{
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error = ResetToSaved());
    SuccessOrExit(error = WriteUintPacked(SPINEL_PROP_LAST_STATUS));
    SuccessOrExit(error = WriteUintPacked(aStatus));

exit:
    return error;
}

otError SpinelEncoder::EndFrame(void)
{
    otError error = OT_ERROR_NONE;

    while (mNumOpenStructs > 0)
    {
        SuccessOrExit(error = CloseStruct());
    }

    error = mNcpBuffer.InFrameEnd();

exit:
    return error;
}

otError SpinelEncoder::WriteUint16(uint16_t aUint16)
{
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint16 >> 0) & 0xff));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint16 >> 8) & 0xff));

exit:
    return error;
}

otError SpinelEncoder::WriteUint32(uint32_t aUint32)
{
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint32 >>  0) & 0xff));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint32 >>  8) & 0xff));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint32 >> 16) & 0xff));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint32 >> 24) & 0xff));

exit:
    return error;
}

otError SpinelEncoder::WriteUint64(uint64_t aUint64)
{
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint64 >>  0) & 0xff));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint64 >>  8) & 0xff));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint64 >> 16) & 0xff));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint64 >> 24) & 0xff));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint64 >> 32) & 0xff));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint64 >> 40) & 0xff));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint64 >> 48) & 0xff));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte((aUint64 >> 56) & 0xff));

exit:
    return error;
}

otError SpinelEncoder::WriteUintPacked(unsigned int aUint)
{
    uint8_t buffer[6];
    spinel_ssize_t len;

    len = spinel_packed_uint_encode(buffer, sizeof(buffer), aUint);

    return WriteData(buffer, static_cast<uint16_t>(len));
}

otError SpinelEncoder::WriteDataWithLen(const uint8_t *aData, uint16_t aDataLen)
{
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error = WriteUint16(aDataLen));
    SuccessOrExit(error = WriteData(aData, aDataLen));

exit:
    return error;
}

otError SpinelEncoder::WriteUtf8(const char *aUtf8)
{
    otError error;
    size_t len = strlen(aUtf8);

    if (len >= 0xffff)
    {
        len = 0xffff;
    }

    SuccessOrExit(error = WriteData(reinterpret_cast<const uint8_t *>(aUtf8), static_cast<uint16_t>(len)));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte(0));

exit:
    return error;
}

otError SpinelEncoder::OpenStruct(void)
{
    otError error = OT_ERROR_NONE;

    VerifyOrExit(mNumOpenStructs < kMaxNestedStructs, error = OT_ERROR_INVALID_STATE);
    SuccessOrExit(error = mNcpBuffer.InFrameGetPosition(mStructPosition[mNumOpenStructs]));

    // Reserve bytes for the length to be filled when the struct gets closed.
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte(0));
    SuccessOrExit(error = mNcpBuffer.InFrameFeedByte(0));

    mNumOpenStructs++;

exit:
    return error;
}

otError SpinelEncoder::CloseStruct(void)
{
    otError error = OT_ERROR_NONE;
    uint16_t len;
    uint8_t buffer[sizeof(uint16_t)];

    VerifyOrExit(mNumOpenStructs > 0, error = OT_ERROR_INVALID_STATE);

    mNumOpenStructs--;

    len = mNcpBuffer.InFrameGetDistance(mStructPosition[mNumOpenStructs]);
    VerifyOrExit(len >= sizeof(uint16_t), error = OT_ERROR_INVALID_STATE);

    len -= sizeof(uint16_t);

    buffer[0] = (len >> 0 & 0xff);
    buffer[1] = (len >> 8 & 0xff);

    SuccessOrExit(error = mNcpBuffer.InFrameOverwrite(mStructPosition[mNumOpenStructs], buffer, sizeof(buffer)));

exit:
    return error;
}

otError SpinelEncoder::SavePosition(void)
{
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error = mNcpBuffer.InFrameGetPosition(mSavedPosition));
    mSavedNumOpenStructs = mNumOpenStructs;

exit:
    return error;
}

otError SpinelEncoder::ResetToSaved(void)
{
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error =  mNcpBuffer.InFrameReset(mSavedPosition));
    mNumOpenStructs = mSavedNumOpenStructs;

exit:
    return error;
}

otError SpinelEncoder::WritePacked(const char *aPackFormat, ...)
{
    uint8_t buf[kPackFormatBufferSize];
    otError error = OT_ERROR_NONE;
    spinel_ssize_t packedLen;
    va_list args;

    va_start(args, aPackFormat);

    packedLen = spinel_datatype_vpack(buf, sizeof(buf), aPackFormat, args);
    VerifyOrExit((packedLen > 0) && (packedLen <= static_cast<spinel_ssize_t>(sizeof(buf))), error = OT_ERROR_NO_BUFS);

    error = mNcpBuffer.InFrameFeedData(buf, static_cast<uint16_t>(packedLen));

exit:
    va_end(args);

    return error;
}

otError SpinelEncoder::WriteVPacked(const char *aPackFormat, va_list aArgs)
{
    uint8_t buf[kPackFormatBufferSize];
    otError error = OT_ERROR_NONE;
    spinel_ssize_t packedLen;

    packedLen = spinel_datatype_vpack(buf, sizeof(buf), aPackFormat, aArgs);
    VerifyOrExit((packedLen > 0) && (packedLen <= static_cast<spinel_ssize_t>(sizeof(buf))), error = OT_ERROR_NO_BUFS);

    error = mNcpBuffer.InFrameFeedData(buf, static_cast<uint16_t>(packedLen));

exit:
    return error;
}

}  // namespace Ncp
}  // namespace ot
<|endoftext|>


<commit_before>/*    Copyright (c) 2010-2017, Delft University of Technology
 *    All rigths reserved
 *
 *    This file is part of the Tudat. Redistribution and use in source and
 *    binary forms, with or without modification, are permitted exclusively
 *    under the terms of the Modified BSD license. You should have received
 *    a copy of the license with this file. If not, please or visit:
 *    http://tudat.tudelft.nl/LICENSE.
 *
 */

#include "ephemeris.h"

#include "Tudat/External/JsonInterface/Mathematics/interpolation.h"

namespace tudat
{

namespace simulation_setup
{

//! Create a `json` object from a shared pointer to a `EphemerisSettings` object.
void to_json( json& jsonObject, const boost::shared_ptr< EphemerisSettings >& ephemerisSettings )
{
    if ( ! ephemerisSettings )
    {
        return;
    }
    using namespace json_interface;
    using K = Keys::Body::Ephemeris;

    // Common keys
    const EphemerisType ephemerisType = ephemerisSettings->getEphemerisType( );
    jsonObject[ K::type ] = ephemerisType;
    jsonObject[ K::frameOrigin ] = ephemerisSettings->getFrameOrigin( );
    jsonObject[ K::frameOrientation ] = ephemerisSettings->getFrameOrientation( );
    jsonObject[ K::makeMultiArc ] = ephemerisSettings->getMakeMultiArcEphemeris( );

    switch ( ephemerisType )
    {
    case approximate_planet_positions:
    {
        boost::shared_ptr< ApproximatePlanetPositionSettings > approximatePlanetPositionSettings =
                boost::dynamic_pointer_cast< ApproximatePlanetPositionSettings >( ephemerisSettings );
        enforceNonNullPointer( approximatePlanetPositionSettings );
        jsonObject[ K::bodyIdentifier ] = approximatePlanetPositionSettings->getBodyIdentifier( );
        jsonObject[ K::useCircularCoplanarApproximation ] =
                approximatePlanetPositionSettings->getUseCircularCoplanarApproximation( );
        return;
    }
    case direct_spice_ephemeris:
    {
        boost::shared_ptr< DirectSpiceEphemerisSettings > directSpiceEphemerisSettings =
                boost::dynamic_pointer_cast< DirectSpiceEphemerisSettings >( ephemerisSettings );
        enforceNonNullPointer( directSpiceEphemerisSettings );
        jsonObject[ K::correctForStellarAbberation ] =
                directSpiceEphemerisSettings->getCorrectForStellarAbberation( );
        jsonObject[ K::correctForLightTimeAbberation ] =
                directSpiceEphemerisSettings->getCorrectForLightTimeAbberation( );
        jsonObject[ K::convergeLighTimeAbberation ] =
                directSpiceEphemerisSettings->getConvergeLighTimeAbberation( );
        return;
    }
    case interpolated_spice:
    {
        boost::shared_ptr< InterpolatedSpiceEphemerisSettings > interpolatedSpiceEphemerisSettings =
                boost::dynamic_pointer_cast< InterpolatedSpiceEphemerisSettings >( ephemerisSettings );
        enforceNonNullPointer( interpolatedSpiceEphemerisSettings );
        jsonObject[ K::initialTime ] = interpolatedSpiceEphemerisSettings->getInitialTime( );
        jsonObject[ K::finalTime ] = interpolatedSpiceEphemerisSettings->getFinalTime( );
        jsonObject[ K::timeStep ] = interpolatedSpiceEphemerisSettings->getTimeStep( );
        jsonObject[ K::interpolator ] = interpolatedSpiceEphemerisSettings->getInterpolatorSettings( );
        jsonObject[ K::useLongDoubleStates ] = interpolatedSpiceEphemerisSettings->getUseLongDoubleStates( );
        return;
    }
    case tabulated_ephemeris:
    {
        boost::shared_ptr< TabulatedEphemerisSettings > tabulatedEphemerisSettings =
                boost::dynamic_pointer_cast< TabulatedEphemerisSettings >( ephemerisSettings );
        enforceNonNullPointer( tabulatedEphemerisSettings );
        jsonObject[ K::bodyStateHistory ] = tabulatedEphemerisSettings->getBodyStateHistory( );
        jsonObject[ K::useLongDoubleStates ] = tabulatedEphemerisSettings->getUseLongDoubleStates( );
        return;
    }
    case constant_ephemeris:
    {
        boost::shared_ptr< ConstantEphemerisSettings > constantEphemerisSettings =
                boost::dynamic_pointer_cast< ConstantEphemerisSettings >( ephemerisSettings );
        enforceNonNullPointer( constantEphemerisSettings );
        jsonObject[ K::constantState ] = constantEphemerisSettings->getConstantState( );
        return;
    }
    case kepler_ephemeris:
    {
        boost::shared_ptr< KeplerEphemerisSettings > keplerEphemerisSettings =
                boost::dynamic_pointer_cast< KeplerEphemerisSettings >( ephemerisSettings );
        enforceNonNullPointer( keplerEphemerisSettings );
        jsonObject[ K::initialStateInKeplerianElements ] =
                keplerEphemerisSettings->getInitialStateInKeplerianElements( );
        jsonObject[ K::epochOfInitialState ] =
                keplerEphemerisSettings->getEpochOfInitialState( );
        jsonObject[ K::centralBodyGravitationalParameter ] =
                keplerEphemerisSettings->getCentralBodyGravitationalParameter( );
        jsonObject[ K::rootFinderAbsoluteTolerance ] =
                keplerEphemerisSettings->getRootFinderAbsoluteTolerance( );
        jsonObject[ K::rootFinderMaximumNumberOfIterations ] =
                keplerEphemerisSettings->getRootFinderMaximumNumberOfIterations( );
        return;
    }
    default:
        handleUnimplementedEnumValue( ephemerisType, ephemerisTypes, unsupportedEphemerisTypes );
    }
}

//! Create a shared pointer to a `EphemerisSettings` object from a `json` object.
void from_json( const json& jsonObject, boost::shared_ptr< EphemerisSettings >& ephemerisSettings )
{
    using namespace ephemerides;
    using namespace json_interface;
    using K = Keys::Body::Ephemeris;

    // Get atmosphere model type
    const EphemerisType ephemerisType = getValue< EphemerisType >( jsonObject, K::type );

    switch ( ephemerisType ) {
    case approximate_planet_positions:
    {
        ephemerisSettings = boost::make_shared< ApproximatePlanetPositionSettings >(
                    getValue< ApproximatePlanetPositionsBase::BodiesWithEphemerisData >(
                        jsonObject, K::bodyIdentifier ),
                    getValue< bool >( jsonObject, K::useCircularCoplanarApproximation ) );
        break;
    }
    case direct_spice_ephemeris:
    {
        DirectSpiceEphemerisSettings defaults;
        ephemerisSettings = boost::make_shared< DirectSpiceEphemerisSettings >(
                    defaults.getFrameOrigin( ),
                    defaults.getFrameOrientation( ),
                    getValue( jsonObject, K::correctForStellarAbberation,
                              defaults.getCorrectForStellarAbberation( ) ),
                    getValue( jsonObject, K::correctForLightTimeAbberation,
                              defaults.getCorrectForLightTimeAbberation( ) ),
                    getValue( jsonObject, K::convergeLighTimeAbberation,
                              defaults.getConvergeLighTimeAbberation( ) ) );
        break;
    }
    case tabulated_ephemeris:
    {
        TabulatedEphemerisSettings defaults( { } );
        TabulatedEphemerisSettings tabulatedEphemerisSettings(
                    getValue< std::map< double, Eigen::Vector6d > >( jsonObject, K::bodyStateHistory ) );
        tabulatedEphemerisSettings.setUseLongDoubleStates(
                    getValue( jsonObject, K::useLongDoubleStates, defaults.getUseLongDoubleStates( ) ) );
        ephemerisSettings = boost::make_shared< TabulatedEphemerisSettings >( tabulatedEphemerisSettings );
        break;
    }
    case interpolated_spice:
    {
        InterpolatedSpiceEphemerisSettings defaults( TUDAT_NAN, TUDAT_NAN, TUDAT_NAN );
        InterpolatedSpiceEphemerisSettings interpolatedSpiceEphemerisSettings(
                    getValue< double >( jsonObject, K::initialTime ),
                    getValue< double >( jsonObject, K::finalTime ),
                    getValue< double >( jsonObject, K::timeStep ),
                    defaults.getFrameOrigin( ),
                    defaults.getFrameOrientation( ),
                    getValue( jsonObject, K::interpolator, defaults.getInterpolatorSettings( ) ) );
        interpolatedSpiceEphemerisSettings.setUseLongDoubleStates(
                    getValue( jsonObject, K::useLongDoubleStates, defaults.getUseLongDoubleStates( ) ) );
        ephemerisSettings = boost::make_shared< InterpolatedSpiceEphemerisSettings >(
                    interpolatedSpiceEphemerisSettings );
        break;
    }
    case constant_ephemeris:
    {
        ConstantEphemerisSettings defaults( ( Eigen::Vector6d( ) ) );
        ephemerisSettings = boost::make_shared< ConstantEphemerisSettings >(
                    getValue< Eigen::Vector6d >( jsonObject, K::constantState ) );
        break;
    }
    case kepler_ephemeris:
    {
        KeplerEphemerisSettings defaults( Eigen::Vector6d( ), TUDAT_NAN, TUDAT_NAN );
        ephemerisSettings = boost::make_shared< KeplerEphemerisSettings >(
                    getValue< Eigen::Vector6d >( jsonObject, K::initialStateInKeplerianElements ),
                    getValue< double >( jsonObject, K::epochOfInitialState ),
                    getValue< double >( jsonObject, K::centralBodyGravitationalParameter ),
                    defaults.getFrameOrigin( ),
                    defaults.getFrameOrientation( ),
                    getValue( jsonObject, K::rootFinderAbsoluteTolerance,
                              defaults.getRootFinderAbsoluteTolerance( ) ),
                    getValue( jsonObject, K::rootFinderMaximumNumberOfIterations,
                              defaults.getRootFinderMaximumNumberOfIterations( ) ) );
        break;
    }
        /* FIXME
    case custom_ephemeris:
    {

    }
    */
    default:
        handleUnimplementedEnumValue( ephemerisType, ephemerisTypes, unsupportedEphemerisTypes );
    }

    if ( defined( jsonObject, K::frameOrigin ) )
    {
        ephemerisSettings->resetFrameOrigin( getValue< std::string >( jsonObject, K::frameOrigin ) );
    }

    if ( defined( jsonObject, K::frameOrientation ) )
    {
        ephemerisSettings->resetFrameOrientation( getValue< std::string >( jsonObject, K::frameOrientation ) );
    }

    if ( defined( jsonObject, K::makeMultiArc ) )
    {
        ephemerisSettings->resetMakeMultiArcEphemeris( getValue< bool >( jsonObject, K::makeMultiArc ) );
    }
}

} // namespace simulation_setup

} // namespace tudat
<commit_msg>Fix bug tabulated ephemeris<commit_after>/*    Copyright (c) 2010-2017, Delft University of Technology
 *    All rigths reserved
 *
 *    This file is part of the Tudat. Redistribution and use in source and
 *    binary forms, with or without modification, are permitted exclusively
 *    under the terms of the Modified BSD license. You should have received
 *    a copy of the license with this file. If not, please or visit:
 *    http://tudat.tudelft.nl/LICENSE.
 *
 */

#include "ephemeris.h"

#include "Tudat/External/JsonInterface/Mathematics/interpolation.h"

namespace tudat
{

namespace simulation_setup
{

//! Create a `json` object from a shared pointer to a `EphemerisSettings` object.
void to_json( json& jsonObject, const boost::shared_ptr< EphemerisSettings >& ephemerisSettings )
{
    if ( ! ephemerisSettings )
    {
        return;
    }
    using namespace json_interface;
    using K = Keys::Body::Ephemeris;

    // Common keys
    const EphemerisType ephemerisType = ephemerisSettings->getEphemerisType( );
    jsonObject[ K::type ] = ephemerisType;
    jsonObject[ K::frameOrigin ] = ephemerisSettings->getFrameOrigin( );
    jsonObject[ K::frameOrientation ] = ephemerisSettings->getFrameOrientation( );
    jsonObject[ K::makeMultiArc ] = ephemerisSettings->getMakeMultiArcEphemeris( );

    switch ( ephemerisType )
    {
    case approximate_planet_positions:
    {
        boost::shared_ptr< ApproximatePlanetPositionSettings > approximatePlanetPositionSettings =
                boost::dynamic_pointer_cast< ApproximatePlanetPositionSettings >( ephemerisSettings );
        enforceNonNullPointer( approximatePlanetPositionSettings );
        jsonObject[ K::bodyIdentifier ] = approximatePlanetPositionSettings->getBodyIdentifier( );
        jsonObject[ K::useCircularCoplanarApproximation ] =
                approximatePlanetPositionSettings->getUseCircularCoplanarApproximation( );
        return;
    }
    case direct_spice_ephemeris:
    {
        boost::shared_ptr< DirectSpiceEphemerisSettings > directSpiceEphemerisSettings =
                boost::dynamic_pointer_cast< DirectSpiceEphemerisSettings >( ephemerisSettings );
        enforceNonNullPointer( directSpiceEphemerisSettings );
        jsonObject[ K::correctForStellarAbberation ] =
                directSpiceEphemerisSettings->getCorrectForStellarAbberation( );
        jsonObject[ K::correctForLightTimeAbberation ] =
                directSpiceEphemerisSettings->getCorrectForLightTimeAbberation( );
        jsonObject[ K::convergeLighTimeAbberation ] =
                directSpiceEphemerisSettings->getConvergeLighTimeAbberation( );
        return;
    }
    case interpolated_spice:
    {
        boost::shared_ptr< InterpolatedSpiceEphemerisSettings > interpolatedSpiceEphemerisSettings =
                boost::dynamic_pointer_cast< InterpolatedSpiceEphemerisSettings >( ephemerisSettings );
        enforceNonNullPointer( interpolatedSpiceEphemerisSettings );
        jsonObject[ K::initialTime ] = interpolatedSpiceEphemerisSettings->getInitialTime( );
        jsonObject[ K::finalTime ] = interpolatedSpiceEphemerisSettings->getFinalTime( );
        jsonObject[ K::timeStep ] = interpolatedSpiceEphemerisSettings->getTimeStep( );
        jsonObject[ K::interpolator ] = interpolatedSpiceEphemerisSettings->getInterpolatorSettings( );
        jsonObject[ K::useLongDoubleStates ] = interpolatedSpiceEphemerisSettings->getUseLongDoubleStates( );
        return;
    }
    case tabulated_ephemeris:
    {
        boost::shared_ptr< TabulatedEphemerisSettings > tabulatedEphemerisSettings =
                boost::dynamic_pointer_cast< TabulatedEphemerisSettings >( ephemerisSettings );
        enforceNonNullPointer( tabulatedEphemerisSettings );
        jsonObject[ K::bodyStateHistory ] = tabulatedEphemerisSettings->getBodyStateHistory( );
        jsonObject[ K::useLongDoubleStates ] = tabulatedEphemerisSettings->getUseLongDoubleStates( );
        return;
    }
    case constant_ephemeris:
    {
        boost::shared_ptr< ConstantEphemerisSettings > constantEphemerisSettings =
                boost::dynamic_pointer_cast< ConstantEphemerisSettings >( ephemerisSettings );
        enforceNonNullPointer( constantEphemerisSettings );
        jsonObject[ K::constantState ] = constantEphemerisSettings->getConstantState( );
        return;
    }
    case kepler_ephemeris:
    {
        boost::shared_ptr< KeplerEphemerisSettings > keplerEphemerisSettings =
                boost::dynamic_pointer_cast< KeplerEphemerisSettings >( ephemerisSettings );
        enforceNonNullPointer( keplerEphemerisSettings );
        jsonObject[ K::initialStateInKeplerianElements ] =
                keplerEphemerisSettings->getInitialStateInKeplerianElements( );
        jsonObject[ K::epochOfInitialState ] =
                keplerEphemerisSettings->getEpochOfInitialState( );
        jsonObject[ K::centralBodyGravitationalParameter ] =
                keplerEphemerisSettings->getCentralBodyGravitationalParameter( );
        jsonObject[ K::rootFinderAbsoluteTolerance ] =
                keplerEphemerisSettings->getRootFinderAbsoluteTolerance( );
        jsonObject[ K::rootFinderMaximumNumberOfIterations ] =
                keplerEphemerisSettings->getRootFinderMaximumNumberOfIterations( );
        return;
    }
    default:
        handleUnimplementedEnumValue( ephemerisType, ephemerisTypes, unsupportedEphemerisTypes );
    }
}

//! Create a shared pointer to a `EphemerisSettings` object from a `json` object.
void from_json( const json& jsonObject, boost::shared_ptr< EphemerisSettings >& ephemerisSettings )
{
    using namespace ephemerides;
    using namespace json_interface;
    using K = Keys::Body::Ephemeris;

    // Get atmosphere model type
    const EphemerisType ephemerisType = getValue< EphemerisType >( jsonObject, K::type );

    switch ( ephemerisType ) {
    case approximate_planet_positions:
    {
        ephemerisSettings = boost::make_shared< ApproximatePlanetPositionSettings >(
                    getValue< ApproximatePlanetPositionsBase::BodiesWithEphemerisData >(
                        jsonObject, K::bodyIdentifier ),
                    getValue< bool >( jsonObject, K::useCircularCoplanarApproximation ) );
        break;
    }
    case direct_spice_ephemeris:
    {
        DirectSpiceEphemerisSettings defaults;
        ephemerisSettings = boost::make_shared< DirectSpiceEphemerisSettings >(
                    defaults.getFrameOrigin( ),
                    defaults.getFrameOrientation( ),
                    getValue( jsonObject, K::correctForStellarAbberation,
                              defaults.getCorrectForStellarAbberation( ) ),
                    getValue( jsonObject, K::correctForLightTimeAbberation,
                              defaults.getCorrectForLightTimeAbberation( ) ),
                    getValue( jsonObject, K::convergeLighTimeAbberation,
                              defaults.getConvergeLighTimeAbberation( ) ) );
        break;
    }
    case tabulated_ephemeris:
    {
        TabulatedEphemerisSettings defaults( ( std::map< double, Eigen::Vector6d >( ) ) );
        TabulatedEphemerisSettings tabulatedEphemerisSettings(
                    getValue< std::map< double, Eigen::Vector6d > >( jsonObject, K::bodyStateHistory ) );
        tabulatedEphemerisSettings.setUseLongDoubleStates(
                    getValue( jsonObject, K::useLongDoubleStates, defaults.getUseLongDoubleStates( ) ) );
        ephemerisSettings = boost::make_shared< TabulatedEphemerisSettings >( tabulatedEphemerisSettings );
        break;
    }
    case interpolated_spice:
    {
        InterpolatedSpiceEphemerisSettings defaults( TUDAT_NAN, TUDAT_NAN, TUDAT_NAN );
        InterpolatedSpiceEphemerisSettings interpolatedSpiceEphemerisSettings(
                    getValue< double >( jsonObject, K::initialTime ),
                    getValue< double >( jsonObject, K::finalTime ),
                    getValue< double >( jsonObject, K::timeStep ),
                    defaults.getFrameOrigin( ),
                    defaults.getFrameOrientation( ),
                    getValue( jsonObject, K::interpolator, defaults.getInterpolatorSettings( ) ) );
        interpolatedSpiceEphemerisSettings.setUseLongDoubleStates(
                    getValue( jsonObject, K::useLongDoubleStates, defaults.getUseLongDoubleStates( ) ) );
        ephemerisSettings = boost::make_shared< InterpolatedSpiceEphemerisSettings >(
                    interpolatedSpiceEphemerisSettings );
        break;
    }
    case constant_ephemeris:
    {
        ConstantEphemerisSettings defaults( ( Eigen::Vector6d( ) ) );
        ephemerisSettings = boost::make_shared< ConstantEphemerisSettings >(
                    getValue< Eigen::Vector6d >( jsonObject, K::constantState ) );
        break;
    }
    case kepler_ephemeris:
    {
        KeplerEphemerisSettings defaults( Eigen::Vector6d( ), TUDAT_NAN, TUDAT_NAN );
        ephemerisSettings = boost::make_shared< KeplerEphemerisSettings >(
                    getValue< Eigen::Vector6d >( jsonObject, K::initialStateInKeplerianElements ),
                    getValue< double >( jsonObject, K::epochOfInitialState ),
                    getValue< double >( jsonObject, K::centralBodyGravitationalParameter ),
                    defaults.getFrameOrigin( ),
                    defaults.getFrameOrientation( ),
                    getValue( jsonObject, K::rootFinderAbsoluteTolerance,
                              defaults.getRootFinderAbsoluteTolerance( ) ),
                    getValue( jsonObject, K::rootFinderMaximumNumberOfIterations,
                              defaults.getRootFinderMaximumNumberOfIterations( ) ) );
        break;
    }
        /* FIXME
    case custom_ephemeris:
    {

    }
    */
    default:
        handleUnimplementedEnumValue( ephemerisType, ephemerisTypes, unsupportedEphemerisTypes );
    }

    if ( defined( jsonObject, K::frameOrigin ) )
    {
        ephemerisSettings->resetFrameOrigin( getValue< std::string >( jsonObject, K::frameOrigin ) );
    }

    if ( defined( jsonObject, K::frameOrientation ) )
    {
        ephemerisSettings->resetFrameOrientation( getValue< std::string >( jsonObject, K::frameOrientation ) );
    }

    if ( defined( jsonObject, K::makeMultiArc ) )
    {
        ephemerisSettings->resetMakeMultiArcEphemeris( getValue< bool >( jsonObject, K::makeMultiArc ) );
    }
}

} // namespace simulation_setup

} // namespace tudat
<|endoftext|>


<commit_before>/*
 *  comet_tool.cpp
 *  PHD Guiding
 *
 *  Created by Andy Galasso
 *  Copyright (c) 2014 Andy Galasso
 *  All rights reserved.
 *
 *  This source code is distributed under the following "BSD" license
 *  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 Craig Stark, Stark Labs 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 "phd.h"
#include "comet_tool.h"
#include "nudge_lock.h"

#include <wx/valnum.h>

struct CometToolWin : public wxDialog
{
    wxToggleButton *m_enable;
    wxStaticText *m_xLabel;
    wxSpinCtrlDouble *m_xRate;
    wxStaticText *m_yLabel;
    wxSpinCtrlDouble *m_yRate;
    wxRadioBox *m_units;
    wxRadioBox *m_axes;
    wxButton *m_start;
    wxButton *m_stop;
    wxTextCtrl *m_status;

    bool m_training;
    wxTimer m_timer;

    PHD_Point m_startPos;
    wxLongLong_t m_startTime;

    CometToolWin();
    ~CometToolWin();

    void OnClose(wxCloseEvent& event);
    void OnAppStateNotify(wxCommandEvent& event);
    void OnTimer(wxTimerEvent& event);
    void OnEnableToggled(wxCommandEvent& event);
    void OnSpinCtrlX(wxSpinDoubleEvent& event);
    void OnSpinCtrlY(wxSpinDoubleEvent& event);
    void OnUnits(wxCommandEvent& event);
    void OnAxes(wxCommandEvent& event);
    void OnStart(wxCommandEvent& event);
    void OnStop(wxCommandEvent& event);

    void UpdateGuiderShift();
    void CalcRate();
    void UpdateStatus();
};

static wxString TITLE = _("Comet Tracking");
static wxString TITLE_TRAINING = _("Comet Tracking - Training Active");

CometToolWin::CometToolWin()
    : wxDialog(pFrame, wxID_ANY, TITLE, wxPoint(-1,-1), wxSize(300,300)),
      m_training(false),
      m_timer(this)
{
    SetSizeHints( wxDefaultSize, wxDefaultSize );

    m_enable = new wxToggleButton(this, wxID_ANY, _("Enable"), wxDefaultPosition, wxDefaultSize, 0);
    m_enable->SetToolTip(_("Toggle comet tracking on or off."));

    m_xLabel = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(20,-1), wxALIGN_RIGHT);
    m_xLabel->Wrap(-1);
    m_yLabel = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(20, -1), wxALIGN_RIGHT);
    m_yLabel->Wrap(-1);

    m_xRate = new wxSpinCtrlDouble(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, -5000., +5000., 0., 1.);
    m_xRate->SetToolTip(_("Comet tracking rate"));
    m_yRate = new wxSpinCtrlDouble(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, -5000., +5000., 0., 1.);
    m_yRate->SetToolTip(_("Comet tracking rate"));

    wxString m_unitsChoices[] = { _("Pixels/hr"), _("Arcsec/hr") };
    int m_unitsNChoices = sizeof(m_unitsChoices) / sizeof(wxString);
    m_units = new wxRadioBox(this, wxID_ANY, _("Units"), wxDefaultPosition, wxDefaultSize, m_unitsNChoices, m_unitsChoices, 1, wxRA_SPECIFY_ROWS);
    m_units->SetSelection(1);
    m_units->SetToolTip(_("Tracking rate units"));

    wxString m_axesChoices[] = { _("Camera (X/Y)"), _("Mount (RA/Dec)") };
    int m_axesNChoices = sizeof(m_axesChoices) / sizeof(wxString);
    m_axes = new wxRadioBox(this, wxID_ANY, _("Axes"), wxDefaultPosition, wxDefaultSize, m_axesNChoices, m_axesChoices, 1, wxRA_SPECIFY_ROWS);
    m_axes->SetSelection(1);
    m_axes->SetToolTip(_("Tracking rate axes"));

    m_start = new wxButton(this, wxID_ANY, _("Start"), wxDefaultPosition, wxDefaultSize, 0);
    m_start->SetToolTip(_("Start training the tracking rate."));
    m_stop = new wxButton(this, wxID_ANY, _("Stop"), wxDefaultPosition, wxDefaultSize, 0);
    m_stop->SetToolTip(_("Stop training"));
    m_stop->Enable(false);

    // Use a text ctrl for status, wxStaticText flickers. Adding the wxTE_NO_VSCROLL style also causes the control to flicker on Windows 7.
    long style = wxSTATIC_BORDER | wxTE_MULTILINE /*| wxTE_NO_VSCROLL*/;
    m_status = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(400, 60), style);
    m_status->Enable(false);

    wxBoxSizer *xSizer = new wxBoxSizer(wxHORIZONTAL);
    xSizer->Add(0, 0, 1, wxEXPAND, 5);
    xSizer->Add(m_xLabel, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
    xSizer->Add(m_xRate, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
    xSizer->Add(0, 0, 1, wxEXPAND, 5);

    wxBoxSizer *ySizer = new wxBoxSizer(wxHORIZONTAL);
    ySizer->Add(0, 0, 1, wxEXPAND, 5);
    ySizer->Add(m_yLabel, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
    ySizer->Add(m_yRate, 0, wxALL, 5);
    ySizer->Add(0, 0, 1, wxEXPAND, 5);

    wxStaticBoxSizer *ratesSizer = new wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, _("Rates")), wxVERTICAL);
    ratesSizer->Add(xSizer, 1, wxEXPAND, 5);
    ratesSizer->Add(ySizer, 1, wxEXPAND, 5);
    ratesSizer->Add(m_units, 0, wxALL, 5);
    ratesSizer->Add(m_axes, 0, wxALL, 5);

    wxBoxSizer *startStopSizer = new wxBoxSizer(wxHORIZONTAL);
    startStopSizer->Add(0, 0, 1, wxEXPAND, 5);
    startStopSizer->Add(m_start, 0, wxALL, 5);
    startStopSizer->Add(m_stop, 0, wxALL, 5);
    startStopSizer->Add(0, 0, 1, wxEXPAND, 5);

    wxStaticBoxSizer *trainingSizer = new wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, _("Rate Training")), wxVERTICAL);
    trainingSizer->Add(startStopSizer, 1, wxEXPAND, 5);
    trainingSizer->Add(m_status, 0, wxALL, 5);

    wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL);
    topSizer->Add(m_enable, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5);
    topSizer->Add(ratesSizer, 1, wxEXPAND, 5);
    topSizer->Add(trainingSizer, 0, wxEXPAND, 5);

    SetSizer(topSizer);
    Layout();
    topSizer->Fit(this);

    // Connect Events
    Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(CometToolWin::OnClose));
    Connect(APPSTATE_NOTIFY_EVENT, wxCommandEventHandler(CometToolWin::OnAppStateNotify));
    Connect(wxEVT_TIMER, wxTimerEventHandler(CometToolWin::OnTimer));
    m_enable->Connect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(CometToolWin::OnEnableToggled), NULL, this);
    m_xRate->Connect(wxEVT_SPINCTRLDOUBLE, wxSpinDoubleEventHandler(CometToolWin::OnSpinCtrlX), NULL, this);
    m_yRate->Connect(wxEVT_SPINCTRLDOUBLE, wxSpinDoubleEventHandler(CometToolWin::OnSpinCtrlY), NULL, this);
    m_units->Connect(wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler(CometToolWin::OnUnits), NULL, this);
    m_axes->Connect(wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler(CometToolWin::OnAxes), NULL, this);
    m_start->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(CometToolWin::OnStart), NULL, this);
    m_stop->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(CometToolWin::OnStop), NULL, this);

    int xpos = pConfig->Global.GetInt("/CometTool/pos.x", -1);
    int ypos = pConfig->Global.GetInt("/CometTool/pos.y", -1);
    if (xpos == -1 || ypos == -1)
        Centre(wxBOTH);
    else
        Move(xpos, ypos);

    UpdateStatus();

    wxCommandEvent dummy;
    OnAppStateNotify(dummy); // init controls
}

CometToolWin::~CometToolWin(void)
{
    pFrame->pCometTool = 0;
}

void CometToolWin::OnEnableToggled(wxCommandEvent& event)
{
    pFrame->pGuider->EnableLockPosShift(m_enable->GetValue());
}

void CometToolWin::UpdateGuiderShift()
{
    PHD_Point rate(m_xRate->GetValue(), m_yRate->GetValue());
    GRAPH_UNITS units = m_units->GetSelection() == 0 ? UNIT_PIXELS : UNIT_ARCSEC;
    bool isMountCoords = m_axes->GetSelection() == 1;
    pFrame->pGuider->SetLockPosShiftRate(rate, units, isMountCoords);
}

void CometToolWin::OnSpinCtrlX(wxSpinDoubleEvent& event)
{
    UpdateGuiderShift();
}

void CometToolWin::OnSpinCtrlY(wxSpinDoubleEvent& event)
{
    UpdateGuiderShift();
}

void CometToolWin::OnUnits(wxCommandEvent& event)
{
    UpdateGuiderShift();
}

void CometToolWin::OnAxes(wxCommandEvent& event)
{
    UpdateGuiderShift();
}

void CometToolWin::OnStart(wxCommandEvent& event)
{
    if (!pFrame->pGuider->IsGuiding())
        return;

    if (!pFrame->pNudgeLock)
        pFrame->pNudgeLock = NudgeLockTool::CreateNudgeLockToolWindow();
    pFrame->pNudgeLock->Show();

    m_startPos = pFrame->pGuider->LockPosition();
    m_startTime = ::wxGetUTCTimeMillis().GetValue();

    pFrame->pGuider->EnableLockPosShift(true);

    m_start->Enable(false);
    m_stop->Enable(true);
    m_units->Enable(false);
    m_axes->Enable(false);

    m_timer.Start(500);
    m_training = true;

    SetTitle(TITLE_TRAINING);
    UpdateStatus();
}

void CometToolWin::OnStop(wxCommandEvent& event)
{
    m_timer.Stop();
    m_training = false;

    m_start->Enable(pFrame->pGuider->IsGuiding());
    m_stop->Enable(false);
    m_units->Enable(true);
    m_axes->Enable(true);

    SetTitle(TITLE);
    UpdateStatus();
}

void CometToolWin::OnTimer(wxTimerEvent& WXUNUSED(evt))
{
    UpdateStatus();
}

void CometToolWin::CalcRate()
{
    double dt = (double) (::wxGetUTCTimeMillis().GetValue() - m_startTime) / 3600000.0; // hours
    PHD_Point rate = (pFrame->pGuider->LockPosition() - m_startPos) / dt;
    pFrame->pGuider->SetLockPosShiftRate(rate, UNIT_PIXELS, false);
}

void CometToolWin::UpdateStatus()
{
    if (m_training)
    {
        m_status->SetValue(wxString::Format(_("Training, elapsed time %lus.\nUse the "
            "\"Adjust Lock Position\" controls to center the comet\nin the imaging "
            "camera and click Stop to complete training."),
            (long)((::wxGetUTCTimeMillis().GetValue() - m_startTime) / 1000)));
    }
    else
    {
        m_status->SetValue(_("Center the comet in the imaging camera.\nSelect a guide "
            "star and start Guiding.\nThen, click Start to begin training."));
    }
}

void CometToolWin::OnAppStateNotify(wxCommandEvent& WXUNUSED(event))
{
    const LockPosShiftParams& shift = pFrame->pGuider->GetLockPosShiftParams();

    m_enable->SetValue(shift.shiftEnabled);

    m_xRate->SetValue(shift.shiftRate.X);
    m_yRate->SetValue(shift.shiftRate.Y);

    if (shift.shiftIsMountCoords)
    {
        m_axes->SetSelection(1);
        m_xLabel->SetLabel(_("RA"));
        m_yLabel->SetLabel(_("Dec"));
    }
    else
    {
        m_axes->SetSelection(0);
        m_xLabel->SetLabel(_("X"));
        m_yLabel->SetLabel(_("Y"));
    }

    if (shift.shiftUnits == UNIT_PIXELS)
    {
        m_units->SetSelection(0);
    }
    else
    {
        m_units->SetSelection(1);
    }

    if (m_training)
    {
        if (!pFrame->pGuider->IsGuiding())
        {
            // if guiding stopped, stop training
            wxCommandEvent dummy;
            OnStop(dummy);
        }
    }
    else
    {
        m_start->Enable(pFrame->pGuider->IsGuiding());
    }
}

void CometToolWin::OnClose(wxCloseEvent& evt)
{
    // save the window position
    int x, y;
    GetPosition(&x, &y);
    pConfig->Global.SetInt("/CometTool/pos.x", x);
    pConfig->Global.SetInt("/CometTool/pos.y", y);

    evt.Skip();
}

wxWindow *CometTool::CreateCometToolWindow()
{
    return new CometToolWin();
}

void CometTool::NotifyUpdateLockPos()
{
    if (pFrame && pFrame->pCometTool)
    {
        CometToolWin *win = static_cast<CometToolWin *>(pFrame->pCometTool);
        if (win->m_training)
            win->CalcRate();
    }
}

void CometTool::UpdateCometToolControls()
{
    // notify comet tool to update its controls
    if (pFrame && pFrame->pCometTool)
    {
        wxCommandEvent event(APPSTATE_NOTIFY_EVENT, pFrame->GetId());
        event.SetEventObject(pFrame);
        wxPostEvent(pFrame->pCometTool, event);
    }
}
<commit_msg>fix OSX crash: do not translate string in static initializer<commit_after>/*
 *  comet_tool.cpp
 *  PHD Guiding
 *
 *  Created by Andy Galasso
 *  Copyright (c) 2014 Andy Galasso
 *  All rights reserved.
 *
 *  This source code is distributed under the following "BSD" license
 *  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 Craig Stark, Stark Labs 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 "phd.h"
#include "comet_tool.h"
#include "nudge_lock.h"

#include <wx/valnum.h>

struct CometToolWin : public wxDialog
{
    wxToggleButton *m_enable;
    wxStaticText *m_xLabel;
    wxSpinCtrlDouble *m_xRate;
    wxStaticText *m_yLabel;
    wxSpinCtrlDouble *m_yRate;
    wxRadioBox *m_units;
    wxRadioBox *m_axes;
    wxButton *m_start;
    wxButton *m_stop;
    wxTextCtrl *m_status;

    bool m_training;
    wxTimer m_timer;

    PHD_Point m_startPos;
    wxLongLong_t m_startTime;

    CometToolWin();
    ~CometToolWin();

    void OnClose(wxCloseEvent& event);
    void OnAppStateNotify(wxCommandEvent& event);
    void OnTimer(wxTimerEvent& event);
    void OnEnableToggled(wxCommandEvent& event);
    void OnSpinCtrlX(wxSpinDoubleEvent& event);
    void OnSpinCtrlY(wxSpinDoubleEvent& event);
    void OnUnits(wxCommandEvent& event);
    void OnAxes(wxCommandEvent& event);
    void OnStart(wxCommandEvent& event);
    void OnStop(wxCommandEvent& event);

    void UpdateGuiderShift();
    void CalcRate();
    void UpdateStatus();
};

static wxString TITLE = wxTRANSLATE("Comet Tracking");
static wxString TITLE_TRAINING = wxTRANSLATE("Comet Tracking - Training Active");

CometToolWin::CometToolWin()
    : wxDialog(pFrame, wxID_ANY, wxGetTranslation(TITLE), wxPoint(-1,-1), wxSize(300,300)),
      m_training(false),
      m_timer(this)
{
    SetSizeHints( wxDefaultSize, wxDefaultSize );

    m_enable = new wxToggleButton(this, wxID_ANY, _("Enable"), wxDefaultPosition, wxDefaultSize, 0);
    m_enable->SetToolTip(_("Toggle comet tracking on or off."));

    m_xLabel = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(20,-1), wxALIGN_RIGHT);
    m_xLabel->Wrap(-1);
    m_yLabel = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(20, -1), wxALIGN_RIGHT);
    m_yLabel->Wrap(-1);

    m_xRate = new wxSpinCtrlDouble(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, -5000., +5000., 0., 1.);
    m_xRate->SetToolTip(_("Comet tracking rate"));
    m_yRate = new wxSpinCtrlDouble(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, -5000., +5000., 0., 1.);
    m_yRate->SetToolTip(_("Comet tracking rate"));

    wxString m_unitsChoices[] = { _("Pixels/hr"), _("Arcsec/hr") };
    int m_unitsNChoices = sizeof(m_unitsChoices) / sizeof(wxString);
    m_units = new wxRadioBox(this, wxID_ANY, _("Units"), wxDefaultPosition, wxDefaultSize, m_unitsNChoices, m_unitsChoices, 1, wxRA_SPECIFY_ROWS);
    m_units->SetSelection(1);
    m_units->SetToolTip(_("Tracking rate units"));

    wxString m_axesChoices[] = { _("Camera (X/Y)"), _("Mount (RA/Dec)") };
    int m_axesNChoices = sizeof(m_axesChoices) / sizeof(wxString);
    m_axes = new wxRadioBox(this, wxID_ANY, _("Axes"), wxDefaultPosition, wxDefaultSize, m_axesNChoices, m_axesChoices, 1, wxRA_SPECIFY_ROWS);
    m_axes->SetSelection(1);
    m_axes->SetToolTip(_("Tracking rate axes"));

    m_start = new wxButton(this, wxID_ANY, _("Start"), wxDefaultPosition, wxDefaultSize, 0);
    m_start->SetToolTip(_("Start training the tracking rate."));
    m_stop = new wxButton(this, wxID_ANY, _("Stop"), wxDefaultPosition, wxDefaultSize, 0);
    m_stop->SetToolTip(_("Stop training"));
    m_stop->Enable(false);

    // Use a text ctrl for status, wxStaticText flickers. Adding the wxTE_NO_VSCROLL style also causes the control to flicker on Windows 7.
    long style = wxSTATIC_BORDER | wxTE_MULTILINE /*| wxTE_NO_VSCROLL*/;
    m_status = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(400, 60), style);
    m_status->Enable(false);

    wxBoxSizer *xSizer = new wxBoxSizer(wxHORIZONTAL);
    xSizer->Add(0, 0, 1, wxEXPAND, 5);
    xSizer->Add(m_xLabel, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
    xSizer->Add(m_xRate, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
    xSizer->Add(0, 0, 1, wxEXPAND, 5);

    wxBoxSizer *ySizer = new wxBoxSizer(wxHORIZONTAL);
    ySizer->Add(0, 0, 1, wxEXPAND, 5);
    ySizer->Add(m_yLabel, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
    ySizer->Add(m_yRate, 0, wxALL, 5);
    ySizer->Add(0, 0, 1, wxEXPAND, 5);

    wxStaticBoxSizer *ratesSizer = new wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, _("Rates")), wxVERTICAL);
    ratesSizer->Add(xSizer, 1, wxEXPAND, 5);
    ratesSizer->Add(ySizer, 1, wxEXPAND, 5);
    ratesSizer->Add(m_units, 0, wxALL, 5);
    ratesSizer->Add(m_axes, 0, wxALL, 5);

    wxBoxSizer *startStopSizer = new wxBoxSizer(wxHORIZONTAL);
    startStopSizer->Add(0, 0, 1, wxEXPAND, 5);
    startStopSizer->Add(m_start, 0, wxALL, 5);
    startStopSizer->Add(m_stop, 0, wxALL, 5);
    startStopSizer->Add(0, 0, 1, wxEXPAND, 5);

    wxStaticBoxSizer *trainingSizer = new wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, _("Rate Training")), wxVERTICAL);
    trainingSizer->Add(startStopSizer, 1, wxEXPAND, 5);
    trainingSizer->Add(m_status, 0, wxALL, 5);

    wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL);
    topSizer->Add(m_enable, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5);
    topSizer->Add(ratesSizer, 1, wxEXPAND, 5);
    topSizer->Add(trainingSizer, 0, wxEXPAND, 5);

    SetSizer(topSizer);
    Layout();
    topSizer->Fit(this);

    // Connect Events
    Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(CometToolWin::OnClose));
    Connect(APPSTATE_NOTIFY_EVENT, wxCommandEventHandler(CometToolWin::OnAppStateNotify));
    Connect(wxEVT_TIMER, wxTimerEventHandler(CometToolWin::OnTimer));
    m_enable->Connect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(CometToolWin::OnEnableToggled), NULL, this);
    m_xRate->Connect(wxEVT_SPINCTRLDOUBLE, wxSpinDoubleEventHandler(CometToolWin::OnSpinCtrlX), NULL, this);
    m_yRate->Connect(wxEVT_SPINCTRLDOUBLE, wxSpinDoubleEventHandler(CometToolWin::OnSpinCtrlY), NULL, this);
    m_units->Connect(wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler(CometToolWin::OnUnits), NULL, this);
    m_axes->Connect(wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler(CometToolWin::OnAxes), NULL, this);
    m_start->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(CometToolWin::OnStart), NULL, this);
    m_stop->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(CometToolWin::OnStop), NULL, this);

    int xpos = pConfig->Global.GetInt("/CometTool/pos.x", -1);
    int ypos = pConfig->Global.GetInt("/CometTool/pos.y", -1);
    if (xpos == -1 || ypos == -1)
        Centre(wxBOTH);
    else
        Move(xpos, ypos);

    UpdateStatus();

    wxCommandEvent dummy;
    OnAppStateNotify(dummy); // init controls
}

CometToolWin::~CometToolWin(void)
{
    pFrame->pCometTool = 0;
}

void CometToolWin::OnEnableToggled(wxCommandEvent& event)
{
    pFrame->pGuider->EnableLockPosShift(m_enable->GetValue());
}

void CometToolWin::UpdateGuiderShift()
{
    PHD_Point rate(m_xRate->GetValue(), m_yRate->GetValue());
    GRAPH_UNITS units = m_units->GetSelection() == 0 ? UNIT_PIXELS : UNIT_ARCSEC;
    bool isMountCoords = m_axes->GetSelection() == 1;
    pFrame->pGuider->SetLockPosShiftRate(rate, units, isMountCoords);
}

void CometToolWin::OnSpinCtrlX(wxSpinDoubleEvent& event)
{
    UpdateGuiderShift();
}

void CometToolWin::OnSpinCtrlY(wxSpinDoubleEvent& event)
{
    UpdateGuiderShift();
}

void CometToolWin::OnUnits(wxCommandEvent& event)
{
    UpdateGuiderShift();
}

void CometToolWin::OnAxes(wxCommandEvent& event)
{
    UpdateGuiderShift();
}

void CometToolWin::OnStart(wxCommandEvent& event)
{
    if (!pFrame->pGuider->IsGuiding())
        return;

    if (!pFrame->pNudgeLock)
        pFrame->pNudgeLock = NudgeLockTool::CreateNudgeLockToolWindow();
    pFrame->pNudgeLock->Show();

    m_startPos = pFrame->pGuider->LockPosition();
    m_startTime = ::wxGetUTCTimeMillis().GetValue();

    pFrame->pGuider->EnableLockPosShift(true);

    m_start->Enable(false);
    m_stop->Enable(true);
    m_units->Enable(false);
    m_axes->Enable(false);

    m_timer.Start(500);
    m_training = true;

    SetTitle(wxGetTranslation(TITLE_TRAINING));
    UpdateStatus();
}

void CometToolWin::OnStop(wxCommandEvent& event)
{
    m_timer.Stop();
    m_training = false;

    m_start->Enable(pFrame->pGuider->IsGuiding());
    m_stop->Enable(false);
    m_units->Enable(true);
    m_axes->Enable(true);

    SetTitle(wxGetTranslation(TITLE));
    UpdateStatus();
}

void CometToolWin::OnTimer(wxTimerEvent& WXUNUSED(evt))
{
    UpdateStatus();
}

void CometToolWin::CalcRate()
{
    double dt = (double) (::wxGetUTCTimeMillis().GetValue() - m_startTime) / 3600000.0; // hours
    PHD_Point rate = (pFrame->pGuider->LockPosition() - m_startPos) / dt;
    pFrame->pGuider->SetLockPosShiftRate(rate, UNIT_PIXELS, false);
}

void CometToolWin::UpdateStatus()
{
    if (m_training)
    {
        m_status->SetValue(wxString::Format(_("Training, elapsed time %lus.\nUse the "
            "\"Adjust Lock Position\" controls to center the comet\nin the imaging "
            "camera and click Stop to complete training."),
            (long)((::wxGetUTCTimeMillis().GetValue() - m_startTime) / 1000)));
    }
    else
    {
        m_status->SetValue(_("Center the comet in the imaging camera.\nSelect a guide "
            "star and start Guiding.\nThen, click Start to begin training."));
    }
}

void CometToolWin::OnAppStateNotify(wxCommandEvent& WXUNUSED(event))
{
    const LockPosShiftParams& shift = pFrame->pGuider->GetLockPosShiftParams();

    m_enable->SetValue(shift.shiftEnabled);

    m_xRate->SetValue(shift.shiftRate.X);
    m_yRate->SetValue(shift.shiftRate.Y);

    if (shift.shiftIsMountCoords)
    {
        m_axes->SetSelection(1);
        m_xLabel->SetLabel(_("RA"));
        m_yLabel->SetLabel(_("Dec"));
    }
    else
    {
        m_axes->SetSelection(0);
        m_xLabel->SetLabel(_("X"));
        m_yLabel->SetLabel(_("Y"));
    }

    if (shift.shiftUnits == UNIT_PIXELS)
    {
        m_units->SetSelection(0);
    }
    else
    {
        m_units->SetSelection(1);
    }

    if (m_training)
    {
        if (!pFrame->pGuider->IsGuiding())
        {
            // if guiding stopped, stop training
            wxCommandEvent dummy;
            OnStop(dummy);
        }
    }
    else
    {
        m_start->Enable(pFrame->pGuider->IsGuiding());
    }
}

void CometToolWin::OnClose(wxCloseEvent& evt)
{
    // save the window position
    int x, y;
    GetPosition(&x, &y);
    pConfig->Global.SetInt("/CometTool/pos.x", x);
    pConfig->Global.SetInt("/CometTool/pos.y", y);

    evt.Skip();
}

wxWindow *CometTool::CreateCometToolWindow()
{
    return new CometToolWin();
}

void CometTool::NotifyUpdateLockPos()
{
    if (pFrame && pFrame->pCometTool)
    {
        CometToolWin *win = static_cast<CometToolWin *>(pFrame->pCometTool);
        if (win->m_training)
            win->CalcRate();
    }
}

void CometTool::UpdateCometToolControls()
{
    // notify comet tool to update its controls
    if (pFrame && pFrame->pCometTool)
    {
        wxCommandEvent event(APPSTATE_NOTIFY_EVENT, pFrame->GetId());
        event.SetEventObject(pFrame);
        wxPostEvent(pFrame->pCometTool, event);
    }
}
<|endoftext|>


<commit_before>#include "Wizard.h"

Wizard::Wizard() :
  _step(1),
  _next("Next"),
  _cancel("Cancel"),
  _back("Back"),
  _shutdown(false),
  _shutdown(false),
  _ptpInstalled(false),
  _eteInstalled(false),
  _peerInstalled(false),
  _trayInstalled(false)
{
  _logger = &Poco::Logger::get("subutai");
  SubutaiLauncher::Session::instance()->start();
#if LAUNCHER_LINUX
  SubutaiLauncher::RootProcess* rp = new SubutaiLauncher::RootProcess();
  rp->addCommand("mkdir -p /opt/subutai");
  rp->addCommand("mkdir -p /opt/subutai/bin");
  rp->addCommand("mkdir -p /opt/subutai/etc");
  rp->addCommand("mkdir -p /opt/subutai/resources");
  std::string chown("chown -R ");
  chown.append(Poco::Environment::get("USER"));
  chown.append(" /opt/subutai");
  rp->addCommand(chown);
  rp->execute("Creating installation directories requires root privileges");
  delete rp;
#elif LAUNCHER_MACOS
  Poco::File bin("/usr/local/share/subutai/bin");
  bin.createDirectories();
  bin = Poco::File("/usr/local/share/subutai/etc");
  bin.createDirectories();
#elif LAUNCHER_WINDOWS
  Poco::File bin(SubutaiLauncher::Session::instance()->getSettings()->getInstallationPath()+"/bin");
  if (!bin.exists())
  {
    bin.createDirectories();
  }
#endif

  setSize(800, 600);
  auto font = juce::Font("Encode Sans", 17, 1);

  _stepIntro.setText("Welcome", dontSendNotification);
  _stepIntro.setColour(Label::textColourId, juce::Colour(105, 116, 144));
  _stepIntro.setBounds(15, 50, 300, 40);
  _stepIntro.setFont(font);
  _stepIntro.setJustificationType(Justification::top);

  _stepSystemCheck.setText("System Check", dontSendNotification);
  _stepSystemCheck.setColour(Label::textColourId, juce::Colour(105, 116, 144));
  _stepSystemCheck.setBounds(15, 80, 300, 40);
  _stepSystemCheck.setFont(font);
  _stepSystemCheck.setJustificationType(Justification::top);

  _stepComponentChooser.setText("Choose Components", dontSendNotification);
  _stepComponentChooser.setColour(Label::textColourId, juce::Colour(105, 116, 144));
  _stepComponentChooser.setBounds(15, 110, 300, 40);
  _stepComponentChooser.setFont(font);
  _stepComponentChooser.setJustificationType(Justification::top);

  _stepInstall.setText("Install", dontSendNotification);
  _stepInstall.setColour(Label::textColourId, juce::Colour(105, 116, 144));
  _stepInstall.setBounds(15, 140, 300, 40);
  _stepInstall.setFont(font);
  _stepInstall.setJustificationType(Justification::top);

  _stepFinal.setText("Finish", dontSendNotification);
  _stepFinal.setColour(Label::textColourId, juce::Colour(105, 116, 144));
  _stepFinal.setBounds(15, 170, 300, 40);
  _stepFinal.setFont(font);
  _stepFinal.setJustificationType(Justification::top);

  addAndMakeVisible(_stepIntro);
  addAndMakeVisible(_stepSystemCheck);
  addAndMakeVisible(_stepComponentChooser);
  addAndMakeVisible(_stepInstall);
  addAndMakeVisible(_stepFinal);

  // Installation step pages

  _introPage = new WizardIntro();
  _introPage->setBounds(300, 0, 500, 600);
  addAndMakeVisible(_introPage);

  _systemCheckPage = new SystemCheck();
  _systemCheckPage->setBounds(300, 0, 500, 600);
  addChildComponent(_systemCheckPage);

  _logger->trace("ComponentChooser::Pre");
  _componentChooserPage = new ComponentChooser();
  _componentChooserPage->setBounds(300, 0, 500, 600);
  addChildComponent(_componentChooserPage);

  _ptpInstall = new WizardInstall();
  _ptpInstall->setBounds(300, 0, 500, 600);
  addChildComponent(_ptpInstall);

  _trayInstall = new WizardInstall();
  _trayInstall->setBounds(300, 0, 500, 600);
  addChildComponent(_trayInstall);

  _eteInstall = new WizardInstall();
  _eteInstall->setBounds(300, 0, 500, 600);
  addChildComponent(_eteInstall);

  _peerInstall = new WizardInstall();
  _peerInstall->setBounds(300, 0, 500, 600);
  addChildComponent(_peerInstall);

  _finishPage = new WizardFinish();
  _finishPage->setBounds(300, 0, 500, 600);
  addChildComponent(_finishPage);

  // Progression buttons

  _next.setBounds(202, 560, 86, 25);
  _next.addListener(this);
  _next.setColour(TextButton::buttonColourId, Colour(7,141,208));
  addAndMakeVisible(_next);

  _back.setBounds(106, 560, 86, 25);
  _back.addListener(this);
  _back.setEnabled(false);
  addAndMakeVisible(_back);

  _cancel.setBounds(10, 560, 86, 25);
  _cancel.addListener(this);
  addAndMakeVisible(_cancel);
}

Wizard::~Wizard()
{
  _shutdown = true;
  cleanInstallers();
  _logger->trace("Requesting Introduction page destroy");
  if (_introPage != nullptr) delete _introPage;
  _logger->trace("Requesting System Check page destroy");
  if (_systemCheckPage != nullptr) delete _systemCheckPage;
  _logger->trace("Requesting Component Selector page destroy");
  if (_componentChooserPage != nullptr) delete _componentChooserPage;
  _logger->trace("Requesting P2P Installation page destroy");
  if (_ptpInstall != nullptr) delete _ptpInstall;
  _logger->trace("Requesting Tray Installation page destroy");
  if (_trayInstall != nullptr) delete _trayInstall;
  _logger->trace("Requesting ETE Installation page destroy");
  if (_eteInstall != nullptr) delete _eteInstall;
  _logger->trace("Requesting Peer Installation page destroy");
  if (_peerInstall != nullptr) delete _peerInstall;
  _logger->trace("Requesting Finish page destroy");
  if (_finishPage != nullptr) delete _finishPage;
}

void Wizard::paint(juce::Graphics& g)
{
  g.fillAll (Colour(247, 249, 252));
}

void Wizard::resized()
{

}

void Wizard::buttonClicked(juce::Button* button)
{
  if (button == &_next)
  {
    switch (_step)
    {
      case 1:
        _introPage->setVisible(false);
        _systemCheckPage->setVisible(true);
        _stepIntro.setColour(Label::textColourId, Colours::black);
        _stepSystemCheck.setColour(Label::textColourId, juce::Colour(7, 141, 208));
        _back.setEnabled(true);
        _step = 2;
        break;
      case 2:
        _systemCheckPage->setVisible(false);
        _componentChooserPage->setVisible(true);
        _stepSystemCheck.setColour(Label::textColourId, Colours::black);
        _stepComponentChooser.setColour(Label::textColourId, juce::Colour(7, 141, 208));
        _step = 3;
        break;
      case 3:
        _componentChooserPage->setVisible(false);
        _ptpInstall->setVisible(true);
        _stepComponentChooser.setColour(Label::textColourId, Colours::black);
        _stepInstall.setColour(Label::textColourId, juce::Colour(7, 141, 208));
        _step = 4;
        _back.setEnabled(false);
        _next.setEnabled(false);
        runInstall();
        break;
      default:
        _introPage->setVisible(true);
        _back.setEnabled(false);
        _step = 1;
        _stepIntro.setColour(Label::textColourId, juce::Colour(7, 141, 208));
        break;
    }
  }
  else if (button == &_back)
  {
    switch (_step)
    {
      case 1:
        break;
      case 2:
        _back.setEnabled(false);
        _systemCheckPage->setVisible(false);
        _introPage->setVisible(true);
        _stepIntro.setColour(Label::textColourId, juce::Colour(7, 141, 208));
        _stepSystemCheck.setColour(Label::textColourId, Colours::grey);
        _step = 1;
        break;
      case 3:
        _componentChooserPage->setVisible(false);
        _systemCheckPage->setVisible(true);
        _stepSystemCheck.setColour(Label::textColourId, juce::Colour(7, 141, 208));
        _stepComponentChooser.setColour(Label::textColourId, Colours::grey);
        _step = 2;
        break;
      default:
        break;
    }
  }
  else if (button == &_cancel)
  {
    runCancelConfirmation();
  }
}

void Wizard::runInstall()
{
  _logger->debug("Collecting choosen components");
  //auto c = _componentChooserPage->getComponents();
  SubutaiLauncher::InstallationSettings pSettings = SubutaiLauncher::Session::instance()->getSettings()->getInstallationSettings();
  // TODO: Replace this with Installation Settings
  SubutaiLauncher::Session::instance()->getSettings()->setCoreNum(pSettings.cpuNum);
  SubutaiLauncher::Session::instance()->getSettings()->setMemSize(pSettings.memSize);

  cleanInstallers();

  if (pSettings.installP2P && !_ptpInstalled)
  {
    _ptpInstall->activate();
    _logger->debug("P2P Component has been choosen");
    _ptpInstall->start("P2P");
    _ptpInstall->run();
    return;
  } else {
    _logger->debug("pSettings.installP2P = %d,  _ptpInstalled = %d", pSettings.installP2P, _ptpInstalled);
  }

  if (pSettings.installTray && !_trayInstalled)
  {
    _trayInstall->activate();
    _logger->debug("Tray Component has been choosen");
    _trayInstall->start("Tray");
    _trayInstall->run();
    return;
  } else {
    _logger->debug("pSettings.installTray = %d,  _trayInstalled = %d", pSettings.installTray, _trayInstalled);
  }

  if (pSettings.installE2E && !_eteInstalled)
  {
    _eteInstall->activate();
    _logger->debug("Browser Plugin Component has been choosen");
    _eteInstall->start("Browser Plugin");
    _eteInstall->run();
    return;
  } else {
    _logger->debug("pSettings.installE2E = %d,  _eteInstalled = %d", pSettings.installE2E, _eteInstalled);
  }

  if (pSettings.installPeer && !_peerInstalled)
  {
    _peerInstall->activate();
    _logger->debug("Peer Component has been choosen");
    _peerInstall->start("Peer");
    _peerInstall->run();
    return;
  } else {
    _logger->debug("pSettings.installPeer = %d,  _peerInstalled = %d", pSettings.installPeer, _peerInstalled);
  }

  _logger->debug("Nothing to install");
  finish();
}

void Wizard::stepCompleted(const std::string& name)
{
  if (_shutdown)
  {
    return;
  }
  if (name == "P2P")
  {
    _ptpInstalled = true;
    _ptpInstall->setVisible(false);
  }
  else if (name == "Tray")
  {
    _trayInstalled = true;
    _trayInstall->setVisible(false);
  }
  else if (name == "Browser Plugin")
  {
    _eteInstalled = true;
    _eteInstall->setVisible(false);
  }
  else if (name == "Peer")
  {
    _peerInstalled = true;
    _peerInstall->setVisible(false);
  }

  // Determine if we need to install something else
  _logger->debug("Looking for next component");
  auto c = _componentChooserPage->getComponents();
  if ((c.ptp && !_ptpInstalled) || (c.tray && !_trayInstalled) || (c.ete && !_eteInstalled) || (c.peer && !_peerInstalled))
  {
    _logger->debug("Next component found");
    runInstall();
    return;
  }
  else
  {
    _logger->trace("Nothing else to install. Proceeding to a final page");
  }

  finish();
}

void Wizard::finish(bool canceled)
{
  cleanInstallers();
  // Show final page
  _cancel.setEnabled(false);
  _cancel.setVisible(false);
  _next.setEnabled(false);
  _next.setVisible(false);
  _back.setEnabled(false);
  _back.setVisible(false);

  if (canceled)
  {
    _finishPage->finalize();
  }

  auto c = _componentChooserPage->getComponents();
  _finishPage->addPTPResult(c.ptp, _ptpInstall->succeed());
  _finishPage->addTrayResult(c.tray, _trayInstall->succeed());
  _finishPage->addETEResult(c.ete, _eteInstall->succeed());
  _finishPage->addPeerResult(c.peer, _peerInstall->succeed());
  _finishPage->setVisible(true);

  _stepFinal.setColour(Label::textColourId, juce::Colour(7, 141, 208));
  _stepInstall.setColour(Label::textColourId, Colours::white);
}

void Wizard::cleanInstallers()
{
  _logger->trace("Cleaning install pages");
  if (_ptpInstall->isActive())
  {
    _logger->trace("Deactivating P2P Installation page");
    _ptpInstall->deactivate();
    if (_ptpInstall->isRunning())
    {
      _logger->trace("Waiting for thread to complete");
      _ptpInstall->wait();
    }
  }
  if (_trayInstall->isActive())
  {
    _logger->trace("Deactivating Tray Installation page");
    _trayInstall->deactivate();
    if (_trayInstall->isRunning())
    {
      _logger->trace("Waiting for thread to complete");
      _trayInstall->wait();
    }
  }
  if (_eteInstall->isActive())
  {
    _logger->trace("Deactivating ETE Installation page");
    _eteInstall->deactivate();
    if (_eteInstall->isRunning())
    {
      _logger->trace("Waiting for thread to complete");
      _eteInstall->wait();
    }
  }
  if (_peerInstall->isActive())
  {
    _logger->trace("Deactivating Peer Installation page");
    _peerInstall->deactivate();
    if (_peerInstall->isRunning())
    {
      _logger->trace("Waiting for thread to complete");
      _peerInstall->wait();
    }
  }
}

void Wizard::runCancelConfirmation()
{
  juce::String title = "Cancel installation";
  juce::String message = "Are you sure you want to cancel installation?";

  if (NativeMessageBox::showOkCancelBox(AlertWindow::QuestionIcon, title,
                                        message, nullptr, nullptr)) {
    this->finish(true);
  }
}
<commit_msg>Fixed typo<commit_after>#include "Wizard.h"

Wizard::Wizard() :
  _step(1),
  _next("Next"),
  _cancel("Cancel"),
  _back("Back"),
  _shutdown(false),
  _ptpInstalled(false),
  _eteInstalled(false),
  _peerInstalled(false),
  _trayInstalled(false)
{
  _logger = &Poco::Logger::get("subutai");
  SubutaiLauncher::Session::instance()->start();
#if LAUNCHER_LINUX
  SubutaiLauncher::RootProcess* rp = new SubutaiLauncher::RootProcess();
  rp->addCommand("mkdir -p /opt/subutai");
  rp->addCommand("mkdir -p /opt/subutai/bin");
  rp->addCommand("mkdir -p /opt/subutai/etc");
  rp->addCommand("mkdir -p /opt/subutai/resources");
  std::string chown("chown -R ");
  chown.append(Poco::Environment::get("USER"));
  chown.append(" /opt/subutai");
  rp->addCommand(chown);
  rp->execute("Creating installation directories requires root privileges");
  delete rp;
#elif LAUNCHER_MACOS
  Poco::File bin("/usr/local/share/subutai/bin");
  bin.createDirectories();
  bin = Poco::File("/usr/local/share/subutai/etc");
  bin.createDirectories();
#elif LAUNCHER_WINDOWS
  Poco::File bin(SubutaiLauncher::Session::instance()->getSettings()->getInstallationPath()+"/bin");
  if (!bin.exists())
  {
    bin.createDirectories();
  }
#endif

  setSize(800, 600);
  auto font = juce::Font("Encode Sans", 17, 1);

  _stepIntro.setText("Welcome", dontSendNotification);
  _stepIntro.setColour(Label::textColourId, juce::Colour(105, 116, 144));
  _stepIntro.setBounds(15, 50, 300, 40);
  _stepIntro.setFont(font);
  _stepIntro.setJustificationType(Justification::top);

  _stepSystemCheck.setText("System Check", dontSendNotification);
  _stepSystemCheck.setColour(Label::textColourId, juce::Colour(105, 116, 144));
  _stepSystemCheck.setBounds(15, 80, 300, 40);
  _stepSystemCheck.setFont(font);
  _stepSystemCheck.setJustificationType(Justification::top);

  _stepComponentChooser.setText("Choose Components", dontSendNotification);
  _stepComponentChooser.setColour(Label::textColourId, juce::Colour(105, 116, 144));
  _stepComponentChooser.setBounds(15, 110, 300, 40);
  _stepComponentChooser.setFont(font);
  _stepComponentChooser.setJustificationType(Justification::top);

  _stepInstall.setText("Install", dontSendNotification);
  _stepInstall.setColour(Label::textColourId, juce::Colour(105, 116, 144));
  _stepInstall.setBounds(15, 140, 300, 40);
  _stepInstall.setFont(font);
  _stepInstall.setJustificationType(Justification::top);

  _stepFinal.setText("Finish", dontSendNotification);
  _stepFinal.setColour(Label::textColourId, juce::Colour(105, 116, 144));
  _stepFinal.setBounds(15, 170, 300, 40);
  _stepFinal.setFont(font);
  _stepFinal.setJustificationType(Justification::top);

  addAndMakeVisible(_stepIntro);
  addAndMakeVisible(_stepSystemCheck);
  addAndMakeVisible(_stepComponentChooser);
  addAndMakeVisible(_stepInstall);
  addAndMakeVisible(_stepFinal);

  // Installation step pages

  _introPage = new WizardIntro();
  _introPage->setBounds(300, 0, 500, 600);
  addAndMakeVisible(_introPage);

  _systemCheckPage = new SystemCheck();
  _systemCheckPage->setBounds(300, 0, 500, 600);
  addChildComponent(_systemCheckPage);

  _logger->trace("ComponentChooser::Pre");
  _componentChooserPage = new ComponentChooser();
  _componentChooserPage->setBounds(300, 0, 500, 600);
  addChildComponent(_componentChooserPage);

  _ptpInstall = new WizardInstall();
  _ptpInstall->setBounds(300, 0, 500, 600);
  addChildComponent(_ptpInstall);

  _trayInstall = new WizardInstall();
  _trayInstall->setBounds(300, 0, 500, 600);
  addChildComponent(_trayInstall);

  _eteInstall = new WizardInstall();
  _eteInstall->setBounds(300, 0, 500, 600);
  addChildComponent(_eteInstall);

  _peerInstall = new WizardInstall();
  _peerInstall->setBounds(300, 0, 500, 600);
  addChildComponent(_peerInstall);

  _finishPage = new WizardFinish();
  _finishPage->setBounds(300, 0, 500, 600);
  addChildComponent(_finishPage);

  // Progression buttons

  _next.setBounds(202, 560, 86, 25);
  _next.addListener(this);
  _next.setColour(TextButton::buttonColourId, Colour(7,141,208));
  addAndMakeVisible(_next);

  _back.setBounds(106, 560, 86, 25);
  _back.addListener(this);
  _back.setEnabled(false);
  addAndMakeVisible(_back);

  _cancel.setBounds(10, 560, 86, 25);
  _cancel.addListener(this);
  addAndMakeVisible(_cancel);
}

Wizard::~Wizard()
{
  _shutdown = true;
  cleanInstallers();
  _logger->trace("Requesting Introduction page destroy");
  if (_introPage != nullptr) delete _introPage;
  _logger->trace("Requesting System Check page destroy");
  if (_systemCheckPage != nullptr) delete _systemCheckPage;
  _logger->trace("Requesting Component Selector page destroy");
  if (_componentChooserPage != nullptr) delete _componentChooserPage;
  _logger->trace("Requesting P2P Installation page destroy");
  if (_ptpInstall != nullptr) delete _ptpInstall;
  _logger->trace("Requesting Tray Installation page destroy");
  if (_trayInstall != nullptr) delete _trayInstall;
  _logger->trace("Requesting ETE Installation page destroy");
  if (_eteInstall != nullptr) delete _eteInstall;
  _logger->trace("Requesting Peer Installation page destroy");
  if (_peerInstall != nullptr) delete _peerInstall;
  _logger->trace("Requesting Finish page destroy");
  if (_finishPage != nullptr) delete _finishPage;
}

void Wizard::paint(juce::Graphics& g)
{
  g.fillAll (Colour(247, 249, 252));
}

void Wizard::resized()
{

}

void Wizard::buttonClicked(juce::Button* button)
{
  if (button == &_next)
  {
    switch (_step)
    {
      case 1:
        _introPage->setVisible(false);
        _systemCheckPage->setVisible(true);
        _stepIntro.setColour(Label::textColourId, Colours::black);
        _stepSystemCheck.setColour(Label::textColourId, juce::Colour(7, 141, 208));
        _back.setEnabled(true);
        _step = 2;
        break;
      case 2:
        _systemCheckPage->setVisible(false);
        _componentChooserPage->setVisible(true);
        _stepSystemCheck.setColour(Label::textColourId, Colours::black);
        _stepComponentChooser.setColour(Label::textColourId, juce::Colour(7, 141, 208));
        _step = 3;
        break;
      case 3:
        _componentChooserPage->setVisible(false);
        _ptpInstall->setVisible(true);
        _stepComponentChooser.setColour(Label::textColourId, Colours::black);
        _stepInstall.setColour(Label::textColourId, juce::Colour(7, 141, 208));
        _step = 4;
        _back.setEnabled(false);
        _next.setEnabled(false);
        runInstall();
        break;
      default:
        _introPage->setVisible(true);
        _back.setEnabled(false);
        _step = 1;
        _stepIntro.setColour(Label::textColourId, juce::Colour(7, 141, 208));
        break;
    }
  }
  else if (button == &_back)
  {
    switch (_step)
    {
      case 1:
        break;
      case 2:
        _back.setEnabled(false);
        _systemCheckPage->setVisible(false);
        _introPage->setVisible(true);
        _stepIntro.setColour(Label::textColourId, juce::Colour(7, 141, 208));
        _stepSystemCheck.setColour(Label::textColourId, Colours::grey);
        _step = 1;
        break;
      case 3:
        _componentChooserPage->setVisible(false);
        _systemCheckPage->setVisible(true);
        _stepSystemCheck.setColour(Label::textColourId, juce::Colour(7, 141, 208));
        _stepComponentChooser.setColour(Label::textColourId, Colours::grey);
        _step = 2;
        break;
      default:
        break;
    }
  }
  else if (button == &_cancel)
  {
    runCancelConfirmation();
  }
}

void Wizard::runInstall()
{
  _logger->debug("Collecting choosen components");
  //auto c = _componentChooserPage->getComponents();
  SubutaiLauncher::InstallationSettings pSettings = SubutaiLauncher::Session::instance()->getSettings()->getInstallationSettings();
  // TODO: Replace this with Installation Settings
  SubutaiLauncher::Session::instance()->getSettings()->setCoreNum(pSettings.cpuNum);
  SubutaiLauncher::Session::instance()->getSettings()->setMemSize(pSettings.memSize);

  cleanInstallers();

  if (pSettings.installP2P && !_ptpInstalled)
  {
    _ptpInstall->activate();
    _logger->debug("P2P Component has been choosen");
    _ptpInstall->start("P2P");
    _ptpInstall->run();
    return;
  } else {
    _logger->debug("pSettings.installP2P = %d,  _ptpInstalled = %d", pSettings.installP2P, _ptpInstalled);
  }

  if (pSettings.installTray && !_trayInstalled)
  {
    _trayInstall->activate();
    _logger->debug("Tray Component has been choosen");
    _trayInstall->start("Tray");
    _trayInstall->run();
    return;
  } else {
    _logger->debug("pSettings.installTray = %d,  _trayInstalled = %d", pSettings.installTray, _trayInstalled);
  }

  if (pSettings.installE2E && !_eteInstalled)
  {
    _eteInstall->activate();
    _logger->debug("Browser Plugin Component has been choosen");
    _eteInstall->start("Browser Plugin");
    _eteInstall->run();
    return;
  } else {
    _logger->debug("pSettings.installE2E = %d,  _eteInstalled = %d", pSettings.installE2E, _eteInstalled);
  }

  if (pSettings.installPeer && !_peerInstalled)
  {
    _peerInstall->activate();
    _logger->debug("Peer Component has been choosen");
    _peerInstall->start("Peer");
    _peerInstall->run();
    return;
  } else {
    _logger->debug("pSettings.installPeer = %d,  _peerInstalled = %d", pSettings.installPeer, _peerInstalled);
  }

  _logger->debug("Nothing to install");
  finish();
}

void Wizard::stepCompleted(const std::string& name)
{
  if (_shutdown)
  {
    return;
  }
  if (name == "P2P")
  {
    _ptpInstalled = true;
    _ptpInstall->setVisible(false);
  }
  else if (name == "Tray")
  {
    _trayInstalled = true;
    _trayInstall->setVisible(false);
  }
  else if (name == "Browser Plugin")
  {
    _eteInstalled = true;
    _eteInstall->setVisible(false);
  }
  else if (name == "Peer")
  {
    _peerInstalled = true;
    _peerInstall->setVisible(false);
  }

  // Determine if we need to install something else
  _logger->debug("Looking for next component");
  auto c = _componentChooserPage->getComponents();
  if ((c.ptp && !_ptpInstalled) || (c.tray && !_trayInstalled) || (c.ete && !_eteInstalled) || (c.peer && !_peerInstalled))
  {
    _logger->debug("Next component found");
    runInstall();
    return;
  }
  else
  {
    _logger->trace("Nothing else to install. Proceeding to a final page");
  }

  finish();
}

void Wizard::finish(bool canceled)
{
  cleanInstallers();
  // Show final page
  _cancel.setEnabled(false);
  _cancel.setVisible(false);
  _next.setEnabled(false);
  _next.setVisible(false);
  _back.setEnabled(false);
  _back.setVisible(false);

  if (canceled)
  {
    _finishPage->finalize();
  }

  auto c = _componentChooserPage->getComponents();
  _finishPage->addPTPResult(c.ptp, _ptpInstall->succeed());
  _finishPage->addTrayResult(c.tray, _trayInstall->succeed());
  _finishPage->addETEResult(c.ete, _eteInstall->succeed());
  _finishPage->addPeerResult(c.peer, _peerInstall->succeed());
  _finishPage->setVisible(true);

  _stepFinal.setColour(Label::textColourId, juce::Colour(7, 141, 208));
  _stepInstall.setColour(Label::textColourId, Colours::white);
}

void Wizard::cleanInstallers()
{
  _logger->trace("Cleaning install pages");
  if (_ptpInstall->isActive())
  {
    _logger->trace("Deactivating P2P Installation page");
    _ptpInstall->deactivate();
    if (_ptpInstall->isRunning())
    {
      _logger->trace("Waiting for thread to complete");
      _ptpInstall->wait();
    }
  }
  if (_trayInstall->isActive())
  {
    _logger->trace("Deactivating Tray Installation page");
    _trayInstall->deactivate();
    if (_trayInstall->isRunning())
    {
      _logger->trace("Waiting for thread to complete");
      _trayInstall->wait();
    }
  }
  if (_eteInstall->isActive())
  {
    _logger->trace("Deactivating ETE Installation page");
    _eteInstall->deactivate();
    if (_eteInstall->isRunning())
    {
      _logger->trace("Waiting for thread to complete");
      _eteInstall->wait();
    }
  }
  if (_peerInstall->isActive())
  {
    _logger->trace("Deactivating Peer Installation page");
    _peerInstall->deactivate();
    if (_peerInstall->isRunning())
    {
      _logger->trace("Waiting for thread to complete");
      _peerInstall->wait();
    }
  }
}

void Wizard::runCancelConfirmation()
{
  juce::String title = "Cancel installation";
  juce::String message = "Are you sure you want to cancel installation?";

  if (NativeMessageBox::showOkCancelBox(AlertWindow::QuestionIcon, title,
                                        message, nullptr, nullptr)) {
    this->finish(true);
  }
}
<|endoftext|>