2. Hooking Up the Grid
Now that we have a view class ready to go, we can create a view
controller that makes use of it. Use the New File Assistant to create a
new UIViewController subclass, making it include the creation of an .xib file, but not making it a UITableViewController subclass. Name it SelectColorController, and give it the following interface in SelectColorController.h:
// StrokeColorController.h
#import <UIKit/UIKit.h>
@class ColorGrid;
// a notification name
#define ColorSelectionDone @"ColorSelectionDone"
@interface SelectColorController : UIViewController {
IBOutlet ColorGrid *colorGrid;
IBOutlet UIView *selectedColorSwatch;
UIColor *selectedColor;
UIPopoverController *container;
}
@property (retain, nonatomic) ColorGrid *colorGrid;
@property (retain, nonatomic) UIColor *selectedColor;
@property (assign, nonatomic) UIPopoverController *container;
@end
The GUI for this class will contain a ColorGrid instance, as well as a simple UIView for displaying the selected color. We make the colorGrid an accessible property so that our main controller, DudelViewController, can set its properties (rowCount, columnCount, and colors) when setting things up. This class also has properties for the currently selected color and the UIPopoverController that displays it. And, like the ColorGrid class, it will communicate "upstream" to the DudelViewController indirectly, through the use of a notification, whose name is defined here.
Now open SelectColorController.xib
in Interface Builder. Once again, the default view is meant to be
full-screen, so use the attribute inspector to turn off the Status Bar
by setting it to Unspecified, and then the size inspector to make it 320
by 320. Use the Library to get instances of UIView and ColorGrid, and lay them out as shown in Figure 2.
The upper view there is the UIView, and the lower one is the ColorGrid. You don't need to get too picky about the sizes of these views, since ColorGrid will adjust to whatever you throw at it, but it's good to have the ColorGrid reasonably large and both views centered in the parent view. Connect the outlets from File's Owner to the colorGrid and selectedColorSwatch views. The GUI is complete! Now we just need to make it work.
Here's the code for SelectColorController.m:
//
// StrokeColorController.m
#import "SelectColorController.h"
#import "ColorGrid.h"
@implementation SelectColorController
@synthesize colorGrid, selectedColor, container;
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(colorGridTouchedOrDragged:)
name:ColorGridTouchedOrDragged object:colorGrid];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(colorGridTouchEnded:)
name:ColorGridTouchEnded object:colorGrid];
selectedColorSwatch.backgroundColor = self.selectedColor;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation {
// Overriden to allow any orientation.
return YES;
}
- (void)viewDidUnload {
[super viewDidUnload];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
self.colorGrid = nil;
[super dealloc];
}
- (void)colorGridTouchedOrDragged:(NSNotification *)notification {
NSDictionary *userDict = [notification userInfo];
self.selectedColor = [userDict objectForKey:ColorGridLatestTouchedColor];
selectedColorSwatch.backgroundColor = self.selectedColor;
}
- (void)colorGridTouchEnded:(NSNotification *)notification {
NSDictionary *userDict = [notification userInfo];
self.selectedColor = [userDict objectForKey:ColorGridLatestTouchedColor];
selectedColorSwatch.backgroundColor = self.selectedColor;
[[NSNotificationCenter defaultCenter] postNotificationName:ColorSelectionDone
object:self];
}
@end
This should be pretty straightforward. We register methods to listen for activity from the ColorGrid,
each of which grabs the latest touched color from the notification
object. If the touch ended, we send out yet another notification, so
that our main controller gets the message that a color has been set.