ScreenStack::PendingAction::PendingAction(Screen::Ptr &&screen)
: screen(std::forward<Screen::Ptr>(screen)), action(Action::PUSH_SCREEN) {}
+ScreenStack::PendingAction::PendingAction(
+ std::function<Screen::Ptr(ScreenStack::Weak)> &&fn)
+ : screen(std::forward<std::function<Screen::Ptr(ScreenStack::Weak)> >(fn)),
+ action(Action::CONSTRUCT_SCREEN) {}
+
ScreenStack::Ptr ScreenStack::new_instance() {
std::shared_ptr<ScreenStack> ptr =
std::shared_ptr<ScreenStack>(new ScreenStack{});
while (!actions.empty()) {
switch (actions.front().action) {
case Action::PUSH_SCREEN:
- stack.push_back(std::move(actions.front().screen));
+ stack.emplace_back(
+ std::move(std::get<Screen::Ptr>(actions.front().screen)));
break;
case Action::POP_SCREEN:
if (!stack.empty()) {
#endif
stack.clear();
break;
+ case Action::CONSTRUCT_SCREEN:
+ stack.emplace_back(
+ std::get<std::function<Screen::Ptr(ScreenStack::Weak)> >(
+ actions.front().screen)(self_weak));
+ break;
case Action::NOP:
// Intentionally left blank.
break;
#define JUMPARTIFACT_DOT_COM_DEMO_0_SCREEN_H_
#include <deque>
+#include <functional>
#include <memory>
+#include <variant>
#include <vector>
// Forward declaration.
};
class ScreenStack {
+ public:
+ using Ptr = std::shared_ptr<ScreenStack>;
+ using Weak = std::weak_ptr<ScreenStack>;
+
private:
- enum Action { PUSH_SCREEN, POP_SCREEN, CLEAR_SCREENS, NOP };
+ enum Action { PUSH_SCREEN, POP_SCREEN, CLEAR_SCREENS, CONSTRUCT_SCREEN, NOP };
struct PendingAction {
PendingAction();
PendingAction(Action action);
PendingAction(Screen::Ptr&&);
+ PendingAction(std::function<Screen::Ptr(ScreenStack::Weak)>&&);
// No copy.
PendingAction(const PendingAction&) = delete;
PendingAction(PendingAction&&) = default;
PendingAction& operator=(PendingAction&&) = default;
- Screen::Ptr screen;
+ std::variant<Screen::Ptr, std::function<Screen::Ptr(ScreenStack::Weak)> >
+ screen;
Action action;
};
public:
- using Ptr = std::shared_ptr<ScreenStack>;
- using Weak = std::weak_ptr<ScreenStack>;
-
static Ptr new_instance();
// No copy.
template <typename SubScreen>
void push_screen();
+ template <typename SubScreen>
+ void push_constructing_screen();
+
void pop_screen();
void clear_screens();
template <typename SubScreen>
void ScreenStack::push_screen() {
- stack.emplace_back(Screen::new_screen<SubScreen>(self_weak));
+ actions.emplace_back(Screen::new_screen<SubScreen>(self_weak));
+}
+
+template <typename SubScreen>
+void ScreenStack::push_constructing_screen() {
+ actions.emplace_back([](ScreenStack::Weak ss) -> Screen::Ptr {
+ return Screen::new_screen<SubScreen>(ss);
+ });
}
#endif