clooneljump/src/sizenotifiable.hpp
King_DuckZ b4ddfa8f4f Fix for a crash occurring when the window is resized.
Temporary Platform objects were registering themselves.
The move ctor would then initialize the final object in
the circular buffer (see PlatformSystem), but it would
leave the address of the temporary object registered in
the ObserversManager.
2014-07-06 02:21:25 +02:00

128 lines
3.6 KiB
C++

/*
Copyright 2014 Michele "King_DuckZ" Santullo
This file is part of CloonelJump.
CloonelJump is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
CloonelJump 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with CloonelJump. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef id78906DE4FB0D43219CD3F0D9C620FC06
#define id78906DE4FB0D43219CD3F0D9C620FC06
#include "vector.hpp"
#include <cstddef>
#include <algorithm>
namespace cloonel {
class SizeRatio;
class SDLMain;
class SizeNotifiableBase;
namespace regbehaviours {
class DontRegister {
public:
enum { SDLMAIN_NEEDED = false };
DontRegister ( void ) = default;
DontRegister ( DontRegister&&, SizeNotifiableBase* ) { }
~DontRegister ( void ) noexcept = default;
void Register ( SizeNotifiableBase* ) const noexcept { return; }
void Unregister ( void ) const noexcept { return; }
};
class AutoRegister {
public:
enum { SDLMAIN_NEEDED = true };
AutoRegister ( AutoRegister&& parOther, SizeNotifiableBase* parSwapTo );
explicit AutoRegister ( SDLMain* parMain ) :
m_sdlmain(parMain)
#if !defined(NDEBUG)
, m_registered(false)
#endif
{
}
~AutoRegister ( void ) noexcept = default;
void Register ( SizeNotifiableBase* parNotifiable );
void Unregister ( void ) noexcept;
private:
SDLMain* m_sdlmain;
size_t m_id;
#if !defined(NDEBUG)
bool m_registered;
#endif
};
} //namespace regbehaviours
class SizeNotifiableBase {
protected:
SizeNotifiableBase ( void ) = default;
SizeNotifiableBase ( const SizeNotifiableBase& ) = default;
virtual ~SizeNotifiableBase ( void ) noexcept = default;
SizeNotifiableBase& operator= ( const SizeNotifiableBase& ) = delete;
public:
virtual void NotifyResChanged ( const SizeRatio& parSize );
const float2& Ratio ( void ) const noexcept { return m_scaleRatio; }
private:
float2 m_scaleRatio;
};
template <class RegisterBehaviour, bool=RegisterBehaviour::SDLMAIN_NEEDED>
class SizeNotifiable;
template <class RegisterBehaviour>
class SizeNotifiable<RegisterBehaviour, false> : private RegisterBehaviour, public SizeNotifiableBase {
static_assert(RegisterBehaviour::SDLMAIN_NEEDED == false, "SdlMainNeeded mismatches expected value");
public:
SizeNotifiable ( const SizeNotifiable& ) = delete;
SizeNotifiable ( SizeNotifiable&& parOther ) :
RegisterBehaviour(std::move(parOther), this),
SizeNotifiableBase(parOther)
{
}
SizeNotifiable ( void ) {
this->Register(this);
}
virtual ~SizeNotifiable ( void ) noexcept {
this->Unregister();
}
};
template <class RegisterBehaviour>
class SizeNotifiable<RegisterBehaviour, true> : private RegisterBehaviour, public SizeNotifiableBase {
static_assert(RegisterBehaviour::SDLMAIN_NEEDED == true, "SdlMainNeeded mismatches expected value");
public:
SizeNotifiable ( const SizeNotifiable& ) = delete;
SizeNotifiable ( SizeNotifiable&& parOther ) :
RegisterBehaviour(std::move(parOther), this),
SizeNotifiableBase(parOther)
{
}
explicit SizeNotifiable ( SDLMain* parSdlMain ) :
RegisterBehaviour(parSdlMain)
{
this->Register(this);
}
virtual ~SizeNotifiable ( void ) noexcept {
this->Unregister();
}
};
} //namespace cloonel
#endif