Monday, April 5, 2010

Selection Controller: Decorating with checkmarks

The first stage was to create a selection controller which allows any list to be decorated with selections.  In this case I extended my previous table list so that it can decorate one of my tables and intercept the selections and modify the cells.  The goal is that I can easily add selection to any list.

Usage:
The following method will create a unique selector for a particular table, in this case I'm creating a new table from scratch, however this should work when changing to 'select mode' on another list (such as multiple delete).

Right now I'm just using the Checkmark accessory to select items.  Eventually I want to add custom images on the left (such as the mail app on the iPhone).


JLTableContainer *container=
[JLTableContainer createFetchControlledTable:nil 
  forEntity:@"WordList"
    forSimpleKey:@"ListName"
  inContext:
[SightWordState Instance].control.managedObjectContext 
createSectionsBy:nil 
controlledBy:nil];
[container updatePredicate:nil];

Now after creating the list, add the selector.
UISelectionMaster * selector=[[UISelectionMaster alloc] init];
selector.listToSelect=container;
[self.navigationController pushViewController:selector animated:true];
Now the selector takes one of my JLTableContainer objects and decorates it with selection items:

@interface JLSelectionController : NSObject {
id<JLTableController> originalController;
id<JLCellProvider> originalCellProvider;
NSMutableSet *selectedItems;
UITableView *tableView;
}
@property (nonatomic,retain) id originalController;
@property (nonatomic,retain) id originalCellProvider;
@property (nonatomic,retain) NSMutableSet *selectedItems;
@property (nonatomic,retain) UITableView *tableView;
- (void) toggleObject:(id) objToToggle;
- (void) addToContainer:(JLTableContainer*) container;
- (void) removeFromContainer:(JLTableContainer*) container;

Here is the implementation.  What this is doing is creating a new level of controller for the strategy pattern keeping track of the old pattern.  In addition it creates a new cellForObject method, which takes the lower level one and changes the accessory type.  (I want to change it to use an icon instead).

@implementation JLSelectionController
@synthesize originalController;
@synthesize originalCellProvider;
@synthesize selectedItems;
@synthesize tableView;
- (UITableViewCell *)cellForObject:(id) object  atIndexPath:(NSIndexPath *)indexPath forTable:(UITableView*) table
{
tableView=table;
// Delegate to previous provider.
UITableViewCell *returnCell=[originalCellProvider 
cellForObject:object 
atIndexPath:indexPath forTable:table] ;
// Check it for now, later I'd like to make a custom image and put it at the left (ala mail).
if ([selectedItems  containsObject:object])
{
returnCell.accessoryType=UITableViewCellAccessoryCheckmark;
}
else {
returnCell.accessoryType=UITableViewCellAccessoryNone;
}

return returnCell;

}

- (void) rowSelected:(id) selectedObject
{
[self toggleObject:selectedObject];
}
- (void) acessorySelected:(id) selectedObject
{
[self toggleObject:selectedObject];
}
- (void) toggleObject:(id) objToToggle
{
if (selectedItems==nil)
selectedItems=[[NSMutableSet alloc]init];
if ([selectedItems containsObject:objToToggle])
{
[selectedItems removeObject:objToToggle];
}
else {
[selectedItems addObject:objToToggle];
}
if (tableView!=nil)
{
[tableView reloadData];
}

}
- (void) dealloc
{
[super dealloc];
[self.selectedItems release];
}
- (void) addToContainer:(JLTableContainer*) container
{
self.originalController=container.tableController;
container.tableController=self;
self.originalCellProvider=container.cellProvider;
container.cellProvider=self;
[container connectObjects];
container.table =container.table;
[container.table reloadData];
}
- (void) removeFromContainer:(JLTableContainer*) container
{
container.tableController=self.originalController;
container.cellProvider=self.originalCellProvider;
[container.table reloadData];

}

I have this working for one case.  The next step will be to extend eventing so that choices can be made on toolbars and navigation bars for the items and passing the results on in a workflow.

In addition I suspect the reload data for the table is a performance problem, I did it when I was having trouble getting the checkmarks to update.




1 comment: