Utility/Cursor: Rework Cursor as a handled object

This commit is contained in:
Lynix 2017-01-19 21:38:56 +01:00
parent c4574ed7ec
commit 670199b557
8 changed files with 92 additions and 50 deletions

View File

@ -8,28 +8,34 @@
#define NAZARA_CURSOR_HPP #define NAZARA_CURSOR_HPP
#include <Nazara/Prerequesites.hpp> #include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/ObjectRef.hpp>
#include <Nazara/Math/Vector2.hpp> #include <Nazara/Math/Vector2.hpp>
#include <Nazara/Utility/Config.hpp> #include <Nazara/Utility/Config.hpp>
#include <Nazara/Utility/Image.hpp> #include <Nazara/Utility/Image.hpp>
#include <array>
namespace Nz namespace Nz
{ {
class CursorImpl; class CursorImpl;
class NAZARA_UTILITY_API Cursor class Cursor;
using CursorConstRef = ObjectRef<const Cursor>;
using CursorRef = ObjectRef<Cursor>;
class NAZARA_UTILITY_API Cursor : public RefCounted
{ {
friend class Utility; friend class Utility;
friend class WindowImpl; friend class WindowImpl;
public: public:
inline Cursor(); inline Cursor();
inline Cursor(SystemCursor systemCursor); //< implicit conversion intended inline Cursor(const Image& cursor, const Vector2i& hotSpot, SystemCursor placeholder);
Cursor(const Cursor&) = delete; Cursor(const Cursor&) = delete;
inline Cursor(Cursor&& cursor) noexcept; Cursor(Cursor&&) = delete;
inline ~Cursor(); inline ~Cursor();
bool Create(const Image& cursor, const Vector2i& hotSpot); bool Create(const Image& cursor, const Vector2i& hotSpot, SystemCursor placeholder);
bool Create(SystemCursor cursor);
void Destroy(); void Destroy();
@ -39,16 +45,24 @@ namespace Nz
inline bool IsValid() const; inline bool IsValid() const;
Cursor& operator=(const Cursor&) = delete; Cursor& operator=(const Cursor&) = delete;
inline Cursor& operator=(Cursor&& cursor); Cursor& operator=(Cursor&&) = delete;
static inline Cursor* Get(SystemCursor cursor);
template<typename... Args> static CursorRef New(Args&&... args);
private: private:
inline explicit Cursor(SystemCursor systemCursor);
bool Create(SystemCursor cursor);
static bool Initialize(); static bool Initialize();
static void Uninitialize(); static void Uninitialize();
Image m_cursorImage; Image m_cursorImage;
SystemCursor m_systemCursor; SystemCursor m_systemCursor;
CursorImpl* m_impl; CursorImpl* m_impl;
bool m_usesSystemCursor;
static std::array<Cursor, SystemCursor_Max + 1> s_systemCursors;
}; };
} }

View File

@ -9,11 +9,21 @@
namespace Nz namespace Nz
{ {
inline Cursor::Cursor() : inline Cursor::Cursor() :
m_impl(nullptr), m_impl(nullptr)
m_usesSystemCursor(false)
{ {
} }
inline Cursor::Cursor(const Image& cursor, const Vector2i& hotSpot, SystemCursor placeholder)
{
ErrorFlags flags(ErrorFlag_ThrowException, true);
Create(cursor, hotSpot, placeholder);
}
inline Cursor* Cursor::Get(SystemCursor cursor)
{
return &s_systemCursors[cursor];
}
inline Cursor::Cursor(SystemCursor systemCursor) : inline Cursor::Cursor(SystemCursor systemCursor) :
Cursor() Cursor()
{ {
@ -21,12 +31,6 @@ namespace Nz
Create(systemCursor); Create(systemCursor);
} }
inline Cursor::Cursor(Cursor&& cursor) noexcept :
Cursor()
{
operator=(std::move(cursor));
}
inline Cursor::~Cursor() inline Cursor::~Cursor()
{ {
Destroy(); Destroy();
@ -35,7 +39,7 @@ namespace Nz
inline const Image& Cursor::GetImage() const inline const Image& Cursor::GetImage() const
{ {
NazaraAssert(IsValid(), "Invalid cursor"); NazaraAssert(IsValid(), "Invalid cursor");
NazaraAssert(!m_usesSystemCursor, "System cursors have no image"); NazaraAssert(m_cursorImage.IsValid(), "System cursors have no image");
return m_cursorImage; return m_cursorImage;
} }
@ -43,7 +47,6 @@ namespace Nz
inline SystemCursor Cursor::GetSystemCursor() const inline SystemCursor Cursor::GetSystemCursor() const
{ {
NazaraAssert(IsValid(), "Invalid cursor"); NazaraAssert(IsValid(), "Invalid cursor");
NazaraAssert(m_usesSystemCursor, "Custom cursor uses an image");
return m_systemCursor; return m_systemCursor;
} }
@ -53,16 +56,13 @@ namespace Nz
return m_impl != nullptr; return m_impl != nullptr;
} }
inline Cursor& Cursor::operator=(Cursor&& cursor) template<typename... Args>
CursorRef Cursor::New(Args&&... args)
{ {
m_cursorImage = std::move(cursor.m_cursorImage); std::unique_ptr<Cursor> object(new Cursor(std::forward<Args>(args)...));
m_systemCursor = cursor.m_systemCursor; object->SetPersistent(false);
m_impl = cursor.m_impl;
m_usesSystemCursor = cursor.m_usesSystemCursor;
cursor.m_impl = nullptr; return object.release();
return *this;
} }
} }

