✨ can now write on the View from UI class.
parent
5188860936
commit
dc3c855ecf
|
@ -22,11 +22,16 @@ twq_lib = static_library('tiwiq',
|
||||||
'src/core/Observable.cpp',
|
'src/core/Observable.cpp',
|
||||||
'src/core/Event.cpp',
|
'src/core/Event.cpp',
|
||||||
|
|
||||||
|
'src/core/Coord.cpp',
|
||||||
|
'src/core/Rect.cpp',
|
||||||
|
'src/core/Color.cpp',
|
||||||
|
|
||||||
'src/cmd/QuitCmd.cpp',
|
'src/cmd/QuitCmd.cpp',
|
||||||
|
|
||||||
'src/plugins/CorePlugin.cpp',
|
'src/plugins/CorePlugin.cpp',
|
||||||
|
|
||||||
'src/term/Controller.cpp',
|
'src/term/Controller.cpp',
|
||||||
|
'src/term/View.cpp',
|
||||||
'src/term/Term.cpp',
|
'src/term/Term.cpp',
|
||||||
],
|
],
|
||||||
dependencies: [
|
dependencies: [
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
#include "Color.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
/*static*/ Color Color::black() { return Color {0, 0, 0}; }
|
||||||
|
/*static*/ Color Color::white() { return Color {255, 255, 255}; }
|
||||||
|
/*static*/ Color Color::red() { return Color {255, 0, 0}; }
|
||||||
|
/*static*/ Color Color::green() { return Color {0, 255, 0}; }
|
||||||
|
/*static*/ Color Color::blue() { return Color {0, 0, 255}; }
|
||||||
|
|
||||||
|
/*explicit*/ Color::Color()
|
||||||
|
: Color(0, 0, 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*explicit*/ Color::Color(int red, int green, int blue)
|
||||||
|
: m_red { red }
|
||||||
|
, m_green { green }
|
||||||
|
, m_blue { blue }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Color::~Color()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Color::equals(Color const& rhs) const
|
||||||
|
{
|
||||||
|
return m_red == rhs.m_red
|
||||||
|
&& m_green == rhs.m_green
|
||||||
|
&& m_blue == rhs.m_blue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
#ifndef twq_core_COLOR_HPP
|
||||||
|
#define twq_core_COLOR_HPP
|
||||||
|
|
||||||
|
#include "../commons.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
class Color
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static Color black();
|
||||||
|
static Color white();
|
||||||
|
static Color red();
|
||||||
|
static Color green();
|
||||||
|
static Color blue();
|
||||||
|
|
||||||
|
explicit Color();
|
||||||
|
explicit Color(int red, int green, int blue);
|
||||||
|
virtual ~Color();
|
||||||
|
|
||||||
|
int r() const { return m_red; }
|
||||||
|
int g() const { return m_green; }
|
||||||
|
int b() const { return m_blue; }
|
||||||
|
|
||||||
|
bool equals(Color const& rhs) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_red;
|
||||||
|
int m_green;
|
||||||
|
int m_blue;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,32 @@
|
||||||
|
#include "Coord.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
/*explicit*/ Coord::Coord()
|
||||||
|
: Coord(0, 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*explicit*/ Coord::Coord(int row, int col)
|
||||||
|
: m_row { row }
|
||||||
|
, m_col { col }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Coord::~Coord()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Coord::string() const
|
||||||
|
{
|
||||||
|
return std::to_string(m_row) + "x" + std::to_string(m_col);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Coord::equals(Coord const& rhs) const
|
||||||
|
{
|
||||||
|
return m_row == rhs.m_row && m_col == rhs.m_col;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef twq_core_COORD_HPP
|
||||||
|
#define twq_core_COORD_HPP
|
||||||
|
|
||||||
|
#include "../commons.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
class Coord
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Coord();
|
||||||
|
explicit Coord(int row, int col);
|
||||||
|
virtual ~Coord();
|
||||||
|
|
||||||
|
int row() const { return m_row; }
|
||||||
|
int col() const { return m_col; }
|
||||||
|
|
||||||
|
std::string string() const;
|
||||||
|
|
||||||
|
bool equals(Coord const& rhs) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_row;
|
||||||
|
int m_col;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -3,14 +3,36 @@
|
||||||
|
|
||||||
#include "../commons.hpp"
|
#include "../commons.hpp"
|
||||||
#include "KeyMod.hpp"
|
#include "KeyMod.hpp"
|
||||||
|
#include "Pixel.hpp"
|
||||||
|
#include "Coord.hpp"
|
||||||
|
|
||||||
|
#define EVENT_TYPES(G) \
|
||||||
|
G(EVENT_UNKNOWN), \
|
||||||
|
G(EVENT_KEY), \
|
||||||
|
G(EVENT_DRAW)
|
||||||
|
|
||||||
namespace twq
|
namespace twq
|
||||||
{
|
{
|
||||||
namespace core
|
namespace core
|
||||||
{
|
{
|
||||||
|
TWQ_ENUM(EventType, EVENT_TYPES);
|
||||||
|
|
||||||
|
struct DrawEvent {
|
||||||
|
Coord coord;
|
||||||
|
Pixel pixel;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ResizeEvent {
|
||||||
|
int w;
|
||||||
|
int h;
|
||||||
|
};
|
||||||
|
|
||||||
struct Event
|
struct Event
|
||||||
{
|
{
|
||||||
|
EventType type = EVENT_UNKNOWN;
|
||||||
std::optional<KeyMod> key;
|
std::optional<KeyMod> key;
|
||||||
|
std::optional<DrawEvent> draw;
|
||||||
|
std::optional<ResizeEvent> resize;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef twq_core_PIXEL_HPP
|
||||||
|
#define twq_core_PIXEL_HPP
|
||||||
|
|
||||||
|
#include "Color.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
struct Pixel {
|
||||||
|
Color background;
|
||||||
|
Color foreground;
|
||||||
|
wchar_t text;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -23,7 +23,6 @@ namespace twq
|
||||||
private:
|
private:
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
std::shared_ptr<Executor> m_executor;
|
std::shared_ptr<Executor> m_executor;
|
||||||
|
|
||||||
std::shared_ptr<UI> m_ui =
|
std::shared_ptr<UI> m_ui =
|
||||||
std::make_shared<UI>();
|
std::make_shared<UI>();
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
#include "Rect.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
/*explicit*/ Rect::Rect()
|
||||||
|
: Rect(Coord {0, 0}, Coord {0, 0})
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*explicit*/ Rect::Rect(Coord const& pos, Coord const& size)
|
||||||
|
: m_pos { pos }
|
||||||
|
, m_size { size }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Rect::~Rect()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Rect::string() const
|
||||||
|
{
|
||||||
|
return "(" + m_pos.string() + " " + m_size.string() + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Rect::equals(Rect const& rhs) const
|
||||||
|
{
|
||||||
|
return m_pos.equals(rhs.m_pos) && m_size.equals(rhs.m_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef twq_core_RECT_HPP
|
||||||
|
#define twq_core_RECT_HPP
|
||||||
|
|
||||||
|
#include "Coord.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
class Rect
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Rect();
|
||||||
|
explicit Rect(Coord const& pos, Coord const& size);
|
||||||
|
virtual ~Rect();
|
||||||
|
|
||||||
|
Coord pos() const { return m_pos; }
|
||||||
|
Coord size() const { return m_size; }
|
||||||
|
|
||||||
|
std::string string() const;
|
||||||
|
|
||||||
|
bool equals(Rect const& rhs) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Coord m_pos;
|
||||||
|
Coord m_size;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -31,7 +31,7 @@ namespace twq
|
||||||
|
|
||||||
void Tiwiq::update(Event& event) /*override*/
|
void Tiwiq::update(Event& event) /*override*/
|
||||||
{
|
{
|
||||||
if (event.key)
|
if (event.type == EVENT_KEY)
|
||||||
{
|
{
|
||||||
if (!m_plugins.empty())
|
if (!m_plugins.empty())
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,5 +11,49 @@ namespace twq
|
||||||
/*virtual*/ UI::~UI()
|
/*virtual*/ UI::~UI()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UI::write(Pixel const& pixel, Coord const& coord)
|
||||||
|
{
|
||||||
|
size_t index = coord.row() * m_screen_rect.size().col()
|
||||||
|
+ coord.col();
|
||||||
|
|
||||||
|
TWQ_ASSERT(index < m_pixels.size(), "cannot write pixel at coord '"
|
||||||
|
+ coord.string()
|
||||||
|
+ "' (actual screen rect: '"
|
||||||
|
+ m_screen_rect.string()
|
||||||
|
+ "'");
|
||||||
|
|
||||||
|
m_pixels[index] = pixel;
|
||||||
|
|
||||||
|
Event event;
|
||||||
|
event.type = EVENT_DRAW;
|
||||||
|
event.draw = DrawEvent {
|
||||||
|
coord,
|
||||||
|
pixel,
|
||||||
|
};
|
||||||
|
|
||||||
|
notify(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UI::resize(Rect const& rect)
|
||||||
|
{
|
||||||
|
size_t dim = rect.size().row() * rect.size().col();
|
||||||
|
m_pixels.clear();
|
||||||
|
|
||||||
|
for (size_t i=0; i<dim; i++)
|
||||||
|
{
|
||||||
|
m_pixels.push_back(Pixel {
|
||||||
|
Color::black(),
|
||||||
|
Color::white(),
|
||||||
|
L'x'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
m_screen_rect = rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UI::update(Event&) /*override*/
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,31 @@
|
||||||
#ifndef twq_core_UI_HPP
|
#ifndef twq_core_UI_HPP
|
||||||
#define twq_core_UI_HPP
|
#define twq_core_UI_HPP
|
||||||
|
|
||||||
|
#include "../commons.hpp"
|
||||||
|
#include "Observable.hpp"
|
||||||
|
#include "Coord.hpp"
|
||||||
|
#include "Color.hpp"
|
||||||
|
#include "Rect.hpp"
|
||||||
|
#include "Pixel.hpp"
|
||||||
|
|
||||||
namespace twq
|
namespace twq
|
||||||
{
|
{
|
||||||
namespace core
|
namespace core
|
||||||
{
|
{
|
||||||
class UI
|
class UI: public Observable, public Observer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit UI();
|
explicit UI();
|
||||||
virtual ~UI();
|
virtual ~UI();
|
||||||
|
|
||||||
|
void write(Pixel const& pixel, Coord const& coord);
|
||||||
|
void resize(Rect const& rect);
|
||||||
|
|
||||||
|
void update(Event& event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Rect m_screen_rect;
|
||||||
|
std::vector<Pixel> m_pixels;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,16 +7,21 @@ int main(int, char**)
|
||||||
{
|
{
|
||||||
auto tiwiq = std::make_shared<twq::core::Tiwiq>();
|
auto tiwiq = std::make_shared<twq::core::Tiwiq>();
|
||||||
auto term = std::make_shared<twq::term::Term>();
|
auto term = std::make_shared<twq::term::Term>();
|
||||||
|
|
||||||
term->controller().lock()->add_observer(tiwiq);
|
term->controller().lock()->add_observer(tiwiq);
|
||||||
|
|
||||||
// Build and add plugins
|
// Build and add plugins
|
||||||
// ---------------------
|
// ---------------------
|
||||||
auto core_plugin = std::make_shared<twq::plugins::CorePlugin>();
|
auto core_plugin = std::make_shared<twq::plugins::CorePlugin>();
|
||||||
|
core_plugin->ui().lock()->add_observer(term->view().lock());
|
||||||
|
core_plugin->ui().lock()->resize(term->view().lock()->dim());
|
||||||
|
|
||||||
tiwiq->add_plugin(core_plugin);
|
tiwiq->add_plugin(core_plugin);
|
||||||
|
|
||||||
// Start TiwiQ
|
// Start TiwiQ
|
||||||
// -----------
|
// -----------
|
||||||
tiwiq->start();
|
tiwiq->start();
|
||||||
|
bool a = true;
|
||||||
|
|
||||||
while (tiwiq->is_running())
|
while (tiwiq->is_running())
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,6 +18,7 @@ namespace twq
|
||||||
void Controller::update()
|
void Controller::update()
|
||||||
{
|
{
|
||||||
core::Event event;
|
core::Event event;
|
||||||
|
event.type = core::EVENT_KEY;
|
||||||
event.key = get();
|
event.key = get();
|
||||||
notify(event);
|
notify(event);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "Term.hpp"
|
#include "Term.hpp"
|
||||||
|
#include <curses.h>
|
||||||
|
|
||||||
namespace twq
|
namespace twq
|
||||||
{
|
{
|
||||||
|
@ -12,6 +13,10 @@ namespace twq
|
||||||
raw();
|
raw();
|
||||||
keypad(stdscr, TRUE);
|
keypad(stdscr, TRUE);
|
||||||
noecho();
|
noecho();
|
||||||
|
curs_set(0);
|
||||||
|
|
||||||
|
TWQ_ASSERT(has_colors(), "your terminal does not support colors");
|
||||||
|
start_color();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*virtual*/ Term::~Term()
|
/*virtual*/ Term::~Term()
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "../commons.hpp"
|
#include "../commons.hpp"
|
||||||
|
|
||||||
#include "Controller.hpp"
|
#include "Controller.hpp"
|
||||||
|
#include "View.hpp"
|
||||||
|
|
||||||
namespace twq
|
namespace twq
|
||||||
{
|
{
|
||||||
|
@ -17,10 +18,14 @@ namespace twq
|
||||||
virtual ~Term();
|
virtual ~Term();
|
||||||
|
|
||||||
std::weak_ptr<Controller> controller() { return m_controller; }
|
std::weak_ptr<Controller> controller() { return m_controller; }
|
||||||
|
std::weak_ptr<View> view() { return m_view; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<Controller> m_controller =
|
std::shared_ptr<Controller> m_controller =
|
||||||
std::make_shared<Controller>();
|
std::make_shared<Controller>();
|
||||||
|
|
||||||
|
std::shared_ptr<View> m_view =
|
||||||
|
std::make_shared<View>();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
#include "View.hpp"
|
||||||
|
#include "../core/Event.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace term
|
||||||
|
{
|
||||||
|
/*explicit*/ View::View()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ View::~View()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
core::Rect View::dim() const
|
||||||
|
{
|
||||||
|
int w, h;
|
||||||
|
getmaxyx(stdscr, h, w);
|
||||||
|
|
||||||
|
return core::Rect {
|
||||||
|
core::Coord {0, 0},
|
||||||
|
core::Coord {h, w}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::update(core::Event& event) /*override*/
|
||||||
|
{
|
||||||
|
if (event.draw)
|
||||||
|
{
|
||||||
|
bkgdset(COLOR_PAIR(get_attr(Attribute {
|
||||||
|
core::Color::black(),
|
||||||
|
core::Color::white(),
|
||||||
|
})));
|
||||||
|
|
||||||
|
clear();
|
||||||
|
|
||||||
|
int i = event.draw->coord.row();
|
||||||
|
int j = event.draw->coord.col();
|
||||||
|
|
||||||
|
int pair = get_attr(Attribute {
|
||||||
|
event.draw->pixel.background,
|
||||||
|
event.draw->pixel.foreground
|
||||||
|
});
|
||||||
|
|
||||||
|
attron(COLOR_PAIR(pair));
|
||||||
|
mvprintw(j, i, "%lc", event.draw->pixel.text);
|
||||||
|
attroff(COLOR_PAIR(pair));
|
||||||
|
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int View::get_color(core::Color const& color)
|
||||||
|
{
|
||||||
|
for (auto p: m_colors)
|
||||||
|
{
|
||||||
|
if (p.second.equals(color))
|
||||||
|
{
|
||||||
|
return p.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int id = m_colors.size() + COLOR_WHITE + 1;
|
||||||
|
|
||||||
|
auto format = [](int color_in){
|
||||||
|
return static_cast<int>((color_in / 255.0) * 1000.0);
|
||||||
|
};
|
||||||
|
|
||||||
|
init_color(id,
|
||||||
|
format(color.r()),
|
||||||
|
format(color.g()),
|
||||||
|
format(color.b()));
|
||||||
|
|
||||||
|
|
||||||
|
m_colors[id] = color;
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
int View::get_attr(Attribute const& attr)
|
||||||
|
{
|
||||||
|
for (auto p: m_attrs)
|
||||||
|
{
|
||||||
|
if (p.second.fg.equals(attr.fg)
|
||||||
|
&& p.second.bg.equals(attr.bg))
|
||||||
|
{
|
||||||
|
return p.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int id = m_attrs.size() + 1;
|
||||||
|
init_pair(id, get_color(attr.fg), get_color(attr.bg));
|
||||||
|
m_attrs[id] = attr;
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
#ifndef twq_term_VIEW_HPP
|
||||||
|
#define twq_term_VIEW_HPP
|
||||||
|
|
||||||
|
#include <ncurses.h>
|
||||||
|
#include "../commons.hpp"
|
||||||
|
#include "../core/Observer.hpp"
|
||||||
|
#include "../core/Observable.hpp"
|
||||||
|
|
||||||
|
#include "../core/Rect.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace term
|
||||||
|
{
|
||||||
|
struct Attribute {
|
||||||
|
core::Color bg;
|
||||||
|
core::Color fg;
|
||||||
|
};
|
||||||
|
|
||||||
|
class View: public core::Observer, public core::Observable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit View();
|
||||||
|
virtual ~View();
|
||||||
|
|
||||||
|
core::Rect dim() const;
|
||||||
|
void update(core::Event& event) override;
|
||||||
|
|
||||||
|
int get_color(core::Color const& color);
|
||||||
|
int get_attr(Attribute const& attr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
core::Rect m_prev_dim;
|
||||||
|
core::Rect m_dim;
|
||||||
|
|
||||||
|
std::unordered_map<int, core::Color> m_colors;
|
||||||
|
std::unordered_map<int, Attribute> m_attrs;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue