giga

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

commitb85d2582224dc41e9e2f35ac5084a893e9004c74
parentd58507c65e24b55232773c2581dff03de96d83af
authorDimitrije Dobrota <mail@dimitrijedobrota.com>
dateWed, 5 Mar 2025 13:48:46 +0100

Iterative, position based navigation

Diffstat:
MCMakeLists.txt|+-
Msource/layout_dynamic.cpp|++++++++++++++++++++++++++++++++--------------------------------------------------
Msource/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;
};