View File

@ -28,12 +28,12 @@ namespace Nz
CursorController(CursorController&&) = default; CursorController(CursorController&&) = default;
~CursorController() = default; ~CursorController() = default;
inline void UpdateCursor(const Cursor& cursor); inline void UpdateCursor(const CursorRef& cursor);
CursorController& operator=(const CursorController&) = delete; CursorController& operator=(const CursorController&) = delete;
CursorController& operator=(CursorController&&) = default; CursorController& operator=(CursorController&&) = default;
NazaraSignal(OnCursorUpdated, const CursorController* /*cursorController*/, const Cursor& /*cursor*/); NazaraSignal(OnCursorUpdated, const CursorController* /*cursorController*/, const CursorRef& /*cursor*/);
}; };
} }

View File

@ -7,7 +7,7 @@
namespace Nz namespace Nz
{ {
inline void CursorController::UpdateCursor(const Cursor& cursor) inline void CursorController::UpdateCursor(const CursorRef& cursor)
{ {
OnCursorUpdated(this, cursor); OnCursorUpdated(this, cursor);
} }

View File

@ -58,6 +58,7 @@ namespace Nz
void EnableKeyRepeat(bool enable); void EnableKeyRepeat(bool enable);
void EnableSmoothScrolling(bool enable); void EnableSmoothScrolling(bool enable);
inline const CursorRef& GetCursor() const;
inline CursorController& GetCursorController(); inline CursorController& GetCursorController();
inline EventHandler& GetEventHandler(); inline EventHandler& GetEventHandler();
WindowHandle GetHandle() const; WindowHandle GetHandle() const;
@ -81,7 +82,8 @@ namespace Nz
void ProcessEvents(bool block = false); void ProcessEvents(bool block = false);
void SetCursor(const Cursor& cursor); void SetCursor(CursorRef cursor);
inline void SetCursor(SystemCursor systemCursor);
void SetEventListener(bool listener); void SetEventListener(bool listener);
void SetFocus(); void SetFocus();
void SetIcon(const Icon& icon); void SetIcon(const Icon& icon);
@ -122,6 +124,7 @@ namespace Nz
std::vector<WindowEvent> m_pendingEvents; std::vector<WindowEvent> m_pendingEvents;
ConditionVariable m_eventCondition; ConditionVariable m_eventCondition;
CursorController m_cursorController; CursorController m_cursorController;
CursorRef m_cursor;
EventHandler m_eventHandler; EventHandler m_eventHandler;
Mutex m_eventMutex; Mutex m_eventMutex;
Mutex m_eventConditionMutex; Mutex m_eventConditionMutex;

View File

@ -67,6 +67,11 @@ namespace Nz
} }
} }
inline const CursorRef& Window::GetCursor() const
{
return m_cursor;
}
inline CursorController& Nz::Window::GetCursorController() inline CursorController& Nz::Window::GetCursorController()
{ {
return m_cursorController; return m_cursorController;
@ -101,6 +106,11 @@ namespace Nz
return m_impl != nullptr; return m_impl != nullptr;
} }
inline void Window::SetCursor(SystemCursor systemCursor)
{
SetCursor(Cursor::Get(systemCursor));
}
inline void Window::HandleEvent(const WindowEvent& event) inline void Window::HandleEvent(const WindowEvent& event)
{ {
if (m_eventPolling) if (m_eventPolling)

View File

@ -16,7 +16,7 @@
namespace Nz namespace Nz
{ {
bool Cursor::Create(const Image& cursor, const Vector2i& hotSpot) bool Cursor::Create(const Image& cursor, const Vector2i& hotSpot, SystemCursor placeholder)
{ {
Destroy(); Destroy();
@ -29,10 +29,24 @@ namespace Nz
m_cursorImage = cursor; m_cursorImage = cursor;
m_impl = impl.release(); m_impl = impl.release();
m_systemCursor = placeholder;
return true; return true;
} }
void Cursor::Destroy()
{
m_cursorImage.Destroy();
if (m_impl)
{
m_impl->Destroy();
delete m_impl;
m_impl = nullptr;
}
}
bool Cursor::Create(SystemCursor cursor) bool Cursor::Create(SystemCursor cursor)
{ {
Destroy(); Destroy();
@ -46,31 +60,28 @@ namespace Nz
m_impl = impl.release(); m_impl = impl.release();
m_systemCursor = cursor; m_systemCursor = cursor;
m_usesSystemCursor = true;
return true; return true;
} }
void Cursor::Destroy()
{
if (m_impl)
{
m_impl->Destroy();
delete m_impl;
m_impl = nullptr;
}
m_usesSystemCursor = false;
}
bool Cursor::Initialize() bool Cursor::Initialize()
{ {
return CursorImpl::Initialize(); if (!CursorImpl::Initialize())
return false;
for (std::size_t i = 0; i <= SystemCursor_Max; ++i)
s_systemCursors[i].Create(static_cast<SystemCursor>(i));
return true;
} }
void Cursor::Uninitialize() void Cursor::Uninitialize()
{ {
for (Cursor& cursor : s_systemCursors)
cursor.Destroy();
CursorImpl::Uninitialize(); CursorImpl::Uninitialize();
} }
std::array<Cursor, SystemCursor_Max + 1> Cursor::s_systemCursors;
} }

View File

@ -36,7 +36,7 @@ namespace Nz
m_eventPolling(false), m_eventPolling(false),
m_waitForEvent(false) m_waitForEvent(false)
{ {
m_cursorController.OnCursorUpdated.Connect([this](const CursorController*, const Cursor& cursor) m_cursorController.OnCursorUpdated.Connect([this](const CursorController*, const CursorRef& cursor)
{ {
if (IsValid()) if (IsValid())
SetCursor(cursor); SetCursor(cursor);
@ -104,11 +104,12 @@ namespace Nz
// Paramètres par défaut // Paramètres par défaut
m_impl->EnableKeyRepeat(true); m_impl->EnableKeyRepeat(true);
m_impl->EnableSmoothScrolling(false); m_impl->EnableSmoothScrolling(false);
m_impl->SetCursor(SystemCursor_Default);
m_impl->SetMaximumSize(-1, -1); m_impl->SetMaximumSize(-1, -1);
m_impl->SetMinimumSize(-1, -1); m_impl->SetMinimumSize(-1, -1);
m_impl->SetVisible(true); m_impl->SetVisible(true);
SetCursor(Cursor::Get(SystemCursor_Default));
if (opened) if (opened)
m_impl->SetPosition(position.x, position.y); m_impl->SetPosition(position.x, position.y);
@ -151,6 +152,8 @@ namespace Nz
void Window::Destroy() void Window::Destroy()
{ {
m_cursor.Reset();
if (m_impl) if (m_impl)
{ {
OnWindowDestroy(); OnWindowDestroy();
@ -364,12 +367,13 @@ namespace Nz
} }
} }
void Window::SetCursor(const Cursor& cursor) void Window::SetCursor(CursorRef cursor)
{ {
NazaraAssert(m_impl, "Window not created"); NazaraAssert(m_impl, "Window not created");
NazaraAssert(cursor.IsValid(), "Invalid cursor"); NazaraAssert(cursor && cursor->IsValid(), "Invalid cursor");
m_impl->SetCursor(cursor); m_cursor = std::move(cursor);
m_impl->SetCursor(*m_cursor);
} }
void Window::SetEventListener(bool listener) void Window::SetEventListener(bool listener)