Skip to content
Browse files

ARC

  • Loading branch information...
1 parent fd4f80d commit bc94512a30f2a2fdedfa5e0a5f392ca2e0aad05c @mxcl committed
Showing with 764 additions and 2,937 deletions.
  1. +40 −109 ApplicationController.m
  2. +5 −13 DBPrefsWindowController.m
  3. +7 −28 English.lproj/MainMenu.xib
  4. +0 −1 English.lproj/PBRemoteProgressSheet.xib
  5. +0 −35 GLFileView.h
  6. +0 −324 GLFileView.m
  7. +9 −72 GitX.xcodeproj/project.pbxproj
  8. +0 −21 MGScopeBar/MGRecessedPopUpButtonCell.h
  9. +0 −54 MGScopeBar/MGRecessedPopUpButtonCell.m
  10. +0 −51 MGScopeBar/MGScopeBar.h
  11. +0 −1,049 MGScopeBar/MGScopeBar.m
  12. +0 −46 MGScopeBar/MGScopeBarDelegateProtocol.h
  13. +0 −7 MGScopeBar/MGScopeBar_Prefix.pch
  14. +0 −75 MGScopeBar/ReadMe.txt
  15. +0 −104 MGScopeBar/Source Code License.rtf
  16. +0 −9 MGScopeBar/TODO
  17. +2 −2 NSString_RegEx.m
  18. +1 −1 PBDiffWindowController.h
  19. +16 −16 PBGitCommit.h
  20. +0 −4 PBGitCommit.m
  21. +1 −2 PBGitGrapher.mm
  22. +12 −14 PBGitHistoryController.h
  23. +10 −10 PBGitHistoryController.m
  24. +7 −8 PBGitHistoryList.h
  25. +2 −2 PBGitHistoryList.m
  26. +503 −690 PBGitHistoryView.xib
  27. +1 −1 PBGitIndex.h
  28. +2 −2 PBGitIndexController.m
  29. +2 −2 PBGitRef.h
  30. +8 −8 PBGitRepository.h
  31. +1 −2 PBGitRepository.m
  32. +1 −1 PBGitRevList.h
  33. +15 −16 PBGitRevSpecifier.h
  34. +17 −34 PBGitRevSpecifier.m
  35. +1 −1 PBGitRevisionCell.h
  36. +2 −2 PBGitRevisionCell.m
  37. +1 −0 PBGitSVBranchItem.m
  38. +1 −0 PBGitSVRemoteBranchItem.m
  39. +1 −0 PBGitSVTagItem.m
  40. +2 −2 PBGitSidebarController.m
  41. +14 −17 PBGitTree.h
  42. +1 −2 PBGitTree.m
  43. +2 −2 PBGitWindowController.h
  44. +2 −2 PBGitWindowController.m
  45. +4 −4 PBGitXMessageSheet.h
  46. +4 −4 PBGraphCellInfo.h
  47. +4 −8 PBGraphCellInfo.m
  48. +7 −7 PBHistorySearchController.h
  49. +2 −1 PBHistorySearchController.m
  50. +1 −1 PBIconAndTextCell.h
  51. +0 −5 PBIconAndTextCell.m
  52. +3 −5 PBRefController.h
  53. +7 −8 PBRefController.m
  54. +1 −1 PBRefMenuItem.h
  55. +6 −6 PBRemoteProgressSheet.h
  56. +0 −6 PBRepositoryDocumentController.h
  57. +2 −0 PBRepositoryDocumentController.m
  58. +6 −6 PBSourceViewItem.h
  59. +7 −8 PBViewController.h
  60. +2 −2 PBWebChangesController.m
  61. +2 −2 PBWebController.h
  62. +7 −5 PBWebController.m
  63. +2 −2 PBWebDiffController.m
  64. +6 −9 PBWebHistoryController.h
  65. +2 −6 PBWebHistoryController.m
