Browse Source

Platform: check and return a reference from Screen::application().

Giving out a pointer implied excessive error checking in user code.
There's a new hasApplication() accessor that can be used to check for
application presence, moreover the ScreenedApplication is now
convertible to a pointer to provide backward compatiblity. This
conversion is marked as deprecated and will be removed in a future
release.
pull/364/head
Vladimír Vondruš 7 years ago
parent
commit
31f5ca4546
  1. 13
      doc/changelog.dox
  2. 39
      src/Magnum/Platform/Screen.h
  3. 12
      src/Magnum/Platform/ScreenedApplication.h
  4. 24
      src/Magnum/Platform/ScreenedApplication.hpp

13
doc/changelog.dox

@ -387,6 +387,11 @@ See also:
in a RAII manner, without needing to explicitly call in a RAII manner, without needing to explicitly call
@ref Platform::BasicScreenedApplication::addScreen() and @ref Platform::BasicScreenedApplication::addScreen() and
@ref Platform::BasicScreen::setPropagatedEvents() later @ref Platform::BasicScreen::setPropagatedEvents() later
- @ref Platform::BasicScreen::application() now returns a reference instead
of a pointer, checking that the screen is actually added to the
application. Users are encouraged to call
@ref Platform::BasicScreen::hasApplication() to check if the application is
accessible.
@subsubsection changelog-latest-changes-text Text library @subsubsection changelog-latest-changes-text Text library
@ -575,6 +580,14 @@ See also:
- Passing @cpp nullptr @ce to @ref ImageView constructors is deprecated and - Passing @cpp nullptr @ce to @ref ImageView constructors is deprecated and
will print a warning at runtime. Use a constructor without the @p data will print a warning at runtime. Use a constructor without the @p data
parameter instead. parameter instead.
- @ref Platform::BasicScreen::application() now returns a reference instead
of a pointer and together with @ref Platform::BasicScreen::redraw() checks
that the screen is actually added to the application instead of returning
@cpp nullptr @ce (and requiring excessive error checking in user code) or,
in case of @ref Platform::BasicScreen::redraw() "redraw()" silently doing
the wrong thing. For backwards compatibility
@ref Platform::BasicScreenedApplication is convertible to a pointer and
implements @cpp operator-> @ce, but this conversion is deprecated.
@subsection changelog-latest-compatibility Potential compatibility breakages, removed APIs @subsection changelog-latest-compatibility Potential compatibility breakages, removed APIs

39
src/Magnum/Platform/Screen.h

@ -252,13 +252,33 @@ template<class Application> class BasicScreen:
*/ */
void setPropagatedEvents(PropagatedEvents events) { _propagatedEvents = events; } void setPropagatedEvents(PropagatedEvents events) { _propagatedEvents = events; }
/** @brief Application holding this screen */ /**
template<class T = BasicScreenedApplication<Application>> T* application() { * @brief Whether the screen is added to an application
return static_cast<T*>(Containers::LinkedListItem<BasicScreen<Application>, BasicScreenedApplication<Application>>::list()); *
* If not, the @ref application() accessor can't be used.
* @see @ref BasicScreenedApplication::addScreen(),
* @ref BasicScreenedApplication::removeScreen()
*/
bool hasApplication() {
return Containers::LinkedListItem<BasicScreen<Application>, BasicScreenedApplication<Application>>::list();
} }
/**
* @brief Application holding this screen
*
* Expects that the screen is added to an application.
* @see @ref hasApplication()
*/
BasicScreenedApplication<Application>& application();
/** @overload */ /** @overload */
template<class T = BasicScreenedApplication<Application>> const T* application() const { const BasicScreenedApplication<Application>& application() const;
return static_cast<const T*>(Containers::LinkedListItem<BasicScreen<Application>, BasicScreenedApplication<Application>>::list()); /** @overload */
template<class T = BasicScreenedApplication<Application>> T& application() {
return static_cast<T&>(application());
}
/** @overload */
template<class T = BasicScreenedApplication<Application>> const T& application() const {
return static_cast<const T&>(application());
} }
/** /**
@ -294,8 +314,13 @@ template<class Application> class BasicScreen:
/** @{ @name Screen handling */ /** @{ @name Screen handling */
protected: protected:
/** @brief Request redraw */ /**
virtual void redraw() { application()->redraw(); } * @brief Request redraw
*
* Expects that the screen is added to an application.
* @see @ref hasApplication()
*/
virtual void redraw();
private: private:
/** /**

12
src/Magnum/Platform/ScreenedApplication.h

@ -265,6 +265,18 @@ template<class Application> class BasicScreenedApplication:
return static_cast<const Containers::LinkedList<BasicScreen<Application>>&>(*this); return static_cast<const Containers::LinkedList<BasicScreen<Application>>&>(*this);
} }
#if defined(MAGNUM_BUILD_DEPRECATED) && !defined(DOXYGEN_GENERATING_OUTPUT)
CORRADE_DEPRECATED("Platform::Screen::application() returns a reference now") BasicScreenedApplication<Application>* operator->() { return this; }
CORRADE_DEPRECATED("Platform::Screen::application() returns a reference now") const BasicScreenedApplication<Application>* operator->() const { return this; }
CORRADE_DEPRECATED("Platform::Screen::application() returns a reference now") BasicScreenedApplication<Application>& operator*() { return *this; }
CORRADE_DEPRECATED("Platform::Screen::application() returns a reference now") const BasicScreenedApplication<Application>& operator*() const { return *this; }
CORRADE_DEPRECATED("Platform::Screen::application() returns a reference now") operator BasicScreenedApplication<Application>*() { return this; }
CORRADE_DEPRECATED("Platform::Screen::application() returns a reference now") operator const BasicScreenedApplication<Application>*() const { return this; }
template<class T, class = typename std::enable_if<std::is_base_of<BasicScreenedApplication<Application>, T>::value>::type> CORRADE_DEPRECATED("Platform::Screen::application() returns a reference now") operator T*() { return static_cast<T*>(this); }
template<class T, class = typename std::enable_if<std::is_base_of<BasicScreenedApplication<Application>, T>::value>::type> CORRADE_DEPRECATED("Platform::Screen::application() returns a reference now") operator const T*() const { return static_cast<const T*>(this); }
CORRADE_DEPRECATED("Platform::Screen::application() returns a reference now, use hasApplication() instead") bool operator!() const { return false; }
#endif
protected: protected:
/* Nobody will need to have (and delete) ScreenedApplication*, thus /* Nobody will need to have (and delete) ScreenedApplication*, thus
this is faster than public pure virtual destructor */ this is faster than public pure virtual destructor */

