Skip to content

Commit

Permalink
Flexible layout, working with iPad.
Browse files Browse the repository at this point in the history
  • Loading branch information
gabriel committed Apr 13, 2010
1 parent 4c5077b commit d4110e1
Show file tree
Hide file tree
Showing 9 changed files with 184 additions and 95 deletions.
31 changes: 31 additions & 0 deletions Classes-IPhone/GHUnitIPhoneView.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// GHUnitIPhoneView.h
// GHUnitIPhone
//
// Created by Gabriel Handford on 4/12/10.
// Copyright 2010. All rights reserved.
//


@interface GHUnitIPhoneView : UIView {
UISearchBar *searchBar_;

UITableView *tableView_;

//! Status label at bottom of the view
UILabel *statusLabel_;

UISegmentedControl *filterControl_;

UIToolbar *runToolbar_;

UIView *footerView_;
}

@property (readonly, nonatomic) UILabel *statusLabel;
@property (readonly, nonatomic) UISegmentedControl *filterControl;
@property (readonly, nonatomic) UISearchBar *searchBar;
@property (readonly, nonatomic) UITableView *tableView;


@end
80 changes: 80 additions & 0 deletions Classes-IPhone/GHUnitIPhoneView.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//
// GHUnitIPhoneView.m
// GHUnitIPhone
//
// Created by Gabriel Handford on 4/12/10.
// Copyright 2010. All rights reserved.
//

#import "GHUnitIPhoneView.h"


@implementation GHUnitIPhoneView

@synthesize statusLabel=statusLabel_, filterControl=filterControl_, searchBar=searchBar_, tableView=tableView_;

- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
self.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin;

searchBar_ = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
searchBar_.showsCancelButton = NO;
searchBar_.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[self addSubview:searchBar_];
[searchBar_ release];

// Table view
tableView_ = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
tableView_.sectionIndexMinimumDisplayRowCount = 5;
[self addSubview:tableView_];
[tableView_ release];

footerView_ = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 36)];
footerView_.backgroundColor = [UIColor colorWithWhite:0.9 alpha:1.0];

// Status label
statusLabel_ = [[UILabel alloc] initWithFrame:CGRectMake(5, 0, 310, 36)];
statusLabel_.text = @"Select 'Run' to start tests";
statusLabel_.backgroundColor = [UIColor clearColor];
statusLabel_.font = [UIFont systemFontOfSize:12];
statusLabel_.numberOfLines = 2;
statusLabel_.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[footerView_ addSubview:statusLabel_];
[statusLabel_ release];

[self addSubview:footerView_];
[footerView_ release];

runToolbar_ = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 36)];
filterControl_ = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@"All", @"Failed", nil]];
filterControl_.frame = CGRectMake(20, 6, 280, 24);
filterControl_.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
filterControl_.segmentedControlStyle = UISegmentedControlStyleBar;
[runToolbar_ addSubview:filterControl_];
[filterControl_ release];
[self addSubview:runToolbar_];
[runToolbar_ release];
}
return self;
}

- (void)layoutSubviews {
[super layoutSubviews];
CGSize size = self.frame.size;
CGFloat y = 0;
CGFloat contentHeight = size.height - 44 - 36 - 36;

searchBar_.frame = CGRectMake(0, y, size.width, 44);
y += 44;

tableView_.frame = CGRectMake(0, y, size.width, contentHeight);
y += contentHeight;

footerView_.frame = CGRectMake(0, y, size.width, 36);
y += 36;

runToolbar_.frame = CGRectMake(0, y, size.width, 36);
}

@end
20 changes: 4 additions & 16 deletions Classes-IPhone/GHUnitIPhoneViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,26 @@
// Copyright 2009. All rights reserved.
//

#import "GHTestViewModel.h"
#import "GHUnitIPhoneView.h"

#import "GHUnitIPhoneTableViewDataSource.h"
#import "GHUnitIPhoneTestViewController.h"

@interface GHUnitIPhoneViewController : UIViewController <UITableViewDelegate, GHTestRunnerDelegate, UISearchBarDelegate> {

UISearchBar *searchBar_;

UITableView *tableView_;

//! Status label at bottom of the view
UILabel *statusLabel_;


GHUnitIPhoneView *view_;

//! Data source for table view
GHUnitIPhoneTableViewDataSource *dataSource_;
GHTestSuite *suite_;

UIBarButtonItem *runButton_;

UISegmentedControl *filterControl_;

//! If set then we will no longer auto scroll as tests are run
BOOL userDidDrag_;

//! Toolbar
UIToolbar *runToolbar_;

}

