├── .gitignore ├── .gitmodules ├── ExampleProject ├── Example.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata └── Example │ ├── Example-Info.plist │ ├── Example-Prefix.pch │ ├── ExampleAppDelegate.h │ ├── ExampleAppDelegate.m │ ├── ExampleScrollView.h │ ├── ExampleScrollView.m │ ├── ExampleSectionHeaderView.h │ ├── ExampleSectionHeaderView.m │ ├── ExampleTabBar.h │ ├── ExampleTabBar.m │ ├── ExampleTableViewCell.h │ ├── ExampleTableViewCell.m │ ├── ExampleView.h │ ├── ExampleView.m │ ├── clock.png │ ├── clock@2x.png │ ├── en.lproj │ ├── Credits.rtf │ ├── InfoPlist.strings │ └── MainMenu.xib │ ├── large-image.jpeg │ └── main.m ├── LICENSE.txt ├── README.md ├── Resources ├── TwUI-Info.plist ├── TwUI-Prefix.pch └── en.lproj │ └── InfoPlist.strings ├── TwUI.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ ├── Dynamic Library.xcscheme │ ├── Static Library.xcscheme │ └── TwUI.xcscheme ├── TwUITests ├── TwUITests-Info.plist ├── TwUITests-Prefix.pch ├── TwUITests.m └── en.lproj │ └── InfoPlist.strings ├── docs ├── .gitignore └── Doxyfile ├── extras └── TwUI Presentation.zip └── lib ├── Support ├── ABActiveRange.h ├── ABActiveRange.m ├── CAAnimation+TUIExtensions.h ├── CAAnimation+TUIExtensions.m ├── CALayer+TUIExtensions.h ├── CALayer+TUIExtensions.m ├── CATransaction+TUIExtensions.h ├── CATransaction+TUIExtensions.m ├── CoreText+Additions.h ├── CoreText+Additions.m ├── NSFont+TUIExtensions.h ├── NSFont+TUIExtensions.m ├── TUICAAction.h └── TUICAAction.m └── UIKit ├── NSClipView+TUIExtensions.h ├── NSClipView+TUIExtensions.m ├── NSColor+TUIExtensions.h ├── NSColor+TUIExtensions.m ├── NSImage+TUIExtensions.h ├── NSImage+TUIExtensions.m ├── NSScrollView+TUIExtensions.h ├── NSScrollView+TUIExtensions.m ├── NSView+TUIExtensions.h ├── NSView+TUIExtensions.m ├── TUIAccessibility.h ├── TUIAccessibility.m ├── TUIActivityIndicatorView.h ├── TUIActivityIndicatorView.m ├── TUIAttributedString.h ├── TUIAttributedString.m ├── TUIBridgedScrollView.h ├── TUIBridgedView.h ├── TUIButton+Accessibility.h ├── TUIButton+Accessibility.m ├── TUIButton+Content.m ├── TUIButton.h ├── TUIButton.m ├── TUICGAdditions.h ├── TUICGAdditions.m ├── TUIControl+Accessibility.h ├── TUIControl+Accessibility.m ├── TUIControl+Private.h ├── TUIControl+Private.m ├── TUIControl+TargetAction.m ├── TUIControl.h ├── TUIControl.m ├── TUIGeometry.h ├── TUIGeometry.m ├── TUIHostView.h ├── TUIImageView.h ├── TUIImageView.m ├── TUIKit.h ├── TUILabel.h ├── TUILabel.m ├── TUILayoutConstraint.h ├── TUILayoutConstraint.m ├── TUILayoutManager.h ├── TUILayoutManager.m ├── TUINSView+Accessibility.h ├── TUINSView+Accessibility.m ├── TUINSView+Hyperfocus.h ├── TUINSView+Hyperfocus.m ├── TUINSView+NSTextInputClient.h ├── TUINSView+NSTextInputClient.m ├── TUINSView+Private.h ├── TUINSView.h ├── TUINSView.m ├── TUINSWindow.h ├── TUINSWindow.m ├── TUIPopover.h ├── TUIPopover.m ├── TUIProgressBar.h ├── TUIProgressBar.m ├── TUIResponder.h ├── TUIResponder.m ├── TUIScrollKnob.h ├── TUIScrollKnob.m ├── TUIScrollView+TUIBridgedScrollView.h ├── TUIScrollView+TUIBridgedScrollView.m ├── TUIScrollView.h ├── TUIScrollView.m ├── TUIStretchableImage.h ├── TUIStretchableImage.m ├── TUIStringDrawing.h ├── TUIStringDrawing.m ├── TUITableView+Additions.h ├── TUITableView+Additions.m ├── TUITableView+Cell.h ├── TUITableView+Cell.m ├── TUITableView+Derepeater.h ├── TUITableView+Derepeater.m ├── TUITableView.h ├── TUITableView.m ├── TUITableViewCell.h ├── TUITableViewCell.m ├── TUITableViewController.h ├── TUITableViewController.m ├── TUITableViewSectionHeader.h ├── TUITableViewSectionHeader.m ├── TUITextEditor.h ├── TUITextEditor.m ├── TUITextField.h ├── TUITextField.m ├── TUITextRenderer+Accessibility.h ├── TUITextRenderer+Accessibility.m ├── TUITextRenderer+Event.h ├── TUITextRenderer+Event.m ├── TUITextRenderer+KeyBindings.m ├── TUITextRenderer+Private.h ├── TUITextRenderer.h ├── TUITextRenderer.m ├── TUITextView.h ├── TUITextView.m ├── TUITextViewEditor.h ├── TUITextViewEditor.m ├── TUITooltipWindow.h ├── TUITooltipWindow.m ├── TUIView+Accessibility.h ├── TUIView+Accessibility.m ├── TUIView+Animation.m ├── TUIView+Event.h ├── TUIView+Event.m ├── TUIView+Layout.h ├── TUIView+Layout.m ├── TUIView+PasteboardDragging.h ├── TUIView+PasteboardDragging.m ├── TUIView+Private.h ├── TUIView+TUIBridgedView.h ├── TUIView+TUIBridgedView.m ├── TUIView.h ├── TUIView.m ├── TUIViewController.h ├── TUIViewController.m ├── TUIViewNSViewContainer+Private.h ├── TUIViewNSViewContainer.h └── TUIViewNSViewContainer.m /.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | xcuserdata 3 | *.mode1v3 4 | *.pbxuser 5 | build 6 | *.perspectivev3 7 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "TwUITests/expecta"] 2 | path = TwUITests/expecta 3 | url = git://github.com/github/expecta.git 4 | [submodule "TwUITests/specta"] 5 | path = TwUITests/specta 6 | url = git://github.com/specta/specta.git 7 | -------------------------------------------------------------------------------- /ExampleProject/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ExampleProject/Example/Example-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.example.${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 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /ExampleProject/Example/Example-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'ConcordeExample' target in the 'ConcordeExample' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /ExampleProject/Example/ExampleAppDelegate.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import 18 | #import "TUIKit.h" 19 | 20 | @interface ExampleAppDelegate : NSObject 21 | { 22 | NSWindow * tableViewWindow; 23 | NSWindow * scrollViewWindow; 24 | } 25 | 26 | -(IBAction)showTableViewExampleWindow:(id)sender; 27 | -(IBAction)showScrollViewExampleWindow:(id)sender; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /ExampleProject/Example/ExampleAppDelegate.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "ExampleAppDelegate.h" 18 | #import "ExampleView.h" 19 | #import "ExampleScrollView.h" 20 | 21 | @implementation ExampleAppDelegate 22 | 23 | 24 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 25 | { 26 | CGRect b = CGRectMake(0, 0, 500, 450); 27 | 28 | /** Table View */ 29 | tableViewWindow = [[NSWindow alloc] initWithContentRect:b styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask backing:NSBackingStoreBuffered defer:NO]; 30 | [tableViewWindow setReleasedWhenClosed:FALSE]; 31 | [tableViewWindow setMinSize:NSMakeSize(300, 250)]; 32 | [tableViewWindow center]; 33 | 34 | /* TUINSView is the bridge between the standard AppKit NSView-based heirarchy and the TUIView-based heirarchy */ 35 | TUINSView *tuiTableViewContainer = [[TUINSView alloc] initWithFrame:b]; 36 | [tableViewWindow setContentView:tuiTableViewContainer]; 37 | 38 | ExampleView *tableExample = [[ExampleView alloc] initWithFrame:b]; 39 | tuiTableViewContainer.rootView = tableExample; 40 | 41 | /** Scroll View */ 42 | scrollViewWindow = [[NSWindow alloc] initWithContentRect:b styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask backing:NSBackingStoreBuffered defer:YES]; 43 | [scrollViewWindow setReleasedWhenClosed:FALSE]; 44 | [scrollViewWindow setMinSize:NSMakeSize(300, 250)]; 45 | [scrollViewWindow setFrameTopLeftPoint:[tableViewWindow cascadeTopLeftFromPoint:CGPointMake(tableViewWindow.frame.origin.x, tableViewWindow.frame.origin.y + tableViewWindow.frame.size.height)]]; 46 | 47 | /* TUINSView is the bridge between the standard AppKit NSView-based heirarchy and the TUIView-based heirarchy */ 48 | TUINSView *tuiScrollViewContainer = [[TUINSView alloc] initWithFrame:b]; 49 | [scrollViewWindow setContentView:tuiScrollViewContainer]; 50 | 51 | ExampleScrollView *scrollExample = [[ExampleScrollView alloc] initWithFrame:b]; 52 | tuiScrollViewContainer.rootView = scrollExample; 53 | 54 | [self showTableViewExampleWindow:nil]; 55 | 56 | } 57 | 58 | /** 59 | * @brief Show the table view example 60 | */ 61 | -(IBAction)showTableViewExampleWindow:(id)sender { 62 | [tableViewWindow makeKeyAndOrderFront:sender]; 63 | } 64 | 65 | /** 66 | * @brief Show the scroll view example 67 | */ 68 | -(IBAction)showScrollViewExampleWindow:(id)sender { 69 | [scrollViewWindow makeKeyAndOrderFront:sender]; 70 | } 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /ExampleProject/Example/ExampleScrollView.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIKit.h" 18 | #import "ExampleTabBar.h" 19 | 20 | @interface ExampleScrollView : TUIView 21 | { 22 | TUIScrollView * _scrollView; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /ExampleProject/Example/ExampleScrollView.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "ExampleScrollView.h" 18 | 19 | @implementation ExampleScrollView 20 | 21 | - (id)initWithFrame:(CGRect)frame 22 | { 23 | if((self = [super initWithFrame:frame])) { 24 | self.backgroundColor = [NSColor colorWithCalibratedWhite:0.9 alpha:1.0]; 25 | 26 | _scrollView = [[TUIScrollView alloc] initWithFrame:self.bounds]; 27 | _scrollView.autoresizingMask = TUIViewAutoresizingFlexibleSize; 28 | _scrollView.scrollIndicatorStyle = TUIScrollViewIndicatorStyleDark; 29 | [self addSubview:_scrollView]; 30 | 31 | TUIImageView *imageView = [[TUIImageView alloc] initWithImage:[NSImage imageNamed:@"large-image.jpeg"]]; 32 | [_scrollView addSubview:imageView]; 33 | [_scrollView setContentSize:imageView.frame.size]; 34 | 35 | } 36 | return self; 37 | } 38 | 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /ExampleProject/Example/ExampleSectionHeaderView.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "TUIKit.h" 4 | 5 | @interface ExampleSectionHeaderView : TUITableViewSectionHeader { 6 | 7 | TUITextRenderer * _labelRenderer; 8 | 9 | } 10 | 11 | @property (readonly) TUITextRenderer * labelRenderer; 12 | 13 | @end 14 | 15 | -------------------------------------------------------------------------------- /ExampleProject/Example/ExampleSectionHeaderView.m: -------------------------------------------------------------------------------- 1 | #import "ExampleSectionHeaderView.h" 2 | 3 | @implementation ExampleSectionHeaderView 4 | 5 | @synthesize labelRenderer = _labelRenderer; 6 | 7 | /** 8 | * Clean up 9 | */ 10 | 11 | /** 12 | * Initialize 13 | */ 14 | -(id)initWithFrame:(CGRect)frame { 15 | if((self = [super initWithFrame:frame])) { 16 | _labelRenderer = [[TUITextRenderer alloc] init]; 17 | self.textRenderers = [NSArray arrayWithObjects:_labelRenderer, nil]; 18 | self.opaque = TRUE; 19 | } 20 | return self; 21 | } 22 | 23 | /** 24 | * @brief The header will become pinned 25 | */ 26 | -(void)headerWillBecomePinned { 27 | self.opaque = FALSE; 28 | [super headerWillBecomePinned]; 29 | } 30 | 31 | /** 32 | * @brief The header will become unpinned 33 | */ 34 | -(void)headerWillBecomeUnpinned { 35 | self.opaque = TRUE; 36 | [super headerWillBecomeUnpinned]; 37 | } 38 | 39 | /** 40 | * Drawing 41 | */ 42 | -(void)drawRect:(CGRect)rect { 43 | 44 | CGContextRef g; 45 | if((g = TUIGraphicsGetCurrentContext()) != nil){ 46 | [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:g flipped:FALSE]]; 47 | 48 | if(!self.pinnedToViewport){ 49 | [[NSColor whiteColor] set]; 50 | NSRectFill(self.bounds); 51 | } 52 | 53 | NSColor *start = [NSColor colorWithCalibratedRed:0.8 green:0.8 blue:0.8 alpha:0.9]; 54 | NSColor *end = [NSColor colorWithCalibratedRed:0.9 green:0.9 blue:0.9 alpha:0.9]; 55 | NSGradient *gradient = nil; 56 | 57 | gradient = [[NSGradient alloc] initWithStartingColor:start endingColor:end]; 58 | [gradient drawInRect:self.bounds angle:90]; 59 | 60 | [[start shadowWithLevel:0.1] set]; 61 | NSRectFill(NSMakeRect(0, 0, self.bounds.size.width, 1)); 62 | 63 | CGFloat labelHeight = 18; 64 | self.labelRenderer.frame = CGRectMake(15, roundf((self.bounds.size.height - labelHeight) / 2.0), self.bounds.size.width - 30, labelHeight); 65 | [self.labelRenderer draw]; 66 | 67 | } 68 | 69 | } 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /ExampleProject/Example/ExampleTabBar.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIKit.h" 18 | 19 | @class ExampleTabBar; 20 | 21 | @protocol ExampleTabBarDelegate 22 | @required 23 | - (void)tabBar:(ExampleTabBar *)tabBar didSelectTab:(NSInteger)index; 24 | @end 25 | 26 | /* 27 | An example of how to build a custom UI control, in this case a simple tab bar 28 | */ 29 | 30 | @interface ExampleTabBar : TUIView 31 | { 32 | id __unsafe_unretained delegate; 33 | NSArray *tabViews; 34 | } 35 | 36 | - (id)initWithNumberOfTabs:(NSInteger)nTabs; 37 | 38 | @property (nonatomic, unsafe_unretained) id delegate; 39 | @property (nonatomic, readonly) NSArray *tabViews; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /ExampleProject/Example/ExampleTableViewCell.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIKit.h" 18 | 19 | @interface ExampleTableViewCell : TUITableViewCell 20 | { 21 | TUITextRenderer *textRenderer; 22 | } 23 | 24 | @property (nonatomic, copy) NSAttributedString *attributedString; 25 | @property (nonatomic, strong) TUIView *textFieldContainer; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /ExampleProject/Example/ExampleTableViewCell.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "ExampleTableViewCell.h" 18 | 19 | @implementation ExampleTableViewCell 20 | 21 | - (id)initWithStyle:(TUITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 22 | { 23 | if((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) { 24 | textRenderer = [[TUITextRenderer alloc] init]; 25 | 26 | /* 27 | Add the text renderer to the view so events get routed to it properly. 28 | Text selection, dictionary popup, etc should just work. 29 | You can add more than one. 30 | 31 | The text renderer encapsulates an attributed string and a frame. 32 | The attributed string in this case is set by setAttributedString: 33 | which is configured by the table view delegate. The frame needs to be 34 | set before it can be drawn, we do that in drawRect: below. 35 | */ 36 | self.textRenderers = [NSArray arrayWithObjects:textRenderer, nil]; 37 | 38 | NSTextField *textField = [[NSTextField alloc] initWithFrame:NSMakeRect(20, 180, 91, 22)]; 39 | [textField.cell setUsesSingleLineMode:YES]; 40 | [textField.cell setScrollable:YES]; 41 | 42 | self.textFieldContainer = [[TUIViewNSViewContainer alloc] initWithNSView:textField]; 43 | self.textFieldContainer.backgroundColor = [NSColor blueColor]; 44 | [self addSubview:self.textFieldContainer]; 45 | } 46 | return self; 47 | } 48 | 49 | - (void)layoutSubviews { 50 | [super layoutSubviews]; 51 | 52 | CGSize textFieldSize = self.textFieldContainer.bounds.size; 53 | CGFloat textFieldLeft = CGRectGetWidth(self.bounds) - textFieldSize.width - 16; 54 | 55 | self.textFieldContainer.frame = CGRectMake(textFieldLeft, 14, textFieldSize.width, textFieldSize.height); 56 | } 57 | 58 | - (NSAttributedString *)attributedString 59 | { 60 | return textRenderer.attributedString; 61 | } 62 | 63 | - (void)setAttributedString:(NSAttributedString *)attributedString 64 | { 65 | textRenderer.attributedString = attributedString; 66 | [self setNeedsDisplay]; 67 | } 68 | 69 | - (void)drawRect:(CGRect)rect 70 | { 71 | CGRect b = self.bounds; 72 | CGContextRef ctx = TUIGraphicsGetCurrentContext(); 73 | 74 | if(self.selected) { 75 | // selected background 76 | CGContextSetRGBFillColor(ctx, .87, .87, .87, 1); 77 | CGContextFillRect(ctx, b); 78 | } else { 79 | // light gray background 80 | CGContextSetRGBFillColor(ctx, .97, .97, .97, 1); 81 | CGContextFillRect(ctx, b); 82 | 83 | // emboss 84 | CGContextSetRGBFillColor(ctx, 1, 1, 1, 0.9); // light at the top 85 | CGContextFillRect(ctx, CGRectMake(0, b.size.height-1, b.size.width, 1)); 86 | CGContextSetRGBFillColor(ctx, 0, 0, 0, 0.08); // dark at the bottom 87 | CGContextFillRect(ctx, CGRectMake(0, 0, b.size.width, 1)); 88 | } 89 | 90 | // text 91 | CGRect textRect = CGRectOffset(b, 15, -15); 92 | textRenderer.frame = textRect; // set the frame so it knows where to draw itself 93 | [textRenderer draw]; 94 | 95 | } 96 | 97 | @end 98 | -------------------------------------------------------------------------------- /ExampleProject/Example/ExampleView.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIKit.h" 18 | #import "ExampleTabBar.h" 19 | 20 | @interface ExampleView : TUIView 21 | { 22 | TUITableView *_tableView; 23 | ExampleTabBar *_tabBar; 24 | 25 | NSFont *exampleFont1; 26 | NSFont *exampleFont2; 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /ExampleProject/Example/clock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/twui/cd68dd45000bf3daf65428edffe577655897943f/ExampleProject/Example/clock.png -------------------------------------------------------------------------------- /ExampleProject/Example/clock@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/twui/cd68dd45000bf3daf65428edffe577655897943f/ExampleProject/Example/clock@2x.png -------------------------------------------------------------------------------- /ExampleProject/Example/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 | -------------------------------------------------------------------------------- /ExampleProject/Example/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /ExampleProject/Example/large-image.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/twui/cd68dd45000bf3daf65428edffe577655897943f/ExampleProject/Example/large-image.jpeg -------------------------------------------------------------------------------- /ExampleProject/Example/main.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import 18 | #import "TUIKit.h" 19 | 20 | /* 21 | Notes: 22 | In your project, add NS_BUILD_32_LIKE_64 to your preprocessor flags 23 | */ 24 | 25 | int main(int argc, char *argv[]) 26 | { 27 | return NSApplicationMain(argc, (const char **)argv); 28 | } 29 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2011 Twitter, Inc. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | 15 | ----------------- 16 | 17 | Code from the Velvet framework is used in TwUI. 18 | Velvet is copyright (c) 2012, Bitswift, Inc. 19 | 20 | All rights reserved. 21 | 22 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 23 | 24 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 25 | * Neither the name of the Bitswift, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 26 | 27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TwUI 2 | 3 | TwUI is a hardware accelerated UI framework for Mac, inspired by UIKit. It enables: 4 | 5 | * GPU accelerated rendering backed by CoreAnimation 6 | * Simple model/view/controller development familiar to iOS developers 7 | 8 | It differs from UIKit in a few ways: 9 | 10 | * Simplified table view cells 11 | * Block-based layout and drawRect 12 | * A consistent coordinate system (bottom left origin) 13 | * Sub-pixel text rendering 14 | 15 | # Setup 16 | 17 | To use the current development version, include all the files in your project and import TUIKit.h. Set your target to link to the ApplicationServices and QuartzCore frameworks. 18 | 19 | # Usage 20 | 21 | Your `TUIView`-based view hierarchy is hosted inside an `TUINSView`, which is the bridge between AppKit and TwUI. You may set a `TUINSView` as the content view of your window, if you'd like to build your whole UI with TwUI. Or you may opt to have a few smaller `TUINSViews`, using TwUI just where it makes sense and continue to use AppKit everywhere else. 22 | 23 | You can also add `NSViews` to a TwUI hierarchy using `TUIViewNSViewContainer`, which bridges back into AppKit from TwUI. 24 | 25 | # Example Project 26 | 27 | An included example project shows off the basic construction of a pure TwUI-based app. A `TUINSView` is added as the content view of the window, and some `TUIView`-based views are hosted in that. Within the table view cells, some `NSTextFields` are also added using `TUIViewNSViewContainer`. It includes a table view and a tab bar (which is a good example of how you might build your own custom controls). 28 | 29 | # Status 30 | 31 | TwUI is currently shipping in Twitter for Mac and GitHub for Mac, in use 24/7 by many, many users, and has proven itself very stable. 32 | 33 | This project follows the [SemVer](http://semver.org/) standard. The API may change in backwards-incompatible ways between major releases. 34 | 35 | The goal of TwUI is to build a high-quality UI framework designed specifically for the Mac. Much inspiration comes from UIKit, but diverging to try new things (i.e. block-based layout and drawRect), and optimizing for Mac-specific interactions is encouraged. 36 | 37 | # Contributing 38 | 39 | We will happily accept pull requests that meet one of the following criteria: 40 | 41 | 1. It fixes some functionality that is already in TwUI. This might be a bug, or something not working as expected. 42 | 2. It's something so basic or important that TwUI really should have it. 43 | 3. It has to integrate with TwUI internals, and so can't easily be done outside of the framework. This one is the most ambiguous, because interesting things may match this criterion, but still be way out of scope. In some cases, a fork might be more appropriate. Use your best judgment. 44 | 45 | All contributions should match our [coding conventions](https://github.com/github/objective-c-conventions). 46 | 47 | # Community 48 | 49 | TwUI has a mailing list, subscribe by sending an email to . 50 | 51 | # Copyright and License 52 | 53 | Copyright 2011 Twitter, Inc. 54 | 55 | Licensed under the Apache License, Version 2.0 (the "License"); 56 | you may not use this work except in compliance with the License. 57 | You may obtain a copy of the License in the LICENSE file, or at: 58 | 59 | http://www.apache.org/licenses/LICENSE-2.0 60 | 61 | Unless required by applicable law or agreed to in writing, software 62 | distributed under the License is distributed on an "AS IS" BASIS, 63 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 64 | See the License for the specific language governing permissions and 65 | limitations under the License. 66 | -------------------------------------------------------------------------------- /Resources/TwUI-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.twitter.${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 © 2011 Twitter. All rights reserved. 27 | NSPrincipalClass 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Resources/TwUI-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'TwUI' target in the 'TwUI' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /Resources/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /TwUI.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TwUI.xcodeproj/xcshareddata/xcschemes/Dynamic Library.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 60 | 61 | 63 | 64 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /TwUI.xcodeproj/xcshareddata/xcschemes/Static Library.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 60 | 61 | 63 | 64 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /TwUI.xcodeproj/xcshareddata/xcschemes/TwUI.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 66 | 67 | 73 | 74 | 75 | 76 | 77 | 78 | 84 | 85 | 87 | 88 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /TwUITests/TwUITests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.twitter.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /TwUITests/TwUITests-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'TwUITests' target in the 'TwUI' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #import "Specta.h" 8 | 9 | #define EXP_SHORTHAND 10 | #import "Expecta.h" 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /TwUITests/TwUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // TwUITests.m 3 | // TwUITests 4 | // 5 | // Created by Karl Adam on 11.07.01. 6 | // 7 | 8 | SpecBegin(TwUITests) 9 | 10 | it(@"should use specta and expecta", ^{ 11 | expect(YES).to.beTruthy(); 12 | }); 13 | 14 | SpecEnd 15 | -------------------------------------------------------------------------------- /TwUITests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | html 2 | latex 3 | -------------------------------------------------------------------------------- /extras/TwUI Presentation.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/twui/cd68dd45000bf3daf65428edffe577655897943f/extras/TwUI Presentation.zip -------------------------------------------------------------------------------- /lib/Support/ABActiveRange.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import 18 | 19 | typedef enum { 20 | ABActiveTextRangeFlavorUnknown = 0, 21 | ABActiveTextRangeFlavorURL, 22 | ABActiveTextRangeFlavorEmail, 23 | ABActiveTextRangeFlavorTwitterUsername, 24 | ABActiveTextRangeFlavorTwitterList, 25 | ABActiveTextRangeFlavorTwitterHashtag, 26 | ABActiveTextRangeFlavorTwitterStockSymbol, 27 | } ABActiveTextRangeFlavor; 28 | 29 | @protocol ABActiveTextRange // NSValue(NSRange) implicitly conforms 30 | @property (nonatomic, readonly) NSRange rangeValue; 31 | @property (nonatomic, readonly) ABActiveTextRangeFlavor rangeFlavor; 32 | @property (nonatomic, readonly) NSString *displayString; 33 | @end 34 | 35 | @interface ABFlavoredRange : NSObject 36 | { 37 | NSString *displayString; 38 | NSRange rangeValue; 39 | ABActiveTextRangeFlavor rangeFlavor; 40 | } 41 | 42 | @property (nonatomic, assign) NSRange rangeValue; 43 | @property (nonatomic, assign) ABActiveTextRangeFlavor rangeFlavor; 44 | 45 | - (void)setDisplayString:(NSString *)s; // copy 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /lib/Support/ABActiveRange.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "ABActiveRange.h" 18 | 19 | @implementation ABFlavoredRange 20 | 21 | @synthesize rangeValue; 22 | 23 | + (id)valueWithRange:(NSRange)r 24 | { 25 | ABFlavoredRange *f = [[ABFlavoredRange alloc] init]; 26 | f.rangeValue = r; 27 | return f; 28 | } 29 | 30 | 31 | - (id)copyWithZone:(NSZone *)zone 32 | { 33 | return self; // these are immutable after creation 34 | } 35 | 36 | - (NSString *)description 37 | { 38 | return [NSString stringWithFormat:@"", rangeFlavor, NSStringFromRange(rangeValue), displayString]; 39 | } 40 | 41 | - (ABActiveTextRangeFlavor)rangeFlavor 42 | { 43 | return rangeFlavor; 44 | } 45 | 46 | - (void)setRangeFlavor:(ABActiveTextRangeFlavor)f 47 | { 48 | rangeFlavor = f; 49 | } 50 | 51 | - (NSString *)displayString 52 | { 53 | return displayString; 54 | } 55 | 56 | - (void)setDisplayString:(NSString *)s 57 | { 58 | displayString = [s copy]; 59 | } 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /lib/Support/CAAnimation+TUIExtensions.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2012 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import 18 | 19 | #import 20 | 21 | typedef void (^TUICAAnimationCompletionBlock)(); 22 | 23 | //Note this is slightly flawed as we set ourself as the delegate, really we should create a chained proxy, if we need that I will add it. 24 | 25 | @interface CAAnimation (TUIExtensions) 26 | 27 | @property (nonatomic, copy) TUICAAnimationCompletionBlock tui_completionBlock; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /lib/Support/CAAnimation+TUIExtensions.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2012 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "CAAnimation+TUIExtensions.h" 18 | 19 | #import 20 | 21 | NSString *TUICAAnimationCompletionBlockAssociatedObjectKey = @"TUICAAnimationCompletionBlockAssociatedObjectKey"; 22 | 23 | @implementation CAAnimation (TUIExtensions) 24 | 25 | - (void)setTui_completionBlock:(TUICAAnimationCompletionBlock)block 26 | { 27 | self.delegate = self; 28 | objc_setAssociatedObject(self, &TUICAAnimationCompletionBlockAssociatedObjectKey, block, OBJC_ASSOCIATION_COPY); 29 | } 30 | 31 | - (TUICAAnimationCompletionBlock)tui_completionBlock 32 | { 33 | return objc_getAssociatedObject(self, &TUICAAnimationCompletionBlockAssociatedObjectKey); 34 | } 35 | 36 | - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag 37 | { 38 | if (flag && self.tui_completionBlock != nil) 39 | self.tui_completionBlock(); 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /lib/Support/CALayer+TUIExtensions.h: -------------------------------------------------------------------------------- 1 | // 2 | // CALayer+TUIExtensions.h 3 | // 4 | // Created by Josh Vera on 11/26/11. 5 | // Copyright (c) 2011 Bitswift. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | /** 11 | * Additional geometry conversions and geometrical functions for CALayer. 12 | */ 13 | @interface CALayer (TUIExtensions) 14 | /** 15 | * Converts a rectangle from the receiver's coordinate system to that of a given 16 | * layer, taking into account any layer clipping between the two. 17 | * 18 | * This will traverse the layer hierarchy, finding a common ancestor between the 19 | * receiver and 'layer' to use as a base for geometry conversion. If any layers 20 | * along the way (including the receiver, 'layer', and the common ancestor) have 21 | * masksToBounds set to YES, the rectangle takes into account their clipping 22 | * paths, such that the final result represents a rectangle that would actually 23 | * be visible on screen. 24 | * 25 | * The receiver and 'layer' must have a common ancestor. 26 | */ 27 | - (CGRect)tui_convertAndClipRect:(CGRect)rect toLayer:(CALayer *)layer; 28 | 29 | /** 30 | * Converts a rectangle from the coordinate system of 'layer' to the 31 | * receiver's, taking into account any layer clipping between the two. 32 | * 33 | * This will call -tui_convertAndClipRect:toLayer:> on 'layer' with the receiver 34 | * as the argument. 35 | * 36 | * The receiver and 'layer' must have a common ancestor. 37 | */ 38 | - (CGRect)tui_convertAndClipRect:(CGRect)rect fromLayer:(CALayer *)layer; 39 | @end 40 | -------------------------------------------------------------------------------- /lib/Support/CALayer+TUIExtensions.m: -------------------------------------------------------------------------------- 1 | // 2 | // CALayer+TUIExtensions.m 3 | // 4 | // Created by Josh Vera on 11/26/11. 5 | // Copyright (c) 2011 Bitswift. All rights reserved. 6 | // 7 | 8 | #import "CALayer+TUIExtensions.h" 9 | 10 | static CGRect convertAndClipRectFromSuperlayers (CGRect rect, CALayer *layer); 11 | 12 | static CGRect convertAndClipRectFromSuperlayers (CGRect rect, CALayer *layer) { 13 | CALayer *superlayer = layer.superlayer; 14 | if (superlayer) { 15 | rect = convertAndClipRectFromSuperlayers(rect, superlayer); 16 | if (CGRectIsNull(rect)) 17 | return CGRectNull; 18 | 19 | rect = [layer convertRect:rect fromLayer:superlayer]; 20 | } 21 | 22 | if (layer.masksToBounds) { 23 | rect = CGRectIntersection(rect, layer.visibleRect); 24 | } 25 | 26 | return rect; 27 | } 28 | 29 | @implementation CALayer (TUIExtensions) 30 | - (CGRect)tui_convertAndClipRect:(CGRect)rect toLayer:(CALayer *)layer { 31 | CALayer *clippingLayer = self.superlayer; 32 | CALayer *lastLayer = self; 33 | while (clippingLayer) { 34 | if (lastLayer.masksToBounds) { 35 | rect = CGRectIntersection(rect, lastLayer.visibleRect); 36 | if (CGRectIsNull(rect)) 37 | return CGRectNull; 38 | } 39 | 40 | rect = [clippingLayer convertRect:rect fromLayer:lastLayer]; 41 | 42 | lastLayer = clippingLayer; 43 | clippingLayer = clippingLayer.superlayer; 44 | } 45 | 46 | // 'rect' is in the coordinate system of the root layer, and has been 47 | // clipped accordingly 48 | return convertAndClipRectFromSuperlayers(rect, layer); 49 | } 50 | 51 | - (CGRect)tui_convertAndClipRect:(CGRect)rect fromLayer:(CALayer *)layer { 52 | return [layer tui_convertAndClipRect:rect toLayer:self]; 53 | } 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /lib/Support/CATransaction+TUIExtensions.h: -------------------------------------------------------------------------------- 1 | // 2 | // CATransaction+TUIExtensions.h 3 | // 4 | // Created by James Lawton on 11/23/11. 5 | // Copyright (c) 2011 Bitswift. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | /** 11 | * Extends CATransaction with useful block-based features. 12 | */ 13 | @interface CATransaction (TUIExtensions) 14 | 15 | /** 16 | * Executes a block with actions disabled. 17 | * 18 | * This will have the effect of suppressing animation. 19 | */ 20 | + (void)tui_performWithDisabledActions:(void(^)(void))block; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /lib/Support/CATransaction+TUIExtensions.m: -------------------------------------------------------------------------------- 1 | // 2 | // CATransaction+TUIExtensions.m 3 | // 4 | // Created by James Lawton on 11/23/11. 5 | // Copyright (c) 2011 Bitswift. All rights reserved. 6 | // 7 | 8 | #import "CATransaction+TUIExtensions.h" 9 | 10 | @implementation CATransaction (TUIExtensions) 11 | + (void)tui_performWithDisabledActions:(void(^)(void))block { 12 | if ([self disableActions]) { 13 | // actions are already disabled 14 | block(); 15 | } else { 16 | [self setDisableActions:YES]; 17 | block(); 18 | [self setDisableActions:NO]; 19 | } 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /lib/Support/CoreText+Additions.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #if TARGET_OS_MAC 18 | #import 19 | #elif TARGET_OS_IPHONE 20 | #import 21 | #endif 22 | 23 | typedef enum { 24 | AB_CTLineRectAggregationTypeInline = 0, 25 | AB_CTLineRectAggregationTypeBlock, 26 | } AB_CTLineRectAggregationType; 27 | 28 | extern CGSize AB_CTLineGetSize(CTLineRef line); 29 | extern CGSize AB_CTFrameGetSize(CTFrameRef frame); 30 | extern CGFloat AB_CTFrameGetHeight(CTFrameRef frame); 31 | extern CFIndex AB_CTFrameGetStringIndexForPosition(CTFrameRef frame, CGPoint p); 32 | 33 | extern void AB_CTFrameGetIndexForPositionInLine(NSString *string, CTFrameRef frame, CFIndex lineIndex, float xPosition, CFIndex *index); 34 | extern void AB_CTFrameGetLinePositionOfIndex(NSString *string, CTFrameRef frame, CFIndex index, CFIndex *lineIndex, float *xPosition); 35 | extern void AB_CTFrameGetRectsForRange(CTFrameRef frame, CFRange range, CGRect rects[], CFIndex *rectCount); 36 | extern void AB_CTFrameGetRectsForRangeWithAggregationType(CTFrameRef frame, CFRange range, AB_CTLineRectAggregationType aggregationType, CGRect rects[], CFIndex *rectCount); 37 | extern void AB_CTLinesGetRectsForRangeWithAggregationType(NSArray *lines, CGPoint *lineOrigins, CGRect bounds, CFRange range, AB_CTLineRectAggregationType aggregationType, CGRect rects[], CFIndex *rectCount); 38 | -------------------------------------------------------------------------------- /lib/Support/NSFont+TUIExtensions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSFont+TUIExtensions.h 3 | // TwUI 4 | // 5 | // Created by Josh Abernathy on 7/26/12. 6 | // 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface NSFont (TUIExtensions) 13 | 14 | // Creates and returns a new font with the given size and fallback font names. 15 | // The fallback fonts all use the font size passed in. 16 | + (NSFont *)tui_fontWithName:(NSString *)fontName size:(CGFloat)fontSize fallbackNames:(NSArray *)fallbackNames; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /lib/Support/NSFont+TUIExtensions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSFont+TUIExtensions.m 3 | // TwUI 4 | // 5 | // Created by Josh Abernathy on 7/26/12. 6 | // 7 | // 8 | 9 | #import "NSFont+TUIExtensions.h" 10 | 11 | 12 | @implementation NSFont (TUIExtensions) 13 | 14 | + (NSFont *)tui_fontWithName:(NSString *)fontName size:(CGFloat)fontSize fallbackNames:(NSArray *)fallbackNames { 15 | NSMutableArray *fallbackDescriptors = [NSMutableArray arrayWithCapacity:fallbackNames.count]; 16 | for(NSString *fallbackName in fallbackNames) { 17 | [fallbackDescriptors addObject:[NSFontDescriptor fontDescriptorWithName:fallbackName size:fontSize]]; 18 | } 19 | 20 | return [NSFont fontWithDescriptor:[NSFontDescriptor fontDescriptorWithFontAttributes:@{ NSFontNameAttribute: fontName, NSFontCascadeListAttribute: fallbackDescriptors }] size:fontSize]; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /lib/Support/TUICAAction.h: -------------------------------------------------------------------------------- 1 | // 2 | // TUICAAction.h 3 | // 4 | // Created by James Lawton on 11/21/11. 5 | // Copyright (c) 2011 Bitswift. All rights reserved. 6 | // 7 | 8 | #import 9 | #import 10 | 11 | /* 12 | * A CAAction which finds AppKit views contained in Velvet and animates them 13 | * alongside. We pass through to the default animation to animate the Velvet 14 | * views. 15 | */ 16 | @interface TUICAAction : NSObject 17 | 18 | /* 19 | * Initializes an action which proxies for the given action, and handles animation 20 | * of all descendent TUIViewNSViewContainer instances along with the layer being acted upon. 21 | * 22 | * This is the designated initializer. 23 | */ 24 | - (id)initWithAction:(id)innerAction; 25 | 26 | /* 27 | * Returns an action initialized with . 28 | */ 29 | + (id)actionWithAction:(id)innerAction; 30 | 31 | /* 32 | * Whether objects of this class add features to actions for the given key. 33 | */ 34 | + (BOOL)interceptsActionForKey:(NSString *)key; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /lib/UIKit/NSClipView+TUIExtensions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSClipView+TUIExtensions.h 3 | // TwUI 4 | // 5 | // Created by Justin Spahr-Summers on 17.07.12. 6 | // 7 | // Portions of this code were taken from Velvet, 8 | // which is copyright (c) 2012 Bitswift, Inc. 9 | // See LICENSE.txt for more information. 10 | // 11 | 12 | #import 13 | #import "TUIBridgedScrollView.h" 14 | 15 | /** 16 | * Implements for NSClipView. 17 | */ 18 | @interface NSClipView (TUIExtensions) 19 | @end 20 | -------------------------------------------------------------------------------- /lib/UIKit/NSClipView+TUIExtensions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSClipView+TUIExtensions.m 3 | // TwUI 4 | // 5 | // Created by Justin Spahr-Summers on 17.07.12. 6 | // 7 | // Portions of this code were taken from Velvet, 8 | // which is copyright (c) 2012 Bitswift, Inc. 9 | // See LICENSE.txt for more information. 10 | // 11 | 12 | #import "NSClipView+TUIExtensions.h" 13 | #import "NSView+TUIExtensions.h" 14 | 15 | // Without this, the compiler will complain about -scrollToPoint: missing from 16 | // this category, but the method is part of NSClipView itself. 17 | #pragma clang diagnostic ignored "-Wprotocol" 18 | 19 | @implementation NSClipView (TUIExtensions) 20 | 21 | #pragma mark TUIBridgedView 22 | 23 | // implemented on NSView 24 | @dynamic layer; 25 | @dynamic hostView; 26 | 27 | #pragma mark TUIBridgedScrollView 28 | 29 | - (void)scrollToIncludeRect:(CGRect)rect; { 30 | CGRect visibleRect = self.documentVisibleRect; 31 | CGSize visibleSize = visibleRect.size; 32 | 33 | CGPoint newScrollPoint = visibleRect.origin; 34 | 35 | if (CGRectGetMinX(rect) < CGRectGetMinX(visibleRect)) { 36 | newScrollPoint.x = CGRectGetMinX(rect); 37 | } else if (CGRectGetMaxX(rect) > CGRectGetMaxX(visibleRect)) { 38 | newScrollPoint.x = fmax(0, CGRectGetMaxX(rect) - visibleSize.width); 39 | } 40 | 41 | if (CGRectGetMinY(rect) < CGRectGetMinY(visibleRect)) { 42 | newScrollPoint.y = CGRectGetMinY(rect); 43 | } else if (CGRectGetMaxY(rect) > CGRectGetMaxY(visibleRect)) { 44 | newScrollPoint.y = fmax(0, CGRectGetMaxY(rect) - visibleSize.width); 45 | } 46 | 47 | [self scrollToPoint:newScrollPoint]; 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /lib/UIKit/NSColor+TUIExtensions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSColor+TUIExtensions.h 3 | // 4 | // Created by Justin Spahr-Summers on 01.12.11. 5 | // Copyright (c) 2011 Bitswift. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | /* 11 | * Extensions to NSColor that add interoperability with CGColor. 12 | */ 13 | @interface NSColor (TUIExtensions) 14 | 15 | /* 16 | * The CGColor corresponding to the receiver. 17 | */ 18 | @property (nonatomic, readonly) CGColorRef tui_CGColor; 19 | 20 | /* 21 | * Returns an NSColor corresponding to the given CGColor. 22 | * 23 | * This method will not handle pattern colors. 24 | */ 25 | + (NSColor *)tui_colorWithCGColor:(CGColorRef)color; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /lib/UIKit/NSColor+TUIExtensions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSColor+TUIExtensions.m 3 | // 4 | // Created by Justin Spahr-Summers on 01.12.11. 5 | // Copyright (c) 2011 Bitswift. All rights reserved. 6 | // 7 | 8 | #import "NSColor+TUIExtensions.h" 9 | #import "NSImage+TUIExtensions.h" 10 | 11 | // CGPatterns involve some complex memory management which doesn't mesh well 12 | // with ARC. 13 | #if __has_feature(objc_arc) 14 | #error "This file cannot be compiled with ARC." 15 | #endif 16 | 17 | static void drawCGImagePattern (void *info, CGContextRef context) { 18 | CGImageRef image = info; 19 | 20 | size_t width = CGImageGetWidth(image); 21 | size_t height = CGImageGetHeight(image); 22 | 23 | CGContextDrawImage(context, CGRectMake(0, 0, width, height), image); 24 | } 25 | 26 | static void releasePatternInfo (void *info) { 27 | CFRelease(info); 28 | } 29 | 30 | @implementation NSColor (TUIExtensions) 31 | 32 | + (NSColor *)tui_colorWithCGColor:(CGColorRef)color; { 33 | if (!color) 34 | return nil; 35 | 36 | CGColorSpaceRef colorSpaceRef = CGColorGetColorSpace(color); 37 | 38 | NSColorSpace *colorSpace = [[NSColorSpace alloc] initWithCGColorSpace:colorSpaceRef]; 39 | NSColor *result = [self colorWithColorSpace:colorSpace components:CGColorGetComponents(color) count:(size_t)CGColorGetNumberOfComponents(color)]; 40 | [colorSpace release]; 41 | 42 | return result; 43 | } 44 | 45 | - (CGColorRef)tui_CGColor; { 46 | if ([self.colorSpaceName isEqualToString:NSPatternColorSpace]) { 47 | CGImageRef patternImage = self.patternImage.tui_CGImage; 48 | if (!patternImage) 49 | return NULL; 50 | 51 | size_t width = CGImageGetWidth(patternImage); 52 | size_t height = CGImageGetHeight(patternImage); 53 | 54 | CGRect patternBounds = CGRectMake(0, 0, width, height); 55 | CGPatternRef pattern = CGPatternCreate( 56 | (void *)CFRetain(patternImage), 57 | patternBounds, 58 | CGAffineTransformIdentity, 59 | width, 60 | height, 61 | kCGPatternTilingConstantSpacingMinimalDistortion, 62 | YES, 63 | &(CGPatternCallbacks){ 64 | .version = 0, 65 | .drawPattern = &drawCGImagePattern, 66 | .releaseInfo = &releasePatternInfo 67 | } 68 | ); 69 | 70 | CGColorSpaceRef colorSpaceRef = CGColorSpaceCreatePattern(NULL); 71 | 72 | CGColorRef result = CGColorCreateWithPattern(colorSpaceRef, pattern, (CGFloat[]){ 1.0 }); 73 | 74 | CGColorSpaceRelease(colorSpaceRef); 75 | CGPatternRelease(pattern); 76 | 77 | return (CGColorRef)[(id)result autorelease]; 78 | } 79 | 80 | NSColorSpace *colorSpace = [NSColorSpace genericRGBColorSpace]; 81 | NSColor *color = [self colorUsingColorSpace:colorSpace]; 82 | 83 | NSInteger count = [color numberOfComponents]; 84 | CGFloat components[count]; 85 | [color getComponents:components]; 86 | 87 | CGColorSpaceRef colorSpaceRef = colorSpace.CGColorSpace; 88 | CGColorRef result = CGColorCreate(colorSpaceRef, components); 89 | 90 | return (CGColorRef)[(id)result autorelease]; 91 | } 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /lib/UIKit/NSImage+TUIExtensions.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import 18 | #import "TUIGeometry.h" 19 | 20 | @class TUIStretchableImage; 21 | 22 | @interface NSImage (TUIExtensions) 23 | 24 | + (NSImage *)tui_imageWithCGImage:(CGImageRef)cgImage; 25 | + (NSImage *)tui_imageWithSize:(CGSize)size drawing:(void (^)(CGContextRef))draw; // thread safe 26 | 27 | /* 28 | * Returns a CGImageRef corresponding to the receiver. 29 | * 30 | * This should only be used with bitmaps. For vector images, use 31 | * -CGImageForProposedRect:context:hints instead. 32 | */ 33 | @property (nonatomic, readonly) CGImageRef tui_CGImage; 34 | 35 | /* 36 | * Similar to -CGImageForProposedRect:context:hints:, but accepts a CGContextRef 37 | * instead. 38 | */ 39 | - (CGImageRef)tui_CGImageForProposedRect:(CGRect *)rectPtr CGContext:(CGContextRef)context; 40 | 41 | /* 42 | * Draws the whole image originating at the given point. 43 | */ 44 | - (void)tui_drawAtPoint:(CGPoint)point; 45 | 46 | /* 47 | * Draws the whole image into the given rectangle. 48 | */ 49 | - (void)tui_drawInRect:(CGRect)rect; 50 | 51 | /* 52 | * Creates and returns a new image, based on the receiver, that has the 53 | * specified end cap insets. 54 | */ 55 | - (TUIStretchableImage *)tui_resizableImageWithCapInsets:(TUIEdgeInsets)insets; 56 | 57 | - (NSImage *)tui_crop:(CGRect)cropRect; 58 | - (NSImage *)tui_upsideDownCrop:(CGRect)cropRect; 59 | - (NSImage *)tui_scale:(CGSize)size; 60 | - (NSImage *)tui_thumbnail:(CGSize)size; 61 | - (NSImage *)tui_pad:(CGFloat)padding; // can be negative (to crop to center) 62 | - (NSImage *)tui_roundImage:(CGFloat)radius; 63 | - (NSImage *)tui_invertedMask; 64 | - (NSImage *)tui_embossMaskWithOffset:(CGSize)offset; // subtract reciever from itself offset by 'offset', use as a mask to draw emboss 65 | - (NSImage *)tui_innerShadowWithOffset:(CGSize)offset radius:(CGFloat)radius color:(NSColor *)color backgroundColor:(NSColor *)backgroundColor; // 'backgroundColor' is used as the color the shadow is drawn with, it is mostly masked out, but a halo will remain, leading to artifacts unless it is close enough to the background color 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /lib/UIKit/NSScrollView+TUIExtensions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSScrollView+TUIExtensions.h 3 | // TwUI 4 | // 5 | // Created by Justin Spahr-Summers on 17.07.12. 6 | // 7 | // Portions of this code were taken from Velvet, 8 | // which is copyright (c) 2012 Bitswift, Inc. 9 | // See LICENSE.txt for more information. 10 | // 11 | 12 | #import 13 | #import "TUIBridgedScrollView.h" 14 | 15 | /** 16 | * Implements for NSScrollView. 17 | * 18 | * Because the protocol is already implemented for NSClipView, 19 | * this category is simply a convenience that invokes the protocol methods 20 | * against the underlying contentView. 21 | */ 22 | @interface NSScrollView (TUIExtensions) 23 | @end 24 | -------------------------------------------------------------------------------- /lib/UIKit/NSScrollView+TUIExtensions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSScrollView+TUIExtensions.m 3 | // TwUI 4 | // 5 | // Created by Justin Spahr-Summers on 17.07.12. 6 | // 7 | // Portions of this code were taken from Velvet, 8 | // which is copyright (c) 2012 Bitswift, Inc. 9 | // See LICENSE.txt for more information. 10 | // 11 | 12 | #import "NSScrollView+TUIExtensions.h" 13 | #import "NSClipView+TUIExtensions.h" 14 | #import "NSView+TUIExtensions.h" 15 | 16 | @implementation NSScrollView (TUIExtensions) 17 | 18 | #pragma mark TUIBridgedView 19 | 20 | // implemented on NSView 21 | @dynamic layer; 22 | @dynamic hostView; 23 | 24 | #pragma mark TUIBridgedScrollView 25 | 26 | - (void)scrollToPoint:(CGPoint)point; { 27 | [self.contentView scrollToPoint:point]; 28 | } 29 | 30 | - (void)scrollToIncludeRect:(CGRect)rect; { 31 | [self.contentView scrollToIncludeRect:rect]; 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /lib/UIKit/NSView+TUIExtensions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSView+TUIExtensions.h 3 | // TwUI 4 | // 5 | // Created by Justin Spahr-Summers on 17.07.12. 6 | // 7 | // Portions of this code were taken from Velvet, 8 | // which is copyright (c) 2012 Bitswift, Inc. 9 | // See LICENSE.txt for more information. 10 | // 11 | 12 | #import 13 | #import "TUIBridgedView.h" 14 | 15 | @class TUIViewNSViewContainer; 16 | @protocol TUIHostView; 17 | 18 | /** 19 | * Implements for NSView. 20 | */ 21 | @interface NSView (TUIExtensions) 22 | 23 | /** 24 | * The TUIViewNSViewContainer that is hosting this view, or nil if it exists 25 | * independently of a TwUI hierarchy. 26 | */ 27 | @property (nonatomic, unsafe_unretained) TUIViewNSViewContainer *hostView; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /lib/UIKit/NSView+TUIExtensions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSView+TUIExtensions.m 3 | // TwUI 4 | // 5 | // Created by Justin Spahr-Summers on 17.07.12. 6 | // 7 | // Portions of this code were taken from Velvet, 8 | // which is copyright (c) 2012 Bitswift, Inc. 9 | // See LICENSE.txt for more information. 10 | // 11 | 12 | #import "NSView+TUIExtensions.h" 13 | #import "TUINSView.h" 14 | #import "TUIBridgedScrollView.h" 15 | #import 16 | 17 | @implementation NSView (TUIExtensions) 18 | 19 | // NSView already implements a layer property 20 | @dynamic layer; 21 | 22 | #pragma mark View hierarchy 23 | 24 | - (id)hostView { 25 | id hostView = objc_getAssociatedObject(self, @selector(hostView)); 26 | if (hostView) 27 | return hostView; 28 | else 29 | return self.superview.hostView; 30 | } 31 | 32 | - (id)immediateParentView { 33 | id hostView = objc_getAssociatedObject(self, @selector(hostView)); 34 | if (hostView) 35 | return hostView; 36 | else 37 | return self.superview; 38 | } 39 | 40 | - (void)setHostView:(id)hostView { 41 | objc_setAssociatedObject(self, @selector(hostView), hostView, OBJC_ASSOCIATION_ASSIGN); 42 | } 43 | 44 | - (void)ancestorDidLayout; { 45 | [self.subviews makeObjectsPerformSelector:_cmd]; 46 | } 47 | 48 | - (TUINSView *)ancestorTUINSView; { 49 | NSView *view = self; 50 | 51 | do { 52 | if ([view isKindOfClass:[TUINSView class]]) 53 | return (id)view; 54 | 55 | view = view.superview; 56 | } while (view); 57 | 58 | return nil; 59 | } 60 | 61 | - (id)ancestorScrollView { 62 | if ([self conformsToProtocol:@protocol(TUIBridgedScrollView)]) 63 | return (id)self; 64 | 65 | return self.immediateParentView.ancestorScrollView; 66 | } 67 | 68 | #pragma mark Geometry 69 | 70 | - (CGPoint)convertFromWindowPoint:(CGPoint)point; { 71 | NSPoint windowPoint = NSPointFromCGPoint(point); 72 | NSPoint selfPoint = [self convertPoint:windowPoint fromView:nil]; 73 | return NSPointToCGPoint(selfPoint); 74 | } 75 | 76 | - (CGPoint)convertToWindowPoint:(CGPoint)point; { 77 | NSPoint windowPoint = NSPointFromCGPoint(point); 78 | NSPoint selfPoint = [self convertPoint:windowPoint toView:nil]; 79 | return NSPointToCGPoint(selfPoint); 80 | } 81 | 82 | - (CGRect)convertFromWindowRect:(CGRect)rect; { 83 | NSRect windowRect = NSRectFromCGRect(rect); 84 | NSRect selfRect = [self convertRect:windowRect fromView:nil]; 85 | return NSRectToCGRect(selfRect); 86 | } 87 | 88 | - (CGRect)convertToWindowRect:(CGRect)rect; { 89 | NSRect windowRect = NSRectFromCGRect(rect); 90 | NSRect selfRect = [self convertRect:windowRect toView:nil]; 91 | return NSRectToCGRect(selfRect); 92 | } 93 | 94 | #pragma mark Hit testing 95 | 96 | - (id)descendantViewAtPoint:(NSPoint)point { 97 | NSPoint superviewPoint = [self convertPoint:point toView:self.superview]; 98 | id hitView = [self hitTest:superviewPoint]; 99 | 100 | if ([hitView isKindOfClass:[TUINSView class]]) { 101 | NSPoint descendantPoint = [self convertPoint:point toView:hitView]; 102 | return [hitView descendantViewAtPoint:descendantPoint]; 103 | } 104 | 105 | return hitView; 106 | } 107 | 108 | - (BOOL)pointInside:(CGPoint)point { 109 | NSPoint superviewPoint = [self convertPoint:point toView:self.superview]; 110 | return [self hitTest:superviewPoint] ? YES : NO; 111 | } 112 | 113 | #pragma mark View hierarchy 114 | 115 | - (void)willMoveToTUINSView:(TUINSView *)view; { 116 | [self.subviews makeObjectsPerformSelector:_cmd withObject:view]; 117 | } 118 | 119 | - (void)didMoveFromTUINSView:(TUINSView *)view; { 120 | [self.subviews makeObjectsPerformSelector:_cmd withObject:view]; 121 | } 122 | 123 | - (void)viewHierarchyDidChange { 124 | [self.subviews makeObjectsPerformSelector:_cmd]; 125 | } 126 | 127 | @end 128 | -------------------------------------------------------------------------------- /lib/UIKit/TUIAccessibility.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | typedef uint64_t TUIAccessibilityTraits; 18 | 19 | extern TUIAccessibilityTraits TUIAccessibilityTraitNone; 20 | extern TUIAccessibilityTraits TUIAccessibilityTraitButton; 21 | extern TUIAccessibilityTraits TUIAccessibilityTraitLink; 22 | extern TUIAccessibilityTraits TUIAccessibilityTraitSearchField; 23 | extern TUIAccessibilityTraits TUIAccessibilityTraitImage; 24 | extern TUIAccessibilityTraits TUIAccessibilityTraitSelected; 25 | extern TUIAccessibilityTraits TUIAccessibilityTraitPlaysSound; 26 | extern TUIAccessibilityTraits TUIAccessibilityTraitStaticText; 27 | extern TUIAccessibilityTraits TUIAccessibilityTraitSummaryElement; 28 | extern TUIAccessibilityTraits TUIAccessibilityTraitNotEnabled; 29 | extern TUIAccessibilityTraits TUIAccessibilityTraitUpdatesFrequently; 30 | 31 | 32 | @interface NSObject (TUIAccessibility) 33 | 34 | @property (nonatomic, assign) BOOL isAccessibilityElement; 35 | @property (nonatomic, copy) NSString *accessibilityLabel; 36 | @property (nonatomic, copy) NSString *accessibilityHint; 37 | @property (nonatomic, copy) NSString *accessibilityValue; 38 | @property (nonatomic, assign) TUIAccessibilityTraits accessibilityTraits; 39 | @property (nonatomic, assign) CGRect accessibilityFrame; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /lib/UIKit/TUIActivityIndicatorView.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIView.h" 18 | 19 | typedef enum { 20 | TUIActivityIndicatorViewStyleGray, 21 | } TUIActivityIndicatorViewStyle; 22 | 23 | @interface TUIActivityIndicatorView : TUIView 24 | { 25 | BOOL _animating; 26 | TUIActivityIndicatorViewStyle _activityIndicatorViewStyle; 27 | 28 | TUIView *spinner; 29 | } 30 | 31 | - (id)initWithActivityIndicatorStyle:(TUIActivityIndicatorViewStyle)style; 32 | 33 | @property(nonatomic,readonly) TUIActivityIndicatorViewStyle activityIndicatorViewStyle; 34 | 35 | - (void)startAnimating; 36 | - (void)stopAnimating; 37 | - (BOOL)isAnimating; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /lib/UIKit/TUIActivityIndicatorView.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIActivityIndicatorView.h" 18 | 19 | @implementation TUIActivityIndicatorView 20 | 21 | - (id)initWithActivityIndicatorStyle:(TUIActivityIndicatorViewStyle)style 22 | { 23 | if((self = [super initWithFrame:CGRectMake(0, 0, 20, 20)])) 24 | { 25 | _activityIndicatorViewStyle = style; 26 | 27 | spinner = [[TUIView alloc] initWithFrame:self.bounds]; 28 | spinner.backgroundColor = [NSColor blackColor]; 29 | spinner.alpha = 0.2; 30 | spinner.layer.cornerRadius = 10.0; 31 | [self addSubview:spinner]; 32 | } 33 | return self; 34 | } 35 | 36 | - (TUIActivityIndicatorViewStyle)activityIndicatorViewStyle 37 | { 38 | return _activityIndicatorViewStyle; 39 | } 40 | 41 | - (void)startAnimating 42 | { 43 | if(!_animating) { 44 | CGFloat duration = 1.0; 45 | 46 | { 47 | CABasicAnimation *animation = [CABasicAnimation animation]; 48 | animation.repeatCount = INT_MAX; 49 | animation.duration = duration; 50 | animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.1, 0.1, 0.1)]; 51 | animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)]; 52 | [spinner.layer addAnimation:animation forKey:@"transform"]; 53 | } 54 | 55 | { 56 | CAKeyframeAnimation *animation = [CAKeyframeAnimation animation]; 57 | animation.values = [NSArray arrayWithObjects: 58 | [NSNumber numberWithFloat:0.0], 59 | [NSNumber numberWithFloat:0.3], 60 | [NSNumber numberWithFloat:0.0], 61 | nil]; 62 | animation.repeatCount = INT_MAX; 63 | animation.duration = duration; 64 | [spinner.layer addAnimation:animation forKey:@"opacity"]; 65 | } 66 | 67 | _animating = YES; 68 | } 69 | } 70 | 71 | - (void)stopAnimating 72 | { 73 | if(_animating) { 74 | [spinner.layer removeAllAnimations]; 75 | _animating = NO; 76 | } 77 | } 78 | 79 | - (BOOL)isAnimating 80 | { 81 | return _animating; 82 | } 83 | 84 | - (CGSize)sizeThatFits:(CGSize)size 85 | { 86 | return CGSizeMake(20, 20); 87 | } 88 | 89 | - (void)removeAllAnimations 90 | { 91 | // do nothing 92 | } 93 | 94 | @end 95 | -------------------------------------------------------------------------------- /lib/UIKit/TUIAttributedString.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import 18 | 19 | extern NSString * const TUIAttributedStringBackgroundColorAttributeName; 20 | extern NSString * const TUIAttributedStringBackgroundFillStyleName; 21 | extern NSString * const TUIAttributedStringPreDrawBlockName; 22 | 23 | typedef void (^TUIAttributedStringPreDrawBlock)(NSAttributedString *attributedString, NSRange substringRange, CGRect rects[], CFIndex rectCount); 24 | 25 | typedef enum { 26 | TUILineBreakModeWordWrap = 0, 27 | TUILineBreakModeCharacterWrap, 28 | TUILineBreakModeClip, 29 | TUILineBreakModeHeadTruncation, 30 | TUILineBreakModeTailTruncation, 31 | TUILineBreakModeMiddleTruncation, 32 | } TUILineBreakMode; 33 | 34 | typedef enum { 35 | TUIBaselineAdjustmentAlignBaselines = 0, 36 | TUIBaselineAdjustmentAlignCenters, 37 | TUIBaselineAdjustmentNone, 38 | } TUIBaselineAdjustment; 39 | 40 | typedef enum { 41 | TUITextAlignmentLeft = 0, 42 | TUITextAlignmentCenter, 43 | TUITextAlignmentRight, 44 | TUITextAlignmentJustified, 45 | } TUITextAlignment; 46 | 47 | typedef enum { 48 | TUIBackgroundFillStyleInline = 0, 49 | TUIBackgroundFillStyleBlock, 50 | } TUIBackgroundFillStyle; 51 | 52 | @interface TUIAttributedString : NSMutableAttributedString 53 | 54 | + (TUIAttributedString *)stringWithString:(NSString *)string; 55 | 56 | @end 57 | 58 | @interface NSMutableAttributedString (TUIAdditions) 59 | 60 | // write-only properties, reading will return nil 61 | @property (nonatomic, retain) NSFont *font; 62 | @property (nonatomic, retain) NSColor *color; 63 | @property (nonatomic, retain) NSColor *backgroundColor; 64 | @property (nonatomic, assign) TUIBackgroundFillStyle backgroundFillStyle; 65 | @property (nonatomic, retain) NSShadow *shadow; 66 | @property (nonatomic, assign) TUITextAlignment alignment; // setting this will set lineBreakMode to word wrap, use setAlignment:lineBreakMode: for more control 67 | @property (nonatomic, assign) CGFloat kerning; 68 | @property (nonatomic, assign) CGFloat lineHeight; 69 | @property (nonatomic, copy) NSString *text; 70 | 71 | - (void)setAlignment:(TUITextAlignment)alignment lineBreakMode:(TUILineBreakMode)lineBreakMode; 72 | 73 | - (NSRange)_stringRange; 74 | - (void)setFont:(NSFont *)font inRange:(NSRange)range; 75 | - (void)setColor:(NSColor *)color inRange:(NSRange)range; 76 | - (void)setBackgroundColor:(NSColor *)color inRange:(NSRange)range; 77 | - (void)setBackgroundFillStyle:(TUIBackgroundFillStyle)fillStyle inRange:(NSRange)range; 78 | - (void)setPreDrawBlock:(TUIAttributedStringPreDrawBlock)block inRange:(NSRange)range; // the pre-draw block is called before the text or text background has been drawn 79 | - (void)setShadow:(NSShadow *)shadow inRange:(NSRange)range; 80 | - (void)setKerning:(CGFloat)f inRange:(NSRange)range; 81 | - (void)setLineHeight:(CGFloat)f inRange:(NSRange)range; 82 | 83 | @end 84 | 85 | @interface NSShadow (TUIAdditions) 86 | 87 | + (NSShadow *)shadowWithRadius:(CGFloat)radius offset:(CGSize)offset color:(NSColor *)color; 88 | 89 | @end 90 | 91 | extern NSParagraphStyle *ABNSParagraphStyleForTextAlignment(TUITextAlignment alignment); 92 | -------------------------------------------------------------------------------- /lib/UIKit/TUIBridgedScrollView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TUIBridgedScrollView.h 3 | // TwUI 4 | // 5 | // Created by Justin Spahr-Summers on 17.07.12. 6 | // 7 | // Portions of this code were taken from Velvet, 8 | // which is copyright (c) 2012 Bitswift, Inc. 9 | // See LICENSE.txt for more information. 10 | // 11 | 12 | #import 13 | #import "TUIBridgedView.h" 14 | 15 | /** 16 | * Represents any kind of bridged scroll view. 17 | */ 18 | @protocol TUIBridgedScrollView 19 | @required 20 | 21 | /** 22 | * @name Scrolling 23 | */ 24 | 25 | /** 26 | * Scrolls the receiver such that the visible rectangle originates at the given 27 | * point in the receiver's coordinate system. This method should enable any 28 | * applicable animations. 29 | * 30 | * If scrolling to the given point would result in a rectangle extending past 31 | * the scroll view's content, the behavior is unspecified; however, the 32 | * resulting visible rectangle should still include the given point. 33 | */ 34 | - (void)scrollToPoint:(CGPoint)point; 35 | 36 | /** 37 | * Scrolls the receiver the minimum distance required to ensure that the given 38 | * rectangle is made visible. This method should enable any applicable 39 | * animations. 40 | * 41 | * If the given rectangle is already visible in the scroll view, nothing 42 | * happens. If the rectangle is larger than the size of the scroll view, as much 43 | * of the rectangle as possible should be made visible; however, it is 44 | * unspecified which part of the rectangle will be used. 45 | * 46 | * This method is named to avoid method signature conflicts with AppKit. 47 | */ 48 | - (void)scrollToIncludeRect:(CGRect)rect; 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /lib/UIKit/TUIBridgedView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TUIBridgedView.h 3 | // TwUI 4 | // 5 | // Created by Justin Spahr-Summers on 17.07.12. 6 | // 7 | // Portions of this code were taken from Velvet, 8 | // which is copyright (c) 2012 Bitswift, Inc. 9 | // See LICENSE.txt for more information. 10 | // 11 | 12 | #import 13 | 14 | @protocol TUIBridgedScrollView; 15 | @protocol TUIHostView; 16 | @class TUINSView; 17 | 18 | /** 19 | * Represents a view that can be bridged by TwUI. 20 | * 21 | * Currently, only NSView and TUIView conform to this protocol. 22 | */ 23 | @protocol TUIBridgedView 24 | @required 25 | 26 | /** 27 | * Converts a point from the coordinate system of the window to that of the 28 | * receiver. 29 | */ 30 | - (CGPoint)convertFromWindowPoint:(CGPoint)point; 31 | 32 | /** 33 | * Converts a point from the receiver's coordinate system to that of its window. 34 | */ 35 | - (CGPoint)convertToWindowPoint:(CGPoint)point; 36 | 37 | /** 38 | * Converts a rectangle from the coordinate system of the window to that of the 39 | * receiver. 40 | */ 41 | - (CGRect)convertFromWindowRect:(CGRect)rect; 42 | 43 | /** 44 | * Converts a rectangle from the receiver's coordinate system to that of its window. 45 | */ 46 | - (CGRect)convertToWindowRect:(CGRect)rect; 47 | 48 | /** 49 | * The layer backing the receiver. 50 | * 51 | * This property must never be nil. 52 | */ 53 | @property (nonatomic, strong, readonly) CALayer *layer; 54 | 55 | /** 56 | * The view directly or indirectly hosting the receiver, or nil if the 57 | * receiver is not part of a hosted view hierarchy. 58 | * 59 | * The receiver or one of its ancestors will be the [TUIHostView rootView] of 60 | * this view. 61 | * 62 | * Implementing classes may require that this property be of a more specific 63 | * type. 64 | * 65 | * This property should not be set except by the TUIHostView itself. 66 | */ 67 | @property (nonatomic, unsafe_unretained) id hostView; 68 | 69 | /** 70 | * Returns the receiver's hostView or superview, whichever is closer in the 71 | * hierarchy. 72 | */ 73 | - (id)immediateParentView; 74 | 75 | /** 76 | * Invoked any time an ancestor of the receiver has relaid itself out, 77 | * potentially moving or clipping the receiver relative to one of its ancestor 78 | * views. 79 | * 80 | * The receiver _must_ forward this message to all of its subviews and any 81 | * [TUIHostView rootView]. 82 | */ 83 | - (void)ancestorDidLayout; 84 | 85 | /** 86 | * Invoked any time the receiver has changed absolute positions in the view 87 | * hierarchy. 88 | * 89 | * This will include, for example, any time the receiver or one of its ancestors 90 | * changes superviews, changes host views, is reordered within its superview, 91 | * etc. 92 | * 93 | * The receiver _must_ forward this message to all of its subviews and any 94 | * [TUIHostView rootView]. 95 | */ 96 | - (void)viewHierarchyDidChange; 97 | 98 | /** 99 | * Returns the nearest that is an ancestor of the receiver, or of 100 | * a view hosting the receiver. 101 | * 102 | * Returns nil if the receiver is not part of a TwUI-hosted view hierarchy. 103 | */ 104 | - (TUINSView *)ancestorTUINSView; 105 | 106 | /** 107 | * Walks up the receiver's ancestor views, returning the nearest 108 | * . 109 | * 110 | * Returns nil if no scroll view is an ancestor of the receiver. 111 | */ 112 | - (id)ancestorScrollView; 113 | 114 | /** 115 | * Invoked when the receiver is moving to a new . 116 | * 117 | * 'view' will be nil if the receiver is being detached from its current 118 | * . 119 | * 120 | * The receiver _must_ forward this message to all of its subviews and any 121 | * [TUIHostView rootView]. 122 | */ 123 | - (void)willMoveToTUINSView:(TUINSView *)view; 124 | 125 | /** 126 | * Invoked when the receiver has moved to a new . 127 | * 128 | * 'view' will be nil if the receiver was previously not hosted. 129 | * 130 | * The receiver _must_ forward this message to all of its subviews and any 131 | * [TUIHostView rootView]. 132 | */ 133 | - (void)didMoveFromTUINSView:(TUINSView *)view; 134 | 135 | /** 136 | * Hit tests the receiver's view hierarchy, returning the which 137 | * is occupying the given point, or nil if there is no such view. 138 | * 139 | * This method should only traverse views which are visible and allow user 140 | * interaction. 141 | * 142 | * 'point' should be specified in the coordinate system of the receiver. 143 | */ 144 | - (id)descendantViewAtPoint:(CGPoint)point; 145 | 146 | /** 147 | * Returns whether the receiver is occupying the given point. 148 | * 149 | * 'point' should be specified in the coordinate system of the receiver. 150 | */ 151 | - (BOOL)pointInside:(CGPoint)point; 152 | 153 | @end 154 | -------------------------------------------------------------------------------- /lib/UIKit/TUIButton+Accessibility.h: -------------------------------------------------------------------------------- 1 | // 2 | // TUIButton+Accessibility.h 3 | // TwUI 4 | // 5 | // Created by Josh Abernathy on 7/29/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "TUIButton.h" 10 | 11 | 12 | @interface TUIButton (Accessibility) 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /lib/UIKit/TUIButton+Accessibility.m: -------------------------------------------------------------------------------- 1 | // 2 | // TUIButton+Accessibility.m 3 | // TwUI 4 | // 5 | // Created by Josh Abernathy on 7/29/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "TUIButton+Accessibility.h" 10 | 11 | 12 | @implementation TUIButton (Accessibility) 13 | 14 | - (NSString *)accessibilityLabel 15 | { 16 | if(accessibilityLabel == nil) { 17 | return [self currentTitle]; 18 | } 19 | 20 | return accessibilityLabel; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /lib/UIKit/TUIButton+Content.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIButton.h" 18 | #import "TUIControl+Private.h" 19 | 20 | @interface TUIButtonContent : NSObject 21 | @property (nonatomic, strong) NSString *title; 22 | @property (nonatomic, strong) NSColor *titleColor; 23 | @property (nonatomic, strong) NSColor *shadowColor; 24 | @property (nonatomic, strong) NSImage *image; 25 | @property (nonatomic, strong) NSImage *backgroundImage; 26 | @end 27 | 28 | @implementation TUIButtonContent 29 | @synthesize title = title; 30 | @synthesize titleColor = titleColor; 31 | @synthesize shadowColor = shadowColor; 32 | @synthesize image = image; 33 | @synthesize backgroundImage = backgroundImage; 34 | @end 35 | 36 | 37 | @implementation TUIButton (Content) 38 | 39 | - (TUIButtonContent *)_contentForState:(TUIControlState)state 40 | { 41 | id key = @(state); 42 | TUIButtonContent *c = [_contentLookup objectForKey:key]; 43 | 44 | if (c == nil && (state & TUIControlStateNotKey)) { 45 | // Try matching without the NotKey state. 46 | c = [_contentLookup objectForKey:@(state & ~TUIControlStateNotKey)]; 47 | } 48 | 49 | if (c == nil) { 50 | c = [[TUIButtonContent alloc] init]; 51 | [_contentLookup setObject:c forKey:key]; 52 | } 53 | 54 | return c; 55 | } 56 | 57 | - (void)setTitle:(NSString *)title forState:(TUIControlState)state 58 | { 59 | [self _stateWillChange]; 60 | [[self _contentForState:state] setTitle:title]; 61 | [self setNeedsDisplay]; 62 | [self _stateDidChange]; 63 | } 64 | 65 | - (void)setTitleColor:(NSColor *)color forState:(TUIControlState)state 66 | { 67 | [self _stateWillChange]; 68 | [[self _contentForState:state] setTitleColor:color]; 69 | [self setNeedsDisplay]; 70 | [self _stateDidChange]; 71 | } 72 | 73 | - (void)setTitleShadowColor:(NSColor *)color forState:(TUIControlState)state 74 | { 75 | [self _stateWillChange]; 76 | [[self _contentForState:state] setShadowColor:color]; 77 | [self setNeedsDisplay]; 78 | [self _stateDidChange]; 79 | } 80 | 81 | - (void)setImage:(NSImage *)i forState:(TUIControlState)state 82 | { 83 | [self _stateWillChange]; 84 | [[self _contentForState:state] setImage:i]; 85 | [self setNeedsDisplay]; 86 | [self _stateDidChange]; 87 | } 88 | 89 | - (void)setBackgroundImage:(NSImage *)i forState:(TUIControlState)state 90 | { 91 | [self _stateWillChange]; 92 | [[self _contentForState:state] setBackgroundImage:i]; 93 | [self setNeedsDisplay]; 94 | [self _stateDidChange]; 95 | } 96 | 97 | - (NSString *)titleForState:(TUIControlState)state 98 | { 99 | return [[self _contentForState:state] title]; 100 | } 101 | 102 | - (NSColor *)titleColorForState:(TUIControlState)state 103 | { 104 | return [[self _contentForState:state] titleColor]; 105 | } 106 | 107 | - (NSColor *)titleShadowColorForState:(TUIControlState)state 108 | { 109 | return [[self _contentForState:state] shadowColor]; 110 | } 111 | 112 | - (NSImage *)imageForState:(TUIControlState)state 113 | { 114 | return [[self _contentForState:state] image]; 115 | } 116 | 117 | - (NSImage *)backgroundImageForState:(TUIControlState)state 118 | { 119 | return [[self _contentForState:state] backgroundImage]; 120 | } 121 | 122 | - (NSString *)currentTitle 123 | { 124 | NSString *title = [self titleForState:self.state]; 125 | if(title == nil) { 126 | title = [self titleForState:TUIControlStateNormal]; 127 | } 128 | 129 | return title; 130 | } 131 | 132 | - (NSColor *)currentTitleColor 133 | { 134 | NSColor *color = [self titleColorForState:self.state]; 135 | if(color == nil) { 136 | color = [self titleColorForState:TUIControlStateNormal]; 137 | } 138 | 139 | return color; 140 | } 141 | 142 | - (NSColor *)currentTitleShadowColor 143 | { 144 | NSColor *color = [self titleShadowColorForState:self.state]; 145 | if(color == nil) { 146 | color = [self titleShadowColorForState:TUIControlStateNormal]; 147 | } 148 | 149 | return color; 150 | } 151 | 152 | - (NSImage *)currentImage 153 | { 154 | NSImage *image = [self imageForState:self.state]; 155 | if(image == nil) { 156 | image = [self imageForState:TUIControlStateNormal]; 157 | } 158 | 159 | return image; 160 | } 161 | 162 | - (NSImage *)currentBackgroundImage 163 | { 164 | NSImage *image = [self backgroundImageForState:self.state]; 165 | if(image == nil) { 166 | image = [self backgroundImageForState:TUIControlStateNormal]; 167 | } 168 | 169 | return image; 170 | } 171 | 172 | @end 173 | -------------------------------------------------------------------------------- /lib/UIKit/TUIButton.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | TUIButton adopts some baggage from UIButton, probably a mistake 19 | this class is likely to change (be simplified) radically. 20 | */ 21 | 22 | #import "TUIControl.h" 23 | #import "TUIGeometry.h" 24 | 25 | @class TUILabel; 26 | @class TUIImageView; 27 | 28 | typedef enum { 29 | TUIButtonTypeCustom = 0, 30 | } TUIButtonType; 31 | 32 | @interface TUIButton : TUIControl 33 | { 34 | NSMutableDictionary *_contentLookup; 35 | TUIEdgeInsets _titleEdgeInsets; 36 | TUIEdgeInsets _imageEdgeInsets; 37 | 38 | TUIImageView *_imageView; 39 | TUILabel *_titleView; 40 | 41 | NSMenu *popUpMenu; 42 | 43 | struct { 44 | unsigned int dimsInBackground:1; 45 | unsigned int buttonType:8; 46 | unsigned int firstDraw:1; 47 | unsigned int reversesTitleShadowWhenHighlighted:1; 48 | } _buttonFlags; 49 | } 50 | 51 | + (id)buttonWithType:(TUIButtonType)buttonType; 52 | + (id)button; // custom 53 | 54 | @property(nonatomic,assign) TUIEdgeInsets titleEdgeInsets; 55 | @property(nonatomic,assign) TUIEdgeInsets imageEdgeInsets; 56 | @property(nonatomic,assign) BOOL dimsInBackground; 57 | 58 | @property(nonatomic,readonly) TUIButtonType buttonType; 59 | 60 | @property (nonatomic, strong) NSMenu *popUpMenu; 61 | 62 | @property(nonatomic,readonly,strong) TUILabel *titleLabel; 63 | @property(nonatomic,readonly,strong) TUIImageView *imageView; 64 | 65 | @property (nonatomic, assign) BOOL reversesTitleShadowWhenHighlighted; 66 | 67 | - (CGRect)backgroundRectForBounds:(CGRect)bounds; 68 | - (CGRect)contentRectForBounds:(CGRect)bounds; 69 | - (CGRect)titleRectForContentRect:(CGRect)contentRect; 70 | - (CGRect)imageRectForContentRect:(CGRect)contentRect; 71 | 72 | @end 73 | 74 | @interface TUIButton (Content) 75 | 76 | - (void)setTitle:(NSString *)title forState:(TUIControlState)state; 77 | - (void)setTitleColor:(NSColor *)color forState:(TUIControlState)state; 78 | - (void)setTitleShadowColor:(NSColor *)color forState:(TUIControlState)state; 79 | - (void)setImage:(NSImage *)image forState:(TUIControlState)state; 80 | - (void)setBackgroundImage:(NSImage *)image forState:(TUIControlState)state; 81 | 82 | - (NSString *)titleForState:(TUIControlState)state; 83 | - (NSColor *)titleColorForState:(TUIControlState)state; 84 | - (NSColor *)titleShadowColorForState:(TUIControlState)state; 85 | - (NSImage *)imageForState:(TUIControlState)state; 86 | - (NSImage *)backgroundImageForState:(TUIControlState)state; 87 | 88 | @property(nonatomic, readonly, strong) NSString *currentTitle; 89 | @property(nonatomic, readonly, strong) NSColor *currentTitleColor; 90 | @property(nonatomic, readonly, strong) NSColor *currentTitleShadowColor; 91 | @property(nonatomic, readonly, strong) NSImage *currentImage; 92 | @property(nonatomic, readonly, strong) NSImage *currentBackgroundImage; 93 | @end 94 | -------------------------------------------------------------------------------- /lib/UIKit/TUICGAdditions.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | enum _TUICGRoundedRectCorner { 18 | TUICGRoundedRectCornerTopLeft = 1 << 0, 19 | TUICGRoundedRectCornerTopRight = 1 << 1, 20 | TUICGRoundedRectCornerBottomLeft = 1 << 2, 21 | TUICGRoundedRectCornerBottomRight = 1 << 3, 22 | TUICGRoundedRectCornerTop = TUICGRoundedRectCornerTopLeft | TUICGRoundedRectCornerTopRight, 23 | TUICGRoundedRectCornerBottom = TUICGRoundedRectCornerBottomLeft | TUICGRoundedRectCornerBottomRight, 24 | TUICGRoundedRectCornerAll = TUICGRoundedRectCornerTopLeft | TUICGRoundedRectCornerTopRight | TUICGRoundedRectCornerBottomLeft | TUICGRoundedRectCornerBottomRight, 25 | TUICGRoundedRectCornerNone = 0, 26 | }; 27 | 28 | typedef NSUInteger TUICGRoundedRectCorner; 29 | 30 | #import 31 | 32 | @class TUIView; 33 | 34 | extern CGContextRef TUICreateOpaqueGraphicsContext(CGSize size); 35 | extern CGContextRef TUICreateGraphicsContext(CGSize size); 36 | extern CGContextRef TUICreateGraphicsContextWithOptions(CGSize size, BOOL opaque); 37 | extern CGImageRef TUICreateCGImageFromBitmapContext(CGContextRef ctx); 38 | 39 | extern CGPathRef TUICGPathCreateRoundedRect(CGRect rect, CGFloat radius); 40 | extern CGPathRef TUICGPathCreateRoundedRectWithCorners(CGRect rect, CGFloat radius, TUICGRoundedRectCorner corners); 41 | extern void CGContextAddRoundRect(CGContextRef context, CGRect rect, CGFloat radius); 42 | extern void CGContextClipToRoundRect(CGContextRef context, CGRect rect, CGFloat radius); 43 | 44 | extern CGRect ABScaleToFill(CGSize s, CGRect r); 45 | extern CGRect ABScaleToFit(CGSize s, CGRect r); 46 | extern CGRect ABRectCenteredInRect(CGRect a, CGRect b); 47 | extern CGRect ABRectRoundOrigin(CGRect f); 48 | extern CGRect ABIntegralRectWithSizeCenteredInRect(CGSize s, CGRect r); 49 | 50 | extern void CGContextFillRoundRect(CGContextRef context, CGRect rect, CGFloat radius); 51 | extern void CGContextDrawLinearGradientBetweenPoints(CGContextRef context, CGPoint a, CGFloat color_a[4], CGPoint b, CGFloat color_b[4]); 52 | 53 | extern CGContextRef TUIGraphicsGetCurrentContext(void); 54 | extern void TUIGraphicsPushContext(CGContextRef context); 55 | extern void TUIGraphicsPopContext(void); 56 | 57 | extern NSImage *TUIGraphicsContextGetImage(CGContextRef ctx); 58 | 59 | extern void TUIGraphicsBeginImageContext(CGSize size); 60 | // as in the iOS docs, "if you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen." 61 | extern void TUIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale); 62 | extern NSImage *TUIGraphicsGetImageFromCurrentImageContext(void); 63 | extern void TUIGraphicsEndImageContext(void); 64 | 65 | extern NSImage *TUIGraphicsGetImageForView(TUIView *view); 66 | 67 | extern NSImage *TUIGraphicsDrawAsImage(CGSize size, void(^draw)(void)); 68 | 69 | /** 70 | Draw drawing as a PDF 71 | @param optionalMediaBox may be NULL 72 | @returns NSData encapsulating the PDF drawing, suitable for writing to a file or the pasteboard 73 | */ 74 | extern NSData *TUIGraphicsDrawAsPDF(CGRect *optionalMediaBox, void(^draw)(CGContextRef)); 75 | -------------------------------------------------------------------------------- /lib/UIKit/TUIControl+Accessibility.h: -------------------------------------------------------------------------------- 1 | // 2 | // TUIControl+Accessibility.h 3 | // TwUI 4 | // 5 | // Created by Josh Abernathy on 7/29/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "TUIControl.h" 10 | 11 | 12 | @interface TUIControl (Accessibility) 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /lib/UIKit/TUIControl+Accessibility.m: -------------------------------------------------------------------------------- 1 | // 2 | // TUIControl+Accessibility.m 3 | // TwUI 4 | // 5 | // Created by Josh Abernathy on 7/29/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "TUIControl+Accessibility.h" 10 | 11 | 12 | @implementation TUIControl (Accessibility) 13 | 14 | 15 | #pragma mark NSAccessibility 16 | 17 | - (NSArray *)accessibilityActionNames 18 | { 19 | return [self allControlEvents] != 0 ? [NSArray arrayWithObject:NSAccessibilityPressAction] : [super accessibilityActionNames]; 20 | } 21 | 22 | - (NSString *)accessibilityActionDescription:(NSString *)action 23 | { 24 | if([action isEqualToString:NSAccessibilityPressAction]) { 25 | return NSLocalizedString(@"press", @""); 26 | } else { 27 | return nil; 28 | } 29 | } 30 | 31 | - (void)accessibilityPerformAction:(NSString *)action 32 | { 33 | if([action isEqualToString:NSAccessibilityPressAction]) { 34 | [self sendActionsForControlEvents:TUIControlEventAllMouseEvents]; 35 | } 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /lib/UIKit/TUIControl+Private.h: -------------------------------------------------------------------------------- 1 | // 2 | // TUIControl+Private.h 3 | // TwUI 4 | // 5 | // Created by Josh Abernathy on 7/19/11. 6 | // Copyright 2011 Maybe Apps, LLC. All rights reserved. 7 | // 8 | 9 | #import "TUIControl.h" 10 | 11 | @interface TUIControl (Private) 12 | 13 | - (void)_stateWillChange; 14 | - (void)_stateDidChange; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /lib/UIKit/TUIControl+Private.m: -------------------------------------------------------------------------------- 1 | // 2 | // TUIControl+Private.m 3 | // TwUI 4 | // 5 | // Created by Josh Abernathy on 7/19/11. 6 | // Copyright 2011 Maybe Apps, LLC. All rights reserved. 7 | // 8 | 9 | #import "TUIControl+Private.h" 10 | 11 | @implementation TUIControl (Private) 12 | 13 | - (void)_stateWillChange 14 | { 15 | 16 | } 17 | 18 | - (void)_stateDidChange 19 | { 20 | 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /lib/UIKit/TUIControl.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIView.h" 18 | 19 | enum { 20 | TUIControlEventMouseDown = 1 << 0, 21 | TUIControlEventMouseDownRepeat = 1 << 1, 22 | TUIControlEventMouseDragInside = 1 << 2, 23 | TUIControlEventMouseDragOutside = 1 << 3, 24 | /* 25 | Needs: 26 | TUIControlEventMouseDragEnter = 1 << 4, 27 | TUIControlEventMouseDragExit = 1 << 5, 28 | */ 29 | TUIControlEventMouseUpInside = 1 << 6, 30 | TUIControlEventMouseUpOutside = 1 << 7, 31 | TUIControlEventMouseCancel = 1 << 8, 32 | 33 | TUIControlEventMouseHover = 1 << 9, 34 | TUIControlEventValueChanged = 1 << 12, 35 | 36 | /* 37 | Needs: 38 | TUIControlEventEditingDidBegin = 1 << 16, 39 | TUIControlEventEditingChanged = 1 << 17, 40 | TUIControlEventEditingDidEnd = 1 << 18, 41 | */ 42 | TUIControlEventEditingDidEndOnExit = 1 << 19, 43 | 44 | TUIControlEventAllMouseEvents = 0x00000FFF, 45 | TUIControlEventAllEditingEvents = 0x000F0000, 46 | TUIControlEventApplicationReserved = 0x0F000000, 47 | TUIControlEventSystemReserved = 0xF0000000, 48 | TUIControlEventAllEvents = 0xFFFFFFFF 49 | }; 50 | typedef NSUInteger TUIControlEvents; 51 | 52 | enum { 53 | TUIControlStateNormal = 0, 54 | TUIControlStateHighlighted = 1 << 0, 55 | TUIControlStateDisabled = 1 << 1, 56 | TUIControlStateSelected = 1 << 2, 57 | TUIControlStateNotKey = 1 << 11, 58 | TUIControlStateApplication = 0x00FF0000, 59 | TUIControlStateReserved = 0xFF000000 60 | }; 61 | typedef NSUInteger TUIControlState; 62 | 63 | @interface TUIControl : TUIView 64 | { 65 | NSMutableArray* _targetActions; 66 | struct { 67 | unsigned int disabled:1; 68 | unsigned int selected:1; 69 | unsigned int acceptsFirstMouse:1; 70 | unsigned int tracking:1; 71 | unsigned int highlighted:1; 72 | } _controlFlags; 73 | } 74 | 75 | @property(nonatomic,getter=isEnabled) BOOL enabled; 76 | 77 | @property(nonatomic,readonly) TUIControlState state; 78 | @property(nonatomic,readonly,getter=isTracking) BOOL tracking; 79 | @property(nonatomic,assign) BOOL selected; 80 | @property (nonatomic, assign) BOOL highlighted; 81 | 82 | @property (nonatomic, assign) BOOL acceptsFirstMouse; 83 | 84 | // When control tracking begins, usually by mouse down or 85 | // swipe start, this method is called to validate the event. 86 | // If YES is returned, tracking will continue, otherwise 87 | // if NO is returned, tracking ends there itself. 88 | - (BOOL)beginTrackingWithEvent:(NSEvent *)event; 89 | 90 | // If the control opts to continue tracking, then this method 91 | // will be continuously called to validate each event in the 92 | // chain of tracking events, and should be used to update the 93 | // control view to reflect tracking changes. If YES is returned, 94 | // the control continues to receive tracking events. If NO 95 | // is returned, tracking ends there itself. 96 | - (BOOL)continueTrackingWithEvent:(NSEvent *)event; 97 | 98 | // When control tracking ends, this method is called to allow 99 | // the control to clean up. It is NOT called when the control 100 | // opts to cancel it - only when the user cancels the tracking. 101 | - (void)endTrackingWithEvent:(NSEvent *)event; 102 | 103 | @end 104 | 105 | @interface TUIControl (TargetAction) 106 | 107 | - (void)addTarget:(id)target action:(SEL)action forControlEvents:(TUIControlEvents)controlEvents; 108 | 109 | - (void)removeTarget:(id)target action:(SEL)action forControlEvents:(TUIControlEvents)controlEvents; 110 | 111 | - (void)addActionForControlEvents:(TUIControlEvents)controlEvents block:(void(^)(void))action; 112 | 113 | - (NSSet *)allTargets; 114 | - (TUIControlEvents)allControlEvents; 115 | - (NSArray *)actionsForTarget:(id)target forControlEvent:(TUIControlEvents)controlEvent; 116 | 117 | - (void)sendAction:(SEL)action to:(id)target forEvent:(NSEvent *)event; 118 | - (void)sendActionsForControlEvents:(TUIControlEvents)controlEvents; 119 | 120 | @end 121 | -------------------------------------------------------------------------------- /lib/UIKit/TUIGeometry.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import 18 | 19 | typedef struct TUIEdgeInsets { 20 | CGFloat top, left, bottom, right; // specify amount to inset (positive) for each of the edges. values can be negative to 'outset' 21 | } TUIEdgeInsets; 22 | 23 | static inline TUIEdgeInsets TUIEdgeInsetsMake(CGFloat top, CGFloat left, CGFloat bottom, CGFloat right) { 24 | TUIEdgeInsets insets = {top, left, bottom, right}; 25 | return insets; 26 | } 27 | 28 | static inline CGRect TUIEdgeInsetsInsetRect(CGRect rect, TUIEdgeInsets insets) { 29 | rect.origin.x += insets.left; 30 | rect.origin.y += insets.top; 31 | rect.size.width -= (insets.left + insets.right); 32 | rect.size.height -= (insets.top + insets.bottom); 33 | return rect; 34 | } 35 | 36 | static inline BOOL TUIEdgeInsetsEqualToEdgeInsets(TUIEdgeInsets insets1, TUIEdgeInsets insets2) { 37 | return insets1.left == insets2.left && insets1.top == insets2.top && insets1.right == insets2.right && insets1.bottom == insets2.bottom; 38 | } 39 | 40 | extern const TUIEdgeInsets TUIEdgeInsetsZero; 41 | 42 | /** 43 | * @brief Constrain a point to a rectangular region 44 | * 45 | * If the provided @p point lies outside the @p rect, it is adjusted to the 46 | * nearest point that lies inside the @p rect. 47 | * 48 | * @param point a point 49 | * @param rect the constraining rect 50 | * @return constrained point 51 | */ 52 | static inline CGPoint CGPointConstrainToRect(CGPoint point, CGRect rect) { 53 | return CGPointMake(MAX(rect.origin.x, MIN((rect.origin.x + rect.size.width), point.x)), MAX(rect.origin.y, MIN((rect.origin.y + rect.size.height), point.y))); 54 | } 55 | 56 | -------------------------------------------------------------------------------- /lib/UIKit/TUIGeometry.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIGeometry.h" 18 | 19 | const TUIEdgeInsets TUIEdgeInsetsZero = { 0.0, 0.0, 0.0, 0.0 }; 20 | -------------------------------------------------------------------------------- /lib/UIKit/TUIHostView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TUIHostView.h 3 | // TwUI 4 | // 5 | // Created by Justin Spahr-Summers on 17.07.12. 6 | // 7 | // Portions of this code were taken from Velvet, 8 | // which is copyright (c) 2012 Bitswift, Inc. 9 | // See LICENSE.txt for more information. 10 | // 11 | 12 | #import 13 | #import "TUIBridgedView.h" 14 | 15 | /** 16 | * Represents a view that can host views of other types (i.e., can bridge across 17 | * UI frameworks). 18 | */ 19 | @protocol TUIHostView 20 | @required 21 | 22 | /** 23 | * The view hosted by the receiver. 24 | * 25 | * Implementing classes may require that this property be of a more specific 26 | * type. 27 | * 28 | * When this property is set, the given view's [TUIBridgedView hostView] 29 | * property should automatically be set to the receiver. 30 | */ 31 | @property (nonatomic, strong) id rootView; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /lib/UIKit/TUIImageView.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIView.h" 18 | 19 | @interface TUIImageView : TUIView 20 | 21 | - (id)initWithImage:(NSImage *)image; 22 | 23 | @property(nonatomic, strong) NSImage *image; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /lib/UIKit/TUIImageView.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIImageView.h" 18 | 19 | @implementation TUIImageView 20 | @synthesize image = _image; 21 | 22 | - (void)setImage:(NSImage *)i 23 | { 24 | _image = i; 25 | [self setNeedsDisplay]; 26 | } 27 | 28 | - (id)initWithImage:(NSImage *)image 29 | { 30 | CGRect frame = CGRectZero; 31 | if (image) frame = CGRectMake(0, 0, image.size.width, image.size.height); 32 | 33 | self = [super initWithFrame:frame]; 34 | if (self == nil) return nil; 35 | 36 | self.userInteractionEnabled = NO; 37 | _image = image; 38 | 39 | return self; 40 | } 41 | 42 | - (void)drawRect:(CGRect)rect 43 | { 44 | [super drawRect:rect]; 45 | if (_image == nil) 46 | return; 47 | 48 | [_image drawInRect:rect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0]; 49 | } 50 | 51 | - (CGSize)sizeThatFits:(CGSize)size { 52 | return _image.size; 53 | } 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /lib/UIKit/TUIKit.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import 18 | 19 | #import "CAAnimation+TUIExtensions.h" 20 | #import "CoreText+Additions.h" 21 | #import "NSClipView+TUIExtensions.h" 22 | #import "NSColor+TUIExtensions.h" 23 | #import "NSImage+TUIExtensions.h" 24 | #import "NSScrollView+TUIExtensions.h" 25 | #import "NSView+TUIExtensions.h" 26 | #import "TUIActivityIndicatorView.h" 27 | #import "TUIAttributedString.h" 28 | #import "TUIBridgedScrollView.h" 29 | #import "TUIBridgedView.h" 30 | #import "TUIButton.h" 31 | #import "TUICGAdditions.h" 32 | #import "TUIHostView.h" 33 | #import "TUIImageView.h" 34 | #import "TUILabel.h" 35 | #import "TUILayoutConstraint.h" 36 | #import "TUINSView.h" 37 | #import "TUINSView+Hyperfocus.h" 38 | #import "TUINSView+NSTextInputClient.h" 39 | #import "TUINSWindow.h" 40 | #import "TUIPopover.h" 41 | #import "TUIProgressBar.h" 42 | #import "TUIResponder.h" 43 | #import "TUIScrollView.h" 44 | #import "TUIScrollView+TUIBridgedScrollView.h" 45 | #import "TUIStretchableImage.h" 46 | #import "TUIStringDrawing.h" 47 | #import "TUITableView+Additions.h" 48 | #import "TUITableView.h" 49 | #import "TUITableViewCell.h" 50 | #import "TUITableViewController.h" 51 | #import "TUITableViewSectionHeader.h" 52 | #import "TUITextEditor.h" 53 | #import "TUITextField.h" 54 | #import "TUITextView.h" 55 | #import "TUIView.h" 56 | #import "TUIView+Layout.h" 57 | #import "TUIView+TUIBridgedView.h" 58 | #import "TUIViewController.h" 59 | #import "TUIViewNSViewContainer.h" 60 | #import "NSFont+TUIExtensions.h" 61 | -------------------------------------------------------------------------------- /lib/UIKit/TUILabel.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIView.h" 18 | #import "TUIAttributedString.h" 19 | 20 | /* 21 | Check out TUITextRenderer, you probably want to use that to get 22 | subpixel AA and a flatter view heirarchy. 23 | */ 24 | 25 | @interface TUILabel : TUIView 26 | @property(nonatomic, copy) NSString *text; 27 | @property(nonatomic, strong) NSAttributedString *attributedString; 28 | @property(nonatomic, getter=isSelectable) BOOL selectable; 29 | @property(nonatomic, readonly) TUITextRenderer *renderer; 30 | @property(nonatomic, strong) NSFont *font; 31 | @property(nonatomic, strong) NSColor *textColor; 32 | @property(nonatomic, assign) TUITextAlignment alignment; 33 | @property(nonatomic, assign) TUILineBreakMode lineBreakMode; 34 | @end 35 | -------------------------------------------------------------------------------- /lib/UIKit/TUILabel.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUILabel.h" 18 | #import "TUINSView.h" 19 | #import "TUITextRenderer.h" 20 | 21 | @interface TUILabel () { 22 | struct { 23 | unsigned int selectable:1; 24 | } _textLabelFlags; 25 | } 26 | 27 | - (void)_recreateAttributedString; 28 | @end 29 | 30 | @implementation TUILabel 31 | 32 | @synthesize renderer; 33 | @synthesize text=_text; 34 | @synthesize font=_font; 35 | @synthesize textColor=_textColor; 36 | @synthesize alignment=_alignment; 37 | @synthesize lineBreakMode = _lineBreakMode; 38 | 39 | - (id)initWithFrame:(CGRect)frame 40 | { 41 | if((self = [super initWithFrame:frame])) { 42 | renderer = [[TUITextRenderer alloc] init]; 43 | renderer.verticalAlignment = TUITextVerticalAlignmentMiddle; 44 | [self setTextRenderers:[NSArray arrayWithObjects:renderer, nil]]; 45 | 46 | _lineBreakMode = TUILineBreakModeClip; 47 | _alignment = TUITextAlignmentLeft; 48 | } 49 | return self; 50 | } 51 | 52 | 53 | - (NSMenu *)menuForEvent:(NSEvent *)event 54 | { 55 | NSMenu *m = [[NSMenu alloc] initWithTitle:@""]; 56 | 57 | { 58 | NSMenuItem *i = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Copy",nil) action:@selector(copyText:) keyEquivalent:@""]; 59 | [i setKeyEquivalent:@"c"]; 60 | [i setKeyEquivalentModifierMask:NSCommandKeyMask]; 61 | [i setTarget:self]; 62 | [m addItem:i]; 63 | 64 | } 65 | 66 | return m; 67 | } 68 | - (void)copyText:(id)sender 69 | { 70 | [[NSPasteboard generalPasteboard] clearContents]; 71 | [[NSPasteboard generalPasteboard] writeObjects:[NSArray arrayWithObjects:[renderer selectedString], nil]]; 72 | } 73 | - (void)drawRect:(CGRect)rect 74 | { 75 | if(renderer.attributedString == nil) { 76 | [self _recreateAttributedString]; 77 | } 78 | 79 | [super drawRect:rect]; // draw background 80 | CGRect bounds = self.bounds; 81 | renderer.frame = CGRectMake(0, 0, bounds.size.width, bounds.size.height); 82 | [renderer draw]; 83 | } 84 | 85 | - (void)_update 86 | { 87 | [self setNeedsDisplay]; 88 | } 89 | 90 | - (NSAttributedString *)attributedString 91 | { 92 | if(renderer.attributedString == nil) { 93 | [self _recreateAttributedString]; 94 | } 95 | 96 | return renderer.attributedString; 97 | } 98 | 99 | - (void)setAttributedString:(NSAttributedString *)a 100 | { 101 | renderer.attributedString = a; 102 | [self _update]; 103 | } 104 | 105 | - (void)_recreateAttributedString 106 | { 107 | if(_text == nil) return; 108 | 109 | TUIAttributedString *newAttributedString = [TUIAttributedString stringWithString:_text]; 110 | if(_font != nil) newAttributedString.font = _font; 111 | if(_textColor != nil) newAttributedString.color = _textColor; 112 | [newAttributedString setAlignment:self.alignment lineBreakMode:self.lineBreakMode]; 113 | self.attributedString = newAttributedString; 114 | } 115 | 116 | - (BOOL)isSelectable 117 | { 118 | return _textLabelFlags.selectable; 119 | } 120 | 121 | - (void)setSelectable:(BOOL)b 122 | { 123 | _textLabelFlags.selectable = b; 124 | } 125 | 126 | - (void)setText:(NSString *)text 127 | { 128 | if(text == _text) return; 129 | 130 | _text = [text copy]; 131 | 132 | self.attributedString = nil; 133 | } 134 | 135 | - (void)setFont:(NSFont *)font 136 | { 137 | if(font == _font) return; 138 | 139 | _font = font; 140 | 141 | self.attributedString = nil; 142 | } 143 | 144 | - (void)setTextColor:(NSColor *)textColor 145 | { 146 | if(textColor == _textColor) return; 147 | 148 | _textColor = textColor; 149 | 150 | self.attributedString = nil; 151 | } 152 | 153 | - (void)setAlignment:(TUITextAlignment)alignment 154 | { 155 | if(alignment == _alignment) return; 156 | 157 | _alignment = alignment; 158 | 159 | self.attributedString = nil; 160 | } 161 | 162 | - (void)setLineBreakMode:(TUILineBreakMode)lineBreakMode 163 | { 164 | if (lineBreakMode == _lineBreakMode) return; 165 | 166 | _lineBreakMode = lineBreakMode; 167 | 168 | self.attributedString = nil; 169 | } 170 | 171 | @end 172 | -------------------------------------------------------------------------------- /lib/UIKit/TUILayoutManager.h: -------------------------------------------------------------------------------- 1 | @class TUILayoutConstraint; 2 | @class TUIView; 3 | 4 | /* 5 | 6 | The layout manager is penultimate to solving constraints. It handles 7 | views marked as needing processing, and recursively invokes the 8 | constraint solver per view when required. 9 | 10 | However, it also provides a bridge to the constraints and the views 11 | by mediating the adding or removing of a constraint to and from a view. 12 | 13 | Views are marked by an internal layout name, to which they are 14 | then referred to from within constraints. 15 | 16 | CAUTION: 17 | This class has been marked as requiring refactorization 18 | and should not be used directly. It will become private soon. 19 | 20 | NOTE: 21 | Layout names as identifiers might be removed in future updates. 22 | 23 | */ 24 | 25 | @interface TUILayoutManager : NSObject 26 | 27 | /* 28 | 29 | Requests the shared layout manager, the preferred usage method. This 30 | shared manager then handles the constraint system for the global space. 31 | 32 | You may also use -init to create a local layout manager, in cases where 33 | you may want your constraint system to be factored and isolated, or 34 | where you may be using TUIViews only in certain places, and not the whole 35 | window or application. 36 | 37 | */ 38 | + (id)sharedLayoutManager; 39 | 40 | /* 41 | 42 | Provides a bridge to add a constraint to a view, or remove a constraint 43 | from a view. You can also remove ALL layout constraints on a view, and 44 | retrieve an array of constraints currently attached to a view. 45 | 46 | */ 47 | - (void)addLayoutConstraint:(TUILayoutConstraint *)constraint toView:(TUIView *)view; 48 | - (void)removeLayoutConstraint:(TUILayoutConstraint *)constraint fromView:(TUIView *)view; 49 | - (void)removeLayoutConstraintsFromView:(TUIView *)view; 50 | 51 | - (NSArray *)layoutConstraintsOnView:(TUIView *)view; 52 | - (void)removeAllLayoutConstraints; 53 | 54 | /* 55 | Provides a bridge for the TUIView layout name identifier. 56 | */ 57 | - (NSString *)layoutNameForView:(TUIView *)view; 58 | - (void)setLayoutName:(NSString *)name forView:(TUIView *)view; 59 | 60 | /* 61 | Similar to -redraw on a TUIView, but for constraints. Forces a re-processing 62 | of all constraints attached to a view. 63 | */ 64 | - (void)beginProcessingView:(TUIView *)aView; 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /lib/UIKit/TUINSView+Accessibility.h: -------------------------------------------------------------------------------- 1 | // 2 | // TUINSView+Accessibility.h 3 | // TwUI 4 | // 5 | // Created by Josh Abernathy on 7/28/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TUINSView.h" 11 | 12 | 13 | @interface TUINSView (Accessibility) 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /lib/UIKit/TUINSView+Accessibility.m: -------------------------------------------------------------------------------- 1 | // 2 | // TUINSView+Accessibility.m 3 | // TwUI 4 | // 5 | // Created by Josh Abernathy on 7/28/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "TUINSView+Accessibility.h" 10 | 11 | 12 | @implementation TUINSView (Accessibility) 13 | 14 | - (id)accessibilityHitTest:(NSPoint)point 15 | { 16 | NSPoint windowPoint = [[self window] convertScreenToBase:point]; 17 | NSPoint localPoint = [self convertPoint:windowPoint fromView:nil]; 18 | return [self.rootView accessibilityHitTest:localPoint]; 19 | } 20 | 21 | - (BOOL)accessibilityIsIgnored 22 | { 23 | return YES; 24 | } 25 | 26 | - (NSArray *)accessibilityAttributeNames 27 | { 28 | static NSArray *attributes = nil; 29 | if(attributes == nil) { 30 | attributes = [[NSArray alloc] initWithObjects:NSAccessibilityChildrenAttribute, NSAccessibilityParentAttribute, NSAccessibilityWindowAttribute, NSAccessibilityTopLevelUIElementAttribute, NSAccessibilityPositionAttribute, NSAccessibilitySizeAttribute, nil]; 31 | } 32 | 33 | return attributes; 34 | } 35 | 36 | - (id)accessibilityAttributeValue:(NSString *)attribute 37 | { 38 | if([attribute isEqualToString:NSAccessibilityChildrenAttribute]) { 39 | return [NSArray arrayWithObject:self.rootView]; 40 | } else if([attribute isEqualToString:NSAccessibilityParentAttribute]) { 41 | return NSAccessibilityUnignoredAncestor(self.superview); 42 | } else if([attribute isEqualToString:NSAccessibilityWindowAttribute]) { 43 | return [self.superview accessibilityAttributeValue:NSAccessibilityWindowAttribute]; 44 | } else if([attribute isEqualToString:NSAccessibilityTopLevelUIElementAttribute]) { 45 | return [self.superview accessibilityAttributeValue:NSAccessibilityTopLevelUIElementAttribute]; 46 | } else if([attribute isEqualToString:NSAccessibilityPositionAttribute]) { 47 | return [NSValue valueWithPoint:[[self window] convertBaseToScreen:[self convertPoint:self.bounds.origin toView:nil]]]; 48 | } else if([attribute isEqualToString:NSAccessibilitySizeAttribute]) { 49 | return [NSValue valueWithSize:self.bounds.size]; 50 | } else { 51 | return nil; 52 | } 53 | } 54 | 55 | - (BOOL)accessibilityIsAttributeSettable:(NSString *)attribute 56 | { 57 | return NO; 58 | } 59 | 60 | - (NSArray *)accessibilityActionNames 61 | { 62 | return [NSArray array]; 63 | } 64 | 65 | - (id)accessibilityFocusedUIElement 66 | { 67 | return NSAccessibilityUnignoredAncestor(self); 68 | } 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /lib/UIKit/TUINSView+Hyperfocus.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import 18 | 19 | @class TUINSView; 20 | 21 | @interface TUINSView (Hyperfocus) 22 | 23 | - (void)hyperFocus:(TUIView *)focusView completion:(void(^)(BOOL cancelled))completion; 24 | - (void)endHyperFocus:(BOOL)cancel; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /lib/UIKit/TUINSView+Hyperfocus.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUINSView.h" 18 | #import "TUICGAdditions.h" 19 | #import "TUINSView+Hyperfocus.h" 20 | 21 | @implementation TUINSView (Hyperfocus) 22 | 23 | - (void)endHyperFocus:(BOOL)cancel 24 | { 25 | if(_hyperFocusView) { 26 | _hyperCompletion(cancel); 27 | _hyperCompletion = nil; 28 | 29 | TUIView *remove = _hyperFadeView; 30 | [TUIView animateWithDuration:0.3 animations:^{ 31 | remove.alpha = 0.0; 32 | } completion:^(BOOL finished) { 33 | [remove removeFromSuperview]; 34 | }]; 35 | 36 | _hyperFadeView = nil; 37 | _hyperFocusView = nil; 38 | } 39 | } 40 | 41 | - (void)hyperFocus:(TUIView *)focusView completion:(void(^)(BOOL))completion 42 | { 43 | [self endHyperFocus:YES]; 44 | 45 | CGRect focusRect = [focusView frameInNSView]; 46 | CGFloat startRadius = 1.0; 47 | CGFloat endRadius = MAX(self.rootView.bounds.size.width, self.rootView.bounds.size.height); 48 | CGPoint center = CGPointMake(focusRect.origin.x + focusRect.size.width * 0.5, focusRect.origin.y + focusRect.size.height * 0.5); 49 | 50 | TUIView *fade = [[TUIView alloc] initWithFrame:self.rootView.bounds]; 51 | fade.userInteractionEnabled = NO; 52 | fade.autoresizingMask = TUIViewAutoresizingFlexibleSize; 53 | fade.opaque = NO; 54 | fade.drawRect = ^(TUIView *v, CGRect r) { 55 | CGContextRef ctx = TUIGraphicsGetCurrentContext(); 56 | 57 | CGFloat locations[] = {0.0, 0.25, 1.0}; 58 | CGFloat components[] = { 59 | 0.0, 0.0, 0.0, 0.0, 60 | 0.0, 0.0, 0.0, 0.15, 61 | 0.0, 0.0, 0.0, 0.55, 62 | }; 63 | 64 | CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB(); 65 | CGGradientRef gradient = CGGradientCreateWithColorComponents(space, components, locations, 3); 66 | 67 | // CGContextSaveGState(ctx); 68 | // CGContextClipToRoundRect(ctx, self.rootView.bounds, 9); 69 | CGContextDrawRadialGradient(ctx, gradient, center, startRadius, center, endRadius, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); 70 | // CGContextRestoreGState(ctx); 71 | 72 | CGGradientRelease(gradient); 73 | CGColorSpaceRelease(space); 74 | }; 75 | 76 | [CATransaction begin]; 77 | fade.alpha = 0.0; 78 | [self.rootView addSubview:fade]; 79 | [CATransaction flush]; 80 | [CATransaction commit]; 81 | 82 | 83 | [TUIView animateWithDuration:0.2 animations:^{ 84 | fade.alpha = 1.0; 85 | }]; 86 | 87 | _hyperFocusView = focusView; 88 | _hyperFadeView = fade; 89 | _hyperCompletion = [completion copy]; 90 | } 91 | 92 | @end 93 | -------------------------------------------------------------------------------- /lib/UIKit/TUINSView+NSTextInputClient.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUINSView.h" 18 | 19 | @interface TUINSView (NSTextInputClient) 20 | @end 21 | -------------------------------------------------------------------------------- /lib/UIKit/TUINSView+Private.h: -------------------------------------------------------------------------------- 1 | // 2 | // TUINSView+Private.h 3 | // TwUI 4 | // 5 | // Created by Justin Spahr-Summers on 17.07.12. 6 | // 7 | // Portions of this code were taken from Velvet, 8 | // which is copyright (c) 2012 Bitswift, Inc. 9 | // See LICENSE.txt for more information. 10 | // 11 | 12 | #import "TUINSView.h" 13 | 14 | /* 15 | * Private functionality of TUINSView that needs to be exposed to other parts of 16 | * the framework. 17 | */ 18 | @interface TUINSView () 19 | 20 | /* 21 | * The layer-backed view which actually holds the AppKit hierarchy. 22 | */ 23 | @property (nonatomic, readonly, strong) NSView *appKitHostView; 24 | 25 | // The view currently tracking mouse events. 26 | @property (nonatomic, unsafe_unretained) TUIView *trackingView; 27 | 28 | /* 29 | * Informs the receiver that the clipping of a TUIViewNSViewContainer it is hosting has 30 | * changed, and asks it to update clipping paths accordingly. 31 | */ 32 | - (void)recalculateNSViewClipping; 33 | 34 | /* 35 | * Informs the receiver that the ordering of a TUIViewNSViewContainer it is hosting has 36 | * changed, and asks it to reorder its subviews to match TwUI. 37 | */ 38 | - (void)recalculateNSViewOrdering; 39 | 40 | - (TUIView *)viewForLocalPoint:(NSPoint)p; 41 | - (NSPoint)localPointForLocationInWindow:(NSPoint)locationInWindow; 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /lib/UIKit/TUINSView.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import 18 | #import "TUIHostView.h" 19 | #import "TUIView+TUIBridgedView.h" 20 | 21 | @class TUITextRenderer; 22 | 23 | /** 24 | TUINSView is the bridge that hosts a TUIView-based interface heirarchy. You may add it as the contentView of your window if you want to build a pure TwUI-based UI, or you can use it for a small part. 25 | */ 26 | @interface TUINSView : NSView 27 | { 28 | TUIView *_hoverView; 29 | 30 | __unsafe_unretained TUIView *_hyperFocusView; // hyperfocus view, weak 31 | 32 | TUIView *_hyperFadeView; 33 | void(^_hyperCompletion)(BOOL); 34 | 35 | NSTrackingArea *_trackingArea; 36 | 37 | __unsafe_unretained TUITextRenderer *_tempTextRendererForTextInputClient; // weak, set temporarily while NSTextInputClient dicks around 38 | 39 | BOOL deliveringEvent; 40 | BOOL inLiveResize; 41 | 42 | BOOL opaque; 43 | } 44 | 45 | /** 46 | Set this as the root TUIView-based view. 47 | */ 48 | @property (nonatomic, strong) TUIView *rootView; 49 | 50 | - (TUIView *)viewForLocationInWindow:(NSPoint)locationInWindow; 51 | - (TUIView *)viewForEvent:(NSEvent *)event; // ignores views with 'userInteractionEnabled=NO' 52 | 53 | - (void)setEverythingNeedsDisplay; 54 | - (void)invalidateHoverForView:(TUIView *)v; 55 | 56 | - (NSMenu *)menuWithPatchedItems:(NSMenu *)menu; // don't use this 57 | 58 | - (BOOL)isTrackingSubviewOfView:(TUIView *)v; 59 | - (BOOL)isHoveringSubviewOfView:(TUIView *)v; // v or subview of v 60 | - (BOOL)isHoveringView:(TUIView *)v; // only v 61 | 62 | - (void)tui_setOpaque:(BOOL)o; 63 | 64 | - (BOOL)isWindowKey; 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /lib/UIKit/TUINSWindow.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import 18 | 19 | @class TUINSView; 20 | 21 | @interface NSWindow (TUIWindowAdditions) 22 | 23 | - (NSArray *)TUINSViews; 24 | - (void)setEverythingNeedsDisplay; 25 | 26 | - (BOOL)tui_containsObjectInResponderChain:(NSResponder *)r; 27 | 28 | /* 29 | If you know you need to make something first responder in the future (say, after an animation completes), 30 | but not if something is made first responder in the meantime, use this: 31 | 1. request a token with futureMakeFirstResponderRequestToken 32 | 2. when the animation completes, try to make first responder with 33 | makeFirstResponder:withFutureRequestToken: 34 | 3. it will succeed if nothing else made something else first responder before you did 35 | 36 | Currently used by TUITableView for when you're arrowing around really fast, and switch sections before 37 | the selected cell comes onscreen. 38 | 39 | Note this has only been tested with a NSWindow subclass that overrides -makeFirstResponder directly, 40 | not with a vanilla NSWindow since I started moving these methods into a category. 41 | */ 42 | 43 | - (BOOL)tui_makeFirstResponder:(NSResponder *)aResponder; // increments future token 44 | 45 | - (NSInteger)futureMakeFirstResponderRequestToken; 46 | - (BOOL)makeFirstResponder:(NSResponder *)aResponder withFutureRequestToken:(NSInteger)token; 47 | - (BOOL)makeFirstResponderIfNotAlreadyInResponderChain:(NSResponder *)responder; 48 | - (BOOL)makeFirstResponderIfNotAlreadyInResponderChain:(NSResponder *)responder withFutureRequestToken:(NSInteger)token; 49 | 50 | @end 51 | 52 | /* 53 | If you're not Twitter for Mac, you probably don't want to use TUINSWindow. 54 | Just use a plain NSWindow, this class will likely be removed from TUIKit 55 | once a bit of cleanup happens on Twitter for Mac. See the category above 56 | for stuff that you can use on any NSWindow instance. 57 | */ 58 | 59 | @interface TUINSWindow : NSWindow 60 | { 61 | TUINSView *nsView; 62 | NSMutableArray *altUINSViews; // kill 63 | } 64 | 65 | - (id)initWithContentRect:(CGRect)rect; 66 | 67 | - (void)drawBackground:(CGRect)rect; 68 | 69 | - (CGFloat)toolbarHeight; 70 | 71 | @property (nonatomic, readonly) TUINSView *nsView; 72 | @property (nonatomic, readonly) NSMutableArray *altUINSViews; // add to this to participate in setEverythingNeedsDisplay 73 | 74 | @end 75 | 76 | extern NSRect ABClampProposedRectToScreen(NSRect proposedRect); 77 | -------------------------------------------------------------------------------- /lib/UIKit/TUIPopover.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2012 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIView.h" 18 | 19 | @class TUIPopover; 20 | @class TUIViewController; 21 | 22 | enum _TUIPopoverViewControllerBehaviour 23 | { 24 | TUIPopoverViewControllerBehaviourApplicationDefined = 0, 25 | TUIPopoverViewControllerBehaviourTransient = 1, 26 | TUIPopoverViewControllerBehaviourSemiTransient = 2 //Currently not supported, here for forwards compatibility purposes 27 | }; 28 | 29 | typedef NSUInteger TUIPopoverViewControllerBehaviour; 30 | 31 | typedef void (^TUIPopoverDelegateBlock)(TUIPopover *popover); 32 | 33 | @interface TUIPopover : NSResponder 34 | 35 | @property (nonatomic, strong) TUIViewController *contentViewController; 36 | @property (nonatomic, unsafe_unretained) Class backgroundViewClass; //Must be a subclass of TUIPopoverBackgroundView 37 | @property (nonatomic, unsafe_unretained) CGSize contentSize; //CGSizeZero uses the size of the view on contentViewController 38 | @property (nonatomic, unsafe_unretained) BOOL animates; 39 | @property (nonatomic, unsafe_unretained) TUIPopoverViewControllerBehaviour behaviour; 40 | @property (nonatomic, readonly) BOOL shown; 41 | @property (nonatomic, readonly) CGRect positioningRect; 42 | 43 | //Block callbacks 44 | @property (nonatomic, copy) TUIPopoverDelegateBlock willCloseBlock; 45 | @property (nonatomic, copy) TUIPopoverDelegateBlock didCloseBlock; 46 | 47 | @property (nonatomic, copy) TUIPopoverDelegateBlock willShowBlock; 48 | @property (nonatomic, copy) TUIPopoverDelegateBlock didShowBlock; 49 | 50 | - (id)initWithContentViewController:(TUIViewController *)viewController; 51 | 52 | - (void)showRelativeToRect:(CGRect)positioningRect ofView:(TUIView *)positioningView preferredEdge:(CGRectEdge)preferredEdge; 53 | 54 | - (void)close; 55 | - (void)closeWithFadeoutDuration:(NSTimeInterval)duration; 56 | - (IBAction)performClose:(id)sender; 57 | 58 | @end 59 | 60 | @interface TUIPopoverBackgroundView : TUIView 61 | 62 | + (CGSize)sizeForBackgroundViewWithContentSize:(CGSize)contentSize popoverEdge:(CGRectEdge)popoverEdge; 63 | + (CGRect)contentViewFrameForBackgroundFrame:(CGRect)frame popoverEdge:(CGRectEdge)popoverEdge; 64 | + (TUIPopoverBackgroundView *)backgroundViewForContentSize:(CGSize)contentSize popoverEdge:(CGRectEdge)popoverEdge originScreenRect:(CGRect)originScreenRect; 65 | 66 | - (id)initWithFrame:(CGRect)frame popoverEdge:(CGRectEdge)popoverEdge originScreenRect:(CGRect)originScreenRect; 67 | - (CGPathRef)newPopoverPathForEdge:(CGRectEdge)popoverEdge inFrame:(CGRect)frame; //override in subclasses to change the shape of the popover, but still use the default drawing. 68 | 69 | //Used in the default implementation 70 | @property (nonatomic, strong) NSColor *strokeColor; 71 | @property (nonatomic, strong) NSColor *fillColor; 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /lib/UIKit/TUIProgressBar.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2012 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIView.h" 18 | 19 | enum _TUIProgressBarStyle 20 | { 21 | TUIProgressBarStyleBlue = 0, //default 22 | TUIProgressBarStyleGray 23 | }; 24 | 25 | typedef NSUInteger TUIProgressBarStyle; 26 | 27 | @interface TUIProgressBar : TUIView 28 | 29 | @property (nonatomic, assign) CGFloat progress; 30 | @property (nonatomic, assign, getter = isIndeterminate) BOOL indeterminate; 31 | 32 | //Drawing 33 | @property (nonatomic, strong) TUIViewDrawRect drawTrack; 34 | @property (nonatomic, strong) TUIViewDrawRect drawFill; 35 | 36 | - (id)initWithFrame:(CGRect)frame style:(TUIProgressBarStyle)style; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /lib/UIKit/TUIResponder.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import 18 | #import 19 | 20 | @interface TUIResponder : NSResponder 21 | 22 | /* Use from NSResponder 23 | - (NSResponder *)nextResponder; 24 | - (BOOL)becomeFirstResponder; 25 | - (BOOL)resignFirstResponder; 26 | */ 27 | 28 | @property (strong, nonatomic, readonly) TUIResponder *initialFirstResponder; 29 | 30 | - (NSMenu *)menuForEvent:(NSEvent *)event; 31 | - (BOOL)acceptsFirstMouse:(NSEvent *)event; 32 | - (BOOL)performKeyAction:(NSEvent *)event; // similar semantics to performKeyEquivalent, as in you can implement, but return NO if you don't want to responsibility based on the event, but it travels *up the responder chain*, rather that to everything 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /lib/UIKit/TUIResponder.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIResponder.h" 18 | 19 | @implementation TUIResponder 20 | 21 | - (BOOL)becomeFirstResponder 22 | { 23 | return YES; 24 | } 25 | 26 | - (BOOL)resignFirstResponder 27 | { 28 | return YES; 29 | } 30 | 31 | - (BOOL)acceptsFirstMouse:(NSEvent *)event 32 | { 33 | return YES; // Controls default to NO 34 | } 35 | 36 | - (NSMenu *)menuForEvent:(NSEvent *)event 37 | { 38 | return nil; 39 | } 40 | 41 | - (BOOL)performKeyAction:(NSEvent *)event 42 | { 43 | return NO; 44 | } 45 | 46 | - (TUIResponder *)initialFirstResponder 47 | { 48 | return self; 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /lib/UIKit/TUIScrollKnob.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIView.h" 18 | 19 | @class TUIScrollView; 20 | 21 | @interface TUIScrollKnob : TUIView 22 | { 23 | TUIScrollView *__unsafe_unretained scrollView; 24 | TUIView *knob; 25 | CGPoint _mouseDown; 26 | CGRect _knobStartFrame; 27 | 28 | struct { 29 | unsigned int hover:1; 30 | unsigned int active:1; 31 | unsigned int trackingInsideKnob:1; 32 | unsigned int scrollIndicatorStyle:2; 33 | unsigned int flashing:1; 34 | } _scrollKnobFlags; 35 | } 36 | 37 | @property (nonatomic, unsafe_unretained) TUIScrollView *scrollView; 38 | @property (nonatomic, assign) unsigned int scrollIndicatorStyle; 39 | @property (nonatomic, readonly) TUIView *knob; 40 | @property (nonatomic, readonly) BOOL flashing; 41 | 42 | - (void)flash; 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /lib/UIKit/TUIScrollView+TUIBridgedScrollView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TUIScrollView+TUIBridgedScrollView.h 3 | // TwUI 4 | // 5 | // Created by Justin Spahr-Summers on 17.07.12. 6 | // 7 | // Portions of this code were taken from Velvet, 8 | // which is copyright (c) 2012 Bitswift, Inc. 9 | // See LICENSE.txt for more information. 10 | // 11 | 12 | #import "TUIBridgedScrollView.h" 13 | #import "TUIScrollView.h" 14 | 15 | /** 16 | * Implements support for the c protocol on TUIScrollView. 17 | */ 18 | @interface TUIScrollView (TUIBridgedScrollView) 19 | @end 20 | -------------------------------------------------------------------------------- /lib/UIKit/TUIScrollView+TUIBridgedScrollView.m: -------------------------------------------------------------------------------- 1 | // 2 | // TUIScrollView+TUIBridgedScrollView.m 3 | // TwUI 4 | // 5 | // Created by Justin Spahr-Summers on 17.07.12. 6 | // 7 | // Portions of this code were taken from Velvet, 8 | // which is copyright (c) 2012 Bitswift, Inc. 9 | // See LICENSE.txt for more information. 10 | // 11 | 12 | #import "TUIScrollView+TUIBridgedScrollView.h" 13 | #import "TUIView+TUIBridgedView.h" 14 | 15 | @implementation TUIScrollView (TUIBridgedScrollView) 16 | 17 | #pragma mark TUIBridgedView 18 | 19 | // implemented by TUIView 20 | @dynamic layer; 21 | @dynamic hostView; 22 | 23 | #pragma mark TUIBridgedScrollView 24 | 25 | - (void)scrollToPoint:(CGPoint)point; { 26 | [self setContentOffset:point animated:YES]; 27 | } 28 | 29 | - (void)scrollToIncludeRect:(CGRect)rect; { 30 | [self scrollRectToVisible:rect animated:YES]; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /lib/UIKit/TUIStretchableImage.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import 18 | #import "TUIGeometry.h" 19 | 20 | /* 21 | * An image that supports resizing based on end caps. 22 | */ 23 | @interface TUIStretchableImage : NSImage 24 | 25 | /* 26 | * The end cap insets for the image. 27 | * 28 | * Any portion of the image not covered by end caps will be tiled when the image 29 | * is drawn. 30 | */ 31 | @property (nonatomic, assign) TUIEdgeInsets tui_capInsets; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /lib/UIKit/TUIStringDrawing.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import 18 | #import "TUIAttributedString.h" 19 | 20 | @class NSFont; 21 | 22 | @interface NSAttributedString (TUIStringDrawing) 23 | 24 | - (CGSize)ab_size; 25 | - (CGSize)ab_sizeConstrainedToSize:(CGSize)size; 26 | - (CGSize)ab_sizeConstrainedToWidth:(CGFloat)width; 27 | 28 | - (CGSize)ab_drawInRect:(CGRect)rect; 29 | - (CGSize)ab_drawInRect:(CGRect)rect context:(CGContextRef)ctx; 30 | 31 | @end 32 | 33 | @interface NSString (TUIStringDrawing) 34 | 35 | - (CGSize)ab_sizeWithFont:(NSFont *)font; 36 | - (CGSize)ab_sizeWithFont:(NSFont *)font constrainedToSize:(CGSize)size; 37 | 38 | #if TARGET_OS_MAC 39 | // for ABRowView 40 | //- (CGSize)drawInRect:(CGRect)rect withFont:(NSFont *)font lineBreakMode:(TUILineBreakMode)lineBreakMode alignment:(TUITextAlignment)alignment; 41 | #endif 42 | 43 | - (CGSize)ab_drawInRect:(CGRect)rect color:(NSColor *)color font:(NSFont *)font; 44 | - (CGSize)ab_drawInRect:(CGRect)rect withFont:(NSFont *)font lineBreakMode:(TUILineBreakMode)lineBreakMode alignment:(TUITextAlignment)alignment; 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /lib/UIKit/TUIStringDrawing.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIAttributedString.h" 18 | #import "TUICGAdditions.h" 19 | #import "TUIStringDrawing.h" 20 | #import "TUITextRenderer.h" 21 | 22 | @implementation NSAttributedString (TUIStringDrawing) 23 | 24 | - (TUITextRenderer *)ab_sharedTextRenderer 25 | { 26 | static TUITextRenderer *t = nil; 27 | if(!t) 28 | t = [[TUITextRenderer alloc] init]; 29 | return t; 30 | } 31 | 32 | - (CGSize)ab_sizeConstrainedToWidth:(CGFloat)width 33 | { 34 | return [self ab_sizeConstrainedToSize:CGSizeMake(width, 2000)]; // big enough 35 | } 36 | 37 | - (CGSize)ab_sizeConstrainedToSize:(CGSize)size 38 | { 39 | TUITextRenderer *t = [self ab_sharedTextRenderer]; 40 | t.attributedString = self; 41 | t.frame = CGRectMake(0, 0, size.width, size.height); 42 | return [t size]; 43 | } 44 | 45 | - (CGSize)ab_size 46 | { 47 | return [self ab_sizeConstrainedToSize:CGSizeMake(2000, 2000)]; // big enough 48 | } 49 | 50 | - (CGSize)ab_drawInRect:(CGRect)rect context:(CGContextRef)ctx 51 | { 52 | TUITextRenderer *t = [self ab_sharedTextRenderer]; 53 | t.attributedString = self; 54 | t.frame = rect; 55 | [t drawInContext:ctx]; 56 | return [t size]; 57 | } 58 | 59 | - (CGSize)ab_drawInRect:(CGRect)rect 60 | { 61 | return [self ab_drawInRect:rect context:TUIGraphicsGetCurrentContext()]; 62 | } 63 | 64 | @end 65 | 66 | @implementation NSString (TUIStringDrawing) 67 | 68 | #if TARGET_OS_MAC 69 | 70 | - (CGSize)ab_sizeWithFont:(NSFont *)font 71 | { 72 | TUIAttributedString *s = [TUIAttributedString stringWithString:self]; 73 | s.font = font; 74 | return [s ab_size]; 75 | } 76 | 77 | - (CGSize)ab_sizeWithFont:(NSFont *)font constrainedToSize:(CGSize)size 78 | { 79 | TUIAttributedString *s = [TUIAttributedString stringWithString:self]; 80 | s.font = font; 81 | return [s ab_sizeConstrainedToSize:size]; 82 | } 83 | 84 | //- (CGSize)drawInRect:(CGRect)rect withFont:(NSFont *)font lineBreakMode:(TUILineBreakMode)lineBreakMode alignment:(TUITextAlignment)alignment 85 | //{ 86 | // return [self ab_drawInRect:rect withFont:font lineBreakMode:lineBreakMode alignment:alignment]; 87 | //} 88 | 89 | #endif 90 | 91 | - (CGSize)ab_drawInRect:(CGRect)rect color:(NSColor *)color font:(NSFont *)font 92 | { 93 | TUIAttributedString *s = [TUIAttributedString stringWithString:self]; 94 | s.color = color; 95 | s.font = font; 96 | return [s ab_drawInRect:rect]; 97 | } 98 | 99 | - (CGSize)ab_drawInRect:(CGRect)rect withFont:(NSFont *)font lineBreakMode:(TUILineBreakMode)lineBreakMode alignment:(TUITextAlignment)alignment 100 | { 101 | TUIAttributedString *s = [TUIAttributedString stringWithString:self]; 102 | [s addAttribute:(NSString *)kCTForegroundColorFromContextAttributeName 103 | value:(id)[NSNumber numberWithBool:YES] 104 | range:NSMakeRange(0, [self length])]; 105 | [s setAlignment:alignment lineBreakMode:lineBreakMode]; 106 | s.font = font; 107 | return [s ab_drawInRect:rect]; 108 | } 109 | 110 | @end 111 | -------------------------------------------------------------------------------- /lib/UIKit/TUITableView+Additions.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUITableView.h" 18 | 19 | typedef void (^TUITableViewInitializationBlock)(id cell); 20 | 21 | @interface TUITableView (Additions) 22 | 23 | - (TUITableViewCell *)ab_reusableCellOfClass:(Class)cellClass identifier:(NSString *)identifier initializationBlock:(TUITableViewInitializationBlock)block; 24 | 25 | @end 26 | 27 | #define reusableTableCellOfClassWithBlock(TABLE, CLASS, BLOCK) \ 28 | (CLASS *)[(TABLE) ab_reusableCellOfClass:[CLASS class] identifier:@"ab." @#CLASS initializationBlock:BLOCK] 29 | 30 | #define reusableTableCellOfClass(TABLE, CLASS) \ 31 | (CLASS *)[(TABLE) ab_reusableCellOfClass:[CLASS class] identifier:@"ab." @#CLASS initializationBlock:nil] 32 | -------------------------------------------------------------------------------- /lib/UIKit/TUITableView+Additions.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUITableView+Additions.h" 18 | 19 | @implementation TUITableView (Additions) 20 | 21 | - (TUITableViewCell *)ab_reusableCellOfClass:(Class)cellClass identifier:(NSString *)identifier initializationBlock:(TUITableViewInitializationBlock)block 22 | { 23 | TUITableViewCell *cell = [self dequeueReusableCellWithIdentifier:identifier]; 24 | if(!cell) { 25 | cell = [[cellClass alloc] initWithStyle:TUITableViewCellStyleDefault reuseIdentifier:identifier]; 26 | if(block != nil) block(cell); 27 | } 28 | return cell; 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /lib/UIKit/TUITableView+Cell.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUITableView.h" 18 | 19 | /** 20 | * @brief Exposes some internal table view methods to cells (primarily for drag-to-reorder support) 21 | */ 22 | @interface TUITableView (Cell) 23 | 24 | -(void)__mouseDownInCell:(TUITableViewCell *)cell offset:(CGPoint)offset event:(NSEvent *)event; 25 | -(void)__mouseUpInCell:(TUITableViewCell *)cell offset:(CGPoint)offset event:(NSEvent *)event; 26 | -(void)__mouseDraggedCell:(TUITableViewCell *)cell offset:(CGPoint)offset event:(NSEvent *)event; 27 | 28 | -(BOOL)__isDraggingCell; 29 | -(void)__beginDraggingCell:(TUITableViewCell *)cell offset:(CGPoint)offset location:(CGPoint)location; 30 | -(void)__updateDraggingCell:(TUITableViewCell *)cell offset:(CGPoint)offset location:(CGPoint)location; 31 | -(void)__endDraggingCell:(TUITableViewCell *)cell offset:(CGPoint)offset location:(CGPoint)location; 32 | 33 | @end 34 | 35 | -------------------------------------------------------------------------------- /lib/UIKit/TUITableView+Derepeater.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | Some bit-rot here, Twitter for Mac feature that used this is currently on ice 19 | */ 20 | 21 | @class TUITableView; 22 | 23 | @interface TUITableView (Derepeater) 24 | 25 | @property (nonatomic, assign) BOOL derepeaterEnabled; // default is NO 26 | 27 | @end 28 | 29 | @protocol ABDerepeaterTableViewCell 30 | 31 | @required 32 | 33 | - (TUIView *)derepeaterView; 34 | - (id)derepeaterIdentifier; // returned object should implement isEqual: 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /lib/UIKit/TUITableView+Derepeater.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUITableView.h" 18 | 19 | @implementation TUITableView (Derepeater) 20 | 21 | - (BOOL)derepeaterEnabled 22 | { 23 | return _tableFlags.derepeaterEnabled; 24 | } 25 | 26 | - (void)setDerepeaterEnabled:(BOOL)s 27 | { 28 | _tableFlags.derepeaterEnabled = s; 29 | } 30 | 31 | - (void)_updateDerepeaterViews 32 | { 33 | CGFloat padding = 7; 34 | 35 | [CATransaction begin]; 36 | [CATransaction setDisableActions:YES]; 37 | 38 | NSInteger zIndex = 5000; 39 | CGRect visibleRect = [self visibleRect]; 40 | NSString *lastIdentifier = nil; 41 | TUIView *previousView = nil; 42 | CGFloat groupHeight = 0.0; 43 | 44 | for(TUITableViewCell *cell in [self sortedVisibleCells]) { 45 | zIndex--; 46 | cell.layer.zPosition = zIndex; 47 | CGRect cellFrame = cell.frame; 48 | 49 | NSString *identifier = [cell derepeaterIdentifier]; 50 | TUIView *derepeaterView = [cell derepeaterView]; 51 | if([identifier isEqual:lastIdentifier]) { 52 | derepeaterView.hidden = YES; 53 | groupHeight += cellFrame.size.height; 54 | } else { 55 | // make sure previous cell isn't too far down 56 | if(previousView) { 57 | CGRect f = previousView.frame; 58 | CGFloat min = -groupHeight + padding; 59 | if(f.origin.y < min) 60 | f.origin.y = min; 61 | 62 | previousView.frame = f; 63 | previousView = nil; 64 | } 65 | 66 | groupHeight = 0.0; 67 | previousView = derepeaterView; 68 | 69 | derepeaterView.hidden = NO; 70 | CGRect f = derepeaterView.frame; 71 | f.origin.y = f.origin.y = cellFrame.size.height - f.size.height - padding; 72 | if(cellFrame.origin.y + cellFrame.size.height > visibleRect.origin.y + visibleRect.size.height) 73 | f.origin.y += (visibleRect.origin.y + visibleRect.size.height) - (cellFrame.origin.y + cellFrame.size.height); 74 | 75 | derepeaterView.frame = f; 76 | lastIdentifier = identifier; 77 | } 78 | } 79 | 80 | [CATransaction commit]; 81 | } 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /lib/UIKit/TUITableViewCell.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIView.h" 18 | 19 | typedef enum { 20 | TUITableViewCellStyleDefault, 21 | } TUITableViewCellStyle; 22 | 23 | @class TUITableView; 24 | 25 | @interface TUITableViewCell : TUIView 26 | { 27 | 28 | NSString * _reuseIdentifier; 29 | CGPoint _mouseOffset; 30 | 31 | struct { 32 | unsigned int highlighted:1; 33 | unsigned int selected:1; 34 | } _tableViewCellFlags; 35 | 36 | } 37 | 38 | - (id)initWithStyle:(TUITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier; 39 | 40 | @property(nonatomic,readonly,copy) NSString *reuseIdentifier; 41 | 42 | - (void)prepareForReuse; // if the cell is reusable (has a reuse identifier), this is called just before the cell is returned from the table view method dequeueReusableCellWithIdentifier:. If you override, you MUST call super. 43 | - (void)prepareForDisplay; // after frame is set, before it is brought onscreen 44 | 45 | @property (weak, nonatomic, readonly) TUITableView *tableView; 46 | @property (strong, nonatomic, readonly) NSIndexPath *indexPath; 47 | 48 | @property (nonatomic, readonly, getter=isHighlighted) BOOL highlighted; 49 | @property (nonatomic, assign, getter=isSelected) BOOL selected; 50 | 51 | - (void)setSelected:(BOOL)s animated:(BOOL)animated; // called by table view (don't call directly). subclasses can override 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /lib/UIKit/TUITableViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIViewController.h" 18 | #import "TUITableView.h" 19 | 20 | // The TUITableViewController is a controller that manages a table view. 21 | // When the table view is about to appear, it reloads the table view’s data. 22 | // You create a custom subclass of TUITableViewController for each table 23 | // view that you want to manage. 24 | // 25 | // It also clears its selection (with or without animation, depending on 26 | // the request) every time the table view is displayed. You can disable 27 | // this behavior by changing the value in the clearsSelectionOnViewWillAppear 28 | // property. When the table view has appeared, the controller flashes the 29 | // table view's scroll indicators. 30 | // 31 | // When you initialize the controller in initWithStyle:, you must specify 32 | // the style of the table view (plain or grouped) that the controller is 33 | // to manage. Because the initially created table view is without table 34 | // dimensions (that is, number of sections and number of rows per section) 35 | // or content, the table view’s data source and delegate — that is, the 36 | // TUITableViewController itself — must provide the table dimensions, 37 | // the cell content, and any desired configurations as usual. 38 | // 39 | // You may override loadView or any other superclass method, but if you do 40 | // be sure to invoke the superclass implementation of the method first. 41 | @interface TUITableViewController : TUIViewController 42 | 43 | // Returns the table view managed by the controller. 44 | @property (nonatomic, strong) TUITableView *view; 45 | 46 | // A Boolean value indicating if the controller clears the selection when 47 | // the table appears. When YES, the table view controller clears the 48 | // table’s current selection when it receives a viewWillAppear: message. 49 | // Setting this property to NO preserves the selection. Defaults to YES. 50 | @property (nonatomic, assign) BOOL clearsSelectionOnViewWillAppear; 51 | 52 | // Initializes a table view controller to manage a table view of a given style. 53 | // The style specifies the style of table view that the controller is to 54 | // manage (plain or grouped). Returns an initialized TUITableViewController. 55 | // If you use the standard init method to initialize a controller, a 56 | // table view in the plain style is created. 57 | - (id)initWithStyle:(TUITableViewStyle)style; 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /lib/UIKit/TUITableViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUITableViewController.h" 18 | 19 | @interface TUITableViewController () 20 | 21 | @property (nonatomic, assign) TUITableViewStyle style; 22 | 23 | @end 24 | 25 | @implementation TUITableViewController 26 | 27 | @dynamic view; 28 | 29 | - (id)init { 30 | return [self initWithStyle:TUITableViewStylePlain]; 31 | } 32 | 33 | - (id)initWithStyle:(TUITableViewStyle)style { 34 | if((self = [super init])) { 35 | _style = style; 36 | } 37 | 38 | return self; 39 | } 40 | 41 | - (void)loadView { 42 | self.view = [[TUITableView alloc] initWithFrame:CGRectZero style:self.style]; 43 | 44 | self.view.delegate = self; 45 | self.view.dataSource = self; 46 | 47 | self.view.maintainContentOffsetAfterReload = YES; 48 | self.view.needsDisplayWhenWindowsKeyednessChanges = YES; 49 | } 50 | 51 | - (void)viewWillAppear:(BOOL)animated { 52 | [super viewWillAppear:animated]; 53 | 54 | [self.view reloadData]; 55 | if(self.clearsSelectionOnViewWillAppear) { 56 | [self.view deselectRowAtIndexPath:self.view.indexPathForSelectedRow animated:animated]; 57 | } 58 | } 59 | 60 | - (void)viewDidAppear:(BOOL)animated { 61 | [super viewDidAppear:animated]; 62 | 63 | [self.view flashScrollIndicators]; 64 | } 65 | 66 | - (NSInteger)tableView:(TUITableView *)tableView numberOfRowsInSection:(NSInteger)section { 67 | return 0; 68 | } 69 | 70 | - (CGFloat)tableView:(TUITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 71 | return 44.0f; 72 | } 73 | 74 | - (TUITableViewCell *)tableView:(TUITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 75 | return nil; 76 | } 77 | 78 | - (NSString *)description { 79 | return [NSString stringWithFormat:@"<%@: %p | TUITableView = %@>", self.class, self, self.view]; 80 | } 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /lib/UIKit/TUITableViewSectionHeader.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIView.h" 18 | 19 | /** 20 | * @brief An optional base for section header views 21 | * 22 | * A view used as a section header may optionally extend this class, 23 | * in which case the view will recieve messages about header state. 24 | */ 25 | @interface TUITableViewSectionHeader : TUIView { 26 | 27 | BOOL _isPinnedToViewport; 28 | 29 | } 30 | 31 | -(void)headerWillBecomePinned; 32 | -(void)headerWillBecomeUnpinned; 33 | 34 | @property (readwrite, assign, getter=isPinnedToViewport) BOOL pinnedToViewport; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /lib/UIKit/TUITableViewSectionHeader.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUITableViewSectionHeader.h" 18 | 19 | @implementation TUITableViewSectionHeader 20 | 21 | /** 22 | * @brief Determine if this header is currently pinned to the viewport 23 | * 24 | * This method should return TRUE whenever the header is not occupying 25 | * it's normal frame and is overlaping row content. 26 | */ 27 | -(BOOL)isPinnedToViewport { 28 | return _isPinnedToViewport; 29 | } 30 | 31 | /** 32 | * @brief Specify whether this header is currently pinned to the viewport 33 | * @note You should not need to set this property directly, it is managed 34 | * by the table view. 35 | */ 36 | -(void)setPinnedToViewport:(BOOL)pinned { 37 | if(_isPinnedToViewport != pinned){ 38 | if(pinned) [self headerWillBecomePinned]; 39 | else [self headerWillBecomeUnpinned]; 40 | } 41 | _isPinnedToViewport = pinned; 42 | } 43 | 44 | /** 45 | * @brief The header will become pinned 46 | * 47 | * Subclasses may override this method to change the appearance of the header 48 | * when it becomes pinned to the viewport. 49 | */ 50 | -(void)headerWillBecomePinned { 51 | [self setNeedsDisplay]; 52 | } 53 | 54 | /** 55 | * @brief The header will become unpinned 56 | * 57 | * Subclasses may override this method to change the appearance of the header 58 | * when it becomes unpinned from the viewport. 59 | */ 60 | -(void)headerWillBecomeUnpinned { 61 | [self setNeedsDisplay]; 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /lib/UIKit/TUITextEditor.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUITextRenderer.h" 18 | 19 | @interface TUITextEditor : TUITextRenderer 20 | { 21 | NSTextInputContext *inputContext; 22 | NSMutableAttributedString *backingStore; 23 | NSRange markedRange; 24 | NSDictionary *defaultAttributes; 25 | NSDictionary *markedAttributes; 26 | BOOL wasValidKeyEquivalentSelector; 27 | } 28 | 29 | - (NSTextInputContext *)inputContext; 30 | - (NSMutableAttributedString *)backingStore; 31 | 32 | // Insert the standard Cut, Copy, and Paste menu items. 33 | - (void)patchMenuWithStandardEditingMenuItems:(NSMenu *)menu; 34 | 35 | @property (nonatomic, copy) NSString *text; 36 | 37 | // To enable secure text entry on an editor class, or view, 38 | // simply set this boolean to YES. Once it is secured, the 39 | // drawingAttributedString will display only bullets, instead 40 | // of the actual string value. Just set this to NO to disable. 41 | @property (nonatomic, assign, getter = isSecure) BOOL secure; 42 | 43 | @property (nonatomic, strong) NSDictionary *defaultAttributes; 44 | @property (nonatomic, strong) NSDictionary *markedAttributes; 45 | 46 | @property (nonatomic, assign) NSRange selectedRange; 47 | 48 | /* 49 | * If NO: ignore key down, copy, and paste events while preserving click and tap responses. 50 | * 51 | * @note Automatically assumes value of owning TUITextView's (if any) property of the same name. 52 | * 53 | */ 54 | @property (nonatomic, assign, getter = isEditable) BOOL editable; 55 | 56 | - (void)insertText:(id)aString; // at cursor 57 | - (void)insertText:(id)aString replacementRange:(NSRange)replacementRange; 58 | - (void)deleteCharactersInRange:(NSRange)range; 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /lib/UIKit/TUITextField.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUITextView.h" 18 | 19 | @class TUIButton; 20 | 21 | @interface TUITextField : TUITextView 22 | { 23 | TUIButton *rightButton; 24 | 25 | @public 26 | struct { 27 | unsigned int delegateTextFieldShouldReturn:1; 28 | unsigned int delegateTextFieldShouldClear:1; 29 | unsigned int delegateTextFieldShouldTabToNext:1; 30 | } _textFieldFlags; 31 | } 32 | 33 | @property (nonatomic, strong) TUIButton *rightButton; 34 | 35 | - (TUIButton *)clearButton; 36 | 37 | @end 38 | 39 | @protocol TUITextFieldDelegate 40 | 41 | @optional 42 | 43 | - (BOOL)textFieldShouldReturn:(TUITextField *)textField; 44 | - (BOOL)textFieldShouldClear:(TUITextField *)textField; 45 | - (BOOL)textFieldShouldTabToNext:(TUITextField *)textField; 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /lib/UIKit/TUITextField.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUITextField.h" 18 | #import "TUIButton.h" 19 | #import "TUITextViewEditor.h" 20 | 21 | @interface TUITextFieldEditor : TUITextViewEditor 22 | @end 23 | 24 | @implementation TUITextField 25 | 26 | @synthesize rightButton; 27 | 28 | - (Class)textEditorClass 29 | { 30 | return [TUITextFieldEditor class]; 31 | } 32 | 33 | 34 | - (void)setDelegate:(id )d 35 | { 36 | _textFieldFlags.delegateTextFieldShouldReturn = [d respondsToSelector:@selector(textFieldShouldReturn:)]; 37 | _textFieldFlags.delegateTextFieldShouldClear = [d respondsToSelector:@selector(textFieldShouldClear:)]; 38 | _textFieldFlags.delegateTextFieldShouldTabToNext = [d respondsToSelector:@selector(textFieldShouldTabToNext:)]; 39 | [super setDelegate:d]; 40 | } 41 | 42 | - (BOOL)singleLine 43 | { 44 | return YES; 45 | } 46 | 47 | - (void)_tabToNext 48 | { 49 | if(_textFieldFlags.delegateTextFieldShouldTabToNext) 50 | [(id)delegate textFieldShouldTabToNext:self]; 51 | } 52 | 53 | - (void)setRightButton:(TUIButton *)b 54 | { 55 | if(rightButton != b) { 56 | [rightButton removeFromSuperview]; 57 | rightButton = b; 58 | rightButton.layout = ^CGRect(TUIView *v) { 59 | CGRect b = v.superview.bounds; 60 | return CGRectMake(b.size.width - b.size.height, 0, b.size.height, b.size.height); 61 | }; 62 | [self addSubview:rightButton]; 63 | } 64 | } 65 | 66 | - (void)clear:(id)sender 67 | { 68 | if(_textFieldFlags.delegateTextFieldShouldClear) { 69 | if([(id)delegate textFieldShouldClear:self]) { 70 | goto doClear; 71 | } 72 | } else { 73 | doClear: 74 | self.text = @""; 75 | } 76 | } 77 | 78 | - (TUIButton *)clearButton 79 | { 80 | TUIButton *b = [TUIButton button]; 81 | [b setImage:[NSImage imageNamed:@"clear-button.png"] forState:TUIControlStateNormal]; 82 | [b addTarget:self action:@selector(clear:) forControlEvents:TUIControlEventMouseUpInside]; 83 | return b; 84 | } 85 | 86 | @end 87 | 88 | @implementation TUITextFieldEditor 89 | 90 | - (TUITextField *)_textField 91 | { 92 | return (TUITextField *)view; 93 | } 94 | 95 | - (void)insertTab:(id)sender 96 | { 97 | [[self _textField] _tabToNext]; 98 | } 99 | 100 | - (void)insertNewline:(id)sender 101 | { 102 | if([self _textField]->_textFieldFlags.delegateTextFieldShouldReturn) 103 | [(id)[self _textField].delegate textFieldShouldReturn:[self _textField]]; 104 | [[self _textField] sendActionsForControlEvents:TUIControlEventEditingDidEndOnExit]; 105 | } 106 | 107 | - (void)cancelOperation:(id)sender 108 | { 109 | [[self _textField] clear:sender]; 110 | } 111 | 112 | @end 113 | -------------------------------------------------------------------------------- /lib/UIKit/TUITextRenderer+Accessibility.h: -------------------------------------------------------------------------------- 1 | // 2 | // TUITextRenderer+Accessibility.h 3 | // TwUI 4 | // 5 | // Created by Josh Abernathy on 10/27/11. 6 | // Copyright (c) 2011 Maybe Apps, LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TUITextRenderer.h" 11 | 12 | 13 | @interface TUITextRenderer (Accessibility) 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /lib/UIKit/TUITextRenderer+Accessibility.m: -------------------------------------------------------------------------------- 1 | // 2 | // TUITextRenderer+Accessibility.m 3 | // TwUI 4 | // 5 | // Created by Josh Abernathy on 10/27/11. 6 | // Copyright (c) 2011 Maybe Apps, LLC. All rights reserved. 7 | // 8 | 9 | #import "TUITextRenderer+Accessibility.h" 10 | #import "TUIView.h" 11 | 12 | 13 | @implementation TUITextRenderer (Accessibility) 14 | 15 | 16 | #pragma mark NSAccessibility 17 | 18 | - (id)accessibilityHitTest:(NSPoint)point 19 | { 20 | return self; 21 | 22 | /* 23 | if(CGRectContainsPoint(self.frame, point)) { 24 | return self; 25 | } else { 26 | return nil; 27 | } 28 | */ 29 | } 30 | 31 | - (BOOL)accessibilityIsIgnored 32 | { 33 | return NO; 34 | } 35 | 36 | - (NSArray *)accessibilityAttributeNames 37 | { 38 | static NSArray *attributes = nil; 39 | if(attributes == nil) { 40 | attributes = [[NSArray alloc] initWithObjects:NSAccessibilityRoleAttribute, NSAccessibilityRoleDescriptionAttribute, NSAccessibilityFocusedAttribute, NSAccessibilityChildrenAttribute, NSAccessibilityParentAttribute, NSAccessibilityWindowAttribute, NSAccessibilityTopLevelUIElementAttribute, NSAccessibilityPositionAttribute, NSAccessibilitySizeAttribute, NSAccessibilityDescriptionAttribute, NSAccessibilityValueAttribute, NSAccessibilityEnabledAttribute, nil]; 41 | } 42 | 43 | return attributes; 44 | } 45 | 46 | - (id)accessibilityAttributeValue:(NSString *)attribute 47 | { 48 | id practicalSuperview = (id) self.view; 49 | if([attribute isEqualToString:NSAccessibilityRoleAttribute]) { 50 | return NSAccessibilityStaticTextRole; 51 | } else if([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute]) { 52 | return NSAccessibilityStaticTextRole; 53 | } else if([attribute isEqualToString:NSAccessibilityFocusedAttribute]) { 54 | id focusedElement = [NSApp accessibilityAttributeValue:NSAccessibilityFocusedUIElementAttribute]; 55 | return [NSNumber numberWithBool:[focusedElement isEqual:self]]; 56 | } else if([attribute isEqualToString:NSAccessibilityParentAttribute]) { 57 | return NSAccessibilityUnignoredAncestor(practicalSuperview); 58 | } else if([attribute isEqualToString:NSAccessibilityWindowAttribute]) { 59 | return [practicalSuperview accessibilityAttributeValue:NSAccessibilityWindowAttribute]; 60 | } else if([attribute isEqualToString:NSAccessibilityTopLevelUIElementAttribute]) { 61 | return [practicalSuperview accessibilityAttributeValue:NSAccessibilityTopLevelUIElementAttribute]; 62 | } else if([attribute isEqualToString:NSAccessibilityPositionAttribute]) { 63 | CGRect viewFrame = [self.view frameInNSView]; 64 | 65 | NSPoint p = [[(NSView *)[self.view nsView] window] convertBaseToScreen:NSMakePoint(viewFrame.origin.x + self.frame.origin.x, viewFrame.origin.y + self.frame.origin.y)]; 66 | return [NSValue valueWithPoint:p]; 67 | } else if([attribute isEqualToString:NSAccessibilitySizeAttribute]) { 68 | return [NSValue valueWithSize:[self frame].size]; 69 | } else if([attribute isEqualToString:NSAccessibilityChildrenAttribute]) { 70 | return [NSArray array]; 71 | } else if([attribute isEqualToString:NSAccessibilityDescriptionAttribute]) { 72 | return [self.attributedString string]; 73 | } else if([attribute isEqualToString:NSAccessibilityValueAttribute]) { 74 | return [self.attributedString string]; 75 | } else if([attribute isEqualToString:NSAccessibilityTitleAttribute]) { 76 | return [self.attributedString string]; 77 | } else if([attribute isEqualToString:NSAccessibilityEnabledAttribute]) { 78 | return [NSNumber numberWithBool:YES]; 79 | }else { 80 | return nil; 81 | } 82 | } 83 | 84 | - (BOOL)accessibilityIsAttributeSettable:(NSString *)attribute 85 | { 86 | if([attribute isEqualToString:NSAccessibilityFocusedAttribute]) { 87 | return NO; // TODO: should this be settable? 88 | } else { 89 | return NO; 90 | } 91 | } 92 | 93 | - (void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute 94 | { 95 | if([attribute isEqualToString:NSAccessibilityFocusedAttribute]) { 96 | // TODO: should we set this? 97 | } 98 | } 99 | 100 | - (NSArray *)accessibilityActionNames 101 | { 102 | return [NSArray array]; 103 | } 104 | 105 | - (id)accessibilityFocusedUIElement 106 | { 107 | return NSAccessibilityUnignoredAncestor(self); 108 | } 109 | 110 | @end 111 | -------------------------------------------------------------------------------- /lib/UIKit/TUITextRenderer+Event.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUITextRenderer.h" 18 | 19 | @interface TUITextRenderer (Event) 20 | 21 | - (CFIndex)stringIndexForPoint:(CGPoint)p; 22 | - (CFIndex)stringIndexForEvent:(NSEvent *)event; 23 | - (void)resetSelection; 24 | - (CGRect)rectForCurrentSelection; 25 | 26 | - (void)copy:(id)sender; 27 | 28 | @property (nonatomic, assign) id delegate; 29 | 30 | @end 31 | 32 | @protocol TUITextRendererDelegate 33 | 34 | @optional 35 | - (NSArray *)activeRangesForTextRenderer:(TUITextRenderer *)t; 36 | 37 | - (void)textRendererWillBecomeFirstResponder:(TUITextRenderer *)textRenderer; 38 | - (void)textRendererDidBecomeFirstResponder:(TUITextRenderer *)textRenderer; 39 | - (void)textRendererWillResignFirstResponder:(TUITextRenderer *)textRenderer; 40 | - (void)textRendererDidResignFirstResponder:(TUITextRenderer *)textRenderer; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /lib/UIKit/TUITextRenderer+Private.h: -------------------------------------------------------------------------------- 1 | #import "TUITextRenderer.h" 2 | 3 | @interface TUITextRenderer () 4 | 5 | - (CTFramesetterRef)ctFramesetter; 6 | - (CTFrameRef)ctFrame; 7 | - (CGPathRef)ctPath; 8 | - (CFRange)_selectedRange; 9 | - (void)_resetFramesetter; 10 | 11 | @end 12 | 13 | @interface TUITextRenderer (KeyBindings) 14 | 15 | - (void)_scrollToIndex:(long)index; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /lib/UIKit/TUITextView.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIControl.h" 18 | #import "TUIGeometry.h" 19 | #import "TUIAttributedString.h" 20 | 21 | @class TUITextEditor; 22 | @class NSFont; 23 | 24 | @protocol TUITextViewDelegate; 25 | 26 | @interface TUITextView : TUIControl { 27 | id __unsafe_unretained delegate; 28 | TUIViewDrawRect drawFrame; 29 | 30 | NSString *placeholder; 31 | TUITextRenderer *placeholderRenderer; 32 | 33 | NSFont *font; 34 | NSColor *textColor; 35 | TUITextAlignment textAlignment; 36 | BOOL editable; 37 | 38 | BOOL spellCheckingEnabled; 39 | NSInteger lastCheckToken; 40 | NSArray *lastCheckResults; 41 | NSTextCheckingResult *selectedTextCheckingResult; 42 | BOOL autocorrectionEnabled; 43 | NSMutableDictionary *autocorrectedResults; 44 | 45 | TUIEdgeInsets contentInset; 46 | 47 | TUITextEditor *renderer; 48 | TUIView *cursor; 49 | 50 | CGRect _lastTextRect; 51 | 52 | struct { 53 | unsigned int delegateTextViewDidChange:1; 54 | unsigned int delegateDoCommandBySelector:1; 55 | unsigned int delegateWillBecomeFirstResponder:1; 56 | unsigned int delegateDidBecomeFirstResponder:1; 57 | unsigned int delegateWillResignFirstResponder:1; 58 | unsigned int delegateDidResignFirstResponder:1; 59 | } _textViewFlags; 60 | } 61 | 62 | - (Class)textEditorClass; 63 | 64 | @property (nonatomic, unsafe_unretained) id delegate; 65 | 66 | @property (nonatomic, copy) NSString *text; 67 | @property (nonatomic, copy) NSString *placeholder; 68 | @property (nonatomic, strong) NSFont *font; 69 | @property (nonatomic, strong) NSColor *textColor; 70 | @property (nonatomic, strong) NSColor *cursorColor; 71 | @property (nonatomic, assign) CGFloat cursorWidth; 72 | @property (nonatomic, assign) TUITextAlignment textAlignment; 73 | @property (nonatomic, assign) TUIEdgeInsets contentInset; 74 | 75 | @property (nonatomic, assign) NSRange selectedRange; 76 | @property (nonatomic, assign, getter=isEditable) BOOL editable; 77 | @property (nonatomic, assign, getter=isSpellCheckingEnabled) BOOL spellCheckingEnabled; 78 | @property (nonatomic, assign, getter=isAutocorrectionEnabled) BOOL autocorrectionEnabled; 79 | 80 | @property (nonatomic, copy) TUIViewDrawRect drawFrame; 81 | 82 | - (BOOL)hasText; 83 | 84 | - (BOOL)doCommandBySelector:(SEL)selector; 85 | 86 | @end 87 | 88 | 89 | @protocol TUITextViewDelegate 90 | 91 | @optional 92 | 93 | - (void)textViewDidChange:(TUITextView *)textView; 94 | - (BOOL)textView:(TUITextView *)textView doCommandBySelector:(SEL)commandSelector; // return YES if the implementation consumes the selector, NO if it should be passed up to super 95 | 96 | - (void)textViewWillBecomeFirstResponder:(TUITextView *)textView; 97 | - (void)textViewDidBecomeFirstResponder:(TUITextView *)textView; 98 | - (void)textViewWillResignFirstResponder:(TUITextView *)textView; 99 | - (void)textViewDidResignFirstResponder:(TUITextView *)textView; 100 | 101 | @end 102 | 103 | 104 | extern TUIViewDrawRect TUITextViewSearchFrame(void); 105 | extern TUIViewDrawRect TUITextViewSearchFrameOverDark(void); 106 | extern TUIViewDrawRect TUITextViewStandardFrame(void); 107 | -------------------------------------------------------------------------------- /lib/UIKit/TUITextViewEditor.h: -------------------------------------------------------------------------------- 1 | // 2 | // TUITextViewEditor.h 3 | // TwUI 4 | // 5 | // Created by Josh Abernathy on 8/11/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "TUITextEditor.h" 10 | 11 | @interface TUITextViewEditor : TUITextEditor 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /lib/UIKit/TUITextViewEditor.m: -------------------------------------------------------------------------------- 1 | // 2 | // TUITextViewEditor.m 3 | // TwUI 4 | // 5 | // Created by Josh Abernathy on 8/11/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "TUITextViewEditor.h" 10 | #import "TUITextView.h" 11 | 12 | @implementation TUITextViewEditor 13 | 14 | - (TUITextView *)_textView 15 | { 16 | return (TUITextView *)view; 17 | } 18 | 19 | - (void)doCommandBySelector:(SEL)selector 20 | { 21 | return [super doCommandBySelector:selector]; 22 | } 23 | 24 | - (BOOL)becomeFirstResponder 25 | { 26 | self.selectedRange = NSMakeRange(self.text.length, 0); 27 | return [super becomeFirstResponder]; 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /lib/UIKit/TUITooltipWindow.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import 18 | 19 | @interface TUITooltipWindow : NSWindow 20 | 21 | + (void)updateTooltip:(NSString *)s delay:(NSTimeInterval)delay; // may pass nil 22 | + (void)endTooltip; // no animation 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /lib/UIKit/TUITooltipWindow.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUITooltipWindow.h" 18 | #import "TUIAttributedString.h" 19 | #import "TUICGAdditions.h" 20 | #import "TUIStringDrawing.h" 21 | 22 | #define TOOLTIP_HEIGHT 18 23 | #define SWITCH_DELAY 0.2 24 | #define FADE_OUT_SPEED 0.07 25 | 26 | static TUIAttributedString *CurrentTooltipString = nil; 27 | static NSTimer *FadeOutTimer = nil; 28 | 29 | @interface TUITooltipWindowView : NSView 30 | @end 31 | 32 | @implementation TUITooltipWindowView 33 | 34 | - (void)drawRect:(NSRect)r 35 | { 36 | CGRect b = [self frame]; 37 | b.origin = CGPointZero; 38 | 39 | CGContextRef ctx = TUIGraphicsGetCurrentContext(); 40 | 41 | CGContextSaveGState(ctx); 42 | CGFloat _a[] = {1.0, 1.0, 198/255., 1.0}; 43 | CGFloat _b[] = {1.0, 1.0, 158/255., 1.0}; 44 | CGContextClipToRoundRect(ctx, b, 2); 45 | CGContextDrawLinearGradientBetweenPoints(ctx, CGPointMake(0, b.size.height), _a, CGPointMake(0, 0), _b); 46 | CGContextRestoreGState(ctx); 47 | 48 | [CurrentTooltipString ab_drawInRect:CGRectMake(0, -2, b.size.width, b.size.height)]; 49 | } 50 | 51 | @end 52 | 53 | 54 | @implementation TUITooltipWindow 55 | 56 | + (TUITooltipWindow *)sharedTooltipWindow 57 | { 58 | static TUITooltipWindow *w = nil; 59 | if(!w) { 60 | NSRect r = NSMakeRect(0, 0, 10, TOOLTIP_HEIGHT); 61 | w = [[TUITooltipWindow alloc] initWithContentRect:r 62 | styleMask:NSBorderlessWindowMask 63 | backing:NSBackingStoreBuffered 64 | defer:NO]; 65 | [w setLevel:NSPopUpMenuWindowLevel]; 66 | [w setOpaque:NO]; 67 | [w setBackgroundColor:[NSColor clearColor]]; 68 | [w setHasShadow:YES]; 69 | [w setIgnoresMouseEvents:YES]; 70 | 71 | TUITooltipWindowView *v = [[TUITooltipWindowView alloc] initWithFrame:r]; 72 | [v setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; 73 | [w setContentView:v]; 74 | } 75 | return w; 76 | } 77 | 78 | static BOOL ShowingTooltip = NO; 79 | 80 | + (CGRect)_tooltipRect 81 | { 82 | CGFloat width = [CurrentTooltipString ab_size].width + 5; 83 | NSPoint p = [NSEvent mouseLocation]; 84 | NSRect r = NSMakeRect(p.x - width*0.5 + 15, p.y - 37, width, TOOLTIP_HEIGHT); 85 | return r; 86 | } 87 | 88 | + (void)_fixTooltipWindow 89 | { 90 | TUITooltipWindow *tooltipWindow = [self sharedTooltipWindow]; 91 | NSRect r = [tooltipWindow frame]; 92 | if(r.origin.y < 50) 93 | r.origin.y += 37 + TOOLTIP_HEIGHT; 94 | [tooltipWindow setFrameOrigin:r.origin]; 95 | } 96 | 97 | + (void)_beginTooltip 98 | { 99 | if([NSApp isHidden]) { 100 | // ignore 101 | } else { 102 | ShowingTooltip = YES; 103 | 104 | TUITooltipWindow *tooltipWindow = [self sharedTooltipWindow]; 105 | 106 | [tooltipWindow setFrame:[self _tooltipRect] display:YES animate:NO]; 107 | [self _fixTooltipWindow]; 108 | [tooltipWindow orderFront:nil]; 109 | [tooltipWindow setAlphaValue:0.93]; 110 | 111 | [[[self sharedTooltipWindow] contentView] setNeedsDisplay:YES]; 112 | } 113 | } 114 | 115 | + (void)tick:(id)sender 116 | { 117 | CGFloat a = [[self sharedTooltipWindow] alphaValue]; 118 | a -= FADE_OUT_SPEED; 119 | if(a <= 0.0) { 120 | [self endTooltip]; 121 | } else { 122 | [[self sharedTooltipWindow] setAlphaValue:a]; 123 | } 124 | } 125 | 126 | + (void)updateTooltip:(NSString *)s delay:(NSTimeInterval)delay 127 | { 128 | [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_beginTooltip) object:nil]; 129 | 130 | if(s) { 131 | if(FadeOutTimer || ShowingTooltip) { 132 | // quick switch 133 | [FadeOutTimer invalidate]; 134 | FadeOutTimer = nil; 135 | [self performSelector:@selector(_beginTooltip) withObject:nil afterDelay:SWITCH_DELAY]; 136 | } else { 137 | // show 138 | [self performSelector:@selector(_beginTooltip) withObject:nil afterDelay:delay]; 139 | } 140 | 141 | CurrentTooltipString = [TUIAttributedString stringWithString:s]; 142 | CurrentTooltipString.font = [NSFont fontWithName:@"HelveticaNeue" size:11]; 143 | CurrentTooltipString.kerning = 0.2; 144 | [CurrentTooltipString setAlignment:TUITextAlignmentCenter lineBreakMode:TUILineBreakModeClip]; 145 | } else { 146 | if(ShowingTooltip) { 147 | // fade out 148 | if(!FadeOutTimer) { 149 | FadeOutTimer = [NSTimer scheduledTimerWithTimeInterval:1/30. target:self selector:@selector(tick:) userInfo:nil repeats:YES]; 150 | } 151 | } else { 152 | // nothing 153 | } 154 | } 155 | } 156 | 157 | + (void)endTooltip 158 | { 159 | [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_beginTooltip) object:nil]; 160 | [FadeOutTimer invalidate]; 161 | FadeOutTimer = nil; 162 | [[self sharedTooltipWindow] orderOut:nil]; 163 | ShowingTooltip = NO; 164 | } 165 | 166 | @end 167 | -------------------------------------------------------------------------------- /lib/UIKit/TUIView+Accessibility.h: -------------------------------------------------------------------------------- 1 | // 2 | // TUIView+Accessibility.h 3 | // TwUI 4 | // 5 | // Created by Josh Abernathy on 7/25/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "TUIView.h" 10 | #import "TUIAccessibility.h" 11 | 12 | 13 | @interface TUIView (Accessibility) 14 | 15 | @property (nonatomic, assign) BOOL isAccessibilityElement; 16 | @property (nonatomic, copy) NSString *accessibilityLabel; 17 | @property (nonatomic, copy) NSString *accessibilityHint; 18 | @property (nonatomic, copy) NSString *accessibilityValue; 19 | @property (nonatomic, assign) TUIAccessibilityTraits accessibilityTraits; 20 | @property (nonatomic, assign) CGRect accessibilityFrame; // accessibilityFrame should be in screen coordinates 21 | 22 | - (NSArray *)accessibleSubviews; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /lib/UIKit/TUIView+Event.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | @interface TUIView (Event) 18 | 19 | - (BOOL)didDrag; // valid when called from mouseUp: will determine if a drag happened in this event sequence 20 | 21 | - (void)viewWillStartLiveResize; // call super to propogate to subviews 22 | - (void)viewDidEndLiveResize; 23 | 24 | /* Observing events in subviews 25 | * 26 | * The subview parameter is the view which recieved the event, not the 27 | * immediate subview of the view recieving the message. To determine if 28 | * the event belongs to a subview of a particular immediate subview, use 29 | * -isDescendantOfView:. 30 | */ 31 | - (void)mouseDown:(NSEvent *)event onSubview:(TUIView *)subview; 32 | - (void)mouseDragged:(NSEvent *)event onSubview:(TUIView *)subview; 33 | - (void)mouseUp:(NSEvent *)event fromSubview:(TUIView *)subview; 34 | - (void)rightMouseDown:(NSEvent *)event onSubview:(TUIView *)subview; 35 | - (void)rightMouseUp:(NSEvent *)event fromSubview:(TUIView *)subview; 36 | - (void)mouseEntered:(NSEvent *)event onSubview:(TUIView *)subview; 37 | - (void)mouseExited:(NSEvent *)event fromSubview:(TUIView *)subview; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /lib/UIKit/TUIView+Layout.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "TUIView.h" 3 | 4 | @class TUILayoutConstraint; 5 | 6 | /* 7 | 8 | The view-end of the layout system allows you to add constraints 9 | to the view directly from the view, list all constraints currently 10 | attached to the view, and remove all layout constraints at once. 11 | 12 | It also allows you to set the layout name without interfacing 13 | with the TUILayoutManager, as a shortcut. 14 | 15 | */ 16 | 17 | @interface TUIView (Layout) 18 | 19 | @property (nonatomic, copy) NSString *layoutName; 20 | 21 | - (void)addLayoutConstraint:(TUILayoutConstraint *)constraint; 22 | - (void)removeLayoutConstraint:(TUILayoutConstraint *)constraint; 23 | - (NSArray *)layoutConstraints; 24 | - (void)removeAllLayoutConstraints; 25 | 26 | - (TUIView *)relativeViewForName:(NSString *)name; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /lib/UIKit/TUIView+PasteboardDragging.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIView.h" 18 | 19 | @interface TUIView (PasteboardDragging) 20 | 21 | @property (nonatomic, assign) BOOL pasteboardDraggingEnabled; // default NO 22 | 23 | - (void)startPasteboardDragging; 24 | - (void)endPasteboardDragging:(NSDragOperation)operation; 25 | 26 | - (id)representedPasteboardObject; 27 | - (TUIView *)handleForPasteboardDragView; // reciever can act as a "drag handle" for another view, returns self by default 28 | 29 | - (void)pasteboardDragMouseDown:(NSEvent *)event; 30 | - (void)pasteboardDragMouseDragged:(NSEvent *)event; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /lib/UIKit/TUIView+PasteboardDragging.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIView+PasteboardDragging.h" 18 | #import "TUICGAdditions.h" 19 | #import "TUINSView.h" 20 | 21 | @implementation TUIView (PasteboardDragging) 22 | 23 | - (BOOL)pasteboardDraggingEnabled 24 | { 25 | return _viewFlags.pasteboardDraggingEnabled; 26 | } 27 | 28 | - (void)setPasteboardDraggingEnabled:(BOOL)e 29 | { 30 | _viewFlags.pasteboardDraggingEnabled = e; 31 | } 32 | 33 | - (void)startPasteboardDragging 34 | { 35 | // implemented by subclasses 36 | } 37 | 38 | - (void)endPasteboardDragging:(NSDragOperation)operation 39 | { 40 | // implemented by subclasses 41 | } 42 | 43 | - (id)representedPasteboardObject 44 | { 45 | return nil; 46 | } 47 | 48 | - (TUIView *)handleForPasteboardDragView 49 | { 50 | return self; 51 | } 52 | 53 | - (void)pasteboardDragMouseDown:(NSEvent *)event 54 | { 55 | _viewFlags.pasteboardDraggingIsDragging = NO; 56 | } 57 | 58 | - (void)pasteboardDragMouseDragged:(NSEvent *)event 59 | { 60 | if(!_viewFlags.pasteboardDraggingIsDragging) { 61 | _viewFlags.pasteboardDraggingIsDragging = YES; 62 | 63 | TUIView *dragView = [self handleForPasteboardDragView]; 64 | id pasteboardObject = [dragView representedPasteboardObject]; 65 | 66 | NSImage *dragNSImage = TUIGraphicsDrawAsImage(dragView.frame.size, ^{ 67 | [TUIGraphicsGetImageForView(dragView) drawAtPoint:CGPointZero fromRect:CGRectZero operation:NSCompositeSourceOver fraction:0.75]; 68 | }); 69 | 70 | NSPasteboard *pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard]; 71 | [pasteboard clearContents]; 72 | [pasteboard writeObjects:[NSArray arrayWithObject:pasteboardObject]]; 73 | 74 | [self.nsView dragImage:dragNSImage 75 | at:[dragView frameInNSView].origin 76 | offset:NSZeroSize 77 | event:event 78 | pasteboard:pasteboard 79 | source:self 80 | slideBack:YES]; 81 | } 82 | } 83 | 84 | - (void)draggedImage:(NSImage *)anImage beganAt:(NSPoint)aPoint 85 | { 86 | [[self handleForPasteboardDragView] startPasteboardDragging]; 87 | } 88 | 89 | - (void)draggedImage:(NSImage *)image movedTo:(NSPoint)screenPoint 90 | { 91 | } 92 | 93 | - (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation 94 | { 95 | [self.nsView mouseUp:nil]; // will clear _trackingView 96 | [[self handleForPasteboardDragView] endPasteboardDragging:operation]; 97 | } 98 | 99 | @end 100 | -------------------------------------------------------------------------------- /lib/UIKit/TUIView+Private.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIView.h" 18 | 19 | typedef void (^TUIMouseDraggedHandler)(NSEvent *dragEvent); 20 | 21 | @class TUITextRenderer; 22 | 23 | @interface TUIView () 24 | 25 | @property (nonatomic, retain) NSArray *textRenderers; 26 | @property (nonatomic, copy) TUIMouseDraggedHandler dragHandler; 27 | 28 | - (TUITextRenderer *)textRendererAtPoint:(CGPoint)point; 29 | - (void)_updateLayerScaleFactor; 30 | 31 | @end 32 | 33 | extern CGFloat TUICurrentContextScaleFactor(void); 34 | -------------------------------------------------------------------------------- /lib/UIKit/TUIView+TUIBridgedView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TUIView+TUIBridgedView.h 3 | // TwUI 4 | // 5 | // Created by Justin Spahr-Summers on 17.07.12. 6 | // 7 | // Portions of this code were taken from Velvet, 8 | // which is copyright (c) 2012 Bitswift, Inc. 9 | // See LICENSE.txt for more information. 10 | // 11 | 12 | #import "TUIView.h" 13 | #import "TUIBridgedView.h" 14 | 15 | /** 16 | * Implements support for the protocol in TUIView. 17 | */ 18 | @interface TUIView (TUIBridgedView) 19 | - (id)descendantViewAtPoint:(NSPoint)point; 20 | @end 21 | -------------------------------------------------------------------------------- /lib/UIKit/TUIViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIResponder.h" 18 | 19 | @class TUINavigationItem; 20 | @class TUIView; 21 | 22 | @interface TUIViewController : TUIResponder 23 | { 24 | TUIView *_view; 25 | __unsafe_unretained TUIViewController *_parentViewController; // Nonretained 26 | } 27 | 28 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil; 29 | 30 | @property(nonatomic,strong) TUIView *view; 31 | 32 | - (void)loadView; 33 | - (void)viewDidLoad; 34 | - (void)viewDidUnload; 35 | - (BOOL)isViewLoaded; 36 | 37 | - (void)viewWillAppear:(BOOL)animated; 38 | - (void)viewDidAppear:(BOOL)animated; 39 | - (void)viewWillDisappear:(BOOL)animated; 40 | - (void)viewDidDisappear:(BOOL)animated; 41 | 42 | - (void)didReceiveMemoryWarning; 43 | 44 | @property(nonatomic,weak) TUIViewController *parentViewController; // If this view controller is inside a navigation controller or tab bar controller, or has been presented modally by another view controller, return it. 45 | 46 | - (TUIView *)setupStandardView; // don't use this 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /lib/UIKit/TUIViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #import "TUIViewController.h" 18 | #import "TUIView.h" 19 | 20 | @implementation TUIViewController 21 | 22 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 23 | { 24 | return [self init]; 25 | } 26 | 27 | 28 | - (id)copyWithZone:(NSZone *)zone 29 | { 30 | TUIViewController *v = [[[self class] alloc] init]; 31 | // subclasses should override, call super, and copy over necessary properties 32 | return v; 33 | } 34 | 35 | - (TUIView *)view 36 | { 37 | if(!_view) { 38 | [self loadView]; 39 | [self viewDidLoad]; 40 | [_view setNextResponder:self]; 41 | } 42 | return _view; 43 | } 44 | 45 | - (void)setView:(TUIView *)v 46 | { 47 | _view = v; 48 | 49 | if(!_view) { 50 | [self viewDidUnload]; 51 | } 52 | } 53 | 54 | - (BOOL)performKeyEquivalent:(NSEvent *)event 55 | { 56 | return NO; 57 | } 58 | 59 | - (void)loadView 60 | { 61 | // subclasses must implement 62 | } 63 | 64 | - (void)viewDidLoad 65 | { 66 | 67 | } 68 | 69 | - (void)viewDidUnload 70 | { 71 | 72 | } 73 | 74 | - (BOOL)isViewLoaded 75 | { 76 | return _view != nil; 77 | } 78 | 79 | - (void)viewWillAppear:(BOOL)animated { } 80 | - (void)viewDidAppear:(BOOL)animated { } 81 | - (void)viewWillDisappear:(BOOL)animated { } 82 | - (void)viewDidDisappear:(BOOL)animated { } 83 | 84 | - (void)didReceiveMemoryWarning // Called when the parent application receives a memory warning. Default implementation releases the view if it doesn't have a superview. 85 | { 86 | if(_view && !_view.superview) { 87 | self.view = nil; 88 | } 89 | } 90 | 91 | - (TUIViewController *)parentViewController 92 | { 93 | return _parentViewController; 94 | } 95 | 96 | - (void)setParentViewController:(TUIViewController *)v 97 | { 98 | _parentViewController = v; 99 | } 100 | 101 | - (TUIResponder *)initialFirstResponder 102 | { 103 | return _view.initialFirstResponder; 104 | } 105 | 106 | - (TUIView *)setupStandardView 107 | { 108 | TUIView *v = [[TUIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; 109 | v.backgroundColor = [NSColor colorWithCalibratedWhite:0.96 alpha:1.0]; 110 | self.view = v; 111 | 112 | return v; 113 | } 114 | 115 | @end 116 | -------------------------------------------------------------------------------- /lib/UIKit/TUIViewNSViewContainer+Private.h: -------------------------------------------------------------------------------- 1 | // 2 | // TUIViewNSView+Private.h 3 | // 4 | // Created by James Lawton on 23.11.11. 5 | // Copyright (c) 2011 Bitswift. All rights reserved. 6 | // 7 | 8 | #import "TUIViewNSViewContainer.h" 9 | 10 | /** 11 | * Private functionality of TUIViewNSViewContainer that needs to be exposed to other parts 12 | * of the framework. 13 | */ 14 | @interface TUIViewNSViewContainer () 15 | 16 | /** 17 | * Whether the receiver is rendering its NSView. 18 | */ 19 | @property (nonatomic, getter = isRenderingContainedView, readonly) BOOL renderingContainedView; 20 | 21 | /** 22 | * Renders the receiver's rootView once and caches into the receiver's layer, 23 | * supporting an animation on the NSView as part of the TwUI hierarchy. 24 | * 25 | * This method can be called multiple times, but each call must eventually be 26 | * balanced with a call to -stopRenderingContainedView. 27 | */ 28 | - (void)startRenderingContainedView; 29 | 30 | /** 31 | * Balances a previous call to -startRenderingContainedView. 32 | * 33 | * If this balances the initial call to -startRenderingContainedView, the 34 | * receiver stop rendering the rootView in its layer, and restore the normal 35 | * AppKit rendering path. 36 | * 37 | * This method can be called multiple times to match multiple calls to 38 | * -startRenderingContainedView. 39 | */ 40 | - (void)stopRenderingContainedView; 41 | 42 | /** 43 | * The frame that the receiver's NSView should have at the time of call. 44 | * 45 | * This is used by -synchronizeNSViewGeometry to keep the NSView attached to 46 | * its TwUI view. 47 | * 48 | * If the receiver has no host view, the value is undefined. 49 | */ 50 | @property (readonly) CGRect NSViewFrame; 51 | 52 | /** 53 | * This will synchronize the appearance of the receiver's NSView with that of 54 | * the receiver, ensuring that the NSView is displayed correctly on screen. 55 | */ 56 | - (void)synchronizeNSViewAppearance; 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /lib/UIKit/TUIViewNSViewContainer.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Twitter, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this work except in compliance with the License. 6 | You may obtain a copy of the License in the LICENSE file, or at: 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Portions of this code were taken from Velvet, 18 | // which is copyright (c) 2012 Bitswift, Inc. 19 | // See LICENSE.txt for more information. 20 | 21 | #import "NSView+TUIExtensions.h" 22 | #import "TUIHostView.h" 23 | #import "TUIView.h" 24 | 25 | /** 26 | * A view that is responsible for displaying and handling an NSView within the 27 | * normal TwUI view hierarchy. 28 | * 29 | * TUIViewNSViewContainer is powerful, but many of its interactions with AppKit rely upon 30 | * assumptions, magic, or unspecified behavior. To that end, there are several 31 | * restrictions on what you can do with TUIViewNSViewContainer: 32 | * 33 | * - A TUIViewNSViewContainer must always appear on top of TwUI views. A TUIViewNSViewContainer 34 | * should always appear at the end of a subview list. You should not attempt to 35 | * add TwUI subviews directly to a TUIViewNSViewContainer. Instead, if you need TwUI 36 | * views to appear on top, nest an TUINSView within the NSView and start 37 | * a new TwUI hierarchy. 38 | * 39 | * - You must not modify the geometry of the hosted NSView. If you need to 40 | * rearrange or resize the NSView, modify the TUIViewNSViewContainer and it will perform 41 | * the necessary updates. 42 | * 43 | * - You must not touch the layer of the hosted NSView. If you wish to 44 | * perform animations or apply other Core Animation effects, use the layer of 45 | * the TUIViewNSViewContainer. Note that not all Core Animation features may be available. 46 | * 47 | * - You should not subclass TUIViewNSViewContainer. If you need additional features, 48 | * create a new view class which contains a TUIViewNSViewContainer instead. 49 | */ 50 | @interface TUIViewNSViewContainer : TUIView 51 | 52 | /** 53 | * Initializes the receiver, setting its rootView to the given view. 54 | * 55 | * The frame of the receiver will automatically be set to that of the given view. 56 | */ 57 | - (id)initWithNSView:(NSView *)view; 58 | 59 | /** 60 | * The view displayed by the receiver. 61 | */ 62 | @property (nonatomic, strong) NSView *rootView; 63 | 64 | @end 65 | --------------------------------------------------------------------------------