Sto progettando e prototipando un wrapper C ++ ncurses. È un progetto per hobby, niente di troppo serio. Tralascio le protezioni incluse e stdlib include ecc.
Considera i seguenti file:
application.hpp
#include "ncurses_forward_decl.hpp"
#include "window/window.hpp"
#define PPCURSES_VERSION_MAJOR 0
#define PPCURSES_VERSION_MINOR 3
#define PPCURSES_VERSION_PATCH 0
namespace ppc {
enum Focus { Canvas = -1 };
using WindowPtr = std::shared_ptr<Window>;
class Application {
public:
Application();
~Application();
WindowPtr NewWindow(Point pos, Point size);
// Event GetWindowEvents();
char GetKeyEvents();
void Draw();
private:
int focus_id_;
std::unique_ptr<WINDOW> canvas_;
std::vector<std::shared_ptr<Window>> windows_;
};
} // namespace ppc
window.hpp
#include "ncurses_forward_decl.hpp"
#include "util/point.hpp"
#include "widgets/widget.hpp"
namespace ppc {
// FIXME: hide this deleter from public API
void RawWindowDeleter(WINDOW *win);
using WidgetPtr = std::shared_ptr<Widget>;
class Window {
friend class Application;
friend class Widget;
public:
Window(Point pos, Point size);
template <class T, class... Args>
void AddWidget(Args... args) {
WidgetPtr widget = std::make_shared<T>(args...);
widgets_.push_back(widget);
}
void SetPosition(Point t_position);
inline Point Position() { return position_; }
void SetSize(Point t_size);
inline Point Size() { return size_; }
protected:
Point position_;
Point size_;
std::shared_ptr<WINDOW> curses_window_;
inline WINDOW *RawPtr() { return curses_window_.get(); }
void Draw();
char GetKeyEvents();
private:
std::vector<WidgetPtr> widgets_;
};
} // namespace ppc
widget.hpp
#include "ncurses_forward_decl.hpp"
namespace ppc {
class Window;
class Widget {
friend class Window;
public:
virtual ~Widget() = default;
protected:
WINDOW *RawPtr(Window &win);
virtual void Draw(Window &win) = 0;
};
} // namespace ppc
label.hpp
#include "util/point.hpp"
#include "widget.hpp"
namespace ppc {
class Label : public Widget {
friend class Window;
public:
Label(Point pos, const char *text);
Point position;
std::string text;
protected:
void Draw(Window &win) override;
};
} // namespace ppc
L'applicazione può creare Windows, che a sua volta può creare e gestire widget (come un'etichetta). Ma, poiché i Widget devono essere in grado di Draw()
, hanno bisogno del puntatore raw WINDOW *
di ncurses, ottenuto tramite il metodo RawPtr()
, ma sto cercando di nasconderlo dall'API pubblica. Il metodo RawPtr(Window &win)
del widget restituisce il puntatore raw della finestra, poiché Widget è dichiarato amico di Window. Sto anche dichiarando Window come amico di Label e Application come amico di Window. Ritengo che questa sia una decisione sbagliata che porterà agli spaghetti in un secondo momento, e sarebbe molto più facile esporre RawPtr()
in Window al pubblico. Ma davvero non voglio che gli utenti finali abbiano nulla a che fare con il funzionamento interno di ncurses. C'è un disegno che mi manca qui?