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

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

Файл «ProxyDataSource.h»

#import <NuGridView/NuGridCellCache.h>
#import <NuGridView/NuGridCellStyle.h>
#import <NuGridView/NuGridView.h>
#import <NuGridView/NuGridProxyDataSource.h>
#import "DataSource.h"
@interface ProxyDataSource : NSObject<NuGridProxyDataSource> {
    DataSource *_dataSource; // Ссылка на источник данных
    NSMutableDictionary *styles; // Массив стилей
    NSMutableArray *updateObserver; // Массив наблюдателей
    id<NuGridCellCache> cellCacheProvider; // Поставщик кэша для таблицы
}
// Возвращает стиль для указанной ячейки
- (NuGridCellStyle *)gridView:(NuGridView *)gridView getStyleForCellInRow:(NSInteger)rowNumber column:(NSInteger)columnNumber;
@end

Файл «ProxyDataSource.m»

#import "ProxyDataSource.h"
#import <NuGridView/NuGridUpdateObserver.h>
#import <NuGridView/NuGridExpandableCell.h>
#import <NuGridView/NuGridDataSource.h>
#import <NuGridView/NuGridCell.h>
#import "GridRow.h"
@implementation ProxyDataSource
- (id) init
{
    self = [super init];
    if(self)
    {
        _dataSource = nil;
        styles = [NSMutableDictionary new];
        updateObserver = [NSMutableArray new];
        return self;
    }
    return nil;
}
// Возвращает источник данных
- (id<NuGridDataSource>)dataSource
{
    return _dataSource;
}
// Устанавливает источник данных
- (void)setDataSource:(id<NuGridDataSource>)dataSource
{
    _dataSource = dataSource;
    // Устанавливаем поставщика кэша для таблицы
    if ([self.dataSource respondsToSelector:@selector(registerCellCacheProvider:)]) {
        [self.dataSource registerCellCacheProvider:cellCacheProvider];
    }
}
// Добавляет наблюдателя в соответствующий массив наблюдателей
- (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)gridViewFixedRowCount:(NuGridView *)gridView
{
    return 0;
}
// Возвращает количество фиксированных строк в таблице
- (NSInteger)gridViewFixedColumnCount:(NuGridView *)gridView
{
    return 0;
}
// Возвращает количество строк в таблице
- (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
{
    [styles setValue:style forKey:@"defStyle"];
}
// Устанавливает стиль, используемый по умолчанию для заголовка столбца
- (void) gridView:(NuGridView *)gridView setDefaultStyleForColumnHeader:(NuGridCellStyle *)style
{
    [styles setValue:style forKey:@"defColumnHeaderStyle"];
}
// Устанавливает стиль, используемый по умолчанию для заголовка строки
- (void) gridView:(NuGridView *)gridView setDefaultStyleForRowHeader:(NuGridCellStyle *)style
{
    [styles setValue:style forKey:@"defRowHeaderStyle"];
}
// Применяет стиль к ячейке таблицы
- (void)gridView:(NuGridView *)gridView applyStyleForCell:(NuGridCell *)cell
{
    if (cell.columnIndex<0) {
        [cell applyStyle:[styles objectForKey:@"defColumnHeaderStyle"]];
    }
    else
    if (cell.rowIndex<0) {
        [cell applyStyle:[styles objectForKey:@"defRowHeaderStyle"]];
    }
    else
    [cell applyStyle:[styles objectForKey:@"defStyle"]];
};
// Возвращает стиль для строки заголовка
-(NuGridCellStyle *)gridView:(NuGridView *)gridView getStyleForHeaderForRow:(NSInteger)rowNumber {
    return [styles valueForKey:@"defRowHeaderStyle"];
};
// Возвращает стиль ячейки таблицы
- (NuGridCellStyle *)gridView:(NuGridView *)gridView getStyleForCellInRow:(NSInteger)rowNumber column:(NSInteger)columnNumber {
    if (columnNumber<0) {
        return [styles valueForKey:@"defColumnHeaderStyle"];
    }
    else
    if (rowNumber<0) {
        return [styles valueForKey:@"defRowHeaderStyle"];
    }
    else {
        return [styles valueForKey:@"defStyle"];
    }
}
// Возвращает ячейку по номеру строки и номеру столбца
- (NuGridCell *) gridView:(NuGridView *)gridView cellInRow:(NSInteger)row inColumn:(NSInteger)column
{
    // Получаем ячейку из источника данных
    NuGridCell *cell=[_dataSource gridView:gridView cellInRow:row inColumn:column];
    // Применяем стиль к данной ячейке
    [self gridView:gridView applyStyleForCell:cell];
    return cell;
};
// Возвращает ячейку заголовка строки
- (NuGridCell *) gridView:(NuGridView *)gridView headerForRow:(NSInteger)row number:(NSInteger)number
{
    NuGridExpandableCell *cell = (NuGridExpandableCell *)[_dataSource gridView:gridView headerForRow:row number:number];
    [self gridView:gridView applyStyleForCell:cell];
    // Определяем, содержит ли ячейка экспандер
    if([_dataSource gridView:gridView parentRowForRow:row] > 0)
    {
        GridRow *gridRow = [[_dataSource data] objectAtIndex:row];
        [cell clearImages];
        // Указываем, что ячейка содержит экспандер
        cell.isExpandableRow = YES;
        // Указываем, что ячейка реагирует на прикосновение к ней
        cell.isExpandIconTouched = YES;
        if ([gridRow isExpanded]) {
            if ([gridView isRightToLeft]) {
                // Добавляем значок экспандера
                [cell addImage:[[cell style] expandedImage]
                outputSize:CGSizeMake(10, 10)
                alignment:[[cell style] expanderImageAlignment] | NuImageHorizontalAlignmentRight
                zPosition:NuImageZOrderBack
                border:[[cell style] expanderImageMargin] * [gridRow level]
                key:@"expand"];
                [cell setIndent:[gridRow level]];
                } else {
                // Добавляем значок экспандера
                [cell addImage:[[cell style] expandedImage]
                outputSize:CGSizeMake(10, 10)
                alignment:[[cell style] expanderImageAlignment]
                zPosition:NuImageZOrderBack
                border:[[cell style] expanderImageMargin] * [gridRow level]
                key:@"expand"];
            }
        }
        else {
            if ([gridView isRightToLeft]) {
                // Добавляем значок экспандера
                [cell addImage:[[cell style] collapsedRTLImage]
                outputSize:CGSizeMake(10, 10)
                alignment:[[cell style] expanderImageAlignment] | NuImageHorizontalAlignmentRight
                zPosition:NuImageZOrderBack
                border:[[cell style] expanderImageMargin] * [gridRow level]
                key:@"collapse"];
                [cell setIndent:[gridRow level]];
                } else {
                // Добавляем значок экспандера
                [cell addImage:[[cell style] collapsedImage]
                outputSize:CGSizeMake(10, 10)
                alignment:[[cell style] expanderImageAlignment]
                zPosition:NuImageZOrderBack
                border:[[cell style] expanderImageMargin] * [gridRow level]
                key:@"collapse"];
            }
        }
    }
    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];
    return cell;
}
// Возвращает левую верхнюю ячейку таблицы
- (NuGridCell *) gridView:(NuGridView *)gridView cornerCellInRowNumber:(NSInteger)rowNumber inColumnNumber:(NSInteger)columnNumber
{
    NuGridCell *cell = [_dataSource gridView:gridView cornerCellInRowNumber:rowNumber inColumnNumber:columnNumber];
    // Устанавливаем стиль для указанной ячейки таблицы
    [self gridView:gridView applyStyleForCell:cell];
    return cell;
}
// Разворачивает строку с указанным номером
- (void) gridView:(NuGridView *)gridView expandRow:(NSInteger)rowNumber
{
    [self beforeUpdate:@"DataSource"];
    // Проверяем, может ли эта строка разворачиваться
    if([_dataSource gridView:gridView parentRowForRow:rowNumber] > 0) {
        // Разворачиваем строку
        [_dataSource expandRow:rowNumber];
    }
    // Обновляем таблицу
    [self afterUpdate:@"DataSource"];
}
// Сворачивает строку с указанным номером
- (void) gridView:(NuGridView *)gridView collapseRow:(NSInteger)rowNumber
{
    [self beforeUpdate:@"DataSource"];
    // Проверяем, может ли эта строка сворачиваться
    if([_dataSource gridView:gridView parentRowForRow:rowNumber] > 0)
    {
        // Сворачиваем строку
        [_dataSource collapseRow:rowNumber];
    }
    [self afterUpdate:@"DataSource"];
}
// Возвращает признак того, является ли указанный столбец фиксированным
- (BOOL)gridView:(NuGridView *)gridView isColumnWithIndexFixed:(NSInteger)columnIndex
{
    return NO;
}
// Возвращает признак того, является ли указанная строка фиксированной
- (BOOL)gridView:(NuGridView *)gridView isRowWithIndexFixed:(NSInteger)rowIndex
{
    return NO;
}
// Устанавливает поставщика кэша для таблицы
- (void)registerCellCacheProvider:(id<NuGridCellCache>)cacheProvider {
    cellCacheProvider = cacheProvider;
    if (self.dataSource && [self.dataSource respondsToSelector:@selector(registerCellCacheProvider:)]) {
        [self.dataSource registerCellCacheProvider:cellCacheProvider];
    }
}
@end

См. также:

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