<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ftpinpstr.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-20 05:24:33 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

/**************************************************************************
                                TODO
 **************************************************************************

 *************************************************************************/

#ifndef _FTP_FTPINPSTR_HXX_
#include "ftpinpstr.hxx"
#endif
#ifndef _RTL_ALLOC_H
#include <rtl/alloc.h>
#endif
#ifndef STD_ALGORITHM
#include <algorithm>
#define STD_ALGORITHM
#endif
#include <stdio.h>

using namespace ftp;
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace com::sun::star::io;

FTPInputStream::FTPInputStream(FILE* tmpfl)
    : m_tmpfl(tmpfl ? tmpfl : tmpfile())
{
    fseek(m_tmpfl,0,SEEK_END);
//  fpos_t pos;
//  fgetpos(m_tmpfl,&pos);
    long pos = ftell(m_tmpfl);
    rewind(m_tmpfl);
    m_nLength = sal_Int64(pos);
}

FTPInputStream::~FTPInputStream()
{
    fclose(m_tmpfl);
}

Any SAL_CALL FTPInputStream::queryInterface(
    const Type& rType
)
    throw(
        RuntimeException
    )
{
    Any aRet = ::cppu::queryInterface(rType,
                                      SAL_STATIC_CAST( XInputStream*,this ),
                                      SAL_STATIC_CAST( XSeekable*,this ) );

    return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
}

void SAL_CALL FTPInputStream::acquire( void ) throw() {
    OWeakObject::acquire();
}

void SAL_CALL FTPInputStream::release( void ) throw() {
    OWeakObject::release();
}

sal_Int32 SAL_CALL FTPInputStream::readBytes(Sequence< sal_Int8 >& aData,
                                             sal_Int32 nBytesToRead)
    throw(NotConnectedException,
          BufferSizeExceededException,
          IOException,
          RuntimeException)
{
    osl::MutexGuard aGuard(m_aMutex);

    if(0 <= nBytesToRead && aData.getLength() < nBytesToRead)
        aData.realloc(nBytesToRead);

//     fpos_t bpos,epos;

//     fgetpos(m_tmpfl,&bpos);
//     fread(aData.getArray(),nBytesToRead,1,m_tmpfl);
//     fgetpos(m_tmpfl,&epos);
    long bpos,epos;

    bpos = ftell(m_tmpfl);
    fread(aData.getArray(),nBytesToRead,1,m_tmpfl);
    epos = ftell(m_tmpfl);

    return sal_Int32(epos-bpos);
}

sal_Int32 SAL_CALL FTPInputStream::readSomeBytes( Sequence< sal_Int8 >& aData,sal_Int32 nMaxBytesToRead )
    throw( NotConnectedException,
           BufferSizeExceededException,
           IOException,
           RuntimeException)
{
    return readBytes(aData,nMaxBytesToRead);
}

void SAL_CALL FTPInputStream::skipBytes(sal_Int32 nBytesToSkip)
    throw(NotConnectedException,
          BufferSizeExceededException,
          IOException,
          RuntimeException)
{
    osl::MutexGuard aGuard(m_aMutex);
    if(!m_tmpfl)
        throw IOException();

    fseek(m_tmpfl,long(nBytesToSkip),SEEK_CUR);
}

sal_Int32 SAL_CALL FTPInputStream::available(void)
    throw(NotConnectedException,
          IOException,
          RuntimeException)
{
    return sal::static_int_cast<sal_Int32>(m_nLength - getPosition());
}

void SAL_CALL FTPInputStream::closeInput(void)
    throw(NotConnectedException,
          IOException,
          RuntimeException)
{
    osl::MutexGuard aGuard(m_aMutex);
    if(m_tmpfl)
        fclose(m_tmpfl),m_tmpfl = 0;
}

void SAL_CALL FTPInputStream::seek(sal_Int64 location)
    throw( IllegalArgumentException,
           IOException,
           RuntimeException )
{
    osl::MutexGuard aGuard(m_aMutex);
    if(!m_tmpfl)
        throw IOException();

    fseek(m_tmpfl,long(location),SEEK_SET);
}

sal_Int64 SAL_CALL
FTPInputStream::getPosition(
    void )
    throw( IOException,
           RuntimeException )
{
    osl::MutexGuard aGuard(m_aMutex);
    if(!m_tmpfl)
        throw IOException();

//     fpos_t pos;
//     fgetpos(m_tmpfl,&pos);
    long pos;
    pos = ftell(m_tmpfl);
    return sal_Int64(pos);
}

sal_Int64 SAL_CALL FTPInputStream::getLength(
    void
) throw(
    IOException,RuntimeException
)
{
    return m_nLength;
}
<commit_msg>INTEGRATION: CWS pchfix02 (1.7.20); FILE MERGED 2006/09/01 17:55:44 kaib 1.7.20.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ftpinpstr.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 13:51:16 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_ucb.hxx"

/**************************************************************************
                                TODO
 **************************************************************************

 *************************************************************************/

#ifndef _FTP_FTPINPSTR_HXX_
#include "ftpinpstr.hxx"
#endif
#ifndef _RTL_ALLOC_H
#include <rtl/alloc.h>
#endif
#ifndef STD_ALGORITHM
#include <algorithm>
#define STD_ALGORITHM
#endif
#include <stdio.h>

using namespace ftp;
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace com::sun::star::io;

FTPInputStream::FTPInputStream(FILE* tmpfl)
    : m_tmpfl(tmpfl ? tmpfl : tmpfile())
{
    fseek(m_tmpfl,0,SEEK_END);
//  fpos_t pos;
//  fgetpos(m_tmpfl,&pos);
    long pos = ftell(m_tmpfl);
    rewind(m_tmpfl);
    m_nLength = sal_Int64(pos);
}

FTPInputStream::~FTPInputStream()
{
    fclose(m_tmpfl);
}

Any SAL_CALL FTPInputStream::queryInterface(
    const Type& rType
)
    throw(
        RuntimeException
    )
{
    Any aRet = ::cppu::queryInterface(rType,
                                      SAL_STATIC_CAST( XInputStream*,this ),
                                      SAL_STATIC_CAST( XSeekable*,this ) );

    return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
}

void SAL_CALL FTPInputStream::acquire( void ) throw() {
    OWeakObject::acquire();
}

void SAL_CALL FTPInputStream::release( void ) throw() {
    OWeakObject::release();
}

sal_Int32 SAL_CALL FTPInputStream::readBytes(Sequence< sal_Int8 >& aData,
                                             sal_Int32 nBytesToRead)
    throw(NotConnectedException,
          BufferSizeExceededException,
          IOException,
          RuntimeException)
{
    osl::MutexGuard aGuard(m_aMutex);

    if(0 <= nBytesToRead && aData.getLength() < nBytesToRead)
        aData.realloc(nBytesToRead);

//     fpos_t bpos,epos;

//     fgetpos(m_tmpfl,&bpos);
//     fread(aData.getArray(),nBytesToRead,1,m_tmpfl);
//     fgetpos(m_tmpfl,&epos);
    long bpos,epos;

    bpos = ftell(m_tmpfl);
    fread(aData.getArray(),nBytesToRead,1,m_tmpfl);
    epos = ftell(m_tmpfl);

    return sal_Int32(epos-bpos);
}

sal_Int32 SAL_CALL FTPInputStream::readSomeBytes( Sequence< sal_Int8 >& aData,sal_Int32 nMaxBytesToRead )
    throw( NotConnectedException,
           BufferSizeExceededException,
           IOException,
           RuntimeException)
{
    return readBytes(aData,nMaxBytesToRead);
}

void SAL_CALL FTPInputStream::skipBytes(sal_Int32 nBytesToSkip)
    throw(NotConnectedException,
          BufferSizeExceededException,
          IOException,
          RuntimeException)
{
    osl::MutexGuard aGuard(m_aMutex);
    if(!m_tmpfl)
        throw IOException();

    fseek(m_tmpfl,long(nBytesToSkip),SEEK_CUR);
}

sal_Int32 SAL_CALL FTPInputStream::available(void)
    throw(NotConnectedException,
          IOException,
          RuntimeException)
{
    return sal::static_int_cast<sal_Int32>(m_nLength - getPosition());
}

void SAL_CALL FTPInputStream::closeInput(void)
    throw(NotConnectedException,
          IOException,
          RuntimeException)
{
    osl::MutexGuard aGuard(m_aMutex);
    if(m_tmpfl)
        fclose(m_tmpfl),m_tmpfl = 0;
}

void SAL_CALL FTPInputStream::seek(sal_Int64 location)
    throw( IllegalArgumentException,
           IOException,
           RuntimeException )
{
    osl::MutexGuard aGuard(m_aMutex);
    if(!m_tmpfl)
        throw IOException();

    fseek(m_tmpfl,long(location),SEEK_SET);
}

sal_Int64 SAL_CALL
FTPInputStream::getPosition(
    void )
    throw( IOException,
           RuntimeException )
{
    osl::MutexGuard aGuard(m_aMutex);
    if(!m_tmpfl)
        throw IOException();

//     fpos_t pos;
//     fgetpos(m_tmpfl,&pos);
    long pos;
    pos = ftell(m_tmpfl);
    return sal_Int64(pos);
}

sal_Int64 SAL_CALL FTPInputStream::getLength(
    void
) throw(
    IOException,RuntimeException
)
{
    return m_nLength;
}
<|endoftext|>


<commit_before>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/model/CModelValue.cpp,v $
   $Revision: 1.36 $
   $Name:  $
   $Author: shoops $
   $Date: 2006/10/25 15:09:38 $
   End CVS Header */

// Copyright  2005 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc. and EML Research, gGmbH.
// All rights reserved.

#include <iostream>
#include <string>
#include <vector>
#include <limits>

#include "copasi.h"

#include "CModel.h"
#include "CModelValue.h"

#include "CopasiDataModel/CCopasiDataModel.h"
#include "function/CExpression.h"
#include "report/CCopasiObjectReference.h"
#include "report/CKeyFactory.h"
#include "utilities/utility.h"

//static
const std::string CModelEntity::StatusName[] =
  {
    "fixed",
    "assignment",
    "determined by reactions",
    "ode",
    ""
  };

//static
const char * CModelEntity::XMLStatus[] =
  {
    "fixed",
    "assignment",
    "reactions",
    "ode",
    NULL
  };

// the "variable" keyword is used for compatibility reasons. It actually means "this metab is part
// of the reaction network, copasi needs to figure out if it is independent, dependent (moieties) or unused."

CModelEntity::CModelEntity(const std::string & name,
                           const CCopasiContainer * pParent,
                           const std::string & type,
                           const unsigned C_INT32 & flag):
    CCopasiContainer(name, pParent, type, (flag | CCopasiObject::Container | CCopasiObject::ValueDbl | CCopasiObject::ModelEntity)),
    mKey(""),
    mpValueData(NULL),
    mpValueAccess(NULL),
    mpIValue(NULL),
    mRate(0.0),
    mpExpression(NULL),
    mpInitialExpression(NULL),
    mStatus(FIXED),
    mUsed(false),
    mUsedOnce(false),
    mpModel(NULL)
{
  initObjects();

  *mpIValue = 1.0;
  *mpValueData = std::numeric_limits<C_FLOAT64>::quiet_NaN();

  CONSTRUCTOR_TRACE;
}

CModelEntity::CModelEntity(const CModelEntity & src,
                           const CCopasiContainer * pParent):
    CCopasiContainer(src, pParent),
    mKey(""),
    mpValueData(NULL),
    mpValueAccess(NULL),
    mpIValue(NULL),
    mRate(src.mRate),
    mpExpression(new CExpression(*src.mpExpression)),
    mpInitialExpression(new CExpression(*src.mpInitialExpression)),
    mStatus(FIXED),
    mUsed(false),
    mUsedOnce(false),
    mpModel(NULL)
{
  initObjects();

  setStatus(src.mStatus);

  *mpValueData = *src.mpValueData;
  *mpIValue = *src.mpIValue;

  CONSTRUCTOR_TRACE;
}

CModelEntity::~CModelEntity()
{
  if (mpModel)
    mpModel->getStateTemplate().remove(this);

  // After the above call we definitely own the data and
  // therfore must destroy them.

  pdelete(mpValueData);
  pdelete(mpIValue);
  pdelete(mpExpression);
  pdelete(mpInitialExpression);

  DESTRUCTOR_TRACE;
}

const std::string & CModelEntity::getKey() const {return mKey;}

const C_FLOAT64 & CModelEntity::getValue() const {return *mpValueAccess;}

const C_FLOAT64 & CModelEntity::getInitialValue() const {return *mpIValue;}

const CModelEntity::Status & CModelEntity::getStatus() const {return mStatus;}

bool CModelEntity::compile()
{
  if (isFixed()) return true;

  std::vector< CCopasiContainer * > listOfContainer;
  listOfContainer.push_back(getObjectAncestor("Model"));

  bool success = mpExpression->compile(listOfContainer);

  switch (mStatus)
    {
    case ASSIGNMENT:
      mpValueReference->setDirectDependencies(mpExpression->getDirectDependencies());
      break;

    case ODE:
      mpRateReference->setDirectDependencies(mpExpression->getDirectDependencies());
      break;

    default:
      break;
    }

  return success;
}