View
149 ApplicationController.m
@@ -16,27 +16,24 @@
#import "PBNSURLPathUserDefaultsTransfomer.h"
#import "PBGitDefaults.h"
+
+
@implementation ApplicationController
-- (ApplicationController*)init
-{
+- (ApplicationController *)init {
#ifdef DEBUG_BUILD
[NSApp activateIgnoringOtherApps:YES];
#endif
- if(!(self = [super init]))
- return nil;
-
- if(![[NSBundle bundleWithPath:@"/System/Library/Frameworks/Quartz.framework/Frameworks/QuickLookUI.framework"] load])
- if(![[NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/QuickLookUI.framework"] load])
- NSLog(@"Could not load QuickLook");
+ if (self = [super init]) {
+ if (![[NSBundle bundleWithPath:@"/System/Library/Frameworks/Quartz.framework/Frameworks/QuickLookUI.framework"] load])
+ if (![[NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/QuickLookUI.framework"] load])
+ NSLog(@"Could not load QuickLook");
- /* Value Transformers */
- NSValueTransformer *transformer = [[PBNSURLPathUserDefaultsTransfomer alloc] init];
- [NSValueTransformer setValueTransformer:transformer forName:@"PBNSURLPathUserDefaultsTransfomer"];
-
- // Make sure the PBGitDefaults is initialized, by calling a random method
- [PBGitDefaults class];
+ [NSValueTransformer setValueTransformer:[PBNSURLPathUserDefaultsTransfomer new] forName:@"PBNSURLPathUserDefaultsTransfomer"];
+
+ [PBGitDefaults class]; // Make sure the PBGitDefaults is initialized, by calling a random method
+ }
return self;
}
@@ -101,9 +98,9 @@ - (void)applicationDidFinishLaunching:(NSNotification*)notification
[[PBRepositoryDocumentController sharedDocumentController] openDocument:self];
}
-- (void) windowWillClose: sender
+- (void)windowWillClose:sender
{
- [firstResponder terminate: sender];
+ [firstResponder terminate:sender];
}
- (IBAction)openPreferencesWindow:(id)sender
@@ -167,13 +164,6 @@ - (IBAction)installCliTool:(id)sender;
}
}
-/**
- Returns the support folder for the application, used to store the Core Data
- store file. This code uses a folder named "GitTest" for
- the content, either in the NSApplicationSupportDirectory location or (if the
- former cannot be found), the system's temporary directory.
- */
-
- (NSString *)applicationSupportFolder {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
@@ -181,111 +171,53 @@ - (NSString *)applicationSupportFolder {
return [basePath stringByAppendingPathComponent:@"GitTest"];
}
-
-/**
- Creates, retains, and returns the managed object model for the application
- by merging all of the models found in the application bundle.
- */
-
- (NSManagedObjectModel *)managedObjectModel {
-
- if (managedObjectModel != nil) {
- return managedObjectModel;
- }
-
- managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];
- return managedObjectModel;
+ return managedObjectModel ?: (managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil]);
}
-
-/**
- Returns the persistent store coordinator for the application. This
- implementation will create and return a coordinator, having added the
- store for the application to it. (The folder for the store is created,
- if necessary.)
- */
-
- (NSPersistentStoreCoordinator *) persistentStoreCoordinator {
-
- if (persistentStoreCoordinator != nil) {
- return persistentStoreCoordinator;
- }
-
- NSFileManager *fileManager;
- NSString *applicationSupportFolder = nil;
- NSURL *url;
- NSError *error;
-
- fileManager = [NSFileManager defaultManager];
- applicationSupportFolder = [self applicationSupportFolder];
- if ( ![fileManager fileExistsAtPath:applicationSupportFolder isDirectory:NULL] ) {
- [fileManager createDirectoryAtPath:applicationSupportFolder withIntermediateDirectories:YES attributes:nil error:nil];
+ if (!persistentStoreCoordinator) {
+ NSFileManager *fileManager;
+ NSString *applicationSupportFolder = nil;
+ NSURL *url;
+ NSError *error;
+
+ fileManager = [NSFileManager defaultManager];
+ applicationSupportFolder = [self applicationSupportFolder];
+ if ( ![fileManager fileExistsAtPath:applicationSupportFolder isDirectory:NULL] ) {
+ [fileManager createDirectoryAtPath:applicationSupportFolder withIntermediateDirectories:YES attributes:nil error:nil];
+ }
+
+ url = [NSURL fileURLWithPath: [applicationSupportFolder stringByAppendingPathComponent: @"GitTest.xml"]];
+ persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
+ if (![persistentStoreCoordinator addPersistentStoreWithType:NSXMLStoreType configuration:nil URL:url options:nil error:&error]){
+ [[NSApplication sharedApplication] presentError:error];
+ }
}
-
- url = [NSURL fileURLWithPath: [applicationSupportFolder stringByAppendingPathComponent: @"GitTest.xml"]];
- persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
- if (![persistentStoreCoordinator addPersistentStoreWithType:NSXMLStoreType configuration:nil URL:url options:nil error:&error]){
- [[NSApplication sharedApplication] presentError:error];
- }
return persistentStoreCoordinator;
}
-
-/**
- Returns the managed object context for the application (which is already
- bound to the persistent store coordinator for the application.)
- */
-
- (NSManagedObjectContext *) managedObjectContext {
-
- if (managedObjectContext != nil) {
- return managedObjectContext;
- }
-
- NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
- if (coordinator != nil) {
- managedObjectContext = [[NSManagedObjectContext alloc] init];
- [managedObjectContext setPersistentStoreCoordinator: coordinator];
+ if (!managedObjectContext) {
+ managedObjectContext = [NSManagedObjectContext new];
+ managedObjectContext.persistentStoreCoordinator = self.persistentStoreCoordinator;
}
-
return managedObjectContext;
}
-
-/**
- Returns the NSUndoManager for the application. In this case, the manager
- returned is that of the managed object context for the application.
- */
-
- (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window {
- return [[self managedObjectContext] undoManager];
+ return self.managedObjectContext.undoManager;
}
-
-
-/**
- Performs the save action for the application, which is to send the save:
- message to the application's managed object context. Any encountered errors
- are presented to the user.
- */
- (IBAction) saveAction:(id)sender {
-
- NSError *error = nil;
+ id error = nil;
if (![[self managedObjectContext] save:&error]) {
- [[NSApplication sharedApplication] presentError:error];
+ [NSApp presentError:error];
}
}
-
-/**
- Implementation of the applicationShouldTerminate: method, used here to
- handle the saving of changes in the application managed object context
- before the application terminates.
- */
-
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
-
NSError *error;
int reply = NSTerminateNow;
@@ -348,10 +280,9 @@ - (void)applicationWillTerminate:(NSNotification *)aNotification
- (void) dealloc {
- [managedObjectContext release], managedObjectContext = nil;
- [persistentStoreCoordinator release], persistentStoreCoordinator = nil;
- [managedObjectModel release], managedObjectModel = nil;
- [super dealloc];
+ managedObjectContext = nil;
+ persistentStoreCoordinator = nil;
+ managedObjectModel = nil;
}
#pragma mark Help menu
View
18 DBPrefsWindowController.m
@@ -74,14 +74,14 @@ - (void)windowDidLoad
// Create a new window to display the preference views.
// If the developer attached a window to this controller
// in Interface Builder, it gets replaced with this one.
- NSPanel *panel = [[[NSPanel alloc] initWithContentRect:NSMakeRect(0,0,1000,1000)
+ NSPanel *panel = [[NSPanel alloc] initWithContentRect:NSMakeRect(0,0,1000,1000)
styleMask:(NSTitledWindowMask |
NSClosableWindowMask |
NSMiniaturizableWindowMask)
backing:NSBackingStoreBuffered
- defer:YES] autorelease];
+ defer:YES];
[self setWindow:panel];
- contentSubview = [[[NSView alloc] initWithFrame:[[[self window] contentView] frame]] autorelease];
+ contentSubview = [[NSView alloc] initWithFrame:[[[self window] contentView] frame]];
[contentSubview setAutoresizingMask:(NSViewMinYMargin | NSViewWidthSizable)];
[[[self window] contentView] addSubview:contentSubview];
[[self window] setShowsToolbarButton:NO];
@@ -90,13 +90,6 @@ - (void)windowDidLoad
-- (void) dealloc {
- [toolbarIdentifiers release];
- [toolbarViews release];
- [toolbarItems release];
- [viewAnimation release];
- [super dealloc];
-}
@@ -129,12 +122,12 @@ - (void)addView:(NSView *)view label:(NSString *)label image:(NSImage *)image
NSAssert (view != nil,
@"Attempted to add a nil view when calling -addView:label:image:.");
- NSString *identifier = [[label copy] autorelease];
+ NSString *identifier = [label copy];
[toolbarIdentifiers addObject:identifier];
[toolbarViews setObject:view forKey:identifier];
- NSToolbarItem *item = [[[NSToolbarItem alloc] initWithItemIdentifier:identifier] autorelease];
+ NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier:identifier];
[item setLabel:label];
[item setImage:image];
[item setTarget:self];
@@ -208,7 +201,6 @@ - (IBAction)showWindow:(id)sender
[toolbar setDisplayMode:NSToolbarDisplayModeIconAndLabel];
[toolbar setDelegate:self];
[[self window] setToolbar:toolbar];
- [toolbar release];
}
NSString *identifier = [self defaultViewIdentifier];
View
35 English.lproj/MainMenu.xib
@@ -2,19 +2,19 @@
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">1070</int>
- <string key="IBDocument.SystemVersion">11D50b</string>
- <string key="IBDocument.InterfaceBuilderVersion">2182</string>
- <string key="IBDocument.AppKitVersion">1138.32</string>
- <string key="IBDocument.HIToolboxVersion">568.00</string>
+ <string key="IBDocument.SystemVersion">12A269</string>
+ <string key="IBDocument.InterfaceBuilderVersion">2549</string>
+ <string key="IBDocument.AppKitVersion">1187</string>
+ <string key="IBDocument.HIToolboxVersion">624.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="NS.object.0">2182</string>
+ <string key="NS.object.0">2549</string>
</object>
<array key="IBDocument.IntegratedClassDependencies">
- <string>NSUserDefaultsController</string>
+ <string>NSCustomObject</string>
<string>NSMenu</string>
<string>NSMenuItem</string>
- <string>NSCustomObject</string>
+ <string>NSUserDefaultsController</string>
</array>
<array key="IBDocument.PluginDependencies">
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
@@ -938,9 +938,6 @@
<object class="NSUserDefaultsController" id="391227374">
<bool key="NSSharedInstance">YES</bool>
</object>
- <object class="NSCustomObject" id="203602687">
- <string key="NSClassName">SUUpdater</string>
- </object>
</array>
<object class="IBObjectContainer" key="IBDocument.Objects">
<array class="NSMutableArray" key="connectionRecords">
@@ -1376,14 +1373,6 @@
</object>
<int key="connectionID">973</int>
</object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">checkForUpdates:</string>
- <reference key="source" ref="203602687"/>
- <reference key="destination" ref="679871620"/>
- </object>
- <int key="connectionID">920</int>
- </object>
</array>
<object class="IBMutableOrderedSet" key="objectRecords">
<array key="orderedObjects">
@@ -1978,11 +1967,6 @@
<reference key="parent" ref="245837913"/>
</object>
<object class="IBObjectRecord">
- <int key="objectID">918</int>
- <reference key="object" ref="203602687"/>
- <reference key="parent" ref="0"/>
- </object>
- <object class="IBObjectRecord">
<int key="objectID">919</int>
<reference key="object" ref="679871620"/>
<reference key="parent" ref="492995933"/>
@@ -2169,7 +2153,6 @@
<string key="912.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="915.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="916.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="918.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="919.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="927.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="928.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
@@ -2235,10 +2218,6 @@
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>
<real value="1070" key="NS.object.0"/>
</object>
- <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
- <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>
- <real value="1070" key="NS.object.0"/>
- </object>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
<real value="4300" key="NS.object.0"/>
View
1 English.lproj/PBRemoteProgressSheet.xib
@@ -53,7 +53,6 @@
<int key="NSvFlags">1314</int>
<string key="NSFrame">{{18, 16}, {361, 20}}</string>
<reference key="NSSuperview" ref="1006"/>
- <reference key="NSNextKeyView"/>
<int key="NSpiFlags">16394</int>
<double key="NSMaxValue">100</double>
</object>
View
35 GLFileView.h
@@ -1,35 +0,0 @@
-//
-// GLFileView.h
-// GitX
-//
-// Created by German Laullon on 14/09/10.
-// Copyright 2010 __MyCompanyName__. All rights reserved.
-//
-
-#import <Cocoa/Cocoa.h>
-#import "PBWebController.h"
-#import "MGScopeBarDelegateProtocol.h"
-#import "PBGitCommit.h"
-#import "PBGitHistoryController.h"
-#import "PBRefContextDelegate.h"
-
-@class PBGitGradientBarView;
-
-@interface GLFileView : PBWebController <MGScopeBarDelegate> {
- IBOutlet PBGitHistoryController* historyController;
- IBOutlet MGScopeBar *typeBar;
- NSMutableArray *groups;
- NSString *logFormat;
- IBOutlet NSView *accessoryView;
- IBOutlet NSSplitView *fileListSplitView;
-}
-
-- (void)showFile;
-- (void)didLoad;
-- (NSString *)parseBlame:(NSString *)txt;
-- (NSString *)parseHTML:(NSString *)txt;
-
-@property(retain) NSMutableArray *groups;
-@property(retain) NSString *logFormat;
-
-@end
View
324 GLFileView.m
@@ -1,324 +0,0 @@
-//
-// GLFileView.m
-// GitX
-//
-// Created by German Laullon on 14/09/10.
-// Copyright 2010 __MyCompanyName__. All rights reserved.
-//
-
-#import "GLFileView.h"
-#import "PBGitGradientBarView.h"
-
-#define GROUP_LABEL @"Label" // string
-#define GROUP_SEPARATOR @"HasSeparator" // BOOL as NSNumber
-#define GROUP_SELECTION_MODE @"SelectionMode" // MGScopeBarGroupSelectionMode (int) as NSNumber
-#define GROUP_ITEMS @"Items" // array of dictionaries, each containing the following keys:
-#define ITEM_IDENTIFIER @"Identifier" // string
-#define ITEM_NAME @"Name" // string
-
-
-@interface GLFileView ()
-
-- (void)saveSplitViewPosition;
-
-@end
-
-
-@implementation GLFileView
-
-- (void) awakeFromNib
-{
- NSString *formatFile = [[NSBundle mainBundle] pathForResource:@"format" ofType:@"html" inDirectory:@"html/views/log"];
- if(formatFile!=nil)
- logFormat=[NSString stringWithContentsOfURL:[NSURL fileURLWithPath:formatFile] encoding:NSUTF8StringEncoding error:nil];
-
-
- startFile = @"fileview";
- //repository = historyController.repository;
- [super awakeFromNib];
- [historyController.treeController addObserver:self forKeyPath:@"selection" options:0 context:@"treeController"];
-
- self.groups = [NSMutableArray arrayWithCapacity:0];
-
- NSArray *items = [NSArray arrayWithObjects:
- [NSDictionary dictionaryWithObjectsAndKeys:
- startFile, ITEM_IDENTIFIER,
- @"Source", ITEM_NAME,
- nil],
- [NSDictionary dictionaryWithObjectsAndKeys:
- @"blame", ITEM_IDENTIFIER,
- @"Blame", ITEM_NAME,
- nil],
- [NSDictionary dictionaryWithObjectsAndKeys:
- @"log", ITEM_IDENTIFIER,
- @"History", ITEM_NAME,
- nil],
- nil];
- [self.groups addObject:[NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithBool:NO], GROUP_SEPARATOR,
- [NSNumber numberWithInt:MGRadioSelectionMode], GROUP_SELECTION_MODE, // single selection group.
- items, GROUP_ITEMS,
- nil]];
- [typeBar reloadData];
-
- [fileListSplitView setHidden:YES];
- [self performSelector:@selector(restoreSplitViewPositiion) withObject:nil afterDelay:0];
-}
-
-- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
-{
- //NSLog(@"keyPath=%@ change=%@ context=%@ object=%@ \n %@",keyPath,change,context,object,[historyController.treeController selectedObjects]);
- [self showFile];
-}
-
-- (void) showFile
-{
- NSArray *files=[historyController.treeController selectedObjects];
- if ([files count]>0) {
- PBGitTree *file=[files objectAtIndex:0];
-
- NSString *fileTxt=@"";
- if(startFile==@"fileview")
- fileTxt=[self parseHTML:[file textContents]];
- else if(startFile==@"blame")
- fileTxt=[self parseBlame:[file blame]];
- else if(startFile==@"log")
- fileTxt=[file log:logFormat];
-
- id script = [view windowScriptObject];
- [script callWebScriptMethod:@"showFile" withArguments:[NSArray arrayWithObject:fileTxt]];
- }
-
-#if 0
- NSString *dom=[[[[view mainFrame] DOMDocument] documentElement] outerHTML];
- NSString *tmpFile=@"~/tmp/test.html";
- [dom writeToFile:[tmpFile stringByExpandingTildeInPath] atomically:true encoding:NSUTF8StringEncoding error:nil];
-#endif
-}
-
-#pragma mark JavaScript log.js methods
-
-- (void) selectCommit:(NSString*)c
-{
- [historyController selectCommit:[PBGitSHA shaWithString:c]];
-}
-
-#pragma mark MGScopeBarDelegate methods
-
-- (int)numberOfGroupsInScopeBar:(MGScopeBar *)theScopeBar
-{
- return [self.groups count];
-}
-
-
-- (NSArray *)scopeBar:(MGScopeBar *)theScopeBar itemIdentifiersForGroup:(int)groupNumber
-{
- return [[self.groups objectAtIndex:groupNumber] valueForKeyPath:[NSString stringWithFormat:@"%@.%@", GROUP_ITEMS, ITEM_IDENTIFIER]];
-}
-
-
-- (NSString *)scopeBar:(MGScopeBar *)theScopeBar labelForGroup:(int)groupNumber
-{
- return [[self.groups objectAtIndex:groupNumber] objectForKey:GROUP_LABEL]; // might be nil, which is fine (nil means no label).
-}
-
-
-- (NSString *)scopeBar:(MGScopeBar *)theScopeBar titleOfItem:(NSString *)identifier inGroup:(int)groupNumber
-{
- NSArray *items = [[self.groups objectAtIndex:groupNumber] objectForKey:GROUP_ITEMS];
- if (items) {
- for (NSDictionary *item in items) {
- if ([[item objectForKey:ITEM_IDENTIFIER] isEqualToString:identifier]) {
- return [item objectForKey:ITEM_NAME];
- break;
- }
- }
- }
- return nil;
-}
-
-
-- (MGScopeBarGroupSelectionMode)scopeBar:(MGScopeBar *)theScopeBar selectionModeForGroup:(int)groupNumber
-{
- return [[[self.groups objectAtIndex:groupNumber] objectForKey:GROUP_SELECTION_MODE] intValue];
-}
-
-- (void)scopeBar:(MGScopeBar *)theScopeBar selectedStateChanged:(BOOL)selected forItem:(NSString *)identifier inGroup:(int)groupNumber
-{
- startFile=identifier;
- NSString *path = [NSString stringWithFormat:@"html/views/%@", identifier];
- NSString *html = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html" inDirectory:path];
- NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL fileURLWithPath:html]];
- [[view mainFrame] loadRequest:request];
-}
-
-- (NSView *)accessoryViewForScopeBar:(MGScopeBar *)scopeBar
-{
- return accessoryView;
-}
-
-- (void) didLoad
-{
- [self showFile];
-}
-
-- (void)closeView
-{
- [historyController.treeController removeObserver:self forKeyPath:@"selection"];
- [self saveSplitViewPosition];
-
- [super closeView];
-}
-
-- (NSString *) parseHTML:(NSString *)txt
-{
- txt=[txt stringByReplacingOccurrencesOfString:@"&" withString:@"&amp;"];
- txt=[txt stringByReplacingOccurrencesOfString:@"<" withString:@"&lt;"];
- txt=[txt stringByReplacingOccurrencesOfString:@">" withString:@"&gt;"];
-
- return txt;
-}
-
-- (NSString *) parseBlame:(NSString *)txt
-{
- txt=[self parseHTML:txt];
-
- NSArray *lines = [txt componentsSeparatedByString:@"\n"];
- NSString *line;
- NSMutableDictionary *headers=[NSMutableDictionary dictionary];
- NSMutableString *res=[NSMutableString string];
-
- [res appendString:@"<table class='blocks'>\n"];
- int i=0;
- while(i<[lines count]){
- line=[lines objectAtIndex:i];
- NSArray *header=[line componentsSeparatedByString:@" "];
- if([header count]==4){
- int nLines=[(NSString *)[header objectAtIndex:3] intValue];
- [res appendFormat:@"<tr class='block l%d'>\n",nLines];
- line=[lines objectAtIndex:++i];
- if([[[line componentsSeparatedByString:@" "] objectAtIndex:0] isEqual:@"author"]){
- NSString *author=[line stringByReplacingOccurrencesOfString:@"author" withString:@""];
- NSString *summary=nil;
- while(summary==nil){
- line=[lines objectAtIndex:i++];
- if([[[line componentsSeparatedByString:@" "] objectAtIndex:0] isEqual:@"summary"]){
- summary=[line stringByReplacingOccurrencesOfString:@"summary" withString:@""];
- }
- }
- NSRange trunc={0,30};
- NSString *truncate_a=author;
- if([author length]>30){
- truncate_a=[author substringWithRange:trunc];
- }
- NSString *truncate_s=summary;
- if([summary length]>30){
- truncate_s=[summary substringWithRange:trunc];
- }
- NSString *block=[NSString stringWithFormat:@"<td><p class='author'>%@</p><p class='summary'>%@</p></td>\n<td>\n",truncate_a,truncate_s];
- [headers setObject:block forKey:[header objectAtIndex:0]];
- }
- [res appendString:[headers objectForKey:[header objectAtIndex:0]]];
-
- NSMutableString *code=[NSMutableString string];
- do{
- line=[lines objectAtIndex:i++];
- }while([line characterAtIndex:0]!='\t');
- line=[line substringFromIndex:1];
- line=[line stringByReplacingOccurrencesOfString:@"\t" withString:@"&nbsp;&nbsp;&nbsp;&nbsp;"];
- [code appendString:line];
- [code appendString:@"\n"];
-
- int n;
- for(n=1;n<nLines;n++){
- line=[lines objectAtIndex:i++];
- do{
- line=[lines objectAtIndex:i++];
- }while([line characterAtIndex:0]!='\t');
- line=[line substringFromIndex:1];
- line=[line stringByReplacingOccurrencesOfString:@"\t" withString:@"&nbsp;&nbsp;&nbsp;&nbsp;"];
- [code appendString:line];
- [code appendString:@"\n"];
- }
- [res appendFormat:@"<pre class='first-line: %@;brush: objc'>%@</pre>",[header objectAtIndex:2],code];
- [res appendString:@"</td>\n"];
- }else{
- break;
- }
- [res appendString:@"</tr>\n"];
- }
- [res appendString:@"</table>\n"];
- //NSLog(@"%@",res);
-
- return (NSString *)res;
-}
-
-
-
-#pragma mark NSSplitView delegate methods
-
-#define kFileListSplitViewLeftMin 120
-#define kFileListSplitViewRightMin 180
-#define kHFileListSplitViewPositionDefault @"File List SplitView Position"
-
-- (CGFloat)splitView:(NSSplitView *)splitView constrainMinCoordinate:(CGFloat)proposedMin ofSubviewAt:(NSInteger)dividerIndex
-{
- return kFileListSplitViewLeftMin;
-}
-
-- (CGFloat)splitView:(NSSplitView *)splitView constrainMaxCoordinate:(CGFloat)proposedMax ofSubviewAt:(NSInteger)dividerIndex
-{
- return [splitView frame].size.width - [splitView dividerThickness] - kFileListSplitViewRightMin;
-}
-
-// while the user resizes the window keep the left (file list) view constant and just resize the right view
-// unless the right view gets too small
-- (void)splitView:(NSSplitView *)splitView resizeSubviewsWithOldSize:(NSSize)oldSize
-{
- NSRect newFrame = [splitView frame];
-
- float dividerThickness = [splitView dividerThickness];
-
- NSView *leftView = [[splitView subviews] objectAtIndex:0];
- NSRect leftFrame = [leftView frame];
- leftFrame.size.height = newFrame.size.height;
-
- if ((newFrame.size.width - leftFrame.size.width - dividerThickness) < kFileListSplitViewRightMin) {
- leftFrame.size.width = newFrame.size.width - kFileListSplitViewRightMin - dividerThickness;
- }
-
- NSView *rightView = [[splitView subviews] objectAtIndex:1];
- NSRect rightFrame = [rightView frame];
- rightFrame.origin.x = leftFrame.size.width + dividerThickness;
- rightFrame.size.width = newFrame.size.width - rightFrame.origin.x;
- rightFrame.size.height = newFrame.size.height;
-
- [leftView setFrame:leftFrame];
- [rightView setFrame:rightFrame];
-}
-
-// NSSplitView does not save and restore the position of the SplitView correctly so do it manually
-- (void)saveSplitViewPosition
-{
- float position = [[[fileListSplitView subviews] objectAtIndex:0] frame].size.width;
- [[NSUserDefaults standardUserDefaults] setFloat:position forKey:kHFileListSplitViewPositionDefault];
- [[NSUserDefaults standardUserDefaults] synchronize];
-}
-
-// make sure this happens after awakeFromNib
-- (void)restoreSplitViewPositiion
-{
- float position = [[NSUserDefaults standardUserDefaults] floatForKey:kHFileListSplitViewPositionDefault];
- if (position < 1.0)
- position = 200;
-
- [fileListSplitView setPosition:position ofDividerAtIndex:0];
- [fileListSplitView setHidden:NO];
-}
-
-
-
-@synthesize groups;
-@synthesize logFormat;
-
-@end
View
81 GitX.xcodeproj/project.pbxproj
@@ -10,12 +10,6 @@
02B41A5E123E307200DFC531 /* PBCommitHookFailedSheet.m in Sources */ = {isa = PBXBuildFile; fileRef = 02B41A5D123E307200DFC531 /* PBCommitHookFailedSheet.m */; };
02B41A60123E307F00DFC531 /* PBCommitHookFailedSheet.xib in Resources */ = {isa = PBXBuildFile; fileRef = 02B41A5F123E307F00DFC531 /* PBCommitHookFailedSheet.xib */; };
056438B70ED0C40B00985397 /* DetailViewTemplate.png in Resources */ = {isa = PBXBuildFile; fileRef = 056438B60ED0C40B00985397 /* DetailViewTemplate.png */; };
- 310DC1D81240599E0017A0F7 /* GLFileView.m in Sources */ = {isa = PBXBuildFile; fileRef = 310DC1D71240599E0017A0F7 /* GLFileView.m */; };
- 31460CD2124185BA00B90AED /* MGRecessedPopUpButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 31460CA7124185BA00B90AED /* MGRecessedPopUpButtonCell.m */; };
- 31460CD3124185BA00B90AED /* MGScopeBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 31460CA9124185BA00B90AED /* MGScopeBar.m */; };
- 31460CD4124185BA00B90AED /* ReadMe.txt in Resources */ = {isa = PBXBuildFile; fileRef = 31460CAF124185BA00B90AED /* ReadMe.txt */; };
- 31460CD5124185BA00B90AED /* Source Code License.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 31460CB0124185BA00B90AED /* Source Code License.rtf */; };
- 31460CD6124185BA00B90AED /* TODO in Resources */ = {isa = PBXBuildFile; fileRef = 31460CB1124185BA00B90AED /* TODO */; };
3BC07F4C0ED5A5C5009A7768 /* HistoryViewTemplate.png in Resources */ = {isa = PBXBuildFile; fileRef = 3BC07F4A0ED5A5C5009A7768 /* HistoryViewTemplate.png */; };
3BC07F4D0ED5A5C5009A7768 /* CommitViewTemplate.png in Resources */ = {isa = PBXBuildFile; fileRef = 3BC07F4B0ED5A5C5009A7768 /* CommitViewTemplate.png */; };
47DBDB580E94EDE700671A1E /* DBPrefsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 47DBDB570E94EDE700671A1E /* DBPrefsWindowController.m */; };
@@ -186,17 +180,6 @@
29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
- 310DC1D61240599E0017A0F7 /* GLFileView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLFileView.h; sourceTree = "<group>"; };
- 310DC1D71240599E0017A0F7 /* GLFileView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLFileView.m; sourceTree = "<group>"; };
- 31460CA6124185BA00B90AED /* MGRecessedPopUpButtonCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGRecessedPopUpButtonCell.h; sourceTree = "<group>"; };
- 31460CA7124185BA00B90AED /* MGRecessedPopUpButtonCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGRecessedPopUpButtonCell.m; sourceTree = "<group>"; };
- 31460CA8124185BA00B90AED /* MGScopeBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGScopeBar.h; sourceTree = "<group>"; };
- 31460CA9124185BA00B90AED /* MGScopeBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGScopeBar.m; sourceTree = "<group>"; };
- 31460CAD124185BA00B90AED /* MGScopeBar_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGScopeBar_Prefix.pch; sourceTree = "<group>"; };
- 31460CAE124185BA00B90AED /* MGScopeBarDelegateProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGScopeBarDelegateProtocol.h; sourceTree = "<group>"; };
- 31460CAF124185BA00B90AED /* ReadMe.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ReadMe.txt; sourceTree = "<group>"; };
- 31460CB0124185BA00B90AED /* Source Code License.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = "Source Code License.rtf"; sourceTree = "<group>"; };
- 31460CB1124185BA00B90AED /* TODO */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = TODO; sourceTree = "<group>"; };
32CA4F630368D1EE00C91783 /* GitX_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GitX_Prefix.pch; sourceTree = "<group>"; };
3BC07F4A0ED5A5C5009A7768 /* HistoryViewTemplate.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = HistoryViewTemplate.png; path = Images/HistoryViewTemplate.png; sourceTree = "<group>"; };
3BC07F4B0ED5A5C5009A7768 /* CommitViewTemplate.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = CommitViewTemplate.png; path = Images/CommitViewTemplate.png; sourceTree = "<group>"; };
@@ -533,31 +516,6 @@
name = Frameworks;
sourceTree = "<group>";
};
- 310DC1D5124059820017A0F7 /* FileView */ = {
- isa = PBXGroup;
- children = (
- 310DC1D61240599E0017A0F7 /* GLFileView.h */,
- 310DC1D71240599E0017A0F7 /* GLFileView.m */,
- );
- name = FileView;
- sourceTree = "<group>";
- };
- 31460C79124185B900B90AED /* MGScopeBar */ = {
- isa = PBXGroup;
- children = (
- 31460CA6124185BA00B90AED /* MGRecessedPopUpButtonCell.h */,
- 31460CA7124185BA00B90AED /* MGRecessedPopUpButtonCell.m */,
- 31460CA8124185BA00B90AED /* MGScopeBar.h */,
- 31460CA9124185BA00B90AED /* MGScopeBar.m */,
- 31460CAD124185BA00B90AED /* MGScopeBar_Prefix.pch */,
- 31460CAE124185BA00B90AED /* MGScopeBarDelegateProtocol.h */,
- 31460CAF124185BA00B90AED /* ReadMe.txt */,
- 31460CB0124185BA00B90AED /* Source Code License.rtf */,
- 31460CB1124185BA00B90AED /* TODO */,
- );
- path = MGScopeBar;
- sourceTree = "<group>";
- };
47DBDB920E94F47200671A1E /* Preference Icons */ = {
isa = PBXGroup;
children = (
@@ -788,7 +746,6 @@
F57CC3850E05DDC1000472E2 /* Controllers */ = {
isa = PBXGroup;
children = (
- 310DC1D5124059820017A0F7 /* FileView */,
F58DB55610566D1F00CFDF4A /* Sidebar */,
F5B161BB0EAB6E0C005A1DE1 /* Diff */,
F5EF8C880E9D498F0050906B /* History */,
@@ -819,7 +776,6 @@
F57CC43E0E05E472000472E2 /* Aux */ = {
isa = PBXGroup;
children = (
- 31460C79124185B900B90AED /* MGScopeBar */,
47DBDBC80E95016F00671A1E /* PBNSURLPathUserDefaultsTransfomer.h */,
47DBDBC90E95016F00671A1E /* PBNSURLPathUserDefaultsTransfomer.m */,
F5AD56770E79B78100EDAAFE /* PBCommitList.h */,
@@ -1121,9 +1077,6 @@
D8022FE811E124A0003C21F6 /* PBGitXMessageSheet.xib in Resources */,
D8F01C4B12182F19007F729F /* GitX.sdef in Resources */,
D8F4AB7912298CE200D6D53C /* rewindImage.pdf in Resources */,
- 31460CD4124185BA00B90AED /* ReadMe.txt in Resources */,
- 31460CD5124185BA00B90AED /* Source Code License.rtf in Resources */,
- 31460CD6124185BA00B90AED /* TODO in Resources */,
02B41A60123E307F00DFC531 /* PBCommitHookFailedSheet.xib in Resources */,
6387450F15C083EE00F12271 /* config.h.in in Resources */,
);
@@ -1235,9 +1188,6 @@
D8F01D531218A164007F729F /* NSApplication+GitXScripting.m in Sources */,
D8B4DC571220D1E4004166D6 /* PBHistorySearchController.m in Sources */,
D8712A00122B14EC00012334 /* GitXTextFieldCell.m in Sources */,
- 310DC1D81240599E0017A0F7 /* GLFileView.m in Sources */,
- 31460CD2124185BA00B90AED /* MGRecessedPopUpButtonCell.m in Sources */,
- 31460CD3124185BA00B90AED /* MGScopeBar.m in Sources */,
02B41A5E123E307200DFC531 /* PBCommitHookFailedSheet.m in Sources */,
6387450D15C083EE00F12271 /* commit.c in Sources */,
6387450E15C083EE00F12271 /* errors.c in Sources */,
@@ -1320,6 +1270,7 @@
26FC0A850875C7B200E6366F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ CLANG_ENABLE_OBJC_ARC = YES;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -1346,6 +1297,7 @@
26FC0A860875C7B200E6366F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ CLANG_ENABLE_OBJC_ARC = YES;
COMBINE_HIDPI_IMAGES = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
FRAMEWORK_SEARCH_PATHS = (
@@ -1371,7 +1323,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
- GCC_ENABLE_OBJC_GC = required;
+ GCC_ENABLE_OBJC_GC = unsupported;
GCC_PREPROCESSOR_DEFINITIONS = DEBUG;
GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = DEBUG_BUILD;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
@@ -1386,7 +1338,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
- GCC_ENABLE_OBJC_GC = required;
+ GCC_ENABLE_OBJC_GC = unsupported;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INFOPLIST_PREFIX_HEADER = "";
@@ -1400,12 +1352,11 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ENABLE_OBJC_ARC = YES;
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
- GCC_PRECOMPILE_PREFIX_HEADER = YES;
- GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
INSTALL_PATH = /usr/local/bin;
OTHER_LDFLAGS = (
"-framework",
@@ -1414,7 +1365,6 @@
AppKit,
);
PRODUCT_NAME = gitx_askpasswd;
- SDKROOT = macosx;
};
name = Debug;
};
@@ -1422,11 +1372,10 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ENABLE_OBJC_ARC = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
GCC_MODEL_TUNING = G5;
- GCC_PRECOMPILE_PREFIX_HEADER = YES;
- GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
INSTALL_PATH = /usr/local/bin;
OTHER_LDFLAGS = (
"-framework",
@@ -1435,7 +1384,6 @@
AppKit,
);
PRODUCT_NAME = gitx_askpasswd;
- SDKROOT = macosx;
ZERO_LINK = NO;
};
name = Release;
@@ -1444,9 +1392,8 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ENABLE_OBJC_ARC = YES;
GCC_MODEL_TUNING = G5;
- GCC_PRECOMPILE_PREFIX_HEADER = YES;
- GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
INSTALL_PATH = /usr/local/bin;
OTHER_LDFLAGS = (
"-framework",
@@ -1455,21 +1402,16 @@
AppKit,
);
PRODUCT_NAME = gitx_askpasswd;
- SDKROOT = macosx;
};
name = Install;
};
913D5E4B0E55644600CECEA2 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ CLANG_ENABLE_OBJC_ARC = YES;
COPY_PHASE_STRIP = NO;
- GCC_DYNAMIC_NO_PIC = NO;
- GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
- GCC_PRECOMPILE_PREFIX_HEADER = YES;
- GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
INSTALL_PATH = /usr/local/bin;
- LIBRARY_SEARCH_PATHS = libgit2;
OTHER_LDFLAGS = (
"-framework",
Foundation,
@@ -1478,20 +1420,16 @@
);
PRODUCT_NAME = gitx;
SDKROOT = macosx;
- ZERO_LINK = YES;
};
name = Debug;
};
913D5E4C0E55644600CECEA2 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ CLANG_ENABLE_OBJC_ARC = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
- GCC_MODEL_TUNING = G5;
- GCC_PRECOMPILE_PREFIX_HEADER = YES;
- GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
INSTALL_PATH = /usr/local/bin;
- LIBRARY_SEARCH_PATHS = libgit2;
OTHER_LDFLAGS = (
"-framework",
Foundation,
@@ -1500,7 +1438,6 @@
);
PRODUCT_NAME = gitx;
SDKROOT = macosx;
- ZERO_LINK = NO;
};
name = Release;
};
View
21 MGScopeBar/MGRecessedPopUpButtonCell.h
@@ -1,21 +0,0 @@
-//
-// MGRecessedPopUpButtonCell.h
-// MGScopeBar
-//
-// Created by Matt Gemmell on 20/03/2008.
-// Copyright 2008 Instinctive Code.
-//
-
-#import <Cocoa/Cocoa.h>
-
-/*
- This cell class is used only for NSPopUpButtons which do NOT automatically
- get their titles from their selected menu-items, since such popup-buttons
- are weirdly broken when using the recessed bezel-style.
-*/
-
-@interface MGRecessedPopUpButtonCell : NSPopUpButtonCell {
- NSButton *recessedButton; // we use a separate NSButton to do the bezel-drawing.
-}
-
-@end
View
54 MGScopeBar/MGRecessedPopUpButtonCell.m
@@ -1,54 +0,0 @@
-//
-// MGRecessedPopUpButtonCell.m
-// MGScopeBar
-//
-// Created by Matt Gemmell on 20/03/2008.
-// Copyright 2008 Instinctive Code.
-//
-
-#import "MGRecessedPopUpButtonCell.h"
-
-
-@implementation MGRecessedPopUpButtonCell
-
-
-- (id)initTextCell:(NSString *)title pullsDown:(BOOL)pullsDown
-{
- if ((self = [super initTextCell:title pullsDown:pullsDown])) {
- recessedButton = [[NSButton alloc] initWithFrame:NSMakeRect(0, 0, 30, 20)]; // arbitrary frame.
- [recessedButton setTitle:@""];
- [recessedButton setBezelStyle:NSRecessedBezelStyle];
- [recessedButton setButtonType:NSPushOnPushOffButton];
- [[recessedButton cell] setHighlightsBy:NSCellIsBordered | NSCellIsInsetButton];
- [recessedButton setShowsBorderOnlyWhileMouseInside:NO];
- [recessedButton setState:NSOnState]; // ensures it looks pushed-in.
- }
- return self;
-}
-
-
-- (void)dealloc
-{
- [recessedButton release];
- [super dealloc];
-}
-
-
-- (void)drawTitleWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
-{
- // Inset title rect since its position is broken when NSPopUpButton
- // isn't using its selected item as its title.
- NSRect titleFrame = cellFrame;
- titleFrame.origin.y += 1.0;
- [super drawTitleWithFrame:titleFrame inView:controlView];
-}
-
-
-- (void)drawBezelWithFrame:(NSRect)frame inView:(NSView *)controlView
-{
- [recessedButton setFrame:frame];
- [recessedButton drawRect:frame];
-}
-
-
-@end
View
51 MGScopeBar/MGScopeBar.h
@@ -1,51 +0,0 @@
-//
-// MGScopeBar.h
-// MGScopeBar
-//
-// Created by Matt Gemmell on 15/03/2008.
-// Copyright 2008 Instinctive Code.
-//
-
-#import <Cocoa/Cocoa.h>
-#import "MGScopeBarDelegateProtocol.h"
-
-@interface MGScopeBar : NSView {
-@private
- IBOutlet id <MGScopeBarDelegate, NSObject> delegate; // weak ref.
- NSMutableArray *_separatorPositions; // x-coords of separators, indexed by their group-number.
- NSMutableArray *_groups; // groups of items.
- NSView *_accessoryView; // weak ref since it's a subview.
- NSMutableDictionary *_identifiers; // map of identifiers to items.
- NSMutableArray *_selectedItems; // all selected items in all groups; see note below.
- float _lastWidth; // previous width of view from when we last resized.
- NSInteger _firstCollapsedGroup; // index of first group collapsed into a popup.
- float _totalGroupsWidthForPopups; // total width needed to show all groups expanded (excluding padding and accessory).
- float _totalGroupsWidth; // total width needed to show all groups as native-width popups (excluding padding and accessory).
- BOOL _smartResizeEnabled; // whether to do our clever collapsing/expanding of buttons when resizing (Smart Resizing).
-}
-
-@property(assign) id delegate; // should implement the MGScopeBarDelegate protocol.
-
-- (void)reloadData; // causes the scope-bar to reload all groups/items from its delegate.
-- (void)sizeToFit; // only resizes vertically to optimum height; does not affect width.
-- (void)adjustSubviews; // performs Smart Resizing if enabled. You should only need to call this yourself if you change the width of the accessoryView.
-
-// Smart Resize is the intelligent conversion of button-groups into NSPopUpButtons and vice-versa, based on available space.
-// This functionality is enabled (YES) by default. Changing this setting will automatically call -reloadData.
-- (BOOL)smartResizeEnabled;
-- (void)setSmartResizeEnabled:(BOOL)enabled;
-
-// The following method must be used to manage selections in the scope-bar; do not attempt to manipulate buttons etc directly.
-- (void)setSelected:(BOOL)selected forItem:(NSString *)identifier inGroup:(int)groupNumber;
-- (NSArray *)selectedItems;
-
-/*
- Note: The -selectedItems method returns an array of arrays.
- Each index in the returned array represents the group of items at that index.
- The contents of each sub-array are the identifiers of each selected item in that group.
- Sub-arrays may be empty, but will always be present (i.e. you will always find an NSArray).
- Depending on the group's selection-mode, sub-arrays may contain zero, one or many identifiers.
- The identifiers in each sub-array are not in any particular order.
- */
-
-@end
View
1,049 MGScopeBar/MGScopeBar.m
@@ -1,1049 +0,0 @@
-//
-// MGScopeBar.m
-// MGScopeBar
-//
-// Created by Matt Gemmell on 15/03/2008.
-// Copyright 2008 Instinctive Code.
-//
-
-#import "MGScopeBar.h"
-#import "MGRecessedPopUpButtonCell.h"
-
-
-#define SCOPE_BAR_H_INSET 8.0 // inset on left and right
-#define SCOPE_BAR_HEIGHT 25.0 // used in -sizeToFit
-#define SCOPE_BAR_START_COLOR_GRAY [NSColor colorWithCalibratedWhite:0.75 alpha:1.0] // bottom color of gray gradient
-#define SCOPE_BAR_END_COLOR_GRAY [NSColor colorWithCalibratedWhite:0.90 alpha:1.0] // top color of gray gradient
-#define SCOPE_BAR_START_COLOR_BLUE [NSColor colorWithCalibratedRed:0.71 green:0.75 blue:0.81 alpha:1.0] // bottom color of blue gradient
-#define SCOPE_BAR_END_COLOR_BLUE [NSColor colorWithCalibratedRed:0.80 green:0.82 blue:0.87 alpha:1.0] // top color of blue gradient
-#define SCOPE_BAR_BORDER_COLOR [NSColor colorWithCalibratedWhite:0.69 alpha:1.0] // bottom line's color
-#define SCOPE_BAR_BORDER_WIDTH 1.0 // bottom line's width
-
-#define SCOPE_BAR_SEPARATOR_COLOR [NSColor colorWithCalibratedWhite:0.52 alpha:1.0] // color of vertical-line separators between groups
-#define SCOPE_BAR_SEPARATOR_WIDTH 1.0 // width of vertical-line separators between groups
-#define SCOPE_BAR_SEPARATOR_HEIGHT 16.0 // separators are vertically centered in the bar
-
-#define SCOPE_BAR_LABEL_COLOR [NSColor colorWithCalibratedWhite:0.45 alpha:1.0] // color of groups' labels
-#define SCOPE_BAR_FONTSIZE 12.0 // font-size of labels and buttons
-#define SCOPE_BAR_ITEM_SPACING 6.0 // spacing between buttons/separators/labels
-#define SCOPE_BAR_BUTTON_IMAGE_SIZE 16.0 // size of buttons' images (width and height)
-
-#define SCOPE_BAR_HIDE_POPUP_BG YES // whether the bezel background of an NSPopUpButton is hidden when none of its menu-items are selected.
-
-// Appearance metrics. These were chosen to mimic the Finder's "Find" (Spotlight / Smart Group / etc) window's scope-bar.
-#define MENU_PADDING 25.0 // how much wider a popup-button is than a regular button with the same title.
-#define MENU_MIN_WIDTH 60.0 // minimum width a popup-button can be narrowed to.
-
-// NSPopUpButton titles used for groups which allow multiple selection.
-#define POPUP_TITLE_EMPTY_SELECTION NSLocalizedString(@"(None)", nil) // title used when no items in the popup are selected.
-#define POPUP_TITLE_MULTIPLE_SELECTION NSLocalizedString(@"(Multiple)", nil) // title used when multiple items in the popup are selected.
-
-
-// ---- end of configurable settings ---- //
-
-
-// Keys for internal use.
-#define GROUP_IDENTIFIERS @"Identifiers" // NSMutableArray of identifier strings.
-#define GROUP_BUTTONS @"Buttons" // NSMutableArray of either NSButtons or NSMenuItems, one per item.
-#define GROUP_SELECTION_MODE @"SelectionMode" // MGScopeBarGroupSelectionMode (int) as NSNumber.
-#define GROUP_MENU_MODE @"MenuMode" // BOOL, YES if group is collected in a popup-menu, else NO.
-#define GROUP_POPUP_BUTTON @"PopupButton" // NSPopUpButton (only present if group is in menu-mode).
-#define GROUP_HAS_SEPARATOR @"HasSeparator" // BOOL, YES if group has a separator before it.
-#define GROUP_HAS_LABEL @"HasLabel" // BOOL, YES if group has a label.
-#define GROUP_LABEL_FIELD @"LabelField" // NSTextField for the label (optional; only if group has a label)
-#define GROUP_TOTAL_BUTTONS_WIDTH @"TotalButtonsWidth" // Width of all buttons in a group plus spacings between them (doesn't include label etc)
-#define GROUP_WIDEST_BUTTON_WIDTH @"WidestButtonWidth" // Width of widest button, used when making popup-menus.
-#define GROUP_CUMULATIVE_WIDTH @"CumulativeWidth" // Width from left of leftmost group to right of this group (all groups fully expanded).
-
-
-@interface MGScopeBar (MGPrivateMethods)
-
-- (IBAction)scopeButtonClicked:(id)sender;
-- (NSButton *)getButtonForItem:(NSString *)identifier inGroup:(int)groupNumber; // returns relevant button/menu-item
-- (void)updateSelectedState:(BOOL)selected forItem:(NSString *)identifier inGroup:(int)groupNumber informDelegate:(BOOL)inform;
-- (NSButton *)buttonForItem:(NSString *)identifier inGroup:(int)groupNumber
- withTitle:(NSString *)title image:(NSImage *)image; // creates a new NSButton
-- (NSMenuItem *)menuItemForItem:(NSString *)identifier inGroup:(int)groupNumber
- withTitle:(NSString *)title image:(NSImage *)image; // creates a new NSMenuitem
-- (NSPopUpButton *)popupButtonForGroup:(NSDictionary *)group;
-- (void)setControl:(NSObject *)control forIdentifier:(NSString *)identifier inGroup:(int)groupNumber;
-- (void)updateMenuTitleForGroupAtIndex:(int)groupNumber;
-
-@end
-
-
-@implementation MGScopeBar
-
-
-#pragma mark Setup and teardown
-
-
-- (id)initWithFrame:(NSRect)frame
-{
- self = [super initWithFrame:frame];
- if (self) {
- _smartResizeEnabled = YES;
- // Everything else is reset in -reloadData.
- }
- return self;
-}
-
-
-- (void)dealloc
-{
- delegate = nil;
- if (_accessoryView) {
- [_accessoryView removeFromSuperview];
- _accessoryView = nil; // weak ref
- }
- [_separatorPositions release];
- [_groups release];
- [_identifiers release];
- [_selectedItems release];
-
- [super dealloc];
-}
-
-
-#pragma mark Data management
-
-
-- (void)reloadData
-{
- // Resize if necessary.
- [self sizeToFit];
-
- // Remove any old objects.
- if (_accessoryView) {
- [_accessoryView removeFromSuperview];
- _accessoryView = nil; // weak ref
- }
-
- NSArray *subviews = [[self subviews] copy]; // so we don't mutate the collection we're iterating over.
- [subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
- [subviews release]; // because copies are retained.
-
- [_separatorPositions release];
- _separatorPositions = nil;
- [_groups release];
- _groups = nil;
- [_identifiers release];
- _identifiers = nil;
- [_selectedItems release];
- _selectedItems = nil;
- _firstCollapsedGroup = NSNotFound;
- _lastWidth = NSNotFound;
- _totalGroupsWidth = 0;
- _totalGroupsWidthForPopups = 0;
-
- // Configure contents via delegate.
- if (self.delegate && [delegate conformsToProtocol:@protocol(MGScopeBarDelegate)]) {
- int numGroups = [delegate numberOfGroupsInScopeBar:self];
-
- if (numGroups > 0) {
- _separatorPositions = [[NSMutableArray alloc] initWithCapacity:numGroups];
- _groups = [[NSMutableArray alloc] initWithCapacity:numGroups];
- _identifiers = [[NSMutableDictionary alloc] initWithCapacity:0];
- _selectedItems = [[NSMutableArray alloc] initWithCapacity:numGroups];
-
- int xCoord = SCOPE_BAR_H_INSET;
- NSRect ctrlRect = NSZeroRect;
- BOOL providesImages = [delegate respondsToSelector:@selector(scopeBar:imageForItem:inGroup:)];
-
- int groupNum;
- for (groupNum = 0; groupNum < numGroups; groupNum++) {
- // Add separator if appropriate.
- BOOL addSeparator = (groupNum > 0); // default behavior.
- if ([delegate respondsToSelector:@selector(scopeBar:showSeparatorBeforeGroup:)]) {
- addSeparator = [delegate scopeBar:self showSeparatorBeforeGroup:groupNum];
- }
- if (addSeparator) {
- [_separatorPositions addObject:[NSNumber numberWithInt:xCoord]];
- xCoord += SCOPE_BAR_SEPARATOR_WIDTH + SCOPE_BAR_ITEM_SPACING;
-
- _totalGroupsWidth += SCOPE_BAR_SEPARATOR_WIDTH + SCOPE_BAR_ITEM_SPACING;
- _totalGroupsWidthForPopups += SCOPE_BAR_SEPARATOR_WIDTH + SCOPE_BAR_ITEM_SPACING;
- } else {
- [_separatorPositions addObject:[NSNull null]];
- }
-
- // Add label if appropriate.
- NSString *groupLabel = [delegate scopeBar:self labelForGroup:groupNum];
- NSTextField *labelField = nil;
- BOOL hasLabel = NO;
- if (groupLabel && [groupLabel length] > 0) {
- hasLabel = YES;
- ctrlRect = NSMakeRect(xCoord, 6, 15, 50);
- labelField = [[NSTextField alloc] initWithFrame:ctrlRect];
- [labelField setStringValue:groupLabel];
- [labelField setEditable:NO];
- [labelField setBordered:NO];
- [labelField setDrawsBackground:NO];
- [labelField setTextColor:SCOPE_BAR_LABEL_COLOR];
- [labelField setFont:[NSFont boldSystemFontOfSize:SCOPE_BAR_FONTSIZE]];
- [labelField sizeToFit];
- ctrlRect.size = [labelField frame].size;
- [labelField setFrame:ctrlRect];
- [self addSubview:labelField];
- [labelField release];
-
- xCoord += ctrlRect.size.width + SCOPE_BAR_ITEM_SPACING;
-
- _totalGroupsWidth += ctrlRect.size.width + SCOPE_BAR_ITEM_SPACING;
- _totalGroupsWidthForPopups += ctrlRect.size.width + SCOPE_BAR_ITEM_SPACING;
- }
-
- // Create group information for use during interaction.
- NSArray *identifiers = [delegate scopeBar:self itemIdentifiersForGroup:groupNum];
- NSMutableArray *usedIdentifiers = [NSMutableArray arrayWithCapacity:[identifiers count]];
- NSMutableArray *buttons = [NSMutableArray arrayWithCapacity:[identifiers count]];
- MGScopeBarGroupSelectionMode selMode = [delegate scopeBar:self selectionModeForGroup:groupNum];
- if (selMode != MGRadioSelectionMode && selMode != MGMultipleSelectionMode) {
- // Sanity check, since this is just an int.
- selMode = MGRadioSelectionMode;
- }
- NSMutableDictionary *groupInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
- usedIdentifiers, GROUP_IDENTIFIERS,
- buttons, GROUP_BUTTONS,
- [NSNumber numberWithInt:selMode], GROUP_SELECTION_MODE,
- [NSNumber numberWithBool:NO], GROUP_MENU_MODE,
- [NSNumber numberWithBool:hasLabel], GROUP_HAS_LABEL,
- [NSNumber numberWithBool:addSeparator], GROUP_HAS_SEPARATOR,
- nil];
- if (hasLabel) {
- [groupInfo setObject:labelField forKey:GROUP_LABEL_FIELD];
- }
- [_groups addObject:groupInfo];
- [_selectedItems addObject:[NSMutableArray arrayWithCapacity:0]];
-
- // Add buttons for this group.
- float widestButtonWidth = 0;
- float totalButtonsWidth = 0;
- for (NSString *itemID in identifiers) {
- if (![usedIdentifiers containsObject:itemID]) {
- [usedIdentifiers addObject:itemID];
- } else {
- // Identifier already used for this group; skip it.
- continue;
- }
-
- NSString *title = [delegate scopeBar:self titleOfItem:itemID inGroup:groupNum];
- NSImage *image = nil;
- if (providesImages) {
- image = [delegate scopeBar:self imageForItem:itemID inGroup:groupNum];
- }
- NSButton *button = [self buttonForItem:itemID inGroup:groupNum withTitle:title image:image];
-
- ctrlRect = [button frame];
- ctrlRect.origin.x = xCoord;
- [button setFrame:ctrlRect];
- [self addSubview:button];
- [buttons addObject:button];
-
- // Adjust x-coordinate for next item in the bar.
- xCoord += ctrlRect.size.width + SCOPE_BAR_ITEM_SPACING;
-
- // Update total and widest button widths.
- if (totalButtonsWidth > 0) {
- // Add spacing before this item, since it's not the first in the group.
- totalButtonsWidth += SCOPE_BAR_ITEM_SPACING;
- }
- totalButtonsWidth += ctrlRect.size.width;
- if (ctrlRect.size.width > widestButtonWidth) {
- widestButtonWidth = ctrlRect.size.width;
- }
- }
-
- // Add the accumulated buttons' width and the widest button's width to groupInfo.
- [groupInfo setObject:[NSNumber numberWithFloat:totalButtonsWidth] forKey:GROUP_TOTAL_BUTTONS_WIDTH];
- [groupInfo setObject:[NSNumber numberWithFloat:widestButtonWidth] forKey:GROUP_WIDEST_BUTTON_WIDTH];
-
- _totalGroupsWidth += totalButtonsWidth;
- _totalGroupsWidthForPopups += widestButtonWidth + MENU_PADDING;
-
- float cumulativeWidth = _totalGroupsWidth + (groupNum * SCOPE_BAR_ITEM_SPACING);
- [groupInfo setObject:[NSNumber numberWithFloat:cumulativeWidth] forKey:GROUP_CUMULATIVE_WIDTH];
-
- // If this is a radio-mode group, select the first item automatically.
- if (selMode == MGRadioSelectionMode) {
- [self updateSelectedState:YES forItem:[identifiers objectAtIndex:0] inGroup:groupNum informDelegate:YES];
- }
- }
-
- _totalGroupsWidth += ((numGroups - 1) * SCOPE_BAR_ITEM_SPACING);
- _totalGroupsWidthForPopups += ((numGroups - 1) * SCOPE_BAR_ITEM_SPACING);
- }
-
- // Add accessoryView, if provided.
- if ([delegate respondsToSelector:@selector(accessoryViewForScopeBar:)]) {
- _accessoryView = [delegate accessoryViewForScopeBar:self];
- if (_accessoryView) {
- // Remove NSViewMaxXMargin flag from resizing mask, if present.
- NSUInteger mask = [_accessoryView autoresizingMask];
- if (mask & NSViewMaxXMargin) {
- mask &= ~NSViewMaxXMargin;
- }
-
- // Add NSViewMinXMargin flag to resizing mask, if not present.
- if (!(mask & NSViewMinXMargin)) {
- mask = (mask | NSViewMinXMargin);
- }
-
- // Update view sizing mask.
- [_accessoryView setAutoresizingMask:mask];
-
- // Adjust frame appropriately.
- NSRect frame = [_accessoryView frame];
- frame.origin.x = round(NSMaxX([self bounds]) - (frame.size.width + SCOPE_BAR_H_INSET));
- frame.origin.y = round(((SCOPE_BAR_HEIGHT - frame.size.height) / 2.0));
- [_accessoryView setFrame:frame];
-
- // Add as subview.
- [self addSubview:_accessoryView];
- }
- }
-
- // Layout subviews appropriately.
- [self adjustSubviews];
- }
-
- [self setNeedsDisplay:YES];
-}
-
-
-#pragma mark Utility methods
-
-
-- (void)sizeToFit
-{
- NSRect frame = [self frame];
- if (frame.size.height != SCOPE_BAR_HEIGHT) {
- float delta = SCOPE_BAR_HEIGHT - frame.size.height;
- frame.size.height += delta;
- frame.origin.y -= delta;
- [self setFrame:frame];
- }
-}
-
-
-- (void)adjustSubviews
-{
- if (!_smartResizeEnabled) {
- return;
- }
-
- /*
- We need to work out which groups we can show fully expanded, and which must be collapsed into popup-buttons.
- Any kind of frame-change may have happened, so we need to take care to create or remove buttons or popup-buttons as needed.
- */
-
- // Bail out if we have nothing to do.
- if (!_groups || [_groups count] == 0) {
- return;
- }
-
- // Obtain current width of view.
- float viewWidth = [self bounds].size.width;
-
- // Abort if there hasn't been any genuine change in width.
- if ((viewWidth == _lastWidth) && (_lastWidth != NSNotFound)) {
- return;
- }
-
- // Determine whether we got narrower or wider.
- float narrower = ((_lastWidth == NSNotFound) || (viewWidth < _lastWidth));
-
- // Find width available for showing groups.
- float availableWidth = viewWidth - (SCOPE_BAR_H_INSET * 2.0);
- if (_accessoryView) {
- // Account for _accessoryView, leaving a normal amount of spacing to the left of it.
- availableWidth -= ([_accessoryView frame].size.width + SCOPE_BAR_ITEM_SPACING);
- }
-
- BOOL shouldAdjustPopups = (availableWidth < _totalGroupsWidthForPopups);
- NSInteger oldFirstCollapsedGroup = _firstCollapsedGroup;
-
- // Work out which groups we should now check for collapsibility/expandability.
- NSEnumerator *groupsEnumerator = nil;
- NSRange enumRange;
- BOOL proceed = YES;
-
- if (narrower) {
- // Got narrower, so work backwards from oldFirstCollapsedGroup (excluding that group, since it's already collapsed),
- // checking to see if we need to collapse any more groups to the left.
- enumRange = NSMakeRange(0, oldFirstCollapsedGroup);
- // If no groups were previously collapsed, work backwards from the last group (including that group).
- if (oldFirstCollapsedGroup == NSNotFound) {
- enumRange.length = [_groups count];
- }
- groupsEnumerator = [[_groups subarrayWithRange:enumRange] reverseObjectEnumerator];
-
- } else {
- // Got wider, so work forwards from oldFirstCollapsedGroup (including that group) checking to see if we can
- // expand any groups into full buttons.
- enumRange = NSMakeRange(oldFirstCollapsedGroup, [_groups count] - oldFirstCollapsedGroup);
- // If no groups were previously collapsed, we have nothing to do here.
- if (oldFirstCollapsedGroup == NSNotFound) {
- proceed = NO;
- }
- if (proceed) {
- groupsEnumerator = [[_groups subarrayWithRange:enumRange] objectEnumerator];
- }
- }
-
- // Get the current occupied width within this view.
- float currentOccupiedWidth = 0;
- NSDictionary *group = [_groups objectAtIndex:0];
- BOOL menuMode = [[group objectForKey:GROUP_MENU_MODE] boolValue];
- NSButton *firstButton = nil;
- if (menuMode) {
- firstButton = [group objectForKey:GROUP_POPUP_BUTTON];
- } else {
- firstButton = [[group objectForKey:GROUP_BUTTONS] objectAtIndex:0];
- }
- float leftLimit = NSMinX([firstButton frame]);
- // Account for label in first group, if present.
- if ([[group objectForKey:GROUP_HAS_LABEL] boolValue]) {
- NSTextField *label = (NSTextField *)[group objectForKey:GROUP_LABEL_FIELD];
- leftLimit -= (SCOPE_BAR_ITEM_SPACING + [label frame].size.width);
- }
-
- group = [_groups lastObject];
- menuMode = [[group objectForKey:GROUP_MENU_MODE] boolValue];
- NSButton *lastButton = nil;
- if (menuMode) {
- lastButton = [group objectForKey:GROUP_POPUP_BUTTON];
- } else {
- lastButton = [[group objectForKey:GROUP_BUTTONS] lastObject];
- }
- float rightLimit = NSMaxX([lastButton frame]);
- currentOccupiedWidth = rightLimit - leftLimit;
-
- // Work out whether we need to try collapsing groups at all, if we're narrowing.
- // We have already handled the case of not requiring to expand groups if we're widening, above.
- if (proceed && narrower) {
- if (availableWidth >= currentOccupiedWidth) {
- // We still have enough room for what we're showing; no change needed.
- proceed = NO;
- }
- }
-
- if (proceed) {
- // Disable screen updates.
- NSDisableScreenUpdates();
-
- // See how many further groups we can expand or contract.
- float theoreticalOccupiedWidth = currentOccupiedWidth;
- for (NSDictionary *groupInfo in groupsEnumerator) {
- BOOL complete = NO;
- float expandedWidth = [[groupInfo objectForKey:GROUP_TOTAL_BUTTONS_WIDTH] floatValue];
- float contractedWidth = [[groupInfo objectForKey:GROUP_WIDEST_BUTTON_WIDTH] floatValue] + MENU_PADDING;
-
- if (narrower) {
- // We're narrowing. See if collapsing this group brings us within availableWidth.
- if (((theoreticalOccupiedWidth - expandedWidth) + contractedWidth) <= availableWidth) {
- // We're now within width constraints, so we're done iterating.
- complete = YES;
- } // else, continue trying to to collapse groups.
- theoreticalOccupiedWidth = ((theoreticalOccupiedWidth - expandedWidth) + contractedWidth);
-
- } else {
- // We're widening. See if we can expand this group and still be within availableWidth.
- if (((theoreticalOccupiedWidth - contractedWidth) + expandedWidth) > availableWidth) {
- // We'd be too wide if we expanded this group. Terminate iteration without updating _firstCollapsedGroup.
- //NSLog(@"We'd be too wide if we expanded right now");
- break;
- } // else, continue trying to expand groups.
- theoreticalOccupiedWidth = ((theoreticalOccupiedWidth - contractedWidth) + expandedWidth);
- //NSLog(@"We can continue expanding");
- }
-
- // Update _firstCollapsedGroup appropriately.
- if (_firstCollapsedGroup == NSNotFound) {
- _firstCollapsedGroup = ((narrower) ? [_groups count] : -1);
- oldFirstCollapsedGroup = _firstCollapsedGroup;
- }
- _firstCollapsedGroup += ((narrower) ? -1 : 1);
-
- // Terminate if we now fit the available space as best we can.
- if (complete) {
- break;
- }
- }
-
- // Work out how many groups we need to actually change.
- NSRange changedRange = NSMakeRange(0, [_groups count]);
- BOOL adjusting = YES;
- //NSLog(@"Old firstCollapsedGroup: %d, new: %d", oldFirstCollapsedGroup, _firstCollapsedGroup);
- if (_firstCollapsedGroup != oldFirstCollapsedGroup) {
- if (narrower) {
- // Narrower. _firstCollapsedGroup will be less (earlier) than oldFirstCollapsedGroup.
- changedRange.location = _firstCollapsedGroup;
- changedRange.length = (oldFirstCollapsedGroup - _firstCollapsedGroup);
- } else {
- // Wider. _firstCollapsedGroup will be greater (later) than oldFirstCollapsedGroup.
- changedRange.location = oldFirstCollapsedGroup;
- changedRange.length = (_firstCollapsedGroup - oldFirstCollapsedGroup);
- }
- } else {
- // _firstCollapsedGroup and oldFirstCollapsedGroup are the same; nothing needs changed.
- adjusting = NO;
- }
-
- // If a change is required, ensure that each group is expanded or contracted as appropriate.
- if (adjusting || shouldAdjustPopups) {
- //NSLog(@"Got %@ - modifying groups %@", ((narrower) ? @"narrower" : @"wider"), NSStringFromRange(changedRange));
- NSInteger nextXCoord = NSNotFound;
- if (adjusting) {
- int i;
- for (i = changedRange.location; i < NSMaxRange(changedRange); i++) {
- NSMutableDictionary *groupInfo = [_groups objectAtIndex:i];
-
- if (nextXCoord == NSNotFound) {
- BOOL menuMode = [[groupInfo objectForKey:GROUP_MENU_MODE] boolValue];
- NSButton *firstButton = nil;
- if (!menuMode) {
- firstButton = [[groupInfo objectForKey:GROUP_BUTTONS] objectAtIndex:0];
- } else {
- firstButton = [groupInfo objectForKey:GROUP_POPUP_BUTTON];
- }
- nextXCoord = [firstButton frame].origin.x;
- } else {
- // Add group-spacing, separator and label as appropriate.
- nextXCoord += SCOPE_BAR_ITEM_SPACING;
- if ([[groupInfo objectForKey:GROUP_HAS_SEPARATOR] boolValue]) {
- nextXCoord += (SCOPE_BAR_SEPARATOR_WIDTH + SCOPE_BAR_ITEM_SPACING);
- }
- if ([[groupInfo objectForKey:GROUP_HAS_LABEL] boolValue]) {
- NSTextField *labelField = (NSTextField *)[groupInfo objectForKey:GROUP_LABEL_FIELD];
- float labelWidth = [labelField frame].size.width;
- nextXCoord += (labelWidth + SCOPE_BAR_ITEM_SPACING);
- }
- }
-
- NSPopUpButton *popup = nil;
- if (narrower) {
- // Remove buttons.
- NSArray *buttons = [groupInfo objectForKey:GROUP_BUTTONS];
- [buttons makeObjectsPerformSelector:@selector(removeFromSuperview)];
-
- // Create popup and add it to this view.
- popup = [self popupButtonForGroup:groupInfo];
- NSRect popupFrame = [popup frame];
- popupFrame.origin.x = nextXCoord;
- [popup setFrame:popupFrame];
- [groupInfo setObject:popup forKey:GROUP_POPUP_BUTTON];
- [self addSubview:popup positioned:NSWindowBelow relativeTo:_accessoryView];
- nextXCoord += popupFrame.size.width;
-
- // Ensure popup has appropriate title.
- [self updateMenuTitleForGroupAtIndex:i];
-
- } else {
- // Remove and release popup.
- popup = [groupInfo objectForKey:GROUP_POPUP_BUTTON];
- [popup removeFromSuperview];
- [groupInfo removeObjectForKey:GROUP_POPUP_BUTTON];
-
- // Replace menuItems with buttons.
- float buttonX = nextXCoord;
- NSMutableArray *menuItems = [groupInfo objectForKey:GROUP_BUTTONS];
- NSArray *selectedItems = [_selectedItems objectAtIndex:i];
- int i;
- for (i = 0; i < [menuItems count]; i++) {
- NSMenuItem *menuItem = [menuItems objectAtIndex:i];
- NSString *itemIdentifier = [menuItem representedObject];
- NSButton *button = [self buttonForItem:itemIdentifier
- inGroup:[menuItem tag]
- withTitle:[menuItem title]
- image:[menuItem image]];
- NSRect buttonFrame = [button frame];
- buttonFrame.origin.x = buttonX;
- [button setFrame:buttonFrame];
- if ([selectedItems containsObject:itemIdentifier]) {
- [button setState:NSOnState];
- }
- [self addSubview:button positioned:NSWindowBelow relativeTo:_accessoryView];
- [menuItems replaceObjectAtIndex:i withObject:button];
- buttonX += [button frame].size.width + SCOPE_BAR_ITEM_SPACING;
- }
- nextXCoord = (buttonX - SCOPE_BAR_ITEM_SPACING);
- }
-
- // Update GROUP_MENU_MODE for this group.
- [groupInfo setObject:[NSNumber numberWithBool:narrower] forKey:GROUP_MENU_MODE];
- }
- }
-
- // Modify positions/sizes of groups and separators as required.
- float startIndex = MIN(changedRange.location, _firstCollapsedGroup);
- float xCoord = 0;
- float perGroupDelta = 0;
- if (shouldAdjustPopups) {
- perGroupDelta = ((_totalGroupsWidthForPopups - availableWidth) / [_groups count]);
- }
- int i;
- for (i = startIndex; i < [_groups count]; i++) {
- NSDictionary *groupInfo = [_groups objectAtIndex:i];
- BOOL menuMode = [[groupInfo objectForKey:GROUP_MENU_MODE] boolValue];
-
- // Further contract or expand popups if appropriate.
- if (shouldAdjustPopups) {
- float fullPopupWidth = [[groupInfo objectForKey:GROUP_WIDEST_BUTTON_WIDTH] floatValue] + MENU_PADDING;
- float popupWidth = fullPopupWidth - perGroupDelta;
- popupWidth = MAX(popupWidth, MENU_MIN_WIDTH);
- popupWidth = MIN(popupWidth, fullPopupWidth);
-
- NSPopUpButton *button = [groupInfo objectForKey:GROUP_POPUP_BUTTON];
- NSRect buttonRect = [button frame];
- buttonRect.size.width = popupWidth;
- [button setFrame:buttonRect];
- }
-
- // Reposition groups appropriately.
- if (i > startIndex) {
- // Reposition separator if present.
- if ([[groupInfo objectForKey:GROUP_HAS_SEPARATOR] boolValue]) {
- [_separatorPositions replaceObjectAtIndex:i withObject:[NSNumber numberWithInt:xCoord]];
- xCoord += (SCOPE_BAR_SEPARATOR_WIDTH + SCOPE_BAR_ITEM_SPACING);
- }
-
- // Reposition label if present.
- if ([[groupInfo objectForKey:GROUP_HAS_LABEL] boolValue]) {
- NSTextField *label = [groupInfo objectForKey:GROUP_LABEL_FIELD];
- NSRect labelFrame = [label frame];
- labelFrame.origin.x = xCoord;
- [label setFrame:labelFrame];
- xCoord = NSMaxX(labelFrame) + SCOPE_BAR_ITEM_SPACING;
- }
-
- // Reposition buttons or popup.
- if (menuMode) {
- NSPopUpButton *button = [groupInfo objectForKey:GROUP_POPUP_BUTTON];
- NSRect buttonRect = [button frame];
- buttonRect.origin.x = xCoord;
- [button setFrame:buttonRect];
- xCoord = NSMaxX(buttonRect) + SCOPE_BAR_ITEM_SPACING;
-
- } else {
- NSArray *buttons = [groupInfo objectForKey:GROUP_BUTTONS];
- for (NSButton *button in buttons) {
- NSRect buttonRect = [button frame];
- buttonRect.origin.x = xCoord;
- [button setFrame:buttonRect];
- xCoord = NSMaxX(buttonRect) + SCOPE_BAR_ITEM_SPACING;
- }
- }
-
- } else {
- // Set up initial value of xCoord.
- NSButton *button = nil;
- if (menuMode) {
- button = [groupInfo objectForKey:GROUP_POPUP_BUTTON];
- } else {
- button = [[groupInfo objectForKey:GROUP_BUTTONS] lastObject];
- }
- xCoord = NSMaxX([button frame]) + SCOPE_BAR_ITEM_SPACING;
- }
- }
-
- // Reset _firstCollapsedGroup to NSNotFound if necessary.
- if (!narrower) {
- if (_firstCollapsedGroup >= [_groups count]) {
- _firstCollapsedGroup = NSNotFound;
- }
- }
- }
-
- // Re-enable screen updates.
- NSEnableScreenUpdates();
- }
-
- // Take note of our width for comparison next time.
- _lastWidth = viewWidth;
-}
-
-
-- (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize
-{
- [super resizeSubviewsWithOldSize:oldBoundsSize];
- [self adjustSubviews];
-}
-
-
-- (NSButton *)getButtonForItem:(NSString *)identifier inGroup:(int)groupNumber
-{
- NSButton *button = nil;
- NSArray *group = [_identifiers objectForKey:identifier];
- if (group && [group count] > groupNumber) {
- NSObject *element = [group objectAtIndex:groupNumber];
- if (element != [NSNull null]) {
- button = (NSButton *)element;
- }
- }
-
- return button;
-}
-
-
-- (NSButton *)buttonForItem:(NSString *)identifier inGroup:(int)groupNumber
- withTitle:(NSString *)title image:(NSImage *)image
-{
- NSRect ctrlRect = NSMakeRect(0, 0, 50, 20); // arbitrary size; will be resized later.
- NSButton *button = [[NSButton alloc] initWithFrame:ctrlRect];
- [button setTitle:title];
- [[button cell] setRepresentedObject:identifier];
- [button setTag:groupNumber];
- [button setFont:[NSFont boldSystemFontOfSize:SCOPE_BAR_FONTSIZE]];
- [button setTarget:self];
- [button setAction:@selector(scopeButtonClicked:)];
- [button setBezelStyle:NSRecessedBezelStyle];
- [button setButtonType:NSPushOnPushOffButton];
- [[button cell] setHighlightsBy:NSCellIsBordered | NSCellIsInsetButton];
- [button setShowsBorderOnlyWhileMouseInside:YES];
- if (image) {
- [image setSize:NSMakeSize(SCOPE_BAR_BUTTON_IMAGE_SIZE, SCOPE_BAR_BUTTON_IMAGE_SIZE)];
- [button setImagePosition:NSImageLeft];
- [button setImage:image];
- }
- [button sizeToFit];
- ctrlRect = [button frame];
- ctrlRect.origin.y = floor(([self frame].size.height - ctrlRect.size.height) / 2.0);
- [button setFrame:ctrlRect];
-
- [self setControl:button forIdentifier:identifier inGroup:groupNumber];
-
- return [button autorelease];
-}
-
-
-- (NSMenuItem *)menuItemForItem:(NSString *)identifier inGroup:(int)groupNumber
- withTitle:(NSString *)title image:(NSImage *)image
-{
- NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:title action:@selector(scopeButtonClicked:) keyEquivalent:@""];
- [menuItem setTarget:self];
- [menuItem setImage:image];
- [menuItem setRepresentedObject:identifier];
- [menuItem setTag:groupNumber];
-
- [self setControl:menuItem forIdentifier:identifier inGroup:groupNumber];
-
- return [menuItem autorelease];
-}
-
-
-- (NSPopUpButton *)popupButtonForGroup:(NSDictionary *)group
-{
- float popWidth = floor([[group objectForKey:GROUP_WIDEST_BUTTON_WIDTH] floatValue] + MENU_PADDING);
- NSRect popFrame = NSMakeRect(0, 0, popWidth, 20); // arbitrary height.
- NSPopUpButton *popup = [[NSPopUpButton alloc] initWithFrame:popFrame pullsDown:NO];
-
- // Since we're not using the selected item's title, we need to specify a NSMenuItem for the title.
- BOOL multiSelect = ([[group objectForKey:GROUP_SELECTION_MODE] intValue] == MGMultipleSelectionMode);
- if (multiSelect) {
- MGRecessedPopUpButtonCell *cell = [[MGRecessedPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO];
- [popup setCell:cell];
- [cell release];
-
- [[popup cell] setUsesItemFromMenu:NO];
- NSMenuItem *titleItem = [[NSMenuItem alloc] init];
- [[popup cell] setMenuItem:titleItem];
- [titleItem release];
- }
-
- // Configure appearance and behaviour.
- [popup setFont:[NSFont boldSystemFontOfSize:SCOPE_BAR_FONTSIZE]];
- [popup setBezelStyle:NSRecessedBezelStyle];
- [popup setButtonType:NSPushOnPushOffButton];
- [[popup cell] setHighlightsBy:NSCellIsBordered | NSCellIsInsetButton];
- [popup setShowsBorderOnlyWhileMouseInside:NO];
- [[popup cell] setAltersStateOfSelectedItem:NO];
- [[popup cell] setArrowPosition:NSPopUpArrowAtBottom];
- [popup setPreferredEdge:NSMaxXEdge];
-
- // Add appropriate items.
- [popup removeAllItems];
- NSMutableArray *buttons = [group objectForKey:GROUP_BUTTONS];
- int i;
- for (i = 0; i < [buttons count]; i++) {
- NSButton *button = (NSButton *)[buttons objectAtIndex:i];
- NSMenuItem *menuItem = [self menuItemForItem:[[button cell] representedObject]
- inGroup:[button tag]
- withTitle:[button title]
- image:[button image]];
- [menuItem setState:[button state]];
- [buttons replaceObjectAtIndex:i withObject:menuItem];
- [[popup menu] addItem:menuItem];
- }
-
- // Vertically center the popup within our frame.
- if (!multiSelect) {
- [popup sizeToFit];
- }
- popFrame = [popup frame];
- popFrame.origin.y = ceil(([self frame].size.height - popFrame.size.height) / 2.0);
- [popup setFrame:popFrame];
-
- return [popup autorelease];
-}
-
-
-- (void)setControl:(NSObject *)control forIdentifier:(NSString *)identifier inGroup:(int)groupNumber
-{
- if (!_identifiers) {
- _identifiers = [[NSMutableDictionary alloc] initWithCapacity:0];
- }
-
- NSMutableArray *identArray = [_identifiers objectForKey:identifier];
- if (!identArray) {
- identArray = [[[NSMutableArray alloc] initWithCapacity:groupNumber + 1] autorelease];
- [_identifiers setObject:identArray forKey:identifier];
- }
-
- int count = [identArray count];
- if (groupNumber >= count) {
- // Pad identArray with nulls if appropriate, so this control lies at index groupNumber.
- int i;
- for (i = count; i < groupNumber; i++) {
- [identArray addObject:[NSNull null]];
- }
- [identArray addObject:control];
- } else {
- [identArray replaceObjectAtIndex:groupNumber withObject:control];
- }
-}
-
-
-- (void)updateMenuTitleForGroupAtIndex:(int)groupNumber
-{
- // Ensure that this group's popup (if present) has the correct title,
- // accounting for the group's selection-mode and selected item(s).
-
- if (groupNumber < 0 || groupNumber >= [_groups count]) {
- return;
- }
-
- NSDictionary *group = [_groups objectAtIndex:groupNumber];
- if (group) {
- NSPopUpButton *popup = [group objectForKey:GROUP_POPUP_BUTTON];
- if (popup) {
- NSArray *groupSelection = [_selectedItems objectAtIndex:groupNumber];
- int numSelected = [groupSelection count];
- if (numSelected == 0) {
- // No items selected.
- [popup setTitle:POPUP_TITLE_EMPTY_SELECTION];
- [[[popup cell] menuItem] setImage:nil];
-
- } else if (numSelected > 1) {
- // Multiple items selected.
- [popup setTitle:POPUP_TITLE_MULTIPLE_SELECTION];
- [[[popup cell] menuItem] setImage:nil];
-
- } else {
- // One item selected.
- NSString *identifier = [groupSelection objectAtIndex:0];
- NSArray *items = [group objectForKey:GROUP_BUTTONS];
- NSMenuItem *item = nil;
- for (NSMenuItem *thisItem in items) {
- if ([[thisItem representedObject] isEqualToString:identifier]) {
- item = thisItem;
- break;
- }
- }
- if (item) {
- [popup setTitle:[item title]];
- [[[popup cell] menuItem] setImage:[item image]];
- }
- }
-
- if (SCOPE_BAR_HIDE_POPUP_BG) {
- BOOL hasBackground = [[popup cell] isBordered];
- if (numSelected == 0 && hasBackground) {
- [[popup cell] setBordered:NO];
- } else if (!hasBackground) {
- [[popup cell] setBordered:YES];
- }
- }
- }
- }
-}
-
-
-#pragma mark Drawing
-
-
-- (void)drawRect:(NSRect)rect
-{
- // Draw gradient background.
- NSGradient *gradient = [[[NSGradient alloc] initWithStartingColor:SCOPE_BAR_START_COLOR_GRAY
- endingColor:SCOPE_BAR_END_COLOR_GRAY] autorelease];
- [gradient drawInRect:[self bounds] angle:90.0];
-
- // Draw border.
- NSRect lineRect = [self bounds];
- lineRect.size.height = SCOPE_BAR_BORDER_WIDTH;
- [SCOPE_BAR_BORDER_COLOR set];
- NSRectFill(lineRect);
-
- // Draw separators.
- if ([_separatorPositions count] > 0) {
- [SCOPE_BAR_SEPARATOR_COLOR set];
- NSRect sepRect = NSMakeRect(0, 0, SCOPE_BAR_SEPARATOR_WIDTH, SCOPE_BAR_SEPARATOR_HEIGHT);
- sepRect.origin.y = (([self bounds].size.height - sepRect.size.height) / 2.0);
- for (NSObject *sepPosn in _separatorPositions) {
- if (sepPosn != [NSNull null]) {
- sepRect.origin.x = [(NSNumber *)sepPosn intValue];
- NSRectFill(sepRect);
- }
- }
- }
-}
-
-
-#pragma mark Interaction
-
-
-- (IBAction)scopeButtonClicked:(id)sender
-{
- NSButton *button = (NSButton *)sender;
- BOOL menuMode = [sender isKindOfClass:[NSMenuItem class]];
- NSString *identifier = [((menuMode) ? sender : [sender cell]) representedObject];
- int groupNumber = [sender tag];
- BOOL nowSelected = YES;
- if (menuMode) {
- // MenuItem. Ensure item has appropriate state.
- nowSelected = ![[_selectedItems objectAtIndex:groupNumber] containsObject:identifier];
- [sender setState:((nowSelected) ? NSOnState : NSOffState)];
- } else {
- // Button. Item will already have appropriate state.
- nowSelected = ([button state] != NSOffState);
- }
- [self setSelected:nowSelected forItem:identifier inGroup:groupNumber];
-}
-
-
-#pragma mark Accessors and properties
-
-
-- (void)setSelected:(BOOL)selected forItem:(NSString *)identifier inGroup:(int)groupNumber
-{
- // Change state of other items in group appropriately, informing delegate if possible.
- // First we find the appropriate group-info for the item's identifier.
- if (identifier && groupNumber >= 0 && groupNumber < [_groups count]) {
- NSDictionary *group = [_groups objectAtIndex:groupNumber];
- BOOL nowSelected = selected;
- BOOL informDelegate = YES;
-
- if (group) {
- [group retain];
- NSDisableScreenUpdates();
-
- // We found the group which this item belongs to. Obtain selection-mode and identifiers.
- MGScopeBarGroupSelectionMode selMode = [[group objectForKey:GROUP_SELECTION_MODE] intValue];
- BOOL radioMode = (selMode == MGRadioSelectionMode);
-
- if (radioMode) {
- // This is a radio-mode group. Ensure this item isn't already selected.
- NSArray *groupSelections = [[_selectedItems objectAtIndex:groupNumber] copy];
-
- if (nowSelected) {
- // Before selecting this item, we first need to deselect any other selected items in this group.
- for (NSString *selectedIdentifier in groupSelections) {
- // Reselect the just-deselected item without informing the delegate, since nothing really changed.
- [self updateSelectedState:NO forItem:selectedIdentifier inGroup:groupNumber informDelegate:NO];
- }
- } else {
- // Prevent deselection if this item is already selected.
- if ([groupSelections containsObject:identifier]) {
- nowSelected = YES;
- informDelegate = NO;
- }
- }
- [groupSelections release];
- }
-
- // Change selected state of this item.
- [self updateSelectedState:nowSelected forItem:identifier inGroup:groupNumber informDelegate:informDelegate];
-
- // Update popup-menu's title if appropriate.
- if ([[group objectForKey:GROUP_MENU_MODE] boolValue]) {
- [self updateMenuTitleForGroupAtIndex:groupNumber];
- }
-
- [group release];
- NSEnableScreenUpdates();
- }
- }
-}
-
-
-- (void)updateSelectedState:(BOOL)selected forItem:(NSString *)identifier inGroup:(int)groupNumber informDelegate:(BOOL)inform
-{
- // This method simply updates the selected state of the item's control, maintains selectedItems, and informs the delegate.
- // All management of dependencies (such as deselecting other selected items in a radio-selection-mode group) is performed
- // in the setSelected:forItem:inGroup: method.
-
- // Determine whether we can inform the delegate about this change.
- SEL stateChangedSel = @selector(scopeBar:selectedStateChanged:forItem:inGroup:);
- BOOL responds = (delegate && [delegate respondsToSelector:stateChangedSel]);
-
- // Ensure selected status of item's control reflects desired value.
- NSButton *button = [self getButtonForItem:identifier inGroup:groupNumber];
- if (selected && [button state] == NSOffState) {
- [button setState:NSOnState];
- } else if (!selected && [button state] != NSOffState) {
- [button setState:NSOffState];
- }
-
- // Maintain _selectedItems appropriately.
- if (_selectedItems && [_selectedItems count] > groupNumber) {
- NSMutableArray *groupSelections = [_selectedItems objectAtIndex:groupNumber];
- BOOL alreadySelected = [groupSelections containsObject:identifier];
- if (selected && !alreadySelected) {
- [groupSelections addObject:identifier];
- } else if (!selected && alreadySelected) {
- [groupSelections removeObject:identifier];
- }
- }
-
- // Inform delegate about this change if possible.
- if (inform && responds) {
- [delegate scopeBar:self selectedStateChanged:selected forItem:identifier inGroup:groupNumber];
- }
-}
-
-
-- (NSArray *)selectedItems
-{
- return [[_selectedItems copy] autorelease];
-}
-
-
-- (void)setDelegate:(id)newDelegate
-{
- if (delegate != newDelegate) {
- delegate = newDelegate;
- [self reloadData];
- }
-}
-
-
-- (BOOL)smartResizeEnabled
-{
- return _smartResizeEnabled;
-}
-
-
-- (void)setSmartResizeEnabled:(BOOL)enabled
-{
- if (enabled != _smartResizeEnabled) {
- _smartResizeEnabled = enabled;
- [self reloadData];
- }
-}
-
-
-@synthesize delegate;
-
-
-@end
View
46 MGScopeBar/MGScopeBarDelegateProtocol.h
@@ -1,46 +0,0 @@
-//
-// MGScopeBarDelegateProtocol.h
-// MGScopeBar
-//
-// Created by Matt Gemmell on 15/03/2008.
-// Copyright 2008 Instinctive Code.
-//
-
-#import <Cocoa/Cocoa.h>
-
-
-// Selection modes for the buttons within a group.
-typedef enum _MGScopeBarGroupSelectionMode {
- MGRadioSelectionMode = 0, // Exactly one item in the group will be selected at a time (no more, and no less).
- MGMultipleSelectionMode = 1 // Any number of items in the group (including none) may be selected at a time.
-} MGScopeBarGroupSelectionMode;
-
-
-@class MGScopeBar;
-@protocol MGScopeBarDelegate
-
-