aboutsummaryrefslogtreecommitdiff
path: root/XcodePlugin/GTMXcodePlugin.m
diff options
context:
space:
mode:
Diffstat (limited to 'XcodePlugin/GTMXcodePlugin.m')
-rw-r--r--XcodePlugin/GTMXcodePlugin.m210
1 files changed, 210 insertions, 0 deletions
diff --git a/XcodePlugin/GTMXcodePlugin.m b/XcodePlugin/GTMXcodePlugin.m
new file mode 100644
index 0000000..58d0109
--- /dev/null
+++ b/XcodePlugin/GTMXcodePlugin.m
@@ -0,0 +1,210 @@
+//
+// GTMXcodePlugin.m
+//
+// Copyright 2007-2009 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+//
+
+#import "GTMXcodePlugin.h"
+#import "GTMXcodeMenuItem.h"
+#import "PBXPreferencesModule.h"
+#import "GTMXcodePreferences.h"
+#import "GTMDefines.h"
+
+@interface GTMXcodePlugin (PrivateMethods)
+
+// Called when the preference panel has been loaded so we can set up our
+// preference pane.
+- (void)preferencesPanelDidLoadNotification:(NSNotification *)notification;
+
+// Called whenever a menu item is added to the list
+- (void)addedMenuItem:(NSNotification *)notification;
+
+// Called whenever the pref for showing the menuitem icon changes
+- (void)updateMenuIcons:(NSNotification *)notification;
+
+// the image to use for our menu items
+- (NSImage *)imageForMenuItems;
+@end
+
+// Our dictionary of menu items to add
+static NSMutableDictionary *gRegisteredMenuItems = nil;
+
+static NSMutableArray *gRegisteredClasses = nil;
+
+@implementation GTMXcodePlugin
++ (void)registerMenuItem:(id)item {
+ @synchronized([self class]) {
+ static int gTag = 0xDADE;
+ if (!gRegisteredMenuItems) {
+ gRegisteredMenuItems = [[NSMutableDictionary alloc] init];
+ }
+ if (item) {
+ [gRegisteredMenuItems setObject:item
+ forKey:[NSNumber numberWithInt:gTag++]];
+ }
+ }
+}
+
++ (void)registerSwizzleClass:(Class)cls {
+ @synchronized([self class]) {
+ if (!gRegisteredClasses) {
+ gRegisteredClasses = [[NSMutableArray alloc] init];
+ }
+ if (cls) {
+ [gRegisteredClasses addObject:cls];
+ }
+ }
+}
+
+- (id)init {
+ self = [super init];
+ if (!self) return nil;
+
+ NSBundle *bundle = [NSBundle bundleForClass:[self class]];
+ NSString *version = [bundle objectForInfoDictionaryKey:@"CFBundleVersion"];
+ NSLog(@"GTMXcodePlugin loaded (%@)", version);
+
+ NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+
+ [nc addObserver:self
+ selector:@selector(preferencesPanelDidLoadNotification:)
+ name:PBXPreferencesPanelDidLoadNotification
+ object:nil];
+
+ [nc addObserver:self
+ selector:@selector(addedMenuItem:)
+ name:NSMenuDidAddItemNotification
+ object:[NSApp mainMenu]];
+
+ [nc addObserver:self
+ selector:@selector(updateMenuIcons:)
+ name:GTMXcodePreferencesMenuItemPrefChanged
+ object:nil];
+
+ NSEnumerator *enumerator = [gRegisteredClasses objectEnumerator];
+ Class cls;
+ while ((cls = [enumerator nextObject])) {
+ [[[cls alloc] init] autorelease];
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+ [gRegisteredMenuItems removeAllObjects];
+ [gRegisteredMenuItems release];
+ [super dealloc];
+}
+
+
+- (void)preferencesPanelDidLoadNotification:(NSNotification *)notification {
+ GTMXcodePreferences *prefs = [[[GTMXcodePreferences alloc] init] autorelease];
+ [[PBXPreferencesModule sharedPreferences] addPreferenceNamed:@"Google"
+ owner:prefs];
+}
+
+- (NSImage *)imageForMenuItems {
+ NSBundle *pluginBundle = [GTMXcodePlugin pluginBundle];
+ NSString *path = [pluginBundle pathForResource:@"GTM"
+ ofType:@"icns"];
+ NSImage *image = [[[NSImage alloc] initWithContentsOfFile:path] autorelease];
+ [image setScalesWhenResized:YES];
+ [image setSize:NSMakeSize(16, 16)];
+ return image;
+}
+
+- (void)addedMenuItem:(NSNotification *)notification {
+ NSMenu *menu = [notification object];
+ NSNumber *idx = [[notification userInfo] objectForKey:@"NSMenuItemIndex"];
+ NSMenuItem *menuItem = [menu itemAtIndex:[idx intValue]];
+ if ([[menuItem title] isEqualToString:@"User Scripts"]) {
+ NSImage *image = nil;
+ if ([GTMXcodePreferences showImageOnMenuItems]) {
+ image = [self imageForMenuItems];
+ }
+ NSArray *sortedKeys
+ = [gRegisteredMenuItems keysSortedByValueUsingSelector:@selector(compareDepth:)];
+ NSEnumerator *keyEnum = [sortedKeys objectEnumerator];
+ NSNumber *key;
+ while ((key = [keyEnum nextObject])) {
+ id<GTMXcodeMenuItemProtocol> item = [gRegisteredMenuItems objectForKey:key];
+ NSInteger insertionIndex = [item insertionIndex];
+ NSMenu *insertionMenu = [item insertionMenu];
+ NSInteger itemCount = [insertionMenu numberOfItems];
+ if (insertionIndex > itemCount) {
+ insertionIndex = itemCount;
+ }
+ NSString *itemTitle = [item title];
+ if ([itemTitle isEqualToString:@"-"]) {
+ [insertionMenu insertItem:[NSMenuItem separatorItem]
+ atIndex:insertionIndex];
+ } else {
+ menuItem = [insertionMenu insertItemWithTitle:[item title]
+ action:[item actionSelector]
+ keyEquivalent:[item keyEquivalent]
+ atIndex:insertionIndex];
+ if (image && [item allowGDTMenuIcon]) {
+ [menuItem setImage:image];
+ }
+ [menuItem setTarget:item];
+ [menuItem setTag:[key intValue]];
+ [item wasInserted:menuItem];
+ }
+ }
+ }
+}
+
+- (void)updateMenuIcons:(NSNotification *)notification {
+ // we use our own notification since the normal defaults one doesn't let you
+ // tell which changed.
+ NSImage *image = nil;
+ if ([GTMXcodePreferences showImageOnMenuItems]) {
+ image = [self imageForMenuItems];
+ }
+ NSEnumerator *keyEnum = [gRegisteredMenuItems keyEnumerator];
+ NSNumber *key;
+ while ((key = [keyEnum nextObject])) {
+ id<GTMXcodeMenuItemProtocol> item = [gRegisteredMenuItems objectForKey:key];
+ NSMenu *insertionMenu = [item insertionMenu];
+ NSMenuItem *menuItem = [insertionMenu itemWithTag:[key intValue]];
+ // play it safe, make sure it's the right target
+ if (menuItem && (item == [menuItem target])) {
+ // if the user wants images and this item should get it, then set the
+ // image. if either wasn't true, just set it to nil to clear the
+ // menu.
+ if (image && [item allowGDTMenuIcon]) {
+ [menuItem setImage:image];
+ } else {
+ [menuItem setImage:nil];
+ }
+ }
+ }
+}
+
++ (NSBundle*)pluginBundle {
+ return [NSBundle bundleForClass:self];
+}
+
++ (float)xCodeVersion {
+ NSBundle *bundle = [NSBundle mainBundle];
+ id object = [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
+ float value = [object floatValue];
+ if (!(value > 0.0)) {
+ NSLog(@"Unable to get Xcode Version");
+ }
+ return value;
+}
+
+@end