void CModelEntity::calculate()
{
  switch (mStatus)
    {
    case ASSIGNMENT:
      *mpValueData = mpExpression->calcValue();
      break;

    case ODE:
      mRate = mpExpression->calcValue();
      break;

    default:
      break;
    }
}

bool CModelEntity::setExpression(const std::string & expression)
{
  if (isFixed()) return false;

  if (mpExpression == NULL)
    mpExpression = new CExpression;

  if (mpModel)
    mpModel->setCompileFlag(true);

  if (!mpExpression->setInfix(expression)) return false;

  return compile();
}

std::string CModelEntity::getExpression() const
  {
    if (isFixed() || mpExpression == NULL)
      return "";

    mpExpression->updateInfix();
    return mpExpression->getInfix();
  }

CExpression* CModelEntity::getExpressionPtr()
{
  return mpExpression;
}

const CExpression* CModelEntity::getExpressionPtr() const
  {
    return mpExpression;
  }

bool CModelEntity::setExpressionPtr(CExpression* pExpression)
{
  if (isFixed()) return false;

  if (mpExpression)
    pdelete(mpExpression);

  mpExpression = pExpression;

  if (mpModel)
    mpModel->setCompileFlag(true);

  return compile();
}

bool CModelEntity::setInitialExpression(const std::string & expression)
{
  if (mStatus == ASSIGNMENT) return false;

  if (mpInitialExpression == NULL)
    mpInitialExpression = new CExpression;

  return mpInitialExpression->setInfix(expression);
}

std::string CModelEntity::getInitialExpression() const
  {
    if (mStatus == ASSIGNMENT || mpInitialExpression == NULL)
      return "";

    return mpInitialExpression->getInfix();
  }

/**
 * Return rate of production of this entity
 */
const C_FLOAT64 & CModelEntity::getRate() const
  {
    return mRate;
  }

CCopasiObject * CModelEntity::getValueReference()
{return mpValueReference;}

CCopasiObject * CModelEntity::getRateReference()
{return mpRateReference;}

//***********

void CModelEntity::setValue(const C_FLOAT64 & value)
{
  if (mStatus == FIXED) return;

  *mpValueData = value;

#ifdef COPASI_DEBUG
  //if (mStatus == FIXED)
  //std::cout << "warning: set the transient concentration on a fixed entity" << std::endl;
#endif
}

void CModelEntity::setInitialValue(const C_FLOAT64 & initialValue)
{
  *mpIValue = initialValue;

  if (mStatus != FIXED) return;
}

void CModelEntity::setRate(const C_FLOAT64 & rate)
{
  mRate = rate;
}

//  ******************

void CModelEntity::setStatus(const CModelEntity::Status & status)
{
  if (mStatus != status)
    {
      mStatus = status;
      this->setValuePtr(mpValueData);

      if (mpModel != NULL)
        mpModel->setCompileFlag(true);

      std::set< const CCopasiObject * > NoDependencies;

      setDirectDependencies(NoDependencies);
      clearRefresh();

      mpValueReference->setDirectDependencies(NoDependencies);
      mpValueReference->clearRefresh();

      mpRateReference->setDirectDependencies(NoDependencies);
      mpRateReference->clearRefresh();

      switch (mStatus)
        {
        case ASSIGNMENT:
          if (mpExpression == NULL)
            mpExpression = new CExpression;
          pdelete(mpInitialExpression)

          mpValueReference->setDirectDependencies(mpExpression->getDirectDependencies());
          mpValueReference->setRefresh(this, &CModelEntity::calculate);

          mUsed = true;
          mUsedOnce = false;
          break;

        case ODE:
          if (mpExpression == NULL)
            mpExpression = new CExpression;
          if (mpInitialExpression == NULL)
            mpInitialExpression = new CExpression;

          mpRateReference->setDirectDependencies(mpExpression->getDirectDependencies());
          mpRateReference->setRefresh(this, &CModelEntity::calculate);

          mUsed = true;
          mUsedOnce = false;
          break;

        case REACTIONS:
          pdelete(mpExpression);
          if (mpInitialExpression == NULL)
            mpInitialExpression = new CExpression;

          mUsed = true;
          mUsedOnce = false;
          break;

        case TIME:
          pdelete(mpExpression);
          if (mpInitialExpression == NULL)
            mpInitialExpression = new CExpression;

          mUsed = true;
          mUsedOnce = false;
          break;

        case FIXED:
          pdelete(mpExpression);
          if (mpInitialExpression == NULL)
            mpInitialExpression = new CExpression;

          mUsed = false;
          mUsedOnce = false;
          break;
        }
    }
}

void * CModelEntity::getValuePointer() const
{return const_cast<C_FLOAT64 *>(mpValueAccess);}

void CModelEntity::initObjects()
{
  C_FLOAT64 Dummy;

  mpValueReference =
    static_cast<CCopasiObjectReference<C_FLOAT64> *>(addObjectReference("Value",
        Dummy,
        CCopasiObject::ValueDbl));
  mpIValueReference =
    static_cast<CCopasiObjectReference<C_FLOAT64> *>(addObjectReference("InitialValue",
        Dummy,
        CCopasiObject::ValueDbl));

  mpRateReference =
    static_cast<CCopasiObjectReference<C_FLOAT64> *>(addObjectReference("Rate", mRate, CCopasiObject::ValueDbl));

  addObjectReference("SBMLId", mSBMLId, CCopasiObject::ValueString);

  mpModel = static_cast<CModel *>(getObjectAncestor("Model"));

  if (mpModel)
    {
      mpModel->getStateTemplate().add(this);
    }
  else
    {
      // This creates the needed values.
      setInitialValuePtr(NULL);
      setValuePtr(NULL);
    }
}

void CModelEntity::setInitialValuePtr(C_FLOAT64 * pInitialValue)
{
  mpIValue = pInitialValue;
  if (!mpIValue) mpIValue = new C_FLOAT64;
  mpIValueReference->setReference(*mpIValue);
}

void CModelEntity::setValuePtr(C_FLOAT64 * pValue)
{
  mpValueData = pValue;
  if (!mpValueData) mpValueData = new C_FLOAT64;

  if (mStatus == FIXED)
    mpValueAccess = mpIValue;
  else
    mpValueAccess = mpValueData;

  mpValueReference->setReference(*mpValueAccess);
}

bool CModelEntity::setObjectParent(const CCopasiContainer * pParent)
{
  CCopasiContainer::setObjectParent(pParent);
  CModel * pNewModel = static_cast<CModel *>(getObjectAncestor("Model"));

  if (mpModel == pNewModel) return true;

  C_FLOAT64 InitialValue = *mpIValue;
  C_FLOAT64 Value = *mpValueData;

  if (mpModel)
    {
      mpModel->getStateTemplate().remove(this);
    }
  else
    {
      pdelete(mpIValue);
      pdelete(mpValueData);
    }

  if (pNewModel)
    {
      pNewModel->getStateTemplate().add(this);
    }
  else
    {
      mpValueData = new C_FLOAT64;
      mpIValue = new C_FLOAT64;
    }

  mpModel = pNewModel;
  *mpIValue = InitialValue;
  *mpValueData = Value;

  return true;
}

std::set< const CCopasiObject * > CModelEntity::getDeletedObjects() const
  {
    std::set< const CCopasiObject * > Deleted;

    Deleted.insert(this);
    Deleted.insert(mpIValueReference);
    Deleted.insert(mpValueReference);
    Deleted.insert(mpRateReference);

    return Deleted;
  }

void CModelEntity::setSBMLId(const std::string& id)
{
  this->mSBMLId = id;
}

const std::string& CModelEntity::getSBMLId() const
  {
    return this->mSBMLId;
  }

void CModelEntity::setUsed(const bool & used)
{mUsed = used;}

const bool & CModelEntity::isUsed() const
  {return mUsed;}

void CModelEntity::setUsedOnce(const bool & usedOnce)
{mUsedOnce = usedOnce;}

const bool & CModelEntity::isUsedOnce() const
  {return mUsedOnce;}

//********************************************************************+

CModelValue::CModelValue(const std::string & name,
                         const CCopasiContainer * pParent):
    CModelEntity(name, pParent, "ModelValue")
{
  mKey = GlobalKeys.add("ModelValue", this);
  initObjects();

  CONSTRUCTOR_TRACE;
}

CModelValue::CModelValue(const CModelValue & src,
                         const CCopasiContainer * pParent):
    CModelEntity(src, pParent)
{
  mKey = GlobalKeys.add("ModelValue", this);
  initObjects();
  CONSTRUCTOR_TRACE;
}

CModelValue::~CModelValue()
{
  GlobalKeys.remove(mKey);

  DESTRUCTOR_TRACE;
}

void CModelValue::initObjects()
{}

std::ostream & operator<<(std::ostream &os, const CModelValue & d)
{
  os << "    ++++CModelValue: " << d.getObjectName() << std::endl;
  os << "        mValue " << *d.mpValueAccess << " mIValue " << *d.mpIValue << std::endl;
  os << "        mRate " << d.mRate << " mStatus " << d.getStatus() << std::endl;
  os << "    ----CModelValue " << std::endl;

  return os;
}
<commit_msg>Added time to the display and XML values.<commit_after>// Begin CVS Header
//   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/model/CModelValue.cpp,v $
//   $Revision: 1.37 $
//   $Name:  $
//   $Author: shoops $
//   $Date: 2007/02/21 16:00:22 $
// End CVS Header

// Copyright (C) 2007 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc. and EML Research, gGmbH.
// All rights reserved.

#include <iostream>
#include <string>
#include <vector>
#include <limits>

#include "copasi.h"

#include "CModel.h"
#include "CModelValue.h"

#include "CopasiDataModel/CCopasiDataModel.h"
#include "function/CExpression.h"
#include "report/CCopasiObjectReference.h"
#include "report/CKeyFactory.h"
#include "utilities/utility.h"

//static
const std::string CModelEntity::StatusName[] =
  {
    "fixed",
    "assignment",
    "determined by reactions",
    "ode",
    "time",
    ""
  };

//static
const char * CModelEntity::XMLStatus[] =
  {
    "fixed",
    "assignment",
    "reactions",
    "ode",
    "time",
    NULL
  };

// the "variable" keyword is used for compatibility reasons. It actually means "this metab is part
// of the reaction network, copasi needs to figure out if it is independent, dependent (moieties) or unused."

CModelEntity::CModelEntity(const std::string & name,
                           const CCopasiContainer * pParent,
                           const std::string & type,
                           const unsigned C_INT32 & flag):
    CCopasiContainer(name, pParent, type, (flag | CCopasiObject::Container | CCopasiObject::ValueDbl | CCopasiObject::ModelEntity)),
    mKey(""),
    mpValueData(NULL),
    mpValueAccess(NULL),
    mpIValue(NULL),
    mRate(0.0),
    mpExpression(NULL),
    mpInitialExpression(NULL),
    mStatus(FIXED),
    mUsed(false),
    mUsedOnce(false),
    mpModel(NULL)
{
  initObjects();

  *mpIValue = 1.0;
  *mpValueData = std::numeric_limits<C_FLOAT64>::quiet_NaN();

  CONSTRUCTOR_TRACE;
}

CModelEntity::CModelEntity(const CModelEntity & src,
                           const CCopasiContainer * pParent):
    CCopasiContainer(src, pParent),
    mKey(""),
    mpValueData(NULL),
    mpValueAccess(NULL),
    mpIValue(NULL),
    mRate(src.mRate),
    mpExpression(new CExpression(*src.mpExpression)),
    mpInitialExpression(new CExpression(*src.mpInitialExpression)),
    mStatus(FIXED),
    mUsed(false),
    mUsedOnce(false),
    mpModel(NULL)
{
  initObjects();

  setStatus(src.mStatus);

  *mpValueData = *src.mpValueData;
  *mpIValue = *src.mpIValue;

  CONSTRUCTOR_TRACE;
}

CModelEntity::~CModelEntity()
{
  if (mpModel)
    mpModel->getStateTemplate().remove(this);

  // After the above call we definitely own the data and
  // therfore must destroy them.

  pdelete(mpValueData);
  pdelete(mpIValue);
  pdelete(mpExpression);
  pdelete(mpInitialExpression);

  DESTRUCTOR_TRACE;
}

const std::string & CModelEntity::getKey() const {return mKey;}

const C_FLOAT64 & CModelEntity::getValue() const {return *mpValueAccess;}

const C_FLOAT64 & CModelEntity::getInitialValue() const {return *mpIValue;}

const CModelEntity::Status & CModelEntity::getStatus() const {return mStatus;}

bool CModelEntity::compile()
{
  if (isFixed()) return true;

  std::vector< CCopasiContainer * > listOfContainer;
  listOfContainer.push_back(getObjectAncestor("Model"));

  bool success = mpExpression->compile(listOfContainer);

  switch (mStatus)
    {
    case ASSIGNMENT:
      mpValueReference->setDirectDependencies(mpExpression->getDirectDependencies());
      break;

    case ODE:
      mpRateReference->setDirectDependencies(mpExpression->getDirectDependencies());
      break;

    default:
      break;
    }

  return success;
}

void CModelEntity::calculate()
{
  switch (mStatus)
    {
    case ASSIGNMENT:
      *mpValueData = mpExpression->calcValue();
      break;

    case ODE:
      mRate = mpExpression->calcValue();
      break;

    default:
      break;
    }
}

