impr: Clean up entire API and added doc comments

This commit is contained in:
WerWolv
2023-03-21 15:33:43 +01:00
parent d82f0e952f
commit 57a62d0544
30 changed files with 1283 additions and 534 deletions

View File

@@ -41,108 +41,206 @@ namespace hex {
/* Settings Registry. Allows adding of new entries into the ImHex preferences window. */
namespace Settings {
using Callback = std::function<bool(const std::string &, nlohmann::json &)>;
struct Entry {
std::string name;
bool requiresRestart;
Callback callback;
};
namespace impl {
using Callback = std::function<bool(const std::string &, nlohmann::json &)>;
struct Category {
std::string name;
size_t slot = 0;
struct Entry {
std::string name;
bool requiresRestart;
Callback callback;
};
bool operator<(const Category &other) const {
return name < other.name;
}
struct Category {
std::string name;
size_t slot = 0;
explicit operator const std::string &() const {
return name;
}
};
bool operator<(const Category &other) const {
return name < other.name;
}
void load();
void store();
void clear();
explicit operator const std::string &() const {
return name;
}
};
void add(const std::string &unlocalizedCategory, const std::string &unlocalizedName, i64 defaultValue, const Callback &callback, bool requiresRestart = false);
void add(const std::string &unlocalizedCategory, const std::string &unlocalizedName, const std::string &defaultValue, const Callback &callback, bool requiresRestart = false);
void add(const std::string &unlocalizedCategory, const std::string &unlocalizedName, const std::vector<std::string> &defaultValue, const Callback &callback, bool requiresRestart = false);
void load();
void store();
void clear();
std::map<Category, std::vector<Entry>> &getEntries();
std::map<std::string, std::string> &getCategoryDescriptions();
nlohmann::json getSetting(const std::string &unlocalizedCategory, const std::string &unlocalizedName);
nlohmann::json &getSettingsData();
}
/**
* @brief Adds a new integer setting entry
* @param unlocalizedCategory The category of the setting
* @param unlocalizedName The name of the setting
* @param defaultValue The default value of the setting
* @param callback The callback that will be called when the settings item in the preferences window is rendered
* @param requiresRestart Whether the setting requires a restart to take effect
*/
void add(const std::string &unlocalizedCategory, const std::string &unlocalizedName, i64 defaultValue, const impl::Callback &callback, bool requiresRestart = false);
/**
* @brief Adds a new string setting entry
* @param unlocalizedCategory The category of the setting
* @param unlocalizedName The name of the setting
* @param defaultValue The default value of the setting
* @param callback The callback that will be called when the settings item in the preferences window is rendered
* @param requiresRestart Whether the setting requires a restart to take effect
*/
void add(const std::string &unlocalizedCategory, const std::string &unlocalizedName, const std::string &defaultValue, const impl::Callback &callback, bool requiresRestart = false);
/**
* @brief Adds a new string list setting entry
* @param unlocalizedCategory The category of the setting
* @param unlocalizedName The name of the setting
* @param defaultValue The default value of the setting
* @param callback The callback that will be called when the settings item in the preferences window is rendered
* @param requiresRestart Whether the setting requires a restart to take effect
*/
void add(const std::string &unlocalizedCategory, const std::string &unlocalizedName, const std::vector<std::string> &defaultValue, const impl::Callback &callback, bool requiresRestart = false);
/**
* @brief Adds a description to a given category
* @param unlocalizedCategory The name of the category
* @param unlocalizedCategoryDescription The description of the category
*/
void addCategoryDescription(const std::string &unlocalizedCategory, const std::string &unlocalizedCategoryDescription);
/**
* @brief Writes a integer value to the settings file
* @param unlocalizedCategory The category of the setting
* @param unlocalizedName The name of the setting
* @param value The value to write
*/
void write(const std::string &unlocalizedCategory, const std::string &unlocalizedName, i64 value);
/**
* @brief Writes a string value to the settings file
* @param unlocalizedCategory The category of the setting
* @param unlocalizedName The name of the setting
* @param value The value to write
*/
void write(const std::string &unlocalizedCategory, const std::string &unlocalizedName, const std::string &value);
/**
* @brief Writes a string list value to the settings file
* @param unlocalizedCategory The category of the setting
* @param unlocalizedName The name of the setting
* @param value The value to write
*/
void write(const std::string &unlocalizedCategory, const std::string &unlocalizedName, const std::vector<std::string> &value);
/**
* @brief Reads an integer value from the settings file
* @param unlocalizedCategory The category of the setting
* @param unlocalizedName The name of the setting
* @param defaultValue The default value of the setting
* @return The value of the setting
*/
i64 read(const std::string &unlocalizedCategory, const std::string &unlocalizedName, i64 defaultValue);
/**
* @brief Reads a string value from the settings file
* @param unlocalizedCategory The category of the setting
* @param unlocalizedName The name of the setting
* @param defaultValue The default value of the setting
* @return The value of the setting
*/
std::string read(const std::string &unlocalizedCategory, const std::string &unlocalizedName, const std::string &defaultValue);
/**
* @brief Reads a string list value from the settings file
* @param unlocalizedCategory The category of the setting
* @param unlocalizedName The name of the setting
* @param defaultValue The default value of the setting
* @return The value of the setting
*/
std::vector<std::string> read(const std::string &unlocalizedCategory, const std::string &unlocalizedName, const std::vector<std::string> &defaultValue = {});
std::map<Category, std::vector<Entry>> &getEntries();
std::map<std::string, std::string> &getCategoryDescriptions();
nlohmann::json getSetting(const std::string &unlocalizedCategory, const std::string &unlocalizedName);
nlohmann::json &getSettingsData();
}
/* Command Palette Command Registry. Allows adding of new commands to the command palette */
namespace CommandPaletteCommands {
enum class Type : u32
{
enum class Type : u32 {
SymbolCommand,
KeywordCommand
};
struct QueryResult {
std::string name;
std::function<void(std::string)> callback;
};
namespace impl {
using DisplayCallback = std::function<std::string(std::string)>;
using ExecuteCallback = std::function<void(std::string)>;
using QueryCallback = std::function<std::vector<QueryResult>(std::string)>;
struct QueryResult {
std::string name;
std::function<void(std::string)> callback;
};
struct Entry {
Type type;
std::string command;
std::string unlocalizedDescription;
DisplayCallback displayCallback;
ExecuteCallback executeCallback;
};
using DisplayCallback = std::function<std::string(std::string)>;
using ExecuteCallback = std::function<void(std::string)>;
using QueryCallback = std::function<std::vector<QueryResult>(std::string)>;
struct Handler {
Type type;
std::string command;
QueryCallback queryCallback;
DisplayCallback displayCallback;
};
struct Entry {
Type type;
std::string command;
std::string unlocalizedDescription;
DisplayCallback displayCallback;
ExecuteCallback executeCallback;
};
struct Handler {
Type type;
std::string command;
QueryCallback queryCallback;
DisplayCallback displayCallback;
};
std::vector<impl::Entry> &getEntries();
std::vector<impl::Handler> &getHandlers();
}
/**
* @brief Adds a new command to the command palette
* @param type The type of the command
* @param command The command to add
* @param unlocalizedDescription The description of the command
* @param displayCallback The callback that will be called when the command is displayed in the command palette
* @param executeCallback The callback that will be called when the command is executed
*/
void add(
Type type,
const std::string &command,
const std::string &unlocalizedDescription,
const DisplayCallback &displayCallback,
const ExecuteCallback &executeCallback = [](auto) {});
const impl::DisplayCallback &displayCallback,
const impl::ExecuteCallback &executeCallback = [](auto) {});
/**
* @brief Adds a new command handler to the command palette
* @param type The type of the command
* @param command The command to add
* @param unlocalizedDescription The description of the command
* @param queryCallback The callback that will be called when the command palette wants to load the name and callback items
* @param displayCallback The callback that will be called when the command is displayed in the command palette
*/
void addHandler(
Type type,
const std::string &command,
const QueryCallback &queryCallback,
const DisplayCallback &displayCallback);
std::vector<Entry> &getEntries();
std::vector<Handler> &getHandlers();
const impl::QueryCallback &queryCallback,
const impl::DisplayCallback &displayCallback);
}
/* Pattern Language Function Registry. Allows adding of new functions that may be used inside the pattern language */
namespace PatternLanguage {
using VisualizerFunctionCallback = std::function<void(pl::ptrn::Pattern&, pl::ptrn::Iteratable&, bool, std::span<const pl::core::Token::Literal>)>;
namespace impl {
using VisualizerFunctionCallback = std::function<void(pl::ptrn::Pattern&, pl::ptrn::Iteratable&, bool, std::span<const pl::core::Token::Literal>)>;
struct FunctionDefinition {
pl::api::Namespace ns;
std::string name;
@@ -159,20 +257,52 @@ namespace hex {
};
std::map<std::string, Visualizer> &getVisualizers();
std::map<std::string, pl::api::PragmaHandler> &getPragmas();
std::vector<impl::FunctionDefinition> &getFunctions();
}
/**
* @brief Configures the pattern language runtime using ImHex's default settings
* @param runtime The pattern language runtime to configure
* @param provider The provider to use for data access
*/
void configureRuntime(pl::PatternLanguage &runtime, prv::Provider *provider);
/**
* @brief Adds a new pragma to the pattern language
* @param name The name of the pragma
* @param handler The handler that will be called when the pragma is encountered
*/
void addPragma(const std::string &name, const pl::api::PragmaHandler &handler);
/**
* @brief Adds a new function to the pattern language
* @param ns The namespace of the function
* @param name The name of the function
* @param parameterCount The amount of parameters the function takes
* @param func The function callback
*/
void addFunction(const pl::api::Namespace &ns, const std::string &name, pl::api::FunctionParameterCount parameterCount, const pl::api::FunctionCallback &func);
/**
* @brief Adds a new dangerous function to the pattern language
* @note Dangerous functions are functions that require the user to explicitly allow them to be used
* @param ns The namespace of the function
* @param name The name of the function
* @param parameterCount The amount of parameters the function takes
* @param func The function callback
*/
void addDangerousFunction(const pl::api::Namespace &ns, const std::string &name, pl::api::FunctionParameterCount parameterCount, const pl::api::FunctionCallback &func);
void addVisualizer(const std::string &name, const VisualizerFunctionCallback &func, u32 parameterCount);
std::map<std::string, pl::api::PragmaHandler> &getPragmas();
std::vector<impl::FunctionDefinition> &getFunctions();
/**
* @brief Adds a new visualizer to the pattern language
* @note Visualizers are extensions to the [[hex::visualize]] attribute, used to visualize data
* @param name The name of the visualizer
* @param func The function callback
* @param parameterCount The amount of parameters the function takes
*/
void addVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &func, u32 parameterCount);
}
@@ -182,18 +312,27 @@ namespace hex {
namespace impl {
void add(View *view);
std::map<std::string, View *> &getEntries();
}
/**
* @brief Adds a new view to ImHex
* @tparam T The custom view class that extends View
* @tparam Args Arguments types
* @param args Arguments passed to the constructor of the view
*/
template<std::derived_from<View> T, typename... Args>
void add(Args &&...args) {
return impl::add(new T(std::forward<Args>(args)...));
}
std::map<std::string, View *> &getEntries();
/**
* @brief Gets a view by its unlocalized name
* @param unlocalizedName The unlocalized name of the view
* @return The view if it exists, nullptr otherwise
*/
View *getViewByName(const std::string &unlocalizedName);
}
/* Tools Registry. Allows adding new entries to the tools window */
@@ -209,11 +348,16 @@ namespace hex {
bool detached;
};
std::vector<impl::Entry> &getEntries();
}
/**
* @brief Adds a new tool to the tools window
* @param unlocalizedName The unlocalized name of the tool
* @param function The function that will be called to draw the tool
*/
void add(const std::string &unlocalizedName, const impl::Callback &function);
std::vector<impl::Entry> &getEntries();
}
/* Data Inspector Registry. Allows adding of new types to the data inspector */
@@ -240,12 +384,28 @@ namespace hex {
std::optional<impl::EditingFunction> editingFunction;
};
std::vector<impl::Entry> &getEntries();
}
/**
* @brief Adds a new entry to the data inspector
* @param unlocalizedName The unlocalized name of the entry
* @param requiredSize The minimum required number of bytes available for the entry to appear
* @param displayGeneratorFunction The function that will be called to generate the display function
* @param editingFunction The function that will be called to edit the data
*/
void add(const std::string &unlocalizedName, size_t requiredSize, impl::GeneratorFunction displayGeneratorFunction, std::optional<impl::EditingFunction> editingFunction = std::nullopt);
void add(const std::string &unlocalizedName, size_t requiredSize, size_t maxSize, impl::GeneratorFunction displayGeneratorFunction, std::optional<impl::EditingFunction> editingFunction = std::nullopt);
std::vector<impl::Entry> &getEntries();
/**
* @brief Adds a new entry to the data inspector
* @param unlocalizedName The unlocalized name of the entry
* @param requiredSize The minimum required number of bytes available for the entry to appear
* @param maxSize The maximum number of bytes to read from the data
* @param displayGeneratorFunction The function that will be called to generate the display function
* @param editingFunction The function that will be called to edit the data
*/
void add(const std::string &unlocalizedName, size_t requiredSize, size_t maxSize, impl::GeneratorFunction displayGeneratorFunction, std::optional<impl::EditingFunction> editingFunction = std::nullopt);
}
/* Data Processor Node Registry. Allows adding new processor nodes to be used in the data processor */
@@ -263,9 +423,18 @@ namespace hex {
void add(const Entry &entry);
std::vector<impl::Entry> &getEntries();
}
/**
* @brief Adds a new node to the data processor
* @tparam T The custom node class that extends dp::Node
* @tparam Args Arguments types
* @param unlocalizedCategory The unlocalized category name of the node
* @param unlocalizedName The unlocalized name of the node
* @param args Arguments passed to the constructor of the node
*/
template<std::derived_from<dp::Node> T, typename... Args>
void add(const std::string &unlocalizedCategory, const std::string &unlocalizedName, Args &&...args) {
add(impl::Entry {
@@ -279,18 +448,29 @@ namespace hex {
});
}
/**
* @brief Adds a separator to the data processor right click menu
*/
void addSeparator();
std::vector<impl::Entry> &getEntries();
}
/* Language Registry. Allows together with the LangEntry class and the _lang user defined literal to add new languages */
namespace Language {
/**
* @brief Loads localization information from json data
* @param data The language data
*/
void addLocalization(const nlohmann::json &data);
std::map<std::string, std::string> &getLanguages();
std::map<std::string, std::vector<LanguageDefinition>> &getLanguageDefinitions();
namespace impl {
std::map<std::string, std::string> &getLanguages();
std::map<std::string, std::vector<LanguageDefinition>> &getLanguageDefinitions();
}
}
/* Interface Registry. Allows adding new items to various interfaces */
@@ -334,31 +514,96 @@ namespace hex {
constexpr static auto SeparatorValue = "$SEPARATOR$";
constexpr static auto SubMenuValue = "$SUBMENU$";
std::multimap<u32, impl::MainMenuItem> &getMainMenuItems();
std::multimap<u32, impl::MenuItem> &getMenuItems();
std::vector<impl::DrawCallback> &getWelcomeScreenEntries();
std::vector<impl::DrawCallback> &getFooterItems();
std::vector<impl::DrawCallback> &getToolbarItems();
std::vector<impl::SidebarItem> &getSidebarItems();
std::vector<impl::TitleBarButton> &getTitleBarButtons();
std::vector<impl::Layout> &getLayouts();
}
/**
* @brief Adds a new top-level main menu entry
* @param unlocalizedName The unlocalized name of the entry
* @param priority The priority of the entry. Lower values are displayed first
*/
void registerMainMenuItem(const std::string &unlocalizedName, u32 priority);
/**
* @brief Adds a new main menu entry
* @param unlocalizedMainMenuNames The unlocalized names of the main menu entries
* @param priority The priority of the entry. Lower values are displayed first
* @param shortcut The shortcut to use for the entry
* @param function The function to call when the entry is clicked
* @param enabledCallback The function to call to determine if the entry is enabled
* @param view The view to use for the entry. If nullptr, the shortcut will work globally
*/
void addMenuItem(const std::vector<std::string> &unlocalizedMainMenuNames, u32 priority, const Shortcut &shortcut, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback = []{ return true; }, View *view = nullptr);
/**
* @brief Adds a new main menu sub-menu entry
* @param unlocalizedMainMenuNames The unlocalized names of the main menu entries
* @param priority The priority of the entry. Lower values are displayed first
* @param function The function to call when the entry is clicked
* @param enabledCallback The function to call to determine if the entry is enabled
* @param view The view to use for the entry. If nullptr, the shortcut will work globally
*/
void addMenuItemSubMenu(std::vector<std::string> unlocalizedMainMenuNames, u32 priority, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback = []{ return true; });
/**
* @brief Adds a new main menu separator
* @param unlocalizedMainMenuNames The unlocalized names of the main menu entries
* @param priority The priority of the entry. Lower values are displayed first
*/
void addMenuItemSeparator(std::vector<std::string> unlocalizedMainMenuNames, u32 priority);
/**
* @brief Adds a new welcome screen entry
* @param function The function to call to draw the entry
*/
void addWelcomeScreenEntry(const impl::DrawCallback &function);
/**
* @brief Adds a new footer item
* @param function The function to call to draw the item
*/
void addFooterItem(const impl::DrawCallback &function);
/**
* @brief Adds a new toolbar item
* @param function The function to call to draw the item
*/
void addToolbarItem(const impl::DrawCallback &function);
/**
* @brief Adds a new sidebar item
* @param icon The icon to use for the item
* @param function The function to call to draw the item
*/
void addSidebarItem(const std::string &icon, const impl::DrawCallback &function);
/**
* @brief Adds a new title bar button
* @param icon The icon to use for the button
* @param unlocalizedTooltip The unlocalized tooltip to use for the button
* @param function The function to call when the button is clicked
*/
void addTitleBarButton(const std::string &icon, const std::string &unlocalizedTooltip, const impl::ClickCallback &function);
/**
* @brief Adds a new layout definition to the Layout menu
* @param unlocalizedName The unlocalized name of the layout
* @param function The function to call to setup the layout
*/
void addLayout(const std::string &unlocalizedName, const impl::LayoutFunction &function);
std::multimap<u32, impl::MainMenuItem> &getMainMenuItems();
std::multimap<u32, impl::MenuItem> &getMenuItems();
std::vector<impl::DrawCallback> &getWelcomeScreenEntries();
std::vector<impl::DrawCallback> &getFooterItems();
std::vector<impl::DrawCallback> &getToolbarItems();
std::vector<impl::SidebarItem> &getSidebarItems();
std::vector<impl::TitleBarButton> &getTitleBarButtons();
std::vector<impl::Layout> &getLayouts();
}
/* Provider Registry. Allows adding new data providers to be created from the UI */
@@ -368,8 +613,15 @@ namespace hex {
void addProviderName(const std::string &unlocalizedName);
std::vector<std::string> &getEntries();
}
/**
* @brief Adds a new provider to the list of providers
* @tparam T The provider type that extends hex::prv::Provider
* @param addToList Whether to display the provider in the Other Providers list in the welcome screen and File menu
*/
template<std::derived_from<hex::prv::Provider> T>
void add(bool addToList = true) {
auto typeName = T().getTypeName();
@@ -389,10 +641,9 @@ namespace hex {
impl::addProviderName(typeName);
}
std::vector<std::string> &getEntries();
}
/* Data Formatter Registry. Allows adding formatters that are used in the Copy-As menu for example */
namespace DataFormatter {
namespace impl {
@@ -403,14 +654,21 @@ namespace hex {
Callback callback;
};
std::vector<impl::Entry> &getEntries();
}
void add(const std::string &unlocalizedName, const impl::Callback &callback);
std::vector<impl::Entry> &getEntries();
/**
* @brief Adds a new data formatter
* @param unlocalizedName The unlocalized name of the formatter
* @param callback The function to call to format the data
*/
void add(const std::string &unlocalizedName, const impl::Callback &callback);
}
/* File Handler Registry. Allows adding handlers for opening files specific file types */
namespace FileHandler {
namespace impl {
@@ -421,14 +679,20 @@ namespace hex {
Callback callback;
};
std::vector<impl::Entry> &getEntries();
}
/**
* @brief Adds a new file handler
* @param extensions The file extensions to handle
* @param callback The function to call to handle the file
*/
void add(const std::vector<std::string> &extensions, const impl::Callback &callback);
std::vector<impl::Entry> &getEntries();
}
/* Hex Editor Registry. Allows adding new functionality to the hex editor */
namespace HexEditor {
class DataVisualizer {
@@ -462,6 +726,12 @@ namespace hex {
}
/**
* @brief Adds a new cell data visualizer
* @tparam T The data visualizer type that extends hex::DataVisualizer
* @param unlocalizedName The unlocalized name of the data visualizer
* @param args The arguments to pass to the constructor of the data visualizer
*/
template<std::derived_from<DataVisualizer> T, typename... Args>
void addDataVisualizer(const std::string &unlocalizedName, Args &&...args) {
return impl::addDataVisualizer(unlocalizedName, new T(std::forward<Args>(args)...));
@@ -469,6 +739,7 @@ namespace hex {
}
/* Hash Registry. Allows adding new hashes to the Hash view */
namespace Hashes {
class Hash {
@@ -534,6 +805,12 @@ namespace hex {
void add(Hash* hash);
}
/**
* @brief Adds a new hash
* @tparam T The hash type that extends hex::Hash
* @param args The arguments to pass to the constructor of the hash
*/
template<typename T, typename ... Args>
void add(Args && ... args) {
impl::add(new T(std::forward<Args>(args)...));

View File

@@ -10,68 +10,98 @@
#include <hex/api/imhex_api.hpp>
#include <hex/helpers/fs.hpp>
#define EVENT_DEF(event_name, ...) \
struct event_name final : public hex::Event<__VA_ARGS__> { \
constexpr static auto id = [] { return hex::EventId(); }(); \
explicit event_name(Callback func) noexcept : Event(std::move(func)) { } \
#define EVENT_DEF(event_name, ...) \
struct event_name final : public hex::impl::Event<__VA_ARGS__> { \
constexpr static auto id = [] { return hex::impl::EventId(); }(); \
explicit event_name(Callback func) noexcept : Event(std::move(func)) { } \
}
struct GLFWwindow;
namespace hex {
class EventId {
public:
explicit constexpr EventId(const char *func = __builtin_FUNCTION(), u32 line = __builtin_LINE()) {
this->m_hash = line ^ 987654321;
for (auto c : std::string_view(func)) {
this->m_hash = (this->m_hash >> 5) | (this->m_hash << 27);
this->m_hash ^= c;
namespace impl {
class EventId {
public:
explicit constexpr EventId(const char *func = __builtin_FUNCTION(), u32 line = __builtin_LINE()) {
this->m_hash = line ^ 987654321;
for (auto c : std::string_view(func)) {
this->m_hash = (this->m_hash >> 5) | (this->m_hash << 27);
this->m_hash ^= c;
}
}
}
constexpr bool operator==(const EventId &rhs) const = default;
constexpr bool operator==(const EventId &rhs) const = default;
private:
u32 m_hash;
};
private:
u32 m_hash;
};
struct EventBase {
EventBase() noexcept = default;
};
struct EventBase {
EventBase() noexcept = default;
};
template<typename... Params>
struct Event : public EventBase {
using Callback = std::function<void(Params...)>;
template<typename... Params>
struct Event : public EventBase {
using Callback = std::function<void(Params...)>;
explicit Event(Callback func) noexcept : m_func(std::move(func)) { }
explicit Event(Callback func) noexcept : m_func(std::move(func)) { }
void operator()(Params... params) const noexcept {
this->m_func(params...);
}
void operator()(Params... params) const noexcept {
this->m_func(params...);
}
private:
Callback m_func;
};
private:
Callback m_func;
};
}
/**
* @brief The EventManager allows subscribing to and posting events to different parts of the program.
* To create a new event, use the EVENT_DEF macro. This will create a new event type with the given name and parameters
*/
class EventManager {
public:
using EventList = std::list<std::pair<EventId, EventBase *>>;
using EventList = std::list<std::pair<impl::EventId, impl::EventBase *>>;
/**
* @brief Subscribes to an event
* @tparam E Event
* @param function Function to call when the event is posted
* @return Token to unsubscribe from the event
*/
template<typename E>
static EventList::iterator subscribe(typename E::Callback function) {
return s_events.insert(s_events.end(), std::make_pair(E::id, new E(function)));
}
/**
* @brief Subscribes to an event
* @tparam E Event
* @param token Unique token to register the event to. Later required to unsubscribe again
* @param function Function to call when the event is posted
*/
template<typename E>
static void subscribe(void *token, typename E::Callback function) {
s_tokenStore.insert(std::make_pair(token, subscribe<E>(function)));
}
static void unsubscribe(EventList::iterator iter) noexcept {
s_events.remove(*iter);
/**
* @brief Unsubscribes from an event
* @param token Token returned by subscribe
*/
static void unsubscribe(const EventList::iterator &token) noexcept {
s_events.remove(*token);
}
/**
* @brief Unsubscribes from an event
* @tparam E Event
* @param token Token passed to subscribe
*/
template<typename E>
static void unsubscribe(void *token) noexcept {
auto iter = std::find_if(s_tokenStore.begin(), s_tokenStore.end(), [&](auto &item) {
@@ -85,6 +115,11 @@ namespace hex {
}
/**
* @brief Posts an event to all subscribers of it
* @tparam E Event
* @param args Arguments to pass to the event
*/
template<typename E>
static void post(auto &&...args) noexcept {
for (const auto &[id, event] : s_events) {
@@ -93,6 +128,9 @@ namespace hex {
}
}
/**
* @brief Unsubscribe all subscribers from all events
*/
static void clear() noexcept {
s_events.clear();
s_tokenStore.clear();

View File

@@ -26,13 +26,7 @@ namespace hex {
namespace ImHexApi {
namespace Common {
void closeImHex(bool noQuestions = false);
void restartImHex();
}
/* Functions to query information from the Hex Editor and interact with it */
namespace HexEditor {
using TooltipFunction = std::function<void(u64, const u8*, size_t)>;
@@ -87,32 +81,127 @@ namespace hex {
void setCurrentSelection(std::optional<ProviderRegion> region);
}
/**
* @brief Adds a background color highlighting to the Hex Editor
* @param region The region to highlight
* @param color The color to use for the highlighting
* @return Unique ID used to remove the highlighting again later
*/
u32 addBackgroundHighlight(const Region &region, color_t color);
/**
* @brief Removes a background color highlighting from the Hex Editor
* @param id The ID of the highlighting to remove
*/
void removeBackgroundHighlight(u32 id);
/**
* @brief Adds a foreground color highlighting to the Hex Editor
* @param region The region to highlight
* @param color The color to use for the highlighting
* @return Unique ID used to remove the highlighting again later
*/
u32 addForegroundHighlight(const Region &region, color_t color);
/**
* @brief Removes a foreground color highlighting from the Hex Editor
* @param id The ID of the highlighting to remove
*/
void removeForegroundHighlight(u32 id);
/**
* @brief Adds a hover tooltip to the Hex Editor
* @param region The region to add the tooltip to
* @param value Text to display in the tooltip
* @param color The color of the tooltip
* @return Unique ID used to remove the tooltip again later
*/
u32 addTooltip(Region region, std::string value, color_t color);
/**
* @brief Removes a hover tooltip from the Hex Editor
* @param id The ID of the tooltip to remove
*/
void removeTooltip(u32 id);
/**
* @brief Adds a background color highlighting to the Hex Editor using a callback function
* @param function Function that draws the highlighting based on the hovered region
* @return Unique ID used to remove the highlighting again later
*/
u32 addTooltipProvider(TooltipFunction function);
/**
* @brief Removes a background color highlighting from the Hex Editor
* @param id The ID of the highlighting to remove
*/
void removeTooltipProvider(u32 id);
/**
* @brief Adds a background color highlighting to the Hex Editor using a callback function
* @param function Function that draws the highlighting based on the hovered region
* @return Unique ID used to remove the highlighting again later
*/
u32 addBackgroundHighlightingProvider(const impl::HighlightingFunction &function);
/**
* @brief Removes a background color highlighting from the Hex Editor
* @param id The ID of the highlighting to remove
*/
void removeBackgroundHighlightingProvider(u32 id);
/**
* @brief Adds a foreground color highlighting to the Hex Editor using a callback function
* @param function Function that draws the highlighting based on the hovered region
* @return Unique ID used to remove the highlighting again later
*/
u32 addForegroundHighlightingProvider(const impl::HighlightingFunction &function);
/**
* @brief Removes a foreground color highlighting from the Hex Editor
* @param id The ID of the highlighting to remove
*/
void removeForegroundHighlightingProvider(u32 id);
/**
* @brief Checks if there's a valid selection in the Hex Editor right now
*/
bool isSelectionValid();
/**
* @brief Gets the current selection in the Hex Editor
* @return The current selection
*/
std::optional<ProviderRegion> getSelection();
/**
* @brief Sets the current selection in the Hex Editor
* @param region The region to select
* @param provider The provider to select the region in
*/
void setSelection(const Region &region, prv::Provider *provider = nullptr);
/**
* @brief Sets the current selection in the Hex Editor
* @param region The region to select
*/
void setSelection(const ProviderRegion &region);
/**
* @brief Sets the current selection in the Hex Editor
* @param address The address to select
* @param size The size of the selection
* @param provider The provider to select the region in
*/
void setSelection(u64 address, size_t size, prv::Provider *provider = nullptr);
}
/* Functions to interact with Bookmarks */
namespace Bookmarks {
struct Entry {
@@ -124,10 +213,19 @@ namespace hex {
bool locked;
};
/**
* @brief Adds a new bookmark
* @param address The address of the bookmark
* @param size The size of the bookmark
* @param name The name of the bookmark
* @param comment The comment of the bookmark
* @param color The color of the bookmark or 0x00 for the default color
*/
void add(u64 address, size_t size, const std::string &name, const std::string &comment, color_t color = 0x00000000);
}
/* Functions to interact with the loaded data provider */
namespace Provider {
namespace impl {
@@ -137,30 +235,82 @@ namespace hex {
}
/**
* @brief Gets the currently selected data provider
* @return The currently selected data provider
*/
prv::Provider *get();
/**
* @brief Gets a list of all currently loaded data providers
* @return The currently loaded data providers
*/
const std::vector<prv::Provider *> &getProviders();
/**
* @brief Sets the currently selected data provider
* @param index Index of the provider to select
*/
void setCurrentProvider(u32 index);
/**
* @brief Checks whether the currently selected data provider is valid
* @return Whether the currently selected data provider is valid
*/
bool isValid();
/**
* @brief Marks the currently selected data provider as dirty
*/
void markDirty();
/**
* @brief Marks the currently selected data provider as clean
*/
void resetDirty();
/**
* @brief Checks whether the currently selected data provider is dirty
* @return Whether the currently selected data provider is dirty
*/
bool isDirty();
/**
* @brief Adds a newly created provider to the list of providers
* @param provider The provider to add
* @param skipLoadInterface Whether to skip loading the provider's loading interface
*/
void add(prv::Provider *provider, bool skipLoadInterface = false);
/**
* @brief Creates a new provider and adds it to the list of providers
* @tparam T The type of the provider to create
* @param args Arguments to pass to the provider's constructor
*/
template<std::derived_from<prv::Provider> T>
void add(auto &&...args) {
add(new T(std::forward<decltype(args)>(args)...));
}
/**
* @brief Removes a provider from the list of providers
* @param provider The provider to remove
* @param noQuestions Whether to skip asking the user for confirmation
*/
void remove(prv::Provider *provider, bool noQuestions = false);
/**
* @brief Creates a new provider using its unlocalized name
* @param unlocalizedName The unlocalized name of the provider to create
* @param skipLoadInterface Whether to skip loading the provider's loading interface
*/
prv::Provider* createProvider(const std::string &unlocalizedName, bool skipLoadInterface = false);
}
/* Functions to interact with various ImHex system settings */
namespace System {
namespace impl {
@@ -204,37 +354,148 @@ namespace hex {
Error
};
/**
* @brief Closes ImHex
* @param noQuestions Whether to skip asking the user for confirmation
*/
void closeImHex(bool noQuestions = false);
/**
* @brief Restarts ImHex
*/
void restartImHex();
/**
* @brief Sets the progress bar in the task bar
* @param state The state of the progress bar
* @param type The type of the progress bar progress
* @param progress The progress of the progress bar
*/
void setTaskBarProgress(TaskProgressState state, TaskProgressType type, u32 progress);
/**
* @brief Gets the current program arguments
* @return The current program arguments
*/
const ProgramArguments &getProgramArguments();
/**
* @brief Gets a program argument
* @param index The index of the argument to get
* @return The argument at the given index
*/
std::optional<std::u8string> getProgramArgument(int index);
/**
* @brief Gets the current target FPS
* @return The current target FPS
*/
float getTargetFPS();
/**
* @brief Sets the target FPS
* @param fps The target FPS
*/
void setTargetFPS(float fps);
/**
* @brief Gets the current global scale
* @return The current global scale
*/
float getGlobalScale();
/**
* @brief Gets the current native scale
* @return The current native scale
*/
float getNativeScale();
/**
* @brief Gets the current main window position
* @return Position of the main window
*/
ImVec2 getMainWindowPosition();
/**
* @brief Gets the current main window size
* @return Size of the main window
*/
ImVec2 getMainWindowSize();
/**
* @brief Gets the current main dock space ID
* @return ID of the main dock space
*/
ImGuiID getMainDockSpaceId();
/**
* @brief Checks if borderless window mode is enabled currently
* @return Whether borderless window mode is enabled
*/
bool isBorderlessWindowModeEnabled();
/**
* @brief Gets the init arguments passed to ImHex from the splash screen
* @return Init arguments
*/
std::map<std::string, std::string> &getInitArguments();
constexpr static float DefaultFontSize = 13.0;
/**
* @brief Gets the current custom font path
* @return The current custom font path
*/
const std::filesystem::path &getCustomFontPath();
/**
* @brief Gets the current font size
* @return The current font size
*/
float getFontSize();
/**
* @brief Sets if ImHex should follow the system theme
* @param enabled Whether to follow the system theme
*/
void enableSystemThemeDetection(bool enabled);
/**
* @brief Checks if ImHex follows the system theme
* @return Whether ImHex follows the system theme
*/
bool usesSystemThemeDetection();
/**
* @brief Gets the currently set additional folder paths
* @return The currently set additional folder paths
*/
const std::vector<std::filesystem::path> &getAdditionalFolderPaths();
/**
* @brief Sets the additional folder paths
* @param paths The additional folder paths
*/
void setAdditionalFolderPaths(const std::vector<std::filesystem::path> &paths);
/**
* @brief Gets the current GPU vendor
* @return The current GPU vendor
*/
const std::string &getGPUVendor();
/**
* @brief Checks if ImHex is running in portable mode
* @return Whether ImHex is running in portable mode
*/
bool isPortableVersion();
}

View File

@@ -363,14 +363,54 @@ namespace hex {
return result;
}
/**
* @brief The ShortcutManager handles global and view-specific shortcuts.
* New shortcuts can be constructed using the + operator on Key objects. For example: CTRL + ALT + Keys::A
*/
class ShortcutManager {
public:
/**
* @brief Add a global shortcut. Global shortcuts can be triggered regardless of what view is currently focused
* @param shortcut The shortcut to add.
* @param callback The callback to call when the shortcut is triggered.
*/
static void addGlobalShortcut(const Shortcut &shortcut, const std::function<void()> &callback);
/**
* @brief Add a view-specific shortcut. View-specific shortcuts can only be triggered when the specified view is focused.
* @param view The view to add the shortcut to.
* @param shortcut The shortcut to add.
* @param callback The callback to call when the shortcut is triggered.
*/
static void addShortcut(View *view, const Shortcut &shortcut, const std::function<void()> &callback);
/**
* @brief Process a key event. This should be called from the main loop.
* @param currentView Current view to process
* @param ctrl Whether the CTRL key is pressed
* @param alt Whether the ALT key is pressed
* @param shift Whether the SHIFT key is pressed
* @param super Whether the SUPER key is pressed
* @param focused Whether the current view is focused
* @param keyCode The key code of the key that was pressed
*/
static void process(View *currentView, bool ctrl, bool alt, bool shift, bool super, bool focused, u32 keyCode);
/**
* @brief Process a key event. This should be called from the main loop.
* @param ctrl Whether the CTRL key is pressed
* @param alt Whether the ALT key is pressed
* @param shift Whether the SHIFT key is pressed
* @param super Whether the SUPER key is pressed
* @param keyCode The key code of the key that was pressed
*/
static void processGlobals(bool ctrl, bool alt, bool shift, bool super, u32 keyCode);
/**
* @brief Clear all shortcuts
*/
static void clearShortcuts();
private:

View File

@@ -14,42 +14,104 @@
namespace hex {
/**
* @brief Project file manager
*
* The project file manager is used to load and store project files. It is used by all features of ImHex
* that want to store any data to a Project File.
*
*/
class ProjectFile {
public:
struct Handler {
using Function = std::function<bool(const std::fs::path &, Tar &tar)>;
std::fs::path basePath;
bool required;
Function load, store;
std::fs::path basePath; //< Base path for where to store the files in the project file
bool required; //< If true, ImHex will display an error if this handler fails to load or store data
Function load, store; //< Functions to load and store data
};
struct ProviderHandler {
using Function = std::function<bool(prv::Provider *provider, const std::fs::path &, Tar &tar)>;
std::fs::path basePath;
bool required;
Function load, store;
std::fs::path basePath; //< Base path for where to store the files in the project file
bool required; //< If true, ImHex will display an error if this handler fails to load or store data
Function load, store; //< Functions to load and store data
};
/**
* @brief Load a project file
*
* @param filePath Path to the project file
* @return true if the project file was loaded successfully
* @return false if the project file was not loaded successfully
*/
static bool load(const std::fs::path &filePath);
/**
* @brief Store a project file
*
* @param filePath Path to the project file
* @return true if the project file was stored successfully
* @return false if the project file was not stored successfully
*/
static bool store(std::optional<std::fs::path> filePath = std::nullopt);
/**
* @brief Check if a project file is currently loaded
*
* @return true if a project file is currently loaded
* @return false if no project file is currently loaded
*/
static bool hasPath();
/**
* @brief Clear the currently loaded project file
*/
static void clearPath();
/**
* @brief Get the path to the currently loaded project file
* @return Path to the currently loaded project file
*/
static std::fs::path getPath();
/**
* @brief Set the path to the currently loaded project file
* @param path Path to the currently loaded project file
*/
static void setPath(const std::fs::path &path);
/**
* @brief Register a handler for storing and loading global data from a project file
*
* @param handler The handler to register
*/
static void registerHandler(const Handler &handler) {
getHandlers().push_back(handler);
}
/**
* @brief Register a handler for storing and loading per-provider data from a project file
*
* @param handler The handler to register
*/
static void registerPerProviderHandler(const ProviderHandler &handler) {
getProviderHandlers().push_back(handler);
}
/**
* @brief Get the list of registered handlers
* @return List of registered handlers
*/
static std::vector<Handler>& getHandlers() {
return s_handlers;
}
/**
* @brief Get the list of registered per-provider handlers
* @return List of registered per-provider handlers
*/
static std::vector<ProviderHandler>& getProviderHandlers() {
return s_providerHandlers;
}

View File

@@ -17,6 +17,9 @@ namespace hex {
class TaskHolder;
class TaskManager;
/**
* @brief A type representing a running asynchronous task
*/
class Task {
public:
Task() = default;
@@ -26,14 +29,38 @@ namespace hex {
Task(Task &&other) noexcept;
~Task();
/**
* @brief Updates the current process value of the task
* @param value Current value
*/
void update(u64 value = 0);
/**
* @brief Sets the maximum value of the task
* @param value Maximum value of the task
*/
void setMaxValue(u64 value);
/**
* @brief Interrupts the task
* For regular Tasks, this just throws an exception to stop the task.
* If a custom interrupt callback is set, an exception is thrown and the callback is called.
*/
void interrupt();
/**
* @brief Sets a callback that is called when the task is interrupted
* @param callback Callback to be called
*/
void setInterruptCallback(std::function<void()> callback);
[[nodiscard]] bool isBackgroundTask() const;
[[nodiscard]] bool isFinished() const;
[[nodiscard]] bool hadException() const;
[[nodiscard]] bool wasInterrupted() const;
[[nodiscard]] bool shouldInterrupt() const;
void clearException();
[[nodiscard]] std::string getExceptionMessage() const;
@@ -41,10 +68,6 @@ namespace hex {
[[nodiscard]] u64 getValue() const;
[[nodiscard]] u64 getMaxValue() const;
void interrupt();
void setInterruptCallback(std::function<void()> callback);
private:
void finish();
void interruption();
@@ -72,6 +95,9 @@ namespace hex {
friend class TaskManager;
};
/**
* @brief A type holding a weak reference to a Task
*/
class TaskHolder {
public:
TaskHolder() = default;
@@ -87,6 +113,9 @@ namespace hex {
std::weak_ptr<Task> m_task;
};
/**
* @brief The Task Manager is responsible for running and managing asynchronous tasks
*/
class TaskManager {
public:
TaskManager() = delete;
@@ -96,19 +125,45 @@ namespace hex {
constexpr static auto NoProgress = 0;
/**
* @brief Creates a new asynchronous task that gets displayed in the Task Manager in the footer
* @param name Name of the task
* @param maxValue Maximum value of the task
* @param function Function to be executed
* @return A TaskHolder holding a weak reference to the task
*/
static TaskHolder createTask(std::string name, u64 maxValue, std::function<void(Task &)> function);
/**
* @brief Creates a new asynchronous task that does not get displayed in the Task Manager
* @param name Name of the task
* @param function Function to be executed
* @return A TaskHolder holding a weak reference to the task
*/
static TaskHolder createBackgroundTask(std::string name, std::function<void(Task &)> function);
/**
* @brief Creates a new synchronous task that will execute the given function at the start of the next frame
* @param function Function to be executed
*/
static void doLater(const std::function<void()> &function);
/**
* @brief Creates a callback that will be executed when all tasks are finished
* @param function Function to be executed
*/
static void runWhenTasksFinished(const std::function<void()> &function);
static void collectGarbage();
static size_t getRunningTaskCount();
static size_t getRunningBackgroundTaskCount();
static std::list<std::shared_ptr<Task>> &getRunningTasks();
static void doLater(const std::function<void()> &function);
static std::list<std::shared_ptr<Task>> &getRunningTasks();
static void runDeferredCalls();
static void runWhenTasksFinished(const std::function<void()> &function);
private:
static std::mutex s_deferredCallsMutex, s_tasksFinishedMutex;

View File

@@ -11,6 +11,9 @@
namespace hex::api {
/**
* @brief The Theme Manager takes care of loading and applying themes
*/
class ThemeManager {
public:
constexpr static auto NativeTheme = "Native";
@@ -25,12 +28,35 @@ namespace hex::api {
};
using StyleMap = std::map<std::string, Style>;
/**
* @brief Changes the current theme to the one with the given name
* @param name Name of the theme to change to
*/
static void changeTheme(std::string name);
/**
* @brief Adds a theme from json data
* @param content JSON data of the theme
*/
static void addTheme(const std::string &content);
/**
* @brief Adds a theme handler to handle color values loaded from a theme file
* @param name Name of the handler
* @param colorMap Map of color names to their respective constants
* @param getFunction Function to get the color value of a constant
* @param setFunction Function to set the color value of a constant
*/
static void addThemeHandler(const std::string &name, const ColorMap &colorMap, const std::function<ImColor(u32)> &getFunction, const std::function<void(u32, ImColor)> &setFunction);
/**
* @brief Adds a style handler to handle style values loaded from a theme file
* @param name Name of the handler
* @param styleMap Map of style names to their respective constants
*/
static void addStyleHandler(const std::string &name, const StyleMap &styleMap);
static std::vector<std::string> getThemeNames();
static const std::string &getThemeImagePostfix();