Прокси-источник данных для простой электронной таблицы

Описание: создание прокси-источника данных для электронной таблицы. Предыдущим этапом является создание источника данных.

Файл «ProxyDataSource.h»

#import <NuGridView/NuGridExpandableCell.h>
#import <NuGridView/NuGridProxyDataSource.h>
#import "DataSource.h"
// Определим структуру, соответствующую диапазону ячеек
struct NuGridRange {
    NuGridExpandableCell *startCell;
    NuGridExpandableCell *endCell;
};
@interface ProxyDataSource : NSObject<NuGridProxyDataSource> {
    DataSource *_dataSource; // Ссылка на источник данных
    NSMutableArray *_updateObserver;
    NSMutableArray *_fixedRows; // Массив фиксированных строк
    NSMutableArray *_fixedColumns; // Массив фиксированных столбцов
    unsigned long long _styleOrder; // Порядок стиля
    NSMutableDictionary *_styles; // Словарь стилей
    NSMutableDictionary *_stylesSettingOrder; // Словарь настроек стилей
}
@property(assign) NuGridCell *defaultCell; // Ячейка по умолчанию
@property(assign) struct NuGridRange gridRange; // Диапазон сгруппированных ячеек
// Фиксирует строку с указанным номером
- (void)gridView:(NuGridView *)gridView fixRow:(NSInteger)rowNumber;
// Фиксирует столбец с указанным номером
- (void)gridView:(NuGridView *)gridView fixColumn:(NSInteger)columnNumber;
@end

Файл «ProxyDataSource.m»

