Skip to content

Commit

Permalink
Merge pull request github#140 from maxgoedjen/feature-navcontroller-i…
Browse files Browse the repository at this point in the history
…mprovements

TUINavigationController Enhancements
  • Loading branch information
CodaFi committed Nov 15, 2012
2 parents cfa6a7f + ab979a1 commit adbc2c4
Show file tree
Hide file tree
Showing 10 changed files with 290 additions and 173 deletions.
6 changes: 6 additions & 0 deletions ExampleProject/Example.xcodeproj/project.pbxproj
Expand Up @@ -20,6 +20,7 @@
484C209615F445EB00B3104E /* ExampleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 484C208815F445EB00B3104E /* ExampleView.m */; };
484C209715F445EB00B3104E /* large-image.jpeg in Resources */ = {isa = PBXBuildFile; fileRef = 484C208915F445EB00B3104E /* large-image.jpeg */; };
484C209815F445EB00B3104E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 484C208A15F445EB00B3104E /* main.m */; };
500088B2165362E60067ED42 /* ExampleTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 500088B1165362E60067ED42 /* ExampleTableViewController.m */; };
5C782FD013A54FFF00CF69EF /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C782FCF13A54FFD00CF69EF /* ApplicationServices.framework */; };
5C782FD713A556A900CF69EF /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C782FD613A556A800CF69EF /* QuartzCore.framework */; };
5ED56678139DC30300031CDF /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5ED56677139DC30300031CDF /* Cocoa.framework */; };
Expand Down Expand Up @@ -86,6 +87,8 @@
484C208815F445EB00B3104E /* ExampleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExampleView.m; sourceTree = "<group>"; };
484C208915F445EB00B3104E /* large-image.jpeg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "large-image.jpeg"; sourceTree = "<group>"; };
484C208A15F445EB00B3104E /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
500088B0165362E60067ED42 /* ExampleTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExampleTableViewController.h; sourceTree = "<group>"; };
500088B1165362E60067ED42 /* ExampleTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExampleTableViewController.m; sourceTree = "<group>"; };
5C782FCF13A54FFD00CF69EF /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = System/Library/Frameworks/ApplicationServices.framework; sourceTree = SDKROOT; };
5C782FD613A556A800CF69EF /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
5ED56673139DC30300031CDF /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -124,6 +127,8 @@
484C208415F445EB00B3104E /* ExampleTabBar.m */,
484C208515F445EB00B3104E /* ExampleTableViewCell.h */,
484C208615F445EB00B3104E /* ExampleTableViewCell.m */,
500088B0165362E60067ED42 /* ExampleTableViewController.h */,
500088B1165362E60067ED42 /* ExampleTableViewController.m */,
484C208715F445EB00B3104E /* ExampleView.h */,
484C208815F445EB00B3104E /* ExampleView.m */,
484C207915F445EB00B3104E /* MainMenu.xib */,
Expand Down Expand Up @@ -308,6 +313,7 @@
484C209515F445EB00B3104E /* ExampleTableViewCell.m in Sources */,
484C209615F445EB00B3104E /* ExampleView.m in Sources */,
484C209815F445EB00B3104E /* main.m in Sources */,
500088B2165362E60067ED42 /* ExampleTableViewController.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
15 changes: 15 additions & 0 deletions ExampleProject/Example/ExampleTableViewController.h
@@ -0,0 +1,15 @@
//
// ExampleTableViewController.h
// Example
//
// Created by Max Goedjen on 11/13/12.
//
//

#import "TUIKit.h"

@interface ExampleTableViewController : TUIViewController <TUITableViewDelegate, TUITableViewDataSource>

@property (nonatomic, strong) TUITableView *tableView;

@end
139 changes: 139 additions & 0 deletions ExampleProject/Example/ExampleTableViewController.m
@@ -0,0 +1,139 @@
//
// ExampleTableViewController.m
// Example
//
// Created by Max Goedjen on 11/13/12.
//
//

#import "ExampleTableViewController.h"
#import "ExampleSectionHeaderView.h"
#import "ExampleTableViewCell.h"

@implementation ExampleTableViewController

- (void)loadView {
self.view = [[TUIView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)];
}

- (void)viewDidLoad {
self.tableView = [[TUITableView alloc] initWithFrame:self.view.frame];
self.tableView.alwaysBounceVertical = YES;
self.tableView.dataSource = self;
self.tableView.delegate = self;
[self.tableView reloadData];
self.tableView.maintainContentOffsetAfterReload = YES;
self.tableView.autoresizingMask = TUIViewAutoresizingFlexibleSize;

TUILabel *footerLabel = [[TUILabel alloc] initWithFrame:CGRectMake(0, 0, _tableView.frame.size.width, 44)];
footerLabel.alignment = TUITextAlignmentCenter;
footerLabel.backgroundColor = [NSColor clearColor];
footerLabel.font = [NSFont fontWithName:@"HelveticaNeue-Bold" size:15];
footerLabel.text = @"Example Footer View";
self.tableView.footerView = footerLabel;

[self.view addSubview:self.tableView];
}

- (NSInteger)numberOfSectionsInTableView:(TUITableView *)tableView {
return 8;
}

- (NSInteger)tableView:(TUITableView *)table numberOfRowsInSection:(NSInteger)section {
return 25;
}

- (CGFloat)tableView:(TUITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 50.0;
}

- (TUIView *)tableView:(TUITableView *)tableView headerViewForSection:(NSInteger)section {
ExampleSectionHeaderView *header = [[ExampleSectionHeaderView alloc] initWithFrame:CGRectMake(0, 0, 100, 32)];
TUIAttributedString *title = [TUIAttributedString stringWithString:[NSString stringWithFormat:@"Example Section %d", (int)section]];
title.color = [NSColor blackColor];
title.font = [NSFont fontWithName:@"HelveticaNeue-Bold" size:15];
header.labelRenderer.attributedString = title;

// Dragging a title can drag the window too.
[header setMoveWindowByDragging:YES];

// Add an activity indicator to the header view with a 24x24 size.
// Since we know the height of the header won't change we can pre-
// pad it to 4. However, since the table view's width can change,
// we'll create a layout constraint to keep the activity indicator
// anchored 16px left of the right side of the header view.
TUIActivityIndicatorView *indicator = [[TUIActivityIndicatorView alloc] initWithFrame:CGRectMake(0, 4, 24, 24)
activityIndicatorStyle:TUIActivityIndicatorViewStyleGray];
[indicator addLayoutConstraint:[TUILayoutConstraint constraintWithAttribute:TUILayoutConstraintAttributeMaxX
relativeTo:@"superview"
attribute:TUILayoutConstraintAttributeMaxX
offset:-16.0f]];

// Add a simple embossing shadow to the white activity indicator.
// This way, we can see it better on a bright background. Using
// the standard layer property keeps the shadow stable through
// animations.
indicator.layer.shadowColor = [NSColor whiteColor].tui_CGColor;
indicator.layer.shadowOffset = CGSizeMake(0, -1);
indicator.layer.shadowOpacity = 1.0f;
indicator.layer.shadowRadius = 1.0f;

// We then add it as a subview and tell it to start animating.
[header addSubview:indicator];
[indicator startAnimating];

return header;
}

- (TUITableViewCell *)tableView:(TUITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ExampleTableViewCell *cell = reusableTableCellOfClass(tableView, ExampleTableViewCell);

TUIAttributedString *s = [TUIAttributedString stringWithString:[NSString stringWithFormat:@"example cell %d", (int)indexPath.row]];
s.color = [NSColor blackColor];
s.font = [NSFont fontWithName:@"HelveticaNeue" size:15];;
[s setFont:[NSFont fontWithName:@"HelveticaNeue-Bold" size:15] inRange:NSMakeRange(8, 4)]; // make the word "cell" bold
cell.attributedString = s;

return cell;
}

- (void)tableView:(TUITableView *)tableView didClickRowAtIndexPath:(NSIndexPath *)indexPath withEvent:(NSEvent *)event {
if([event clickCount] == 1) {
// do something cool
ExampleTableViewController *pushed = [[ExampleTableViewController alloc] initWithNibName:nil bundle:nil];
[self.navigationController pushViewController:pushed animated:YES];
}

if(event.type == NSRightMouseUp){
// show context menu
}
}
- (BOOL)tableView:(TUITableView *)tableView shouldSelectRowAtIndexPath:(NSIndexPath *)indexPath forEvent:(NSEvent *)event{
switch (event.type) {
case NSRightMouseDown:
return NO;
}

return YES;
}

-(BOOL)tableView:(TUITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
// return YES to enable row reordering by dragging; don't implement this method or return
// NO to disable
return YES;
}

-(void)tableView:(TUITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
// update the model to reflect the changed index paths; since this example isn't backed by
// a "real" model, after dropping a cell the table will revert to it's previous state
NSLog(@"Move dragged row: %@ => %@", fromIndexPath, toIndexPath);
}

-(NSIndexPath *)tableView:(TUITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)fromPath toProposedIndexPath:(NSIndexPath *)proposedPath {
// optionally revise the drag-to-reorder drop target index path by returning a different index path
// than proposedPath. if proposedPath is suitable, return that. if this method is not implemented,
// proposedPath is used by default.
return proposedPath;
}

@end
12 changes: 4 additions & 8 deletions ExampleProject/Example/ExampleView.h
Expand Up @@ -17,13 +17,9 @@
#import "TUIKit.h"
#import "ExampleTabBar.h"

@interface ExampleView : TUIView <TUITableViewDelegate, TUITableViewDataSource, ExampleTabBarDelegate>
{
TUITableView *_tableView;
ExampleTabBar *_tabBar;

NSFont *exampleFont1;
NSFont *exampleFont2;
}
@interface ExampleView : TUIView <ExampleTabBarDelegate>

@property (nonatomic, strong) ExampleTabBar *tabBar;
@property (nonatomic, strong) TUINavigationController *navigationController;

@end
140 changes: 11 additions & 129 deletions ExampleProject/Example/ExampleView.m
Expand Up @@ -15,8 +15,7 @@
*/

