Files
rrr.v2/src/rrr/layers/gui/browser/navigation/navigation.cpp
2023-05-09 10:49:21 +03:00

466 lines
13 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);
current_position = std::distance(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_copy_buffer.empty())
if (f.path == buffers::get_instance().single_copy_buffer[1].path)
file_content = "* " + file_content;
if (!buffers::get_instance().single_cut_buffer.empty())
if (f.path == buffers::get_instance().single_cut_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 (key.get_keycode() == try_engine::key::D)
{
em->execute(types::event_type::SHOW_DELETE_ONE_FILE_DIALOG, selected_file);
freeze = true;
}
// создание файла/директории
if (key.get_keycode() == try_engine::key::A)
{
em->execute(types::event_type::SHOW_CREATE_FILE_DIALOG, nullptr);
freeze = true;
}
// переименование файла/директории
if (key.get_keycode() == try_engine::key::R)
{
em->execute(types::event_type::SHOW_RENAME_FILE_DIALOG, selected_file);
freeze = true;
}
// перемещение в конец списка
if (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 (key.get_keycode() == try_engine::key::P)
{
paste_from_copy();
paste_from_cut();
}
// перемещение на несколько позиций вниз
if (key.get_keycode() == try_engine::key::J)
{
cnt->increment_position((data->size() - current_position) / 4);
selected_file = cnt->get_selected_file(TYPE_WIN::NAVIGATION);
em->execute(types::event_type::NAVIGATION_DOWN, nullptr);
set_delta(MOVE_DIRECTION::DOWN);
set_scroll();
}
// перемещение на несколько позиций вверх
if (key.get_keycode() == try_engine::key::K)
{
cnt->increment_position(current_position - current_position / 4);
selected_file = cnt->get_selected_file(TYPE_WIN::NAVIGATION);
em->execute(types::event_type::NAVIGATION_UP, nullptr);
set_delta(MOVE_DIRECTION::UP);
set_scroll();
}
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_cut_buffer.empty())
buffers::get_instance().single_cut_buffer.clear();
if (buffers::get_instance().single_copy_buffer.empty())
buffers::get_instance().single_copy_buffer[1] = selected_file;
else
if (selected_file.path == buffers::get_instance().single_copy_buffer[1].path)
buffers::get_instance().single_copy_buffer.clear();
else
buffers::get_instance().single_copy_buffer[1] = selected_file;
}
if (key.get_keycode() == try_engine::key::X)
{
// проверяем а может это файл отмечен на копирование
if (!buffers::get_instance().single_copy_buffer.empty())
buffers::get_instance().single_copy_buffer.clear();
if (buffers::get_instance().single_cut_buffer.empty())
buffers::get_instance().single_cut_buffer[1] = selected_file;
else
if (selected_file.path == buffers::get_instance().single_cut_buffer[1].path)
buffers::get_instance().single_cut_buffer.clear();
else
buffers::get_instance().single_cut_buffer[1] = selected_file;
}
// очистка
if (key.get_keycode() == try_engine::key::ESCAPE)
{
buffers::get_instance().single_copy_buffer.clear();
buffers::get_instance().single_cut_buffer.clear();
}
// помощь
if (key.get_keycode() == try_engine::key::F1)
{
em->execute(types::event_type::SHOW_HELP_DIALOG, nullptr);
freeze = true;
}
detect_img();
}
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;
}
}
}
}
void navigation::paste_from_copy()
{
if (buffers::get_instance().single_copy_buffer.empty()) return;
cnt->paste(buffers::get_instance().single_copy_buffer[1].path);
buffers::get_instance().single_copy_buffer.clear();
}
void navigation::paste_from_cut()
{
if (buffers::get_instance().single_cut_buffer.empty()) return;
cnt->cut(buffers::get_instance().single_cut_buffer[1].path);
buffers::get_instance().single_cut_buffer.clear();
selected_file = cnt->get_selected_file(TYPE_WIN::NAVIGATION);
}
void navigation::detect_img()
{
if (selected_file.path.extension() == ".jpg" ||
selected_file.path.extension() == ".jpeg" ||
selected_file.path.extension() == ".png")
em->execute(types::event_type::SHOW_IMG, selected_file.path);
}
}