giga

Terminal text editor
git clone git://git.dimitrijedobrota.com/giga.git
Log | Files | Refs | README | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING

commit775a7a593487d6aa4ecc25975feaec4069b5c02a
parent6d35b46728c76b2e9ca7d1ee62ba214d3f35a903
authorDimitrije Dobrota <mail@dimitrijedobrota.com>
dateSat, 8 Mar 2025 19:27:12 +0100

Ensure enum safety with concepts

Diffstat:
Msource/layout_dynamic.cpp|+++++++++++++++++--------------
Msource/layout_dynamic.hpp|++++++++++++++++++++++------

2 files changed, 39 insertions(+), 20 deletions(-)


diff --git a/source/layout_dynamic.cpp b/source/layout_dynamic.cpp

@@ -112,24 +112,21 @@ Panel* Panel::close()

return std::visit(visit_parent, m_parent->m_payload);
}
Panel* Panel::select(Panel* sel, Direction dir)
template<Panel::Direction D>
requires is_enum_valid_v<Panel::Direction, D>
Panel* Panel::select(Panel* sel)
{
const auto& sele = sel->get_elem();
pos_t tpos = {0, 0};
switch (dir) {
case Direction::Up:
tpos = sele.apos() + pos_t(0, -1);
break;
case Direction::Left:
tpos = sele.apos() + pos_t(-1, 0);
break;
case Direction::Down:
tpos = sele.apos() + pos_t(0UL, sele.ahgt().value());
break;
case Direction::Right:
tpos = sele.apos() + pos_t(sele.awth().value(), 0UL);
break;
if constexpr (D == Direction::Up) {
tpos = sele.apos() + pos_t(0, -1);
} else if (D == Direction::Left) {
tpos = sele.apos() + pos_t(-1, 0);
} else if (D == Direction::Down) {
tpos = sele.apos() + pos_t(0UL, sele.ahgt().value());
} else if (D == Direction::Right) {
tpos = sele.apos() + pos_t(sele.awth().value(), 0UL);
}
const auto& roote = get_elem();

@@ -174,6 +171,7 @@ Panel* Panel::select(pos_t tpos)

}
template<Panel::Split T>
requires is_enum_valid_v<Panel::Split, T>
Panel* Panel::split()
{
const auto visit_parent = [&]<typename M>(M& pcont) -> Panel*

@@ -224,4 +222,9 @@ Panel* Panel::split()

template Panel* Panel::split<Panel::Split::Horizontal>();
template Panel* Panel::split<Panel::Split::Vertical>();
template Panel* Panel::select<Panel::Direction::Up>(Panel*);
template Panel* Panel::select<Panel::Direction::Left>(Panel*);
template Panel* Panel::select<Panel::Direction::Right>(Panel*);
template Panel* Panel::select<Panel::Direction::Down>(Panel*);
} // namespace display

diff --git a/source/layout_dynamic.hpp b/source/layout_dynamic.hpp

@@ -10,6 +10,16 @@

namespace display
{
template<typename T>
concept is_enum_type_v = std::is_enum_v<T>;
template<typename T>
concept is_enum_count_v = requires { T::_count; };
template<typename T, T Val>
concept is_enum_valid_v = is_enum_type_v<T> && is_enum_count_v<T>
&& requires { requires(Val >= T {} && Val < T::_count); };
class Panel
{
public:

@@ -19,6 +29,7 @@ public:

{
Horizontal,
Vertical,
_count, // NOLINT
};
enum class Direction : std::uint8_t

@@ -26,7 +37,8 @@ public:

Up,
Left,
Down,
Right
Right,
_count, // NOLINT
};
Panel(Panel* parent, plc_t aplc, layout_t::ptr_t&& child)

@@ -47,10 +59,14 @@ public:

void render() const;
template<Split T>
requires is_enum_valid_v<Split, T>
Panel* split();
template<Direction D>
requires is_enum_valid_v<Direction, D>
Panel* select(Panel* sel);
Panel* close();
Panel* select(Panel* sel, Direction dir);
private:
const Element& get_elem() const

@@ -177,13 +193,13 @@ void LayoutDynamic<T>::input(event& evnt)

} else if (evnt.key() == 'x') {
m_sel = m_sel->close();
} else if (evnt.key() == 'w') {
m_sel = m_container.select(m_sel, Panel::Direction::Up);
m_sel = m_container.select<Panel::Direction::Up>(m_sel);
} else if (evnt.key() == 'a') {
m_sel = m_container.select(m_sel, Panel::Direction::Left);
m_sel = m_container.select<Panel::Direction::Left>(m_sel);
} else if (evnt.key() == 's') {
m_sel = m_container.select(m_sel, Panel::Direction::Down);
m_sel = m_container.select<Panel::Direction::Down>(m_sel);
} else if (evnt.key() == 'd') {
m_sel = m_container.select(m_sel, Panel::Direction::Right);
m_sel = m_container.select<Panel::Direction::Right>(m_sel);
} else {
m_sel->layout().input(evnt);
}