diff --git a/NSImage+Resize.m b/NSImage+Resize.m index d0b3c4f..952dcfb 100644 --- a/NSImage+Resize.m +++ b/NSImage+Resize.m @@ -3,8 +3,8 @@ @interface ImageCache : NSObject + (ImageCache *)instance; - (void)setImage:(NSImage *)image - forName:(NSString *)name - withHeight:(CGFloat)height; + forName:(NSString *)name + withHeight:(CGFloat)height; - (NSImage *)getImageForName:(NSString *)name withHeight:(CGFloat)height; @property(nonatomic, strong) NSCache *imageCache; @end @@ -14,34 +14,34 @@ - (NSImage *)getImageForName:(NSString *)name withHeight:(CGFloat)height; @implementation ImageCache + (ImageCache *)instance { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - instance = [[ImageCache alloc] init]; - }); - return instance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [[ImageCache alloc] init]; + }); + return instance; } - (instancetype)init { - self = [super init]; - if (self) { - self.imageCache = [[NSCache alloc] init]; - } - return self; + self = [super init]; + if (self) { + self.imageCache = [[NSCache alloc] init]; + } + return self; } - (NSString *)keyForName:(NSString *)name withHeight:(CGFloat)height { - return [NSString stringWithFormat:@"%f/%@", height, name]; + return [NSString stringWithFormat:@"%f/%@", height, name]; } - (void)setImage:(NSImage *)image - forName:(NSString *)name - withHeight:(CGFloat)height { - [self.imageCache setObject:image - forKey:[self keyForName:name withHeight:height]]; + forName:(NSString *)name + withHeight:(CGFloat)height { + [self.imageCache setObject:image + forKey:[self keyForName:name withHeight:height]]; } - (NSImage *)getImageForName:(NSString *)name withHeight:(CGFloat)height { - return - [self.imageCache objectForKey:[self keyForName:name withHeight:height]]; + return + [self.imageCache objectForKey:[self keyForName:name withHeight:height]]; } @end @@ -49,45 +49,45 @@ - (NSImage *)getImageForName:(NSString *)name withHeight:(CGFloat)height { @implementation NSImage (Resize) - (NSImage *)imageWithHeight:(CGFloat)height { - NSImage *image = self; - if (![image isValid]) { - NSLog(@"Can't resize invalid image"); - return nil; - } - NSSize newSize = - NSMakeSize(image.size.width * height / image.size.height, height); - NSImage *newImage = [[NSImage alloc] initWithSize:newSize]; - [newImage lockFocus]; - [image setSize:newSize]; - [[NSGraphicsContext currentContext] - setImageInterpolation:NSImageInterpolationDefault]; - [image drawAtPoint:NSZeroPoint - fromRect:CGRectMake(0, 0, newSize.width, newSize.height) - operation:NSCompositingOperationCopy - fraction:1.0]; - [newImage unlockFocus]; - return newImage; + NSImage *image = self; + if (![image isValid]) { + NSLog(@"Can't resize invalid image"); + return nil; + } + NSSize newSize = + NSMakeSize(image.size.width * height / image.size.height, height); + NSImage *newImage = [[NSImage alloc] initWithSize:newSize]; + [newImage lockFocus]; + [image setSize:newSize]; + [[NSGraphicsContext currentContext] + setImageInterpolation:NSImageInterpolationDefault]; + [image drawAtPoint:NSZeroPoint + fromRect:CGRectMake(0, 0, newSize.width, newSize.height) + operation:NSCompositingOperationCopy + fraction:1.0]; + [newImage unlockFocus]; + return newImage; } + (NSImage *)imageFromName:(NSString *)name withHeight:(CGFloat)height { - if (name.length == 0) { - return nil; - } - NSImage *image = - [[ImageCache instance] getImageForName:name withHeight:height]; - if (image != nil) { - return image; - } - if ([name hasPrefix:@"http"]) { - image = [[NSImage alloc] initWithContentsOfURL:[NSURL URLWithString:name]]; - } else { - image = [NSImage imageNamed:name]; - } - if (height > 0 && image.size.height > height) { - image = [image imageWithHeight:height]; - } - [[ImageCache instance] setImage:image forName:name withHeight:height]; - return image; + if (name.length == 0) { + return nil; + } + NSImage *image = + [[ImageCache instance] getImageForName:name withHeight:height]; + if (image != nil) { + return image; + } + if ([name hasPrefix:@"http"]) { + image = [[NSImage alloc] initWithContentsOfURL:[NSURL URLWithString:name]]; + } else { + image = [NSImage imageNamed:name]; + } + if (height > 0 && image.size.height > height) { + image = [image imageWithHeight:height]; + } + [[ImageCache instance] setImage:image forName:name withHeight:height]; + return image; } @end \ No newline at end of file diff --git a/alert.m b/alert.m index 15dadeb..cb0abb7 100644 --- a/alert.m +++ b/alert.m @@ -5,58 +5,58 @@ void alertClicked(int, const char *); void showAlert(const char *jsonString) { - NSDictionary *jsonDict = [NSJSONSerialization - JSONObjectWithData:[[NSString stringWithUTF8String:jsonString] - dataUsingEncoding:NSUTF8StringEncoding] - options:0 - error:nil]; - - dispatch_async(dispatch_get_main_queue(), ^{ - NSAlert *alert = [NSAlert new]; - alert.messageText = jsonDict[@"MessageText"]; - alert.informativeText = jsonDict[@"InformativeText"]; - NSArray *buttons = jsonDict[@"Buttons"]; - if (![buttons isEqualTo:NSNull.null] && buttons.count > 0) { - for (NSString *label in buttons) { - [alert addButtonWithTitle:label]; - } - } - NSView *accessoryView; - NSArray *inputs = jsonDict[@"Inputs"]; - BOOL hasInputs = ![inputs isEqualTo:NSNull.null] && inputs.count > 0; - if (hasInputs) { - BOOL first = false; - int y = 30 * inputs.count; - accessoryView = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 200, y)]; - for (NSString *input in inputs) { - y -= 30; - NSTextField *textfield = - [[NSTextField alloc] initWithFrame:NSMakeRect(0, y, 200, 25)]; - [textfield setPlaceholderString:input]; - [accessoryView addSubview:textfield]; - if (!first) { - [alert.window setInitialFirstResponder:textfield]; - first = true; - } - } - [alert setAccessoryView:accessoryView]; - } - - [NSApp activateIgnoringOtherApps:YES]; - NSInteger resp = [alert runModal]; - NSMutableArray *values = [NSMutableArray new]; - if (hasInputs) { - for (NSView *subview in accessoryView.subviews) { - if (![subview isKindOfClass:[NSTextField class]]) { - continue; - } - [values addObject:((NSTextField *)subview).stringValue]; - } - } - NSData *jsonData = - [NSJSONSerialization dataWithJSONObject:values options:0 error:nil]; - NSString *jsonString = - [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; - alertClicked(resp - NSAlertFirstButtonReturn, jsonString.UTF8String); - }); + NSDictionary *jsonDict = [NSJSONSerialization + JSONObjectWithData:[[NSString stringWithUTF8String:jsonString] + dataUsingEncoding:NSUTF8StringEncoding] + options:0 + error:nil]; + + dispatch_async(dispatch_get_main_queue(), ^{ + NSAlert *alert = [NSAlert new]; + alert.messageText = jsonDict[@"MessageText"]; + alert.informativeText = jsonDict[@"InformativeText"]; + NSArray *buttons = jsonDict[@"Buttons"]; + if (![buttons isEqualTo:NSNull.null] && buttons.count > 0) { + for (NSString *label in buttons) { + [alert addButtonWithTitle:label]; + } + } + NSView *accessoryView; + NSArray *inputs = jsonDict[@"Inputs"]; + BOOL hasInputs = ![inputs isEqualTo:NSNull.null] && inputs.count > 0; + if (hasInputs) { + BOOL first = false; + int y = 30 * inputs.count; + accessoryView = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 200, y)]; + for (NSString *input in inputs) { + y -= 30; + NSTextField *textfield = + [[NSTextField alloc] initWithFrame:NSMakeRect(0, y, 200, 25)]; + [textfield setPlaceholderString:input]; + [accessoryView addSubview:textfield]; + if (!first) { + [alert.window setInitialFirstResponder:textfield]; + first = true; + } + } + [alert setAccessoryView:accessoryView]; + } + + [NSApp activateIgnoringOtherApps:YES]; + NSInteger resp = [alert runModal]; + NSMutableArray *values = [NSMutableArray new]; + if (hasInputs) { + for (NSView *subview in accessoryView.subviews) { + if (![subview isKindOfClass:[NSTextField class]]) { + continue; + } + [values addObject:((NSTextField *)subview).stringValue]; + } + } + NSData *jsonData = + [NSJSONSerialization dataWithJSONObject:values options:0 error:nil]; + NSString *jsonString = + [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + alertClicked(resp - NSAlertFirstButtonReturn, jsonString.UTF8String); + }); } diff --git a/menuet.m b/menuet.m index 70cd034..670e2be 100644 --- a/menuet.m +++ b/menuet.m @@ -22,152 +22,152 @@ @interface MenuetMenu : NSMenu @implementation MenuetMenu - (id)init { - self = [super init]; - if (self) { - self.delegate = self; - self.autoenablesItems = false; - } - return self; + self = [super init]; + if (self) { + self.delegate = self; + self.autoenablesItems = false; + } + return self; } - (void)refreshVisibleMenus { - if (!self.open) { - return; - } - [self menuWillOpen:self]; - for (NSMenuItem *item in self.itemArray) { - MenuetMenu *menu = (MenuetMenu *)item.submenu; - if (menu != NULL) { - [menu refreshVisibleMenus]; - } - } + if (!self.open) { + return; + } + [self menuWillOpen:self]; + for (NSMenuItem *item in self.itemArray) { + MenuetMenu *menu = (MenuetMenu *)item.submenu; + if (menu != NULL) { + [menu refreshVisibleMenus]; + } + } } - (void)populate:(NSArray *)items { - for (int i = 0; i < items.count; i++) { - NSMenuItem *item = nil; - if (i < self.numberOfItems) { - item = [self itemAtIndex:i]; - } - NSDictionary *dict = [items objectAtIndex:i]; - NSString *type = dict[@"Type"]; - if ([type isEqualTo:@"separator"]) { - if (!item || !item.isSeparatorItem) { - [self insertItem:[NSMenuItem separatorItem] atIndex:i]; - } - continue; - } - NSString *unique = dict[@"Unique"]; - NSString *text = dict[@"Text"]; - NSString *imageName = dict[@"Image"]; - NSNumber *fontSize = dict[@"FontSize"]; - NSNumber *fontWeight = dict[@"FontWeight"]; - BOOL state = [dict[@"State"] boolValue]; - BOOL hasChildren = [dict[@"HasChildren"] boolValue]; - BOOL clickable = [dict[@"Clickable"] boolValue]; - if (!item || item.isSeparatorItem) { - item = - [self insertItemWithTitle:@"" action:nil keyEquivalent:@"" atIndex:i]; - } - NSMutableDictionary *attributes = [NSMutableDictionary new]; - float size = fontSize.floatValue; - if (fontSize == 0) { - size = 14; - } - attributes[NSFontAttributeName] = - [NSFont monospacedDigitSystemFontOfSize:size - weight:fontWeight.floatValue]; - item.attributedTitle = - [[NSMutableAttributedString alloc] initWithString:text - attributes:attributes]; - item.target = self; - if (clickable) { - item.action = @selector(press:); - item.representedObject = unique; - } else { - item.action = nil; - item.representedObject = nil; - } - if (state) { - item.state = NSControlStateValueOn; - } else { - item.state = NSControlStateValueOff; - } - if (hasChildren) { - if (!item.submenu) { - item.submenu = [MenuetMenu new]; - } - MenuetMenu *menu = (MenuetMenu *)item.submenu; - menu.unique = unique; - } else if (item.submenu) { - item.submenu = nil; - } - item.enabled = clickable || hasChildren; - item.image = [NSImage imageFromName:imageName withHeight:16]; - } - while (self.numberOfItems > items.count) { - [self removeItemAtIndex:self.numberOfItems - 1]; - } + for (int i = 0; i < items.count; i++) { + NSMenuItem *item = nil; + if (i < self.numberOfItems) { + item = [self itemAtIndex:i]; + } + NSDictionary *dict = [items objectAtIndex:i]; + NSString *type = dict[@"Type"]; + if ([type isEqualTo:@"separator"]) { + if (!item || !item.isSeparatorItem) { + [self insertItem:[NSMenuItem separatorItem] atIndex:i]; + } + continue; + } + NSString *unique = dict[@"Unique"]; + NSString *text = dict[@"Text"]; + NSString *imageName = dict[@"Image"]; + NSNumber *fontSize = dict[@"FontSize"]; + NSNumber *fontWeight = dict[@"FontWeight"]; + BOOL state = [dict[@"State"] boolValue]; + BOOL hasChildren = [dict[@"HasChildren"] boolValue]; + BOOL clickable = [dict[@"Clickable"] boolValue]; + if (!item || item.isSeparatorItem) { + item = + [self insertItemWithTitle:@"" action:nil keyEquivalent:@"" atIndex:i]; + } + NSMutableDictionary *attributes = [NSMutableDictionary new]; + float size = fontSize.floatValue; + if (fontSize == 0) { + size = 14; + } + attributes[NSFontAttributeName] = + [NSFont monospacedDigitSystemFontOfSize:size + weight:fontWeight.floatValue]; + item.attributedTitle = + [[NSMutableAttributedString alloc] initWithString:text + attributes:attributes]; + item.target = self; + if (clickable) { + item.action = @selector(press:); + item.representedObject = unique; + } else { + item.action = nil; + item.representedObject = nil; + } + if (state) { + item.state = NSControlStateValueOn; + } else { + item.state = NSControlStateValueOff; + } + if (hasChildren) { + if (!item.submenu) { + item.submenu = [MenuetMenu new]; + } + MenuetMenu *menu = (MenuetMenu *)item.submenu; + menu.unique = unique; + } else if (item.submenu) { + item.submenu = nil; + } + item.enabled = clickable || hasChildren; + item.image = [NSImage imageFromName:imageName withHeight:16]; + } + while (self.numberOfItems > items.count) { + [self removeItemAtIndex:self.numberOfItems - 1]; + } } // The documentation says not to make changes here, but it seems to work. // submenuAction does not appear to be called, and menuNeedsUpdate is only // called once per tracking session. - (void)menuWillOpen:(MenuetMenu *)menu { - if (self.root) { - // For the root menu, we generate a new unique every time it's opened. Go - // handles all other unique generation. - self.unique = [[[[NSProcessInfo processInfo] globallyUniqueString] - substringFromIndex:51] stringByAppendingString:@":root"]; - } - const char *str = children(self.unique.UTF8String); - NSArray *items = @[]; - if (str != NULL) { - items = [NSJSONSerialization - JSONObjectWithData:[[NSString stringWithUTF8String:str] - dataUsingEncoding:NSUTF8StringEncoding] - options:0 - error:nil]; - free((char *)str); - } - if (self.root) { - items = [items arrayByAddingObjectsFromArray:@[ - @{@"Type" : @"separator", - @"Clickable" : @YES}, - @{@"Text" : @"Start at Login", - @"Clickable" : @YES}, - @{@"Text" : @"Quit", - @"Clickable" : @YES}, - ]]; - } - [self populate:items]; - if (self.root) { - NSMenuItem *item = [self itemAtIndex:items.count - 2]; - item.action = @selector(toggleStartup:); - if (runningAtStartup()) { - item.state = NSControlStateValueOn; - } else { - item.state = NSControlStateValueOff; - } - item = [self itemAtIndex:items.count - 1]; - item.target = nil; - item.action = @selector(terminate:); - } - self.open = YES; + if (self.root) { + // For the root menu, we generate a new unique every time it's opened. Go + // handles all other unique generation. + self.unique = [[[[NSProcessInfo processInfo] globallyUniqueString] + substringFromIndex:51] stringByAppendingString:@":root"]; + } + const char *str = children(self.unique.UTF8String); + NSArray *items = @[]; + if (str != NULL) { + items = [NSJSONSerialization + JSONObjectWithData:[[NSString stringWithUTF8String:str] + dataUsingEncoding:NSUTF8StringEncoding] + options:0 + error:nil]; + free((char *)str); + } + if (self.root) { + items = [items arrayByAddingObjectsFromArray:@[ + @{@"Type" : @"separator", + @"Clickable" : @YES}, + @{@"Text" : @"Start at Login", + @"Clickable" : @YES}, + @{@"Text" : @"Quit", + @"Clickable" : @YES}, + ]]; + } + [self populate:items]; + if (self.root) { + NSMenuItem *item = [self itemAtIndex:items.count - 2]; + item.action = @selector(toggleStartup:); + if (runningAtStartup()) { + item.state = NSControlStateValueOn; + } else { + item.state = NSControlStateValueOff; + } + item = [self itemAtIndex:items.count - 1]; + item.target = nil; + item.action = @selector(terminate:); + } + self.open = YES; } - (void)menuDidClose:(MenuetMenu *)menu { - self.open = NO; - menuClosed(self.unique.UTF8String); + self.open = NO; + menuClosed(self.unique.UTF8String); } - (void)press:(id)sender { - NSString *callback = [sender representedObject]; - itemClicked(callback.UTF8String); + NSString *callback = [sender representedObject]; + itemClicked(callback.UTF8String); } - (void)toggleStartup:(id)sender { - toggleStartup(); + toggleStartup(); } @end @@ -177,63 +177,63 @@ @interface MenuetAppDelegate : NSObject 0) { - notification.identifier = identifier; - } - NSString *closeButton = jsonDict[@"CloseButton"]; - if (closeButton.length > 0) { - showsButtons = true; - notification.otherButtonTitle = closeButton; - } - NSString *actionButton = jsonDict[@"ActionButton"]; - if (actionButton.length > 0) { - showsButtons = true; - notification.actionButtonTitle = actionButton; - } - NSString *responsePlaceholder = jsonDict[@"ResponsePlaceholder"]; - if (responsePlaceholder.length > 0) { - notification.hasReplyButton = YES; - notification.responsePlaceholder = responsePlaceholder; - } - if (showsButtons) { - // Override banner setting, could check plist to see if we're already set to alerts - [notification setValue:@YES forKey:@"_showsButtons"]; - } - BOOL removeFromNotificationCenter = [jsonDict[@"RemoveFromNotificationCenter"] boolValue]; - dispatch_async(dispatch_get_main_queue(), ^{ - NSUserNotificationCenter *center = - [NSUserNotificationCenter defaultUserNotificationCenter]; - [center deliverNotification:notification]; - if (removeFromNotificationCenter) { - [center removeDeliveredNotification:notification]; - } - }); + NSDictionary *jsonDict = [NSJSONSerialization + JSONObjectWithData:[[NSString stringWithUTF8String:jsonString] + dataUsingEncoding:NSUTF8StringEncoding] + options:0 + error:nil]; + NSUserNotification *notification = [NSUserNotification new]; + BOOL showsButtons = NO; + notification.title = jsonDict[@"Title"]; + notification.subtitle = jsonDict[@"Subtitle"]; + notification.informativeText = jsonDict[@"Message"]; + NSString *identifier = jsonDict[@"Identifier"]; + if (identifier.length > 0) { + notification.identifier = identifier; + } + NSString *closeButton = jsonDict[@"CloseButton"]; + if (closeButton.length > 0) { + showsButtons = true; + notification.otherButtonTitle = closeButton; + } + NSString *actionButton = jsonDict[@"ActionButton"]; + if (actionButton.length > 0) { + showsButtons = true; + notification.actionButtonTitle = actionButton; + } + NSString *responsePlaceholder = jsonDict[@"ResponsePlaceholder"]; + if (responsePlaceholder.length > 0) { + notification.hasReplyButton = YES; + notification.responsePlaceholder = responsePlaceholder; + } + if (showsButtons) { + // Override banner setting, could check plist to see if we're already set to alerts + [notification setValue:@YES forKey:@"_showsButtons"]; + } + BOOL removeFromNotificationCenter = [jsonDict[@"RemoveFromNotificationCenter"] boolValue]; + dispatch_async(dispatch_get_main_queue(), ^{ + NSUserNotificationCenter *center = + [NSUserNotificationCenter defaultUserNotificationCenter]; + [center deliverNotification:notification]; + if (removeFromNotificationCenter) { + [center removeDeliveredNotification:notification]; + } + }); } diff --git a/userdefaults.m b/userdefaults.m index 4da30e3..ca77854 100644 --- a/userdefaults.m +++ b/userdefaults.m @@ -3,38 +3,38 @@ #import "menuet.h" void setString(const char *key, const char *value) { - NSString *keyStr = [NSString stringWithUTF8String:key]; - NSString *valueStr = [NSString stringWithUTF8String:value]; - [NSUserDefaults.standardUserDefaults setObject:valueStr forKey:keyStr]; - [NSUserDefaults.standardUserDefaults synchronize]; + NSString *keyStr = [NSString stringWithUTF8String:key]; + NSString *valueStr = [NSString stringWithUTF8String:value]; + [NSUserDefaults.standardUserDefaults setObject:valueStr forKey:keyStr]; + [NSUserDefaults.standardUserDefaults synchronize]; } const char *getString(const char *key) { - NSString *keyStr = [NSString stringWithUTF8String:key]; - NSString *valueStr = [NSUserDefaults.standardUserDefaults stringForKey:keyStr]; - return valueStr.UTF8String; + NSString *keyStr = [NSString stringWithUTF8String:key]; + NSString *valueStr = [NSUserDefaults.standardUserDefaults stringForKey:keyStr]; + return valueStr.UTF8String; } void setInteger(const char *key, long value) { - NSString *keyStr = [NSString stringWithUTF8String:key]; - [NSUserDefaults.standardUserDefaults setInteger:value forKey:keyStr]; - [NSUserDefaults.standardUserDefaults synchronize]; + NSString *keyStr = [NSString stringWithUTF8String:key]; + [NSUserDefaults.standardUserDefaults setInteger:value forKey:keyStr]; + [NSUserDefaults.standardUserDefaults synchronize]; } long getInteger(const char *key) { - NSString *keyStr = [NSString stringWithUTF8String:key]; - NSInteger value = [NSUserDefaults.standardUserDefaults integerForKey:keyStr]; - return value; + NSString *keyStr = [NSString stringWithUTF8String:key]; + NSInteger value = [NSUserDefaults.standardUserDefaults integerForKey:keyStr]; + return value; } void setBoolean(const char* key, bool value) { - NSString *keyStr = [NSString stringWithUTF8String:key]; - [NSUserDefaults.standardUserDefaults setBool:value forKey:keyStr]; - [NSUserDefaults.standardUserDefaults synchronize]; + NSString *keyStr = [NSString stringWithUTF8String:key]; + [NSUserDefaults.standardUserDefaults setBool:value forKey:keyStr]; + [NSUserDefaults.standardUserDefaults synchronize]; } bool getBoolean(const char *key) { - NSString *keyStr = [NSString stringWithUTF8String:key]; - NSInteger value = [NSUserDefaults.standardUserDefaults boolForKey:keyStr]; - return value; + NSString *keyStr = [NSString stringWithUTF8String:key]; + NSInteger value = [NSUserDefaults.standardUserDefaults boolForKey:keyStr]; + return value; }