gigaTerminal text editor |
git clone git://git.dimitrijedobrota.com/giga.git |
Log | Files | Refs | README | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING |
commit | 775a7a593487d6aa4ecc25975feaec4069b5c02a |
parent | 6d35b46728c76b2e9ca7d1ee62ba214d3f35a903 |
author | Dimitrije Dobrota <mail@dimitrijedobrota.com> |
date | Sat, 8 Mar 2025 19:27:12 +0100 |
Ensure enum safety with concepts
Diffstat:M | source/layout_dynamic.cpp | | | +++++++++++++++++-------------- |
M | source/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);
}