bool CModelEntity::setExpression(const std::string & expression)
{
  if (isFixed()) return false;

  if (mpExpression == NULL)
    mpExpression = new CExpression;

  if (mpModel)
    mpModel->setCompileFlag(true);

  if (!mpExpression->setInfix(expression)) return false;

  return compile();
}

std::string CModelEntity::getExpression() const
  {
    if (isFixed() || mpExpression == NULL)
      return "";

    mpExpression->updateInfix();
    return mpExpression->getInfix();
  }

CExpression* CModelEntity::getExpressionPtr()
{
  return mpExpression;
}

const CExpression* CModelEntity::getExpressionPtr() const
  {
    return mpExpression;
  }

bool CModelEntity::setExpressionPtr(CExpression* pExpression)
{
  if (isFixed()) return false;

  if (mpExpression)
    pdelete(mpExpression);

  mpExpression = pExpression;

  if (mpModel)
    mpModel->setCompileFlag(true);

  return compile();
}

bool CModelEntity::setInitialExpression(const std::string & expression)
{
  if (mStatus == ASSIGNMENT) return false;

  if (mpInitialExpression == NULL)
    mpInitialExpression = new CExpression;

  return mpInitialExpression->setInfix(expression);
}

std::string CModelEntity::getInitialExpression() const
  {
    if (mStatus == ASSIGNMENT || mpInitialExpression == NULL)
      return "";

    return mpInitialExpression->getInfix();
  }

/**
 * Return rate of production of this entity
 */
const C_FLOAT64 & CModelEntity::getRate() const
  {
    return mRate;
  }

CCopasiObject * CModelEntity::getValueReference()
{return mpValueReference;}

CCopasiObject * CModelEntity::getRateReference()
{return mpRateReference;}

//***********

void CModelEntity::setValue(const C_FLOAT64 & value)
{
  if (mStatus == FIXED) return;

  *mpValueData = value;

#ifdef COPASI_DEBUG
  //if (mStatus == FIXED)
  //std::cout << "warning: set the transient concentration on a fixed entity" << std::endl;
#endif
}

void CModelEntity::setInitialValue(const C_FLOAT64 & initialValue)
{
  *mpIValue = initialValue;

  if (mStatus != FIXED) return;
}

void CModelEntity::setRate(const C_FLOAT64 & rate)
{
  mRate = rate;
}

//  ******************

void CModelEntity::setStatus(const CModelEntity::Status & status)
{
  if (mStatus != status)
    {
      mStatus = status;
      this->setValuePtr(mpValueData);

      if (mpModel != NULL)
        mpModel->setCompileFlag(true);

      std::set< const CCopasiObject * > NoDependencies;

      setDirectDependencies(NoDependencies);
      clearRefresh();

      mpValueReference->setDirectDependencies(NoDependencies);
      mpValueReference->clearRefresh();

      mpRateReference->setDirectDependencies(NoDependencies);
      mpRateReference->clearRefresh();

      switch (mStatus)
        {
        case ASSIGNMENT:
          if (mpExpression == NULL)
            mpExpression = new CExpression;
          pdelete(mpInitialExpression)

          mpValueReference->setDirectDependencies(mpExpression->getDirectDependencies());
          mpValueReference->setRefresh(this, &CModelEntity::calculate);

          mUsed = true;
          mUsedOnce = false;
          break;

        case ODE:
          if (mpExpression == NULL)
            mpExpression = new CExpression;
          if (mpInitialExpression == NULL)
            mpInitialExpression = new CExpression;

          mpRateReference->setDirectDependencies(mpExpression->getDirectDependencies());
          mpRateReference->setRefresh(this, &CModelEntity::calculate);

          mUsed = true;
          mUsedOnce = false;
          break;

        case REACTIONS:
          pdelete(mpExpression);
          if (mpInitialExpression == NULL)
            mpInitialExpression = new CExpression;

          mUsed = true;
          mUsedOnce = false;
          break;

        case TIME:
          pdelete(mpExpression);
          if (mpInitialExpression == NULL)
            mpInitialExpression = new CExpression;

          mUsed = true;
          mUsedOnce = false;
          break;

        case FIXED:
          pdelete(mpExpression);
          if (mpInitialExpression == NULL)
            mpInitialExpression = new CExpression;

          mUsed = false;
          mUsedOnce = false;
          break;
        }
    }
}

void * CModelEntity::getValuePointer() const
{return const_cast<C_FLOAT64 *>(mpValueAccess);}

void CModelEntity::initObjects()
{
  C_FLOAT64 Dummy;

  mpValueReference =
    static_cast<CCopasiObjectReference<C_FLOAT64> *>(addObjectReference("Value",
        Dummy,
        CCopasiObject::ValueDbl));
  mpIValueReference =
    static_cast<CCopasiObjectReference<C_FLOAT64> *>(addObjectReference("InitialValue",
        Dummy,
        CCopasiObject::ValueDbl));

  mpRateReference =
    static_cast<CCopasiObjectReference<C_FLOAT64> *>(addObjectReference("Rate", mRate, CCopasiObject::ValueDbl));

  addObjectReference("SBMLId", mSBMLId, CCopasiObject::ValueString);

  mpModel = static_cast<CModel *>(getObjectAncestor("Model"));

  if (mpModel)
    {
      mpModel->getStateTemplate().add(this);
    }
  else
    {
      // This creates the needed values.
      setInitialValuePtr(NULL);
      setValuePtr(NULL);
    }
}

void CModelEntity::setInitialValuePtr(C_FLOAT64 * pInitialValue)
{
  mpIValue = pInitialValue;
  if (!mpIValue) mpIValue = new C_FLOAT64;
  mpIValueReference->setReference(*mpIValue);
}

void CModelEntity::setValuePtr(C_FLOAT64 * pValue)
{
  mpValueData = pValue;
  if (!mpValueData) mpValueData = new C_FLOAT64;

  if (mStatus == FIXED)
    mpValueAccess = mpIValue;
  else
    mpValueAccess = mpValueData;

  mpValueReference->setReference(*mpValueAccess);
}

bool CModelEntity::setObjectParent(const CCopasiContainer * pParent)
{
  CCopasiContainer::setObjectParent(pParent);
  CModel * pNewModel = static_cast<CModel *>(getObjectAncestor("Model"));

  if (mpModel == pNewModel) return true;

  C_FLOAT64 InitialValue = *mpIValue;
  C_FLOAT64 Value = *mpValueData;

  if (mpModel)
    {
      mpModel->getStateTemplate().remove(this);
    }
  else
    {
      pdelete(mpIValue);
      pdelete(mpValueData);
    }

  if (pNewModel)
    {
      pNewModel->getStateTemplate().add(this);
    }
  else
    {
      mpValueData = new C_FLOAT64;
      mpIValue = new C_FLOAT64;
    }

  mpModel = pNewModel;
  *mpIValue = InitialValue;
  *mpValueData = Value;

  return true;
}

std::set< const CCopasiObject * > CModelEntity::getDeletedObjects() const
  {
    std::set< const CCopasiObject * > Deleted;

    Deleted.insert(this);
    Deleted.insert(mpIValueReference);
    Deleted.insert(mpValueReference);
    Deleted.insert(mpRateReference);

    return Deleted;
  }

void CModelEntity::setSBMLId(const std::string& id)
{
  this->mSBMLId = id;
}

const std::string& CModelEntity::getSBMLId() const
  {
    return this->mSBMLId;
  }

void CModelEntity::setUsed(const bool & used)
{mUsed = used;}

const bool & CModelEntity::isUsed() const
  {return mUsed;}

void CModelEntity::setUsedOnce(const bool & usedOnce)
{mUsedOnce = usedOnce;}

const bool & CModelEntity::isUsedOnce() const
  {return mUsedOnce;}

//********************************************************************+

CModelValue::CModelValue(const std::string & name,
                         const CCopasiContainer * pParent):
    CModelEntity(name, pParent, "ModelValue")
{
  mKey = GlobalKeys.add("ModelValue", this);
  initObjects();

  CONSTRUCTOR_TRACE;
}

CModelValue::CModelValue(const CModelValue & src,
                         const CCopasiContainer * pParent):
    CModelEntity(src, pParent)
{
  mKey = GlobalKeys.add("ModelValue", this);
  initObjects();
  CONSTRUCTOR_TRACE;
}

CModelValue::~CModelValue()
{
  GlobalKeys.remove(mKey);

  DESTRUCTOR_TRACE;
}

void CModelValue::initObjects()
{}

