gigaTerminal text editor |
git clone git://git.dimitrijedobrota.com/giga.git |
Log | Files | Refs | README | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING | |
commit | b85d2582224dc41e9e2f35ac5084a893e9004c74 |
parent | d58507c65e24b55232773c2581dff03de96d83af |
author | Dimitrije Dobrota <mail@dimitrijedobrota.com> |
date | Wed, 5 Mar 2025 13:48:46 +0100 |
Iterative, position based navigation
Diffstat:M | CMakeLists.txt | | | +- |
M | source/layout_dynamic.cpp | | | ++++++++++++++++++++++++++++++++-------------------------------------------------- |
M | source/layout_dynamic.hpp | | | ++++++++++-------------- |
3 files changed, 54 insertions(+), 83 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -4,7 +4,7 @@ include(cmake/prelude.cmake)
project(
giga
VERSION 0.1.9
VERSION 0.1.10
DESCRIPTION "Terminal text editor"
HOMEPAGE_URL "https://git.dimitrijedobrota.com/giga.git"
LANGUAGES CXX
diff --git a/source/layout_dynamic.cpp b/source/layout_dynamic.cpp
@@ -1,4 +1,3 @@
#include <functional>
#include <stdexcept>
#include "layout_dynamic.hpp"
@@ -37,28 +36,28 @@ void LayoutDynamic::input(event& evnt)
}
if (evnt.key() == 'w') {
m_sel = m_sel->up();
m_sel = m_layout.select(m_sel, Panel::Direction::Up);
render();
evnt.type() = event::Type::NONE;
return;
}
if (evnt.key() == 'a') {
m_sel = m_sel->left();
m_sel = m_layout.select(m_sel, Panel::Direction::Left);
render();
evnt.type() = event::Type::NONE;
return;
}
if (evnt.key() == 's') {
m_sel = m_sel->down();
m_sel = m_layout.select(m_sel, Panel::Direction::Down);
render();
evnt.type() = event::Type::NONE;
return;
}
if (evnt.key() == 'd') {
m_sel = m_sel->right();
m_sel = m_layout.select(m_sel, Panel::Direction::Right);
render();
evnt.type() = event::Type::NONE;
return;
@@ -127,7 +126,6 @@ LayoutDynamic::Panel* LayoutDynamic::Panel::split_horizontal()
std::make_unique<Panel>(panel, panel->place_horizontal(idx, size)));
panel->resize_horizontal(size);
panel->m_sel = idx;
return panel->m_splits[idx].get();
}
@@ -159,7 +157,6 @@ LayoutDynamic::Panel* LayoutDynamic::Panel::split_vertical()
std::make_unique<Panel>(panel, panel->place_vertical(idx, size)));
panel->resize_vertical(size);
panel->m_sel = idx;
return panel->m_splits[idx].get();
}
@@ -174,43 +171,30 @@ LayoutDynamic::Panel* LayoutDynamic::Panel::close()
return nullptr;
}
auto* parent = m_parent; // I'll be deleted
// I'll be deleted
const auto pos = apos();
auto* parent = m_parent;
auto& splits = parent->m_splits;
if (splits.size() == 2) {
if (splits.size() != 2) {
splits.erase(parent->find_child(this));
} else {
auto& base = splits[0].get() == this ? *splits[1] : *splits[0];
parent->m_type = base.m_type;
if (parent->m_type == Type::Single) {
parent->set_child(base.release_child());
parent->m_splits.clear();
parent->resize(parent->aplc());
return parent;
}
parent->m_splits = std::move(base.m_splits);
for (auto& panel : parent->m_splits) {
panel->m_parent = parent;
} else {
parent->m_splits = std::move(base.m_splits);
for (auto& panel : parent->m_splits) {
panel->m_parent = parent;
}
}
parent->m_sel = base.m_sel;
parent->resize(parent->aplc());
// return my selection
} else {
const auto itr = splits.erase(parent->find_child(this));
parent->resize(parent->aplc());
parent->m_sel =
std::min(static_cast<std::size_t>(std::distance(splits.begin(), itr)),
splits.size() - 1);
}
const auto& call =
parent->m_type == Type::Horizontal ? &Panel::leftright : &Panel::updown;
return std::invoke(call, splits[parent->m_sel], Action::Prop);
parent->resize(parent->aplc());
return parent->select(pos);
}
plc_t LayoutDynamic::Panel::place_horizontal(std::size_t idx,
@@ -261,54 +245,45 @@ void LayoutDynamic::Panel::resize_vertical(std::size_t size) // NOLINT
}
}
LayoutDynamic::Panel* LayoutDynamic::Panel::updown(Action action) // NOLINT
LayoutDynamic::Panel* LayoutDynamic::Panel::select(Panel* crnt, Direction dir)
{
if (action != Action::Prop) {
if (m_type == Type::Vertical) {
if (action == Action::Inc && m_sel + 1 < m_splits.size()) {
return m_splits[++m_sel]->updown(Action::Prop);
}
if (action == Action::Dec && m_sel > 0) {
return m_splits[--m_sel]->updown(Action::Prop);
}
}
Panel* sel = nullptr;
if (m_parent != nullptr) {
return m_parent->updown(action);
}
}
if (m_type == Type::Single) {
return this;
switch (dir) {
case Direction::Up:
sel = select(crnt->apos() + pos_t(0, -1));
break;
case Direction::Left:
sel = select(crnt->apos() + pos_t(-1, 0));
break;
case Direction::Down:
sel = select(crnt->apos() + pos_t(0UL, crnt->ahgt().value()));
break;
case Direction::Right:
sel = select(crnt->apos() + pos_t(crnt->awth().value(), 0UL));
break;
}
return m_splits[m_sel]->updown(Action::Prop);
return sel != nullptr ? sel : crnt;
}
LayoutDynamic::Panel* LayoutDynamic::Panel::leftright(Action action) // NOLINT
LayoutDynamic::Panel* LayoutDynamic::Panel::select(pos_t pos)
{
if (action != Action::Prop) {
if (m_type == Type::Horizontal) {
if (action == Action::Inc && m_sel + 1 < m_splits.size()) {
return m_splits[++m_sel]->leftright(Action::Prop);
}
Panel* crnt = this;
if (action == Action::Dec && m_sel > 0) {
return m_splits[--m_sel]->leftright(Action::Prop);
while (crnt->m_type != Type::Single) {
for (const auto& panel : crnt->m_splits) {
if (panel->apos() <= pos && pos < panel->apos() + panel->adim()) {
crnt = panel.get();
goto next;
}
}
if (m_parent != nullptr) {
return m_parent->leftright(action);
}
}
if (m_type == Type::Single) {
return this;
return nullptr;
next:;
}
return m_splits[m_sel]->leftright(Action::Prop);
return crnt;
}
} // namespace display
diff --git a/source/layout_dynamic.hpp b/source/layout_dynamic.hpp
@@ -89,10 +89,15 @@ private:
Panel* close();
Panel* up() { return updown(Action::Dec); }
Panel* left() { return leftright(Action::Dec); }
Panel* down() { return updown(Action::Inc); }
Panel* right() { return leftright(Action::Inc); }
enum class Direction : std::uint8_t
{
Up,
Left,
Down,
Right,
};
Panel* select(Panel* crnt, Direction dir);
private:
using panel_ptr = std::unique_ptr<Panel>;
@@ -104,21 +109,13 @@ private:
Vertical,
};
enum Action : std::uint8_t
{
Inc,
Dec,
Prop,
};
plc_t place_horizontal(std::size_t idx, std::size_t size) const;
plc_t place_vertical(std::size_t idx, std::size_t size) const;
void resize_horizontal(std::size_t size);
void resize_vertical(std::size_t size);
Panel* leftright(Action action);
Panel* updown(Action action);
Panel* select(pos_t pos);
auto find_child(const Panel* panel) const
{
@@ -137,7 +134,6 @@ private:
Panel* m_parent;
Type m_type = Type::Single;
std::size_t m_sel = 0;
std::vector<panel_ptr> m_splits;
};