400 lines
11 KiB
C++
400 lines
11 KiB
C++
#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;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|