std::ostream & operator<<(std::ostream &os, const CModelValue & d)
{
  os << "    ++++CModelValue: " << d.getObjectName() << std::endl;
  os << "        mValue " << *d.mpValueAccess << " mIValue " << *d.mpIValue << std::endl;
  os << "        mRate " << d.mRate << " mStatus " << d.getStatus() << std::endl;
  os << "    ----CModelValue " << std::endl;

  return os;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <boost/variant.hpp>

using std::nullptr_t;
using std::pair;
using std::make_pair;
using std::move;

template <typename T, typename F, typename BaseInner, typename ArgsT>
struct ComposeVariantVisitor
{
  struct Inner : BaseInner
  {
    Inner(ArgsT&& a) : BaseInner(std::move(a.second)), f_(std::move(a.first)) {}

    using BaseInner::operator();

    void operator()(T& t) const { f_(t); }

private:

    F f_;
  };

  ComposeVariantVisitor(ArgsT&& args) : m_args(move(args))
  {
  }

  template<typename Tadd, typename Fadd>
  auto on(Fadd&& f)
  {
    return ComposeVariantVisitor<Tadd, Fadd, Inner, std::pair<Fadd, ArgsT>>(
        make_pair(move(f), move(m_args)));
  }

  auto end_visitor()
  {
    return Inner(move(m_args));
  }

  ArgsT m_args;
};

struct EmptyVariantVisitor
{
  struct Inner : public boost::static_visitor<>
  {
    struct detail_t {};

    Inner(nullptr_t)
    {
    }

    void operator()(detail_t&) const {}
  };

  template <typename Tadd, typename Fadd>
  auto on(Fadd&& f)
  {
    return ComposeVariantVisitor<Tadd, Fadd, Inner, pair<Fadd, nullptr_t>>(
        make_pair(move(f), nullptr));
  }
};

EmptyVariantVisitor begin_variant_visitor()
{
    return EmptyVariantVisitor();
}

class A{};
class B{};
class C{};

int main(int argc, char* argv[])
{
  boost::variant<A,B,C> v;

  /////////////////////////////////////////////////////////////

  struct printer : boost::static_visitor<>
  {
    void operator()(A&) const { std::cout << "A\n"; }
    void operator()(B&) const { std::cout << "B\n"; }
    void operator()(C&) const { std::cout << "C\n"; }
  };

  v = A();
  boost::apply_visitor(printer(), v);

  v = B();
  boost::apply_visitor(printer(), v);

  v = C();
  boost::apply_visitor(printer(), v);

  std::cout << "\n";

  /////////////////////////////////////////////////////////////

  auto inline_printer = begin_variant_visitor()
    .on<A>([](A&) { std::cout << "A\n";})
    .on<B>([](B&) { std::cout << "B\n";})
    .on<C>([](C&) { std::cout << "C\n";})
    .end_visitor();

  v = A();
  boost::apply_visitor(inline_printer, v);

  v = B();
  boost::apply_visitor(inline_printer, v);

  v = C();
  boost::apply_visitor(inline_printer, v);
}

<commit_msg>remove use of std:: ready for publication of code<commit_after>#include <iostream>
#include <boost/variant.hpp>

using std::nullptr_t;
using std::pair;
using std::make_pair;
using std::move;
using std::cout;

template <typename T, typename F, typename BaseInner, typename ArgsT>
struct ComposeVariantVisitor
{
  struct Inner : BaseInner
  {
    Inner(ArgsT&& a) : BaseInner(move(a.second)), f_(move(a.first)) {}

    using BaseInner::operator();

    void operator()(T& t) const { f_(t); }

private:

    F f_;
  };

  ComposeVariantVisitor(ArgsT&& args) : m_args(move(args))
  {
  }

  template<typename Tadd, typename Fadd>
  auto on(Fadd&& f)
  {
    return ComposeVariantVisitor<Tadd, Fadd, Inner, pair<Fadd, ArgsT>>(
        make_pair(move(f), move(m_args)));
  }

  auto end_visitor()
  {
    return Inner(move(m_args));
  }

  ArgsT m_args;
};

struct EmptyVariantVisitor
{
  struct Inner : public boost::static_visitor<>
  {
    struct detail_t {};

    Inner(nullptr_t)
    {
    }

    void operator()(detail_t&) const {}
  };

  template <typename Tadd, typename Fadd>
  auto on(Fadd&& f)
  {
    return ComposeVariantVisitor<Tadd, Fadd, Inner, pair<Fadd, nullptr_t>>(
        make_pair(move(f), nullptr));
  }
};

EmptyVariantVisitor begin_variant_visitor()
{
    return EmptyVariantVisitor();
}

class A{};
class B{};
class C{};

int main(int argc, char* argv[])
{
  boost::variant<A,B,C> v;

  /////////////////////////////////////////////////////////////

  struct printer : boost::static_visitor<>
  {
    void operator()(A&) const { cout << "A\n"; }
    void operator()(B&) const { cout << "B\n"; }
    void operator()(C&) const { cout << "C\n"; }
  };

  v = A();
  boost::apply_visitor(printer(), v);

  v = B();
  boost::apply_visitor(printer(), v);

  v = C();
  boost::apply_visitor(printer(), v);

  cout << "\n";

  /////////////////////////////////////////////////////////////

  auto inline_printer = begin_variant_visitor()
    .on<A>([](A&) { cout << "A\n";})
    .on<B>([](B&) { cout << "B\n";})
    .on<C>([](C&) { cout << "C\n";})
    .end_visitor();

  v = A();
  boost::apply_visitor(inline_printer, v);

  v = B();
  boost::apply_visitor(inline_printer, v);

  v = C();
  boost::apply_visitor(inline_printer, v);
}

<|endoftext|>


<commit_before>#include "test.hpp"
#include "cppa/cppa.hpp"

using namespace cppa;

/*

test case:

  A                  B                  C
  |                  |                  |
  | --(sync_send)--> |                  |
  |                  | --(forward)----> |
  |                  X                  |---\
  |                                     |   |
  |                                     |<--/
  | <-------------(reply)-------------- |

*/

struct A : event_based_actor {
    void init() {
        become (
            on(atom("go"), arg_match) >> [=](const actor_ptr& next) {
                handle_response(sync_send(next, atom("gogo"))) (
                    on(atom("gogogo")) >> [=] {
                        quit();
                    },
                    after(std::chrono::seconds(1)) >> [=] {
                        quit(exit_reason::user_defined);
                    }
                );
            },
            others() >> [=] {
                cerr << "UNEXPECTED: " << to_string(last_dequeued()) << endl;
            }
        );
    }
};

struct B : event_based_actor {
    actor_ptr m_buddy;
    B(const actor_ptr& buddy) : m_buddy(buddy) { }
    void init() {
        become (
            others() >> [=]() {
                forward_to(m_buddy);
            }
        );
    }
};

struct C : event_based_actor {
    void init() {
        become (
            on(atom("gogo")) >> [=] {
                reply(atom("gogogo"));
            }
        );
    }
};

int main() {
    send(spawn<A>(), atom("go"), spawn<B>(spawn<C>()));
    await_all_others_done();
    return 0;
}
<commit_msg>added quit() to all testees<commit_after>#include "test.hpp"
#include "cppa/cppa.hpp"

using namespace cppa;

/*

test case:

  A                  B                  C
  |                  |                  |
  | --(sync_send)--> |                  |
  |                  | --(forward)----> |
  |                  X                  |---\
  |                                     |   |
  |                                     |<--/
  | <-------------(reply)-------------- |

*/

struct A : event_based_actor {
    void init() {
        become (
            on(atom("go"), arg_match) >> [=](const actor_ptr& next) {
                handle_response(sync_send(next, atom("gogo"))) (
                    on(atom("gogogo")) >> [=] {
cout << "A received gogogo" << endl;
                        quit();
                    },
                    after(std::chrono::seconds(1)) >> [=] {
                        quit(exit_reason::user_defined);
                    }
                );
            },
            others() >> [=] {
cerr << "UNEXPECTED: " << to_string(last_dequeued()) << endl;
            }
        );
    }
};

struct B : event_based_actor {
    actor_ptr m_buddy;
    B(const actor_ptr& buddy) : m_buddy(buddy) { }
    void init() {
        become (
            others() >> [=]() {
cout << "B forward_to C" << endl;
                forward_to(m_buddy);
                quit();
            }
        );
    }
};

struct C : event_based_actor {
    void init() {
        become (
            on(atom("gogo")) >> [=] {
cout << "C received gogo (reply)" << endl;
                reply(atom("gogogo"));
                quit();
            }
        );
    }
};

int main() {
    send(spawn<A>(), atom("go"), spawn<B>(spawn<C>()));
    await_all_others_done();
    return 0;
}
<|endoftext|>


<commit_before>#include "TextInputWidget.hpp"
#include <iostream>

gsf::TextInputWidget::Ptr gsf::TextInputWidget::create(sf::Font &font)
{
    Ptr widget{ std::make_unique<TextInputWidget>(font) };
    return widget;
}

gsf::TextInputWidget::Ptr gsf::TextInputWidget::create(float width, float height,
        sf::Font &font)
{
    Ptr widget{ std::make_unique<TextInputWidget>(width, height, font) };
    return widget;
}

gsf::TextInputWidget::TextInputWidget(sf::Font &font)
: Widget{ }
//, m_text{ "", font, 12, sf::Color::Black }
, m_text{ nullptr }
, m_font{ font }
, m_charSize{ 12 }
, m_isEditable{ true }
, m_cursor{ "|", font, m_charSize }
, m_cursorColor{ sf::Color::Black }
, m_scrollable{ nullptr }
, m_acceptNewLines{ true }
, m_isFocused{ false }
, m_cursorPos{ 0 }
, m_lBreaksBefCur{ 0 }
, m_isCursorShown{ true }
, m_blinkFreq{ 0.8f }
, m_lastBlinkTime{ 0.f }
, m_whiteListChars{ L"" }
, m_blackListChars{ L"" }
, m_minBreakCharCnt{ 0 }
{
    init();
}
gsf::TextInputWidget::TextInputWidget(float width, float height,
        sf::Font &font)
: Widget{ width, height }
//, m_text{ "", font, 12, sf::Color::Black }
, m_text{ nullptr }
, m_font{ font }
, m_charSize{ 12 }
, m_isEditable{ true }
, m_cursor{ "|", font, m_charSize }
, m_cursorColor{ sf::Color::Black }
, m_scrollable{ nullptr }
, m_acceptNewLines{ true }
, m_isFocused{ false }
, m_cursorPos{ 0 }
, m_lBreaksBefCur{ 0 }
, m_isCursorShown{ true }
, m_blinkFreq{ 0.8f }
, m_lastBlinkTime{ 0.f }
, m_whiteListChars{ L"" }
, m_blackListChars{ L"" }
, m_minBreakCharCnt{ 0 }
{
    init();
}

void gsf::TextInputWidget::init()
{
    std::unique_ptr<TextWidget> text{
        std::make_unique<TextWidget>("", m_font, m_charSize, sf::Color::Black) };
    std::unique_ptr<ScrollableWidget> scrollable{
        std::make_unique<ScrollableWidget>(
                getWidth(),
                getHeight()) };
    m_scrollable = scrollable.get();
    m_text = text.get();
    scrollable->setBackgroundColor(sf::Color::Transparent);
    scrollable->attachChild(std::move(text));
    // Change content area so that the scrollbar fits in the TextInputWidget when
    // necassary.
    scrollable->setOnVerticalScrollNeededChangedListener(
            [](Widget* widget, bool isNeeded)
            {
                // Vertical Scrollbar is needed so we reduce the width of the content
                // area, so that the scrollbar fits in the TextInputWidget
                if (isNeeded)
                {
                    widget->setWidth(widget->getWidth()
                            - ScrollableWidget::SCROLLBAR_THICKNESS);
                }
                // Vertical Scrollbar is no longer so we can make the
                // reductoion undone
                else
                {
                    widget->setWidth(widget->getWidth()
                            + ScrollableWidget::SCROLLBAR_THICKNESS);
                }
            });
    attachChild(std::move(scrollable));
    m_cursor.setFillColor(m_cursorColor);
    setOutlineThickness(4.f);
}

void gsf::TextInputWidget::setCursorColor(sf::Color color)
{
    m_cursorColor = color;
    m_cursor.setFillColor(color);
}

sf::Color gsf::TextInputWidget::getCursorColor() const
{
    return m_cursorColor;
}

void gsf::TextInputWidget::setIsEditable(bool isEditable)
{
    m_isEditable = isEditable;
}

bool gsf::TextInputWidget::isEditable() const
{
    return m_isEditable;
}

void gsf::TextInputWidget::setText(const std::wstring &text)
{
    m_currentText = text;
    m_text->setText(m_currentText);
    // Move cursor to end of text
    m_cursorPos = m_currentText.size();
    // Adjust text so that it fits the scrollbar when horizontal scrolling is disabled
    adjustShownText();
    m_scrollable->recalculateScroll();
    m_scrollable->scrollToBottom();
    m_scrollable->scrollToLeft();
}

std::wstring gsf::TextInputWidget::getText() const
{
    //return m_text->getText().toWideString();
    return m_currentText;
}

void gsf::TextInputWidget::setCharacterSize(const unsigned int size)
{
    m_text->setCharacterSize(size);
    m_charSize = size;
    m_cursor.setCharacterSize(size);
}

unsigned int gsf::TextInputWidget::getCharacterSize() const
{
    return m_charSize;
}

void gsf::TextInputWidget::setTextColor(const sf::Color color)
{
    m_text->setTextColor(color);
}

sf::Color gsf::TextInputWidget::getTextColor() const
{
    return m_text->getTextColor();
}

void gsf::TextInputWidget::setIsNewLineAccepted(bool isAccepted)
{
    m_acceptNewLines = isAccepted;
}

bool gsf::TextInputWidget::getIsNewLineAccepted() const
{
    return m_acceptNewLines;
}

bool gsf::TextInputWidget::isFocused() const
{
    return m_isFocused;
}

void gsf::TextInputWidget::setIsVerticalScrollEnabled(bool isEnabled)
{
    m_scrollable->setIsVerticalScrollEnabled(isEnabled);
}

bool gsf::TextInputWidget::isVerticalScrollEnabled() const
{
    return m_scrollable->isVerticalScrollEnabled();
}

void gsf::TextInputWidget::setIsHorizontalScrollEnabled(bool isEnabled)
{
    m_scrollable->setIsHorizontalScrollEnabled(isEnabled);
}

bool gsf::TextInputWidget::isHorizontalScrollEnabled() const
{
    return m_scrollable->isHorizontalScrollEnabled();
}

void gsf::TextInputWidget::setIsVerticalScrollbarDrawn(bool isDrawn)
{
    m_scrollable->setIsVerticalScrollbarDrawn(isDrawn);
}

void gsf::TextInputWidget::setIsHorizontalScrollbarDrawn(bool isDrawn)
{
    m_scrollable->setIsHorizontalScrollbarDrawn(isDrawn);
}

std::wstring gsf::TextInputWidget::getBlackListChars() const
{
    return m_blackListChars;
}

void gsf::TextInputWidget::setBlackListChars(std::wstring chars)
{
    m_blackListChars = chars;
}

std::wstring gsf::TextInputWidget::getWhiteListChars() const
{
    return m_whiteListChars;
}

void gsf::TextInputWidget::setWhiteListChars(std::wstring chars)
{
    m_whiteListChars = chars;
}

void gsf::TextInputWidget::adjustShownText()
{
    if (!m_scrollable->isHorizontalScrollEnabled() && m_currentText.size() > 0)
    {
        m_lBreaksBefCur = 0;
        m_lBreakIndexes.clear();
        std::wstring shownString{ L"" };
        // The chars which are in the actual line
        unsigned int charCntLine{ 0 };
        // The total width of all chars in the current line
        float lineWidth{ 0.f };
        for (unsigned int i{ 0 }; i < m_currentText.size(); i++)
        {
            wchar_t c{ m_currentText[i] };
            // If we have a new line as char we can set the lineWidth and charCntLine
            // to 0 because there is no need to handle the chars in this line
            // (It is already handled by user width the new line char)
            if (c == '\n')
            {
                lineWidth = 0.f;
                charCntLine = 0;
                shownString += c;
                continue;
            }
            // Width of the current char
            float cWidth{ m_text->getWidthAndHeightOfChar(c).x };
            lineWidth += cWidth;
            // When Text is out of scrollable widget, we have to add a new line
            if (lineWidth > m_scrollable->getWidth())
            {
                if (i < m_cursorPos)
                {
                    // We have to increase the "line breaks befor cursor" counter
                    // so we add the cursor later on the right position
                    m_lBreaksBefCur++;
                }
                //shownString += m_currentText.substr(i - charCntLine, charCntLine);
                // Add new line
                shownString += L"\n";
                // Store the position (of the shown text)
                // where the new line was added
                m_lBreakIndexes.push_back(i + 1);
                // add the char with which the line was to wide in the new line
                shownString += c;
                // We have added the char c in the new line,
                // so we have now 1 char in the current line
                charCntLine = 1;
                lineWidth = cWidth;
            }
            else
            {
                charCntLine++;
                shownString += c;
            }
        }
        m_shownText = shownString;
        m_text->setText(m_shownText);
    }
}

void gsf::TextInputWidget::resetCursorStatus()
{
    m_lastBlinkTime = 0.f;
    m_isCursorShown = true;
}

unsigned int gsf::TextInputWidget::getAddedLineBreaksUpToIndex
    (unsigned int index) const
{
    unsigned int cnt{ 0 };

    for (unsigned int lBreakIndex : m_lBreakIndexes)
    {
        if (lBreakIndex < index)
        {
            cnt++;
        }
        else
        {
            return cnt;
        }
    }
    return cnt;
}

bool gsf::TextInputWidget::handleEventCurrentAfterChildren(sf::Event &event,
        const sf::RenderTarget &target)
{

    bool handled{ Widget::handleEventCurrentAfterChildren(event, target) };
    if (!m_isEditable)
    {
        // Nothing to do
        return handled;
    }

    //bool handled{ ChildWidget::handleEvent(event) };/*||
      //  m_scrollable->handleEventWidget(event) };*/
    // Check if actual Widget is focused
    if (event.type == sf::Event::MouseButtonPressed)
    {
        sf::Vector2f mousePos{ target.mapPixelToCoords({ event.mouseButton.x,
            event.mouseButton.y }) };
        sf::Vector2f localPos{ convertToLocalPoint(mousePos) };

        bool isMouseInShownArea{ getShownArea().contains(mousePos) };
        bool intersecting{ isIntersecting(mousePos) };
        if (isMouseInShownArea && intersecting)
        {
            m_isFocused = true;
            handled = true;
            // Put cursor to clicked postion
            // Get the index of the char where the mouse has clicked
            int clickedCharIndex{ m_text->findIndexOfCharOnPos(localPos) };
            // Clicked on a char?
            if (clickedCharIndex > -1)
            {
                // The index is the index of m_shownText, but we need the index of
                // the char in m_currentText, so we have to remove the automatic
                // added line breaks.
                unsigned int autoAddedLineBreaks{
                    getAddedLineBreaksUpToIndex(clickedCharIndex) };
                m_cursorPos = clickedCharIndex - autoAddedLineBreaks;
                m_lBreaksBefCur = autoAddedLineBreaks;
            }
            // If there was no click on a char, move cursor to end
            else
            {

                m_cursorPos = m_shownText.length();
            }
        }
        else
        {
            m_isFocused = false;
        }
    }
    if (event.type == sf::Event::KeyPressed && m_isFocused)
    {
        switch (event.key.code)
        {
        case sf::Keyboard::Left:
            if (m_cursorPos > 0)
            {
                m_cursorPos--;
            }
            // when cursor is moved it should be drawn so we reset its status
            resetCursorStatus();
            adjustShownText();
            //m_cursor.setPosition(
            //    m_text->findCharacterPos(m_cursorPos + m_lBreaksBefCur));
            return true;
        case sf::Keyboard::Right:
            if (m_cursorPos < m_currentText.length())
            {
                m_cursorPos++;
            }
            resetCursorStatus();
            adjustShownText();
            //m_cursor.setPosition
            //    (m_text->findCharacterPos(m_cursorPos + m_lBreaksBefCur));
            return true;
        default: break;
        }
    }
    // If Widget is focused and Text entered, handle entered text
    if (m_isFocused && event.type == sf::Event::TextEntered)
    {
        // To handle umlauts and other 'exotic' chars we use widestring
        // and wide char
        //std::wstring actualTxt{ m_text.getString().toWideString() };
        wchar_t c{ static_cast<wchar_t>(event.text.unicode) };
        std::cout << "Entered: " << c << std::endl;
        switch (c)
        {
        // Backspace
        case 8:
            if (m_currentText.length() > 0)
            {
                // Remove chars right of cursor when there are chars
                if (m_cursorPos > 0 && m_cursorPos < m_currentText.length())
                {
                    m_currentText.erase(m_cursorPos - 1, 1);
                    m_cursorPos--;
                }
                // When cursos is at the end of the text, p
                // place cursor behind char which we want to delete,
                else if (m_cursorPos == m_currentText.length())
                {
                    // Delete last char
                    m_currentText.pop_back();
                    m_cursorPos--;
                }
            }
            break;
        // Delete Pressed
        case 127:
            if (m_currentText.length() > 0 &&
                    m_cursorPos < m_currentText.length())
            {
                m_currentText.erase(m_cursorPos, 1);
            }
            break;
        // Enter key
        case 13:
            // Dont add new line, when new lines are not accepted
            if (!m_acceptNewLines)
            {
                return false;
            }
            m_currentText.insert(m_cursorPos, L"\n"); m_cursorPos++;
            break;
        // Add char to text
        default:
            // If there are white listed chars specified, check if char is in it.
            // If not return
            if (m_whiteListChars.length() > 0 &&
                    m_whiteListChars.find(c) == std::wstring::npos)
            {
                return false;
            }
            // Check if char is black listed, if so return
            if(m_blackListChars.find(c) != std::wstring::npos)
            {
                return false;
            }
            m_currentText.insert(m_cursorPos, std::wstring() + c);
                 m_cursorPos++;
        }
        resetCursorStatus();
        m_shownText = m_currentText;
        m_text->setText(m_shownText);
        adjustShownText();
        //m_cursor.setPosition
            //(m_text->findCharacterPos(m_cursorPos + m_lBreaksBefCur));
        m_scrollable->recalculateScroll();
        m_scrollable->scrollToRight();
        m_scrollable->scrollToBottom();
        return true;
    }
    return handled;
}

void gsf::TextInputWidget::updateCurrentAfterChildren(float dt)
{
    if (!m_isEditable)
    {
        // Nothing to do
        return;
    }

    // Update cursor stuff
    m_lastBlinkTime += dt;
    if (m_lastBlinkTime >= m_blinkFreq)
    {
        m_isCursorShown = !m_isCursorShown;
        m_lastBlinkTime = 0.f;
    }

    m_cursor.setPosition(
            m_text->findGlobalCharacterPos(m_cursorPos + m_lBreaksBefCur));
    //std::wstring text{ m_currentText };
    //std::wstring text{ m_shownText };
    //m_text->setText(text);
}

void gsf::TextInputWidget::drawCurrentAfterChildren(sf::RenderTarget &target,
                    sf::RenderStates states, sf::View defaultView) const
{
    // Draw cursor after children, so that children are not drawn over cursor
    if (m_isCursorShown && m_isEditable)
    {
        target.draw(m_cursor, states);
    }
}
<commit_msg>Only move cursor when left button was clicked<commit_after>#include "TextInputWidget.hpp"
#include <iostream>

gsf::TextInputWidget::Ptr gsf::TextInputWidget::create(sf::Font &font)
{
    Ptr widget{ std::make_unique<TextInputWidget>(font) };
    return widget;
}

gsf::TextInputWidget::Ptr gsf::TextInputWidget::create(float width, float height,
        sf::Font &font)
{
    Ptr widget{ std::make_unique<TextInputWidget>(width, height, font) };
    return widget;
}

gsf::TextInputWidget::TextInputWidget(sf::Font &font)
: Widget{ }
//, m_text{ "", font, 12, sf::Color::Black }
, m_text{ nullptr }
, m_font{ font }
, m_charSize{ 12 }
, m_isEditable{ true }
, m_cursor{ "|", font, m_charSize }
, m_cursorColor{ sf::Color::Black }
, m_scrollable{ nullptr }
, m_acceptNewLines{ true }
, m_isFocused{ false }
, m_cursorPos{ 0 }
, m_lBreaksBefCur{ 0 }
, m_isCursorShown{ true }
, m_blinkFreq{ 0.8f }
, m_lastBlinkTime{ 0.f }
, m_whiteListChars{ L"" }
, m_blackListChars{ L"" }
, m_minBreakCharCnt{ 0 }
{
    init();
}
gsf::TextInputWidget::TextInputWidget(float width, float height,
        sf::Font &font)
: Widget{ width, height }
//, m_text{ "", font, 12, sf::Color::Black }
, m_text{ nullptr }
, m_font{ font }
, m_charSize{ 12 }
, m_isEditable{ true }
, m_cursor{ "|", font, m_charSize }
, m_cursorColor{ sf::Color::Black }
, m_scrollable{ nullptr }
, m_acceptNewLines{ true }
, m_isFocused{ false }
, m_cursorPos{ 0 }
, m_lBreaksBefCur{ 0 }
, m_isCursorShown{ true }
, m_blinkFreq{ 0.8f }
, m_lastBlinkTime{ 0.f }
, m_whiteListChars{ L"" }
, m_blackListChars{ L"" }
, m_minBreakCharCnt{ 0 }
{
    init();
}

void gsf::TextInputWidget::init()
{
    std::unique_ptr<TextWidget> text{
        std::make_unique<TextWidget>("", m_font, m_charSize, sf::Color::Black) };
    std::unique_ptr<ScrollableWidget> scrollable{
        std::make_unique<ScrollableWidget>(
                getWidth(),
                getHeight()) };
    m_scrollable = scrollable.get();
    m_text = text.get();
    scrollable->setBackgroundColor(sf::Color::Transparent);
    scrollable->attachChild(std::move(text));
    // Change content area so that the scrollbar fits in the TextInputWidget when
    // necassary.
    scrollable->setOnVerticalScrollNeededChangedListener(
            [](Widget* widget, bool isNeeded)
            {
                // Vertical Scrollbar is needed so we reduce the width of the content
                // area, so that the scrollbar fits in the TextInputWidget
                if (isNeeded)
                {
                    widget->setWidth(widget->getWidth()
                            - ScrollableWidget::SCROLLBAR_THICKNESS);
                }
                // Vertical Scrollbar is no longer so we can make the
                // reductoion undone
                else
                {
                    widget->setWidth(widget->getWidth()
                            + ScrollableWidget::SCROLLBAR_THICKNESS);
                }
            });
    attachChild(std::move(scrollable));
    m_cursor.setFillColor(m_cursorColor);
    setOutlineThickness(4.f);
}

void gsf::TextInputWidget::setCursorColor(sf::Color color)
{
    m_cursorColor = color;
    m_cursor.setFillColor(color);
}

sf::Color gsf::TextInputWidget::getCursorColor() const
{
    return m_cursorColor;
}

void gsf::TextInputWidget::setIsEditable(bool isEditable)
{
    m_isEditable = isEditable;
}

bool gsf::TextInputWidget::isEditable() const
{
    return m_isEditable;
}

void gsf::TextInputWidget::setText(const std::wstring &text)
{
    m_currentText = text;
    m_text->setText(m_currentText);
    // Move cursor to end of text
    m_cursorPos = m_currentText.size();
    // Adjust text so that it fits the scrollbar when horizontal scrolling is disabled
    adjustShownText();
    m_scrollable->recalculateScroll();
    m_scrollable->scrollToBottom();
    m_scrollable->scrollToLeft();
}

std::wstring gsf::TextInputWidget::getText() const
{
    //return m_text->getText().toWideString();
    return m_currentText;
}

void gsf::TextInputWidget::setCharacterSize(const unsigned int size)
{
    m_text->setCharacterSize(size);
    m_charSize = size;
    m_cursor.setCharacterSize(size);
}

unsigned int gsf::TextInputWidget::getCharacterSize() const
{
    return m_charSize;
}

void gsf::TextInputWidget::setTextColor(const sf::Color color)
{
    m_text->setTextColor(color);
}

sf::Color gsf::TextInputWidget::getTextColor() const
{
    return m_text->getTextColor();
}

void gsf::TextInputWidget::setIsNewLineAccepted(bool isAccepted)
{
    m_acceptNewLines = isAccepted;
}

bool gsf::TextInputWidget::getIsNewLineAccepted() const
{
    return m_acceptNewLines;
}

bool gsf::TextInputWidget::isFocused() const
{
    return m_isFocused;
}

void gsf::TextInputWidget::setIsVerticalScrollEnabled(bool isEnabled)
{
    m_scrollable->setIsVerticalScrollEnabled(isEnabled);
}

bool gsf::TextInputWidget::isVerticalScrollEnabled() const
{
    return m_scrollable->isVerticalScrollEnabled();
}

void gsf::TextInputWidget::setIsHorizontalScrollEnabled(bool isEnabled)
{
    m_scrollable->setIsHorizontalScrollEnabled(isEnabled);
}

bool gsf::TextInputWidget::isHorizontalScrollEnabled() const
{
    return m_scrollable->isHorizontalScrollEnabled();
}

void gsf::TextInputWidget::setIsVerticalScrollbarDrawn(bool isDrawn)
{
    m_scrollable->setIsVerticalScrollbarDrawn(isDrawn);
}

void gsf::TextInputWidget::setIsHorizontalScrollbarDrawn(bool isDrawn)
{
    m_scrollable->setIsHorizontalScrollbarDrawn(isDrawn);
}

std::wstring gsf::TextInputWidget::getBlackListChars() const
{
    return m_blackListChars;
}

void gsf::TextInputWidget::setBlackListChars(std::wstring chars)
{
    m_blackListChars = chars;
}

std::wstring gsf::TextInputWidget::getWhiteListChars() const
{
    return m_whiteListChars;
}

void gsf::TextInputWidget::setWhiteListChars(std::wstring chars)
{
    m_whiteListChars = chars;
}

void gsf::TextInputWidget::adjustShownText()
{
    if (!m_scrollable->isHorizontalScrollEnabled() && m_currentText.size() > 0)
    {
        m_lBreaksBefCur = 0;
        m_lBreakIndexes.clear();
        std::wstring shownString{ L"" };
        // The chars which are in the actual line
        unsigned int charCntLine{ 0 };
        // The total width of all chars in the current line
        float lineWidth{ 0.f };
        for (unsigned int i{ 0 }; i < m_currentText.size(); i++)
        {
            wchar_t c{ m_currentText[i] };
            // If we have a new line as char we can set the lineWidth and charCntLine
            // to 0 because there is no need to handle the chars in this line
            // (It is already handled by user width the new line char)
            if (c == '\n')
            {
                lineWidth = 0.f;
                charCntLine = 0;
                shownString += c;
                continue;
            }
            // Width of the current char
            float cWidth{ m_text->getWidthAndHeightOfChar(c).x };
            lineWidth += cWidth;
            // When Text is out of scrollable widget, we have to add a new line
            if (lineWidth > m_scrollable->getWidth())
            {
                if (i < m_cursorPos)
                {
                    // We have to increase the "line breaks befor cursor" counter
                    // so we add the cursor later on the right position
                    m_lBreaksBefCur++;
                }
                //shownString += m_currentText.substr(i - charCntLine, charCntLine);
                // Add new line
                shownString += L"\n";
                // Store the position (of the shown text)
                // where the new line was added
                m_lBreakIndexes.push_back(i + 1);
                // add the char with which the line was to wide in the new line
                shownString += c;
                // We have added the char c in the new line,
                // so we have now 1 char in the current line
                charCntLine = 1;
                lineWidth = cWidth;
            }
            else
            {
                charCntLine++;
                shownString += c;
            }
        }
        m_shownText = shownString;
        m_text->setText(m_shownText);
    }
}

void gsf::TextInputWidget::resetCursorStatus()
{
    m_lastBlinkTime = 0.f;
    m_isCursorShown = true;
}

unsigned int gsf::TextInputWidget::getAddedLineBreaksUpToIndex
    (unsigned int index) const
{
    unsigned int cnt{ 0 };

    for (unsigned int lBreakIndex : m_lBreakIndexes)
    {
        if (lBreakIndex < index)
        {
            cnt++;
        }
        else
        {
            return cnt;
        }
    }
    return cnt;
}

bool gsf::TextInputWidget::handleEventCurrentAfterChildren(sf::Event &event,
        const sf::RenderTarget &target)
{

    bool handled{ Widget::handleEventCurrentAfterChildren(event, target) };
    if (!m_isEditable)
    {
        // Nothing to do
        return handled;
    }

    //bool handled{ ChildWidget::handleEvent(event) };/*||
      //  m_scrollable->handleEventWidget(event) };*/
    // Check if actual Widget is focused
    if (event.type == sf::Event::MouseButtonPressed &&
            event.mouseButton.button == sf::Mouse::Left)
    {
        sf::Vector2f mousePos{ target.mapPixelToCoords({ event.mouseButton.x,
            event.mouseButton.y }) };
        sf::Vector2f localPos{ convertToLocalPoint(mousePos) };

        bool isMouseInShownArea{ getShownArea().contains(mousePos) };
        bool intersecting{ isIntersecting(mousePos) };
        if (isMouseInShownArea && intersecting)
        {
            m_isFocused = true;
            handled = true;
            // Put cursor to clicked postion
            // Get the index of the char where the mouse has clicked
            int clickedCharIndex{ m_text->findIndexOfCharOnPos(localPos) };
            // Clicked on a char?
            if (clickedCharIndex > -1)
            {
                // The index is the index of m_shownText, but we need the index of
                // the char in m_currentText, so we have to remove the automatic
                // added line breaks.
                unsigned int autoAddedLineBreaks{
                    getAddedLineBreaksUpToIndex(clickedCharIndex) };
                m_cursorPos = clickedCharIndex - autoAddedLineBreaks;
                m_lBreaksBefCur = autoAddedLineBreaks;
            }
        }
        else
        {
            m_isFocused = false;
        }
    }
    if (event.type == sf::Event::KeyPressed && m_isFocused)
    {
        switch (event.key.code)
        {
        case sf::Keyboard::Left:
            if (m_cursorPos > 0)
            {
                m_cursorPos--;
            }
            // when cursor is moved it should be drawn so we reset its status
            resetCursorStatus();
            adjustShownText();
            //m_cursor.setPosition(
            //    m_text->findCharacterPos(m_cursorPos + m_lBreaksBefCur));
            return true;
        case sf::Keyboard::Right:
            if (m_cursorPos < m_currentText.length())
            {
                m_cursorPos++;
            }
            resetCursorStatus();
            adjustShownText();
            //m_cursor.setPosition
            //    (m_text->findCharacterPos(m_cursorPos + m_lBreaksBefCur));
            return true;
        default: break;
        }
    }
    // If Widget is focused and Text entered, handle entered text
    if (m_isFocused && event.type == sf::Event::TextEntered)
    {
        // To handle umlauts and other 'exotic' chars we use widestring
        // and wide char
        //std::wstring actualTxt{ m_text.getString().toWideString() };
        wchar_t c{ static_cast<wchar_t>(event.text.unicode) };
        std::cout << "Entered: " << c << std::endl;
        switch (c)
        {
        // Backspace
        case 8:
            if (m_currentText.length() > 0)
            {
                // Remove chars right of cursor when there are chars
                if (m_cursorPos > 0 && m_cursorPos < m_currentText.length())
                {
                    m_currentText.erase(m_cursorPos - 1, 1);
                    m_cursorPos--;
                }
                // When cursos is at the end of the text, p
                // place cursor behind char which we want to delete,
                else if (m_cursorPos == m_currentText.length())
                {
                    // Delete last char
                    m_currentText.pop_back();
                    m_cursorPos--;
                }
            }
            break;
        // Delete Pressed
        case 127:
            if (m_currentText.length() > 0 &&
                    m_cursorPos < m_currentText.length())
            {
                m_currentText.erase(m_cursorPos, 1);
            }
            break;
        // Enter key
        case 13:
            // Dont add new line, when new lines are not accepted
            if (!m_acceptNewLines)
            {
                return false;
            }
            m_currentText.insert(m_cursorPos, L"\n"); m_cursorPos++;
            break;
        // Add char to text
        default:
            // If there are white listed chars specified, check if char is in it.
            // If not return
            if (m_whiteListChars.length() > 0 &&
                    m_whiteListChars.find(c) == std::wstring::npos)
            {
                return false;
            }
            // Check if char is black listed, if so return
            if(m_blackListChars.find(c) != std::wstring::npos)
            {
                return false;
            }
            m_currentText.insert(m_cursorPos, std::wstring() + c);
                 m_cursorPos++;
        }
        resetCursorStatus();
        m_shownText = m_currentText;
        m_text->setText(m_shownText);
        adjustShownText();
        //m_cursor.setPosition
            //(m_text->findCharacterPos(m_cursorPos + m_lBreaksBefCur));
        m_scrollable->recalculateScroll();
        m_scrollable->scrollToRight();
        m_scrollable->scrollToBottom();
        return true;
    }
    return handled;
}

void gsf::TextInputWidget::updateCurrentAfterChildren(float dt)
{
    if (!m_isEditable)
    {
        // Nothing to do
        return;
    }

    // Update cursor stuff
    m_lastBlinkTime += dt;
    if (m_lastBlinkTime >= m_blinkFreq)
    {
        m_isCursorShown = !m_isCursorShown;
        m_lastBlinkTime = 0.f;
    }

    m_cursor.setPosition(
            m_text->findGlobalCharacterPos(m_cursorPos + m_lBreaksBefCur));
    //std::wstring text{ m_currentText };
    //std::wstring text{ m_shownText };
    //m_text->setText(text);
}

void gsf::TextInputWidget::drawCurrentAfterChildren(sf::RenderTarget &target,
                    sf::RenderStates states, sf::View defaultView) const
{
    // Draw cursor after children, so that children are not drawn over cursor
    if (m_isCursorShown && m_isEditable)
    {
        target.draw(m_cursor, states);
    }
}
<|endoftext|>


<commit_before>// UniformMagField
// Author: Matthew Raso-Barnett  22/05/2009
#include "TMath.h"
#include "UniformMagField.h"

using namespace std;

ClassImp(UniformMagField)

//_____________________________________________________________________________
UniformMagField::UniformMagField()
                :MagField()
{
// Default constructor.
   Info("UniformMagField", "Default Constructor");
}

//_____________________________________________________________________________
UniformMagField::UniformMagField(const string& name, const TVector3& field, const TGeoShape* shape, const TGeoMatrix* matrix)
                :MagField(name, shape, matrix),
                 fField(field)
{
// Default constructor.
   Info("UniformMagField", "Constructor");
}

//_____________________________________________________________________________
UniformMagField::UniformMagField(const UniformMagField& other)
                :MagField(other),
                 fField(other.fField)
{
// Copy constructor.
}

//_____________________________________________________________________________
UniformMagField &UniformMagField::operator=(const UniformMagField& other)
{
// Assignment.
   if(this != &other) {
      MagField::operator=(other);
      fField = other.fField;
   }
   return *this;
}

//_____________________________________________________________________________
UniformMagField::~UniformMagField()
{
// Destructor.
   Info("UniformMagField", "Destructor");
}

//______________________________________________________________________________
const TVector3 UniformMagField::GetField(const TVector3& /*position*/) const
{
   // No position dependence for a Uniform field so return field vector
   return fField;
}
<commit_msg>Convert UniformField to global coordinates <commit_after>// UniformMagField
// Author: Matthew Raso-Barnett  22/05/2009
#include <iostream>

#include "TMath.h"
#include "TGeoMatrix.h"
#include "UniformMagField.h"

using namespace std;

ClassImp(UniformMagField)

//_____________________________________________________________________________
UniformMagField::UniformMagField()
                :MagField(),
                 fField()
{
// Default constructor.
   Info("UniformMagField", "Default Constructor");
}

//_____________________________________________________________________________
UniformMagField::UniformMagField(const string& name, const TVector3& field, const TGeoShape* shape, const TGeoMatrix* matrix)
                :MagField(name, shape, matrix),
                 fField()
{
// Default constructor.
   Info("UniformMagField", "Constructor");
   // Convert field vector supplied to global coordinates
   Double_t global[3], local[3] = {field[0],field[1],field[2]};
   matrix->LocalToMaster(local, global);
   // Zero out any rounding errors
   for (int i = 0; i < 3; i++) {global[i] = (TMath::Abs(global[i]) < 1.E-12) ? 0.0 : global[i];}
   fField.SetXYZ(global[0],global[1],global[2]);
   cout << "Built Uniform Magnetic Field - ";
   cout << "Bx: " << fField[0] << "\t By: " << fField[1];
   cout << "\t Bz: " << fField[2] << endl;
}

//_____________________________________________________________________________
UniformMagField::UniformMagField(const UniformMagField& other)
                :MagField(other),
                 fField(other.fField)
{
// Copy constructor.
}

//_____________________________________________________________________________
UniformMagField &UniformMagField::operator=(const UniformMagField& other)
{
// Assignment.
   if(this != &other) {
      MagField::operator=(other);
      fField = other.fField;
   }
   return *this;
}

//_____________________________________________________________________________
UniformMagField::~UniformMagField()
{
// Destructor.
   Info("UniformMagField", "Destructor");
}

//______________________________________________________________________________
const TVector3 UniformMagField::GetField(const TVector3& /*position*/) const
{
   // No position dependence for a Uniform field so return field vector
   return fField;
}
<|endoftext|>


<commit_before>#include <gtest\gtest.h>

#include "vm.h"

using namespace elsa::vm;

class GCTest : public testing::Test {
protected:
	virtual void SetUp()
	{
		int ep = 0;

		vm_.add_constant_entry(new FunctionInfo("main", 0, 1, ep, FunctionType::Static));

		auto si = new StructInfo("my_struct");
		si->add_field(new FieldInfo("field0", OType::GCOPtr));
		//si->add_field(new FieldInfo("field1", OType::GCOPtr));
		//si->add_field(new FieldInfo("field2", OType::GCOPtr));
		vm_.add_constant_entry(si);

		auto si2 = new StructInfo("my_struct2");
		si2->add_field(new FieldInfo("field0", OType::Int));
		vm_.add_constant_entry(si2);

		vm_.set_entry_point(ep);
	}

	virtual void TearDown() {}

	VM vm_;
};

TEST_F(GCTest, MARK)
{
	std::vector<int> p =
	{
		new_struct, 1,
		s_local, 0,

		//l_local, 0,
		//new_struct, 2,
		//s_field, 0,
	};

	vm_.set_program(p);

	vm_.execute();
	auto result = vm_.gc_collect();

	ASSERT_EQ(1, result.num_marked);
}
<commit_msg>the gc now passes some basic mark tests<commit_after>#include <gtest\gtest.h>

#include "vm.h"

using namespace elsa::vm;

class GCTest : public testing::Test {
protected:
	virtual void SetUp()
	{
		auto si = new StructInfo("my_struct");
		si->add_field(new FieldInfo("field0", OType::GCOPtr));
		si->add_field(new FieldInfo("field1", OType::GCOPtr));
		si->add_field(new FieldInfo("field2", OType::GCOPtr));
		vm_.add_constant_entry(si);

		auto si2 = new StructInfo("my_struct2");
		si2->add_field(new FieldInfo("field0", OType::Int));
		vm_.add_constant_entry(si2);
	}

	virtual void TearDown() {}

	VM vm_;
};

TEST_F(GCTest, BASIC_MARK_STRUCTS)
{
	vm_.add_constant_entry(new FunctionInfo("main", 0, 1, 0, FunctionType::Static));
	vm_.set_entry_point(0);

	std::vector<int> p =
	{
		new_struct, 0,
		s_local, 0,

		l_local, 0,
		new_struct, 1,
		s_field, 0,

		l_local, 0,
		new_struct, 0,
		s_field, 1,

		l_local, 0,
		new_struct, 1,
		s_field, 2,

		l_local, 0,
		l_field, 1,
		new_struct, 0,
		s_field, 0
	};

	vm_.set_program(p);

	vm_.execute();
	auto result = vm_.gc_collect();
	ASSERT_EQ(5, result.num_marked);
}

TEST_F(GCTest, BASIC_CALL_MARK_STRUCTS)
{
	vm_.add_constant_entry(new FunctionInfo("main", 0, 1, 11, FunctionType::Static));
	vm_.add_constant_entry(new FunctionInfo("my_func", 0, 1, 0, FunctionType::Static));
	vm_.set_entry_point(11);

	std::vector<int> p =
	{
		new_struct, 0,
		s_local, 0,
		l_local, 0,
		new_struct, 1,
		s_field, 0,
		ret,

		call, 0,
		new_struct, 0,
		s_local, 0,
	};

	vm_.set_program(p);

	vm_.execute();
	auto result = vm_.gc_collect();

	// Since my_func has been popped of the call stack we should only have 1 marked object for gc(the one created in main)
	ASSERT_EQ(1, result.num_marked);
}
<|endoftext|>


<commit_before>#include <algorithm>
#define NOMINMAX // Para que nadie nos redefina min max
#include <sstream>

#include "game_window.h"

#include "../parser_yaml/parser_yaml.h"

using namespace std;

bool GameWindow::sdlInitialized = false;

bool GameWindow::initialize() {
	Logger::getInstance()->writeInformation("Initializing graphics");
	if (GameWindow::sdlInitialized) {
		Logger::getInstance()->writeWarning("SDL already initialized");
	} else {
		atexit(SDL_Quit);
		if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
			Logger::getInstance()->writeError("SDL could not initialize!");
			Logger::getInstance()->writeError(SDL_GetError());
			GameWindow::sdlInitialized = false;
		} else {
			GameWindow::sdlInitialized = true;
		}
	}
	return GameWindow::sdlInitialized;
}

