1
0
mirror of synced 2024-11-24 07:40:17 +01:00

feat: Added font picker to the settings (#1570)

This commit is contained in:
Nik 2024-02-24 22:46:52 +01:00 committed by GitHub
parent 8bf7aa9ceb
commit ec69849749
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 179 additions and 21 deletions

View File

@ -141,7 +141,7 @@ namespace hex {
[[nodiscard]] bool isChecked() const { return m_value; }
private:
protected:
bool m_value;
};
@ -155,7 +155,7 @@ namespace hex {
[[nodiscard]] i32 getValue() const { return m_value; }
private:
protected:
int m_value;
i32 m_min, m_max;
};
@ -170,7 +170,7 @@ namespace hex {
[[nodiscard]] float getValue() const { return m_value; }
private:
protected:
float m_value;
float m_min, m_max;
};
@ -186,7 +186,7 @@ namespace hex {
[[nodiscard]] ImColor getColor() const;
private:
protected:
std::array<float, 4> m_value{};
};
@ -202,7 +202,7 @@ namespace hex {
[[nodiscard]]
const nlohmann::json& getValue() const;
private:
protected:
std::vector<std::string> m_items;
std::vector<nlohmann::json> m_settingsValues;
nlohmann::json m_defaultItem;
@ -222,7 +222,7 @@ namespace hex {
[[nodiscard]]
const std::string& getValue() const { return m_value; }
private:
protected:
std::string m_value;
};
@ -233,12 +233,12 @@ namespace hex {
void load(const nlohmann::json &data) override;
nlohmann::json store() override;
[[nodiscard]] std::fs::path getPath() const {
return m_value;
[[nodiscard]] const std::fs::path& getPath() const {
return m_path;
}
private:
std::string m_value;
protected:
std::fs::path m_path;
};
class Label : public Widget {

View File

@ -12,6 +12,7 @@
#include <concepts>
#include <functional>
#include <limits>
#include <map>
#include <memory>
#include <optional>
#include <string>
@ -76,6 +77,9 @@ namespace hex {
int executeCommand(const std::string &command);
void openWebpage(std::string url);
extern "C" void registerFont(const char *fontName, const char *fontPath);
const std::map<std::fs::path, std::string>& getFonts();
[[nodiscard]] std::string encodeByteString(const std::vector<u8> &bytes);
[[nodiscard]] std::vector<u8> decodeByteString(const std::string &string);

View File

@ -14,6 +14,7 @@
void setupMacosWindowStyle(GLFWwindow *window, bool borderlessWindowMode);
void enumerateFontsMacos();
}
#endif

View File

@ -413,16 +413,18 @@ namespace hex {
bool FilePicker::draw(const std::string &name) {
bool changed = false;
if (ImGui::InputText("##font_path", m_value)) {
auto pathString = wolv::util::toUTF8String(m_path);
if (ImGui::InputText("##font_path", pathString)) {
changed = true;
}
ImGui::SameLine();
if (ImGuiExt::IconButton("...", ImGui::GetStyleColorVec4(ImGuiCol_Text))) {
return fs::openFileBrowser(fs::DialogMode::Open, { { "TTF Font", "ttf" }, { "OTF Font", "otf" } },
changed = fs::openFileBrowser(fs::DialogMode::Open, { { "TTF Font", "ttf" }, { "OTF Font", "otf" } },
[&](const std::fs::path &path) {
m_value = wolv::util::toUTF8String(path);
pathString = wolv::util::toUTF8String(path);
});
}
@ -430,19 +432,23 @@ namespace hex {
ImGuiExt::TextFormatted("{}", name);
if (changed) {
m_path = pathString;
}
return changed;
}
void FilePicker::load(const nlohmann::json &data) {
if (data.is_string()) {
m_value = data.get<std::string>();
m_path = data.get<std::fs::path>();
} else {
log::warn("Invalid data type loaded from settings for file picker!");
}
}
nlohmann::json FilePicker::store() {
return m_value;
return m_path;
}
bool Label::draw(const std::string& name) {

View File

@ -677,14 +677,23 @@ namespace hex {
return value;
}
static std::optional<std::fs::path> fileToOpen;
static std::optional<std::fs::path> s_fileToOpen;
extern "C" void openFile(const char *path) {
log::info("Opening file: {0}", path);
fileToOpen = path;
s_fileToOpen = path;
}
std::optional<std::fs::path> getInitialFilePath() {
return fileToOpen;
return s_fileToOpen;
}
static std::map<std::fs::path, std::string> s_fonts;
extern "C" void registerFont(const char *fontName, const char *fontPath) {
s_fonts[fontPath] = fontName;
}
const std::map<std::fs::path, std::string>& getFonts() {
return s_fonts;
}
namespace {

View File

@ -3,8 +3,9 @@
#include <CoreFoundation/CFBundle.h>
#include <ApplicationServices/ApplicationServices.h>
#include <Foundation/NSUserDefaults.h>
#include <Foundation/Foundation.h>
#include <AppKit/NSScreen.h>
#include <CoreFoundation/CoreFoundation.h>
#include <CoreText/CoreText.h>
#include <string.h>
#include <stdlib.h>
@ -23,6 +24,7 @@
}
void openFile(const char *path);
void registerFont(const char *fontName, const char *fontPath);
void openWebpageMacos(const char *url) {
CFURLRef urlRef = CFURLCreateWithBytes(NULL, (uint8_t*)(url), strlen(url), kCFStringEncodingASCII, NULL);
@ -64,6 +66,28 @@
return (cocoaWindow.styleMask & NSWindowStyleMaskFullScreen) == NSWindowStyleMaskFullScreen;
}
void enumerateFontsMacos(void) {
CFArrayRef fontDescriptors = CTFontManagerCopyAvailableFontFamilyNames();
CFIndex count = CFArrayGetCount(fontDescriptors);
for (CFIndex i = 0; i < count; i++) {
CFStringRef fontName = (CFStringRef)CFArrayGetValueAtIndex(fontDescriptors, i);
// Get font path
CFDictionaryRef attributes = (__bridge CFDictionaryRef)@{ (__bridge NSString *)kCTFontNameAttribute : (__bridge NSString *)fontName };
CTFontDescriptorRef descriptor = CTFontDescriptorCreateWithAttributes(attributes);
CFURLRef fontURL = CTFontDescriptorCopyAttribute(descriptor, kCTFontURLAttribute);
CFStringRef fontPath = CFURLCopyFileSystemPath(fontURL, kCFURLPOSIXPathStyle);
registerFont([(__bridge NSString *)fontName UTF8String], [(__bridge NSString *)fontPath UTF8String]);
CFRelease(descriptor);
CFRelease(fontURL);
}
CFRelease(fontDescriptors);
}
@interface HexDocument : NSDocument
@end

View File

@ -47,6 +47,31 @@ namespace hex {
} // Hopefully one of these commands is installed
}
void enumerateFonts() {
const std::array FontDirectories = {
"/usr/share/fonts",
"/usr/local/share/fonts",
"~/.fonts",
"~/.local/share/fonts"
};
for (const auto &directory : FontDirectories) {
if (!std::fs::exists(directory))
continue;
for (const auto &entry : std::fs::recursive_directory_iterator(directory)) {
if (!entry.exists())
continue;
if (!entry.is_regular_file())
continue;
if (entry.path().extension() != ".ttf" && entry.path().extension() != ".otf")
continue;
registerFont(entry.path().stem().c_str(), entry.path().c_str());
}
}
}
void Window::initNative() {
log::impl::enableColorPrinting();
@ -65,6 +90,8 @@ namespace hex {
if (!isatty(STDOUT_FILENO)) {
log::impl::redirectToFile();
}
enumerateFonts();
}
void Window::setupNativeWindow() {

View File

@ -38,6 +38,8 @@ namespace hex {
if (!isatty(STDOUT_FILENO)) {
log::impl::redirectToFile();
}
enumerateFontsMacos();
}
void Window::setupNativeWindow() {

View File

@ -268,6 +268,46 @@ namespace hex {
dup2(unboundFd, stdFileDescriptor);
}
void enumerateFonts() {
constexpr static auto FontRegistryPath = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts";
static const std::array RegistryLocations = {
HKEY_LOCAL_MACHINE,
HKEY_CURRENT_USER
};
for (const auto location : RegistryLocations) {
HKEY key;
if (RegOpenKeyExW(location, FontRegistryPath, 0, KEY_READ, &key) != ERROR_SUCCESS) {
continue;
}
DWORD index = 0;
std::wstring valueName(0xFFF, L'\0');
DWORD valueNameSize = valueName.size() * sizeof(wchar_t);
std::wstring valueData(0xFFF, L'\0');
DWORD valueDataSize = valueData.size() * sizeof(wchar_t);
DWORD valueType;
while (RegEnumValueW(key, index, valueName.data(), &valueNameSize, nullptr, &valueType, reinterpret_cast<BYTE *>(valueData.data()), &valueDataSize) == ERROR_SUCCESS) {
if (valueType == REG_SZ) {
auto fontName = hex::utf16ToUtf8(valueName.c_str());
auto fontPath = std::fs::path(valueData);
if (fontPath.is_relative())
fontPath = std::fs::path("C:\\Windows\\Fonts") / fontPath;
registerFont(fontName.c_str(), wolv::util::toUTF8String(fontPath).c_str());
}
valueNameSize = valueName.size();
valueDataSize = valueData.size();
index++;
}
RegCloseKey(key);
}
}
void Window::initNative() {
if (ImHexApi::System::isDebugBuild()) {
@ -301,6 +341,8 @@ namespace hex {
if (std::fs::exists(path))
AddDllDirectory(path.c_str());
}
enumerateFonts();
}
class DropManager : public IDropTarget {
@ -486,7 +528,6 @@ namespace hex {
});
ImGui::GetIO().ConfigDebugIsDebuggerPresent = ::IsDebuggerPresent();
}
void Window::beginNativeWindowFrame() {

View File

@ -603,6 +603,50 @@ namespace hex::plugin::builtin {
i32 m_currIndex = 0;
};
class FontFilePicker : public ContentRegistry::Settings::Widgets::FilePicker {
public:
bool draw(const std::string &name) {
bool changed = false;
const auto &fonts = hex::getFonts();
bool customFont = false;
std::string pathPreview = "";
if (m_path.empty()) {
pathPreview = "Default Font";
} else if (fonts.contains(m_path)) {
pathPreview = fonts.at(m_path);
} else {
pathPreview = wolv::util::toUTF8String(m_path.filename());
customFont = true;
}
if (ImGui::BeginCombo(name.c_str(), pathPreview.c_str())) {
if (ImGui::Selectable("Default Font", m_path.empty())) {
m_path.clear();
changed = true;
}
if (ImGui::Selectable("Custom Font", customFont)) {
changed = fs::openFileBrowser(fs::DialogMode::Open, { { "TTF Font", "ttf" }, { "OTF Font", "otf" } }, [this](const std::fs::path &path) {
m_path = path;
});
}
for (const auto &[path, fontName] : fonts) {
if (ImGui::Selectable(fontName.c_str(), m_path == path)) {
m_path = path;
changed = true;
}
}
ImGui::EndCombo();
}
return changed;
}
};
bool getDefaultBorderlessWindowMode() {
bool result = false;
@ -739,7 +783,7 @@ namespace hex::plugin::builtin {
return customFontsEnabled.isChecked();
};
auto customFontPathSetting = ContentRegistry::Settings::add<Widgets::FilePicker>("hex.builtin.setting.font", "hex.builtin.setting.font.custom_font", "hex.builtin.setting.font.font_path")
auto customFontPathSetting = ContentRegistry::Settings::add<FontFilePicker>("hex.builtin.setting.font", "hex.builtin.setting.font.custom_font", "hex.builtin.setting.font.font_path")
.requiresRestart()
.setEnabledCallback(customFontsEnabled);