24
src/Magnum/Platform/ScreenedApplication.hpp

@ -117,6 +117,24 @@ template<class Application> BasicScreen<Application>::BasicScreen(BasicScreenedA
template<class Application> BasicScreen<Application>::~BasicScreen() = default; template<class Application> BasicScreen<Application>::~BasicScreen() = default;
template<class Application> BasicScreenedApplication<Application>& BasicScreen<Application>::application() {
BasicScreenedApplication<Application>* application = Containers::LinkedListItem<BasicScreen<Application>, BasicScreenedApplication<Application>>::list();
CORRADE_ASSERT(application, "Platform::Screen::application(): the screen is not added to any application", *application);
return *application;
}
template<class Application> const BasicScreenedApplication<Application>& BasicScreen<Application>::application() const {
const BasicScreenedApplication<Application>* application = Containers::LinkedListItem<BasicScreen<Application>, BasicScreenedApplication<Application>>::list();
CORRADE_ASSERT(application, "Platform::Screen::application(): the screen is not added to any application", *application);
return *application;
}
template<class Application> void BasicScreen<Application>::redraw() {
BasicScreenedApplication<Application>* application = Containers::LinkedListItem<BasicScreen<Application>, BasicScreenedApplication<Application>>::list();
CORRADE_ASSERT(application, "Platform::Screen::redraw(): the screen is not added to any application", );
application->redraw();
}
template<class Application> void BasicScreen<Application>::focusEvent() {} template<class Application> void BasicScreen<Application>::focusEvent() {}
template<class Application> void BasicScreen<Application>::blurEvent() {} template<class Application> void BasicScreen<Application>::blurEvent() {}
@ -149,7 +167,7 @@ template<class Application> BasicScreenedApplication<Application>::BasicScreened
template<class Application> BasicScreenedApplication<Application>::~BasicScreenedApplication() = default; template<class Application> BasicScreenedApplication<Application>::~BasicScreenedApplication() = default;
template<class Application> BasicScreenedApplication<Application>& BasicScreenedApplication<Application>::addScreen(BasicScreen<Application>& screen) { template<class Application> BasicScreenedApplication<Application>& BasicScreenedApplication<Application>::addScreen(BasicScreen<Application>& screen) {
CORRADE_ASSERT(!screen.application(), CORRADE_ASSERT(!screen.hasApplication(),
"Platform::ScreenedApplication::addScreen(): screen already added to an application", *this); "Platform::ScreenedApplication::addScreen(): screen already added to an application", *this);
/* A subset of this (except focusEvent()) is done in /* A subset of this (except focusEvent()) is done in
@ -162,7 +180,7 @@ template<class Application> BasicScreenedApplication<Application>& BasicScreened
} }
template<class Application> BasicScreenedApplication<Application>& BasicScreenedApplication<Application>::removeScreen(BasicScreen<Application>& screen) { template<class Application> BasicScreenedApplication<Application>& BasicScreenedApplication<Application>::removeScreen(BasicScreen<Application>& screen) {
CORRADE_ASSERT(screen.application() == this, CORRADE_ASSERT(screen.hasApplication() && &screen.application() == this,
"Platform::ScreenedApplication::removeScreen(): screen not owned by this application", *this); "Platform::ScreenedApplication::removeScreen(): screen not owned by this application", *this);
screen.blurEvent(); screen.blurEvent();
@ -172,7 +190,7 @@ template<class Application> BasicScreenedApplication<Application>& BasicScreened
} }
template<class Application> BasicScreenedApplication<Application>& BasicScreenedApplication<Application>::focusScreen(BasicScreen<Application>& screen) { template<class Application> BasicScreenedApplication<Application>& BasicScreenedApplication<Application>::focusScreen(BasicScreen<Application>& screen) {
CORRADE_ASSERT(screen.application() == this, CORRADE_ASSERT(screen.hasApplication() && &screen.application() == this,
"Platform::ScreenedApplication::focusScreen(): screen not owned by this application", *this); "Platform::ScreenedApplication::focusScreen(): screen not owned by this application", *this);
/* Already focused, nothing to do */ /* Already focused, nothing to do */

Loading…
Cancel
Save