GameWindow::GameWindow(Game& owner, Player& player, ParserYAML& parser) :
	owner(owner), player(player), board(player.board),
	ancho_pantalla(parser.getPantalla().ancho), alto_pantalla(parser.getPantalla().alto),
	margen_pantalla(parser.getPantalla().margen_scroll), scroll_speed(parser.getPantalla().velocidad_scroll)
{
	GameWindow::initialize();
	window = SDL_CreateWindow("Trabajo Práctico 7542",
		SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
		ancho_pantalla, alto_pantalla,
		SDL_WINDOW_SHOWN);

	Logger::getInstance()->writeInformation("Creating renderer");
	renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED );

	SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // Color: negro opaco
	SDL_RenderClear(renderer); // Limpio pantalla inicialmente
	SDL_RenderPresent( renderer );

	addSpriteSheet(ENTIDAD_DEFAULT_NOMBRE, ENTIDAD_DEFAULT_IMAGEN, ENTIDAD_DEFAULT_PIXEL_REF_X, ENTIDAD_DEFAULT_PIXEL_REF_Y, ENTIDAD_DEFAULT_ALTO_SPRITE, ENTIDAD_DEFAULT_ANCHO_SPRITE, ENTIDAD_DEFAULT_CANTIDAD_SPRITES, ENTIDAD_DEFAULT_FPS, ENTIDAD_DEFAULT_DELAY);
	addSpriteSheet(TERRENO_DEFAULT_NOMBRE, TERRENO_DEFAULT_IMAGEN, TERRENO_DEFAULT_PIXEL_REF_X, TERRENO_DEFAULT_PIXEL_REF_Y, TERRENO_DEFAULT_ALTO_SPRITE, TERRENO_DEFAULT_ANCHO_SPRITE, TERRENO_DEFAULT_CANTIDAD_SPRITES, TERRENO_DEFAULT_FPS, TERRENO_DEFAULT_DELAY);
	addSpriteSheet(PROTAGONISTA_DEFAULT_NOMBRE, PROTAGONISTA_DEFAULT_IMAGEN, PROTAGONISTA_DEFAULT_PIXEL_REF_X, PROTAGONISTA_DEFAULT_PIXEL_REF_Y, PROTAGONISTA_DEFAULT_ALTO_SPRITE, PROTAGONISTA_DEFAULT_ANCHO_SPRITE, PROTAGONISTA_DEFAULT_CANTIDAD_SPRITES, PROTAGONISTA_DEFAULT_FPS, PROTAGONISTA_DEFAULT_DELAY);

	auto tp = parser.getPantalla();
	auto tc = parser.getConfiguracion();
	for(auto& t : parser.getTiposEntidades()) {
		addSpriteSheet(t.nombre, t.imagen, t.pixel_ref_x, t.pixel_ref_y, t.alto_sprite, t.ancho_sprite,  t.cantidad_sprites, t.fps, t.delay);
	}

	for(auto& t : parser.getTiposTerrenos()) {
		addSpriteSheet(t.nombre, t.imagen, t.pixel_ref_x, t.pixel_ref_y, t.alto_sprite, t.ancho_sprite,  t.cantidad_sprites, t.fps, t.delay);
	}

	focus();
}