#import "ProxyDataSource.h"
#import <NuGridView/NuGridView.h>
#import <NuGridView/NuGridSolidColorBrush.h>
#import <NuGridView/NuGridCellWithSparkline.h>
#import <NuGridView/NuGridSparklineHelper.h>
#import <NuGridView/NuGridCellImage.h>
#import "CustomCell.h"
#import "SparklineCell.h"
@implementation ProxyDataSource
@synthesize defaultCell = _defaultCell; // Ячейка по умолчанию
@synthesize gridRange = _gridRange; // Диапазон ячеек таблицы
- (id) init
{
    self = [super init];
    if(self) {
        _dataSource = nil;
        _updateObserver = [NSMutableArray new];
        _defaultCell = nil;
        // Создаём массив фиксированных строк
        _fixedRows = [NSMutableArray new];
        // Создаём массив фиксированных столбцов
        _fixedColumns = [NSMutableArray new];
        _styles = [NSMutableDictionary new];
        _stylesSettingOrder = [NSMutableDictionary new];
        _styleOrder = 0;
        
        return self;
    }
    return nil;
}
// Возвращает источник данных
- (id<NuGridDataSource>)dataSource
{
    return _dataSource;
}
// Устанавливает источник данных
- (void)setDataSource:(id<NuGridDataSource>)dataSource
{
    _dataSource = dataSource;
}
// Добавляет наблюдателя в соответствующий массив наблюдателей
- (void)addObserver:(id<NuGridUpdateObserver>)observer
{
    [_updateObserver addObject:observer];
}
// Удаляет наблюдателя из соответствующего массива наблюдателей
- (void)removeObserver:(id<NuGridUpdateObserver>)observer
{
    [_updateObserver removeObject:observer];
}
- (void)beforeUpdate:(NSString *)key {
    
    for (id<NuGridUpdateObserver> observer in _updateObserver) {
        [observer beforeUpdate:key];
    }
}
- (void)afterUpdate:(NSString*)key {
    
    for (id<NuGridUpdateObserver> observer in _updateObserver) {
        [observer afterUpdate:key];
    }
}
// Возвращает признак наличия заголовков строк в источнике данных
- (BOOL)gridViewHasRowHeader:(NuGridView *)gridView
{
    return [_dataSource gridViewHasRowHeader:gridView];
}
// Возвращает признак наличия столбцов в источнике данных
- (BOOL)gridViewHasColumnHeader:(NuGridView *)gridView
{
    return [_dataSource gridViewHasColumnHeader:gridView];
}
// Возвращает количество строк
- (NSInteger)gridViewRowCount:(NuGridView *)gridView
{
    return [_dataSource gridViewRowCount:gridView];
}
// Возвращает количество столбцов
- (NSInteger)gridViewColumnCount:(NuGridView *)gridView
{
    return [_dataSource gridViewColumnCount:gridView];
}
// Возвращает количество строк заголовка
- (NSInteger)gridViewRowHeaderCount:(NuGridView *)gridView
{
    return [_dataSource gridViewRowHeaderCount:gridView];
}
// Возвращает количество столбцов заголовка
- (NSInteger)gridViewColumnHeaderCount:(NuGridView *)gridView
{
    return [_dataSource gridViewColumnHeaderCount:gridView];
}
// Возвращает номер строки по индексу
- (NSInteger)gridView:(NuGridView *)gridView rowIndexByNumber:(NSInteger)rowNumber
{
    return rowNumber;
}
// Возвращает номер столбца по индексу
- (NSInteger)gridView:(NuGridView *)gridView columnIndexByNumber:(NSInteger)columnNumber
{
    return columnNumber;
}
// Возвращает индекс столбца по его номеру
- (NSInteger)gridView:(NuGridView *)gridView columnNumberByIndex:(NSInteger)columnIndex
{
    return columnIndex;
}
// Возвращает индекс строки по её номеру
- (NSInteger)gridView:(NuGridView *)gridView rowNumberByIndex:(NSInteger)rowIndex
{
    return rowIndex;
}
// Устанавливает стиль, используемый по умолчанию
- (void) gridView:(NuGridView *)gridView setDefaultStyle:(NuGridCellStyle *)style
{
    [self beforeUpdate:@"dataSource"];
    NSString *key = [NSString stringWithFormat:@"Default"];
    [_styles setObject:style forKey:key];
    [_stylesSettingOrder setObject:[NSNumber numberWithUnsignedLongLong:_styleOrder++] forKey:key];
    [self afterUpdate:@"dataSource"];
}
// Устанавливает стиль, используемый по умолчанию для заголовка столбца
- (void) gridView:(NuGridView *)gridView setDefaultStyleForColumnHeader:(NuGridCellStyle *)style
{
    [self beforeUpdate:@"dataSource"];
    NSString *key = [NSString stringWithFormat:@"Column header"];
    [_styles setObject:style forKey:key];
    [_stylesSettingOrder setObject:[NSNumber numberWithUnsignedLongLong:_styleOrder++] forKey:key];
    [self afterUpdate:@"dataSource"];
}
// Устанавливает стиль, используемый по умолчанию для заголовка строки
- (void) gridView:(NuGridView *)gridView setDefaultStyleForRowHeader:(NuGridCellStyle *)style
{
    [self beforeUpdate:@"dataSource"];
    NSString *key = [NSString stringWithFormat:@"Row header"];
    [_styles setObject:style forKey:key];
    [_stylesSettingOrder setObject:[NSNumber numberWithUnsignedLongLong:_styleOrder++] forKey:key];
    [self afterUpdate:@"dataSource"];
}
// Установливает тему оформления таблицы
- (void)gridView:(NuGridView *)gridView setTheme:(NuGridTheme *)theme {
    [self gridView:gridView setDefaultStyle:[theme defaultStyle]];
    [self gridView:gridView setDefaultStyleForRowHeader:[theme defaultRowHeaderStyle]];
    [self gridView:gridView setDefaultStyleForColumnHeader:[theme defaultColumnHeaderStyle]];
}
// Возвращает стиль для заголовка столбца
- (NuGridCellStyle *)styleForColumnHeader:(NSInteger)columnNumber {
    
    NSMutableArray *orderArray = [[NSMutableArray new] autorelease];
    NSNumber *order = [_stylesSettingOrder objectForKey:[NSString stringWithFormat:@"Column_header_%d", columnNumber]];
    if (order) {
        [orderArray addObject:order];
    }
    order = [_stylesSettingOrder objectForKey:@"Column header"];
    if (order) {
        [orderArray addObject:order];
    }
    order = [_stylesSettingOrder objectForKey:@"Default"];
    if (order) {
        [orderArray addObject:order];
    }
    if (orderArray.count > 0) {
        [orderArray sortUsingSelector:@selector(compare:)];
        
        NSArray *actualKeys = [_stylesSettingOrder allKeysForObject:[orderArray lastObject]];
        if (actualKeys.count > 0) {
            NSString *actualKey = [actualKeys objectAtIndex:0];
            
            NuGridCellStyle *style = [_styles objectForKey:actualKey];
            if (style) {
                return style;
            }
        }
    }
    return [[NuGridCellStyle new] autorelease];
}
// Возвращает стиль для заголовка строки
- (NuGridCellStyle *)styleForRowHeader:(NSInteger)rowNumber {
    NSMutableArray *orderArray = [[NSMutableArray new] autorelease];
    NSNumber *order = [_stylesSettingOrder objectForKey:[NSString stringWithFormat:@"Row_header_%d", rowNumber]];
    if (order) {
        [orderArray addObject:order];
    }
    order = [_stylesSettingOrder objectForKey:@"Row header"];
    if (order) {
        [orderArray addObject:order];
    }
    order = [_stylesSettingOrder objectForKey:@"Default"];
    if (order) {
        [orderArray addObject:order];
    }
    if (orderArray.count > 0) {
        [orderArray sortUsingSelector:@selector(compare:)];
        
        NSArray *actualKeys = [_stylesSettingOrder allKeysForObject:[orderArray lastObject]];
        if (actualKeys.count > 0) {
            NSString *actualKey = [actualKeys objectAtIndex:0];
            
            NuGridCellStyle *style = [_styles objectForKey:actualKey];
            if (style) {
                return style;
            }
        }
    }
    return [[NuGridCellStyle new] autorelease];
}
// Возвращает стиль для ячейки таблицы
- (NuGridCellStyle *)styleForCellInRow:(NSInteger)rowNumber inColumn:(NSInteger)columnNumber {
    NSMutableArray *orderArray = [[NSMutableArray new] autorelease];
    NSNumber *order = [_stylesSettingOrder objectForKey:[NSString stringWithFormat:@"Cell_%d:%d", rowNumber, columnNumber]];
    if (order) {
        [orderArray addObject:order];
    }
    order = [_stylesSettingOrder objectForKey:[NSString stringWithFormat:@"Column_%d", columnNumber]];
    if (order) {
        [orderArray addObject:order];
    }
    order = [_stylesSettingOrder objectForKey:[NSString stringWithFormat:@"Row_%d", rowNumber]];
    if (order) {
        [orderArray addObject:order];
    }
    order = [_stylesSettingOrder objectForKey:@"Default"];
    if (order) {
        [orderArray addObject:order];
    }
    if (orderArray.count > 0) {
        [orderArray sortUsingSelector:@selector(compare:)];
        
        NSArray *actualKeys = [_stylesSettingOrder allKeysForObject:[orderArray lastObject]];
        if (actualKeys.count > 0) {
            NSString *actualKey = [actualKeys objectAtIndex:0];
            
            NuGridCellStyle *style = [_styles objectForKey:actualKey];
            if (style) {
                return style;
            }
        }
    }
    return [[NuGridCellStyle new] autorelease];
}
// Применяет стиль к ячейке таблицы
- (void)gridView:(NuGridView *)gridView applyStyleForCell:(NuGridCell *)cell {
    NuGridCellStyle *style = nil;
    if ([cell isColumnHeader]) {
        style = [[self styleForColumnHeader:[cell columnNumber]] retain];
    }
    else if ([cell isRowHeader]) {
        style = [[self styleForRowHeader:[cell rowNumber]] retain];
    }
    else {
        style = [[self styleForCellInRow:[cell rowNumber] inColumn:[cell columnNumber]]retain];
    }
    // Применяем стиль для ячейки таблицы
    [cell applyStyle:style];
    // Устанавливаем чередование цветов
    [self applyBackgroundColorInterchangeForCell:cell];
    // Устанавливаем градиент, используемый для условного форматирования
    [self applyGradientForCell:cell];
    // Добавляем изображения для условного форматирования
    [self addConditionImageForCell:cell InGrid:gridView];
    // Применяем кисть для заливки ячеек таблицы, если это возможно
    if(style != nil && [cell isKindOfClass:[CustomCell class]] && [style backgroundBrush] != nil) {
        [(CustomCell *)cell setBrush:[style backgroundBrush]];
        [(CustomCell*)cell setNeedsDisplay];
    }
    // Изменяем текст ячейки в соответствии с её типом
    [self gridView: gridView applyTypeForCell:(CustomCell*)cell];
    [style release];
};
// Реализует чередование цветов
-(void) applyBackgroundColorInterchangeForCell:(NuGridCell *) cell {
    NuGridCellStyle *style = [cell style];
    if([style backgroundColorInterchange]) {
        if([cell rowNumber] % 2 ==0) {
            if ([style firstColor] != nil) {
                [cell setBackgroundColor:[style firstColor]];                
            }
        } else {
            if([style secondColor] != nil) {
                [cell setBackgroundColor:[style secondColor]];
            }
        };
    }
}
// Устанавливаем градиентную заливку для ячеек, используемую для условного форматирования
-(void) applyGradientForCell:(NuGridCell *) cell {
    if ([[cell style] isGradientConfigured] &&
    ([[cell style] gradientRowBackground] | [[cell style] gradientColumnBackground])) {
        // Получаем значение ячейки таблицы
        double value = [(NSNumber *)[cell value] doubleValue];
        double max = 0.0;
        
        UIColor *lowColor = cell.style.minColor;
        UIColor *midColor = cell.style.midColor;
        UIColor *topColor = cell.style.maxColor;
        
        if (value >= cell.style.midGradValue) {
            max = cell.style.maxGradValue - cell.style.midGradValue;
            value -= cell.style.midGradValue;
            double q = value / max;
            cell.backgroundColor = [self transitionColorFrom:midColor to:topColor position:q for:cell];
            } else {
            max = cell.style.midGradValue - cell.style.minGradValue;
            value -= cell.style.minGradValue;
            double q = value / max;
            cell.backgroundColor = [self transitionColorFrom:lowColor to:midColor position:q for:cell];
        }
    }
}
// Добавляем изображения, используемые для условного форматирования
-(void) addConditionImageForCell:(NuGridCell *) cell InGrid:(NuGridView *) gridView{
    if ([cell isKindOfClass:[NuGridImageTextCell class]]) {
        NuGridCellStyle *style = [cell style];
        if(([style rowWithImageCondition] | [style columnWithImageCondition]) && [[style imageCollection] count] > 0) {
            double step = ([style maxGradValue] - [style minGradValue]) / (cell.style.imageCollection.count - 1);
            int part = 0;
            double doubleVal = [(NSNumber *)cell.value doubleValue] - cell.style.minGradValue;
            part = doubleVal / step;
            int index = cell.style.imageCollection.count - 1 - part;
            // Определяем ключ изображения для условного форматирования
            NSString *imageKey = @"arrow0";
            // Удаляем старое изображение
            [(NuGridImageTextCell *)cell removeImage:imageKey];
            // Добавляем новое изображение
            [(NuGridImageTextCell *)cell addImage:[[style imageCollection] objectAtIndex:index]
            outputSize:CGSizeMake(12, 12)
            alignment:[style imageAlignment]
            zPosition:[style imageZOrder]
            border:2.0
            key:imageKey];
        }
    }
}
// Определяет цвет ячейки таблицы по его значению
- (UIColor *) transitionColorFrom: (UIColor *) srcCol to: (UIColor *) dstCol position: (double) q for: (NuGridCell*) cell {
    if(srcCol != nil & dstCol != nil) {
        const CGFloat *src = CGColorGetComponents([srcCol CGColor]);
        const CGFloat *dst = CGColorGetComponents([dstCol CGColor]);
        CGFloat result[4];
        for (int i=0; i<4; i++) {
            double s = src[i];
            double d = dst[i];
            double delta = d-s;
            result[i]=s+delta*q;
        }
        return [UIColor colorWithRed:result[0] green:result[1] blue:result[2] alpha:result[3]];
        } else {
        return [cell backgroundColor];
    }
}
// Изменяет текст ячейки в соответствии с её типом
-(void) gridView: (NuGridView*)gridView applyTypeForCell:(CustomCell*)cell {
    if ([[cell style] cellType] == NuCellTypePercentageCell) {
        // Изменяем текст ячейки
        [cell setText:[NSString stringWithFormat: @"%@%%", [cell value]]];
    }
}
// Устанавливает стиль для ячейки таблицы
- (void)gridView:(NuGridView *)gridView setStyle:(NuGridCellStyle *)style forCellInRow:(NSInteger)rowNumber column:(NSInteger)columnNumber {
    [self beforeUpdate:@"dataSource"];
    NSString *key = [NSString stringWithFormat:@"Cell_%d:%d", rowNumber, columnNumber];
    [_styles setObject:style forKey:key];
    [_stylesSettingOrder setObject:[NSNumber numberWithUnsignedLongLong:_styleOrder++] forKey:key];
    [self afterUpdate:@"dataSource"];
}
// Устанавливает стиль для строки таблицы
- (void)gridView:(NuGridView *)gridView setStyle:(NuGridCellStyle *)style forRow:(NSInteger)rowNumber {
    [self beforeUpdate:@"dataSource"];
    NSString *key = [NSString stringWithFormat:@"Row_%d", rowNumber];
    [_styles setObject:style forKey:key];
    [_stylesSettingOrder setObject:[NSNumber numberWithUnsignedLongLong:_styleOrder++] forKey:key];
    [self afterUpdate:@"dataSource"];
}
// Устанавливает стиль для столбца таблицы
- (void)gridView:(NuGridView *)gridView setStyle:(NuGridCellStyle *)style forColumn:(NSInteger)columnNumber {
    [self beforeUpdate:@"dataSource"];
    NSString *key = [NSString stringWithFormat:@"Column_%d", columnNumber];
    [_styles setObject:style forKey:key];
    [_stylesSettingOrder setObject:[NSNumber numberWithUnsignedLongLong:_styleOrder++] forKey:key];
    [self afterUpdate:@"dataSource"];
}
// Устанавливает стиль для заголовка строки
- (void)gridView:(NuGridView *)gridView setStyle:(NuGridCellStyle *)style forHeaderForRow:(NSInteger)rowNumber {
    [self beforeUpdate:@"dataSource"];
    NSString *key = [NSString stringWithFormat:@"Row_header_%d", rowNumber];
    [_styles setObject:style forKey:key];
    [_stylesSettingOrder setObject:[NSNumber numberWithUnsignedLongLong:_styleOrder++] forKey:key];
    [self afterUpdate:@"dataSource"];
}
// Устанавливает стиль для заголовка столбца
- (void)gridView:(NuGridView *)gridView setStyle:(NuGridCellStyle *)style forHeaderForColumn:(NSInteger)columnNumber {
    [self beforeUpdate:@"dataSource"];
    NSString *key = [NSString stringWithFormat:@"Column_header_%d", columnNumber];
    [_styles setObject:style forKey:key];
    [_stylesSettingOrder setObject:[NSNumber numberWithUnsignedLongLong:_styleOrder++] forKey:key];
    [self afterUpdate:@"dataSource"];
}
// Возвращает стиль для строки таблицы
- (NuGridCellStyle *)gridView:(NuGridView *)gridView getStyleForRow:(NSInteger)rowNumber {
    NSString *key = [NSString stringWithFormat:@"Row_%d", rowNumber];
    NuGridCellStyle *style = (NuGridCellStyle *)[_styles objectForKey:key];
    if (style == nil) {
        style = [self gridViewGetDefaultStyle:gridView];
    }
    return style;
}
// Возвращает стиль для столбца таблицы
- (NuGridCellStyle *)gridView:(NuGridView *)gridView getStyleForColumn:(NSInteger)columnNumber {
    NSString *key = [NSString stringWithFormat:@"Column_%d", columnNumber];
    NuGridCellStyle *style = (NuGridCellStyle *)[_styles objectForKey:key];
    if (style == nil) {
        style = [self gridViewGetDefaultStyle:gridView];
    }
    return style;
}
// Возвращает стиль ячейки таблицы
- (NuGridCellStyle *)gridView:(NuGridView *)gridView getStyleForCellInRow:(NSInteger)rowNumber column:(NSInteger)columnNumber {
    NSString *key = [NSString stringWithFormat:@"Cell_%d:%d", rowNumber, columnNumber];
    NuGridCellStyle *style = (NuGridCellStyle *)[_styles objectForKey:key];
    if (style == nil) {
        style = [self gridViewGetDefaultStyle:gridView];
    }
    return style;
}
// Возвращает стиль для строки заголовка
- (NuGridCellStyle *)gridView:(NuGridView *)gridView getStyleForHeaderForRow:(NSInteger)rowNumber {
    NSString *key = [NSString stringWithFormat:@"Row_header_%d", rowNumber];
    NuGridCellStyle * style = (NuGridCellStyle *)[_styles objectForKey:key];
    if (style == nil) {
        style = [self gridViewGetDefaultStyleForRowHeader:gridView];
    }
    return style;
}
// Возвращает стиль для столбца заголовка
- (NuGridCellStyle *)gridView:(NuGridView *)gridView getStyleForHeaderForColumn:(NSInteger)columnNumber {
    NSString *key = [NSString stringWithFormat:@"Column_header_%d", columnNumber];
    NuGridCellStyle * style = (NuGridCellStyle *)[_styles objectForKey:key];
    if (style == nil) {
        style = [self gridViewGetDefaultStyleForColumnHeader:gridView];
    }
    return style;
}
// Возвращает текущую тему оформления таблицы
- (NuGridTheme *)gridViewTheme:(NuGridView *)gridView {
    // Создаём тему оформления таблицы
    NuGridTheme *theme = [[NuGridTheme new] autorelease];
    [theme setDefaultRowHeaderStyle:[self gridViewGetDefaultStyleForRowHeader:gridView]];
    [theme setDefaultColumnHeaderStyle:[self gridViewGetDefaultStyleForColumnHeader:gridView]];
    [theme setDefaultStyle:[self gridViewGetDefaultStyle:gridView]];
    return theme;
}
// Возвращает тему по умолчанию для ячеек таблицы
- (NuGridCellStyle *)gridViewGetDefaultStyle:(NuGridView *)gridView {
    NSString *key = [NSString stringWithFormat:@"Default"];
    return (NuGridCellStyle *)[_styles objectForKey:key];
}
// Возвращает тему по умолчанию для заголовков строк
- (NuGridCellStyle *)gridViewGetDefaultStyleForRowHeader:(NuGridView *)gridView {
    NSString *key = [NSString stringWithFormat:@"Row header"];
    return (NuGridCellStyle *)[_styles objectForKey:key];
}
// Возвращает тему по умолчанию для заголовков столбцов
- (NuGridCellStyle *)gridViewGetDefaultStyleForColumnHeader:(NuGridView *)gridView {
    NSString *key = [NSString stringWithFormat:@"Column header"];
    return (NuGridCellStyle *)[_styles objectForKey:key];
}
// Конвертирует индекс фиксированного столбца в индекс обычного столбца
- (NSInteger)gridView:(NuGridView *)gridView indexForFixedColumnWithIndex:(NSInteger)index {
    if(_fixedColumns > 0) {
        NSNumber *fixedColumnIndex = (NSNumber*)[_fixedColumns objectAtIndex:([_fixedColumns count] - 1)];
        return [fixedColumnIndex intValue];
        } else {
        return  NSNotFound;
    }
}
// Конвертирует индекс фиксированной строки в индекс обычной строки
- (NSInteger)gridView:(NuGridView *)gridView indexForFixedRowWithIndex:(NSInteger)index {
    if(_fixedRows > 0) {
        NSNumber *fixedRowIndex = (NSNumber*)[_fixedRows objectAtIndex:([_fixedRows count] - 1)];
        return [fixedRowIndex intValue];
        } else {
        return  NSNotFound;
    }
}
// Фиксирует строку с указанным номером
- (void)gridView:(NuGridView *)gridView fixRow:(NSInteger)rowNumber {
    NSNumber *number = [NSNumber numberWithInt:rowNumber];
    if (![_fixedRows containsObject:number]) {
        [self beforeUpdate:@"dataSource"];
        [_fixedRows addObject:number];
        [self afterUpdate:@"dataSource"];
    }
}
// Фиксирует столбец с указанным номером
- (void)gridView:(NuGridView *)gridView fixColumn:(NSInteger)columnNumber {
    NSNumber *number = [NSNumber numberWithInt:columnNumber];
    if (![_fixedColumns containsObject:number]) {
        [self beforeUpdate:@"dataSource"];
        [_fixedColumns addObject:number];
        [self afterUpdate:@"dataSource"];
    }
}
// Возвращает ячейку по номеру строки и номеру столбца
- (NuGridCell *) gridView:(NuGridView *)gridView cellInRow:(NSInteger)row inColumn:(NSInteger)column
{
    // Получаем ячейку из источника данных
    CustomCell *cell= (CustomCell*)[_dataSource gridView:gridView cellInRow:row inColumn:column];
    // Применяем стиль к данной ячейке
    [self gridView:gridView applyStyleForCell:cell];
    cell = (CustomCell *)[self mergeGridCell:(CustomCell *)cell];
    return cell;
}
// Возвращает ячейку заголовка строки
- (NuGridCell *) gridView:(NuGridView *)gridView headerForRow:(NSInteger)row number:(NSInteger)number
{
    NuGridCell *cell = [_dataSource gridView:gridView headerForRow:row number:number];
    [self gridView:gridView applyStyleForCell:cell];
    cell = [self mergeGridCell:(NuGridImageTextCell *)cell];
    return cell;
}
// Возвращает ячейку заголовка столбца
- (NuGridCell *) gridView:(NuGridView *)gridView headerForColumn:(NSInteger)column number:(NSInteger)number
{
    NuGridCell *cell = [_dataSource gridView:gridView headerForColumn:column number:number];
    [self gridView:gridView applyStyleForCell:cell];
    cell = [self mergeGridCell:(NuGridImageTextCell *)cell];
    return cell;
}
// Возвращает левую верхнюю ячейку таблицы
- (NuGridCell *) gridView:(NuGridView *)gridView cornerCellInRowNumber:(NSInteger)rowNumber inColumnNumber:(NSInteger)columnNumber
{
    SparklineCell *cell = (SparklineCell *)[_dataSource gridView:gridView cornerCellInRowNumber:rowNumber inColumnNumber:columnNumber];
    // Устанавливаем стиль для указанной ячейки таблицы
    [self gridView:gridView applyStyleForCell:cell];
    
    [cell setIsUseSparkline:NO];
    cell = (SparklineCell *)[self mergeGridCell:(SparklineCell *)cell];
    return cell;
}
// Расширяет настройки ячейки
-(NuGridCell *)mergeGridCell:(NuGridCell *)gridCell {
    if (_defaultCell != nil && gridCell != nil) {
        if([gridCell isKindOfClass:[SparklineCell class]] & [_defaultCell isKindOfClass:[SparklineCell class]]) {
            [(SparklineCell *)gridCell setIsUseSparkline:[(SparklineCell *)_defaultCell isUseSparkline]];
            [(SparklineCell *)gridCell setRowData:[(SparklineCell *)_defaultCell rowData]];
        }
        if([[self defaultCell] isKindOfClass:[CustomCell class]]) {
            // Получаем изображение для ячейки
            NSMutableDictionary *images = [[self defaultCell] valueForKey:@"m_images"];
            if (images != nil) {
                for (int i = 0; i < [[images allValues] count]; i++) {
                    // Получаем изображение для ячейки таблицы
                    NuGridCellImage *imageCell = [images valueForKey:[NSString stringWithFormat:@"cellImage%d", i]];
                    if(imageCell != nil) {
                        // Получаем номер ячейки
                        NSNumber *rowNumber = (NSNumber *)[images valueForKey:[NSString stringWithFormat:@"row%d", i]];
                        // Получаем номер столбца
                        NSNumber *columnNumber = (NSNumber *)[images valueForKey:[NSString stringWithFormat:@"column%d", i]];
                        if(([rowNumber intValue] == [gridCell rowNumber]) &&
                        ([columnNumber intValue] == [gridCell columnNumber])) {
                            // Добавляем изображение к ячейке
                            if([imageCell border] == 0.f) {
                                [(NuGridImageTextCell*)gridCell addImage:[imageCell image] outputSize:[imageCell size] alignment:[imageCell alignment] zPosition:[imageCell zPosition] leftBorder:[imageCell leftBorder] rightBorder:[imageCell rightBorder] topBorder:[imageCell topBorder] bottomBorder:[imageCell bottomBorder] key:[NSString stringWithFormat:@"NuGridCellImage%d", i]];
                                } else {
                                [(NuGridImageTextCell*)gridCell addImage:[imageCell image] outputSize:[imageCell size] alignment:[imageCell alignment] zPosition:[imageCell zPosition] border:[imageCell border] key:[NSString    stringWithFormat:@"NuGridCellImage%d", i]];
                            }
                        }
                    }
                }
            }
        }
        if ([gridCell isKindOfClass:[CustomCell class]] & [_defaultCell isKindOfClass:[CustomCell class]]) {
            if ([gridCell rowNumber] == [_defaultCell rowNumber] &
            [gridCell columnNumber] == [_defaultCell columnNumber]) {
                [(CustomCell*)gridCell setIsExpandableRow:[(CustomCell*)_defaultCell isExpandableRow]];
                [(CustomCell*)gridCell setIsExpandableColumn:[(CustomCell*)_defaultCell isExpandableColumn]];
                [(CustomCell*) gridCell setIsExpanded:[(CustomCell*)_defaultCell isExpanded]];
            }
        }
    }
    return gridCell;
};
// Возвращает признак того, является ли указанный столбец фиксированным
- (BOOL)gridView:(NuGridView *)gridView isColumnWithIndexFixed:(NSInteger)columnIndex
{
    if (_fixedColumns.count) {
        int columnNumber = [self gridView:gridView columnNumberByIndex:columnIndex];
        NSNumber *number = [NSNumber numberWithInt:columnNumber];
        return [_fixedColumns containsObject:number];
    }
    return NO;
}
// Возвращает признак того, является ли указанная строка фиксированной
- (BOOL)gridView:(NuGridView *)gridView isRowWithIndexFixed:(NSInteger)rowIndex
{
    if (_fixedRows.count) {
        int rowNumber = [self gridView:gridView rowNumberByIndex:rowIndex];
        NSNumber *number = [NSNumber numberWithInt:rowNumber];
        return [_fixedRows containsObject:number];
    }
    return NO;
}
// Возвращает количество фиксированных строк таблицы
- (NSInteger)gridViewFixedRowCount:(NuGridView *)gridView {
    return [_fixedRows count];
};
// Возвращает количество фиксированных столбцов таблицы
- (NSInteger)gridViewFixedColumnCount:(NuGridView *)gridView {
    return [_fixedColumns count];
}
// Разворачивает строку таблицы
- (void)gridView:(NuGridView *)gridView expandRow:(NSInteger)rowNumber {
    [self beforeUpdate:@"DataSource"];
    [[self gridRange].startCell setIsExpanded:YES];
    [[self gridRange].startCell setIsExpandableRow:YES];
    if ([[self gridRange].startCell rowNumber] == rowNumber) {
        NuGridCell *toCell = [[NuGridCell new] autorelease];
        [toCell setRowNumber:[self gridRange].endCell.rowNumber];
        [toCell setColumnNumber:[self gridRange].startCell.columnNumber];
        [_dataSource expandRangeFromCell:[self gridRange].startCell ToCell:toCell];
        _defaultCell = [self gridRange].startCell;
    }
    [self afterUpdate:@"DataSource"];
}
// Сворачивает строку таблицы
- (void) gridView:(NuGridView *)gridView collapseRow:(NSInteger)rowNumber {
    [self beforeUpdate:@"DataSource"];
    [[self gridRange].startCell setIsExpanded:NO];
    [[self gridRange].startCell setIsExpandableRow:YES];
    if ([[self gridRange].startCell rowNumber] == rowNumber) {
        NuGridCell *toCell = [[NuGridCell new] autorelease];
        [toCell setRowNumber:[self gridRange].endCell.rowNumber];
        [toCell setColumnNumber:[self gridRange].startCell.columnNumber];
        [_dataSource collapseRangeFromCell:[self gridRange].startCell ToCell:toCell];
        _defaultCell = [self gridRange].startCell;
    }
    [self afterUpdate:@"DataSource"];
}
// Разворачивает столбец таблицы
- (void)gridView:(NuGridView *)gridView expandColumn:(NSInteger)columnNumber {
    [self beforeUpdate:@"DataSource"];
    [[self gridRange].startCell setIsExpanded:YES];
    [[self gridRange].startCell setIsExpandableColumn:YES];
    if ([[self gridRange].startCell columnNumber] == columnNumber) {
        NuGridCell *toCell = [[NuGridCell new] autorelease];
        [toCell setRowNumber:[self gridRange].startCell.rowNumber];
        [toCell setColumnNumber:[self gridRange].endCell.columnNumber];
        [_dataSource expandRangeFromCell:[self gridRange].startCell ToCell:toCell];
        _defaultCell = [self gridRange].startCell;
    }
    [self afterUpdate:@"DataSource"];
}
// Сворачивает столбец таблицы
- (void) gridView:(NuGridView *)gridView collapseColumn:(NSInteger)columnNumber {
    [self beforeUpdate:@"DataSource"];
    [[self gridRange].startCell setIsExpanded:NO];
    [[self gridRange].startCell setIsExpandableColumn:YES];
    if ([[self gridRange].startCell columnNumber] == columnNumber) {
        NuGridCell *toCell = [[NuGridCell new] autorelease];
        [toCell setRowNumber:[self gridRange].startCell.rowNumber];
        [toCell setColumnNumber:[self gridRange].endCell.columnNumber];
        [_dataSource collapseRangeFromCell:[self gridRange].startCell ToCell:toCell];
        _defaultCell = [self gridRange].startCell;
    }
    [self afterUpdate:@"DataSource"];
}
- (void)dealloc
{
    [[self defaultCell] release];
    [super dealloc];
}
@end

См. также:

Создание простой электронной таблицы