@property (readonly, nonatomic) UITableView *tableView;

@property (retain, nonatomic) GHTestSuite *suite;

- (void)reloadTest:(id<GHTest>)test;
Expand Down
116 changes: 40 additions & 76 deletions Classes-IPhone/GHUnitIPhoneViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
NSString *const GHUnitPrefixKey = @"Prefix";
NSString *const GHUnitFilterKey = @"Filter";

@interface GHUnitIPhoneViewController (Private)
@interface GHUnitIPhoneViewController ()
- (NSString *)_prefix;
- (void)_setPrefix:(NSString *)prefix;
- (void)_setFilterIndex:(NSInteger)index;
Expand All @@ -20,13 +20,18 @@ - (NSInteger)_filterIndex;

@implementation GHUnitIPhoneViewController

@synthesize tableView=tableView_, suite=suite_;
@synthesize suite=suite_;

- (id)init {
if ((self = [super init])) {
self.title = @"Tests";
}
return self;
}

- (void)dealloc {
[dataSource_ release];
[suite_ release];
searchBar_.delegate = nil;
[searchBar_ release];
[super dealloc];
}

Expand All @@ -37,66 +42,25 @@ - (void)saveDefaults {
}

- (void)loadView {
self.title = @"Tests";

UIView *view = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 416)] autorelease];
view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;

// Search bar
searchBar_ = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
searchBar_.delegate = self;
searchBar_.showsCancelButton = NO;
searchBar_.autoresizingMask = UIViewAutoresizingFlexibleWidth;
NSString *prefix = [self _prefix];
if (prefix)
searchBar_.text = prefix;
[view addSubview:searchBar_];

// Table view
tableView_ = [[UITableView alloc] initWithFrame:CGRectMake(0, 44, 320, 300) style:UITableViewStylePlain];
tableView_.delegate = self;
tableView_.dataSource = self.dataSource;
tableView_.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
tableView_.sectionIndexMinimumDisplayRowCount = 5;
[view addSubview:tableView_];
[tableView_ release];

UIView *footerView = [[UIView alloc] initWithFrame:CGRectMake(0, 344, 320, 36)];
footerView.backgroundColor = [UIColor colorWithWhite:0.9 alpha:1.0];
footerView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;

// Status label
statusLabel_ = [[UILabel alloc] initWithFrame:CGRectMake(5, 0, 310, 36)];
statusLabel_.text = @"Select 'Run' to start tests";
statusLabel_.backgroundColor = [UIColor clearColor];
statusLabel_.font = [UIFont systemFontOfSize:12];
statusLabel_.numberOfLines = 2;
statusLabel_.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[footerView addSubview:statusLabel_];
[statusLabel_ release];

[view addSubview:footerView];
[footerView release];

runToolbar_ = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 380, 320, 36)];
filterControl_ = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@"All", @"Failed", nil]];
filterControl_.segmentedControlStyle = UISegmentedControlStyleBar;
filterControl_.frame = CGRectMake(20, 6, 280, 24);
filterControl_.autoresizingMask = UIViewAutoresizingFlexibleWidth;
filterControl_.selectedSegmentIndex = [self _filterIndex];
[filterControl_ addTarget:self action:@selector(_filterChanged:) forControlEvents:UIControlEventValueChanged];
runToolbar_.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[runToolbar_ addSubview:filterControl_];
[filterControl_ release];
[view addSubview:runToolbar_];
[runToolbar_ release];

runButton_ = [[UIBarButtonItem alloc] initWithTitle:@"Run" style:UIBarButtonItemStyleDone
target:self action:@selector(_toggleTestsRunning)];
[super loadView];

if (!runButton_)
runButton_ = [[UIBarButtonItem alloc] initWithTitle:@"Run" style:UIBarButtonItemStyleDone
target:self action:@selector(_toggleTestsRunning)];
self.navigationItem.rightBarButtonItem = runButton_;
[runButton_ release];

