mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-03-28 07:47:03 -05:00
impr: Added icons to all menu items on macOS
This commit is contained in:
@@ -47,6 +47,10 @@
|
||||
|
||||
#if defined(OS_WEB)
|
||||
#include <emscripten.h>
|
||||
#elif defined(OS_MACOS)
|
||||
extern "C" {
|
||||
void macosRegisterFont(const unsigned char *data, size_t size);
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace hex {
|
||||
@@ -1205,6 +1209,10 @@ namespace hex {
|
||||
offset,
|
||||
fontSizeMultiplier
|
||||
);
|
||||
|
||||
#if defined(OS_MACOS)
|
||||
macosRegisterFont(data.data(), data.size_bytes());
|
||||
#endif
|
||||
}
|
||||
|
||||
void registerFont(const Font& font) {
|
||||
|
||||
@@ -61,7 +61,120 @@ void macosEndMainMenuBar(void) {
|
||||
s_constructingMenu = false;
|
||||
}
|
||||
|
||||
bool macosBeginMenu(const char* label, bool enabled) {
|
||||
|
||||
static NSMutableArray* g_RegisteredIconFontDescriptors = nil;
|
||||
void macosRegisterFont(const unsigned char* fontBytes, size_t fontLength) {
|
||||
if (!fontBytes || fontLength == 0 || fontLength > 100 * 1024 * 1024) { // Max 100MB sanity check
|
||||
NSLog(@"Invalid font data: bytes=%p, length=%zu", fontBytes, fontLength);
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize array on first use
|
||||
if (!g_RegisteredIconFontDescriptors) {
|
||||
g_RegisteredIconFontDescriptors = [[NSMutableArray alloc] init];
|
||||
}
|
||||
|
||||
// Create NSData - this will copy the bytes
|
||||
NSData *fontData = [NSData dataWithBytes:fontBytes length:fontLength];
|
||||
if (!fontData) {
|
||||
NSLog(@"Failed to create NSData from font bytes");
|
||||
return;
|
||||
}
|
||||
|
||||
CFErrorRef error = NULL;
|
||||
CFArrayRef descriptors = CTFontManagerCreateFontDescriptorsFromData((__bridge CFDataRef)fontData);
|
||||
|
||||
if (descriptors && CFArrayGetCount(descriptors) > 0) {
|
||||
// Register all descriptors from this font file
|
||||
CTFontManagerRegisterFontDescriptors(descriptors, kCTFontManagerScopeProcess, true, NULL);
|
||||
if (true) {
|
||||
// Store each descriptor for later use
|
||||
for (CFIndex i = 0; i < CFArrayGetCount(descriptors); i++) {
|
||||
CTFontDescriptorRef descriptor = (CTFontDescriptorRef)CFArrayGetValueAtIndex(descriptors, i);
|
||||
[g_RegisteredIconFontDescriptors addObject:(__bridge id)descriptor];
|
||||
|
||||
// Log the font name for debugging
|
||||
CTFontRef font = CTFontCreateWithFontDescriptor(descriptor, 16.0, NULL);
|
||||
if (font) {
|
||||
CFRelease(font);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
NSLog(@"Failed to register font descriptors");
|
||||
}
|
||||
|
||||
CFRelease(descriptors);
|
||||
} else {
|
||||
NSLog(@"Failed to create font descriptors from data (length: %zu)", fontLength);
|
||||
if (error) {
|
||||
NSLog(@"Error: %@", (__bridge NSError *)error);
|
||||
CFRelease(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static NSImage* imageFromIconFont(NSString* character,
|
||||
CGFloat size,
|
||||
NSColor* color) {
|
||||
|
||||
if (!character || [character length] == 0) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (!g_RegisteredIconFontDescriptors || [g_RegisteredIconFontDescriptors count] == 0) {
|
||||
NSLog(@"No icon fonts registered");
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSFont *font = nil;
|
||||
unichar unicode = [character characterAtIndex:0];
|
||||
|
||||
for (id descriptorObj in g_RegisteredIconFontDescriptors) {
|
||||
CTFontDescriptorRef descriptor = (__bridge CTFontDescriptorRef)descriptorObj;
|
||||
CTFontRef ctFont = CTFontCreateWithFontDescriptor(descriptor, size, NULL);
|
||||
|
||||
if (ctFont) {
|
||||
CGGlyph glyph;
|
||||
UniChar unichar = unicode;
|
||||
if (CTFontGetGlyphsForCharacters(ctFont, &unichar, &glyph, 1)) {
|
||||
font = (__bridge NSFont *)ctFont;
|
||||
break;
|
||||
}
|
||||
CFRelease(ctFont);
|
||||
}
|
||||
}
|
||||
|
||||
if (!font) {
|
||||
NSLog(@"No font found with glyph for character U+%04X (string: '%@', length: %lu)",
|
||||
unicode, character, (unsigned long)[character length]);
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSDictionary *attributes = @{
|
||||
NSFontAttributeName: font,
|
||||
NSForegroundColorAttributeName: color
|
||||
};
|
||||
NSAttributedString *attrString = [[NSAttributedString alloc]
|
||||
initWithString:character
|
||||
attributes:attributes];
|
||||
|
||||
NSSize stringSize = [attrString size];
|
||||
|
||||
NSImage *image = [[NSImage alloc] initWithSize:NSMakeSize(size, size)];
|
||||
|
||||
[image lockFocus];
|
||||
|
||||
NSPoint drawPoint = NSMakePoint((size - stringSize.width) / 2.0,
|
||||
(size - stringSize.height) / 2.0);
|
||||
[attrString drawAtPoint:drawPoint];
|
||||
|
||||
[image unlockFocus];
|
||||
[image setTemplate:YES];
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
bool macosBeginMenu(const char* label, const char *icon, bool enabled) {
|
||||
NSString* title = [NSString stringWithUTF8String:label];
|
||||
|
||||
// Search for menu item with the given name
|
||||
@@ -79,6 +192,12 @@ bool macosBeginMenu(const char* label, bool enabled) {
|
||||
menuItem.title = title;
|
||||
[menuItem setSubmenu:newMenu];
|
||||
|
||||
if (icon != NULL) {
|
||||
NSString *iconString = [NSString stringWithUTF8String:icon];
|
||||
NSImage* iconImage = imageFromIconFont(iconString, 16.0, [NSColor blackColor]);
|
||||
[menuItem setImage:iconImage];
|
||||
}
|
||||
|
||||
// Add the new menu to the end of the list
|
||||
menuIndex = [s_menuStack[s_menuStackSize - 1] numberOfItems];
|
||||
|
||||
@@ -104,7 +223,7 @@ void macosEndMenu(void) {
|
||||
s_menuStackSize -= 1;
|
||||
}
|
||||
|
||||
bool macosMenuItem(const char* label, struct KeyEquivalent keyEquivalent, bool selected, bool enabled) {
|
||||
bool macosMenuItem(const char* label, const char *icon, struct KeyEquivalent keyEquivalent, bool selected, bool enabled) {
|
||||
NSString* title = [NSString stringWithUTF8String:label];
|
||||
|
||||
if (s_constructingMenu) {
|
||||
@@ -113,6 +232,12 @@ bool macosMenuItem(const char* label, struct KeyEquivalent keyEquivalent, bool s
|
||||
menuItem.action = @selector(OnClick:);
|
||||
menuItem.target = s_menuItemHandler;
|
||||
|
||||
if (icon != NULL) {
|
||||
NSString *iconString = [NSString stringWithUTF8String:icon];
|
||||
NSImage* iconImage = imageFromIconFont(iconString, 16.0, [NSColor blackColor]);
|
||||
[menuItem setImage:iconImage];
|
||||
}
|
||||
|
||||
[menuItem setTag:s_currTag];
|
||||
s_currTag += 1;
|
||||
|
||||
@@ -164,8 +289,8 @@ bool macosMenuItem(const char* label, struct KeyEquivalent keyEquivalent, bool s
|
||||
return false;
|
||||
}
|
||||
|
||||
bool macosMenuItemSelect(const char* label, struct KeyEquivalent keyEquivalent, bool* selected, bool enabled) {
|
||||
if (macosMenuItem(label, keyEquivalent, selected != NULL ? *selected : false, enabled)) {
|
||||
bool macosMenuItemSelect(const char* label, const char *icon, struct KeyEquivalent keyEquivalent, bool* selected, bool enabled) {
|
||||
if (macosMenuItem(label, icon, keyEquivalent, selected != NULL ? *selected : false, enabled)) {
|
||||
if (selected != NULL)
|
||||
*selected = !(*selected);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <../../../../lib/libimhex/include/hex/helpers/menu_items.hpp>
|
||||
#include <hex/helpers/menu_items.hpp>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
@@ -12,13 +12,14 @@
|
||||
void macosEndMainMenuBar(void);
|
||||
void macosClearMenu(void);
|
||||
|
||||
bool macosBeginMenu(const char* label, bool enabled);
|
||||
bool macosBeginMenu(const char* label, const char *icon, bool enabled);
|
||||
void macosEndMenu(void);
|
||||
|
||||
bool macosMenuItem(const char* label, KeyEquivalent keyEquivalent, bool selected, bool enabled);
|
||||
bool macosMenuItemSelect(const char* label, KeyEquivalent keyEquivalent, bool* p_selected, bool enabled);
|
||||
bool macosMenuItem(const char* label, const char *icon, KeyEquivalent keyEquivalent, bool selected, bool enabled);
|
||||
bool macosMenuItemSelect(const char* label, const char *icon, KeyEquivalent keyEquivalent, bool* p_selected, bool enabled);
|
||||
|
||||
void macosSeparator(void);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -71,7 +72,7 @@ namespace hex::menu {
|
||||
bool beginMenu(const char *label, bool enabled) {
|
||||
#if defined(OS_MACOS)
|
||||
if (s_useNativeMenuBar)
|
||||
return macosBeginMenu(label, enabled);
|
||||
return macosBeginMenu(label, nullptr, enabled);
|
||||
#endif
|
||||
|
||||
return ImGui::BeginMenu(label, enabled);
|
||||
@@ -80,7 +81,7 @@ namespace hex::menu {
|
||||
bool beginMenuEx(const char *label, const char *icon, bool enabled) {
|
||||
#if defined(OS_MACOS)
|
||||
if (s_useNativeMenuBar)
|
||||
return macosBeginMenu(label, enabled);
|
||||
return macosBeginMenu(label, icon, enabled);
|
||||
#endif
|
||||
|
||||
return ImGui::BeginMenuEx(label, icon, enabled);
|
||||
@@ -101,7 +102,7 @@ namespace hex::menu {
|
||||
bool menuItem(const char *label, const Shortcut &shortcut, bool selected, bool enabled) {
|
||||
#if defined(OS_MACOS)
|
||||
if (s_useNativeMenuBar)
|
||||
return macosMenuItem(label, shortcut.toKeyEquivalent(), selected, enabled);
|
||||
return macosMenuItem(label, nullptr, shortcut.toKeyEquivalent(), selected, enabled);
|
||||
#endif
|
||||
|
||||
return ImGui::MenuItem(label, shortcut.toString().c_str(), selected, enabled);
|
||||
@@ -110,7 +111,7 @@ namespace hex::menu {
|
||||
bool menuItem(const char *label, const Shortcut &shortcut, bool *selected, bool enabled) {
|
||||
#if defined(OS_MACOS)
|
||||
if (s_useNativeMenuBar)
|
||||
return macosMenuItemSelect(label, shortcut.toKeyEquivalent(), selected, enabled);
|
||||
return macosMenuItemSelect(label, nullptr, shortcut.toKeyEquivalent(), selected, enabled);
|
||||
#endif
|
||||
|
||||
return ImGui::MenuItem(label, shortcut.toString().c_str(), selected, enabled);
|
||||
@@ -119,7 +120,7 @@ namespace hex::menu {
|
||||
bool menuItemEx(const char *label, const char *icon, const Shortcut &shortcut, bool selected, bool enabled) {
|
||||
#if defined(OS_MACOS)
|
||||
if (s_useNativeMenuBar)
|
||||
return macosMenuItem(label, shortcut.toKeyEquivalent(), selected, enabled);
|
||||
return macosMenuItem(label, icon, shortcut.toKeyEquivalent(), selected, enabled);
|
||||
#endif
|
||||
|
||||
return ImGui::MenuItemEx(label, icon, shortcut.toString().c_str(), selected, enabled);
|
||||
@@ -128,7 +129,7 @@ namespace hex::menu {
|
||||
bool menuItemEx(const char *label, const char *icon, const Shortcut &shortcut, bool *selected, bool enabled) {
|
||||
#if defined(OS_MACOS)
|
||||
if (s_useNativeMenuBar)
|
||||
return macosMenuItemSelect(label, shortcut.toKeyEquivalent(), selected, enabled);
|
||||
return macosMenuItemSelect(label, icon, shortcut.toKeyEquivalent(), selected, enabled);
|
||||
#endif
|
||||
|
||||
if (ImGui::MenuItemEx(label, icon, shortcut.toString().c_str(), selected != nullptr ? *selected : false, enabled)) {
|
||||
|
||||
Reference in New Issue
Block a user