GameWindow::~GameWindow() {
	spriteSheets.clear();

	Logger::getInstance()->writeInformation("Destroying renderer");
	if (renderer) {
		SDL_DestroyRenderer(renderer);
		renderer = nullptr;
	}

	Logger::getInstance()->writeInformation("Destroying window");
	if (window) {
		SDL_DestroyWindow(window);
		window = nullptr;
	} else {
		Logger::getInstance()->writeWarning("Window never initialized");
	}
}

bool GameWindow::canDraw(Entity& entity) {
	if (!(&entity)) {
		return false;
	}
	SDL_Rect screenRect = {0, 0, ancho_pantalla, alto_pantalla};
	auto it = spriteSheets.find(entity.name);
	if (it == spriteSheets.end()) {
		Logger::getInstance()->writeWarning("No existe SpriteSheet para este tipo de entidad" + entity.name);
		return false;
	}
	auto candidate = it->second->targetRect(entity);
	return SDL_HasIntersection(&screenRect, &candidate);
}

void GameWindow::render() {
	//	Dibujar
	SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
	SDL_RenderClear(renderer);
	// Dibujamos el terreno
	r2 margin(1,1),
	   ul = screenToBoardPosition({0, 0}) - margin, // Upper Left
	   ur = screenToBoardPosition({ancho_pantalla, 0}) - margin, // Upper Right
	   bl = screenToBoardPosition({0, alto_pantalla}) + margin, // Bottom Left
	   br = screenToBoardPosition({ancho_pantalla, alto_pantalla}) + margin; // Bottom Right
	double ud = ul.x + ul.y - 2, // Upper diagonal
		   bd = bl.x + bl.y + 2, // Bottom diagonal
		   ld = ul.x - ul.y - 2, // Left diagonal
		   rd = ur.x - ur.y + 2; // Right diagonal
	for (size_t x = max(0.0, ul.x),
			maxx = min(((double)board.sizeX), br.x);
			x < maxx;
			x++) {
		if (x >= board.sizeX) {
			break;
		}
		for (size_t y = max(max(max(0.0, ur.y), ud - x), x - rd),
				maxy = min(min(min(((double)board.sizeY), bl.y), bd - x), x - ld);
				y < maxy;
				y++) {
			if (y >= board.sizeY) {
				break;
			}
			Entity & tile = board.getTerrain(x, y);
			if (&tile) {
				if (canDraw(tile)) {
					spriteSheets[tile.name]->render(tile, renderer);
				}
			}
		}
	}
	// Seleccionamos entidades que se pisan con la pantalla
	auto entities = board.selectEntities([this](shared_ptr<Entity> e) {
			return canDraw(*e);});
	// Ordenamos las entidades por oclusión
	sort(entities.begin(), entities.end(), [](shared_ptr<Entity> a, shared_ptr<Entity> b) {
		return (a->size.x == a->size.y && b->size.x == b->size.y) ?
			(a->getPosition().x + a->getPosition().y + a->size.x < b->getPosition().x + b->getPosition().y + b->size.x) :
			((a->getPosition().x + a->size.x < b->getPosition().x) || (a->getPosition().y + a->size.y < b->getPosition().y)) &&
			!((b->getPosition().x + b->size.x <= a->getPosition().x) || (b->getPosition().y + b->size.y <= a->getPosition().y));
	});
	for(auto& e : entities) {
		auto it = spriteSheets.find(e->name);
		if(it == spriteSheets.end()){
			Logger::getInstance()->writeWarning("No existe SpriteSheet para este tipo de entidad" + e->name);
			continue;
		}
		it->second->render(*e, renderer);
	}

	SDL_RenderPresent( renderer );
	return;
}

