Files
textmate/Frameworks/OakDebug/src/OakDebugMenu.mm
Allan Odgaard 9894969e67 Initial commit
2012-08-09 16:25:56 +02:00

157 lines
4.3 KiB
Plaintext

#import "OakDebug.h"
#import "OakDebugMenu.h"
#import <oak/oak.h>
#import <oak/CocoaSTL.h>
#import <malloc/malloc.h>
namespace
{
struct MiB_t
{
MiB_t (size_t inBytes) : unit(bytes)
{
size = (double)inBytes;
if(inBytes > 1000 * 1024*1024)
{
size /= 1024*1024*1024;
unit = GiB;
}
else if(inBytes > 1000 * 1024)
{
size /= 1024*1024;
unit = MiB;
}
else if(inBytes > 1000)
{
size /= 1024;
unit = KiB;
}
}
NSString* to_s () const
{
char const* unitStr = NULL;
switch(unit)
{
case GiB: unitStr = "GB"; break;
case MiB: unitStr = "MB"; break;
case KiB: unitStr = "KB"; break;
case bytes: unitStr = "bytes"; break;
}
std::string pad = "";
for(size_t i = 1000; i > 1 && size < i; i /= 10)
pad += "\u2007"; // Figure Space
return [NSString stringWithFormat:@"%@%.1f %s", @(pad.c_str()), size, unitStr];
}
double size;
enum unit_t { GiB, MiB, KiB, bytes } unit;
};
}
@implementation OakDebugMenu
+ (void)load
{
NSAutoreleasePool* pool = [NSAutoreleasePool new];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(installDebugMenu:) name:NSApplicationDidFinishLaunchingNotification object:NSApp];
if(NSArray* debugEnabled = [[NSUserDefaults standardUserDefaults] objectForKey:@"OakDebug Enabled"])
{
iterate(it, debugEnabled)
OakDebugBaseClass::registry()[[(NSString*)*it UTF8String]] = true;
}
[pool release];
}
+ (void)toggleDebugOption:(id)menuItem
{
OakDebugBaseClass::registry()[[[menuItem representedObject] UTF8String]] ^= true;
NSMutableArray* debugEnabled = [NSMutableArray array];
iterate(it, OakDebugBaseClass::registry())
{
if(it->second)
[debugEnabled addObject:@(it->first.c_str())];
}
[[NSUserDefaults standardUserDefaults] setObject:debugEnabled forKey:@"OakDebug Enabled"];
}
+ (BOOL)validateMenuItem:(NSMenuItem*)menuItem
{
bool enabled = OakDebugBaseClass::registry()[[[menuItem representedObject] UTF8String]];
[menuItem setState:enabled ? NSOnState : NSOffState];
return YES;
}
+ (BOOL)menuHasKeyEquivalent:(NSMenu*)menu forEvent:(NSEvent*)event target:(id*)target action:(SEL*)action
{
return NO;
}
+ (void)menuNeedsUpdate:(NSMenu*)aMenu
{
for(int i = [aMenu numberOfItems]; i-- > 0; )
[aMenu removeItemAtIndex:i];
// ===================
// = Add Memory Info =
// ===================
struct mstats m = mstats();
NSString* usedMemory = [NSString stringWithFormat:@"%@ Used", MiB_t(m.bytes_used).to_s()];
NSString* freeMemory = [NSString stringWithFormat:@"%@ Free", MiB_t(m.bytes_free).to_s()];
NSString* totalMemory = [NSString stringWithFormat:@"%@ Total", MiB_t(m.bytes_total).to_s()];
NSString* titles[] = { usedMemory, freeMemory, totalMemory };
for(size_t i = 0; i < sizeofA(titles); ++i)
{
NSMenuItem* item = [aMenu addItemWithTitle:titles[i] action:NULL keyEquivalent:@""];
[item setEnabled:NO];
}
[aMenu addItem:[NSMenuItem separatorItem]];
// ===================
std::vector<std::string> sectionNames = OakDebugBaseClass::sectionNames();;
NSMenu* submenu = nil;
iterate(it, OakDebugBaseClass::registry())
{
std::string const& sectionName = OakDebugBaseClass::sectionName(it->first);
NSMenuItem* item;
if(oak::contains(sectionNames.begin(), sectionNames.end(), sectionName))
{
NSString* section = @(sectionName.c_str());
NSString* title = sectionName.size() == it->first.size() ? @"Base" : @(it->first.substr(sectionName.size() + 1).c_str());
if(![[submenu title] isEqualToString:section])
{
submenu = [[[NSMenu alloc] initWithTitle:section] autorelease];
[[aMenu addItemWithTitle:section action:NULL keyEquivalent:@""] setSubmenu:submenu];
}
item = [submenu addItemWithTitle:title action:@selector(toggleDebugOption:) keyEquivalent:@""];
}
else
{
item = [aMenu addItemWithTitle:@(it->first.c_str()) action:@selector(toggleDebugOption:) keyEquivalent:@""];
}
[item setRepresentedObject:@(it->first.c_str())];
[item setTarget:self];
[item setState:it->second ? NSOnState : NSOffState];
}
}
+ (void)installDebugMenu:(id)sender
{
NSMenuItem* menuItem = [[[NSMenuItem alloc] init] autorelease];
[menuItem setTitle:@"Debug"];
NSMenu* debugMenu = [[[NSMenu alloc] initWithTitle:@"Debug"] autorelease];
[debugMenu setDelegate:self];
[menuItem setSubmenu:debugMenu];
[[NSApp mainMenu] addItem:menuItem];
}
@end