#pragma once #include #include #include #include "key_event.h" // The help panel (issue #69, docs/milestones/U1.md): Fn+h on any screen lists the keys that work // there. Every App says what its keys are in the state it's in; nothing on a screen names keys. namespace roro { // One line of the panel: a key (or keys) and what it does. A line with no action is a heading. struct KeyHelp { const char* keys; const char* action; }; // The panel itself: what it lists, and how far it's scrolled. The keys it takes while open are the // arrows; any other key closes it, and none reaches the App. class HelpModel { public: explicit HelpModel(int visibleRows = 8) : visible_(visibleRows) {} void open(const std::string& title, std::vector rows) { title_ = title; rows_ = std::move(rows); top_ = 0; open_ = true; } void close() { open_ = false; rows_.clear(); rows_.shrink_to_fit(); // nothing is kept while it's closed } bool isOpen() const { return open_; } void onKey(const KeyEvent& e) { int last = std::max(0, static_cast(rows_.size()) - visible_); switch (e.key) { case Key::Up: top_ = std::max(0, top_ - 1); break; case Key::Down: top_ = std::min(last, top_ + 1); break; case Key::Left: top_ = std::max(0, top_ - visible_); break; case Key::Right: top_ = std::min(last, top_ + visible_); break; default: close(); break; } } const std::string& title() const { return title_; } const std::vector& rows() const { return rows_; } int top() const { return top_; } int visibleRows() const { return visible_; } private: std::string title_; std::vector rows_; int top_ = 0; int visible_; bool open_ = false; }; } // namespace roro