void GameWindow::update(){
	for(auto & kv : spriteSheets) {
		kv.second->update();
	}
	processInput();
	render();
	return;
}

void GameWindow::addSpriteSheet(string name, string pPath, int pixelRefX, int pixelRefY, int altoSprite, int anchoSprite, int cantSprites, double fps, double delay) {
	auto it = spriteSheets.find(name);
	if(it != spriteSheets.end())
		Logger::getInstance()->writeError("Ya existe un spriteSheet para el tipo de entidad con nombre " + name);
	else{
		spriteSheets[name] = make_shared<SpriteSheet>(pPath, pixelRefX, pixelRefY, altoSprite, anchoSprite, cantSprites, fps, delay, *this);
		Logger::getInstance()->writeInformation("Se agrega spriteSheet para el tipo de entidad con nombre " + name);
	}
}

r2 GameWindow::screenToBoardPosition(SDL_Point screenPos) {
	double XsTerm = (double)((double)screenPos.x - ancho_pantalla/2)/(double)TILE_WIDTH_DEFAULT;
	double YsTerm = (double)((double)screenPos.y - alto_pantalla/2)/(double)TILE_HEIGHT_DEFAULT;
	return focusPosition + r2(XsTerm + YsTerm + .5, -XsTerm + YsTerm + .5);
}

SDL_Point GameWindow::boardToScreenPosition(r2 boardPos) {
	boardPos -= focusPosition;
	SDL_Point ret = {
		(int)((boardPos.x - boardPos.y) * TILE_WIDTH_DEFAULT / 2) + (ancho_pantalla) / 2,
		(int)((boardPos.x + boardPos.y) * TILE_HEIGHT_DEFAULT / 2) + (alto_pantalla - TILE_HEIGHT_DEFAULT) / 2};
	return ret;
}

void GameWindow::processInput(){
	SDL_GetMouseState(&mouse.x, &mouse.y);
	scroll();
	//	Procesar input del usuario
	while(SDL_PollEvent(EventHandler::getInstance()->getEvent())) {
		auto & e = *(EventHandler::getInstance()->getEvent());
		switch(e.type) {
			case SDL_QUIT:
				owner.exit();
				break;
			case SDL_KEYDOWN:
				Logger::getInstance()->writeInformation("Teclado");
				switch(e.key.keysym.sym) {
					case SDLK_r:
						owner.restart();
						break;
					case SDLK_SPACE:
						focus();
						break;
				}
			case SDL_MOUSEBUTTONUP:
				ostringstream oss;
				oss << "Mouse en " << mouse.x << "," << mouse.y;

				// Conversion de coordenadas en pantalla a coordenadas mapa

				auto mouseBoard = screenToBoardPosition(mouse);
				oss << "; mapa: " << mouseBoard.x << "," << mouseBoard.y;

				Logger::getInstance()->writeInformation(oss.str().c_str());
				if( EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_LEFT ) {
					Logger::getInstance()->writeInformation("Boton Izquierdo");
					auto protagonist = getSelection();
					if (protagonist) {
						if (!(SDL_GetModState()&KMOD_SHIFT)) {
							protagonist->unsetTarget();
						}
						protagonist->addTarget(mouseBoard);
					}
				}
				if( EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_RIGHT) {
					Logger::getInstance()->writeInformation("Boton derecho");
				}
				break;
		}
	}
}

void GameWindow::scroll(){
	double ds = (double)scroll_speed * (double)(board.dt) / 1000.0; //deltascroll
	r2 df;

	if(mouse.x <= margen_pantalla) {
		auto dsi = interpolate(mouse.x, 0, margen_pantalla, ds, 0);
		df += {-dsi, dsi};
		Logger::getInstance()->writeInformation("Scrolleando hacia la izquierda");
	}
	if(mouse.x >= ancho_pantalla - margen_pantalla){
		auto dsi = interpolate(mouse.x, ancho_pantalla - margen_pantalla, ancho_pantalla, 0, ds);
		df += {dsi, -dsi};
		Logger::getInstance()->writeInformation("Scrolleando hacia la derecha");
	}
	if(mouse.y <= margen_pantalla) {
		auto dsi = interpolate(mouse.y, 0, margen_pantalla, ds, 0);
		df += {-dsi, -dsi};
		Logger::getInstance()->writeInformation("Scrolleando hacia arriba");
	}
	if(mouse.y >= alto_pantalla - margen_pantalla) {
		auto dsi = interpolate(mouse.y, alto_pantalla - margen_pantalla, alto_pantalla, 0, ds);
		df += {dsi, dsi};
		Logger::getInstance()->writeInformation("Scrolleando hacia abajo");
	}
	focus(focusPosition + df);
}

