├── .gitmodules ├── Butter ├── en.lproj │ └── InfoPlist.strings ├── Butter-Prefix.pch ├── Private │ ├── BTRControlAction.m │ └── BTRControlAction.h ├── BTRLabel.h ├── NSImage+BTRImageAdditions.h ├── NSImage+BTRImageAdditions.m ├── BTRImage.h ├── BTRImage.m ├── Butter.h ├── BTRSecureTextField.h ├── BTRLabel.m ├── BTRButton.h ├── BTRTextField.h ├── Butter-Info.plist ├── BTRGeometryAdditions.h ├── BTRTextFieldProtocol.h ├── BTRScrollView.h ├── NSView+BTRAdditions.h ├── BTRPopUpButton.h ├── BTRImageView.h ├── BTRScrollView.m ├── BTRView.h ├── BTRClipView.h ├── NSView+BTRAdditions.m ├── BTRActivityIndicator.h ├── BTRView.m ├── BTRButton.m ├── BTRControl.h ├── BTRImageView.m ├── BTRActivityIndicator.m ├── BTRClipView.m └── BTRPopUpButton.m ├── Examples ├── BTRButton │ └── ButtonDemo │ │ ├── ButtonDemo │ │ ├── en.lproj │ │ │ ├── InfoPlist.strings │ │ │ └── Credits.rtf │ │ ├── ButtonDemo-Prefix.pch │ │ ├── main.m │ │ ├── AppDelegate.h │ │ ├── ButtonDemo-Info.plist │ │ └── AppDelegate.m │ │ └── ButtonDemo.xcodeproj │ │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ │ └── project.pbxproj ├── BTRControl │ └── ControlEvents │ │ ├── ControlEvents │ │ ├── en.lproj │ │ │ ├── InfoPlist.strings │ │ │ └── Credits.rtf │ │ ├── ControlEvents-Prefix.pch │ │ ├── main.m │ │ ├── AppDelegate.h │ │ ├── ControlEvents-Info.plist │ │ └── AppDelegate.m │ │ └── ControlEvents.xcodeproj │ │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── ControlEvents.xccheckout │ │ └── project.pbxproj ├── BTRImageView │ └── ImageView Test │ │ ├── ImageView Test │ │ ├── en.lproj │ │ │ ├── InfoPlist.strings │ │ │ └── Credits.rtf │ │ ├── ImageView Test-Prefix.pch │ │ ├── main.m │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ └── ImageView Test-Info.plist │ │ └── ImageView Test.xcodeproj │ │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ │ └── project.pbxproj ├── BTRTextField │ └── TextFieldDemo │ │ ├── TextFieldDemo │ │ ├── en.lproj │ │ │ ├── InfoPlist.strings │ │ │ └── Credits.rtf │ │ ├── TextFieldDemo-Prefix.pch │ │ ├── main.m │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ └── TextFieldDemo-Info.plist │ │ └── TextFieldDemo.xcodeproj │ │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── TextFieldDemo.xccheckout │ │ └── project.pbxproj ├── BTRPopUpButton │ └── Popup Button Demo │ │ ├── Popup Button Demo │ │ ├── en.lproj │ │ │ ├── InfoPlist.strings │ │ │ └── Credits.rtf │ │ ├── Popup Button Demo-Prefix.pch │ │ ├── main.m │ │ ├── AppDelegate.m │ │ ├── AppDelegate.h │ │ └── Popup Button Demo-Info.plist │ │ └── Popup Button Demo.xcodeproj │ │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── Popup Button Demo.xccheckout │ │ └── project.pbxproj ├── BTRActivityIndicator │ └── ActivityIndicator Demo │ │ ├── ActivityIndicator Demo │ │ ├── en.lproj │ │ │ ├── InfoPlist.strings │ │ │ └── Credits.rtf │ │ ├── ActivityIndicator Demo-Prefix.pch │ │ ├── main.m │ │ ├── AppDelegate.h │ │ ├── ActivityIndicator Demo-Info.plist │ │ └── AppDelegate.m │ │ └── ActivityIndicator Demo.xcodeproj │ │ └── project.xcworkspace │ │ └── contents.xcworkspacedata └── ButterExamples.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ └── ButterExamples.xccheckout ├── Butter.xcodeproj └── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ └── Butter.xccheckout ├── .gitignore ├── Butter.podspec ├── LICENSE.md └── README.md /.gitmodules: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Butter/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Examples/BTRButton/ButtonDemo/ButtonDemo/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Examples/BTRControl/ControlEvents/ControlEvents/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Examples/BTRImageView/ImageView Test/ImageView Test/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Examples/BTRTextField/TextFieldDemo/TextFieldDemo/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Examples/BTRPopUpButton/Popup Button Demo/Popup Button Demo/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Examples/BTRActivityIndicator/ActivityIndicator Demo/ActivityIndicator Demo/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Butter/Butter-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'Butter' target in the 'Butter' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /Examples/BTRButton/ButtonDemo/ButtonDemo/ButtonDemo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'ButtonDemo' target in the 'ButtonDemo' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /Butter.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Examples/BTRControl/ControlEvents/ControlEvents/ControlEvents-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'ControlEvents' target in the 'ControlEvents' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /Examples/BTRTextField/TextFieldDemo/TextFieldDemo/TextFieldDemo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'TextFieldDemo' target in the 'TextFieldDemo' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /Examples/BTRImageView/ImageView Test/ImageView Test/ImageView Test-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'ImageView Test' target in the 'ImageView Test' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /Examples/BTRButton/ButtonDemo/ButtonDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Examples/BTRPopUpButton/Popup Button Demo/Popup Button Demo/Popup Button Demo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'Popup Button Demo' target in the 'Popup Button Demo' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /Examples/BTRControl/ControlEvents/ControlEvents.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Examples/BTRImageView/ImageView Test/ImageView Test.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Examples/BTRTextField/TextFieldDemo/TextFieldDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Examples/BTRPopUpButton/Popup Button Demo/Popup Button Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Butter/Private/BTRControlAction.m: -------------------------------------------------------------------------------- 1 | // 2 | // BTRControlAction.m 3 | // Butter 4 | // 5 | // Created by Jonathan Willing on 7/19/13. 6 | // Copyright (c) 2013 ButterKit. All rights reserved. 7 | // 8 | 9 | #import "BTRControlAction.h" 10 | 11 | @implementation BTRControlAction 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Examples/BTRActivityIndicator/ActivityIndicator Demo/ActivityIndicator Demo/ActivityIndicator Demo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'ActivityIndicator Demo' target in the 'ActivityIndicator Demo' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | !default.xcworkspace 13 | xcuserdata 14 | profile 15 | *.moved-aside 16 | DerivedData 17 | .idea/ 18 | -------------------------------------------------------------------------------- /Examples/BTRActivityIndicator/ActivityIndicator Demo/ActivityIndicator Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Examples/BTRButton/ButtonDemo/ButtonDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ButtonDemo 4 | // 5 | // Created by Jonathan Willing on 12/21/12. 6 | // Copyright (c) 2012 Butter. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | return NSApplicationMain(argc, (const char **)argv); 14 | } 15 | -------------------------------------------------------------------------------- /Examples/BTRControl/ControlEvents/ControlEvents/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ControlEvents 4 | // 5 | // Created by Jonathan Willing on 12/14/12. 6 | // Copyright (c) 2012 ButterKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | return NSApplicationMain(argc, (const char **)argv); 14 | } 15 | -------------------------------------------------------------------------------- /Examples/BTRImageView/ImageView Test/ImageView Test/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ImageView Test 4 | // 5 | // Created by Jonathan Willing on 1/14/13. 6 | // Copyright (c) 2013 Butter. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | return NSApplicationMain(argc, (const char **)argv); 14 | } 15 | -------------------------------------------------------------------------------- /Examples/BTRTextField/TextFieldDemo/TextFieldDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // TextFieldDemo 4 | // 5 | // Created by Indragie Karunaratne on 2012-12-28. 6 | // Copyright (c) 2012 ButterKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | return NSApplicationMain(argc, (const char **)argv); 14 | } 15 | -------------------------------------------------------------------------------- /Examples/BTRPopUpButton/Popup Button Demo/Popup Button Demo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Popup Button Demo 4 | // 5 | // Created by Jonathan Willing on 12/30/12. 6 | // Copyright (c) 2012 Butter. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | return NSApplicationMain(argc, (const char **)argv); 14 | } 15 | -------------------------------------------------------------------------------- /Examples/BTRActivityIndicator/ActivityIndicator Demo/ActivityIndicator Demo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ActivityIndicator Demo 4 | // 5 | // Created by Jonathan Willing on 12/26/12. 6 | // Copyright (c) 2012 Butter. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | return NSApplicationMain(argc, (const char **)argv); 14 | } 15 | -------------------------------------------------------------------------------- /Examples/BTRTextField/TextFieldDemo/TextFieldDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // TextFieldDemo 4 | // 5 | // Created by Indragie Karunaratne on 2012-12-28. 6 | // Copyright (c) 2012 ButterKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : NSObject 12 | 13 | @property (assign) IBOutlet NSWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Butter/BTRLabel.h: -------------------------------------------------------------------------------- 1 | // 2 | // BTRLabel.h 3 | // Butter 4 | // 5 | // Created by Jonathan Willing on 12/21/12. 6 | // Copyright (c) 2012 ButterKit. All rights reserved. 7 | // 8 | 9 | #import "BTRTextField.h" 10 | 11 | // A convenience class for creating a BTRTextField that is set up to show 12 | // like a label, with selection, editing, bezel and background drawing, and 13 | // focus rings disabled. 14 | @interface BTRLabel : BTRTextField 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Examples/BTRTextField/TextFieldDemo/TextFieldDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // TextFieldDemo 4 | // 5 | // Created by Indragie Karunaratne on 2012-12-28. 6 | // Copyright (c) 2012 ButterKit. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @implementation AppDelegate 12 | 13 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 14 | { 15 | // Insert code here to initialize your application 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Examples/BTRButton/ButtonDemo/ButtonDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // ButtonDemo 4 | // 5 | // Created by Jonathan Willing on 12/21/12. 6 | // Copyright (c) 2012 Butter. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface AppDelegate : NSObject 13 | 14 | @property (assign) IBOutlet NSWindow *window; 15 | @property (nonatomic, weak) IBOutlet BTRButton *button; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Examples/BTRControl/ControlEvents/ControlEvents/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // ControlEvents 4 | // 5 | // Created by Jonathan Willing on 12/14/12. 6 | // Copyright (c) 2012 ButterKit. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface AppDelegate : NSObject 13 | 14 | @property (assign) IBOutlet NSWindow *window; 15 | @property (assign) IBOutlet BTRControl *control; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Examples/BTRPopUpButton/Popup Button Demo/Popup Button Demo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // Popup Button Demo 4 | // 5 | // Created by Jonathan Willing on 12/30/12. 6 | // Copyright (c) 2012 Butter. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @implementation AppDelegate 12 | 13 | - (void)awakeFromNib { 14 | [self.popupButton setArrowImage:[NSImage imageNamed:NSImageNameLeftFacingTriangleTemplate] forControlState:BTRControlStateNormal]; 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Examples/BTRPopUpButton/Popup Button Demo/Popup Button Demo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // Popup Button Demo 4 | // 5 | // Created by Jonathan Willing on 12/30/12. 6 | // Copyright (c) 2012 Butter. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface AppDelegate : NSObject 13 | 14 | @property (assign) IBOutlet NSWindow *window; 15 | @property (assign) IBOutlet BTRPopUpButton *popupButton; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Butter/NSImage+BTRImageAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSImage+BTRImageAdditions.h 3 | // Butter 4 | // 5 | // Created by Indragie Karunaratne on 7/16/2013. 6 | // Copyright (c) 2013 ButterKit. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "BTRImage.h" 11 | 12 | @interface NSImage (BTRImageAdditions) 13 | 14 | // Returns an instance of `BTRImage` by copying the receiver and setting the cap insets 15 | // to the given value. 16 | - (BTRImage *)btr_resizableImageWithCapInsets:(NSEdgeInsets)insets; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Butter/Private/BTRControlAction.h: -------------------------------------------------------------------------------- 1 | // 2 | // BTRControlAction.h 3 | // Butter 4 | // 5 | // Created by Jonathan Willing on 7/19/13. 6 | // Copyright (c) 2013 ButterKit. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "BTRControl.h" 11 | 12 | @interface BTRControlAction : NSObject 13 | 14 | @property (nonatomic, weak) id target; 15 | @property (nonatomic, assign) SEL action; 16 | @property (nonatomic, copy) void(^block)(BTRControlEvents events); 17 | @property (nonatomic, assign) BTRControlEvents events; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Examples/BTRImageView/ImageView Test/ImageView Test/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // ImageView Test 4 | // 5 | // Created by Jonathan Willing on 1/14/13. 6 | // Copyright (c) 2013 Butter. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface AppDelegate : NSObject 13 | 14 | @property (assign) IBOutlet NSWindow *window; 15 | @property (nonatomic, assign) IBOutlet BTRImageView *imageView; 16 | 17 | - (IBAction)imageViewContentModeShouldChange:(id)sender; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Butter/NSImage+BTRImageAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSImage+BTRImageAdditions.m 3 | // Butter 4 | // 5 | // Created by Indragie Karunaratne on 7/16/2013. 6 | // Copyright (c) 2013 ButterKit. All rights reserved. 7 | // 8 | 9 | #import "NSImage+BTRImageAdditions.h" 10 | 11 | @implementation NSImage (BTRImageAdditions) 12 | 13 | - (BTRImage *)btr_resizableImageWithCapInsets:(NSEdgeInsets)insets { 14 | BTRImage *image = [[BTRImage alloc] initWithSize:self.size]; 15 | [image addRepresentations:self.representations]; 16 | image.btr_capInsets = insets; 17 | return image; 18 | } 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Examples/BTRButton/ButtonDemo/ButtonDemo/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} 2 | {\colortbl;\red255\green255\blue255;} 3 | \paperw9840\paperh8400 4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural 5 | 6 | \f0\b\fs24 \cf0 Engineering: 7 | \b0 \ 8 | Some people\ 9 | \ 10 | 11 | \b Human Interface Design: 12 | \b0 \ 13 | Some other people\ 14 | \ 15 | 16 | \b Testing: 17 | \b0 \ 18 | Hopefully not nobody\ 19 | \ 20 | 21 | \b Documentation: 22 | \b0 \ 23 | Whoever\ 24 | \ 25 | 26 | \b With special thanks to: 27 | \b0 \ 28 | Mom\ 29 | } 30 | -------------------------------------------------------------------------------- /Examples/BTRControl/ControlEvents/ControlEvents/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} 2 | {\colortbl;\red255\green255\blue255;} 3 | \paperw9840\paperh8400 4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural 5 | 6 | \f0\b\fs24 \cf0 Engineering: 7 | \b0 \ 8 | Some people\ 9 | \ 10 | 11 | \b Human Interface Design: 12 | \b0 \ 13 | Some other people\ 14 | \ 15 | 16 | \b Testing: 17 | \b0 \ 18 | Hopefully not nobody\ 19 | \ 20 | 21 | \b Documentation: 22 | \b0 \ 23 | Whoever\ 24 | \ 25 | 26 | \b With special thanks to: 27 | \b0 \ 28 | Mom\ 29 | } 30 | -------------------------------------------------------------------------------- /Examples/BTRTextField/TextFieldDemo/TextFieldDemo/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} 2 | {\colortbl;\red255\green255\blue255;} 3 | \paperw9840\paperh8400 4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural 5 | 6 | \f0\b\fs24 \cf0 Engineering: 7 | \b0 \ 8 | Some people\ 9 | \ 10 | 11 | \b Human Interface Design: 12 | \b0 \ 13 | Some other people\ 14 | \ 15 | 16 | \b Testing: 17 | \b0 \ 18 | Hopefully not nobody\ 19 | \ 20 | 21 | \b Documentation: 22 | \b0 \ 23 | Whoever\ 24 | \ 25 | 26 | \b With special thanks to: 27 | \b0 \ 28 | Mom\ 29 | } 30 | -------------------------------------------------------------------------------- /Examples/BTRImageView/ImageView Test/ImageView Test/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} 2 | {\colortbl;\red255\green255\blue255;} 3 | \paperw9840\paperh8400 4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural 5 | 6 | \f0\b\fs24 \cf0 Engineering: 7 | \b0 \ 8 | Some people\ 9 | \ 10 | 11 | \b Human Interface Design: 12 | \b0 \ 13 | Some other people\ 14 | \ 15 | 16 | \b Testing: 17 | \b0 \ 18 | Hopefully not nobody\ 19 | \ 20 | 21 | \b Documentation: 22 | \b0 \ 23 | Whoever\ 24 | \ 25 | 26 | \b With special thanks to: 27 | \b0 \ 28 | Mom\ 29 | } 30 | -------------------------------------------------------------------------------- /Butter/BTRImage.h: -------------------------------------------------------------------------------- 1 | // 2 | // BTRImage.h 3 | // Butter 4 | // 5 | // Created by Jonathan Willing on 7/16/13. 6 | // Copyright (c) 2013 ButterKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface BTRImage : NSImage 12 | 13 | // The edge insets for use in BTRImageView. This property will not affect normal image drawing. 14 | @property (nonatomic, assign) NSEdgeInsets btr_capInsets; 15 | 16 | // Returns an image created by calling NSImage +imageNamed:, copying the image, and setting `capInsets`. 17 | + (instancetype)resizableImageNamed:(NSString *)name withCapInsets:(NSEdgeInsets)insets; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Examples/BTRPopUpButton/Popup Button Demo/Popup Button Demo/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} 2 | {\colortbl;\red255\green255\blue255;} 3 | \paperw9840\paperh8400 4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural 5 | 6 | \f0\b\fs24 \cf0 Engineering: 7 | \b0 \ 8 | Some people\ 9 | \ 10 | 11 | \b Human Interface Design: 12 | \b0 \ 13 | Some other people\ 14 | \ 15 | 16 | \b Testing: 17 | \b0 \ 18 | Hopefully not nobody\ 19 | \ 20 | 21 | \b Documentation: 22 | \b0 \ 23 | Whoever\ 24 | \ 25 | 26 | \b With special thanks to: 27 | \b0 \ 28 | Mom\ 29 | } 30 | -------------------------------------------------------------------------------- /Examples/BTRActivityIndicator/ActivityIndicator Demo/ActivityIndicator Demo/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} 2 | {\colortbl;\red255\green255\blue255;} 3 | \paperw9840\paperh8400 4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural 5 | 6 | \f0\b\fs24 \cf0 Engineering: 7 | \b0 \ 8 | Some people\ 9 | \ 10 | 11 | \b Human Interface Design: 12 | \b0 \ 13 | Some other people\ 14 | \ 15 | 16 | \b Testing: 17 | \b0 \ 18 | Hopefully not nobody\ 19 | \ 20 | 21 | \b Documentation: 22 | \b0 \ 23 | Whoever\ 24 | \ 25 | 26 | \b With special thanks to: 27 | \b0 \ 28 | Mom\ 29 | } 30 | -------------------------------------------------------------------------------- /Butter/BTRImage.m: -------------------------------------------------------------------------------- 1 | // 2 | // BTRImage.m 3 | // Butter 4 | // 5 | // Created by Jonathan Willing on 7/16/13. 6 | // Copyright (c) 2013 ButterKit. All rights reserved. 7 | // 8 | 9 | #import "BTRImage.h" 10 | 11 | @implementation BTRImage 12 | 13 | + (instancetype)resizableImageNamed:(NSString *)name withCapInsets:(NSEdgeInsets)insets { 14 | NSImage *originalImage = [self imageNamed:name]; 15 | if (originalImage.representations) { 16 | BTRImage *image = [[BTRImage alloc] initWithSize:originalImage.size]; 17 | [image addRepresentations:originalImage.representations]; 18 | image.btr_capInsets = insets; 19 | return image; 20 | } else { 21 | return nil; 22 | } 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Butter/Butter.h: -------------------------------------------------------------------------------- 1 | // 2 | // ButterKit.h 3 | // Butter 4 | // 5 | // Created by Indragie Karunaratne And Jonathan Willing on 2012-12-07. 6 | // Copyright (c) 2012 ButterKit. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | #import 13 | #import 14 | #import 15 | #import 16 | #import 17 | #import 18 | #import 19 | #import 20 | #import 21 | #import 22 | #import 23 | -------------------------------------------------------------------------------- /Examples/BTRActivityIndicator/ActivityIndicator Demo/ActivityIndicator Demo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // ActivityIndicator Demo 4 | // 5 | // Created by Jonathan Willing on 12/26/12. 6 | // Copyright (c) 2012 Butter. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface AppDelegate : NSObject 13 | 14 | @property (nonatomic, assign) IBOutlet NSWindow *window; 15 | @property (nonatomic, assign) IBOutlet BTRActivityIndicator *defaultIndicator; 16 | @property (nonatomic, assign) IBOutlet BTRActivityIndicator *customizedIndicatorOne; 17 | @property (nonatomic, assign) IBOutlet BTRActivityIndicator *customizedIndicatorTwo; 18 | 19 | - (IBAction)toggleAnimation:(id)sender; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Butter/BTRSecureTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // BTRSecureTextField.h 3 | // Butter 4 | // 5 | // Created by Indragie Karunaratne on 2012-12-28. 6 | // Copyright (c) 2012 ButterKit. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "BTRTextFieldProtocol.h" 11 | 12 | // The secure variant of BTRTextField. See BTRTextField header for more information. 13 | @interface BTRSecureTextField : NSSecureTextField 14 | @end 15 | 16 | // Subclassing hooks for a BTRSecureTextField 17 | @interface BTRSecureTextField (SubclassingHooks) 18 | 19 | - (void)drawBackgroundInRect:(NSRect)rect; 20 | - (NSRect)drawingRectForProposedDrawingRect:(NSRect)rect; 21 | - (NSRect)editingRectForProposedEditingRect:(NSRect)rect; 22 | - (void)setFieldEditorAttributes:(NSTextView *)fieldEditor; 23 | 24 | @end 25 | 26 | -------------------------------------------------------------------------------- /Butter/BTRLabel.m: -------------------------------------------------------------------------------- 1 | // 2 | // BTRLabel.m 3 | // Butter 4 | // 5 | // Created by Jonathan Willing on 12/21/12. 6 | // Copyright (c) 2012 ButterKit. All rights reserved. 7 | // 8 | 9 | #import "BTRLabel.h" 10 | 11 | @implementation BTRLabel 12 | 13 | static void BTRLabelCommonInit(BTRLabel *self) { 14 | self.bezeled = NO; 15 | self.editable = NO; 16 | self.drawsFocusRing = NO; 17 | self.drawsBackground = NO; 18 | self.selectable = NO; 19 | } 20 | 21 | - (instancetype)initWithFrame:(NSRect)frame { 22 | self = [super initWithFrame:frame]; 23 | if (self == nil) return nil; 24 | BTRLabelCommonInit(self); 25 | return self; 26 | } 27 | 28 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 29 | self = [super initWithCoder:aDecoder]; 30 | if (self == nil) return nil; 31 | BTRLabelCommonInit(self); 32 | return self; 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /Examples/ButterExamples.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 15 | 16 | 18 | 19 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Butter/BTRButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // BTRButton.h 3 | // Butter 4 | // 5 | // Created by Jonathan Willing on 12/21/12. 6 | // Copyright (c) 2012 ButterKit. All rights reserved. 7 | // 8 | 9 | #import "BTRControl.h" 10 | #import "BTRImageView.h" 11 | #import "BTRLabel.h" 12 | 13 | @interface BTRButton : BTRControl 14 | 15 | @property (nonatomic, strong, readonly) BTRLabel *titleLabel; 16 | @property (nonatomic, strong, readonly) BTRImageView *backgroundImageView; 17 | @property (nonatomic, strong, readonly) BTRImageView *imageView; 18 | 19 | // Sets the content mode on the underlying image view. 20 | @property (nonatomic, assign) BTRViewContentMode backgroundContentMode; 21 | @property (nonatomic, assign) BTRViewContentMode imageContentMode; 22 | 23 | // Subclassing hooks 24 | @property (readonly) CGRect backgroundImageFrame; 25 | @property (readonly) CGRect imageFrame; 26 | @property (readonly) CGRect labelFrame; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Butter.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |spec| 2 | spec.name = "Butter" 3 | spec.version = "0.2.0" 4 | spec.summary = "A big shot of epicness for AppKit. It's time to put a jetpack on your tricycle." 5 | spec.homepage = "https://github.com/ButterKit/Butter" 6 | spec.authors = { "Indragie Karunaratne" => "indragiek", 7 | "Jonathan Willing" => "jwilling" } 8 | spec.source = { :git => "https://github.com/ButterKit/Butter.git", :tag => "#{spec.version}" } 9 | spec.license = { :type => "MIT", :file => "LICENSE.md" } 10 | spec.description = "Butter is a framework for OS X that seeks to provide a set of commonly used controls which are full replacements for their cell-based AppKit counterparts." 11 | 12 | spec.platform = :osx 13 | spec.frameworks = 'Cocoa', 'QuartzCore' 14 | spec.requires_arc = true 15 | 16 | spec.osx.deployment_target = '10.8' 17 | 18 | spec.source_files = "Butter/**/*.{h,m}" 19 | spec.exclude_files = "Butter/en.lproj" 20 | spec.private_header_files = "Butter/Private/*.h" 21 | end 22 | -------------------------------------------------------------------------------- /Butter/BTRTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // BTRTextField.h 3 | // Butter 4 | // 5 | // Created by Jonathan Willing on 12/21/12. 6 | // Copyright (c) 2012 ButterKit. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "BTRTextFieldProtocol.h" 11 | 12 | // BTRTextField is a powerful subclass of NSTextField that adds support 13 | // for image-based customization and modifications of default drawing, 14 | // plus control event additions. 15 | // 16 | // BTRTextField should _not_ be layer backed in Interface Builder. 17 | // There is an Interface Builder bug that leads to an issue which causes 18 | // an additional shadow to be shown underneath the textfield. 19 | @interface BTRTextField : NSTextField 20 | @end 21 | 22 | // Subclassing hooks for a BTRTextField 23 | @interface BTRTextField (SubclassingHooks) 24 | 25 | - (void)drawBackgroundInRect:(NSRect)rect; 26 | - (NSRect)drawingRectForProposedDrawingRect:(NSRect)rect; 27 | - (NSRect)editingRectForProposedEditingRect:(NSRect)rect; 28 | - (void)setFieldEditorAttributes:(NSTextView *)fieldEditor; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Butter/Butter-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.ButterKit.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | FMWK 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | NSHumanReadableCopyright 26 | Copyright © 2012 ButterKit. All rights reserved. 27 | NSPrincipalClass 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Examples/BTRImageView/ImageView Test/ImageView Test/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // ImageView Test 4 | // 5 | // Created by Jonathan Willing on 1/14/13. 6 | // Copyright (c) 2013 Butter. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @implementation AppDelegate 12 | 13 | - (void)awakeFromNib { 14 | self.imageView.contentMode = BTRViewContentModeCenter; 15 | 16 | // We're just setting the image view's image to a random image. In this case I'm redrawing 17 | // system-provided artwork at a larger size, just for demonstration purposes. 18 | self.imageView.image = [NSImage imageWithSize:CGSizeMake(150, 150) flipped:NO 19 | drawingHandler:^BOOL(NSRect dstRect) { 20 | [[NSImage imageNamed:NSImageNameUser] drawInRect:dstRect fromRect:CGRectZero operation:NSCompositeSourceOver fraction:1]; 21 | return YES; 22 | }]; 23 | } 24 | 25 | - (void)imageViewContentModeShouldChange:(NSSegmentedControl *)sender { 26 | self.imageView.contentMode = (sender.selectedSegment == 0 ? BTRViewContentModeCenter : BTRViewContentModeScaleAspectFit); 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /Examples/BTRButton/ButtonDemo/ButtonDemo/ButtonDemo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | Butter.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSHumanReadableCopyright 28 | Copyright © 2012 Butter. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /Examples/BTRControl/ControlEvents/ControlEvents/ControlEvents-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | ButterKit.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSHumanReadableCopyright 28 | Copyright © 2012 ButterKit. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /Examples/BTRImageView/ImageView Test/ImageView Test/ImageView Test-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.Butter.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSHumanReadableCopyright 28 | Copyright © 2013 Butter. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /Examples/BTRPopUpButton/Popup Button Demo/Popup Button Demo/Popup Button Demo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | Butter.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSHumanReadableCopyright 28 | Copyright © 2012 Butter. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /Examples/BTRTextField/TextFieldDemo/TextFieldDemo/TextFieldDemo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.butterkit.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSHumanReadableCopyright 28 | Copyright © 2012 ButterKit. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /Examples/BTRActivityIndicator/ActivityIndicator Demo/ActivityIndicator Demo/ActivityIndicator Demo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | Butter.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSHumanReadableCopyright 28 | Copyright © 2012 Butter. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /Butter/BTRGeometryAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // BTRGeometryAdditions.h 3 | // Butter 4 | // 5 | // Created by Indragie Karunaratne on 2012-12-07. 6 | // Copyright (c) 2012 Indragie Karunaratne and Jonathan Willing. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | // Reimplementation of UIEdgeInsets 12 | 13 | #define BTRNSEdgeInsetsZero (NSEdgeInsets){0, 0, 0, 0} 14 | 15 | NS_INLINE CGRect BTRNSEdgeInsetsInsetRect(CGRect rect, NSEdgeInsets insets) { 16 | CGRect newRect = rect; 17 | newRect.origin.x += insets.left; 18 | newRect.size.width -= insets.right + insets.left; 19 | newRect.origin.y += insets.top; 20 | newRect.size.height -= insets.top + insets.bottom; 21 | return newRect; 22 | } 23 | 24 | NS_INLINE CGRect BTRCAContentsCenterForInsets(NSEdgeInsets insets, CGSize imageSize) { 25 | CGRect imageRect = BTRNSEdgeInsetsInsetRect((CGRect){.size=imageSize}, insets); 26 | if (imageRect.size.width > 0) { 27 | imageRect.origin.x /= imageSize.width; 28 | imageRect.size.width /= imageSize.width; 29 | } 30 | if (imageRect.size.height > 0) { 31 | imageRect.origin.y /= imageSize.height; 32 | imageRect.size.height /= imageSize.height; 33 | } 34 | return imageRect; 35 | } 36 | 37 | // NSString to Data type conversions 38 | 39 | NS_INLINE NSString * BTRNSStringFromCGRect(CGRect rect) { 40 | return NSStringFromRect(rect); 41 | } 42 | 43 | NS_INLINE NSString * BTRNSStringFromCGSize(CGSize size) { 44 | return NSStringFromSize(size); 45 | } 46 | -------------------------------------------------------------------------------- /Butter.xcodeproj/project.xcworkspace/xcshareddata/Butter.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | C5D60C9A-8331-4F11-AB25-B2A5E1F71B98 9 | IDESourceControlProjectName 10 | Butter 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 1BE2EC80BAFB45464F850DCF6C22CB755957A826 14 | https://github.com/ButterKit/Butter.git 15 | 16 | IDESourceControlProjectPath 17 | Butter.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 1BE2EC80BAFB45464F850DCF6C22CB755957A826 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/ButterKit/Butter.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | 1BE2EC80BAFB45464F850DCF6C22CB755957A826 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 1BE2EC80BAFB45464F850DCF6C22CB755957A826 36 | IDESourceControlWCCName 37 | Butter 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Examples/ButterExamples.xcworkspace/xcshareddata/ButterExamples.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 58E26AFF-31E8-49B3-915D-F25597B2A0C0 9 | IDESourceControlProjectName 10 | ButterExamples 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 93B7E5AC-6168-4090-8944-748E76788CD0 14 | https://github.com/ButterKit/Butter.git 15 | 16 | IDESourceControlProjectPath 17 | ButterExamples.xcworkspace 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 93B7E5AC-6168-4090-8944-748E76788CD0 21 | .. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/ButterKit/Butter.git 25 | IDESourceControlProjectVersion 26 | 110 27 | IDESourceControlProjectWCCIdentifier 28 | 93B7E5AC-6168-4090-8944-748E76788CD0 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 93B7E5AC-6168-4090-8944-748E76788CD0 36 | IDESourceControlWCCName 37 | Butter 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Butter/BTRTextFieldProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // BTRTextFieldProtocol.h 3 | // Butter 4 | // 5 | // Created by Aron Cedercrantz on 21/04/14. 6 | // Copyright (c) 2014 ButterKit. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "BTRControl.h" 11 | #import "BTRImageView.h" 12 | 13 | // The BTRTextField protocol declares all methods a Butter text field responds 14 | // to. 15 | // 16 | // Instead of this protocol you're probably more interested in the two concrete 17 | // classes `BTRTextField` and `BTRSecureTextField`. 18 | @protocol BTRTextField 19 | 20 | - (NSImage *)backgroundImageForControlState:(BTRControlState)state; 21 | - (void)setBackgroundImage:(NSImage *)image forControlState:(BTRControlState)state; 22 | 23 | @property (nonatomic, assign) BOOL drawsFocusRing; 24 | // Modifies the contentMode on the underlying image view. 25 | @property (nonatomic, assign) BTRViewContentMode contentMode; 26 | @property (nonatomic, assign) BOOL animatesContents; 27 | @property (nonatomic, strong) NSTextFieldCell *textFieldCell; 28 | 29 | // Text attribute accessors 30 | @property (nonatomic, strong) NSString *placeholderTitle; 31 | @property (nonatomic, strong) NSColor *placeholderTextColor; 32 | @property (nonatomic, strong) NSFont *placeholderFont; 33 | @property (nonatomic, strong) NSShadow *placeholderShadow; 34 | 35 | @property (nonatomic, strong) NSShadow *textShadow; 36 | 37 | // State 38 | @property (nonatomic, readonly) BTRControlState state; 39 | @property (nonatomic, getter = isHighlighted) BOOL highlighted; 40 | @property (nonatomic, readonly) NSInteger clickCount; 41 | 42 | - (void)addBlock:(void (^)(BTRControlEvents events))block forControlEvents:(BTRControlEvents)events; 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /Examples/BTRControl/ControlEvents/ControlEvents.xcodeproj/project.xcworkspace/xcshareddata/ControlEvents.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectIdentifier 6 | 0F329738-3833-43FA-A0FA-6AD8B821962F 7 | IDESourceControlProjectName 8 | ControlEvents 9 | IDESourceControlProjectOriginsDictionary 10 | 11 | 93B7E5AC-6168-4090-8944-748E76788CD0 12 | https://github.com/ButterKit/Butter.git 13 | 14 | IDESourceControlProjectPath 15 | Butter/Examples/BTRControl/ControlEvents/ControlEvents.xcodeproj/project.xcworkspace 16 | IDESourceControlProjectRelativeInstallPathDictionary 17 | 18 | 93B7E5AC-6168-4090-8944-748E76788CD0 19 | ../../../../../.. 20 | 21 | IDESourceControlProjectURL 22 | https://github.com/ButterKit/Butter.git 23 | IDESourceControlProjectVersion 24 | 110 25 | IDESourceControlProjectWCCIdentifier 26 | 93B7E5AC-6168-4090-8944-748E76788CD0 27 | IDESourceControlProjectWCConfigurations 28 | 29 | 30 | IDESourceControlRepositoryExtensionIdentifierKey 31 | public.vcs.git 32 | IDESourceControlWCCIdentifierKey 33 | 93B7E5AC-6168-4090-8944-748E76788CD0 34 | IDESourceControlWCCName 35 | Butter 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Butter/BTRScrollView.h: -------------------------------------------------------------------------------- 1 | /* 2 | Created by Jonathan Willing on 8/28/13. 3 | Copyright (c) 2013, ButterKit. All rights reserved. 4 | Licensed under the MIT license 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 7 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation 8 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 9 | to permit persons to whom the Software is furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 14 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 15 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 16 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 17 | IN THE SOFTWARE. 18 | */ 19 | 20 | #import 21 | #import "BTRClipView.h" 22 | 23 | // A NSScrollView subclass which uses an instance of BTRClipView 24 | // as the clip view instead of NSClipView. 25 | // 26 | // Layer-backed by default. 27 | @interface BTRScrollView : NSScrollView 28 | 29 | // Returns the scroll view's content view that is an instance of BTRClipView, or 30 | // nil if it does not exist. 31 | @property (readonly, strong) BTRClipView *clipView; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /Examples/BTRTextField/TextFieldDemo/TextFieldDemo.xcodeproj/project.xcworkspace/xcshareddata/TextFieldDemo.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectIdentifier 6 | A205AB43-CC6A-416E-A376-7BEFCE55FF80 7 | IDESourceControlProjectName 8 | TextFieldDemo 9 | IDESourceControlProjectOriginsDictionary 10 | 11 | 93B7E5AC-6168-4090-8944-748E76788CD0 12 | https://github.com/ButterKit/Butter.git 13 | 14 | IDESourceControlProjectPath 15 | Butter/Examples/BTRTextField/TextFieldDemo/TextFieldDemo.xcodeproj/project.xcworkspace 16 | IDESourceControlProjectRelativeInstallPathDictionary 17 | 18 | 93B7E5AC-6168-4090-8944-748E76788CD0 19 | ../../../../../.. 20 | 21 | IDESourceControlProjectURL 22 | https://github.com/ButterKit/Butter.git 23 | IDESourceControlProjectVersion 24 | 110 25 | IDESourceControlProjectWCCIdentifier 26 | 93B7E5AC-6168-4090-8944-748E76788CD0 27 | IDESourceControlProjectWCConfigurations 28 | 29 | 30 | IDESourceControlRepositoryExtensionIdentifierKey 31 | public.vcs.git 32 | IDESourceControlWCCIdentifierKey 33 | 93B7E5AC-6168-4090-8944-748E76788CD0 34 | IDESourceControlWCCName 35 | Butter 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Examples/BTRPopUpButton/Popup Button Demo/Popup Button Demo.xcodeproj/project.xcworkspace/xcshareddata/Popup Button Demo.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectIdentifier 6 | E9D48EC3-A133-4C05-B463-26D8CA5F617E 7 | IDESourceControlProjectName 8 | Popup Button Demo 9 | IDESourceControlProjectOriginsDictionary 10 | 11 | 93B7E5AC-6168-4090-8944-748E76788CD0 12 | https://github.com/ButterKit/Butter.git 13 | 14 | IDESourceControlProjectPath 15 | Butter/Examples/BTRPopUpButton/Popup Button Demo/Popup Button Demo.xcodeproj/project.xcworkspace 16 | IDESourceControlProjectRelativeInstallPathDictionary 17 | 18 | 93B7E5AC-6168-4090-8944-748E76788CD0 19 | ../../../../../.. 20 | 21 | IDESourceControlProjectURL 22 | https://github.com/ButterKit/Butter.git 23 | IDESourceControlProjectVersion 24 | 110 25 | IDESourceControlProjectWCCIdentifier 26 | 93B7E5AC-6168-4090-8944-748E76788CD0 27 | IDESourceControlProjectWCConfigurations 28 | 29 | 30 | IDESourceControlRepositoryExtensionIdentifierKey 31 | public.vcs.git 32 | IDESourceControlWCCIdentifierKey 33 | 93B7E5AC-6168-4090-8944-748E76788CD0 34 | IDESourceControlWCCName 35 | Butter 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Butter/NSView+BTRAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSView+BTRAdditions.h 3 | // Originally from Rebel 4 | // 5 | // Created by Justin Spahr-Summers on 2012-09-04. 6 | // Updated by Jonathan Willing 7 | // Copyright (c) 2012 GitHub. All rights reserved. 8 | // 9 | 10 | #import 11 | 12 | typedef NS_ENUM(NSInteger, BTRViewAnimationCurve) { 13 | BTRViewAnimationCurveEaseInOut, 14 | BTRViewAnimationCurveEaseIn, 15 | BTRViewAnimationCurveEaseOut, 16 | BTRViewAnimationCurveLinear 17 | }; 18 | 19 | // Better block-based animation and animator proxies. 20 | @interface NSView (BTRAnimationAdditions) 21 | 22 | // Invokes +btr_animate:completion: with a nil completion block. 23 | + (void)btr_animate:(void (^)(void))animations; 24 | 25 | // Executes the given animation block within a new NSAnimationContext. When all 26 | // animations in the group complete or are canceled, the given completion block 27 | // (if not nil) will be invoked. Implicit animation is turned on by default. 28 | + (void)btr_animate:(void (^)(void))animations 29 | completion:(void (^)(void))completion; 30 | 31 | // Invokes +btr_animate:completion:, setting the animation duration of the 32 | // context before queuing the given animations. 33 | + (void)btr_animateWithDuration:(NSTimeInterval)duration 34 | animations:(void (^)(void))animations 35 | completion:(void (^)(void))completion; 36 | 37 | // Invokes +btr_animateWithDuration:animations:completion: with the specified 38 | // animation curve. 39 | + (void)btr_animateWithDuration:(NSTimeInterval)duration 40 | animationCurve:(BTRViewAnimationCurve)curve 41 | animations:(void (^)(void))animations 42 | completion:(void (^)(void))completion; 43 | 44 | 45 | // If the receiver is a descendant of a clip view, then this method will 46 | // scroll the clip view to the passed in rect, optionally using the animator 47 | // proxy, or using the enhanced scrolling in BTRClipView, if in use. 48 | - (void)btr_scrollRectToVisible:(NSRect)rect animated:(BOOL)animated; 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /Butter/BTRPopUpButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // BTRPopUpButton.h 3 | // Butter 4 | // 5 | // Created by Indragie Karunaratne on 2012-12-30. 6 | // Copyright (c) 2012 ButterKit. All rights reserved. 7 | // 8 | 9 | #import "BTRControl.h" 10 | 11 | @interface BTRPopUpButton : BTRControl 12 | 13 | // The pop up button's menu. 14 | @property IBOutlet NSMenu *menu; 15 | 16 | // The selected item whose title is being currently displayed in 17 | // the pop up button. 18 | @property (nonatomic, strong) NSMenuItem *selectedItem; 19 | 20 | // Whether the pop up button automatically calls -setEnabled: on all 21 | // menu items before displaying the menu. 22 | @property (nonatomic, assign) BOOL autoenablesItems; 23 | 24 | // Alignment of the text in the pop up button label. 25 | @property (nonatomic, assign) NSTextAlignment textAlignment; 26 | 27 | - (void)selectItemAtIndex:(NSUInteger)index; 28 | @property (readonly) NSUInteger indexOfSelectedItem; 29 | 30 | // Adjust the width of the view to fit the content 31 | - (void)sizeToFit; 32 | 33 | - (NSImage *)arrowImageForControlState:(BTRControlState)state; 34 | - (void)setArrowImage:(NSImage *)image forControlState:(BTRControlState)state; 35 | 36 | // Can be overriden by subclasses to customize layout 37 | // The frame of the image view 38 | @property (readonly) NSRect imageFrame; 39 | 40 | // The frame of the text label 41 | @property (readonly) NSRect labelFrame; 42 | 43 | // The frame of the arrow image view 44 | @property (readonly) NSRect arrowFrame; 45 | 46 | // The padding between each element (between image and label, and label and arrow) 47 | @property (readonly) CGFloat interElementSpacing; 48 | 49 | // The distance between the pop up button content and the view edges 50 | @property (readonly) CGFloat edgeInset; 51 | 52 | // The width to fit all the content in the view (used by -sizeToFit) 53 | @property (readonly) CGFloat widthToFit; 54 | 55 | // Returns the arrow image for the current `BTRControlState` 56 | @property (nonatomic, strong, readonly) NSImage *currentArrowImage; 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /Butter/BTRImageView.h: -------------------------------------------------------------------------------- 1 | // 2 | // BTRImageView.h 3 | // Butter 4 | // 5 | // Created by Jonathan Willing on 12/12/12. 6 | // Copyright (c) 2012 ButterKit. All rights reserved. 7 | // 8 | 9 | #import "BTRView.h" 10 | 11 | // Equivalent to UIViewContentMode. See "Providing CALayer Content" 12 | // in the Core Animation guide for more information about the modes. 13 | typedef NS_ENUM(NSInteger, BTRViewContentMode) { 14 | BTRViewContentModeScaleToFill, 15 | BTRViewContentModeScaleAspectFit, 16 | BTRViewContentModeScaleAspectFill, 17 | BTRViewContentModeCenter, 18 | BTRViewContentModeTop, 19 | BTRViewContentModeBottom, 20 | BTRViewContentModeLeft, 21 | BTRViewContentModeRight, 22 | BTRViewContentModeTopLeft, 23 | BTRViewContentModeTopRight, 24 | BTRViewContentModeBottomLeft, 25 | BTRViewContentModeBottomRight, 26 | }; 27 | 28 | // BTRImageView is an extremely lightweight replacement for NSImageView that is based 29 | // off of CALayers. The image layer itself can have a transform directly applied without 30 | // any consequence, as this is a layer-hosting view. BTRImageView can also display animated 31 | // images, such as animated GIFs. 32 | @interface BTRImageView : BTRView 33 | 34 | // The dedicated initializer. The bounds of the image view will 35 | // be adjusted to match the size of the image. 36 | - (instancetype)initWithImage:(NSImage *)image; 37 | 38 | // The image displayed in the image view. 39 | @property (nonatomic, strong) NSImage *image; 40 | 41 | // Set to YES to animate images with multiple frames (e.g. animated GIFs). Default is NO. 42 | @property (nonatomic, assign) BOOL animatesMultipleFrames; 43 | 44 | // The transform applied to the image. 45 | @property (nonatomic, assign) CATransform3D transform; 46 | 47 | // Add an animation to the image. 48 | - (void)addAnimation:(CAAnimation *)animation forKey:(NSString *)key; 49 | 50 | // The content mode for the image view. Directly modifies the layer's contentsGravity. 51 | // 52 | // Defaults to BTRViewContentModeScaleToFill. 53 | @property (nonatomic, assign) BTRViewContentMode contentMode; 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /Examples/BTRControl/ControlEvents/ControlEvents/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // ControlEvents 4 | // 5 | // Created by Jonathan Willing on 12/14/12. 6 | // Copyright (c) 2012 ButterKit. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @implementation AppDelegate 12 | 13 | - (void)awakeFromNib { 14 | self.control.btr_backgroundColor = [NSColor redColor]; 15 | 16 | [self.control addBlock:^(BTRControlEvents events) { NSLog(@"drag enter"); } forControlEvents:BTRControlEventMouseDragEnter]; 17 | [self.control addBlock:^(BTRControlEvents events) { NSLog(@"drag exit"); } forControlEvents:BTRControlEventMouseDragExit]; 18 | [self.control addBlock:^(BTRControlEvents events) { NSLog(@"mouse up inside"); } forControlEvents:BTRControlEventMouseUpInside]; 19 | [self.control addBlock:^(BTRControlEvents events) { NSLog(@"mouse down inside"); } forControlEvents:BTRControlEventMouseDownInside]; 20 | [self.control addBlock:^(BTRControlEvents events) { NSLog(@"mouse up outside"); } forControlEvents:BTRControlEventMouseUpOutside]; 21 | [self.control addBlock:^(BTRControlEvents events) { NSLog(@"mouse entered"); } forControlEvents:BTRControlEventMouseEntered]; 22 | [self.control addBlock:^(BTRControlEvents events) { NSLog(@"mouse exited"); } forControlEvents:BTRControlEventMouseExited]; 23 | 24 | [self.control addBlock:^(BTRControlEvents events) { NSLog(@"click"); } forControlEvents:BTRControlEventClick]; 25 | [self.control addBlock:^(BTRControlEvents events) { NSLog(@"repeat click"); } forControlEvents:BTRControlEventClickRepeat]; 26 | [self.control addBlock:^(BTRControlEvents events) { NSLog(@"left click"); } forControlEvents:BTRControlEventLeftClick]; 27 | [self.control addBlock:^(BTRControlEvents events) { NSLog(@"right click"); } forControlEvents:BTRControlEventRightClick]; 28 | 29 | [self.control addBlock:^(BTRControlEvents events) { NSLog(@"***VALUE CHANGED***"); } forControlEvents:BTRControlEventValueChanged]; 30 | 31 | self.control.enabled = YES; 32 | self.control.selected = YES; 33 | NSLog(@"state: %li",self.control.state); 34 | 35 | [self.control addTarget:self action:@selector(handleClick:) forControlEvents:BTRControlEventClick]; 36 | } 37 | 38 | - (void)handleClick:(id)sender { 39 | NSLog(@"click (selector)"); 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /Butter/BTRScrollView.m: -------------------------------------------------------------------------------- 1 | /* 2 | Created by Jonathan Willing on 8/28/13. 3 | Copyright (c) 2013, ButterKit. All rights reserved. 4 | Licensed under the MIT license 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 7 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation 8 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 9 | to permit persons to whom the Software is furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 14 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 15 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 16 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 17 | IN THE SOFTWARE. 18 | */ 19 | 20 | #import "BTRScrollView.h" 21 | #import "BTRClipView.h" 22 | 23 | @implementation BTRScrollView 24 | 25 | #pragma mark Lifecycle 26 | 27 | - (instancetype)initWithFrame:(NSRect)frameRect { 28 | self = [super initWithFrame:frameRect]; 29 | if (self == nil) return nil; 30 | 31 | [self swapClipView]; 32 | 33 | return self; 34 | } 35 | 36 | - (void)awakeFromNib { 37 | [super awakeFromNib]; 38 | 39 | if (![self.contentView isKindOfClass:BTRClipView.class]) { 40 | [self swapClipView]; 41 | } 42 | } 43 | 44 | - (BTRClipView *)clipView { 45 | if ([self.contentView isKindOfClass:BTRClipView.class]) { 46 | return (BTRClipView *)self.contentView; 47 | } 48 | 49 | return nil; 50 | } 51 | 52 | #pragma mark Clip view swapping 53 | 54 | - (void)swapClipView { 55 | self.wantsLayer = YES; 56 | id documentView = self.documentView; 57 | BTRClipView *clipView = [[BTRClipView alloc] initWithFrame:self.contentView.frame]; 58 | self.contentView = clipView; 59 | self.documentView = documentView; 60 | } 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /Butter/BTRView.h: -------------------------------------------------------------------------------- 1 | // 2 | // BTRView.h 3 | // Originally from Rebel 4 | // 5 | // Created by Justin Spahr-Summers on 2012-07-29. 6 | // Copyright (c) 2012 GitHub. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | // A base class for layer-backed views. 12 | @interface BTRView : NSView 13 | 14 | // Optional initializer which opts to provide the option to create a 15 | // layer-hosted view instead of a layer-backed view. 16 | - (instancetype)initWithFrame:(NSRect)frame layerHosted:(BOOL)hostsLayer; 17 | 18 | // A background color for the view, or nil if none has been set. 19 | @property (nonatomic, strong) NSColor *btr_backgroundColor; 20 | 21 | // Whether the view's content and subviews masks to its bounds 22 | // 23 | // Defaults to NO. 24 | @property (nonatomic, assign) BOOL masksToBounds; 25 | 26 | // A radius used to draw rounded corners for the view's background. 27 | // 28 | // Typically, you will want to enable clipsToBounds when setting this property 29 | // to a non-zero value. 30 | // 31 | // Defaults to 0. 32 | @property (nonatomic, assign) CGFloat cornerRadius; 33 | 34 | // Whether the view's drawing completely fills its bounds with opaque content. 35 | // 36 | // Defaults to NO. 37 | @property (assign, getter = isOpaque) BOOL opaque; 38 | 39 | // Whether the view's drawing and layout uses a flipped (top-left origin) 40 | // coordinate system. 41 | // 42 | // Defaults to NO. 43 | @property (assign, getter = isFlipped) BOOL flipped; 44 | 45 | // Whether the content is redrawn with a default animation applied. 46 | // 47 | // Defaults to NO. 48 | @property (nonatomic, assign) BOOL animatesContents; 49 | 50 | // The view's parent view controller. 51 | // 52 | // Used to patch the view controller into the responder chain. 53 | @property (nonatomic, assign) IBOutlet NSViewController *viewController; 54 | 55 | // A wrapper around -display that enables the animation on view redrawing, 56 | // draws the view, and changes back to default content animation setting. 57 | // 58 | // The animation can be customized by wrapping the call in a NSView animation. 59 | - (void)displayAnimated; 60 | 61 | // TODO: Disabled due to an AppKit bug getting in the way. Will be implemented 62 | // in the future. 63 | //@property (nonatomic, copy) void (^drawRectBlock)(BTRView *view, CGContextRef ctx); 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /Examples/BTRButton/ButtonDemo/ButtonDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // ButtonDemo 4 | // 5 | // Created by Jonathan Willing on 12/21/12. 6 | // Copyright (c) 2012 Butter. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @implementation AppDelegate 12 | 13 | - (void)awakeFromNib { 14 | [self.button setTitle:@"Standard" forControlState:BTRControlStateNormal]; 15 | [self.button setTitle:@"Highlighted" forControlState:BTRControlStateHighlighted]; 16 | [self.button setTitle:@"Hovering" forControlState:BTRControlStateHover]; 17 | [self.button setTitle:@"Selected" forControlState:BTRControlStateSelected]; 18 | [self.button setTitle:@"Selected & Hover" forControlState:BTRControlStateSelected | BTRControlStateHover]; 19 | 20 | NSImage *green = [self pixelImageWithColor:NSColor.greenColor]; 21 | NSImage *purple = [self pixelImageWithColor:NSColor.purpleColor]; 22 | NSImage *red = [self pixelImageWithColor:NSColor.redColor]; 23 | NSImage *yellow = [self pixelImageWithColor:NSColor.yellowColor]; 24 | NSImage *blue = [self pixelImageWithColor:NSColor.blueColor]; 25 | 26 | [self.button setBackgroundImage:green forControlState:BTRControlStateNormal]; 27 | [self.button setBackgroundImage:red forControlState:BTRControlStateHighlighted]; 28 | [self.button setBackgroundImage:purple forControlState:BTRControlStateHover]; 29 | [self.button setBackgroundImage:yellow forControlState:BTRControlStateSelected]; 30 | [self.button setBackgroundImage:blue forControlState:BTRControlStateSelected | BTRControlStateHover]; 31 | 32 | // fades the image back after clicking down 33 | self.button.animatesContents = YES; 34 | 35 | // you can either use the traditional target/action approach 36 | [self.button addTarget:self action:@selector(buttonClicked:) forControlEvents:BTRControlEventClick]; 37 | 38 | // or you can use fancy blocks. 39 | [self.button addBlock:^(BTRControlEvents events) { 40 | NSLog(@"repeated click"); 41 | } forControlEvents:BTRControlEventClickRepeat]; 42 | } 43 | 44 | - (void)buttonClicked:(BTRButton *)sender { 45 | // toggle the selected state of the button each click 46 | sender.selected = !sender.selected; 47 | } 48 | 49 | - (NSImage *)pixelImageWithColor:(NSColor *)color { 50 | return [NSImage imageWithSize:CGSizeMake(1, 1) flipped:NO drawingHandler:^BOOL(NSRect dstRect) { 51 | [color set]; 52 | NSRectFill(dstRect); 53 | return YES; 54 | }]; 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /Examples/BTRActivityIndicator/ActivityIndicator Demo/ActivityIndicator Demo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // ActivityIndicator Demo 4 | // 5 | // Created by Jonathan Willing on 12/26/12. 6 | // Copyright (c) 2012 Butter. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @implementation AppDelegate 12 | 13 | - (void)awakeFromNib { 14 | self.window.backgroundColor = [NSColor colorWithCalibratedWhite:0.9 alpha:1]; 15 | 16 | [self.defaultIndicator startAnimating]; 17 | 18 | // Customize the first custom indicator. 19 | self.customizedIndicatorOne.progressShapeColor = [NSColor colorWithCalibratedRed:0.251 green:0.000 blue:0.502 alpha:1.000]; 20 | self.customizedIndicatorOne.progressAnimationDuration = 1.5f; 21 | self.customizedIndicatorOne.progressShapeLength = 20.f; 22 | self.customizedIndicatorOne.progressShapeSpread = 8.f; 23 | self.customizedIndicatorOne.progressShapeCount = 20; 24 | self.customizedIndicatorOne.progressShapeThickness = 4.f; 25 | [self.customizedIndicatorOne startAnimating]; 26 | 27 | 28 | // Create a custom indicator shape layer for the second custom indicator. 29 | CALayer *customIndicatorLayer = [CALayer layer]; 30 | customIndicatorLayer.bounds = CGRectMake(0, 0, 6, 6); 31 | customIndicatorLayer.cornerRadius = CGRectGetWidth(customIndicatorLayer.bounds) / 2; 32 | customIndicatorLayer.backgroundColor = NSColor.grayColor.CGColor; 33 | 34 | // Add a layer shadow onto the progress indicator. 35 | self.customizedIndicatorTwo.layer.shadowColor = [NSColor colorWithCalibratedWhite:1.f alpha:0.5f].CGColor; 36 | self.customizedIndicatorTwo.layer.shadowRadius = 0.f; 37 | self.customizedIndicatorTwo.layer.shadowOpacity = 1.f; 38 | self.customizedIndicatorTwo.layer.shadowOffset = CGSizeMake(0, -1.f); 39 | 40 | // Now we actually set the customized shape layer as the progress shape layer, and start animating. 41 | self.customizedIndicatorTwo.progressShapeLayer = customIndicatorLayer; 42 | 43 | // Although we could have set the progress shape layer after beginning the animation, it 44 | // causes undesired artifacts as the animation must restart and the layer must be replicated. 45 | [self.customizedIndicatorTwo startAnimating]; 46 | } 47 | 48 | - (void)toggleAnimation:(id)sender { 49 | if (self.customizedIndicatorTwo.animating) { 50 | [self.customizedIndicatorTwo stopAnimating]; 51 | } else { 52 | [self.customizedIndicatorTwo startAnimating]; 53 | } 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /Butter/BTRClipView.h: -------------------------------------------------------------------------------- 1 | /* 2 | Created by Jonathan Willing on 8/28/13. 3 | Copyright (c) 2013, ButterKit. All rights reserved. 4 | Licensed under the MIT license 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 7 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation 8 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 9 | to permit persons to whom the Software is furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 14 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 15 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 16 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 17 | IN THE SOFTWARE. 18 | */ 19 | 20 | #import 21 | 22 | // A NSClipView subclass with a buttery -scrollToRect: animation. 23 | @interface BTRClipView : NSClipView 24 | 25 | // Calls -scrollRectToVisible:, optionally animated. 26 | // 27 | // If animated, the animation will be performed with an ease-out timing function. 28 | // Any calls to this method while an animation is still in flight will update the 29 | // current animation and adjust the deceleration as needed. 30 | // 31 | // Any input to the scroll view that would cause an adjustment to the bounds (such as 32 | // a trackpad scroll) will cancel any animations in progress. 33 | - (BOOL)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated; 34 | 35 | // Calls -scrollRectToVisible:animated: with an optional completion block. The scrolled 36 | // completion parameter is whether any scrolling was performed. 37 | - (BOOL)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated completion:(void (^)(BOOL scrolled))completion; 38 | 39 | // Any time the origin changes with an animation as discussed above, the deceleration 40 | // rate will be used to create an ease-out animation. 41 | // 42 | // Values should range from (0, 1]. Smaller deceleration rates will provide 43 | // generally fast animations, whereas larger rates will create lengthy animations. 44 | // 45 | // Defaults to 0.78. 46 | @property (nonatomic, assign) CGFloat decelerationRate; 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /Butter/NSView+BTRAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSView+BTRAdditions.m 3 | // Originally from Rebel 4 | // 5 | // Created by Justin Spahr-Summers on 2012-09-04. 6 | // Updated by Jonathan Willing 7 | // Copyright (c) 2012 GitHub. All rights reserved. 8 | // 9 | 10 | #import "NSView+BTRAdditions.h" 11 | #import "BTRClipView.h" 12 | #import 13 | 14 | @implementation NSView (BTRAnimationAdditions) 15 | 16 | #pragma mark Animations 17 | 18 | + (void)btr_animate:(void (^)(void))animations { 19 | [self btr_animate:animations completion:nil]; 20 | } 21 | 22 | + (void)btr_animate:(void (^)(void))animations completion:(void (^)(void))completion { 23 | [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) { 24 | NSAnimationContext.currentContext.allowsImplicitAnimation = YES; 25 | animations(); 26 | } completionHandler:completion]; 27 | } 28 | 29 | + (void)btr_animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(void))completion { 30 | [self btr_animate:^{ 31 | NSAnimationContext.currentContext.duration = duration; 32 | animations(); 33 | } completion:completion]; 34 | } 35 | 36 | + (void)btr_animateWithDuration:(NSTimeInterval)duration animationCurve:(BTRViewAnimationCurve)curve animations:(void (^)(void))animations completion:(void (^)(void))completion { 37 | [self btr_animateWithDuration:duration animations:^{ 38 | NSAnimationContext.currentContext.timingFunction = [self btr_timingFunctionWithCurve:curve]; 39 | animations(); 40 | } completion:completion]; 41 | } 42 | 43 | - (void)btr_scrollRectToVisible:(NSRect)rect animated:(BOOL)animated { 44 | NSClipView *clipView = [[self enclosingScrollView] contentView]; 45 | if (clipView == nil) { 46 | return; 47 | } 48 | 49 | if ([clipView isKindOfClass:BTRClipView.class]) { 50 | [(BTRClipView *)clipView scrollRectToVisible:rect animated:animated]; 51 | } else { 52 | if (animated) { 53 | [(NSClipView *)[clipView animator] scrollRectToVisible:rect]; 54 | } else { 55 | [clipView scrollRectToVisible:rect]; 56 | } 57 | } 58 | } 59 | 60 | #pragma mark Timing 61 | 62 | + (CAMediaTimingFunction *)btr_timingFunctionWithCurve:(BTRViewAnimationCurve)curve { 63 | switch (curve) { 64 | case BTRViewAnimationCurveEaseInOut: 65 | return [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 66 | break; 67 | case BTRViewAnimationCurveEaseIn: 68 | return [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; 69 | break; 70 | case BTRViewAnimationCurveEaseOut: 71 | return [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; 72 | break; 73 | case BTRViewAnimationCurveLinear: 74 | return [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; 75 | break; 76 | default: 77 | break; 78 | } 79 | 80 | return nil; 81 | } 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | **Copyright (c) 2012, Jonathan Willing & Indragie Karunaratne. All rights reserved.** 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | --- 10 | 11 | **This project uses portions of code from the Rebel framework. Rebel is copyright 2012 - 2013 GitHub, Inc.** 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | --- 20 | 21 | **This project uses portions of code from the TwUI framework. TwUI is copyright 2011 Twitter, Inc.** 22 | 23 | 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 24 | 25 | http://www.apache.org/licenses/LICENSE-2.0 26 | 27 | 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. -------------------------------------------------------------------------------- /Butter/BTRActivityIndicator.h: -------------------------------------------------------------------------------- 1 | // 2 | // BTRActivityIndicator.h 3 | // Butter 4 | // 5 | // Created by Jonathan Willing on 12/25/12. 6 | // Copyright (c) 2012 ButterKit. All rights reserved. 7 | // 8 | // Much thanks to David Rönnqvist (@davidronnqvist) for the original idea of using CAReplicatorLayer. 9 | 10 | #import "BTRView.h" 11 | 12 | typedef NS_ENUM(NSInteger, BTRActivityIndicatorStyle) { 13 | BTRActivityIndicatorStyleWhite, 14 | BTRActivityIndicatorStyleGray 15 | }; 16 | 17 | // An indeterminate activity indicator. 18 | @interface BTRActivityIndicator : BTRView 19 | 20 | // Returns an activity indicator sized to the default indicator size. 21 | - (instancetype)initWithActivityIndicatorStyle:(BTRActivityIndicatorStyle)style; 22 | 23 | // Initializes the activity indicator with the default indicator style (BTRActivityIndicatorStyleGray). 24 | - (instancetype)initWithFrame:(NSRect)frameRect; 25 | 26 | - (instancetype)initWithFrame:(NSRect)frameRect activityIndicatorStyle:(BTRActivityIndicatorStyle)style NS_DESIGNATED_INITIALIZER; 27 | 28 | // Starts and ends the animation of the activity indicator. 29 | - (void)startAnimating; 30 | - (void)stopAnimating; 31 | 32 | // Whether the activity indicator is currently animating. 33 | @property (nonatomic, assign, readonly) BOOL animating; 34 | 35 | // Change the style of the activity indicator. 36 | @property (nonatomic, assign) BTRActivityIndicatorStyle activityIndicatorStyle; 37 | 38 | // The fill color for the indicator. If the shape layer is replaced, 39 | // setting a shape color will have no effect. 40 | @property (nonatomic, strong) NSColor *progressShapeColor; 41 | 42 | // The number of shapes in the indicator. The spacing will be 43 | // automatically adjusted to evenly distribute all of the shapes. 44 | @property (nonatomic, assign) NSUInteger progressShapeCount; 45 | 46 | // The thickness of the shapes in the indicator. 47 | @property (nonatomic, assign) CGFloat progressShapeThickness; 48 | 49 | // The length of the shapes in the indicator. 50 | @property (nonatomic, assign) CGFloat progressShapeLength; 51 | 52 | // The spread of the shapes in the indicator. Smaller spreads may cause 53 | // unintentional overlap of the shapes due to close proximity. 54 | @property (nonatomic, assign) CGFloat progressShapeSpread; 55 | 56 | // The duration of one complete rotation of the activity indicator. 57 | // 58 | // Defaults to 1.0s. 59 | @property (nonatomic, assign) CGFloat progressAnimationDuration; 60 | 61 | // The "tooth" of the indicator. If the progress indicator needs to be modified, 62 | // a new layer can be set as the new progress shape layer. The layer will have 63 | // the correct transforms and replications automatically applied. 64 | // 65 | // Behavior for modifying the default layer is undefined. If smaller customizations 66 | // are needed, it is better to use the appearance properties defined above. 67 | @property (nonatomic, strong) CALayer *progressShapeLayer; 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /Butter/BTRView.m: -------------------------------------------------------------------------------- 1 | // 2 | // BTRView.m 3 | // Originally from Rebel 4 | // 5 | // Created by Justin Spahr-Summers on 2012-07-29. 6 | // Copyright (c) 2012 GitHub. All rights reserved. 7 | // 8 | 9 | #import "BTRView.h" 10 | #import 11 | 12 | @implementation BTRView { 13 | BOOL drawFlag; 14 | } 15 | @synthesize flipped = _flipped; 16 | 17 | #pragma mark Properties 18 | 19 | - (void)setFlipped:(BOOL)flipped { 20 | if (_flipped != flipped) { 21 | _flipped = flipped; 22 | self.needsLayout = YES; 23 | self.needsDisplay = YES; 24 | } 25 | } 26 | 27 | - (BOOL)isFlipped 28 | { 29 | return _flipped; 30 | } 31 | 32 | #pragma mark Lifecycle 33 | 34 | - (instancetype)initWithFrame:(NSRect)frame layerHosted:(BOOL)hostsLayer { 35 | self = [super initWithFrame:frame]; 36 | if (self == nil) return nil; 37 | 38 | if (hostsLayer) { 39 | self.layer = [CALayer layer]; 40 | self.layer.delegate = self; 41 | } 42 | 43 | BTRViewCommonInit(self); 44 | 45 | return self; 46 | } 47 | 48 | - (instancetype)initWithFrame:(NSRect)frame { 49 | return [self initWithFrame:frame layerHosted:NO]; 50 | } 51 | 52 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 53 | self = [super initWithCoder:aDecoder]; 54 | if (self == nil) return nil; 55 | 56 | BTRViewCommonInit(self); 57 | 58 | return self; 59 | } 60 | 61 | static void BTRViewCommonInit(BTRView *self) { 62 | self.wantsLayer = YES; 63 | self.layerContentsPlacement = NSViewLayerContentsPlacementScaleAxesIndependently; 64 | self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay; 65 | } 66 | 67 | #pragma mark NSObject 68 | 69 | - (NSString *)description { 70 | return [NSString stringWithFormat:@"<%@: %p>{ frame = %@, layer = <%@: %p> }", self.class, self, NSStringFromRect(self.frame), self.layer.class, self.layer]; 71 | } 72 | 73 | #pragma mark NSView 74 | 75 | - (NSColor *)btr_backgroundColor { 76 | return [NSColor colorWithCGColor:self.layer.backgroundColor]; 77 | } 78 | 79 | - (void)setBtr_backgroundColor:(NSColor *)color { 80 | self.layer.backgroundColor = color.CGColor; 81 | } 82 | 83 | - (CGFloat)cornerRadius { 84 | return self.layer.cornerRadius; 85 | } 86 | 87 | - (void)setCornerRadius:(CGFloat)radius { 88 | self.layer.cornerRadius = radius; 89 | } 90 | 91 | - (BOOL)masksToBounds { 92 | return self.layer.masksToBounds; 93 | } 94 | 95 | - (void)setMasksToBounds:(BOOL)masksToBounds { 96 | self.layer.masksToBounds = masksToBounds; 97 | } 98 | 99 | - (BOOL)isOpaque { 100 | return self.layer.opaque; 101 | } 102 | 103 | - (void)setOpaque:(BOOL)opaque { 104 | self.layer.opaque = opaque; 105 | } 106 | 107 | #pragma mark Drawing and actions 108 | 109 | - (void)displayAnimated { 110 | drawFlag = self.animatesContents; 111 | self.animatesContents = YES; 112 | [self display]; 113 | } 114 | 115 | - (void)setAnimatesContents:(BOOL)animate { 116 | drawFlag = animate; 117 | _animatesContents = animate; 118 | } 119 | 120 | - (id)actionForLayer:(CALayer *)layer forKey:(NSString *)event { 121 | if ([event isEqualToString:@"contents"]) { 122 | if (!self.animatesContents) { 123 | return (id)[NSNull null]; 124 | } 125 | self.animatesContents = drawFlag; 126 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"contents"]; 127 | return animation; 128 | } 129 | 130 | return [super actionForLayer:layer forKey:event]; 131 | } 132 | 133 | #pragma mark - View controller 134 | 135 | // From http://www.cocoawithlove.com/2008/07/better-integration-for-nsviewcontroller.html 136 | - (void)setViewController:(NSViewController *)newController { 137 | if (_viewController) { 138 | NSResponder *controllerNextResponder = _viewController.nextResponder; 139 | [super setNextResponder:controllerNextResponder]; 140 | _viewController.nextResponder = nil; 141 | } 142 | 143 | _viewController = newController; 144 | 145 | if (newController) { 146 | NSResponder *ownNextResponder = self.nextResponder; 147 | [super setNextResponder:_viewController]; 148 | if (ownNextResponder != _viewController) { 149 | _viewController.nextResponder = ownNextResponder; 150 | } 151 | } 152 | } 153 | 154 | - (void)setNextResponder:(NSResponder *)newNextResponder { 155 | if (_viewController) { 156 | _viewController.nextResponder = newNextResponder; 157 | return; 158 | } 159 | [super setNextResponder:newNextResponder]; 160 | } 161 | 162 | #pragma mark Drawing block 163 | 164 | //- (void)drawRect:(NSRect)dirtyRect { 165 | // [super drawRect:dirtyRect]; 166 | // 167 | // if (self.drawRectBlock != nil) { 168 | // NSLog(@"%s",__PRETTY_FUNCTION__); 169 | // CGContextRef ctx = [[NSGraphicsContext currentContext] graphicsPort]; 170 | // self.drawRectBlock(self, ctx); 171 | // } 172 | //} 173 | 174 | @end 175 | -------------------------------------------------------------------------------- /Butter/BTRButton.m: -------------------------------------------------------------------------------- 1 | // 2 | // BTRButton.m 3 | // Butter 4 | // 5 | // Created by Jonathan Willing on 12/21/12. 6 | // Copyright (c) 2012 ButterKit. All rights reserved. 7 | // 8 | 9 | #import "BTRButton.h" 10 | #import "BTRLabel.h" 11 | 12 | // Subclasses to override -hitTest: and prevent them from receiving mouse events 13 | @interface BTRButtonLabel : BTRLabel 14 | @end 15 | 16 | @interface BTRButtonImageView : BTRImageView 17 | @end 18 | 19 | @implementation BTRButton { 20 | BTRButtonImageView *_imageView; 21 | } 22 | 23 | #pragma mark - Initialization 24 | 25 | static void BTRButtonCommonInit(BTRButton *self) { 26 | self->_backgroundImageView = [[BTRButtonImageView alloc] initWithFrame:self.bounds]; 27 | [self addSubview:self->_backgroundImageView]; 28 | self->_titleLabel = [[BTRButtonLabel alloc] initWithFrame:self.bounds]; 29 | [self addSubview:self->_titleLabel]; 30 | 31 | [self accessibilitySetOverrideValue:NSAccessibilityButtonRole forAttribute:NSAccessibilityRoleAttribute]; 32 | [self accessibilitySetOverrideValue:NSAccessibilityRoleDescription(NSAccessibilityButtonRole, nil) forAttribute:NSAccessibilityRoleDescriptionAttribute]; 33 | } 34 | 35 | - (instancetype)initWithFrame:(NSRect)frameRect { 36 | self = [super initWithFrame:frameRect]; 37 | if (self == nil) return nil; 38 | BTRButtonCommonInit(self); 39 | return self; 40 | } 41 | 42 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 43 | self = [super initWithCoder:aDecoder]; 44 | if (self == nil) return nil; 45 | BTRButtonCommonInit(self); 46 | return self; 47 | } 48 | 49 | #pragma mark - Accessibility 50 | 51 | - (NSArray *)accessibilityActionNames { 52 | return @[NSAccessibilityPressAction]; 53 | } 54 | 55 | - (NSString *)accessibilityActionDescription:(NSString *)action { 56 | return NSAccessibilityActionDescription(action); 57 | } 58 | 59 | - (void)accessibilityPerformAction:(NSString *)action { 60 | if ([action isEqualToString:NSAccessibilityPressAction]) { 61 | [self performClick:nil]; 62 | } 63 | } 64 | 65 | #pragma mark - Accessors 66 | 67 | - (BTRButtonImageView *)imageView { 68 | if (!_imageView) { 69 | _imageView = [[BTRButtonImageView alloc] initWithFrame:self.bounds]; 70 | _imageView.contentMode = BTRViewContentModeCenter; 71 | [self addSubview:_imageView]; 72 | } 73 | return _imageView; 74 | } 75 | 76 | #pragma mark - State 77 | 78 | - (void)handleStateChange { 79 | self.backgroundImageView.image = self.currentBackgroundImage; 80 | if (self.currentImage) { 81 | self.imageView.image = self.currentImage; 82 | } 83 | self.titleLabel.attributedStringValue = self.currentAttributedTitle; 84 | } 85 | 86 | #pragma mark - Drawing 87 | 88 | - (void)layout { 89 | self.backgroundImageView.frame = [self backgroundImageFrame]; 90 | self.titleLabel.frame = [self labelFrame]; 91 | if (_imageView) { 92 | self.imageView.frame = [self imageFrame]; 93 | } 94 | [super layout]; 95 | } 96 | 97 | - (void)setBackgroundContentMode:(BTRViewContentMode)backgroundContentMode { 98 | self.backgroundImageView.contentMode = backgroundContentMode; 99 | } 100 | 101 | - (BTRViewContentMode)contentMode { 102 | return self.backgroundImageView.contentMode; 103 | } 104 | 105 | - (void)setImageContentMode:(BTRViewContentMode)imageContentMode { 106 | self.imageView.contentMode = imageContentMode; 107 | } 108 | 109 | - (BTRViewContentMode)imageContentMode { 110 | return self.imageView.contentMode; 111 | } 112 | 113 | // When a button is clicked, the initial state change shouldn't animate 114 | // or it will appear to be laggy. However, if the user has opted to animate 115 | // the contents, we animate the transition back out. 116 | - (void)setHighlighted:(BOOL)highlighted { 117 | BOOL animatesFlag = self.animatesContents; 118 | BOOL shouldAnimate = (!highlighted && animatesFlag); 119 | self.imageView.animatesContents = shouldAnimate; 120 | self.backgroundImageView.animatesContents = shouldAnimate; 121 | [super setHighlighted:highlighted]; 122 | self.imageView.animatesContents = animatesFlag; 123 | self.backgroundImageView.animatesContents = animatesFlag; 124 | } 125 | 126 | - (void)setCornerRadius:(CGFloat)cornerRadius { 127 | [super setCornerRadius:cornerRadius]; 128 | self.backgroundImageView.cornerRadius = cornerRadius; 129 | } 130 | 131 | - (CGFloat)cornerRadius { 132 | return self.backgroundImageView.cornerRadius; 133 | } 134 | 135 | #pragma mark - Mouse Events 136 | 137 | - (void)mouseDragged:(NSEvent *)theEvent { 138 | // Override to prevent superviews from receiving mouse dragged events 139 | // when the button is dragged. 140 | } 141 | 142 | #pragma mark - Subclassing Hooks 143 | 144 | - (CGRect)imageFrame { 145 | return self.bounds; 146 | } 147 | 148 | - (CGRect)backgroundImageFrame { 149 | return self.bounds; 150 | } 151 | 152 | - (CGRect)labelFrame { 153 | return self.bounds; 154 | } 155 | 156 | @end 157 | 158 | @implementation BTRButtonLabel 159 | - (NSView *)hitTest:(NSPoint)aPoint { return nil; } 160 | @end 161 | 162 | @implementation BTRButtonImageView 163 | - (NSView *)hitTest:(NSPoint)aPoint { return nil; } 164 | @end 165 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Butter # 2 | 3 | Butter is a framework for OS X that seeks to provide a set of commonly used controls which are full replacements for their cell-based AppKit counterparts. This framework is still a work in progress, but it is **usable in production apps.** 4 | 5 | This framework seeks to provide the following: 6 | 7 | - Image-based customization of controls for various states 8 | - Block-based action handlers 9 | - Complete independence of cell-based controls 10 | - Customizable properties that would otherwise be hard to change 11 | 12 | **Butter is compatible with OS X 10.8+.** 13 | 14 | 15 | # Controls # 16 | 17 | ## BTRControl ## 18 | `BTRControl` is a subclass of `BTRView` that provides a base for all controls. It offers state-based customization with block-based (or alternatively target/action-based) control event handling. `BTRControl` is designed for subclassing. 19 | 20 | ## BTRButton ## 21 | `BTRButton` is a subclass of `BTRControl`, and is an extremely customizable. Here's an example: 22 | 23 | ```objc 24 | BTRButton *button = [[BTRButton alloc] initWithFrame:rect]; 25 | [button setTitle:@"Hey!" forControlState:BTRControlStateNormal]; 26 | [button setBackgroundImage:image1 forControlState:BTRControlStateNormal]; 27 | [button setBackgroundImage:image2 forControlState:BTRControlStateHighlighted]; 28 | [button addBlock:^{ NSLog(@"hi!"); } forControlEvents:BTRControlEventClick]; 29 | button.animatesContents = YES; // animate the transition back from click 30 | ``` 31 | 32 | ## BTRActivityIndicator ## 33 | `BTRActvityIndicator` is a subclass of `BTRView` that provides a comprehensive API for creating any type of circular indeterminate activity indicator. Nearly all features of the indicator can be modified, and if more customization is desired a custom layer can be set to completely modify the appearance of the spinner. Short example: 34 | 35 | ```objc 36 | BTRActivityIndicator *indicator = [[BTRActivityIndicator alloc] initWithFrame:rect]; 37 | indicator.progressShapeColor = newColor; 38 | indicator.progressAnimationDuration = 4.f; // make it slow 39 | indicator.progressShapeCount = 20; // give it more gears 40 | [indicator startAnimating]; 41 | ``` 42 | 43 | ## BTRImageView ## 44 | `BTRImageView` is a subclass of `BTRView`, and it provides a fast and lightweight alternative to `NSImageView`. The view is layer-hosted, meaning the sublayer that contains the image itself can safely have a transform applied. This opens up many possibilities for complex animations. `BTRImageView` can also handle animated images, such as GIFs. 45 | 46 | ```objc 47 | BTRImageView *imageView = [[BTRImageView alloc] initWithImage:someGIF]; 48 | imageView.contentMode = BTRViewContentModeScaleAspectFit; 49 | imageView.transform = some3DTransform; 50 | imageView.animatesMultipleFrames = YES; // animate the GIF 51 | ``` 52 | 53 | `BTRImageView` is also capable of displaying stretchable images when combined with `BTRImage`. 54 | 55 | ## BTRImage ## 56 | `BTRImage` is a `NSImage` subclass that provides support for stretchable images. 57 | 58 | ```objc 59 | NSEdgeInsets insets = NSEdgeInsetsMake(0, 5, 0, 5); 60 | BTRImage *image = [BTRImage resizableImageNamed:@"epic" withCapInsets:insets]; 61 | self.imageView.image = image; // BTRImageView only 62 | ``` 63 | Note that `BTRImage` will not attempt to use the stretched images when manually drawing, or for any other purpose than setting it as the image of a `BTRImageView`. 64 | 65 | There is also a convenience category for creating `BTRImage`s out of `NSImage`s, located in `NSImage+BTRImageAdditions.h`. 66 | 67 | ## BTRTextField ## 68 | `BTRTextField` is a subclass of `NSTextField`. It takes all the pain out of customizing normal text fields. Background images for states, text shadow, placeholder text customization, custom text drawing frames, control event handlers, and more. 69 | 70 | ```objc 71 | BTRTextField *textField = [[BTRTextField alloc] initWithFrame:rect]; 72 | [textField setBackgroundImage:image forControlState:BTRControlStateNormal]; 73 | textField.textShadow = someNSShadow; 74 | ``` 75 | 76 | ## BTRSecureTextField ## 77 | The secure variant of `BTRTextField`. 78 | 79 | ## BTRLabel ## 80 | `BTRLabel` is a subclass of `BTRTextField` that provides a common setup for labels, with no bezel, background drawing, editing, or selection. 81 | 82 | ```objc 83 | BTRLabel *label = [[BTRLabel alloc] initWithFrame:rect]; 84 | ``` 85 | 86 | ## NSView Additions ## 87 | This category contains some convenience animation additions for `NSView`. 88 | 89 | ```objc 90 | NSView/BTRView *view = someView; 91 | [view btr_animate:^{ // simplified 92 | view.frame = newFrame; 93 | }]; 94 | 95 | [view btr_animateWithDuration:2 96 | animationCurve:BTRViewAnimationCurveEaseInOut 97 | animations:^{ 98 | view.frame = newFrame; 99 | } completion:nil]; 100 | ``` 101 | 102 | ## BTRView ## 103 | `BTRView` is a subclass of `NSView`, and it provides the base for many of the controls in Butter. It is layer-backed by default. It provides some convenience properties for common customization points. 104 | 105 | ```objc 106 | BTRView *view = [[BTRView alloc] initWithFrame:rect]; 107 | view.backgroundColor = [NSColor redColor]; 108 | view.flipped = YES; 109 | view.animatesContents = YES; // fades between redraws 110 | view.viewController = someVC; // patch into the responder chain 111 | ``` 112 | 113 | ## BTRClipView / BTRScrollView ## 114 | `BTRClipView` implements a completely custom scrolling mechanism that is used for buttery-smooth scrolling in response to keyboard events, and calls to a custom `-scrollRectToVisible:animated:` method. 115 | 116 | `BTRScrollView` makes it easy to use `BTRClipView` by swapping out the clip view at runtime. 117 | 118 | 119 | ## BTRPopupButton ## 120 | `BTRPopUpButton` is the layer-backed Butter equivalent of `NSPopUpButton`. Like `NSPopUpButton`, it uses an `NSMenu` as the model for its content. Basic elements like the arrow image are customizable via properties, and many of the layout attributes are designed to be customizable via subclassing. 121 | 122 | 123 | More controls will be added in due time if seen fit. 124 | 125 | License 126 | --- 127 | Butter is licensed under the MIT License. See the [License](https://github.com/ButterKit/Butter/blob/master/LICENSE.md). -------------------------------------------------------------------------------- /Butter/BTRControl.h: -------------------------------------------------------------------------------- 1 | // 2 | // BTRControl.h 3 | // Butter 4 | // 5 | // Created by Jonathan Willing on 12/14/12. 6 | // Copyright (c) 2012 ButterKit. All rights reserved. 7 | 8 | // This class is heavily inspired by UIKit and TwUI. 9 | #import "BTRView.h" 10 | 11 | typedef NS_OPTIONS(NSUInteger, BTRControlEvents) { 12 | // TODO: UNIMPLEMENTED 13 | // *************** 14 | BTRControlEventMouseDragEnter = 1 << 1, 15 | BTRControlEventMouseDragExit = 1 << 2, 16 | // *************** 17 | 18 | BTRControlEventMouseUpInside = 1 << 3, 19 | BTRControlEventMouseDownInside = 1 << 4, 20 | BTRControlEventMouseUpOutside = 1 << 5, 21 | BTRControlEventMouseEntered = 1 << 6, 22 | BTRControlEventMouseExited = 1 << 7, 23 | 24 | BTRControlEventClick = 1 << 12, //after mouse down & up inside 25 | BTRControlEventClickRepeat = 1 << 13, 26 | BTRControlEventLeftClick = 1 << 14, 27 | BTRControlEventRightClick = 1 << 15, 28 | 29 | BTRControlEventValueChanged = 1 << 16, // sliders, etc. 30 | }; 31 | 32 | typedef NS_OPTIONS(NSUInteger, BTRControlState) { 33 | BTRControlStateNormal = 0, 34 | BTRControlStateHighlighted = 1 << 0, 35 | BTRControlStateDisabled = 1 << 1, 36 | BTRControlStateSelected = 1 << 2, 37 | BTRControlStateHover = 1 << 3 38 | }; 39 | 40 | // State key constants for use with `-currentValueForControlStateKey:` 41 | extern NSString * const BTRControlStateTitleKey; 42 | extern NSString * const BTRControlStateTitleColorKey; 43 | extern NSString * const BTRControlStateTitleShadowKey; 44 | extern NSString * const BTRControlStateTitleFontKey; 45 | extern NSString * const BTRControlStateAttributedTitleKey; 46 | extern NSString * const BTRControlStateImageKey; 47 | extern NSString * const BTRControlStateBackgroundImageKey; 48 | 49 | @class BTRControlContent; 50 | @interface BTRControl : BTRView 51 | 52 | - (void)addBlock:(void (^)(BTRControlEvents events))block forControlEvents:(BTRControlEvents)events; 53 | - (void)addTarget:(id)target action:(SEL)action forControlEvents:(BTRControlEvents)events; 54 | 55 | @property (nonatomic, readonly) NSInteger clickCount; 56 | 57 | @property (nonatomic, readonly) BTRControlState state; 58 | @property (nonatomic, getter = isEnabled) BOOL enabled; 59 | @property (nonatomic, getter = isSelected) BOOL selected; 60 | @property (nonatomic, getter = isHighlighted) BOOL highlighted; 61 | 62 | @property (nonatomic, getter = isUserInteractionEnabled) BOOL userInteractionEnabled; 63 | 64 | // Implemented by subclasses. Useful for reacting to state changes caused either by 65 | // mouse events, or by changing the state properties above. 66 | - (void)handleStateChange; 67 | 68 | // This method should be called by subclasses 69 | - (void)sendActionsForControlEvents:(BTRControlEvents)events; 70 | 71 | // Sends actions for the `BTRControlClick` event, provided that `enabled` and 72 | // `userInteractionEnabled` are equal to `YES`. 73 | - (IBAction)performClick:(id)sender; 74 | 75 | // This is the dynamic version of the `current*` property getters. 76 | // 77 | // Unless explicitly defined in your own subclasses, state keys passed into this method 78 | // should be limited to those defined in the `BTRControlState*Key` constants. 79 | // 80 | // Returns the current value for the given control state key. 81 | - (id)currentValueForControlStateKey:(NSString *)key; 82 | 83 | // Implemented by subclasses. Use it to return a subclass of BTRControlContent that 84 | // contains additional content properties pertaining to the specific control. 85 | + (Class)controlContentClass; 86 | 87 | // Returns the content (BTRControlContent or a subclass, if one was 88 | // returned from +controlContentClass) for the given control state. 89 | // A new content object will be created if one does not exist 90 | - (BTRControlContent *)contentForControlState:(BTRControlState)state; 91 | 92 | // General properties for controls 93 | // Your control subclass can add more methods and properties similar to this 94 | @property (nonatomic, strong, readonly) NSString *currentTitle; 95 | @property (nonatomic, strong, readonly) NSAttributedString *currentAttributedTitle; 96 | @property (nonatomic, strong, readonly) NSImage *currentImage; 97 | @property (nonatomic, strong, readonly) NSImage *currentBackgroundImage; 98 | @property (nonatomic, strong, readonly) NSColor *currentTitleColor; 99 | @property (nonatomic, strong, readonly) NSShadow *currentTitleShadow; 100 | @property (nonatomic, strong, readonly) NSFont *currentTitleFont; 101 | 102 | - (NSImage *)backgroundImageForControlState:(BTRControlState)state; 103 | - (void)setBackgroundImage:(NSImage *)image forControlState:(BTRControlState)state; 104 | 105 | - (NSImage *)imageForControlState:(BTRControlState)state; 106 | - (void)setImage:(NSImage *)image forControlState:(BTRControlState)state; 107 | 108 | - (NSString *)titleForControlState:(BTRControlState)state; 109 | - (void)setTitle:(NSString *)title forControlState:(BTRControlState)state; 110 | 111 | - (NSAttributedString *)attributedTitleForControlState:(BTRControlState)state; 112 | - (void)setAttributedTitle:(NSAttributedString *)title forControlState:(BTRControlState)state; 113 | 114 | - (NSColor *)titleColorForControlState:(BTRControlState)state; 115 | - (void)setTitleColor:(NSColor *)color forControlState:(BTRControlState)state; 116 | 117 | - (NSShadow *)titleShadowForControlState:(BTRControlState)state; 118 | - (void)setTitleShadow:(NSShadow *)shadow forControlState:(BTRControlState)state; 119 | 120 | - (NSFont *)titleFontForControlState:(BTRControlState)state; 121 | - (void)setTitleFont:(NSFont *)font forControlState:(BTRControlState)state; 122 | 123 | @end 124 | 125 | @interface BTRControlContent : NSObject 126 | @property (nonatomic, copy) NSString *title; 127 | @property (nonatomic, copy) NSAttributedString *attributedTitle; 128 | @property (nonatomic, strong) NSColor *titleColor; 129 | @property (nonatomic, strong) NSShadow *titleShadow; 130 | @property (nonatomic, strong) NSFont *titleFont; 131 | @property (nonatomic, strong) NSImage *image; 132 | @property (nonatomic, strong) NSImage *backgroundImage; 133 | // Any setter on a BTRControlContent subclass should always call the 134 | // -controlContentChanged method in order to notify the control of the 135 | // change. TODO: See if there is a way to monitor all properties for 136 | // change so that each setter individually doesn't need to call the method 137 | - (void)controlContentChanged; 138 | 139 | // Subclasses can use this to return text attributes that the 140 | // attributedTitle should use by default 141 | + (NSDictionary *)defaultTitleAttributes; 142 | 143 | @end 144 | -------------------------------------------------------------------------------- /Butter/BTRImageView.m: -------------------------------------------------------------------------------- 1 | // 2 | // BTRImageView.m 3 | // Butter 4 | // 5 | // Created by Jonathan Willing on 12/12/12. 6 | // Copyright (c) 2012 ButterKit. All rights reserved. 7 | // 8 | 9 | #import "BTRImageView.h" 10 | #import "BTRGeometryAdditions.h" 11 | #import "BTRImage.h" 12 | 13 | @interface BTRImageView() 14 | @property (nonatomic, strong, readwrite) CALayer *imageLayer; 15 | @end 16 | 17 | @implementation BTRImageView { 18 | NSUInteger _currentImageFrame; 19 | NSUInteger _totalImageFrames; 20 | NSInteger _animationLoopCount; 21 | NSInteger _currentLoopCount; 22 | NSTimer *_animationTimer; 23 | } 24 | 25 | - (instancetype)initWithFrame:(NSRect)frame { 26 | self = [super initWithFrame:frame layerHosted:YES]; 27 | if (self == nil) return nil; 28 | BTRImageViewCommonInit(self); 29 | return self; 30 | } 31 | 32 | - (instancetype)initWithImage:(NSImage *)image { 33 | self = [self initWithFrame:(CGRect){ .size = image.size }]; 34 | self.image = image; 35 | return self; 36 | } 37 | 38 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 39 | self = [super initWithCoder:aDecoder]; 40 | if (self == nil) return nil; 41 | self.layer = [CALayer layer]; 42 | self.wantsLayer = YES; 43 | BTRImageViewCommonInit(self); 44 | return self; 45 | } 46 | 47 | static void BTRImageViewCommonInit(BTRImageView *self) { 48 | self.imageLayer = [CALayer layer]; 49 | self.imageLayer.delegate = self; 50 | self.imageLayer.masksToBounds = YES; 51 | [self.layer addSublayer:self.imageLayer]; 52 | 53 | self.contentMode = BTRViewContentModeScaleToFill; 54 | self.imageLayer.anchorPoint = CGPointMake(0.5f, 0.5f); 55 | 56 | [self accessibilitySetOverrideValue:NSAccessibilityImageRole forAttribute:NSAccessibilityRoleAttribute]; 57 | [self accessibilitySetOverrideValue:NSAccessibilityRoleDescription(NSAccessibilityImageRole, nil) forAttribute:NSAccessibilityRoleDescriptionAttribute]; 58 | } 59 | 60 | - (void)layout { 61 | [super layout]; 62 | 63 | self.imageLayer.bounds = self.bounds; 64 | self.imageLayer.position = CGPointMake(NSMidX(self.bounds), NSMidY(self.bounds)); 65 | } 66 | 67 | - (void)setImage:(NSImage *)image { 68 | if (_image == image) 69 | return; 70 | [_animationTimer invalidate]; 71 | _animationTimer = nil; 72 | _image = image; 73 | self.imageLayer.contents = image; 74 | 75 | if ([image isKindOfClass:BTRImage.class]) { 76 | NSSize imageSize = image.size; 77 | NSEdgeInsets insets = ((BTRImage *)image).btr_capInsets; 78 | self.imageLayer.contentsCenter = BTRCAContentsCenterForInsets(insets, imageSize); 79 | } else { 80 | self.imageLayer.contentsCenter = CGRectMake(0.0, 0.0, 1.0, 1.0); 81 | } 82 | 83 | NSArray *representations = [image representations]; 84 | if (representations.count && self.animatesMultipleFrames) { 85 | NSBitmapImageRep *rep = representations[0]; 86 | if ([rep isKindOfClass:[NSBitmapImageRep class]]) { 87 | _totalImageFrames = [[rep valueForProperty:NSImageFrameCount] unsignedIntegerValue]; 88 | _currentImageFrame = [[rep valueForProperty:NSImageCurrentFrame] unsignedIntegerValue]; 89 | _animationLoopCount = [[rep valueForProperty:NSImageLoopCount] unsignedIntegerValue]; 90 | _currentLoopCount = 0; 91 | if (_totalImageFrames > 1) [self imageAnimationTimerFired:nil]; 92 | } 93 | } 94 | } 95 | 96 | - (void)imageAnimationTimerFired:(NSTimer *)timer { 97 | if (timer) _currentImageFrame++; 98 | if (_currentImageFrame > _totalImageFrames - 1) { 99 | _currentImageFrame = 0; 100 | _currentLoopCount++; 101 | if (_animationLoopCount != 0 && _currentLoopCount > _animationLoopCount) return; 102 | } 103 | NSBitmapImageRep *rep = self.image.representations[0]; 104 | [rep setProperty:NSImageCurrentFrame withValue:@(_currentImageFrame)]; 105 | if (!NSEqualRects(self.visibleRect, NSZeroRect)) { 106 | NSImage *currentFrameImage = [NSImage new]; 107 | [currentFrameImage addRepresentation:rep]; 108 | self.imageLayer.contents = currentFrameImage; 109 | } 110 | _animationTimer = [NSTimer scheduledTimerWithTimeInterval:[[rep valueForProperty:NSImageCurrentFrameDuration] doubleValue] target:self selector:@selector(imageAnimationTimerFired:) userInfo:nil repeats:NO]; 111 | } 112 | 113 | - (void)viewDidChangeBackingProperties { 114 | self.layer.contentsScale = self.window.backingScaleFactor; 115 | self.imageLayer.contentsScale = self.layer.contentsScale; 116 | } 117 | 118 | #pragma mark Layer properties 119 | 120 | - (void)setCornerRadius:(CGFloat)cornerRadius { 121 | self.imageLayer.cornerRadius = cornerRadius; 122 | } 123 | 124 | - (CGFloat)cornerRadius { 125 | return self.imageLayer.cornerRadius; 126 | } 127 | 128 | - (void)setTransform:(CATransform3D)transform { 129 | self.imageLayer.transform = transform; 130 | } 131 | 132 | - (CATransform3D)transform { 133 | return self.imageLayer.transform; 134 | } 135 | 136 | - (void)addAnimation:(CAAnimation *)animation forKey:(NSString *)key { 137 | [self.imageLayer addAnimation:animation forKey:key]; 138 | } 139 | 140 | #pragma mark Content mode 141 | 142 | - (void)setContentMode:(BTRViewContentMode)contentMode { 143 | _contentMode = contentMode; 144 | self.imageLayer.contentsGravity = [self contentsGravityFromContentMode:contentMode]; 145 | } 146 | 147 | - (NSString *)contentsGravityFromContentMode:(BTRViewContentMode)contentMode { 148 | switch (contentMode) { 149 | case BTRViewContentModeScaleToFill: 150 | return kCAGravityResize; 151 | break; 152 | case BTRViewContentModeScaleAspectFit: 153 | return kCAGravityResizeAspect; 154 | break; 155 | case BTRViewContentModeScaleAspectFill: 156 | return kCAGravityResizeAspectFill; 157 | break; 158 | case BTRViewContentModeCenter: 159 | return kCAGravityCenter; 160 | break; 161 | case BTRViewContentModeTop: 162 | return kCAGravityTop; 163 | break; 164 | case BTRViewContentModeBottom: 165 | return kCAGravityBottom; 166 | break; 167 | case BTRViewContentModeLeft: 168 | return kCAGravityLeft; 169 | break; 170 | case BTRViewContentModeRight: 171 | return kCAGravityRight; 172 | break; 173 | case BTRViewContentModeTopLeft: 174 | return kCAGravityTopLeft; 175 | break; 176 | case BTRViewContentModeTopRight: 177 | return kCAGravityTopRight; 178 | break; 179 | case BTRViewContentModeBottomLeft: 180 | return kCAGravityBottomLeft; 181 | break; 182 | case BTRViewContentModeBottomRight: 183 | return kCAGravityBottomRight; 184 | break; 185 | default: 186 | break; 187 | } 188 | } 189 | 190 | #pragma mark Accessibility 191 | 192 | - (BOOL)accessibilityIsIgnored { 193 | return NO; 194 | } 195 | 196 | @end 197 | -------------------------------------------------------------------------------- /Butter/BTRActivityIndicator.m: -------------------------------------------------------------------------------- 1 | // 2 | // BTRActivityIndicator.m 3 | // Butter 4 | // 5 | // Created by Jonathan Willing on 12/25/12. 6 | // Copyright (c) 2012 ButterKit. All rights reserved. 7 | // 8 | // Much thanks to David Rönnqvist (@davidronnqvist) for the original idea of using CAReplicatorLayer. 9 | 10 | #import "BTRActivityIndicator.h" 11 | #import 12 | 13 | @interface BTRActivityIndicator() 14 | @property (nonatomic, strong) CAReplicatorLayer *replicatorLayer; 15 | @property (nonatomic, readonly) CABasicAnimation *progressShapeLayerFadeOutAnimation; 16 | @property (nonatomic, assign, readwrite) BOOL animating; 17 | @end 18 | 19 | static const CGFloat BTRActivityIndicatorDefaultFrameLength = 24.f; 20 | static const CGFloat BTRActivityIndicatorFadeInOutDuration = 0.2f; 21 | static NSString * const BTRActivityIndicatorAnimationKey = @"BTRActivityIndicatorFadeOut"; 22 | 23 | @implementation BTRActivityIndicator 24 | @synthesize progressShapeLayer = _progressShapeLayer; 25 | 26 | //- (instancetype)initWithFrame:(NSRect)frame layerHosted:(BOOL)hostsLayer { 27 | // return [super initWithFrame:frame layerHosted:hostsLayer]; 28 | //} 29 | 30 | - (instancetype)initWithFrame:(NSRect)frame { 31 | return [self initWithFrame:frame activityIndicatorStyle:BTRActivityIndicatorStyleGray]; 32 | } 33 | 34 | - (instancetype)initWithActivityIndicatorStyle:(BTRActivityIndicatorStyle)style { 35 | CGFloat length = BTRActivityIndicatorDefaultFrameLength; 36 | return [self initWithFrame:CGRectMake(0, 0, length, length) activityIndicatorStyle:style]; 37 | } 38 | 39 | - (instancetype)initWithFrame:(NSRect)frame activityIndicatorStyle:(BTRActivityIndicatorStyle)style { 40 | self = [super initWithFrame:frame layerHosted:YES]; 41 | if (self == nil) return nil; 42 | 43 | _activityIndicatorStyle = style; 44 | _progressShapeColor = (style == BTRActivityIndicatorStyleGray ? [NSColor grayColor] : [NSColor whiteColor]); 45 | _progressShapeCount = 12; 46 | 47 | CGFloat minLength = fminf(CGRectGetWidth(frame), CGRectGetHeight(frame)); 48 | _progressShapeLength = ceilf(minLength / 4); 49 | _progressShapeThickness = ceilf(minLength / _progressShapeCount); 50 | _progressShapeSpread = _progressShapeLength; 51 | _progressAnimationDuration = 1.f; 52 | 53 | [self.layer addSublayer:self.replicatorLayer]; 54 | self.progressShapeLayer.opacity = 0.f; 55 | 56 | [self accessibilitySetOverrideValue:NSAccessibilityProgressIndicatorRole forAttribute:NSAccessibilityRoleAttribute]; 57 | [self accessibilitySetOverrideValue:NSAccessibilityRoleDescription(NSAccessibilityProgressIndicatorRole, nil) forAttribute:NSAccessibilityRoleDescriptionAttribute]; 58 | 59 | return self; 60 | } 61 | 62 | - (void)setActivityIndicatorStyle:(BTRActivityIndicatorStyle)style { 63 | self.progressShapeColor = (style == BTRActivityIndicatorStyleGray ? [NSColor grayColor] : [NSColor whiteColor]); 64 | } 65 | 66 | - (void)startAnimating { 67 | self.layer.opacity = 1.f; 68 | self.progressShapeLayer.opacity = 0.f; 69 | [self.progressShapeLayer addAnimation:self.progressShapeLayerFadeOutAnimation forKey:BTRActivityIndicatorAnimationKey]; 70 | self.animating = YES; 71 | } 72 | 73 | - (void)stopAnimating { 74 | [CATransaction begin]; 75 | [CATransaction setCompletionBlock:^{ 76 | [self.progressShapeLayer removeAnimationForKey:BTRActivityIndicatorAnimationKey]; 77 | }]; 78 | CABasicAnimation *fadeOut = [self animationFromOpacity:1 toOpacity:0 withDuration:BTRActivityIndicatorFadeInOutDuration]; 79 | self.layer.opacity = 0.f; 80 | [self.layer addAnimation:fadeOut forKey:nil]; 81 | self.animating = NO; 82 | [CATransaction commit]; 83 | } 84 | 85 | 86 | #pragma mark Animation 87 | 88 | - (CABasicAnimation *)animationFromOpacity:(CGFloat)fromVal toOpacity:(CGFloat)toVal withDuration:(CGFloat)duration { 89 | CABasicAnimation *fadeOut = [CABasicAnimation animationWithKeyPath:@"opacity"]; 90 | fadeOut.fromValue = @(fromVal); 91 | fadeOut.toValue = @(toVal); 92 | fadeOut.duration = duration; 93 | return fadeOut; 94 | } 95 | 96 | - (CABasicAnimation *)progressShapeLayerFadeOutAnimation { 97 | CABasicAnimation *fadeOut = [self animationFromOpacity:1 toOpacity:0 withDuration:self.progressAnimationDuration]; 98 | fadeOut.repeatCount = HUGE_VALF; 99 | return fadeOut; 100 | } 101 | 102 | 103 | #pragma mark Layers 104 | 105 | - (CALayer *)progressShapeLayer { 106 | if (_progressShapeLayer == nil) { 107 | _progressShapeLayer = [CALayer layer]; 108 | _progressShapeLayer.bounds = CGRectMake(0, 0, self.progressShapeThickness, self.progressShapeLength); 109 | _progressShapeLayer.anchorPoint = CGPointMake(0.5f, 0.5f); 110 | _progressShapeLayer.position = self.progressShapeLayerPosition; 111 | _progressShapeLayer.backgroundColor = self.progressShapeColor.CGColor; 112 | _progressShapeLayer.cornerRadius = self.progressShapeThickness * 0.5f; 113 | } 114 | return _progressShapeLayer; 115 | } 116 | 117 | - (CAReplicatorLayer *)replicatorLayer { 118 | if (_replicatorLayer == nil) { 119 | _replicatorLayer = [CAReplicatorLayer layer]; 120 | _replicatorLayer.anchorPoint = CGPointMake(0.5f, 0.5f); 121 | _replicatorLayer.position = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); 122 | 123 | [_replicatorLayer addSublayer:self.progressShapeLayer]; 124 | 125 | [self updateReplicatorSettings]; 126 | } 127 | return _replicatorLayer; 128 | } 129 | 130 | - (void)updateReplicatorSettings { 131 | self.replicatorLayer.instanceDelay = self.progressAnimationDuration / self.progressShapeCount; 132 | CGFloat angle = (2.f * M_PI) / self.progressShapeCount; 133 | CATransform3D rotation = CATransform3DMakeRotation(angle, 0.f, 0.f, -1.f); 134 | _replicatorLayer.instanceTransform = rotation; 135 | _replicatorLayer.instanceCount = self.progressShapeCount; 136 | } 137 | 138 | - (CGPoint)progressShapeLayerPosition { 139 | return CGPointMake(0, self.progressShapeSpread); 140 | } 141 | 142 | 143 | #pragma mark Customization 144 | 145 | - (void)setProgressShapeColor:(NSColor *)progressShapeColor { 146 | _progressShapeColor = progressShapeColor; 147 | self.progressShapeLayer.backgroundColor = progressShapeColor.CGColor; 148 | } 149 | 150 | - (void)setProgressShapeCount:(NSUInteger)progressShapeCount { 151 | _progressShapeCount = progressShapeCount; 152 | [self updateReplicatorSettings]; 153 | } 154 | 155 | - (void)setProgressShapeThickness:(CGFloat)progressShapeThickness { 156 | _progressShapeThickness = progressShapeThickness; 157 | [self.progressShapeLayer setValue:@(progressShapeThickness) forKeyPath:@"bounds.size.width"]; 158 | } 159 | 160 | - (void)setProgressShapeLength:(CGFloat)progressShapeLength { 161 | _progressShapeLength = progressShapeLength; 162 | [self.progressShapeLayer setValue:@(progressShapeLength) forKeyPath:@"bounds.size.height"]; 163 | } 164 | 165 | - (void)setProgressShapeSpread:(CGFloat)progressShapeSpread { 166 | _progressShapeSpread = progressShapeSpread; 167 | self.progressShapeLayer.position = self.progressShapeLayerPosition; 168 | } 169 | 170 | - (void)setProgressAnimationDuration:(CGFloat)progressAnimationDuration { 171 | _progressAnimationDuration = progressAnimationDuration; 172 | [self updateReplicatorSettings]; 173 | 174 | if ([self.progressShapeLayer animationForKey:BTRActivityIndicatorAnimationKey]) { 175 | [self.progressShapeLayer removeAnimationForKey:BTRActivityIndicatorAnimationKey]; 176 | [self.progressShapeLayer addAnimation:self.progressShapeLayerFadeOutAnimation forKey:BTRActivityIndicatorAnimationKey]; 177 | } 178 | } 179 | 180 | - (void)setProgressShapeLayer:(CALayer *)progressShapeLayer { 181 | BOOL needsAnimation = ([self.progressShapeLayer animationForKey:BTRActivityIndicatorAnimationKey] != nil); 182 | [self.progressShapeLayer removeFromSuperlayer]; 183 | _progressShapeLayer = progressShapeLayer; 184 | self.progressShapeLayer.position = self.progressShapeLayerPosition; 185 | [self.replicatorLayer addSublayer:self.progressShapeLayer]; 186 | if (needsAnimation) { 187 | [self.progressShapeLayer addAnimation:self.progressShapeLayerFadeOutAnimation forKey:BTRActivityIndicatorAnimationKey]; 188 | } 189 | } 190 | 191 | 192 | #pragma mark Accessibility 193 | 194 | - (BOOL)accessibilityIsIgnored { 195 | return NO; 196 | } 197 | 198 | @end 199 | -------------------------------------------------------------------------------- /Butter/BTRClipView.m: -------------------------------------------------------------------------------- 1 | /* 2 | Created by Jonathan Willing on 8/28/13. 3 | Copyright (c) 2013, ButterKit. All rights reserved. 4 | Licensed under the MIT license 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 7 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation 8 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 9 | to permit persons to whom the Software is furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 14 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 15 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 16 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 17 | IN THE SOFTWARE. 18 | */ 19 | 20 | #import "BTRClipView.h" 21 | 22 | // The default deceleration constant used for the ease-out curve in the animation. 23 | static const CGFloat BTRClipViewDecelerationRate = 0.78; 24 | 25 | @interface BTRClipView () 26 | // Used to drive the animation through repeated callbacks. 27 | // A display link is used instead of a timer so that we don't get dropped frames and tearing. 28 | // Lazily created when needed, released in dealloc. Stopped automatically when scrolling is not occurring. 29 | @property (nonatomic, assign) CVDisplayLinkRef displayLink; 30 | 31 | // Used to determine whether to animate in `scrollToPoint:`. 32 | @property (nonatomic, assign) BOOL shouldAnimateOriginChange; 33 | 34 | // Used when animating with the display link as the final origin for the animation. 35 | @property (nonatomic, assign) CGPoint destinationOrigin; 36 | 37 | // The scroll view which has this clip view set as the content view. 38 | @property (nonatomic, assign) NSScrollView *containingScrollView; 39 | 40 | // The optional completion block which is called at the end of the scroll animation. 41 | @property (nonatomic, copy) void (^scrollCompletion)(BOOL success); 42 | @end 43 | 44 | 45 | @implementation BTRClipView 46 | 47 | - (instancetype)initWithFrame:(NSRect)frame { 48 | self = [super initWithFrame:frame]; 49 | if (self == nil) return nil; 50 | 51 | self.wantsLayer = YES; 52 | self.decelerationRate = BTRClipViewDecelerationRate; 53 | 54 | return self; 55 | } 56 | 57 | - (void)dealloc { 58 | CVDisplayLinkRelease(_displayLink); 59 | [NSNotificationCenter.defaultCenter removeObserver:self]; 60 | } 61 | 62 | #pragma mark View Heirarchy 63 | 64 | - (void)viewWillMoveToWindow:(NSWindow *)newWindow { 65 | if (self.window != nil) { 66 | [NSNotificationCenter.defaultCenter removeObserver:self name:NSWindowDidChangeScreenNotification object:self.window]; 67 | } 68 | 69 | [super viewWillMoveToWindow:newWindow]; 70 | 71 | if (newWindow != nil) { 72 | [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(updateCVDisplay:) name:NSWindowDidChangeScreenNotification object:newWindow]; 73 | } 74 | } 75 | 76 | #pragma mark Display link 77 | 78 | static CVReturn BTRScrollingCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *now, const CVTimeStamp *outputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *displayLinkContext) { 79 | @autoreleasepool { 80 | BTRClipView *clipView = (__bridge id)displayLinkContext; 81 | dispatch_async(dispatch_get_main_queue(), ^{ 82 | [clipView updateOrigin]; 83 | }); 84 | } 85 | 86 | return kCVReturnSuccess; 87 | } 88 | 89 | - (CVDisplayLinkRef)displayLink { 90 | if (_displayLink == NULL) { 91 | CVDisplayLinkCreateWithActiveCGDisplays(&_displayLink); 92 | CVDisplayLinkSetOutputCallback(_displayLink, &BTRScrollingCallback, (__bridge void *)self); 93 | [self updateCVDisplay:nil]; 94 | } 95 | 96 | return _displayLink; 97 | } 98 | 99 | - (void)updateCVDisplay:(NSNotification *)note { 100 | NSScreen *screen = self.window.screen; 101 | if (screen == nil) { 102 | NSDictionary *screenDictionary = NSScreen.mainScreen.deviceDescription; 103 | NSNumber *screenID = screenDictionary[@"NSScreenNumber"]; 104 | CGDirectDisplayID displayID = screenID.unsignedIntValue; 105 | CVDisplayLinkSetCurrentCGDisplay(_displayLink, displayID); 106 | } else { 107 | CVDisplayLinkSetCurrentCGDisplay(_displayLink, kCGDirectMainDisplay); 108 | } 109 | } 110 | 111 | #pragma mark Scrolling 112 | 113 | - (void)scrollToPoint:(NSPoint)newOrigin { 114 | // We should only attempt to animate ourselves if we know this point we're scrolling to 115 | // was the point determined from a -scrollToRect:animated: call. 116 | if (self.shouldAnimateOriginChange) { 117 | self.shouldAnimateOriginChange = NO; 118 | self.destinationOrigin = newOrigin; 119 | [self beginScrolling]; 120 | } else { 121 | // Otherwise, we stop any scrolling that is currently occurring (if needed) and let 122 | // super's implementation handle a normal scroll. 123 | [self endScrolling]; 124 | [super scrollToPoint:newOrigin]; 125 | } 126 | } 127 | 128 | - (BOOL)scrollRectToVisible:(NSRect)aRect animated:(BOOL)animated { 129 | self.shouldAnimateOriginChange = animated; 130 | return [super scrollRectToVisible:aRect]; 131 | } 132 | 133 | - (BOOL)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated completion:(void (^)(BOOL sucess))completion { 134 | self.scrollCompletion = completion; 135 | BOOL success = [self scrollRectToVisible:rect animated:animated]; 136 | 137 | if (!animated || !success) { 138 | [self handleCompletionIfNeededWithSuccess:success]; 139 | } 140 | 141 | return success; 142 | } 143 | 144 | - (void)beginScrolling { 145 | if (CVDisplayLinkIsRunning(self.displayLink)) { 146 | return; 147 | } 148 | 149 | CVDisplayLinkStart(self.displayLink); 150 | } 151 | 152 | - (void)endScrolling { 153 | if (!CVDisplayLinkIsRunning(self.displayLink)) { 154 | return; 155 | } 156 | 157 | CVDisplayLinkStop(self.displayLink); 158 | } 159 | 160 | // Sanitize the deceleration rate to [0, 1] so nothing unexpected happens. 161 | - (void)setDecelerationRate:(CGFloat)decelerationRate { 162 | if (decelerationRate > 1) { 163 | decelerationRate = 1; 164 | } 165 | else if (decelerationRate < 0) { 166 | decelerationRate = 0; 167 | } 168 | _decelerationRate = decelerationRate; 169 | } 170 | 171 | - (NSScrollView *)containingScrollView { 172 | if (_containingScrollView == nil) { 173 | _containingScrollView = self.enclosingScrollView; 174 | if (_containingScrollView == nil && [self.superview isKindOfClass:NSScrollView.class]) { 175 | _containingScrollView = (NSScrollView *)self.superview; 176 | } 177 | } 178 | 179 | return _containingScrollView; 180 | } 181 | 182 | - (void)updateOrigin { 183 | if (self.window == nil) { 184 | [self endScrolling]; 185 | return; 186 | } 187 | 188 | CGPoint o = self.bounds.origin; 189 | CGPoint lastOrigin = o; 190 | CGFloat deceleration = self.decelerationRate; 191 | 192 | // Calculate the next origin on a basic ease-out curve. 193 | o.x = o.x * deceleration + self.destinationOrigin.x * (1 - self.decelerationRate); 194 | o.y = o.y * deceleration + self.destinationOrigin.y * (1 - self.decelerationRate); 195 | 196 | // Calling -scrollToPoint: instead of manually adjusting the bounds lets us get the expected 197 | // overlay scroller behavior for free. 198 | [super scrollToPoint:o]; 199 | 200 | // Make this call so that we can force an update of the scroller positions. 201 | [self.containingScrollView reflectScrolledClipView:self]; 202 | 203 | if ((fabs(o.x - lastOrigin.x) < 0.1 && fabs(o.y - lastOrigin.y) < 0.1)) { 204 | [self endScrolling]; 205 | 206 | // Make sure we always finish out the animation with the actual coordinates 207 | [super scrollToPoint:o]; 208 | [self handleCompletionIfNeededWithSuccess:YES]; 209 | } 210 | } 211 | 212 | #pragma mark Completion handling 213 | 214 | - (void)handleCompletionIfNeededWithSuccess:(BOOL)success { 215 | if (self.scrollCompletion != nil) { 216 | self.scrollCompletion(success); 217 | self.scrollCompletion = nil; 218 | } 219 | } 220 | 221 | @end 222 | -------------------------------------------------------------------------------- /Butter/BTRPopUpButton.m: -------------------------------------------------------------------------------- 1 | // 2 | // BTRPopUpButton.m 3 | // Butter 4 | // 5 | // Created by Indragie Karunaratne on 2012-12-30. 6 | // Copyright (c) 2012 ButterKit. All rights reserved. 7 | // 8 | 9 | #import "BTRPopUpButton.h" 10 | #import "BTRLabel.h" 11 | 12 | @interface BTRPopUpButtonLabel : BTRLabel 13 | @end 14 | @interface BTRPopUpButtonImageView : BTRImageView 15 | @end 16 | 17 | @interface BTRPopUpButton () 18 | @property (nonatomic, strong) BTRImageView *imageView; 19 | @property (nonatomic, strong) BTRLabel *label; 20 | 21 | @property (nonatomic, strong) BTRImageView *backgroundImageView; 22 | @property (nonatomic, strong) BTRImageView *arrowImageView; 23 | 24 | @property (nonatomic, strong) id notificationObserver; 25 | @end 26 | 27 | @interface BTRPopUpButtonContent : BTRControlContent 28 | @property (nonatomic, strong) NSImage *arrowImage; 29 | @end 30 | 31 | @implementation BTRPopUpButton 32 | 33 | @dynamic menu; 34 | 35 | #pragma mark - Initialization 36 | 37 | static void BTRPopupButtonCommonInit(BTRPopUpButton *self) { 38 | self.label = [[BTRPopUpButtonLabel alloc] initWithFrame:NSZeroRect]; 39 | self.imageView = [[BTRPopUpButtonImageView alloc] initWithFrame:NSZeroRect]; 40 | self.imageView.contentMode = BTRViewContentModeCenter; 41 | self.arrowImageView = [[BTRPopUpButtonImageView alloc] initWithFrame:NSZeroRect]; 42 | self.arrowImageView.contentMode = BTRViewContentModeCenter; 43 | self.backgroundImageView = [[BTRPopUpButtonImageView alloc] initWithFrame:NSZeroRect]; 44 | 45 | self.layer.masksToBounds = YES; 46 | [self addSubview:self.backgroundImageView]; 47 | [self addSubview:self.imageView]; 48 | [self addSubview:self.label]; 49 | [self addSubview:self.arrowImageView]; 50 | 51 | // Observe changes to the menu's delegate. When the delegate changes 52 | // we want to force a menu refresh if the delegate has implemented the 53 | // menu update methods declared in the NSMenuDelegate protocol. 54 | [self addObserver:self forKeyPath:@"menu.delegate" options:NSKeyValueObservingOptionNew context:NULL]; 55 | 56 | [self accessibilitySetOverrideValue:NSAccessibilityPopUpButtonRole forAttribute:NSAccessibilityRoleAttribute]; 57 | [self accessibilitySetOverrideValue:NSAccessibilityRoleDescription(NSAccessibilityPopUpButtonRole, nil) forAttribute:NSAccessibilityRoleDescriptionAttribute]; 58 | 59 | } 60 | 61 | - (instancetype)initWithFrame:(NSRect)frameRect { 62 | self = [super initWithFrame:frameRect]; 63 | if (self == nil) return nil; 64 | BTRPopupButtonCommonInit(self); 65 | return self; 66 | } 67 | 68 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 69 | self = [super initWithCoder:aDecoder]; 70 | if (self == nil) return nil; 71 | BTRPopupButtonCommonInit(self); 72 | return self; 73 | } 74 | 75 | - (void)dealloc { 76 | [self removeObserver:self forKeyPath:@"menu.delegate"]; 77 | if (self.notificationObserver) { 78 | [NSNotificationCenter.defaultCenter removeObserver:self.notificationObserver]; 79 | } 80 | } 81 | 82 | #pragma mark - KVO 83 | 84 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 85 | // Force a menu update when the delegate changes 86 | if ([keyPath isEqualToString:@"menu.delegate"]) { 87 | [self forceMenuUpdate]; 88 | } 89 | } 90 | 91 | #pragma mark - Accessibility 92 | 93 | - (NSArray *)accessibilityActionNames { 94 | return @[NSAccessibilityPressAction, NSAccessibilityShowMenuAction]; 95 | } 96 | 97 | - (NSString *)accessibilityActionDescription:(NSString *)action { 98 | return NSAccessibilityActionDescription(action); 99 | } 100 | 101 | - (void)accessibilityPerformAction:(NSString *)action { 102 | if ([action isEqualToString:NSAccessibilityPressAction] || [action isEqualToString:NSAccessibilityShowMenuAction]) { 103 | [self showMenuWithEvent:nil]; 104 | } 105 | } 106 | 107 | #pragma mark - BTRControl 108 | 109 | + (Class)controlContentClass { 110 | return [BTRPopUpButtonContent class]; 111 | } 112 | 113 | - (BTRPopUpButtonContent *)popUpButtonContentForState:(BTRControlState)state { 114 | return (BTRPopUpButtonContent *)[self contentForControlState:state]; 115 | } 116 | 117 | - (void)handleStateChange { 118 | NSString *title = self.selectedItem.title; 119 | if (title) { 120 | self.label.textColor = self.currentTitleColor; 121 | self.label.font = self.currentTitleFont; 122 | self.label.stringValue = title; 123 | self.label.textShadow = self.currentTitleShadow; 124 | } else { 125 | self.label.stringValue = @""; 126 | } 127 | self.arrowImageView.image = self.currentArrowImage; 128 | self.backgroundImageView.image = self.currentBackgroundImage; 129 | self.imageView.image = self.selectedItem.image; 130 | } 131 | 132 | #pragma mark - Public Methods 133 | 134 | - (NSImage *)arrowImageForControlState:(BTRControlState)state { 135 | return [self popUpButtonContentForState:state].arrowImage; 136 | } 137 | 138 | - (void)setArrowImage:(NSImage *)image forControlState:(BTRControlState)state { 139 | [self popUpButtonContentForState:state].arrowImage = image; 140 | } 141 | 142 | - (NSImage *)currentArrowImage { 143 | return [self popUpButtonContentForState:self.state].arrowImage ?: [self popUpButtonContentForState:BTRControlStateNormal].arrowImage; 144 | } 145 | 146 | - (void)selectItemAtIndex:(NSUInteger)index { 147 | self.selectedItem = [self.menu itemAtIndex:index]; 148 | } 149 | 150 | - (NSUInteger)indexOfSelectedItem { 151 | return [self.menu indexOfItem:self.selectedItem]; 152 | } 153 | 154 | #pragma mark - Accessors 155 | 156 | - (void)setMenu:(NSMenu *)menu { 157 | if (self.menu != menu) { 158 | NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 159 | if (self.notificationObserver) { 160 | [nc removeObserver:self.notificationObserver]; 161 | self.notificationObserver = nil; 162 | } 163 | self.selectedItem = nil; 164 | super.menu = menu; 165 | if (self.menu) { 166 | self.menu.autoenablesItems = self.autoenablesItems; 167 | // Register for notifications for when the menu closes. This is important 168 | // because mouseUp: and mouseExited: are not normally called if the menu is closed 169 | // when the cursor is outside the pop up button. This ensures that the proper 170 | // state is restored once the menu is closed. 171 | __weak BTRPopUpButton *weakSelf = self; 172 | 173 | self.notificationObserver = [nc addObserverForName:NSMenuDidEndTrackingNotification object:self.menu queue:nil usingBlock:^(NSNotification *note) { 174 | BTRPopUpButton *strongSelf = weakSelf; 175 | 176 | [strongSelf mouseUp:nil]; 177 | [strongSelf mouseExited:nil]; 178 | [strongSelf accessibilitySetOverrideValue:nil forAttribute:NSAccessibilityShownMenuAttribute]; 179 | }]; 180 | 181 | // Force a menu update from the delegate once the menu is initially set 182 | [self forceMenuUpdate]; 183 | } 184 | } 185 | } 186 | 187 | - (void)setSelectedItem:(NSMenuItem *)selectedItem { 188 | if (_selectedItem != selectedItem) { 189 | _selectedItem.state = NSOffState; 190 | _selectedItem = selectedItem; 191 | _selectedItem.state = NSOnState; 192 | [self handleStateChange]; 193 | [self setNeedsLayout:YES]; 194 | [self accessibilitySetOverrideValue:_selectedItem.title forAttribute:NSAccessibilityTitleAttribute]; 195 | } 196 | } 197 | 198 | - (void)setTextAlignment:(NSTextAlignment)textAlignment { 199 | if (_textAlignment != textAlignment) { 200 | _textAlignment = textAlignment; 201 | [self setNeedsLayout:YES]; 202 | } 203 | } 204 | 205 | #pragma mark - NSMenu 206 | 207 | - (void)reconfigureMenuItems { 208 | // Reset the target and action of each item so that the pop up button receives 209 | // the events when the items are clicked. 210 | [self.menu.itemArray enumerateObjectsUsingBlock:^(NSMenuItem *item, NSUInteger idx, BOOL *stop) { 211 | item.target = self; 212 | item.action = @selector(popUpMenuSelectedItem:); 213 | }]; 214 | // Default to setting the first item in the menu as the selected item 215 | if ([self.menu numberOfItems] && !self.selectedItem) { 216 | self.selectedItem = [self.menu itemAtIndex:0]; 217 | self.selectedItem.state = NSOnState; 218 | } 219 | } 220 | 221 | - (void)forceMenuUpdate { 222 | id delegate = self.menu.delegate; 223 | if (!delegate) { 224 | [self reconfigureMenuItems]; 225 | return; 226 | } 227 | // This runs a delegate based update to the menu as documented by the NSMenuDelegate protocol. 228 | // First a check to see if -menuNeedsUpdate: is implemented. If so, this means that the delegate 229 | // takes complete control of handling the update in this one method, and no further 230 | // method calls are necessary 231 | if ([delegate respondsToSelector:@selector(menuNeedsUpdate:)]) { 232 | [delegate menuNeedsUpdate:self.menu]; 233 | // The other update mechanism that the delegate provides are two "data source" type methods that 234 | // are called repetitively to update each item 235 | } else if ([delegate respondsToSelector:@selector(numberOfItemsInMenu:)] && [delegate respondsToSelector:@selector(menu:updateItem:atIndex:shouldCancel:)]) { 236 | NSInteger numberOfItems = [delegate numberOfItemsInMenu:self.menu]; 237 | BOOL shouldCancel = NO; 238 | for (NSInteger i = 0; i < numberOfItems; i++) { 239 | shouldCancel = [delegate menu:self.menu updateItem:[self.menu itemAtIndex:i] atIndex:i shouldCancel:shouldCancel]; 240 | } 241 | } 242 | [self reconfigureMenuItems]; 243 | } 244 | 245 | #pragma mark - Layout 246 | 247 | - (void)layout { 248 | self.imageView.frame = [self imageFrame]; 249 | self.label.frame = [self labelFrame]; 250 | self.arrowImageView.frame = [self arrowFrame]; 251 | self.backgroundImageView.frame = self.bounds; 252 | [super layout]; 253 | } 254 | 255 | - (NSRect)imageFrame { 256 | const NSSize imageSize = self.selectedItem.image.size; 257 | // Size the image rect to the exact height and width of the selected image 258 | return NSMakeRect([self edgeInset], roundf(NSMidY(self.bounds) - (imageSize.height / 2.f)), imageSize.width, imageSize.height); 259 | } 260 | 261 | - (NSRect)labelFrame { 262 | const NSRect imageFrame = [self imageFrame]; 263 | const NSRect arrowFrame = [self arrowFrame]; 264 | const CGFloat spacing = [self interElementSpacing]; 265 | 266 | CGFloat maximumWidth = NSWidth(self.bounds) - NSMaxX(imageFrame) - NSWidth(arrowFrame) - [self edgeInset]; 267 | if (NSWidth(imageFrame)) { 268 | maximumWidth -= spacing; 269 | } 270 | if (NSWidth(arrowFrame)) { 271 | maximumWidth -= spacing; 272 | } 273 | 274 | // Calling -sizeToFit modifies the frame of the label. This is necessary 275 | // to get accurate metrics for the intrinsic content size. 276 | [self.label sizeToFit]; 277 | const CGFloat textWidth = fminf(NSWidth(self.label.frame), maximumWidth); 278 | CGFloat xOrigin; 279 | switch (self.textAlignment) { 280 | case NSRightTextAlignment: 281 | xOrigin = NSMinX(arrowFrame) - spacing - textWidth; 282 | break; 283 | case NSCenterTextAlignment: 284 | xOrigin = floorf(NSMidX(self.bounds) - (textWidth / 2.f)); 285 | break; 286 | case NSLeftTextAlignment: 287 | default: 288 | xOrigin = NSMaxX(imageFrame) + spacing; 289 | break; 290 | } 291 | return NSMakeRect(xOrigin, 0.f, textWidth, NSHeight(self.bounds)); 292 | } 293 | 294 | - (NSRect)arrowFrame { 295 | const NSSize arrowSize = self.currentArrowImage.size; 296 | // Size the arrow image to the exact height and width of the image 297 | return NSMakeRect(NSMaxX(self.bounds) - arrowSize.width - [self edgeInset], roundf(NSMidY(self.bounds) - (arrowSize.height / 2.f)), arrowSize.width, arrowSize.height); 298 | } 299 | 300 | - (CGFloat)interElementSpacing { 301 | return 3.f; 302 | } 303 | 304 | - (CGFloat)edgeInset { 305 | return 6.f; 306 | } 307 | 308 | - (CGFloat)widthToFit { 309 | // Need to tack on padding here because NSTextFieldCell does some weird padding stuff 310 | // that causes the actual drawing bounds of the text to be less than the width of the text field. 311 | // I've already tried a bunch of stuff like NSTextFieldCell's -cellSizeForBounds:, -drawingRectForBounds:, 312 | // and none of them return a properly sized rect. 313 | return NSWidth([self imageFrame]) + ceilf(self.label.attributedStringValue.size.width) + NSWidth([self arrowFrame]) + (2.f * [self edgeInset]) + (2.f * [self interElementSpacing]) + 4.f; 314 | } 315 | 316 | - (void)sizeToFit { 317 | NSRect newFrame = self.frame; 318 | newFrame.size.width = [self widthToFit]; 319 | self.frame = newFrame; 320 | [self setNeedsLayout:YES]; 321 | } 322 | 323 | #pragma mark - Mouse Events 324 | 325 | - (void)mouseDown:(NSEvent *)theEvent { 326 | [super mouseDown:theEvent]; 327 | [self showMenuWithEvent:theEvent]; 328 | } 329 | 330 | - (void)showMenuWithEvent:(NSEvent *)event { 331 | if (!self.menu || !self.enabled || !self.userInteractionEnabled) return; 332 | 333 | NSPoint origin; 334 | NSRect imageFrame = [self imageFrame]; 335 | if (NSWidth(imageFrame)) { 336 | origin = imageFrame.origin; 337 | // Offset to line up the menu item image 338 | // TODO: Figure out a better way to calculate this offset at runtime. 339 | // There are no geometry methods on NSMenu or NSMenuItem that would 340 | // allow the retrieval of layout information for menu items 341 | origin.x -= 22.f; 342 | } else { 343 | origin = [self labelFrame].origin; 344 | } 345 | origin.y = 0.f; 346 | // Synthesize an event just so we can change the location of the menu 347 | NSEvent *synthesizedEvent = [self synthesizedEventWithLocalMouseLocation:origin realEvent:event]; 348 | [NSMenu popUpContextMenu:self.menu withEvent:synthesizedEvent forView:self]; 349 | [self accessibilitySetOverrideValue:self.menu forAttribute:NSAccessibilityShownMenuAttribute]; 350 | } 351 | 352 | - (NSEvent *)synthesizedEventWithLocalMouseLocation:(NSPoint)location realEvent:(NSEvent *)event { 353 | NSPoint windowPoint = [self convertPoint:location toView:nil]; 354 | return [NSEvent mouseEventWithType:NSLeftMouseDown 355 | location:windowPoint 356 | modifierFlags:event.modifierFlags 357 | timestamp:event.timestamp 358 | windowNumber:self.window.windowNumber 359 | context:event.context 360 | eventNumber:event.eventNumber 361 | clickCount:event.clickCount ?: 1 362 | pressure:event.pressure]; 363 | } 364 | 365 | #pragma mark - Menu Events 366 | 367 | - (IBAction)popUpMenuSelectedItem:(id)sender { 368 | self.selectedItem = sender; 369 | [self sendActionsForControlEvents:BTRControlEventValueChanged]; 370 | [self handleStateChange]; 371 | } 372 | 373 | @end 374 | 375 | @implementation BTRPopUpButtonContent 376 | - (void)setArrowImage:(NSImage *)arrowImage { 377 | if (_arrowImage != arrowImage) { 378 | _arrowImage = arrowImage; 379 | [self controlContentChanged]; 380 | } 381 | } 382 | 383 | + (NSDictionary *)defaultTitleAttributes { 384 | NSMutableParagraphStyle *style = [NSMutableParagraphStyle new]; 385 | style.lineBreakMode = NSLineBreakByTruncatingTail; 386 | style.alignment = NSLeftTextAlignment; 387 | return @{NSParagraphStyleAttributeName: style}; 388 | } 389 | @end 390 | 391 | // Prevent the subviews from receiving mouse events 392 | @implementation BTRPopUpButtonLabel { 393 | BOOL _isEditing; 394 | } 395 | - (NSView *)hitTest:(NSPoint)aPoint { 396 | return _isEditing ? [super hitTest:aPoint] : nil; 397 | } 398 | 399 | - (BOOL)becomeFirstResponder { 400 | _isEditing = YES; 401 | return [super becomeFirstResponder]; 402 | } 403 | 404 | - (NSRect)drawingRectForProposedDrawingRect:(NSRect)rect { 405 | return rect; 406 | } 407 | 408 | @end 409 | 410 | @implementation BTRPopUpButtonImageView 411 | 412 | - (NSView *)hitTest:(NSPoint)aPoint { return nil; } 413 | 414 | @end -------------------------------------------------------------------------------- /Examples/BTRButton/ButtonDemo/ButtonDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | AB9774BE17ED8D4A00810BA9 /* Butter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB9774BA17ED8CFA00810BA9 /* Butter.framework */; }; 11 | ABECF085168563CB00BED126 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ABECF084168563CB00BED126 /* Cocoa.framework */; }; 12 | ABECF08F168563CB00BED126 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = ABECF08D168563CB00BED126 /* InfoPlist.strings */; }; 13 | ABECF091168563CB00BED126 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = ABECF090168563CB00BED126 /* main.m */; }; 14 | ABECF095168563CB00BED126 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = ABECF093168563CB00BED126 /* Credits.rtf */; }; 15 | ABECF098168563CB00BED126 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = ABECF097168563CB00BED126 /* AppDelegate.m */; }; 16 | ABECF09B168563CB00BED126 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = ABECF099168563CB00BED126 /* MainMenu.xib */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXContainerItemProxy section */ 20 | AB9774B917ED8CFA00810BA9 /* PBXContainerItemProxy */ = { 21 | isa = PBXContainerItemProxy; 22 | containerPortal = AB9774B517ED8CF900810BA9 /* Butter.xcodeproj */; 23 | proxyType = 2; 24 | remoteGlobalIDString = 03239EB21672E6D6004263D7; 25 | remoteInfo = Butter; 26 | }; 27 | AB9774BB17ED8CFD00810BA9 /* PBXContainerItemProxy */ = { 28 | isa = PBXContainerItemProxy; 29 | containerPortal = AB9774B517ED8CF900810BA9 /* Butter.xcodeproj */; 30 | proxyType = 1; 31 | remoteGlobalIDString = 03239EB11672E6D6004263D7; 32 | remoteInfo = Butter; 33 | }; 34 | /* End PBXContainerItemProxy section */ 35 | 36 | /* Begin PBXFileReference section */ 37 | AB9774B517ED8CF900810BA9 /* Butter.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Butter.xcodeproj; path = ../../../../Butter.xcodeproj; sourceTree = ""; }; 38 | ABECF081168563CB00BED126 /* ButtonDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ButtonDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 39 | ABECF084168563CB00BED126 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 40 | ABECF087168563CB00BED126 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 41 | ABECF088168563CB00BED126 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 42 | ABECF089168563CB00BED126 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 43 | ABECF08C168563CB00BED126 /* ButtonDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ButtonDemo-Info.plist"; sourceTree = ""; }; 44 | ABECF08E168563CB00BED126 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 45 | ABECF090168563CB00BED126 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 46 | ABECF092168563CB00BED126 /* ButtonDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ButtonDemo-Prefix.pch"; sourceTree = ""; }; 47 | ABECF094168563CB00BED126 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; 48 | ABECF096168563CB00BED126 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 49 | ABECF097168563CB00BED126 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 50 | ABECF09A168563CB00BED126 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; 51 | /* End PBXFileReference section */ 52 | 53 | /* Begin PBXFrameworksBuildPhase section */ 54 | ABECF07E168563CB00BED126 /* Frameworks */ = { 55 | isa = PBXFrameworksBuildPhase; 56 | buildActionMask = 2147483647; 57 | files = ( 58 | AB9774BE17ED8D4A00810BA9 /* Butter.framework in Frameworks */, 59 | ABECF085168563CB00BED126 /* Cocoa.framework in Frameworks */, 60 | ); 61 | runOnlyForDeploymentPostprocessing = 0; 62 | }; 63 | /* End PBXFrameworksBuildPhase section */ 64 | 65 | /* Begin PBXGroup section */ 66 | AB9774B617ED8CF900810BA9 /* Products */ = { 67 | isa = PBXGroup; 68 | children = ( 69 | AB9774BA17ED8CFA00810BA9 /* Butter.framework */, 70 | ); 71 | name = Products; 72 | sourceTree = ""; 73 | }; 74 | ABECF078168563CB00BED126 = { 75 | isa = PBXGroup; 76 | children = ( 77 | ABECF08A168563CB00BED126 /* ButtonDemo */, 78 | ABECF083168563CB00BED126 /* Frameworks */, 79 | ABECF082168563CB00BED126 /* Products */, 80 | ); 81 | sourceTree = ""; 82 | }; 83 | ABECF082168563CB00BED126 /* Products */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | ABECF081168563CB00BED126 /* ButtonDemo.app */, 87 | ); 88 | name = Products; 89 | sourceTree = ""; 90 | }; 91 | ABECF083168563CB00BED126 /* Frameworks */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | ABECF084168563CB00BED126 /* Cocoa.framework */, 95 | ABECF086168563CB00BED126 /* Other Frameworks */, 96 | ); 97 | name = Frameworks; 98 | sourceTree = ""; 99 | }; 100 | ABECF086168563CB00BED126 /* Other Frameworks */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | ABECF087168563CB00BED126 /* AppKit.framework */, 104 | ABECF088168563CB00BED126 /* CoreData.framework */, 105 | ABECF089168563CB00BED126 /* Foundation.framework */, 106 | ); 107 | name = "Other Frameworks"; 108 | sourceTree = ""; 109 | }; 110 | ABECF08A168563CB00BED126 /* ButtonDemo */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | AB9774B517ED8CF900810BA9 /* Butter.xcodeproj */, 114 | ABECF096168563CB00BED126 /* AppDelegate.h */, 115 | ABECF097168563CB00BED126 /* AppDelegate.m */, 116 | ABECF099168563CB00BED126 /* MainMenu.xib */, 117 | ABECF08B168563CB00BED126 /* Supporting Files */, 118 | ); 119 | path = ButtonDemo; 120 | sourceTree = ""; 121 | }; 122 | ABECF08B168563CB00BED126 /* Supporting Files */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | ABECF08C168563CB00BED126 /* ButtonDemo-Info.plist */, 126 | ABECF08D168563CB00BED126 /* InfoPlist.strings */, 127 | ABECF090168563CB00BED126 /* main.m */, 128 | ABECF092168563CB00BED126 /* ButtonDemo-Prefix.pch */, 129 | ABECF093168563CB00BED126 /* Credits.rtf */, 130 | ); 131 | name = "Supporting Files"; 132 | sourceTree = ""; 133 | }; 134 | /* End PBXGroup section */ 135 | 136 | /* Begin PBXNativeTarget section */ 137 | ABECF080168563CB00BED126 /* ButtonDemo */ = { 138 | isa = PBXNativeTarget; 139 | buildConfigurationList = ABECF09E168563CB00BED126 /* Build configuration list for PBXNativeTarget "ButtonDemo" */; 140 | buildPhases = ( 141 | ABECF07D168563CB00BED126 /* Sources */, 142 | ABECF07E168563CB00BED126 /* Frameworks */, 143 | ABECF07F168563CB00BED126 /* Resources */, 144 | ); 145 | buildRules = ( 146 | ); 147 | dependencies = ( 148 | AB9774BC17ED8CFD00810BA9 /* PBXTargetDependency */, 149 | ); 150 | name = ButtonDemo; 151 | productName = ButtonDemo; 152 | productReference = ABECF081168563CB00BED126 /* ButtonDemo.app */; 153 | productType = "com.apple.product-type.application"; 154 | }; 155 | /* End PBXNativeTarget section */ 156 | 157 | /* Begin PBXProject section */ 158 | ABECF079168563CB00BED126 /* Project object */ = { 159 | isa = PBXProject; 160 | attributes = { 161 | LastUpgradeCheck = 0510; 162 | ORGANIZATIONNAME = Butter; 163 | }; 164 | buildConfigurationList = ABECF07C168563CB00BED126 /* Build configuration list for PBXProject "ButtonDemo" */; 165 | compatibilityVersion = "Xcode 3.2"; 166 | developmentRegion = English; 167 | hasScannedForEncodings = 0; 168 | knownRegions = ( 169 | en, 170 | ); 171 | mainGroup = ABECF078168563CB00BED126; 172 | productRefGroup = ABECF082168563CB00BED126 /* Products */; 173 | projectDirPath = ""; 174 | projectReferences = ( 175 | { 176 | ProductGroup = AB9774B617ED8CF900810BA9 /* Products */; 177 | ProjectRef = AB9774B517ED8CF900810BA9 /* Butter.xcodeproj */; 178 | }, 179 | ); 180 | projectRoot = ""; 181 | targets = ( 182 | ABECF080168563CB00BED126 /* ButtonDemo */, 183 | ); 184 | }; 185 | /* End PBXProject section */ 186 | 187 | /* Begin PBXReferenceProxy section */ 188 | AB9774BA17ED8CFA00810BA9 /* Butter.framework */ = { 189 | isa = PBXReferenceProxy; 190 | fileType = wrapper.framework; 191 | path = Butter.framework; 192 | remoteRef = AB9774B917ED8CFA00810BA9 /* PBXContainerItemProxy */; 193 | sourceTree = BUILT_PRODUCTS_DIR; 194 | }; 195 | /* End PBXReferenceProxy section */ 196 | 197 | /* Begin PBXResourcesBuildPhase section */ 198 | ABECF07F168563CB00BED126 /* Resources */ = { 199 | isa = PBXResourcesBuildPhase; 200 | buildActionMask = 2147483647; 201 | files = ( 202 | ABECF08F168563CB00BED126 /* InfoPlist.strings in Resources */, 203 | ABECF095168563CB00BED126 /* Credits.rtf in Resources */, 204 | ABECF09B168563CB00BED126 /* MainMenu.xib in Resources */, 205 | ); 206 | runOnlyForDeploymentPostprocessing = 0; 207 | }; 208 | /* End PBXResourcesBuildPhase section */ 209 | 210 | /* Begin PBXSourcesBuildPhase section */ 211 | ABECF07D168563CB00BED126 /* Sources */ = { 212 | isa = PBXSourcesBuildPhase; 213 | buildActionMask = 2147483647; 214 | files = ( 215 | ABECF091168563CB00BED126 /* main.m in Sources */, 216 | ABECF098168563CB00BED126 /* AppDelegate.m in Sources */, 217 | ); 218 | runOnlyForDeploymentPostprocessing = 0; 219 | }; 220 | /* End PBXSourcesBuildPhase section */ 221 | 222 | /* Begin PBXTargetDependency section */ 223 | AB9774BC17ED8CFD00810BA9 /* PBXTargetDependency */ = { 224 | isa = PBXTargetDependency; 225 | name = Butter; 226 | targetProxy = AB9774BB17ED8CFD00810BA9 /* PBXContainerItemProxy */; 227 | }; 228 | /* End PBXTargetDependency section */ 229 | 230 | /* Begin PBXVariantGroup section */ 231 | ABECF08D168563CB00BED126 /* InfoPlist.strings */ = { 232 | isa = PBXVariantGroup; 233 | children = ( 234 | ABECF08E168563CB00BED126 /* en */, 235 | ); 236 | name = InfoPlist.strings; 237 | sourceTree = ""; 238 | }; 239 | ABECF093168563CB00BED126 /* Credits.rtf */ = { 240 | isa = PBXVariantGroup; 241 | children = ( 242 | ABECF094168563CB00BED126 /* en */, 243 | ); 244 | name = Credits.rtf; 245 | sourceTree = ""; 246 | }; 247 | ABECF099168563CB00BED126 /* MainMenu.xib */ = { 248 | isa = PBXVariantGroup; 249 | children = ( 250 | ABECF09A168563CB00BED126 /* en */, 251 | ); 252 | name = MainMenu.xib; 253 | sourceTree = ""; 254 | }; 255 | /* End PBXVariantGroup section */ 256 | 257 | /* Begin XCBuildConfiguration section */ 258 | ABECF09C168563CB00BED126 /* Debug */ = { 259 | isa = XCBuildConfiguration; 260 | buildSettings = { 261 | ALWAYS_SEARCH_USER_PATHS = NO; 262 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 263 | CLANG_CXX_LIBRARY = "libc++"; 264 | CLANG_ENABLE_OBJC_ARC = YES; 265 | CLANG_WARN_CONSTANT_CONVERSION = YES; 266 | CLANG_WARN_EMPTY_BODY = YES; 267 | CLANG_WARN_ENUM_CONVERSION = YES; 268 | CLANG_WARN_INT_CONVERSION = YES; 269 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 270 | COPY_PHASE_STRIP = NO; 271 | GCC_C_LANGUAGE_STANDARD = gnu99; 272 | GCC_DYNAMIC_NO_PIC = NO; 273 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 274 | GCC_OPTIMIZATION_LEVEL = 0; 275 | GCC_PREPROCESSOR_DEFINITIONS = ( 276 | "DEBUG=1", 277 | "$(inherited)", 278 | ); 279 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 280 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 281 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 282 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 283 | GCC_WARN_UNUSED_VARIABLE = YES; 284 | MACOSX_DEPLOYMENT_TARGET = 10.8; 285 | ONLY_ACTIVE_ARCH = YES; 286 | SDKROOT = macosx; 287 | }; 288 | name = Debug; 289 | }; 290 | ABECF09D168563CB00BED126 /* Release */ = { 291 | isa = XCBuildConfiguration; 292 | buildSettings = { 293 | ALWAYS_SEARCH_USER_PATHS = NO; 294 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 295 | CLANG_CXX_LIBRARY = "libc++"; 296 | CLANG_ENABLE_OBJC_ARC = YES; 297 | CLANG_WARN_CONSTANT_CONVERSION = YES; 298 | CLANG_WARN_EMPTY_BODY = YES; 299 | CLANG_WARN_ENUM_CONVERSION = YES; 300 | CLANG_WARN_INT_CONVERSION = YES; 301 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 302 | COPY_PHASE_STRIP = YES; 303 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 304 | GCC_C_LANGUAGE_STANDARD = gnu99; 305 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 306 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 307 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 308 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 309 | GCC_WARN_UNUSED_VARIABLE = YES; 310 | MACOSX_DEPLOYMENT_TARGET = 10.8; 311 | SDKROOT = macosx; 312 | }; 313 | name = Release; 314 | }; 315 | ABECF09F168563CB00BED126 /* Debug */ = { 316 | isa = XCBuildConfiguration; 317 | buildSettings = { 318 | COMBINE_HIDPI_IMAGES = YES; 319 | FRAMEWORK_SEARCH_PATHS = ( 320 | "$(inherited)", 321 | "\"$(SRCROOT)/../../../../../../../../../Library/Developer/Xcode/DerivedData/Butter-gqoqbeasmoutbjeyiuunhmhydaex/Build/Products/Debug\"", 322 | ); 323 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 324 | GCC_PREFIX_HEADER = "ButtonDemo/ButtonDemo-Prefix.pch"; 325 | INFOPLIST_FILE = "ButtonDemo/ButtonDemo-Info.plist"; 326 | PRODUCT_NAME = "$(TARGET_NAME)"; 327 | WRAPPER_EXTENSION = app; 328 | }; 329 | name = Debug; 330 | }; 331 | ABECF0A0168563CB00BED126 /* Release */ = { 332 | isa = XCBuildConfiguration; 333 | buildSettings = { 334 | COMBINE_HIDPI_IMAGES = YES; 335 | FRAMEWORK_SEARCH_PATHS = ( 336 | "$(inherited)", 337 | "\"$(SRCROOT)/../../../../../../../../../Library/Developer/Xcode/DerivedData/Butter-gqoqbeasmoutbjeyiuunhmhydaex/Build/Products/Debug\"", 338 | ); 339 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 340 | GCC_PREFIX_HEADER = "ButtonDemo/ButtonDemo-Prefix.pch"; 341 | INFOPLIST_FILE = "ButtonDemo/ButtonDemo-Info.plist"; 342 | PRODUCT_NAME = "$(TARGET_NAME)"; 343 | WRAPPER_EXTENSION = app; 344 | }; 345 | name = Release; 346 | }; 347 | /* End XCBuildConfiguration section */ 348 | 349 | /* Begin XCConfigurationList section */ 350 | ABECF07C168563CB00BED126 /* Build configuration list for PBXProject "ButtonDemo" */ = { 351 | isa = XCConfigurationList; 352 | buildConfigurations = ( 353 | ABECF09C168563CB00BED126 /* Debug */, 354 | ABECF09D168563CB00BED126 /* Release */, 355 | ); 356 | defaultConfigurationIsVisible = 0; 357 | defaultConfigurationName = Release; 358 | }; 359 | ABECF09E168563CB00BED126 /* Build configuration list for PBXNativeTarget "ButtonDemo" */ = { 360 | isa = XCConfigurationList; 361 | buildConfigurations = ( 362 | ABECF09F168563CB00BED126 /* Debug */, 363 | ABECF0A0168563CB00BED126 /* Release */, 364 | ); 365 | defaultConfigurationIsVisible = 0; 366 | defaultConfigurationName = Release; 367 | }; 368 | /* End XCConfigurationList section */ 369 | }; 370 | rootObject = ABECF079168563CB00BED126 /* Project object */; 371 | } 372 | -------------------------------------------------------------------------------- /Examples/BTRTextField/TextFieldDemo/TextFieldDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 03034021168D880B00697D51 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03034020168D880B00697D51 /* Cocoa.framework */; }; 11 | 0303402B168D880B00697D51 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 03034029168D880B00697D51 /* InfoPlist.strings */; }; 12 | 0303402D168D880B00697D51 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0303402C168D880B00697D51 /* main.m */; }; 13 | 03034031168D880B00697D51 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 0303402F168D880B00697D51 /* Credits.rtf */; }; 14 | 03034034168D880B00697D51 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 03034033168D880B00697D51 /* AppDelegate.m */; }; 15 | 03034037168D880B00697D51 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03034035168D880B00697D51 /* MainMenu.xib */; }; 16 | AB9774D017ED8E6E00810BA9 /* Butter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB9774CD17ED8E6100810BA9 /* Butter.framework */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXContainerItemProxy section */ 20 | AB9774CC17ED8E6100810BA9 /* PBXContainerItemProxy */ = { 21 | isa = PBXContainerItemProxy; 22 | containerPortal = AB9774C817ED8E6000810BA9 /* Butter.xcodeproj */; 23 | proxyType = 2; 24 | remoteGlobalIDString = 03239EB21672E6D6004263D7; 25 | remoteInfo = Butter; 26 | }; 27 | AB9774CE17ED8E6A00810BA9 /* PBXContainerItemProxy */ = { 28 | isa = PBXContainerItemProxy; 29 | containerPortal = AB9774C817ED8E6000810BA9 /* Butter.xcodeproj */; 30 | proxyType = 1; 31 | remoteGlobalIDString = 03239EB11672E6D6004263D7; 32 | remoteInfo = Butter; 33 | }; 34 | /* End PBXContainerItemProxy section */ 35 | 36 | /* Begin PBXFileReference section */ 37 | 0303401D168D880B00697D51 /* TextFieldDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TextFieldDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | 03034020168D880B00697D51 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 39 | 03034023168D880B00697D51 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 40 | 03034024168D880B00697D51 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 41 | 03034025168D880B00697D51 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 42 | 03034028168D880B00697D51 /* TextFieldDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "TextFieldDemo-Info.plist"; sourceTree = ""; }; 43 | 0303402A168D880B00697D51 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 44 | 0303402C168D880B00697D51 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 45 | 0303402E168D880B00697D51 /* TextFieldDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TextFieldDemo-Prefix.pch"; sourceTree = ""; }; 46 | 03034030168D880B00697D51 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; 47 | 03034032168D880B00697D51 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 48 | 03034033168D880B00697D51 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 49 | 03034036168D880B00697D51 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; 50 | AB9774C817ED8E6000810BA9 /* Butter.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Butter.xcodeproj; path = ../../../../Butter.xcodeproj; sourceTree = ""; }; 51 | /* End PBXFileReference section */ 52 | 53 | /* Begin PBXFrameworksBuildPhase section */ 54 | 0303401A168D880B00697D51 /* Frameworks */ = { 55 | isa = PBXFrameworksBuildPhase; 56 | buildActionMask = 2147483647; 57 | files = ( 58 | AB9774D017ED8E6E00810BA9 /* Butter.framework in Frameworks */, 59 | 03034021168D880B00697D51 /* Cocoa.framework in Frameworks */, 60 | ); 61 | runOnlyForDeploymentPostprocessing = 0; 62 | }; 63 | /* End PBXFrameworksBuildPhase section */ 64 | 65 | /* Begin PBXGroup section */ 66 | 03034014168D880B00697D51 = { 67 | isa = PBXGroup; 68 | children = ( 69 | 03034026168D880B00697D51 /* TextFieldDemo */, 70 | 0303401F168D880B00697D51 /* Frameworks */, 71 | 0303401E168D880B00697D51 /* Products */, 72 | ); 73 | sourceTree = ""; 74 | }; 75 | 0303401E168D880B00697D51 /* Products */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | 0303401D168D880B00697D51 /* TextFieldDemo.app */, 79 | ); 80 | name = Products; 81 | sourceTree = ""; 82 | }; 83 | 0303401F168D880B00697D51 /* Frameworks */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | 03034020168D880B00697D51 /* Cocoa.framework */, 87 | 03034022168D880B00697D51 /* Other Frameworks */, 88 | ); 89 | name = Frameworks; 90 | sourceTree = ""; 91 | }; 92 | 03034022168D880B00697D51 /* Other Frameworks */ = { 93 | isa = PBXGroup; 94 | children = ( 95 | 03034023168D880B00697D51 /* AppKit.framework */, 96 | 03034024168D880B00697D51 /* CoreData.framework */, 97 | 03034025168D880B00697D51 /* Foundation.framework */, 98 | ); 99 | name = "Other Frameworks"; 100 | sourceTree = ""; 101 | }; 102 | 03034026168D880B00697D51 /* TextFieldDemo */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | AB9774C817ED8E6000810BA9 /* Butter.xcodeproj */, 106 | 03034032168D880B00697D51 /* AppDelegate.h */, 107 | 03034033168D880B00697D51 /* AppDelegate.m */, 108 | 03034035168D880B00697D51 /* MainMenu.xib */, 109 | 03034027168D880B00697D51 /* Supporting Files */, 110 | ); 111 | path = TextFieldDemo; 112 | sourceTree = ""; 113 | }; 114 | 03034027168D880B00697D51 /* Supporting Files */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | 03034028168D880B00697D51 /* TextFieldDemo-Info.plist */, 118 | 03034029168D880B00697D51 /* InfoPlist.strings */, 119 | 0303402C168D880B00697D51 /* main.m */, 120 | 0303402E168D880B00697D51 /* TextFieldDemo-Prefix.pch */, 121 | 0303402F168D880B00697D51 /* Credits.rtf */, 122 | ); 123 | name = "Supporting Files"; 124 | sourceTree = ""; 125 | }; 126 | AB9774C917ED8E6000810BA9 /* Products */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | AB9774CD17ED8E6100810BA9 /* Butter.framework */, 130 | ); 131 | name = Products; 132 | sourceTree = ""; 133 | }; 134 | /* End PBXGroup section */ 135 | 136 | /* Begin PBXNativeTarget section */ 137 | 0303401C168D880B00697D51 /* TextFieldDemo */ = { 138 | isa = PBXNativeTarget; 139 | buildConfigurationList = 0303403A168D880B00697D51 /* Build configuration list for PBXNativeTarget "TextFieldDemo" */; 140 | buildPhases = ( 141 | 03034019168D880B00697D51 /* Sources */, 142 | 0303401A168D880B00697D51 /* Frameworks */, 143 | 0303401B168D880B00697D51 /* Resources */, 144 | ); 145 | buildRules = ( 146 | ); 147 | dependencies = ( 148 | AB9774CF17ED8E6A00810BA9 /* PBXTargetDependency */, 149 | ); 150 | name = TextFieldDemo; 151 | productName = TextFieldDemo; 152 | productReference = 0303401D168D880B00697D51 /* TextFieldDemo.app */; 153 | productType = "com.apple.product-type.application"; 154 | }; 155 | /* End PBXNativeTarget section */ 156 | 157 | /* Begin PBXProject section */ 158 | 03034015168D880B00697D51 /* Project object */ = { 159 | isa = PBXProject; 160 | attributes = { 161 | LastUpgradeCheck = 0510; 162 | ORGANIZATIONNAME = ButterKit; 163 | }; 164 | buildConfigurationList = 03034018168D880B00697D51 /* Build configuration list for PBXProject "TextFieldDemo" */; 165 | compatibilityVersion = "Xcode 3.2"; 166 | developmentRegion = English; 167 | hasScannedForEncodings = 0; 168 | knownRegions = ( 169 | en, 170 | ); 171 | mainGroup = 03034014168D880B00697D51; 172 | productRefGroup = 0303401E168D880B00697D51 /* Products */; 173 | projectDirPath = ""; 174 | projectReferences = ( 175 | { 176 | ProductGroup = AB9774C917ED8E6000810BA9 /* Products */; 177 | ProjectRef = AB9774C817ED8E6000810BA9 /* Butter.xcodeproj */; 178 | }, 179 | ); 180 | projectRoot = ""; 181 | targets = ( 182 | 0303401C168D880B00697D51 /* TextFieldDemo */, 183 | ); 184 | }; 185 | /* End PBXProject section */ 186 | 187 | /* Begin PBXReferenceProxy section */ 188 | AB9774CD17ED8E6100810BA9 /* Butter.framework */ = { 189 | isa = PBXReferenceProxy; 190 | fileType = wrapper.framework; 191 | path = Butter.framework; 192 | remoteRef = AB9774CC17ED8E6100810BA9 /* PBXContainerItemProxy */; 193 | sourceTree = BUILT_PRODUCTS_DIR; 194 | }; 195 | /* End PBXReferenceProxy section */ 196 | 197 | /* Begin PBXResourcesBuildPhase section */ 198 | 0303401B168D880B00697D51 /* Resources */ = { 199 | isa = PBXResourcesBuildPhase; 200 | buildActionMask = 2147483647; 201 | files = ( 202 | 0303402B168D880B00697D51 /* InfoPlist.strings in Resources */, 203 | 03034031168D880B00697D51 /* Credits.rtf in Resources */, 204 | 03034037168D880B00697D51 /* MainMenu.xib in Resources */, 205 | ); 206 | runOnlyForDeploymentPostprocessing = 0; 207 | }; 208 | /* End PBXResourcesBuildPhase section */ 209 | 210 | /* Begin PBXSourcesBuildPhase section */ 211 | 03034019168D880B00697D51 /* Sources */ = { 212 | isa = PBXSourcesBuildPhase; 213 | buildActionMask = 2147483647; 214 | files = ( 215 | 0303402D168D880B00697D51 /* main.m in Sources */, 216 | 03034034168D880B00697D51 /* AppDelegate.m in Sources */, 217 | ); 218 | runOnlyForDeploymentPostprocessing = 0; 219 | }; 220 | /* End PBXSourcesBuildPhase section */ 221 | 222 | /* Begin PBXTargetDependency section */ 223 | AB9774CF17ED8E6A00810BA9 /* PBXTargetDependency */ = { 224 | isa = PBXTargetDependency; 225 | name = Butter; 226 | targetProxy = AB9774CE17ED8E6A00810BA9 /* PBXContainerItemProxy */; 227 | }; 228 | /* End PBXTargetDependency section */ 229 | 230 | /* Begin PBXVariantGroup section */ 231 | 03034029168D880B00697D51 /* InfoPlist.strings */ = { 232 | isa = PBXVariantGroup; 233 | children = ( 234 | 0303402A168D880B00697D51 /* en */, 235 | ); 236 | name = InfoPlist.strings; 237 | sourceTree = ""; 238 | }; 239 | 0303402F168D880B00697D51 /* Credits.rtf */ = { 240 | isa = PBXVariantGroup; 241 | children = ( 242 | 03034030168D880B00697D51 /* en */, 243 | ); 244 | name = Credits.rtf; 245 | sourceTree = ""; 246 | }; 247 | 03034035168D880B00697D51 /* MainMenu.xib */ = { 248 | isa = PBXVariantGroup; 249 | children = ( 250 | 03034036168D880B00697D51 /* en */, 251 | ); 252 | name = MainMenu.xib; 253 | sourceTree = ""; 254 | }; 255 | /* End PBXVariantGroup section */ 256 | 257 | /* Begin XCBuildConfiguration section */ 258 | 03034038168D880B00697D51 /* Debug */ = { 259 | isa = XCBuildConfiguration; 260 | buildSettings = { 261 | ALWAYS_SEARCH_USER_PATHS = NO; 262 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 263 | CLANG_CXX_LIBRARY = "libc++"; 264 | CLANG_ENABLE_OBJC_ARC = YES; 265 | CLANG_WARN_CONSTANT_CONVERSION = YES; 266 | CLANG_WARN_EMPTY_BODY = YES; 267 | CLANG_WARN_ENUM_CONVERSION = YES; 268 | CLANG_WARN_INT_CONVERSION = YES; 269 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 270 | COPY_PHASE_STRIP = NO; 271 | GCC_C_LANGUAGE_STANDARD = gnu99; 272 | GCC_DYNAMIC_NO_PIC = NO; 273 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 274 | GCC_OPTIMIZATION_LEVEL = 0; 275 | GCC_PREPROCESSOR_DEFINITIONS = ( 276 | "DEBUG=1", 277 | "$(inherited)", 278 | ); 279 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 280 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 281 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 282 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 283 | GCC_WARN_UNUSED_VARIABLE = YES; 284 | MACOSX_DEPLOYMENT_TARGET = 10.8; 285 | ONLY_ACTIVE_ARCH = YES; 286 | SDKROOT = macosx; 287 | }; 288 | name = Debug; 289 | }; 290 | 03034039168D880B00697D51 /* Release */ = { 291 | isa = XCBuildConfiguration; 292 | buildSettings = { 293 | ALWAYS_SEARCH_USER_PATHS = NO; 294 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 295 | CLANG_CXX_LIBRARY = "libc++"; 296 | CLANG_ENABLE_OBJC_ARC = YES; 297 | CLANG_WARN_CONSTANT_CONVERSION = YES; 298 | CLANG_WARN_EMPTY_BODY = YES; 299 | CLANG_WARN_ENUM_CONVERSION = YES; 300 | CLANG_WARN_INT_CONVERSION = YES; 301 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 302 | COPY_PHASE_STRIP = YES; 303 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 304 | GCC_C_LANGUAGE_STANDARD = gnu99; 305 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 306 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 307 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 308 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 309 | GCC_WARN_UNUSED_VARIABLE = YES; 310 | MACOSX_DEPLOYMENT_TARGET = 10.8; 311 | SDKROOT = macosx; 312 | }; 313 | name = Release; 314 | }; 315 | 0303403B168D880B00697D51 /* Debug */ = { 316 | isa = XCBuildConfiguration; 317 | buildSettings = { 318 | COMBINE_HIDPI_IMAGES = YES; 319 | FRAMEWORK_SEARCH_PATHS = ( 320 | "$(inherited)", 321 | "\"$(SRCROOT)/../../../../../../Library/Developer/Xcode/DerivedData/Butter-efnfuzlzcszjexczntjphyuejbht/Build/Products/Debug\"", 322 | ); 323 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 324 | GCC_PREFIX_HEADER = "TextFieldDemo/TextFieldDemo-Prefix.pch"; 325 | INFOPLIST_FILE = "TextFieldDemo/TextFieldDemo-Info.plist"; 326 | PRODUCT_NAME = "$(TARGET_NAME)"; 327 | WRAPPER_EXTENSION = app; 328 | }; 329 | name = Debug; 330 | }; 331 | 0303403C168D880B00697D51 /* Release */ = { 332 | isa = XCBuildConfiguration; 333 | buildSettings = { 334 | COMBINE_HIDPI_IMAGES = YES; 335 | FRAMEWORK_SEARCH_PATHS = ( 336 | "$(inherited)", 337 | "\"$(SRCROOT)/../../../../../../Library/Developer/Xcode/DerivedData/Butter-efnfuzlzcszjexczntjphyuejbht/Build/Products/Debug\"", 338 | ); 339 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 340 | GCC_PREFIX_HEADER = "TextFieldDemo/TextFieldDemo-Prefix.pch"; 341 | INFOPLIST_FILE = "TextFieldDemo/TextFieldDemo-Info.plist"; 342 | PRODUCT_NAME = "$(TARGET_NAME)"; 343 | WRAPPER_EXTENSION = app; 344 | }; 345 | name = Release; 346 | }; 347 | /* End XCBuildConfiguration section */ 348 | 349 | /* Begin XCConfigurationList section */ 350 | 03034018168D880B00697D51 /* Build configuration list for PBXProject "TextFieldDemo" */ = { 351 | isa = XCConfigurationList; 352 | buildConfigurations = ( 353 | 03034038168D880B00697D51 /* Debug */, 354 | 03034039168D880B00697D51 /* Release */, 355 | ); 356 | defaultConfigurationIsVisible = 0; 357 | defaultConfigurationName = Release; 358 | }; 359 | 0303403A168D880B00697D51 /* Build configuration list for PBXNativeTarget "TextFieldDemo" */ = { 360 | isa = XCConfigurationList; 361 | buildConfigurations = ( 362 | 0303403B168D880B00697D51 /* Debug */, 363 | 0303403C168D880B00697D51 /* Release */, 364 | ); 365 | defaultConfigurationIsVisible = 0; 366 | defaultConfigurationName = Release; 367 | }; 368 | /* End XCConfigurationList section */ 369 | }; 370 | rootObject = 03034015168D880B00697D51 /* Project object */; 371 | } 372 | -------------------------------------------------------------------------------- /Examples/BTRControl/ControlEvents/ControlEvents.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | AB9774C717ED8D6100810BA9 /* Butter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB9774C417ED8D5400810BA9 /* Butter.framework */; }; 11 | ABB9D753167BF0F100ECB31D /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ABB9D752167BF0F100ECB31D /* Cocoa.framework */; }; 12 | ABB9D75D167BF0F100ECB31D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = ABB9D75B167BF0F100ECB31D /* InfoPlist.strings */; }; 13 | ABB9D75F167BF0F100ECB31D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = ABB9D75E167BF0F100ECB31D /* main.m */; }; 14 | ABB9D763167BF0F100ECB31D /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = ABB9D761167BF0F100ECB31D /* Credits.rtf */; }; 15 | ABB9D766167BF0F100ECB31D /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = ABB9D765167BF0F100ECB31D /* AppDelegate.m */; }; 16 | ABB9D769167BF0F100ECB31D /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = ABB9D767167BF0F100ECB31D /* MainMenu.xib */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXContainerItemProxy section */ 20 | AB9774C317ED8D5400810BA9 /* PBXContainerItemProxy */ = { 21 | isa = PBXContainerItemProxy; 22 | containerPortal = AB9774BF17ED8D5400810BA9 /* Butter.xcodeproj */; 23 | proxyType = 2; 24 | remoteGlobalIDString = 03239EB21672E6D6004263D7; 25 | remoteInfo = Butter; 26 | }; 27 | AB9774C517ED8D5D00810BA9 /* PBXContainerItemProxy */ = { 28 | isa = PBXContainerItemProxy; 29 | containerPortal = AB9774BF17ED8D5400810BA9 /* Butter.xcodeproj */; 30 | proxyType = 1; 31 | remoteGlobalIDString = 03239EB11672E6D6004263D7; 32 | remoteInfo = Butter; 33 | }; 34 | /* End PBXContainerItemProxy section */ 35 | 36 | /* Begin PBXFileReference section */ 37 | AB9774BF17ED8D5400810BA9 /* Butter.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Butter.xcodeproj; path = ../../../../Butter.xcodeproj; sourceTree = ""; }; 38 | ABB9D74F167BF0F100ECB31D /* ControlEvents.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ControlEvents.app; sourceTree = BUILT_PRODUCTS_DIR; }; 39 | ABB9D752167BF0F100ECB31D /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 40 | ABB9D755167BF0F100ECB31D /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 41 | ABB9D756167BF0F100ECB31D /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 42 | ABB9D757167BF0F100ECB31D /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 43 | ABB9D75A167BF0F100ECB31D /* ControlEvents-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ControlEvents-Info.plist"; sourceTree = ""; }; 44 | ABB9D75C167BF0F100ECB31D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 45 | ABB9D75E167BF0F100ECB31D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 46 | ABB9D760167BF0F100ECB31D /* ControlEvents-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ControlEvents-Prefix.pch"; sourceTree = ""; }; 47 | ABB9D762167BF0F100ECB31D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; 48 | ABB9D764167BF0F100ECB31D /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 49 | ABB9D765167BF0F100ECB31D /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 50 | ABB9D768167BF0F100ECB31D /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; 51 | /* End PBXFileReference section */ 52 | 53 | /* Begin PBXFrameworksBuildPhase section */ 54 | ABB9D74C167BF0F100ECB31D /* Frameworks */ = { 55 | isa = PBXFrameworksBuildPhase; 56 | buildActionMask = 2147483647; 57 | files = ( 58 | AB9774C717ED8D6100810BA9 /* Butter.framework in Frameworks */, 59 | ABB9D753167BF0F100ECB31D /* Cocoa.framework in Frameworks */, 60 | ); 61 | runOnlyForDeploymentPostprocessing = 0; 62 | }; 63 | /* End PBXFrameworksBuildPhase section */ 64 | 65 | /* Begin PBXGroup section */ 66 | AB9774C017ED8D5400810BA9 /* Products */ = { 67 | isa = PBXGroup; 68 | children = ( 69 | AB9774C417ED8D5400810BA9 /* Butter.framework */, 70 | ); 71 | name = Products; 72 | sourceTree = ""; 73 | }; 74 | ABB9D746167BF0F000ECB31D = { 75 | isa = PBXGroup; 76 | children = ( 77 | ABB9D758167BF0F100ECB31D /* ControlEvents */, 78 | ABB9D751167BF0F100ECB31D /* Frameworks */, 79 | ABB9D750167BF0F100ECB31D /* Products */, 80 | ); 81 | sourceTree = ""; 82 | }; 83 | ABB9D750167BF0F100ECB31D /* Products */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | ABB9D74F167BF0F100ECB31D /* ControlEvents.app */, 87 | ); 88 | name = Products; 89 | sourceTree = ""; 90 | }; 91 | ABB9D751167BF0F100ECB31D /* Frameworks */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | ABB9D752167BF0F100ECB31D /* Cocoa.framework */, 95 | ABB9D754167BF0F100ECB31D /* Other Frameworks */, 96 | ); 97 | name = Frameworks; 98 | sourceTree = ""; 99 | }; 100 | ABB9D754167BF0F100ECB31D /* Other Frameworks */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | ABB9D755167BF0F100ECB31D /* AppKit.framework */, 104 | ABB9D756167BF0F100ECB31D /* CoreData.framework */, 105 | ABB9D757167BF0F100ECB31D /* Foundation.framework */, 106 | ); 107 | name = "Other Frameworks"; 108 | sourceTree = ""; 109 | }; 110 | ABB9D758167BF0F100ECB31D /* ControlEvents */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | AB9774BF17ED8D5400810BA9 /* Butter.xcodeproj */, 114 | ABB9D764167BF0F100ECB31D /* AppDelegate.h */, 115 | ABB9D765167BF0F100ECB31D /* AppDelegate.m */, 116 | ABB9D767167BF0F100ECB31D /* MainMenu.xib */, 117 | ABB9D759167BF0F100ECB31D /* Supporting Files */, 118 | ); 119 | path = ControlEvents; 120 | sourceTree = ""; 121 | }; 122 | ABB9D759167BF0F100ECB31D /* Supporting Files */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | ABB9D75A167BF0F100ECB31D /* ControlEvents-Info.plist */, 126 | ABB9D75B167BF0F100ECB31D /* InfoPlist.strings */, 127 | ABB9D75E167BF0F100ECB31D /* main.m */, 128 | ABB9D760167BF0F100ECB31D /* ControlEvents-Prefix.pch */, 129 | ABB9D761167BF0F100ECB31D /* Credits.rtf */, 130 | ); 131 | name = "Supporting Files"; 132 | sourceTree = ""; 133 | }; 134 | /* End PBXGroup section */ 135 | 136 | /* Begin PBXNativeTarget section */ 137 | ABB9D74E167BF0F100ECB31D /* ControlEvents */ = { 138 | isa = PBXNativeTarget; 139 | buildConfigurationList = ABB9D76C167BF0F100ECB31D /* Build configuration list for PBXNativeTarget "ControlEvents" */; 140 | buildPhases = ( 141 | ABB9D74B167BF0F100ECB31D /* Sources */, 142 | ABB9D74C167BF0F100ECB31D /* Frameworks */, 143 | ABB9D74D167BF0F100ECB31D /* Resources */, 144 | ); 145 | buildRules = ( 146 | ); 147 | dependencies = ( 148 | AB9774C617ED8D5D00810BA9 /* PBXTargetDependency */, 149 | ); 150 | name = ControlEvents; 151 | productName = ControlEvents; 152 | productReference = ABB9D74F167BF0F100ECB31D /* ControlEvents.app */; 153 | productType = "com.apple.product-type.application"; 154 | }; 155 | /* End PBXNativeTarget section */ 156 | 157 | /* Begin PBXProject section */ 158 | ABB9D747167BF0F000ECB31D /* Project object */ = { 159 | isa = PBXProject; 160 | attributes = { 161 | LastUpgradeCheck = 0510; 162 | ORGANIZATIONNAME = ButterKit; 163 | }; 164 | buildConfigurationList = ABB9D74A167BF0F000ECB31D /* Build configuration list for PBXProject "ControlEvents" */; 165 | compatibilityVersion = "Xcode 3.2"; 166 | developmentRegion = English; 167 | hasScannedForEncodings = 0; 168 | knownRegions = ( 169 | en, 170 | ); 171 | mainGroup = ABB9D746167BF0F000ECB31D; 172 | productRefGroup = ABB9D750167BF0F100ECB31D /* Products */; 173 | projectDirPath = ""; 174 | projectReferences = ( 175 | { 176 | ProductGroup = AB9774C017ED8D5400810BA9 /* Products */; 177 | ProjectRef = AB9774BF17ED8D5400810BA9 /* Butter.xcodeproj */; 178 | }, 179 | ); 180 | projectRoot = ""; 181 | targets = ( 182 | ABB9D74E167BF0F100ECB31D /* ControlEvents */, 183 | ); 184 | }; 185 | /* End PBXProject section */ 186 | 187 | /* Begin PBXReferenceProxy section */ 188 | AB9774C417ED8D5400810BA9 /* Butter.framework */ = { 189 | isa = PBXReferenceProxy; 190 | fileType = wrapper.framework; 191 | path = Butter.framework; 192 | remoteRef = AB9774C317ED8D5400810BA9 /* PBXContainerItemProxy */; 193 | sourceTree = BUILT_PRODUCTS_DIR; 194 | }; 195 | /* End PBXReferenceProxy section */ 196 | 197 | /* Begin PBXResourcesBuildPhase section */ 198 | ABB9D74D167BF0F100ECB31D /* Resources */ = { 199 | isa = PBXResourcesBuildPhase; 200 | buildActionMask = 2147483647; 201 | files = ( 202 | ABB9D75D167BF0F100ECB31D /* InfoPlist.strings in Resources */, 203 | ABB9D763167BF0F100ECB31D /* Credits.rtf in Resources */, 204 | ABB9D769167BF0F100ECB31D /* MainMenu.xib in Resources */, 205 | ); 206 | runOnlyForDeploymentPostprocessing = 0; 207 | }; 208 | /* End PBXResourcesBuildPhase section */ 209 | 210 | /* Begin PBXSourcesBuildPhase section */ 211 | ABB9D74B167BF0F100ECB31D /* Sources */ = { 212 | isa = PBXSourcesBuildPhase; 213 | buildActionMask = 2147483647; 214 | files = ( 215 | ABB9D75F167BF0F100ECB31D /* main.m in Sources */, 216 | ABB9D766167BF0F100ECB31D /* AppDelegate.m in Sources */, 217 | ); 218 | runOnlyForDeploymentPostprocessing = 0; 219 | }; 220 | /* End PBXSourcesBuildPhase section */ 221 | 222 | /* Begin PBXTargetDependency section */ 223 | AB9774C617ED8D5D00810BA9 /* PBXTargetDependency */ = { 224 | isa = PBXTargetDependency; 225 | name = Butter; 226 | targetProxy = AB9774C517ED8D5D00810BA9 /* PBXContainerItemProxy */; 227 | }; 228 | /* End PBXTargetDependency section */ 229 | 230 | /* Begin PBXVariantGroup section */ 231 | ABB9D75B167BF0F100ECB31D /* InfoPlist.strings */ = { 232 | isa = PBXVariantGroup; 233 | children = ( 234 | ABB9D75C167BF0F100ECB31D /* en */, 235 | ); 236 | name = InfoPlist.strings; 237 | sourceTree = ""; 238 | }; 239 | ABB9D761167BF0F100ECB31D /* Credits.rtf */ = { 240 | isa = PBXVariantGroup; 241 | children = ( 242 | ABB9D762167BF0F100ECB31D /* en */, 243 | ); 244 | name = Credits.rtf; 245 | sourceTree = ""; 246 | }; 247 | ABB9D767167BF0F100ECB31D /* MainMenu.xib */ = { 248 | isa = PBXVariantGroup; 249 | children = ( 250 | ABB9D768167BF0F100ECB31D /* en */, 251 | ); 252 | name = MainMenu.xib; 253 | sourceTree = ""; 254 | }; 255 | /* End PBXVariantGroup section */ 256 | 257 | /* Begin XCBuildConfiguration section */ 258 | ABB9D76A167BF0F100ECB31D /* Debug */ = { 259 | isa = XCBuildConfiguration; 260 | buildSettings = { 261 | ALWAYS_SEARCH_USER_PATHS = NO; 262 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 263 | CLANG_CXX_LIBRARY = "libc++"; 264 | CLANG_ENABLE_OBJC_ARC = YES; 265 | CLANG_WARN_CONSTANT_CONVERSION = YES; 266 | CLANG_WARN_EMPTY_BODY = YES; 267 | CLANG_WARN_ENUM_CONVERSION = YES; 268 | CLANG_WARN_INT_CONVERSION = YES; 269 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 270 | COPY_PHASE_STRIP = NO; 271 | GCC_C_LANGUAGE_STANDARD = gnu99; 272 | GCC_DYNAMIC_NO_PIC = NO; 273 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 274 | GCC_OPTIMIZATION_LEVEL = 0; 275 | GCC_PREPROCESSOR_DEFINITIONS = ( 276 | "DEBUG=1", 277 | "$(inherited)", 278 | ); 279 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 280 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 281 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 282 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 283 | GCC_WARN_UNUSED_VARIABLE = YES; 284 | MACOSX_DEPLOYMENT_TARGET = 10.8; 285 | ONLY_ACTIVE_ARCH = YES; 286 | SDKROOT = macosx; 287 | }; 288 | name = Debug; 289 | }; 290 | ABB9D76B167BF0F100ECB31D /* Release */ = { 291 | isa = XCBuildConfiguration; 292 | buildSettings = { 293 | ALWAYS_SEARCH_USER_PATHS = NO; 294 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 295 | CLANG_CXX_LIBRARY = "libc++"; 296 | CLANG_ENABLE_OBJC_ARC = YES; 297 | CLANG_WARN_CONSTANT_CONVERSION = YES; 298 | CLANG_WARN_EMPTY_BODY = YES; 299 | CLANG_WARN_ENUM_CONVERSION = YES; 300 | CLANG_WARN_INT_CONVERSION = YES; 301 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 302 | COPY_PHASE_STRIP = YES; 303 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 304 | GCC_C_LANGUAGE_STANDARD = gnu99; 305 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 306 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 307 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 308 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 309 | GCC_WARN_UNUSED_VARIABLE = YES; 310 | MACOSX_DEPLOYMENT_TARGET = 10.8; 311 | SDKROOT = macosx; 312 | }; 313 | name = Release; 314 | }; 315 | ABB9D76D167BF0F100ECB31D /* Debug */ = { 316 | isa = XCBuildConfiguration; 317 | buildSettings = { 318 | COMBINE_HIDPI_IMAGES = YES; 319 | FRAMEWORK_SEARCH_PATHS = ( 320 | "$(inherited)", 321 | "\"$(SRCROOT)/../../../../../../../../../Library/Developer/Xcode/DerivedData/Butter-gqoqbeasmoutbjeyiuunhmhydaex/Build/Products/Debug\"", 322 | ); 323 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 324 | GCC_PREFIX_HEADER = "ControlEvents/ControlEvents-Prefix.pch"; 325 | INFOPLIST_FILE = "ControlEvents/ControlEvents-Info.plist"; 326 | PRODUCT_NAME = "$(TARGET_NAME)"; 327 | WRAPPER_EXTENSION = app; 328 | }; 329 | name = Debug; 330 | }; 331 | ABB9D76E167BF0F100ECB31D /* Release */ = { 332 | isa = XCBuildConfiguration; 333 | buildSettings = { 334 | COMBINE_HIDPI_IMAGES = YES; 335 | FRAMEWORK_SEARCH_PATHS = ( 336 | "$(inherited)", 337 | "\"$(SRCROOT)/../../../../../../../../../Library/Developer/Xcode/DerivedData/Butter-gqoqbeasmoutbjeyiuunhmhydaex/Build/Products/Debug\"", 338 | ); 339 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 340 | GCC_PREFIX_HEADER = "ControlEvents/ControlEvents-Prefix.pch"; 341 | INFOPLIST_FILE = "ControlEvents/ControlEvents-Info.plist"; 342 | PRODUCT_NAME = "$(TARGET_NAME)"; 343 | WRAPPER_EXTENSION = app; 344 | }; 345 | name = Release; 346 | }; 347 | /* End XCBuildConfiguration section */ 348 | 349 | /* Begin XCConfigurationList section */ 350 | ABB9D74A167BF0F000ECB31D /* Build configuration list for PBXProject "ControlEvents" */ = { 351 | isa = XCConfigurationList; 352 | buildConfigurations = ( 353 | ABB9D76A167BF0F100ECB31D /* Debug */, 354 | ABB9D76B167BF0F100ECB31D /* Release */, 355 | ); 356 | defaultConfigurationIsVisible = 0; 357 | defaultConfigurationName = Release; 358 | }; 359 | ABB9D76C167BF0F100ECB31D /* Build configuration list for PBXNativeTarget "ControlEvents" */ = { 360 | isa = XCConfigurationList; 361 | buildConfigurations = ( 362 | ABB9D76D167BF0F100ECB31D /* Debug */, 363 | ABB9D76E167BF0F100ECB31D /* Release */, 364 | ); 365 | defaultConfigurationIsVisible = 0; 366 | defaultConfigurationName = Release; 367 | }; 368 | /* End XCConfigurationList section */ 369 | }; 370 | rootObject = ABB9D747167BF0F000ECB31D /* Project object */; 371 | } 372 | -------------------------------------------------------------------------------- /Examples/BTRImageView/ImageView Test/ImageView Test.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | AB00F1D316A4F20700096C91 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB00F1D216A4F20700096C91 /* Cocoa.framework */; }; 11 | AB00F1DD16A4F20700096C91 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = AB00F1DB16A4F20700096C91 /* InfoPlist.strings */; }; 12 | AB00F1DF16A4F20700096C91 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = AB00F1DE16A4F20700096C91 /* main.m */; }; 13 | AB00F1E316A4F20700096C91 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = AB00F1E116A4F20700096C91 /* Credits.rtf */; }; 14 | AB00F1E616A4F20700096C91 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = AB00F1E516A4F20700096C91 /* AppDelegate.m */; }; 15 | AB00F1E916A4F20800096C91 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB00F1E716A4F20800096C91 /* MainMenu.xib */; }; 16 | AB9774E217ED8EB300810BA9 /* Butter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB9774DF17ED8EA800810BA9 /* Butter.framework */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXContainerItemProxy section */ 20 | AB9774DE17ED8EA800810BA9 /* PBXContainerItemProxy */ = { 21 | isa = PBXContainerItemProxy; 22 | containerPortal = AB9774DA17ED8EA800810BA9 /* Butter.xcodeproj */; 23 | proxyType = 2; 24 | remoteGlobalIDString = 03239EB21672E6D6004263D7; 25 | remoteInfo = Butter; 26 | }; 27 | AB9774E017ED8EB000810BA9 /* PBXContainerItemProxy */ = { 28 | isa = PBXContainerItemProxy; 29 | containerPortal = AB9774DA17ED8EA800810BA9 /* Butter.xcodeproj */; 30 | proxyType = 1; 31 | remoteGlobalIDString = 03239EB11672E6D6004263D7; 32 | remoteInfo = Butter; 33 | }; 34 | /* End PBXContainerItemProxy section */ 35 | 36 | /* Begin PBXFileReference section */ 37 | AB00F1CF16A4F20700096C91 /* ImageView Test.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ImageView Test.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | AB00F1D216A4F20700096C91 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 39 | AB00F1D516A4F20700096C91 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 40 | AB00F1D616A4F20700096C91 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 41 | AB00F1D716A4F20700096C91 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 42 | AB00F1DA16A4F20700096C91 /* ImageView Test-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ImageView Test-Info.plist"; sourceTree = ""; }; 43 | AB00F1DC16A4F20700096C91 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 44 | AB00F1DE16A4F20700096C91 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 45 | AB00F1E016A4F20700096C91 /* ImageView Test-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ImageView Test-Prefix.pch"; sourceTree = ""; }; 46 | AB00F1E216A4F20700096C91 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; 47 | AB00F1E416A4F20700096C91 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 48 | AB00F1E516A4F20700096C91 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 49 | AB00F1E816A4F20800096C91 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; 50 | AB9774DA17ED8EA800810BA9 /* Butter.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Butter.xcodeproj; path = ../../../../Butter.xcodeproj; sourceTree = ""; }; 51 | /* End PBXFileReference section */ 52 | 53 | /* Begin PBXFrameworksBuildPhase section */ 54 | AB00F1CC16A4F20700096C91 /* Frameworks */ = { 55 | isa = PBXFrameworksBuildPhase; 56 | buildActionMask = 2147483647; 57 | files = ( 58 | AB9774E217ED8EB300810BA9 /* Butter.framework in Frameworks */, 59 | AB00F1D316A4F20700096C91 /* Cocoa.framework in Frameworks */, 60 | ); 61 | runOnlyForDeploymentPostprocessing = 0; 62 | }; 63 | /* End PBXFrameworksBuildPhase section */ 64 | 65 | /* Begin PBXGroup section */ 66 | AB00F1C616A4F20700096C91 = { 67 | isa = PBXGroup; 68 | children = ( 69 | AB00F1D816A4F20700096C91 /* ImageView Test */, 70 | AB00F1D116A4F20700096C91 /* Frameworks */, 71 | AB00F1D016A4F20700096C91 /* Products */, 72 | ); 73 | sourceTree = ""; 74 | }; 75 | AB00F1D016A4F20700096C91 /* Products */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | AB00F1CF16A4F20700096C91 /* ImageView Test.app */, 79 | ); 80 | name = Products; 81 | sourceTree = ""; 82 | }; 83 | AB00F1D116A4F20700096C91 /* Frameworks */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | AB00F1D216A4F20700096C91 /* Cocoa.framework */, 87 | AB00F1D416A4F20700096C91 /* Other Frameworks */, 88 | ); 89 | name = Frameworks; 90 | sourceTree = ""; 91 | }; 92 | AB00F1D416A4F20700096C91 /* Other Frameworks */ = { 93 | isa = PBXGroup; 94 | children = ( 95 | AB00F1D516A4F20700096C91 /* AppKit.framework */, 96 | AB00F1D616A4F20700096C91 /* CoreData.framework */, 97 | AB00F1D716A4F20700096C91 /* Foundation.framework */, 98 | ); 99 | name = "Other Frameworks"; 100 | sourceTree = ""; 101 | }; 102 | AB00F1D816A4F20700096C91 /* ImageView Test */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | AB9774DA17ED8EA800810BA9 /* Butter.xcodeproj */, 106 | AB00F1E416A4F20700096C91 /* AppDelegate.h */, 107 | AB00F1E516A4F20700096C91 /* AppDelegate.m */, 108 | AB00F1E716A4F20800096C91 /* MainMenu.xib */, 109 | AB00F1D916A4F20700096C91 /* Supporting Files */, 110 | ); 111 | path = "ImageView Test"; 112 | sourceTree = ""; 113 | }; 114 | AB00F1D916A4F20700096C91 /* Supporting Files */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | AB00F1DA16A4F20700096C91 /* ImageView Test-Info.plist */, 118 | AB00F1DB16A4F20700096C91 /* InfoPlist.strings */, 119 | AB00F1DE16A4F20700096C91 /* main.m */, 120 | AB00F1E016A4F20700096C91 /* ImageView Test-Prefix.pch */, 121 | AB00F1E116A4F20700096C91 /* Credits.rtf */, 122 | ); 123 | name = "Supporting Files"; 124 | sourceTree = ""; 125 | }; 126 | AB9774DB17ED8EA800810BA9 /* Products */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | AB9774DF17ED8EA800810BA9 /* Butter.framework */, 130 | ); 131 | name = Products; 132 | sourceTree = ""; 133 | }; 134 | /* End PBXGroup section */ 135 | 136 | /* Begin PBXNativeTarget section */ 137 | AB00F1CE16A4F20700096C91 /* ImageView Test */ = { 138 | isa = PBXNativeTarget; 139 | buildConfigurationList = AB00F1EC16A4F20800096C91 /* Build configuration list for PBXNativeTarget "ImageView Test" */; 140 | buildPhases = ( 141 | AB00F1CB16A4F20700096C91 /* Sources */, 142 | AB00F1CC16A4F20700096C91 /* Frameworks */, 143 | AB00F1CD16A4F20700096C91 /* Resources */, 144 | ); 145 | buildRules = ( 146 | ); 147 | dependencies = ( 148 | AB9774E117ED8EB000810BA9 /* PBXTargetDependency */, 149 | ); 150 | name = "ImageView Test"; 151 | productName = "ImageView Test"; 152 | productReference = AB00F1CF16A4F20700096C91 /* ImageView Test.app */; 153 | productType = "com.apple.product-type.application"; 154 | }; 155 | /* End PBXNativeTarget section */ 156 | 157 | /* Begin PBXProject section */ 158 | AB00F1C716A4F20700096C91 /* Project object */ = { 159 | isa = PBXProject; 160 | attributes = { 161 | LastUpgradeCheck = 0510; 162 | ORGANIZATIONNAME = Butter; 163 | }; 164 | buildConfigurationList = AB00F1CA16A4F20700096C91 /* Build configuration list for PBXProject "ImageView Test" */; 165 | compatibilityVersion = "Xcode 3.2"; 166 | developmentRegion = English; 167 | hasScannedForEncodings = 0; 168 | knownRegions = ( 169 | en, 170 | ); 171 | mainGroup = AB00F1C616A4F20700096C91; 172 | productRefGroup = AB00F1D016A4F20700096C91 /* Products */; 173 | projectDirPath = ""; 174 | projectReferences = ( 175 | { 176 | ProductGroup = AB9774DB17ED8EA800810BA9 /* Products */; 177 | ProjectRef = AB9774DA17ED8EA800810BA9 /* Butter.xcodeproj */; 178 | }, 179 | ); 180 | projectRoot = ""; 181 | targets = ( 182 | AB00F1CE16A4F20700096C91 /* ImageView Test */, 183 | ); 184 | }; 185 | /* End PBXProject section */ 186 | 187 | /* Begin PBXReferenceProxy section */ 188 | AB9774DF17ED8EA800810BA9 /* Butter.framework */ = { 189 | isa = PBXReferenceProxy; 190 | fileType = wrapper.framework; 191 | path = Butter.framework; 192 | remoteRef = AB9774DE17ED8EA800810BA9 /* PBXContainerItemProxy */; 193 | sourceTree = BUILT_PRODUCTS_DIR; 194 | }; 195 | /* End PBXReferenceProxy section */ 196 | 197 | /* Begin PBXResourcesBuildPhase section */ 198 | AB00F1CD16A4F20700096C91 /* Resources */ = { 199 | isa = PBXResourcesBuildPhase; 200 | buildActionMask = 2147483647; 201 | files = ( 202 | AB00F1DD16A4F20700096C91 /* InfoPlist.strings in Resources */, 203 | AB00F1E316A4F20700096C91 /* Credits.rtf in Resources */, 204 | AB00F1E916A4F20800096C91 /* MainMenu.xib in Resources */, 205 | ); 206 | runOnlyForDeploymentPostprocessing = 0; 207 | }; 208 | /* End PBXResourcesBuildPhase section */ 209 | 210 | /* Begin PBXSourcesBuildPhase section */ 211 | AB00F1CB16A4F20700096C91 /* Sources */ = { 212 | isa = PBXSourcesBuildPhase; 213 | buildActionMask = 2147483647; 214 | files = ( 215 | AB00F1DF16A4F20700096C91 /* main.m in Sources */, 216 | AB00F1E616A4F20700096C91 /* AppDelegate.m in Sources */, 217 | ); 218 | runOnlyForDeploymentPostprocessing = 0; 219 | }; 220 | /* End PBXSourcesBuildPhase section */ 221 | 222 | /* Begin PBXTargetDependency section */ 223 | AB9774E117ED8EB000810BA9 /* PBXTargetDependency */ = { 224 | isa = PBXTargetDependency; 225 | name = Butter; 226 | targetProxy = AB9774E017ED8EB000810BA9 /* PBXContainerItemProxy */; 227 | }; 228 | /* End PBXTargetDependency section */ 229 | 230 | /* Begin PBXVariantGroup section */ 231 | AB00F1DB16A4F20700096C91 /* InfoPlist.strings */ = { 232 | isa = PBXVariantGroup; 233 | children = ( 234 | AB00F1DC16A4F20700096C91 /* en */, 235 | ); 236 | name = InfoPlist.strings; 237 | sourceTree = ""; 238 | }; 239 | AB00F1E116A4F20700096C91 /* Credits.rtf */ = { 240 | isa = PBXVariantGroup; 241 | children = ( 242 | AB00F1E216A4F20700096C91 /* en */, 243 | ); 244 | name = Credits.rtf; 245 | sourceTree = ""; 246 | }; 247 | AB00F1E716A4F20800096C91 /* MainMenu.xib */ = { 248 | isa = PBXVariantGroup; 249 | children = ( 250 | AB00F1E816A4F20800096C91 /* en */, 251 | ); 252 | name = MainMenu.xib; 253 | sourceTree = ""; 254 | }; 255 | /* End PBXVariantGroup section */ 256 | 257 | /* Begin XCBuildConfiguration section */ 258 | AB00F1EA16A4F20800096C91 /* Debug */ = { 259 | isa = XCBuildConfiguration; 260 | buildSettings = { 261 | ALWAYS_SEARCH_USER_PATHS = NO; 262 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 263 | CLANG_CXX_LIBRARY = "libc++"; 264 | CLANG_ENABLE_OBJC_ARC = YES; 265 | CLANG_WARN_CONSTANT_CONVERSION = YES; 266 | CLANG_WARN_EMPTY_BODY = YES; 267 | CLANG_WARN_ENUM_CONVERSION = YES; 268 | CLANG_WARN_INT_CONVERSION = YES; 269 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 270 | COPY_PHASE_STRIP = NO; 271 | GCC_C_LANGUAGE_STANDARD = gnu99; 272 | GCC_DYNAMIC_NO_PIC = NO; 273 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 274 | GCC_OPTIMIZATION_LEVEL = 0; 275 | GCC_PREPROCESSOR_DEFINITIONS = ( 276 | "DEBUG=1", 277 | "$(inherited)", 278 | ); 279 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 280 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 281 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 282 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 283 | GCC_WARN_UNUSED_VARIABLE = YES; 284 | MACOSX_DEPLOYMENT_TARGET = 10.8; 285 | ONLY_ACTIVE_ARCH = YES; 286 | SDKROOT = macosx; 287 | }; 288 | name = Debug; 289 | }; 290 | AB00F1EB16A4F20800096C91 /* Release */ = { 291 | isa = XCBuildConfiguration; 292 | buildSettings = { 293 | ALWAYS_SEARCH_USER_PATHS = NO; 294 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 295 | CLANG_CXX_LIBRARY = "libc++"; 296 | CLANG_ENABLE_OBJC_ARC = YES; 297 | CLANG_WARN_CONSTANT_CONVERSION = YES; 298 | CLANG_WARN_EMPTY_BODY = YES; 299 | CLANG_WARN_ENUM_CONVERSION = YES; 300 | CLANG_WARN_INT_CONVERSION = YES; 301 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 302 | COPY_PHASE_STRIP = YES; 303 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 304 | GCC_C_LANGUAGE_STANDARD = gnu99; 305 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 306 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 307 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 308 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 309 | GCC_WARN_UNUSED_VARIABLE = YES; 310 | MACOSX_DEPLOYMENT_TARGET = 10.8; 311 | SDKROOT = macosx; 312 | }; 313 | name = Release; 314 | }; 315 | AB00F1ED16A4F20800096C91 /* Debug */ = { 316 | isa = XCBuildConfiguration; 317 | buildSettings = { 318 | COMBINE_HIDPI_IMAGES = YES; 319 | FRAMEWORK_SEARCH_PATHS = ( 320 | "$(inherited)", 321 | "\"$(SRCROOT)/../../../../../../../../../Library/Developer/Xcode/DerivedData/Butter-gqoqbeasmoutbjeyiuunhmhydaex/Build/Products/Debug\"", 322 | ); 323 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 324 | GCC_PREFIX_HEADER = "ImageView Test/ImageView Test-Prefix.pch"; 325 | INFOPLIST_FILE = "ImageView Test/ImageView Test-Info.plist"; 326 | PRODUCT_NAME = "$(TARGET_NAME)"; 327 | WRAPPER_EXTENSION = app; 328 | }; 329 | name = Debug; 330 | }; 331 | AB00F1EE16A4F20800096C91 /* Release */ = { 332 | isa = XCBuildConfiguration; 333 | buildSettings = { 334 | COMBINE_HIDPI_IMAGES = YES; 335 | FRAMEWORK_SEARCH_PATHS = ( 336 | "$(inherited)", 337 | "\"$(SRCROOT)/../../../../../../../../../Library/Developer/Xcode/DerivedData/Butter-gqoqbeasmoutbjeyiuunhmhydaex/Build/Products/Debug\"", 338 | ); 339 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 340 | GCC_PREFIX_HEADER = "ImageView Test/ImageView Test-Prefix.pch"; 341 | INFOPLIST_FILE = "ImageView Test/ImageView Test-Info.plist"; 342 | PRODUCT_NAME = "$(TARGET_NAME)"; 343 | WRAPPER_EXTENSION = app; 344 | }; 345 | name = Release; 346 | }; 347 | /* End XCBuildConfiguration section */ 348 | 349 | /* Begin XCConfigurationList section */ 350 | AB00F1CA16A4F20700096C91 /* Build configuration list for PBXProject "ImageView Test" */ = { 351 | isa = XCConfigurationList; 352 | buildConfigurations = ( 353 | AB00F1EA16A4F20800096C91 /* Debug */, 354 | AB00F1EB16A4F20800096C91 /* Release */, 355 | ); 356 | defaultConfigurationIsVisible = 0; 357 | defaultConfigurationName = Release; 358 | }; 359 | AB00F1EC16A4F20800096C91 /* Build configuration list for PBXNativeTarget "ImageView Test" */ = { 360 | isa = XCConfigurationList; 361 | buildConfigurations = ( 362 | AB00F1ED16A4F20800096C91 /* Debug */, 363 | AB00F1EE16A4F20800096C91 /* Release */, 364 | ); 365 | defaultConfigurationIsVisible = 0; 366 | defaultConfigurationName = Release; 367 | }; 368 | /* End XCConfigurationList section */ 369 | }; 370 | rootObject = AB00F1C716A4F20700096C91 /* Project object */; 371 | } 372 | -------------------------------------------------------------------------------- /Examples/BTRPopUpButton/Popup Button Demo/Popup Button Demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | AB799687169146CD00B1FF7E /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB799686169146CC00B1FF7E /* Cocoa.framework */; }; 11 | AB799691169146CD00B1FF7E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = AB79968F169146CD00B1FF7E /* InfoPlist.strings */; }; 12 | AB799693169146CD00B1FF7E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = AB799692169146CD00B1FF7E /* main.m */; }; 13 | AB799697169146CD00B1FF7E /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = AB799695169146CD00B1FF7E /* Credits.rtf */; }; 14 | AB79969A169146CD00B1FF7E /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = AB799699169146CD00B1FF7E /* AppDelegate.m */; }; 15 | AB79969D169146CD00B1FF7E /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB79969B169146CD00B1FF7E /* MainMenu.xib */; }; 16 | AB9774D917ED8E9200810BA9 /* Butter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB9774D617ED8E8700810BA9 /* Butter.framework */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXContainerItemProxy section */ 20 | AB9774D517ED8E8700810BA9 /* PBXContainerItemProxy */ = { 21 | isa = PBXContainerItemProxy; 22 | containerPortal = AB9774D117ED8E8700810BA9 /* Butter.xcodeproj */; 23 | proxyType = 2; 24 | remoteGlobalIDString = 03239EB21672E6D6004263D7; 25 | remoteInfo = Butter; 26 | }; 27 | AB9774D717ED8E8F00810BA9 /* PBXContainerItemProxy */ = { 28 | isa = PBXContainerItemProxy; 29 | containerPortal = AB9774D117ED8E8700810BA9 /* Butter.xcodeproj */; 30 | proxyType = 1; 31 | remoteGlobalIDString = 03239EB11672E6D6004263D7; 32 | remoteInfo = Butter; 33 | }; 34 | /* End PBXContainerItemProxy section */ 35 | 36 | /* Begin PBXFileReference section */ 37 | AB799683169146CC00B1FF7E /* Popup Button Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Popup Button Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | AB799686169146CC00B1FF7E /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 39 | AB799689169146CD00B1FF7E /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 40 | AB79968A169146CD00B1FF7E /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 41 | AB79968B169146CD00B1FF7E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 42 | AB79968E169146CD00B1FF7E /* Popup Button Demo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Popup Button Demo-Info.plist"; sourceTree = ""; }; 43 | AB799690169146CD00B1FF7E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 44 | AB799692169146CD00B1FF7E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 45 | AB799694169146CD00B1FF7E /* Popup Button Demo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Popup Button Demo-Prefix.pch"; sourceTree = ""; }; 46 | AB799696169146CD00B1FF7E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; 47 | AB799698169146CD00B1FF7E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 48 | AB799699169146CD00B1FF7E /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 49 | AB79969C169146CD00B1FF7E /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; 50 | AB9774D117ED8E8700810BA9 /* Butter.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Butter.xcodeproj; path = ../../../../Butter.xcodeproj; sourceTree = ""; }; 51 | /* End PBXFileReference section */ 52 | 53 | /* Begin PBXFrameworksBuildPhase section */ 54 | AB799680169146CC00B1FF7E /* Frameworks */ = { 55 | isa = PBXFrameworksBuildPhase; 56 | buildActionMask = 2147483647; 57 | files = ( 58 | AB9774D917ED8E9200810BA9 /* Butter.framework in Frameworks */, 59 | AB799687169146CD00B1FF7E /* Cocoa.framework in Frameworks */, 60 | ); 61 | runOnlyForDeploymentPostprocessing = 0; 62 | }; 63 | /* End PBXFrameworksBuildPhase section */ 64 | 65 | /* Begin PBXGroup section */ 66 | AB79967A169146CC00B1FF7E = { 67 | isa = PBXGroup; 68 | children = ( 69 | AB79968C169146CD00B1FF7E /* Popup Button Demo */, 70 | AB799685169146CC00B1FF7E /* Frameworks */, 71 | AB799684169146CC00B1FF7E /* Products */, 72 | ); 73 | sourceTree = ""; 74 | }; 75 | AB799684169146CC00B1FF7E /* Products */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | AB799683169146CC00B1FF7E /* Popup Button Demo.app */, 79 | ); 80 | name = Products; 81 | sourceTree = ""; 82 | }; 83 | AB799685169146CC00B1FF7E /* Frameworks */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | AB799686169146CC00B1FF7E /* Cocoa.framework */, 87 | AB799688169146CD00B1FF7E /* Other Frameworks */, 88 | ); 89 | name = Frameworks; 90 | sourceTree = ""; 91 | }; 92 | AB799688169146CD00B1FF7E /* Other Frameworks */ = { 93 | isa = PBXGroup; 94 | children = ( 95 | AB799689169146CD00B1FF7E /* AppKit.framework */, 96 | AB79968A169146CD00B1FF7E /* CoreData.framework */, 97 | AB79968B169146CD00B1FF7E /* Foundation.framework */, 98 | ); 99 | name = "Other Frameworks"; 100 | sourceTree = ""; 101 | }; 102 | AB79968C169146CD00B1FF7E /* Popup Button Demo */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | AB9774D117ED8E8700810BA9 /* Butter.xcodeproj */, 106 | AB799698169146CD00B1FF7E /* AppDelegate.h */, 107 | AB799699169146CD00B1FF7E /* AppDelegate.m */, 108 | AB79969B169146CD00B1FF7E /* MainMenu.xib */, 109 | AB79968D169146CD00B1FF7E /* Supporting Files */, 110 | ); 111 | path = "Popup Button Demo"; 112 | sourceTree = ""; 113 | }; 114 | AB79968D169146CD00B1FF7E /* Supporting Files */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | AB79968E169146CD00B1FF7E /* Popup Button Demo-Info.plist */, 118 | AB79968F169146CD00B1FF7E /* InfoPlist.strings */, 119 | AB799692169146CD00B1FF7E /* main.m */, 120 | AB799694169146CD00B1FF7E /* Popup Button Demo-Prefix.pch */, 121 | AB799695169146CD00B1FF7E /* Credits.rtf */, 122 | ); 123 | name = "Supporting Files"; 124 | sourceTree = ""; 125 | }; 126 | AB9774D217ED8E8700810BA9 /* Products */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | AB9774D617ED8E8700810BA9 /* Butter.framework */, 130 | ); 131 | name = Products; 132 | sourceTree = ""; 133 | }; 134 | /* End PBXGroup section */ 135 | 136 | /* Begin PBXNativeTarget section */ 137 | AB799682169146CC00B1FF7E /* Popup Button Demo */ = { 138 | isa = PBXNativeTarget; 139 | buildConfigurationList = AB7996A0169146CD00B1FF7E /* Build configuration list for PBXNativeTarget "Popup Button Demo" */; 140 | buildPhases = ( 141 | AB79967F169146CC00B1FF7E /* Sources */, 142 | AB799680169146CC00B1FF7E /* Frameworks */, 143 | AB799681169146CC00B1FF7E /* Resources */, 144 | ); 145 | buildRules = ( 146 | ); 147 | dependencies = ( 148 | AB9774D817ED8E8F00810BA9 /* PBXTargetDependency */, 149 | ); 150 | name = "Popup Button Demo"; 151 | productName = "Popup Button Demo"; 152 | productReference = AB799683169146CC00B1FF7E /* Popup Button Demo.app */; 153 | productType = "com.apple.product-type.application"; 154 | }; 155 | /* End PBXNativeTarget section */ 156 | 157 | /* Begin PBXProject section */ 158 | AB79967B169146CC00B1FF7E /* Project object */ = { 159 | isa = PBXProject; 160 | attributes = { 161 | LastUpgradeCheck = 0510; 162 | ORGANIZATIONNAME = Butter; 163 | }; 164 | buildConfigurationList = AB79967E169146CC00B1FF7E /* Build configuration list for PBXProject "Popup Button Demo" */; 165 | compatibilityVersion = "Xcode 3.2"; 166 | developmentRegion = English; 167 | hasScannedForEncodings = 0; 168 | knownRegions = ( 169 | en, 170 | ); 171 | mainGroup = AB79967A169146CC00B1FF7E; 172 | productRefGroup = AB799684169146CC00B1FF7E /* Products */; 173 | projectDirPath = ""; 174 | projectReferences = ( 175 | { 176 | ProductGroup = AB9774D217ED8E8700810BA9 /* Products */; 177 | ProjectRef = AB9774D117ED8E8700810BA9 /* Butter.xcodeproj */; 178 | }, 179 | ); 180 | projectRoot = ""; 181 | targets = ( 182 | AB799682169146CC00B1FF7E /* Popup Button Demo */, 183 | ); 184 | }; 185 | /* End PBXProject section */ 186 | 187 | /* Begin PBXReferenceProxy section */ 188 | AB9774D617ED8E8700810BA9 /* Butter.framework */ = { 189 | isa = PBXReferenceProxy; 190 | fileType = wrapper.framework; 191 | path = Butter.framework; 192 | remoteRef = AB9774D517ED8E8700810BA9 /* PBXContainerItemProxy */; 193 | sourceTree = BUILT_PRODUCTS_DIR; 194 | }; 195 | /* End PBXReferenceProxy section */ 196 | 197 | /* Begin PBXResourcesBuildPhase section */ 198 | AB799681169146CC00B1FF7E /* Resources */ = { 199 | isa = PBXResourcesBuildPhase; 200 | buildActionMask = 2147483647; 201 | files = ( 202 | AB799691169146CD00B1FF7E /* InfoPlist.strings in Resources */, 203 | AB799697169146CD00B1FF7E /* Credits.rtf in Resources */, 204 | AB79969D169146CD00B1FF7E /* MainMenu.xib in Resources */, 205 | ); 206 | runOnlyForDeploymentPostprocessing = 0; 207 | }; 208 | /* End PBXResourcesBuildPhase section */ 209 | 210 | /* Begin PBXSourcesBuildPhase section */ 211 | AB79967F169146CC00B1FF7E /* Sources */ = { 212 | isa = PBXSourcesBuildPhase; 213 | buildActionMask = 2147483647; 214 | files = ( 215 | AB799693169146CD00B1FF7E /* main.m in Sources */, 216 | AB79969A169146CD00B1FF7E /* AppDelegate.m in Sources */, 217 | ); 218 | runOnlyForDeploymentPostprocessing = 0; 219 | }; 220 | /* End PBXSourcesBuildPhase section */ 221 | 222 | /* Begin PBXTargetDependency section */ 223 | AB9774D817ED8E8F00810BA9 /* PBXTargetDependency */ = { 224 | isa = PBXTargetDependency; 225 | name = Butter; 226 | targetProxy = AB9774D717ED8E8F00810BA9 /* PBXContainerItemProxy */; 227 | }; 228 | /* End PBXTargetDependency section */ 229 | 230 | /* Begin PBXVariantGroup section */ 231 | AB79968F169146CD00B1FF7E /* InfoPlist.strings */ = { 232 | isa = PBXVariantGroup; 233 | children = ( 234 | AB799690169146CD00B1FF7E /* en */, 235 | ); 236 | name = InfoPlist.strings; 237 | sourceTree = ""; 238 | }; 239 | AB799695169146CD00B1FF7E /* Credits.rtf */ = { 240 | isa = PBXVariantGroup; 241 | children = ( 242 | AB799696169146CD00B1FF7E /* en */, 243 | ); 244 | name = Credits.rtf; 245 | sourceTree = ""; 246 | }; 247 | AB79969B169146CD00B1FF7E /* MainMenu.xib */ = { 248 | isa = PBXVariantGroup; 249 | children = ( 250 | AB79969C169146CD00B1FF7E /* en */, 251 | ); 252 | name = MainMenu.xib; 253 | sourceTree = ""; 254 | }; 255 | /* End PBXVariantGroup section */ 256 | 257 | /* Begin XCBuildConfiguration section */ 258 | AB79969E169146CD00B1FF7E /* Debug */ = { 259 | isa = XCBuildConfiguration; 260 | buildSettings = { 261 | ALWAYS_SEARCH_USER_PATHS = NO; 262 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 263 | CLANG_CXX_LIBRARY = "libc++"; 264 | CLANG_ENABLE_OBJC_ARC = YES; 265 | CLANG_WARN_CONSTANT_CONVERSION = YES; 266 | CLANG_WARN_EMPTY_BODY = YES; 267 | CLANG_WARN_ENUM_CONVERSION = YES; 268 | CLANG_WARN_INT_CONVERSION = YES; 269 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 270 | COPY_PHASE_STRIP = NO; 271 | GCC_C_LANGUAGE_STANDARD = gnu99; 272 | GCC_DYNAMIC_NO_PIC = NO; 273 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 274 | GCC_OPTIMIZATION_LEVEL = 0; 275 | GCC_PREPROCESSOR_DEFINITIONS = ( 276 | "DEBUG=1", 277 | "$(inherited)", 278 | ); 279 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 280 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 281 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 282 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 283 | GCC_WARN_UNUSED_VARIABLE = YES; 284 | MACOSX_DEPLOYMENT_TARGET = 10.8; 285 | ONLY_ACTIVE_ARCH = YES; 286 | SDKROOT = macosx; 287 | }; 288 | name = Debug; 289 | }; 290 | AB79969F169146CD00B1FF7E /* Release */ = { 291 | isa = XCBuildConfiguration; 292 | buildSettings = { 293 | ALWAYS_SEARCH_USER_PATHS = NO; 294 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 295 | CLANG_CXX_LIBRARY = "libc++"; 296 | CLANG_ENABLE_OBJC_ARC = YES; 297 | CLANG_WARN_CONSTANT_CONVERSION = YES; 298 | CLANG_WARN_EMPTY_BODY = YES; 299 | CLANG_WARN_ENUM_CONVERSION = YES; 300 | CLANG_WARN_INT_CONVERSION = YES; 301 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 302 | COPY_PHASE_STRIP = YES; 303 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 304 | GCC_C_LANGUAGE_STANDARD = gnu99; 305 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 306 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 307 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 308 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 309 | GCC_WARN_UNUSED_VARIABLE = YES; 310 | MACOSX_DEPLOYMENT_TARGET = 10.8; 311 | SDKROOT = macosx; 312 | }; 313 | name = Release; 314 | }; 315 | AB7996A1169146CD00B1FF7E /* Debug */ = { 316 | isa = XCBuildConfiguration; 317 | buildSettings = { 318 | COMBINE_HIDPI_IMAGES = YES; 319 | FRAMEWORK_SEARCH_PATHS = ( 320 | "$(inherited)", 321 | "\"$(SRCROOT)/../../../../../../../../../Library/Developer/Xcode/DerivedData/Butter-gqoqbeasmoutbjeyiuunhmhydaex/Build/Products/Debug\"", 322 | ); 323 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 324 | GCC_PREFIX_HEADER = "Popup Button Demo/Popup Button Demo-Prefix.pch"; 325 | INFOPLIST_FILE = "Popup Button Demo/Popup Button Demo-Info.plist"; 326 | PRODUCT_NAME = "$(TARGET_NAME)"; 327 | WRAPPER_EXTENSION = app; 328 | }; 329 | name = Debug; 330 | }; 331 | AB7996A2169146CD00B1FF7E /* Release */ = { 332 | isa = XCBuildConfiguration; 333 | buildSettings = { 334 | COMBINE_HIDPI_IMAGES = YES; 335 | FRAMEWORK_SEARCH_PATHS = ( 336 | "$(inherited)", 337 | "\"$(SRCROOT)/../../../../../../../../../Library/Developer/Xcode/DerivedData/Butter-gqoqbeasmoutbjeyiuunhmhydaex/Build/Products/Debug\"", 338 | ); 339 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 340 | GCC_PREFIX_HEADER = "Popup Button Demo/Popup Button Demo-Prefix.pch"; 341 | INFOPLIST_FILE = "Popup Button Demo/Popup Button Demo-Info.plist"; 342 | PRODUCT_NAME = "$(TARGET_NAME)"; 343 | WRAPPER_EXTENSION = app; 344 | }; 345 | name = Release; 346 | }; 347 | /* End XCBuildConfiguration section */ 348 | 349 | /* Begin XCConfigurationList section */ 350 | AB79967E169146CC00B1FF7E /* Build configuration list for PBXProject "Popup Button Demo" */ = { 351 | isa = XCConfigurationList; 352 | buildConfigurations = ( 353 | AB79969E169146CD00B1FF7E /* Debug */, 354 | AB79969F169146CD00B1FF7E /* Release */, 355 | ); 356 | defaultConfigurationIsVisible = 0; 357 | defaultConfigurationName = Release; 358 | }; 359 | AB7996A0169146CD00B1FF7E /* Build configuration list for PBXNativeTarget "Popup Button Demo" */ = { 360 | isa = XCConfigurationList; 361 | buildConfigurations = ( 362 | AB7996A1169146CD00B1FF7E /* Debug */, 363 | AB7996A2169146CD00B1FF7E /* Release */, 364 | ); 365 | defaultConfigurationIsVisible = 0; 366 | defaultConfigurationName = Release; 367 | }; 368 | /* End XCConfigurationList section */ 369 | }; 370 | rootObject = AB79967B169146CC00B1FF7E /* Project object */; 371 | } 372 | --------------------------------------------------------------------------------