#include "screen.h"
+// standard library includes
+#include <cassert>
+#ifndef NDEBUG
+#include <iostream>
+#endif // NDEBUG
+
+// local includes
+#include "screen_test.h"
+
Screen::Screen(std::weak_ptr<ScreenStack> stack) : stack(stack) {}
+ScreenStack::PendingAction::PendingAction() : screen(), action(Action::NOP) {}
+
+ScreenStack::PendingAction::PendingAction(Action action)
+ : screen(), action(action) {}
+
+ScreenStack::PendingAction::PendingAction(Screen::Ptr &&screen)
+ : screen(std::forward<Screen::Ptr>(screen)), action(Action::PUSH_SCREEN) {}
+
ScreenStack::Ptr ScreenStack::new_instance() {
std::shared_ptr<ScreenStack> ptr =
std::shared_ptr<ScreenStack>(new ScreenStack{});
}
void ScreenStack::update(float dt) {
+ handle_pending_actions();
+
auto idx = stack.size();
+ if (idx == 0) {
+#ifndef NDEBUG
+ std::cerr << "WARNING: Stack is empty, pushing TestScreen...\n";
+#endif // NDEBUG
+ push_screen(Screen::new_screen<TestScreen>(self_weak));
+ update(dt);
+ return;
+ }
while (idx > 0 && stack.at(--idx)->update(dt)) {
}
}
}
void ScreenStack::push_screen(Screen::Ptr &&screen) {
- stack.emplace_back(std::forward<Screen::Ptr>(screen));
+ actions.push_back(PendingAction(std::forward<Screen::Ptr>(screen)));
}
void ScreenStack::pop_screen() {
- if (!stack.empty()) {
- stack.pop_back();
- }
+ actions.push_back(PendingAction(Action::POP_SCREEN));
}
-ScreenStack::ScreenStack() : self_weak(), stack() {}
+ScreenStack::ScreenStack() : self_weak(), stack(), actions() {}
+
+void ScreenStack::handle_pending_actions() {
+ while (!actions.empty()) {
+ switch (actions.front().action) {
+ case Action::PUSH_SCREEN:
+ stack.push_back(std::move(actions.front().screen));
+ break;
+ case Action::POP_SCREEN:
+ if (!stack.empty()) {
+ stack.pop_back();
+ }
+ break;
+ case Action::NOP:
+ // Intentionally left blank.
+ break;
+ default:
+ assert(!"unreachable");
+ break;
+ }
+ actions.pop_front();
+ }
+}
#ifndef JUMPARTIFACT_DOT_COM_DEMO_0_SCREEN_H_
#define JUMPARTIFACT_DOT_COM_DEMO_0_SCREEN_H_
+#include <deque>
#include <memory>
#include <vector>
protected:
Screen(std::weak_ptr<ScreenStack> stack);
-
- private:
std::weak_ptr<ScreenStack> stack;
};
class ScreenStack {
+ private:
+ enum Action { PUSH_SCREEN, POP_SCREEN, NOP };
+
+ struct PendingAction {
+ PendingAction();
+ PendingAction(Action action);
+ PendingAction(Screen::Ptr&&);
+
+ // No copy.
+ PendingAction(const PendingAction&) = delete;
+ PendingAction& operator=(const PendingAction&) = delete;
+
+ // Allow move.
+ PendingAction(PendingAction&&) = default;
+ PendingAction& operator=(PendingAction&&) = default;
+
+ Screen::Ptr screen;
+ Action action;
+ };
+
public:
using Ptr = std::shared_ptr<ScreenStack>;
using Weak = std::weak_ptr<ScreenStack>;
private:
ScreenStack();
+ void handle_pending_actions();
+
Weak self_weak;
std::vector<Screen::Ptr> stack;
+ std::deque<PendingAction> actions;
};
template <typename SubScreen>