#import "ExampleView.h"
#import "ExampleTableViewCell.h"
#import "ExampleSectionHeaderView.h"
#import "ExampleTableViewController.h"

#define TAB_HEIGHT 60

Expand All @@ -27,35 +26,23 @@ - (id)initWithFrame:(CGRect)frame
if((self = [super initWithFrame:frame])) {
self.backgroundColor = [NSColor colorWithCalibratedWhite:0.9 alpha:1.0];

// if you're using a font a lot, it's best to allocate it once and re-use it
exampleFont1 = [NSFont fontWithName:@"HelveticaNeue" size:15];
exampleFont2 = [NSFont fontWithName:@"HelveticaNeue-Bold" size:15];

CGRect b = self.bounds;
b.origin.y += TAB_HEIGHT;
b.size.height -= TAB_HEIGHT;

ExampleTableViewController *tableViewController = [[ExampleTableViewController alloc] initWithNibName:nil bundle:nil];
_navigationController = [[TUINavigationController alloc] initWithRootViewController:tableViewController];
[self addSubview:_navigationController.view];
[_navigationController.view addLayoutConstraint:[TUILayoutConstraint constraintWithAttribute:TUILayoutConstraintAttributeWidth relativeTo:@"superview" attribute:TUILayoutConstraintAttributeWidth]];
[_navigationController.view addLayoutConstraint:[TUILayoutConstraint constraintWithAttribute:TUILayoutConstraintAttributeHeight relativeTo:@"superview" attribute:TUILayoutConstraintAttributeHeight offset:-TAB_HEIGHT]];
[_navigationController.view addLayoutConstraint:[TUILayoutConstraint constraintWithAttribute:TUILayoutConstraintAttributeMinX relativeTo:@"superview" attribute:TUILayoutConstraintAttributeMinX]];
[_navigationController.view addLayoutConstraint:[TUILayoutConstraint constraintWithAttribute:TUILayoutConstraintAttributeMinY relativeTo:@"superview" attribute:TUILayoutConstraintAttributeMinY offset:TAB_HEIGHT]];

/*
Note by default scroll views (and therefore table views) don't
have clipsToBounds enabled. Set only if needed. In this case
we don't, so it could potentially save us some rendering costs.
*/
_tableView = [[TUITableView alloc] initWithFrame:b];
_tableView.alwaysBounceVertical = YES;
_tableView.autoresizingMask = TUIViewAutoresizingFlexibleSize;
_tableView.dataSource = self;
_tableView.delegate = self;
_tableView.maintainContentOffsetAfterReload = YES;

TUILabel *footerLabel = [[TUILabel alloc] initWithFrame:CGRectMake(0, 0, _tableView.frame.size.width, 44)];
footerLabel.alignment = TUITextAlignmentCenter;
footerLabel.backgroundColor = [NSColor clearColor];
footerLabel.font = exampleFont2;
footerLabel.text = @"Example Footer View";
_tableView.footerView = footerLabel;

[self addSubview:_tableView];

_tabBar = [[ExampleTabBar alloc] initWithNumberOfTabs:5];
_tabBar.delegate = self;
// It'd be easier to just use .autoresizingmask, but for demonstration we'll use ^layout.
Expand Down Expand Up @@ -123,114 +110,9 @@ - (void)tabBar:(ExampleTabBar *)tabBar didSelectTab:(NSInteger)index
{
NSLog(@"selected tab %ld", index);
if(index == [[tabBar tabViews] count] - 1){
NSLog(@"Reload table data...");
[_tableView reloadData];
}
}

- (NSInteger)numberOfSectionsInTableView:(TUITableView *)tableView
{
return 8;
}

- (NSInteger)tableView:(TUITableView *)table numberOfRowsInSection:(NSInteger)section
{
return 25;
}

- (CGFloat)tableView:(TUITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 50.0;
}

- (TUIView *)tableView:(TUITableView *)tableView headerViewForSection:(NSInteger)section
{
ExampleSectionHeaderView *view = [[ExampleSectionHeaderView alloc] initWithFrame:CGRectMake(0, 0, 100, 32)];
TUIAttributedString *title = [TUIAttributedString stringWithString:[NSString stringWithFormat:@"Example Section %d", (int)section]];
title.color = [NSColor blackColor];
title.font = exampleFont2;
view.labelRenderer.attributedString = title;

// Dragging a title can drag the window too.
[view setMoveWindowByDragging:YES];

// Add an activity indicator to the header view with a 24x24 size.
// Since we know the height of the header won't change we can pre-
// pad it to 4. However, since the table view's width can change,
// we'll create a layout constraint to keep the activity indicator
// anchored 16px left of the right side of the header view.
TUIActivityIndicatorView *indicator = [[TUIActivityIndicatorView alloc] initWithFrame:CGRectMake(0, 4, 24, 24)
activityIndicatorStyle:TUIActivityIndicatorViewStyleGray];
[indicator addLayoutConstraint:[TUILayoutConstraint constraintWithAttribute:TUILayoutConstraintAttributeMaxX
relativeTo:@"superview"
attribute:TUILayoutConstraintAttributeMaxX
offset:-16.0f]];

// Add a simple embossing shadow to the white activity indicator.
// This way, we can see it better on a bright background. Using
// the standard layer property keeps the shadow stable through
// animations.
indicator.layer.shadowColor = [NSColor whiteColor].tui_CGColor;
indicator.layer.shadowOffset = CGSizeMake(0, -1);
indicator.layer.shadowOpacity = 1.0f;
indicator.layer.shadowRadius = 1.0f;

// We then add it as a subview and tell it to start animating.
[view addSubview:indicator];
[indicator startAnimating];

return view;
}

- (TUITableViewCell *)tableView:(TUITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
ExampleTableViewCell *cell = reusableTableCellOfClass(tableView, ExampleTableViewCell);

TUIAttributedString *s = [TUIAttributedString stringWithString:[NSString stringWithFormat:@"example cell %d", (int)indexPath.row]];
s.color = [NSColor blackColor];
s.font = exampleFont1;
[s setFont:exampleFont2 inRange:NSMakeRange(8, 4)]; // make the word "cell" bold
cell.attributedString = s;

return cell;
}

- (void)tableView:(TUITableView *)tableView didClickRowAtIndexPath:(NSIndexPath *)indexPath withEvent:(NSEvent *)event
{
if([event clickCount] == 1) {
// do something cool
NSLog(@"popping nav controller...");
[self.navigationController popViewControllerAnimated:YES];
}

if(event.type == NSRightMouseUp){
// show context menu
}
}
- (BOOL)tableView:(TUITableView *)tableView shouldSelectRowAtIndexPath:(NSIndexPath *)indexPath forEvent:(NSEvent *)event{
switch (event.type) {
case NSRightMouseDown:
return NO;
}

return YES;
}

-(BOOL)tableView:(TUITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
// return TRUE to enable row reordering by dragging; don't implement this method or return
// FALSE to disable
return TRUE;
}

-(void)tableView:(TUITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
// update the model to reflect the changed index paths; since this example isn't backed by
// a "real" model, after dropping a cell the table will revert to it's previous state
NSLog(@"Move dragged row: %@ => %@", fromIndexPath, toIndexPath);
}

-(NSIndexPath *)tableView:(TUITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)fromPath toProposedIndexPath:(NSIndexPath *)proposedPath {
// optionally revise the drag-to-reorder drop target index path by returning a different index path
// than proposedPath. if proposedPath is suitable, return that. if this method is not implemented,
// proposedPath is used by default.
return proposedPath;
}

@end

0 comments on commit adbc2c4

Please sign in to comment.