self.view = view;
if (!view_)
view_ = [[GHUnitIPhoneView alloc] initWithFrame:CGRectMake(0, 0, 320, 344)];
view_.searchBar.delegate = self;
NSString *prefix = [self _prefix];
if (prefix) view_.searchBar.text = prefix;
view_.filterControl.selectedSegmentIndex = [self _filterIndex];
[view_.filterControl addTarget:self action:@selector(_filterChanged:) forControlEvents:UIControlEventValueChanged];
view_.tableView.delegate = self;
view_.tableView.dataSource = self.dataSource;
self.view = view_;
[view_ release];
[self reload];
}

Expand All @@ -111,7 +75,7 @@ - (GHUnitIPhoneTableViewDataSource *)dataSource {
- (void)reload {
[self.dataSource.root setTextFilter:[self _prefix]];
[self.dataSource.root setFilter:[self _filterIndex]];
[self.tableView reloadData];
[view_.tableView reloadData];
}

#pragma mark Running
Expand All @@ -127,13 +91,13 @@ - (void)runTests {
self.view;
runButton_.title = @"Cancel";
userDidDrag_ = NO; // Reset drag status
statusLabel_.textColor = [UIColor blackColor];
statusLabel_.text = @"Starting tests...";
view_.statusLabel.textColor = [UIColor blackColor];
view_.statusLabel.text = @"Starting tests...";
[self.dataSource run:self inParallel:NO options:0];
}

- (void)cancel {
statusLabel_.text = @"Cancelling...";
view_.statusLabel.text = @"Cancelling...";
[dataSource_ cancel];
}

Expand Down Expand Up @@ -168,12 +132,12 @@ - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interface
}

- (void)_filterChanged:(id)sender {
[self _setFilterIndex:filterControl_.selectedSegmentIndex];
[self _setFilterIndex:view_.filterControl.selectedSegmentIndex];
[self reload];
}

- (void)reloadTest:(id<GHTest>)test {
[self.tableView reloadData];
[view_.tableView reloadData];
if (!userDidDrag_ && !dataSource_.isEditing && ![test isDisabled]
&& [test status] == GHTestStatusRunning && ![test conformsToProtocol:@protocol(GHTestGroup)])
[self scrollToTest:test];
Expand All @@ -182,7 +146,7 @@ - (void)reloadTest:(id<GHTest>)test {
- (void)scrollToTest:(id<GHTest>)test {
NSIndexPath *path = [dataSource_ indexPathToTest:test];
if (!path) return;
[self.tableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionMiddle animated:NO];
[view_.tableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionMiddle animated:NO];
}

- (void)scrollToBottom {
Expand All @@ -191,11 +155,11 @@ - (void)scrollToBottom {
NSInteger lastTestIndex = [dataSource_ numberOfTestsInGroup:lastGroupIndex] - 1;
if (lastTestIndex < 0) return;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:lastTestIndex inSection:lastGroupIndex];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO];
[view_.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO];
}

- (void)setStatusText:(NSString *)message {
statusLabel_.text = message;
view_.statusLabel.text = message;
}

#pragma mark Delegates (UITableView)
Expand All @@ -206,7 +170,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
[node setSelected:![node isSelected]];
[node notifyChanged];
[tableView deselectRowAtIndexPath:indexPath animated:NO];
[self.tableView reloadData];
[view_.tableView reloadData];
} else {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
GHTestNode *sectionNode = [[[dataSource_ root] children] objectAtIndex:indexPath.section];
Expand All @@ -233,14 +197,14 @@ - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {

- (void)_setRunning:(BOOL)running runner:(GHTestRunner *)runner {
if (running) {
filterControl_.enabled = NO;
view_.filterControl.enabled = NO;
} else {
filterControl_.enabled = YES;
view_.filterControl.enabled = YES;
GHTestStats stats = [runner.test stats];
if (stats.failureCount > 0) {
statusLabel_.textColor = [UIColor redColor];
view_.statusLabel.textColor = [UIColor redColor];
} else {
statusLabel_.textColor = [UIColor blackColor];
view_.statusLabel.textColor = [UIColor blackColor];
}

runButton_.title = @"Run";
Expand Down Expand Up @@ -288,7 +252,7 @@ - (void)testRunnerDidEnd:(GHTestRunner *)runner {
#pragma mark Delegates (UISearchBar)

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
[searchBar_ setShowsCancelButton:YES animated:YES];
[searchBar setShowsCancelButton:YES animated:YES];
}

- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
Expand Down
Loading

0 comments on commit d4110e1

Please sign in to comment.