2020-12-22 18:10:01 +01:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <hex.hpp>
|
|
|
|
|
2021-01-13 17:28:27 +01:00
|
|
|
#include <imgui.h>
|
2021-09-20 23:40:36 +02:00
|
|
|
#include <imgui_internal.h>
|
2021-12-31 01:10:06 +01:00
|
|
|
#include <hex/ui/imgui_imhex_extensions.h>
|
2021-02-25 21:50:57 +01:00
|
|
|
|
2022-07-26 14:59:08 +02:00
|
|
|
#include <fonts/codicons_font.h>
|
2020-12-22 18:10:01 +01:00
|
|
|
|
2021-08-21 13:55:21 +02:00
|
|
|
#include <hex/api/imhex_api.hpp>
|
2023-11-18 14:50:43 +01:00
|
|
|
#include <hex/api/shortcut_manager.hpp>
|
|
|
|
#include <hex/api/event_manager.hpp>
|
2023-12-19 12:22:28 +01:00
|
|
|
#include <hex/api/localization_manager.hpp>
|
|
|
|
|
2021-01-27 14:26:24 +01:00
|
|
|
#include <hex/providers/provider.hpp>
|
2023-04-17 16:18:48 +02:00
|
|
|
#include <hex/providers/provider_data.hpp>
|
2022-02-27 23:25:39 +01:00
|
|
|
#include <hex/helpers/utils.hpp>
|
2020-12-22 18:10:01 +01:00
|
|
|
|
2021-09-08 15:18:24 +02:00
|
|
|
|
2023-11-21 13:47:50 +01:00
|
|
|
#include <map>
|
2020-12-22 18:10:01 +01:00
|
|
|
#include <string>
|
|
|
|
|
|
|
|
namespace hex {
|
|
|
|
|
|
|
|
class View {
|
2023-12-19 12:22:28 +01:00
|
|
|
explicit View(UnlocalizedString unlocalizedName);
|
2023-11-21 13:47:50 +01:00
|
|
|
public:
|
2020-12-22 18:10:01 +01:00
|
|
|
virtual ~View() = default;
|
|
|
|
|
2023-11-21 13:47:50 +01:00
|
|
|
/**
|
|
|
|
* @brief Draws the view
|
|
|
|
* @note Do not override this method. Override drawContent() instead
|
|
|
|
*/
|
|
|
|
virtual void draw() = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Draws the content of the view
|
|
|
|
*/
|
2020-12-22 18:10:01 +01:00
|
|
|
virtual void drawContent() = 0;
|
|
|
|
|
2023-11-21 13:47:50 +01:00
|
|
|
/**
|
|
|
|
* @brief Draws content that should always be visible, even if the view is not open
|
|
|
|
*/
|
|
|
|
virtual void drawAlwaysVisibleContent() { }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Whether or not the view window should be drawn
|
|
|
|
* @return True if the view window should be drawn, false otherwise
|
|
|
|
*/
|
|
|
|
[[nodiscard]] virtual bool shouldDraw() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Whether or not the entire view should be processed
|
|
|
|
* If this returns false, the view will not be drawn and no shortcuts will be handled. This includes things
|
|
|
|
* drawn in the drawAlwaysVisibleContent() function.
|
|
|
|
* @return True if the view should be processed, false otherwise
|
|
|
|
*/
|
2023-11-21 14:38:01 +01:00
|
|
|
[[nodiscard]] virtual bool shouldProcess() const;
|
2023-11-21 13:47:50 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Whether or not the view should have an entry in the view menu
|
|
|
|
* @return True if the view should have an entry in the view menu, false otherwise
|
|
|
|
*/
|
2022-02-01 18:09:40 +01:00
|
|
|
[[nodiscard]] virtual bool hasViewMenuItemEntry() const;
|
2023-11-21 13:47:50 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Gets the minimum size of the view window
|
|
|
|
* @return The minimum size of the view window
|
|
|
|
*/
|
2022-02-01 18:09:40 +01:00
|
|
|
[[nodiscard]] virtual ImVec2 getMinSize() const;
|
2023-11-21 13:47:50 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Gets the maximum size of the view window
|
|
|
|
* @return The maximum size of the view window
|
|
|
|
*/
|
2022-02-01 18:09:40 +01:00
|
|
|
[[nodiscard]] virtual ImVec2 getMaxSize() const;
|
2020-12-22 18:10:01 +01:00
|
|
|
|
2023-11-21 13:47:50 +01:00
|
|
|
/**
|
|
|
|
* @brief Gets additional window flags for the view window
|
|
|
|
* @return Additional window flags for the view window
|
|
|
|
*/
|
|
|
|
[[nodiscard]] virtual ImGuiWindowFlags getWindowFlags() const;
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-02-01 18:09:40 +01:00
|
|
|
[[nodiscard]] bool &getWindowOpenState();
|
|
|
|
[[nodiscard]] const bool &getWindowOpenState() const;
|
2020-12-22 18:10:01 +01:00
|
|
|
|
2023-12-19 12:22:28 +01:00
|
|
|
[[nodiscard]] const UnlocalizedString &getUnlocalizedName() const;
|
2022-01-18 00:10:10 +01:00
|
|
|
[[nodiscard]] std::string getName() const;
|
2020-12-22 18:10:01 +01:00
|
|
|
|
2023-10-30 21:53:44 +01:00
|
|
|
[[nodiscard]] bool didWindowJustOpen();
|
|
|
|
void setWindowJustOpened(bool state);
|
|
|
|
|
2023-12-13 23:03:39 +01:00
|
|
|
void trackViewOpenState();
|
|
|
|
|
2021-09-22 17:56:06 +02:00
|
|
|
static void discardNavigationRequests();
|
2021-01-04 00:19:56 +01:00
|
|
|
|
2023-12-19 12:22:28 +01:00
|
|
|
[[nodiscard]] static std::string toWindowName(const UnlocalizedString &unlocalizedName);
|
2021-03-03 22:26:17 +01:00
|
|
|
|
2023-11-21 13:47:50 +01:00
|
|
|
public:
|
|
|
|
class Window;
|
|
|
|
class Special;
|
|
|
|
class Floating;
|
|
|
|
class Modal;
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2020-12-22 18:10:01 +01:00
|
|
|
private:
|
2023-12-19 12:22:28 +01:00
|
|
|
UnlocalizedString m_unlocalizedViewName;
|
2023-12-13 23:03:39 +01:00
|
|
|
bool m_windowOpen = false, m_prevWindowOpen = false;
|
2023-11-17 14:46:21 +01:00
|
|
|
std::map<Shortcut, ShortcutManager::ShortcutEntry> m_shortcuts;
|
2023-10-30 21:53:44 +01:00
|
|
|
bool m_windowJustOpened = false;
|
2021-12-23 15:11:38 +01:00
|
|
|
|
|
|
|
friend class ShortcutManager;
|
2020-12-22 18:10:01 +01:00
|
|
|
};
|
|
|
|
|
2023-11-21 13:47:50 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief A view that draws a regular window. This should be the default for most views
|
|
|
|
*/
|
|
|
|
class View::Window : public View {
|
|
|
|
public:
|
2023-12-19 12:22:28 +01:00
|
|
|
explicit Window(UnlocalizedString unlocalizedName) : View(std::move(unlocalizedName)) {}
|
2023-11-21 13:47:50 +01:00
|
|
|
|
|
|
|
void draw() final {
|
|
|
|
if (this->shouldDraw()) {
|
|
|
|
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
|
|
|
|
if (ImGui::Begin(View::toWindowName(this->getUnlocalizedName()).c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse | this->getWindowFlags())) {
|
|
|
|
this->drawContent();
|
|
|
|
}
|
|
|
|
ImGui::End();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief A view that doesn't handle any window creation and just draws its content.
|
|
|
|
* This should be used if you intend to draw your own special window
|
|
|
|
*/
|
|
|
|
class View::Special : public View {
|
|
|
|
public:
|
2023-12-19 12:22:28 +01:00
|
|
|
explicit Special(UnlocalizedString unlocalizedName) : View(std::move(unlocalizedName)) {}
|
2023-11-21 13:47:50 +01:00
|
|
|
|
|
|
|
void draw() final {
|
|
|
|
if (this->shouldDraw()) {
|
2023-11-25 12:43:48 +01:00
|
|
|
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
|
2023-11-21 13:47:50 +01:00
|
|
|
this->drawContent();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief A view that draws a floating window. These are the same as regular windows but cannot be docked
|
|
|
|
*/
|
|
|
|
class View::Floating : public View::Window {
|
|
|
|
public:
|
2023-12-19 12:22:28 +01:00
|
|
|
explicit Floating(UnlocalizedString unlocalizedName) : Window(std::move(unlocalizedName)) {}
|
2023-11-21 13:47:50 +01:00
|
|
|
|
2023-12-04 22:17:43 +01:00
|
|
|
[[nodiscard]] ImGuiWindowFlags getWindowFlags() const override { return ImGuiWindowFlags_NoDocking; }
|
2023-11-21 13:47:50 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief A view that draws a modal window. The window will always be drawn on top and will block input to other windows
|
|
|
|
*/
|
|
|
|
class View::Modal : public View {
|
|
|
|
public:
|
2023-12-19 12:22:28 +01:00
|
|
|
explicit Modal(UnlocalizedString unlocalizedName) : View(std::move(unlocalizedName)) {}
|
2023-11-21 13:47:50 +01:00
|
|
|
|
|
|
|
void draw() final {
|
|
|
|
if (this->shouldDraw()) {
|
2023-11-23 13:08:45 +01:00
|
|
|
if (this->getWindowOpenState())
|
|
|
|
ImGui::OpenPopup(View::toWindowName(this->getUnlocalizedName()).c_str());
|
|
|
|
|
2023-12-04 22:32:25 +01:00
|
|
|
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
|
2023-12-17 23:15:52 +01:00
|
|
|
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
|
|
|
|
if (ImGui::BeginPopupModal(View::toWindowName(this->getUnlocalizedName()).c_str(), this->hasCloseButton() ? &this->getWindowOpenState() : nullptr, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_AlwaysAutoResize | this->getWindowFlags())) {
|
2023-11-21 13:47:50 +01:00
|
|
|
this->drawContent();
|
2023-11-21 14:38:01 +01:00
|
|
|
|
|
|
|
ImGui::EndPopup();
|
2023-11-21 13:47:50 +01:00
|
|
|
}
|
2023-12-13 15:08:27 +01:00
|
|
|
|
|
|
|
if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Escape)))
|
|
|
|
this->getWindowOpenState() = false;
|
2023-11-21 13:47:50 +01:00
|
|
|
}
|
|
|
|
}
|
2023-12-17 23:15:52 +01:00
|
|
|
|
|
|
|
virtual bool hasCloseButton() const { return true; }
|
2023-11-21 13:47:50 +01:00
|
|
|
};
|
|
|
|
|
2020-12-22 18:10:01 +01:00
|
|
|
}
|