From 44ed461df95a7ca43b8c8efed295d06d247bd54e Mon Sep 17 00:00:00 2001 From: chatlanin Date: Sun, 12 Mar 2023 12:50:05 +0300 Subject: [PATCH] add style and base navigation --- src/rrr/buffer/buffer.hpp | 4 +- src/rrr/content/content.cpp | 119 ++++++++++++++++ src/rrr/content/content.hpp | 12 ++ src/rrr/content/file/file.hpp | 6 +- .../layers/gui/browser/history/history.cpp | 53 ++++++- .../layers/gui/browser/history/history.hpp | 14 ++ .../gui/browser/navigation/navigation.cpp | 134 +++++++++++++----- .../gui/browser/navigation/navigation.hpp | 20 ++- .../layers/gui/browser/preview/preview.cpp | 60 +++++++- .../layers/gui/browser/preview/preview.hpp | 15 ++ src/rrr/utils/func.hpp | 10 ++ src/rrr/utils/types.hpp | 12 ++ 12 files changed, 408 insertions(+), 51 deletions(-) create mode 100644 src/rrr/utils/func.hpp create mode 100644 src/rrr/utils/types.hpp diff --git a/src/rrr/buffer/buffer.hpp b/src/rrr/buffer/buffer.hpp index e306626..3ca970b 100644 --- a/src/rrr/buffer/buffer.hpp +++ b/src/rrr/buffer/buffer.hpp @@ -11,7 +11,7 @@ // value - это то, что тебя там ждет. // т.е. буфер хранит наши прошщлые похождения // и это отображается в history -namespace rrr::database +namespace rrr::buffer { struct content_hash { @@ -29,6 +29,6 @@ namespace rrr::database } }; - inline std::unordered_map buffer; + inline std::unordered_map state; } diff --git a/src/rrr/content/content.cpp b/src/rrr/content/content.cpp index c678063..32d2024 100644 --- a/src/rrr/content/content.cpp +++ b/src/rrr/content/content.cpp @@ -1,5 +1,8 @@ #include "content.hpp" +#include +#include "buffer/buffer.hpp" + namespace rrr { void content::set_pwd(std::filesystem::path p) @@ -32,4 +35,120 @@ namespace rrr break; } } + + int content::get_cursor_position(TYPE_WIN type) const + { + switch (type) + { + case TYPE_WIN::HISTORY: + return get_history_cursor_position(); + break; + case TYPE_WIN::NAVIGATION: + return cursor_position; + break; + case TYPE_WIN::PREVIEW: + return 0; + break; + default: + return 0; + break; + } + } + + int content::get_history_cursor_position() const + { + int history_cursor_position = 0; + tbb::parallel_for(tbb::blocked_range(0, his.data.size()), [&](tbb::blocked_range r) + { + for (int i = r.begin(); i < r.end(); ++i) + if (his.data.at(i).path == PWD) + history_cursor_position = i; + }); + + return history_cursor_position; + } + + int content::get_preview_cursor_position() + { + int preview_cursor_position = 0; + auto pwd = nav.store[PWD].at(cursor_position).path; + + if (buffer::state.contains(pwd)) + { + tbb::parallel_for(tbb::blocked_range(0, prev.data.size()), [&](tbb::blocked_range r) + { + for (int i = r.begin(); i < r.end(); ++i) + if (prev.data.at(i).path == buffer::state[pwd].path) + preview_cursor_position = i; + }); + } + + return preview_cursor_position; + } + + void content::increment_position(int step) + { + cursor_position += step; + check_cursor_position(); + prev.fill(nav.store[PWD].at(cursor_position).path); + } + + void content::check_cursor_position() + { + if (cursor_position == (int)nav.store[PWD].size()) cursor_position = (int)nav.store[PWD].size() - 1; + if (cursor_position < 0) cursor_position = 0; + } + + void content::navigation_right() + { + // ставим новый pwd и заполняем навигацию и историю + PWD = PWD / nav.store[PWD].at(cursor_position).path.filename(); + nav.fill(PWD); + his.fill(PWD); + + // смотрим есть ли в этом pwd какой-то файл в буфере + // проще говоря, были ли мы тут + // и если были, то устанавливаем курсор + if (buffer::state.contains(PWD)) + { + auto f = buffer::state[PWD]; + tbb::parallel_for(tbb::blocked_range(0, nav.store[PWD].size()), [&](tbb::blocked_range r) + { + for (int i = r.begin(); i < r.end(); ++i) + if (nav.store[PWD].at(i).path == f.path) + cursor_position = i; + }); + } + else + { + cursor_position = 0; + } + + // и исходя из позиции курсора заполняем окно предварительного просмотра + prev.fill(nav.store[PWD].at(cursor_position).path); + } + + void content::navigation_left() + { + // буфер заполняется только когда отсюда уходишь + // типа я тут был + buffer::state[PWD] = nav.store[PWD].at(cursor_position); + auto from = PWD; + + // ставим новый pwd и заполняем навигацию и историю + PWD = PWD.parent_path(); + nav.fill(PWD); + his.fill(PWD); + prev.fill(from); + + // тут всегда есть место откуда ты пришел + // т.е. нет возмолжности придти неоткуда + // соответственно находим это место + tbb::parallel_for(tbb::blocked_range(0, nav.store[PWD].size()), [&](tbb::blocked_range r) + { + for (int i = r.begin(); i < r.end(); ++i) + if (nav.store[PWD].at(i).path == from) + cursor_position = i; + }); + } } diff --git a/src/rrr/content/content.hpp b/src/rrr/content/content.hpp index 7310574..f865e5e 100644 --- a/src/rrr/content/content.hpp +++ b/src/rrr/content/content.hpp @@ -15,6 +15,9 @@ namespace rrr using files = std::vector; + // Именно этот класс работает с данными + // вычисляет для каждых данных позиции курсора. какие нужно сейчас отрисовать + // и т.п. Отсюда забираются данные для вывода н экран class content { public: @@ -25,6 +28,10 @@ namespace rrr void set_pwd(std::filesystem::path); void fill(); files* get(TYPE_WIN); + int get_cursor_position(TYPE_WIN) const; + void increment_position(int); + void navigation_right(); + void navigation_left(); private: content_type::navigation nav; @@ -38,5 +45,10 @@ namespace rrr // чтобы не устанавливалась стрелка изначально // полезно при первом открытии окна prev int cursor_position = 0; + + private: + int get_history_cursor_position() const; + int get_preview_cursor_position(); + void check_cursor_position(); }; } diff --git a/src/rrr/content/file/file.hpp b/src/rrr/content/file/file.hpp index bc31769..66efc22 100644 --- a/src/rrr/content/file/file.hpp +++ b/src/rrr/content/file/file.hpp @@ -7,12 +7,12 @@ namespace rrr { + // NONE - просто выводится текст. когда пупка пуста и нет контента вообще // FILE - файл // DIR - дирректория - // TEXT - просто выводится текст enum class file_type { - FILE, DIR, TEXT + NONE, FILE, DIR }; // класс-тип контента @@ -83,7 +83,7 @@ namespace rrr::file_utils } catch(...) { - f.push_back({ path / "no permission", file_type::TEXT, false, false }); + f.push_back({ path / "no permission", file_type::NONE, false, false }); } return f; diff --git a/src/rrr/layers/gui/browser/history/history.cpp b/src/rrr/layers/gui/browser/history/history.cpp index 8a7fb0c..41de1de 100644 --- a/src/rrr/layers/gui/browser/history/history.cpp +++ b/src/rrr/layers/gui/browser/history/history.cpp @@ -5,6 +5,9 @@ namespace rrr::layers::gui void history::on_attach() { BASE_WINDOW_FLAGS(); + + data = cnt->get(TYPE_WIN::HISTORY); + cursor_position = cnt->get_cursor_position(TYPE_WIN::HISTORY); } void history::on_detach() @@ -17,8 +20,47 @@ namespace rrr::layers::gui ImGui::SetNextWindowPos(ImVec2(pos_x, pos_y)); ImGui::SetNextWindowSize(ImVec2(width, height)); + ImGuiStyle& st = ImGui::GetStyle(); + st.Colors[ImGuiCol_WindowBg] = ImVec4(0.13f, 0.14f, 0.18f, 1.00f); + BEGIN_IMGUI_WIN(); + auto pos = ImGui::GetCursorPos(); + pos.x += 17.f; + pos.y += 9.f; // небольшой отступ сверху + ImGui::SetCursorPosY(pos.y); + + int index = 0; + for (auto& item : *data) + { + ImGui::PushID(item.id); + + if (item.type == file_type::DIR) + ImGui::PushStyleColor(ImGuiCol_Text, dir_color); + else + ImGui::PushStyleColor(ImGuiCol_Text, file_color); + + if (cursor_position == index) + { + font = try_engine::style::fonts::get_font(font_type::SEMI_BOLD, 18); + ImGui::PushFont(font); + ImGui::TextUnformatted(">"); + ImGui::SameLine(22.f); + } + else + { + ImGui::SetCursorPosX(pos.x); + font = try_engine::style::fonts::get_font(font_type::MEDIUM, 18); + ImGui::PushFont(font); + } + + ImGui::TextUnformatted(item.path.filename().string().data()); + ++index; + + ImGui::PopFont(); + ImGui::PopStyleColor(); + ImGui::PopID(); + } END_IMGUI_WIN(); } @@ -26,10 +68,13 @@ namespace rrr::layers::gui void history::on_event(system_event& e) { if (e.get_name() == try_engine::system_event::classificator::WINDOW_RESIZE()) - { - height = try_engine::application::get()->get_window()->height() - 40.f; - width = try_engine::application::get()->get_window()->width() / 3.f; - } + resize(); + } + + void history::resize() + { + height = try_engine::application::get()->get_window()->height(); + width = try_engine::application::get()->get_window()->width() / 3.f; } void history::on_event(std::any e, std::any value) diff --git a/src/rrr/layers/gui/browser/history/history.hpp b/src/rrr/layers/gui/browser/history/history.hpp index e0ab35f..5d3b2b6 100644 --- a/src/rrr/layers/gui/browser/history/history.hpp +++ b/src/rrr/layers/gui/browser/history/history.hpp @@ -7,6 +7,8 @@ namespace rrr::layers::gui { class history : public try_engine::layer { + using font_type = try_engine::style::fonts::font_type; + BASE_TYPE_DEFINE(); public: @@ -27,11 +29,23 @@ namespace rrr::layers::gui bool show = true; event_manager* em; content* cnt; + files* data; + int cursor_position = 0; float width = 0.f; float height = 0.f; float pos_x = 0.f; float pos_y = 0.f; + + private: + ImGuiIO& io = ImGui::GetIO(); + ImFontAtlas* atlas = io.Fonts; + ImFont* font; + const ImVec4 dir_color = ImVec4(0.36f, 0.5f, 0.74f, 1.0f); + const ImVec4 file_color = ImVec4(0.9f, 0.9f, 0.9f, 1.0f); + + private: + void resize(); }; } diff --git a/src/rrr/layers/gui/browser/navigation/navigation.cpp b/src/rrr/layers/gui/browser/navigation/navigation.cpp index 13b4b45..dcd2866 100644 --- a/src/rrr/layers/gui/browser/navigation/navigation.cpp +++ b/src/rrr/layers/gui/browser/navigation/navigation.cpp @@ -1,5 +1,7 @@ #include "navigation.hpp" +#include "utils/types.hpp" + #include "logger/logger.hpp" namespace rrr::layers::gui @@ -9,7 +11,6 @@ namespace rrr::layers::gui BASE_WINDOW_FLAGS(); data = cnt->get(TYPE_WIN::NAVIGATION); - font = try_engine::style::fonts::get_font(font_type::MEDIUM, 18); } void navigation::on_detach() @@ -24,66 +25,98 @@ namespace rrr::layers::gui ImGuiStyle& st = ImGui::GetStyle(); st.Colors[ImGuiCol_WindowBg] = ImVec4(0.13f, 0.14f, 0.18f, 1.00f); - - ImGui::PushFont(font); BEGIN_IMGUI_WIN(); auto pos = ImGui::GetCursorPos(); + pos.x += 17.f; + pos.y += 9.f; // небольшой отступ сверху + ImGui::SetCursorPosY(pos.y); int index = 0; for (auto& item : *data) { ImGui::PushID(item.id); - if (item.type == file_type::DIR) - ImGui::PushStyleColor(ImGuiCol_Text, dir_color); - else - ImGui::PushStyleColor(ImGuiCol_Text, file_color); + push_style(item); - if (selected == index) + if (cursor_position == index) { + font = try_engine::style::fonts::get_font(item.is_hidden ? font_type::SEMI_BOLD_ITALIC : font_type::SEMI_BOLD, 18); + ImGui::PushFont(font); ImGui::TextUnformatted(">"); ImGui::SameLine(22.f); } else + { ImGui::SetCursorPosX(pos.x); + font = try_engine::style::fonts::get_font(item.is_hidden ? font_type::MEDIUM_ITALIC : font_type::MEDIUM, 18); + ImGui::PushFont(font); + } - ImGui::TextUnformatted(item.path.filename().string().data()); - - - ImGui::PopStyleColor(); - ImGui::PopID(); + ImGui::TextUnformatted(get_file_content(item).data()); ++index; + + pop_style(item); } - - ImGui::PopFont(); - - END_IMGUI_WIN(); } - void navigation::on_event(try_engine::system_event::event& e) + // HERE начинаем тут + // нужно сделать навигацию влево и вправо + // в прошлыq раз тут сделали стилизацию по типу файлов (скрыты ссылки и тп) + // и затем все это нужно распространить на другие части (history, preview) + // когда делаем навигацию влево и вправо то не меняется центральный контент + // почему то у нас отличаются данные контента в файле content/navigation от + // content/history и content/preview + // там map а у всех других файл. зачем это нужно??? + 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); + + if (f.is_hidden) + font = try_engine::style::fonts::get_font(font_type::MEDIUM_ITALIC, 18); + } + + void navigation::pop_style(file& f) + { + ImGui::PopFont(); + 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 (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()) - { - height = try_engine::application::get()->get_window()->height() - 40.f; - 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; - } - - // HERE начинаем тут - // нужно реализовать обработку клавишь - // и выннести это в движок тоже + resize(); if (e.get_name() == try_engine::system_event::classificator::KEY_PRESSED()) - { - auto key = static_cast(e); - hack::log()(key.get_keycode()); - } - - hack::log()(e.get_name()); + set_selected(e); } void navigation::on_event(std::any e, std::any value) @@ -94,5 +127,38 @@ namespace rrr::layers::gui { } -} + 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::set_selected(system_event& e) + { + auto key = static_cast(e); + + if (key.get_keycode() == try_engine::key::J) + { + cnt->increment_position(STEP_DOWN); + cursor_position = cnt->get_cursor_position(TYPE_WIN::NAVIGATION); + } + + if (key.get_keycode() == try_engine::key::K) + { + cnt->increment_position(STEP_UP); + cursor_position = cnt->get_cursor_position(TYPE_WIN::NAVIGATION); + } + + if (key.get_keycode() == try_engine::key::H) + { + cnt->navigation_left(); + } + + if (key.get_keycode() == try_engine::key::L) + { + cnt->navigation_right(); + } + } +} diff --git a/src/rrr/layers/gui/browser/navigation/navigation.hpp b/src/rrr/layers/gui/browser/navigation/navigation.hpp index 0261e0e..8b0eae5 100644 --- a/src/rrr/layers/gui/browser/navigation/navigation.hpp +++ b/src/rrr/layers/gui/browser/navigation/navigation.hpp @@ -2,9 +2,12 @@ #include "try_engine/try_engine.hpp" #include "rrr/content/content.hpp" +#include "rrr/utils/func.hpp" namespace rrr::layers::gui { + // Все эти классы просто рисуют полученные у контента данные + // Они не вычисляют ни чего, все вычисления делает контент (cnt) class navigation : public try_engine::layer { using font_type = try_engine::style::fonts::font_type; @@ -37,14 +40,25 @@ namespace rrr::layers::gui float pos_y = 0.f; float padding_between_window = 2.f; - int selected = 0; + int cursor_position = 0; + const int STEP_UP = -1; + const int STEP_DOWN = 1; private: ImGuiIO& io = ImGui::GetIO(); ImFontAtlas* atlas = io.Fonts; ImFont* font; - const ImVec4 dir_color = ImVec4(0.36f, 0.5f, 0.74f, 1.0f); - const ImVec4 file_color = ImVec4(0.9f, 0.9f, 0.9f, 1.0f); + const ImVec4 dir_color = func::get_IMGUI_color(91.f, 128.f, 191.f); + const ImVec4 file_color = func::get_IMGUI_color(186.f, 186.f, 186.f); + const ImVec4 link_color = func::get_IMGUI_color(51.f, 95.f, 165.f); + + private: + void resize(); + void set_selected(system_event& e); + void check_selected(); + void push_style(file&); + void pop_style(file&); + std::string get_file_content(file&); }; } diff --git a/src/rrr/layers/gui/browser/preview/preview.cpp b/src/rrr/layers/gui/browser/preview/preview.cpp index f3ade54..39428bd 100644 --- a/src/rrr/layers/gui/browser/preview/preview.cpp +++ b/src/rrr/layers/gui/browser/preview/preview.cpp @@ -5,6 +5,9 @@ namespace rrr::layers::gui void preview::on_attach() { BASE_WINDOW_FLAGS(); + + data = cnt->get(TYPE_WIN::PREVIEW); + cursor_position = cnt->get_cursor_position(TYPE_WIN::PREVIEW); } void preview::on_detach() @@ -17,8 +20,47 @@ namespace rrr::layers::gui ImGui::SetNextWindowPos(ImVec2(pos_x, pos_y)); ImGui::SetNextWindowSize(ImVec2(width, height)); + ImGuiStyle& st = ImGui::GetStyle(); + st.Colors[ImGuiCol_WindowBg] = ImVec4(0.13f, 0.14f, 0.18f, 1.00f); + BEGIN_IMGUI_WIN(); + auto pos = ImGui::GetCursorPos(); + pos.x += 17.f; + pos.y += 9.f; // небольшой отступ сверху + ImGui::SetCursorPosY(pos.y); + + int index = 0; + for (auto& item : *data) + { + ImGui::PushID(item.id); + + if (item.type == file_type::DIR) + ImGui::PushStyleColor(ImGuiCol_Text, dir_color); + else + ImGui::PushStyleColor(ImGuiCol_Text, file_color); + + if (cursor_position == index) + { + font = try_engine::style::fonts::get_font(font_type::SEMI_BOLD, 18); + ImGui::PushFont(font); + ImGui::TextUnformatted(">"); + ImGui::SameLine(22.f); + } + else + { + ImGui::SetCursorPosX(pos.x); + font = try_engine::style::fonts::get_font(font_type::MEDIUM, 18); + ImGui::PushFont(font); + } + + ImGui::TextUnformatted(item.path.filename().string().data()); + ++index; + + ImGui::PopFont(); + ImGui::PopStyleColor(); + ImGui::PopID(); + } END_IMGUI_WIN(); } @@ -26,11 +68,19 @@ namespace rrr::layers::gui void preview::on_event(system_event& e) { if (e.get_name() == try_engine::system_event::classificator::WINDOW_RESIZE()) - { - height = try_engine::application::get()->get_window()->height() - 40.f; - width = try_engine::application::get()->get_window()->width() / 3.f; - pos_x = try_engine::application::get()->get_window()->width() - try_engine::application::get()->get_window()->width() / 3.f; - } + resize(); + } + + void preview::update_content() + { + + } + + void preview::resize() + { + height = try_engine::application::get()->get_window()->height(); + width = try_engine::application::get()->get_window()->width() / 3.f; + pos_x = try_engine::application::get()->get_window()->width() - try_engine::application::get()->get_window()->width() / 3.f; } void preview::on_event(std::any e, std::any value) diff --git a/src/rrr/layers/gui/browser/preview/preview.hpp b/src/rrr/layers/gui/browser/preview/preview.hpp index 9ce25ab..4adc24b 100644 --- a/src/rrr/layers/gui/browser/preview/preview.hpp +++ b/src/rrr/layers/gui/browser/preview/preview.hpp @@ -7,6 +7,8 @@ namespace rrr::layers::gui { class preview : public try_engine::layer { + using font_type = try_engine::style::fonts::font_type; + BASE_TYPE_DEFINE(); public: @@ -27,11 +29,24 @@ namespace rrr::layers::gui bool show = true; event_manager* em; content* cnt; + int cursor_position = 0; + files* data; float width = 0.f; float height = 0.f; float pos_x = 0.f; float pos_y = 0.f; + + private: + ImGuiIO& io = ImGui::GetIO(); + ImFontAtlas* atlas = io.Fonts; + ImFont* font; + const ImVec4 dir_color = ImVec4(0.36f, 0.5f, 0.74f, 1.0f); + const ImVec4 file_color = ImVec4(0.9f, 0.9f, 0.9f, 1.0f); + + private: + void resize(); + void update_content(); }; } diff --git a/src/rrr/utils/func.hpp b/src/rrr/utils/func.hpp new file mode 100644 index 0000000..76f2a92 --- /dev/null +++ b/src/rrr/utils/func.hpp @@ -0,0 +1,10 @@ +#pragma once + +namespace rrr::func +{ + template + inline Color get_IMGUI_color(float r, float g, float b) + { + return Color(r / 255.f, g / 255.f, b / 255.f, 1.f); + } +} diff --git a/src/rrr/utils/types.hpp b/src/rrr/utils/types.hpp new file mode 100644 index 0000000..60d9f81 --- /dev/null +++ b/src/rrr/utils/types.hpp @@ -0,0 +1,12 @@ +#pragma once + +namespace rrr::types +{ + enum class event_type : unsigned int + { + NONE = 0, + NAVIGATION_UP, + NAVIGATION_DOWN + }; +} +