Files
rrr.v2/src/rrr/layers/gui/browser/navigation/navigation.cpp
chatlanin d2816fb157 add help
2023-04-10 15:13:22 +03:00

400 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "navigation.hpp"
#include <algorithm>
#include "try_engine/event/event_classificator.hpp"
#include "utils/types.hpp"
#include "buffer/buffer.hpp"
#include "logger/logger.hpp"
namespace rrr::layers::gui
{
void navigation::on_attach()
{
BASE_WINDOW_FLAGS();
data = cnt->get(TYPE_WIN::NAVIGATION);
selected_file = cnt->get_selected_file(TYPE_WIN::NAVIGATION);
}
void navigation::on_detach()
{
}
void navigation::gui_render()
{
if (!show) return;
ImGui::SetNextWindowPos(ImVec2(pos_x, pos_y));
ImGui::SetNextWindowSize(ImVec2(width, height));
ImGuiStyle& st = ImGui::GetStyle();
st.Colors[ImGuiCol_WindowBg] = func::get_IMGUI_color<ImVec4>(33.f, 36.f, 46.f);
BEGIN_IMGUI_WIN();
auto pos = ImGui::GetCursorPos();
pos.x += 17.f;
pos.y += 9.f; // небольшой отступ сверху
ImGui::SetCursorPosY(pos.y);
auto begin = data->begin() + delta;
auto end = data->end();
for (files::iterator it = begin; it != end; ++it)
{
auto item = *it;
ImGui::PushID(item.id);
push_style(item);
if (selected_file.path == item.path)
{
if (selected_file.is_hidden)
TR_PUSH_FONT(SEMI_BOLD_ITALIC, 18);
else
TR_PUSH_FONT(SEMI_BOLD, 18);
ImGui::TextUnformatted(">");
ImGui::SameLine(22.f);
// HERE
// нужно использовать std::distance
current_position = it - data->begin();
}
else
{
ImGui::SetCursorPosX(pos.x);
if (item.is_hidden)
TR_PUSH_FONT(MEDIUM_ITALIC, 18);
else
TR_PUSH_FONT(MEDIUM, 18);
}
ImGui::TextUnformatted(get_file_content(item).data());
pop_style(item);
}
END_IMGUI_WIN();
}
void navigation::push_style(file& f)
{
switch (f.type)
{
case file_type::DIR:
ImGui::PushStyleColor(ImGuiCol_Text, dir_color);
break;
default: // когда просто файл
ImGui::PushStyleColor(ImGuiCol_Text, file_color);
break;
}
if (f.is_link)
ImGui::PushStyleColor(ImGuiCol_Text, link_color);
}
void navigation::pop_style(file& f)
{
TR_POP_FONT();
ImGui::PopStyleColor();
ImGui::PopID();
if (f.is_link)
ImGui::PopStyleColor();
}
std::string navigation::get_file_content(file& f)
{
auto file_content = f.path.filename().string();
if (!buffers::get_instance().single_buffer.empty())
if (f.path == buffers::get_instance().single_buffer[1].path)
file_content = "* " + file_content;
if (f.is_link)
file_content += " ->";
return file_content;
}
void navigation::on_event(system_event& e)
{
if (e.get_name() == try_engine::system_event::classificator::WINDOW_RESIZE())
resize();
if (e.get_name() == try_engine::system_event::classificator::KEY_PRESSED())
pressed(e);
if (e.get_name() == try_engine::system_event::classificator::KEY_RELEASED())
released(e);
}
void navigation::on_event(std::any event_type, std::any value)
{
auto et = std::any_cast<types::event_type>(event_type);
switch (et)
{
case types::event_type::FREEZE_BROWSER_ACTION:
freeze = true;
break;
case types::event_type::UNFREEZE_BROWSER_ACTION:
freeze = false;
break;
case types::event_type::DELETE_CURRENT_FILE:
{
freeze = false;
cnt->delete_file(selected_file);
selected_file = cnt->get_selected_file(TYPE_WIN::NAVIGATION);
}
break;
case types::event_type::CREATE_FILE:
{
freeze = false;
auto filename = std::any_cast<std::string>(value);
cnt->create_file(filename);
selected_file = cnt->get_selected_file(TYPE_WIN::NAVIGATION);
}
break;
case types::event_type::RENAME_FILE:
{
freeze = false;
auto filename = std::any_cast<std::filesystem::path>(value);
cnt->rename_file(selected_file.path, filename);
selected_file = cnt->get_selected_file(TYPE_WIN::NAVIGATION);
}
break;
default:
break;
}
}
void navigation::on_update(time t)
{
}
void navigation::resize()
{
height = try_engine::application::get()->get_window()->height();
width = try_engine::application::get()->get_window()->width() / 3.f - padding_between_window;
pos_x = try_engine::application::get()->get_window()->width() / 3.f + padding_between_window / 2.f;
}
void navigation::pressed(system_event& e)
{
if (freeze) return;
auto key = static_cast<try_engine::system_event::key_pressed_event&>(e);
if (key.get_keycode() == try_engine::key::LEFTSHIFT || key.get_keycode() == try_engine::key::RIGHTSHIFT)
shift = true;
if (shift)
{
// удаление
if (shift && key.get_keycode() == try_engine::key::D)
{
em->execute(types::event_type::SHOW_DELETE_ONE_FILE_DIALOG, selected_file);
freeze = true;
}
// создание файла/директории
if (shift && key.get_keycode() == try_engine::key::A)
{
em->execute(types::event_type::SHOW_CREATE_FILE_DIALOG, nullptr);
freeze = true;
}
// переименование файла/директории
if (shift && key.get_keycode() == try_engine::key::R)
{
em->execute(types::event_type::SHOW_RENAME_FILE_DIALOG, selected_file);
freeze = true;
}
// перемещение в конец списка
if (shift && key.get_keycode() == try_engine::key::G)
{
cnt->increment_position(data->size());
selected_file = cnt->get_selected_file(TYPE_WIN::NAVIGATION);
em->execute(types::event_type::NAVIGATION_DOWN, nullptr);
set_delta(MOVE_DIRECTION::DOWN);
set_scroll();
}
// вставка из single_buffer
if (shift && key.get_keycode() == try_engine::key::P)
{
if (buffers::get_instance().single_buffer.empty()) return;
cnt->paste(buffers::get_instance().single_buffer[1].path);
buffers::get_instance().single_buffer.clear();
}
return;
}
if (key.get_keycode() == try_engine::key::J)
{
cnt->increment_position(STEP_DOWN);
selected_file = cnt->get_selected_file(TYPE_WIN::NAVIGATION);
em->execute(types::event_type::NAVIGATION_DOWN, nullptr);
set_delta(MOVE_DIRECTION::DOWN);
}
if (key.get_keycode() == try_engine::key::K)
{
cnt->increment_position(STEP_UP);
selected_file = cnt->get_selected_file(TYPE_WIN::NAVIGATION);
em->execute(types::event_type::NAVIGATION_UP, nullptr);
set_delta(MOVE_DIRECTION::UP);
}
if (key.get_keycode() == try_engine::key::H)
{
cnt->navigation_left();
data = cnt->get(TYPE_WIN::NAVIGATION);
selected_file = cnt->get_selected_file(TYPE_WIN::NAVIGATION);
em->execute(types::event_type::NAVIGATION_LEFT, nullptr);
set_scroll();
}
if (key.get_keycode() == try_engine::key::L)
{
cnt->navigation_right();
data = cnt->get(TYPE_WIN::NAVIGATION);
selected_file = cnt->get_selected_file(TYPE_WIN::NAVIGATION);
em->execute(types::event_type::NAVIGATION_RIGHT, nullptr);
set_scroll();
}
// двойное нажатие перемещение в начало списка
if (key.get_keycode() == try_engine::key::G)
{
++g_coutn;
if (g_coutn != 2) return;
cnt->increment_position(-data->size());
selected_file = cnt->get_selected_file(TYPE_WIN::NAVIGATION);
em->execute(types::event_type::NAVIGATION_UP, nullptr);
set_delta(MOVE_DIRECTION::UP);
set_scroll();
g_coutn = 0;
}
// копирование/добавление в буфер одного файла вместо другого
if (key.get_keycode() == try_engine::key::C)
{
if (buffers::get_instance().single_buffer.empty())
buffers::get_instance().single_buffer[1] = selected_file;
else
if (selected_file.path == buffers::get_instance().single_buffer[1].path)
buffers::get_instance().single_buffer.clear();
else
buffers::get_instance().single_buffer[1] = selected_file;
}
// очистка
if (key.get_keycode() == try_engine::key::ESCAPE)
buffers::get_instance().single_buffer.clear();
// помощь
if (key.get_keycode() == try_engine::key::F1)
{
em->execute(types::event_type::SHOW_HELP_DIALOG, nullptr);
freeze = true;
}
// HERE начинаем тут
// сделали помощь и начинаем делать множественное копирование и вырезание
// буфер для этого делаем в папке buffers
// там уже есть организация такого типа
}
void navigation::released(system_event& e)
{
auto key = static_cast<try_engine::system_event::key_pressed_event&>(e);
if (key.get_keycode() == try_engine::key::LEFTSHIFT || key.get_keycode() == try_engine::key::RIGHTSHIFT)
shift = false;
}
void navigation::set_delta(MOVE_DIRECTION mvd)
{
auto row_size = 26.3f; // высота вы пикселях одной строки списка
int h = height / row_size; // высота в строках списка всего столбца экрана
auto big_content = height < data->size() * row_size;
int size = data->size();
if (big_content)
{
if (mvd == MOVE_DIRECTION::DOWN)
{
++cursor_position;
// на самом деле получаем его выше, но делаем такой трюк
// т.к. происходит задержка на один ход нажатия клавиши
++current_position;
if (current_position >= size) current_position = size - 1;
bool is_end = size - current_position <= 10;
if (cursor_position >= h - 10 && !is_end)
{
++delta;
cursor_position = h - 10;
}
if (cursor_position >= h) cursor_position = h;
}
if (mvd == MOVE_DIRECTION::UP)
{
--cursor_position;
--current_position;
if (cursor_position <= 10)
--delta;
if (cursor_position < 10 && current_position > 12)
cursor_position = 10;
if (delta < 0)
{
delta = 0;
cursor_position = 0;
}
}
}
}
void navigation::set_scroll()
{
delta = 0;
current_position = 0;
cursor_position = 0;
auto row_size = 26.3f; // высота вы пикселях одной строки списка
auto big_content = height < data->size() * row_size;
if (big_content)
{
// как бы прокручиваем с начала списка
for (const auto& f : *data)
{
if (f.path != selected_file.path)
{
set_delta(MOVE_DIRECTION::DOWN);
}
else
{
set_delta(MOVE_DIRECTION::DOWN);
break;
}
}
}
}
}