giga

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

commitd58507c65e24b55232773c2581dff03de96d83af
parent7219cd8965aca6a2c0c7dd3f98f79b5b6e87b3ff
authorDimitrije Dobrota <mail@dimitrijedobrota.com>
dateTue, 4 Mar 2025 13:45:00 +0100

Close selected pane with recalculation

Diffstat:
MCMakeLists.txt|+-
Msource/layout_dynamic.cpp|+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
Msource/layout_dynamic.hpp|++++++++++++++++++++++++++++--
Msource/main.cpp|+++++-

4 files changed, 102 insertions(+), 24 deletions(-)


diff --git a/CMakeLists.txt b/CMakeLists.txt

@@ -4,7 +4,7 @@ include(cmake/prelude.cmake)

project(
giga
VERSION 0.1.8
VERSION 0.1.9
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,3 +1,4 @@

#include <functional>
#include <stdexcept>
#include "layout_dynamic.hpp"

@@ -5,12 +6,14 @@

namespace display
{
int WindowTest::counter = 0;
void LayoutDynamic::input(event& evnt)
{
if (evnt.type() == event::Type::KEY) {
if (evnt.key() == 'e') {
m_sel = m_sel->split_horizontal();
m_sel->set_child();
m_sel->emplace_child();
render();
evnt.type() = event::Type::NONE;
return;

@@ -18,12 +21,21 @@ void LayoutDynamic::input(event& evnt)

if (evnt.key() == 'r') {
m_sel = m_sel->split_vertical();
m_sel->set_child();
m_sel->emplace_child();
render();
evnt.type() = event::Type::NONE;
return;
}
if (evnt.key() == 'x') {
m_sel = m_sel->close();
if (m_sel != nullptr) {
render();
}
evnt.type() = event::Type::NONE;
return;
}
if (evnt.key() == 'w') {
m_sel = m_sel->up();
render();

@@ -93,15 +105,8 @@ LayoutDynamic::Panel* LayoutDynamic::Panel::split_horizontal()

std::size_t idx = 1;
if (m_parent != nullptr && m_parent->m_type == Type::Horizontal) {
auto& splits = m_parent->m_splits;
const auto itr =
std::find_if(splits.begin(),
splits.end(),
[&](auto& uptr) { return uptr.get() == this; });
if (itr == splits.end()) {
throw std::runtime_error("Can't to horizontal split [Bad parent]");
}
const auto itr = m_parent->find_child(this);
const auto& splits = m_parent->m_splits;
idx = static_cast<std::size_t>(std::distance(splits.begin(), itr) + 1);
panel = m_parent;

@@ -132,15 +137,8 @@ LayoutDynamic::Panel* LayoutDynamic::Panel::split_vertical()

std::size_t idx = 1;
if (m_parent != nullptr && m_parent->m_type == Type::Vertical) {
auto& splits = m_parent->m_splits;
const auto itr =
std::find_if(splits.begin(),
splits.end(),
[&](auto& uptr) { return uptr.get() == this; });
if (itr == splits.end()) {
throw std::runtime_error("Can't to vertical split [Bad parent]");
}
const auto itr = m_parent->find_child(this);
const auto& splits = m_parent->m_splits;
idx = static_cast<std::size_t>(std::distance(splits.begin(), itr) + 1);
panel = m_parent;

@@ -165,6 +163,56 @@ LayoutDynamic::Panel* LayoutDynamic::Panel::split_vertical()

return panel->m_splits[idx].get();
}
LayoutDynamic::Panel* LayoutDynamic::Panel::close()
{
if (m_type != Type::Single) {
throw std::runtime_error("Can't close non leaf panel");
}
// I am the last one
if (m_parent == nullptr) {
return nullptr;
}
auto* parent = m_parent; // I'll be deleted
auto& splits = parent->m_splits;
if (splits.size() == 2) {
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;
}
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);
}
plc_t LayoutDynamic::Panel::place_horizontal(std::size_t idx,
std::size_t size) const
{

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

@@ -18,7 +18,15 @@ public:

{
}
void render() const override { Window::render_border(); }
void render() const override
{
line_reset();
line_right(std::to_string(m_num));
Window::render_border();
}
static int counter;
int m_num = ++counter;
};
class LayoutDynamic : public Element

@@ -30,6 +38,8 @@ public:

{
}
bool is_finished() const { return m_sel == nullptr; }
void render() const override
{
Element::clear();

@@ -56,7 +66,7 @@ private:

: Layout(aplc)
, m_parent(nullptr)
{
set_child();
emplace_child();
}
explicit Panel(Panel* parent, plc_t aplc)

@@ -77,6 +87,8 @@ private:

Panel* split_horizontal();
Panel* split_vertical();
Panel* close();
Panel* up() { return updown(Action::Dec); }
Panel* left() { return leftright(Action::Dec); }
Panel* down() { return updown(Action::Inc); }

@@ -108,6 +120,20 @@ private:

Panel* leftright(Action action);
Panel* updown(Action action);
auto find_child(const Panel* panel) const
{
const auto itr =
std::find_if(m_splits.begin(),
m_splits.end(),
[&](auto& uptr) { return uptr.get() == panel; });
if (itr == m_splits.end()) {
throw std::runtime_error("Can't find child");
}
return itr;
}
Panel* m_parent;
Type m_type = Type::Single;

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

@@ -338,7 +338,7 @@ int main(const int argc, const char* argv[])

auto& inst = display::Display::display();
// inst.layout().set_child<Panel>(File(args[1]));
inst.layout().set_child<display::LayoutDynamic>();
const auto& layout = inst.layout().emplace_child<display::LayoutDynamic>();
inst.render();
while (true) {

@@ -357,6 +357,10 @@ int main(const int argc, const char* argv[])

}
inst.input(evnt);
if (layout.is_finished()) {
break;
}
}
return 0;