void GameWindow::focus(r2 newFocus) {
	focusPosition.x = clip(newFocus.x, 0, board.sizeX - 1);
	focusPosition.y = clip(newFocus.y, 0, board.sizeY - 1);
}

void GameWindow::focus() {
	auto protagonist = getSelection();
	if (protagonist) {
		focus(protagonist->getPosition());
	}
}

r2 GameWindow::getFocus() {
	return focusPosition;
}

shared_ptr<Entity> GameWindow::getSelection() {
	return player.entities().front();
}

<commit_msg>Faltaba un break al final de SDL_KEYDOWN<commit_after>#include <algorithm>
#define NOMINMAX // Para que nadie nos redefina min max
#include <sstream>

#include "game_window.h"

#include "../parser_yaml/parser_yaml.h"

using namespace std;

bool GameWindow::sdlInitialized = false;

bool GameWindow::initialize() {
	Logger::getInstance()->writeInformation("Initializing graphics");
	if (GameWindow::sdlInitialized) {
		Logger::getInstance()->writeWarning("SDL already initialized");
	} else {
		atexit(SDL_Quit);
		if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
			Logger::getInstance()->writeError("SDL could not initialize!");
			Logger::getInstance()->writeError(SDL_GetError());
			GameWindow::sdlInitialized = false;
		} else {
			GameWindow::sdlInitialized = true;
		}
	}
	return GameWindow::sdlInitialized;
}

GameWindow::GameWindow(Game& owner, Player& player, ParserYAML& parser) :
	owner(owner), player(player), board(player.board),
	ancho_pantalla(parser.getPantalla().ancho), alto_pantalla(parser.getPantalla().alto),
	margen_pantalla(parser.getPantalla().margen_scroll), scroll_speed(parser.getPantalla().velocidad_scroll)
{
	GameWindow::initialize();
	window = SDL_CreateWindow("Trabajo Práctico 7542",
		SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
		ancho_pantalla, alto_pantalla,
		SDL_WINDOW_SHOWN);

	Logger::getInstance()->writeInformation("Creating renderer");
	renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED );

	SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // Color: negro opaco
	SDL_RenderClear(renderer); // Limpio pantalla inicialmente
	SDL_RenderPresent( renderer );

	addSpriteSheet(ENTIDAD_DEFAULT_NOMBRE, ENTIDAD_DEFAULT_IMAGEN, ENTIDAD_DEFAULT_PIXEL_REF_X, ENTIDAD_DEFAULT_PIXEL_REF_Y, ENTIDAD_DEFAULT_ALTO_SPRITE, ENTIDAD_DEFAULT_ANCHO_SPRITE, ENTIDAD_DEFAULT_CANTIDAD_SPRITES, ENTIDAD_DEFAULT_FPS, ENTIDAD_DEFAULT_DELAY);
	addSpriteSheet(TERRENO_DEFAULT_NOMBRE, TERRENO_DEFAULT_IMAGEN, TERRENO_DEFAULT_PIXEL_REF_X, TERRENO_DEFAULT_PIXEL_REF_Y, TERRENO_DEFAULT_ALTO_SPRITE, TERRENO_DEFAULT_ANCHO_SPRITE, TERRENO_DEFAULT_CANTIDAD_SPRITES, TERRENO_DEFAULT_FPS, TERRENO_DEFAULT_DELAY);
	addSpriteSheet(PROTAGONISTA_DEFAULT_NOMBRE, PROTAGONISTA_DEFAULT_IMAGEN, PROTAGONISTA_DEFAULT_PIXEL_REF_X, PROTAGONISTA_DEFAULT_PIXEL_REF_Y, PROTAGONISTA_DEFAULT_ALTO_SPRITE, PROTAGONISTA_DEFAULT_ANCHO_SPRITE, PROTAGONISTA_DEFAULT_CANTIDAD_SPRITES, PROTAGONISTA_DEFAULT_FPS, PROTAGONISTA_DEFAULT_DELAY);

	auto tp = parser.getPantalla();
	auto tc = parser.getConfiguracion();
	for(auto& t : parser.getTiposEntidades()) {
		addSpriteSheet(t.nombre, t.imagen, t.pixel_ref_x, t.pixel_ref_y, t.alto_sprite, t.ancho_sprite,  t.cantidad_sprites, t.fps, t.delay);
	}

	for(auto& t : parser.getTiposTerrenos()) {
		addSpriteSheet(t.nombre, t.imagen, t.pixel_ref_x, t.pixel_ref_y, t.alto_sprite, t.ancho_sprite,  t.cantidad_sprites, t.fps, t.delay);
	}

	focus();
}

GameWindow::~GameWindow() {
	spriteSheets.clear();

	Logger::getInstance()->writeInformation("Destroying renderer");
	if (renderer) {
		SDL_DestroyRenderer(renderer);
		renderer = nullptr;
	}

	Logger::getInstance()->writeInformation("Destroying window");
	if (window) {
		SDL_DestroyWindow(window);
		window = nullptr;
	} else {
		Logger::getInstance()->writeWarning("Window never initialized");
	}
}

bool GameWindow::canDraw(Entity& entity) {
	if (!(&entity)) {
		return false;
	}
	SDL_Rect screenRect = {0, 0, ancho_pantalla, alto_pantalla};
	auto it = spriteSheets.find(entity.name);
	if (it == spriteSheets.end()) {
		Logger::getInstance()->writeWarning("No existe SpriteSheet para este tipo de entidad" + entity.name);
		return false;
	}
	auto candidate = it->second->targetRect(entity);
	return SDL_HasIntersection(&screenRect, &candidate);
}

void GameWindow::render() {
	//	Dibujar
	SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
	SDL_RenderClear(renderer);
	// Dibujamos el terreno
	r2 margin(1,1),
	   ul = screenToBoardPosition({0, 0}) - margin, // Upper Left
	   ur = screenToBoardPosition({ancho_pantalla, 0}) - margin, // Upper Right
	   bl = screenToBoardPosition({0, alto_pantalla}) + margin, // Bottom Left
	   br = screenToBoardPosition({ancho_pantalla, alto_pantalla}) + margin; // Bottom Right
	double ud = ul.x + ul.y - 2, // Upper diagonal
		   bd = bl.x + bl.y + 2, // Bottom diagonal
		   ld = ul.x - ul.y - 2, // Left diagonal
		   rd = ur.x - ur.y + 2; // Right diagonal
	for (size_t x = max(0.0, ul.x),
			maxx = min(((double)board.sizeX), br.x);
			x < maxx;
			x++) {
		if (x >= board.sizeX) {
			break;
		}
		for (size_t y = max(max(max(0.0, ur.y), ud - x), x - rd),
				maxy = min(min(min(((double)board.sizeY), bl.y), bd - x), x - ld);
				y < maxy;
				y++) {
			if (y >= board.sizeY) {
				break;
			}
			Entity & tile = board.getTerrain(x, y);
			if (&tile) {
				if (canDraw(tile)) {
					spriteSheets[tile.name]->render(tile, renderer);
				}
			}
		}
	}
	// Seleccionamos entidades que se pisan con la pantalla
	auto entities = board.selectEntities([this](shared_ptr<Entity> e) {
			return canDraw(*e);});
	// Ordenamos las entidades por oclusión
	sort(entities.begin(), entities.end(), [](shared_ptr<Entity> a, shared_ptr<Entity> b) {
		return (a->size.x == a->size.y && b->size.x == b->size.y) ?
			(a->getPosition().x + a->getPosition().y + a->size.x < b->getPosition().x + b->getPosition().y + b->size.x) :
			((a->getPosition().x + a->size.x < b->getPosition().x) || (a->getPosition().y + a->size.y < b->getPosition().y)) &&
			!((b->getPosition().x + b->size.x <= a->getPosition().x) || (b->getPosition().y + b->size.y <= a->getPosition().y));
	});
	for(auto& e : entities) {
		auto it = spriteSheets.find(e->name);
		if(it == spriteSheets.end()){
			Logger::getInstance()->writeWarning("No existe SpriteSheet para este tipo de entidad" + e->name);
			continue;
		}
		it->second->render(*e, renderer);
	}

	SDL_RenderPresent( renderer );
	return;
}

void GameWindow::update(){
	for(auto & kv : spriteSheets) {
		kv.second->update();
	}
	processInput();
	render();
	return;
}

void GameWindow::addSpriteSheet(string name, string pPath, int pixelRefX, int pixelRefY, int altoSprite, int anchoSprite, int cantSprites, double fps, double delay) {
	auto it = spriteSheets.find(name);
	if(it != spriteSheets.end())
		Logger::getInstance()->writeError("Ya existe un spriteSheet para el tipo de entidad con nombre " + name);
	else{
		spriteSheets[name] = make_shared<SpriteSheet>(pPath, pixelRefX, pixelRefY, altoSprite, anchoSprite, cantSprites, fps, delay, *this);
		Logger::getInstance()->writeInformation("Se agrega spriteSheet para el tipo de entidad con nombre " + name);
	}
}

r2 GameWindow::screenToBoardPosition(SDL_Point screenPos) {
	double XsTerm = (double)((double)screenPos.x - ancho_pantalla/2)/(double)TILE_WIDTH_DEFAULT;
	double YsTerm = (double)((double)screenPos.y - alto_pantalla/2)/(double)TILE_HEIGHT_DEFAULT;
	return focusPosition + r2(XsTerm + YsTerm + .5, -XsTerm + YsTerm + .5);
}

SDL_Point GameWindow::boardToScreenPosition(r2 boardPos) {
	boardPos -= focusPosition;
	SDL_Point ret = {
		(int)((boardPos.x - boardPos.y) * TILE_WIDTH_DEFAULT / 2) + (ancho_pantalla) / 2,
		(int)((boardPos.x + boardPos.y) * TILE_HEIGHT_DEFAULT / 2) + (alto_pantalla - TILE_HEIGHT_DEFAULT) / 2};
	return ret;
}

void GameWindow::processInput(){
	SDL_GetMouseState(&mouse.x, &mouse.y);
	scroll();
	//	Procesar input del usuario
	while(SDL_PollEvent(EventHandler::getInstance()->getEvent())) {
		auto & e = *(EventHandler::getInstance()->getEvent());
		switch(e.type) {
			case SDL_QUIT:
				owner.exit();
				break;
			case SDL_KEYDOWN:
				Logger::getInstance()->writeInformation("Teclado");
				switch(e.key.keysym.sym) {
					case SDLK_r:
						owner.restart();
						break;
					case SDLK_SPACE:
						focus();
						break;
				}
				break;
			case SDL_MOUSEBUTTONUP:
				ostringstream oss;
				oss << "Mouse en " << mouse.x << "," << mouse.y;

				// Conversion de coordenadas en pantalla a coordenadas mapa

				auto mouseBoard = screenToBoardPosition(mouse);
				oss << "; mapa: " << mouseBoard.x << "," << mouseBoard.y;

				Logger::getInstance()->writeInformation(oss.str().c_str());
				if( EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_LEFT ) {
					Logger::getInstance()->writeInformation("Boton Izquierdo");
					auto protagonist = getSelection();
					if (protagonist) {
						if (!(SDL_GetModState()&KMOD_SHIFT)) {
							protagonist->unsetTarget();
						}
						protagonist->addTarget(mouseBoard);
					}
				}
				if( EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_RIGHT) {
					Logger::getInstance()->writeInformation("Boton derecho");
				}
				break;
		}
	}
}

void GameWindow::scroll(){
	double ds = (double)scroll_speed * (double)(board.dt) / 1000.0; //deltascroll
	r2 df;

	if(mouse.x <= margen_pantalla) {
		auto dsi = interpolate(mouse.x, 0, margen_pantalla, ds, 0);
		df += {-dsi, dsi};
		Logger::getInstance()->writeInformation("Scrolleando hacia la izquierda");
	}
	if(mouse.x >= ancho_pantalla - margen_pantalla){
		auto dsi = interpolate(mouse.x, ancho_pantalla - margen_pantalla, ancho_pantalla, 0, ds);
		df += {dsi, -dsi};
		Logger::getInstance()->writeInformation("Scrolleando hacia la derecha");
	}
	if(mouse.y <= margen_pantalla) {
		auto dsi = interpolate(mouse.y, 0, margen_pantalla, ds, 0);
		df += {-dsi, -dsi};
		Logger::getInstance()->writeInformation("Scrolleando hacia arriba");
	}
	if(mouse.y >= alto_pantalla - margen_pantalla) {
		auto dsi = interpolate(mouse.y, alto_pantalla - margen_pantalla, alto_pantalla, 0, ds);
		df += {dsi, dsi};
		Logger::getInstance()->writeInformation("Scrolleando hacia abajo");
	}
	focus(focusPosition + df);
}

void GameWindow::focus(r2 newFocus) {
	focusPosition.x = clip(newFocus.x, 0, board.sizeX - 1);
	focusPosition.y = clip(newFocus.y, 0, board.sizeY - 1);
}

void GameWindow::focus() {
	auto protagonist = getSelection();
	if (protagonist) {
		focus(protagonist->getPosition());
	}
}

r2 GameWindow::getFocus() {
	return focusPosition;
}

shared_ptr<Entity> GameWindow::getSelection() {
	return player.entities().front();
}

<|endoftext|>