Data Source for Table with Expanders

Description: creating a data source for data grid.

The DataSource.h File

#import <NuGridView/NuGridCellCache.h>
#import <NuGridView/NuGridDataSource.h>
#import "GridRow.h"
@interface DataSource : NSObject<NuGridDataSource> {
    GridRow *columnHeader; // Column headers
    NSMutableArray *observers; // Array of observers
    id<NuGridCellCache> cellCacheProvider; // Table cache provider
}
@property(assign) NSMutableArray *data; // Data array
- (id) init;
// Returns whether the specified rows is expanded
- (BOOL)rowIsExpanded:(NSInteger)row;
// Exoands the specified row
- (void) expandRow:(NSInteger) row;
// Collapses the specified row
- (void) collapseRow:(NSInteger) row;
@end

The DataSource.m File

#import &quot;DataSource.h&quot;
#import &lt;NuGridView/NuGridView.h&gt;
#import &lt;NuGridView/NuGridCell.h&gt;
#import &lt;NuGridView/NuGridExpandableCell.h&gt;
#import &lt;NuGridView/NuTextGridCell.h&gt;
#import &lt;NuGridView/NuGridUpdateObserver.h&gt;
#import &lt;NuGridView/NuGridExpandableCell.h&gt;
@implementation DataSource
@synthesize data = _data;
- (id) init {
    self=[super init];
    if(self)
    {
        // Initialize arrays
        observers = [NSMutableArray new];
        _data = [NSMutableArray new];
        columnHeader = [[GridRow alloc] initWithHeader:@&quot;Table&quot;
        andData:[NSArray arrayWithObjects:@&quot;A&quot;,
        @&quot;B&quot;,
        @&quot;C&quot;,
        @&quot;D&quot;,
        nil]];
        // Create data for table
        NSMutableArray *tmp;
        for (int i=0; i&lt;10; i++) {
            tmp = [NSMutableArray new];
            for (int j=0; j&lt;4; j++) {
                [tmp addObject:[NSString stringWithFormat:@&quot;%d&quot;, i + j]];
            }
            GridRow *row = [[GridRow alloc] initWithHeader:[NSString stringWithFormat:@&quot;%d&quot;, i] andData:tmp];
            [_data addObject:row];
            [tmp release];
            if (i == 1) {
                for (int k = 0; k &lt; 4; k++) {
                    tmp = [NSMutableArray new];
                    i++;
                    for (int l=0; l&lt;4; l++) {
                        [tmp addObject:[NSString stringWithFormat:@&quot;%d&quot;, i + l]];
                    }
                    GridRow *subRow = [[GridRow alloc] initWithHeader:[NSString stringWithFormat:@&quot;%d&quot;, i] andData:tmp andParent:row];
                    if (k == 2) {
                        for (int m = 0; m &lt; 2; m++) {
                            tmp = [NSMutableArray new];
                            i++;
                            for (int n = 0; n &lt; 4; n++) {
                                [tmp addObject:[NSString stringWithFormat:@&quot;%d&quot;, i + n]];
                            }
                            [[GridRow alloc] initWithHeader:[NSString stringWithFormat:@&quot;%d&quot;, i] andData:tmp andParent:subRow];
                            [tmp release];
                        }
                    }
                }
            };
            if(i == 3) {
                for (int k = 0; k &lt; 3; k++) {
                    tmp = [NSMutableArray new];
                    i++;
                    for (int l=0; l&lt;4; l++)
                    [tmp addObject:[NSString stringWithFormat:@&quot;%d&quot;, i + l]];
                    GridRow *subRow = [[GridRow alloc] initWithHeader:[NSString stringWithFormat:@&quot;%d&quot;, i] andData:tmp andParent:row];
                    if (k == 2) {
                        for (int m = 0; m &lt; 2; m ++) {
                            tmp = [NSMutableArray new];
                            i++;
                            for (int n=0; n &lt; 4; n++) {
                                [tmp addObject:[NSString stringWithFormat:@&quot;%d&quot;, i + n]];
                            }
                            [[GridRow alloc] initWithHeader:[NSString stringWithFormat:@&quot;%d&quot;, i] andData:tmp andParent:subRow];
                            [tmp release];
                        }
                    }
                    if (k == 3) {
                        for (int m = 0; m &lt; 4; m++) {
                            tmp = [NSMutableArray new];
                            i++;
                            for (int n=0; n &lt; 4; n++) {
                                [tmp addObject:[NSString stringWithFormat:@&quot;%d&quot;, i + n]];
                            }
                            [[GridRow alloc] initWithHeader:[NSString stringWithFormat:@&quot;%d&quot;, i] andData:tmp andParent:subRow];
                            [tmp release];
                        }
                    }
                    [tmp release];
                }
            }
        }
        return self;
    }
    return nil;
}
// Returns cell by header row with setting of data
- (NuGridCell *)gridView:(NuGridView *)gridView headerForRow:(NSInteger)row number:(NSInteger)number {
    // Create a cell with identifier
    NuGridExpandableCell *cell =  (cellCacheProvider) ? (NuGridExpandableCell *)[cellCacheProvider dequeueReusableCellWithID:@"row_header"] : nil;
    if (!cell) {
        cell = [[[NuGridExpandableCell alloc] initWithReuseIdentifier:@"header"] autorelease];
    }
    // Get cell value
    NSObject *value = [self gridView:gridView valueForHeaderForRow:row number:number];
    GridRow *gridRow = [_data objectAtIndex:row];
    // Set cell value
    cell.value = value;
    NSMutableString *text = [NSMutableString stringWithString:[gridRow title]];
    for (int i = 0; i <= [gridRow level]; i ++) {
        [text insertString:@"   " atIndex:0];
    };
    // Set value displayed in cell
    cell.text = [NSString stringWithString:text];
    // Specify row number
    cell.rowNumber = row;
    // Specify column number
    cell.columnNumber = number;
    // Set cell index for column
    cell.columnIndex = 0;
    // Set cell index for row
    cell.rowIndex = -1;
    // Specify that cell is not a column header
    cell.isColumnHeader = NO;
    // Specify that cell is not a row header
    cell.isRowHeader = YES;
    // Link cell to the table, in which it will be located
    cell.parentGrid = gridView;
    return cell;
}
// Returns whether the specified row is expanded
- (BOOL)rowIsExpanded:(NSInteger)row {
    if (row < [_data count]) {
        GridRow *gridRow = [_data objectAtIndex:row];
        return [gridRow isExpanded];
    }
    else
    return NO;
}
// Returns cell by header column with setting of data
- (NuGridCell *)gridView:(NuGridView *)gridView headerForColumn:(NSInteger)column number:(NSInteger)number
{
    NuTextGridCell *cell =  (cellCacheProvider) ?
    (NuTextGridCell *)[cellCacheProvider dequeueReusableCellWithID:@"column_header"] : nil;
    if (!cell) {
        cell = [[[NuTextGridCell alloc] initWithReuseIdentifier:@"column_header"] autorelease];
    }
    NSObject *value = [self gridView:gridView valueForHeaderForColumn:column number:number];
    cell.value = value;
    cell.text = [columnHeader.values objectAtIndex:column];
    cell.rowNumber = number;
    cell.columnNumber = column;
    cell.columnIndex = -1;
    cell.rowIndex = 0;
    cell.isColumnHeader = YES;
    cell.isRowHeader = NO;
    cell.parentGrid = gridView;
    return cell;
}
// Returns cell by column and row with setting of data
- (NuGridCell *)gridView:(NuGridView *)gridView cellInRow:(NSInteger)row inColumn:(NSInteger)column
{
    NuTextGridCell *cell =  (cellCacheProvider) ?
(NuTextGridCell *)[cellCacheProvider dequeueReusableCellWithID:@&quot;cell&quot;] : nil;
    if (!cell) {
        cell = [[[NuTextGridCell alloc] initWithReuseIdentifier:@&quot;cell&quot;] autorelease];
    }
    NSObject *value = [self gridView:gridView valueForCellInRow:row inColumn:column];
    cell.value = value;
    cell.text = [NSString stringWithFormat:@&quot;%@&quot;, value];
    cell.rowNumber = row;
    cell.columnNumber = column;
    cell.columnIndex = 0;
    cell.rowIndex = 0;
    cell.isColumnHeader = NO;
    cell.isRowHeader = NO;
    cell.parentGrid = gridView;
    return cell;
}
// Returns the number of table rows
- (NSInteger)gridViewRowCount:(NuGridView *)gridView
{
    return [_data count];
}
// Returns the number of table columns
- (NSInteger)gridViewColumnCount:(NuGridView *)gridView
{
    GridRow *row = [_data objectAtIndex:0];
    return [row.values count];
}
// Determine whether table contain rows with headers
- (BOOL)gridViewHasRowHeader:(NuGridView *)gridView
{
    return YES;
}
// Determine whether table contains columns with headers
- (BOOL)gridViewHasColumnHeader:(NuGridView *)gridView
{
    return YES;
}
// Returns the number of header rows
-(NSInteger)gridViewRowHeaderCount:(NuGridView *)gridView
{
    return 1;
}
// Returns the number of header columns
-(NSInteger)gridViewColumnHeaderCount:(NuGridView *)gridView
{
    return 1;
}
// Returns the value stored in table row header
- (NSObject *)gridView:(NuGridView *)gridView valueForHeaderForRow:(NSInteger)row number:(NSInteger)number
{
    if (row &lt; [_data count]) {
        GridRow *gridRow = [_data objectAtIndex:row];
        return [gridRow title];
    }
    else
    return nil;
}
// Returns the value stored in table column header
- (NSObject *)gridView:(NuGridView *)gridView valueForHeaderForColumn:(NSInteger)column number:(NSInteger)number
{
    return [columnHeader.values objectAtIndex:column];
}
// Returns the value stored in table cell
- (NSObject *)gridView:(NuGridView *)gridView valueForCellInRow:(NSInteger)row inColumn:(NSInteger)column
{
    if (row &lt; [_data count]) {
        GridRow *gridRow = [_data objectAtIndex:row];
        return [gridRow.values objectAtIndex:column];
    }
    else
    return nil;
}
// Returns left top table cell
- (NuGridCell *) gridView:(NuGridView *) gridView cornerCellInRowNumber:(NSInteger)rowNumber inColumnNumber:(NSInteger)columnNumber
{
    NuTextGridCell *cell = [[NuTextGridCell alloc] initWithReuseIdentifier:@&quot;corner&quot;];
    cell.value = [self gridView:gridView valueForCornerCellInRowNumber:rowNumber inColumnNumber:columnNumber];
    cell.text = [NSString stringWithFormat:@&quot;%@&quot;, [cell value]];
    cell.rowNumber = rowNumber;
    cell.columnNumber = columnNumber;
    cell.rowIndex = -1;
    cell.columnIndex = -1;
    cell.isRowHeader = YES;
    cell.isColumnHeader = YES;
    cell.parentGrid = gridView;
    cell.alignment = UITextAlignmentRight;
    return cell;
}
// Returns the value stored in left top table cell
- (NSObject *)gridView:(NuGridView *)gridView valueForCornerCellInRowNumber:(NSInteger)rowNumber inColumnNumber:(NSInteger)columnNumber {
    return @&quot;Prognoz&quot;;
}
// Add observer to corresponding array of observers
- (void)addObserver:(id&lt;NuGridUpdateObserver&gt;)observer
{
    [observers addObject:observer];
}
// Removes observer from corresponding array of observers
- (void)removeObserver:(id&lt;NuGridUpdateObserver&gt;)observer
{
    [observers removeObject:observer];
}
// Expands specified row
- (void)expandRow:(NSInteger)row {
    if (row &lt; [_data count] &amp;&amp; [self gridView:nil parentRowForRow:row] &gt; 0) {
        GridRow *gridRow = [_data objectAtIndex:row];
        [gridRow setIsExpanded:YES];
        for (int i = 0; i &lt; [gridRow childrenCount]; i++) {
            [_data insertObject:[gridRow childAtIndex:i] atIndex:row + i + 1];
        }
    }
}
// Collapses specified row
- (void) collapseRow:(NSInteger)row {
    if (row &lt; [_data count] &amp;&amp; [self gridView:nil parentRowForRow:row] &gt; 0) {
        GridRow *gridRow = [_data objectAtIndex:row];
        [gridRow setIsExpanded:NO];
        for (int i = 0; i &lt; [gridRow childrenCount]; i++) {
            GridRow *subRow = [_data objectAtIndex:row + 1];
            if ([subRow isExpanded]) {
                [subRow setIsExpanded:NO];
                [self collapseRow:row + 1];
            };
            [_data removeObject:subRow];
        }
    }
}
// Returns number of the row that is parent for the row with the specified number
- (NSInteger)gridView:(NuGridView *)gridView parentRowForRow:(NSInteger)rowNumber {
    if(rowNumber &lt; [_data count]) {
        GridRow *gridRow = [_data objectAtIndex:rowNumber];
        return [gridRow childrenCount];
    } else
    return -1;
}
// Returns number of the column that is parent of the column with the specified number
- (NSInteger)gridView:(NuGridView *)gridView parentColumnForColumn:(NSInteger)columnNumber{
    return -1;
}
// Set tale cache provider
- (void)registerCellCacheProvider:(id&lt;NuGridCellCache&gt;)cacheProvider {
    cellCacheProvider = cacheProvider;
}
@end

See also:

Creating a Table with Expanders